aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/gpu/GrShaderCaps.h15
-rw-r--r--src/gpu/GrShaderCaps.cpp6
-rw-r--r--src/gpu/gl/GrGLCaps.cpp22
-rw-r--r--src/gpu/vk/GrVkCaps.cpp2
-rw-r--r--src/sksl/SkSLGLSLCodeGenerator.cpp14
-rw-r--r--src/sksl/SkSLGLSLCodeGenerator.h1
-rw-r--r--src/sksl/SkSLIRGenerator.cpp10
-rw-r--r--src/sksl/SkSLUtil.h15
-rw-r--r--tests/SkSLGLSLTest.cpp23
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) {