aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Chris Dalton <csmartdalton@google.com>2017-12-10 16:41:45 -0700
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-12-11 17:27:38 +0000
commit2326177e3499d96e1e5df68504cc98764d80209a (patch)
tree4178ee42f8e82bb0ea2edcc1399c5663c4954356 /src
parent30c48065dd4c200c5b37256ff943bc2032f2a9fb (diff)
CCPR: Don't use instanced draw calls with geometry shaders
It isn't necessary for the vertex shader to know all the points because everything happens in the geometry shader. It's simpler to use regular vertex arrays instead. Bug: skia: Change-Id: I7bf83180476fbe0ab01492611cd72e72b3f7d4f2 Reviewed-on: https://skia-review.googlesource.com/82881 Reviewed-by: Brian Salomon <bsalomon@google.com> Commit-Queue: Chris Dalton <csmartdalton@google.com>
Diffstat (limited to 'src')
-rw-r--r--src/gpu/ccpr/GrCCPRCoverageOp.cpp28
-rw-r--r--src/gpu/ccpr/GrCCPRCoverageOp.h9
-rw-r--r--src/gpu/ccpr/GrCCPRCoverageProcessor.cpp26
-rw-r--r--src/gpu/ccpr/GrCCPRCoverageProcessor.h145
-rw-r--r--src/gpu/ccpr/GrCCPRCoverageProcessor_GSImpl.cpp48
-rw-r--r--src/gpu/glsl/GrGLSLGeometryProcessor.cpp28
6 files changed, 143 insertions, 141 deletions
diff --git a/src/gpu/ccpr/GrCCPRCoverageOp.cpp b/src/gpu/ccpr/GrCCPRCoverageOp.cpp
index 5775c5aa86..57b73bf935 100644
--- a/src/gpu/ccpr/GrCCPRCoverageOp.cpp
+++ b/src/gpu/ccpr/GrCCPRCoverageOp.cpp
@@ -393,32 +393,28 @@ void GrCCPRCoverageOp::onExecute(GrOpFlushState* flushState) {
fDynamicStatesScratchBuffer.reserve(1 + fScissorBatches.count());
// Triangles.
- auto constexpr kTrianglesGrPrimitiveType = GrCCPRCoverageProcessor::kTrianglesGrPrimitiveType;
this->drawMaskPrimitives(flushState, pipeline, RenderPass::kTriangleHulls,
- kTrianglesGrPrimitiveType, 3, &PrimitiveTallies::fTriangles);
+ &PrimitiveTallies::fTriangles);
this->drawMaskPrimitives(flushState, pipeline, RenderPass::kTriangleEdges,
- kTrianglesGrPrimitiveType, 3, &PrimitiveTallies::fTriangles);
+ &PrimitiveTallies::fTriangles);
this->drawMaskPrimitives(flushState, pipeline, RenderPass::kTriangleCorners,
- kTrianglesGrPrimitiveType, 3, &PrimitiveTallies::fTriangles);
+ &PrimitiveTallies::fTriangles);
// Quadratics.
- auto constexpr kQuadraticsGrPrimitiveType = GrCCPRCoverageProcessor::kQuadraticsGrPrimitiveType;
this->drawMaskPrimitives(flushState, pipeline, RenderPass::kQuadraticHulls,
- kQuadraticsGrPrimitiveType, 3, &PrimitiveTallies::fQuadratics);
+ &PrimitiveTallies::fQuadratics);
this->drawMaskPrimitives(flushState, pipeline, RenderPass::kQuadraticCorners,
- kQuadraticsGrPrimitiveType, 3, &PrimitiveTallies::fQuadratics);
+ &PrimitiveTallies::fQuadratics);
// Cubics.
- auto constexpr kCubicsGrPrimitiveType = GrCCPRCoverageProcessor::kCubicsGrPrimitiveType;
this->drawMaskPrimitives(flushState, pipeline, RenderPass::kCubicHulls,
- kCubicsGrPrimitiveType, 4, &PrimitiveTallies::fCubics);
+ &PrimitiveTallies::fCubics);
this->drawMaskPrimitives(flushState, pipeline, RenderPass::kCubicCorners,
- kCubicsGrPrimitiveType, 4, &PrimitiveTallies::fCubics);
+ &PrimitiveTallies::fCubics);
}
void GrCCPRCoverageOp::drawMaskPrimitives(GrOpFlushState* flushState, const GrPipeline& pipeline,
GrCCPRCoverageProcessor::RenderPass renderPass,
- GrPrimitiveType primType, int vertexCount,
int PrimitiveTallies::* instanceType) const {
using ScissorMode = GrCCPRCoverageOpsBuilder::ScissorMode;
SkASSERT(pipeline.getScissorState().enabled());
@@ -426,11 +422,12 @@ void GrCCPRCoverageOp::drawMaskPrimitives(GrOpFlushState* flushState, const GrPi
fMeshesScratchBuffer.reset();
fDynamicStatesScratchBuffer.reset();
+ GrCCPRCoverageProcessor proc(renderPass);
+
if (const int instanceCount = fInstanceCounts[(int)ScissorMode::kNonScissored].*instanceType) {
SkASSERT(instanceCount > 0);
const int baseInstance = fBaseInstances[(int)ScissorMode::kNonScissored].*instanceType;
- GrMesh& mesh = fMeshesScratchBuffer.emplace_back(primType);
- mesh.setInstanced(fInstanceBuffer.get(), instanceCount, baseInstance, vertexCount);
+ proc.appendMesh(fInstanceBuffer.get(), instanceCount, baseInstance, &fMeshesScratchBuffer);
fDynamicStatesScratchBuffer.push_back().fScissorRect.setXYWH(0, 0, fDrawBounds.width(),
fDrawBounds.height());
}
@@ -444,8 +441,8 @@ void GrCCPRCoverageOp::drawMaskPrimitives(GrOpFlushState* flushState, const GrPi
continue;
}
SkASSERT(instanceCount > 0);
- GrMesh& mesh = fMeshesScratchBuffer.emplace_back(primType);
- mesh.setInstanced(fInstanceBuffer.get(), instanceCount, baseInstance, vertexCount);
+ proc.appendMesh(fInstanceBuffer.get(), instanceCount, baseInstance,
+ &fMeshesScratchBuffer);
fDynamicStatesScratchBuffer.push_back().fScissorRect = batch.fScissor;
baseInstance += instanceCount;
}
@@ -454,7 +451,6 @@ void GrCCPRCoverageOp::drawMaskPrimitives(GrOpFlushState* flushState, const GrPi
SkASSERT(fMeshesScratchBuffer.count() == fDynamicStatesScratchBuffer.count());
if (!fMeshesScratchBuffer.empty()) {
- GrCCPRCoverageProcessor proc(renderPass);
SkASSERT(flushState->rtCommandBuffer());
flushState->rtCommandBuffer()->draw(pipeline, proc, fMeshesScratchBuffer.begin(),
fDynamicStatesScratchBuffer.begin(),
diff --git a/src/gpu/ccpr/GrCCPRCoverageOp.h b/src/gpu/ccpr/GrCCPRCoverageOp.h
index 571e29a8cf..7957586958 100644
--- a/src/gpu/ccpr/GrCCPRCoverageOp.h
+++ b/src/gpu/ccpr/GrCCPRCoverageOp.h
@@ -158,9 +158,8 @@ private:
const PrimitiveTallies baseInstances[kNumScissorModes],
const PrimitiveTallies endInstances[kNumScissorModes]);
- void drawMaskPrimitives(GrOpFlushState*, const GrPipeline&,
- const GrCCPRCoverageProcessor::RenderPass, GrPrimitiveType,
- int vertexCount, int PrimitiveTallies::* instanceType) const;
+ void drawMaskPrimitives(GrOpFlushState*, const GrPipeline&, GrCCPRCoverageProcessor::RenderPass,
+ int PrimitiveTallies::* instanceType) const;
sk_sp<GrBuffer> fInstanceBuffer;
PrimitiveTallies fBaseInstances[kNumScissorModes];
@@ -168,8 +167,8 @@ private:
const SkTArray<ScissorBatch, true> fScissorBatches;
const SkISize fDrawBounds;
- mutable SkTArray<GrMesh> fMeshesScratchBuffer;
- mutable SkTArray<GrPipeline::DynamicState> fDynamicStatesScratchBuffer;
+ mutable SkTArray<GrMesh, true> 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 61e431a2c9..c7b80390e9 100644
--- a/src/gpu/ccpr/GrCCPRCoverageProcessor.cpp
+++ b/src/gpu/ccpr/GrCCPRCoverageProcessor.cpp
@@ -13,32 +13,6 @@
#include "ccpr/GrCCPRTriangleShader.h"
#include "glsl/GrGLSLFragmentShaderBuilder.h"
-GrCCPRCoverageProcessor::GrCCPRCoverageProcessor(RenderPass renderPass)
- : INHERITED(kGrCCPRCoverageProcessor_ClassID)
- , fRenderPass(renderPass) {
- if (RenderPassIsCubic(fRenderPass)) {
- this->addInstanceAttrib("X", kFloat4_GrVertexAttribType);
- this->addInstanceAttrib("Y", kFloat4_GrVertexAttribType);
-
- SkASSERT(offsetof(CubicInstance, fX) ==
- this->getInstanceAttrib(InstanceAttribs::kX).fOffsetInRecord);
- SkASSERT(offsetof(CubicInstance, fY) ==
- this->getInstanceAttrib(InstanceAttribs::kY).fOffsetInRecord);
- SkASSERT(sizeof(CubicInstance) == this->getInstanceStride());
- } else {
- this->addInstanceAttrib("X", kFloat3_GrVertexAttribType);
- this->addInstanceAttrib("Y", kFloat3_GrVertexAttribType);
-
- SkASSERT(offsetof(TriangleInstance, fX) ==
- this->getInstanceAttrib(InstanceAttribs::kX).fOffsetInRecord);
- SkASSERT(offsetof(TriangleInstance, fY) ==
- this->getInstanceAttrib(InstanceAttribs::kY).fOffsetInRecord);
- SkASSERT(sizeof(TriangleInstance) == this->getInstanceStride());
- }
-
- this->setWillUseGeoShader();
-}
-
void GrCCPRCoverageProcessor::Shader::emitVaryings(GrGLSLVaryingHandler* varyingHandler,
SkString* code, const char* position,
const char* coverage, const char* wind) {
diff --git a/src/gpu/ccpr/GrCCPRCoverageProcessor.h b/src/gpu/ccpr/GrCCPRCoverageProcessor.h
index 7ecb888005..dfd2e249c4 100644
--- a/src/gpu/ccpr/GrCCPRCoverageProcessor.h
+++ b/src/gpu/ccpr/GrCCPRCoverageProcessor.h
@@ -15,6 +15,7 @@
class GrGLSLPPFragmentBuilder;
class GrGLSLShaderBuilder;
+class GrMesh;
/**
* This is the geometry processor for the simple convex primitive shapes (triangles and closed curve
@@ -26,22 +27,12 @@ class GrGLSLShaderBuilder;
* below). Once all of a path's primitives have been drawn, the render target contains a composite
* coverage count that can then be used to draw the path (see GrCCPRPathProcessor).
*
- * Draw calls are instanced. They use use the corresponding GrPrimitiveTypes as defined below.
- * Caller fills out the primitives' atlas-space vertices and control points in instance arrays
- * using the provided structs below. There are no vertex attribs.
+ * To draw a renderer pass, see appendMesh below.
*/
class GrCCPRCoverageProcessor : public GrGeometryProcessor {
public:
- static constexpr GrPrimitiveType kTrianglesGrPrimitiveType = GrPrimitiveType::kTriangles;
- static constexpr GrPrimitiveType kQuadraticsGrPrimitiveType = GrPrimitiveType::kTriangles;
- static constexpr GrPrimitiveType kCubicsGrPrimitiveType = GrPrimitiveType::kLinesAdjacency;
-
- enum class InstanceAttribs : int {
- kX,
- kY
- };
-
- struct TriangleInstance { // Also used by quadratics.
+ // Defines a single triangle or closed quadratic bezier, with transposed x,y point values.
+ struct TriangleInstance {
float fX[3];
float fY[3];
@@ -49,6 +40,7 @@ public:
void set(const SkPoint&, const SkPoint&, const SkPoint&, const Sk2f& trans);
};
+ // Defines a single closed cubic bezier, with transposed x,y point values.
struct CubicInstance {
float fX[4];
float fY[4];
@@ -56,11 +48,9 @@ public:
void set(const SkPoint[4], float dx, float dy);
};
- /**
- * All primitive shapes (triangles and convex closed curve segments) 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.
- */
+ // All primitive shapes (triangles and convex closed curve segments) 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.
enum class RenderPass {
// Triangles.
kTriangleHulls,
@@ -75,42 +65,44 @@ public:
kCubicHulls,
kCubicCorners
};
+ static bool RenderPassIsCubic(RenderPass);
+ static const char* RenderPassName(RenderPass);
- static inline bool RenderPassIsCubic(RenderPass pass) {
- switch (pass) {
- case RenderPass::kTriangleHulls:
- case RenderPass::kTriangleEdges:
- case RenderPass::kTriangleCorners:
- case RenderPass::kQuadraticHulls:
- case RenderPass::kQuadraticCorners:
- return false;
- case RenderPass::kCubicHulls:
- case RenderPass::kCubicCorners:
- return true;
- }
- SK_ABORT("Invalid GrCCPRCoverageProcessor::RenderPass");
- return false;
+ GrCCPRCoverageProcessor(RenderPass pass)
+ : INHERITED(kGrCCPRCoverageProcessor_ClassID)
+ , fRenderPass(pass) {
+ this->initGS();
}
- static inline const char* RenderPassName(RenderPass pass) {
- switch (pass) {
- case RenderPass::kTriangleHulls: return "kTriangleHulls";
- case RenderPass::kTriangleEdges: return "kTriangleEdges";
- case RenderPass::kTriangleCorners: return "kTriangleCorners";
- case RenderPass::kQuadraticHulls: return "kQuadraticHulls";
- case RenderPass::kQuadraticCorners: return "kQuadraticCorners";
- case RenderPass::kCubicHulls: return "kCubicHulls";
- case RenderPass::kCubicCorners: return "kCubicCorners";
- }
- SK_ABORT("Invalid GrCCPRCoverageProcessor::RenderPass");
- return "";
+ // Appends a GrMesh that will draw the provided instances. The instanceBuffer must be an array
+ // of either TriangleInstance or CubicInstance, depending on this processor's RendererPass, with
+ // coordinates in the desired shape's final atlas-space position.
+ //
+ // 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);
}
- /**
- * 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.
- */
+ // GrPrimitiveProcessor overrides.
+ const char* name() const override { return RenderPassName(fRenderPass); }
+ SkString dumpInfo() const override {
+ return SkStringPrintf("%s\n%s", this->name(), this->INHERITED::dumpInfo().c_str());
+ }
+ void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
+ GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override;
+
+#ifdef SK_DEBUG
+ // Increases the 1/2 pixel AA bloat by a factor of debugBloat and outputs color instead of
+ // coverage (coverage=+1 -> green, coverage=0 -> black, coverage=-1 -> red).
+ void enableDebugVisualizations(float debugBloat) { fDebugBloat = debugBloat; }
+ bool debugVisualizationsEnabled() const { return fDebugBloat > 0; }
+ 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.
class Shader {
public:
using TexelBufferHandle = GrGLSLGeometryProcessor::TexelBufferHandle;
@@ -211,27 +203,6 @@ public:
GrGLSLVarying fWind{kHalf_GrSLType, GrGLSLVarying::Scope::kGeoToFrag};
};
- GrCCPRCoverageProcessor(RenderPass);
-
- const char* name() const override { return RenderPassName(fRenderPass); }
- SkString dumpInfo() const override {
- return SkStringPrintf("%s\n%s", this->name(), this->INHERITED::dumpInfo().c_str());
- }
- const Attribute& getInstanceAttrib(InstanceAttribs attribID) const {
- return this->getAttrib((int)attribID);
- }
-
- void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
- GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override;
-
-#ifdef SK_DEBUG
- // Increases the 1/2 pixel AA bloat by a factor of debugBloat and outputs color instead of
- // coverage (coverage=+1 -> green, coverage=0 -> black, coverage=-1 -> red).
- void enableDebugVisualizations(float debugBloat) { fDebugBloat = debugBloat; }
- bool debugVisualizationsEnabled() const { return fDebugBloat > 0; }
- float debugBloat() const { SkASSERT(this->debugVisualizationsEnabled()); return fDebugBloat; }
-#endif
-
class GSImpl;
private:
@@ -239,6 +210,10 @@ private:
// accidentally bleed into neighbor pixels.
static constexpr float kAABloatRadius = 0.491111f;
+ void initGS();
+ void appendGSMesh(GrBuffer* instanceBuffer, int instanceCount, int baseInstance,
+ SkTArray<GrMesh, true>* out);
+
int numInputPoints() const {
return RenderPassIsCubic(fRenderPass) ? 4 : 3;
}
@@ -270,4 +245,34 @@ inline void GrCCPRCoverageProcessor::CubicInstance::set(const SkPoint p[4], floa
(Y + dy).store(&fY);
}
+inline bool GrCCPRCoverageProcessor::RenderPassIsCubic(RenderPass pass) {
+ switch (pass) {
+ case RenderPass::kTriangleHulls:
+ case RenderPass::kTriangleEdges:
+ case RenderPass::kTriangleCorners:
+ case RenderPass::kQuadraticHulls:
+ case RenderPass::kQuadraticCorners:
+ return false;
+ case RenderPass::kCubicHulls:
+ case RenderPass::kCubicCorners:
+ return true;
+ }
+ SK_ABORT("Invalid GrCCPRCoverageProcessor::RenderPass");
+ return false;
+}
+
+inline const char* GrCCPRCoverageProcessor::RenderPassName(RenderPass pass) {
+ switch (pass) {
+ case RenderPass::kTriangleHulls: return "kTriangleHulls";
+ case RenderPass::kTriangleEdges: return "kTriangleEdges";
+ case RenderPass::kTriangleCorners: return "kTriangleCorners";
+ case RenderPass::kQuadraticHulls: return "kQuadraticHulls";
+ case RenderPass::kQuadraticCorners: return "kQuadraticCorners";
+ case RenderPass::kCubicHulls: return "kCubicHulls";
+ case RenderPass::kCubicCorners: return "kCubicCorners";
+ }
+ SK_ABORT("Invalid GrCCPRCoverageProcessor::RenderPass");
+ return "";
+}
+
#endif
diff --git a/src/gpu/ccpr/GrCCPRCoverageProcessor_GSImpl.cpp b/src/gpu/ccpr/GrCCPRCoverageProcessor_GSImpl.cpp
index 5c9ba3bfc2..60928b6afc 100644
--- a/src/gpu/ccpr/GrCCPRCoverageProcessor_GSImpl.cpp
+++ b/src/gpu/ccpr/GrCCPRCoverageProcessor_GSImpl.cpp
@@ -7,6 +7,7 @@
#include "GrCCPRCoverageProcessor.h"
+#include "GrMesh.h"
#include "glsl/GrGLSLVertexGeoBuilder.h"
using Shader = GrCCPRCoverageProcessor::Shader;
@@ -26,17 +27,16 @@ protected:
void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) final {
const GrCCPRCoverageProcessor& proc = args.fGP.cast<GrCCPRCoverageProcessor>();
- // Vertex shader.
- GrGLSLVertexBuilder* v = args.fVertBuilder;
- v->codeAppendf("float2 self = float2(%s[sk_VertexID], %s[sk_VertexID]);",
- proc.getInstanceAttrib(InstanceAttribs::kX).fName,
- proc.getInstanceAttrib(InstanceAttribs::kY).fName);
- gpArgs->fPositionVar.set(kFloat2_GrSLType, "self");
+ // The vertex shader simply forwards transposed x or y values to the geometry shader.
+ SkASSERT(1 == proc.numAttribs());
+ gpArgs->fPositionVar.set(4 == proc.numInputPoints() ? kFloat4_GrSLType : kFloat3_GrSLType,
+ proc.getAttrib(0).fName);
// Geometry shader.
GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
this->emitGeometryShader(proc, varyingHandler, args.fGeomBuilder, args.fRTAdjustName);
varyingHandler->emitAttributes(proc);
+ varyingHandler->setNoPerspective();
SkASSERT(!args.fFPCoordTransformHandler->nextCoordTransform());
// Fragment shader.
@@ -52,12 +52,9 @@ protected:
int numInputPoints = proc.numInputPoints();
SkASSERT(3 == numInputPoints || 4 == numInputPoints);
- g->codeAppendf("float%ix2 pts = float%ix2(", numInputPoints, numInputPoints);
- for (int i = 0; i < numInputPoints; ++i) {
- g->codeAppend (i ? ", " : "");
- g->codeAppendf("sk_in[%i].sk_Position.xy", i);
- }
- g->codeAppend (");");
+ const char* posValues = (4 == numInputPoints) ? "sk_Position" : "sk_Position.xyz";
+ g->codeAppendf("float%ix2 pts = transpose(float2x%i(sk_in[0].%s, sk_in[1].%s));",
+ numInputPoints, numInputPoints, posValues, posValues);
GrShaderVar wind("wind", kHalf_GrSLType);
g->declareGlobal(wind);
@@ -89,9 +86,8 @@ protected:
Shader::GeometryVars vars;
fShader->emitSetupCode(g, "pts", "sk_InvocationID", wind.c_str(), &vars);
int maxPoints = this->onEmitGeometryShader(g, wind, emitVertexFn.c_str(), vars);
- InputType inputType = (3 == numInputPoints) ? InputType::kTriangles
- : InputType::kLinesAdjacency;
- g->configure(inputType, OutputType::kTriangleStrip, maxPoints, fShader->getNumSegments());
+ g->configure(InputType::kLines, OutputType::kTriangleStrip, maxPoints,
+ fShader->getNumSegments());
}
virtual int onEmitGeometryShader(GrGLSLGeometryBuilder*, const GrShaderVar& wind,
@@ -255,6 +251,17 @@ public:
}
};
+void GrCCPRCoverageProcessor::initGS() {
+ if (RenderPassIsCubic(fRenderPass)) {
+ this->addVertexAttrib("x_or_y_values", kFloat4_GrVertexAttribType); // (See appendMesh.)
+ SkASSERT(sizeof(CubicInstance) == this->getVertexStride() * 2);
+ } else {
+ this->addVertexAttrib("x_or_y_values", kFloat3_GrVertexAttribType); // (See appendMesh.)
+ SkASSERT(sizeof(TriangleInstance) == this->getVertexStride() * 2);
+ }
+ this->setWillUseGeoShader();
+}
+
GrGLSLPrimitiveProcessor* GrCCPRCoverageProcessor::CreateGSImpl(std::unique_ptr<Shader> shader) {
switch (shader->getGeometryType()) {
case Shader::GeometryType::kHull:
@@ -267,3 +274,14 @@ GrGLSLPrimitiveProcessor* GrCCPRCoverageProcessor::CreateGSImpl(std::unique_ptr<
SK_ABORT("Unexpected Shader::GeometryType.");
return nullptr;
}
+
+void GrCCPRCoverageProcessor::appendGSMesh(GrBuffer* instanceBuffer, int instanceCount,
+ int baseInstance, SkTArray<GrMesh, true>* out) {
+ // 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.
+ GrMesh& mesh = out->emplace_back(GrPrimitiveType::kLines);
+ mesh.setNonIndexedNonInstanced(instanceCount * 2);
+ mesh.setVertexData(instanceBuffer, baseInstance * 2);
+}
diff --git a/src/gpu/glsl/GrGLSLGeometryProcessor.cpp b/src/gpu/glsl/GrGLSLGeometryProcessor.cpp
index ab27ffaa7b..9c71042413 100644
--- a/src/gpu/glsl/GrGLSLGeometryProcessor.cpp
+++ b/src/gpu/glsl/GrGLSLGeometryProcessor.cpp
@@ -16,27 +16,37 @@
void GrGLSLGeometryProcessor::emitCode(EmitArgs& args) {
GrGPArgs gpArgs;
this->onEmitCode(args, &gpArgs);
- SkASSERT(kFloat2_GrSLType == gpArgs.fPositionVar.getType() ||
- kFloat3_GrSLType == gpArgs.fPositionVar.getType());
GrGLSLVertexBuilder* vBuilder = args.fVertBuilder;
if (!args.fGP.willUseGeoShader()) {
// Emit the vertex position to the hardware in the normalized window coordinates it expects.
+ SkASSERT(kFloat2_GrSLType == gpArgs.fPositionVar.getType() ||
+ kFloat3_GrSLType == gpArgs.fPositionVar.getType());
vBuilder->emitNormalizedSkPosition(gpArgs.fPositionVar.c_str(), args.fRTAdjustName,
gpArgs.fPositionVar.getType());
+ if (kFloat2_GrSLType == gpArgs.fPositionVar.getType()) {
+ args.fVaryingHandler->setNoPerspective();
+ }
} else {
// Since we have a geometry shader, leave the vertex position in Skia device space for now.
// The geometry Shader will operate in device space, and then convert the final positions to
// normalized hardware window coordinates under the hood, once everything else has finished.
+ // The subclass must call setNoPerspective on the varying handler, if applicable.
vBuilder->codeAppendf("sk_Position = float4(%s", gpArgs.fPositionVar.c_str());
- if (kFloat2_GrSLType == gpArgs.fPositionVar.getType()) {
- vBuilder->codeAppend(", 0");
+ switch (gpArgs.fPositionVar.getType()) {
+ case kFloat_GrSLType:
+ vBuilder->codeAppend(", 0"); // fallthru.
+ case kFloat2_GrSLType:
+ vBuilder->codeAppend(", 0"); // fallthru.
+ case kFloat3_GrSLType:
+ vBuilder->codeAppend(", 1"); // fallthru.
+ case kFloat4_GrSLType:
+ vBuilder->codeAppend(");");
+ break;
+ default:
+ SK_ABORT("Invalid position var type");
+ break;
}
- vBuilder->codeAppend(", 1);");
- }
-
- if (kFloat2_GrSLType == gpArgs.fPositionVar.getType()) {
- args.fVaryingHandler->setNoPerspective();
}
}