Update glslang

--HG--
branch : minor
This commit is contained in:
Alex Szpakowski
2017-06-11 14:35:51 -03:00
parent 45de7cebb6
commit ad399cab39
47 changed files with 8133 additions and 6047 deletions
@@ -53,6 +53,10 @@ enum TBasicType {
EbtUint,
EbtInt64,
EbtUint64,
#ifdef AMD_EXTENSIONS
EbtInt16,
EbtUint16,
#endif
EbtBool,
EbtAtomicUint,
EbtSampler,
@@ -203,6 +207,9 @@ enum TBuiltInVariable {
EbvBaryCoordPullModel,
#endif
EbvViewIndex,
EbvDeviceIndex,
#ifdef NV_EXTENSIONS
EbvViewportMaskNV,
EbvSecondaryPositionNV,
@@ -210,10 +217,22 @@ enum TBuiltInVariable {
EbvPositionPerViewNV,
EbvViewportMaskPerViewNV,
#endif
// HLSL built-ins that live only temporarily, until they get remapped
// to one of the above.
EbvFragDepthGreater,
EbvFragDepthLesser,
EbvStencilRef,
EbvGsOutputStream,
EbvOutputPatch,
EbvInputPatch,
// structbuffer types
EbvAppendConsume, // no need to differentiate append and consume
EbvRWStructuredBuffer,
EbvStructuredBuffer,
EbvByteAddressBuffer,
EbvRWByteAddressBuffer,
EbvLast
};
@@ -323,6 +342,10 @@ __inline const char* GetBuiltInVariableString(TBuiltInVariable v)
case EbvBaryCoordSmoothSample: return "BaryCoordSmoothSample";
case EbvBaryCoordPullModel: return "BaryCoordPullModel";
#endif
case EbvViewIndex: return "ViewIndex";
case EbvDeviceIndex: return "DeviceIndex";
#ifdef NV_EXTENSIONS
case EbvViewportMaskNV: return "ViewportMaskNV";
case EbvSecondaryPositionNV: return "SecondaryPositionNV";
+177 -170
View File
@@ -43,6 +43,8 @@
#include "../Public/ShaderLang.h"
#include "arrays.h"
#include <algorithm>
namespace glslang {
const int GlslangMaxTypeLength = 200; // TODO: need to print block/struct one member per line, so this can stay bounded
@@ -396,11 +398,13 @@ public:
invariant = false;
noContraction = false;
makeTemporary();
declaredBuiltIn = EbvNone;
}
// drop qualifiers that don't belong in a temporary variable
void makeTemporary()
{
semanticName = nullptr;
storage = EvqTemporary;
builtIn = EbvNone;
clearInterstage();
@@ -449,8 +453,10 @@ public:
specConstant = false;
}
const char* semanticName;
TStorageQualifier storage : 6;
TBuiltInVariable builtIn : 8;
TBuiltInVariable declaredBuiltIn : 8;
TPrecisionQualifier precision : 3;
bool invariant : 1; // require canonical treatment for cross-shader invariance
bool noContraction: 1; // prevent contraction and reassociation, e.g., for 'precise' keyword, and expressions it affects
@@ -1302,6 +1308,7 @@ public:
virtual TBasicType getBasicType() const { return basicType; }
virtual const TSampler& getSampler() const { return sampler; }
virtual TSampler& getSampler() { return sampler; }
virtual TQualifier& getQualifier() { return qualifier; }
virtual const TQualifier& getQualifier() const { return qualifier; }
@@ -1378,127 +1385,84 @@ public:
return !isPerVertexAndBuiltIn(language);
}
// return true if this type contains any subtype which satisfies the given predicate.
template <typename P>
bool contains(P predicate) const
{
if (predicate(this))
return true;
const auto hasa = [predicate](const TTypeLoc& tl) { return tl.type->contains(predicate); };
return structure && std::any_of(structure->begin(), structure->end(), hasa);
}
// Recursively checks if the type contains the given basic type
virtual bool containsBasicType(TBasicType checkType) const
{
if (basicType == checkType)
return true;
if (! structure)
return false;
for (unsigned int i = 0; i < structure->size(); ++i) {
if ((*structure)[i].type->containsBasicType(checkType))
return true;
}
return false;
return contains([checkType](const TType* t) { return t->basicType == checkType; } );
}
// Recursively check the structure for any arrays, needed for some error checks
virtual bool containsArray() const
{
if (isArray())
return true;
if (structure == nullptr)
return false;
for (unsigned int i = 0; i < structure->size(); ++i) {
if ((*structure)[i].type->containsArray())
return true;
}
return false;
return contains([](const TType* t) { return t->isArray(); } );
}
// Check the structure for any structures, needed for some error checks
virtual bool containsStructure() const
{
if (structure == nullptr)
return false;
for (unsigned int i = 0; i < structure->size(); ++i) {
if ((*structure)[i].type->structure)
return true;
}
return false;
return contains([this](const TType* t) { return t != this && t->isStruct(); } );
}
// Recursively check the structure for any implicitly-sized arrays, needed for triggering a copyUp().
virtual bool containsImplicitlySizedArray() const
{
if (isImplicitlySizedArray())
return true;
if (structure == nullptr)
return false;
for (unsigned int i = 0; i < structure->size(); ++i) {
if ((*structure)[i].type->containsImplicitlySizedArray())
return true;
}
return false;
return contains([](const TType* t) { return t->isImplicitlySizedArray(); } );
}
virtual bool containsOpaque() const
{
if (isOpaque())
return true;
if (! structure)
return false;
for (unsigned int i = 0; i < structure->size(); ++i) {
if ((*structure)[i].type->containsOpaque())
return true;
}
return false;
return contains([](const TType* t) { return t->isOpaque(); } );
}
// Recursively checks if the type contains an interstage IO builtin
virtual bool containsBuiltInInterstageIO(EShLanguage language) const
{
if (isBuiltInInterstageIO(language))
return true;
if (! structure)
return false;
for (unsigned int i = 0; i < structure->size(); ++i) {
if ((*structure)[i].type->containsBuiltInInterstageIO(language))
return true;
}
return false;
return contains([language](const TType* t) { return t->isBuiltInInterstageIO(language); } );
}
virtual bool containsNonOpaque() const
{
// list all non-opaque types
switch (basicType) {
case EbtVoid:
case EbtFloat:
case EbtDouble:
const auto nonOpaque = [](const TType* t) {
switch (t->basicType) {
case EbtVoid:
case EbtFloat:
case EbtDouble:
#ifdef AMD_EXTENSIONS
case EbtFloat16:
case EbtFloat16:
#endif
case EbtInt:
case EbtUint:
case EbtInt64:
case EbtUint64:
case EbtBool:
case EbtInt:
case EbtUint:
case EbtInt64:
case EbtUint64:
#ifdef AMD_EXTENSIONS
case EbtInt16:
case EbtUint16:
#endif
case EbtBool:
return true;
default:
break;
}
if (! structure)
default:
return false;
for (unsigned int i = 0; i < structure->size(); ++i) {
if ((*structure)[i].type->containsNonOpaque())
return true;
}
return false;
}
};
return contains(nonOpaque);
}
virtual bool containsSpecializationSize() const
{
if (isArray() && arraySizes->containsNode())
return true;
if (! structure)
return false;
for (unsigned int i = 0; i < structure->size(); ++i) {
if ((*structure)[i].type->containsSpecializationSize())
return true;
}
return false;
return contains([](const TType* t) { return t->isArray() && t->arraySizes->isOuterSpecialization(); } );
}
// Array editing methods. Array descriptors can be shared across
@@ -1569,6 +1533,10 @@ public:
case EbtUint: return "uint";
case EbtInt64: return "int64_t";
case EbtUint64: return "uint64_t";
#ifdef AMD_EXTENSIONS
case EbtInt16: return "int16_t";
case EbtUint16: return "uint16_t";
#endif
case EbtBool: return "bool";
case EbtAtomicUint: return "atomic_uint";
case EbtSampler: return "sampler/image";
@@ -1580,10 +1548,11 @@ public:
TString getCompleteString() const
{
const int maxSize = GlslangMaxTypeLength;
char buf[maxSize];
char* p = &buf[0];
char* end = &buf[maxSize];
TString typeString;
const auto appendStr = [&](const char* s) { typeString.append(s); };
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()); };
if (qualifier.hasLayout()) {
// To reduce noise, skip this if the only layout is an xfb_buffer
@@ -1591,137 +1560,175 @@ public:
TQualifier noXfbBuffer = qualifier;
noXfbBuffer.layoutXfbBuffer = TQualifier::layoutXfbBufferEnd;
if (noXfbBuffer.hasLayout()) {
p += snprintf(p, end - p, "layout(");
appendStr("layout(");
if (qualifier.hasAnyLocation()) {
p += snprintf(p, end - p, "location=%d ", qualifier.layoutLocation);
if (qualifier.hasComponent())
p += snprintf(p, end - p, "component=%d ", qualifier.layoutComponent);
if (qualifier.hasIndex())
p += snprintf(p, end - p, "index=%d ", qualifier.layoutIndex);
appendStr(" location=");
appendUint(qualifier.layoutLocation);
if (qualifier.hasComponent()) {
appendStr(" component=");
appendUint(qualifier.layoutComponent);
}
if (qualifier.hasIndex()) {
appendStr(" index=");
appendUint(qualifier.layoutIndex);
}
}
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.hasSet())
p += snprintf(p, end - p, "set=%d ", qualifier.layoutSet);
if (qualifier.hasBinding())
p += snprintf(p, end - p, "binding=%d ", qualifier.layoutBinding);
if (qualifier.hasStream())
p += snprintf(p, end - p, "stream=%d ", qualifier.layoutStream);
if (qualifier.hasMatrix())
p += snprintf(p, end - p, "%s ", TQualifier::getLayoutMatrixString(qualifier.layoutMatrix));
if (qualifier.hasPacking())
p += snprintf(p, end - p, "%s ", TQualifier::getLayoutPackingString(qualifier.layoutPacking));
if (qualifier.hasOffset())
p += snprintf(p, end - p, "offset=%d ", qualifier.layoutOffset);
if (qualifier.hasAlign())
p += snprintf(p, end - p, "align=%d ", qualifier.layoutAlign);
if (qualifier.hasFormat())
p += snprintf(p, end - p, "%s ", TQualifier::getLayoutFormatString(qualifier.layoutFormat));
if (qualifier.hasXfbBuffer() && qualifier.hasXfbOffset())
p += snprintf(p, end - p, "xfb_buffer=%d ", qualifier.layoutXfbBuffer);
if (qualifier.hasXfbOffset())
p += snprintf(p, end - p, "xfb_offset=%d ", qualifier.layoutXfbOffset);
if (qualifier.hasXfbStride())
p += snprintf(p, end - p, "xfb_stride=%d ", qualifier.layoutXfbStride);
if (qualifier.hasAttachment())
p += snprintf(p, end - p, "input_attachment_index=%d ", qualifier.layoutAttachment);
if (qualifier.hasSpecConstantId())
p += snprintf(p, end - p, "constant_id=%d ", qualifier.layoutSpecConstantId);
if (qualifier.layoutPushConstant)
p += snprintf(p, end - p, "push_constant ");
appendStr(" push_constant");
#ifdef NV_EXTENSIONS
if (qualifier.layoutPassthrough)
p += snprintf(p, end - p, "passthrough ");
appendStr(" passthrough");
if (qualifier.layoutViewportRelative)
p += snprintf(p, end - p, "layoutViewportRelative ");
if (qualifier.layoutSecondaryViewportRelativeOffset != -2048)
p += snprintf(p, end - p, "layoutSecondaryViewportRelativeOffset=%d ", qualifier.layoutSecondaryViewportRelativeOffset);
appendStr(" layoutViewportRelative");
if (qualifier.layoutSecondaryViewportRelativeOffset != -2048) {
appendStr(" layoutSecondaryViewportRelativeOffset=");
appendInt(qualifier.layoutSecondaryViewportRelativeOffset);
}
#endif
p += snprintf(p, end - p, ") ");
appendStr(")");
}
}
if (qualifier.invariant)
p += snprintf(p, end - p, "invariant ");
appendStr(" invariant");
if (qualifier.noContraction)
p += snprintf(p, end - p, "noContraction ");
appendStr(" noContraction");
if (qualifier.centroid)
p += snprintf(p, end - p, "centroid ");
appendStr(" centroid");
if (qualifier.smooth)
p += snprintf(p, end - p, "smooth ");
appendStr(" smooth");
if (qualifier.flat)
p += snprintf(p, end - p, "flat ");
appendStr(" flat");
if (qualifier.nopersp)
p += snprintf(p, end - p, "noperspective ");
appendStr(" noperspective");
#ifdef AMD_EXTENSIONS
if (qualifier.explicitInterp)
p += snprintf(p, end - p, "__explicitInterpAMD ");
appendStr(" __explicitInterpAMD");
#endif
if (qualifier.patch)
p += snprintf(p, end - p, "patch ");
appendStr(" patch");
if (qualifier.sample)
p += snprintf(p, end - p, "sample ");
appendStr(" sample");
if (qualifier.coherent)
p += snprintf(p, end - p, "coherent ");
appendStr(" coherent");
if (qualifier.volatil)
p += snprintf(p, end - p, "volatile ");
appendStr(" volatile");
if (qualifier.restrict)
p += snprintf(p, end - p, "restrict ");
appendStr(" restrict");
if (qualifier.readonly)
p += snprintf(p, end - p, "readonly ");
appendStr(" readonly");
if (qualifier.writeonly)
p += snprintf(p, end - p, "writeonly ");
appendStr(" writeonly");
if (qualifier.specConstant)
p += snprintf(p, end - p, "specialization-constant ");
p += snprintf(p, end - p, "%s ", getStorageQualifierString());
appendStr(" specialization-constant");
appendStr(" ");
appendStr(getStorageQualifierString());
if (isArray()) {
for(int i = 0; i < (int)arraySizes->getNumDims(); ++i) {
int size = arraySizes->getDimSize(i);
if (size == 0)
p += snprintf(p, end - p, "implicitly-sized array of ");
else
p += snprintf(p, end - p, "%d-element array of ", arraySizes->getDimSize(i));
appendStr(" implicitly-sized array of");
else {
appendStr(" ");
appendInt(arraySizes->getDimSize(i));
appendStr("-element array of");
}
}
}
if (qualifier.precision != EpqNone)
p += snprintf(p, end - p, "%s ", getPrecisionQualifierString());
if (isMatrix())
p += snprintf(p, end - p, "%dX%d matrix of ", matrixCols, matrixRows);
else if (isVector())
p += snprintf(p, end - p, "%d-component vector of ", vectorSize);
if (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");
}
*p = 0;
TString s(buf);
s.append(getBasicTypeString());
appendStr(" ");
typeString.append(getBasicTypeString());
if (qualifier.builtIn != EbvNone) {
s.append(" ");
s.append(getBuiltInVariableString());
appendStr(" ");
appendStr(getBuiltInVariableString());
}
// Add struct/block members
if (structure) {
s.append("{");
appendStr("{");
for (size_t i = 0; i < structure->size(); ++i) {
if (s.size() > 3 * GlslangMaxTypeLength) {
// If we are getting too long, cut it short,
// just need to draw the line somewhere, as there is no limit to
// how large a struct/block type can get.
s.append("...");
break;
}
if (! (*structure)[i].type->hiddenMember()) {
s.append((*structure)[i].type->getCompleteString());
s.append(" ");
s.append((*structure)[i].type->getFieldName());
typeString.append((*structure)[i].type->getCompleteString());
typeString.append(" ");
typeString.append((*structure)[i].type->getFieldName());
if (i < structure->size() - 1)
s.append(", ");
appendStr(", ");
}
}
s.append("}");
appendStr("}");
}
return s;
return typeString;
}
TString getBasicTypeString() const
@@ -1759,7 +1766,7 @@ public:
}
// append this type's mangled name to the passed in 'name'
void appendMangledName(TString& name)
void appendMangledName(TString& name) const
{
buildMangledName(name);
name += ';' ;
@@ -1883,7 +1890,7 @@ protected:
}
void buildMangledName(TString&);
void buildMangledName(TString&) const;
TBasicType basicType : 8;
int vectorSize : 4; // 1 means either scalar or 1-component vector; see vector1 to disambiguate.
+14 -12
View File
@@ -264,6 +264,20 @@ struct TArraySizes {
return false;
}
bool isInnerSpecialization() const
{
for (int d = 1; d < sizes.size(); ++d) {
if (sizes.getDimNode(d) != nullptr)
return true;
}
return false;
}
bool isOuterSpecialization()
{
return sizes.getDimNode(0) != nullptr;
}
bool isImplicit() const { return getOuterSize() == UnsizedArraySize || isInnerImplicit(); }
void addOuterSizes(const TArraySizes& s) { sizes.push_front(s.sizes); }
void dereference() { sizes.pop_front(); }
@@ -288,18 +302,6 @@ struct TArraySizes {
return true;
}
// Returns true if any of the dimensions of the array is sized with a node
// instead of a front-end compile-time constant.
bool containsNode()
{
for (int d = 0; d < sizes.size(); ++d) {
if (sizes.getDimNode(d) != nullptr)
return true;
}
return false;
}
bool operator==(const TArraySizes& rhs) { return sizes == rhs.sizes; }
bool operator!=(const TArraySizes& rhs) { return sizes != rhs.sizes; }
@@ -141,6 +141,42 @@ enum TOperator {
EOpConvFloat16ToDouble,
EOpConvFloat16ToInt64,
EOpConvFloat16ToUint64,
EOpConvBoolToInt16,
EOpConvIntToInt16,
EOpConvUintToInt16,
EOpConvFloatToInt16,
EOpConvDoubleToInt16,
EOpConvFloat16ToInt16,
EOpConvInt64ToInt16,
EOpConvUint64ToInt16,
EOpConvUint16ToInt16,
EOpConvInt16ToBool,
EOpConvInt16ToInt,
EOpConvInt16ToUint,
EOpConvInt16ToFloat,
EOpConvInt16ToDouble,
EOpConvInt16ToFloat16,
EOpConvInt16ToInt64,
EOpConvInt16ToUint64,
EOpConvBoolToUint16,
EOpConvIntToUint16,
EOpConvUintToUint16,
EOpConvFloatToUint16,
EOpConvDoubleToUint16,
EOpConvFloat16ToUint16,
EOpConvInt64ToUint16,
EOpConvUint64ToUint16,
EOpConvInt16ToUint16,
EOpConvUint16ToBool,
EOpConvUint16ToInt,
EOpConvUint16ToUint,
EOpConvUint16ToFloat,
EOpConvUint16ToDouble,
EOpConvUint16ToFloat16,
EOpConvUint16ToInt64,
EOpConvUint16ToUint64,
#endif
//
@@ -183,6 +219,7 @@ enum TOperator {
EOpVectorSwizzle,
EOpMethod,
EOpScoping,
//
// Built-in functions mapped to operators
@@ -243,6 +280,12 @@ enum TOperator {
EOpDoubleBitsToUint64,
EOpInt64BitsToDouble,
EOpUint64BitsToDouble,
#ifdef AMD_EXTENSIONS
EOpFloat16BitsToInt16,
EOpFloat16BitsToUint16,
EOpInt16BitsToFloat16,
EOpUint16BitsToFloat16,
#endif
EOpPackSnorm2x16,
EOpUnpackSnorm2x16,
EOpPackUnorm2x16,
@@ -262,6 +305,14 @@ enum TOperator {
#ifdef AMD_EXTENSIONS
EOpPackFloat2x16,
EOpUnpackFloat2x16,
EOpPackInt2x16,
EOpUnpackInt2x16,
EOpPackUint2x16,
EOpUnpackUint2x16,
EOpPackInt4x16,
EOpUnpackInt4x16,
EOpPackUint4x16,
EOpUnpackUint4x16,
#endif
EOpLength,
@@ -393,15 +444,27 @@ enum TOperator {
EOpConstructUint,
EOpConstructInt64,
EOpConstructUint64,
#ifdef AMD_EXTENSIONS
EOpConstructInt16,
EOpConstructUint16,
#endif
EOpConstructBool,
EOpConstructFloat,
EOpConstructDouble,
#ifdef AMD_EXTENSIONS
EOpConstructFloat16,
#endif
EOpConstructVec2,
EOpConstructVec3,
EOpConstructVec4,
EOpConstructDVec2,
EOpConstructDVec3,
EOpConstructDVec4,
#ifdef AMD_EXTENSIONS
EOpConstructF16Vec2,
EOpConstructF16Vec3,
EOpConstructF16Vec4,
#endif
EOpConstructBVec2,
EOpConstructBVec3,
EOpConstructBVec4,
@@ -417,6 +480,14 @@ enum TOperator {
EOpConstructU64Vec2,
EOpConstructU64Vec3,
EOpConstructU64Vec4,
#ifdef AMD_EXTENSIONS
EOpConstructI16Vec2,
EOpConstructI16Vec3,
EOpConstructI16Vec4,
EOpConstructU16Vec2,
EOpConstructU16Vec3,
EOpConstructU16Vec4,
#endif
EOpConstructMat2x2,
EOpConstructMat2x3,
EOpConstructMat2x4,
@@ -435,11 +506,34 @@ enum TOperator {
EOpConstructDMat4x2,
EOpConstructDMat4x3,
EOpConstructDMat4x4,
EOpConstructIMat2x2,
EOpConstructIMat2x3,
EOpConstructIMat2x4,
EOpConstructIMat3x2,
EOpConstructIMat3x3,
EOpConstructIMat3x4,
EOpConstructIMat4x2,
EOpConstructIMat4x3,
EOpConstructIMat4x4,
EOpConstructUMat2x2,
EOpConstructUMat2x3,
EOpConstructUMat2x4,
EOpConstructUMat3x2,
EOpConstructUMat3x3,
EOpConstructUMat3x4,
EOpConstructUMat4x2,
EOpConstructUMat4x3,
EOpConstructUMat4x4,
EOpConstructBMat2x2,
EOpConstructBMat2x3,
EOpConstructBMat2x4,
EOpConstructBMat3x2,
EOpConstructBMat3x3,
EOpConstructBMat3x4,
EOpConstructBMat4x2,
EOpConstructBMat4x3,
EOpConstructBMat4x4,
#ifdef AMD_EXTENSIONS
EOpConstructFloat16,
EOpConstructF16Vec2,
EOpConstructF16Vec3,
EOpConstructF16Vec4,
EOpConstructF16Mat2x2,
EOpConstructF16Mat2x3,
EOpConstructF16Mat2x4,
@@ -539,6 +633,11 @@ enum TOperator {
EOpTextureOffsetClamp,
EOpTextureGradClamp,
EOpTextureGradOffsetClamp,
#ifdef AMD_EXTENSIONS
EOpTextureGatherLod,
EOpTextureGatherLodOffset,
EOpTextureGatherLodOffsets,
#endif
EOpSparseTextureGuardBegin,
@@ -558,6 +657,11 @@ enum TOperator {
EOpSparseTextureOffsetClamp,
EOpSparseTextureGradClamp,
EOpSparseTextureGradOffsetClamp,
#ifdef AMD_EXTENSIONS
EOpSparseTextureGatherLod,
EOpSparseTextureGatherLodOffset,
EOpSparseTextureGatherLodOffsets,
#endif
EOpSparseTextureGuardEnd,
EOpSamplingGuardEnd,
@@ -624,6 +728,19 @@ enum TOperator {
EOpMethodCalculateLevelOfDetail, // ...
EOpMethodCalculateLevelOfDetailUnclamped, // ...
// Load already defined above for textures
EOpMethodLoad2, // Structure buffer object methods. These are translated to existing
EOpMethodLoad3, // AST methods, and exist to represent HLSL semantics until that
EOpMethodLoad4, // translation is performed. See HlslParseContext::decomposeSampleMethods().
EOpMethodStore, // ...
EOpMethodStore2, // ...
EOpMethodStore3, // ...
EOpMethodStore4, // ...
EOpMethodIncrementCounter, // ...
EOpMethodDecrementCounter, // ...
// EOpMethodAppend is defined for geo shaders below
EOpMethodConsume,
// SM5 texture methods
EOpMethodGatherRed, // These are covered under the above EOpMethodSample comment about
EOpMethodGatherGreen, // translation to existing AST opcodes. They exist temporarily
@@ -744,6 +861,15 @@ protected:
TType type;
};
//
// Loop control hints
//
enum TLoopControl {
ELoopControlNone,
ELoopControlUnroll,
ELoopControlDontUnroll,
};
//
// Handle for, do-while, and while loops.
//
@@ -753,17 +879,25 @@ public:
body(aBody),
test(aTest),
terminal(aTerminal),
first(testFirst) { }
first(testFirst),
control(ELoopControlNone)
{ }
virtual void traverse(TIntermTraverser*);
TIntermNode* getBody() const { return body; }
TIntermTyped* getTest() const { return test; }
TIntermTyped* getTerminal() const { return terminal; }
bool testFirst() const { return first; }
void setLoopControl(TLoopControl c) { control = c; }
TLoopControl getLoopControl() const { return control; }
protected:
TIntermNode* body; // code to loop over
TIntermTyped* test; // exit condition associated with loop, could be 0 for 'for' loops
TIntermTyped* terminal; // exists for for-loops
bool first; // true for while and for, not for do-while
TLoopControl control; // loop control hint
};
//
@@ -1017,6 +1151,25 @@ public:
cracked.gather = true;
cracked.offsets = true;
break;
#ifdef AMD_EXTENSIONS
case EOpTextureGatherLod:
case EOpSparseTextureGatherLod:
cracked.gather = true;
cracked.lod = true;
break;
case EOpTextureGatherLodOffset:
case EOpSparseTextureGatherLodOffset:
cracked.gather = true;
cracked.offset = true;
cracked.lod = true;
break;
case EOpTextureGatherLodOffsets:
case EOpSparseTextureGatherLodOffsets:
cracked.gather = true;
cracked.offsets = true;
cracked.lod = true;
break;
#endif
case EOpSubpassLoad:
case EOpSubpassLoadMS:
cracked.subpass = true;
@@ -2,5 +2,5 @@
// For the version, it uses the latest git tag followed by the number of commits.
// For the date, it uses the current date (when then script is run).
#define GLSLANG_REVISION "Overload400-PrecQual.1843"
#define GLSLANG_DATE "18-Feb-2017"
#define GLSLANG_REVISION "Overload400-PrecQual.2000"
#define GLSLANG_DATE "12-Apr-2017"
@@ -193,7 +193,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TIntermTyped* right
case EbtUint:
if (rightUnionArray[i] == 0) {
newConstArray[i].setUConst(0xFFFFFFFF);
newConstArray[i].setUConst(0xFFFFFFFFu);
} else
newConstArray[i].setUConst(leftUnionArray[i].getUConst() / rightUnionArray[i].getUConst());
break;
@@ -213,6 +213,23 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TIntermTyped* right
} else
newConstArray[i].setU64Const(leftUnionArray[i].getU64Const() / rightUnionArray[i].getU64Const());
break;
#ifdef AMD_EXTENSIONS
case EbtInt16:
if (rightUnionArray[i] == 0)
newConstArray[i].setIConst(0x7FFF);
else if (rightUnionArray[i].getIConst() == -1 && leftUnionArray[i].getIConst() == (int)0x8000)
newConstArray[i].setIConst(0x8000);
else
newConstArray[i].setIConst(leftUnionArray[i].getIConst() / rightUnionArray[i].getIConst());
break;
case EbtUint16:
if (rightUnionArray[i] == 0) {
newConstArray[i].setUConst(0xFFFFu);
} else
newConstArray[i].setUConst(leftUnionArray[i].getUConst() / rightUnionArray[i].getUConst());
break;
#endif
default:
return 0;
}
@@ -457,10 +474,16 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TType& returnType)
case EbtFloat16:
#endif
case EbtFloat: newConstArray[i].setDConst(-unionArray[i].getDConst()); break;
#ifdef AMD_EXTENSIONS
case EbtInt16:
#endif
case EbtInt: newConstArray[i].setIConst(-unionArray[i].getIConst()); break;
#ifdef AMD_EXTENSIONS
case EbtUint16:
#endif
case EbtUint: newConstArray[i].setUConst(static_cast<unsigned int>(-static_cast<int>(unionArray[i].getUConst()))); break;
case EbtInt64: newConstArray[i].setI64Const(-unionArray[i].getI64Const()); break;
case EbtUint64: newConstArray[i].setU64Const(static_cast<unsigned int>(-static_cast<int>(unionArray[i].getU64Const()))); break;
case EbtUint64: newConstArray[i].setU64Const(static_cast<unsigned long long>(-static_cast<long long>(unionArray[i].getU64Const()))); break;
default:
return 0;
}
@@ -610,6 +633,14 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TType& returnType)
case EOpUintBitsToFloat:
case EOpDoubleBitsToInt64:
case EOpDoubleBitsToUint64:
case EOpInt64BitsToDouble:
case EOpUint64BitsToDouble:
#ifdef AMD_EXTENSIONS
case EOpFloat16BitsToInt16:
case EOpFloat16BitsToUint16:
case EOpInt16BitsToFloat16:
case EOpUint16BitsToFloat16:
#endif
default:
return 0;
@@ -702,6 +733,9 @@ TIntermTyped* TIntermediate::fold(TIntermAggregate* aggrNode)
#endif
children[0]->getAsTyped()->getBasicType() == EbtDouble;
bool isSigned = children[0]->getAsTyped()->getBasicType() == EbtInt ||
#ifdef AMD_EXTENSIONS
children[0]->getAsTyped()->getBasicType() == EbtInt16 ||
#endif
children[0]->getAsTyped()->getBasicType() == EbtInt64;
bool isInt64 = children[0]->getAsTyped()->getBasicType() == EbtInt64 ||
children[0]->getAsTyped()->getBasicType() == EbtUint64;
@@ -103,6 +103,7 @@ TBuiltIns::~TBuiltIns()
{
}
//
// Add all context-independent built-in functions and variables that are present
// for the given version and profile. Share common ones across stages, otherwise
@@ -2615,6 +2616,157 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
"\n");
}
// GL_AMD_gpu_shader_int16
if (profile != EEsProfile && version >= 450) {
commonBuiltins.append(
"int16_t abs(int16_t);"
"i16vec2 abs(i16vec2);"
"i16vec3 abs(i16vec3);"
"i16vec4 abs(i16vec4);"
"int16_t sign(int16_t);"
"i16vec2 sign(i16vec2);"
"i16vec3 sign(i16vec3);"
"i16vec4 sign(i16vec4);"
"int16_t min(int16_t, int16_t);"
"i16vec2 min(i16vec2, int16_t);"
"i16vec3 min(i16vec3, int16_t);"
"i16vec4 min(i16vec4, int16_t);"
"i16vec2 min(i16vec2, i16vec2);"
"i16vec3 min(i16vec3, i16vec3);"
"i16vec4 min(i16vec4, i16vec4);"
"uint16_t min(uint16_t, uint16_t);"
"u16vec2 min(u16vec2, uint16_t);"
"u16vec3 min(u16vec3, uint16_t);"
"u16vec4 min(u16vec4, uint16_t);"
"u16vec2 min(u16vec2, u16vec2);"
"u16vec3 min(u16vec3, u16vec3);"
"u16vec4 min(u16vec4, u16vec4);"
"int16_t max(int16_t, int16_t);"
"i16vec2 max(i16vec2, int16_t);"
"i16vec3 max(i16vec3, int16_t);"
"i16vec4 max(i16vec4, int16_t);"
"i16vec2 max(i16vec2, i16vec2);"
"i16vec3 max(i16vec3, i16vec3);"
"i16vec4 max(i16vec4, i16vec4);"
"uint16_t max(uint16_t, uint16_t);"
"u16vec2 max(u16vec2, uint16_t);"
"u16vec3 max(u16vec3, uint16_t);"
"u16vec4 max(u16vec4, uint16_t);"
"u16vec2 max(u16vec2, u16vec2);"
"u16vec3 max(u16vec3, u16vec3);"
"u16vec4 max(u16vec4, u16vec4);"
"int16_t clamp(int16_t, int16_t, int16_t);"
"i16vec2 clamp(i16vec2, int16_t, int16_t);"
"i16vec3 clamp(i16vec3, int16_t, int16_t);"
"i16vec4 clamp(i16vec4, int16_t, int16_t);"
"i16vec2 clamp(i16vec2, i16vec2, i16vec2);"
"i16vec3 clamp(i16vec3, i16vec3, i16vec3);"
"i16vec4 clamp(i16vec4, i16vec4, i16vec4);"
"uint16_t clamp(uint16_t, uint16_t, uint16_t);"
"u16vec2 clamp(u16vec2, uint16_t, uint16_t);"
"u16vec3 clamp(u16vec3, uint16_t, uint16_t);"
"u16vec4 clamp(u16vec4, uint16_t, uint16_t);"
"u16vec2 clamp(u16vec2, u16vec2, u16vec2);"
"u16vec3 clamp(u16vec3, u16vec3, u16vec3);"
"u16vec4 clamp(u16vec4, u16vec4, u16vec4);"
"int16_t mix(int16_t, int16_t, bool);"
"i16vec2 mix(i16vec2, i16vec2, bvec2);"
"i16vec3 mix(i16vec3, i16vec3, bvec3);"
"i16vec4 mix(i16vec4, i16vec4, bvec4);"
"uint16_t mix(uint16_t, uint16_t, bool);"
"u16vec2 mix(u16vec2, u16vec2, bvec2);"
"u16vec3 mix(u16vec3, u16vec3, bvec3);"
"u16vec4 mix(u16vec4, u16vec4, bvec4);"
"float16_t frexp(float16_t, out int16_t);"
"f16vec2 frexp(f16vec2, out i16vec2);"
"f16vec3 frexp(f16vec3, out i16vec3);"
"f16vec4 frexp(f16vec4, out i16vec4);"
"float16_t ldexp(float16_t, int16_t);"
"f16vec2 ldexp(f16vec2, i16vec2);"
"f16vec3 ldexp(f16vec3, i16vec3);"
"f16vec4 ldexp(f16vec4, i16vec4);"
"int16_t float16BitsToInt16(float16_t);"
"i16vec2 float16BitsToInt16(f16vec2);"
"i16vec3 float16BitsToInt16(f16vec3);"
"i16vec4 float16BitsToInt16(f16vec4);"
"uint16_t float16BitsToUint16(float16_t);"
"u16vec2 float16BitsToUint16(f16vec2);"
"u16vec3 float16BitsToUint16(f16vec3);"
"u16vec4 float16BitsToUint16(f16vec4);"
"float16_t int16BitsToFloat16(int16_t);"
"f16vec2 int16BitsToFloat16(i16vec2);"
"f16vec3 int16BitsToFloat16(i16vec3);"
"f16vec4 int16BitsToFloat16(i16vec4);"
"float16_t uint16BitsToFloat16(uint16_t);"
"f16vec2 uint16BitsToFloat16(u16vec2);"
"f16vec3 uint16BitsToFloat16(u16vec3);"
"f16vec4 uint16BitsToFloat16(u16vec4);"
"int packInt2x16(i16vec2);"
"uint packUint2x16(u16vec2);"
"int64_t packInt4x16(i16vec4);"
"uint64_t packUint4x16(u16vec4);"
"i16vec2 unpackInt2x16(int);"
"u16vec2 unpackUint2x16(uint);"
"i16vec4 unpackInt4x16(int64_t);"
"u16vec4 unpackUint4x16(uint64_t);"
"bvec2 lessThan(i16vec2, i16vec2);"
"bvec3 lessThan(i16vec3, i16vec3);"
"bvec4 lessThan(i16vec4, i16vec4);"
"bvec2 lessThan(u16vec2, u16vec2);"
"bvec3 lessThan(u16vec3, u16vec3);"
"bvec4 lessThan(u16vec4, u16vec4);"
"bvec2 lessThanEqual(i16vec2, i16vec2);"
"bvec3 lessThanEqual(i16vec3, i16vec3);"
"bvec4 lessThanEqual(i16vec4, i16vec4);"
"bvec2 lessThanEqual(u16vec2, u16vec2);"
"bvec3 lessThanEqual(u16vec3, u16vec3);"
"bvec4 lessThanEqual(u16vec4, u16vec4);"
"bvec2 greaterThan(i16vec2, i16vec2);"
"bvec3 greaterThan(i16vec3, i16vec3);"
"bvec4 greaterThan(i16vec4, i16vec4);"
"bvec2 greaterThan(u16vec2, u16vec2);"
"bvec3 greaterThan(u16vec3, u16vec3);"
"bvec4 greaterThan(u16vec4, u16vec4);"
"bvec2 greaterThanEqual(i16vec2, i16vec2);"
"bvec3 greaterThanEqual(i16vec3, i16vec3);"
"bvec4 greaterThanEqual(i16vec4, i16vec4);"
"bvec2 greaterThanEqual(u16vec2, u16vec2);"
"bvec3 greaterThanEqual(u16vec3, u16vec3);"
"bvec4 greaterThanEqual(u16vec4, u16vec4);"
"bvec2 equal(i16vec2, i16vec2);"
"bvec3 equal(i16vec3, i16vec3);"
"bvec4 equal(i16vec4, i16vec4);"
"bvec2 equal(u16vec2, u16vec2);"
"bvec3 equal(u16vec3, u16vec3);"
"bvec4 equal(u16vec4, u16vec4);"
"bvec2 notEqual(i16vec2, i16vec2);"
"bvec3 notEqual(i16vec3, i16vec3);"
"bvec4 notEqual(i16vec4, i16vec4);"
"bvec2 notEqual(u16vec2, u16vec2);"
"bvec3 notEqual(u16vec3, u16vec3);"
"bvec4 notEqual(u16vec4, u16vec4);"
"\n");
}
#endif
//============================================================================
@@ -3137,6 +3289,13 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
"\n");
}
if ((profile != EEsProfile && version >= 140) ||
(profile == EEsProfile && version >= 310)) {
stageBuiltins[EShLangCompute].append(
"in highp int gl_DeviceIndex;" // GL_EXT_device_group
"\n");
}
//============================================================================
//
// Define the interface to the vertex shader.
@@ -3261,11 +3420,11 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
stageBuiltins[EShLangVertex].append(
"out int gl_ViewportIndex;"
"out int gl_Layer;"
"out int gl_ViewportMask[];"
"out int gl_SecondaryViewportMaskNV[];"
"out vec4 gl_SecondaryPositionNV;"
"out vec4 gl_PositionPerViewNV[];"
"out int gl_ViewportMaskPerViewNV[];"
"out int gl_ViewportMask[];" // GL_NV_viewport_array2
"out int gl_SecondaryViewportMaskNV[];" // 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 int gl_ViewportMaskPerViewNV[];" // GL_NVX_multiview_per_view_attributes
);
#endif
@@ -3302,6 +3461,15 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
}
}
if ((profile != EEsProfile && version >= 140) ||
(profile == EEsProfile && version >= 310)) {
stageBuiltins[EShLangVertex].append(
"in highp int gl_DeviceIndex;" // GL_EXT_device_group
"in highp int gl_ViewIndex;" // GL_EXT_multiview
"\n");
}
//============================================================================
//
// Define the interface to the geometry shader.
@@ -3329,8 +3497,8 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
stageBuiltins[EShLangGeometry].append(
"float gl_CullDistance[];"
#ifdef NV_EXTENSIONS
"vec4 gl_SecondaryPositionNV;"
"vec4 gl_PositionPerViewNV[];"
"vec4 gl_SecondaryPositionNV;" // GL_NV_stereo_view_rendering
"vec4 gl_PositionPerViewNV[];" // GL_NVX_multiview_per_view_attributes
#endif
);
stageBuiltins[EShLangGeometry].append(
@@ -3380,11 +3548,11 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
#ifdef NV_EXTENSIONS
if (version >= 450)
stageBuiltins[EShLangGeometry].append(
"out int gl_ViewportMask[];"
"out int gl_SecondaryViewportMaskNV[];"
"out vec4 gl_SecondaryPositionNV;"
"out vec4 gl_PositionPerViewNV[];"
"out int gl_ViewportMaskPerViewNV[];"
"out int gl_ViewportMask[];" // GL_NV_viewport_array2
"out int gl_SecondaryViewportMaskNV[];" // 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 int gl_ViewportMaskPerViewNV[];" // GL_NVX_multiview_per_view_attributes
);
#endif
@@ -3410,6 +3578,14 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
);
}
if ((profile != EEsProfile && version >= 140) ||
(profile == EEsProfile && version >= 310)) {
stageBuiltins[EShLangGeometry].append(
"in highp int gl_DeviceIndex;" // GL_EXT_device_group
"in highp int gl_ViewIndex;" // GL_EXT_multiview
"\n");
}
//============================================================================
//
// Define the interface to the tessellation control shader.
@@ -3446,11 +3622,11 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
#ifdef NV_EXTENSIONS
"int gl_ViewportIndex;"
"int gl_Layer;"
"int gl_ViewportMask[];"
"vec4 gl_SecondaryPositionNV;"
"int gl_SecondaryViewportMaskNV[];"
"vec4 gl_PositionPerViewNV[];"
"int gl_ViewportMaskPerViewNV[];"
"int gl_ViewportMask[];" // GL_NV_viewport_array2
"vec4 gl_SecondaryPositionNV;" // GL_NV_stereo_view_rendering
"int gl_SecondaryViewportMaskNV[];" // GL_NV_stereo_view_rendering
"vec4 gl_PositionPerViewNV[];" // GL_NVX_multiview_per_view_attributes
"int gl_ViewportMaskPerViewNV[];" // GL_NVX_multiview_per_view_attributes
#endif
);
stageBuiltins[EShLangTessControl].append(
@@ -3481,6 +3657,14 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
"\n");
}
if ((profile != EEsProfile && version >= 140) ||
(profile == EEsProfile && version >= 310)) {
stageBuiltins[EShLangTessControl].append(
"in highp int gl_DeviceIndex;" // GL_EXT_device_group
"in highp int gl_ViewIndex;" // GL_EXT_multiview
"\n");
}
//============================================================================
//
// Define the interface to the tessellation evaluation shader.
@@ -3527,11 +3711,11 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
stageBuiltins[EShLangTessEvaluation].append(
"out int gl_ViewportIndex;"
"out int gl_Layer;"
"out int gl_ViewportMask[];"
"out vec4 gl_SecondaryPositionNV;"
"out int gl_SecondaryViewportMaskNV[];"
"out vec4 gl_PositionPerViewNV[];"
"out int gl_ViewportMaskPerViewNV[];"
"out int gl_ViewportMask[];" // GL_NV_viewport_array2
"out vec4 gl_SecondaryPositionNV;" // 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 int gl_ViewportMaskPerViewNV[];" // GL_NVX_multiview_per_view_attributes
);
#endif
@@ -3556,6 +3740,14 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
"\n");
}
if ((profile != EEsProfile && version >= 140) ||
(profile == EEsProfile && version >= 310)) {
stageBuiltins[EShLangTessEvaluation].append(
"in highp int gl_DeviceIndex;" // GL_EXT_device_group
"in highp int gl_ViewIndex;" // GL_EXT_multiview
"\n");
}
//============================================================================
//
// Define the interface to the fragment shader.
@@ -3713,6 +3905,14 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
"\n");
}
if ((profile != EEsProfile && version >= 140) ||
(profile == EEsProfile && version >= 310)) {
stageBuiltins[EShLangFragment].append(
"flat in highp int gl_DeviceIndex;" // GL_EXT_device_group
"flat in highp int gl_ViewIndex;" // GL_EXT_multiview
"\n");
}
// printf("%s\n", commonBuiltins.c_str());
// printf("%s\n", stageBuiltins[EShLangFragment].c_str());
}
@@ -3808,6 +4008,17 @@ void TBuiltIns::add2ndGenerationSamplingImaging(int version, EProfile profile, c
else {
addSamplingFunctions(sampler, typeName, version, profile);
addGatherFunctions(sampler, typeName, version, profile);
if (spvVersion.vulkan > 0 && sampler.dim == EsdBuffer && sampler.isCombined()) {
// Vulkan wants a textureBuffer to allow texelFetch() --
// a sampled image with no sampler.
// So, add sampling functions for both the
// samplerBuffer and textureBuffer types.
sampler.setTexture(sampler.type, sampler.dim, sampler.arrayed, sampler.shadow,
sampler.ms);
TString textureTypeName = sampler.getString();
addSamplingFunctions(sampler, textureTypeName, version, profile);
}
}
}
}
@@ -3831,7 +4042,7 @@ void TBuiltIns::add2ndGenerationSamplingImaging(int version, EProfile profile, c
//
// Add all the query functions for the given type.
//
void TBuiltIns::addQueryFunctions(TSampler sampler, TString& typeName, int version, EProfile profile)
void TBuiltIns::addQueryFunctions(TSampler sampler, const TString& typeName, int version, EProfile profile)
{
if (sampler.image && ((profile == EEsProfile && version < 310) || (profile != EEsProfile && version < 430)))
return;
@@ -3908,7 +4119,7 @@ void TBuiltIns::addQueryFunctions(TSampler sampler, TString& typeName, int versi
//
// Add all the image access functions for the given type.
//
void TBuiltIns::addImageFunctions(TSampler sampler, TString& typeName, int version, EProfile profile)
void TBuiltIns::addImageFunctions(TSampler sampler, const TString& typeName, int version, EProfile profile)
{
int dims = dimMap[sampler.dim];
// most things with an array add a dimension, except for cubemaps
@@ -4001,7 +4212,7 @@ void TBuiltIns::addImageFunctions(TSampler sampler, TString& typeName, int versi
//
// Add all the subpass access functions for the given type.
//
void TBuiltIns::addSubpassSampling(TSampler sampler, TString& typeName, int /*version*/, EProfile /*profile*/)
void TBuiltIns::addSubpassSampling(TSampler sampler, const TString& typeName, int /*version*/, EProfile /*profile*/)
{
stageBuiltins[EShLangFragment].append(prefixes[sampler.type]);
stageBuiltins[EShLangFragment].append("vec4 subpassLoad");
@@ -4018,7 +4229,7 @@ void TBuiltIns::addSubpassSampling(TSampler sampler, TString& typeName, int /*ve
//
// Add all the texture lookup functions for the given type.
//
void TBuiltIns::addSamplingFunctions(TSampler sampler, TString& typeName, int version, EProfile profile)
void TBuiltIns::addSamplingFunctions(TSampler sampler, const TString& typeName, int version, EProfile profile)
{
//
// texturing
@@ -4248,7 +4459,7 @@ void TBuiltIns::addSamplingFunctions(TSampler sampler, TString& typeName, int ve
//
// Add all the texture gather functions for the given type.
//
void TBuiltIns::addGatherFunctions(TSampler sampler, TString& typeName, int version, EProfile profile)
void TBuiltIns::addGatherFunctions(TSampler sampler, const TString& typeName, int version, EProfile profile)
{
switch (sampler.dim) {
case Esd2D:
@@ -4303,6 +4514,7 @@ void TBuiltIns::addGatherFunctions(TSampler sampler, TString& typeName, int vers
default:
break;
}
if (sparse)
s.append("ARB");
s.append("(");
@@ -4342,6 +4554,116 @@ void TBuiltIns::addGatherFunctions(TSampler sampler, TString& typeName, int vers
}
}
}
#ifdef AMD_EXTENSIONS
if (sampler.dim == EsdRect || sampler.shadow)
return;
if (profile == EEsProfile || version < 450)
return;
for (int bias = 0; bias < 2; ++bias) { // loop over presence of bias argument
for (int lod = 0; lod < 2; ++lod) { // loop over presence of lod argument
if ((lod && bias) || (lod == 0 && bias == 0))
continue;
for (int offset = 0; offset < 3; ++offset) { // loop over three forms of offset in the call name: none, Offset, and Offsets
for (int comp = 0; comp < 2; ++comp) { // loop over presence of comp argument
if (comp == 0 && bias)
continue;
if (offset > 0 && sampler.dim == EsdCube)
continue;
for (int sparse = 0; sparse <= 1; ++sparse) { // loop over "bool" sparse or not
if (sparse && (profile == EEsProfile || version < 450))
continue;
TString s;
// return type
if (sparse)
s.append("int ");
else {
s.append(prefixes[sampler.type]);
s.append("vec4 ");
}
// name
if (sparse)
s.append("sparseTextureGather");
else
s.append("textureGather");
if (lod)
s.append("Lod");
switch (offset) {
case 1:
s.append("Offset");
break;
case 2:
s.append("Offsets");
default:
break;
}
if (lod)
s.append("AMD");
else if (sparse)
s.append("ARB");
s.append("(");
// sampler type argument
s.append(typeName);
// P coordinate argument
s.append(",vec");
int totalDims = dimMap[sampler.dim] + (sampler.arrayed ? 1 : 0);
s.append(postfixes[totalDims]);
// lod argument
if (lod)
s.append(",float");
// offset argument
if (offset > 0) {
s.append(",ivec2");
if (offset == 2)
s.append("[4]");
}
// texel out (for sparse texture)
if (sparse) {
s.append(",out ");
s.append(prefixes[sampler.type]);
s.append("vec4 ");
}
// comp argument
if (comp)
s.append(",int");
// bias argument
if (bias)
s.append(",float");
s.append(");\n");
if (bias)
stageBuiltins[EShLangFragment].append(s);
else
commonBuiltins.append(s);
}
}
}
}
}
#endif
}
//
@@ -4469,8 +4791,8 @@ void TBuiltIns::initialize(const TBuiltInResource &resources, int version, EProf
"highp vec4 gl_Position;"
"highp float gl_PointSize;"
#ifdef NV_EXTENSIONS
"highp vec4 gl_SecondaryPositionNV;"
"highp vec4 gl_PositionPerViewNV[];"
"highp vec4 gl_SecondaryPositionNV;" // GL_NV_stereo_view_rendering
"highp vec4 gl_PositionPerViewNV[];" // GL_NVX_multiview_per_view_attributes
#endif
"} gl_in[gl_MaxPatchVertices];"
"\n");
@@ -4659,8 +4981,8 @@ void TBuiltIns::initialize(const TBuiltInResource &resources, int version, EProf
s.append(
"float gl_CullDistance[];"
#ifdef NV_EXTENSIONS
"vec4 gl_SecondaryPositionNV;"
"vec4 gl_PositionPerViewNV[];"
"vec4 gl_SecondaryPositionNV;" // GL_NV_stereo_view_rendering
"vec4 gl_PositionPerViewNV[];" // GL_NVX_multiview_per_view_attributes
#endif
);
s.append(
@@ -5127,13 +5449,29 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
// symbolTable.setVariableExtensions("gl_PointSize", Num_AEP_tessellation_point_size, AEP_tessellation_point_size);
//}
if ((profile != EEsProfile && version >= 140) ||
(profile == EEsProfile && version >= 310)) {
symbolTable.setVariableExtensions("gl_DeviceIndex", 1, &E_GL_EXT_device_group);
BuiltInVariable("gl_DeviceIndex", EbvDeviceIndex, symbolTable);
symbolTable.setVariableExtensions("gl_ViewIndex", 1, &E_GL_EXT_multiview);
BuiltInVariable("gl_ViewIndex", EbvViewIndex, symbolTable);
}
break;
case EShLangFragment:
SpecialQualifier("gl_FrontFacing", EvqFace, EbvFace, symbolTable);
SpecialQualifier("gl_FragCoord", EvqFragCoord, EbvFragCoord, symbolTable);
SpecialQualifier("gl_PointCoord", EvqPointCoord, EbvPointCoord, symbolTable);
SpecialQualifier("gl_FragColor", EvqFragColor, EbvFragColor, symbolTable);
if (spvVersion.spv == 0)
SpecialQualifier("gl_FragColor", EvqFragColor, EbvFragColor, symbolTable);
else {
TSymbol* symbol = symbolTable.find("gl_FragColor");
if (symbol) {
symbol->getWritableType().getQualifier().storage = EvqVaryingOut;
symbol->getWritableType().getQualifier().layoutLocation = 0;
}
}
SpecialQualifier("gl_FragDepth", EvqFragDepth, EbvFragDepth, symbolTable);
SpecialQualifier("gl_FragDepthEXT", EvqFragDepth, EbvFragDepth, symbolTable);
SpecialQualifier("gl_HelperInvocation", EvqVaryingIn, EbvHelperInvocation, symbolTable);
@@ -5325,6 +5663,16 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
BuiltInVariable("gl_BaryCoordSmoothSampleAMD", EbvBaryCoordSmoothSample, symbolTable);
BuiltInVariable("gl_BaryCoordPullModelAMD", EbvBaryCoordPullModel, symbolTable);
}
// E_GL_AMD_texture_gather_bias_lod
if (profile != EEsProfile) {
symbolTable.setFunctionExtensions("textureGatherLodAMD", 1, &E_GL_AMD_texture_gather_bias_lod);
symbolTable.setFunctionExtensions("textureGatherLodOffsetAMD", 1, &E_GL_AMD_texture_gather_bias_lod);
symbolTable.setFunctionExtensions("textureGatherLodOffsetsAMD", 1, &E_GL_AMD_texture_gather_bias_lod);
symbolTable.setFunctionExtensions("sparseTextureGatherLodAMD", 1, &E_GL_AMD_texture_gather_bias_lod);
symbolTable.setFunctionExtensions("sparseTextureGatherLodOffsetAMD", 1, &E_GL_AMD_texture_gather_bias_lod);
symbolTable.setFunctionExtensions("sparseTextureGatherLodOffsetsAMD", 1, &E_GL_AMD_texture_gather_bias_lod);
}
#endif
symbolTable.setVariableExtensions("gl_FragDepthEXT", 1, &E_GL_EXT_frag_depth);
@@ -5344,6 +5692,11 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
symbolTable.setFunctionExtensions("imageAtomicExchange", 1, &E_GL_OES_shader_image_atomic);
symbolTable.setFunctionExtensions("imageAtomicCompSwap", 1, &E_GL_OES_shader_image_atomic);
}
symbolTable.setVariableExtensions("gl_DeviceIndex", 1, &E_GL_EXT_device_group);
BuiltInVariable("gl_DeviceIndex", EbvDeviceIndex, symbolTable);
symbolTable.setVariableExtensions("gl_ViewIndex", 1, &E_GL_EXT_multiview);
BuiltInVariable("gl_ViewIndex", EbvViewIndex, symbolTable);
break;
case EShLangCompute:
@@ -5377,6 +5730,15 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
symbolTable.setFunctionExtensions("memoryBarrierShared", 1, &E_GL_ARB_compute_shader);
symbolTable.setFunctionExtensions("groupMemoryBarrier", 1, &E_GL_ARB_compute_shader);
}
if ((profile != EEsProfile && version >= 140) ||
(profile == EEsProfile && version >= 310)) {
symbolTable.setVariableExtensions("gl_DeviceIndex", 1, &E_GL_EXT_device_group);
BuiltInVariable("gl_DeviceIndex", EbvDeviceIndex, symbolTable);
symbolTable.setVariableExtensions("gl_ViewIndex", 1, &E_GL_EXT_multiview);
BuiltInVariable("gl_ViewIndex", EbvViewIndex, symbolTable);
}
break;
default:
@@ -5462,6 +5824,12 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
symbolTable.relateToOperator("doubleBitsToUint64", EOpDoubleBitsToUint64);
symbolTable.relateToOperator("int64BitsToDouble", EOpInt64BitsToDouble);
symbolTable.relateToOperator("uint64BitsToDouble", EOpUint64BitsToDouble);
#ifdef AMD_EXTENSIONS
symbolTable.relateToOperator("float16BitsToInt16", EOpFloat16BitsToInt16);
symbolTable.relateToOperator("float16BitsToUint16", EOpFloat16BitsToUint16);
symbolTable.relateToOperator("int16BitsToFloat16", EOpInt16BitsToFloat16);
symbolTable.relateToOperator("uint16BitsToFloat16", EOpUint16BitsToFloat16);
#endif
symbolTable.relateToOperator("packSnorm2x16", EOpPackSnorm2x16);
symbolTable.relateToOperator("unpackSnorm2x16", EOpUnpackSnorm2x16);
@@ -5485,6 +5853,16 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
symbolTable.relateToOperator("unpackUint2x32", EOpUnpackUint2x32);
#ifdef AMD_EXTENSIONS
symbolTable.relateToOperator("packInt2x16", EOpPackInt2x16);
symbolTable.relateToOperator("unpackInt2x16", EOpUnpackInt2x16);
symbolTable.relateToOperator("packUint2x16", EOpPackUint2x16);
symbolTable.relateToOperator("unpackUint2x16", EOpUnpackUint2x16);
symbolTable.relateToOperator("packInt4x16", EOpPackInt4x16);
symbolTable.relateToOperator("unpackInt4x16", EOpUnpackInt4x16);
symbolTable.relateToOperator("packUint4x16", EOpPackUint4x16);
symbolTable.relateToOperator("unpackUint4x16", EOpUnpackUint4x16);
symbolTable.relateToOperator("packFloat2x16", EOpPackFloat2x16);
symbolTable.relateToOperator("unpackFloat2x16", EOpUnpackFloat2x16);
#endif
@@ -5706,6 +6084,13 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
symbolTable.relateToOperator("cubeFaceIndexAMD", EOpCubeFaceIndex);
symbolTable.relateToOperator("cubeFaceCoordAMD", EOpCubeFaceCoord);
symbolTable.relateToOperator("timeAMD", EOpTime);
symbolTable.relateToOperator("textureGatherLodAMD", EOpTextureGatherLod);
symbolTable.relateToOperator("textureGatherLodOffsetAMD", EOpTextureGatherLodOffset);
symbolTable.relateToOperator("textureGatherLodOffsetsAMD", EOpTextureGatherLodOffsets);
symbolTable.relateToOperator("sparseTextureGatherLodAMD", EOpSparseTextureGatherLod);
symbolTable.relateToOperator("sparseTextureGatherLodOffsetAMD", EOpSparseTextureGatherLodOffset);
symbolTable.relateToOperator("sparseTextureGatherLodOffsetsAMD", EOpSparseTextureGatherLodOffsets);
#endif
}
}
@@ -94,11 +94,11 @@ public:
protected:
void add2ndGenerationSamplingImaging(int version, EProfile profile, const SpvVersion& spvVersion);
void addSubpassSampling(TSampler, TString& typeName, int version, EProfile profile);
void addQueryFunctions(TSampler, TString& typeName, int version, EProfile profile);
void addImageFunctions(TSampler, TString& typeName, int version, EProfile profile);
void addSamplingFunctions(TSampler, TString& typeName, int version, EProfile profile);
void addGatherFunctions(TSampler, TString& typeName, int version, EProfile profile);
void addSubpassSampling(TSampler, const TString& typeName, int version, EProfile profile);
void addQueryFunctions(TSampler, const TString& typeName, int version, EProfile profile);
void addImageFunctions(TSampler, const TString& typeName, int version, EProfile profile);
void addSamplingFunctions(TSampler, const TString& typeName, int version, EProfile profile);
void addGatherFunctions(TSampler, const TString& typeName, int version, EProfile profile);
// Helpers for making textual representations of the permutations
// of texturing/imaging functions.
@@ -130,8 +130,9 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn
}
// Convert the children's type shape to be compatible.
right = addShapeConversion(op, left->getType(), right);
left = addShapeConversion(op, right->getType(), left);
addBiShapeConversion(op, left, right);
if (left == nullptr || right == nullptr)
return nullptr;
//
// Need a new node holding things together. Make
@@ -147,8 +148,8 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn
// If they are both (non-specialization) constants, they must be folded.
// (Unless it's the sequence (comma) operator, but that's handled in addComma().)
//
TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion();
TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion();
TIntermConstantUnion *leftTempConstant = node->getLeft()->getAsConstantUnion();
TIntermConstantUnion *rightTempConstant = node->getRight()->getAsConstantUnion();
if (leftTempConstant && rightTempConstant) {
TIntermTyped* folded = leftTempConstant->fold(node->getOp(), rightTempConstant);
if (folded)
@@ -157,7 +158,7 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn
// If can propagate spec-constantness and if the operation is an allowed
// specialization-constant operation, make a spec-constant.
if (specConstantPropagates(*left, *right) && isSpecializationOperation(*node))
if (specConstantPropagates(*node->getLeft(), *node->getRight()) && isSpecializationOperation(*node))
node->getWritableType().getQualifier().makeSpecConstant();
return node;
@@ -238,7 +239,7 @@ TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TInterm
return nullptr;
// convert shape
right = addShapeConversion(op, left->getType(), right);
right = addUniShapeConversion(op, left->getType(), right);
// build the node
TIntermBinary* node = addBinaryNode(op, left, right, loc);
@@ -307,6 +308,10 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermTyped* child, TSo
case EOpConstructUint: newType = EbtUint; break;
case EOpConstructInt64: newType = EbtInt64; break;
case EOpConstructUint64: newType = EbtUint64; break;
#ifdef AMD_EXTENSIONS
case EOpConstructInt16: newType = EbtInt16; break;
case EOpConstructUint16: newType = EbtUint16; break;
#endif
case EOpConstructBool: newType = EbtBool; break;
case EOpConstructFloat: newType = EbtFloat; break;
case EOpConstructDouble: newType = EbtDouble; break;
@@ -335,6 +340,10 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermTyped* child, TSo
case EOpConstructUint:
case EOpConstructInt64:
case EOpConstructUint64:
#ifdef AMD_EXTENSIONS
case EOpConstructInt16:
case EOpConstructUint16:
#endif
case EOpConstructBool:
case EOpConstructFloat:
case EOpConstructDouble:
@@ -356,12 +365,12 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermTyped* child, TSo
node->updatePrecision();
// If it's a (non-specialization) constant, it must be folded.
if (child->getAsConstantUnion())
return child->getAsConstantUnion()->fold(op, node->getType());
if (node->getOperand()->getAsConstantUnion())
return node->getOperand()->getAsConstantUnion()->fold(op, node->getType());
// If it's a specialization constant, the result is too,
// if the operation is allowed for specialization constants.
if (child->getType().getQualifier().isSpecConstant() && isSpecializationOperation(*node))
if (node->getOperand()->getType().getQualifier().isSpecConstant() && isSpecializationOperation(*node))
node->getWritableType().getQualifier().makeSpecConstant();
return node;
@@ -527,6 +536,14 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
case EOpConstructUint64:
promoteTo = EbtUint64;
break;
#ifdef AMD_EXTENSIONS
case EOpConstructInt16:
promoteTo = EbtInt16;
break;
case EOpConstructUint16:
promoteTo = EbtUint16;
break;
#endif
//
// List all the binary ops that can implicitly convert one operand to the other's type;
@@ -615,15 +632,26 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
case EOpRightShiftAssign:
if ((type.getBasicType() == EbtInt ||
type.getBasicType() == EbtUint ||
#ifdef AMD_EXTENSIONS
type.getBasicType() == EbtInt16 ||
type.getBasicType() == EbtUint16 ||
#endif
type.getBasicType() == EbtInt64 ||
type.getBasicType() == EbtUint64) &&
(node->getType().getBasicType() == EbtInt ||
node->getType().getBasicType() == EbtUint ||
#ifdef AMD_EXTENSIONS
node->getType().getBasicType() == EbtInt16 ||
node->getType().getBasicType() == EbtUint16 ||
#endif
node->getType().getBasicType() == EbtInt64 ||
node->getType().getBasicType() == EbtUint64))
return node;
else
else if (source == EShSourceHlsl && node->getType().getBasicType() == EbtBool) {
promoteTo = type.getBasicType();
break;
} else
return nullptr;
default:
@@ -659,6 +687,10 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
#endif
case EbtInt64: newOp = EOpConvInt64ToDouble; break;
case EbtUint64: newOp = EOpConvUint64ToDouble; break;
#ifdef AMD_EXTENSIONS
case EbtInt16: newOp = EOpConvInt16ToDouble; break;
case EbtUint16: newOp = EOpConvUint16ToDouble; break;
#endif
default:
return nullptr;
}
@@ -674,6 +706,10 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
#endif
case EbtInt64: newOp = EOpConvInt64ToFloat; break;
case EbtUint64: newOp = EOpConvUint64ToFloat; break;
#ifdef AMD_EXTENSIONS
case EbtInt16: newOp = EOpConvInt16ToFloat; break;
case EbtUint16: newOp = EOpConvUint16ToFloat; break;
#endif
default:
return nullptr;
}
@@ -688,6 +724,8 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
case EbtDouble: newOp = EOpConvDoubleToFloat16; break;
case EbtInt64: newOp = EOpConvInt64ToFloat16; break;
case EbtUint64: newOp = EOpConvUint64ToFloat16; break;
case EbtInt16: newOp = EOpConvInt16ToFloat16; break;
case EbtUint16: newOp = EOpConvUint16ToFloat16; break;
default:
return nullptr;
}
@@ -704,6 +742,10 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
#endif
case EbtInt64: newOp = EOpConvInt64ToBool; break;
case EbtUint64: newOp = EOpConvUint64ToBool; break;
#ifdef AMD_EXTENSIONS
case EbtInt16: newOp = EOpConvInt16ToBool; break;
case EbtUint16: newOp = EOpConvUint16ToBool; break;
#endif
default:
return nullptr;
}
@@ -719,6 +761,10 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
#endif
case EbtInt64: newOp = EOpConvInt64ToInt; break;
case EbtUint64: newOp = EOpConvUint64ToInt; break;
#ifdef AMD_EXTENSIONS
case EbtInt16: newOp = EOpConvInt16ToInt; break;
case EbtUint16: newOp = EOpConvUint16ToInt; break;
#endif
default:
return nullptr;
}
@@ -734,6 +780,10 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
#endif
case EbtInt64: newOp = EOpConvInt64ToUint; break;
case EbtUint64: newOp = EOpConvUint64ToUint; break;
#ifdef AMD_EXTENSIONS
case EbtInt16: newOp = EOpConvInt16ToUint; break;
case EbtUint16: newOp = EOpConvUint16ToUint; break;
#endif
default:
return nullptr;
}
@@ -749,6 +799,10 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
case EbtFloat16: newOp = EOpConvFloat16ToInt64; break;
#endif
case EbtUint64: newOp = EOpConvUint64ToInt64; break;
#ifdef AMD_EXTENSIONS
case EbtInt16: newOp = EOpConvInt16ToInt64; break;
case EbtUint16: newOp = EOpConvUint16ToInt64; break;
#endif
default:
return nullptr;
}
@@ -764,10 +818,46 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
case EbtFloat16: newOp = EOpConvFloat16ToUint64; break;
#endif
case EbtInt64: newOp = EOpConvInt64ToUint64; break;
#ifdef AMD_EXTENSIONS
case EbtInt16: newOp = EOpConvInt16ToUint64; break;
case EbtUint16: newOp = EOpConvUint16ToUint64; break;
#endif
default:
return nullptr;
}
break;
#ifdef AMD_EXTENSIONS
case EbtInt16:
switch (node->getBasicType()) {
case EbtInt: newOp = EOpConvIntToInt16; break;
case EbtUint: newOp = EOpConvUintToInt16; break;
case EbtBool: newOp = EOpConvBoolToInt16; break;
case EbtFloat: newOp = EOpConvFloatToInt16; break;
case EbtDouble: newOp = EOpConvDoubleToInt16; break;
case EbtFloat16: newOp = EOpConvFloat16ToInt16; break;
case EbtInt64: newOp = EOpConvInt64ToInt16; break;
case EbtUint64: newOp = EOpConvUint64ToInt16; break;
case EbtUint16: newOp = EOpConvUint16ToInt16; break;
default:
return nullptr;
}
break;
case EbtUint16:
switch (node->getBasicType()) {
case EbtInt: newOp = EOpConvIntToUint16; break;
case EbtUint: newOp = EOpConvUintToUint16; break;
case EbtBool: newOp = EOpConvBoolToUint16; break;
case EbtFloat: newOp = EOpConvFloatToUint16; break;
case EbtDouble: newOp = EOpConvDoubleToUint16; break;
case EbtFloat16: newOp = EOpConvFloat16ToUint16; break;
case EbtInt64: newOp = EOpConvInt64ToUint16; break;
case EbtUint64: newOp = EOpConvUint64ToUint16; break;
case EbtInt16: newOp = EOpConvInt16ToUint16; break;
default:
return nullptr;
}
break;
#endif
default:
return nullptr;
}
@@ -785,7 +875,10 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
}
// Convert the node's shape of type for the given type, as allowed by the
// operation involved: 'op'.
// operation involved: 'op'. This is for situations where there is only one
// direction to consider doing the shape conversion.
//
// This implements policy, it call addShapeConversion() for the mechanism.
//
// Generally, the AST represents allowed GLSL shapes, so this isn't needed
// for GLSL. Bad shapes are caught in conversion or promotion.
@@ -793,7 +886,7 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
// Return 'node' if no conversion was done. Promotion handles final shape
// checking.
//
TIntermTyped* TIntermediate::addShapeConversion(TOperator op, const TType& type, TIntermTyped* node)
TIntermTyped* TIntermediate::addUniShapeConversion(TOperator op, const TType& type, TIntermTyped* node)
{
// some source languages don't do this
switch (source) {
@@ -806,23 +899,142 @@ TIntermTyped* TIntermediate::addShapeConversion(TOperator op, const TType& type,
// some operations don't do this
switch (op) {
case EOpFunctionCall:
case EOpReturn:
break;
case EOpMulAssign:
// want to support vector *= scalar native ops in AST and lower, not smear, similarly for
// matrix *= scalar, etc.
case EOpAddAssign:
case EOpSubAssign:
case EOpDivAssign:
case EOpAndAssign:
case EOpInclusiveOrAssign:
case EOpExclusiveOrAssign:
case EOpRightShiftAssign:
case EOpLeftShiftAssign:
if (node->getVectorSize() == 1)
return node;
break;
case EOpAssign:
break;
case EOpMix:
break;
default:
return node;
}
return addShapeConversion(type, node);
}
// Convert the nodes' shapes to be compatible for the operation 'op'.
//
// This implements policy, it call addShapeConversion() for the mechanism.
//
// Generally, the AST represents allowed GLSL shapes, so this isn't needed
// for GLSL. Bad shapes are caught in conversion or promotion.
//
void TIntermediate::addBiShapeConversion(TOperator op, TIntermTyped*& lhsNode, TIntermTyped*& rhsNode)
{
// some source languages don't do this
switch (source) {
case EShSourceHlsl:
break;
case EShSourceGlsl:
default:
return;
}
// some operations don't do this
// 'break' will mean attempt bidirectional conversion
switch (op) {
case EOpMulAssign:
case EOpAssign:
case EOpAddAssign:
case EOpSubAssign:
case EOpDivAssign:
case EOpAndAssign:
case EOpInclusiveOrAssign:
case EOpExclusiveOrAssign:
case EOpRightShiftAssign:
case EOpLeftShiftAssign:
// switch to unidirectional conversion (the lhs can't change)
rhsNode = addUniShapeConversion(op, lhsNode->getType(), rhsNode);
return;
case EOpAdd:
case EOpSub:
case EOpMul:
case EOpDiv:
// want to support vector * scalar native ops in AST and lower, not smear, similarly for
// matrix * vector, etc.
if (lhsNode->getVectorSize() == 1 || rhsNode->getVectorSize() == 1)
return;
break;
case EOpRightShift:
case EOpLeftShift:
// can natively support the right operand being a scalar and the left a vector,
// but not the reverse
if (rhsNode->getVectorSize() == 1)
return;
break;
case EOpLessThan:
case EOpGreaterThan:
case EOpLessThanEqual:
case EOpGreaterThanEqual:
case EOpEqual:
case EOpNotEqual:
case EOpFunctionCall:
case EOpReturn:
case EOpLogicalAnd:
case EOpLogicalOr:
case EOpLogicalXor:
case EOpAnd:
case EOpInclusiveOr:
case EOpExclusiveOr:
case EOpMix:
break;
default:
return node;
return;
}
// Do bidirectional conversions
if (lhsNode->getType().isScalarOrVec1() || rhsNode->getType().isScalarOrVec1()) {
if (lhsNode->getType().isScalarOrVec1())
lhsNode = addShapeConversion(rhsNode->getType(), lhsNode);
else
rhsNode = addShapeConversion(lhsNode->getType(), rhsNode);
}
lhsNode = addShapeConversion(rhsNode->getType(), lhsNode);
rhsNode = addShapeConversion(lhsNode->getType(), rhsNode);
}
// Convert the node's shape of type for the given type. It's not necessarily
// an error if they are different and not converted, as some operations accept
// mixed types. Promotion will do final shape checking.
//
// If there is a chance of two nodes, with conversions possible in each direction,
// the policy for what to ask for must be in the caller; this will do what is asked.
//
// Return 'node' if no conversion was done. Promotion handles final shape
// checking.
//
TIntermTyped* TIntermediate::addShapeConversion(const TType& type, TIntermTyped* node)
{
// no conversion needed
if (node->getType() == type)
return node;
// structures and arrays don't change shape, either to or from
if (node->getType().isStruct() || node->getType().isArray() ||
type.isStruct() || type.isArray())
@@ -831,12 +1043,12 @@ TIntermTyped* TIntermediate::addShapeConversion(TOperator op, const TType& type,
// The new node that handles the conversion
TOperator constructorOp = mapTypeToConstructorOp(type);
// scalar -> smeared -> vector, or
// vec1 -> scalar, or
// bigger vector -> smaller vector or scalar
if ((type.isVector() && node->getType().isScalar()) ||
(node->getType().isVector() && node->getVectorSize() == 1 && type.isScalar()) ||
(node->getVectorSize() > type.getVectorSize() && type.isVector()))
// scalar -> vector or vec1 -> vector or
// vector -> scalar or
// bigger vector -> smaller vector
if ((node->getType().isScalarOrVec1() && type.isVector()) ||
(node->getType().isVector() && type.isScalar()) ||
(node->isVector() && type.isVector() && node->getVectorSize() > type.getVectorSize()))
return setAggregateOperator(makeAggregate(node), constructorOp, type, node->getLoc());
return node;
@@ -894,6 +1106,10 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat
case EbtUint:
case EbtInt64:
case EbtUint64:
#ifdef AMD_EXTENSIONS
case EbtInt16:
case EbtUint16:
#endif
case EbtFloat:
case EbtDouble:
#ifdef AMD_EXTENSIONS
@@ -907,6 +1123,10 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat
switch (from) {
case EbtInt:
case EbtUint:
#ifdef AMD_EXTENSIONS
case EbtInt16:
case EbtUint16:
#endif
case EbtFloat:
#ifdef AMD_EXTENSIONS
case EbtFloat16:
@@ -920,8 +1140,12 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat
case EbtUint:
switch (from) {
case EbtInt:
return version >= 400;
return version >= 400 || (source == EShSourceHlsl);
case EbtUint:
#ifdef AMD_EXTENSIONS
case EbtInt16:
case EbtUint16:
#endif
return true;
case EbtBool:
return (source == EShSourceHlsl);
@@ -931,6 +1155,9 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat
case EbtInt:
switch (from) {
case EbtInt:
#ifdef AMD_EXTENSIONS
case EbtInt16:
#endif
return true;
case EbtBool:
return (source == EShSourceHlsl);
@@ -943,6 +1170,10 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat
case EbtUint:
case EbtInt64:
case EbtUint64:
#ifdef AMD_EXTENSIONS
case EbtInt16:
case EbtUint16:
#endif
return true;
default:
return false;
@@ -951,10 +1182,32 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat
switch (from) {
case EbtInt:
case EbtInt64:
#ifdef AMD_EXTENSIONS
case EbtInt16:
#endif
return true;
default:
return false;
}
#ifdef AMD_EXTENSIONS
case EbtFloat16:
switch (from) {
case EbtInt16:
case EbtUint16:
case EbtFloat16:
return true;
default:
return false;
}
case EbtUint16:
switch (from) {
case EbtInt16:
case EbtUint16:
return true;
default:
return false;
}
#endif
default:
return false;
}
@@ -1094,21 +1347,79 @@ TOperator TIntermediate::mapTypeToConstructorOp(const TType& type) const
break;
#endif
case EbtInt:
switch(type.getVectorSize()) {
case 1: op = EOpConstructInt; break;
case 2: op = EOpConstructIVec2; break;
case 3: op = EOpConstructIVec3; break;
case 4: op = EOpConstructIVec4; break;
default: break; // some compilers want this
if (type.getMatrixCols()) {
switch (type.getMatrixCols()) {
case 2:
switch (type.getMatrixRows()) {
case 2: op = EOpConstructIMat2x2; break;
case 3: op = EOpConstructIMat2x3; break;
case 4: op = EOpConstructIMat2x4; break;
default: break; // some compilers want this
}
break;
case 3:
switch (type.getMatrixRows()) {
case 2: op = EOpConstructIMat3x2; break;
case 3: op = EOpConstructIMat3x3; break;
case 4: op = EOpConstructIMat3x4; break;
default: break; // some compilers want this
}
break;
case 4:
switch (type.getMatrixRows()) {
case 2: op = EOpConstructIMat4x2; break;
case 3: op = EOpConstructIMat4x3; break;
case 4: op = EOpConstructIMat4x4; break;
default: break; // some compilers want this
}
break;
}
} else {
switch(type.getVectorSize()) {
case 1: op = EOpConstructInt; break;
case 2: op = EOpConstructIVec2; break;
case 3: op = EOpConstructIVec3; break;
case 4: op = EOpConstructIVec4; break;
default: break; // some compilers want this
}
}
break;
case EbtUint:
switch(type.getVectorSize()) {
case 1: op = EOpConstructUint; break;
case 2: op = EOpConstructUVec2; break;
case 3: op = EOpConstructUVec3; break;
case 4: op = EOpConstructUVec4; break;
default: break; // some compilers want this
if (type.getMatrixCols()) {
switch (type.getMatrixCols()) {
case 2:
switch (type.getMatrixRows()) {
case 2: op = EOpConstructUMat2x2; break;
case 3: op = EOpConstructUMat2x3; break;
case 4: op = EOpConstructUMat2x4; break;
default: break; // some compilers want this
}
break;
case 3:
switch (type.getMatrixRows()) {
case 2: op = EOpConstructUMat3x2; break;
case 3: op = EOpConstructUMat3x3; break;
case 4: op = EOpConstructUMat3x4; break;
default: break; // some compilers want this
}
break;
case 4:
switch (type.getMatrixRows()) {
case 2: op = EOpConstructUMat4x2; break;
case 3: op = EOpConstructUMat4x3; break;
case 4: op = EOpConstructUMat4x4; break;
default: break; // some compilers want this
}
break;
}
} else {
switch(type.getVectorSize()) {
case 1: op = EOpConstructUint; break;
case 2: op = EOpConstructUVec2; break;
case 3: op = EOpConstructUVec3; break;
case 4: op = EOpConstructUVec4; break;
default: break; // some compilers want this
}
}
break;
case EbtInt64:
@@ -1129,15 +1440,64 @@ TOperator TIntermediate::mapTypeToConstructorOp(const TType& type) const
default: break; // some compilers want this
}
break;
case EbtBool:
#ifdef AMD_EXTENSIONS
case EbtInt16:
switch(type.getVectorSize()) {
case 1: op = EOpConstructBool; break;
case 2: op = EOpConstructBVec2; break;
case 3: op = EOpConstructBVec3; break;
case 4: op = EOpConstructBVec4; break;
case 1: op = EOpConstructInt16; break;
case 2: op = EOpConstructI16Vec2; break;
case 3: op = EOpConstructI16Vec3; break;
case 4: op = EOpConstructI16Vec4; break;
default: break; // some compilers want this
}
break;
case EbtUint16:
switch(type.getVectorSize()) {
case 1: op = EOpConstructUint16; break;
case 2: op = EOpConstructU16Vec2; break;
case 3: op = EOpConstructU16Vec3; break;
case 4: op = EOpConstructU16Vec4; break;
default: break; // some compilers want this
}
break;
#endif
case EbtBool:
if (type.getMatrixCols()) {
switch (type.getMatrixCols()) {
case 2:
switch (type.getMatrixRows()) {
case 2: op = EOpConstructBMat2x2; break;
case 3: op = EOpConstructBMat2x3; break;
case 4: op = EOpConstructBMat2x4; break;
default: break; // some compilers want this
}
break;
case 3:
switch (type.getMatrixRows()) {
case 2: op = EOpConstructBMat3x2; break;
case 3: op = EOpConstructBMat3x3; break;
case 4: op = EOpConstructBMat3x4; break;
default: break; // some compilers want this
}
break;
case 4:
switch (type.getMatrixRows()) {
case 2: op = EOpConstructBMat4x2; break;
case 3: op = EOpConstructBMat4x3; break;
case 4: op = EOpConstructBMat4x4; break;
default: break; // some compilers want this
}
break;
}
} else {
switch(type.getVectorSize()) {
case 1: op = EOpConstructBool; break;
case 2: op = EOpConstructBVec2; break;
case 3: op = EOpConstructBVec3; break;
case 4: op = EOpConstructBVec4; break;
default: break; // some compilers want this
}
}
break;
default:
break;
}
@@ -1158,15 +1518,15 @@ TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* r
return nullptr;
TIntermAggregate* aggNode = nullptr;
if (left)
if (left != nullptr)
aggNode = left->getAsAggregate();
if (! aggNode || aggNode->getOp() != EOpNull) {
if (aggNode == nullptr || aggNode->getOp() != EOpNull) {
aggNode = new TIntermAggregate;
if (left)
if (left != nullptr)
aggNode->getSequence().push_back(left);
}
if (right)
if (right != nullptr)
aggNode->getSequence().push_back(right);
return aggNode;
@@ -1271,7 +1631,8 @@ TIntermTyped* TIntermediate::addMethod(TIntermTyped* object, const TType& type,
//
// For "?:" test nodes. There are three children; a condition,
// a true path, and a false path. The two paths are specified
// as separate parameters.
// as separate parameters. For vector 'cond', the true and false
// are not paths, but vectors to mix.
//
// Specialization constant operations include
// - The ternary operator ( ? : )
@@ -1300,14 +1661,39 @@ TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* true
return nullptr;
}
// Handle a vector condition as a mix
if (!cond->getType().isScalarOrVec1()) {
TType targetVectorType(trueBlock->getType().getBasicType(), EvqTemporary,
cond->getType().getVectorSize());
// smear true/false operands as needed
trueBlock = addUniShapeConversion(EOpMix, targetVectorType, trueBlock);
falseBlock = addUniShapeConversion(EOpMix, targetVectorType, falseBlock);
// After conversion, types have to match.
if (falseBlock->getType() != trueBlock->getType())
return nullptr;
// make the mix operation
TIntermAggregate* mix = makeAggregate(loc);
mix = growAggregate(mix, falseBlock);
mix = growAggregate(mix, trueBlock);
mix = growAggregate(mix, cond);
mix->setType(targetVectorType);
mix->setOp(EOpMix);
return mix;
}
// Now have a scalar condition...
// Convert true and false expressions to matching types
addBiShapeConversion(EOpMix, trueBlock, falseBlock);
// After conversion, types have to match.
if (falseBlock->getType() != trueBlock->getType())
return nullptr;
//
// See if all the operands are constant, then fold it otherwise not.
//
// Eliminate the selection when the condition is a scalar and all operands are constant.
if (cond->getAsConstantUnion() && trueBlock->getAsConstantUnion() && falseBlock->getAsConstantUnion()) {
if (cond->getAsConstantUnion()->getConstArray()[0].getBConst())
return trueBlock;
@@ -1381,6 +1767,24 @@ TIntermConstantUnion* TIntermediate::addConstantUnion(unsigned long long u64, co
return addConstantUnion(unionArray, TType(EbtUint64, EvqConst), loc, literal);
}
#ifdef AMD_EXTENSIONS
TIntermConstantUnion* TIntermediate::addConstantUnion(short i16, const TSourceLoc& loc, bool literal) const
{
TConstUnionArray unionArray(1);
unionArray[0].setIConst(i16);
return addConstantUnion(unionArray, TType(EbtInt16, EvqConst), loc, literal);
}
TIntermConstantUnion* TIntermediate::addConstantUnion(unsigned short u16, const TSourceLoc& loc, bool literal) const
{
TConstUnionArray unionArray(1);
unionArray[0].setUConst(u16);
return addConstantUnion(unionArray, TType(EbtUint16, EvqConst), loc, literal);
}
#endif
TIntermConstantUnion* TIntermediate::addConstantUnion(bool b, const TSourceLoc& loc, bool literal) const
{
TConstUnionArray unionArray(1);
@@ -1478,10 +1882,11 @@ const TIntermTyped* TIntermediate::findLValueBase(const TIntermTyped* node, bool
//
// Create while and do-while loop nodes.
//
TIntermLoop* TIntermediate::addLoop(TIntermNode* body, TIntermTyped* test, TIntermTyped* terminal, bool testFirst, const TSourceLoc& loc)
TIntermLoop* TIntermediate::addLoop(TIntermNode* body, TIntermTyped* test, TIntermTyped* terminal, bool testFirst, const TSourceLoc& loc, TLoopControl control)
{
TIntermLoop* node = new TIntermLoop(body, test, terminal, testFirst);
node->setLoc(loc);
node->setLoopControl(control);
return node;
}
@@ -1489,13 +1894,19 @@ TIntermLoop* TIntermediate::addLoop(TIntermNode* body, TIntermTyped* test, TInte
//
// Create a for-loop sequence.
//
TIntermAggregate* TIntermediate::addForLoop(TIntermNode* body, TIntermNode* initializer, TIntermTyped* test, TIntermTyped* terminal, bool testFirst, const TSourceLoc& loc)
TIntermAggregate* TIntermediate::addForLoop(TIntermNode* body, TIntermNode* initializer, TIntermTyped* test, TIntermTyped* terminal, bool testFirst, const TSourceLoc& loc, TLoopControl control)
{
TIntermLoop* node = new TIntermLoop(body, test, terminal, testFirst);
node->setLoc(loc);
node->setLoopControl(control);
// make a sequence of the initializer and statement
TIntermAggregate* loopSequence = makeAggregate(initializer, loc);
// make a sequence of the initializer and statement, but try to reuse the
// aggregate already created for whatever is in the initializer, if there is one
TIntermAggregate* loopSequence = (initializer == nullptr ||
initializer->getAsAggregate() == nullptr) ? makeAggregate(initializer, loc)
: initializer->getAsAggregate();
if (loopSequence != nullptr && loopSequence->getOp() == EOpSequence)
loopSequence->setOp(EOpNull);
loopSequence = growAggregate(loopSequence, node);
loopSequence->setOperator(EOpSequence);
@@ -1535,6 +1946,14 @@ bool TIntermediate::postProcess(TIntermNode* root, EShLanguage /*language*/)
// Propagate 'noContraction' label in backward from 'precise' variables.
glslang::PropagateNoContraction(*this);
switch (textureSamplerTransformMode) {
case EShTexSampTransKeep:
break;
case EShTexSampTransUpgradeTextureRemoveSampler:
performTextureUpgradeAndSamplerRemovalTransformation(root);
break;
}
return true;
}
@@ -1725,6 +2144,30 @@ bool TIntermediate::isSpecializationOperation(const TIntermOperator& node) const
case EOpConvUintToInt64:
case EOpConvUint64ToInt:
case EOpConvIntToUint64:
#ifdef AMD_EXTENSIONS
case EOpConvInt16ToBool:
case EOpConvBoolToInt16:
case EOpConvInt16ToInt:
case EOpConvIntToInt16:
case EOpConvInt16ToUint:
case EOpConvUintToInt16:
case EOpConvInt16ToInt64:
case EOpConvInt64ToInt16:
case EOpConvInt16ToUint64:
case EOpConvUint64ToInt16:
case EOpConvUint16ToBool:
case EOpConvBoolToUint16:
case EOpConvUint16ToInt:
case EOpConvIntToUint16:
case EOpConvUint16ToUint:
case EOpConvUintToUint16:
case EOpConvUint16ToInt64:
case EOpConvInt64ToUint16:
case EOpConvUint16ToUint64:
case EOpConvUint64ToUint16:
case EOpConvInt16ToUint16:
case EOpConvUint16ToInt16:
#endif
// unary operations
case EOpNegative:
@@ -1853,6 +2296,10 @@ bool TIntermediate::promoteUnary(TIntermUnary& node)
case EOpBitwiseNot:
if (operand->getBasicType() != EbtInt &&
operand->getBasicType() != EbtUint &&
#ifdef AMD_EXTENSIONS
operand->getBasicType() != EbtInt16 &&
operand->getBasicType() != EbtUint16 &&
#endif
operand->getBasicType() != EbtInt64 &&
operand->getBasicType() != EbtUint64)
@@ -1867,6 +2314,10 @@ bool TIntermediate::promoteUnary(TIntermUnary& node)
operand->getBasicType() != EbtUint &&
operand->getBasicType() != EbtInt64 &&
operand->getBasicType() != EbtUint64 &&
#ifdef AMD_EXTENSIONS
operand->getBasicType() != EbtInt16 &&
operand->getBasicType() != EbtUint16 &&
#endif
operand->getBasicType() != EbtFloat &&
#ifdef AMD_EXTENSIONS
operand->getBasicType() != EbtFloat16 &&
@@ -1967,6 +2418,42 @@ bool TIntermediate::promoteBinary(TIntermBinary& node)
// We now have only scalars, vectors, and matrices to worry about.
//
// HLSL implicitly promotes bool -> int for numeric operations.
// (Implicit conversions to make the operands match each other's types were already done.)
if (getSource() == EShSourceHlsl &&
(left->getBasicType() == EbtBool || right->getBasicType() == EbtBool)) {
switch (op) {
case EOpLessThan:
case EOpGreaterThan:
case EOpLessThanEqual:
case EOpGreaterThanEqual:
case EOpRightShift:
case EOpLeftShift:
case EOpMod:
case EOpAnd:
case EOpInclusiveOr:
case EOpExclusiveOr:
case EOpAdd:
case EOpSub:
case EOpDiv:
case EOpMul:
left = addConversion(op, TType(EbtInt, EvqTemporary, left->getVectorSize()), left);
right = addConversion(op, TType(EbtInt, EvqTemporary, right->getVectorSize()), right);
if (left == nullptr || right == nullptr)
return false;
node.setLeft(left);
node.setRight(right);
break;
default:
break;
}
}
// Do general type checks against individual operands (comparing left and right is coming up, checking mixed shapes after that)
switch (op) {
case EOpLessThan:
@@ -2037,8 +2524,14 @@ bool TIntermediate::promoteBinary(TIntermBinary& node)
// Check for integer-only operands.
if ((left->getBasicType() != EbtInt && left->getBasicType() != EbtUint &&
left->getBasicType() != EbtInt64 && left->getBasicType() != EbtUint64) ||
#ifdef AMD_EXTENSIONS
left->getBasicType() != EbtInt16 && left->getBasicType() != EbtUint16 &&
#endif
left->getBasicType() != EbtInt64 && left->getBasicType() != EbtUint64) ||
(right->getBasicType() != EbtInt && right->getBasicType() != EbtUint &&
#ifdef AMD_EXTENSIONS
right->getBasicType() != EbtInt16 && right->getBasicType() != EbtUint16 &&
#endif
right->getBasicType() != EbtInt64 && right->getBasicType() != EbtUint64))
return false;
if (left->isMatrix() || right->isMatrix())
@@ -2079,8 +2572,6 @@ bool TIntermediate::promoteBinary(TIntermBinary& node)
case EOpLogicalXor:
return left->getType() == right->getType();
// no shifts: they can mix types (scalar int can shift a vector uint, etc.)
case EOpMod:
case EOpModAssign:
@@ -2094,6 +2585,7 @@ bool TIntermediate::promoteBinary(TIntermBinary& node)
case EOpAdd:
case EOpSub:
case EOpDiv:
case EOpAddAssign:
case EOpSubAssign:
case EOpDivAssign:
@@ -2118,7 +2610,7 @@ bool TIntermediate::promoteBinary(TIntermBinary& node)
return true;
// Finish handling the case, for all ops, where there are two vectors of different sizes
if (left->isVector() && right->isVector() && left->getVectorSize() != right->getVectorSize())
if (left->isVector() && right->isVector() && left->getVectorSize() != right->getVectorSize() && right->getVectorSize() > 1)
return false;
//
@@ -2667,4 +3159,41 @@ bool TIntermediate::specConstantPropagates(const TIntermTyped& node1, const TInt
(node2.getType().getQualifier().isSpecConstant() && node1.getType().getQualifier().isConstant());
}
struct TextureUpgradeAndSamplerRemovalTransform : public TIntermTraverser {
bool visitAggregate(TVisit, TIntermAggregate* ag) override {
using namespace std;
TIntermSequence& seq = ag->getSequence();
// remove pure sampler variables
TIntermSequence::iterator newEnd = remove_if(seq.begin(), seq.end(), [](TIntermNode* node) {
TIntermSymbol* symbol = node->getAsSymbolNode();
if (!symbol)
return false;
return (symbol->getBasicType() == EbtSampler && symbol->getType().getSampler().isPureSampler());
});
seq.erase(newEnd, seq.end());
// replace constructors with sampler/textures
// update textures into sampled textures
for_each(seq.begin(), seq.end(), [](TIntermNode*& node) {
TIntermSymbol* symbol = node->getAsSymbolNode();
if (!symbol) {
TIntermAggregate *constructor = node->getAsAggregate();
if (constructor && constructor->getOp() == EOpConstructTextureSampler) {
if (!constructor->getSequence().empty())
node = constructor->getSequence()[0];
}
} else if (symbol->getBasicType() == EbtSampler && symbol->getType().getSampler().isTexture()) {
symbol->getWritableType().getSampler().combined = true;
}
});
return true;
}
};
void TIntermediate::performTextureUpgradeAndSamplerRemovalTransformation(TIntermNode* root)
{
TextureUpgradeAndSamplerRemovalTransform transform;
root->traverse(&transform);
}
} // end namespace glslang
@@ -33,6 +33,8 @@
// POSSIBILITY OF SUCH DAMAGE.
//
#pragma once
#include "../Include/Common.h"
#include "reflection.h"
#include "localintermediate.h"
@@ -226,7 +226,8 @@ void TParseContextBase::rValueErrorCheck(const TSourceLoc& loc, const char* op,
// Add 'symbol' to the list of deferred linkage symbols, which
// are later processed in finish(), at which point the symbol
// must still be valid.
// It is okay if the symbol's type will be subsequently edited.
// It is okay if the symbol's type will be subsequently edited;
// the modifications will be tracked.
void TParseContextBase::trackLinkage(TSymbol& symbol)
{
if (!parsingBuiltins)
@@ -530,21 +531,20 @@ void TParseContextBase::parseSwizzleSelector(const TSourceLoc& loc, const TStrin
// Make the passed-in variable information become a member of the
// global uniform block. If this doesn't exist yet, make it.
//
void TParseContextBase::growGlobalUniformBlock(TSourceLoc& loc, TType& memberType, TString& memberName, TTypeList* typeList)
void TParseContextBase::growGlobalUniformBlock(const TSourceLoc& loc, TType& memberType, const TString& memberName, TTypeList* typeList)
{
// make the global block, if not yet made
// Make the global block, if not yet made.
if (globalUniformBlock == nullptr) {
TString& blockName = *NewPoolTString(getGlobalUniformBlockName());
TQualifier blockQualifier;
blockQualifier.clear();
blockQualifier.storage = EvqUniform;
TType blockType(new TTypeList, blockName, blockQualifier);
TString* instanceName = NewPoolTString("");
globalUniformBlock = new TVariable(instanceName, blockType, true);
TType blockType(new TTypeList, *NewPoolTString(getGlobalUniformBlockName()), blockQualifier);
setUniformBlockDefaults(blockType);
globalUniformBlock = new TVariable(NewPoolTString(""), blockType, true);
firstNewMember = 0;
}
// add the requested member as a member to the block
// Add the requested member as a member to the global block.
TType* type = new TType;
type->shallowCopy(memberType);
type->setFieldName(memberName);
@@ -552,36 +552,20 @@ void TParseContextBase::growGlobalUniformBlock(TSourceLoc& loc, TType& memberTyp
type->setStruct(typeList);
TTypeLoc typeLoc = {type, loc};
globalUniformBlock->getType().getWritableStruct()->push_back(typeLoc);
}
//
// Insert into the symbol table the global uniform block created in
// growGlobalUniformBlock(). The variables added as members won't be
// found unless this is done.
//
bool TParseContextBase::insertGlobalUniformBlock()
{
if (globalUniformBlock == nullptr)
return true;
int numMembers = (int)globalUniformBlock->getType().getStruct()->size();
bool inserted = false;
// Insert into the symbol table.
if (firstNewMember == 0) {
// This is the first request; we need a normal symbol table insert
inserted = symbolTable.insert(*globalUniformBlock);
if (inserted)
if (symbolTable.insert(*globalUniformBlock))
trackLinkage(*globalUniformBlock);
} else if (firstNewMember <= numMembers) {
else
error(loc, "failed to insert the global constant buffer", "uniform", "");
} else {
// This is a follow-on request; we need to amend the first insert
inserted = symbolTable.amend(*globalUniformBlock, firstNewMember);
symbolTable.amend(*globalUniformBlock, firstNewMember);
}
if (inserted) {
finalizeGlobalUniformBlockLayout(*globalUniformBlock);
firstNewMember = numMembers;
}
return inserted;
++firstNewMember;
}
void TParseContextBase::finish()
@@ -51,8 +51,8 @@ TParseContext::TParseContext(TSymbolTable& symbolTable, TIntermediate& interm, b
int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language,
TInfoSink& infoSink, bool forwardCompatible, EShMessages messages) :
TParseContextBase(symbolTable, interm, parsingBuiltins, version, profile, spvVersion, language, infoSink, forwardCompatible, messages),
contextPragma(true, false), loopNestingLevel(0), structNestingLevel(0), controlFlowNestingLevel(0), statementNestingLevel(0),
inMain(false), postMainReturn(false), currentFunctionType(nullptr), blockName(nullptr),
inMain(false),
blockName(nullptr),
limits(resources.limits),
atomicUintOffsets(nullptr), anyIndexLimits(false)
{
@@ -255,6 +255,10 @@ void TParseContext::handlePragma(const TSourceLoc& loc, const TVector<TString>&
error(loc, "\")\" expected to end 'debug' pragma", "#pragma", "");
return;
}
} else if (spvVersion.spv > 0 && tokens[0].compare("use_storage_buffer") == 0) {
if (tokens.size() != 1)
error(loc, "extra tokens", "#pragma", "");
intermediate.setUseStorageBuffer();
}
}
@@ -342,10 +346,8 @@ TIntermTyped* TParseContext::handleBracketDereference(const TSourceLoc& loc, TIn
TIntermTyped* result = nullptr;
int indexValue = 0;
if (index->getQualifier().isFrontEndConstant()) {
if (index->getQualifier().isFrontEndConstant())
indexValue = index->getAsConstantUnion()->getConstArray()[0].getIConst();
checkIndex(loc, base->getType(), indexValue);
}
variableCheck(base);
if (! base->isArray() && ! base->isMatrix() && ! base->isVector()) {
@@ -353,10 +355,12 @@ TIntermTyped* TParseContext::handleBracketDereference(const TSourceLoc& loc, TIn
error(loc, " left of '[' is not of type array, matrix, or vector ", base->getAsSymbolNode()->getName().c_str(), "");
else
error(loc, " left of '[' is not of type array, matrix, or vector ", "expression", "");
} else if (base->getType().getQualifier().isFrontEndConstant() && index->getQualifier().isFrontEndConstant())
} else if (base->getType().getQualifier().isFrontEndConstant() && index->getQualifier().isFrontEndConstant()) {
// both base and index are front-end constants
checkIndex(loc, base->getType(), indexValue);
return intermediate.foldDereference(base, indexValue, loc);
else {
// at least one of base and index is variable...
} else {
// at least one of base and index is not a front-end constant variable...
if (base->getAsSymbolNode() && isIoResizeArray(base->getType()))
handleIoResizeArrayAccess(loc, base);
@@ -364,6 +368,8 @@ TIntermTyped* TParseContext::handleBracketDereference(const TSourceLoc& loc, TIn
if (index->getQualifier().isFrontEndConstant()) {
if (base->getType().isImplicitlySizedArray())
updateImplicitArraySize(loc, base, indexValue);
else
checkIndex(loc, base->getType(), indexValue);
result = intermediate.addIndex(EOpIndexDirect, base, index, loc);
} else {
if (base->getType().isImplicitlySizedArray()) {
@@ -906,7 +912,7 @@ TIntermAggregate* TParseContext::handleFunctionDefinition(const TSourceLoc& loc,
loopNestingLevel = 0;
statementNestingLevel = 0;
controlFlowNestingLevel = 0;
postMainReturn = false;
postEntryPointReturn = false;
return paramNodes;
}
@@ -1187,7 +1193,7 @@ void TParseContext::checkLocation(const TSourceLoc& loc, TOperator op)
error(loc, "tessellation control barrier() cannot be placed within flow control", "", "");
if (! inMain)
error(loc, "tessellation control barrier() must be in main()", "", "");
else if (postMainReturn)
else if (postEntryPointReturn)
error(loc, "tessellation control barrier() cannot be placed after a return from main()", "", "");
}
break;
@@ -1436,9 +1442,56 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan
error(loc, "must be a compile-time constant:", feature, "component argument");
}
#ifdef AMD_EXTENSIONS
bool bias = false;
if (callNode.getOp() == EOpTextureGather)
bias = fnCandidate.getParamCount() > 3;
else if (callNode.getOp() == EOpTextureGatherOffset ||
callNode.getOp() == EOpTextureGatherOffsets)
bias = fnCandidate.getParamCount() > 4;
if (bias) {
TString biasFeatureString = fnCandidate.getName() + "with bias argument";
const char* feature = biasFeatureString.c_str();
profileRequires(loc, ~EEsProfile, 450, nullptr, feature);
requireExtensions(loc, 1, &E_GL_AMD_texture_gather_bias_lod, feature);
}
#endif
break;
}
#ifdef AMD_EXTENSIONS
case EOpSparseTextureGather:
case EOpSparseTextureGatherOffset:
case EOpSparseTextureGatherOffsets:
{
bool bias = false;
if (callNode.getOp() == EOpSparseTextureGather)
bias = fnCandidate.getParamCount() > 4;
else if (callNode.getOp() == EOpSparseTextureGatherOffset ||
callNode.getOp() == EOpSparseTextureGatherOffsets)
bias = fnCandidate.getParamCount() > 5;
if (bias) {
TString featureString = fnCandidate.getName() + "with bias argument";
const char* feature = featureString.c_str();
profileRequires(loc, ~EEsProfile, 450, nullptr, feature);
requireExtensions(loc, 1, &E_GL_AMD_texture_gather_bias_lod, feature);
}
break;
}
case EOpSparseTextureGatherLod:
case EOpSparseTextureGatherLodOffset:
case EOpSparseTextureGatherLodOffsets:
{
requireExtensions(loc, 1, &E_GL_ARB_sparse_texture2, fnCandidate.getName().c_str());
break;
}
#endif
case EOpTextureOffset:
case EOpTextureFetchOffset:
case EOpTextureProjOffset:
@@ -2096,6 +2149,17 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T
case EOpConstructDMat4x2:
case EOpConstructDMat4x3:
case EOpConstructDMat4x4:
#ifdef AMD_EXTENSIONS
case EOpConstructF16Mat2x2:
case EOpConstructF16Mat2x3:
case EOpConstructF16Mat2x4:
case EOpConstructF16Mat3x2:
case EOpConstructF16Mat3x3:
case EOpConstructF16Mat3x4:
case EOpConstructF16Mat4x2:
case EOpConstructF16Mat4x3:
case EOpConstructF16Mat4x4:
#endif
constructingMatrix = true;
break;
default:
@@ -2156,6 +2220,10 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T
case EOpConstructUint:
case EOpConstructInt64:
case EOpConstructUint64:
#ifdef AMD_EXTENSIONS
case EOpConstructInt16:
case EOpConstructUint16:
#endif
case EOpConstructBool:
case EOpConstructBVec2:
case EOpConstructBVec3:
@@ -2172,6 +2240,14 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T
case EOpConstructU64Vec2:
case EOpConstructU64Vec3:
case EOpConstructU64Vec4:
#ifdef AMD_EXTENSIONS
case EOpConstructI16Vec2:
case EOpConstructI16Vec3:
case EOpConstructI16Vec4:
case EOpConstructU16Vec2:
case EOpConstructU16Vec3:
case EOpConstructU16Vec4:
#endif
// This was the list of valid ones, if they aren't converting from float
// and aren't making an array.
makeSpecConst = ! floatArgument && ! type.isArray();
@@ -2464,6 +2540,9 @@ void TParseContext::globalQualifierTypeCheck(const TSourceLoc& loc, const TQuali
}
if (publicType.basicType == EbtInt || publicType.basicType == EbtUint ||
#ifdef AMD_EXTENSIONS
publicType.basicType == EbtInt16 || publicType.basicType == EbtUint16 ||
#endif
publicType.basicType == EbtInt64 || publicType.basicType == EbtUint64 ||
publicType.basicType == EbtDouble)
profileRequires(loc, EEsProfile, 300, nullptr, "shader input/output");
@@ -2474,6 +2553,9 @@ void TParseContext::globalQualifierTypeCheck(const TSourceLoc& loc, const TQuali
if (!qualifier.flat) {
#endif
if (publicType.basicType == EbtInt || publicType.basicType == EbtUint ||
#ifdef AMD_EXTENSIONS
publicType.basicType == EbtInt16 || publicType.basicType == EbtUint16 ||
#endif
publicType.basicType == EbtInt64 || publicType.basicType == EbtUint64 ||
publicType.basicType == EbtDouble ||
(publicType.userDef && (publicType.userDef->containsBasicType(EbtInt) ||
@@ -2894,7 +2976,7 @@ void TParseContext::structArrayCheck(const TSourceLoc& /*loc*/, const TType& typ
}
}
void TParseContext::arrayUnsizedCheck(const TSourceLoc& loc, const TQualifier& qualifier, const TArraySizes* arraySizes, bool initializer, bool lastMember)
void TParseContext::arraySizesCheck(const TSourceLoc& loc, const TQualifier& qualifier, const TArraySizes* arraySizes, bool initializer, bool lastMember)
{
assert(arraySizes);
@@ -2906,10 +2988,13 @@ void TParseContext::arrayUnsizedCheck(const TSourceLoc& loc, const TQualifier& q
if (initializer)
return;
// No environment lets any non-outer-dimension that's to be implicitly sized
// No environment allows any non-outer-dimension to be implicitly sized
if (arraySizes->isInnerImplicit())
error(loc, "only outermost dimension of an array of arrays can be implicitly sized", "[]", "");
if (arraySizes->isInnerSpecialization())
error(loc, "only outermost dimension of an array of arrays can be a specialization constant", "[]", "");
// desktop always allows outer-dimension-unsized variable arrays,
if (profile != EEsProfile)
return;
@@ -2990,7 +3075,7 @@ void TParseContext::arrayDimMerge(TType& type, const TArraySizes* sizes)
// Do all the semantic checking for declaring or redeclaring an array, with and
// without a size, and make the right changes to the symbol table.
//
void TParseContext::declareArray(const TSourceLoc& loc, TString& identifier, const TType& type, TSymbol*& symbol)
void TParseContext::declareArray(const TSourceLoc& loc, const TString& identifier, const TType& type, TSymbol*& symbol)
{
if (symbol == nullptr) {
bool currentScope;
@@ -4196,6 +4281,10 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi
if (id.compare(0, 11, "local_size_") == 0) {
profileRequires(loc, EEsProfile, 310, 0, "gl_WorkGroupSize");
profileRequires(loc, ~EEsProfile, 430, E_GL_ARB_compute_shader, "gl_WorkGroupSize");
if (id.size() == 12 && value == 0) {
error(loc, "must be at least 1", id.c_str(), "");
return;
}
if (id == "local_size_x") {
publicType.shaderQualifiers.localSize[0] = value;
return;
@@ -4246,7 +4335,6 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi
// This is also true for overriding layout-qualifier-names, where one
// overrides the other (e.g., row_major vs. column_major); only the last
// occurrence has any effect."
//
void TParseContext::mergeObjectLayoutQualifiers(TQualifier& dst, const TQualifier& src, bool inheritOnly)
{
if (src.hasMatrix())
@@ -4328,6 +4416,25 @@ void TParseContext::layoutObjectCheck(const TSourceLoc& loc, const TSymbol& symb
}
}
// user-variable location check, which are required for SPIR-V in/out:
// - variables have it directly,
// - blocks have it on each member (already enforced), so check first one
if (spvVersion.spv > 0 && !parsingBuiltins && qualifier.builtIn == EbvNone &&
!qualifier.hasLocation() && !intermediate.getAutoMapLocations()) {
switch (qualifier.storage) {
case EvqVaryingIn:
case EvqVaryingOut:
if (type.getBasicType() != EbtBlock ||
(!(*type.getStruct())[0].type->getQualifier().hasLocation() &&
(*type.getStruct())[0].type->getQualifier().builtIn == EbvNone))
error(loc, "SPIR-V requires location for user input/output", "location", "");
break;
default:
break;
}
}
// Check packing and matrix
if (qualifier.hasUniformLayout()) {
switch (qualifier.storage) {
@@ -4355,6 +4462,22 @@ void TParseContext::layoutObjectCheck(const TSourceLoc& loc, const TSymbol& symb
}
}
// "For some blocks declared as arrays, the location can only be applied at the block level:
// When a block is declared as an array where additional locations are needed for each member
// for each block array element, it is a compile-time error to specify locations on the block
// members. That is, when locations would be under specified by applying them on block members,
// they are not allowed on block members. For arrayed interfaces (those generally having an
// extra level of arrayness due to interface expansion), the outer array is stripped before
// applying this rule."
void TParseContext::layoutMemberLocationArrayCheck(const TSourceLoc& loc, bool memberWithLocation, TArraySizes* arraySizes)
{
if (memberWithLocation && arraySizes != nullptr) {
if (arraySizes->getNumDims() > (currentBlockQualifier.isArrayedIo(language) ? 1 : 0))
error(loc, "cannot use in a block array where new locations are needed for each block element",
"location", "");
}
}
// Do layout error checking with respect to a type.
void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type)
{
@@ -4500,7 +4623,7 @@ void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type)
}
}
} else if (type.isImage() && ! qualifier.writeonly) {
const char *explanation = "image variables declared 'writeonly' without a format layout qualifier";
const char *explanation = "image variables not declared 'writeonly' and without a format layout qualifier";
requireProfile(loc, ECoreProfile | ECompatibilityProfile, explanation);
profileRequires(loc, ECoreProfile | ECompatibilityProfile, 0, E_GL_EXT_shader_image_load_formatted, explanation);
}
@@ -4529,6 +4652,10 @@ void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type)
case EbtUint:
case EbtInt64:
case EbtUint64:
#ifdef AMD_EXTENSIONS
case EbtInt16:
case EbtUint16:
#endif
case EbtBool:
case EbtFloat:
case EbtDouble:
@@ -4692,12 +4819,8 @@ void TParseContext::fixOffset(const TSourceLoc& loc, TSymbol& symbol)
if (symbol.getType().isExplicitlySizedArray())
numOffsets *= symbol.getType().getCumulativeArraySize();
else {
// TODO: functionality: implicitly-sized atomic_uint arrays.
// We don't know the full size until later. This might
// be a specification problem, will report to Khronos. For the
// cases that is not true, the rest of the checking would need
// to be done at link time instead of compile time.
warn(loc, "implicitly sized atomic_uint array treated as having one element for tracking the default offset", "atomic_uint", "");
// "It is a compile-time error to declare an unsized array of atomic_uint."
error(loc, "array must be explicitly sized", "atomic_uint", "");
}
}
int repeated = intermediate.addUsedOffsets(qualifier.layoutBinding, offset, numOffsets);
@@ -4983,7 +5106,7 @@ TIntermNode* TParseContext::declareVariable(const TSourceLoc& loc, TString& iden
arrayDimMerge(type, arraySizes);
// Check that implicit sizing is only where allowed.
arrayUnsizedCheck(loc, type.getQualifier(), &type.getArraySizes(), initializer != nullptr, false);
arraySizesCheck(loc, type.getQualifier(), &type.getArraySizes(), initializer != nullptr, false);
if (! arrayQualifierError(loc, type.getQualifier()) && ! arrayError(loc, type))
declareArray(loc, identifier, type, symbol);
@@ -5016,6 +5139,8 @@ TIntermNode* TParseContext::declareVariable(const TSourceLoc& loc, TString& iden
// look for errors in layout qualifier use
layoutObjectCheck(loc, *symbol);
// fix up
fixOffset(loc, *symbol);
return initNode;
@@ -5053,7 +5178,7 @@ TVariable* TParseContext::makeInternalVariable(const char* name, const TType& ty
//
// Return the successfully declared variable.
//
TVariable* TParseContext::declareNonArray(const TSourceLoc& loc, TString& identifier, TType& type)
TVariable* TParseContext::declareNonArray(const TSourceLoc& loc, const TString& identifier, const TType& type)
{
// make a new variable
TVariable* variable = new TVariable(&identifier, type);
@@ -5477,6 +5602,22 @@ TIntermTyped* TParseContext::constructBuiltIn(const TType& type, TOperator op, T
basicOp = EOpConstructUint64;
break;
#ifdef AMD_EXTENSIONS
case EOpConstructI16Vec2:
case EOpConstructI16Vec3:
case EOpConstructI16Vec4:
case EOpConstructInt16:
basicOp = EOpConstructInt16;
break;
case EOpConstructU16Vec2:
case EOpConstructU16Vec3:
case EOpConstructU16Vec4:
case EOpConstructUint16:
basicOp = EOpConstructUint16;
break;
#endif
case EOpConstructBVec2:
case EOpConstructBVec3:
case EOpConstructBVec4:
@@ -5533,7 +5674,7 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con
blockStageIoCheck(loc, currentBlockQualifier);
blockQualifierCheck(loc, currentBlockQualifier, instanceName != nullptr);
if (arraySizes) {
arrayUnsizedCheck(loc, currentBlockQualifier, arraySizes, false, false);
arraySizesCheck(loc, currentBlockQualifier, arraySizes, false, false);
arrayDimCheck(loc, arraySizes, 0);
if (arraySizes->getNumDims() > 1)
requireProfile(loc, ~EEsProfile, "array-of-array of block");
@@ -5551,7 +5692,7 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con
if ((currentBlockQualifier.storage == EvqUniform || currentBlockQualifier.storage == EvqBuffer) && (memberQualifier.isInterpolation() || memberQualifier.isAuxiliary()))
error(memberLoc, "member of uniform or buffer block cannot have an auxiliary or interpolation qualifier", memberType.getFieldName().c_str(), "");
if (memberType.isArray())
arrayUnsizedCheck(memberLoc, currentBlockQualifier, &memberType.getArraySizes(), false, member == typeList.size() - 1);
arraySizesCheck(memberLoc, currentBlockQualifier, &memberType.getArraySizes(), false, member == typeList.size() - 1);
if (memberQualifier.hasOffset()) {
if (spvVersion.spv == 0) {
requireProfile(memberLoc, ~EEsProfile, "offset on block member");
@@ -5597,11 +5738,10 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con
mergeObjectLayoutQualifiers(defaultQualification, currentBlockQualifier, true);
// "The offset qualifier can only be used on block members of blocks declared with std140 or std430 layouts."
// "The align qualifier can only be used on blocks or block members, and only for blocks declared with std140 or std430 layouts."
if (currentBlockQualifier.hasAlign() || currentBlockQualifier.hasAlign()) {
if (currentBlockQualifier.hasAlign()) {
if (defaultQualification.layoutPacking != ElpStd140 && defaultQualification.layoutPacking != ElpStd430) {
error(loc, "can only be used with std140 or std430 layout packing", "offset/align", "");
error(loc, "can only be used with std140 or std430 layout packing", "align", "");
defaultQualification.layoutAlign = -1;
}
}
@@ -5643,9 +5783,12 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con
}
} else
memberWithoutLocation = true;
if (memberQualifier.hasAlign()) {
// "The offset qualifier can only be used on block members of blocks declared with std140 or std430 layouts."
// "The align qualifier can only be used on blocks or block members, and only for blocks declared with std140 or std430 layouts."
if (memberQualifier.hasAlign() || memberQualifier.hasOffset()) {
if (defaultQualification.layoutPacking != ElpStd140 && defaultQualification.layoutPacking != ElpStd430)
error(memberLoc, "can only be used with std140 or std430 layout packing", "align", "");
error(memberLoc, "can only be used with std140 or std430 layout packing", "offset/align", "");
}
TQualifier newMemberQualification = defaultQualification;
@@ -5653,6 +5796,8 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con
memberQualifier = newMemberQualification;
}
layoutMemberLocationArrayCheck(loc, memberWithLocation, arraySizes);
// Process the members
fixBlockLocations(loc, currentBlockQualifier, typeList, memberWithLocation, memberWithoutLocation);
fixBlockXfbOffsets(currentBlockQualifier, typeList);
@@ -5720,6 +5865,7 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con
// Check for general layout qualifier errors
layoutObjectCheck(loc, variable);
// fix up
if (isIoResizeArray(blockType)) {
ioArraySymbolResizeList.push_back(&variable);
checkIoArraysConsistency(loc, true);
@@ -5768,7 +5914,7 @@ void TParseContext::blockStageIoCheck(const TSourceLoc& loc, const TQualifier& q
}
// Do all block-declaration checking regarding its qualifiers.
void TParseContext::blockQualifierCheck(const TSourceLoc& loc, const TQualifier& qualifier, bool instanceName)
void TParseContext::blockQualifierCheck(const TSourceLoc& loc, const TQualifier& qualifier, bool /*instanceName*/)
{
// The 4.5 specification says:
//
@@ -5795,11 +5941,8 @@ void TParseContext::blockQualifierCheck(const TSourceLoc& loc, const TQualifier&
error(loc, "cannot use sample qualifier on an interface block", "sample", "");
if (qualifier.invariant)
error(loc, "cannot use invariant qualifier on an interface block", "invariant", "");
if (qualifier.layoutPushConstant) {
if (qualifier.layoutPushConstant)
intermediate.addPushConstantCount();
if (! instanceName)
error(loc, "requires an instance name", "push_constant", "");
}
}
//
@@ -5837,7 +5980,7 @@ void TParseContext::fixBlockLocations(const TSourceLoc& loc, TQualifier& qualifi
if (nextLocation >= (int)TQualifier::layoutLocationEnd)
error(memberLoc, "location is too large", "location", "");
memberQualifier.layoutLocation = nextLocation;
memberQualifier.layoutComponent = 0;
memberQualifier.layoutComponent = TQualifier::layoutComponentEnd;
}
nextLocation = memberQualifier.layoutLocation + intermediate.computeTypeLocationSize(*typeList[member].type);
}
@@ -77,6 +77,10 @@ public:
TInfoSink& infoSink, bool forwardCompatible, EShMessages messages)
: TParseVersions(interm, version, profile, spvVersion, language, infoSink, forwardCompatible, messages),
symbolTable(symbolTable),
statementNestingLevel(0), loopNestingLevel(0), structNestingLevel(0), controlFlowNestingLevel(0),
postEntryPointReturn(false),
contextPragma(true, false),
limits(resources.limits),
parsingBuiltins(parsingBuiltins), scanContext(nullptr), ppContext(nullptr),
globalUniformBlock(nullptr)
{ }
@@ -133,18 +137,31 @@ public:
extensionCallback(line, extension, behavior);
}
TSymbolTable& symbolTable; // symbol table that goes with the current language, version, and profile
// Manage the global uniform block (default uniforms in GLSL, $Global in HLSL)
// TODO: This could perhaps get its own object, but the current design doesn't work
// yet when new uniform variables are declared between function definitions, so
// this is pending getting a fully functional design.
virtual void growGlobalUniformBlock(TSourceLoc&, TType&, TString& memberName, TTypeList* typeList = nullptr);
virtual bool insertGlobalUniformBlock();
virtual void growGlobalUniformBlock(const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr);
virtual bool lValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*);
virtual void rValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*);
const char* const scopeMangler = "::";
// Basic parsing state, easily accessible to the grammar
TSymbolTable& symbolTable; // symbol table that goes with the current language, version, and profile
int statementNestingLevel; // 0 if outside all flow control or compound statements
int loopNestingLevel; // 0 if outside all loops
int structNestingLevel; // 0 if outside blocks and structures
int controlFlowNestingLevel; // 0 if outside all flow control
const TType* currentFunctionType; // the return type of the function that's currently being parsed
bool functionReturnsValue; // true if a non-void function has a return
// if inside a function, true if the function is the entry point and this is after a return statement
bool postEntryPointReturn;
// case, node, case, case, node, ...; ensure only one node between cases; stack of them for nesting
TList<TIntermSequence*> switchSequenceStack;
// the statementNestingLevel the current switch statement is at, which must match the level of its case statements
TList<int> switchLevel;
struct TPragma contextPragma;
protected:
TParseContextBase(TParseContextBase&);
TParseContextBase& operator=(TParseContextBase&);
@@ -153,6 +170,8 @@ protected:
TVector<TSymbol*> linkageSymbols; // these need to be transferred to 'linkage', after all editing is done
TScanContext* scanContext;
TPpContext* ppContext;
TBuiltInResource resources;
TLimits& limits;
// These, if set, will be called when a line, pragma ... is preprocessed.
// They will be called with any parameters to the original directive.
@@ -175,7 +194,8 @@ protected:
TVariable* globalUniformBlock; // the actual block, inserted into the symbol table
int firstNewMember; // the index of the first member not yet inserted into the symbol table
// override this to set the language-specific name
virtual const char* getGlobalUniformBlockName() { return ""; }
virtual const char* getGlobalUniformBlockName() const { return ""; }
virtual void setUniformBlockDefaults(TType&) const { }
virtual void finalizeGlobalUniformBlockLayout(TVariable&) { }
virtual void outputMessage(const TSourceLoc&, const char* szReason, const char* szToken,
const char* szExtraInfoFormat, TPrefixType prefix,
@@ -297,7 +317,7 @@ public:
bool arrayError(const TSourceLoc&, const TType&);
void arraySizeRequiredCheck(const TSourceLoc&, const TArraySizes&);
void structArrayCheck(const TSourceLoc&, const TType& structure);
void arrayUnsizedCheck(const TSourceLoc&, const TQualifier&, const TArraySizes*, bool initializer, bool lastMember);
void arraySizesCheck(const TSourceLoc&, const TQualifier&, const TArraySizes*, bool initializer, bool lastMember);
void arrayOfArrayVersionCheck(const TSourceLoc&);
void arrayDimCheck(const TSourceLoc&, const TArraySizes* sizes1, const TArraySizes* sizes2);
void arrayDimCheck(const TSourceLoc&, const TType*, const TArraySizes*);
@@ -339,6 +359,7 @@ public:
void setLayoutQualifier(const TSourceLoc&, TPublicType&, TString&, const TIntermTyped*);
void mergeObjectLayoutQualifiers(TQualifier& dest, const TQualifier& src, bool inheritOnly);
void layoutObjectCheck(const TSourceLoc&, const TSymbol&);
void layoutMemberLocationArrayCheck(const TSourceLoc&, bool memberWithLocation, TArraySizes* arraySizes);
void layoutTypeCheck(const TSourceLoc&, const TType&);
void layoutQualifierCheck(const TSourceLoc&, const TQualifier&);
void checkNoShaderLayouts(const TSourceLoc&, const TShaderQualifiers&);
@@ -372,8 +393,8 @@ protected:
void nonInitConstCheck(const TSourceLoc&, TString& identifier, TType& type);
void inheritGlobalDefaults(TQualifier& dst) const;
TVariable* makeInternalVariable(const char* name, const TType&) const;
TVariable* declareNonArray(const TSourceLoc&, TString& identifier, TType&);
void declareArray(const TSourceLoc&, TString& identifier, const TType&, TSymbol*&);
TVariable* declareNonArray(const TSourceLoc&, const TString& identifier, const TType&);
void declareArray(const TSourceLoc&, const TString& identifier, const TType&, TSymbol*&);
TIntermNode* executeInitializer(const TSourceLoc&, TIntermTyped* initializer, TVariable* variable);
TIntermTyped* convertInitializerList(const TSourceLoc&, const TType&, TIntermTyped* initializer);
void finish() override;
@@ -384,17 +405,7 @@ public:
//
// Current state of parsing
struct TPragma contextPragma;
int loopNestingLevel; // 0 if outside all loops
int structNestingLevel; // 0 if outside blocks and structures
int controlFlowNestingLevel; // 0 if outside all flow control
int statementNestingLevel; // 0 if outside all flow control or compound statements
TList<TIntermSequence*> switchSequenceStack; // case, node, case, case, node, ...; ensure only one node between cases; stack of them for nesting
TList<int> switchLevel; // the statementNestingLevel the current switch statement is at, which must match the level of its case statements
bool inMain; // if inside a function, true if the function is main
bool postMainReturn; // if inside a function, true if the function is main and this is after a return statement
const TType* currentFunctionType; // the return type of the function that's currently being parsed
bool functionReturnsValue; // true if a non-void function has a return
const TString* blockName;
TQualifier currentBlockQualifier;
TPrecisionQualifier defaultPrecision[EbtNumTypes];
@@ -32,6 +32,8 @@
// POSSIBILITY OF SUCH DAMAGE.
//
#pragma once
namespace glslang {
void RemoveAllTreeNodes(TIntermNode*);
@@ -175,7 +175,7 @@ bool TInputScanner::scanVersion(int& version, EProfile& profile, bool& notFirstT
bool versionNotFirst = false; // means not first WRT comments and white space, nothing more
notFirstToken = false; // means not first WRT to real tokens
version = 0; // means not found
version = 0; // means not found
profile = ENoProfile;
bool foundNonSpaceTab = false;
@@ -464,6 +464,15 @@ void TScanContext::fillInKeywordMap()
(*KeywordMap)["u64vec4"] = U64VEC4;
#ifdef AMD_EXTENSIONS
(*KeywordMap)["int16_t"] = INT16_T;
(*KeywordMap)["uint16_t"] = UINT16_T;
(*KeywordMap)["i16vec2"] = I16VEC2;
(*KeywordMap)["i16vec3"] = I16VEC3;
(*KeywordMap)["i16vec4"] = I16VEC4;
(*KeywordMap)["u16vec2"] = U16VEC2;
(*KeywordMap)["u16vec3"] = U16VEC3;
(*KeywordMap)["u16vec4"] = U16VEC4;
(*KeywordMap)["float16_t"] = FLOAT16_T;
(*KeywordMap)["f16vec2"] = F16VEC2;
(*KeywordMap)["f16vec3"] = F16VEC3;
@@ -701,10 +710,18 @@ int TScanContext::tokenize(TPpContext* pp, TParserToken& token)
case PpAtomDecrement: return DEC_OP;
case PpAtomIncrement: return INC_OP;
case PpAtomColonColon:
parseContext.error(loc, "not supported", "::", "");
break;
case PpAtomConstInt: parserToken->sType.lex.i = ppToken.ival; return INTCONSTANT;
case PpAtomConstUint: parserToken->sType.lex.i = ppToken.ival; return UINTCONSTANT;
case PpAtomConstInt64: parserToken->sType.lex.i64 = ppToken.i64val; return INT64CONSTANT;
case PpAtomConstUint64: parserToken->sType.lex.i64 = ppToken.i64val; return UINT64CONSTANT;
#ifdef AMD_EXTENSIONS
case PpAtomConstInt16: parserToken->sType.lex.i = ppToken.ival; return INT16CONSTANT;
case PpAtomConstUint16: parserToken->sType.lex.i = ppToken.ival; return UINT16CONSTANT;
#endif
case PpAtomConstFloat: parserToken->sType.lex.d = ppToken.dval; return FLOATCONSTANT;
case PpAtomConstDouble: parserToken->sType.lex.d = ppToken.dval; return DOUBLECONSTANT;
#ifdef AMD_EXTENSIONS
@@ -969,6 +986,21 @@ int TScanContext::tokenizeIdentifier()
return identifierOrType();
#ifdef AMD_EXTENSIONS
case INT16_T:
case UINT16_T:
case I16VEC2:
case I16VEC3:
case I16VEC4:
case U16VEC2:
case U16VEC3:
case U16VEC4:
afterType = true;
if (parseContext.symbolTable.atBuiltInLevel() ||
(parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_int16) &&
parseContext.profile != EEsProfile && parseContext.version >= 450))
return keyword;
return identifierOrType();
case FLOAT16_T:
case F16VEC2:
case F16VEC3:
@@ -38,6 +38,8 @@
// sits between the preprocessor scanner and parser.
//
#pragma once
#include "ParseHelper.h"
namespace glslang {
@@ -442,7 +442,7 @@ bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNo
bool correct = true;
if (source == EShSourceHlsl) {
version = 450; // TODO: GLSL parser is still used for builtins.
version = 500; // shader model; currently a characteristic of glslang, not the input
profile = ECoreProfile; // allow doubles in prototype parsing
return correct;
}
@@ -566,41 +566,6 @@ bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNo
}
}
// A meta check on the condition of the compiler itself...
switch (version) {
// ES versions
case 100:
case 300:
// versions are complete
break;
// Desktop versions
case 110:
case 120:
case 130:
case 140:
case 150:
case 330:
// versions are complete
break;
case 310:
case 400:
case 410:
case 420:
case 430:
case 440:
case 450:
infoSink.info << "Warning, version " << version << " is not yet complete; most version-specific features are present, but some are missing.\n";
break;
default:
infoSink.info << "Warning, version " << version << " is unknown.\n";
break;
}
return correct;
}
@@ -679,13 +644,13 @@ bool ProcessDeferred(
// First, without using the preprocessor or parser, find the #version, so we know what
// symbol tables, processing rules, etc. to set up. This does not need the extra strings
// outlined above, just the user shader.
int version;
EProfile profile;
glslang::TInputScanner userInput(numStrings, &strings[numPre], &lengths[numPre]); // no preamble
bool versionNotFirstToken;
bool versionNotFirst = userInput.scanVersion(version, profile, versionNotFirstToken);
int version = 0;
EProfile profile = ENoProfile;
bool versionNotFirstToken = false;
bool versionNotFirst = (messages & EShMsgReadHlsl) ? true : userInput.scanVersion(version, profile, versionNotFirstToken);
bool versionNotFound = version == 0;
if (forceDefaultVersionAndProfile) {
if (forceDefaultVersionAndProfile && (messages & EShMsgReadHlsl) == 0) {
if (! (messages & EShMsgSuppressWarnings) && ! versionNotFound &&
(version != defaultVersion || profile != defaultProfile)) {
compiler->infoSink.info << "Warning, (version, profile) forced to be ("
@@ -726,6 +691,13 @@ bool ProcessDeferred(
intermediate.setSpv(spvVersion);
if (spvVersion.vulkan >= 100)
intermediate.setOriginUpperLeft();
if ((messages & EShMsgHlslOffsets) || (messages & EShMsgReadHlsl))
intermediate.setHlslOffsets();
if (messages & EShMsgDebugInfo) {
intermediate.setSourceFile(names[numPre]);
for (int s = 0; s < numStrings; ++s)
intermediate.addSourceText(strings[numPre]);
}
SetupBuiltinSymbolTable(version, profile, spvVersion, source);
TSymbolTable* cachedTable = SharedSymbolTables[MapVersionToIndex(version)]
@@ -1553,13 +1525,30 @@ void TShader::setSourceEntryPoint(const char* name)
sourceEntryPointName = name;
}
// Set binding base for sampler types
void TShader::setShiftSamplerBinding(unsigned int base) { intermediate->setShiftSamplerBinding(base); }
// Set binding base for texture types (SRV)
void TShader::setShiftTextureBinding(unsigned int base) { intermediate->setShiftTextureBinding(base); }
// Set binding base for image types
void TShader::setShiftImageBinding(unsigned int base) { intermediate->setShiftImageBinding(base); }
// Set binding base for uniform buffer objects (CBV)
void TShader::setShiftUboBinding(unsigned int base) { intermediate->setShiftUboBinding(base); }
// Synonym for setShiftUboBinding, to match HLSL language.
void TShader::setShiftCbufferBinding(unsigned int base) { intermediate->setShiftUboBinding(base); }
// Set binding base for UAV (unordered access view)
void TShader::setShiftUavBinding(unsigned int base) { intermediate->setShiftUavBinding(base); }
// Set binding base for SSBOs
void TShader::setShiftSsboBinding(unsigned int base) { intermediate->setShiftSsboBinding(base); }
// Enables binding automapping using TIoMapper
void TShader::setAutoMapBindings(bool map) { intermediate->setAutoMapBindings(map); }
// Fragile: currently within one stage: simple auto-assignment of location
void TShader::setAutoMapLocations(bool map) { intermediate->setAutoMapLocations(map); }
// See comment above TDefaultHlslIoMapper in iomapper.cpp:
void TShader::setHlslIoMapping(bool hlslIoMap) { intermediate->setHlslIoMapping(hlslIoMap); }
void TShader::setFlattenUniformArrays(bool flatten) { intermediate->setFlattenUniformArrays(flatten); }
void TShader::setNoStorageFormat(bool useUnknownFormat) { intermediate->setNoStorageFormat(useUnknownFormat); }
void TShader::setResourceSetBinding(const std::vector<std::string>& base) { intermediate->setResourceSetBinding(base); }
void TShader::setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode) { intermediate->setTextureSamplerTransformMode(mode); }
//
// Turn the shader strings into a parse tree in the TIntermediate.
@@ -1583,11 +1572,6 @@ bool TShader::parse(const TBuiltInResource* builtInResources, int defaultVersion
forwardCompatible, messages, *intermediate, includer, sourceEntryPointName);
}
bool TShader::parse(const TBuiltInResource* builtInResources, int defaultVersion, bool forwardCompatible, EShMessages messages)
{
return parse(builtInResources, defaultVersion, ENoProfile, false, forwardCompatible, messages);
}
// Fill in a string with the result of preprocessing ShaderStrings
// Returns true if all extensions, pragmas and version strings were valid.
bool TShader::preprocess(const TBuiltInResource* builtInResources,
@@ -1775,6 +1759,7 @@ const char* TProgram::getUniformBlockName(int index) const { return reflection
int TProgram::getUniformBlockSize(int index) const { return reflection->getUniformBlock(index).size; }
int TProgram::getUniformIndex(const char* name) const { return reflection->getIndex(name); }
int TProgram::getUniformBlockIndex(int index) const { return reflection->getUniform(index).index; }
int TProgram::getUniformBlockCounterIndex(int index) const { return reflection->getUniformBlock(index).counterIndex; }
int TProgram::getUniformType(int index) const { return reflection->getUniform(index).glDefineType; }
int TProgram::getUniformBufferOffset(int index) const { return reflection->getUniform(index).offset; }
int TProgram::getUniformArraySize(int index) const { return reflection->getUniform(index).size; }
@@ -1784,6 +1769,7 @@ int TProgram::getAttributeType(int index) const { return reflection
const TType* TProgram::getAttributeTType(int index) const { return reflection->getAttribute(index).getType(); }
const TType* TProgram::getUniformTType(int index) const { return reflection->getUniform(index).getType(); }
const TType* TProgram::getUniformBlockTType(int index) const { return reflection->getUniformBlock(index).getType(); }
unsigned TProgram::getLocalSize(int dim) const { return reflection->getLocalSize(dim); }
void TProgram::dumpReflection() { reflection->dump(); }
@@ -50,7 +50,7 @@ namespace glslang {
//
// Recursively generate mangled names.
//
void TType::buildMangledName(TString& mangledName)
void TType::buildMangledName(TString& mangledName) const
{
if (isMatrix())
mangledName += 'm';
@@ -67,6 +67,10 @@ void TType::buildMangledName(TString& mangledName)
case EbtUint: mangledName += 'u'; break;
case EbtInt64: mangledName += "i64"; break;
case EbtUint64: mangledName += "u64"; break;
#ifdef AMD_EXTENSIONS
case EbtInt16: mangledName += "i16"; break;
case EbtUint16: mangledName += "u16"; break;
#endif
case EbtBool: mangledName += 'b'; break;
case EbtAtomicUint: mangledName += "au"; break;
case EbtSampler:
@@ -99,11 +103,23 @@ void TType::buildMangledName(TString& mangledName)
case EsdSubpass: mangledName += "P"; break;
default: break; // some compilers want this
}
switch (sampler.vectorSize) {
case 1: mangledName += "1"; break;
case 2: mangledName += "2"; break;
case 3: mangledName += "3"; break;
case 4: break; // default to prior name mangle behavior
}
if (sampler.ms)
mangledName += "M";
break;
case EbtStruct:
mangledName += "struct-";
case EbtBlock:
if (basicType == EbtStruct)
mangledName += "struct-";
else
mangledName += "block-";
if (typeName)
mangledName += *typeName;
for (unsigned int i = 0; i < structure->size(); ++i) {
@@ -295,6 +311,8 @@ TFunction::TFunction(const TFunction& copyOf) : TSymbol(copyOf)
op = copyOf.op;
defined = copyOf.defined;
prototyped = copyOf.prototyped;
implicitThis = copyOf.implicitThis;
illegalImplicitThis = copyOf.illegalImplicitThis;
defaultParamCount = copyOf.defaultParamCount;
}
@@ -319,6 +337,7 @@ TSymbolTableLevel* TSymbolTableLevel::clone() const
{
TSymbolTableLevel *symTableLevel = new TSymbolTableLevel();
symTableLevel->anonId = anonId;
symTableLevel->thisLevel = thisLevel;
std::vector<bool> containerCopied(anonId, false);
tLevel::const_iterator iter;
for (iter = level.begin(); iter != level.end(); ++iter) {
@@ -198,7 +198,6 @@ struct TParameter {
TString *name;
TType* type;
TIntermTyped* defaultValue;
TBuiltInVariable declaredBuiltIn;
void copyParam(const TParameter& param)
{
if (param.name)
@@ -207,8 +206,8 @@ struct TParameter {
name = 0;
type = param.type->clone();
defaultValue = param.defaultValue;
declaredBuiltIn = param.declaredBuiltIn;
}
TBuiltInVariable getDeclaredBuiltIn() const { return type->getQualifier().declaredBuiltIn; }
};
//
@@ -219,48 +218,70 @@ public:
explicit TFunction(TOperator o) :
TSymbol(0),
op(o),
defined(false), prototyped(false), defaultParamCount(0) { }
defined(false), prototyped(false), implicitThis(false), illegalImplicitThis(false), defaultParamCount(0) { }
TFunction(const TString *name, const TType& retType, TOperator tOp = EOpNull) :
TSymbol(name),
mangledName(*name + '('),
op(tOp),
defined(false), prototyped(false), defaultParamCount(0)
defined(false), prototyped(false), implicitThis(false), illegalImplicitThis(false), defaultParamCount(0)
{
returnType.shallowCopy(retType);
declaredBuiltIn = retType.getQualifier().builtIn;
}
virtual TFunction* clone() const;
virtual TFunction* clone() const override;
virtual ~TFunction();
virtual TFunction* getAsFunction() { return this; }
virtual const TFunction* getAsFunction() const { return this; }
virtual TFunction* getAsFunction() override { return this; }
virtual const TFunction* getAsFunction() const override { return this; }
// Install 'p' as the (non-'this') last parameter.
// Non-'this' parameters are reflected in both the list of parameters and the
// mangled name.
virtual void addParameter(TParameter& p)
{
assert(writable);
p.declaredBuiltIn = p.type->getQualifier().builtIn;
parameters.push_back(p);
p.type->appendMangledName(mangledName);
if (p.defaultValue != nullptr)
defaultParamCount++;
}
// Install 'this' as the first parameter.
// 'this' is reflected in the list of parameters, but not the mangled name.
virtual void addThisParameter(TType& type, const char* name)
{
TParameter p = { NewPoolTString(name), new TType, nullptr };
p.type->shallowCopy(type);
parameters.insert(parameters.begin(), p);
}
virtual void addPrefix(const char* prefix) override
{
TSymbol::addPrefix(prefix);
mangledName.insert(0, prefix);
}
virtual const TString& getMangledName() const { return mangledName; }
virtual const TType& getType() const { return returnType; }
virtual void removePrefix(const TString& prefix)
{
assert(mangledName.compare(0, prefix.size(), prefix) == 0);
mangledName.erase(0, prefix.size());
}
virtual const TString& getMangledName() const override { return mangledName; }
virtual const TType& getType() const override { return returnType; }
virtual TBuiltInVariable getDeclaredBuiltInType() const { return declaredBuiltIn; }
virtual TType& getWritableType() { return returnType; }
virtual TType& getWritableType() override { return returnType; }
virtual void relateToOperator(TOperator o) { assert(writable); op = o; }
virtual TOperator getBuiltInOp() const { return op; }
virtual void setDefined() { assert(writable); defined = true; }
virtual bool isDefined() const { return defined; }
virtual void setPrototyped() { assert(writable); prototyped = true; }
virtual bool isPrototyped() const { return prototyped; }
virtual void setImplicitThis() { assert(writable); implicitThis = true; }
virtual bool hasImplicitThis() const { return implicitThis; }
virtual void setIllegalImplicitThis() { assert(writable); illegalImplicitThis = true; }
virtual bool hasIllegalImplicitThis() const { return illegalImplicitThis; }
// Return total number of parameters
virtual int getParamCount() const { return static_cast<int>(parameters.size()); }
@@ -272,7 +293,7 @@ public:
virtual TParameter& operator[](int i) { assert(writable); return parameters[i]; }
virtual const TParameter& operator[](int i) const { return parameters[i]; }
virtual void dump(TInfoSink &infoSink) const;
virtual void dump(TInfoSink &infoSink) const override;
protected:
explicit TFunction(const TFunction&);
@@ -287,6 +308,11 @@ protected:
TOperator op;
bool defined;
bool prototyped;
bool implicitThis; // True if this function is allowed to see all members of 'this'
bool illegalImplicitThis; // True if this function is not supposed to have access to dynamic members of 'this',
// even if it finds member variables in the symbol table.
// This is important for a static member function that has member variables in scope,
// but is not allowed to use them, or see hidden symbols instead.
int defaultParamCount;
};
@@ -334,7 +360,7 @@ protected:
class TSymbolTableLevel {
public:
POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
TSymbolTableLevel() : defaultPrecision(0), anonId(0) { }
TSymbolTableLevel() : defaultPrecision(0), anonId(0), thisLevel(false) { }
~TSymbolTableLevel();
bool insert(TSymbol& symbol, bool separateNameSpaces)
@@ -492,6 +518,9 @@ public:
TSymbolTableLevel* clone() const;
void readOnly();
void setThisLevel() { thisLevel = true; }
bool isThisLevel() const { return thisLevel; }
protected:
explicit TSymbolTableLevel(TSymbolTableLevel&);
TSymbolTableLevel& operator=(TSymbolTableLevel&);
@@ -503,6 +532,8 @@ protected:
tLevel level; // named mappings
TPrecisionQualifier *defaultPrecision;
int anonId;
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.
};
class TSymbolTable {
@@ -559,6 +590,20 @@ public:
table.push_back(new TSymbolTableLevel);
}
// Make a new symbol-table level to represent the scope introduced by a structure
// containing member functions, such that the member functions can find anonymous
// references to member variables.
//
// 'thisSymbol' should have a name of "" to trigger anonymous structure-member
// symbol finds.
void pushThis(TSymbol& thisSymbol)
{
assert(thisSymbol.getName().size() == 0);
table.push_back(new TSymbolTableLevel);
table.back()->setThisLevel();
insert(thisSymbol);
}
void pop(TPrecisionQualifier *p)
{
table[currentLevel()]->getPreviousDefaultPrecisions(p);
@@ -645,19 +690,50 @@ public:
}
}
TSymbol* find(const TString& name, bool* builtIn = 0, bool *currentScope = 0)
// Normal find of a symbol, that can optionally say whether the symbol was found
// at a built-in level or the current top-scope level.
TSymbol* find(const TString& name, bool* builtIn = 0, bool* currentScope = 0, int* thisDepthP = 0)
{
int level = currentLevel();
TSymbol* symbol;
int thisDepth = 0;
do {
if (table[level]->isThisLevel())
++thisDepth;
symbol = table[level]->find(name);
--level;
} while (symbol == 0 && level >= 0);
} while (symbol == nullptr && level >= 0);
level++;
if (builtIn)
*builtIn = isBuiltInLevel(level);
if (currentScope)
*currentScope = isGlobalLevel(currentLevel()) || level == currentLevel(); // consider shared levels as "current scope" WRT user globals
if (thisDepthP != nullptr) {
if (! table[level]->isThisLevel())
thisDepth = 0;
*thisDepthP = thisDepth;
}
return symbol;
}
// Find of a symbol that returns how many layers deep of nested
// structures-with-member-functions ('this' scopes) deep the symbol was
// found in.
TSymbol* find(const TString& name, int& thisDepth)
{
int level = currentLevel();
TSymbol* symbol;
thisDepth = 0;
do {
if (table[level]->isThisLevel())
++thisDepth;
symbol = table[level]->find(name);
--level;
} while (symbol == 0 && level >= 0);
if (! table[level + 1]->isThisLevel())
thisDepth = 0;
return symbol;
}
@@ -195,6 +195,8 @@ void TParseVersions::initializeExtensionBehavior()
extensionBehavior[E_GL_AMD_shader_explicit_vertex_parameter] = EBhDisable;
extensionBehavior[E_GL_AMD_gcn_shader] = EBhDisable;
extensionBehavior[E_GL_AMD_gpu_shader_half_float] = EBhDisable;
extensionBehavior[E_GL_AMD_texture_gather_bias_lod] = EBhDisable;
extensionBehavior[E_GL_AMD_gpu_shader_int16] = EBhDisable;
#endif
#ifdef NV_EXTENSIONS
@@ -233,6 +235,10 @@ void TParseVersions::initializeExtensionBehavior()
extensionBehavior[E_GL_OES_tessellation_point_size] = EBhDisable;
extensionBehavior[E_GL_OES_texture_buffer] = EBhDisable;
extensionBehavior[E_GL_OES_texture_cube_map_array] = EBhDisable;
// EXT extensions
extensionBehavior[E_GL_EXT_device_group] = EBhDisable;
extensionBehavior[E_GL_EXT_multiview] = EBhDisable;
}
// Get code that is not part of a shared symbol table, is specific to this shader,
@@ -315,6 +321,8 @@ void TParseVersions::getPreamble(std::string& preamble)
"#define GL_AMD_shader_explicit_vertex_parameter 1\n"
"#define GL_AMD_gcn_shader 1\n"
"#define GL_AMD_gpu_shader_half_float 1\n"
"#define GL_AMD_texture_gather_bias_lod 1\n"
"#define GL_AMD_gpu_shader_int16 1\n"
#endif
#ifdef NV_EXTENSIONS
@@ -323,6 +331,22 @@ void TParseVersions::getPreamble(std::string& preamble)
"#define GL_NV_viewport_array2 1\n"
#endif
;
if (version >= 150) {
// define GL_core_profile and GL_compatibility_profile
preamble += "#define GL_core_profile 1\n";
if (profile == ECompatibilityProfile)
preamble += "#define GL_compatibility_profile 1\n";
}
}
if ((profile != EEsProfile && version >= 140) ||
(profile == EEsProfile && version >= 310)) {
preamble +=
"#define GL_EXT_device_group 1\n"
"#define GL_EXT_multiview 1\n"
;
}
// #line and #include
@@ -481,6 +505,11 @@ void TParseVersions::requireNotRemoved(const TSourceLoc& loc, int profileMask, i
}
}
void TParseVersions::unimplemented(const TSourceLoc& loc, const char* featureDesc)
{
error(loc, "feature not yet implemented", featureDesc, "");
}
// Returns true if at least one of the extensions in the extensions parameter is requested. Otherwise, returns false.
// Warns appropriately if the requested behavior of an extension is "warn".
bool TParseVersions::checkExtensionsRequested(const TSourceLoc& loc, int numExtensions, const char* const extensions[], const char* featureDesc)
@@ -686,10 +715,21 @@ void TParseVersions::doubleCheck(const TSourceLoc& loc, const char* op)
}
#ifdef AMD_EXTENSIONS
// Call for any operation needing GLSL 16-bit integer data-type support.
void TParseVersions::int16Check(const TSourceLoc& loc, const char* op, bool builtIn)
{
if (! builtIn) {
requireExtensions(loc, 1, &E_GL_AMD_gpu_shader_int16, "shader int16");
requireProfile(loc, ECoreProfile | ECompatibilityProfile, op);
profileRequires(loc, ECoreProfile, 450, nullptr, op);
profileRequires(loc, ECompatibilityProfile, 450, nullptr, op);
}
}
// Call for any operation needing GLSL float16 data-type support.
void TParseVersions::float16Check(const TSourceLoc& loc, const char* op, bool builtIn)
{
if (!builtIn) {
if (! builtIn) {
requireExtensions(loc, 1, &E_GL_AMD_gpu_shader_half_float, "shader half float");
requireProfile(loc, ECoreProfile | ECompatibilityProfile, op);
profileRequires(loc, ECoreProfile, 450, nullptr, op);
@@ -133,6 +133,10 @@ const char* const E_GL_ARB_sparse_texture_clamp = "GL_ARB_sparse_texture
const char* const E_GL_EXT_shader_non_constant_global_initializers = "GL_EXT_shader_non_constant_global_initializers";
const char* const E_GL_EXT_shader_image_load_formatted = "GL_EXT_shader_image_load_formatted";
// EXT extensions
const char* const E_GL_EXT_device_group = "GL_EXT_device_group";
const char* const E_GL_EXT_multiview = "GL_EXT_multiview";
// #line and #include
const char* const E_GL_GOOGLE_cpp_style_line_directive = "GL_GOOGLE_cpp_style_line_directive";
const char* const E_GL_GOOGLE_include_directive = "GL_GOOGLE_include_directive";
@@ -143,7 +147,10 @@ const char* const E_GL_AMD_shader_trinary_minmax = "GL_AMD_shader
const char* const E_GL_AMD_shader_explicit_vertex_parameter = "GL_AMD_shader_explicit_vertex_parameter";
const char* const E_GL_AMD_gcn_shader = "GL_AMD_gcn_shader";
const char* const E_GL_AMD_gpu_shader_half_float = "GL_AMD_gpu_shader_half_float";
const char* const E_GL_AMD_texture_gather_bias_lod = "GL_AMD_texture_gather_bias_lod";
const char* const E_GL_AMD_gpu_shader_int16 = "GL_AMD_gpu_shader_int16";
#endif
#ifdef NV_EXTENSIONS
const char* const E_GL_NV_sample_mask_override_coverage = "GL_NV_sample_mask_override_coverage";
@@ -21,6 +21,8 @@
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
*/
#pragma once
#define GL_FLOAT 0x1406
#define GL_FLOAT_VEC2 0x8B50
#define GL_FLOAT_VEC3 0x8B51
File diff suppressed because it is too large Load Diff
@@ -1,19 +1,19 @@
/* A Bison parser, made by GNU Bison 2.7. */
/* A Bison parser, made by GNU Bison 3.0.4. */
/* Bison interface for Yacc-like parsers in C
Copyright (C) 1984, 1989-1990, 2000-2012 Free Software Foundation, Inc.
Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
@@ -26,13 +26,13 @@
special exception, which will cause the skeleton and the resulting
Bison output files to be licensed under the GNU General Public
License without this special exception.
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
#ifndef YY_YY_GLSLANG_TAB_CPP_H_INCLUDED
# define YY_YY_GLSLANG_TAB_CPP_H_INCLUDED
/* Enabling traces. */
#ifndef YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED
# define YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED
/* Debug traces. */
#ifndef YYDEBUG
# define YYDEBUG 1
#endif
@@ -40,306 +40,315 @@
extern int yydebug;
#endif
/* Tokens. */
/* Token type. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
/* Put the tokens into the symbol table, so that GDB and other debuggers
know about them. */
enum yytokentype {
ATTRIBUTE = 258,
VARYING = 259,
CONST = 260,
BOOL = 261,
FLOAT = 262,
DOUBLE = 263,
INT = 264,
UINT = 265,
INT64_T = 266,
UINT64_T = 267,
FLOAT16_T = 268,
BREAK = 269,
CONTINUE = 270,
DO = 271,
ELSE = 272,
FOR = 273,
IF = 274,
DISCARD = 275,
RETURN = 276,
SWITCH = 277,
CASE = 278,
DEFAULT = 279,
SUBROUTINE = 280,
BVEC2 = 281,
BVEC3 = 282,
BVEC4 = 283,
IVEC2 = 284,
IVEC3 = 285,
IVEC4 = 286,
I64VEC2 = 287,
I64VEC3 = 288,
I64VEC4 = 289,
UVEC2 = 290,
UVEC3 = 291,
UVEC4 = 292,
U64VEC2 = 293,
U64VEC3 = 294,
U64VEC4 = 295,
VEC2 = 296,
VEC3 = 297,
VEC4 = 298,
MAT2 = 299,
MAT3 = 300,
MAT4 = 301,
CENTROID = 302,
IN = 303,
OUT = 304,
INOUT = 305,
UNIFORM = 306,
PATCH = 307,
SAMPLE = 308,
BUFFER = 309,
SHARED = 310,
COHERENT = 311,
VOLATILE = 312,
RESTRICT = 313,
READONLY = 314,
WRITEONLY = 315,
DVEC2 = 316,
DVEC3 = 317,
DVEC4 = 318,
DMAT2 = 319,
DMAT3 = 320,
DMAT4 = 321,
F16VEC2 = 322,
F16VEC3 = 323,
F16VEC4 = 324,
F16MAT2 = 325,
F16MAT3 = 326,
F16MAT4 = 327,
NOPERSPECTIVE = 328,
FLAT = 329,
SMOOTH = 330,
LAYOUT = 331,
__EXPLICITINTERPAMD = 332,
MAT2X2 = 333,
MAT2X3 = 334,
MAT2X4 = 335,
MAT3X2 = 336,
MAT3X3 = 337,
MAT3X4 = 338,
MAT4X2 = 339,
MAT4X3 = 340,
MAT4X4 = 341,
DMAT2X2 = 342,
DMAT2X3 = 343,
DMAT2X4 = 344,
DMAT3X2 = 345,
DMAT3X3 = 346,
DMAT3X4 = 347,
DMAT4X2 = 348,
DMAT4X3 = 349,
DMAT4X4 = 350,
F16MAT2X2 = 351,
F16MAT2X3 = 352,
F16MAT2X4 = 353,
F16MAT3X2 = 354,
F16MAT3X3 = 355,
F16MAT3X4 = 356,
F16MAT4X2 = 357,
F16MAT4X3 = 358,
F16MAT4X4 = 359,
ATOMIC_UINT = 360,
SAMPLER1D = 361,
SAMPLER2D = 362,
SAMPLER3D = 363,
SAMPLERCUBE = 364,
SAMPLER1DSHADOW = 365,
SAMPLER2DSHADOW = 366,
SAMPLERCUBESHADOW = 367,
SAMPLER1DARRAY = 368,
SAMPLER2DARRAY = 369,
SAMPLER1DARRAYSHADOW = 370,
SAMPLER2DARRAYSHADOW = 371,
ISAMPLER1D = 372,
ISAMPLER2D = 373,
ISAMPLER3D = 374,
ISAMPLERCUBE = 375,
ISAMPLER1DARRAY = 376,
ISAMPLER2DARRAY = 377,
USAMPLER1D = 378,
USAMPLER2D = 379,
USAMPLER3D = 380,
USAMPLERCUBE = 381,
USAMPLER1DARRAY = 382,
USAMPLER2DARRAY = 383,
SAMPLER2DRECT = 384,
SAMPLER2DRECTSHADOW = 385,
ISAMPLER2DRECT = 386,
USAMPLER2DRECT = 387,
SAMPLERBUFFER = 388,
ISAMPLERBUFFER = 389,
USAMPLERBUFFER = 390,
SAMPLERCUBEARRAY = 391,
SAMPLERCUBEARRAYSHADOW = 392,
ISAMPLERCUBEARRAY = 393,
USAMPLERCUBEARRAY = 394,
SAMPLER2DMS = 395,
ISAMPLER2DMS = 396,
USAMPLER2DMS = 397,
SAMPLER2DMSARRAY = 398,
ISAMPLER2DMSARRAY = 399,
USAMPLER2DMSARRAY = 400,
SAMPLEREXTERNALOES = 401,
SAMPLER = 402,
SAMPLERSHADOW = 403,
TEXTURE1D = 404,
TEXTURE2D = 405,
TEXTURE3D = 406,
TEXTURECUBE = 407,
TEXTURE1DARRAY = 408,
TEXTURE2DARRAY = 409,
ITEXTURE1D = 410,
ITEXTURE2D = 411,
ITEXTURE3D = 412,
ITEXTURECUBE = 413,
ITEXTURE1DARRAY = 414,
ITEXTURE2DARRAY = 415,
UTEXTURE1D = 416,
UTEXTURE2D = 417,
UTEXTURE3D = 418,
UTEXTURECUBE = 419,
UTEXTURE1DARRAY = 420,
UTEXTURE2DARRAY = 421,
TEXTURE2DRECT = 422,
ITEXTURE2DRECT = 423,
UTEXTURE2DRECT = 424,
TEXTUREBUFFER = 425,
ITEXTUREBUFFER = 426,
UTEXTUREBUFFER = 427,
TEXTURECUBEARRAY = 428,
ITEXTURECUBEARRAY = 429,
UTEXTURECUBEARRAY = 430,
TEXTURE2DMS = 431,
ITEXTURE2DMS = 432,
UTEXTURE2DMS = 433,
TEXTURE2DMSARRAY = 434,
ITEXTURE2DMSARRAY = 435,
UTEXTURE2DMSARRAY = 436,
SUBPASSINPUT = 437,
SUBPASSINPUTMS = 438,
ISUBPASSINPUT = 439,
ISUBPASSINPUTMS = 440,
USUBPASSINPUT = 441,
USUBPASSINPUTMS = 442,
IMAGE1D = 443,
IIMAGE1D = 444,
UIMAGE1D = 445,
IMAGE2D = 446,
IIMAGE2D = 447,
UIMAGE2D = 448,
IMAGE3D = 449,
IIMAGE3D = 450,
UIMAGE3D = 451,
IMAGE2DRECT = 452,
IIMAGE2DRECT = 453,
UIMAGE2DRECT = 454,
IMAGECUBE = 455,
IIMAGECUBE = 456,
UIMAGECUBE = 457,
IMAGEBUFFER = 458,
IIMAGEBUFFER = 459,
UIMAGEBUFFER = 460,
IMAGE1DARRAY = 461,
IIMAGE1DARRAY = 462,
UIMAGE1DARRAY = 463,
IMAGE2DARRAY = 464,
IIMAGE2DARRAY = 465,
UIMAGE2DARRAY = 466,
IMAGECUBEARRAY = 467,
IIMAGECUBEARRAY = 468,
UIMAGECUBEARRAY = 469,
IMAGE2DMS = 470,
IIMAGE2DMS = 471,
UIMAGE2DMS = 472,
IMAGE2DMSARRAY = 473,
IIMAGE2DMSARRAY = 474,
UIMAGE2DMSARRAY = 475,
STRUCT = 476,
VOID = 477,
WHILE = 478,
IDENTIFIER = 479,
TYPE_NAME = 480,
FLOATCONSTANT = 481,
DOUBLECONSTANT = 482,
INTCONSTANT = 483,
UINTCONSTANT = 484,
INT64CONSTANT = 485,
UINT64CONSTANT = 486,
BOOLCONSTANT = 487,
FLOAT16CONSTANT = 488,
LEFT_OP = 489,
RIGHT_OP = 490,
INC_OP = 491,
DEC_OP = 492,
LE_OP = 493,
GE_OP = 494,
EQ_OP = 495,
NE_OP = 496,
AND_OP = 497,
OR_OP = 498,
XOR_OP = 499,
MUL_ASSIGN = 500,
DIV_ASSIGN = 501,
ADD_ASSIGN = 502,
MOD_ASSIGN = 503,
LEFT_ASSIGN = 504,
RIGHT_ASSIGN = 505,
AND_ASSIGN = 506,
XOR_ASSIGN = 507,
OR_ASSIGN = 508,
SUB_ASSIGN = 509,
LEFT_PAREN = 510,
RIGHT_PAREN = 511,
LEFT_BRACKET = 512,
RIGHT_BRACKET = 513,
LEFT_BRACE = 514,
RIGHT_BRACE = 515,
DOT = 516,
COMMA = 517,
COLON = 518,
EQUAL = 519,
SEMICOLON = 520,
BANG = 521,
DASH = 522,
TILDE = 523,
PLUS = 524,
STAR = 525,
SLASH = 526,
PERCENT = 527,
LEFT_ANGLE = 528,
RIGHT_ANGLE = 529,
VERTICAL_BAR = 530,
CARET = 531,
AMPERSAND = 532,
QUESTION = 533,
INVARIANT = 534,
PRECISE = 535,
HIGH_PRECISION = 536,
MEDIUM_PRECISION = 537,
LOW_PRECISION = 538,
PRECISION = 539,
PACKED = 540,
RESOURCE = 541,
SUPERP = 542
};
enum yytokentype
{
ATTRIBUTE = 258,
VARYING = 259,
CONST = 260,
BOOL = 261,
FLOAT = 262,
DOUBLE = 263,
INT = 264,
UINT = 265,
INT64_T = 266,
UINT64_T = 267,
INT16_T = 268,
UINT16_T = 269,
FLOAT16_T = 270,
BREAK = 271,
CONTINUE = 272,
DO = 273,
ELSE = 274,
FOR = 275,
IF = 276,
DISCARD = 277,
RETURN = 278,
SWITCH = 279,
CASE = 280,
DEFAULT = 281,
SUBROUTINE = 282,
BVEC2 = 283,
BVEC3 = 284,
BVEC4 = 285,
IVEC2 = 286,
IVEC3 = 287,
IVEC4 = 288,
I64VEC2 = 289,
I64VEC3 = 290,
I64VEC4 = 291,
UVEC2 = 292,
UVEC3 = 293,
UVEC4 = 294,
U64VEC2 = 295,
U64VEC3 = 296,
U64VEC4 = 297,
VEC2 = 298,
VEC3 = 299,
VEC4 = 300,
MAT2 = 301,
MAT3 = 302,
MAT4 = 303,
CENTROID = 304,
IN = 305,
OUT = 306,
INOUT = 307,
UNIFORM = 308,
PATCH = 309,
SAMPLE = 310,
BUFFER = 311,
SHARED = 312,
COHERENT = 313,
VOLATILE = 314,
RESTRICT = 315,
READONLY = 316,
WRITEONLY = 317,
DVEC2 = 318,
DVEC3 = 319,
DVEC4 = 320,
DMAT2 = 321,
DMAT3 = 322,
DMAT4 = 323,
F16VEC2 = 324,
F16VEC3 = 325,
F16VEC4 = 326,
F16MAT2 = 327,
F16MAT3 = 328,
F16MAT4 = 329,
I16VEC2 = 330,
I16VEC3 = 331,
I16VEC4 = 332,
U16VEC2 = 333,
U16VEC3 = 334,
U16VEC4 = 335,
NOPERSPECTIVE = 336,
FLAT = 337,
SMOOTH = 338,
LAYOUT = 339,
__EXPLICITINTERPAMD = 340,
MAT2X2 = 341,
MAT2X3 = 342,
MAT2X4 = 343,
MAT3X2 = 344,
MAT3X3 = 345,
MAT3X4 = 346,
MAT4X2 = 347,
MAT4X3 = 348,
MAT4X4 = 349,
DMAT2X2 = 350,
DMAT2X3 = 351,
DMAT2X4 = 352,
DMAT3X2 = 353,
DMAT3X3 = 354,
DMAT3X4 = 355,
DMAT4X2 = 356,
DMAT4X3 = 357,
DMAT4X4 = 358,
F16MAT2X2 = 359,
F16MAT2X3 = 360,
F16MAT2X4 = 361,
F16MAT3X2 = 362,
F16MAT3X3 = 363,
F16MAT3X4 = 364,
F16MAT4X2 = 365,
F16MAT4X3 = 366,
F16MAT4X4 = 367,
ATOMIC_UINT = 368,
SAMPLER1D = 369,
SAMPLER2D = 370,
SAMPLER3D = 371,
SAMPLERCUBE = 372,
SAMPLER1DSHADOW = 373,
SAMPLER2DSHADOW = 374,
SAMPLERCUBESHADOW = 375,
SAMPLER1DARRAY = 376,
SAMPLER2DARRAY = 377,
SAMPLER1DARRAYSHADOW = 378,
SAMPLER2DARRAYSHADOW = 379,
ISAMPLER1D = 380,
ISAMPLER2D = 381,
ISAMPLER3D = 382,
ISAMPLERCUBE = 383,
ISAMPLER1DARRAY = 384,
ISAMPLER2DARRAY = 385,
USAMPLER1D = 386,
USAMPLER2D = 387,
USAMPLER3D = 388,
USAMPLERCUBE = 389,
USAMPLER1DARRAY = 390,
USAMPLER2DARRAY = 391,
SAMPLER2DRECT = 392,
SAMPLER2DRECTSHADOW = 393,
ISAMPLER2DRECT = 394,
USAMPLER2DRECT = 395,
SAMPLERBUFFER = 396,
ISAMPLERBUFFER = 397,
USAMPLERBUFFER = 398,
SAMPLERCUBEARRAY = 399,
SAMPLERCUBEARRAYSHADOW = 400,
ISAMPLERCUBEARRAY = 401,
USAMPLERCUBEARRAY = 402,
SAMPLER2DMS = 403,
ISAMPLER2DMS = 404,
USAMPLER2DMS = 405,
SAMPLER2DMSARRAY = 406,
ISAMPLER2DMSARRAY = 407,
USAMPLER2DMSARRAY = 408,
SAMPLEREXTERNALOES = 409,
SAMPLER = 410,
SAMPLERSHADOW = 411,
TEXTURE1D = 412,
TEXTURE2D = 413,
TEXTURE3D = 414,
TEXTURECUBE = 415,
TEXTURE1DARRAY = 416,
TEXTURE2DARRAY = 417,
ITEXTURE1D = 418,
ITEXTURE2D = 419,
ITEXTURE3D = 420,
ITEXTURECUBE = 421,
ITEXTURE1DARRAY = 422,
ITEXTURE2DARRAY = 423,
UTEXTURE1D = 424,
UTEXTURE2D = 425,
UTEXTURE3D = 426,
UTEXTURECUBE = 427,
UTEXTURE1DARRAY = 428,
UTEXTURE2DARRAY = 429,
TEXTURE2DRECT = 430,
ITEXTURE2DRECT = 431,
UTEXTURE2DRECT = 432,
TEXTUREBUFFER = 433,
ITEXTUREBUFFER = 434,
UTEXTUREBUFFER = 435,
TEXTURECUBEARRAY = 436,
ITEXTURECUBEARRAY = 437,
UTEXTURECUBEARRAY = 438,
TEXTURE2DMS = 439,
ITEXTURE2DMS = 440,
UTEXTURE2DMS = 441,
TEXTURE2DMSARRAY = 442,
ITEXTURE2DMSARRAY = 443,
UTEXTURE2DMSARRAY = 444,
SUBPASSINPUT = 445,
SUBPASSINPUTMS = 446,
ISUBPASSINPUT = 447,
ISUBPASSINPUTMS = 448,
USUBPASSINPUT = 449,
USUBPASSINPUTMS = 450,
IMAGE1D = 451,
IIMAGE1D = 452,
UIMAGE1D = 453,
IMAGE2D = 454,
IIMAGE2D = 455,
UIMAGE2D = 456,
IMAGE3D = 457,
IIMAGE3D = 458,
UIMAGE3D = 459,
IMAGE2DRECT = 460,
IIMAGE2DRECT = 461,
UIMAGE2DRECT = 462,
IMAGECUBE = 463,
IIMAGECUBE = 464,
UIMAGECUBE = 465,
IMAGEBUFFER = 466,
IIMAGEBUFFER = 467,
UIMAGEBUFFER = 468,
IMAGE1DARRAY = 469,
IIMAGE1DARRAY = 470,
UIMAGE1DARRAY = 471,
IMAGE2DARRAY = 472,
IIMAGE2DARRAY = 473,
UIMAGE2DARRAY = 474,
IMAGECUBEARRAY = 475,
IIMAGECUBEARRAY = 476,
UIMAGECUBEARRAY = 477,
IMAGE2DMS = 478,
IIMAGE2DMS = 479,
UIMAGE2DMS = 480,
IMAGE2DMSARRAY = 481,
IIMAGE2DMSARRAY = 482,
UIMAGE2DMSARRAY = 483,
STRUCT = 484,
VOID = 485,
WHILE = 486,
IDENTIFIER = 487,
TYPE_NAME = 488,
FLOATCONSTANT = 489,
DOUBLECONSTANT = 490,
INTCONSTANT = 491,
UINTCONSTANT = 492,
INT64CONSTANT = 493,
UINT64CONSTANT = 494,
INT16CONSTANT = 495,
UINT16CONSTANT = 496,
BOOLCONSTANT = 497,
FLOAT16CONSTANT = 498,
LEFT_OP = 499,
RIGHT_OP = 500,
INC_OP = 501,
DEC_OP = 502,
LE_OP = 503,
GE_OP = 504,
EQ_OP = 505,
NE_OP = 506,
AND_OP = 507,
OR_OP = 508,
XOR_OP = 509,
MUL_ASSIGN = 510,
DIV_ASSIGN = 511,
ADD_ASSIGN = 512,
MOD_ASSIGN = 513,
LEFT_ASSIGN = 514,
RIGHT_ASSIGN = 515,
AND_ASSIGN = 516,
XOR_ASSIGN = 517,
OR_ASSIGN = 518,
SUB_ASSIGN = 519,
LEFT_PAREN = 520,
RIGHT_PAREN = 521,
LEFT_BRACKET = 522,
RIGHT_BRACKET = 523,
LEFT_BRACE = 524,
RIGHT_BRACE = 525,
DOT = 526,
COMMA = 527,
COLON = 528,
EQUAL = 529,
SEMICOLON = 530,
BANG = 531,
DASH = 532,
TILDE = 533,
PLUS = 534,
STAR = 535,
SLASH = 536,
PERCENT = 537,
LEFT_ANGLE = 538,
RIGHT_ANGLE = 539,
VERTICAL_BAR = 540,
CARET = 541,
AMPERSAND = 542,
QUESTION = 543,
INVARIANT = 544,
PRECISE = 545,
HIGH_PRECISION = 546,
MEDIUM_PRECISION = 547,
LOW_PRECISION = 548,
PRECISION = 549,
PACKED = 550,
RESOURCE = 551,
SUPERP = 552
};
#endif
/* Value type. */
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE
union YYSTYPE
{
/* Line 2058 of yacc.c */
#line 66 "glslang.y"
#line 68 "MachineIndependent/glslang.y" /* yacc.c:1909 */
struct {
glslang::TSourceLoc loc;
@@ -373,28 +382,16 @@ typedef union YYSTYPE
};
} interm;
#line 386 "MachineIndependent/glslang_tab.cpp.h" /* yacc.c:1909 */
};
/* Line 2058 of yacc.c */
#line 379 "glslang_tab.cpp.h"
} YYSTYPE;
typedef union YYSTYPE YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
#endif
#ifdef YYPARSE_PARAM
#if defined __STDC__ || defined __cplusplus
int yyparse (void *YYPARSE_PARAM);
#else
int yyparse ();
#endif
#else /* ! YYPARSE_PARAM */
#if defined __STDC__ || defined __cplusplus
int yyparse (glslang::TParseContext* pParseContext);
#else
int yyparse ();
#endif
#endif /* ! YYPARSE_PARAM */
#endif /* !YY_YY_GLSLANG_TAB_CPP_H_INCLUDED */
int yyparse (glslang::TParseContext* pParseContext);
#endif /* !YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED */
@@ -45,11 +45,31 @@
namespace {
bool is_positive_infinity(double x) {
bool IsInfinity(double x) {
#ifdef _MSC_VER
return _fpclass(x) == _FPCLASS_PINF;
switch (_fpclass(x)) {
case _FPCLASS_NINF:
case _FPCLASS_PINF:
return true;
default:
return false;
}
#else
return std::isinf(x) && (x >= 0);
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
}
@@ -288,6 +308,13 @@ bool TOutputTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node)
case EOpDoubleBitsToUint64: out.debug << "doubleBitsToUint64"; break;
case EOpInt64BitsToDouble: out.debug << "int64BitsToDouble"; break;
case EOpUint64BitsToDouble: out.debug << "uint64BitsToDouble"; break;
#ifdef AMD_EXTENSIONS
case EOpFloat16BitsToInt16: out.debug << "float16BitsToInt16"; break;
case EOpFloat16BitsToUint16: out.debug << "float16BitsToUint16"; break;
case EOpInt16BitsToFloat16: out.debug << "int16BitsToFloat16"; break;
case EOpUint16BitsToFloat16: out.debug << "uint16BitsToFloat16"; break;
#endif
case EOpPackSnorm2x16: out.debug << "packSnorm2x16"; break;
case EOpUnpackSnorm2x16:out.debug << "unpackSnorm2x16"; break;
case EOpPackUnorm2x16: out.debug << "packUnorm2x16"; break;
@@ -308,6 +335,16 @@ bool TOutputTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node)
case EOpUnpackUint2x32: out.debug << "unpackUint2x32"; break;
#ifdef AMD_EXTENSIONS
case EOpPackInt2x16: out.debug << "packInt2x16"; break;
case EOpUnpackInt2x16: out.debug << "unpackInt2x16"; break;
case EOpPackUint2x16: out.debug << "packUint2x16"; break;
case EOpUnpackUint2x16: out.debug << "unpackUint2x16"; break;
case EOpPackInt4x16: out.debug << "packInt4x16"; break;
case EOpUnpackInt4x16: out.debug << "unpackInt4x16"; break;
case EOpPackUint4x16: out.debug << "packUint4x16"; break;
case EOpUnpackUint4x16: out.debug << "unpackUint4x16"; break;
case EOpPackFloat2x16: out.debug << "packFloat2x16"; break;
case EOpUnpackFloat2x16: out.debug << "unpackFloat2x16"; break;
#endif
@@ -370,6 +407,8 @@ bool TOutputTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node)
case EOpRcp: out.debug << "rcp"; break;
case EOpSaturate: out.debug << "saturate"; break;
case EOpSparseTexelsResident: out.debug << "sparseTexelsResident"; break;
#ifdef AMD_EXTENSIONS
case EOpMinInvocations: out.debug << "minInvocations"; break;
case EOpMaxInvocations: out.debug << "maxInvocations"; break;
@@ -411,6 +450,42 @@ bool TOutputTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node)
case EOpConvFloat16ToDouble: out.debug << "Convert float16 to double"; break;
case EOpConvFloat16ToInt64: out.debug << "Convert float16 to int64"; break;
case EOpConvFloat16ToUint64: out.debug << "Convert float16 to uint64"; break;
case EOpConvBoolToInt16: out.debug << "Convert bool to int16"; break;
case EOpConvIntToInt16: out.debug << "Convert int to int16"; break;
case EOpConvUintToInt16: out.debug << "Convert uint to int16"; break;
case EOpConvFloatToInt16: out.debug << "Convert float to int16"; break;
case EOpConvDoubleToInt16: out.debug << "Convert double to int16"; break;
case EOpConvFloat16ToInt16: out.debug << "Convert float16 to int16"; break;
case EOpConvInt64ToInt16: out.debug << "Convert int64 to int16"; break;
case EOpConvUint64ToInt16: out.debug << "Convert uint64 to int16"; break;
case EOpConvUint16ToInt16: out.debug << "Convert uint16 to int16"; break;
case EOpConvInt16ToBool: out.debug << "Convert int16 to bool"; break;
case EOpConvInt16ToInt: out.debug << "Convert int16 to int"; break;
case EOpConvInt16ToUint: out.debug << "Convert int16 to uint"; break;
case EOpConvInt16ToFloat: out.debug << "Convert int16 to float"; break;
case EOpConvInt16ToDouble: out.debug << "Convert int16 to double"; break;
case EOpConvInt16ToFloat16: out.debug << "Convert int16 to float16"; break;
case EOpConvInt16ToInt64: out.debug << "Convert int16 to int64"; break;
case EOpConvInt16ToUint64: out.debug << "Convert int16 to uint64"; break;
case EOpConvBoolToUint16: out.debug << "Convert bool to uint16"; break;
case EOpConvIntToUint16: out.debug << "Convert int to uint16"; break;
case EOpConvUintToUint16: out.debug << "Convert uint to uint16"; break;
case EOpConvFloatToUint16: out.debug << "Convert float to uint16"; break;
case EOpConvDoubleToUint16: out.debug << "Convert double to uint16"; break;
case EOpConvFloat16ToUint16: out.debug << "Convert float16 to uint16"; break;
case EOpConvInt64ToUint16: out.debug << "Convert int64 to uint16"; break;
case EOpConvUint64ToUint16: out.debug << "Convert uint64 to uint16"; break;
case EOpConvInt16ToUint16: out.debug << "Convert int16 to uint16"; break;
case EOpConvUint16ToBool: out.debug << "Convert uint16 to bool"; break;
case EOpConvUint16ToInt: out.debug << "Convert uint16 to int"; break;
case EOpConvUint16ToUint: out.debug << "Convert uint16 to uint"; break;
case EOpConvUint16ToFloat: out.debug << "Convert uint16 to float"; break;
case EOpConvUint16ToDouble: out.debug << "Convert uint16 to double"; break;
case EOpConvUint16ToFloat16: out.debug << "Convert uint16 to float16"; break;
case EOpConvUint16ToInt64: out.debug << "Convert uint16 to int64"; break;
case EOpConvUint16ToUint64: out.debug << "Convert uint16 to uint64"; break;
#endif
default: out.debug.message(EPrefixError, "Bad unary op");
@@ -444,9 +519,13 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node
case EOpConstructFloat: out.debug << "Construct float"; break;
case EOpConstructDouble:out.debug << "Construct double"; break;
case EOpConstructVec2: out.debug << "Construct vec2"; break;
case EOpConstructVec3: out.debug << "Construct vec3"; break;
case EOpConstructVec4: out.debug << "Construct vec4"; break;
case EOpConstructDVec2: out.debug << "Construct dvec2"; break;
case EOpConstructDVec3: out.debug << "Construct dvec3"; break;
case EOpConstructDVec4: out.debug << "Construct dvec4"; break;
case EOpConstructBool: out.debug << "Construct bool"; break;
case EOpConstructBVec2: out.debug << "Construct bvec2"; break;
case EOpConstructBVec3: out.debug << "Construct bvec3"; break;
@@ -467,6 +546,16 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node
case EOpConstructU64Vec2: out.debug << "Construct u64vec2"; break;
case EOpConstructU64Vec3: out.debug << "Construct u64vec3"; break;
case EOpConstructU64Vec4: out.debug << "Construct u64vec4"; break;
#ifdef AMD_EXTENSIONS
case EOpConstructInt16: out.debug << "Construct int16_t"; break;
case EOpConstructI16Vec2: out.debug << "Construct i16vec2"; break;
case EOpConstructI16Vec3: out.debug << "Construct i16vec3"; break;
case EOpConstructI16Vec4: out.debug << "Construct i16vec4"; break;
case EOpConstructUint16: out.debug << "Construct uint16_t"; break;
case EOpConstructU16Vec2: out.debug << "Construct u16vec2"; break;
case EOpConstructU16Vec3: out.debug << "Construct u16vec3"; break;
case EOpConstructU16Vec4: out.debug << "Construct u16vec4"; break;
#endif
case EOpConstructMat2x2: out.debug << "Construct mat2"; break;
case EOpConstructMat2x3: out.debug << "Construct mat2x3"; break;
case EOpConstructMat2x4: out.debug << "Construct mat2x4"; break;
@@ -485,6 +574,33 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node
case EOpConstructDMat4x2: out.debug << "Construct dmat4x2"; break;
case EOpConstructDMat4x3: out.debug << "Construct dmat4x3"; break;
case EOpConstructDMat4x4: out.debug << "Construct dmat4"; break;
case EOpConstructIMat2x2: out.debug << "Construct imat2"; break;
case EOpConstructIMat2x3: out.debug << "Construct imat2x3"; break;
case EOpConstructIMat2x4: out.debug << "Construct imat2x4"; break;
case EOpConstructIMat3x2: out.debug << "Construct imat3x2"; break;
case EOpConstructIMat3x3: out.debug << "Construct imat3"; break;
case EOpConstructIMat3x4: out.debug << "Construct imat3x4"; break;
case EOpConstructIMat4x2: out.debug << "Construct imat4x2"; break;
case EOpConstructIMat4x3: out.debug << "Construct imat4x3"; break;
case EOpConstructIMat4x4: out.debug << "Construct imat4"; break;
case EOpConstructUMat2x2: out.debug << "Construct umat2"; break;
case EOpConstructUMat2x3: out.debug << "Construct umat2x3"; break;
case EOpConstructUMat2x4: out.debug << "Construct umat2x4"; break;
case EOpConstructUMat3x2: out.debug << "Construct umat3x2"; break;
case EOpConstructUMat3x3: out.debug << "Construct umat3"; break;
case EOpConstructUMat3x4: out.debug << "Construct umat3x4"; break;
case EOpConstructUMat4x2: out.debug << "Construct umat4x2"; break;
case EOpConstructUMat4x3: out.debug << "Construct umat4x3"; break;
case EOpConstructUMat4x4: out.debug << "Construct umat4"; break;
case EOpConstructBMat2x2: out.debug << "Construct bmat2"; break;
case EOpConstructBMat2x3: out.debug << "Construct bmat2x3"; break;
case EOpConstructBMat2x4: out.debug << "Construct bmat2x4"; break;
case EOpConstructBMat3x2: out.debug << "Construct bmat3x2"; break;
case EOpConstructBMat3x3: out.debug << "Construct bmat3"; break;
case EOpConstructBMat3x4: out.debug << "Construct bmat3x4"; break;
case EOpConstructBMat4x2: out.debug << "Construct bmat4x2"; break;
case EOpConstructBMat4x3: out.debug << "Construct bmat4x3"; break;
case EOpConstructBMat4x4: out.debug << "Construct bmat4"; break;
#ifdef AMD_EXTENSIONS
case EOpConstructFloat16: out.debug << "Construct float16_t"; break;
case EOpConstructF16Vec2: out.debug << "Construct f16vec2"; break;
@@ -600,6 +716,37 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node
case EOpTextureGather: out.debug << "textureGather"; break;
case EOpTextureGatherOffset: out.debug << "textureGatherOffset"; break;
case EOpTextureGatherOffsets: out.debug << "textureGatherOffsets"; break;
case EOpTextureClamp: out.debug << "textureClamp"; break;
case EOpTextureOffsetClamp: out.debug << "textureOffsetClamp"; break;
case EOpTextureGradClamp: out.debug << "textureGradClamp"; break;
case EOpTextureGradOffsetClamp: out.debug << "textureGradOffsetClamp"; break;
#ifdef AMD_EXTENSIONS
case EOpTextureGatherLod: out.debug << "textureGatherLod"; break;
case EOpTextureGatherLodOffset: out.debug << "textureGatherLodOffset"; break;
case EOpTextureGatherLodOffsets: out.debug << "textureGatherLodOffsets"; break;
#endif
case EOpSparseTexture: out.debug << "sparseTexture"; break;
case EOpSparseTextureOffset: out.debug << "sparseTextureOffset"; break;
case EOpSparseTextureLod: out.debug << "sparseTextureLod"; break;
case EOpSparseTextureLodOffset: out.debug << "sparseTextureLodOffset"; break;
case EOpSparseTextureFetch: out.debug << "sparseTexelFetch"; break;
case EOpSparseTextureFetchOffset: out.debug << "sparseTexelFetchOffset"; break;
case EOpSparseTextureGrad: out.debug << "sparseTextureGrad"; break;
case EOpSparseTextureGradOffset: out.debug << "sparseTextureGradOffset"; break;
case EOpSparseTextureGather: out.debug << "sparseTextureGather"; break;
case EOpSparseTextureGatherOffset: out.debug << "sparseTextureGatherOffset"; break;
case EOpSparseTextureGatherOffsets: out.debug << "sparseTextureGatherOffsets"; break;
case EOpSparseImageLoad: out.debug << "sparseImageLoad"; break;
case EOpSparseTextureClamp: out.debug << "sparseTextureClamp"; break;
case EOpSparseTextureOffsetClamp: out.debug << "sparseTextureOffsetClamp"; break;
case EOpSparseTextureGradClamp: out.debug << "sparseTextureGradClamp"; break;
case EOpSparseTextureGradOffsetClamp: out.debug << "sparseTextureGradOffsetClam"; break;
#ifdef AMD_EXTENSIONS
case EOpSparseTextureGatherLod: out.debug << "sparseTextureGatherLod"; break;
case EOpSparseTextureGatherLodOffset: out.debug << "sparseTextureGatherLodOffset"; break;
case EOpSparseTextureGatherLodOffsets: out.debug << "sparseTextureGatherLodOffsets"; break;
#endif
case EOpAddCarry: out.debug << "addCarry"; break;
case EOpSubBorrow: out.debug << "subBorrow"; break;
@@ -694,11 +841,14 @@ static void OutputConstantUnion(TInfoSink& out, const TIntermTyped* node, const
#endif
{
const double value = constUnion[i].getDConst();
// Print infinity in a portable way, for test stability.
// Other cases may be needed in the future: negative infinity,
// and NaNs.
if (is_positive_infinity(value))
out.debug << "inf\n";
// Print infinities and NaNs in a portable way.
if (IsInfinity(value)) {
if (value < 0)
out.debug << "-1.#INF\n";
else
out.debug << "+1.#INF\n";
} else if (IsNan(value))
out.debug << "1.#IND\n";
else {
const int maxSize = 300;
char buf[maxSize];
@@ -744,6 +894,26 @@ static void OutputConstantUnion(TInfoSink& out, const TIntermTyped* node, const
out.debug << buf << "\n";
}
break;
#ifdef AMD_EXTENSIONS
case EbtInt16:
{
const int maxSize = 300;
char buf[maxSize];
snprintf(buf, maxSize, "%d (%s)", constUnion[i].getIConst(), "const int16_t");
out.debug << buf << "\n";
}
break;
case EbtUint16:
{
const int maxSize = 300;
char buf[maxSize];
snprintf(buf, maxSize, "%u (%s)", constUnion[i].getUConst(), "const uint16_t");
out.debug << buf << "\n";
}
break;
#endif
default:
out.info.message(EPrefixInternalError, "Unknown constant", node->getLoc());
break;
@@ -884,6 +1054,13 @@ void TIntermediate::output(TInfoSink& infoSink, bool tree)
case EShLangTessControl:
infoSink.debug << "vertices = " << vertices << "\n";
if (inputPrimitive != ElgNone)
infoSink.debug << "input primitive = " << TQualifier::getGeometryString(inputPrimitive) << "\n";
if (vertexSpacing != EvsNone)
infoSink.debug << "vertex spacing = " << TQualifier::getVertexSpacingString(vertexSpacing) << "\n";
if (vertexOrder != EvoNone)
infoSink.debug << "triangle order = " << TQualifier::getVertexOrderString(vertexOrder) << "\n";
break;
case EShLangTessEvaluation:
@@ -1,5 +1,5 @@
//
// Copyright (C) 2016 LunarG, Inc.
// Copyright (C) 2016-2017 LunarG, Inc.
//
// All rights reserved.
//
@@ -66,11 +66,14 @@ namespace glslang {
struct TVarEntryInfo
{
int id;
TIntermSymbol* symbol;
bool live;
int newBinding;
int newSet;
int id;
TIntermSymbol* symbol;
bool live;
int newBinding;
int newSet;
int newLocation;
int newComponent;
int newIndex;
struct TOrderById
{
@@ -113,70 +116,143 @@ typedef std::vector<TVarEntryInfo> TVarLiveMap;
class TVarGatherTraverser : public TLiveTraverser
{
public:
TVarGatherTraverser(const TIntermediate& i, TVarLiveMap& vars, bool traverseDeadCode)
TVarGatherTraverser(const TIntermediate& i, bool traverseDeadCode, TVarLiveMap& inList, TVarLiveMap& outList, TVarLiveMap& uniformList)
: TLiveTraverser(i, traverseDeadCode, true, true, false)
, varLiveList(vars)
, inputList(inList)
, outputList(outList)
, uniformList(uniformList)
{
}
virtual void visitSymbol(TIntermSymbol* base)
{
if (base->getQualifier().storage == EvqUniform) {
TVarLiveMap* target = nullptr;
if (base->getQualifier().storage == EvqVaryingIn)
target = &inputList;
else if (base->getQualifier().storage == EvqVaryingOut)
target = &outputList;
else if (base->getQualifier().isUniformOrBuffer())
target = &uniformList;
if (target) {
TVarEntryInfo ent = { base->getId(), base, !traverseAll };
TVarLiveMap::iterator at = std::lower_bound(varLiveList.begin(), varLiveList.end(), ent, TVarEntryInfo::TOrderById());
if (at != varLiveList.end() && at->id == ent.id)
TVarLiveMap::iterator at = std::lower_bound(target->begin(), target->end(), ent, TVarEntryInfo::TOrderById());
if (at != target->end() && at->id == ent.id)
at->live = at->live || !traverseAll; // update live state
else
varLiveList.insert(at, ent);
target->insert(at, ent);
}
}
private:
TVarLiveMap& varLiveList;
TVarLiveMap& inputList;
TVarLiveMap& outputList;
TVarLiveMap& uniformList;
};
class TVarSetTraverser : public TLiveTraverser
{
public:
TVarSetTraverser(const TIntermediate& i, const TVarLiveMap& vars)
TVarSetTraverser(const TIntermediate& i, const TVarLiveMap& inList, const TVarLiveMap& outList, const TVarLiveMap& uniformList)
: TLiveTraverser(i, true, true, true, false)
, varLiveList(vars)
, inputList(inList)
, outputList(outList)
, uniformList(uniformList)
{
}
virtual void visitSymbol(TIntermSymbol* base)
{
TVarEntryInfo ent = { base->getId() };
TVarLiveMap::const_iterator at = std::lower_bound(varLiveList.begin(), varLiveList.end(), ent, TVarEntryInfo::TOrderById());
if (at == varLiveList.end())
const TVarLiveMap* source;
if (base->getQualifier().storage == EvqVaryingIn)
source = &inputList;
else if (base->getQualifier().storage == EvqVaryingOut)
source = &outputList;
else if (base->getQualifier().isUniformOrBuffer())
source = &uniformList;
else
return;
if (!(at->id == ent.id))
TVarEntryInfo ent = { base->getId() };
TVarLiveMap::const_iterator at = std::lower_bound(source->begin(), source->end(), ent, TVarEntryInfo::TOrderById());
if (at == source->end())
return;
if (at->id != ent.id)
return;
if (at->newBinding != -1)
base->getWritableType().getQualifier().layoutBinding = at->newBinding;
if (at->newSet != -1)
base->getWritableType().getQualifier().layoutSet = at->newSet;
if (at->newLocation != -1)
base->getWritableType().getQualifier().layoutLocation = at->newLocation;
if (at->newComponent != -1)
base->getWritableType().getQualifier().layoutComponent = at->newComponent;
if (at->newIndex != -1)
base->getWritableType().getQualifier().layoutIndex = at->newIndex;
}
private:
const TVarLiveMap& varLiveList;
const TVarLiveMap& inputList;
const TVarLiveMap& outputList;
const TVarLiveMap& uniformList;
};
struct TResolverAdaptor
struct TNotifyUniformAdaptor
{
TResolverAdaptor(EShLanguage s, TIoMapResolver& r, TInfoSink& i, bool& e)
EShLanguage stage;
TIoMapResolver& resolver;
inline TNotifyUniformAdaptor(EShLanguage s, TIoMapResolver& r)
: stage(s)
, resolver(r)
{
}
inline void operator()(TVarEntryInfo& ent)
{
resolver.notifyBinding(stage, ent.symbol->getName().c_str(), ent.symbol->getType(), ent.live);
}
private:
TNotifyUniformAdaptor& operator=(TNotifyUniformAdaptor&);
};
struct TNotifyInOutAdaptor
{
EShLanguage stage;
TIoMapResolver& resolver;
inline TNotifyInOutAdaptor(EShLanguage s, TIoMapResolver& r)
: stage(s)
, resolver(r)
{
}
inline void operator()(TVarEntryInfo& ent)
{
resolver.notifyInOut(stage, ent.symbol->getName().c_str(), ent.symbol->getType(), ent.live);
}
private:
TNotifyInOutAdaptor& operator=(TNotifyInOutAdaptor&);
};
struct TResolverUniformAdaptor
{
TResolverUniformAdaptor(EShLanguage s, TIoMapResolver& r, TInfoSink& i, bool& e, TIntermediate& interm)
: stage(s)
, resolver(r)
, infoSink(i)
, error(e)
, intermediate(interm)
{
}
inline void operator()(TVarEntryInfo& ent)
{
ent.newLocation = -1;
ent.newComponent = -1;
ent.newBinding = -1;
ent.newSet = -1;
ent.newIndex = -1;
const bool isValid = resolver.validateBinding(stage, ent.symbol->getName().c_str(), ent.symbol->getType(), ent.live);
if (isValid) {
ent.newBinding = resolver.resolveBinding(stage, ent.symbol->getName().c_str(), ent.symbol->getType(), ent.live);
@@ -209,25 +285,77 @@ struct TResolverAdaptor
TIoMapResolver& resolver;
TInfoSink& infoSink;
bool& error;
TIntermediate& intermediate;
private:
TResolverAdaptor& operator=(TResolverAdaptor&);
TResolverUniformAdaptor& operator=(TResolverUniformAdaptor&);
};
/*
* Basic implementation of glslang::TIoMapResolver that replaces the
* previous offset behaviour.
* It does the same, uses the offsets for th corresponding uniform
* types. Also respects the EOptionAutoMapBindings flag and binds
* them if needed.
*/
struct TDefaultIoResolver : public glslang::TIoMapResolver
struct TResolverInOutAdaptor
{
TResolverInOutAdaptor(EShLanguage s, TIoMapResolver& r, TInfoSink& i, bool& e, TIntermediate& interm)
: stage(s)
, resolver(r)
, infoSink(i)
, error(e)
, intermediate(interm)
{
}
inline void operator()(TVarEntryInfo& ent)
{
ent.newLocation = -1;
ent.newComponent = -1;
ent.newBinding = -1;
ent.newSet = -1;
ent.newIndex = -1;
const bool isValid = resolver.validateInOut(stage,
ent.symbol->getName().c_str(),
ent.symbol->getType(),
ent.live);
if (isValid) {
ent.newLocation = resolver.resolveInOutLocation(stage,
ent.symbol->getName().c_str(),
ent.symbol->getType(),
ent.live);
ent.newComponent = resolver.resolveInOutComponent(stage,
ent.symbol->getName().c_str(),
ent.symbol->getType(),
ent.live);
ent.newIndex = resolver.resolveInOutIndex(stage,
ent.symbol->getName().c_str(),
ent.symbol->getType(),
ent.live);
} else {
TString errorMsg = "Invalid shader In/Out variable semantic: ";
errorMsg += ent.symbol->getType().getQualifier().semanticName;
infoSink.info.message(EPrefixInternalError, errorMsg.c_str());
error = true;
}
}
EShLanguage stage;
TIoMapResolver& resolver;
TInfoSink& infoSink;
bool& error;
TIntermediate& intermediate;
private:
TResolverInOutAdaptor& operator=(TResolverInOutAdaptor&);
};
// Base class for shared TIoMapResolver services, used by several derivations.
struct TDefaultIoResolverBase : public glslang::TIoMapResolver
{
int baseSamplerBinding;
int baseTextureBinding;
int baseImageBinding;
int baseUboBinding;
bool doAutoMapping;
int baseSsboBinding;
int baseUavBinding;
std::vector<std::string> baseResourceSetBinding;
bool doAutoBindingMapping;
bool doAutoLocationMapping;
typedef std::vector<int> TSlotSet;
typedef std::unordered_map<int, TSlotSet> TSlotSetMap;
TSlotSetMap slots;
@@ -246,7 +374,12 @@ struct TDefaultIoResolver : public glslang::TIoMapResolver
int reserveSlot(int set, int slot)
{
TSlotSet::iterator at = findSlot(set, slot);
slots[set].insert(at, slot);
// tolerate aliasing, by not double-recording aliases
// (policy about appropriateness of the alias is higher up)
if (at == slots[set].end() || *at != slot)
slots[set].insert(at, slot);
return slot;
}
@@ -263,74 +396,9 @@ struct TDefaultIoResolver : public glslang::TIoMapResolver
return reserveSlot(set, base);
}
bool validateBinding(EShLanguage /*stage*/, const char* /*name*/, const glslang::TType& type, bool /*is_live*/) override
{
if (type.getQualifier().hasBinding()) {
int set;
if (type.getQualifier().hasSet())
set = type.getQualifier().layoutSet;
else
set = 0;
virtual bool validateBinding(EShLanguage /*stage*/, const char* /*name*/, const glslang::TType& type, bool /*is_live*/) override = 0;
if (type.getBasicType() == glslang::EbtSampler) {
const glslang::TSampler& sampler = type.getSampler();
if (sampler.isPureSampler())
return checkEmpty(set, baseSamplerBinding + type.getQualifier().layoutBinding);
if (sampler.isTexture())
return checkEmpty(set, baseTextureBinding + type.getQualifier().layoutBinding);
}
if (type.getQualifier().isUniformOrBuffer())
return checkEmpty(set, baseUboBinding + type.getQualifier().layoutBinding);
}
return true;
}
int resolveBinding(EShLanguage /*stage*/, const char* /*name*/, const glslang::TType& type, bool is_live) override
{
int set;
if (type.getQualifier().hasSet())
set = type.getQualifier().layoutSet;
else
set = 0;
if (type.getQualifier().hasBinding()) {
if (type.getBasicType() == glslang::EbtSampler) {
const glslang::TSampler& sampler = type.getSampler();
if (sampler.isImage())
return reserveSlot(set, baseImageBinding + type.getQualifier().layoutBinding);
if (sampler.isPureSampler())
return reserveSlot(set, baseSamplerBinding + type.getQualifier().layoutBinding);
if (sampler.isTexture())
return reserveSlot(set, baseTextureBinding + type.getQualifier().layoutBinding);
}
if (type.getQualifier().isUniformOrBuffer())
return reserveSlot(set, baseUboBinding + type.getQualifier().layoutBinding);
} else if (is_live && doAutoMapping) {
// find free slot, the caller did make sure it passes all vars with binding
// first and now all are passed that do not have a binding and needs one
if (type.getBasicType() == glslang::EbtSampler) {
const glslang::TSampler& sampler = type.getSampler();
if (sampler.isImage())
return getFreeSlot(set, baseImageBinding);
if (sampler.isPureSampler())
return getFreeSlot(set, baseSamplerBinding);
if (sampler.isTexture())
return getFreeSlot(set, baseTextureBinding);
}
if (type.getQualifier().isUniformOrBuffer())
return getFreeSlot(set, baseUboBinding);
}
return -1;
}
virtual int resolveBinding(EShLanguage /*stage*/, const char* /*name*/, const glslang::TType& type, bool is_live) override = 0;
int resolveSet(EShLanguage /*stage*/, const char* /*name*/, const glslang::TType& type, bool /*is_live*/) override
{
@@ -338,8 +406,231 @@ struct TDefaultIoResolver : public glslang::TIoMapResolver
return type.getQualifier().layoutSet;
return 0;
}
bool validateInOut(EShLanguage /*stage*/, const char* /*name*/, const TType& /*type*/, bool /*is_live*/) override
{
return true;
}
int resolveInOutLocation(EShLanguage /*stage*/, const char* /*name*/, const TType& type, bool /*is_live*/) override
{
if (!doAutoLocationMapping || type.getQualifier().hasLocation())
return -1;
// Placeholder.
// TODO: It would be nice to flesh this out using
// intermediate->computeTypeLocationSize(type), or functions that call it like
// intermediate->addUsedLocation()
// These in turn would want the intermediate, which is not available here, but
// is available in many places, and a lot of copying from it could be saved if
// it were just available.
return 0;
}
int resolveInOutComponent(EShLanguage /*stage*/, const char* /*name*/, const TType& /*type*/, bool /*is_live*/) override
{
return -1;
}
int resolveInOutIndex(EShLanguage /*stage*/, const char* /*name*/, const TType& /*type*/, bool /*is_live*/) override
{
return -1;
}
void notifyBinding(EShLanguage, const char* /*name*/, const TType&, bool /*is_live*/) override {}
void notifyInOut(EShLanguage, const char* /*name*/, const TType&, bool /*is_live*/) override {}
void endNotifications() override {}
protected:
static int getLayoutSet(const glslang::TType& type) {
if (type.getQualifier().hasSet())
return type.getQualifier().layoutSet;
else
return 0;
}
static bool isSamplerType(const glslang::TType& type) {
return type.getBasicType() == glslang::EbtSampler && type.getSampler().isPureSampler();
}
static bool isTextureType(const glslang::TType& type) {
return type.getBasicType() == glslang::EbtSampler && type.getSampler().isTexture();
}
static bool isUboType(const glslang::TType& type) {
return type.getQualifier().storage == EvqUniform;
}
};
/*
* Basic implementation of glslang::TIoMapResolver that replaces the
* previous offset behavior.
* It does the same, uses the offsets for the corresponding uniform
* types. Also respects the EOptionAutoMapBindings flag and binds
* them if needed.
*/
/*
* Default resolver
*/
struct TDefaultIoResolver : public TDefaultIoResolverBase
{
bool validateBinding(EShLanguage /*stage*/, const char* /*name*/, const glslang::TType& /*type*/, bool /*is_live*/) override
{
return true;
}
int resolveBinding(EShLanguage /*stage*/, const char* /*name*/, const glslang::TType& type, bool is_live) override
{
const int set = getLayoutSet(type);
if (type.getQualifier().hasBinding()) {
if (isImageType(type))
return reserveSlot(set, baseImageBinding + type.getQualifier().layoutBinding);
if (isTextureType(type))
return reserveSlot(set, baseTextureBinding + type.getQualifier().layoutBinding);
if (isSsboType(type))
return reserveSlot(set, baseSsboBinding + type.getQualifier().layoutBinding);
if (isSamplerType(type))
return reserveSlot(set, baseSamplerBinding + type.getQualifier().layoutBinding);
if (isUboType(type))
return reserveSlot(set, baseUboBinding + type.getQualifier().layoutBinding);
} else if (is_live && doAutoBindingMapping) {
// find free slot, the caller did make sure it passes all vars with binding
// first and now all are passed that do not have a binding and needs one
if (isImageType(type))
return getFreeSlot(set, baseImageBinding);
if (isTextureType(type))
return getFreeSlot(set, baseTextureBinding);
if (isSsboType(type))
return getFreeSlot(set, baseSsboBinding);
if (isSamplerType(type))
return getFreeSlot(set, baseSamplerBinding);
if (isUboType(type))
return getFreeSlot(set, baseUboBinding);
}
return -1;
}
protected:
static bool isImageType(const glslang::TType& type) {
return type.getBasicType() == glslang::EbtSampler && type.getSampler().isImage();
}
static bool isSsboType(const glslang::TType& type) {
return type.getQualifier().storage == EvqBuffer;
}
};
/********************************************************************************
The following IO resolver maps types in HLSL register space, as follows:
t for shader resource views (SRV)
TEXTURE1D
TEXTURE1DARRAY
TEXTURE2D
TEXTURE2DARRAY
TEXTURE3D
TEXTURECUBE
TEXTURECUBEARRAY
TEXTURE2DMS
TEXTURE2DMSARRAY
STRUCTUREDBUFFER
BYTEADDRESSBUFFER
BUFFER
TBUFFER
s for samplers
SAMPLER
SAMPLER1D
SAMPLER2D
SAMPLER3D
SAMPLERCUBE
SAMPLERSTATE
SAMPLERCOMPARISONSTATE
u for unordered access views (UAV)
RWBYTEADDRESSBUFFER
RWSTRUCTUREDBUFFER
APPENDSTRUCTUREDBUFFER
CONSUMESTRUCTUREDBUFFER
RWBUFFER
RWTEXTURE1D
RWTEXTURE1DARRAY
RWTEXTURE2D
RWTEXTURE2DARRAY
RWTEXTURE3D
b for constant buffer views (CBV)
CBUFFER
CONSTANTBUFFER
********************************************************************************/
struct TDefaultHlslIoResolver : public TDefaultIoResolverBase
{
bool validateBinding(EShLanguage /*stage*/, const char* /*name*/, const glslang::TType& /*type*/, bool /*is_live*/) override
{
return true;
}
int resolveBinding(EShLanguage /*stage*/, const char* /*name*/, const glslang::TType& type, bool is_live) override
{
const int set = getLayoutSet(type);
if (type.getQualifier().hasBinding()) {
if (isUavType(type))
return reserveSlot(set, baseUavBinding + type.getQualifier().layoutBinding);
if (isSrvType(type))
return reserveSlot(set, baseTextureBinding + type.getQualifier().layoutBinding);
if (isSamplerType(type))
return reserveSlot(set, baseSamplerBinding + type.getQualifier().layoutBinding);
if (isUboType(type))
return reserveSlot(set, baseUboBinding + type.getQualifier().layoutBinding);
} else if (is_live && doAutoBindingMapping) {
// find free slot, the caller did make sure it passes all vars with binding
// first and now all are passed that do not have a binding and needs one
if (isUavType(type))
return getFreeSlot(set, baseUavBinding);
if (isSrvType(type))
return getFreeSlot(set, baseTextureBinding);
if (isSamplerType(type))
return getFreeSlot(set, baseSamplerBinding);
if (isUboType(type))
return getFreeSlot(set, baseUboBinding);
}
return -1;
}
protected:
// Return true if this is a SRV (shader resource view) type:
static bool isSrvType(const glslang::TType& type) {
return isTextureType(type) || type.getQualifier().storage == EvqBuffer;
}
// Return true if this is a UAV (unordered access view) type:
static bool isUavType(const glslang::TType& type) {
if (type.getQualifier().readonly)
return false;
return (type.getBasicType() == glslang::EbtSampler && type.getSampler().isImage()) ||
(type.getQualifier().storage == EvqBuffer);
}
};
// Map I/O variables to provided offsets, and make bindings for
// unbound but live variables.
//
@@ -351,7 +642,11 @@ bool TIoMapper::addStage(EShLanguage stage, TIntermediate &intermediate, TInfoSi
intermediate.getShiftTextureBinding() == 0 &&
intermediate.getShiftImageBinding() == 0 &&
intermediate.getShiftUboBinding() == 0 &&
intermediate.getShiftSsboBinding() == 0 &&
intermediate.getShiftUavBinding() == 0 &&
intermediate.getResourceSetBinding().empty() &&
intermediate.getAutoMapBindings() == false &&
intermediate.getAutoMapLocations() == false &&
resolver == nullptr)
return true;
@@ -364,19 +659,33 @@ bool TIoMapper::addStage(EShLanguage stage, TIntermediate &intermediate, TInfoSi
// if no resolver is provided, use the default resolver with the given shifts and auto map settings
TDefaultIoResolver defaultResolver;
if (resolver == nullptr) {
defaultResolver.baseSamplerBinding = intermediate.getShiftSamplerBinding();
defaultResolver.baseTextureBinding = intermediate.getShiftTextureBinding();
defaultResolver.baseImageBinding = intermediate.getShiftImageBinding();
defaultResolver.baseUboBinding = intermediate.getShiftUboBinding();
defaultResolver.doAutoMapping = intermediate.getAutoMapBindings();
TDefaultHlslIoResolver defaultHlslResolver;
resolver = &defaultResolver;
if (resolver == nullptr) {
TDefaultIoResolverBase* resolverBase;
// TODO: use a passed in IO mapper for this
if (intermediate.usingHlslIoMapping())
resolverBase = &defaultHlslResolver;
else
resolverBase = &defaultResolver;
resolverBase->baseSamplerBinding = intermediate.getShiftSamplerBinding();
resolverBase->baseTextureBinding = intermediate.getShiftTextureBinding();
resolverBase->baseImageBinding = intermediate.getShiftImageBinding();
resolverBase->baseUboBinding = intermediate.getShiftUboBinding();
resolverBase->baseSsboBinding = intermediate.getShiftSsboBinding();
resolverBase->baseUavBinding = intermediate.getShiftUavBinding();
resolverBase->baseResourceSetBinding = intermediate.getResourceSetBinding();
resolverBase->doAutoBindingMapping = intermediate.getAutoMapBindings();
resolverBase->doAutoLocationMapping = intermediate.getAutoMapLocations();
resolver = resolverBase;
}
TVarLiveMap varMap;
TVarGatherTraverser iter_binding_all(intermediate, varMap, true);
TVarGatherTraverser iter_binding_live(intermediate, varMap, false);
TVarLiveMap inVarMap, outVarMap, uniformVarMap;
TVarGatherTraverser iter_binding_all(intermediate, true, inVarMap, outVarMap, uniformVarMap);
TVarGatherTraverser iter_binding_live(intermediate, false, inVarMap, outVarMap, uniformVarMap);
root->traverse(&iter_binding_all);
iter_binding_live.pushFunction(intermediate.getEntryPointMangledName().c_str());
@@ -388,16 +697,25 @@ bool TIoMapper::addStage(EShLanguage stage, TIntermediate &intermediate, TInfoSi
}
// sort entries by priority. see TVarEntryInfo::TOrderByPriority for info.
std::sort(varMap.begin(), varMap.end(), TVarEntryInfo::TOrderByPriority());
std::sort(uniformVarMap.begin(), uniformVarMap.end(), TVarEntryInfo::TOrderByPriority());
bool hadError = false;
TResolverAdaptor doResolve(stage, *resolver, infoSink, hadError);
std::for_each(varMap.begin(), varMap.end(), doResolve);
TNotifyInOutAdaptor inOutNotify(stage, *resolver);
TNotifyUniformAdaptor uniformNotify(stage, *resolver);
TResolverUniformAdaptor uniformResolve(stage, *resolver, infoSink, hadError, intermediate);
TResolverInOutAdaptor inOutResolve(stage, *resolver, infoSink, hadError, intermediate);
std::for_each(inVarMap.begin(), inVarMap.end(), inOutNotify);
std::for_each(outVarMap.begin(), outVarMap.end(), inOutNotify);
std::for_each(uniformVarMap.begin(), uniformVarMap.end(), uniformNotify);
resolver->endNotifications();
std::for_each(inVarMap.begin(), inVarMap.end(), inOutResolve);
std::for_each(outVarMap.begin(), outVarMap.end(), inOutResolve);
std::for_each(uniformVarMap.begin(), uniformVarMap.end(), uniformResolve);
if (!hadError) {
// sort by id again, so we can use lower bound to find entries
std::sort(varMap.begin(), varMap.end(), TVarEntryInfo::TOrderById());
TVarSetTraverser iter_iomap(intermediate, varMap);
std::sort(uniformVarMap.begin(), uniformVarMap.end(), TVarEntryInfo::TOrderById());
TVarSetTraverser iter_iomap(intermediate, inVarMap, outVarMap, uniformVarMap);
root->traverse(&iter_iomap);
}
@@ -461,10 +461,12 @@ void TIntermediate::finalCheck(TInfoSink& infoSink, bool keepUncalled)
case EShLangTessEvaluation:
if (inputPrimitive == ElgNone)
error(infoSink, "At least one shader must specify an input layout primitive");
if (vertexSpacing == EvsNone)
vertexSpacing = EvsEqual;
if (vertexOrder == EvoNone)
vertexOrder = EvoCcw;
if (source == EShSourceGlsl) {
if (vertexSpacing == EvsNone)
vertexSpacing = EvsEqual;
if (vertexOrder == EvoNone)
vertexOrder = EvoCcw;
}
break;
case EShLangGeometry:
if (inputPrimitive == ElgNone)
@@ -858,7 +860,7 @@ int TIntermediate::checkLocationRange(int set, const TIoRange& range, const TTyp
return -1; // no collision
}
// Accumulate locations used for inputs, outputs, and uniforms, and check for collisions
// Accumulate bindings and offsets, and check for collisions
// as the accumulation is done.
//
// Returns < 0 if no collision, >= 0 if collision and the value returned is a colliding value.
@@ -1045,9 +1047,9 @@ unsigned int TIntermediate::computeTypeXfbSize(const TType& type, bool& contains
const int baseAlignmentVec4Std140 = 16;
// Return the size and alignment of a scalar.
// Return the size and alignment of a component of the given type.
// The size is returned in the 'size' parameter
// Return value is the alignment of the type.
// Return value is the alignment..
int TIntermediate::getBaseAlignmentScalar(const TType& type, int& size)
{
switch (type.getBasicType()) {
@@ -1055,6 +1057,8 @@ int TIntermediate::getBaseAlignmentScalar(const TType& type, int& size)
case EbtUint64:
case EbtDouble: size = 8; return 8;
#ifdef AMD_EXTENSIONS
case EbtInt16:
case EbtUint16:
case EbtFloat16: size = 2; return 2;
#endif
default: size = 4; return 4;
@@ -1217,4 +1221,14 @@ int TIntermediate::getBaseAlignment(const TType& type, int& size, int& stride, b
return baseAlignmentVec4Std140;
}
// To aid the basic HLSL rule about crossing vec4 boundaries.
bool TIntermediate::improperStraddle(const TType& type, int size, int offset)
{
if (! type.isVector() || type.isArray())
return false;
return size <= 16 ? offset / 16 != (offset + size - 1) / 16
: offset % 16 != 0;
}
} // end namespace glslang
@@ -174,9 +174,16 @@ public:
shiftTextureBinding(0),
shiftImageBinding(0),
shiftUboBinding(0),
shiftSsboBinding(0),
shiftUavBinding(0),
autoMapBindings(false),
autoMapLocations(false),
flattenUniformArrays(false),
useUnknownFormat(false)
useUnknownFormat(false),
hlslOffsets(false),
useStorageBuffer(false),
hlslIoMapping(false),
textureSamplerTransformMode(EShTexSampTransKeep)
{
localSize[0] = 1;
localSize[1] = 1;
@@ -207,12 +214,27 @@ public:
unsigned int getShiftImageBinding() const { return shiftImageBinding; }
void setShiftUboBinding(unsigned int shift) { shiftUboBinding = shift; }
unsigned int getShiftUboBinding() const { return shiftUboBinding; }
void setAutoMapBindings(bool map) { autoMapBindings = map; }
void setShiftSsboBinding(unsigned int shift) { shiftSsboBinding = shift; }
unsigned int getShiftSsboBinding() const { return shiftSsboBinding; }
void setShiftUavBinding(unsigned int shift) { shiftUavBinding = shift; }
unsigned int getShiftUavBinding() const { return shiftUavBinding; }
void setResourceSetBinding(const std::vector<std::string>& shift) { resourceSetBinding = shift; }
const std::vector<std::string>& getResourceSetBinding() const { return resourceSetBinding; }
void setAutoMapBindings(bool map) { autoMapBindings = map; }
bool getAutoMapBindings() const { return autoMapBindings; }
void setFlattenUniformArrays(bool flatten) { flattenUniformArrays = flatten; }
void setAutoMapLocations(bool map) { autoMapLocations = map; }
bool getAutoMapLocations() const { return autoMapLocations; }
void setFlattenUniformArrays(bool flatten) { flattenUniformArrays = flatten; }
bool getFlattenUniformArrays() const { return flattenUniformArrays; }
void setNoStorageFormat(bool b) { useUnknownFormat = b; }
bool getNoStorageFormat() const { return useUnknownFormat; }
void setHlslOffsets() { hlslOffsets = true; }
bool usingHlslOFfsets() const { return hlslOffsets; }
void setUseStorageBuffer() { useStorageBuffer = true; }
bool usingStorageBuffer() const { return useStorageBuffer; }
void setHlslIoMapping(bool b) { hlslIoMapping = b; }
bool usingHlslIoMapping() { return hlslIoMapping; }
void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode) { textureSamplerTransformMode = mode; }
void setVersion(int v) { version = v; }
int getVersion() const { return version; }
@@ -237,7 +259,9 @@ public:
TIntermSymbol* addSymbol(const TType&, const TSourceLoc&);
TIntermSymbol* addSymbol(const TIntermSymbol&);
TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*) const;
TIntermTyped* addShapeConversion(TOperator, const TType&, TIntermTyped*);
TIntermTyped* addUniShapeConversion(TOperator, const TType&, TIntermTyped*);
void addBiShapeConversion(TOperator, TIntermTyped*& lhsNode, TIntermTyped*& rhsNode);
TIntermTyped* addShapeConversion(const TType&, TIntermTyped*);
TIntermTyped* addBinaryMath(TOperator, TIntermTyped* left, TIntermTyped* right, TSourceLoc);
TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc);
TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc);
@@ -261,13 +285,18 @@ public:
TIntermConstantUnion* addConstantUnion(unsigned int, const TSourceLoc&, bool literal = false) const;
TIntermConstantUnion* addConstantUnion(long long, const TSourceLoc&, bool literal = false) const;
TIntermConstantUnion* addConstantUnion(unsigned long long, const TSourceLoc&, bool literal = false) const;
#ifdef AMD_EXTENSIONS
TIntermConstantUnion* addConstantUnion(short, const TSourceLoc&, bool literal = false) const;
TIntermConstantUnion* addConstantUnion(unsigned short, const TSourceLoc&, bool literal = false) const;
#endif
TIntermConstantUnion* addConstantUnion(bool, const TSourceLoc&, bool literal = false) const;
TIntermConstantUnion* addConstantUnion(double, TBasicType, const TSourceLoc&, bool literal = false) const;
TIntermConstantUnion* addConstantUnion(const TString*, const TSourceLoc&, bool literal = false) const;
TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) const;
bool parseConstTree(TIntermNode*, TConstUnionArray, TOperator, const TType&, bool singleConstantParam = false);
TIntermLoop* addLoop(TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, const TSourceLoc&);
TIntermAggregate* addForLoop(TIntermNode*, TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, const TSourceLoc&);
TIntermLoop* addLoop(TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, const TSourceLoc&, TLoopControl = ELoopControlNone);
TIntermAggregate* addForLoop(TIntermNode*, TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, const TSourceLoc&, TLoopControl = ELoopControlNone);
TIntermBranch* addBranch(TOperator, const TSourceLoc&);
TIntermBranch* addBranch(TOperator, TIntermTyped*, const TSourceLoc&);
template<typename selectorType> TIntermTyped* addSwizzle(TSwizzleSelectors<selectorType>&, const TSourceLoc&);
@@ -410,7 +439,9 @@ public:
}
int addXfbBufferOffset(const TType&);
unsigned int computeTypeXfbSize(const TType&, bool& containsDouble) const;
static int getBaseAlignmentScalar(const TType&, int& size);
static int getBaseAlignment(const TType&, int& size, int& stride, bool std140, bool rowMajor);
static bool improperStraddle(const TType& type, int size, int offset);
bool promote(TIntermOperator*);
#ifdef NV_EXTENSIONS
@@ -420,6 +451,18 @@ public:
bool getGeoPassthroughEXT() const { return geoPassthroughEXT; }
#endif
const char* addSemanticName(const TString& name)
{
return semanticNameSet.insert(name).first->c_str();
}
void setSourceFile(const char* file) { sourceFile = file; }
const std::string& getSourceFile() const { return sourceFile; }
void addSourceText(const char* text) { sourceText = sourceText + text; }
const std::string& getSourceText() const { return sourceText; }
const char* const implicitThisName = "@this";
protected:
TIntermSymbol* addSymbol(int Id, const TString&, const TType&, const TConstUnionArray&, TIntermTyped* subtree, const TSourceLoc&);
void error(TInfoSink& infoSink, const char*);
@@ -433,7 +476,6 @@ protected:
void inOutLocationCheck(TInfoSink&);
TIntermSequence& findLinkerObjects() const;
bool userOutputUsed() const;
static int getBaseAlignmentScalar(const TType&, int& size);
bool isSpecializationOperation(const TIntermOperator&) const;
bool promoteUnary(TIntermUnary&);
bool promoteBinary(TIntermBinary&);
@@ -442,6 +484,7 @@ protected:
void pushSelector(TIntermSequence&, const TVectorSelector&, const TSourceLoc&);
void pushSelector(TIntermSequence&, const TMatrixSelector&, const TSourceLoc&);
bool specConstantPropagates(const TIntermTyped&, const TIntermTyped&);
void performTextureUpgradeAndSamplerRemovalTransformation(TIntermNode* root);
const EShLanguage language; // stage, known at construction time
EShSource source; // source language, known a bit later
@@ -485,9 +528,16 @@ protected:
unsigned int shiftTextureBinding;
unsigned int shiftImageBinding;
unsigned int shiftUboBinding;
unsigned int shiftSsboBinding;
unsigned int shiftUavBinding;
std::vector<std::string> resourceSetBinding;
bool autoMapBindings;
bool autoMapLocations;
bool flattenUniformArrays;
bool useUnknownFormat;
bool hlslOffsets;
bool useStorageBuffer;
bool hlslIoMapping;
typedef std::list<TCall> TGraph;
TGraph callGraph;
@@ -497,6 +547,13 @@ protected:
std::vector<TOffsetRange> usedAtomics; // sets of bindings used by atomic counters
std::vector<TXfbBuffer> xfbBuffers; // all the data we need to track per xfb buffer
std::unordered_set<int> usedConstantId; // specialization constant ids used
std::set<TString> semanticNameSet;
EShTextureSamplerTransformMode textureSamplerTransformMode;
// source code of shader, useful as part of debug information
std::string sourceFile;
std::string sourceText;
private:
void operator=(TIntermediate&); // prevent assignments
@@ -76,12 +76,6 @@ bool TConstTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node)
return false;
}
if (node->getSequence().size() == 0) {
error = true;
return false;
}
bool flag = node->getSequence().size() == 1 && node->getSequence()[0]->getAsTyped()->getAsConstantUnion();
if (flag) {
singleConstantParam = true;
@@ -68,6 +68,7 @@ public:
virtual void requireStage(const TSourceLoc&, EShLanguage, const char* featureDesc);
virtual void checkDeprecated(const TSourceLoc&, int queryProfiles, int depVersion, const char* featureDesc);
virtual void requireNotRemoved(const TSourceLoc&, int queryProfiles, int removedVersion, const char* featureDesc);
virtual void unimplemented(const TSourceLoc&, const char* featureDesc);
virtual void requireExtensions(const TSourceLoc&, int numExtensions, const char* const extensions[], const char* featureDesc);
virtual void ppRequireExtensions(const TSourceLoc&, int numExtensions, const char* const extensions[], const char* featureDesc);
virtual TExtensionBehavior getExtensionBehavior(const char*);
@@ -77,6 +78,7 @@ public:
virtual void fullIntegerCheck(const TSourceLoc&, const char* op);
virtual void doubleCheck(const TSourceLoc&, const char* op);
#ifdef AMD_EXTENSIONS
virtual void int16Check(const TSourceLoc& loc, const char* op, bool builtIn = false);
virtual void float16Check(const TSourceLoc&, const char* op, bool builtIn = false);
#endif
virtual void int64Check(const TSourceLoc&, const char* op, bool builtIn = false);
@@ -76,7 +76,9 @@ TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\****************************************************************************/
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <sstream>
#include <cstdlib>
@@ -391,6 +393,14 @@ int TPpContext::eval(int token, int precedence, bool shortCircuit, int& res, boo
TSourceLoc loc = ppToken->loc; // because we sometimes read the newline before reporting the error
if (token == PpAtomIdentifier) {
if (strcmp("defined", ppToken->name) == 0) {
if (! parseContext.isReadingHLSL() && isMacroInput()) {
if (parseContext.relaxedErrors())
parseContext.ppWarn(ppToken->loc, "nonportable when expanded from macros for preprocessor expression",
"defined", "");
else
parseContext.ppError(ppToken->loc, "cannot use in preprocessor expression when expanded from macros",
"defined", "");
}
bool needclose = 0;
token = scanToken(ppToken);
if (token == '(') {
@@ -611,14 +621,14 @@ int TPpContext::CPPinclude(TPpToken* ppToken)
TShader::Includer::IncludeResult* res = nullptr;
if (startWithLocalSearch)
res = includer.includeLocal(filename.c_str(), currentSourceFile.c_str(), includeStack.size() + 1);
if (! res || res->headerName.empty()) {
if (res == nullptr || res->headerName.empty()) {
includer.releaseInclude(res);
res = includer.includeSystem(filename.c_str(), currentSourceFile.c_str(), includeStack.size() + 1);
}
// Process the results
if (res && !res->headerName.empty()) {
if (res->headerData && res->headerLength) {
if (res != nullptr && !res->headerName.empty()) {
if (res->headerData != nullptr && res->headerLength > 0) {
// path for processing one or more tokens from an included header, hand off 'res'
const bool forNextLine = parseContext.lineDirectiveShouldSetNextLine();
std::ostringstream prologue;
@@ -636,8 +646,8 @@ int TPpContext::CPPinclude(TPpToken* ppToken)
} else {
// error path, clean up
std::string message =
res ? std::string(res->headerData, res->headerLength)
: std::string("Could not process include directive");
res != nullptr ? std::string(res->headerData, res->headerLength)
: std::string("Could not process include directive");
parseContext.ppError(directiveLoc, message.c_str(), "#include", "for header name: %s", filename.c_str());
includer.releaseInclude(res);
}
@@ -714,6 +724,7 @@ int TPpContext::CPPerror(TPpToken* ppToken)
if (token == PpAtomConstInt || token == PpAtomConstUint ||
token == PpAtomConstInt64 || token == PpAtomConstUint64 ||
#ifdef AMD_EXTENSIONS
token == PpAtomConstInt16 || token == PpAtomConstUint16 ||
token == PpAtomConstFloat16 ||
#endif
token == PpAtomConstFloat || token == PpAtomConstDouble) {
@@ -748,6 +759,10 @@ int TPpContext::CPPpragma(TPpToken* ppToken)
case PpAtomConstUint:
case PpAtomConstInt64:
case PpAtomConstUint64:
#ifdef AMD_EXTENSIONS
case PpAtomConstInt16:
case PpAtomConstUint16:
#endif
case PpAtomConstFloat:
case PpAtomConstDouble:
#ifdef AMD_EXTENSIONS
@@ -776,8 +791,12 @@ int TPpContext::CPPversion(TPpToken* ppToken)
{
int token = scanToken(ppToken);
if (errorOnVersion || versionSeen)
parseContext.ppError(ppToken->loc, "must occur first in shader", "#version", "");
if (errorOnVersion || versionSeen) {
if (parseContext.isReadingHLSL())
parseContext.ppError(ppToken->loc, "invalid preprocessor command", "#version", "");
else
parseContext.ppError(ppToken->loc, "must occur first in shader", "#version", "");
}
versionSeen = true;
if (token == '\n') {
@@ -986,6 +1005,8 @@ TPpContext::TokenStream* TPpContext::PrescanMacroArg(TokenStream& arg, TPpToken*
int token;
while ((token = scanToken(ppToken)) != tMarkerInput::marker && token != EndOfInput) {
token = tokenPaste(token, *ppToken);
if (token == tMarkerInput::marker || token == EndOfInput)
break;
if (token == PpAtomIdentifier && MacroExpand(ppToken, false, newLineOkay) != 0)
continue;
expandedArg->putToken(token, ppToken);
@@ -1050,7 +1071,7 @@ int TPpContext::tMacroInput::scan(TPpToken* ppToken)
// TODO: preprocessor: properly handle whitespace (or lack of it) between tokens when expanding
if (token == PpAtomIdentifier) {
int i;
for (i = mac->args.size() - 1; i >= 0; i--)
for (i = (int)mac->args.size() - 1; i >= 0; i--)
if (strcmp(pp->atomStrings.getString(mac->args[i]), ppToken->name) == 0)
break;
if (i >= 0) {
@@ -76,7 +76,9 @@ TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\****************************************************************************/
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <cassert>
#include <cstdlib>
@@ -120,6 +122,8 @@ const struct {
{ PpAtomDecrement, "--" },
{ PpAtomIncrement, "++" },
{ PpAtomColonColon, "::" },
{ PpAtomDefine, "define" },
{ PpAtomUndef, "undef" },
{ PpAtomIf, "if" },
@@ -92,7 +92,7 @@ namespace glslang {
class TPpToken {
public:
TPpToken() : space(false), ival(0), dval(0.0), i64val(0)
TPpToken() : space(false), i64val(0)
{
loc.init();
name[0] = 0;
@@ -108,10 +108,14 @@ public:
bool operator!=(const TPpToken& right) { return ! operator==(right); }
TSourceLoc loc;
bool space; // true if a space (for white space or a removed comment) should also be recognized, in front of the token returned
int ival;
double dval;
long long i64val;
bool space; // true if a space (for white space or a removed comment) should also be recognized, in front of the token returned
union {
int ival;
double dval;
long long i64val;
};
char name[MaxTokenLength + 1];
};
@@ -196,6 +200,7 @@ public:
virtual void ungetch() = 0;
virtual bool peekPasting() { return false; } // true when about to see ##
virtual bool endOfReplacementList() { return false; } // true when at the end of a macro replacement list (RHS of #define)
virtual bool isMacroInput() { return false; }
// Will be called when we start reading tokens from this instance
virtual void notifyActivated() {}
@@ -236,7 +241,7 @@ public:
void reset() { current = 0; }
protected:
void putSubtoken(int);
void putSubtoken(char);
int getSubtoken();
void ungetSubtoken();
@@ -302,6 +307,7 @@ protected:
void ungetChar() { inputStack.back()->ungetch(); }
bool peekPasting() { return !inputStack.empty() && inputStack.back()->peekPasting(); }
bool endOfReplacementList() { return inputStack.empty() || inputStack.back()->endOfReplacementList(); }
bool isMacroInput() { return inputStack.size() > 0 && inputStack.back()->isMacroInput(); }
static const int maxIfNesting = 64;
@@ -325,6 +331,7 @@ protected:
virtual void ungetch() override { assert(0); }
bool peekPasting() override { return prepaste; }
bool endOfReplacementList() override { return mac->body.atEnd(); }
bool isMacroInput() override { return true; }
MacroSymbol *mac;
TVector<TokenStream*> args;
@@ -584,6 +591,7 @@ protected:
int ScanFromString(char* s);
void missingEndifCheck();
int lFloatConst(int len, int ch, TPpToken* ppToken);
int characterLiteral(TPpToken* ppToken);
void push_include(TShader::Includer::IncludeResult* result)
{
@@ -1,81 +0,0 @@
//
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2013 LunarG, Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
//
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
/****************************************************************************\
Copyright (c) 2002, NVIDIA Corporation.
NVIDIA Corporation("NVIDIA") supplies this software to you in
consideration of your agreement to the following terms, and your use,
installation, modification or redistribution of this NVIDIA software
constitutes acceptance of these terms. If you do not agree with these
terms, please do not use, install, modify or redistribute this NVIDIA
software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, NVIDIA grants you a personal, non-exclusive
license, under NVIDIA's copyrights in this original NVIDIA software (the
"NVIDIA Software"), to use, reproduce, modify and redistribute the
NVIDIA Software, with or without modifications, in source and/or binary
forms; provided that if you redistribute the NVIDIA Software, you must
retain the copyright notice of NVIDIA, this notice and the following
text and disclaimers in all such redistributions of the NVIDIA Software.
Neither the name, trademarks, service marks nor logos of NVIDIA
Corporation may be used to endorse or promote products derived from the
NVIDIA Software without specific prior written permission from NVIDIA.
Except as expressly stated in this notice, no other rights or licenses
express or implied, are granted by NVIDIA herein, including but not
limited to any patent rights that may be infringed by your derivative
works or by other works in which the NVIDIA Software may be
incorporated. No hardware is licensed hereunder.
THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
PRODUCTS.
IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\****************************************************************************/
namespace glslang {
} // end namespace glslang
@@ -76,7 +76,9 @@ TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\****************************************************************************/
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <cstdlib>
#include <cstring>
@@ -101,9 +103,16 @@ int TPpContext::lFloatConst(int len, int ch, TPpToken* ppToken)
{
bool HasDecimalOrExponent = false;
int isDouble = 0;
bool generateFloat16 = false;
bool acceptFloat16 = parseContext.intermediate.getSource() == EShSourceHlsl;
bool isFloat16 = false;
bool requireHF = false;
#ifdef AMD_EXTENSIONS
int isFloat16 = 0;
bool enableFloat16 = parseContext.version >= 450 && parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_half_float);
if (parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_half_float)) {
acceptFloat16 = true;
generateFloat16 = true;
requireHF = true;
}
#endif
const auto saveName = [&](int ch) {
@@ -117,6 +126,35 @@ int TPpContext::lFloatConst(int len, int ch, TPpToken* ppToken)
HasDecimalOrExponent = true;
saveName(ch);
ch = getChar();
// 1.#INF or -1.#INF
if (ch == '#') {
if ((len < 2) ||
(len == 2 && ppToken->name[0] != '1') ||
(len == 3 && ppToken->name[1] != '1' && !(ppToken->name[0] == '-' || ppToken->name[0] == '+')) ||
(len > 3))
parseContext.ppError(ppToken->loc, "unexpected use of", "#", "");
else {
// we have 1.# or -1.# or +1.#, check for 'INF'
if ((ch = getChar()) != 'I' ||
(ch = getChar()) != 'N' ||
(ch = getChar()) != 'F')
parseContext.ppError(ppToken->loc, "expected 'INF'", "#", "");
else {
// we have [+-].#INF, and we are targeting IEEE 754, so wrap it up:
saveName('I');
saveName('N');
saveName('F');
ppToken->name[len] = '\0';
if (ppToken->name[0] == '-')
ppToken->i64val = 0xfff0000000000000; // -Infinity
else
ppToken->i64val = 0x7ff0000000000000; // +Infinity
return PpAtomConstFloat;
}
}
}
while (ch >= '0' && ch <= '9') {
saveName(ch);
ch = getChar();
@@ -158,21 +196,27 @@ int TPpContext::lFloatConst(int len, int ch, TPpToken* ppToken)
saveName(ch2);
isDouble = 1;
}
} else if (acceptFloat16 && (ch == 'h' || ch == 'H')) {
#ifdef AMD_EXTENSIONS
} else if (enableFloat16 && (ch == 'h' || ch == 'H')) {
parseContext.float16Check(ppToken->loc, "half floating-point suffix");
if (generateFloat16)
parseContext.float16Check(ppToken->loc, "half floating-point suffix");
#endif
if (!HasDecimalOrExponent)
parseContext.ppError(ppToken->loc, "float literal needs a decimal point or exponent", "", "");
int ch2 = getChar();
if (ch2 != 'f' && ch2 != 'F') {
ungetChar();
ungetChar();
if (requireHF) {
int ch2 = getChar();
if (ch2 != 'f' && ch2 != 'F') {
ungetChar();
ungetChar();
} else {
saveName(ch);
saveName(ch2);
isFloat16 = generateFloat16;
}
} else {
saveName(ch);
saveName(ch2);
isFloat16 = 1;
isFloat16 = generateFloat16;
}
#endif
} else if (ch == 'f' || ch == 'F') {
parseContext.profileRequires(ppToken->loc, EEsProfile, 300, nullptr, "floating-point suffix");
if (! parseContext.relaxedErrors())
@@ -197,14 +241,88 @@ int TPpContext::lFloatConst(int len, int ch, TPpToken* ppToken)
// Return the right token type
if (isDouble)
return PpAtomConstDouble;
#ifdef AMD_EXTENSIONS
else if (isFloat16)
return PpAtomConstFloat16;
#endif
else
return PpAtomConstFloat;
}
// Recognize a character literal.
//
// The first ' has already been accepted, read the rest, through the closing '.
//
// Always returns PpAtomConstInt.
//
int TPpContext::characterLiteral(TPpToken* ppToken)
{
ppToken->name[0] = 0;
ppToken->ival = 0;
if (parseContext.intermediate.getSource() != EShSourceHlsl) {
// illegal, except in macro definition, for which case we report the character
return '\'';
}
int ch = getChar();
switch (ch) {
case '\'':
// As empty sequence: ''
parseContext.ppError(ppToken->loc, "unexpected", "\'", "");
return PpAtomConstInt;
case '\\':
// As escape sequence: '\XXX'
switch (ch = getChar()) {
case 'a':
ppToken->ival = 7;
break;
case 'b':
ppToken->ival = 8;
break;
case 't':
ppToken->ival = 9;
break;
case 'n':
ppToken->ival = 10;
break;
case 'v':
ppToken->ival = 11;
break;
case 'f':
ppToken->ival = 12;
break;
case 'r':
ppToken->ival = 13;
break;
case 'x':
case '0':
parseContext.ppError(ppToken->loc, "octal and hex sequences not supported", "\\", "");
break;
default:
// This catches '\'', '\"', '\?', etc.
// Also, things like '\C' mean the same thing as 'C'
// (after the above cases are filtered out).
ppToken->ival = ch;
break;
}
break;
default:
ppToken->ival = ch;
break;
}
ppToken->name[0] = (char)ppToken->ival;
ppToken->name[1] = '\0';
ch = getChar();
if (ch != '\'') {
parseContext.ppError(ppToken->loc, "expected", "\'", "");
// Look ahead for a closing '
do {
ch = getChar();
} while (ch != '\'' && ch != EndOfInput && ch != '\n');
}
return PpAtomConstInt;
}
//
// Scanner used to tokenize source stream.
//
@@ -216,6 +334,18 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
int ii = 0;
unsigned long long ival = 0;
bool enableInt64 = pp->parseContext.version >= 450 && pp->parseContext.extensionTurnedOn(E_GL_ARB_gpu_shader_int64);
#ifdef AMD_EXTENSIONS
bool enableInt16 = pp->parseContext.version >= 450 && pp->parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_int16);
#endif
bool acceptHalf = pp->parseContext.intermediate.getSource() == EShSourceHlsl;
#ifdef AMD_EXTENSIONS
if (pp->parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_half_float))
acceptHalf = true;
#endif
const auto floatingPointChar = [&](int ch) { return ch == '.' || ch == 'e' || ch == 'E' ||
ch == 'f' || ch == 'F' ||
(acceptHalf && (ch == 'h' || ch == 'H')); };
ppToken->ival = 0;
ppToken->i64val = 0;
@@ -279,6 +409,9 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
bool isUnsigned = false;
bool isInt64 = false;
#ifdef AMD_EXTENSIONS
bool isInt16 = false;
#endif
ppToken->name[len++] = (char)ch;
ch = getch();
if ((ch >= '0' && ch <= '9') ||
@@ -287,7 +420,7 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
ival = 0;
do {
if (ival <= 0x0fffffff || (enableInt64 && ival <= 0x0fffffffffffffffull)) {
if (ival <= 0x0fffffffu || (enableInt64 && ival <= 0x0fffffffffffffffull)) {
ppToken->name[len++] = (char)ch;
if (ch >= '0' && ch <= '9') {
ii = ch - '0';
@@ -326,11 +459,28 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
} else
ungetch();
}
}
else if (enableInt64 && (ch == 'l' || ch == 'L')) {
#ifdef AMD_EXTENSIONS
if (enableInt16) {
int nextCh = getch();
if ((ch == 'u' && nextCh == 's') || (ch == 'U' && nextCh == 'S')) {
if (len < MaxTokenLength)
ppToken->name[len++] = (char)nextCh;
isInt16 = true;
} else
ungetch();
}
#endif
} else if (enableInt64 && (ch == 'l' || ch == 'L')) {
if (len < MaxTokenLength)
ppToken->name[len++] = (char)ch;
isInt64 = true;
#ifdef AMD_EXTENSIONS
} else if (enableInt16 && (ch == 's' || ch == 'S')) {
if (len < MaxTokenLength)
ppToken->name[len++] = (char)ch;
isInt16 = true;
#endif
} else
ungetch();
ppToken->name[len] = '\0';
@@ -338,6 +488,11 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
if (isInt64) {
ppToken->i64val = ival;
return isUnsigned ? PpAtomConstUint64 : PpAtomConstInt64;
#ifdef AMD_EXTENSIONS
} else if (isInt16) {
ppToken->ival = (int)ival;
return isUnsigned ? PpAtomConstUint16 : PpAtomConstInt16;
#endif
} else {
ppToken->ival = (int)ival;
return isUnsigned ? PpAtomConstUint : PpAtomConstInt;
@@ -347,6 +502,9 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
bool isUnsigned = false;
bool isInt64 = false;
#ifdef AMD_EXTENSIONS
bool isInt16 = false;
#endif
bool octalOverflow = false;
bool nonOctal = false;
ival = 0;
@@ -359,7 +517,7 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
pp->parseContext.ppError(ppToken->loc, "numeric literal too long", "", "");
AlreadyComplained = 1;
}
if (ival <= 0x1fffffff || (enableInt64 && ival <= 0x1fffffffffffffffull)) {
if (ival <= 0x1fffffffu || (enableInt64 && ival <= 0x1fffffffffffffffull)) {
ii = ch - '0';
ival = (ival << 3) | ii;
} else
@@ -380,7 +538,7 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
ch = getch();
} while (ch >= '0' && ch <= '9');
}
if (ch == '.' || ch == 'e' || ch == 'f' || ch == 'E' || ch == 'F')
if (floatingPointChar(ch))
return pp->lFloatConst(len, ch, ppToken);
// wasn't a float, so must be octal...
@@ -401,11 +559,28 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
} else
ungetch();
}
}
else if (enableInt64 && (ch == 'l' || ch == 'L')) {
#ifdef AMD_EXTENSIONS
if (enableInt16) {
int nextCh = getch();
if ((ch == 'u' && nextCh == 's') || (ch == 'U' && nextCh == 'S')) {
if (len < MaxTokenLength)
ppToken->name[len++] = (char)nextCh;
isInt16 = true;
} else
ungetch();
}
#endif
} else if (enableInt64 && (ch == 'l' || ch == 'L')) {
if (len < MaxTokenLength)
ppToken->name[len++] = (char)ch;
isInt64 = true;
#ifdef AMD_EXTENSIONS
} else if (enableInt16 && (ch == 's' || ch == 'S')) {
if (len < MaxTokenLength)
ppToken->name[len++] = (char)ch;
isInt16 = true;
#endif
} else
ungetch();
ppToken->name[len] = '\0';
@@ -416,6 +591,11 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
if (isInt64) {
ppToken->i64val = ival;
return isUnsigned ? PpAtomConstUint64 : PpAtomConstInt64;
#ifdef AMD_EXTENSIONS
} else if (isInt16) {
ppToken->ival = (int)ival;
return isUnsigned ? PpAtomConstUint16 : PpAtomConstInt16;
#endif
} else {
ppToken->ival = (int)ival;
return isUnsigned ? PpAtomConstUint : PpAtomConstInt;
@@ -435,13 +615,16 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
}
ch = getch();
} while (ch >= '0' && ch <= '9');
if (ch == '.' || ch == 'e' || ch == 'f' || ch == 'E' || ch == 'F') {
if (floatingPointChar(ch))
return pp->lFloatConst(len, ch, ppToken);
} else {
else {
// Finish handling signed and unsigned integers
int numericLen = len;
bool isUnsigned = false;
bool isInt64 = false;
#ifdef AMD_EXTENSIONS
bool isInt16 = false;
#endif
if (ch == 'u' || ch == 'U') {
if (len < MaxTokenLength)
ppToken->name[len++] = (char)ch;
@@ -456,10 +639,28 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
} else
ungetch();
}
#ifdef AMD_EXTENSIONS
if (enableInt16) {
int nextCh = getch();
if ((ch == 'u' && nextCh == 's') || (ch == 'U' && nextCh == 'S')) {
if (len < MaxTokenLength)
ppToken->name[len++] = (char)nextCh;
isInt16 = true;
} else
ungetch();
}
#endif
} else if (enableInt64 && (ch == 'l' || ch == 'L')) {
if (len < MaxTokenLength)
ppToken->name[len++] = (char)ch;
isInt64 = true;
#ifdef AMD_EXTENSIONS
} else if (enableInt16 && (ch == 's' || ch == 'S')) {
if (len < MaxTokenLength)
ppToken->name[len++] = (char)ch;
isInt16 = true;
#endif
} else
ungetch();
@@ -469,10 +670,22 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
const unsigned remainderMaxInt = 0xFFFFFFFFu - 10 * oneTenthMaxInt;
const unsigned long long oneTenthMaxInt64 = 0xFFFFFFFFFFFFFFFFull / 10;
const unsigned long long remainderMaxInt64 = 0xFFFFFFFFFFFFFFFFull - 10 * oneTenthMaxInt64;
#ifdef AMD_EXTENSIONS
const unsigned short oneTenthMaxInt16 = 0xFFFFu / 10;
const unsigned short remainderMaxInt16 = 0xFFFFu - 10 * oneTenthMaxInt16;
#endif
for (int i = 0; i < numericLen; i++) {
ch = ppToken->name[i] - '0';
if ((enableInt64 == false && ((ival > oneTenthMaxInt) || (ival == oneTenthMaxInt && (unsigned)ch > remainderMaxInt))) ||
(enableInt64 && ((ival > oneTenthMaxInt64) || (ival == oneTenthMaxInt64 && (unsigned long long)ch > remainderMaxInt64)))) {
bool overflow = false;
if (isInt64)
overflow = (ival > oneTenthMaxInt64 || (ival == oneTenthMaxInt64 && (unsigned long long)ch > remainderMaxInt64));
#ifdef AMD_EXTENSIONS
else if (isInt16)
overflow = (ival > oneTenthMaxInt16 || (ival == oneTenthMaxInt16 && (unsigned short)ch > remainderMaxInt16));
#endif
else
overflow = (ival > oneTenthMaxInt || (ival == oneTenthMaxInt && (unsigned)ch > remainderMaxInt));
if (overflow) {
pp->parseContext.ppError(ppToken->loc, "numeric literal too big", "", "");
ival = 0xFFFFFFFFFFFFFFFFull;
break;
@@ -483,6 +696,11 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
if (isInt64) {
ppToken->i64val = ival;
return isUnsigned ? PpAtomConstUint64 : PpAtomConstInt64;
#ifdef AMD_EXTENSIONS
} else if (isInt16) {
ppToken->ival = (int)ival;
return isUnsigned ? PpAtomConstUint16 : PpAtomConstInt16;
#endif
} else {
ppToken->ival = (int)ival;
return isUnsigned ? PpAtomConstUint : PpAtomConstInt;
@@ -652,6 +870,8 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
return '/';
}
break;
case '\'':
return pp->characterLiteral(ppToken);
case '"':
// TODO: If this gets enhanced to handle escape sequences, or
// anything that is different than what #include needs, then
@@ -671,6 +891,12 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
pp->parseContext.ppError(ppToken->loc, "End of line in string", "string", "");
}
return PpAtomConstString;
case ':':
ch = getch();
if (ch == ':')
return PpAtomColonColon;
ungetch();
return ':';
}
ch = getch();
@@ -724,6 +950,10 @@ int TPpContext::tokenize(TPpToken& ppToken)
case PpAtomConstFloat:
case PpAtomConstInt64:
case PpAtomConstUint64:
#ifdef AMD_EXTENSIONS
case PpAtomConstInt16:
case PpAtomConstUint16:
#endif
case PpAtomConstDouble:
#ifdef AMD_EXTENSIONS
case PpAtomConstFloat16:
@@ -773,6 +1003,7 @@ int TPpContext::tokenPaste(int token, TPpToken& ppToken)
token = scanToken(&pastedPpToken);
assert(token == PpAtomPaste);
// This covers end of macro expansion
if (endOfReplacementList()) {
parseContext.ppError(ppToken.loc, "unexpected location; end of replacement list", "##", "");
break;
@@ -781,6 +1012,12 @@ int TPpContext::tokenPaste(int token, TPpToken& ppToken)
// get the token after the ##
token = scanToken(&pastedPpToken);
// This covers end of argument expansion
if (token == tMarkerInput::marker) {
parseContext.ppError(ppToken.loc, "unexpected location; end of argument", "##", "");
break;
}
// get the token text
switch (resultToken) {
case PpAtomIdentifier:
@@ -1,77 +0,0 @@
//
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2013 LunarG, Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
//
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
/****************************************************************************\
Copyright (c) 2002, NVIDIA Corporation.
NVIDIA Corporation("NVIDIA") supplies this software to you in
consideration of your agreement to the following terms, and your use,
installation, modification or redistribution of this NVIDIA software
constitutes acceptance of these terms. If you do not agree with these
terms, please do not use, install, modify or redistribute this NVIDIA
software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, NVIDIA grants you a personal, non-exclusive
license, under NVIDIA's copyrights in this original NVIDIA software (the
"NVIDIA Software"), to use, reproduce, modify and redistribute the
NVIDIA Software, with or without modifications, in source and/or binary
forms; provided that if you redistribute the NVIDIA Software, you must
retain the copyright notice of NVIDIA, this notice and the following
text and disclaimers in all such redistributions of the NVIDIA Software.
Neither the name, trademarks, service marks nor logos of NVIDIA
Corporation may be used to endorse or promote products derived from the
NVIDIA Software without specific prior written permission from NVIDIA.
Except as expressly stated in this notice, no other rights or licenses
express or implied, are granted by NVIDIA herein, including but not
limited to any patent rights that may be infringed by your derivative
works or by other works in which the NVIDIA Software may be
incorporated. No hardware is licensed hereunder.
THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
PRODUCTS.
IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\****************************************************************************/
@@ -80,8 +80,10 @@ NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// For recording and playing back the stream of tokens in a macro definition.
//
#if (defined(_MSC_VER) && _MSC_VER < 1900 /*vs2015*/)
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif
#if (defined(_MSC_VER) && _MSC_VER < 1900 /*vs2015*/)
#define snprintf sprintf_s
#endif
@@ -96,9 +98,8 @@ NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace glslang {
// push onto back of stream
void TPpContext::TokenStream::putSubtoken(int subtoken)
void TPpContext::TokenStream::putSubtoken(char subtoken)
{
assert((subtoken & ~0xff) == 0);
data.push_back(static_cast<unsigned char>(subtoken));
}
@@ -125,7 +126,8 @@ void TPpContext::TokenStream::putToken(int token, TPpToken* ppToken)
const char* s;
char* str = NULL;
putSubtoken(token);
assert((token & ~0xff) == 0);
putSubtoken(static_cast<char>(token));
switch (token) {
case PpAtomIdentifier:
@@ -139,6 +141,10 @@ void TPpContext::TokenStream::putToken(int token, TPpToken* ppToken)
case PpAtomConstUint:
case PpAtomConstInt64:
case PpAtomConstUint64:
#ifdef AMD_EXTENSIONS
case PpAtomConstInt16:
case PpAtomConstUint16:
#endif
case PpAtomConstFloat:
case PpAtomConstDouble:
#ifdef AMD_EXTENSIONS
@@ -188,6 +194,10 @@ int TPpContext::TokenStream::getToken(TParseContextBase& parseContext, TPpToken
case PpAtomConstUint:
case PpAtomConstInt64:
case PpAtomConstUint64:
#ifdef AMD_EXTENSIONS
case PpAtomConstInt16:
case PpAtomConstUint16:
#endif
len = 0;
ch = getSubtoken();
while (ch != 0 && ch != EndOfInput) {
@@ -215,6 +225,9 @@ int TPpContext::TokenStream::getToken(TParseContextBase& parseContext, TPpToken
ppToken->dval = atof(ppToken->name);
break;
case PpAtomConstInt:
#ifdef AMD_EXTENSIONS
case PpAtomConstInt16:
#endif
if (len > 0 && ppToken->name[0] == '0') {
if (len > 1 && (ppToken->name[1] == 'x' || ppToken->name[1] == 'X'))
ppToken->ival = (int)strtol(ppToken->name, 0, 16);
@@ -224,6 +237,9 @@ int TPpContext::TokenStream::getToken(TParseContextBase& parseContext, TPpToken
ppToken->ival = atoi(ppToken->name);
break;
case PpAtomConstUint:
#ifdef AMD_EXTENSIONS
case PpAtomConstUint16:
#endif
if (len > 0 && ppToken->name[0] == '0') {
if (len > 1 && (ppToken->name[1] == 'x' || ppToken->name[1] == 'X'))
ppToken->ival = (int)strtoul(ppToken->name, 0, 16);
@@ -117,6 +117,8 @@ enum EFixedAtoms {
PpAtomDecrement,
PpAtomIncrement,
PpAtomColonColon,
PpAtomPaste,
// Constants
@@ -125,11 +127,13 @@ enum EFixedAtoms {
PpAtomConstUint,
PpAtomConstInt64,
PpAtomConstUint64,
#ifdef AMD_EXTENSIONS
PpAtomConstInt16,
PpAtomConstUint16,
#endif
PpAtomConstFloat,
PpAtomConstDouble,
#ifdef AMD_EXTENSIONS
PpAtomConstFloat16,
#endif
PpAtomConstString,
// Identifiers
@@ -37,6 +37,8 @@
// propagate 'noContraction' qualifier.
//
#pragma once
#include "../Include/intermediate.h"
namespace glslang {
@@ -696,14 +696,40 @@ void TReflectionTraverser::visitSymbol(TIntermSymbol* base)
// Implement TReflection methods.
//
// Track any required attribute reflection, such as compute shader numthreads.
//
void TReflection::buildAttributeReflection(EShLanguage stage, const TIntermediate& intermediate)
{
if (stage == EShLangCompute) {
// Remember thread dimensions
for (int dim=0; dim<3; ++dim)
localSize[dim] = intermediate.getLocalSize(dim);
}
}
// build counter block index associations for buffers
void TReflection::buildCounterIndices()
{
// search for ones that have counters
for (int i = 0; i < int(indexToUniformBlock.size()); ++i) {
const TString counterName(indexToUniformBlock[i].name + "@count");
const int index = getIndex(counterName);
if (index >= 0)
indexToUniformBlock[i].counterIndex = index;
}
}
// Merge live symbols from 'intermediate' into the existing reflection database.
//
// Returns false if the input is too malformed to do this.
bool TReflection::addStage(EShLanguage, const TIntermediate& intermediate)
bool TReflection::addStage(EShLanguage stage, const TIntermediate& intermediate)
{
if (intermediate.getNumEntryPoints() != 1 || intermediate.isRecursive())
return false;
buildAttributeReflection(stage, intermediate);
TReflectionTraverser it(intermediate, *this);
// put the entry point on the list of functions to process
@@ -716,6 +742,8 @@ bool TReflection::addStage(EShLanguage, const TIntermediate& intermediate)
function->traverse(&it);
}
buildCounterIndices();
return true;
}
@@ -736,6 +764,16 @@ void TReflection::dump()
indexToAttribute[i].dump();
printf("\n");
if (getLocalSize(0) > 1) {
static const char* axis[] = { "X", "Y", "Z" };
for (int dim=0; dim<3; ++dim)
if (getLocalSize(dim) > 1)
printf("Local size %s: %d\n", axis[dim], getLocalSize(dim));
printf("\n");
}
// printf("Live names\n");
// for (TNameToIndex::const_iterator it = nameToIndex.begin(); it != nameToIndex.end(); ++it)
// printf("%s: %d\n", it->first.c_str(), it->second);
@@ -57,11 +57,16 @@ class TObjectReflection {
public:
TObjectReflection(const TString& pName, const TType& pType, int pOffset, int pGLDefineType, int pSize, int pIndex) :
name(pName), offset(pOffset),
glDefineType(pGLDefineType), size(pSize), index(pIndex), type(pType.clone()) { }
glDefineType(pGLDefineType), size(pSize), index(pIndex), counterIndex(-1), type(pType.clone()) { }
void dump() const {
printf("%s: offset %d, type %x, size %d, index %d, binding %d\n",
printf("%s: offset %d, type %x, size %d, index %d, binding %d",
name.c_str(), offset, glDefineType, size, index, getBinding() );
if (counterIndex != -1)
printf(", counter %d", counterIndex);
printf("\n");
}
const TType* const getType() const { return type; }
@@ -71,6 +76,7 @@ public:
int glDefineType;
int size; // data size in bytes for a block, array size for a (non-block) object that's an array
int index;
int counterIndex;
static TObjectReflection badReflection() { return TObjectReflection(); }
@@ -89,7 +95,12 @@ protected:
// The full reflection database
class TReflection {
public:
TReflection() : badReflection(TObjectReflection::badReflection()) { }
TReflection() : badReflection(TObjectReflection::badReflection())
{
for (int dim=0; dim<3; ++dim)
localSize[dim] = 0;
}
virtual ~TReflection() {}
// grow the reflection stage by stage
@@ -135,11 +146,20 @@ public:
return it->second;
}
// see getIndex(const char*)
int getIndex(const TString& name) const { return getIndex(name.c_str()); }
// Thread local size
unsigned getLocalSize(int dim) const { return dim <= 2 ? localSize[dim] : 0; }
void dump();
protected:
friend class glslang::TReflectionTraverser;
void buildCounterIndices();
void buildAttributeReflection(EShLanguage, const TIntermediate&);
// Need a TString hash: typedef std::unordered_map<TString, int> TNameToIndex;
typedef std::map<TString, int> TNameToIndex;
typedef std::vector<TObjectReflection> TMapIndexToReflection;
@@ -149,6 +169,8 @@ protected:
TMapIndexToReflection indexToUniform;
TMapIndexToReflection indexToUniformBlock;
TMapIndexToReflection indexToAttribute;
unsigned int localSize[3];
};
} // end namespace glslang
@@ -184,20 +184,6 @@ void ReleaseGlobalLock()
pthread_mutex_unlock(&gMutex);
}
// TODO: non-windows: if we need these on linux, flesh them out
void* OS_CreateThread(TThreadEntrypoint /*entry*/)
{
return 0;
}
void OS_WaitForAllThreads(void* /*threads*/, int /*numThreads*/)
{
}
void OS_Sleep(int /*milliseconds*/)
{
}
void OS_DumpMemoryCounters()
{
}
@@ -131,21 +131,6 @@ unsigned int __stdcall EnterGenericThread (void* entry)
return ((TThreadEntrypoint)entry)(0);
}
void* OS_CreateThread(TThreadEntrypoint entry)
{
return (void*)_beginthreadex(0, 0, EnterGenericThread, (void*)entry, 0, 0);
}
void OS_WaitForAllThreads(void* threads, int numThreads)
{
WaitForMultipleObjects(numThreads, (HANDLE*)threads, true, INFINITE);
}
void OS_Sleep(int milliseconds)
{
Sleep(milliseconds);
}
//#define DUMP_COUNTERS
void OS_DumpMemoryCounters()
@@ -53,11 +53,8 @@ void GetGlobalLock();
void ReleaseGlobalLock();
typedef unsigned int (*TThreadEntrypoint)(void*);
void* OS_CreateThread(TThreadEntrypoint);
void OS_WaitForAllThreads(void* threads, int numThreads);
void OS_CleanupThreadData(void);
void OS_Sleep(int milliseconds);
void OS_DumpMemoryCounters();
@@ -40,6 +40,7 @@
#include "../MachineIndependent/Versions.h"
#include <cstring>
#include <vector>
#ifdef _WIN32
#define C_DECL __cdecl
@@ -133,6 +134,14 @@ typedef enum {
EShOptFull, // Optimizations that will take more time
} EShOptimizationLevel;
//
// Texture and Sampler transformation mode.
//
typedef enum {
EShTexSampTransKeep, // keep textures and samplers as is (default)
EShTexSampTransUpgradeTextureRemoveSampler, // change texture w/o embeded sampler into sampled texture and throw away all samplers
} EShTextureSamplerTransformMode;
//
// Message choices for what errors and warnings are given.
//
@@ -147,6 +156,8 @@ enum EShMessages {
EShMsgReadHlsl = (1 << 6), // use HLSL parsing rules and semantics
EShMsgCascadingErrors = (1 << 7), // get cascading errors; risks error-recovery issues, instead of an early exit
EShMsgKeepUncalled = (1 << 8), // for testing, don't eliminate uncalled functions
EShMsgHlslOffsets = (1 << 9), // allow block offsets to follow HLSL rules instead of GLSL rules
EShMsgDebugInfo = (1 << 10), // save debug information
};
//
@@ -203,14 +214,6 @@ SH_IMPORT_EXPORT int ShCompile(
EShMessages messages = EShMsgDefault // warnings and errors
);
SH_IMPORT_EXPORT int ShLink(
const ShHandle, // linker object
const ShHandle h[], // compiler objects to link together
const int numHandles,
ShHandle uniformMap, // updated with new uniforms
short int** uniformsAccessed, // returned with indexes of uniforms accessed
int* numUniformsAccessed);
SH_IMPORT_EXPORT int ShLinkExt(
const ShHandle, // linker object
const ShHandle h[], // compiler objects to link together
@@ -310,9 +313,16 @@ public:
void setShiftTextureBinding(unsigned int base);
void setShiftImageBinding(unsigned int base);
void setShiftUboBinding(unsigned int base);
void setShiftUavBinding(unsigned int base);
void setShiftCbufferBinding(unsigned int base); // synonym for setShiftUboBinding
void setShiftSsboBinding(unsigned int base);
void setResourceSetBinding(const std::vector<std::string>& base);
void setAutoMapBindings(bool map);
void setAutoMapLocations(bool map);
void setHlslIoMapping(bool hlslIoMap);
void setFlattenUniformArrays(bool flatten);
void setNoStorageFormat(bool useUnknownFormat);
void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode);
// Interface to #include handlers.
//
@@ -397,6 +407,9 @@ public:
virtual void releaseInclude(IncludeResult*) override { }
};
bool parse(const TBuiltInResource*, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile,
bool forwardCompatible, EShMessages, Includer&);
bool parse(const TBuiltInResource* res, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile,
bool forwardCompatible, EShMessages messages)
{
@@ -404,12 +417,18 @@ public:
return parse(res, defaultVersion, defaultProfile, forceDefaultVersionAndProfile, forwardCompatible, messages, includer);
}
bool parse(const TBuiltInResource*, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile,
bool forwardCompatible, EShMessages, Includer&);
// Equivalent to parse() without a default profile and without forcing defaults.
// Provided for backwards compatibility.
bool parse(const TBuiltInResource*, int defaultVersion, bool forwardCompatible, EShMessages);
bool parse(const TBuiltInResource* builtInResources, int defaultVersion, bool forwardCompatible, EShMessages messages)
{
return parse(builtInResources, defaultVersion, ENoProfile, false, forwardCompatible, messages);
}
bool parse(const TBuiltInResource* builtInResources, int defaultVersion, bool forwardCompatible, EShMessages messages,
Includer& includer)
{
return parse(builtInResources, defaultVersion, ENoProfile, false, forwardCompatible, messages, includer);
}
bool preprocess(const TBuiltInResource* builtInResources,
int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile,
bool forwardCompatible, EShMessages message, std::string* outputString,
@@ -459,10 +478,19 @@ class TIoMapper;
// and resolveSet are invoked to resolve the binding and descriptor
// set index respectively.
// Invocations happen in a particular order:
// 1) var with binding and set already defined
// 2) var with binding but no set defined
// 3) var with set but no binding defined
// 4) var with no binding and no set defined
// 1) all shader inputs
// 2) all shader outputs
// 3) all uniforms with binding and set already defined
// 4) all uniforms with binding but no set defined
// 5) all uniforms with set but no binding defined
// 6) all uniforms with no binding and no set defined
//
// mapIO will use this resolver in two phases. The first
// phase is a notification phase, calling the corresponging
// notifiy callbacks, this phase ends with a call to endNotifications.
// Phase two starts directly after the call to endNotifications
// and calls all other callbacks to validate and to get the
// bindings, sets, locations, component and color indices.
//
// NOTE: that still limit checks are applied to bindings and sets
// and may result in an error.
@@ -471,15 +499,33 @@ class TIoMapResolver
public:
virtual ~TIoMapResolver() {}
// Should return true if the resulting/current binding would be ok.
// Should return true if the resulting/current binding would be okay.
// Basic idea is to do aliasing binding checks with this.
virtual bool validateBinding(EShLanguage stage, const char* name, const TType& type, bool is_live) = 0;
// Should return a value >= 0 if the current binding should be overridden.
// Return -1 if the current binding (including no binding) should be kept.
virtual int resolveBinding(EShLanguage stage, const char* name, const TType& type, bool is_live) = 0;
// Should return a value >= 0 if the current set should be overriden.
// Should return a value >= 0 if the current set should be overridden.
// Return -1 if the current set (including no set) should be kept.
virtual int resolveSet(EShLanguage stage, const char* name, const TType& type, bool is_live) = 0;
// Should return true if the resulting/current setup would be okay.
// Basic idea is to do aliasing checks and reject invalid semantic names.
virtual bool validateInOut(EShLanguage stage, const char* name, const TType& type, bool is_live) = 0;
// Should return a value >= 0 if the current location should be overridden.
// Return -1 if the current location (including no location) should be kept.
virtual int resolveInOutLocation(EShLanguage stage, const char* name, const TType& type, bool is_live) = 0;
// Should return a value >= 0 if the current component index should be overridden.
// Return -1 if the current component index (including no index) should be kept.
virtual int resolveInOutComponent(EShLanguage stage, const char* name, const TType& type, bool is_live) = 0;
// Should return a value >= 0 if the current color index should be overridden.
// Return -1 if the current color index (including no index) should be kept.
virtual int resolveInOutIndex(EShLanguage stage, const char* name, const TType& type, bool is_live) = 0;
// Notification of a uniform variable
virtual void notifyBinding(EShLanguage stage, const char* name, const TType& type, bool is_live) = 0;
// Notification of a in or out variable
virtual void notifyInOut(EShLanguage stage, const char* name, const TType& type, bool is_live) = 0;
// Called by mapIO when it has finished the notify pass
virtual void endNotifications() = 0;
};
// Make one TProgram per set of shaders that will get linked together. Add all
@@ -510,10 +556,12 @@ public:
int getUniformBlockSize(int blockIndex) const; // can be used for glGetActiveUniformBlockiv(UNIFORM_BLOCK_DATA_SIZE)
int getUniformIndex(const char* name) const; // can be used for glGetUniformIndices()
int getUniformBlockIndex(int index) const; // can be used for glGetActiveUniformsiv(GL_UNIFORM_BLOCK_INDEX)
int getUniformBlockCounterIndex(int index) const; // returns block index of associated counter.
int getUniformType(int index) const; // can be used for glGetActiveUniformsiv(GL_UNIFORM_TYPE)
int getUniformBufferOffset(int index) const; // can be used for glGetActiveUniformsiv(GL_UNIFORM_OFFSET)
int getUniformArraySize(int index) const; // can be used for glGetActiveUniformsiv(GL_UNIFORM_SIZE)
int getNumLiveAttributes() const; // can be used for glGetProgramiv(GL_ACTIVE_ATTRIBUTES)
unsigned getLocalSize(int dim) const; // return dim'th local size
const char *getAttributeName(int index) const; // can be used for glGetActiveAttrib()
int getAttributeType(int index) const; // can be used for glGetActiveAttrib()
const TType* getUniformTType(int index) const; // returns a TType*