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

@ -41,5 +41,6 @@ static const char* const E_SPV_KHR_storage_buffer_storage_class = "SPV_KHR_stora
static const char* const E_SPV_KHR_post_depth_coverage = "SPV_KHR_post_depth_coverage"; static const char* const E_SPV_KHR_post_depth_coverage = "SPV_KHR_post_depth_coverage";
static const char* const E_SPV_KHR_vulkan_memory_model = "SPV_KHR_vulkan_memory_model"; static const char* const E_SPV_KHR_vulkan_memory_model = "SPV_KHR_vulkan_memory_model";
static const char* const E_SPV_EXT_physical_storage_buffer = "SPV_EXT_physical_storage_buffer"; static const char* const E_SPV_EXT_physical_storage_buffer = "SPV_EXT_physical_storage_buffer";
static const char* const E_SPV_EXT_fragment_shader_interlock = "SPV_EXT_fragment_shader_interlock";
#endif // #ifndef GLSLextKHR_H #endif // #ifndef GLSLextKHR_H

View File

@ -1469,6 +1469,30 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, const gl
if (glslangIntermediate->getDepth() != glslang::EldUnchanged && glslangIntermediate->isDepthReplacing()) if (glslangIntermediate->getDepth() != glslang::EldUnchanged && glslangIntermediate->isDepthReplacing())
builder.addExecutionMode(shaderEntry, spv::ExecutionModeDepthReplacing); builder.addExecutionMode(shaderEntry, spv::ExecutionModeDepthReplacing);
switch (glslangIntermediate->getInterlockOrdering()) {
case glslang::EioPixelInterlockOrdered: mode = spv::ExecutionModePixelInterlockOrderedEXT; break;
case glslang::EioPixelInterlockUnordered: mode = spv::ExecutionModePixelInterlockUnorderedEXT; break;
case glslang::EioSampleInterlockOrdered: mode = spv::ExecutionModeSampleInterlockOrderedEXT; break;
case glslang::EioSampleInterlockUnordered: mode = spv::ExecutionModeSampleInterlockUnorderedEXT; break;
case glslang::EioShadingRateInterlockOrdered: mode = spv::ExecutionModeShadingRateInterlockOrderedEXT; break;
case glslang::EioShadingRateInterlockUnordered: mode = spv::ExecutionModeShadingRateInterlockUnorderedEXT; break;
default: mode = spv::ExecutionModeMax; break;
}
if (mode != spv::ExecutionModeMax) {
builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode);
if (mode == spv::ExecutionModeShadingRateInterlockOrderedEXT ||
mode == spv::ExecutionModeShadingRateInterlockUnorderedEXT) {
builder.addCapability(spv::CapabilityFragmentShaderShadingRateInterlockEXT);
} else if (mode == spv::ExecutionModePixelInterlockOrderedEXT ||
mode == spv::ExecutionModePixelInterlockUnorderedEXT) {
builder.addCapability(spv::CapabilityFragmentShaderPixelInterlockEXT);
} else {
builder.addCapability(spv::CapabilityFragmentShaderSampleInterlockEXT);
}
builder.addExtension(spv::E_SPV_EXT_fragment_shader_interlock);
}
break; break;
case EShLangCompute: case EShLangCompute:
@ -2396,6 +2420,11 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
case glslang::EOpCooperativeMatrixStore: case glslang::EOpCooperativeMatrixStore:
noReturnValue = true; noReturnValue = true;
break; break;
case glslang::EOpBeginInvocationInterlock:
case glslang::EOpEndInvocationInterlock:
builder.addExtension(spv::E_SPV_EXT_fragment_shader_interlock);
noReturnValue = true;
break;
default: default:
break; break;
@ -7429,6 +7458,14 @@ spv::Id TGlslangToSpvTraverser::createNoArgOperation(glslang::TOperator op, spv:
builder.createNoResultOp(spv::OpTerminateRayNV); builder.createNoResultOp(spv::OpTerminateRayNV);
return 0; return 0;
#endif #endif
case glslang::EOpBeginInvocationInterlock:
builder.createNoResultOp(spv::OpBeginInvocationInterlockEXT);
return 0;
case glslang::EOpEndInvocationInterlock:
builder.createNoResultOp(spv::OpEndInvocationInterlockEXT);
return 0;
default: default:
logger->missingFunctionality("unknown operation with no arguments"); logger->missingFunctionality("unknown operation with no arguments");
return 0; return 0;

View File

@ -191,6 +191,13 @@ const char* ExecutionModeString(int mode)
case ExecutionModeDerivativeGroupLinearNV: return "DerivativeGroupLinearNV"; case ExecutionModeDerivativeGroupLinearNV: return "DerivativeGroupLinearNV";
#endif #endif
case ExecutionModePixelInterlockOrderedEXT: return "PixelInterlockOrderedEXT";
case ExecutionModePixelInterlockUnorderedEXT: return "PixelInterlockUnorderedEXT";
case ExecutionModeSampleInterlockOrderedEXT: return "SampleInterlockOrderedEXT";
case ExecutionModeSampleInterlockUnorderedEXT: return "SampleInterlockUnorderedEXT";
case ExecutionModeShadingRateInterlockOrderedEXT: return "ShadingRateInterlockOrderedEXT";
case ExecutionModeShadingRateInterlockUnorderedEXT: return "ShadingRateInterlockUnorderedEXT";
case ExecutionModeCeiling: case ExecutionModeCeiling:
default: return "Bad"; default: return "Bad";
} }
@ -942,6 +949,10 @@ const char* CapabilityString(int info)
case CapabilityCooperativeMatrixNV: return "CooperativeMatrixNV"; case CapabilityCooperativeMatrixNV: return "CooperativeMatrixNV";
case CapabilityFragmentShaderSampleInterlockEXT: return "CapabilityFragmentShaderSampleInterlockEXT";
case CapabilityFragmentShaderPixelInterlockEXT: return "CapabilityFragmentShaderPixelInterlockEXT";
case CapabilityFragmentShaderShadingRateInterlockEXT: return "CapabilityFragmentShaderShadingRateInterlockEXT";
default: return "Bad"; default: return "Bad";
} }
} }
@ -1352,6 +1363,9 @@ const char* OpcodeString(int op)
case OpCooperativeMatrixMulAddNV: return "OpCooperativeMatrixMulAddNV"; case OpCooperativeMatrixMulAddNV: return "OpCooperativeMatrixMulAddNV";
case OpCooperativeMatrixLengthNV: return "OpCooperativeMatrixLengthNV"; case OpCooperativeMatrixLengthNV: return "OpCooperativeMatrixLengthNV";
case OpBeginInvocationInterlockEXT: return "OpBeginInvocationInterlockEXT";
case OpEndInvocationInterlockEXT: return "OpEndInvocationInterlockEXT";
default: default:
return "Bad"; return "Bad";
} }
@ -1465,6 +1479,8 @@ void Parameterize()
InstructionDesc[OpModuleProcessed].setResultAndType(false, false); InstructionDesc[OpModuleProcessed].setResultAndType(false, false);
InstructionDesc[OpTypeCooperativeMatrixNV].setResultAndType(true, false); InstructionDesc[OpTypeCooperativeMatrixNV].setResultAndType(true, false);
InstructionDesc[OpCooperativeMatrixStoreNV].setResultAndType(false, false); InstructionDesc[OpCooperativeMatrixStoreNV].setResultAndType(false, false);
InstructionDesc[OpBeginInvocationInterlockEXT].setResultAndType(false, false);
InstructionDesc[OpEndInvocationInterlockEXT].setResultAndType(false, false);
// Specific additional context-dependent operands // Specific additional context-dependent operands

