Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

glsl: add parser support for two-dimensional arrays in geometry shaders

Also fixes various things related to 2D arrays, so they are working fully
now.
  • Loading branch information...
commit 7f7f7869ea44d68437919ad01ee7eadfa21081cf 1 parent aa9706b
@Plombo authored
View
5 src/glsl/ast.h
@@ -319,12 +319,17 @@ class ast_declaration : public ast_node {
public:
ast_declaration(const char *identifier, int is_array, ast_expression *array_size,
ast_expression *initializer);
+ ast_declaration(const char *identifier, int is_array, ast_expression *array_size,
+ int is_2D_array, ast_expression *outer_array_size,
+ ast_expression *initializer);
virtual void print(void) const;
const char *identifier;
int is_array;
ast_expression *array_size;
+ int is_2D_array;
+ ast_expression *outer_array_size;
ast_expression *initializer;
};
View
22 src/glsl/ast_to_hir.cpp
@@ -1619,7 +1619,7 @@ ast_expression::hir(exec_list *instructions,
* FINISHME: array access limits be added to ir_dereference?
*/
ir_variable *const v = array->whole_variable_referenced();
- if ((v != NULL) && (unsigned(idx) > v->max_array_access)) {
+ if ((v != NULL) && (idx > v->max_array_access)) {
v->max_array_access = idx;
/* Check whether this access will, as a side effect, implicitly
@@ -1629,7 +1629,11 @@ ast_expression::hir(exec_list *instructions,
error_emitted = true;
}
}
- } else if (array->type->array_size() == 0) {
+ } else if (array->type->array_size() == 0 &&
+ !(state->ARB_geometry_shader4_enable &&
+ !array->type->element_type()->is_array() &&
+ (array->ir_type != ir_type_dereference_variable ||
+ ((ir_dereference_variable*)array)->var->mode == ir_var_in))){
_mesa_glsl_error(&loc, state, "unsized array index must be constant");
} else {
if (array->type->is_array()) {
@@ -1843,7 +1847,7 @@ process_array_type(YYLTYPE *loc, const glsl_type *base, ast_node *array_size,
*
* "Only one-dimensional arrays may be declared."
*/
- if (base->is_array()) {
+ if (base->is_array() && !state->ARB_geometry_shader4_enable) {
_mesa_glsl_error(loc, state,
"invalid array of `%s' (only one-dimensional arrays "
"may be declared)",
@@ -1955,9 +1959,12 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
if (qual->flags.q.varying) {
const glsl_type *non_array_type;
- if (var->type && var->type->is_array())
+ if (var->type && var->type->is_array()) {
non_array_type = var->type->fields.array;
- else
+ if (non_array_type && non_array_type->is_array() &&
+ state->ARB_geometry_shader4_enable)
+ non_array_type = non_array_type->fields.array;
+ } else
non_array_type = var->type;
if (non_array_type && non_array_type->base_type != GLSL_TYPE_FLOAT) {
@@ -2238,7 +2245,7 @@ get_variable_being_redeclared(ir_variable *var, ast_declaration *decl,
* FINISHME: required or not.
*/
- const unsigned size = unsigned(var->type->array_size());
+ const int size = var->type->array_size();
check_builtin_array_max_size(var->name, size, loc, state);
if ((size > 0) && (size <= earlier->max_array_access)) {
_mesa_glsl_error(& loc, state, "array size must be > %u due to "
@@ -2573,6 +2580,9 @@ ast_declarator_list::hir(exec_list *instructions,
if (decl->is_array) {
var_type = process_array_type(&loc, decl_type, decl->array_size,
state);
+ if (decl->is_2D_array)
+ var_type = process_array_type(&loc, var_type, decl->outer_array_size,
+ state);
if (var_type->is_error())
continue;
} else {
View
4 src/glsl/builtin_variables.cpp
@@ -1089,11 +1089,11 @@ initialize_gs_variables(exec_list *instructions,
/* For the input arrays with size gl_VerticesIn (injected at link time),
* set the size to a nonzero value temporarily to allow indirect addressing.
*/
- vec4_array_type = glsl_type::get_array_instance(glsl_type::vec4_type, 6);
+ vec4_array_type = glsl_type::get_array_instance(glsl_type::vec4_type, 0);
const glsl_type *const vec4_2D_array_type =
glsl_type::get_array_instance(vec4_array_type, 0);
const glsl_type *const float_array_type =
- glsl_type::get_array_instance(glsl_type::float_type, 6);
+ glsl_type::get_array_instance(glsl_type::float_type, 0);
const glsl_type *const float_2D_array_type =
glsl_type::get_array_instance(float_array_type, 0);
View
38 src/glsl/glsl_parser.yy
@@ -965,6 +965,26 @@ init_declarator_list:
$$->declarations.push_tail(&decl->link);
state->symbols->add_variable(new(state) ir_variable(NULL, $3, ir_var_auto));
}
+ | init_declarator_list ',' any_identifier '[' ']' '[' constant_expression ']'
+ { // Geometry (EXT/ARB) only
+ void *ctx = state;
+ ast_declaration *decl = new(ctx) ast_declaration($3, true, NULL, true, $7, NULL);
+ decl->set_location(yylloc);
+
+ $$ = $1;
+ $$->declarations.push_tail(&decl->link);
+ state->symbols->add_variable(new(state) ir_variable(NULL, $3, ir_var_auto));
+ }
+ | init_declarator_list ',' any_identifier '[' constant_expression ']' '[' constant_expression ']'
+ { // Geometry (EXT/ARB) only
+ void *ctx = state;
+ ast_declaration *decl = new(ctx) ast_declaration($3, true, $5, true, $8, NULL);
+ decl->set_location(yylloc);
+
+ $$ = $1;
+ $$->declarations.push_tail(&decl->link);
+ state->symbols->add_variable(new(state) ir_variable(NULL, $3, ir_var_auto));
+ }
| init_declarator_list ',' any_identifier '[' ']' '=' initializer
{
void *ctx = state;
@@ -1033,6 +1053,24 @@ single_declaration:
$$->set_location(yylloc);
$$->declarations.push_tail(&decl->link);
}
+ | fully_specified_type any_identifier '[' ']' '[' constant_expression ']'
+ { // Geometry (EXT/ARB) only
+ void *ctx = state;
+ ast_declaration *decl = new(ctx) ast_declaration($2, true, NULL, true, $6, NULL);
+
+ $$ = new(ctx) ast_declarator_list($1);
+ $$->set_location(yylloc);
+ $$->declarations.push_tail(&decl->link);
+ }
+ | fully_specified_type any_identifier '[' constant_expression ']' '[' constant_expression ']'
+ { // Geometry (EXT/ARB) only
+ void *ctx = state;
+ ast_declaration *decl = new(ctx) ast_declaration($2, true, $4, true, $7, NULL);
+
+ $$ = new(ctx) ast_declarator_list($1);
+ $$->set_location(yylloc);
+ $$->declarations.push_tail(&decl->link);
+ }
| fully_specified_type any_identifier '[' ']' '=' initializer
{
void *ctx = state;
View
17 src/glsl/glsl_parser_extras.cpp
@@ -749,6 +749,23 @@ ast_declaration::ast_declaration(const char *identifier, int is_array,
this->identifier = identifier;
this->is_array = is_array;
this->array_size = array_size;
+ this->is_2D_array = false;
+ this->outer_array_size = NULL;
+ this->initializer = initializer;
+}
+
+
+ast_declaration::ast_declaration(const char *identifier, int is_array,
+ ast_expression *array_size,
+ int is_2D_array,
+ ast_expression *outer_array_size,
+ ast_expression *initializer)
+{
+ this->identifier = identifier;
+ this->is_array = is_array;
+ this->array_size = array_size;
+ this->is_2D_array = is_2D_array;
+ this->outer_array_size = outer_array_size;
this->initializer = initializer;
}
View
4 src/glsl/ir.h
@@ -364,7 +364,7 @@ class ir_variable : public ir_instruction {
*
* Not used for non-array variables.
*/
- unsigned max_array_access;
+ int max_array_access;
/**
* Is the variable read-only?
@@ -453,6 +453,8 @@ class ir_variable : public ir_instruction {
*
* - Vertex shader input: one of the values from \c gl_vert_attrib.
* - Vertex shader output: one of the values from \c gl_vert_result.
+ * - Geometry shader input: one of the values from \c gl_geom_attrib.
+ * - Geometry shader output: one of the values from \c gl_geom_result.
* - Fragment shader input: one of the values from \c gl_frag_attrib.
* - Fragment shader output: one of the values from \c gl_frag_result.
* - Uniforms: Per-stage uniform slot number.
View
22 src/glsl/ir_set_program_inouts.cpp
@@ -110,9 +110,16 @@ ir_set_program_inouts_visitor::visit(ir_dereference_variable *ir)
if (hash_table_find(this->ht, ir->var) == NULL)
return visit_continue;
- if (ir->type->is_array() && !this->is_geometry_shader) {
- mark(this->prog, ir->var, 0,
- ir->type->length * ir->type->fields.array->matrix_columns,
+ bool is_2D_register = this->is_geometry_shader &&
+ ir->var->mode == ir_var_in &&
+ ir->type->is_array() &&
+ !ir->type->element_type()->is_array();
+
+ if (ir->type->is_array() && !is_2D_register) {
+ int matrix_columns = ir->type->fields.array->matrix_columns;
+ if (this->is_geometry_shader && ir->var->mode == ir_var_in)
+ matrix_columns = ir->type->fields.array->fields.array->matrix_columns;
+ mark(this->prog, ir->var, 0, ir->type->length * matrix_columns,
this->is_fragment_shader);
} else {
mark(this->prog, ir->var, 0, ir->type->matrix_columns,
@@ -129,11 +136,18 @@ ir_set_program_inouts_visitor::visit_enter(ir_dereference_array *ir)
ir_constant *index = ir->array_index->as_constant();
deref_var = ir->array->as_dereference_variable();
ir_variable *var = NULL;
+ bool is_2D_input;
/* Check that we're dereferencing a shader in or out */
if (deref_var)
var = (ir_variable *)hash_table_find(this->ht, deref_var->var);
+ /* Check whether this dereference is of a GS input array (2D register) */
+ is_2D_input = this->is_geometry_shader &&
+ !ir->type->is_array() &&
+ (ir->array->ir_type == ir_type_dereference_array ||
+ (deref_var && deref_var->var->mode == ir_var_in));
+
if (index && var) {
int width = 1;
@@ -142,7 +156,7 @@ ir_set_program_inouts_visitor::visit_enter(ir_dereference_array *ir)
width = deref_var->type->fields.array->matrix_columns;
}
- if (this->is_geometry_shader)
+ if (is_2D_input)
mark(this->prog, var, 0, 1, this->is_fragment_shader);
else
mark(this->prog, var, index->value.i[0] * width, width,
View
2  src/glsl/ir_validate.cpp
@@ -508,7 +508,7 @@ ir_validate::visit(ir_variable *ir)
* to be out of bounds.
*/
if (ir->type->array_size() > 0) {
- if (ir->max_array_access >= ir->type->length) {
+ if (ir->max_array_access >= int(ir->type->length)) {
printf("ir_variable has maximum access out of bounds (%d vs %d)\n",
ir->max_array_access, ir->type->length - 1);
ir->print();
View
51 src/glsl/linker.cpp
@@ -198,7 +198,7 @@ class inject_num_vertices_visitor : public ir_rvalue_visitor {
};
-class geom_array_resize_visitor : public ir_visitor {
+class geom_array_resize_visitor : public ir_hierarchical_visitor {
public:
int num_vertices;
@@ -212,28 +212,10 @@ class geom_array_resize_visitor : public ir_visitor {
/* empty */
}
- void visit(ir_function_signature *) {}
- void visit(ir_function *) {}
- void visit(ir_expression *) {}
- void visit(ir_texture *) {}
- void visit(ir_swizzle *) {}
- void visit(ir_dereference_variable *) {};
- void visit(ir_dereference_array *) {};
- void visit(ir_dereference_record *) {};
- void visit(ir_assignment *) {};
- void visit(ir_constant *) {};
- void visit(ir_call *) {};
- void visit(ir_return *) {};
- void visit(ir_discard *) {};
- void visit(ir_if *) {};
- void visit(ir_loop *) {};
- void visit(ir_loop_jump *) {};
- void visit(ir_emitvertex *) {};
- void visit(ir_endprim *) {};
-
- void visit(ir_variable *var)
+ virtual ir_visitor_status visit(ir_variable *var)
{
- if (!var->type->is_array() || var->mode != ir_var_in) return;
+ if (!var->type->is_array() || var->mode != ir_var_in)
+ return visit_continue;
if (var->type->element_type()->is_array()) {
const glsl_type *inner_type = glsl_type::get_array_instance(
@@ -244,6 +226,7 @@ class geom_array_resize_visitor : public ir_visitor {
} else {
var->type = glsl_type::get_array_instance(var->type->element_type(),
this->num_vertices);
+ var->max_array_access = this->num_vertices - 1;
/* XXX: This should be a link error, but a hack in the builtin variable
* generation sets the size of the per-vertex input arrays for
@@ -257,6 +240,26 @@ class geom_array_resize_visitor : public ir_visitor {
if ((int) var->max_array_access >= this->num_vertices)
var->max_array_access = this->num_vertices - 1;
}
+
+ return visit_continue;
+ }
+
+ /* Dereferences of input variables need to be updated so that their type
+ * matches the newly assigned type of the variable they are accessing. */
+ virtual ir_visitor_status visit(ir_dereference_variable *ir)
+ {
+ ir->type = ir->var->type;
+ return visit_continue;
+ }
+
+ /* Dereferences of 2D input arrays need to be updated so that their type
+ * matches the newly assigned type of the array they are accessing. */
+ virtual ir_visitor_status visit_leave(ir_dereference_array *ir)
+ {
+ const glsl_type *const vt = ir->array->type;
+ if (vt->is_array())
+ ir->type = vt->element_type();
+ return visit_continue;
}
};
@@ -1285,7 +1288,7 @@ update_array_sizes(struct gl_shader_program *prog)
!var->type->is_array())
continue;
- unsigned int size = var->max_array_access;
+ int size = var->max_array_access;
for (unsigned j = 0; j < MESA_SHADER_TYPES; j++) {
if (prog->_LinkedShaders[j] == NULL)
continue;
@@ -1302,7 +1305,7 @@ update_array_sizes(struct gl_shader_program *prog)
}
}
- if (size + 1 != var->type->fields.array->length) {
+ if (size + 1 != int(var->type->fields.array->length)) {
/* If this is a built-in uniform (i.e., it's backed by some
* fixed-function state), adjust the number of state slots to
* match the new array size. The number of slots per array entry
View
5 src/mesa/state_tracker/st_glsl_to_tgsi.cpp
@@ -2006,7 +2006,10 @@ glsl_to_tgsi_visitor::visit(ir_dereference_array *ir)
src = this->result;
is_2D_input = this->prog->Target == GL_GEOMETRY_PROGRAM_NV &&
- src.file == PROGRAM_INPUT;
+ src.file == PROGRAM_INPUT && !ir->type->is_array();
+
+ if (this->prog->Target == GL_GEOMETRY_PROGRAM_NV && ir->type->is_array())
+ element_size = 1;
if (index) {
if (is_2D_input) {
Please sign in to comment.
Something went wrong with that request. Please try again.