summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2016-05-17 14:44:47 +1000
committerDave Airlie <airlied@redhat.com>2016-05-23 16:19:57 +1000
commit6f2dc0d04498a1d03f02a4b72480e8b409981432 (patch)
tree339b4212c25e8e523318fecb423af168056b38ff
parent5fe912831cac6722f2cf8add010c553a43e178b4 (diff)
subroutines: handle explicit indexes properly
The code didn't deal with explicit function indexes properly. It also handed out the indexes at link time, when we really need them in the lowering pass to create the correct if ladder. So this patch moves assigning the non-explicit indexes earlier, fixes the lowering pass and the lookups to get the correct values. This fixes a few of: GL45-CTS.explicit_uniform_location.subroutine-index-* Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r--src/compiler/glsl/glsl_parser_extras.cpp22
-rw-r--r--src/compiler/glsl/linker.cpp20
-rw-r--r--src/compiler/glsl/lower_subroutine.cpp3
-rw-r--r--src/mesa/main/mtypes.h1
-rw-r--r--src/mesa/main/shaderapi.c16
5 files changed, 43 insertions, 19 deletions
diff --git a/src/compiler/glsl/glsl_parser_extras.cpp b/src/compiler/glsl/glsl_parser_extras.cpp
index 771fd19722..1d0110b077 100644
--- a/src/compiler/glsl/glsl_parser_extras.cpp
+++ b/src/compiler/glsl/glsl_parser_extras.cpp
@@ -1755,6 +1755,27 @@ set_shader_inout_layout(struct gl_shader *shader,
extern "C" {
+static void
+assign_subroutine_indexes(struct gl_shader *sh,
+ struct _mesa_glsl_parse_state *state)
+{
+ int j, k;
+ int index = 0;
+
+ for (j = 0; j < state->num_subroutines; j++) {
+ while (state->subroutines[j]->subroutine_index == -1) {
+ for (k = 0; k < state->num_subroutines; k++) {
+ if (state->subroutines[k]->subroutine_index == index)
+ break;
+ else if (k == state->num_subroutines - 1) {
+ state->subroutines[j]->subroutine_index = index;
+ }
+ }
+ index++;
+ }
+ }
+}
+
void
_mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *shader,
bool dump_ast, bool dump_hir)
@@ -1802,6 +1823,7 @@ _mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *shader,
struct gl_shader_compiler_options *options =
&ctx->Const.ShaderCompilerOptions[shader->Stage];
+ assign_subroutine_indexes(shader, state);
lower_subroutine(shader->ir, state);
/* Do some optimization at compile time to reduce shader IR size
* and reduce later work if the same shader is linked multiple times
diff --git a/src/compiler/glsl/linker.cpp b/src/compiler/glsl/linker.cpp
index a7b2a19a66..0b8c494369 100644
--- a/src/compiler/glsl/linker.cpp
+++ b/src/compiler/glsl/linker.cpp
@@ -4222,6 +4222,7 @@ link_assign_subroutine_types(struct gl_shader_program *prog)
if (sh == NULL)
continue;
+ sh->MaxSubroutineFunctionIndex = 0;
foreach_in_list(ir_instruction, node, sh->ir) {
ir_function *fn = node->as_function();
if (!fn)
@@ -4233,6 +4234,8 @@ link_assign_subroutine_types(struct gl_shader_program *prog)
if (!fn->num_subroutine_types)
continue;
+ /* these should have been calculated earlier. */
+ assert(fn->subroutine_index != -1);
if (sh->NumSubroutineFunctions + 1 > MAX_SUBROUTINES) {
linker_error(prog, "Too many subroutine functions declared.\n");
return;
@@ -4264,24 +4267,13 @@ link_assign_subroutine_types(struct gl_shader_program *prog)
sh->SubroutineFunctions[sh->NumSubroutineFunctions].index =
fn->subroutine_index;
+ if (fn->subroutine_index > (int)sh->MaxSubroutineFunctionIndex)
+ sh->MaxSubroutineFunctionIndex = fn->subroutine_index;
+
for (int j = 0; j < fn->num_subroutine_types; j++)
sh->SubroutineFunctions[sh->NumSubroutineFunctions].types[j] = fn->subroutine_types[j];
sh->NumSubroutineFunctions++;
}
-
- /* Assign index for subroutines without an explicit index*/
- int index = 0;
- for (unsigned j = 0; j < sh->NumSubroutineFunctions; j++) {
- while (sh->SubroutineFunctions[j].index == -1) {
- for (unsigned k = 0; k < sh->NumSubroutineFunctions; k++) {
- if (sh->SubroutineFunctions[k].index == index)
- break;
- else if (k == sh->NumSubroutineFunctions - 1)
- sh->SubroutineFunctions[j].index = index;
- }
- index++;
- }
- }
}
}
diff --git a/src/compiler/glsl/lower_subroutine.cpp b/src/compiler/glsl/lower_subroutine.cpp
index e80c1be768..de178a59b0 100644
--- a/src/compiler/glsl/lower_subroutine.cpp
+++ b/src/compiler/glsl/lower_subroutine.cpp
@@ -87,8 +87,9 @@ lower_subroutine_visitor::visit_leave(ir_call *ir)
for (int s = this->state->num_subroutines - 1; s >= 0; s--) {
ir_rvalue *var;
- ir_constant *lc = new(mem_ctx)ir_constant(s);
ir_function *fn = this->state->subroutines[s];
+ ir_constant *lc = new(mem_ctx)ir_constant(fn->subroutine_index);
+
bool is_compat = false;
for (int i = 0; i < fn->num_subroutine_types; i++) {
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 05b2059036..f6c6d9733e 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -2445,6 +2445,7 @@ struct gl_shader
* and storage for them.
*/
GLuint NumSubroutineFunctions;
+ GLuint MaxSubroutineFunctionIndex;
struct gl_subroutine_function *SubroutineFunctions;
};
diff --git a/src/mesa/main/shaderapi.c b/src/mesa/main/shaderapi.c
index 6d58fbb492..167e06f3d4 100644
--- a/src/mesa/main/shaderapi.c
+++ b/src/mesa/main/shaderapi.c
@@ -2546,16 +2546,24 @@ _mesa_UniformSubroutinesuiv(GLenum shadertype, GLsizei count,
}
int uni_count = uni->array_elements ? uni->array_elements : 1;
- int j, k;
+ int j, k, f;
for (j = i; j < i + uni_count; j++) {
- struct gl_subroutine_function *subfn;
- if (indices[j] >= sh->NumSubroutineFunctions) {
+ struct gl_subroutine_function *subfn = NULL;
+ if (indices[j] > sh->MaxSubroutineFunctionIndex) {
_mesa_error(ctx, GL_INVALID_VALUE, "%s", api_name);
return;
}
- subfn = &sh->SubroutineFunctions[indices[j]];
+ for (f = 0; f < sh->NumSubroutineFunctions; f++) {
+ if (sh->SubroutineFunctions[f].index == indices[j])
+ subfn = &sh->SubroutineFunctions[f];
+ }
+
+ if (!subfn) {
+ continue;
+ }
+
for (k = 0; k < subfn->num_compat_types; k++) {
if (subfn->types[k] == uni->type)
break;