diff options
author | 2018-07-03 21:18:07 +0000 | |
---|---|---|
committer | 2018-07-03 21:18:18 +0000 | |
commit | c05aa7d163fd0b930fa450d2e4c7f2497f036254 (patch) | |
tree | d741730ca4b88ade1f73f4f2c20dec0ad1789464 /src | |
parent | 5ffcb4d20e3f9798daa013f2b4d00bfb4a9a01da (diff) |
Revert "added skeletal animation support to GPU backend"
This reverts commit b6307340e8a6a9d3a7517def7f5eaaadffd07d14.
Reason for revert: patch/atlas failing in gold
Original change's description:
> added skeletal animation support to GPU backend
>
> added caching of SkVertices
>
> Docs-Preview: https://skia.org/?cl=138596
> Bug: skia:
> Change-Id: Ia750f55f5f6d0de250d9e9c5619f4d1ac856f9f5
> Reviewed-on: https://skia-review.googlesource.com/138596
> Reviewed-by: Brian Osman <brianosman@google.com>
> Reviewed-by: Robert Phillips <robertphillips@google.com>
> Commit-Queue: Ruiqi Mao <ruiqimao@google.com>
TBR=robertphillips@google.com,brianosman@google.com,reed@google.com,ruiqimao@google.com
Change-Id: Idfaf016a7ff4cdd8af2543d510706f489d04417a
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: skia:
Reviewed-on: https://skia-review.googlesource.com/139281
Reviewed-by: Ruiqi Mao <ruiqimao@google.com>
Commit-Queue: Ruiqi Mao <ruiqimao@google.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/core/SkBlurMF.cpp | 3 | ||||
-rw-r--r-- | src/core/SkCanvas.cpp | 2 | ||||
-rw-r--r-- | src/core/SkVertices.cpp | 29 | ||||
-rw-r--r-- | src/gpu/GrDefaultGeoProcFactory.cpp | 142 | ||||
-rw-r--r-- | src/gpu/GrDefaultGeoProcFactory.h | 22 | ||||
-rw-r--r-- | src/gpu/GrRenderTargetContext.cpp | 4 | ||||
-rw-r--r-- | src/gpu/GrRenderTargetContext.h | 4 | ||||
-rw-r--r-- | src/gpu/SkGpuDevice.cpp | 17 | ||||
-rw-r--r-- | src/gpu/SkGpuDevice.h | 5 | ||||
-rw-r--r-- | src/gpu/ops/GrDrawVerticesOp.cpp | 289 | ||||
-rw-r--r-- | src/gpu/ops/GrDrawVerticesOp.h | 47 |
11 files changed, 70 insertions, 494 deletions
diff --git a/src/core/SkBlurMF.cpp b/src/core/SkBlurMF.cpp index f3d71230e7..23cca83655 100644 --- a/src/core/SkBlurMF.cpp +++ b/src/core/SkBlurMF.cpp @@ -874,8 +874,7 @@ bool SkBlurMaskFilterImpl::directFilterRRectMaskGPU(GrContext* context, } paint.addCoverageFragmentProcessor(std::move(fp)); - renderTargetContext->drawVertices(clip, std::move(paint), viewMatrix, std::move(vertices), - nullptr, 0); + renderTargetContext->drawVertices(clip, std::move(paint), viewMatrix, std::move(vertices)); } else { SkMatrix inverse; if (!viewMatrix.invert(&inverse)) { diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp index 45bbc64308..8314f803f0 100644 --- a/src/core/SkCanvas.cpp +++ b/src/core/SkCanvas.cpp @@ -1715,7 +1715,6 @@ void SkCanvas::drawVertices(const sk_sp<SkVertices>& vertices, const SkMatrix* b SkBlendMode mode, const SkPaint& paint) { TRACE_EVENT0("skia", TRACE_FUNC); RETURN_ON_NULL(vertices); - SkASSERT(boneCount <= 100); this->onDrawVerticesObject(vertices.get(), bones, boneCount, mode, paint); } @@ -1723,7 +1722,6 @@ void SkCanvas::drawVertices(const SkVertices* vertices, const SkMatrix* bones, i SkBlendMode mode, const SkPaint& paint) { TRACE_EVENT0("skia", TRACE_FUNC); RETURN_ON_NULL(vertices); - SkASSERT(boneCount <= 100); this->onDrawVerticesObject(vertices, bones, boneCount, mode, paint); } diff --git a/src/core/SkVertices.cpp b/src/core/SkVertices.cpp index 7cbf209285..04db0d35fb 100644 --- a/src/core/SkVertices.cpp +++ b/src/core/SkVertices.cpp @@ -95,17 +95,16 @@ SkVertices::Builder::Builder(VertexMode mode, int vertexCount, int indexCount, bool hasTexs = SkToBool(builderFlags & SkVertices::kHasTexCoords_BuilderFlag); bool hasColors = SkToBool(builderFlags & SkVertices::kHasColors_BuilderFlag); bool hasBones = SkToBool(builderFlags & SkVertices::kHasBones_BuilderFlag); - bool isVolatile = SkToBool(builderFlags & SkVertices::kIsVolatile_BuilderFlag); - this->init(mode, vertexCount, indexCount, isVolatile, + this->init(mode, vertexCount, indexCount, SkVertices::Sizes(mode, vertexCount, indexCount, hasTexs, hasColors, hasBones)); } -SkVertices::Builder::Builder(VertexMode mode, int vertexCount, int indexCount, bool isVolatile, +SkVertices::Builder::Builder(VertexMode mode, int vertexCount, int indexCount, const SkVertices::Sizes& sizes) { - this->init(mode, vertexCount, indexCount, isVolatile, sizes); + this->init(mode, vertexCount, indexCount, sizes); } -void SkVertices::Builder::init(VertexMode mode, int vertexCount, int indexCount, bool isVolatile, +void SkVertices::Builder::init(VertexMode mode, int vertexCount, int indexCount, const SkVertices::Sizes& sizes) { if (!sizes.isValid()) { return; // fVertices will already be null @@ -129,7 +128,6 @@ void SkVertices::Builder::init(VertexMode mode, int vertexCount, int indexCount, fVertices->fIndices = sizes.fISize ? (uint16_t*)ptr : nullptr; fVertices->fVertexCnt = vertexCount; fVertices->fIndexCnt = indexCount; - fVertices->fIsVolatile = isVolatile; fVertices->fMode = mode; // We defer assigning fBounds and fUniqueID until detach() is called @@ -173,10 +171,6 @@ int SkVertices::Builder::indexCount() const { return fVertices ? fVertices->indexCount() : 0; } -bool SkVertices::Builder::isVolatile() const { - return fVertices ? fVertices->isVolatile() : false; -} - SkPoint* SkVertices::Builder::positions() { return fVertices ? const_cast<SkPoint*>(fVertices->positions()) : nullptr; } @@ -214,8 +208,7 @@ sk_sp<SkVertices> SkVertices::MakeCopy(VertexMode mode, int vertexCount, const SkColor colors[], const BoneIndices boneIndices[], const BoneWeights boneWeights[], - int indexCount, const uint16_t indices[], - bool isVolatile) { + int indexCount, const uint16_t indices[]) { SkASSERT((!boneIndices && !boneWeights) || (boneIndices && boneWeights)); Sizes sizes(mode, vertexCount, @@ -227,7 +220,7 @@ sk_sp<SkVertices> SkVertices::MakeCopy(VertexMode mode, int vertexCount, return nullptr; } - Builder builder(mode, vertexCount, indexCount, isVolatile, sizes); + Builder builder(mode, vertexCount, indexCount, sizes); SkASSERT(builder.isValid()); sk_careful_memcpy(builder.positions(), pos, sizes.fVSize); @@ -254,15 +247,15 @@ size_t SkVertices::approximateSize() const { /////////////////////////////////////////////////////////////////////////////////////////////////// -// storage = packed | vertex_count | index_count | is_volatile | pos[] | texs[] | colors[] | -// boneIndices[] | boneWeights[] | indices[] +// storage = packed | vertex_count | index_count | pos[] | texs[] | colors[] | boneIndices[] | +// boneWeights[] | indices[] // = header + arrays #define kMode_Mask 0x0FF #define kHasTexs_Mask 0x100 #define kHasColors_Mask 0x200 #define kHasBones_Mask 0x400 -#define kHeaderSize (4 * sizeof(uint32_t)) +#define kHeaderSize (3 * sizeof(uint32_t)) sk_sp<SkData> SkVertices::encode() const { // packed has room for addtional flags in the future (e.g. versioning) @@ -295,7 +288,6 @@ sk_sp<SkData> SkVertices::encode() const { writer.write32(packed); writer.write32(fVertexCnt); writer.write32(fIndexCnt); - writer.writeBool(fIsVolatile); writer.write(fPositions, sizes.fVSize); writer.write(fTexs, sizes.fTSize); writer.write(fColors, sizes.fCSize); @@ -318,7 +310,6 @@ sk_sp<SkVertices> SkVertices::Decode(const void* data, size_t length) { const uint32_t packed = reader.readInt(); const int vertexCount = safe.checkGE(reader.readInt(), 0); const int indexCount = safe.checkGE(reader.readInt(), 0); - const bool isVolatile = reader.readBool(); const VertexMode mode = safe.checkLE<VertexMode>(packed & kMode_Mask, SkVertices::kLast_VertexMode); if (!safe) { @@ -336,7 +327,7 @@ sk_sp<SkVertices> SkVertices::Decode(const void* data, size_t length) { return nullptr; } - Builder builder(mode, vertexCount, indexCount, isVolatile, sizes); + Builder builder(mode, vertexCount, indexCount, sizes); reader.read(builder.positions(), sizes.fVSize); reader.read(builder.texCoords(), sizes.fTSize); diff --git a/src/gpu/GrDefaultGeoProcFactory.cpp b/src/gpu/GrDefaultGeoProcFactory.cpp index c9108e3d96..e2bf87b277 100644 --- a/src/gpu/GrDefaultGeoProcFactory.cpp +++ b/src/gpu/GrDefaultGeoProcFactory.cpp @@ -27,13 +27,8 @@ enum GPFlag { kColorAttributeIsSkColor_GPFlag = 0x2, kLocalCoordAttribute_GPFlag = 0x4, kCoverageAttribute_GPFlag = 0x8, - kBonesAttribute_GPFlag = 0x10, }; -static constexpr int kNumFloatsPerSkMatrix = 9; -static constexpr int kMaxBones = 100; // Due to GPU memory limitations, only up to 100 bone - // matrices are accepted. - class DefaultGeoProc : public GrGeometryProcessor { public: static sk_sp<GrGeometryProcessor> Make(uint32_t gpTypeFlags, @@ -42,12 +37,10 @@ public: const SkMatrix& viewMatrix, const SkMatrix& localMatrix, bool localCoordsWillBeRead, - uint8_t coverage, - const SkMatrix bones[], - int boneCount) { + uint8_t coverage) { return sk_sp<GrGeometryProcessor>(new DefaultGeoProc( gpTypeFlags, color, std::move(colorSpaceXform), viewMatrix, localMatrix, coverage, - localCoordsWillBeRead, bones, boneCount)); + localCoordsWillBeRead)); } const char* name() const override { return "DefaultGeometryProcessor"; } @@ -59,9 +52,6 @@ public: bool localCoordsWillBeRead() const { return fLocalCoordsWillBeRead; } uint8_t coverage() const { return fCoverage; } bool hasVertexCoverage() const { return fInCoverage.isInitialized(); } - const float* bones() const { return fBones.data(); } - int boneCount() const { return fBones.size() / kNumFloatsPerSkMatrix; } - bool hasBones() const { return fBones.size() > 0; } class GLSLProcessor : public GrGLSLGeometryProcessor { public: @@ -109,37 +99,11 @@ public: &fColorUniform); } - // Setup bone transforms - const char* transformedPositionName = gp.fInPosition.name(); - if (gp.hasBones()) { - const char* vertBonesUniformName; - fBonesUniform = uniformHandler->addUniformArray(kVertex_GrShaderFlag, - kFloat3x3_GrSLType, - "Bones", - kMaxBones, - &vertBonesUniformName); - vertBuilder->codeAppendf( - "float2 transformedPosition = (%s[0] * float3(%s, 1)).xy;" - "float3x3 influence = float3x3(0);" - "for (int i = 0; i < 4; i++) {" - " int index = %s[i];" - " float weight = %s[i];" - " influence += %s[index] * weight;" - "}" - "transformedPosition = (influence * float3(transformedPosition, 1)).xy;", - vertBonesUniformName, - gp.fInPosition.name(), - gp.fInBoneIndices.name(), - gp.fInBoneWeights.name(), - vertBonesUniformName); - transformedPositionName = "transformedPosition"; - } - // Setup position this->writeOutputPosition(vertBuilder, uniformHandler, gpArgs, - transformedPositionName, + gp.fInPosition.name(), gp.viewMatrix(), &fViewMatrixUniform); @@ -183,8 +147,8 @@ public: GrProcessorKeyBuilder* b) { const DefaultGeoProc& def = gp.cast<DefaultGeoProc>(); uint32_t key = def.fFlags; - key |= (def.coverage() == 0xff) ? 0x20 : 0; - key |= (def.localCoordsWillBeRead() && def.localMatrix().hasPerspective()) ? 0x40 : 0x0; + key |= (def.coverage() == 0xff) ? 0x10 : 0; + key |= (def.localCoordsWillBeRead() && def.localMatrix().hasPerspective()) ? 0x20 : 0x0; key |= ComputePosKey(def.viewMatrix()) << 20; b->add32(key); b->add32(GrColorSpaceXform::XformKey(def.fColorSpaceXform.get())); @@ -216,10 +180,6 @@ public: this->setTransformDataHelper(dgp.fLocalMatrix, pdman, &transformIter); fColorSpaceHelper.setData(pdman, dgp.fColorSpaceXform.get()); - - if (dgp.hasBones()) { - pdman.setMatrix3fv(fBonesUniform, dgp.boneCount(), dgp.bones()); - } } private: @@ -229,7 +189,6 @@ public: UniformHandle fViewMatrixUniform; UniformHandle fColorUniform; UniformHandle fCoverageUniform; - UniformHandle fBonesUniform; GrGLSLColorSpaceXformHelper fColorSpaceHelper; typedef GrGLSLGeometryProcessor INHERITED; @@ -250,9 +209,7 @@ private: const SkMatrix& viewMatrix, const SkMatrix& localMatrix, uint8_t coverage, - bool localCoordsWillBeRead, - const SkMatrix* bones, - int boneCount) + bool localCoordsWillBeRead) : INHERITED(kDefaultGeoProc_ClassID) , fColor(color) , fViewMatrix(viewMatrix) @@ -260,8 +217,7 @@ private: , fCoverage(coverage) , fFlags(gpTypeFlags) , fLocalCoordsWillBeRead(localCoordsWillBeRead) - , fColorSpaceXform(std::move(colorSpaceXform)) - , fBones() { + , fColorSpaceXform(std::move(colorSpaceXform)) { fInPosition = {"inPosition", kFloat2_GrVertexAttribType}; int cnt = 1; if (fFlags & kColorAttribute_GPFlag) { @@ -276,49 +232,17 @@ private: fInCoverage = {"inCoverage", kHalf_GrVertexAttribType}; ++cnt; } - if (fFlags & kBonesAttribute_GPFlag) { - SkASSERT(bones && (boneCount > 0)); - fInBoneIndices = {"inBoneIndices", kInt4_GrVertexAttribType}; - ++cnt; - fInBoneWeights = {"inBoneWeights", kFloat4_GrVertexAttribType}; - ++cnt; - } this->setVertexAttributeCnt(cnt); - - // Set bone data - if (bones) { - fBones.reserve(boneCount * kNumFloatsPerSkMatrix); - for (int i = 0; i < boneCount; i ++) { - const SkMatrix& matrix = bones[i]; - fBones.push_back(matrix.get(SkMatrix::kMScaleX)); - fBones.push_back(matrix.get(SkMatrix::kMSkewY)); - fBones.push_back(matrix.get(SkMatrix::kMPersp0)); - fBones.push_back(matrix.get(SkMatrix::kMSkewX)); - fBones.push_back(matrix.get(SkMatrix::kMScaleY)); - fBones.push_back(matrix.get(SkMatrix::kMPersp1)); - fBones.push_back(matrix.get(SkMatrix::kMTransX)); - fBones.push_back(matrix.get(SkMatrix::kMTransY)); - fBones.push_back(matrix.get(SkMatrix::kMPersp2)); - } - } } const Attribute& onVertexAttribute(int i) const override { - return IthInitializedAttribute(i, - fInPosition, - fInColor, - fInLocalCoords, - fInCoverage, - fInBoneIndices, - fInBoneWeights); + return IthInitializedAttribute(i, fInPosition, fInColor, fInLocalCoords, fInCoverage); } Attribute fInPosition; Attribute fInColor; Attribute fInLocalCoords; Attribute fInCoverage; - Attribute fInBoneIndices; - Attribute fInBoneWeights; GrColor fColor; SkMatrix fViewMatrix; SkMatrix fLocalMatrix; @@ -326,7 +250,6 @@ private: uint32_t fFlags; bool fLocalCoordsWillBeRead; sk_sp<GrColorSpaceXform> fColorSpaceXform; - std::vector<float> fBones; GR_DECLARE_GEOMETRY_PROCESSOR_TEST @@ -350,17 +273,6 @@ sk_sp<GrGeometryProcessor> DefaultGeoProc::TestCreate(GrProcessorTestData* d) { if (d->fRandom->nextBool()) { flags |= kLocalCoordAttribute_GPFlag; } - if (d->fRandom->nextBool()) { - flags |= kBonesAttribute_GPFlag; - } - - int numBones = d->fRandom->nextRangeU(0, kMaxBones); - std::vector<SkMatrix> bones(numBones); - for (int i = 0; i < numBones; i++) { - for (int j = 0; j < kNumFloatsPerSkMatrix; j++) { - bones[i][j] = d->fRandom->nextF(); - } - } return DefaultGeoProc::Make(flags, GrRandomColor(d->fRandom), @@ -368,9 +280,7 @@ sk_sp<GrGeometryProcessor> DefaultGeoProc::TestCreate(GrProcessorTestData* d) { GrTest::TestMatrix(d->fRandom), GrTest::TestMatrix(d->fRandom), d->fRandom->nextBool(), - GrRandomCoverage(d->fRandom), - bones.data(), - numBones); + GrRandomCoverage(d->fRandom)); } #endif @@ -397,9 +307,7 @@ sk_sp<GrGeometryProcessor> GrDefaultGeoProcFactory::Make(const Color& color, viewMatrix, localCoords.fMatrix ? *localCoords.fMatrix : SkMatrix::I(), localCoordsWillBeRead, - inCoverage, - nullptr, - 0); + inCoverage); } sk_sp<GrGeometryProcessor> GrDefaultGeoProcFactory::MakeForDeviceSpace( @@ -422,33 +330,3 @@ sk_sp<GrGeometryProcessor> GrDefaultGeoProcFactory::MakeForDeviceSpace( LocalCoords inverted(LocalCoords::kUsePosition_Type, &invert); return Make(color, coverage, inverted, SkMatrix::I()); } - -sk_sp<GrGeometryProcessor> GrDefaultGeoProcFactory::MakeWithBones(const Color& color, - const Coverage& coverage, - const LocalCoords& localCoords, - const Bones& bones, - const SkMatrix& viewMatrix) { - uint32_t flags = 0; - if (Color::kPremulGrColorAttribute_Type == color.fType) { - flags |= kColorAttribute_GPFlag; - } else if (Color::kUnpremulSkColorAttribute_Type == color.fType) { - flags |= kColorAttribute_GPFlag | kColorAttributeIsSkColor_GPFlag; - } - flags |= coverage.fType == Coverage::kAttribute_Type ? kCoverageAttribute_GPFlag : 0; - flags |= localCoords.fType == LocalCoords::kHasExplicit_Type ? kLocalCoordAttribute_GPFlag : 0; - flags |= kBonesAttribute_GPFlag; - - uint8_t inCoverage = coverage.fCoverage; - bool localCoordsWillBeRead = localCoords.fType != LocalCoords::kUnused_Type; - - GrColor inColor = color.fColor; - return DefaultGeoProc::Make(flags, - inColor, - color.fColorSpaceXform, - viewMatrix, - localCoords.fMatrix ? *localCoords.fMatrix : SkMatrix::I(), - localCoordsWillBeRead, - inCoverage, - bones.fBones, - bones.fBoneCount); -} diff --git a/src/gpu/GrDefaultGeoProcFactory.h b/src/gpu/GrDefaultGeoProcFactory.h index c22cefbd73..314c1bb963 100644 --- a/src/gpu/GrDefaultGeoProcFactory.h +++ b/src/gpu/GrDefaultGeoProcFactory.h @@ -54,7 +54,7 @@ namespace GrDefaultGeoProcFactory { SkPoint fLocalCoord; }; - struct PositionColorLocalCoordCoverageAttr { + struct PositionColorLocalCoordCoverage { SkPoint fPosition; GrColor fColor; SkPoint fLocalCoord; @@ -118,15 +118,6 @@ namespace GrDefaultGeoProcFactory { const SkMatrix* fMatrix; }; - struct Bones { - Bones(const SkMatrix bones[], int boneCount) - : fBones(bones) - , fBoneCount(boneCount) {} - - const SkMatrix* fBones; - int fBoneCount; - }; - sk_sp<GrGeometryProcessor> Make(const Color&, const Coverage&, const LocalCoords&, @@ -141,17 +132,6 @@ namespace GrDefaultGeoProcFactory { const Coverage&, const LocalCoords&, const SkMatrix& viewMatrix); - - /* - * Use this factory to create a GrGeometryProcessor that supports skeletal animation through - * deformation of vertices using matrices that are passed in. This should only be called from - * GrDrawVerticesOp. - */ - sk_sp<GrGeometryProcessor> MakeWithBones(const Color&, - const Coverage&, - const LocalCoords&, - const Bones&, - const SkMatrix& viewMatrix); }; #endif diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp index 40303668d8..05b3c2475a 100644 --- a/src/gpu/GrRenderTargetContext.cpp +++ b/src/gpu/GrRenderTargetContext.cpp @@ -844,8 +844,6 @@ void GrRenderTargetContext::drawVertices(const GrClip& clip, GrPaint&& paint, const SkMatrix& viewMatrix, sk_sp<SkVertices> vertices, - const SkMatrix bones[], - int boneCount, GrPrimitiveType* overridePrimType) { ASSERT_SINGLE_OWNER RETURN_IF_ABANDONED @@ -857,7 +855,7 @@ void GrRenderTargetContext::drawVertices(const GrClip& clip, SkASSERT(vertices); GrAAType aaType = this->chooseAAType(GrAA::kNo, GrAllowMixedSamples::kNo); std::unique_ptr<GrDrawOp> op = GrDrawVerticesOp::Make( - fContext, std::move(paint), std::move(vertices), bones, boneCount, viewMatrix, aaType, + fContext, std::move(paint), std::move(vertices), viewMatrix, aaType, this->colorSpaceInfo().refColorSpaceXformFromSRGB(), overridePrimType); this->addDrawOp(clip, std::move(op)); } diff --git a/src/gpu/GrRenderTargetContext.h b/src/gpu/GrRenderTargetContext.h index ee0d183981..783b351b06 100644 --- a/src/gpu/GrRenderTargetContext.h +++ b/src/gpu/GrRenderTargetContext.h @@ -218,16 +218,12 @@ public: * @param paint describes how to color pixels. * @param viewMatrix transformation matrix * @param vertices specifies the mesh to draw. - * @param bones bone deformation matrices. - * @param boneCount number of bone matrices. * @param overridePrimType primitive type to draw. If NULL, derive prim type from vertices. */ void drawVertices(const GrClip&, GrPaint&& paint, const SkMatrix& viewMatrix, sk_sp<SkVertices> vertices, - const SkMatrix bones[], - int boneCount, GrPrimitiveType* overridePrimType = nullptr); /** diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp index f1e527036b..a665517d4f 100644 --- a/src/gpu/SkGpuDevice.cpp +++ b/src/gpu/SkGpuDevice.cpp @@ -365,7 +365,7 @@ void SkGpuDevice::drawPoints(SkCanvas::PointMode mode, nullptr); fRenderTargetContext->drawVertices(this->clip(), std::move(grPaint), *viewMatrix, - std::move(vertices), nullptr, 0, &primitiveType); + std::move(vertices), &primitiveType); } /////////////////////////////////////////////////////////////////////////////// @@ -1480,9 +1480,7 @@ static bool init_vertices_paint(GrContext* context, const GrColorSpaceInfo& colo } void SkGpuDevice::wireframeVertices(SkVertices::VertexMode vmode, int vertexCount, - const SkPoint vertices[], - const SkMatrix bones[], int boneCount, - SkBlendMode bmode, + const SkPoint vertices[], SkBlendMode bmode, const uint16_t indices[], int indexCount, const SkPaint& paint) { ASSERT_SINGLE_OWNER @@ -1540,13 +1538,12 @@ void SkGpuDevice::wireframeVertices(SkVertices::VertexMode vmode, int vertexCoun std::move(grPaint), this->ctm(), builder.detach(), - bones, - boneCount, &primitiveType); } -void SkGpuDevice::drawVertices(const SkVertices* vertices, const SkMatrix bones[], int boneCount, +void SkGpuDevice::drawVertices(const SkVertices* vertices, const SkMatrix* bones, int boneCount, SkBlendMode mode, const SkPaint& paint) { + // TODO: GPU ANIMATION ASSERT_SINGLE_OWNER GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawVertices", fContext.get()); @@ -1557,8 +1554,7 @@ void SkGpuDevice::drawVertices(const SkVertices* vertices, const SkMatrix bones[ if ((!hasTexs || !paint.getShader()) && !hasColors) { // The dreaded wireframe mode. Fallback to drawVertices and go so slooooooow. this->wireframeVertices(vertices->mode(), vertices->vertexCount(), vertices->positions(), - bones, boneCount, mode, vertices->indices(), vertices->indexCount(), - paint); + mode, vertices->indices(), vertices->indexCount(), paint); return; } if (!init_vertices_paint(fContext.get(), fRenderTargetContext->colorSpaceInfo(), paint, @@ -1566,8 +1562,7 @@ void SkGpuDevice::drawVertices(const SkVertices* vertices, const SkMatrix bones[ return; } fRenderTargetContext->drawVertices(this->clip(), std::move(grPaint), this->ctm(), - sk_ref_sp(const_cast<SkVertices*>(vertices)), - bones, boneCount); + sk_ref_sp(const_cast<SkVertices*>(vertices))); } /////////////////////////////////////////////////////////////////////////////// diff --git a/src/gpu/SkGpuDevice.h b/src/gpu/SkGpuDevice.h index c31e6245b3..48ba8ac8a1 100644 --- a/src/gpu/SkGpuDevice.h +++ b/src/gpu/SkGpuDevice.h @@ -91,7 +91,7 @@ public: int scalarsPerPos, const SkPoint& offset, const SkPaint&) override; void drawTextBlob(const SkTextBlob*, SkScalar x, SkScalar y, const SkPaint& paint, SkDrawFilter* drawFilter) override; - void drawVertices(const SkVertices*, const SkMatrix bones[], int boneCount, SkBlendMode, + void drawVertices(const SkVertices*, const SkMatrix* bones, int boneCount, SkBlendMode, const SkPaint&) override; void drawShadow(const SkPath&, const SkDrawShadowRec&) override; void drawAtlas(const SkImage* atlas, const SkRSXform[], const SkRect[], @@ -248,8 +248,7 @@ private: void drawStrokedLine(const SkPoint pts[2], const SkPaint&); void wireframeVertices(SkVertices::VertexMode, int vertexCount, const SkPoint verts[], - const SkMatrix bones[], int boneCount, SkBlendMode, - const uint16_t indices[], int indexCount, const SkPaint&); + SkBlendMode, const uint16_t indices[], int indexCount, const SkPaint&); static sk_sp<GrRenderTargetContext> MakeRenderTargetContext(GrContext*, SkBudgeted, diff --git a/src/gpu/ops/GrDrawVerticesOp.cpp b/src/gpu/ops/GrDrawVerticesOp.cpp index 6abca9d3e8..ad5aba2b2c 100644 --- a/src/gpu/ops/GrDrawVerticesOp.cpp +++ b/src/gpu/ops/GrDrawVerticesOp.cpp @@ -10,13 +10,10 @@ #include "GrDefaultGeoProcFactory.h" #include "GrOpFlushState.h" #include "SkGr.h" -#include "SkRectPriv.h" std::unique_ptr<GrDrawOp> GrDrawVerticesOp::Make(GrContext* context, GrPaint&& paint, sk_sp<SkVertices> vertices, - const SkMatrix bones[], - int boneCount, const SkMatrix& viewMatrix, GrAAType aaType, sk_sp<GrColorSpaceXform> colorSpaceXform, @@ -25,14 +22,13 @@ std::unique_ptr<GrDrawOp> GrDrawVerticesOp::Make(GrContext* context, GrPrimitiveType primType = overridePrimType ? *overridePrimType : SkVertexModeToGrPrimitiveType(vertices->mode()); return Helper::FactoryHelper<GrDrawVerticesOp>(context, std::move(paint), std::move(vertices), - bones, boneCount, primType, aaType, - std::move(colorSpaceXform), viewMatrix); + primType, aaType, std::move(colorSpaceXform), + viewMatrix); } GrDrawVerticesOp::GrDrawVerticesOp(const Helper::MakeArgs& helperArgs, GrColor color, - sk_sp<SkVertices> vertices, const SkMatrix bones[], - int boneCount, GrPrimitiveType primitiveType, GrAAType aaType, - sk_sp<GrColorSpaceXform> colorSpaceXform, + sk_sp<SkVertices> vertices, GrPrimitiveType primitiveType, + GrAAType aaType, sk_sp<GrColorSpaceXform> colorSpaceXform, const SkMatrix& viewMatrix) : INHERITED(ClassID()) , fHelper(helperArgs, aaType) @@ -49,28 +45,15 @@ GrDrawVerticesOp::GrDrawVerticesOp(const Helper::MakeArgs& helperArgs, GrColor c mesh.fColor = color; mesh.fViewMatrix = viewMatrix; mesh.fVertices = std::move(vertices); - if (bones) { - mesh.fBones.assign(bones, bones + boneCount); - } mesh.fIgnoreTexCoords = false; mesh.fIgnoreColors = false; - mesh.fIgnoreBones = false; fFlags = 0; if (mesh.hasPerVertexColors()) { fFlags |= kRequiresPerVertexColors_Flag; } if (mesh.hasExplicitLocalCoords()) { - fFlags |= kAnyMeshHasExplicitLocalCoords_Flag; - } - if (mesh.hasBones()) { - fFlags |= kHasBones_Flag; - } - - // Special case for meshes with a world transform but no bone weights. - // These will be considered normal vertices draws without bones. - if (!mesh.fVertices->hasBones() && boneCount == 1) { - mesh.fViewMatrix.preConcat(bones[0]); + fFlags |= kAnyMeshHasExplicitLocalCoords; } IsZeroArea zeroArea; @@ -79,27 +62,7 @@ GrDrawVerticesOp::GrDrawVerticesOp(const Helper::MakeArgs& helperArgs, GrColor c } else { zeroArea = IsZeroArea::kNo; } - - if (this->hasBones()) { - // We don't know the bounds if there are deformations involved, so attempt to calculate - // the maximum possible. - SkRect bounds; - const SkRect& originalBounds = bones[0].mapRect(mesh.fVertices->bounds()); - for (int i = 1; i < boneCount; i++) { - const SkMatrix& matrix = bones[i]; - bounds.join(matrix.mapRect(originalBounds)); - } - - this->setTransformedBounds(bounds, - mesh.fViewMatrix, - HasAABloat::kNo, - zeroArea); - } else { - this->setTransformedBounds(mesh.fVertices->bounds(), - mesh.fViewMatrix, - HasAABloat::kNo, - zeroArea); - } + this->setTransformedBounds(mesh.fVertices->bounds(), viewMatrix, HasAABloat::kNo, zeroArea); } SkString GrDrawVerticesOp::dumpInfo() const { @@ -133,14 +96,13 @@ GrDrawOp::RequiresDstTexture GrDrawVerticesOp::finalize(const GrCaps& caps, } if (!fHelper.usesLocalCoords()) { fMeshes[0].fIgnoreTexCoords = true; - fFlags &= ~kAnyMeshHasExplicitLocalCoords_Flag; + fFlags &= ~kAnyMeshHasExplicitLocalCoords; } return result; } sk_sp<GrGeometryProcessor> GrDrawVerticesOp::makeGP(bool* hasColorAttribute, - bool* hasLocalCoordAttribute, - bool* hasBoneAttribute) const { + bool* hasLocalCoordAttribute) const { using namespace GrDefaultGeoProcFactory; LocalCoords::Type localCoordsType; if (fHelper.usesLocalCoords()) { @@ -170,53 +132,26 @@ sk_sp<GrGeometryProcessor> GrDrawVerticesOp::makeGP(bool* hasColorAttribute, } else { *hasColorAttribute = false; }; - const SkMatrix& vm = this->hasMultipleViewMatrices() ? SkMatrix::I() : fMeshes[0].fViewMatrix; - - Bones bones(fMeshes[0].fBones.data(), fMeshes[0].fBones.size()); - *hasBoneAttribute = this->hasBones(); - - if (this->hasBones()) { - return GrDefaultGeoProcFactory::MakeWithBones(color, - Coverage::kSolid_Type, - localCoordsType, - bones, - vm); - } else { - return GrDefaultGeoProcFactory::Make(color, - Coverage::kSolid_Type, - localCoordsType, - vm); - } + return GrDefaultGeoProcFactory::Make(color, Coverage::kSolid_Type, localCoordsType, vm); } void GrDrawVerticesOp::onPrepareDraws(Target* target) { - if (fMeshes[0].fVertices->isVolatile()) { - this->drawVolatile(target); - } else { - this->drawNonVolatile(target); - } -} - -void GrDrawVerticesOp::drawVolatile(Target* target) { bool hasColorAttribute; bool hasLocalCoordsAttribute; - bool hasBoneAttribute; - sk_sp<GrGeometryProcessor> gp = this->makeGP(&hasColorAttribute, - &hasLocalCoordsAttribute, - &hasBoneAttribute); - - // Calculate the stride. - size_t vertexStride = sizeof(SkPoint) + - (hasColorAttribute ? sizeof(uint32_t) : 0) + - (hasLocalCoordsAttribute ? sizeof(SkPoint) : 0) + - (hasBoneAttribute ? 4 * (sizeof(uint32_t) + sizeof(float)) : 0); + sk_sp<GrGeometryProcessor> gp = this->makeGP(&hasColorAttribute, &hasLocalCoordsAttribute); + + size_t vertexStride = sizeof(SkPoint) + (hasColorAttribute ? sizeof(uint32_t) : 0) + + (hasLocalCoordsAttribute ? sizeof(SkPoint) : 0); SkASSERT(vertexStride == gp->debugOnly_vertexStride()); - // Allocate buffers. - const GrBuffer* vertexBuffer = nullptr; - int firstVertex = 0; + int instanceCount = fMeshes.count(); + + const GrBuffer* vertexBuffer; + int firstVertex; + void* verts = target->makeVertexSpace(vertexStride, fVertexCount, &vertexBuffer, &firstVertex); + if (!verts) { SkDebugf("Could not allocate vertices\n"); return; @@ -224,157 +159,37 @@ void GrDrawVerticesOp::drawVolatile(Target* target) { const GrBuffer* indexBuffer = nullptr; int firstIndex = 0; + uint16_t* indices = nullptr; if (this->isIndexed()) { indices = target->makeIndexSpace(fIndexCount, &indexBuffer, &firstIndex); - if (!indices) { - SkDebugf("Could not allocate indices\n"); - return; - } - } - - // Fill the buffers. - this->fillBuffers(hasColorAttribute, - hasLocalCoordsAttribute, - hasBoneAttribute, - vertexStride, - verts, - indices); - - // Draw the vertices. - this->drawVertices(target, gp.get(), vertexBuffer, firstVertex, indexBuffer, firstIndex); -} - -void GrDrawVerticesOp::drawNonVolatile(Target* target) { - static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain(); - - bool hasColorAttribute; - bool hasLocalCoordsAttribute; - bool hasBoneAttribute; - sk_sp<GrGeometryProcessor> gp = this->makeGP(&hasColorAttribute, - &hasLocalCoordsAttribute, - &hasBoneAttribute); - - int instanceCount = fMeshes.count(); - SkASSERT(instanceCount == 1); // Non-volatile meshes should never combine. - - // Get the resource provider. - GrResourceProvider* rp = target->resourceProvider(); - // Generate keys for the buffers. - GrUniqueKey vertexKey, indexKey; - GrUniqueKey::Builder vertexKeyBuilder(&vertexKey, kDomain, instanceCount + 1); - GrUniqueKey::Builder indexKeyBuilder(&indexKey, kDomain, instanceCount + 1); - for (int i = 0; i < instanceCount; i ++) { - vertexKeyBuilder[i] = indexKeyBuilder[i] = fMeshes[i].fVertices->uniqueID(); - } - vertexKeyBuilder[instanceCount] = 0; - indexKeyBuilder[instanceCount] = 1; - vertexKeyBuilder.finish(); - indexKeyBuilder.finish(); - - // Try to grab data from the cache. - sk_sp<GrBuffer> vertexBuffer = rp->findByUniqueKey<GrBuffer>(vertexKey); - sk_sp<GrBuffer> indexBuffer = rp->findByUniqueKey<GrBuffer>(indexKey); - - // Draw using the cached buffers if possible. - if (vertexBuffer) { - this->drawVertices(target, gp.get(), vertexBuffer.get(), 0, indexBuffer.get(), 0); - return; - } - - // Calculate the stride. - size_t vertexStride = sizeof(SkPoint) + - (hasColorAttribute ? sizeof(uint32_t) : 0) + - (hasLocalCoordsAttribute ? sizeof(SkPoint) : 0) + - (hasBoneAttribute ? 4 * (sizeof(uint32_t) + sizeof(float)) : 0); - SkASSERT(vertexStride == gp->debugOnly_vertexStride()); - - // Allocate vertex buffer. - vertexBuffer.reset(rp->createBuffer(fVertexCount * vertexStride, - kVertex_GrBufferType, - kStatic_GrAccessPattern, - 0)); - void* verts = vertexBuffer ? vertexBuffer->map() : nullptr; - if (!verts) { - SkDebugf("Could not allocate vertices\n"); - return; - } - - // Allocate index buffer. - uint16_t* indices = nullptr; - if (this->isIndexed()) { - indexBuffer.reset(rp->createBuffer(fIndexCount * sizeof(uint16_t), - kIndex_GrBufferType, - kStatic_GrAccessPattern, - 0)); - indices = indexBuffer ? static_cast<uint16_t*>(indexBuffer->map()) : nullptr; if (!indices) { SkDebugf("Could not allocate indices\n"); return; } } - // Fill the buffers. - this->fillBuffers(hasColorAttribute, - hasLocalCoordsAttribute, - hasBoneAttribute, - vertexStride, - verts, - indices); - - // Unmap the buffers. - vertexBuffer->unmap(); - if (indexBuffer) { - indexBuffer->unmap(); - } - - // Cache the buffers. - rp->assignUniqueKeyToResource(vertexKey, vertexBuffer.get()); - rp->assignUniqueKeyToResource(indexKey, indexBuffer.get()); - - // Draw the vertices. - this->drawVertices(target, gp.get(), vertexBuffer.get(), 0, indexBuffer.get(), 0); -} - -void GrDrawVerticesOp::fillBuffers(bool hasColorAttribute, - bool hasLocalCoordsAttribute, - bool hasBoneAttribute, - size_t vertexStride, - void* verts, - uint16_t* indices) const { - int instanceCount = fMeshes.count(); - - // Copy data into the buffers. int vertexOffset = 0; // We have a fast case below for uploading the vertex data when the matrix is translate - // only and there are colors but not local coords. Fast case does not apply when there are bone - // transformations. - bool fastAttrs = hasColorAttribute && !hasLocalCoordsAttribute && !hasBoneAttribute; + // only and there are colors but not local coords. + bool fastAttrs = hasColorAttribute && !hasLocalCoordsAttribute; for (int i = 0; i < instanceCount; i++) { - // Get each mesh. const Mesh& mesh = fMeshes[i]; - - // Copy data into the index buffer. if (indices) { int indexCount = mesh.fVertices->indexCount(); for (int j = 0; j < indexCount; ++j) { *indices++ = mesh.fVertices->indices()[j] + vertexOffset; } } - - // Copy data into the vertex buffer. int vertexCount = mesh.fVertices->vertexCount(); const SkPoint* positions = mesh.fVertices->positions(); const SkColor* colors = mesh.fVertices->colors(); const SkPoint* localCoords = mesh.fVertices->texCoords(); - const SkVertices::BoneIndices* boneIndices = mesh.fVertices->boneIndices(); - const SkVertices::BoneWeights* boneWeights = mesh.fVertices->boneWeights(); bool fastMesh = (!this->hasMultipleViewMatrices() || mesh.fViewMatrix.getType() <= SkMatrix::kTranslate_Mask) && mesh.hasPerVertexColors(); if (fastAttrs && fastMesh) { - // Fast case. struct V { SkPoint fPos; uint32_t fColor; @@ -392,19 +207,9 @@ void GrDrawVerticesOp::fillBuffers(bool hasColorAttribute, } verts = v + vertexCount; } else { - // Normal case. static constexpr size_t kColorOffset = sizeof(SkPoint); - size_t offset = kColorOffset; - if (hasColorAttribute) { - offset += sizeof(uint32_t); - } - size_t localCoordOffset = offset; - if (hasLocalCoordsAttribute) { - offset += sizeof(SkPoint); - } - size_t boneIndexOffset = offset; - offset += 4 * sizeof(uint32_t); - size_t boneWeightOffset = offset; + size_t localCoordOffset = + hasColorAttribute ? kColorOffset + sizeof(uint32_t) : kColorOffset; for (int j = 0; j < vertexCount; ++j) { if (this->hasMultipleViewMatrices()) { @@ -426,40 +231,22 @@ void GrDrawVerticesOp::fillBuffers(bool hasColorAttribute, *(SkPoint*)((intptr_t)verts + localCoordOffset) = positions[j]; } } - if (hasBoneAttribute) { - const SkVertices::BoneIndices& indices = boneIndices[j]; - const SkVertices::BoneWeights& weights = boneWeights[j]; - for (int k = 0; k < 4; k++) { - size_t indexOffset = boneIndexOffset + sizeof(uint32_t) * k; - size_t weightOffset = boneWeightOffset + sizeof(float) * k; - *(uint32_t*)((intptr_t)verts + indexOffset) = indices.indices[k]; - *(float*)((intptr_t)verts + weightOffset) = weights.weights[k]; - } - } verts = (void*)((intptr_t)verts + vertexStride); } } vertexOffset += vertexCount; } -} -void GrDrawVerticesOp::drawVertices(Target* target, - GrGeometryProcessor* gp, - const GrBuffer* vertexBuffer, - int firstVertex, - const GrBuffer* indexBuffer, - int firstIndex) { GrMesh mesh(this->primitiveType()); - if (this->isIndexed()) { - mesh.setIndexed(indexBuffer, fIndexCount, - firstIndex, 0, fVertexCount - 1, - GrPrimitiveRestart::kNo); - } else { + if (!indices) { mesh.setNonIndexedNonInstanced(fVertexCount); + } else { + mesh.setIndexed(indexBuffer, fIndexCount, firstIndex, 0, fVertexCount - 1, + GrPrimitiveRestart::kNo); } mesh.setVertexData(vertexBuffer, firstVertex); auto pipe = fHelper.makePipeline(target); - target->draw(gp, pipe.fPipeline, pipe.fFixedDynamicState, mesh); + target->draw(gp.get(), pipe.fPipeline, pipe.fFixedDynamicState, mesh); } bool GrDrawVerticesOp::onCombineIfPossible(GrOp* t, const GrCaps& caps) { @@ -469,20 +256,6 @@ bool GrDrawVerticesOp::onCombineIfPossible(GrOp* t, const GrCaps& caps) { return false; } - // Meshes with bones cannot be combined because different meshes use different bones, so to - // combine them, the matrices would have to be combined, and the bone indices on each vertex - // would change, thus making the vertices uncacheable. - if (this->hasBones() || that->hasBones()) { - return false; - } - - // Non-volatile meshes cannot batch, because if a non-volatile mesh batches with another mesh, - // then on the next frame, if that non-volatile mesh is drawn, it will draw the other mesh - // that was saved in its vertex buffer, which is not necessarily there anymore. - if (!this->fMeshes[0].fVertices->isVolatile() || !that->fMeshes[0].fVertices->isVolatile()) { - return false; - } - if (!this->combinablePrimitive() || this->primitiveType() != that->primitiveType()) { return false; } @@ -637,8 +410,8 @@ GR_DRAW_OP_TEST_DEFINE(GrDrawVerticesOp) { if (GrFSAAType::kUnifiedMSAA == fsaaType && random->nextBool()) { aaType = GrAAType::kMSAA; } - return GrDrawVerticesOp::Make(context, std::move(paint), std::move(vertices), nullptr, 0, - viewMatrix, aaType, std::move(colorSpaceXform), &type); + return GrDrawVerticesOp::Make(context, std::move(paint), std::move(vertices), viewMatrix, + aaType, std::move(colorSpaceXform), &type); } #endif diff --git a/src/gpu/ops/GrDrawVerticesOp.h b/src/gpu/ops/GrDrawVerticesOp.h index 2e10fefe94..6d35c0d0e9 100644 --- a/src/gpu/ops/GrDrawVerticesOp.h +++ b/src/gpu/ops/GrDrawVerticesOp.h @@ -38,15 +38,13 @@ public: static std::unique_ptr<GrDrawOp> Make(GrContext* context, GrPaint&&, sk_sp<SkVertices>, - const SkMatrix bones[], - int boneCount, const SkMatrix& viewMatrix, GrAAType, sk_sp<GrColorSpaceXform>, GrPrimitiveType* overridePrimType = nullptr); - GrDrawVerticesOp(const Helper::MakeArgs&, GrColor, sk_sp<SkVertices>, const SkMatrix bones[], - int boneCount, GrPrimitiveType, GrAAType, sk_sp<GrColorSpaceXform>, + GrDrawVerticesOp(const Helper::MakeArgs& helperArgs, GrColor, sk_sp<SkVertices>, + GrPrimitiveType, GrAAType, sk_sp<GrColorSpaceXform>, const SkMatrix& viewMatrix); const char* name() const override { return "DrawVerticesOp"; } @@ -70,26 +68,7 @@ private: void onPrepareDraws(Target*) override; - void drawVolatile(Target*); - void drawNonVolatile(Target*); - - void fillBuffers(bool hasColorAttribute, - bool hasLocalCoordsAttribute, - bool hasBoneAttribute, - size_t vertexStride, - void* verts, - uint16_t* indices) const; - - void drawVertices(Target*, - GrGeometryProcessor*, - const GrBuffer* vertexBuffer, - int firstVertex, - const GrBuffer* indexBuffer, - int firstIndex); - - sk_sp<GrGeometryProcessor> makeGP(bool* hasColorAttribute, - bool* hasLocalCoordAttribute, - bool* hasBoneAttribute) const; + sk_sp<GrGeometryProcessor> makeGP(bool* hasColorAttribute, bool* hasLocalCoordAttribute) const; GrPrimitiveType primitiveType() const { return fPrimitiveType; } bool combinablePrimitive() const { @@ -103,11 +82,9 @@ private: struct Mesh { GrColor fColor; // Used if this->hasPerVertexColors() is false. sk_sp<SkVertices> fVertices; - std::vector<SkMatrix> fBones; SkMatrix fViewMatrix; bool fIgnoreTexCoords; bool fIgnoreColors; - bool fIgnoreBones; bool hasExplicitLocalCoords() const { return fVertices->hasTexCoords() && !fIgnoreTexCoords; @@ -116,10 +93,6 @@ private: bool hasPerVertexColors() const { return fVertices->hasColors() && !fIgnoreColors; } - - bool hasBones() const { - return fVertices->hasBones() && fBones.size() && !fIgnoreBones; - } }; bool isIndexed() const { @@ -132,22 +105,18 @@ private: } bool anyMeshHasExplicitLocalCoords() const { - return SkToBool(kAnyMeshHasExplicitLocalCoords_Flag & fFlags); + return SkToBool(kAnyMeshHasExplicitLocalCoords & fFlags); } bool hasMultipleViewMatrices() const { return SkToBool(kHasMultipleViewMatrices_Flag & fFlags); } - bool hasBones() const { - return SkToBool(kHasBones_Flag & fFlags); - } - enum Flags { - kRequiresPerVertexColors_Flag = 0x1, - kAnyMeshHasExplicitLocalCoords_Flag = 0x2, - kHasMultipleViewMatrices_Flag = 0x4, - kHasBones_Flag = 0x8, + kRequiresPerVertexColors_Flag = 0x1, + kAnyMeshHasExplicitLocalCoords = 0x2, + kHasMultipleViewMatrices_Flag = 0x4 + }; Helper fHelper; |