Upgrade glslang to 11.10.0

This commit is contained in:
Magnus Norddahl 2022-06-12 07:59:07 +02:00 committed by Christoph Oelckers
parent 32d059e432
commit 5cc21c5a4a
53 changed files with 5696 additions and 4693 deletions

View file

@ -263,6 +263,7 @@ enum TBuiltInVariable {
EbvObjectRayDirection, EbvObjectRayDirection,
EbvRayTmin, EbvRayTmin,
EbvRayTmax, EbvRayTmax,
EbvCullMask,
EbvHitT, EbvHitT,
EbvHitKind, EbvHitKind,
EbvObjectToWorld, EbvObjectToWorld,
@ -274,6 +275,8 @@ enum TBuiltInVariable {
// barycentrics // barycentrics
EbvBaryCoordNV, EbvBaryCoordNV,
EbvBaryCoordNoPerspNV, EbvBaryCoordNoPerspNV,
EbvBaryCoordEXT,
EbvBaryCoordNoPerspEXT,
// mesh shaders // mesh shaders
EbvTaskCountNV, EbvTaskCountNV,
EbvPrimitiveCountNV, EbvPrimitiveCountNV,
@ -478,8 +481,10 @@ __inline const char* GetBuiltInVariableString(TBuiltInVariable v)
case EbvWorldToObject: return "WorldToObjectNV"; case EbvWorldToObject: return "WorldToObjectNV";
case EbvCurrentRayTimeNV: return "CurrentRayTimeNV"; case EbvCurrentRayTimeNV: return "CurrentRayTimeNV";
case EbvBaryCoordNV: return "BaryCoordNV"; case EbvBaryCoordEXT:
case EbvBaryCoordNoPerspNV: return "BaryCoordNoPerspNV"; case EbvBaryCoordNV: return "BaryCoordKHR";
case EbvBaryCoordNoPerspEXT:
case EbvBaryCoordNoPerspNV: return "BaryCoordNoPerspKHR";
case EbvTaskCountNV: return "TaskCountNV"; case EbvTaskCountNV: return "TaskCountNV";
case EbvPrimitiveCountNV: return "PrimitiveCountNV"; case EbvPrimitiveCountNV: return "PrimitiveCountNV";

View file

@ -39,6 +39,11 @@
#include <algorithm> #include <algorithm>
#include <cassert> #include <cassert>
#ifdef _MSC_VER
#include <cfloat>
#else
#include <cmath>
#endif
#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
#include <list> #include <list>
@ -61,7 +66,7 @@ std::string to_string(const T& val) {
} }
#endif #endif
#if (defined(_MSC_VER) && _MSC_VER < 1900 /*vs2015*/) || defined MINGW_HAS_SECURE_API #if (defined(_MSC_VER) && _MSC_VER < 1900 /*vs2015*/) || MINGW_HAS_SECURE_API
#include <basetsd.h> #include <basetsd.h>
#ifndef snprintf #ifndef snprintf
#define snprintf sprintf_s #define snprintf sprintf_s
@ -213,7 +218,7 @@ template <class T> T Max(const T a, const T b) { return a > b ? a : b; }
// //
// Create a TString object from an integer. // Create a TString object from an integer.
// //
#if defined _MSC_VER || defined MINGW_HAS_SECURE_API #if defined _MSC_VER || MINGW_HAS_SECURE_API
inline const TString String(const int i, const int base = 10) inline const TString String(const int i, const int base = 10)
{ {
char text[16]; // 32 bit ints are at most 10 digits in base 10 char text[16]; // 32 bit ints are at most 10 digits in base 10
@ -302,6 +307,34 @@ template <class T> int IntLog2(T n)
return result; return result;
} }
inline bool IsInfinity(double x) {
#ifdef _MSC_VER
switch (_fpclass(x)) {
case _FPCLASS_NINF:
case _FPCLASS_PINF:
return true;
default:
return false;
}
#else
return std::isinf(x);
#endif
}
inline bool IsNan(double x) {
#ifdef _MSC_VER
switch (_fpclass(x)) {
case _FPCLASS_SNAN:
case _FPCLASS_QNAN:
return true;
default:
return false;
}
#else
return std::isnan(x);
#endif
}
} // end namespace glslang } // end namespace glslang
#endif // _COMMON_INCLUDED_ #endif // _COMMON_INCLUDED_

View file

@ -306,6 +306,8 @@ public:
TPoolAllocator& getAllocator() const { return allocator; } TPoolAllocator& getAllocator() const { return allocator; }
pool_allocator select_on_container_copy_construction() const { return pool_allocator{}; }
protected: protected:
pool_allocator& operator=(const pool_allocator&) { return *this; } pool_allocator& operator=(const pool_allocator&) { return *this; }
TPoolAllocator& allocator; TPoolAllocator& allocator;

View file

