Add Shared/Std140 SSBO process & top-level array elements related (#2231)
authorChow <laddoc@outlook.com>
Thu, 4 Jun 2020 07:47:18 +0000 (15:47 +0800)
committerGitHub <noreply@github.com>
Thu, 4 Jun 2020 07:47:18 +0000 (01:47 -0600)
* Add Shared/Std140 SSBO process & top-level array elements related
process

1.Add process options for shared/std140 ssbo, following ubo process
2.Add IO Variables reflection option, would keep all input/output
variables in reflection
3.Add Top-level related process, fix top-level array size issues,
following spec
4.Split ssbo/ubo reflection options, merge blowup expanding all into
function blowupActiveAggregate to allow other functions keep same entry
format.

Add options in StandAlone and test symbols.

1. Add options in StandAlone for std140/shared ubo/ssbo and all io variables reflection.
2. Add test for ssbo. When EShReflectionSharedStd140SSBO turns on, generated symbol and output would be different, to remind the difference. Defaultly disabled and nothing would change, nor blocking normal test.

* Add options in runtest script, refresh test results.

Add options in StandAlone:
--reflect-all-io-variables --reflect-shared-std140-ubo --reflect-shared-std140-ssbo

refresh test results.
Now the index, size of unsized array are expected.

17 files changed:
StandAlone/StandAlone.cpp
Test/420.frag
Test/baseResults/420.frag.out
Test/baseResults/hlsl.automap.frag.out
Test/baseResults/hlsl.reflection.binding.frag.out
Test/baseResults/hlsl.reflection.vert.out
Test/baseResults/hlsl.shift.per-set.frag.out
Test/baseResults/reflection.linked.options.out
Test/baseResults/reflection.linked.out
Test/baseResults/reflection.options.vert.out
Test/baseResults/reflection.vert.out
Test/runtests
glslang/Include/glslang_c_shader_types.h
glslang/MachineIndependent/iomapper.cpp
glslang/MachineIndependent/linkValidate.cpp
glslang/MachineIndependent/reflection.cpp
glslang/Public/ShaderLang.h

index 871788e..ab8d904 100644 (file)
@@ -555,6 +555,12 @@ void ProcessArguments(std::vector<std::unique_ptr<glslang::TWorkItem>>& workItem
                         ReflectOptions |= EShReflectionAllBlockVariables;
                     } else if (lowerword == "reflect-unwrap-io-blocks") {
                         ReflectOptions |= EShReflectionUnwrapIOBlocks;
+                    } else if (lowerword == "reflect-all-io-variables") {
+                        ReflectOptions |= EShReflectionAllIOVariables;
+                    } else if (lowerword == "reflect-shared-std140-ubo") {
+                        ReflectOptions |= EShReflectionSharedStd140UBO;
+                    } else if (lowerword == "reflect-shared-std140-ssbo") {
+                        ReflectOptions |= EShReflectionSharedStd140SSBO;
                     } else if (lowerword == "resource-set-bindings" ||  // synonyms
                                lowerword == "resource-set-binding"  ||
                                lowerword == "rsb") {
index d3020b3..4c0b15f 100644 (file)
@@ -34,6 +34,21 @@ void atomicOpPass()
     origu = atomicCompSwap(atomu, 10u, 8u);
 }
 
+layout(binding = 2,std430) buffer ssboElem01
+{
+    int member01;
+    int memberArr01[2];
+    int memberUnsizedArr01[];
+} ssboStd430Arr[2];
+
+// if turns on EShReflectionSharedStd140SSBO, SPIR-V would be different
+layout(binding = 3,shared) buffer ssboElem02
+{
+    int member02;
+    int memberArr02[2];
+    int memberUnsizedArr02[];
+} ssboSharedArr[2];
+
 #extension GL_ARB_shader_storage_buffer_object : disable
 
 layout(binding = 1,std430) buffer BufferFail // Error std430 and "buffer" block support disabled 
index 1a7586a..19b5c9b 100644 (file)
@@ -4,8 +4,8 @@ ERROR: 0:11: 'layout qualifier' : can only apply depth layout to gl_FragDepth
 ERROR: 0:12: 'gl_FragDepth' : cannot redeclare after use 
 ERROR: 0:14: 'atomic_uint' : array must be explicitly sized 
 ERROR: 0:17: 'imageSize' : required extension not requested: GL_ARB_shader_image_size
-ERROR: 0:39: 'std430' : not supported for this version or the enabled extensions 
-ERROR: 0:39: '' :  syntax error, unexpected IDENTIFIER, expecting LEFT_BRACE or COMMA or SEMICOLON
+ERROR: 0:54: 'std430' : not supported for this version or the enabled extensions 
+ERROR: 0:54: '' :  syntax error, unexpected IDENTIFIER, expecting LEFT_BRACE or COMMA or SEMICOLON
 ERROR: 7 compilation errors.  No code generated.
 
 
@@ -82,6 +82,8 @@ ERROR: node is still EOpNull!
 0:?     'iv2dim' ( global 2-component vector of int)
 0:?     'iv2dim1' ( global 2-component vector of int)
 0:?     'anon@0' (layout( binding=0 column_major std430) buffer block{layout( column_major std430 offset=0) buffer int atomi, layout( column_major std430 offset=4) buffer uint atomu})
+0:?     'ssboStd430Arr' (layout( binding=2 column_major std430) buffer 2-element array of block{layout( column_major std430 offset=0) buffer int member01, layout( column_major std430 offset=4) buffer 2-element array of int memberArr01, layout( column_major std430 offset=12) buffer unsized 1-element array of int memberUnsizedArr01})
+0:?     'ssboSharedArr' (layout( binding=3 column_major shared) buffer 2-element array of block{layout( column_major shared) buffer int member02, layout( column_major shared) buffer 2-element array of int memberArr02, layout( column_major shared) buffer unsized 1-element array of int memberUnsizedArr02})
 
 
 Linked fragment stage:
@@ -117,4 +119,6 @@ ERROR: node is still EOpNull!
 0:?     'iv2dim' ( global 2-component vector of int)
 0:?     'iv2dim1' ( global 2-component vector of int)
 0:?     'anon@0' (layout( binding=0 column_major std430) buffer block{layout( column_major std430 offset=0) buffer int atomi, layout( column_major std430 offset=4) buffer uint atomu})
+0:?     'ssboStd430Arr' (layout( binding=2 column_major std430) buffer 2-element array of block{layout( column_major std430 offset=0) buffer int member01, layout( column_major std430 offset=4) buffer 2-element array of int memberArr01, layout( column_major std430 offset=12) buffer unsized 1-element array of int memberUnsizedArr01})
+0:?     'ssboSharedArr' (layout( binding=3 column_major shared) buffer 2-element array of block{layout( column_major shared) buffer int member02, layout( column_major shared) buffer 2-element array of int memberArr02, layout( column_major shared) buffer unsized 1-element array of int memberUnsizedArr02})
 
index 7691b89..240e67a 100644 (file)
@@ -18,12 +18,12 @@ cb1: offset 0, type 1404, size 1, index 4, binding -1, stages 16
 tb1: offset 0, type 1404, size 1, index 5, binding -1, stages 16
 
 Uniform block reflection:
-t4: offset -1, type ffffffff, size 0, index -1, binding 14, stages 16, numMembers 1
-t5: offset -1, type ffffffff, size 0, index -1, binding 15, stages 16, numMembers 1
-u5: offset -1, type ffffffff, size 0, index -1, binding 45, stages 16, numMembers 1
-u6: offset -1, type ffffffff, size 0, index -1, binding 46, stages 16, numMembers 1
-cb: offset -1, type ffffffff, size 4, index -1, binding 51, stages 16, numMembers 1
-tb: offset -1, type ffffffff, size 4, index -1, binding 17, stages 16, numMembers 1
+t4: offset -1, type ffffffff, size 16, index 0, binding 14, stages 16, numMembers 1
+t5: offset -1, type ffffffff, size 4, index 1, binding 15, stages 16, numMembers 1
+u5: offset -1, type ffffffff, size 4, index 2, binding 45, stages 16, numMembers 1
+u6: offset -1, type ffffffff, size 4, index 3, binding 46, stages 16, numMembers 1
+cb: offset -1, type ffffffff, size 4, index 4, binding 51, stages 16, numMembers 1
+tb: offset -1, type ffffffff, size 4, index 5, binding 17, stages 16, numMembers 1
 
 Buffer variable reflection:
 
index a13e575..e559dd3 100644 (file)
@@ -12,8 +12,8 @@ c2_b: offset 16, type 1404, size 1, index 1, binding -1, stages 16
 c2_c: offset 20, type 1406, size 1, index 1, binding -1, stages 16
 
 Uniform block reflection:
-cbuff1: offset -1, type ffffffff, size 24, index -1, binding 2, stages 16, numMembers 3
-cbuff2: offset -1, type ffffffff, size 24, index -1, binding 3, stages 16, numMembers 3
+cbuff1: offset -1, type ffffffff, size 24, index 0, binding 2, stages 16, numMembers 3
+cbuff2: offset -1, type ffffffff, size 24, index 1, binding 3, stages 16, numMembers 3
 
 Buffer variable reflection:
 
index 1b3cb51..796784b 100644 (file)
@@ -63,12 +63,12 @@ foo1: offset 0, type 1406, size 1, index 4, binding -1, stages 1
 foo2: offset 0, type 1406, size 1, index 5, binding -1, stages 1
 
 Uniform block reflection:
-nameless: offset -1, type ffffffff, size 496, index -1, binding -1, stages 1, numMembers 9
-$Global: offset -1, type ffffffff, size 3088, index -1, binding -1, stages 1, numMembers 106
-c_nameless: offset -1, type ffffffff, size 96, index -1, binding -1, stages 1, numMembers 5
-nested: offset -1, type ffffffff, size 32, index -1, binding -1, stages 1, numMembers 4
-abl: offset -1, type ffffffff, size 4, index -1, binding -1, stages 1, numMembers 1
-abl2: offset -1, type ffffffff, size 4, index -1, binding -1, stages 1, numMembers 1
+nameless: offset -1, type ffffffff, size 496, index 0, binding -1, stages 1, numMembers 9
+$Global: offset -1, type ffffffff, size 3088, index 1, binding -1, stages 1, numMembers 106
+c_nameless: offset -1, type ffffffff, size 96, index 2, binding -1, stages 1, numMembers 5
+nested: offset -1, type ffffffff, size 32, index 3, binding -1, stages 1, numMembers 4
+abl: offset -1, type ffffffff, size 4, index 4, binding -1, stages 1, numMembers 1
+abl2: offset -1, type ffffffff, size 4, index 5, binding -1, stages 1, numMembers 1
 
 Buffer variable reflection:
 
index 60e2ecc..ad0b7e0 100644 (file)
@@ -219,12 +219,12 @@ tb1: offset 0, type 1404, size 1, index 5, binding -1, stages 16
 ts6: offset -1, type 8b5f, size 1, index -1, binding 71, stages 16
 
 Uniform block reflection:
-t4: offset -1, type ffffffff, size 0, index -1, binding 21, stages 16, numMembers 1
-t5: offset -1, type ffffffff, size 0, index -1, binding 22, stages 16, numMembers 1
-u5: offset -1, type ffffffff, size 0, index -1, binding 44, stages 16, numMembers 1
-u6: offset -1, type ffffffff, size 0, index -1, binding 34, stages 16, numMembers 1
-cb: offset -1, type ffffffff, size 4, index -1, binding 51, stages 16, numMembers 1
-tb: offset -1, type ffffffff, size 4, index -1, binding 27, stages 16, numMembers 1
+t4: offset -1, type ffffffff, size 16, index 0, binding 21, stages 16, numMembers 1
+t5: offset -1, type ffffffff, size 4, index 1, binding 22, stages 16, numMembers 1
+u5: offset -1, type ffffffff, size 4, index 2, binding 44, stages 16, numMembers 1
+u6: offset -1, type ffffffff, size 4, index 3, binding 34, stages 16, numMembers 1
+cb: offset -1, type ffffffff, size 4, index 4, binding 51, stages 16, numMembers 1
+tb: offset -1, type ffffffff, size 4, index 5, binding 27, stages 16, numMembers 1
 
 Buffer variable reflection:
 
index af07bbd..a0e45ed 100644 (file)
@@ -7,7 +7,7 @@ ubo_block.vsonly_uniform: offset 8, type 1406, size 1, index 0, binding -1, stag
 ubo_block.fsonly_uniform: offset 12, type 1406, size 1, index 0, binding -1, stages 16
 
 Uniform block reflection:
-ubo_block: offset -1, type ffffffff, size 16, index -1, binding 0, stages 17, numMembers 4
+ubo_block: offset -1, type ffffffff, size 16, index 0, binding 0, stages 17, numMembers 4
 
 Buffer variable reflection:
 
@@ -15,6 +15,8 @@ Buffer block reflection:
 
 Pipeline input reflection:
 vertin: offset 0, type 1406, size 1, index 0, binding -1, stages 1
+gl_VertexID: offset 0, type 1404, size 1, index 0, binding -1, stages 1
+gl_InstanceID: offset 0, type 1404, size 1, index 0, binding -1, stages 1
 
 Pipeline output reflection:
 fragout: offset 0, type 1406, size 1, index 0, binding -1, stages 16
index b1b2b3c..3874218 100644 (file)
@@ -6,7 +6,7 @@ ubo_block.vsonly_uniform: offset 8, type 1406, size 1, index 0, binding -1, stag
 ubo_block.fsonly_uniform: offset 12, type 1406, size 1, index 0, binding -1, stages 16
 
 Uniform block reflection:
-ubo_block: offset -1, type ffffffff, size 16, index -1, binding 0, stages 17, numMembers 4
+ubo_block: offset -1, type ffffffff, size 16, index 0, binding 0, stages 17, numMembers 4
 
 Buffer variable reflection:
 
index 3f4a271..d68bf37 100644 (file)
@@ -32,7 +32,7 @@ uniform_multi[3][1][0]: offset -1, type 1406, size 2, index -1, binding -1, stag
 uniform_multi[3][2][0]: offset -1, type 1406, size 2, index -1, binding -1, stages 1, arrayStride 4, topLevelArrayStride 24
 
 Uniform block reflection:
-UBO: offset -1, type ffffffff, size 192, index -1, binding -1, stages 1, numMembers 7
+UBO: offset -1, type ffffffff, size 192, index 0, binding -1, stages 1, numMembers 7
 
 Buffer variable reflection:
 t[0].v[0].position[0]: offset 0, type 1406, size 3, index 0, binding -1, stages 1, arrayStride 4, topLevelArrayStride 72
@@ -51,18 +51,19 @@ MultipleArrays.tri[0].v[2].normal[0]: offset 60, type 1406, size 3, index 1, bin
 MultipleArrays.vert[0].position[0]: offset 360, type 1406, size 3, index 1, binding -1, stages 1, arrayStride 4, topLevelArrayStride 24
 MultipleArrays.vert[0].normal[0]: offset 372, type 1406, size 3, index 1, binding -1, stages 0, arrayStride 4, topLevelArrayStride 24
 MultipleArrays.f[0]: offset 480, type 1406, size 5, index 1, binding -1, stages 1, arrayStride 4, topLevelArrayStride 4
-ArrayedBind[0].a: offset 0, type 1406, size 1, index 4, binding -1, stages 0
-ArrayedBind[0].b: offset 4, type 1406, size 1, index 4, binding -1, stages 1
+ArrayedBind.a: offset 0, type 1406, size 1, index 2, binding -1, stages 0
+ArrayedBind.b: offset 4, type 1406, size 1, index 2, binding -1, stages 1
 
 Buffer block reflection:
-VertexCollection: offset -1, type ffffffff, size 400, index -1, binding -1, stages 1, numMembers 7
-MultipleArrays: offset -1, type ffffffff, size 500, index -1, binding -1, stages 1, numMembers 9
-ArrayedBind[0]: offset -1, type ffffffff, size 8, index -1, binding -1, stages 1, numMembers 2
-ArrayedBind[1]: offset -1, type ffffffff, size 8, index -1, binding -1, stages 1, numMembers 2
-ArrayedBind[2]: offset -1, type ffffffff, size 8, index -1, binding -1, stages 1, numMembers 2
+VertexCollection: offset -1, type ffffffff, size 400, index 0, binding -1, stages 1, numMembers 7
+MultipleArrays: offset -1, type ffffffff, size 500, index 1, binding -1, stages 1, numMembers 9
+ArrayedBind[0]: offset -1, type ffffffff, size 8, index 2, binding -1, stages 1, numMembers 2
+ArrayedBind[1]: offset -1, type ffffffff, size 8, index 3, binding -1, stages 1, numMembers 2
+ArrayedBind[2]: offset -1, type ffffffff, size 8, index 4, binding -1, stages 1, numMembers 2
 
 Pipeline input reflection:
 gl_InstanceID: offset 0, type 1404, size 1, index 0, binding -1, stages 1
+gl_VertexID: offset 0, type 1404, size 1, index 0, binding -1, stages 1
 
 Pipeline output reflection:
 outval.val: offset 0, type 1406, size 1, index 0, binding -1, stages 1
index 612a0b9..84f690f 100644 (file)
@@ -90,8 +90,8 @@ deepA[1].d2.d1[2].b: offset -1, type 8b56, size 1, index -1, binding -1, stages
 deepA[1].d2.d1[3].va: offset -1, type 8b50, size 3, index -1, binding -1, stages 1, arrayStride 8, topLevelArrayStride 176
 deepA[1].d2.d1[3].b: offset -1, type 8b56, size 1, index -1, binding -1, stages 1, topLevelArrayStride 176
 ufDead3: offset -1, type 1406, size 1, index -1, binding -1, stages 1
-abl.foo: offset 0, type 1406, size 1, index 7, binding -1, stages 1
-abl2.foo: offset 0, type 1406, size 1, index 11, binding -1, stages 1
+abl.foo: offset 0, type 1406, size 1, index 4, binding -1, stages 1
+abl2.foo: offset 0, type 1406, size 1, index 8, binding -1, stages 1
 buf1.runtimeArray: offset 4, type 1406, size 4, index 12, binding -1, stages 1, arrayStride 4, topLevelArrayStride 4
 buf2.runtimeArray.c: offset 8, type 1406, size 1, index 13, binding -1, stages 1, topLevelArrayStride 12
 buf3.runtimeArray: offset 4, type 1406, size 0, index 14, binding -1, stages 1, arrayStride 4, topLevelArrayStride 4
@@ -145,24 +145,24 @@ t[4].v[2].position: offset 336, type 1406, size 3, index 17, binding -1, stages
 t[4].v[2].normal: offset 348, type 1406, size 3, index 17, binding -1, stages 1, arrayStride 4, topLevelArrayStride 72
 
 Uniform block reflection:
-named: offset -1, type ffffffff, size 304, index -1, binding -1, stages 1, numMembers 10
-nameless: offset -1, type ffffffff, size 496, index -1, binding -1, stages 1, numMembers 9
-c_nameless: offset -1, type ffffffff, size 112, index -1, binding -1, stages 1, numMembers 5
-nested: offset -1, type ffffffff, size 32, index -1, binding -1, stages 1, numMembers 4
-abl[0]: offset -1, type ffffffff, size 4, index -1, binding -1, stages 1, numMembers 1
-abl[1]: offset -1, type ffffffff, size 4, index -1, binding -1, stages 1, numMembers 1
-abl[2]: offset -1, type ffffffff, size 4, index -1, binding -1, stages 1, numMembers 1
-abl[3]: offset -1, type ffffffff, size 4, index -1, binding -1, stages 1, numMembers 1
-abl2[0]: offset -1, type ffffffff, size 4, index -1, binding -1, stages 1, numMembers 1
-abl2[1]: offset -1, type ffffffff, size 4, index -1, binding -1, stages 1, numMembers 1
-abl2[2]: offset -1, type ffffffff, size 4, index -1, binding -1, stages 1, numMembers 1
-abl2[3]: offset -1, type ffffffff, size 4, index -1, binding -1, stages 1, numMembers 1
-buf1: offset -1, type ffffffff, size 4, index -1, binding -1, stages 1, numMembers 2
-buf2: offset -1, type ffffffff, size 4, index -1, binding -1, stages 1, numMembers 4
-buf3: offset -1, type ffffffff, size 4, index -1, binding -1, stages 1, numMembers 2
-buf4: offset -1, type ffffffff, size 4, index -1, binding -1, stages 1, numMembers 4
-nested2: offset -1, type ffffffff, size 208, index -1, binding -1, stages 1, numMembers 15
-VertexCollection: offset -1, type ffffffff, size 400, index -1, binding -1, stages 1, numMembers 31
+named: offset -1, type ffffffff, size 304, index 0, binding -1, stages 1, numMembers 10
+nameless: offset -1, type ffffffff, size 496, index 1, binding -1, stages 1, numMembers 9
+c_nameless: offset -1, type ffffffff, size 112, index 2, binding -1, stages 1, numMembers 5
+nested: offset -1, type ffffffff, size 32, index 3, binding -1, stages 1, numMembers 4
+abl[0]: offset -1, type ffffffff, size 4, index 4, binding -1, stages 1, numMembers 1
+abl[1]: offset -1, type ffffffff, size 4, index 5, binding -1, stages 1, numMembers 1
+abl[2]: offset -1, type ffffffff, size 4, index 6, binding -1, stages 1, numMembers 1
+abl[3]: offset -1, type ffffffff, size 4, index 7, binding -1, stages 1, numMembers 1
+abl2[0]: offset -1, type ffffffff, size 4, index 8, binding -1, stages 1, numMembers 1
+abl2[1]: offset -1, type ffffffff, size 4, index 9, binding -1, stages 1, numMembers 1
+abl2[2]: offset -1, type ffffffff, size 4, index 10, binding -1, stages 1, numMembers 1
+abl2[3]: offset -1, type ffffffff, size 4, index 11, binding -1, stages 1, numMembers 1
+buf1: offset -1, type ffffffff, size 8, index 12, binding -1, stages 1, numMembers 2
+buf2: offset -1, type ffffffff, size 16, index 13, binding -1, stages 1, numMembers 4
+buf3: offset -1, type ffffffff, size 8, index 14, binding -1, stages 1, numMembers 2
+buf4: offset -1, type ffffffff, size 16, index 15, binding -1, stages 1, numMembers 4
+nested2: offset -1, type ffffffff, size 208, index 16, binding -1, stages 1, numMembers 15
+VertexCollection: offset -1, type ffffffff, size 400, index 17, binding -1, stages 1, numMembers 31
 
 Buffer variable reflection:
 
index 1a7c7c9..5dd76ce 100755 (executable)
@@ -37,17 +37,17 @@ diff -b $BASEDIR/badMacroArgs.frag.out $TARGETDIR/badMacroArgs.frag.out || HASER
 echo Running reflection...
 $EXE -l -q -C reflection.vert > $TARGETDIR/reflection.vert.out
 diff -b $BASEDIR/reflection.vert.out $TARGETDIR/reflection.vert.out || HASERROR=1
-$EXE -l -q -C --reflect-strict-array-suffix --reflect-basic-array-suffix --reflect-intermediate-io --reflect-separate-buffers --reflect-all-block-variables --reflect-unwrap-io-blocks reflection.options.vert > $TARGETDIR/reflection.options.vert.out
+$EXE -l -q -C --reflect-strict-array-suffix --reflect-basic-array-suffix --reflect-intermediate-io --reflect-separate-buffers --reflect-all-block-variables --reflect-unwrap-io-blocks --reflect-all-io-variables --reflect-shared-std140-ubo --reflect-shared-std140-ssbo reflection.options.vert > $TARGETDIR/reflection.options.vert.out
 diff -b $BASEDIR/reflection.options.vert.out $TARGETDIR/reflection.options.vert.out || HASERROR=1
 $EXE -l -q -C reflection.frag > $TARGETDIR/reflection.frag.out
 diff -b $BASEDIR/reflection.frag.out $TARGETDIR/reflection.frag.out || HASERROR=1
-$EXE -l -q -C --reflect-strict-array-suffix --reflect-basic-array-suffix --reflect-intermediate-io --reflect-separate-buffers --reflect-all-block-variables --reflect-unwrap-io-blocks reflection.frag > $TARGETDIR/reflection.options.frag.out
+$EXE -l -q -C --reflect-strict-array-suffix --reflect-basic-array-suffix --reflect-intermediate-io --reflect-separate-buffers --reflect-all-block-variables --reflect-unwrap-io-blocks --reflect-all-io-variables --reflect-shared-std140-ubo --reflect-shared-std140-ssbo reflection.frag > $TARGETDIR/reflection.options.frag.out
 diff -b $BASEDIR/reflection.options.frag.out $TARGETDIR/reflection.options.frag.out || HASERROR=1
-$EXE -l -q -C --reflect-strict-array-suffix --reflect-basic-array-suffix --reflect-intermediate-io --reflect-separate-buffers --reflect-all-block-variables --reflect-unwrap-io-blocks reflection.options.geom > $TARGETDIR/reflection.options.geom.out
+$EXE -l -q -C --reflect-strict-array-suffix --reflect-basic-array-suffix --reflect-intermediate-io --reflect-separate-buffers --reflect-all-block-variables --reflect-unwrap-io-blocks --reflect-all-io-variables --reflect-shared-std140-ubo --reflect-shared-std140-ssbo reflection.options.geom > $TARGETDIR/reflection.options.geom.out
 diff -b $BASEDIR/reflection.options.geom.out $TARGETDIR/reflection.options.geom.out || HASERROR=1
 $EXE -l -q -C reflection.linked.vert reflection.linked.frag > $TARGETDIR/reflection.linked.out
 diff -b $BASEDIR/reflection.linked.out $TARGETDIR/reflection.linked.out || HASERROR=1
-$EXE -l -q -C --reflect-strict-array-suffix --reflect-basic-array-suffix --reflect-intermediate-io --reflect-separate-buffers --reflect-all-block-variables --reflect-unwrap-io-blocks reflection.linked.vert reflection.linked.frag > $TARGETDIR/reflection.linked.options.out
+$EXE -l -q -C --reflect-strict-array-suffix --reflect-basic-array-suffix --reflect-intermediate-io --reflect-separate-buffers --reflect-all-block-variables --reflect-unwrap-io-blocks --reflect-all-io-variables --reflect-shared-std140-ubo --reflect-shared-std140-ssbo reflection.linked.vert reflection.linked.frag > $TARGETDIR/reflection.linked.options.out
 diff -b $BASEDIR/reflection.linked.options.out $TARGETDIR/reflection.linked.options.out || HASERROR=1
 $EXE -D -Od -e flizv -l -q -C -V -Od hlsl.reflection.vert > $TARGETDIR/hlsl.reflection.vert.out
 diff -b $BASEDIR/hlsl.reflection.vert.out $TARGETDIR/hlsl.reflection.vert.out || HASERROR=1
index 15bf1e1..d01a115 100644 (file)
@@ -164,7 +164,9 @@ typedef enum {
     GLSLANG_REFLECTION_SEPARATE_BUFFERS_BIT = (1 << 3),
     GLSLANG_REFLECTION_ALL_BLOCK_VARIABLES_BIT = (1 << 4),
     GLSLANG_REFLECTION_UNWRAP_IO_BLOCKS_BIT = (1 << 5),
-    GLSLANG_REFLECTION_SHARED_STD140_BLOCKS_BIT = (1 << 6),
+    GLSLANG_REFLECTION_ALL_IO_VARIABLES_BIT = (1 << 6),
+    GLSLANG_REFLECTION_SHARED_STD140_SSBO_BIT = (1 << 7),
+    GLSLANG_REFLECTION_SHARED_STD140_UBO_BIT = (1 << 8),
     LAST_ELEMENT_MARKER(GLSLANG_REFLECTION_COUNT),
 } glslang_reflection_options_t;
 
index 4e409e0..fadcb1b 100644 (file)
@@ -309,26 +309,43 @@ struct TSymbolValidater
         TIntermSymbol* base = ent1.symbol;
         const TType& type = ent1.symbol->getType();
         const TString& name = entKey.first;
-        TString mangleName1, mangleName2;
-        type.appendMangledName(mangleName1);
         EShLanguage stage = ent1.stage;
+        TString mangleName1, mangleName2;
         if (currentStage != stage) {
             preStage = currentStage;
             currentStage = stage;
             nextStage = EShLangCount;
             for (int i = currentStage + 1; i < EShLangCount; i++) {
-                if (inVarMaps[i] != nullptr)
+                if (inVarMaps[i] != nullptr) {
                     nextStage = static_cast<EShLanguage>(i);
+                    break;
+                }
             }
         }
+
+        if (type.getQualifier().isArrayedIo(stage)) {
+            TType subType(type, 0);
+            subType.appendMangledName(mangleName1);
+        } else {
+            type.appendMangledName(mangleName1);
+        }
+
         if (base->getQualifier().storage == EvqVaryingIn) {
             // validate stage in;
             if (preStage == EShLangCount)
                 return;
+            if (name == "gl_PerVertex")
+                return;
             if (outVarMaps[preStage] != nullptr) {
                 auto ent2 = outVarMaps[preStage]->find(name);
                 if (ent2 != outVarMaps[preStage]->end()) {
-                    ent2->second.symbol->getType().appendMangledName(mangleName2);
+                    if (ent2->second.symbol->getType().getQualifier().isArrayedIo(preStage)) {
+                        TType subType(ent2->second.symbol->getType(), 0);
+                        subType.appendMangledName(mangleName2);
+                    }
+                    else {
+                        ent2->second.symbol->getType().appendMangledName(mangleName2);
+                    }
                     if (mangleName1 == mangleName2)
                         return;
                     else {
@@ -343,10 +360,18 @@ struct TSymbolValidater
             // validate stage out;
             if (nextStage == EShLangCount)
                 return;
+            if (name == "gl_PerVertex")
+                return;
             if (outVarMaps[nextStage] != nullptr) {
                 auto ent2 = inVarMaps[nextStage]->find(name);
                 if (ent2 != inVarMaps[nextStage]->end()) {
-                    ent2->second.symbol->getType().appendMangledName(mangleName2);
+                    if (ent2->second.symbol->getType().getQualifier().isArrayedIo(nextStage)) {
+                        TType subType(ent2->second.symbol->getType(), 0);
+                        subType.appendMangledName(mangleName2);
+                    }
+                    else {
+                        ent2->second.symbol->getType().appendMangledName(mangleName2);
+                    }
                     if (mangleName1 == mangleName2)
                         return;
                     else {
index 045d45e..96ea468 100755 (executable)
@@ -1550,7 +1550,9 @@ int TIntermediate::getBaseAlignment(const TType& type, int& size, int& stride, T
         RoundToPow2(size, alignment);
         stride = size;  // uses full matrix size for stride of an array of matrices (not quite what rule 6/8, but what's expected)
                         // uses the assumption for rule 10 in the comment above
-        size = stride * type.getOuterArraySize();
+        // use one element to represent the last member of SSBO which is unsized array
+        int arraySize = (type.isUnsizedArray() && (type.getOuterArraySize() == 0)) ? 1 : type.getOuterArraySize();
+        size = stride * arraySize;
         return alignment;
     }
 
index 55caa1f..d394cf0 100644 (file)
@@ -107,22 +107,13 @@ public:
                 else
                     baseName = "";
 
-                if (base.getType().isArray()) {
-                    TType derefType(base.getType(), 0);
-
-                    assert(!anonymous);
-                    for (int e = 0; e < base.getType().getCumulativeArraySize(); ++e)
-                        blockIndex = addBlockName(blockName + "[" + String(e) + "]", derefType,
-                            intermediate.getBlockSize(base.getType()));
-                }
-                else
-                    blockIndex = addBlockName(blockName, base.getType(), intermediate.getBlockSize(base.getType()));
+                blockIndex = addBlockName(blockName, base.getType(), intermediate.getBlockSize(base.getType()));
             }
 
             // Use a degenerate (empty) set of dereferences to immediately put as at the end of
             // the dereference change expected by blowUpActiveAggregate.
-            blowUpActiveAggregate(base.getType(), baseName, derefs, derefs.end(), offset, blockIndex, 0, 0,
-                                  base.getQualifier().storage, updateStageMasks);
+            blowUpActiveAggregate(base.getType(), baseName, derefs, derefs.end(), offset, blockIndex, 0, -1, 0,
+                                    base.getQualifier().storage, updateStageMasks);
         }
     }
 
@@ -259,7 +250,7 @@ public:
     // A value of 0 for arraySize will mean to use the full array's size.
     void blowUpActiveAggregate(const TType& baseType, const TString& baseName, const TList<TIntermBinary*>& derefs,
                                TList<TIntermBinary*>::const_iterator deref, int offset, int blockIndex, int arraySize,
-                               int topLevelArrayStride, TStorageQualifier baseStorage, bool active)
+                               int topLevelArraySize, int topLevelArrayStride, TStorageQualifier baseStorage, bool active)
     {
         // when strictArraySuffix is enabled, we closely follow the rules from ARB_program_interface_query.
         // Broadly:
@@ -288,14 +279,15 @@ public:
                 // Visit all the indices of this array, and for each one add on the remaining dereferencing
                 for (int i = 0; i < std::max(visitNode->getLeft()->getType().getOuterArraySize(), 1); ++i) {
                     TString newBaseName = name;
-                    if (strictArraySuffix && blockParent)
+                    if (terminalType->getBasicType() == EbtBlock) {}
+                    else if (strictArraySuffix && blockParent)
                         newBaseName.append(TString("[0]"));
                     else if (strictArraySuffix || baseType.getBasicType() != EbtBlock)
                         newBaseName.append(TString("[") + String(i) + "]");
                     TList<TIntermBinary*>::const_iterator nextDeref = deref;
                     ++nextDeref;
                     blowUpActiveAggregate(*terminalType, newBaseName, derefs, nextDeref, offset, blockIndex, arraySize,
-                                          topLevelArrayStride, baseStorage, active);
+                                          topLevelArraySize, topLevelArrayStride, baseStorage, active);
 
                     if (offset >= 0)
                         offset += stride;
@@ -308,9 +300,10 @@ public:
                 int stride = getArrayStride(baseType, visitNode->getLeft()->getType());
 
                 index = visitNode->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst();
-                if (strictArraySuffix && blockParent) {
+                if (terminalType->getBasicType() == EbtBlock) {}
+                else if (strictArraySuffix && blockParent)
                     name.append(TString("[0]"));
-                else if (strictArraySuffix || baseType.getBasicType() != EbtBlock) {
+                else if (strictArraySuffix || baseType.getBasicType() != EbtBlock) {
                     name.append(TString("[") + String(index) + "]");
 
                     if (offset >= 0)
@@ -320,7 +313,10 @@ public:
                 if (topLevelArrayStride == 0)
                     topLevelArrayStride = stride;
 
-                blockParent = false;
+                // expand top-level arrays in blocks with [0] suffix
+                if (topLevelArrayStride != 0 && visitNode->getLeft()->getType().isArray()) {
+                    blockParent = false;
+                }
                 break;
             }
             case EOpIndexDirectStruct:
@@ -330,6 +326,12 @@ public:
                 if (name.size() > 0)
                     name.append(".");
                 name.append((*visitNode->getLeft()->getType().getStruct())[index].type->getFieldName());
+
+                // expand non top-level arrays with [x] suffix
+                if (visitNode->getLeft()->getType().getBasicType() != EbtBlock && terminalType->isArray())
+                {
+                    blockParent = false;
+                }
                 break;
             default:
                 break;
@@ -349,14 +351,16 @@ public:
                 if (offset >= 0)
                     stride = getArrayStride(baseType, *terminalType);
 
-                if (topLevelArrayStride == 0)
-                    topLevelArrayStride = stride;
-
                 int arrayIterateSize = std::max(terminalType->getOuterArraySize(), 1);
 
                 // for top-level arrays in blocks, only expand [0] to avoid explosion of items
-                if (strictArraySuffix && blockParent)
+                if ((strictArraySuffix && blockParent) ||
+                    ((topLevelArraySize == arrayIterateSize) && (topLevelArrayStride == 0))) {
                     arrayIterateSize = 1;
+                }
+
+                if (topLevelArrayStride == 0)
+                    topLevelArrayStride = stride;
 
                 for (int i = 0; i < arrayIterateSize; ++i) {
                     TString newBaseName = name;
@@ -367,7 +371,7 @@ public:
                         offset = baseOffset + stride * i;
 
                     blowUpActiveAggregate(derefType, newBaseName, derefs, derefs.end(), offset, blockIndex, 0,
-                                          topLevelArrayStride, baseStorage, active);
+                                          topLevelArraySize, topLevelArrayStride, baseStorage, active);
                 }
             } else {
                 // Visit all members of this aggregate, and for each one,
@@ -396,8 +400,31 @@ public:
                         arrayStride = getArrayStride(baseType, derefType);
                     }
 
-                    blowUpActiveAggregate(derefType, newBaseName, derefs, derefs.end(), offset, blockIndex, 0,
-                                          arrayStride, baseStorage, active);
+                    if (topLevelArraySize == -1 && arrayStride == 0 && blockParent)
+                        topLevelArraySize = 1;
+
+                    if (strictArraySuffix && blockParent) {
+                        // if this member is an array, store the top-level array stride but start the explosion from
+                        // the inner struct type.
+                        if (derefType.isArray() && derefType.isStruct()) {
+                            newBaseName.append("[0]");
+                            auto dimSize = derefType.isUnsizedArray() ? 0 : derefType.getArraySizes()->getDimSize(0);
+                            blowUpActiveAggregate(TType(derefType, 0), newBaseName, derefs, derefs.end(), memberOffsets[i],
+                                blockIndex, 0, dimSize, arrayStride, terminalType->getQualifier().storage, false);
+                        }
+                        else if (derefType.isArray()) {
+                            auto dimSize = derefType.isUnsizedArray() ? 0 : derefType.getArraySizes()->getDimSize(0);
+                            blowUpActiveAggregate(derefType, newBaseName, derefs, derefs.end(), memberOffsets[i], blockIndex,
+                                0, dimSize, 0, terminalType->getQualifier().storage, false);
+                        }
+                        else {
+                            blowUpActiveAggregate(derefType, newBaseName, derefs, derefs.end(), memberOffsets[i], blockIndex,
+                                0, 1, 0, terminalType->getQualifier().storage, false);
+                        }
+                    } else {
+                        blowUpActiveAggregate(derefType, newBaseName, derefs, derefs.end(), offset, blockIndex, 0,
+                                              topLevelArraySize, arrayStride, baseStorage, active);
+                    }
                 }
             }
 
@@ -433,6 +460,7 @@ public:
             if ((reflection.options & EShReflectionSeparateBuffers) && terminalType->isAtomic())
                 reflection.atomicCounterUniformIndices.push_back(uniformIndex);
 
+            variables.back().topLevelArraySize = topLevelArraySize;
             variables.back().topLevelArrayStride = topLevelArrayStride;
             
             if ((reflection.options & EShReflectionAllBlockVariables) && active) {
@@ -564,65 +592,17 @@ public:
             if (! anonymous)
                 baseName = blockName;
 
-            if (base->getType().isArray()) {
-                TType derefType(base->getType(), 0);
-
-                assert(! anonymous);
-                for (int e = 0; e < base->getType().getCumulativeArraySize(); ++e)
-                    blockIndex = addBlockName(blockName + "[" + String(e) + "]", derefType,
-                                              intermediate.getBlockSize(base->getType()));
-                baseName.append(TString("[0]"));
-            } else
-                blockIndex = addBlockName(blockName, base->getType(), intermediate.getBlockSize(base->getType()));
+            blockIndex = addBlockName(blockName, base->getType(), intermediate.getBlockSize(base->getType()));
 
             if (reflection.options & EShReflectionAllBlockVariables) {
                 // Use a degenerate (empty) set of dereferences to immediately put as at the end of
                 // the dereference change expected by blowUpActiveAggregate.
                 TList<TIntermBinary*> derefs;
 
-                // because we don't have any derefs, the first thing blowUpActiveAggregate will do is iterate over each
-                // member in the struct definition. This will lose any information about whether the parent was a buffer
-                // block. So if we're using strict array rules which don't expand the first child of a buffer block we
-                // instead iterate over the children here.
-                const bool strictArraySuffix = (reflection.options & EShReflectionStrictArraySuffix);
-                bool blockParent = (base->getType().getBasicType() == EbtBlock && base->getQualifier().storage == EvqBuffer);
-
-                if (strictArraySuffix && blockParent) {
-                    TType structDerefType(base->getType(), 0);
-
-                    const TType &structType = base->getType().isArray() ? structDerefType : base->getType();
-                    const TTypeList& typeList = *structType.getStruct();
-
-                    TVector<int> memberOffsets;
-
-                    memberOffsets.resize(typeList.size());
-                    getOffsets(structType, memberOffsets);
-
-                    for (int i = 0; i < (int)typeList.size(); ++i) {
-                        TType derefType(structType, i);
-                        TString name = baseName;
-                        if (name.size() > 0)
-                            name.append(".");
-                        name.append(typeList[i].type->getFieldName());
-
-                        // if this member is an array, store the top-level array stride but start the explosion from
-                        // the inner struct type.
-                        if (derefType.isArray() && derefType.isStruct()) {
-                            name.append("[0]");
-                            blowUpActiveAggregate(TType(derefType, 0), name, derefs, derefs.end(), memberOffsets[i],
-                                                  blockIndex, 0, getArrayStride(structType, derefType),
-                                                  base->getQualifier().storage, false);
-                        } else {
-                            blowUpActiveAggregate(derefType, name, derefs, derefs.end(), memberOffsets[i], blockIndex,
-                                                  0, 0, base->getQualifier().storage, false);
-                        }
-                    }
-                } else {
-                    // otherwise - if we're not using strict array suffix rules, or this isn't a block so we are
-                    // expanding root arrays anyway, just start the iteration from the base block type.
-                    blowUpActiveAggregate(base->getType(), baseName, derefs, derefs.end(), 0, blockIndex, 0, 0,
+                // otherwise - if we're not using strict array suffix rules, or this isn't a block so we are
+                // expanding root arrays anyway, just start the iteration from the base block type.
+                blowUpActiveAggregate(base->getType(), baseName, derefs, derefs.end(), 0, blockIndex, 0, -1, 0,
                                           base->getQualifier().storage, false);
-                }
             }
         }
 
@@ -653,31 +633,37 @@ public:
             else
                 baseName = base->getName();
         }
-        blowUpActiveAggregate(base->getType(), baseName, derefs, derefs.begin(), offset, blockIndex, arraySize, 0,
+        blowUpActiveAggregate(base->getType(), baseName, derefs, derefs.begin(), offset, blockIndex, arraySize, -1, 0,
                               base->getQualifier().storage, true);
     }
 
     int addBlockName(const TString& name, const TType& type, int size)
     {
-        TReflection::TMapIndexToReflection& blocks = reflection.GetBlockMapForStorage(type.getQualifier().storage);
-
         int blockIndex;
-        TReflection::TNameToIndex::const_iterator it = reflection.nameToIndex.find(name.c_str());
-        if (reflection.nameToIndex.find(name.c_str()) == reflection.nameToIndex.end()) {
-            blockIndex = (int)blocks.size();
-            reflection.nameToIndex[name.c_str()] = blockIndex;
-            blocks.push_back(TObjectReflection(name.c_str(), type, -1, -1, size, -1));
+        if (type.isArray()) {
+            TType derefType(type, 0);
+            for (int e = 0; e < type.getOuterArraySize(); ++e) {
+                uint32_t memberBlockIndex = addBlockName(name + "[" + String(e) + "]", derefType, size);
+                if (e == 0)
+                    blockIndex = memberBlockIndex;
+            }
+        } else {
+            TReflection::TMapIndexToReflection& blocks = reflection.GetBlockMapForStorage(type.getQualifier().storage);
+
+            TReflection::TNameToIndex::const_iterator it = reflection.nameToIndex.find(name.c_str());
+            if (reflection.nameToIndex.find(name.c_str()) == reflection.nameToIndex.end()) {
+                blockIndex = (int)blocks.size();
+                reflection.nameToIndex[name.c_str()] = blockIndex;
+                blocks.push_back(TObjectReflection(name.c_str(), type, -1, -1, size, blockIndex));
 
-            blocks.back().numMembers = countAggregateMembers(type);
+                blocks.back().numMembers = countAggregateMembers(type);
 
-            if (updateStageMasks) {
                 EShLanguageMask& stages = blocks.back().stages;
                 stages = static_cast<EShLanguageMask>(stages | 1 << intermediate.getStage());
             }
-        } else {
-            blockIndex = it->second;
+            else {
+                blockIndex = it->second;
 
-            if (updateStageMasks) {
                 EShLanguageMask& stages = blocks[blockIndex].stages;
                 stages = static_cast<EShLanguageMask>(stages | 1 << intermediate.getStage());
             }
@@ -1064,7 +1050,7 @@ void TReflectionTraverser::visitSymbol(TIntermSymbol* base)
 {
     if (base->getQualifier().storage == EvqUniform) {
         if (base->getBasicType() == EbtBlock) {
-            if (reflection.options & EShReflectionSharedStd140Blocks) {
+            if (reflection.options & EShReflectionSharedStd140UBO) {
                 addUniform(*base);
             }
         } else {
@@ -1072,6 +1058,13 @@ void TReflectionTraverser::visitSymbol(TIntermSymbol* base)
         }
     }
 
+    // #TODO add std140/layout active rules for ssbo, same with ubo.
+    // Storage buffer blocks will be collected and expanding in this part.
+    if((reflection.options & EShReflectionSharedStd140SSBO) &&
+       (base->getQualifier().storage == EvqBuffer && base->getBasicType() == EbtBlock &&
+        (base->getQualifier().layoutPacking == ElpStd140 || base->getQualifier().layoutPacking == ElpShared)))
+        addUniform(*base);
+
     if ((intermediate.getStage() == reflection.firstStage && base->getQualifier().isPipeInput()) ||
         (intermediate.getStage() == reflection.lastStage && base->getQualifier().isPipeOutput()))
         addPipeIOVariable(*base);
@@ -1182,15 +1175,23 @@ bool TReflection::addStage(EShLanguage stage, const TIntermediate& intermediate)
                 TIntermAggregate* linkerObjects = sequnence->getAsAggregate();
                 for (auto& sequnence : linkerObjects->getSequence()) {
                     auto pNode = sequnence->getAsSymbolNode();
-                    if (pNode != nullptr && pNode->getQualifier().storage == EvqUniform &&
-                        (options & EShReflectionSharedStd140Blocks)) {
-                        if (pNode->getBasicType() == EbtBlock) {
+                    if (pNode != nullptr) {
+                        if ((pNode->getQualifier().storage == EvqUniform &&
+                            (options & EShReflectionSharedStd140UBO)) ||
+                           (pNode->getQualifier().storage == EvqBuffer &&
+                            (options & EShReflectionSharedStd140SSBO))) {
                             // collect std140 and shared uniform block form AST
-                            if (pNode->getQualifier().layoutPacking == ElpStd140 ||
-                                pNode->getQualifier().layoutPacking == ElpShared) {
-                                pNode->traverse(&it);
+                            if ((pNode->getBasicType() == EbtBlock) &&
+                                ((pNode->getQualifier().layoutPacking == ElpStd140) ||
+                                 (pNode->getQualifier().layoutPacking == ElpShared))) {
+                                   pNode->traverse(&it);
                             }
                         }
+                        else if ((options & EShReflectionAllIOVariables) &&
+                            (pNode->getQualifier().isPipeInput() || pNode->getQualifier().isPipeOutput()))
+                        {
+                            pNode->traverse(&it);
+                        }
                     }
                 }
             } else {
index 38693aa..7905b3d 100644 (file)
@@ -271,7 +271,9 @@ typedef enum {
     EShReflectionSeparateBuffers    = (1 << 3), // buffer variables and buffer blocks are reflected separately
     EShReflectionAllBlockVariables  = (1 << 4), // reflect all variables in blocks, even if they are inactive
     EShReflectionUnwrapIOBlocks     = (1 << 5), // unwrap input/output blocks the same as with uniform blocks
-    EShReflectionSharedStd140Blocks = (1 << 6), // Apply std140/shared rules for ubo to ssbo
+    EShReflectionAllIOVariables     = (1 << 6), // reflect all input/output variables, even if they are inactive
+    EShReflectionSharedStd140SSBO   = (1 << 7), // Apply std140/shared rules for ubo to ssbo
+    EShReflectionSharedStd140UBO    = (1 << 8), // Apply std140/shared rules for ubo to ssbo
     LAST_ELEMENT_MARKER(EShReflectionCount),
 } EShReflectionOptions;
 
@@ -696,6 +698,7 @@ public:
     int counterIndex;
     int numMembers;
     int arrayStride;            // stride of an array variable
+    int topLevelArraySize;      // size of the top-level variable in a storage buffer member
     int topLevelArrayStride;    // stride of the top-level variable in a storage buffer member
     EShLanguageMask stages;