summaryrefslogtreecommitdiffstats
path: root/thirdparty/glslang/glslang/MachineIndependent/ParseHelper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/glslang/glslang/MachineIndependent/ParseHelper.cpp')
-rw-r--r--thirdparty/glslang/glslang/MachineIndependent/ParseHelper.cpp121
1 files changed, 102 insertions, 19 deletions
diff --git a/thirdparty/glslang/glslang/MachineIndependent/ParseHelper.cpp b/thirdparty/glslang/glslang/MachineIndependent/ParseHelper.cpp
index d9cb640b2a..cb19b2d434 100644
--- a/thirdparty/glslang/glslang/MachineIndependent/ParseHelper.cpp
+++ b/thirdparty/glslang/glslang/MachineIndependent/ParseHelper.cpp
@@ -598,6 +598,10 @@ TIntermTyped* TParseContext::handleBracketDereference(const TSourceLoc& loc, TIn
indexValue >= resources.maxCullDistances) {
error(loc, "gl_CullDistance", "[", "array index out of range '%d'", indexValue);
}
+ else if (base->getQualifier().builtIn == EbvSampleMask &&
+ indexValue >= (resources.maxSamples + 31) / 32) {
+ error(loc, "gl_SampleMask", "[", "array index out of range '%d'", indexValue);
+ }
// For 2D per-view builtin arrays, update the inner dimension size in parent type
if (base->getQualifier().isPerView() && base->getQualifier().builtIn != EbvNone) {
TIntermBinary* binaryNode = base->getAsBinaryNode();
@@ -632,7 +636,7 @@ TIntermTyped* TParseContext::handleBracketDereference(const TSourceLoc& loc, TIn
else {
// input/output blocks either don't exist or can't be variably indexed
}
- } else if (language == EShLangFragment && base->getQualifier().isPipeOutput())
+ } else if (language == EShLangFragment && base->getQualifier().isPipeOutput() && base->getQualifier().builtIn != EbvSampleMask)
requireProfile(base->getLoc(), ~EEsProfile, "variable indexing fragment shader output array");
else if (base->getBasicType() == EbtSampler && version >= 130) {
const char* explanation = "variable indexing sampler array";
@@ -1351,6 +1355,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());
@@ -1360,7 +1368,10 @@ TIntermTyped* TParseContext::handleFunctionCall(const TSourceLoc& loc, TFunction
requireInt16Arithmetic(loc, "built-in function", "(u)int16 types can only be in uniform block or buffer storage");
if (builtIn && fnCandidate->getType().contains8BitInt())
requireInt8Arithmetic(loc, "built-in function", "(u)int8 types can only be in uniform block or buffer storage");
-
+ if (builtIn && (fnCandidate->getBuiltInOp() == EOpTextureFetch || fnCandidate->getBuiltInOp() == EOpTextureQuerySize)) {
+ if ((*fnCandidate)[0].type->getSampler().isMultiSample() && version <= 140)
+ requireExtensions(loc, 1, &E_GL_ARB_texture_multisample, fnCandidate->getName().c_str());
+ }
if (arguments != nullptr) {
// Make sure qualifications work for these arguments.
TIntermAggregate* aggregate = arguments->getAsAggregate();
@@ -1756,6 +1767,11 @@ TIntermTyped* TParseContext::handleLengthMethod(const TSourceLoc& loc, TFunction
name == "gl_MeshPrimitivesNV") {
length = getIoArrayImplicitSize(type.getQualifier());
}
+ } else if (const auto typed = intermNode->getAsTyped()) {
+ if (typed->getQualifier().builtIn == EbvSampleMask) {
+ requireProfile(loc, EEsProfile, "the array size of gl_SampleMask and gl_SampleMaskIn is ceil(gl_MaxSamples/32)");
+ length = (resources.maxSamples + 31) / 32;
+ }
}
if (length == 0) {
if (intermNode->getAsSymbolNode() && isIoResizeArray(type))
@@ -2512,15 +2528,26 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan
error(loc, "only supported on image with format r64i", fnCandidate.getName().c_str(), "");
else if (callNode.getType().getBasicType() == EbtUint64 && imageType.getQualifier().getFormat() != ElfR64ui)
error(loc, "only supported on image with format r64ui", fnCandidate.getName().c_str(), "");
+ } else if(callNode.getType().getBasicType() == EbtFloat16 &&
+ ((callNode.getType().getVectorSize() == 2 && arg0->getType().getQualifier().getFormat() == ElfRg16f) ||
+ (callNode.getType().getVectorSize() == 4 && arg0->getType().getQualifier().getFormat() == ElfRgba16f))) {
+ if (StartsWith(fnCandidate.getName(), "imageAtomicAdd") ||
+ StartsWith(fnCandidate.getName(), "imageAtomicExchange") ||
+ StartsWith(fnCandidate.getName(), "imageAtomicMin") ||
+ StartsWith(fnCandidate.getName(), "imageAtomicMax")) {
+ requireExtensions(loc, 1, &E_GL_NV_shader_atomic_fp16_vector, fnCandidate.getName().c_str());
+ } else {
+ error(loc, "f16vec2/4 operation not supported on: ", fnCandidate.getName().c_str(), "");
+ }
} else if (imageType.getSampler().type == EbtFloat) {
- if (fnCandidate.getName().compare(0, 19, "imageAtomicExchange") == 0) {
+ if (StartsWith(fnCandidate.getName(), "imageAtomicExchange")) {
// imageAtomicExchange doesn't require an extension
- } else if ((fnCandidate.getName().compare(0, 14, "imageAtomicAdd") == 0) ||
- (fnCandidate.getName().compare(0, 15, "imageAtomicLoad") == 0) ||
- (fnCandidate.getName().compare(0, 16, "imageAtomicStore") == 0)) {
+ } else if (StartsWith(fnCandidate.getName(), "imageAtomicAdd") ||
+ StartsWith(fnCandidate.getName(), "imageAtomicLoad") ||
+ StartsWith(fnCandidate.getName(), "imageAtomicStore")) {
requireExtensions(loc, 1, &E_GL_EXT_shader_atomic_float, fnCandidate.getName().c_str());
- } else if ((fnCandidate.getName().compare(0, 14, "imageAtomicMin") == 0) ||
- (fnCandidate.getName().compare(0, 14, "imageAtomicMax") == 0)) {
+ } else if (StartsWith(fnCandidate.getName(), "imageAtomicMin") ||
+ StartsWith(fnCandidate.getName(), "imageAtomicMax")) {
requireExtensions(loc, 1, &E_GL_EXT_shader_atomic_float2, fnCandidate.getName().c_str());
} else {
error(loc, "only supported on integer images", fnCandidate.getName().c_str(), "");
@@ -2570,6 +2597,11 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan
const char* const extensions[2] = { E_GL_NV_shader_atomic_int64,
E_GL_EXT_shader_atomic_int64 };
requireExtensions(loc, 2, extensions, fnCandidate.getName().c_str());
+ } else if ((callNode.getOp() == EOpAtomicAdd || callNode.getOp() == EOpAtomicExchange ||
+ callNode.getOp() == EOpAtomicMin || callNode.getOp() == EOpAtomicMax) &&
+ arg0->getType().getBasicType() == EbtFloat16 &&
+ (arg0->getType().getVectorSize() == 2 || arg0->getType().getVectorSize() == 4 )) {
+ requireExtensions(loc, 1, &E_GL_NV_shader_atomic_fp16_vector, fnCandidate.getName().c_str());
} else if ((callNode.getOp() == EOpAtomicAdd || callNode.getOp() == EOpAtomicExchange) &&
(arg0->getType().getBasicType() == EbtFloat ||
arg0->getType().getBasicType() == EbtDouble)) {
@@ -3978,6 +4010,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();
+ }
}
//
@@ -5851,6 +5895,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 ||
@@ -5900,6 +5953,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(), "");
}
@@ -6201,7 +6264,7 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi
error(loc, "needs a literal integer", "max_primitives", "");
return;
}
- // Fall through
+ [[fallthrough]];
case EShLangTask:
// Fall through
@@ -6328,6 +6391,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)
@@ -6501,10 +6568,10 @@ void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type)
int repeated = intermediate.addUsedLocation(qualifier, type, typeCollision);
if (repeated >= 0 && ! typeCollision)
error(loc, "overlapping use of location", "location", "%d", repeated);
- // "fragment-shader outputs/tileImageEXT ... if two variables are placed within the same
- // location, they must have the same underlying type (floating-point or integer)"
- if (typeCollision && language == EShLangFragment && (qualifier.isPipeOutput() || qualifier.storage == EvqTileImageEXT))
- error(loc, "fragment outputs or tileImageEXTs sharing the same location", "location", "%d must be the same basic type", repeated);
+ // When location aliasing, the aliases sharing the location must have the same underlying numerical type and bit width(
+ // floating - point or integer, 32 - bit versus 64 - bit,etc.)
+ if (typeCollision && (qualifier.isPipeInput() || qualifier.isPipeOutput() || qualifier.storage == EvqTileImageEXT))
+ error(loc, "the aliases sharing the location", "location", "%d must be the same basic type and interpolation qualification", repeated);
}
if (qualifier.hasXfbOffset() && qualifier.hasXfbBuffer()) {
@@ -7273,7 +7340,7 @@ TIntermTyped* TParseContext::vkRelaxedRemapFunctionCall(const TSourceLoc& loc, T
realFunc.addParameter(TParameter().copyParam((*function)[i]));
}
- TParameter tmpP = { nullptr, &uintType };
+ TParameter tmpP = { nullptr, &uintType, {} };
realFunc.addParameter(TParameter().copyParam(tmpP));
arguments = intermediate.growAggregate(arguments, intermediate.addConstantUnion(1, loc, true));
@@ -7290,7 +7357,7 @@ TIntermTyped* TParseContext::vkRelaxedRemapFunctionCall(const TSourceLoc& loc, T
realFunc.addParameter(TParameter().copyParam((*function)[i]));
}
- TParameter tmpP = { nullptr, &uintType };
+ TParameter tmpP = { nullptr, &uintType, {} };
realFunc.addParameter(TParameter().copyParam(tmpP));
arguments = intermediate.growAggregate(arguments, intermediate.addConstantUnion(-1, loc, true));
@@ -7350,6 +7417,7 @@ void TParseContext::coopMatTypeParametersCheck(const TSourceLoc& loc, const TPub
case EbtUint:
case EbtUint8:
case EbtUint16:
+ case EbtSpirvType:
break;
default:
error(loc, "coopmat invalid basic type", TType::getBasicString(publicType.typeParameters->basicType), "");
@@ -7573,6 +7641,7 @@ struct AccessChainTraverser : public TIntermTraverser {
{}
TString path = "";
+ TStorageQualifier topLevelStorageQualifier = TStorageQualifier::EvqLast;
bool visitBinary(TVisit, TIntermBinary* binary) override {
if (binary->getOp() == EOpIndexDirectStruct)
@@ -7603,6 +7672,8 @@ struct AccessChainTraverser : public TIntermTraverser {
}
void visitSymbol(TIntermSymbol* symbol) override {
+ if (symbol->getType().isOpaque())
+ topLevelStorageQualifier = symbol->getQualifier().storage;
if (!IsAnonymous(symbol->getName()))
path.append(symbol->getName());
}
@@ -7613,7 +7684,16 @@ TIntermNode* TParseContext::vkRelaxedRemapFunctionArgument(const TSourceLoc& loc
AccessChainTraverser accessChainTraverser{};
intermTyped->traverse(&accessChainTraverser);
- TParameter param = { NewPoolTString(accessChainTraverser.path.c_str()), new TType };
+ if (accessChainTraverser.topLevelStorageQualifier == TStorageQualifier::EvqUniform)
+ {
+ TParameter param = { 0, new TType, {} };
+ param.type->shallowCopy(intermTyped->getType());
+
+ function->addParameter(param);
+ return intermTyped;
+ }
+
+ TParameter param = { NewPoolTString(accessChainTraverser.path.c_str()), new TType, {} };
param.type->shallowCopy(intermTyped->getType());
std::vector<int> newParams = {};
@@ -7732,7 +7812,8 @@ TIntermNode* TParseContext::declareVariable(const TSourceLoc& loc, TString& iden
error(loc, "unexpected number type parameters", identifier.c_str(), "");
}
if (publicType.typeParameters) {
- if (!isTypeFloat(publicType.typeParameters->basicType) && !isTypeInt(publicType.typeParameters->basicType)) {
+ if (!isTypeFloat(publicType.typeParameters->basicType) &&
+ !isTypeInt(publicType.typeParameters->basicType) && publicType.typeParameters->basicType != EbtSpirvType) {
error(loc, "expected 8, 16, 32, or 64 bit signed or unsigned integer or 16, 32, or 64 bit float type", identifier.c_str(), "");
}
}
@@ -8371,6 +8452,7 @@ TIntermTyped* TParseContext::constructBuiltIn(const TType& type, TOperator op, T
intermediate.addBuiltInFunctionCall(node->getLoc(), EOpConstructUVec2, false, newSrcNode, type);
return newNode;
}
+ [[fallthrough]];
case EOpConstructUVec3:
case EOpConstructUVec4:
case EOpConstructUint:
@@ -8392,6 +8474,7 @@ TIntermTyped* TParseContext::constructBuiltIn(const TType& type, TOperator op, T
intermediate.addBuiltInFunctionCall(node->getLoc(), EOpPackUint2x32, true, node, type);
return newNode;
}
+ [[fallthrough]];
case EOpConstructDVec2:
case EOpConstructDVec3:
case EOpConstructDVec4:
@@ -8544,7 +8627,7 @@ TIntermTyped* TParseContext::constructBuiltIn(const TType& type, TOperator op, T
TIntermTyped* newNode = intermediate.addBuiltInFunctionCall(node->getLoc(), EOpConvPtrToUint64, true, node, type);
return newNode;
}
- // fall through
+ [[fallthrough]];
case EOpConstructU64Vec2:
case EOpConstructU64Vec3:
case EOpConstructU64Vec4:
@@ -9609,7 +9692,7 @@ void TParseContext::updateStandaloneQualifierDefaults(const TSourceLoc& loc, con
error(loc, "cannot apply to 'out'", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), "");
break;
}
- // Fall through
+ [[fallthrough]];
case ElgPoints:
case ElgLineStrip:
case ElgTriangleStrip: