Enhance readability of error messages for GLSL
Specifically, make GLSL link error messages more specific and output only information relevant to the error. Also change type printing to more closely reflect GLSL syntax. This is the default for link error messages, but must me enabled with the new option --enhanced-msgs for compilation error messages. Also with --enhanced-msgs, only emit one error message per source line.
This commit is contained in:
parent
c34bb3b6c5
commit
ca0d54d51b
56 changed files with 1055 additions and 374 deletions
|
|
@ -74,6 +74,9 @@ void C_DECL TParseContextBase::error(const TSourceLoc& loc, const char* szReason
|
|||
{
|
||||
if (messages & EShMsgOnlyPreprocessor)
|
||||
return;
|
||||
// If enhanced msg readability, only print one error
|
||||
if (messages & EShMsgEnhanced && numErrors > 0)
|
||||
return;
|
||||
va_list args;
|
||||
va_start(args, szExtraInfoFormat);
|
||||
outputMessage(loc, szReason, szToken, szExtraInfoFormat, EPrefixError, args);
|
||||
|
|
|
|||
|
|
@ -902,8 +902,10 @@ TIntermTyped* TParseContext::handleBinaryMath(const TSourceLoc& loc, const char*
|
|||
result = intermediate.addBinaryMath(op, left, right, loc);
|
||||
}
|
||||
|
||||
if (result == nullptr)
|
||||
binaryOpError(loc, str, left->getCompleteString(), right->getCompleteString());
|
||||
if (result == nullptr) {
|
||||
bool enhanced = intermediate.getEnhancedMsgs();
|
||||
binaryOpError(loc, str, left->getCompleteString(enhanced), right->getCompleteString(enhanced));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
@ -926,8 +928,10 @@ TIntermTyped* TParseContext::handleUnaryMath(const TSourceLoc& loc, const char*
|
|||
|
||||
if (result)
|
||||
return result;
|
||||
else
|
||||
unaryOpError(loc, str, childNode->getCompleteString());
|
||||
else {
|
||||
bool enhanced = intermediate.getEnhancedMsgs();
|
||||
unaryOpError(loc, str, childNode->getCompleteString(enhanced));
|
||||
}
|
||||
|
||||
return childNode;
|
||||
}
|
||||
|
|
@ -953,8 +957,8 @@ TIntermTyped* TParseContext::handleDotDereference(const TSourceLoc& loc, TInterm
|
|||
requireProfile(loc, ~EEsProfile, feature);
|
||||
profileRequires(loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, feature);
|
||||
} else if (!base->getType().isCoopMat()) {
|
||||
error(loc, "does not operate on this type:", field.c_str(), base->getType().getCompleteString().c_str());
|
||||
|
||||
bool enhanced = intermediate.getEnhancedMsgs();
|
||||
error(loc, "does not operate on this type:", field.c_str(), base->getType().getCompleteString(enhanced).c_str());
|
||||
return base;
|
||||
}
|
||||
|
||||
|
|
@ -1005,10 +1009,16 @@ TIntermTyped* TParseContext::handleDotDereference(const TSourceLoc& loc, TInterm
|
|||
intermediate.addIoAccessed(field);
|
||||
}
|
||||
inheritMemoryQualifiers(base->getQualifier(), result->getWritableType().getQualifier());
|
||||
} else
|
||||
error(loc, "no such field in structure", field.c_str(), "");
|
||||
} else {
|
||||
auto baseSymbol = base;
|
||||
while (baseSymbol->getAsSymbolNode() == nullptr)
|
||||
baseSymbol = baseSymbol->getAsBinaryNode()->getLeft();
|
||||
TString structName;
|
||||
structName.append("\'").append(baseSymbol->getAsSymbolNode()->getName().c_str()).append( "\'");
|
||||
error(loc, "no such field in structure", field.c_str(), structName.c_str());
|
||||
}
|
||||
} else
|
||||
error(loc, "does not apply to this type:", field.c_str(), base->getType().getCompleteString().c_str());
|
||||
error(loc, "does not apply to this type:", field.c_str(), base->getType().getCompleteString(intermediate.getEnhancedMsgs()).c_str());
|
||||
|
||||
// Propagate noContraction up the dereference chain
|
||||
if (base->getQualifier().isNoContraction())
|
||||
|
|
@ -1314,7 +1324,7 @@ TIntermTyped* TParseContext::handleFunctionCall(const TSourceLoc& loc, TFunction
|
|||
//
|
||||
result = addConstructor(loc, arguments, type);
|
||||
if (result == nullptr)
|
||||
error(loc, "cannot construct with these arguments", type.getCompleteString().c_str(), "");
|
||||
error(loc, "cannot construct with these arguments", type.getCompleteString(intermediate.getEnhancedMsgs()).c_str(), "");
|
||||
}
|
||||
} else {
|
||||
//
|
||||
|
|
@ -1494,7 +1504,7 @@ TIntermTyped* TParseContext::handleBuiltInFunctionCall(TSourceLoc loc, TIntermNo
|
|||
else
|
||||
error(arguments->getLoc(), " wrong operand type", "Internal Error",
|
||||
"built in unary operator function. Type: %s",
|
||||
static_cast<TIntermTyped*>(arguments)->getCompleteString().c_str());
|
||||
static_cast<TIntermTyped*>(arguments)->getCompleteString(intermediate.getEnhancedMsgs()).c_str());
|
||||
} else if (result->getAsOperator())
|
||||
builtInOpCheck(loc, function, *result->getAsOperator());
|
||||
|
||||
|
|
@ -2599,23 +2609,24 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan
|
|||
// Check that if extended types are being used that the correct extensions are enabled.
|
||||
if (arg0 != nullptr) {
|
||||
const TType& type = arg0->getType();
|
||||
bool enhanced = intermediate.getEnhancedMsgs();
|
||||
switch (type.getBasicType()) {
|
||||
default:
|
||||
break;
|
||||
case EbtInt8:
|
||||
case EbtUint8:
|
||||
requireExtensions(loc, 1, &E_GL_EXT_shader_subgroup_extended_types_int8, type.getCompleteString().c_str());
|
||||
requireExtensions(loc, 1, &E_GL_EXT_shader_subgroup_extended_types_int8, type.getCompleteString(enhanced).c_str());
|
||||
break;
|
||||
case EbtInt16:
|
||||
case EbtUint16:
|
||||
requireExtensions(loc, 1, &E_GL_EXT_shader_subgroup_extended_types_int16, type.getCompleteString().c_str());
|
||||
requireExtensions(loc, 1, &E_GL_EXT_shader_subgroup_extended_types_int16, type.getCompleteString(enhanced).c_str());
|
||||
break;
|
||||
case EbtInt64:
|
||||
case EbtUint64:
|
||||
requireExtensions(loc, 1, &E_GL_EXT_shader_subgroup_extended_types_int64, type.getCompleteString().c_str());
|
||||
requireExtensions(loc, 1, &E_GL_EXT_shader_subgroup_extended_types_int64, type.getCompleteString(enhanced).c_str());
|
||||
break;
|
||||
case EbtFloat16:
|
||||
requireExtensions(loc, 1, &E_GL_EXT_shader_subgroup_extended_types_float16, type.getCompleteString().c_str());
|
||||
requireExtensions(loc, 1, &E_GL_EXT_shader_subgroup_extended_types_float16, type.getCompleteString(enhanced).c_str());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -3198,6 +3209,12 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T
|
|||
break;
|
||||
}
|
||||
|
||||
TString constructorString;
|
||||
if (intermediate.getEnhancedMsgs())
|
||||
constructorString.append(type.getCompleteString(true, false, false, true)).append(" constructor");
|
||||
else
|
||||
constructorString.append("constructor");
|
||||
|
||||
// See if it's a matrix
|
||||
bool constructingMatrix = false;
|
||||
switch (op) {
|
||||
|
|
@ -3255,7 +3272,7 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T
|
|||
if (function[arg].type->isArray()) {
|
||||
if (function[arg].type->isUnsizedArray()) {
|
||||
// Can't construct from an unsized array.
|
||||
error(loc, "array argument must be sized", "constructor", "");
|
||||
error(loc, "array argument must be sized", constructorString.c_str(), "");
|
||||
return true;
|
||||
}
|
||||
arrayArg = true;
|
||||
|
|
@ -3285,13 +3302,13 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T
|
|||
intArgument = true;
|
||||
if (type.isStruct()) {
|
||||
if (function[arg].type->contains16BitFloat()) {
|
||||
requireFloat16Arithmetic(loc, "constructor", "can't construct structure containing 16-bit type");
|
||||
requireFloat16Arithmetic(loc, constructorString.c_str(), "can't construct structure containing 16-bit type");
|
||||
}
|
||||
if (function[arg].type->contains16BitInt()) {
|
||||
requireInt16Arithmetic(loc, "constructor", "can't construct structure containing 16-bit type");
|
||||
requireInt16Arithmetic(loc, constructorString.c_str(), "can't construct structure containing 16-bit type");
|
||||
}
|
||||
if (function[arg].type->contains8BitInt()) {
|
||||
requireInt8Arithmetic(loc, "constructor", "can't construct structure containing 8-bit type");
|
||||
requireInt8Arithmetic(loc, constructorString.c_str(), "can't construct structure containing 8-bit type");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3305,9 +3322,9 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T
|
|||
case EOpConstructF16Vec3:
|
||||
case EOpConstructF16Vec4:
|
||||
if (type.isArray())
|
||||
requireFloat16Arithmetic(loc, "constructor", "16-bit arrays not supported");
|
||||
requireFloat16Arithmetic(loc, constructorString.c_str(), "16-bit arrays not supported");
|
||||
if (type.isVector() && function.getParamCount() != 1)
|
||||
requireFloat16Arithmetic(loc, "constructor", "16-bit vectors only take vector types");
|
||||
requireFloat16Arithmetic(loc, constructorString.c_str(), "16-bit vectors only take vector types");
|
||||
break;
|
||||
case EOpConstructUint16:
|
||||
case EOpConstructU16Vec2:
|
||||
|
|
@ -3318,9 +3335,9 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T
|
|||
case EOpConstructI16Vec3:
|
||||
case EOpConstructI16Vec4:
|
||||
if (type.isArray())
|
||||
requireInt16Arithmetic(loc, "constructor", "16-bit arrays not supported");
|
||||
requireInt16Arithmetic(loc, constructorString.c_str(), "16-bit arrays not supported");
|
||||
if (type.isVector() && function.getParamCount() != 1)
|
||||
requireInt16Arithmetic(loc, "constructor", "16-bit vectors only take vector types");
|
||||
requireInt16Arithmetic(loc, constructorString.c_str(), "16-bit vectors only take vector types");
|
||||
break;
|
||||
case EOpConstructUint8:
|
||||
case EOpConstructU8Vec2:
|
||||
|
|
@ -3331,9 +3348,9 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T
|
|||
case EOpConstructI8Vec3:
|
||||
case EOpConstructI8Vec4:
|
||||
if (type.isArray())
|
||||
requireInt8Arithmetic(loc, "constructor", "8-bit arrays not supported");
|
||||
requireInt8Arithmetic(loc, constructorString.c_str(), "8-bit arrays not supported");
|
||||
if (type.isVector() && function.getParamCount() != 1)
|
||||
requireInt8Arithmetic(loc, "constructor", "8-bit vectors only take vector types");
|
||||
requireInt8Arithmetic(loc, constructorString.c_str(), "8-bit vectors only take vector types");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
@ -3415,7 +3432,7 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T
|
|||
|
||||
if (type.isArray()) {
|
||||
if (function.getParamCount() == 0) {
|
||||
error(loc, "array constructor must have at least one argument", "constructor", "");
|
||||
error(loc, "array constructor must have at least one argument", constructorString.c_str(), "");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -3423,7 +3440,7 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T
|
|||
// auto adapt the constructor type to the number of arguments
|
||||
type.changeOuterArraySize(function.getParamCount());
|
||||
} else if (type.getOuterArraySize() != function.getParamCount()) {
|
||||
error(loc, "array constructor needs one argument per array element", "constructor", "");
|
||||
error(loc, "array constructor needs one argument per array element", constructorString.c_str(), "");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -3436,7 +3453,7 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T
|
|||
// At least the dimensionalities have to match.
|
||||
if (! function[0].type->isArray() ||
|
||||
arraySizes.getNumDims() != function[0].type->getArraySizes()->getNumDims() + 1) {
|
||||
error(loc, "array constructor argument not correct type to construct array element", "constructor", "");
|
||||
error(loc, "array constructor argument not correct type to construct array element", constructorString.c_str(), "");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -3453,7 +3470,7 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T
|
|||
}
|
||||
|
||||
if (arrayArg && op != EOpConstructStruct && ! type.isArrayOfArrays()) {
|
||||
error(loc, "constructing non-array constituent from array argument", "constructor", "");
|
||||
error(loc, "constructing non-array constituent from array argument", constructorString.c_str(), "");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -3463,51 +3480,51 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T
|
|||
// "If a matrix argument is given to a matrix constructor,
|
||||
// it is a compile-time error to have any other arguments."
|
||||
if (function.getParamCount() != 1)
|
||||
error(loc, "matrix constructed from matrix can only have one argument", "constructor", "");
|
||||
error(loc, "matrix constructed from matrix can only have one argument", constructorString.c_str(), "");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (overFull) {
|
||||
error(loc, "too many arguments", "constructor", "");
|
||||
error(loc, "too many arguments", constructorString.c_str(), "");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (op == EOpConstructStruct && ! type.isArray() && (int)type.getStruct()->size() != function.getParamCount()) {
|
||||
error(loc, "Number of constructor parameters does not match the number of structure fields", "constructor", "");
|
||||
error(loc, "Number of constructor parameters does not match the number of structure fields", constructorString.c_str(), "");
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((op != EOpConstructStruct && size != 1 && size < type.computeNumComponents()) ||
|
||||
(op == EOpConstructStruct && size < type.computeNumComponents())) {
|
||||
error(loc, "not enough data provided for construction", "constructor", "");
|
||||
error(loc, "not enough data provided for construction", constructorString.c_str(), "");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (type.isCoopMat() && function.getParamCount() != 1) {
|
||||
error(loc, "wrong number of arguments", "constructor", "");
|
||||
error(loc, "wrong number of arguments", constructorString.c_str(), "");
|
||||
return true;
|
||||
}
|
||||
if (type.isCoopMat() &&
|
||||
!(function[0].type->isScalar() || function[0].type->isCoopMat())) {
|
||||
error(loc, "Cooperative matrix constructor argument must be scalar or cooperative matrix", "constructor", "");
|
||||
error(loc, "Cooperative matrix constructor argument must be scalar or cooperative matrix", constructorString.c_str(), "");
|
||||
return true;
|
||||
}
|
||||
|
||||
TIntermTyped* typed = node->getAsTyped();
|
||||
if (typed == nullptr) {
|
||||
error(loc, "constructor argument does not have a type", "constructor", "");
|
||||
error(loc, "constructor argument does not have a type", constructorString.c_str(), "");
|
||||
return true;
|
||||
}
|
||||
if (op != EOpConstructStruct && op != EOpConstructNonuniform && typed->getBasicType() == EbtSampler) {
|
||||
error(loc, "cannot convert a sampler", "constructor", "");
|
||||
error(loc, "cannot convert a sampler", constructorString.c_str(), "");
|
||||
return true;
|
||||
}
|
||||
if (op != EOpConstructStruct && typed->isAtomic()) {
|
||||
error(loc, "cannot convert an atomic_uint", "constructor", "");
|
||||
error(loc, "cannot convert an atomic_uint", constructorString.c_str(), "");
|
||||
return true;
|
||||
}
|
||||
if (typed->getBasicType() == EbtVoid) {
|
||||
error(loc, "cannot convert a void", "constructor", "");
|
||||
error(loc, "cannot convert a void", constructorString.c_str(), "");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -7430,14 +7447,14 @@ TIntermNode* TParseContext::executeInitializer(const TSourceLoc& loc, TIntermTyp
|
|||
// Uniforms require a compile-time constant initializer
|
||||
if (qualifier == EvqUniform && ! initializer->getType().getQualifier().isFrontEndConstant()) {
|
||||
error(loc, "uniform initializers must be constant", "=", "'%s'",
|
||||
variable->getType().getCompleteString().c_str());
|
||||
variable->getType().getCompleteString(intermediate.getEnhancedMsgs()).c_str());
|
||||
variable->getWritableType().getQualifier().makeTemporary();
|
||||
return nullptr;
|
||||
}
|
||||
// Global consts require a constant initializer (specialization constant is okay)
|
||||
if (qualifier == EvqConst && symbolTable.atGlobalLevel() && ! initializer->getType().getQualifier().isConstant()) {
|
||||
error(loc, "global const initializers must be constant", "=", "'%s'",
|
||||
variable->getType().getCompleteString().c_str());
|
||||
variable->getType().getCompleteString(intermediate.getEnhancedMsgs()).c_str());
|
||||
variable->getWritableType().getQualifier().makeTemporary();
|
||||
return nullptr;
|
||||
}
|
||||
|
|
@ -7500,7 +7517,7 @@ TIntermNode* TParseContext::executeInitializer(const TSourceLoc& loc, TIntermTyp
|
|||
TIntermSymbol* intermSymbol = intermediate.addSymbol(*variable, loc);
|
||||
TIntermTyped* initNode = intermediate.addAssign(EOpAssign, intermSymbol, initializer, loc);
|
||||
if (! initNode)
|
||||
assignError(loc, "=", intermSymbol->getCompleteString(), initializer->getCompleteString());
|
||||
assignError(loc, "=", intermSymbol->getCompleteString(intermediate.getEnhancedMsgs()), initializer->getCompleteString(intermediate.getEnhancedMsgs()));
|
||||
|
||||
return initNode;
|
||||
}
|
||||
|
|
@ -7571,7 +7588,7 @@ TIntermTyped* TParseContext::convertInitializerList(const TSourceLoc& loc, const
|
|||
}
|
||||
} else if (type.isMatrix()) {
|
||||
if (type.getMatrixCols() != (int)initList->getSequence().size()) {
|
||||
error(loc, "wrong number of matrix columns:", "initializer list", type.getCompleteString().c_str());
|
||||
error(loc, "wrong number of matrix columns:", "initializer list", type.getCompleteString(intermediate.getEnhancedMsgs()).c_str());
|
||||
return nullptr;
|
||||
}
|
||||
TType vectorType(type, 0); // dereferenced type
|
||||
|
|
@ -7582,20 +7599,20 @@ TIntermTyped* TParseContext::convertInitializerList(const TSourceLoc& loc, const
|
|||
}
|
||||
} else if (type.isVector()) {
|
||||
if (type.getVectorSize() != (int)initList->getSequence().size()) {
|
||||
error(loc, "wrong vector size (or rows in a matrix column):", "initializer list", type.getCompleteString().c_str());
|
||||
error(loc, "wrong vector size (or rows in a matrix column):", "initializer list", type.getCompleteString(intermediate.getEnhancedMsgs()).c_str());
|
||||
return nullptr;
|
||||
}
|
||||
TBasicType destType = type.getBasicType();
|
||||
for (int i = 0; i < type.getVectorSize(); ++i) {
|
||||
TBasicType initType = initList->getSequence()[i]->getAsTyped()->getBasicType();
|
||||
if (destType != initType && !intermediate.canImplicitlyPromote(initType, destType)) {
|
||||
error(loc, "type mismatch in initializer list", "initializer list", type.getCompleteString().c_str());
|
||||
error(loc, "type mismatch in initializer list", "initializer list", type.getCompleteString(intermediate.getEnhancedMsgs()).c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
error(loc, "unexpected initializer-list type:", "initializer list", type.getCompleteString().c_str());
|
||||
error(loc, "unexpected initializer-list type:", "initializer list", type.getCompleteString(intermediate.getEnhancedMsgs()).c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
@ -8103,8 +8120,9 @@ TIntermTyped* TParseContext::constructAggregate(TIntermNode* node, const TType&
|
|||
{
|
||||
TIntermTyped* converted = intermediate.addConversion(EOpConstructStruct, type, node->getAsTyped());
|
||||
if (! converted || converted->getType() != type) {
|
||||
bool enhanced = intermediate.getEnhancedMsgs();
|
||||
error(loc, "", "constructor", "cannot convert parameter %d from '%s' to '%s'", paramCount,
|
||||
node->getAsTyped()->getType().getCompleteString().c_str(), type.getCompleteString().c_str());
|
||||
node->getAsTyped()->getType().getCompleteString(enhanced).c_str(), type.getCompleteString(enhanced).c_str());
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1830,6 +1830,7 @@ void TShader::setUniqueId(unsigned long long id)
|
|||
|
||||
void TShader::setInvertY(bool invert) { intermediate->setInvertY(invert); }
|
||||
void TShader::setDxPositionW(bool invert) { intermediate->setDxPositionW(invert); }
|
||||
void TShader::setEnhancedMsgs() { intermediate->setEnhancedMsgs(); }
|
||||
void TShader::setNanMinMaxClamp(bool useNonNan) { intermediate->setNanMinMaxClamp(useNonNan); }
|
||||
|
||||
#ifndef GLSLANG_WEB
|
||||
|
|
@ -2049,6 +2050,8 @@ bool TProgram::linkStage(EShLanguage stage, EShMessages messages)
|
|||
firstIntermediate->getVersion(),
|
||||
firstIntermediate->getProfile());
|
||||
intermediate[stage]->setLimits(firstIntermediate->getLimits());
|
||||
if (firstIntermediate->getEnhancedMsgs())
|
||||
intermediate[stage]->setEnhancedMsgs();
|
||||
|
||||
// The new TIntermediate must use the same origin as the original TIntermediates.
|
||||
// Otherwise linking will fail due to different coordinate systems.
|
||||
|
|
|
|||
|
|
@ -798,7 +798,7 @@ conditional_expression
|
|||
parseContext.rValueErrorCheck($5.loc, ":", $6);
|
||||
$$ = parseContext.intermediate.addSelection($1, $4, $6, $2.loc);
|
||||
if ($$ == 0) {
|
||||
parseContext.binaryOpError($2.loc, ":", $4->getCompleteString(), $6->getCompleteString());
|
||||
parseContext.binaryOpError($2.loc, ":", $4->getCompleteString(parseContext.intermediate.getEnhancedMsgs()), $6->getCompleteString(parseContext.intermediate.getEnhancedMsgs()));
|
||||
$$ = $6;
|
||||
}
|
||||
}
|
||||
|
|
@ -815,7 +815,7 @@ assignment_expression
|
|||
parseContext.rValueErrorCheck($2.loc, "assign", $3);
|
||||
$$ = parseContext.addAssign($2.loc, $2.op, $1, $3);
|
||||
if ($$ == 0) {
|
||||
parseContext.assignError($2.loc, "assign", $1->getCompleteString(), $3->getCompleteString());
|
||||
parseContext.assignError($2.loc, "assign", $1->getCompleteString(parseContext.intermediate.getEnhancedMsgs()), $3->getCompleteString(parseContext.intermediate.getEnhancedMsgs()));
|
||||
$$ = $1;
|
||||
}
|
||||
}
|
||||
|
|
@ -877,7 +877,7 @@ expression
|
|||
parseContext.samplerConstructorLocationCheck($2.loc, ",", $3);
|
||||
$$ = parseContext.intermediate.addComma($1, $3, $2.loc);
|
||||
if ($$ == 0) {
|
||||
parseContext.binaryOpError($2.loc, ",", $1->getCompleteString(), $3->getCompleteString());
|
||||
parseContext.binaryOpError($2.loc, ",", $1->getCompleteString(parseContext.intermediate.getEnhancedMsgs()), $3->getCompleteString(parseContext.intermediate.getEnhancedMsgs()));
|
||||
$$ = $3;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -798,7 +798,7 @@ conditional_expression
|
|||
parseContext.rValueErrorCheck($5.loc, ":", $6);
|
||||
$$ = parseContext.intermediate.addSelection($1, $4, $6, $2.loc);
|
||||
if ($$ == 0) {
|
||||
parseContext.binaryOpError($2.loc, ":", $4->getCompleteString(), $6->getCompleteString());
|
||||
parseContext.binaryOpError($2.loc, ":", $4->getCompleteString(parseContext.intermediate.getEnhancedMsgs()), $6->getCompleteString(parseContext.intermediate.getEnhancedMsgs()));
|
||||
$$ = $6;
|
||||
}
|
||||
}
|
||||
|
|
@ -815,7 +815,7 @@ assignment_expression
|
|||
parseContext.rValueErrorCheck($2.loc, "assign", $3);
|
||||
$$ = parseContext.addAssign($2.loc, $2.op, $1, $3);
|
||||
if ($$ == 0) {
|
||||
parseContext.assignError($2.loc, "assign", $1->getCompleteString(), $3->getCompleteString());
|
||||
parseContext.assignError($2.loc, "assign", $1->getCompleteString(parseContext.intermediate.getEnhancedMsgs()), $3->getCompleteString(parseContext.intermediate.getEnhancedMsgs()));
|
||||
$$ = $1;
|
||||
}
|
||||
}
|
||||
|
|
@ -877,7 +877,7 @@ expression
|
|||
parseContext.samplerConstructorLocationCheck($2.loc, ",", $3);
|
||||
$$ = parseContext.intermediate.addComma($1, $3, $2.loc);
|
||||
if ($$ == 0) {
|
||||
parseContext.binaryOpError($2.loc, ",", $1->getCompleteString(), $3->getCompleteString());
|
||||
parseContext.binaryOpError($2.loc, ",", $1->getCompleteString(parseContext.intermediate.getEnhancedMsgs()), $3->getCompleteString(parseContext.intermediate.getEnhancedMsgs()));
|
||||
$$ = $3;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5878,7 +5878,7 @@ yyreduce:
|
|||
parseContext.rValueErrorCheck((yyvsp[-1].lex).loc, ":", (yyvsp[0].interm.intermTypedNode));
|
||||
(yyval.interm.intermTypedNode) = parseContext.intermediate.addSelection((yyvsp[-5].interm.intermTypedNode), (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yyvsp[-4].lex).loc);
|
||||
if ((yyval.interm.intermTypedNode) == 0) {
|
||||
parseContext.binaryOpError((yyvsp[-4].lex).loc, ":", (yyvsp[-2].interm.intermTypedNode)->getCompleteString(), (yyvsp[0].interm.intermTypedNode)->getCompleteString());
|
||||
parseContext.binaryOpError((yyvsp[-4].lex).loc, ":", (yyvsp[-2].interm.intermTypedNode)->getCompleteString(parseContext.intermediate.getEnhancedMsgs()), (yyvsp[0].interm.intermTypedNode)->getCompleteString(parseContext.intermediate.getEnhancedMsgs()));
|
||||
(yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
|
||||
}
|
||||
}
|
||||
|
|
@ -5902,7 +5902,7 @@ yyreduce:
|
|||
parseContext.rValueErrorCheck((yyvsp[-1].interm).loc, "assign", (yyvsp[0].interm.intermTypedNode));
|
||||
(yyval.interm.intermTypedNode) = parseContext.addAssign((yyvsp[-1].interm).loc, (yyvsp[-1].interm).op, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
|
||||
if ((yyval.interm.intermTypedNode) == 0) {
|
||||
parseContext.assignError((yyvsp[-1].interm).loc, "assign", (yyvsp[-2].interm.intermTypedNode)->getCompleteString(), (yyvsp[0].interm.intermTypedNode)->getCompleteString());
|
||||
parseContext.assignError((yyvsp[-1].interm).loc, "assign", (yyvsp[-2].interm.intermTypedNode)->getCompleteString(parseContext.intermediate.getEnhancedMsgs()), (yyvsp[0].interm.intermTypedNode)->getCompleteString(parseContext.intermediate.getEnhancedMsgs()));
|
||||
(yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode);
|
||||
}
|
||||
}
|
||||
|
|
@ -6023,7 +6023,7 @@ yyreduce:
|
|||
parseContext.samplerConstructorLocationCheck((yyvsp[-1].lex).loc, ",", (yyvsp[0].interm.intermTypedNode));
|
||||
(yyval.interm.intermTypedNode) = parseContext.intermediate.addComma((yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yyvsp[-1].lex).loc);
|
||||
if ((yyval.interm.intermTypedNode) == 0) {
|
||||
parseContext.binaryOpError((yyvsp[-1].lex).loc, ",", (yyvsp[-2].interm.intermTypedNode)->getCompleteString(), (yyvsp[0].interm.intermTypedNode)->getCompleteString());
|
||||
parseContext.binaryOpError((yyvsp[-1].lex).loc, ",", (yyvsp[-2].interm.intermTypedNode)->getCompleteString(parseContext.intermediate.getEnhancedMsgs()), (yyvsp[0].interm.intermTypedNode)->getCompleteString(parseContext.intermediate.getEnhancedMsgs()));
|
||||
(yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,22 +55,28 @@ namespace glslang {
|
|||
//
|
||||
// Link-time error emitter.
|
||||
//
|
||||
void TIntermediate::error(TInfoSink& infoSink, const char* message)
|
||||
void TIntermediate::error(TInfoSink& infoSink, const char* message, EShLanguage unitStage)
|
||||
{
|
||||
#ifndef GLSLANG_WEB
|
||||
infoSink.info.prefix(EPrefixError);
|
||||
infoSink.info << "Linking " << StageName(language) << " stage: " << message << "\n";
|
||||
if (unitStage < EShLangCount)
|
||||
infoSink.info << "Linking " << StageName(getStage()) << " and " << StageName(unitStage) << " stages: " << message << "\n";
|
||||
else
|
||||
infoSink.info << "Linking " << StageName(language) << " stage: " << message << "\n";
|
||||
#endif
|
||||
|
||||
++numErrors;
|
||||
}
|
||||
|
||||
// Link-time warning.
|
||||
void TIntermediate::warn(TInfoSink& infoSink, const char* message)
|
||||
void TIntermediate::warn(TInfoSink& infoSink, const char* message, EShLanguage unitStage)
|
||||
{
|
||||
#ifndef GLSLANG_WEB
|
||||
infoSink.info.prefix(EPrefixWarning);
|
||||
infoSink.info << "Linking " << StageName(language) << " stage: " << message << "\n";
|
||||
if (unitStage < EShLangCount)
|
||||
infoSink.info << "Linking " << StageName(language) << " and " << StageName(unitStage) << " stages: " << message << "\n";
|
||||
else
|
||||
infoSink.info << "Linking " << StageName(language) << " stage: " << message << "\n";
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -819,6 +825,10 @@ void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& sy
|
|||
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
|
||||
bool crossStage = getStage() != unitStage;
|
||||
bool writeTypeComparison = false;
|
||||
bool errorReported = false;
|
||||
bool printQualifiers = false;
|
||||
bool printPrecision = false;
|
||||
bool printType = false;
|
||||
|
||||
// Types have to match
|
||||
{
|
||||
|
|
@ -850,11 +860,48 @@ void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& sy
|
|||
(symbol.getType().isUnsizedArray() || unitSymbol.getType().isUnsizedArray()));
|
||||
}
|
||||
|
||||
if (!symbol.getType().sameElementType(unitSymbol.getType()) ||
|
||||
!symbol.getType().sameTypeParameters(unitSymbol.getType()) ||
|
||||
!arraysMatch ) {
|
||||
int lpidx = -1;
|
||||
int rpidx = -1;
|
||||
if (!symbol.getType().sameElementType(unitSymbol.getType(), &lpidx, &rpidx)) {
|
||||
if (lpidx >= 0 && rpidx >= 0) {
|
||||
error(infoSink, "Member names and types must match:", unitStage);
|
||||
infoSink.info << " Block: " << symbol.getType().getTypeName() << "\n";
|
||||
infoSink.info << " " << StageName(getStage()) << " stage: \""
|
||||
<< (*symbol.getType().getStruct())[lpidx].type->getCompleteString(true, false, false, true,
|
||||
(*symbol.getType().getStruct())[lpidx].type->getFieldName()) << "\"\n";
|
||||
infoSink.info << " " << StageName(unitStage) << " stage: \""
|
||||
<< (*unitSymbol.getType().getStruct())[rpidx].type->getCompleteString(true, false, false, true,
|
||||
(*unitSymbol.getType().getStruct())[rpidx].type->getFieldName()) << "\"\n";
|
||||
errorReported = true;
|
||||
} else if (lpidx >= 0 && rpidx == -1) {
|
||||
TString errmsg = StageName(getStage());
|
||||
errmsg.append(" block member has no corresponding member in ").append(StageName(unitStage)).append(" block:");
|
||||
error(infoSink, errmsg.c_str(), unitStage);
|
||||
infoSink.info << " " << StageName(getStage()) << " stage: Block: " << symbol.getType().getTypeName() << ", Member: "
|
||||
<< (*symbol.getType().getStruct())[lpidx].type->getFieldName() << "\n";
|
||||
infoSink.info << " " << StageName(unitStage) << " stage: Block: " << unitSymbol.getType().getTypeName() << ", Member: n/a \n";
|
||||
errorReported = true;
|
||||
} else if (lpidx == -1 && rpidx >= 0) {
|
||||
TString errmsg = StageName(unitStage);
|
||||
errmsg.append(" block member has no corresponding member in ").append(StageName(getStage())).append(" block:");
|
||||
error(infoSink, errmsg.c_str(), unitStage);
|
||||
infoSink.info << " " << StageName(unitStage) << " stage: Block: " << unitSymbol.getType().getTypeName() << ", Member: "
|
||||
<< (*unitSymbol.getType().getStruct())[rpidx].type->getFieldName() << "\n";
|
||||
infoSink.info << " " << StageName(getStage()) << " stage: Block: " << symbol.getType().getTypeName() << ", Member: n/a \n";
|
||||
errorReported = true;
|
||||
} else {
|
||||
error(infoSink, "Types must match:", unitStage);
|
||||
writeTypeComparison = true;
|
||||
printType = true;
|
||||
}
|
||||
} else if (!arraysMatch) {
|
||||
error(infoSink, "Array sizes must be compatible:", unitStage);
|
||||
writeTypeComparison = true;
|
||||
error(infoSink, "Types must match:");
|
||||
printType = true;
|
||||
} else if (!symbol.getType().sameTypeParameters(unitSymbol.getType())) {
|
||||
error(infoSink, "Type parameters must match:", unitStage);
|
||||
writeTypeComparison = true;
|
||||
printType = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -875,13 +922,35 @@ void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& sy
|
|||
}
|
||||
const TQualifier& qualifier = (*symbol.getType().getStruct())[li].type->getQualifier();
|
||||
const TQualifier & unitQualifier = (*unitSymbol.getType().getStruct())[ri].type->getQualifier();
|
||||
if (qualifier.layoutMatrix != unitQualifier.layoutMatrix ||
|
||||
qualifier.layoutOffset != unitQualifier.layoutOffset ||
|
||||
qualifier.layoutAlign != unitQualifier.layoutAlign ||
|
||||
qualifier.layoutLocation != unitQualifier.layoutLocation ||
|
||||
qualifier.layoutComponent != unitQualifier.layoutComponent) {
|
||||
error(infoSink, "Interface block member layout qualifiers must match:");
|
||||
writeTypeComparison = true;
|
||||
bool layoutQualifierError = false;
|
||||
if (qualifier.layoutMatrix != unitQualifier.layoutMatrix) {
|
||||
error(infoSink, "Interface block member layout matrix qualifier must match:", unitStage);
|
||||
layoutQualifierError = true;
|
||||
}
|
||||
if (qualifier.layoutOffset != unitQualifier.layoutOffset) {
|
||||
error(infoSink, "Interface block member layout offset qualifier must match:", unitStage);
|
||||
layoutQualifierError = true;
|
||||
}
|
||||
if (qualifier.layoutAlign != unitQualifier.layoutAlign) {
|
||||
error(infoSink, "Interface block member layout align qualifier must match:", unitStage);
|
||||
layoutQualifierError = true;
|
||||
}
|
||||
if (qualifier.layoutLocation != unitQualifier.layoutLocation) {
|
||||
error(infoSink, "Interface block member layout location qualifier must match:", unitStage);
|
||||
layoutQualifierError = true;
|
||||
}
|
||||
if (qualifier.layoutComponent != unitQualifier.layoutComponent) {
|
||||
error(infoSink, "Interface block member layout component qualifier must match:", unitStage);
|
||||
layoutQualifierError = true;
|
||||
}
|
||||
if (layoutQualifierError) {
|
||||
infoSink.info << " " << StageName(getStage()) << " stage: Block: " << symbol.getType().getTypeName() << ", Member: "
|
||||
<< (*symbol.getType().getStruct())[li].type->getFieldName() << " \""
|
||||
<< (*symbol.getType().getStruct())[li].type->getCompleteString(true, true, false, false) << "\"\n";
|
||||
infoSink.info << " " << StageName(unitStage) << " stage: Block: " << unitSymbol.getType().getTypeName() << ", Member: "
|
||||
<< (*unitSymbol.getType().getStruct())[ri].type->getFieldName() << " \""
|
||||
<< (*unitSymbol.getType().getStruct())[ri].type->getCompleteString(true, true, false, false) << "\"\n";
|
||||
errorReported = true;
|
||||
}
|
||||
++li;
|
||||
++ri;
|
||||
|
|
@ -895,8 +964,9 @@ void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& sy
|
|||
// Qualifiers have to (almost) match
|
||||
// Storage...
|
||||
if (!isInOut && symbol.getQualifier().storage != unitSymbol.getQualifier().storage) {
|
||||
error(infoSink, "Storage qualifiers must match:");
|
||||
error(infoSink, "Storage qualifiers must match:", unitStage);
|
||||
writeTypeComparison = true;
|
||||
printQualifiers = true;
|
||||
}
|
||||
|
||||
// Uniform and buffer blocks must either both have an instance name, or
|
||||
|
|
@ -904,33 +974,36 @@ void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& sy
|
|||
if (symbol.getQualifier().isUniformOrBuffer() &&
|
||||
(IsAnonymous(symbol.getName()) != IsAnonymous(unitSymbol.getName()))) {
|
||||
error(infoSink, "Matched Uniform or Storage blocks must all be anonymous,"
|
||||
" or all be named:");
|
||||
" or all be named:", unitStage);
|
||||
writeTypeComparison = true;
|
||||
}
|
||||
|
||||
if (symbol.getQualifier().storage == unitSymbol.getQualifier().storage &&
|
||||
(IsAnonymous(symbol.getName()) != IsAnonymous(unitSymbol.getName()) ||
|
||||
(!IsAnonymous(symbol.getName()) && symbol.getName() != unitSymbol.getName()))) {
|
||||
warn(infoSink, "Matched shader interfaces are using different instance names.");
|
||||
warn(infoSink, "Matched shader interfaces are using different instance names.", unitStage);
|
||||
writeTypeComparison = true;
|
||||
}
|
||||
|
||||
// Precision...
|
||||
if (!isInOut && symbol.getQualifier().precision != unitSymbol.getQualifier().precision) {
|
||||
error(infoSink, "Precision qualifiers must match:");
|
||||
error(infoSink, "Precision qualifiers must match:", unitStage);
|
||||
writeTypeComparison = true;
|
||||
printPrecision = true;
|
||||
}
|
||||
|
||||
// Invariance...
|
||||
if (! crossStage && symbol.getQualifier().invariant != unitSymbol.getQualifier().invariant) {
|
||||
error(infoSink, "Presence of invariant qualifier must match:");
|
||||
error(infoSink, "Presence of invariant qualifier must match:", unitStage);
|
||||
writeTypeComparison = true;
|
||||
printQualifiers = true;
|
||||
}
|
||||
|
||||
// Precise...
|
||||
if (! crossStage && symbol.getQualifier().isNoContraction() != unitSymbol.getQualifier().isNoContraction()) {
|
||||
error(infoSink, "Presence of precise qualifier must match:");
|
||||
error(infoSink, "Presence of precise qualifier must match:", unitStage);
|
||||
writeTypeComparison = true;
|
||||
printPrecision = true;
|
||||
}
|
||||
|
||||
// Auxiliary and interpolation...
|
||||
|
|
@ -944,57 +1017,137 @@ void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& sy
|
|||
symbol.getQualifier().isSample()!= unitSymbol.getQualifier().isSample() ||
|
||||
symbol.getQualifier().isPatch() != unitSymbol.getQualifier().isPatch() ||
|
||||
symbol.getQualifier().isNonPerspective() != unitSymbol.getQualifier().isNonPerspective())) {
|
||||
error(infoSink, "Interpolation and auxiliary storage qualifiers must match:");
|
||||
error(infoSink, "Interpolation and auxiliary storage qualifiers must match:", unitStage);
|
||||
writeTypeComparison = true;
|
||||
printQualifiers = true;
|
||||
}
|
||||
|
||||
// Memory...
|
||||
if (symbol.getQualifier().coherent != unitSymbol.getQualifier().coherent ||
|
||||
symbol.getQualifier().devicecoherent != unitSymbol.getQualifier().devicecoherent ||
|
||||
symbol.getQualifier().queuefamilycoherent != unitSymbol.getQualifier().queuefamilycoherent ||
|
||||
symbol.getQualifier().workgroupcoherent != unitSymbol.getQualifier().workgroupcoherent ||
|
||||
symbol.getQualifier().subgroupcoherent != unitSymbol.getQualifier().subgroupcoherent ||
|
||||
symbol.getQualifier().shadercallcoherent!= unitSymbol.getQualifier().shadercallcoherent ||
|
||||
symbol.getQualifier().nonprivate != unitSymbol.getQualifier().nonprivate ||
|
||||
symbol.getQualifier().volatil != unitSymbol.getQualifier().volatil ||
|
||||
symbol.getQualifier().restrict != unitSymbol.getQualifier().restrict ||
|
||||
symbol.getQualifier().readonly != unitSymbol.getQualifier().readonly ||
|
||||
symbol.getQualifier().writeonly != unitSymbol.getQualifier().writeonly) {
|
||||
error(infoSink, "Memory qualifiers must match:");
|
||||
writeTypeComparison = true;
|
||||
bool memoryQualifierError = false;
|
||||
if (symbol.getQualifier().coherent != unitSymbol.getQualifier().coherent) {
|
||||
error(infoSink, "Memory coherent qualifier must match:", unitStage);
|
||||
memoryQualifierError = true;
|
||||
}
|
||||
if (symbol.getQualifier().devicecoherent != unitSymbol.getQualifier().devicecoherent) {
|
||||
error(infoSink, "Memory devicecoherent qualifier must match:", unitStage);
|
||||
memoryQualifierError = true;
|
||||
}
|
||||
if (symbol.getQualifier().queuefamilycoherent != unitSymbol.getQualifier().queuefamilycoherent) {
|
||||
error(infoSink, "Memory queuefamilycoherent qualifier must match:", unitStage);
|
||||
memoryQualifierError = true;
|
||||
}
|
||||
if (symbol.getQualifier().workgroupcoherent != unitSymbol.getQualifier().workgroupcoherent) {
|
||||
error(infoSink, "Memory workgroupcoherent qualifier must match:", unitStage);
|
||||
memoryQualifierError = true;
|
||||
}
|
||||
if (symbol.getQualifier().subgroupcoherent != unitSymbol.getQualifier().subgroupcoherent) {
|
||||
error(infoSink, "Memory subgroupcoherent qualifier must match:", unitStage);
|
||||
memoryQualifierError = true;
|
||||
}
|
||||
if (symbol.getQualifier().shadercallcoherent != unitSymbol.getQualifier().shadercallcoherent) {
|
||||
error(infoSink, "Memory shadercallcoherent qualifier must match:", unitStage);
|
||||
memoryQualifierError = true;
|
||||
}
|
||||
if (symbol.getQualifier().nonprivate != unitSymbol.getQualifier().nonprivate) {
|
||||
error(infoSink, "Memory nonprivate qualifier must match:", unitStage);
|
||||
memoryQualifierError = true;
|
||||
}
|
||||
if (symbol.getQualifier().volatil != unitSymbol.getQualifier().volatil) {
|
||||
error(infoSink, "Memory volatil qualifier must match:", unitStage);
|
||||
memoryQualifierError = true;
|
||||
}
|
||||
if (symbol.getQualifier().restrict != unitSymbol.getQualifier().restrict) {
|
||||
error(infoSink, "Memory restrict qualifier must match:", unitStage);
|
||||
memoryQualifierError = true;
|
||||
}
|
||||
if (symbol.getQualifier().readonly != unitSymbol.getQualifier().readonly) {
|
||||
error(infoSink, "Memory readonly qualifier must match:", unitStage);
|
||||
memoryQualifierError = true;
|
||||
}
|
||||
if (symbol.getQualifier().writeonly != unitSymbol.getQualifier().writeonly) {
|
||||
error(infoSink, "Memory writeonly qualifier must match:", unitStage);
|
||||
memoryQualifierError = true;
|
||||
}
|
||||
if (memoryQualifierError) {
|
||||
writeTypeComparison = true;
|
||||
printQualifiers = true;
|
||||
}
|
||||
|
||||
// Layouts...
|
||||
// TODO: 4.4 enhanced layouts: Generalize to include offset/align: current spec
|
||||
// requires separate user-supplied offset from actual computed offset, but
|
||||
// current implementation only has one offset.
|
||||
if (symbol.getQualifier().layoutMatrix != unitSymbol.getQualifier().layoutMatrix ||
|
||||
symbol.getQualifier().layoutPacking != unitSymbol.getQualifier().layoutPacking ||
|
||||
(symbol.getQualifier().hasLocation() && unitSymbol.getQualifier().hasLocation() && symbol.getQualifier().layoutLocation != unitSymbol.getQualifier().layoutLocation) ||
|
||||
symbol.getQualifier().layoutComponent != unitSymbol.getQualifier().layoutComponent ||
|
||||
symbol.getQualifier().layoutIndex != unitSymbol.getQualifier().layoutIndex ||
|
||||
(symbol.getQualifier().hasBinding() && unitSymbol.getQualifier().hasBinding() && symbol.getQualifier().layoutBinding != unitSymbol.getQualifier().layoutBinding) ||
|
||||
(symbol.getQualifier().hasBinding() && (symbol.getQualifier().layoutOffset != unitSymbol.getQualifier().layoutOffset))) {
|
||||
error(infoSink, "Layout qualification must match:");
|
||||
bool layoutQualifierError = false;
|
||||
if (symbol.getQualifier().layoutMatrix != unitSymbol.getQualifier().layoutMatrix) {
|
||||
error(infoSink, "Layout matrix qualifier must match:", unitStage);
|
||||
layoutQualifierError = true;
|
||||
}
|
||||
if (symbol.getQualifier().layoutPacking != unitSymbol.getQualifier().layoutPacking) {
|
||||
error(infoSink, "Layout packing qualifier must match:", unitStage);
|
||||
layoutQualifierError = true;
|
||||
}
|
||||
if (symbol.getQualifier().hasLocation() && unitSymbol.getQualifier().hasLocation() && symbol.getQualifier().layoutLocation != unitSymbol.getQualifier().layoutLocation) {
|
||||
error(infoSink, "Layout location qualifier must match:", unitStage);
|
||||
layoutQualifierError = true;
|
||||
}
|
||||
if (symbol.getQualifier().layoutComponent != unitSymbol.getQualifier().layoutComponent) {
|
||||
error(infoSink, "Layout component qualifier must match:", unitStage);
|
||||
layoutQualifierError = true;
|
||||
}
|
||||
if (symbol.getQualifier().layoutIndex != unitSymbol.getQualifier().layoutIndex) {
|
||||
error(infoSink, "Layout index qualifier must match:", unitStage);
|
||||
layoutQualifierError = true;
|
||||
}
|
||||
if (symbol.getQualifier().hasBinding() && unitSymbol.getQualifier().hasBinding() && symbol.getQualifier().layoutBinding != unitSymbol.getQualifier().layoutBinding) {
|
||||
error(infoSink, "Layout binding qualifier must match:", unitStage);
|
||||
layoutQualifierError = true;
|
||||
}
|
||||
if (symbol.getQualifier().hasBinding() && (symbol.getQualifier().layoutOffset != unitSymbol.getQualifier().layoutOffset)) {
|
||||
error(infoSink, "Layout offset qualifier must match:", unitStage);
|
||||
layoutQualifierError = true;
|
||||
}
|
||||
if (layoutQualifierError) {
|
||||
writeTypeComparison = true;
|
||||
printQualifiers = true;
|
||||
}
|
||||
|
||||
// Initializers have to match, if both are present, and if we don't already know the types don't match
|
||||
if (! writeTypeComparison) {
|
||||
if (! writeTypeComparison && ! errorReported) {
|
||||
if (! symbol.getConstArray().empty() && ! unitSymbol.getConstArray().empty()) {
|
||||
if (symbol.getConstArray() != unitSymbol.getConstArray()) {
|
||||
error(infoSink, "Initializers must match:");
|
||||
error(infoSink, "Initializers must match:", unitStage);
|
||||
infoSink.info << " " << symbol.getName() << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (writeTypeComparison) {
|
||||
infoSink.info << " " << symbol.getName() << ": \"" << symbol.getType().getCompleteString() << "\" versus ";
|
||||
if (symbol.getName() != unitSymbol.getName())
|
||||
infoSink.info << unitSymbol.getName() << ": ";
|
||||
|
||||
infoSink.info << "\"" << unitSymbol.getType().getCompleteString() << "\"\n";
|
||||
if (symbol.getType().getBasicType() == EbtBlock && unitSymbol.getType().getBasicType() == EbtBlock &&
|
||||
symbol.getType().getStruct() && unitSymbol.getType().getStruct()) {
|
||||
if (printType) {
|
||||
infoSink.info << " " << StageName(getStage()) << " stage: \"" << symbol.getType().getCompleteString(true, printQualifiers, printPrecision,
|
||||
printType, symbol.getName(), symbol.getType().getTypeName()) << "\"\n";
|
||||
infoSink.info << " " << StageName(unitStage) << " stage: \"" << unitSymbol.getType().getCompleteString(true, printQualifiers, printPrecision,
|
||||
printType, unitSymbol.getName(), unitSymbol.getType().getTypeName()) << "\"\n";
|
||||
} else {
|
||||
infoSink.info << " " << StageName(getStage()) << " stage: Block: " << symbol.getType().getTypeName() << " Instance: " << symbol.getName()
|
||||
<< ": \"" << symbol.getType().getCompleteString(true, printQualifiers, printPrecision, printType) << "\"\n";
|
||||
infoSink.info << " " << StageName(unitStage) << " stage: Block: " << unitSymbol.getType().getTypeName() << " Instance: " << unitSymbol.getName()
|
||||
<< ": \"" << unitSymbol.getType().getCompleteString(true, printQualifiers, printPrecision, printType) << "\"\n";
|
||||
}
|
||||
} else {
|
||||
if (printType) {
|
||||
infoSink.info << " " << StageName(getStage()) << " stage: \""
|
||||
<< symbol.getType().getCompleteString(true, printQualifiers, printPrecision, printType, symbol.getName()) << "\"\n";
|
||||
infoSink.info << " " << StageName(unitStage) << " stage: \""
|
||||
<< unitSymbol.getType().getCompleteString(true, printQualifiers, printPrecision, printType, unitSymbol.getName()) << "\"\n";
|
||||
} else {
|
||||
infoSink.info << " " << StageName(getStage()) << " stage: " << symbol.getName() << " \""
|
||||
<< symbol.getType().getCompleteString(true, printQualifiers, printPrecision, printType) << "\"\n";
|
||||
infoSink.info << " " << StageName(unitStage) << " stage: " << unitSymbol.getName() << " \""
|
||||
<< unitSymbol.getType().getCompleteString(true, printQualifiers, printPrecision, printType) << "\"\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -291,6 +291,7 @@ public:
|
|||
numEntryPoints(0), numErrors(0), numPushConstants(0), recursive(false),
|
||||
invertY(false),
|
||||
dxPositionW(false),
|
||||
enhancedMsgs(false),
|
||||
useStorageBuffer(false),
|
||||
invariantAll(false),
|
||||
nanMinMaxClamp(false),
|
||||
|
|
@ -469,12 +470,18 @@ public:
|
|||
|
||||
void setDxPositionW(bool dxPosW)
|
||||
{
|
||||
dxPositionW = dxPosW;
|
||||
if (dxPositionW)
|
||||
processes.addProcess("dx-position-w");
|
||||
dxPositionW = dxPosW;
|
||||
if (dxPositionW)
|
||||
processes.addProcess("dx-position-w");
|
||||
}
|
||||
bool getDxPositionW() const { return dxPositionW; }
|
||||
|
||||
void setEnhancedMsgs()
|
||||
{
|
||||
enhancedMsgs = true;
|
||||
}
|
||||
bool getEnhancedMsgs() const { return enhancedMsgs && source == EShSourceGlsl; }
|
||||
|
||||
#ifdef ENABLE_HLSL
|
||||
void setSource(EShSource s) { source = s; }
|
||||
EShSource getSource() const { return source; }
|
||||
|
|
@ -1031,8 +1038,8 @@ public:
|
|||
|
||||
protected:
|
||||
TIntermSymbol* addSymbol(long long Id, const TString&, const TType&, const TConstUnionArray&, TIntermTyped* subtree, const TSourceLoc&);
|
||||
void error(TInfoSink& infoSink, const char*);
|
||||
void warn(TInfoSink& infoSink, const char*);
|
||||
void error(TInfoSink& infoSink, const char*, EShLanguage unitStage = EShLangCount);
|
||||
void warn(TInfoSink& infoSink, const char*, EShLanguage unitStage = EShLangCount);
|
||||
void mergeCallGraphs(TInfoSink&, TIntermediate&);
|
||||
void mergeModes(TInfoSink&, TIntermediate&);
|
||||
void mergeTrees(TInfoSink&, TIntermediate&);
|
||||
|
|
@ -1086,6 +1093,7 @@ protected:
|
|||
bool recursive;
|
||||
bool invertY;
|
||||
bool dxPositionW;
|
||||
bool enhancedMsgs;
|
||||
bool useStorageBuffer;
|
||||
bool invariantAll;
|
||||
bool nanMinMaxClamp; // true if desiring min/max/clamp to favor non-NaN over NaN
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue