Support GL_ARB_fragment_shader_interlock

This commit is contained in:
Jeff Bolz 2019-06-03 11:33:50 -05:00
parent a549bb8175
commit c6f0ce8dbc
19 changed files with 336 additions and 5 deletions

View file

@ -5030,6 +5030,10 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
"\n");
}
stageBuiltins[EShLangFragment].append(
"void beginInvocationInterlockARB(void);"
"void endInvocationInterlockARB(void);");
#ifdef AMD_EXTENSIONS
// GL_AMD_shader_explicit_vertex_parameter
if (profile != EEsProfile && version >= 450) {
@ -9539,6 +9543,10 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
if (profile != EEsProfile)
symbolTable.relateToOperator("interpolateAtVertexAMD", EOpInterpolateAtVertex);
#endif
symbolTable.relateToOperator("beginInvocationInterlockARB", EOpBeginInvocationInterlock);
symbolTable.relateToOperator("endInvocationInterlockARB", EOpEndInvocationInterlock);
break;
case EShLangCompute:

View file

@ -1410,6 +1410,44 @@ void TParseContext::checkLocation(const TSourceLoc& loc, TOperator op)
error(loc, "tessellation control barrier() cannot be placed after a return from main()", "", "");
}
break;
case EOpBeginInvocationInterlock:
if (language != EShLangFragment)
error(loc, "beginInvocationInterlockARB() must be in a fragment shader", "", "");
if (! inMain)
error(loc, "beginInvocationInterlockARB() must be in main()", "", "");
else if (postEntryPointReturn)
error(loc, "beginInvocationInterlockARB() cannot be placed after a return from main()", "", "");
if (controlFlowNestingLevel > 0)
error(loc, "beginInvocationInterlockARB() cannot be placed within flow control", "", "");
if (beginInvocationInterlockCount > 0)
error(loc, "beginInvocationInterlockARB() must only be called once", "", "");
if (endInvocationInterlockCount > 0)
error(loc, "beginInvocationInterlockARB() must be called before endInvocationInterlockARB()", "", "");
beginInvocationInterlockCount++;
// default to pixel_interlock_ordered
if (intermediate.getInterlockOrdering() == EioNone)
intermediate.setInterlockOrdering(EioPixelInterlockOrdered);
break;
case EOpEndInvocationInterlock:
if (language != EShLangFragment)
error(loc, "endInvocationInterlockARB() must be in a fragment shader", "", "");
if (! inMain)
error(loc, "endInvocationInterlockARB() must be in main()", "", "");
else if (postEntryPointReturn)
error(loc, "endInvocationInterlockARB() cannot be placed after a return from main()", "", "");
if (controlFlowNestingLevel > 0)
error(loc, "endInvocationInterlockARB() cannot be placed within flow control", "", "");
if (endInvocationInterlockCount > 0)
error(loc, "endInvocationInterlockARB() must only be called once", "", "");
if (beginInvocationInterlockCount == 0)
error(loc, "beginInvocationInterlockARB() must be called before endInvocationInterlockARB()", "", "");
endInvocationInterlockCount++;
break;
default:
break;
}
@ -4945,6 +4983,17 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi
return;
}
}
for (TInterlockOrdering order = (TInterlockOrdering)(EioNone + 1); order < EioCount; order = (TInterlockOrdering)(order+1)) {
if (id == TQualifier::getInterlockOrderingString(order)) {
requireProfile(loc, ECoreProfile | ECompatibilityProfile, "fragment shader interlock layout qualifier");
profileRequires(loc, ECoreProfile | ECompatibilityProfile, 450, nullptr, "fragment shader interlock layout qualifier");
requireExtensions(loc, 1, &E_GL_ARB_fragment_shader_interlock, TQualifier::getInterlockOrderingString(order));
if (order == EioShadingRateInterlockOrdered || order == EioShadingRateInterlockUnordered)
requireExtensions(loc, 1, &E_GL_NV_shading_rate_image, TQualifier::getInterlockOrderingString(order));
publicType.shaderQualifiers.interlockOrdering = order;
return;
}
}
if (id.compare(0, 13, "blend_support") == 0) {
bool found = false;
for (TBlendEquationShift be = (TBlendEquationShift)0; be < EBlendCount; be = (TBlendEquationShift)(be + 1)) {
@ -5945,6 +5994,8 @@ void TParseContext::checkNoShaderLayouts(const TSourceLoc& loc, const TShaderQua
error(loc, message, "blend equation", "");
if (shaderQualifiers.numViews != TQualifier::layoutNotSet)
error(loc, message, "num_views", "");
if (shaderQualifiers.interlockOrdering != EioNone)
error(loc, message, TQualifier::getInterlockOrderingString(shaderQualifiers.interlockOrdering), "");
}
// Correct and/or advance an object's offset layout qualifier.
@ -7874,6 +7925,14 @@ void TParseContext::updateStandaloneQualifierDefaults(const TSourceLoc& loc, con
if (publicType.qualifier.storage != EvqVaryingOut)
error(loc, "can only apply to 'out'", "blend equation", "");
}
if (publicType.shaderQualifiers.interlockOrdering) {
if (publicType.qualifier.storage == EvqVaryingIn) {
if (!intermediate.setInterlockOrdering(publicType.shaderQualifiers.interlockOrdering))
error(loc, "cannot change previously set fragment shader interlock ordering", TQualifier::getInterlockOrderingString(publicType.shaderQualifiers.interlockOrdering), "");
}
else
error(loc, "can only apply to 'in'", TQualifier::getInterlockOrderingString(publicType.shaderQualifiers.interlockOrdering), "");
}
#ifdef NV_EXTENSIONS
if (publicType.shaderQualifiers.layoutDerivativeGroupQuads &&

View file

@ -85,6 +85,7 @@ public:
statementNestingLevel(0), loopNestingLevel(0), structNestingLevel(0), controlFlowNestingLevel(0),
postEntryPointReturn(false),
contextPragma(true, false),
beginInvocationInterlockCount(0), endInvocationInterlockCount(0),
parsingBuiltins(parsingBuiltins), scanContext(nullptr), ppContext(nullptr),
limits(resources.limits),
globalUniformBlock(nullptr),
@ -182,6 +183,8 @@ public:
// the statementNestingLevel the current switch statement is at, which must match the level of its case statements
TList<int> switchLevel;
struct TPragma contextPragma;
int beginInvocationInterlockCount;
int endInvocationInterlockCount;
protected:
TParseContextBase(TParseContextBase&);

View file

@ -187,6 +187,7 @@ void TParseVersions::initializeExtensionBehavior()
// extensionBehavior[E_GL_ARB_cull_distance] = EBhDisable; // present for 4.5, but need extension control over block members
extensionBehavior[E_GL_ARB_post_depth_coverage] = EBhDisable;
extensionBehavior[E_GL_ARB_shader_viewport_layer_array] = EBhDisable;
extensionBehavior[E_GL_ARB_fragment_shader_interlock] = EBhDisable;
extensionBehavior[E_GL_KHR_shader_subgroup_basic] = EBhDisable;
extensionBehavior[E_GL_KHR_shader_subgroup_vote] = EBhDisable;
@ -379,6 +380,7 @@ void TParseVersions::getPreamble(std::string& preamble)
"#define GL_ARB_shader_stencil_export 1\n"
// "#define GL_ARB_cull_distance 1\n" // present for 4.5, but need extension control over block members
"#define GL_ARB_post_depth_coverage 1\n"
"#define GL_ARB_fragment_shader_interlock 1\n"
"#define GL_EXT_shader_non_constant_global_initializers 1\n"
"#define GL_EXT_shader_image_load_formatted 1\n"
"#define GL_EXT_post_depth_coverage 1\n"

View file

@ -141,6 +141,7 @@ const char* const E_GL_ARB_shader_stencil_export = "GL_ARB_shader_stencil
// const char* const E_GL_ARB_cull_distance = "GL_ARB_cull_distance"; // present for 4.5, but need extension control over block members
const char* const E_GL_ARB_post_depth_coverage = "GL_ARB_post_depth_coverage";
const char* const E_GL_ARB_shader_viewport_layer_array = "GL_ARB_shader_viewport_layer_array";
const char* const E_GL_ARB_fragment_shader_interlock = "GL_ARB_fragment_shader_interlock";
const char* const E_GL_KHR_shader_subgroup_basic = "GL_KHR_shader_subgroup_basic";
const char* const E_GL_KHR_shader_subgroup_vote = "GL_KHR_shader_subgroup_vote";

View file

@ -1502,6 +1502,8 @@ void TIntermediate::output(TInfoSink& infoSink, bool tree)
}
infoSink.debug << "\n";
}
if (interlockOrdering != EioNone)
infoSink.debug << "interlock ordering = " << TQualifier::getInterlockOrderingString(interlockOrdering) << "\n";
break;
#ifdef NV_EXTENSIONS

View file

@ -240,7 +240,7 @@ public:
invocations(TQualifier::layoutNotSet), vertices(TQualifier::layoutNotSet),
inputPrimitive(ElgNone), outputPrimitive(ElgNone),
pixelCenterInteger(false), originUpperLeft(false),
vertexSpacing(EvsNone), vertexOrder(EvoNone), pointMode(false), earlyFragmentTests(false),
vertexSpacing(EvsNone), vertexOrder(EvoNone), interlockOrdering(EioNone), pointMode(false), earlyFragmentTests(false),
postDepthCoverage(false), depthLayout(EldNone), depthReplacing(false),
hlslFunctionality1(false),
blendEquations(0), xfbMode(false), multiStream(false),
@ -608,6 +608,15 @@ public:
void setPointMode() { pointMode = true; }
bool getPointMode() const { return pointMode; }
bool setInterlockOrdering(TInterlockOrdering o)
{
if (interlockOrdering != EioNone)
return interlockOrdering == o;
interlockOrdering = o;
return true;
}
TInterlockOrdering getInterlockOrdering() const { return interlockOrdering; }
bool setLocalSize(int dim, int size)
{
if (localSize[dim] > 1)
@ -826,6 +835,7 @@ protected:
bool originUpperLeft;
TVertexSpacing vertexSpacing;
TVertexOrder vertexOrder;
TInterlockOrdering interlockOrdering;
bool pointMode;
int localSize[3];
int localSizeSpecId[3];