mirror of
https://github.com/RPCS3/glslang.git
synced 2025-01-24 12:04:57 +00:00
HLSL: Merge pull request #515 from steve-lunarg/flatten-uniform-array
HLSL: Flatten uniform arrays
This commit is contained in:
commit
4455258a08
StandAlone
Test
glslang
gtests
hlsl
@ -81,6 +81,7 @@ enum TOptions {
|
||||
EOptionReadHlsl = (1 << 17),
|
||||
EOptionCascadingErrors = (1 << 18),
|
||||
EOptionAutoMapBindings = (1 << 19),
|
||||
EOptionFlattenUniformArrays = (1 << 20),
|
||||
};
|
||||
|
||||
//
|
||||
@ -285,6 +286,10 @@ void ProcessArguments(int argc, char* argv[])
|
||||
lowerword == "auto-map-binding" ||
|
||||
lowerword == "amb") {
|
||||
Options |= EOptionAutoMapBindings;
|
||||
} else if (lowerword == "flatten-uniform-arrays" || // synonyms
|
||||
lowerword == "flatten-uniform-array" ||
|
||||
lowerword == "fua") {
|
||||
Options |= EOptionFlattenUniformArrays;
|
||||
} else {
|
||||
usage();
|
||||
}
|
||||
@ -407,6 +412,10 @@ void ProcessArguments(int argc, char* argv[])
|
||||
// -o or -x makes no sense if there is no target binary
|
||||
if (binaryFileName && (Options & EOptionSpv) == 0)
|
||||
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->setShiftTextureBinding(baseTextureBinding[compUnit.stage]);
|
||||
shader->setShiftUboBinding(baseUboBinding[compUnit.stage]);
|
||||
shader->setFlattenUniformArrays((Options & EOptionFlattenUniformArrays) != 0);
|
||||
|
||||
if (Options & EOptionAutoMapBindings)
|
||||
shader->setAutoMapBindings(true);
|
||||
@ -930,6 +940,9 @@ void usage()
|
||||
" --auto-map-bindings automatically bind uniform variables without\n"
|
||||
" explicit 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);
|
||||
|
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
|
||||
if (op == EOpFunction)
|
||||
break;
|
||||
|
||||
// HLSL can assign samplers directly (no constructor)
|
||||
if (source == EShSourceHlsl && node->getBasicType() == EbtSampler)
|
||||
break;
|
||||
|
||||
// samplers can get assigned via a sampler constructor
|
||||
// (well, not yet, but code in the rest of this function is ready for it)
|
||||
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::setShiftUboBinding(unsigned int base) { intermediate->setShiftUboBinding(base); }
|
||||
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.
|
||||
//
|
||||
|
@ -145,7 +145,8 @@ public:
|
||||
shiftSamplerBinding(0),
|
||||
shiftTextureBinding(0),
|
||||
shiftUboBinding(0),
|
||||
autoMapBindings(false)
|
||||
autoMapBindings(false),
|
||||
flattenUniformArrays(false)
|
||||
{
|
||||
localSize[0] = 1;
|
||||
localSize[1] = 1;
|
||||
@ -176,6 +177,8 @@ public:
|
||||
unsigned int getShiftUboBinding() const { return shiftUboBinding; }
|
||||
void setAutoMapBindings(bool map) { autoMapBindings = map; }
|
||||
bool getAutoMapBindings() const { return autoMapBindings; }
|
||||
void setFlattenUniformArrays(bool flatten) { flattenUniformArrays = flatten; }
|
||||
bool getFlattenUniformArrays() const { return flattenUniformArrays; }
|
||||
|
||||
void setVersion(int v) { version = v; }
|
||||
int getVersion() const { return version; }
|
||||
@ -385,6 +388,7 @@ protected:
|
||||
unsigned int shiftTextureBinding;
|
||||
unsigned int shiftUboBinding;
|
||||
bool autoMapBindings;
|
||||
bool flattenUniformArrays;
|
||||
|
||||
EProfile profile;
|
||||
int version;
|
||||
|
@ -304,6 +304,7 @@ public:
|
||||
void setShiftTextureBinding(unsigned int base);
|
||||
void setShiftUboBinding(unsigned int base);
|
||||
void setAutoMapBindings(bool map);
|
||||
void setFlattenUniformArrays(bool flatten);
|
||||
|
||||
// Interface to #include handlers.
|
||||
//
|
||||
|
@ -58,6 +58,7 @@ std::string FileNameAsCustomTestSuffix(
|
||||
}
|
||||
|
||||
using HlslCompileTest = GlslangTest<::testing::TestWithParam<FileNameEntryPointPair>>;
|
||||
using HlslCompileAndFlattenTest = GlslangTest<::testing::TestWithParam<FileNameEntryPointPair>>;
|
||||
|
||||
// Compiling HLSL to SPIR-V under Vulkan semantics. Expected to successfully
|
||||
// generate both AST and SPIR-V.
|
||||
@ -68,6 +69,13 @@ TEST_P(HlslCompileTest, FromFile)
|
||||
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
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
ToSpirv, HlslCompileTest,
|
||||
@ -181,5 +189,15 @@ INSTANTIATE_TEST_CASE_P(
|
||||
);
|
||||
// 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
|
||||
} // namespace glslangtest
|
||||
|
@ -204,11 +204,14 @@ public:
|
||||
// the result and returns disassembly text.
|
||||
GlslangResult compileAndLink(
|
||||
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));
|
||||
|
||||
glslang::TShader shader(kind);
|
||||
shader.setFlattenUniformArrays(flattenUniformArrays);
|
||||
|
||||
bool success = compile(&shader, code, entryPointName, controls);
|
||||
|
||||
glslang::TProgram program;
|
||||
@ -395,6 +398,32 @@ public:
|
||||
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,
|
||||
const std::string& testName,
|
||||
Source source,
|
||||
|
@ -403,12 +403,19 @@ TIntermTyped* HlslParseContext::handleBracketDereference(const TSourceLoc& loc,
|
||||
if (base->getAsSymbolNode() && isIoResizeArray(base->getType()))
|
||||
handleIoResizeArrayAccess(loc, base);
|
||||
|
||||
if (index->getQualifier().storage == EvqConst) {
|
||||
if (base->getType().isImplicitlySizedArray())
|
||||
updateImplicitArraySize(loc, base, indexValue);
|
||||
result = intermediate.addIndex(EOpIndexDirect, base, index, loc);
|
||||
if (base->getAsSymbolNode() && shouldFlatten(base->getType())) {
|
||||
if (index->getQualifier().storage != EvqConst)
|
||||
error(loc, "Invalid variable index to flattened uniform array", base->getAsSymbolNode()->getName().c_str(), "");
|
||||
|
||||
result = flattenAccess(base, indexValue);
|
||||
} 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;
|
||||
}
|
||||
|
||||
// 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.
|
||||
bool HlslParseContext::shouldFlatten(const TType& type) const
|
||||
bool HlslParseContext::shouldFlattenIO(const TType& type) const
|
||||
{
|
||||
if (! inEntryPoint)
|
||||
return false;
|
||||
@ -715,6 +722,33 @@ bool HlslParseContext::shouldFlatten(const TType& type) const
|
||||
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
|
||||
// equivalent set of individual variables.
|
||||
//
|
||||
@ -724,7 +758,7 @@ bool HlslParseContext::shouldFlatten(const TType& type) const
|
||||
// Assumes shouldFlatten() or equivalent was called first.
|
||||
//
|
||||
// TODO: generalize this to arbitrary nesting?
|
||||
void HlslParseContext::flatten(const TVariable& variable)
|
||||
void HlslParseContext::flattenStruct(const TVariable& variable)
|
||||
{
|
||||
TVector<TVariable*> memberVariables;
|
||||
|
||||
@ -742,8 +776,54 @@ void HlslParseContext::flatten(const TVariable& variable)
|
||||
flattenMap[variable.getUniqueId()] = memberVariables;
|
||||
}
|
||||
|
||||
// Turn an access into aggregate that was flattened to instead be
|
||||
// an access to the individual variable the element/member was flattened to.
|
||||
// Figure out mapping between an array's members and an
|
||||
// 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.
|
||||
TIntermTyped* HlslParseContext::flattenAccess(TIntermTyped* base, int member)
|
||||
{
|
||||
@ -864,7 +944,7 @@ TIntermAggregate* HlslParseContext::handleFunctionDefinition(const TSourceLoc& l
|
||||
remapEntryPointIO(function);
|
||||
if (entryPointOutput) {
|
||||
if (shouldFlatten(entryPointOutput->getType()))
|
||||
flatten(*entryPointOutput);
|
||||
flatten(loc, *entryPointOutput);
|
||||
assignLocations(*entryPointOutput);
|
||||
}
|
||||
} else
|
||||
@ -896,7 +976,7 @@ TIntermAggregate* HlslParseContext::handleFunctionDefinition(const TSourceLoc& l
|
||||
// get IO straightened out
|
||||
if (inEntryPoint) {
|
||||
if (shouldFlatten(*param.type))
|
||||
flatten(*variable);
|
||||
flatten(loc, *variable);
|
||||
assignLocations(*variable);
|
||||
}
|
||||
|
||||
@ -1051,40 +1131,68 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op
|
||||
flattenMap.find(node.getAsSymbolNode()->getId()) != flattenMap.end();
|
||||
};
|
||||
|
||||
bool flattenLeft = mustFlatten(*left);
|
||||
bool flattenRight = mustFlatten(*right);
|
||||
const bool flattenLeft = mustFlatten(*left);
|
||||
const bool flattenRight = mustFlatten(*right);
|
||||
if (! flattenLeft && ! flattenRight)
|
||||
return intermediate.addAssign(op, left, right, loc);
|
||||
|
||||
// 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();
|
||||
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;
|
||||
};
|
||||
|
||||
TIntermAggregate* assignList = nullptr;
|
||||
const TVector<TVariable*>* leftVariables = nullptr;
|
||||
const TVector<TVariable*>* rightVariables = nullptr;
|
||||
|
||||
if (flattenLeft)
|
||||
leftVariables = &flattenMap.find(left->getAsSymbolNode()->getId())->second;
|
||||
if (flattenRight)
|
||||
rightVariables = &flattenMap.find(right->getAsSymbolNode()->getId())->second;
|
||||
TIntermAggregate* assignList = nullptr;
|
||||
for (int member = 0; member < (int)members.size(); ++member) {
|
||||
TIntermTyped* subRight = getMember(flattenRight, right, *rightVariables, member);
|
||||
TIntermTyped* subLeft = getMember(flattenLeft, left, *leftVariables, member);
|
||||
assignList = intermediate.growAggregate(assignList, intermediate.addAssign(op, subLeft, subRight, loc));
|
||||
|
||||
const auto getMember = [&](bool flatten, TIntermTyped* node,
|
||||
const TVector<TVariable*>& memberVariables, int member,
|
||||
TOperator op, const TType& memberType) {
|
||||
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);
|
||||
|
||||
return assignList;
|
||||
@ -4095,13 +4203,21 @@ TIntermNode* HlslParseContext::declareVariable(const TSourceLoc& loc, TString& i
|
||||
|
||||
inheritGlobalDefaults(type.getQualifier());
|
||||
|
||||
bool flattenVar = false;
|
||||
|
||||
// Declare the variable
|
||||
if (arraySizes || type.isArray()) {
|
||||
// Arrayness is potentially coming both from the type and from the
|
||||
// variable: "int[] a[];" or just one or the other.
|
||||
// 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);
|
||||
|
||||
flattenVar = shouldFlatten(type);
|
||||
|
||||
if (flattenVar)
|
||||
flatten(loc, *symbol->getAsVariable());
|
||||
} else {
|
||||
// non-array case
|
||||
if (! symbol)
|
||||
@ -4116,6 +4232,9 @@ TIntermNode* HlslParseContext::declareVariable(const TSourceLoc& loc, TString& i
|
||||
// Deal with initializer
|
||||
TIntermNode* initNode = nullptr;
|
||||
if (symbol && initializer) {
|
||||
if (flattenVar)
|
||||
error(loc, "flattened array with initializer list unsupported", identifier.c_str(), "");
|
||||
|
||||
TVariable* variable = symbol->getAsVariable();
|
||||
if (! variable) {
|
||||
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);
|
||||
}
|
||||
|
||||
// see if it's a linker-level object to track
|
||||
if (newDeclaration && symbolTable.atGlobalLevel())
|
||||
intermediate.addSymbolLinkageNode(linkage, *symbol);
|
||||
// see if it's a linker-level object to track. if it's flattened above,
|
||||
// that process added linkage objects for the flattened symbols, we don't
|
||||
// add the aggregate here.
|
||||
if (!flattenVar)
|
||||
if (newDeclaration && symbolTable.atGlobalLevel())
|
||||
intermediate.addSymbolLinkageNode(linkage, *symbol);
|
||||
|
||||
return initNode;
|
||||
}
|
||||
@ -4257,7 +4379,7 @@ TIntermNode* HlslParseContext::executeInitializer(const TSourceLoc& loc, TInterm
|
||||
// normal assigning of a value to a variable...
|
||||
specializationCheck(loc, initializer->getType(), "initializer");
|
||||
TIntermSymbol* intermSymbol = intermediate.addSymbol(*variable, loc);
|
||||
TIntermNode* initNode = intermediate.addAssign(EOpAssign, intermSymbol, initializer, loc);
|
||||
TIntermNode* initNode = handleAssign(loc, EOpAssign, intermSymbol, initializer);
|
||||
if (! initNode)
|
||||
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* handleUnaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* childNode);
|
||||
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);
|
||||
TFunction& handleFunctionDeclarator(const TSourceLoc&, TFunction& function, bool prototype);
|
||||
TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&);
|
||||
@ -181,6 +178,15 @@ protected:
|
||||
const char* szExtraInfoFormat, TPrefixType prefix,
|
||||
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
|
||||
struct TPragma contextPragma;
|
||||
int loopNestingLevel; // 0 if outside all loops
|
||||
|
Loading…
x
Reference in New Issue
Block a user