@ -65,7 +65,7 @@ struct TSpirvExecutionMode {
// spirv_execution_mode // spirv_execution_mode
TMap<int, TVector<const TIntermConstantUnion*>> modes; TMap<int, TVector<const TIntermConstantUnion*>> modes;
// spirv_execution_mode_id // spirv_execution_mode_id
TMap<int, TVector<const TIntermConstantUnion*> > modeIds; TMap<int, TVector<const TIntermTyped*> > modeIds;
}; };
// SPIR-V decorations // SPIR-V decorations
@ -75,7 +75,7 @@ struct TSpirvDecorate {
// spirv_decorate // spirv_decorate
TMap<int, TVector<const TIntermConstantUnion*> > decorates; TMap<int, TVector<const TIntermConstantUnion*> > decorates;
// spirv_decorate_id // spirv_decorate_id
TMap<int, TVector<const TIntermConstantUnion*> > decorateIds; TMap<int, TVector<const TIntermTyped*>> decorateIds;
// spirv_decorate_string // spirv_decorate_string
TMap<int, TVector<const TIntermConstantUnion*> > decorateStrings; TMap<int, TVector<const TIntermConstantUnion*> > decorateStrings;
}; };
@ -98,20 +98,12 @@ struct TSpirvInstruction {
struct TSpirvTypeParameter { struct TSpirvTypeParameter {
POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
TSpirvTypeParameter(const TIntermConstantUnion* arg) { isConstant = true; constant = arg; } TSpirvTypeParameter(const TIntermConstantUnion* arg) { constant = arg; }
TSpirvTypeParameter(const TType* arg) { isConstant = false; type = arg; }
bool operator==(const TSpirvTypeParameter& rhs) const bool operator==(const TSpirvTypeParameter& rhs) const { return constant == rhs.constant; }
{
return isConstant == rhs.isConstant && ((isConstant && constant == rhs.constant) || (!isConstant && type == rhs.type));
}
bool operator!=(const TSpirvTypeParameter& rhs) const { return !operator==(rhs); } bool operator!=(const TSpirvTypeParameter& rhs) const { return !operator==(rhs); }
bool isConstant; const TIntermConstantUnion* constant;
union {
const TIntermConstantUnion* constant;
const TType* type;
};
}; };
typedef TVector<TSpirvTypeParameter> TSpirvTypeParameters; typedef TVector<TSpirvTypeParameter> TSpirvTypeParameters;

View file

@ -552,6 +552,7 @@ public:
perViewNV = false; perViewNV = false;
perTaskNV = false; perTaskNV = false;
#endif #endif
pervertexEXT = false;
} }
void clearMemory() void clearMemory()
@ -604,7 +605,8 @@ public:
bool isNoContraction() const { return false; } bool isNoContraction() const { return false; }
void setNoContraction() { } void setNoContraction() { }
bool isPervertexNV() const { return false; } bool isPervertexNV() const { return false; }
void setNullInit() { } bool isPervertexEXT() const { return pervertexEXT; }
void setNullInit() {}
bool isNullInit() const { return false; } bool isNullInit() const { return false; }
void setSpirvByReference() { } void setSpirvByReference() { }
bool isSpirvByReference() { return false; } bool isSpirvByReference() { return false; }
@ -615,6 +617,7 @@ public:
bool nopersp : 1; bool nopersp : 1;
bool explicitInterp : 1; bool explicitInterp : 1;
bool pervertexNV : 1; bool pervertexNV : 1;
bool pervertexEXT : 1;
bool perPrimitiveNV : 1; bool perPrimitiveNV : 1;
bool perViewNV : 1; bool perViewNV : 1;
bool perTaskNV : 1; bool perTaskNV : 1;
@ -663,12 +666,13 @@ public:
} }
bool isAuxiliary() const bool isAuxiliary() const
{ {
return centroid || patch || sample || pervertexNV; return centroid || patch || sample || pervertexNV || pervertexEXT;
} }
bool isPatch() const { return patch; } bool isPatch() const { return patch; }
bool isNoContraction() const { return noContraction; } bool isNoContraction() const { return noContraction; }
void setNoContraction() { noContraction = true; } void setNoContraction() { noContraction = true; }
bool isPervertexNV() const { return pervertexNV; } bool isPervertexNV() const { return pervertexNV; }
bool isPervertexEXT() const { return pervertexEXT; }
void setNullInit() { nullInit = true; } void setNullInit() { nullInit = true; }
bool isNullInit() const { return nullInit; } bool isNullInit() const { return nullInit; }
void setSpirvByReference() { spirvByReference = true; } void setSpirvByReference() { spirvByReference = true; }
@ -741,6 +745,16 @@ public:
} }
} }
bool isUniform() const
{
switch (storage) {
case EvqUniform:
return true;
default:
return false;
}
}
bool isIo() const bool isIo() const
{ {
switch (storage) { switch (storage) {
@ -846,7 +860,7 @@ public:
case EShLangTessEvaluation: case EShLangTessEvaluation:
return ! patch && isPipeInput(); return ! patch && isPipeInput();
case EShLangFragment: case EShLangFragment:
return pervertexNV && isPipeInput(); return (pervertexNV || pervertexEXT) && isPipeInput();
case EShLangMeshNV: case EShLangMeshNV:
return ! perTaskNV && isPipeOutput(); return ! perTaskNV && isPipeOutput();
@ -1855,10 +1869,12 @@ public:
bool isAtomic() const { return false; } bool isAtomic() const { return false; }
bool isCoopMat() const { return false; } bool isCoopMat() const { return false; }
bool isReference() const { return false; } bool isReference() const { return false; }
bool isSpirvType() const { return false; }
#else #else
bool isAtomic() const { return basicType == EbtAtomicUint; } bool isAtomic() const { return basicType == EbtAtomicUint; }
bool isCoopMat() const { return coopmat; } bool isCoopMat() const { return coopmat; }
bool isReference() const { return getBasicType() == EbtReference; } bool isReference() const { return getBasicType() == EbtReference; }
bool isSpirvType() const { return getBasicType() == EbtSpirvType; }
#endif #endif
// return true if this type contains any subtype which satisfies the given predicate. // return true if this type contains any subtype which satisfies the given predicate.
@ -2130,7 +2146,8 @@ public:
const char* getPrecisionQualifierString() const { return ""; } const char* getPrecisionQualifierString() const { return ""; }
TString getBasicTypeString() const { return ""; } TString getBasicTypeString() const { return ""; }
#else #else
TString getCompleteString() const TString getCompleteString(bool syntactic = false, bool getQualifiers = true, bool getPrecision = true,
bool getType = true, TString name = "", TString structName = "") const
{ {
TString typeString; TString typeString;
@ -2138,232 +2155,337 @@ public:
const auto appendUint = [&](unsigned int u) { typeString.append(std::to_string(u).c_str()); }; const auto appendUint = [&](unsigned int u) { typeString.append(std::to_string(u).c_str()); };
const auto appendInt = [&](int i) { typeString.append(std::to_string(i).c_str()); }; const auto appendInt = [&](int i) { typeString.append(std::to_string(i).c_str()); };
if (qualifier.hasSprivDecorate()) if (getQualifiers) {
if (qualifier.hasSprivDecorate())
appendStr(qualifier.getSpirvDecorateQualifierString().c_str()); appendStr(qualifier.getSpirvDecorateQualifierString().c_str());
if (qualifier.hasLayout()) { if (qualifier.hasLayout()) {
// To reduce noise, skip this if the only layout is an xfb_buffer // To reduce noise, skip this if the only layout is an xfb_buffer
// with no triggering xfb_offset. // with no triggering xfb_offset.
TQualifier noXfbBuffer = qualifier; TQualifier noXfbBuffer = qualifier;
noXfbBuffer.layoutXfbBuffer = TQualifier::layoutXfbBufferEnd; noXfbBuffer.layoutXfbBuffer = TQualifier::layoutXfbBufferEnd;
if (noXfbBuffer.hasLayout()) { if (noXfbBuffer.hasLayout()) {
appendStr("layout("); appendStr("layout(");
if (qualifier.hasAnyLocation()) { if (qualifier.hasAnyLocation()) {
appendStr(" location="); appendStr(" location=");
appendUint(qualifier.layoutLocation); appendUint(qualifier.layoutLocation);
if (qualifier.hasComponent()) { if (qualifier.hasComponent()) {
appendStr(" component="); appendStr(" component=");
appendUint(qualifier.layoutComponent); appendUint(qualifier.layoutComponent);
}
if (qualifier.hasIndex()) {
appendStr(" index=");
appendUint(qualifier.layoutIndex);
}
} }
if (qualifier.hasSet()) { if (qualifier.hasIndex()) {
appendStr(" set="); appendStr(" index=");
appendUint(qualifier.layoutSet); appendUint(qualifier.layoutIndex);
}
if (qualifier.hasBinding()) {
appendStr(" binding=");
appendUint(qualifier.layoutBinding);
}
if (qualifier.hasStream()) {
appendStr(" stream=");
appendUint(qualifier.layoutStream);
}
if (qualifier.hasMatrix()) {
appendStr(" ");
appendStr(TQualifier::getLayoutMatrixString(qualifier.layoutMatrix));
}
if (qualifier.hasPacking()) {
appendStr(" ");
appendStr(TQualifier::getLayoutPackingString(qualifier.layoutPacking));
}
if (qualifier.hasOffset()) {
appendStr(" offset=");
appendInt(qualifier.layoutOffset);
}
if (qualifier.hasAlign()) {
appendStr(" align=");
appendInt(qualifier.layoutAlign);
}
if (qualifier.hasFormat()) {
appendStr(" ");
appendStr(TQualifier::getLayoutFormatString(qualifier.layoutFormat));
}
if (qualifier.hasXfbBuffer() && qualifier.hasXfbOffset()) {
appendStr(" xfb_buffer=");
appendUint(qualifier.layoutXfbBuffer);
}
if (qualifier.hasXfbOffset()) {
appendStr(" xfb_offset=");
appendUint(qualifier.layoutXfbOffset);
}
if (qualifier.hasXfbStride()) {
appendStr(" xfb_stride=");
appendUint(qualifier.layoutXfbStride);
}
if (qualifier.hasAttachment()) {
appendStr(" input_attachment_index=");
appendUint(qualifier.layoutAttachment);
}
if (qualifier.hasSpecConstantId()) {
appendStr(" constant_id=");
appendUint(qualifier.layoutSpecConstantId);
}
if (qualifier.layoutPushConstant)
appendStr(" push_constant");
if (qualifier.layoutBufferReference)
appendStr(" buffer_reference");
if (qualifier.hasBufferReferenceAlign()) {
appendStr(" buffer_reference_align=");
appendUint(1u << qualifier.layoutBufferReferenceAlign);
} }
}
if (qualifier.hasSet()) {
appendStr(" set=");
appendUint(qualifier.layoutSet);
}
if (qualifier.hasBinding()) {
appendStr(" binding=");
appendUint(qualifier.layoutBinding);
}
if (qualifier.hasStream()) {
appendStr(" stream=");
appendUint(qualifier.layoutStream);
}
if (qualifier.hasMatrix()) {
appendStr(" ");
appendStr(TQualifier::getLayoutMatrixString(qualifier.layoutMatrix));
}
if (qualifier.hasPacking()) {
appendStr(" ");
appendStr(TQualifier::getLayoutPackingString(qualifier.layoutPacking));
}
if (qualifier.hasOffset()) {
appendStr(" offset=");
appendInt(qualifier.layoutOffset);
}
if (qualifier.hasAlign()) {
appendStr(" align=");
appendInt(qualifier.layoutAlign);
}
if (qualifier.hasFormat()) {
appendStr(" ");
appendStr(TQualifier::getLayoutFormatString(qualifier.layoutFormat));
}
if (qualifier.hasXfbBuffer() && qualifier.hasXfbOffset()) {
appendStr(" xfb_buffer=");
appendUint(qualifier.layoutXfbBuffer);
}
if (qualifier.hasXfbOffset()) {
appendStr(" xfb_offset=");
appendUint(qualifier.layoutXfbOffset);
}
if (qualifier.hasXfbStride()) {
appendStr(" xfb_stride=");
appendUint(qualifier.layoutXfbStride);
}
if (qualifier.hasAttachment()) {
appendStr(" input_attachment_index=");
appendUint(qualifier.layoutAttachment);
}
if (qualifier.hasSpecConstantId()) {
appendStr(" constant_id=");
appendUint(qualifier.layoutSpecConstantId);
}
if (qualifier.layoutPushConstant)
appendStr(" push_constant");
if (qualifier.layoutBufferReference)
appendStr(" buffer_reference");
if (qualifier.hasBufferReferenceAlign()) {
appendStr(" buffer_reference_align=");
appendUint(1u << qualifier.layoutBufferReferenceAlign);
}
if (qualifier.layoutPassthrough) if (qualifier.layoutPassthrough)
appendStr(" passthrough"); appendStr(" passthrough");
if (qualifier.layoutViewportRelative) if (qualifier.layoutViewportRelative)
appendStr(" layoutViewportRelative"); appendStr(" layoutViewportRelative");
if (qualifier.layoutSecondaryViewportRelativeOffset != -2048) { if (qualifier.layoutSecondaryViewportRelativeOffset != -2048) {
appendStr(" layoutSecondaryViewportRelativeOffset="); appendStr(" layoutSecondaryViewportRelativeOffset=");
appendInt(qualifier.layoutSecondaryViewportRelativeOffset); appendInt(qualifier.layoutSecondaryViewportRelativeOffset);
} }
if (qualifier.layoutShaderRecord) if (qualifier.layoutShaderRecord)
appendStr(" shaderRecordNV"); appendStr(" shaderRecordNV");
appendStr(")"); appendStr(")");
} }
} }
if (qualifier.invariant) if (qualifier.invariant)
appendStr(" invariant"); appendStr(" invariant");
if (qualifier.noContraction) if (qualifier.noContraction)
appendStr(" noContraction"); appendStr(" noContraction");
if (qualifier.centroid) if (qualifier.centroid)
appendStr(" centroid"); appendStr(" centroid");
if (qualifier.smooth) if (qualifier.smooth)
appendStr(" smooth"); appendStr(" smooth");
if (qualifier.flat) if (qualifier.flat)
appendStr(" flat"); appendStr(" flat");
if (qualifier.nopersp) if (qualifier.nopersp)
appendStr(" noperspective"); appendStr(" noperspective");
if (qualifier.explicitInterp) if (qualifier.explicitInterp)
appendStr(" __explicitInterpAMD"); appendStr(" __explicitInterpAMD");
if (qualifier.pervertexNV) if (qualifier.pervertexNV)
appendStr(" pervertexNV"); appendStr(" pervertexNV");
if (qualifier.perPrimitiveNV) if (qualifier.pervertexEXT)
appendStr(" pervertexEXT");
if (qualifier.perPrimitiveNV)
appendStr(" perprimitiveNV"); appendStr(" perprimitiveNV");
if (qualifier.perViewNV) if (qualifier.perViewNV)
appendStr(" perviewNV"); appendStr(" perviewNV");
if (qualifier.perTaskNV) if (qualifier.perTaskNV)
appendStr(" taskNV"); appendStr(" taskNV");
if (qualifier.patch) if (qualifier.patch)
appendStr(" patch"); appendStr(" patch");
if (qualifier.sample) if (qualifier.sample)
appendStr(" sample"); appendStr(" sample");
if (qualifier.coherent) if (qualifier.coherent)
appendStr(" coherent"); appendStr(" coherent");
if (qualifier.devicecoherent) if (qualifier.devicecoherent)
appendStr(" devicecoherent"); appendStr(" devicecoherent");
if (qualifier.queuefamilycoherent) if (qualifier.queuefamilycoherent)
appendStr(" queuefamilycoherent"); appendStr(" queuefamilycoherent");
if (qualifier.workgroupcoherent) if (qualifier.workgroupcoherent)
appendStr(" workgroupcoherent"); appendStr(" workgroupcoherent");
if (qualifier.subgroupcoherent) if (qualifier.subgroupcoherent)
appendStr(" subgroupcoherent"); appendStr(" subgroupcoherent");
if (qualifier.shadercallcoherent) if (qualifier.shadercallcoherent)
appendStr(" shadercallcoherent"); appendStr(" shadercallcoherent");
if (qualifier.nonprivate) if (qualifier.nonprivate)
appendStr(" nonprivate"); appendStr(" nonprivate");
if (qualifier.volatil) if (qualifier.volatil)
appendStr(" volatile"); appendStr(" volatile");
if (qualifier.restrict) if (qualifier.restrict)
appendStr(" restrict"); appendStr(" restrict");
if (qualifier.readonly) if (qualifier.readonly)
appendStr(" readonly"); appendStr(" readonly");
if (qualifier.writeonly) if (qualifier.writeonly)
appendStr(" writeonly"); appendStr(" writeonly");
if (qualifier.specConstant) if (qualifier.specConstant)
appendStr(" specialization-constant"); appendStr(" specialization-constant");
if (qualifier.nonUniform) if (qualifier.nonUniform)
appendStr(" nonuniform"); appendStr(" nonuniform");
if (qualifier.isNullInit()) if (qualifier.isNullInit())
appendStr(" null-init"); appendStr(" null-init");
if (qualifier.isSpirvByReference()) if (qualifier.isSpirvByReference())
appendStr(" spirv_by_reference"); appendStr(" spirv_by_reference");
if (qualifier.isSpirvLiteral()) if (qualifier.isSpirvLiteral())
appendStr(" spirv_literal"); appendStr(" spirv_literal");
appendStr(" "); appendStr(" ");
appendStr(getStorageQualifierString()); appendStr(getStorageQualifierString());
if (isArray()) { }
for(int i = 0; i < (int)arraySizes->getNumDims(); ++i) { if (getType) {
if (syntactic) {
if (getPrecision && qualifier.precision != EpqNone) {
appendStr(" ");
appendStr(getPrecisionQualifierString());
}
if (isVector() || isMatrix()) {
appendStr(" ");
switch (basicType) {
case EbtDouble:
appendStr("d");
break;
case EbtInt:
appendStr("i");
break;
case EbtUint:
appendStr("u");
break;
case EbtBool:
appendStr("b");
break;
case EbtFloat:
default:
break;
}
if (isVector()) {
appendStr("vec");
appendInt(vectorSize);
} else {
appendStr("mat");
appendInt(matrixCols);
appendStr("x");
appendInt(matrixRows);
}
} else if (isStruct() && structure) {
appendStr(" ");
appendStr(structName.c_str());
appendStr("{");
bool hasHiddenMember = true;
for (size_t i = 0; i < structure->size(); ++i) {
if (!(*structure)[i].type->hiddenMember()) {
if (!hasHiddenMember)
appendStr(", ");
typeString.append((*structure)[i].type->getCompleteString(syntactic, getQualifiers, getPrecision, getType, (*structure)[i].type->getFieldName()));
hasHiddenMember = false;
}
}
appendStr("}");
} else {
appendStr(" ");
switch (basicType) {
case EbtDouble:
appendStr("double");
break;
case EbtInt:
appendStr("int");
break;
case EbtUint:
appendStr("uint");
break;
case EbtBool:
appendStr("bool");
break;
case EbtFloat:
appendStr("float");
break;
default:
appendStr("unexpected");
break;
}
}
if (name.length() > 0) {
appendStr(" ");
appendStr(name.c_str());
}
if (isArray()) {
for (int i = 0; i < (int)arraySizes->getNumDims(); ++i) {
int size = arraySizes->getDimSize(i); int size = arraySizes->getDimSize(i);
if (size == UnsizedArraySize && i == 0 && arraySizes->isVariablyIndexed()) if (size == UnsizedArraySize && i == 0 && arraySizes->isVariablyIndexed())
appendStr(" runtime-sized array of"); appendStr("[]");
else { else {
if (size == UnsizedArraySize) { if (size == UnsizedArraySize) {
appendStr(" unsized"); appendStr("[");
if (i == 0) { if (i == 0)
appendStr(" "); appendInt(arraySizes->getImplicitSize());
appendInt(arraySizes->getImplicitSize()); appendStr("]");
} }
} else { else {
appendStr(" "); appendStr("[");
appendInt(arraySizes->getDimSize(i)); appendInt(arraySizes->getDimSize(i));
} appendStr("]");
appendStr("-element array of"); }
} }
}
} }
} }
if (isParameterized()) { else {
appendStr("<"); if (isArray()) {
for(int i = 0; i < (int)typeParameters->getNumDims(); ++i) { for (int i = 0; i < (int)arraySizes->getNumDims(); ++i) {
int size = arraySizes->getDimSize(i);
if (size == UnsizedArraySize && i == 0 && arraySizes->isVariablyIndexed())
appendStr(" runtime-sized array of");
else {
if (size == UnsizedArraySize) {
appendStr(" unsized");
if (i == 0) {
appendStr(" ");
appendInt(arraySizes->getImplicitSize());
}
}
else {
appendStr(" ");
appendInt(arraySizes->getDimSize(i));
}
appendStr("-element array of");
}
}
}
if (isParameterized()) {
appendStr("<");
for (int i = 0; i < (int)typeParameters->getNumDims(); ++i) {
appendInt(typeParameters->getDimSize(i)); appendInt(typeParameters->getDimSize(i));
if (i != (int)typeParameters->getNumDims() - 1) if (i != (int)typeParameters->getNumDims() - 1)
appendStr(", ");
}
appendStr(">");
}
if (getPrecision && qualifier.precision != EpqNone) {
appendStr(" ");
appendStr(getPrecisionQualifierString());
}
if (isMatrix()) {
appendStr(" ");
appendInt(matrixCols);
appendStr("X");
appendInt(matrixRows);
appendStr(" matrix of");
}
else if (isVector()) {
appendStr(" ");
appendInt(vectorSize);
appendStr("-component vector of");
}
appendStr(" ");
typeString.append(getBasicTypeString());
if (qualifier.builtIn != EbvNone) {
appendStr(" ");
appendStr(getBuiltInVariableString());
}
// Add struct/block members
if (isStruct() && structure) {
appendStr("{");
bool hasHiddenMember = true;
for (size_t i = 0; i < structure->size(); ++i) {
if (!(*structure)[i].type->hiddenMember()) {
if (!hasHiddenMember)
appendStr(", "); appendStr(", ");
} typeString.append((*structure)[i].type->getCompleteString());
appendStr(">"); typeString.append(" ");
} typeString.append((*structure)[i].type->getFieldName());
if (qualifier.precision != EpqNone) { hasHiddenMember = false;
appendStr(" ");
appendStr(getPrecisionQualifierString());
}
if (isMatrix()) {
appendStr(" ");
appendInt(matrixCols);
appendStr("X");
appendInt(matrixRows);
appendStr(" matrix of");
} else if (isVector()) {
appendStr(" ");
appendInt(vectorSize);
appendStr("-component vector of");
}
appendStr(" ");
typeString.append(getBasicTypeString());
if (qualifier.builtIn != EbvNone) {
appendStr(" ");
appendStr(getBuiltInVariableString());
}
// Add struct/block members
if (isStruct() && structure) {
appendStr("{");
bool hasHiddenMember = true;
for (size_t i = 0; i < structure->size(); ++i) {
if (! (*structure)[i].type->hiddenMember()) {
if (!hasHiddenMember)
appendStr(", ");
typeString.append((*structure)[i].type->getCompleteString());
typeString.append(" ");
typeString.append((*structure)[i].type->getFieldName());
hasHiddenMember = false;
} }
}
appendStr("}");
} }
appendStr("}"); }
} }
return typeString; return typeString;
@ -2432,13 +2554,27 @@ public:
// type definitions, and member names to be considered the same type. // type definitions, and member names to be considered the same type.
// This rule applies recursively for nested or embedded types." // This rule applies recursively for nested or embedded types."
// //
bool sameStructType(const TType& right) const // If type mismatch in structure, return member indices through lpidx and rpidx.
// If matching members for either block are exhausted, return -1 for exhausted
// block and the index of the unmatched member. Otherwise return {-1,-1}.
//
bool sameStructType(const TType& right, int* lpidx = nullptr, int* rpidx = nullptr) const
{ {
// Initialize error to general type mismatch.
if (lpidx != nullptr) {
*lpidx = -1;
*rpidx = -1;
}
// Most commonly, they are both nullptr, or the same pointer to the same actual structure // Most commonly, they are both nullptr, or the same pointer to the same actual structure
// TODO: Why return true when neither types are structures?
if ((!isStruct() && !right.isStruct()) || if ((!isStruct() && !right.isStruct()) ||
(isStruct() && right.isStruct() && structure == right.structure)) (isStruct() && right.isStruct() && structure == right.structure))
return true; return true;
if (!isStruct() || !right.isStruct())
return false;
// Structure names have to match // Structure names have to match
if (*typeName != *right.typeName) if (*typeName != *right.typeName)
return false; return false;
@ -2448,17 +2584,30 @@ public:
bool isGLPerVertex = *typeName == "gl_PerVertex"; bool isGLPerVertex = *typeName == "gl_PerVertex";
// Both being nullptr was caught above, now they both have to be structures of the same number of elements // Both being nullptr was caught above, now they both have to be structures of the same number of elements
if (!isStruct() || !right.isStruct() || if (lpidx == nullptr &&
(structure->size() != right.structure->size() && !isGLPerVertex)) (structure->size() != right.structure->size() && !isGLPerVertex)) {
return false; return false;
}
// Compare the names and types of all the members, which have to match // Compare the names and types of all the members, which have to match
for (size_t li = 0, ri = 0; li < structure->size() || ri < right.structure->size(); ++li, ++ri) { for (size_t li = 0, ri = 0; li < structure->size() || ri < right.structure->size(); ++li, ++ri) {
if (lpidx != nullptr) {
*lpidx = static_cast<int>(li);
*rpidx = static_cast<int>(ri);
}
if (li < structure->size() && ri < right.structure->size()) { if (li < structure->size() && ri < right.structure->size()) {
if ((*structure)[li].type->getFieldName() == (*right.structure)[ri].type->getFieldName()) { if ((*structure)[li].type->getFieldName() == (*right.structure)[ri].type->getFieldName()) {
if (*(*structure)[li].type != *(*right.structure)[ri].type) if (*(*structure)[li].type != *(*right.structure)[ri].type)
return false; return false;
} else { } else {
// Skip hidden members
if ((*structure)[li].type->hiddenMember()) {
ri--;
continue;
} else if ((*right.structure)[ri].type->hiddenMember()) {
li--;
continue;
}
// If one of the members is something that's inconsistently declared, skip over it // If one of the members is something that's inconsistently declared, skip over it
// for now. // for now.
if (isGLPerVertex) { if (isGLPerVertex) {
@ -2475,11 +2624,19 @@ public:
} }
// If we get here, then there should only be inconsistently declared members left // If we get here, then there should only be inconsistently declared members left
} else if (li < structure->size()) { } else if (li < structure->size()) {
if (!isInconsistentGLPerVertexMember((*structure)[li].type->getFieldName())) if (!(*structure)[li].type->hiddenMember() && !isInconsistentGLPerVertexMember((*structure)[li].type->getFieldName())) {
if (lpidx != nullptr) {
*rpidx = -1;
}
return false; return false;
}
} else { } else {
if (!isInconsistentGLPerVertexMember((*right.structure)[ri].type->getFieldName())) if (!(*right.structure)[ri].type->hiddenMember() && !isInconsistentGLPerVertexMember((*right.structure)[ri].type->getFieldName())) {
if (lpidx != nullptr) {
*lpidx = -1;
}
return false; return false;
}
} }
} }
@ -2503,10 +2660,15 @@ public:
return *referentType == *right.referentType; return *referentType == *right.referentType;
} }
// See if two types match, in all aspects except arrayness // See if two types match, in all aspects except arrayness
bool sameElementType(const TType& right) const // If mismatch in structure members, return member indices in lpidx and rpidx.
bool sameElementType(const TType& right, int* lpidx = nullptr, int* rpidx = nullptr) const
{ {
return basicType == right.basicType && sameElementShape(right); if (lpidx != nullptr) {
*lpidx = -1;
*rpidx = -1;
}
return basicType == right.basicType && sameElementShape(right, lpidx, rpidx);
} }
// See if two type's arrayness match // See if two type's arrayness match
@ -2540,15 +2702,20 @@ public:
#endif #endif
// See if two type's elements match in all ways except basic type // See if two type's elements match in all ways except basic type
bool sameElementShape(const TType& right) const // If mismatch in structure members, return member indices in lpidx and rpidx.
bool sameElementShape(const TType& right, int* lpidx = nullptr, int* rpidx = nullptr) const
{ {
return sampler == right.sampler && if (lpidx != nullptr) {
*lpidx = -1;
*rpidx = -1;
}
return ((basicType != EbtSampler && right.basicType != EbtSampler) || sampler == right.sampler) &&
vectorSize == right.vectorSize && vectorSize == right.vectorSize &&
matrixCols == right.matrixCols && matrixCols == right.matrixCols &&
matrixRows == right.matrixRows && matrixRows == right.matrixRows &&
vector1 == right.vector1 && vector1 == right.vector1 &&
isCoopMat() == right.isCoopMat() && isCoopMat() == right.isCoopMat() &&
sameStructType(right) && sameStructType(right, lpidx, rpidx) &&
sameReferenceType(right); sameReferenceType(right);
} }

View file

@ -35,7 +35,7 @@
#define GLSLANG_BUILD_INFO #define GLSLANG_BUILD_INFO
#define GLSLANG_VERSION_MAJOR 11 #define GLSLANG_VERSION_MAJOR 11
#define GLSLANG_VERSION_MINOR 6 #define GLSLANG_VERSION_MINOR 10
#define GLSLANG_VERSION_PATCH 0 #define GLSLANG_VERSION_PATCH 0
#define GLSLANG_VERSION_FLAVOR "" #define GLSLANG_VERSION_FLAVOR ""

View file

@ -1155,7 +1155,7 @@ public:
virtual bool isIntegerDomain() const { return type.isIntegerDomain(); } virtual bool isIntegerDomain() const { return type.isIntegerDomain(); }
bool isAtomic() const { return type.isAtomic(); } bool isAtomic() const { return type.isAtomic(); }
bool isReference() const { return type.isReference(); } bool isReference() const { return type.isReference(); }
TString getCompleteString() const { return type.getCompleteString(); } TString getCompleteString(bool enhanced = false) const { return type.getCompleteString(enhanced); }
protected: protected:
TIntermTyped& operator=(const TIntermTyped&); TIntermTyped& operator=(const TIntermTyped&);
@ -1643,6 +1643,7 @@ public:
~TIntermAggregate() { delete pragmaTable; } ~TIntermAggregate() { delete pragmaTable; }
virtual TIntermAggregate* getAsAggregate() { return this; } virtual TIntermAggregate* getAsAggregate() { return this; }
virtual const TIntermAggregate* getAsAggregate() const { return this; } virtual const TIntermAggregate* getAsAggregate() const { return this; }
virtual void updatePrecision();
virtual void setOperator(TOperator o) { op = o; } virtual void setOperator(TOperator o) { op = o; }
virtual TIntermSequence& getSequence() { return sequence; } virtual TIntermSequence& getSequence() { return sequence; }
virtual const TIntermSequence& getSequence() const { return sequence; } virtual const TIntermSequence& getSequence() const { return sequence; }

View file

@ -1,3 +0,0 @@
// This header is generated by the make-revision script.
#define GLSLANG_PATCH_LEVEL 3559

View file

@ -1,13 +0,0 @@
// The file revision.h should be updated to the latest version, somehow, on
// check-in, if glslang has changed.
//
// revision.template is the source for revision.h when using SubWCRev as the
// method of updating revision.h. You don't have to do it this way, the
// requirement is only that revision.h gets updated.
//
// revision.h is under source control so that not all consumers of glslang
// source have to figure out how to create revision.h just to get a build
// going. However, if it is not updated, it can be a version behind.
#define GLSLANG_REVISION "$WCREV$"
#define GLSLANG_DATE "$WCDATE$"

View file

@ -42,43 +42,10 @@
#include <cstdlib> #include <cstdlib>
#include <climits> #include <climits>
#ifdef _MSC_VER
#pragma warning(disable: 4146) // warning C4146: unary minus operator applied to unsigned type, result still unsigned
#endif
namespace { namespace {
using namespace glslang; using namespace glslang;
typedef union {
double d;
int i[2];
} DoubleIntUnion;
// Some helper functions
bool isNan(double x)
{
DoubleIntUnion u;
// tough to find a platform independent library function, do it directly
u.d = x;
int bitPatternL = u.i[0];
int bitPatternH = u.i[1];
return (bitPatternH & 0x7ff80000) == 0x7ff80000 &&
((bitPatternH & 0xFFFFF) != 0 || bitPatternL != 0);
}
bool isInf(double x)
{
DoubleIntUnion u;
// tough to find a platform independent library function, do it directly
u.d = x;
int bitPatternL = u.i[0];
int bitPatternH = u.i[1];
return (bitPatternH & 0x7ff00000) == 0x7ff00000 &&
(bitPatternH & 0xFFFFF) == 0 && bitPatternL == 0;
}
const double pi = 3.1415926535897932384626433832795; const double pi = 3.1415926535897932384626433832795;
} // end anonymous namespace } // end anonymous namespace
@ -535,7 +502,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TType& returnType)
case EbtFloat: newConstArray[i].setDConst(-unionArray[i].getDConst()); break; case EbtFloat: newConstArray[i].setDConst(-unionArray[i].getDConst()); break;
// Note: avoid UBSAN error regarding negating 0x80000000 // Note: avoid UBSAN error regarding negating 0x80000000
case EbtInt: newConstArray[i].setIConst( case EbtInt: newConstArray[i].setIConst(
unionArray[i].getIConst() == 0x80000000 static_cast<unsigned int>(unionArray[i].getIConst()) == 0x80000000
? -0x7FFFFFFF - 1 ? -0x7FFFFFFF - 1
: -unionArray[i].getIConst()); : -unionArray[i].getIConst());
break; break;
@ -667,12 +634,12 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TType& returnType)
case EOpIsNan: case EOpIsNan:
{ {
newConstArray[i].setBConst(isNan(unionArray[i].getDConst())); newConstArray[i].setBConst(IsNan(unionArray[i].getDConst()));
break; break;
} }
case EOpIsInf: case EOpIsInf:
{ {
newConstArray[i].setBConst(isInf(unionArray[i].getDConst())); newConstArray[i].setBConst(IsInfinity(unionArray[i].getDConst()));
break; break;
} }

View file

@ -3,7 +3,7 @@
// Copyright (C) 2012-2016 LunarG, Inc. // Copyright (C) 2012-2016 LunarG, Inc.
// Copyright (C) 2015-2020 Google, Inc. // Copyright (C) 2015-2020 Google, Inc.
// Copyright (C) 2017 ARM Limited. // Copyright (C) 2017 ARM Limited.
// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. // Modifications Copyright (C) 2020-2021 Advanced Micro Devices, Inc. All rights reserved.
// //
// All rights reserved. // All rights reserved.
// //
@ -316,6 +316,7 @@ const CustomFunction CustomFunctions[] = {
{ EOpTextureQuerySize, "textureSize", nullptr }, { EOpTextureQuerySize, "textureSize", nullptr },
{ EOpTextureQueryLod, "textureQueryLod", nullptr }, { EOpTextureQueryLod, "textureQueryLod", nullptr },
{ EOpTextureQueryLod, "textureQueryLOD", nullptr }, // extension GL_ARB_texture_query_lod
{ EOpTextureQueryLevels, "textureQueryLevels", nullptr }, { EOpTextureQueryLevels, "textureQueryLevels", nullptr },
{ EOpTextureQuerySamples, "textureSamples", nullptr }, { EOpTextureQuerySamples, "textureSamples", nullptr },
{ EOpTexture, "texture", nullptr }, { EOpTexture, "texture", nullptr },
@ -4159,106 +4160,6 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
"u16vec4 unpack16(uint64_t);" "u16vec4 unpack16(uint64_t);"
"i32vec2 unpack32(int64_t);" "i32vec2 unpack32(int64_t);"
"u32vec2 unpack32(uint64_t);" "u32vec2 unpack32(uint64_t);"
"float64_t radians(float64_t);"
"f64vec2 radians(f64vec2);"
"f64vec3 radians(f64vec3);"
"f64vec4 radians(f64vec4);"
"float64_t degrees(float64_t);"
"f64vec2 degrees(f64vec2);"
"f64vec3 degrees(f64vec3);"
"f64vec4 degrees(f64vec4);"
"float64_t sin(float64_t);"
"f64vec2 sin(f64vec2);"
"f64vec3 sin(f64vec3);"
"f64vec4 sin(f64vec4);"
"float64_t cos(float64_t);"
"f64vec2 cos(f64vec2);"
"f64vec3 cos(f64vec3);"
"f64vec4 cos(f64vec4);"
"float64_t tan(float64_t);"
"f64vec2 tan(f64vec2);"
"f64vec3 tan(f64vec3);"
"f64vec4 tan(f64vec4);"
"float64_t asin(float64_t);"
"f64vec2 asin(f64vec2);"
"f64vec3 asin(f64vec3);"
"f64vec4 asin(f64vec4);"
"float64_t acos(float64_t);"
"f64vec2 acos(f64vec2);"
"f64vec3 acos(f64vec3);"
"f64vec4 acos(f64vec4);"
"float64_t atan(float64_t, float64_t);"
"f64vec2 atan(f64vec2, f64vec2);"
"f64vec3 atan(f64vec3, f64vec3);"
"f64vec4 atan(f64vec4, f64vec4);"
"float64_t atan(float64_t);"
"f64vec2 atan(f64vec2);"
"f64vec3 atan(f64vec3);"
"f64vec4 atan(f64vec4);"
"float64_t sinh(float64_t);"
"f64vec2 sinh(f64vec2);"
"f64vec3 sinh(f64vec3);"
"f64vec4 sinh(f64vec4);"
"float64_t cosh(float64_t);"
"f64vec2 cosh(f64vec2);"
"f64vec3 cosh(f64vec3);"
"f64vec4 cosh(f64vec4);"
"float64_t tanh(float64_t);"
"f64vec2 tanh(f64vec2);"
"f64vec3 tanh(f64vec3);"
"f64vec4 tanh(f64vec4);"
"float64_t asinh(float64_t);"
"f64vec2 asinh(f64vec2);"
"f64vec3 asinh(f64vec3);"
"f64vec4 asinh(f64vec4);"
"float64_t acosh(float64_t);"
"f64vec2 acosh(f64vec2);"
"f64vec3 acosh(f64vec3);"
"f64vec4 acosh(f64vec4);"
"float64_t atanh(float64_t);"
"f64vec2 atanh(f64vec2);"
"f64vec3 atanh(f64vec3);"
"f64vec4 atanh(f64vec4);"
"float64_t pow(float64_t, float64_t);"
"f64vec2 pow(f64vec2, f64vec2);"
"f64vec3 pow(f64vec3, f64vec3);"
"f64vec4 pow(f64vec4, f64vec4);"
"float64_t exp(float64_t);"
"f64vec2 exp(f64vec2);"
"f64vec3 exp(f64vec3);"
"f64vec4 exp(f64vec4);"
"float64_t log(float64_t);"
"f64vec2 log(f64vec2);"
"f64vec3 log(f64vec3);"
"f64vec4 log(f64vec4);"
"float64_t exp2(float64_t);"
"f64vec2 exp2(f64vec2);"
"f64vec3 exp2(f64vec3);"
"f64vec4 exp2(f64vec4);"
"float64_t log2(float64_t);"
"f64vec2 log2(f64vec2);"
"f64vec3 log2(f64vec3);"
"f64vec4 log2(f64vec4);"
"\n"); "\n");
} }
@ -4369,7 +4270,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
// //
//============================================================================ //============================================================================
if (profile != EEsProfile && version >= 400) { if (profile != EEsProfile && (version >= 400 || version == 150)) {
stageBuiltins[EShLangGeometry].append( stageBuiltins[EShLangGeometry].append(
"void EmitStreamVertex(int);" "void EmitStreamVertex(int);"
"void EndStreamPrimitive(int);" "void EndStreamPrimitive(int);"
@ -4653,7 +4554,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
"\n"); "\n");
} }
// GL_ARB_shader_clock & GL_EXT_shader_realtime_clock // GL_ARB_shader_clock& GL_EXT_shader_realtime_clock
if (profile != EEsProfile && version >= 450) { if (profile != EEsProfile && version >= 450) {
commonBuiltins.append( commonBuiltins.append(
"uvec2 clock2x32ARB();" "uvec2 clock2x32ARB();"
@ -5174,9 +5075,13 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
); );
} }
if (version >= 450) if (version >= 430)
stageBuiltins[EShLangVertex].append( stageBuiltins[EShLangVertex].append(
"out int gl_ViewportMask[];" // GL_NV_viewport_array2 "out int gl_ViewportMask[];" // GL_NV_viewport_array2
);
if (version >= 450)
stageBuiltins[EShLangVertex].append(
"out int gl_SecondaryViewportMaskNV[];" // GL_NV_stereo_view_rendering "out int gl_SecondaryViewportMaskNV[];" // GL_NV_stereo_view_rendering
"out vec4 gl_SecondaryPositionNV;" // GL_NV_stereo_view_rendering "out vec4 gl_SecondaryPositionNV;" // GL_NV_stereo_view_rendering
"out vec4 gl_PositionPerViewNV[];" // GL_NVX_multiview_per_view_attributes "out vec4 gl_PositionPerViewNV[];" // GL_NVX_multiview_per_view_attributes
@ -5312,9 +5217,13 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
"in int gl_InvocationID;" "in int gl_InvocationID;"
); );
if (version >= 450) if (version >= 430)
stageBuiltins[EShLangGeometry].append( stageBuiltins[EShLangGeometry].append(
"out int gl_ViewportMask[];" // GL_NV_viewport_array2 "out int gl_ViewportMask[];" // GL_NV_viewport_array2
);
if (version >= 450)
stageBuiltins[EShLangGeometry].append(
"out int gl_SecondaryViewportMaskNV[];" // GL_NV_stereo_view_rendering "out int gl_SecondaryViewportMaskNV[];" // GL_NV_stereo_view_rendering
"out vec4 gl_SecondaryPositionNV;" // GL_NV_stereo_view_rendering "out vec4 gl_SecondaryPositionNV;" // GL_NV_stereo_view_rendering
"out vec4 gl_PositionPerViewNV[];" // GL_NVX_multiview_per_view_attributes "out vec4 gl_PositionPerViewNV[];" // GL_NVX_multiview_per_view_attributes
@ -5390,7 +5299,13 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
if (version >= 450) if (version >= 450)
stageBuiltins[EShLangTessControl].append( stageBuiltins[EShLangTessControl].append(
"float gl_CullDistance[];" "float gl_CullDistance[];"
);
if (version >= 430)
stageBuiltins[EShLangTessControl].append(
"int gl_ViewportMask[];" // GL_NV_viewport_array2 "int gl_ViewportMask[];" // GL_NV_viewport_array2
);
if (version >= 450)
stageBuiltins[EShLangTessControl].append(
"vec4 gl_SecondaryPositionNV;" // GL_NV_stereo_view_rendering "vec4 gl_SecondaryPositionNV;" // GL_NV_stereo_view_rendering
"int gl_SecondaryViewportMaskNV[];" // GL_NV_stereo_view_rendering "int gl_SecondaryViewportMaskNV[];" // GL_NV_stereo_view_rendering
"vec4 gl_PositionPerViewNV[];" // GL_NVX_multiview_per_view_attributes "vec4 gl_PositionPerViewNV[];" // GL_NVX_multiview_per_view_attributes
@ -5493,9 +5408,13 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
"out int gl_Layer;" "out int gl_Layer;"
"\n"); "\n");
if (version >= 450) if (version >= 430)
stageBuiltins[EShLangTessEvaluation].append( stageBuiltins[EShLangTessEvaluation].append(
"out int gl_ViewportMask[];" // GL_NV_viewport_array2 "out int gl_ViewportMask[];" // GL_NV_viewport_array2
);
if (version >= 450)
stageBuiltins[EShLangTessEvaluation].append(
"out vec4 gl_SecondaryPositionNV;" // GL_NV_stereo_view_rendering "out vec4 gl_SecondaryPositionNV;" // GL_NV_stereo_view_rendering
"out int gl_SecondaryViewportMaskNV[];" // GL_NV_stereo_view_rendering "out int gl_SecondaryViewportMaskNV[];" // GL_NV_stereo_view_rendering
"out vec4 gl_PositionPerViewNV[];" // GL_NVX_multiview_per_view_attributes "out vec4 gl_PositionPerViewNV[];" // GL_NVX_multiview_per_view_attributes
@ -5652,6 +5571,8 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
"flat in int gl_InvocationsPerPixelNV;" "flat in int gl_InvocationsPerPixelNV;"
"in vec3 gl_BaryCoordNV;" // GL_NV_fragment_shader_barycentric "in vec3 gl_BaryCoordNV;" // GL_NV_fragment_shader_barycentric
"in vec3 gl_BaryCoordNoPerspNV;" "in vec3 gl_BaryCoordNoPerspNV;"
"in vec3 gl_BaryCoordEXT;" // GL_EXT_fragment_shader_barycentric
"in vec3 gl_BaryCoordNoPerspEXT;"
); );
if (version >= 450) if (version >= 450)
@ -5716,7 +5637,9 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
stageBuiltins[EShLangFragment].append( stageBuiltins[EShLangFragment].append(
"in vec3 gl_BaryCoordNV;" "in vec3 gl_BaryCoordNV;"
"in vec3 gl_BaryCoordNoPerspNV;" "in vec3 gl_BaryCoordNoPerspNV;"
); "in vec3 gl_BaryCoordEXT;"
"in vec3 gl_BaryCoordNoPerspEXT;"
);
if (version >= 310) if (version >= 310)
stageBuiltins[EShLangFragment].append( stageBuiltins[EShLangFragment].append(
"flat in highp int gl_ShadingRateEXT;" // GL_EXT_fragment_shading_rate "flat in highp int gl_ShadingRateEXT;" // GL_EXT_fragment_shading_rate
@ -5938,6 +5861,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
"in uint gl_IncomingRayFlagsNV;" "in uint gl_IncomingRayFlagsNV;"
"in uint gl_IncomingRayFlagsEXT;" "in uint gl_IncomingRayFlagsEXT;"
"in float gl_CurrentRayTimeNV;" "in float gl_CurrentRayTimeNV;"
"in uint gl_CullMaskEXT;"
"\n"; "\n";
const char *hitDecls = const char *hitDecls =
"in uvec3 gl_LaunchIDNV;" "in uvec3 gl_LaunchIDNV;"
@ -5974,6 +5898,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
"in uint gl_IncomingRayFlagsNV;" "in uint gl_IncomingRayFlagsNV;"
"in uint gl_IncomingRayFlagsEXT;" "in uint gl_IncomingRayFlagsEXT;"
"in float gl_CurrentRayTimeNV;" "in float gl_CurrentRayTimeNV;"
"in uint gl_CullMaskEXT;"
"\n"; "\n";
const char *missDecls = const char *missDecls =
"in uvec3 gl_LaunchIDNV;" "in uvec3 gl_LaunchIDNV;"
@ -5993,6 +5918,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
"in uint gl_IncomingRayFlagsNV;" "in uint gl_IncomingRayFlagsNV;"
"in uint gl_IncomingRayFlagsEXT;" "in uint gl_IncomingRayFlagsEXT;"
"in float gl_CurrentRayTimeNV;" "in float gl_CurrentRayTimeNV;"
"in uint gl_CullMaskEXT;"
"\n"; "\n";
const char *callableDecls = const char *callableDecls =
@ -6329,38 +6255,44 @@ void TBuiltIns::addQueryFunctions(TSampler sampler, const TString& typeName, int
// //
// textureQueryLod(), fragment stage only // textureQueryLod(), fragment stage only
// Also enabled with extension GL_ARB_texture_query_lod // Also enabled with extension GL_ARB_texture_query_lod
// Extension GL_ARB_texture_query_lod says that textureQueryLOD() also exist at extension.
if (profile != EEsProfile && version >= 150 && sampler.isCombined() && sampler.dim != EsdRect && if (profile != EEsProfile && version >= 150 && sampler.isCombined() && sampler.dim != EsdRect &&
! sampler.isMultiSample() && ! sampler.isBuffer()) { ! sampler.isMultiSample() && ! sampler.isBuffer()) {
for (int f16TexAddr = 0; f16TexAddr < 2; ++f16TexAddr) {
if (f16TexAddr && sampler.type != EbtFloat16)
continue;
stageBuiltins[EShLangFragment].append("vec2 textureQueryLod(");
stageBuiltins[EShLangFragment].append(typeName);
if (dimMap[sampler.dim] == 1)
if (f16TexAddr)
stageBuiltins[EShLangFragment].append(", float16_t");
else
stageBuiltins[EShLangFragment].append(", float");
else {
if (f16TexAddr)
stageBuiltins[EShLangFragment].append(", f16vec");
else
stageBuiltins[EShLangFragment].append(", vec");
stageBuiltins[EShLangFragment].append(postfixes[dimMap[sampler.dim]]);
}
stageBuiltins[EShLangFragment].append(");\n");
}
stageBuiltins[EShLangCompute].append("vec2 textureQueryLod("); const TString funcName[2] = {"vec2 textureQueryLod(", "vec2 textureQueryLOD("};
stageBuiltins[EShLangCompute].append(typeName);
if (dimMap[sampler.dim] == 1) for (int i = 0; i < 2; ++i){
stageBuiltins[EShLangCompute].append(", float"); for (int f16TexAddr = 0; f16TexAddr < 2; ++f16TexAddr) {
else { if (f16TexAddr && sampler.type != EbtFloat16)
stageBuiltins[EShLangCompute].append(", vec"); continue;
stageBuiltins[EShLangCompute].append(postfixes[dimMap[sampler.dim]]); stageBuiltins[EShLangFragment].append(funcName[i]);
stageBuiltins[EShLangFragment].append(typeName);
if (dimMap[sampler.dim] == 1)
if (f16TexAddr)
stageBuiltins[EShLangFragment].append(", float16_t");
else
stageBuiltins[EShLangFragment].append(", float");
else {
if (f16TexAddr)
stageBuiltins[EShLangFragment].append(", f16vec");
else
stageBuiltins[EShLangFragment].append(", vec");
stageBuiltins[EShLangFragment].append(postfixes[dimMap[sampler.dim]]);
}
stageBuiltins[EShLangFragment].append(");\n");
}
stageBuiltins[EShLangCompute].append(funcName[i]);
stageBuiltins[EShLangCompute].append(typeName);
if (dimMap[sampler.dim] == 1)
stageBuiltins[EShLangCompute].append(", float");
else {
stageBuiltins[EShLangCompute].append(", vec");
stageBuiltins[EShLangCompute].append(postfixes[dimMap[sampler.dim]]);
}
stageBuiltins[EShLangCompute].append(");\n");
} }
stageBuiltins[EShLangCompute].append(");\n");
} }
// //
@ -7701,6 +7633,11 @@ static void BuiltInVariable(const char* name, TBuiltInVariable builtIn, TSymbolT
symQualifier.builtIn = builtIn; symQualifier.builtIn = builtIn;
} }
static void RetargetVariable(const char* from, const char* to, TSymbolTable& symbolTable)
{
symbolTable.retargetSymbol(from, to);
}
// //
// For built-in variables inside a named block. // For built-in variables inside a named block.
// SpecialQualifier() won't ever go inside a block; their member's qualifier come // SpecialQualifier() won't ever go inside a block; their member's qualifier come
@ -7768,8 +7705,8 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
if (spvVersion.vulkan > 0 && spvVersion.vulkanRelaxed) { if (spvVersion.vulkan > 0 && spvVersion.vulkanRelaxed) {
// treat these built-ins as aliases of VertexIndex and InstanceIndex // treat these built-ins as aliases of VertexIndex and InstanceIndex
BuiltInVariable("gl_VertexID", EbvVertexIndex, symbolTable); RetargetVariable("gl_InstanceID", "gl_InstanceIndex", symbolTable);
BuiltInVariable("gl_InstanceID", EbvInstanceIndex, symbolTable); RetargetVariable("gl_VertexID", "gl_VertexIndex", symbolTable);
} }
if (profile != EEsProfile) { if (profile != EEsProfile) {
@ -8140,7 +8077,7 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
} }
if (profile != EEsProfile && version < 400) { if (profile != EEsProfile && version < 400) {
symbolTable.setFunctionExtensions("textureQueryLod", 1, &E_GL_ARB_texture_query_lod); symbolTable.setFunctionExtensions("textureQueryLOD", 1, &E_GL_ARB_texture_query_lod);
} }
if (profile != EEsProfile && version >= 460) { if (profile != EEsProfile && version >= 460) {
@ -8388,6 +8325,10 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
symbolTable.setVariableExtensions("gl_BaryCoordNoPerspNV", 1, &E_GL_NV_fragment_shader_barycentric); symbolTable.setVariableExtensions("gl_BaryCoordNoPerspNV", 1, &E_GL_NV_fragment_shader_barycentric);
BuiltInVariable("gl_BaryCoordNV", EbvBaryCoordNV, symbolTable); BuiltInVariable("gl_BaryCoordNV", EbvBaryCoordNV, symbolTable);
BuiltInVariable("gl_BaryCoordNoPerspNV", EbvBaryCoordNoPerspNV, symbolTable); BuiltInVariable("gl_BaryCoordNoPerspNV", EbvBaryCoordNoPerspNV, symbolTable);
symbolTable.setVariableExtensions("gl_BaryCoordEXT", 1, &E_GL_EXT_fragment_shader_barycentric);
symbolTable.setVariableExtensions("gl_BaryCoordNoPerspEXT", 1, &E_GL_EXT_fragment_shader_barycentric);
BuiltInVariable("gl_BaryCoordEXT", EbvBaryCoordEXT, symbolTable);
BuiltInVariable("gl_BaryCoordNoPerspEXT", EbvBaryCoordNoPerspEXT, symbolTable);
} }
if ((profile != EEsProfile && version >= 450) || if ((profile != EEsProfile && version >= 450) ||
@ -8403,7 +8344,7 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
symbolTable.setFunctionExtensions("clockARB", 1, &E_GL_ARB_shader_clock); symbolTable.setFunctionExtensions("clockARB", 1, &E_GL_ARB_shader_clock);
symbolTable.setFunctionExtensions("clock2x32ARB", 1, &E_GL_ARB_shader_clock); symbolTable.setFunctionExtensions("clock2x32ARB", 1, &E_GL_ARB_shader_clock);
symbolTable.setFunctionExtensions("clockRealtimeEXT", 1, &E_GL_EXT_shader_realtime_clock); symbolTable.setFunctionExtensions("clockRealtimeEXT", 1, &E_GL_EXT_shader_realtime_clock);
symbolTable.setFunctionExtensions("clockRealtime2x32EXT", 1, &E_GL_EXT_shader_realtime_clock); symbolTable.setFunctionExtensions("clockRealtime2x32EXT", 1, &E_GL_EXT_shader_realtime_clock);
if (profile == EEsProfile && version < 320) { if (profile == EEsProfile && version < 320) {
@ -8423,10 +8364,11 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
} }
if (profile != EEsProfile && version < 330 ) { if (profile != EEsProfile && version < 330 ) {
symbolTable.setFunctionExtensions("floatBitsToInt", 1, &E_GL_ARB_shader_bit_encoding); const char* bitsConvertExt[2] = {E_GL_ARB_shader_bit_encoding, E_GL_ARB_gpu_shader5};
symbolTable.setFunctionExtensions("floatBitsToUint", 1, &E_GL_ARB_shader_bit_encoding); symbolTable.setFunctionExtensions("floatBitsToInt", 2, bitsConvertExt);
symbolTable.setFunctionExtensions("intBitsToFloat", 1, &E_GL_ARB_shader_bit_encoding); symbolTable.setFunctionExtensions("floatBitsToUint", 2, bitsConvertExt);
symbolTable.setFunctionExtensions("uintBitsToFloat", 1, &E_GL_ARB_shader_bit_encoding); symbolTable.setFunctionExtensions("intBitsToFloat", 2, bitsConvertExt);
symbolTable.setFunctionExtensions("uintBitsToFloat", 2, bitsConvertExt);
} }
if (profile != EEsProfile && version < 430 ) { if (profile != EEsProfile && version < 430 ) {
@ -8812,6 +8754,7 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
symbolTable.setVariableExtensions("gl_RayTminEXT", 1, &E_GL_EXT_ray_tracing); symbolTable.setVariableExtensions("gl_RayTminEXT", 1, &E_GL_EXT_ray_tracing);
symbolTable.setVariableExtensions("gl_RayTmaxNV", 1, &E_GL_NV_ray_tracing); symbolTable.setVariableExtensions("gl_RayTmaxNV", 1, &E_GL_NV_ray_tracing);
symbolTable.setVariableExtensions("gl_RayTmaxEXT", 1, &E_GL_EXT_ray_tracing); symbolTable.setVariableExtensions("gl_RayTmaxEXT", 1, &E_GL_EXT_ray_tracing);
symbolTable.setVariableExtensions("gl_CullMaskEXT", 1, &E_GL_EXT_ray_cull_mask);
symbolTable.setVariableExtensions("gl_HitTNV", 1, &E_GL_NV_ray_tracing); symbolTable.setVariableExtensions("gl_HitTNV", 1, &E_GL_NV_ray_tracing);
symbolTable.setVariableExtensions("gl_HitTEXT", 1, &E_GL_EXT_ray_tracing); symbolTable.setVariableExtensions("gl_HitTEXT", 1, &E_GL_EXT_ray_tracing);
symbolTable.setVariableExtensions("gl_HitKindNV", 1, &E_GL_NV_ray_tracing); symbolTable.setVariableExtensions("gl_HitKindNV", 1, &E_GL_NV_ray_tracing);
@ -8861,6 +8804,7 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
BuiltInVariable("gl_RayTminEXT", EbvRayTmin, symbolTable); BuiltInVariable("gl_RayTminEXT", EbvRayTmin, symbolTable);
BuiltInVariable("gl_RayTmaxNV", EbvRayTmax, symbolTable); BuiltInVariable("gl_RayTmaxNV", EbvRayTmax, symbolTable);
BuiltInVariable("gl_RayTmaxEXT", EbvRayTmax, symbolTable); BuiltInVariable("gl_RayTmaxEXT", EbvRayTmax, symbolTable);
BuiltInVariable("gl_CullMaskEXT", EbvCullMask, symbolTable);
BuiltInVariable("gl_HitTNV", EbvHitT, symbolTable); BuiltInVariable("gl_HitTNV", EbvHitT, symbolTable);
BuiltInVariable("gl_HitTEXT", EbvHitT, symbolTable); BuiltInVariable("gl_HitTEXT", EbvHitT, symbolTable);
BuiltInVariable("gl_HitKindNV", EbvHitKind, symbolTable); BuiltInVariable("gl_HitKindNV", EbvHitKind, symbolTable);

View file

@ -416,20 +416,24 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermTyped* child,
// TODO: but, did this bypass constant folding? // TODO: but, did this bypass constant folding?
// //
switch (op) { switch (op) {
case EOpConstructInt8: case EOpConstructInt8:
case EOpConstructUint8: case EOpConstructUint8:
case EOpConstructInt16: case EOpConstructInt16:
case EOpConstructUint16: case EOpConstructUint16:
case EOpConstructInt: case EOpConstructInt:
case EOpConstructUint: case EOpConstructUint:
case EOpConstructInt64: case EOpConstructInt64:
case EOpConstructUint64: case EOpConstructUint64:
case EOpConstructBool: case EOpConstructBool:
case EOpConstructFloat: case EOpConstructFloat:
case EOpConstructDouble: case EOpConstructDouble:
case EOpConstructFloat16: case EOpConstructFloat16: {
return child; TIntermUnary* unary_node = child->getAsUnaryNode();
default: break; // some compilers want this if (unary_node != nullptr)
unary_node->updatePrecision();
return child;
}
default: break; // some compilers want this
} }
// //
@ -2762,7 +2766,7 @@ void TIntermBranch::updatePrecision(TPrecisionQualifier parentPrecision)
return; return;
if (exp->getBasicType() == EbtInt || exp->getBasicType() == EbtUint || if (exp->getBasicType() == EbtInt || exp->getBasicType() == EbtUint ||
exp->getBasicType() == EbtFloat || exp->getBasicType() == EbtFloat16) { exp->getBasicType() == EbtFloat) {
if (parentPrecision != EpqNone && exp->getQualifier().precision == EpqNone) { if (parentPrecision != EpqNone && exp->getQualifier().precision == EpqNone) {
exp->propagatePrecision(parentPrecision); exp->propagatePrecision(parentPrecision);
} }
@ -3280,7 +3284,7 @@ bool TIntermediate::promoteUnary(TIntermUnary& node)
void TIntermUnary::updatePrecision() void TIntermUnary::updatePrecision()
{ {
if (getBasicType() == EbtInt || getBasicType() == EbtUint || if (getBasicType() == EbtInt || getBasicType() == EbtUint ||
getBasicType() == EbtFloat || getBasicType() == EbtFloat16) { getBasicType() == EbtFloat) {
if (operand->getQualifier().precision > getQualifier().precision) if (operand->getQualifier().precision > getQualifier().precision)
getQualifier().precision = operand->getQualifier().precision; getQualifier().precision = operand->getQualifier().precision;
} }
@ -3776,12 +3780,34 @@ bool TIntermediate::promoteAggregate(TIntermAggregate& node)
return false; return false;
} }
// Propagate precision qualifiers *up* from children to parent, and then
// back *down* again to the children's subtrees.
void TIntermAggregate::updatePrecision()
{
if (getBasicType() == EbtInt || getBasicType() == EbtUint ||
getBasicType() == EbtFloat) {
TPrecisionQualifier maxPrecision = EpqNone;
TIntermSequence operands = getSequence();
for (unsigned int i = 0; i < operands.size(); ++i) {
TIntermTyped* typedNode = operands[i]->getAsTyped();
assert(typedNode);
maxPrecision = std::max(maxPrecision, typedNode->getQualifier().precision);
}
getQualifier().precision = maxPrecision;
for (unsigned int i = 0; i < operands.size(); ++i) {
TIntermTyped* typedNode = operands[i]->getAsTyped();
assert(typedNode);
typedNode->propagatePrecision(maxPrecision);
}
}
}
// Propagate precision qualifiers *up* from children to parent, and then // Propagate precision qualifiers *up* from children to parent, and then
// back *down* again to the children's subtrees. // back *down* again to the children's subtrees.
void TIntermBinary::updatePrecision() void TIntermBinary::updatePrecision()
{ {
if (getBasicType() == EbtInt || getBasicType() == EbtUint || if (getBasicType() == EbtInt || getBasicType() == EbtUint ||
getBasicType() == EbtFloat || getBasicType() == EbtFloat16) { getBasicType() == EbtFloat) {
if (op == EOpRightShift || op == EOpLeftShift) { if (op == EOpRightShift || op == EOpLeftShift) {
// For shifts get precision from left side only and thus no need to propagate // For shifts get precision from left side only and thus no need to propagate
getQualifier().precision = left->getQualifier().precision; getQualifier().precision = left->getQualifier().precision;
@ -3876,7 +3902,7 @@ TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermC
case EbtFloat16: PROMOTE(setDConst, double, Get); break; \ case EbtFloat16: PROMOTE(setDConst, double, Get); break; \
case EbtFloat: PROMOTE(setDConst, double, Get); break; \ case EbtFloat: PROMOTE(setDConst, double, Get); break; \
case EbtDouble: PROMOTE(setDConst, double, Get); break; \ case EbtDouble: PROMOTE(setDConst, double, Get); break; \
case EbtInt8: PROMOTE(setI8Const, char, Get); break; \ case EbtInt8: PROMOTE(setI8Const, signed char, Get); break; \
case EbtInt16: PROMOTE(setI16Const, short, Get); break; \ case EbtInt16: PROMOTE(setI16Const, short, Get); break; \
case EbtInt: PROMOTE(setIConst, int, Get); break; \ case EbtInt: PROMOTE(setIConst, int, Get); break; \
case EbtInt64: PROMOTE(setI64Const, long long, Get); break; \ case EbtInt64: PROMOTE(setI64Const, long long, Get); break; \

View file

@ -74,6 +74,9 @@ void C_DECL TParseContextBase::error(const TSourceLoc& loc, const char* szReason
{ {
if (messages & EShMsgOnlyPreprocessor) if (messages & EShMsgOnlyPreprocessor)
return; return;
// If enhanced msg readability, only print one error
if (messages & EShMsgEnhanced && numErrors > 0)
return;
va_list args; va_list args;
va_start(args, szExtraInfoFormat); va_start(args, szExtraInfoFormat);
outputMessage(loc, szReason, szToken, szExtraInfoFormat, EPrefixError, args); outputMessage(loc, szReason, szToken, szExtraInfoFormat, EPrefixError, args);
@ -622,6 +625,19 @@ void TParseContextBase::growGlobalUniformBlock(const TSourceLoc& loc, TType& mem
globalUniformBlock->getWritableType().getQualifier().layoutBinding = globalUniformBinding; globalUniformBlock->getWritableType().getQualifier().layoutBinding = globalUniformBinding;
globalUniformBlock->getWritableType().getQualifier().layoutSet = globalUniformSet; globalUniformBlock->getWritableType().getQualifier().layoutSet = globalUniformSet;
// Check for declarations of this default uniform that already exist due to other compilation units.
TSymbol* symbol = symbolTable.find(memberName);
if (symbol) {
if (memberType != symbol->getType()) {
TString err;
err += "\"" + memberType.getCompleteString() + "\"";
err += " versus ";
err += "\"" + symbol->getType().getCompleteString() + "\"";
error(loc, "Types must match:", memberType.getFieldName().c_str(), err.c_str());
}
return;
}
// Add the requested member as a member to the global block. // Add the requested member as a member to the global block.
TType* type = new TType; TType* type = new TType;
type->shallowCopy(memberType); type->shallowCopy(memberType);

View file

@ -716,7 +716,7 @@ bool TParseContext::isIoResizeArray(const TType& type) const
(language == EShLangTessControl && type.getQualifier().storage == EvqVaryingOut && (language == EShLangTessControl && type.getQualifier().storage == EvqVaryingOut &&
! type.getQualifier().patch) || ! type.getQualifier().patch) ||
(language == EShLangFragment && type.getQualifier().storage == EvqVaryingIn && (language == EShLangFragment && type.getQualifier().storage == EvqVaryingIn &&
type.getQualifier().pervertexNV) || (type.getQualifier().pervertexNV || type.getQualifier().pervertexEXT)) ||
(language == EShLangMeshNV && type.getQualifier().storage == EvqVaryingOut && (language == EShLangMeshNV && type.getQualifier().storage == EvqVaryingOut &&
!type.getQualifier().perTaskNV)); !type.getQualifier().perTaskNV));
} }
@ -856,7 +856,7 @@ void TParseContext::checkIoArrayConsistency(const TSourceLoc& loc, int requiredS
error(loc, "inconsistent output number of vertices for array size of", feature, name.c_str()); error(loc, "inconsistent output number of vertices for array size of", feature, name.c_str());
else if (language == EShLangFragment) { else if (language == EShLangFragment) {
if (type.getOuterArraySize() > requiredSize) if (type.getOuterArraySize() > requiredSize)
error(loc, " cannot be greater than 3 for pervertexNV", feature, name.c_str()); error(loc, " cannot be greater than 3 for pervertexEXT", feature, name.c_str());
} }
else if (language == EShLangMeshNV) else if (language == EShLangMeshNV)
error(loc, "inconsistent output array size of", feature, name.c_str()); error(loc, "inconsistent output array size of", feature, name.c_str());
@ -902,8 +902,10 @@ TIntermTyped* TParseContext::handleBinaryMath(const TSourceLoc& loc, const char*
result = intermediate.addBinaryMath(op, left, right, loc); result = intermediate.addBinaryMath(op, left, right, loc);
} }
if (result == nullptr) if (result == nullptr) {
binaryOpError(loc, str, left->getCompleteString(), right->getCompleteString()); bool enhanced = intermediate.getEnhancedMsgs();
binaryOpError(loc, str, left->getCompleteString(enhanced), right->getCompleteString(enhanced));
}
return result; return result;
} }
@ -926,8 +928,10 @@ TIntermTyped* TParseContext::handleUnaryMath(const TSourceLoc& loc, const char*
if (result) if (result)
return result; return result;
else else {
unaryOpError(loc, str, childNode->getCompleteString()); bool enhanced = intermediate.getEnhancedMsgs();
unaryOpError(loc, str, childNode->getCompleteString(enhanced));
}
return childNode; return childNode;
} }
@ -953,8 +957,8 @@ TIntermTyped* TParseContext::handleDotDereference(const TSourceLoc& loc, TInterm
requireProfile(loc, ~EEsProfile, feature); requireProfile(loc, ~EEsProfile, feature);
profileRequires(loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, feature); profileRequires(loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, feature);
} else if (!base->getType().isCoopMat()) { } 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; return base;
} }
@ -1005,10 +1009,16 @@ TIntermTyped* TParseContext::handleDotDereference(const TSourceLoc& loc, TInterm
intermediate.addIoAccessed(field); intermediate.addIoAccessed(field);
} }
inheritMemoryQualifiers(base->getQualifier(), result->getWritableType().getQualifier()); inheritMemoryQualifiers(base->getQualifier(), result->getWritableType().getQualifier());
} else } else {
error(loc, "no such field in structure", field.c_str(), ""); 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 } 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 // Propagate noContraction up the dereference chain
if (base->getQualifier().isNoContraction()) if (base->getQualifier().isNoContraction())
@ -1314,14 +1324,14 @@ TIntermTyped* TParseContext::handleFunctionCall(const TSourceLoc& loc, TFunction
// //
result = addConstructor(loc, arguments, type); result = addConstructor(loc, arguments, type);
if (result == nullptr) 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 { } else {
// //
// Find it in the symbol table. // Find it in the symbol table.
// //
const TFunction* fnCandidate; const TFunction* fnCandidate;
bool builtIn; bool builtIn {false};
fnCandidate = findFunction(loc, *function, builtIn); fnCandidate = findFunction(loc, *function, builtIn);
if (fnCandidate) { if (fnCandidate) {
// This is a declared function that might map to // This is a declared function that might map to
@ -1494,7 +1504,7 @@ TIntermTyped* TParseContext::handleBuiltInFunctionCall(TSourceLoc loc, TIntermNo
else else
error(arguments->getLoc(), " wrong operand type", "Internal Error", error(arguments->getLoc(), " wrong operand type", "Internal Error",
"built in unary operator function. Type: %s", "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()) } else if (result->getAsOperator())
builtInOpCheck(loc, function, *result->getAsOperator()); builtInOpCheck(loc, function, *result->getAsOperator());
@ -2317,7 +2327,7 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan
error(loc, "argument must be compile-time constant", "payload number", "a"); error(loc, "argument must be compile-time constant", "payload number", "a");
else { else {
unsigned int location = (*argp)[10]->getAsConstantUnion()->getAsConstantUnion()->getConstArray()[0].getUConst(); unsigned int location = (*argp)[10]->getAsConstantUnion()->getAsConstantUnion()->getConstArray()[0].getUConst();
if (intermediate.checkLocationRT(0, location) < 0) if (!extensionTurnedOn(E_GL_EXT_spirv_intrinsics) && intermediate.checkLocationRT(0, location) < 0)
error(loc, "with layout(location =", "no rayPayloadEXT/rayPayloadInEXT declared", "%d)", location); error(loc, "with layout(location =", "no rayPayloadEXT/rayPayloadInEXT declared", "%d)", location);
} }
break; break;
@ -2330,7 +2340,7 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan
error(loc, "argument must be compile-time constant", "callable data number", ""); error(loc, "argument must be compile-time constant", "callable data number", "");
else { else {
unsigned int location = (*argp)[1]->getAsConstantUnion()->getAsConstantUnion()->getConstArray()[0].getUConst(); unsigned int location = (*argp)[1]->getAsConstantUnion()->getAsConstantUnion()->getConstArray()[0].getUConst();
if (intermediate.checkLocationRT(1, location) < 0) if (!extensionTurnedOn(E_GL_EXT_spirv_intrinsics) && intermediate.checkLocationRT(1, location) < 0)
error(loc, "with layout(location =", "no callableDataEXT/callableDataInEXT declared", "%d)", location); error(loc, "with layout(location =", "no callableDataEXT/callableDataInEXT declared", "%d)", location);
} }
break; break;
@ -2495,6 +2505,8 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan
case EOpEmitStreamVertex: case EOpEmitStreamVertex:
case EOpEndStreamPrimitive: case EOpEndStreamPrimitive:
if (version == 150)
requireExtensions(loc, 1, &E_GL_ARB_gpu_shader5, "if the verison is 150 , the EmitStreamVertex and EndStreamPrimitive only support at extension GL_ARB_gpu_shader5");
intermediate.setMultiStream(); intermediate.setMultiStream();
break; break;
@ -2597,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. // Check that if extended types are being used that the correct extensions are enabled.
if (arg0 != nullptr) { if (arg0 != nullptr) {
const TType& type = arg0->getType(); const TType& type = arg0->getType();
bool enhanced = intermediate.getEnhancedMsgs();
switch (type.getBasicType()) { switch (type.getBasicType()) {
default: default:
break; break;
case EbtInt8: case EbtInt8:
case EbtUint8: 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; break;
case EbtInt16: case EbtInt16:
case EbtUint16: 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; break;
case EbtInt64: case EbtInt64:
case EbtUint64: 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; break;
case EbtFloat16: 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; break;
} }
} }
@ -2786,7 +2799,10 @@ TFunction* TParseContext::handleConstructorCall(const TSourceLoc& loc, const TPu
TOperator op = intermediate.mapTypeToConstructorOp(type); TOperator op = intermediate.mapTypeToConstructorOp(type);
if (op == EOpNull) { if (op == EOpNull) {
error(loc, "cannot construct this type", type.getBasicString(), ""); if (intermediate.getEnhancedMsgs() && type.getBasicType() == EbtSampler)
error(loc, "function not supported in this version; use texture() instead", "texture*D*", "");
else
error(loc, "cannot construct this type", type.getBasicString(), "");
op = EOpConstructFloat; op = EOpConstructFloat;
TType errorType(EbtFloat); TType errorType(EbtFloat);
type.shallowCopy(errorType); type.shallowCopy(errorType);
@ -3029,11 +3045,14 @@ void TParseContext::constantValueCheck(TIntermTyped* node, const char* token)
// //
// Both test, and if necessary spit out an error, to see if the node is really // Both test, and if necessary spit out an error, to see if the node is really
// an integer. // a 32-bit integer or can implicitly convert to one.
// //
void TParseContext::integerCheck(const TIntermTyped* node, const char* token) void TParseContext::integerCheck(const TIntermTyped* node, const char* token)
{ {
if ((node->getBasicType() == EbtInt || node->getBasicType() == EbtUint) && node->isScalar()) auto from_type = node->getBasicType();
if ((from_type == EbtInt || from_type == EbtUint ||
intermediate.canImplicitlyPromote(from_type, EbtInt, EOpNull) ||
intermediate.canImplicitlyPromote(from_type, EbtUint, EOpNull)) && node->isScalar())
return; return;
error(node->getLoc(), "scalar integer expression required", token, ""); error(node->getLoc(), "scalar integer expression required", token, "");
@ -3193,6 +3212,12 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T
break; 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 // See if it's a matrix
bool constructingMatrix = false; bool constructingMatrix = false;
switch (op) { switch (op) {
@ -3250,7 +3275,7 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T
if (function[arg].type->isArray()) { if (function[arg].type->isArray()) {
if (function[arg].type->isUnsizedArray()) { if (function[arg].type->isUnsizedArray()) {
// Can't construct from an unsized array. // 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; return true;
} }
arrayArg = true; arrayArg = true;
@ -3280,13 +3305,13 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T
intArgument = true; intArgument = true;
if (type.isStruct()) { if (type.isStruct()) {
if (function[arg].type->contains16BitFloat()) { 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()) { 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()) { 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");
} }
} }
} }
@ -3300,9 +3325,9 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T
case EOpConstructF16Vec3: case EOpConstructF16Vec3:
case EOpConstructF16Vec4: case EOpConstructF16Vec4:
if (type.isArray()) 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) 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; break;
case EOpConstructUint16: case EOpConstructUint16:
case EOpConstructU16Vec2: case EOpConstructU16Vec2:
@ -3313,9 +3338,9 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T
case EOpConstructI16Vec3: case EOpConstructI16Vec3:
case EOpConstructI16Vec4: case EOpConstructI16Vec4:
if (type.isArray()) 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) 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; break;
case EOpConstructUint8: case EOpConstructUint8:
case EOpConstructU8Vec2: case EOpConstructU8Vec2:
@ -3326,9 +3351,9 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T
case EOpConstructI8Vec3: case EOpConstructI8Vec3:
case EOpConstructI8Vec4: case EOpConstructI8Vec4:
if (type.isArray()) 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) 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; break;
default: default:
break; break;
@ -3410,7 +3435,7 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T
if (type.isArray()) { if (type.isArray()) {
if (function.getParamCount() == 0) { 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; return true;
} }
@ -3418,7 +3443,7 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T
// auto adapt the constructor type to the number of arguments // auto adapt the constructor type to the number of arguments
type.changeOuterArraySize(function.getParamCount()); type.changeOuterArraySize(function.getParamCount());
} else if (type.getOuterArraySize() != 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; return true;
} }
@ -3431,7 +3456,7 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T
// At least the dimensionalities have to match. // At least the dimensionalities have to match.
if (! function[0].type->isArray() || if (! function[0].type->isArray() ||
arraySizes.getNumDims() != function[0].type->getArraySizes()->getNumDims() + 1) { 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; return true;
} }
@ -3448,7 +3473,7 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T
} }
if (arrayArg && op != EOpConstructStruct && ! type.isArrayOfArrays()) { 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; return true;
} }
@ -3458,51 +3483,51 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T
// "If a matrix argument is given to a matrix constructor, // "If a matrix argument is given to a matrix constructor,
// it is a compile-time error to have any other arguments." // it is a compile-time error to have any other arguments."
if (function.getParamCount() != 1) 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; return false;
} }
if (overFull) { if (overFull) {
error(loc, "too many arguments", "constructor", ""); error(loc, "too many arguments", constructorString.c_str(), "");
return true; return true;
} }
if (op == EOpConstructStruct && ! type.isArray() && (int)type.getStruct()->size() != function.getParamCount()) { 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; return true;
} }
if ((op != EOpConstructStruct && size != 1 && size < type.computeNumComponents()) || if ((op != EOpConstructStruct && size != 1 && size < type.computeNumComponents()) ||
(op == EOpConstructStruct && 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; return true;
} }
if (type.isCoopMat() && function.getParamCount() != 1) { if (type.isCoopMat() && function.getParamCount() != 1) {
error(loc, "wrong number of arguments", "constructor", ""); error(loc, "wrong number of arguments", constructorString.c_str(), "");
return true; return true;
} }
if (type.isCoopMat() && if (type.isCoopMat() &&
!(function[0].type->isScalar() || function[0].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; return true;
} }
TIntermTyped* typed = node->getAsTyped(); TIntermTyped* typed = node->getAsTyped();
if (typed == nullptr) { 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; return true;
} }
if (op != EOpConstructStruct && op != EOpConstructNonuniform && typed->getBasicType() == EbtSampler) { 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; return true;
} }
if (op != EOpConstructStruct && typed->isAtomic()) { 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; return true;
} }
if (typed->getBasicType() == EbtVoid) { if (typed->getBasicType() == EbtVoid) {
error(loc, "cannot convert a void", "constructor", ""); error(loc, "cannot convert a void", constructorString.c_str(), "");
return true; return true;
} }
@ -3781,7 +3806,7 @@ void TParseContext::globalQualifierTypeCheck(const TSourceLoc& loc, const TQuali
if (isTypeInt(publicType.basicType) || publicType.basicType == EbtDouble) if (isTypeInt(publicType.basicType) || publicType.basicType == EbtDouble)
profileRequires(loc, EEsProfile, 300, nullptr, "shader input/output"); profileRequires(loc, EEsProfile, 300, nullptr, "shader input/output");
if (!qualifier.flat && !qualifier.isExplicitInterpolation() && !qualifier.isPervertexNV()) { if (!qualifier.flat && !qualifier.isExplicitInterpolation() && !qualifier.isPervertexNV() && !qualifier.isPervertexEXT()) {
if (isTypeInt(publicType.basicType) || if (isTypeInt(publicType.basicType) ||
publicType.basicType == EbtDouble || publicType.basicType == EbtDouble ||
(publicType.userDef && ( publicType.userDef->containsBasicType(EbtInt) (publicType.userDef && ( publicType.userDef->containsBasicType(EbtInt)
@ -4586,7 +4611,7 @@ TSymbol* TParseContext::redeclareBuiltinVariable(const TSourceLoc& loc, const TS
if (ssoPre150 || if (ssoPre150 ||
(identifier == "gl_FragDepth" && ((nonEsRedecls && version >= 420) || esRedecls)) || (identifier == "gl_FragDepth" && ((nonEsRedecls && version >= 420) || esRedecls)) ||
(identifier == "gl_FragCoord" && ((nonEsRedecls && version >= 150) || esRedecls)) || (identifier == "gl_FragCoord" && ((nonEsRedecls && version >= 140) || esRedecls)) ||
identifier == "gl_ClipDistance" || identifier == "gl_ClipDistance" ||
identifier == "gl_CullDistance" || identifier == "gl_CullDistance" ||
identifier == "gl_ShadingRateEXT" || identifier == "gl_ShadingRateEXT" ||
@ -4655,7 +4680,7 @@ TSymbol* TParseContext::redeclareBuiltinVariable(const TSourceLoc& loc, const TS
symbolQualifier.storage != qualifier.storage) symbolQualifier.storage != qualifier.storage)
error(loc, "cannot change qualification of", "redeclaration", symbol->getName().c_str()); error(loc, "cannot change qualification of", "redeclaration", symbol->getName().c_str());
} else if (identifier == "gl_FragCoord") { } else if (identifier == "gl_FragCoord") {
if (intermediate.inIoAccessed("gl_FragCoord")) if (!intermediate.getTexCoordRedeclared() && intermediate.inIoAccessed("gl_FragCoord"))
error(loc, "cannot redeclare after use", "gl_FragCoord", ""); error(loc, "cannot redeclare after use", "gl_FragCoord", "");
if (qualifier.nopersp != symbolQualifier.nopersp || qualifier.flat != symbolQualifier.flat || if (qualifier.nopersp != symbolQualifier.nopersp || qualifier.flat != symbolQualifier.flat ||
qualifier.isMemory() || qualifier.isAuxiliary()) qualifier.isMemory() || qualifier.isAuxiliary())
@ -4665,6 +4690,9 @@ TSymbol* TParseContext::redeclareBuiltinVariable(const TSourceLoc& loc, const TS
if (! builtIn && (publicType.pixelCenterInteger != intermediate.getPixelCenterInteger() || if (! builtIn && (publicType.pixelCenterInteger != intermediate.getPixelCenterInteger() ||
publicType.originUpperLeft != intermediate.getOriginUpperLeft())) publicType.originUpperLeft != intermediate.getOriginUpperLeft()))
error(loc, "cannot redeclare with different qualification:", "redeclaration", symbol->getName().c_str()); error(loc, "cannot redeclare with different qualification:", "redeclaration", symbol->getName().c_str());
intermediate.setTexCoordRedeclared();
if (publicType.pixelCenterInteger) if (publicType.pixelCenterInteger)
intermediate.setPixelCenterInteger(); intermediate.setPixelCenterInteger();
if (publicType.originUpperLeft) if (publicType.originUpperLeft)
@ -5496,12 +5524,19 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi
} }
if (language == EShLangFragment) { if (language == EShLangFragment) {
if (id == "origin_upper_left") { if (id == "origin_upper_left") {
requireProfile(loc, ECoreProfile | ECompatibilityProfile, "origin_upper_left"); requireProfile(loc, ECoreProfile | ECompatibilityProfile | ENoProfile, "origin_upper_left");
if (profile == ENoProfile) {
profileRequires(loc,ECoreProfile | ECompatibilityProfile, 140, E_GL_ARB_fragment_coord_conventions, "origin_upper_left");
}
publicType.shaderQualifiers.originUpperLeft = true; publicType.shaderQualifiers.originUpperLeft = true;
return; return;
} }
if (id == "pixel_center_integer") { if (id == "pixel_center_integer") {
requireProfile(loc, ECoreProfile | ECompatibilityProfile, "pixel_center_integer"); requireProfile(loc, ECoreProfile | ECompatibilityProfile | ENoProfile, "pixel_center_integer");
if (profile == ENoProfile) {
profileRequires(loc,ECoreProfile | ECompatibilityProfile, 140, E_GL_ARB_fragment_coord_conventions, "pixel_center_integer");
}
publicType.shaderQualifiers.pixelCenterInteger = true; publicType.shaderQualifiers.pixelCenterInteger = true;
return; return;
} }
@ -6034,6 +6069,8 @@ void TParseContext::mergeObjectLayoutQualifiers(TQualifier& dst, const TQualifie
dst.layoutShaderRecord = true; dst.layoutShaderRecord = true;
if (src.pervertexNV) if (src.pervertexNV)
dst.pervertexNV = true; dst.pervertexNV = true;
if (src.pervertexEXT)
dst.pervertexEXT = true;
#endif #endif
} }
} }
@ -6207,11 +6244,13 @@ void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type)
#ifndef GLSLANG_WEB #ifndef GLSLANG_WEB
if (qualifier.hasXfbOffset() && qualifier.hasXfbBuffer()) { if (qualifier.hasXfbOffset() && qualifier.hasXfbBuffer()) {
int repeated = intermediate.addXfbBufferOffset(type); if (type.isUnsizedArray()) {
if (repeated >= 0)
error(loc, "overlapping offsets at", "xfb_offset", "offset %d in buffer %d", repeated, qualifier.layoutXfbBuffer);
if (type.isUnsizedArray())
error(loc, "unsized array", "xfb_offset", "in buffer %d", qualifier.layoutXfbBuffer); error(loc, "unsized array", "xfb_offset", "in buffer %d", qualifier.layoutXfbBuffer);
} else {
int repeated = intermediate.addXfbBufferOffset(type);
if (repeated >= 0)
error(loc, "overlapping offsets at", "xfb_offset", "offset %d in buffer %d", repeated, qualifier.layoutXfbBuffer);
}
// "The offset must be a multiple of the size of the first component of the first // "The offset must be a multiple of the size of the first component of the first
// qualified variable or block member, or a compile-time error results. Further, if applied to an aggregate // qualified variable or block member, or a compile-time error results. Further, if applied to an aggregate
@ -6331,8 +6370,12 @@ void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type)
profileRequires(loc, ECoreProfile | ECompatibilityProfile, 0, E_GL_EXT_shader_image_load_formatted, explanation); profileRequires(loc, ECoreProfile | ECompatibilityProfile, 0, E_GL_EXT_shader_image_load_formatted, explanation);
} }
if (qualifier.isPushConstant() && type.getBasicType() != EbtBlock) if (qualifier.isPushConstant()) {
error(loc, "can only be used with a block", "push_constant", ""); if (type.getBasicType() != EbtBlock)
error(loc, "can only be used with a block", "push_constant", "");
if (type.isArray())
error(loc, "Push constants blocks can't be an array", "push_constant", "");
}
if (qualifier.hasBufferReference() && type.getBasicType() != EbtBlock) if (qualifier.hasBufferReference() && type.getBasicType() != EbtBlock)
error(loc, "can only be used with a block", "buffer_reference", ""); error(loc, "can only be used with a block", "buffer_reference", "");
@ -6493,6 +6536,8 @@ void TParseContext::layoutQualifierCheck(const TSourceLoc& loc, const TQualifier
error(loc, "can only be used with a uniform", "push_constant", ""); error(loc, "can only be used with a uniform", "push_constant", "");
if (qualifier.hasSet()) if (qualifier.hasSet())
error(loc, "cannot be used with push_constant", "set", ""); error(loc, "cannot be used with push_constant", "set", "");
if (qualifier.hasBinding())
error(loc, "cannot be used with push_constant", "binding", "");
} }
if (qualifier.hasBufferReference()) { if (qualifier.hasBufferReference()) {
if (qualifier.storage != EvqBuffer) if (qualifier.storage != EvqBuffer)
@ -6647,8 +6692,10 @@ const TFunction* TParseContext::findFunction(const TSourceLoc& loc, const TFunct
: findFunctionExact(loc, call, builtIn)); : findFunctionExact(loc, call, builtIn));
else if (version < 120) else if (version < 120)
function = findFunctionExact(loc, call, builtIn); function = findFunctionExact(loc, call, builtIn);
else if (version < 400) else if (version < 400) {
function = extensionTurnedOn(E_GL_ARB_gpu_shader_fp64) ? findFunction400(loc, call, builtIn) : findFunction120(loc, call, builtIn); bool needfindFunction400 = extensionTurnedOn(E_GL_ARB_gpu_shader_fp64) || extensionTurnedOn(E_GL_ARB_gpu_shader5);
function = needfindFunction400 ? findFunction400(loc, call, builtIn) : findFunction120(loc, call, builtIn);
}
else if (explicitTypesEnabled) else if (explicitTypesEnabled)
function = findFunctionExplicitTypes(loc, call, builtIn); function = findFunctionExplicitTypes(loc, call, builtIn);
else else
@ -7419,14 +7466,14 @@ TIntermNode* TParseContext::executeInitializer(const TSourceLoc& loc, TIntermTyp
// Uniforms require a compile-time constant initializer // Uniforms require a compile-time constant initializer
if (qualifier == EvqUniform && ! initializer->getType().getQualifier().isFrontEndConstant()) { if (qualifier == EvqUniform && ! initializer->getType().getQualifier().isFrontEndConstant()) {
error(loc, "uniform initializers must be constant", "=", "'%s'", error(loc, "uniform initializers must be constant", "=", "'%s'",
variable->getType().getCompleteString().c_str()); variable->getType().getCompleteString(intermediate.getEnhancedMsgs()).c_str());
variable->getWritableType().getQualifier().makeTemporary(); variable->getWritableType().getQualifier().makeTemporary();
return nullptr; return nullptr;
} }
// Global consts require a constant initializer (specialization constant is okay) // Global consts require a constant initializer (specialization constant is okay)
if (qualifier == EvqConst && symbolTable.atGlobalLevel() && ! initializer->getType().getQualifier().isConstant()) { if (qualifier == EvqConst && symbolTable.atGlobalLevel() && ! initializer->getType().getQualifier().isConstant()) {
error(loc, "global const initializers must be constant", "=", "'%s'", 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(); variable->getWritableType().getQualifier().makeTemporary();
return nullptr; return nullptr;
} }
@ -7489,7 +7536,7 @@ TIntermNode* TParseContext::executeInitializer(const TSourceLoc& loc, TIntermTyp
TIntermSymbol* intermSymbol = intermediate.addSymbol(*variable, loc); TIntermSymbol* intermSymbol = intermediate.addSymbol(*variable, loc);
TIntermTyped* initNode = intermediate.addAssign(EOpAssign, intermSymbol, initializer, loc); TIntermTyped* initNode = intermediate.addAssign(EOpAssign, intermSymbol, initializer, loc);
if (! initNode) if (! initNode)
assignError(loc, "=", intermSymbol->getCompleteString(), initializer->getCompleteString()); assignError(loc, "=", intermSymbol->getCompleteString(intermediate.getEnhancedMsgs()), initializer->getCompleteString(intermediate.getEnhancedMsgs()));
return initNode; return initNode;
} }
@ -7560,7 +7607,7 @@ TIntermTyped* TParseContext::convertInitializerList(const TSourceLoc& loc, const
} }
} else if (type.isMatrix()) { } else if (type.isMatrix()) {
if (type.getMatrixCols() != (int)initList->getSequence().size()) { 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; return nullptr;
} }
TType vectorType(type, 0); // dereferenced type TType vectorType(type, 0); // dereferenced type
@ -7571,20 +7618,20 @@ TIntermTyped* TParseContext::convertInitializerList(const TSourceLoc& loc, const
} }
} else if (type.isVector()) { } else if (type.isVector()) {
if (type.getVectorSize() != (int)initList->getSequence().size()) { 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; return nullptr;
} }
TBasicType destType = type.getBasicType(); TBasicType destType = type.getBasicType();
for (int i = 0; i < type.getVectorSize(); ++i) { for (int i = 0; i < type.getVectorSize(); ++i) {
TBasicType initType = initList->getSequence()[i]->getAsTyped()->getBasicType(); TBasicType initType = initList->getSequence()[i]->getAsTyped()->getBasicType();
if (destType != initType && !intermediate.canImplicitlyPromote(initType, destType)) { 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; return nullptr;
} }
} }
} else { } 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; return nullptr;
} }
@ -7691,7 +7738,13 @@ TIntermTyped* TParseContext::addConstructor(const TSourceLoc& loc, TIntermNode*
return nullptr; return nullptr;
} }
return intermediate.setAggregateOperator(aggrNode, op, type, loc); TIntermTyped *ret_node = intermediate.setAggregateOperator(aggrNode, op, type, loc);
TIntermAggregate *agg_node = ret_node->getAsAggregate();
if (agg_node && (agg_node->isVector() || agg_node->isArray() || agg_node->isMatrix()))
agg_node->updatePrecision();
return ret_node;
} }
// Function for constructor implementation. Calls addUnaryMath with appropriate EOp value // Function for constructor implementation. Calls addUnaryMath with appropriate EOp value
@ -8086,8 +8139,9 @@ TIntermTyped* TParseContext::constructAggregate(TIntermNode* node, const TType&
{ {
TIntermTyped* converted = intermediate.addConversion(EOpConstructStruct, type, node->getAsTyped()); TIntermTyped* converted = intermediate.addConversion(EOpConstructStruct, type, node->getAsTyped());
if (! converted || converted->getType() != type) { if (! converted || converted->getType() != type) {
bool enhanced = intermediate.getEnhancedMsgs();
error(loc, "", "constructor", "cannot convert parameter %d from '%s' to '%s'", paramCount, 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; return nullptr;
} }
@ -9237,11 +9291,14 @@ TIntermNode* TParseContext::addSwitch(const TSourceLoc& loc, TIntermTyped* expre
// "it is an error to have no statement between a label and the end of the switch statement." // "it is an error to have no statement between a label and the end of the switch statement."
// The specifications were updated to remove this (being ill-defined what a "statement" was), // The specifications were updated to remove this (being ill-defined what a "statement" was),
// so, this became a warning. However, 3.0 tests still check for the error. // so, this became a warning. However, 3.0 tests still check for the error.
if (isEsProfile() && version <= 300 && ! relaxedErrors()) if (isEsProfile() && (version <= 300 || version >= 320) && ! relaxedErrors())
error(loc, "last case/default label not followed by statements", "switch", "");
else if (!isEsProfile() && (version <= 430 || version >= 460))
error(loc, "last case/default label not followed by statements", "switch", ""); error(loc, "last case/default label not followed by statements", "switch", "");
else else
warn(loc, "last case/default label not followed by statements", "switch", ""); warn(loc, "last case/default label not followed by statements", "switch", "");
// emulate a break for error recovery // emulate a break for error recovery
lastStatements = intermediate.makeAggregate(intermediate.addBranch(EOpBreak, loc)); lastStatements = intermediate.makeAggregate(intermediate.addBranch(EOpBreak, loc));
lastStatements->setOperator(EOpSequence); lastStatements->setOperator(EOpSequence);

View file

@ -241,7 +241,7 @@ protected:
// override this to set the language-specific name // override this to set the language-specific name
virtual const char* getAtomicCounterBlockName() const { return ""; } virtual const char* getAtomicCounterBlockName() const { return ""; }
virtual void setAtomicCounterBlockDefaults(TType&) const {} virtual void setAtomicCounterBlockDefaults(TType&) const {}
virtual void setInvariant(const TSourceLoc& loc, const char* builtin) {} virtual void setInvariant(const TSourceLoc&, const char*) {}
virtual void finalizeAtomicCounterBlockLayout(TVariable&) {} virtual void finalizeAtomicCounterBlockLayout(TVariable&) {}
bool isAtomicCounterBlock(const TSymbol& symbol) { bool isAtomicCounterBlock(const TSymbol& symbol) {
const TVariable* var = symbol.getAsVariable(); const TVariable* var = symbol.getAsVariable();
@ -472,7 +472,7 @@ public:
// Determine loop control from attributes // Determine loop control from attributes
void handleLoopAttributes(const TAttributes& attributes, TIntermNode*); void handleLoopAttributes(const TAttributes& attributes, TIntermNode*);
// Function attributes // Function attributes
void handleFunctionAttributes(const TSourceLoc&, const TAttributes&, TFunction*); void handleFunctionAttributes(const TSourceLoc&, const TAttributes&);
// GL_EXT_spirv_intrinsics // GL_EXT_spirv_intrinsics
TSpirvRequirement* makeSpirvRequirement(const TSourceLoc& loc, const TString& name, TSpirvRequirement* makeSpirvRequirement(const TSourceLoc& loc, const TString& name,
@ -480,7 +480,6 @@ public:
TSpirvRequirement* mergeSpirvRequirements(const TSourceLoc& loc, TSpirvRequirement* spirvReq1, TSpirvRequirement* mergeSpirvRequirements(const TSourceLoc& loc, TSpirvRequirement* spirvReq1,
TSpirvRequirement* spirvReq2); TSpirvRequirement* spirvReq2);
TSpirvTypeParameters* makeSpirvTypeParameters(const TSourceLoc& loc, const TIntermConstantUnion* constant); TSpirvTypeParameters* makeSpirvTypeParameters(const TSourceLoc& loc, const TIntermConstantUnion* constant);
TSpirvTypeParameters* makeSpirvTypeParameters(const TPublicType& type);
TSpirvTypeParameters* mergeSpirvTypeParameters(TSpirvTypeParameters* spirvTypeParams1, TSpirvTypeParameters* mergeSpirvTypeParameters(TSpirvTypeParameters* spirvTypeParams1,
TSpirvTypeParameters* spirvTypeParams2); TSpirvTypeParameters* spirvTypeParams2);
TSpirvInstruction* makeSpirvInstruction(const TSourceLoc& loc, const TString& name, const TString& value); TSpirvInstruction* makeSpirvInstruction(const TSourceLoc& loc, const TString& name, const TString& value);

View file

@ -739,6 +739,7 @@ void TScanContext::fillInKeywordMap()
(*KeywordMap)["f16subpassInputMS"] = F16SUBPASSINPUTMS; (*KeywordMap)["f16subpassInputMS"] = F16SUBPASSINPUTMS;
(*KeywordMap)["__explicitInterpAMD"] = EXPLICITINTERPAMD; (*KeywordMap)["__explicitInterpAMD"] = EXPLICITINTERPAMD;
(*KeywordMap)["pervertexNV"] = PERVERTEXNV; (*KeywordMap)["pervertexNV"] = PERVERTEXNV;
(*KeywordMap)["pervertexEXT"] = PERVERTEXEXT;
(*KeywordMap)["precise"] = PRECISE; (*KeywordMap)["precise"] = PRECISE;
(*KeywordMap)["rayPayloadNV"] = PAYLOADNV; (*KeywordMap)["rayPayloadNV"] = PAYLOADNV;
@ -1719,6 +1720,12 @@ int TScanContext::tokenizeIdentifier()
return keyword; return keyword;
return identifierOrType(); return identifierOrType();
case PERVERTEXEXT:
if ((!parseContext.isEsProfile() && parseContext.version >= 450) ||
parseContext.extensionTurnedOn(E_GL_EXT_fragment_shader_barycentric))
return keyword;
return identifierOrType();
case PRECISE: case PRECISE:
if ((parseContext.isEsProfile() && if ((parseContext.isEsProfile() &&
(parseContext.version >= 320 || parseContext.extensionsTurnedOn(Num_AEP_gpu_shader5, AEP_gpu_shader5))) || (parseContext.version >= 320 || parseContext.extensionsTurnedOn(Num_AEP_gpu_shader5, AEP_gpu_shader5))) ||

View file

@ -813,6 +813,7 @@ bool ProcessDeferred(
// set version/profile to defaultVersion/defaultProfile regardless of the #version // set version/profile to defaultVersion/defaultProfile regardless of the #version
// directive in the source code // directive in the source code
bool forceDefaultVersionAndProfile, bool forceDefaultVersionAndProfile,
int overrideVersion, // overrides version specified by #verison or default version
bool forwardCompatible, // give errors for use of deprecated features bool forwardCompatible, // give errors for use of deprecated features
EShMessages messages, // warnings/errors/AST; things to print out EShMessages messages, // warnings/errors/AST; things to print out
TIntermediate& intermediate, // returned tree, etc. TIntermediate& intermediate, // returned tree, etc.
@ -900,6 +901,9 @@ bool ProcessDeferred(
version = defaultVersion; version = defaultVersion;
profile = defaultProfile; profile = defaultProfile;
} }
if (source == EShSourceGlsl && overrideVersion != 0) {
version = overrideVersion;
}
bool goodVersion = DeduceVersionProfile(compiler->infoSink, stage, bool goodVersion = DeduceVersionProfile(compiler->infoSink, stage,
versionNotFirst, defaultVersion, source, version, profile, spvVersion); versionNotFirst, defaultVersion, source, version, profile, spvVersion);
@ -1275,6 +1279,7 @@ bool PreprocessDeferred(
int defaultVersion, // use 100 for ES environment, 110 for desktop int defaultVersion, // use 100 for ES environment, 110 for desktop
EProfile defaultProfile, EProfile defaultProfile,
bool forceDefaultVersionAndProfile, bool forceDefaultVersionAndProfile,
int overrideVersion, // use 0 if not overriding GLSL version
bool forwardCompatible, // give errors for use of deprecated features bool forwardCompatible, // give errors for use of deprecated features
EShMessages messages, // warnings/errors/AST; things to print out EShMessages messages, // warnings/errors/AST; things to print out
TShader::Includer& includer, TShader::Includer& includer,
@ -1285,7 +1290,7 @@ bool PreprocessDeferred(
DoPreprocessing parser(outputString); DoPreprocessing parser(outputString);
return ProcessDeferred(compiler, shaderStrings, numStrings, inputLengths, stringNames, return ProcessDeferred(compiler, shaderStrings, numStrings, inputLengths, stringNames,
preamble, optLevel, resources, defaultVersion, preamble, optLevel, resources, defaultVersion,
defaultProfile, forceDefaultVersionAndProfile, defaultProfile, forceDefaultVersionAndProfile, overrideVersion,
forwardCompatible, messages, intermediate, parser, forwardCompatible, messages, intermediate, parser,
false, includer, "", environment); false, includer, "", environment);
} }
@ -1314,6 +1319,7 @@ bool CompileDeferred(
int defaultVersion, // use 100 for ES environment, 110 for desktop int defaultVersion, // use 100 for ES environment, 110 for desktop
EProfile defaultProfile, EProfile defaultProfile,
bool forceDefaultVersionAndProfile, bool forceDefaultVersionAndProfile,
int overrideVersion, // use 0 if not overriding GLSL version
bool forwardCompatible, // give errors for use of deprecated features bool forwardCompatible, // give errors for use of deprecated features
EShMessages messages, // warnings/errors/AST; things to print out EShMessages messages, // warnings/errors/AST; things to print out
TIntermediate& intermediate,// returned tree, etc. TIntermediate& intermediate,// returned tree, etc.
@ -1324,7 +1330,7 @@ bool CompileDeferred(
DoFullParse parser; DoFullParse parser;
return ProcessDeferred(compiler, shaderStrings, numStrings, inputLengths, stringNames, return ProcessDeferred(compiler, shaderStrings, numStrings, inputLengths, stringNames,
preamble, optLevel, resources, defaultVersion, preamble, optLevel, resources, defaultVersion,
defaultProfile, forceDefaultVersionAndProfile, defaultProfile, forceDefaultVersionAndProfile, overrideVersion,
forwardCompatible, messages, intermediate, parser, forwardCompatible, messages, intermediate, parser,
true, includer, sourceEntryPointName, environment); true, includer, sourceEntryPointName, environment);
} }
@ -1343,7 +1349,6 @@ int ShInitialize()
glslang::GetGlobalLock(); glslang::GetGlobalLock();
++NumberOfClients; ++NumberOfClients;
glslang::ReleaseGlobalLock();
if (PerProcessGPA == nullptr) if (PerProcessGPA == nullptr)
PerProcessGPA = new TPoolAllocator(); PerProcessGPA = new TPoolAllocator();
@ -1353,6 +1358,7 @@ int ShInitialize()
glslang::HlslScanContext::fillInKeywordMap(); glslang::HlslScanContext::fillInKeywordMap();
#endif #endif
glslang::ReleaseGlobalLock();
return 1; return 1;
} }
@ -1415,9 +1421,10 @@ int ShFinalize()
--NumberOfClients; --NumberOfClients;
assert(NumberOfClients >= 0); assert(NumberOfClients >= 0);
bool finalize = NumberOfClients == 0; bool finalize = NumberOfClients == 0;
glslang::ReleaseGlobalLock(); if (! finalize) {
if (! finalize) glslang::ReleaseGlobalLock();
return 1; return 1;
}
for (int version = 0; version < VersionCount; ++version) { for (int version = 0; version < VersionCount; ++version) {
for (int spvVersion = 0; spvVersion < SpvVersionCount; ++spvVersion) { for (int spvVersion = 0; spvVersion < SpvVersionCount; ++spvVersion) {
@ -1455,6 +1462,7 @@ int ShFinalize()
glslang::HlslScanContext::deleteKeywordMap(); glslang::HlslScanContext::deleteKeywordMap();
#endif #endif
glslang::ReleaseGlobalLock();
return 1; return 1;
} }
@ -1496,7 +1504,7 @@ int ShCompile(
TIntermediate intermediate(compiler->getLanguage()); TIntermediate intermediate(compiler->getLanguage());
TShader::ForbidIncluder includer; TShader::ForbidIncluder includer;
bool success = CompileDeferred(compiler, shaderStrings, numStrings, inputLengths, nullptr, bool success = CompileDeferred(compiler, shaderStrings, numStrings, inputLengths, nullptr,
"", optLevel, resources, defaultVersion, ENoProfile, false, "", optLevel, resources, defaultVersion, ENoProfile, false, 0,
forwardCompatible, messages, intermediate, includer); forwardCompatible, messages, intermediate, includer);
// //
@ -1757,7 +1765,7 @@ public:
}; };
TShader::TShader(EShLanguage s) TShader::TShader(EShLanguage s)
: stage(s), lengths(nullptr), stringNames(nullptr), preamble("") : stage(s), lengths(nullptr), stringNames(nullptr), preamble(""), overrideVersion(0)
{ {
pool = new TPoolAllocator; pool = new TPoolAllocator;
infoSink = new TInfoSink; infoSink = new TInfoSink;
@ -1826,7 +1834,14 @@ void TShader::setUniqueId(unsigned long long id)
intermediate->setUniqueId(id); intermediate->setUniqueId(id);
} }
void TShader::setOverrideVersion(int version)
{
overrideVersion = version;
}
void TShader::setInvertY(bool invert) { intermediate->setInvertY(invert); } 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); } void TShader::setNanMinMaxClamp(bool useNonNan) { intermediate->setNanMinMaxClamp(useNonNan); }
#ifndef GLSLANG_WEB #ifndef GLSLANG_WEB
@ -1906,7 +1921,7 @@ bool TShader::parse(const TBuiltInResource* builtInResources, int defaultVersion
return CompileDeferred(compiler, strings, numStrings, lengths, stringNames, return CompileDeferred(compiler, strings, numStrings, lengths, stringNames,
preamble, EShOptNone, builtInResources, defaultVersion, preamble, EShOptNone, builtInResources, defaultVersion,
defaultProfile, forceDefaultVersionAndProfile, defaultProfile, forceDefaultVersionAndProfile, overrideVersion,
forwardCompatible, messages, *intermediate, includer, sourceEntryPointName, forwardCompatible, messages, *intermediate, includer, sourceEntryPointName,
&environment); &environment);
} }
@ -1933,7 +1948,7 @@ bool TShader::preprocess(const TBuiltInResource* builtInResources,
return PreprocessDeferred(compiler, strings, numStrings, lengths, stringNames, preamble, return PreprocessDeferred(compiler, strings, numStrings, lengths, stringNames, preamble,
EShOptNone, builtInResources, defaultVersion, EShOptNone, builtInResources, defaultVersion,
defaultProfile, forceDefaultVersionAndProfile, defaultProfile, forceDefaultVersionAndProfile, overrideVersion,
forwardCompatible, message, includer, *intermediate, output_string, forwardCompatible, message, includer, *intermediate, output_string,
&environment); &environment);
} }
@ -2046,6 +2061,8 @@ bool TProgram::linkStage(EShLanguage stage, EShMessages messages)
firstIntermediate->getVersion(), firstIntermediate->getVersion(),
firstIntermediate->getProfile()); firstIntermediate->getProfile());
intermediate[stage]->setLimits(firstIntermediate->getLimits()); intermediate[stage]->setLimits(firstIntermediate->getLimits());
if (firstIntermediate->getEnhancedMsgs())
intermediate[stage]->setEnhancedMsgs();
// The new TIntermediate must use the same origin as the original TIntermediates. // The new TIntermediate must use the same origin as the original TIntermediates.
// Otherwise linking will fail due to different coordinate systems. // Otherwise linking will fail due to different coordinate systems.

View file

@ -130,11 +130,11 @@ void TIntermediate::insertSpirvExecutionModeId(int executionMode, const TIntermA
spirvExecutionMode = new TSpirvExecutionMode; spirvExecutionMode = new TSpirvExecutionMode;
assert(args); assert(args);
TVector<const TIntermConstantUnion*> extraOperands; TVector<const TIntermTyped*> extraOperands;
for (auto arg : args->getSequence()) { for (auto arg : args->getSequence()) {
auto extraOperand = arg->getAsConstantUnion(); auto extraOperand = arg->getAsTyped();
assert(extraOperand != nullptr); assert(extraOperand != nullptr && extraOperand->getQualifier().isConstant());
extraOperands.push_back(extraOperand); extraOperands.push_back(extraOperand);
} }
spirvExecutionMode->modeIds[executionMode] = extraOperands; spirvExecutionMode->modeIds[executionMode] = extraOperands;
@ -165,10 +165,10 @@ void TQualifier::setSpirvDecorateId(int decoration, const TIntermAggregate* args
spirvDecorate = new TSpirvDecorate; spirvDecorate = new TSpirvDecorate;
assert(args); assert(args);
TVector<const TIntermConstantUnion*> extraOperands; TVector<const TIntermTyped*> extraOperands;
for (auto arg : args->getSequence()) { for (auto arg : args->getSequence()) {
auto extraOperand = arg->getAsConstantUnion(); auto extraOperand = arg->getAsTyped();
assert(extraOperand != nullptr); assert(extraOperand != nullptr && extraOperand->getQualifier().isConstant());
extraOperands.push_back(extraOperand); extraOperands.push_back(extraOperand);
} }
spirvDecorate->decorateIds[decoration] = extraOperands; spirvDecorate->decorateIds[decoration] = extraOperands;
@ -201,25 +201,27 @@ TString TQualifier::getSpirvDecorateQualifierString() const
const auto appendBool = [&](bool b) { qualifierString.append(std::to_string(b).c_str()); }; const auto appendBool = [&](bool b) { qualifierString.append(std::to_string(b).c_str()); };
const auto appendStr = [&](const char* s) { qualifierString.append(s); }; const auto appendStr = [&](const char* s) { qualifierString.append(s); };
const auto appendDecorate = [&](const TIntermConstantUnion* constant) { const auto appendDecorate = [&](const TIntermTyped* constant) {
auto& constArray = constant->getAsConstantUnion() != nullptr ? constant->getAsConstantUnion()->getConstArray()
: constant->getAsSymbolNode()->getConstArray();
if (constant->getBasicType() == EbtFloat) { if (constant->getBasicType() == EbtFloat) {
float value = static_cast<float>(constant->getConstArray()[0].getDConst()); float value = static_cast<float>(constArray[0].getDConst());
appendFloat(value); appendFloat(value);
} }
else if (constant->getBasicType() == EbtInt) { else if (constant->getBasicType() == EbtInt) {
int value = constant->getConstArray()[0].getIConst(); int value = constArray[0].getIConst();
appendInt(value); appendInt(value);
} }
else if (constant->getBasicType() == EbtUint) { else if (constant->getBasicType() == EbtUint) {
unsigned value = constant->getConstArray()[0].getUConst(); unsigned value = constArray[0].getUConst();
appendUint(value); appendUint(value);
} }
else if (constant->getBasicType() == EbtBool) { else if (constant->getBasicType() == EbtBool) {
bool value = constant->getConstArray()[0].getBConst(); bool value = constArray[0].getBConst();
appendBool(value); appendBool(value);
} }
else if (constant->getBasicType() == EbtString) { else if (constant->getBasicType() == EbtString) {
const TString* value = constant->getConstArray()[0].getSConst(); const TString* value = constArray[0].getSConst();
appendStr(value->c_str()); appendStr(value->c_str());
} }
else else
@ -290,13 +292,6 @@ TSpirvTypeParameters* TParseContext::makeSpirvTypeParameters(const TSourceLoc& l
return spirvTypeParams; return spirvTypeParams;
} }
TSpirvTypeParameters* TParseContext::makeSpirvTypeParameters(const TPublicType& type)
{
TSpirvTypeParameters* spirvTypeParams = new TSpirvTypeParameters;
spirvTypeParams->push_back(TSpirvTypeParameter(new TType(type)));
return spirvTypeParams;
}
TSpirvTypeParameters* TParseContext::mergeSpirvTypeParameters(TSpirvTypeParameters* spirvTypeParams1, TSpirvTypeParameters* spirvTypeParams2) TSpirvTypeParameters* TParseContext::mergeSpirvTypeParameters(TSpirvTypeParameters* spirvTypeParams1, TSpirvTypeParameters* spirvTypeParams2)
{ {
// Merge SPIR-V type parameters of the second one to the first one // Merge SPIR-V type parameters of the second one to the first one

View file

@ -279,8 +279,14 @@ TFunction::~TFunction()
// //
TSymbolTableLevel::~TSymbolTableLevel() TSymbolTableLevel::~TSymbolTableLevel()
{ {
for (tLevel::iterator it = level.begin(); it != level.end(); ++it) for (tLevel::iterator it = level.begin(); it != level.end(); ++it) {
delete (*it).second; const TString& name = it->first;
auto retargetIter = std::find_if(retargetedSymbols.begin(), retargetedSymbols.end(),
[&name](const std::pair<TString, TString>& i) { return i.first == name; });
if (retargetIter == retargetedSymbols.end())
delete (*it).second;
}
delete [] defaultPrecision; delete [] defaultPrecision;
} }
@ -418,6 +424,10 @@ TSymbolTableLevel* TSymbolTableLevel::clone() const
TSymbolTableLevel *symTableLevel = new TSymbolTableLevel(); TSymbolTableLevel *symTableLevel = new TSymbolTableLevel();
symTableLevel->anonId = anonId; symTableLevel->anonId = anonId;
symTableLevel->thisLevel = thisLevel; symTableLevel->thisLevel = thisLevel;
symTableLevel->retargetedSymbols.clear();
for (auto &s : retargetedSymbols) {
symTableLevel->retargetedSymbols.push_back({s.first, s.second});
}
std::vector<bool> containerCopied(anonId, false); std::vector<bool> containerCopied(anonId, false);
tLevel::const_iterator iter; tLevel::const_iterator iter;
for (iter = level.begin(); iter != level.end(); ++iter) { for (iter = level.begin(); iter != level.end(); ++iter) {
@ -433,8 +443,21 @@ TSymbolTableLevel* TSymbolTableLevel::clone() const
symTableLevel->insert(*container, false); symTableLevel->insert(*container, false);
containerCopied[anon->getAnonId()] = true; containerCopied[anon->getAnonId()] = true;
} }
} else } else {
const TString& name = iter->first;
auto retargetIter = std::find_if(retargetedSymbols.begin(), retargetedSymbols.end(),
[&name](const std::pair<TString, TString>& i) { return i.first == name; });
if (retargetIter != retargetedSymbols.end())
continue;
symTableLevel->insert(*iter->second->clone(), false); symTableLevel->insert(*iter->second->clone(), false);
}
}
// Now point retargeted symbols to the newly created versions of them
for (auto &s : retargetedSymbols) {
TSymbol* sym = symTableLevel->find(s.second);
if (!sym)
continue;
symTableLevel->insert(s.first, sym);
} }
return symTableLevel; return symTableLevel;

View file

@ -84,7 +84,7 @@ typedef TVector<const char*> TExtensionList;
class TSymbol { class TSymbol {
public: public:
POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
explicit TSymbol(const TString *n) : name(n), extensions(0), writable(true) { } explicit TSymbol(const TString *n) : name(n), uniqueId(0), extensions(0), writable(true) { }
virtual TSymbol* clone() const = 0; virtual TSymbol* clone() const = 0;
virtual ~TSymbol() { } // rely on all symbol owned memory coming from the pool virtual ~TSymbol() { } // rely on all symbol owned memory coming from the pool
@ -413,13 +413,20 @@ public:
TSymbolTableLevel() : defaultPrecision(0), anonId(0), thisLevel(false) { } TSymbolTableLevel() : defaultPrecision(0), anonId(0), thisLevel(false) { }
~TSymbolTableLevel(); ~TSymbolTableLevel();
bool insert(TSymbol& symbol, bool separateNameSpaces) bool insert(const TString& name, TSymbol* symbol) {
return level.insert(tLevelPair(name, symbol)).second;
}
bool insert(TSymbol& symbol, bool separateNameSpaces, const TString& forcedKeyName = TString())
{ {
// //
// returning true means symbol was added to the table with no semantic errors // returning true means symbol was added to the table with no semantic errors
// //
const TString& name = symbol.getName(); const TString& name = symbol.getName();
if (name == "") { if (forcedKeyName.length()) {
return level.insert(tLevelPair(forcedKeyName, &symbol)).second;
}
else if (name == "") {
symbol.getAsVariable()->setAnonId(anonId++); symbol.getAsVariable()->setAnonId(anonId++);
// An empty name means an anonymous container, exposing its members to the external scope. // An empty name means an anonymous container, exposing its members to the external scope.
// Give it a name and insert its members in the symbol table, pointing to the container. // Give it a name and insert its members in the symbol table, pointing to the container.
@ -471,6 +478,16 @@ public:
return true; return true;
} }
void retargetSymbol(const TString& from, const TString& to) {
tLevel::const_iterator fromIt = level.find(from);
tLevel::const_iterator toIt = level.find(to);
if (fromIt == level.end() || toIt == level.end())
return;
delete fromIt->second;
level[from] = toIt->second;
retargetedSymbols.push_back({from, to});
}
TSymbol* find(const TString& name) const TSymbol* find(const TString& name) const
{ {
tLevel::const_iterator it = level.find(name); tLevel::const_iterator it = level.find(name);
@ -583,6 +600,8 @@ protected:
tLevel level; // named mappings tLevel level; // named mappings
TPrecisionQualifier *defaultPrecision; TPrecisionQualifier *defaultPrecision;
// pair<FromName, ToName>
TVector<std::pair<TString, TString>> retargetedSymbols;
int anonId; int anonId;
bool thisLevel; // True if this level of the symbol table is a structure scope containing member function bool thisLevel; // True if this level of the symbol table is a structure scope containing member function
// that are supposed to see anonymous access to member variables. // that are supposed to see anonymous access to member variables.
@ -788,6 +807,12 @@ public:
return symbol; return symbol;
} }
void retargetSymbol(const TString& from, const TString& to) {
int level = currentLevel();
table[level]->retargetSymbol(from, to);
}
// Find of a symbol that returns how many layers deep of nested // Find of a symbol that returns how many layers deep of nested
// structures-with-member-functions ('this' scopes) deep the symbol was // structures-with-member-functions ('this' scopes) deep the symbol was
// found in. // found in.

View file

@ -225,6 +225,9 @@ void TParseVersions::initializeExtensionBehavior()
extensionBehavior[E_GL_ARB_shading_language_packing] = EBhDisable; extensionBehavior[E_GL_ARB_shading_language_packing] = EBhDisable;
extensionBehavior[E_GL_ARB_texture_query_lod] = EBhDisable; extensionBehavior[E_GL_ARB_texture_query_lod] = EBhDisable;
extensionBehavior[E_GL_ARB_vertex_attrib_64bit] = EBhDisable; extensionBehavior[E_GL_ARB_vertex_attrib_64bit] = EBhDisable;
extensionBehavior[E_GL_ARB_draw_instanced] = EBhDisable;
extensionBehavior[E_GL_ARB_fragment_coord_conventions] = EBhDisable;
extensionBehavior[E_GL_KHR_shader_subgroup_basic] = EBhDisable; extensionBehavior[E_GL_KHR_shader_subgroup_basic] = EBhDisable;
extensionBehavior[E_GL_KHR_shader_subgroup_vote] = EBhDisable; extensionBehavior[E_GL_KHR_shader_subgroup_vote] = EBhDisable;
@ -256,6 +259,8 @@ void TParseVersions::initializeExtensionBehavior()
extensionBehavior[E_GL_EXT_shader_8bit_storage] = EBhDisable; extensionBehavior[E_GL_EXT_shader_8bit_storage] = EBhDisable;
extensionBehavior[E_GL_EXT_subgroup_uniform_control_flow] = EBhDisable; extensionBehavior[E_GL_EXT_subgroup_uniform_control_flow] = EBhDisable;
extensionBehavior[E_GL_EXT_fragment_shader_barycentric] = EBhDisable;
// #line and #include // #line and #include
extensionBehavior[E_GL_GOOGLE_cpp_style_line_directive] = EBhDisable; extensionBehavior[E_GL_GOOGLE_cpp_style_line_directive] = EBhDisable;
extensionBehavior[E_GL_GOOGLE_include_directive] = EBhDisable; extensionBehavior[E_GL_GOOGLE_include_directive] = EBhDisable;
@ -331,6 +336,7 @@ void TParseVersions::initializeExtensionBehavior()
extensionBehavior[E_GL_EXT_ray_tracing] = EBhDisable; extensionBehavior[E_GL_EXT_ray_tracing] = EBhDisable;
extensionBehavior[E_GL_EXT_ray_query] = EBhDisable; extensionBehavior[E_GL_EXT_ray_query] = EBhDisable;
extensionBehavior[E_GL_EXT_ray_flags_primitive_culling] = EBhDisable; extensionBehavior[E_GL_EXT_ray_flags_primitive_culling] = EBhDisable;
extensionBehavior[E_GL_EXT_ray_cull_mask] = EBhDisable;
extensionBehavior[E_GL_EXT_blend_func_extended] = EBhDisable; extensionBehavior[E_GL_EXT_blend_func_extended] = EBhDisable;
extensionBehavior[E_GL_EXT_shader_implicit_conversions] = EBhDisable; extensionBehavior[E_GL_EXT_shader_implicit_conversions] = EBhDisable;
extensionBehavior[E_GL_EXT_fragment_shading_rate] = EBhDisable; extensionBehavior[E_GL_EXT_fragment_shading_rate] = EBhDisable;
@ -465,6 +471,8 @@ void TParseVersions::getPreamble(std::string& preamble)
"#define GL_ARB_shader_storage_buffer_object 1\n" "#define GL_ARB_shader_storage_buffer_object 1\n"
"#define GL_ARB_texture_query_lod 1\n" "#define GL_ARB_texture_query_lod 1\n"
"#define GL_ARB_vertex_attrib_64bit 1\n" "#define GL_ARB_vertex_attrib_64bit 1\n"
"#define GL_ARB_draw_instanced 1\n"
"#define GL_ARB_fragment_coord_conventions 1\n"
"#define GL_EXT_shader_non_constant_global_initializers 1\n" "#define GL_EXT_shader_non_constant_global_initializers 1\n"
"#define GL_EXT_shader_image_load_formatted 1\n" "#define GL_EXT_shader_image_load_formatted 1\n"
"#define GL_EXT_post_depth_coverage 1\n" "#define GL_EXT_post_depth_coverage 1\n"
@ -482,6 +490,7 @@ void TParseVersions::getPreamble(std::string& preamble)
"#define GL_EXT_debug_printf 1\n" "#define GL_EXT_debug_printf 1\n"
"#define GL_EXT_fragment_shading_rate 1\n" "#define GL_EXT_fragment_shading_rate 1\n"
"#define GL_EXT_shared_memory_block 1\n" "#define GL_EXT_shared_memory_block 1\n"
"#define GL_EXT_shader_integer_mix 1\n"
// GL_KHR_shader_subgroup // GL_KHR_shader_subgroup
"#define GL_KHR_shader_subgroup_basic 1\n" "#define GL_KHR_shader_subgroup_basic 1\n"
@ -499,6 +508,7 @@ void TParseVersions::getPreamble(std::string& preamble)
"#define GL_EXT_ray_tracing 1\n" "#define GL_EXT_ray_tracing 1\n"
"#define GL_EXT_ray_query 1\n" "#define GL_EXT_ray_query 1\n"
"#define GL_EXT_ray_flags_primitive_culling 1\n" "#define GL_EXT_ray_flags_primitive_culling 1\n"
"#define GL_EXT_ray_cull_mask 1\n"
"#define GL_EXT_spirv_intrinsics 1\n" "#define GL_EXT_spirv_intrinsics 1\n"
"#define GL_AMD_shader_ballot 1\n" "#define GL_AMD_shader_ballot 1\n"
@ -546,6 +556,8 @@ void TParseVersions::getPreamble(std::string& preamble)
"#define GL_EXT_shader_atomic_float 1\n" "#define GL_EXT_shader_atomic_float 1\n"
"#define GL_EXT_shader_atomic_float2 1\n" "#define GL_EXT_shader_atomic_float2 1\n"
"#define GL_EXT_fragment_shader_barycentric 1\n"
; ;
if (version >= 150) { if (version >= 150) {

View file

@ -161,6 +161,8 @@ const char* const E_GL_ARB_shader_storage_buffer_object = "GL_ARB_shader_storage
const char* const E_GL_ARB_shading_language_packing = "GL_ARB_shading_language_packing"; const char* const E_GL_ARB_shading_language_packing = "GL_ARB_shading_language_packing";
const char* const E_GL_ARB_texture_query_lod = "GL_ARB_texture_query_lod"; 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_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_ARB_fragment_coord_conventions = "GL_ARB_fragment_coord_conventions";
const char* const E_GL_KHR_shader_subgroup_basic = "GL_KHR_shader_subgroup_basic"; 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"; const char* const E_GL_KHR_shader_subgroup_vote = "GL_KHR_shader_subgroup_vote";
@ -199,6 +201,7 @@ const char* const E_GL_EXT_debug_printf = "GL_EXT_debug_prin
const char* const E_GL_EXT_ray_tracing = "GL_EXT_ray_tracing"; const char* const E_GL_EXT_ray_tracing = "GL_EXT_ray_tracing";
const char* const E_GL_EXT_ray_query = "GL_EXT_ray_query"; const char* const E_GL_EXT_ray_query = "GL_EXT_ray_query";
const char* const E_GL_EXT_ray_flags_primitive_culling = "GL_EXT_ray_flags_primitive_culling"; const char* const E_GL_EXT_ray_flags_primitive_culling = "GL_EXT_ray_flags_primitive_culling";
const char* const E_GL_EXT_ray_cull_mask = "GL_EXT_ray_cull_mask";
const char* const E_GL_EXT_blend_func_extended = "GL_EXT_blend_func_extended"; const char* const E_GL_EXT_blend_func_extended = "GL_EXT_blend_func_extended";
const char* const E_GL_EXT_shader_implicit_conversions = "GL_EXT_shader_implicit_conversions"; 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_fragment_shading_rate = "GL_EXT_fragment_shading_rate";
@ -207,6 +210,7 @@ const char* const E_GL_EXT_null_initializer = "GL_EXT_null_initi
const char* const E_GL_EXT_shared_memory_block = "GL_EXT_shared_memory_block"; 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"; const char* const E_GL_EXT_subgroup_uniform_control_flow = "GL_EXT_subgroup_uniform_control_flow";
const char* const E_GL_EXT_spirv_intrinsics = "GL_EXT_spirv_intrinsics"; const char* const E_GL_EXT_spirv_intrinsics = "GL_EXT_spirv_intrinsics";
const char* const E_GL_EXT_fragment_shader_barycentric = "GL_EXT_fragment_shader_barycentric";
// Arrays of extensions for the above viewportEXTs duplications // Arrays of extensions for the above viewportEXTs duplications

View file

@ -347,7 +347,7 @@ void TParseContext::handleLoopAttributes(const TAttributes& attributes, TIntermN
// //
// Function attributes // Function attributes
// //
void TParseContext::handleFunctionAttributes(const TSourceLoc& loc, const TAttributes& attributes, TFunction* function) void TParseContext::handleFunctionAttributes(const TSourceLoc& loc, const TAttributes& attributes)
{ {
for (auto it = attributes.begin(); it != attributes.end(); ++it) { for (auto it = attributes.begin(); it != attributes.end(); ++it) {
if (it->size() > 0) { if (it->size() > 0) {

View file

@ -315,7 +315,7 @@ GLSLANG_WEB_EXCLUDE_ON
%token <lex> PATCH SAMPLE NONUNIFORM %token <lex> PATCH SAMPLE NONUNIFORM
%token <lex> COHERENT VOLATILE RESTRICT READONLY WRITEONLY DEVICECOHERENT QUEUEFAMILYCOHERENT WORKGROUPCOHERENT %token <lex> COHERENT VOLATILE RESTRICT READONLY WRITEONLY DEVICECOHERENT QUEUEFAMILYCOHERENT WORKGROUPCOHERENT
%token <lex> SUBGROUPCOHERENT NONPRIVATE SHADERCALLCOHERENT %token <lex> SUBGROUPCOHERENT NONPRIVATE SHADERCALLCOHERENT
%token <lex> NOPERSPECTIVE EXPLICITINTERPAMD PERVERTEXNV PERPRIMITIVENV PERVIEWNV PERTASKNV %token <lex> NOPERSPECTIVE EXPLICITINTERPAMD PERVERTEXEXT PERVERTEXNV PERPRIMITIVENV PERVIEWNV PERTASKNV
%token <lex> PRECISE %token <lex> PRECISE
GLSLANG_WEB_EXCLUDE_OFF GLSLANG_WEB_EXCLUDE_OFF
@ -798,7 +798,7 @@ conditional_expression
parseContext.rValueErrorCheck($5.loc, ":", $6); parseContext.rValueErrorCheck($5.loc, ":", $6);
$$ = parseContext.intermediate.addSelection($1, $4, $6, $2.loc); $$ = parseContext.intermediate.addSelection($1, $4, $6, $2.loc);
if ($$ == 0) { 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; $$ = $6;
} }
} }
@ -815,7 +815,7 @@ assignment_expression
parseContext.rValueErrorCheck($2.loc, "assign", $3); parseContext.rValueErrorCheck($2.loc, "assign", $3);
$$ = parseContext.addAssign($2.loc, $2.op, $1, $3); $$ = parseContext.addAssign($2.loc, $2.op, $1, $3);
if ($$ == 0) { 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; $$ = $1;
} }
} }
@ -877,7 +877,7 @@ expression
parseContext.samplerConstructorLocationCheck($2.loc, ",", $3); parseContext.samplerConstructorLocationCheck($2.loc, ",", $3);
$$ = parseContext.intermediate.addComma($1, $3, $2.loc); $$ = parseContext.intermediate.addComma($1, $3, $2.loc);
if ($$ == 0) { 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; $$ = $3;
} }
} }
@ -983,20 +983,20 @@ function_prototype
$$.function = $1; $$.function = $1;
$$.loc = $2.loc; $$.loc = $2.loc;
parseContext.requireExtensions($2.loc, 1, &E_GL_EXT_subgroup_uniform_control_flow, "attribute"); parseContext.requireExtensions($2.loc, 1, &E_GL_EXT_subgroup_uniform_control_flow, "attribute");
parseContext.handleFunctionAttributes($2.loc, *$3, $$.function); parseContext.handleFunctionAttributes($2.loc, *$3);
} }
| attribute function_declarator RIGHT_PAREN { | attribute function_declarator RIGHT_PAREN {
$$.function = $2; $$.function = $2;
$$.loc = $3.loc; $$.loc = $3.loc;
parseContext.requireExtensions($3.loc, 1, &E_GL_EXT_subgroup_uniform_control_flow, "attribute"); parseContext.requireExtensions($3.loc, 1, &E_GL_EXT_subgroup_uniform_control_flow, "attribute");
parseContext.handleFunctionAttributes($3.loc, *$1, $$.function); parseContext.handleFunctionAttributes($3.loc, *$1);
} }
| attribute function_declarator RIGHT_PAREN attribute { | attribute function_declarator RIGHT_PAREN attribute {
$$.function = $2; $$.function = $2;
$$.loc = $3.loc; $$.loc = $3.loc;
parseContext.requireExtensions($3.loc, 1, &E_GL_EXT_subgroup_uniform_control_flow, "attribute"); parseContext.requireExtensions($3.loc, 1, &E_GL_EXT_subgroup_uniform_control_flow, "attribute");
parseContext.handleFunctionAttributes($3.loc, *$1, $$.function); parseContext.handleFunctionAttributes($3.loc, *$1);
parseContext.handleFunctionAttributes($3.loc, *$4, $$.function); parseContext.handleFunctionAttributes($3.loc, *$4);
} }
; ;
@ -1290,6 +1290,14 @@ GLSLANG_WEB_EXCLUDE_ON
$$.init($1.loc); $$.init($1.loc);
$$.qualifier.pervertexNV = true; $$.qualifier.pervertexNV = true;
} }
| PERVERTEXEXT {
parseContext.globalCheck($1.loc, "pervertexEXT");
parseContext.profileRequires($1.loc, ECoreProfile, 0, E_GL_EXT_fragment_shader_barycentric, "fragment shader barycentric");
parseContext.profileRequires($1.loc, ECompatibilityProfile, 0, E_GL_EXT_fragment_shader_barycentric, "fragment shader barycentric");
parseContext.profileRequires($1.loc, EEsProfile, 0, E_GL_EXT_fragment_shader_barycentric, "fragment shader barycentric");
$$.init($1.loc);
$$.qualifier.pervertexEXT = true;
}
| PERPRIMITIVENV { | PERPRIMITIVENV {
// No need for profile version or extension check. Shader stage already checks both. // No need for profile version or extension check. Shader stage already checks both.
parseContext.globalCheck($1.loc, "perprimitiveNV"); parseContext.globalCheck($1.loc, "perprimitiveNV");
@ -3926,6 +3934,7 @@ iteration_statement_nonattributed
--parseContext.controlFlowNestingLevel; --parseContext.controlFlowNestingLevel;
} }
| DO { | DO {
parseContext.symbolTable.push();
++parseContext.loopNestingLevel; ++parseContext.loopNestingLevel;
++parseContext.statementNestingLevel; ++parseContext.statementNestingLevel;
++parseContext.controlFlowNestingLevel; ++parseContext.controlFlowNestingLevel;
@ -3937,6 +3946,7 @@ iteration_statement_nonattributed
parseContext.boolCheck($8.loc, $6); parseContext.boolCheck($8.loc, $6);
$$ = parseContext.intermediate.addLoop($3, $6, 0, false, $4.loc); $$ = parseContext.intermediate.addLoop($3, $6, 0, false, $4.loc);
parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]);
--parseContext.loopNestingLevel; --parseContext.loopNestingLevel;
--parseContext.statementNestingLevel; --parseContext.statementNestingLevel;
--parseContext.controlFlowNestingLevel; --parseContext.controlFlowNestingLevel;
@ -4365,9 +4375,6 @@ spirv_type_parameter
: constant_expression { : constant_expression {
$$ = parseContext.makeSpirvTypeParameters($1->getLoc(), $1->getAsConstantUnion()); $$ = parseContext.makeSpirvTypeParameters($1->getLoc(), $1->getAsConstantUnion());
} }
| type_specifier {
$$ = parseContext.makeSpirvTypeParameters($1);
}
spirv_instruction_qualifier spirv_instruction_qualifier
: SPIRV_INSTRUCTION LEFT_PAREN spirv_instruction_qualifier_list RIGHT_PAREN { : SPIRV_INSTRUCTION LEFT_PAREN spirv_instruction_qualifier_list RIGHT_PAREN {

View file

@ -315,7 +315,7 @@ extern int yylex(YYSTYPE*, TParseContext&);
%token <lex> PATCH SAMPLE NONUNIFORM %token <lex> PATCH SAMPLE NONUNIFORM
%token <lex> COHERENT VOLATILE RESTRICT READONLY WRITEONLY DEVICECOHERENT QUEUEFAMILYCOHERENT WORKGROUPCOHERENT %token <lex> COHERENT VOLATILE RESTRICT READONLY WRITEONLY DEVICECOHERENT QUEUEFAMILYCOHERENT WORKGROUPCOHERENT
%token <lex> SUBGROUPCOHERENT NONPRIVATE SHADERCALLCOHERENT %token <lex> SUBGROUPCOHERENT NONPRIVATE SHADERCALLCOHERENT
%token <lex> NOPERSPECTIVE EXPLICITINTERPAMD PERVERTEXNV PERPRIMITIVENV PERVIEWNV PERTASKNV %token <lex> NOPERSPECTIVE EXPLICITINTERPAMD PERVERTEXEXT PERVERTEXNV PERPRIMITIVENV PERVIEWNV PERTASKNV
%token <lex> PRECISE %token <lex> PRECISE
@ -798,7 +798,7 @@ conditional_expression
parseContext.rValueErrorCheck($5.loc, ":", $6); parseContext.rValueErrorCheck($5.loc, ":", $6);
$$ = parseContext.intermediate.addSelection($1, $4, $6, $2.loc); $$ = parseContext.intermediate.addSelection($1, $4, $6, $2.loc);
if ($$ == 0) { 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; $$ = $6;
} }
} }
@ -815,7 +815,7 @@ assignment_expression
parseContext.rValueErrorCheck($2.loc, "assign", $3); parseContext.rValueErrorCheck($2.loc, "assign", $3);
$$ = parseContext.addAssign($2.loc, $2.op, $1, $3); $$ = parseContext.addAssign($2.loc, $2.op, $1, $3);
if ($$ == 0) { 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; $$ = $1;
} }
} }
@ -877,7 +877,7 @@ expression
parseContext.samplerConstructorLocationCheck($2.loc, ",", $3); parseContext.samplerConstructorLocationCheck($2.loc, ",", $3);
$$ = parseContext.intermediate.addComma($1, $3, $2.loc); $$ = parseContext.intermediate.addComma($1, $3, $2.loc);
if ($$ == 0) { 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; $$ = $3;
} }
} }
@ -983,20 +983,20 @@ function_prototype
$$.function = $1; $$.function = $1;
$$.loc = $2.loc; $$.loc = $2.loc;
parseContext.requireExtensions($2.loc, 1, &E_GL_EXT_subgroup_uniform_control_flow, "attribute"); parseContext.requireExtensions($2.loc, 1, &E_GL_EXT_subgroup_uniform_control_flow, "attribute");
parseContext.handleFunctionAttributes($2.loc, *$3, $$.function); parseContext.handleFunctionAttributes($2.loc, *$3);
} }
| attribute function_declarator RIGHT_PAREN { | attribute function_declarator RIGHT_PAREN {
$$.function = $2; $$.function = $2;
$$.loc = $3.loc; $$.loc = $3.loc;
parseContext.requireExtensions($3.loc, 1, &E_GL_EXT_subgroup_uniform_control_flow, "attribute"); parseContext.requireExtensions($3.loc, 1, &E_GL_EXT_subgroup_uniform_control_flow, "attribute");
parseContext.handleFunctionAttributes($3.loc, *$1, $$.function); parseContext.handleFunctionAttributes($3.loc, *$1);
} }
| attribute function_declarator RIGHT_PAREN attribute { | attribute function_declarator RIGHT_PAREN attribute {
$$.function = $2; $$.function = $2;
$$.loc = $3.loc; $$.loc = $3.loc;
parseContext.requireExtensions($3.loc, 1, &E_GL_EXT_subgroup_uniform_control_flow, "attribute"); parseContext.requireExtensions($3.loc, 1, &E_GL_EXT_subgroup_uniform_control_flow, "attribute");
parseContext.handleFunctionAttributes($3.loc, *$1, $$.function); parseContext.handleFunctionAttributes($3.loc, *$1);
parseContext.handleFunctionAttributes($3.loc, *$4, $$.function); parseContext.handleFunctionAttributes($3.loc, *$4);
} }
; ;
@ -1290,6 +1290,14 @@ interpolation_qualifier
$$.init($1.loc); $$.init($1.loc);
$$.qualifier.pervertexNV = true; $$.qualifier.pervertexNV = true;
} }
| PERVERTEXEXT {
parseContext.globalCheck($1.loc, "pervertexEXT");
parseContext.profileRequires($1.loc, ECoreProfile, 0, E_GL_EXT_fragment_shader_barycentric, "fragment shader barycentric");
parseContext.profileRequires($1.loc, ECompatibilityProfile, 0, E_GL_EXT_fragment_shader_barycentric, "fragment shader barycentric");
parseContext.profileRequires($1.loc, EEsProfile, 0, E_GL_EXT_fragment_shader_barycentric, "fragment shader barycentric");
$$.init($1.loc);
$$.qualifier.pervertexEXT = true;
}
| PERPRIMITIVENV { | PERPRIMITIVENV {
// No need for profile version or extension check. Shader stage already checks both. // No need for profile version or extension check. Shader stage already checks both.
parseContext.globalCheck($1.loc, "perprimitiveNV"); parseContext.globalCheck($1.loc, "perprimitiveNV");
@ -3926,6 +3934,7 @@ iteration_statement_nonattributed
--parseContext.controlFlowNestingLevel; --parseContext.controlFlowNestingLevel;
} }
| DO { | DO {
parseContext.symbolTable.push();
++parseContext.loopNestingLevel; ++parseContext.loopNestingLevel;
++parseContext.statementNestingLevel; ++parseContext.statementNestingLevel;
++parseContext.controlFlowNestingLevel; ++parseContext.controlFlowNestingLevel;
@ -3937,6 +3946,7 @@ iteration_statement_nonattributed
parseContext.boolCheck($8.loc, $6); parseContext.boolCheck($8.loc, $6);
$$ = parseContext.intermediate.addLoop($3, $6, 0, false, $4.loc); $$ = parseContext.intermediate.addLoop($3, $6, 0, false, $4.loc);
parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]);
--parseContext.loopNestingLevel; --parseContext.loopNestingLevel;
--parseContext.statementNestingLevel; --parseContext.statementNestingLevel;
--parseContext.controlFlowNestingLevel; --parseContext.controlFlowNestingLevel;
@ -4365,9 +4375,6 @@ spirv_type_parameter
: constant_expression { : constant_expression {
$$ = parseContext.makeSpirvTypeParameters($1->getLoc(), $1->getAsConstantUnion()); $$ = parseContext.makeSpirvTypeParameters($1->getLoc(), $1->getAsConstantUnion());
} }
| type_specifier {
$$ = parseContext.makeSpirvTypeParameters($1);
}
spirv_instruction_qualifier spirv_instruction_qualifier
: SPIRV_INSTRUCTION LEFT_PAREN spirv_instruction_qualifier_list RIGHT_PAREN { : SPIRV_INSTRUCTION LEFT_PAREN spirv_instruction_qualifier_list RIGHT_PAREN {

File diff suppressed because it is too large Load diff

View file

@ -501,11 +501,12 @@ extern int yydebug;
SHADERCALLCOHERENT = 702, /* SHADERCALLCOHERENT */ SHADERCALLCOHERENT = 702, /* SHADERCALLCOHERENT */
NOPERSPECTIVE = 703, /* NOPERSPECTIVE */ NOPERSPECTIVE = 703, /* NOPERSPECTIVE */
EXPLICITINTERPAMD = 704, /* EXPLICITINTERPAMD */ EXPLICITINTERPAMD = 704, /* EXPLICITINTERPAMD */
PERVERTEXNV = 705, /* PERVERTEXNV */ PERVERTEXEXT = 705, /* PERVERTEXEXT */
PERPRIMITIVENV = 706, /* PERPRIMITIVENV */ PERVERTEXNV = 706, /* PERVERTEXNV */
PERVIEWNV = 707, /* PERVIEWNV */ PERPRIMITIVENV = 707, /* PERPRIMITIVENV */
PERTASKNV = 708, /* PERTASKNV */ PERVIEWNV = 708, /* PERVIEWNV */
PRECISE = 709 /* PRECISE */ PERTASKNV = 709, /* PERTASKNV */
PRECISE = 710 /* PRECISE */
}; };
typedef enum yytokentype yytoken_kind_t; typedef enum yytokentype yytoken_kind_t;
#endif #endif
@ -553,7 +554,7 @@ union YYSTYPE
glslang::TArraySizes* typeParameters; glslang::TArraySizes* typeParameters;
} interm; } interm;
#line 557 "MachineIndependent/glslang_tab.cpp.h" #line 558 "MachineIndependent/glslang_tab.cpp.h"
}; };
typedef union YYSTYPE YYSTYPE; typedef union YYSTYPE YYSTYPE;

View file

@ -48,37 +48,6 @@
#endif #endif
#include <cstdint> #include <cstdint>
namespace {
bool IsInfinity(double x) {
#ifdef _MSC_VER
switch (_fpclass(x)) {
case _FPCLASS_NINF:
case _FPCLASS_PINF:
return true;
default:
return false;
}
#else
return std::isinf(x);
#endif
}
bool IsNan(double x) {
#ifdef _MSC_VER
switch (_fpclass(x)) {
case _FPCLASS_SNAN:
case _FPCLASS_QNAN:
return true;
default:
return false;
}
#else
return std::isnan(x);
#endif
}
}
namespace glslang { namespace glslang {

View file

@ -79,7 +79,7 @@ public:
target = &inputList; target = &inputList;
else if (base->getQualifier().storage == EvqVaryingOut) else if (base->getQualifier().storage == EvqVaryingOut)
target = &outputList; target = &outputList;
else if (base->getQualifier().isUniformOrBuffer() && !base->getQualifier().isPushConstant()) else if (base->getQualifier().isUniformOrBuffer() && !base->getQualifier().isPushConstant() && !base->getQualifier().isShaderRecord())
target = &uniformList; target = &uniformList;
// If a global is being visited, then we should also traverse it incase it's evaluation // If a global is being visited, then we should also traverse it incase it's evaluation
// ends up visiting inputs we want to tag as live // ends up visiting inputs we want to tag as live
@ -203,11 +203,7 @@ struct TResolverUniformAdaptor {
inline void operator()(std::pair<const TString, TVarEntryInfo>& entKey) { inline void operator()(std::pair<const TString, TVarEntryInfo>& entKey) {
TVarEntryInfo& ent = entKey.second; TVarEntryInfo& ent = entKey.second;
ent.newLocation = -1; ent.clearNewAssignments();
ent.newComponent = -1;
ent.newBinding = -1;
ent.newSet = -1;
ent.newIndex = -1;
const bool isValid = resolver.validateBinding(stage, ent); const bool isValid = resolver.validateBinding(stage, ent);
if (isValid) { if (isValid) {
resolver.resolveSet(ent.stage, ent); resolver.resolveSet(ent.stage, ent);
@ -281,11 +277,7 @@ struct TResolverInOutAdaptor {
inline void operator()(std::pair<const TString, TVarEntryInfo>& entKey) inline void operator()(std::pair<const TString, TVarEntryInfo>& entKey)
{ {
TVarEntryInfo& ent = entKey.second; TVarEntryInfo& ent = entKey.second;
ent.newLocation = -1; ent.clearNewAssignments();
ent.newComponent = -1;
ent.newBinding = -1;
ent.newSet = -1;
ent.newIndex = -1;
const bool isValid = resolver.validateInOut(ent.stage, ent); const bool isValid = resolver.validateInOut(ent.stage, ent);
if (isValid) { if (isValid) {
resolver.resolveInOutLocation(stage, ent); resolver.resolveInOutLocation(stage, ent);
@ -514,6 +506,24 @@ struct TSymbolValidater
return; return;
} }
else { else {
// Deal with input/output pairs where one is a block member but the other is loose,
// e.g. with ARB_separate_shader_objects
if (type1.getBasicType() == EbtBlock &&
type1.isStruct() && !type2.isStruct()) {
// Iterate through block members tracking layout
glslang::TString name;
type1.getStruct()->begin()->type->appendMangledName(name);
if (name == mangleName2
&& type1.getQualifier().layoutLocation == type2.getQualifier().layoutLocation) return;
}
if (type2.getBasicType() == EbtBlock &&
type2.isStruct() && !type1.isStruct()) {
// Iterate through block members tracking layout
glslang::TString name;
type2.getStruct()->begin()->type->appendMangledName(name);
if (name == mangleName1
&& type1.getQualifier().layoutLocation == type2.getQualifier().layoutLocation) return;
}
TString err = "Invalid In/Out variable type : " + entKey.first; TString err = "Invalid In/Out variable type : " + entKey.first;
infoSink.info.message(EPrefixInternalError, err.c_str()); infoSink.info.message(EPrefixInternalError, err.c_str());
hadError = true; hadError = true;
@ -748,7 +758,7 @@ private:
}; };
TDefaultIoResolverBase::TDefaultIoResolverBase(const TIntermediate& intermediate) TDefaultIoResolverBase::TDefaultIoResolverBase(const TIntermediate& intermediate)
: intermediate(intermediate) : referenceIntermediate(intermediate)
, nextUniformLocation(intermediate.getUniformLocationBase()) , nextUniformLocation(intermediate.getUniformLocationBase())
, nextInputLocation(0) , nextInputLocation(0)
, nextOutputLocation(0) , nextOutputLocation(0)
@ -760,17 +770,17 @@ TDefaultIoResolverBase::TDefaultIoResolverBase(const TIntermediate& intermediate
int TDefaultIoResolverBase::getBaseBinding(EShLanguage stage, TResourceType res, unsigned int set) const { int TDefaultIoResolverBase::getBaseBinding(EShLanguage stage, TResourceType res, unsigned int set) const {
return stageIntermediates[stage] ? selectBaseBinding(stageIntermediates[stage]->getShiftBinding(res), stageIntermediates[stage]->getShiftBindingForSet(res, set)) return stageIntermediates[stage] ? selectBaseBinding(stageIntermediates[stage]->getShiftBinding(res), stageIntermediates[stage]->getShiftBindingForSet(res, set))
: selectBaseBinding(intermediate.getShiftBinding(res), intermediate.getShiftBindingForSet(res, set)); : selectBaseBinding(referenceIntermediate.getShiftBinding(res), referenceIntermediate.getShiftBindingForSet(res, set));
} }
const std::vector<std::string>& TDefaultIoResolverBase::getResourceSetBinding(EShLanguage stage) const { const std::vector<std::string>& TDefaultIoResolverBase::getResourceSetBinding(EShLanguage stage) const {
return stageIntermediates[stage] ? stageIntermediates[stage]->getResourceSetBinding() return stageIntermediates[stage] ? stageIntermediates[stage]->getResourceSetBinding()
: intermediate.getResourceSetBinding(); : referenceIntermediate.getResourceSetBinding();
} }
bool TDefaultIoResolverBase::doAutoBindingMapping() const { return intermediate.getAutoMapBindings(); } bool TDefaultIoResolverBase::doAutoBindingMapping() const { return referenceIntermediate.getAutoMapBindings(); }
bool TDefaultIoResolverBase::doAutoLocationMapping() const { return intermediate.getAutoMapLocations(); } bool TDefaultIoResolverBase::doAutoLocationMapping() const { return referenceIntermediate.getAutoMapLocations(); }
TDefaultIoResolverBase::TSlotSet::iterator TDefaultIoResolverBase::findSlot(int set, int slot) { TDefaultIoResolverBase::TSlotSet::iterator TDefaultIoResolverBase::findSlot(int set, int slot) {
return std::lower_bound(slots[set].begin(), slots[set].end(), slot); return std::lower_bound(slots[set].begin(), slots[set].end(), slot);
@ -827,7 +837,7 @@ int TDefaultIoResolverBase::resolveUniformLocation(EShLanguage /*stage*/, TVarEn
} }
// no locations added if already present, a built-in variable, a block, or an opaque // no locations added if already present, a built-in variable, a block, or an opaque
if (type.getQualifier().hasLocation() || type.isBuiltIn() || type.getBasicType() == EbtBlock || if (type.getQualifier().hasLocation() || type.isBuiltIn() || type.getBasicType() == EbtBlock ||
type.isAtomic() || (type.containsOpaque() && intermediate.getSpv().openGl == 0)) { type.isAtomic() || type.isSpirvType() || (type.containsOpaque() && referenceIntermediate.getSpv().openGl == 0)) {
return ent.newLocation = -1; return ent.newLocation = -1;
} }
// no locations on blocks of built-in variables // no locations on blocks of built-in variables
@ -839,7 +849,7 @@ int TDefaultIoResolverBase::resolveUniformLocation(EShLanguage /*stage*/, TVarEn
return ent.newLocation = -1; return ent.newLocation = -1;
} }
} }
int location = intermediate.getUniformLocationOverride(name); int location = referenceIntermediate.getUniformLocationOverride(name);
if (location != -1) { if (location != -1) {
return ent.newLocation = location; return ent.newLocation = location;
} }
@ -855,8 +865,8 @@ int TDefaultIoResolverBase::resolveInOutLocation(EShLanguage stage, TVarEntryInf
return ent.newLocation = -1; return ent.newLocation = -1;
} }
// no locations added if already present, or a built-in variable // no locations added if already present, a built-in variable, or a variable with SPIR-V decorate
if (type.getQualifier().hasLocation() || type.isBuiltIn()) { if (type.getQualifier().hasLocation() || type.isBuiltIn() || type.getQualifier().hasSprivDecorate()) {
return ent.newLocation = -1; return ent.newLocation = -1;
} }
@ -942,8 +952,8 @@ int TDefaultGlslIoResolver::resolveInOutLocation(EShLanguage stage, TVarEntryInf
if (type.getQualifier().hasLocation()) { if (type.getQualifier().hasLocation()) {
return ent.newLocation = type.getQualifier().layoutLocation; return ent.newLocation = type.getQualifier().layoutLocation;
} }
// no locations added if already present, or a built-in variable // no locations added if already present, a built-in variable, or a variable with SPIR-V decorate
if (type.isBuiltIn()) { if (type.isBuiltIn() || type.getQualifier().hasSprivDecorate()) {
return ent.newLocation = -1; return ent.newLocation = -1;
} }
// no locations on blocks of built-in variables // no locations on blocks of built-in variables
@ -1024,7 +1034,8 @@ int TDefaultGlslIoResolver::resolveUniformLocation(EShLanguage /*stage*/, TVarEn
} else { } else {
// no locations added if already present, a built-in variable, a block, or an opaque // no locations added if already present, a built-in variable, a block, or an opaque
if (type.getQualifier().hasLocation() || type.isBuiltIn() || type.getBasicType() == EbtBlock || if (type.getQualifier().hasLocation() || type.isBuiltIn() || type.getBasicType() == EbtBlock ||
type.isAtomic() || (type.containsOpaque() && intermediate.getSpv().openGl == 0)) { type.isAtomic() || type.isSpirvType() ||
(type.containsOpaque() && referenceIntermediate.getSpv().openGl == 0)) {
return ent.newLocation = -1; return ent.newLocation = -1;
} }
// no locations on blocks of built-in variables // no locations on blocks of built-in variables
@ -1037,7 +1048,7 @@ int TDefaultGlslIoResolver::resolveUniformLocation(EShLanguage /*stage*/, TVarEn
} }
} }
} }
int location = intermediate.getUniformLocationOverride(name.c_str()); int location = referenceIntermediate.getUniformLocationOverride(name.c_str());
if (location != -1) { if (location != -1) {
return ent.newLocation = location; return ent.newLocation = location;
} }
@ -1086,7 +1097,7 @@ int TDefaultGlslIoResolver::resolveBinding(EShLanguage stage, TVarEntryInfo& ent
const TType& type = ent.symbol->getType(); const TType& type = ent.symbol->getType();
const TString& name = ent.symbol->getAccessName(); const TString& name = ent.symbol->getAccessName();
// On OpenGL arrays of opaque types take a separate binding for each element // On OpenGL arrays of opaque types take a separate binding for each element
int numBindings = intermediate.getSpv().openGl != 0 && type.isSizedArray() ? type.getCumulativeArraySize() : 1; int numBindings = referenceIntermediate.getSpv().openGl != 0 && type.isSizedArray() ? type.getCumulativeArraySize() : 1;
TResourceType resource = getResourceType(type); TResourceType resource = getResourceType(type);
// don't need to handle uniform symbol, it will be handled in resolveUniformLocation // don't need to handle uniform symbol, it will be handled in resolveUniformLocation
if (resource == EResUbo && type.getBasicType() != EbtBlock) { if (resource == EResUbo && type.getBasicType() != EbtBlock) {
@ -1095,7 +1106,7 @@ int TDefaultGlslIoResolver::resolveBinding(EShLanguage stage, TVarEntryInfo& ent
// There is no 'set' qualifier in OpenGL shading language, each resource has its own // There is no 'set' qualifier in OpenGL shading language, each resource has its own
// binding name space, so remap the 'set' to resource type which make each resource // binding name space, so remap the 'set' to resource type which make each resource
// binding is valid from 0 to MAX_XXRESOURCE_BINDINGS // binding is valid from 0 to MAX_XXRESOURCE_BINDINGS
int set = intermediate.getSpv().openGl != 0 ? resource : ent.newSet; int set = referenceIntermediate.getSpv().openGl != 0 ? resource : ent.newSet;
int resourceKey = set; int resourceKey = set;
if (resource < EResCount) { if (resource < EResCount) {
if (type.getQualifier().hasBinding()) { if (type.getQualifier().hasBinding()) {
@ -1223,7 +1234,7 @@ void TDefaultGlslIoResolver::reserverResourceSlot(TVarEntryInfo& ent, TInfoSink&
const TType& type = ent.symbol->getType(); const TType& type = ent.symbol->getType();
const TString& name = ent.symbol->getAccessName(); const TString& name = ent.symbol->getAccessName();
TResourceType resource = getResourceType(type); TResourceType resource = getResourceType(type);
int set = intermediate.getSpv().openGl != 0 ? resource : resolveSet(ent.stage, ent); int set = referenceIntermediate.getSpv().openGl != 0 ? resource : resolveSet(ent.stage, ent);
int resourceKey = set; int resourceKey = set;
if (type.getQualifier().hasBinding()) { if (type.getQualifier().hasBinding()) {
@ -1233,7 +1244,7 @@ void TDefaultGlslIoResolver::reserverResourceSlot(TVarEntryInfo& ent, TInfoSink&
if (iter == varSlotMap.end()) { if (iter == varSlotMap.end()) {
// Reserve the slots for the ubo, ssbo and opaques who has explicit binding // Reserve the slots for the ubo, ssbo and opaques who has explicit binding
int numBindings = intermediate.getSpv().openGl != 0 && type.isSizedArray() ? type.getCumulativeArraySize() : 1; int numBindings = referenceIntermediate.getSpv().openGl != 0 && type.isSizedArray() ? type.getCumulativeArraySize() : 1;
varSlotMap[name] = binding; varSlotMap[name] = binding;
reserveSlot(resourceKey, binding, numBindings); reserveSlot(resourceKey, binding, numBindings);
} else { } else {
@ -1288,7 +1299,7 @@ struct TDefaultIoResolver : public TDefaultIoResolverBase {
const TType& type = ent.symbol->getType(); const TType& type = ent.symbol->getType();
const int set = getLayoutSet(type); const int set = getLayoutSet(type);
// On OpenGL arrays of opaque types take a seperate binding for each element // On OpenGL arrays of opaque types take a seperate binding for each element
int numBindings = intermediate.getSpv().openGl != 0 && type.isSizedArray() ? type.getCumulativeArraySize() : 1; int numBindings = referenceIntermediate.getSpv().openGl != 0 && type.isSizedArray() ? type.getCumulativeArraySize() : 1;
TResourceType resource = getResourceType(type); TResourceType resource = getResourceType(type);
if (resource < EResCount) { if (resource < EResCount) {
if (type.getQualifier().hasBinding()) { if (type.getQualifier().hasBinding()) {
@ -1633,6 +1644,45 @@ bool TGlslIoMapper::doMap(TIoMapResolver* resolver, TInfoSink& infoSink) {
return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second); return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second);
}); });
resolver->endResolve(EShLangCount); resolver->endResolve(EShLangCount);
if (autoPushConstantBlockName.length()) {
bool upgraded = false;
for (size_t stage = 0; stage < EShLangCount; stage++) {
if (intermediates[stage] != nullptr) {
TVarLiveMap** pUniformVarMap = uniformResolve.uniformVarMap;
auto at = pUniformVarMap[stage]->find(autoPushConstantBlockName);
if (at == pUniformVarMap[stage]->end())
continue;
TQualifier& qualifier = at->second.symbol->getQualifier();
if (!qualifier.isUniform())
continue;
TType& t = at->second.symbol->getWritableType();
int size, stride;
TIntermediate::getBaseAlignment(t, size, stride, autoPushConstantBlockPacking,
qualifier.layoutMatrix == ElmRowMajor);
if (size <= int(autoPushConstantMaxSize)) {
qualifier.setBlockStorage(EbsPushConstant);
qualifier.layoutPacking = autoPushConstantBlockPacking;
// Push constants don't have set/binding etc. decorations, remove those.
qualifier.layoutSet = TQualifier::layoutSetEnd;
at->second.clearNewAssignments();
upgraded = true;
}
}
}
// If it's been upgraded to push_constant, then remove it from the uniformVector
// so it doesn't get a set/binding assigned to it.
if (upgraded) {
while (1) {
auto at = std::find_if(uniformVector.begin(), uniformVector.end(),
[this](const TVarLivePair& p) { return p.first == autoPushConstantBlockName; });
if (at != uniformVector.end())
uniformVector.erase(at);
else
break;
}
}
}
for (size_t stage = 0; stage < EShLangCount; stage++) { for (size_t stage = 0; stage < EShLangCount; stage++) {
if (intermediates[stage] != nullptr) { if (intermediates[stage] != nullptr) {
// traverse each stage, set new location to each input/output and unifom symbol, set new binding to // traverse each stage, set new location to each input/output and unifom symbol, set new binding to

View file

@ -61,6 +61,15 @@ struct TVarEntryInfo {
int newComponent; int newComponent;
int newIndex; int newIndex;
EShLanguage stage; EShLanguage stage;
void clearNewAssignments() {
newBinding = -1;
newSet = -1;
newLocation = -1;
newComponent = -1;
newIndex = -1;
}
struct TOrderById { struct TOrderById {
inline bool operator()(const TVarEntryInfo& l, const TVarEntryInfo& r) { return l.id < r.id; } inline bool operator()(const TVarEntryInfo& l, const TVarEntryInfo& r) { return l.id < r.id; }
}; };
@ -165,7 +174,7 @@ public:
protected: protected:
TDefaultIoResolverBase(TDefaultIoResolverBase&); TDefaultIoResolverBase(TDefaultIoResolverBase&);
TDefaultIoResolverBase& operator=(TDefaultIoResolverBase&); TDefaultIoResolverBase& operator=(TDefaultIoResolverBase&);
const TIntermediate& intermediate; const TIntermediate& referenceIntermediate;
int nextUniformLocation; int nextUniformLocation;
int nextInputLocation; int nextInputLocation;
int nextOutputLocation; int nextOutputLocation;
@ -291,7 +300,7 @@ public:
bool virtual doMap(TIoMapResolver*, TInfoSink&) { return true; } bool virtual doMap(TIoMapResolver*, TInfoSink&) { return true; }
}; };
// I/O mapper for OpenGL // I/O mapper for GLSL
class TGlslIoMapper : public TIoMapper { class TGlslIoMapper : public TIoMapper {
public: public:
TGlslIoMapper() { TGlslIoMapper() {
@ -301,6 +310,8 @@ public:
memset(intermediates, 0, sizeof(TIntermediate*) * (EShLangCount + 1)); memset(intermediates, 0, sizeof(TIntermediate*) * (EShLangCount + 1));
profile = ENoProfile; profile = ENoProfile;
version = 0; version = 0;
autoPushConstantMaxSize = 128;
autoPushConstantBlockPacking = ElpStd430;
} }
virtual ~TGlslIoMapper() { virtual ~TGlslIoMapper() {
for (size_t stage = 0; stage < EShLangCount; stage++) { for (size_t stage = 0; stage < EShLangCount; stage++) {
@ -320,6 +331,13 @@ public:
intermediates[stage] = nullptr; intermediates[stage] = nullptr;
} }
} }
// If set, the uniform block with the given name will be changed to be backed by
// push_constant if it's size is <= maxSize
void setAutoPushConstantBlock(const char* name, unsigned int maxSize, TLayoutPacking packing) {
autoPushConstantBlockName = name;
autoPushConstantMaxSize = maxSize;
autoPushConstantBlockPacking = packing;
}
// grow the reflection stage by stage // grow the reflection stage by stage
bool addStage(EShLanguage, TIntermediate&, TInfoSink&, TIoMapResolver*) override; bool addStage(EShLanguage, TIntermediate&, TInfoSink&, TIoMapResolver*) override;
bool doMap(TIoMapResolver*, TInfoSink&) override; bool doMap(TIoMapResolver*, TInfoSink&) override;
@ -329,6 +347,11 @@ public:
bool hadError = false; bool hadError = false;
EProfile profile; EProfile profile;
int version; int version;
private:
TString autoPushConstantBlockName;
unsigned int autoPushConstantMaxSize;
TLayoutPacking autoPushConstantBlockPacking;
}; };
} // end namespace glslang } // end namespace glslang

View file

@ -55,22 +55,28 @@ namespace glslang {
// //
// Link-time error emitter. // 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 #ifndef GLSLANG_WEB
infoSink.info.prefix(EPrefixError); 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 #endif
++numErrors; ++numErrors;
} }
// Link-time warning. // Link-time warning.
void TIntermediate::warn(TInfoSink& infoSink, const char* message) void TIntermediate::warn(TInfoSink& infoSink, const char* message, EShLanguage unitStage)
{ {
#ifndef GLSLANG_WEB #ifndef GLSLANG_WEB
infoSink.info.prefix(EPrefixWarning); 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 #endif
} }
@ -312,6 +318,7 @@ void TIntermediate::mergeModes(TInfoSink& infoSink, TIntermediate& unit)
MERGE_TRUE(autoMapBindings); MERGE_TRUE(autoMapBindings);
MERGE_TRUE(autoMapLocations); MERGE_TRUE(autoMapLocations);
MERGE_TRUE(invertY); MERGE_TRUE(invertY);
MERGE_TRUE(dxPositionW);
MERGE_TRUE(flattenUniformArrays); MERGE_TRUE(flattenUniformArrays);
MERGE_TRUE(useUnknownFormat); MERGE_TRUE(useUnknownFormat);
MERGE_TRUE(hlslOffsets); MERGE_TRUE(hlslOffsets);
@ -579,9 +586,6 @@ void TIntermediate::mergeGlobalUniformBlocks(TInfoSink& infoSink, TIntermediate&
} }
void TIntermediate::mergeBlockDefinitions(TInfoSink& infoSink, TIntermSymbol* block, TIntermSymbol* unitBlock, TIntermediate* unit) { void TIntermediate::mergeBlockDefinitions(TInfoSink& infoSink, TIntermSymbol* block, TIntermSymbol* unitBlock, TIntermediate* unit) {
if (block->getType() == unitBlock->getType()) {
return;
}
if (block->getType().getTypeName() != unitBlock->getType().getTypeName() || if (block->getType().getTypeName() != unitBlock->getType().getTypeName() ||
block->getType().getBasicType() != unitBlock->getType().getBasicType() || block->getType().getBasicType() != unitBlock->getType().getBasicType() ||
@ -628,44 +632,42 @@ void TIntermediate::mergeBlockDefinitions(TInfoSink& infoSink, TIntermSymbol* bl
} }
} }
TType unitType;
unitType.shallowCopy(unitBlock->getType());
// update symbol node in unit tree, // update symbol node in unit tree,
// and other nodes that may reference it // and other nodes that may reference it
class TMergeBlockTraverser : public TIntermTraverser { class TMergeBlockTraverser : public TIntermTraverser {
public: public:
TMergeBlockTraverser(const glslang::TType &type, const glslang::TType& unitType, TMergeBlockTraverser(const TIntermSymbol* newSym)
glslang::TIntermediate& unit, : newSymbol(newSym), unitType(nullptr), unit(nullptr), memberIndexUpdates(nullptr)
const std::map<unsigned int, unsigned int>& memberIdxUpdates) : {
newType(type), unitType(unitType), unit(unit), memberIndexUpdates(memberIdxUpdates) }
{ } TMergeBlockTraverser(const TIntermSymbol* newSym, const glslang::TType* unitType, glslang::TIntermediate* unit,
virtual ~TMergeBlockTraverser() { } const std::map<unsigned int, unsigned int>* memberIdxUpdates)
: TIntermTraverser(false, true), newSymbol(newSym), unitType(unitType), unit(unit), memberIndexUpdates(memberIdxUpdates)
{
}
virtual ~TMergeBlockTraverser() {}
const glslang::TType& newType; // type with modifications const TIntermSymbol* newSymbol;
const glslang::TType& unitType; // copy of original type const glslang::TType* unitType; // copy of original type
glslang::TIntermediate& unit; // intermediate that is being updated glslang::TIntermediate* unit; // intermediate that is being updated
const std::map<unsigned int, unsigned int>& memberIndexUpdates; const std::map<unsigned int, unsigned int>* memberIndexUpdates;
virtual void visitSymbol(TIntermSymbol* symbol) virtual void visitSymbol(TIntermSymbol* symbol)
{ {
glslang::TType& symType = symbol->getWritableType(); if (newSymbol->getAccessName() == symbol->getAccessName() &&
newSymbol->getQualifier().getBlockStorage() == symbol->getQualifier().getBlockStorage()) {
if (symType == unitType) { // Each symbol node may have a local copy of the block structure.
// each symbol node has a local copy of the unitType // Update those structures to match the new one post-merge
// if merging involves changing properties that aren't shared objects *(symbol->getWritableType().getWritableStruct()) = *(newSymbol->getType().getStruct());
// they should be updated in all instances
// e.g. the struct list is a ptr to an object, so it can be updated
// once, outside the traverser
//*symType.getWritableStruct() = *newType.getStruct();
} }
} }
virtual bool visitBinary(TVisit, glslang::TIntermBinary* node) virtual bool visitBinary(TVisit, glslang::TIntermBinary* node)
{ {
if (node->getOp() == EOpIndexDirectStruct && node->getLeft()->getType() == unitType) { if (!unit || !unitType || !memberIndexUpdates || memberIndexUpdates->empty())
return true;
if (node->getOp() == EOpIndexDirectStruct && node->getLeft()->getType() == *unitType) {
// this is a dereference to a member of the block since the // this is a dereference to a member of the block since the
// member list changed, need to update this to point to the // member list changed, need to update this to point to the
// right index // right index
@ -673,8 +675,8 @@ void TIntermediate::mergeBlockDefinitions(TInfoSink& infoSink, TIntermSymbol* bl
glslang::TIntermConstantUnion* constNode = node->getRight()->getAsConstantUnion(); glslang::TIntermConstantUnion* constNode = node->getRight()->getAsConstantUnion();
unsigned int memberIdx = constNode->getConstArray()[0].getUConst(); unsigned int memberIdx = constNode->getConstArray()[0].getUConst();
unsigned int newIdx = memberIndexUpdates.at(memberIdx); unsigned int newIdx = memberIndexUpdates->at(memberIdx);
TIntermTyped* newConstNode = unit.addConstantUnion(newIdx, node->getRight()->getLoc()); TIntermTyped* newConstNode = unit->addConstantUnion(newIdx, node->getRight()->getLoc());
node->setRight(newConstNode); node->setRight(newConstNode);
delete constNode; delete constNode;
@ -683,10 +685,20 @@ void TIntermediate::mergeBlockDefinitions(TInfoSink& infoSink, TIntermSymbol* bl
} }
return true; return true;
} }
} finalLinkTraverser(block->getType(), unitType, *unit, memberIndexUpdates); };
// update the tree to use the new type // 'this' may have symbols that are using the old block structure, so traverse the tree to update those
unit->getTreeRoot()->traverse(&finalLinkTraverser); // in 'visitSymbol'
TMergeBlockTraverser finalLinkTraverser(block);
getTreeRoot()->traverse(&finalLinkTraverser);
// The 'unit' intermediate needs the block structures update, but also structure entry indices
// may have changed from the old block to the new one that it was merged into, so update those
// in 'visitBinary'
TType unitType;
unitType.shallowCopy(unitBlock->getType());
TMergeBlockTraverser unitFinalLinkTraverser(block, &unitType, unit, &memberIndexUpdates);
unit->getTreeRoot()->traverse(&unitFinalLinkTraverser);
// update the member list // update the member list
(*unitMemberList) = (*memberList); (*unitMemberList) = (*memberList);
@ -759,7 +771,10 @@ void TIntermediate::mergeLinkerObjects(TInfoSink& infoSink, TIntermSequence& lin
auto checkName = [this, unitSymbol, &infoSink](const TString& name) { auto checkName = [this, unitSymbol, &infoSink](const TString& name) {
for (unsigned int i = 0; i < unitSymbol->getType().getStruct()->size(); ++i) { for (unsigned int i = 0; i < unitSymbol->getType().getStruct()->size(); ++i) {
if (name == (*unitSymbol->getType().getStruct())[i].type->getFieldName()) { if (name == (*unitSymbol->getType().getStruct())[i].type->getFieldName()
&& !((*unitSymbol->getType().getStruct())[i].type->getQualifier().hasLocation()
|| unitSymbol->getType().getQualifier().hasLocation())
) {
error(infoSink, "Anonymous member name used for global variable or other anonymous member: "); error(infoSink, "Anonymous member name used for global variable or other anonymous member: ");
infoSink.info << (*unitSymbol->getType().getStruct())[i].type->getCompleteString() << "\n"; infoSink.info << (*unitSymbol->getType().getStruct())[i].type->getCompleteString() << "\n";
} }
@ -815,6 +830,10 @@ void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& sy
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE) #if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
bool crossStage = getStage() != unitStage; bool crossStage = getStage() != unitStage;
bool writeTypeComparison = false; bool writeTypeComparison = false;
bool errorReported = false;
bool printQualifiers = false;
bool printPrecision = false;
bool printType = false;
// Types have to match // Types have to match
{ {
@ -846,11 +865,48 @@ void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& sy
(symbol.getType().isUnsizedArray() || unitSymbol.getType().isUnsizedArray())); (symbol.getType().isUnsizedArray() || unitSymbol.getType().isUnsizedArray()));
} }
if (!symbol.getType().sameElementType(unitSymbol.getType()) || int lpidx = -1;
!symbol.getType().sameTypeParameters(unitSymbol.getType()) || int rpidx = -1;
!arraysMatch ) { 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; 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;
} }
} }
@ -858,17 +914,51 @@ void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& sy
if (symbol.getType().getBasicType() == EbtBlock && unitSymbol.getType().getBasicType() == EbtBlock && if (symbol.getType().getBasicType() == EbtBlock && unitSymbol.getType().getBasicType() == EbtBlock &&
symbol.getType().getStruct() && unitSymbol.getType().getStruct() && symbol.getType().getStruct() && unitSymbol.getType().getStruct() &&
symbol.getType().sameStructType(unitSymbol.getType())) { symbol.getType().sameStructType(unitSymbol.getType())) {
for (unsigned int i = 0; i < symbol.getType().getStruct()->size(); ++i) { unsigned int li = 0;
const TQualifier& qualifier = (*symbol.getType().getStruct())[i].type->getQualifier(); unsigned int ri = 0;
const TQualifier& unitQualifier = (*unitSymbol.getType().getStruct())[i].type->getQualifier(); while (li < symbol.getType().getStruct()->size() && ri < unitSymbol.getType().getStruct()->size()) {
if (qualifier.layoutMatrix != unitQualifier.layoutMatrix || if ((*symbol.getType().getStruct())[li].type->hiddenMember()) {
qualifier.layoutOffset != unitQualifier.layoutOffset || ++li;
qualifier.layoutAlign != unitQualifier.layoutAlign || continue;
qualifier.layoutLocation != unitQualifier.layoutLocation ||
qualifier.layoutComponent != unitQualifier.layoutComponent) {
error(infoSink, "Interface block member layout qualifiers must match:");
writeTypeComparison = true;
} }
if ((*unitSymbol.getType().getStruct())[ri].type->hiddenMember()) {
++ri;
continue;
}
const TQualifier& qualifier = (*symbol.getType().getStruct())[li].type->getQualifier();
const TQualifier & unitQualifier = (*unitSymbol.getType().getStruct())[ri].type->getQualifier();
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;
} }
} }
@ -879,8 +969,9 @@ void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& sy
// Qualifiers have to (almost) match // Qualifiers have to (almost) match
// Storage... // Storage...
if (!isInOut && symbol.getQualifier().storage != unitSymbol.getQualifier().storage) { if (!isInOut && symbol.getQualifier().storage != unitSymbol.getQualifier().storage) {
error(infoSink, "Storage qualifiers must match:"); error(infoSink, "Storage qualifiers must match:", unitStage);
writeTypeComparison = true; writeTypeComparison = true;
printQualifiers = true;
} }
// Uniform and buffer blocks must either both have an instance name, or // Uniform and buffer blocks must either both have an instance name, or
@ -888,33 +979,36 @@ void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& sy
if (symbol.getQualifier().isUniformOrBuffer() && if (symbol.getQualifier().isUniformOrBuffer() &&
(IsAnonymous(symbol.getName()) != IsAnonymous(unitSymbol.getName()))) { (IsAnonymous(symbol.getName()) != IsAnonymous(unitSymbol.getName()))) {
error(infoSink, "Matched Uniform or Storage blocks must all be anonymous," error(infoSink, "Matched Uniform or Storage blocks must all be anonymous,"
" or all be named:"); " or all be named:", unitStage);
writeTypeComparison = true; writeTypeComparison = true;
} }
if (symbol.getQualifier().storage == unitSymbol.getQualifier().storage && if (symbol.getQualifier().storage == unitSymbol.getQualifier().storage &&
(IsAnonymous(symbol.getName()) != IsAnonymous(unitSymbol.getName()) || (IsAnonymous(symbol.getName()) != IsAnonymous(unitSymbol.getName()) ||
(!IsAnonymous(symbol.getName()) && symbol.getName() != 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; writeTypeComparison = true;
} }
// Precision... // Precision...
if (!isInOut && symbol.getQualifier().precision != unitSymbol.getQualifier().precision) { if (!isInOut && symbol.getQualifier().precision != unitSymbol.getQualifier().precision) {
error(infoSink, "Precision qualifiers must match:"); error(infoSink, "Precision qualifiers must match:", unitStage);
writeTypeComparison = true; writeTypeComparison = true;
printPrecision = true;
} }
// Invariance... // Invariance...
if (! crossStage && symbol.getQualifier().invariant != unitSymbol.getQualifier().invariant) { 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; writeTypeComparison = true;
printQualifiers = true;
} }
// Precise... // Precise...
if (! crossStage && symbol.getQualifier().isNoContraction() != unitSymbol.getQualifier().isNoContraction()) { 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; writeTypeComparison = true;
printPrecision = true;
} }
// Auxiliary and interpolation... // Auxiliary and interpolation...
@ -928,57 +1022,137 @@ void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& sy
symbol.getQualifier().isSample()!= unitSymbol.getQualifier().isSample() || symbol.getQualifier().isSample()!= unitSymbol.getQualifier().isSample() ||
symbol.getQualifier().isPatch() != unitSymbol.getQualifier().isPatch() || symbol.getQualifier().isPatch() != unitSymbol.getQualifier().isPatch() ||
symbol.getQualifier().isNonPerspective() != unitSymbol.getQualifier().isNonPerspective())) { 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; writeTypeComparison = true;
printQualifiers = true;
} }
// Memory... // Memory...
if (symbol.getQualifier().coherent != unitSymbol.getQualifier().coherent || bool memoryQualifierError = false;
symbol.getQualifier().devicecoherent != unitSymbol.getQualifier().devicecoherent || if (symbol.getQualifier().coherent != unitSymbol.getQualifier().coherent) {
symbol.getQualifier().queuefamilycoherent != unitSymbol.getQualifier().queuefamilycoherent || error(infoSink, "Memory coherent qualifier must match:", unitStage);
symbol.getQualifier().workgroupcoherent != unitSymbol.getQualifier().workgroupcoherent || memoryQualifierError = true;
symbol.getQualifier().subgroupcoherent != unitSymbol.getQualifier().subgroupcoherent || }
symbol.getQualifier().shadercallcoherent!= unitSymbol.getQualifier().shadercallcoherent || if (symbol.getQualifier().devicecoherent != unitSymbol.getQualifier().devicecoherent) {
symbol.getQualifier().nonprivate != unitSymbol.getQualifier().nonprivate || error(infoSink, "Memory devicecoherent qualifier must match:", unitStage);
symbol.getQualifier().volatil != unitSymbol.getQualifier().volatil || memoryQualifierError = true;
symbol.getQualifier().restrict != unitSymbol.getQualifier().restrict || }
symbol.getQualifier().readonly != unitSymbol.getQualifier().readonly || if (symbol.getQualifier().queuefamilycoherent != unitSymbol.getQualifier().queuefamilycoherent) {
symbol.getQualifier().writeonly != unitSymbol.getQualifier().writeonly) { error(infoSink, "Memory queuefamilycoherent qualifier must match:", unitStage);
error(infoSink, "Memory qualifiers must match:"); memoryQualifierError = true;
writeTypeComparison = 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... // Layouts...
// TODO: 4.4 enhanced layouts: Generalize to include offset/align: current spec // TODO: 4.4 enhanced layouts: Generalize to include offset/align: current spec
// requires separate user-supplied offset from actual computed offset, but // requires separate user-supplied offset from actual computed offset, but
// current implementation only has one offset. // current implementation only has one offset.
if (symbol.getQualifier().layoutMatrix != unitSymbol.getQualifier().layoutMatrix || bool layoutQualifierError = false;
symbol.getQualifier().layoutPacking != unitSymbol.getQualifier().layoutPacking || if (symbol.getQualifier().layoutMatrix != unitSymbol.getQualifier().layoutMatrix) {
symbol.getQualifier().layoutLocation != unitSymbol.getQualifier().layoutLocation || error(infoSink, "Layout matrix qualifier must match:", unitStage);
symbol.getQualifier().layoutComponent != unitSymbol.getQualifier().layoutComponent || layoutQualifierError = true;
symbol.getQualifier().layoutIndex != unitSymbol.getQualifier().layoutIndex || }
symbol.getQualifier().layoutBinding != unitSymbol.getQualifier().layoutBinding || if (symbol.getQualifier().layoutPacking != unitSymbol.getQualifier().layoutPacking) {
(symbol.getQualifier().hasBinding() && (symbol.getQualifier().layoutOffset != unitSymbol.getQualifier().layoutOffset))) { error(infoSink, "Layout packing qualifier must match:", unitStage);
error(infoSink, "Layout qualification must match:"); 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; writeTypeComparison = true;
printQualifiers = true;
} }
// Initializers have to match, if both are present, and if we don't already know the types don't match // 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().empty() && ! unitSymbol.getConstArray().empty()) {
if (symbol.getConstArray() != unitSymbol.getConstArray()) { if (symbol.getConstArray() != unitSymbol.getConstArray()) {
error(infoSink, "Initializers must match:"); error(infoSink, "Initializers must match:", unitStage);
infoSink.info << " " << symbol.getName() << "\n"; infoSink.info << " " << symbol.getName() << "\n";
} }
} }
} }
if (writeTypeComparison) { if (writeTypeComparison) {
infoSink.info << " " << symbol.getName() << ": \"" << symbol.getType().getCompleteString() << "\" versus "; if (symbol.getType().getBasicType() == EbtBlock && unitSymbol.getType().getBasicType() == EbtBlock &&
if (symbol.getName() != unitSymbol.getName()) symbol.getType().getStruct() && unitSymbol.getType().getStruct()) {
infoSink.info << unitSymbol.getName() << ": "; if (printType) {
infoSink.info << " " << StageName(getStage()) << " stage: \"" << symbol.getType().getCompleteString(true, printQualifiers, printPrecision,
infoSink.info << "\"" << unitSymbol.getType().getCompleteString() << "\"\n"; 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 #endif
} }
@ -1786,7 +1960,7 @@ unsigned int TIntermediate::computeTypeXfbSize(const TType& type, bool& contains
return size; return size;
} }
int numComponents; int numComponents {0};
if (type.isScalar()) if (type.isScalar())
numComponents = 1; numComponents = 1;
else if (type.isVector()) else if (type.isVector())
@ -1934,7 +2108,7 @@ int TIntermediate::getBaseAlignment(const TType& type, int& size, int& stride, T
} }
// rule 9 // rule 9
if (type.getBasicType() == EbtStruct) { if (type.getBasicType() == EbtStruct || type.getBasicType() == EbtBlock) {
const TTypeList& memberList = *type.getStruct(); const TTypeList& memberList = *type.getStruct();
size = 0; size = 0;
@ -2159,10 +2333,11 @@ int TIntermediate::computeBufferReferenceTypeSize(const TType& type)
bool TIntermediate::isIoResizeArray(const TType& type, EShLanguage language) { bool TIntermediate::isIoResizeArray(const TType& type, EShLanguage language) {
return type.isArray() && return type.isArray() &&
((language == EShLangGeometry && type.getQualifier().storage == EvqVaryingIn) || ((language == EShLangGeometry && type.getQualifier().storage == EvqVaryingIn) ||
(language == EShLangTessControl && type.getQualifier().storage == EvqVaryingOut && (language == EShLangTessControl && (type.getQualifier().storage == EvqVaryingIn || type.getQualifier().storage == EvqVaryingOut) &&
! type.getQualifier().patch) || ! type.getQualifier().patch) ||
(language == EShLangTessEvaluation && type.getQualifier().storage == EvqVaryingIn) ||
(language == EShLangFragment && type.getQualifier().storage == EvqVaryingIn && (language == EShLangFragment && type.getQualifier().storage == EvqVaryingIn &&
type.getQualifier().pervertexNV) || (type.getQualifier().pervertexNV || type.getQualifier().pervertexEXT)) ||
(language == EShLangMeshNV && type.getQualifier().storage == EvqVaryingOut && (language == EShLangMeshNV && type.getQualifier().storage == EvqVaryingOut &&
!type.getQualifier().perTaskNV)); !type.getQualifier().perTaskNV));
} }

View file

@ -290,6 +290,8 @@ public:
resources(TBuiltInResource{}), resources(TBuiltInResource{}),
numEntryPoints(0), numErrors(0), numPushConstants(0), recursive(false), numEntryPoints(0), numErrors(0), numPushConstants(0), recursive(false),
invertY(false), invertY(false),
dxPositionW(false),
enhancedMsgs(false),
useStorageBuffer(false), useStorageBuffer(false),
invariantAll(false), invariantAll(false),
nanMinMaxClamp(false), nanMinMaxClamp(false),
@ -307,7 +309,7 @@ public:
useVulkanMemoryModel(false), useVulkanMemoryModel(false),
invocations(TQualifier::layoutNotSet), vertices(TQualifier::layoutNotSet), invocations(TQualifier::layoutNotSet), vertices(TQualifier::layoutNotSet),
inputPrimitive(ElgNone), outputPrimitive(ElgNone), inputPrimitive(ElgNone), outputPrimitive(ElgNone),
pixelCenterInteger(false), originUpperLeft(false), pixelCenterInteger(false), originUpperLeft(false),texCoordBuiltinRedeclared(false),
vertexSpacing(EvsNone), vertexOrder(EvoNone), interlockOrdering(EioNone), pointMode(false), earlyFragmentTests(false), vertexSpacing(EvsNone), vertexOrder(EvoNone), interlockOrdering(EioNone), pointMode(false), earlyFragmentTests(false),
postDepthCoverage(false), depthLayout(EldNone), postDepthCoverage(false), depthLayout(EldNone),
hlslFunctionality1(false), hlslFunctionality1(false),
@ -397,6 +399,9 @@ public:
case EShTargetSpv_1_5: case EShTargetSpv_1_5:
processes.addProcess("target-env spirv1.5"); processes.addProcess("target-env spirv1.5");
break; break;
case EShTargetSpv_1_6:
processes.addProcess("target-env spirv1.6");
break;
default: default:
processes.addProcess("target-env spirvUnknown"); processes.addProcess("target-env spirvUnknown");
break; break;
@ -415,6 +420,9 @@ public:
case EShTargetVulkan_1_2: case EShTargetVulkan_1_2:
processes.addProcess("target-env vulkan1.2"); processes.addProcess("target-env vulkan1.2");
break; break;
case EShTargetVulkan_1_3:
processes.addProcess("target-env vulkan1.3");
break;
default: default:
processes.addProcess("target-env vulkanUnknown"); processes.addProcess("target-env vulkanUnknown");
break; break;
@ -460,6 +468,20 @@ public:
} }
bool getInvertY() const { return invertY; } bool getInvertY() const { return invertY; }
void setDxPositionW(bool dxPosW)
{
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 #ifdef ENABLE_HLSL
void setSource(EShSource s) { source = s; } void setSource(EShSource s) { source = s; }
EShSource getSource() const { return source; } EShSource getSource() const { return source; }
@ -812,6 +834,8 @@ public:
bool getOriginUpperLeft() const { return originUpperLeft; } bool getOriginUpperLeft() const { return originUpperLeft; }
void setPixelCenterInteger() { pixelCenterInteger = true; } void setPixelCenterInteger() { pixelCenterInteger = true; }
bool getPixelCenterInteger() const { return pixelCenterInteger; } bool getPixelCenterInteger() const { return pixelCenterInteger; }
void setTexCoordRedeclared() { texCoordBuiltinRedeclared = true; }
bool getTexCoordRedeclared() const { return texCoordBuiltinRedeclared; }
void addBlendEquation(TBlendEquationShift b) { blendEquations |= (1 << b); } void addBlendEquation(TBlendEquationShift b) { blendEquations |= (1 << b); }
unsigned int getBlendEquations() const { return blendEquations; } unsigned int getBlendEquations() const { return blendEquations; }
bool setXfbBufferStride(int buffer, unsigned stride) bool setXfbBufferStride(int buffer, unsigned stride)
@ -1016,8 +1040,8 @@ public:
protected: protected:
TIntermSymbol* addSymbol(long long Id, const TString&, const TType&, const TConstUnionArray&, TIntermTyped* subtree, const TSourceLoc&); TIntermSymbol* addSymbol(long long Id, const TString&, const TType&, const TConstUnionArray&, TIntermTyped* subtree, const TSourceLoc&);
void error(TInfoSink& infoSink, const char*); void error(TInfoSink& infoSink, const char*, EShLanguage unitStage = EShLangCount);
void warn(TInfoSink& infoSink, const char*); void warn(TInfoSink& infoSink, const char*, EShLanguage unitStage = EShLangCount);
void mergeCallGraphs(TInfoSink&, TIntermediate&); void mergeCallGraphs(TInfoSink&, TIntermediate&);
void mergeModes(TInfoSink&, TIntermediate&); void mergeModes(TInfoSink&, TIntermediate&);
void mergeTrees(TInfoSink&, TIntermediate&); void mergeTrees(TInfoSink&, TIntermediate&);
@ -1070,6 +1094,8 @@ protected:
int numPushConstants; int numPushConstants;
bool recursive; bool recursive;
bool invertY; bool invertY;
bool dxPositionW;
bool enhancedMsgs;
bool useStorageBuffer; bool useStorageBuffer;
bool invariantAll; bool invariantAll;
bool nanMinMaxClamp; // true if desiring min/max/clamp to favor non-NaN over NaN bool nanMinMaxClamp; // true if desiring min/max/clamp to favor non-NaN over NaN
@ -1098,6 +1124,7 @@ protected:
TLayoutGeometry outputPrimitive; TLayoutGeometry outputPrimitive;
bool pixelCenterInteger; bool pixelCenterInteger;
bool originUpperLeft; bool originUpperLeft;
bool texCoordBuiltinRedeclared;
TVertexSpacing vertexSpacing; TVertexSpacing vertexSpacing;
TVertexOrder vertexOrder; TVertexOrder vertexOrder;
TInterlockOrdering interlockOrdering; TInterlockOrdering interlockOrdering;
@ -1158,6 +1185,7 @@ protected:
// for callableData/callableDataIn // for callableData/callableDataIn
// set of names of statically read/written I/O that might need extra checking // set of names of statically read/written I/O that might need extra checking
std::set<TString> ioAccessed; std::set<TString> ioAccessed;
// source code of shader, useful as part of debug information // source code of shader, useful as part of debug information
std::string sourceFile; std::string sourceFile;
std::string sourceText; std::string sourceText;

View file

@ -56,4 +56,4 @@ if(ENABLE_GLSLANG_INSTALL)
install(TARGETS OSDependent EXPORT OSDependentTargets install(TARGETS OSDependent EXPORT OSDependentTargets
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
install(EXPORT OSDependentTargets DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake) install(EXPORT OSDependentTargets DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake)
endif(ENABLE_GLSLANG_INSTALL) endif()

View file

@ -172,7 +172,7 @@ namespace {
pthread_mutex_t gMutex; pthread_mutex_t gMutex;
} }
void InitGlobalLock() static void InitMutex(void)
{ {
pthread_mutexattr_t mutexattr; pthread_mutexattr_t mutexattr;
pthread_mutexattr_init(&mutexattr); pthread_mutexattr_init(&mutexattr);
@ -180,6 +180,12 @@ void InitGlobalLock()
pthread_mutex_init(&gMutex, &mutexattr); pthread_mutex_init(&gMutex, &mutexattr);
} }
void InitGlobalLock()
{
static pthread_once_t once = PTHREAD_ONCE_INIT;
pthread_once(&once, InitMutex);
}
void GetGlobalLock() void GetGlobalLock()
{ {
pthread_mutex_lock(&gMutex); pthread_mutex_lock(&gMutex);

View file

@ -55,7 +55,7 @@ if(ENABLE_GLSLANG_JS)
if(ENABLE_EMSCRIPTEN_SINGLE_FILE) if(ENABLE_EMSCRIPTEN_SINGLE_FILE)
target_link_libraries(glslang.js "-s SINGLE_FILE=1") target_link_libraries(glslang.js "-s SINGLE_FILE=1")
endif(ENABLE_EMSCRIPTEN_SINGLE_FILE) endif()
if(ENABLE_EMSCRIPTEN_ENVIRONMENT_NODE) if(ENABLE_EMSCRIPTEN_ENVIRONMENT_NODE)
target_link_libraries(glslang.js "-s ENVIRONMENT=node -s BINARYEN_ASYNC_COMPILATION=0") target_link_libraries(glslang.js "-s ENVIRONMENT=node -s BINARYEN_ASYNC_COMPILATION=0")
@ -67,5 +67,5 @@ if(ENABLE_GLSLANG_JS)
add_custom_command(TARGET glslang.js POST_BUILD add_custom_command(TARGET glslang.js POST_BUILD
COMMAND cat ${CMAKE_CURRENT_SOURCE_DIR}/glslang.after.js >> ${CMAKE_CURRENT_BINARY_DIR}/glslang.js) COMMAND cat ${CMAKE_CURRENT_SOURCE_DIR}/glslang.after.js >> ${CMAKE_CURRENT_BINARY_DIR}/glslang.js)
endif() endif()
endif(EMSCRIPTEN) endif()
endif(ENABLE_GLSLANG_JS) endif()

View file

@ -45,10 +45,10 @@ endif()
if(WIN32) if(WIN32)
source_group("Source" FILES ${SOURCES}) source_group("Source" FILES ${SOURCES})
endif(WIN32) endif()
if(ENABLE_GLSLANG_INSTALL) if(ENABLE_GLSLANG_INSTALL)
install(TARGETS OSDependent EXPORT OSDependentTargets install(TARGETS OSDependent EXPORT OSDependentTargets
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
install(EXPORT OSDependentTargets DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake) install(EXPORT OSDependentTargets DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake)
endif(ENABLE_GLSLANG_INSTALL) endif()

View file

@ -150,8 +150,8 @@ typedef enum {
typedef enum { typedef enum {
EShClientNone, // use when there is no client, e.g. for validation EShClientNone, // use when there is no client, e.g. for validation
EShClientVulkan, EShClientVulkan, // as GLSL dialect, specifies KHR_vulkan_glsl extension
EShClientOpenGL, EShClientOpenGL, // as GLSL dialect, specifies ARB_gl_spirv extension
LAST_ELEMENT_MARKER(EShClientCount), LAST_ELEMENT_MARKER(EShClientCount),
} EShClient; } EShClient;
@ -166,8 +166,9 @@ typedef enum {
EShTargetVulkan_1_0 = (1 << 22), // Vulkan 1.0 EShTargetVulkan_1_0 = (1 << 22), // Vulkan 1.0
EShTargetVulkan_1_1 = (1 << 22) | (1 << 12), // Vulkan 1.1 EShTargetVulkan_1_1 = (1 << 22) | (1 << 12), // Vulkan 1.1
EShTargetVulkan_1_2 = (1 << 22) | (2 << 12), // Vulkan 1.2 EShTargetVulkan_1_2 = (1 << 22) | (2 << 12), // Vulkan 1.2
EShTargetVulkan_1_3 = (1 << 22) | (3 << 12), // Vulkan 1.3
EShTargetOpenGL_450 = 450, // OpenGL EShTargetOpenGL_450 = 450, // OpenGL
LAST_ELEMENT_MARKER(EShTargetClientVersionCount = 4), LAST_ELEMENT_MARKER(EShTargetClientVersionCount = 5),
} EShTargetClientVersion; } EShTargetClientVersion;
typedef EShTargetClientVersion EshTargetClientVersion; typedef EShTargetClientVersion EshTargetClientVersion;
@ -179,7 +180,8 @@ typedef enum {
EShTargetSpv_1_3 = (1 << 16) | (3 << 8), // SPIR-V 1.3 EShTargetSpv_1_3 = (1 << 16) | (3 << 8), // SPIR-V 1.3
EShTargetSpv_1_4 = (1 << 16) | (4 << 8), // SPIR-V 1.4 EShTargetSpv_1_4 = (1 << 16) | (4 << 8), // SPIR-V 1.4
EShTargetSpv_1_5 = (1 << 16) | (5 << 8), // SPIR-V 1.5 EShTargetSpv_1_5 = (1 << 16) | (5 << 8), // SPIR-V 1.5
LAST_ELEMENT_MARKER(EShTargetLanguageVersionCount = 6), EShTargetSpv_1_6 = (1 << 16) | (6 << 8), // SPIR-V 1.6
LAST_ELEMENT_MARKER(EShTargetLanguageVersionCount = 7),
} EShTargetLanguageVersion; } EShTargetLanguageVersion;
struct TInputLanguage { struct TInputLanguage {
@ -262,6 +264,7 @@ enum EShMessages : unsigned {
EShMsgHlslLegalization = (1 << 12), // enable HLSL Legalization messages EShMsgHlslLegalization = (1 << 12), // enable HLSL Legalization messages
EShMsgHlslDX9Compatible = (1 << 13), // enable HLSL DX9 compatible mode (for samplers and semantics) EShMsgHlslDX9Compatible = (1 << 13), // enable HLSL DX9 compatible mode (for samplers and semantics)
EShMsgBuiltinSymbolTable = (1 << 14), // print the builtin symbol table EShMsgBuiltinSymbolTable = (1 << 14), // print the builtin symbol table
EShMsgEnhanced = (1 << 15), // enhanced message readability
LAST_ELEMENT_MARKER(EShMsgCount), LAST_ELEMENT_MARKER(EShMsgCount),
}; };
@ -468,6 +471,7 @@ public:
GLSLANG_EXPORT void setSourceEntryPoint(const char* sourceEntryPointName); GLSLANG_EXPORT void setSourceEntryPoint(const char* sourceEntryPointName);
GLSLANG_EXPORT void addProcesses(const std::vector<std::string>&); GLSLANG_EXPORT void addProcesses(const std::vector<std::string>&);
GLSLANG_EXPORT void setUniqueId(unsigned long long id); GLSLANG_EXPORT void setUniqueId(unsigned long long id);
GLSLANG_EXPORT void setOverrideVersion(int version);
// IO resolver binding data: see comments in ShaderLang.cpp // IO resolver binding data: see comments in ShaderLang.cpp
GLSLANG_EXPORT void setShiftBinding(TResourceType res, unsigned int base); GLSLANG_EXPORT void setShiftBinding(TResourceType res, unsigned int base);
@ -485,6 +489,8 @@ public:
GLSLANG_EXPORT void addUniformLocationOverride(const char* name, int loc); GLSLANG_EXPORT void addUniformLocationOverride(const char* name, int loc);
GLSLANG_EXPORT void setUniformLocationBase(int base); GLSLANG_EXPORT void setUniformLocationBase(int base);
GLSLANG_EXPORT void setInvertY(bool invert); GLSLANG_EXPORT void setInvertY(bool invert);
GLSLANG_EXPORT void setDxPositionW(bool dxPosW);
GLSLANG_EXPORT void setEnhancedMsgs();
#ifdef ENABLE_HLSL #ifdef ENABLE_HLSL
GLSLANG_EXPORT void setHlslIoMapping(bool hlslIoMap); GLSLANG_EXPORT void setHlslIoMapping(bool hlslIoMap);
GLSLANG_EXPORT void setFlattenUniformArrays(bool flatten); GLSLANG_EXPORT void setFlattenUniformArrays(bool flatten);
@ -512,6 +518,9 @@ public:
// use EShClientNone and version of 0, e.g. for validation mode. // use EShClientNone and version of 0, e.g. for validation mode.
// Note 'version' does not describe the target environment, // Note 'version' does not describe the target environment,
// just the version of the source dialect to compile under. // just the version of the source dialect to compile under.
// For example, to choose the Vulkan dialect of GLSL defined by
// version 100 of the KHR_vulkan_glsl extension: lang = EShSourceGlsl,
// dialect = EShClientVulkan, and version = 100.
// //
// See the definitions of TEnvironment, EShSource, EShLanguage, // See the definitions of TEnvironment, EShSource, EShLanguage,
// and EShClient for choices and more detail. // and EShClient for choices and more detail.
@ -703,6 +712,9 @@ protected:
// a function in the source string can be renamed FROM this TO the name given in setEntryPoint. // a function in the source string can be renamed FROM this TO the name given in setEntryPoint.
std::string sourceEntryPointName; std::string sourceEntryPointName;
// overrides #version in shader source or default version if #version isn't present
int overrideVersion;
TEnvironment environment; TEnvironment environment;
friend class TProgram; friend class TProgram;

View file

@ -29,7 +29,7 @@
#define GLSLextKHR_H #define GLSLextKHR_H
static const int GLSLextKHRVersion = 100; static const int GLSLextKHRVersion = 100;
static const int GLSLextKHRRevision = 2; static const int GLSLextKHRRevision = 3;
static const char* const E_SPV_KHR_shader_ballot = "SPV_KHR_shader_ballot"; static const char* const E_SPV_KHR_shader_ballot = "SPV_KHR_shader_ballot";
static const char* const E_SPV_KHR_subgroup_vote = "SPV_KHR_subgroup_vote"; static const char* const E_SPV_KHR_subgroup_vote = "SPV_KHR_subgroup_vote";
@ -52,5 +52,6 @@ static const char* const E_SPV_KHR_fragment_shading_rate = "SPV_KHR_fragm
static const char* const E_SPV_KHR_terminate_invocation = "SPV_KHR_terminate_invocation"; static const char* const E_SPV_KHR_terminate_invocation = "SPV_KHR_terminate_invocation";
static const char* const E_SPV_KHR_workgroup_memory_explicit_layout = "SPV_KHR_workgroup_memory_explicit_layout"; static const char* const E_SPV_KHR_workgroup_memory_explicit_layout = "SPV_KHR_workgroup_memory_explicit_layout";
static const char* const E_SPV_KHR_subgroup_uniform_control_flow = "SPV_KHR_subgroup_uniform_control_flow"; static const char* const E_SPV_KHR_subgroup_uniform_control_flow = "SPV_KHR_subgroup_uniform_control_flow";
static const char* const E_SPV_KHR_fragment_shader_barycentric = "SPV_KHR_fragment_shader_barycentric";
#endif // #ifndef GLSLextKHR_H #endif // #ifndef GLSLextKHR_H

View file

@ -260,6 +260,7 @@ protected:
std::unordered_map<std::string, spv::Id> extBuiltinMap; std::unordered_map<std::string, spv::Id> extBuiltinMap;
std::unordered_map<long long, spv::Id> symbolValues; std::unordered_map<long long, spv::Id> symbolValues;
std::unordered_map<uint32_t, spv::Id> builtInVariableIds;
std::unordered_set<long long> rValueParameters; // set of formal function parameters passed as rValues, std::unordered_set<long long> rValueParameters; // set of formal function parameters passed as rValues,
// rather than a pointer // rather than a pointer
std::unordered_map<std::string, spv::Function*> functionMap; std::unordered_map<std::string, spv::Function*> functionMap;
@ -1007,6 +1008,8 @@ spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltI
return spv::BuiltInRayTminKHR; return spv::BuiltInRayTminKHR;
case glslang::EbvRayTmax: case glslang::EbvRayTmax:
return spv::BuiltInRayTmaxKHR; return spv::BuiltInRayTmaxKHR;
case glslang::EbvCullMask:
return spv::BuiltInCullMaskKHR;
case glslang::EbvInstanceCustomIndex: case glslang::EbvInstanceCustomIndex:
return spv::BuiltInInstanceCustomIndexKHR; return spv::BuiltInInstanceCustomIndexKHR;
case glslang::EbvHitT: case glslang::EbvHitT:
@ -1048,6 +1051,15 @@ spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltI
builder.addCapability(spv::CapabilityFragmentBarycentricNV); builder.addCapability(spv::CapabilityFragmentBarycentricNV);
return spv::BuiltInBaryCoordNoPerspNV; return spv::BuiltInBaryCoordNoPerspNV;
case glslang::EbvBaryCoordEXT:
builder.addExtension(spv::E_SPV_KHR_fragment_shader_barycentric);
builder.addCapability(spv::CapabilityFragmentBarycentricKHR);
return spv::BuiltInBaryCoordKHR;
case glslang::EbvBaryCoordNoPerspEXT:
builder.addExtension(spv::E_SPV_KHR_fragment_shader_barycentric);
builder.addCapability(spv::CapabilityFragmentBarycentricKHR);
return spv::BuiltInBaryCoordNoPerspKHR;
// mesh shaders // mesh shaders
case glslang::EbvTaskCountNV: case glslang::EbvTaskCountNV:
return spv::BuiltInTaskCountNV; return spv::BuiltInTaskCountNV;
@ -1256,8 +1268,10 @@ spv::StorageClass TGlslangToSpvTraverser::TranslateStorageClass(const glslang::T
if (type.getBasicType() == glslang::EbtRayQuery) if (type.getBasicType() == glslang::EbtRayQuery)
return spv::StorageClassPrivate; return spv::StorageClassPrivate;
#ifndef GLSLANG_WEB #ifndef GLSLANG_WEB
if (type.getQualifier().isSpirvByReference()) if (type.getQualifier().isSpirvByReference()) {
return spv::StorageClassFunction; if (type.getQualifier().isParamInput() || type.getQualifier().isParamOutput())
return spv::StorageClassFunction;
}
#endif #endif
if (type.getQualifier().isPipeInput()) if (type.getQualifier().isPipeInput())
return spv::StorageClassInput; return spv::StorageClassInput;
@ -1662,9 +1676,22 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion,
case EShLangCompute: case EShLangCompute:
builder.addCapability(spv::CapabilityShader); builder.addCapability(spv::CapabilityShader);
builder.addExecutionMode(shaderEntry, spv::ExecutionModeLocalSize, glslangIntermediate->getLocalSize(0), if (glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_6) {
glslangIntermediate->getLocalSize(1), std::vector<spv::Id> dimConstId;
glslangIntermediate->getLocalSize(2)); for (int dim = 0; dim < 3; ++dim) {
bool specConst = (glslangIntermediate->getLocalSizeSpecId(dim) != glslang::TQualifier::layoutNotSet);
dimConstId.push_back(builder.makeUintConstant(glslangIntermediate->getLocalSize(dim), specConst));
if (specConst) {
builder.addDecoration(dimConstId.back(), spv::DecorationSpecId,
glslangIntermediate->getLocalSizeSpecId(dim));
}
}
builder.addExecutionModeId(shaderEntry, spv::ExecutionModeLocalSizeId, dimConstId);
} else {
builder.addExecutionMode(shaderEntry, spv::ExecutionModeLocalSize, glslangIntermediate->getLocalSize(0),
glslangIntermediate->getLocalSize(1),
glslangIntermediate->getLocalSize(2));
}
if (glslangIntermediate->getLayoutDerivativeModeNone() == glslang::LayoutDerivativeGroupQuads) { if (glslangIntermediate->getLayoutDerivativeModeNone() == glslang::LayoutDerivativeGroupQuads) {
builder.addCapability(spv::CapabilityComputeDerivativeGroupQuadsNV); builder.addCapability(spv::CapabilityComputeDerivativeGroupQuadsNV);
builder.addExecutionMode(shaderEntry, spv::ExecutionModeDerivativeGroupQuadsNV); builder.addExecutionMode(shaderEntry, spv::ExecutionModeDerivativeGroupQuadsNV);
@ -1762,15 +1789,35 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion,
builder.addCapability(spv::CapabilityRayTracingNV); builder.addCapability(spv::CapabilityRayTracingNV);
builder.addExtension("SPV_NV_ray_tracing"); builder.addExtension("SPV_NV_ray_tracing");
} }
if (glslangIntermediate->getStage() != EShLangRayGen && glslangIntermediate->getStage() != EShLangCallable)
{
if (extensions.find("GL_EXT_ray_cull_mask") != extensions.end()) {
builder.addCapability(spv::CapabilityRayCullMaskKHR);
builder.addExtension("SPV_KHR_ray_cull_mask");
}
}
break; break;
} }
case EShLangTaskNV: case EShLangTaskNV:
case EShLangMeshNV: case EShLangMeshNV:
builder.addCapability(spv::CapabilityMeshShadingNV); builder.addCapability(spv::CapabilityMeshShadingNV);
builder.addExtension(spv::E_SPV_NV_mesh_shader); builder.addExtension(spv::E_SPV_NV_mesh_shader);
builder.addExecutionMode(shaderEntry, spv::ExecutionModeLocalSize, glslangIntermediate->getLocalSize(0), if (glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_6) {
glslangIntermediate->getLocalSize(1), std::vector<spv::Id> dimConstId;
glslangIntermediate->getLocalSize(2)); for (int dim = 0; dim < 3; ++dim) {
bool specConst = (glslangIntermediate->getLocalSizeSpecId(dim) != glslang::TQualifier::layoutNotSet);
dimConstId.push_back(builder.makeUintConstant(glslangIntermediate->getLocalSize(dim), specConst));
if (specConst) {
builder.addDecoration(dimConstId.back(), spv::DecorationSpecId,
glslangIntermediate->getLocalSizeSpecId(dim));
}
}
builder.addExecutionModeId(shaderEntry, spv::ExecutionModeLocalSizeId, dimConstId);
} else {
builder.addExecutionMode(shaderEntry, spv::ExecutionModeLocalSize, glslangIntermediate->getLocalSize(0),
glslangIntermediate->getLocalSize(1),
glslangIntermediate->getLocalSize(2));
}
if (glslangIntermediate->getStage() == EShLangMeshNV) { if (glslangIntermediate->getStage() == EShLangMeshNV) {
builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputVertices, builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputVertices,
glslangIntermediate->getVertices()); glslangIntermediate->getVertices());
@ -1830,10 +1877,10 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion,
std::vector<spv::Id> operandIds; std::vector<spv::Id> operandIds;
assert(!modeId.second.empty()); assert(!modeId.second.empty());
for (auto extraOperand : modeId.second) { for (auto extraOperand : modeId.second) {
int nextConst = 0; if (extraOperand->getType().getQualifier().isSpecConstant())
spv::Id operandId = createSpvConstantFromConstUnionArray( operandIds.push_back(getSymbolId(extraOperand->getAsSymbolNode()));
extraOperand->getType(), extraOperand->getConstArray(), nextConst, false); else
operandIds.push_back(operandId); operandIds.push_back(createSpvConstant(*extraOperand));
} }
builder.addExecutionModeId(shaderEntry, static_cast<spv::ExecutionMode>(modeId.first), operandIds); builder.addExecutionModeId(shaderEntry, static_cast<spv::ExecutionMode>(modeId.first), operandIds);
} }
@ -2746,6 +2793,10 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
} else { } else {
handleFunctionEntry(node); handleFunctionEntry(node);
} }
if (options.generateDebugInfo) {
const auto& loc = node->getLoc();
currentFunction->setDebugLineInfo(builder.getSourceFile(), loc.line, loc.column);
}
} else { } else {
if (inEntryPoint) if (inEntryPoint)
entryPointTerminated = true; entryPointTerminated = true;
@ -3384,7 +3435,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
const auto& spirvInst = node->getSpirvInstruction(); const auto& spirvInst = node->getSpirvInstruction();
if (spirvInst.set == "") { if (spirvInst.set == "") {
std::vector<spv::IdImmediate> idImmOps; std::vector<spv::IdImmediate> idImmOps;
for (int i = 0; i < glslangOperands.size(); ++i) { for (unsigned int i = 0; i < glslangOperands.size(); ++i) {
if (glslangOperands[i]->getAsTyped()->getQualifier().isSpirvLiteral()) { if (glslangOperands[i]->getAsTyped()->getQualifier().isSpirvLiteral()) {
// Translate the constant to a literal value // Translate the constant to a literal value
std::vector<unsigned> literals; std::vector<unsigned> literals;
@ -3777,7 +3828,16 @@ bool TGlslangToSpvTraverser::visitBranch(glslang::TVisit /* visit */, glslang::T
switch (node->getFlowOp()) { switch (node->getFlowOp()) {
case glslang::EOpKill: case glslang::EOpKill:
builder.makeStatementTerminator(spv::OpKill, "post-discard"); if (glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_6) {
if (glslangIntermediate->getSource() == glslang::EShSourceHlsl) {
builder.addCapability(spv::CapabilityDemoteToHelperInvocation);
builder.createNoResultOp(spv::OpDemoteToHelperInvocationEXT);
} else {
builder.makeStatementTerminator(spv::OpTerminateInvocation, "post-terminate-invocation");
}
} else {
builder.makeStatementTerminator(spv::OpKill, "post-discard");
}
break; break;
case glslang::EOpTerminateInvocation: case glslang::EOpTerminateInvocation:
builder.addExtension(spv::E_SPV_KHR_terminate_invocation); builder.addExtension(spv::E_SPV_KHR_terminate_invocation);
@ -3940,12 +4000,14 @@ spv::Id TGlslangToSpvTraverser::getSampledType(const glslang::TSampler& sampler)
builder.addExtension(spv::E_SPV_AMD_gpu_shader_half_float_fetch); builder.addExtension(spv::E_SPV_AMD_gpu_shader_half_float_fetch);
builder.addCapability(spv::CapabilityFloat16ImageAMD); builder.addCapability(spv::CapabilityFloat16ImageAMD);
return builder.makeFloatType(16); return builder.makeFloatType(16);
case glslang::EbtInt64: return builder.makeIntType(64); case glslang::EbtInt64:
builder.addExtension(spv::E_SPV_EXT_shader_image_int64); builder.addExtension(spv::E_SPV_EXT_shader_image_int64);
builder.addCapability(spv::CapabilityFloat16ImageAMD); builder.addCapability(spv::CapabilityInt64ImageEXT);
case glslang::EbtUint64: return builder.makeUintType(64); return builder.makeIntType(64);
case glslang::EbtUint64:
builder.addExtension(spv::E_SPV_EXT_shader_image_int64); builder.addExtension(spv::E_SPV_EXT_shader_image_int64);
builder.addCapability(spv::CapabilityFloat16ImageAMD); builder.addCapability(spv::CapabilityInt64ImageEXT);
return builder.makeUintType(64);
#endif #endif
default: default:
assert(0); assert(0);
@ -4146,68 +4208,55 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
const auto& spirvType = type.getSpirvType(); const auto& spirvType = type.getSpirvType();
const auto& spirvInst = spirvType.spirvInst; const auto& spirvInst = spirvType.spirvInst;
std::vector<spv::Id> operands; std::vector<spv::IdImmediate> operands;
for (const auto& typeParam : spirvType.typeParams) { for (const auto& typeParam : spirvType.typeParams) {
if (typeParam.isConstant) { // Constant expression
// Constant expression if (typeParam.constant->isLiteral()) {
if (typeParam.constant->isLiteral()) { if (typeParam.constant->getBasicType() == glslang::EbtFloat) {
if (typeParam.constant->getBasicType() == glslang::EbtFloat) { float floatValue = static_cast<float>(typeParam.constant->getConstArray()[0].getDConst());
float floatValue = static_cast<float>(typeParam.constant->getConstArray()[0].getDConst()); unsigned literal = *reinterpret_cast<unsigned*>(&floatValue);
unsigned literal = *reinterpret_cast<unsigned*>(&floatValue); operands.push_back({false, literal});
operands.push_back(literal); } else if (typeParam.constant->getBasicType() == glslang::EbtInt) {
} else if (typeParam.constant->getBasicType() == glslang::EbtInt) { unsigned literal = typeParam.constant->getConstArray()[0].getIConst();
unsigned literal = typeParam.constant->getConstArray()[0].getIConst(); operands.push_back({false, literal});
operands.push_back(literal); } else if (typeParam.constant->getBasicType() == glslang::EbtUint) {
} else if (typeParam.constant->getBasicType() == glslang::EbtUint) { unsigned literal = typeParam.constant->getConstArray()[0].getUConst();
unsigned literal = typeParam.constant->getConstArray()[0].getUConst(); operands.push_back({false, literal});
operands.push_back(literal); } else if (typeParam.constant->getBasicType() == glslang::EbtBool) {
} else if (typeParam.constant->getBasicType() == glslang::EbtBool) { unsigned literal = typeParam.constant->getConstArray()[0].getBConst();
unsigned literal = typeParam.constant->getConstArray()[0].getBConst(); operands.push_back({false, literal});
operands.push_back(literal); } else if (typeParam.constant->getBasicType() == glslang::EbtString) {
} else if (typeParam.constant->getBasicType() == glslang::EbtString) { auto str = typeParam.constant->getConstArray()[0].getSConst()->c_str();
auto str = typeParam.constant->getConstArray()[0].getSConst()->c_str(); unsigned literal = 0;
unsigned literal = 0; char* literalPtr = reinterpret_cast<char*>(&literal);
char* literalPtr = reinterpret_cast<char*>(&literal); unsigned charCount = 0;
unsigned charCount = 0; char ch = 0;
char ch = 0; do {
do { ch = *(str++);
ch = *(str++); *(literalPtr++) = ch;
*(literalPtr++) = ch; ++charCount;
++charCount; if (charCount == 4) {
if (charCount == 4) { operands.push_back({false, literal});
operands.push_back(literal); literalPtr = reinterpret_cast<char*>(&literal);
literalPtr = reinterpret_cast<char*>(&literal); charCount = 0;
charCount = 0;
}
} while (ch != 0);
// Partial literal is padded with 0
if (charCount > 0) {
for (; charCount < 4; ++charCount)
*(literalPtr++) = 0;
operands.push_back(literal);
} }
} else } while (ch != 0);
assert(0); // Unexpected type
} else { // Partial literal is padded with 0
int nextConst = 0; if (charCount > 0) {
spv::Id constant = createSpvConstantFromConstUnionArray( for (; charCount < 4; ++charCount)
typeParam.constant->getType(), typeParam.constant->getConstArray(), nextConst, false); *(literalPtr++) = 0;
operands.push_back(constant); operands.push_back({false, literal});
} }
} else { } else
// Type specifier assert(0); // Unexpected type
spv::Id typeId = convertGlslangToSpvType(*typeParam.type); } else
operands.push_back(typeId); operands.push_back({true, createSpvConstant(*typeParam.constant)});
}
} }
if (spirvInst.set == "") assert(spirvInst.set == ""); // Currently, couldn't be extended instructions.
spvType = builder.createOp(static_cast<spv::Op>(spirvInst.id), spv::NoType, operands); spvType = builder.makeGenericType(static_cast<spv::Op>(spirvInst.id), operands);
else {
spvType = builder.createBuiltinCall(
spv::NoType, getExtBuiltins(spirvInst.set.c_str()), spirvInst.id, operands);
}
break; break;
} }
#endif #endif
@ -7506,6 +7555,8 @@ spv::Id TGlslangToSpvTraverser::createInvocationsOperation(glslang::TOperator op
break; break;
case glslang::EOpReadFirstInvocation: case glslang::EOpReadFirstInvocation:
opCode = spv::OpSubgroupFirstInvocationKHR; opCode = spv::OpSubgroupFirstInvocationKHR;
if (builder.isVectorType(typeId))
return CreateInvocationsVectorOperation(opCode, groupOperation, typeId, operands);
break; break;
case glslang::EOpBallot: case glslang::EOpBallot:
{ {
@ -7630,7 +7681,7 @@ spv::Id TGlslangToSpvTraverser::CreateInvocationsVectorOperation(spv::Op op, spv
assert(op == spv::OpGroupFMin || op == spv::OpGroupUMin || op == spv::OpGroupSMin || assert(op == spv::OpGroupFMin || op == spv::OpGroupUMin || op == spv::OpGroupSMin ||
op == spv::OpGroupFMax || op == spv::OpGroupUMax || op == spv::OpGroupSMax || op == spv::OpGroupFMax || op == spv::OpGroupUMax || op == spv::OpGroupSMax ||
op == spv::OpGroupFAdd || op == spv::OpGroupIAdd || op == spv::OpGroupBroadcast || op == spv::OpGroupFAdd || op == spv::OpGroupIAdd || op == spv::OpGroupBroadcast ||
op == spv::OpSubgroupReadInvocationKHR || op == spv::OpSubgroupReadInvocationKHR || op == spv::OpSubgroupFirstInvocationKHR ||
op == spv::OpGroupFMinNonUniformAMD || op == spv::OpGroupUMinNonUniformAMD || op == spv::OpGroupFMinNonUniformAMD || op == spv::OpGroupUMinNonUniformAMD ||
op == spv::OpGroupSMinNonUniformAMD || op == spv::OpGroupSMinNonUniformAMD ||
op == spv::OpGroupFMaxNonUniformAMD || op == spv::OpGroupUMaxNonUniformAMD || op == spv::OpGroupFMaxNonUniformAMD || op == spv::OpGroupUMaxNonUniformAMD ||
@ -7659,6 +7710,8 @@ spv::Id TGlslangToSpvTraverser::CreateInvocationsVectorOperation(spv::Op op, spv
spvGroupOperands.push_back(scalar); spvGroupOperands.push_back(scalar);
spv::IdImmediate operand = { true, operands[1] }; spv::IdImmediate operand = { true, operands[1] };
spvGroupOperands.push_back(operand); spvGroupOperands.push_back(operand);
} else if (op == spv::OpSubgroupFirstInvocationKHR) {
spvGroupOperands.push_back(scalar);
} else if (op == spv::OpGroupBroadcast) { } else if (op == spv::OpGroupBroadcast) {
spv::IdImmediate scope = { true, builder.makeUintConstant(spv::ScopeSubgroup) }; spv::IdImmediate scope = { true, builder.makeUintConstant(spv::ScopeSubgroup) };
spvGroupOperands.push_back(scope); spvGroupOperands.push_back(scope);
@ -8698,7 +8751,32 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol
// it was not found, create it // it was not found, create it
spv::BuiltIn builtIn = TranslateBuiltInDecoration(symbol->getQualifier().builtIn, false); spv::BuiltIn builtIn = TranslateBuiltInDecoration(symbol->getQualifier().builtIn, false);
auto forcedType = getForcedType(symbol->getQualifier().builtIn, symbol->getType()); auto forcedType = getForcedType(symbol->getQualifier().builtIn, symbol->getType());
// There are pairs of symbols that map to the same SPIR-V built-in:
// gl_ObjectToWorldEXT and gl_ObjectToWorld3x4EXT, and gl_WorldToObjectEXT
// and gl_WorldToObject3x4EXT. SPIR-V forbids having two OpVariables
// with the same BuiltIn in the same storage class, so we must re-use one.
const bool mayNeedToReuseBuiltIn =
builtIn == spv::BuiltInObjectToWorldKHR ||
builtIn == spv::BuiltInWorldToObjectKHR;
if (mayNeedToReuseBuiltIn) {
auto iter = builtInVariableIds.find(uint32_t(builtIn));
if (builtInVariableIds.end() != iter) {
id = iter->second;
symbolValues[symbol->getId()] = id;
if (forcedType.second != spv::NoType)
forceType[id] = forcedType.second;
return id;
}
}
id = createSpvVariable(symbol, forcedType.first); id = createSpvVariable(symbol, forcedType.first);
if (mayNeedToReuseBuiltIn) {
builtInVariableIds.insert({uint32_t(builtIn), id});
}
symbolValues[symbol->getId()] = id; symbolValues[symbol->getId()] = id;
if (forcedType.second != spv::NoType) if (forcedType.second != spv::NoType)
forceType[id] = forcedType.second; forceType[id] = forcedType.second;
@ -8721,8 +8799,18 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol
builder.addDecoration(id, spv::DecorationOffset, symbol->getQualifier().layoutOffset); builder.addDecoration(id, spv::DecorationOffset, symbol->getQualifier().layoutOffset);
} }
if (symbol->getQualifier().hasLocation()) if (symbol->getQualifier().hasLocation()) {
builder.addDecoration(id, spv::DecorationLocation, symbol->getQualifier().layoutLocation); if (!(glslangIntermediate->isRayTracingStage() && glslangIntermediate->IsRequestedExtension(glslang::E_GL_EXT_ray_tracing)
&& (builder.getStorageClass(id) == spv::StorageClassRayPayloadKHR ||
builder.getStorageClass(id) == spv::StorageClassIncomingRayPayloadKHR ||
builder.getStorageClass(id) == spv::StorageClassCallableDataKHR ||
builder.getStorageClass(id) == spv::StorageClassIncomingCallableDataKHR))) {
// Location values are used to link TraceRayKHR and ExecuteCallableKHR to corresponding variables
// but are not valid in SPIRV since they are supported only for Input/Output Storage classes.
builder.addDecoration(id, spv::DecorationLocation, symbol->getQualifier().layoutLocation);
}
}
builder.addDecoration(id, TranslateInvariantDecoration(symbol->getType().getQualifier())); builder.addDecoration(id, TranslateInvariantDecoration(symbol->getType().getQualifier()));
if (symbol->getQualifier().hasStream() && glslangIntermediate->isMultiStream()) { if (symbol->getQualifier().hasStream() && glslangIntermediate->isMultiStream()) {
builder.addCapability(spv::CapabilityGeometryStreams); builder.addCapability(spv::CapabilityGeometryStreams);
@ -8756,7 +8844,16 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol
// add built-in variable decoration // add built-in variable decoration
if (builtIn != spv::BuiltInMax) { if (builtIn != spv::BuiltInMax) {
builder.addDecoration(id, spv::DecorationBuiltIn, (int)builtIn); // WorkgroupSize deprecated in spirv1.6
if (glslangIntermediate->getSpv().spv < glslang::EShTargetSpv_1_6 ||
builtIn != spv::BuiltInWorkgroupSize)
builder.addDecoration(id, spv::DecorationBuiltIn, (int)builtIn);
}
// Add volatile decoration to HelperInvocation for spirv1.6 and beyond
if (builtIn == spv::BuiltInHelperInvocation &&
glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_6) {
builder.addDecoration(id, spv::DecorationVolatile);
} }
#ifndef GLSLANG_WEB #ifndef GLSLANG_WEB
@ -8808,6 +8905,12 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol
builder.addExtension(spv::E_SPV_NV_fragment_shader_barycentric); builder.addExtension(spv::E_SPV_NV_fragment_shader_barycentric);
} }
if (symbol->getQualifier().pervertexEXT) {
builder.addDecoration(id, spv::DecorationPerVertexKHR);
builder.addCapability(spv::CapabilityFragmentBarycentricKHR);
builder.addExtension(spv::E_SPV_KHR_fragment_shader_barycentric);
}
if (glslangIntermediate->getHlslFunctionality1() && symbol->getType().getQualifier().semanticName != nullptr) { if (glslangIntermediate->getHlslFunctionality1() && symbol->getType().getQualifier().semanticName != nullptr) {
builder.addExtension("SPV_GOOGLE_hlsl_functionality1"); builder.addExtension("SPV_GOOGLE_hlsl_functionality1");
builder.addDecoration(id, (spv::Decoration)spv::DecorationHlslSemanticGOOGLE, builder.addDecoration(id, (spv::Decoration)spv::DecorationHlslSemanticGOOGLE,
@ -8841,12 +8944,12 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol
std::vector<spv::Id> operandIds; std::vector<spv::Id> operandIds;
assert(!decorateId.second.empty()); assert(!decorateId.second.empty());
for (auto extraOperand : decorateId.second) { for (auto extraOperand : decorateId.second) {
int nextConst = 0; if (extraOperand->getQualifier().isSpecConstant())
spv::Id operandId = createSpvConstantFromConstUnionArray( operandIds.push_back(getSymbolId(extraOperand->getAsSymbolNode()));
extraOperand->getType(), extraOperand->getConstArray(), nextConst, false); else
operandIds.push_back(operandId); operandIds.push_back(createSpvConstant(*extraOperand));
} }
builder.addDecoration(id, static_cast<spv::Decoration>(decorateId.first), operandIds); builder.addDecorationId(id, static_cast<spv::Decoration>(decorateId.first), operandIds);
} }
// Add spirv_decorate_string // Add spirv_decorate_string
@ -9029,15 +9132,19 @@ spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstUnionArray(const glsla
break; break;
#ifndef GLSLANG_WEB #ifndef GLSLANG_WEB
case glslang::EbtInt8: case glslang::EbtInt8:
builder.addCapability(spv::CapabilityInt8);
spvConsts.push_back(builder.makeInt8Constant(zero ? 0 : consts[nextConst].getI8Const())); spvConsts.push_back(builder.makeInt8Constant(zero ? 0 : consts[nextConst].getI8Const()));
break; break;
case glslang::EbtUint8: case glslang::EbtUint8:
builder.addCapability(spv::CapabilityInt8);
spvConsts.push_back(builder.makeUint8Constant(zero ? 0 : consts[nextConst].getU8Const())); spvConsts.push_back(builder.makeUint8Constant(zero ? 0 : consts[nextConst].getU8Const()));
break; break;
case glslang::EbtInt16: case glslang::EbtInt16:
builder.addCapability(spv::CapabilityInt16);
spvConsts.push_back(builder.makeInt16Constant(zero ? 0 : consts[nextConst].getI16Const())); spvConsts.push_back(builder.makeInt16Constant(zero ? 0 : consts[nextConst].getI16Const()));
break; break;
case glslang::EbtUint16: case glslang::EbtUint16:
builder.addCapability(spv::CapabilityInt16);
spvConsts.push_back(builder.makeUint16Constant(zero ? 0 : consts[nextConst].getU16Const())); spvConsts.push_back(builder.makeUint16Constant(zero ? 0 : consts[nextConst].getU16Const()));
break; break;
case glslang::EbtInt64: case glslang::EbtInt64:
@ -9050,6 +9157,7 @@ spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstUnionArray(const glsla
spvConsts.push_back(builder.makeDoubleConstant(zero ? 0.0 : consts[nextConst].getDConst())); spvConsts.push_back(builder.makeDoubleConstant(zero ? 0.0 : consts[nextConst].getDConst()));
break; break;
case glslang::EbtFloat16: case glslang::EbtFloat16:
builder.addCapability(spv::CapabilityFloat16);
spvConsts.push_back(builder.makeFloat16Constant(zero ? 0.0F : (float)consts[nextConst].getDConst())); spvConsts.push_back(builder.makeFloat16Constant(zero ? 0.0F : (float)consts[nextConst].getDConst()));
break; break;
#endif #endif
@ -9078,15 +9186,19 @@ spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstUnionArray(const glsla
break; break;
#ifndef GLSLANG_WEB #ifndef GLSLANG_WEB
case glslang::EbtInt8: case glslang::EbtInt8:
builder.addCapability(spv::CapabilityInt8);
scalar = builder.makeInt8Constant(zero ? 0 : consts[nextConst].getI8Const(), specConstant); scalar = builder.makeInt8Constant(zero ? 0 : consts[nextConst].getI8Const(), specConstant);
break; break;
case glslang::EbtUint8: case glslang::EbtUint8:
builder.addCapability(spv::CapabilityInt8);
scalar = builder.makeUint8Constant(zero ? 0 : consts[nextConst].getU8Const(), specConstant); scalar = builder.makeUint8Constant(zero ? 0 : consts[nextConst].getU8Const(), specConstant);
break; break;
case glslang::EbtInt16: case glslang::EbtInt16:
builder.addCapability(spv::CapabilityInt16);
scalar = builder.makeInt16Constant(zero ? 0 : consts[nextConst].getI16Const(), specConstant); scalar = builder.makeInt16Constant(zero ? 0 : consts[nextConst].getI16Const(), specConstant);
break; break;
case glslang::EbtUint16: case glslang::EbtUint16:
builder.addCapability(spv::CapabilityInt16);
scalar = builder.makeUint16Constant(zero ? 0 : consts[nextConst].getU16Const(), specConstant); scalar = builder.makeUint16Constant(zero ? 0 : consts[nextConst].getU16Const(), specConstant);
break; break;
case glslang::EbtInt64: case glslang::EbtInt64:
@ -9099,6 +9211,7 @@ spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstUnionArray(const glsla
scalar = builder.makeDoubleConstant(zero ? 0.0 : consts[nextConst].getDConst(), specConstant); scalar = builder.makeDoubleConstant(zero ? 0.0 : consts[nextConst].getDConst(), specConstant);
break; break;
case glslang::EbtFloat16: case glslang::EbtFloat16:
builder.addCapability(spv::CapabilityFloat16);
scalar = builder.makeFloat16Constant(zero ? 0.0F : (float)consts[nextConst].getDConst(), specConstant); scalar = builder.makeFloat16Constant(zero ? 0.0F : (float)consts[nextConst].getDConst(), specConstant);
break; break;
case glslang::EbtReference: case glslang::EbtReference:

View file

@ -40,7 +40,7 @@
#endif #endif
#include "SpvTools.h" #include "SpvTools.h"
#include "../glslang/Include/intermediate.h" #include "glslang/Include/intermediate.h"
#include <string> #include <string>
#include <vector> #include <vector>

View file

@ -160,15 +160,29 @@ namespace spv {
} }
// Is this an opcode we should remove when using --strip? // Is this an opcode we should remove when using --strip?
bool spirvbin_t::isStripOp(spv::Op opCode) const bool spirvbin_t::isStripOp(spv::Op opCode, unsigned start) const
{ {
switch (opCode) { switch (opCode) {
case spv::OpSource: case spv::OpSource:
case spv::OpSourceExtension: case spv::OpSourceExtension:
case spv::OpName: case spv::OpName:
case spv::OpMemberName: case spv::OpMemberName:
case spv::OpLine: return true; case spv::OpLine :
default: return false; {
const std::string name = literalString(start + 2);
std::vector<std::string>::const_iterator it;
for (it = stripWhiteList.begin(); it < stripWhiteList.end(); it++)
{
if (name.find(*it) != std::string::npos) {
return false;
}
}
return true;
}
default :
return false;
} }
} }
@ -297,15 +311,21 @@ namespace spv {
std::string spirvbin_t::literalString(unsigned word) const std::string spirvbin_t::literalString(unsigned word) const
{ {
std::string literal; std::string literal;
const spirword_t * pos = spv.data() + word;
literal.reserve(16); literal.reserve(16);
const char* bytes = reinterpret_cast<const char*>(spv.data() + word); do {
spirword_t word = *pos;
while (bytes && *bytes) for (int i = 0; i < 4; i++) {
literal += *bytes++; char c = word & 0xff;
if (c == '\0')
return literal; return literal;
literal += c;
word >>= 8;
}
pos++;
} while (true);
} }
void spirvbin_t::applyMap() void spirvbin_t::applyMap()
@ -366,7 +386,7 @@ namespace spv {
process( process(
[&](spv::Op opCode, unsigned start) { [&](spv::Op opCode, unsigned start) {
// remember opcodes we want to strip later // remember opcodes we want to strip later
if (isStripOp(opCode)) if (isStripOp(opCode, start))
stripInst(start); stripInst(start);
return true; return true;
}, },
@ -1488,13 +1508,24 @@ namespace spv {
} }
// remap from a memory image // remap from a memory image
void spirvbin_t::remap(std::vector<std::uint32_t>& in_spv, std::uint32_t opts) void spirvbin_t::remap(std::vector<std::uint32_t>& in_spv, const std::vector<std::string>& whiteListStrings,
std::uint32_t opts)
{ {
stripWhiteList = whiteListStrings;
spv.swap(in_spv); spv.swap(in_spv);
remap(opts); remap(opts);
spv.swap(in_spv); spv.swap(in_spv);
} }
// remap from a memory image - legacy interface without white list
void spirvbin_t::remap(std::vector<std::uint32_t>& in_spv, std::uint32_t opts)
{
stripWhiteList.clear();
spv.swap(in_spv);
remap(opts);
spv.swap(in_spv);
}
} // namespace SPV } // namespace SPV
#endif // defined (use_cpp11) #endif // defined (use_cpp11)

View file

@ -118,6 +118,10 @@ public:
virtual ~spirvbin_t() { } virtual ~spirvbin_t() { }
// remap on an existing binary in memory // remap on an existing binary in memory
void remap(std::vector<std::uint32_t>& spv, const std::vector<std::string>& whiteListStrings,
std::uint32_t opts = DO_EVERYTHING);
// remap on an existing binary in memory - legacy interface without white list
void remap(std::vector<std::uint32_t>& spv, std::uint32_t opts = DO_EVERYTHING); void remap(std::vector<std::uint32_t>& spv, std::uint32_t opts = DO_EVERYTHING);
// Type for error/log handler functions // Type for error/log handler functions
@ -180,6 +184,8 @@ private:
unsigned typeSizeInWords(spv::Id id) const; unsigned typeSizeInWords(spv::Id id) const;
unsigned idTypeSizeInWords(spv::Id id) const; unsigned idTypeSizeInWords(spv::Id id) const;
bool isStripOp(spv::Op opCode, unsigned start) const;
spv::Id& asId(unsigned word) { return spv[word]; } spv::Id& asId(unsigned word) { return spv[word]; }
const spv::Id& asId(unsigned word) const { return spv[word]; } const spv::Id& asId(unsigned word) const { return spv[word]; }
spv::Op asOpCode(unsigned word) const { return opOpCode(spv[word]); } spv::Op asOpCode(unsigned word) const { return opOpCode(spv[word]); }
@ -249,6 +255,8 @@ private:
std::vector<spirword_t> spv; // SPIR words std::vector<spirword_t> spv; // SPIR words
std::vector<std::string> stripWhiteList;
namemap_t nameMap; // ID names from OpName namemap_t nameMap; // ID names from OpName
// Since we want to also do binary ops, we can't use std::vector<bool>. we could use // Since we want to also do binary ops, we can't use std::vector<bool>. we could use

View file

@ -427,6 +427,37 @@ Id Builder::makeCooperativeMatrixType(Id component, Id scope, Id rows, Id cols)
return type->getResultId(); return type->getResultId();
} }
Id Builder::makeGenericType(spv::Op opcode, std::vector<spv::IdImmediate>& operands)
{
// try to find it
Instruction* type;
for (int t = 0; t < (int)groupedTypes[opcode].size(); ++t) {
type = groupedTypes[opcode][t];
if (static_cast<size_t>(type->getNumOperands()) != operands.size())
continue; // Number mismatch, find next
bool match = true;
for (int op = 0; match && op < (int)operands.size(); ++op) {
match = (operands[op].isId ? type->getIdOperand(op) : type->getImmediateOperand(op)) == operands[op].word;
}
if (match)
return type->getResultId();
}
// not found, make it
type = new Instruction(getUniqueId(), NoType, opcode);
for (size_t op = 0; op < operands.size(); ++op) {
if (operands[op].isId)
type->addIdOperand(operands[op].word);
else
type->addImmediateOperand(operands[op].word);
}
groupedTypes[opcode].push_back(type);
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
module.mapInstruction(type);
return type->getResultId();
}
// TODO: performance: track arrays per stride // TODO: performance: track arrays per stride
// If a stride is supplied (non-zero) make an array. // If a stride is supplied (non-zero) make an array.

View file

@ -99,6 +99,10 @@ public:
stringIds[file_c_str] = strId; stringIds[file_c_str] = strId;
return strId; return strId;
} }
spv::Id getSourceFile() const
{
return sourceFileStringId;
}
void setSourceFile(const std::string& file) void setSourceFile(const std::string& file)
{ {
sourceFileStringId = getStringId(file); sourceFileStringId = getStringId(file);
@ -181,6 +185,7 @@ public:
Id makeSamplerType(); Id makeSamplerType();
Id makeSampledImageType(Id imageType); Id makeSampledImageType(Id imageType);
Id makeCooperativeMatrixType(Id component, Id scope, Id rows, Id cols); Id makeCooperativeMatrixType(Id component, Id scope, Id rows, Id cols);
Id makeGenericType(spv::Op opcode, std::vector<spv::IdImmediate>& operands);
// accelerationStructureNV type // accelerationStructureNV type
Id makeAccelerationStructureType(); Id makeAccelerationStructureType();

View file

@ -44,10 +44,8 @@
#include <algorithm> #include <algorithm>
#include "SpvBuilder.h" #include "SpvBuilder.h"
#include "spirv.hpp" #include "spirv.hpp"
#include "GlslangToSpv.h"
#include "SpvBuilder.h"
namespace spv { namespace spv {
#include "GLSL.std.450.h" #include "GLSL.std.450.h"
#include "GLSL.ext.KHR.h" #include "GLSL.ext.KHR.h"
@ -113,8 +111,6 @@ void Builder::postProcessType(const Instruction& inst, Id typeId)
} }
} }
break; break;
case OpAccessChain:
case OpPtrAccessChain:
case OpCopyObject: case OpCopyObject:
break; break;
case OpFConvert: case OpFConvert:
@ -161,26 +157,43 @@ void Builder::postProcessType(const Instruction& inst, Id typeId)
switch (inst.getImmediateOperand(1)) { switch (inst.getImmediateOperand(1)) {
case GLSLstd450Frexp: case GLSLstd450Frexp:
case GLSLstd450FrexpStruct: case GLSLstd450FrexpStruct:
if (getSpvVersion() < glslang::EShTargetSpv_1_3 && containsType(typeId, OpTypeInt, 16)) if (getSpvVersion() < spv::Spv_1_3 && containsType(typeId, OpTypeInt, 16))
addExtension(spv::E_SPV_AMD_gpu_shader_int16); addExtension(spv::E_SPV_AMD_gpu_shader_int16);
break; break;
case GLSLstd450InterpolateAtCentroid: case GLSLstd450InterpolateAtCentroid:
case GLSLstd450InterpolateAtSample: case GLSLstd450InterpolateAtSample:
case GLSLstd450InterpolateAtOffset: case GLSLstd450InterpolateAtOffset:
if (getSpvVersion() < glslang::EShTargetSpv_1_3 && containsType(typeId, OpTypeFloat, 16)) if (getSpvVersion() < spv::Spv_1_3 && containsType(typeId, OpTypeFloat, 16))
addExtension(spv::E_SPV_AMD_gpu_shader_half_float); addExtension(spv::E_SPV_AMD_gpu_shader_half_float);
break; break;
default: default:
break; break;
} }
break; break;
case OpAccessChain:
case OpPtrAccessChain:
if (isPointerType(typeId))
break;
if (basicTypeOp == OpTypeInt) {
if (width == 16)
addCapability(CapabilityInt16);
else if (width == 8)
addCapability(CapabilityInt8);
}
default: default:
if (basicTypeOp == OpTypeFloat && width == 16) if (basicTypeOp == OpTypeInt) {
addCapability(CapabilityFloat16); if (width == 16)
if (basicTypeOp == OpTypeInt && width == 16) addCapability(CapabilityInt16);
addCapability(CapabilityInt16); else if (width == 8)
if (basicTypeOp == OpTypeInt && width == 8) addCapability(CapabilityInt8);
addCapability(CapabilityInt8); else if (width == 64)
addCapability(CapabilityInt64);
} else if (basicTypeOp == OpTypeFloat) {
if (width == 16)
addCapability(CapabilityFloat16);
else if (width == 64)
addCapability(CapabilityFloat64);
}
break; break;
} }
} }

View file

@ -68,6 +68,8 @@ spv_target_env MapToSpirvToolsEnv(const SpvVersion& spvVersion, spv::SpvBuildLog
} }
case glslang::EShTargetVulkan_1_2: case glslang::EShTargetVulkan_1_2:
return spv_target_env::SPV_ENV_VULKAN_1_2; return spv_target_env::SPV_ENV_VULKAN_1_2;
case glslang::EShTargetVulkan_1_3:
return spv_target_env::SPV_ENV_VULKAN_1_3;
default: default:
break; break;
} }
@ -210,6 +212,7 @@ void SpirvToolsTransform(const glslang::TIntermediate& intermediate, std::vector
optimizer.RegisterPass(spvtools::CreateInterpolateFixupPass()); optimizer.RegisterPass(spvtools::CreateInterpolateFixupPass());
if (options->optimizeSize) { if (options->optimizeSize) {
optimizer.RegisterPass(spvtools::CreateRedundancyEliminationPass()); optimizer.RegisterPass(spvtools::CreateRedundancyEliminationPass());
optimizer.RegisterPass(spvtools::CreateEliminateDeadInputComponentsPass());
} }
optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass()); optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass());
optimizer.RegisterPass(spvtools::CreateCFGCleanupPass()); optimizer.RegisterPass(spvtools::CreateCFGCleanupPass());

View file

@ -47,7 +47,7 @@
#include "spirv-tools/libspirv.h" #include "spirv-tools/libspirv.h"
#endif #endif
#include "../glslang/MachineIndependent/localintermediate.h" #include "glslang/MachineIndependent/localintermediate.h"
#include "Logger.h" #include "Logger.h"
namespace glslang { namespace glslang {

View file

@ -43,6 +43,7 @@
#include <stack> #include <stack>
#include <sstream> #include <sstream>
#include <cstring> #include <cstring>
#include <utility>
#include "disassemble.h" #include "disassemble.h"
#include "doc.h" #include "doc.h"
@ -100,6 +101,7 @@ protected:
void outputMask(OperandClass operandClass, unsigned mask); void outputMask(OperandClass operandClass, unsigned mask);
void disassembleImmediates(int numOperands); void disassembleImmediates(int numOperands);
void disassembleIds(int numOperands); void disassembleIds(int numOperands);
std::pair<int, std::string> decodeString();
int disassembleString(); int disassembleString();
void disassembleInstruction(Id resultId, Id typeId, Op opCode, int numOperands); void disassembleInstruction(Id resultId, Id typeId, Op opCode, int numOperands);
@ -290,31 +292,44 @@ void SpirvStream::disassembleIds(int numOperands)
} }
} }
// return the number of operands consumed by the string // decode string from words at current position (non-consuming)
int SpirvStream::disassembleString() std::pair<int, std::string> SpirvStream::decodeString()
{ {
int startWord = word; std::string res;
int wordPos = word;
out << " \""; char c;
const char* wordString;
bool done = false; bool done = false;
do { do {
unsigned int content = stream[word]; unsigned int content = stream[wordPos];
wordString = (const char*)&content;
for (int charCount = 0; charCount < 4; ++charCount) { for (int charCount = 0; charCount < 4; ++charCount) {
if (*wordString == 0) { c = content & 0xff;
content >>= 8;
if (c == '\0') {
done = true; done = true;
break; break;
} }
out << *(wordString++); res += c;
} }
++word; ++wordPos;
} while (! done); } while(! done);
return std::make_pair(wordPos - word, res);
}
// return the number of operands consumed by the string
int SpirvStream::disassembleString()
{
out << " \"";
std::pair<int, std::string> decoderes = decodeString();
out << decoderes.second;
out << "\""; out << "\"";
return word - startWord; word += decoderes.first;
return decoderes.first;
} }
void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode, int numOperands) void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode, int numOperands)
@ -331,7 +346,7 @@ void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode,
nextNestedControl = 0; nextNestedControl = 0;
} }
} else if (opCode == OpExtInstImport) { } else if (opCode == OpExtInstImport) {
idDescriptor[resultId] = (const char*)(&stream[word]); idDescriptor[resultId] = decodeString().second;
} }
else { else {
if (resultId != 0 && idDescriptor[resultId].size() == 0) { if (resultId != 0 && idDescriptor[resultId].size() == 0) {
@ -428,7 +443,7 @@ void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode,
--numOperands; --numOperands;
// Get names for printing "(XXX)" for readability, *after* this id // Get names for printing "(XXX)" for readability, *after* this id
if (opCode == OpName) if (opCode == OpName)
idDescriptor[stream[word - 1]] = (const char*)(&stream[word]); idDescriptor[stream[word - 1]] = decodeString().second;
break; break;
case OperandVariableIds: case OperandVariableIds:
disassembleIds(numOperands); disassembleIds(numOperands);

View file

@ -305,7 +305,8 @@ const char* DecorationString(int decoration)
case DecorationPerPrimitiveNV: return "PerPrimitiveNV"; case DecorationPerPrimitiveNV: return "PerPrimitiveNV";
case DecorationPerViewNV: return "PerViewNV"; case DecorationPerViewNV: return "PerViewNV";
case DecorationPerTaskNV: return "PerTaskNV"; case DecorationPerTaskNV: return "PerTaskNV";
case DecorationPerVertexNV: return "PerVertexNV";
case DecorationPerVertexKHR: return "PerVertexKHR";
case DecorationNonUniformEXT: return "DecorationNonUniformEXT"; case DecorationNonUniformEXT: return "DecorationNonUniformEXT";
case DecorationHlslCounterBufferGOOGLE: return "DecorationHlslCounterBufferGOOGLE"; case DecorationHlslCounterBufferGOOGLE: return "DecorationHlslCounterBufferGOOGLE";
@ -392,6 +393,7 @@ const char* BuiltInString(int builtIn)
case BuiltInObjectRayDirectionKHR: return "ObjectRayDirectionKHR"; case BuiltInObjectRayDirectionKHR: return "ObjectRayDirectionKHR";
case BuiltInRayTminKHR: return "RayTminKHR"; case BuiltInRayTminKHR: return "RayTminKHR";
case BuiltInRayTmaxKHR: return "RayTmaxKHR"; case BuiltInRayTmaxKHR: return "RayTmaxKHR";
case BuiltInCullMaskKHR: return "CullMaskKHR";
case BuiltInInstanceCustomIndexKHR: return "InstanceCustomIndexKHR"; case BuiltInInstanceCustomIndexKHR: return "InstanceCustomIndexKHR";
case BuiltInRayGeometryIndexKHR: return "RayGeometryIndexKHR"; case BuiltInRayGeometryIndexKHR: return "RayGeometryIndexKHR";
case BuiltInObjectToWorldKHR: return "ObjectToWorldKHR"; case BuiltInObjectToWorldKHR: return "ObjectToWorldKHR";
@ -406,8 +408,8 @@ const char* BuiltInString(int builtIn)
case BuiltInViewportMaskPerViewNV: return "ViewportMaskPerViewNV"; case BuiltInViewportMaskPerViewNV: return "ViewportMaskPerViewNV";
// case BuiltInFragmentSizeNV: return "FragmentSizeNV"; // superseded by BuiltInFragSizeEXT // case BuiltInFragmentSizeNV: return "FragmentSizeNV"; // superseded by BuiltInFragSizeEXT
// case BuiltInInvocationsPerPixelNV: return "InvocationsPerPixelNV"; // superseded by BuiltInFragInvocationCountEXT // case BuiltInInvocationsPerPixelNV: return "InvocationsPerPixelNV"; // superseded by BuiltInFragInvocationCountEXT
case BuiltInBaryCoordNV: return "BaryCoordNV"; case BuiltInBaryCoordKHR: return "BaryCoordKHR";
case BuiltInBaryCoordNoPerspNV: return "BaryCoordNoPerspNV"; case BuiltInBaryCoordNoPerspKHR: return "BaryCoordNoPerspKHR";
case BuiltInFragSizeEXT: return "FragSizeEXT"; case BuiltInFragSizeEXT: return "FragSizeEXT";
case BuiltInFragInvocationCountEXT: return "FragInvocationCountEXT"; case BuiltInFragInvocationCountEXT: return "FragInvocationCountEXT";
@ -900,6 +902,12 @@ const char* CapabilityString(int info)
case CapabilityDeviceGroup: return "DeviceGroup"; case CapabilityDeviceGroup: return "DeviceGroup";
case CapabilityMultiView: return "MultiView"; case CapabilityMultiView: return "MultiView";
case CapabilityDenormPreserve: return "DenormPreserve";
case CapabilityDenormFlushToZero: return "DenormFlushToZero";
case CapabilitySignedZeroInfNanPreserve: return "SignedZeroInfNanPreserve";
case CapabilityRoundingModeRTE: return "RoundingModeRTE";
case CapabilityRoundingModeRTZ: return "RoundingModeRTZ";
case CapabilityStencilExportEXT: return "StencilExportEXT"; case CapabilityStencilExportEXT: return "StencilExportEXT";
case CapabilityFloat16ImageAMD: return "Float16ImageAMD"; case CapabilityFloat16ImageAMD: return "Float16ImageAMD";
@ -919,12 +927,13 @@ const char* CapabilityString(int info)
case CapabilityRayTracingNV: return "RayTracingNV"; case CapabilityRayTracingNV: return "RayTracingNV";
case CapabilityRayTracingMotionBlurNV: return "RayTracingMotionBlurNV"; case CapabilityRayTracingMotionBlurNV: return "RayTracingMotionBlurNV";
case CapabilityRayTracingKHR: return "RayTracingKHR"; case CapabilityRayTracingKHR: return "RayTracingKHR";
case CapabilityRayCullMaskKHR: return "RayCullMaskKHR";
case CapabilityRayQueryKHR: return "RayQueryKHR"; case CapabilityRayQueryKHR: return "RayQueryKHR";
case CapabilityRayTracingProvisionalKHR: return "RayTracingProvisionalKHR"; case CapabilityRayTracingProvisionalKHR: return "RayTracingProvisionalKHR";
case CapabilityRayTraversalPrimitiveCullingKHR: return "RayTraversalPrimitiveCullingKHR"; case CapabilityRayTraversalPrimitiveCullingKHR: return "RayTraversalPrimitiveCullingKHR";
case CapabilityComputeDerivativeGroupQuadsNV: return "ComputeDerivativeGroupQuadsNV"; case CapabilityComputeDerivativeGroupQuadsNV: return "ComputeDerivativeGroupQuadsNV";
case CapabilityComputeDerivativeGroupLinearNV: return "ComputeDerivativeGroupLinearNV"; case CapabilityComputeDerivativeGroupLinearNV: return "ComputeDerivativeGroupLinearNV";
case CapabilityFragmentBarycentricNV: return "FragmentBarycentricNV"; case CapabilityFragmentBarycentricKHR: return "FragmentBarycentricKHR";
case CapabilityMeshShadingNV: return "MeshShadingNV"; case CapabilityMeshShadingNV: return "MeshShadingNV";
case CapabilityImageFootprintNV: return "ImageFootprintNV"; case CapabilityImageFootprintNV: return "ImageFootprintNV";
// case CapabilityShadingRateNV: return "ShadingRateNV"; // superseded by FragmentDensityEXT // case CapabilityShadingRateNV: return "ShadingRateNV"; // superseded by FragmentDensityEXT

View file

@ -49,12 +49,12 @@ namespace spv {
typedef unsigned int Id; typedef unsigned int Id;
#define SPV_VERSION 0x10500 #define SPV_VERSION 0x10600
#define SPV_REVISION 4 #define SPV_REVISION 1
static const unsigned int MagicNumber = 0x07230203; static const unsigned int MagicNumber = 0x07230203;
static const unsigned int Version = 0x00010500; static const unsigned int Version = 0x00010600;
static const unsigned int Revision = 4; static const unsigned int Revision = 1;
static const unsigned int OpCodeMask = 0xffff; static const unsigned int OpCodeMask = 0xffff;
static const unsigned int WordCountShift = 16; static const unsigned int WordCountShift = 16;
@ -65,6 +65,7 @@ enum SourceLanguage {
SourceLanguageOpenCL_C = 3, SourceLanguageOpenCL_C = 3,
SourceLanguageOpenCL_CPP = 4, SourceLanguageOpenCL_CPP = 4,
SourceLanguageHLSL = 5, SourceLanguageHLSL = 5,
SourceLanguageCPP_for_OpenCL = 6,
SourceLanguageMax = 0x7fffffff, SourceLanguageMax = 0x7fffffff,
}; };
@ -352,6 +353,8 @@ enum ImageOperandsShift {
ImageOperandsVolatileTexelKHRShift = 11, ImageOperandsVolatileTexelKHRShift = 11,
ImageOperandsSignExtendShift = 12, ImageOperandsSignExtendShift = 12,
ImageOperandsZeroExtendShift = 13, ImageOperandsZeroExtendShift = 13,
ImageOperandsNontemporalShift = 14,
ImageOperandsOffsetsShift = 16,
ImageOperandsMax = 0x7fffffff, ImageOperandsMax = 0x7fffffff,
}; };
@ -375,6 +378,8 @@ enum ImageOperandsMask {
ImageOperandsVolatileTexelKHRMask = 0x00000800, ImageOperandsVolatileTexelKHRMask = 0x00000800,
ImageOperandsSignExtendMask = 0x00001000, ImageOperandsSignExtendMask = 0x00001000,
ImageOperandsZeroExtendMask = 0x00002000, ImageOperandsZeroExtendMask = 0x00002000,
ImageOperandsNontemporalMask = 0x00004000,
ImageOperandsOffsetsMask = 0x00010000,
}; };
enum FPFastMathModeShift { enum FPFastMathModeShift {
@ -491,6 +496,7 @@ enum Decoration {
DecorationPerPrimitiveNV = 5271, DecorationPerPrimitiveNV = 5271,
DecorationPerViewNV = 5272, DecorationPerViewNV = 5272,
DecorationPerTaskNV = 5273, DecorationPerTaskNV = 5273,
DecorationPerVertexKHR = 5285,
DecorationPerVertexNV = 5285, DecorationPerVertexNV = 5285,
DecorationNonUniform = 5300, DecorationNonUniform = 5300,
DecorationNonUniformEXT = 5300, DecorationNonUniformEXT = 5300,
@ -498,6 +504,10 @@ enum Decoration {
DecorationRestrictPointerEXT = 5355, DecorationRestrictPointerEXT = 5355,
DecorationAliasedPointer = 5356, DecorationAliasedPointer = 5356,
DecorationAliasedPointerEXT = 5356, DecorationAliasedPointerEXT = 5356,
DecorationBindlessSamplerNV = 5398,
DecorationBindlessImageNV = 5399,
DecorationBoundSamplerNV = 5400,
DecorationBoundImageNV = 5401,
DecorationSIMTCallINTEL = 5599, DecorationSIMTCallINTEL = 5599,
DecorationReferencedIndirectlyINTEL = 5602, DecorationReferencedIndirectlyINTEL = 5602,
DecorationClobberINTEL = 5607, DecorationClobberINTEL = 5607,
@ -537,6 +547,7 @@ enum Decoration {
DecorationFunctionFloatingPointModeINTEL = 6080, DecorationFunctionFloatingPointModeINTEL = 6080,
DecorationSingleElementVectorINTEL = 6085, DecorationSingleElementVectorINTEL = 6085,
DecorationVectorComputeCallableFunctionINTEL = 6087, DecorationVectorComputeCallableFunctionINTEL = 6087,
DecorationMediaBlockIOINTEL = 6140,
DecorationMax = 0x7fffffff, DecorationMax = 0x7fffffff,
}; };
@ -621,7 +632,9 @@ enum BuiltIn {
BuiltInLayerPerViewNV = 5279, BuiltInLayerPerViewNV = 5279,
BuiltInMeshViewCountNV = 5280, BuiltInMeshViewCountNV = 5280,
BuiltInMeshViewIndicesNV = 5281, BuiltInMeshViewIndicesNV = 5281,
BuiltInBaryCoordKHR = 5286,
BuiltInBaryCoordNV = 5286, BuiltInBaryCoordNV = 5286,
BuiltInBaryCoordNoPerspKHR = 5287,
BuiltInBaryCoordNoPerspNV = 5287, BuiltInBaryCoordNoPerspNV = 5287,
BuiltInFragSizeEXT = 5292, BuiltInFragSizeEXT = 5292,
BuiltInFragmentSizeNV = 5292, BuiltInFragmentSizeNV = 5292,
@ -660,6 +673,7 @@ enum BuiltIn {
BuiltInSMCountNV = 5375, BuiltInSMCountNV = 5375,
BuiltInWarpIDNV = 5376, BuiltInWarpIDNV = 5376,
BuiltInSMIDNV = 5377, BuiltInSMIDNV = 5377,
BuiltInCullMaskKHR = 6021,
BuiltInMax = 0x7fffffff, BuiltInMax = 0x7fffffff,
}; };
@ -722,6 +736,7 @@ enum FunctionControlShift {
FunctionControlDontInlineShift = 1, FunctionControlDontInlineShift = 1,
FunctionControlPureShift = 2, FunctionControlPureShift = 2,
FunctionControlConstShift = 3, FunctionControlConstShift = 3,
FunctionControlOptNoneINTELShift = 16,
FunctionControlMax = 0x7fffffff, FunctionControlMax = 0x7fffffff,
}; };
@ -731,6 +746,7 @@ enum FunctionControlMask {
FunctionControlDontInlineMask = 0x00000002, FunctionControlDontInlineMask = 0x00000002,
FunctionControlPureMask = 0x00000004, FunctionControlPureMask = 0x00000004,
FunctionControlConstMask = 0x00000008, FunctionControlConstMask = 0x00000008,
FunctionControlOptNoneINTELMask = 0x00010000,
}; };
enum MemorySemanticsShift { enum MemorySemanticsShift {
@ -911,6 +927,7 @@ enum Capability {
CapabilityGroupNonUniformQuad = 68, CapabilityGroupNonUniformQuad = 68,
CapabilityShaderLayer = 69, CapabilityShaderLayer = 69,
CapabilityShaderViewportIndex = 70, CapabilityShaderViewportIndex = 70,
CapabilityUniformDecoration = 71,
CapabilityFragmentShadingRateKHR = 4422, CapabilityFragmentShadingRateKHR = 4422,
CapabilitySubgroupBallotKHR = 4423, CapabilitySubgroupBallotKHR = 4423,
CapabilityDrawParameters = 4427, CapabilityDrawParameters = 4427,
@ -959,6 +976,7 @@ enum Capability {
CapabilityFragmentFullyCoveredEXT = 5265, CapabilityFragmentFullyCoveredEXT = 5265,
CapabilityMeshShadingNV = 5266, CapabilityMeshShadingNV = 5266,
CapabilityImageFootprintNV = 5282, CapabilityImageFootprintNV = 5282,
CapabilityFragmentBarycentricKHR = 5284,
CapabilityFragmentBarycentricNV = 5284, CapabilityFragmentBarycentricNV = 5284,
CapabilityComputeDerivativeGroupQuadsNV = 5288, CapabilityComputeDerivativeGroupQuadsNV = 5288,
CapabilityFragmentDensityEXT = 5291, CapabilityFragmentDensityEXT = 5291,
@ -1003,7 +1021,9 @@ enum Capability {
CapabilityFragmentShaderShadingRateInterlockEXT = 5372, CapabilityFragmentShaderShadingRateInterlockEXT = 5372,
CapabilityShaderSMBuiltinsNV = 5373, CapabilityShaderSMBuiltinsNV = 5373,
CapabilityFragmentShaderPixelInterlockEXT = 5378, CapabilityFragmentShaderPixelInterlockEXT = 5378,
CapabilityDemoteToHelperInvocation = 5379,
CapabilityDemoteToHelperInvocationEXT = 5379, CapabilityDemoteToHelperInvocationEXT = 5379,
CapabilityBindlessTextureNV = 5390,
CapabilitySubgroupShuffleINTEL = 5568, CapabilitySubgroupShuffleINTEL = 5568,
CapabilitySubgroupBufferBlockIOINTEL = 5569, CapabilitySubgroupBufferBlockIOINTEL = 5569,
CapabilitySubgroupImageBlockIOINTEL = 5570, CapabilitySubgroupImageBlockIOINTEL = 5570,
@ -1028,6 +1048,7 @@ enum Capability {
CapabilityFPGAMemoryAttributesINTEL = 5824, CapabilityFPGAMemoryAttributesINTEL = 5824,
CapabilityFPFastMathModeINTEL = 5837, CapabilityFPFastMathModeINTEL = 5837,
CapabilityArbitraryPrecisionIntegersINTEL = 5844, CapabilityArbitraryPrecisionIntegersINTEL = 5844,
CapabilityArbitraryPrecisionFloatingPointINTEL = 5845,
CapabilityUnstructuredLoopControlsINTEL = 5886, CapabilityUnstructuredLoopControlsINTEL = 5886,
CapabilityFPGALoopControlsINTEL = 5888, CapabilityFPGALoopControlsINTEL = 5888,
CapabilityKernelAttributesINTEL = 5892, CapabilityKernelAttributesINTEL = 5892,
@ -1036,14 +1057,27 @@ enum Capability {
CapabilityFPGAClusterAttributesINTEL = 5904, CapabilityFPGAClusterAttributesINTEL = 5904,
CapabilityLoopFuseINTEL = 5906, CapabilityLoopFuseINTEL = 5906,
CapabilityFPGABufferLocationINTEL = 5920, CapabilityFPGABufferLocationINTEL = 5920,
CapabilityArbitraryPrecisionFixedPointINTEL = 5922,
CapabilityUSMStorageClassesINTEL = 5935, CapabilityUSMStorageClassesINTEL = 5935,
CapabilityIOPipesINTEL = 5943, CapabilityIOPipesINTEL = 5943,
CapabilityBlockingPipesINTEL = 5945, CapabilityBlockingPipesINTEL = 5945,
CapabilityFPGARegINTEL = 5948, CapabilityFPGARegINTEL = 5948,
CapabilityDotProductInputAll = 6016,
CapabilityDotProductInputAllKHR = 6016,
CapabilityDotProductInput4x8Bit = 6017,
CapabilityDotProductInput4x8BitKHR = 6017,
CapabilityDotProductInput4x8BitPacked = 6018,
CapabilityDotProductInput4x8BitPackedKHR = 6018,
CapabilityDotProduct = 6019,
CapabilityDotProductKHR = 6019,
CapabilityRayCullMaskKHR = 6020,
CapabilityBitInstructions = 6025,
CapabilityAtomicFloat32AddEXT = 6033, CapabilityAtomicFloat32AddEXT = 6033,
CapabilityAtomicFloat64AddEXT = 6034, CapabilityAtomicFloat64AddEXT = 6034,
CapabilityLongConstantCompositeINTEL = 6089, CapabilityLongConstantCompositeINTEL = 6089,
CapabilityOptNoneINTEL = 6094,
CapabilityAtomicFloat16AddEXT = 6095, CapabilityAtomicFloat16AddEXT = 6095,
CapabilityDebugInfoModuleINTEL = 6114,
CapabilityMax = 0x7fffffff, CapabilityMax = 0x7fffffff,
}; };
@ -1122,6 +1156,32 @@ enum FPOperationMode {
FPOperationModeMax = 0x7fffffff, FPOperationModeMax = 0x7fffffff,
}; };
enum QuantizationModes {
QuantizationModesTRN = 0,
QuantizationModesTRN_ZERO = 1,
QuantizationModesRND = 2,
QuantizationModesRND_ZERO = 3,
QuantizationModesRND_INF = 4,
QuantizationModesRND_MIN_INF = 5,
QuantizationModesRND_CONV = 6,
QuantizationModesRND_CONV_ODD = 7,
QuantizationModesMax = 0x7fffffff,
};
enum OverflowModes {
OverflowModesWRAP = 0,
OverflowModesSAT = 1,
OverflowModesSAT_ZERO = 2,
OverflowModesSAT_SYM = 3,
OverflowModesMax = 0x7fffffff,
};
enum PackedVectorFormat {
PackedVectorFormatPackedVectorFormat4x8Bit = 0,
PackedVectorFormatPackedVectorFormat4x8BitKHR = 0,
PackedVectorFormatMax = 0x7fffffff,
};
enum Op { enum Op {
OpNop = 0, OpNop = 0,
OpUndef = 1, OpUndef = 1,
@ -1479,6 +1539,18 @@ enum Op {
OpConvertUToAccelerationStructureKHR = 4447, OpConvertUToAccelerationStructureKHR = 4447,
OpIgnoreIntersectionKHR = 4448, OpIgnoreIntersectionKHR = 4448,
OpTerminateRayKHR = 4449, OpTerminateRayKHR = 4449,
OpSDot = 4450,
OpSDotKHR = 4450,
OpUDot = 4451,
OpUDotKHR = 4451,
OpSUDot = 4452,
OpSUDotKHR = 4452,
OpSDotAccSat = 4453,
OpSDotAccSatKHR = 4453,
OpUDotAccSat = 4454,
OpUDotAccSatKHR = 4454,
OpSUDotAccSat = 4455,
OpSUDotAccSatKHR = 4455,
OpTypeRayQueryKHR = 4472, OpTypeRayQueryKHR = 4472,
OpRayQueryInitializeKHR = 4473, OpRayQueryInitializeKHR = 4473,
OpRayQueryTerminateKHR = 4474, OpRayQueryTerminateKHR = 4474,
@ -1517,8 +1589,16 @@ enum Op {
OpCooperativeMatrixLengthNV = 5362, OpCooperativeMatrixLengthNV = 5362,
OpBeginInvocationInterlockEXT = 5364, OpBeginInvocationInterlockEXT = 5364,
OpEndInvocationInterlockEXT = 5365, OpEndInvocationInterlockEXT = 5365,
OpDemoteToHelperInvocation = 5380,
OpDemoteToHelperInvocationEXT = 5380, OpDemoteToHelperInvocationEXT = 5380,
OpIsHelperInvocationEXT = 5381, OpIsHelperInvocationEXT = 5381,
OpConvertUToImageNV = 5391,
OpConvertUToSamplerNV = 5392,
OpConvertImageToUNV = 5393,
OpConvertSamplerToUNV = 5394,
OpConvertUToSampledImageNV = 5395,
OpConvertSampledImageToUNV = 5396,
OpSamplerImageAddressingModeNV = 5397,
OpSubgroupShuffleINTEL = 5571, OpSubgroupShuffleINTEL = 5571,
OpSubgroupShuffleDownINTEL = 5572, OpSubgroupShuffleDownINTEL = 5572,
OpSubgroupShuffleUpINTEL = 5573, OpSubgroupShuffleUpINTEL = 5573,
@ -1543,7 +1623,7 @@ enum Op {
OpUSubSatINTEL = 5596, OpUSubSatINTEL = 5596,
OpIMul32x16INTEL = 5597, OpIMul32x16INTEL = 5597,
OpUMul32x16INTEL = 5598, OpUMul32x16INTEL = 5598,
OpConstFunctionPointerINTEL = 5600, OpConstantFunctionPointerINTEL = 5600,
OpFunctionPointerCallINTEL = 5601, OpFunctionPointerCallINTEL = 5601,
OpAsmTargetINTEL = 5609, OpAsmTargetINTEL = 5609,
OpAsmINTEL = 5610, OpAsmINTEL = 5610,
@ -1677,7 +1757,59 @@ enum Op {
OpVariableLengthArrayINTEL = 5818, OpVariableLengthArrayINTEL = 5818,
OpSaveMemoryINTEL = 5819, OpSaveMemoryINTEL = 5819,
OpRestoreMemoryINTEL = 5820, OpRestoreMemoryINTEL = 5820,
OpArbitraryFloatSinCosPiINTEL = 5840,
OpArbitraryFloatCastINTEL = 5841,
OpArbitraryFloatCastFromIntINTEL = 5842,
OpArbitraryFloatCastToIntINTEL = 5843,
OpArbitraryFloatAddINTEL = 5846,
OpArbitraryFloatSubINTEL = 5847,
OpArbitraryFloatMulINTEL = 5848,
OpArbitraryFloatDivINTEL = 5849,
OpArbitraryFloatGTINTEL = 5850,
OpArbitraryFloatGEINTEL = 5851,
OpArbitraryFloatLTINTEL = 5852,
OpArbitraryFloatLEINTEL = 5853,
OpArbitraryFloatEQINTEL = 5854,
OpArbitraryFloatRecipINTEL = 5855,
OpArbitraryFloatRSqrtINTEL = 5856,
OpArbitraryFloatCbrtINTEL = 5857,
OpArbitraryFloatHypotINTEL = 5858,
OpArbitraryFloatSqrtINTEL = 5859,
OpArbitraryFloatLogINTEL = 5860,
OpArbitraryFloatLog2INTEL = 5861,
OpArbitraryFloatLog10INTEL = 5862,
OpArbitraryFloatLog1pINTEL = 5863,
OpArbitraryFloatExpINTEL = 5864,
OpArbitraryFloatExp2INTEL = 5865,
OpArbitraryFloatExp10INTEL = 5866,
OpArbitraryFloatExpm1INTEL = 5867,
OpArbitraryFloatSinINTEL = 5868,
OpArbitraryFloatCosINTEL = 5869,
OpArbitraryFloatSinCosINTEL = 5870,
OpArbitraryFloatSinPiINTEL = 5871,
OpArbitraryFloatCosPiINTEL = 5872,
OpArbitraryFloatASinINTEL = 5873,
OpArbitraryFloatASinPiINTEL = 5874,
OpArbitraryFloatACosINTEL = 5875,
OpArbitraryFloatACosPiINTEL = 5876,
OpArbitraryFloatATanINTEL = 5877,
OpArbitraryFloatATanPiINTEL = 5878,
OpArbitraryFloatATan2INTEL = 5879,
OpArbitraryFloatPowINTEL = 5880,
OpArbitraryFloatPowRINTEL = 5881,
OpArbitraryFloatPowNINTEL = 5882,
OpLoopControlINTEL = 5887, OpLoopControlINTEL = 5887,
OpFixedSqrtINTEL = 5923,
OpFixedRecipINTEL = 5924,
OpFixedRsqrtINTEL = 5925,
OpFixedSinINTEL = 5926,
OpFixedCosINTEL = 5927,
OpFixedSinCosINTEL = 5928,
OpFixedSinPiINTEL = 5929,
OpFixedCosPiINTEL = 5930,
OpFixedSinCosPiINTEL = 5931,
OpFixedLogINTEL = 5932,
OpFixedExpINTEL = 5933,
OpPtrCastToCrossWorkgroupINTEL = 5934, OpPtrCastToCrossWorkgroupINTEL = 5934,
OpCrossWorkgroupCastToPtrINTEL = 5938, OpCrossWorkgroupCastToPtrINTEL = 5938,
OpReadPipeBlockingINTEL = 5946, OpReadPipeBlockingINTEL = 5946,
@ -2069,6 +2201,12 @@ inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) {
case OpConvertUToAccelerationStructureKHR: *hasResult = true; *hasResultType = true; break; case OpConvertUToAccelerationStructureKHR: *hasResult = true; *hasResultType = true; break;
case OpIgnoreIntersectionKHR: *hasResult = false; *hasResultType = false; break; case OpIgnoreIntersectionKHR: *hasResult = false; *hasResultType = false; break;
case OpTerminateRayKHR: *hasResult = false; *hasResultType = false; break; case OpTerminateRayKHR: *hasResult = false; *hasResultType = false; break;
case OpSDot: *hasResult = true; *hasResultType = true; break;
case OpUDot: *hasResult = true; *hasResultType = true; break;
case OpSUDot: *hasResult = true; *hasResultType = true; break;
case OpSDotAccSat: *hasResult = true; *hasResultType = true; break;
case OpUDotAccSat: *hasResult = true; *hasResultType = true; break;
case OpSUDotAccSat: *hasResult = true; *hasResultType = true; break;
case OpTypeRayQueryKHR: *hasResult = true; *hasResultType = false; break; case OpTypeRayQueryKHR: *hasResult = true; *hasResultType = false; break;
case OpRayQueryInitializeKHR: *hasResult = false; *hasResultType = false; break; case OpRayQueryInitializeKHR: *hasResult = false; *hasResultType = false; break;
case OpRayQueryTerminateKHR: *hasResult = false; *hasResultType = false; break; case OpRayQueryTerminateKHR: *hasResult = false; *hasResultType = false; break;
@ -2105,8 +2243,15 @@ inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) {
case OpCooperativeMatrixLengthNV: *hasResult = true; *hasResultType = true; break; case OpCooperativeMatrixLengthNV: *hasResult = true; *hasResultType = true; break;
case OpBeginInvocationInterlockEXT: *hasResult = false; *hasResultType = false; break; case OpBeginInvocationInterlockEXT: *hasResult = false; *hasResultType = false; break;
case OpEndInvocationInterlockEXT: *hasResult = false; *hasResultType = false; break; case OpEndInvocationInterlockEXT: *hasResult = false; *hasResultType = false; break;
case OpDemoteToHelperInvocationEXT: *hasResult = false; *hasResultType = false; break; case OpDemoteToHelperInvocation: *hasResult = false; *hasResultType = false; break;
case OpIsHelperInvocationEXT: *hasResult = true; *hasResultType = true; break; case OpIsHelperInvocationEXT: *hasResult = true; *hasResultType = true; break;
case OpConvertUToImageNV: *hasResult = true; *hasResultType = true; break;
case OpConvertUToSamplerNV: *hasResult = true; *hasResultType = true; break;
case OpConvertImageToUNV: *hasResult = true; *hasResultType = true; break;
case OpConvertSamplerToUNV: *hasResult = true; *hasResultType = true; break;
case OpConvertUToSampledImageNV: *hasResult = true; *hasResultType = true; break;
case OpConvertSampledImageToUNV: *hasResult = true; *hasResultType = true; break;
case OpSamplerImageAddressingModeNV: *hasResult = false; *hasResultType = false; break;
case OpSubgroupShuffleINTEL: *hasResult = true; *hasResultType = true; break; case OpSubgroupShuffleINTEL: *hasResult = true; *hasResultType = true; break;
case OpSubgroupShuffleDownINTEL: *hasResult = true; *hasResultType = true; break; case OpSubgroupShuffleDownINTEL: *hasResult = true; *hasResultType = true; break;
case OpSubgroupShuffleUpINTEL: *hasResult = true; *hasResultType = true; break; case OpSubgroupShuffleUpINTEL: *hasResult = true; *hasResultType = true; break;
@ -2131,7 +2276,7 @@ inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) {
case OpUSubSatINTEL: *hasResult = true; *hasResultType = true; break; case OpUSubSatINTEL: *hasResult = true; *hasResultType = true; break;
case OpIMul32x16INTEL: *hasResult = true; *hasResultType = true; break; case OpIMul32x16INTEL: *hasResult = true; *hasResultType = true; break;
case OpUMul32x16INTEL: *hasResult = true; *hasResultType = true; break; case OpUMul32x16INTEL: *hasResult = true; *hasResultType = true; break;
case OpConstFunctionPointerINTEL: *hasResult = true; *hasResultType = true; break; case OpConstantFunctionPointerINTEL: *hasResult = true; *hasResultType = true; break;
case OpFunctionPointerCallINTEL: *hasResult = true; *hasResultType = true; break; case OpFunctionPointerCallINTEL: *hasResult = true; *hasResultType = true; break;
case OpAsmTargetINTEL: *hasResult = true; *hasResultType = true; break; case OpAsmTargetINTEL: *hasResult = true; *hasResultType = true; break;
case OpAsmINTEL: *hasResult = true; *hasResultType = true; break; case OpAsmINTEL: *hasResult = true; *hasResultType = true; break;
@ -2263,7 +2408,59 @@ inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) {
case OpVariableLengthArrayINTEL: *hasResult = true; *hasResultType = true; break; case OpVariableLengthArrayINTEL: *hasResult = true; *hasResultType = true; break;
case OpSaveMemoryINTEL: *hasResult = true; *hasResultType = true; break; case OpSaveMemoryINTEL: *hasResult = true; *hasResultType = true; break;
case OpRestoreMemoryINTEL: *hasResult = false; *hasResultType = false; break; case OpRestoreMemoryINTEL: *hasResult = false; *hasResultType = false; break;
case OpArbitraryFloatSinCosPiINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatCastINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatCastFromIntINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatCastToIntINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatAddINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatSubINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatMulINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatDivINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatGTINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatGEINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatLTINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatLEINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatEQINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatRecipINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatRSqrtINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatCbrtINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatHypotINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatSqrtINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatLogINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatLog2INTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatLog10INTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatLog1pINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatExpINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatExp2INTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatExp10INTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatExpm1INTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatSinINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatCosINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatSinCosINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatSinPiINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatCosPiINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatASinINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatASinPiINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatACosINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatACosPiINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatATanINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatATanPiINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatATan2INTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatPowINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatPowRINTEL: *hasResult = true; *hasResultType = true; break;
case OpArbitraryFloatPowNINTEL: *hasResult = true; *hasResultType = true; break;
case OpLoopControlINTEL: *hasResult = false; *hasResultType = false; break; case OpLoopControlINTEL: *hasResult = false; *hasResultType = false; break;
case OpFixedSqrtINTEL: *hasResult = true; *hasResultType = true; break;
case OpFixedRecipINTEL: *hasResult = true; *hasResultType = true; break;
case OpFixedRsqrtINTEL: *hasResult = true; *hasResultType = true; break;
case OpFixedSinINTEL: *hasResult = true; *hasResultType = true; break;
case OpFixedCosINTEL: *hasResult = true; *hasResultType = true; break;
case OpFixedSinCosINTEL: *hasResult = true; *hasResultType = true; break;
case OpFixedSinPiINTEL: *hasResult = true; *hasResultType = true; break;
case OpFixedCosPiINTEL: *hasResult = true; *hasResultType = true; break;
case OpFixedSinCosPiINTEL: *hasResult = true; *hasResultType = true; break;
case OpFixedLogINTEL: *hasResult = true; *hasResultType = true; break;
case OpFixedExpINTEL: *hasResult = true; *hasResultType = true; break;
case OpPtrCastToCrossWorkgroupINTEL: *hasResult = true; *hasResultType = true; break; case OpPtrCastToCrossWorkgroupINTEL: *hasResult = true; *hasResultType = true; break;
case OpCrossWorkgroupCastToPtrINTEL: *hasResult = true; *hasResultType = true; break; case OpCrossWorkgroupCastToPtrINTEL: *hasResult = true; *hasResultType = true; break;
case OpReadPipeBlockingINTEL: *hasResult = true; *hasResultType = true; break; case OpReadPipeBlockingINTEL: *hasResult = true; *hasResultType = true; break;

View file

@ -111,27 +111,23 @@ public:
void addStringOperand(const char* str) void addStringOperand(const char* str)
{ {
unsigned int word; unsigned int word = 0;
char* wordString = (char*)&word; unsigned int shiftAmount = 0;
char* wordPtr = wordString;
int charCount = 0;
char c; char c;
do { do {
c = *(str++); c = *(str++);
*(wordPtr++) = c; word |= ((unsigned int)c) << shiftAmount;
++charCount; shiftAmount += 8;
if (charCount == 4) { if (shiftAmount == 32) {
addImmediateOperand(word); addImmediateOperand(word);
wordPtr = wordString; word = 0;
charCount = 0; shiftAmount = 0;
} }
} while (c != 0); } while (c != 0);
// deal with partial last word // deal with partial last word
if (charCount > 0) { if (shiftAmount > 0) {
// pad with 0s
for (; charCount < 4; ++charCount)
*(wordPtr++) = 0;
addImmediateOperand(word); addImmediateOperand(word);
} }
} }
@ -361,6 +357,14 @@ public:
Decoration getReturnPrecision() const Decoration getReturnPrecision() const
{ return reducedPrecisionReturn ? DecorationRelaxedPrecision : NoPrecision; } { return reducedPrecisionReturn ? DecorationRelaxedPrecision : NoPrecision; }
void setDebugLineInfo(Id fileName, int line, int column) {
lineInstruction = std::unique_ptr<Instruction>{new Instruction(OpLine)};
lineInstruction->addIdOperand(fileName);
lineInstruction->addImmediateOperand(line);
lineInstruction->addImmediateOperand(column);
}
bool hasDebugLineInfo() const { return lineInstruction != nullptr; }
void setImplicitThis() { implicitThis = true; } void setImplicitThis() { implicitThis = true; }
bool hasImplicitThis() const { return implicitThis; } bool hasImplicitThis() const { return implicitThis; }
@ -377,6 +381,11 @@ public:
void dump(std::vector<unsigned int>& out) const void dump(std::vector<unsigned int>& out) const
{ {
// OpLine
if (lineInstruction != nullptr) {
lineInstruction->dump(out);
}
// OpFunction // OpFunction
functionInstruction.dump(out); functionInstruction.dump(out);
@ -395,6 +404,7 @@ protected:
Function& operator=(Function&); Function& operator=(Function&);
Module& parent; Module& parent;
std::unique_ptr<Instruction> lineInstruction;
Instruction functionInstruction; Instruction functionInstruction;
std::vector<Instruction*> parameterInstructions; std::vector<Instruction*> parameterInstructions;
std::vector<Block*> blocks; std::vector<Block*> blocks;
@ -461,7 +471,8 @@ protected:
// - the OpFunction instruction // - the OpFunction instruction
// - all the OpFunctionParameter instructions // - all the OpFunctionParameter instructions
__inline Function::Function(Id id, Id resultType, Id functionType, Id firstParamId, Module& parent) __inline Function::Function(Id id, Id resultType, Id functionType, Id firstParamId, Module& parent)
: parent(parent), functionInstruction(id, resultType, OpFunction), implicitThis(false), : parent(parent), lineInstruction(nullptr),
functionInstruction(id, resultType, OpFunction), implicitThis(false),
reducedPrecisionReturn(false) reducedPrecisionReturn(false)
{ {
// OpFunction // OpFunction

View file

@ -27,111 +27,111 @@
#include <GlslangToSpv.h> #include <GlslangToSpv.h>
static const TBuiltInResource DefaultTBuiltInResource = { static const TBuiltInResource DefaultTBuiltInResource = {
/* .MaxLights = */ 32, /* .MaxLights = */ 32,
/* .MaxClipPlanes = */ 6, /* .MaxClipPlanes = */ 6,
/* .MaxTextureUnits = */ 32, /* .MaxTextureUnits = */ 32,
/* .MaxTextureCoords = */ 32, /* .MaxTextureCoords = */ 32,
/* .MaxVertexAttribs = */ 64, /* .MaxVertexAttribs = */ 64,
/* .MaxVertexUniformComponents = */ 4096, /* .MaxVertexUniformComponents = */ 4096,
/* .MaxVaryingFloats = */ 64, /* .MaxVaryingFloats = */ 64,
/* .MaxVertexTextureImageUnits = */ 32, /* .MaxVertexTextureImageUnits = */ 32,
/* .MaxCombinedTextureImageUnits = */ 80, /* .MaxCombinedTextureImageUnits = */ 80,
/* .MaxTextureImageUnits = */ 32, /* .MaxTextureImageUnits = */ 32,
/* .MaxFragmentUniformComponents = */ 4096, /* .MaxFragmentUniformComponents = */ 4096,
/* .MaxDrawBuffers = */ 32, /* .MaxDrawBuffers = */ 32,
/* .MaxVertexUniformVectors = */ 128, /* .MaxVertexUniformVectors = */ 128,
/* .MaxVaryingVectors = */ 8, /* .MaxVaryingVectors = */ 8,
/* .MaxFragmentUniformVectors = */ 16, /* .MaxFragmentUniformVectors = */ 16,
/* .MaxVertexOutputVectors = */ 16, /* .MaxVertexOutputVectors = */ 16,
/* .MaxFragmentInputVectors = */ 15, /* .MaxFragmentInputVectors = */ 15,
/* .MinProgramTexelOffset = */ -8, /* .MinProgramTexelOffset = */ -8,
/* .MaxProgramTexelOffset = */ 7, /* .MaxProgramTexelOffset = */ 7,
/* .MaxClipDistances = */ 8, /* .MaxClipDistances = */ 8,
/* .MaxComputeWorkGroupCountX = */ 65535, /* .MaxComputeWorkGroupCountX = */ 65535,
/* .MaxComputeWorkGroupCountY = */ 65535, /* .MaxComputeWorkGroupCountY = */ 65535,
/* .MaxComputeWorkGroupCountZ = */ 65535, /* .MaxComputeWorkGroupCountZ = */ 65535,
/* .MaxComputeWorkGroupSizeX = */ 1024, /* .MaxComputeWorkGroupSizeX = */ 1024,
/* .MaxComputeWorkGroupSizeY = */ 1024, /* .MaxComputeWorkGroupSizeY = */ 1024,
/* .MaxComputeWorkGroupSizeZ = */ 64, /* .MaxComputeWorkGroupSizeZ = */ 64,
/* .MaxComputeUniformComponents = */ 1024, /* .MaxComputeUniformComponents = */ 1024,
/* .MaxComputeTextureImageUnits = */ 16, /* .MaxComputeTextureImageUnits = */ 16,
/* .MaxComputeImageUniforms = */ 8, /* .MaxComputeImageUniforms = */ 8,
/* .MaxComputeAtomicCounters = */ 8, /* .MaxComputeAtomicCounters = */ 8,
/* .MaxComputeAtomicCounterBuffers = */ 1, /* .MaxComputeAtomicCounterBuffers = */ 1,
/* .MaxVaryingComponents = */ 60, /* .MaxVaryingComponents = */ 60,
/* .MaxVertexOutputComponents = */ 64, /* .MaxVertexOutputComponents = */ 64,
/* .MaxGeometryInputComponents = */ 64, /* .MaxGeometryInputComponents = */ 64,
/* .MaxGeometryOutputComponents = */ 128, /* .MaxGeometryOutputComponents = */ 128,
/* .MaxFragmentInputComponents = */ 128, /* .MaxFragmentInputComponents = */ 128,
/* .MaxImageUnits = */ 8, /* .MaxImageUnits = */ 8,
/* .MaxCombinedImageUnitsAndFragmentOutputs = */ 8, /* .MaxCombinedImageUnitsAndFragmentOutputs = */ 8,
/* .MaxCombinedShaderOutputResources = */ 8, /* .MaxCombinedShaderOutputResources = */ 8,
/* .MaxImageSamples = */ 0, /* .MaxImageSamples = */ 0,
/* .MaxVertexImageUniforms = */ 0, /* .MaxVertexImageUniforms = */ 0,
/* .MaxTessControlImageUniforms = */ 0, /* .MaxTessControlImageUniforms = */ 0,
/* .MaxTessEvaluationImageUniforms = */ 0, /* .MaxTessEvaluationImageUniforms = */ 0,
/* .MaxGeometryImageUniforms = */ 0, /* .MaxGeometryImageUniforms = */ 0,
/* .MaxFragmentImageUniforms = */ 8, /* .MaxFragmentImageUniforms = */ 8,
/* .MaxCombinedImageUniforms = */ 8, /* .MaxCombinedImageUniforms = */ 8,
/* .MaxGeometryTextureImageUnits = */ 16, /* .MaxGeometryTextureImageUnits = */ 16,
/* .MaxGeometryOutputVertices = */ 256, /* .MaxGeometryOutputVertices = */ 256,
/* .MaxGeometryTotalOutputComponents = */ 1024, /* .MaxGeometryTotalOutputComponents = */ 1024,
/* .MaxGeometryUniformComponents = */ 1024, /* .MaxGeometryUniformComponents = */ 1024,
/* .MaxGeometryVaryingComponents = */ 64, /* .MaxGeometryVaryingComponents = */ 64,
/* .MaxTessControlInputComponents = */ 128, /* .MaxTessControlInputComponents = */ 128,
/* .MaxTessControlOutputComponents = */ 128, /* .MaxTessControlOutputComponents = */ 128,
/* .MaxTessControlTextureImageUnits = */ 16, /* .MaxTessControlTextureImageUnits = */ 16,
/* .MaxTessControlUniformComponents = */ 1024, /* .MaxTessControlUniformComponents = */ 1024,
/* .MaxTessControlTotalOutputComponents = */ 4096, /* .MaxTessControlTotalOutputComponents = */ 4096,
/* .MaxTessEvaluationInputComponents = */ 128, /* .MaxTessEvaluationInputComponents = */ 128,
/* .MaxTessEvaluationOutputComponents = */ 128, /* .MaxTessEvaluationOutputComponents = */ 128,
/* .MaxTessEvaluationTextureImageUnits = */ 16, /* .MaxTessEvaluationTextureImageUnits = */ 16,
/* .MaxTessEvaluationUniformComponents = */ 1024, /* .MaxTessEvaluationUniformComponents = */ 1024,
/* .MaxTessPatchComponents = */ 120, /* .MaxTessPatchComponents = */ 120,
/* .MaxPatchVertices = */ 32, /* .MaxPatchVertices = */ 32,
/* .MaxTessGenLevel = */ 64, /* .MaxTessGenLevel = */ 64,
/* .MaxViewports = */ 16, /* .MaxViewports = */ 16,
/* .MaxVertexAtomicCounters = */ 0, /* .MaxVertexAtomicCounters = */ 0,
/* .MaxTessControlAtomicCounters = */ 0, /* .MaxTessControlAtomicCounters = */ 0,
/* .MaxTessEvaluationAtomicCounters = */ 0, /* .MaxTessEvaluationAtomicCounters = */ 0,
/* .MaxGeometryAtomicCounters = */ 0, /* .MaxGeometryAtomicCounters = */ 0,
/* .MaxFragmentAtomicCounters = */ 8, /* .MaxFragmentAtomicCounters = */ 8,
/* .MaxCombinedAtomicCounters = */ 8, /* .MaxCombinedAtomicCounters = */ 8,
/* .MaxAtomicCounterBindings = */ 1, /* .MaxAtomicCounterBindings = */ 1,
/* .MaxVertexAtomicCounterBuffers = */ 0, /* .MaxVertexAtomicCounterBuffers = */ 0,
/* .MaxTessControlAtomicCounterBuffers = */ 0, /* .MaxTessControlAtomicCounterBuffers = */ 0,
/* .MaxTessEvaluationAtomicCounterBuffers = */ 0, /* .MaxTessEvaluationAtomicCounterBuffers = */ 0,
/* .MaxGeometryAtomicCounterBuffers = */ 0, /* .MaxGeometryAtomicCounterBuffers = */ 0,
/* .MaxFragmentAtomicCounterBuffers = */ 1, /* .MaxFragmentAtomicCounterBuffers = */ 1,
/* .MaxCombinedAtomicCounterBuffers = */ 1, /* .MaxCombinedAtomicCounterBuffers = */ 1,
/* .MaxAtomicCounterBufferSize = */ 16384, /* .MaxAtomicCounterBufferSize = */ 16384,
/* .MaxTransformFeedbackBuffers = */ 4, /* .MaxTransformFeedbackBuffers = */ 4,
/* .MaxTransformFeedbackInterleavedComponents = */ 64, /* .MaxTransformFeedbackInterleavedComponents = */ 64,
/* .MaxCullDistances = */ 8, /* .MaxCullDistances = */ 8,
/* .MaxCombinedClipAndCullDistances = */ 8, /* .MaxCombinedClipAndCullDistances = */ 8,
/* .MaxSamples = */ 4, /* .MaxSamples = */ 4,
/* .maxMeshOutputVerticesNV = */ 256, /* .maxMeshOutputVerticesNV = */ 256,
/* .maxMeshOutputPrimitivesNV = */ 512, /* .maxMeshOutputPrimitivesNV = */ 512,
/* .maxMeshWorkGroupSizeX_NV = */ 32, /* .maxMeshWorkGroupSizeX_NV = */ 32,
/* .maxMeshWorkGroupSizeY_NV = */ 1, /* .maxMeshWorkGroupSizeY_NV = */ 1,
/* .maxMeshWorkGroupSizeZ_NV = */ 1, /* .maxMeshWorkGroupSizeZ_NV = */ 1,
/* .maxTaskWorkGroupSizeX_NV = */ 32, /* .maxTaskWorkGroupSizeX_NV = */ 32,
/* .maxTaskWorkGroupSizeY_NV = */ 1, /* .maxTaskWorkGroupSizeY_NV = */ 1,
/* .maxTaskWorkGroupSizeZ_NV = */ 1, /* .maxTaskWorkGroupSizeZ_NV = */ 1,
/* .maxMeshViewCountNV = */ 4, /* .maxMeshViewCountNV = */ 4,
/* .maxDualSourceDrawBuffersEXT = */ 1, /* .maxDualSourceDrawBuffersEXT = */ 1,
/* .limits = */ { /* .limits = */ {
/* .nonInductiveForLoops = */ 1, /* .nonInductiveForLoops = */ 1,
/* .whileLoops = */ 1, /* .whileLoops = */ 1,
/* .doWhileLoops = */ 1, /* .doWhileLoops = */ 1,
/* .generalUniformIndexing = */ 1, /* .generalUniformIndexing = */ 1,
/* .generalAttributeMatrixVectorIndexing = */ 1, /* .generalAttributeMatrixVectorIndexing = */ 1,
/* .generalVaryingIndexing = */ 1, /* .generalVaryingIndexing = */ 1,
/* .generalSamplerIndexing = */ 1, /* .generalSamplerIndexing = */ 1,
/* .generalVariableIndexing = */ 1, /* .generalVariableIndexing = */ 1,
/* .generalConstantMatrixVectorIndexing = */ 1, /* .generalConstantMatrixVectorIndexing = */ 1,
} }
}; };
ShaderBuilder::ShaderBuilder() ShaderBuilder::ShaderBuilder()

View file

@ -352,7 +352,7 @@ float shadowAttenuation(vec4 lightpos, float lightcolorA)
vec3 origin = pixelpos.xyz; vec3 origin = pixelpos.xyz;
vec3 direction = normalize(lightpos.xyz - pixelpos.xyz); vec3 direction = normalize(lightpos.xyz - pixelpos.xyz);
float lightDistance = distance(pixelpos.xyz, lightpos.xyz); float lightDistance = distance(pixelpos.xyz, lightpos.xyz);
/* /*
rayQueryEXT rayQuery; rayQueryEXT rayQuery;
rayQueryInitializeEXT(rayQuery, TopLevelAS, gl_RayFlagsTerminateOnFirstHitEXT, 0xFF, origin, 0.01f, direction, lightDistance); rayQueryInitializeEXT(rayQuery, TopLevelAS, gl_RayFlagsTerminateOnFirstHitEXT, 0xFF, origin, 0.01f, direction, lightDistance);
@ -364,7 +364,8 @@ float shadowAttenuation(vec4 lightpos, float lightcolorA)
{ {
return 0.0; return 0.0;
} }
*/ */
return 1.0; return 1.0;
} }