Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
2f4c832d47
484 changed files with 101726 additions and 19867 deletions
|
|
@ -10,10 +10,12 @@ set(SOURCES
|
|||
MachineIndependent/glslang.y
|
||||
MachineIndependent/glslang_tab.cpp
|
||||
MachineIndependent/Constant.cpp
|
||||
MachineIndependent/iomapper.cpp
|
||||
MachineIndependent/InfoSink.cpp
|
||||
MachineIndependent/Initialize.cpp
|
||||
MachineIndependent/IntermTraverse.cpp
|
||||
MachineIndependent/Intermediate.cpp
|
||||
MachineIndependent/ParseContextBase.cpp
|
||||
MachineIndependent/ParseHelper.cpp
|
||||
MachineIndependent/PoolAlloc.cpp
|
||||
MachineIndependent/RemoveTree.cpp
|
||||
|
|
@ -54,6 +56,8 @@ set(HEADERS
|
|||
MachineIndependent/glslang_tab.cpp.h
|
||||
MachineIndependent/gl_types.h
|
||||
MachineIndependent/Initialize.h
|
||||
MachineIndependent/iomapper.h
|
||||
MachineIndependent/LiveTraverser.h
|
||||
MachineIndependent/localintermediate.h
|
||||
MachineIndependent/ParseHelper.h
|
||||
MachineIndependent/reflection.h
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ class TGenericLinker : public TLinker {
|
|||
public:
|
||||
TGenericLinker(EShExecutable e, int dOptions) : TLinker(e, infoSink), debugOptions(dOptions) { }
|
||||
bool link(TCompilerList&, TUniformMap*) { return true; }
|
||||
void getAttributeBindings(ShBindingTable const **) const { }
|
||||
void getAttributeBindings(ShBindingTable const **) const { }
|
||||
TInfoSink infoSink;
|
||||
int debugOptions;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -46,6 +46,9 @@ enum TBasicType {
|
|||
EbtVoid,
|
||||
EbtFloat,
|
||||
EbtDouble,
|
||||
#ifdef AMD_EXTENSIONS
|
||||
EbtFloat16,
|
||||
#endif
|
||||
EbtInt,
|
||||
EbtUint,
|
||||
EbtInt64,
|
||||
|
|
@ -55,6 +58,10 @@ enum TBasicType {
|
|||
EbtSampler,
|
||||
EbtStruct,
|
||||
EbtBlock,
|
||||
|
||||
// HLSL types that live only temporarily.
|
||||
EbtString,
|
||||
|
||||
EbtNumTypes
|
||||
};
|
||||
|
||||
|
|
@ -186,6 +193,20 @@ enum TBuiltInVariable {
|
|||
EbvSamplePosition,
|
||||
EbvSampleMask,
|
||||
EbvHelperInvocation,
|
||||
#ifdef AMD_EXTENSIONS
|
||||
EbvBaryCoordNoPersp,
|
||||
EbvBaryCoordNoPerspCentroid,
|
||||
EbvBaryCoordNoPerspSample,
|
||||
EbvBaryCoordSmooth,
|
||||
EbvBaryCoordSmoothCentroid,
|
||||
EbvBaryCoordSmoothSample,
|
||||
EbvBaryCoordPullModel,
|
||||
#endif
|
||||
|
||||
// HLSL built-ins that live only temporarily, until they get remapped
|
||||
// to one of the above.
|
||||
EbvFragDepthGreater,
|
||||
EbvFragDepthLesser,
|
||||
|
||||
EbvLast
|
||||
};
|
||||
|
|
@ -286,6 +307,15 @@ __inline const char* GetBuiltInVariableString(TBuiltInVariable v)
|
|||
case EbvSamplePosition: return "SamplePosition";
|
||||
case EbvSampleMask: return "SampleMaskIn";
|
||||
case EbvHelperInvocation: return "HelperInvocation";
|
||||
#ifdef AMD_EXTENSIONS
|
||||
case EbvBaryCoordNoPersp: return "BaryCoordNoPersp";
|
||||
case EbvBaryCoordNoPerspCentroid: return "BaryCoordNoPerspCentroid";
|
||||
case EbvBaryCoordNoPerspSample: return "BaryCoordNoPerspSample";
|
||||
case EbvBaryCoordSmooth: return "BaryCoordSmooth";
|
||||
case EbvBaryCoordSmoothCentroid: return "BaryCoordSmoothCentroid";
|
||||
case EbvBaryCoordSmoothSample: return "BaryCoordSmoothSample";
|
||||
case EbvBaryCoordPullModel: return "BaryCoordPullModel";
|
||||
#endif
|
||||
default: return "unknown built-in variable";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,6 +68,10 @@ inline long long int strtoll (const char* str, char** endptr, int base)
|
|||
{
|
||||
return _strtoi64(str, endptr, base);
|
||||
}
|
||||
inline unsigned long long int strtoull (const char* str, char** endptr, int base)
|
||||
{
|
||||
return _strtoui64(str, endptr, base);
|
||||
}
|
||||
inline long long int atoll (const char* str)
|
||||
{
|
||||
return strtoll(str, NULL, 10);
|
||||
|
|
@ -93,8 +97,8 @@ inline long long int atoll (const char* str)
|
|||
#include <list>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
|
||||
#include "PoolAlloc.h"
|
||||
|
||||
|
|
@ -103,11 +107,11 @@ inline long long int atoll (const char* str)
|
|||
//
|
||||
#define POOL_ALLOCATOR_NEW_DELETE(A) \
|
||||
void* operator new(size_t s) { return (A).allocate(s); } \
|
||||
void* operator new(size_t, void *_Where) { return (_Where); } \
|
||||
void* operator new(size_t, void *_Where) { return (_Where); } \
|
||||
void operator delete(void*) { } \
|
||||
void operator delete(void *, void *) { } \
|
||||
void* operator new[](size_t s) { return (A).allocate(s); } \
|
||||
void* operator new[](size_t, void *_Where) { return (_Where); } \
|
||||
void* operator new[](size_t, void *_Where) { return (_Where); } \
|
||||
void operator delete[](void*) { } \
|
||||
void operator delete[](void *, void *) { }
|
||||
|
||||
|
|
@ -201,20 +205,25 @@ template <class T> T Max(const T a, const T b) { return a > b ? a : b; }
|
|||
//
|
||||
// Create a TString object from an integer.
|
||||
//
|
||||
#if defined _MSC_VER || defined MINGW_HAS_SECURE_API
|
||||
inline const TString String(const int i, const int base = 10)
|
||||
{
|
||||
char text[16]; // 32 bit ints are at most 10 digits in base 10
|
||||
_itoa_s(i, text, sizeof(text), base);
|
||||
return text;
|
||||
}
|
||||
#else
|
||||
inline const TString String(const int i, const int /*base*/ = 10)
|
||||
{
|
||||
char text[16]; // 32 bit ints are at most 10 digits in base 10
|
||||
|
||||
#if defined _MSC_VER || defined MINGW_HAS_SECURE_API
|
||||
_itoa_s(i, text, sizeof(text), base);
|
||||
#else
|
||||
// we assume base 10 for all cases
|
||||
snprintf(text, sizeof(text), "%d", i);
|
||||
#endif
|
||||
// we assume base 10 for all cases
|
||||
snprintf(text, sizeof(text), "%d", i);
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
struct TSourceLoc {
|
||||
void init() { name = nullptr; string = 0; line = 0; column = 0; }
|
||||
// Returns the name if it exists. Otherwise, returns the string number.
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@
|
|||
#define _INFOSINK_INCLUDED_
|
||||
|
||||
#include "../Include/Common.h"
|
||||
#include <math.h>
|
||||
#include <cmath>
|
||||
|
||||
namespace glslang {
|
||||
|
||||
|
|
@ -74,7 +74,6 @@ public:
|
|||
TInfoSinkBase& operator<<(const char* s) { append(s); return *this; }
|
||||
TInfoSinkBase& operator<<(int n) { append(String(n)); return *this; }
|
||||
TInfoSinkBase& operator<<(unsigned int n) { append(String(n)); return *this; }
|
||||
TInfoSinkBase& operator<<(long unsigned int n) { append(String(n)); return *this; }
|
||||
TInfoSinkBase& operator<<(float n) { const int size = 40; char buf[size];
|
||||
snprintf(buf, size, (fabs(n) > 1e-8 && fabs(n) < 1e8) || n == 0.0f ? "%f" : "%g", n);
|
||||
append(buf);
|
||||
|
|
|
|||
|
|
@ -61,13 +61,13 @@
|
|||
// class as the allocator (second) template argument.
|
||||
//
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
|
||||
namespace glslang {
|
||||
|
||||
// If we are using guard blocks, we must track each indivual
|
||||
// If we are using guard blocks, we must track each individual
|
||||
// allocation. If we aren't using guard blocks, these
|
||||
// never get instantiated, so won't have any impact.
|
||||
//
|
||||
|
|
@ -297,10 +297,10 @@ public:
|
|||
pointer allocate(size_type n, const void*) {
|
||||
return reinterpret_cast<pointer>(getAllocator().allocate(n * sizeof(T))); }
|
||||
|
||||
void deallocate(void*, size_type) { }
|
||||
void deallocate(void*, size_type) { }
|
||||
void deallocate(pointer, size_type) { }
|
||||
|
||||
pointer _Charalloc(size_t n) {
|
||||
pointer _Charalloc(size_t n) {
|
||||
return reinterpret_cast<pointer>(getAllocator().allocate(n)); }
|
||||
|
||||
void construct(pointer p, const T& val) { new ((void *)p) T(val); }
|
||||
|
|
|
|||
|
|
@ -123,8 +123,8 @@ public:
|
|||
haveReturnableObjectCode(false),
|
||||
appAttributeBindings(0),
|
||||
fixedAttributeBindings(0),
|
||||
excludedAttributes(0),
|
||||
excludedCount(0),
|
||||
excludedAttributes(0),
|
||||
excludedCount(0),
|
||||
uniformBindings(0) { }
|
||||
virtual TLinker* getAsLinker() { return this; }
|
||||
virtual ~TLinker() { }
|
||||
|
|
@ -132,8 +132,8 @@ public:
|
|||
virtual bool link(THandleList&) { return false; }
|
||||
virtual void setAppAttributeBindings(const ShBindingTable* t) { appAttributeBindings = t; }
|
||||
virtual void setFixedAttributeBindings(const ShBindingTable* t) { fixedAttributeBindings = t; }
|
||||
virtual void getAttributeBindings(ShBindingTable const **t) const = 0;
|
||||
virtual void setExcludedAttributes(const int* attributes, int count) { excludedAttributes = attributes; excludedCount = count; }
|
||||
virtual void getAttributeBindings(ShBindingTable const **t) const = 0;
|
||||
virtual void setExcludedAttributes(const int* attributes, int count) { excludedAttributes = attributes; excludedCount = count; }
|
||||
virtual ShBindingTable* getUniformBindings() const { return uniformBindings; }
|
||||
virtual const void* getObjectCode() const { return 0; } // a real compiler would be returning object code here
|
||||
virtual TInfoSink& getInfoSink() { return infoSink; }
|
||||
|
|
@ -145,8 +145,8 @@ protected:
|
|||
|
||||
const ShBindingTable* appAttributeBindings;
|
||||
const ShBindingTable* fixedAttributeBindings;
|
||||
const int* excludedAttributes;
|
||||
int excludedCount;
|
||||
const int* excludedAttributes;
|
||||
int excludedCount;
|
||||
ShBindingTable* uniformBindings; // created by the linker
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -78,12 +78,16 @@ struct TSampler { // misnomer now; includes images, textures without sampler,
|
|||
bool combined : 1; // true means texture is combined with a sampler, false means texture with no sampler
|
||||
bool sampler : 1; // true means a pure sampler, other fields should be clear()
|
||||
bool external : 1; // GL_OES_EGL_image_external
|
||||
unsigned int vectorSize : 3; // return vector size. TODO: support arbitrary types.
|
||||
|
||||
bool isImage() const { return image && dim != EsdSubpass; }
|
||||
bool isSubpass() const { return dim == EsdSubpass; }
|
||||
bool isCombined() const { return combined; }
|
||||
bool isPureSampler() const { return sampler; }
|
||||
bool isTexture() const { return !sampler && !image; }
|
||||
bool isShadow() const { return shadow; }
|
||||
bool isArrayed() const { return arrayed; }
|
||||
bool isMultiSample() const { return ms; }
|
||||
|
||||
void clear()
|
||||
{
|
||||
|
|
@ -96,6 +100,7 @@ struct TSampler { // misnomer now; includes images, textures without sampler,
|
|||
combined = false;
|
||||
sampler = false;
|
||||
external = false;
|
||||
vectorSize = 4;
|
||||
}
|
||||
|
||||
// make a combined sampler and texture
|
||||
|
|
@ -161,7 +166,8 @@ struct TSampler { // misnomer now; includes images, textures without sampler,
|
|||
image == right.image &&
|
||||
combined == right.combined &&
|
||||
sampler == right.sampler &&
|
||||
external == right.external;
|
||||
external == right.external &&
|
||||
vectorSize == right.vectorSize;
|
||||
}
|
||||
|
||||
bool operator!=(const TSampler& right) const
|
||||
|
|
@ -182,8 +188,6 @@ struct TSampler { // misnomer now; includes images, textures without sampler,
|
|||
case EbtFloat: break;
|
||||
case EbtInt: s.append("i"); break;
|
||||
case EbtUint: s.append("u"); break;
|
||||
case EbtInt64: s.append("i64"); break;
|
||||
case EbtUint64: s.append("u64"); break;
|
||||
default: break; // some compilers want this
|
||||
}
|
||||
if (image) {
|
||||
|
|
@ -403,6 +407,9 @@ public:
|
|||
smooth = false;
|
||||
flat = false;
|
||||
nopersp = false;
|
||||
#ifdef AMD_EXTENSIONS
|
||||
explicitInterp = false;
|
||||
#endif
|
||||
patch = false;
|
||||
sample = false;
|
||||
coherent = false;
|
||||
|
|
@ -436,6 +443,9 @@ public:
|
|||
bool smooth : 1;
|
||||
bool flat : 1;
|
||||
bool nopersp : 1;
|
||||
#ifdef AMD_EXTENSIONS
|
||||
bool explicitInterp : 1;
|
||||
#endif
|
||||
bool patch : 1;
|
||||
bool sample : 1;
|
||||
bool coherent : 1;
|
||||
|
|
@ -451,7 +461,11 @@ public:
|
|||
}
|
||||
bool isInterpolation() const
|
||||
{
|
||||
#ifdef AMD_EXTENSIONS
|
||||
return flat || smooth || nopersp || explicitInterp;
|
||||
#else
|
||||
return flat || smooth || nopersp;
|
||||
#endif
|
||||
}
|
||||
bool isAuxiliary() const
|
||||
{
|
||||
|
|
@ -610,8 +624,8 @@ public:
|
|||
unsigned int layoutSet : 7;
|
||||
static const unsigned int layoutSetEnd = 0x3F;
|
||||
|
||||
unsigned int layoutBinding : 8;
|
||||
static const unsigned int layoutBindingEnd = 0xFF;
|
||||
unsigned int layoutBinding : 16;
|
||||
static const unsigned int layoutBindingEnd = 0xFFFF;
|
||||
|
||||
unsigned int layoutIndex : 8;
|
||||
static const unsigned int layoutIndexEnd = 0xFF;
|
||||
|
|
@ -1062,7 +1076,7 @@ public:
|
|||
qualifier.clear();
|
||||
qualifier.storage = q;
|
||||
qualifier.precision = p;
|
||||
assert(p >= 0 && p <= EpqHigh);
|
||||
assert(p >= EpqNone && p <= EpqHigh);
|
||||
}
|
||||
// for turning a TPublicType into a TType, using a shallow copy
|
||||
explicit TType(const TPublicType& p) :
|
||||
|
|
@ -1080,6 +1094,15 @@ public:
|
|||
typeName = NewPoolTString(p.userDef->getTypeName().c_str());
|
||||
}
|
||||
}
|
||||
// for construction of sampler types
|
||||
TType(const TSampler& sampler, TStorageQualifier q = EvqUniform, TArraySizes* as = nullptr) :
|
||||
basicType(EbtSampler), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false),
|
||||
arraySizes(as), structure(nullptr), fieldName(nullptr), typeName(nullptr),
|
||||
sampler(sampler)
|
||||
{
|
||||
qualifier.clear();
|
||||
qualifier.storage = q;
|
||||
}
|
||||
// to efficiently make a dereferenced type
|
||||
// without ever duplicating the outer structure that will be thrown away
|
||||
// and using only shallow copy
|
||||
|
|
@ -1182,7 +1205,7 @@ public:
|
|||
typeName = NewPoolTString(copyOf.typeName->c_str());
|
||||
}
|
||||
|
||||
TType* clone()
|
||||
TType* clone() const
|
||||
{
|
||||
TType *newType = new TType();
|
||||
newType->deepCopy(*this);
|
||||
|
|
@ -1255,7 +1278,11 @@ public:
|
|||
virtual bool isImplicitlySizedArray() const { return isArray() && getOuterArraySize() == UnsizedArraySize && qualifier.storage != EvqBuffer; }
|
||||
virtual bool isRuntimeSizedArray() const { return isArray() && getOuterArraySize() == UnsizedArraySize && qualifier.storage == EvqBuffer; }
|
||||
virtual bool isStruct() const { return structure != nullptr; }
|
||||
#ifdef AMD_EXTENSIONS
|
||||
virtual bool isFloatingDomain() const { return basicType == EbtFloat || basicType == EbtDouble || basicType == EbtFloat16; }
|
||||
#else
|
||||
virtual bool isFloatingDomain() const { return basicType == EbtFloat || basicType == EbtDouble; }
|
||||
#endif
|
||||
|
||||
virtual bool isOpaque() const { return basicType == EbtSampler || basicType == EbtAtomicUint; }
|
||||
|
||||
|
|
@ -1337,6 +1364,9 @@ public:
|
|||
case EbtVoid:
|
||||
case EbtFloat:
|
||||
case EbtDouble:
|
||||
#ifdef AMD_EXTENSIONS
|
||||
case EbtFloat16:
|
||||
#endif
|
||||
case EbtInt:
|
||||
case EbtUint:
|
||||
case EbtInt64:
|
||||
|
|
@ -1429,6 +1459,9 @@ public:
|
|||
case EbtVoid: return "void";
|
||||
case EbtFloat: return "float";
|
||||
case EbtDouble: return "double";
|
||||
#ifdef AMD_EXTENSIONS
|
||||
case EbtFloat16: return "float16_t";
|
||||
#endif
|
||||
case EbtInt: return "int";
|
||||
case EbtUint: return "uint";
|
||||
case EbtInt64: return "int64_t";
|
||||
|
|
@ -1507,6 +1540,10 @@ public:
|
|||
p += snprintf(p, end - p, "flat ");
|
||||
if (qualifier.nopersp)
|
||||
p += snprintf(p, end - p, "noperspective ");
|
||||
#ifdef AMD_EXTENSIONS
|
||||
if (qualifier.explicitInterp)
|
||||
p += snprintf(p, end - p, "__explicitInterpAMD ");
|
||||
#endif
|
||||
if (qualifier.patch)
|
||||
p += snprintf(p, end - p, "patch ");
|
||||
if (qualifier.sample)
|
||||
|
|
@ -1707,13 +1744,13 @@ protected:
|
|||
// functionality is added.
|
||||
// HLSL does have a 1-component vectors, so this will be true to disambiguate
|
||||
// from a scalar.
|
||||
TSampler sampler;
|
||||
TQualifier qualifier;
|
||||
|
||||
TArraySizes* arraySizes; // nullptr unless an array; can be shared across types
|
||||
TTypeList* structure; // nullptr unless this is a struct; can be shared across types
|
||||
TString *fieldName; // for structure field names
|
||||
TString *typeName; // for structure type name
|
||||
TSampler sampler;
|
||||
};
|
||||
|
||||
} // end namespace glslang
|
||||
|
|
|
|||
|
|
@ -57,6 +57,8 @@
|
|||
|
||||
namespace glslang {
|
||||
|
||||
class TIntermediate;
|
||||
|
||||
//
|
||||
// Operators used by the high-level (parse tree) representation.
|
||||
//
|
||||
|
|
@ -124,6 +126,22 @@ enum TOperator {
|
|||
EOpConvFloatToUint64,
|
||||
EOpConvDoubleToUint64,
|
||||
EOpConvInt64ToUint64,
|
||||
#ifdef AMD_EXTENSIONS
|
||||
EOpConvBoolToFloat16,
|
||||
EOpConvIntToFloat16,
|
||||
EOpConvUintToFloat16,
|
||||
EOpConvFloatToFloat16,
|
||||
EOpConvDoubleToFloat16,
|
||||
EOpConvInt64ToFloat16,
|
||||
EOpConvUint64ToFloat16,
|
||||
EOpConvFloat16ToBool,
|
||||
EOpConvFloat16ToInt,
|
||||
EOpConvFloat16ToUint,
|
||||
EOpConvFloat16ToFloat,
|
||||
EOpConvFloat16ToDouble,
|
||||
EOpConvFloat16ToInt64,
|
||||
EOpConvFloat16ToUint64,
|
||||
#endif
|
||||
|
||||
//
|
||||
// binary operations
|
||||
|
|
@ -241,6 +259,10 @@ enum TOperator {
|
|||
EOpUnpackInt2x32,
|
||||
EOpPackUint2x32,
|
||||
EOpUnpackUint2x32,
|
||||
#ifdef AMD_EXTENSIONS
|
||||
EOpPackFloat2x16,
|
||||
EOpUnpackFloat2x16,
|
||||
#endif
|
||||
|
||||
EOpLength,
|
||||
EOpDistance,
|
||||
|
|
@ -251,6 +273,12 @@ enum TOperator {
|
|||
EOpReflect,
|
||||
EOpRefract,
|
||||
|
||||
#ifdef AMD_EXTENSIONS
|
||||
EOpMin3,
|
||||
EOpMax3,
|
||||
EOpMid3,
|
||||
#endif
|
||||
|
||||
EOpDPdx, // Fragment only
|
||||
EOpDPdy, // Fragment only
|
||||
EOpFwidth, // Fragment only
|
||||
|
|
@ -265,6 +293,10 @@ enum TOperator {
|
|||
EOpInterpolateAtSample, // Fragment only
|
||||
EOpInterpolateAtOffset, // Fragment only
|
||||
|
||||
#ifdef AMD_EXTENSIONS
|
||||
EOpInterpolateAtVertex,
|
||||
#endif
|
||||
|
||||
EOpMatrixTimesMatrix,
|
||||
EOpOuterProduct,
|
||||
EOpDeterminant,
|
||||
|
|
@ -296,6 +328,23 @@ enum TOperator {
|
|||
EOpAllInvocations,
|
||||
EOpAllInvocationsEqual,
|
||||
|
||||
#ifdef AMD_EXTENSIONS
|
||||
EOpMinInvocations,
|
||||
EOpMaxInvocations,
|
||||
EOpAddInvocations,
|
||||
EOpMinInvocationsNonUniform,
|
||||
EOpMaxInvocationsNonUniform,
|
||||
EOpAddInvocationsNonUniform,
|
||||
EOpSwizzleInvocations,
|
||||
EOpSwizzleInvocationsMasked,
|
||||
EOpWriteInvocation,
|
||||
EOpMbcnt,
|
||||
|
||||
EOpCubeFaceIndex,
|
||||
EOpCubeFaceCoord,
|
||||
EOpTime,
|
||||
#endif
|
||||
|
||||
EOpAtomicAdd,
|
||||
EOpAtomicMin,
|
||||
EOpAtomicMax,
|
||||
|
|
@ -374,6 +423,21 @@ enum TOperator {
|
|||
EOpConstructDMat4x2,
|
||||
EOpConstructDMat4x3,
|
||||
EOpConstructDMat4x4,
|
||||
#ifdef AMD_EXTENSIONS
|
||||
EOpConstructFloat16,
|
||||
EOpConstructF16Vec2,
|
||||
EOpConstructF16Vec3,
|
||||
EOpConstructF16Vec4,
|
||||
EOpConstructF16Mat2x2,
|
||||
EOpConstructF16Mat2x3,
|
||||
EOpConstructF16Mat2x4,
|
||||
EOpConstructF16Mat3x2,
|
||||
EOpConstructF16Mat3x3,
|
||||
EOpConstructF16Mat3x4,
|
||||
EOpConstructF16Mat4x2,
|
||||
EOpConstructF16Mat4x3,
|
||||
EOpConstructF16Mat4x4,
|
||||
#endif
|
||||
EOpConstructStruct,
|
||||
EOpConstructTextureSampler,
|
||||
EOpConstructGuardEnd,
|
||||
|
|
@ -439,6 +503,9 @@ enum TOperator {
|
|||
EOpTextureQueryLod,
|
||||
EOpTextureQueryLevels,
|
||||
EOpTextureQuerySamples,
|
||||
|
||||
EOpSamplingGuardBegin,
|
||||
|
||||
EOpTexture,
|
||||
EOpTextureProj,
|
||||
EOpTextureLod,
|
||||
|
|
@ -481,7 +548,7 @@ enum TOperator {
|
|||
EOpSparseTextureGradOffsetClamp,
|
||||
|
||||
EOpSparseTextureGuardEnd,
|
||||
|
||||
EOpSamplingGuardEnd,
|
||||
EOpTextureGuardEnd,
|
||||
|
||||
//
|
||||
|
|
@ -530,6 +597,30 @@ enum TOperator {
|
|||
EOpLit, // HLSL lighting coefficient vector
|
||||
EOpTextureBias, // HLSL texture bias: will be lowered to EOpTexture
|
||||
EOpAsDouble, // slightly different from EOpUint64BitsToDouble
|
||||
|
||||
EOpMethodSample, // Texture object methods. These are translated to existing
|
||||
EOpMethodSampleBias, // AST methods, and exist to represent HLSL semantics until that
|
||||
EOpMethodSampleCmp, // translation is performed. See HlslParseContext::decomposeSampleMethods().
|
||||
EOpMethodSampleCmpLevelZero, // ...
|
||||
EOpMethodSampleGrad, // ...
|
||||
EOpMethodSampleLevel, // ...
|
||||
EOpMethodLoad, // ...
|
||||
EOpMethodGetDimensions, // ...
|
||||
EOpMethodGetSamplePosition, // ...
|
||||
EOpMethodGather, // ...
|
||||
EOpMethodCalculateLevelOfDetail, // ...
|
||||
EOpMethodCalculateLevelOfDetailUnclamped, // ...
|
||||
|
||||
// SM5 texture methods
|
||||
EOpMethodGatherRed, // These are covered under the above EOpMethodSample comment about
|
||||
EOpMethodGatherGreen, // translation to existing AST opcodes. They exist temporarily
|
||||
EOpMethodGatherBlue, // because HLSL arguments are slightly different.
|
||||
EOpMethodGatherAlpha, // ...
|
||||
EOpMethodGatherCmp, // ...
|
||||
EOpMethodGatherCmpRed, // ...
|
||||
EOpMethodGatherCmpGreen, // ...
|
||||
EOpMethodGatherCmpBlue, // ...
|
||||
EOpMethodGatherCmpAlpha, // ...
|
||||
};
|
||||
|
||||
class TIntermTraverser;
|
||||
|
|
@ -761,14 +852,30 @@ public:
|
|||
virtual TIntermOperator* getAsOperator() { return this; }
|
||||
virtual const TIntermOperator* getAsOperator() const { return this; }
|
||||
TOperator getOp() const { return op; }
|
||||
virtual bool promote() { return true; }
|
||||
void setOp(TOperator newOp) { op = newOp; }
|
||||
bool modifiesState() const;
|
||||
bool isConstructor() const;
|
||||
bool isTexture() const { return op > EOpTextureGuardBegin && op < EOpTextureGuardEnd; }
|
||||
bool isImage() const { return op > EOpImageGuardBegin && op < EOpImageGuardEnd; }
|
||||
bool isTexture() const { return op > EOpTextureGuardBegin && op < EOpTextureGuardEnd; }
|
||||
bool isSampling() const { return op > EOpSamplingGuardBegin && op < EOpSamplingGuardEnd; }
|
||||
bool isImage() const { return op > EOpImageGuardBegin && op < EOpImageGuardEnd; }
|
||||
bool isSparseTexture() const { return op > EOpSparseTextureGuardBegin && op < EOpSparseTextureGuardEnd; }
|
||||
bool isSparseImage() const { return op == EOpSparseImageLoad; }
|
||||
|
||||
void setOperationPrecision(TPrecisionQualifier p) { operationPrecision = p; }
|
||||
TPrecisionQualifier getOperationPrecision() const { return operationPrecision != EpqNone ?
|
||||
operationPrecision :
|
||||
type.getQualifier().precision; }
|
||||
TString getCompleteString() const
|
||||
{
|
||||
TString cs = type.getCompleteString();
|
||||
if (getOperationPrecision() != type.getQualifier().precision) {
|
||||
cs += ", operation at ";
|
||||
cs += GetPrecisionQualifierString(getOperationPrecision());
|
||||
}
|
||||
|
||||
return cs;
|
||||
}
|
||||
|
||||
// Crack the op into the individual dimensions of texturing operation.
|
||||
void crackTexture(TSampler sampler, TCrackedTextureOp& cracked) const
|
||||
{
|
||||
|
|
@ -900,9 +1007,15 @@ public:
|
|||
}
|
||||
|
||||
protected:
|
||||
TIntermOperator(TOperator o) : TIntermTyped(EbtFloat), op(o) {}
|
||||
TIntermOperator(TOperator o, TType& t) : TIntermTyped(t), op(o) {}
|
||||
TIntermOperator(TOperator o) : TIntermTyped(EbtFloat), op(o), operationPrecision(EpqNone) {}
|
||||
TIntermOperator(TOperator o, TType& t) : TIntermTyped(t), op(o), operationPrecision(EpqNone) {}
|
||||
TOperator op;
|
||||
// The result precision is in the inherited TType, and is usually meant to be both
|
||||
// the operation precision and the result precision. However, some more complex things,
|
||||
// like built-in function calls, distinguish between the two, in which case non-EqpNone
|
||||
// 'operationPrecision' overrides the result precision as far as operation precision
|
||||
// is concerned.
|
||||
TPrecisionQualifier operationPrecision;
|
||||
};
|
||||
|
||||
//
|
||||
|
|
@ -918,7 +1031,6 @@ public:
|
|||
virtual TIntermTyped* getRight() const { return right; }
|
||||
virtual TIntermBinary* getAsBinaryNode() { return this; }
|
||||
virtual const TIntermBinary* getAsBinaryNode() const { return this; }
|
||||
virtual bool promote();
|
||||
virtual void updatePrecision();
|
||||
protected:
|
||||
TIntermTyped* left;
|
||||
|
|
@ -938,7 +1050,6 @@ public:
|
|||
virtual const TIntermTyped* getOperand() const { return operand; }
|
||||
virtual TIntermUnary* getAsUnaryNode() { return this; }
|
||||
virtual const TIntermUnary* getAsUnaryNode() const { return this; }
|
||||
virtual bool promote();
|
||||
virtual void updatePrecision();
|
||||
protected:
|
||||
TIntermTyped* operand;
|
||||
|
|
|
|||
|
|
@ -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 "SPIRV99.947"
|
||||
#define GLSLANG_DATE "15-Feb-2016"
|
||||
#define GLSLANG_REVISION "Overload400-PrecQual.1603"
|
||||
#define GLSLANG_DATE "16-Oct-2016"
|
||||
|
|
|
|||
|
|
@ -176,6 +176,9 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TIntermTyped* right
|
|||
switch (getType().getBasicType()) {
|
||||
case EbtDouble:
|
||||
case EbtFloat:
|
||||
#ifdef AMD_EXTENSIONS
|
||||
case EbtFloat16:
|
||||
#endif
|
||||
newConstArray[i].setDConst(leftUnionArray[i].getDConst() / rightUnionArray[i].getDConst());
|
||||
break;
|
||||
|
||||
|
|
@ -450,6 +453,9 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TType& returnType)
|
|||
case EOpNegative:
|
||||
switch (getType().getBasicType()) {
|
||||
case EbtDouble:
|
||||
#ifdef AMD_EXTENSIONS
|
||||
case EbtFloat16:
|
||||
#endif
|
||||
case EbtFloat: newConstArray[i].setDConst(-unionArray[i].getDConst()); break;
|
||||
case EbtInt: newConstArray[i].setIConst(-unionArray[i].getIConst()); break;
|
||||
case EbtUint: newConstArray[i].setUConst(static_cast<unsigned int>(-static_cast<int>(unionArray[i].getUConst()))); break;
|
||||
|
|
@ -688,6 +694,9 @@ TIntermTyped* TIntermediate::fold(TIntermAggregate* aggrNode)
|
|||
// Second, do the actual folding
|
||||
|
||||
bool isFloatingPoint = children[0]->getAsTyped()->getBasicType() == EbtFloat ||
|
||||
#ifdef AMD_EXTENSIONS
|
||||
children[0]->getAsTyped()->getBasicType() == EbtFloat16 ||
|
||||
#endif
|
||||
children[0]->getAsTyped()->getBasicType() == EbtDouble;
|
||||
bool isSigned = children[0]->getAsTyped()->getBasicType() == EbtInt ||
|
||||
children[0]->getAsTyped()->getBasicType() == EbtInt64;
|
||||
|
|
|
|||
|
|
@ -34,15 +34,19 @@
|
|||
|
||||
#include "../Include/InfoSink.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <cstring>
|
||||
|
||||
namespace glslang {
|
||||
|
||||
void TInfoSinkBase::append(const char* s)
|
||||
void TInfoSinkBase::append(const char* s)
|
||||
{
|
||||
if (outputStream & EString) {
|
||||
checkMem(strlen(s));
|
||||
sink.append(s);
|
||||
if (s == nullptr)
|
||||
sink.append("(null)");
|
||||
else {
|
||||
checkMem(strlen(s));
|
||||
sink.append(s);
|
||||
}
|
||||
}
|
||||
|
||||
//#ifdef _WIN32
|
||||
|
|
@ -54,10 +58,10 @@ void TInfoSinkBase::append(const char* s)
|
|||
fprintf(stdout, "%s", s);
|
||||
}
|
||||
|
||||
void TInfoSinkBase::append(int count, char c)
|
||||
void TInfoSinkBase::append(int count, char c)
|
||||
{
|
||||
if (outputStream & EString) {
|
||||
checkMem(count);
|
||||
checkMem(count);
|
||||
sink.append(count, c);
|
||||
}
|
||||
|
||||
|
|
@ -74,10 +78,10 @@ void TInfoSinkBase::append(int count, char c)
|
|||
fprintf(stdout, "%c", c);
|
||||
}
|
||||
|
||||
void TInfoSinkBase::append(const TPersistString& t)
|
||||
void TInfoSinkBase::append(const TPersistString& t)
|
||||
{
|
||||
if (outputStream & EString) {
|
||||
checkMem(t.size());
|
||||
checkMem(t.size());
|
||||
sink.append(t);
|
||||
}
|
||||
|
||||
|
|
@ -93,7 +97,7 @@ void TInfoSinkBase::append(const TPersistString& t)
|
|||
void TInfoSinkBase::append(const TString& t)
|
||||
{
|
||||
if (outputStream & EString) {
|
||||
checkMem(t.size());
|
||||
checkMem(t.size());
|
||||
sink.append(t.c_str());
|
||||
}
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
136
glslang/MachineIndependent/LiveTraverser.h
Normal file
136
glslang/MachineIndependent/LiveTraverser.h
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
//
|
||||
//Copyright (C) 2016 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.
|
||||
//
|
||||
|
||||
#include "../Include/Common.h"
|
||||
#include "reflection.h"
|
||||
#include "localintermediate.h"
|
||||
|
||||
#include "gl_types.h"
|
||||
|
||||
#include <list>
|
||||
#include <unordered_set>
|
||||
|
||||
namespace glslang {
|
||||
|
||||
//
|
||||
// The traverser: mostly pass through, except
|
||||
// - processing function-call nodes to push live functions onto the stack of functions to process
|
||||
// - processing selection nodes to trim semantically dead code
|
||||
//
|
||||
// This is in the glslang namespace directly so it can be a friend of TReflection.
|
||||
// This can be derived from to implement reflection database traversers or
|
||||
// binding mappers: anything that wants to traverse the live subset of the tree.
|
||||
//
|
||||
|
||||
class TLiveTraverser : public TIntermTraverser {
|
||||
public:
|
||||
TLiveTraverser(const TIntermediate& i, bool traverseAll = false,
|
||||
bool preVisit = true, bool inVisit = false, bool postVisit = false) :
|
||||
TIntermTraverser(preVisit, inVisit, postVisit),
|
||||
intermediate(i), traverseAll(traverseAll)
|
||||
{ }
|
||||
|
||||
//
|
||||
// Given a function name, find its subroot in the tree, and push it onto the stack of
|
||||
// functions left to process.
|
||||
//
|
||||
void pushFunction(const TString& name)
|
||||
{
|
||||
TIntermSequence& globals = intermediate.getTreeRoot()->getAsAggregate()->getSequence();
|
||||
for (unsigned int f = 0; f < globals.size(); ++f) {
|
||||
TIntermAggregate* candidate = globals[f]->getAsAggregate();
|
||||
if (candidate && candidate->getOp() == EOpFunction && candidate->getName() == name) {
|
||||
functions.push_back(candidate);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typedef std::list<TIntermAggregate*> TFunctionStack;
|
||||
TFunctionStack functions;
|
||||
|
||||
protected:
|
||||
// To catch which function calls are not dead, and hence which functions must be visited.
|
||||
virtual bool visitAggregate(TVisit, TIntermAggregate* node)
|
||||
{
|
||||
if (!traverseAll)
|
||||
if (node->getOp() == EOpFunctionCall)
|
||||
addFunctionCall(node);
|
||||
|
||||
return true; // traverse this subtree
|
||||
}
|
||||
|
||||
// To prune semantically dead paths.
|
||||
virtual bool visitSelection(TVisit /* visit */, TIntermSelection* node)
|
||||
{
|
||||
if (traverseAll)
|
||||
return true; // traverse all code
|
||||
|
||||
TIntermConstantUnion* constant = node->getCondition()->getAsConstantUnion();
|
||||
if (constant) {
|
||||
// cull the path that is dead
|
||||
if (constant->getConstArray()[0].getBConst() == true && node->getTrueBlock())
|
||||
node->getTrueBlock()->traverse(this);
|
||||
if (constant->getConstArray()[0].getBConst() == false && node->getFalseBlock())
|
||||
node->getFalseBlock()->traverse(this);
|
||||
|
||||
return false; // don't traverse any more, we did it all above
|
||||
} else
|
||||
return true; // traverse the whole subtree
|
||||
}
|
||||
|
||||
// Track live functions as well as uniforms, so that we don't visit dead functions
|
||||
// and only visit each function once.
|
||||
void addFunctionCall(TIntermAggregate* call)
|
||||
{
|
||||
// // just use the map to ensure we process each function at most once
|
||||
if (liveFunctions.find(call->getName()) == liveFunctions.end()) {
|
||||
liveFunctions.insert(call->getName());
|
||||
pushFunction(call->getName());
|
||||
}
|
||||
}
|
||||
|
||||
const TIntermediate& intermediate;
|
||||
typedef std::unordered_set<TString> TLiveFunctions;
|
||||
TLiveFunctions liveFunctions;
|
||||
bool traverseAll;
|
||||
|
||||
private:
|
||||
// prevent copy & copy construct
|
||||
TLiveTraverser(TLiveTraverser&);
|
||||
TLiveTraverser& operator=(TLiveTraverser&);
|
||||
};
|
||||
|
||||
} // namespace glslang
|
||||
451
glslang/MachineIndependent/ParseContextBase.cpp
Normal file
451
glslang/MachineIndependent/ParseContextBase.cpp
Normal file
|
|
@ -0,0 +1,451 @@
|
|||
//
|
||||
//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
||||
//Copyright (C) 2016 Google, 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.
|
||||
//
|
||||
|
||||
// Implement the TParseContextBase class.
|
||||
|
||||
#include <cstdarg>
|
||||
|
||||
#include "ParseHelper.h"
|
||||
|
||||
extern int yyparse(glslang::TParseContext*);
|
||||
|
||||
namespace glslang {
|
||||
|
||||
//
|
||||
// Used to output syntax, parsing, and semantic errors.
|
||||
//
|
||||
|
||||
void TParseContextBase::outputMessage(const TSourceLoc& loc, const char* szReason,
|
||||
const char* szToken,
|
||||
const char* szExtraInfoFormat,
|
||||
TPrefixType prefix, va_list args)
|
||||
{
|
||||
const int maxSize = MaxTokenLength + 200;
|
||||
char szExtraInfo[maxSize];
|
||||
|
||||
safe_vsprintf(szExtraInfo, maxSize, szExtraInfoFormat, args);
|
||||
|
||||
infoSink.info.prefix(prefix);
|
||||
infoSink.info.location(loc);
|
||||
infoSink.info << "'" << szToken << "' : " << szReason << " " << szExtraInfo << "\n";
|
||||
|
||||
if (prefix == EPrefixError) {
|
||||
++numErrors;
|
||||
}
|
||||
}
|
||||
|
||||
void C_DECL TParseContextBase::error(const TSourceLoc& loc, const char* szReason, const char* szToken,
|
||||
const char* szExtraInfoFormat, ...)
|
||||
{
|
||||
if (messages & EShMsgOnlyPreprocessor)
|
||||
return;
|
||||
va_list args;
|
||||
va_start(args, szExtraInfoFormat);
|
||||
outputMessage(loc, szReason, szToken, szExtraInfoFormat, EPrefixError, args);
|
||||
va_end(args);
|
||||
|
||||
if ((messages & EShMsgCascadingErrors) == 0)
|
||||
currentScanner->setEndOfInput();
|
||||
}
|
||||
|
||||
void C_DECL TParseContextBase::warn(const TSourceLoc& loc, const char* szReason, const char* szToken,
|
||||
const char* szExtraInfoFormat, ...)
|
||||
{
|
||||
if (suppressWarnings())
|
||||
return;
|
||||
va_list args;
|
||||
va_start(args, szExtraInfoFormat);
|
||||
outputMessage(loc, szReason, szToken, szExtraInfoFormat, EPrefixWarning, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void C_DECL TParseContextBase::ppError(const TSourceLoc& loc, const char* szReason, const char* szToken,
|
||||
const char* szExtraInfoFormat, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, szExtraInfoFormat);
|
||||
outputMessage(loc, szReason, szToken, szExtraInfoFormat, EPrefixError, args);
|
||||
va_end(args);
|
||||
|
||||
if ((messages & EShMsgCascadingErrors) == 0)
|
||||
currentScanner->setEndOfInput();
|
||||
}
|
||||
|
||||
void C_DECL TParseContextBase::ppWarn(const TSourceLoc& loc, const char* szReason, const char* szToken,
|
||||
const char* szExtraInfoFormat, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, szExtraInfoFormat);
|
||||
outputMessage(loc, szReason, szToken, szExtraInfoFormat, EPrefixWarning, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
//
|
||||
// Both test and if necessary, spit out an error, to see if the node is really
|
||||
// an l-value that can be operated on this way.
|
||||
//
|
||||
// Returns true if there was an error.
|
||||
//
|
||||
bool TParseContextBase::lValueErrorCheck(const TSourceLoc& loc, const char* op, TIntermTyped* node)
|
||||
{
|
||||
TIntermBinary* binaryNode = node->getAsBinaryNode();
|
||||
|
||||
if (binaryNode) {
|
||||
switch(binaryNode->getOp()) {
|
||||
case EOpIndexDirect:
|
||||
case EOpIndexIndirect: // fall through
|
||||
case EOpIndexDirectStruct: // fall through
|
||||
case EOpVectorSwizzle:
|
||||
return lValueErrorCheck(loc, op, binaryNode->getLeft());
|
||||
default:
|
||||
break;
|
||||
}
|
||||
error(loc, " l-value required", op, "", "");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const char* symbol = nullptr;
|
||||
TIntermSymbol* symNode = node->getAsSymbolNode();
|
||||
if (symNode != nullptr)
|
||||
symbol = symNode->getName().c_str();
|
||||
|
||||
const char* message = nullptr;
|
||||
switch (node->getQualifier().storage) {
|
||||
case EvqConst: message = "can't modify a const"; break;
|
||||
case EvqConstReadOnly: message = "can't modify a const"; break;
|
||||
case EvqUniform: message = "can't modify a uniform"; break;
|
||||
case EvqBuffer:
|
||||
if (node->getQualifier().readonly)
|
||||
message = "can't modify a readonly buffer";
|
||||
break;
|
||||
|
||||
default:
|
||||
//
|
||||
// Type that can't be written to?
|
||||
//
|
||||
switch (node->getBasicType()) {
|
||||
case EbtSampler:
|
||||
message = "can't modify a sampler";
|
||||
break;
|
||||
case EbtAtomicUint:
|
||||
message = "can't modify an atomic_uint";
|
||||
break;
|
||||
case EbtVoid:
|
||||
message = "can't modify void";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (message == nullptr && binaryNode == nullptr && symNode == nullptr) {
|
||||
error(loc, " l-value required", op, "", "");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// Everything else is okay, no error.
|
||||
//
|
||||
if (message == nullptr)
|
||||
return false;
|
||||
|
||||
//
|
||||
// If we get here, we have an error and a message.
|
||||
//
|
||||
if (symNode)
|
||||
error(loc, " l-value required", op, "\"%s\" (%s)", symbol, message);
|
||||
else
|
||||
error(loc, " l-value required", op, "(%s)", message);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Test for and give an error if the node can't be read from.
|
||||
void TParseContextBase::rValueErrorCheck(const TSourceLoc& loc, const char* op, TIntermTyped* node)
|
||||
{
|
||||
if (! node)
|
||||
return;
|
||||
|
||||
TIntermBinary* binaryNode = node->getAsBinaryNode();
|
||||
if (binaryNode) {
|
||||
switch(binaryNode->getOp()) {
|
||||
case EOpIndexDirect:
|
||||
case EOpIndexIndirect:
|
||||
case EOpIndexDirectStruct:
|
||||
case EOpVectorSwizzle:
|
||||
rValueErrorCheck(loc, op, binaryNode->getLeft());
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
TIntermSymbol* symNode = node->getAsSymbolNode();
|
||||
if (symNode && symNode->getQualifier().writeonly)
|
||||
error(loc, "can't read from writeonly object: ", op, symNode->getName().c_str());
|
||||
}
|
||||
|
||||
// Make a shared symbol have a non-shared version that can be edited by the current
|
||||
// compile, such that editing its type will not change the shared version and will
|
||||
// effect all nodes sharing it.
|
||||
void TParseContextBase::makeEditable(TSymbol*& symbol)
|
||||
{
|
||||
// copyUp() does a deep copy of the type.
|
||||
symbol = symbolTable.copyUp(symbol);
|
||||
|
||||
// Save it in the AST for linker use.
|
||||
intermediate.addSymbolLinkageNode(linkage, *symbol);
|
||||
}
|
||||
|
||||
// Return a writable version of the variable 'name'.
|
||||
//
|
||||
// Return nullptr if 'name' is not found. This should mean
|
||||
// something is seriously wrong (e.g., compiler asking self for
|
||||
// built-in that doesn't exist).
|
||||
TVariable* TParseContextBase::getEditableVariable(const char* name)
|
||||
{
|
||||
bool builtIn;
|
||||
TSymbol* symbol = symbolTable.find(name, &builtIn);
|
||||
|
||||
assert(symbol != nullptr);
|
||||
if (symbol == nullptr)
|
||||
return nullptr;
|
||||
|
||||
if (builtIn)
|
||||
makeEditable(symbol);
|
||||
|
||||
return symbol->getAsVariable();
|
||||
}
|
||||
|
||||
// Select the best matching function for 'call' from 'candidateList'.
|
||||
//
|
||||
// Assumptions
|
||||
//
|
||||
// There is no exact match, so a selection algorithm needs to run. That is, the
|
||||
// language-specific handler should check for exact match first, to
|
||||
// decide what to do, before calling this selector.
|
||||
//
|
||||
// Input
|
||||
//
|
||||
// * list of candidate signatures to select from
|
||||
// * the call
|
||||
// * a predicate function convertible(from, to) that says whether or not type
|
||||
// 'from' can implicitly convert to type 'to' (it includes the case of what
|
||||
// the calling language would consider a matching type with no conversion
|
||||
// needed)
|
||||
// * a predicate function better(from1, from2, to1, to2) that says whether or
|
||||
// not a conversion from <-> to2 is considered better than a conversion
|
||||
// from <-> to1 (both in and out directions need testing, as declared by the
|
||||
// formal parameter)
|
||||
//
|
||||
// Output
|
||||
//
|
||||
// * best matching candidate (or none, if no viable candidates found)
|
||||
// * whether there was a tie for the best match (ambiguous overload selection,
|
||||
// caller's choice for how to report)
|
||||
//
|
||||
const TFunction* TParseContextBase::selectFunction(
|
||||
const TVector<const TFunction*> candidateList,
|
||||
const TFunction& call,
|
||||
std::function<bool(const TType& from, const TType& to)> convertible,
|
||||
std::function<bool(const TType& from, const TType& to1, const TType& to2)> better,
|
||||
/* output */ bool& tie)
|
||||
{
|
||||
//
|
||||
// Operation
|
||||
//
|
||||
// 1. Prune the input list of candidates down to a list of viable candidates,
|
||||
// where each viable candidate has
|
||||
//
|
||||
// * at least as many parameters as there are calling arguments, with any
|
||||
// remaining parameters being optional or having default values
|
||||
// * each parameter is true under convertible(A, B), where A is the calling
|
||||
// type for in and B is the formal type, and in addition, for out B is the
|
||||
// calling type and A is the formal type
|
||||
//
|
||||
// 2. If there are no viable candidates, return with no match.
|
||||
//
|
||||
// 3. If there is only one viable candidate, it is the best match.
|
||||
//
|
||||
// 4. If there are multiple viable candidates, select the first viable candidate
|
||||
// as the incumbent. Compare the incumbent to the next viable candidate, and if
|
||||
// that candidate is better (bullets below), make it the incumbent. Repeat, with
|
||||
// a linear walk through the viable candidate list. The final incumbent will be
|
||||
// returned as the best match. A viable candidate is better than the incumbent if
|
||||
//
|
||||
// * it has a function argument with a better(...) conversion than the incumbent,
|
||||
// for all directions needed by in and out
|
||||
// * the incumbent has no argument with a better(...) conversion then the
|
||||
// candidate, for either in or out (as needed)
|
||||
//
|
||||
// 5. Check for ambiguity by comparing the best match against all other viable
|
||||
// candidates. If any other viable candidate has a function argument with a
|
||||
// better(...) conversion than the best candidate (for either in or out
|
||||
// directions), return that there was a tie for best.
|
||||
//
|
||||
|
||||
tie = false;
|
||||
|
||||
// 1. prune to viable...
|
||||
TVector<const TFunction*> viableCandidates;
|
||||
for (auto it = candidateList.begin(); it != candidateList.end(); ++it) {
|
||||
const TFunction& candidate = *(*it);
|
||||
|
||||
// to even be a potential match, number of arguments has to match
|
||||
if (call.getParamCount() != candidate.getParamCount())
|
||||
continue;
|
||||
|
||||
// see if arguments are convertible
|
||||
bool viable = true;
|
||||
for (int param = 0; param < candidate.getParamCount(); ++param) {
|
||||
if (candidate[param].type->getQualifier().isParamInput()) {
|
||||
if (! convertible(*call[param].type, *candidate[param].type)) {
|
||||
viable = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (candidate[param].type->getQualifier().isParamOutput()) {
|
||||
if (! convertible(*candidate[param].type, *call[param].type)) {
|
||||
viable = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (viable)
|
||||
viableCandidates.push_back(&candidate);
|
||||
}
|
||||
|
||||
// 2. none viable...
|
||||
if (viableCandidates.size() == 0)
|
||||
return nullptr;
|
||||
|
||||
// 3. only one viable...
|
||||
if (viableCandidates.size() == 1)
|
||||
return viableCandidates.front();
|
||||
|
||||
// 4. find best...
|
||||
auto betterParam = [&call, &better](const TFunction& can1, const TFunction& can2) -> bool {
|
||||
// is call -> can2 better than call -> can1 for any parameter
|
||||
bool hasBetterParam = false;
|
||||
for (int param = 0; param < call.getParamCount(); ++param) {
|
||||
if (better(*call[param].type, *can1[param].type, *can2[param].type)) {
|
||||
hasBetterParam = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return hasBetterParam;
|
||||
};
|
||||
|
||||
const TFunction* incumbent = viableCandidates.front();
|
||||
for (auto it = viableCandidates.begin() + 1; it != viableCandidates.end(); ++it) {
|
||||
const TFunction& candidate = *(*it);
|
||||
if (betterParam(*incumbent, candidate) && ! betterParam(candidate, *incumbent))
|
||||
incumbent = &candidate;
|
||||
}
|
||||
|
||||
// 5. ambiguity...
|
||||
for (auto it = viableCandidates.begin(); it != viableCandidates.end(); ++it) {
|
||||
if (incumbent == *it)
|
||||
continue;
|
||||
const TFunction& candidate = *(*it);
|
||||
if (betterParam(*incumbent, candidate))
|
||||
tie = true;
|
||||
}
|
||||
|
||||
return incumbent;
|
||||
}
|
||||
|
||||
//
|
||||
// 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)
|
||||
{
|
||||
// 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);
|
||||
firstNewMember = 0;
|
||||
}
|
||||
|
||||
// add the requested member as a member to the block
|
||||
TType* type = new TType;
|
||||
type->shallowCopy(memberType);
|
||||
type->setFieldName(memberName);
|
||||
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;
|
||||
if (firstNewMember == 0) {
|
||||
// This is the first request; we need a normal symbol table insert
|
||||
inserted = symbolTable.insert(*globalUniformBlock);
|
||||
if (inserted)
|
||||
intermediate.addSymbolLinkageNode(linkage, *globalUniformBlock);
|
||||
} else if (firstNewMember <= numMembers) {
|
||||
// This is a follow-on request; we need to amend the first insert
|
||||
inserted = symbolTable.amend(*globalUniformBlock, firstNewMember);
|
||||
}
|
||||
|
||||
if (inserted) {
|
||||
finalizeGlobalUniformBlockLayout(*globalUniformBlock);
|
||||
firstNewMember = numMembers;
|
||||
}
|
||||
|
||||
return inserted;
|
||||
}
|
||||
|
||||
} // end namespace glslang
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -77,12 +77,22 @@ public:
|
|||
EProfile profile, const SpvVersion& spvVersion, EShLanguage language,
|
||||
TInfoSink& infoSink, bool forwardCompatible, EShMessages messages)
|
||||
: TParseVersions(interm, version, profile, spvVersion, language, infoSink, forwardCompatible, messages),
|
||||
symbolTable(symbolTable), tokensBeforeEOF(false),
|
||||
linkage(nullptr), scanContext(nullptr), ppContext(nullptr) { }
|
||||
symbolTable(symbolTable),
|
||||
linkage(nullptr), scanContext(nullptr), ppContext(nullptr),
|
||||
globalUniformBlock(nullptr) { }
|
||||
virtual ~TParseContextBase() { }
|
||||
|
||||
|
||||
virtual void C_DECL error(const TSourceLoc&, const char* szReason, const char* szToken,
|
||||
const char* szExtraInfoFormat, ...);
|
||||
virtual void C_DECL warn(const TSourceLoc&, const char* szReason, const char* szToken,
|
||||
const char* szExtraInfoFormat, ...);
|
||||
virtual void C_DECL ppError(const TSourceLoc&, const char* szReason, const char* szToken,
|
||||
const char* szExtraInfoFormat, ...);
|
||||
virtual void C_DECL ppWarn(const TSourceLoc&, const char* szReason, const char* szToken,
|
||||
const char* szExtraInfoFormat, ...);
|
||||
|
||||
virtual void setLimits(const TBuiltInResource&) = 0;
|
||||
|
||||
|
||||
EShLanguage getLanguage() const { return language; }
|
||||
TIntermAggregate*& getLinkage() { return linkage; }
|
||||
void setScanContext(TScanContext* c) { scanContext = c; }
|
||||
|
|
@ -125,7 +135,16 @@ public:
|
|||
}
|
||||
|
||||
TSymbolTable& symbolTable; // symbol table that goes with the current language, version, and profile
|
||||
bool tokensBeforeEOF;
|
||||
|
||||
// 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);
|
||||
virtual bool insertGlobalUniformBlock();
|
||||
|
||||
virtual bool lValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*);
|
||||
virtual void rValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*);
|
||||
|
||||
protected:
|
||||
TParseContextBase(TParseContextBase&);
|
||||
|
|
@ -142,6 +161,58 @@ protected:
|
|||
std::function<void(int, int, const char*)> versionCallback;
|
||||
std::function<void(int, const char*, const char*)> extensionCallback;
|
||||
std::function<void(int, const char*)> errorCallback;
|
||||
|
||||
// see implementation for detail
|
||||
const TFunction* selectFunction(const TVector<const TFunction*>, const TFunction&,
|
||||
std::function<bool(const TType&, const TType&)>,
|
||||
std::function<bool(const TType&, const TType&, const TType&)>,
|
||||
/* output */ bool& tie);
|
||||
|
||||
// Manage the global uniform block (default uniforms in GLSL, $Global in HLSL)
|
||||
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 void finalizeGlobalUniformBlockLayout(TVariable&) { }
|
||||
virtual void outputMessage(const TSourceLoc&, const char* szReason, const char* szToken,
|
||||
const char* szExtraInfoFormat, TPrefixType prefix,
|
||||
va_list args);
|
||||
virtual void makeEditable(TSymbol*&);
|
||||
virtual TVariable* getEditableVariable(const char* name);
|
||||
};
|
||||
|
||||
//
|
||||
// Manage the state for when to respect precision qualifiers and when to warn about
|
||||
// the defaults being different than might be expected.
|
||||
//
|
||||
class TPrecisionManager {
|
||||
public:
|
||||
TPrecisionManager() : obey(false), warn(false), explicitIntDefault(false), explicitFloatDefault(false){ }
|
||||
virtual ~TPrecisionManager() {}
|
||||
|
||||
void respectPrecisionQualifiers() { obey = true; }
|
||||
bool respectingPrecisionQualifiers() const { return obey; }
|
||||
bool shouldWarnAboutDefaults() const { return warn; }
|
||||
void defaultWarningGiven() { warn = false; }
|
||||
void warnAboutDefaults() { warn = true; }
|
||||
void explicitIntDefaultSeen()
|
||||
{
|
||||
explicitIntDefault = true;
|
||||
if (explicitFloatDefault)
|
||||
warn = false;
|
||||
}
|
||||
void explicitFloatDefaultSeen()
|
||||
{
|
||||
explicitFloatDefault = true;
|
||||
if (explicitIntDefault)
|
||||
warn = false;
|
||||
}
|
||||
|
||||
protected:
|
||||
bool obey; // respect precision qualifiers
|
||||
bool warn; // need to give a warning about the defaults
|
||||
bool explicitIntDefault; // user set the default for int/uint
|
||||
bool explicitFloatDefault; // user set the default for float
|
||||
};
|
||||
|
||||
//
|
||||
|
|
@ -155,19 +226,13 @@ public:
|
|||
bool forwardCompatible = false, EShMessages messages = EShMsgDefault);
|
||||
virtual ~TParseContext();
|
||||
|
||||
bool obeyPrecisionQualifiers() const { return precisionManager.respectingPrecisionQualifiers(); };
|
||||
void setPrecisionDefaults();
|
||||
|
||||
void setLimits(const TBuiltInResource&);
|
||||
bool parseShaderStrings(TPpContext&, TInputScanner& input, bool versionWillBeError = false);
|
||||
void parserError(const char* s); // for bison's yyerror
|
||||
|
||||
void C_DECL error(const TSourceLoc&, const char* szReason, const char* szToken,
|
||||
const char* szExtraInfoFormat, ...);
|
||||
void C_DECL warn(const TSourceLoc&, const char* szReason, const char* szToken,
|
||||
const char* szExtraInfoFormat, ...);
|
||||
void C_DECL ppError(const TSourceLoc&, const char* szReason, const char* szToken,
|
||||
const char* szExtraInfoFormat, ...);
|
||||
void C_DECL ppWarn(const TSourceLoc&, const char* szReason, const char* szToken,
|
||||
const char* szExtraInfoFormat, ...);
|
||||
|
||||
void reservedErrorCheck(const TSourceLoc&, const TString&);
|
||||
void reservedPpErrorCheck(const TSourceLoc&, const char* name, const char* op);
|
||||
bool lineContinuationCheck(const TSourceLoc&, bool endOfComment);
|
||||
|
|
@ -181,7 +246,6 @@ public:
|
|||
void handleIndexLimits(const TSourceLoc&, TIntermTyped* base, TIntermTyped* index);
|
||||
|
||||
void makeEditable(TSymbol*&);
|
||||
TVariable* getEditableVariable(const char* name);
|
||||
bool isIoResizeArray(const TType&) const;
|
||||
void fixIoArraySize(const TSourceLoc&, TType&);
|
||||
void ioArrayCheck(const TSourceLoc&, const TType&, const TString& identifier);
|
||||
|
|
@ -197,6 +261,8 @@ public:
|
|||
TFunction* handleFunctionDeclarator(const TSourceLoc&, TFunction& function, bool prototype);
|
||||
TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&);
|
||||
TIntermTyped* handleFunctionCall(const TSourceLoc&, TFunction*, TIntermNode*);
|
||||
TIntermTyped* handleBuiltInFunctionCall(TSourceLoc, TIntermNode& arguments, const TFunction& function);
|
||||
void computeBuiltinPrecisions(TIntermTyped&, const TFunction&);
|
||||
TIntermNode* handleReturnValue(const TSourceLoc&, TIntermTyped*);
|
||||
void checkLocation(const TSourceLoc&, TOperator);
|
||||
TIntermTyped* handleLengthMethod(const TSourceLoc&, TFunction*, TIntermNode*);
|
||||
|
|
@ -204,15 +270,19 @@ public:
|
|||
TIntermTyped* addOutputArgumentConversions(const TFunction&, TIntermAggregate&) const;
|
||||
void builtInOpCheck(const TSourceLoc&, const TFunction&, TIntermOperator&);
|
||||
void nonOpBuiltInCheck(const TSourceLoc&, const TFunction&, TIntermAggregate&);
|
||||
void userFunctionCallCheck(const TSourceLoc&, TIntermAggregate&);
|
||||
void samplerConstructorLocationCheck(const TSourceLoc&, const char* token, TIntermNode*);
|
||||
TFunction* handleConstructorCall(const TSourceLoc&, const TPublicType&);
|
||||
void handlePrecisionQualifier(const TSourceLoc&, TQualifier&, TPrecisionQualifier);
|
||||
void checkPrecisionQualifier(const TSourceLoc&, TPrecisionQualifier);
|
||||
|
||||
bool parseVectorFields(const TSourceLoc&, const TString&, int vecSize, TVectorFields&);
|
||||
void assignError(const TSourceLoc&, const char* op, TString left, TString right);
|
||||
void unaryOpError(const TSourceLoc&, const char* op, TString operand);
|
||||
void binaryOpError(const TSourceLoc&, const char* op, TString left, TString right);
|
||||
void variableCheck(TIntermTyped*& nodePtr);
|
||||
bool lValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*);
|
||||
void rValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*);
|
||||
bool lValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*) override;
|
||||
void rValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*) override;
|
||||
void constantValueCheck(TIntermTyped* node, const char* token);
|
||||
void integerCheck(const TIntermTyped* node, const char* token);
|
||||
void globalCheck(const TSourceLoc&, const char* token);
|
||||
|
|
@ -276,7 +346,7 @@ public:
|
|||
const TFunction* findFunction400(const TSourceLoc& loc, const TFunction& call, bool& builtIn);
|
||||
void declareTypeDefaults(const TSourceLoc&, const TPublicType&);
|
||||
TIntermNode* declareVariable(const TSourceLoc&, TString& identifier, const TPublicType&, TArraySizes* typeArray = 0, TIntermTyped* initializer = 0);
|
||||
TIntermTyped* addConstructor(const TSourceLoc&, TIntermNode*, const TType&, TOperator);
|
||||
TIntermTyped* addConstructor(const TSourceLoc&, TIntermNode*, const TType&);
|
||||
TIntermTyped* constructAggregate(TIntermNode*, const TType&, int, const TSourceLoc&);
|
||||
TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermTyped*, const TSourceLoc&, bool subset);
|
||||
void declareBlock(const TSourceLoc&, TTypeList& typeList, const TString* instanceName = 0, TArraySizes* arraySizes = 0);
|
||||
|
|
@ -302,11 +372,7 @@ protected:
|
|||
void declareArray(const TSourceLoc&, TString& identifier, const TType&, TSymbol*&, bool& newDeclaration);
|
||||
TIntermNode* executeInitializer(const TSourceLoc&, TIntermTyped* initializer, TVariable* variable);
|
||||
TIntermTyped* convertInitializerList(const TSourceLoc&, const TType&, TIntermTyped* initializer);
|
||||
TOperator mapTypeToConstructorOp(const TType&) const;
|
||||
void finalErrorCheck();
|
||||
void outputMessage(const TSourceLoc&, const char* szReason, const char* szToken,
|
||||
const char* szExtraInfoFormat, TPrefixType prefix,
|
||||
va_list args);
|
||||
|
||||
public:
|
||||
//
|
||||
|
|
@ -338,7 +404,7 @@ protected:
|
|||
const bool parsingBuiltins; // true if parsing built-in symbols/functions
|
||||
static const int maxSamplerIndex = EsdNumDims * (EbtNumTypes * (2 * 2 * 2 * 2 * 2)); // see computeSamplerTypeIndex()
|
||||
TPrecisionQualifier defaultSamplerPrecision[maxSamplerIndex];
|
||||
bool afterEOF;
|
||||
TPrecisionManager precisionManager;
|
||||
TQualifier globalBufferDefaults;
|
||||
TQualifier globalUniformDefaults;
|
||||
TQualifier globalInputDefaults;
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ void InitializeMemoryPools()
|
|||
TThreadMemoryPools* threadData = new TThreadMemoryPools();
|
||||
|
||||
threadData->threadPoolAllocator = threadPoolAllocator;
|
||||
|
||||
|
||||
OS_SetTLSValue(PoolIndex, threadData);
|
||||
}
|
||||
|
||||
|
|
@ -63,7 +63,7 @@ void FreeGlobalPools()
|
|||
TThreadMemoryPools* globalPools = static_cast<TThreadMemoryPools*>(OS_GetTLSValue(PoolIndex));
|
||||
if (! globalPools)
|
||||
return;
|
||||
|
||||
|
||||
GetThreadPoolAllocator().popAll();
|
||||
delete &GetThreadPoolAllocator();
|
||||
delete globalPools;
|
||||
|
|
@ -149,12 +149,12 @@ TPoolAllocator::TPoolAllocator(int growthIncrement, int allocationAlignment) :
|
|||
|
||||
TPoolAllocator::~TPoolAllocator()
|
||||
{
|
||||
while (inUseList) {
|
||||
tHeader* next = inUseList->nextPage;
|
||||
while (inUseList) {
|
||||
tHeader* next = inUseList->nextPage;
|
||||
inUseList->~tHeader();
|
||||
delete [] reinterpret_cast<char*>(inUseList);
|
||||
inUseList = next;
|
||||
}
|
||||
inUseList = next;
|
||||
}
|
||||
|
||||
//
|
||||
// Always delete the free list memory - it can't be being
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@
|
|||
// GLSL scanning, leveraging the scanning done by the preprocessor.
|
||||
//
|
||||
|
||||
#include <string.h>
|
||||
#include <cstring>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
|
|
@ -55,7 +55,7 @@
|
|||
|
||||
// Required to avoid missing prototype warnings for some compilers
|
||||
int yylex(YYSTYPE*, glslang::TParseContext&);
|
||||
|
||||
|
||||
namespace glslang {
|
||||
|
||||
// read past any white space
|
||||
|
|
@ -463,6 +463,25 @@ void TScanContext::fillInKeywordMap()
|
|||
(*KeywordMap)["u64vec3"] = U64VEC3;
|
||||
(*KeywordMap)["u64vec4"] = U64VEC4;
|
||||
|
||||
#ifdef AMD_EXTENSIONS
|
||||
(*KeywordMap)["float16_t"] = FLOAT16_T;
|
||||
(*KeywordMap)["f16vec2"] = F16VEC2;
|
||||
(*KeywordMap)["f16vec3"] = F16VEC3;
|
||||
(*KeywordMap)["f16vec4"] = F16VEC4;
|
||||
(*KeywordMap)["f16mat2"] = F16MAT2;
|
||||
(*KeywordMap)["f16mat3"] = F16MAT3;
|
||||
(*KeywordMap)["f16mat4"] = F16MAT4;
|
||||
(*KeywordMap)["f16mat2x2"] = F16MAT2X2;
|
||||
(*KeywordMap)["f16mat2x3"] = F16MAT2X3;
|
||||
(*KeywordMap)["f16mat2x4"] = F16MAT2X4;
|
||||
(*KeywordMap)["f16mat3x2"] = F16MAT3X2;
|
||||
(*KeywordMap)["f16mat3x3"] = F16MAT3X3;
|
||||
(*KeywordMap)["f16mat3x4"] = F16MAT3X4;
|
||||
(*KeywordMap)["f16mat4x2"] = F16MAT4X2;
|
||||
(*KeywordMap)["f16mat4x3"] = F16MAT4X3;
|
||||
(*KeywordMap)["f16mat4x4"] = F16MAT4X4;
|
||||
#endif
|
||||
|
||||
(*KeywordMap)["sampler2D"] = SAMPLER2D;
|
||||
(*KeywordMap)["samplerCube"] = SAMPLERCUBE;
|
||||
(*KeywordMap)["samplerCubeArray"] = SAMPLERCUBEARRAY;
|
||||
|
|
@ -553,6 +572,9 @@ void TScanContext::fillInKeywordMap()
|
|||
(*KeywordMap)["noperspective"] = NOPERSPECTIVE;
|
||||
(*KeywordMap)["smooth"] = SMOOTH;
|
||||
(*KeywordMap)["flat"] = FLAT;
|
||||
#ifdef AMD_EXTENSIONS
|
||||
(*KeywordMap)["__explicitInterpAMD"] = __EXPLICITINTERPAMD;
|
||||
#endif
|
||||
(*KeywordMap)["centroid"] = CENTROID;
|
||||
(*KeywordMap)["precise"] = PRECISE;
|
||||
(*KeywordMap)["invariant"] = INVARIANT;
|
||||
|
|
@ -561,7 +583,7 @@ void TScanContext::fillInKeywordMap()
|
|||
(*KeywordMap)["superp"] = SUPERP;
|
||||
|
||||
ReservedSet = new std::unordered_set<const char*, str_hash, str_eq>;
|
||||
|
||||
|
||||
ReservedSet->insert("common");
|
||||
ReservedSet->insert("partition");
|
||||
ReservedSet->insert("active");
|
||||
|
|
@ -609,13 +631,15 @@ void TScanContext::deleteKeywordMap()
|
|||
ReservedSet = nullptr;
|
||||
}
|
||||
|
||||
// Called by yylex to get the next token.
|
||||
// Returning 0 implies end of input.
|
||||
int TScanContext::tokenize(TPpContext* pp, TParserToken& token)
|
||||
{
|
||||
do {
|
||||
parserToken = &token;
|
||||
TPpToken ppToken;
|
||||
tokenText = pp->tokenize(&ppToken);
|
||||
if (tokenText == nullptr)
|
||||
if (tokenText == nullptr || tokenText[0] == 0)
|
||||
return 0;
|
||||
|
||||
loc = ppToken.loc;
|
||||
|
|
@ -675,13 +699,16 @@ int TScanContext::tokenize(TPpContext* pp, TParserToken& token)
|
|||
|
||||
case PpAtomDecrement: return DEC_OP;
|
||||
case PpAtomIncrement: return INC_OP;
|
||||
|
||||
|
||||
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;
|
||||
case PpAtomConstFloat: parserToken->sType.lex.d = ppToken.dval; return FLOATCONSTANT;
|
||||
case PpAtomConstDouble: parserToken->sType.lex.d = ppToken.dval; return DOUBLECONSTANT;
|
||||
#ifdef AMD_EXTENSIONS
|
||||
case PpAtomConstFloat16: parserToken->sType.lex.d = ppToken.dval; return FLOAT16CONSTANT;
|
||||
#endif
|
||||
case PpAtomIdentifier:
|
||||
{
|
||||
int token = tokenizeIdentifier();
|
||||
|
|
@ -847,7 +874,7 @@ int TScanContext::tokenizeIdentifier()
|
|||
case MAT3X4:
|
||||
case MAT4X2:
|
||||
case MAT4X3:
|
||||
case MAT4X4:
|
||||
case MAT4X4:
|
||||
return matNxM();
|
||||
|
||||
case DMAT2:
|
||||
|
|
@ -933,10 +960,38 @@ int TScanContext::tokenizeIdentifier()
|
|||
case U64VEC2:
|
||||
case U64VEC3:
|
||||
case U64VEC4:
|
||||
if (parseContext.profile != EEsProfile && parseContext.version >= 450)
|
||||
afterType = true;
|
||||
if (parseContext.symbolTable.atBuiltInLevel() ||
|
||||
(parseContext.extensionTurnedOn(E_GL_ARB_gpu_shader_int64) &&
|
||||
parseContext.profile != EEsProfile && parseContext.version >= 450))
|
||||
return keyword;
|
||||
return identifierOrType();
|
||||
|
||||
#ifdef AMD_EXTENSIONS
|
||||
case FLOAT16_T:
|
||||
case F16VEC2:
|
||||
case F16VEC3:
|
||||
case F16VEC4:
|
||||
case F16MAT2:
|
||||
case F16MAT3:
|
||||
case F16MAT4:
|
||||
case F16MAT2X2:
|
||||
case F16MAT2X3:
|
||||
case F16MAT2X4:
|
||||
case F16MAT3X2:
|
||||
case F16MAT3X3:
|
||||
case F16MAT3X4:
|
||||
case F16MAT4X2:
|
||||
case F16MAT4X3:
|
||||
case F16MAT4X4:
|
||||
afterType = true;
|
||||
if (parseContext.symbolTable.atBuiltInLevel() ||
|
||||
(parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_half_float) &&
|
||||
parseContext.profile != EEsProfile && parseContext.version >= 450))
|
||||
return keyword;
|
||||
return identifierOrType();
|
||||
#endif
|
||||
|
||||
case SAMPLERCUBEARRAY:
|
||||
case SAMPLERCUBEARRAYSHADOW:
|
||||
case ISAMPLERCUBEARRAY:
|
||||
|
|
@ -973,7 +1028,7 @@ int TScanContext::tokenizeIdentifier()
|
|||
case USAMPLER2DARRAY:
|
||||
afterType = true;
|
||||
return nonreservedKeyword(300, 130);
|
||||
|
||||
|
||||
case ISAMPLER2DRECT:
|
||||
case USAMPLER2DRECT:
|
||||
afterType = true;
|
||||
|
|
@ -991,7 +1046,7 @@ int TScanContext::tokenizeIdentifier()
|
|||
if (parseContext.extensionsTurnedOn(Num_AEP_texture_buffer, AEP_texture_buffer))
|
||||
return keyword;
|
||||
return es30ReservedFromGLSL(140);
|
||||
|
||||
|
||||
case SAMPLER2DMS:
|
||||
case ISAMPLER2DMS:
|
||||
case USAMPLER2DMS:
|
||||
|
|
@ -1110,13 +1165,21 @@ int TScanContext::tokenizeIdentifier()
|
|||
|
||||
case NOPERSPECTIVE:
|
||||
return es30ReservedFromGLSL(130);
|
||||
|
||||
|
||||
case SMOOTH:
|
||||
if ((parseContext.profile == EEsProfile && parseContext.version < 300) ||
|
||||
(parseContext.profile != EEsProfile && parseContext.version < 130))
|
||||
return identifierOrType();
|
||||
return keyword;
|
||||
|
||||
#ifdef AMD_EXTENSIONS
|
||||
case __EXPLICITINTERPAMD:
|
||||
if (parseContext.profile != EEsProfile && parseContext.version >= 450 &&
|
||||
parseContext.extensionTurnedOn(E_GL_AMD_shader_explicit_vertex_parameter))
|
||||
return keyword;
|
||||
return identifierOrType();
|
||||
#endif
|
||||
|
||||
case FLAT:
|
||||
if (parseContext.profile == EEsProfile && parseContext.version < 300)
|
||||
reservedWord();
|
||||
|
|
@ -1161,7 +1224,7 @@ int TScanContext::tokenizeIdentifier()
|
|||
bool reserved = parseContext.profile == EEsProfile || parseContext.version >= 130;
|
||||
return identifierOrReserved(reserved);
|
||||
}
|
||||
|
||||
|
||||
default:
|
||||
parseContext.infoSink.info.message(EPrefixInternalError, "Unknown glslang keyword", loc);
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -204,6 +204,8 @@ public:
|
|||
currentSource = numSources;
|
||||
}
|
||||
|
||||
bool atEndOfInput() const { return endOfFileReached; }
|
||||
|
||||
const TSourceLoc& getSourceLoc() const
|
||||
{
|
||||
if (singleLogical) {
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@
|
|||
// This is the platform independent interface between an OGL driver
|
||||
// and the shading language compiler/linker.
|
||||
//
|
||||
#include <string.h>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <memory>
|
||||
|
|
@ -51,6 +51,7 @@
|
|||
#include "../../hlsl/hlslParseables.h"
|
||||
#include "Scan.h"
|
||||
#include "ScanContext.h"
|
||||
#include "../../hlsl/hlslScanContext.h"
|
||||
|
||||
#include "../Include/ShHandle.h"
|
||||
#include "../../OGLCompilersDLL/InitializeDll.h"
|
||||
|
|
@ -60,6 +61,7 @@
|
|||
#define SH_EXPORTING
|
||||
#include "../Public/ShaderLang.h"
|
||||
#include "reflection.h"
|
||||
#include "iomapper.h"
|
||||
#include "Initialize.h"
|
||||
|
||||
namespace { // anonymous namespace for file-local functions and symbols
|
||||
|
|
@ -146,6 +148,23 @@ int MapProfileToIndex(EProfile profile)
|
|||
return index;
|
||||
}
|
||||
|
||||
const int SourceCount = 2;
|
||||
|
||||
int MapSourceToIndex(EShSource source)
|
||||
{
|
||||
int index = 0;
|
||||
|
||||
switch (source) {
|
||||
case EShSourceGlsl: index = 0; break;
|
||||
case EShSourceHlsl: index = 1; break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
assert(index < SourceCount);
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
// only one of these needed for non-ES; ES needs 2 for different precision defaults of built-ins
|
||||
enum EPrecisionClass {
|
||||
EPcGeneral,
|
||||
|
|
@ -161,8 +180,8 @@ enum EPrecisionClass {
|
|||
// Each has a different set of built-ins, and we want to preserve that from
|
||||
// compile to compile.
|
||||
//
|
||||
TSymbolTable* CommonSymbolTable[VersionCount][SpvVersionCount][ProfileCount][EPcCount] = {};
|
||||
TSymbolTable* SharedSymbolTables[VersionCount][SpvVersionCount][ProfileCount][EShLangCount] = {};
|
||||
TSymbolTable* CommonSymbolTable[VersionCount][SpvVersionCount][ProfileCount][SourceCount][EPcCount] = {};
|
||||
TSymbolTable* SharedSymbolTables[VersionCount][SpvVersionCount][ProfileCount][SourceCount][EShLangCount] = {};
|
||||
|
||||
TPoolAllocator* PerProcessGPA = 0;
|
||||
|
||||
|
|
@ -305,7 +324,8 @@ void SetupBuiltinSymbolTable(int version, EProfile profile, const SpvVersion& sp
|
|||
int versionIndex = MapVersionToIndex(version);
|
||||
int spvVersionIndex = MapSpvVersionToIndex(spvVersion);
|
||||
int profileIndex = MapProfileToIndex(profile);
|
||||
if (CommonSymbolTable[versionIndex][spvVersionIndex][profileIndex][EPcGeneral]) {
|
||||
int sourceIndex = MapSourceToIndex(source);
|
||||
if (CommonSymbolTable[versionIndex][spvVersionIndex][profileIndex][sourceIndex][EPcGeneral]) {
|
||||
glslang::ReleaseGlobalLock();
|
||||
|
||||
return;
|
||||
|
|
@ -333,18 +353,18 @@ void SetupBuiltinSymbolTable(int version, EProfile profile, const SpvVersion& sp
|
|||
// Copy the local symbol tables from the new pool to the global tables using the process-global pool
|
||||
for (int precClass = 0; precClass < EPcCount; ++precClass) {
|
||||
if (! commonTable[precClass]->isEmpty()) {
|
||||
CommonSymbolTable[versionIndex][spvVersionIndex][profileIndex][precClass] = new TSymbolTable;
|
||||
CommonSymbolTable[versionIndex][spvVersionIndex][profileIndex][precClass]->copyTable(*commonTable[precClass]);
|
||||
CommonSymbolTable[versionIndex][spvVersionIndex][profileIndex][precClass]->readOnly();
|
||||
CommonSymbolTable[versionIndex][spvVersionIndex][profileIndex][sourceIndex][precClass] = new TSymbolTable;
|
||||
CommonSymbolTable[versionIndex][spvVersionIndex][profileIndex][sourceIndex][precClass]->copyTable(*commonTable[precClass]);
|
||||
CommonSymbolTable[versionIndex][spvVersionIndex][profileIndex][sourceIndex][precClass]->readOnly();
|
||||
}
|
||||
}
|
||||
for (int stage = 0; stage < EShLangCount; ++stage) {
|
||||
if (! stageTables[stage]->isEmpty()) {
|
||||
SharedSymbolTables[versionIndex][spvVersionIndex][profileIndex][stage] = new TSymbolTable;
|
||||
SharedSymbolTables[versionIndex][spvVersionIndex][profileIndex][stage]->adoptLevels(*CommonSymbolTable
|
||||
[versionIndex][spvVersionIndex][profileIndex][CommonIndex(profile, (EShLanguage)stage)]);
|
||||
SharedSymbolTables[versionIndex][spvVersionIndex][profileIndex][stage]->copyTable(*stageTables[stage]);
|
||||
SharedSymbolTables[versionIndex][spvVersionIndex][profileIndex][stage]->readOnly();
|
||||
SharedSymbolTables[versionIndex][spvVersionIndex][profileIndex][sourceIndex][stage] = new TSymbolTable;
|
||||
SharedSymbolTables[versionIndex][spvVersionIndex][profileIndex][sourceIndex][stage]->adoptLevels(*CommonSymbolTable
|
||||
[versionIndex][spvVersionIndex][profileIndex][sourceIndex][CommonIndex(profile, (EShLanguage)stage)]);
|
||||
SharedSymbolTables[versionIndex][spvVersionIndex][profileIndex][sourceIndex][stage]->copyTable(*stageTables[stage]);
|
||||
SharedSymbolTables[versionIndex][spvVersionIndex][profileIndex][sourceIndex][stage]->readOnly();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -656,6 +676,7 @@ bool ProcessDeferred(
|
|||
TSymbolTable* cachedTable = SharedSymbolTables[MapVersionToIndex(version)]
|
||||
[MapSpvVersionToIndex(spvVersion)]
|
||||
[MapProfileToIndex(profile)]
|
||||
[MapSourceToIndex(source)]
|
||||
[compiler->getLanguage()];
|
||||
|
||||
// Dynamically allocate the symbol table so we can control when it is deallocated WRT the pool.
|
||||
|
|
@ -676,10 +697,9 @@ bool ProcessDeferred(
|
|||
TParseContextBase* parseContext;
|
||||
if (source == EShSourceHlsl) {
|
||||
parseContext = new HlslParseContext(symbolTable, intermediate, false, version, profile, spvVersion,
|
||||
compiler->getLanguage(), compiler->infoSink, forwardCompatible, messages);
|
||||
}
|
||||
else {
|
||||
intermediate.setEntryPoint("main");
|
||||
compiler->getLanguage(), compiler->infoSink, forwardCompatible, messages);
|
||||
} else {
|
||||
intermediate.setEntryPointName("main");
|
||||
parseContext = new TParseContext(symbolTable, intermediate, false, version, profile, spvVersion,
|
||||
compiler->getLanguage(), compiler->infoSink, forwardCompatible, messages);
|
||||
}
|
||||
|
|
@ -1030,6 +1050,7 @@ int ShInitialize()
|
|||
PerProcessGPA = new TPoolAllocator();
|
||||
|
||||
glslang::TScanContext::fillInKeywordMap();
|
||||
glslang::HlslScanContext::fillInKeywordMap();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -1092,9 +1113,11 @@ int __fastcall ShFinalize()
|
|||
for (int version = 0; version < VersionCount; ++version) {
|
||||
for (int spvVersion = 0; spvVersion < SpvVersionCount; ++spvVersion) {
|
||||
for (int p = 0; p < ProfileCount; ++p) {
|
||||
for (int lang = 0; lang < EShLangCount; ++lang) {
|
||||
delete SharedSymbolTables[version][spvVersion][p][lang];
|
||||
SharedSymbolTables[version][spvVersion][p][lang] = 0;
|
||||
for (int source = 0; source < SourceCount; ++source) {
|
||||
for (int stage = 0; stage < EShLangCount; ++stage) {
|
||||
delete SharedSymbolTables[version][spvVersion][p][source][stage];
|
||||
SharedSymbolTables[version][spvVersion][p][source][stage] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1103,9 +1126,11 @@ int __fastcall ShFinalize()
|
|||
for (int version = 0; version < VersionCount; ++version) {
|
||||
for (int spvVersion = 0; spvVersion < SpvVersionCount; ++spvVersion) {
|
||||
for (int p = 0; p < ProfileCount; ++p) {
|
||||
for (int pc = 0; pc < EPcCount; ++pc) {
|
||||
delete CommonSymbolTable[version][spvVersion][p][pc];
|
||||
CommonSymbolTable[version][spvVersion][p][pc] = 0;
|
||||
for (int source = 0; source < SourceCount; ++source) {
|
||||
for (int pc = 0; pc < EPcCount; ++pc) {
|
||||
delete CommonSymbolTable[version][spvVersion][p][source][pc];
|
||||
CommonSymbolTable[version][spvVersion][p][source][pc] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1118,6 +1143,7 @@ int __fastcall ShFinalize()
|
|||
}
|
||||
|
||||
glslang::TScanContext::deleteKeywordMap();
|
||||
glslang::HlslScanContext::deleteKeywordMap();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -1463,9 +1489,16 @@ void TShader::setStringsWithLengthsAndNames(
|
|||
|
||||
void TShader::setEntryPoint(const char* entryPoint)
|
||||
{
|
||||
intermediate->setEntryPoint(entryPoint);
|
||||
intermediate->setEntryPointName(entryPoint);
|
||||
}
|
||||
|
||||
void TShader::setShiftSamplerBinding(unsigned int base) { intermediate->setShiftSamplerBinding(base); }
|
||||
void TShader::setShiftTextureBinding(unsigned int base) { intermediate->setShiftTextureBinding(base); }
|
||||
void TShader::setShiftUboBinding(unsigned int base) { intermediate->setShiftUboBinding(base); }
|
||||
void TShader::setAutoMapBindings(bool map) { intermediate->setAutoMapBindings(map); }
|
||||
void TShader::setFlattenUniformArrays(bool flatten) { intermediate->setFlattenUniformArrays(flatten); }
|
||||
void TShader::setNoStorageFormat(bool useUnknownFormat) { intermediate->setNoStorageFormat(useUnknownFormat); }
|
||||
|
||||
//
|
||||
// Turn the shader strings into a parse tree in the TIntermediate.
|
||||
//
|
||||
|
|
@ -1526,7 +1559,7 @@ const char* TShader::getInfoDebugLog()
|
|||
return infoSink->debug.c_str();
|
||||
}
|
||||
|
||||
TProgram::TProgram() : pool(0), reflection(0), linked(false)
|
||||
TProgram::TProgram() : pool(0), reflection(0), ioMapper(nullptr), linked(false)
|
||||
{
|
||||
infoSink = new TInfoSink;
|
||||
for (int s = 0; s < EShLangCount; ++s) {
|
||||
|
|
@ -1662,20 +1695,42 @@ bool TProgram::buildReflection()
|
|||
return true;
|
||||
}
|
||||
|
||||
int TProgram::getNumLiveUniformVariables() { return reflection->getNumUniforms(); }
|
||||
int TProgram::getNumLiveUniformBlocks() { return reflection->getNumUniformBlocks(); }
|
||||
const char* TProgram::getUniformName(int index) { return reflection->getUniform(index).name.c_str(); }
|
||||
const char* TProgram::getUniformBlockName(int index) { return reflection->getUniformBlock(index).name.c_str(); }
|
||||
int TProgram::getUniformBlockSize(int index) { return reflection->getUniformBlock(index).size; }
|
||||
int TProgram::getUniformIndex(const char* name) { return reflection->getIndex(name); }
|
||||
int TProgram::getUniformBlockIndex(int index) { return reflection->getUniform(index).index; }
|
||||
int TProgram::getUniformType(int index) { return reflection->getUniform(index).glDefineType; }
|
||||
int TProgram::getUniformBufferOffset(int index) { return reflection->getUniform(index).offset; }
|
||||
int TProgram::getUniformArraySize(int index) { return reflection->getUniform(index).size; }
|
||||
int TProgram::getNumLiveAttributes() { return reflection->getNumAttributes(); }
|
||||
const char* TProgram::getAttributeName(int index) { return reflection->getAttribute(index).name.c_str(); }
|
||||
int TProgram::getAttributeType(int index) { return reflection->getAttribute(index).glDefineType; }
|
||||
int TProgram::getNumLiveUniformVariables() const { return reflection->getNumUniforms(); }
|
||||
int TProgram::getNumLiveUniformBlocks() const { return reflection->getNumUniformBlocks(); }
|
||||
const char* TProgram::getUniformName(int index) const { return reflection->getUniform(index).name.c_str(); }
|
||||
const char* TProgram::getUniformBlockName(int index) const { return reflection->getUniformBlock(index).name.c_str(); }
|
||||
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::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; }
|
||||
int TProgram::getNumLiveAttributes() const { return reflection->getNumAttributes(); }
|
||||
const char* TProgram::getAttributeName(int index) const { return reflection->getAttribute(index).name.c_str(); }
|
||||
int TProgram::getAttributeType(int index) const { return reflection->getAttribute(index).glDefineType; }
|
||||
const TType* TProgram::getUniformTType(int index) const { return reflection->getUniform(index).getType(); }
|
||||
const TType* TProgram::getUniformBlockTType(int index) const { return reflection->getUniformBlock(index).getType(); }
|
||||
|
||||
void TProgram::dumpReflection() { reflection->dump(); }
|
||||
|
||||
//
|
||||
// I/O mapping implementation.
|
||||
//
|
||||
bool TProgram::mapIO()
|
||||
{
|
||||
if (! linked || ioMapper)
|
||||
return false;
|
||||
|
||||
ioMapper = new TIoMapper;
|
||||
|
||||
for (int s = 0; s < EShLangCount; ++s) {
|
||||
if (intermediate[s]) {
|
||||
if (! ioMapper->addStage((EShLanguage)s, *intermediate[s], *infoSink))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // end namespace glslang
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@
|
|||
//
|
||||
|
||||
//
|
||||
// Symbol table for parsing. Most functionaliy and main ideas
|
||||
// Symbol table for parsing. Most functionality and main ideas
|
||||
// are documented in the header file.
|
||||
//
|
||||
|
||||
|
|
@ -60,6 +60,9 @@ void TType::buildMangledName(TString& mangledName)
|
|||
switch (basicType) {
|
||||
case EbtFloat: mangledName += 'f'; break;
|
||||
case EbtDouble: mangledName += 'd'; break;
|
||||
#ifdef AMD_EXTENSIONS
|
||||
case EbtFloat16: mangledName += "f16"; break;
|
||||
#endif
|
||||
case EbtInt: mangledName += 'i'; break;
|
||||
case EbtUint: mangledName += 'u'; break;
|
||||
case EbtInt64: mangledName += "i64"; break;
|
||||
|
|
@ -250,7 +253,7 @@ TSymbol::TSymbol(const TSymbol& copyOf)
|
|||
}
|
||||
|
||||
TVariable::TVariable(const TVariable& copyOf) : TSymbol(copyOf)
|
||||
{
|
||||
{
|
||||
type.deepCopy(copyOf.type);
|
||||
userType = copyOf.userType;
|
||||
numExtensions = 0;
|
||||
|
|
@ -276,7 +279,7 @@ TVariable* TVariable::clone() const
|
|||
}
|
||||
|
||||
TFunction::TFunction(const TFunction& copyOf) : TSymbol(copyOf)
|
||||
{
|
||||
{
|
||||
for (unsigned int i = 0; i < copyOf.parameters.size(); ++i) {
|
||||
TParameter param;
|
||||
parameters.push_back(param);
|
||||
|
|
|
|||
|
|
@ -147,7 +147,8 @@ public:
|
|||
TVariable(const TString *name, const TType& t, bool uT = false )
|
||||
: TSymbol(name),
|
||||
userType(uT),
|
||||
constSubtree(nullptr) { type.shallowCopy(t); }
|
||||
constSubtree(nullptr),
|
||||
anonId(-1) { type.shallowCopy(t); }
|
||||
virtual TVariable* clone() const;
|
||||
virtual ~TVariable() { }
|
||||
|
||||
|
|
@ -161,6 +162,8 @@ public:
|
|||
virtual void setConstArray(const TConstUnionArray& array) { constArray = array; }
|
||||
virtual void setConstSubtree(TIntermTyped* subtree) { constSubtree = subtree; }
|
||||
virtual TIntermTyped* getConstSubtree() const { return constSubtree; }
|
||||
virtual void setAnonId(int i) { anonId = i; }
|
||||
virtual int getAnonId() const { return anonId; }
|
||||
|
||||
virtual void dump(TInfoSink &infoSink) const;
|
||||
|
||||
|
|
@ -178,6 +181,7 @@ protected:
|
|||
// constant, or neither, but never both.
|
||||
TConstUnionArray constArray; // for compile-time constant value
|
||||
TIntermTyped* constSubtree; // for specialization constant computation
|
||||
int anonId; // the ID used for anonymous blocks: TODO: see if uniqueId could serve a dual purpose
|
||||
};
|
||||
|
||||
//
|
||||
|
|
@ -305,27 +309,16 @@ public:
|
|||
//
|
||||
// returning true means symbol was added to the table with no semantic errors
|
||||
//
|
||||
tInsertResult result;
|
||||
const TString& name = symbol.getName();
|
||||
if (name == "") {
|
||||
symbol.getAsVariable()->setAnonId(anonId++);
|
||||
// An empty name means an anonymous container, exposing its members to the external scope.
|
||||
// Give it a name and insert its members in the symbol table, pointing to the container.
|
||||
char buf[20];
|
||||
snprintf(buf, 20, "%s%d", AnonymousPrefix, anonId);
|
||||
snprintf(buf, 20, "%s%d", AnonymousPrefix, symbol.getAsVariable()->getAnonId());
|
||||
symbol.changeName(NewPoolTString(buf));
|
||||
|
||||
bool isOkay = true;
|
||||
const TTypeList& types = *symbol.getAsVariable()->getType().getStruct();
|
||||
for (unsigned int m = 0; m < types.size(); ++m) {
|
||||
TAnonMember* member = new TAnonMember(&types[m].type->getFieldName(), m, *symbol.getAsVariable(), anonId);
|
||||
result = level.insert(tLevelPair(member->getMangledName(), member));
|
||||
if (! result.second)
|
||||
isOkay = false;
|
||||
}
|
||||
|
||||
++anonId;
|
||||
|
||||
return isOkay;
|
||||
return insertAnonymousMembers(symbol, 0);
|
||||
} else {
|
||||
// Check for redefinition errors:
|
||||
// - STL itself will tell us if there is a direct name collision, with name mangling, at this level
|
||||
|
|
@ -340,14 +333,35 @@ public:
|
|||
level.insert(tLevelPair(insertName, &symbol));
|
||||
|
||||
return true;
|
||||
} else {
|
||||
result = level.insert(tLevelPair(insertName, &symbol));
|
||||
|
||||
return result.second;
|
||||
}
|
||||
} else
|
||||
return level.insert(tLevelPair(insertName, &symbol)).second;
|
||||
}
|
||||
}
|
||||
|
||||
// Add more members to an already inserted aggregate object
|
||||
bool amend(TSymbol& symbol, int firstNewMember)
|
||||
{
|
||||
// See insert() for comments on basic explanation of insert.
|
||||
// This operates similarly, but more simply.
|
||||
// Only supporting amend of anonymous blocks so far.
|
||||
if (IsAnonymous(symbol.getName()))
|
||||
return insertAnonymousMembers(symbol, firstNewMember);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool insertAnonymousMembers(TSymbol& symbol, int firstMember)
|
||||
{
|
||||
const TTypeList& types = *symbol.getAsVariable()->getType().getStruct();
|
||||
for (unsigned int m = firstMember; m < types.size(); ++m) {
|
||||
TAnonMember* member = new TAnonMember(&types[m].type->getFieldName(), m, *symbol.getAsVariable(), symbol.getAsVariable()->getAnonId());
|
||||
if (! level.insert(tLevelPair(member->getMangledName(), member)).second)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
TSymbol* find(const TString& name) const
|
||||
{
|
||||
tLevel::const_iterator it = level.find(name);
|
||||
|
|
@ -357,7 +371,7 @@ public:
|
|||
return (*it).second;
|
||||
}
|
||||
|
||||
void findFunctionNameList(const TString& name, TVector<TFunction*>& list)
|
||||
void findFunctionNameList(const TString& name, TVector<const TFunction*>& list)
|
||||
{
|
||||
size_t parenAt = name.find_first_of('(');
|
||||
TString base(name, 0, parenAt + 1);
|
||||
|
|
@ -546,6 +560,14 @@ public:
|
|||
return table[currentLevel()]->insert(symbol, separateNameSpaces);
|
||||
}
|
||||
|
||||
// Add more members to an already inserted aggregate object
|
||||
bool amend(TSymbol& symbol, int firstNewMember)
|
||||
{
|
||||
// See insert() for comments on basic explanation of insert.
|
||||
// This operates similarly, but more simply.
|
||||
return table[currentLevel()]->amend(symbol, firstNewMember);
|
||||
}
|
||||
|
||||
//
|
||||
// To allocate an internal temporary, which will need to be uniquely
|
||||
// identified by the consumer of the AST, but never need to
|
||||
|
|
@ -624,7 +646,7 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
void findFunctionNameList(const TString& name, TVector<TFunction*>& list, bool& builtIn)
|
||||
void findFunctionNameList(const TString& name, TVector<const TFunction*>& list, bool& builtIn)
|
||||
{
|
||||
// For user levels, return the set found in the first scope with a match
|
||||
builtIn = false;
|
||||
|
|
|
|||
|
|
@ -187,6 +187,14 @@ void TParseVersions::initializeExtensionBehavior()
|
|||
extensionBehavior[E_GL_GOOGLE_cpp_style_line_directive] = EBhDisable;
|
||||
extensionBehavior[E_GL_GOOGLE_include_directive] = EBhDisable;
|
||||
|
||||
#ifdef AMD_EXTENSIONS
|
||||
extensionBehavior[E_GL_AMD_shader_ballot] = EBhDisable;
|
||||
extensionBehavior[E_GL_AMD_shader_trinary_minmax] = EBhDisable;
|
||||
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;
|
||||
#endif
|
||||
|
||||
// AEP
|
||||
extensionBehavior[E_GL_ANDROID_extension_pack_es31a] = EBhDisable;
|
||||
extensionBehavior[E_GL_KHR_blend_equation_advanced] = EBhDisable;
|
||||
|
|
@ -286,6 +294,14 @@ void TParseVersions::getPreamble(std::string& preamble)
|
|||
"#define GL_ARB_sparse_texture_clamp 1\n"
|
||||
// "#define GL_ARB_cull_distance 1\n" // present for 4.5, but need extension control over block members
|
||||
"#define GL_EXT_shader_non_constant_global_initializers 1\n"
|
||||
|
||||
#ifdef AMD_EXTENSIONS
|
||||
"#define GL_AMD_shader_ballot 1\n"
|
||||
"#define GL_AMD_shader_trinary_minmax 1\n"
|
||||
"#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"
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
||||
|
|
@ -649,6 +665,19 @@ void TParseVersions::doubleCheck(const TSourceLoc& loc, const char* op)
|
|||
profileRequires(loc, ECompatibilityProfile, 400, nullptr, op);
|
||||
}
|
||||
|
||||
#ifdef AMD_EXTENSIONS
|
||||
// Call for any operation needing GLSL float16 data-type support.
|
||||
void TParseVersions::float16Check(const TSourceLoc& loc, const char* op, bool 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);
|
||||
profileRequires(loc, ECompatibilityProfile, 450, nullptr, op);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Call for any operation needing GLSL 64-bit integer data-type support.
|
||||
void TParseVersions::int64Check(const TSourceLoc& loc, const char* op, bool builtIn)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -135,6 +135,14 @@ const char* const E_GL_EXT_shader_non_constant_global_initializers = "GL_EXT_sha
|
|||
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";
|
||||
|
||||
#ifdef AMD_EXTENSIONS
|
||||
const char* const E_GL_AMD_shader_ballot = "GL_AMD_shader_ballot";
|
||||
const char* const E_GL_AMD_shader_trinary_minmax = "GL_AMD_shader_trinary_minmax";
|
||||
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";
|
||||
#endif
|
||||
|
||||
// AEP
|
||||
const char* const E_GL_ANDROID_extension_pack_es31a = "GL_ANDROID_extension_pack_es31a";
|
||||
const char* const E_GL_KHR_blend_equation_advanced = "GL_KHR_blend_equation_advanced";
|
||||
|
|
|
|||
|
|
@ -76,6 +76,24 @@
|
|||
#define GL_DOUBLE_MAT4x2 0x8F4D
|
||||
#define GL_DOUBLE_MAT4x3 0x8F4E
|
||||
|
||||
#ifdef AMD_EXTENSIONS
|
||||
// Those constants are borrowed from extension NV_gpu_shader5
|
||||
#define GL_FLOAT16_NV 0x8FF8
|
||||
#define GL_FLOAT16_VEC2_NV 0x8FF9
|
||||
#define GL_FLOAT16_VEC3_NV 0x8FFA
|
||||
#define GL_FLOAT16_VEC4_NV 0x8FFB
|
||||
|
||||
#define GL_FLOAT16_MAT2_AMD 0x91C5
|
||||
#define GL_FLOAT16_MAT3_AMD 0x91C6
|
||||
#define GL_FLOAT16_MAT4_AMD 0x91C7
|
||||
#define GL_FLOAT16_MAT2x3_AMD 0x91C8
|
||||
#define GL_FLOAT16_MAT2x4_AMD 0x91C9
|
||||
#define GL_FLOAT16_MAT3x2_AMD 0x91CA
|
||||
#define GL_FLOAT16_MAT3x4_AMD 0x91CB
|
||||
#define GL_FLOAT16_MAT4x2_AMD 0x91CC
|
||||
#define GL_FLOAT16_MAT4x3_AMD 0x91CD
|
||||
#endif
|
||||
|
||||
#define GL_SAMPLER_1D 0x8B5D
|
||||
#define GL_SAMPLER_2D 0x8B5E
|
||||
#define GL_SAMPLER_3D 0x8B5F
|
||||
|
|
|
|||
|
|
@ -119,14 +119,15 @@ extern int yylex(YYSTYPE*, TParseContext&);
|
|||
%expect 1 // One shift reduce conflict because of if | else
|
||||
|
||||
%token <lex> ATTRIBUTE VARYING
|
||||
%token <lex> CONST BOOL FLOAT DOUBLE INT UINT INT64_T UINT64_T
|
||||
%token <lex> CONST BOOL FLOAT DOUBLE INT UINT INT64_T UINT64_T FLOAT16_T
|
||||
%token <lex> BREAK CONTINUE DO ELSE FOR IF DISCARD RETURN SWITCH CASE DEFAULT SUBROUTINE
|
||||
%token <lex> BVEC2 BVEC3 BVEC4 IVEC2 IVEC3 IVEC4 I64VEC2 I64VEC3 I64VEC4 UVEC2 UVEC3 UVEC4 U64VEC2 U64VEC3 U64VEC4 VEC2 VEC3 VEC4
|
||||
%token <lex> MAT2 MAT3 MAT4 CENTROID IN OUT INOUT
|
||||
%token <lex> UNIFORM PATCH SAMPLE BUFFER SHARED
|
||||
%token <lex> COHERENT VOLATILE RESTRICT READONLY WRITEONLY
|
||||
%token <lex> DVEC2 DVEC3 DVEC4 DMAT2 DMAT3 DMAT4
|
||||
%token <lex> NOPERSPECTIVE FLAT SMOOTH LAYOUT
|
||||
%token <lex> F16VEC2 F16VEC3 F16VEC4 F16MAT2 F16MAT3 F16MAT4
|
||||
%token <lex> NOPERSPECTIVE FLAT SMOOTH LAYOUT __EXPLICITINTERPAMD
|
||||
|
||||
%token <lex> MAT2X2 MAT2X3 MAT2X4
|
||||
%token <lex> MAT3X2 MAT3X3 MAT3X4
|
||||
|
|
@ -134,6 +135,9 @@ extern int yylex(YYSTYPE*, TParseContext&);
|
|||
%token <lex> DMAT2X2 DMAT2X3 DMAT2X4
|
||||
%token <lex> DMAT3X2 DMAT3X3 DMAT3X4
|
||||
%token <lex> DMAT4X2 DMAT4X3 DMAT4X4
|
||||
%token <lex> F16MAT2X2 F16MAT2X3 F16MAT2X4
|
||||
%token <lex> F16MAT3X2 F16MAT3X3 F16MAT3X4
|
||||
%token <lex> F16MAT4X2 F16MAT4X3 F16MAT4X4
|
||||
%token <lex> ATOMIC_UINT
|
||||
|
||||
// combined image/sampler
|
||||
|
|
@ -182,7 +186,7 @@ extern int yylex(YYSTYPE*, TParseContext&);
|
|||
%token <lex> STRUCT VOID WHILE
|
||||
|
||||
%token <lex> IDENTIFIER TYPE_NAME
|
||||
%token <lex> FLOATCONSTANT DOUBLECONSTANT INTCONSTANT UINTCONSTANT INT64CONSTANT UINT64CONSTANT BOOLCONSTANT
|
||||
%token <lex> FLOATCONSTANT DOUBLECONSTANT INTCONSTANT UINTCONSTANT INT64CONSTANT UINT64CONSTANT BOOLCONSTANT FLOAT16CONSTANT
|
||||
%token <lex> LEFT_OP RIGHT_OP
|
||||
%token <lex> INC_OP DEC_OP LE_OP GE_OP EQ_OP NE_OP
|
||||
%token <lex> AND_OP OR_OP XOR_OP MUL_ASSIGN DIV_ASSIGN ADD_ASSIGN
|
||||
|
|
@ -274,6 +278,12 @@ primary_expression
|
|||
parseContext.doubleCheck($1.loc, "double literal");
|
||||
$$ = parseContext.intermediate.addConstantUnion($1.d, EbtDouble, $1.loc, true);
|
||||
}
|
||||
| FLOAT16CONSTANT {
|
||||
#ifdef AMD_EXTENSIONS
|
||||
parseContext.float16Check($1.loc, "half float literal");
|
||||
$$ = parseContext.intermediate.addConstantUnion($1.d, EbtFloat16, $1.loc, true);
|
||||
#endif
|
||||
}
|
||||
| BOOLCONSTANT {
|
||||
$$ = parseContext.intermediate.addConstantUnion($1.b, $1.loc, true);
|
||||
}
|
||||
|
|
@ -691,6 +701,7 @@ expression
|
|||
$$ = $1;
|
||||
}
|
||||
| expression COMMA assignment_expression {
|
||||
parseContext.samplerConstructorLocationCheck($2.loc, ",", $3);
|
||||
$$ = parseContext.intermediate.addComma($1, $3, $2.loc);
|
||||
if ($$ == 0) {
|
||||
parseContext.binaryOpError($2.loc, ",", $1->getCompleteString(), $3->getCompleteString());
|
||||
|
|
@ -1050,6 +1061,15 @@ interpolation_qualifier
|
|||
$$.init($1.loc);
|
||||
$$.qualifier.nopersp = true;
|
||||
}
|
||||
| __EXPLICITINTERPAMD {
|
||||
#ifdef AMD_EXTENSIONS
|
||||
parseContext.globalCheck($1.loc, "__explicitInterpAMD");
|
||||
parseContext.profileRequires($1.loc, ECoreProfile, 450, E_GL_AMD_shader_explicit_vertex_parameter, "explicit interpolation");
|
||||
parseContext.profileRequires($1.loc, ECompatibilityProfile, 450, E_GL_AMD_shader_explicit_vertex_parameter, "explicit interpolation");
|
||||
$$.init($1.loc);
|
||||
$$.qualifier.explicitInterp = true;
|
||||
#endif
|
||||
}
|
||||
;
|
||||
|
||||
layout_qualifier
|
||||
|
|
@ -1115,6 +1135,7 @@ single_type_qualifier
|
|||
$$ = $1;
|
||||
}
|
||||
| precision_qualifier {
|
||||
parseContext.checkPrecisionQualifier($1.loc, $1.qualifier.precision);
|
||||
$$ = $1;
|
||||
}
|
||||
| interpolation_qualifier {
|
||||
|
|
@ -1313,6 +1334,13 @@ type_specifier_nonarray
|
|||
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
|
||||
$$.basicType = EbtDouble;
|
||||
}
|
||||
| FLOAT16_T {
|
||||
#ifdef AMD_EXTENSIONS
|
||||
parseContext.float16Check($1.loc, "half float", parseContext.symbolTable.atBuiltInLevel());
|
||||
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
|
||||
$$.basicType = EbtFloat16;
|
||||
#endif
|
||||
}
|
||||
| INT {
|
||||
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
|
||||
$$.basicType = EbtInt;
|
||||
|
|
@ -1369,6 +1397,30 @@ type_specifier_nonarray
|
|||
$$.basicType = EbtDouble;
|
||||
$$.setVector(4);
|
||||
}
|
||||
| F16VEC2 {
|
||||
#ifdef AMD_EXTENSIONS
|
||||
parseContext.float16Check($1.loc, "half float vector", parseContext.symbolTable.atBuiltInLevel());
|
||||
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
|
||||
$$.basicType = EbtFloat16;
|
||||
$$.setVector(2);
|
||||
#endif
|
||||
}
|
||||
| F16VEC3 {
|
||||
#ifdef AMD_EXTENSIONS
|
||||
parseContext.float16Check($1.loc, "half float vector", parseContext.symbolTable.atBuiltInLevel());
|
||||
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
|
||||
$$.basicType = EbtFloat16;
|
||||
$$.setVector(3);
|
||||
#endif
|
||||
}
|
||||
| F16VEC4 {
|
||||
#ifdef AMD_EXTENSIONS
|
||||
parseContext.float16Check($1.loc, "half float vector", parseContext.symbolTable.atBuiltInLevel());
|
||||
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
|
||||
$$.basicType = EbtFloat16;
|
||||
$$.setVector(4);
|
||||
#endif
|
||||
}
|
||||
| BVEC2 {
|
||||
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
|
||||
$$.basicType = EbtBool;
|
||||
|
|
@ -1585,6 +1637,102 @@ type_specifier_nonarray
|
|||
$$.basicType = EbtDouble;
|
||||
$$.setMatrix(4, 4);
|
||||
}
|
||||
| F16MAT2 {
|
||||
#ifdef AMD_EXTENSIONS
|
||||
parseContext.float16Check($1.loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel());
|
||||
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
|
||||
$$.basicType = EbtFloat16;
|
||||
$$.setMatrix(2, 2);
|
||||
#endif
|
||||
}
|
||||
| F16MAT3 {
|
||||
#ifdef AMD_EXTENSIONS
|
||||
parseContext.float16Check($1.loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel());
|
||||
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
|
||||
$$.basicType = EbtFloat16;
|
||||
$$.setMatrix(3, 3);
|
||||
#endif
|
||||
}
|
||||
| F16MAT4 {
|
||||
#ifdef AMD_EXTENSIONS
|
||||
parseContext.float16Check($1.loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel());
|
||||
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
|
||||
$$.basicType = EbtFloat16;
|
||||
$$.setMatrix(4, 4);
|
||||
#endif
|
||||
}
|
||||
| F16MAT2X2 {
|
||||
#ifdef AMD_EXTENSIONS
|
||||
parseContext.float16Check($1.loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel());
|
||||
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
|
||||
$$.basicType = EbtFloat16;
|
||||
$$.setMatrix(2, 2);
|
||||
#endif
|
||||
}
|
||||
| F16MAT2X3 {
|
||||
#ifdef AMD_EXTENSIONS
|
||||
parseContext.float16Check($1.loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel());
|
||||
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
|
||||
$$.basicType = EbtFloat16;
|
||||
$$.setMatrix(2, 3);
|
||||
#endif
|
||||
}
|
||||
| F16MAT2X4 {
|
||||
#ifdef AMD_EXTENSIONS
|
||||
parseContext.float16Check($1.loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel());
|
||||
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
|
||||
$$.basicType = EbtFloat16;
|
||||
$$.setMatrix(2, 4);
|
||||
#endif
|
||||
}
|
||||
| F16MAT3X2 {
|
||||
#ifdef AMD_EXTENSIONS
|
||||
parseContext.float16Check($1.loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel());
|
||||
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
|
||||
$$.basicType = EbtFloat16;
|
||||
$$.setMatrix(3, 2);
|
||||
#endif
|
||||
}
|
||||
| F16MAT3X3 {
|
||||
#ifdef AMD_EXTENSIONS
|
||||
parseContext.float16Check($1.loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel());
|
||||
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
|
||||
$$.basicType = EbtFloat16;
|
||||
$$.setMatrix(3, 3);
|
||||
#endif
|
||||
}
|
||||
| F16MAT3X4 {
|
||||
#ifdef AMD_EXTENSIONS
|
||||
parseContext.float16Check($1.loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel());
|
||||
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
|
||||
$$.basicType = EbtFloat16;
|
||||
$$.setMatrix(3, 4);
|
||||
#endif
|
||||
}
|
||||
| F16MAT4X2 {
|
||||
#ifdef AMD_EXTENSIONS
|
||||
parseContext.float16Check($1.loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel());
|
||||
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
|
||||
$$.basicType = EbtFloat16;
|
||||
$$.setMatrix(4, 2);
|
||||
#endif
|
||||
}
|
||||
| F16MAT4X3 {
|
||||
#ifdef AMD_EXTENSIONS
|
||||
parseContext.float16Check($1.loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel());
|
||||
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
|
||||
$$.basicType = EbtFloat16;
|
||||
$$.setMatrix(4, 3);
|
||||
#endif
|
||||
}
|
||||
| F16MAT4X4 {
|
||||
#ifdef AMD_EXTENSIONS
|
||||
parseContext.float16Check($1.loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel());
|
||||
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
|
||||
$$.basicType = EbtFloat16;
|
||||
$$.setMatrix(4, 4);
|
||||
#endif
|
||||
}
|
||||
| ATOMIC_UINT {
|
||||
parseContext.vulkanRemoved($1.loc, "atomic counter types");
|
||||
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
|
||||
|
|
@ -2196,20 +2344,17 @@ precision_qualifier
|
|||
: HIGH_PRECISION {
|
||||
parseContext.profileRequires($1.loc, ENoProfile, 130, 0, "highp precision qualifier");
|
||||
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
|
||||
if (parseContext.profile == EEsProfile)
|
||||
$$.qualifier.precision = EpqHigh;
|
||||
parseContext.handlePrecisionQualifier($1.loc, $$.qualifier, EpqHigh);
|
||||
}
|
||||
| MEDIUM_PRECISION {
|
||||
parseContext.profileRequires($1.loc, ENoProfile, 130, 0, "mediump precision qualifier");
|
||||
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
|
||||
if (parseContext.profile == EEsProfile)
|
||||
$$.qualifier.precision = EpqMedium;
|
||||
parseContext.handlePrecisionQualifier($1.loc, $$.qualifier, EpqMedium);
|
||||
}
|
||||
| LOW_PRECISION {
|
||||
parseContext.profileRequires($1.loc, ENoProfile, 130, 0, "lowp precision qualifier");
|
||||
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
|
||||
if (parseContext.profile == EEsProfile)
|
||||
$$.qualifier.precision = EpqLow;
|
||||
parseContext.handlePrecisionQualifier($1.loc, $$.qualifier, EpqLow);
|
||||
}
|
||||
;
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,19 +1,19 @@
|
|||
/* A Bison parser, made by GNU Bison 3.0.4. */
|
||||
/* A Bison parser, made by GNU Bison 2.7. */
|
||||
|
||||
/* Bison interface for Yacc-like parsers in C
|
||||
|
||||
Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
|
||||
|
||||
|
||||
Copyright (C) 1984, 1989-1990, 2000-2012 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_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED
|
||||
# define YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED
|
||||
/* Debug traces. */
|
||||
#ifndef YY_YY_GLSLANG_TAB_CPP_H_INCLUDED
|
||||
# define YY_YY_GLSLANG_TAB_CPP_H_INCLUDED
|
||||
/* Enabling traces. */
|
||||
#ifndef YYDEBUG
|
||||
# define YYDEBUG 1
|
||||
#endif
|
||||
|
|
@ -40,287 +40,306 @@
|
|||
extern int yydebug;
|
||||
#endif
|
||||
|
||||
/* Token type. */
|
||||
/* Tokens. */
|
||||
#ifndef YYTOKENTYPE
|
||||
# define YYTOKENTYPE
|
||||
enum yytokentype
|
||||
{
|
||||
ATTRIBUTE = 258,
|
||||
VARYING = 259,
|
||||
CONST = 260,
|
||||
BOOL = 261,
|
||||
FLOAT = 262,
|
||||
DOUBLE = 263,
|
||||
INT = 264,
|
||||
UINT = 265,
|
||||
INT64_T = 266,
|
||||
UINT64_T = 267,
|
||||
BREAK = 268,
|
||||
CONTINUE = 269,
|
||||
DO = 270,
|
||||
ELSE = 271,
|
||||
FOR = 272,
|
||||
IF = 273,
|
||||
DISCARD = 274,
|
||||
RETURN = 275,
|
||||
SWITCH = 276,
|
||||
CASE = 277,
|
||||
DEFAULT = 278,
|
||||
SUBROUTINE = 279,
|
||||
BVEC2 = 280,
|
||||
BVEC3 = 281,
|
||||
BVEC4 = 282,
|
||||
IVEC2 = 283,
|
||||
IVEC3 = 284,
|
||||
IVEC4 = 285,
|
||||
I64VEC2 = 286,
|
||||
I64VEC3 = 287,
|
||||
I64VEC4 = 288,
|
||||
UVEC2 = 289,
|
||||
UVEC3 = 290,
|
||||
UVEC4 = 291,
|
||||
U64VEC2 = 292,
|
||||
U64VEC3 = 293,
|
||||
U64VEC4 = 294,
|
||||
VEC2 = 295,
|
||||
VEC3 = 296,
|
||||
VEC4 = 297,
|
||||
MAT2 = 298,
|
||||
MAT3 = 299,
|
||||
MAT4 = 300,
|
||||
CENTROID = 301,
|
||||
IN = 302,
|
||||
OUT = 303,
|
||||
INOUT = 304,
|
||||
UNIFORM = 305,
|
||||
PATCH = 306,
|
||||
SAMPLE = 307,
|
||||
BUFFER = 308,
|
||||
SHARED = 309,
|
||||
COHERENT = 310,
|
||||
VOLATILE = 311,
|
||||
RESTRICT = 312,
|
||||
READONLY = 313,
|
||||
WRITEONLY = 314,
|
||||
DVEC2 = 315,
|
||||
DVEC3 = 316,
|
||||
DVEC4 = 317,
|
||||
DMAT2 = 318,
|
||||
DMAT3 = 319,
|
||||
DMAT4 = 320,
|
||||
NOPERSPECTIVE = 321,
|
||||
FLAT = 322,
|
||||
SMOOTH = 323,
|
||||
LAYOUT = 324,
|
||||
MAT2X2 = 325,
|
||||
MAT2X3 = 326,
|
||||
MAT2X4 = 327,
|
||||
MAT3X2 = 328,
|
||||
MAT3X3 = 329,
|
||||
MAT3X4 = 330,
|
||||
MAT4X2 = 331,
|
||||
MAT4X3 = 332,
|
||||
MAT4X4 = 333,
|
||||
DMAT2X2 = 334,
|
||||
DMAT2X3 = 335,
|
||||
DMAT2X4 = 336,
|
||||
DMAT3X2 = 337,
|
||||
DMAT3X3 = 338,
|
||||
DMAT3X4 = 339,
|
||||
DMAT4X2 = 340,
|
||||
DMAT4X3 = 341,
|
||||
DMAT4X4 = 342,
|
||||
ATOMIC_UINT = 343,
|
||||
SAMPLER1D = 344,
|
||||
SAMPLER2D = 345,
|
||||
SAMPLER3D = 346,
|
||||
SAMPLERCUBE = 347,
|
||||
SAMPLER1DSHADOW = 348,
|
||||
SAMPLER2DSHADOW = 349,
|
||||
SAMPLERCUBESHADOW = 350,
|
||||
SAMPLER1DARRAY = 351,
|
||||
SAMPLER2DARRAY = 352,
|
||||
SAMPLER1DARRAYSHADOW = 353,
|
||||
SAMPLER2DARRAYSHADOW = 354,
|
||||
ISAMPLER1D = 355,
|
||||
ISAMPLER2D = 356,
|
||||
ISAMPLER3D = 357,
|
||||
ISAMPLERCUBE = 358,
|
||||
ISAMPLER1DARRAY = 359,
|
||||
ISAMPLER2DARRAY = 360,
|
||||
USAMPLER1D = 361,
|
||||
USAMPLER2D = 362,
|
||||
USAMPLER3D = 363,
|
||||
USAMPLERCUBE = 364,
|
||||
USAMPLER1DARRAY = 365,
|
||||
USAMPLER2DARRAY = 366,
|
||||
SAMPLER2DRECT = 367,
|
||||
SAMPLER2DRECTSHADOW = 368,
|
||||
ISAMPLER2DRECT = 369,
|
||||
USAMPLER2DRECT = 370,
|
||||
SAMPLERBUFFER = 371,
|
||||
ISAMPLERBUFFER = 372,
|
||||
USAMPLERBUFFER = 373,
|
||||
SAMPLERCUBEARRAY = 374,
|
||||
SAMPLERCUBEARRAYSHADOW = 375,
|
||||
ISAMPLERCUBEARRAY = 376,
|
||||
USAMPLERCUBEARRAY = 377,
|
||||
SAMPLER2DMS = 378,
|
||||
ISAMPLER2DMS = 379,
|
||||
USAMPLER2DMS = 380,
|
||||
SAMPLER2DMSARRAY = 381,
|
||||
ISAMPLER2DMSARRAY = 382,
|
||||
USAMPLER2DMSARRAY = 383,
|
||||
SAMPLEREXTERNALOES = 384,
|
||||
SAMPLER = 385,
|
||||
SAMPLERSHADOW = 386,
|
||||
TEXTURE1D = 387,
|
||||
TEXTURE2D = 388,
|
||||
TEXTURE3D = 389,
|
||||
TEXTURECUBE = 390,
|
||||
TEXTURE1DARRAY = 391,
|
||||
TEXTURE2DARRAY = 392,
|
||||
ITEXTURE1D = 393,
|
||||
ITEXTURE2D = 394,
|
||||
ITEXTURE3D = 395,
|
||||
ITEXTURECUBE = 396,
|
||||
ITEXTURE1DARRAY = 397,
|
||||
ITEXTURE2DARRAY = 398,
|
||||
UTEXTURE1D = 399,
|
||||
UTEXTURE2D = 400,
|
||||
UTEXTURE3D = 401,
|
||||
UTEXTURECUBE = 402,
|
||||
UTEXTURE1DARRAY = 403,
|
||||
UTEXTURE2DARRAY = 404,
|
||||
TEXTURE2DRECT = 405,
|
||||
ITEXTURE2DRECT = 406,
|
||||
UTEXTURE2DRECT = 407,
|
||||
TEXTUREBUFFER = 408,
|
||||
ITEXTUREBUFFER = 409,
|
||||
UTEXTUREBUFFER = 410,
|
||||
TEXTURECUBEARRAY = 411,
|
||||
ITEXTURECUBEARRAY = 412,
|
||||
UTEXTURECUBEARRAY = 413,
|
||||
TEXTURE2DMS = 414,
|
||||
ITEXTURE2DMS = 415,
|
||||
UTEXTURE2DMS = 416,
|
||||
TEXTURE2DMSARRAY = 417,
|
||||
ITEXTURE2DMSARRAY = 418,
|
||||
UTEXTURE2DMSARRAY = 419,
|
||||
SUBPASSINPUT = 420,
|
||||
SUBPASSINPUTMS = 421,
|
||||
ISUBPASSINPUT = 422,
|
||||
ISUBPASSINPUTMS = 423,
|
||||
USUBPASSINPUT = 424,
|
||||
USUBPASSINPUTMS = 425,
|
||||
IMAGE1D = 426,
|
||||
IIMAGE1D = 427,
|
||||
UIMAGE1D = 428,
|
||||
IMAGE2D = 429,
|
||||
IIMAGE2D = 430,
|
||||
UIMAGE2D = 431,
|
||||
IMAGE3D = 432,
|
||||
IIMAGE3D = 433,
|
||||
UIMAGE3D = 434,
|
||||
IMAGE2DRECT = 435,
|
||||
IIMAGE2DRECT = 436,
|
||||
UIMAGE2DRECT = 437,
|
||||
IMAGECUBE = 438,
|
||||
IIMAGECUBE = 439,
|
||||
UIMAGECUBE = 440,
|
||||
IMAGEBUFFER = 441,
|
||||
IIMAGEBUFFER = 442,
|
||||
UIMAGEBUFFER = 443,
|
||||
IMAGE1DARRAY = 444,
|
||||
IIMAGE1DARRAY = 445,
|
||||
UIMAGE1DARRAY = 446,
|
||||
IMAGE2DARRAY = 447,
|
||||
IIMAGE2DARRAY = 448,
|
||||
UIMAGE2DARRAY = 449,
|
||||
IMAGECUBEARRAY = 450,
|
||||
IIMAGECUBEARRAY = 451,
|
||||
UIMAGECUBEARRAY = 452,
|
||||
IMAGE2DMS = 453,
|
||||
IIMAGE2DMS = 454,
|
||||
UIMAGE2DMS = 455,
|
||||
IMAGE2DMSARRAY = 456,
|
||||
IIMAGE2DMSARRAY = 457,
|
||||
UIMAGE2DMSARRAY = 458,
|
||||
STRUCT = 459,
|
||||
VOID = 460,
|
||||
WHILE = 461,
|
||||
IDENTIFIER = 462,
|
||||
TYPE_NAME = 463,
|
||||
FLOATCONSTANT = 464,
|
||||
DOUBLECONSTANT = 465,
|
||||
INTCONSTANT = 466,
|
||||
UINTCONSTANT = 467,
|
||||
INT64CONSTANT = 468,
|
||||
UINT64CONSTANT = 469,
|
||||
BOOLCONSTANT = 470,
|
||||
LEFT_OP = 471,
|
||||
RIGHT_OP = 472,
|
||||
INC_OP = 473,
|
||||
DEC_OP = 474,
|
||||
LE_OP = 475,
|
||||
GE_OP = 476,
|
||||
EQ_OP = 477,
|
||||
NE_OP = 478,
|
||||
AND_OP = 479,
|
||||
OR_OP = 480,
|
||||
XOR_OP = 481,
|
||||
MUL_ASSIGN = 482,
|
||||
DIV_ASSIGN = 483,
|
||||
ADD_ASSIGN = 484,
|
||||
MOD_ASSIGN = 485,
|
||||
LEFT_ASSIGN = 486,
|
||||
RIGHT_ASSIGN = 487,
|
||||
AND_ASSIGN = 488,
|
||||
XOR_ASSIGN = 489,
|
||||
OR_ASSIGN = 490,
|
||||
SUB_ASSIGN = 491,
|
||||
LEFT_PAREN = 492,
|
||||
RIGHT_PAREN = 493,
|
||||
LEFT_BRACKET = 494,
|
||||
RIGHT_BRACKET = 495,
|
||||
LEFT_BRACE = 496,
|
||||
RIGHT_BRACE = 497,
|
||||
DOT = 498,
|
||||
COMMA = 499,
|
||||
COLON = 500,
|
||||
EQUAL = 501,
|
||||
SEMICOLON = 502,
|
||||
BANG = 503,
|
||||
DASH = 504,
|
||||
TILDE = 505,
|
||||
PLUS = 506,
|
||||
STAR = 507,
|
||||
SLASH = 508,
|
||||
PERCENT = 509,
|
||||
LEFT_ANGLE = 510,
|
||||
RIGHT_ANGLE = 511,
|
||||
VERTICAL_BAR = 512,
|
||||
CARET = 513,
|
||||
AMPERSAND = 514,
|
||||
QUESTION = 515,
|
||||
INVARIANT = 516,
|
||||
PRECISE = 517,
|
||||
HIGH_PRECISION = 518,
|
||||
MEDIUM_PRECISION = 519,
|
||||
LOW_PRECISION = 520,
|
||||
PRECISION = 521,
|
||||
PACKED = 522,
|
||||
RESOURCE = 523,
|
||||
SUPERP = 524
|
||||
};
|
||||
/* 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
|
||||
};
|
||||
#endif
|
||||
|
||||
/* Value type. */
|
||||
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
|
||||
|
||||
union YYSTYPE
|
||||
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
|
||||
typedef union YYSTYPE
|
||||
{
|
||||
#line 66 "MachineIndependent/glslang.y" /* yacc.c:1909 */
|
||||
/* Line 2058 of yacc.c */
|
||||
#line 66 "glslang.y"
|
||||
|
||||
struct {
|
||||
glslang::TSourceLoc loc;
|
||||
|
|
@ -354,16 +373,28 @@ union YYSTYPE
|
|||
};
|
||||
} interm;
|
||||
|
||||
#line 358 "MachineIndependent/glslang_tab.cpp.h" /* yacc.c:1909 */
|
||||
};
|
||||
|
||||
typedef union YYSTYPE YYSTYPE;
|
||||
/* Line 2058 of yacc.c */
|
||||
#line 379 "glslang_tab.cpp.h"
|
||||
} 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_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED */
|
||||
#endif /* !YY_YY_GLSLANG_TAB_CPP_H_INCLUDED */
|
||||
|
|
|
|||
|
|
@ -38,11 +38,9 @@
|
|||
#include "../Include/InfoSink.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <float.h>
|
||||
#elif defined __ANDROID__ || defined __linux__ || __MINGW32__ || __MINGW64__
|
||||
#include <cmath>
|
||||
#include <cfloat>
|
||||
#else
|
||||
#include <math.h>
|
||||
#include <cmath>
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
|
@ -50,10 +48,8 @@ namespace {
|
|||
bool is_positive_infinity(double x) {
|
||||
#ifdef _MSC_VER
|
||||
return _fpclass(x) == _FPCLASS_PINF;
|
||||
#elif defined __ANDROID__ || defined __linux__ || __MINGW32__ || __MINGW64__
|
||||
return std::isinf(x) && (x >= 0);
|
||||
#else
|
||||
return isinf(x) && (x >= 0);
|
||||
return std::isinf(x) && (x >= 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -308,6 +304,11 @@ bool TOutputTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node)
|
|||
case EOpPackUint2x32: out.debug << "packUint2x32"; break;
|
||||
case EOpUnpackUint2x32: out.debug << "unpackUint2x32"; break;
|
||||
|
||||
#ifdef AMD_EXTENSIONS
|
||||
case EOpPackFloat2x16: out.debug << "packFloat2x16"; break;
|
||||
case EOpUnpackFloat2x16: out.debug << "unpackFloat2x16"; break;
|
||||
#endif
|
||||
|
||||
case EOpLength: out.debug << "length"; break;
|
||||
case EOpNormalize: out.debug << "normalize"; break;
|
||||
case EOpDPdx: out.debug << "dPdx"; break;
|
||||
|
|
@ -355,6 +356,7 @@ bool TOutputTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node)
|
|||
|
||||
case EOpBallot: out.debug << "ballot"; break;
|
||||
case EOpReadFirstInvocation: out.debug << "readFirstInvocation"; break;
|
||||
|
||||
case EOpAnyInvocation: out.debug << "anyInvocation"; break;
|
||||
case EOpAllInvocations: out.debug << "allInvocations"; break;
|
||||
case EOpAllInvocationsEqual: out.debug << "allInvocationsEqual"; break;
|
||||
|
|
@ -365,6 +367,34 @@ bool TOutputTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node)
|
|||
case EOpRcp: out.debug << "rcp"; break;
|
||||
case EOpSaturate: out.debug << "saturate"; break;
|
||||
|
||||
#ifdef AMD_EXTENSIONS
|
||||
case EOpMinInvocations: out.debug << "minInvocations"; break;
|
||||
case EOpMaxInvocations: out.debug << "maxInvocations"; break;
|
||||
case EOpAddInvocations: out.debug << "addInvocations"; break;
|
||||
case EOpMinInvocationsNonUniform: out.debug << "minInvocationsNonUniform"; break;
|
||||
case EOpMaxInvocationsNonUniform: out.debug << "maxInvocationsNonUniform"; break;
|
||||
case EOpAddInvocationsNonUniform: out.debug << "addInvocationsNonUniform"; break;
|
||||
case EOpMbcnt: out.debug << "mbcnt"; break;
|
||||
|
||||
case EOpCubeFaceIndex: out.debug << "cubeFaceIndex"; break;
|
||||
case EOpCubeFaceCoord: out.debug << "cubeFaceCoord"; break;
|
||||
|
||||
case EOpConvBoolToFloat16: out.debug << "Convert bool to float16"; break;
|
||||
case EOpConvIntToFloat16: out.debug << "Convert int to float16"; break;
|
||||
case EOpConvUintToFloat16: out.debug << "Convert uint to float16"; break;
|
||||
case EOpConvFloatToFloat16: out.debug << "Convert float to float16"; break;
|
||||
case EOpConvDoubleToFloat16: out.debug << "Convert double to float16"; break;
|
||||
case EOpConvInt64ToFloat16: out.debug << "Convert int64 to float16"; break;
|
||||
case EOpConvUint64ToFloat16: out.debug << "Convert uint64 to float16"; break;
|
||||
case EOpConvFloat16ToBool: out.debug << "Convert float16 to bool"; break;
|
||||
case EOpConvFloat16ToInt: out.debug << "Convert float16 to int"; break;
|
||||
case EOpConvFloat16ToUint: out.debug << "Convert float16 to uint"; break;
|
||||
case EOpConvFloat16ToFloat: out.debug << "Convert float16 to float"; break;
|
||||
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;
|
||||
#endif
|
||||
|
||||
default: out.debug.message(EPrefixError, "Bad unary op");
|
||||
}
|
||||
|
||||
|
|
@ -437,6 +467,21 @@ 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;
|
||||
#ifdef AMD_EXTENSIONS
|
||||
case EOpConstructFloat16: out.debug << "Construct float16_t"; break;
|
||||
case EOpConstructF16Vec2: out.debug << "Construct f16vec2"; break;
|
||||
case EOpConstructF16Vec3: out.debug << "Construct f16vec3"; break;
|
||||
case EOpConstructF16Vec4: out.debug << "Construct f16vec4"; break;
|
||||
case EOpConstructF16Mat2x2: out.debug << "Construct f16mat2"; break;
|
||||
case EOpConstructF16Mat2x3: out.debug << "Construct f16mat2x3"; break;
|
||||
case EOpConstructF16Mat2x4: out.debug << "Construct f16mat2x4"; break;
|
||||
case EOpConstructF16Mat3x2: out.debug << "Construct f16mat3x2"; break;
|
||||
case EOpConstructF16Mat3x3: out.debug << "Construct f16mat3"; break;
|
||||
case EOpConstructF16Mat3x4: out.debug << "Construct f16mat3x4"; break;
|
||||
case EOpConstructF16Mat4x2: out.debug << "Construct f16mat4x2"; break;
|
||||
case EOpConstructF16Mat4x3: out.debug << "Construct f16mat4x3"; break;
|
||||
case EOpConstructF16Mat4x4: out.debug << "Construct f16mat4"; break;
|
||||
#endif
|
||||
case EOpConstructStruct: out.debug << "Construct structure"; break;
|
||||
case EOpConstructTextureSampler: out.debug << "Construct combined texture-sampler"; break;
|
||||
|
||||
|
|
@ -482,6 +527,18 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node
|
|||
|
||||
case EOpReadInvocation: out.debug << "readInvocation"; break;
|
||||
|
||||
#ifdef AMD_EXTENSIONS
|
||||
case EOpSwizzleInvocations: out.debug << "swizzleInvocations"; break;
|
||||
case EOpSwizzleInvocationsMasked: out.debug << "swizzleInvocationsMasked"; break;
|
||||
case EOpWriteInvocation: out.debug << "writeInvocation"; break;
|
||||
|
||||
case EOpMin3: out.debug << "min3"; break;
|
||||
case EOpMax3: out.debug << "max3"; break;
|
||||
case EOpMid3: out.debug << "mid3"; break;
|
||||
|
||||
case EOpTime: out.debug << "time"; break;
|
||||
#endif
|
||||
|
||||
case EOpAtomicAdd: out.debug << "AtomicAdd"; break;
|
||||
case EOpAtomicMin: out.debug << "AtomicMin"; break;
|
||||
case EOpAtomicMax: out.debug << "AtomicMax"; break;
|
||||
|
|
@ -539,6 +596,9 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node
|
|||
|
||||
case EOpInterpolateAtSample: out.debug << "interpolateAtSample"; break;
|
||||
case EOpInterpolateAtOffset: out.debug << "interpolateAtOffset"; break;
|
||||
#ifdef AMD_EXTENSIONS
|
||||
case EOpInterpolateAtVertex: out.debug << "interpolateAtVertex"; break;
|
||||
#endif
|
||||
|
||||
case EOpSinCos: out.debug << "sincos"; break;
|
||||
case EOpGenMul: out.debug << "mul"; break;
|
||||
|
|
@ -611,6 +671,9 @@ static void OutputConstantUnion(TInfoSink& out, const TIntermTyped* node, const
|
|||
break;
|
||||
case EbtFloat:
|
||||
case EbtDouble:
|
||||
#ifdef AMD_EXTENSIONS
|
||||
case EbtFloat16:
|
||||
#endif
|
||||
{
|
||||
const double value = constUnion[i].getDConst();
|
||||
// Print infinity in a portable way, for test stability.
|
||||
|
|
|
|||
270
glslang/MachineIndependent/iomapper.cpp
Normal file
270
glslang/MachineIndependent/iomapper.cpp
Normal file
|
|
@ -0,0 +1,270 @@
|
|||
//
|
||||
//Copyright (C) 2016 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.
|
||||
//
|
||||
|
||||
#include "../Include/Common.h"
|
||||
#include "../Include/InfoSink.h"
|
||||
#include "iomapper.h"
|
||||
#include "LiveTraverser.h"
|
||||
#include "localintermediate.h"
|
||||
|
||||
#include "gl_types.h"
|
||||
|
||||
#include <unordered_set>
|
||||
#include <unordered_map>
|
||||
|
||||
//
|
||||
// Map IO bindings.
|
||||
//
|
||||
// High-level algorithm for one stage:
|
||||
//
|
||||
// 1. Traverse all code (live+dead) to find the explicitly provided bindings.
|
||||
//
|
||||
// 2. Traverse (just) the live code to determine which non-provided bindings
|
||||
// require auto-numbering. We do not auto-number dead ones.
|
||||
//
|
||||
// 3. Traverse all the code to apply the bindings:
|
||||
// a. explicitly given bindings are offset according to their type
|
||||
// b. implicit live bindings are auto-numbered into the holes, using
|
||||
// any open binding slot.
|
||||
// c. implicit dead bindings are left un-bound.
|
||||
//
|
||||
|
||||
|
||||
namespace glslang {
|
||||
|
||||
// Map of IDs to bindings
|
||||
typedef std::unordered_map<unsigned int, int> TBindingMap;
|
||||
typedef std::unordered_set<int> TUsedBindings;
|
||||
|
||||
|
||||
// This traverses the AST to determine which bindings are used, and which are implicit
|
||||
// (for subsequent auto-numbering)
|
||||
class TBindingTraverser : public TLiveTraverser {
|
||||
public:
|
||||
TBindingTraverser(const TIntermediate& i, TBindingMap& bindingMap, TUsedBindings& usedBindings,
|
||||
bool traverseDeadCode = false) :
|
||||
TLiveTraverser(i, traverseDeadCode, true, true, false),
|
||||
bindingMap(bindingMap),
|
||||
usedBindings(usedBindings)
|
||||
{ }
|
||||
|
||||
protected:
|
||||
virtual void visitSymbol(TIntermSymbol* base) {
|
||||
if (base->getQualifier().storage == EvqUniform)
|
||||
addUniform(*base);
|
||||
}
|
||||
|
||||
// Return the right binding base given the variable type.
|
||||
int getBindingBase(const TType& type) {
|
||||
if (type.getBasicType() == EbtSampler) {
|
||||
const TSampler& sampler = type.getSampler();
|
||||
if (sampler.isPureSampler())
|
||||
return intermediate.getShiftSamplerBinding();
|
||||
if (sampler.isTexture())
|
||||
return intermediate.getShiftTextureBinding();
|
||||
}
|
||||
|
||||
if (type.getQualifier().isUniformOrBuffer())
|
||||
return intermediate.getShiftUboBinding();
|
||||
|
||||
return -1; // not a type with a binding
|
||||
}
|
||||
|
||||
// Mark a given base symbol ID as being bound to 'binding'
|
||||
void markBinding(const TIntermSymbol& base, int binding) {
|
||||
bindingMap[base.getId()] = binding;
|
||||
|
||||
if (binding >= 0) {
|
||||
// const TType& type = base.getType();
|
||||
const unsigned int size = 1; // type.isArray() ? type.getCumulativeArraySize() : 1;
|
||||
|
||||
for (unsigned int offset=0; offset<size; ++offset)
|
||||
usedBindings.insert(binding + offset);
|
||||
}
|
||||
}
|
||||
|
||||
// Mark the bindings that are given explicitly, and set ones that need
|
||||
// implicit bindings to -1 for a subsequent pass. (Can't happen in this
|
||||
// pass because explicit bindings in dead code reserve the location).
|
||||
virtual void addUniform(TIntermSymbol& base)
|
||||
{
|
||||
// Skip ones we've already seen.
|
||||
if (bindingMap.find(base.getId()) != bindingMap.end())
|
||||
return;
|
||||
|
||||
const TType& type = base.getType();
|
||||
const int bindingBase = getBindingBase(type);
|
||||
|
||||
// Return if it's not a type we bind
|
||||
if (bindingBase == -1)
|
||||
return;
|
||||
|
||||
if (type.getQualifier().hasBinding()) {
|
||||
// It has a binding: keep that one.
|
||||
markBinding(base, type.getQualifier().layoutBinding + bindingBase);
|
||||
} else if (!traverseAll) {
|
||||
// Mark it as something we need to dynamically create a binding for,
|
||||
// only if we're walking just the live code. We don't auto-number
|
||||
// in dead code.
|
||||
markBinding(base, -1);
|
||||
}
|
||||
}
|
||||
|
||||
TBindingMap& bindingMap;
|
||||
TUsedBindings& usedBindings;
|
||||
};
|
||||
|
||||
|
||||
// This traverses the AST and applies binding maps it's given.
|
||||
class TIoMappingTraverser : public TBindingTraverser {
|
||||
public:
|
||||
TIoMappingTraverser(TIntermediate& i, TBindingMap& bindingMap, TUsedBindings& usedBindings,
|
||||
TInfoSink& infoSink, bool traverseDeadCode) :
|
||||
TBindingTraverser(i, bindingMap, usedBindings, traverseDeadCode),
|
||||
infoSink(infoSink),
|
||||
assignError(false)
|
||||
{ }
|
||||
|
||||
bool success() const { return !assignError; }
|
||||
|
||||
protected:
|
||||
unsigned checkBindingRange(const TIntermSymbol& base, unsigned binding)
|
||||
{
|
||||
if (binding >= TQualifier::layoutBindingEnd) {
|
||||
TString err = "mapped binding out of range: ";
|
||||
err += base.getName();
|
||||
|
||||
infoSink.info.message(EPrefixInternalError, err.c_str());
|
||||
assignError = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return binding;
|
||||
}
|
||||
|
||||
void addUniform(TIntermSymbol& base) override
|
||||
{
|
||||
// Skip things we don't intend to bind.
|
||||
if (bindingMap.find(base.getId()) == bindingMap.end())
|
||||
return;
|
||||
|
||||
const int existingBinding = bindingMap[base.getId()];
|
||||
|
||||
// Apply existing binding, if we were given one or already made one up.
|
||||
if (existingBinding != -1) {
|
||||
base.getWritableType().getQualifier().layoutBinding = checkBindingRange(base, existingBinding);
|
||||
return;
|
||||
}
|
||||
|
||||
if (intermediate.getAutoMapBindings()) {
|
||||
// Otherwise, find a free spot for it.
|
||||
const int freeBinding = getFreeBinding(base.getType(), getBindingBase(base.getType()));
|
||||
|
||||
markBinding(base, freeBinding);
|
||||
base.getWritableType().getQualifier().layoutBinding = checkBindingRange(base, freeBinding);
|
||||
}
|
||||
}
|
||||
|
||||
// Search for N free consecutive binding slots in [base, base+required).
|
||||
// E.g, if we want to reserve consecutive bindings for flattened arrays.
|
||||
bool hasNFreeSlots(int base, int required) {
|
||||
for (int binding = base; binding < (base + required); ++binding)
|
||||
if (usedBindings.find(binding) != usedBindings.end())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Find a free binding spot
|
||||
int getFreeBinding(const TType&, int nextBinding) {
|
||||
while (!hasNFreeSlots(nextBinding, 1))
|
||||
++nextBinding;
|
||||
|
||||
return nextBinding;
|
||||
}
|
||||
|
||||
private:
|
||||
bool assignError; // true if there was an error assigning the bindings
|
||||
TInfoSink& infoSink;
|
||||
};
|
||||
|
||||
// Map I/O variables to provided offsets, and make bindings for
|
||||
// unbound but live variables.
|
||||
//
|
||||
// Returns false if the input is too malformed to do this.
|
||||
bool TIoMapper::addStage(EShLanguage, TIntermediate& intermediate, TInfoSink& infoSink)
|
||||
{
|
||||
// Trivial return if there is nothing to do.
|
||||
if (intermediate.getShiftSamplerBinding() == 0 &&
|
||||
intermediate.getShiftTextureBinding() == 0 &&
|
||||
intermediate.getShiftUboBinding() == 0 &&
|
||||
intermediate.getAutoMapBindings() == false)
|
||||
return true;
|
||||
|
||||
if (intermediate.getNumEntryPoints() != 1 || intermediate.isRecursive())
|
||||
return false;
|
||||
|
||||
TIntermNode* root = intermediate.getTreeRoot();
|
||||
if (root == nullptr)
|
||||
return false;
|
||||
|
||||
// The lifetime of this data spans several passes.
|
||||
TBindingMap bindingMap;
|
||||
TUsedBindings usedBindings;
|
||||
|
||||
TBindingTraverser it_binding_all(intermediate, bindingMap, usedBindings, true);
|
||||
TBindingTraverser it_binding_live(intermediate, bindingMap, usedBindings, false);
|
||||
TIoMappingTraverser it_iomap(intermediate, bindingMap, usedBindings, infoSink, true);
|
||||
|
||||
// Traverse all (live+dead) code to find explicit bindings, so we can avoid those.
|
||||
root->traverse(&it_binding_all);
|
||||
|
||||
// Traverse just live code to find things that need implicit bindings.
|
||||
it_binding_live.pushFunction(intermediate.getEntryPointMangledName().c_str());
|
||||
|
||||
while (! it_binding_live.functions.empty()) {
|
||||
TIntermNode* function = it_binding_live.functions.back();
|
||||
it_binding_live.functions.pop_back();
|
||||
function->traverse(&it_binding_live);
|
||||
}
|
||||
|
||||
// Bind everything that needs a binding and doesn't have one.
|
||||
root->traverse(&it_iomap);
|
||||
|
||||
return it_iomap.success();
|
||||
}
|
||||
|
||||
} // end namespace glslang
|
||||
63
glslang/MachineIndependent/iomapper.h
Normal file
63
glslang/MachineIndependent/iomapper.h
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
//
|
||||
//Copyright (C) 2016 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.
|
||||
//
|
||||
|
||||
#ifndef _IOMAPPER_INCLUDED
|
||||
#define _IOMAPPER_INCLUDED
|
||||
|
||||
#include "../Public/ShaderLang.h"
|
||||
|
||||
//
|
||||
// A reflection database and its interface, consistent with the OpenGL API reflection queries.
|
||||
//
|
||||
|
||||
class TInfoSink;
|
||||
|
||||
namespace glslang {
|
||||
|
||||
class TIntermediate;
|
||||
|
||||
// I/O mapper
|
||||
class TIoMapper {
|
||||
public:
|
||||
TIoMapper() {}
|
||||
virtual ~TIoMapper() {}
|
||||
|
||||
// grow the reflection stage by stage
|
||||
bool addStage(EShLanguage, TIntermediate&, TInfoSink&);
|
||||
};
|
||||
|
||||
} // end namespace glslang
|
||||
|
||||
#endif // _IOMAPPER_INCLUDED
|
||||
|
|
@ -75,13 +75,13 @@ void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit)
|
|||
if (source != unit.source)
|
||||
error(infoSink, "can't link compilation units from different source languages");
|
||||
|
||||
if (source == EShSourceHlsl && unit.entryPoint.size() > 0) {
|
||||
if (entryPoint.size() > 0)
|
||||
if (source == EShSourceHlsl && unit.getNumEntryPoints() > 0) {
|
||||
if (getNumEntryPoints() > 0)
|
||||
error(infoSink, "can't handle multiple entry points per stage");
|
||||
else
|
||||
entryPoint = unit.entryPoint;
|
||||
entryPointName = unit.entryPointName;
|
||||
}
|
||||
numMains += unit.numMains;
|
||||
numEntryPoints += unit.numEntryPoints;
|
||||
numErrors += unit.numErrors;
|
||||
numPushConstants += unit.numPushConstants;
|
||||
callGraph.insert(callGraph.end(), unit.callGraph.begin(), unit.callGraph.end());
|
||||
|
|
@ -370,8 +370,8 @@ void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& sy
|
|||
//
|
||||
void TIntermediate::finalCheck(TInfoSink& infoSink)
|
||||
{
|
||||
if (source == EShSourceGlsl && numMains < 1)
|
||||
error(infoSink, "Missing entry point: Each stage requires one \"void main()\" entry point");
|
||||
if (source == EShSourceGlsl && numEntryPoints < 1)
|
||||
error(infoSink, "Missing entry point: Each stage requires one entry point");
|
||||
|
||||
if (numPushConstants > 1)
|
||||
error(infoSink, "Only one push_constant block is allowed per stage");
|
||||
|
|
@ -651,7 +651,7 @@ int TIntermediate::addUsedLocation(const TQualifier& qualifier, const TType& typ
|
|||
|
||||
int size;
|
||||
if (qualifier.isUniformOrBuffer()) {
|
||||
if (type.isArray())
|
||||
if (type.isExplicitlySizedArray())
|
||||
size = type.getCumulativeArraySize();
|
||||
else
|
||||
size = 1;
|
||||
|
|
@ -664,30 +664,93 @@ int TIntermediate::addUsedLocation(const TQualifier& qualifier, const TType& typ
|
|||
size = computeTypeLocationSize(type);
|
||||
}
|
||||
|
||||
TRange locationRange(qualifier.layoutLocation, qualifier.layoutLocation + size - 1);
|
||||
TRange componentRange(0, 3);
|
||||
if (qualifier.hasComponent()) {
|
||||
componentRange.start = qualifier.layoutComponent;
|
||||
componentRange.last = componentRange.start + type.getVectorSize() - 1;
|
||||
}
|
||||
TIoRange range(locationRange, componentRange, type.getBasicType(), qualifier.hasIndex() ? qualifier.layoutIndex : 0);
|
||||
// Locations, and components within locations.
|
||||
//
|
||||
// Almost always, dealing with components means a single location is involved.
|
||||
// The exception is a dvec3. From the spec:
|
||||
//
|
||||
// "A dvec3 will consume all four components of the first location and components 0 and 1 of
|
||||
// the second location. This leaves components 2 and 3 available for other component-qualified
|
||||
// declarations."
|
||||
//
|
||||
// That means, without ever mentioning a component, a component range
|
||||
// for a different location gets specified, if it's not a vertex shader input. (!)
|
||||
// (A vertex shader input will show using only one location, even for a dvec3/4.)
|
||||
//
|
||||
// So, for the case of dvec3, we need two independent ioRanges.
|
||||
|
||||
// check for collisions, except for vertex inputs on desktop
|
||||
if (! (profile != EEsProfile && language == EShLangVertex && qualifier.isPipeInput())) {
|
||||
for (size_t r = 0; r < usedIo[set].size(); ++r) {
|
||||
if (range.overlap(usedIo[set][r])) {
|
||||
// there is a collision; pick one
|
||||
return std::max(locationRange.start, usedIo[set][r].location.start);
|
||||
} else if (locationRange.overlap(usedIo[set][r].location) && type.getBasicType() != usedIo[set][r].basicType) {
|
||||
// aliased-type mismatch
|
||||
typeCollision = true;
|
||||
return std::max(locationRange.start, usedIo[set][r].location.start);
|
||||
}
|
||||
int collision = -1; // no collision
|
||||
if (size == 2 && type.getBasicType() == EbtDouble && type.getVectorSize() == 3 &&
|
||||
(qualifier.isPipeInput() || qualifier.isPipeOutput())) {
|
||||
// Dealing with dvec3 in/out split across two locations.
|
||||
// Need two io-ranges.
|
||||
// The case where the dvec3 doesn't start at component 0 was previously caught as overflow.
|
||||
|
||||
// First range:
|
||||
TRange locationRange(qualifier.layoutLocation, qualifier.layoutLocation);
|
||||
TRange componentRange(0, 3);
|
||||
TIoRange range(locationRange, componentRange, type.getBasicType(), 0);
|
||||
|
||||
// check for collisions
|
||||
collision = checkLocationRange(set, range, type, typeCollision);
|
||||
if (collision < 0) {
|
||||
usedIo[set].push_back(range);
|
||||
|
||||
// Second range:
|
||||
TRange locationRange2(qualifier.layoutLocation + 1, qualifier.layoutLocation + 1);
|
||||
TRange componentRange2(0, 1);
|
||||
TIoRange range2(locationRange2, componentRange2, type.getBasicType(), 0);
|
||||
|
||||
// check for collisions
|
||||
collision = checkLocationRange(set, range2, type, typeCollision);
|
||||
if (collision < 0)
|
||||
usedIo[set].push_back(range2);
|
||||
}
|
||||
} else {
|
||||
// Not a dvec3 in/out split across two locations, generic path.
|
||||
// Need a single IO-range block.
|
||||
|
||||
TRange locationRange(qualifier.layoutLocation, qualifier.layoutLocation + size - 1);
|
||||
TRange componentRange(0, 3);
|
||||
if (qualifier.hasComponent() || type.getVectorSize() > 0) {
|
||||
int consumedComponents = type.getVectorSize() * (type.getBasicType() == EbtDouble ? 2 : 1);
|
||||
if (qualifier.hasComponent())
|
||||
componentRange.start = qualifier.layoutComponent;
|
||||
componentRange.last = componentRange.start + consumedComponents - 1;
|
||||
}
|
||||
|
||||
// combine location and component ranges
|
||||
TIoRange range(locationRange, componentRange, type.getBasicType(), qualifier.hasIndex() ? qualifier.layoutIndex : 0);
|
||||
|
||||
// check for collisions, except for vertex inputs on desktop
|
||||
if (! (profile != EEsProfile && language == EShLangVertex && qualifier.isPipeInput()))
|
||||
collision = checkLocationRange(set, range, type, typeCollision);
|
||||
|
||||
if (collision < 0)
|
||||
usedIo[set].push_back(range);
|
||||
}
|
||||
|
||||
return collision;
|
||||
}
|
||||
|
||||
// Compare a new (the passed in) 'range' against the existing set, and see
|
||||
// if there are any collisions.
|
||||
//
|
||||
// Returns < 0 if no collision, >= 0 if collision and the value returned is a colliding value.
|
||||
//
|
||||
int TIntermediate::checkLocationRange(int set, const TIoRange& range, const TType& type, bool& typeCollision)
|
||||
{
|
||||
for (size_t r = 0; r < usedIo[set].size(); ++r) {
|
||||
if (range.overlap(usedIo[set][r])) {
|
||||
// there is a collision; pick one
|
||||
return std::max(range.location.start, usedIo[set][r].location.start);
|
||||
} else if (range.location.overlap(usedIo[set][r].location) && type.getBasicType() != usedIo[set][r].basicType) {
|
||||
// aliased-type mismatch
|
||||
typeCollision = true;
|
||||
return std::max(range.location.start, usedIo[set][r].location.start);
|
||||
}
|
||||
}
|
||||
|
||||
usedIo[set].push_back(range);
|
||||
|
||||
return -1; // no collision
|
||||
}
|
||||
|
||||
|
|
@ -887,6 +950,9 @@ int TIntermediate::getBaseAlignmentScalar(const TType& type, int& size)
|
|||
case EbtInt64:
|
||||
case EbtUint64:
|
||||
case EbtDouble: size = 8; return 8;
|
||||
#ifdef AMD_EXTENSIONS
|
||||
case EbtFloat16: size = 2; return 2;
|
||||
#endif
|
||||
default: size = 4; return 4;
|
||||
}
|
||||
}
|
||||
|
|
@ -940,7 +1006,7 @@ int TIntermediate::getBaseAlignment(const TType& type, int& size, int& stride, b
|
|||
// components each, according to rule (4).
|
||||
//
|
||||
// 6. If the member is an array of S column-major matrices with C columns and
|
||||
// R rows, the matrix is stored identically to a row of S C column vectors
|
||||
// R rows, the matrix is stored identically to a row of S X C column vectors
|
||||
// with R components each, according to rule (4).
|
||||
//
|
||||
// 7. If the member is a row-major matrix with C columns and R rows, the matrix
|
||||
|
|
@ -948,7 +1014,7 @@ int TIntermediate::getBaseAlignment(const TType& type, int& size, int& stride, b
|
|||
// according to rule (4).
|
||||
//
|
||||
// 8. If the member is an array of S row-major matrices with C columns and R
|
||||
// rows, the matrix is stored identically to a row of S R row vectors with C
|
||||
// rows, the matrix is stored identically to a row of S X R row vectors with C
|
||||
// components each, according to rule (4).
|
||||
//
|
||||
// 9. If the member is a structure, the base alignment of the structure is N , where
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
//
|
||||
//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
||||
//Copyright (C) 2016 LunarG, Inc.
|
||||
//All rights reserved.
|
||||
//
|
||||
//Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -47,6 +48,16 @@ class TInfoSink;
|
|||
namespace glslang {
|
||||
|
||||
struct TVectorFields {
|
||||
TVectorFields() { }
|
||||
|
||||
TVectorFields(int c0, int c1, int c2, int c3) : num(4)
|
||||
{
|
||||
offsets[0] = c0;
|
||||
offsets[1] = c1;
|
||||
offsets[2] = c2;
|
||||
offsets[3] = c3;
|
||||
}
|
||||
|
||||
int offsets[4];
|
||||
int num;
|
||||
};
|
||||
|
|
@ -126,11 +137,17 @@ class TIntermediate {
|
|||
public:
|
||||
explicit TIntermediate(EShLanguage l, int v = 0, EProfile p = ENoProfile) :
|
||||
source(EShSourceNone), language(l), profile(p), version(v), treeRoot(0),
|
||||
numMains(0), numErrors(0), numPushConstants(0), recursive(false),
|
||||
numEntryPoints(0), numErrors(0), numPushConstants(0), recursive(false),
|
||||
invocations(TQualifier::layoutNotSet), vertices(TQualifier::layoutNotSet), inputPrimitive(ElgNone), outputPrimitive(ElgNone),
|
||||
pixelCenterInteger(false), originUpperLeft(false),
|
||||
vertexSpacing(EvsNone), vertexOrder(EvoNone), pointMode(false), earlyFragmentTests(false), depthLayout(EldNone), depthReplacing(false), blendEquations(0),
|
||||
multiStream(false), xfbMode(false)
|
||||
multiStream(false), xfbMode(false),
|
||||
shiftSamplerBinding(0),
|
||||
shiftTextureBinding(0),
|
||||
shiftUboBinding(0),
|
||||
autoMapBindings(false),
|
||||
flattenUniformArrays(false),
|
||||
useUnknownFormat(false)
|
||||
{
|
||||
localSize[0] = 1;
|
||||
localSize[1] = 1;
|
||||
|
|
@ -148,8 +165,24 @@ public:
|
|||
|
||||
void setSource(EShSource s) { source = s; }
|
||||
EShSource getSource() const { return source; }
|
||||
void setEntryPoint(const char* ep) { entryPoint = ep; }
|
||||
const std::string& getEntryPoint() const { return entryPoint; }
|
||||
void setEntryPointName(const char* ep) { entryPointName = ep; }
|
||||
void setEntryPointMangledName(const char* ep) { entryPointMangledName = ep; }
|
||||
const std::string& getEntryPointName() const { return entryPointName; }
|
||||
const std::string& getEntryPointMangledName() const { return entryPointMangledName; }
|
||||
|
||||
void setShiftSamplerBinding(unsigned int shift) { shiftSamplerBinding = shift; }
|
||||
unsigned int getShiftSamplerBinding() const { return shiftSamplerBinding; }
|
||||
void setShiftTextureBinding(unsigned int shift) { shiftTextureBinding = shift; }
|
||||
unsigned int getShiftTextureBinding() const { return shiftTextureBinding; }
|
||||
void setShiftUboBinding(unsigned int shift) { shiftUboBinding = shift; }
|
||||
unsigned int getShiftUboBinding() const { return shiftUboBinding; }
|
||||
void setAutoMapBindings(bool map) { autoMapBindings = map; }
|
||||
bool getAutoMapBindings() const { return autoMapBindings; }
|
||||
void setFlattenUniformArrays(bool flatten) { flattenUniformArrays = flatten; }
|
||||
bool getFlattenUniformArrays() const { return flattenUniformArrays; }
|
||||
void setNoStorageFormat(bool b) { useUnknownFormat = b; }
|
||||
bool getNoStorageFormat() const { return useUnknownFormat; }
|
||||
|
||||
void setVersion(int v) { version = v; }
|
||||
int getVersion() const { return version; }
|
||||
void setProfile(EProfile p) { profile = p; }
|
||||
|
|
@ -162,8 +195,8 @@ public:
|
|||
|
||||
void setTreeRoot(TIntermNode* r) { treeRoot = r; }
|
||||
TIntermNode* getTreeRoot() const { return treeRoot; }
|
||||
void addMainCount() { ++numMains; }
|
||||
int getNumMains() const { return numMains; }
|
||||
void incrementEntryPointCount() { ++numEntryPoints; }
|
||||
int getNumEntryPoints() const { return numEntryPoints; }
|
||||
int getNumErrors() const { return numErrors; }
|
||||
void addPushConstantCount() { ++numPushConstants; }
|
||||
bool isRecursive() const { return recursive; }
|
||||
|
|
@ -171,13 +204,16 @@ public:
|
|||
TIntermSymbol* addSymbol(const TVariable&);
|
||||
TIntermSymbol* addSymbol(const TVariable&, const TSourceLoc&);
|
||||
TIntermSymbol* addSymbol(const TType&, const TSourceLoc&);
|
||||
TIntermSymbol* addSymbol(const TIntermSymbol&);
|
||||
TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*) const;
|
||||
TIntermTyped* addShapeConversion(TOperator, 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);
|
||||
TIntermTyped* addUnaryMath(TOperator, TIntermTyped* child, TSourceLoc);
|
||||
TIntermTyped* addBuiltInFunctionCall(const TSourceLoc& line, TOperator, bool unary, TIntermNode*, const TType& returnType);
|
||||
bool canImplicitlyPromote(TBasicType from, TBasicType to) const;
|
||||
bool canImplicitlyPromote(TBasicType from, TBasicType to, TOperator op = EOpNull) const;
|
||||
TOperator mapTypeToConstructorOp(const TType&) const;
|
||||
TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right);
|
||||
TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc&);
|
||||
TIntermAggregate* makeAggregate(TIntermNode* node);
|
||||
|
|
@ -203,6 +239,16 @@ public:
|
|||
TIntermBranch* addBranch(TOperator, TIntermTyped*, const TSourceLoc&);
|
||||
TIntermTyped* addSwizzle(TVectorFields&, const TSourceLoc&);
|
||||
|
||||
// Low level functions to add nodes (no conversions or other higher level transformations)
|
||||
// If a type is provided, the node's type will be set to it.
|
||||
TIntermBinary* addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc) const;
|
||||
TIntermBinary* addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc, const TType&) const;
|
||||
TIntermUnary* addUnaryNode(TOperator op, TIntermTyped* child, TSourceLoc) const;
|
||||
TIntermUnary* addUnaryNode(TOperator op, TIntermTyped* child, TSourceLoc, const TType&) const;
|
||||
|
||||
// Add conversion from node's type to given basic type.
|
||||
TIntermTyped* convertToBasicType(TOperator op, TBasicType basicType, TIntermTyped* node) const;
|
||||
|
||||
// Constant folding (in Constant.cpp)
|
||||
TIntermTyped* fold(TIntermAggregate* aggrNode);
|
||||
TIntermTyped* foldConstructor(TIntermAggregate* aggrNode);
|
||||
|
|
@ -318,6 +364,7 @@ public:
|
|||
bool inIoAccessed(const TString& name) const { return ioAccessed.find(name) != ioAccessed.end(); }
|
||||
|
||||
int addUsedLocation(const TQualifier&, const TType&, bool& typeCollision);
|
||||
int checkLocationRange(int set, const TIoRange& range, const TType&, bool& typeCollision);
|
||||
int addUsedOffsets(int binding, int offset, int numOffsets);
|
||||
bool addUsedConstantId(int id);
|
||||
int computeTypeLocationSize(const TType&) const;
|
||||
|
|
@ -346,17 +393,28 @@ protected:
|
|||
bool userOutputUsed() const;
|
||||
static int getBaseAlignmentScalar(const TType&, int& size);
|
||||
bool isSpecializationOperation(const TIntermOperator&) const;
|
||||
|
||||
bool promote(TIntermOperator*);
|
||||
bool promoteUnary(TIntermUnary&);
|
||||
bool promoteBinary(TIntermBinary&);
|
||||
|
||||
const EShLanguage language; // stage, known at construction time
|
||||
EShSource source; // source language, known a bit later
|
||||
std::string entryPoint;
|
||||
std::string entryPointName;
|
||||
std::string entryPointMangledName;
|
||||
unsigned int shiftSamplerBinding;
|
||||
unsigned int shiftTextureBinding;
|
||||
unsigned int shiftUboBinding;
|
||||
bool autoMapBindings;
|
||||
bool flattenUniformArrays;
|
||||
bool useUnknownFormat;
|
||||
|
||||
EProfile profile;
|
||||
int version;
|
||||
SpvVersion spvVersion;
|
||||
TIntermNode* treeRoot;
|
||||
std::set<std::string> requestedExtensions; // cumulation of all enabled or required extensions; not connected to what subset of the shader used them
|
||||
TBuiltInResource resources;
|
||||
int numMains;
|
||||
int numEntryPoints;
|
||||
int numErrors;
|
||||
int numPushConstants;
|
||||
bool recursive;
|
||||
|
|
|
|||
|
|
@ -76,6 +76,9 @@ public:
|
|||
virtual void updateExtensionBehavior(int line, const char* const extension, const char* behavior);
|
||||
virtual void fullIntegerCheck(const TSourceLoc&, const char* op);
|
||||
virtual void doubleCheck(const TSourceLoc&, const char* op);
|
||||
#ifdef AMD_EXTENSIONS
|
||||
virtual void float16Check(const TSourceLoc&, const char* op, bool builtIn = false);
|
||||
#endif
|
||||
virtual void int64Check(const TSourceLoc&, const char* op, bool builtIn = false);
|
||||
virtual void spvRemoved(const TSourceLoc&, const char* op);
|
||||
virtual void vulkanRemoved(const TSourceLoc&, const char* op);
|
||||
|
|
@ -119,12 +122,12 @@ public:
|
|||
TIntermediate& intermediate; // helper for making and hooking up pieces of the parse tree
|
||||
|
||||
protected:
|
||||
TMap<TString, TExtensionBehavior> extensionBehavior; // for each extension string, what its current behavior is set to
|
||||
EShMessages messages; // errors/warnings/rule-sets
|
||||
int numErrors; // number of compile-time errors encountered
|
||||
TInputScanner* currentScanner;
|
||||
|
||||
private:
|
||||
TMap<TString, TExtensionBehavior> extensionBehavior; // for each extension string, what its current behavior is set to
|
||||
explicit TParseVersions(const TParseVersions&);
|
||||
TParseVersions& operator=(const TParseVersions&);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -81,12 +81,10 @@ NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <sstream>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cctype>
|
||||
|
||||
#include "PpContext.h"
|
||||
#include "PpTokens.h"
|
||||
|
|
@ -192,7 +190,7 @@ int TPpContext::CPPdefine(TPpToken* ppToken)
|
|||
do {
|
||||
int oldToken;
|
||||
TPpToken oldPpToken;
|
||||
TPpToken newPpToken;
|
||||
TPpToken newPpToken;
|
||||
oldToken = ReadToken(symb->mac.body, &oldPpToken);
|
||||
newToken = ReadToken(mac.body, &newPpToken);
|
||||
if (oldToken != newToken || oldPpToken != newPpToken) {
|
||||
|
|
@ -250,7 +248,7 @@ int TPpContext::CPPelse(int matchelse, TPpToken* ppToken)
|
|||
if (token != '#') {
|
||||
while (token != '\n' && token != EndOfInput)
|
||||
token = scanToken(ppToken);
|
||||
|
||||
|
||||
if (token == EndOfInput)
|
||||
return token;
|
||||
|
||||
|
|
@ -495,7 +493,7 @@ int TPpContext::eval(int token, int precedence, bool shortCircuit, int& res, boo
|
|||
if (op < 0 || binop[op].precedence <= precedence)
|
||||
break;
|
||||
int leftSide = res;
|
||||
|
||||
|
||||
// Setup short-circuiting, needed for ES, unless already in a short circuit.
|
||||
// (Once in a short-circuit, can't turn off again, until that whole subexpression is done.
|
||||
if (! shortCircuit) {
|
||||
|
|
@ -707,6 +705,9 @@ int TPpContext::CPPerror(TPpToken* ppToken)
|
|||
while (token != '\n' && token != EndOfInput) {
|
||||
if (token == PpAtomConstInt || token == PpAtomConstUint ||
|
||||
token == PpAtomConstInt64 || token == PpAtomConstUint64 ||
|
||||
#ifdef AMD_EXTENSIONS
|
||||
token == PpAtomConstFloat16 ||
|
||||
#endif
|
||||
token == PpAtomConstFloat || token == PpAtomConstDouble) {
|
||||
message.append(ppToken->name);
|
||||
} else if (token == PpAtomIdentifier || token == PpAtomConstString) {
|
||||
|
|
@ -741,6 +742,9 @@ int TPpContext::CPPpragma(TPpToken* ppToken)
|
|||
case PpAtomConstUint64:
|
||||
case PpAtomConstFloat:
|
||||
case PpAtomConstDouble:
|
||||
#ifdef AMD_EXTENSIONS
|
||||
case PpAtomConstFloat16:
|
||||
#endif
|
||||
tokens.push_back(ppToken->name);
|
||||
break;
|
||||
default:
|
||||
|
|
@ -756,7 +760,7 @@ int TPpContext::CPPpragma(TPpToken* ppToken)
|
|||
else
|
||||
parseContext.handlePragma(loc, tokens);
|
||||
|
||||
return token;
|
||||
return token;
|
||||
}
|
||||
|
||||
// #version: This is just for error checking: the version and profile are decided before preprocessing starts
|
||||
|
|
@ -980,7 +984,7 @@ int TPpContext::tMacroInput::scan(TPpToken* ppToken)
|
|||
|
||||
if (token == EndOfInput)
|
||||
mac->busy = 0;
|
||||
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
|
|
@ -1060,7 +1064,7 @@ int TPpContext::MacroExpand(int atom, TPpToken* ppToken, bool expandUndef, bool
|
|||
if (sym->mac.args) {
|
||||
token = scanToken(ppToken);
|
||||
if (newLineOkay) {
|
||||
while (token == '\n')
|
||||
while (token == '\n')
|
||||
token = scanToken(ppToken);
|
||||
}
|
||||
if (token != '(') {
|
||||
|
|
|
|||
|
|
@ -82,10 +82,9 @@ NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#include "PpContext.h"
|
||||
#include "PpTokens.h"
|
||||
|
|
@ -98,6 +97,32 @@ const struct {
|
|||
int val;
|
||||
const char* str;
|
||||
} tokens[] = {
|
||||
|
||||
{ PpAtomAdd, "+=" },
|
||||
{ PpAtomSub, "-=" },
|
||||
{ PpAtomMul, "*=" },
|
||||
{ PpAtomDiv, "/=" },
|
||||
{ PpAtomMod, "%=" },
|
||||
{ PpAtomRight, ">>" },
|
||||
{ PpAtomLeft, "<<" },
|
||||
{ PpAtomAnd, "&&" },
|
||||
{ PpAtomOr, "||" },
|
||||
{ PpAtomXor, "^^" },
|
||||
|
||||
{ PpAtomRightAssign, ">>=" },
|
||||
{ PpAtomLeftAssign, "<<=" },
|
||||
{ PpAtomAndAssign, "&=" },
|
||||
{ PpAtomOrAssign, "|=" },
|
||||
{ PpAtomXorAssign, "^=" },
|
||||
|
||||
{ PpAtomEQ, "==" },
|
||||
{ PpAtomNE, "!=" },
|
||||
{ PpAtomGE, ">=" },
|
||||
{ PpAtomLE, "<=" },
|
||||
|
||||
{ PpAtomDecrement, "--" },
|
||||
{ PpAtomIncrement, "++" },
|
||||
|
||||
{ PpAtomDefine, "define" },
|
||||
{ PpAtomDefined, "defined" },
|
||||
{ PpAtomUndef, "undef" },
|
||||
|
|
@ -121,8 +146,7 @@ const struct {
|
|||
{ PpAtomFileMacro, "__FILE__" },
|
||||
{ PpAtomVersionMacro, "__VERSION__" },
|
||||
|
||||
{ PpAtomInclude, "include" },
|
||||
|
||||
{ PpAtomInclude, "include" },
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
|
|
|
|||
|
|
@ -76,8 +76,7 @@ TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
|
|||
NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
\****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "PpContext.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -218,7 +218,7 @@ protected:
|
|||
TParseContextBase& parseContext;
|
||||
|
||||
// Get the next token from *stack* of input sources, popping input sources
|
||||
// that are out of tokens, down until an input sources is found that has a token.
|
||||
// that are out of tokens, down until an input source is found that has a token.
|
||||
// Return EndOfInput when there are no more tokens to be found by doing this.
|
||||
int scanToken(TPpToken* ppToken)
|
||||
{
|
||||
|
|
@ -226,7 +226,7 @@ protected:
|
|||
|
||||
while (! inputStack.empty()) {
|
||||
token = inputStack.back()->scan(ppToken);
|
||||
if (token != EndOfInput)
|
||||
if (token != EndOfInput || inputStack.empty())
|
||||
break;
|
||||
popInput();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,10 +76,9 @@ TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
|
|||
NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
\****************************************************************************/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#include "PpContext.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -81,10 +81,8 @@ NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#include "PpContext.h"
|
||||
#include "PpTokens.h"
|
||||
|
|
@ -119,6 +117,10 @@ int TPpContext::lFloatConst(int len, int ch, TPpToken* ppToken)
|
|||
int declen;
|
||||
int str_len;
|
||||
int isDouble = 0;
|
||||
#ifdef AMD_EXTENSIONS
|
||||
int isFloat16 = 0;
|
||||
bool enableFloat16 = parseContext.version >= 450 && parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_half_float);
|
||||
#endif
|
||||
|
||||
declen = 0;
|
||||
|
||||
|
|
@ -202,6 +204,28 @@ int TPpContext::lFloatConst(int len, int ch, TPpToken* ppToken)
|
|||
len = 1,str_len=1;
|
||||
}
|
||||
}
|
||||
#ifdef AMD_EXTENSIONS
|
||||
} else if (enableFloat16 && (ch == 'h' || ch == 'H')) {
|
||||
parseContext.float16Check(ppToken->loc, "half floating-point suffix");
|
||||
if (!HasDecimalOrExponent)
|
||||
parseContext.ppError(ppToken->loc, "float literal needs a decimal point or exponent", "", "");
|
||||
int ch2 = getChar();
|
||||
if (ch2 != 'f' && ch2 != 'F') {
|
||||
ungetChar();
|
||||
ungetChar();
|
||||
}
|
||||
else {
|
||||
if (len < MaxTokenLength) {
|
||||
str[len++] = (char)ch;
|
||||
str[len++] = (char)ch2;
|
||||
isFloat16 = 1;
|
||||
}
|
||||
else {
|
||||
parseContext.ppError(ppToken->loc, "float literal too long", "", "");
|
||||
len = 1, str_len = 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} else if (ch == 'f' || ch == 'F') {
|
||||
parseContext.profileRequires(ppToken->loc, EEsProfile, 300, nullptr, "floating-point suffix");
|
||||
if (! parseContext.relaxedErrors())
|
||||
|
|
@ -224,6 +248,10 @@ int TPpContext::lFloatConst(int len, int ch, TPpToken* ppToken)
|
|||
|
||||
if (isDouble)
|
||||
return PpAtomConstDouble;
|
||||
#ifdef AMD_EXTENSIONS
|
||||
else if (isFloat16)
|
||||
return PpAtomConstFloat16;
|
||||
#endif
|
||||
else
|
||||
return PpAtomConstFloat;
|
||||
}
|
||||
|
|
@ -298,7 +326,7 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
|
|||
ppToken->name[len++] = (char)ch;
|
||||
ch = getch();
|
||||
if (ch == 'x' || ch == 'X') {
|
||||
// must be hexidecimal
|
||||
// must be hexadecimal
|
||||
|
||||
bool isUnsigned = false;
|
||||
bool isInt64 = false;
|
||||
|
|
@ -319,11 +347,11 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
|
|||
} else if (ch >= 'a' && ch <= 'f') {
|
||||
ii = ch - 'a' + 10;
|
||||
} else
|
||||
pp->parseContext.ppError(ppToken->loc, "bad digit in hexidecimal literal", "", "");
|
||||
pp->parseContext.ppError(ppToken->loc, "bad digit in hexadecimal literal", "", "");
|
||||
ival = (ival << 4) | ii;
|
||||
} else {
|
||||
if (! AlreadyComplained) {
|
||||
pp->parseContext.ppError(ppToken->loc, "hexidecimal literal too big", "", "");
|
||||
pp->parseContext.ppError(ppToken->loc, "hexadecimal literal too big", "", "");
|
||||
AlreadyComplained = 1;
|
||||
}
|
||||
ival = 0xffffffffffffffffull;
|
||||
|
|
@ -333,7 +361,7 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
|
|||
(ch >= 'A' && ch <= 'F') ||
|
||||
(ch >= 'a' && ch <= 'f'));
|
||||
} else {
|
||||
pp->parseContext.ppError(ppToken->loc, "bad digit in hexidecimal literal", "", "");
|
||||
pp->parseContext.ppError(ppToken->loc, "bad digit in hexadecimal literal", "", "");
|
||||
}
|
||||
if (ch == 'u' || ch == 'U') {
|
||||
if (len < MaxTokenLength)
|
||||
|
|
@ -405,7 +433,7 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
|
|||
}
|
||||
if (ch == '.' || ch == 'e' || ch == 'f' || ch == 'E' || ch == 'F')
|
||||
return pp->lFloatConst(len, ch, ppToken);
|
||||
|
||||
|
||||
// wasn't a float, so must be octal...
|
||||
if (nonOctal)
|
||||
pp->parseContext.ppError(ppToken->loc, "octal literal digit too large", "", "");
|
||||
|
|
@ -447,7 +475,7 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
|
|||
break;
|
||||
case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
// can't be hexidecimal or octal, is either decimal or floating point
|
||||
// can't be hexadecimal or octal, is either decimal or floating point
|
||||
|
||||
do {
|
||||
if (len < MaxTokenLength)
|
||||
|
|
@ -698,14 +726,14 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
|
|||
}
|
||||
|
||||
//
|
||||
// The main functional entry-point into the preprocessor, which will
|
||||
// The main functional entry point into the preprocessor, which will
|
||||
// scan the source strings to figure out and return the next processing token.
|
||||
//
|
||||
// Return string pointer to next token.
|
||||
// Return 0 when no more tokens.
|
||||
//
|
||||
const char* TPpContext::tokenize(TPpToken* ppToken)
|
||||
{
|
||||
{
|
||||
int token = '\n';
|
||||
|
||||
for(;;) {
|
||||
|
|
@ -746,10 +774,18 @@ const char* TPpContext::tokenize(TPpToken* ppToken)
|
|||
case PpAtomConstInt64:
|
||||
case PpAtomConstUint64:
|
||||
case PpAtomConstDouble:
|
||||
#ifdef AMD_EXTENSIONS
|
||||
case PpAtomConstFloat16:
|
||||
#endif
|
||||
tokenString = ppToken->name;
|
||||
break;
|
||||
case PpAtomConstString:
|
||||
parseContext.ppError(ppToken->loc, "string literals not supported", "\"\"", "");
|
||||
if (parseContext.intermediate.getSource() == EShSourceHlsl) {
|
||||
// HLSL allows string literals.
|
||||
tokenString = ppToken->name;
|
||||
} else {
|
||||
parseContext.ppError(ppToken->loc, "string literals not supported", "\"\"", "");
|
||||
}
|
||||
break;
|
||||
case '\'':
|
||||
parseContext.ppError(ppToken->loc, "character literals not supported", "\'", "");
|
||||
|
|
@ -759,12 +795,8 @@ const char* TPpContext::tokenize(TPpToken* ppToken)
|
|||
break;
|
||||
}
|
||||
|
||||
if (tokenString) {
|
||||
if (tokenString[0] != 0)
|
||||
parseContext.tokensBeforeEOF = 1;
|
||||
|
||||
if (tokenString)
|
||||
return tokenString;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -79,10 +79,9 @@ NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
// symbols.c
|
||||
//
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#include "PpContext.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -85,11 +85,10 @@ NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#define snprintf sprintf_s
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cctype>
|
||||
|
||||
#include "PpContext.h"
|
||||
#include "PpTokens.h"
|
||||
|
|
@ -145,6 +144,9 @@ void TPpContext::RecordToken(TokenStream *pTok, int token, TPpToken* ppToken)
|
|||
case PpAtomConstUint64:
|
||||
case PpAtomConstFloat:
|
||||
case PpAtomConstDouble:
|
||||
#ifdef AMD_EXTENSIONS
|
||||
case PpAtomConstFloat16:
|
||||
#endif
|
||||
str = ppToken->name;
|
||||
while (*str) {
|
||||
lAddByte(pTok, (unsigned char) *str);
|
||||
|
|
@ -179,20 +181,26 @@ int TPpContext::ReadToken(TokenStream *pTok, TPpToken *ppToken)
|
|||
if (ltoken > 127)
|
||||
ltoken += 128;
|
||||
switch (ltoken) {
|
||||
case '#':
|
||||
if (lReadByte(pTok) == '#') {
|
||||
parseContext.requireProfile(ppToken->loc, ~EEsProfile, "token pasting (##)");
|
||||
parseContext.profileRequires(ppToken->loc, ~EEsProfile, 130, 0, "token pasting (##)");
|
||||
parseContext.error(ppToken->loc, "token pasting not implemented (internal error)", "##", "");
|
||||
//return PpAtomPaste;
|
||||
return ReadToken(pTok, ppToken);
|
||||
} else
|
||||
lUnreadByte(pTok);
|
||||
case '#':
|
||||
// Check for ##, unless the current # is the last character
|
||||
if (pTok->current < pTok->data.size()) {
|
||||
if (lReadByte(pTok) == '#') {
|
||||
parseContext.requireProfile(ppToken->loc, ~EEsProfile, "token pasting (##)");
|
||||
parseContext.profileRequires(ppToken->loc, ~EEsProfile, 130, 0, "token pasting (##)");
|
||||
parseContext.error(ppToken->loc, "token pasting not implemented (internal error)", "##", "");
|
||||
//return PpAtomPaste;
|
||||
return ReadToken(pTok, ppToken);
|
||||
} else
|
||||
lUnreadByte(pTok);
|
||||
}
|
||||
break;
|
||||
case PpAtomConstString:
|
||||
case PpAtomIdentifier:
|
||||
case PpAtomConstFloat:
|
||||
case PpAtomConstDouble:
|
||||
#ifdef AMD_EXTENSIONS
|
||||
case PpAtomConstFloat16:
|
||||
#endif
|
||||
case PpAtomConstInt:
|
||||
case PpAtomConstUint:
|
||||
case PpAtomConstInt64:
|
||||
|
|
@ -219,20 +227,30 @@ int TPpContext::ReadToken(TokenStream *pTok, TPpToken *ppToken)
|
|||
break;
|
||||
case PpAtomConstFloat:
|
||||
case PpAtomConstDouble:
|
||||
#ifdef AMD_EXTENSIONS
|
||||
case PpAtomConstFloat16:
|
||||
#endif
|
||||
ppToken->dval = atof(ppToken->name);
|
||||
break;
|
||||
case PpAtomConstInt:
|
||||
case PpAtomConstUint:
|
||||
if (len > 0 && tokenText[0] == '0') {
|
||||
if (len > 1 && (tokenText[1] == 'x' || tokenText[1] == 'X'))
|
||||
ppToken->ival = strtol(ppToken->name, 0, 16);
|
||||
ppToken->ival = (int)strtol(ppToken->name, 0, 16);
|
||||
else
|
||||
ppToken->ival = strtol(ppToken->name, 0, 8);
|
||||
ppToken->ival = (int)strtol(ppToken->name, 0, 8);
|
||||
} else
|
||||
ppToken->ival = atoi(ppToken->name);
|
||||
break;
|
||||
case PpAtomConstUint:
|
||||
if (len > 0 && tokenText[0] == '0') {
|
||||
if (len > 1 && (tokenText[1] == 'x' || tokenText[1] == 'X'))
|
||||
ppToken->ival = (int)strtoul(ppToken->name, 0, 16);
|
||||
else
|
||||
ppToken->ival = (int)strtoul(ppToken->name, 0, 8);
|
||||
} else
|
||||
ppToken->ival = (int)strtoul(ppToken->name, 0, 10);
|
||||
break;
|
||||
case PpAtomConstInt64:
|
||||
case PpAtomConstUint64:
|
||||
if (len > 0 && tokenText[0] == '0') {
|
||||
if (len > 1 && (tokenText[1] == 'x' || tokenText[1] == 'X'))
|
||||
ppToken->i64val = strtoll(ppToken->name, nullptr, 16);
|
||||
|
|
@ -241,6 +259,15 @@ int TPpContext::ReadToken(TokenStream *pTok, TPpToken *ppToken)
|
|||
} else
|
||||
ppToken->i64val = atoll(ppToken->name);
|
||||
break;
|
||||
case PpAtomConstUint64:
|
||||
if (len > 0 && tokenText[0] == '0') {
|
||||
if (len > 1 && (tokenText[1] == 'x' || tokenText[1] == 'X'))
|
||||
ppToken->i64val = (long long)strtoull(ppToken->name, nullptr, 16);
|
||||
else
|
||||
ppToken->i64val = (long long)strtoull(ppToken->name, nullptr, 8);
|
||||
} else
|
||||
ppToken->i64val = (long long)strtoull(ppToken->name, 0, 10);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -123,9 +123,12 @@ enum EFixedAtoms {
|
|||
PpAtomConstUint64,
|
||||
PpAtomConstFloat,
|
||||
PpAtomConstDouble,
|
||||
#ifdef AMD_EXTENSIONS
|
||||
PpAtomConstFloat16,
|
||||
#endif
|
||||
PpAtomConstString,
|
||||
|
||||
// Indentifiers
|
||||
// Identifiers
|
||||
PpAtomIdentifier,
|
||||
|
||||
// preprocessor "keywords"
|
||||
|
|
|
|||
|
|
@ -670,7 +670,7 @@ protected:
|
|||
// Gets the struct dereference index that leads to 'precise' object.
|
||||
ObjectAccessChain precise_accesschain_index_str =
|
||||
getFrontElement(remained_accesschain_);
|
||||
unsigned precise_accesschain_index = strtoul(precise_accesschain_index_str.c_str(), nullptr, 10);
|
||||
unsigned precise_accesschain_index = (unsigned)strtoul(precise_accesschain_index_str.c_str(), nullptr, 10);
|
||||
// Gets the node pointed by the access chain index extracted before.
|
||||
glslang::TIntermTyped* potential_precise_node =
|
||||
node->getSequence()[precise_accesschain_index]->getAsTyped();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
//Copyright (C) 2013 LunarG, Inc.
|
||||
//Copyright (C) 2013-2016 LunarG, Inc.
|
||||
//
|
||||
//All rights reserved.
|
||||
//
|
||||
|
|
@ -35,6 +35,7 @@
|
|||
|
||||
#include "../Include/Common.h"
|
||||
#include "reflection.h"
|
||||
#include "LiveTraverser.h"
|
||||
#include "localintermediate.h"
|
||||
|
||||
#include "gl_types.h"
|
||||
|
|
@ -48,7 +49,7 @@
|
|||
//
|
||||
// High-level algorithm for one stage:
|
||||
//
|
||||
// 1. Put main() on list of live functions.
|
||||
// 1. Put the entry point on the list of live functions.
|
||||
//
|
||||
// 2. Traverse any live function, while skipping if-tests with a compile-time constant
|
||||
// condition of false, and while adding any encountered function calls to the live
|
||||
|
|
@ -59,40 +60,29 @@
|
|||
// 3. Add any encountered uniform variables and blocks to the reflection database.
|
||||
//
|
||||
// Can be attempted with a failed link, but will return false if recursion had been detected, or
|
||||
// there wasn't exactly one main.
|
||||
// there wasn't exactly one entry point.
|
||||
//
|
||||
|
||||
|
||||
namespace glslang {
|
||||
|
||||
//
|
||||
// The traverser: mostly pass through, except
|
||||
// - processing function-call nodes to push live functions onto the stack of functions to process
|
||||
// - processing binary nodes to see if they are dereferences of an aggregates to track
|
||||
// - processing symbol nodes to see if they are non-aggregate objects to track
|
||||
// - processing selection nodes to trim semantically dead code
|
||||
//
|
||||
// This ignores semantically dead code by using TLiveTraverser.
|
||||
//
|
||||
// This is in the glslang namespace directly so it can be a friend of TReflection.
|
||||
//
|
||||
|
||||
class TLiveTraverser : public TIntermTraverser {
|
||||
class TReflectionTraverser : public TLiveTraverser {
|
||||
public:
|
||||
TLiveTraverser(const TIntermediate& i, TReflection& r) : intermediate(i), reflection(r) { }
|
||||
TReflectionTraverser(const TIntermediate& i, TReflection& r) :
|
||||
TLiveTraverser(i), reflection(r) { }
|
||||
|
||||
virtual bool visitAggregate(TVisit, TIntermAggregate* node);
|
||||
virtual bool visitBinary(TVisit, TIntermBinary* node);
|
||||
virtual void visitSymbol(TIntermSymbol* base);
|
||||
virtual bool visitSelection(TVisit, TIntermSelection* node);
|
||||
|
||||
// Track live funtions as well as uniforms, so that we don't visit dead functions
|
||||
// and only visit each function once.
|
||||
void addFunctionCall(TIntermAggregate* call)
|
||||
{
|
||||
// just use the map to ensure we process each function at most once
|
||||
if (reflection.nameToIndex.find(call->getName()) == reflection.nameToIndex.end()) {
|
||||
reflection.nameToIndex[call->getName()] = -1;
|
||||
pushFunction(call->getName());
|
||||
}
|
||||
}
|
||||
|
||||
// Add a simple reference to a uniform variable to the uniform database, no dereference involved.
|
||||
// However, no dereference doesn't mean simple... it could be a complex aggregate.
|
||||
|
|
@ -119,7 +109,7 @@ public:
|
|||
TReflection::TNameToIndex::const_iterator it = reflection.nameToIndex.find(name);
|
||||
if (it == reflection.nameToIndex.end()) {
|
||||
reflection.nameToIndex[name] = (int)reflection.indexToAttribute.size();
|
||||
reflection.indexToAttribute.push_back(TObjectReflection(name, 0, mapToGlType(type), 0, 0));
|
||||
reflection.indexToAttribute.push_back(TObjectReflection(name, type, 0, mapToGlType(type), 0, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -255,7 +245,8 @@ public:
|
|||
TReflection::TNameToIndex::const_iterator it = reflection.nameToIndex.find(name);
|
||||
if (it == reflection.nameToIndex.end()) {
|
||||
reflection.nameToIndex[name] = (int)reflection.indexToUniform.size();
|
||||
reflection.indexToUniform.push_back(TObjectReflection(name, offset, mapToGlType(*terminalType), arraySize, blockIndex));
|
||||
reflection.indexToUniform.push_back(TObjectReflection(name, *terminalType, offset, mapToGlType(*terminalType),
|
||||
arraySize, blockIndex));
|
||||
} else if (arraySize > 1) {
|
||||
int& reflectedArraySize = reflection.indexToUniform[it->second].size;
|
||||
reflectedArraySize = std::max(arraySize, reflectedArraySize);
|
||||
|
|
@ -306,12 +297,18 @@ public:
|
|||
if (block) {
|
||||
offset = 0;
|
||||
anonymous = IsAnonymous(base->getName());
|
||||
|
||||
const TString& blockName = base->getType().getTypeName();
|
||||
|
||||
if (base->getType().isArray()) {
|
||||
TType derefType(base->getType(), 0);
|
||||
|
||||
assert(! anonymous);
|
||||
for (int e = 0; e < base->getType().getCumulativeArraySize(); ++e)
|
||||
blockIndex = addBlockName(base->getType().getTypeName() + "[" + String(e) + "]", getBlockSize(base->getType()));
|
||||
blockIndex = addBlockName(blockName + "[" + String(e) + "]", derefType,
|
||||
getBlockSize(base->getType()));
|
||||
} else
|
||||
blockIndex = addBlockName(base->getType().getTypeName(), getBlockSize(base->getType()));
|
||||
blockIndex = addBlockName(blockName, base->getType(), getBlockSize(base->getType()));
|
||||
}
|
||||
|
||||
// Process the dereference chain, backward, accumulating the pieces for later forward traversal.
|
||||
|
|
@ -344,35 +341,20 @@ public:
|
|||
blowUpActiveAggregate(base->getType(), baseName, derefs, derefs.begin(), offset, blockIndex, arraySize);
|
||||
}
|
||||
|
||||
int addBlockName(const TString& name, int size)
|
||||
int addBlockName(const TString& name, const TType& type, int size)
|
||||
{
|
||||
int blockIndex;
|
||||
TReflection::TNameToIndex::const_iterator it = reflection.nameToIndex.find(name);
|
||||
if (reflection.nameToIndex.find(name) == reflection.nameToIndex.end()) {
|
||||
blockIndex = (int)reflection.indexToUniformBlock.size();
|
||||
reflection.nameToIndex[name] = blockIndex;
|
||||
reflection.indexToUniformBlock.push_back(TObjectReflection(name, -1, -1, size, -1));
|
||||
reflection.indexToUniformBlock.push_back(TObjectReflection(name, type, -1, -1, size, -1));
|
||||
} else
|
||||
blockIndex = it->second;
|
||||
|
||||
return blockIndex;
|
||||
}
|
||||
|
||||
//
|
||||
// Given a function name, find its subroot in the tree, and push it onto the stack of
|
||||
// functions left to process.
|
||||
//
|
||||
void pushFunction(const TString& name)
|
||||
{
|
||||
TIntermSequence& globals = intermediate.getTreeRoot()->getAsAggregate()->getSequence();
|
||||
for (unsigned int f = 0; f < globals.size(); ++f) {
|
||||
TIntermAggregate* candidate = globals[f]->getAsAggregate();
|
||||
if (candidate && candidate->getOp() == EOpFunction && candidate->getName() == name) {
|
||||
functions.push_back(candidate);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Are we at a level in a dereference chain at which individual active uniform queries are made?
|
||||
bool isReflectionGranularity(const TType& type)
|
||||
|
|
@ -554,6 +536,9 @@ public:
|
|||
switch (type.getBasicType()) {
|
||||
case EbtFloat: return GL_FLOAT_VEC2 + offset;
|
||||
case EbtDouble: return GL_DOUBLE_VEC2 + offset;
|
||||
#ifdef AMD_EXTENSIONS
|
||||
case EbtFloat16: return GL_FLOAT16_VEC2_NV + offset;
|
||||
#endif
|
||||
case EbtInt: return GL_INT_VEC2 + offset;
|
||||
case EbtUint: return GL_UNSIGNED_INT_VEC2 + offset;
|
||||
case EbtInt64: return GL_INT64_ARB + offset;
|
||||
|
|
@ -613,6 +598,32 @@ public:
|
|||
default: return 0;
|
||||
}
|
||||
}
|
||||
#ifdef AMD_EXTENSIONS
|
||||
case EbtFloat16:
|
||||
switch (type.getMatrixCols()) {
|
||||
case 2:
|
||||
switch (type.getMatrixRows()) {
|
||||
case 2: return GL_FLOAT16_MAT2_AMD;
|
||||
case 3: return GL_FLOAT16_MAT2x3_AMD;
|
||||
case 4: return GL_FLOAT16_MAT2x4_AMD;
|
||||
default: return 0;
|
||||
}
|
||||
case 3:
|
||||
switch (type.getMatrixRows()) {
|
||||
case 2: return GL_FLOAT16_MAT3x2_AMD;
|
||||
case 3: return GL_FLOAT16_MAT3_AMD;
|
||||
case 4: return GL_FLOAT16_MAT3x4_AMD;
|
||||
default: return 0;
|
||||
}
|
||||
case 4:
|
||||
switch (type.getMatrixRows()) {
|
||||
case 2: return GL_FLOAT16_MAT4x2_AMD;
|
||||
case 3: return GL_FLOAT16_MAT4x3_AMD;
|
||||
case 4: return GL_FLOAT16_MAT4_AMD;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -621,6 +632,9 @@ public:
|
|||
switch (type.getBasicType()) {
|
||||
case EbtFloat: return GL_FLOAT;
|
||||
case EbtDouble: return GL_DOUBLE;
|
||||
#ifdef AMD_EXTENSIONS
|
||||
case EbtFloat16: return GL_FLOAT16_NV;
|
||||
#endif
|
||||
case EbtInt: return GL_INT;
|
||||
case EbtUint: return GL_UNSIGNED_INT;
|
||||
case EbtInt64: return GL_INT64_ARB;
|
||||
|
|
@ -639,33 +653,21 @@ public:
|
|||
return type.isArray() ? type.getOuterArraySize() : 1;
|
||||
}
|
||||
|
||||
typedef std::list<TIntermAggregate*> TFunctionStack;
|
||||
TFunctionStack functions;
|
||||
const TIntermediate& intermediate;
|
||||
TReflection& reflection;
|
||||
std::set<const TIntermNode*> processedDerefs;
|
||||
|
||||
protected:
|
||||
TLiveTraverser(TLiveTraverser&);
|
||||
TLiveTraverser& operator=(TLiveTraverser&);
|
||||
TReflectionTraverser(TReflectionTraverser&);
|
||||
TReflectionTraverser& operator=(TReflectionTraverser&);
|
||||
};
|
||||
|
||||
//
|
||||
// Implement the traversal functions of interest.
|
||||
//
|
||||
|
||||
// To catch which function calls are not dead, and hence which functions must be visited.
|
||||
bool TLiveTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node)
|
||||
{
|
||||
if (node->getOp() == EOpFunctionCall)
|
||||
addFunctionCall(node);
|
||||
|
||||
return true; // traverse this subtree
|
||||
}
|
||||
|
||||
// To catch dereferenced aggregates that must be reflected.
|
||||
// This catches them at the highest level possible in the tree.
|
||||
bool TLiveTraverser::visitBinary(TVisit /* visit */, TIntermBinary* node)
|
||||
bool TReflectionTraverser::visitBinary(TVisit /* visit */, TIntermBinary* node)
|
||||
{
|
||||
switch (node->getOp()) {
|
||||
case EOpIndexDirect:
|
||||
|
|
@ -683,7 +685,7 @@ bool TLiveTraverser::visitBinary(TVisit /* visit */, TIntermBinary* node)
|
|||
}
|
||||
|
||||
// To reflect non-dereferenced objects.
|
||||
void TLiveTraverser::visitSymbol(TIntermSymbol* base)
|
||||
void TReflectionTraverser::visitSymbol(TIntermSymbol* base)
|
||||
{
|
||||
if (base->getQualifier().storage == EvqUniform)
|
||||
addUniform(*base);
|
||||
|
|
@ -692,21 +694,6 @@ void TLiveTraverser::visitSymbol(TIntermSymbol* base)
|
|||
addAttribute(*base);
|
||||
}
|
||||
|
||||
// To prune semantically dead paths.
|
||||
bool TLiveTraverser::visitSelection(TVisit /* visit */, TIntermSelection* node)
|
||||
{
|
||||
TIntermConstantUnion* constant = node->getCondition()->getAsConstantUnion();
|
||||
if (constant) {
|
||||
// cull the path that is dead
|
||||
if (constant->getConstArray()[0].getBConst() == true && node->getTrueBlock())
|
||||
node->getTrueBlock()->traverse(this);
|
||||
if (constant->getConstArray()[0].getBConst() == false && node->getFalseBlock())
|
||||
node->getFalseBlock()->traverse(this);
|
||||
|
||||
return false; // don't traverse any more, we did it all above
|
||||
} else
|
||||
return true; // traverse the whole subtree
|
||||
}
|
||||
|
||||
//
|
||||
// Implement TReflection methods.
|
||||
|
|
@ -717,13 +704,13 @@ bool TLiveTraverser::visitSelection(TVisit /* visit */, TIntermSelection* node)
|
|||
// Returns false if the input is too malformed to do this.
|
||||
bool TReflection::addStage(EShLanguage, const TIntermediate& intermediate)
|
||||
{
|
||||
if (intermediate.getNumMains() != 1 || intermediate.isRecursive())
|
||||
if (intermediate.getNumEntryPoints() != 1 || intermediate.isRecursive())
|
||||
return false;
|
||||
|
||||
TLiveTraverser it(intermediate, *this);
|
||||
TReflectionTraverser it(intermediate, *this);
|
||||
|
||||
// put main() on functions to process
|
||||
it.pushFunction("main(");
|
||||
// put the entry point on the list of functions to process
|
||||
it.pushFunction(intermediate.getEntryPointMangledName().c_str());
|
||||
|
||||
// process all the functions
|
||||
while (! it.functions.empty()) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
//Copyright (C) 2013 LunarG, Inc.
|
||||
//Copyright (C) 2013-2016 LunarG, Inc.
|
||||
//
|
||||
//All rights reserved.
|
||||
//
|
||||
|
|
@ -37,6 +37,7 @@
|
|||
#define _REFLECTION_INCLUDED
|
||||
|
||||
#include "../Public/ShaderLang.h"
|
||||
#include "../Include/Types.h"
|
||||
|
||||
#include <list>
|
||||
#include <set>
|
||||
|
|
@ -49,25 +50,46 @@ namespace glslang {
|
|||
|
||||
class TIntermediate;
|
||||
class TIntermAggregate;
|
||||
class TLiveTraverser;
|
||||
class TReflectionTraverser;
|
||||
|
||||
// Data needed for just a single object at the granularity exchanged by the reflection API
|
||||
class TObjectReflection {
|
||||
public:
|
||||
TObjectReflection(const TString& pName, int pOffset, int pGLDefineType, int pSize, int pIndex) :
|
||||
name(pName), offset(pOffset), glDefineType(pGLDefineType), size(pSize), index(pIndex) { }
|
||||
void dump() const { printf("%s: offset %d, type %x, size %d, index %d\n", name.c_str(), offset, glDefineType, size, index); }
|
||||
TObjectReflection(const TString& pName, const TType& pType, int pOffset, int pGLDefineType, int pSize, int pIndex) :
|
||||
name(pName), type(pType.clone()),
|
||||
offset(pOffset), glDefineType(pGLDefineType), size(pSize), index(pIndex) { }
|
||||
|
||||
void dump() const {
|
||||
printf("%s: offset %d, type %x, size %d, index %d, binding %d\n",
|
||||
name.c_str(), offset, glDefineType, size, index, getBinding() );
|
||||
}
|
||||
|
||||
const TType* const getType() const { return type; }
|
||||
|
||||
TString name;
|
||||
int offset;
|
||||
int glDefineType;
|
||||
int size; // data size in bytes for a block, array size for a (non-block) object that's an array
|
||||
int index;
|
||||
|
||||
static TObjectReflection badReflection() { return TObjectReflection(); }
|
||||
|
||||
protected:
|
||||
int getBinding() const {
|
||||
if (type == nullptr || type->getQualifier().layoutBinding == TQualifier::layoutBindingEnd)
|
||||
return -1;
|
||||
return type->getQualifier().layoutBinding;
|
||||
}
|
||||
|
||||
TObjectReflection() : type(nullptr), offset(-1), glDefineType(-1), size(-1), index(-1) { }
|
||||
|
||||
const TType* type;
|
||||
};
|
||||
|
||||
// The full reflection database
|
||||
class TReflection {
|
||||
public:
|
||||
TReflection() : badReflection("__bad__", -1, -1, -1, -1) {}
|
||||
TReflection() : badReflection(TObjectReflection::badReflection()) { }
|
||||
virtual ~TReflection() {}
|
||||
|
||||
// grow the reflection stage by stage
|
||||
|
|
@ -116,7 +138,7 @@ public:
|
|||
void dump();
|
||||
|
||||
protected:
|
||||
friend class glslang::TLiveTraverser;
|
||||
friend class glslang::TReflectionTraverser;
|
||||
|
||||
// Need a TString hash: typedef std::unordered_map<TString, int> TNameToIndex;
|
||||
typedef std::map<TString, int> TNameToIndex;
|
||||
|
|
|
|||
|
|
@ -165,21 +165,39 @@ bool OS_FreeTLSIndex(OS_TLSIndex nIndex)
|
|||
return false;
|
||||
}
|
||||
|
||||
// TODO: non-windows: if we need these on linux, flesh them out
|
||||
void InitGlobalLock() { }
|
||||
void GetGlobalLock() { }
|
||||
void ReleaseGlobalLock() { }
|
||||
namespace {
|
||||
pthread_mutex_t gMutex;
|
||||
}
|
||||
|
||||
void* OS_CreateThread(TThreadEntrypoint entry)
|
||||
void InitGlobalLock()
|
||||
{
|
||||
pthread_mutexattr_t mutexattr;
|
||||
pthread_mutexattr_init(&mutexattr);
|
||||
pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE);
|
||||
pthread_mutex_init(&gMutex, &mutexattr);
|
||||
}
|
||||
|
||||
void GetGlobalLock()
|
||||
{
|
||||
pthread_mutex_lock(&gMutex);
|
||||
}
|
||||
|
||||
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_WaitForAllThreads(void* /*threads*/, int /*numThreads*/)
|
||||
{
|
||||
}
|
||||
|
||||
void OS_Sleep(int milliseconds)
|
||||
void OS_Sleep(int /*milliseconds*/)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -37,14 +37,14 @@
|
|||
#define STRICT
|
||||
#define VC_EXTRALEAN 1
|
||||
#include <windows.h>
|
||||
#include <assert.h>
|
||||
#include <cassert>
|
||||
#include <process.h>
|
||||
#include <psapi.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <cstdio>
|
||||
#include <cstdint>
|
||||
|
||||
//
|
||||
// This file contains contains the Window-OS-specific functions
|
||||
// This file contains the Window-OS-specific functions
|
||||
//
|
||||
|
||||
#if !(defined(_WIN32) || defined(_WIN64))
|
||||
|
|
@ -55,12 +55,12 @@ namespace glslang {
|
|||
|
||||
inline OS_TLSIndex ToGenericTLSIndex (DWORD handle)
|
||||
{
|
||||
return (OS_TLSIndex)((uintptr_t)handle + 1);
|
||||
return (OS_TLSIndex)((uintptr_t)handle + 1);
|
||||
}
|
||||
|
||||
inline DWORD ToNativeTLSIndex (OS_TLSIndex nIndex)
|
||||
{
|
||||
return (DWORD)((uintptr_t)nIndex - 1);
|
||||
return (DWORD)((uintptr_t)nIndex - 1);
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -68,46 +68,46 @@ inline DWORD ToNativeTLSIndex (OS_TLSIndex nIndex)
|
|||
//
|
||||
OS_TLSIndex OS_AllocTLSIndex()
|
||||
{
|
||||
DWORD dwIndex = TlsAlloc();
|
||||
if (dwIndex == TLS_OUT_OF_INDEXES) {
|
||||
assert(0 && "OS_AllocTLSIndex(): Unable to allocate Thread Local Storage");
|
||||
return OS_INVALID_TLS_INDEX;
|
||||
}
|
||||
DWORD dwIndex = TlsAlloc();
|
||||
if (dwIndex == TLS_OUT_OF_INDEXES) {
|
||||
assert(0 && "OS_AllocTLSIndex(): Unable to allocate Thread Local Storage");
|
||||
return OS_INVALID_TLS_INDEX;
|
||||
}
|
||||
|
||||
return ToGenericTLSIndex(dwIndex);
|
||||
return ToGenericTLSIndex(dwIndex);
|
||||
}
|
||||
|
||||
|
||||
bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue)
|
||||
{
|
||||
if (nIndex == OS_INVALID_TLS_INDEX) {
|
||||
assert(0 && "OS_SetTLSValue(): Invalid TLS Index");
|
||||
return false;
|
||||
}
|
||||
if (nIndex == OS_INVALID_TLS_INDEX) {
|
||||
assert(0 && "OS_SetTLSValue(): Invalid TLS Index");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (TlsSetValue(ToNativeTLSIndex(nIndex), lpvValue))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
if (TlsSetValue(ToNativeTLSIndex(nIndex), lpvValue))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void* OS_GetTLSValue(OS_TLSIndex nIndex)
|
||||
{
|
||||
assert(nIndex != OS_INVALID_TLS_INDEX);
|
||||
return TlsGetValue(ToNativeTLSIndex(nIndex));
|
||||
assert(nIndex != OS_INVALID_TLS_INDEX);
|
||||
return TlsGetValue(ToNativeTLSIndex(nIndex));
|
||||
}
|
||||
|
||||
bool OS_FreeTLSIndex(OS_TLSIndex nIndex)
|
||||
{
|
||||
if (nIndex == OS_INVALID_TLS_INDEX) {
|
||||
assert(0 && "OS_SetTLSValue(): Invalid TLS Index");
|
||||
return false;
|
||||
}
|
||||
if (nIndex == OS_INVALID_TLS_INDEX) {
|
||||
assert(0 && "OS_SetTLSValue(): Invalid TLS Index");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (TlsFree(ToNativeTLSIndex(nIndex)))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
if (TlsFree(ToNativeTLSIndex(nIndex)))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
HANDLE GlobalLock;
|
||||
|
|
@ -129,7 +129,7 @@ void ReleaseGlobalLock()
|
|||
|
||||
unsigned int __stdcall EnterGenericThread (void* entry)
|
||||
{
|
||||
return ((TThreadEntrypoint)entry)(0);
|
||||
return ((TThreadEntrypoint)entry)(0);
|
||||
}
|
||||
|
||||
void* OS_CreateThread(TThreadEntrypoint entry)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
//
|
||||
//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
||||
//Copyright (C) 2013-2016 LunarG, Inc.
|
||||
//
|
||||
//All rights reserved.
|
||||
//
|
||||
//Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -37,7 +39,7 @@
|
|||
#include "../Include/ResourceLimits.h"
|
||||
#include "../MachineIndependent/Versions.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <cstring>
|
||||
|
||||
#ifdef _WIN32
|
||||
#define C_DECL __cdecl
|
||||
|
|
@ -101,6 +103,8 @@ typedef enum {
|
|||
|
||||
namespace glslang {
|
||||
|
||||
class TType;
|
||||
|
||||
typedef enum {
|
||||
EShSourceNone,
|
||||
EShSourceGlsl,
|
||||
|
|
@ -300,6 +304,12 @@ public:
|
|||
const char* const* s, const int* l, const char* const* names, int n);
|
||||
void setPreamble(const char* s) { preamble = s; }
|
||||
void setEntryPoint(const char* entryPoint);
|
||||
void setShiftSamplerBinding(unsigned int base);
|
||||
void setShiftTextureBinding(unsigned int base);
|
||||
void setShiftUboBinding(unsigned int base);
|
||||
void setAutoMapBindings(bool map);
|
||||
void setFlattenUniformArrays(bool flatten);
|
||||
void setNoStorageFormat(bool useUnknownFormat);
|
||||
|
||||
// Interface to #include handlers.
|
||||
//
|
||||
|
|
@ -433,6 +443,7 @@ private:
|
|||
};
|
||||
|
||||
class TReflection;
|
||||
class TIoMapper;
|
||||
|
||||
// Make one TProgram per set of shaders that will get linked together. Add all
|
||||
// the shaders that are to be linked together. After calling shader.parse()
|
||||
|
|
@ -455,21 +466,27 @@ public:
|
|||
|
||||
// Reflection Interface
|
||||
bool buildReflection(); // call first, to do liveness analysis, index mapping, etc.; returns false on failure
|
||||
int getNumLiveUniformVariables(); // can be used for glGetProgramiv(GL_ACTIVE_UNIFORMS)
|
||||
int getNumLiveUniformBlocks(); // can be used for glGetProgramiv(GL_ACTIVE_UNIFORM_BLOCKS)
|
||||
const char* getUniformName(int index); // can be used for "name" part of glGetActiveUniform()
|
||||
const char* getUniformBlockName(int blockIndex); // can be used for glGetActiveUniformBlockName()
|
||||
int getUniformBlockSize(int blockIndex); // can be used for glGetActiveUniformBlockiv(UNIFORM_BLOCK_DATA_SIZE)
|
||||
int getUniformIndex(const char* name); // can be used for glGetUniformIndices()
|
||||
int getUniformBlockIndex(int index); // can be used for glGetActiveUniformsiv(GL_UNIFORM_BLOCK_INDEX)
|
||||
int getUniformType(int index); // can be used for glGetActiveUniformsiv(GL_UNIFORM_TYPE)
|
||||
int getUniformBufferOffset(int index); // can be used for glGetActiveUniformsiv(GL_UNIFORM_OFFSET)
|
||||
int getUniformArraySize(int index); // can be used for glGetActiveUniformsiv(GL_UNIFORM_SIZE)
|
||||
int getNumLiveAttributes(); // can be used for glGetProgramiv(GL_ACTIVE_ATTRIBUTES)
|
||||
const char *getAttributeName(int index); // can be used for glGetActiveAttrib()
|
||||
int getAttributeType(int index); // can be used for glGetActiveAttrib()
|
||||
int getNumLiveUniformVariables() const; // can be used for glGetProgramiv(GL_ACTIVE_UNIFORMS)
|
||||
int getNumLiveUniformBlocks() const; // can be used for glGetProgramiv(GL_ACTIVE_UNIFORM_BLOCKS)
|
||||
const char* getUniformName(int index) const; // can be used for "name" part of glGetActiveUniform()
|
||||
const char* getUniformBlockName(int blockIndex) const; // can be used for glGetActiveUniformBlockName()
|
||||
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 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)
|
||||
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*
|
||||
const TType* getUniformBlockTType(int index) const; // returns a TType*
|
||||
|
||||
void dumpReflection();
|
||||
|
||||
// I/O mapping: apply base offsets and map live unbound variables
|
||||
bool mapIO();
|
||||
|
||||
protected:
|
||||
bool linkStage(EShLanguage, EShMessages);
|
||||
|
||||
|
|
@ -479,6 +496,7 @@ protected:
|
|||
bool newedIntermediate[EShLangCount]; // track which intermediate were "new" versus reusing a singleton unit in a stage
|
||||
TInfoSink* infoSink;
|
||||
TReflection* reflection;
|
||||
TIoMapper* ioMapper;
|
||||
bool linked;
|
||||
|
||||
private:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue