[glslang][EXT] Support extension ARB_bindless_texture.

Add missing callgraph clean for bindless status flag.

Add test cases. Add support to check special extensions not be available for Vulkan when using GLSL.
This commit is contained in:
Zhou 2022-11-16 00:04:55 +08:00 committed by ShchchowAMD
parent 2b2523fb95
commit 16526fd9d2
19 changed files with 608 additions and 35 deletions

View File

@ -1293,7 +1293,7 @@ spv::StorageClass TGlslangToSpvTraverser::TranslateStorageClass(const glslang::T
type.getQualifier().storage == glslang::EvqUniform) {
if (type.isAtomic())
return spv::StorageClassAtomicCounter;
if (type.containsOpaque())
if (type.containsOpaque() && !glslangIntermediate->getBindlessMode())
return spv::StorageClassUniformConstant;
}
@ -5083,7 +5083,7 @@ bool TGlslangToSpvTraverser::originalParam(glslang::TStorageQualifier qualifier,
return true;
if (glslangIntermediate->getSource() == glslang::EShSourceHlsl)
return paramType.getBasicType() == glslang::EbtBlock;
return paramType.containsOpaque() || // sampler, etc.
return (paramType.containsOpaque() && !glslangIntermediate->getBindlessMode()) || // sampler, etc.
#ifndef GLSLANG_WEB
paramType.getQualifier().isSpirvByReference() || // spirv_by_reference
#endif

View File

@ -0,0 +1,50 @@
#version 460 compatibility
#extension GL_ARB_bindless_texture: require
#if !defined GL_ARB_bindless_texture
# error GL_ARB_bindless_texture is not defined
#elif GL_ARB_bindless_texture != 1
# error GL_ARB_bindless_texture is not equal to 1
#endif
// Valid usage cases
layout(bindless_sampler) uniform sampler2D s0; // case0: bindless layout
in sampler2D s1; // case1: sampler as an input
uniform uvec2 s2; // case2: uvec2 as sampler constructor
uniform ivec2 s3; // case3: ivec2 as sampler constructor
uniform int index;
in sampler2D s4[2][3]; // case4: sampler arrays of arrays
uniform BB {sampler2D s5;} bbs5[2]; // case5: uniform block member as a sampler
in samplerBuffer s6; // case6: samplerBuffer input
uniform UBO9 {samplerBuffer s7;}; // case7: samplerBuffer as an uniform block member
buffer SSBO10 {samplerBuffer s8;}; // case8: samplerBuffer as an ssbo member
layout(rgba8, bindless_image) in image2D i9; // case9: bindless image as an input
uniform vec2 coord; // bindless coord 2-D
uniform int icoord; // bindless coord 1-D
out vec4 color0;
out vec4 color1;
out vec4 color2;
out vec4 color3;
out vec4 color4;
out vec4 color5;
out vec4 color6;
out vec4 color7;
out vec4 color8;
out vec4 color9;
void main()
{
color0 = texture(s0, coord);
color1 = texture(s1, coord);
color2 = texture(sampler2D(s2), coord);
color3 = texture(sampler2D(s3), coord);
color4 = texture(s4[index][index], coord);
color5 = texture(bbs5[index].s5, coord);
color6 = texelFetch(s6, icoord);
color7 = texelFetch(s7, icoord);
color8 = texelFetch(s8, icoord);
color9 = imageLoad(i9, ivec2(0,0));
}

View File

@ -0,0 +1,205 @@
GL_ARB_bindless_texture.frag
Shader version: 460
Requested GL_ARB_bindless_texture
0:? Sequence
0:38 Function Definition: main( ( global void)
0:38 Function Parameters:
0:40 Sequence
0:40 move second child to first child ( temp 4-component vector of float)
0:40 'color0' ( out 4-component vector of float)
0:40 texture ( global 4-component vector of float)
0:40 's0' ( uniform sampler2D)
0:40 'coord' ( uniform 2-component vector of float)
0:41 move second child to first child ( temp 4-component vector of float)
0:41 'color1' ( out 4-component vector of float)
0:41 texture ( global 4-component vector of float)
0:41 's1' ( smooth in sampler2D)
0:41 'coord' ( uniform 2-component vector of float)
0:42 move second child to first child ( temp 4-component vector of float)
0:42 'color2' ( out 4-component vector of float)
0:42 texture ( global 4-component vector of float)
0:42 packUint2x32 ( temp sampler2D)
0:42 's2' ( uniform 2-component vector of uint)
0:42 'coord' ( uniform 2-component vector of float)
0:43 move second child to first child ( temp 4-component vector of float)
0:43 'color3' ( out 4-component vector of float)
0:43 texture ( global 4-component vector of float)
0:43 packUint2x32 ( temp sampler2D)
0:43 's3' ( uniform 2-component vector of int)
0:43 'coord' ( uniform 2-component vector of float)
0:44 move second child to first child ( temp 4-component vector of float)
0:44 'color4' ( out 4-component vector of float)
0:44 texture ( global 4-component vector of float)
0:44 indirect index ( smooth temp sampler2D)
0:44 indirect index ( smooth temp 3-element array of sampler2D)
0:44 's4' ( smooth in 2-element array of 3-element array of sampler2D)
0:44 'index' ( uniform int)
0:44 'index' ( uniform int)
0:44 'coord' ( uniform 2-component vector of float)
0:45 move second child to first child ( temp 4-component vector of float)
0:45 'color5' ( out 4-component vector of float)
0:45 texture ( global 4-component vector of float)
0:45 s5: direct index for structure (layout( column_major shared layoutBindlessSampler) uniform sampler2D)
0:45 indirect index (layout( column_major shared) temp block{layout( column_major shared layoutBindlessSampler) uniform sampler2D s5})
0:45 'bbs5' (layout( column_major shared) uniform 2-element array of block{layout( column_major shared layoutBindlessSampler) uniform sampler2D s5})
0:45 'index' ( uniform int)
0:45 Constant:
0:45 0 (const int)
0:45 'coord' ( uniform 2-component vector of float)
0:46 move second child to first child ( temp 4-component vector of float)
0:46 'color6' ( out 4-component vector of float)
0:46 textureFetch ( global 4-component vector of float)
0:46 's6' ( smooth in samplerBuffer)
0:46 'icoord' ( uniform int)
0:47 move second child to first child ( temp 4-component vector of float)
0:47 'color7' ( out 4-component vector of float)
0:47 textureFetch ( global 4-component vector of float)
0:47 s7: direct index for structure (layout( column_major shared layoutBindlessSampler) uniform samplerBuffer)
0:47 'anon@0' (layout( column_major shared) uniform block{layout( column_major shared layoutBindlessSampler) uniform samplerBuffer s7})
0:47 Constant:
0:47 0 (const uint)
0:47 'icoord' ( uniform int)
0:48 move second child to first child ( temp 4-component vector of float)
0:48 'color8' ( out 4-component vector of float)
0:48 textureFetch ( global 4-component vector of float)
0:48 s8: direct index for structure (layout( column_major shared layoutBindlessSampler) buffer samplerBuffer)
0:48 'anon@1' (layout( column_major shared) buffer block{layout( column_major shared layoutBindlessSampler) buffer samplerBuffer s8})
0:48 Constant:
0:48 0 (const uint)
0:48 'icoord' ( uniform int)
0:49 move second child to first child ( temp 4-component vector of float)
0:49 'color9' ( out 4-component vector of float)
0:49 imageLoad ( global 4-component vector of float)
0:49 'i9' (layout( rgba8 layoutBindlessImage) smooth in image2D)
0:49 Constant:
0:49 0 (const int)
0:49 0 (const int)
0:? Linker Objects
0:? 's0' ( uniform sampler2D)
0:? 's1' ( smooth in sampler2D)
0:? 's2' ( uniform 2-component vector of uint)
0:? 's3' ( uniform 2-component vector of int)
0:? 'index' ( uniform int)
0:? 's4' ( smooth in 2-element array of 3-element array of sampler2D)
0:? 'bbs5' (layout( column_major shared) uniform 2-element array of block{layout( column_major shared layoutBindlessSampler) uniform sampler2D s5})
0:? 's6' ( smooth in samplerBuffer)
0:? 'anon@0' (layout( column_major shared) uniform block{layout( column_major shared layoutBindlessSampler) uniform samplerBuffer s7})
0:? 'anon@1' (layout( column_major shared) buffer block{layout( column_major shared layoutBindlessSampler) buffer samplerBuffer s8})
0:? 'i9' (layout( rgba8 layoutBindlessImage) smooth in image2D)
0:? 'coord' ( uniform 2-component vector of float)
0:? 'icoord' ( uniform int)
0:? 'color0' ( out 4-component vector of float)
0:? 'color1' ( out 4-component vector of float)
0:? 'color2' ( out 4-component vector of float)
0:? 'color3' ( out 4-component vector of float)
0:? 'color4' ( out 4-component vector of float)
0:? 'color5' ( out 4-component vector of float)
0:? 'color6' ( out 4-component vector of float)
0:? 'color7' ( out 4-component vector of float)
0:? 'color8' ( out 4-component vector of float)
0:? 'color9' ( out 4-component vector of float)
Linked fragment stage:
Shader version: 460
Requested GL_ARB_bindless_texture
0:? Sequence
0:38 Function Definition: main( ( global void)
0:38 Function Parameters:
0:40 Sequence
0:40 move second child to first child ( temp 4-component vector of float)
0:40 'color0' ( out 4-component vector of float)
0:40 texture ( global 4-component vector of float)
0:40 's0' ( uniform sampler2D)
0:40 'coord' ( uniform 2-component vector of float)
0:41 move second child to first child ( temp 4-component vector of float)
0:41 'color1' ( out 4-component vector of float)
0:41 texture ( global 4-component vector of float)
0:41 's1' ( smooth in sampler2D)
0:41 'coord' ( uniform 2-component vector of float)
0:42 move second child to first child ( temp 4-component vector of float)
0:42 'color2' ( out 4-component vector of float)
0:42 texture ( global 4-component vector of float)
0:42 packUint2x32 ( temp sampler2D)
0:42 's2' ( uniform 2-component vector of uint)
0:42 'coord' ( uniform 2-component vector of float)
0:43 move second child to first child ( temp 4-component vector of float)
0:43 'color3' ( out 4-component vector of float)
0:43 texture ( global 4-component vector of float)
0:43 packUint2x32 ( temp sampler2D)
0:43 's3' ( uniform 2-component vector of int)
0:43 'coord' ( uniform 2-component vector of float)
0:44 move second child to first child ( temp 4-component vector of float)
0:44 'color4' ( out 4-component vector of float)
0:44 texture ( global 4-component vector of float)
0:44 indirect index ( smooth temp sampler2D)
0:44 indirect index ( smooth temp 3-element array of sampler2D)
0:44 's4' ( smooth in 2-element array of 3-element array of sampler2D)
0:44 'index' ( uniform int)
0:44 'index' ( uniform int)
0:44 'coord' ( uniform 2-component vector of float)
0:45 move second child to first child ( temp 4-component vector of float)
0:45 'color5' ( out 4-component vector of float)
0:45 texture ( global 4-component vector of float)
0:45 s5: direct index for structure (layout( column_major shared layoutBindlessSampler) uniform sampler2D)
0:45 indirect index (layout( column_major shared) temp block{layout( column_major shared layoutBindlessSampler) uniform sampler2D s5})
0:45 'bbs5' (layout( column_major shared) uniform 2-element array of block{layout( column_major shared layoutBindlessSampler) uniform sampler2D s5})
0:45 'index' ( uniform int)
0:45 Constant:
0:45 0 (const int)
0:45 'coord' ( uniform 2-component vector of float)
0:46 move second child to first child ( temp 4-component vector of float)
0:46 'color6' ( out 4-component vector of float)
0:46 textureFetch ( global 4-component vector of float)
0:46 's6' ( smooth in samplerBuffer)
0:46 'icoord' ( uniform int)
0:47 move second child to first child ( temp 4-component vector of float)
0:47 'color7' ( out 4-component vector of float)
0:47 textureFetch ( global 4-component vector of float)
0:47 s7: direct index for structure (layout( column_major shared layoutBindlessSampler) uniform samplerBuffer)
0:47 'anon@0' (layout( column_major shared) uniform block{layout( column_major shared layoutBindlessSampler) uniform samplerBuffer s7})
0:47 Constant:
0:47 0 (const uint)
0:47 'icoord' ( uniform int)
0:48 move second child to first child ( temp 4-component vector of float)
0:48 'color8' ( out 4-component vector of float)
0:48 textureFetch ( global 4-component vector of float)
0:48 s8: direct index for structure (layout( column_major shared layoutBindlessSampler) buffer samplerBuffer)
0:48 'anon@1' (layout( column_major shared) buffer block{layout( column_major shared layoutBindlessSampler) buffer samplerBuffer s8})
0:48 Constant:
0:48 0 (const uint)
0:48 'icoord' ( uniform int)
0:49 move second child to first child ( temp 4-component vector of float)
0:49 'color9' ( out 4-component vector of float)
0:49 imageLoad ( global 4-component vector of float)
0:49 'i9' (layout( rgba8 layoutBindlessImage) smooth in image2D)
0:49 Constant:
0:49 0 (const int)
0:49 0 (const int)
0:? Linker Objects
0:? 's0' ( uniform sampler2D)
0:? 's1' ( smooth in sampler2D)
0:? 's2' ( uniform 2-component vector of uint)
0:? 's3' ( uniform 2-component vector of int)
0:? 'index' ( uniform int)
0:? 's4' ( smooth in 2-element array of 3-element array of sampler2D)
0:? 'bbs5' (layout( column_major shared) uniform 2-element array of block{layout( column_major shared layoutBindlessSampler) uniform sampler2D s5})
0:? 's6' ( smooth in samplerBuffer)
0:? 'anon@0' (layout( column_major shared) uniform block{layout( column_major shared layoutBindlessSampler) uniform samplerBuffer s7})
0:? 'anon@1' (layout( column_major shared) buffer block{layout( column_major shared layoutBindlessSampler) buffer samplerBuffer s8})
0:? 'i9' (layout( rgba8 layoutBindlessImage) smooth in image2D)
0:? 'coord' ( uniform 2-component vector of float)
0:? 'icoord' ( uniform int)
0:? 'color0' ( out 4-component vector of float)
0:? 'color1' ( out 4-component vector of float)
0:? 'color2' ( out 4-component vector of float)
0:? 'color3' ( out 4-component vector of float)
0:? 'color4' ( out 4-component vector of float)
0:? 'color5' ( out 4-component vector of float)
0:? 'color6' ( out 4-component vector of float)
0:? 'color7' ( out 4-component vector of float)
0:? 'color8' ( out 4-component vector of float)
0:? 'color9' ( out 4-component vector of float)

View File

@ -6,7 +6,7 @@ ERROR: 0:6: 'binding' : sampler/texture/image requires layout(binding=X)
ERROR: 0:8: 'binding' : sampler/texture/image requires layout(binding=X)
ERROR: 0:9: 'binding' : sampler/texture/image requires layout(binding=X)
ERROR: 0:10: 'binding' : sampler/texture/image requires layout(binding=X)
ERROR: 0:14: 'sampler2D' : sampler-constructor requires two arguments
ERROR: 0:14: 'sampler2D' : sampler-constructor requires the extension GL_ARB_bindless_texture enabled
ERROR: 0:15: 'sampler2D' : sampler-constructor first argument must be a scalar *texture* type
ERROR: 0:16: 'sampler2D' : sampler-constructor first argument must be a scalar *texture* type
ERROR: 0:17: 'sampler2D' : sampler-constructor second argument must be a scalar sampler or samplerShadow

View File

@ -429,6 +429,12 @@ enum TLayoutFormat {
ElfR16ui,
ElfR8ui,
ElfR64ui,
ElfExtSizeGuard, // to help with comparisons
ElfSize1x8,
ElfSize1x16,
ElfSize1x32,
ElfSize2x32,
ElfSize4x32,
ElfCount
};
@ -898,6 +904,8 @@ public:
// -2048 as the default value indicating layoutSecondaryViewportRelative is not set
layoutSecondaryViewportRelativeOffset = -2048;
layoutShaderRecord = false;
layoutBindlessSampler = false;
layoutBindlessImage = false;
layoutBufferReferenceAlign = layoutBufferReferenceAlignEnd;
layoutFormat = ElfNone;
#endif
@ -1001,6 +1009,9 @@ public:
// GL_EXT_spirv_intrinsics
int spirvStorageClass;
TSpirvDecorate* spirvDecorate;
bool layoutBindlessSampler;
bool layoutBindlessImage;
#endif
bool hasUniformLayout() const
@ -1132,6 +1143,14 @@ public:
{
return nonUniform;
}
bool isBindlessSampler() const
{
return layoutBindlessSampler;
}
bool isBindlessImage() const
{
return layoutBindlessImage;
}
// GL_EXT_spirv_intrinsics
bool hasSprivDecorate() const { return spirvDecorate != nullptr; }
@ -1241,6 +1260,11 @@ public:
case ElfR8ui: return "r8ui";
case ElfR64ui: return "r64ui";
case ElfR64i: return "r64i";
case ElfSize1x8: return "size1x8";
case ElfSize1x16: return "size1x16";
case ElfSize1x32: return "size1x32";
case ElfSize2x32: return "size2x32";
case ElfSize4x32: return "size4x32";
default: return "none";
}
}
@ -1898,6 +1922,8 @@ public:
virtual bool isImage() const { return basicType == EbtSampler && getSampler().isImage(); }
virtual bool isSubpass() const { return basicType == EbtSampler && getSampler().isSubpass(); }
virtual bool isTexture() const { return basicType == EbtSampler && getSampler().isTexture(); }
virtual bool isBindlessImage() const { return isImage() && qualifier.layoutBindlessImage; }
virtual bool isBindlessTexture() const { return isTexture() && qualifier.layoutBindlessSampler; }
// Check the block-name convention of creating a block without populating it's members:
virtual bool isUnusableName() const { return isStruct() && structure == nullptr; }
virtual bool isParameterized() const { return typeParameters != nullptr; }
@ -1954,6 +1980,11 @@ public:
return contains([](const TType* t) { return t->isOpaque(); } );
}
virtual bool containsSampler() const
{
return contains([](const TType* t) { return t->isTexture() || t->isImage(); });
}
// Recursively checks if the type contains a built-in variable
virtual bool containsBuiltIn() const
{
@ -2285,7 +2316,10 @@ public:
}
if (qualifier.layoutShaderRecord)
appendStr(" shaderRecordNV");
if (qualifier.layoutBindlessSampler)
appendStr(" layoutBindlessSampler");
if (qualifier.layoutBindlessImage)
appendStr(" layoutBindlessImage");
appendStr(")");
}
}
@ -2544,6 +2578,7 @@ public:
void setStruct(TTypeList* s) { assert(isStruct()); structure = s; }
TTypeList* getWritableStruct() const { assert(isStruct()); return structure; } // This should only be used when known to not be sharing with other threads
void setBasicType(const TBasicType& t) { basicType = t; }
void setVectorSize(int s) { vectorSize = s; }
int computeNumComponents() const
{

View File

@ -751,6 +751,11 @@ bool TIntermediate::buildConvertOp(TBasicType dst, TBasicType src, TOperator& ne
case EbtInt64: newOp = EOpConvInt64ToUint; break;
case EbtUint64: newOp = EOpConvUint64ToUint; break;
#endif
// For bindless texture type conversion, add a dummy convert op, just
// to generate a new TIntermTyped
// uvec2(any sampler type)
// uvec2(any image type)
case EbtSampler: newOp = EOpConvIntToUint; break;
default:
return false;
}

View File

@ -159,7 +159,8 @@ bool TParseContextBase::lValueErrorCheck(const TSourceLoc& loc, const char* op,
//
switch (node->getBasicType()) {
case EbtSampler:
message = "can't modify a sampler";
if (extensionTurnedOn(E_GL_ARB_bindless_texture) == false)
message = "can't modify a sampler";
break;
case EbtVoid:
message = "can't modify void";

View File

@ -1389,7 +1389,8 @@ TIntermTyped* TParseContext::handleFunctionCall(const TSourceLoc& loc, TFunction
#endif
const TType& argType = arg->getAsTyped()->getType();
const TQualifier& argQualifier = argType.getQualifier();
if (argQualifier.isMemory() && (argType.containsOpaque() || argType.isReference())) {
bool containsBindlessSampler = intermediate.getBindlessMode() && argType.containsSampler();
if (argQualifier.isMemory() && !containsBindlessSampler && (argType.containsOpaque() || argType.isReference())) {
const char* message = "argument cannot drop memory qualifier when passed to formal parameter";
#ifndef GLSLANG_WEB
if (argQualifier.volatil && ! formalQualifier.volatil)
@ -1675,9 +1676,13 @@ TIntermNode* TParseContext::handleReturnValue(const TSourceLoc& loc, TIntermType
error(loc, "type does not match, or is not convertible to, the function's return type", "return", "");
branch = intermediate.addBranch(EOpReturn, value, loc);
}
} else
} else {
if (value->getType().isTexture() || value->getType().isImage()) {
if (!extensionTurnedOn(E_GL_ARB_bindless_texture))
error(loc, "sampler or image can be used as return type only when the extension GL_ARB_bindless_texture enabled", "return", "");
}
branch = intermediate.addBranch(EOpReturn, value, loc);
}
branch->updatePrecision(currentFunctionType->getQualifier().precision);
return branch;
}
@ -1928,6 +1933,9 @@ TIntermTyped* TParseContext::addAssign(const TSourceLoc& loc, TOperator op, TInt
if ((op == EOpAddAssign || op == EOpSubAssign) && left->isReference())
requireExtensions(loc, 1, &E_GL_EXT_buffer_reference2, "+= and -= on a buffer reference");
if (op == EOpAssign && left->getBasicType() == EbtSampler && right->getBasicType() == EbtSampler)
requireExtensions(loc, 1, &E_GL_ARB_bindless_texture, "sampler assignment for bindless texture");
return intermediate.addAssign(op, left, right, loc);
}
@ -2811,6 +2819,14 @@ TFunction* TParseContext::handleConstructorCall(const TSourceLoc& loc, const TPu
profileRequires(loc, EEsProfile, 300, nullptr, "arrayed constructor");
}
// Reuse EOpConstructTextureSampler for bindless image constructor
// uvec2 imgHandle;
// imageLoad(image1D(imgHandle), 0);
if (type.isImage() && extensionTurnedOn(E_GL_ARB_bindless_texture))
{
intermediate.setBindlessImageMode(currentCaller, AstRefTypeFunc);
}
TOperator op = intermediate.mapTypeToConstructorOp(type);
if (op == EOpNull) {
@ -3544,8 +3560,13 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T
return true;
}
if (op != EOpConstructStruct && op != EOpConstructNonuniform && typed->getBasicType() == EbtSampler) {
error(loc, "cannot convert a sampler", constructorString.c_str(), "");
return true;
if (op == EOpConstructUVec2 && extensionTurnedOn(E_GL_ARB_bindless_texture)) {
intermediate.setBindlessTextureMode(currentCaller, AstRefTypeFunc);
}
else {
error(loc, "cannot convert a sampler", constructorString.c_str(), "");
return true;
}
}
if (op != EOpConstructStruct && typed->isAtomic()) {
error(loc, "cannot convert an atomic_uint", constructorString.c_str(), "");
@ -3565,6 +3586,26 @@ bool TParseContext::constructorTextureSamplerError(const TSourceLoc& loc, const
{
TString constructorName = function.getType().getBasicTypeString(); // TODO: performance: should not be making copy; interface needs to change
const char* token = constructorName.c_str();
// verify the constructor for bindless texture, the input must be ivec2 or uvec2
if (function.getParamCount() == 1) {
TType* pType = function[0].type;
TBasicType basicType = pType->getBasicType();
bool isIntegerVec2 = ((basicType == EbtUint || basicType == EbtInt) && pType->getVectorSize() == 2);
bool bindlessMode = extensionTurnedOn(E_GL_ARB_bindless_texture);
if (isIntegerVec2 && bindlessMode) {
if (pType->getSampler().isImage())
intermediate.setBindlessImageMode(currentCaller, AstRefTypeFunc);
else
intermediate.setBindlessTextureMode(currentCaller, AstRefTypeFunc);
return false;
} else {
if (!bindlessMode)
error(loc, "sampler-constructor requires the extension GL_ARB_bindless_texture enabled", token, "");
else
error(loc, "sampler-constructor requires the input to be ivec2 or uvec2", token, "");
return true;
}
}
// exactly two arguments needed
if (function.getParamCount() != 2) {
@ -3660,13 +3701,32 @@ void TParseContext::samplerCheck(const TSourceLoc& loc, const TType& type, const
if (type.getQualifier().storage == EvqUniform)
return;
if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtSampler))
error(loc, "non-uniform struct contains a sampler or image:", type.getBasicTypeString().c_str(), identifier.c_str());
if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtSampler)) {
// For bindless texture, sampler can be declared as an struct member
if (extensionTurnedOn(E_GL_ARB_bindless_texture)) {
if (type.getSampler().isImage())
intermediate.setBindlessImageMode(currentCaller, AstRefTypeVar);
else
intermediate.setBindlessTextureMode(currentCaller, AstRefTypeVar);
}
else {
error(loc, "non-uniform struct contains a sampler or image:", type.getBasicTypeString().c_str(), identifier.c_str());
}
}
else if (type.getBasicType() == EbtSampler && type.getQualifier().storage != EvqUniform) {
// non-uniform sampler
// not yet: okay if it has an initializer
// if (! initializer)
error(loc, "sampler/image types can only be used in uniform variables or function parameters:", type.getBasicTypeString().c_str(), identifier.c_str());
// For bindless texture, sampler can be declared as an input/output/block member
if (extensionTurnedOn(E_GL_ARB_bindless_texture)) {
if (type.getSampler().isImage())
intermediate.setBindlessImageMode(currentCaller, AstRefTypeVar);
else
intermediate.setBindlessTextureMode(currentCaller, AstRefTypeVar);
}
else {
// non-uniform sampler
// not yet: okay if it has an initializer
// if (! initializer)
error(loc, "sampler/image types can only be used in uniform variables or function parameters:", type.getBasicTypeString().c_str(), identifier.c_str());
}
}
}
@ -3732,7 +3792,7 @@ void TParseContext::memberQualifierCheck(glslang::TPublicType& publicType)
//
// Check/fix just a full qualifier (no variables or types yet, but qualifier is complete) at global level.
//
void TParseContext::globalQualifierFixCheck(const TSourceLoc& loc, TQualifier& qualifier, bool isMemberCheck)
void TParseContext::globalQualifierFixCheck(const TSourceLoc& loc, TQualifier& qualifier, bool isMemberCheck, const TPublicType* publicType)
{
bool nonuniformOkay = false;
@ -3768,6 +3828,11 @@ void TParseContext::globalQualifierFixCheck(const TSourceLoc& loc, TQualifier& q
{
requireExtensions(loc, 1, &E_GL_EXT_scalar_block_layout, "default std430 layout for uniform");
}
if (publicType != nullptr && publicType->isImage() &&
(qualifier.layoutFormat > ElfExtSizeGuard && qualifier.layoutFormat < ElfCount))
qualifier.layoutFormat = mapLegacyLayoutFormat(qualifier.layoutFormat, publicType->sampler.getBasicType());
break;
default:
break;
@ -4172,7 +4237,7 @@ void TParseContext::precisionQualifierCheck(const TSourceLoc& loc, TBasicType ba
void TParseContext::parameterTypeCheck(const TSourceLoc& loc, TStorageQualifier qualifier, const TType& type)
{
if ((qualifier == EvqOut || qualifier == EvqInOut) && type.isOpaque())
if ((qualifier == EvqOut || qualifier == EvqInOut) && type.isOpaque() && !intermediate.getBindlessMode())
error(loc, "samplers and atomic_uints cannot be output parameters", type.getBasicTypeString().c_str(), "");
if (!parsingBuiltins && type.contains16BitFloat())
requireFloat16Arithmetic(loc, type.getBasicTypeString().c_str(), "float16 types can only be in uniform block or buffer storage");
@ -5105,7 +5170,7 @@ void TParseContext::arrayObjectCheck(const TSourceLoc& loc, const TType& type, c
void TParseContext::opaqueCheck(const TSourceLoc& loc, const TType& type, const char* op)
{
if (containsFieldWithBasicType(type, EbtSampler))
if (containsFieldWithBasicType(type, EbtSampler) && !extensionTurnedOn(E_GL_ARB_bindless_texture))
error(loc, "can't use with samplers or structs containing samplers", op, "");
}
@ -5480,6 +5545,28 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi
intermediate.setUsePhysicalStorageBuffer();
return;
}
if (id == "bindless_sampler") {
requireExtensions(loc, 1, &E_GL_ARB_bindless_texture, "bindless_sampler");
publicType.qualifier.layoutBindlessSampler = true;
intermediate.setBindlessTextureMode(currentCaller, AstRefTypeLayout);
return;
}
if (id == "bindless_image") {
requireExtensions(loc, 1, &E_GL_ARB_bindless_texture, "bindless_image");
publicType.qualifier.layoutBindlessImage = true;
intermediate.setBindlessImageMode(currentCaller, AstRefTypeLayout);
return;
}
if (id == "bound_sampler") {
requireExtensions(loc, 1, &E_GL_ARB_bindless_texture, "bound_sampler");
publicType.qualifier.layoutBindlessSampler = false;
return;
}
if (id == "bound_image") {
requireExtensions(loc, 1, &E_GL_ARB_bindless_texture, "bound_image");
publicType.qualifier.layoutBindlessImage = false;
return;
}
if (language == EShLangGeometry || language == EShLangTessEvaluation || language == EShLangMesh) {
if (id == TQualifier::getGeometryString(ElgTriangles)) {
publicType.shaderQualifiers.geometry = ElgTriangles;
@ -6137,6 +6224,10 @@ void TParseContext::mergeObjectLayoutQualifiers(TQualifier& dst, const TQualifie
dst.layoutSecondaryViewportRelativeOffset = src.layoutSecondaryViewportRelativeOffset;
if (src.layoutShaderRecord)
dst.layoutShaderRecord = true;
if (src.layoutBindlessSampler)
dst.layoutBindlessSampler = true;
if (src.layoutBindlessImage)
dst.layoutBindlessImage = true;
if (src.pervertexNV)
dst.pervertexNV = true;
if (src.pervertexEXT)
@ -6418,7 +6509,7 @@ void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type)
// Image format
if (qualifier.hasFormat()) {
if (! type.isImage())
if (! type.isImage() && !intermediate.getBindlessImageMode())
error(loc, "only apply to images", TQualifier::getLayoutFormatString(qualifier.getFormat()), "");
else {
if (type.getSampler().type == EbtFloat && qualifier.getFormat() > ElfFloatGuard)
@ -6437,7 +6528,7 @@ void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type)
}
}
}
} else if (type.isImage() && ! qualifier.isWriteOnly()) {
} else if (type.isImage() && ! qualifier.isWriteOnly() && !intermediate.getBindlessImageMode()) {
const char *explanation = "image variables not declared 'writeonly' and without a format layout qualifier";
requireProfile(loc, ECoreProfile | ECompatibilityProfile, explanation);
profileRequires(loc, ECoreProfile | ECompatibilityProfile, 0, E_GL_EXT_shader_image_load_formatted, explanation);
@ -7745,12 +7836,14 @@ TIntermTyped* TParseContext::addConstructor(const TSourceLoc& loc, TIntermNode*
// Combined texture-sampler constructors are completely semantic checked
// in constructorTextureSamplerError()
if (op == EOpConstructTextureSampler) {
if (aggrNode->getSequence()[1]->getAsTyped()->getType().getSampler().shadow) {
// Transfer depth into the texture (SPIR-V image) type, as a hint
// for tools to know this texture/image is a depth image.
aggrNode->getSequence()[0]->getAsTyped()->getWritableType().getSampler().shadow = true;
if (aggrNode != nullptr) {
if (aggrNode->getSequence()[1]->getAsTyped()->getType().getSampler().shadow) {
// Transfer depth into the texture (SPIR-V image) type, as a hint
// for tools to know this texture/image is a depth image.
aggrNode->getSequence()[0]->getAsTyped()->getWritableType().getSampler().shadow = true;
}
return intermediate.setAggregateOperator(aggrNode, op, type, loc);
}
return intermediate.setAggregateOperator(aggrNode, op, type, loc);
}
TTypeList::const_iterator memberTypes;
@ -7885,6 +7978,16 @@ TIntermTyped* TParseContext::constructBuiltIn(const TType& type, TOperator op, T
TIntermTyped* newNode = intermediate.addBuiltInFunctionCall(node->getLoc(), EOpConvPtrToUvec2, true, node,
type);
return newNode;
} else if (node->getType().getBasicType() == EbtSampler) {
requireExtensions(loc, 1, &E_GL_ARB_bindless_texture, "sampler conversion to uvec2");
// force the basic type of the constructor param to uvec2, otherwise spv builder will
// report some errors
TIntermTyped* newSrcNode = intermediate.createConversion(EbtUint, node);
newSrcNode->getAsTyped()->getWritableType().setVectorSize(2);
TIntermTyped* newNode =
intermediate.addBuiltInFunctionCall(node->getLoc(), EOpConstructUVec2, false, newSrcNode, type);
return newNode;
}
case EOpConstructUVec3:
case EOpConstructUVec4:
@ -7898,7 +8001,15 @@ TIntermTyped* TParseContext::constructBuiltIn(const TType& type, TOperator op, T
case EOpConstructBool:
basicOp = EOpConstructBool;
break;
case EOpConstructTextureSampler:
if ((node->getType().getBasicType() == EbtUint || node->getType().getBasicType() == EbtInt) &&
node->getType().getVectorSize() == 2) {
requireExtensions(loc, 1, &E_GL_ARB_bindless_texture, "ivec2/uvec2 convert to texture handle");
// No matter ivec2 or uvec2, Set EOpPackUint2x32 just to generate an opBitcast op code
TIntermTyped* newNode =
intermediate.addBuiltInFunctionCall(node->getLoc(), EOpPackUint2x32, true, node, type);
return newNode;
}
#ifndef GLSLANG_WEB
case EOpConstructDVec2:
@ -8245,6 +8356,30 @@ void TParseContext::inheritMemoryQualifiers(const TQualifier& from, TQualifier&
#endif
}
//
// Update qualifier layoutBindlessImage & layoutBindlessSampler on block member
//
void TParseContext::updateBindlessQualifier(TType& memberType)
{
if (memberType.containsSampler()) {
if (memberType.isStruct()) {
TTypeList* typeList = memberType.getWritableStruct();
for (unsigned int member = 0; member < typeList->size(); ++member) {
TType* subMemberType = (*typeList)[member].type;
updateBindlessQualifier(*subMemberType);
}
}
else if (memberType.getSampler().isImage()) {
intermediate.setBindlessImageMode(currentCaller, AstRefTypeLayout);
memberType.getQualifier().layoutBindlessImage = true;
}
else {
intermediate.setBindlessTextureMode(currentCaller, AstRefTypeLayout);
memberType.getQualifier().layoutBindlessSampler = true;
}
}
}
//
// Do everything needed to add an interface block.
//
@ -8297,8 +8432,13 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con
}
}
if (memberType.containsOpaque())
error(memberLoc, "member of block cannot be or contain a sampler, image, or atomic_uint type", typeList[member].type->getFieldName().c_str(), "");
// For bindless texture, sampler can be declared as uniform/storage block member,
if (memberType.containsOpaque()) {
if (memberType.containsSampler() && extensionTurnedOn(E_GL_ARB_bindless_texture))
updateBindlessQualifier(memberType);
else
error(memberLoc, "member of block cannot be or contain a sampler, image, or atomic_uint type", typeList[member].type->getFieldName().c_str(), "");
}
if (memberType.containsCoopMat())
error(memberLoc, "member of block cannot be or contain a cooperative matrix type", typeList[member].type->getFieldName().c_str(), "");
@ -9472,4 +9612,38 @@ const TTypeList* TParseContext::recordStructCopy(TStructRecord& record, const TT
return originStruct;
}
TLayoutFormat TParseContext::mapLegacyLayoutFormat(TLayoutFormat legacyLayoutFormat, TBasicType imageType)
{
TLayoutFormat layoutFormat = ElfNone;
if (imageType == EbtFloat) {
switch (legacyLayoutFormat) {
case ElfSize1x16: layoutFormat = ElfR16f; break;
case ElfSize1x32: layoutFormat = ElfR32f; break;
case ElfSize2x32: layoutFormat = ElfRg32f; break;
case ElfSize4x32: layoutFormat = ElfRgba32f; break;
default: break;
}
} else if (imageType == EbtUint) {
switch (legacyLayoutFormat) {
case ElfSize1x8: layoutFormat = ElfR8ui; break;
case ElfSize1x16: layoutFormat = ElfR16ui; break;
case ElfSize1x32: layoutFormat = ElfR32ui; break;
case ElfSize2x32: layoutFormat = ElfRg32ui; break;
case ElfSize4x32: layoutFormat = ElfRgba32ui; break;
default: break;
}
} else if (imageType == EbtInt) {
switch (legacyLayoutFormat) {
case ElfSize1x8: layoutFormat = ElfR8i; break;
case ElfSize1x16: layoutFormat = ElfR16i; break;
case ElfSize1x32: layoutFormat = ElfR32i; break;
case ElfSize2x32: layoutFormat = ElfRg32i; break;
case ElfSize4x32: layoutFormat = ElfRgba32i; break;
default: break;
}
}
return layoutFormat;
}
} // end namespace glslang

View File

@ -393,7 +393,7 @@ public:
void accStructCheck(const TSourceLoc & loc, const TType & type, const TString & identifier);
void transparentOpaqueCheck(const TSourceLoc&, const TType&, const TString& identifier);
void memberQualifierCheck(glslang::TPublicType&);
void globalQualifierFixCheck(const TSourceLoc&, TQualifier&, bool isMemberCheck = false);
void globalQualifierFixCheck(const TSourceLoc&, TQualifier&, bool isMemberCheck = false, const TPublicType* publicType = nullptr);
void globalQualifierTypeCheck(const TSourceLoc&, const TQualifier&, const TPublicType&);
bool structQualifierErrorCheck(const TSourceLoc&, const TPublicType& pType);
void mergeQualifiers(const TSourceLoc&, TQualifier& dst, const TQualifier& src, bool force);
@ -456,9 +456,11 @@ public:
void addQualifierToExisting(const TSourceLoc&, TQualifier, TIdentifierList&);
void invariantCheck(const TSourceLoc&, const TQualifier&);
void updateStandaloneQualifierDefaults(const TSourceLoc&, const TPublicType&);
void updateBindlessQualifier(TType& memberType);
void wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode);
TIntermNode* addSwitch(const TSourceLoc&, TIntermTyped* expression, TIntermAggregate* body);
const TTypeList* recordStructCopy(TStructRecord&, const TType*, const TType*);
TLayoutFormat mapLegacyLayoutFormat(TLayoutFormat legacyLayoutFormat, TBasicType imageType);
#ifndef GLSLANG_WEB
TAttributeType attributeFromName(const TString& name) const;

View File

@ -319,6 +319,7 @@ public:
virtual TParameter& operator[](int i) { assert(writable); return parameters[i]; }
virtual const TParameter& operator[](int i) const { return parameters[i]; }
const TQualifier& getQualifier() const { return returnType.getQualifier(); }
#ifndef GLSLANG_WEB
virtual void setSpirvInstruction(const TSpirvInstruction& inst)

View File

@ -227,6 +227,7 @@ void TParseVersions::initializeExtensionBehavior()
extensionBehavior[E_GL_ARB_texture_query_lod] = EBhDisable;
extensionBehavior[E_GL_ARB_vertex_attrib_64bit] = EBhDisable;
extensionBehavior[E_GL_ARB_draw_instanced] = EBhDisable;
extensionBehavior[E_GL_ARB_bindless_texture] = EBhDisable;
extensionBehavior[E_GL_ARB_fragment_coord_conventions] = EBhDisable;
@ -370,6 +371,9 @@ void TParseVersions::initializeExtensionBehavior()
extensionBehavior[E_GL_EXT_shader_subgroup_extended_types_float16] = EBhDisable;
extensionBehavior[E_GL_EXT_shader_atomic_float] = EBhDisable;
extensionBehavior[E_GL_EXT_shader_atomic_float2] = EBhDisable;
// Record extensions not for spv.
spvUnsupportedExt.push_back(E_GL_ARB_bindless_texture);
}
#endif // GLSLANG_WEB
@ -437,7 +441,6 @@ void TParseVersions::getPreamble(std::string& preamble)
} else { // !isEsProfile()
preamble =
"#define GL_FRAGMENT_PRECISION_HIGH 1\n"
"#define GL_ARB_texture_rectangle 1\n"
"#define GL_ARB_shading_language_420pack 1\n"
"#define GL_ARB_texture_gather 1\n"
@ -477,6 +480,7 @@ void TParseVersions::getPreamble(std::string& preamble)
"#define GL_ARB_vertex_attrib_64bit 1\n"
"#define GL_ARB_draw_instanced 1\n"
"#define GL_ARB_fragment_coord_conventions 1\n"
"#define GL_ARB_bindless_texture 1\n"
"#define GL_EXT_shader_non_constant_global_initializers 1\n"
"#define GL_EXT_shader_image_load_formatted 1\n"
"#define GL_EXT_post_depth_coverage 1\n"
@ -576,6 +580,10 @@ void TParseVersions::getPreamble(std::string& preamble)
preamble += "#define GL_EXT_null_initializer 1\n";
preamble += "#define GL_EXT_subgroup_uniform_control_flow 1\n";
}
if (version >= 130) {
preamble +="#define GL_FRAGMENT_PRECISION_HIGH 1\n";
}
#endif // GLSLANG_WEB
}
@ -1099,6 +1107,13 @@ void TParseVersions::extensionRequires(const TSourceLoc &loc, const char * const
minSpvVersion = iter->second;
requireSpv(loc, extension, minSpvVersion);
}
if (spvVersion.spv != 0){
for (auto ext : spvUnsupportedExt){
if (strcmp(extension, ext.c_str()) == 0)
error(loc, "not allowed when using generating SPIR-V codes", extension, "");
}
}
}
// Call for any operation needing full GLSL integer data-type support.

View File

@ -163,6 +163,7 @@ const char* const E_GL_ARB_texture_query_lod = "GL_ARB_texture_query_
const char* const E_GL_ARB_vertex_attrib_64bit = "GL_ARB_vertex_attrib_64bit";
const char* const E_GL_ARB_draw_instanced = "GL_ARB_draw_instanced";
const char* const E_GL_ARB_fragment_coord_conventions = "GL_ARB_fragment_coord_conventions";
const char* const E_GL_ARB_bindless_texture = "GL_ARB_bindless_texture";
const char* const E_GL_KHR_shader_subgroup_basic = "GL_KHR_shader_subgroup_basic";
const char* const E_GL_KHR_shader_subgroup_vote = "GL_KHR_shader_subgroup_vote";

View File

@ -1218,7 +1218,7 @@ fully_specified_type
parseContext.precisionQualifierCheck($$.loc, $$.basicType, $$.qualifier);
}
| type_qualifier type_specifier {
parseContext.globalQualifierFixCheck($1.loc, $1.qualifier);
parseContext.globalQualifierFixCheck($1.loc, $1.qualifier, false, &$2);
parseContext.globalQualifierTypeCheck($1.loc, $1.qualifier, $2);
if ($2.arraySizes) {

View File

@ -1218,7 +1218,7 @@ fully_specified_type
parseContext.precisionQualifierCheck($$.loc, $$.basicType, $$.qualifier);
}
| type_qualifier type_specifier {
parseContext.globalQualifierFixCheck($1.loc, $1.qualifier);
parseContext.globalQualifierFixCheck($1.loc, $1.qualifier, false, &$2);
parseContext.globalQualifierTypeCheck($1.loc, $1.qualifier, $2);
if ($2.arraySizes) {

View File

@ -6551,7 +6551,7 @@ yyreduce:
case 136: /* fully_specified_type: type_qualifier type_specifier */
#line 1220 "MachineIndependent/glslang.y"
{
parseContext.globalQualifierFixCheck((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).qualifier);
parseContext.globalQualifierFixCheck((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).qualifier, false, &(yyvsp[0].interm.type));
parseContext.globalQualifierTypeCheck((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).qualifier, (yyvsp[0].interm.type));
if ((yyvsp[0].interm.type).arraySizes) {

View File

@ -1517,7 +1517,10 @@ void TIntermediate::checkCallGraphBodies(TInfoSink& infoSink, bool keepUncalled)
if (! keepUncalled) {
for (int f = 0; f < (int)functionSequence.size(); ++f) {
if (! reachable[f])
{
resetTopLevelUncalledStatus(functionSequence[f]->getAsAggregate()->getName());
functionSequence[f] = nullptr;
}
}
functionSequence.erase(std::remove(functionSequence.begin(), functionSequence.end(), nullptr), functionSequence.end());
}
@ -2012,6 +2015,15 @@ int TIntermediate::getBaseAlignmentScalar(const TType& type, int& size)
case EbtInt16:
case EbtUint16: size = 2; return 2;
case EbtReference: size = 8; return 8;
case EbtSampler:
{
if (type.isBindlessImage() || type.isBindlessTexture()) {
size = 8; return 8;
}
else {
size = 4; return 4;
}
}
default: size = 4; return 4;
}
}

View File

@ -225,6 +225,16 @@ enum ComputeDerivativeMode {
LayoutDerivativeGroupLinear, // derivative_group_linearNV
};
//
// Status type on AST level. Some uncalled status or functions would be reset in call graph.
// Currently we will keep status set by explicitly declared layout or variable decl.
//
enum AstRefType {
AstRefTypeVar, // Status set by variable decl
AstRefTypeFunc, // Status set by function decl
AstRefTypeLayout, // Status set by layout decl
};
class TIdMaps {
public:
TMap<TString, long long>& operator[](long long i) { return maps[i]; }
@ -744,6 +754,65 @@ public:
useVariablePointers = true;
processes.addProcess("use-variable-pointers");
}
// Set the global flag for bindless texture
void setBindlessTextureMode(const TString& currentCaller, AstRefType type)
{
// When type is not func, currentCaller should be "" (empty string)
bindlessTextureModeCaller[currentCaller] = type;
}
// Get the global flag for bindless texture
bool getBindlessTextureMode() const
{
return (bindlessTextureModeCaller.size() > 0);
}
// Set the global flag for bindless image
void setBindlessImageMode(const TString& currentCaller, AstRefType type)
{
// When type is not func, currentCaller should be "" (empty string)
bindlessImageModeCaller[currentCaller] = type;
}
// Get the global flag for bindless image
bool getBindlessImageMode() const
{
return (bindlessImageModeCaller.size() > 0);
}
// Get the global flag for bindless texture
bool resetTopLevelUncalledStatus(const TString& deadCaller)
{
// For reflection collection purpose, currently uniform layout setting and some
// flags introduced by variables (IO, global, etc,.) won't be reset here.
// Remove each global status (AST top level) introduced by uncalled functions.
// If a status is set by several functions, keep those which in call graph.
bool result = false;
// For two types of bindless mode flag, we would only reset which is set by an uncalled function.
// If one status flag's key in caller vec is empty, it should be come from a non-function setting.
if (!bindlessTextureModeCaller.empty()) {
auto caller = bindlessTextureModeCaller.find(deadCaller);
if (caller != bindlessTextureModeCaller.end() && bindlessTextureModeCaller[deadCaller] == AstRefTypeFunc) {
bindlessTextureModeCaller.erase(caller);
result = true;
}
}
if (!bindlessImageModeCaller.empty()) {
auto caller = bindlessImageModeCaller.find(deadCaller);
if (caller != bindlessImageModeCaller.end() && bindlessImageModeCaller[deadCaller] == AstRefTypeFunc) {
bindlessImageModeCaller.erase(caller);
result = true;
}
}
return result;
}
bool getBindlessMode() const
{
return getBindlessTextureMode() || getBindlessImageMode();
}
bool usingVariablePointers() const { return useVariablePointers; }
#ifdef ENABLE_HLSL
@ -1188,7 +1257,8 @@ protected:
TSpirvRequirement* spirvRequirement;
TSpirvExecutionMode* spirvExecutionMode;
std::map<TString, AstRefType> bindlessTextureModeCaller;
std::map<TString, AstRefType> bindlessImageModeCaller;
std::unordered_map<std::string, int> uniformLocationOverrides;
int uniformLocationBase;
TNumericFeatures numericFeatures;

View File

@ -226,6 +226,7 @@ public:
protected:
TMap<TString, TExtensionBehavior> extensionBehavior; // for each extension string, what its current behavior is
TMap<TString, unsigned int> extensionMinSpv; // for each extension string, store minimum spirv required
TVector<TString> spvUnsupportedExt; // for extensions reserved for spv usage.
EShMessages messages; // errors/warnings/rule-sets
int numErrors; // number of compile-time errors encountered
TInputScanner* currentScanner;

View File

@ -291,6 +291,7 @@ INSTANTIATE_TEST_SUITE_P(
"GL_EXT_shader_integer_mix.vert",
"GL_ARB_draw_instanced.vert",
"GL_ARB_fragment_coord_conventions.vert",
"GL_ARB_bindless_texture.frag",
"BestMatchFunction.vert",
"EndStreamPrimitive.geom",
"floatBitsToInt.vert",