On 07/31/2015 12:37 PM, Samuel Iglesias Gonsálvez wrote:
On Fri, 2015-07-31 at 09:32 +0200, Samuel Iglesias Gonsálvez wrote:On Fri, 2015-07-31 at 09:09 +0300, Tapani Pälli wrote:On 07/14/2015 10:46 AM, Iago Toral Quiroga wrote:From: Samuel Iglesias Gonsalvez <sigles...@igalia.com> Including TOP_LEVEL_ARRAY_SIZE and TOP_LEVEL_ARRAY_STRIDE queries. Signed-off-by: Samuel Iglesias Gonsalvez <sigles...@igalia.com> --- src/glsl/ir_uniform.h | 5 + src/glsl/link_uniforms.cpp | 17 ++- src/glsl/linker.cpp | 10 +- src/mesa/main/program_resource.c | 7 +- src/mesa/main/shader_query.cpp | 265 +++++++++++++++++++++++++++++++++++++-- 5 files changed, 289 insertions(+), 15 deletions(-) diff --git a/src/glsl/ir_uniform.h b/src/glsl/ir_uniform.h index e1b8014..71d894c 100644 --- a/src/glsl/ir_uniform.h +++ b/src/glsl/ir_uniform.h @@ -186,6 +186,11 @@ struct gl_uniform_storage { * This is a built-in uniform that should not be modified through any gl API. */ bool builtin; + + /** + * This is a shader storage buffer variable, not an uniform. + */ + bool is_shader_storage; }; #ifdef __cplusplus diff --git a/src/glsl/link_uniforms.cpp b/src/glsl/link_uniforms.cpp index eefe7dc..29a8799 100644 --- a/src/glsl/link_uniforms.cpp +++ b/src/glsl/link_uniforms.cpp @@ -638,6 +638,9 @@ private: if (!this->uniforms[id].builtin) this->uniforms[id].storage = this->values; + this->uniforms[id].is_shader_storage = + current_var->is_in_shader_storage_block(); + if (this->ubo_block_index != -1) { this->uniforms[id].block_index = this ->ubo_block_index; @@ -647,8 +650,12 @@ private: this->ubo_byte_offset += type->std140_size(row_major); if (type->is_array()) { - this->uniforms[id].array_stride = - glsl_align(type->fields.array ->std140_size(row_major), 16); + if (type->interface_packing == GLSL_INTERFACE_PACKING_STD430) + this->uniforms[id].array_stride = + type->fields.array->std430_size(row_major); + else + this->uniforms[id].array_stride = + glsl_align(type->fields.array ->std140_size(row_major), 16); } else { this->uniforms[id].array_stride = 0; } @@ -659,7 +666,11 @@ private: const unsigned items = row_major ? matrix ->matrix_columns : matrix->vector_elements; assert(items <= 4); - this->uniforms[id].matrix_stride = glsl_align(items * N, 16); + if (type->interface_packing == GLSL_INTERFACE_PACKING_STD430) + this->uniforms[id].matrix_stride = items < 3 ? items * N : + glsl_align(items * N, 16); + else + this->uniforms[id].matrix_stride = glsl_align(items * N, 16); this->uniforms[id].row_major = row_major; } else { this->uniforms[id].matrix_stride = 0; diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp index 330ef56..e82aa61 100644 --- a/src/glsl/linker.cpp +++ b/src/glsl/linker.cpp @@ -2852,14 +2852,18 @@ build_program_resource_list(struct gl_context *ctx, } } - if (!add_program_resource(shProg, GL_UNIFORM, + bool is_shader_storage = shProg ->UniformStorage[i].is_shader_storage; + GLenum type = is_shader_storage ? GL_BUFFER_VARIABLE : GL_UNIFORM; + if (!add_program_resource(shProg, type, &shProg->UniformStorage[i], stageref)) return; } - /* Add program uniform blocks. */ + /* Add program uniform blocks and shader storage blocks. */ for (unsigned i = 0; i < shProg->NumUniformBlocks; i++) { - if (!add_program_resource(shProg, GL_UNIFORM_BLOCK, + bool is_shader_storage = shProg ->UniformBlocks[i].IsShaderStorage; + GLenum type = is_shader_storage ? GL_SHADER_STORAGE_BLOCK : GL_UNIFORM_BLOCK; + if (!add_program_resource(shProg, type, &shProg->UniformBlocks[i], 0)) return; } diff --git a/src/mesa/main/program_resource.c b/src/mesa/main/program_resource.c index d857b84..0444e3b 100644 --- a/src/mesa/main/program_resource.c +++ b/src/mesa/main/program_resource.c @@ -40,6 +40,8 @@ supported_interface_enum(GLenum iface) case GL_PROGRAM_OUTPUT: case GL_TRANSFORM_FEEDBACK_VARYING: case GL_ATOMIC_COUNTER_BUFFER: + case GL_BUFFER_VARIABLE: + case GL_SHADER_STORAGE_BLOCK: return true; case GL_VERTEX_SUBROUTINE: case GL_TESS_CONTROL_SUBROUTINE: @@ -53,8 +55,6 @@ supported_interface_enum(GLenum iface) case GL_GEOMETRY_SUBROUTINE_UNIFORM: case GL_FRAGMENT_SUBROUTINE_UNIFORM: case GL_COMPUTE_SUBROUTINE_UNIFORM: - case GL_BUFFER_VARIABLE: - case GL_SHADER_STORAGE_BLOCK: default: return false; } @@ -116,6 +116,7 @@ _mesa_GetProgramInterfaceiv(GLuint program, GLenum programInterface, case GL_MAX_NUM_ACTIVE_VARIABLES: switch (programInterface) { case GL_UNIFORM_BLOCK: + case GL_SHADER_STORAGE_BLOCK: for (i = 0, *params = 0; i < shProg ->NumProgramResourceList; i++) { if (shProg->ProgramResourceList[i].Type == programInterface) { struct gl_uniform_block *block = @@ -220,12 +221,14 @@ _mesa_GetProgramResourceIndex(GLuint program, GLenum programInterface, case GL_PROGRAM_INPUT: case GL_PROGRAM_OUTPUT: case GL_UNIFORM: + case GL_BUFFER_VARIABLE: case GL_TRANSFORM_FEEDBACK_VARYING: /* Validate name syntax for array variables */ if (!valid_program_resource_index_name(name)) return GL_INVALID_INDEX; /* fall-through */ case GL_UNIFORM_BLOCK: + case GL_SHADER_STORAGE_BLOCK: res = _mesa_program_resource_find_name(shProg, programInterface, name); if (!res) return GL_INVALID_INDEX; diff --git a/src/mesa/main/shader_query.cpp b/src/mesa/main/shader_query.cpp index a6246a3..2f1b8e2 100644 --- a/src/mesa/main/shader_query.cpp +++ b/src/mesa/main/shader_query.cpp @@ -482,6 +482,7 @@ _mesa_program_resource_name(struct gl_program_resource *res) const ir_variable *var; switch (res->Type) { case GL_UNIFORM_BLOCK: + case GL_SHADER_STORAGE_BLOCK: return RESOURCE_UBO(res)->Name; case GL_TRANSFORM_FEEDBACK_VARYING: return RESOURCE_XFB(res)->Name; @@ -496,6 +497,7 @@ _mesa_program_resource_name(struct gl_program_resource *res) case GL_PROGRAM_OUTPUT: return RESOURCE_VAR(res)->name; case GL_UNIFORM: + case GL_BUFFER_VARIABLE: return RESOURCE_UNI(res)->name; default: assert(!"support for resource type not implemented"); @@ -515,9 +517,11 @@ _mesa_program_resource_array_size(struct gl_program_resource *res) case GL_PROGRAM_OUTPUT: return RESOURCE_VAR(res)->data.max_array_access; case GL_UNIFORM: + case GL_BUFFER_VARIABLE: return RESOURCE_UNI(res)->array_elements; case GL_ATOMIC_COUNTER_BUFFER: case GL_UNIFORM_BLOCK: + case GL_SHADER_STORAGE_BLOCK: return 0; default: assert(!"support for resource type not implemented"); @@ -571,6 +575,8 @@ _mesa_program_resource_find_name(struct gl_shader_program *shProg, case GL_TRANSFORM_FEEDBACK_VARYING: case GL_UNIFORM_BLOCK: case GL_UNIFORM: + case GL_SHADER_STORAGE_BLOCK: + case GL_BUFFER_VARIABLE: if (strncmp(rname, name, baselen) == 0) { /* Basename match, check if array or struct. */ if (name[baselen] == '\0' || @@ -619,6 +625,7 @@ _mesa_program_resource_index(struct gl_shader_program *shProg, switch (res->Type) { case GL_UNIFORM_BLOCK: + case GL_SHADER_STORAGE_BLOCK: return RESOURCE_UBO(res)- shProg->UniformBlocks; case GL_ATOMIC_COUNTER_BUFFER: return RESOURCE_ATC(res) - shProg->AtomicBuffers; @@ -644,6 +651,7 @@ _mesa_program_resource_find_index(struct gl_shader_program *shProg, switch (res->Type) { case GL_UNIFORM_BLOCK: case GL_ATOMIC_COUNTER_BUFFER: + case GL_SHADER_STORAGE_BLOCK: if (_mesa_program_resource_index(shProg, res) == index) return res; break; @@ -651,6 +659,7 @@ _mesa_program_resource_find_index(struct gl_shader_program *shProg, case GL_PROGRAM_INPUT: case GL_PROGRAM_OUTPUT: case GL_UNIFORM: + case GL_BUFFER_VARIABLE: if (++idx == (int) index) return res; break; @@ -785,6 +794,197 @@ program_resource_location(struct gl_shader_program *shProg, } } +static char* +get_top_level_name(const char *name) +{ + const char *first_dot = strchr(name, '.'); + const char *first_square_bracket = strchr(name, '['); + int name_size = 0; + /* From GL_shader_storage_buffer_object spec:Here it should be ARB_program_interface_query spec. I am going to change it.
OK
+ * + * "For the property TOP_LEVEL_ARRAY_SIZE, a single integer identifying the + * number of active array elements of the top-level shader storage block + * member containing to the active variable is written to <params>. If the + * top-level block member is not declared as an array, the value one is + * written to <params>. If the top-level block member is an array with no + * declared size, the value zero is written to <params>. + */ + + /* The buffer variable is on top level.*/ + if (!first_square_bracket && !first_dot) + name_size = strlen(name); + else if ((!first_square_bracket || + (first_dot && first_dot < first_square_bracket))) + name_size = first_dot - name; + else + name_size = first_square_bracket - name; + + return strndup(name, name_size); +}I think instead of this function you should be able to do something along the lines of: const char *base_name_end; const char *base_name = parse_program_resource_name(name, &base_name_end); return strndup(base_name, base_name_end - base_name);OKI have checked this solution and it doesn't work: parse_program_resource_name() expects the name to be of an array element (i.e, last char is ']'). If this is not the case, it returns the same name written into 'out_base_name_end' and 'array_index' is -1.
Argh I see, sorry for leading to wrong tracks. Then I'm happy with the added function.
Notice that the buffer variable used to query TOP_LEVEL_ARRAY_SIZE could not be an array element and we want to know the array size of the top-level shader storage block member containing that buffer variable.
Right, this makes sense. I was hoping we could utilize existing 'parsing' logic but it seems it is not that generic as it makes the array assumption.
With the other small changes fixed this is Reviewed-by: Tapani Pälli <tapani.pa...@intel.com>
See ARB_program_interface_query spec: "For the property TOP_LEVEL_ARRAY_SIZE, a single integer identifying the number of active array elements of the top-level shader storage block member containing to the active variable is written to <params>. If the top-level block member is not declared as an array, the value one is written to <params>. If the top-level block member is an array with no declared size, the value zero is written to <params>." Sam+ +static char* +get_var_name(const char *name) +{ + const char *first_dot = strchr(name, '.'); + + if (!first_dot) + return strdup(name); + + return strndup(first_dot+1, strlen(first_dot) - 1); +} + +static GLint +program_resource_top_level_array_size(struct gl_shader_program *shProg, + struct gl_program_resource *res, + const char *name) +{ + int block_index = RESOURCE_UNI(res)->block_index; + int array_size = -1; + char *var_name = get_top_level_name(name); + char *interface_name = + get_top_level_name(shProg ->UniformBlocks[block_index].Name); + + if (strcmp(var_name, interface_name) == 0) { + /* Deal with instanced array of SSBOs */ + char *temp_name = get_var_name(name); + free(var_name); + var_name = get_top_level_name(temp_name); + free(temp_name); + } + + for (unsigned i = 0; i < shProg->NumShaders; i++) { + if (shProg->Shaders[i] == NULL) + continue; + + const gl_shader *stage = shProg->Shaders[i]; + foreach_in_list(ir_instruction, node, stage->ir) { + ir_variable *var = node->as_variable(); + if (!var || !var->get_interface_type() || + var->data.mode != ir_var_shader_storage) + continue; + + const glsl_type *interface = var->get_interface_type(); + + if (strcmp(interface_name, interface->name) != 0) { + continue; + }strip { } for single line statementOK+ + for (unsigned i = 0; i < interface->length; i++) { + const glsl_struct_field *field = &interface ->fields.structure[i]; + if (strcmp(field->name, var_name) != 0) + continue; + /* From GL_ARB_program_interface_query spec: + * + * "For the property TOP_LEVEL_ARRAY_SIZE, a single integer + * identifying the number of active array elements of the top-level + * shader storage block member containing to the active variable is + * written to <params>. If the top-level block member is not + * declared as an array, the value one is written to <params>. If + * the top-level block member is an array with no declared size, + * the value zero is written to <params>. + */ + if (field->type->is_unsized_array()) + array_size = 0; + else if (field->type->is_array()) + array_size = field->type->length; + else + array_size = 1; + goto found_top_level_array_size; + } + } + } +found_top_level_array_size: + free(interface_name); + free(var_name); + return array_size; +} + +static GLint +program_resource_top_level_array_stride(struct gl_shader_program *shProg, + struct gl_program_resource *res, + const char *name) +{ + int block_index = RESOURCE_UNI(res)->block_index; + int array_stride = -1; + char *var_name = get_top_level_name(name); + char *interface_name = + get_top_level_name(shProg ->UniformBlocks[block_index].Name); + + if (strcmp(var_name, interface_name) == 0) { + /* Deal with instanced array of SSBOs */ + char *temp_name = get_var_name(name); + free(var_name); + var_name = get_top_level_name(temp_name); + free(temp_name); + } + + for (unsigned i = 0; i < shProg->NumShaders; i++) { + if (shProg->Shaders[i] == NULL) + continue; + + const gl_shader *stage = shProg->Shaders[i]; + foreach_in_list(ir_instruction, node, stage->ir) { + ir_variable *var = node->as_variable(); + if (!var || !var->get_interface_type() || + var->data.mode != ir_var_shader_storage) + continue; + + const glsl_type *interface = var->get_interface_type(); + + if (strcmp(interface_name, interface->name) != 0) { + continue; + } + + for (unsigned i = 0; i < interface->length; i++) { + const glsl_struct_field *field = &interface ->fields.structure[i]; + if (strcmp(field->name, var_name) != 0) + continue; + /* From GL_ARB_program_interface_query: + * + * "For the property TOP_LEVEL_ARRAY_STRIDE, a single integer + * identifying the stride between array elements of the top-level + * shader storage block member containing the active variable is + * written to <params>. For top-level block members declared as + * arrays, the value written is the difference, in basic machine + * units, between the offsets of the active variable for + * consecutive elements in the top-level array. For top-level + * block members not declared as an array, zero is written to + * <params>." + */ + if (field->type->is_array()) { + const enum glsl_matrix_layout matrix_layout = + glsl_matrix_layout(field->matrix_layout); + bool row_major = matrix_layout == GLSL_MATRIX_LAYOUT_ROW_MAJOR; + const glsl_type *array_type = field->type ->fields.array; + + if (array_type->is_record()) { + if (field->type->interface_packing == GLSL_INTERFACE_PACKING_STD430) { + array_stride = array_type ->std430_size(row_major); + } else { + array_stride = array_type ->std140_size(row_major); + array_stride = glsl_align(array_stride, 16); + } + } else { + unsigned element_base_align = 0; + if (field->type->interface_packing == GLSL_INTERFACE_PACKING_STD430) { + array_stride = array_type ->std430_base_alignment(row_major); + } else { + element_base_align = array_type ->std140_base_alignment(row_major); + array_stride = MAX2(element_base_align, 16); + } + } + } else { + array_stride = 0; + } + goto found_top_level_array_size; + } + } + } +found_top_level_array_size: + free(var_name); + return array_stride; +} + /** * Function implements following location queries: * glGetAttribLocation @@ -857,7 +1057,7 @@ is_resource_referenced(struct gl_shader_program *shProg, if (res->Type == GL_ATOMIC_COUNTER_BUFFER) return RESOURCE_ATC(res)->StageReferences[stage]; - if (res->Type == GL_UNIFORM_BLOCK) + if (res->Type == GL_UNIFORM_BLOCK || res->Type == GL_SHADER_STORAGE_BLOCK) return shProg->UniformBlockStageIndex[stage][index] != -1; return res->StageReferences & (1 << stage); @@ -870,7 +1070,8 @@ get_buffer_property(struct gl_shader_program *shProg, { GET_CURRENT_CONTEXT(ctx); if (res->Type != GL_UNIFORM_BLOCK && - res->Type != GL_ATOMIC_COUNTER_BUFFER) + res->Type != GL_ATOMIC_COUNTER_BUFFER && + res->Type != GL_SHADER_STORAGE_BLOCK) goto invalid_operation; if (res->Type == GL_UNIFORM_BLOCK) { @@ -904,6 +1105,37 @@ get_buffer_property(struct gl_shader_program *shProg, } return RESOURCE_UBO(res)->NumUniforms; } + } else if (res->Type == GL_SHADER_STORAGE_BLOCK) { + switch (prop) { + case GL_BUFFER_BINDING: + *val = RESOURCE_UBO(res)->Binding; + return 1; + case GL_BUFFER_DATA_SIZE: + *val = RESOURCE_UBO(res)->UniformBufferSize; + return 1; + case GL_NUM_ACTIVE_VARIABLES: + *val = 0; + for (unsigned i = 0; i < RESOURCE_UBO(res) ->NumUniforms; i++) { + const char *iname = RESOURCE_UBO(res) ->Uniforms[i].IndexName; + struct gl_program_resource *uni = + _mesa_program_resource_find_name(shProg, GL_BUFFER_VARIABLE, iname); + if (!uni) + continue; + (*val)++; + } + return 1; + case GL_ACTIVE_VARIABLES: + for (unsigned i = 0; i < RESOURCE_UBO(res) ->NumUniforms; i++) { + const char *iname = RESOURCE_UBO(res) ->Uniforms[i].IndexName; + struct gl_program_resource *uni = + _mesa_program_resource_find_name(shProg, GL_BUFFER_VARIABLE, iname); + if (!uni) + continue; + *val++ = + _mesa_program_resource_index(shProg, uni); + } + return RESOURCE_UBO(res)->NumUniforms; + } } else if (res->Type == GL_ATOMIC_COUNTER_BUFFER) { switch (prop) { case GL_BUFFER_BINDING: @@ -942,6 +1174,10 @@ _mesa_program_resource_prop(struct gl_shader_program *shProg, if (res->Type != type)\ goto invalid_operation; +#define VALIDATE_TYPE_2(type1, type2)\ + if (res->Type != type1 && res->Type != type2)\ + goto invalid_operation; +add undef for VALIDATE_TYPE2OK Thanks for the review! Samswitch(prop) { case GL_NAME_LENGTH: if (res->Type == GL_ATOMIC_COUNTER_BUFFER) @@ -953,6 +1189,7 @@ _mesa_program_resource_prop(struct gl_shader_program *shProg, case GL_TYPE: switch (res->Type) { case GL_UNIFORM: + case GL_BUFFER_VARIABLE: *val = RESOURCE_UNI(res)->type->gl_type; return 1; case GL_PROGRAM_INPUT: @@ -968,6 +1205,7 @@ _mesa_program_resource_prop(struct gl_shader_program *shProg, case GL_ARRAY_SIZE: switch (res->Type) { case GL_UNIFORM: + case GL_BUFFER_VARIABLE: *val = MAX2(RESOURCE_UNI(res)->array_elements, 1); return 1; case GL_PROGRAM_INPUT: @@ -981,23 +1219,23 @@ _mesa_program_resource_prop(struct gl_shader_program *shProg, goto invalid_operation; } case GL_OFFSET: - VALIDATE_TYPE(GL_UNIFORM); + VALIDATE_TYPE_2(GL_UNIFORM, GL_BUFFER_VARIABLE); *val = RESOURCE_UNI(res)->offset; return 1; case GL_BLOCK_INDEX: - VALIDATE_TYPE(GL_UNIFORM); + VALIDATE_TYPE_2(GL_UNIFORM, GL_BUFFER_VARIABLE); *val = RESOURCE_UNI(res)->block_index; return 1; case GL_ARRAY_STRIDE: - VALIDATE_TYPE(GL_UNIFORM); + VALIDATE_TYPE_2(GL_UNIFORM, GL_BUFFER_VARIABLE); *val = RESOURCE_UNI(res)->array_stride; return 1; case GL_MATRIX_STRIDE: - VALIDATE_TYPE(GL_UNIFORM); + VALIDATE_TYPE_2(GL_UNIFORM, GL_BUFFER_VARIABLE); *val = RESOURCE_UNI(res)->matrix_stride; return 1; case GL_IS_ROW_MAJOR: - VALIDATE_TYPE(GL_UNIFORM); + VALIDATE_TYPE_2(GL_UNIFORM, GL_BUFFER_VARIABLE); *val = RESOURCE_UNI(res)->row_major; return 1; case GL_ATOMIC_COUNTER_BUFFER_INDEX: @@ -1021,6 +1259,8 @@ _mesa_program_resource_prop(struct gl_shader_program *shProg, case GL_PROGRAM_INPUT: case GL_PROGRAM_OUTPUT: case GL_UNIFORM_BLOCK: + case GL_BUFFER_VARIABLE: + case GL_SHADER_STORAGE_BLOCK: case GL_ATOMIC_COUNTER_BUFFER: *val = is_resource_referenced(shProg, res, index, stage_from_enum(prop)); @@ -1045,6 +1285,17 @@ _mesa_program_resource_prop(struct gl_shader_program *shProg, *val = RESOURCE_VAR(res)->data.index; return 1; + case GL_TOP_LEVEL_ARRAY_SIZE: + VALIDATE_TYPE(GL_BUFFER_VARIABLE); + *val = program_resource_top_level_array_size(shProg, res, + _mesa_program_resource_name(res)); + return 1; + + case GL_TOP_LEVEL_ARRAY_STRIDE: + VALIDATE_TYPE(GL_BUFFER_VARIABLE); + *val = program_resource_top_level_array_stride(shProg, res, + _mesa_program_resource_name(res)); + return 1; /* GL_ARB_tessellation_shader */ case GL_IS_PER_PATCH: case GL_REFERENCED_BY_TESS_CONTROL_SHADER:_______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev
_______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev