Browse Source

glsl linker: compare interface blocks during interstage linking

Verify that interface blocks match when linking separate shader
stages into a program.

Fixes piglit glsl-1.50 tests:
* linker/interface-blocks-vs-fs-member-count-mismatch.shader_test
* linker/interface-blocks-vs-fs-member-order-mismatch.shader_test

Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Signed-off-by: Jordan Justen <jordan.l.justen@intel.com>
tags/mesa-9.2-rc1
Kenneth Graunke 12 years ago
parent
commit
3ddfccb303
3 changed files with 49 additions and 0 deletions
  1. 39
    0
      src/glsl/link_interface_blocks.cpp
  2. 6
    0
      src/glsl/linker.cpp
  3. 4
    0
      src/glsl/linker.h

+ 39
- 0
src/glsl/link_interface_blocks.cpp View File

@@ -69,3 +69,42 @@ validate_intrastage_interface_blocks(const gl_shader **shader_list,

return true;
}

bool
validate_interstage_interface_blocks(const gl_shader *producer,
const gl_shader *consumer)
{
glsl_symbol_table interfaces;

/* Add non-output interfaces from the consumer to the symbol table. */
foreach_list(node, consumer->ir) {
ir_variable *var = ((ir_instruction *) node)->as_variable();
if (!var || !var->interface_type || var->mode == ir_var_shader_out)
continue;

interfaces.add_interface(var->interface_type->name,
var->interface_type,
(enum ir_variable_mode) var->mode);
}

/* Verify that the producer's interfaces match. */
foreach_list(node, producer->ir) {
ir_variable *var = ((ir_instruction *) node)->as_variable();
if (!var || !var->interface_type || var->mode == ir_var_shader_in)
continue;

enum ir_variable_mode consumer_mode =
var->mode == ir_var_uniform ? ir_var_uniform : ir_var_shader_in;
const glsl_type *expected_type =
interfaces.get_interface(var->interface_type->name, consumer_mode);

/* The consumer doesn't use this output block. Ignore it. */
if (expected_type == NULL)
continue;

if (var->interface_type != expected_type)
return false;
}

return true;
}

+ 6
- 0
src/glsl/linker.cpp View File

@@ -1728,6 +1728,12 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
if (prog->_LinkedShaders[i] == NULL)
continue;

if (!validate_interstage_interface_blocks(prog->_LinkedShaders[prev],
prog->_LinkedShaders[i])) {
linker_error(prog, "interface block mismatch between shader stages\n");
goto done;
}

if (!cross_validate_outputs_to_inputs(prog,
prog->_LinkedShaders[prev],
prog->_LinkedShaders[i]))

+ 4
- 0
src/glsl/linker.h View File

@@ -64,6 +64,10 @@ bool
validate_intrastage_interface_blocks(const gl_shader **shader_list,
unsigned num_shaders);

bool
validate_interstage_interface_blocks(const gl_shader *producer,
const gl_shader *consumer);

/**
* Class for processing all of the leaf fields of a variable that corresponds
* to a program resource.

Loading…
Cancel
Save