View File

@ -154,6 +154,12 @@ enum ExecutionMode {
ExecutionModeDerivativeGroupQuadsNV = 5289, ExecutionModeDerivativeGroupQuadsNV = 5289,
ExecutionModeDerivativeGroupLinearNV = 5290, ExecutionModeDerivativeGroupLinearNV = 5290,
ExecutionModeOutputTrianglesNV = 5298, ExecutionModeOutputTrianglesNV = 5298,
ExecutionModePixelInterlockOrderedEXT = 5366,
ExecutionModePixelInterlockUnorderedEXT = 5367,
ExecutionModeSampleInterlockOrderedEXT = 5368,
ExecutionModeSampleInterlockUnorderedEXT = 5369,
ExecutionModeShadingRateInterlockOrderedEXT = 5370,
ExecutionModeShadingRateInterlockUnorderedEXT = 5371,
ExecutionModeMax = 0x7fffffff, ExecutionModeMax = 0x7fffffff,
}; };
@ -551,6 +557,10 @@ enum BuiltIn {
BuiltInHitTNV = 5332, BuiltInHitTNV = 5332,
BuiltInHitKindNV = 5333, BuiltInHitKindNV = 5333,
BuiltInIncomingRayFlagsNV = 5351, BuiltInIncomingRayFlagsNV = 5351,
BuiltInWarpsPerSMNV = 5374,
BuiltInSMCountNV = 5375,
BuiltInWarpIDNV = 5376,
BuiltInSMIDNV = 5377,
BuiltInMax = 0x7fffffff, BuiltInMax = 0x7fffffff,
}; };
@ -829,10 +839,15 @@ enum Capability {
CapabilityPhysicalStorageBufferAddressesEXT = 5347, CapabilityPhysicalStorageBufferAddressesEXT = 5347,
CapabilityComputeDerivativeGroupLinearNV = 5350, CapabilityComputeDerivativeGroupLinearNV = 5350,
CapabilityCooperativeMatrixNV = 5357, CapabilityCooperativeMatrixNV = 5357,
CapabilityFragmentShaderSampleInterlockEXT = 5363,
CapabilityFragmentShaderShadingRateInterlockEXT = 5372,
CapabilityShaderSMBuiltinsNV = 5373,
CapabilityFragmentShaderPixelInterlockEXT = 5378,
CapabilitySubgroupShuffleINTEL = 5568, CapabilitySubgroupShuffleINTEL = 5568,
CapabilitySubgroupBufferBlockIOINTEL = 5569, CapabilitySubgroupBufferBlockIOINTEL = 5569,
CapabilitySubgroupImageBlockIOINTEL = 5570, CapabilitySubgroupImageBlockIOINTEL = 5570,
CapabilitySubgroupImageMediaBlockIOINTEL = 5579, CapabilitySubgroupImageMediaBlockIOINTEL = 5579,
CapabilityIntegerFunctions2INTEL = 5584,
CapabilitySubgroupAvcMotionEstimationINTEL = 5696, CapabilitySubgroupAvcMotionEstimationINTEL = 5696,
CapabilitySubgroupAvcMotionEstimationIntraINTEL = 5697, CapabilitySubgroupAvcMotionEstimationIntraINTEL = 5697,
CapabilitySubgroupAvcMotionEstimationChromaINTEL = 5698, CapabilitySubgroupAvcMotionEstimationChromaINTEL = 5698,
@ -1214,6 +1229,8 @@ enum Op {
OpCooperativeMatrixStoreNV = 5360, OpCooperativeMatrixStoreNV = 5360,
OpCooperativeMatrixMulAddNV = 5361, OpCooperativeMatrixMulAddNV = 5361,
OpCooperativeMatrixLengthNV = 5362, OpCooperativeMatrixLengthNV = 5362,
OpBeginInvocationInterlockEXT = 5364,
OpEndInvocationInterlockEXT = 5365,
OpSubgroupShuffleINTEL = 5571, OpSubgroupShuffleINTEL = 5571,
OpSubgroupShuffleDownINTEL = 5572, OpSubgroupShuffleDownINTEL = 5572,
OpSubgroupShuffleUpINTEL = 5573, OpSubgroupShuffleUpINTEL = 5573,
@ -1224,6 +1241,20 @@ enum Op {
OpSubgroupImageBlockWriteINTEL = 5578, OpSubgroupImageBlockWriteINTEL = 5578,
OpSubgroupImageMediaBlockReadINTEL = 5580, OpSubgroupImageMediaBlockReadINTEL = 5580,
OpSubgroupImageMediaBlockWriteINTEL = 5581, OpSubgroupImageMediaBlockWriteINTEL = 5581,
OpUCountLeadingZerosINTEL = 5585,
OpUCountTrailingZerosINTEL = 5586,
OpAbsISubINTEL = 5587,
OpAbsUSubINTEL = 5588,
OpIAddSatINTEL = 5589,
OpUAddSatINTEL = 5590,
OpIAverageINTEL = 5591,
OpUAverageINTEL = 5592,
OpIAverageRoundedINTEL = 5593,
OpUAverageRoundedINTEL = 5594,
OpISubSatINTEL = 5595,
OpUSubSatINTEL = 5596,
OpIMul32x16INTEL = 5597,
OpUMul32x16INTEL = 5598,
OpDecorateString = 5632, OpDecorateString = 5632,
OpDecorateStringGOOGLE = 5632, OpDecorateStringGOOGLE = 5632,
OpMemberDecorateString = 5633, OpMemberDecorateString = 5633,
@ -1738,10 +1769,22 @@ inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) {
case OpSubgroupImageBlockWriteINTEL: *hasResult = false; *hasResultType = false; break; case OpSubgroupImageBlockWriteINTEL: *hasResult = false; *hasResultType = false; break;
case OpSubgroupImageMediaBlockReadINTEL: *hasResult = true; *hasResultType = true; break; case OpSubgroupImageMediaBlockReadINTEL: *hasResult = true; *hasResultType = true; break;
case OpSubgroupImageMediaBlockWriteINTEL: *hasResult = false; *hasResultType = false; break; case OpSubgroupImageMediaBlockWriteINTEL: *hasResult = false; *hasResultType = false; break;
case OpUCountLeadingZerosINTEL: *hasResult = true; *hasResultType = true; break;
case OpUCountTrailingZerosINTEL: *hasResult = true; *hasResultType = true; break;
case OpAbsISubINTEL: *hasResult = true; *hasResultType = true; break;
case OpAbsUSubINTEL: *hasResult = true; *hasResultType = true; break;
case OpIAddSatINTEL: *hasResult = true; *hasResultType = true; break;
case OpUAddSatINTEL: *hasResult = true; *hasResultType = true; break;
case OpIAverageINTEL: *hasResult = true; *hasResultType = true; break;
case OpUAverageINTEL: *hasResult = true; *hasResultType = true; break;
case OpIAverageRoundedINTEL: *hasResult = true; *hasResultType = true; break;
case OpUAverageRoundedINTEL: *hasResult = true; *hasResultType = true; break;
case OpISubSatINTEL: *hasResult = true; *hasResultType = true; break;
case OpUSubSatINTEL: *hasResult = true; *hasResultType = true; break;
case OpIMul32x16INTEL: *hasResult = true; *hasResultType = true; break;
case OpUMul32x16INTEL: *hasResult = true; *hasResultType = true; break;
case OpDecorateString: *hasResult = false; *hasResultType = false; break; case OpDecorateString: *hasResult = false; *hasResultType = false; break;
case OpDecorateStringGOOGLE: *hasResult = false; *hasResultType = false; break;
case OpMemberDecorateString: *hasResult = false; *hasResultType = false; break; case OpMemberDecorateString: *hasResult = false; *hasResultType = false; break;
case OpMemberDecorateStringGOOGLE: *hasResult = false; *hasResultType = false; break;
case OpVmeImageINTEL: *hasResult = true; *hasResultType = true; break; case OpVmeImageINTEL: *hasResult = true; *hasResultType = true; break;
case OpTypeVmeImageINTEL: *hasResult = true; *hasResultType = false; break; case OpTypeVmeImageINTEL: *hasResult = true; *hasResultType = false; break;
case OpTypeAvcImePayloadINTEL: *hasResult = true; *hasResultType = false; break; case OpTypeAvcImePayloadINTEL: *hasResult = true; *hasResultType = false; break;
@ -1860,6 +1903,8 @@ inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) {
case OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL: *hasResult = true; *hasResultType = true; break; case OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL: *hasResult = true; *hasResultType = true; break;
case OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL: *hasResult = true; *hasResultType = true; break; case OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL: *hasResult = true; *hasResultType = true; break;
case OpSubgroupAvcSicGetInterRawSadsINTEL: *hasResult = true; *hasResultType = true; break; case OpSubgroupAvcSicGetInterRawSadsINTEL: *hasResult = true; *hasResultType = true; break;
case OpBeginInvocationInterlockEXT: *hasResult = false; *hasResultType = false; break;
case OpEndInvocationInterlockEXT: *hasResult = false; *hasResultType = false; break;
} }
} }
#endif /* SPV_ENABLE_UTILITY_CODE */ #endif /* SPV_ENABLE_UTILITY_CODE */

