glsl: Modify ir_set_program_inouts to handle geometry shaders.

Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
This commit is contained in:
Paul Berry 2013-07-31 12:49:49 -07:00
parent cea946e39d
commit 8fc41df549

View file

@ -114,7 +114,13 @@ mark(struct gl_program *prog, ir_variable *var, int offset, int len,
void
ir_set_program_inouts_visitor::mark_whole_variable(ir_variable *var)
{
mark(this->prog, var, 0, var->type->count_attribute_slots(),
const glsl_type *type = var->type;
if (this->shader_type == GL_GEOMETRY_SHADER &&
var->mode == ir_var_shader_in && type->is_array()) {
type = type->fields.array;
}
mark(this->prog, var, 0, type->count_attribute_slots(),
this->shader_type == GL_FRAGMENT_SHADER);
}
@ -133,7 +139,11 @@ ir_set_program_inouts_visitor::visit(ir_dereference_variable *ir)
/**
* Try to mark a portion of the given variable as used. Caller must ensure
* that the variable represents a shader input or output which can be indexed
* into in array fashion (an array or matrix).
* into in array fashion (an array or matrix). For the purpose of geometry
* shader inputs (which are always arrays*), this means that the array element
* must be something that can be indexed into in array fashion.
*
* *Except gl_PrimitiveIDIn, as noted below.
*
* If the index can't be interpreted as a constant, or some other problem
* occurs, then nothing will be marked and false will be returned.
@ -144,6 +154,16 @@ ir_set_program_inouts_visitor::try_mark_partial_variable(ir_variable *var,
{
const glsl_type *type = var->type;
if (this->shader_type == GL_GEOMETRY_SHADER &&
var->mode == ir_var_shader_in) {
/* The only geometry shader input that is not an array is
* gl_PrimitiveIDIn, and in that case, this code will never be reached,
* because gl_PrimitiveIDIn can't be indexed into in array fashion.
*/
assert(type->is_array());
type = type->fields.array;
}
/* The code below only handles:
*
* - Indexing into matrices
@ -205,17 +225,60 @@ ir_set_program_inouts_visitor::try_mark_partial_variable(ir_variable *var,
ir_visitor_status
ir_set_program_inouts_visitor::visit_enter(ir_dereference_array *ir)
{
ir_dereference_variable *deref_var;
deref_var = ir->array->as_dereference_variable();
ir_variable *var = deref_var ? deref_var->var : NULL;
/* Check that we're dereferencing a shader in or out */
if (!var || !is_shader_inout(var))
return visit_continue;
if (try_mark_partial_variable(var, ir->array_index))
return visit_continue_with_parent;
/* Note: for geometry shader inputs, lower_named_interface_blocks may
* create 2D arrays, so we need to be able to handle those. 2D arrays
* shouldn't be able to crop up for any other reason.
*/
if (ir_dereference_array * const inner_array =
ir->array->as_dereference_array()) {
/* ir => foo[i][j]
* inner_array => foo[i]
*/
if (ir_dereference_variable * const deref_var =
inner_array->as_dereference_variable()) {
if (this->shader_type == GL_GEOMETRY_SHADER &&
deref_var->var->mode == ir_var_shader_in) {
/* foo is a geometry shader input, so i is the vertex, and j the
* part of the input we're accessing.
*/
if (try_mark_partial_variable(deref_var->var, ir->array_index))
{
/* We've now taken care of foo and j, but i might contain a
* subexpression that accesses shader inputs. So manually
* visit i and then continue with the parent.
*/
inner_array->array_index->accept(this);
return visit_continue_with_parent;
}
}
}
} else if (ir_dereference_variable * const deref_var =
ir->as_dereference_variable()) {
/* ir => foo[i], where foo is a variable. */
if (this->shader_type == GL_GEOMETRY_SHADER &&
deref_var->var->mode == ir_var_shader_in) {
/* foo is a geometry shader input, so i is the vertex, and we're
* accessing the entire input.
*/
mark_whole_variable(deref_var->var);
/* We've now taken care of foo, but i might contain a subexpression
* that accesses shader inputs. So manually visit i and then
* continue with the parent.
*/
ir->array_index->accept(this);
return visit_continue_with_parent;
} else if (is_shader_inout(deref_var->var)) {
/* foo is a shader input/output, but not a geometry shader input,
* so i is the part of the input we're accessing.
*/
if (try_mark_partial_variable(deref_var->var, ir->array_index))
return visit_continue_with_parent;
}
}
/* The expression is something we don't recognize. Just visit its
* subexpressions.
*/
return visit_continue;
}