SPV arrays: Add support for runtime-sized array types and arrays of arrays.

This includes run-time block.member.length() (OpArrayLength).
This commit is contained in:
John Kessenich 2015-09-12 12:17:44 -06:00
parent 9312269d09
commit c9a808319a
9 changed files with 369 additions and 27 deletions

View File

@ -680,6 +680,24 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI
}
// Non-texturing.
if (node->getOp() == glslang::EOpArrayLength) {
// Quite special; won't want to evaluate the operand.
// Normal .length() would have been constant folded by the front-end.
// So, this has to be block.lastMember.length().
// SPV wants "block" as the operand, go get it.
assert(node->getOperand()->getType().isRuntimeSizedArray());
glslang::TIntermTyped* block = node->getOperand()->getAsBinaryNode()->getLeft();
block->traverse(this);
spv::Id length = builder.createUnaryOp(spv::OpArrayLength, builder.makeIntType(32), builder.accessChainGetLValue());
builder.clearAccessChain();
builder.setAccessChainRValue(length);
return false;
}
// Start by evaluating the operand
builder.clearAccessChain();
@ -967,17 +985,6 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
// which can be emitted by the one in createBinaryOperation()
binOp = glslang::EOpMod;
break;
case glslang::EOpArrayLength:
{
glslang::TIntermTyped* typedNode = node->getSequence()[0]->getAsTyped();
assert(typedNode);
spv::Id length = builder.makeIntConstant(typedNode->getType().getOuterArraySize());
builder.clearAccessChain();
builder.setAccessChainRValue(length);
return false;
}
case glslang::EOpEmitVertex:
case glslang::EOpEndPrimitive:
case glslang::EOpBarrier:
@ -1468,14 +1475,23 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
}
if (type.isArray()) {
unsigned arraySize;
if (! type.isExplicitlySizedArray()) {
spv::MissingFunctionality("Unsized array");
arraySize = 8;
} else
arraySize = type.getOuterArraySize();
spvType = builder.makeArrayType(spvType, arraySize);
// Do all but the outer dimension
for (int dim = type.getArraySizes()->getNumDims() - 1; dim > 0; --dim) {
assert(type.getArraySizes()->getDimSize(dim) > 0);
spvType = builder.makeArrayType(spvType, type.getArraySizes()->getDimSize(dim));
}
// Do the outer dimension, which might not be known for a runtime-sized array
if (type.isRuntimeSizedArray()) {
spvType = builder.makeRuntimeArray(spvType);
} else {
assert(type.getOuterArraySize() > 0);
spvType = builder.makeArrayType(spvType, type.getOuterArraySize());
}
// TODO: layout still needs to be done hierarchically for arrays of arrays, which
// may still require additional "link time" support from the front-end
// for arrays of arrays
if (explicitLayout)
builder.addDecoration(spvType, spv::DecorationArrayStride, getArrayStride(type));
}

View File

@ -264,6 +264,16 @@ Id Builder::makeArrayType(Id element, unsigned size)
return type->getResultId();
}
Id Builder::makeRuntimeArray(Id element)
{
Instruction* type = new Instruction(getUniqueId(), NoType, OpTypeRuntimeArray);
type->addIdOperand(element);
constantsTypesGlobals.push_back(type);
module.mapInstruction(type);
return type->getResultId();
}
Id Builder::makeFunctionType(Id returnType, std::vector<Id>& paramTypes)
{
// try to find it
@ -280,7 +290,7 @@ Id Builder::makeFunctionType(Id returnType, std::vector<Id>& paramTypes)
}
}
if (! mismatch)
return type->getResultId();
return type->getResultId();
}
// not found, make it

View File

@ -102,6 +102,7 @@ public:
Id makeVectorType(Id component, int size);
Id makeMatrixType(Id component, int cols, int rows);
Id makeArrayType(Id element, unsigned size);
Id makeRuntimeArray(Id element);
Id makeFunctionType(Id returnType, std::vector<Id>& paramTypes);
Id makeImageType(Id sampledType, Dim, bool depth, bool arrayed, bool ms, unsigned sampled, ImageFormat format);
Id makeSampledImageType(Id imageType);

View File

@ -5,4 +5,121 @@ Warning, version 310 is not yet complete; most version-specific features are pre
Linked compute stage:
Missing functionality: Unsized array
// Module Version 99
// Generated by (magic number): 51a00bb
// Id's are bound by 72
Source ESSL 310
Capability Shader
1: ExtInstImport "GLSL.std.450"
MemoryModel Logical GLSL450
EntryPoint GLCompute 4 "main"
Name 4 "main"
Name 14 "outb"
MemberName 14(outb) 0 "f"
MemberName 14(outb) 1 "g"
MemberName 14(outb) 2 "h"
MemberName 14(outb) 3 "uns"
Name 16 "outbname"
Name 20 "s"
Name 25 "outbna"
MemberName 25(outbna) 0 "k"
MemberName 25(outbna) 1 "na"
Name 27 "outbnamena"
Name 47 "i"
Name 53 "outs"
MemberName 53(outs) 0 "s"
MemberName 53(outs) 1 "va"
Name 55 "outnames"
Name 59 "gl_LocalInvocationID"
Decorate 14(outb) GLSLShared
Decorate 14(outb) BufferBlock
Decorate 25(outbna) GLSLShared
Decorate 25(outbna) BufferBlock
Decorate 53(outs) GLSLShared
Decorate 53(outs) BufferBlock
Decorate 59(gl_LocalInvocationID) BuiltIn LocalInvocationId
Decorate 71 BuiltIn WorkgroupSize
Decorate 71 NoStaticUse
2: TypeVoid
3: TypeFunction 2
7: TypeInt 32 0
8: 7(int) Constant 1
9: 7(int) Constant 1023
10: 7(int) Constant 0
11: TypeFloat 32
12: TypeVector 11(float) 3
13: TypeRuntimeArray 12(fvec3)
14(outb): TypeStruct 11(float) 11(float) 11(float) 13
15: TypePointer Uniform 14(outb)
16(outbname): 15(ptr) Variable Uniform
17: TypeInt 32 1
18: 17(int) Constant 0
19: TypePointer WorkgroupLocal 11(float)
20(s): 19(ptr) Variable WorkgroupLocal
22: TypePointer Uniform 11(float)
24: TypeVector 11(float) 4
25(outbna): TypeStruct 17(int) 24(fvec4)
26: TypePointer Uniform 25(outbna)
27(outbnamena): 26(ptr) Variable Uniform
28: 17(int) Constant 1
31: TypePointer Uniform 24(fvec4)
33: TypeRuntimeArray 12(fvec3)
34: 17(int) Constant 3
35: 17(int) Constant 18
36: TypePointer Uniform 12(fvec3)
40: TypeRuntimeArray 12(fvec3)
41: 17(int) Constant 17
42: 11(float) Constant 1077936128
43: 12(fvec3) ConstantComposite 42 42 42
45: TypeRuntimeArray 12(fvec3)
46: TypePointer WorkgroupLocal 17(int)
47(i): 46(ptr) Variable WorkgroupLocal
52: TypeRuntimeArray 24(fvec4)
53(outs): TypeStruct 17(int) 52
54: TypePointer Uniform 53(outs)
55(outnames): 54(ptr) Variable Uniform
56: TypeRuntimeArray 24(fvec4)
57: TypeVector 7(int) 3
58: TypePointer Input 57(ivec3)
59(gl_LocalInvocationID): 58(ptr) Variable Input
66: TypePointer Uniform 17(int)
68: 7(int) Constant 16
69: 7(int) Constant 32
70: 7(int) Constant 4
71: 57(ivec3) ConstantComposite 68 69 70
4(main): 2 Function None 3
5: Label
MemoryBarrier 8 9
ControlBarrier 8 8 10
21: 11(float) Load 20(s)
23: 22(ptr) AccessChain 16(outbname) 18
Store 23 21
29: 11(float) Load 20(s)
30: 24(fvec4) CompositeConstruct 29 29 29 29
32: 31(ptr) AccessChain 27(outbnamena) 28
Store 32 30
37: 36(ptr) AccessChain 16(outbname) 34 35
38: 12(fvec3) Load 37
39: 11(float) CompositeExtract 38 0
Store 20(s) 39
44: 36(ptr) AccessChain 16(outbname) 34 41
Store 44 43
48: 17(int) Load 47(i)
49: 11(float) Load 20(s)
50: 12(fvec3) CompositeConstruct 49 49 49
51: 36(ptr) AccessChain 16(outbname) 34 48
Store 51 50
60: 57(ivec3) Load 59(gl_LocalInvocationID)
61: 7(int) CompositeExtract 60 0
62: 11(float) Load 20(s)
63: 24(fvec4) CompositeConstruct 62 62 62 62
64: 31(ptr) AccessChain 55(outnames) 28 61
Store 64 63
65: 17(int) ArrayLength 16(outbname)
67: 66(ptr) AccessChain 55(outnames) 18
Store 67 65
Branch 6
6: Label
Return
FunctionEnd

View File

@ -0,0 +1,154 @@
spv.AofA.frag
Warning, version 430 is not yet complete; most version-specific features are present, but some are missing.
Linked fragment stage:
// Module Version 99
// Generated by (magic number): 51a00bb
// Id's are bound by 104
Source GLSL 430
Capability Shader
1: ExtInstImport "GLSL.std.450"
MemoryModel Logical GLSL450
EntryPoint Fragment 4 "main"
ExecutionMode 4 OriginLowerLeft
Name 4 "main"
Name 18 "foo(f1[5][7];"
Name 17 "a"
Name 21 "r"
Name 39 "outfloat"
Name 42 "g4"
Name 44 "g5"
Name 45 "param"
Name 48 "u"
Name 52 "param"
Name 66 "many"
Name 68 "i"
Name 70 "j"
Name 72 "k"
Name 78 "infloat"
Name 94 "uAofA"
MemberName 94(uAofA) 0 "f"
Name 98 "nameAofA"
Decorate 44(g5) Smooth
Decorate 78(infloat) Smooth
Decorate 94(uAofA) GLSLShared
Decorate 94(uAofA) Block
2: TypeVoid
3: TypeFunction 2
7: TypeFloat 32
8: TypeInt 32 0
9: 8(int) Constant 7
10: TypeArray 7(float) 9
11: 8(int) Constant 5
12: TypeArray 10 11
13: TypePointer Function 12
14: 8(int) Constant 4
15: TypeArray 10 14
16: TypeFunction 15 13(ptr)
20: TypePointer Function 10
22: TypeInt 32 1
23: 22(int) Constant 2
26: 22(int) Constant 0
29: 22(int) Constant 1
33: 22(int) Constant 3
38: TypePointer Output 7(float)
39(outfloat): 38(ptr) Variable Output
40: 7(float) Constant 0
41: TypePointer PrivateGlobal 15
42(g4): 41(ptr) Variable PrivateGlobal
43: TypePointer Input 12
44(g5): 43(ptr) Variable Input
49: 7(float) Constant 1077936128
50: TypePointer Function 7(float)
55: 8(int) Constant 6
56: TypeArray 7(float) 55
57: TypeArray 56 11
58: TypeArray 57 14
59: 8(int) Constant 3
60: TypeArray 58 59
61: 8(int) Constant 2
62: TypeArray 60 61
63: 8(int) Constant 1
64: TypeArray 62 63
65: TypePointer PrivateGlobal 64
66(many): 65(ptr) Variable PrivateGlobal
67: TypePointer UniformConstant 22(int)
68(i): 67(ptr) Variable UniformConstant
70(j): 67(ptr) Variable UniformConstant
72(k): 67(ptr) Variable UniformConstant
77: TypePointer Input 7(float)
78(infloat): 77(ptr) Variable Input
80: TypePointer PrivateGlobal 7(float)
92: TypeArray 7(float) 14
93: TypeArray 92 61
94(uAofA): TypeStruct 93
95: TypeArray 94(uAofA) 11
96: TypeArray 95 59
97: TypePointer Uniform 96
98(nameAofA): 97(ptr) Variable Uniform
99: TypePointer Uniform 7(float)
4(main): 2 Function None 3
5: Label
45(param): 13(ptr) Variable Function
48(u): 13(ptr) Variable Function
52(param): 13(ptr) Variable Function
Store 39(outfloat) 40
46: 12 Load 44(g5)
Store 45(param) 46
47: 15 FunctionCall 18(foo(f1[5][7];) 45(param)
Store 42(g4) 47
51: 50(ptr) AccessChain 48(u) 23 23
Store 51 49
53: 12 Load 48(u)
Store 52(param) 53
54: 15 FunctionCall 18(foo(f1[5][7];) 52(param)
69: 22(int) Load 68(i)
71: 22(int) Load 70(j)
73: 22(int) Load 72(k)
74: 22(int) Load 68(i)
75: 22(int) Load 70(j)
76: 22(int) Load 72(k)
79: 7(float) Load 78(infloat)
81: 80(ptr) AccessChain 66(many) 69 71 73 74 75 76
Store 81 79
82: 22(int) Load 70(j)
83: 22(int) Load 70(j)
84: 22(int) Load 70(j)
85: 22(int) Load 70(j)
86: 22(int) Load 70(j)
87: 22(int) Load 70(j)
88: 80(ptr) AccessChain 66(many) 82 83 84 85 86 87
89: 7(float) Load 88
90: 7(float) Load 39(outfloat)
91: 7(float) FAdd 90 89
Store 39(outfloat) 91
100: 99(ptr) AccessChain 98(nameAofA) 29 23 26 26 33
101: 7(float) Load 100
102: 7(float) Load 39(outfloat)
103: 7(float) FAdd 102 101
Store 39(outfloat) 103
Branch 6
6: Label
Return
FunctionEnd
18(foo(f1[5][7];): 15 Function None 16
17(a): 13(ptr) FunctionParameter
19: Label
21(r): 20(ptr) Variable Function
24: 20(ptr) AccessChain 17(a) 23
25: 10 Load 24
Store 21(r) 25
27: 20(ptr) AccessChain 17(a) 26
28: 10 Load 27
30: 20(ptr) AccessChain 17(a) 29
31: 10 Load 30
32: 10 Load 21(r)
34: 20(ptr) AccessChain 17(a) 33
35: 10 Load 34
36: 15 CompositeConstruct 28 31 32 35
ReturnValue 36
FunctionEnd

View File

@ -11,9 +11,7 @@ buffer outb {
float f;
float g;
float h;
vec3 uns[]; // this makes it look like the "second" set of 3 floats in a struct, which LLVM
// takes advantage of when optimizing, giving confusing results, like thinking
// &outbname.uns[18].x == &outbname[9].uns.x
vec3 uns[];
} outbname;
buffer outbna {
@ -22,6 +20,7 @@ buffer outbna {
} outbnamena;
buffer outs {
int s;
vec4 va[];
} outnames;
@ -30,8 +29,9 @@ void main()
barrier();
outbname.f = s;
outbnamena.na = vec4(s);
s = outbname.uns[18].x; // TODO: see note above
//outbname.uns[17] = vec3(3.0); // TODO: see note above, this one bitcasts, which isn't handled
s = outbname.uns[18].x;
outbname.uns[17] = vec3(3.0);
outbname.uns[i] = vec3(s);
outnames.va[gl_LocalInvocationID.x] = vec4(s);
outnames.s = outbname.uns.length();
}

43
Test/spv.AofA.frag Normal file
View File

@ -0,0 +1,43 @@
#version 430
in float infloat;
out float outfloat;
uniform uAofA {
float f[2][4];
} nameAofA[3][5];
float[4][5][6] many[1][2][3];
float g4[4][7];
in float g5[5][7];
uniform int i, j, k;
float[4][7] foo(float a[5][7])
{
float r[7];
r = a[2];
return float[4][7](a[0], a[1], r, a[3]);
}
void main()
{
outfloat = 0.0;
g4 = foo(g5);
// if (foo(g5) == g4)
// ++outfloat;
float u[][7];
u[2][2] = 3.0;
float u[5][7];
foo(u);
many[i][j][k][i][j][k] = infloat;
outfloat += many[j][j][j][j][j][j];
outfloat += nameAofA[1][2].f[0][3];
}

View File

@ -79,3 +79,4 @@ spv.varyingArrayIndirect.frag
spv.voidFunction.frag
spv.whileLoop.frag
spv.atomic.comp
spv.AofA.frag

View File

@ -2,5 +2,5 @@
// For the version, it uses the latest git tag followed by the number of commits.
// For the date, it uses the current date (when then script is run).
#define GLSLANG_REVISION "3.0.748"
#define GLSLANG_DATE "11-Sep-2015"
#define GLSLANG_REVISION "3.0.750"
#define GLSLANG_DATE "13-Sep-2015"