aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/ccpr
diff options
context:
space:
mode:
authorGravatar Chris Dalton <csmartdalton@google.com>2017-12-22 02:24:53 -0700
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-12-22 18:42:05 +0000
commite3877ce5ceb7842b61d54bebcc51864e5787a2bc (patch)
tree60496eb4538ae408f46471db1b394602abd519c9 /src/gpu/ccpr
parent92c7fa6b009b3ea4e93ca179153f837c2d9d7962 (diff)
CCPR: Initial semi-optimized vertex shader Impl
TBR=bsalomon@google.com Bug: skia: Change-Id: I24173e146d8c95cec5f29e8cb4fa5e2c28f9a33c Reviewed-on: https://skia-review.googlesource.com/89120 Reviewed-by: Chris Dalton <csmartdalton@google.com> Commit-Queue: Chris Dalton <csmartdalton@google.com>
Diffstat (limited to 'src/gpu/ccpr')
-rw-r--r--src/gpu/ccpr/GrCCPRCoverageOp.cpp14
-rw-r--r--src/gpu/ccpr/GrCCPRCoverageOp.h2
-rw-r--r--src/gpu/ccpr/GrCCPRCoverageProcessor.cpp28
-rw-r--r--src/gpu/ccpr/GrCCPRCoverageProcessor.h74
-rw-r--r--src/gpu/ccpr/GrCCPRCoverageProcessor_GSImpl.cpp9
-rw-r--r--src/gpu/ccpr/GrCCPRCoverageProcessor_VSImpl.cpp441
-rw-r--r--src/gpu/ccpr/GrCCPRCubicShader.cpp25
-rw-r--r--src/gpu/ccpr/GrCCPRCubicShader.h18
-rw-r--r--src/gpu/ccpr/GrCCPRQuadraticShader.cpp22
-rw-r--r--src/gpu/ccpr/GrCCPRQuadraticShader.h18
-rw-r--r--src/gpu/ccpr/GrCCPRTriangleShader.cpp17
-rw-r--r--src/gpu/ccpr/GrCCPRTriangleShader.h25
-rw-r--r--src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp4
13 files changed, 612 insertions, 85 deletions
diff --git a/src/gpu/ccpr/GrCCPRCoverageOp.cpp b/src/gpu/ccpr/GrCCPRCoverageOp.cpp
index 57b73bf935..5cd35cd2c6 100644
--- a/src/gpu/ccpr/GrCCPRCoverageOp.cpp
+++ b/src/gpu/ccpr/GrCCPRCoverageOp.cpp
@@ -7,6 +7,7 @@
#include "GrCCPRCoverageOp.h"
+#include "GrCaps.h"
#include "GrGpuCommandBuffer.h"
#include "GrOnFlushResourceProvider.h"
#include "GrOpFlushState.h"
@@ -396,7 +397,7 @@ void GrCCPRCoverageOp::onExecute(GrOpFlushState* flushState) {
this->drawMaskPrimitives(flushState, pipeline, RenderPass::kTriangleHulls,
&PrimitiveTallies::fTriangles);
this->drawMaskPrimitives(flushState, pipeline, RenderPass::kTriangleEdges,
- &PrimitiveTallies::fTriangles);
+ &PrimitiveTallies::fTriangles); // Might get skipped.
this->drawMaskPrimitives(flushState, pipeline, RenderPass::kTriangleCorners,
&PrimitiveTallies::fTriangles);
@@ -419,14 +420,19 @@ void GrCCPRCoverageOp::drawMaskPrimitives(GrOpFlushState* flushState, const GrPi
using ScissorMode = GrCCPRCoverageOpsBuilder::ScissorMode;
SkASSERT(pipeline.getScissorState().enabled());
+ if (!GrCCPRCoverageProcessor::DoesRenderPass(renderPass, *flushState->caps().shaderCaps())) {
+ return;
+ }
+
fMeshesScratchBuffer.reset();
fDynamicStatesScratchBuffer.reset();
- GrCCPRCoverageProcessor proc(renderPass);
+ GrCCPRCoverageProcessor proc(flushState->resourceProvider(), renderPass,
+ *flushState->caps().shaderCaps());
- if (const int instanceCount = fInstanceCounts[(int)ScissorMode::kNonScissored].*instanceType) {
+ if (int instanceCount = fInstanceCounts[(int)ScissorMode::kNonScissored].*instanceType) {
SkASSERT(instanceCount > 0);
- const int baseInstance = fBaseInstances[(int)ScissorMode::kNonScissored].*instanceType;
+ int baseInstance = fBaseInstances[(int)ScissorMode::kNonScissored].*instanceType;
proc.appendMesh(fInstanceBuffer.get(), instanceCount, baseInstance, &fMeshesScratchBuffer);
fDynamicStatesScratchBuffer.push_back().fScissorRect.setXYWH(0, 0, fDrawBounds.width(),
fDrawBounds.height());
diff --git a/src/gpu/ccpr/GrCCPRCoverageOp.h b/src/gpu/ccpr/GrCCPRCoverageOp.h
index 7957586958..e3eee48899 100644
--- a/src/gpu/ccpr/GrCCPRCoverageOp.h
+++ b/src/gpu/ccpr/GrCCPRCoverageOp.h
@@ -167,7 +167,7 @@ private:
const SkTArray<ScissorBatch, true> fScissorBatches;
const SkISize fDrawBounds;
- mutable SkTArray<GrMesh, true> fMeshesScratchBuffer;
+ mutable SkTArray<GrMesh> fMeshesScratchBuffer;
mutable SkTArray<GrPipeline::DynamicState, true> fDynamicStatesScratchBuffer;
friend class GrCCPRCoverageOpsBuilder;
diff --git a/src/gpu/ccpr/GrCCPRCoverageProcessor.cpp b/src/gpu/ccpr/GrCCPRCoverageProcessor.cpp
index 3a456fda00..11e847fcc6 100644
--- a/src/gpu/ccpr/GrCCPRCoverageProcessor.cpp
+++ b/src/gpu/ccpr/GrCCPRCoverageProcessor.cpp
@@ -11,17 +11,21 @@
#include "ccpr/GrCCPRCubicShader.h"
#include "ccpr/GrCCPRQuadraticShader.h"
#include "ccpr/GrCCPRTriangleShader.h"
+#include "glsl/GrGLSLVertexGeoBuilder.h"
#include "glsl/GrGLSLFragmentShaderBuilder.h"
#include "glsl/GrGLSLVertexGeoBuilder.h"
void GrCCPRCoverageProcessor::Shader::emitVaryings(GrGLSLVaryingHandler* varyingHandler,
- SkString* code, const char* position,
- const char* coverage, const char* wind) {
- WindHandling windHandling = this->onEmitVaryings(varyingHandler, code, position, coverage,
- wind);
+ GrGLSLVarying::Scope scope, SkString* code,
+ const char* position, const char* coverage,
+ const char* wind) {
+ SkASSERT(GrGLSLVarying::Scope::kVertToGeo != scope);
+ WindHandling windHandling = this->onEmitVaryings(varyingHandler, scope, code, position,
+ coverage, wind);
if (WindHandling::kNotHandled == windHandling) {
+ fWind.reset(kHalf_GrSLType, scope);
varyingHandler->addFlatVarying("wind", &fWind);
- code->appendf("%s = %s;", fWind.gsOut(), wind);
+ code->appendf("%s = %s;", OutName(fWind), wind);
}
}
@@ -80,7 +84,16 @@ int GrCCPRCoverageProcessor::Shader::DefineSoftSampleLocations(GrGLSLPPFragmentB
void GrCCPRCoverageProcessor::getGLSLProcessorKey(const GrShaderCaps&,
GrProcessorKeyBuilder* b) const {
- b->add32((int)fRenderPass);
+ int key = (int)fRenderPass << 1;
+ if (Impl::kGeometryShader == fImpl) {
+ key |= 1;
+ }
+#ifdef SK_DEBUG
+ uint32_t bloatBits;
+ memcpy(&bloatBits, &fDebugBloat, 4);
+ b->add32(bloatBits);
+#endif
+ b->add32(key);
}
GrGLSLPrimitiveProcessor* GrCCPRCoverageProcessor::createGLSLInstance(const GrShaderCaps&) const {
@@ -106,5 +119,6 @@ GrGLSLPrimitiveProcessor* GrCCPRCoverageProcessor::createGLSLInstance(const GrSh
shader = skstd::make_unique<GrCCPRCubicCornerShader>();
break;
}
- return this->createGSImpl(std::move(shader));
+ return Impl::kGeometryShader == fImpl ? this->createGSImpl(std::move(shader))
+ : this->createVSImpl(std::move(shader));
}
diff --git a/src/gpu/ccpr/GrCCPRCoverageProcessor.h b/src/gpu/ccpr/GrCCPRCoverageProcessor.h
index 7210d3975e..3de36f1f52 100644
--- a/src/gpu/ccpr/GrCCPRCoverageProcessor.h
+++ b/src/gpu/ccpr/GrCCPRCoverageProcessor.h
@@ -9,6 +9,7 @@
#define GrCCPRCoverageProcessor_DEFINED
#include "GrGeometryProcessor.h"
+#include "GrShaderCaps.h"
#include "SkNx.h"
#include "glsl/GrGLSLGeometryProcessor.h"
#include "glsl/GrGLSLVarying.h"
@@ -52,14 +53,15 @@ public:
// 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
+ // During a render pass, the "Impl" (GSImpl or VSimpl) generates conservative geometry for
// rasterization, and the Shader decides the coverage value at each pixel.
enum class RenderPass {
// 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. Initial coverage values sent to the Shader at each vertex will be null.
- // Logically, the conservative raster hull is equivalent to the convex hull of pixel size
- // boxes centered on each input point.
+ // input polygon. The initial coverage values sent to the Shader at each vertex are either
+ // null, or +1 all around if the Impl combines this pass with kTriangleEdges. Logically,
+ // the conservative raster hull is equivalent to the convex hull of pixel size boxes
+ // centered on each input point.
kTriangleHulls,
kQuadraticHulls,
kCubicHulls,
@@ -70,6 +72,9 @@ public:
// 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.
+ //
+ // NOTE: The Impl may combine this pass with kTriangleHulls, in which case DoesRenderPass()
+ // will be false for kTriangleEdges and it must not be used.
kTriangleEdges,
// For Corners, the Impl Generates the conservative rasters of corner points (i.e.
@@ -82,10 +87,20 @@ public:
static bool RenderPassIsCubic(RenderPass);
static const char* RenderPassName(RenderPass);
- GrCCPRCoverageProcessor(RenderPass pass)
+ constexpr static bool DoesRenderPass(RenderPass renderPass, const GrShaderCaps& caps) {
+ return RenderPass::kTriangleEdges != renderPass || caps.geometryShaderSupport();
+ }
+
+ GrCCPRCoverageProcessor(GrResourceProvider* rp, RenderPass pass, const GrShaderCaps& caps)
: INHERITED(kGrCCPRCoverageProcessor_ClassID)
- , fRenderPass(pass) {
- this->initGS();
+ , fRenderPass(pass)
+ , fImpl(caps.geometryShaderSupport() ? Impl::kGeometryShader : Impl::kVertexShader) {
+ SkASSERT(DoesRenderPass(pass, caps));
+ if (Impl::kGeometryShader == fImpl) {
+ this->initGS();
+ } else {
+ this->initVS(rp);
+ }
}
// Appends a GrMesh that will draw the provided instances. The instanceBuffer must be an array
@@ -94,8 +109,12 @@ public:
//
// NOTE: Quadratics use TriangleInstance since both have 3 points.
void appendMesh(GrBuffer* instanceBuffer, int instanceCount, int baseInstance,
- SkTArray<GrMesh, true>* out) {
- this->appendGSMesh(instanceBuffer, instanceCount, baseInstance, out);
+ SkTArray<GrMesh>* out) {
+ if (Impl::kGeometryShader == fImpl) {
+ this->appendGSMesh(instanceBuffer, instanceCount, baseInstance, out);
+ } else {
+ this->appendVSMesh(instanceBuffer, instanceCount, baseInstance, out);
+ }
}
// GrPrimitiveProcessor overrides.
@@ -140,8 +159,8 @@ public:
const char* repetitionID, const char* wind,
GeometryVars*) const {}
- void emitVaryings(GrGLSLVaryingHandler*, SkString* code, const char* position,
- const char* coverage, const char* wind);
+ void emitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code,
+ const char* position, const char* coverage, const char* wind);
void emitFragmentCode(const GrCCPRCoverageProcessor& proc, GrGLSLPPFragmentBuilder*,
const char* skOutputColor, const char* skOutputCoverage) const;
@@ -169,15 +188,23 @@ public:
//
// 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,
- const char* wind) = 0;
+ virtual WindHandling onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope,
+ SkString* code, const char* position,
+ const char* coverage, const char* wind) = 0;
// Emits the fragment code that calculates a pixel's coverage value. If using
// WindHandling::kHandled, this value must be signed appropriately.
virtual void onEmitFragmentCode(GrGLSLPPFragmentBuilder*,
const char* outputCoverage) const = 0;
+ // Returns the name of a Shader's internal varying at the point where where its value is
+ // assigned. This is intended to work whether called for a vertex or a geometry shader.
+ const char* OutName(const GrGLSLVarying& varying) const {
+ using Scope = GrGLSLVarying::Scope;
+ SkASSERT(Scope::kVertToGeo != varying.scope());
+ return Scope::kGeoToFrag == varying.scope() ? varying.gsOut() : varying.vsOut();
+ }
+
// Defines a global float2 array that contains MSAA sample locations as offsets from pixel
// center. Subclasses can use this for software multisampling.
//
@@ -185,10 +212,11 @@ public:
static int DefineSoftSampleLocations(GrGLSLPPFragmentBuilder* f, const char* samplesName);
private:
- GrGLSLVarying fWind{kHalf_GrSLType, GrGLSLVarying::Scope::kGeoToFrag};
+ GrGLSLVarying fWind;
};
class GSImpl;
+ class VSImpl;
private:
// Slightly undershoot a bloat radius of 0.5 so vertices that fall on integer boundaries don't
@@ -198,12 +226,26 @@ private:
// Number of bezier points for curves, or 3 for triangles.
int numInputPoints() const { return RenderPassIsCubic(fRenderPass) ? 4 : 3; }
+ enum class Impl : bool {
+ kGeometryShader,
+ kVertexShader
+ };
+
void initGS();
+ void initVS(GrResourceProvider*);
+
void appendGSMesh(GrBuffer* instanceBuffer, int instanceCount, int baseInstance,
- SkTArray<GrMesh, true>* out) const;
+ SkTArray<GrMesh>* out) const;
+ void appendVSMesh(GrBuffer* instanceBuffer, int instanceCount, int baseInstance,
+ SkTArray<GrMesh>* out) const;
+
GrGLSLPrimitiveProcessor* createGSImpl(std::unique_ptr<Shader>) const;
+ GrGLSLPrimitiveProcessor* createVSImpl(std::unique_ptr<Shader>) const;
const RenderPass fRenderPass;
+ const Impl fImpl;
+ sk_sp<const GrBuffer> fVertexBuffer; // Used by VSImpl.
+ sk_sp<const GrBuffer> fIndexBuffer; // Used by VSImpl.
SkDEBUGCODE(float fDebugBloat = 0;)
typedef GrGeometryProcessor INHERITED;
diff --git a/src/gpu/ccpr/GrCCPRCoverageProcessor_GSImpl.cpp b/src/gpu/ccpr/GrCCPRCoverageProcessor_GSImpl.cpp
index 5006ff5a4b..4d1df8ced2 100644
--- a/src/gpu/ccpr/GrCCPRCoverageProcessor_GSImpl.cpp
+++ b/src/gpu/ccpr/GrCCPRCoverageProcessor_GSImpl.cpp
@@ -72,7 +72,8 @@ protected:
}
g->emitFunction(kVoid_GrSLType, "emitVertex", emitArgs.count(), emitArgs.begin(), [&]() {
SkString fnBody;
- fShader->emitVaryings(varyingHandler, &fnBody, position, coverage, wind.c_str());
+ fShader->emitVaryings(varyingHandler, GrGLSLVarying::Scope::kGeoToFrag, &fnBody,
+ position, coverage, wind.c_str());
g->emitVertex(&fnBody, position, rtAdjust);
return fnBody;
}().c_str(), &emitVertexFn);
@@ -292,7 +293,7 @@ public:
};
/**
- * Generates conservatives around corners. (See comments for RenderPass)
+ * Generates conservative rasters around corners. (See comments for RenderPass)
*/
class GSCornerImpl : public GrCCPRCoverageProcessor::GSImpl {
public:
@@ -320,6 +321,7 @@ private:
};
void GrCCPRCoverageProcessor::initGS() {
+ SkASSERT(Impl::kGeometryShader == fImpl);
if (RenderPassIsCubic(fRenderPass)) {
this->addVertexAttrib("x_or_y_values", kFloat4_GrVertexAttribType); // (See appendMesh.)
SkASSERT(sizeof(CubicInstance) == this->getVertexStride() * 2);
@@ -331,11 +333,12 @@ void GrCCPRCoverageProcessor::initGS() {
}
void GrCCPRCoverageProcessor::appendGSMesh(GrBuffer* instanceBuffer, int instanceCount,
- int baseInstance, SkTArray<GrMesh, true>* out) const {
+ int baseInstance, SkTArray<GrMesh>* out) const {
// GSImpl doesn't actually make instanced draw calls. Instead, we feed transposed x,y point
// values to the GPU in a regular vertex array and draw kLines (see initGS). Then, each vertex
// invocation receives either the shape's x or y values as inputs, which it forwards to the
// geometry shader.
+ SkASSERT(Impl::kGeometryShader == fImpl);
GrMesh& mesh = out->emplace_back(GrPrimitiveType::kLines);
mesh.setNonIndexedNonInstanced(instanceCount * 2);
mesh.setVertexData(instanceBuffer, baseInstance * 2);
diff --git a/src/gpu/ccpr/GrCCPRCoverageProcessor_VSImpl.cpp b/src/gpu/ccpr/GrCCPRCoverageProcessor_VSImpl.cpp
new file mode 100644
index 0000000000..fdd304d5f4
--- /dev/null
+++ b/src/gpu/ccpr/GrCCPRCoverageProcessor_VSImpl.cpp
@@ -0,0 +1,441 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrCCPRCoverageProcessor.h"
+
+#include "GrMesh.h"
+#include "glsl/GrGLSLVertexGeoBuilder.h"
+
+using Shader = GrCCPRCoverageProcessor::Shader;
+
+static constexpr int kAttribIdx_X = 0;
+static constexpr int kAttribIdx_Y = 1;
+static constexpr int kAttribIdx_VertexData = 2;
+
+/**
+ * This class and its subclasses implement the coverage processor with vertex shaders.
+ */
+class GrCCPRCoverageProcessor::VSImpl : public GrGLSLGeometryProcessor {
+protected:
+ VSImpl(std::unique_ptr<Shader> shader) : fShader(std::move(shader)) {}
+
+ void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor&,
+ FPCoordTransformIter&& transformIter) final {
+ this->setTransformDataHelper(SkMatrix::I(), pdman, &transformIter);
+ }
+
+ void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) final {
+ const GrCCPRCoverageProcessor& proc = args.fGP.cast<GrCCPRCoverageProcessor>();
+
+ // Vertex shader.
+ GrGLSLVertexBuilder* v = args.fVertBuilder;
+ int numInputPoints = proc.numInputPoints();
+
+ v->codeAppendf("float%ix2 pts = transpose(float2x%i(%s, %s));",
+ numInputPoints, numInputPoints, proc.getAttrib(kAttribIdx_X).fName,
+ proc.getAttrib(kAttribIdx_Y).fName);
+
+ v->codeAppend ("float area_x2 = determinant(float2x2(pts[0] - pts[1], pts[0] - pts[2]));");
+ if (4 == numInputPoints) {
+ v->codeAppend ("area_x2 += determinant(float2x2(pts[0] - pts[2], pts[0] - pts[3]));");
+ }
+ v->codeAppend ("half wind = sign(area_x2);");
+
+ float bloat = kAABloatRadius;
+#ifdef SK_DEBUG
+ if (proc.debugVisualizationsEnabled()) {
+ bloat *= proc.debugBloat();
+ }
+#endif
+ v->defineConstant("bloat", bloat);
+
+ const char* coverage = this->emitVertexPosition(proc, v, gpArgs);
+ SkASSERT(kFloat2_GrSLType == gpArgs->fPositionVar.getType());
+
+ GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
+ SkString varyingCode;
+ fShader->emitVaryings(varyingHandler, GrGLSLVarying::Scope::kVertToFrag, &varyingCode,
+ gpArgs->fPositionVar.c_str(), coverage, "wind");
+ v->codeAppend(varyingCode.c_str());
+
+ varyingHandler->emitAttributes(proc);
+ SkASSERT(!args.fFPCoordTransformHandler->nextCoordTransform());
+
+ // Fragment shader.
+ fShader->emitFragmentCode(proc, args.fFragBuilder, args.fOutputColor, args.fOutputCoverage);
+ }
+
+ virtual const char* emitVertexPosition(const GrCCPRCoverageProcessor&, GrGLSLVertexBuilder*,
+ GrGPArgs*) const = 0;
+
+ virtual ~VSImpl() {}
+
+ const std::unique_ptr<Shader> fShader;
+
+ typedef GrGLSLGeometryProcessor INHERITED;
+};
+
+/**
+ * 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 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 edge_vertex_data(int32_t edgeID, int32_t endptIdx, int32_t endptVertexID,
+ int n) {
+ return pack_vertex_data(0 == endptIdx ? (edgeID + 1) % n : edgeID, (endptIdx << 1) | 1,
+ endptVertexID, 0 == endptIdx ? edgeID : (edgeID + 1) % n);
+}
+
+static constexpr int32_t kHull3AndEdgeVertices[] = {
+ hull_vertex_data(0, 0, 3),
+ hull_vertex_data(0, 1, 3),
+ hull_vertex_data(0, 2, 3),
+ hull_vertex_data(1, 0, 3),
+ hull_vertex_data(1, 1, 3),
+ hull_vertex_data(1, 2, 3),
+ hull_vertex_data(2, 0, 3),
+ hull_vertex_data(2, 1, 3),
+ hull_vertex_data(2, 2, 3),
+
+ edge_vertex_data(0, 0, 0, 3),
+ edge_vertex_data(0, 0, 1, 3),
+ edge_vertex_data(0, 0, 2, 3),
+ edge_vertex_data(0, 1, 0, 3),
+ edge_vertex_data(0, 1, 1, 3),
+ edge_vertex_data(0, 1, 2, 3),
+
+ edge_vertex_data(1, 0, 0, 3),
+ edge_vertex_data(1, 0, 1, 3),
+ edge_vertex_data(1, 0, 2, 3),
+ edge_vertex_data(1, 1, 0, 3),
+ edge_vertex_data(1, 1, 1, 3),
+ edge_vertex_data(1, 1, 2, 3),
+
+ edge_vertex_data(2, 0, 0, 3),
+ edge_vertex_data(2, 0, 1, 3),
+ edge_vertex_data(2, 0, 2, 3),
+ edge_vertex_data(2, 1, 0, 3),
+ edge_vertex_data(2, 1, 1, 3),
+ edge_vertex_data(2, 1, 2, 3),
+};
+
+GR_DECLARE_STATIC_UNIQUE_KEY(gHull3AndEdgeVertexBufferKey);
+
+static constexpr uint16_t kHull3AndEdgeIndices[] = {
+ // First corner and main body of the hull.
+ 1, 2, 0,
+ 2, 3, 0,
+ 0, 3, 8, // Main body.
+
+ // Opposite side and corners of the hull.
+ 4, 5, 3,
+ 5, 6, 3,
+ 3, 6, 8,
+ 6, 7, 8,
+
+ // First edge.
+ 10, 9, 11,
+ 9, 14, 11,
+ 11, 14, 12,
+ 14, 13, 12,
+
+ // Second edge.
+ 16, 15, 17,
+ 15, 20, 17,
+ 17, 20, 18,
+ 20, 19, 18,
+
+ // Third edge.
+ 22, 21, 23,
+ 21, 26, 23,
+ 23, 26, 24,
+ 26, 25, 24,
+};
+
+GR_DECLARE_STATIC_UNIQUE_KEY(gHull3AndEdgeIndexBufferKey);
+
+static constexpr int32_t kHull4Vertices[] = {
+ hull_vertex_data(0, 0, 4),
+ hull_vertex_data(0, 1, 4),
+ hull_vertex_data(0, 2, 4),
+ hull_vertex_data(1, 0, 4),
+ hull_vertex_data(1, 1, 4),
+ hull_vertex_data(1, 2, 4),
+ hull_vertex_data(2, 0, 4),
+ hull_vertex_data(2, 1, 4),
+ hull_vertex_data(2, 2, 4),
+ hull_vertex_data(3, 0, 4),
+ hull_vertex_data(3, 1, 4),
+ hull_vertex_data(3, 2, 4),
+
+ // No edges for now (beziers don't use edges).
+};
+
+GR_DECLARE_STATIC_UNIQUE_KEY(gHull4VertexBufferKey);
+
+static constexpr uint16_t kHull4Indices[] = {
+ // First half of the hull (split diagonally).
+ 1, 0, 2,
+ 0, 11, 2,
+ 2, 11, 3,
+ 11, 5, 3,
+ 3, 5, 4,
+
+ // Second half of the hull.
+ 7, 6, 8,
+ 6, 5, 8,
+ 8, 5, 9,
+ 5, 11, 9,
+ 9, 11, 10,
+};
+
+GR_DECLARE_STATIC_UNIQUE_KEY(gHull4IndexBufferKey);
+
+/**
+ * Generates a conservative raster hull around a convex polygon. For triangles, we also generate
+ * independent conservative rasters around each edge. (See comments for RenderPass)
+ */
+class VSHullAndEdgeImpl : public GrCCPRCoverageProcessor::VSImpl {
+public:
+ VSHullAndEdgeImpl(std::unique_ptr<Shader> shader, int numSides)
+ : VSImpl(std::move(shader)), fNumSides(numSides) {}
+
+ const char* emitVertexPosition(const GrCCPRCoverageProcessor& proc, GrGLSLVertexBuilder* v,
+ GrGPArgs* gpArgs) const override {
+ Shader::GeometryVars vars;
+ fShader->emitSetupCode(v, "pts", nullptr, "wind", &vars);
+
+ const char* hullPts = vars.fHullVars.fAlternatePoints;
+ if (!hullPts) {
+ hullPts = "pts";
+ }
+
+ // 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),
+ 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:
+ // https://developer.nvidia.com/gpugems/GPUGems2/gpugems2_chapter42.html
+ 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->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.
+ }
+
+ // 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 ("}");
+
+ return "coverage";
+ }
+
+private:
+ const int fNumSides;
+};
+
+static constexpr uint16_t kCornerIndices[] = {
+ // First corner.
+ 0, 1, 2,
+ 1, 3, 2,
+
+ // Second corner.
+ 4, 5, 6,
+ 5, 7, 6,
+
+ // Third corner.
+ 8, 9, 10,
+ 9, 11, 10,
+};
+
+GR_DECLARE_STATIC_UNIQUE_KEY(gCornerIndexBufferKey);
+
+/**
+ * Generates conservative rasters around corners. (See comments for RenderPass)
+ */
+class VSCornerImpl : public GrCCPRCoverageProcessor::VSImpl {
+public:
+ VSCornerImpl(std::unique_ptr<Shader> shader) : VSImpl(std::move(shader)) {}
+
+ const char* emitVertexPosition(const GrCCPRCoverageProcessor&, GrGLSLVertexBuilder* v,
+ GrGPArgs* gpArgs) const override {
+ Shader::GeometryVars vars;
+ v->codeAppend ("int corner_id = sk_VertexID / 4;");
+ fShader->emitSetupCode(v, "pts", "corner_id", "wind", &vars);
+
+ v->codeAppendf("float2 vertex = %s;", vars.fCornerVars.fPoint);
+ v->codeAppend ("vertex.x += (0 == (sk_VertexID & 2)) ? -bloat : +bloat;");
+ v->codeAppend ("vertex.y += (0 == (sk_VertexID & 1)) ? -bloat : +bloat;");
+
+ gpArgs->fPositionVar.set(kFloat2_GrSLType, "vertex");
+ return nullptr; // Corner vertices don't have an initial coverage value.
+ }
+};
+
+void GrCCPRCoverageProcessor::initVS(GrResourceProvider* rp) {
+ SkASSERT(Impl::kVertexShader == fImpl);
+
+ GrVertexAttribType inputPtsType = RenderPassIsCubic(fRenderPass) ?
+ kFloat4_GrVertexAttribType : kFloat3_GrVertexAttribType;
+
+ SkASSERT(kAttribIdx_X == this->numAttribs());
+ this->addInstanceAttrib("X", inputPtsType);
+
+ SkASSERT(kAttribIdx_Y == this->numAttribs());
+ this->addInstanceAttrib("Y", inputPtsType);
+
+ switch (fRenderPass) {
+ case RenderPass::kTriangleHulls: {
+ GR_DEFINE_STATIC_UNIQUE_KEY(gHull3AndEdgeVertexBufferKey);
+ fVertexBuffer = rp->findOrMakeStaticBuffer(kVertex_GrBufferType,
+ sizeof(kHull3AndEdgeVertices),
+ kHull3AndEdgeVertices,
+ gHull3AndEdgeVertexBufferKey);
+ GR_DEFINE_STATIC_UNIQUE_KEY(gHull3AndEdgeIndexBufferKey);
+ fIndexBuffer = rp->findOrMakeStaticBuffer(kIndex_GrBufferType,
+ sizeof(kHull3AndEdgeIndices),
+ kHull3AndEdgeIndices,
+ gHull3AndEdgeIndexBufferKey);
+ SkASSERT(kAttribIdx_VertexData == this->numAttribs());
+ this->addVertexAttrib("vertexdata", kInt_GrVertexAttribType);
+ break;
+ }
+ case RenderPass::kQuadraticHulls:
+ case RenderPass::kCubicHulls: {
+ GR_DEFINE_STATIC_UNIQUE_KEY(gHull4VertexBufferKey);
+ fVertexBuffer = rp->findOrMakeStaticBuffer(kVertex_GrBufferType, sizeof(kHull4Vertices),
+ kHull4Vertices, gHull4VertexBufferKey);
+ GR_DEFINE_STATIC_UNIQUE_KEY(gHull4IndexBufferKey);
+ fIndexBuffer = rp->findOrMakeStaticBuffer(kIndex_GrBufferType, sizeof(kHull4Indices),
+ kHull4Indices, gHull4IndexBufferKey);
+ SkASSERT(kAttribIdx_VertexData == this->numAttribs());
+ this->addVertexAttrib("vertexdata", kInt_GrVertexAttribType);
+ break;
+ }
+ case RenderPass::kTriangleEdges:
+ SK_ABORT("kTriangleEdges RenderPass is not used by VSImpl.");
+ break;
+ case RenderPass::kTriangleCorners:
+ case RenderPass::kQuadraticCorners:
+ case RenderPass::kCubicCorners: {
+ GR_DEFINE_STATIC_UNIQUE_KEY(gCornerIndexBufferKey);
+ fIndexBuffer = rp->findOrMakeStaticBuffer(kIndex_GrBufferType, sizeof(kCornerIndices),
+ kCornerIndices, gCornerIndexBufferKey);
+ break;
+ }
+ }
+
+#ifdef SK_DEBUG
+ if (RenderPassIsCubic(fRenderPass)) {
+ SkASSERT(offsetof(CubicInstance, fX) == this->getAttrib(kAttribIdx_X).fOffsetInRecord);
+ SkASSERT(offsetof(CubicInstance, fY) == this->getAttrib(kAttribIdx_Y).fOffsetInRecord);
+ SkASSERT(sizeof(CubicInstance) == this->getInstanceStride());
+ } else {
+ SkASSERT(offsetof(TriangleInstance, fX) == this->getAttrib(kAttribIdx_X).fOffsetInRecord);
+ SkASSERT(offsetof(TriangleInstance, fY) == this->getAttrib(kAttribIdx_Y).fOffsetInRecord);
+ SkASSERT(sizeof(TriangleInstance) == this->getInstanceStride());
+ }
+ if (fVertexBuffer) {
+ SkASSERT(sizeof(int32_t) == this->getVertexStride());
+ }
+#endif
+}
+
+static int num_indices_per_instance(GrCCPRCoverageProcessor::RenderPass pass) {
+ switch (pass) {
+ using RenderPass = GrCCPRCoverageProcessor::RenderPass;
+ case RenderPass::kTriangleHulls:
+ return SK_ARRAY_COUNT(kHull3AndEdgeIndices);
+ case RenderPass::kQuadraticHulls:
+ case RenderPass::kCubicHulls:
+ return SK_ARRAY_COUNT(kHull4Indices);
+ case RenderPass::kTriangleEdges:
+ SK_ABORT("kTriangleEdges RenderPass is not used by VSImpl.");
+ return 0;
+ case RenderPass::kTriangleCorners:
+ return SK_ARRAY_COUNT(kCornerIndices);
+ case RenderPass::kQuadraticCorners:
+ case RenderPass::kCubicCorners:
+ return SK_ARRAY_COUNT(kCornerIndices) * 2/3;
+ }
+ SK_ABORT("Invalid RenderPass");
+ return 0;
+}
+
+void GrCCPRCoverageProcessor::appendVSMesh(GrBuffer* instanceBuffer, int instanceCount,
+ int baseInstance, SkTArray<GrMesh>* out) const {
+ SkASSERT(Impl::kVertexShader == fImpl);
+ GrMesh& mesh = out->emplace_back(GrPrimitiveType::kTriangles);
+ mesh.setIndexedInstanced(fIndexBuffer.get(), num_indices_per_instance(fRenderPass),
+ instanceBuffer, instanceCount, baseInstance);
+ if (fVertexBuffer) {
+ mesh.setVertexData(fVertexBuffer.get(), 0);
+ }
+}
+
+GrGLSLPrimitiveProcessor*
+GrCCPRCoverageProcessor::createVSImpl(std::unique_ptr<Shader> shader) const {
+ switch (fRenderPass) {
+ case RenderPass::kTriangleHulls:
+ return new VSHullAndEdgeImpl(std::move(shader), 3);
+ case RenderPass::kQuadraticHulls:
+ case RenderPass::kCubicHulls:
+ return new VSHullAndEdgeImpl(std::move(shader), 4);
+ case RenderPass::kTriangleEdges:
+ SK_ABORT("kTriangleEdges RenderPass is not used by VSImpl.");
+ return nullptr;
+ case RenderPass::kTriangleCorners:
+ case RenderPass::kQuadraticCorners:
+ case RenderPass::kCubicCorners:
+ return new VSCornerImpl(std::move(shader));
+ }
+ SK_ABORT("Invalid RenderPass");
+ return nullptr;
+}
diff --git a/src/gpu/ccpr/GrCCPRCubicShader.cpp b/src/gpu/ccpr/GrCCPRCubicShader.cpp
index c9e546a74b..f2ef861fc2 100644
--- a/src/gpu/ccpr/GrCCPRCubicShader.cpp
+++ b/src/gpu/ccpr/GrCCPRCubicShader.cpp
@@ -76,25 +76,29 @@ void GrCCPRCubicShader::emitSetupCode(GrGLSLVertexGeoBuilder* s, const char* pts
}
Shader::WindHandling GrCCPRCubicShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
+ GrGLSLVarying::Scope scope,
SkString* code, const char* position,
const char* coverage, const char* /*wind*/) {
SkASSERT(!coverage);
+ fKLMD.reset(kFloat4_GrSLType, scope);
varyingHandler->addVarying("klmd", &fKLMD);
code->appendf("float3 klm = float3(%s, 1) * %s;", position, fKLMMatrix.c_str());
code->appendf("float d = dot(float3(%s, 1), %s);", position, fEdgeDistanceEquation.c_str());
- code->appendf("%s = float4(klm, d);", fKLMD.gsOut());
+ code->appendf("%s = float4(klm, d);", OutName(fKLMD));
- this->onEmitVaryings(varyingHandler, code);
+ this->onEmitVaryings(varyingHandler, scope, code);
return WindHandling::kNotHandled;
}
-void GrCCPRCubicHullShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler, SkString* code) {
- // "klm" was just defined by the base class.
+void GrCCPRCubicHullShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
+ GrGLSLVarying::Scope scope, SkString* code) {
+ fGradMatrix.reset(kFloat2x2_GrSLType, scope);
varyingHandler->addVarying("grad_matrix", &fGradMatrix);
- code->appendf("%s[0] = 3 * klm[0] * %s[0].xy;", fGradMatrix.gsOut(), fKLMMatrix.c_str());
+ // "klm" was just defined by the base class.
+ code->appendf("%s[0] = 3 * klm[0] * %s[0].xy;", OutName(fGradMatrix), fKLMMatrix.c_str());
code->appendf("%s[1] = -klm[1] * %s[2].xy - klm[2] * %s[1].xy;",
- fGradMatrix.gsOut(), fKLMMatrix.c_str(), fKLMMatrix.c_str());
+ OutName(fGradMatrix), fKLMMatrix.c_str(), fKLMMatrix.c_str());
}
void GrCCPRCubicHullShader::onEmitFragmentCode(GrGLSLPPFragmentBuilder* f,
@@ -113,15 +117,18 @@ void GrCCPRCubicCornerShader::onEmitSetupCode(GrGLSLVertexGeoBuilder* s, const c
vars->fCornerVars.fPoint = "corner";
}
-void GrCCPRCubicCornerShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler, SkString* code) {
+void GrCCPRCubicCornerShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
+ GrGLSLVarying::Scope scope, SkString* code) {
+ fdKLMDdx.reset(kFloat4_GrSLType, scope);
varyingHandler->addFlatVarying("dklmddx", &fdKLMDdx);
code->appendf("%s = float4(%s[0].x, %s[1].x, %s[2].x, %s.x);",
- fdKLMDdx.gsOut(), fKLMMatrix.c_str(), fKLMMatrix.c_str(),
+ OutName(fdKLMDdx), fKLMMatrix.c_str(), fKLMMatrix.c_str(),
fKLMMatrix.c_str(), fEdgeDistanceEquation.c_str());
+ fdKLMDdy.reset(kFloat4_GrSLType, scope);
varyingHandler->addFlatVarying("dklmddy", &fdKLMDdy);
code->appendf("%s = float4(%s[0].y, %s[1].y, %s[2].y, %s.y);",
- fdKLMDdy.gsOut(), fKLMMatrix.c_str(), fKLMMatrix.c_str(),
+ OutName(fdKLMDdy), fKLMMatrix.c_str(), fKLMMatrix.c_str(),
fKLMMatrix.c_str(), fEdgeDistanceEquation.c_str());
}
diff --git a/src/gpu/ccpr/GrCCPRCubicShader.h b/src/gpu/ccpr/GrCCPRCubicShader.h
index 10f4dffd76..bb578782f4 100644
--- a/src/gpu/ccpr/GrCCPRCubicShader.h
+++ b/src/gpu/ccpr/GrCCPRCubicShader.h
@@ -29,31 +29,31 @@ protected:
virtual void onEmitSetupCode(GrGLSLVertexGeoBuilder*, const char* pts, const char* repetitionID,
GeometryVars*) const {}
- WindHandling onEmitVaryings(GrGLSLVaryingHandler*, SkString* code, const char* position,
- const char* coverage, const char* wind) final;
+ WindHandling onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code,
+ const char* position, const char* coverage, const char* wind) final;
- virtual void onEmitVaryings(GrGLSLVaryingHandler*, SkString* code) = 0;
+ virtual void onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code) = 0;
GrShaderVar fKLMMatrix{"klm_matrix", kFloat3x3_GrSLType};
GrShaderVar fEdgeDistanceEquation{"edge_distance_equation", kFloat3_GrSLType};
- GrGLSLVarying fKLMD{kFloat4_GrSLType, GrGLSLVarying::Scope::kGeoToFrag};
+ GrGLSLVarying fKLMD;
};
class GrCCPRCubicHullShader : public GrCCPRCubicShader {
- void onEmitVaryings(GrGLSLVaryingHandler*, SkString* code) override;
+ void onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code) override;
void onEmitFragmentCode(GrGLSLPPFragmentBuilder*, const char* outputCoverage) const override;
- GrGLSLVarying fGradMatrix{kFloat2x2_GrSLType, GrGLSLVarying::Scope::kGeoToFrag};
+ GrGLSLVarying fGradMatrix;
};
class GrCCPRCubicCornerShader : public GrCCPRCubicShader {
void onEmitSetupCode(GrGLSLVertexGeoBuilder*, const char* pts, const char* repetitionID,
GeometryVars*) const override;
- void onEmitVaryings(GrGLSLVaryingHandler*, SkString* code) override;
+ void onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code) override;
void onEmitFragmentCode(GrGLSLPPFragmentBuilder*, const char* outputCoverage) const override;
- GrGLSLVarying fdKLMDdx{kFloat4_GrSLType, GrGLSLVarying::Scope::kGeoToFrag};
- GrGLSLVarying fdKLMDdy{kFloat4_GrSLType, GrGLSLVarying::Scope::kGeoToFrag};
+ GrGLSLVarying fdKLMDdx;
+ GrGLSLVarying fdKLMDdy;
};
#endif
diff --git a/src/gpu/ccpr/GrCCPRQuadraticShader.cpp b/src/gpu/ccpr/GrCCPRQuadraticShader.cpp
index 308e3ff927..429cb4efc3 100644
--- a/src/gpu/ccpr/GrCCPRQuadraticShader.cpp
+++ b/src/gpu/ccpr/GrCCPRQuadraticShader.cpp
@@ -7,6 +7,7 @@
#include "GrCCPRQuadraticShader.h"
+#include "glsl/GrGLSLVertexGeoBuilder.h"
#include "glsl/GrGLSLFragmentShaderBuilder.h"
#include "glsl/GrGLSLVertexGeoBuilder.h"
@@ -33,19 +34,21 @@ void GrCCPRQuadraticShader::emitSetupCode(GrGLSLVertexGeoBuilder* s, const char*
}
Shader::WindHandling GrCCPRQuadraticShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
+ GrGLSLVarying::Scope scope,
SkString* code, const char* position,
const char* coverage,
const char* /*wind*/) {
SkASSERT(!coverage);
+ fXYD.reset(kFloat3_GrSLType, scope);
varyingHandler->addVarying("xyd", &fXYD);
code->appendf("%s.xy = (%s * float3(%s, 1)).xy;",
- fXYD.gsOut(), fCanonicalMatrix.c_str(), position);
+ OutName(fXYD), fCanonicalMatrix.c_str(), position);
code->appendf("%s.z = dot(%s.xy, %s) + %s.z;",
- fXYD.gsOut(), fEdgeDistanceEquation.c_str(), position,
+ OutName(fXYD), fEdgeDistanceEquation.c_str(), position,
fEdgeDistanceEquation.c_str());
- this->onEmitVaryings(varyingHandler, code);
+ this->onEmitVaryings(varyingHandler, scope, code);
return WindHandling::kNotHandled;
}
@@ -69,10 +72,11 @@ void GrCCPRQuadraticHullShader::onEmitSetupCode(GrGLSLVertexGeoBuilder* s, const
}
void GrCCPRQuadraticHullShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
- SkString* code) {
+ GrGLSLVarying::Scope scope, SkString* code) {
+ fGrad.reset(kFloat2_GrSLType, scope);
varyingHandler->addVarying("grad", &fGrad);
code->appendf("%s = float2(2 * %s.x, -1) * float2x2(%s);",
- fGrad.gsOut(), fXYD.gsOut(), fCanonicalMatrix.c_str());
+ OutName(fGrad), OutName(fXYD), fCanonicalMatrix.c_str());
}
void GrCCPRQuadraticHullShader::onEmitFragmentCode(GrGLSLPPFragmentBuilder* f,
@@ -91,15 +95,17 @@ void GrCCPRQuadraticCornerShader::onEmitSetupCode(GrGLSLVertexGeoBuilder* s, con
}
void GrCCPRQuadraticCornerShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
- SkString* code) {
+ GrGLSLVarying::Scope scope, SkString* code) {
+ fdXYDdx.reset(kFloat3_GrSLType, scope);
varyingHandler->addFlatVarying("dXYDdx", &fdXYDdx);
code->appendf("%s = float3(%s[0].x, %s[0].y, %s.x);",
- fdXYDdx.gsOut(), fCanonicalMatrix.c_str(), fCanonicalMatrix.c_str(),
+ OutName(fdXYDdx), fCanonicalMatrix.c_str(), fCanonicalMatrix.c_str(),
fEdgeDistanceEquation.c_str());
+ fdXYDdy.reset(kFloat3_GrSLType, scope);
varyingHandler->addFlatVarying("dXYDdy", &fdXYDdy);
code->appendf("%s = float3(%s[1].x, %s[1].y, %s.y);",
- fdXYDdy.gsOut(), fCanonicalMatrix.c_str(), fCanonicalMatrix.c_str(),
+ OutName(fdXYDdy), fCanonicalMatrix.c_str(), fCanonicalMatrix.c_str(),
fEdgeDistanceEquation.c_str());
}
diff --git a/src/gpu/ccpr/GrCCPRQuadraticShader.h b/src/gpu/ccpr/GrCCPRQuadraticShader.h
index 14505c6e2e..76b2563e43 100644
--- a/src/gpu/ccpr/GrCCPRQuadraticShader.h
+++ b/src/gpu/ccpr/GrCCPRQuadraticShader.h
@@ -28,14 +28,14 @@ protected:
virtual void onEmitSetupCode(GrGLSLVertexGeoBuilder*, const char* pts, const char* repetitionID,
GeometryVars*) const = 0;
- WindHandling onEmitVaryings(GrGLSLVaryingHandler*, SkString* code, const char* position,
- const char* coverage, const char* wind) final;
+ WindHandling onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code,
+ const char* position, const char* coverage, const char* wind) final;
- virtual void onEmitVaryings(GrGLSLVaryingHandler*, SkString* code) = 0;
+ virtual void onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code) {}
const GrShaderVar fCanonicalMatrix{"canonical_matrix", kFloat3x3_GrSLType};
const GrShaderVar fEdgeDistanceEquation{"edge_distance_equation", kFloat3_GrSLType};
- GrGLSLVarying fXYD{kFloat3_GrSLType, GrGLSLVarying::Scope::kGeoToFrag};
+ GrGLSLVarying fXYD;
};
/**
@@ -47,10 +47,10 @@ protected:
class GrCCPRQuadraticHullShader : public GrCCPRQuadraticShader {
void onEmitSetupCode(GrGLSLVertexGeoBuilder*, const char* pts, const char* repetitionID,
GeometryVars*) const override;
- void onEmitVaryings(GrGLSLVaryingHandler*, SkString* code) override;
+ void onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code) override;
void onEmitFragmentCode(GrGLSLPPFragmentBuilder*, const char* outputCoverage) const override;
- GrGLSLVarying fGrad{kFloat2_GrSLType, GrGLSLVarying::Scope::kGeoToFrag};
+ GrGLSLVarying fGrad;
};
/**
@@ -59,11 +59,11 @@ class GrCCPRQuadraticHullShader : public GrCCPRQuadraticShader {
class GrCCPRQuadraticCornerShader : public GrCCPRQuadraticShader {
void onEmitSetupCode(GrGLSLVertexGeoBuilder*, const char* pts, const char* repetitionID,
GeometryVars*) const override;
- void onEmitVaryings(GrGLSLVaryingHandler*, SkString* code) override;
+ void onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code) override;
void onEmitFragmentCode(GrGLSLPPFragmentBuilder*, const char* outputCoverage) const override;
- GrGLSLVarying fdXYDdx{kFloat3_GrSLType, GrGLSLVarying::Scope::kGeoToFrag};
- GrGLSLVarying fdXYDdy{kFloat3_GrSLType, GrGLSLVarying::Scope::kGeoToFrag};
+ GrGLSLVarying fdXYDdx;
+ GrGLSLVarying fdXYDdy;
};
#endif
diff --git a/src/gpu/ccpr/GrCCPRTriangleShader.cpp b/src/gpu/ccpr/GrCCPRTriangleShader.cpp
index ce05697dbf..130580125c 100644
--- a/src/gpu/ccpr/GrCCPRTriangleShader.cpp
+++ b/src/gpu/ccpr/GrCCPRTriangleShader.cpp
@@ -13,14 +13,16 @@
using Shader = GrCCPRCoverageProcessor::Shader;
Shader::WindHandling GrCCPRTriangleShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
+ GrGLSLVarying::Scope scope,
SkString* code, const char* /*position*/,
const char* coverage, const char* wind) {
+ fCoverageTimesWind.reset(kHalf_GrSLType, scope);
if (!coverage) {
varyingHandler->addFlatVarying("wind", &fCoverageTimesWind);
- code->appendf("%s = %s;", fCoverageTimesWind.gsOut(), wind);
+ code->appendf("%s = %s;", OutName(fCoverageTimesWind), wind);
} else {
varyingHandler->addVarying("coverage_times_wind", &fCoverageTimesWind);
- code->appendf("%s = %s * %s;", fCoverageTimesWind.gsOut(), coverage, wind);
+ code->appendf("%s = %s * %s;", OutName(fCoverageTimesWind), coverage, wind);
}
return WindHandling::kHandled;
}
@@ -85,18 +87,23 @@ void GrCCPRTriangleCornerShader::emitSetupCode(GrGLSLVertexGeoBuilder* s, const
}
Shader::WindHandling
-GrCCPRTriangleCornerShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler, SkString* code,
+GrCCPRTriangleCornerShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
+ GrGLSLVarying::Scope scope, SkString* code,
const char* position, const char* coverage,
const char* /*wind*/) {
SkASSERT(!coverage);
+ fCornerLocationInAABoxes.reset(kFloat2x2_GrSLType, scope);
varyingHandler->addVarying("corner_location_in_aa_boxes", &fCornerLocationInAABoxes);
+
+ fBisectInAABoxes.reset(kFloat2x2_GrSLType, scope);
varyingHandler->addFlatVarying("bisect_in_aa_boxes", &fBisectInAABoxes);
+
code->appendf("for (int i = 0; i < 2; ++i) {");
code->appendf( "%s[i] = %s * %s[i] + %s[i];",
- fCornerLocationInAABoxes.gsOut(), position, fAABoxMatrices.c_str(),
+ OutName(fCornerLocationInAABoxes), position, fAABoxMatrices.c_str(),
fAABoxTranslates.c_str());
- code->appendf( "%s[i] = %s[i];", fBisectInAABoxes.gsOut(), fGeoShaderBisects.c_str());
+ code->appendf( "%s[i] = %s[i];", OutName(fBisectInAABoxes), fGeoShaderBisects.c_str());
code->appendf("}");
return WindHandling::kNotHandled;
diff --git a/src/gpu/ccpr/GrCCPRTriangleShader.h b/src/gpu/ccpr/GrCCPRTriangleShader.h
index 1f58e84d78..02eb77174b 100644
--- a/src/gpu/ccpr/GrCCPRTriangleShader.h
+++ b/src/gpu/ccpr/GrCCPRTriangleShader.h
@@ -11,35 +11,38 @@
#include "ccpr/GrCCPRCoverageProcessor.h"
/**
- * Passes 1 & 2: Draw the triangle's conservative raster hull with a coverage of 1, then smooth the
- * edges by drawing the conservative rasters of all 3 edges and interpolating from
- * coverage=-1 on the outside to coverage=0 on the inside.
+ * Steps 1 & 2: Draw the triangle's conservative raster hull with a coverage of +1, then smooth the
+ * edges by drawing the conservative rasters of all 3 edges and interpolating from
+ * coverage=-1 on the outside to coverage=0 on the inside. The Impl may choose to
+ * implement these steps in either one or two actual render passes.
*/
class GrCCPRTriangleShader : public GrCCPRCoverageProcessor::Shader {
- WindHandling onEmitVaryings(GrGLSLVaryingHandler*, SkString* code, const char* position,
- const char* coverage, const char* wind) override;
+ WindHandling onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code,
+ const char* position, const char* coverage,
+ const char* wind) override;
void onEmitFragmentCode(GrGLSLPPFragmentBuilder*, const char* outputCoverage) const override;
- GrGLSLVarying fCoverageTimesWind{kHalf_GrSLType, GrGLSLVarying::Scope::kGeoToFrag};
+ GrGLSLVarying fCoverageTimesWind;
};
/**
- * Pass 3: Touch up the corner pixels. Here we fix the simple distance-to-edge coverage analysis
+ * Step 3: Touch up the corner pixels. Here we fix the simple distance-to-edge coverage analysis
* done previously so that it takes into account the region that is outside both edges at
* the same time.
*/
class GrCCPRTriangleCornerShader : public GrCCPRCoverageProcessor::Shader {
void emitSetupCode(GrGLSLVertexGeoBuilder*, const char* pts, const char* repetitionID,
const char* wind, GeometryVars*) const override;
- WindHandling onEmitVaryings(GrGLSLVaryingHandler*, SkString* code, const char* position,
- const char* coverage, const char* wind) override;
+ WindHandling onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code,
+ const char* position, const char* coverage,
+ const char* wind) override;
void onEmitFragmentCode(GrGLSLPPFragmentBuilder* f, const char* outputCoverage) const override;
GrShaderVar fAABoxMatrices{"aa_box_matrices", kFloat2x2_GrSLType, 2};
GrShaderVar fAABoxTranslates{"aa_box_translates", kFloat2_GrSLType, 2};
GrShaderVar fGeoShaderBisects{"bisects", kFloat2_GrSLType, 2};
- GrGLSLVarying fCornerLocationInAABoxes{kFloat2x2_GrSLType, GrGLSLVarying::Scope::kGeoToFrag};
- GrGLSLVarying fBisectInAABoxes{kFloat2x2_GrSLType, GrGLSLVarying::Scope::kGeoToFrag};
+ GrGLSLVarying fCornerLocationInAABoxes;
+ GrGLSLVarying fBisectInAABoxes;
};
#endif
diff --git a/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp b/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp
index a239569b3e..6a38ee099b 100644
--- a/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp
+++ b/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp
@@ -38,14 +38,12 @@ static void crop_path(const SkPath& path, const SkIRect& cropbox, SkPath* out) {
bool GrCoverageCountingPathRenderer::IsSupported(const GrCaps& caps) {
const GrShaderCaps& shaderCaps = *caps.shaderCaps();
- return shaderCaps.geometryShaderSupport() &&
- shaderCaps.integerSupport() &&
+ return shaderCaps.integerSupport() &&
shaderCaps.flatInterpolationSupport() &&
caps.instanceAttribSupport() &&
GrCaps::kNone_MapFlags != caps.mapBufferFlags() &&
caps.isConfigTexturable(kAlpha_half_GrPixelConfig) &&
caps.isConfigRenderable(kAlpha_half_GrPixelConfig, /*withMSAA=*/false) &&
- GrCaps::kNone_MapFlags != caps.mapBufferFlags() &&
!caps.blacklistCoverageCounting();
}