From 2e777ead127b03a06ccc7dfc983e1b28e1aa2f86 Mon Sep 17 00:00:00 2001 From: csmartdalton Date: Wed, 15 Feb 2017 10:41:27 -0700 Subject: Add a workaround for platforms with broken geo shader invocations BUG=skia: Change-Id: I9105b65b522d9ffac5a90ca7126bfd4ae88f8069 Reviewed-on: https://skia-review.googlesource.com/8422 Reviewed-by: Greg Daniel Reviewed-by: Brian Salomon Commit-Queue: Chris Dalton --- src/gpu/GrShaderCaps.cpp | 3 +++ src/gpu/gl/GrGLCaps.cpp | 7 +++++++ src/gpu/glsl/GrGLSLGeometryShaderBuilder.cpp | 25 +++++++++++++++++++++---- src/gpu/glsl/GrGLSLGeometryShaderBuilder.h | 3 ++- 4 files changed, 33 insertions(+), 5 deletions(-) (limited to 'src') 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; -- cgit v1.2.3