diff options
-rw-r--r-- | include/gpu/GrShaderCaps.h | 15 | ||||
-rw-r--r-- | src/gpu/GrShaderCaps.cpp | 6 | ||||
-rw-r--r-- | src/gpu/gl/GrGLCaps.cpp | 22 | ||||
-rw-r--r-- | src/gpu/vk/GrVkCaps.cpp | 2 | ||||
-rw-r--r-- | src/sksl/SkSLGLSLCodeGenerator.cpp | 14 | ||||
-rw-r--r-- | src/sksl/SkSLGLSLCodeGenerator.h | 1 | ||||
-rw-r--r-- | src/sksl/SkSLIRGenerator.cpp | 10 | ||||
-rw-r--r-- | src/sksl/SkSLUtil.h | 15 | ||||
-rw-r--r-- | tests/SkSLGLSLTest.cpp | 23 |
9 files changed, 84 insertions, 24 deletions
diff --git a/include/gpu/GrShaderCaps.h b/include/gpu/GrShaderCaps.h index 667433c295..b10ad60b5a 100644 --- a/include/gpu/GrShaderCaps.h +++ b/include/gpu/GrShaderCaps.h @@ -73,6 +73,7 @@ public: bool shaderDerivativeSupport() const { return fShaderDerivativeSupport; } bool geometryShaderSupport() const { return fGeometryShaderSupport; } + bool gsInvocationsSupport() const { return fGSInvocationsSupport; } bool pathRenderingSupport() const { return fPathRenderingSupport; } bool dstReadInShaderSupport() const { return fDstReadInShaderSupport; } bool dualSourceBlendingSupport() const { return fDualSourceBlendingSupport; } @@ -165,9 +166,6 @@ public: bool requiresLocalOutputColorForFBFetch() const { return fRequiresLocalOutputColorForFBFetch; } - // On MacBook, geometry shaders break if they have more than one invocation. - bool mustImplementGSInvocationsWithLoop() const { return fMustImplementGSInvocationsWithLoop; } - bool mustObfuscateUniformColor() const { return fMustObfuscateUniformColor; } // The D3D shader compiler, when targeting PS 3.0 (ie within ANGLE) fails to compile certain @@ -184,6 +182,14 @@ public: return fShaderDerivativeExtensionString; } + // Returns the string of an extension that must be enabled in the shader to support + // geometry shader invocations. If nullptr is returned then no extension needs to be enabled. + // Before calling this function, the caller must verify that gsInvocationsSupport exists. + const char* gsInvocationsExtensionString() const { + SkASSERT(this->gsInvocationsSupport()); + return fGSInvocationsExtensionString; + } + // Returns the string of an extension that will do all necessary coord transfomations needed // when reading the fragment position. If such an extension does not exisits, this function // returns a nullptr, and all transforms of the frag position must be done manually in the @@ -277,6 +283,7 @@ private: bool fShaderDerivativeSupport : 1; bool fGeometryShaderSupport : 1; + bool fGSInvocationsSupport : 1; bool fPathRenderingSupport : 1; bool fDstReadInShaderSupport : 1; bool fDualSourceBlendingSupport : 1; @@ -306,7 +313,6 @@ private: bool fMustForceNegatedAtanParamToFloat : 1; bool fAtan2ImplementedAsAtanYOverX : 1; bool fRequiresLocalOutputColorForFBFetch : 1; - bool fMustImplementGSInvocationsWithLoop : 1; bool fMustObfuscateUniformColor : 1; bool fMustGuardDivisionEvenAfterExplicitZeroCheck : 1; @@ -315,6 +321,7 @@ private: const char* fVersionDeclString; const char* fShaderDerivativeExtensionString; + const char* fGSInvocationsExtensionString; const char* fFragCoordConventionsExtensionString; const char* fSecondaryOutputExtensionString; const char* fExternalTextureExtensionString; diff --git a/src/gpu/GrShaderCaps.cpp b/src/gpu/GrShaderCaps.cpp index 90c2e68a93..0ee9339b45 100644 --- a/src/gpu/GrShaderCaps.cpp +++ b/src/gpu/GrShaderCaps.cpp @@ -43,6 +43,7 @@ GrShaderCaps::GrShaderCaps(const GrContextOptions& options) { fGLSLGeneration = k330_GrGLSLGeneration; fShaderDerivativeSupport = false; fGeometryShaderSupport = false; + fGSInvocationsSupport = false; fPathRenderingSupport = false; fDstReadInShaderSupport = false; fDualSourceBlendingSupport = false; @@ -61,7 +62,6 @@ GrShaderCaps::GrShaderCaps(const GrContextOptions& options) { fMustForceNegatedAtanParamToFloat = false; fAtan2ImplementedAsAtanYOverX = false; fRequiresLocalOutputColorForFBFetch = false; - fMustImplementGSInvocationsWithLoop = false; fMustObfuscateUniformColor = false; fMustGuardDivisionEvenAfterExplicitZeroCheck = false; fFlatInterpolationSupport = false; @@ -76,6 +76,7 @@ GrShaderCaps::GrShaderCaps(const GrContextOptions& options) { fVersionDeclString = nullptr; fShaderDerivativeExtensionString = nullptr; + fGSInvocationsExtensionString = nullptr; fFragCoordConventionsExtensionString = nullptr; fSecondaryOutputExtensionString = nullptr; fExternalTextureExtensionString = nullptr; @@ -102,6 +103,7 @@ void GrShaderCaps::dumpJSON(SkJSONWriter* writer) const { writer->appendBool("Shader Derivative Support", fShaderDerivativeSupport); writer->appendBool("Geometry Shader Support", fGeometryShaderSupport); + writer->appendBool("Geometry Shader Invocations Support", fGSInvocationsSupport); writer->appendBool("Path Rendering Support", fPathRenderingSupport); writer->appendBool("Dst Read In Shader Support", fDstReadInShaderSupport); writer->appendBool("Dual Source Blending Support", fDualSourceBlendingSupport); @@ -150,8 +152,6 @@ void GrShaderCaps::dumpJSON(SkJSONWriter* writer) const { writer->appendBool("Can use fract() for negative values", fCanUseFractForNegativeValues); writer->appendBool("Must force negated atan param to float", fMustForceNegatedAtanParamToFloat); writer->appendBool("Must use local out color for FBFetch", fRequiresLocalOutputColorForFBFetch); - writer->appendBool("Must implement geo shader invocations with loop", - fMustImplementGSInvocationsWithLoop); writer->appendBool("Must obfuscate uniform color", fMustObfuscateUniformColor); writer->appendBool("Must guard division even after explicit zero check", fMustGuardDivisionEvenAfterExplicitZeroCheck); diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp index c424b84a1a..21aadd59f6 100644 --- a/src/gpu/gl/GrGLCaps.cpp +++ b/src/gpu/gl/GrGLCaps.cpp @@ -307,10 +307,24 @@ void GrGLCaps::init(const GrContextOptions& contextOptions, shaderCaps->fDualSourceBlendingSupport = (ctxInfo.version() >= GR_GL_VER(3, 3) || ctxInfo.hasExtension("GL_ARB_blend_func_extended")) && GrGLSLSupportsNamedFragmentShaderOutputs(ctxInfo.glslGeneration()); + shaderCaps->fShaderDerivativeSupport = true; + // we don't support GL_ARB_geometry_shader4, just GL 3.2+ GS shaderCaps->fGeometryShaderSupport = ctxInfo.version() >= GR_GL_VER(3, 2) && ctxInfo.glslGeneration() >= k150_GrGLSLGeneration; + if (shaderCaps->fGeometryShaderSupport) { + // On at least some MacBooks, GLSL 4.0 geometry shaders break if we use invocations. +#ifndef SK_BUILD_FOR_MAC + if (ctxInfo.glslGeneration() >= k400_GrGLSLGeneration) { + shaderCaps->fGSInvocationsSupport = true; + } else if (ctxInfo.hasExtension("GL_ARB_gpu_shader5")) { + shaderCaps->fGSInvocationsSupport = true; + shaderCaps->fGSInvocationsExtensionString = "GL_ARB_gpu_shader5"; + } +#endif + } + shaderCaps->fIntegerSupport = ctxInfo.version() >= GR_GL_VER(3, 0) && ctxInfo.glslGeneration() >= k130_GrGLSLGeneration; } @@ -321,6 +335,7 @@ void GrGLCaps::init(const GrContextOptions& contextOptions, ctxInfo.hasExtension("GL_OES_standard_derivatives"); shaderCaps->fGeometryShaderSupport = ctxInfo.hasExtension("GL_EXT_geometry_shader"); + shaderCaps->fGSInvocationsSupport = shaderCaps->fGeometryShaderSupport; shaderCaps->fIntegerSupport = ctxInfo.version() >= GR_GL_VER(3, 0) && ctxInfo.glslGeneration() >= k330_GrGLSLGeneration; // We use this value for GLSL ES 3.0. @@ -938,13 +953,6 @@ void GrGLCaps::initGLSL(const GrGLContextInfo& ctxInfo) { 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 - // Newer Mali GPUs do incorrect static analysis in specific situations: If there is uniform // color, and that uniform contains an opaque color, and the output of the shader is only based // on that uniform plus soemthing un-trackable (like a texture read), the compiler will deduce diff --git a/src/gpu/vk/GrVkCaps.cpp b/src/gpu/vk/GrVkCaps.cpp index c92c7d59f9..1b0db7fb23 100644 --- a/src/gpu/vk/GrVkCaps.cpp +++ b/src/gpu/vk/GrVkCaps.cpp @@ -242,7 +242,9 @@ void GrVkCaps::initShaderCaps(const VkPhysicalDeviceProperties& properties, uint // GrShaderCaps shaderCaps->fShaderDerivativeSupport = true; + shaderCaps->fGeometryShaderSupport = SkToBool(featureFlags & kGeometryShader_GrVkFeatureFlag); + shaderCaps->fGSInvocationsSupport = shaderCaps->fGeometryShaderSupport; shaderCaps->fDualSourceBlendingSupport = SkToBool(featureFlags & kDualSrcBlend_GrVkFeatureFlag); if (kAMD_VkVendor == properties.vendorID) { diff --git a/src/sksl/SkSLGLSLCodeGenerator.cpp b/src/sksl/SkSLGLSLCodeGenerator.cpp index 389acfb1f5..229b183ac7 100644 --- a/src/sksl/SkSLGLSLCodeGenerator.cpp +++ b/src/sksl/SkSLGLSLCodeGenerator.cpp @@ -1005,10 +1005,20 @@ void GLSLCodeGenerator::writeProgramElement(const ProgramElement& e) { case ProgramElement::kFunction_Kind: this->writeFunction((FunctionDefinition&) e); break; - case ProgramElement::kModifiers_Kind: - this->writeModifiers(((ModifiersDeclaration&) e).fModifiers, true); + case ProgramElement::kModifiers_Kind: { + const Modifiers& modifiers = ((ModifiersDeclaration&) e).fModifiers; + if (!fFoundGSInvocations && modifiers.fLayout.fInvocations >= 0) { + if (fProgram.fSettings.fCaps->gsInvocationsExtensionString()) { + fHeader.writeText("#extension "); + fHeader.writeText(fProgram.fSettings.fCaps->gsInvocationsExtensionString()); + fHeader.writeText(" : require\n"); + } + fFoundGSInvocations = true; + } + this->writeModifiers(modifiers, true); this->writeLine(";"); break; + } default: printf("%s\n", e.description().c_str()); ABORT("unsupported program element"); diff --git a/src/sksl/SkSLGLSLCodeGenerator.h b/src/sksl/SkSLGLSLCodeGenerator.h index 4813d0d155..7c736b35a1 100644 --- a/src/sksl/SkSLGLSLCodeGenerator.h +++ b/src/sksl/SkSLGLSLCodeGenerator.h @@ -199,6 +199,7 @@ protected: // true if we have run into usages of dFdx / dFdy bool fFoundDerivatives = false; bool fFoundImageDecl = false; + bool fFoundGSInvocations = false; bool fSetupFragPositionGlobal = false; bool fSetupFragPositionLocal = false; diff --git a/src/sksl/SkSLIRGenerator.cpp b/src/sksl/SkSLIRGenerator.cpp index 2c6b9e3f5c..0c872e4676 100644 --- a/src/sksl/SkSLIRGenerator.cpp +++ b/src/sksl/SkSLIRGenerator.cpp @@ -290,7 +290,7 @@ std::unique_ptr<ModifiersDeclaration> IRGenerator::convertModifiersDeclaration( Modifiers modifiers = m.fModifiers; if (modifiers.fLayout.fInvocations != -1) { fInvocations = modifiers.fLayout.fInvocations; - if (fSettings->fCaps && fSettings->fCaps->mustImplementGSInvocationsWithLoop()) { + if (fSettings->fCaps && !fSettings->fCaps->gsInvocationsSupport()) { modifiers.fLayout.fInvocations = -1; Variable* invocationId = (Variable*) (*fSymbolTable)["sk_InvocationID"]; ASSERT(invocationId); @@ -301,7 +301,7 @@ std::unique_ptr<ModifiersDeclaration> IRGenerator::convertModifiersDeclaration( } } if (modifiers.fLayout.fMaxVertices != -1 && fInvocations > 0 && fSettings->fCaps && - fSettings->fCaps->mustImplementGSInvocationsWithLoop()) { + !fSettings->fCaps->gsInvocationsSupport()) { modifiers.fLayout.fMaxVertices *= fInvocations; } return std::unique_ptr<ModifiersDeclaration>(new ModifiersDeclaration(modifiers)); @@ -676,9 +676,9 @@ void IRGenerator::convertFunction(const ASTFunction& f, for (size_t i = 0; i < parameters.size(); i++) { fSymbolTable->addWithoutOwnership(parameters[i]->fName, decl->fParameters[i]); } - bool needInvocationIDWorkaround = fSettings->fCaps && - fSettings->fCaps->mustImplementGSInvocationsWithLoop() && - fInvocations != -1 && f.fName == "main"; + bool needInvocationIDWorkaround = fInvocations != -1 && f.fName == "main" && + fSettings->fCaps && + !fSettings->fCaps->gsInvocationsSupport(); ASSERT(!fExtraVars.size()); std::unique_ptr<Block> body = this->convertBlock(*f.fBody); for (auto& v : fExtraVars) { diff --git a/src/sksl/SkSLUtil.h b/src/sksl/SkSLUtil.h index 808ec8a1d4..c4a6475034 100644 --- a/src/sksl/SkSLUtil.h +++ b/src/sksl/SkSLUtil.h @@ -180,6 +180,7 @@ public: sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions()); result->fVersionDeclString = "#version 400"; result->fShaderDerivativeSupport = true; + result->fGSInvocationsSupport = true; return result; } @@ -248,10 +249,20 @@ public: return result; } - static sk_sp<GrShaderCaps> MustImplementGSInvocationsWithLoop() { + static sk_sp<GrShaderCaps> NoGSInvocationsSupport() { sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions()); result->fVersionDeclString = "#version 400"; - result->fMustImplementGSInvocationsWithLoop = true; + result->fGeometryShaderSupport = true; + result->fGSInvocationsSupport = false; + return result; + } + + static sk_sp<GrShaderCaps> GSInvocationsExtensionString() { + sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions()); + result->fVersionDeclString = "#version 400"; + result->fGeometryShaderSupport = true; + result->fGSInvocationsSupport = true; + result->fGSInvocationsExtensionString = "GL_ARB_gpu_shader5"; return result; } diff --git a/tests/SkSLGLSLTest.cpp b/tests/SkSLGLSLTest.cpp index 3845b8b438..28d5039121 100644 --- a/tests/SkSLGLSLTest.cpp +++ b/tests/SkSLGLSLTest.cpp @@ -1434,7 +1434,7 @@ DEF_TEST(SkSLInvocations, r) { "sk_Position = sk_in[0].sk_Position + float4(-0.5, 0, 0, sk_InvocationID);" "EmitVertex();" "}", - *SkSL::ShaderCapsFactory::MustImplementGSInvocationsWithLoop(), + *SkSL::ShaderCapsFactory::NoGSInvocationsSupport(), "#version 400\n" "int sk_InvocationID;\n" "layout (points) in ;\n" @@ -1454,6 +1454,27 @@ DEF_TEST(SkSLInvocations, r) { " }\n" "}\n", SkSL::Program::kGeometry_Kind); + test(r, + "layout(points, invocations = 2) in;" + "layout(invocations = 3) in;" + "layout(line_strip, max_vertices = 2) out;" + "void main() {" + "sk_Position = sk_in[0].sk_Position + float4(-0.5, 0, 0, sk_InvocationID);" + "EmitVertex();" + "EndPrimitive();" + "}", + *SkSL::ShaderCapsFactory::GSInvocationsExtensionString(), + "#version 400\n" + "#extension GL_ARB_gpu_shader5 : require\n" + "layout (points, invocations = 2) in ;\n" + "layout (invocations = 3) in ;\n" + "layout (line_strip, max_vertices = 2) out ;\n" + "void main() {\n" + " gl_Position = gl_in[0].gl_Position + vec4(-0.5, 0.0, 0.0, float(gl_InvocationID));\n" + " EmitVertex();\n" + " EndPrimitive();\n" + "}\n", + SkSL::Program::kGeometry_Kind); } DEF_TEST(SkSLTypePrecision, r) { |