View File

@ -0,0 +1,56 @@
spv.fsi.frag
// Module Version 10000
// Generated by (magic number): 80007
// Id's are bound by 24
Capability Shader
Capability CapabilityFragmentShaderSampleInterlockEXT
Extension "SPV_EXT_fragment_shader_interlock"
1: ExtInstImport "GLSL.std.450"
MemoryModel Logical GLSL450
EntryPoint Fragment 4 "main"
ExecutionMode 4 OriginUpperLeft
ExecutionMode 4 SampleInterlockOrderedEXT
Source GLSL 450
SourceExtension "GL_ARB_fragment_shader_interlock"
Name 4 "main"
Name 7 "B1"
MemberName 7(B1) 0 "x"
Name 9 "b1"
Name 17 "im"
MemberDecorate 7(B1) 0 Coherent
MemberDecorate 7(B1) 0 Offset 0
Decorate 7(B1) BufferBlock
Decorate 9(b1) DescriptorSet 0
Decorate 9(b1) Binding 0
Decorate 17(im) DescriptorSet 0
Decorate 17(im) Binding 1
Decorate 17(im) Coherent
2: TypeVoid
3: TypeFunction 2
6: TypeInt 32 1
7(B1): TypeStruct 6(int)
8: TypePointer Uniform 7(B1)
9(b1): 8(ptr) Variable Uniform
10: 6(int) Constant 0
11: 6(int) Constant 1
12: TypePointer Uniform 6(int)
14: TypeFloat 32
15: TypeImage 14(float) 2D nonsampled format:Rgba32f
16: TypePointer UniformConstant 15
17(im): 16(ptr) Variable UniformConstant
19: TypeVector 6(int) 2
20: 19(ivec2) ConstantComposite 10 10
21: TypeVector 14(float) 4
22: 14(float) Constant 0
23: 21(fvec4) ConstantComposite 22 22 22 22
4(main): 2 Function None 3
5: Label
BeginInvocationInterlockEXT
13: 12(ptr) AccessChain 9(b1) 10
Store 13 11
18: 15 Load 17(im)
ImageWrite 18 20 23
EndInvocationInterlockEXT
Return
FunctionEnd

