HLSL: allow implicit array sizing.

In HLSL array sizes need not be provided explicitly in all circumstances.
For example, this is valid (note no number between the [ ]):

  // no explicit array size
  uniform float g_array[] = { 1, 2, 3, 4, 5 };

This PR does not attempt to validate most invalid cases.

A new test is added to verify the resulting linker objects.
This commit is contained in:
steve-lunarg 2016-09-27 10:57:35 -06:00
Родитель 16a99a3804
Коммит 265c0618b1
4 изменённых файлов: 316 добавлений и 9 удалений

Просмотреть файл

@ -0,0 +1,264 @@
hlsl.array.implicit-size.frag
Shader version: 450
gl_FragCoord origin is upper left
0:? Sequence
0:26 Function Definition: main(struct-PS_OUTPUT-vf41; (global void)
0:26 Function Parameters:
0:26 'ps_output' (out structure{temp 4-component vector of float color})
0:? Sequence
0:28 Sequence
0:28 move second child to first child (temp 3-element array of float)
0:28 'l_array' (temp 3-element array of float)
0:28 Constant:
0:28 1.000000
0:28 2.000000
0:28 3.000000
0:30 move second child to first child (temp 4-component vector of float)
0:30 color: direct index for structure (temp 4-component vector of float)
0:30 'ps_output' (out structure{temp 4-component vector of float color})
0:30 Constant:
0:30 0 (const int)
0:30 Construct vec4 (temp 4-component vector of float)
0:30 add (temp float)
0:30 add (temp float)
0:30 add (temp float)
0:30 add (temp float)
0:30 direct index (temp float)
0:30 'g_array' (uniform 5-element array of float)
0:30 1.000000
0:30 2.000000
0:30 3.000000
0:30 4.000000
0:30 5.000000
0:30 Constant:
0:30 0 (const int)
0:30 direct index (temp float)
0:30 'g_array' (uniform 5-element array of float)
0:30 1.000000
0:30 2.000000
0:30 3.000000
0:30 4.000000
0:30 5.000000
0:30 Constant:
0:30 4 (const int)
0:30 direct index (temp float)
0:30 'l_array' (temp 3-element array of float)
0:30 Constant:
0:30 1 (const int)
0:30 f: direct index for structure (temp float)
0:30 direct index (temp structure{temp int i, temp float f})
0:30 'g_mystruct' (uniform 2-element array of structure{temp int i, temp float f})
0:30 1 (const int)
0:30 2.000000
0:30 3 (const int)
0:30 4.000000
0:30 Constant:
0:30 0 (const int)
0:30 Constant:
0:30 1 (const int)
0:30 indirect index (temp float)
0:30 'g_array' (uniform 5-element array of float)
0:30 1.000000
0:30 2.000000
0:30 3.000000
0:30 4.000000
0:30 5.000000
0:30 'idx' (temp void)
0:? Linker Objects
0:? 'g_array' (uniform 5-element array of float)
0:? 1.000000
0:? 2.000000
0:? 3.000000
0:? 4.000000
0:? 5.000000
0:? 'g_array_unused' (uniform 7-element array of float)
0:? 1.000000
0:? 2.000000
0:? 3.000000
0:? 4.000000
0:? 5.000000
0:? 6.000000
0:? 7.000000
0:? 'g_mystruct' (uniform 2-element array of structure{temp int i, temp float f})
0:? 1 (const int)
0:? 2.000000
0:? 3 (const int)
0:? 4.000000
Linked fragment stage:
Shader version: 450
gl_FragCoord origin is upper left
0:? Sequence
0:26 Function Definition: main(struct-PS_OUTPUT-vf41; (global void)
0:26 Function Parameters:
0:26 'ps_output' (out structure{temp 4-component vector of float color})
0:? Sequence
0:28 Sequence
0:28 move second child to first child (temp 3-element array of float)
0:28 'l_array' (temp 3-element array of float)
0:28 Constant:
0:28 1.000000
0:28 2.000000
0:28 3.000000
0:30 move second child to first child (temp 4-component vector of float)
0:30 color: direct index for structure (temp 4-component vector of float)
0:30 'ps_output' (out structure{temp 4-component vector of float color})
0:30 Constant:
0:30 0 (const int)
0:30 Construct vec4 (temp 4-component vector of float)
0:30 add (temp float)
0:30 add (temp float)
0:30 add (temp float)
0:30 add (temp float)
0:30 direct index (temp float)
0:30 'g_array' (uniform 5-element array of float)
0:30 1.000000
0:30 2.000000
0:30 3.000000
0:30 4.000000
0:30 5.000000
0:30 Constant:
0:30 0 (const int)
0:30 direct index (temp float)
0:30 'g_array' (uniform 5-element array of float)
0:30 1.000000
0:30 2.000000
0:30 3.000000
0:30 4.000000
0:30 5.000000
0:30 Constant:
0:30 4 (const int)
0:30 direct index (temp float)
0:30 'l_array' (temp 3-element array of float)
0:30 Constant:
0:30 1 (const int)
0:30 f: direct index for structure (temp float)
0:30 direct index (temp structure{temp int i, temp float f})
0:30 'g_mystruct' (uniform 2-element array of structure{temp int i, temp float f})
0:30 1 (const int)
0:30 2.000000
0:30 3 (const int)
0:30 4.000000
0:30 Constant:
0:30 0 (const int)
0:30 Constant:
0:30 1 (const int)
0:30 indirect index (temp float)
0:30 'g_array' (uniform 5-element array of float)
0:30 1.000000
0:30 2.000000
0:30 3.000000
0:30 4.000000
0:30 5.000000
0:30 'idx' (temp void)
0:? Linker Objects
0:? 'g_array' (uniform 5-element array of float)
0:? 1.000000
0:? 2.000000
0:? 3.000000
0:? 4.000000
0:? 5.000000
0:? 'g_array_unused' (uniform 7-element array of float)
0:? 1.000000
0:? 2.000000
0:? 3.000000
0:? 4.000000
0:? 5.000000
0:? 6.000000
0:? 7.000000
0:? 'g_mystruct' (uniform 2-element array of structure{temp int i, temp float f})
0:? 1 (const int)
0:? 2.000000
0:? 3 (const int)
0:? 4.000000
// Module Version 10000
// Generated by (magic number): 80001
// Id's are bound by 62
Capability Shader
1: ExtInstImport "GLSL.std.450"
MemoryModel Logical GLSL450
EntryPoint Fragment 4 "PixelShaderFunction"
ExecutionMode 4 OriginUpperLeft
Name 4 "PixelShaderFunction"
Name 8 "PS_OUTPUT"
MemberName 8(PS_OUTPUT) 0 "color"
Name 12 "main(struct-PS_OUTPUT-vf41;"
Name 11 "ps_output"
Name 18 "l_array"
Name 28 "g_array"
Name 41 "mystruct"
MemberName 41(mystruct) 0 "i"
MemberName 41(mystruct) 1 "f"
Name 45 "g_mystruct"
Name 50 "idx"
Name 61 "g_array_unused"
2: TypeVoid
3: TypeFunction 2
6: TypeFloat 32
7: TypeVector 6(float) 4
8(PS_OUTPUT): TypeStruct 7(fvec4)
9: TypePointer Function 8(PS_OUTPUT)
10: TypeFunction 2 9(ptr)
14: TypeInt 32 0
15: 14(int) Constant 3
16: TypeArray 6(float) 15
17: TypePointer Function 16
19: 6(float) Constant 1065353216
20: 6(float) Constant 1073741824
21: 6(float) Constant 1077936128
22: 16 ConstantComposite 19 20 21
23: TypeInt 32 1
24: 23(int) Constant 0
25: 14(int) Constant 5
26: TypeArray 6(float) 25
27: TypePointer UniformConstant 26
28(g_array): 27(ptr) Variable UniformConstant
29: TypePointer UniformConstant 6(float)
32: 23(int) Constant 4
36: 23(int) Constant 1
37: TypePointer Function 6(float)
41(mystruct): TypeStruct 23(int) 6(float)
42: 14(int) Constant 2
43: TypeArray 41(mystruct) 42
44: TypePointer UniformConstant 43
45(g_mystruct): 44(ptr) Variable UniformConstant
49: TypePointer Function 2
56: TypePointer Function 7(fvec4)
58: 14(int) Constant 7
59: TypeArray 6(float) 58
60: TypePointer UniformConstant 59
61(g_array_unused): 60(ptr) Variable UniformConstant
4(PixelShaderFunction): 2 Function None 3
5: Label
FunctionEnd
12(main(struct-PS_OUTPUT-vf41;): 2 Function None 10
11(ps_output): 9(ptr) FunctionParameter
13: Label
18(l_array): 17(ptr) Variable Function
50(idx): 49(ptr) Variable Function
Store 18(l_array) 22
30: 29(ptr) AccessChain 28(g_array) 24
31: 6(float) Load 30
33: 29(ptr) AccessChain 28(g_array) 32
34: 6(float) Load 33
35: 6(float) FAdd 31 34
38: 37(ptr) AccessChain 18(l_array) 36
39: 6(float) Load 38
40: 6(float) FAdd 35 39
46: 29(ptr) AccessChain 45(g_mystruct) 24 36
47: 6(float) Load 46
48: 6(float) FAdd 40 47
51: 2 Load 50(idx)
52: 29(ptr) AccessChain 28(g_array) 51
53: 6(float) Load 52
54: 6(float) FAdd 48 53
55: 7(fvec4) CompositeConstruct 54 54 54 54
57: 56(ptr) AccessChain 11(ps_output) 24
Store 57 55
Return
FunctionEnd

Просмотреть файл

@ -0,0 +1,31 @@
// implicit sized array
uniform float g_array [ ] = { 1, 2, 3, 4, 5 };
// Unused implicit sized array
uniform float g_array_unused [ ] = { 1, 2, 3, 4, 5, 6, 7 };
// Test implicit size arrayed structs
uniform struct mystruct {
int i;
float f;
} g_mystruct[] = {
{ 1, 2.0 },
{ 3, 4.0 },
};
struct PS_OUTPUT { float4 color : SV_Target0; };
// INVALID: implicit size requires an initializer expression.
// uniform float bad[];
// INVALID: function parameters cannot be implicitly sized
// void BadFunction(int a[]) { }
void main(out PS_OUTPUT ps_output)
{
// implicit sized local array
float l_array[] = { 1, 2, 3 };
ps_output.color = g_array[0] + g_array[4] + l_array[1] + g_mystruct[0].f + g_array[idx];
}

Просмотреть файл

@ -81,6 +81,7 @@ INSTANTIATE_TEST_CASE_P(
ToSpirv, HlslCompileTest,
::testing::ValuesIn(std::vector<FileNameEntryPointPair>{
{"hlsl.array.frag", "PixelShaderFunction"},
{"hlsl.array.implicit-size.frag", "PixelShaderFunction"},
{"hlsl.assoc.frag", "PixelShaderFunction"},
{"hlsl.attribute.frag", "PixelShaderFunction"},
{"hlsl.buffer.frag", "PixelShaderFunction"},

Просмотреть файл

@ -1515,8 +1515,14 @@ bool HlslGrammar::acceptParameterDeclaration(TFunction& function)
// array_specifier
TArraySizes* arraySizes = nullptr;
acceptArraySpecifier(arraySizes);
if (arraySizes)
if (arraySizes) {
if (arraySizes->isImplicit()) {
parseContext.error(token.loc, "function parameter array cannot be implicitly sized", "", "");
return false;
}
type->newArraySizes(*arraySizes);
}
// post_decls
acceptPostDecls(type->getQualifier());
@ -2601,6 +2607,7 @@ bool HlslGrammar::acceptDefaultLabel(TIntermNode*& statement)
// array_specifier
// : LEFT_BRACKET integer_expression RGHT_BRACKET post_decls // optional
// : LEFT_BRACKET RGHT_BRACKET post_decls // optional
//
void HlslGrammar::acceptArraySpecifier(TArraySizes*& arraySizes)
{
@ -2610,21 +2617,25 @@ void HlslGrammar::acceptArraySpecifier(TArraySizes*& arraySizes)
return;
TSourceLoc loc = token.loc;
TIntermTyped* sizeExpr;
if (! acceptAssignmentExpression(sizeExpr)) {
expected("array-sizing expression");
return;
}
TIntermTyped* sizeExpr = nullptr;
// Array sizing expression is optional. If ommitted, array is implicitly sized.
const bool hasArraySize = acceptAssignmentExpression(sizeExpr);
if (! acceptTokenClass(EHTokRightBracket)) {
expected("]");
return;
}
arraySizes = new TArraySizes;
if (hasArraySize) {
TArraySize arraySize;
parseContext.arraySizeCheck(loc, sizeExpr, arraySize);
arraySizes = new TArraySizes;
arraySizes->addInnerSize(arraySize);
} else {
arraySizes->addInnerSize(); // implicitly sized
}
}
// post_decls