Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support specialization composite constants #211

Merged
merged 1 commit into from
Mar 25, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 75 additions & 12 deletions SPIRV/GlslangToSpv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,9 @@ class TGlslangToSpvTraverser : public glslang::TIntermTraverser {
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, unsigned value);
spv::Id createSpvSpecConstant(const glslang::TIntermTyped&);
spv::Id createSpvConstant(const glslang::TType& type, const glslang::TConstUnionArray&, int& nextConst, bool specConstant);
spv::Id createSpvConstant(const glslang::TIntermTyped&);
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 isTrivial(const glslang::TIntermTyped* node);
spv::Id createShortCircuit(glslang::TOperator, glslang::TIntermTyped& left, glslang::TIntermTyped& right);
Expand Down Expand Up @@ -1520,7 +1521,7 @@ bool TGlslangToSpvTraverser::visitSwitch(glslang::TVisit /* visit */, glslang::T
void TGlslangToSpvTraverser::visitConstantUnion(glslang::TIntermConstantUnion* node)
{
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.setAccessChainRValue(constant);
Expand Down Expand Up @@ -1630,7 +1631,7 @@ spv::Id TGlslangToSpvTraverser::createSpvVariable(const glslang::TIntermSymbol*
// can still have a mapping to a SPIR-V Id.
// This includes specialization constants.
if (node->getQualifier().isConstant()) {
return createSpvSpecConstant(*node);
return createSpvConstant(*node);
}

// Now, handle actual variables
Expand Down Expand Up @@ -3730,15 +3731,15 @@ void TGlslangToSpvTraverser::addMemberDecoration(spv::Id id, int member, spv::De
// recursively walks. So, this function walks the "top" of the tree:
// - emit specialization constant-building instructions for specConstant
// - 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());

if (! node.getQualifier().specConstant) {
// hand off to the non-spec-constant path
assert(node.getAsConstantUnion() != nullptr || node.getAsSymbolNode() != nullptr);
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);
}

Expand All @@ -3747,7 +3748,7 @@ spv::Id TGlslangToSpvTraverser::createSpvSpecConstant(const glslang::TIntermType
if (node.getAsSymbolNode() && node.getQualifier().hasSpecConstantId()) {
// this is a direct literal assigned to a layout(constant_id=) declaration
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);
} else {
// gl_WorkgroupSize is a special case until the front-end handles hierarchical specialization constants,
Expand All @@ -3761,8 +3762,10 @@ spv::Id TGlslangToSpvTraverser::createSpvSpecConstant(const glslang::TIntermType
addDecoration(dimConstId.back(), spv::DecorationSpecId, glslangIntermediate->getLocalSizeSpecId(dim));
}
return builder.makeCompositeConstant(builder.makeVectorType(builder.makeUintType(32), 3), dimConstId, true);
} else if (auto* sn = node.getAsSymbolNode()){
return createSpvConstantFromConstSubTree(sn->getConstSubtree());
} else {
spv::MissingFunctionality("specialization-constant expression trees");
spv::MissingFunctionality("Neither a front-end constant nor a spec constant.");
exit(1);
return spv::NoResult;
}
Expand All @@ -3775,7 +3778,7 @@ spv::Id TGlslangToSpvTraverser::createSpvSpecConstant(const glslang::TIntermType
// 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.
//
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
std::vector<spv::Id> spvConsts;
Expand All @@ -3786,15 +3789,15 @@ spv::Id TGlslangToSpvTraverser::createSpvConstant(const glslang::TType& glslangT
if (glslangType.isArray()) {
glslang::TType elementType(glslangType, 0);
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()) {
glslang::TType vectorType(glslangType, 0);
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()) {
glslang::TVector<glslang::TTypeLoc>::const_iterator 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()) {
for (unsigned int i = 0; i < (unsigned int)glslangType.getVectorSize(); ++i) {
bool zero = nextConst >= consts.size();
Expand Down Expand Up @@ -3851,6 +3854,66 @@ spv::Id TGlslangToSpvTraverser::createSpvConstant(const glslang::TType& glslangT
return builder.makeCompositeConstant(typeId, spvConsts);
}

// Create constant ID from const initializer sub tree.
spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstSubTree(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need 4 space indentation.

const glslang::TIntermTyped* subTree) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have function open '{' start a new line.

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
// non-trivial observable cost or effect.
bool TGlslangToSpvTraverser::isTrivialLeaf(const glslang::TIntermTyped* node)
Expand Down
172 changes: 172 additions & 0 deletions Test/baseResults/spv.specConstantComposite.vert.out
Original file line number Diff line number Diff line change
@@ -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
Loading