View File

@ -0,0 +1,14 @@
spv.fsi_Error.frag
ERROR: 0:4: 'pixel_interlock_ordered' : can only apply to 'in'
ERROR: 0:7: 'pixel_interlock_unordered' : cannot change previously set fragment shader interlock ordering
ERROR: 0:11: '' : beginInvocationInterlockARB() must be in main()
ERROR: 0:12: '' : endInvocationInterlockARB() must be in main()
ERROR: 0:17: '' : endInvocationInterlockARB() must only be called once
ERROR: 0:18: '' : beginInvocationInterlockARB() must only be called once
ERROR: 0:18: '' : beginInvocationInterlockARB() must be called before endInvocationInterlockARB()
ERROR: 0:22: '' : endInvocationInterlockARB() cannot be placed after a return from main()
ERROR: 0:22: '' : endInvocationInterlockARB() must only be called once
ERROR: 9 compilation errors. No code generated.
SPIR-V is not generated for failed compile or link

20
Test/spv.fsi.frag Normal file
View File

@ -0,0 +1,20 @@
#version 450
#extension GL_ARB_fragment_shader_interlock : enable
layout(set = 0, binding = 0) coherent buffer B1 {
layout(offset = 0) int x;
} b1;
layout(set = 0, binding = 1, rgba32f) coherent uniform image2D im;
layout(sample_interlock_ordered) in;
void main() {
beginInvocationInterlockARB();
b1.x = 1;
imageStore(im, ivec2(0,0), vec4(0));
endInvocationInterlockARB();
}

23
Test/spv.fsi_Error.frag Normal file
View File

@ -0,0 +1,23 @@
#version 450
#extension GL_ARB_fragment_shader_interlock : enable
layout(pixel_interlock_ordered) out;
layout(pixel_interlock_ordered) in;
layout(pixel_interlock_unordered) in;
void foo()
{
beginInvocationInterlockARB();
endInvocationInterlockARB();
}
void main() {
endInvocationInterlockARB();
beginInvocationInterlockARB();
return;
endInvocationInterlockARB();
}

View File

@ -422,6 +422,18 @@ enum TBlendEquationShift {
EBlendCount EBlendCount
}; };
enum TInterlockOrdering {
EioNone,
EioPixelInterlockOrdered,
EioPixelInterlockUnordered,
EioSampleInterlockOrdered,
EioSampleInterlockUnordered,
EioShadingRateInterlockOrdered,
EioShadingRateInterlockUnordered,
EioCount,
};
class TQualifier { class TQualifier {
public: public:
static const int layoutNotSet = -1; static const int layoutNotSet = -1;
@ -1110,6 +1122,18 @@ public:
default: return 0; default: return 0;
} }
} }
static const char* getInterlockOrderingString(TInterlockOrdering order)
{
switch (order) {
case EioPixelInterlockOrdered: return "pixel_interlock_ordered";
case EioPixelInterlockUnordered: return "pixel_interlock_unordered";
case EioSampleInterlockOrdered: return "sample_interlock_ordered";
case EioSampleInterlockUnordered: return "sample_interlock_unordered";
case EioShadingRateInterlockOrdered: return "shading_rate_interlock_ordered";
case EioShadingRateInterlockUnordered: return "shading_rate_interlock_unordered";
default: return "none";
}
}
}; };
// Qualifiers that don't need to be keep per object. They have shader scope, not object scope. // Qualifiers that don't need to be keep per object. They have shader scope, not object scope.
@ -1130,6 +1154,7 @@ struct TShaderQualifiers {
TLayoutDepth layoutDepth; TLayoutDepth layoutDepth;
bool blendEquation; // true if any blend equation was specified bool blendEquation; // true if any blend equation was specified
int numViews; // multiview extenstions int numViews; // multiview extenstions
TInterlockOrdering interlockOrdering;
#ifdef NV_EXTENSIONS #ifdef NV_EXTENSIONS
bool layoutOverrideCoverage; // true if layout override_coverage set bool layoutOverrideCoverage; // true if layout override_coverage set
@ -1165,6 +1190,7 @@ struct TShaderQualifiers {
layoutDerivativeGroupLinear = false; layoutDerivativeGroupLinear = false;
primitives = TQualifier::layoutNotSet; primitives = TQualifier::layoutNotSet;
#endif #endif
interlockOrdering = EioNone;
} }
// Merge in characteristics from the 'src' qualifier. They can override when // Merge in characteristics from the 'src' qualifier. They can override when
@ -1215,6 +1241,9 @@ struct TShaderQualifiers {
if (src.primitives != TQualifier::layoutNotSet) if (src.primitives != TQualifier::layoutNotSet)
primitives = src.primitives; primitives = src.primitives;
#endif #endif
if (src.interlockOrdering != EioNone)
interlockOrdering = src.interlockOrdering;
} }
}; };

