mirror of
https://github.com/KhronosGroup/glslang
synced 2024-09-18 19:59:54 +00:00
Support GL_ARB_fragment_shader_interlock
This commit is contained in:
parent
a549bb8175
commit
c6f0ce8dbc
@ -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_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_fragment_shader_interlock = "SPV_EXT_fragment_shader_interlock";
|
||||
|
||||
#endif // #ifndef GLSLextKHR_H
|
||||
|
@ -1469,6 +1469,30 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, const gl
|
||||
|
||||
if (glslangIntermediate->getDepth() != glslang::EldUnchanged && glslangIntermediate->isDepthReplacing())
|
||||
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;
|
||||
|
||||
case EShLangCompute:
|
||||
@ -2396,6 +2420,11 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
|
||||
case glslang::EOpCooperativeMatrixStore:
|
||||
noReturnValue = true;
|
||||
break;
|
||||
case glslang::EOpBeginInvocationInterlock:
|
||||
case glslang::EOpEndInvocationInterlock:
|
||||
builder.addExtension(spv::E_SPV_EXT_fragment_shader_interlock);
|
||||
noReturnValue = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
@ -7429,6 +7458,14 @@ spv::Id TGlslangToSpvTraverser::createNoArgOperation(glslang::TOperator op, spv:
|
||||
builder.createNoResultOp(spv::OpTerminateRayNV);
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
case glslang::EOpBeginInvocationInterlock:
|
||||
builder.createNoResultOp(spv::OpBeginInvocationInterlockEXT);
|
||||
return 0;
|
||||
case glslang::EOpEndInvocationInterlock:
|
||||
builder.createNoResultOp(spv::OpEndInvocationInterlockEXT);
|
||||
return 0;
|
||||
|
||||
default:
|
||||
logger->missingFunctionality("unknown operation with no arguments");
|
||||
return 0;
|
||||
|
@ -191,6 +191,13 @@ const char* ExecutionModeString(int mode)
|
||||
case ExecutionModeDerivativeGroupLinearNV: return "DerivativeGroupLinearNV";
|
||||
#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:
|
||||
default: return "Bad";
|
||||
}
|
||||
@ -942,6 +949,10 @@ const char* CapabilityString(int info)
|
||||
|
||||
case CapabilityCooperativeMatrixNV: return "CooperativeMatrixNV";
|
||||
|
||||
case CapabilityFragmentShaderSampleInterlockEXT: return "CapabilityFragmentShaderSampleInterlockEXT";
|
||||
case CapabilityFragmentShaderPixelInterlockEXT: return "CapabilityFragmentShaderPixelInterlockEXT";
|
||||
case CapabilityFragmentShaderShadingRateInterlockEXT: return "CapabilityFragmentShaderShadingRateInterlockEXT";
|
||||
|
||||
default: return "Bad";
|
||||
}
|
||||
}
|
||||
@ -1352,6 +1363,9 @@ const char* OpcodeString(int op)
|
||||
case OpCooperativeMatrixMulAddNV: return "OpCooperativeMatrixMulAddNV";
|
||||
case OpCooperativeMatrixLengthNV: return "OpCooperativeMatrixLengthNV";
|
||||
|
||||
case OpBeginInvocationInterlockEXT: return "OpBeginInvocationInterlockEXT";
|
||||
case OpEndInvocationInterlockEXT: return "OpEndInvocationInterlockEXT";
|
||||
|
||||
default:
|
||||
return "Bad";
|
||||
}
|
||||
@ -1465,6 +1479,8 @@ void Parameterize()
|
||||
InstructionDesc[OpModuleProcessed].setResultAndType(false, false);
|
||||
InstructionDesc[OpTypeCooperativeMatrixNV].setResultAndType(true, false);
|
||||
InstructionDesc[OpCooperativeMatrixStoreNV].setResultAndType(false, false);
|
||||
InstructionDesc[OpBeginInvocationInterlockEXT].setResultAndType(false, false);
|
||||
InstructionDesc[OpEndInvocationInterlockEXT].setResultAndType(false, false);
|
||||
|
||||
// Specific additional context-dependent operands
|
||||
|
||||
|
@ -154,6 +154,12 @@ enum ExecutionMode {
|
||||
ExecutionModeDerivativeGroupQuadsNV = 5289,
|
||||
ExecutionModeDerivativeGroupLinearNV = 5290,
|
||||
ExecutionModeOutputTrianglesNV = 5298,
|
||||
ExecutionModePixelInterlockOrderedEXT = 5366,
|
||||
ExecutionModePixelInterlockUnorderedEXT = 5367,
|
||||
ExecutionModeSampleInterlockOrderedEXT = 5368,
|
||||
ExecutionModeSampleInterlockUnorderedEXT = 5369,
|
||||
ExecutionModeShadingRateInterlockOrderedEXT = 5370,
|
||||
ExecutionModeShadingRateInterlockUnorderedEXT = 5371,
|
||||
ExecutionModeMax = 0x7fffffff,
|
||||
};
|
||||
|
||||
@ -551,6 +557,10 @@ enum BuiltIn {
|
||||
BuiltInHitTNV = 5332,
|
||||
BuiltInHitKindNV = 5333,
|
||||
BuiltInIncomingRayFlagsNV = 5351,
|
||||
BuiltInWarpsPerSMNV = 5374,
|
||||
BuiltInSMCountNV = 5375,
|
||||
BuiltInWarpIDNV = 5376,
|
||||
BuiltInSMIDNV = 5377,
|
||||
BuiltInMax = 0x7fffffff,
|
||||
};
|
||||
|
||||
@ -829,10 +839,15 @@ enum Capability {
|
||||
CapabilityPhysicalStorageBufferAddressesEXT = 5347,
|
||||
CapabilityComputeDerivativeGroupLinearNV = 5350,
|
||||
CapabilityCooperativeMatrixNV = 5357,
|
||||
CapabilityFragmentShaderSampleInterlockEXT = 5363,
|
||||
CapabilityFragmentShaderShadingRateInterlockEXT = 5372,
|
||||
CapabilityShaderSMBuiltinsNV = 5373,
|
||||
CapabilityFragmentShaderPixelInterlockEXT = 5378,
|
||||
CapabilitySubgroupShuffleINTEL = 5568,
|
||||
CapabilitySubgroupBufferBlockIOINTEL = 5569,
|
||||
CapabilitySubgroupImageBlockIOINTEL = 5570,
|
||||
CapabilitySubgroupImageMediaBlockIOINTEL = 5579,
|
||||
CapabilityIntegerFunctions2INTEL = 5584,
|
||||
CapabilitySubgroupAvcMotionEstimationINTEL = 5696,
|
||||
CapabilitySubgroupAvcMotionEstimationIntraINTEL = 5697,
|
||||
CapabilitySubgroupAvcMotionEstimationChromaINTEL = 5698,
|
||||
@ -1214,6 +1229,8 @@ enum Op {
|
||||
OpCooperativeMatrixStoreNV = 5360,
|
||||
OpCooperativeMatrixMulAddNV = 5361,
|
||||
OpCooperativeMatrixLengthNV = 5362,
|
||||
OpBeginInvocationInterlockEXT = 5364,
|
||||
OpEndInvocationInterlockEXT = 5365,
|
||||
OpSubgroupShuffleINTEL = 5571,
|
||||
OpSubgroupShuffleDownINTEL = 5572,
|
||||
OpSubgroupShuffleUpINTEL = 5573,
|
||||
@ -1224,6 +1241,20 @@ enum Op {
|
||||
OpSubgroupImageBlockWriteINTEL = 5578,
|
||||
OpSubgroupImageMediaBlockReadINTEL = 5580,
|
||||
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,
|
||||
OpDecorateStringGOOGLE = 5632,
|
||||
OpMemberDecorateString = 5633,
|
||||
@ -1738,10 +1769,22 @@ inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) {
|
||||
case OpSubgroupImageBlockWriteINTEL: *hasResult = false; *hasResultType = false; break;
|
||||
case OpSubgroupImageMediaBlockReadINTEL: *hasResult = true; *hasResultType = true; 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 OpDecorateStringGOOGLE: *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 OpTypeVmeImageINTEL: *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 OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL: *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 */
|
||||
|
56
Test/baseResults/spv.fsi.frag.out
Normal file
56
Test/baseResults/spv.fsi.frag.out
Normal 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
|
14
Test/baseResults/spv.fsi_Error.frag.out
Normal file
14
Test/baseResults/spv.fsi_Error.frag.out
Normal 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
20
Test/spv.fsi.frag
Normal 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
23
Test/spv.fsi_Error.frag
Normal 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();
|
||||
}
|
@ -422,6 +422,18 @@ enum TBlendEquationShift {
|
||||
EBlendCount
|
||||
};
|
||||
|
||||
enum TInterlockOrdering {
|
||||
EioNone,
|
||||
EioPixelInterlockOrdered,
|
||||
EioPixelInterlockUnordered,
|
||||
EioSampleInterlockOrdered,
|
||||
EioSampleInterlockUnordered,
|
||||
EioShadingRateInterlockOrdered,
|
||||
EioShadingRateInterlockUnordered,
|
||||
|
||||
EioCount,
|
||||
};
|
||||
|
||||
class TQualifier {
|
||||
public:
|
||||
static const int layoutNotSet = -1;
|
||||
@ -1110,6 +1122,18 @@ public:
|
||||
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.
|
||||
@ -1130,6 +1154,7 @@ struct TShaderQualifiers {
|
||||
TLayoutDepth layoutDepth;
|
||||
bool blendEquation; // true if any blend equation was specified
|
||||
int numViews; // multiview extenstions
|
||||
TInterlockOrdering interlockOrdering;
|
||||
|
||||
#ifdef NV_EXTENSIONS
|
||||
bool layoutOverrideCoverage; // true if layout override_coverage set
|
||||
@ -1165,6 +1190,7 @@ struct TShaderQualifiers {
|
||||
layoutDerivativeGroupLinear = false;
|
||||
primitives = TQualifier::layoutNotSet;
|
||||
#endif
|
||||
interlockOrdering = EioNone;
|
||||
}
|
||||
|
||||
// Merge in characteristics from the 'src' qualifier. They can override when
|
||||
@ -1215,6 +1241,9 @@ struct TShaderQualifiers {
|
||||
if (src.primitives != TQualifier::layoutNotSet)
|
||||
primitives = src.primitives;
|
||||
#endif
|
||||
|
||||
if (src.interlockOrdering != EioNone)
|
||||
interlockOrdering = src.interlockOrdering;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -621,6 +621,9 @@ enum TOperator {
|
||||
EOpCooperativeMatrixStore,
|
||||
EOpCooperativeMatrixMulAdd,
|
||||
|
||||
EOpBeginInvocationInterlock, // Fragment only
|
||||
EOpEndInvocationInterlock, // Fragment only
|
||||
|
||||
//
|
||||
// Branch
|
||||
//
|
||||
|
@ -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:
|
||||
|
@ -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 &&
|
||||
|
@ -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&);
|
||||
|
@ -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"
|
||||
|
@ -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";
|
||||
|
@ -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
|
||||
|
@ -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];
|
||||
|
@ -319,6 +319,8 @@ INSTANTIATE_TEST_CASE_P(
|
||||
"spv.fragmentDensity.vert",
|
||||
"spv.fragmentDensity-es.frag",
|
||||
"spv.fragmentDensity-neg.frag",
|
||||
"spv.fsi.frag",
|
||||
"spv.fsi_Error.frag",
|
||||
"spv.fullyCovered.frag",
|
||||
"spv.functionCall.frag",
|
||||
"spv.functionNestedOpaque.vert",
|
||||
|
@ -5,14 +5,14 @@
|
||||
"site" : "github",
|
||||
"subrepo" : "KhronosGroup/SPIRV-Tools",
|
||||
"subdir" : "External/spirv-tools",
|
||||
"commit" : "9dfd4b8358077bdbe8e2f9388572b5376c370f5d"
|
||||
"commit" : "2c0111e6eba779cf30e8c7f5a733ea0762895ba0"
|
||||
},
|
||||
{
|
||||
"name" : "spirv-tools/external/spirv-headers",
|
||||
"site" : "github",
|
||||
"subrepo" : "KhronosGroup/SPIRV-Headers",
|
||||
"subdir" : "External/spirv-tools/external/spirv-headers",
|
||||
"commit" : "4b0985f29277a81f5ce88feb0502cc44d6d5e7c3"
|
||||
"commit" : "8b911bd2ba37677037b38c9bd286c7c05701bcda"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user