diff options
Diffstat (limited to 'src/glsl')
-rw-r--r-- | src/glsl/ast_function.cpp | 6 | ||||
-rw-r--r-- | src/glsl/ast_to_hir.cpp | 217 | ||||
-rw-r--r-- | src/glsl/glcpp/glcpp-parse.y | 82 | ||||
-rw-r--r-- | src/glsl/glcpp/tests/084-unbalanced-parentheses.c.expected | 2 | ||||
-rw-r--r-- | src/glsl/glcpp/tests/093-divide-by-zero.c.expected | 4 | ||||
-rw-r--r-- | src/glsl/glcpp/tests/094-divide-by-zero-short-circuit.c | 11 | ||||
-rw-r--r-- | src/glsl/glcpp/tests/094-divide-by-zero-short-circuit.c.expected | 15 | ||||
-rw-r--r-- | src/glsl/glcpp/tests/095-recursive-define.c.expected | 4 | ||||
-rwxr-xr-x | src/glsl/glcpp/tests/glcpp-test | 62 | ||||
-rw-r--r-- | src/glsl/glsl_parser_extras.cpp | 27 | ||||
-rw-r--r-- | src/glsl/glsl_parser_extras.h | 4 | ||||
-rw-r--r-- | src/glsl/ir.h | 26 | ||||
-rw-r--r-- | src/glsl/ir_clone.cpp | 12 | ||||
-rw-r--r-- | src/glsl/ir_print_visitor.cpp | 45 | ||||
-rw-r--r-- | src/glsl/ir_print_visitor.h | 29 | ||||
-rw-r--r-- | src/glsl/ir_validate.cpp | 21 | ||||
-rw-r--r-- | src/glsl/ir_variable.cpp | 508 | ||||
-rw-r--r-- | src/glsl/linker.cpp | 13 | ||||
-rw-r--r-- | src/glsl/opt_copy_propagation_elements.cpp | 15 |
19 files changed, 803 insertions, 300 deletions
diff --git a/src/glsl/ast_function.cpp b/src/glsl/ast_function.cpp index e5cb8733952..67147b6718f 100644 --- a/src/glsl/ast_function.cpp +++ b/src/glsl/ast_function.cpp @@ -107,7 +107,11 @@ match_function_by_name(exec_list *instructions, const char *name, * FINISHME: matching signature but shader X + N contains an _exact_ * FINISHME: matching signature. */ - if (sig == NULL && (f == NULL || state->es_shader || !f->has_user_signature()) && state->symbols->get_type(name) == NULL && (state->language_version == 110 || state->symbols->get_variable(name) == NULL)) { + if (sig == NULL + && (f == NULL || state->es_shader || !f->has_user_signature()) + && state->symbols->get_type(name) == NULL + && (state->language_version == 110 + || state->symbols->get_variable(name) == NULL)) { /* The current shader doesn't contain a matching function or signature. * Before giving up, look for the prototype in the built-in functions. */ diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp index cdb16fd492b..3b87f0d56de 100644 --- a/src/glsl/ast_to_hir.cpp +++ b/src/glsl/ast_to_hir.cpp @@ -848,6 +848,36 @@ do_comparison(void *mem_ctx, int operation, ir_rvalue *op0, ir_rvalue *op1) return cmp; } +/* For logical operations, we want to ensure that the operands are + * scalar booleans. If it isn't, emit an error and return a constant + * boolean to avoid triggering cascading error messages. + */ +ir_rvalue * +get_scalar_boolean_operand(exec_list *instructions, + struct _mesa_glsl_parse_state *state, + ast_expression *parent_expr, + int operand, + const char *operand_name, + bool *error_emitted) +{ + ast_expression *expr = parent_expr->subexpressions[operand]; + void *ctx = state; + ir_rvalue *val = expr->hir(instructions, state); + + if (val->type->is_boolean() && val->type->is_scalar()) + return val; + + if (!*error_emitted) { + YYLTYPE loc = expr->get_location(); + _mesa_glsl_error(&loc, state, "%s of `%s' must be scalar boolean", + operand_name, + parent_expr->operator_string(parent_expr->oper)); + *error_emitted = true; + } + + return new(ctx) ir_constant(true); +} + ir_rvalue * ast_expression::hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) @@ -910,7 +940,7 @@ ast_expression::hir(exec_list *instructions, }; ir_rvalue *result = NULL; ir_rvalue *op[3]; - const struct glsl_type *type = glsl_type::error_type; + const struct glsl_type *type; /* a temporary variable for switch cases */ bool error_emitted = false; YYLTYPE loc; @@ -924,7 +954,6 @@ ast_expression::hir(exec_list *instructions, result = do_assignment(instructions, state, op[0], op[1], false, this->subexpressions[0]->get_location()); error_emitted = result->type->is_error(); - type = result->type; break; } @@ -1043,10 +1072,12 @@ ast_expression::hir(exec_list *instructions, error_emitted = true; } - result = do_comparison(ctx, operations[this->oper], op[0], op[1]); - type = glsl_type::bool_type; - - assert(error_emitted || (result->type == glsl_type::bool_type)); + if (error_emitted) { + result = new(ctx) ir_constant(false); + } else { + result = do_comparison(ctx, operations[this->oper], op[0], op[1]); + assert(result->type == glsl_type::bool_type); + } break; case ast_bit_and: @@ -1079,29 +1110,16 @@ ast_expression::hir(exec_list *instructions, break; case ast_logic_and: { - op[0] = this->subexpressions[0]->hir(instructions, state); - - if (!op[0]->type->is_boolean() || !op[0]->type->is_scalar()) { - YYLTYPE loc = this->subexpressions[0]->get_location(); - - _mesa_glsl_error(& loc, state, "LHS of `%s' must be scalar boolean", - operator_string(this->oper)); - error_emitted = true; - } + exec_list rhs_instructions; + op[0] = get_scalar_boolean_operand(instructions, state, this, 0, + "LHS", &error_emitted); + op[1] = get_scalar_boolean_operand(&rhs_instructions, state, this, 1, + "RHS", &error_emitted); ir_constant *op0_const = op[0]->constant_expression_value(); if (op0_const) { if (op0_const->value.b[0]) { - op[1] = this->subexpressions[1]->hir(instructions, state); - - if (!op[1]->type->is_boolean() || !op[1]->type->is_scalar()) { - YYLTYPE loc = this->subexpressions[1]->get_location(); - - _mesa_glsl_error(& loc, state, - "RHS of `%s' must be scalar boolean", - operator_string(this->oper)); - error_emitted = true; - } + instructions->append_list(&rhs_instructions); result = op[1]; } else { result = op0_const; @@ -1116,17 +1134,7 @@ ast_expression::hir(exec_list *instructions, ir_if *const stmt = new(ctx) ir_if(op[0]); instructions->push_tail(stmt); - op[1] = this->subexpressions[1]->hir(&stmt->then_instructions, state); - - if (!op[1]->type->is_boolean() || !op[1]->type->is_scalar()) { - YYLTYPE loc = this->subexpressions[1]->get_location(); - - _mesa_glsl_error(& loc, state, - "RHS of `%s' must be scalar boolean", - operator_string(this->oper)); - error_emitted = true; - } - + stmt->then_instructions.append_list(&rhs_instructions); ir_dereference *const then_deref = new(ctx) ir_dereference_variable(tmp); ir_assignment *const then_assign = new(ctx) ir_assignment(then_deref, op[1], NULL); @@ -1144,31 +1152,17 @@ ast_expression::hir(exec_list *instructions, } case ast_logic_or: { - op[0] = this->subexpressions[0]->hir(instructions, state); - - if (!op[0]->type->is_boolean() || !op[0]->type->is_scalar()) { - YYLTYPE loc = this->subexpressions[0]->get_location(); - - _mesa_glsl_error(& loc, state, "LHS of `%s' must be scalar boolean", - operator_string(this->oper)); - error_emitted = true; - } + exec_list rhs_instructions; + op[0] = get_scalar_boolean_operand(instructions, state, this, 0, + "LHS", &error_emitted); + op[1] = get_scalar_boolean_operand(&rhs_instructions, state, this, 1, + "RHS", &error_emitted); ir_constant *op0_const = op[0]->constant_expression_value(); if (op0_const) { if (op0_const->value.b[0]) { result = op0_const; } else { - op[1] = this->subexpressions[1]->hir(instructions, state); - - if (!op[1]->type->is_boolean() || !op[1]->type->is_scalar()) { - YYLTYPE loc = this->subexpressions[1]->get_location(); - - _mesa_glsl_error(& loc, state, - "RHS of `%s' must be scalar boolean", - operator_string(this->oper)); - error_emitted = true; - } result = op[1]; } type = glsl_type::bool_type; @@ -1181,21 +1175,12 @@ ast_expression::hir(exec_list *instructions, ir_if *const stmt = new(ctx) ir_if(op[0]); instructions->push_tail(stmt); - op[1] = this->subexpressions[1]->hir(&stmt->else_instructions, state); - - if (!op[1]->type->is_boolean() || !op[1]->type->is_scalar()) { - YYLTYPE loc = this->subexpressions[1]->get_location(); - - _mesa_glsl_error(& loc, state, "RHS of `%s' must be scalar boolean", - operator_string(this->oper)); - error_emitted = true; - } - ir_dereference *const then_deref = new(ctx) ir_dereference_variable(tmp); ir_assignment *const then_assign = new(ctx) ir_assignment(then_deref, new(ctx) ir_constant(true), NULL); stmt->then_instructions.push_tail(then_assign); + stmt->else_instructions.append_list(&rhs_instructions); ir_dereference *const else_deref = new(ctx) ir_dereference_variable(tmp); ir_assignment *const else_assign = new(ctx) ir_assignment(else_deref, op[1], NULL); @@ -1208,29 +1193,27 @@ ast_expression::hir(exec_list *instructions, } case ast_logic_xor: - op[0] = this->subexpressions[0]->hir(instructions, state); - op[1] = this->subexpressions[1]->hir(instructions, state); - + /* From page 33 (page 39 of the PDF) of the GLSL 1.10 spec: + * + * "The logical binary operators and (&&), or ( | | ), and + * exclusive or (^^). They operate only on two Boolean + * expressions and result in a Boolean expression." + */ + op[0] = get_scalar_boolean_operand(instructions, state, this, 0, "LHS", + &error_emitted); + op[1] = get_scalar_boolean_operand(instructions, state, this, 1, "RHS", + &error_emitted); result = new(ctx) ir_expression(operations[this->oper], glsl_type::bool_type, op[0], op[1]); - type = glsl_type::bool_type; break; case ast_logic_not: - op[0] = this->subexpressions[0]->hir(instructions, state); - - if (!op[0]->type->is_boolean() || !op[0]->type->is_scalar()) { - YYLTYPE loc = this->subexpressions[0]->get_location(); - - _mesa_glsl_error(& loc, state, - "operand of `!' must be scalar boolean"); - error_emitted = true; - } + op[0] = get_scalar_boolean_operand(instructions, state, this, 0, + "operand", &error_emitted); result = new(ctx) ir_expression(operations[this->oper], glsl_type::bool_type, op[0], NULL); - type = glsl_type::bool_type; break; case ast_mul_assign: @@ -1250,7 +1233,6 @@ ast_expression::hir(exec_list *instructions, result = do_assignment(instructions, state, op[0]->clone(ctx, NULL), temp_rhs, false, this->subexpressions[0]->get_location()); - type = result->type; error_emitted = (op[0]->type->is_error()); /* GLSL 1.10 does not allow array assignment. However, we don't have to @@ -1276,7 +1258,6 @@ ast_expression::hir(exec_list *instructions, result = do_assignment(instructions, state, op[0]->clone(ctx, NULL), temp_rhs, false, this->subexpressions[0]->get_location()); - type = result->type; error_emitted = type->is_error(); break; } @@ -1313,20 +1294,14 @@ ast_expression::hir(exec_list *instructions, } case ast_conditional: { - op[0] = this->subexpressions[0]->hir(instructions, state); - /* From page 59 (page 65 of the PDF) of the GLSL 1.50 spec: * * "The ternary selection operator (?:). It operates on three * expressions (exp1 ? exp2 : exp3). This operator evaluates the * first expression, which must result in a scalar Boolean." */ - if (!op[0]->type->is_boolean() || !op[0]->type->is_scalar()) { - YYLTYPE loc = this->subexpressions[0]->get_location(); - - _mesa_glsl_error(& loc, state, "?: condition must be scalar boolean"); - error_emitted = true; - } + op[0] = get_scalar_boolean_operand(instructions, state, this, 0, + "condition", &error_emitted); /* The :? operator is implemented by generating an anonymous temporary * followed by an if-statement. The last instruction in each branch of @@ -1424,7 +1399,6 @@ ast_expression::hir(exec_list *instructions, result = do_assignment(instructions, state, op[0]->clone(ctx, NULL), temp_rhs, false, this->subexpressions[0]->get_location()); - type = result->type; error_emitted = op[0]->type->is_error(); break; } @@ -1454,14 +1428,12 @@ ast_expression::hir(exec_list *instructions, op[0]->clone(ctx, NULL), temp_rhs, false, this->subexpressions[0]->get_location()); - type = result->type; error_emitted = op[0]->type->is_error(); break; } case ast_field_selection: result = _mesa_ast_field_selection_to_hir(this, instructions, state); - type = result->type; break; case ast_array_index: { @@ -1577,7 +1549,7 @@ ast_expression::hir(exec_list *instructions, */ ir_variable *v = array->whole_variable_referenced(); if (v != NULL) - v->max_array_access = array->type->array_size(); + v->max_array_access = array->type->array_size() - 1; } } @@ -1618,7 +1590,6 @@ ast_expression::hir(exec_list *instructions, if (error_emitted) result->type = glsl_type::error_type; - type = result->type; break; } @@ -1641,7 +1612,6 @@ ast_expression::hir(exec_list *instructions, if (var != NULL) { var->used = true; - type = result->type; } else { _mesa_glsl_error(& loc, state, "`%s' undeclared", this->primary_expression.identifier); @@ -1652,22 +1622,18 @@ ast_expression::hir(exec_list *instructions, } case ast_int_constant: - type = glsl_type::int_type; result = new(ctx) ir_constant(this->primary_expression.int_constant); break; case ast_uint_constant: - type = glsl_type::uint_type; result = new(ctx) ir_constant(this->primary_expression.uint_constant); break; case ast_float_constant: - type = glsl_type::float_type; result = new(ctx) ir_constant(this->primary_expression.float_constant); break; case ast_bool_constant: - type = glsl_type::bool_type; result = new(ctx) ir_constant(bool(this->primary_expression.bool_constant)); break; @@ -1682,10 +1648,42 @@ ast_expression::hir(exec_list *instructions, * therefore add instructions to the instruction list), they get dropped * on the floor. */ - foreach_list_typed (ast_node, ast, link, &this->expressions) - result = ast->hir(instructions, state); + exec_node *previous_tail_pred = NULL; + YYLTYPE previous_operand_loc = loc; + + foreach_list_typed (ast_node, ast, link, &this->expressions) { + /* If one of the operands of comma operator does not generate any + * code, we want to emit a warning. At each pass through the loop + * previous_tail_pred will point to the last instruction in the + * stream *before* processing the previous operand. Naturally, + * instructions->tail_pred will point to the last instruction in the + * stream *after* processing the previous operand. If the two + * pointers match, then the previous operand had no effect. + * + * The warning behavior here differs slightly from GCC. GCC will + * only emit a warning if none of the left-hand operands have an + * effect. However, it will emit a warning for each. I believe that + * there are some cases in C (especially with GCC extensions) where + * it is useful to have an intermediate step in a sequence have no + * effect, but I don't think these cases exist in GLSL. Either way, + * it would be a giant hassle to replicate that behavior. + */ + if (previous_tail_pred == instructions->tail_pred) { + _mesa_glsl_warning(&previous_operand_loc, state, + "left-hand operand of comma expression has " + "no effect"); + } + + /* tail_pred is directly accessed instead of using the get_tail() + * method for performance reasons. get_tail() has extra code to + * return NULL when the list is empty. We don't care about that + * here, so using tail_pred directly is fine. + */ + previous_tail_pred = instructions->tail_pred; + previous_operand_loc = ast->get_location(); - type = result->type; + result = ast->hir(instructions, state); + } /* Any errors should have already been emitted in the loop above. */ @@ -1693,8 +1691,10 @@ ast_expression::hir(exec_list *instructions, break; } } + type = NULL; /* use result->type, not type. */ + assert(result != NULL); - if (type->is_error() && !error_emitted) + if (result->type->is_error() && !error_emitted) _mesa_glsl_error(& loc, state, "type mismatch"); return result; @@ -2676,17 +2676,24 @@ ast_declarator_list::hir(exec_list *instructions, * preceded by one of these precision qualifiers [...] Literal * constants do not have precision qualifiers. Neither do Boolean * variables. + * + * In GLSL ES, sampler types are also allowed. + * + * From page 87 of the GLSL ES spec: + * "RESOLUTION: Allow sampler types to take a precision qualifier." */ if (this->type->specifier->precision != ast_precision_none && !var->type->is_float() && !var->type->is_integer() + && !(var->type->is_sampler() && state->es_shader) && !(var->type->is_array() && (var->type->fields.array->is_float() || var->type->fields.array->is_integer()))) { _mesa_glsl_error(&loc, state, - "precision qualifiers apply only to floating point " - "and integer types"); + "precision qualifiers apply only to floating point" + "%s types", state->es_shader ? ", integer, and sampler" + : "and integer"); } /* Process the initializer and add its instructions to a temporary diff --git a/src/glsl/glcpp/glcpp-parse.y b/src/glsl/glcpp/glcpp-parse.y index 1f6e67fa062..6f15e85a122 100644 --- a/src/glsl/glcpp/glcpp-parse.y +++ b/src/glsl/glcpp/glcpp-parse.y @@ -95,16 +95,16 @@ _token_list_append_list (token_list_t *list, token_list_t *tail); static int _token_list_equal_ignoring_space (token_list_t *a, token_list_t *b); -static active_list_t * -_active_list_push (active_list_t *list, - const char *identifier, - token_node_t *marker); +static void +_parser_active_list_push (glcpp_parser_t *parser, + const char *identifier, + token_node_t *marker); -static active_list_t * -_active_list_pop (active_list_t *list); +static void +_parser_active_list_pop (glcpp_parser_t *parser); -int -_active_list_contains (active_list_t *list, const char *identifier); +static int +_parser_active_list_contains (glcpp_parser_t *parser, const char *identifier); static void _glcpp_parser_expand_if (glcpp_parser_t *parser, int type, token_list_t *list); @@ -1468,7 +1468,7 @@ _glcpp_parser_expand_node (glcpp_parser_t *parser, /* Finally, don't expand this macro if we're already actively * expanding it, (to avoid infinite recursion). */ - if (_active_list_contains (parser->active, identifier)) { + if (_parser_active_list_contains (parser, identifier)) { /* We change the token type here from IDENTIFIER to * OTHER to prevent any future expansion of this * unexpanded token. */ @@ -1498,51 +1498,53 @@ _glcpp_parser_expand_node (glcpp_parser_t *parser, return _glcpp_parser_expand_function (parser, node, last); } -/* Push a new identifier onto the active list, returning the new list. +/* Push a new identifier onto the parser's active list. * * Here, 'marker' is the token node that appears in the list after the * expansion of 'identifier'. That is, when the list iterator begins - * examinging 'marker', then it is time to pop this node from the + * examining 'marker', then it is time to pop this node from the * active stack. */ -active_list_t * -_active_list_push (active_list_t *list, - const char *identifier, - token_node_t *marker) +static void +_parser_active_list_push (glcpp_parser_t *parser, + const char *identifier, + token_node_t *marker) { active_list_t *node; - node = ralloc (list, active_list_t); + node = ralloc (parser->active, active_list_t); node->identifier = ralloc_strdup (node, identifier); node->marker = marker; - node->next = list; + node->next = parser->active; - return node; + parser->active = node; } -active_list_t * -_active_list_pop (active_list_t *list) +static void +_parser_active_list_pop (glcpp_parser_t *parser) { - active_list_t *node = list; + active_list_t *node = parser->active; - if (node == NULL) - return NULL; + if (node == NULL) { + parser->active = NULL; + return; + } - node = list->next; - ralloc_free (list); + node = parser->active->next; + ralloc_free (parser->active); - return node; + parser->active = node; } -int -_active_list_contains (active_list_t *list, const char *identifier) +static int +_parser_active_list_contains (glcpp_parser_t *parser, const char *identifier) { active_list_t *node; - if (list == NULL) + if (parser->active == NULL) return 0; - for (node = list; node; node = node->next) + for (node = parser->active; node; node = node->next) if (strcmp (node->identifier, identifier) == 0) return 1; @@ -1561,6 +1563,7 @@ _glcpp_parser_expand_token_list (glcpp_parser_t *parser, token_node_t *node_prev; token_node_t *node, *last = NULL; token_list_t *expansion; + active_list_t *active_initial = parser->active; if (list == NULL) return; @@ -1573,10 +1576,8 @@ _glcpp_parser_expand_token_list (glcpp_parser_t *parser, while (node) { while (parser->active && parser->active->marker == node) - parser->active = _active_list_pop (parser->active); + _parser_active_list_pop (parser); - /* Find the expansion for node, which will replace all - * nodes from node to last, inclusive. */ expansion = _glcpp_parser_expand_node (parser, node, &last); if (expansion) { token_node_t *n; @@ -1585,12 +1586,12 @@ _glcpp_parser_expand_token_list (glcpp_parser_t *parser, while (parser->active && parser->active->marker == n) { - parser->active = _active_list_pop (parser->active); + _parser_active_list_pop (parser); } - parser->active = _active_list_push (parser->active, - node->token->value.str, - last->next); + _parser_active_list_push (parser, + node->token->value.str, + last->next); /* Splice expansion into list, supporting a * simple deletion if the expansion is @@ -1617,8 +1618,11 @@ _glcpp_parser_expand_token_list (glcpp_parser_t *parser, node = node_prev ? node_prev->next : list->head; } - while (parser->active) - parser->active = _active_list_pop (parser->active); + /* Remove any lingering effects of this invocation on the + * active list. That is, pop until the list looks like it did + * at the beginning of this function. */ + while (parser->active && parser->active != active_initial) + _parser_active_list_pop (parser); list->non_space_tail = list->tail; } diff --git a/src/glsl/glcpp/tests/084-unbalanced-parentheses.c.expected b/src/glsl/glcpp/tests/084-unbalanced-parentheses.c.expected new file mode 100644 index 00000000000..af49a37369d --- /dev/null +++ b/src/glsl/glcpp/tests/084-unbalanced-parentheses.c.expected @@ -0,0 +1,2 @@ +0:2(8): preprocessor error: syntax error, unexpected $end + diff --git a/src/glsl/glcpp/tests/093-divide-by-zero.c.expected b/src/glsl/glcpp/tests/093-divide-by-zero.c.expected new file mode 100644 index 00000000000..08f183f24f5 --- /dev/null +++ b/src/glsl/glcpp/tests/093-divide-by-zero.c.expected @@ -0,0 +1,4 @@ +0:1(13): preprocessor error: division by 0 in preprocessor directive + + + diff --git a/src/glsl/glcpp/tests/094-divide-by-zero-short-circuit.c b/src/glsl/glcpp/tests/094-divide-by-zero-short-circuit.c index a9c6f36def8..04497b17913 100644 --- a/src/glsl/glcpp/tests/094-divide-by-zero-short-circuit.c +++ b/src/glsl/glcpp/tests/094-divide-by-zero-short-circuit.c @@ -1,2 +1,13 @@ +/* glcpp is generating a division-by-zero error for this case. It's + * easy to argue that it should be short-circuiting the evaluation and + * not generating the diagnostic (which happens to be what gcc does). + * But it doesn't seem like we should force this behavior on our + * pre-processor, (and, as always, the GLSL specification of the + * pre-processor is too vague on this point). + * + * If a short-circuit evaluation optimization does get added to the + * pre-processor then it would legitimate to update the expected file + * for this test. +*/ #if 1 || (1 / 0) #endif diff --git a/src/glsl/glcpp/tests/094-divide-by-zero-short-circuit.c.expected b/src/glsl/glcpp/tests/094-divide-by-zero-short-circuit.c.expected new file mode 100644 index 00000000000..84fdc50c920 --- /dev/null +++ b/src/glsl/glcpp/tests/094-divide-by-zero-short-circuit.c.expected @@ -0,0 +1,15 @@ +0:12(17): preprocessor error: division by 0 in preprocessor directive + + + + + + + + + + + + + + diff --git a/src/glsl/glcpp/tests/095-recursive-define.c.expected b/src/glsl/glcpp/tests/095-recursive-define.c.expected new file mode 100644 index 00000000000..c7aa18ff6cb --- /dev/null +++ b/src/glsl/glcpp/tests/095-recursive-define.c.expected @@ -0,0 +1,4 @@ + + +B(0, C) + diff --git a/src/glsl/glcpp/tests/glcpp-test b/src/glsl/glcpp/tests/glcpp-test index 5dc08ea6acb..e8f3b546387 100755 --- a/src/glsl/glcpp/tests/glcpp-test +++ b/src/glsl/glcpp/tests/glcpp-test @@ -2,6 +2,34 @@ trap 'rm $test.valgrind-errors; exit 1' INT QUIT +usage () +{ + cat <<EOF +Usage: glcpp [options...] + +Run the test suite for mesa's GLSL pre-processor. + +Valid options include: + + --valgrind Run the test suite a second time under valgrind +EOF +} + +# Parse command-line options +for option; do + if [ "${option}" = '--help' ] ; then + usage + exit 0 + elif [ "${option}" = '--valgrind' ] ; then + do_valgrind=yes + else + echo "Unrecognized option: $option" >&2 + echo >&2 + usage + exit 1 + fi +done + total=0 pass=0 clean=0 @@ -24,23 +52,25 @@ echo "" echo "$pass/$total tests returned correct results" echo "" -echo "====== Testing for valgrind cleanliness ======" -for test in *.c; do - echo -n "Testing $test with valgrind..." - valgrind --error-exitcode=31 --log-file=$test.valgrind-errors ../glcpp < $test >/dev/null 2>&1 - if [ "$?" = "31" ]; then - echo "ERRORS" - cat $test.valgrind-errors - else - echo "CLEAN" - clean=$((clean+1)) - rm $test.valgrind-errors - fi -done +if [ "$do_valgrind" = "yes" ]; then + echo "====== Testing for valgrind cleanliness ======" + for test in *.c; do + echo -n "Testing $test with valgrind..." + valgrind --error-exitcode=31 --log-file=$test.valgrind-errors ../glcpp < $test >/dev/null 2>&1 + if [ "$?" = "31" ]; then + echo "ERRORS" + cat $test.valgrind-errors + else + echo "CLEAN" + clean=$((clean+1)) + rm $test.valgrind-errors + fi + done -echo "" -echo "$pass/$total tests returned correct results" -echo "$clean/$total tests are valgrind-clean" + echo "" + echo "$pass/$total tests returned correct results" + echo "$clean/$total tests are valgrind-clean" +fi if [ "$pass" = "$total" ] && [ "$clean" = "$total" ]; then exit 0 diff --git a/src/glsl/glsl_parser_extras.cpp b/src/glsl/glsl_parser_extras.cpp index e8c60936fb6..5bb3a6f25a3 100644 --- a/src/glsl/glsl_parser_extras.cpp +++ b/src/glsl/glsl_parser_extras.cpp @@ -211,14 +211,13 @@ _mesa_glsl_process_extension(const char *name, YYLTYPE *name_locp, state->ARB_draw_buffers_warn = (ext_mode == extension_warn); } } else if (strcmp(name, "GL_ARB_draw_instanced") == 0) { + state->ARB_draw_instanced_enable = (ext_mode != extension_disable); + state->ARB_draw_instanced_warn = (ext_mode == extension_warn); + /* This extension is only supported in vertex shaders. */ - if (state->target != vertex_shader) { - unsupported = true; - } else { - state->ARB_draw_instanced_enable = (ext_mode != extension_disable); - state->ARB_draw_instanced_warn = (ext_mode == extension_warn); - } + unsupported = (state->target != vertex_shader) + || !state->extensions->ARB_draw_instanced; } else if (strcmp(name, "GL_ARB_explicit_attrib_location") == 0) { state->ARB_explicit_attrib_location_enable = (ext_mode != extension_disable); @@ -242,13 +241,13 @@ _mesa_glsl_process_extension(const char *name, YYLTYPE *name_locp, unsupported = !state->extensions->EXT_texture_array; } else if (strcmp(name, "GL_ARB_shader_stencil_export") == 0) { - if (state->target != fragment_shader) { - unsupported = true; - } else { - state->ARB_shader_stencil_export_enable = (ext_mode != extension_disable); - state->ARB_shader_stencil_export_warn = (ext_mode == extension_warn); - unsupported = !state->extensions->ARB_shader_stencil_export; - } + state->ARB_shader_stencil_export_enable = (ext_mode != extension_disable); + state->ARB_shader_stencil_export_warn = (ext_mode == extension_warn); + + /* This extension is only supported in fragment shaders. + */ + unsupported = (state->target != fragment_shader) + || !state->extensions->ARB_shader_stencil_export; } else if (strcmp(name, "GL_AMD_conservative_depth") == 0) { /* The AMD_conservative spec does not forbid requiring the extension in * the vertex shader. @@ -769,7 +768,7 @@ do_common_optimization(exec_list *ir, bool linked, unsigned max_unroll_iteration progress = do_if_simplification(ir) || progress; progress = do_discard_simplification(ir) || progress; progress = do_copy_propagation(ir) || progress; - /*progress = do_copy_propagation_elements(ir) || progress;*/ + progress = do_copy_propagation_elements(ir) || progress; if (linked) progress = do_dead_code(ir) || progress; else diff --git a/src/glsl/glsl_parser_extras.h b/src/glsl/glsl_parser_extras.h index b5c016fb399..6df0e160ae3 100644 --- a/src/glsl/glsl_parser_extras.h +++ b/src/glsl/glsl_parser_extras.h @@ -268,8 +268,8 @@ extern "C" { extern int preprocess(void *ctx, const char **shader, char **info_log, const struct gl_extensions *extensions, int api); -extern void _mesa_destroy_shader_compiler(); -extern void _mesa_destroy_shader_compiler_caches(); +extern void _mesa_destroy_shader_compiler(void); +extern void _mesa_destroy_shader_compiler_caches(void); #ifdef __cplusplus } diff --git a/src/glsl/ir.h b/src/glsl/ir.h index 39d4ebc7107..a41984310b3 100644 --- a/src/glsl/ir.h +++ b/src/glsl/ir.h @@ -253,6 +253,16 @@ enum ir_depth_layout { const char* depth_layout_string(ir_depth_layout layout); +/** + * Description of built-in state associated with a uniform + * + * \sa ir_variable::state_slots + */ +struct ir_state_slot { + int tokens[5]; + int swizzle; +}; + class ir_variable : public ir_instruction { public: ir_variable(const struct glsl_type *, const char *, ir_variable_mode); @@ -386,6 +396,22 @@ public: int location; /** + * Built-in state that backs this uniform + * + * Once set at variable creation, \c state_slots must remain invariant. + * This is because, ideally, this array would be shared by all clones of + * this variable in the IR tree. In other words, we'd really like for it + * to be a fly-weight. + * + * If the variable is not a uniform, \c num_state_slots will be zero and + * \c state_slots will be \c NULL. + */ + /*@{*/ + unsigned num_state_slots; /**< Number of state slots used */ + ir_state_slot *state_slots; /**< State descriptors. */ + /*@}*/ + + /** * Emit a warning if this variable is accessed. */ const char *warn_extension; diff --git a/src/glsl/ir_clone.cpp b/src/glsl/ir_clone.cpp index 2c0574dc6bf..069bb85e8de 100644 --- a/src/glsl/ir_clone.cpp +++ b/src/glsl/ir_clone.cpp @@ -53,6 +53,18 @@ ir_variable::clone(void *mem_ctx, struct hash_table *ht) const var->origin_upper_left = this->origin_upper_left; var->pixel_center_integer = this->pixel_center_integer; var->explicit_location = this->explicit_location; + + var->num_state_slots = this->num_state_slots; + if (this->state_slots) { + /* FINISHME: This really wants to use something like talloc_reference, but + * FINISHME: ralloc doesn't have any similar function. + */ + var->state_slots = ralloc_array(var, ir_state_slot, + this->num_state_slots); + memcpy(var->state_slots, this->state_slots, + sizeof(this->state_slots[0]) * var->num_state_slots); + } + if (this->explicit_location) var->location = this->location; diff --git a/src/glsl/ir_print_visitor.cpp b/src/glsl/ir_print_visitor.cpp index a84f8dfc8a1..02f3d814926 100644 --- a/src/glsl/ir_print_visitor.cpp +++ b/src/glsl/ir_print_visitor.cpp @@ -25,6 +25,10 @@ #include "glsl_types.h" #include "glsl_parser_extras.h" +extern "C" { +#include "program/hash_table.h" +} + static void print_type(const glsl_type *t); void @@ -67,6 +71,21 @@ _mesa_print_ir(exec_list *instructions, printf("\n)"); } +ir_print_visitor::ir_print_visitor() +{ + indentation = 0; + printable_names = + hash_table_ctor(32, hash_table_pointer_hash, hash_table_pointer_compare); + symbols = _mesa_symbol_table_ctor(); + mem_ctx = ralloc_context(NULL); +} + +ir_print_visitor::~ir_print_visitor() +{ + hash_table_dtor(printable_names); + _mesa_symbol_table_dtor(symbols); + ralloc_free(mem_ctx); +} void ir_print_visitor::indent(void) { @@ -74,6 +93,26 @@ void ir_print_visitor::indent(void) printf(" "); } +const char * +ir_print_visitor::unique_name(ir_variable *var) +{ + /* Do we already have a name for this variable? */ + const char *name = (const char *) hash_table_find(this->printable_names, var); + if (name != NULL) + return name; + + /* If there's no conflict, just use the original name */ + if (_mesa_symbol_table_find_symbol(this->symbols, -1, var->name) == NULL) { + name = var->name; + } else { + static unsigned i = 1; + name = ralloc_asprintf(this->mem_ctx, "%s@%u", var->name, ++i); + } + hash_table_insert(this->printable_names, (void *) name, var); + _mesa_symbol_table_add_symbol(this->symbols, -1, name, var); + return name; +} + static void print_type(const glsl_type *t) { @@ -104,12 +143,13 @@ void ir_print_visitor::visit(ir_variable *ir) cent, inv, mode[ir->mode], interp[ir->interpolation]); print_type(ir->type); - printf(" %s@%p)", ir->name, (void *) ir); + printf(" %s)", unique_name(ir)); } void ir_print_visitor::visit(ir_function_signature *ir) { + _mesa_symbol_table_push_scope(symbols); printf("(signature "); indentation++; @@ -148,6 +188,7 @@ void ir_print_visitor::visit(ir_function_signature *ir) indent(); printf("))\n"); indentation--; + _mesa_symbol_table_pop_scope(symbols); } @@ -265,7 +306,7 @@ void ir_print_visitor::visit(ir_swizzle *ir) void ir_print_visitor::visit(ir_dereference_variable *ir) { ir_variable *var = ir->variable_referenced(); - printf("(var_ref %s@%p) ", var->name, (void *) var); + printf("(var_ref %s) ", unique_name(var)); } diff --git a/src/glsl/ir_print_visitor.h b/src/glsl/ir_print_visitor.h index 4feeb8c184d..c7136f11a3b 100644 --- a/src/glsl/ir_print_visitor.h +++ b/src/glsl/ir_print_visitor.h @@ -29,6 +29,10 @@ #include "ir.h" #include "ir_visitor.h" +extern "C" { +#include "program/symbol_table.h" +} + extern void _mesa_print_ir(exec_list *instructions, struct _mesa_glsl_parse_state *state); @@ -37,15 +41,8 @@ extern void _mesa_print_ir(exec_list *instructions, */ class ir_print_visitor : public ir_visitor { public: - ir_print_visitor() - { - indentation = 0; - } - - virtual ~ir_print_visitor() - { - /* empty */ - } + ir_print_visitor(); + virtual ~ir_print_visitor(); void indent(void); @@ -77,6 +74,20 @@ public: /*@}*/ private: + /** + * Fetch/generate a unique name for ir_variable. + * + * GLSL IR permits multiple ir_variables to share the same name. This works + * fine until we try to print it, when we really need a unique one. + */ + const char *unique_name(ir_variable *var); + + /** A mapping from ir_variable * -> unique printable names. */ + hash_table *printable_names; + _mesa_symbol_table *symbols; + + void *mem_ctx; + int indentation; }; diff --git a/src/glsl/ir_validate.cpp b/src/glsl/ir_validate.cpp index 0fc3baf8690..7b1c19d65aa 100644 --- a/src/glsl/ir_validate.cpp +++ b/src/glsl/ir_validate.cpp @@ -254,7 +254,7 @@ ir_validate::visit_leave(ir_expression *ir) case ir_unop_f2i: assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT); - assert(ir->type->base_type == GLSL_TYPE_INT); + assert(ir->type->is_integer()); break; case ir_unop_i2f: assert(ir->operands[0]->type->base_type == GLSL_TYPE_INT); @@ -269,12 +269,12 @@ ir_validate::visit_leave(ir_expression *ir) assert(ir->type->base_type == GLSL_TYPE_FLOAT); break; case ir_unop_i2b: - assert(ir->operands[0]->type->base_type == GLSL_TYPE_INT); + assert(ir->operands[0]->type->is_integer()); assert(ir->type->base_type == GLSL_TYPE_BOOL); break; case ir_unop_b2i: assert(ir->operands[0]->type->base_type == GLSL_TYPE_BOOL); - assert(ir->type->base_type == GLSL_TYPE_INT); + assert(ir->type->is_integer()); break; case ir_unop_u2f: assert(ir->operands[0]->type->base_type == GLSL_TYPE_UINT); @@ -473,6 +473,21 @@ ir_validate::visit(ir_variable *ir) assert(ralloc_parent(ir->name) == ir); hash_table_insert(ht, ir, ir); + + + /* If a variable is an array, verify that the maximum array index is in + * bounds. There was once an error in AST-to-HIR conversion that set this + * to be out of bounds. + */ + if (ir->type->array_size() > 0) { + if (ir->max_array_access >= 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(); + abort(); + } + } + return visit_continue; } diff --git a/src/glsl/ir_variable.cpp b/src/glsl/ir_variable.cpp index 18a3e0fb0d9..f3577175691 100644 --- a/src/glsl/ir_variable.cpp +++ b/src/glsl/ir_variable.cpp @@ -25,6 +25,10 @@ #include "glsl_parser_extras.h" #include "glsl_symbol_table.h" #include "builtin_variables.h" +#include "main/uniforms.h" +#include "program/prog_parameter.h" +#include "program/prog_statevars.h" +#include "program/prog_instruction.h" static void generate_ARB_draw_buffers_variables(exec_list *, struct _mesa_glsl_parse_state *, @@ -35,10 +39,259 @@ generate_ARB_draw_instanced_variables(exec_list *, struct _mesa_glsl_parse_state *, bool, _mesa_glsl_parser_targets); +static struct gl_builtin_uniform_element gl_DepthRange_elements[] = { + {"near", {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_XXXX}, + {"far", {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_YYYY}, + {"diff", {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_ZZZZ}, +}; + +static struct gl_builtin_uniform_element gl_ClipPlane_elements[] = { + {NULL, {STATE_CLIPPLANE, 0, 0}, SWIZZLE_XYZW} +}; + +static struct gl_builtin_uniform_element gl_Point_elements[] = { + {"size", {STATE_POINT_SIZE}, SWIZZLE_XXXX}, + {"sizeMin", {STATE_POINT_SIZE}, SWIZZLE_YYYY}, + {"sizeMax", {STATE_POINT_SIZE}, SWIZZLE_ZZZZ}, + {"fadeThresholdSize", {STATE_POINT_SIZE}, SWIZZLE_WWWW}, + {"distanceConstantAttenuation", {STATE_POINT_ATTENUATION}, SWIZZLE_XXXX}, + {"distanceLinearAttenuation", {STATE_POINT_ATTENUATION}, SWIZZLE_YYYY}, + {"distanceQuadraticAttenuation", {STATE_POINT_ATTENUATION}, SWIZZLE_ZZZZ}, +}; + +static struct gl_builtin_uniform_element gl_FrontMaterial_elements[] = { + {"emission", {STATE_MATERIAL, 0, STATE_EMISSION}, SWIZZLE_XYZW}, + {"ambient", {STATE_MATERIAL, 0, STATE_AMBIENT}, SWIZZLE_XYZW}, + {"diffuse", {STATE_MATERIAL, 0, STATE_DIFFUSE}, SWIZZLE_XYZW}, + {"specular", {STATE_MATERIAL, 0, STATE_SPECULAR}, SWIZZLE_XYZW}, + {"shininess", {STATE_MATERIAL, 0, STATE_SHININESS}, SWIZZLE_XXXX}, +}; + +static struct gl_builtin_uniform_element gl_BackMaterial_elements[] = { + {"emission", {STATE_MATERIAL, 1, STATE_EMISSION}, SWIZZLE_XYZW}, + {"ambient", {STATE_MATERIAL, 1, STATE_AMBIENT}, SWIZZLE_XYZW}, + {"diffuse", {STATE_MATERIAL, 1, STATE_DIFFUSE}, SWIZZLE_XYZW}, + {"specular", {STATE_MATERIAL, 1, STATE_SPECULAR}, SWIZZLE_XYZW}, + {"shininess", {STATE_MATERIAL, 1, STATE_SHININESS}, SWIZZLE_XXXX}, +}; + +static struct gl_builtin_uniform_element gl_LightSource_elements[] = { + {"ambient", {STATE_LIGHT, 0, STATE_AMBIENT}, SWIZZLE_XYZW}, + {"diffuse", {STATE_LIGHT, 0, STATE_DIFFUSE}, SWIZZLE_XYZW}, + {"specular", {STATE_LIGHT, 0, STATE_SPECULAR}, SWIZZLE_XYZW}, + {"position", {STATE_LIGHT, 0, STATE_POSITION}, SWIZZLE_XYZW}, + {"halfVector", {STATE_LIGHT, 0, STATE_HALF_VECTOR}, SWIZZLE_XYZW}, + {"spotDirection", {STATE_LIGHT, 0, STATE_SPOT_DIRECTION}, + MAKE_SWIZZLE4(SWIZZLE_X, + SWIZZLE_Y, + SWIZZLE_Z, + SWIZZLE_Z)}, + {"spotCosCutoff", {STATE_LIGHT, 0, STATE_SPOT_DIRECTION}, SWIZZLE_WWWW}, + {"spotCutoff", {STATE_LIGHT, 0, STATE_SPOT_CUTOFF}, SWIZZLE_XXXX}, + {"spotExponent", {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_WWWW}, + {"constantAttenuation", {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_XXXX}, + {"linearAttenuation", {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_YYYY}, + {"quadraticAttenuation", {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_ZZZZ}, +}; + +static struct gl_builtin_uniform_element gl_LightModel_elements[] = { + {"ambient", {STATE_LIGHTMODEL_AMBIENT, 0}, SWIZZLE_XYZW}, +}; + +static struct gl_builtin_uniform_element gl_FrontLightModelProduct_elements[] = { + {"sceneColor", {STATE_LIGHTMODEL_SCENECOLOR, 0}, SWIZZLE_XYZW}, +}; + +static struct gl_builtin_uniform_element gl_BackLightModelProduct_elements[] = { + {"sceneColor", {STATE_LIGHTMODEL_SCENECOLOR, 1}, SWIZZLE_XYZW}, +}; + +static struct gl_builtin_uniform_element gl_FrontLightProduct_elements[] = { + {"ambient", {STATE_LIGHTPROD, 0, 0, STATE_AMBIENT}, SWIZZLE_XYZW}, + {"diffuse", {STATE_LIGHTPROD, 0, 0, STATE_DIFFUSE}, SWIZZLE_XYZW}, + {"specular", {STATE_LIGHTPROD, 0, 0, STATE_SPECULAR}, SWIZZLE_XYZW}, +}; + +static struct gl_builtin_uniform_element gl_BackLightProduct_elements[] = { + {"ambient", {STATE_LIGHTPROD, 0, 1, STATE_AMBIENT}, SWIZZLE_XYZW}, + {"diffuse", {STATE_LIGHTPROD, 0, 1, STATE_DIFFUSE}, SWIZZLE_XYZW}, + {"specular", {STATE_LIGHTPROD, 0, 1, STATE_SPECULAR}, SWIZZLE_XYZW}, +}; + +static struct gl_builtin_uniform_element gl_TextureEnvColor_elements[] = { + {NULL, {STATE_TEXENV_COLOR, 0}, SWIZZLE_XYZW}, +}; + +static struct gl_builtin_uniform_element gl_EyePlaneS_elements[] = { + {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_S}, SWIZZLE_XYZW}, +}; + +static struct gl_builtin_uniform_element gl_EyePlaneT_elements[] = { + {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_T}, SWIZZLE_XYZW}, +}; + +static struct gl_builtin_uniform_element gl_EyePlaneR_elements[] = { + {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_R}, SWIZZLE_XYZW}, +}; + +static struct gl_builtin_uniform_element gl_EyePlaneQ_elements[] = { + {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_Q}, SWIZZLE_XYZW}, +}; + +static struct gl_builtin_uniform_element gl_ObjectPlaneS_elements[] = { + {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_S}, SWIZZLE_XYZW}, +}; + +static struct gl_builtin_uniform_element gl_ObjectPlaneT_elements[] = { + {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_T}, SWIZZLE_XYZW}, +}; + +static struct gl_builtin_uniform_element gl_ObjectPlaneR_elements[] = { + {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_R}, SWIZZLE_XYZW}, +}; + +static struct gl_builtin_uniform_element gl_ObjectPlaneQ_elements[] = { + {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_Q}, SWIZZLE_XYZW}, +}; + +static struct gl_builtin_uniform_element gl_Fog_elements[] = { + {"color", {STATE_FOG_COLOR}, SWIZZLE_XYZW}, + {"density", {STATE_FOG_PARAMS}, SWIZZLE_XXXX}, + {"start", {STATE_FOG_PARAMS}, SWIZZLE_YYYY}, + {"end", {STATE_FOG_PARAMS}, SWIZZLE_ZZZZ}, + {"scale", {STATE_FOG_PARAMS}, SWIZZLE_WWWW}, +}; + +static struct gl_builtin_uniform_element gl_NormalScale_elements[] = { + {NULL, {STATE_NORMAL_SCALE}, SWIZZLE_XXXX}, +}; + +static struct gl_builtin_uniform_element gl_MESABumpRotMatrix0_elements[] = { + {NULL, {STATE_INTERNAL, STATE_ROT_MATRIX_0}, SWIZZLE_XYZW}, +}; + +static struct gl_builtin_uniform_element gl_MESABumpRotMatrix1_elements[] = { + {NULL, {STATE_INTERNAL, STATE_ROT_MATRIX_1}, SWIZZLE_XYZW}, +}; + +static struct gl_builtin_uniform_element gl_MESAFogParamsOptimized_elements[] = { + {NULL, {STATE_INTERNAL, STATE_FOG_PARAMS_OPTIMIZED}, SWIZZLE_XYZW}, +}; + +#define MATRIX(name, statevar, modifier) \ + static struct gl_builtin_uniform_element name ## _elements[] = { \ + { NULL, { statevar, 0, 0, 0, modifier}, SWIZZLE_XYZW }, \ + { NULL, { statevar, 0, 1, 1, modifier}, SWIZZLE_XYZW }, \ + { NULL, { statevar, 0, 2, 2, modifier}, SWIZZLE_XYZW }, \ + { NULL, { statevar, 0, 3, 3, modifier}, SWIZZLE_XYZW }, \ + } + +MATRIX(gl_ModelViewMatrix, + STATE_MODELVIEW_MATRIX, STATE_MATRIX_TRANSPOSE); +MATRIX(gl_ModelViewMatrixInverse, + STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVTRANS); +MATRIX(gl_ModelViewMatrixTranspose, + STATE_MODELVIEW_MATRIX, 0); +MATRIX(gl_ModelViewMatrixInverseTranspose, + STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVERSE); + +MATRIX(gl_ProjectionMatrix, + STATE_PROJECTION_MATRIX, STATE_MATRIX_TRANSPOSE); +MATRIX(gl_ProjectionMatrixInverse, + STATE_PROJECTION_MATRIX, STATE_MATRIX_INVTRANS); +MATRIX(gl_ProjectionMatrixTranspose, + STATE_PROJECTION_MATRIX, 0); +MATRIX(gl_ProjectionMatrixInverseTranspose, + STATE_PROJECTION_MATRIX, STATE_MATRIX_INVERSE); + +MATRIX(gl_ModelViewProjectionMatrix, + STATE_MVP_MATRIX, STATE_MATRIX_TRANSPOSE); +MATRIX(gl_ModelViewProjectionMatrixInverse, + STATE_MVP_MATRIX, STATE_MATRIX_INVTRANS); +MATRIX(gl_ModelViewProjectionMatrixTranspose, + STATE_MVP_MATRIX, 0); +MATRIX(gl_ModelViewProjectionMatrixInverseTranspose, + STATE_MVP_MATRIX, STATE_MATRIX_INVERSE); + +MATRIX(gl_TextureMatrix, + STATE_TEXTURE_MATRIX, STATE_MATRIX_TRANSPOSE); +MATRIX(gl_TextureMatrixInverse, + STATE_TEXTURE_MATRIX, STATE_MATRIX_INVTRANS); +MATRIX(gl_TextureMatrixTranspose, + STATE_TEXTURE_MATRIX, 0); +MATRIX(gl_TextureMatrixInverseTranspose, + STATE_TEXTURE_MATRIX, STATE_MATRIX_INVERSE); + +static struct gl_builtin_uniform_element gl_NormalMatrix_elements[] = { + { NULL, { STATE_MODELVIEW_MATRIX, 0, 0, 0, STATE_MATRIX_INVERSE}, + SWIZZLE_XYZW }, + { NULL, { STATE_MODELVIEW_MATRIX, 0, 1, 1, STATE_MATRIX_INVERSE}, + SWIZZLE_XYZW }, + { NULL, { STATE_MODELVIEW_MATRIX, 0, 2, 2, STATE_MATRIX_INVERSE}, + SWIZZLE_XYZW }, +}; + +#undef MATRIX + +#define STATEVAR(name) {#name, name ## _elements, Elements(name ## _elements)} + +const struct gl_builtin_uniform_desc _mesa_builtin_uniform_desc[] = { + STATEVAR(gl_DepthRange), + STATEVAR(gl_ClipPlane), + STATEVAR(gl_Point), + STATEVAR(gl_FrontMaterial), + STATEVAR(gl_BackMaterial), + STATEVAR(gl_LightSource), + STATEVAR(gl_LightModel), + STATEVAR(gl_FrontLightModelProduct), + STATEVAR(gl_BackLightModelProduct), + STATEVAR(gl_FrontLightProduct), + STATEVAR(gl_BackLightProduct), + STATEVAR(gl_TextureEnvColor), + STATEVAR(gl_EyePlaneS), + STATEVAR(gl_EyePlaneT), + STATEVAR(gl_EyePlaneR), + STATEVAR(gl_EyePlaneQ), + STATEVAR(gl_ObjectPlaneS), + STATEVAR(gl_ObjectPlaneT), + STATEVAR(gl_ObjectPlaneR), + STATEVAR(gl_ObjectPlaneQ), + STATEVAR(gl_Fog), + + STATEVAR(gl_ModelViewMatrix), + STATEVAR(gl_ModelViewMatrixInverse), + STATEVAR(gl_ModelViewMatrixTranspose), + STATEVAR(gl_ModelViewMatrixInverseTranspose), + + STATEVAR(gl_ProjectionMatrix), + STATEVAR(gl_ProjectionMatrixInverse), + STATEVAR(gl_ProjectionMatrixTranspose), + STATEVAR(gl_ProjectionMatrixInverseTranspose), + + STATEVAR(gl_ModelViewProjectionMatrix), + STATEVAR(gl_ModelViewProjectionMatrixInverse), + STATEVAR(gl_ModelViewProjectionMatrixTranspose), + STATEVAR(gl_ModelViewProjectionMatrixInverseTranspose), + + STATEVAR(gl_TextureMatrix), + STATEVAR(gl_TextureMatrixInverse), + STATEVAR(gl_TextureMatrixTranspose), + STATEVAR(gl_TextureMatrixInverseTranspose), + + STATEVAR(gl_NormalMatrix), + STATEVAR(gl_NormalScale), + + STATEVAR(gl_MESABumpRotMatrix0), + STATEVAR(gl_MESABumpRotMatrix1), + STATEVAR(gl_MESAFogParamsOptimized), + + {NULL, NULL, 0} +}; + static ir_variable * -add_variable(const char *name, enum ir_variable_mode mode, int slot, - const glsl_type *type, exec_list *instructions, - glsl_symbol_table *symtab) +add_variable(exec_list *instructions, glsl_symbol_table *symtab, + const char *name, const glsl_type *type, + enum ir_variable_mode mode, int slot) { ir_variable *var = new(symtab) ir_variable(type, name, mode); @@ -71,17 +324,51 @@ add_variable(const char *name, enum ir_variable_mode mode, int slot, } static ir_variable * -add_uniform(exec_list *instructions, - struct _mesa_glsl_parse_state *state, +add_uniform(exec_list *instructions, glsl_symbol_table *symtab, const char *name, const glsl_type *type) { - return add_variable(name, ir_var_uniform, -1, type, instructions, - state->symbols); + ir_variable *const uni = + add_variable(instructions, symtab, name, type, ir_var_uniform, -1); + + unsigned i; + for (i = 0; _mesa_builtin_uniform_desc[i].name != NULL; i++) { + if (strcmp(_mesa_builtin_uniform_desc[i].name, name) == 0) { + break; + } + } + + assert(_mesa_builtin_uniform_desc[i].name != NULL); + const struct gl_builtin_uniform_desc* const statevar = + &_mesa_builtin_uniform_desc[i]; + + const unsigned array_count = type->is_array() ? type->length : 1; + uni->num_state_slots = array_count * statevar->num_elements; + + ir_state_slot *slots = + ralloc_array(uni, ir_state_slot, uni->num_state_slots); + + uni->state_slots = slots; + + for (unsigned a = 0; a < array_count; a++) { + for (unsigned j = 0; j < statevar->num_elements; j++) { + struct gl_builtin_uniform_element *element = &statevar->elements[j]; + + memcpy(slots->tokens, element->tokens, sizeof(element->tokens)); + if (type->is_array()) { + slots->tokens[1] = a; + } + + slots->swizzle = element->swizzle; + slots++; + } + } + + return uni; } static void -add_builtin_variable(const builtin_variable *proto, exec_list *instructions, - glsl_symbol_table *symtab) +add_builtin_variable(exec_list *instructions, glsl_symbol_table *symtab, + const builtin_variable *proto) { /* Create a new variable declaration from the description supplied by * the caller. @@ -90,18 +377,21 @@ add_builtin_variable(const builtin_variable *proto, exec_list *instructions, assert(type != NULL); - add_variable(proto->name, proto->mode, proto->slot, type, instructions, - symtab); + if (proto->mode == ir_var_uniform) { + add_uniform(instructions, symtab, proto->name, type); + } else { + add_variable(instructions, symtab, proto->name, type, proto->mode, + proto->slot); + } } static void -add_builtin_constant(exec_list *instructions, - struct _mesa_glsl_parse_state *state, +add_builtin_constant(exec_list *instructions, glsl_symbol_table *symtab, const char *name, int value) { - ir_variable *const var = add_variable(name, ir_var_auto, - -1, glsl_type::int_type, - instructions, state->symbols); + ir_variable *const var = add_variable(instructions, symtab, + name, glsl_type::int_type, + ir_var_auto, -1); var->constant_value = new(var) ir_constant(value); } @@ -112,22 +402,24 @@ static void generate_100ES_uniforms(exec_list *instructions, struct _mesa_glsl_parse_state *state) { - add_builtin_constant(instructions, state, "gl_MaxVertexAttribs", + glsl_symbol_table *const symtab = state->symbols; + + add_builtin_constant(instructions, symtab, "gl_MaxVertexAttribs", state->Const.MaxVertexAttribs); - add_builtin_constant(instructions, state, "gl_MaxVertexUniformVectors", + add_builtin_constant(instructions, symtab, "gl_MaxVertexUniformVectors", state->Const.MaxVertexUniformComponents); - add_builtin_constant(instructions, state, "gl_MaxVaryingVectors", + add_builtin_constant(instructions, symtab, "gl_MaxVaryingVectors", state->Const.MaxVaryingFloats / 4); - add_builtin_constant(instructions, state, "gl_MaxVertexTextureImageUnits", + add_builtin_constant(instructions, symtab, "gl_MaxVertexTextureImageUnits", state->Const.MaxVertexTextureImageUnits); - add_builtin_constant(instructions, state, "gl_MaxCombinedTextureImageUnits", + add_builtin_constant(instructions, symtab, "gl_MaxCombinedTextureImageUnits", state->Const.MaxCombinedTextureImageUnits); - add_builtin_constant(instructions, state, "gl_MaxTextureImageUnits", + add_builtin_constant(instructions, symtab, "gl_MaxTextureImageUnits", state->Const.MaxTextureImageUnits); - add_builtin_constant(instructions, state, "gl_MaxFragmentUniformVectors", + add_builtin_constant(instructions, symtab, "gl_MaxFragmentUniformVectors", state->Const.MaxFragmentUniformComponents); - add_uniform(instructions, state, "gl_DepthRange", + add_uniform(instructions, symtab, "gl_DepthRange", state->symbols->get_type("gl_DepthRangeParameters")); } @@ -135,95 +427,97 @@ static void generate_110_uniforms(exec_list *instructions, struct _mesa_glsl_parse_state *state) { + glsl_symbol_table *const symtab = state->symbols; + for (unsigned i = 0 ; i < Elements(builtin_110_deprecated_uniforms) ; i++) { - add_builtin_variable(& builtin_110_deprecated_uniforms[i], - instructions, state->symbols); + add_builtin_variable(instructions, symtab, + & builtin_110_deprecated_uniforms[i]); } - add_builtin_constant(instructions, state, "gl_MaxLights", + add_builtin_constant(instructions, symtab, "gl_MaxLights", state->Const.MaxLights); - add_builtin_constant(instructions, state, "gl_MaxClipPlanes", + add_builtin_constant(instructions, symtab, "gl_MaxClipPlanes", state->Const.MaxClipPlanes); - add_builtin_constant(instructions, state, "gl_MaxTextureUnits", + add_builtin_constant(instructions, symtab, "gl_MaxTextureUnits", state->Const.MaxTextureUnits); - add_builtin_constant(instructions, state, "gl_MaxTextureCoords", + add_builtin_constant(instructions, symtab, "gl_MaxTextureCoords", state->Const.MaxTextureCoords); - add_builtin_constant(instructions, state, "gl_MaxVertexAttribs", + add_builtin_constant(instructions, symtab, "gl_MaxVertexAttribs", state->Const.MaxVertexAttribs); - add_builtin_constant(instructions, state, "gl_MaxVertexUniformComponents", + add_builtin_constant(instructions, symtab, "gl_MaxVertexUniformComponents", state->Const.MaxVertexUniformComponents); - add_builtin_constant(instructions, state, "gl_MaxVaryingFloats", + add_builtin_constant(instructions, symtab, "gl_MaxVaryingFloats", state->Const.MaxVaryingFloats); - add_builtin_constant(instructions, state, "gl_MaxVertexTextureImageUnits", + add_builtin_constant(instructions, symtab, "gl_MaxVertexTextureImageUnits", state->Const.MaxVertexTextureImageUnits); - add_builtin_constant(instructions, state, "gl_MaxCombinedTextureImageUnits", + add_builtin_constant(instructions, symtab, "gl_MaxCombinedTextureImageUnits", state->Const.MaxCombinedTextureImageUnits); - add_builtin_constant(instructions, state, "gl_MaxTextureImageUnits", + add_builtin_constant(instructions, symtab, "gl_MaxTextureImageUnits", state->Const.MaxTextureImageUnits); - add_builtin_constant(instructions, state, "gl_MaxFragmentUniformComponents", + add_builtin_constant(instructions, symtab, "gl_MaxFragmentUniformComponents", state->Const.MaxFragmentUniformComponents); const glsl_type *const mat4_array_type = glsl_type::get_array_instance(glsl_type::mat4_type, state->Const.MaxTextureCoords); - add_uniform(instructions, state, "gl_TextureMatrix", mat4_array_type); - add_uniform(instructions, state, "gl_TextureMatrixInverse", mat4_array_type); - add_uniform(instructions, state, "gl_TextureMatrixTranspose", mat4_array_type); - add_uniform(instructions, state, "gl_TextureMatrixInverseTranspose", mat4_array_type); + add_uniform(instructions, symtab, "gl_TextureMatrix", mat4_array_type); + add_uniform(instructions, symtab, "gl_TextureMatrixInverse", mat4_array_type); + add_uniform(instructions, symtab, "gl_TextureMatrixTranspose", mat4_array_type); + add_uniform(instructions, symtab, "gl_TextureMatrixInverseTranspose", mat4_array_type); - add_uniform(instructions, state, "gl_DepthRange", - state->symbols->get_type("gl_DepthRangeParameters")); + add_uniform(instructions, symtab, "gl_DepthRange", + symtab->get_type("gl_DepthRangeParameters")); - add_uniform(instructions, state, "gl_ClipPlane", + add_uniform(instructions, symtab, "gl_ClipPlane", glsl_type::get_array_instance(glsl_type::vec4_type, state->Const.MaxClipPlanes)); - add_uniform(instructions, state, "gl_Point", - state->symbols->get_type("gl_PointParameters")); + add_uniform(instructions, symtab, "gl_Point", + symtab->get_type("gl_PointParameters")); const glsl_type *const material_parameters_type = - state->symbols->get_type("gl_MaterialParameters"); - add_uniform(instructions, state, "gl_FrontMaterial", material_parameters_type); - add_uniform(instructions, state, "gl_BackMaterial", material_parameters_type); + symtab->get_type("gl_MaterialParameters"); + add_uniform(instructions, symtab, "gl_FrontMaterial", material_parameters_type); + add_uniform(instructions, symtab, "gl_BackMaterial", material_parameters_type); const glsl_type *const light_source_array_type = - glsl_type::get_array_instance(state->symbols->get_type("gl_LightSourceParameters"), state->Const.MaxLights); + glsl_type::get_array_instance(symtab->get_type("gl_LightSourceParameters"), state->Const.MaxLights); - add_uniform(instructions, state, "gl_LightSource", light_source_array_type); + add_uniform(instructions, symtab, "gl_LightSource", light_source_array_type); const glsl_type *const light_model_products_type = - state->symbols->get_type("gl_LightModelProducts"); - add_uniform(instructions, state, "gl_FrontLightModelProduct", + symtab->get_type("gl_LightModelProducts"); + add_uniform(instructions, symtab, "gl_FrontLightModelProduct", light_model_products_type); - add_uniform(instructions, state, "gl_BackLightModelProduct", + add_uniform(instructions, symtab, "gl_BackLightModelProduct", light_model_products_type); const glsl_type *const light_products_type = - glsl_type::get_array_instance(state->symbols->get_type("gl_LightProducts"), + glsl_type::get_array_instance(symtab->get_type("gl_LightProducts"), state->Const.MaxLights); - add_uniform(instructions, state, "gl_FrontLightProduct", light_products_type); - add_uniform(instructions, state, "gl_BackLightProduct", light_products_type); + add_uniform(instructions, symtab, "gl_FrontLightProduct", light_products_type); + add_uniform(instructions, symtab, "gl_BackLightProduct", light_products_type); - add_uniform(instructions, state, "gl_TextureEnvColor", + add_uniform(instructions, symtab, "gl_TextureEnvColor", glsl_type::get_array_instance(glsl_type::vec4_type, state->Const.MaxTextureUnits)); const glsl_type *const texcoords_vec4 = glsl_type::get_array_instance(glsl_type::vec4_type, state->Const.MaxTextureCoords); - add_uniform(instructions, state, "gl_EyePlaneS", texcoords_vec4); - add_uniform(instructions, state, "gl_EyePlaneT", texcoords_vec4); - add_uniform(instructions, state, "gl_EyePlaneR", texcoords_vec4); - add_uniform(instructions, state, "gl_EyePlaneQ", texcoords_vec4); - add_uniform(instructions, state, "gl_ObjectPlaneS", texcoords_vec4); - add_uniform(instructions, state, "gl_ObjectPlaneT", texcoords_vec4); - add_uniform(instructions, state, "gl_ObjectPlaneR", texcoords_vec4); - add_uniform(instructions, state, "gl_ObjectPlaneQ", texcoords_vec4); - - add_uniform(instructions, state, "gl_Fog", - state->symbols->get_type("gl_FogParameters")); + add_uniform(instructions, symtab, "gl_EyePlaneS", texcoords_vec4); + add_uniform(instructions, symtab, "gl_EyePlaneT", texcoords_vec4); + add_uniform(instructions, symtab, "gl_EyePlaneR", texcoords_vec4); + add_uniform(instructions, symtab, "gl_EyePlaneQ", texcoords_vec4); + add_uniform(instructions, symtab, "gl_ObjectPlaneS", texcoords_vec4); + add_uniform(instructions, symtab, "gl_ObjectPlaneT", texcoords_vec4); + add_uniform(instructions, symtab, "gl_ObjectPlaneR", texcoords_vec4); + add_uniform(instructions, symtab, "gl_ObjectPlaneQ", texcoords_vec4); + + add_uniform(instructions, symtab, "gl_Fog", + symtab->get_type("gl_FogParameters")); } /* This function should only be called for ES, not desktop GL. */ @@ -232,8 +526,8 @@ generate_100ES_vs_variables(exec_list *instructions, struct _mesa_glsl_parse_state *state) { for (unsigned i = 0; i < Elements(builtin_core_vs_variables); i++) { - add_builtin_variable(& builtin_core_vs_variables[i], - instructions, state->symbols); + add_builtin_variable(instructions, state->symbols, + & builtin_core_vs_variables[i]); } generate_100ES_uniforms(instructions, state); @@ -248,15 +542,15 @@ generate_110_vs_variables(exec_list *instructions, struct _mesa_glsl_parse_state *state) { for (unsigned i = 0; i < Elements(builtin_core_vs_variables); i++) { - add_builtin_variable(& builtin_core_vs_variables[i], - instructions, state->symbols); + add_builtin_variable(instructions, state->symbols, + & builtin_core_vs_variables[i]); } for (unsigned i = 0 ; i < Elements(builtin_110_deprecated_vs_variables) ; i++) { - add_builtin_variable(& builtin_110_deprecated_vs_variables[i], - instructions, state->symbols); + add_builtin_variable(instructions, state->symbols, + & builtin_110_deprecated_vs_variables[i]); } generate_110_uniforms(instructions, state); @@ -271,8 +565,8 @@ generate_110_vs_variables(exec_list *instructions, const glsl_type *const vec4_array_type = glsl_type::get_array_instance(glsl_type::vec4_type, 0); - add_variable("gl_TexCoord", ir_var_out, VERT_RESULT_TEX0, vec4_array_type, - instructions, state->symbols); + add_variable(instructions, state->symbols, + "gl_TexCoord", vec4_array_type, ir_var_out, VERT_RESULT_TEX0); generate_ARB_draw_buffers_variables(instructions, state, false, vertex_shader); @@ -297,8 +591,8 @@ generate_130_vs_variables(exec_list *instructions, generate_120_vs_variables(instructions, state); for (unsigned i = 0; i < Elements(builtin_130_vs_variables); i++) { - add_builtin_variable(& builtin_130_vs_variables[i], - instructions, state->symbols); + add_builtin_variable(instructions, state->symbols, + & builtin_130_vs_variables[i]); } const glsl_type *const clip_distance_array_type = @@ -306,8 +600,8 @@ generate_130_vs_variables(exec_list *instructions, state->Const.MaxClipPlanes); /* FINISHME: gl_ClipDistance needs a real location assigned. */ - add_variable("gl_ClipDistance", ir_var_out, -1, clip_distance_array_type, - instructions, state->symbols); + add_variable(instructions, state->symbols, + "gl_ClipDistance", clip_distance_array_type, ir_var_out, -1); } @@ -344,13 +638,13 @@ generate_100ES_fs_variables(exec_list *instructions, struct _mesa_glsl_parse_state *state) { for (unsigned i = 0; i < Elements(builtin_core_fs_variables); i++) { - add_builtin_variable(& builtin_core_fs_variables[i], - instructions, state->symbols); + add_builtin_variable(instructions, state->symbols, + & builtin_core_fs_variables[i]); } for (unsigned i = 0; i < Elements(builtin_100ES_fs_variables); i++) { - add_builtin_variable(& builtin_100ES_fs_variables[i], - instructions, state->symbols); + add_builtin_variable(instructions, state->symbols, + & builtin_100ES_fs_variables[i]); } generate_100ES_uniforms(instructions, state); @@ -364,20 +658,20 @@ generate_110_fs_variables(exec_list *instructions, struct _mesa_glsl_parse_state *state) { for (unsigned i = 0; i < Elements(builtin_core_fs_variables); i++) { - add_builtin_variable(& builtin_core_fs_variables[i], - instructions, state->symbols); + add_builtin_variable(instructions, state->symbols, + & builtin_core_fs_variables[i]); } for (unsigned i = 0; i < Elements(builtin_110_fs_variables); i++) { - add_builtin_variable(& builtin_110_fs_variables[i], - instructions, state->symbols); + add_builtin_variable(instructions, state->symbols, + & builtin_110_fs_variables[i]); } for (unsigned i = 0 ; i < Elements(builtin_110_deprecated_fs_variables) ; i++) { - add_builtin_variable(& builtin_110_deprecated_fs_variables[i], - instructions, state->symbols); + add_builtin_variable(instructions, state->symbols, + & builtin_110_deprecated_fs_variables[i]); } generate_110_uniforms(instructions, state); @@ -392,8 +686,8 @@ generate_110_fs_variables(exec_list *instructions, const glsl_type *const vec4_array_type = glsl_type::get_array_instance(glsl_type::vec4_type, 0); - add_variable("gl_TexCoord", ir_var_in, FRAG_ATTRIB_TEX0, vec4_array_type, - instructions, state->symbols); + add_variable(instructions, state->symbols, + "gl_TexCoord", vec4_array_type, ir_var_in, FRAG_ATTRIB_TEX0); generate_ARB_draw_buffers_variables(instructions, state, false, fragment_shader); @@ -408,8 +702,8 @@ generate_ARB_draw_buffers_variables(exec_list *instructions, /* gl_MaxDrawBuffers is available in all shader stages. */ ir_variable *const mdb = - add_variable("gl_MaxDrawBuffers", ir_var_auto, -1, - glsl_type::int_type, instructions, state->symbols); + add_variable(instructions, state->symbols, + "gl_MaxDrawBuffers", glsl_type::int_type, ir_var_auto, -1); if (warn) mdb->warn_extension = "GL_ARB_draw_buffers"; @@ -426,8 +720,9 @@ generate_ARB_draw_buffers_variables(exec_list *instructions, state->Const.MaxDrawBuffers); ir_variable *const fd = - add_variable("gl_FragData", ir_var_out, FRAG_RESULT_DATA0, - vec4_array_type, instructions, state->symbols); + add_variable(instructions, state->symbols, + "gl_FragData", vec4_array_type, + ir_var_out, FRAG_RESULT_DATA0); if (warn) fd->warn_extension = "GL_ARB_draw_buffers"; @@ -445,9 +740,9 @@ generate_ARB_draw_instanced_variables(exec_list *instructions, */ if (target == vertex_shader) { ir_variable *const inst = - add_variable("gl_InstanceIDARB", ir_var_system_value, - SYSTEM_VALUE_INSTANCE_ID, - glsl_type::int_type, instructions, state->symbols); + add_variable(instructions, state->symbols, + "gl_InstanceIDARB", glsl_type::int_type, + ir_var_system_value, SYSTEM_VALUE_INSTANCE_ID); if (warn) inst->warn_extension = "GL_ARB_draw_instanced"; @@ -463,8 +758,9 @@ generate_ARB_shader_stencil_export_variables(exec_list *instructions, /* gl_FragStencilRefARB is only available in the fragment shader. */ ir_variable *const fd = - add_variable("gl_FragStencilRefARB", ir_var_out, FRAG_RESULT_STENCIL, - glsl_type::int_type, instructions, state->symbols); + add_variable(instructions, state->symbols, + "gl_FragStencilRefARB", glsl_type::int_type, + ir_var_out, FRAG_RESULT_STENCIL); if (warn) fd->warn_extension = "GL_ARB_shader_stencil_export"; @@ -479,8 +775,8 @@ generate_120_fs_variables(exec_list *instructions, for (unsigned i = 0 ; i < Elements(builtin_120_fs_variables) ; i++) { - add_builtin_variable(& builtin_120_fs_variables[i], - instructions, state->symbols); + add_builtin_variable(instructions, state->symbols, + & builtin_120_fs_variables[i]); } } @@ -495,8 +791,8 @@ generate_130_fs_variables(exec_list *instructions, state->Const.MaxClipPlanes); /* FINISHME: gl_ClipDistance needs a real location assigned. */ - add_variable("gl_ClipDistance", ir_var_in, -1, clip_distance_array_type, - instructions, state->symbols); + add_variable(instructions, state->symbols, + "gl_ClipDistance", clip_distance_array_type, ir_var_in, -1); } static void diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp index 7db5c5e8d53..17492357f2d 100644 --- a/src/glsl/linker.cpp +++ b/src/glsl/linker.cpp @@ -994,6 +994,19 @@ update_array_sizes(struct gl_shader_program *prog) } if (size + 1 != 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 + * is not known. It seems saft to assume that the total number of + * slots is an integer multiple of the number of array elements. + * Determine the number of slots per array element by dividing by + * the old (total) size. + */ + if (var->num_state_slots > 0) { + var->num_state_slots = (size + 1) + * (var->num_state_slots / var->type->length); + } + var->type = glsl_type::get_array_instance(var->type->fields.array, size + 1); /* FINISHME: We should update the types of array diff --git a/src/glsl/opt_copy_propagation_elements.cpp b/src/glsl/opt_copy_propagation_elements.cpp index 8541d9a8ee1..a91e624cb72 100644 --- a/src/glsl/opt_copy_propagation_elements.cpp +++ b/src/glsl/opt_copy_propagation_elements.cpp @@ -161,9 +161,16 @@ ir_visitor_status ir_copy_propagation_elements_visitor::visit_leave(ir_assignment *ir) { ir_dereference_variable *lhs = ir->lhs->as_dereference_variable(); + ir_variable *var = ir->lhs->variable_referenced(); + + if (var->type->is_scalar() || var->type->is_vector()) { + kill_entry *k; + + if (lhs) + k = new(mem_ctx) kill_entry(var, ir->write_mask); + else + k = new(mem_ctx) kill_entry(var, ~0); - if (lhs && (lhs->type->is_scalar() || lhs->type->is_vector())) { - kill_entry *k = new(mem_ctx) kill_entry(lhs->var, ir->write_mask); kill(k); } @@ -383,8 +390,10 @@ ir_copy_propagation_elements_visitor::kill(kill_entry *k) if (entry->lhs == k->var) { entry->write_mask = entry->write_mask & ~k->write_mask; - if (entry->write_mask == 0) + if (entry->write_mask == 0) { entry->remove(); + continue; + } } if (entry->rhs == k->var) { entry->remove(); |