diff options
author | 2018-07-03 11:38:15 -0400 | |
---|---|---|
committer | 2018-07-03 16:07:44 +0000 | |
commit | b6307340e8a6a9d3a7517def7f5eaaadffd07d14 (patch) | |
tree | 7337790911d8e791d495f37f637382f3fb5acad3 /src/gpu/GrDefaultGeoProcFactory.cpp | |
parent | b7b73f5bbec55020c873cab6f4e11444b4011c34 (diff) |
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>
Diffstat (limited to 'src/gpu/GrDefaultGeoProcFactory.cpp')
-rw-r--r-- | src/gpu/GrDefaultGeoProcFactory.cpp | 142 |
1 files changed, 132 insertions, 10 deletions
diff --git a/src/gpu/GrDefaultGeoProcFactory.cpp b/src/gpu/GrDefaultGeoProcFactory.cpp index e2bf87b277..c9108e3d96 100644 --- a/src/gpu/GrDefaultGeoProcFactory.cpp +++ b/src/gpu/GrDefaultGeoProcFactory.cpp @@ -27,8 +27,13 @@ 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, @@ -37,10 +42,12 @@ public: const SkMatrix& viewMatrix, const SkMatrix& localMatrix, bool localCoordsWillBeRead, - uint8_t coverage) { + uint8_t coverage, + const SkMatrix bones[], + int boneCount) { return sk_sp<GrGeometryProcessor>(new DefaultGeoProc( gpTypeFlags, color, std::move(colorSpaceXform), viewMatrix, localMatrix, coverage, - localCoordsWillBeRead)); + localCoordsWillBeRead, bones, boneCount)); } const char* name() const override { return "DefaultGeometryProcessor"; } @@ -52,6 +59,9 @@ 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: @@ -99,11 +109,37 @@ 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, - gp.fInPosition.name(), + transformedPositionName, gp.viewMatrix(), &fViewMatrixUniform); @@ -147,8 +183,8 @@ public: GrProcessorKeyBuilder* b) { const DefaultGeoProc& def = gp.cast<DefaultGeoProc>(); uint32_t key = def.fFlags; - key |= (def.coverage() == 0xff) ? 0x10 : 0; - key |= (def.localCoordsWillBeRead() && def.localMatrix().hasPerspective()) ? 0x20 : 0x0; + key |= (def.coverage() == 0xff) ? 0x20 : 0; + key |= (def.localCoordsWillBeRead() && def.localMatrix().hasPerspective()) ? 0x40 : 0x0; key |= ComputePosKey(def.viewMatrix()) << 20; b->add32(key); b->add32(GrColorSpaceXform::XformKey(def.fColorSpaceXform.get())); @@ -180,6 +216,10 @@ public: this->setTransformDataHelper(dgp.fLocalMatrix, pdman, &transformIter); fColorSpaceHelper.setData(pdman, dgp.fColorSpaceXform.get()); + + if (dgp.hasBones()) { + pdman.setMatrix3fv(fBonesUniform, dgp.boneCount(), dgp.bones()); + } } private: @@ -189,6 +229,7 @@ public: UniformHandle fViewMatrixUniform; UniformHandle fColorUniform; UniformHandle fCoverageUniform; + UniformHandle fBonesUniform; GrGLSLColorSpaceXformHelper fColorSpaceHelper; typedef GrGLSLGeometryProcessor INHERITED; @@ -209,7 +250,9 @@ private: const SkMatrix& viewMatrix, const SkMatrix& localMatrix, uint8_t coverage, - bool localCoordsWillBeRead) + bool localCoordsWillBeRead, + const SkMatrix* bones, + int boneCount) : INHERITED(kDefaultGeoProc_ClassID) , fColor(color) , fViewMatrix(viewMatrix) @@ -217,7 +260,8 @@ private: , fCoverage(coverage) , fFlags(gpTypeFlags) , fLocalCoordsWillBeRead(localCoordsWillBeRead) - , fColorSpaceXform(std::move(colorSpaceXform)) { + , fColorSpaceXform(std::move(colorSpaceXform)) + , fBones() { fInPosition = {"inPosition", kFloat2_GrVertexAttribType}; int cnt = 1; if (fFlags & kColorAttribute_GPFlag) { @@ -232,17 +276,49 @@ 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); + return IthInitializedAttribute(i, + fInPosition, + fInColor, + fInLocalCoords, + fInCoverage, + fInBoneIndices, + fInBoneWeights); } Attribute fInPosition; Attribute fInColor; Attribute fInLocalCoords; Attribute fInCoverage; + Attribute fInBoneIndices; + Attribute fInBoneWeights; GrColor fColor; SkMatrix fViewMatrix; SkMatrix fLocalMatrix; @@ -250,6 +326,7 @@ private: uint32_t fFlags; bool fLocalCoordsWillBeRead; sk_sp<GrColorSpaceXform> fColorSpaceXform; + std::vector<float> fBones; GR_DECLARE_GEOMETRY_PROCESSOR_TEST @@ -273,6 +350,17 @@ 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), @@ -280,7 +368,9 @@ sk_sp<GrGeometryProcessor> DefaultGeoProc::TestCreate(GrProcessorTestData* d) { GrTest::TestMatrix(d->fRandom), GrTest::TestMatrix(d->fRandom), d->fRandom->nextBool(), - GrRandomCoverage(d->fRandom)); + GrRandomCoverage(d->fRandom), + bones.data(), + numBones); } #endif @@ -307,7 +397,9 @@ sk_sp<GrGeometryProcessor> GrDefaultGeoProcFactory::Make(const Color& color, viewMatrix, localCoords.fMatrix ? *localCoords.fMatrix : SkMatrix::I(), localCoordsWillBeRead, - inCoverage); + inCoverage, + nullptr, + 0); } sk_sp<GrGeometryProcessor> GrDefaultGeoProcFactory::MakeForDeviceSpace( @@ -330,3 +422,33 @@ 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); +} |