summaryrefslogtreecommitdiffstats
path: root/src/compiler/glsl
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/glsl')
-rw-r--r--src/compiler/glsl/link_varyings.cpp43
-rw-r--r--src/compiler/glsl/link_varyings.h3
-rw-r--r--src/compiler/glsl/linker.cpp2
3 files changed, 43 insertions, 5 deletions
diff --git a/src/compiler/glsl/link_varyings.cpp b/src/compiler/glsl/link_varyings.cpp
index 29842ecacda..69c92bf53b0 100644
--- a/src/compiler/glsl/link_varyings.cpp
+++ b/src/compiler/glsl/link_varyings.cpp
@@ -377,11 +377,38 @@ cross_validate_front_and_back_color(struct gl_shader_program *prog,
consumer_stage, producer_stage);
}
+static unsigned
+compute_variable_location_slot(ir_variable *var, gl_shader_stage stage)
+{
+ unsigned location_start = VARYING_SLOT_VAR0;
+
+ switch (stage) {
+ case MESA_SHADER_VERTEX:
+ if (var->data.mode == ir_var_shader_in)
+ location_start = VERT_ATTRIB_GENERIC0;
+ break;
+ case MESA_SHADER_TESS_CTRL:
+ case MESA_SHADER_TESS_EVAL:
+ if (var->data.patch)
+ location_start = VARYING_SLOT_PATCH0;
+ break;
+ case MESA_SHADER_FRAGMENT:
+ if (var->data.mode == ir_var_shader_out)
+ location_start = FRAG_RESULT_DATA0;
+ break;
+ default:
+ break;
+ }
+
+ return var->data.location - location_start;
+}
+
/**
* Validate that outputs from one stage match inputs of another
*/
void
-cross_validate_outputs_to_inputs(struct gl_shader_program *prog,
+cross_validate_outputs_to_inputs(struct gl_context *ctx,
+ struct gl_shader_program *prog,
gl_linked_shader *producer,
gl_linked_shader *consumer)
{
@@ -406,10 +433,19 @@ cross_validate_outputs_to_inputs(struct gl_shader_program *prog,
*/
const glsl_type *type = get_varying_type(var, producer->Stage);
unsigned num_elements = type->count_attribute_slots(false);
- unsigned idx = var->data.location - VARYING_SLOT_VAR0;
+ unsigned idx = compute_variable_location_slot(var, producer->Stage);
unsigned slot_limit = idx + num_elements;
unsigned last_comp;
+ unsigned slot_max =
+ ctx->Const.Program[producer->Stage].MaxOutputComponents / 4;
+ if (slot_limit > slot_max) {
+ linker_error(prog,
+ "Invalid location %u in %s shader\n",
+ idx, _mesa_shader_stage_to_string(producer->Stage));
+ return;
+ }
+
if (type->without_array()->is_record()) {
/* The component qualifier can't be used on structs so just treat
* all component slots as used.
@@ -515,7 +551,8 @@ cross_validate_outputs_to_inputs(struct gl_shader_program *prog,
const glsl_type *type = get_varying_type(input, consumer->Stage);
unsigned num_elements = type->count_attribute_slots(false);
- unsigned idx = input->data.location - VARYING_SLOT_VAR0;
+ unsigned idx =
+ compute_variable_location_slot(input, consumer->Stage);
unsigned slot_limit = idx + num_elements;
while (idx < slot_limit) {
diff --git a/src/compiler/glsl/link_varyings.h b/src/compiler/glsl/link_varyings.h
index 4e1f6d2e42a..081b04ea38f 100644
--- a/src/compiler/glsl/link_varyings.h
+++ b/src/compiler/glsl/link_varyings.h
@@ -300,7 +300,8 @@ link_varyings(struct gl_shader_program *prog, unsigned first, unsigned last,
struct gl_context *ctx, void *mem_ctx);
void
-cross_validate_outputs_to_inputs(struct gl_shader_program *prog,
+cross_validate_outputs_to_inputs(struct gl_context *ctx,
+ struct gl_shader_program *prog,
gl_linked_shader *producer,
gl_linked_shader *consumer);
diff --git a/src/compiler/glsl/linker.cpp b/src/compiler/glsl/linker.cpp
index 03eb05bf637..37983096784 100644
--- a/src/compiler/glsl/linker.cpp
+++ b/src/compiler/glsl/linker.cpp
@@ -4929,7 +4929,7 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
if (!prog->data->LinkStatus)
goto done;
- cross_validate_outputs_to_inputs(prog,
+ cross_validate_outputs_to_inputs(ctx, prog,
prog->_LinkedShaders[prev],
prog->_LinkedShaders[i]);
if (!prog->data->LinkStatus)