diff options
author | csmartdalton <csmartdalton@google.com> | 2016-07-13 08:48:53 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-07-13 08:48:53 -0700 |
commit | 0caee1778d92c30ff6eb053f7fb58509d275a2df (patch) | |
tree | 0f5c6a2b911155c73fc8a51dd9d03db278fc36d4 | |
parent | b3772dcb306241f53fe10ba62117ed67f89f24b2 (diff) |
Replace switch statements in instanced vertex shaders
Replaces switch statements with 3-way if’s. The switches as they were
seemed to be the cause of an Adreno compiler crash.
BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2136103011
Review-Url: https://codereview.chromium.org/2136103011
-rw-r--r-- | src/gpu/instanced/InstanceProcessor.cpp | 138 |
1 files changed, 81 insertions, 57 deletions
diff --git a/src/gpu/instanced/InstanceProcessor.cpp b/src/gpu/instanced/InstanceProcessor.cpp index acad4c1e1b..82e3e219a3 100644 --- a/src/gpu/instanced/InstanceProcessor.cpp +++ b/src/gpu/instanced/InstanceProcessor.cpp @@ -147,12 +147,12 @@ public: void init(GrGLSLVaryingHandler*, GrGLSLVertexBuilder*); virtual void setupRect(GrGLSLVertexBuilder*) = 0; virtual void setupOval(GrGLSLVertexBuilder*) = 0; - void setupRRect(GrGLSLVertexBuilder*); + void setupRRect(GrGLSLVertexBuilder*, int* usedShapeDefinitions); void initInnerShape(GrGLSLVaryingHandler*, GrGLSLVertexBuilder*); virtual void setupInnerRect(GrGLSLVertexBuilder*) = 0; virtual void setupInnerOval(GrGLSLVertexBuilder*) = 0; - void setupInnerRRect(GrGLSLVertexBuilder*); + void setupInnerSimpleRRect(GrGLSLVertexBuilder*); const char* outShapeCoords() { return fModifiedShapeCoords ? fModifiedShapeCoords : fInputs.attr(Attrib::kShapeCoords); @@ -184,7 +184,7 @@ protected: virtual void onSetupRRect(GrGLSLVertexBuilder*) {} virtual void onInitInnerShape(GrGLSLVaryingHandler*, GrGLSLVertexBuilder*) = 0; - virtual void onSetupInnerRRect(GrGLSLVertexBuilder*) = 0; + virtual void onSetupInnerSimpleRRect(GrGLSLVertexBuilder*) = 0; virtual void onEmitCode(GrGLSLVertexBuilder*, GrGLSLPPFragmentBuilder*, const char* outCoverage, const char* outColor) = 0; @@ -237,11 +237,8 @@ void GLSLInstanceProcessor::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) { v->codeAppend ("}"); } - int usedShapeTypes = 0; - bool hasSingleShapeType = SkIsPow2(ip.batchInfo().fShapeTypes); if (!hasSingleShapeType) { - usedShapeTypes |= ip.batchInfo().fShapeTypes; v->define("SHAPE_TYPE_BIT", kShapeType_InfoBit); v->codeAppendf("uint shapeType = %s >> SHAPE_TYPE_BIT;", inputs.attr(Attrib::kInstanceInfo)); @@ -250,38 +247,46 @@ void GLSLInstanceProcessor::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) { SkAutoTDelete<Backend> backend(Backend::Create(pipeline, ip.batchInfo(), inputs)); backend->init(varyingHandler, v); - if (hasSingleShapeType) { + int usedShapeDefinitions = 0; + + if (hasSingleShapeType || !(ip.batchInfo().fShapeTypes & ~kRRect_ShapesMask)) { if (kRect_ShapeFlag == ip.batchInfo().fShapeTypes) { backend->setupRect(v); } else if (kOval_ShapeFlag == ip.batchInfo().fShapeTypes) { backend->setupOval(v); } else { - backend->setupRRect(v); + backend->setupRRect(v, &usedShapeDefinitions); } } else { - v->codeAppend ("switch (shapeType) {"); - if (ip.batchInfo().fShapeTypes & kRect_ShapeFlag) { - v->codeAppend ("case RECT_SHAPE_TYPE: {"); - backend->setupRect(v); - v->codeAppend ("} break;"); + if (ip.batchInfo().fShapeTypes & kRRect_ShapesMask) { + v->codeAppend ("if (shapeType >= SIMPLE_R_RECT_SHAPE_TYPE) {"); + backend->setupRRect(v, &usedShapeDefinitions); + v->codeAppend ("}"); + usedShapeDefinitions |= kSimpleRRect_ShapeFlag; } if (ip.batchInfo().fShapeTypes & kOval_ShapeFlag) { - v->codeAppend ("case OVAL_SHAPE_TYPE: {"); + if (ip.batchInfo().fShapeTypes & kRect_ShapeFlag) { + if (ip.batchInfo().fShapeTypes & kRRect_ShapesMask) { + v->codeAppend ("else "); + } + v->codeAppend ("if (OVAL_SHAPE_TYPE == shapeType) {"); + usedShapeDefinitions |= kOval_ShapeFlag; + } else { + v->codeAppend ("else {"); + } backend->setupOval(v); - v->codeAppend ("} break;"); + v->codeAppend ("}"); } - if (ip.batchInfo().fShapeTypes & kRRect_ShapesMask) { - v->codeAppend ("default: {"); - backend->setupRRect(v); - v->codeAppend ("} break;"); + if (ip.batchInfo().fShapeTypes & kRect_ShapeFlag) { + v->codeAppend ("else {"); + backend->setupRect(v); + v->codeAppend ("}"); } - v->codeAppend ("}"); } if (ip.batchInfo().fInnerShapeTypes) { bool hasSingleInnerShapeType = SkIsPow2(ip.batchInfo().fInnerShapeTypes); if (!hasSingleInnerShapeType) { - usedShapeTypes |= ip.batchInfo().fInnerShapeTypes; v->definef("INNER_SHAPE_TYPE_MASK", "0x%xu", kInnerShapeType_InfoMask); v->define("INNER_SHAPE_TYPE_BIT", kInnerShapeType_InfoBit); v->codeAppendf("uint innerShapeType = ((%s & INNER_SHAPE_TYPE_MASK) >> " @@ -303,41 +308,55 @@ void GLSLInstanceProcessor::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) { backend->initInnerShape(varyingHandler, v); + SkASSERT(0 == (ip.batchInfo().fInnerShapeTypes & kRRect_ShapesMask) || + kSimpleRRect_ShapeFlag == (ip.batchInfo().fInnerShapeTypes & kRRect_ShapesMask)); + if (hasSingleInnerShapeType) { if (kRect_ShapeFlag == ip.batchInfo().fInnerShapeTypes) { backend->setupInnerRect(v); } else if (kOval_ShapeFlag == ip.batchInfo().fInnerShapeTypes) { backend->setupInnerOval(v); } else { - backend->setupInnerRRect(v); + backend->setupInnerSimpleRRect(v); } } else { - v->codeAppend("switch (innerShapeType) {"); - if (ip.batchInfo().fInnerShapeTypes & kRect_ShapeFlag) { - v->codeAppend("case RECT_SHAPE_TYPE: {"); - backend->setupInnerRect(v); - v->codeAppend("} break;"); + if (ip.batchInfo().fInnerShapeTypes & kSimpleRRect_ShapeFlag) { + v->codeAppend ("if (SIMPLE_R_RECT_SHAPE_TYPE == innerShapeType) {"); + backend->setupInnerSimpleRRect(v); + v->codeAppend("}"); + usedShapeDefinitions |= kSimpleRRect_ShapeFlag; } if (ip.batchInfo().fInnerShapeTypes & kOval_ShapeFlag) { - v->codeAppend("case OVAL_SHAPE_TYPE: {"); + if (ip.batchInfo().fInnerShapeTypes & kRect_ShapeFlag) { + if (ip.batchInfo().fInnerShapeTypes & kSimpleRRect_ShapeFlag) { + v->codeAppend ("else "); + } + v->codeAppend ("if (OVAL_SHAPE_TYPE == innerShapeType) {"); + usedShapeDefinitions |= kOval_ShapeFlag; + } else { + v->codeAppend ("else {"); + } backend->setupInnerOval(v); - v->codeAppend("} break;"); + v->codeAppend("}"); } - if (ip.batchInfo().fInnerShapeTypes & kRRect_ShapesMask) { - v->codeAppend("default: {"); - backend->setupInnerRRect(v); - v->codeAppend("} break;"); + if (ip.batchInfo().fInnerShapeTypes & kRect_ShapeFlag) { + v->codeAppend("else {"); + backend->setupInnerRect(v); + v->codeAppend("}"); } - v->codeAppend("}"); } } - if (usedShapeTypes & kRect_ShapeFlag) { - v->definef("RECT_SHAPE_TYPE", "%du", (int)ShapeType::kRect); - } - if (usedShapeTypes & kOval_ShapeFlag) { + if (usedShapeDefinitions & kOval_ShapeFlag) { v->definef("OVAL_SHAPE_TYPE", "%du", (int)ShapeType::kOval); } + if (usedShapeDefinitions & kSimpleRRect_ShapeFlag) { + v->definef("SIMPLE_R_RECT_SHAPE_TYPE", "%du", (int)ShapeType::kSimpleRRect); + } + if (usedShapeDefinitions & kNinePatch_ShapeFlag) { + v->definef("NINE_PATCH_SHAPE_TYPE", "%du", (int)ShapeType::kNinePatch); + } + SkASSERT(!(usedShapeDefinitions & (kRect_ShapeFlag | kComplexRRect_ShapeFlag))); backend->emitCode(v, f, pipeline.ignoresCoverage() ? nullptr : args.fOutputCoverage, args.fOutputColor); @@ -393,7 +412,7 @@ void GLSLInstanceProcessor::Backend::init(GrGLSLVaryingHandler* varyingHandler, } } -void GLSLInstanceProcessor::Backend::setupRRect(GrGLSLVertexBuilder* v) { +void GLSLInstanceProcessor::Backend::setupRRect(GrGLSLVertexBuilder* v, int* usedShapeDefinitions) { v->codeAppendf("uvec2 corner = uvec2(%s & 1, (%s >> 1) & 1);", fInputs.attr(Attrib::kVertexAttrs), fInputs.attr(Attrib::kVertexAttrs)); v->codeAppend ("vec2 cornerSign = vec2(corner) * 2.0 - 1.0;"); @@ -411,25 +430,30 @@ void GLSLInstanceProcessor::Backend::setupRRect(GrGLSLVertexBuilder* v) { this->setupComplexRadii(v); } } else { - v->codeAppend("switch (shapeType) {"); if (types & kSimpleRRect_ShapeFlag) { - v->definef("SIMPLE_R_RECT_SHAPE_TYPE", "%du", (int)ShapeType::kSimpleRRect); - v->codeAppend ("case SIMPLE_R_RECT_SHAPE_TYPE: {"); + v->codeAppend ("if (SIMPLE_R_RECT_SHAPE_TYPE == shapeType) {"); this->setupSimpleRadii(v); - v->codeAppend ("} break;"); + v->codeAppend ("}"); + *usedShapeDefinitions |= kSimpleRRect_ShapeFlag; } if (types & kNinePatch_ShapeFlag) { - v->definef("NINE_PATCH_SHAPE_TYPE", "%du", (int)ShapeType::kNinePatch); - v->codeAppend ("case NINE_PATCH_SHAPE_TYPE: {"); + if (types & kComplexRRect_ShapeFlag) { + if (types & kSimpleRRect_ShapeFlag) { + v->codeAppend ("else "); + } + v->codeAppend ("if (NINE_PATCH_SHAPE_TYPE == shapeType) {"); + *usedShapeDefinitions |= kNinePatch_ShapeFlag; + } else { + v->codeAppend ("else {"); + } this->setupNinePatchRadii(v); - v->codeAppend ("} break;"); + v->codeAppend ("}"); } if (types & kComplexRRect_ShapeFlag) { - v->codeAppend ("default: {"); + v->codeAppend ("else {"); this->setupComplexRadii(v); - v->codeAppend ("} break;"); + v->codeAppend ("}"); } - v->codeAppend("}"); } this->adjustRRectVertices(v); @@ -507,12 +531,12 @@ void GLSLInstanceProcessor::Backend::initInnerShape(GrGLSLVaryingHandler* varyin } } -void GLSLInstanceProcessor::Backend::setupInnerRRect(GrGLSLVertexBuilder* v) { +void GLSLInstanceProcessor::Backend::setupInnerSimpleRRect(GrGLSLVertexBuilder* v) { v->codeAppend("mat2 innerP = "); fInputs.fetchNextParam(kMat22f_GrSLType); v->codeAppend(";"); v->codeAppend("vec2 innerRadii = innerP[0] * 2.0 / innerP[1];"); - this->onSetupInnerRRect(v); + this->onSetupInnerSimpleRRect(v); } void GLSLInstanceProcessor::Backend::emitCode(GrGLSLVertexBuilder* v, GrGLSLPPFragmentBuilder* f, @@ -550,7 +574,7 @@ private: void onInitInnerShape(GrGLSLVaryingHandler*, GrGLSLVertexBuilder*) override; void setupInnerRect(GrGLSLVertexBuilder*) override; void setupInnerOval(GrGLSLVertexBuilder*) override; - void onSetupInnerRRect(GrGLSLVertexBuilder*) override; + void onSetupInnerSimpleRRect(GrGLSLVertexBuilder*) override; void onEmitCode(GrGLSLVertexBuilder*, GrGLSLPPFragmentBuilder*, const char*, const char*) override; @@ -600,7 +624,7 @@ void GLSLInstanceProcessor::BackendNonAA::setupInnerOval(GrGLSLVertexBuilder* v) } } -void GLSLInstanceProcessor::BackendNonAA::onSetupInnerRRect(GrGLSLVertexBuilder* v) { +void GLSLInstanceProcessor::BackendNonAA::onSetupInnerSimpleRRect(GrGLSLVertexBuilder* v) { v->codeAppendf("%s = vec4(1.0 - innerRadii, 1.0 / innerRadii);", fInnerRRect.vsOut()); } @@ -690,7 +714,7 @@ private: void onInitInnerShape(GrGLSLVaryingHandler*, GrGLSLVertexBuilder*) override; void setupInnerRect(GrGLSLVertexBuilder*) override; void setupInnerOval(GrGLSLVertexBuilder*) override; - void onSetupInnerRRect(GrGLSLVertexBuilder*) override; + void onSetupInnerSimpleRRect(GrGLSLVertexBuilder*) override; void onEmitCode(GrGLSLVertexBuilder*, GrGLSLPPFragmentBuilder*, const char* outCoverage, const char* outColor) override; @@ -882,7 +906,7 @@ void GLSLInstanceProcessor::BackendCoverage::setupInnerOval(GrGLSLVertexBuilder* } } -void GLSLInstanceProcessor::BackendCoverage::onSetupInnerRRect(GrGLSLVertexBuilder* v) { +void GLSLInstanceProcessor::BackendCoverage::onSetupInnerSimpleRRect(GrGLSLVertexBuilder* v) { // The distance to ellipse formula doesn't work well when the radii are less than half a pixel. v->codeAppend ("innerRadii = max(innerRadii, bloat);"); v->codeAppendf("%s = 1.0 / (innerRadii * innerRadii * innerShapeHalfSize * " @@ -1064,7 +1088,7 @@ private: void onInitInnerShape(GrGLSLVaryingHandler*, GrGLSLVertexBuilder*) override; void setupInnerRect(GrGLSLVertexBuilder*) override; void setupInnerOval(GrGLSLVertexBuilder*) override; - void onSetupInnerRRect(GrGLSLVertexBuilder*) override; + void onSetupInnerSimpleRRect(GrGLSLVertexBuilder*) override; void onEmitCode(GrGLSLVertexBuilder*, GrGLSLPPFragmentBuilder*, const char*, const char*) override; @@ -1319,7 +1343,7 @@ void GLSLInstanceProcessor::BackendMultisample::setupInnerOval(GrGLSLVertexBuild } } -void GLSLInstanceProcessor::BackendMultisample::onSetupInnerRRect(GrGLSLVertexBuilder* v) { +void GLSLInstanceProcessor::BackendMultisample::onSetupInnerSimpleRRect(GrGLSLVertexBuilder* v) { // Avoid numeric instability by not allowing the inner radii to get smaller than 1/10th pixel. if (fFragInnerShapeHalfSpan.vsOut()) { v->codeAppendf("innerRadii = max(innerRadii, 2e-1 * %s);", fFragInnerShapeHalfSpan.vsOut()); |