Merge pull request #211 from Qining/spec-constants-composite
SPV: Support specialization composite constants.
This commit is contained in:
commit
c3869fee41
@ -128,8 +128,9 @@ protected:
|
|||||||
void addDecoration(spv::Id id, spv::Decoration dec, unsigned value);
|
void addDecoration(spv::Id id, spv::Decoration dec, unsigned value);
|
||||||
void addMemberDecoration(spv::Id id, int member, spv::Decoration dec);
|
void addMemberDecoration(spv::Id id, int member, spv::Decoration dec);
|
||||||
void addMemberDecoration(spv::Id id, int member, spv::Decoration dec, unsigned value);
|
void addMemberDecoration(spv::Id id, int member, spv::Decoration dec, unsigned value);
|
||||||
spv::Id createSpvSpecConstant(const glslang::TIntermTyped&);
|
spv::Id createSpvConstant(const glslang::TIntermTyped&);
|
||||||
spv::Id createSpvConstant(const glslang::TType& type, const glslang::TConstUnionArray&, int& nextConst, bool specConstant);
|
spv::Id createSpvConstantFromConstUnionArray(const glslang::TType& type, const glslang::TConstUnionArray&, int& nextConst, bool specConstant);
|
||||||
|
spv::Id createSpvConstantFromConstSubTree(const glslang::TIntermTyped* subTree);
|
||||||
bool isTrivialLeaf(const glslang::TIntermTyped* node);
|
bool isTrivialLeaf(const glslang::TIntermTyped* node);
|
||||||
bool isTrivial(const glslang::TIntermTyped* node);
|
bool isTrivial(const glslang::TIntermTyped* node);
|
||||||
spv::Id createShortCircuit(glslang::TOperator, glslang::TIntermTyped& left, glslang::TIntermTyped& right);
|
spv::Id createShortCircuit(glslang::TOperator, glslang::TIntermTyped& left, glslang::TIntermTyped& right);
|
||||||
@ -1520,7 +1521,7 @@ bool TGlslangToSpvTraverser::visitSwitch(glslang::TVisit /* visit */, glslang::T
|
|||||||
void TGlslangToSpvTraverser::visitConstantUnion(glslang::TIntermConstantUnion* node)
|
void TGlslangToSpvTraverser::visitConstantUnion(glslang::TIntermConstantUnion* node)
|
||||||
{
|
{
|
||||||
int nextConst = 0;
|
int nextConst = 0;
|
||||||
spv::Id constant = createSpvConstant(node->getType(), node->getConstArray(), nextConst, false);
|
spv::Id constant = createSpvConstantFromConstUnionArray(node->getType(), node->getConstArray(), nextConst, false);
|
||||||
|
|
||||||
builder.clearAccessChain();
|
builder.clearAccessChain();
|
||||||
builder.setAccessChainRValue(constant);
|
builder.setAccessChainRValue(constant);
|
||||||
@ -1630,7 +1631,7 @@ spv::Id TGlslangToSpvTraverser::createSpvVariable(const glslang::TIntermSymbol*
|
|||||||
// can still have a mapping to a SPIR-V Id.
|
// can still have a mapping to a SPIR-V Id.
|
||||||
// This includes specialization constants.
|
// This includes specialization constants.
|
||||||
if (node->getQualifier().isConstant()) {
|
if (node->getQualifier().isConstant()) {
|
||||||
return createSpvSpecConstant(*node);
|
return createSpvConstant(*node);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now, handle actual variables
|
// Now, handle actual variables
|
||||||
@ -3730,7 +3731,7 @@ void TGlslangToSpvTraverser::addMemberDecoration(spv::Id id, int member, spv::De
|
|||||||
// recursively walks. So, this function walks the "top" of the tree:
|
// recursively walks. So, this function walks the "top" of the tree:
|
||||||
// - emit specialization constant-building instructions for specConstant
|
// - emit specialization constant-building instructions for specConstant
|
||||||
// - when running into a non-spec-constant, switch to createSpvConstant()
|
// - when running into a non-spec-constant, switch to createSpvConstant()
|
||||||
spv::Id TGlslangToSpvTraverser::createSpvSpecConstant(const glslang::TIntermTyped& node)
|
spv::Id TGlslangToSpvTraverser::createSpvConstant(const glslang::TIntermTyped& node)
|
||||||
{
|
{
|
||||||
assert(node.getQualifier().isConstant());
|
assert(node.getQualifier().isConstant());
|
||||||
|
|
||||||
@ -3738,7 +3739,7 @@ spv::Id TGlslangToSpvTraverser::createSpvSpecConstant(const glslang::TIntermType
|
|||||||
// hand off to the non-spec-constant path
|
// hand off to the non-spec-constant path
|
||||||
assert(node.getAsConstantUnion() != nullptr || node.getAsSymbolNode() != nullptr);
|
assert(node.getAsConstantUnion() != nullptr || node.getAsSymbolNode() != nullptr);
|
||||||
int nextConst = 0;
|
int nextConst = 0;
|
||||||
return createSpvConstant(node.getType(), node.getAsConstantUnion() ? node.getAsConstantUnion()->getConstArray() : node.getAsSymbolNode()->getConstArray(),
|
return createSpvConstantFromConstUnionArray(node.getType(), node.getAsConstantUnion() ? node.getAsConstantUnion()->getConstArray() : node.getAsSymbolNode()->getConstArray(),
|
||||||
nextConst, false);
|
nextConst, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3747,7 +3748,7 @@ spv::Id TGlslangToSpvTraverser::createSpvSpecConstant(const glslang::TIntermType
|
|||||||
if (node.getAsSymbolNode() && node.getQualifier().hasSpecConstantId()) {
|
if (node.getAsSymbolNode() && node.getQualifier().hasSpecConstantId()) {
|
||||||
// this is a direct literal assigned to a layout(constant_id=) declaration
|
// this is a direct literal assigned to a layout(constant_id=) declaration
|
||||||
int nextConst = 0;
|
int nextConst = 0;
|
||||||
return createSpvConstant(node.getType(), node.getAsConstantUnion() ? node.getAsConstantUnion()->getConstArray() : node.getAsSymbolNode()->getConstArray(),
|
return createSpvConstantFromConstUnionArray(node.getType(), node.getAsConstantUnion() ? node.getAsConstantUnion()->getConstArray() : node.getAsSymbolNode()->getConstArray(),
|
||||||
nextConst, true);
|
nextConst, true);
|
||||||
} else {
|
} else {
|
||||||
// gl_WorkgroupSize is a special case until the front-end handles hierarchical specialization constants,
|
// gl_WorkgroupSize is a special case until the front-end handles hierarchical specialization constants,
|
||||||
@ -3761,8 +3762,10 @@ spv::Id TGlslangToSpvTraverser::createSpvSpecConstant(const glslang::TIntermType
|
|||||||
addDecoration(dimConstId.back(), spv::DecorationSpecId, glslangIntermediate->getLocalSizeSpecId(dim));
|
addDecoration(dimConstId.back(), spv::DecorationSpecId, glslangIntermediate->getLocalSizeSpecId(dim));
|
||||||
}
|
}
|
||||||
return builder.makeCompositeConstant(builder.makeVectorType(builder.makeUintType(32), 3), dimConstId, true);
|
return builder.makeCompositeConstant(builder.makeVectorType(builder.makeUintType(32), 3), dimConstId, true);
|
||||||
|
} else if (auto* sn = node.getAsSymbolNode()){
|
||||||
|
return createSpvConstantFromConstSubTree(sn->getConstSubtree());
|
||||||
} else {
|
} else {
|
||||||
spv::MissingFunctionality("specialization-constant expression trees");
|
spv::MissingFunctionality("Neither a front-end constant nor a spec constant.");
|
||||||
exit(1);
|
exit(1);
|
||||||
return spv::NoResult;
|
return spv::NoResult;
|
||||||
}
|
}
|
||||||
@ -3775,7 +3778,7 @@ spv::Id TGlslangToSpvTraverser::createSpvSpecConstant(const glslang::TIntermType
|
|||||||
// If there are not enough elements present in 'consts', 0 will be substituted;
|
// If there are not enough elements present in 'consts', 0 will be substituted;
|
||||||
// an empty 'consts' can be used to create a fully zeroed SPIR-V constant.
|
// an empty 'consts' can be used to create a fully zeroed SPIR-V constant.
|
||||||
//
|
//
|
||||||
spv::Id TGlslangToSpvTraverser::createSpvConstant(const glslang::TType& glslangType, const glslang::TConstUnionArray& consts, int& nextConst, bool specConstant)
|
spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstUnionArray(const glslang::TType& glslangType, const glslang::TConstUnionArray& consts, int& nextConst, bool specConstant)
|
||||||
{
|
{
|
||||||
// vector of constants for SPIR-V
|
// vector of constants for SPIR-V
|
||||||
std::vector<spv::Id> spvConsts;
|
std::vector<spv::Id> spvConsts;
|
||||||
@ -3786,15 +3789,15 @@ spv::Id TGlslangToSpvTraverser::createSpvConstant(const glslang::TType& glslangT
|
|||||||
if (glslangType.isArray()) {
|
if (glslangType.isArray()) {
|
||||||
glslang::TType elementType(glslangType, 0);
|
glslang::TType elementType(glslangType, 0);
|
||||||
for (int i = 0; i < glslangType.getOuterArraySize(); ++i)
|
for (int i = 0; i < glslangType.getOuterArraySize(); ++i)
|
||||||
spvConsts.push_back(createSpvConstant(elementType, consts, nextConst, false));
|
spvConsts.push_back(createSpvConstantFromConstUnionArray(elementType, consts, nextConst, false));
|
||||||
} else if (glslangType.isMatrix()) {
|
} else if (glslangType.isMatrix()) {
|
||||||
glslang::TType vectorType(glslangType, 0);
|
glslang::TType vectorType(glslangType, 0);
|
||||||
for (int col = 0; col < glslangType.getMatrixCols(); ++col)
|
for (int col = 0; col < glslangType.getMatrixCols(); ++col)
|
||||||
spvConsts.push_back(createSpvConstant(vectorType, consts, nextConst, false));
|
spvConsts.push_back(createSpvConstantFromConstUnionArray(vectorType, consts, nextConst, false));
|
||||||
} else if (glslangType.getStruct()) {
|
} else if (glslangType.getStruct()) {
|
||||||
glslang::TVector<glslang::TTypeLoc>::const_iterator iter;
|
glslang::TVector<glslang::TTypeLoc>::const_iterator iter;
|
||||||
for (iter = glslangType.getStruct()->begin(); iter != glslangType.getStruct()->end(); ++iter)
|
for (iter = glslangType.getStruct()->begin(); iter != glslangType.getStruct()->end(); ++iter)
|
||||||
spvConsts.push_back(createSpvConstant(*iter->type, consts, nextConst, false));
|
spvConsts.push_back(createSpvConstantFromConstUnionArray(*iter->type, consts, nextConst, false));
|
||||||
} else if (glslangType.isVector()) {
|
} else if (glslangType.isVector()) {
|
||||||
for (unsigned int i = 0; i < (unsigned int)glslangType.getVectorSize(); ++i) {
|
for (unsigned int i = 0; i < (unsigned int)glslangType.getVectorSize(); ++i) {
|
||||||
bool zero = nextConst >= consts.size();
|
bool zero = nextConst >= consts.size();
|
||||||
@ -3851,6 +3854,66 @@ spv::Id TGlslangToSpvTraverser::createSpvConstant(const glslang::TType& glslangT
|
|||||||
return builder.makeCompositeConstant(typeId, spvConsts);
|
return builder.makeCompositeConstant(typeId, spvConsts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create constant ID from const initializer sub tree.
|
||||||
|
spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstSubTree(
|
||||||
|
const glslang::TIntermTyped* subTree) {
|
||||||
|
const glslang::TType& glslangType = subTree->getType();
|
||||||
|
spv::Id typeId = convertGlslangToSpvType(glslangType);
|
||||||
|
bool is_spec_const = subTree->getType().getQualifier().isSpecConstant();
|
||||||
|
if (const glslang::TIntermAggregate* an = subTree->getAsAggregate()) {
|
||||||
|
// Aggregate node, we should generate OpConstantComposite or
|
||||||
|
// OpSpecConstantComposite instruction.
|
||||||
|
std::vector<spv::Id> const_constituents;
|
||||||
|
for (auto NI = an->getSequence().begin(); NI != an->getSequence().end();
|
||||||
|
NI++) {
|
||||||
|
const_constituents.push_back(
|
||||||
|
createSpvConstantFromConstSubTree((*NI)->getAsTyped()));
|
||||||
|
}
|
||||||
|
// Note that constructors are aggregate nodes, so expressions like:
|
||||||
|
// float x = float(y) will become an aggregate node. If 'x' is declared
|
||||||
|
// as a constant, the aggregate node representing 'float(y)' will be
|
||||||
|
// processed here.
|
||||||
|
if (builder.isVectorType(typeId) || builder.isMatrixType(typeId) ||
|
||||||
|
builder.isAggregateType(typeId)) {
|
||||||
|
return builder.makeCompositeConstant(typeId, const_constituents, is_spec_const);
|
||||||
|
} else {
|
||||||
|
assert(builder.isScalarType(typeId) && const_constituents.size() == 1);
|
||||||
|
return const_constituents.front();
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (const glslang::TIntermBinary* bn = subTree->getAsBinaryNode()) {
|
||||||
|
// Binary operation node, we should generate OpSpecConstantOp <binary op>
|
||||||
|
// This case should only happen when Specialization Constants are involved.
|
||||||
|
spv::MissingFunctionality("OpSpecConstantOp <binary op> not implemented");
|
||||||
|
return spv::NoResult;
|
||||||
|
|
||||||
|
} else if (const glslang::TIntermUnary* un = subTree->getAsUnaryNode()) {
|
||||||
|
// Unary operation node, similar to binary operation node, should only
|
||||||
|
// happen when specialization constants are involved.
|
||||||
|
spv::MissingFunctionality("OpSpecConstantOp <unary op> not implemented");
|
||||||
|
return spv::NoResult;
|
||||||
|
|
||||||
|
} else if (const glslang::TIntermConstantUnion* cn = subTree->getAsConstantUnion()) {
|
||||||
|
// ConstantUnion node, should redirect to
|
||||||
|
// createSpvConstantFromConstUnionArray
|
||||||
|
int nextConst = 0;
|
||||||
|
return createSpvConstantFromConstUnionArray(
|
||||||
|
glslangType, cn->getConstArray(), nextConst, is_spec_const);
|
||||||
|
|
||||||
|
} else if (const glslang::TIntermSymbol* sn = subTree->getAsSymbolNode()) {
|
||||||
|
// Symbol node. Call getSymbolId(). This should cover both cases 1) the
|
||||||
|
// symbol has already been assigned an ID, 2) need a new ID for this
|
||||||
|
// symbol.
|
||||||
|
return getSymbolId(sn);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
spv::MissingFunctionality(
|
||||||
|
"createSpvConstantFromConstSubTree() not covered TIntermTyped* const "
|
||||||
|
"initializer subtree.");
|
||||||
|
return spv::NoResult;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Return true if the node is a constant or symbol whose reading has no
|
// Return true if the node is a constant or symbol whose reading has no
|
||||||
// non-trivial observable cost or effect.
|
// non-trivial observable cost or effect.
|
||||||
bool TGlslangToSpvTraverser::isTrivialLeaf(const glslang::TIntermTyped* node)
|
bool TGlslangToSpvTraverser::isTrivialLeaf(const glslang::TIntermTyped* node)
|
||||||
|
172
Test/baseResults/spv.specConstantComposite.vert.out
Normal file
172
Test/baseResults/spv.specConstantComposite.vert.out
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
spv.specConstantComposite.vert
|
||||||
|
Warning, version 450 is not yet complete; most version-specific features are present, but some are missing.
|
||||||
|
|
||||||
|
|
||||||
|
Linked vertex stage:
|
||||||
|
|
||||||
|
|
||||||
|
// Module Version 10000
|
||||||
|
// Generated by (magic number): 80001
|
||||||
|
// Id's are bound by 106
|
||||||
|
|
||||||
|
Capability Shader
|
||||||
|
Capability Float64
|
||||||
|
1: ExtInstImport "GLSL.std.450"
|
||||||
|
MemoryModel Logical GLSL450
|
||||||
|
EntryPoint Vertex 4 "main" 27 105
|
||||||
|
Source GLSL 450
|
||||||
|
Name 4 "main"
|
||||||
|
Name 6 "refer_primary_spec_const("
|
||||||
|
Name 8 "refer_composite_spec_const("
|
||||||
|
Name 10 "refer_copmosite_dot_dereference("
|
||||||
|
Name 12 "refer_composite_bracket_dereference("
|
||||||
|
Name 16 "refer_spec_const_array_length("
|
||||||
|
Name 18 "declare_spec_const_in_func("
|
||||||
|
Name 27 "color"
|
||||||
|
Name 41 "flat_struct"
|
||||||
|
MemberName 41(flat_struct) 0 "i"
|
||||||
|
MemberName 41(flat_struct) 1 "f"
|
||||||
|
MemberName 41(flat_struct) 2 "d"
|
||||||
|
MemberName 41(flat_struct) 3 "b"
|
||||||
|
Name 42 "nesting_struct"
|
||||||
|
MemberName 42(nesting_struct) 0 "nested"
|
||||||
|
MemberName 42(nesting_struct) 1 "v"
|
||||||
|
MemberName 42(nesting_struct) 2 "i"
|
||||||
|
Name 72 "indexable"
|
||||||
|
Name 76 "indexable"
|
||||||
|
Name 83 "len"
|
||||||
|
Name 105 "global_vec4_array_with_spec_length"
|
||||||
|
Decorate 21 SpecId 203
|
||||||
|
Decorate 28 SpecId 200
|
||||||
|
Decorate 32 SpecId 201
|
||||||
|
Decorate 43 SpecId 202
|
||||||
|
2: TypeVoid
|
||||||
|
3: TypeFunction 2
|
||||||
|
14: TypeInt 32 1
|
||||||
|
15: TypeFunction 14(int)
|
||||||
|
20: TypeBool
|
||||||
|
21: 20(bool) SpecConstantTrue
|
||||||
|
24: TypeFloat 32
|
||||||
|
25: TypeVector 24(float) 4
|
||||||
|
26: TypePointer Output 25(fvec4)
|
||||||
|
27(color): 26(ptr) Variable Output
|
||||||
|
28: 14(int) SpecConstant 3
|
||||||
|
32: 24(float) SpecConstant 1078523331
|
||||||
|
33: 25(fvec4) SpecConstantComposite 32 32 32 32
|
||||||
|
36: 24(float) Constant 1133908460
|
||||||
|
37: 25(fvec4) SpecConstantComposite 32 32 36 36
|
||||||
|
40: TypeFloat 64
|
||||||
|
41(flat_struct): TypeStruct 14(int) 24(float) 40(float) 20(bool)
|
||||||
|
42(nesting_struct): TypeStruct 41(flat_struct) 25(fvec4) 14(int)
|
||||||
|
43: 40(float) SpecConstant 1413754136 1074340347
|
||||||
|
44:41(flat_struct) SpecConstantComposite 28 32 43 21
|
||||||
|
45:42(nesting_struct) SpecConstantComposite 44 33 28
|
||||||
|
46: 14(int) Constant 2
|
||||||
|
51: TypeInt 32 0
|
||||||
|
52: 51(int) Constant 0
|
||||||
|
57: 51(int) Constant 5
|
||||||
|
58: TypeArray 24(float) 57
|
||||||
|
59: 24(float) Constant 1065353216
|
||||||
|
60: 24(float) Constant 1073741824
|
||||||
|
61: 24(float) Constant 1077936128
|
||||||
|
62: 58 SpecConstantComposite 32 32 59 60 61
|
||||||
|
63: 14(int) Constant 1
|
||||||
|
68: TypeArray 14(int) 57
|
||||||
|
69: 14(int) Constant 30
|
||||||
|
70: 68 SpecConstantComposite 28 28 63 46 69
|
||||||
|
71: TypePointer Function 68
|
||||||
|
73: TypePointer Function 14(int)
|
||||||
|
87: 24(float) Constant 1106321080
|
||||||
|
88:41(flat_struct) SpecConstantComposite 69 87 43 21
|
||||||
|
89: 14(int) Constant 10
|
||||||
|
90:42(nesting_struct) SpecConstantComposite 88 37 89
|
||||||
|
96: 20(bool) ConstantFalse
|
||||||
|
97:41(flat_struct) SpecConstantComposite 28 32 43 96
|
||||||
|
98: 24(float) Constant 1036831949
|
||||||
|
99: 25(fvec4) ConstantComposite 98 98 98 98
|
||||||
|
100:42(nesting_struct) SpecConstantComposite 97 99 28
|
||||||
|
101: 14(int) Constant 3000
|
||||||
|
102:42(nesting_struct) SpecConstantComposite 88 37 101
|
||||||
|
103: TypeArray 25(fvec4) 28
|
||||||
|
104: TypePointer Input 103
|
||||||
|
105(global_vec4_array_with_spec_length): 104(ptr) Variable Input
|
||||||
|
4(main): 2 Function None 3
|
||||||
|
5: Label
|
||||||
|
Return
|
||||||
|
FunctionEnd
|
||||||
|
6(refer_primary_spec_const(): 2 Function None 3
|
||||||
|
7: Label
|
||||||
|
SelectionMerge 23 None
|
||||||
|
BranchConditional 21 22 23
|
||||||
|
22: Label
|
||||||
|
29: 24(float) ConvertSToF 28
|
||||||
|
30: 25(fvec4) Load 27(color)
|
||||||
|
31: 25(fvec4) VectorTimesScalar 30 29
|
||||||
|
Store 27(color) 31
|
||||||
|
Branch 23
|
||||||
|
23: Label
|
||||||
|
Return
|
||||||
|
FunctionEnd
|
||||||
|
8(refer_composite_spec_const(): 2 Function None 3
|
||||||
|
9: Label
|
||||||
|
34: 25(fvec4) Load 27(color)
|
||||||
|
35: 25(fvec4) FAdd 34 33
|
||||||
|
Store 27(color) 35
|
||||||
|
38: 25(fvec4) Load 27(color)
|
||||||
|
39: 25(fvec4) FSub 38 37
|
||||||
|
Store 27(color) 39
|
||||||
|
Return
|
||||||
|
FunctionEnd
|
||||||
|
10(refer_copmosite_dot_dereference(): 2 Function None 3
|
||||||
|
11: Label
|
||||||
|
47: 14(int) CompositeExtract 45 2
|
||||||
|
48: 24(float) ConvertSToF 47
|
||||||
|
49: 25(fvec4) Load 27(color)
|
||||||
|
50: 25(fvec4) VectorTimesScalar 49 48
|
||||||
|
Store 27(color) 50
|
||||||
|
53: 24(float) CompositeExtract 33 0
|
||||||
|
54: 25(fvec4) Load 27(color)
|
||||||
|
55: 25(fvec4) CompositeConstruct 53 53 53 53
|
||||||
|
56: 25(fvec4) FAdd 54 55
|
||||||
|
Store 27(color) 56
|
||||||
|
Return
|
||||||
|
FunctionEnd
|
||||||
|
12(refer_composite_bracket_dereference(): 2 Function None 3
|
||||||
|
13: Label
|
||||||
|
72(indexable): 71(ptr) Variable Function
|
||||||
|
76(indexable): 71(ptr) Variable Function
|
||||||
|
64: 24(float) CompositeExtract 62 1
|
||||||
|
65: 25(fvec4) Load 27(color)
|
||||||
|
66: 25(fvec4) CompositeConstruct 64 64 64 64
|
||||||
|
67: 25(fvec4) FSub 65 66
|
||||||
|
Store 27(color) 67
|
||||||
|
Store 72(indexable) 70
|
||||||
|
74: 73(ptr) AccessChain 72(indexable) 28
|
||||||
|
75: 14(int) Load 74
|
||||||
|
Store 76(indexable) 70
|
||||||
|
77: 73(ptr) AccessChain 76(indexable) 75
|
||||||
|
78: 14(int) Load 77
|
||||||
|
79: 24(float) ConvertSToF 78
|
||||||
|
80: 25(fvec4) Load 27(color)
|
||||||
|
81: 25(fvec4) CompositeConstruct 79 79 79 79
|
||||||
|
82: 25(fvec4) FDiv 80 81
|
||||||
|
Store 27(color) 82
|
||||||
|
Return
|
||||||
|
FunctionEnd
|
||||||
|
16(refer_spec_const_array_length(): 14(int) Function None 15
|
||||||
|
17: Label
|
||||||
|
83(len): 73(ptr) Variable Function
|
||||||
|
Store 83(len) 28
|
||||||
|
84: 14(int) Load 83(len)
|
||||||
|
ReturnValue 84
|
||||||
|
FunctionEnd
|
||||||
|
18(declare_spec_const_in_func(): 2 Function None 3
|
||||||
|
19: Label
|
||||||
|
91: 14(int) CompositeExtract 90 2
|
||||||
|
92: 24(float) ConvertSToF 91
|
||||||
|
93: 25(fvec4) Load 27(color)
|
||||||
|
94: 25(fvec4) CompositeConstruct 92 92 92 92
|
||||||
|
95: 25(fvec4) FDiv 93 94
|
||||||
|
Store 27(color) 95
|
||||||
|
Return
|
||||||
|
FunctionEnd
|
93
Test/spv.specConstantComposite.vert
Normal file
93
Test/spv.specConstantComposite.vert
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
#version 450
|
||||||
|
|
||||||
|
// constant_id specified scalar spec constants
|
||||||
|
layout(constant_id = 200) const int spec_int = 3;
|
||||||
|
layout(constant_id = 201) const float spec_float = 3.14;
|
||||||
|
layout(constant_id = 202) const
|
||||||
|
double spec_double = 3.1415926535897932384626433832795;
|
||||||
|
layout(constant_id = 203) const bool spec_bool = true;
|
||||||
|
|
||||||
|
const float cast_spec_float = float(spec_float);
|
||||||
|
|
||||||
|
// Flat struct
|
||||||
|
struct flat_struct {
|
||||||
|
int i;
|
||||||
|
float f;
|
||||||
|
double d;
|
||||||
|
bool b;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Nesting struct
|
||||||
|
struct nesting_struct {
|
||||||
|
flat_struct nested;
|
||||||
|
vec4 v;
|
||||||
|
int i;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Expect OpSpecConstantComposite
|
||||||
|
// Flat struct initializer
|
||||||
|
const flat_struct spec_flat_struct_all_spec = {spec_int, spec_float,
|
||||||
|
spec_double, spec_bool};
|
||||||
|
const flat_struct spec_flat_struct_partial_spec = {30, 30.14, spec_double,
|
||||||
|
spec_bool};
|
||||||
|
|
||||||
|
// Nesting struct initializer
|
||||||
|
const nesting_struct nesting_struct_ctor = {
|
||||||
|
{spec_int, spec_float, spec_double, false},
|
||||||
|
vec4(0.1, 0.1, 0.1, 0.1),
|
||||||
|
spec_int};
|
||||||
|
|
||||||
|
// Vector constructor
|
||||||
|
const vec4 spec_vec4_all_spec =
|
||||||
|
vec4(spec_float, spec_float, spec_float, spec_float);
|
||||||
|
const vec4 spec_vec4_partial_spec =
|
||||||
|
vec4(spec_float, spec_float, 300.14, 300.14);
|
||||||
|
|
||||||
|
// Struct nesting constructor
|
||||||
|
const nesting_struct spec_nesting_struct_all_spec = {
|
||||||
|
spec_flat_struct_all_spec, spec_vec4_all_spec, spec_int};
|
||||||
|
const nesting_struct spec_nesting_struct_partial_spec = {
|
||||||
|
spec_flat_struct_partial_spec, spec_vec4_partial_spec, 3000};
|
||||||
|
|
||||||
|
const float spec_float_array[5] = {spec_float, spec_float, 1.0, 2.0, 3.0};
|
||||||
|
const int spec_int_array[5] = {spec_int, spec_int, 1, 2, 30};
|
||||||
|
|
||||||
|
// global_vec4_array_with_spec_length is not a spec constant, but its array
|
||||||
|
// size is. When calling global_vec4_array_with_spec_length.length(), A
|
||||||
|
// TIntermSymbol Node shoule be returned, instead of a TIntermConstantUnion
|
||||||
|
// node which represents a known constant value.
|
||||||
|
in vec4 global_vec4_array_with_spec_length[spec_int];
|
||||||
|
|
||||||
|
out vec4 color;
|
||||||
|
|
||||||
|
void refer_primary_spec_const() {
|
||||||
|
if (spec_bool) color *= spec_int;
|
||||||
|
}
|
||||||
|
|
||||||
|
void refer_composite_spec_const() {
|
||||||
|
color += spec_vec4_all_spec;
|
||||||
|
color -= spec_vec4_partial_spec;
|
||||||
|
}
|
||||||
|
|
||||||
|
void refer_copmosite_dot_dereference() {
|
||||||
|
color *= spec_nesting_struct_all_spec.i;
|
||||||
|
color += spec_vec4_all_spec.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
void refer_composite_bracket_dereference() {
|
||||||
|
color -= spec_float_array[1];
|
||||||
|
color /= spec_int_array[spec_int_array[spec_int]];
|
||||||
|
}
|
||||||
|
|
||||||
|
int refer_spec_const_array_length() {
|
||||||
|
int len = global_vec4_array_with_spec_length.length();
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void declare_spec_const_in_func() {
|
||||||
|
const nesting_struct spec_const_declared_in_func = {
|
||||||
|
spec_flat_struct_partial_spec, spec_vec4_partial_spec, 10};
|
||||||
|
color /= spec_const_declared_in_func.i;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {}
|
@ -102,6 +102,7 @@ spv.pushConstant.vert
|
|||||||
spv.subpass.frag
|
spv.subpass.frag
|
||||||
spv.specConstant.vert
|
spv.specConstant.vert
|
||||||
spv.specConstant.comp
|
spv.specConstant.comp
|
||||||
|
spv.specConstantComposite.vert
|
||||||
# GLSL-level semantics
|
# GLSL-level semantics
|
||||||
vulkan.frag
|
vulkan.frag
|
||||||
vulkan.vert
|
vulkan.vert
|
||||||
|
@ -1223,6 +1223,7 @@ public:
|
|||||||
virtual int getMatrixCols() const { return matrixCols; }
|
virtual int getMatrixCols() const { return matrixCols; }
|
||||||
virtual int getMatrixRows() const { return matrixRows; }
|
virtual int getMatrixRows() const { return matrixRows; }
|
||||||
virtual int getOuterArraySize() const { return arraySizes->getOuterSize(); }
|
virtual int getOuterArraySize() const { return arraySizes->getOuterSize(); }
|
||||||
|
virtual TIntermTyped* getOuterArrayNode() const { return arraySizes->getOuterNode(); }
|
||||||
virtual int getCumulativeArraySize() const { return arraySizes->getCumulativeSize(); }
|
virtual int getCumulativeArraySize() const { return arraySizes->getCumulativeSize(); }
|
||||||
virtual bool isArrayOfArrays() const { return arraySizes != nullptr && arraySizes->getNumDims() > 1; }
|
virtual bool isArrayOfArrays() const { return arraySizes != nullptr && arraySizes->getNumDims() > 1; }
|
||||||
virtual int getImplicitArraySize() const { return arraySizes->getImplicitSize(); }
|
virtual int getImplicitArraySize() const { return arraySizes->getImplicitSize(); }
|
||||||
|
@ -484,7 +484,7 @@ TIntermTyped* TParseContext::handleBracketDereference(const TSourceLoc& loc, TIn
|
|||||||
TIntermTyped* result = nullptr;
|
TIntermTyped* result = nullptr;
|
||||||
|
|
||||||
int indexValue = 0;
|
int indexValue = 0;
|
||||||
if (index->getQualifier().isConstant()) {
|
if (index->getQualifier().isFrontEndConstant()) {
|
||||||
indexValue = index->getAsConstantUnion()->getConstArray()[0].getIConst();
|
indexValue = index->getAsConstantUnion()->getConstArray()[0].getIConst();
|
||||||
checkIndex(loc, base->getType(), indexValue);
|
checkIndex(loc, base->getType(), indexValue);
|
||||||
}
|
}
|
||||||
@ -503,7 +503,7 @@ TIntermTyped* TParseContext::handleBracketDereference(const TSourceLoc& loc, TIn
|
|||||||
if (base->getAsSymbolNode() && isIoResizeArray(base->getType()))
|
if (base->getAsSymbolNode() && isIoResizeArray(base->getType()))
|
||||||
handleIoResizeArrayAccess(loc, base);
|
handleIoResizeArrayAccess(loc, base);
|
||||||
|
|
||||||
if (index->getQualifier().isConstant()) {
|
if (index->getQualifier().isFrontEndConstant()) {
|
||||||
if (base->getType().isImplicitlySizedArray())
|
if (base->getType().isImplicitlySizedArray())
|
||||||
updateImplicitArraySize(loc, base, indexValue);
|
updateImplicitArraySize(loc, base, indexValue);
|
||||||
result = intermediate.addIndex(EOpIndexDirect, base, index, loc);
|
result = intermediate.addIndex(EOpIndexDirect, base, index, loc);
|
||||||
@ -541,10 +541,15 @@ TIntermTyped* TParseContext::handleBracketDereference(const TSourceLoc& loc, TIn
|
|||||||
} else {
|
} else {
|
||||||
// Insert valid dereferenced result
|
// Insert valid dereferenced result
|
||||||
TType newType(base->getType(), 0); // dereferenced type
|
TType newType(base->getType(), 0); // dereferenced type
|
||||||
if (base->getType().getQualifier().isFrontEndConstant() && index->getQualifier().isFrontEndConstant())
|
if (base->getType().getQualifier().isConstant() && index->getQualifier().isConstant()) {
|
||||||
newType.getQualifier().storage = EvqConst;
|
newType.getQualifier().storage = EvqConst;
|
||||||
else
|
// If base or index is a specialization constant, the result should also be a specialization constant.
|
||||||
|
if (base->getType().getQualifier().isSpecConstant() || index->getQualifier().isSpecConstant()) {
|
||||||
|
newType.getQualifier().makeSpecConstant();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
newType.getQualifier().makePartialTemporary();
|
newType.getQualifier().makePartialTemporary();
|
||||||
|
}
|
||||||
result->setType(newType);
|
result->setType(newType);
|
||||||
|
|
||||||
if (anyIndexLimits)
|
if (anyIndexLimits)
|
||||||
@ -1226,6 +1231,11 @@ TIntermTyped* TParseContext::handleLengthMethod(const TSourceLoc& loc, TFunction
|
|||||||
else
|
else
|
||||||
error(loc, "", function->getName().c_str(), "array must be declared with a size before using this method");
|
error(loc, "", function->getName().c_str(), "array must be declared with a size before using this method");
|
||||||
}
|
}
|
||||||
|
} else if (type.getOuterArrayNode()) {
|
||||||
|
// If the array's outer size is specified by an intermediate node, it means the array's length
|
||||||
|
// was specified by a specialization constant. In such a case, we should return the node of the
|
||||||
|
// specialization constants to represent the length.
|
||||||
|
return type.getOuterArrayNode();
|
||||||
} else
|
} else
|
||||||
length = type.getOuterArraySize();
|
length = type.getOuterArraySize();
|
||||||
} else if (type.isMatrix())
|
} else if (type.isMatrix())
|
||||||
@ -5110,7 +5120,8 @@ TIntermTyped* TParseContext::addConstructor(const TSourceLoc& loc, TIntermNode*
|
|||||||
|
|
||||||
// We don't know "top down" whether type is a specialization constant,
|
// We don't know "top down" whether type is a specialization constant,
|
||||||
// but a const becomes a specialization constant if any of its children are.
|
// but a const becomes a specialization constant if any of its children are.
|
||||||
bool specConst = false;
|
bool hasSpecConst = false;
|
||||||
|
bool isConstConstrutor = true;
|
||||||
|
|
||||||
for (TIntermSequence::iterator p = sequenceVector.begin();
|
for (TIntermSequence::iterator p = sequenceVector.begin();
|
||||||
p != sequenceVector.end(); p++, paramCount++) {
|
p != sequenceVector.end(); p++, paramCount++) {
|
||||||
@ -5123,14 +5134,16 @@ TIntermTyped* TParseContext::addConstructor(const TSourceLoc& loc, TIntermNode*
|
|||||||
|
|
||||||
if (newNode) {
|
if (newNode) {
|
||||||
*p = newNode;
|
*p = newNode;
|
||||||
|
if (! newNode->getType().getQualifier().isConstant())
|
||||||
|
isConstConstrutor = false;
|
||||||
if (newNode->getType().getQualifier().isSpecConstant())
|
if (newNode->getType().getQualifier().isSpecConstant())
|
||||||
specConst = true;
|
hasSpecConst = true;
|
||||||
} else
|
} else
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
TIntermTyped* constructor = intermediate.setAggregateOperator(aggrNode, op, type, loc);
|
TIntermTyped* constructor = intermediate.setAggregateOperator(aggrNode, op, type, loc);
|
||||||
if (constructor->getType().getQualifier().isConstant() && specConst)
|
if (isConstConstrutor && hasSpecConst)
|
||||||
constructor->getWritableType().getQualifier().makeSpecConstant();
|
constructor->getWritableType().getQualifier().makeSpecConstant();
|
||||||
|
|
||||||
return constructor;
|
return constructor;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user