summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/glsl/linker.cpp241
-rw-r--r--src/mesa/main/shader_query.cpp244
2 files changed, 243 insertions, 242 deletions
diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp
index 972bd40fa9f..d787b88cd39 100644
--- a/src/glsl/linker.cpp
+++ b/src/glsl/linker.cpp
@@ -3389,6 +3389,242 @@ add_packed_varyings(struct gl_shader_program *shProg, int stage)
return true;
}
+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 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>.
+ */
+
+ /* 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);
+}
+
+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 bool
+is_top_level_shader_storage_block_member(const char* name,
+ const char* interface_name,
+ const char* field_name)
+{
+ bool result = false;
+
+ /* If the given variable is already a top-level shader storage
+ * block member, then return array_size = 1.
+ * We could have two possibilities: if we have an instanced
+ * shader storage block or not instanced.
+ *
+ * For the first, we check create a name as it was in top level and
+ * compare it with the real name. If they are the same, then
+ * the variable is already at top-level.
+ *
+ * Full instanced name is: interface name + '.' + var name +
+ * NULL character
+ */
+ int name_length = strlen(interface_name) + 1 + strlen(field_name) + 1;
+ char *full_instanced_name = (char *) calloc(name_length, sizeof(char));
+ if (!full_instanced_name) {
+ fprintf(stderr, "%s: Cannot allocate space for name\n", __func__);
+ return false;
+ }
+
+ snprintf(full_instanced_name, name_length, "%s.%s",
+ interface_name, field_name);
+
+ /* Check if its top-level shader storage block member of an
+ * instanced interface block, or of a unnamed interface block.
+ */
+ if (strcmp(name, full_instanced_name) == 0 ||
+ strcmp(name, field_name) == 0)
+ result = true;
+
+ free(full_instanced_name);
+ return result;
+}
+
+static void
+calculate_array_size(struct gl_shader_program *shProg,
+ struct gl_uniform_storage *uni)
+{
+ int block_index = uni->block_index;
+ int array_size = -1;
+ char *var_name = get_top_level_name(uni->name);
+ char *interface_name =
+ get_top_level_name(shProg->BufferInterfaceBlocks[block_index].Name);
+
+ if (strcmp(var_name, interface_name) == 0) {
+ /* Deal with instanced array of SSBOs */
+ char *temp_name = get_var_name(uni->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 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 (is_top_level_shader_storage_block_member(uni->name,
+ interface_name,
+ var_name))
+ array_size = 1;
+ else 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);
+ uni->top_level_array_size = array_size;
+}
+
+static void
+calculate_array_stride(struct gl_shader_program *shProg,
+ struct gl_uniform_storage *uni)
+{
+ int block_index = uni->block_index;
+ int array_stride = -1;
+ char *var_name = get_top_level_name(uni->name);
+ char *interface_name =
+ get_top_level_name(shProg->BufferInterfaceBlocks[block_index].Name);
+
+ if (strcmp(var_name, interface_name) == 0) {
+ /* Deal with instanced array of SSBOs */
+ char *temp_name = get_var_name(uni->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 (is_top_level_shader_storage_block_member(uni->name,
+ interface_name,
+ var_name)) {
+ array_stride = 0;
+ goto found_top_level_array_stride;
+ }
+ if (interface->interface_packing != GLSL_INTERFACE_PACKING_STD430) {
+ if (array_type->is_record() || array_type->is_array()) {
+ array_stride = array_type->std140_size(row_major);
+ array_stride = glsl_align(array_stride, 16);
+ } else {
+ unsigned element_base_align = 0;
+ element_base_align = array_type->std140_base_alignment(row_major);
+ array_stride = MAX2(element_base_align, 16);
+ }
+ } else {
+ array_stride = array_type->std430_array_stride(row_major);
+ }
+ } else {
+ array_stride = 0;
+ }
+ goto found_top_level_array_stride;
+ }
+ }
+ }
+found_top_level_array_stride:
+ free(interface_name);
+ free(var_name);
+ uni->top_level_array_stride = array_stride;
+}
+
/**
* Builds up a list of program resources that point to existing
* resource data.
@@ -3473,6 +3709,11 @@ build_program_resource_list(struct gl_shader_program *shProg)
shProg->UniformStorage[i].name))
continue;
+ if (is_shader_storage) {
+ calculate_array_size(shProg, &shProg->UniformStorage[i]);
+ calculate_array_stride(shProg, &shProg->UniformStorage[i]);
+ }
+
if (!add_program_resource(shProg, type,
&shProg->UniformStorage[i], stageref))
return;
diff --git a/src/mesa/main/shader_query.cpp b/src/mesa/main/shader_query.cpp
index 50b44fa9e16..8182d3dcc04 100644
--- a/src/mesa/main/shader_query.cpp
+++ b/src/mesa/main/shader_query.cpp
@@ -839,244 +839,6 @@ 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 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>.
- */
-
- /* 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);
-}
-
-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 bool
-is_top_level_shader_storage_block_member(const char* name,
- const char* interface_name,
- const char* field_name)
-{
- bool result = false;
-
- /* If the given variable is already a top-level shader storage
- * block member, then return array_size = 1.
- * We could have two possibilities: if we have an instanced
- * shader storage block or not instanced.
- *
- * For the first, we check create a name as it was in top level and
- * compare it with the real name. If they are the same, then
- * the variable is already at top-level.
- *
- * Full instanced name is: interface name + '.' + var name +
- * NULL character
- */
- int name_length = strlen(interface_name) + 1 + strlen(field_name) + 1;
- char *full_instanced_name = (char *) calloc(name_length, sizeof(char));
- if (!full_instanced_name) {
- fprintf(stderr, "%s: Cannot allocate space for name\n", __func__);
- return false;
- }
-
- snprintf(full_instanced_name, name_length, "%s.%s",
- interface_name, field_name);
-
- /* Check if its top-level shader storage block member of an
- * instanced interface block, or of a unnamed interface block.
- */
- if (strcmp(name, full_instanced_name) == 0 ||
- strcmp(name, field_name) == 0)
- result = true;
-
- free(full_instanced_name);
- return result;
-}
-
-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->BufferInterfaceBlocks[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 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 (is_top_level_shader_storage_block_member(name,
- interface_name,
- var_name))
- array_size = 1;
- else 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->BufferInterfaceBlocks[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 (is_top_level_shader_storage_block_member(name,
- interface_name,
- var_name)) {
- array_stride = 0;
- goto found_top_level_array_stride;
- }
- if (interface->interface_packing != GLSL_INTERFACE_PACKING_STD430) {
- if (array_type->is_record() || array_type->is_array()) {
- array_stride = array_type->std140_size(row_major);
- array_stride = glsl_align(array_stride, 16);
- } else {
- unsigned element_base_align = 0;
- element_base_align = array_type->std140_base_alignment(row_major);
- array_stride = MAX2(element_base_align, 16);
- }
- } else {
- array_stride = array_type->std430_array_stride(row_major);
- }
- } else {
- array_stride = 0;
- }
- goto found_top_level_array_stride;
- }
- }
- }
-found_top_level_array_stride:
- free(interface_name);
- free(var_name);
- return array_stride;
-}
-
/**
* Function implements following location queries:
* glGetUniformLocation
@@ -1444,14 +1206,12 @@ _mesa_program_resource_prop(struct gl_shader_program *shProg,
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));
+ *val = RESOURCE_UNI(res)->top_level_array_size;
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));
+ *val = RESOURCE_UNI(res)->top_level_array_stride;
return 1;
/* GL_ARB_tessellation_shader */