From 070863af690bcc160da6e49d913f5d2e45bf095c Mon Sep 17 00:00:00 2001 From: dwang102 Date: Fri, 15 Jul 2022 14:36:03 +0800 Subject: [PATCH] Add SPV_AMD_shader_early_and_late_fragment_tests --- SPIRV/GLSL.ext.KHR.h | 1 + SPIRV/GlslangToSpv.cpp | 23 ++++++++++ SPIRV/doc.cpp | 42 ++++++++++-------- SPIRV/spirv.hpp | 7 +++ .../spv.earlyAndlateFragmentTests.frag.out | 41 +++++++++++++++++ .../spv.shaderStencilExport.frag.out | 1 + Test/spv.earlyAndlateFragmentTests.frag | 12 +++++ glslang/Include/BaseTypes.h | 2 + glslang/Include/Types.h | 35 +++++++++++++++ glslang/MachineIndependent/Initialize.cpp | 1 + glslang/MachineIndependent/ParseHelper.cpp | 44 ++++++++++++++++++- glslang/MachineIndependent/Versions.cpp | 1 + glslang/MachineIndependent/Versions.h | 1 + .../MachineIndependent/localintermediate.h | 18 +++++++- 14 files changed, 207 insertions(+), 22 deletions(-) create mode 100644 Test/baseResults/spv.earlyAndlateFragmentTests.frag.out create mode 100644 Test/spv.earlyAndlateFragmentTests.frag diff --git a/SPIRV/GLSL.ext.KHR.h b/SPIRV/GLSL.ext.KHR.h index 5c89480e..d5c670f0 100644 --- a/SPIRV/GLSL.ext.KHR.h +++ b/SPIRV/GLSL.ext.KHR.h @@ -53,5 +53,6 @@ static const char* const E_SPV_KHR_terminate_invocation = "SPV_KHR_termi static const char* const E_SPV_KHR_workgroup_memory_explicit_layout = "SPV_KHR_workgroup_memory_explicit_layout"; static const char* const E_SPV_KHR_subgroup_uniform_control_flow = "SPV_KHR_subgroup_uniform_control_flow"; static const char* const E_SPV_KHR_fragment_shader_barycentric = "SPV_KHR_fragment_shader_barycentric"; +static const char* const E_SPV_AMD_shader_early_and_late_fragment_tests = "SPV_AMD_shader_early_and_late_fragment_tests"; #endif // #ifndef GLSLextKHR_H diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp index 3c869bc9..307ee28e 100644 --- a/SPIRV/GlslangToSpv.cpp +++ b/SPIRV/GlslangToSpv.cpp @@ -1623,6 +1623,12 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, if (glslangIntermediate->getEarlyFragmentTests()) builder.addExecutionMode(shaderEntry, spv::ExecutionModeEarlyFragmentTests); + if (glslangIntermediate->getEarlyAndLateFragmentTestsAMD()) + { + builder.addExecutionMode(shaderEntry, spv::ExecutionModeEarlyAndLateFragmentTestsAMD); + builder.addExtension(spv::E_SPV_AMD_shader_early_and_late_fragment_tests); + } + if (glslangIntermediate->getPostDepthCoverage()) { builder.addCapability(spv::CapabilitySampleMaskPostDepthCoverage); builder.addExecutionMode(shaderEntry, spv::ExecutionModePostDepthCoverage); @@ -1632,6 +1638,9 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, if (glslangIntermediate->isDepthReplacing()) builder.addExecutionMode(shaderEntry, spv::ExecutionModeDepthReplacing); + if (glslangIntermediate->isStencilReplacing()) + builder.addExecutionMode(shaderEntry, spv::ExecutionModeStencilRefReplacingEXT); + #ifndef GLSLANG_WEB switch(glslangIntermediate->getDepth()) { @@ -1640,6 +1649,20 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, case glslang::EldUnchanged: mode = spv::ExecutionModeDepthUnchanged; break; default: mode = spv::ExecutionModeMax; break; } + + if (mode != spv::ExecutionModeMax) + builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode); + + switch (glslangIntermediate->getStencil()) { + case glslang::ElsRefUnchangedFrontAMD: mode = spv::ExecutionModeStencilRefUnchangedFrontAMD; break; + case glslang::ElsRefGreaterFrontAMD: mode = spv::ExecutionModeStencilRefGreaterFrontAMD; break; + case glslang::ElsRefLessFrontAMD: mode = spv::ExecutionModeStencilRefLessFrontAMD; break; + case glslang::ElsRefUnchangedBackAMD: mode = spv::ExecutionModeStencilRefUnchangedBackAMD; break; + case glslang::ElsRefGreaterBackAMD: mode = spv::ExecutionModeStencilRefGreaterBackAMD; break; + case glslang::ElsRefLessBackAMD: mode = spv::ExecutionModeStencilRefLessBackAMD; break; + default: mode = spv::ExecutionModeMax; break; + } + if (mode != spv::ExecutionModeMax) builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode); switch (glslangIntermediate->getInterlockOrdering()) { diff --git a/SPIRV/doc.cpp b/SPIRV/doc.cpp index 1ba92a87..9cc26541 100644 --- a/SPIRV/doc.cpp +++ b/SPIRV/doc.cpp @@ -173,28 +173,32 @@ const char* ExecutionModeString(int mode) case 31: return "ContractionOff"; case 32: return "Bad"; - case ExecutionModeInitializer: return "Initializer"; - case ExecutionModeFinalizer: return "Finalizer"; - case ExecutionModeSubgroupSize: return "SubgroupSize"; - case ExecutionModeSubgroupsPerWorkgroup: return "SubgroupsPerWorkgroup"; - case ExecutionModeSubgroupsPerWorkgroupId: return "SubgroupsPerWorkgroupId"; - case ExecutionModeLocalSizeId: return "LocalSizeId"; - case ExecutionModeLocalSizeHintId: return "LocalSizeHintId"; + case ExecutionModeInitializer: return "Initializer"; + case ExecutionModeFinalizer: return "Finalizer"; + case ExecutionModeSubgroupSize: return "SubgroupSize"; + case ExecutionModeSubgroupsPerWorkgroup: return "SubgroupsPerWorkgroup"; + case ExecutionModeSubgroupsPerWorkgroupId: return "SubgroupsPerWorkgroupId"; + case ExecutionModeLocalSizeId: return "LocalSizeId"; + case ExecutionModeLocalSizeHintId: return "LocalSizeHintId"; - case ExecutionModePostDepthCoverage: return "PostDepthCoverage"; - case ExecutionModeDenormPreserve: return "DenormPreserve"; - case ExecutionModeDenormFlushToZero: return "DenormFlushToZero"; - case ExecutionModeSignedZeroInfNanPreserve: return "SignedZeroInfNanPreserve"; - case ExecutionModeRoundingModeRTE: return "RoundingModeRTE"; - case ExecutionModeRoundingModeRTZ: return "RoundingModeRTZ"; - case ExecutionModeStencilRefReplacingEXT: return "StencilRefReplacingEXT"; + case ExecutionModePostDepthCoverage: return "PostDepthCoverage"; + case ExecutionModeDenormPreserve: return "DenormPreserve"; + case ExecutionModeDenormFlushToZero: return "DenormFlushToZero"; + case ExecutionModeSignedZeroInfNanPreserve: return "SignedZeroInfNanPreserve"; + case ExecutionModeRoundingModeRTE: return "RoundingModeRTE"; + case ExecutionModeRoundingModeRTZ: return "RoundingModeRTZ"; + case ExecutionModeEarlyAndLateFragmentTestsAMD: return "EarlyAndLateFragmentTestsAMD"; + case ExecutionModeStencilRefUnchangedFrontAMD: return "StencilRefUnchangedFrontAMD"; + case ExecutionModeStencilRefLessFrontAMD: return "StencilRefLessFrontAMD"; + case ExecutionModeStencilRefGreaterBackAMD: return "StencilRefGreaterBackAMD"; + case ExecutionModeStencilRefReplacingEXT: return "StencilRefReplacingEXT"; case ExecutionModeSubgroupUniformControlFlowKHR: return "SubgroupUniformControlFlow"; - case ExecutionModeOutputLinesNV: return "OutputLinesNV"; - case ExecutionModeOutputPrimitivesNV: return "OutputPrimitivesNV"; - case ExecutionModeOutputTrianglesNV: return "OutputTrianglesNV"; - case ExecutionModeDerivativeGroupQuadsNV: return "DerivativeGroupQuadsNV"; - case ExecutionModeDerivativeGroupLinearNV: return "DerivativeGroupLinearNV"; + case ExecutionModeOutputLinesNV: return "OutputLinesNV"; + case ExecutionModeOutputPrimitivesNV: return "OutputPrimitivesNV"; + case ExecutionModeOutputTrianglesNV: return "OutputTrianglesNV"; + case ExecutionModeDerivativeGroupQuadsNV: return "DerivativeGroupQuadsNV"; + case ExecutionModeDerivativeGroupLinearNV: return "DerivativeGroupLinearNV"; case ExecutionModePixelInterlockOrderedEXT: return "PixelInterlockOrderedEXT"; case ExecutionModePixelInterlockUnorderedEXT: return "PixelInterlockUnorderedEXT"; diff --git a/SPIRV/spirv.hpp b/SPIRV/spirv.hpp index 806b4ddc..9afd8a90 100644 --- a/SPIRV/spirv.hpp +++ b/SPIRV/spirv.hpp @@ -158,7 +158,14 @@ enum ExecutionMode { ExecutionModeSignedZeroInfNanPreserve = 4461, ExecutionModeRoundingModeRTE = 4462, ExecutionModeRoundingModeRTZ = 4463, + ExecutionModeEarlyAndLateFragmentTestsAMD = 5017, ExecutionModeStencilRefReplacingEXT = 5027, + ExecutionModeStencilRefUnchangedFrontAMD = 5079, + ExecutionModeStencilRefGreaterFrontAMD = 5080, + ExecutionModeStencilRefLessFrontAMD = 5081, + ExecutionModeStencilRefUnchangedBackAMD = 5082, + ExecutionModeStencilRefGreaterBackAMD = 5083, + ExecutionModeStencilRefLessBackAMD = 5084, ExecutionModeOutputLinesNV = 5269, ExecutionModeOutputPrimitivesNV = 5270, ExecutionModeDerivativeGroupQuadsNV = 5289, diff --git a/Test/baseResults/spv.earlyAndlateFragmentTests.frag.out b/Test/baseResults/spv.earlyAndlateFragmentTests.frag.out new file mode 100644 index 00000000..e5b9a427 --- /dev/null +++ b/Test/baseResults/spv.earlyAndlateFragmentTests.frag.out @@ -0,0 +1,41 @@ +spv.earlyAndlateFragmentTests.frag +// Module Version 10000 +// Generated by (magic number): 8000a +// Id's are bound by 16 + + Capability Shader + Extension "SPV_AMD_shader_early_and_late_fragment_tests" + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint Fragment 4 "main" 8 11 + ExecutionMode 4 OriginUpperLeft + ExecutionMode 4 EarlyAndLateFragmentTestsAMD + ExecutionMode 4 DepthReplacing + ExecutionMode 4 DepthLess + Source GLSL 450 + SourceExtension "GL_ARB_fragment_shader_interlock" + SourceExtension "GL_ARB_shader_stencil_export" + SourceExtension "GL_EXT_fragment_shading_rate" + Name 4 "main" + Name 8 "gl_FragDepth" + Name 11 "instanceIndex" + Decorate 8(gl_FragDepth) BuiltIn FragDepth + Decorate 11(instanceIndex) Flat + Decorate 11(instanceIndex) Location 0 + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeFloat 32 + 7: TypePointer Output 6(float) + 8(gl_FragDepth): 7(ptr) Variable Output + 9: TypeInt 32 1 + 10: TypePointer Input 9(int) +11(instanceIndex): 10(ptr) Variable Input + 14: 6(float) Constant 1117913088 + 4(main): 2 Function None 3 + 5: Label + 12: 9(int) Load 11(instanceIndex) + 13: 6(float) ConvertSToF 12 + 15: 6(float) FDiv 13 14 + Store 8(gl_FragDepth) 15 + Return + FunctionEnd diff --git a/Test/baseResults/spv.shaderStencilExport.frag.out b/Test/baseResults/spv.shaderStencilExport.frag.out index f73349c9..9bb21789 100644 --- a/Test/baseResults/spv.shaderStencilExport.frag.out +++ b/Test/baseResults/spv.shaderStencilExport.frag.out @@ -10,6 +10,7 @@ spv.shaderStencilExport.frag MemoryModel Logical GLSL450 EntryPoint Fragment 4 "main" 8 ExecutionMode 4 OriginUpperLeft + ExecutionMode 4 StencilRefReplacingEXT Source GLSL 450 SourceExtension "GL_ARB_shader_stencil_export" Name 4 "main" diff --git a/Test/spv.earlyAndlateFragmentTests.frag b/Test/spv.earlyAndlateFragmentTests.frag new file mode 100644 index 00000000..ef3b4af6 --- /dev/null +++ b/Test/spv.earlyAndlateFragmentTests.frag @@ -0,0 +1,12 @@ +#version 450 core +#extension GL_EXT_fragment_shading_rate : enable +#extension GL_ARB_shader_stencil_export : enable +#extension GL_ARB_fragment_shader_interlock : enable +#extension GL_AMD_shader_early_and_late_fragment_tests : enable +layout(location = 0) flat in int instanceIndex; +layout(early_and_late_fragment_tests_amd) in; +layout(depth_less) out float gl_FragDepth; +void main() +{ + gl_FragDepth = float(instanceIndex) / float(81); +} diff --git a/glslang/Include/BaseTypes.h b/glslang/Include/BaseTypes.h index 3eec5973..6a429fd4 100644 --- a/glslang/Include/BaseTypes.h +++ b/glslang/Include/BaseTypes.h @@ -128,6 +128,7 @@ enum TStorageQualifier { // built-ins written by fragment shader EvqFragColor, EvqFragDepth, + EvqFragStencil, // end of list EvqLast @@ -353,6 +354,7 @@ __inline const char* GetStorageQualifierString(TStorageQualifier q) case EvqPointCoord: return "gl_PointCoord"; break; case EvqFragColor: return "fragColor"; break; case EvqFragDepth: return "gl_FragDepth"; break; + case EvqFragStencil: return "gl_FragStencilRefARB"; break; case EvqPayload: return "rayPayloadNV"; break; case EvqPayloadIn: return "rayPayloadInNV"; break; case EvqHitAttr: return "hitAttributeNV"; break; diff --git a/glslang/Include/Types.h b/glslang/Include/Types.h index 682d124c..93909a30 100644 --- a/glslang/Include/Types.h +++ b/glslang/Include/Types.h @@ -443,6 +443,18 @@ enum TLayoutDepth { EldCount }; +enum TLayoutStencil { + ElsNone, + ElsRefUnchangedFrontAMD, + ElsRefGreaterFrontAMD, + ElsRefLessFrontAMD, + ElsRefUnchangedBackAMD, + ElsRefGreaterBackAMD, + ElsRefLessBackAMD, + + ElsCount +}; + enum TBlendEquationShift { // No 'EBlendNone': // These are used as bit-shift amounts. A mask of such shifts will have type 'int', @@ -705,6 +717,7 @@ public: case EvqVaryingOut: case EvqFragColor: case EvqFragDepth: + case EvqFragStencil: return true; default: return false; @@ -772,6 +785,7 @@ public: case EvqVaryingOut: case EvqFragColor: case EvqFragDepth: + case EvqFragStencil: return true; default: return false; @@ -1239,6 +1253,18 @@ public: default: return "none"; } } + static const char* getLayoutStencilString(TLayoutStencil s) + { + switch (s) { + case ElsRefUnchangedFrontAMD: return "stencil_ref_unchanged_front_amd"; + case ElsRefGreaterFrontAMD: return "stencil_ref_greater_front_amd"; + case ElsRefLessFrontAMD: return "stencil_ref_less_front_amd"; + case ElsRefUnchangedBackAMD: return "stencil_ref_unchanged_back_amd"; + case ElsRefGreaterBackAMD: return "stencil_ref_greater_back_amd"; + case ElsRefLessBackAMD: return "stencil_ref_less_back_amd"; + default: return "none"; + } + } static const char* getBlendEquationString(TBlendEquationShift e) { switch (e) { @@ -1336,7 +1362,9 @@ struct TShaderQualifiers { #ifndef GLSLANG_WEB bool earlyFragmentTests; // fragment input bool postDepthCoverage; // fragment input + bool earlyAndLateFragmentTestsAMD; //fragment input TLayoutDepth layoutDepth; + TLayoutStencil layoutStencil; bool blendEquation; // true if any blend equation was specified int numViews; // multiview extenstions TInterlockOrdering interlockOrdering; @@ -1346,6 +1374,7 @@ struct TShaderQualifiers { int primitives; // mesh shader "max_primitives"DerivativeGroupLinear; // true if layout derivative_group_linearNV set bool layoutPrimitiveCulling; // true if layout primitive_culling set TLayoutDepth getDepth() const { return layoutDepth; } + TLayoutStencil getStencil() const { return layoutStencil; } #else TLayoutDepth getDepth() const { return EldNone; } #endif @@ -1371,8 +1400,10 @@ struct TShaderQualifiers { localSizeSpecId[2] = TQualifier::layoutNotSet; #ifndef GLSLANG_WEB earlyFragmentTests = false; + earlyAndLateFragmentTestsAMD = false; postDepthCoverage = false; layoutDepth = EldNone; + layoutStencil = ElsNone; blendEquation = false; numViews = TQualifier::layoutNotSet; layoutOverrideCoverage = false; @@ -1424,10 +1455,14 @@ struct TShaderQualifiers { #ifndef GLSLANG_WEB if (src.earlyFragmentTests) earlyFragmentTests = true; + if (src.earlyAndLateFragmentTestsAMD) + earlyAndLateFragmentTestsAMD = true; if (src.postDepthCoverage) postDepthCoverage = true; if (src.layoutDepth) layoutDepth = src.layoutDepth; + if (src.layoutStencil) + layoutStencil = src.layoutStencil; if (src.blendEquation) blendEquation = src.blendEquation; if (src.numViews != TQualifier::layoutNotSet) diff --git a/glslang/MachineIndependent/Initialize.cpp b/glslang/MachineIndependent/Initialize.cpp index b18b2575..ff3db7cd 100644 --- a/glslang/MachineIndependent/Initialize.cpp +++ b/glslang/MachineIndependent/Initialize.cpp @@ -8065,6 +8065,7 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion SpecialQualifier("gl_FragDepth", EvqFragDepth, EbvFragDepth, symbolTable); #ifndef GLSLANG_WEB SpecialQualifier("gl_FragDepthEXT", EvqFragDepth, EbvFragDepth, symbolTable); + SpecialQualifier("gl_FragStencilRefARB", EvqFragStencil, EbvFragStencilRef, symbolTable); SpecialQualifier("gl_HelperInvocation", EvqVaryingIn, EbvHelperInvocation, symbolTable); BuiltInVariable("gl_ClipDistance", EbvClipDistance, symbolTable); diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index 45a72d93..143d6214 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -2988,6 +2988,12 @@ bool TParseContext::lValueErrorCheck(const TSourceLoc& loc, const char* op, TInt if (isEsProfile() && intermediate.getEarlyFragmentTests()) message = "can't modify gl_FragDepth if using early_fragment_tests"; break; + case EvqFragStencil: + intermediate.setStencilReplacing(); + // "In addition, it is an error to statically write to gl_FragDepth in the fragment shader." + if (isEsProfile() && intermediate.getEarlyFragmentTests()) + message = "can't modify EvqFragStencil if using early_fragment_tests"; + break; default: break; @@ -4709,10 +4715,22 @@ TSymbol* TParseContext::redeclareBuiltinVariable(const TSourceLoc& loc, const TS if (! intermediate.setDepth(publicType.layoutDepth)) error(loc, "all redeclarations must use the same depth layout on", "redeclaration", symbol->getName().c_str()); } + } else if (identifier == "gl_FragStencilRefARB") { + if (qualifier.nopersp != symbolQualifier.nopersp || qualifier.flat != symbolQualifier.flat || + qualifier.isMemory() || qualifier.isAuxiliary()) + error(loc, "can only change layout qualification of", "redeclaration", symbol->getName().c_str()); + if (qualifier.storage != EvqVaryingOut) + error(loc, "cannot change output storage qualification of", "redeclaration", symbol->getName().c_str()); + if (publicType.layoutStencil != ElsNone) { + if (intermediate.inIoAccessed("gl_FragStencilRefARB")) + error(loc, "cannot redeclare after use", "gl_FragStencilRefARB", ""); + if (!intermediate.setStencil(publicType.layoutStencil)) + error(loc, "all redeclarations must use the same stencil layout on", "redeclaration", + symbol->getName().c_str()); + } } else if ( - identifier == "gl_PrimitiveIndicesNV" || - identifier == "gl_FragStencilRefARB") { + identifier == "gl_PrimitiveIndicesNV") { if (qualifier.hasLayout()) error(loc, "cannot apply layout qualifier to", "redeclaration", symbol->getName().c_str()); if (qualifier.storage != EvqVaryingOut) @@ -5546,6 +5564,12 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi publicType.shaderQualifiers.earlyFragmentTests = true; return; } + if (id == "early_and_late_fragment_tests_amd") { + profileRequires(loc, ENoProfile | ECoreProfile | ECompatibilityProfile, 420, E_GL_AMD_shader_early_and_late_fragment_tests, "early_and_late_fragment_tests_amd"); + profileRequires(loc, EEsProfile, 310, nullptr, "early_and_late_fragment_tests_amd"); + publicType.shaderQualifiers.earlyAndLateFragmentTestsAMD = true; + return; + } if (id == "post_depth_coverage") { requireExtensions(loc, Num_post_depth_coverageEXTs, post_depth_coverageEXTs, "post depth coverage"); if (extensionTurnedOn(E_GL_ARB_post_depth_coverage)) { @@ -5562,6 +5586,14 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi return; } } + for (TLayoutStencil stencil = (TLayoutStencil)(ElsNone + 1); stencil < ElsCount; stencil = (TLayoutStencil)(stencil+1)) { + if (id == TQualifier::getLayoutStencilString(stencil)) { + requireProfile(loc, ECoreProfile | ECompatibilityProfile, "stencil layout qualifier"); + profileRequires(loc, ECoreProfile | ECompatibilityProfile, 420, nullptr, "stencil layout qualifier"); + publicType.shaderQualifiers.layoutStencil = stencil; + 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"); @@ -7259,6 +7291,8 @@ TIntermNode* TParseContext::declareVariable(const TSourceLoc& loc, TString& iden error(loc, "can only apply origin_upper_left and pixel_center_origin to gl_FragCoord", "layout qualifier", ""); if (identifier != "gl_FragDepth" && publicType.shaderQualifiers.getDepth() != EldNone) error(loc, "can only apply depth layout to gl_FragDepth", "layout qualifier", ""); + if (identifier != "gl_FragStencilRefARB" && publicType.shaderQualifiers.getStencil() != ElsNone) + error(loc, "can only apply depth layout to gl_FragStencilRefARB", "layout qualifier", ""); // Check for redeclaration of built-ins and/or attempting to declare a reserved name TSymbol* symbol = redeclareBuiltinVariable(loc, identifier, type.getQualifier(), publicType.shaderQualifiers); @@ -9091,6 +9125,12 @@ void TParseContext::updateStandaloneQualifierDefaults(const TSourceLoc& loc, con else error(loc, "can only apply to 'in'", "early_fragment_tests", ""); } + if (publicType.shaderQualifiers.earlyAndLateFragmentTestsAMD) { + if (publicType.qualifier.storage == EvqVaryingIn) + intermediate.setEarlyAndLateFragmentTestsAMD(); + else + error(loc, "can only apply to 'in'", "early_and_late_fragment_tests_amd", ""); + } if (publicType.shaderQualifiers.postDepthCoverage) { if (publicType.qualifier.storage == EvqVaryingIn) intermediate.setPostDepthCoverage(); diff --git a/glslang/MachineIndependent/Versions.cpp b/glslang/MachineIndependent/Versions.cpp index 52c1e1cc..e24d5c54 100644 --- a/glslang/MachineIndependent/Versions.cpp +++ b/glslang/MachineIndependent/Versions.cpp @@ -275,6 +275,7 @@ void TParseVersions::initializeExtensionBehavior() extensionBehavior[E_GL_AMD_shader_image_load_store_lod] = EBhDisable; extensionBehavior[E_GL_AMD_shader_fragment_mask] = EBhDisable; extensionBehavior[E_GL_AMD_gpu_shader_half_float_fetch] = EBhDisable; + extensionBehavior[E_GL_AMD_shader_early_and_late_fragment_tests] = EBhDisable; extensionBehavior[E_GL_INTEL_shader_integer_functions2] = EBhDisable; diff --git a/glslang/MachineIndependent/Versions.h b/glslang/MachineIndependent/Versions.h index c411f5b6..6817cff2 100644 --- a/glslang/MachineIndependent/Versions.h +++ b/glslang/MachineIndependent/Versions.h @@ -238,6 +238,7 @@ const char* const E_GL_AMD_gpu_shader_int16 = "GL_AMD_gpu_sh const char* const E_GL_AMD_shader_image_load_store_lod = "GL_AMD_shader_image_load_store_lod"; const char* const E_GL_AMD_shader_fragment_mask = "GL_AMD_shader_fragment_mask"; const char* const E_GL_AMD_gpu_shader_half_float_fetch = "GL_AMD_gpu_shader_half_float_fetch"; +const char* const E_GL_AMD_shader_early_and_late_fragment_tests = "GL_AMD_shader_early_and_late_fragment_tests"; const char* const E_GL_INTEL_shader_integer_functions2 = "GL_INTEL_shader_integer_functions2"; diff --git a/glslang/MachineIndependent/localintermediate.h b/glslang/MachineIndependent/localintermediate.h index d3e86f9e..ddeaa353 100644 --- a/glslang/MachineIndependent/localintermediate.h +++ b/glslang/MachineIndependent/localintermediate.h @@ -296,6 +296,7 @@ public: invariantAll(false), nanMinMaxClamp(false), depthReplacing(false), + stencilReplacing(false), uniqueId(0), globalUniformBlockName(""), atomicCounterBlockName(""), @@ -311,7 +312,7 @@ public: inputPrimitive(ElgNone), outputPrimitive(ElgNone), pixelCenterInteger(false), originUpperLeft(false),texCoordBuiltinRedeclared(false), vertexSpacing(EvsNone), vertexOrder(EvoNone), interlockOrdering(EioNone), pointMode(false), earlyFragmentTests(false), - postDepthCoverage(false), depthLayout(EldNone), + postDepthCoverage(false), earlyAndLateFragmentTestsAMD(false), depthLayout(EldNone), stencilLayout(ElsNone), hlslFunctionality1(false), blendEquations(0), xfbMode(false), multiStream(false), layoutOverrideCoverage(false), @@ -587,6 +588,8 @@ public: bool isInvariantAll() const { return invariantAll; } void setDepthReplacing() { depthReplacing = true; } bool isDepthReplacing() const { return depthReplacing; } + void setStencilReplacing() { stencilReplacing = true; } + bool isStencilReplacing() const { return stencilReplacing; } bool setLocalSize(int dim, int size) { if (localSizeNotDefault[dim]) @@ -821,7 +824,9 @@ public: void setPostDepthCoverage() { postDepthCoverage = true; } bool getPostDepthCoverage() const { return postDepthCoverage; } void setEarlyFragmentTests() { earlyFragmentTests = true; } + void setEarlyAndLateFragmentTestsAMD() { earlyAndLateFragmentTestsAMD = true; } bool getEarlyFragmentTests() const { return earlyFragmentTests; } + bool getEarlyAndLateFragmentTestsAMD() const { return earlyAndLateFragmentTestsAMD; } bool setDepth(TLayoutDepth d) { if (depthLayout != EldNone) @@ -829,7 +834,15 @@ public: depthLayout = d; return true; } + bool setStencil(TLayoutStencil s) + { + if (stencilLayout != ElsNone) + return stencilLayout == s; + stencilLayout = s; + return true; + } TLayoutDepth getDepth() const { return depthLayout; } + TLayoutStencil getStencil() const { return stencilLayout; } void setOriginUpperLeft() { originUpperLeft = true; } bool getOriginUpperLeft() const { return originUpperLeft; } void setPixelCenterInteger() { pixelCenterInteger = true; } @@ -1100,6 +1113,7 @@ protected: bool invariantAll; bool nanMinMaxClamp; // true if desiring min/max/clamp to favor non-NaN over NaN bool depthReplacing; + bool stencilReplacing; int localSize[3]; bool localSizeNotDefault[3]; int localSizeSpecId[3]; @@ -1131,7 +1145,9 @@ protected: bool pointMode; bool earlyFragmentTests; bool postDepthCoverage; + bool earlyAndLateFragmentTestsAMD; TLayoutDepth depthLayout; + TLayoutStencil stencilLayout; bool hlslFunctionality1; int blendEquations; // an 'or'ing of masks of shifts of TBlendEquationShift bool xfbMode;