diff --git a/glslang/MachineIndependent/Initialize.cpp b/glslang/MachineIndependent/Initialize.cpp index 5a9e5003de..371b724401 100644 --- a/glslang/MachineIndependent/Initialize.cpp +++ b/glslang/MachineIndependent/Initialize.cpp @@ -478,10 +478,9 @@ void TBuiltIns::relateTabledBuiltins(int /* version */, EProfile /* profile */, RelateTabledBuiltins(CustomFunctions, symbolTable); } -inline bool IncludeLegacy(int version, EProfile profile, const SpvVersion& spvVersion) +inline bool IncludeLegacy(int version, EProfile profile, const SpvVersion& spvVersion, bool compatibilityIncluded) { - return profile != EEsProfile && (version <= 130 || (spvVersion.spv == 0 && version == 140 && ARBCompatibility) || - profile == ECompatibilityProfile); + return profile != EEsProfile && (version <= 130 || (spvVersion.spv == 0 && compatibilityIncluded) || profile == ECompatibilityProfile); } // Construct TBuiltInParseables base class. This can be used for language-common constructs. @@ -546,6 +545,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV version = 310; profile = EEsProfile; #endif + compatibilityIncluded = (profile == ECompatibilityProfile) && ARBCompatibility; addTabledBuiltins(version, profile, spvVersion); //============================================================================ @@ -1719,7 +1719,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV // (Per-stage functions below.) // if ((profile == EEsProfile && version == 100) || - profile == ECompatibilityProfile || + IncludeLegacy(version, profile, spvVersion, compatibilityIncluded) || (profile == ECoreProfile && version < 420) || profile == ENoProfile) { if (spvVersion.spv == 0) { @@ -4174,7 +4174,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV // // Geometric Functions. // - if (spvVersion.vulkan == 0 && IncludeLegacy(version, profile, spvVersion)) + if (spvVersion.vulkan == 0 && IncludeLegacy(version, profile, spvVersion, compatibilityIncluded)) stageBuiltins[EShLangVertex].append("vec4 ftransform();"); // @@ -4678,7 +4678,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV } #if !defined(GLSLANG_WEB) - if (spvVersion.spv == 0 && IncludeLegacy(version, profile, spvVersion)) { + if (spvVersion.spv == 0 && IncludeLegacy(version, profile, spvVersion, compatibilityIncluded)) { // // Matrix state. p. 31, 32, 37, 39, 40. // @@ -4966,7 +4966,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV "attribute vec4 gl_MultiTexCoord7;" "attribute float gl_FogCoord;" "\n"); - } else if (IncludeLegacy(version, profile, spvVersion)) { + } else if (IncludeLegacy(version, profile, spvVersion, compatibilityIncluded)) { stageBuiltins[EShLangVertex].append( "in vec4 gl_Color;" "in vec4 gl_SecondaryColor;" @@ -4995,7 +4995,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV "varying vec4 gl_TexCoord[];" "varying float gl_FogFragCoord;" "\n"); - } else if (IncludeLegacy(version, profile, spvVersion)) { + } else if (IncludeLegacy(version, profile, spvVersion, compatibilityIncluded)) { stageBuiltins[EShLangVertex].append( " vec4 gl_ClipVertex;" // needs qualifier fixed later "out vec4 gl_FrontColor;" @@ -5023,7 +5023,8 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV "float gl_PointSize;" // needs qualifier fixed later "float gl_ClipDistance[];" ); - if (IncludeLegacy(version, profile, spvVersion)) + if (IncludeLegacy(version, profile, spvVersion, compatibilityIncluded) || + (profile != EEsProfile && version >= 110)) // GL_ARB_geometry_shader4 stageBuiltins[EShLangVertex].append( "vec4 gl_ClipVertex;" // needs qualifier fixed later "vec4 gl_FrontColor;" @@ -5157,39 +5158,92 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV // //============================================================================ - if (profile == ECoreProfile || profile == ECompatibilityProfile) { - stageBuiltins[EShLangGeometry].append( - "in gl_PerVertex {" - "vec4 gl_Position;" - "float gl_PointSize;" - "float gl_ClipDistance[];" - ); - if (profile == ECompatibilityProfile) + if (profile == ECoreProfile || + profile == ECompatibilityProfile || + (profile != EEsProfile && version >= 110)) { + if (!(profile != EEsProfile && version < 140)) { // "in block" from 140 stageBuiltins[EShLangGeometry].append( - "vec4 gl_ClipVertex;" - "vec4 gl_FrontColor;" - "vec4 gl_BackColor;" - "vec4 gl_FrontSecondaryColor;" - "vec4 gl_BackSecondaryColor;" - "vec4 gl_TexCoord[];" - "float gl_FogFragCoord;" - ); - if (version >= 450) + "in gl_PerVertex {" + "vec4 gl_Position;" + "float gl_PointSize;" + "float gl_ClipDistance[];" + ); + if (version >= 130) + stageBuiltins[EShLangGeometry].append( + "float gl_CullDistance[];" // GL_ARB_cull_distance + ); + if (IncludeLegacy(version, profile, spvVersion, compatibilityIncluded) || + (profile != EEsProfile && version >= 110)) // GL_ARB_geometry_shader4 + stageBuiltins[EShLangGeometry].append( + "vec4 gl_ClipVertex;" + "vec4 gl_FrontColor;" + "vec4 gl_BackColor;" + "vec4 gl_FrontSecondaryColor;" + "vec4 gl_BackSecondaryColor;" + "vec4 gl_TexCoord[];" + "float gl_FogFragCoord;" + ); + if (version >= 450) + stageBuiltins[EShLangGeometry].append( + "vec4 gl_SecondaryPositionNV;" // GL_NV_stereo_view_rendering + "vec4 gl_PositionPerViewNV[];" // GL_NVX_multiview_per_view_attributes + ); stageBuiltins[EShLangGeometry].append( - "float gl_CullDistance[];" - "vec4 gl_SecondaryPositionNV;" // GL_NV_stereo_view_rendering - "vec4 gl_PositionPerViewNV[];" // GL_NVX_multiview_per_view_attributes + "} gl_in[];" + ); + } + + if (version >= 110) + { + stageBuiltins[EShLangGeometry].append( + "const int gl_VerticesIn = 1;" // Value set later according to input primitive setting. + ); + + if (version < 130) { + stageBuiltins[EShLangGeometry].append( + "varying in vec4 gl_PositionIn[];" + "varying in vec4 gl_FrontColorIn[];" + "varying in vec4 gl_BackColorIn[];" + "varying in vec4 gl_FrontSecondaryColorIn[];" + "varying in vec4 gl_BackSecondaryColorIn[];" + "varying in vec4 gl_FogFragCoordIn[];" + "varying in vec4 gl_ClipVertexIn[];" + "varying in vec4 gl_PointSizeIn[];" + "varying in vec4 gl_TexCoordIn[gl_VerticesIn][];" ); - stageBuiltins[EShLangGeometry].append( - "} gl_in[];" + } + else { + stageBuiltins[EShLangGeometry].append( + "in vec4 gl_PositionIn[];" + "in vec4 gl_FrontColorIn[];" + "in vec4 gl_BackColorIn[];" + "in vec4 gl_FrontSecondaryColorIn[];" + "in vec4 gl_BackSecondaryColorIn[];" + "in vec4 gl_FogFragCoordIn[];" + "in vec4 gl_ClipVertexIn[];" + "in vec4 gl_PointSizeIn[];" + "in vec4 gl_TexCoordIn[gl_VerticesIn][];" + ); + } + } + stageBuiltins[EShLangGeometry].append( "in int gl_PrimitiveIDIn;" + ); + + if (!(profile != EEsProfile && version < 140)) { // "out block" from 140 + stageBuiltins[EShLangGeometry].append( "out gl_PerVertex {" "vec4 gl_Position;" "float gl_PointSize;" "float gl_ClipDistance[];" "\n"); - if (profile == ECompatibilityProfile && version >= 400) + if (version >= 130) + stageBuiltins[EShLangGeometry].append( + "float gl_CullDistance[];" // GL_ARB_cull_distance + ); + if (IncludeLegacy(version, profile, spvVersion, compatibilityIncluded) || + (profile != EEsProfile && version >= 140)) stageBuiltins[EShLangGeometry].append( "vec4 gl_ClipVertex;" "vec4 gl_FrontColor;" @@ -5199,13 +5253,36 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV "vec4 gl_TexCoord[];" "float gl_FogFragCoord;" ); - if (version >= 450) - stageBuiltins[EShLangGeometry].append( - "float gl_CullDistance[];" - ); stageBuiltins[EShLangGeometry].append( - "};" - + "};"); + } + else { + if (version < 130) { + stageBuiltins[EShLangGeometry].append( + "varying out vec4 gl_Position;" + "varying out vec4 gl_PointSize;" + "varying out vec4 gl_ClipVertex;" + "varying out vec4 gl_FrontColor;" + "varying out vec4 gl_BackColor;" + "varying out vec4 gl_FrontSecondaryColor;" + "varying out vec4 gl_BackSecondaryColor;" + "varying out vec4 gl_TexCoord[];" + "varying out float gl_FogFragCoord;"); + } + else { + stageBuiltins[EShLangGeometry].append( + "out vec4 gl_Position;" + "out vec4 gl_PointSize;" + "out vec4 gl_ClipVertex;" + "out vec4 gl_FrontColor;" + "out vec4 gl_BackColor;" + "out vec4 gl_FrontSecondaryColor;" + "out vec4 gl_BackSecondaryColor;" + "out vec4 gl_TexCoord[];" + "out float gl_FogFragCoord;"); + } + } + stageBuiltins[EShLangGeometry].append( "out int gl_PrimitiveID;" "out int gl_Layer;"); @@ -5214,12 +5291,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV "out int gl_ViewportIndex;" ); - if (profile == ECompatibilityProfile && version < 400) - stageBuiltins[EShLangGeometry].append( - "out vec4 gl_ClipVertex;" - ); - - if (version >= 400) + if (version >= 150) stageBuiltins[EShLangGeometry].append( "in int gl_InvocationID;" ); @@ -5293,7 +5365,8 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV "float gl_PointSize;" "float gl_ClipDistance[];" ); - if (profile == ECompatibilityProfile) + if (IncludeLegacy(version, profile, spvVersion, compatibilityIncluded)|| + (profile != EEsProfile && version >= 140)) // ARB_geometry_shader4 stageBuiltins[EShLangTessControl].append( "vec4 gl_ClipVertex;" "vec4 gl_FrontColor;" @@ -5391,7 +5464,8 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV "float gl_PointSize;" "float gl_ClipDistance[];" ); - if (version >= 400 && profile == ECompatibilityProfile) + if (IncludeLegacy(version, profile, spvVersion, compatibilityIncluded)|| + (profile != EEsProfile && version >= 140)) // ARB_geometry_shader4 stageBuiltins[EShLangTessEvaluation].append( "vec4 gl_ClipVertex;" "vec4 gl_FrontColor;" @@ -5478,7 +5552,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV stageBuiltins[EShLangFragment].append( "out int gl_FragStencilRefARB;" ); - if (IncludeLegacy(version, profile, spvVersion) || (! ForwardCompatibility && version < 420)) + if (IncludeLegacy(version, profile, spvVersion, compatibilityIncluded) || (! ForwardCompatibility && version < 420)) stageBuiltins[EShLangFragment].append( "vec4 gl_FragColor;" // needs qualifier fixed later ); @@ -5495,7 +5569,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV "in float gl_ClipDistance[];" ); - if (IncludeLegacy(version, profile, spvVersion)) { + if (IncludeLegacy(version, profile, spvVersion, compatibilityIncluded)) { if (version < 150) stageBuiltins[EShLangFragment].append( "in float gl_FogFragCoord;" @@ -7273,7 +7347,7 @@ void TBuiltIns::initialize(const TBuiltInResource &resources, int version, EProf snprintf(builtInConstant, maxSize, "const int gl_MaxFragmentUniformComponents = %d;", resources.maxFragmentUniformComponents); s.append(builtInConstant); - if (spvVersion.spv == 0 && IncludeLegacy(version, profile, spvVersion)) { + if (spvVersion.spv == 0 && IncludeLegacy(version, profile, spvVersion, compatibilityIncluded)) { // // OpenGL'uniform' state. Page numbers are in reference to version // 1.4 of the OpenGL specification. @@ -7400,7 +7474,7 @@ void TBuiltIns::initialize(const TBuiltInResource &resources, int version, EProf "float gl_PointSize;" "float gl_ClipDistance[];" ); - if (profile == ECompatibilityProfile) + if (IncludeLegacy(version, profile, spvVersion, compatibilityIncluded)) s.append( "vec4 gl_ClipVertex;" "vec4 gl_FrontColor;" @@ -7942,6 +8016,35 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion if (version < 410) symbolTable.setVariableExtensions("gl_ViewportIndex", 1, &E_GL_ARB_viewport_array); + // GL_ARB_geometry_shader4 + SpecialQualifier("gl_TexCoordIn", EvqVaryingIn, EbvTexCoord, symbolTable); + SpecialQualifier("gl_PositionIn", EvqVaryingIn, EbvPosition, symbolTable); + SpecialQualifier("gl_FrontColorIn", EvqVaryingIn, EbvFrontColor, symbolTable); + SpecialQualifier("gl_BackColorIn", EvqVaryingIn, EbvBackColor, symbolTable); + SpecialQualifier("gl_FrontSecondaryColorIn",EvqVaryingIn, EbvFrontSecondaryColor, symbolTable); + SpecialQualifier("gl_BackSecondaryColorIn", EvqVaryingIn, EbvBackSecondaryColor, symbolTable); + SpecialQualifier("gl_FogFragCoordIn", EvqVaryingIn, EbvFogFragCoord, symbolTable); + SpecialQualifier("gl_ClipVertexIn", EvqVaryingIn, EbvClipVertex, symbolTable); + SpecialQualifier("gl_PointSizeIn", EvqVaryingIn, EbvPointSize, symbolTable); + BuiltInVariable("gl_TexCoordIn", EbvTexCoord, symbolTable); + BuiltInVariable("gl_PositionIn", EbvPosition, symbolTable); + BuiltInVariable("gl_FrontColorIn", EbvFrontColor, symbolTable); + BuiltInVariable("gl_BackColorIn", EbvBackColor, symbolTable); + BuiltInVariable("gl_FrontSecondaryColorIn", EbvFrontSecondaryColor, symbolTable); + BuiltInVariable("gl_BackSecondaryColorIn", EbvBackSecondaryColor, symbolTable); + BuiltInVariable("gl_FogFragCoordIn", EbvFogFragCoord, symbolTable); + BuiltInVariable("gl_ClipVertexIn", EbvClipVertex, symbolTable); + BuiltInVariable("gl_PointSizeIn", EbvPointSize, symbolTable); + symbolTable.setVariableExtensions("gl_TexCoordIn", Num_ARB_geometry_shader4, ARB_geometry_shader4); + symbolTable.setVariableExtensions("gl_PositionIn", Num_ARB_geometry_shader4, ARB_geometry_shader4); + symbolTable.setVariableExtensions("gl_FrontColorIn", Num_ARB_geometry_shader4, ARB_geometry_shader4); + symbolTable.setVariableExtensions("gl_BackColorIn", Num_ARB_geometry_shader4, ARB_geometry_shader4); + symbolTable.setVariableExtensions("gl_FrontSecondaryColorIn", Num_ARB_geometry_shader4, ARB_geometry_shader4); + symbolTable.setVariableExtensions("gl_BackSecondaryColorIn", Num_ARB_geometry_shader4, ARB_geometry_shader4); + symbolTable.setVariableExtensions("gl_FogFragCoordIn", Num_ARB_geometry_shader4, ARB_geometry_shader4); + symbolTable.setVariableExtensions("gl_ClipVertexIn", Num_ARB_geometry_shader4, ARB_geometry_shader4); + symbolTable.setVariableExtensions("gl_PointSizeIn", Num_ARB_geometry_shader4, ARB_geometry_shader4); + symbolTable.setVariableExtensions("gl_VerticesIn", Num_ARB_geometry_shader4, ARB_geometry_shader4); // Compatibility variables @@ -9438,11 +9541,11 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion symbolTable.relateToOperator("textureFootprintGradNV", EOpImageSampleFootprintGradNV); symbolTable.relateToOperator("textureFootprintGradClampNV", EOpImageSampleFootprintGradClampNV); - if (spvVersion.spv == 0 && IncludeLegacy(version, profile, spvVersion)) + if (spvVersion.spv == 0 && IncludeLegacy(version, profile, spvVersion, compatibilityIncluded)) symbolTable.relateToOperator("ftransform", EOpFtransform); - if (spvVersion.spv == 0 && (IncludeLegacy(version, profile, spvVersion) || - (profile == EEsProfile && version == 100))) { + if (spvVersion.spv == 0 && (IncludeLegacy(version, profile, spvVersion, compatibilityIncluded) || + (profile == EEsProfile && version == 100) || profile != EEsProfile)) { symbolTable.relateToOperator("texture1D", EOpTexture); symbolTable.relateToOperator("texture1DGradARB", EOpTextureGrad); @@ -9834,7 +9937,7 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion switch(language) { case EShLangFragment: // Set up gl_FragData based on current array size. - if (version == 100 || IncludeLegacy(version, profile, spvVersion) || (! ForwardCompatibility && profile != EEsProfile && version < 420)) { + if (version == 100 || IncludeLegacy(version, profile, spvVersion, compatibilityIncluded) || (! ForwardCompatibility && profile != EEsProfile && version < 420)) { TPrecisionQualifier pq = profile == EEsProfile ? EpqMedium : EpqNone; TType fragData(EbtFloat, EvqFragColor, pq, 4); TArraySizes* arraySizes = new TArraySizes; diff --git a/glslang/MachineIndependent/Initialize.h b/glslang/MachineIndependent/Initialize.h index ac8ec33e99..350d0401cf 100644 --- a/glslang/MachineIndependent/Initialize.h +++ b/glslang/MachineIndependent/Initialize.h @@ -105,6 +105,7 @@ class TBuiltIns : public TBuiltInParseables { const char* postfixes[5]; const char* prefixes[EbtNumTypes]; int dimMap[EsdNumDims]; + bool compatibilityIncluded = false; }; } // end namespace glslang diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index 41afbc052a..d9abcefc07 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -456,6 +456,11 @@ TIntermTyped* TParseContext::handleVariable(const TSourceLoc& loc, TSymbol* symb requireExtensions(loc, symbol->getNumExtensions(), symbol->getExtensions(), symbol->getName().c_str()); #ifndef GLSLANG_WEB + if (extensionsTurnedOn(Num_ARB_geometry_shader4, ARB_geometry_shader4) && (*string == TString("gl_VerticesIn")) + && (language == EShLangGeometry)) { + fixBuiltinConstantVerticesIn(); + } + if (symbol && symbol->isReadOnly()) { // All shared things containing an unsized array must be copied up // on first use, so that all future references will share its array structure, @@ -597,6 +602,39 @@ TIntermTyped* TParseContext::handleBracketDereference(const TSourceLoc& loc, TIn } return result; } + + // gl_TexCoordIn[...][...] + if (base->getQualifier().builtIn == EbvTexCoord && + extensionsTurnedOn(Num_ARB_geometry_shader4, ARB_geometry_shader4)) { + int newSize = TQualifier::mapGeometryToSize(intermediate.getInputPrimitive()); + TIntermSymbol* nodeOneDimension = base->getAsSymbolNode(); + TIntermBinary* nodeTwoDimension = base->getAsBinaryNode(); + /* + if (nodeOneDimension && base->getQualifier().storage == EvqVaryingIn && nodeOneDimension->getName() == "gl_TexCoordIn" && + (base->getArraySizes()->getDimSize(0) == UnsizedArraySize || base->getArraySizes()->isImplicitlySized())) { + TArraySizes* sizes = base->getWritableType().getArraySizes(); + sizes->setDimSize(0, std::max(indexValue + 1, newSize)); + sizes->setImplicitlySized(true); + base->getWritableType().setImplicitlySized(true); + } + + if (nodeTwoDimension) { + TType& leftType = nodeTwoDimension->getLeft()->getWritableType(); + if (nodeTwoDimension->getLeft()->getAsSymbolNode()->getName() == "gl_TexCoordIn" && + leftType.getQualifier().storage == EvqVaryingIn && + (leftType.getArraySizes()->getDimSize(1) == UnsizedArraySize || + leftType.getArraySizes()->isImplicitlySized())) { + TArraySizes& arraySizes = *leftType.getArraySizes(); + assert(arraySizes.getNumDims() == 2); + arraySizes.setDimSize(1, std::max(arraySizes.getDimSize(1), indexValue + 1)); + arraySizes.setImplicitlySized(true); + // second dimension. + base->getWritableType().changeOuterArraySize(arraySizes.getDimSize(1)); + base->getWritableType().setImplicitlySized(true); + } + }*/ + } + if (base->getAsSymbolNode() && isIoResizeArray(base->getType())) handleIoResizeArrayAccess(loc, base); #endif @@ -627,8 +665,11 @@ TIntermTyped* TParseContext::handleBracketDereference(const TSourceLoc& loc, TIn if (base->getType().isUnsizedArray()) { // we have a variable index into an unsized array, which is okay, // depending on the situation - if (base->getAsSymbolNode() && isIoResizeArray(base->getType())) - error(loc, "", "[", "array must be sized by a redeclaration or layout qualifier before being indexed with a variable"); + if (base->getAsSymbolNode() && isIoResizeArray(base->getType())) { + bool isGsInput = base->getType().getQualifier().isArrayedIo(EShLangGeometry); + if (!isGsInput) + error(loc, "", "[", "array must be sized by a redeclaration or layout qualifier before being indexed with a variable"); + } else { // it is okay for a run-time sized array checkRuntimeSizable(loc, *base); @@ -651,7 +692,7 @@ TIntermTyped* TParseContext::handleBracketDereference(const TSourceLoc& loc, TIn const char* explanation = "variable indexing sampler array"; requireProfile(base->getLoc(), EEsProfile | ECoreProfile | ECompatibilityProfile, explanation); profileRequires(base->getLoc(), EEsProfile, 320, Num_AEP_gpu_shader5, AEP_gpu_shader5, explanation); - profileRequires(base->getLoc(), ECoreProfile | ECompatibilityProfile, 400, nullptr, explanation); + profileRequires(base->getLoc(), ECoreProfile | ECompatibilityProfile, 400, E_GL_GL_ARB_arrays_of_arrays, explanation); } result = intermediate.addIndex(EOpIndexIndirect, base, index, loc); @@ -780,6 +821,24 @@ void TParseContext::handleIoResizeArrayAccess(const TSourceLoc& /*loc*/, TInterm } } +// +// Fix constant value of gl_VerticesIn during link-time. Depending on input primitive type from API or layout declaration. +// +void TParseContext::fixBuiltinConstantVerticesIn() +{ + // gl_VerticesIn + if (intermediate.getInputPrimitive() != ElpNone) { + bool builtIn; + TSymbol* symbol = symbolTable.find("gl_VerticesIn", &builtIn); + if (symbol != nullptr && builtIn) { + makeEditable(symbol); + symbolTable.amendSymbolIdLevel(*symbol); + TConstUnionArray& verticesInConstArr = symbol->getAsVariable()->getWritableConstArray(); + verticesInConstArr[0].setIConst(TQualifier::mapGeometryToSize(intermediate.getInputPrimitive())); + } + } +} + // If there has been an input primitive declaration (geometry shader) or an output // number of vertices declaration(tessellation shader), make sure all input array types // match it in size. Types come either from nodes in the AST or symbols in the @@ -865,8 +924,14 @@ void TParseContext::checkIoArrayConsistency(const TSourceLoc& loc, int requiredS if (type.isUnsizedArray()) type.changeOuterArraySize(requiredSize); else if (type.getOuterArraySize() != requiredSize) { - if (language == EShLangGeometry) - error(loc, "inconsistent input primitive for array size of", feature, name.c_str()); + if (language == EShLangGeometry) { + if (intermediate.getInputPrimitiveSetOutside() == true && type.getQualifier().storage == EvqVaryingIn) { + // Resizing io arrays influenced by primitive layout set from API. + type.changeOuterArraySize(requiredSize); + } + else + error(loc, "inconsistent input primitive for array size of", feature, name.c_str()); + } else if (language == EShLangTessControl) error(loc, "inconsistent output number of vertices for array size of", feature, name.c_str()); else if (language == EShLangFragment) { @@ -3993,6 +4058,14 @@ void TParseContext::mergeQualifiers(const TSourceLoc& loc, TQualifier& dst, cons else if ((dst.storage == EvqIn && src.storage == EvqConst) || (dst.storage == EvqConst && src.storage == EvqIn)) dst.storage = EvqConstReadOnly; + else if (version >= 110 && language == EShLangGeometry && + ((dst.storage == EvqVaryingIn && src.storage == EvqIn) || + (src.storage == EvqVaryingIn && dst.storage == EvqIn))) + dst.storage = EvqIn; + else if (version >= 110 && language == EShLangGeometry && + ((dst.storage == EvqVaryingIn && src.storage == EvqOut) || + (src.storage == EvqVaryingIn && dst.storage == EvqOut))) + dst.storage = EvqOut; else if (src.storage != EvqTemporary && src.storage != EvqGlobal) error(loc, "too many storage qualifiers", GetStorageQualifierString(src.storage), ""); @@ -4396,7 +4469,7 @@ void TParseContext::arrayOfArrayVersionCheck(const TSourceLoc& loc, const TArray requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, feature); profileRequires(loc, EEsProfile, 310, nullptr, feature); - profileRequires(loc, ECoreProfile | ECompatibilityProfile, 430, nullptr, feature); + profileRequires(loc, ECoreProfile | ECompatibilityProfile, 430, E_GL_GL_ARB_arrays_of_arrays, feature); } // @@ -4613,12 +4686,13 @@ void TParseContext::nonInitConstCheck(const TSourceLoc& loc, TString& identifier // Returns a redeclared and type-modified variable if a redeclarated occurred. // TSymbol* TParseContext::redeclareBuiltinVariable(const TSourceLoc& loc, const TString& identifier, - const TQualifier& qualifier, const TShaderQualifiers& publicType) + const TType& type, const TShaderQualifiers& publicType) { #ifndef GLSLANG_WEB if (! builtInName(identifier) || symbolTable.atBuiltInLevel() || ! symbolTable.atGlobalLevel()) return nullptr; + const TQualifier& qualifier = type.getQualifier(); bool nonEsRedecls = (!isEsProfile() && (version >= 130 || identifier == "gl_TexCoord")); bool esRedecls = (isEsProfile() && (version >= 320 || extensionsTurnedOn(Num_AEP_shader_io_blocks, AEP_shader_io_blocks))); @@ -4635,9 +4709,19 @@ TSymbol* TParseContext::redeclareBuiltinVariable(const TSourceLoc& loc, const TS ssoPre150 = true; } + // Special case when using GL_ARB_geometry_shader4 + bool gsPre150 = false; // means the only reason this variable is redeclared is due to this combination + if (!isEsProfile() && version >= 110 && extensionsTurnedOn(Num_ARB_geometry_shader4, ARB_geometry_shader4)) { + if (identifier == "gl_PositionIn" || identifier == "gl_FrontColorIn" || identifier == "gl_BackColorIn" || + identifier == "gl_PointSizeIn" || identifier == "gl_ClipVertexIn" || identifier == "gl_TexCoordIn" || + identifier == "gl_FrontSecondaryColorIn" || identifier == "gl_BackSecondaryColorIn" || + identifier == "gl_FogFragCoordIn") + gsPre150 = true; + } + // Potentially redeclaring a built-in variable... - if (ssoPre150 || + if (ssoPre150 || gsPre150 || (identifier == "gl_FragDepth" && ((nonEsRedecls && version >= 420) || esRedecls)) || (identifier == "gl_FragCoord" && ((nonEsRedecls && version >= 140) || esRedecls)) || identifier == "gl_ClipDistance" || @@ -4690,7 +4774,27 @@ TSymbol* TParseContext::redeclareBuiltinVariable(const TSourceLoc& loc, const TS error(loc, "cannot change storage, memory, or auxiliary qualification of", "redeclaration", symbol->getName().c_str()); if (! qualifier.smooth) error(loc, "cannot change interpolation qualification of", "redeclaration", symbol->getName().c_str()); - } else if (identifier == "gl_FrontColor" || + } + else if (gsPre150) { + if (intermediate.inIoAccessed(identifier)) + error(loc, "cannot redeclare after use", identifier.c_str(), ""); + + if (identifier == "gl_TexCoordIn") { + if (type.getArraySizes()->getNumDims() != 2 && type.getArraySizes()->getDimSize(1) <= 0) + error(loc, "cannot redeclared without 2-nd dimension's size or a size less than zero", identifier.c_str(), ""); + if (type.getArraySizes()->getDimSize(1) > resources.maxTextureCoords) + error(loc, "cannot redeclared with size larger than gl_MaxTexCoord on second dimension", identifier.c_str(), ""); + + symbol->getWritableType().getArraySizes()->setDimSize(0, type.getArraySizes()->getDimSize(0)); + symbol->getWritableType().getArraySizes()->setDimSize(1, type.getArraySizes()->getDimSize(1)); + //symbol->getWritableType().setImplicitlySized(false); + } + else { + symbol->getWritableType().changeOuterArraySize(type.getArraySizes()->getOuterSize()); + //symbol->getWritableType().setImplicitlySized(false); + } + } + else if (identifier == "gl_FrontColor" || identifier == "gl_BackColor" || identifier == "gl_FrontSecondaryColor" || identifier == "gl_BackSecondaryColor" || @@ -7248,7 +7352,9 @@ TIntermNode* TParseContext::declareVariable(const TSourceLoc& loc, TString& iden TType type(publicType); type.transferArraySizes(arraySizes); type.copyArrayInnerSizes(publicType.arraySizes); - arrayOfArrayVersionCheck(loc, type.getArraySizes()); + // Initialization (declaring built-ins) happens before scanning or setting extension behaviors. + if (!builtInName(identifier)) + arrayOfArrayVersionCheck(loc, type.getArraySizes()); if (initializer) { if (type.getBasicType() == EbtRayQuery) { @@ -7340,7 +7446,7 @@ TIntermNode* TParseContext::declareVariable(const TSourceLoc& loc, TString& iden 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); + TSymbol* symbol = redeclareBuiltinVariable(loc, identifier, type, publicType.shaderQualifiers); if (symbol == nullptr) reservedErrorCheck(loc, identifier); @@ -9018,6 +9124,8 @@ void TParseContext::updateStandaloneQualifierDefaults(const TSourceLoc& loc, con error(loc, "can only apply to 'out'", id, ""); if (! intermediate.setVertices(publicType.shaderQualifiers.vertices)) error(loc, "cannot change previously set layout value", id, ""); + else + intermediate.setMaxGSVerticesSetOutside(false); if (language == EShLangTessControl) checkIoArraysConsistency(loc); @@ -9052,8 +9160,14 @@ void TParseContext::updateStandaloneQualifierDefaults(const TSourceLoc& loc, con break; } if (intermediate.setInputPrimitive(publicType.shaderQualifiers.geometry)) { - if (language == EShLangGeometry) + if (language == EShLangGeometry) { + // ARB_geometry_shader4 : gl_VerticesIn + if (extensionsTurnedOn(Num_ARB_geometry_shader4, ARB_geometry_shader4)) + fixBuiltinConstantVerticesIn(); + checkIoArraysConsistency(loc); + intermediate.setInputPrimitiveSetOutside(false); + } } else error(loc, "cannot change previously set input primitive", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), ""); break; @@ -9072,8 +9186,12 @@ void TParseContext::updateStandaloneQualifierDefaults(const TSourceLoc& loc, con case ElgPoints: case ElgLineStrip: case ElgTriangleStrip: - if (! intermediate.setOutputPrimitive(publicType.shaderQualifiers.geometry)) + if (!intermediate.setOutputPrimitive(publicType.shaderQualifiers.geometry)) { error(loc, "cannot change previously set output primitive", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), ""); + } + else { + intermediate.setOutputPrimitiveSetOutside(false); + } break; default: error(loc, "cannot apply to 'out'", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), ""); diff --git a/glslang/MachineIndependent/ParseHelper.h b/glslang/MachineIndependent/ParseHelper.h index 885fd90810..87c48fee59 100644 --- a/glslang/MachineIndependent/ParseHelper.h +++ b/glslang/MachineIndependent/ParseHelper.h @@ -335,6 +335,7 @@ class TParseContext : public TParseContextBase { void fixIoArraySize(const TSourceLoc&, TType&); void handleIoResizeArrayAccess(const TSourceLoc&, TIntermTyped* base); void checkIoArraysConsistency(const TSourceLoc&, bool tailOnly = false); + void fixBuiltinConstantVerticesIn(); int getIoArrayImplicitSize(const TQualifier&, TString* featureString = nullptr) const; void checkIoArrayConsistency(const TSourceLoc&, int requiredSize, const char* feature, TType&, const TString&); @@ -403,7 +404,7 @@ class TParseContext : public TParseContextBase { void precisionQualifierCheck(const TSourceLoc&, TBasicType, TQualifier&); void parameterTypeCheck(const TSourceLoc&, TStorageQualifier qualifier, const TType& type); bool containsFieldWithBasicType(const TType& type ,TBasicType basicType); - TSymbol* redeclareBuiltinVariable(const TSourceLoc&, const TString&, const TQualifier&, const TShaderQualifiers&); + TSymbol* redeclareBuiltinVariable(const TSourceLoc&, const TString&, const TType& type, const TShaderQualifiers&); void redeclareBuiltinBlock(const TSourceLoc&, TTypeList& typeList, const TString& blockName, const TString* instanceName, TArraySizes* arraySizes); void paramCheckFixStorage(const TSourceLoc&, const TStorageQualifier&, TType& type); void paramCheckFix(const TSourceLoc&, const TQualifier&, TType& type); diff --git a/glslang/MachineIndependent/ShaderLang.cpp b/glslang/MachineIndependent/ShaderLang.cpp index ced00863e3..621f07b30b 100644 --- a/glslang/MachineIndependent/ShaderLang.cpp +++ b/glslang/MachineIndependent/ShaderLang.cpp @@ -354,7 +354,7 @@ bool InitializeSymbolTables(TInfoSink& infoSink, TSymbolTable** commonTable, TS } // check for geometry - if ((profile != EEsProfile && version >= 150) || + if ((profile != EEsProfile && version >= 110) || (profile == EEsProfile && version >= 310)) InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangGeometry, source, infoSink, commonTable, symbolTables); @@ -605,8 +605,8 @@ bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNo if ((profile == EEsProfile && version < 310) || (profile != EEsProfile && version < 150)) { correct = false; - infoSink.info.message(EPrefixError, "#version: geometry shaders require es profile with version 310 or non-es profile with version 150 or above"); - version = (profile == EEsProfile) ? 310 : 150; + infoSink.info.message(EPrefixError, "#version: geometry shaders require es profile with version 310 or non-es profile with version 110 or above"); + version = (profile == EEsProfile) ? 310 : 110; // OpenGL 1.1 is required for ARB_geometry_shader4 extension if (profile == EEsProfile || profile == ENoProfile) profile = ECoreProfile; } @@ -1013,6 +1013,10 @@ bool ProcessDeferred( versionWillBeError, *symbolTable, intermediate, optLevel, messages); intermediate.setUniqueId(symbolTable->getMaxSymbolId()); + + // A local change here. May not be upstreamed. + intermediate.setGeometryShader4(parseContext->extensionsTurnedOn(Num_ARB_geometry_shader4, ARB_geometry_shader4)); + return success; } diff --git a/glslang/MachineIndependent/Versions.cpp b/glslang/MachineIndependent/Versions.cpp index a5fd107535..80ea821c9d 100644 --- a/glslang/MachineIndependent/Versions.cpp +++ b/glslang/MachineIndependent/Versions.cpp @@ -227,6 +227,8 @@ void TParseVersions::initializeExtensionBehavior() extensionBehavior[E_GL_ARB_texture_query_lod] = EBhDisable; extensionBehavior[E_GL_ARB_vertex_attrib_64bit] = EBhDisable; extensionBehavior[E_GL_ARB_draw_instanced] = EBhDisable; + extensionBehavior[E_GL_GL_ARB_arrays_of_arrays] = EBhDisable; + extensionBehavior[E_GL_ARB_geometry_shader4] = EBhDisable; extensionBehavior[E_GL_ARB_fragment_coord_conventions] = EBhDisable; @@ -255,6 +257,7 @@ void TParseVersions::initializeExtensionBehavior() extensionBehavior[E_GL_EXT_buffer_reference_uvec2] = EBhDisable; extensionBehavior[E_GL_EXT_demote_to_helper_invocation] = EBhDisable; extensionBehavior[E_GL_EXT_debug_printf] = EBhDisable; + extensionBehavior[E_GL_EXT_geometry_shader4] = EBhDisable; extensionBehavior[E_GL_EXT_shader_16bit_storage] = EBhDisable; extensionBehavior[E_GL_EXT_shader_8bit_storage] = EBhDisable; @@ -444,6 +447,7 @@ void TParseVersions::getPreamble(std::string& preamble) "#define GL_ARB_gpu_shader5 1\n" "#define GL_ARB_separate_shader_objects 1\n" "#define GL_ARB_compute_shader 1\n" + "#define GL_ARB_geometry_shader4 1\n" "#define GL_ARB_tessellation_shader 1\n" "#define GL_ARB_enhanced_layouts 1\n" "#define GL_ARB_texture_cube_map_array 1\n" @@ -476,6 +480,7 @@ void TParseVersions::getPreamble(std::string& preamble) "#define GL_ARB_texture_query_lod 1\n" "#define GL_ARB_vertex_attrib_64bit 1\n" "#define GL_ARB_draw_instanced 1\n" + "#define GL_ARB_arrays_of_arrays 1 \n" "#define GL_ARB_fragment_coord_conventions 1\n" "#define GL_EXT_shader_non_constant_global_initializers 1\n" "#define GL_EXT_shader_image_load_formatted 1\n" @@ -494,6 +499,7 @@ void TParseVersions::getPreamble(std::string& preamble) "#define GL_EXT_debug_printf 1\n" "#define GL_EXT_fragment_shading_rate 1\n" "#define GL_EXT_shared_memory_block 1\n" + "#define GL_EXT_geometry_shader4 1\n" "#define GL_EXT_shader_integer_mix 1\n" // GL_KHR_shader_subgroup diff --git a/glslang/MachineIndependent/Versions.h b/glslang/MachineIndependent/Versions.h index f06abdd6f0..69963a2ddc 100644 --- a/glslang/MachineIndependent/Versions.h +++ b/glslang/MachineIndependent/Versions.h @@ -162,7 +162,9 @@ const char* const E_GL_ARB_shading_language_packing = "GL_ARB_shading_langua const char* const E_GL_ARB_texture_query_lod = "GL_ARB_texture_query_lod"; const char* const E_GL_ARB_vertex_attrib_64bit = "GL_ARB_vertex_attrib_64bit"; const char* const E_GL_ARB_draw_instanced = "GL_ARB_draw_instanced"; +const char* const E_GL_GL_ARB_arrays_of_arrays = "GL_ARB_arrays_of_arrays"; const char* const E_GL_ARB_fragment_coord_conventions = "GL_ARB_fragment_coord_conventions"; +const char* const E_GL_ARB_geometry_shader4 = "GL_ARB_geometry_shader4"; 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"; @@ -206,6 +208,8 @@ const char* const E_GL_EXT_blend_func_extended = "GL_EXT_blend_func const char* const E_GL_EXT_shader_implicit_conversions = "GL_EXT_shader_implicit_conversions"; const char* const E_GL_EXT_fragment_shading_rate = "GL_EXT_fragment_shading_rate"; const char* const E_GL_EXT_shader_image_int64 = "GL_EXT_shader_image_int64"; +const char* const E_GL_EXT_geometry_shader4 = "GL_EXT_geometry_shader4"; + const char* const E_GL_EXT_null_initializer = "GL_EXT_null_initializer"; const char* const E_GL_EXT_shared_memory_block = "GL_EXT_shared_memory_block"; const char* const E_GL_EXT_subgroup_uniform_control_flow = "GL_EXT_subgroup_uniform_control_flow"; @@ -351,6 +355,11 @@ const int Num_AEP_texture_buffer = sizeof(AEP_texture_buffer)/sizeof(AEP_texture const char* const AEP_texture_cube_map_array[] = { E_GL_EXT_texture_cube_map_array, E_GL_OES_texture_cube_map_array }; const int Num_AEP_texture_cube_map_array = sizeof(AEP_texture_cube_map_array)/sizeof(AEP_texture_cube_map_array[0]); +const char* const ARB_geometry_arrays_of_arrays[] = { E_GL_GL_ARB_arrays_of_arrays , E_GL_ARB_geometry_shader4 }; +const int Num_ARB_geometry_arrays_of_arrays = sizeof(ARB_geometry_arrays_of_arrays) / sizeof(ARB_geometry_arrays_of_arrays[0]); + +const char* const ARB_geometry_shader4[] = { E_GL_EXT_geometry_shader4 , E_GL_ARB_geometry_shader4 }; +const int Num_ARB_geometry_shader4 = sizeof(ARB_geometry_shader4) / sizeof(ARB_geometry_shader4[0]); const char* const AEP_mesh_shader[] = { E_GL_NV_mesh_shader, E_GL_EXT_mesh_shader }; const int Num_AEP_mesh_shader = sizeof(AEP_mesh_shader)/sizeof(AEP_mesh_shader[0]); diff --git a/glslang/MachineIndependent/linkValidate.cpp b/glslang/MachineIndependent/linkValidate.cpp index fab65a76ef..70611fecd5 100644 --- a/glslang/MachineIndependent/linkValidate.cpp +++ b/glslang/MachineIndependent/linkValidate.cpp @@ -334,6 +334,20 @@ void TIntermediate::mergeModes(TInfoSink& infoSink, TIntermediate& unit) MERGE_TRUE(needToLegalize); MERGE_TRUE(binaryDoubleOutput); MERGE_TRUE(usePhysicalStorageBuffer); + + // Merge primitive info of 'this' AST to the 'unit' AST. + // (In the other case, primitive info will be merged during merge trees) + // That includes input and output primitive layouts. Merged results will be copied into both AST. + // Also unmatched primitive layouts would be reported. + if (getStage() == EShLangGeometry && unit.getStage() == EShLangGeometry) { + if (unit.getInputPrimitive() == ElgNone) { + unit.setInputPrimitive(getInputPrimitive()); + } + + if (getInputPrimitive() != unit.getInputPrimitive() && getInputPrimitive() != ElgNone) { + infoSink.info.message(EPrefixError, "Can't merge two Geometry shaders with different input primitive layouts."); + } + } } // @@ -1287,11 +1301,13 @@ void TIntermediate::finalCheck(TInfoSink& infoSink, bool keepUncalled) } break; case EShLangGeometry: - if (inputPrimitive == ElgNone) + // Those three related qualifiers' keywords are not supported in version <= 140. + // We need to allow setting those three qualifiers through api in low versions, but keep checks for gs shaders > 140. + if (inputPrimitive == ElgNone && (inputPrimitiveSetOutside == false && version > 140)) error(infoSink, "At least one shader must specify an input layout primitive"); - if (outputPrimitive == ElgNone) + if (outputPrimitive == ElgNone && (outputPrimitiveSetOutside == false && version > 140)) error(infoSink, "At least one shader must specify an output layout primitive"); - if (vertices == TQualifier::layoutNotSet) + if (vertices == TQualifier::layoutNotSet && (maxGSVerticesSetOutside == false && version > 140)) error(infoSink, "At least one shader must specify a layout(max_vertices = value)"); break; case EShLangFragment: @@ -1325,9 +1341,9 @@ void TIntermediate::finalCheck(TInfoSink& infoSink, bool keepUncalled) error(infoSink, "Can only use one of gl_Layer or gl_LayerPerViewNV"); if (inIoAccessed("gl_ViewportMask") && inIoAccessed("gl_ViewportMaskPerViewNV")) error(infoSink, "Can only use one of gl_ViewportMask or gl_ViewportMaskPerViewNV"); - if (outputPrimitive == ElgNone) + if (outputPrimitive == ElgNone || (outputPrimitiveSetOutside == true && version > 140)) error(infoSink, "At least one shader must specify an output layout primitive"); - if (vertices == TQualifier::layoutNotSet) + if (vertices == TQualifier::layoutNotSet || (maxGSVerticesSetOutside == true && version > 140)) error(infoSink, "At least one shader must specify a layout(max_vertices = value)"); if (primitives == TQualifier::layoutNotSet) error(infoSink, "At least one shader must specify a layout(max_primitives = value)"); diff --git a/glslang/MachineIndependent/localintermediate.h b/glslang/MachineIndependent/localintermediate.h index 1bb4e97709..b47021efad 100644 --- a/glslang/MachineIndependent/localintermediate.h +++ b/glslang/MachineIndependent/localintermediate.h @@ -297,6 +297,7 @@ class TIntermediate { depthReplacing(false), stencilReplacing(false), uniqueId(0), + useGeometryShader4(false), globalUniformBlockName(""), atomicCounterBlockName(""), globalUniformBlockSet(TQualifier::layoutSetEnd), @@ -308,6 +309,7 @@ class TIntermediate { source(EShSourceNone), useVulkanMemoryModel(false), invocations(TQualifier::layoutNotSet), vertices(TQualifier::layoutNotSet), + inputPrimitiveSetOutside(false), outputPrimitiveSetOutside(false), maxGSVerticesSetOutside(false), inputPrimitive(ElgNone), outputPrimitive(ElgNone), pixelCenterInteger(false), originUpperLeft(false),texCoordBuiltinRedeclared(false), vertexSpacing(EvsNone), vertexOrder(EvoNone), interlockOrdering(EioNone), pointMode(false), earlyFragmentTests(false), @@ -771,7 +773,8 @@ class TIntermediate { int getInvocations() const { return invocations; } bool setVertices(int m) { - if (vertices != TQualifier::layoutNotSet) + if (vertices != TQualifier::layoutNotSet && + getMaxGSVerticesSetOutside() == false) return vertices == m; vertices = m; return true; @@ -779,12 +782,19 @@ class TIntermediate { int getVertices() const { return vertices; } bool setInputPrimitive(TLayoutGeometry p) { - if (inputPrimitive != ElgNone) + if (inputPrimitive != ElgNone && + getInputPrimitiveSetOutside() == false) return inputPrimitive == p; inputPrimitive = p; return true; } TLayoutGeometry getInputPrimitive() const { return inputPrimitive; } + bool setInputPrimitiveSetOutside(bool p) + { + inputPrimitiveSetOutside = p; + return true; + } + bool getInputPrimitiveSetOutside() const { return inputPrimitiveSetOutside; } bool setVertexSpacing(TVertexSpacing s) { if (vertexSpacing != EvsNone) @@ -819,12 +829,25 @@ class TIntermediate { bool isMultiStream() const { return multiStream; } bool setOutputPrimitive(TLayoutGeometry p) { - if (outputPrimitive != ElgNone) + if (outputPrimitive != ElgNone && + getOutputPrimitiveSetOutside() == false) return outputPrimitive == p; outputPrimitive = p; return true; } TLayoutGeometry getOutputPrimitive() const { return outputPrimitive; } + bool setOutputPrimitiveSetOutside(bool p) + { + outputPrimitiveSetOutside = p; + return true; + } + bool getOutputPrimitiveSetOutside() const { return outputPrimitiveSetOutside; } + bool setMaxGSVerticesSetOutside(bool p) + { + maxGSVerticesSetOutside = p; + return true; + } + bool getMaxGSVerticesSetOutside() const { return maxGSVerticesSetOutside; } void setPostDepthCoverage() { postDepthCoverage = true; } bool getPostDepthCoverage() const { return postDepthCoverage; } void setEarlyFragmentTests() { earlyFragmentTests = true; } @@ -1028,6 +1051,8 @@ class TIntermediate { const std::vector& getProcesses() const { return processes.getProcesses(); } unsigned long long getUniqueId() const { return uniqueId; } void setUniqueId(unsigned long long id) { uniqueId = id; } + bool getGeometryShader4() const { return useGeometryShader4; } + void setGeometryShader4(bool enable) { useGeometryShader4 = enable; } // Certain explicit conversions are allowed conditionally #ifdef GLSLANG_WEB @@ -1118,6 +1143,7 @@ class TIntermediate { bool localSizeNotDefault[3]; int localSizeSpecId[3]; unsigned long long uniqueId; + bool useGeometryShader4; std::string globalUniformBlockName; std::string atomicCounterBlockName; @@ -1134,6 +1160,9 @@ class TIntermediate { bool useVulkanMemoryModel; int invocations; int vertices; + bool inputPrimitiveSetOutside; // input primitive set from outside. + bool outputPrimitiveSetOutside; // output primitive set from outside. + bool maxGSVerticesSetOutside; // max_vertices set from outside. TLayoutGeometry inputPrimitive; TLayoutGeometry outputPrimitive; bool pixelCenterInteger;