aboutsummaryrefslogtreecommitdiffstats
path: root/src/glsl/linker.cpp
diff options
context:
space:
mode:
authorJuha-Pekka Heikkila <[email protected]>2015-10-21 12:09:21 +0300
committerJuha-Pekka Heikkila <[email protected]>2015-11-02 10:03:32 +0200
commitc2c124f89194fe33af522f090aa8e71f2c3aa474 (patch)
treede030222f2d5d77642602a70ed8a86ae62fe26ce /src/glsl/linker.cpp
parentaf7c98a9c75b17fc8c8ed0989aa732766e5b06d1 (diff)
glsl: join calculate_array_size() and calculate_array_stride()
These helpers are ran for same case the same loop. Here joined their operation so the loop is ran just once. Also fixed out-of-memory condition here. v2: Make the loop simpler to read as per Tapani's suggestion Signed-off-by: Juha-Pekka Heikkila <[email protected]> Reviewed-by: Samuel Iglesias Gonsálvez <[email protected]> Tested-by: Tapani Pälli <[email protected]>
Diffstat (limited to 'src/glsl/linker.cpp')
-rw-r--r--src/glsl/linker.cpp190
1 files changed, 80 insertions, 110 deletions
diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp
index 48dd2d38633..c35d87acea6 100644
--- a/src/glsl/linker.cpp
+++ b/src/glsl/linker.cpp
@@ -3530,80 +3530,78 @@ is_top_level_shader_storage_block_member(const char* name,
return result;
}
-static void
-calculate_array_size(struct gl_shader_program *shProg,
- struct gl_uniform_storage *uni)
+static int
+get_array_size(struct gl_uniform_storage *uni, const glsl_struct_field *field,
+ char *interface_name, char *var_name)
{
- 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;
+ /* 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))
+ return 1;
+ else if (field->type->is_unsized_array())
+ return 0;
+ else if (field->type->is_array())
+ return field->type->length;
+
+ return 1;
+}
- goto found_top_level_array_size;
- }
+static int
+get_array_stride(struct gl_uniform_storage *uni, const glsl_type *interface,
+ const glsl_struct_field *field, char *interface_name,
+ char *var_name)
+{
+ /* 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))
+ return 0;
+
+ if (interface->interface_packing != GLSL_INTERFACE_PACKING_STD430) {
+ if (array_type->is_record() || array_type->is_array())
+ return glsl_align(array_type->std140_size(row_major), 16);
+ else
+ return MAX2(array_type->std140_base_alignment(row_major), 16);
+ } else {
+ return array_type->std430_array_stride(row_major);
}
}
-found_top_level_array_size:
- free(interface_name);
- free(var_name);
- uni->top_level_array_size = array_size;
+ return 0;
}
static void
-calculate_array_stride(struct gl_shader_program *shProg,
- struct gl_uniform_storage *uni)
+calculate_array_size_and_stride(struct gl_shader_program *shProg,
+ struct gl_uniform_storage *uni)
{
int block_index = uni->block_index;
+ int array_size = -1;
int array_stride = -1;
char *var_name = get_top_level_name(uni->name);
char *interface_name =
@@ -3612,9 +3610,17 @@ calculate_array_stride(struct gl_shader_program *shProg,
if (strcmp(var_name, interface_name) == 0) {
/* Deal with instanced array of SSBOs */
char *temp_name = get_var_name(uni->name);
+ if (!temp_name) {
+ linker_error(shProg, "Out of memory during linking.\n");
+ goto write_top_level_array_size_and_stride;
+ }
free(var_name);
var_name = get_top_level_name(temp_name);
free(temp_name);
+ if (!var_name) {
+ linker_error(shProg, "Out of memory during linking.\n");
+ goto write_top_level_array_size_and_stride;
+ }
}
for (unsigned i = 0; i < shProg->NumShaders; i++) {
@@ -3630,61 +3636,26 @@ calculate_array_stride(struct gl_shader_program *shProg,
const glsl_type *interface = var->get_interface_type();
- if (strcmp(interface_name, interface->name) != 0) {
+ 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;
+
+ array_stride = get_array_stride(uni, interface, field,
+ interface_name, var_name);
+ array_size = get_array_size(uni, field, interface_name, var_name);
+ goto write_top_level_array_size_and_stride;
}
}
}
-found_top_level_array_stride:
+write_top_level_array_size_and_stride:
free(interface_name);
free(var_name);
uni->top_level_array_stride = array_stride;
+ uni->top_level_array_size = array_size;
}
/**
@@ -3775,8 +3746,7 @@ build_program_resource_list(struct gl_shader_program *shProg)
continue;
if (is_shader_storage) {
- calculate_array_size(shProg, &shProg->UniformStorage[i]);
- calculate_array_stride(shProg, &shProg->UniformStorage[i]);
+ calculate_array_size_and_stride(shProg, &shProg->UniformStorage[i]);
}
if (!add_program_resource(shProg, type,