From 1fbdb61f1389f01ce1cf1b7950e03a84811a9f38 Mon Sep 17 00:00:00 2001 From: Chris Dalton Date: Tue, 12 Dec 2017 12:48:47 -0700 Subject: CCPR: Optimize Hull geometry Conceptualizes hulls a as single entity, rather than a set of "wedges" fanned around the midpoint. Optimizes GSImpl hulls to use less, better triangles and not use the midpoint. This refactoring also paves the way for VSImpl hulls. Bug: skia: Change-Id: I6a03c7b64811edfd1589f11a5d102e6ee56ea2d2 Reviewed-on: https://skia-review.googlesource.com/83962 Reviewed-by: Brian Salomon Commit-Queue: Chris Dalton --- src/gpu/ccpr/GrCCPRCoverageProcessor.h | 116 ++++++++++++++------------------- 1 file changed, 50 insertions(+), 66 deletions(-) (limited to 'src/gpu/ccpr/GrCCPRCoverageProcessor.h') diff --git a/src/gpu/ccpr/GrCCPRCoverageProcessor.h b/src/gpu/ccpr/GrCCPRCoverageProcessor.h index dfd2e249c4..6bc3fadf29 100644 --- a/src/gpu/ccpr/GrCCPRCoverageProcessor.h +++ b/src/gpu/ccpr/GrCCPRCoverageProcessor.h @@ -14,13 +14,13 @@ #include "glsl/GrGLSLVarying.h" class GrGLSLPPFragmentBuilder; -class GrGLSLShaderBuilder; +class GrGLSLVertexGeoBuilder; class GrMesh; /** - * This is the geometry processor for the simple convex primitive shapes (triangles and closed curve - * segments) from which ccpr paths are composed. The output is a single-channel alpha value, - * positive for clockwise shapes and negative for counter-clockwise, that indicates coverage. + * This is the geometry processor for the simple convex primitive shapes (triangles and closed, + * convex bezier curves) from which ccpr paths are composed. The output is a single-channel alpha + * value, positive for clockwise shapes and negative for counter-clockwise, that indicates coverage. * * The caller is responsible to execute all render passes for all applicable primitives into a * cleared, floating point, alpha-only render target using SkBlendMode::kPlus (see RenderPass @@ -48,21 +48,36 @@ public: void set(const SkPoint[4], float dx, float dy); }; - // All primitive shapes (triangles and convex closed curve segments) require more than one + // All primitive shapes (triangles and closed, convex bezier curves) require more than one // render pass. Here we enumerate every render pass needed in order to produce a complete // coverage count mask. This is an exhaustive list of all ccpr coverage shaders. + // + // During a render pass, the "Impl" (currently only GSImpl) generates conservative geometry for + // rasterization, and the Shader decides the coverage value at each pixel. enum class RenderPass { - // Triangles. + // For a Hull, the Impl generates a "conservative raster hull" around the input points. This + // is the geometry that causes a pixel to be rasterized if it is touched anywhere by the + // input polygon. The initial coverage values sent to the Shader at each vertex are +1 all + // around. Logically, the conservative raster hull is equivalent to the convex hull of pixel + // size boxes centered on each input point. kTriangleHulls, + kQuadraticHulls, + kCubicHulls, + + // For Edges, the Impl generates conservative rasters around every input edge (i.e. convex + // hulls of two pixel-size boxes centered on both of the edge's endpoints). The initial + // coverage values sent to the Shader at each vertex are -1 on the outside border of the + // edge geometry and 0 on the inside. This is the only geometry type that associates + // coverage values with the output vertices. Interpolated, these coverage values convert + // jagged conservative raster edges into a smooth antialiased edge. kTriangleEdges, - kTriangleCorners, - // Quadratics. - kQuadraticHulls, + // For Corners, the Impl Generates the conservative rasters of corner points (i.e. + // pixel-size boxes). It generates 3 corner boxes for triangles and 2 for curves. The Shader + // specifies which corners. The initial coverage values sent to the Shader at each pixel are + // +1 all around. + kTriangleCorners, kQuadraticCorners, - - // Cubics. - kCubicHulls, kCubicCorners }; static bool RenderPassIsCubic(RenderPass); @@ -100,46 +115,13 @@ public: float debugBloat() const { SkASSERT(this->debugVisualizationsEnabled()); return fDebugBloat; } #endif - // This serves as the base class for each RenderPass's Shader. It indicates what type of - // geometry the Impl should generate and provides implementation-independent code to process the - // inputs and calculate coverage in the fragment Shader. + // The Shader provides code to calculate each pixel's coverage in a RenderPass. It also + // provides details about shape-specific geometry. class Shader { public: - using TexelBufferHandle = GrGLSLGeometryProcessor::TexelBufferHandle; - - // This enum specifies the type of geometry that should be generated for a Shader instance. - // Subclasses are limited to three built-in types of geometry to choose from: - enum class GeometryType { - // Generates a conservative raster hull around the input points. This is the geometry - // that causes a pixel to be rasterized if it is touched anywhere by the input polygon. - // Coverage is +1 all around. - // - // Logically, the conservative raster hull is equivalent to the convex hull of pixel - // size boxes centered around each input point. - kHull, - - // Generates the conservative rasters of the input edges (i.e. convex hull of two - // pixel-size boxes centered on both endpoints). Coverage is -1 on the outside border of - // the edge geometry and 0 on the inside. This is the only geometry type that associates - // coverage values with the output points. It effectively converts a jagged conservative - // raster edge into a smooth antialiased edge. - kEdges, - - // Generates the conservative rasters of the corners specified by the geometry provider - // (i.e. pixel-size box centered on the corner point). Coverage is +1 all around. - kCorners - }; - - virtual GeometryType getGeometryType() const = 0; - - // Returns the number of independent geometric segments to generate for the render pass - // (number of wedges for a hull, number of edges, or number of corners.) - virtual int getNumSegments() const = 0; - union GeometryVars { struct { const char* fAlternatePoints; // floatNx2 (if left null, will use input points). - const char* fAlternateMidpoint; // float2 (if left null, finds euclidean midpoint). } fHullVars; struct { @@ -152,8 +134,12 @@ public: // Called before generating geometry. Subclasses must fill out the applicable fields in // GeometryVars (if any), and may also use this opportunity to setup internal member // variables that will be needed during onEmitVaryings (e.g. transformation matrices). - virtual void emitSetupCode(GrGLSLShaderBuilder*, const char* pts, const char* segmentId, - const char* wind, GeometryVars*) const {} + // + // repetitionID is a 0-based index and indicates which edge or corner is being generated. + // It will be null when generating a hull. + virtual void emitSetupCode(GrGLSLVertexGeoBuilder*, const char* pts, + const char* repetitionID, const char* wind, + GeometryVars*) const {} void emitVaryings(GrGLSLVaryingHandler*, SkString* code, const char* position, const char* coverage, const char* wind); @@ -164,16 +150,10 @@ public: // Defines an equation ("dot(float3(pt, 1), distance_equation)") that is -1 on the outside // border of a conservative raster edge and 0 on the inside. 'leftPt' and 'rightPt' must be // ordered clockwise. - static void EmitEdgeDistanceEquation(GrGLSLShaderBuilder*, const char* leftPt, + static void EmitEdgeDistanceEquation(GrGLSLVertexGeoBuilder*, const char* leftPt, const char* rightPt, const char* outputDistanceEquation); - // Defines a global float2 array that contains MSAA sample locations as offsets from pixel - // center. Subclasses can use this for software multisampling. - // - // Returns the number of samples. - static int DefineSoftSampleLocations(GrGLSLPPFragmentBuilder* f, const char* samplesName); - virtual ~Shader() {} protected: @@ -188,7 +168,7 @@ public: // Returns whether the subclass will handle wind modulation or if this base class should // take charge of multiplying the final coverage output by "wind". // - // NOTE: the coverage parameter is only relevant for edges (see comments in GeometryType). + // NOTE: the coverage parameter is only relevant for edges (see comments in RenderPass). // Otherwise it is +1 all around. virtual WindHandling onEmitVaryings(GrGLSLVaryingHandler*, SkString* code, const char* position, const char* coverage, @@ -199,6 +179,12 @@ public: virtual void onEmitFragmentCode(GrGLSLPPFragmentBuilder*, const char* outputCoverage) const = 0; + // Defines a global float2 array that contains MSAA sample locations as offsets from pixel + // center. Subclasses can use this for software multisampling. + // + // Returns the number of samples. + static int DefineSoftSampleLocations(GrGLSLPPFragmentBuilder* f, const char* samplesName); + private: GrGLSLVarying fWind{kHalf_GrSLType, GrGLSLVarying::Scope::kGeoToFrag}; }; @@ -210,15 +196,13 @@ private: // accidentally bleed into neighbor pixels. static constexpr float kAABloatRadius = 0.491111f; + // Number of bezier points for curves, or 3 for triangles. + int numInputPoints() const { return RenderPassIsCubic(fRenderPass) ? 4 : 3; } + void initGS(); void appendGSMesh(GrBuffer* instanceBuffer, int instanceCount, int baseInstance, - SkTArray* out); - - int numInputPoints() const { - return RenderPassIsCubic(fRenderPass) ? 4 : 3; - } - - static GrGLSLPrimitiveProcessor* CreateGSImpl(std::unique_ptr); + SkTArray* out) const; + GrGLSLPrimitiveProcessor* createGSImpl(std::unique_ptr) const; const RenderPass fRenderPass; SkDEBUGCODE(float fDebugBloat = 0;) @@ -257,7 +241,7 @@ inline bool GrCCPRCoverageProcessor::RenderPassIsCubic(RenderPass pass) { case RenderPass::kCubicCorners: return true; } - SK_ABORT("Invalid GrCCPRCoverageProcessor::RenderPass"); + SK_ABORT("Invalid RenderPass"); return false; } @@ -271,7 +255,7 @@ inline const char* GrCCPRCoverageProcessor::RenderPassName(RenderPass pass) { case RenderPass::kCubicHulls: return "kCubicHulls"; case RenderPass::kCubicCorners: return "kCubicCorners"; } - SK_ABORT("Invalid GrCCPRCoverageProcessor::RenderPass"); + SK_ABORT("Invalid RenderPass"); return ""; } -- cgit v1.2.3