On Monday, December 19, 2016 1:36:00 PM PST Ian Romanick wrote: > On 12/16/2016 09:35 PM, Kenneth Graunke wrote: > > This fixes 555 dEQP tests (using the nougat-cts-dev branch), Piglit's > > arb_program_interface_query/arb_program_interface_query-resource-query, > > and GL45-CTS.program_interface_query.separate-programs-{tess-control, > > tess-eval,geometry}. Only one dEQP program interface failure remains. > > > > I would have liked to split this up into several distinct changes, but > > I wasn't sure how to do that given thet tangled nature of these issues. > > > > So, the issues: > > > > * We need to treat interface blocks declared as an array of instances > > as a single block - removing the outer array. The resource list > > entry's name should not include the array length. Properties such > > as GL_ARRAY_SIZE should refer to the variable inside the block, not > > the interface block's array properties. > > > > * We need to do this prefixing even for structure variables. > > > > * We need to do this for built-ins (such as gl_PerVertex.gl_Position). > > > > * After interface array unwrapping, any variable which is an array > > should have [0] appended. It doesn't matter if it's a TCS/TES/GS > > input or TCS output - that looked like an attempt to unwrap for > > per-vertex variables, but that didn't consider per-patch variables, > > and as far as I can tell there's nothing to justify this. > > > > Several Mesa developers have suggested that Issue 16 contradicts the > > main specification, but I believe that it doesn't - the main spec just > > isn't terribly clear. The main ARB_program_interface query spec says: > > > > "* For an active interface block not declared as an array of block > > instances, a single entry will be generated, using the block name from > > the shader source. > > > > * For an active interface block declared as an array of instances, > > separate entries will be generated for each active instance. The name > > of the instance is formed by concatenating the block name, the "[" > > character, an integer identifying the instance number, and the "]" > > character." > > > > Issue 16 says that built-ins should be named "gl_PerVertex.gl_Position", > > but several people suggested the second bullet above means that it > > should be named "gl_PerVertex[array length].gl_Position". > > > > There are two important things to note. Those bullet points say > > "an active interface block", while the others say "variable" or "active > > shader storage block member". They also don't mention applying the > > rules recursively (unlike the other bullets). Both suggest that > > these rules apply to blocks themselves, not members of blocks. > > > > In fact, for GL_UNIFORM_BLOCK queries, we do have "block[0]", > > "block[1]", ... resource list entries - so those rules are real, > > and actually used. So if they don't apply to block members, then how > > should members be named? Unfortunately, I don't see any rules outside > > of issue 16 - where the rationale is very unclear. I hope to clarify > > the spec in the future. > > Based on my understanding, something like > > out Vertex { > vec4 p; > vec4 c[3]; > } vertex[2]; > > in a vertex shader should produce > > Vertex[0].p > Vertex[0].c[0] (with GL_ARRAY_SIZE = 3) > Vertex[1].p > Vertex[1].c[0] (with GL_ARRAY_SIZE = 3) > > This is definitely what we would produce for a uniform block. > > What I've never understood is why that isn't done for gl_PerVertex stage > boundaries where gl_PerVertex is explicitly arrayed.
My expectation is that the above code would produce: Block entries: Vertex[0] Vertex[1] Variable/member entries: Vertex.p Vertex.c[0] (with GL_ARRAY_SIZE = 3) We would produce similar results for uniform blocks after my patch. I don't think anything about the rules is gl_PerVertex specific. > I think this patch is good for now. I like that it brings all the > strange edge-case handling into one place. > > Reviewed-by: Ian Romanick <ian.d.roman...@intel.com> I've attached some notes I took while looking at dEQP program interface query tests - it has the shader code and expected results for a lot of test cases. I didn't write down the uniform ones, but they follow the same pattern (as shown above). For what it's worth, the OpenGL wiki's Program Introspection page(*), under "Interface block member naming" gives an example matching my above reply. It says: uniform BlockName3 { int mem; } instanceName3[4]; This definition will create a single member named "BlockName3.min". The reason this array of four blocks only counts as having one variable is because each of the four blocks uses the same internal definition. There is nothing that could be queried from BlockName3[1] that could not be queried from BlockName3[0]. (*) https://www.khronos.org/opengl/wiki/Program_Introspection I think that's a decent explanation of why this is reasonable. Because the block entries have per-element entries (Block[0], Block[1], etc. you can query whether a block is referenced (i.e. a UBO binding is used). But for fields...things like names, locations, and so on would be the same regardless of whether it's Block[0].field or Block[1].field. So they collapsed the field entries to "Block.field". --Ken
╻┏┓╻┏━┓╺┳╸┏━┓┏┓╻┏━╸┏━╸╺┳┓ ╻┏┓╻╺┳╸┏━╸┏━┓┏━╸┏━┓┏━╸┏━╸┏━┓ ┃┃┗┫┗━┓ ┃ ┣━┫┃┗┫┃ ┣╸ ┃┃ ┃┃┗┫ ┃ ┣╸ ┣┳┛┣╸ ┣━┫┃ ┣╸ ┗━┓ ╹╹ ╹┗━┛ ╹ ╹ ╹╹ ╹┗━╸┗━╸╺┻┛ ╹╹ ╹ ╹ ┗━╸╹┗╸╹ ╹ ╹┗━╸┗━╸┗━┛ (( Interface is an instanced array? Unwrap it. )) program_input.resource_list.interface_blocks.in.named_block.var in TargetInterface { highp vec4 target; } targetInstance; => TargetInterface.target OK. program_input.resource_list.interface_blocks.in.named_block_explicit_location.var layout(location=3) in TargetInterface { highp vec4 target; } targetInstance; => TargetInterface.target OK. program_input.resource_list.interface_blocks.in.named_block.var_array in TargetInterface { highp vec4 target[3]; } targetInstance; => TargetInterface.target[0] OK. program_input.resource_list.interface_blocks.in.named_block_explicit_location.var_array layout(location=3) in TargetInterface { highp vec4 target[3]; } targetInstance; => TargetInterface.target[0] OK. program_input.resource_list.interface_blocks.in.block_array.var program_input.location.interface_blocks.in.block_array.var (FS) in TargetInterface { highp vec4 target; } targetInstance[3]; => TargetInterface.target OK. program_input.resource_list.interface_blocks.in.block_array.var_array (FS) in TargetInterface { highp vec4 target[3]; } targetInstance[2]; => TargetInterface.target[0] OK. program_input.resource_list.interface_blocks.patch_in.named_block.var patch in TargetInterface { highp vec4 target; } targetInstance; => TargetInterface.target OK. program_input.resource_list.interface_blocks.patch_in.named_block_explicit_location.var layout(location=3) patch in TargetInterface { highp vec4 target; } targetInstance; => TargetInterface.target OK. program_input.resource_list.interface_blocks.patch_in.named_block.var_array patch in TargetInterface { highp vec4 target[3]; } targetInstance; => TargetInterface.target[0] OK. program_input.resource_list.interface_blocks.patch_in.named_block_explicit_location.var_array layout(location=3) patch in TargetInterface { highp vec4 target[3]; } targetInstance; => TargetInterface.target[0] OK. program_input.resource_list.interface_blocks.patch_in.block_array.var patch in TargetInterface { highp vec4 target; } targetInstance[3]; => TargetInterface.target OK. program_input.resource_list.interface_blocks.patch_in.block_array.var_array patch in TargetInterface { highp vec4 target[3]; } targetInstance[2]; => TargetInterface.target[0] OK. program_output.resource_list.interface_blocks.out.named_block.var program_output.resource_list.interface_blocks.out.named_block.var_array program_output.resource_list.interface_blocks.out.named_block_explicit_location.var program_output.resource_list.interface_blocks.out.named_block_explicit_location.var_array program_output.resource_list.interface_blocks.out.block_array.var program_output.resource_list.interface_blocks.out.block_array.var_array program_output.resource_list.interface_blocks.patch_out.named_block.var program_output.resource_list.interface_blocks.patch_out.named_block.var_array program_output.resource_list.interface_blocks.patch_out.named_block_explicit_location.var program_output.resource_list.interface_blocks.patch_out.named_block_explicit_location.var_array program_output.resource_list.interface_blocks.patch_out.block_array.var_array ╻ ╻┏┓╻┏┓╻┏━┓┏┳┓┏━╸╺┳┓ ╻┏┓╻╺┳╸┏━╸┏━┓┏━╸┏━┓┏━╸┏━╸┏━┓ ┃ ┃┃┗┫┃┗┫┣━┫┃┃┃┣╸ ┃┃ ┃┃┗┫ ┃ ┣╸ ┣┳┛┣╸ ┣━┫┃ ┣╸ ┗━┓ ┗━┛╹ ╹╹ ╹╹ ╹╹ ╹┗━╸╺┻┛ ╹╹ ╹ ╹ ┗━╸╹┗╸╹ ╹ ╹┗━╸┗━╸┗━┛ program_input.resource_list.interface_blocks.in.unnamed_block.var in TargetInterface { highp vec4 target; }; => target program_input.resource_list.interface_blocks.in.unnamed_block.var_array in TargetInterface { highp vec4 target[3]; }; => target[0] program_input.resource_list.interface_blocks.patch_in.unnamed_block.var patch in TargetInterface { highp vec4 target; }; => target program_input.resource_list.interface_blocks.patch_in.unnamed_block.var_array patch in TargetInterface { highp vec4 target[3]; }; => target[0] program_output.resource_list.interface_blocks.out.unnamed_block.var program_output.resource_list.interface_blocks.out.unnamed_block.var_array program_output.resource_list.interface_blocks.patch_out.unnamed_block.var program_output.resource_list.interface_blocks.patch_out.unnamed_block.var_array program_output.resource_list.interface_blocks.patch_out.block_array.var ┏━┓╻┏┳┓┏━┓╻ ┏━╸ ╻ ╻┏━┓┏━┓╻┏━┓┏┓ ╻ ┏━╸┏━┓ ┗━┓┃┃┃┃┣━┛┃ ┣╸ ┃┏┛┣━┫┣┳┛┃┣━┫┣┻┓┃ ┣╸ ┗━┓ ┗━┛╹╹ ╹╹ ┗━╸┗━╸ ┗┛ ╹ ╹╹┗╸╹╹ ╹┗━┛┗━╸┗━╸┗━┛ (( Use the name of the variable. If an array, append "[0]". )) program_input.resource_list.vertex_fragment.var program_input.resource_list.separable_fragment.var in highp vec4 target; => target program_input.resource_list.separable_fragment.var_array in highp vec4 target[3]; => target[0] program_input.resource_list.separable_tess_ctrl.var program_input.resource_list.separable_tess_eval.var program_input.resource_list.separable_geometry.var in highp vec4 target[]; => target[0] program_input.resource_list.separable_tess_eval.patch_var patch in highp vec4 target; => target program_input.resource_list.separable_tess_eval.patch_var_array patch in highp vec4 target[3]; => target[0] program_output.resource_list.vertex_fragment.var program_output.resource_list.separable_vertex.var program_output.resource_list.separable_fragment.var out highp vec4 target; => target program_output.resource_list.vertex_fragment.var_array program_output.resource_list.separable_vertex.var_array program_output.resource_list.separable_fragment.var_array out highp vec4 target[3]; => target[0] program_output.resource_list.separable_tess_ctrl.var program_output.resource_list.separable_tess_ctrl.patch_var program_output.resource_list.separable_tess_ctrl.patch_var_array => gl_TessLevelOuter[0] and gl_TessLevelInner[0] ┏━┓╺┳╸┏━┓╻ ╻┏━╸╺┳╸┏━┓ ┗━┓ ┃ ┣┳┛┃ ┃┃ ┃ ┗━┓ ┗━┛ ╹ ╹┗╸┗━┛┗━╸ ╹ ┗━┛ (( [<interface>.]<struct-name>.<recurse> )) program_input.resource_list.separable_fragment.var_struct program_input.resource_list.separable_tess_eval.patch_var_struct program_input.resource_list.interface_blocks.in.named_block.var_struct program_input.resource_list.interface_blocks.in.named_block_explicit_location.var_struct program_input.resource_list.interface_blocks.in.unnamed_block.var_struct program_input.resource_list.interface_blocks.in.block_array.var_struct program_input.resource_list.interface_blocks.patch_in.named_block.var_struct program_input.resource_list.interface_blocks.patch_in.named_block_explicit_location.var_struct program_input.resource_list.interface_blocks.patch_in.unnamed_block.var_struct program_input.resource_list.interface_blocks.patch_in.block_array.var_struct program_output.resource_list.separable_vertex.var_struct program_output.resource_list.separable_tess_ctrl.patch_var_struct program_output.resource_list.separable_tess_eval.var_struct program_output.resource_list.separable_geometry.var_struct program_output.resource_list.interface_blocks.out.named_block.var_struct program_output.resource_list.interface_blocks.out.named_block_explicit_location.var_struct program_output.resource_list.interface_blocks.out.unnamed_block.var_struct program_output.resource_list.interface_blocks.out.block_array.var_struct program_output.resource_list.interface_blocks.patch_out.named_block.var_struct program_output.resource_list.interface_blocks.patch_out.named_block_explicit_location.var_struct program_output.resource_list.interface_blocks.patch_out.unnamed_block.var_struct program_output.resource_list.interface_blocks.patch_out.block_array.var_struct program_input.resource_list.interface_blocks.in.block_array.var_struct program_input.array_size.interface_blocks.in.block_array.var_struct (FS) struct StructType0 { highp vec4 target; }; in TargetInterface { StructType0 target; } targetInstance[3]; => TargetInterface.target.target program_input.resource_list.interface_blocks.patch_in.block_array.var_struct program_input.array_size.interface_blocks.patch_in.block_array.var_struct struct StructType0 { highp vec4 target; }; patch in TargetInterface { StructType0 target; } targetInstance[3]; => TargetInterface.target.target program_input.resource_list.separable_fragment.var_struct struct StructType0 { highp vec4 target; }; in StructType0 target; => target.target
signature.asc
Description: This is a digitally signed message part.
_______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev