Merge branch 'KhronosGroup:master' into master

This commit is contained in:
ZhiqianXia 2021-07-07 14:12:33 +08:00 committed by GitHub
commit 8a5c5e8210
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
94 changed files with 10862 additions and 6812 deletions

View file

@ -1092,12 +1092,31 @@ TFunction* TParseContext::handleFunctionDeclarator(const TSourceLoc& loc, TFunct
TSymbol* symbol = symbolTable.find(function.getMangledName(), &builtIn);
if (symbol && symbol->getAsFunction() && builtIn)
requireProfile(loc, ~EEsProfile, "redefinition of built-in function");
#ifndef GLSLANG_WEB
// Check the validity of using spirv_literal qualifier
for (int i = 0; i < function.getParamCount(); ++i) {
if (function[i].type->getQualifier().isSpirvLiteral() && function.getBuiltInOp() != EOpSpirvInst)
error(loc, "'spirv_literal' can only be used on functions defined with 'spirv_instruction' for argument",
function.getName().c_str(), "%d", i + 1);
}
// For function declaration with SPIR-V instruction qualifier, always ignore the built-in function and
// respect this redeclared one.
if (symbol && builtIn && function.getBuiltInOp() == EOpSpirvInst)
symbol = nullptr;
#endif
const TFunction* prevDec = symbol ? symbol->getAsFunction() : 0;
if (prevDec) {
if (prevDec->isPrototyped() && prototype)
profileRequires(loc, EEsProfile, 300, nullptr, "multiple prototypes for same function");
if (prevDec->getType() != function.getType())
error(loc, "overloaded functions must have the same return type", function.getName().c_str(), "");
#ifndef GLSLANG_WEB
if (prevDec->getSpirvInstruction() != function.getSpirvInstruction()) {
error(loc, "overloaded functions must have the same qualifiers", function.getName().c_str(),
"spirv_instruction");
}
#endif
for (int i = 0; i < prevDec->getParamCount(); ++i) {
if ((*prevDec)[i].type->getQualifier().storage != function[i].type->getQualifier().storage)
error(loc, "overloaded functions must have the same parameter storage qualifiers for argument", function[i].type->getStorageQualifierString(), "%d", i+1);
@ -1299,6 +1318,15 @@ TIntermTyped* TParseContext::handleFunctionCall(const TSourceLoc& loc, TFunction
if (lValueErrorCheck(arguments->getLoc(), "assign", arg->getAsTyped()))
error(arguments->getLoc(), "Non-L-value cannot be passed for 'out' or 'inout' parameters.", "out", "");
}
#ifndef GLSLANG_WEB
if (formalQualifier.isSpirvLiteral()) {
if (!arg->getAsTyped()->getQualifier().isFrontEndConstant()) {
error(arguments->getLoc(),
"Non front-end constant expressions cannot be passed for 'spirv_literal' parameters.",
"spirv_literal", "");
}
}
#endif
const TType& argType = arg->getAsTyped()->getType();
const TQualifier& argQualifier = argType.getQualifier();
if (argQualifier.isMemory() && (argType.containsOpaque() || argType.isReference())) {
@ -1353,6 +1381,11 @@ TIntermTyped* TParseContext::handleFunctionCall(const TSourceLoc& loc, TFunction
if (builtIn && fnCandidate->getBuiltInOp() != EOpNull) {
// A function call mapped to a built-in operation.
result = handleBuiltInFunctionCall(loc, arguments, *fnCandidate);
#ifndef GLSLANG_WEB
} else if (fnCandidate->getBuiltInOp() == EOpSpirvInst) {
// When SPIR-V instruction qualifier is specified, the function call is still mapped to a built-in operation.
result = handleBuiltInFunctionCall(loc, arguments, *fnCandidate);
#endif
} else {
// This is a function call not mapped to built-in operator.
// It could still be a built-in function, but only if PureOperatorBuiltins == false.
@ -1430,6 +1463,35 @@ TIntermTyped* TParseContext::handleBuiltInFunctionCall(TSourceLoc loc, TIntermNo
} else if (result->getAsOperator())
builtInOpCheck(loc, function, *result->getAsOperator());
#ifndef GLSLANG_WEB
// Special handling for function call with SPIR-V instruction qualifier specified
if (function.getBuiltInOp() == EOpSpirvInst) {
if (auto agg = result->getAsAggregate()) {
// Propogate spirv_by_reference/spirv_literal from parameters to arguments
auto& sequence = agg->getSequence();
for (unsigned i = 0; i < sequence.size(); ++i) {
if (function[i].type->getQualifier().isSpirvByReference())
sequence[i]->getAsTyped()->getQualifier().setSpirvByReference();
if (function[i].type->getQualifier().isSpirvLiteral())
sequence[i]->getAsTyped()->getQualifier().setSpirvLiteral();
}
// Attach the function call to SPIR-V intruction
agg->setSpirvInstruction(function.getSpirvInstruction());
} else if (auto unaryNode = result->getAsUnaryNode()) {
// Propogate spirv_by_reference/spirv_literal from parameters to arguments
if (function[0].type->getQualifier().isSpirvByReference())
unaryNode->getOperand()->getQualifier().setSpirvByReference();
if (function[0].type->getQualifier().isSpirvLiteral())
unaryNode->getOperand()->getQualifier().setSpirvLiteral();
// Attach the function call to SPIR-V intruction
unaryNode->setSpirvInstruction(function.getSpirvInstruction());
} else
assert(0);
}
#endif
return result;
}
@ -2279,18 +2341,23 @@ 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 {
bool isImageAtomicOnFloatAllowed = ((fnCandidate.getName().compare(0, 14, "imageAtomicAdd") == 0) ||
(fnCandidate.getName().compare(0, 15, "imageAtomicLoad") == 0) ||
(fnCandidate.getName().compare(0, 16, "imageAtomicStore") == 0) ||
(fnCandidate.getName().compare(0, 19, "imageAtomicExchange") == 0));
if (imageType.getSampler().type == EbtFloat && isImageAtomicOnFloatAllowed &&
(fnCandidate.getName().compare(0, 19, "imageAtomicExchange") != 0)) // imageAtomicExchange doesn't require GL_EXT_shader_atomic_float
} else if (imageType.getSampler().type == EbtFloat) {
if (fnCandidate.getName().compare(0, 19, "imageAtomicExchange") == 0) {
// 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)) {
requireExtensions(loc, 1, &E_GL_EXT_shader_atomic_float, fnCandidate.getName().c_str());
if (!isImageAtomicOnFloatAllowed)
} else if ((fnCandidate.getName().compare(0, 14, "imageAtomicMin") == 0) ||
(fnCandidate.getName().compare(0, 14, "imageAtomicMax") == 0)) {
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(), "");
else if (imageType.getQualifier().getFormat() != ElfR32f && isEsProfile())
}
if (imageType.getQualifier().getFormat() != ElfR32f && isEsProfile())
error(loc, "only supported on image with format r32f", fnCandidate.getName().c_str(), "");
} else {
error(loc, "not supported on this image type", fnCandidate.getName().c_str(), "");
}
const size_t maxArgs = imageType.getSampler().isMultiSample() ? 5 : 4;
@ -2319,16 +2386,28 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan
memorySemanticsCheck(loc, fnCandidate, callNode);
if ((callNode.getOp() == EOpAtomicAdd || callNode.getOp() == EOpAtomicExchange ||
callNode.getOp() == EOpAtomicLoad || callNode.getOp() == EOpAtomicStore) &&
(arg0->getType().isFloatingDomain())) {
(arg0->getType().getBasicType() == EbtFloat ||
arg0->getType().getBasicType() == EbtDouble)) {
requireExtensions(loc, 1, &E_GL_EXT_shader_atomic_float, fnCandidate.getName().c_str());
} else if ((callNode.getOp() == EOpAtomicAdd || callNode.getOp() == EOpAtomicExchange ||
callNode.getOp() == EOpAtomicLoad || callNode.getOp() == EOpAtomicStore ||
callNode.getOp() == EOpAtomicMin || callNode.getOp() == EOpAtomicMax) &&
arg0->getType().isFloatingDomain()) {
requireExtensions(loc, 1, &E_GL_EXT_shader_atomic_float2, fnCandidate.getName().c_str());
}
} else if (arg0->getType().getBasicType() == EbtInt64 || arg0->getType().getBasicType() == EbtUint64) {
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) &&
(arg0->getType().isFloatingDomain())) {
(arg0->getType().getBasicType() == EbtFloat ||
arg0->getType().getBasicType() == EbtDouble)) {
requireExtensions(loc, 1, &E_GL_EXT_shader_atomic_float, fnCandidate.getName().c_str());
} else if ((callNode.getOp() == EOpAtomicAdd || callNode.getOp() == EOpAtomicExchange ||
callNode.getOp() == EOpAtomicLoad || callNode.getOp() == EOpAtomicStore ||
callNode.getOp() == EOpAtomicMin || callNode.getOp() == EOpAtomicMax) &&
arg0->getType().isFloatingDomain()) {
requireExtensions(loc, 1, &E_GL_EXT_shader_atomic_float2, fnCandidate.getName().c_str());
}
const TIntermTyped* base = TIntermediate::findLValueBase(arg0, true);
@ -2937,7 +3016,8 @@ void TParseContext::reservedErrorCheck(const TSourceLoc& loc, const TString& ide
// "Identifiers starting with "gl_" are reserved for use by OpenGL, and may not be
// declared in a shader; this results in a compile-time error."
if (! symbolTable.atBuiltInLevel()) {
if (builtInName(identifier))
if (builtInName(identifier) && !extensionTurnedOn(E_GL_EXT_spirv_intrinsics))
// The extension GL_EXT_spirv_intrinsics allows us to declare identifiers starting with "gl_".
error(loc, "identifiers starting with \"gl_\" are reserved", identifier.c_str(), "");
// "__" are not supposed to be an error. ES 300 (and desktop) added the clarification:
@ -2945,7 +3025,8 @@ void TParseContext::reservedErrorCheck(const TSourceLoc& loc, const TString& ide
// reserved; using such a name does not itself result in an error, but may result
// in undefined behavior."
// however, before that, ES tests required an error.
if (identifier.find("__") != TString::npos) {
if (identifier.find("__") != TString::npos && !extensionTurnedOn(E_GL_EXT_spirv_intrinsics)) {
// The extension GL_EXT_spirv_intrinsics allows us to declare identifiers starting with "__".
if (isEsProfile() && version < 300)
error(loc, "identifiers containing consecutive underscores (\"__\") are reserved, and an error if version < 300", identifier.c_str(), "");
else
@ -2966,14 +3047,16 @@ void TParseContext::reservedPpErrorCheck(const TSourceLoc& loc, const char* iden
// single underscore) are also reserved, and defining such a name results in a
// compile-time error."
// however, before that, ES tests required an error.
if (strncmp(identifier, "GL_", 3) == 0)
if (strncmp(identifier, "GL_", 3) == 0 && !extensionTurnedOn(E_GL_EXT_spirv_intrinsics))
// The extension GL_EXT_spirv_intrinsics allows us to declare macros prefixed with "GL_".
ppError(loc, "names beginning with \"GL_\" can't be (un)defined:", op, identifier);
else if (strncmp(identifier, "defined", 8) == 0)
if (relaxedErrors())
ppWarn(loc, "\"defined\" is (un)defined:", op, identifier);
else
ppError(loc, "\"defined\" can't be (un)defined:", op, identifier);
else if (strstr(identifier, "__") != 0) {
else if (strstr(identifier, "__") != 0 && !extensionTurnedOn(E_GL_EXT_spirv_intrinsics)) {
// The extension GL_EXT_spirv_intrinsics allows us to declare macros prefixed with "__".
if (isEsProfile() && version >= 300 &&
(strcmp(identifier, "__LINE__") == 0 ||
strcmp(identifier, "__FILE__") == 0 ||
@ -3121,6 +3204,7 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T
bool matrixInMatrix = false;
bool arrayArg = false;
bool floatArgument = false;
bool intArgument = false;
for (int arg = 0; arg < function.getParamCount(); ++arg) {
if (function[arg].type->isArray()) {
if (function[arg].type->isUnsizedArray()) {
@ -3151,6 +3235,8 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T
specConstType = true;
if (function[arg].type->isFloatingDomain())
floatArgument = true;
if (function[arg].type->isIntegerDomain())
intArgument = true;
if (type.isStruct()) {
if (function[arg].type->contains16BitFloat()) {
requireFloat16Arithmetic(loc, "constructor", "can't construct structure containing 16-bit type");
@ -3256,6 +3342,15 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T
// and aren't making an array.
makeSpecConst = ! floatArgument && ! type.isArray();
break;
case EOpConstructVec2:
case EOpConstructVec3:
case EOpConstructVec4:
// This was the list of valid ones, if they aren't converting from int
// and aren't making an array.
makeSpecConst = ! intArgument && !type.isArray();
break;
default:
// anything else wasn't white-listed in the spec as a conversion
makeSpecConst = false;
@ -3588,6 +3683,14 @@ void TParseContext::globalQualifierFixCheck(const TSourceLoc& loc, TQualifier& q
if (!nonuniformOkay && qualifier.isNonUniform())
error(loc, "for non-parameter, can only apply to 'in' or no storage qualifier", "nonuniformEXT", "");
#ifndef GLSLANG_WEB
if (qualifier.isSpirvByReference())
error(loc, "can only apply to parameter", "spirv_by_reference", "");
if (qualifier.isSpirvLiteral())
error(loc, "can only apply to parameter", "spirv_literal", "");
#endif
// Storage qualifier isn't ready for memberQualifierCheck, we should skip invariantCheck for it.
if (!isMemberCheck || structNestingLevel > 0)
invariantCheck(loc, qualifier);
@ -3849,6 +3952,41 @@ void TParseContext::mergeQualifiers(const TSourceLoc& loc, TQualifier& dst, cons
MERGE_SINGLETON(nonUniform);
#endif
#ifndef GLSLANG_WEB
// SPIR-V storage class qualifier (GL_EXT_spirv_intrinsics)
dst.spirvStorageClass = src.spirvStorageClass;
// SPIR-V decorate qualifiers (GL_EXT_spirv_intrinsics)
if (src.hasSprivDecorate()) {
if (dst.hasSprivDecorate()) {
const TSpirvDecorate& srcSpirvDecorate = src.getSpirvDecorate();
TSpirvDecorate& dstSpirvDecorate = dst.getSpirvDecorate();
for (auto& decorate : srcSpirvDecorate.decorates) {
if (dstSpirvDecorate.decorates.find(decorate.first) != dstSpirvDecorate.decorates.end())
error(loc, "too many SPIR-V decorate qualifiers", "spirv_decorate", "(decoration=%u)", decorate.first);
else
dstSpirvDecorate.decorates.insert(decorate);
}
for (auto& decorateId : srcSpirvDecorate.decorateIds) {
if (dstSpirvDecorate.decorateIds.find(decorateId.first) != dstSpirvDecorate.decorateIds.end())
error(loc, "too many SPIR-V decorate qualifiers", "spirv_decorate_id", "(decoration=%u)", decorateId.first);
else
dstSpirvDecorate.decorateIds.insert(decorateId);
}
for (auto& decorateString : srcSpirvDecorate.decorateStrings) {
if (dstSpirvDecorate.decorates.find(decorateString.first) != dstSpirvDecorate.decorates.end())
error(loc, "too many SPIR-V decorate qualifiers", "spirv_decorate_string", "(decoration=%u)", decorateString.first);
else
dstSpirvDecorate.decorates.insert(decorateString);
}
} else {
dst.spirvDecorate = src.spirvDecorate;
}
}
#endif
if (repeated)
error(loc, "replicated qualifiers", "", "");
}
@ -4812,6 +4950,17 @@ void TParseContext::paramCheckFix(const TSourceLoc& loc, const TQualifier& quali
}
if (qualifier.isNonUniform())
type.getQualifier().nonUniform = qualifier.nonUniform;
#ifndef GLSLANG_WEB
if (qualifier.isSpirvByReference())
type.getQualifier().setSpirvByReference();
if (qualifier.isSpirvLiteral()) {
if (type.getBasicType() == EbtFloat || type.getBasicType() == EbtInt || type.getBasicType() == EbtUint ||
type.getBasicType() == EbtBool)
type.getQualifier().setSpirvLiteral();
else
error(loc, "cannot use spirv_literal qualifier", type.getBasicTypeString().c_str(), "");
#endif
}
paramCheckFixStorage(loc, qualifier.storage, type);
}
@ -5879,6 +6028,9 @@ void TParseContext::layoutObjectCheck(const TSourceLoc& loc, const TSymbol& symb
case EvqVaryingIn:
case EvqVaryingOut:
if (!type.getQualifier().isTaskMemory() &&
#ifndef GLSLANG_WEB
!type.getQualifier().hasSprivDecorate() &&
#endif
(type.getBasicType() != EbtBlock ||
(!(*type.getStruct())[0].type->getQualifier().hasLocation() &&
(*type.getStruct())[0].type->getQualifier().builtIn == EbvNone)))
@ -5940,6 +6092,11 @@ void TParseContext::layoutMemberLocationArrayCheck(const TSourceLoc& loc, bool m
// Do layout error checking with respect to a type.
void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type)
{
#ifndef GLSLANG_WEB
if (extensionTurnedOn(E_GL_EXT_spirv_intrinsics))
return; // Skip any check if GL_EXT_spirv_intrinsics is turned on
#endif
const TQualifier& qualifier = type.getQualifier();
// first, intra-layout qualifier-only error checking
@ -7946,6 +8103,10 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con
memberQualifier.perViewNV = currentBlockQualifier.perViewNV;
if (currentBlockQualifier.perTaskNV)
memberQualifier.perTaskNV = currentBlockQualifier.perTaskNV;
if (memberQualifier.storage == EvqSpirvStorageClass)
error(memberLoc, "member cannot have a spirv_storage_class qualifier", memberType.getFieldName().c_str(), "");
if (memberQualifier.hasSprivDecorate() && !memberQualifier.getSpirvDecorate().decorateIds.empty())
error(memberLoc, "member cannot have a spirv_decorate_id qualifier", memberType.getFieldName().c_str(), "");
#endif
if ((currentBlockQualifier.storage == EvqUniform || currentBlockQualifier.storage == EvqBuffer) && (memberQualifier.isInterpolation() || memberQualifier.isAuxiliary()))
error(memberLoc, "member of uniform or buffer block cannot have an auxiliary or interpolation qualifier", memberType.getFieldName().c_str(), "");