Flatten uniform arrays
This checkin adds a --flatten-uniform-arrays option which can break uniform arrays of samplers, textures, or UBOs up into individual scalars named (e.g) myarray[0], myarray[1], etc. These appear as individual linkage objects. Code notes: - shouldFlatten internally calls shouldFlattenIO, and shouldFlattenUniform, but is the only flattening query directly called. - flattenVariable will handle structs or arrays (but not yet arrayed structs; this is tested an an error is generated). - There's some error checking around unhandled situations. E.g, flattening uniform arrays with initializer lists is not implemented. - This piggybacks on as much of the existing mechanism for struct flattening as it can. E.g, it uses the same flattenMap, and the same flattenAccess() method. - handleAssign() has been generalized to cope with either structs or arrays. - Extended test infrastructure to test flattening ability.
This commit is contained in:
parent
6714bcc2ca
commit
e0b9debda2
@ -81,6 +81,7 @@ enum TOptions {
|
|||||||
EOptionReadHlsl = (1 << 17),
|
EOptionReadHlsl = (1 << 17),
|
||||||
EOptionCascadingErrors = (1 << 18),
|
EOptionCascadingErrors = (1 << 18),
|
||||||
EOptionAutoMapBindings = (1 << 19),
|
EOptionAutoMapBindings = (1 << 19),
|
||||||
|
EOptionFlattenUniformArrays = (1 << 20),
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -285,6 +286,10 @@ void ProcessArguments(int argc, char* argv[])
|
|||||||
lowerword == "auto-map-binding" ||
|
lowerword == "auto-map-binding" ||
|
||||||
lowerword == "amb") {
|
lowerword == "amb") {
|
||||||
Options |= EOptionAutoMapBindings;
|
Options |= EOptionAutoMapBindings;
|
||||||
|
} else if (lowerword == "flatten-uniform-arrays" || // synonyms
|
||||||
|
lowerword == "flatten-uniform-array" ||
|
||||||
|
lowerword == "fua") {
|
||||||
|
Options |= EOptionFlattenUniformArrays;
|
||||||
} else {
|
} else {
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
@ -407,6 +412,10 @@ void ProcessArguments(int argc, char* argv[])
|
|||||||
// -o or -x makes no sense if there is no target binary
|
// -o or -x makes no sense if there is no target binary
|
||||||
if (binaryFileName && (Options & EOptionSpv) == 0)
|
if (binaryFileName && (Options & EOptionSpv) == 0)
|
||||||
Error("no binary generation requested (e.g., -V)");
|
Error("no binary generation requested (e.g., -V)");
|
||||||
|
|
||||||
|
if ((Options & EOptionFlattenUniformArrays) != 0 &&
|
||||||
|
(Options & EOptionReadHlsl) == 0)
|
||||||
|
Error("uniform array flattening only valid when compiling HLSL source.");
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -532,6 +541,7 @@ void CompileAndLinkShaderUnits(std::vector<ShaderCompUnit> compUnits)
|
|||||||
shader->setShiftSamplerBinding(baseSamplerBinding[compUnit.stage]);
|
shader->setShiftSamplerBinding(baseSamplerBinding[compUnit.stage]);
|
||||||
shader->setShiftTextureBinding(baseTextureBinding[compUnit.stage]);
|
shader->setShiftTextureBinding(baseTextureBinding[compUnit.stage]);
|
||||||
shader->setShiftUboBinding(baseUboBinding[compUnit.stage]);
|
shader->setShiftUboBinding(baseUboBinding[compUnit.stage]);
|
||||||
|
shader->setFlattenUniformArrays((Options & EOptionFlattenUniformArrays) != 0);
|
||||||
|
|
||||||
if (Options & EOptionAutoMapBindings)
|
if (Options & EOptionAutoMapBindings)
|
||||||
shader->setAutoMapBindings(true);
|
shader->setAutoMapBindings(true);
|
||||||
@ -930,6 +940,9 @@ void usage()
|
|||||||
" --auto-map-bindings automatically bind uniform variables without\n"
|
" --auto-map-bindings automatically bind uniform variables without\n"
|
||||||
" explicit bindings.\n"
|
" explicit bindings.\n"
|
||||||
" --amb synonym for --auto-map-bindings\n"
|
" --amb synonym for --auto-map-bindings\n"
|
||||||
|
"\n"
|
||||||
|
" --flatten-uniform-arrays flatten uniform array references to scalars\n"
|
||||||
|
" --fua synonym for --flatten-uniform-arrays\n"
|
||||||
);
|
);
|
||||||
|
|
||||||
exit(EFailUsage);
|
exit(EFailUsage);
|
||||||
|
588
Test/baseResults/hlsl.array.flatten.frag.out
Normal file
588
Test/baseResults/hlsl.array.flatten.frag.out
Normal file
@ -0,0 +1,588 @@
|
|||||||
|
hlsl.array.flatten.frag
|
||||||
|
Shader version: 450
|
||||||
|
gl_FragCoord origin is upper left
|
||||||
|
0:? Sequence
|
||||||
|
0:17 Function Definition: TestFn1( (global 4-component vector of float)
|
||||||
|
0:17 Function Parameters:
|
||||||
|
0:? Sequence
|
||||||
|
0:18 Branch: Return with expression
|
||||||
|
0:18 texture (global 4-component vector of float)
|
||||||
|
0:18 Construct combined texture-sampler (temp sampler1D)
|
||||||
|
0:? 'g_tex[1]' (temp texture1D)
|
||||||
|
0:? 'g_samp[1]' (temp sampler)
|
||||||
|
0:18 Constant:
|
||||||
|
0:18 0.200000
|
||||||
|
0:22 Function Definition: TestFn2(t11[3];p1[3]; (global 4-component vector of float)
|
||||||
|
0:22 Function Parameters:
|
||||||
|
0:22 'l_tex' (in 3-element array of texture1D)
|
||||||
|
0:22 'l_samp' (in 3-element array of sampler)
|
||||||
|
0:? Sequence
|
||||||
|
0:23 Branch: Return with expression
|
||||||
|
0:23 texture (global 4-component vector of float)
|
||||||
|
0:23 Construct combined texture-sampler (temp sampler1D)
|
||||||
|
0:23 direct index (temp texture1D)
|
||||||
|
0:23 'l_tex' (in 3-element array of texture1D)
|
||||||
|
0:23 Constant:
|
||||||
|
0:23 2 (const int)
|
||||||
|
0:23 direct index (temp sampler)
|
||||||
|
0:23 'l_samp' (in 3-element array of sampler)
|
||||||
|
0:23 Constant:
|
||||||
|
0:23 2 (const int)
|
||||||
|
0:23 Constant:
|
||||||
|
0:23 0.200000
|
||||||
|
0:26 Sequence
|
||||||
|
0:26 move second child to first child (temp 5-element array of int)
|
||||||
|
0:26 'not_flattened_a' (global 5-element array of int)
|
||||||
|
0:26 Constant:
|
||||||
|
0:26 1 (const int)
|
||||||
|
0:26 2 (const int)
|
||||||
|
0:26 3 (const int)
|
||||||
|
0:26 4 (const int)
|
||||||
|
0:26 5 (const int)
|
||||||
|
0:31 Function Definition: main(struct-PS_OUTPUT-vf41; (global void)
|
||||||
|
0:31 Function Parameters:
|
||||||
|
0:31 'ps_output' (out structure{temp 4-component vector of float color})
|
||||||
|
0:? Sequence
|
||||||
|
0:33 Sequence
|
||||||
|
0:? Sequence
|
||||||
|
0:33 move second child to first child (temp sampler)
|
||||||
|
0:33 direct index (temp sampler)
|
||||||
|
0:33 'local_sampler_array' (temp 3-element array of sampler)
|
||||||
|
0:33 Constant:
|
||||||
|
0:33 0 (const int)
|
||||||
|
0:? 'g_samp[0]' (uniform sampler)
|
||||||
|
0:33 move second child to first child (temp sampler)
|
||||||
|
0:33 direct index (temp sampler)
|
||||||
|
0:33 'local_sampler_array' (temp 3-element array of sampler)
|
||||||
|
0:33 Constant:
|
||||||
|
0:33 1 (const int)
|
||||||
|
0:? 'g_samp[1]' (uniform sampler)
|
||||||
|
0:33 move second child to first child (temp sampler)
|
||||||
|
0:33 direct index (temp sampler)
|
||||||
|
0:33 'local_sampler_array' (temp 3-element array of sampler)
|
||||||
|
0:33 Constant:
|
||||||
|
0:33 2 (const int)
|
||||||
|
0:? 'g_samp[2]' (uniform sampler)
|
||||||
|
0:34 Sequence
|
||||||
|
0:? Sequence
|
||||||
|
0:34 move second child to first child (temp texture1D)
|
||||||
|
0:34 direct index (temp texture1D)
|
||||||
|
0:34 'local_texture_array' (temp 3-element array of texture1D)
|
||||||
|
0:34 Constant:
|
||||||
|
0:34 0 (const int)
|
||||||
|
0:? 'g_tex[0]' (uniform texture1D)
|
||||||
|
0:34 move second child to first child (temp texture1D)
|
||||||
|
0:34 direct index (temp texture1D)
|
||||||
|
0:34 'local_texture_array' (temp 3-element array of texture1D)
|
||||||
|
0:34 Constant:
|
||||||
|
0:34 1 (const int)
|
||||||
|
0:? 'g_tex[1]' (uniform texture1D)
|
||||||
|
0:34 move second child to first child (temp texture1D)
|
||||||
|
0:34 direct index (temp texture1D)
|
||||||
|
0:34 'local_texture_array' (temp 3-element array of texture1D)
|
||||||
|
0:34 Constant:
|
||||||
|
0:34 2 (const int)
|
||||||
|
0:? 'g_tex[2]' (uniform texture1D)
|
||||||
|
0:35 Sequence
|
||||||
|
0:? Sequence
|
||||||
|
0:35 move second child to first child (temp float)
|
||||||
|
0:35 direct index (temp float)
|
||||||
|
0:35 'local_float_array' (temp 4-element array of float)
|
||||||
|
0:35 Constant:
|
||||||
|
0:35 0 (const int)
|
||||||
|
0:? 'g_floats[0]' (uniform float)
|
||||||
|
0:35 move second child to first child (temp float)
|
||||||
|
0:35 direct index (temp float)
|
||||||
|
0:35 'local_float_array' (temp 4-element array of float)
|
||||||
|
0:35 Constant:
|
||||||
|
0:35 1 (const int)
|
||||||
|
0:? 'g_floats[1]' (uniform float)
|
||||||
|
0:35 move second child to first child (temp float)
|
||||||
|
0:35 direct index (temp float)
|
||||||
|
0:35 'local_float_array' (temp 4-element array of float)
|
||||||
|
0:35 Constant:
|
||||||
|
0:35 2 (const int)
|
||||||
|
0:? 'g_floats[2]' (uniform float)
|
||||||
|
0:35 move second child to first child (temp float)
|
||||||
|
0:35 direct index (temp float)
|
||||||
|
0:35 'local_float_array' (temp 4-element array of float)
|
||||||
|
0:35 Constant:
|
||||||
|
0:35 3 (const int)
|
||||||
|
0:? 'g_floats[3]' (uniform float)
|
||||||
|
0:37 move second child to first child (temp 4-component vector of float)
|
||||||
|
0:? 'color' (layout(location=0 ) out 4-component vector of float)
|
||||||
|
0:37 add (temp 4-component vector of float)
|
||||||
|
0:37 Function Call: TestFn1( (global 4-component vector of float)
|
||||||
|
0:37 Function Call: TestFn2(t11[3];p1[3]; (global 4-component vector of float)
|
||||||
|
0:? Comma (temp 3-element array of texture1D)
|
||||||
|
0:? Sequence
|
||||||
|
0:? move second child to first child (temp texture1D)
|
||||||
|
0:? direct index (temp texture1D)
|
||||||
|
0:? 'aggShadow' (temp 3-element array of texture1D)
|
||||||
|
0:? Constant:
|
||||||
|
0:? 0 (const int)
|
||||||
|
0:? 'g_tex[0]' (uniform texture1D)
|
||||||
|
0:? move second child to first child (temp texture1D)
|
||||||
|
0:? direct index (temp texture1D)
|
||||||
|
0:? 'aggShadow' (temp 3-element array of texture1D)
|
||||||
|
0:? Constant:
|
||||||
|
0:? 1 (const int)
|
||||||
|
0:? 'g_tex[1]' (uniform texture1D)
|
||||||
|
0:? move second child to first child (temp texture1D)
|
||||||
|
0:? direct index (temp texture1D)
|
||||||
|
0:? 'aggShadow' (temp 3-element array of texture1D)
|
||||||
|
0:? Constant:
|
||||||
|
0:? 2 (const int)
|
||||||
|
0:? 'g_tex[2]' (uniform texture1D)
|
||||||
|
0:? 'aggShadow' (temp 3-element array of texture1D)
|
||||||
|
0:? Comma (temp 3-element array of sampler)
|
||||||
|
0:? Sequence
|
||||||
|
0:? move second child to first child (temp sampler)
|
||||||
|
0:? direct index (temp sampler)
|
||||||
|
0:? 'aggShadow' (temp 3-element array of sampler)
|
||||||
|
0:? Constant:
|
||||||
|
0:? 0 (const int)
|
||||||
|
0:? 'g_samp[0]' (uniform sampler)
|
||||||
|
0:? move second child to first child (temp sampler)
|
||||||
|
0:? direct index (temp sampler)
|
||||||
|
0:? 'aggShadow' (temp 3-element array of sampler)
|
||||||
|
0:? Constant:
|
||||||
|
0:? 1 (const int)
|
||||||
|
0:? 'g_samp[1]' (uniform sampler)
|
||||||
|
0:? move second child to first child (temp sampler)
|
||||||
|
0:? direct index (temp sampler)
|
||||||
|
0:? 'aggShadow' (temp 3-element array of sampler)
|
||||||
|
0:? Constant:
|
||||||
|
0:? 2 (const int)
|
||||||
|
0:? 'g_samp[2]' (uniform sampler)
|
||||||
|
0:? 'aggShadow' (temp 3-element array of sampler)
|
||||||
|
0:? Linker Objects
|
||||||
|
0:? 'g_tex[0]' (uniform texture1D)
|
||||||
|
0:? 'g_tex[1]' (uniform texture1D)
|
||||||
|
0:? 'g_tex[2]' (uniform texture1D)
|
||||||
|
0:? 'g_tex_explicit[0]' (layout(binding=1 ) uniform texture1D)
|
||||||
|
0:? 'g_tex_explicit[1]' (layout(binding=2 ) uniform texture1D)
|
||||||
|
0:? 'g_tex_explicit[2]' (layout(binding=3 ) uniform texture1D)
|
||||||
|
0:? 'g_samp[0]' (uniform sampler)
|
||||||
|
0:? 'g_samp[1]' (uniform sampler)
|
||||||
|
0:? 'g_samp[2]' (uniform sampler)
|
||||||
|
0:? 'g_samp_explicit[0]' (layout(binding=5 ) uniform sampler)
|
||||||
|
0:? 'g_samp_explicit[1]' (layout(binding=6 ) uniform sampler)
|
||||||
|
0:? 'g_samp_explicit[2]' (layout(binding=7 ) uniform sampler)
|
||||||
|
0:? 'g_mats[0]' (uniform 3X3 matrix of float)
|
||||||
|
0:? 'g_mats[1]' (uniform 3X3 matrix of float)
|
||||||
|
0:? 'g_mats[2]' (uniform 3X3 matrix of float)
|
||||||
|
0:? 'g_mats[3]' (uniform 3X3 matrix of float)
|
||||||
|
0:? 'g_mats_explicit[0]' (layout(binding=10 ) uniform 3X3 matrix of float)
|
||||||
|
0:? 'g_mats_explicit[1]' (layout(binding=11 ) uniform 3X3 matrix of float)
|
||||||
|
0:? 'g_mats_explicit[2]' (layout(binding=12 ) uniform 3X3 matrix of float)
|
||||||
|
0:? 'g_mats_explicit[3]' (layout(binding=13 ) uniform 3X3 matrix of float)
|
||||||
|
0:? 'g_floats[0]' (uniform float)
|
||||||
|
0:? 'g_floats[1]' (uniform float)
|
||||||
|
0:? 'g_floats[2]' (uniform float)
|
||||||
|
0:? 'g_floats[3]' (uniform float)
|
||||||
|
0:? 'not_flattened_a' (global 5-element array of int)
|
||||||
|
0:? 'color' (layout(location=0 ) out 4-component vector of float)
|
||||||
|
|
||||||
|
|
||||||
|
Linked fragment stage:
|
||||||
|
|
||||||
|
|
||||||
|
Shader version: 450
|
||||||
|
gl_FragCoord origin is upper left
|
||||||
|
0:? Sequence
|
||||||
|
0:17 Function Definition: TestFn1( (global 4-component vector of float)
|
||||||
|
0:17 Function Parameters:
|
||||||
|
0:? Sequence
|
||||||
|
0:18 Branch: Return with expression
|
||||||
|
0:18 texture (global 4-component vector of float)
|
||||||
|
0:18 Construct combined texture-sampler (temp sampler1D)
|
||||||
|
0:? 'g_tex[1]' (temp texture1D)
|
||||||
|
0:? 'g_samp[1]' (temp sampler)
|
||||||
|
0:18 Constant:
|
||||||
|
0:18 0.200000
|
||||||
|
0:22 Function Definition: TestFn2(t11[3];p1[3]; (global 4-component vector of float)
|
||||||
|
0:22 Function Parameters:
|
||||||
|
0:22 'l_tex' (in 3-element array of texture1D)
|
||||||
|
0:22 'l_samp' (in 3-element array of sampler)
|
||||||
|
0:? Sequence
|
||||||
|
0:23 Branch: Return with expression
|
||||||
|
0:23 texture (global 4-component vector of float)
|
||||||
|
0:23 Construct combined texture-sampler (temp sampler1D)
|
||||||
|
0:23 direct index (temp texture1D)
|
||||||
|
0:23 'l_tex' (in 3-element array of texture1D)
|
||||||
|
0:23 Constant:
|
||||||
|
0:23 2 (const int)
|
||||||
|
0:23 direct index (temp sampler)
|
||||||
|
0:23 'l_samp' (in 3-element array of sampler)
|
||||||
|
0:23 Constant:
|
||||||
|
0:23 2 (const int)
|
||||||
|
0:23 Constant:
|
||||||
|
0:23 0.200000
|
||||||
|
0:26 Sequence
|
||||||
|
0:26 move second child to first child (temp 5-element array of int)
|
||||||
|
0:26 'not_flattened_a' (global 5-element array of int)
|
||||||
|
0:26 Constant:
|
||||||
|
0:26 1 (const int)
|
||||||
|
0:26 2 (const int)
|
||||||
|
0:26 3 (const int)
|
||||||
|
0:26 4 (const int)
|
||||||
|
0:26 5 (const int)
|
||||||
|
0:31 Function Definition: main(struct-PS_OUTPUT-vf41; (global void)
|
||||||
|
0:31 Function Parameters:
|
||||||
|
0:31 'ps_output' (out structure{temp 4-component vector of float color})
|
||||||
|
0:? Sequence
|
||||||
|
0:33 Sequence
|
||||||
|
0:? Sequence
|
||||||
|
0:33 move second child to first child (temp sampler)
|
||||||
|
0:33 direct index (temp sampler)
|
||||||
|
0:33 'local_sampler_array' (temp 3-element array of sampler)
|
||||||
|
0:33 Constant:
|
||||||
|
0:33 0 (const int)
|
||||||
|
0:? 'g_samp[0]' (uniform sampler)
|
||||||
|
0:33 move second child to first child (temp sampler)
|
||||||
|
0:33 direct index (temp sampler)
|
||||||
|
0:33 'local_sampler_array' (temp 3-element array of sampler)
|
||||||
|
0:33 Constant:
|
||||||
|
0:33 1 (const int)
|
||||||
|
0:? 'g_samp[1]' (uniform sampler)
|
||||||
|
0:33 move second child to first child (temp sampler)
|
||||||
|
0:33 direct index (temp sampler)
|
||||||
|
0:33 'local_sampler_array' (temp 3-element array of sampler)
|
||||||
|
0:33 Constant:
|
||||||
|
0:33 2 (const int)
|
||||||
|
0:? 'g_samp[2]' (uniform sampler)
|
||||||
|
0:34 Sequence
|
||||||
|
0:? Sequence
|
||||||
|
0:34 move second child to first child (temp texture1D)
|
||||||
|
0:34 direct index (temp texture1D)
|
||||||
|
0:34 'local_texture_array' (temp 3-element array of texture1D)
|
||||||
|
0:34 Constant:
|
||||||
|
0:34 0 (const int)
|
||||||
|
0:? 'g_tex[0]' (uniform texture1D)
|
||||||
|
0:34 move second child to first child (temp texture1D)
|
||||||
|
0:34 direct index (temp texture1D)
|
||||||
|
0:34 'local_texture_array' (temp 3-element array of texture1D)
|
||||||
|
0:34 Constant:
|
||||||
|
0:34 1 (const int)
|
||||||
|
0:? 'g_tex[1]' (uniform texture1D)
|
||||||
|
0:34 move second child to first child (temp texture1D)
|
||||||
|
0:34 direct index (temp texture1D)
|
||||||
|
0:34 'local_texture_array' (temp 3-element array of texture1D)
|
||||||
|
0:34 Constant:
|
||||||
|
0:34 2 (const int)
|
||||||
|
0:? 'g_tex[2]' (uniform texture1D)
|
||||||
|
0:35 Sequence
|
||||||
|
0:? Sequence
|
||||||
|
0:35 move second child to first child (temp float)
|
||||||
|
0:35 direct index (temp float)
|
||||||
|
0:35 'local_float_array' (temp 4-element array of float)
|
||||||
|
0:35 Constant:
|
||||||
|
0:35 0 (const int)
|
||||||
|
0:? 'g_floats[0]' (uniform float)
|
||||||
|
0:35 move second child to first child (temp float)
|
||||||
|
0:35 direct index (temp float)
|
||||||
|
0:35 'local_float_array' (temp 4-element array of float)
|
||||||
|
0:35 Constant:
|
||||||
|
0:35 1 (const int)
|
||||||
|
0:? 'g_floats[1]' (uniform float)
|
||||||
|
0:35 move second child to first child (temp float)
|
||||||
|
0:35 direct index (temp float)
|
||||||
|
0:35 'local_float_array' (temp 4-element array of float)
|
||||||
|
0:35 Constant:
|
||||||
|
0:35 2 (const int)
|
||||||
|
0:? 'g_floats[2]' (uniform float)
|
||||||
|
0:35 move second child to first child (temp float)
|
||||||
|
0:35 direct index (temp float)
|
||||||
|
0:35 'local_float_array' (temp 4-element array of float)
|
||||||
|
0:35 Constant:
|
||||||
|
0:35 3 (const int)
|
||||||
|
0:? 'g_floats[3]' (uniform float)
|
||||||
|
0:37 move second child to first child (temp 4-component vector of float)
|
||||||
|
0:? 'color' (layout(location=0 ) out 4-component vector of float)
|
||||||
|
0:37 add (temp 4-component vector of float)
|
||||||
|
0:37 Function Call: TestFn1( (global 4-component vector of float)
|
||||||
|
0:37 Function Call: TestFn2(t11[3];p1[3]; (global 4-component vector of float)
|
||||||
|
0:? Comma (temp 3-element array of texture1D)
|
||||||
|
0:? Sequence
|
||||||
|
0:? move second child to first child (temp texture1D)
|
||||||
|
0:? direct index (temp texture1D)
|
||||||
|
0:? 'aggShadow' (temp 3-element array of texture1D)
|
||||||
|
0:? Constant:
|
||||||
|
0:? 0 (const int)
|
||||||
|
0:? 'g_tex[0]' (uniform texture1D)
|
||||||
|
0:? move second child to first child (temp texture1D)
|
||||||
|
0:? direct index (temp texture1D)
|
||||||
|
0:? 'aggShadow' (temp 3-element array of texture1D)
|
||||||
|
0:? Constant:
|
||||||
|
0:? 1 (const int)
|
||||||
|
0:? 'g_tex[1]' (uniform texture1D)
|
||||||
|
0:? move second child to first child (temp texture1D)
|
||||||
|
0:? direct index (temp texture1D)
|
||||||
|
0:? 'aggShadow' (temp 3-element array of texture1D)
|
||||||
|
0:? Constant:
|
||||||
|
0:? 2 (const int)
|
||||||
|
0:? 'g_tex[2]' (uniform texture1D)
|
||||||
|
0:? 'aggShadow' (temp 3-element array of texture1D)
|
||||||
|
0:? Comma (temp 3-element array of sampler)
|
||||||
|
0:? Sequence
|
||||||
|
0:? move second child to first child (temp sampler)
|
||||||
|
0:? direct index (temp sampler)
|
||||||
|
0:? 'aggShadow' (temp 3-element array of sampler)
|
||||||
|
0:? Constant:
|
||||||
|
0:? 0 (const int)
|
||||||
|
0:? 'g_samp[0]' (uniform sampler)
|
||||||
|
0:? move second child to first child (temp sampler)
|
||||||
|
0:? direct index (temp sampler)
|
||||||
|
0:? 'aggShadow' (temp 3-element array of sampler)
|
||||||
|
0:? Constant:
|
||||||
|
0:? 1 (const int)
|
||||||
|
0:? 'g_samp[1]' (uniform sampler)
|
||||||
|
0:? move second child to first child (temp sampler)
|
||||||
|
0:? direct index (temp sampler)
|
||||||
|
0:? 'aggShadow' (temp 3-element array of sampler)
|
||||||
|
0:? Constant:
|
||||||
|
0:? 2 (const int)
|
||||||
|
0:? 'g_samp[2]' (uniform sampler)
|
||||||
|
0:? 'aggShadow' (temp 3-element array of sampler)
|
||||||
|
0:? Linker Objects
|
||||||
|
0:? 'g_tex[0]' (uniform texture1D)
|
||||||
|
0:? 'g_tex[1]' (uniform texture1D)
|
||||||
|
0:? 'g_tex[2]' (uniform texture1D)
|
||||||
|
0:? 'g_tex_explicit[0]' (layout(binding=1 ) uniform texture1D)
|
||||||
|
0:? 'g_tex_explicit[1]' (layout(binding=2 ) uniform texture1D)
|
||||||
|
0:? 'g_tex_explicit[2]' (layout(binding=3 ) uniform texture1D)
|
||||||
|
0:? 'g_samp[0]' (uniform sampler)
|
||||||
|
0:? 'g_samp[1]' (uniform sampler)
|
||||||
|
0:? 'g_samp[2]' (uniform sampler)
|
||||||
|
0:? 'g_samp_explicit[0]' (layout(binding=5 ) uniform sampler)
|
||||||
|
0:? 'g_samp_explicit[1]' (layout(binding=6 ) uniform sampler)
|
||||||
|
0:? 'g_samp_explicit[2]' (layout(binding=7 ) uniform sampler)
|
||||||
|
0:? 'g_mats[0]' (uniform 3X3 matrix of float)
|
||||||
|
0:? 'g_mats[1]' (uniform 3X3 matrix of float)
|
||||||
|
0:? 'g_mats[2]' (uniform 3X3 matrix of float)
|
||||||
|
0:? 'g_mats[3]' (uniform 3X3 matrix of float)
|
||||||
|
0:? 'g_mats_explicit[0]' (layout(binding=10 ) uniform 3X3 matrix of float)
|
||||||
|
0:? 'g_mats_explicit[1]' (layout(binding=11 ) uniform 3X3 matrix of float)
|
||||||
|
0:? 'g_mats_explicit[2]' (layout(binding=12 ) uniform 3X3 matrix of float)
|
||||||
|
0:? 'g_mats_explicit[3]' (layout(binding=13 ) uniform 3X3 matrix of float)
|
||||||
|
0:? 'g_floats[0]' (uniform float)
|
||||||
|
0:? 'g_floats[1]' (uniform float)
|
||||||
|
0:? 'g_floats[2]' (uniform float)
|
||||||
|
0:? 'g_floats[3]' (uniform float)
|
||||||
|
0:? 'not_flattened_a' (global 5-element array of int)
|
||||||
|
0:? 'color' (layout(location=0 ) out 4-component vector of float)
|
||||||
|
|
||||||
|
// Module Version 10000
|
||||||
|
// Generated by (magic number): 80001
|
||||||
|
// Id's are bound by 128
|
||||||
|
|
||||||
|
Capability Shader
|
||||||
|
Capability Sampled1D
|
||||||
|
1: ExtInstImport "GLSL.std.450"
|
||||||
|
MemoryModel Logical GLSL450
|
||||||
|
EntryPoint Fragment 4 "main" 93
|
||||||
|
ExecutionMode 4 OriginUpperLeft
|
||||||
|
Name 4 "main"
|
||||||
|
Name 9 "TestFn1("
|
||||||
|
Name 22 "TestFn2(t11[3];p1[3];"
|
||||||
|
Name 20 "l_tex"
|
||||||
|
Name 21 "l_samp"
|
||||||
|
Name 28 "not_flattened_a"
|
||||||
|
Name 36 "g_tex[1]"
|
||||||
|
Name 39 "g_samp[1]"
|
||||||
|
Name 55 "local_sampler_array"
|
||||||
|
Name 57 "g_samp[0]"
|
||||||
|
Name 62 "g_samp[2]"
|
||||||
|
Name 65 "local_texture_array"
|
||||||
|
Name 66 "g_tex[0]"
|
||||||
|
Name 71 "g_tex[2]"
|
||||||
|
Name 77 "local_float_array"
|
||||||
|
Name 79 "g_floats[0]"
|
||||||
|
Name 83 "g_floats[1]"
|
||||||
|
Name 86 "g_floats[2]"
|
||||||
|
Name 89 "g_floats[3]"
|
||||||
|
Name 93 "color"
|
||||||
|
Name 95 "aggShadow"
|
||||||
|
Name 102 "aggShadow"
|
||||||
|
Name 111 "g_tex_explicit[0]"
|
||||||
|
Name 112 "g_tex_explicit[1]"
|
||||||
|
Name 113 "g_tex_explicit[2]"
|
||||||
|
Name 114 "g_samp_explicit[0]"
|
||||||
|
Name 115 "g_samp_explicit[1]"
|
||||||
|
Name 116 "g_samp_explicit[2]"
|
||||||
|
Name 120 "g_mats[0]"
|
||||||
|
Name 121 "g_mats[1]"
|
||||||
|
Name 122 "g_mats[2]"
|
||||||
|
Name 123 "g_mats[3]"
|
||||||
|
Name 124 "g_mats_explicit[0]"
|
||||||
|
Name 125 "g_mats_explicit[1]"
|
||||||
|
Name 126 "g_mats_explicit[2]"
|
||||||
|
Name 127 "g_mats_explicit[3]"
|
||||||
|
Decorate 57(g_samp[0]) DescriptorSet 0
|
||||||
|
Decorate 62(g_samp[2]) DescriptorSet 0
|
||||||
|
Decorate 66(g_tex[0]) DescriptorSet 0
|
||||||
|
Decorate 71(g_tex[2]) DescriptorSet 0
|
||||||
|
Decorate 93(color) Location 0
|
||||||
|
Decorate 111(g_tex_explicit[0]) DescriptorSet 0
|
||||||
|
Decorate 111(g_tex_explicit[0]) Binding 1
|
||||||
|
Decorate 112(g_tex_explicit[1]) DescriptorSet 0
|
||||||
|
Decorate 112(g_tex_explicit[1]) Binding 2
|
||||||
|
Decorate 113(g_tex_explicit[2]) DescriptorSet 0
|
||||||
|
Decorate 113(g_tex_explicit[2]) Binding 3
|
||||||
|
Decorate 114(g_samp_explicit[0]) DescriptorSet 0
|
||||||
|
Decorate 114(g_samp_explicit[0]) Binding 5
|
||||||
|
Decorate 115(g_samp_explicit[1]) DescriptorSet 0
|
||||||
|
Decorate 115(g_samp_explicit[1]) Binding 6
|
||||||
|
Decorate 116(g_samp_explicit[2]) DescriptorSet 0
|
||||||
|
Decorate 116(g_samp_explicit[2]) Binding 7
|
||||||
|
Decorate 124(g_mats_explicit[0]) Binding 10
|
||||||
|
Decorate 125(g_mats_explicit[1]) Binding 11
|
||||||
|
Decorate 126(g_mats_explicit[2]) Binding 12
|
||||||
|
Decorate 127(g_mats_explicit[3]) Binding 13
|
||||||
|
2: TypeVoid
|
||||||
|
3: TypeFunction 2
|
||||||
|
6: TypeFloat 32
|
||||||
|
7: TypeVector 6(float) 4
|
||||||
|
8: TypeFunction 7(fvec4)
|
||||||
|
11: TypeImage 6(float) 1D sampled format:Unknown
|
||||||
|
12: TypeInt 32 0
|
||||||
|
13: 12(int) Constant 3
|
||||||
|
14: TypeArray 11 13
|
||||||
|
15: TypePointer UniformConstant 14
|
||||||
|
16: TypeSampler
|
||||||
|
17: TypeArray 16 13
|
||||||
|
18: TypePointer UniformConstant 17
|
||||||
|
19: TypeFunction 7(fvec4) 15(ptr) 18(ptr)
|
||||||
|
24: TypeInt 32 1
|
||||||
|
25: 12(int) Constant 5
|
||||||
|
26: TypeArray 24(int) 25
|
||||||
|
27: TypePointer Private 26
|
||||||
|
28(not_flattened_a): 27(ptr) Variable Private
|
||||||
|
29: 24(int) Constant 1
|
||||||
|
30: 24(int) Constant 2
|
||||||
|
31: 24(int) Constant 3
|
||||||
|
32: 24(int) Constant 4
|
||||||
|
33: 24(int) Constant 5
|
||||||
|
34: 26 ConstantComposite 29 30 31 32 33
|
||||||
|
35: TypePointer UniformConstant 11
|
||||||
|
36(g_tex[1]): 35(ptr) Variable UniformConstant
|
||||||
|
38: TypePointer UniformConstant 16
|
||||||
|
39(g_samp[1]): 38(ptr) Variable UniformConstant
|
||||||
|
41: TypeSampledImage 11
|
||||||
|
43: 6(float) Constant 1045220557
|
||||||
|
55(local_sampler_array): 18(ptr) Variable UniformConstant
|
||||||
|
56: 24(int) Constant 0
|
||||||
|
57(g_samp[0]): 38(ptr) Variable UniformConstant
|
||||||
|
62(g_samp[2]): 38(ptr) Variable UniformConstant
|
||||||
|
65(local_texture_array): 15(ptr) Variable UniformConstant
|
||||||
|
66(g_tex[0]): 35(ptr) Variable UniformConstant
|
||||||
|
71(g_tex[2]): 35(ptr) Variable UniformConstant
|
||||||
|
74: 12(int) Constant 4
|
||||||
|
75: TypeArray 6(float) 74
|
||||||
|
76: TypePointer Function 75
|
||||||
|
78: TypePointer UniformConstant 6(float)
|
||||||
|
79(g_floats[0]): 78(ptr) Variable UniformConstant
|
||||||
|
81: TypePointer Function 6(float)
|
||||||
|
83(g_floats[1]): 78(ptr) Variable UniformConstant
|
||||||
|
86(g_floats[2]): 78(ptr) Variable UniformConstant
|
||||||
|
89(g_floats[3]): 78(ptr) Variable UniformConstant
|
||||||
|
92: TypePointer Output 7(fvec4)
|
||||||
|
93(color): 92(ptr) Variable Output
|
||||||
|
95(aggShadow): 15(ptr) Variable UniformConstant
|
||||||
|
102(aggShadow): 18(ptr) Variable UniformConstant
|
||||||
|
111(g_tex_explicit[0]): 35(ptr) Variable UniformConstant
|
||||||
|
112(g_tex_explicit[1]): 35(ptr) Variable UniformConstant
|
||||||
|
113(g_tex_explicit[2]): 35(ptr) Variable UniformConstant
|
||||||
|
114(g_samp_explicit[0]): 38(ptr) Variable UniformConstant
|
||||||
|
115(g_samp_explicit[1]): 38(ptr) Variable UniformConstant
|
||||||
|
116(g_samp_explicit[2]): 38(ptr) Variable UniformConstant
|
||||||
|
117: TypeVector 6(float) 3
|
||||||
|
118: TypeMatrix 117(fvec3) 3
|
||||||
|
119: TypePointer UniformConstant 118
|
||||||
|
120(g_mats[0]): 119(ptr) Variable UniformConstant
|
||||||
|
121(g_mats[1]): 119(ptr) Variable UniformConstant
|
||||||
|
122(g_mats[2]): 119(ptr) Variable UniformConstant
|
||||||
|
123(g_mats[3]): 119(ptr) Variable UniformConstant
|
||||||
|
124(g_mats_explicit[0]): 119(ptr) Variable UniformConstant
|
||||||
|
125(g_mats_explicit[1]): 119(ptr) Variable UniformConstant
|
||||||
|
126(g_mats_explicit[2]): 119(ptr) Variable UniformConstant
|
||||||
|
127(g_mats_explicit[3]): 119(ptr) Variable UniformConstant
|
||||||
|
4(main): 2 Function None 3
|
||||||
|
5: Label
|
||||||
|
77(local_float_array): 76(ptr) Variable Function
|
||||||
|
Store 28(not_flattened_a) 34
|
||||||
|
58: 16 Load 57(g_samp[0])
|
||||||
|
59: 38(ptr) AccessChain 55(local_sampler_array) 56
|
||||||
|
Store 59 58
|
||||||
|
60: 16 Load 39(g_samp[1])
|
||||||
|
61: 38(ptr) AccessChain 55(local_sampler_array) 29
|
||||||
|
Store 61 60
|
||||||
|
63: 16 Load 62(g_samp[2])
|
||||||
|
64: 38(ptr) AccessChain 55(local_sampler_array) 30
|
||||||
|
Store 64 63
|
||||||
|
67: 11 Load 66(g_tex[0])
|
||||||
|
68: 35(ptr) AccessChain 65(local_texture_array) 56
|
||||||
|
Store 68 67
|
||||||
|
69: 11 Load 36(g_tex[1])
|
||||||
|
70: 35(ptr) AccessChain 65(local_texture_array) 29
|
||||||
|
Store 70 69
|
||||||
|
72: 11 Load 71(g_tex[2])
|
||||||
|
73: 35(ptr) AccessChain 65(local_texture_array) 30
|
||||||
|
Store 73 72
|
||||||
|
80: 6(float) Load 79(g_floats[0])
|
||||||
|
82: 81(ptr) AccessChain 77(local_float_array) 56
|
||||||
|
Store 82 80
|
||||||
|
84: 6(float) Load 83(g_floats[1])
|
||||||
|
85: 81(ptr) AccessChain 77(local_float_array) 29
|
||||||
|
Store 85 84
|
||||||
|
87: 6(float) Load 86(g_floats[2])
|
||||||
|
88: 81(ptr) AccessChain 77(local_float_array) 30
|
||||||
|
Store 88 87
|
||||||
|
90: 6(float) Load 89(g_floats[3])
|
||||||
|
91: 81(ptr) AccessChain 77(local_float_array) 31
|
||||||
|
Store 91 90
|
||||||
|
94: 7(fvec4) FunctionCall 9(TestFn1()
|
||||||
|
96: 11 Load 66(g_tex[0])
|
||||||
|
97: 35(ptr) AccessChain 95(aggShadow) 56
|
||||||
|
Store 97 96
|
||||||
|
98: 11 Load 36(g_tex[1])
|
||||||
|
99: 35(ptr) AccessChain 95(aggShadow) 29
|
||||||
|
Store 99 98
|
||||||
|
100: 11 Load 71(g_tex[2])
|
||||||
|
101: 35(ptr) AccessChain 95(aggShadow) 30
|
||||||
|
Store 101 100
|
||||||
|
103: 16 Load 57(g_samp[0])
|
||||||
|
104: 38(ptr) AccessChain 102(aggShadow) 56
|
||||||
|
Store 104 103
|
||||||
|
105: 16 Load 39(g_samp[1])
|
||||||
|
106: 38(ptr) AccessChain 102(aggShadow) 29
|
||||||
|
Store 106 105
|
||||||
|
107: 16 Load 62(g_samp[2])
|
||||||
|
108: 38(ptr) AccessChain 102(aggShadow) 30
|
||||||
|
Store 108 107
|
||||||
|
109: 7(fvec4) FunctionCall 22(TestFn2(t11[3];p1[3];) 95(aggShadow) 102(aggShadow)
|
||||||
|
110: 7(fvec4) FAdd 94 109
|
||||||
|
Store 93(color) 110
|
||||||
|
Return
|
||||||
|
FunctionEnd
|
||||||
|
9(TestFn1(): 7(fvec4) Function None 8
|
||||||
|
10: Label
|
||||||
|
37: 11 Load 36(g_tex[1])
|
||||||
|
40: 16 Load 39(g_samp[1])
|
||||||
|
42: 41 SampledImage 37 40
|
||||||
|
44: 7(fvec4) ImageSampleImplicitLod 42 43
|
||||||
|
ReturnValue 44
|
||||||
|
FunctionEnd
|
||||||
|
22(TestFn2(t11[3];p1[3];): 7(fvec4) Function None 19
|
||||||
|
20(l_tex): 15(ptr) FunctionParameter
|
||||||
|
21(l_samp): 18(ptr) FunctionParameter
|
||||||
|
23: Label
|
||||||
|
47: 35(ptr) AccessChain 20(l_tex) 30
|
||||||
|
48: 11 Load 47
|
||||||
|
49: 38(ptr) AccessChain 21(l_samp) 30
|
||||||
|
50: 16 Load 49
|
||||||
|
51: 41 SampledImage 48 50
|
||||||
|
52: 7(fvec4) ImageSampleImplicitLod 51 43
|
||||||
|
ReturnValue 52
|
||||||
|
FunctionEnd
|
38
Test/hlsl.array.flatten.frag
Normal file
38
Test/hlsl.array.flatten.frag
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
|
||||||
|
// uniform Texture1D g_tex3[3][2]; // TODO: legal in HLSL, but we don't handle it yet.
|
||||||
|
|
||||||
|
uniform Texture1D g_tex[3];
|
||||||
|
uniform Texture1D g_tex_explicit[3] : register(t1);
|
||||||
|
|
||||||
|
SamplerState g_samp[3];
|
||||||
|
SamplerState g_samp_explicit[3] : register(s5);
|
||||||
|
|
||||||
|
uniform float3x3 g_mats[4];
|
||||||
|
uniform float3x3 g_mats_explicit[4] : register(b10);
|
||||||
|
uniform float g_floats[4];
|
||||||
|
|
||||||
|
// uniform float g_floats[4] = { 10, 11, 12, 13 }; // TODO: ... add when initializer lists can be flattened.
|
||||||
|
|
||||||
|
float4 TestFn1()
|
||||||
|
{
|
||||||
|
return g_tex[1].Sample(g_samp[1], 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
float4 TestFn2(Texture1D l_tex[3], SamplerState l_samp[3])
|
||||||
|
{
|
||||||
|
return l_tex[2].Sample(l_samp[2], 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
int not_flattened_a[5] = { 1, 2, 3, 4, 5 };
|
||||||
|
|
||||||
|
struct PS_OUTPUT { float4 color : SV_Target0; };
|
||||||
|
|
||||||
|
void main(out PS_OUTPUT ps_output)
|
||||||
|
{
|
||||||
|
// test flattening for local assignment initialization
|
||||||
|
SamplerState local_sampler_array[3] = g_samp;
|
||||||
|
Texture1D local_texture_array[3] = g_tex;
|
||||||
|
float local_float_array[4] = g_floats;
|
||||||
|
|
||||||
|
ps_output.color = TestFn1() + TestFn2(g_tex, g_samp);
|
||||||
|
}
|
@ -424,6 +424,11 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
|
|||||||
// opaque types can be passed to functions
|
// opaque types can be passed to functions
|
||||||
if (op == EOpFunction)
|
if (op == EOpFunction)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// HLSL can assign samplers directly (no constructor)
|
||||||
|
if (source == EShSourceHlsl && node->getBasicType() == EbtSampler)
|
||||||
|
break;
|
||||||
|
|
||||||
// samplers can get assigned via a sampler constructor
|
// samplers can get assigned via a sampler constructor
|
||||||
// (well, not yet, but code in the rest of this function is ready for it)
|
// (well, not yet, but code in the rest of this function is ready for it)
|
||||||
if (node->getBasicType() == EbtSampler && op == EOpAssign &&
|
if (node->getBasicType() == EbtSampler && op == EOpAssign &&
|
||||||
|
@ -1493,6 +1493,8 @@ void TShader::setShiftSamplerBinding(unsigned int base) { intermediate->setShift
|
|||||||
void TShader::setShiftTextureBinding(unsigned int base) { intermediate->setShiftTextureBinding(base); }
|
void TShader::setShiftTextureBinding(unsigned int base) { intermediate->setShiftTextureBinding(base); }
|
||||||
void TShader::setShiftUboBinding(unsigned int base) { intermediate->setShiftUboBinding(base); }
|
void TShader::setShiftUboBinding(unsigned int base) { intermediate->setShiftUboBinding(base); }
|
||||||
void TShader::setAutoMapBindings(bool map) { intermediate->setAutoMapBindings(map); }
|
void TShader::setAutoMapBindings(bool map) { intermediate->setAutoMapBindings(map); }
|
||||||
|
void TShader::setFlattenUniformArrays(bool flatten) { intermediate->setFlattenUniformArrays(flatten); }
|
||||||
|
|
||||||
//
|
//
|
||||||
// Turn the shader strings into a parse tree in the TIntermediate.
|
// Turn the shader strings into a parse tree in the TIntermediate.
|
||||||
//
|
//
|
||||||
|
@ -145,7 +145,8 @@ public:
|
|||||||
shiftSamplerBinding(0),
|
shiftSamplerBinding(0),
|
||||||
shiftTextureBinding(0),
|
shiftTextureBinding(0),
|
||||||
shiftUboBinding(0),
|
shiftUboBinding(0),
|
||||||
autoMapBindings(false)
|
autoMapBindings(false),
|
||||||
|
flattenUniformArrays(false)
|
||||||
{
|
{
|
||||||
localSize[0] = 1;
|
localSize[0] = 1;
|
||||||
localSize[1] = 1;
|
localSize[1] = 1;
|
||||||
@ -176,6 +177,8 @@ public:
|
|||||||
unsigned int getShiftUboBinding() const { return shiftUboBinding; }
|
unsigned int getShiftUboBinding() const { return shiftUboBinding; }
|
||||||
void setAutoMapBindings(bool map) { autoMapBindings = map; }
|
void setAutoMapBindings(bool map) { autoMapBindings = map; }
|
||||||
bool getAutoMapBindings() const { return autoMapBindings; }
|
bool getAutoMapBindings() const { return autoMapBindings; }
|
||||||
|
void setFlattenUniformArrays(bool flatten) { flattenUniformArrays = flatten; }
|
||||||
|
bool getFlattenUniformArrays() const { return flattenUniformArrays; }
|
||||||
|
|
||||||
void setVersion(int v) { version = v; }
|
void setVersion(int v) { version = v; }
|
||||||
int getVersion() const { return version; }
|
int getVersion() const { return version; }
|
||||||
@ -385,6 +388,7 @@ protected:
|
|||||||
unsigned int shiftTextureBinding;
|
unsigned int shiftTextureBinding;
|
||||||
unsigned int shiftUboBinding;
|
unsigned int shiftUboBinding;
|
||||||
bool autoMapBindings;
|
bool autoMapBindings;
|
||||||
|
bool flattenUniformArrays;
|
||||||
|
|
||||||
EProfile profile;
|
EProfile profile;
|
||||||
int version;
|
int version;
|
||||||
|
@ -304,6 +304,7 @@ public:
|
|||||||
void setShiftTextureBinding(unsigned int base);
|
void setShiftTextureBinding(unsigned int base);
|
||||||
void setShiftUboBinding(unsigned int base);
|
void setShiftUboBinding(unsigned int base);
|
||||||
void setAutoMapBindings(bool map);
|
void setAutoMapBindings(bool map);
|
||||||
|
void setFlattenUniformArrays(bool flatten);
|
||||||
|
|
||||||
// Interface to #include handlers.
|
// Interface to #include handlers.
|
||||||
//
|
//
|
||||||
|
@ -58,6 +58,7 @@ std::string FileNameAsCustomTestSuffix(
|
|||||||
}
|
}
|
||||||
|
|
||||||
using HlslCompileTest = GlslangTest<::testing::TestWithParam<FileNameEntryPointPair>>;
|
using HlslCompileTest = GlslangTest<::testing::TestWithParam<FileNameEntryPointPair>>;
|
||||||
|
using HlslCompileAndFlattenTest = GlslangTest<::testing::TestWithParam<FileNameEntryPointPair>>;
|
||||||
|
|
||||||
// Compiling HLSL to SPIR-V under Vulkan semantics. Expected to successfully
|
// Compiling HLSL to SPIR-V under Vulkan semantics. Expected to successfully
|
||||||
// generate both AST and SPIR-V.
|
// generate both AST and SPIR-V.
|
||||||
@ -68,6 +69,13 @@ TEST_P(HlslCompileTest, FromFile)
|
|||||||
Target::BothASTAndSpv, GetParam().entryPoint);
|
Target::BothASTAndSpv, GetParam().entryPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_P(HlslCompileAndFlattenTest, FromFile)
|
||||||
|
{
|
||||||
|
loadFileCompileFlattenUniformsAndCheck(GLSLANG_TEST_DIRECTORY, GetParam().fileName,
|
||||||
|
Source::HLSL, Semantics::Vulkan,
|
||||||
|
Target::BothASTAndSpv, GetParam().entryPoint);
|
||||||
|
}
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
INSTANTIATE_TEST_CASE_P(
|
INSTANTIATE_TEST_CASE_P(
|
||||||
ToSpirv, HlslCompileTest,
|
ToSpirv, HlslCompileTest,
|
||||||
@ -181,5 +189,15 @@ INSTANTIATE_TEST_CASE_P(
|
|||||||
);
|
);
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
INSTANTIATE_TEST_CASE_P(
|
||||||
|
ToSpirv, HlslCompileAndFlattenTest,
|
||||||
|
::testing::ValuesIn(std::vector<FileNameEntryPointPair>{
|
||||||
|
{"hlsl.array.flatten.frag", "main"},
|
||||||
|
}),
|
||||||
|
FileNameAsCustomTestSuffix
|
||||||
|
);
|
||||||
|
|
||||||
|
// clang-format on
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
} // namespace glslangtest
|
} // namespace glslangtest
|
||||||
|
@ -204,11 +204,14 @@ public:
|
|||||||
// the result and returns disassembly text.
|
// the result and returns disassembly text.
|
||||||
GlslangResult compileAndLink(
|
GlslangResult compileAndLink(
|
||||||
const std::string shaderName, const std::string& code,
|
const std::string shaderName, const std::string& code,
|
||||||
const std::string& entryPointName, EShMessages controls)
|
const std::string& entryPointName, EShMessages controls,
|
||||||
|
bool flattenUniformArrays = false)
|
||||||
{
|
{
|
||||||
const EShLanguage kind = GetShaderStage(GetSuffix(shaderName));
|
const EShLanguage kind = GetShaderStage(GetSuffix(shaderName));
|
||||||
|
|
||||||
glslang::TShader shader(kind);
|
glslang::TShader shader(kind);
|
||||||
|
shader.setFlattenUniformArrays(flattenUniformArrays);
|
||||||
|
|
||||||
bool success = compile(&shader, code, entryPointName, controls);
|
bool success = compile(&shader, code, entryPointName, controls);
|
||||||
|
|
||||||
glslang::TProgram program;
|
glslang::TProgram program;
|
||||||
@ -395,6 +398,32 @@ public:
|
|||||||
expectedOutputFname);
|
expectedOutputFname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void loadFileCompileFlattenUniformsAndCheck(const std::string& testDir,
|
||||||
|
const std::string& testName,
|
||||||
|
Source source,
|
||||||
|
Semantics semantics,
|
||||||
|
Target target,
|
||||||
|
const std::string& entryPointName="")
|
||||||
|
{
|
||||||
|
const std::string inputFname = testDir + "/" + testName;
|
||||||
|
const std::string expectedOutputFname =
|
||||||
|
testDir + "/baseResults/" + testName + ".out";
|
||||||
|
std::string input, expectedOutput;
|
||||||
|
|
||||||
|
tryLoadFile(inputFname, "input", &input);
|
||||||
|
tryLoadFile(expectedOutputFname, "expected output", &expectedOutput);
|
||||||
|
|
||||||
|
const EShMessages controls = DeriveOptions(source, semantics, target);
|
||||||
|
GlslangResult result = compileAndLink(testName, input, entryPointName, controls, true);
|
||||||
|
|
||||||
|
// Generate the hybrid output in the way of glslangValidator.
|
||||||
|
std::ostringstream stream;
|
||||||
|
outputResultToStream(&stream, result, controls);
|
||||||
|
|
||||||
|
checkEqAndUpdateIfRequested(expectedOutput, stream.str(),
|
||||||
|
expectedOutputFname);
|
||||||
|
}
|
||||||
|
|
||||||
void loadFileCompileIoMapAndCheck(const std::string& testDir,
|
void loadFileCompileIoMapAndCheck(const std::string& testDir,
|
||||||
const std::string& testName,
|
const std::string& testName,
|
||||||
Source source,
|
Source source,
|
||||||
|
@ -403,12 +403,19 @@ TIntermTyped* HlslParseContext::handleBracketDereference(const TSourceLoc& loc,
|
|||||||
if (base->getAsSymbolNode() && isIoResizeArray(base->getType()))
|
if (base->getAsSymbolNode() && isIoResizeArray(base->getType()))
|
||||||
handleIoResizeArrayAccess(loc, base);
|
handleIoResizeArrayAccess(loc, base);
|
||||||
|
|
||||||
if (index->getQualifier().storage == EvqConst) {
|
if (base->getAsSymbolNode() && shouldFlatten(base->getType())) {
|
||||||
if (base->getType().isImplicitlySizedArray())
|
if (index->getQualifier().storage != EvqConst)
|
||||||
updateImplicitArraySize(loc, base, indexValue);
|
error(loc, "Invalid variable index to flattened uniform array", base->getAsSymbolNode()->getName().c_str(), "");
|
||||||
result = intermediate.addIndex(EOpIndexDirect, base, index, loc);
|
|
||||||
|
result = flattenAccess(base, indexValue);
|
||||||
} else {
|
} else {
|
||||||
result = intermediate.addIndex(EOpIndexIndirect, base, index, loc);
|
if (index->getQualifier().storage == EvqConst) {
|
||||||
|
if (base->getType().isImplicitlySizedArray())
|
||||||
|
updateImplicitArraySize(loc, base, indexValue);
|
||||||
|
result = intermediate.addIndex(EOpIndexDirect, base, index, loc);
|
||||||
|
} else {
|
||||||
|
result = intermediate.addIndex(EOpIndexIndirect, base, index, loc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -701,9 +708,9 @@ TIntermTyped* HlslParseContext::handleDotDereference(const TSourceLoc& loc, TInt
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is this an aggregate that can't be passed down the stack?
|
// Is this an IO variable that can't be passed down the stack?
|
||||||
// E.g., pipeline inputs to the vertex stage and outputs from the fragment stage.
|
// E.g., pipeline inputs to the vertex stage and outputs from the fragment stage.
|
||||||
bool HlslParseContext::shouldFlatten(const TType& type) const
|
bool HlslParseContext::shouldFlattenIO(const TType& type) const
|
||||||
{
|
{
|
||||||
if (! inEntryPoint)
|
if (! inEntryPoint)
|
||||||
return false;
|
return false;
|
||||||
@ -715,6 +722,33 @@ bool HlslParseContext::shouldFlatten(const TType& type) const
|
|||||||
qualifier == EvqVaryingOut);
|
qualifier == EvqVaryingOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Is this a uniform array which should be flattened?
|
||||||
|
bool HlslParseContext::shouldFlattenUniform(const TType& type) const
|
||||||
|
{
|
||||||
|
const TStorageQualifier qualifier = type.getQualifier().storage;
|
||||||
|
|
||||||
|
return type.isArray() &&
|
||||||
|
intermediate.getFlattenUniformArrays() &&
|
||||||
|
qualifier == EvqUniform;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HlslParseContext::flatten(const TSourceLoc& loc, const TVariable& variable)
|
||||||
|
{
|
||||||
|
const TType& type = variable.getType();
|
||||||
|
|
||||||
|
// Presently, flattening of structure arrays is unimplemented.
|
||||||
|
// We handle one, or the other.
|
||||||
|
if (type.isArray() && type.isStruct()) {
|
||||||
|
error(loc, "cannot flatten structure array", variable.getName().c_str(), "");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type.isStruct())
|
||||||
|
flattenStruct(variable);
|
||||||
|
|
||||||
|
if (type.isArray())
|
||||||
|
flattenArray(loc, variable);
|
||||||
|
}
|
||||||
|
|
||||||
// Figure out the mapping between an aggregate's top members and an
|
// Figure out the mapping between an aggregate's top members and an
|
||||||
// equivalent set of individual variables.
|
// equivalent set of individual variables.
|
||||||
//
|
//
|
||||||
@ -724,7 +758,7 @@ bool HlslParseContext::shouldFlatten(const TType& type) const
|
|||||||
// Assumes shouldFlatten() or equivalent was called first.
|
// Assumes shouldFlatten() or equivalent was called first.
|
||||||
//
|
//
|
||||||
// TODO: generalize this to arbitrary nesting?
|
// TODO: generalize this to arbitrary nesting?
|
||||||
void HlslParseContext::flatten(const TVariable& variable)
|
void HlslParseContext::flattenStruct(const TVariable& variable)
|
||||||
{
|
{
|
||||||
TVector<TVariable*> memberVariables;
|
TVector<TVariable*> memberVariables;
|
||||||
|
|
||||||
@ -742,8 +776,54 @@ void HlslParseContext::flatten(const TVariable& variable)
|
|||||||
flattenMap[variable.getUniqueId()] = memberVariables;
|
flattenMap[variable.getUniqueId()] = memberVariables;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Turn an access into aggregate that was flattened to instead be
|
// Figure out mapping between an array's members and an
|
||||||
// an access to the individual variable the element/member was flattened to.
|
// equivalent set of individual variables.
|
||||||
|
//
|
||||||
|
// Assumes shouldFlatten() or equivalent was called first.
|
||||||
|
void HlslParseContext::flattenArray(const TSourceLoc& loc, const TVariable& variable)
|
||||||
|
{
|
||||||
|
const TType& type = variable.getType();
|
||||||
|
assert(type.isArray());
|
||||||
|
|
||||||
|
if (type.isImplicitlySizedArray())
|
||||||
|
error(loc, "cannot flatten implicitly sized array", variable.getName().c_str(), "");
|
||||||
|
|
||||||
|
if (type.getArraySizes()->getNumDims() != 1)
|
||||||
|
error(loc, "cannot flatten multi-dimensional array", variable.getName().c_str(), "");
|
||||||
|
|
||||||
|
const int size = type.getCumulativeArraySize();
|
||||||
|
|
||||||
|
TVector<TVariable*> memberVariables;
|
||||||
|
|
||||||
|
const TType dereferencedType(type, 0);
|
||||||
|
int binding = type.getQualifier().layoutBinding;
|
||||||
|
|
||||||
|
if (dereferencedType.isStruct() || dereferencedType.isArray()) {
|
||||||
|
error(loc, "cannot flatten array of aggregate types", variable.getName().c_str(), "");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int element=0; element < size; ++element) {
|
||||||
|
char elementNumBuf[20]; // sufficient for MAXINT
|
||||||
|
snprintf(elementNumBuf, sizeof(elementNumBuf)-1, "[%d]", element);
|
||||||
|
const TString memberName = variable.getName() + elementNumBuf;
|
||||||
|
|
||||||
|
TVariable* memberVariable = makeInternalVariable(memberName.c_str(), dereferencedType);
|
||||||
|
memberVariable->getWritableType().getQualifier() = variable.getType().getQualifier();
|
||||||
|
|
||||||
|
memberVariable->getWritableType().getQualifier().layoutBinding = binding;
|
||||||
|
|
||||||
|
if (binding != TQualifier::layoutBindingEnd)
|
||||||
|
++binding;
|
||||||
|
|
||||||
|
memberVariables.push_back(memberVariable);
|
||||||
|
intermediate.addSymbolLinkageNode(linkage, *memberVariable);
|
||||||
|
}
|
||||||
|
|
||||||
|
flattenMap[variable.getUniqueId()] = memberVariables;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Turn an access into an aggregate that was flattened to instead be
|
||||||
|
// an access to the individual variable the member was flattened to.
|
||||||
// Assumes shouldFlatten() or equivalent was called first.
|
// Assumes shouldFlatten() or equivalent was called first.
|
||||||
TIntermTyped* HlslParseContext::flattenAccess(TIntermTyped* base, int member)
|
TIntermTyped* HlslParseContext::flattenAccess(TIntermTyped* base, int member)
|
||||||
{
|
{
|
||||||
@ -864,7 +944,7 @@ TIntermAggregate* HlslParseContext::handleFunctionDefinition(const TSourceLoc& l
|
|||||||
remapEntryPointIO(function);
|
remapEntryPointIO(function);
|
||||||
if (entryPointOutput) {
|
if (entryPointOutput) {
|
||||||
if (shouldFlatten(entryPointOutput->getType()))
|
if (shouldFlatten(entryPointOutput->getType()))
|
||||||
flatten(*entryPointOutput);
|
flatten(loc, *entryPointOutput);
|
||||||
assignLocations(*entryPointOutput);
|
assignLocations(*entryPointOutput);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
@ -896,7 +976,7 @@ TIntermAggregate* HlslParseContext::handleFunctionDefinition(const TSourceLoc& l
|
|||||||
// get IO straightened out
|
// get IO straightened out
|
||||||
if (inEntryPoint) {
|
if (inEntryPoint) {
|
||||||
if (shouldFlatten(*param.type))
|
if (shouldFlatten(*param.type))
|
||||||
flatten(*variable);
|
flatten(loc, *variable);
|
||||||
assignLocations(*variable);
|
assignLocations(*variable);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1051,40 +1131,68 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op
|
|||||||
flattenMap.find(node.getAsSymbolNode()->getId()) != flattenMap.end();
|
flattenMap.find(node.getAsSymbolNode()->getId()) != flattenMap.end();
|
||||||
};
|
};
|
||||||
|
|
||||||
bool flattenLeft = mustFlatten(*left);
|
const bool flattenLeft = mustFlatten(*left);
|
||||||
bool flattenRight = mustFlatten(*right);
|
const bool flattenRight = mustFlatten(*right);
|
||||||
if (! flattenLeft && ! flattenRight)
|
if (! flattenLeft && ! flattenRight)
|
||||||
return intermediate.addAssign(op, left, right, loc);
|
return intermediate.addAssign(op, left, right, loc);
|
||||||
|
|
||||||
// If we get here, we are assigning to or from a whole struct that must be
|
TIntermAggregate* assignList = nullptr;
|
||||||
// flattened, so have to do member-by-member assignment:
|
|
||||||
const auto& members = *left->getType().getStruct();
|
|
||||||
const auto getMember = [&](bool flatten, TIntermTyped* node,
|
|
||||||
const TVector<TVariable*>& memberVariables, int member) {
|
|
||||||
TIntermTyped* subTree;
|
|
||||||
if (flatten)
|
|
||||||
subTree = intermediate.addSymbol(*memberVariables[member]);
|
|
||||||
else {
|
|
||||||
subTree = intermediate.addIndex(EOpIndexDirectStruct, node,
|
|
||||||
intermediate.addConstantUnion(member, loc), loc);
|
|
||||||
subTree->setType(*members[member].type);
|
|
||||||
}
|
|
||||||
|
|
||||||
return subTree;
|
|
||||||
};
|
|
||||||
|
|
||||||
const TVector<TVariable*>* leftVariables = nullptr;
|
const TVector<TVariable*>* leftVariables = nullptr;
|
||||||
const TVector<TVariable*>* rightVariables = nullptr;
|
const TVector<TVariable*>* rightVariables = nullptr;
|
||||||
|
|
||||||
if (flattenLeft)
|
if (flattenLeft)
|
||||||
leftVariables = &flattenMap.find(left->getAsSymbolNode()->getId())->second;
|
leftVariables = &flattenMap.find(left->getAsSymbolNode()->getId())->second;
|
||||||
if (flattenRight)
|
if (flattenRight)
|
||||||
rightVariables = &flattenMap.find(right->getAsSymbolNode()->getId())->second;
|
rightVariables = &flattenMap.find(right->getAsSymbolNode()->getId())->second;
|
||||||
TIntermAggregate* assignList = nullptr;
|
|
||||||
for (int member = 0; member < (int)members.size(); ++member) {
|
const auto getMember = [&](bool flatten, TIntermTyped* node,
|
||||||
TIntermTyped* subRight = getMember(flattenRight, right, *rightVariables, member);
|
const TVector<TVariable*>& memberVariables, int member,
|
||||||
TIntermTyped* subLeft = getMember(flattenLeft, left, *leftVariables, member);
|
TOperator op, const TType& memberType) {
|
||||||
assignList = intermediate.growAggregate(assignList, intermediate.addAssign(op, subLeft, subRight, loc));
|
TIntermTyped* subTree;
|
||||||
|
if (flatten)
|
||||||
|
subTree = intermediate.addSymbol(*memberVariables[member]);
|
||||||
|
else {
|
||||||
|
subTree = intermediate.addIndex(op, node, intermediate.addConstantUnion(member, loc), loc);
|
||||||
|
subTree->setType(memberType);
|
||||||
|
}
|
||||||
|
|
||||||
|
return subTree;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Handle struct assignment
|
||||||
|
if (left->getType().isStruct()) {
|
||||||
|
// If we get here, we are assigning to or from a whole struct that must be
|
||||||
|
// flattened, so have to do member-by-member assignment:
|
||||||
|
const auto& members = *left->getType().getStruct();
|
||||||
|
|
||||||
|
for (int member = 0; member < (int)members.size(); ++member) {
|
||||||
|
TIntermTyped* subRight = getMember(flattenRight, right, *rightVariables, member,
|
||||||
|
EOpIndexDirectStruct, *members[member].type);
|
||||||
|
TIntermTyped* subLeft = getMember(flattenLeft, left, *leftVariables, member,
|
||||||
|
EOpIndexDirectStruct, *members[member].type);
|
||||||
|
assignList = intermediate.growAggregate(assignList, intermediate.addAssign(op, subLeft, subRight, loc));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle array assignment
|
||||||
|
if (left->getType().isArray()) {
|
||||||
|
// If we get here, we are assigning to or from a whole array that must be
|
||||||
|
// flattened, so have to do member-by-member assignment:
|
||||||
|
|
||||||
|
const TType dereferencedType(left->getType(), 0);
|
||||||
|
const int size = left->getType().getCumulativeArraySize();
|
||||||
|
|
||||||
|
for (int element=0; element < size; ++element) {
|
||||||
|
TIntermTyped* subRight = getMember(flattenRight, right, *rightVariables, element,
|
||||||
|
EOpIndexDirect, dereferencedType);
|
||||||
|
TIntermTyped* subLeft = getMember(flattenLeft, left, *leftVariables, element,
|
||||||
|
EOpIndexDirect, dereferencedType);
|
||||||
|
|
||||||
|
assignList = intermediate.growAggregate(assignList, intermediate.addAssign(op, subLeft, subRight, loc));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(assignList != nullptr);
|
||||||
assignList->setOperator(EOpSequence);
|
assignList->setOperator(EOpSequence);
|
||||||
|
|
||||||
return assignList;
|
return assignList;
|
||||||
@ -4095,13 +4203,21 @@ TIntermNode* HlslParseContext::declareVariable(const TSourceLoc& loc, TString& i
|
|||||||
|
|
||||||
inheritGlobalDefaults(type.getQualifier());
|
inheritGlobalDefaults(type.getQualifier());
|
||||||
|
|
||||||
|
bool flattenVar = false;
|
||||||
|
|
||||||
// Declare the variable
|
// Declare the variable
|
||||||
if (arraySizes || type.isArray()) {
|
if (arraySizes || type.isArray()) {
|
||||||
// Arrayness is potentially coming both from the type and from the
|
// Arrayness is potentially coming both from the type and from the
|
||||||
// variable: "int[] a[];" or just one or the other.
|
// variable: "int[] a[];" or just one or the other.
|
||||||
// Merge it all to the type, so all arrayness is part of the type.
|
// Merge it all to the type, so all arrayness is part of the type.
|
||||||
arrayDimMerge(type, arraySizes);
|
arrayDimMerge(type, arraySizes); // Safe if there are no arraySizes
|
||||||
|
|
||||||
declareArray(loc, identifier, type, symbol, newDeclaration);
|
declareArray(loc, identifier, type, symbol, newDeclaration);
|
||||||
|
|
||||||
|
flattenVar = shouldFlatten(type);
|
||||||
|
|
||||||
|
if (flattenVar)
|
||||||
|
flatten(loc, *symbol->getAsVariable());
|
||||||
} else {
|
} else {
|
||||||
// non-array case
|
// non-array case
|
||||||
if (! symbol)
|
if (! symbol)
|
||||||
@ -4116,6 +4232,9 @@ TIntermNode* HlslParseContext::declareVariable(const TSourceLoc& loc, TString& i
|
|||||||
// Deal with initializer
|
// Deal with initializer
|
||||||
TIntermNode* initNode = nullptr;
|
TIntermNode* initNode = nullptr;
|
||||||
if (symbol && initializer) {
|
if (symbol && initializer) {
|
||||||
|
if (flattenVar)
|
||||||
|
error(loc, "flattened array with initializer list unsupported", identifier.c_str(), "");
|
||||||
|
|
||||||
TVariable* variable = symbol->getAsVariable();
|
TVariable* variable = symbol->getAsVariable();
|
||||||
if (! variable) {
|
if (! variable) {
|
||||||
error(loc, "initializer requires a variable, not a member", identifier.c_str(), "");
|
error(loc, "initializer requires a variable, not a member", identifier.c_str(), "");
|
||||||
@ -4124,9 +4243,12 @@ TIntermNode* HlslParseContext::declareVariable(const TSourceLoc& loc, TString& i
|
|||||||
initNode = executeInitializer(loc, initializer, variable);
|
initNode = executeInitializer(loc, initializer, variable);
|
||||||
}
|
}
|
||||||
|
|
||||||
// see if it's a linker-level object to track
|
// see if it's a linker-level object to track. if it's flattened above,
|
||||||
if (newDeclaration && symbolTable.atGlobalLevel())
|
// that process added linkage objects for the flattened symbols, we don't
|
||||||
intermediate.addSymbolLinkageNode(linkage, *symbol);
|
// add the aggregate here.
|
||||||
|
if (!flattenVar)
|
||||||
|
if (newDeclaration && symbolTable.atGlobalLevel())
|
||||||
|
intermediate.addSymbolLinkageNode(linkage, *symbol);
|
||||||
|
|
||||||
return initNode;
|
return initNode;
|
||||||
}
|
}
|
||||||
@ -4257,7 +4379,7 @@ TIntermNode* HlslParseContext::executeInitializer(const TSourceLoc& loc, TInterm
|
|||||||
// normal assigning of a value to a variable...
|
// normal assigning of a value to a variable...
|
||||||
specializationCheck(loc, initializer->getType(), "initializer");
|
specializationCheck(loc, initializer->getType(), "initializer");
|
||||||
TIntermSymbol* intermSymbol = intermediate.addSymbol(*variable, loc);
|
TIntermSymbol* intermSymbol = intermediate.addSymbol(*variable, loc);
|
||||||
TIntermNode* initNode = intermediate.addAssign(EOpAssign, intermSymbol, initializer, loc);
|
TIntermNode* initNode = handleAssign(loc, EOpAssign, intermSymbol, initializer);
|
||||||
if (! initNode)
|
if (! initNode)
|
||||||
assignError(loc, "=", intermSymbol->getCompleteString(), initializer->getCompleteString());
|
assignError(loc, "=", intermSymbol->getCompleteString(), initializer->getCompleteString());
|
||||||
|
|
||||||
|
@ -83,9 +83,6 @@ public:
|
|||||||
TIntermTyped* handleBinaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* left, TIntermTyped* right);
|
TIntermTyped* handleBinaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* left, TIntermTyped* right);
|
||||||
TIntermTyped* handleUnaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* childNode);
|
TIntermTyped* handleUnaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* childNode);
|
||||||
TIntermTyped* handleDotDereference(const TSourceLoc&, TIntermTyped* base, const TString& field);
|
TIntermTyped* handleDotDereference(const TSourceLoc&, TIntermTyped* base, const TString& field);
|
||||||
bool shouldFlatten(const TType&) const;
|
|
||||||
void flatten(const TVariable& variable);
|
|
||||||
TIntermTyped* flattenAccess(TIntermTyped* base, int member);
|
|
||||||
void assignLocations(TVariable& variable);
|
void assignLocations(TVariable& variable);
|
||||||
TFunction& handleFunctionDeclarator(const TSourceLoc&, TFunction& function, bool prototype);
|
TFunction& handleFunctionDeclarator(const TSourceLoc&, TFunction& function, bool prototype);
|
||||||
TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&);
|
TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&);
|
||||||
@ -181,6 +178,15 @@ protected:
|
|||||||
const char* szExtraInfoFormat, TPrefixType prefix,
|
const char* szExtraInfoFormat, TPrefixType prefix,
|
||||||
va_list args);
|
va_list args);
|
||||||
|
|
||||||
|
// Array and struct flattening
|
||||||
|
bool shouldFlatten(const TType& type) const { return shouldFlattenIO(type) || shouldFlattenUniform(type); }
|
||||||
|
TIntermTyped* flattenAccess(TIntermTyped* base, int member);
|
||||||
|
bool shouldFlattenIO(const TType&) const;
|
||||||
|
bool shouldFlattenUniform(const TType&) const;
|
||||||
|
void flatten(const TSourceLoc& loc, const TVariable& variable);
|
||||||
|
void flattenStruct(const TVariable& variable);
|
||||||
|
void flattenArray(const TSourceLoc& loc, const TVariable& variable);
|
||||||
|
|
||||||
// Current state of parsing
|
// Current state of parsing
|
||||||
struct TPragma contextPragma;
|
struct TPragma contextPragma;
|
||||||
int loopNestingLevel; // 0 if outside all loops
|
int loopNestingLevel; // 0 if outside all loops
|
||||||
|
Loading…
x
Reference in New Issue
Block a user