aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar csmartdalton <csmartdalton@google.com>2016-07-13 08:48:53 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-07-13 08:48:53 -0700
commit0caee1778d92c30ff6eb053f7fb58509d275a2df (patch)
tree0f5c6a2b911155c73fc8a51dd9d03db278fc36d4
parentb3772dcb306241f53fe10ba62117ed67f89f24b2 (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.cpp138
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());