From 92be2f74db81f0ed480b55c58cbde39270f9b772 Mon Sep 17 00:00:00 2001 From: Brian Salomon Date: Tue, 19 Jun 2018 14:33:47 -0400 Subject: Revert "Revert "Change how vertex/instance attributes are handled in geometry processors."" This reverts commit 5045e501d2aec23e5f1e4b46346033ac3202c6b0. TBR=csmartdalton@google.com Change-Id: Ifbf5f1d8f8ef340fdc69653e931b6d68d4bf0854 Reviewed-on: https://skia-review.googlesource.com/135862 Reviewed-by: Brian Salomon Commit-Queue: Brian Salomon --- gm/beziereffects.cpp | 17 +- gm/convexpolyeffect.cpp | 5 +- include/private/GrTypesPriv.h | 45 ----- src/gpu/GrDefaultGeoProcFactory.cpp | 45 +++-- src/gpu/GrGeometryProcessor.h | 37 ++++ src/gpu/GrGpuCommandBuffer.cpp | 8 +- src/gpu/GrPathProcessor.h | 12 ++ src/gpu/GrPrimitiveProcessor.cpp | 52 +++++ src/gpu/GrPrimitiveProcessor.h | 149 +++++++++----- src/gpu/ccpr/GrCCCoverageProcessor.h | 10 + src/gpu/ccpr/GrCCCoverageProcessor_GSImpl.cpp | 24 ++- src/gpu/ccpr/GrCCCoverageProcessor_VSImpl.cpp | 68 +++---- src/gpu/ccpr/GrCCPathProcessor.cpp | 36 ++-- src/gpu/ccpr/GrCCPathProcessor.h | 23 ++- src/gpu/effects/GrBezierEffect.cpp | 30 +-- src/gpu/effects/GrBezierEffect.h | 44 ++-- src/gpu/effects/GrBitmapTextGeoProc.cpp | 23 ++- src/gpu/effects/GrBitmapTextGeoProc.h | 16 +- src/gpu/effects/GrDistanceFieldGeoProc.cpp | 120 ++++++----- src/gpu/effects/GrDistanceFieldGeoProc.h | 52 +++-- src/gpu/effects/GrShadowGeoProc.cpp | 15 +- src/gpu/effects/GrShadowGeoProc.h | 17 +- src/gpu/gl/GrGLGpu.cpp | 40 ++-- src/gpu/gl/GrGLProgram.cpp | 6 +- src/gpu/gl/GrGLProgram.h | 27 ++- src/gpu/gl/GrGLVaryingHandler.cpp | 3 +- src/gpu/gl/builders/GrGLProgramBuilder.cpp | 38 ++-- src/gpu/gl/builders/GrGLProgramBuilder.h | 7 +- src/gpu/glsl/GrGLSLVarying.cpp | 18 +- src/gpu/glsl/GrGLSLVarying.h | 2 +- src/gpu/ops/GrAAConvexPathRenderer.cpp | 42 ++-- src/gpu/ops/GrAAFillRectOp.cpp | 19 +- src/gpu/ops/GrAAHairLinePathRenderer.cpp | 15 +- src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp | 10 +- src/gpu/ops/GrAAStrokeRectOp.cpp | 8 +- src/gpu/ops/GrAtlasTextOp.cpp | 4 +- src/gpu/ops/GrDashOp.cpp | 115 ++++++----- src/gpu/ops/GrDefaultPathRenderer.cpp | 2 +- src/gpu/ops/GrDrawAtlasOp.cpp | 6 +- src/gpu/ops/GrDrawVerticesOp.cpp | 6 +- src/gpu/ops/GrLatticeOp.cpp | 48 +++-- src/gpu/ops/GrNonAAFillRectOp.cpp | 23 +-- src/gpu/ops/GrNonAAStrokeRectOp.cpp | 6 +- src/gpu/ops/GrOvalOpFactory.cpp | 236 ++++++++++++---------- src/gpu/ops/GrRegionOp.cpp | 13 +- src/gpu/ops/GrShadowRRectOp.cpp | 7 +- src/gpu/ops/GrSmallPathRenderer.cpp | 17 +- src/gpu/ops/GrTessellatingPathRenderer.cpp | 18 +- src/gpu/ops/GrTextureOp.cpp | 112 +++++----- src/gpu/vk/GrVkPipeline.cpp | 80 +++++--- tests/GrMeshTest.cpp | 51 +++-- tests/GrPipelineDynamicStateTest.cpp | 22 +- tests/OnFlushCallbackTest.cpp | 9 +- tests/PrimitiveProcessorTest.cpp | 27 ++- 54 files changed, 1091 insertions(+), 794 deletions(-) diff --git a/gm/beziereffects.cpp b/gm/beziereffects.cpp index 1c26989df2..26da791746 100644 --- a/gm/beziereffects.cpp +++ b/gm/beziereffects.cpp @@ -93,14 +93,13 @@ private: void onPrepareDraws(Target* target) override { QuadHelper helper; - size_t vertexStride = this->gp()->getVertexStride(); - SkASSERT(vertexStride == sizeof(SkPoint)); - SkPoint* pts = reinterpret_cast(helper.init(target, vertexStride, 1)); + SkASSERT(this->gp()->debugOnly_vertexStride() == sizeof(SkPoint)); + SkPoint* pts = reinterpret_cast(helper.init(target, sizeof(SkPoint), 1)); if (!pts) { return; } SkRect rect = this->rect(); - SkPointPriv::SetRectTriStrip(pts, rect, vertexStride); + SkPointPriv::SetRectTriStrip(pts, rect, sizeof(SkPoint)); helper.recordDraw(target, this->gp(), this->makePipeline(target)); } @@ -285,9 +284,8 @@ private: void onPrepareDraws(Target* target) override { QuadHelper helper; - size_t vertexStride = this->gp()->getVertexStride(); - SkASSERT(vertexStride == sizeof(Vertex)); - Vertex* verts = reinterpret_cast(helper.init(target, vertexStride, 1)); + SkASSERT(this->gp()->debugOnly_vertexStride() == sizeof(Vertex)); + Vertex* verts = reinterpret_cast(helper.init(target, sizeof(Vertex), 1)); if (!verts) { return; } @@ -507,9 +505,8 @@ private: void onPrepareDraws(Target* target) override { QuadHelper helper; - size_t vertexStride = this->gp()->getVertexStride(); - SkASSERT(vertexStride == sizeof(Vertex)); - Vertex* verts = reinterpret_cast(helper.init(target, vertexStride, 1)); + SkASSERT(this->gp()->debugOnly_vertexStride() == sizeof(Vertex)); + Vertex* verts = reinterpret_cast(helper.init(target, sizeof(Vertex), 1)); if (!verts) { return; } diff --git a/gm/convexpolyeffect.cpp b/gm/convexpolyeffect.cpp index 18c5ebdcdc..496b6b173f 100644 --- a/gm/convexpolyeffect.cpp +++ b/gm/convexpolyeffect.cpp @@ -83,10 +83,9 @@ private: sk_sp gp(GrDefaultGeoProcFactory::Make( color, Coverage::kSolid_Type, LocalCoords::kUnused_Type, SkMatrix::I())); - size_t vertexStride = gp->getVertexStride(); - SkASSERT(vertexStride == sizeof(SkPoint)); + SkASSERT(gp->debugOnly_vertexStride() == sizeof(SkPoint)); QuadHelper helper; - SkPoint* verts = reinterpret_cast(helper.init(target, vertexStride, 1)); + SkPoint* verts = reinterpret_cast(helper.init(target, sizeof(SkPoint), 1)); if (!verts) { return; } diff --git a/include/private/GrTypesPriv.h b/include/private/GrTypesPriv.h index 5913a1e48c..e957f1f893 100644 --- a/include/private/GrTypesPriv.h +++ b/include/private/GrTypesPriv.h @@ -693,51 +693,6 @@ enum GrVertexAttribType { }; static const int kGrVertexAttribTypeCount = kLast_GrVertexAttribType + 1; -/** - * Returns the size of the attrib type in bytes. - */ -static inline size_t GrVertexAttribTypeSize(GrVertexAttribType type) { - switch (type) { - case kFloat_GrVertexAttribType: - return sizeof(float); - case kFloat2_GrVertexAttribType: - return 2 * sizeof(float); - case kFloat3_GrVertexAttribType: - return 3 * sizeof(float); - case kFloat4_GrVertexAttribType: - return 4 * sizeof(float); - case kHalf_GrVertexAttribType: - return sizeof(float); - case kHalf2_GrVertexAttribType: - return 2 * sizeof(float); - case kHalf3_GrVertexAttribType: - return 3 * sizeof(float); - case kHalf4_GrVertexAttribType: - return 4 * sizeof(float); - case kInt2_GrVertexAttribType: - return 2 * sizeof(int32_t); - case kInt3_GrVertexAttribType: - return 3 * sizeof(int32_t); - case kInt4_GrVertexAttribType: - return 4 * sizeof(int32_t); - case kUByte_norm_GrVertexAttribType: - return 1 * sizeof(char); - case kUByte4_norm_GrVertexAttribType: - return 4 * sizeof(char); - case kShort2_GrVertexAttribType: - return 2 * sizeof(int16_t); - case kUShort2_GrVertexAttribType: // fall through - case kUShort2_norm_GrVertexAttribType: - return 2 * sizeof(uint16_t); - case kInt_GrVertexAttribType: - return sizeof(int32_t); - case kUint_GrVertexAttribType: - return sizeof(uint32_t); - } - SK_ABORT("Unexpected attribute type"); - return 0; -} - /** * converts a GrVertexAttribType to a GrSLType */ diff --git a/src/gpu/GrDefaultGeoProcFactory.cpp b/src/gpu/GrDefaultGeoProcFactory.cpp index defb214eb0..e2bf87b277 100644 --- a/src/gpu/GrDefaultGeoProcFactory.cpp +++ b/src/gpu/GrDefaultGeoProcFactory.cpp @@ -45,17 +45,13 @@ public: const char* name() const override { return "DefaultGeometryProcessor"; } - const Attribute* inPosition() const { return fInPosition; } - const Attribute* inColor() const { return fInColor; } - const Attribute* inLocalCoords() const { return fInLocalCoords; } - const Attribute* inCoverage() const { return fInCoverage; } GrColor color() const { return fColor; } - bool hasVertexColor() const { return SkToBool(fInColor); } + bool hasVertexColor() const { return fInColor.isInitialized(); } const SkMatrix& viewMatrix() const { return fViewMatrix; } const SkMatrix& localMatrix() const { return fLocalMatrix; } bool localCoordsWillBeRead() const { return fLocalCoordsWillBeRead; } uint8_t coverage() const { return fCoverage; } - bool hasVertexCoverage() const { return SkToBool(fInCoverage); } + bool hasVertexCoverage() const { return fInCoverage.isInitialized(); } class GLSLProcessor : public GrGLSLGeometryProcessor { public: @@ -78,7 +74,7 @@ public: varyingHandler->addVarying("color", &varying); // There are several optional steps to process the color. Start with the attribute: - vertBuilder->codeAppendf("half4 color = %s;", gp.inColor()->name()); + vertBuilder->codeAppendf("half4 color = %s;", gp.fInColor.name()); // For SkColor, do a red/blue swap, possible color space conversion, and premul if (gp.fFlags & kColorAttributeIsSkColor_GPFlag) { @@ -107,16 +103,16 @@ public: this->writeOutputPosition(vertBuilder, uniformHandler, gpArgs, - gp.inPosition()->name(), + gp.fInPosition.name(), gp.viewMatrix(), &fViewMatrixUniform); - if (gp.inLocalCoords()) { + if (gp.fInLocalCoords.isInitialized()) { // emit transforms with explicit local coords this->emitTransforms(vertBuilder, varyingHandler, uniformHandler, - gp.inLocalCoords()->asShaderVar(), + gp.fInLocalCoords.asShaderVar(), gp.localMatrix(), args.fFPCoordTransformHandler); } else { @@ -124,7 +120,7 @@ public: this->emitTransforms(vertBuilder, varyingHandler, uniformHandler, - gp.inPosition()->asShaderVar(), + gp.fInPosition.asShaderVar(), gp.localMatrix(), args.fFPCoordTransformHandler); } @@ -132,7 +128,7 @@ public: // Setup coverage as pass through if (gp.hasVertexCoverage()) { fragBuilder->codeAppendf("half alpha = 1.0;"); - varyingHandler->addPassThroughAttribute(gp.inCoverage(), "alpha"); + varyingHandler->addPassThroughAttribute(gp.fInCoverage, "alpha"); fragBuilder->codeAppendf("%s = half4(alpha);", args.fOutputCoverage); } else if (gp.coverage() == 0xff) { fragBuilder->codeAppendf("%s = half4(1);", args.fOutputCoverage); @@ -222,22 +218,31 @@ private: , fFlags(gpTypeFlags) , fLocalCoordsWillBeRead(localCoordsWillBeRead) , fColorSpaceXform(std::move(colorSpaceXform)) { - fInPosition = &this->addVertexAttrib("inPosition", kFloat2_GrVertexAttribType); + fInPosition = {"inPosition", kFloat2_GrVertexAttribType}; + int cnt = 1; if (fFlags & kColorAttribute_GPFlag) { - fInColor = &this->addVertexAttrib("inColor", kUByte4_norm_GrVertexAttribType); + fInColor = {"inColor", kUByte4_norm_GrVertexAttribType}; + ++cnt; } if (fFlags & kLocalCoordAttribute_GPFlag) { - fInLocalCoords = &this->addVertexAttrib("inLocalCoord", kFloat2_GrVertexAttribType); + fInLocalCoords = {"inLocalCoord", kFloat2_GrVertexAttribType}; + ++cnt; } if (fFlags & kCoverageAttribute_GPFlag) { - fInCoverage = &this->addVertexAttrib("inCoverage", kHalf_GrVertexAttribType); + fInCoverage = {"inCoverage", kHalf_GrVertexAttribType}; + ++cnt; } + this->setVertexAttributeCnt(cnt); } - const Attribute* fInPosition = nullptr; - const Attribute* fInColor = nullptr; - const Attribute* fInLocalCoords = nullptr; - const Attribute* fInCoverage = nullptr; + const Attribute& onVertexAttribute(int i) const override { + return IthInitializedAttribute(i, fInPosition, fInColor, fInLocalCoords, fInCoverage); + } + + Attribute fInPosition; + Attribute fInColor; + Attribute fInLocalCoords; + Attribute fInCoverage; GrColor fColor; SkMatrix fViewMatrix; SkMatrix fLocalMatrix; diff --git a/src/gpu/GrGeometryProcessor.h b/src/gpu/GrGeometryProcessor.h index a12ab0058d..5035ad0f53 100644 --- a/src/gpu/GrGeometryProcessor.h +++ b/src/gpu/GrGeometryProcessor.h @@ -39,7 +39,44 @@ protected: fSampleShading = sampleShading; } + /** + * Recursive helpers for implementing onVertexAttribute or onInstanceAttribute. + */ + + template + static const Attribute& IthAttribute(int i, const Attribute& attr0, const Args&... attrs) { + SkASSERT(attr0.isInitialized()); + return (0 == i) ? attr0 : IthAttribute(i - 1, attrs...); + } + + static const Attribute& IthAttribute(int i) { + SK_ABORT("Illegal attribute Index"); + static constexpr Attribute kBogus; + return kBogus; + } + + template + static const Attribute& IthInitializedAttribute(int i, const Attribute& attr0, + const Args&... attrs) { + if (attr0.isInitialized()) { + if (0 == i) { + return attr0; + } + i -= 1; + } + return IthInitializedAttribute(i, attrs...); + } + + static const Attribute& IthInitializedAttribute(int i) { return IthAttribute(i); } + private: + // Since most subclasses don't use instancing provide a default implementation for that case. + const Attribute& onInstanceAttribute(int i) const override { + SK_ABORT("No instanced attributes"); + static constexpr Attribute kBogus; + return kBogus; + } + bool fWillUseGeoShader; float fSampleShading; diff --git a/src/gpu/GrGpuCommandBuffer.cpp b/src/gpu/GrGpuCommandBuffer.cpp index 13ae6c9844..fa2ce077b5 100644 --- a/src/gpu/GrGpuCommandBuffer.cpp +++ b/src/gpu/GrGpuCommandBuffer.cpp @@ -33,12 +33,12 @@ bool GrGpuRTCommandBuffer::draw(const GrPipeline& pipeline, int meshCount, const SkRect& bounds) { #ifdef SK_DEBUG - SkASSERT(!primProc.hasInstanceAttribs() || this->gpu()->caps()->instanceAttribSupport()); + SkASSERT(!primProc.hasInstanceAttributes() || this->gpu()->caps()->instanceAttribSupport()); for (int i = 0; i < meshCount; ++i) { SkASSERT(!GrPrimTypeRequiresGeometryShaderSupport(meshes[i].primitiveType()) || this->gpu()->caps()->shaderCaps()->geometryShaderSupport()); - SkASSERT(primProc.hasVertexAttribs() == meshes[i].hasVertexData()); - SkASSERT(primProc.hasInstanceAttribs() == meshes[i].isInstanced()); + SkASSERT(primProc.hasVertexAttributes() == meshes[i].hasVertexData()); + SkASSERT(primProc.hasInstanceAttributes() == meshes[i].isInstanced()); } #endif auto resourceProvider = this->gpu()->getContext()->contextPriv().resourceProvider(); @@ -47,7 +47,7 @@ bool GrGpuRTCommandBuffer::draw(const GrPipeline& pipeline, return false; } - if (primProc.numAttribs() > this->gpu()->caps()->maxVertexAttributes()) { + if (primProc.numVertexAttributes() > this->gpu()->caps()->maxVertexAttributes()) { this->gpu()->stats()->incNumFailedDraws(); return false; } diff --git a/src/gpu/GrPathProcessor.h b/src/gpu/GrPathProcessor.h index 72e5168a4f..6893e882dc 100644 --- a/src/gpu/GrPathProcessor.h +++ b/src/gpu/GrPathProcessor.h @@ -38,6 +38,18 @@ public: virtual bool isPathRendering() const override { return true; } private: + const Attribute& onVertexAttribute(int i) const final { + SK_ABORT("No vertex attributes"); + static constexpr Attribute kBogus; + return kBogus; + } + + const Attribute& onInstanceAttribute(int i) const final { + SK_ABORT("No instanced attributes"); + static constexpr Attribute kBogus; + return kBogus; + } + GrPathProcessor(GrColor, const SkMatrix& viewMatrix, const SkMatrix& localMatrix); GrColor fColor; diff --git a/src/gpu/GrPrimitiveProcessor.cpp b/src/gpu/GrPrimitiveProcessor.cpp index 7d1e1a644e..db79fb1052 100644 --- a/src/gpu/GrPrimitiveProcessor.cpp +++ b/src/gpu/GrPrimitiveProcessor.cpp @@ -17,6 +17,58 @@ enum MatrixType { kGeneral_MatrixType = 1, }; +GrPrimitiveProcessor::GrPrimitiveProcessor(ClassID classID) : GrResourceIOProcessor(classID) {} + +const GrPrimitiveProcessor::Attribute& GrPrimitiveProcessor::vertexAttribute(int i) const { + SkASSERT(i >= 0 && i < this->numVertexAttributes()); + const auto& result = this->onVertexAttribute(i); + SkASSERT(result.isInitialized()); + return result; +} + +const GrPrimitiveProcessor::Attribute& GrPrimitiveProcessor::instanceAttribute(int i) const { + SkASSERT(i >= 0 && i < this->numInstanceAttributes()); + const auto& result = this->onInstanceAttribute(i); + SkASSERT(result.isInitialized()); + return result; +} + +#ifdef SK_DEBUG +size_t GrPrimitiveProcessor::debugOnly_vertexStride() const { + size_t stride = 0; + for (int i = 0; i < fVertexAttributeCnt; ++i) { + stride += this->vertexAttribute(i).sizeAlign4(); + } + return stride; +} + +size_t GrPrimitiveProcessor::debugOnly_instanceStride() const { + size_t stride = 0; + for (int i = 0; i < fInstanceAttributeCnt; ++i) { + stride += this->instanceAttribute(i).sizeAlign4(); + } + return stride; +} + +size_t GrPrimitiveProcessor::debugOnly_vertexAttributeOffset(int i) const { + SkASSERT(i >= 0 && i < fVertexAttributeCnt); + size_t offset = 0; + for (int j = 0; j < i; ++j) { + offset += this->vertexAttribute(j).sizeAlign4(); + } + return offset; +} + +size_t GrPrimitiveProcessor::debugOnly_instanceAttributeOffset(int i) const { + SkASSERT(i >= 0 && i < fInstanceAttributeCnt); + size_t offset = 0; + for (int j = 0; j < i; ++j) { + offset += this->instanceAttribute(j).sizeAlign4(); + } + return offset; +} +#endif + uint32_t GrPrimitiveProcessor::getTransformKey(const SkTArray& coords, int numCoords) const { diff --git a/src/gpu/GrPrimitiveProcessor.h b/src/gpu/GrPrimitiveProcessor.h index c75f13c496..6563ad9a7d 100644 --- a/src/gpu/GrPrimitiveProcessor.h +++ b/src/gpu/GrPrimitiveProcessor.h @@ -40,23 +40,22 @@ class GrGLSLPrimitiveProcessor; */ class GrPrimitiveProcessor : public GrResourceIOProcessor, public GrProgramElement { public: + /** Describes a vertex or instance attribute. */ class Attribute { public: - enum class InputRate : bool { - kPerVertex, - kPerInstance - }; - constexpr Attribute() = default; - constexpr Attribute(const char* name, GrVertexAttribType type, int offset, InputRate rate) - : fName(name), fType(type), fOffsetInRecord(offset), fInputRate(rate) {} + constexpr Attribute(const char* name, GrVertexAttribType type) : fName(name), fType(type) {} + constexpr Attribute(const Attribute&) = default; + + Attribute& operator=(const Attribute&) = default; + + constexpr bool isInitialized() const { return SkToBool(fName); } - bool isInitialized() const { return SkToBool(fName); } + constexpr const char* name() const { return fName; } + constexpr GrVertexAttribType type() const { return fType; } - const char* name() const { return fName; } - GrVertexAttribType type() const { return fType; } - int offsetInRecord() const { return fOffsetInRecord; } - InputRate inputRate() const { return fInputRate; } + inline constexpr size_t size() const; + constexpr size_t sizeAlign4() const { return SkAlign4(this->size()); } GrShaderVar asShaderVar() const { return {fName, GrVertexAttribTypeToSLType(fType), GrShaderVar::kIn_TypeModifier}; @@ -65,35 +64,34 @@ public: private: const char* fName = nullptr; GrVertexAttribType fType = kFloat_GrVertexAttribType; - int fOffsetInRecord = 0; - InputRate fInputRate = InputRate::kPerVertex; }; - GrPrimitiveProcessor(ClassID classID) - : GrResourceIOProcessor(classID) {} + GrPrimitiveProcessor(ClassID); - int numAttribs() const { return fAttribs.count(); } - const Attribute& getAttrib(int index) const { return fAttribs[index]; } + int numVertexAttributes() const { return fVertexAttributeCnt; } + const Attribute& vertexAttribute(int i) const; + int numInstanceAttributes() const { return fInstanceAttributeCnt; } + const Attribute& instanceAttribute(int i) const; - bool hasVertexAttribs() const { return SkToBool(fVertexStride); } - bool hasInstanceAttribs() const { return SkToBool(fInstanceStride); } + bool hasVertexAttributes() const { return SkToBool(fVertexAttributeCnt); } + bool hasInstanceAttributes() const { return SkToBool(fInstanceAttributeCnt); } +#ifdef SK_DEBUG /** - * These return the strides of the vertex and instance buffers. Attributes are expected to be - * laid out interleaved in their corresponding buffer (vertex or instance). fOffsetInRecord - * indicates an attribute's location in bytes relative to the first attribute. (These are padded - * to the nearest 4 bytes for performance reasons.) - * - * A common practice is to populate the buffer's memory using an implicit array of structs. In - * this case, it is best to assert: - * - * stride == sizeof(struct) and - * offsetof(struct, field[i]) == attrib[i].fOffsetInRecord - * - * NOTE: for instanced draws the vertex buffer has a single record that each instance reuses. + * A common practice is to populate the the vertex/instance's memory using an implicit array of + * structs. In this case, it is best to assert that: + * debugOnly_stride == sizeof(struct) and + * offsetof(struct, field[i]) == debugOnly_AttributeOffset(i) + * In general having Op subclasses assert that attribute offsets and strides agree with their + * tessellation code's expectations is good practice. + * However, these functions walk the attributes to compute offsets and call virtual functions + * to access the attributes. Thus, they are only available in debug builds. */ - int getVertexStride() const { return fVertexStride; } - int getInstanceStride() const { return fInstanceStride; } + size_t debugOnly_vertexStride() const; + size_t debugOnly_instanceStride() const; + size_t debugOnly_vertexAttributeOffset(int) const; + size_t debugOnly_instanceAttributeOffset(int) const; +#endif // Only the GrGeometryProcessor subclass actually has a geo shader or vertex attributes, but // we put these calls on the base class to prevent having to cast @@ -129,24 +127,11 @@ public: */ virtual const char* getDestColorOverride() const { return nullptr; } - virtual float getSampleShading() const { - return 0.0; - } + virtual float getSampleShading() const { return 0.0; } protected: - /** - * Subclasses call these from their constructor to register vertex and instance attributes. - */ - const Attribute& addVertexAttrib(const char* name, GrVertexAttribType type) { - fAttribs.push_back() = {name, type, fVertexStride, Attribute::InputRate::kPerVertex}; - fVertexStride += static_cast(SkAlign4(GrVertexAttribTypeSize(type))); - return fAttribs.back(); - } - const Attribute& addInstanceAttrib(const char* name, GrVertexAttribType type) { - fAttribs.push_back() = {name, type, fInstanceStride, Attribute::InputRate::kPerInstance}; - fInstanceStride += static_cast(SkAlign4(GrVertexAttribTypeSize(type))); - return fAttribs.back(); - } + void setVertexAttributeCnt(int cnt) { fVertexAttributeCnt = cnt; } + void setInstanceAttributeCnt(int cnt) { fInstanceAttributeCnt = cnt; } private: void addPendingIOs() const override { GrResourceIOProcessor::addPendingIOs(); } @@ -154,11 +139,69 @@ private: void pendingIOComplete() const override { GrResourceIOProcessor::pendingIOComplete(); } void notifyRefCntIsZero() const final {} - SkSTArray<8, Attribute> fAttribs; - int fVertexStride = 0; - int fInstanceStride = 0; + virtual const Attribute& onVertexAttribute(int) const = 0; + virtual const Attribute& onInstanceAttribute(int) const = 0; + int fVertexAttributeCnt = 0; + int fInstanceAttributeCnt = 0; typedef GrProcessor INHERITED; }; +////////////////////////////////////////////////////////////////////////////// + +/** + * Returns the size of the attrib type in bytes. + * This was moved from include/private/GrTypesPriv.h in service of Skia dependents that build + * with C++11. + */ +static constexpr inline size_t GrVertexAttribTypeSize(GrVertexAttribType type) { + switch (type) { + case kFloat_GrVertexAttribType: + return sizeof(float); + case kFloat2_GrVertexAttribType: + return 2 * sizeof(float); + case kFloat3_GrVertexAttribType: + return 3 * sizeof(float); + case kFloat4_GrVertexAttribType: + return 4 * sizeof(float); + case kHalf_GrVertexAttribType: + return sizeof(float); + case kHalf2_GrVertexAttribType: + return 2 * sizeof(float); + case kHalf3_GrVertexAttribType: + return 3 * sizeof(float); + case kHalf4_GrVertexAttribType: + return 4 * sizeof(float); + case kInt2_GrVertexAttribType: + return 2 * sizeof(int32_t); + case kInt3_GrVertexAttribType: + return 3 * sizeof(int32_t); + case kInt4_GrVertexAttribType: + return 4 * sizeof(int32_t); + case kUByte_norm_GrVertexAttribType: + return 1 * sizeof(char); + case kUByte4_norm_GrVertexAttribType: + return 4 * sizeof(char); + case kShort2_GrVertexAttribType: + return 2 * sizeof(int16_t); + case kUShort2_GrVertexAttribType: // fall through + case kUShort2_norm_GrVertexAttribType: + return 2 * sizeof(uint16_t); + case kInt_GrVertexAttribType: + return sizeof(int32_t); + case kUint_GrVertexAttribType: + return sizeof(uint32_t); + } + // GCC fails because SK_ABORT evaluates to non constexpr. clang and cl.exe think this is + // unreachable and don't complain. +#if defined(__clang__) || !defined(__GNUC__) + SK_ABORT("Unsupported type conversion"); +#endif + return 0; +} + +constexpr size_t GrPrimitiveProcessor::Attribute::size() const { + return GrVertexAttribTypeSize(fType); +} + #endif diff --git a/src/gpu/ccpr/GrCCCoverageProcessor.h b/src/gpu/ccpr/GrCCCoverageProcessor.h index e3ea34f8dd..89890486d3 100644 --- a/src/gpu/ccpr/GrCCCoverageProcessor.h +++ b/src/gpu/ccpr/GrCCCoverageProcessor.h @@ -246,6 +246,13 @@ private: void initGS(); void initVS(GrResourceProvider*); + const Attribute& onVertexAttribute(int i) const override { return fVertexAttribute; } + + const Attribute& onInstanceAttribute(int i) const override { + SkASSERT(fImpl == Impl::kVertexShader); + return fInstanceAttributes[i]; + } + void appendGSMesh(GrBuffer* instanceBuffer, int instanceCount, int baseInstance, SkTArray* out) const; void appendVSMesh(GrBuffer* instanceBuffer, int instanceCount, int baseInstance, @@ -253,6 +260,8 @@ private: GrGLSLPrimitiveProcessor* createGSImpl(std::unique_ptr) const; GrGLSLPrimitiveProcessor* createVSImpl(std::unique_ptr) const; + // The type and meaning of this attribute depends on whether we're using VSImpl or GSImpl. + Attribute fVertexAttribute; const PrimitiveType fPrimitiveType; const Impl fImpl; @@ -262,6 +271,7 @@ private: const GSSubpass fGSSubpass = GSSubpass::kHulls; // Used by VSImpl. + Attribute fInstanceAttributes[2]; sk_sp fVSVertexBuffer; sk_sp fVSIndexBuffer; int fVSNumIndicesPerInstance; diff --git a/src/gpu/ccpr/GrCCCoverageProcessor_GSImpl.cpp b/src/gpu/ccpr/GrCCCoverageProcessor_GSImpl.cpp index aa7a8db8a5..8134fbe89b 100644 --- a/src/gpu/ccpr/GrCCCoverageProcessor_GSImpl.cpp +++ b/src/gpu/ccpr/GrCCCoverageProcessor_GSImpl.cpp @@ -31,9 +31,8 @@ protected: const GrCCCoverageProcessor& proc = args.fGP.cast(); // The vertex shader simply forwards transposed x or y values to the geometry shader. - SkASSERT(1 == proc.numAttribs()); - gpArgs->fPositionVar.set(GrVertexAttribTypeToSLType(proc.getAttrib(0).type()), - proc.getAttrib(0).name()); + SkASSERT(1 == proc.numVertexAttributes()); + gpArgs->fPositionVar = proc.fVertexAttribute.asShaderVar(); // Geometry shader. GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler; @@ -62,7 +61,7 @@ protected: Shader::CalcWind(proc, g, "pts", wind.c_str()); if (PrimitiveType::kWeightedTriangles == proc.fPrimitiveType) { SkASSERT(3 == numInputPoints); - SkASSERT(kFloat4_GrVertexAttribType == proc.getAttrib(0).type()); + SkASSERT(kFloat4_GrVertexAttribType == proc.fVertexAttribute.type()); g->codeAppendf("%s *= sk_in[0].sk_Position.w;", wind.c_str()); } @@ -382,14 +381,19 @@ public: void GrCCCoverageProcessor::initGS() { SkASSERT(Impl::kGeometryShader == fImpl); if (4 == this->numInputPoints() || this->hasInputWeight()) { - this->addVertexAttrib("x_or_y_values", kFloat4_GrVertexAttribType); - SkASSERT(sizeof(QuadPointInstance) == this->getVertexStride() * 2); - SkASSERT(offsetof(QuadPointInstance, fY) == this->getVertexStride()); + fVertexAttribute = {"x_or_y_values", kFloat4_GrVertexAttribType}; + GR_STATIC_ASSERT(sizeof(QuadPointInstance) == + 2 * GrVertexAttribTypeSize(kFloat4_GrVertexAttribType)); + GR_STATIC_ASSERT(offsetof(QuadPointInstance, fY) == + GrVertexAttribTypeSize(kFloat4_GrVertexAttribType)); } else { - this->addVertexAttrib("x_or_y_values", kFloat3_GrVertexAttribType); - SkASSERT(sizeof(TriPointInstance) == this->getVertexStride() * 2); - SkASSERT(offsetof(TriPointInstance, fY) == this->getVertexStride()); + fVertexAttribute = {"x_or_y_values", kFloat3_GrVertexAttribType}; + GR_STATIC_ASSERT(sizeof(TriPointInstance) == + 2 * GrVertexAttribTypeSize(kFloat3_GrVertexAttribType)); + GR_STATIC_ASSERT(offsetof(TriPointInstance, fY) == + GrVertexAttribTypeSize(kFloat3_GrVertexAttribType)); } + this->setVertexAttributeCnt(1); this->setWillUseGeoShader(); } diff --git a/src/gpu/ccpr/GrCCCoverageProcessor_VSImpl.cpp b/src/gpu/ccpr/GrCCCoverageProcessor_VSImpl.cpp index 3c9fe89fbc..5c5120cf45 100644 --- a/src/gpu/ccpr/GrCCCoverageProcessor_VSImpl.cpp +++ b/src/gpu/ccpr/GrCCCoverageProcessor_VSImpl.cpp @@ -28,9 +28,8 @@ private: const int fNumSides; }; -static constexpr int kAttribIdx_X = 0; // Transposed X values of all input points. -static constexpr int kAttribIdx_Y = 1; // Transposed Y values of all input points. -static constexpr int kAttribIdx_VertexData = 2; +static constexpr int kInstanceAttribIdx_X = 0; // Transposed X values of all input points. +static constexpr int kInstanceAttribIdx_Y = 1; // Transposed Y values of all input points. // Vertex data tells the shader how to offset vertices for conservative raster, as well as how to // calculate coverage values for corners and edges. @@ -260,15 +259,16 @@ void GrCCCoverageProcessor::VSImpl::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) int inputWidth = (4 == numInputPoints || proc.hasInputWeight()) ? 4 : 3; const char* swizzle = (4 == inputWidth) ? "xyzw" : "xyz"; v->codeAppendf("float%ix2 pts = transpose(float2x%i(%s.%s, %s.%s));", inputWidth, inputWidth, - proc.getAttrib(kAttribIdx_X).name(), swizzle, - proc.getAttrib(kAttribIdx_Y).name(), swizzle); + proc.fInstanceAttributes[kInstanceAttribIdx_X].name(), swizzle, + proc.fInstanceAttributes[kInstanceAttribIdx_Y].name(), swizzle); v->codeAppend ("half wind;"); Shader::CalcWind(proc, v, "pts", "wind"); if (PrimitiveType::kWeightedTriangles == proc.fPrimitiveType) { SkASSERT(3 == numInputPoints); - SkASSERT(kFloat4_GrVertexAttribType == proc.getAttrib(kAttribIdx_X).type()); - v->codeAppendf("wind *= %s.w;", proc.getAttrib(kAttribIdx_X).name()); + SkASSERT(kFloat4_GrVertexAttribType == + proc.fInstanceAttributes[kInstanceAttribIdx_X].type()); + v->codeAppendf("wind *= %s.w;", proc.fInstanceAttributes[kInstanceAttribIdx_X].name()); } float bloat = kAABloatRadius; @@ -284,12 +284,12 @@ void GrCCCoverageProcessor::VSImpl::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) // 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).name(), + proc.fVertexAttribute.name(), ((fNumSides - 1) << kVertexData_LeftNeighborIdShift) | ((fNumSides - 1) << kVertexData_RightNeighborIdShift) | (((1 << kVertexData_RightNeighborIdShift) - 1) ^ 3) | (fNumSides - 1), - proc.getAttrib(kAttribIdx_VertexData).name()); + proc.fVertexAttribute.name()); // 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 @@ -322,7 +322,7 @@ void GrCCCoverageProcessor::VSImpl::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) v->codeAppend ("rightdir = (float2(0) != rightdir) ? normalize(rightdir) : float2(1, 0);"); v->codeAppendf("if (0 != (%s & %i)) {", // Are we a corner? - proc.getAttrib(kAttribIdx_VertexData).name(), kVertexData_IsCornerBit); + proc.fVertexAttribute.name(), kVertexData_IsCornerBit); // In corner boxes, all 4 coverage values will not map linearly. // Therefore it is important to align the box so its diagonal shared @@ -341,7 +341,7 @@ void GrCCCoverageProcessor::VSImpl::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) // continue rotating 90 degrees clockwise until we reach the desired raster vertex for this // invocation. Corners with less than 3 corresponding raster vertices will result in // redundant vertices and degenerate triangles. - v->codeAppendf("int bloatidx = (%s >> %i) & 3;", proc.getAttrib(kAttribIdx_VertexData).name(), + v->codeAppendf("int bloatidx = (%s >> %i) & 3;", proc.fVertexAttribute.name(), kVertexData_BloatIdxShift); v->codeAppend ("switch (bloatidx) {"); v->codeAppend ( "case 3:"); @@ -376,12 +376,12 @@ void GrCCCoverageProcessor::VSImpl::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) v->codeAppend ("}"); v->codeAppendf("if (0 != (%s & %i)) {", // Are we an edge? - proc.getAttrib(kAttribIdx_VertexData).name(), kVertexData_IsEdgeBit); + proc.fVertexAttribute.name(), kVertexData_IsEdgeBit); v->codeAppend ( "coverage = left_coverage;"); v->codeAppend ("}"); v->codeAppendf("if (0 != (%s & %i)) {", // Invert coverage? - proc.getAttrib(kAttribIdx_VertexData).name(), + proc.fVertexAttribute.name(), kVertexData_InvertNegativeCoverageBit); v->codeAppend ( "coverage = -1 - coverage;"); v->codeAppend ("}"); @@ -391,7 +391,7 @@ void GrCCCoverageProcessor::VSImpl::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) v->codeAppend ("half2 corner_coverage = half2(0);"); v->codeAppendf("if (0 != (%s & %i)) {", // Are we a corner? - proc.getAttrib(kAttribIdx_VertexData).name(), kVertexData_IsCornerBit); + proc.fVertexAttribute.name(), kVertexData_IsCornerBit); // We use coverage=-1 to erase what the hull geometry wrote. // // In the context of curves, this effectively means "wind = -wind" and @@ -495,31 +495,27 @@ void GrCCCoverageProcessor::initVS(GrResourceProvider* rp) { } } + GrVertexAttribType xyAttribType; if (4 == this->numInputPoints() || this->hasInputWeight()) { - SkASSERT(kAttribIdx_X == this->numAttribs()); - this->addInstanceAttrib("X", kFloat4_GrVertexAttribType); - - SkASSERT(kAttribIdx_Y == this->numAttribs()); - this->addInstanceAttrib("Y", kFloat4_GrVertexAttribType); - - SkASSERT(offsetof(QuadPointInstance, fX) == this->getAttrib(kAttribIdx_X).offsetInRecord()); - SkASSERT(offsetof(QuadPointInstance, fY) == this->getAttrib(kAttribIdx_Y).offsetInRecord()); - SkASSERT(sizeof(QuadPointInstance) == this->getInstanceStride()); + GR_STATIC_ASSERT(offsetof(QuadPointInstance, fX) == 0); + GR_STATIC_ASSERT(sizeof(QuadPointInstance::fX) == + GrVertexAttribTypeSize(kFloat4_GrVertexAttribType)); + GR_STATIC_ASSERT(sizeof(QuadPointInstance::fY) == + GrVertexAttribTypeSize(kFloat4_GrVertexAttribType)); + xyAttribType = kFloat4_GrVertexAttribType; } else { - SkASSERT(kAttribIdx_X == this->numAttribs()); - this->addInstanceAttrib("X", kFloat3_GrVertexAttribType); - - SkASSERT(kAttribIdx_Y == this->numAttribs()); - this->addInstanceAttrib("Y", kFloat3_GrVertexAttribType); - - SkASSERT(offsetof(TriPointInstance, fX) == this->getAttrib(kAttribIdx_X).offsetInRecord()); - SkASSERT(offsetof(TriPointInstance, fY) == this->getAttrib(kAttribIdx_Y).offsetInRecord()); - SkASSERT(sizeof(TriPointInstance) == this->getInstanceStride()); + GR_STATIC_ASSERT(offsetof(TriPointInstance, fX) == 0); + GR_STATIC_ASSERT(sizeof(TriPointInstance::fX) == + GrVertexAttribTypeSize(kFloat3_GrVertexAttribType)); + GR_STATIC_ASSERT(sizeof(TriPointInstance::fY) == + GrVertexAttribTypeSize(kFloat3_GrVertexAttribType)); + xyAttribType = kFloat3_GrVertexAttribType; } - - SkASSERT(kAttribIdx_VertexData == this->numAttribs()); - this->addVertexAttrib("vertexdata", kInt_GrVertexAttribType); - SkASSERT(sizeof(int32_t) == this->getVertexStride()); + fInstanceAttributes[kInstanceAttribIdx_X] = {"X", xyAttribType}; + fInstanceAttributes[kInstanceAttribIdx_Y] = {"Y", xyAttribType}; + this->setInstanceAttributeCnt(2); + fVertexAttribute = {"vertexdata", kInt_GrVertexAttribType}; + this->setVertexAttributeCnt(1); if (caps.usePrimitiveRestart()) { fVSTriangleType = GrPrimitiveType::kTriangleStrip; diff --git a/src/gpu/ccpr/GrCCPathProcessor.cpp b/src/gpu/ccpr/GrCCPathProcessor.cpp index b8ebb44059..e180724f8a 100644 --- a/src/gpu/ccpr/GrCCPathProcessor.cpp +++ b/src/gpu/ccpr/GrCCPathProcessor.cpp @@ -65,6 +65,9 @@ static constexpr uint16_t kOctoIndicesAsTris[] = { GR_DECLARE_STATIC_UNIQUE_KEY(gIndexBufferKey); +constexpr GrPrimitiveProcessor::Attribute GrCCPathProcessor::kInstanceAttribs[]; +constexpr GrPrimitiveProcessor::Attribute GrCCPathProcessor::kEdgeNormsAttrib; + sk_sp GrCCPathProcessor::FindIndexBuffer(GrOnFlushResourceProvider* onFlushRP) { GR_DEFINE_STATIC_UNIQUE_KEY(gIndexBufferKey); if (onFlushRP->caps()->usePrimitiveRestart()) { @@ -82,24 +85,19 @@ GrCCPathProcessor::GrCCPathProcessor(GrResourceProvider* resourceProvider, : INHERITED(kGrCCPathProcessor_ClassID) , fAtlasAccess(std::move(atlas), GrSamplerState::Filter::kNearest, GrSamplerState::WrapMode::kClamp, kFragment_GrShaderFlag) { - this->addInstanceAttrib("devbounds", kFloat4_GrVertexAttribType); - this->addInstanceAttrib("devbounds45", kFloat4_GrVertexAttribType); - this->addInstanceAttrib("dev_to_atlas_offset", kInt2_GrVertexAttribType); - this->addInstanceAttrib("color", kUByte4_norm_GrVertexAttribType); - - SkASSERT(offsetof(Instance, fDevBounds) == - this->getInstanceAttrib(InstanceAttribs::kDevBounds).offsetInRecord()); - SkASSERT(offsetof(Instance, fDevBounds45) == - this->getInstanceAttrib(InstanceAttribs::kDevBounds45).offsetInRecord()); - SkASSERT(offsetof(Instance, fDevToAtlasOffset) == - this->getInstanceAttrib(InstanceAttribs::kDevToAtlasOffset).offsetInRecord()); - SkASSERT(offsetof(Instance, fColor) == - this->getInstanceAttrib(InstanceAttribs::kColor).offsetInRecord()); - SkASSERT(sizeof(Instance) == this->getInstanceStride()); - - GR_STATIC_ASSERT(4 == kNumInstanceAttribs); - - this->addVertexAttrib("edge_norms", kFloat4_GrVertexAttribType); + this->setInstanceAttributeCnt(kNumInstanceAttribs); + // Check that instance attributes exactly match Instance struct layout. + SkASSERT(!strcmp(this->instanceAttribute(0).name(), "devbounds")); + SkASSERT(!strcmp(this->instanceAttribute(1).name(), "devbounds45")); + SkASSERT(!strcmp(this->instanceAttribute(2).name(), "dev_to_atlas_offset")); + SkASSERT(!strcmp(this->instanceAttribute(3).name(), "color")); + SkASSERT(this->debugOnly_instanceAttributeOffset(0) == offsetof(Instance, fDevBounds)); + SkASSERT(this->debugOnly_instanceAttributeOffset(1) == offsetof(Instance, fDevBounds45)); + SkASSERT(this->debugOnly_instanceAttributeOffset(2) == offsetof(Instance, fDevToAtlasOffset)); + SkASSERT(this->debugOnly_instanceAttributeOffset(3) == offsetof(Instance, fColor)); + SkASSERT(this->debugOnly_instanceStride() == sizeof(Instance)); + + this->setVertexAttributeCnt(1); fAtlasAccess.instantiate(resourceProvider); this->addTextureSampler(&fAtlasAccess); @@ -170,7 +168,7 @@ void GLSLPathProcessor::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) { GrGLSLVarying texcoord(kFloat3_GrSLType); GrGLSLVarying color(kHalf4_GrSLType); varyingHandler->addVarying("texcoord", &texcoord); - varyingHandler->addPassThroughAttribute(&proc.getInstanceAttrib(InstanceAttribs::kColor), + varyingHandler->addPassThroughAttribute(proc.getInstanceAttrib(InstanceAttribs::kColor), args.fOutputColor, Interpolation::kCanBeFlat); // The vertex shader bloats and intersects the devBounds and devBounds45 rectangles, in order to diff --git a/src/gpu/ccpr/GrCCPathProcessor.h b/src/gpu/ccpr/GrCCPathProcessor.h index 785dd2c919..54c1b7e2ed 100644 --- a/src/gpu/ccpr/GrCCPathProcessor.h +++ b/src/gpu/ccpr/GrCCPathProcessor.h @@ -77,16 +77,11 @@ public: const GrTexture* atlas() const { return fAtlasAccess.peekTexture(); } const SkMatrix& localMatrix() const { return fLocalMatrix; } const Attribute& getInstanceAttrib(InstanceAttribs attribID) const { - const Attribute& attrib = this->getAttrib((int)attribID); - SkASSERT(Attribute::InputRate::kPerInstance == attrib.inputRate()); - return attrib; - } - const Attribute& getEdgeNormsAttrib() const { - SkASSERT(1 + kNumInstanceAttribs == this->numAttribs()); - const Attribute& attrib = this->getAttrib(kNumInstanceAttribs); - SkASSERT(Attribute::InputRate::kPerVertex == attrib.inputRate()); - return attrib; + int idx = static_cast(attribID); + SkASSERT(idx >= 0 && idx < static_cast(SK_ARRAY_COUNT(kInstanceAttribs))); + return kInstanceAttribs[idx]; } + const Attribute& getEdgeNormsAttrib() const { return kEdgeNormsAttrib; } void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {} GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override; @@ -95,8 +90,18 @@ public: int baseInstance, int endInstance, const SkRect& bounds) const; private: + const Attribute& onVertexAttribute(int i) const override { return kEdgeNormsAttrib; } + const Attribute& onInstanceAttribute(int i) const override { return kInstanceAttribs[i]; } + const TextureSampler fAtlasAccess; SkMatrix fLocalMatrix; + static constexpr Attribute kInstanceAttribs[kNumInstanceAttribs] = { + {"devbounds", kFloat4_GrVertexAttribType}, + {"devbounds45", kFloat4_GrVertexAttribType}, + {"dev_to_atlas_offset", kInt2_GrVertexAttribType}, + {"color", kUByte4_norm_GrVertexAttribType} + }; + static constexpr Attribute kEdgeNormsAttrib = {"edge_norms", kFloat4_GrVertexAttribType}; typedef GrGeometryProcessor INHERITED; }; diff --git a/src/gpu/effects/GrBezierEffect.cpp b/src/gpu/effects/GrBezierEffect.cpp index 3dee2f4dab..d68b1bfed6 100644 --- a/src/gpu/effects/GrBezierEffect.cpp +++ b/src/gpu/effects/GrBezierEffect.cpp @@ -79,7 +79,7 @@ void GrGLConicEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) { GrGLSLVarying v(kFloat4_GrSLType); varyingHandler->addVarying("ConicCoeffs", &v); - vertBuilder->codeAppendf("%s = %s;", v.vsOut(), gp.inConicCoeffs()->name()); + vertBuilder->codeAppendf("%s = %s;", v.vsOut(), gp.inConicCoeffs().name()); GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; // Setup pass through color @@ -89,7 +89,7 @@ void GrGLConicEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) { this->writeOutputPosition(vertBuilder, uniformHandler, gpArgs, - gp.inPosition()->name(), + gp.inPosition().name(), gp.viewMatrix(), &fViewMatrixUniform); @@ -97,7 +97,7 @@ void GrGLConicEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) { this->emitTransforms(vertBuilder, varyingHandler, uniformHandler, - gp.inPosition()->asShaderVar(), + gp.inPosition().asShaderVar(), gp.localMatrix(), args.fFPCoordTransformHandler); @@ -219,6 +219,8 @@ void GrGLConicEffect::GenKey(const GrGeometryProcessor& gp, ////////////////////////////////////////////////////////////////////////////// +constexpr GrPrimitiveProcessor::Attribute GrConicEffect::kAttributes[]; + GrConicEffect::~GrConicEffect() {} void GrConicEffect::getGLSLProcessorKey(const GrShaderCaps& caps, @@ -240,8 +242,7 @@ GrConicEffect::GrConicEffect(GrColor color, const SkMatrix& viewMatrix, uint8_t , fUsesLocalCoords(usesLocalCoords) , fCoverageScale(coverage) , fEdgeType(edgeType) { - fInPosition = &this->addVertexAttrib("inPosition", kFloat2_GrVertexAttribType); - fInConicCoeffs = &this->addVertexAttrib("inConicCoeffs", kHalf4_GrVertexAttribType); + this->setVertexAttributeCnt(2); } ////////////////////////////////////////////////////////////////////////////// @@ -331,7 +332,7 @@ void GrGLQuadEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) { GrGLSLVarying v(kHalf4_GrSLType); varyingHandler->addVarying("HairQuadEdge", &v); - vertBuilder->codeAppendf("%s = %s;", v.vsOut(), gp.inHairQuadEdge()->name()); + vertBuilder->codeAppendf("%s = %s;", v.vsOut(), gp.inHairQuadEdge().name()); GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; // Setup pass through color @@ -341,7 +342,7 @@ void GrGLQuadEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) { this->writeOutputPosition(vertBuilder, uniformHandler, gpArgs, - gp.inPosition()->name(), + gp.inPosition().name(), gp.viewMatrix(), &fViewMatrixUniform); @@ -349,7 +350,7 @@ void GrGLQuadEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) { this->emitTransforms(vertBuilder, varyingHandler, uniformHandler, - gp.inPosition()->asShaderVar(), + gp.inPosition().asShaderVar(), gp.localMatrix(), args.fFPCoordTransformHandler); @@ -420,6 +421,8 @@ void GrGLQuadEffect::GenKey(const GrGeometryProcessor& gp, ////////////////////////////////////////////////////////////////////////////// +constexpr GrPrimitiveProcessor::Attribute GrQuadEffect::kAttributes[]; + GrQuadEffect::~GrQuadEffect() {} void GrQuadEffect::getGLSLProcessorKey(const GrShaderCaps& caps, @@ -441,8 +444,7 @@ GrQuadEffect::GrQuadEffect(GrColor color, const SkMatrix& viewMatrix, uint8_t co , fUsesLocalCoords(usesLocalCoords) , fCoverageScale(coverage) , fEdgeType(edgeType) { - fInPosition = &this->addVertexAttrib("inPosition", kFloat2_GrVertexAttribType); - fInHairQuadEdge = &this->addVertexAttrib("inHairQuadEdge", kHalf4_GrVertexAttribType); + this->setVertexAttributeCnt(2); } ////////////////////////////////////////////////////////////////////////////// @@ -544,7 +546,7 @@ void GrGLCubicEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) { this->writeOutputPosition(vertBuilder, uniformHandler, gpArgs, - gp.inPosition()->name(), + gp.inPosition().name(), gp.viewMatrix(), &fViewMatrixUniform); @@ -576,7 +578,7 @@ void GrGLCubicEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) { this->emitTransforms(vertBuilder, varyingHandler, uniformHandler, - gp.inPosition()->asShaderVar(), + gp.inPosition().asShaderVar(), args.fFPCoordTransformHandler); GrShaderVar edgeAlpha("edgeAlpha", kFloat_GrSLType, 0); @@ -647,6 +649,8 @@ void GrGLCubicEffect::GenKey(const GrGeometryProcessor& gp, ////////////////////////////////////////////////////////////////////////////// +constexpr GrPrimitiveProcessor::Attribute GrCubicEffect::kInPosition; + GrCubicEffect::~GrCubicEffect() {} void GrCubicEffect::getGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const { @@ -664,7 +668,7 @@ GrCubicEffect::GrCubicEffect(GrColor color, const SkMatrix& viewMatrix, const Sk , fViewMatrix(viewMatrix) , fDevKLMMatrix(devKLMMatrix) , fEdgeType(edgeType) { - fInPosition = &this->addVertexAttrib("inPosition", kFloat2_GrVertexAttribType); + this->setVertexAttributeCnt(1); } ////////////////////////////////////////////////////////////////////////////// diff --git a/src/gpu/effects/GrBezierEffect.h b/src/gpu/effects/GrBezierEffect.h index 174470410c..eebe42a5cd 100644 --- a/src/gpu/effects/GrBezierEffect.h +++ b/src/gpu/effects/GrBezierEffect.h @@ -93,8 +93,8 @@ public: const char* name() const override { return "Conic"; } - inline const Attribute* inPosition() const { return fInPosition; } - inline const Attribute* inConicCoeffs() const { return fInConicCoeffs; } + inline const Attribute& inPosition() const { return kAttributes[0]; } + inline const Attribute& inConicCoeffs() const { return kAttributes[1]; } inline bool isAntiAliased() const { return GrProcessorEdgeTypeIsAA(fEdgeType); } inline bool isFilled() const { return GrProcessorEdgeTypeIsFill(fEdgeType); } inline GrClipEdgeType getEdgeType() const { return fEdgeType; } @@ -112,14 +112,16 @@ private: GrConicEffect(GrColor, const SkMatrix& viewMatrix, uint8_t coverage, GrClipEdgeType, const SkMatrix& localMatrix, bool usesLocalCoords); + const Attribute& onVertexAttribute(int i) const override { return kAttributes[i]; } + GrColor fColor; SkMatrix fViewMatrix; SkMatrix fLocalMatrix; bool fUsesLocalCoords; uint8_t fCoverageScale; GrClipEdgeType fEdgeType; - const Attribute* fInPosition; - const Attribute* fInConicCoeffs; + static constexpr Attribute kAttributes[] = {{"inPosition", kFloat2_GrVertexAttribType}, + {"inConicCoeffs", kHalf4_GrVertexAttribType}}; GR_DECLARE_GEOMETRY_PROCESSOR_TEST @@ -175,8 +177,8 @@ public: const char* name() const override { return "Quad"; } - inline const Attribute* inPosition() const { return fInPosition; } - inline const Attribute* inHairQuadEdge() const { return fInHairQuadEdge; } + inline const Attribute& inPosition() const { return kAttributes[0]; } + inline const Attribute& inHairQuadEdge() const { return kAttributes[1]; } inline bool isAntiAliased() const { return GrProcessorEdgeTypeIsAA(fEdgeType); } inline bool isFilled() const { return GrProcessorEdgeTypeIsFill(fEdgeType); } inline GrClipEdgeType getEdgeType() const { return fEdgeType; } @@ -194,14 +196,17 @@ private: GrQuadEffect(GrColor, const SkMatrix& viewMatrix, uint8_t coverage, GrClipEdgeType, const SkMatrix& localMatrix, bool usesLocalCoords); - GrColor fColor; - SkMatrix fViewMatrix; - SkMatrix fLocalMatrix; - bool fUsesLocalCoords; - uint8_t fCoverageScale; + const Attribute& onVertexAttribute(int i) const override { return kAttributes[i]; } + + GrColor fColor; + SkMatrix fViewMatrix; + SkMatrix fLocalMatrix; + bool fUsesLocalCoords; + uint8_t fCoverageScale; GrClipEdgeType fEdgeType; - const Attribute* fInPosition; - const Attribute* fInHairQuadEdge; + + static constexpr Attribute kAttributes[] = {{"inPosition", kFloat2_GrVertexAttribType}, + {"inHairQuadEdge", kHalf4_GrVertexAttribType}}; GR_DECLARE_GEOMETRY_PROCESSOR_TEST @@ -263,7 +268,7 @@ public: const char* name() const override { return "Cubic"; } - inline const Attribute* inPosition() const { return fInPosition; } + inline const Attribute& inPosition() const { return kInPosition; } inline bool isAntiAliased() const { return GrProcessorEdgeTypeIsAA(fEdgeType); } inline bool isFilled() const { return GrProcessorEdgeTypeIsFill(fEdgeType); } inline GrClipEdgeType getEdgeType() const { return fEdgeType; } @@ -280,11 +285,14 @@ private: GrCubicEffect(GrColor, const SkMatrix& viewMatrix, const SkMatrix& devKLMMatrix, GrClipEdgeType); - GrColor fColor; - SkMatrix fViewMatrix; - SkMatrix fDevKLMMatrix; + const Attribute& onVertexAttribute(int) const override { return kInPosition; } + + GrColor fColor; + SkMatrix fViewMatrix; + SkMatrix fDevKLMMatrix; GrClipEdgeType fEdgeType; - const Attribute* fInPosition; + + static constexpr Attribute kInPosition = {"inPosition", kFloat2_GrVertexAttribType}; GR_DECLARE_GEOMETRY_PROCESSOR_TEST diff --git a/src/gpu/effects/GrBitmapTextGeoProc.cpp b/src/gpu/effects/GrBitmapTextGeoProc.cpp index 4089555362..2594f40ee5 100644 --- a/src/gpu/effects/GrBitmapTextGeoProc.cpp +++ b/src/gpu/effects/GrBitmapTextGeoProc.cpp @@ -40,7 +40,7 @@ public: GrGLSLVarying uv(kFloat2_GrSLType); GrSLType texIdxType = args.fShaderCaps->integerSupport() ? kInt_GrSLType : kFloat_GrSLType; GrGLSLVarying texIdx(texIdxType); - append_index_uv_varyings(args, btgp.inTextureCoords()->name(), atlasSizeInvName, &uv, + append_index_uv_varyings(args, btgp.inTextureCoords().name(), atlasSizeInvName, &uv, &texIdx, nullptr); GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; @@ -53,13 +53,13 @@ public: } // Setup position - gpArgs->fPositionVar = btgp.inPosition()->asShaderVar(); + gpArgs->fPositionVar = btgp.inPosition().asShaderVar(); // emit transforms this->emitTransforms(vertBuilder, varyingHandler, uniformHandler, - btgp.inPosition()->asShaderVar(), + btgp.inPosition().asShaderVar(), btgp.localMatrix(), args.fFPCoordTransformHandler); @@ -129,23 +129,26 @@ GrBitmapTextGeoProc::GrBitmapTextGeoProc(GrColor color, , fColor(color) , fLocalMatrix(localMatrix) , fUsesW(usesW) - , fInColor(nullptr) , fMaskFormat(format) { SkASSERT(numActiveProxies <= kMaxTextures); if (usesW) { - fInPosition = &this->addVertexAttrib("inPosition", kFloat3_GrVertexAttribType); + fInPosition = {"inPosition", kFloat3_GrVertexAttribType}; } else { - fInPosition = &this->addVertexAttrib("inPosition", kFloat2_GrVertexAttribType); + fInPosition = {"inPosition", kFloat2_GrVertexAttribType}; } + fInTextureCoords = {"inTextureCoords", kUShort2_GrVertexAttribType}; + int cnt = 2; bool hasVertexColor = kA8_GrMaskFormat == fMaskFormat || kA565_GrMaskFormat == fMaskFormat; if (hasVertexColor) { - fInColor = &this->addVertexAttrib("inColor", kUByte4_norm_GrVertexAttribType); + fInColor = {"inColor", kUByte4_norm_GrVertexAttribType}; + ++cnt; } - fInTextureCoords = &this->addVertexAttrib("inTextureCoords", kUShort2_GrVertexAttribType); + this->setVertexAttributeCnt(cnt); + for (int i = 0; i < numActiveProxies; ++i) { SkASSERT(proxies[i]); @@ -154,6 +157,10 @@ GrBitmapTextGeoProc::GrBitmapTextGeoProc(GrColor color, } } +const GrPrimitiveProcessor::Attribute& GrBitmapTextGeoProc::onVertexAttribute(int i) const { + return IthInitializedAttribute(i, fInPosition, fInColor, fInTextureCoords); +} + void GrBitmapTextGeoProc::addNewProxies(const sk_sp* proxies, int numActiveProxies, const GrSamplerState& params) { diff --git a/src/gpu/effects/GrBitmapTextGeoProc.h b/src/gpu/effects/GrBitmapTextGeoProc.h index 40ba8559e5..5e444977c2 100644 --- a/src/gpu/effects/GrBitmapTextGeoProc.h +++ b/src/gpu/effects/GrBitmapTextGeoProc.h @@ -36,12 +36,12 @@ public: const char* name() const override { return "Texture"; } - const Attribute* inPosition() const { return fInPosition; } - const Attribute* inColor() const { return fInColor; } - const Attribute* inTextureCoords() const { return fInTextureCoords; } + const Attribute& inPosition() const { return fInPosition; } + const Attribute& inColor() const { return fInColor; } + const Attribute& inTextureCoords() const { return fInTextureCoords; } GrMaskFormat maskFormat() const { return fMaskFormat; } GrColor color() const { return fColor; } - bool hasVertexColor() const { return SkToBool(fInColor); } + bool hasVertexColor() const { return fInColor.isInitialized(); } const SkMatrix& localMatrix() const { return fLocalMatrix; } bool usesW() const { return fUsesW; } @@ -58,13 +58,15 @@ private: const GrSamplerState& params, GrMaskFormat format, const SkMatrix& localMatrix, bool usesW); + const Attribute& onVertexAttribute(int i) const override; + GrColor fColor; SkMatrix fLocalMatrix; bool fUsesW; TextureSampler fTextureSamplers[kMaxTextures]; - const Attribute* fInPosition; - const Attribute* fInColor; - const Attribute* fInTextureCoords; + Attribute fInPosition; + Attribute fInColor; + Attribute fInTextureCoords; GrMaskFormat fMaskFormat; GR_DECLARE_GEOMETRY_PROCESSOR_TEST diff --git a/src/gpu/effects/GrDistanceFieldGeoProc.cpp b/src/gpu/effects/GrDistanceFieldGeoProc.cpp index 5ac73989ee..4d5d50b8db 100644 --- a/src/gpu/effects/GrDistanceFieldGeoProc.cpp +++ b/src/gpu/effects/GrDistanceFieldGeoProc.cpp @@ -54,13 +54,13 @@ public: varyingHandler->addPassThroughAttribute(dfTexEffect.inColor(), args.fOutputColor); // Setup position - gpArgs->fPositionVar = dfTexEffect.inPosition()->asShaderVar(); + gpArgs->fPositionVar = dfTexEffect.inPosition().asShaderVar(); // emit transforms this->emitTransforms(vertBuilder, varyingHandler, uniformHandler, - dfTexEffect.inPosition()->asShaderVar(), + dfTexEffect.inPosition().asShaderVar(), dfTexEffect.localMatrix(), args.fFPCoordTransformHandler); @@ -69,7 +69,7 @@ public: GrSLType texIdxType = args.fShaderCaps->integerSupport() ? kInt_GrSLType : kFloat_GrSLType; GrGLSLVarying texIdx(texIdxType); GrGLSLVarying st(kFloat2_GrSLType); - append_index_uv_varyings(args, dfTexEffect.inTextureCoords()->name(), atlasSizeInvName, &uv, + append_index_uv_varyings(args, dfTexEffect.inTextureCoords().name(), atlasSizeInvName, &uv, &texIdx, &st); bool isUniformScale = (dfTexEffect.getFlags() & kUniformScale_DistanceFieldEffectMask) == @@ -206,32 +206,34 @@ private: /////////////////////////////////////////////////////////////////////////////// -GrDistanceFieldA8TextGeoProc::GrDistanceFieldA8TextGeoProc( - const sk_sp* proxies, - int numProxies, - const GrSamplerState& params, +constexpr GrPrimitiveProcessor::Attribute GrDistanceFieldA8TextGeoProc::kInColor; +constexpr GrPrimitiveProcessor::Attribute GrDistanceFieldA8TextGeoProc::kInTextureCoords; + +GrDistanceFieldA8TextGeoProc::GrDistanceFieldA8TextGeoProc(const sk_sp* proxies, + int numProxies, + const GrSamplerState& params, #ifdef SK_GAMMA_APPLY_TO_A8 - float distanceAdjust, + float distanceAdjust, #endif - uint32_t flags, - const SkMatrix& localMatrix) + uint32_t flags, + const SkMatrix& localMatrix) : INHERITED(kGrDistanceFieldA8TextGeoProc_ClassID) + , fLocalMatrix(localMatrix) + , fFlags(flags & kNonLCD_DistanceFieldEffectMask) #ifdef SK_GAMMA_APPLY_TO_A8 , fDistanceAdjust(distanceAdjust) #endif - , fFlags(flags & kNonLCD_DistanceFieldEffectMask) - , fInColor(nullptr) - , fLocalMatrix(localMatrix) { +{ SkASSERT(numProxies <= kMaxTextures); - SkASSERT(!(flags & ~kNonLCD_DistanceFieldEffectMask)); + if (flags & kPerspective_DistanceFieldEffectFlag) { - fInPosition = &this->addVertexAttrib("inPosition", kFloat3_GrVertexAttribType); + fInPosition = {"inPosition", kFloat3_GrVertexAttribType}; } else { - fInPosition = &this->addVertexAttrib("inPosition", kFloat2_GrVertexAttribType); + fInPosition = {"inPosition", kFloat2_GrVertexAttribType}; } - fInColor = &this->addVertexAttrib("inColor", kUByte4_norm_GrVertexAttribType); - fInTextureCoords = &this->addVertexAttrib("inTextureCoords", kUShort2_GrVertexAttribType); + this->setVertexAttributeCnt(3); + for (int i = 0; i < numProxies; ++i) { SkASSERT(proxies[i]); @@ -337,8 +339,8 @@ public: GrSLType texIdxType = args.fShaderCaps->integerSupport() ? kInt_GrSLType : kFloat_GrSLType; GrGLSLVarying texIdx(texIdxType); GrGLSLVarying st(kFloat2_GrSLType); - append_index_uv_varyings(args, dfPathEffect.inTextureCoords()->name(), atlasSizeInvName, - &uv, &texIdx, &st); + append_index_uv_varyings(args, dfPathEffect.inTextureCoords().name(), atlasSizeInvName, &uv, + &texIdx, &st); // setup pass through color varyingHandler->addPassThroughAttribute(dfPathEffect.inColor(), args.fOutputColor); @@ -348,7 +350,7 @@ public: this->writeOutputPosition(vertBuilder, uniformHandler, gpArgs, - dfPathEffect.inPosition()->name(), + dfPathEffect.inPosition().name(), dfPathEffect.matrix(), &fMatrixUniform); @@ -356,17 +358,17 @@ public: this->emitTransforms(vertBuilder, varyingHandler, uniformHandler, - dfPathEffect.inPosition()->asShaderVar(), + dfPathEffect.inPosition().asShaderVar(), args.fFPCoordTransformHandler); } else { // Setup position - this->writeOutputPosition(vertBuilder, gpArgs, dfPathEffect.inPosition()->name()); + this->writeOutputPosition(vertBuilder, gpArgs, dfPathEffect.inPosition().name()); // emit transforms this->emitTransforms(vertBuilder, varyingHandler, uniformHandler, - dfPathEffect.inPosition()->asShaderVar(), + dfPathEffect.inPosition().asShaderVar(), dfPathEffect.matrix(), args.fFPCoordTransformHandler); } @@ -499,22 +501,22 @@ private: }; /////////////////////////////////////////////////////////////////////////////// -GrDistanceFieldPathGeoProc::GrDistanceFieldPathGeoProc( - const SkMatrix& matrix, - const sk_sp* proxies, - int numProxies, - const GrSamplerState& params, - uint32_t flags) +constexpr GrPrimitiveProcessor::Attribute GrDistanceFieldPathGeoProc::kInPosition; +constexpr GrPrimitiveProcessor::Attribute GrDistanceFieldPathGeoProc::kInColor; +constexpr GrPrimitiveProcessor::Attribute GrDistanceFieldPathGeoProc::kInTextureCoords; + +GrDistanceFieldPathGeoProc::GrDistanceFieldPathGeoProc(const SkMatrix& matrix, + const sk_sp* proxies, + int numProxies, + const GrSamplerState& params, + uint32_t flags) : INHERITED(kGrDistanceFieldPathGeoProc_ClassID) , fMatrix(matrix) - , fFlags(flags & kNonLCD_DistanceFieldEffectMask) - , fInColor(nullptr) { + , fFlags(flags & kNonLCD_DistanceFieldEffectMask) { SkASSERT(numProxies <= kMaxTextures); - SkASSERT(!(flags & ~kNonLCD_DistanceFieldEffectMask)); - fInPosition = &this->addVertexAttrib("inPosition", kFloat2_GrVertexAttribType); - fInColor = &this->addVertexAttrib("inColor", kUByte4_norm_GrVertexAttribType); - fInTextureCoords = &this->addVertexAttrib("inTextureCoords", kUShort2_GrVertexAttribType); + + this->setVertexAttributeCnt(3); for (int i = 0; i < numProxies; ++i) { SkASSERT(proxies[i]); @@ -548,6 +550,10 @@ GrDistanceFieldPathGeoProc::createGLSLInstance(const GrShaderCaps&) const { return new GrGLDistanceFieldPathGeoProc(); } +const GrPrimitiveProcessor::Attribute& GrDistanceFieldPathGeoProc::onVertexAttribute(int i) const { + return IthAttribute(i, kInPosition, kInColor, kInTextureCoords); +} + /////////////////////////////////////////////////////////////////////////////// GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrDistanceFieldPathGeoProc); @@ -614,13 +620,13 @@ public: varyingHandler->addPassThroughAttribute(dfTexEffect.inColor(), args.fOutputColor); // Setup position - gpArgs->fPositionVar = dfTexEffect.inPosition()->asShaderVar(); + gpArgs->fPositionVar = dfTexEffect.inPosition().asShaderVar(); // emit transforms this->emitTransforms(vertBuilder, varyingHandler, uniformHandler, - dfTexEffect.inPosition()->asShaderVar(), + dfTexEffect.inPosition().asShaderVar(), dfTexEffect.localMatrix(), args.fFPCoordTransformHandler); @@ -629,7 +635,7 @@ public: GrSLType texIdxType = args.fShaderCaps->integerSupport() ? kInt_GrSLType : kFloat_GrSLType; GrGLSLVarying texIdx(texIdxType); GrGLSLVarying st(kFloat2_GrSLType); - append_index_uv_varyings(args, dfTexEffect.inTextureCoords()->name(), atlasSizeInvName, &uv, + append_index_uv_varyings(args, dfTexEffect.inTextureCoords().name(), atlasSizeInvName, &uv, &texIdx, &st); GrGLSLVarying delta(kFloat_GrSLType); @@ -802,27 +808,30 @@ private: }; /////////////////////////////////////////////////////////////////////////////// -GrDistanceFieldLCDTextGeoProc::GrDistanceFieldLCDTextGeoProc( - const sk_sp* proxies, - int numProxies, - const GrSamplerState& params, - DistanceAdjust distanceAdjust, - uint32_t flags, - const SkMatrix& localMatrix) + +constexpr GrPrimitiveProcessor::Attribute GrDistanceFieldLCDTextGeoProc::kInColor; +constexpr GrPrimitiveProcessor::Attribute GrDistanceFieldLCDTextGeoProc::kInTextureCoords; + +GrDistanceFieldLCDTextGeoProc::GrDistanceFieldLCDTextGeoProc(const sk_sp* proxies, + int numProxies, + const GrSamplerState& params, + DistanceAdjust distanceAdjust, + uint32_t flags, + const SkMatrix& localMatrix) : INHERITED(kGrDistanceFieldLCDTextGeoProc_ClassID) + , fLocalMatrix(localMatrix) , fDistanceAdjust(distanceAdjust) - , fFlags(flags & kLCD_DistanceFieldEffectMask) - , fLocalMatrix(localMatrix) { + , fFlags(flags & kLCD_DistanceFieldEffectMask) { SkASSERT(numProxies <= kMaxTextures); - SkASSERT(!(flags & ~kLCD_DistanceFieldEffectMask) && (flags & kUseLCD_DistanceFieldEffectFlag)); + if (fFlags & kPerspective_DistanceFieldEffectFlag) { - fInPosition = &this->addVertexAttrib("inPosition", kFloat3_GrVertexAttribType); + fInPosition = {"inPosition", kFloat3_GrVertexAttribType}; } else { - fInPosition = &this->addVertexAttrib("inPosition", kFloat2_GrVertexAttribType); + fInPosition = {"inPosition", kFloat2_GrVertexAttribType}; } - fInColor = &this->addVertexAttrib("inColor", kUByte4_norm_GrVertexAttribType); - fInTextureCoords = &this->addVertexAttrib("inTextureCoords", kUShort2_GrVertexAttribType); + this->setVertexAttributeCnt(3); + for (int i = 0; i < numProxies; ++i) { SkASSERT(proxies[i]); @@ -855,6 +864,11 @@ GrGLSLPrimitiveProcessor* GrDistanceFieldLCDTextGeoProc::createGLSLInstance(cons return new GrGLDistanceFieldLCDTextGeoProc(); } +const GrPrimitiveProcessor::Attribute& GrDistanceFieldLCDTextGeoProc::onVertexAttribute( + int i) const { + return IthAttribute(i, fInPosition, kInColor, kInTextureCoords); +} + /////////////////////////////////////////////////////////////////////////////// GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrDistanceFieldLCDTextGeoProc); diff --git a/src/gpu/effects/GrDistanceFieldGeoProc.h b/src/gpu/effects/GrDistanceFieldGeoProc.h index 5ba19ed5a5..71626fa938 100644 --- a/src/gpu/effects/GrDistanceFieldGeoProc.h +++ b/src/gpu/effects/GrDistanceFieldGeoProc.h @@ -76,9 +76,9 @@ public: const char* name() const override { return "DistanceFieldA8Text"; } - const Attribute* inPosition() const { return fInPosition; } - const Attribute* inColor() const { return fInColor; } - const Attribute* inTextureCoords() const { return fInTextureCoords; } + const Attribute& inPosition() const { return fInPosition; } + const Attribute& inColor() const { return kInColor; } + const Attribute& inTextureCoords() const { return kInTextureCoords; } const SkMatrix& localMatrix() const { return fLocalMatrix; } #ifdef SK_GAMMA_APPLY_TO_A8 float getDistanceAdjust() const { return fDistanceAdjust; } @@ -100,17 +100,22 @@ private: #endif uint32_t flags, const SkMatrix& localMatrix); + const Attribute& onVertexAttribute(int i) const override { + return IthAttribute(i, fInPosition, kInColor, kInTextureCoords); + } + static constexpr int kMaxTextures = 4; TextureSampler fTextureSamplers[kMaxTextures]; + SkMatrix fLocalMatrix; + Attribute fInPosition; + uint32_t fFlags; #ifdef SK_GAMMA_APPLY_TO_A8 float fDistanceAdjust; #endif - uint32_t fFlags; - const Attribute* fInPosition; - const Attribute* fInColor; - const Attribute* fInTextureCoords; - SkMatrix fLocalMatrix; + + static constexpr Attribute kInColor = {"inColor", kUByte4_norm_GrVertexAttribType}; + static constexpr Attribute kInTextureCoords = {"inTextureCoords", kUShort2_GrVertexAttribType}; GR_DECLARE_GEOMETRY_PROCESSOR_TEST @@ -139,9 +144,9 @@ public: const char* name() const override { return "DistanceFieldPath"; } - const Attribute* inPosition() const { return fInPosition; } - const Attribute* inColor() const { return fInColor; } - const Attribute* inTextureCoords() const { return fInTextureCoords; } + const Attribute& inPosition() const { return kInPosition; } + const Attribute& inColor() const { return kInColor; } + const Attribute& inTextureCoords() const { return kInTextureCoords; } const SkMatrix& matrix() const { return fMatrix; } uint32_t getFlags() const { return fFlags; } @@ -159,12 +164,14 @@ private: int numActiveProxies, const GrSamplerState&, uint32_t flags); + const Attribute& onVertexAttribute(int i) const override; + SkMatrix fMatrix; // view matrix if perspective, local matrix otherwise TextureSampler fTextureSamplers[kMaxTextures]; uint32_t fFlags; - const Attribute* fInPosition; - const Attribute* fInColor; - const Attribute* fInTextureCoords; + static constexpr Attribute kInPosition = {"inPosition", kFloat2_GrVertexAttribType}; + static constexpr Attribute kInColor = {"inColor", kUByte4_norm_GrVertexAttribType}; + static constexpr Attribute kInTextureCoords = {"inTextureCoords", kUShort2_GrVertexAttribType}; GR_DECLARE_GEOMETRY_PROCESSOR_TEST @@ -209,9 +216,9 @@ public: const char* name() const override { return "DistanceFieldLCDText"; } - const Attribute* inPosition() const { return fInPosition; } - const Attribute* inColor() const { return fInColor; } - const Attribute* inTextureCoords() const { return fInTextureCoords; } + const Attribute& inPosition() const { return fInPosition; } + const Attribute& inColor() const { return kInColor; } + const Attribute& inTextureCoords() const { return kInTextureCoords; } DistanceAdjust getDistanceAdjust() const { return fDistanceAdjust; } uint32_t getFlags() const { return fFlags; } const SkMatrix& localMatrix() const { return fLocalMatrix; } @@ -227,15 +234,18 @@ private: const GrSamplerState& params, DistanceAdjust wa, uint32_t flags, const SkMatrix& localMatrix); + const Attribute& onVertexAttribute(int) const override; + static constexpr int kMaxTextures = 4; TextureSampler fTextureSamplers[kMaxTextures]; + const SkMatrix fLocalMatrix; DistanceAdjust fDistanceAdjust; + Attribute fInPosition; uint32_t fFlags; - const Attribute* fInPosition; - const Attribute* fInColor; - const Attribute* fInTextureCoords; - const SkMatrix fLocalMatrix; + + static constexpr Attribute kInColor = {"inColor", kUByte4_norm_GrVertexAttribType}; + static constexpr Attribute kInTextureCoords = {"inTextureCoords", kUShort2_GrVertexAttribType}; GR_DECLARE_GEOMETRY_PROCESSOR_TEST diff --git a/src/gpu/effects/GrShadowGeoProc.cpp b/src/gpu/effects/GrShadowGeoProc.cpp index 52bf287bea..bf78f41c97 100644 --- a/src/gpu/effects/GrShadowGeoProc.cpp +++ b/src/gpu/effects/GrShadowGeoProc.cpp @@ -33,13 +33,13 @@ public: varyingHandler->addPassThroughAttribute(rsgp.inColor(), args.fOutputColor); // Setup position - this->writeOutputPosition(vertBuilder, gpArgs, rsgp.inPosition()->name()); + this->writeOutputPosition(vertBuilder, gpArgs, rsgp.inPosition().name()); // emit transforms this->emitTransforms(vertBuilder, varyingHandler, uniformHandler, - rsgp.inPosition()->asShaderVar(), + rsgp.inPosition().asShaderVar(), args.fFPCoordTransformHandler); fragBuilder->codeAppend("half d = length(shadowParams.xy);"); @@ -62,11 +62,8 @@ private: /////////////////////////////////////////////////////////////////////////////// -GrRRectShadowGeoProc::GrRRectShadowGeoProc() -: INHERITED(kGrRRectShadowGeoProc_ClassID) { - fInPosition = &this->addVertexAttrib("inPosition", kFloat2_GrVertexAttribType); - fInColor = &this->addVertexAttrib("inColor", kUByte4_norm_GrVertexAttribType); - fInShadowParams = &this->addVertexAttrib("inShadowParams", kHalf4_GrVertexAttribType); +GrRRectShadowGeoProc::GrRRectShadowGeoProc() : INHERITED(kGrRRectShadowGeoProc_ClassID) { + this->setVertexAttributeCnt(3); } GrGLSLPrimitiveProcessor* GrRRectShadowGeoProc::createGLSLInstance(const GrShaderCaps&) const { @@ -75,6 +72,10 @@ GrGLSLPrimitiveProcessor* GrRRectShadowGeoProc::createGLSLInstance(const GrShade /////////////////////////////////////////////////////////////////////////////// +constexpr GrPrimitiveProcessor::Attribute GrRRectShadowGeoProc::kInPosition; +constexpr GrPrimitiveProcessor::Attribute GrRRectShadowGeoProc::kInColor; +constexpr GrPrimitiveProcessor::Attribute GrRRectShadowGeoProc::kInShadowParams; + GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrRRectShadowGeoProc); #if GR_TEST_UTILS diff --git a/src/gpu/effects/GrShadowGeoProc.h b/src/gpu/effects/GrShadowGeoProc.h index 0b4baf49b8..df3e501c59 100644 --- a/src/gpu/effects/GrShadowGeoProc.h +++ b/src/gpu/effects/GrShadowGeoProc.h @@ -25,9 +25,9 @@ public: const char* name() const override { return "RRectShadow"; } - const Attribute* inPosition() const { return fInPosition; } - const Attribute* inColor() const { return fInColor; } - const Attribute* inShadowParams() const { return fInShadowParams; } + const Attribute& inPosition() const { return kInPosition; } + const Attribute& inColor() const { return kInColor; } + const Attribute& inShadowParams() const { return kInShadowParams; } GrColor color() const { return fColor; } void getGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {} @@ -37,10 +37,15 @@ public: private: GrRRectShadowGeoProc(); + const Attribute& onVertexAttribute(int i) const override { + return IthAttribute(i, kInPosition, kInColor, kInShadowParams); + } + GrColor fColor; - const Attribute* fInPosition; - const Attribute* fInColor; - const Attribute* fInShadowParams; + + static constexpr Attribute kInPosition = {"inPosition", kFloat2_GrVertexAttribType}; + static constexpr Attribute kInColor = {"inColor", kUByte4_norm_GrVertexAttribType}; + static constexpr Attribute kInShadowParams = {"inShadowParams", kHalf4_GrVertexAttribType}; GR_DECLARE_GEOMETRY_PROCESSOR_TEST diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp index 88f5abecb4..be53222ee8 100644 --- a/src/gpu/gl/GrGLGpu.cpp +++ b/src/gpu/gl/GrGLGpu.cpp @@ -1775,35 +1775,29 @@ void GrGLGpu::setupGeometry(const GrBuffer* indexBuffer, attribState = fHWVertexArrayState.bindInternalVertexArray(this); } - struct { - const GrBuffer* fBuffer; - int fStride; - size_t fBufferOffset; - } bindings[2]; + int numAttribs = fHWProgram->numVertexAttributes() + fHWProgram->numInstanceAttributes(); + attribState->enableVertexArrays(this, numAttribs, enablePrimitiveRestart); if (int vertexStride = fHWProgram->vertexStride()) { SkASSERT(vertexBuffer && !vertexBuffer->isMapped()); - bindings[0].fBuffer = vertexBuffer; - bindings[0].fStride = vertexStride; - bindings[0].fBufferOffset = vertexBuffer->baseOffset() + baseVertex * vertexStride; + size_t bufferOffset = vertexBuffer->baseOffset() + baseVertex * vertexStride; + for (int i = 0; i < fHWProgram->numVertexAttributes(); ++i) { + const auto& attrib = fHWProgram->vertexAttribute(i); + static constexpr int kDivisor = 0; + attribState->set(this, attrib.fLocation, vertexBuffer, attrib.fType, vertexStride, + bufferOffset + attrib.fOffset, kDivisor); + } } if (int instanceStride = fHWProgram->instanceStride()) { SkASSERT(instanceBuffer && !instanceBuffer->isMapped()); - bindings[1].fBuffer = instanceBuffer; - bindings[1].fStride = instanceStride; - bindings[1].fBufferOffset = instanceBuffer->baseOffset() + baseInstance * instanceStride; - } - - auto numAttributes = fHWProgram->numAttributes(); - attribState->enableVertexArrays(this, numAttributes, enablePrimitiveRestart); - - for (int i = 0; i < numAttributes; ++i) { - using InputRate = GrPrimitiveProcessor::Attribute::InputRate; - const GrGLProgram::Attribute& attribute = fHWProgram->attribute(i); - const int divisor = InputRate::kPerInstance == attribute.fInputRate ? 1 : 0; - const auto& binding = bindings[divisor]; - attribState->set(this, attribute.fLocation, binding.fBuffer, attribute.fType, - binding.fStride, binding.fBufferOffset + attribute.fOffset, divisor); + size_t bufferOffset = instanceBuffer->baseOffset() + baseInstance * instanceStride; + int attribIdx = fHWProgram->numVertexAttributes(); + for (int i = 0; i < fHWProgram->numInstanceAttributes(); ++i, ++attribIdx) { + const auto& attrib = fHWProgram->instanceAttribute(i); + static constexpr int kDivisor = 1; + attribState->set(this, attrib.fLocation, instanceBuffer, attrib.fType, instanceStride, + bufferOffset + attrib.fOffset, kDivisor); + } } } diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp index 262f0b21c4..3d4bd380fa 100644 --- a/src/gpu/gl/GrGLProgram.cpp +++ b/src/gpu/gl/GrGLProgram.cpp @@ -38,7 +38,8 @@ GrGLProgram::GrGLProgram( std::unique_ptr[]> fragmentProcessors, int fragmentProcessorCnt, std::unique_ptr attributes, - int attributeCnt, + int vertexAttributeCnt, + int instanceAttributeCnt, int vertexStride, int instanceStride) : fBuiltinUniformHandles(builtinUniforms) @@ -48,7 +49,8 @@ GrGLProgram::GrGLProgram( , fFragmentProcessors(std::move(fragmentProcessors)) , fFragmentProcessorCnt(fragmentProcessorCnt) , fAttributes(std::move(attributes)) - , fAttributeCnt(attributeCnt) + , fVertexAttributeCnt(vertexAttributeCnt) + , fInstanceAttributeCnt(instanceAttributeCnt) , fVertexStride(vertexStride) , fInstanceStride(instanceStride) , fGpu(gpu) diff --git a/src/gpu/gl/GrGLProgram.h b/src/gpu/gl/GrGLProgram.h index 6ea1f2cbf9..ca4eddce4b 100644 --- a/src/gpu/gl/GrGLProgram.h +++ b/src/gpu/gl/GrGLProgram.h @@ -10,7 +10,6 @@ #define GrGLProgram_DEFINED #include "GrGLProgramDataManager.h" -#include "GrPrimitiveProcessor.h" #include "glsl/GrGLSLProgramDataManager.h" #include "glsl/GrGLSLUniformHandler.h" @@ -35,15 +34,18 @@ public: */ struct Attribute { GrVertexAttribType fType; - int fOffset; + size_t fOffset; GrGLint fLocation; - GrPrimitiveProcessor::Attribute::InputRate fInputRate; }; using UniformHandle = GrGLSLProgramDataManager::UniformHandle; using UniformInfoArray = GrGLProgramDataManager::UniformInfoArray; using VaryingInfoArray = GrGLProgramDataManager::VaryingInfoArray; + /** + * The attribute array consists of vertexAttributeCnt + instanceAttributeCnt elements with + * the vertex attributes preceding the instance attributes. + */ GrGLProgram(GrGLGpu*, const GrGLSLBuiltinUniformHandles&, GrGLuint programID, @@ -56,7 +58,8 @@ public: std::unique_ptr[]> fragmentProcessors, int fragmentProcessorCnt, std::unique_ptr, - int attributeCnt, + int vertexAttributeCnt, + int instanceAttributeCnt, int vertexStride, int instanceStride); @@ -124,8 +127,17 @@ public: int vertexStride() const { return fVertexStride; } int instanceStride() const { return fInstanceStride; } - int numAttributes() const { return fAttributeCnt; } - const Attribute& attribute(int i) const { return fAttributes[i]; } + int numVertexAttributes() const { return fVertexAttributeCnt; } + const Attribute& vertexAttribute(int i) const { + SkASSERT(i >= 0 && i < fVertexAttributeCnt); + return fAttributes[i]; + } + + int numInstanceAttributes() const { return fInstanceAttributeCnt; } + const Attribute& instanceAttribute(int i) const { + SkASSERT(i >= 0 && i < fInstanceAttributeCnt); + return fAttributes[i + fVertexAttributeCnt]; + } private: // A helper to loop over effects, set the transforms (via subclass) and bind textures @@ -153,7 +165,8 @@ private: int fFragmentProcessorCnt; std::unique_ptr fAttributes; - int fAttributeCnt; + int fVertexAttributeCnt; + int fInstanceAttributeCnt; int fVertexStride; int fInstanceStride; diff --git a/src/gpu/gl/GrGLVaryingHandler.cpp b/src/gpu/gl/GrGLVaryingHandler.cpp index eecc63e617..e426d46e14 100644 --- a/src/gpu/gl/GrGLVaryingHandler.cpp +++ b/src/gpu/gl/GrGLVaryingHandler.cpp @@ -20,7 +20,8 @@ GrGLSLVaryingHandler::VaryingHandle GrGLVaryingHandler::addPathProcessingVarying SkASSERT(glPB->gpu()->glCaps().shaderCaps()->pathRenderingSupport() && glPB->fPrimProc.isPathRendering() && !glPB->fPrimProc.willUseGeoShader() && - glPB->fPrimProc.numAttribs() == 0); + !glPB->fPrimProc.numVertexAttributes() && + !glPB->fPrimProc.numInstanceAttributes()); #endif this->addVarying(name, v); auto varyingInfo = fPathProcVaryingInfos.push_back(); diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.cpp b/src/gpu/gl/builders/GrGLProgramBuilder.cpp index 0cdc3b5b21..79e13d3555 100644 --- a/src/gpu/gl/builders/GrGLProgramBuilder.cpp +++ b/src/gpu/gl/builders/GrGLProgramBuilder.cpp @@ -70,7 +70,8 @@ GrGLProgramBuilder::GrGLProgramBuilder(GrGLGpu* gpu, , fGpu(gpu) , fVaryingHandler(this) , fUniformHandler(this) - , fAttributeCnt(0) + , fVertexAttributeCnt(0) + , fInstanceAttributeCnt(0) , fVertexStride(0) , fInstanceStride(0) {} @@ -227,18 +228,30 @@ GrGLProgram* GrGLProgramBuilder::finalize() { // NVPR actually requires a vertex shader to compile bool useNvpr = primProc.isPathRendering(); if (!useNvpr) { - fAttributeCnt = primProc.numAttribs(); - fAttributes.reset(new GrGLProgram::Attribute[fAttributeCnt]); - fVertexStride = primProc.getVertexStride(); - fInstanceStride = primProc.getInstanceStride(); - for (int i = 0; i < fAttributeCnt; i++) { - const auto& attr = primProc.getAttrib(i); - fAttributes[i].fInputRate = attr.inputRate(); - fAttributes[i].fType = attr.type(); - fAttributes[i].fOffset = attr.offsetInRecord(); + fVertexAttributeCnt = primProc.numVertexAttributes(); + fInstanceAttributeCnt = primProc.numInstanceAttributes(); + fAttributes.reset( + new GrGLProgram::Attribute[fVertexAttributeCnt + fInstanceAttributeCnt]); + auto addAttr = [&](int i, const auto& a, size_t* stride) { + fAttributes[i].fType = a.type(); + fAttributes[i].fOffset = *stride; + *stride += a.sizeAlign4(); fAttributes[i].fLocation = i; - GL_CALL(BindAttribLocation(programID, i, attr.name())); + GL_CALL(BindAttribLocation(programID, i, a.name())); + }; + fVertexStride = 0; + int i = 0; + for (; i < fVertexAttributeCnt; i++) { + addAttr(i, primProc.vertexAttribute(i), &fVertexStride); + SkASSERT(fAttributes[i].fOffset == primProc.debugOnly_vertexAttributeOffset(i)); } + SkASSERT(fVertexStride == primProc.debugOnly_vertexStride()); + fInstanceStride = 0; + for (int j = 0; j < fInstanceAttributeCnt; j++, ++i) { + addAttr(i, primProc.instanceAttribute(j), &fInstanceStride); + SkASSERT(fAttributes[i].fOffset == primProc.debugOnly_instanceAttributeOffset(j)); + } + SkASSERT(fInstanceStride == primProc.debugOnly_instanceStride()); } if (primProc.willUseGeoShader()) { @@ -406,7 +419,8 @@ GrGLProgram* GrGLProgramBuilder::createProgram(GrGLuint programID) { std::move(fFragmentProcessors), fFragmentProcessorCnt, std::move(fAttributes), - fAttributeCnt, + fVertexAttributeCnt, + fInstanceAttributeCnt, fVertexStride, fInstanceStride); } diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.h b/src/gpu/gl/builders/GrGLProgramBuilder.h index ea3432bd04..30d5179325 100644 --- a/src/gpu/gl/builders/GrGLProgramBuilder.h +++ b/src/gpu/gl/builders/GrGLProgramBuilder.h @@ -81,9 +81,10 @@ private: GrGLUniformHandler fUniformHandler; std::unique_ptr fAttributes; - int fAttributeCnt; - int fVertexStride; - int fInstanceStride; + int fVertexAttributeCnt; + int fInstanceAttributeCnt; + size_t fVertexStride; + size_t fInstanceStride; // shader pulled from cache. Data is organized as: // SkSL::Program::Inputs inputs diff --git a/src/gpu/glsl/GrGLSLVarying.cpp b/src/gpu/glsl/GrGLSLVarying.cpp index f8ec1c24d9..0563406385 100644 --- a/src/gpu/glsl/GrGLSLVarying.cpp +++ b/src/gpu/glsl/GrGLSLVarying.cpp @@ -9,14 +9,15 @@ #include "glsl/GrGLSLVarying.h" #include "glsl/GrGLSLProgramBuilder.h" -void GrGLSLVaryingHandler::addPassThroughAttribute(const GrGeometryProcessor::Attribute* input, +void GrGLSLVaryingHandler::addPassThroughAttribute(const GrGeometryProcessor::Attribute& input, const char* output, Interpolation interpolation) { + SkASSERT(input.isInitialized()); SkASSERT(!fProgramBuilder->primitiveProcessor().willUseGeoShader()); - GrSLType type = GrVertexAttribTypeToSLType(input->type()); + GrSLType type = GrVertexAttribTypeToSLType(input.type()); GrGLSLVarying v(type); - this->addVarying(input->name(), &v, interpolation); - fProgramBuilder->fVS.codeAppendf("%s = %s;", v.vsOut(), input->name()); + this->addVarying(input.name(), &v, interpolation); + fProgramBuilder->fVS.codeAppendf("%s = %s;", v.vsOut(), input.name()); fProgramBuilder->fFS.codeAppendf("%s = %s;", output, v.fsIn()); } @@ -67,10 +68,13 @@ void GrGLSLVaryingHandler::addVarying(const char* name, GrGLSLVarying* varying, } void GrGLSLVaryingHandler::emitAttributes(const GrGeometryProcessor& gp) { - int vaCount = gp.numAttribs(); + int vaCount = gp.numVertexAttributes(); for (int i = 0; i < vaCount; i++) { - const GrGeometryProcessor::Attribute& attr = gp.getAttrib(i); - this->addAttribute(attr.asShaderVar()); + this->addAttribute(gp.vertexAttribute(i).asShaderVar()); + } + int iaCount = gp.numInstanceAttributes(); + for (int i = 0; i < iaCount; i++) { + this->addAttribute(gp.instanceAttribute(i).asShaderVar()); } } diff --git a/src/gpu/glsl/GrGLSLVarying.h b/src/gpu/glsl/GrGLSLVarying.h index 57704ad075..0da88a0fbd 100644 --- a/src/gpu/glsl/GrGLSLVarying.h +++ b/src/gpu/glsl/GrGLSLVarying.h @@ -104,7 +104,7 @@ public: * that will be set as the output varying for all emitted vertices. * TODO it might be nicer behavior to have a flag to declare output inside these calls */ - void addPassThroughAttribute(const GrGeometryProcessor::Attribute*, const char* output, + void addPassThroughAttribute(const GrGeometryProcessor::Attribute&, const char* output, Interpolation = Interpolation::kInterpolated); void emitAttributes(const GrGeometryProcessor& gp); diff --git a/src/gpu/ops/GrAAConvexPathRenderer.cpp b/src/gpu/ops/GrAAConvexPathRenderer.cpp index 3237afeaed..566eebd827 100644 --- a/src/gpu/ops/GrAAConvexPathRenderer.cpp +++ b/src/gpu/ops/GrAAConvexPathRenderer.cpp @@ -576,21 +576,21 @@ public: GrGLSLVarying v(kHalf4_GrSLType); varyingHandler->addVarying("QuadEdge", &v); - vertBuilder->codeAppendf("%s = %s;", v.vsOut(), qe.fInQuadEdge->name()); + vertBuilder->codeAppendf("%s = %s;", v.vsOut(), qe.kInQuadEdge.name()); // Setup pass through color - varyingHandler->addPassThroughAttribute(qe.fInColor, args.fOutputColor); + varyingHandler->addPassThroughAttribute(qe.kInColor, args.fOutputColor); GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; // Setup position - this->writeOutputPosition(vertBuilder, gpArgs, qe.fInPosition->name()); + this->writeOutputPosition(vertBuilder, gpArgs, qe.kInPosition.name()); // emit transforms this->emitTransforms(vertBuilder, varyingHandler, uniformHandler, - qe.fInPosition->asShaderVar(), + qe.kInPosition.asShaderVar(), qe.fLocalMatrix, args.fFPCoordTransformHandler); @@ -646,21 +646,25 @@ private: : INHERITED(kQuadEdgeEffect_ClassID) , fLocalMatrix(localMatrix) , fUsesLocalCoords(usesLocalCoords) { - fInPosition = &this->addVertexAttrib("inPosition", kFloat2_GrVertexAttribType); - fInColor = &this->addVertexAttrib("inColor", kUByte4_norm_GrVertexAttribType); - fInQuadEdge = &this->addVertexAttrib("inQuadEdge", kHalf4_GrVertexAttribType); + this->setVertexAttributeCnt(3); } - const Attribute* fInPosition; - const Attribute* fInQuadEdge; - const Attribute* fInColor; - SkMatrix fLocalMatrix; - bool fUsesLocalCoords; + const Attribute& onVertexAttribute(int i) const override { + return IthAttribute(i, kInPosition, kInColor, kInQuadEdge); + } + static constexpr Attribute kInPosition = {"inPosition", kFloat2_GrVertexAttribType}; + static constexpr Attribute kInColor = {"inColor", kUByte4_norm_GrVertexAttribType}; + static constexpr Attribute kInQuadEdge = {"inQuadEdge", kHalf4_GrVertexAttribType}; + SkMatrix fLocalMatrix; + bool fUsesLocalCoords; GR_DECLARE_GEOMETRY_PROCESSOR_TEST typedef GrGeometryProcessor INHERITED; }; +constexpr GrPrimitiveProcessor::Attribute QuadEdgeEffect::kInPosition; +constexpr GrPrimitiveProcessor::Attribute QuadEdgeEffect::kInColor; +constexpr GrPrimitiveProcessor::Attribute QuadEdgeEffect::kInQuadEdge; GR_DEFINE_GEOMETRY_PROCESSOR_TEST(QuadEdgeEffect); @@ -795,12 +799,10 @@ private: return; } - size_t vertexStride = gp->getVertexStride(); - - SkASSERT(fHelper.compatibleWithAlphaAsCoverage() - ? vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorAttr) - : vertexStride == - sizeof(GrDefaultGeoProcFactory::PositionColorCoverageAttr)); + size_t vertexStride = fHelper.compatibleWithAlphaAsCoverage() + ? sizeof(GrDefaultGeoProcFactory::PositionColorAttr) + : sizeof(GrDefaultGeoProcFactory::PositionColorCoverageAttr); + SkASSERT(vertexStride == gp->debugOnly_vertexStride()); GrAAConvexTessellator tess; @@ -901,9 +903,9 @@ private: const GrBuffer* vertexBuffer; int firstVertex; - size_t vertexStride = quadProcessor->getVertexStride(); + SkASSERT(sizeof(QuadVertex) == quadProcessor->debugOnly_vertexStride()); QuadVertex* verts = reinterpret_cast(target->makeVertexSpace( - vertexStride, vertexCount, &vertexBuffer, &firstVertex)); + sizeof(QuadVertex), vertexCount, &vertexBuffer, &firstVertex)); if (!verts) { SkDebugf("Could not allocate vertices\n"); diff --git a/src/gpu/ops/GrAAFillRectOp.cpp b/src/gpu/ops/GrAAFillRectOp.cpp index 5472f11f71..76bc8128cf 100644 --- a/src/gpu/ops/GrAAFillRectOp.cpp +++ b/src/gpu/ops/GrAAFillRectOp.cpp @@ -242,12 +242,19 @@ private: void onPrepareDraws(Target* target) override { using namespace GrDefaultGeoProcFactory; + size_t vertexStride = sizeof(SkPoint) + sizeof(GrColor); Color color(Color::kPremulGrColorAttribute_Type); - Coverage::Type coverageType = fHelper.compatibleWithAlphaAsCoverage() - ? Coverage::kSolid_Type - : Coverage::kAttribute_Type; - LocalCoords lc = fHelper.usesLocalCoords() ? LocalCoords::kHasExplicit_Type - : LocalCoords::kUnused_Type; + Coverage::Type coverageType = Coverage::kSolid_Type; + if (!fHelper.compatibleWithAlphaAsCoverage()) { + coverageType = Coverage::kAttribute_Type; + vertexStride += sizeof(float); + } + LocalCoords lc = LocalCoords::kUnused_Type; + if (fHelper.usesLocalCoords()) { + lc = LocalCoords::kHasExplicit_Type; + vertexStride += sizeof(SkPoint); + } + sk_sp gp = GrDefaultGeoProcFactory::Make(color, coverageType, lc, SkMatrix::I()); if (!gp) { @@ -255,7 +262,7 @@ private: return; } - size_t vertexStride = gp->getVertexStride(); + SkASSERT(vertexStride == gp->debugOnly_vertexStride()); sk_sp indexBuffer = get_index_buffer(target->resourceProvider()); PatternHelper helper(GrPrimitiveType::kTriangles); diff --git a/src/gpu/ops/GrAAHairLinePathRenderer.cpp b/src/gpu/ops/GrAAHairLinePathRenderer.cpp index b62c14b197..89dedc48a4 100644 --- a/src/gpu/ops/GrAAHairLinePathRenderer.cpp +++ b/src/gpu/ops/GrAAHairLinePathRenderer.cpp @@ -959,18 +959,16 @@ void AAHairlineOp::onPrepareDraws(Target* target) { const GrBuffer* vertexBuffer; int firstVertex; - size_t vertexStride = lineGP->getVertexStride(); + SkASSERT(sizeof(LineVertex) == lineGP->debugOnly_vertexStride()); int vertexCount = kLineSegNumVertices * lineCount; - LineVertex* verts = reinterpret_cast( - target->makeVertexSpace(vertexStride, vertexCount, &vertexBuffer, &firstVertex)); + LineVertex* verts = reinterpret_cast(target->makeVertexSpace( + sizeof(LineVertex), vertexCount, &vertexBuffer, &firstVertex)); if (!verts|| !linesIndexBuffer) { SkDebugf("Could not allocate vertices\n"); return; } - SkASSERT(lineGP->getVertexStride() == sizeof(LineVertex)); - for (int i = 0; i < lineCount; ++i) { add_line(&lines[2*i], toSrc, this->coverage(), &verts); } @@ -1004,10 +1002,11 @@ void AAHairlineOp::onPrepareDraws(Target* target) { sk_sp quadsIndexBuffer = get_quads_index_buffer(target->resourceProvider()); - size_t vertexStride = sizeof(BezierVertex); + SkASSERT(sizeof(BezierVertex) == quadGP->debugOnly_vertexStride()); + SkASSERT(sizeof(BezierVertex) == conicGP->debugOnly_vertexStride()); int vertexCount = kQuadNumVertices * quadAndConicCount; - void *vertices = target->makeVertexSpace(vertexStride, vertexCount, - &vertexBuffer, &firstVertex); + void* vertices = target->makeVertexSpace(sizeof(BezierVertex), vertexCount, &vertexBuffer, + &firstVertex); if (!vertices || !quadsIndexBuffer) { SkDebugf("Could not allocate vertices\n"); diff --git a/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp b/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp index 5659099c84..b6b70779ff 100644 --- a/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp +++ b/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp @@ -249,12 +249,10 @@ private: return; } - size_t vertexStride = gp->getVertexStride(); - - SkASSERT(fHelper.compatibleWithAlphaAsCoverage() - ? vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorAttr) - : vertexStride == - sizeof(GrDefaultGeoProcFactory::PositionColorCoverageAttr)); + size_t vertexStride = fHelper.compatibleWithAlphaAsCoverage() + ? sizeof(GrDefaultGeoProcFactory::PositionColorAttr) + : sizeof(GrDefaultGeoProcFactory::PositionColorCoverageAttr); + SkASSERT(vertexStride == gp->debugOnly_vertexStride()); int instanceCount = fPaths.count(); diff --git a/src/gpu/ops/GrAAStrokeRectOp.cpp b/src/gpu/ops/GrAAStrokeRectOp.cpp index b9a6d88021..3347227f04 100644 --- a/src/gpu/ops/GrAAStrokeRectOp.cpp +++ b/src/gpu/ops/GrAAStrokeRectOp.cpp @@ -268,11 +268,11 @@ void AAStrokeRectOp::onPrepareDraws(Target* target) { return; } - size_t vertexStride = gp->getVertexStride(); + size_t vertexStride = fHelper.compatibleWithAlphaAsCoverage() + ? sizeof(GrDefaultGeoProcFactory::PositionColorAttr) + : sizeof(GrDefaultGeoProcFactory::PositionColorCoverageAttr); - SkASSERT(fHelper.compatibleWithAlphaAsCoverage() - ? vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorAttr) - : vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorCoverageAttr)); + SkASSERT(vertexStride == gp->debugOnly_vertexStride()); int innerVertexNum = 4; int outerVertexNum = this->miterStroke() ? 4 : 8; int verticesPerInstance = (outerVertexNum + innerVertexNum) * 2; diff --git a/src/gpu/ops/GrAtlasTextOp.cpp b/src/gpu/ops/GrAtlasTextOp.cpp index 1ea3ddfae6..fc5e5804eb 100644 --- a/src/gpu/ops/GrAtlasTextOp.cpp +++ b/src/gpu/ops/GrAtlasTextOp.cpp @@ -312,8 +312,8 @@ void GrAtlasTextOp::onPrepareDraws(Target* target) { } flushInfo.fGlyphsToFlush = 0; - size_t vertexStride = flushInfo.fGeometryProcessor->getVertexStride(); - SkASSERT(vertexStride == GrTextBlob::GetVertexStride(maskFormat, vmPerspective)); + size_t vertexStride = GrTextBlob::GetVertexStride(maskFormat, vmPerspective); + SkASSERT(vertexStride == flushInfo.fGeometryProcessor->debugOnly_vertexStride()); int glyphCount = this->numGlyphs(); const GrBuffer* vertexBuffer; diff --git a/src/gpu/ops/GrDashOp.cpp b/src/gpu/ops/GrDashOp.cpp index cafb3e54c9..968d169376 100644 --- a/src/gpu/ops/GrDashOp.cpp +++ b/src/gpu/ops/GrDashOp.cpp @@ -626,7 +626,15 @@ private: } QuadHelper helper; - void* vertices = helper.init(target, gp->getVertexStride(), totalRectCount); + size_t vertexStride; + if (fullDash) { + vertexStride = + SkPaint::kRound_Cap == fCap ? sizeof(DashCircleVertex) : sizeof(DashLineVertex); + } else { + vertexStride = sizeof(SkPoint); + } + SkASSERT(vertexStride == gp->debugOnly_vertexStride()); + void* vertices = helper.init(target, vertexStride, totalRectCount); if (!vertices) { return; } @@ -638,15 +646,13 @@ private: if (!draws[i].fLineDone) { if (fullDash) { - setup_dashed_rect(rects[rectIndex], vertices, curVIdx, geom.fSrcRotInv, - draws[i].fStartOffset, draws[i].fDevBloatX, - draws[i].fDevBloatY, draws[i].fLineLength, - draws[i].fHalfDevStroke, draws[i].fIntervals[0], - draws[i].fIntervals[1], draws[i].fStrokeWidth, - capType, gp->getVertexStride()); + setup_dashed_rect( + rects[rectIndex], vertices, curVIdx, geom.fSrcRotInv, + draws[i].fStartOffset, draws[i].fDevBloatX, draws[i].fDevBloatY, + draws[i].fLineLength, draws[i].fHalfDevStroke, draws[i].fIntervals[0], + draws[i].fIntervals[1], draws[i].fStrokeWidth, capType, vertexStride); } else { SkPoint* verts = reinterpret_cast(vertices); - SkASSERT(gp->getVertexStride() == sizeof(SkPoint)); setup_dashed_rect_pos(rects[rectIndex], curVIdx, geom.fSrcRotInv, verts); } curVIdx += 4; @@ -655,15 +661,13 @@ private: if (draws[i].fHasStartRect) { if (fullDash) { - setup_dashed_rect(rects[rectIndex], vertices, curVIdx, geom.fSrcRotInv, - draws[i].fStartOffset, draws[i].fDevBloatX, - draws[i].fDevBloatY, draws[i].fIntervals[0], - draws[i].fHalfDevStroke, draws[i].fIntervals[0], - draws[i].fIntervals[1], draws[i].fStrokeWidth, capType, - gp->getVertexStride()); + setup_dashed_rect( + rects[rectIndex], vertices, curVIdx, geom.fSrcRotInv, + draws[i].fStartOffset, draws[i].fDevBloatX, draws[i].fDevBloatY, + draws[i].fIntervals[0], draws[i].fHalfDevStroke, draws[i].fIntervals[0], + draws[i].fIntervals[1], draws[i].fStrokeWidth, capType, vertexStride); } else { SkPoint* verts = reinterpret_cast(vertices); - SkASSERT(gp->getVertexStride() == sizeof(SkPoint)); setup_dashed_rect_pos(rects[rectIndex], curVIdx, geom.fSrcRotInv, verts); } curVIdx += 4; @@ -672,15 +676,13 @@ private: if (draws[i].fHasEndRect) { if (fullDash) { - setup_dashed_rect(rects[rectIndex], vertices, curVIdx, geom.fSrcRotInv, - draws[i].fStartOffset, draws[i].fDevBloatX, - draws[i].fDevBloatY, draws[i].fIntervals[0], - draws[i].fHalfDevStroke, draws[i].fIntervals[0], - draws[i].fIntervals[1], draws[i].fStrokeWidth, capType, - gp->getVertexStride()); + setup_dashed_rect( + rects[rectIndex], vertices, curVIdx, geom.fSrcRotInv, + draws[i].fStartOffset, draws[i].fDevBloatX, draws[i].fDevBloatY, + draws[i].fIntervals[0], draws[i].fHalfDevStroke, draws[i].fIntervals[0], + draws[i].fIntervals[1], draws[i].fStrokeWidth, capType, vertexStride); } else { SkPoint* verts = reinterpret_cast(vertices); - SkASSERT(gp->getVertexStride() == sizeof(SkPoint)); setup_dashed_rect_pos(rects[rectIndex], curVIdx, geom.fSrcRotInv, verts); } curVIdx += 4; @@ -840,12 +842,6 @@ public: const char* name() const override { return "DashingCircleEffect"; } - const Attribute* inPosition() const { return fInPosition; } - - const Attribute* inDashParams() const { return fInDashParams; } - - const Attribute* inCircleParams() const { return fInCircleParams; } - AAMode aaMode() const { return fAAMode; } GrColor color() const { return fColor; } @@ -862,18 +858,27 @@ private: DashingCircleEffect(GrColor, AAMode aaMode, const SkMatrix& localMatrix, bool usesLocalCoords); + const Attribute& onVertexAttribute(int i) const override { + return IthAttribute(i, kInPosition, kInDashParams, kInCircleParams); + } + GrColor fColor; SkMatrix fLocalMatrix; bool fUsesLocalCoords; AAMode fAAMode; - const Attribute* fInPosition; - const Attribute* fInDashParams; - const Attribute* fInCircleParams; + + static constexpr Attribute kInPosition = {"inPosition", kFloat2_GrVertexAttribType}; + static constexpr Attribute kInDashParams = {"inDashParams", kHalf3_GrVertexAttribType}; + static constexpr Attribute kInCircleParams = {"inCircleParams", kHalf2_GrVertexAttribType}; GR_DECLARE_GEOMETRY_PROCESSOR_TEST + friend class GLDashingCircleEffect; typedef GrGeometryProcessor INHERITED; }; +constexpr GrPrimitiveProcessor::Attribute DashingCircleEffect::kInPosition; +constexpr GrPrimitiveProcessor::Attribute DashingCircleEffect::kInDashParams; +constexpr GrPrimitiveProcessor::Attribute DashingCircleEffect::kInCircleParams; ////////////////////////////////////////////////////////////////////////////// @@ -918,25 +923,25 @@ void GLDashingCircleEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) { // XY are dashPos, Z is dashInterval GrGLSLVarying dashParams(kHalf3_GrSLType); varyingHandler->addVarying("DashParam", &dashParams); - vertBuilder->codeAppendf("%s = %s;", dashParams.vsOut(), dce.inDashParams()->name()); + vertBuilder->codeAppendf("%s = %s;", dashParams.vsOut(), dce.kInDashParams.name()); // x refers to circle radius - 0.5, y refers to cicle's center x coord GrGLSLVarying circleParams(kHalf2_GrSLType); varyingHandler->addVarying("CircleParams", &circleParams); - vertBuilder->codeAppendf("%s = %s;", circleParams.vsOut(), dce.inCircleParams()->name()); + vertBuilder->codeAppendf("%s = %s;", circleParams.vsOut(), dce.kInCircleParams.name()); GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; // Setup pass through color this->setupUniformColor(fragBuilder, uniformHandler, args.fOutputColor, &fColorUniform); // Setup position - this->writeOutputPosition(vertBuilder, gpArgs, dce.inPosition()->name()); + this->writeOutputPosition(vertBuilder, gpArgs, dce.kInPosition.name()); // emit transforms this->emitTransforms(vertBuilder, varyingHandler, uniformHandler, - dce.inPosition()->asShaderVar(), + dce.kInPosition.asShaderVar(), dce.localMatrix(), args.fFPCoordTransformHandler); @@ -1009,9 +1014,7 @@ DashingCircleEffect::DashingCircleEffect(GrColor color, , fLocalMatrix(localMatrix) , fUsesLocalCoords(usesLocalCoords) , fAAMode(aaMode) { - fInPosition = &this->addVertexAttrib("inPosition", kFloat2_GrVertexAttribType); - fInDashParams = &this->addVertexAttrib("inDashParams", kHalf3_GrVertexAttribType); - fInCircleParams = &this->addVertexAttrib("inCircleParams", kHalf2_GrVertexAttribType); + this->setVertexAttributeCnt(3); } GR_DEFINE_GEOMETRY_PROCESSOR_TEST(DashingCircleEffect); @@ -1049,12 +1052,6 @@ public: const char* name() const override { return "DashingEffect"; } - const Attribute* inPosition() const { return fInPosition; } - - const Attribute* inDashParams() const { return fInDashParams; } - - const Attribute* inRectParams() const { return fInRectParams; } - AAMode aaMode() const { return fAAMode; } GrColor color() const { return fColor; } @@ -1071,18 +1068,28 @@ private: DashingLineEffect(GrColor, AAMode aaMode, const SkMatrix& localMatrix, bool usesLocalCoords); + const Attribute& onVertexAttribute(int i) const override { + return IthAttribute(i, kInPosition, kInDashParams, kInRectParams); + } + GrColor fColor; SkMatrix fLocalMatrix; bool fUsesLocalCoords; AAMode fAAMode; - const Attribute* fInPosition; - const Attribute* fInDashParams; - const Attribute* fInRectParams; + + static constexpr Attribute kInPosition = {"inPosition", kFloat2_GrVertexAttribType}; + static constexpr Attribute kInDashParams = {"inDashParams", kHalf3_GrVertexAttribType}; + static constexpr Attribute kInRectParams = {"inRect", kHalf4_GrVertexAttribType}; GR_DECLARE_GEOMETRY_PROCESSOR_TEST + friend class GLDashingLineEffect; + typedef GrGeometryProcessor INHERITED; }; +constexpr GrPrimitiveProcessor::Attribute DashingLineEffect::kInPosition; +constexpr GrPrimitiveProcessor::Attribute DashingLineEffect::kInDashParams; +constexpr GrPrimitiveProcessor::Attribute DashingLineEffect::kInRectParams; ////////////////////////////////////////////////////////////////////////////// @@ -1120,26 +1127,26 @@ void GLDashingLineEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) { // XY refers to dashPos, Z is the dash interval length GrGLSLVarying inDashParams(kFloat3_GrSLType); varyingHandler->addVarying("DashParams", &inDashParams); - vertBuilder->codeAppendf("%s = %s;", inDashParams.vsOut(), de.inDashParams()->name()); + vertBuilder->codeAppendf("%s = %s;", inDashParams.vsOut(), de.kInDashParams.name()); // The rect uniform's xyzw refer to (left + 0.5, top + 0.5, right - 0.5, bottom - 0.5), // respectively. GrGLSLVarying inRectParams(kFloat4_GrSLType); varyingHandler->addVarying("RectParams", &inRectParams); - vertBuilder->codeAppendf("%s = %s;", inRectParams.vsOut(), de.inRectParams()->name()); + vertBuilder->codeAppendf("%s = %s;", inRectParams.vsOut(), de.kInRectParams.name()); GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; // Setup pass through color this->setupUniformColor(fragBuilder, uniformHandler, args.fOutputColor, &fColorUniform); // Setup position - this->writeOutputPosition(vertBuilder, gpArgs, de.inPosition()->name()); + this->writeOutputPosition(vertBuilder, gpArgs, de.kInPosition.name()); // emit transforms this->emitTransforms(vertBuilder, varyingHandler, uniformHandler, - de.inPosition()->asShaderVar(), + de.kInPosition.asShaderVar(), de.localMatrix(), args.fFPCoordTransformHandler); @@ -1230,9 +1237,7 @@ DashingLineEffect::DashingLineEffect(GrColor color, , fLocalMatrix(localMatrix) , fUsesLocalCoords(usesLocalCoords) , fAAMode(aaMode) { - fInPosition = &this->addVertexAttrib("inPosition", kFloat2_GrVertexAttribType); - fInDashParams = &this->addVertexAttrib("inDashParams", kHalf3_GrVertexAttribType); - fInRectParams = &this->addVertexAttrib("inRect", kHalf4_GrVertexAttribType); + this->setVertexAttributeCnt(3); } GR_DEFINE_GEOMETRY_PROCESSOR_TEST(DashingLineEffect); @@ -1244,8 +1249,8 @@ sk_sp DashingLineEffect::TestCreate(GrProcessorTestData* d) aaMode, GrTest::TestMatrix(d->fRandom), d->fRandom->nextBool()); } -#endif +#endif ////////////////////////////////////////////////////////////////////////////// static sk_sp make_dash_gp(GrColor color, diff --git a/src/gpu/ops/GrDefaultPathRenderer.cpp b/src/gpu/ops/GrDefaultPathRenderer.cpp index df6f81f552..aa0963b02a 100644 --- a/src/gpu/ops/GrDefaultPathRenderer.cpp +++ b/src/gpu/ops/GrDefaultPathRenderer.cpp @@ -404,7 +404,7 @@ private: gp = GrDefaultGeoProcFactory::Make(color, coverage, localCoords, this->viewMatrix()); } - SkASSERT(gp->getVertexStride() == sizeof(SkPoint)); + SkASSERT(gp->debugOnly_vertexStride() == sizeof(SkPoint)); int instanceCount = fPaths.count(); diff --git a/src/gpu/ops/GrDrawAtlasOp.cpp b/src/gpu/ops/GrDrawAtlasOp.cpp index fa08e558f3..47bad8b2a4 100644 --- a/src/gpu/ops/GrDrawAtlasOp.cpp +++ b/src/gpu/ops/GrDrawAtlasOp.cpp @@ -122,9 +122,9 @@ void GrDrawAtlasOp::onPrepareDraws(Target* target) { sk_sp gp(make_gp(this->hasColors(), this->color(), this->viewMatrix())); int instanceCount = fGeoData.count(); - size_t vertexStride = gp->getVertexStride(); - SkASSERT(vertexStride == - sizeof(SkPoint) + sizeof(SkPoint) + (this->hasColors() ? sizeof(GrColor) : 0)); + size_t vertexStride = + sizeof(SkPoint) + sizeof(SkPoint) + (this->hasColors() ? sizeof(GrColor) : 0); + SkASSERT(vertexStride == gp->debugOnly_vertexStride()); QuadHelper helper; int numQuads = this->quadCount(); diff --git a/src/gpu/ops/GrDrawVerticesOp.cpp b/src/gpu/ops/GrDrawVerticesOp.cpp index c968611152..8f6ad9745d 100644 --- a/src/gpu/ops/GrDrawVerticesOp.cpp +++ b/src/gpu/ops/GrDrawVerticesOp.cpp @@ -140,10 +140,10 @@ void GrDrawVerticesOp::onPrepareDraws(Target* target) { bool hasColorAttribute; bool hasLocalCoordsAttribute; sk_sp gp = this->makeGP(&hasColorAttribute, &hasLocalCoordsAttribute); - size_t vertexStride = gp->getVertexStride(); - SkASSERT(vertexStride == sizeof(SkPoint) + (hasColorAttribute ? sizeof(uint32_t) : 0) + - (hasLocalCoordsAttribute ? sizeof(SkPoint) : 0)); + size_t vertexStride = sizeof(SkPoint) + (hasColorAttribute ? sizeof(uint32_t) : 0) + + (hasLocalCoordsAttribute ? sizeof(SkPoint) : 0); + SkASSERT(vertexStride == gp->debugOnly_vertexStride()); int instanceCount = fMeshes.count(); diff --git a/src/gpu/ops/GrLatticeOp.cpp b/src/gpu/ops/GrLatticeOp.cpp index 5903231cb2..7bfa72ec94 100644 --- a/src/gpu/ops/GrLatticeOp.cpp +++ b/src/gpu/ops/GrLatticeOp.cpp @@ -62,19 +62,19 @@ public: latticeGP.fColorSpaceXform.get()); args.fVaryingHandler->emitAttributes(latticeGP); - this->writeOutputPosition(args.fVertBuilder, gpArgs, latticeGP.fPositions.name()); + this->writeOutputPosition(args.fVertBuilder, gpArgs, latticeGP.kPositions.name()); this->emitTransforms(args.fVertBuilder, args.fVaryingHandler, args.fUniformHandler, - latticeGP.fTextureCoords.asShaderVar(), + latticeGP.kTextureCoords.asShaderVar(), args.fFPCoordTransformHandler); args.fFragBuilder->codeAppend("float2 textureCoords;"); - args.fVaryingHandler->addPassThroughAttribute(&latticeGP.fTextureCoords, + args.fVaryingHandler->addPassThroughAttribute(latticeGP.kTextureCoords, "textureCoords"); args.fFragBuilder->codeAppend("float4 textureDomain;"); args.fVaryingHandler->addPassThroughAttribute( - &latticeGP.fTextureDomain, "textureDomain", Interpolation::kCanBeFlat); - args.fVaryingHandler->addPassThroughAttribute(&latticeGP.fColors, args.fOutputColor, + latticeGP.kTextureDomain, "textureDomain", Interpolation::kCanBeFlat); + args.fVaryingHandler->addPassThroughAttribute(latticeGP.kColors, args.fOutputColor, Interpolation::kCanBeFlat); args.fFragBuilder->codeAppendf("%s = ", args.fOutputColor); args.fFragBuilder->appendTextureLookupAndModulate( @@ -95,24 +95,31 @@ private: LatticeGP(sk_sp proxy, sk_sp csxf, GrSamplerState::Filter filter) : INHERITED(kLatticeGP_ClassID), fColorSpaceXform(std::move(csxf)) { - fPositions = this->addVertexAttrib("position", kFloat2_GrVertexAttribType); fSampler.reset(std::move(proxy), filter); this->addTextureSampler(&fSampler); - fTextureCoords = this->addVertexAttrib("textureCoords", kFloat2_GrVertexAttribType); - fTextureDomain = this->addVertexAttrib("textureDomain", kFloat4_GrVertexAttribType); - fColors = this->addVertexAttrib("color", kUByte4_norm_GrVertexAttribType); + this->setVertexAttributeCnt(4); } - Attribute fPositions; - Attribute fTextureCoords; - Attribute fTextureDomain; - Attribute fColors; + const Attribute& onVertexAttribute(int i) const override { + return IthAttribute(i, kPositions, kTextureCoords, kTextureDomain, kColors); + } + + static constexpr Attribute kPositions = {"position", kFloat2_GrVertexAttribType}; + static constexpr Attribute kTextureCoords = {"textureCoords", kFloat2_GrVertexAttribType}; + static constexpr Attribute kTextureDomain = {"textureDomain", kFloat4_GrVertexAttribType}; + static constexpr Attribute kColors = {"color", kUByte4_norm_GrVertexAttribType}; + sk_sp fColorSpaceXform; TextureSampler fSampler; typedef GrGeometryProcessor INHERITED; }; +constexpr GrPrimitiveProcessor::Attribute LatticeGP::kPositions; +constexpr GrPrimitiveProcessor::Attribute LatticeGP::kTextureCoords; +constexpr GrPrimitiveProcessor::Attribute LatticeGP::kTextureDomain; +constexpr GrPrimitiveProcessor::Attribute LatticeGP::kColors; + class NonAALatticeOp final : public GrMeshDrawOp { private: using Helper = GrSimpleMeshDrawOpHelper; @@ -200,7 +207,10 @@ private: return; } - size_t vertexStride = gp->getVertexStride(); + static constexpr size_t kVertexStide = + sizeof(SkPoint) + sizeof(SkPoint) + sizeof(SkRect) + sizeof(uint32_t); + SkASSERT(kVertexStide == gp->debugOnly_vertexStride()); + int patchCnt = fPatches.count(); int numRects = 0; for (int i = 0; i < patchCnt; i++) { @@ -213,7 +223,7 @@ private: sk_sp indexBuffer = target->resourceProvider()->refQuadIndexBuffer(); PatternHelper helper(GrPrimitiveType::kTriangles); - void* vertices = helper.init(target, vertexStride, indexBuffer.get(), kVertsPerRect, + void* vertices = helper.init(target, kVertexStide, indexBuffer.get(), kVertsPerRect, kIndicesPerRect, numRects); if (!vertices || !indexBuffer) { SkDebugf("Could not allocate vertices\n"); @@ -241,7 +251,7 @@ private: static const Sk4f kFlipMuls(1.f, -1.f, 1.f, -1.f); while (patch.fIter->next(&srcR, &dstR)) { auto vertices = reinterpret_cast(verts); - SkPointPriv::SetRectTriStrip(&vertices->fPosition, dstR, vertexStride); + SkPointPriv::SetRectTriStrip(&vertices->fPosition, dstR, kVertexStide); Sk4f coords(SkIntToScalar(srcR.fLeft), SkIntToScalar(srcR.fTop), SkIntToScalar(srcR.fRight), SkIntToScalar(srcR.fBottom)); Sk4f domain = coords + kDomainOffsets; @@ -252,7 +262,7 @@ private: domain = SkNx_shuffle<0, 3, 2, 1>(kFlipMuls * domain + kFlipOffsets); } SkPointPriv::SetRectTriStrip(&vertices->fTextureCoords, coords[0], coords[1], - coords[2], coords[3], vertexStride); + coords[2], coords[3], kVertexStide); for (int j = 0; j < kVertsPerRect; ++j) { vertices[j].fTextureDomain = {domain[0], domain[1], domain[2], domain[3]}; } @@ -260,13 +270,13 @@ private: for (int j = 0; j < kVertsPerRect; ++j) { vertices[j].fColor = patch.fColor; } - verts += kVertsPerRect * vertexStride; + verts += kVertsPerRect * kVertexStide; } // If we didn't handle it above, apply the matrix here. if (!isScaleTranslate) { SkPoint* positions = reinterpret_cast(patchVerts); - SkMatrixPriv::MapPointsWithStride(patch.fViewMatrix, positions, vertexStride, + SkMatrixPriv::MapPointsWithStride(patch.fViewMatrix, positions, kVertexStide, kVertsPerRect * patch.fIter->numRectsToDraw()); } } diff --git a/src/gpu/ops/GrNonAAFillRectOp.cpp b/src/gpu/ops/GrNonAAFillRectOp.cpp index 20bd599133..d4ebedc6e1 100644 --- a/src/gpu/ops/GrNonAAFillRectOp.cpp +++ b/src/gpu/ops/GrNonAAFillRectOp.cpp @@ -181,15 +181,16 @@ private: SkDebugf("Couldn't create GrGeometryProcessor\n"); return; } - SkASSERT(gp->getVertexStride() == - sizeof(GrDefaultGeoProcFactory::PositionColorLocalCoordAttr)); - size_t vertexStride = gp->getVertexStride(); + static constexpr size_t kVertexStride = + sizeof(GrDefaultGeoProcFactory::PositionColorLocalCoordAttr); + SkASSERT(kVertexStride == gp->debugOnly_vertexStride()); + int rectCount = fRects.count(); sk_sp indexBuffer = target->resourceProvider()->refQuadIndexBuffer(); PatternHelper helper(GrPrimitiveType::kTriangles); - void* vertices = helper.init(target, vertexStride, indexBuffer.get(), kVertsPerRect, + void* vertices = helper.init(target, kVertexStride, indexBuffer.get(), kVertsPerRect, kIndicesPerRect, rectCount); if (!vertices || !indexBuffer) { SkDebugf("Could not allocate vertices\n"); @@ -198,8 +199,8 @@ private: for (int i = 0; i < rectCount; i++) { intptr_t verts = - reinterpret_cast(vertices) + i * kVertsPerRect * vertexStride; - tesselate(verts, vertexStride, fRects[i].fColor, &fRects[i].fViewMatrix, + reinterpret_cast(vertices) + i * kVertsPerRect * kVertexStride; + tesselate(verts, kVertexStride, fRects[i].fColor, &fRects[i].fViewMatrix, fRects[i].fRect, &fRects[i].fLocalQuad); } helper.recordDraw(target, gp.get(), fHelper.makePipeline(target)); @@ -311,13 +312,11 @@ private: SkDebugf("Couldn't create GrGeometryProcessor\n"); return; } - SkASSERT(fHasLocalRect - ? gp->getVertexStride() == - sizeof(GrDefaultGeoProcFactory::PositionColorLocalCoordAttr) - : gp->getVertexStride() == - sizeof(GrDefaultGeoProcFactory::PositionColorAttr)); + size_t vertexStride = fHasLocalRect + ? sizeof(GrDefaultGeoProcFactory::PositionColorLocalCoordAttr) + : sizeof(GrDefaultGeoProcFactory::PositionColorAttr); + SkASSERT(vertexStride == gp->debugOnly_vertexStride()); - size_t vertexStride = gp->getVertexStride(); int rectCount = fRects.count(); sk_sp indexBuffer = target->resourceProvider()->refQuadIndexBuffer(); diff --git a/src/gpu/ops/GrNonAAStrokeRectOp.cpp b/src/gpu/ops/GrNonAAStrokeRectOp.cpp index 5e00e559e7..11c2f8cda5 100644 --- a/src/gpu/ops/GrNonAAStrokeRectOp.cpp +++ b/src/gpu/ops/GrNonAAStrokeRectOp.cpp @@ -152,9 +152,9 @@ private: fViewMatrix); } - size_t vertexStride = gp->getVertexStride(); + static constexpr size_t kVertexStride = sizeof(GrDefaultGeoProcFactory::PositionAttr); - SkASSERT(vertexStride == sizeof(GrDefaultGeoProcFactory::PositionAttr)); + SkASSERT(kVertexStride == gp->debugOnly_vertexStride()); int vertexCount = kVertsPerHairlineRect; if (fStrokeWidth > 0) { @@ -165,7 +165,7 @@ private: int firstVertex; void* verts = - target->makeVertexSpace(vertexStride, vertexCount, &vertexBuffer, &firstVertex); + target->makeVertexSpace(kVertexStride, vertexCount, &vertexBuffer, &firstVertex); if (!verts) { SkDebugf("Could not allocate vertices\n"); diff --git a/src/gpu/ops/GrOvalOpFactory.cpp b/src/gpu/ops/GrOvalOpFactory.cpp index 7b0e4621e9..1655b76326 100644 --- a/src/gpu/ops/GrOvalOpFactory.cpp +++ b/src/gpu/ops/GrOvalOpFactory.cpp @@ -75,32 +75,26 @@ public: : INHERITED(kCircleGeometryProcessor_ClassID) , fLocalMatrix(localMatrix) , fStroke(stroke) { - fInPosition = &this->addVertexAttrib("inPosition", kFloat2_GrVertexAttribType); - fInColor = &this->addVertexAttrib("inColor", kUByte4_norm_GrVertexAttribType); - fInCircleEdge = &this->addVertexAttrib("inCircleEdge", kFloat4_GrVertexAttribType); + int cnt = 3; if (clipPlane) { - fInClipPlane = &this->addVertexAttrib("inClipPlane", kHalf3_GrVertexAttribType); - } else { - fInClipPlane = nullptr; + fInClipPlane = {"inClipPlane", kHalf3_GrVertexAttribType}; + ++cnt; } if (isectPlane) { - fInIsectPlane = &this->addVertexAttrib("inIsectPlane", kHalf3_GrVertexAttribType); - } else { - fInIsectPlane = nullptr; + fInIsectPlane = {"inIsectPlane", kHalf3_GrVertexAttribType}; + ++cnt; } if (unionPlane) { - fInUnionPlane = &this->addVertexAttrib("inUnionPlane", kHalf3_GrVertexAttribType); - } else { - fInUnionPlane = nullptr; + fInUnionPlane = {"inUnionPlane", kHalf3_GrVertexAttribType}; + ++cnt; } if (roundCaps) { SkASSERT(stroke); SkASSERT(clipPlane); - fInRoundCapCenters = - &this->addVertexAttrib("inRoundCapCenters", kFloat4_GrVertexAttribType); - } else { - fInRoundCapCenters = nullptr; + fInRoundCapCenters = {"inRoundCapCenters", kFloat4_GrVertexAttribType}; + ++cnt; } + this->setVertexAttributeCnt(cnt); } ~CircleGeometryProcessor() override {} @@ -130,23 +124,22 @@ private: // emit attributes varyingHandler->emitAttributes(cgp); fragBuilder->codeAppend("float4 circleEdge;"); - varyingHandler->addPassThroughAttribute(cgp.fInCircleEdge, "circleEdge"); - if (cgp.fInClipPlane) { + varyingHandler->addPassThroughAttribute(cgp.kInCircleEdge, "circleEdge"); + if (cgp.fInClipPlane.isInitialized()) { fragBuilder->codeAppend("half3 clipPlane;"); varyingHandler->addPassThroughAttribute(cgp.fInClipPlane, "clipPlane"); } - if (cgp.fInIsectPlane) { - SkASSERT(cgp.fInClipPlane); + if (cgp.fInIsectPlane.isInitialized()) { fragBuilder->codeAppend("half3 isectPlane;"); varyingHandler->addPassThroughAttribute(cgp.fInIsectPlane, "isectPlane"); } - if (cgp.fInUnionPlane) { - SkASSERT(cgp.fInClipPlane); + if (cgp.fInUnionPlane.isInitialized()) { + SkASSERT(cgp.fInClipPlane.isInitialized()); fragBuilder->codeAppend("half3 unionPlane;"); varyingHandler->addPassThroughAttribute(cgp.fInUnionPlane, "unionPlane"); } GrGLSLVarying capRadius(kFloat_GrSLType); - if (cgp.fInRoundCapCenters) { + if (cgp.fInRoundCapCenters.isInitialized()) { fragBuilder->codeAppend("float4 roundCapCenters;"); varyingHandler->addPassThroughAttribute(cgp.fInRoundCapCenters, "roundCapCenters"); varyingHandler->addVarying("capRadius", &capRadius, @@ -154,20 +147,20 @@ private: // This is the cap radius in normalized space where the outer radius is 1 and // circledEdge.w is the normalized inner radius. vertBuilder->codeAppendf("%s = (1.0 - %s.w) / 2.0;", capRadius.vsOut(), - cgp.fInCircleEdge->name()); + cgp.kInCircleEdge.name()); } // setup pass through color - varyingHandler->addPassThroughAttribute(cgp.fInColor, args.fOutputColor); + varyingHandler->addPassThroughAttribute(cgp.kInColor, args.fOutputColor); // Setup position - this->writeOutputPosition(vertBuilder, gpArgs, cgp.fInPosition->name()); + this->writeOutputPosition(vertBuilder, gpArgs, cgp.kInPosition.name()); // emit transforms this->emitTransforms(vertBuilder, varyingHandler, uniformHandler, - cgp.fInPosition->asShaderVar(), + cgp.kInPosition.asShaderVar(), cgp.fLocalMatrix, args.fFPCoordTransformHandler); @@ -181,22 +174,22 @@ private: fragBuilder->codeAppend("edgeAlpha *= innerAlpha;"); } - if (cgp.fInClipPlane) { + if (cgp.fInClipPlane.isInitialized()) { fragBuilder->codeAppend( "half clip = clamp(circleEdge.z * dot(circleEdge.xy, clipPlane.xy) + " "clipPlane.z, 0.0, 1.0);"); - if (cgp.fInIsectPlane) { + if (cgp.fInIsectPlane.isInitialized()) { fragBuilder->codeAppend( "clip *= clamp(circleEdge.z * dot(circleEdge.xy, isectPlane.xy) + " "isectPlane.z, 0.0, 1.0);"); } - if (cgp.fInUnionPlane) { + if (cgp.fInUnionPlane.isInitialized()) { fragBuilder->codeAppend( "clip += (1.0 - clip)*clamp(circleEdge.z * dot(circleEdge.xy, " "unionPlane.xy) + unionPlane.z, 0.0, 1.0);"); } fragBuilder->codeAppend("edgeAlpha *= clip;"); - if (cgp.fInRoundCapCenters) { + if (cgp.fInRoundCapCenters.isInitialized()) { // We compute coverage of the round caps as circles at the butt caps produced // by the clip planes. The inverse of the clip planes is applied so that there // is no double counting. @@ -220,10 +213,10 @@ private: uint16_t key; key = cgp.fStroke ? 0x01 : 0x0; key |= cgp.fLocalMatrix.hasPerspective() ? 0x02 : 0x0; - key |= cgp.fInClipPlane ? 0x04 : 0x0; - key |= cgp.fInIsectPlane ? 0x08 : 0x0; - key |= cgp.fInUnionPlane ? 0x10 : 0x0; - key |= cgp.fInRoundCapCenters ? 0x20 : 0x0; + key |= cgp.fInClipPlane.isInitialized() ? 0x04 : 0x0; + key |= cgp.fInIsectPlane.isInitialized() ? 0x08 : 0x0; + key |= cgp.fInUnionPlane.isInitialized() ? 0x10 : 0x0; + key |= cgp.fInRoundCapCenters.isInitialized() ? 0x20 : 0x0; b->add32(key); } @@ -237,19 +230,31 @@ private: typedef GrGLSLGeometryProcessor INHERITED; }; + const Attribute& onVertexAttribute(int i) const override { + return IthInitializedAttribute(i, kInPosition, kInColor, kInCircleEdge, fInClipPlane, + fInIsectPlane, fInUnionPlane, fInRoundCapCenters); + } + SkMatrix fLocalMatrix; - const Attribute* fInPosition; - const Attribute* fInColor; - const Attribute* fInCircleEdge; - const Attribute* fInClipPlane; - const Attribute* fInIsectPlane; - const Attribute* fInUnionPlane; - const Attribute* fInRoundCapCenters; + + static constexpr Attribute kInPosition = {"inPosition", kFloat2_GrVertexAttribType}; + static constexpr Attribute kInColor = {"inColor", kUByte4_norm_GrVertexAttribType}; + static constexpr Attribute kInCircleEdge = {"inCircleEdge", kFloat4_GrVertexAttribType}; + + // Optional attributes. + Attribute fInClipPlane; + Attribute fInIsectPlane; + Attribute fInUnionPlane; + Attribute fInRoundCapCenters; + bool fStroke; GR_DECLARE_GEOMETRY_PROCESSOR_TEST typedef GrGeometryProcessor INHERITED; }; +constexpr GrPrimitiveProcessor::Attribute CircleGeometryProcessor::kInPosition; +constexpr GrPrimitiveProcessor::Attribute CircleGeometryProcessor::kInColor; +constexpr GrPrimitiveProcessor::Attribute CircleGeometryProcessor::kInCircleEdge; GR_DEFINE_GEOMETRY_PROCESSOR_TEST(CircleGeometryProcessor); @@ -270,10 +275,7 @@ class ButtCapDashedCircleGeometryProcessor : public GrGeometryProcessor { public: ButtCapDashedCircleGeometryProcessor(const SkMatrix& localMatrix) : INHERITED(kButtCapStrokedCircleGeometryProcessor_ClassID), fLocalMatrix(localMatrix) { - fInPosition = &this->addVertexAttrib("inPosition", kFloat2_GrVertexAttribType); - fInColor = &this->addVertexAttrib("inColor", kUByte4_norm_GrVertexAttribType); - fInCircleEdge = &this->addVertexAttrib("inCircleEdge", kFloat4_GrVertexAttribType); - fInDashParams = &this->addVertexAttrib("inDashParams", kFloat4_GrVertexAttribType); + this->setVertexAttributeCnt(4); } ~ButtCapDashedCircleGeometryProcessor() override {} @@ -304,11 +306,11 @@ private: // emit attributes varyingHandler->emitAttributes(bcscgp); fragBuilder->codeAppend("float4 circleEdge;"); - varyingHandler->addPassThroughAttribute(bcscgp.fInCircleEdge, "circleEdge"); + varyingHandler->addPassThroughAttribute(bcscgp.kInCircleEdge, "circleEdge"); fragBuilder->codeAppend("float4 dashParams;"); varyingHandler->addPassThroughAttribute( - bcscgp.fInDashParams, "dashParams", + bcscgp.kInDashParams, "dashParams", GrGLSLVaryingHandler::Interpolation::kCanBeFlat); GrGLSLVarying wrapDashes(kHalf4_GrSLType); varyingHandler->addVarying("wrapDashes", &wrapDashes, @@ -316,7 +318,7 @@ private: GrGLSLVarying lastIntervalLength(kHalf_GrSLType); varyingHandler->addVarying("lastIntervalLength", &lastIntervalLength, GrGLSLVaryingHandler::Interpolation::kCanBeFlat); - vertBuilder->codeAppendf("float4 dashParams = %s;", bcscgp.fInDashParams->name()); + vertBuilder->codeAppendf("float4 dashParams = %s;", bcscgp.kInDashParams.name()); // Our fragment shader works in on/off intervals as specified by dashParams.xy: // x = length of on interval, y = length of on + off. // There are two other parameters in dashParams.zw: @@ -378,17 +380,17 @@ private: // setup pass through color varyingHandler->addPassThroughAttribute( - bcscgp.fInColor, args.fOutputColor, + bcscgp.kInColor, args.fOutputColor, GrGLSLVaryingHandler::Interpolation::kCanBeFlat); // Setup position - this->writeOutputPosition(vertBuilder, gpArgs, bcscgp.fInPosition->name()); + this->writeOutputPosition(vertBuilder, gpArgs, bcscgp.kInPosition.name()); // emit transforms this->emitTransforms(vertBuilder, varyingHandler, uniformHandler, - bcscgp.fInPosition->asShaderVar(), + bcscgp.kInPosition.asShaderVar(), bcscgp.fLocalMatrix, args.fFPCoordTransformHandler); GrShaderVar fnArgs[] = { @@ -482,16 +484,24 @@ private: typedef GrGLSLGeometryProcessor INHERITED; }; + const Attribute& onVertexAttribute(int i) const override { + return IthAttribute(i, kInPosition, kInColor, kInCircleEdge, kInDashParams); + } + SkMatrix fLocalMatrix; - const Attribute* fInPosition; - const Attribute* fInColor; - const Attribute* fInCircleEdge; - const Attribute* fInDashParams; + static constexpr Attribute kInPosition = {"inPosition", kFloat2_GrVertexAttribType}; + static constexpr Attribute kInColor = {"inColor", kUByte4_norm_GrVertexAttribType}; + static constexpr Attribute kInCircleEdge = {"inCircleEdge", kFloat4_GrVertexAttribType}; + static constexpr Attribute kInDashParams = {"inDashParams", kFloat4_GrVertexAttribType}; GR_DECLARE_GEOMETRY_PROCESSOR_TEST typedef GrGeometryProcessor INHERITED; }; +constexpr GrPrimitiveProcessor::Attribute ButtCapDashedCircleGeometryProcessor::kInPosition; +constexpr GrPrimitiveProcessor::Attribute ButtCapDashedCircleGeometryProcessor::kInColor; +constexpr GrPrimitiveProcessor::Attribute ButtCapDashedCircleGeometryProcessor::kInCircleEdge; +constexpr GrPrimitiveProcessor::Attribute ButtCapDashedCircleGeometryProcessor::kInDashParams; #if GR_TEST_UTILS sk_sp ButtCapDashedCircleGeometryProcessor::TestCreate(GrProcessorTestData* d) { @@ -515,10 +525,7 @@ public: EllipseGeometryProcessor(bool stroke, const SkMatrix& localMatrix) : INHERITED(kEllipseGeometryProcessor_ClassID) , fLocalMatrix(localMatrix) { - fInPosition = &this->addVertexAttrib("inPosition", kFloat2_GrVertexAttribType); - fInColor = &this->addVertexAttrib("inColor", kUByte4_norm_GrVertexAttribType); - fInEllipseOffset = &this->addVertexAttrib("inEllipseOffset", kHalf2_GrVertexAttribType); - fInEllipseRadii = &this->addVertexAttrib("inEllipseRadii", kHalf4_GrVertexAttribType); + this->setVertexAttributeCnt(4); fStroke = stroke; } @@ -551,24 +558,24 @@ private: GrGLSLVarying ellipseOffsets(kHalf2_GrSLType); varyingHandler->addVarying("EllipseOffsets", &ellipseOffsets); vertBuilder->codeAppendf("%s = %s;", ellipseOffsets.vsOut(), - egp.fInEllipseOffset->name()); + egp.kInEllipseOffset.name()); GrGLSLVarying ellipseRadii(kHalf4_GrSLType); varyingHandler->addVarying("EllipseRadii", &ellipseRadii); - vertBuilder->codeAppendf("%s = %s;", ellipseRadii.vsOut(), egp.fInEllipseRadii->name()); + vertBuilder->codeAppendf("%s = %s;", ellipseRadii.vsOut(), egp.kInEllipseRadii.name()); GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; // setup pass through color - varyingHandler->addPassThroughAttribute(egp.fInColor, args.fOutputColor); + varyingHandler->addPassThroughAttribute(egp.kInColor, args.fOutputColor); // Setup position - this->writeOutputPosition(vertBuilder, gpArgs, egp.fInPosition->name()); + this->writeOutputPosition(vertBuilder, gpArgs, egp.kInPosition.name()); // emit transforms this->emitTransforms(vertBuilder, varyingHandler, uniformHandler, - egp.fInPosition->asShaderVar(), + egp.kInPosition.asShaderVar(), egp.fLocalMatrix, args.fFPCoordTransformHandler); @@ -616,10 +623,15 @@ private: typedef GrGLSLGeometryProcessor INHERITED; }; - const Attribute* fInPosition; - const Attribute* fInColor; - const Attribute* fInEllipseOffset; - const Attribute* fInEllipseRadii; + const Attribute& onVertexAttribute(int i) const override { + return IthAttribute(i, kInPosition, kInColor, kInEllipseOffset, kInEllipseRadii); + } + + static constexpr Attribute kInPosition = {"inPosition", kFloat2_GrVertexAttribType}; + static constexpr Attribute kInColor = {"inColor", kUByte4_norm_GrVertexAttribType}; + static constexpr Attribute kInEllipseOffset = {"inEllipseOffset", kHalf2_GrVertexAttribType}; + static constexpr Attribute kInEllipseRadii = {"inEllipseRadii", kHalf4_GrVertexAttribType}; + SkMatrix fLocalMatrix; bool fStroke; @@ -627,6 +639,10 @@ private: typedef GrGeometryProcessor INHERITED; }; +constexpr GrPrimitiveProcessor::Attribute EllipseGeometryProcessor::kInPosition; +constexpr GrPrimitiveProcessor::Attribute EllipseGeometryProcessor::kInColor; +constexpr GrPrimitiveProcessor::Attribute EllipseGeometryProcessor::kInEllipseOffset; +constexpr GrPrimitiveProcessor::Attribute EllipseGeometryProcessor::kInEllipseRadii; GR_DEFINE_GEOMETRY_PROCESSOR_TEST(EllipseGeometryProcessor); @@ -655,11 +671,8 @@ public: DIEllipseGeometryProcessor(const SkMatrix& viewMatrix, DIEllipseStyle style) : INHERITED(kDIEllipseGeometryProcessor_ClassID) , fViewMatrix(viewMatrix) { - fInPosition = &this->addVertexAttrib("inPosition", kFloat2_GrVertexAttribType); - fInColor = &this->addVertexAttrib("inColor", kUByte4_norm_GrVertexAttribType); - fInEllipseOffsets0 = &this->addVertexAttrib("inEllipseOffsets0", kHalf2_GrVertexAttribType); - fInEllipseOffsets1 = &this->addVertexAttrib("inEllipseOffsets1", kHalf2_GrVertexAttribType); fStyle = style; + this->setVertexAttributeCnt(4); } ~DIEllipseGeometryProcessor() override {} @@ -690,22 +703,20 @@ private: GrGLSLVarying offsets0(kHalf2_GrSLType); varyingHandler->addVarying("EllipseOffsets0", &offsets0); - vertBuilder->codeAppendf("%s = %s;", offsets0.vsOut(), - diegp.fInEllipseOffsets0->name()); + vertBuilder->codeAppendf("%s = %s;", offsets0.vsOut(), diegp.kInEllipseOffsets0.name()); GrGLSLVarying offsets1(kHalf2_GrSLType); varyingHandler->addVarying("EllipseOffsets1", &offsets1); - vertBuilder->codeAppendf("%s = %s;", offsets1.vsOut(), - diegp.fInEllipseOffsets1->name()); + vertBuilder->codeAppendf("%s = %s;", offsets1.vsOut(), diegp.kInEllipseOffsets1.name()); GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; - varyingHandler->addPassThroughAttribute(diegp.fInColor, args.fOutputColor); + varyingHandler->addPassThroughAttribute(diegp.kInColor, args.fOutputColor); // Setup position this->writeOutputPosition(vertBuilder, uniformHandler, gpArgs, - diegp.fInPosition->name(), + diegp.kInPosition.name(), diegp.fViewMatrix, &fViewMatrixUniform); @@ -713,7 +724,7 @@ private: this->emitTransforms(vertBuilder, varyingHandler, uniformHandler, - diegp.fInPosition->asShaderVar(), + diegp.kInPosition.asShaderVar(), args.fFPCoordTransformHandler); // for outer curve @@ -784,10 +795,17 @@ private: typedef GrGLSLGeometryProcessor INHERITED; }; - const Attribute* fInPosition; - const Attribute* fInColor; - const Attribute* fInEllipseOffsets0; - const Attribute* fInEllipseOffsets1; + const Attribute& onVertexAttribute(int i) const override { + return IthAttribute(i, kInPosition, kInColor, kInEllipseOffsets0, kInEllipseOffsets1); + } + + static constexpr Attribute kInPosition = {"inPosition", kFloat2_GrVertexAttribType}; + static constexpr Attribute kInColor = {"inColor", kUByte4_norm_GrVertexAttribType}; + static constexpr Attribute kInEllipseOffsets0 = {"inEllipseOffsets0", + kHalf2_GrVertexAttribType}; + static constexpr Attribute kInEllipseOffsets1 = {"inEllipseOffsets1", + kHalf2_GrVertexAttribType}; + SkMatrix fViewMatrix; DIEllipseStyle fStyle; @@ -795,6 +813,10 @@ private: typedef GrGeometryProcessor INHERITED; }; +constexpr GrPrimitiveProcessor::Attribute DIEllipseGeometryProcessor::kInPosition; +constexpr GrPrimitiveProcessor::Attribute DIEllipseGeometryProcessor::kInColor; +constexpr GrPrimitiveProcessor::Attribute DIEllipseGeometryProcessor::kInEllipseOffsets0; +constexpr GrPrimitiveProcessor::Attribute DIEllipseGeometryProcessor::kInEllipseOffsets1; GR_DEFINE_GEOMETRY_PROCESSOR_TEST(DIEllipseGeometryProcessor); @@ -1144,11 +1166,11 @@ private: auto vertexCapCenters = [numPlanes](CircleVertex* v) { return (void*)(v->fHalfPlanes + numPlanes); }; - size_t vertexStride = gp->getVertexStride(); - SkASSERT(vertexStride == sizeof(CircleVertex) - (fClipPlane ? 0 : 3 * sizeof(SkScalar)) - - (fClipPlaneIsect ? 0 : 3 * sizeof(SkScalar)) - - (fClipPlaneUnion ? 0 : 3 * sizeof(SkScalar)) + - (fRoundCaps ? 2 * sizeof(SkPoint) : 0)); + size_t vertexStride = sizeof(CircleVertex) - (fClipPlane ? 0 : 3 * sizeof(SkScalar)) - + (fClipPlaneIsect ? 0 : 3 * sizeof(SkScalar)) - + (fClipPlaneUnion ? 0 : 3 * sizeof(SkScalar)) + + (fRoundCaps ? 2 * sizeof(SkPoint) : 0); + SkASSERT(vertexStride == gp->debugOnly_vertexStride()); const GrBuffer* vertexBuffer; int firstVertex; @@ -1632,12 +1654,12 @@ private: SkScalar fPhaseAngle; }; - size_t vertexStride = gp->getVertexStride(); - SkASSERT(vertexStride == sizeof(CircleVertex)); + static constexpr size_t kVertexStride = sizeof(CircleVertex); + SkASSERT(kVertexStride == gp->debugOnly_vertexStride()); const GrBuffer* vertexBuffer; int firstVertex; - char* vertices = (char*)target->makeVertexSpace(vertexStride, fVertCount, &vertexBuffer, + char* vertices = (char*)target->makeVertexSpace(kVertexStride, fVertCount, &vertexBuffer, &firstVertex); if (!vertices) { SkDebugf("Could not allocate vertices\n"); @@ -1688,7 +1710,7 @@ private: SkPoint center = SkPoint::Make(bounds.centerX(), bounds.centerY()); SkScalar halfWidth = 0.5f * bounds.width(); auto init_outer_vertex = [&](int idx, SkScalar x, SkScalar y) { - CircleVertex* v = reinterpret_cast(vertices + idx * vertexStride); + CircleVertex* v = reinterpret_cast(vertices + idx * kVertexStride); v->fPos = center + SkPoint{x * halfWidth, y * halfWidth}; v->fOffset = {x, y}; init_const_attrs_and_reflect(v); @@ -1706,7 +1728,7 @@ private: // Compute the vertices of the inner octagon. auto init_inner_vertex = [&](int idx, SkScalar x, SkScalar y) { CircleVertex* v = - reinterpret_cast(vertices + (idx + 8) * vertexStride); + reinterpret_cast(vertices + (idx + 8) * kVertexStride); v->fPos = center + SkPoint{x * circle.fInnerRadius, y * circle.fInnerRadius}; v->fOffset = {x * normInnerRadius, y * normInnerRadius}; init_const_attrs_and_reflect(v); @@ -1732,7 +1754,7 @@ private: } currStartVertex += circle_type_to_vert_count(true); - vertices += circle_type_to_vert_count(true) * vertexStride; + vertices += circle_type_to_vert_count(true) * kVertexStride; } GrMesh mesh(GrPrimitiveType::kTriangles); @@ -1934,10 +1956,9 @@ private: sk_sp gp(new EllipseGeometryProcessor(fStroked, localMatrix)); QuadHelper helper; - size_t vertexStride = gp->getVertexStride(); - SkASSERT(vertexStride == sizeof(EllipseVertex)); + SkASSERT(sizeof(EllipseVertex) == gp->debugOnly_vertexStride()); EllipseVertex* verts = reinterpret_cast( - helper.init(target, vertexStride, fEllipses.count())); + helper.init(target, sizeof(EllipseVertex), fEllipses.count())); if (!verts) { return; } @@ -2163,11 +2184,10 @@ private: sk_sp gp( new DIEllipseGeometryProcessor(this->viewMatrix(), this->style())); - size_t vertexStride = gp->getVertexStride(); - SkASSERT(vertexStride == sizeof(DIEllipseVertex)); + SkASSERT(sizeof(DIEllipseVertex) == gp->debugOnly_vertexStride()); QuadHelper helper; DIEllipseVertex* verts = reinterpret_cast( - helper.init(target, vertexStride, fEllipses.count())); + helper.init(target, sizeof(DIEllipseVertex), fEllipses.count())); if (!verts) { return; } @@ -2578,14 +2598,13 @@ private: sk_sp gp( new CircleGeometryProcessor(!fAllFill, false, false, false, false, localMatrix)); - size_t vertexStride = gp->getVertexStride(); - SkASSERT(sizeof(CircleVertex) == vertexStride); + SkASSERT(sizeof(CircleVertex) == gp->debugOnly_vertexStride()); const GrBuffer* vertexBuffer; int firstVertex; - CircleVertex* verts = (CircleVertex*)target->makeVertexSpace(vertexStride, fVertCount, - &vertexBuffer, &firstVertex); + CircleVertex* verts = (CircleVertex*)target->makeVertexSpace( + sizeof(CircleVertex), fVertCount, &vertexBuffer, &firstVertex); if (!verts) { SkDebugf("Could not allocate vertices\n"); return; @@ -2867,8 +2886,7 @@ private: // Setup geometry processor sk_sp gp(new EllipseGeometryProcessor(fStroked, localMatrix)); - size_t vertexStride = gp->getVertexStride(); - SkASSERT(vertexStride == sizeof(EllipseVertex)); + SkASSERT(sizeof(EllipseVertex) == gp->debugOnly_vertexStride()); // drop out the middle quad if we're stroked int indicesPerInstance = fStroked ? kIndicesPerStrokeRRect : kIndicesPerFillRRect; @@ -2877,8 +2895,8 @@ private: PatternHelper helper(GrPrimitiveType::kTriangles); EllipseVertex* verts = reinterpret_cast( - helper.init(target, vertexStride, indexBuffer.get(), kVertsPerStandardRRect, - indicesPerInstance, fRRects.count())); + helper.init(target, sizeof(EllipseVertex), indexBuffer.get(), + kVertsPerStandardRRect, indicesPerInstance, fRRects.count())); if (!verts || !indexBuffer) { SkDebugf("Could not allocate vertices\n"); return; diff --git a/src/gpu/ops/GrRegionOp.cpp b/src/gpu/ops/GrRegionOp.cpp index 9e81d66730..9a9814e0be 100644 --- a/src/gpu/ops/GrRegionOp.cpp +++ b/src/gpu/ops/GrRegionOp.cpp @@ -115,7 +115,8 @@ private: SkDebugf("Couldn't create GrGeometryProcessor\n"); return; } - SkASSERT(gp->getVertexStride() == sizeof(GrDefaultGeoProcFactory::PositionColorAttr)); + static constexpr size_t kVertexStride = sizeof(GrDefaultGeoProcFactory::PositionColorAttr); + SkASSERT(kVertexStride == gp->debugOnly_vertexStride()); int numRegions = fRegions.count(); int numRects = 0; @@ -126,12 +127,10 @@ private: if (!numRects) { return; } - size_t vertexStride = gp->getVertexStride(); sk_sp indexBuffer = target->resourceProvider()->refQuadIndexBuffer(); PatternHelper helper(GrPrimitiveType::kTriangles); - void* vertices = - helper.init(target, vertexStride, indexBuffer.get(), kVertsPerInstance, - kIndicesPerInstance, numRects); + void* vertices = helper.init(target, kVertexStride, indexBuffer.get(), kVertsPerInstance, + kIndicesPerInstance, numRects); if (!vertices || !indexBuffer) { SkDebugf("Could not allocate vertices\n"); return; @@ -139,9 +138,9 @@ private: intptr_t verts = reinterpret_cast(vertices); for (int i = 0; i < numRegions; i++) { - tesselate_region(verts, vertexStride, fRegions[i].fColor, fRegions[i].fRegion); + tesselate_region(verts, kVertexStride, fRegions[i].fColor, fRegions[i].fRegion); int numRectsInRegion = fRegions[i].fRegion.computeRegionComplexity(); - verts += numRectsInRegion * kVertsPerInstance * vertexStride; + verts += numRectsInRegion * kVertsPerInstance * kVertexStride; } helper.recordDraw(target, gp.get(), fHelper.makePipeline(target)); } diff --git a/src/gpu/ops/GrShadowRRectOp.cpp b/src/gpu/ops/GrShadowRRectOp.cpp index f61d11dd53..afb084dc36 100644 --- a/src/gpu/ops/GrShadowRRectOp.cpp +++ b/src/gpu/ops/GrShadowRRectOp.cpp @@ -576,13 +576,12 @@ private: sk_sp gp = GrRRectShadowGeoProc::Make(); int instanceCount = fGeoData.count(); - size_t vertexStride = gp->getVertexStride(); - SkASSERT(sizeof(CircleVertex) == vertexStride); + SkASSERT(sizeof(CircleVertex) == gp->debugOnly_vertexStride()); const GrBuffer* vertexBuffer; int firstVertex; - CircleVertex* verts = (CircleVertex*)target->makeVertexSpace(vertexStride, fVertCount, - &vertexBuffer, &firstVertex); + CircleVertex* verts = (CircleVertex*)target->makeVertexSpace( + sizeof(CircleVertex), fVertCount, &vertexBuffer, &firstVertex); if (!verts) { SkDebugf("Could not allocate vertices\n"); return; diff --git a/src/gpu/ops/GrSmallPathRenderer.cpp b/src/gpu/ops/GrSmallPathRenderer.cpp index 4ffe47855e..a0c9f9cf2b 100644 --- a/src/gpu/ops/GrSmallPathRenderer.cpp +++ b/src/gpu/ops/GrSmallPathRenderer.cpp @@ -351,8 +351,9 @@ private: } // allocate vertices - size_t vertexStride = flushInfo.fGeometryProcessor->getVertexStride(); - SkASSERT(vertexStride == sizeof(SkPoint) + sizeof(GrColor) + 2*sizeof(uint16_t)); + static constexpr size_t kVertexStride = + sizeof(SkPoint) + sizeof(GrColor) + 2 * sizeof(uint16_t); + SkASSERT(kVertexStride == flushInfo.fGeometryProcessor->debugOnly_vertexStride()); const GrBuffer* vertexBuffer; @@ -361,7 +362,7 @@ private: if (instanceCount > SK_MaxS32 / kVerticesPerQuad) { return; } - void* vertices = target->makeVertexSpace(vertexStride, + void* vertices = target->makeVertexSpace(kVertexStride, kVerticesPerQuad * instanceCount, &vertexBuffer, &flushInfo.fVertexOffset); @@ -476,13 +477,9 @@ private: auto uploadTarget = target->deferredUploadTarget(); fAtlas->setLastUseToken(shapeData->fID, uploadTarget->tokenTracker()->nextDrawToken()); - this->writePathVertices(fAtlas, - offset, - args.fColor, - vertexStride, - args.fViewMatrix, - shapeData); - offset += kVerticesPerQuad * vertexStride; + this->writePathVertices( + fAtlas, offset, args.fColor, kVertexStride, args.fViewMatrix, shapeData); + offset += kVerticesPerQuad * kVertexStride; flushInfo.fInstancesToFlush++; } diff --git a/src/gpu/ops/GrTessellatingPathRenderer.cpp b/src/gpu/ops/GrTessellatingPathRenderer.cpp index 51dac5adff..4c436c291d 100644 --- a/src/gpu/ops/GrTessellatingPathRenderer.cpp +++ b/src/gpu/ops/GrTessellatingPathRenderer.cpp @@ -237,7 +237,7 @@ private: return path; } - void draw(Target* target, const GrGeometryProcessor* gp) { + void draw(Target* target, const GrGeometryProcessor* gp, size_t vertexStride) { SkASSERT(!fAntiAlias); GrResourceProvider* rp = target->resourceProvider(); bool inverseFill = fShape.inverseFilled(); @@ -274,7 +274,7 @@ private: vmi.mapRect(&clipBounds); bool isLinear; bool canMapVB = GrCaps::kNone_MapFlags != target->caps().mapBufferFlags(); - StaticVertexAllocator allocator(gp->getVertexStride(), rp, canMapVB); + StaticVertexAllocator allocator(vertexStride, rp, canMapVB); int count = GrTessellator::PathToTriangles(getPath(), tol, clipBounds, &allocator, false, GrColor(), false, &isLinear); if (count == 0) { @@ -289,7 +289,7 @@ private: fShape.addGenIDChangeListener(sk_make_sp(key)); } - void drawAA(Target* target, const GrGeometryProcessor* gp) { + void drawAA(Target* target, const GrGeometryProcessor* gp, size_t vertexStride) { SkASSERT(fAntiAlias); SkPath path = getPath(); if (path.isEmpty()) { @@ -299,7 +299,7 @@ private: path.transform(fViewMatrix); SkScalar tol = GrPathUtils::kDefaultTolerance; bool isLinear; - DynamicVertexAllocator allocator(gp->getVertexStride(), target); + DynamicVertexAllocator allocator(vertexStride, target); int count = GrTessellator::PathToTriangles(path, tol, clipBounds, &allocator, true, fColor, fHelper.compatibleWithAlphaAsCoverage(), &isLinear); @@ -311,9 +311,12 @@ private: void onPrepareDraws(Target* target) override { sk_sp gp; + size_t vertexStride; { using namespace GrDefaultGeoProcFactory; + vertexStride = sizeof(SkPoint); // position + Color color(fColor); LocalCoords::Type localCoordsType = fHelper.usesLocalCoords() ? LocalCoords::kUsePosition_Type @@ -321,10 +324,12 @@ private: Coverage::Type coverageType; if (fAntiAlias) { color = Color(Color::kPremulGrColorAttribute_Type); + vertexStride += sizeof(uint32_t); if (fHelper.compatibleWithAlphaAsCoverage()) { coverageType = Coverage::kSolid_Type; } else { coverageType = Coverage::kAttribute_Type; + vertexStride += 4; } } else { coverageType = Coverage::kSolid_Type; @@ -340,10 +345,11 @@ private: if (!gp.get()) { return; } + SkASSERT(vertexStride == gp->debugOnly_vertexStride()); if (fAntiAlias) { - this->drawAA(target, gp.get()); + this->drawAA(target, gp.get(), vertexStride); } else { - this->draw(target, gp.get()); + this->draw(target, gp.get(), vertexStride); } } diff --git a/src/gpu/ops/GrTextureOp.cpp b/src/gpu/ops/GrTextureOp.cpp index e06d94f806..a895230241 100644 --- a/src/gpu/ops/GrTextureOp.cpp +++ b/src/gpu/ops/GrTextureOp.cpp @@ -163,16 +163,14 @@ public: args.fUniformHandler, textureGP.fTextureCoords.asShaderVar(), args.fFPCoordTransformHandler); - args.fVaryingHandler->addPassThroughAttribute(&textureGP.fColors, - args.fOutputColor, - Interpolation::kCanBeFlat); + args.fVaryingHandler->addPassThroughAttribute( + textureGP.fColors, args.fOutputColor, Interpolation::kCanBeFlat); args.fFragBuilder->codeAppend("float2 texCoord;"); - args.fVaryingHandler->addPassThroughAttribute(&textureGP.fTextureCoords, - "texCoord"); + args.fVaryingHandler->addPassThroughAttribute(textureGP.fTextureCoords, "texCoord"); if (textureGP.fDomain.isInitialized()) { args.fFragBuilder->codeAppend("float4 domain;"); args.fVaryingHandler->addPassThroughAttribute( - &textureGP.fDomain, "domain", + textureGP.fDomain, "domain", GrGLSLVaryingHandler::Interpolation::kCanBeFlat); args.fFragBuilder->codeAppend( "texCoord = clamp(texCoord, domain.xy, domain.zw);"); @@ -182,7 +180,7 @@ public: SkASSERT(kInt_GrVertexAttribType == textureGP.fTextureIdx.type()); SkASSERT(args.fShaderCaps->integerSupport()); args.fFragBuilder->codeAppend("int texIdx;"); - args.fVaryingHandler->addPassThroughAttribute(&textureGP.fTextureIdx, "texIdx", + args.fVaryingHandler->addPassThroughAttribute(textureGP.fTextureIdx, "texIdx", Interpolation::kMustBeFlat); args.fFragBuilder->codeAppend("switch (texIdx) {"); for (int i = 0; i < textureGP.numTextureSamplers(); ++i) { @@ -316,12 +314,13 @@ private: } if (perspective) { - fPositions = this->addVertexAttrib("position", kFloat3_GrVertexAttribType); + fPositions = {"position", kFloat3_GrVertexAttribType}; } else { - fPositions = this->addVertexAttrib("position", kFloat2_GrVertexAttribType); + fPositions = {"position", kFloat2_GrVertexAttribType}; } - fColors = this->addVertexAttrib("color", kUByte4_norm_GrVertexAttribType); - fTextureCoords = this->addVertexAttrib("textureCoords", kFloat2_GrVertexAttribType); + fColors = {"color", kUByte4_norm_GrVertexAttribType}; + fTextureCoords = {"textureCoords", kFloat2_GrVertexAttribType}; + int vertexAttributeCnt = 3; if (samplerCnt > 1) { // Here we initialize any extra samplers by repeating the last one samplerCnt - proxyCnt @@ -332,17 +331,26 @@ private: this->addTextureSampler(&fSamplers[i]); } SkASSERT(caps.integerSupport()); - fTextureIdx = this->addVertexAttrib("textureIdx", kInt_GrVertexAttribType); + fTextureIdx = {"textureIdx", kInt_GrVertexAttribType}; + ++vertexAttributeCnt; } if (domain == Domain::kYes) { - fDomain = this->addVertexAttrib("domain", kFloat4_GrVertexAttribType); + fDomain = {"domain", kFloat4_GrVertexAttribType}; + ++vertexAttributeCnt; } if (coverageAA) { - fAAEdges[0] = this->addVertexAttrib("aaEdge0", kFloat3_GrVertexAttribType); - fAAEdges[1] = this->addVertexAttrib("aaEdge1", kFloat3_GrVertexAttribType); - fAAEdges[2] = this->addVertexAttrib("aaEdge2", kFloat3_GrVertexAttribType); - fAAEdges[3] = this->addVertexAttrib("aaEdge3", kFloat3_GrVertexAttribType); + fAAEdges[0] = {"aaEdge0", kFloat3_GrVertexAttribType}; + fAAEdges[1] = {"aaEdge1", kFloat3_GrVertexAttribType}; + fAAEdges[2] = {"aaEdge2", kFloat3_GrVertexAttribType}; + fAAEdges[3] = {"aaEdge3", kFloat3_GrVertexAttribType}; + vertexAttributeCnt += 4; } + this->setVertexAttributeCnt(vertexAttributeCnt); + } + + const Attribute& onVertexAttribute(int i) const override { + return IthInitializedAttribute(i, fPositions, fColors, fTextureCoords, fTextureIdx, fDomain, + fAAEdges[0], fAAEdges[1], fAAEdges[2], fAAEdges[3]); } Attribute fPositions; @@ -746,7 +754,7 @@ __attribute__((no_sanitize("float-cast-overflow"))) template void tess(void* v, const float iw[], const float ih[], const GrGeometryProcessor* gp) { using Vertex = TextureGeometryProcessor::Vertex; - SkASSERT(gp->getVertexStride() == sizeof(Vertex)); + SkASSERT(gp->debugOnly_vertexStride() == sizeof(Vertex)); auto vertices = static_cast(v); auto proxies = this->proxies(); auto filters = this->filters(); @@ -787,10 +795,47 @@ __attribute__((no_sanitize("float-cast-overflow"))) const GrPipeline* pipeline = target->allocPipeline(args, GrProcessorSet::MakeEmptySet(), target->detachAppliedClip()); + using TessFn = + decltype(&TextureOp::tess); +#define TESS_FN_AND_VERTEX_SIZE(Point, MT, Domain, AA) \ + { \ + &TextureOp::tess, \ + sizeof(TextureGeometryProcessor::Vertex) \ + } + static constexpr struct { + TessFn fTessFn; + size_t fVertexSize; + } kTessFnsAndVertexSizes[] = { + TESS_FN_AND_VERTEX_SIZE(SkPoint, MultiTexture::kNo, Domain::kNo, GrAA::kNo), + TESS_FN_AND_VERTEX_SIZE(SkPoint, MultiTexture::kNo, Domain::kNo, GrAA::kYes), + TESS_FN_AND_VERTEX_SIZE(SkPoint, MultiTexture::kNo, Domain::kYes, GrAA::kNo), + TESS_FN_AND_VERTEX_SIZE(SkPoint, MultiTexture::kNo, Domain::kYes, GrAA::kYes), + TESS_FN_AND_VERTEX_SIZE(SkPoint, MultiTexture::kYes, Domain::kNo, GrAA::kNo), + TESS_FN_AND_VERTEX_SIZE(SkPoint, MultiTexture::kYes, Domain::kNo, GrAA::kYes), + TESS_FN_AND_VERTEX_SIZE(SkPoint, MultiTexture::kYes, Domain::kYes, GrAA::kNo), + TESS_FN_AND_VERTEX_SIZE(SkPoint, MultiTexture::kYes, Domain::kYes, GrAA::kYes), + TESS_FN_AND_VERTEX_SIZE(SkPoint3, MultiTexture::kNo, Domain::kNo, GrAA::kNo), + TESS_FN_AND_VERTEX_SIZE(SkPoint3, MultiTexture::kNo, Domain::kNo, GrAA::kYes), + TESS_FN_AND_VERTEX_SIZE(SkPoint3, MultiTexture::kNo, Domain::kYes, GrAA::kNo), + TESS_FN_AND_VERTEX_SIZE(SkPoint3, MultiTexture::kNo, Domain::kYes, GrAA::kYes), + TESS_FN_AND_VERTEX_SIZE(SkPoint3, MultiTexture::kYes, Domain::kNo, GrAA::kNo), + TESS_FN_AND_VERTEX_SIZE(SkPoint3, MultiTexture::kYes, Domain::kNo, GrAA::kYes), + TESS_FN_AND_VERTEX_SIZE(SkPoint3, MultiTexture::kYes, Domain::kYes, GrAA::kNo), + TESS_FN_AND_VERTEX_SIZE(SkPoint3, MultiTexture::kYes, Domain::kYes, GrAA::kYes), + }; +#undef TESS_FN_AND_VERTEX_SIZE + int tessFnIdx = 0; + tessFnIdx |= coverageAA ? 0x1 : 0x0; + tessFnIdx |= fDomain ? 0x2 : 0x0; + tessFnIdx |= (fProxyCnt > 1) ? 0x4 : 0x0; + tessFnIdx |= fPerspective ? 0x8 : 0x0; + + SkASSERT(kTessFnsAndVertexSizes[tessFnIdx].fVertexSize == gp->debugOnly_vertexStride()); + int vstart; const GrBuffer* vbuffer; - void* vdata = target->makeVertexSpace(gp->getVertexStride(), 4 * fDraws.count(), &vbuffer, - &vstart); + void* vdata = target->makeVertexSpace(kTessFnsAndVertexSizes[tessFnIdx].fVertexSize, + 4 * fDraws.count(), &vbuffer, &vstart); if (!vdata) { SkDebugf("Could not allocate vertices\n"); return; @@ -804,32 +849,7 @@ __attribute__((no_sanitize("float-cast-overflow"))) ih[t] = 1.f / texture->height(); } - using TessFn = - decltype(&TextureOp::tess); - static constexpr TessFn kTessFns[] = { - &TextureOp::tess, - &TextureOp::tess, - &TextureOp::tess, - &TextureOp::tess, - &TextureOp::tess, - &TextureOp::tess, - &TextureOp::tess, - &TextureOp::tess, - &TextureOp::tess, - &TextureOp::tess, - &TextureOp::tess, - &TextureOp::tess, - &TextureOp::tess, - &TextureOp::tess, - &TextureOp::tess, - &TextureOp::tess, - }; - int tessFnIdx = 0; - tessFnIdx |= coverageAA ? 0x1 : 0x0; - tessFnIdx |= fDomain ? 0x2 : 0x0; - tessFnIdx |= (fProxyCnt > 1) ? 0x4 : 0x0; - tessFnIdx |= fPerspective ? 0x8 : 0x0; - (this->*(kTessFns[tessFnIdx]))(vdata, iw, ih, gp.get()); + (this->*(kTessFnsAndVertexSizes[tessFnIdx].fTessFn))(vdata, iw, ih, gp.get()); GrPrimitiveType primitiveType = fDraws.count() > 1 ? GrPrimitiveType::kTriangles : GrPrimitiveType::kTriangleStrip; diff --git a/src/gpu/vk/GrVkPipeline.cpp b/src/gpu/vk/GrVkPipeline.cpp index 500ab967cc..c5b4592950 100644 --- a/src/gpu/vk/GrVkPipeline.cpp +++ b/src/gpu/vk/GrVkPipeline.cpp @@ -59,37 +59,58 @@ static void setup_vertex_input_state(const GrPrimitiveProcessor& primProc, VkVertexInputAttributeDescription* attributeDesc) { uint32_t vertexBinding = 0, instanceBinding = 0; - if (primProc.hasVertexAttribs()) { - vertexBinding = bindingDescs->count(); - bindingDescs->push_back() = { - vertexBinding, - (uint32_t) primProc.getVertexStride(), - VK_VERTEX_INPUT_RATE_VERTEX - }; + int nextBinding = bindingDescs->count(); + if (primProc.hasVertexAttributes()) { + vertexBinding = nextBinding++; } - if (primProc.hasInstanceAttribs()) { - instanceBinding = bindingDescs->count(); - bindingDescs->push_back() = { - instanceBinding, - (uint32_t) primProc.getInstanceStride(), - VK_VERTEX_INPUT_RATE_INSTANCE - }; + if (primProc.hasInstanceAttributes()) { + instanceBinding = nextBinding; } // setup attribute descriptions - int vaCount = primProc.numAttribs(); - if (vaCount > 0) { - for (int attribIndex = 0; attribIndex < vaCount; attribIndex++) { - using InputRate = GrPrimitiveProcessor::Attribute::InputRate; - const GrGeometryProcessor::Attribute& attrib = primProc.getAttrib(attribIndex); - VkVertexInputAttributeDescription& vkAttrib = attributeDesc[attribIndex]; - vkAttrib.location = attribIndex; // for now assume location = attribIndex - vkAttrib.binding = - InputRate::kPerInstance == attrib.inputRate() ? instanceBinding : vertexBinding; - vkAttrib.format = attrib_type_to_vkformat(attrib.type()); - vkAttrib.offset = attrib.offsetInRecord(); - } + int vaCount = primProc.numVertexAttributes(); + int attribIndex = 0; + size_t vertexAttributeOffset = 0; + for (; attribIndex < vaCount; attribIndex++) { + const GrGeometryProcessor::Attribute& attrib = primProc.vertexAttribute(attribIndex); + VkVertexInputAttributeDescription& vkAttrib = attributeDesc[attribIndex]; + vkAttrib.location = attribIndex; // for now assume location = attribIndex + vkAttrib.binding = vertexBinding; + vkAttrib.format = attrib_type_to_vkformat(attrib.type()); + vkAttrib.offset = vertexAttributeOffset; + SkASSERT(vkAttrib.offset == primProc.debugOnly_vertexAttributeOffset(attribIndex)); + vertexAttributeOffset += attrib.sizeAlign4(); + } + SkASSERT(vertexAttributeOffset == primProc.debugOnly_vertexStride()); + + int iaCount = primProc.numInstanceAttributes(); + size_t instanceAttributeOffset = 0; + for (int iaIndex = 0; iaIndex < iaCount; ++iaIndex, ++attribIndex) { + const GrGeometryProcessor::Attribute& attrib = primProc.instanceAttribute(iaIndex); + VkVertexInputAttributeDescription& vkAttrib = attributeDesc[attribIndex]; + vkAttrib.location = attribIndex; // for now assume location = attribIndex + vkAttrib.binding = instanceBinding; + vkAttrib.format = attrib_type_to_vkformat(attrib.type()); + vkAttrib.offset = instanceAttributeOffset; + SkASSERT(vkAttrib.offset == primProc.debugOnly_instanceAttributeOffset(iaIndex)); + instanceAttributeOffset += attrib.sizeAlign4(); + } + SkASSERT(instanceAttributeOffset == primProc.debugOnly_instanceStride()); + + if (primProc.hasVertexAttributes()) { + bindingDescs->push_back() = { + vertexBinding, + (uint32_t) vertexAttributeOffset, + VK_VERTEX_INPUT_RATE_VERTEX + }; + } + if (primProc.hasInstanceAttributes()) { + bindingDescs->push_back() = { + instanceBinding, + (uint32_t) instanceAttributeOffset, + VK_VERTEX_INPUT_RATE_INSTANCE + }; } memset(vertexInputInfo, 0, sizeof(VkPipelineVertexInputStateCreateInfo)); @@ -98,7 +119,7 @@ static void setup_vertex_input_state(const GrPrimitiveProcessor& primProc, vertexInputInfo->flags = 0; vertexInputInfo->vertexBindingDescriptionCount = bindingDescs->count(); vertexInputInfo->pVertexBindingDescriptions = bindingDescs->begin(); - vertexInputInfo->vertexAttributeDescriptionCount = vaCount; + vertexInputInfo->vertexAttributeDescriptionCount = vaCount + iaCount; vertexInputInfo->pVertexAttributeDescriptions = attributeDesc; } @@ -432,8 +453,9 @@ GrVkPipeline* GrVkPipeline::Create(GrVkGpu* gpu, const GrPipeline& pipeline, VkPipelineVertexInputStateCreateInfo vertexInputInfo; SkSTArray<2, VkVertexInputBindingDescription, true> bindingDescs; SkSTArray<16, VkVertexInputAttributeDescription> attributeDesc; - SkASSERT(primProc.numAttribs() <= gpu->vkCaps().maxVertexAttributes()); - VkVertexInputAttributeDescription* pAttribs = attributeDesc.push_back_n(primProc.numAttribs()); + int totalAttributeCnt = primProc.numVertexAttributes() + primProc.numInstanceAttributes(); + SkASSERT(totalAttributeCnt <= gpu->vkCaps().maxVertexAttributes()); + VkVertexInputAttributeDescription* pAttribs = attributeDesc.push_back_n(totalAttributeCnt); setup_vertex_input_state(primProc, &vertexInputInfo, &bindingDescs, pAttribs); VkPipelineInputAssemblyStateCreateInfo inputAssemblyInfo; diff --git a/tests/GrMeshTest.cpp b/tests/GrMeshTest.cpp index 4d9773b1a9..f95dbc8603 100644 --- a/tests/GrMeshTest.cpp +++ b/tests/GrMeshTest.cpp @@ -294,35 +294,46 @@ private: class GrMeshTestProcessor : public GrGeometryProcessor { public: GrMeshTestProcessor(bool instanced, bool hasVertexBuffer) - : INHERITED(kGrMeshTestProcessor_ClassID) - , fInstanceLocation(nullptr) - , fVertex(nullptr) - , fColor(nullptr) { + : INHERITED(kGrMeshTestProcessor_ClassID) { if (instanced) { - fInstanceLocation = &this->addInstanceAttrib("location", kHalf2_GrVertexAttribType); + fInstanceLocation = {"location", kHalf2_GrVertexAttribType}; + fColor = {"color", kUByte4_norm_GrVertexAttribType}; + this->setInstanceAttributeCnt(2); if (hasVertexBuffer) { - fVertex = &this->addVertexAttrib("vertex", kHalf2_GrVertexAttribType); + fVertex = {"vertex", kHalf2_GrVertexAttribType}; + this->setVertexAttributeCnt(1); } - fColor = &this->addInstanceAttrib("color", kUByte4_norm_GrVertexAttribType); } else { - fVertex = &this->addVertexAttrib("vertex", kHalf2_GrVertexAttribType); - fColor = &this->addVertexAttrib("color", kUByte4_norm_GrVertexAttribType); + fVertex = {"vertex", kHalf2_GrVertexAttribType}; + fColor = {"color", kUByte4_norm_GrVertexAttribType}; + this->setVertexAttributeCnt(2); } } const char* name() const override { return "GrMeshTest Processor"; } void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const final { - b->add32(SkToBool(fInstanceLocation)); - b->add32(SkToBool(fVertex)); + b->add32(fInstanceLocation.isInitialized()); + b->add32(fVertex.isInitialized()); } GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const final; -protected: - const Attribute* fInstanceLocation; - const Attribute* fVertex; - const Attribute* fColor; +private: + const Attribute& onVertexAttribute(int i) const override { + if (fInstanceLocation.isInitialized()) { + return fVertex; + } + return IthAttribute(i, fVertex, fColor); + } + + const Attribute& onInstanceAttribute(int i) const override { + return IthAttribute(i, fInstanceLocation, fColor); + } + + Attribute fInstanceLocation; + Attribute fVertex; + Attribute fColor; friend class GLSLMeshTestProcessor; typedef GrGeometryProcessor INHERITED; @@ -340,15 +351,15 @@ class GLSLMeshTestProcessor : public GrGLSLGeometryProcessor { varyingHandler->addPassThroughAttribute(mp.fColor, args.fOutputColor); GrGLSLVertexBuilder* v = args.fVertBuilder; - if (!mp.fInstanceLocation) { - v->codeAppendf("float2 vertex = %s;", mp.fVertex->name()); + if (!mp.fInstanceLocation.isInitialized()) { + v->codeAppendf("float2 vertex = %s;", mp.fVertex.name()); } else { - if (mp.fVertex) { - v->codeAppendf("float2 offset = %s;", mp.fVertex->name()); + if (mp.fVertex.isInitialized()) { + v->codeAppendf("float2 offset = %s;", mp.fVertex.name()); } else { v->codeAppend ("float2 offset = float2(sk_VertexID / 2, sk_VertexID % 2);"); } - v->codeAppendf("float2 vertex = %s + offset * %i;", mp.fInstanceLocation->name(), + v->codeAppendf("float2 vertex = %s + offset * %i;", mp.fInstanceLocation.name(), kBoxSize); } gpArgs->fPositionVar.set(kFloat2_GrSLType, "vertex"); diff --git a/tests/GrPipelineDynamicStateTest.cpp b/tests/GrPipelineDynamicStateTest.cpp index a197650c4f..b5bc74d382 100644 --- a/tests/GrPipelineDynamicStateTest.cpp +++ b/tests/GrPipelineDynamicStateTest.cpp @@ -58,9 +58,9 @@ struct Vertex { class GrPipelineDynamicStateTestProcessor : public GrGeometryProcessor { public: GrPipelineDynamicStateTestProcessor() - : INHERITED(kGrPipelineDynamicStateTestProcessor_ClassID) - , fVertex(this->addVertexAttrib("vertex", kHalf2_GrVertexAttribType)) - , fColor(this->addVertexAttrib("color", kUByte4_norm_GrVertexAttribType)) {} + : INHERITED(kGrPipelineDynamicStateTestProcessor_ClassID) { + this->setVertexAttributeCnt(2); + } const char* name() const override { return "GrPipelineDynamicStateTest Processor"; } @@ -68,13 +68,19 @@ public: GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const final; -protected: - const Attribute& fVertex; - const Attribute& fColor; +private: + const Attribute& onVertexAttribute(int i) const override { + return IthAttribute(i, kVertex, kColor); + } + + static constexpr Attribute kVertex = {"vertex", kHalf2_GrVertexAttribType}; + static constexpr Attribute kColor = {"color", kUByte4_norm_GrVertexAttribType}; friend class GLSLPipelineDynamicStateTestProcessor; typedef GrGeometryProcessor INHERITED; }; +constexpr GrPrimitiveProcessor::Attribute GrPipelineDynamicStateTestProcessor::kVertex; +constexpr GrPrimitiveProcessor::Attribute GrPipelineDynamicStateTestProcessor::kColor; class GLSLPipelineDynamicStateTestProcessor : public GrGLSLGeometryProcessor { void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor&, @@ -86,10 +92,10 @@ class GLSLPipelineDynamicStateTestProcessor : public GrGLSLGeometryProcessor { GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler; varyingHandler->emitAttributes(mp); - varyingHandler->addPassThroughAttribute(&mp.fColor, args.fOutputColor); + varyingHandler->addPassThroughAttribute(mp.kColor, args.fOutputColor); GrGLSLVertexBuilder* v = args.fVertBuilder; - v->codeAppendf("float2 vertex = %s;", mp.fVertex.name()); + v->codeAppendf("float2 vertex = %s;", mp.kVertex.name()); gpArgs->fPositionVar.set(kFloat2_GrSLType, "vertex"); GrGLSLFPFragmentBuilder* f = args.fFragBuilder; diff --git a/tests/OnFlushCallbackTest.cpp b/tests/OnFlushCallbackTest.cpp index e2f6fbf9e1..a8752057c8 100644 --- a/tests/OnFlushCallbackTest.cpp +++ b/tests/OnFlushCallbackTest.cpp @@ -110,11 +110,10 @@ private: return; } - size_t vertexStride = gp->getVertexStride(); - - SkASSERT(fHasLocalRect - ? vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorLocalCoordAttr) - : vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorAttr)); + size_t vertexStride = fHasLocalRect + ? sizeof(GrDefaultGeoProcFactory::PositionColorLocalCoordAttr) + : sizeof(GrDefaultGeoProcFactory::PositionColorAttr); + SkASSERT(vertexStride == gp->debugOnly_vertexStride()); const GrBuffer* indexBuffer; int firstIndex; diff --git a/tests/PrimitiveProcessorTest.cpp b/tests/PrimitiveProcessorTest.cpp index 74a73a66a9..60b2205cf7 100644 --- a/tests/PrimitiveProcessorTest.cpp +++ b/tests/PrimitiveProcessorTest.cpp @@ -59,15 +59,15 @@ private: void onPrepareDraws(Target* target) override { class GP : public GrGeometryProcessor { public: - GP(int numAttribs) - : INHERITED(kGP_ClassID) { + GP(int numAttribs) : INHERITED(kGP_ClassID), fNumAttribs(numAttribs) { SkASSERT(numAttribs > 1); + fAttribNames.reset(new SkString[numAttribs]); + fAttributes.reset(new Attribute[numAttribs]); for (auto i = 0; i < numAttribs; ++i) { - fAttribNames.push_back().printf("attr%d", i); - } - for (auto i = 0; i < numAttribs; ++i) { - this->addVertexAttrib(fAttribNames[i].c_str(), kFloat2_GrVertexAttribType); + fAttribNames[i].printf("attr%d", i); + fAttributes[i] = {fAttribNames[i].c_str(), kFloat2_GrVertexAttribType}; } + this->setVertexAttributeCnt(numAttribs); } const char* name() const override { return "Dummy GP"; } @@ -78,7 +78,7 @@ private: const GP& gp = args.fGP.cast(); args.fVaryingHandler->emitAttributes(gp); this->writeOutputPosition(args.fVertBuilder, gpArgs, - gp.getAttrib(0).name()); + gp.fAttributes[0].name()); GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; fragBuilder->codeAppendf("%s = half4(1);", args.fOutputColor); fragBuilder->codeAppendf("%s = half4(1);", args.fOutputCoverage); @@ -91,17 +91,24 @@ private: } void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* builder) const override { - builder->add32(this->numAttribs()); + builder->add32(fNumAttribs); } private: - SkTArray fAttribNames; + const GrPrimitiveProcessor::Attribute& onVertexAttribute(int i) const override { + return fAttributes[i]; + } + + int fNumAttribs; + std::unique_ptr fAttribNames; + std::unique_ptr fAttributes; typedef GrGeometryProcessor INHERITED; }; sk_sp gp(new GP(fNumAttribs)); QuadHelper helper; - size_t vertexStride = gp->getVertexStride(); + size_t vertexStride = fNumAttribs * GrVertexAttribTypeSize(kFloat2_GrVertexAttribType); + SkASSERT(vertexStride == gp->debugOnly_vertexStride()); SkPoint* vertices = reinterpret_cast(helper.init(target, vertexStride, 1)); SkPointPriv::SetRectTriStrip(vertices, 0.f, 0.f, 1.f, 1.f, vertexStride); helper.recordDraw(target, gp.get(), -- cgit v1.2.3