diff --git a/SPIRV/GLSL.ext.KHR.h b/SPIRV/GLSL.ext.KHR.h index 5bda76598..83ca83f5e 100644 --- a/SPIRV/GLSL.ext.KHR.h +++ b/SPIRV/GLSL.ext.KHR.h @@ -53,6 +53,7 @@ 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_KHR_quad_control = "SPV_KHR_quad_control"; static const char* const E_SPV_AMD_shader_early_and_late_fragment_tests = "SPV_AMD_shader_early_and_late_fragment_tests"; static const char* const E_SPV_KHR_ray_tracing_position_fetch = "SPV_KHR_ray_tracing_position_fetch"; static const char* const E_SPV_KHR_cooperative_matrix = "SPV_KHR_cooperative_matrix"; diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp index 2d5aa7a73..30232e355 100755 --- a/SPIRV/GlslangToSpv.cpp +++ b/SPIRV/GlslangToSpv.cpp @@ -1640,6 +1640,20 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, builder.addExecutionMode(shaderEntry, spv::ExecutionModeMaximallyReconvergesKHR); } + if (glslangIntermediate->getQuadDerivMode()) + { + builder.addCapability(spv::CapabilityQuadControlKHR); + builder.addExtension(spv::E_SPV_KHR_quad_control); + builder.addExecutionMode(shaderEntry, spv::ExecutionModeQuadDerivativesKHR); + } + + if (glslangIntermediate->getReqFullQuadsMode()) + { + builder.addCapability(spv::CapabilityQuadControlKHR); + builder.addExtension(spv::E_SPV_KHR_quad_control); + builder.addExecutionMode(shaderEntry, spv::ExecutionModeRequireFullQuadsKHR); + } + unsigned int mode; switch (glslangIntermediate->getStage()) { case EShLangVertex: @@ -7173,7 +7187,9 @@ spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, OpDe case glslang::EOpSubgroupExclusiveXor: case glslang::EOpSubgroupQuadSwapHorizontal: case glslang::EOpSubgroupQuadSwapVertical: - case glslang::EOpSubgroupQuadSwapDiagonal: { + case glslang::EOpSubgroupQuadSwapDiagonal: + case glslang::EOpSubgroupQuadAll: + case glslang::EOpSubgroupQuadAny: { std::vector operands; operands.push_back(operand); return createSubgroupOperation(op, typeId, operands, typeProxy); @@ -8278,6 +8294,11 @@ spv::Id TGlslangToSpvTraverser::createSubgroupOperation(glslang::TOperator op, s case glslang::EOpSubgroupElect: builder.addCapability(spv::CapabilityGroupNonUniform); break; + case glslang::EOpSubgroupQuadAll: + case glslang::EOpSubgroupQuadAny: + builder.addExtension(spv::E_SPV_KHR_quad_control); + builder.addCapability(spv::CapabilityQuadControlKHR); + // pass through case glslang::EOpSubgroupAll: case glslang::EOpSubgroupAny: case glslang::EOpSubgroupAllEqual: @@ -8385,7 +8406,9 @@ spv::Id TGlslangToSpvTraverser::createSubgroupOperation(glslang::TOperator op, s // Figure out which opcode to use. switch (op) { case glslang::EOpSubgroupElect: opCode = spv::OpGroupNonUniformElect; break; + case glslang::EOpSubgroupQuadAll: opCode = spv::OpGroupNonUniformQuadAllKHR; break; case glslang::EOpSubgroupAll: opCode = spv::OpGroupNonUniformAll; break; + case glslang::EOpSubgroupQuadAny: opCode = spv::OpGroupNonUniformQuadAnyKHR; break; case glslang::EOpSubgroupAny: opCode = spv::OpGroupNonUniformAny; break; case glslang::EOpSubgroupAllEqual: opCode = spv::OpGroupNonUniformAllEqual; break; case glslang::EOpSubgroupBroadcast: opCode = spv::OpGroupNonUniformBroadcast; break; @@ -8582,7 +8605,10 @@ spv::Id TGlslangToSpvTraverser::createSubgroupOperation(glslang::TOperator op, s // Every operation begins with the Execution Scope operand. spv::IdImmediate executionScope = { true, builder.makeUintConstant(spv::ScopeSubgroup) }; - spvGroupOperands.push_back(executionScope); + // All other ops need the execution scope. Quad Control Ops don't need scope, it's always Quad. + if (opCode != spv::OpGroupNonUniformQuadAllKHR && opCode != spv::OpGroupNonUniformQuadAnyKHR) { + spvGroupOperands.push_back(executionScope); + } // Next, for all operations that use a Group Operation, push that as an operand. if (groupOperation != spv::GroupOperationMax) { diff --git a/SPIRV/doc.cpp b/SPIRV/doc.cpp index 3915dccb5..a342eee38 100755 --- a/SPIRV/doc.cpp +++ b/SPIRV/doc.cpp @@ -218,6 +218,9 @@ const char* ExecutionModeString(int mode) case ExecutionModeNoGlobalOffsetINTEL: return "NoGlobalOffsetINTEL"; case ExecutionModeNumSIMDWorkitemsINTEL: return "NumSIMDWorkitemsINTEL"; + case ExecutionModeRequireFullQuadsKHR: return "RequireFullQuadsKHR"; + case ExecutionModeQuadDerivativesKHR: return "QuadDerivativesKHR"; + case ExecutionModeNonCoherentColorAttachmentReadEXT: return "NonCoherentColorAttachmentReadEXT"; case ExecutionModeNonCoherentDepthAttachmentReadEXT: return "NonCoherentDepthAttachmentReadEXT"; case ExecutionModeNonCoherentStencilAttachmentReadEXT: return "NonCoherentStencilAttachmentReadEXT"; @@ -1033,6 +1036,7 @@ const char* CapabilityString(int info) case CapabilityDemoteToHelperInvocationEXT: return "DemoteToHelperInvocationEXT"; case CapabilityShaderClockKHR: return "ShaderClockKHR"; + case CapabilityQuadControlKHR: return "QuadControlKHR"; case CapabilityInt64ImageEXT: return "Int64ImageEXT"; case CapabilityIntegerFunctions2INTEL: return "CapabilityIntegerFunctions2INTEL"; @@ -1433,6 +1437,9 @@ const char* OpcodeString(int op) case 4430: return "OpSubgroupAllEqualKHR"; case 4432: return "OpSubgroupReadInvocationKHR"; + case OpGroupNonUniformQuadAllKHR: return "OpGroupNonUniformQuadAllKHR"; + case OpGroupNonUniformQuadAnyKHR: return "OpGroupNonUniformQuadAnyKHR"; + case OpAtomicFAddEXT: return "OpAtomicFAddEXT"; case OpAtomicFMinEXT: return "OpAtomicFMinEXT"; case OpAtomicFMaxEXT: return "OpAtomicFMaxEXT"; @@ -2940,6 +2947,8 @@ void Parameterize() InstructionDesc[OpGroupNonUniformPartitionNV].operands.push(OperandId, "X"); + InstructionDesc[OpGroupNonUniformQuadAllKHR].operands.push(OperandId, "'Predicate'"); + InstructionDesc[OpGroupNonUniformQuadAnyKHR].operands.push(OperandId, "'Predicate'"); InstructionDesc[OpTypeAccelerationStructureKHR].setResultAndType(true, false); InstructionDesc[OpTraceNV].operands.push(OperandId, "'Acceleration Structure'"); diff --git a/SPIRV/spirv.hpp b/SPIRV/spirv.hpp index f5bf2d680..1fc3ae6f7 100644 --- a/SPIRV/spirv.hpp +++ b/SPIRV/spirv.hpp @@ -174,6 +174,8 @@ enum ExecutionMode { ExecutionModeStencilRefUnchangedBackAMD = 5082, ExecutionModeStencilRefGreaterBackAMD = 5083, ExecutionModeStencilRefLessBackAMD = 5084, + ExecutionModeQuadDerivativesKHR = 5088, + ExecutionModeRequireFullQuadsKHR = 5089, ExecutionModeOutputLinesEXT = 5269, ExecutionModeOutputLinesNV = 5269, ExecutionModeOutputPrimitivesEXT = 5270, @@ -1040,6 +1042,7 @@ enum Capability { CapabilityImageReadWriteLodAMD = 5015, CapabilityInt64ImageEXT = 5016, CapabilityShaderClockKHR = 5055, + CapabilityQuadControlKHR = 5087, CapabilitySampleMaskOverrideCoverageNV = 5249, CapabilityGeometryShaderPassthroughNV = 5251, CapabilityShaderViewportIndexLayerEXT = 5254, @@ -1705,6 +1708,8 @@ enum Op { OpFragmentMaskFetchAMD = 5011, OpFragmentFetchAMD = 5012, OpReadClockKHR = 5056, + OpGroupNonUniformQuadAllKHR = 5110, + OpGroupNonUniformQuadAnyKHR = 5111, OpHitObjectRecordHitMotionNV = 5249, OpHitObjectRecordHitWithIndexMotionNV = 5250, OpHitObjectRecordMissMotionNV = 5251, @@ -2375,6 +2380,8 @@ inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) { case OpGroupNonUniformLogicalXor: *hasResult = true; *hasResultType = true; break; case OpGroupNonUniformQuadBroadcast: *hasResult = true; *hasResultType = true; break; case OpGroupNonUniformQuadSwap: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformQuadAllKHR: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformQuadAnyKHR: *hasResult = true; *hasResultType = true; break; case OpCopyLogical: *hasResult = true; *hasResultType = true; break; case OpPtrEqual: *hasResult = true; *hasResultType = true; break; case OpPtrNotEqual: *hasResult = true; *hasResultType = true; break; diff --git a/Test/baseResults/spv.1.6.quad.frag.out b/Test/baseResults/spv.1.6.quad.frag.out new file mode 100644 index 000000000..9c4458127 --- /dev/null +++ b/Test/baseResults/spv.1.6.quad.frag.out @@ -0,0 +1,76 @@ +spv.1.6.quad.frag +// Module Version 10600 +// Generated by (magic number): 8000b +// Id's are bound by 39 + + Capability Shader + Capability GroupNonUniform + Capability GroupNonUniformVote + Capability QuadControlKHR + Extension "SPV_KHR_quad_control" + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint Fragment 4 "main" 16 33 + ExecutionMode 4 QuadDerivativesKHR + ExecutionMode 4 RequireFullQuadsKHR + ExecutionMode 4 OriginUpperLeft + Source GLSL 460 + SourceExtension "GL_EXT_shader_quad_control" + SourceExtension "GL_KHR_shader_subgroup_basic" + SourceExtension "GL_KHR_shader_subgroup_vote" + Name 4 "main" + Name 8 "bTemp" + Name 16 "iInput" + Name 33 "bOut" + Decorate 16(iInput) Flat + Decorate 16(iInput) Location 0 + Decorate 33(bOut) Location 0 + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeBool + 7: TypePointer Function 6(bool) + 9: 6(bool) ConstantFalse + 14: TypeInt 32 1 + 15: TypePointer Input 14(int) + 16(iInput): 15(ptr) Variable Input + 18: 14(int) Constant 0 + 20: TypeInt 32 0 + 21: 20(int) Constant 3 + 32: TypePointer Output 14(int) + 33(bOut): 32(ptr) Variable Output + 35: 6(bool) ConstantTrue + 37: 14(int) Constant 1 + 4(main): 2 Function None 3 + 5: Label + 8(bTemp): 7(ptr) Variable Function + Store 8(bTemp) 9 + 10: 6(bool) Load 8(bTemp) + 11: 6(bool) LogicalNot 10 + SelectionMerge 13 None + BranchConditional 11 12 13 + 12: Label + 17: 14(int) Load 16(iInput) + 19: 6(bool) SGreaterThan 17 18 + 22: 6(bool) GroupNonUniformQuadAllKHR 19 + Branch 13 + 13: Label + 23: 6(bool) Phi 10 5 22 12 + Store 8(bTemp) 23 + 24: 6(bool) Load 8(bTemp) + 25: 6(bool) LogicalNot 24 + SelectionMerge 27 None + BranchConditional 25 26 27 + 26: Label + 28: 14(int) Load 16(iInput) + 29: 6(bool) SGreaterThan 28 18 + 30: 6(bool) GroupNonUniformQuadAnyKHR 29 + Branch 27 + 27: Label + 31: 6(bool) Phi 24 13 30 26 + Store 8(bTemp) 31 + 34: 6(bool) Load 8(bTemp) + 36: 6(bool) LogicalEqual 34 35 + 38: 14(int) Select 36 37 18 + Store 33(bOut) 38 + Return + FunctionEnd \ No newline at end of file diff --git a/Test/spv.1.6.quad.frag b/Test/spv.1.6.quad.frag new file mode 100644 index 000000000..24f72de9f --- /dev/null +++ b/Test/spv.1.6.quad.frag @@ -0,0 +1,21 @@ +#version 460 core +#extension GL_KHR_shader_subgroup_basic: require +#extension GL_EXT_shader_quad_control: require +#extension GL_KHR_shader_subgroup_vote: require + +layout (full_quads) in; +layout (quad_derivatives) in; + +flat in int iInput; + +out int bOut; + + +void main(){ + bool bTemp = false; + + // EXT_shader_quad_control required begin + bTemp = bTemp || subgroupQuadAll(iInput > 0); // GL_KHR_shader_subgroup_vote + bTemp = bTemp || subgroupQuadAny(iInput > 0); // GL_KHR_shader_subgroup_vote + bOut = bTemp == true ? 1 : 0; +} \ No newline at end of file diff --git a/glslang/Include/Types.h b/glslang/Include/Types.h index 1fb59e5bf..f938f1185 100644 --- a/glslang/Include/Types.h +++ b/glslang/Include/Types.h @@ -852,6 +852,8 @@ public: // -2048 as the default value indicating layoutSecondaryViewportRelative is not set layoutSecondaryViewportRelativeOffset = -2048; layoutShaderRecord = false; + layoutFullQuads = false; + layoutQuadDeriv = false; layoutHitObjectShaderRecordNV = false; layoutBindlessSampler = false; layoutBindlessImage = false; @@ -948,6 +950,8 @@ public: bool layoutViewportRelative; int layoutSecondaryViewportRelativeOffset; bool layoutShaderRecord; + bool layoutFullQuads; + bool layoutQuadDeriv; bool layoutHitObjectShaderRecordNV; // GL_EXT_spirv_intrinsics @@ -1055,6 +1059,8 @@ public: TLayoutFormat getFormat() const { return layoutFormat; } bool isPushConstant() const { return layoutPushConstant; } bool isShaderRecord() const { return layoutShaderRecord; } + bool isFullQuads() const { return layoutFullQuads; } + bool isQuadDeriv() const { return layoutQuadDeriv; } bool hasHitObjectShaderRecordNV() const { return layoutHitObjectShaderRecordNV; } bool hasBufferReference() const { return layoutBufferReference; } bool hasBufferReferenceAlign() const @@ -2206,6 +2212,10 @@ public: if (qualifier.layoutShaderRecord) appendStr(" shaderRecordNV"); + if (qualifier.layoutFullQuads) + appendStr(" full_quads"); + if (qualifier.layoutQuadDeriv) + appendStr(" quad_derivatives"); if (qualifier.layoutHitObjectShaderRecordNV) appendStr(" hitobjectshaderrecordnv"); diff --git a/glslang/Include/intermediate.h b/glslang/Include/intermediate.h index b0e154e92..5308bca78 100644 --- a/glslang/Include/intermediate.h +++ b/glslang/Include/intermediate.h @@ -538,6 +538,8 @@ enum TOperator { EOpSubgroupQuadSwapHorizontal, EOpSubgroupQuadSwapVertical, EOpSubgroupQuadSwapDiagonal, + EOpSubgroupQuadAll, + EOpSubgroupQuadAny, EOpSubgroupPartition, EOpSubgroupPartitionedAdd, diff --git a/glslang/MachineIndependent/Initialize.cpp b/glslang/MachineIndependent/Initialize.cpp index dddb5957f..44551bcb4 100755 --- a/glslang/MachineIndependent/Initialize.cpp +++ b/glslang/MachineIndependent/Initialize.cpp @@ -2227,6 +2227,15 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV ); } + // GL_EXT_shader_quad_control + if ((profile == EEsProfile && version >= 310) || + (profile != EEsProfile && version >= 140)) { + commonBuiltins.append( + "bool subgroupQuadAll(bool);\n" + "bool subgroupQuadAny(bool);\n" + ); + } + if (profile != EEsProfile && version >= 460) { commonBuiltins.append( "bool anyInvocation(bool);" @@ -8779,6 +8788,13 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion symbolTable.setVariableExtensions("gl_ShadingRateFlag4HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate); } + // GL_EXT_shader_quad_control + if ((profile != EEsProfile && version >= 140) || + (profile == EEsProfile && version >= 310)) { + symbolTable.setFunctionExtensions("subgroupQuadAll", 1, &E_GL_KHR_shader_subgroup_vote); + symbolTable.setFunctionExtensions("subgroupQuadAny", 1, &E_GL_KHR_shader_subgroup_vote); + } + // GL_EXT_shader_tile_image symbolTable.setFunctionExtensions("stencilAttachmentReadEXT", 1, &E_GL_EXT_shader_tile_image); symbolTable.setFunctionExtensions("depthAttachmentReadEXT", 1, &E_GL_EXT_shader_tile_image); @@ -9977,6 +9993,13 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion symbolTable.relateToOperator("shadow2DProjEXT", EOpTextureProj); } + // GL_EXT_shader_quad_control + if ((profile == EEsProfile && version >= 310) || + (profile != EEsProfile && version >= 140)) { + symbolTable.relateToOperator("subgroupQuadAll", EOpSubgroupQuadAll); + symbolTable.relateToOperator("subgroupQuadAny", EOpSubgroupQuadAny); + } + if ((profile == EEsProfile && version >= 310) || (profile != EEsProfile && version >= 140)) { symbolTable.relateToOperator("textureWeightedQCOM", EOpImageSampleWeightedQCOM); diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index f84dc9bec..98148100a 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -1351,6 +1351,10 @@ TIntermTyped* TParseContext::handleFunctionCall(const TSourceLoc& loc, TFunction // - a user function. // Error check for a function requiring specific extensions present. + if (builtIn && + (fnCandidate->getBuiltInOp() == EOpSubgroupQuadAll || fnCandidate->getBuiltInOp() == EOpSubgroupQuadAny)) + requireExtensions(loc, 1, &E_GL_EXT_shader_quad_control, fnCandidate->getName().c_str()); + if (builtIn && fnCandidate->getNumExtensions()) requireExtensions(loc, fnCandidate->getNumExtensions(), fnCandidate->getExtensions(), fnCandidate->getName().c_str()); @@ -3986,6 +3990,18 @@ void TParseContext::globalQualifierFixCheck(const TSourceLoc& loc, TQualifier& q // Storage qualifier isn't ready for memberQualifierCheck, we should skip invariantCheck for it. if (!isMemberCheck || structNestingLevel > 0) invariantCheck(loc, qualifier); + + if (qualifier.isFullQuads()) { + if (qualifier.storage != EvqVaryingIn) + error(loc, "can only apply to input layout", "full_quads ", ""); + intermediate.setReqFullQuadsMode(); + } + + if (qualifier.isQuadDeriv()) { + if (qualifier.storage != EvqVaryingIn) + error(loc, "can only apply to input layout", "quad_derivatives", ""); + intermediate.setQuadDerivMode(); + } } // @@ -5859,6 +5875,15 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi publicType.shaderQualifiers.layoutOverrideCoverage = true; return; } + if (id == "full_quads") + { + const char* feature = "full_quads qualifier"; + requireProfile(loc, ECompatibilityProfile | ECoreProfile | EEsProfile, feature); + profileRequires(loc, ECoreProfile | ECompatibilityProfile, 140, E_GL_EXT_shader_quad_control, feature); + profileRequires(loc, EEsProfile, 310, E_GL_EXT_shader_quad_control, feature); + publicType.qualifier.layoutFullQuads = true; + return; + } } if (language == EShLangVertex || language == EShLangTessControl || @@ -5908,6 +5933,16 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi return; } + if (id == "quad_derivatives") + { + const char* feature = "quad_derivatives qualifier"; + requireProfile(loc, ECompatibilityProfile | ECoreProfile | EEsProfile, feature); + profileRequires(loc, ECoreProfile | ECompatibilityProfile, 140, E_GL_EXT_shader_quad_control, feature); + profileRequires(loc, EEsProfile, 310, E_GL_EXT_shader_quad_control, feature); + publicType.qualifier.layoutQuadDeriv = true; + return; + } + error(loc, "unrecognized layout identifier, or qualifier requires assignment (e.g., binding = 4)", id.c_str(), ""); } @@ -6336,6 +6371,10 @@ void TParseContext::mergeObjectLayoutQualifiers(TQualifier& dst, const TQualifie dst.layoutSecondaryViewportRelativeOffset = src.layoutSecondaryViewportRelativeOffset; if (src.layoutShaderRecord) dst.layoutShaderRecord = true; + if (src.layoutFullQuads) + dst.layoutFullQuads = true; + if (src.layoutQuadDeriv) + dst.layoutQuadDeriv = true; if (src.layoutBindlessSampler) dst.layoutBindlessSampler = true; if (src.layoutBindlessImage) diff --git a/glslang/MachineIndependent/Versions.cpp b/glslang/MachineIndependent/Versions.cpp index 15d8dc69d..b550ca2b0 100644 --- a/glslang/MachineIndependent/Versions.cpp +++ b/glslang/MachineIndependent/Versions.cpp @@ -357,6 +357,7 @@ void TParseVersions::initializeExtensionBehavior() extensionBehavior[E_GL_EXT_spirv_intrinsics] = EBhDisable; extensionBehavior[E_GL_EXT_mesh_shader] = EBhDisable; extensionBehavior[E_GL_EXT_opacity_micromap] = EBhDisable; + extensionBehavior[E_GL_EXT_shader_quad_control] = EBhDisable; extensionBehavior[E_GL_EXT_ray_tracing_position_fetch] = EBhDisable; extensionBehavior[E_GL_EXT_shader_tile_image] = EBhDisable; extensionBehavior[E_GL_EXT_texture_shadow_lod] = EBhDisable; @@ -584,6 +585,7 @@ void TParseVersions::getPreamble(std::string& preamble) "#define GL_EXT_shader_atomic_float2 1\n" "#define GL_EXT_fragment_shader_barycentric 1\n" + "#define GL_EXT_shader_quad_control 1\n" "#define GL_EXT_texture_array 1\n" ; diff --git a/glslang/MachineIndependent/Versions.h b/glslang/MachineIndependent/Versions.h index 504e3bc98..771672577 100755 --- a/glslang/MachineIndependent/Versions.h +++ b/glslang/MachineIndependent/Versions.h @@ -215,6 +215,7 @@ const char* const E_GL_EXT_spirv_intrinsics = "GL_EXT_spirv_intr const char* const E_GL_EXT_fragment_shader_barycentric = "GL_EXT_fragment_shader_barycentric"; const char* const E_GL_EXT_mesh_shader = "GL_EXT_mesh_shader"; const char* const E_GL_EXT_opacity_micromap = "GL_EXT_opacity_micromap"; +const char* const E_GL_EXT_shader_quad_control = "GL_EXT_shader_quad_control"; const char* const E_GL_EXT_draw_instanced = "GL_EXT_draw_instanced"; const char* const E_GL_EXT_texture_array = "GL_EXT_texture_array"; const char* const E_GL_EXT_maximal_reconvergence = "GL_EXT_maximal_reconvergence"; diff --git a/glslang/MachineIndependent/intermOut.cpp b/glslang/MachineIndependent/intermOut.cpp index 8dcdc6792..19691487a 100644 --- a/glslang/MachineIndependent/intermOut.cpp +++ b/glslang/MachineIndependent/intermOut.cpp @@ -597,6 +597,8 @@ bool TOutputTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node) case EOpSubgroupQuadSwapHorizontal: out.debug << "subgroupQuadSwapHorizontal"; break; case EOpSubgroupQuadSwapVertical: out.debug << "subgroupQuadSwapVertical"; break; case EOpSubgroupQuadSwapDiagonal: out.debug << "subgroupQuadSwapDiagonal"; break; + case EOpSubgroupQuadAll: out.debug << "subgroupQuadAll"; break; + case EOpSubgroupQuadAny: out.debug << "subgroupQuadAny"; break; case EOpSubgroupPartition: out.debug << "subgroupPartitionNV"; break; case EOpSubgroupPartitionedAdd: out.debug << "subgroupPartitionedAddNV"; break; @@ -1032,6 +1034,8 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node case EOpSubgroupQuadSwapHorizontal: out.debug << "subgroupQuadSwapHorizontal"; break; case EOpSubgroupQuadSwapVertical: out.debug << "subgroupQuadSwapVertical"; break; case EOpSubgroupQuadSwapDiagonal: out.debug << "subgroupQuadSwapDiagonal"; break; + case EOpSubgroupQuadAll: out.debug << "subgroupQuadAll"; break; + case EOpSubgroupQuadAny: out.debug << "subgroupQuadAny"; break; case EOpSubgroupPartition: out.debug << "subgroupPartitionNV"; break; case EOpSubgroupPartitionedAdd: out.debug << "subgroupPartitionedAddNV"; break; diff --git a/glslang/MachineIndependent/localintermediate.h b/glslang/MachineIndependent/localintermediate.h index 3cd958057..f723d9436 100644 --- a/glslang/MachineIndependent/localintermediate.h +++ b/glslang/MachineIndependent/localintermediate.h @@ -349,7 +349,8 @@ public: usePhysicalStorageBuffer(false), spirvRequirement(nullptr), spirvExecutionMode(nullptr), - uniformLocationBase(0) + uniformLocationBase(0), + quadDerivMode(false), reqFullQuadsMode(false) { localSize[0] = 1; localSize[1] = 1; @@ -858,6 +859,10 @@ public: void setXfbMode() { xfbMode = true; } bool getXfbMode() const { return xfbMode; } + void setQuadDerivMode(bool mode = true) { quadDerivMode = mode; } + bool getQuadDerivMode() const { return quadDerivMode; } + void setReqFullQuadsMode(bool mode = true) { reqFullQuadsMode = mode; } + bool getReqFullQuadsMode() const { return reqFullQuadsMode; } void setMultiStream() { multiStream = true; } bool isMultiStream() const { return multiStream; } bool setOutputPrimitive(TLayoutGeometry p) @@ -1197,6 +1202,8 @@ protected: bool hlslFunctionality1; int blendEquations; // an 'or'ing of masks of shifts of TBlendEquationShift bool xfbMode; + bool quadDerivMode; + bool reqFullQuadsMode; std::vector xfbBuffers; // all the data we need to track per xfb buffer bool multiStream; bool layoutOverrideCoverage; diff --git a/gtests/Spv.FromFile.cpp b/gtests/Spv.FromFile.cpp index c16bab61b..13e35b7ac 100644 --- a/gtests/Spv.FromFile.cpp +++ b/gtests/Spv.FromFile.cpp @@ -735,6 +735,7 @@ INSTANTIATE_TEST_SUITE_P( "spv.1.6.specConstant.comp", "spv.1.6.samplerBuffer.frag", "spv.1.6.separate.frag", + "spv.1.6.quad.frag", })), FileNameAsCustomTestSuffix );