aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/ccpr/GrCCCoverageProcessor_VSImpl.cpp
diff options
context:
space:
mode:
authorGravatar Chris Dalton <csmartdalton@google.com>2018-03-07 11:18:30 -0700
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-03-07 19:39:20 +0000
commit0a79381fd1e43214d0bdd34fb1137d9048d303a0 (patch)
treeb27f83b03978e5d9a3f4859aa200d26315b8f0ef /src/gpu/ccpr/GrCCCoverageProcessor_VSImpl.cpp
parentb5e1f7558052cc60deaf23ccc2c898d1c6c94c09 (diff)
ccpr: Fix very small edges
Fixes a bug in the vertex shader backend where a pixel could be hit twice on very small, axis-aligned edges. Improves the coverage calculations to be more accurate when dealing with very small edges. Bug: skia: Change-Id: I4bac191695d7b7d73b6eef9df0fca3539503a965 Reviewed-on: https://skia-review.googlesource.com/111323 Commit-Queue: Chris Dalton <csmartdalton@google.com> Reviewed-by: Greg Daniel <egdaniel@google.com>
Diffstat (limited to 'src/gpu/ccpr/GrCCCoverageProcessor_VSImpl.cpp')
-rw-r--r--src/gpu/ccpr/GrCCCoverageProcessor_VSImpl.cpp129
1 files changed, 83 insertions, 46 deletions
diff --git a/src/gpu/ccpr/GrCCCoverageProcessor_VSImpl.cpp b/src/gpu/ccpr/GrCCCoverageProcessor_VSImpl.cpp
index 4ac6443322..4c3bb67a93 100644
--- a/src/gpu/ccpr/GrCCCoverageProcessor_VSImpl.cpp
+++ b/src/gpu/ccpr/GrCCCoverageProcessor_VSImpl.cpp
@@ -89,24 +89,38 @@ protected:
typedef GrGLSLGeometryProcessor INHERITED;
};
+static constexpr int kVertexData_LeftNeighborIdShift = 9;
+static constexpr int kVertexData_RightNeighborIdShift = 7;
+static constexpr int kVertexData_BloatIdxShift = 5;
+static constexpr int kVertexData_InvertCoverageBit = 1 << 4;
+static constexpr int kVertexData_IsEdgeBit = 1 << 3;
+static constexpr int kVertexData_IsHullBit = 1 << 2;
+
/**
* Vertex data tells the shader how to offset vertices for conservative raster, and how/whether to
* calculate initial coverage values for edges. See VSHullAndEdgeImpl.
*/
-static constexpr int32_t pack_vertex_data(int32_t bloatIdx, int32_t edgeData,
- int32_t cornerVertexID, int32_t cornerIdx) {
- return (bloatIdx << 6) | (edgeData << 4) | (cornerVertexID << 2) | cornerIdx;
+static constexpr int32_t pack_vertex_data(int32_t leftNeighborID, int32_t rightNeighborID,
+ int32_t bloatIdx, int32_t cornerID,
+ int32_t extraData = 0) {
+ return (leftNeighborID << kVertexData_LeftNeighborIdShift) |
+ (rightNeighborID << kVertexData_RightNeighborIdShift) |
+ (bloatIdx << kVertexData_BloatIdxShift) |
+ cornerID | extraData;
}
-static constexpr int32_t hull_vertex_data(int32_t cornerIdx, int32_t cornerVertexID, int n) {
- return pack_vertex_data((cornerIdx + (2 == cornerVertexID ? 1 : n - 1)) % n, 0, cornerVertexID,
- cornerIdx);
+static constexpr int32_t hull_vertex_data(int32_t cornerID, int32_t bloatIdx, int n) {
+ return pack_vertex_data((cornerID + n - 1) % n, (cornerID + 1) % n, bloatIdx, cornerID,
+ kVertexData_IsHullBit);
}
-static constexpr int32_t edge_vertex_data(int32_t edgeID, int32_t endptIdx, int32_t endptVertexID,
+static constexpr int32_t edge_vertex_data(int32_t edgeID, int32_t endptIdx, int32_t bloatIdx,
int n) {
- return pack_vertex_data(0 == endptIdx ? (edgeID + 1) % n : edgeID, (endptIdx << 1) | 1,
- endptVertexID, 0 == endptIdx ? edgeID : (edgeID + 1) % n);
+ return pack_vertex_data(0 == endptIdx ? (edgeID + 1) % n : edgeID,
+ 0 == endptIdx ? (edgeID + 1) % n : edgeID,
+ bloatIdx, 0 == endptIdx ? edgeID : (edgeID + 1) % n,
+ kVertexData_IsEdgeBit |
+ (!endptIdx ? kVertexData_InvertCoverageBit : 0));
}
static constexpr int32_t kHull3AndEdgeVertices[] = {
@@ -251,55 +265,78 @@ public:
// Reverse all indices if the wind is counter-clockwise: [0, 1, 2] -> [2, 1, 0].
v->codeAppendf("int clockwise_indices = wind > 0 ? %s : 0x%x - %s;",
proc.getAttrib(kAttribIdx_VertexData).fName,
- ((fNumSides - 1) << 6) | (0xf << 2) | (fNumSides - 1),
+ ((fNumSides - 1) << kVertexData_LeftNeighborIdShift) |
+ ((fNumSides - 1) << kVertexData_RightNeighborIdShift) |
+ (((1 << kVertexData_RightNeighborIdShift) - 1) ^ 3) |
+ (fNumSides - 1),
proc.getAttrib(kAttribIdx_VertexData).fName);
// Here we generate conservative raster geometry for the input polygon. It is the convex
// hull of N pixel-size boxes, one centered on each the input points. Each corner has three
// vertices, where one or two may cause degenerate triangles. The vertex data tells us how
- // to offset each vertex. Triangle edges are also handled here (see kHull3AndEdgeIndices).
- // For more details on conservative raster, see:
+ // to offset each vertex. For more details on conservative raster, see:
// https://developer.nvidia.com/gpugems/GPUGems2/gpugems2_chapter42.html
+ //
+ // Triangle edges are also handled here using the same concept (see kHull3AndEdgeVertices).
v->codeAppendf("float2 corner = %s[clockwise_indices & 3];", hullPts);
- v->codeAppendf("float2 bloatpoint = %s[clockwise_indices >> 6];", hullPts);
- v->codeAppend ("float2 vertexbloat = float2(bloatpoint.y > corner.y ? -bloat : +bloat, "
- "bloatpoint.x > corner.x ? +bloat : -bloat);");
-
- v->codeAppendf("if ((1 << 2) == (%s & (3 << 2))) {",
- proc.getAttrib(kAttribIdx_VertexData).fName);
- // We are the corner's middle vertex (of 3).
- v->codeAppend ( "vertexbloat = float2(-vertexbloat.y, vertexbloat.x);");
- v->codeAppend ("}");
-
- v->codeAppendf("if ((2 << 2) == (%s & (3 << 2))) {",
- proc.getAttrib(kAttribIdx_VertexData).fName);
- // We are the corner's third vertex (of 3).
- v->codeAppend ( "vertexbloat = -vertexbloat;");
+ v->codeAppendf("float2 left = %s[clockwise_indices >> %i];",
+ hullPts, kVertexData_LeftNeighborIdShift);
+ v->codeAppendf("float2 right = %s[(clockwise_indices >> %i) & 3];",
+ hullPts, kVertexData_RightNeighborIdShift);
+
+ v->codeAppend ("float2 leftbloat = sign(corner - left);");
+ v->codeAppend ("leftbloat = float2(0 != leftbloat.y ? leftbloat.y : leftbloat.x, "
+ "0 != leftbloat.x ? -leftbloat.x : -leftbloat.y);");
+
+ v->codeAppend ("float2 rightbloat = sign(right - corner);");
+ v->codeAppend ("rightbloat = float2(0 != rightbloat.y ? rightbloat.y : rightbloat.x, "
+ "0 != rightbloat.x ? -rightbloat.x : -rightbloat.y);");
+
+ v->codeAppend ("bool2 left_right_notequal = notEqual(leftbloat, rightbloat);");
+
+ // At each corner of the polygon, our hull will have either 1, 2, or 3 vertices. We begin
+ // with the first hull vertex (leftbloat), then continue rotating 90 degrees clockwise until
+ // we reach the desired vertex for this invocation. Corners with less than 3 corresponding
+ // hull vertices will result in redundant vertices and degenerate triangles.
+ v->codeAppend ("float2 bloatdir = leftbloat;");
+ v->codeAppendf("int bloatidx = (%s >> %i) & 3;",
+ proc.getAttrib(kAttribIdx_VertexData).fName, kVertexData_BloatIdxShift);
+ v->codeAppend ("switch (bloatidx) {");
+ v->codeAppend ( "case 2:");
+ v->codeAppendf( "if (all(left_right_notequal)) {");
+ v->codeAppend ( "bloatdir = float2(-bloatdir.y, +bloatdir.x);");
+ v->codeAppend ( "}");
+ // fallthru.
+ v->codeAppend ( "case 1:");
+ v->codeAppendf( "if (any(left_right_notequal)) {");
+ v->codeAppend ( "bloatdir = float2(-bloatdir.y, +bloatdir.x);");
+ v->codeAppend ( "}");
+ // fallthru.
v->codeAppend ("}");
- v->codeAppend ("float2 vertex = corner + vertexbloat;");
- gpArgs->fPositionVar.set(kFloat2_GrSLType, "vertex");
-
- if (4 == fNumSides) {
- // We don't generate edges around 4-sided polygons.
- return nullptr; // Known hull vertices don't need an initial coverage value.
+ // For triangles, we also emit coverage in order to handle edges and corners.
+ const char* coverage = nullptr;
+ if (3 == fNumSides) {
+ v->codeAppend ("half coverage;");
+ Shader::CalcEdgeCoverageAtBloatVertex(v, "left", "corner", "bloatdir", "coverage");
+ v->codeAppendf("if (0 != (%s & %i)) {", // Are we the opposite endpoint of an edge?
+ proc.getAttrib(kAttribIdx_VertexData).fName,
+ kVertexData_InvertCoverageBit);
+ v->codeAppend ( "coverage = -1 - coverage;");
+ v->codeAppend ("}");
+
+ v->codeAppendf("if (0 != (%s & %i)) {", // Are we a hull vertex?
+ proc.getAttrib(kAttribIdx_VertexData).fName, kVertexData_IsHullBit);
+ v->codeAppend ( "coverage = +1;"); // Hull coverage is +1 all around.
+ v->codeAppend ("}");
+
+ coverage = "coverage";
}
- // Find coverage for edge vertices.
- Shader::EmitEdgeDistanceEquation(v, "bloatpoint", "corner",
- "float3 edge_distance_equation");
- v->codeAppend ("half coverage = dot(edge_distance_equation.xy, vertex) + "
- "edge_distance_equation.z;");
- v->codeAppendf("if (0 == (%s & (1 << 5))) {", proc.getAttrib(kAttribIdx_VertexData).fName);
- // We are the opposite endpoint. Invert coverage.
- v->codeAppend ( "coverage = -1 - coverage;");
- v->codeAppend ("}");
- v->codeAppendf("if (0 == (%s & (1 << 4))) {", proc.getAttrib(kAttribIdx_VertexData).fName);
- // We are actually a hull vertex. Hull coverage is +1 all around.
- v->codeAppend ( "coverage = +1;");
- v->codeAppend ("}");
+ v->codeAppend ("float2 vertex = corner + bloatdir * bloat;");
+ gpArgs->fPositionVar.set(kFloat2_GrSLType, "vertex");
- return "coverage";
+ return coverage;
}
private: