mirror of
https://github.com/love2d/love.git
synced 2026-08-16 00:02:12 +02:00
Update glslang
--HG-- branch : minor
This commit is contained in:
@@ -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";
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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*
|
||||
|
||||
Reference in New Issue
Block a user