aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/gpu/GrShaderCaps.h4
-rw-r--r--src/gpu/GrShaderCaps.cpp3
-rw-r--r--src/gpu/gl/GrGLCaps.cpp7
-rw-r--r--src/gpu/glsl/GrGLSLGeometryShaderBuilder.cpp25
-rw-r--r--src/gpu/glsl/GrGLSLGeometryShaderBuilder.h3
5 files changed, 37 insertions, 5 deletions
diff --git a/include/gpu/GrShaderCaps.h b/include/gpu/GrShaderCaps.h
index 918138c878..36ab3c3c35 100644
--- a/include/gpu/GrShaderCaps.h
+++ b/include/gpu/GrShaderCaps.h
@@ -176,6 +176,9 @@ public:
bool requiresLocalOutputColorForFBFetch() const { return fRequiresLocalOutputColorForFBFetch; }
+ // On MacBook, geometry shaders break if they have more than one invocation.
+ bool mustImplementGSInvocationsWithLoop() const { return fMustImplementGSInvocationsWithLoop; }
+
// Returns the string of an extension that must be enabled in the shader to support
// derivatives. If nullptr is returned then no extension needs to be enabled. Before calling
// this function, the caller should check that shaderDerivativeSupport exists.
@@ -304,6 +307,7 @@ private:
bool fMustForceNegatedAtanParamToFloat : 1;
bool fAtan2ImplementedAsAtanYOverX : 1;
bool fRequiresLocalOutputColorForFBFetch : 1;
+ bool fMustImplementGSInvocationsWithLoop : 1;
PrecisionInfo fFloatPrecisions[kGrShaderTypeCount][kGrSLPrecisionCount];
int fPixelLocalStorageSize;
diff --git a/src/gpu/GrShaderCaps.cpp b/src/gpu/GrShaderCaps.cpp
index 621ac3db03..69af070bc7 100644
--- a/src/gpu/GrShaderCaps.cpp
+++ b/src/gpu/GrShaderCaps.cpp
@@ -58,6 +58,7 @@ GrShaderCaps::GrShaderCaps(const GrContextOptions& options) {
fMustForceNegatedAtanParamToFloat = false;
fAtan2ImplementedAsAtanYOverX = false;
fRequiresLocalOutputColorForFBFetch = false;
+ fMustImplementGSInvocationsWithLoop = false;
fFlatInterpolationSupport = false;
fNoPerspectiveInterpolationSupport = false;
fMultisampleInterpolationSupport = false;
@@ -144,6 +145,8 @@ SkString GrShaderCaps::dump() const {
"YES" : "NO"));
r.appendf("Must use local out color for FBFetch: %s\n", (fRequiresLocalOutputColorForFBFetch ?
"YES" : "NO"));
+ r.appendf("Must implement geo shader invocations with loop : %s\n",
+ (fMustImplementGSInvocationsWithLoop ? "YES" : "NO"));
r.appendf("Flat interpolation support: %s\n", (fFlatInterpolationSupport ? "YES" : "NO"));
r.appendf("No perspective interpolation support: %s\n", (fNoPerspectiveInterpolationSupport ?
"YES" : "NO"));
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index aea875f23b..4c252215a9 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -870,6 +870,13 @@ void GrGLCaps::initGLSL(const GrGLContextInfo& ctxInfo) {
if (shaderCaps->fFBFetchSupport && kQualcomm_GrGLVendor == ctxInfo.vendor()) {
shaderCaps->fRequiresLocalOutputColorForFBFetch = true;
}
+
+#ifdef SK_BUILD_FOR_MAC
+ // On at least some MacBooks, geometry shaders fall apart if we use more than one invocation. To
+ // work around this, we always use a single invocation and wrap the shader in a loop. The long-
+ // term plan for this WAR is for it to eventually be baked into SkSL.
+ shaderCaps->fMustImplementGSInvocationsWithLoop = true;
+#endif
}
bool GrGLCaps::hasPathRenderingSupport(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
diff --git a/src/gpu/glsl/GrGLSLGeometryShaderBuilder.cpp b/src/gpu/glsl/GrGLSLGeometryShaderBuilder.cpp
index a8e746cf0a..01f223f4b3 100644
--- a/src/gpu/glsl/GrGLSLGeometryShaderBuilder.cpp
+++ b/src/gpu/glsl/GrGLSLGeometryShaderBuilder.cpp
@@ -35,22 +35,39 @@ static const char* output_type_name(GrGLSLGeometryBuilder::OutputType out) {
GrGLSLGeometryBuilder::GrGLSLGeometryBuilder(GrGLSLProgramBuilder* program)
: INHERITED(program)
- , fIsConfigured(false) {
+ , fNumInvocations(0) {
}
void GrGLSLGeometryBuilder::configure(InputType inputType, OutputType outputType, int maxVertices,
int numInvocations) {
- SkASSERT(!fIsConfigured);
+ SkASSERT(!this->isConfigured());
+ fNumInvocations = numInvocations;
+ if (this->getProgramBuilder()->shaderCaps()->mustImplementGSInvocationsWithLoop()) {
+ maxVertices *= numInvocations;
+ numInvocations = 1;
+ }
this->addLayoutQualifier(input_type_name(inputType), kIn_InterfaceQualifier);
this->addLayoutQualifier(SkStringPrintf("invocations = %i", numInvocations).c_str(),
kIn_InterfaceQualifier);
this->addLayoutQualifier(output_type_name(outputType), kOut_InterfaceQualifier);
this->addLayoutQualifier(SkStringPrintf("max_vertices = %i", maxVertices).c_str(),
kOut_InterfaceQualifier);
- fIsConfigured = true;
}
void GrGLSLGeometryBuilder::onFinalize() {
- SkASSERT(fIsConfigured);
+ SkASSERT(this->isConfigured());
fProgramBuilder->varyingHandler()->getGeomDecls(&this->inputs(), &this->outputs());
+ GrShaderVar sk_InvocationID("sk_InvocationID", kInt_GrSLType);
+ this->declareGlobal(sk_InvocationID);
+ SkASSERT(sk_InvocationID.getName() == SkString("sk_InvocationID"));
+ if (this->getProgramBuilder()->shaderCaps()->mustImplementGSInvocationsWithLoop()) {
+ SkString invokeFn;
+ this->emitFunction(kVoid_GrSLType, "invoke", 0, nullptr, this->code().c_str(), &invokeFn);
+ this->code().printf("for (sk_InvocationID = 0; sk_InvocationID < %i; ++sk_InvocationID) {"
+ "%s();"
+ "EndPrimitive();"
+ "}", fNumInvocations, invokeFn.c_str());
+ } else {
+ this->codePrependf("sk_InvocationID = gl_InvocationID;");
+ }
}
diff --git a/src/gpu/glsl/GrGLSLGeometryShaderBuilder.h b/src/gpu/glsl/GrGLSLGeometryShaderBuilder.h
index feedcf2930..04be53030e 100644
--- a/src/gpu/glsl/GrGLSLGeometryShaderBuilder.h
+++ b/src/gpu/glsl/GrGLSLGeometryShaderBuilder.h
@@ -31,11 +31,12 @@ public:
};
void configure(InputType, OutputType, int maxVertices, int numInvocations = 1);
+ bool isConfigured() const { return fNumInvocations; }
private:
void onFinalize() override;
- bool fIsConfigured;
+ int fNumInvocations;
friend class GrGLProgramBuilder;