Handle buffer references vs 'const'
Allow constructors to and from references to be constant folded. Section 4.3.3 says constructors whose arguments are all constant expressions must fold. Disallow 'const' on buffer reference types. It is not a 'non-void transparent basic data type' (it is not considered 'basic'). Handle buffer reference constants (which can be assigned to a non-const reference, or can be further folded to another type of constant) by converting to 'constructor(uint64_t constant)' in addConversion. Disallow == and != operators on reference types.
This commit is contained in:
parent
d90d548161
commit
be63facd80
76
Test/baseResults/spv.bufferhandle16.frag.out
Normal file
76
Test/baseResults/spv.bufferhandle16.frag.out
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
spv.bufferhandle16.frag
|
||||||
|
// Module Version 10000
|
||||||
|
// Generated by (magic number): 80007
|
||||||
|
// Id's are bound by 37
|
||||||
|
|
||||||
|
Capability Shader
|
||||||
|
Capability Int64
|
||||||
|
Capability CapabilityPhysicalStorageBufferAddressesEXT
|
||||||
|
Extension "SPV_EXT_physical_storage_buffer"
|
||||||
|
1: ExtInstImport "GLSL.std.450"
|
||||||
|
MemoryModel PhysicalStorageBuffer64EXT GLSL450
|
||||||
|
EntryPoint Fragment 4 "main"
|
||||||
|
ExecutionMode 4 OriginUpperLeft
|
||||||
|
Source GLSL 450
|
||||||
|
SourceExtension "GL_EXT_buffer_reference"
|
||||||
|
SourceExtension "GL_EXT_scalar_block_layout"
|
||||||
|
SourceExtension "GL_EXT_shader_explicit_arithmetic_types_int64"
|
||||||
|
Name 4 "main"
|
||||||
|
Name 8 "T1"
|
||||||
|
MemberName 8(T1) 0 "x"
|
||||||
|
Name 10 "a"
|
||||||
|
Name 14 "b"
|
||||||
|
Name 17 "c"
|
||||||
|
Name 23 "d"
|
||||||
|
Name 25 "e"
|
||||||
|
Name 36 "x"
|
||||||
|
MemberDecorate 8(T1) 0 Offset 0
|
||||||
|
Decorate 8(T1) Block
|
||||||
|
Decorate 10(a) DecorationAliasedPointerEXT
|
||||||
|
Decorate 14(b) DecorationAliasedPointerEXT
|
||||||
|
Decorate 17(c) DecorationAliasedPointerEXT
|
||||||
|
Decorate 23(d) DecorationAliasedPointerEXT
|
||||||
|
Decorate 25(e) DecorationAliasedPointerEXT
|
||||||
|
2: TypeVoid
|
||||||
|
3: TypeFunction 2
|
||||||
|
TypeForwardPointer 6 PhysicalStorageBufferEXT
|
||||||
|
7: TypeInt 32 1
|
||||||
|
8(T1): TypeStruct 7(int)
|
||||||
|
6: TypePointer PhysicalStorageBufferEXT 8(T1)
|
||||||
|
9: TypePointer Function 6(ptr)
|
||||||
|
11: TypeInt 64 0
|
||||||
|
12: 11(int64_t) Constant 4 0
|
||||||
|
15: 11(int64_t) Constant 5 0
|
||||||
|
18: TypeBool
|
||||||
|
19: 18(bool) ConstantTrue
|
||||||
|
26: 11(int64_t) Constant 6 0
|
||||||
|
28: 11(int64_t) Constant 7 0
|
||||||
|
31: 7(int) Constant 3
|
||||||
|
32: TypeInt 32 0
|
||||||
|
33: 32(int) Constant 3
|
||||||
|
34: TypeArray 7(int) 33
|
||||||
|
35: TypePointer Private 34
|
||||||
|
36(x): 35(ptr) Variable Private
|
||||||
|
4(main): 2 Function None 3
|
||||||
|
5: Label
|
||||||
|
10(a): 9(ptr) Variable Function
|
||||||
|
14(b): 9(ptr) Variable Function
|
||||||
|
17(c): 9(ptr) Variable Function
|
||||||
|
23(d): 9(ptr) Variable Function
|
||||||
|
25(e): 9(ptr) Variable Function
|
||||||
|
13: 6(ptr) Bitcast 12
|
||||||
|
Store 10(a) 13
|
||||||
|
16: 6(ptr) Bitcast 15
|
||||||
|
Store 14(b) 16
|
||||||
|
20: 6(ptr) Load 10(a)
|
||||||
|
21: 6(ptr) Load 14(b)
|
||||||
|
22: 6(ptr) Select 19 20 21
|
||||||
|
Store 17(c) 22
|
||||||
|
24: 6(ptr) Load 14(b)
|
||||||
|
Store 23(d) 24
|
||||||
|
27: 6(ptr) Bitcast 26
|
||||||
|
29: 6(ptr) Bitcast 28
|
||||||
|
30: 6(ptr) Select 19 27 29
|
||||||
|
Store 25(e) 30
|
||||||
|
Return
|
||||||
|
FunctionEnd
|
9
Test/baseResults/spv.bufferhandle17_Errors.frag.out
Normal file
9
Test/baseResults/spv.bufferhandle17_Errors.frag.out
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
spv.bufferhandle17_Errors.frag
|
||||||
|
ERROR: 0:11: 'qualifier' : variables with reference type can't have qualifier 'const'
|
||||||
|
ERROR: 0:16: 'qualifier' : variables with reference type can't have qualifier 'const'
|
||||||
|
ERROR: 0:18: '==' : can't use with reference types
|
||||||
|
ERROR: 0:19: '!=' : can't use with reference types
|
||||||
|
ERROR: 4 compilation errors. No code generated.
|
||||||
|
|
||||||
|
|
||||||
|
SPIR-V is not generated for failed compile or link
|
23
Test/spv.bufferhandle16.frag
Normal file
23
Test/spv.bufferhandle16.frag
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#version 450
|
||||||
|
|
||||||
|
#extension GL_EXT_shader_explicit_arithmetic_types_int64 : enable
|
||||||
|
#extension GL_EXT_buffer_reference : enable
|
||||||
|
#extension GL_EXT_scalar_block_layout : enable
|
||||||
|
|
||||||
|
layout(buffer_reference) buffer T1 {
|
||||||
|
int x;
|
||||||
|
};
|
||||||
|
layout(buffer_reference) buffer T2 {
|
||||||
|
int x;
|
||||||
|
};
|
||||||
|
|
||||||
|
const int s = int(uint64_t(T1(T2(uint64_t(3)))));
|
||||||
|
int x[s];
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
T1 a = T1(uint64_t(4)), b = T1(uint64_t(5));
|
||||||
|
T1 c = true ? a : b;
|
||||||
|
T1 d = (a,b);
|
||||||
|
T1 e = true ? T1(uint64_t(6)) : T1(uint64_t(7));
|
||||||
|
}
|
20
Test/spv.bufferhandle17_Errors.frag
Normal file
20
Test/spv.bufferhandle17_Errors.frag
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#version 450
|
||||||
|
|
||||||
|
#extension GL_EXT_shader_explicit_arithmetic_types_int64 : enable
|
||||||
|
#extension GL_EXT_buffer_reference : enable
|
||||||
|
#extension GL_EXT_scalar_block_layout : enable
|
||||||
|
|
||||||
|
layout(buffer_reference) buffer T1 {
|
||||||
|
int x;
|
||||||
|
};
|
||||||
|
|
||||||
|
const T1 a = T1(uint64_t(2));
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
T1 b, c;
|
||||||
|
const T1 d = b;
|
||||||
|
|
||||||
|
b == c;
|
||||||
|
b != c;
|
||||||
|
}
|
@ -1628,6 +1628,7 @@ public:
|
|||||||
case EbtInt64:
|
case EbtInt64:
|
||||||
case EbtUint64:
|
case EbtUint64:
|
||||||
case EbtBool:
|
case EbtBool:
|
||||||
|
case EbtReference:
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
@ -941,6 +941,10 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TType& returnType)
|
|||||||
newConstArray[i].setDConst(unionArray[i].getDConst()); break;
|
newConstArray[i].setDConst(unionArray[i].getDConst()); break;
|
||||||
case EOpConvDoubleToFloat:
|
case EOpConvDoubleToFloat:
|
||||||
newConstArray[i].setDConst(unionArray[i].getDConst()); break;
|
newConstArray[i].setDConst(unionArray[i].getDConst()); break;
|
||||||
|
case EOpConvPtrToUint64:
|
||||||
|
case EOpConvUint64ToPtr:
|
||||||
|
case EOpConstructReference:
|
||||||
|
newConstArray[i].setU64Const(unionArray[i].getU64Const()); break;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -725,6 +725,19 @@ TIntermTyped* TIntermediate::createConversion(TBasicType convertTo, TIntermTyped
|
|||||||
return newNode;
|
return newNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Convert a constant that is a reference type to a uint64_t constant plus a
|
||||||
|
// constructor instruction. This is needed because SPIR-V doesn't support
|
||||||
|
// OpConstant on pointer types.
|
||||||
|
TIntermTyped* TIntermediate::addConstantReferenceConversion(TIntermTyped* node)
|
||||||
|
{
|
||||||
|
if (node->getType().getBasicType() == EbtReference && node->getAsConstantUnion()) {
|
||||||
|
const TType &type = node->getType();
|
||||||
|
node = addBuiltInFunctionCall(node->getLoc(), EOpConvPtrToUint64, true, node, TType(EbtUint64));
|
||||||
|
node = addUnaryNode(EOpConstructReference, node, node->getLoc(), type);
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
TIntermTyped* TIntermediate::addConversion(TBasicType convertTo, TIntermTyped* node) const
|
TIntermTyped* TIntermediate::addConversion(TBasicType convertTo, TIntermTyped* node) const
|
||||||
{
|
{
|
||||||
return createConversion(convertTo, node);
|
return createConversion(convertTo, node);
|
||||||
@ -743,7 +756,7 @@ TIntermTyped* TIntermediate::addConversion(TBasicType convertTo, TIntermTyped* n
|
|||||||
// Returns the converted pair of nodes.
|
// Returns the converted pair of nodes.
|
||||||
// Returns <nullptr, nullptr> when there is no conversion.
|
// Returns <nullptr, nullptr> when there is no conversion.
|
||||||
std::tuple<TIntermTyped*, TIntermTyped*>
|
std::tuple<TIntermTyped*, TIntermTyped*>
|
||||||
TIntermediate::addConversion(TOperator op, TIntermTyped* node0, TIntermTyped* node1) const
|
TIntermediate::addConversion(TOperator op, TIntermTyped* node0, TIntermTyped* node1)
|
||||||
{
|
{
|
||||||
if (!isConversionAllowed(op, node0) || !isConversionAllowed(op, node1))
|
if (!isConversionAllowed(op, node0) || !isConversionAllowed(op, node1))
|
||||||
return std::make_tuple(nullptr, nullptr);
|
return std::make_tuple(nullptr, nullptr);
|
||||||
@ -762,6 +775,9 @@ TIntermediate::addConversion(TOperator op, TIntermTyped* node0, TIntermTyped* no
|
|||||||
return std::make_tuple(node0, node1);
|
return std::make_tuple(node0, node1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
node0 = addConstantReferenceConversion(node0);
|
||||||
|
node1 = addConstantReferenceConversion(node1);
|
||||||
|
|
||||||
auto promoteTo = std::make_tuple(EbtNumTypes, EbtNumTypes);
|
auto promoteTo = std::make_tuple(EbtNumTypes, EbtNumTypes);
|
||||||
|
|
||||||
switch (op) {
|
switch (op) {
|
||||||
@ -876,11 +892,13 @@ TIntermediate::addConversion(TOperator op, TIntermTyped* node0, TIntermTyped* no
|
|||||||
//
|
//
|
||||||
// Return nullptr if a conversion can't be done.
|
// Return nullptr if a conversion can't be done.
|
||||||
//
|
//
|
||||||
TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TIntermTyped* node) const
|
TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TIntermTyped* node)
|
||||||
{
|
{
|
||||||
if (!isConversionAllowed(op, node))
|
if (!isConversionAllowed(op, node))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
node = addConstantReferenceConversion(node);
|
||||||
|
|
||||||
// Otherwise, if types are identical, no problem
|
// Otherwise, if types are identical, no problem
|
||||||
if (type == node->getType())
|
if (type == node->getType())
|
||||||
return node;
|
return node;
|
||||||
|
@ -4435,6 +4435,12 @@ void TParseContext::opaqueCheck(const TSourceLoc& loc, const TType& type, const
|
|||||||
error(loc, "can't use with samplers or structs containing samplers", op, "");
|
error(loc, "can't use with samplers or structs containing samplers", op, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TParseContext::referenceCheck(const TSourceLoc& loc, const TType& type, const char* op)
|
||||||
|
{
|
||||||
|
if (containsFieldWithBasicType(type, EbtReference))
|
||||||
|
error(loc, "can't use with reference types", op, "");
|
||||||
|
}
|
||||||
|
|
||||||
void TParseContext::storage16BitAssignmentCheck(const TSourceLoc& loc, const TType& type, const char* op)
|
void TParseContext::storage16BitAssignmentCheck(const TSourceLoc& loc, const TType& type, const char* op)
|
||||||
{
|
{
|
||||||
if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtFloat16))
|
if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtFloat16))
|
||||||
@ -6290,6 +6296,9 @@ TIntermNode* TParseContext::declareVariable(const TSourceLoc& loc, TString& iden
|
|||||||
#ifdef NV_EXTENSIONS
|
#ifdef NV_EXTENSIONS
|
||||||
accStructNVCheck(loc, type, identifier);
|
accStructNVCheck(loc, type, identifier);
|
||||||
#endif
|
#endif
|
||||||
|
if (type.getQualifier().storage == EvqConst && type.containsBasicType(EbtReference)) {
|
||||||
|
error(loc, "variables with reference type can't have qualifier 'const'", "qualifier", "");
|
||||||
|
}
|
||||||
|
|
||||||
if (type.getQualifier().storage != EvqUniform && type.getQualifier().storage != EvqBuffer) {
|
if (type.getQualifier().storage != EvqUniform && type.getQualifier().storage != EvqBuffer) {
|
||||||
if (type.containsBasicType(EbtFloat16))
|
if (type.containsBasicType(EbtFloat16))
|
||||||
@ -6518,7 +6527,11 @@ TIntermNode* TParseContext::executeInitializer(const TSourceLoc& loc, TIntermTyp
|
|||||||
// We either have a folded constant in getAsConstantUnion, or we have to use
|
// We either have a folded constant in getAsConstantUnion, or we have to use
|
||||||
// the initializer's subtree in the AST to represent the computation of a
|
// the initializer's subtree in the AST to represent the computation of a
|
||||||
// specialization constant.
|
// specialization constant.
|
||||||
assert(initializer->getAsConstantUnion() || initializer->getType().getQualifier().isSpecConstant());
|
// A third case arises when a reference type is made non-constant due to
|
||||||
|
// addConstantReferenceConversion, but reference types can't be const, so
|
||||||
|
// this is an error.
|
||||||
|
assert(initializer->getAsConstantUnion() || initializer->getType().getQualifier().isSpecConstant() ||
|
||||||
|
initializer->getType().getBasicType() == EbtReference);
|
||||||
if (initializer->getAsConstantUnion())
|
if (initializer->getAsConstantUnion())
|
||||||
variable->setConstArray(initializer->getAsConstantUnion()->getConstArray());
|
variable->setConstArray(initializer->getAsConstantUnion()->getConstArray());
|
||||||
else {
|
else {
|
||||||
@ -6860,7 +6873,7 @@ TIntermTyped* TParseContext::constructBuiltIn(const TType& type, TOperator op, T
|
|||||||
|
|
||||||
case EOpConstructUint64:
|
case EOpConstructUint64:
|
||||||
if (type.isScalar() && node->getType().getBasicType() == EbtReference) {
|
if (type.isScalar() && node->getType().getBasicType() == EbtReference) {
|
||||||
TIntermUnary* newNode = intermediate.addUnaryNode(EOpConvPtrToUint64, node, node->getLoc(), type);
|
TIntermTyped* newNode = intermediate.addBuiltInFunctionCall(node->getLoc(), EOpConvPtrToUint64, true, node, type);
|
||||||
return newNode;
|
return newNode;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
@ -6885,11 +6898,11 @@ TIntermTyped* TParseContext::constructBuiltIn(const TType& type, TOperator op, T
|
|||||||
case EOpConstructReference:
|
case EOpConstructReference:
|
||||||
// construct reference from reference
|
// construct reference from reference
|
||||||
if (node->getType().getBasicType() == EbtReference) {
|
if (node->getType().getBasicType() == EbtReference) {
|
||||||
newNode = intermediate.addUnaryNode(EOpConstructReference, node, node->getLoc(), type);
|
newNode = intermediate.addBuiltInFunctionCall(node->getLoc(), EOpConstructReference, true, node, type);
|
||||||
return newNode;
|
return newNode;
|
||||||
// construct reference from uint64
|
// construct reference from uint64
|
||||||
} else if (node->getType().isScalar() && node->getType().getBasicType() == EbtUint64) {
|
} else if (node->getType().isScalar() && node->getType().getBasicType() == EbtUint64) {
|
||||||
TIntermUnary* newNode = intermediate.addUnaryNode(EOpConvUint64ToPtr, node, node->getLoc(), type);
|
TIntermTyped* newNode = intermediate.addBuiltInFunctionCall(node->getLoc(), EOpConvUint64ToPtr, true, node, type);
|
||||||
return newNode;
|
return newNode;
|
||||||
} else {
|
} else {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -370,6 +370,7 @@ public:
|
|||||||
void nestedStructCheck(const TSourceLoc&);
|
void nestedStructCheck(const TSourceLoc&);
|
||||||
void arrayObjectCheck(const TSourceLoc&, const TType&, const char* op);
|
void arrayObjectCheck(const TSourceLoc&, const TType&, const char* op);
|
||||||
void opaqueCheck(const TSourceLoc&, const TType&, const char* op);
|
void opaqueCheck(const TSourceLoc&, const TType&, const char* op);
|
||||||
|
void referenceCheck(const TSourceLoc&, const TType&, const char* op);
|
||||||
void storage16BitAssignmentCheck(const TSourceLoc&, const TType&, const char* op);
|
void storage16BitAssignmentCheck(const TSourceLoc&, const TType&, const char* op);
|
||||||
void specializationCheck(const TSourceLoc&, const TType&, const char* op);
|
void specializationCheck(const TSourceLoc&, const TType&, const char* op);
|
||||||
void structTypeCheck(const TSourceLoc&, TPublicType&);
|
void structTypeCheck(const TSourceLoc&, TPublicType&);
|
||||||
|
@ -613,6 +613,7 @@ equality_expression
|
|||||||
parseContext.arrayObjectCheck($2.loc, $1->getType(), "array comparison");
|
parseContext.arrayObjectCheck($2.loc, $1->getType(), "array comparison");
|
||||||
parseContext.opaqueCheck($2.loc, $1->getType(), "==");
|
parseContext.opaqueCheck($2.loc, $1->getType(), "==");
|
||||||
parseContext.specializationCheck($2.loc, $1->getType(), "==");
|
parseContext.specializationCheck($2.loc, $1->getType(), "==");
|
||||||
|
parseContext.referenceCheck($2.loc, $1->getType(), "==");
|
||||||
$$ = parseContext.handleBinaryMath($2.loc, "==", EOpEqual, $1, $3);
|
$$ = parseContext.handleBinaryMath($2.loc, "==", EOpEqual, $1, $3);
|
||||||
if ($$ == 0)
|
if ($$ == 0)
|
||||||
$$ = parseContext.intermediate.addConstantUnion(false, $2.loc);
|
$$ = parseContext.intermediate.addConstantUnion(false, $2.loc);
|
||||||
@ -621,6 +622,7 @@ equality_expression
|
|||||||
parseContext.arrayObjectCheck($2.loc, $1->getType(), "array comparison");
|
parseContext.arrayObjectCheck($2.loc, $1->getType(), "array comparison");
|
||||||
parseContext.opaqueCheck($2.loc, $1->getType(), "!=");
|
parseContext.opaqueCheck($2.loc, $1->getType(), "!=");
|
||||||
parseContext.specializationCheck($2.loc, $1->getType(), "!=");
|
parseContext.specializationCheck($2.loc, $1->getType(), "!=");
|
||||||
|
parseContext.referenceCheck($2.loc, $1->getType(), "!=");
|
||||||
$$ = parseContext.handleBinaryMath($2.loc, "!=", EOpNotEqual, $1, $3);
|
$$ = parseContext.handleBinaryMath($2.loc, "!=", EOpNotEqual, $1, $3);
|
||||||
if ($$ == 0)
|
if ($$ == 0)
|
||||||
$$ = parseContext.intermediate.addConstantUnion(false, $2.loc);
|
$$ = parseContext.intermediate.addConstantUnion(false, $2.loc);
|
||||||
|
File diff suppressed because it is too large
Load Diff
5
glslang/MachineIndependent/localintermediate.h
Executable file → Normal file
5
glslang/MachineIndependent/localintermediate.h
Executable file → Normal file
@ -495,12 +495,13 @@ public:
|
|||||||
TIntermSymbol* addSymbol(const TVariable&, const TSourceLoc&);
|
TIntermSymbol* addSymbol(const TVariable&, const TSourceLoc&);
|
||||||
TIntermSymbol* addSymbol(const TType&, const TSourceLoc&);
|
TIntermSymbol* addSymbol(const TType&, const TSourceLoc&);
|
||||||
TIntermSymbol* addSymbol(const TIntermSymbol&);
|
TIntermSymbol* addSymbol(const TIntermSymbol&);
|
||||||
TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*) const;
|
TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*);
|
||||||
std::tuple<TIntermTyped*, TIntermTyped*> addConversion(TOperator op, TIntermTyped* node0, TIntermTyped* node1) const;
|
std::tuple<TIntermTyped*, TIntermTyped*> addConversion(TOperator op, TIntermTyped* node0, TIntermTyped* node1);
|
||||||
TIntermTyped* addUniShapeConversion(TOperator, const TType&, TIntermTyped*);
|
TIntermTyped* addUniShapeConversion(TOperator, const TType&, TIntermTyped*);
|
||||||
TIntermTyped* addConversion(TBasicType convertTo, TIntermTyped* node) const;
|
TIntermTyped* addConversion(TBasicType convertTo, TIntermTyped* node) const;
|
||||||
void addBiShapeConversion(TOperator, TIntermTyped*& lhsNode, TIntermTyped*& rhsNode);
|
void addBiShapeConversion(TOperator, TIntermTyped*& lhsNode, TIntermTyped*& rhsNode);
|
||||||
TIntermTyped* addShapeConversion(const TType&, TIntermTyped*);
|
TIntermTyped* addShapeConversion(const TType&, TIntermTyped*);
|
||||||
|
TIntermTyped* addConstantReferenceConversion(TIntermTyped* node);
|
||||||
TIntermTyped* addBinaryMath(TOperator, TIntermTyped* left, TIntermTyped* right, TSourceLoc);
|
TIntermTyped* addBinaryMath(TOperator, TIntermTyped* left, TIntermTyped* right, TSourceLoc);
|
||||||
TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc);
|
TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc);
|
||||||
TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc);
|
TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc);
|
||||||
|
@ -272,6 +272,8 @@ INSTANTIATE_TEST_CASE_P(
|
|||||||
"spv.bufferhandle13.frag",
|
"spv.bufferhandle13.frag",
|
||||||
"spv.bufferhandle14.frag",
|
"spv.bufferhandle14.frag",
|
||||||
"spv.bufferhandle15.frag",
|
"spv.bufferhandle15.frag",
|
||||||
|
"spv.bufferhandle16.frag",
|
||||||
|
"spv.bufferhandle17_Errors.frag",
|
||||||
"spv.bufferhandle2.frag",
|
"spv.bufferhandle2.frag",
|
||||||
"spv.bufferhandle3.frag",
|
"spv.bufferhandle3.frag",
|
||||||
"spv.bufferhandle4.frag",
|
"spv.bufferhandle4.frag",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user