View File

@ -621,6 +621,9 @@ enum TOperator {
EOpCooperativeMatrixStore, EOpCooperativeMatrixStore,
EOpCooperativeMatrixMulAdd, EOpCooperativeMatrixMulAdd,
EOpBeginInvocationInterlock, // Fragment only
EOpEndInvocationInterlock, // Fragment only
// //
// Branch // Branch
// //

View File

@ -5030,6 +5030,10 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
"\n"); "\n");
} }
stageBuiltins[EShLangFragment].append(
"void beginInvocationInterlockARB(void);"
"void endInvocationInterlockARB(void);");
#ifdef AMD_EXTENSIONS #ifdef AMD_EXTENSIONS
// GL_AMD_shader_explicit_vertex_parameter // GL_AMD_shader_explicit_vertex_parameter
if (profile != EEsProfile && version >= 450) { if (profile != EEsProfile && version >= 450) {
@ -9539,6 +9543,10 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
if (profile != EEsProfile) if (profile != EEsProfile)
symbolTable.relateToOperator("interpolateAtVertexAMD", EOpInterpolateAtVertex); symbolTable.relateToOperator("interpolateAtVertexAMD", EOpInterpolateAtVertex);
#endif #endif
symbolTable.relateToOperator("beginInvocationInterlockARB", EOpBeginInvocationInterlock);
symbolTable.relateToOperator("endInvocationInterlockARB", EOpEndInvocationInterlock);
break; break;
case EShLangCompute: 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()", "", ""); error(loc, "tessellation control barrier() cannot be placed after a return from main()", "", "");
} }
break; 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: default:
break; break;
} }
@ -4945,6 +4983,17 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi
return; 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) { if (id.compare(0, 13, "blend_support") == 0) {
bool found = false; bool found = false;
for (TBlendEquationShift be = (TBlendEquationShift)0; be < EBlendCount; be = (TBlendEquationShift)(be + 1)) { 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", ""); error(loc, message, "blend equation", "");
if (shaderQualifiers.numViews != TQualifier::layoutNotSet) if (shaderQualifiers.numViews != TQualifier::layoutNotSet)
error(loc, message, "num_views", ""); 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. // 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) if (publicType.qualifier.storage != EvqVaryingOut)
error(loc, "can only apply to 'out'", "blend equation", ""); 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 #ifdef NV_EXTENSIONS
if (publicType.shaderQualifiers.layoutDerivativeGroupQuads && if (publicType.shaderQualifiers.layoutDerivativeGroupQuads &&

View File

@ -85,6 +85,7 @@ public:
statementNestingLevel(0), loopNestingLevel(0), structNestingLevel(0), controlFlowNestingLevel(0), statementNestingLevel(0), loopNestingLevel(0), structNestingLevel(0), controlFlowNestingLevel(0),
postEntryPointReturn(false), postEntryPointReturn(false),
contextPragma(true, false), contextPragma(true, false),
beginInvocationInterlockCount(0), endInvocationInterlockCount(0),
parsingBuiltins(parsingBuiltins), scanContext(nullptr), ppContext(nullptr), parsingBuiltins(parsingBuiltins), scanContext(nullptr), ppContext(nullptr),
limits(resources.limits), limits(resources.limits),
globalUniformBlock(nullptr), globalUniformBlock(nullptr),
@ -182,6 +183,8 @@ public:
// the statementNestingLevel the current switch statement is at, which must match the level of its case statements // the statementNestingLevel the current switch statement is at, which must match the level of its case statements
TList<int> switchLevel; TList<int> switchLevel;
struct TPragma contextPragma; struct TPragma contextPragma;
int beginInvocationInterlockCount;
int endInvocationInterlockCount;
protected: protected:
TParseContextBase(TParseContextBase&); 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_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_post_depth_coverage] = EBhDisable;
extensionBehavior[E_GL_ARB_shader_viewport_layer_array] = 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_basic] = EBhDisable;
extensionBehavior[E_GL_KHR_shader_subgroup_vote] = 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_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_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_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_non_constant_global_initializers 1\n"
"#define GL_EXT_shader_image_load_formatted 1\n" "#define GL_EXT_shader_image_load_formatted 1\n"
"#define GL_EXT_post_depth_coverage 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_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_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_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_basic = "GL_KHR_shader_subgroup_basic";
const char* const E_GL_KHR_shader_subgroup_vote = "GL_KHR_shader_subgroup_vote"; 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"; infoSink.debug << "\n";
} }
if (interlockOrdering != EioNone)
infoSink.debug << "interlock ordering = " << TQualifier::getInterlockOrderingString(interlockOrdering) << "\n";
break; break;
#ifdef NV_EXTENSIONS #ifdef NV_EXTENSIONS

View File

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

View File

@ -319,6 +319,8 @@ INSTANTIATE_TEST_CASE_P(
"spv.fragmentDensity.vert", "spv.fragmentDensity.vert",
"spv.fragmentDensity-es.frag", "spv.fragmentDensity-es.frag",
"spv.fragmentDensity-neg.frag", "spv.fragmentDensity-neg.frag",
"spv.fsi.frag",
"spv.fsi_Error.frag",
"spv.fullyCovered.frag", "spv.fullyCovered.frag",
"spv.functionCall.frag", "spv.functionCall.frag",
"spv.functionNestedOpaque.vert", "spv.functionNestedOpaque.vert",

View File

@ -5,14 +5,14 @@
"site" : "github", "site" : "github",
"subrepo" : "KhronosGroup/SPIRV-Tools", "subrepo" : "KhronosGroup/SPIRV-Tools",
"subdir" : "External/spirv-tools", "subdir" : "External/spirv-tools",
"commit" : "9dfd4b8358077bdbe8e2f9388572b5376c370f5d" "commit" : "2c0111e6eba779cf30e8c7f5a733ea0762895ba0"
}, },
{ {
"name" : "spirv-tools/external/spirv-headers", "name" : "spirv-tools/external/spirv-headers",
"site" : "github", "site" : "github",
"subrepo" : "KhronosGroup/SPIRV-Headers", "subrepo" : "KhronosGroup/SPIRV-Headers",
"subdir" : "External/spirv-tools/external/spirv-headers", "subdir" : "External/spirv-tools/external/spirv-headers",
"commit" : "4b0985f29277a81f5ce88feb0502cc44d6d5e7c3" "commit" : "8b911bd2ba37677037b38c9bd286c7c05701bcda"
} }
] ]
} }