summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSamuel Iglesias Gonsalvez <[email protected]>2015-09-16 15:47:34 +0200
committerSamuel Iglesias Gonsalvez <[email protected]>2015-09-30 08:13:07 +0200
commitf24e5e68d6bd640da2d9a3ae1cf7898ef9ed2fce (patch)
tree851033e631259c67d9b80b5d34bee4e152fb8d7b /src
parent4810d02112b7d056d5355ec9fd8953a4e763fd26 (diff)
glsl: apply shader storage block member rules when adding program resources
From ARB_program_interface_query: "For an active shader storage block member declared as an array, an entry will be generated only for the first array element, regardless of its type. For arrays of aggregate types, the enumeration rules are applied recursively for the single enumerated array element." v2: - Simplify 'if' conditions and return true if it is not a buffer variable, because these rules only apply to buffer variables (Timothy). Signed-off-by: Samuel Iglesias Gonsalvez <[email protected]> Reviewed-by: Timothy Arceri <[email protected]>
Diffstat (limited to 'src')
-rw-r--r--src/glsl/linker.cpp58
1 files changed, 58 insertions, 0 deletions
diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp
index 87c7d4b087b..dbf300ac691 100644
--- a/src/glsl/linker.cpp
+++ b/src/glsl/linker.cpp
@@ -3134,6 +3134,60 @@ check_explicit_uniform_locations(struct gl_context *ctx,
}
static bool
+should_add_buffer_variable(struct gl_shader_program *shProg,
+ GLenum type, const char *name)
+{
+ bool found_interface = false;
+ const char *block_name = NULL;
+
+ /* These rules only apply to buffer variables. So we return
+ * true for the rest of types.
+ */
+ if (type != GL_BUFFER_VARIABLE)
+ return true;
+
+ for (unsigned i = 0; i < shProg->NumBufferInterfaceBlocks; i++) {
+ block_name = shProg->UniformBlocks[i].Name;
+ if (strncmp(block_name, name, strlen(block_name)) == 0) {
+ found_interface = true;
+ break;
+ }
+ }
+
+ /* We remove the interface name from the buffer variable name,
+ * including the dot that follows it.
+ */
+ if (found_interface)
+ name = name + strlen(block_name) + 1;
+
+ /* From: ARB_program_interface_query extension:
+ *
+ * "For an active shader storage block member declared as an array, an
+ * entry will be generated only for the first array element, regardless
+ * of its type. For arrays of aggregate types, the enumeration rules are
+ * applied recursively for the single enumerated array element.
+ */
+ const char *first_dot = strchr(name, '.');
+ const char *first_square_bracket = strchr(name, '[');
+
+ /* The buffer variable is on top level and it is not an array */
+ if (!first_square_bracket) {
+ return true;
+ /* The shader storage block member is a struct, then generate the entry */
+ } else if (first_dot && first_dot < first_square_bracket) {
+ return true;
+ } else {
+ /* Shader storage block member is an array, only generate an entry for the
+ * first array element.
+ */
+ if (strncmp(first_square_bracket, "[0]", 3) == 0)
+ return true;
+ }
+
+ return false;
+}
+
+static bool
add_program_resource(struct gl_shader_program *prog, GLenum type,
const void *data, uint8_t stages)
{
@@ -3412,6 +3466,10 @@ build_program_resource_list(struct gl_shader_program *shProg)
bool is_shader_storage = shProg->UniformStorage[i].is_shader_storage;
GLenum type = is_shader_storage ? GL_BUFFER_VARIABLE : GL_UNIFORM;
+ if (!should_add_buffer_variable(shProg, type,
+ shProg->UniformStorage[i].name))
+ continue;
+
if (!add_program_resource(shProg, type,
&shProg->UniformStorage[i], stageref))
return;