summaryrefslogtreecommitdiffstats
path: root/src/glsl
diff options
context:
space:
mode:
Diffstat (limited to 'src/glsl')
-rw-r--r--src/glsl/ast_function.cpp6
-rw-r--r--src/glsl/ast_to_hir.cpp217
-rw-r--r--src/glsl/glcpp/glcpp-parse.y82
-rw-r--r--src/glsl/glcpp/tests/084-unbalanced-parentheses.c.expected2
-rw-r--r--src/glsl/glcpp/tests/093-divide-by-zero.c.expected4
-rw-r--r--src/glsl/glcpp/tests/094-divide-by-zero-short-circuit.c11
-rw-r--r--src/glsl/glcpp/tests/094-divide-by-zero-short-circuit.c.expected15
-rw-r--r--src/glsl/glcpp/tests/095-recursive-define.c.expected4
-rwxr-xr-xsrc/glsl/glcpp/tests/glcpp-test62
-rw-r--r--src/glsl/glsl_parser_extras.cpp27
-rw-r--r--src/glsl/glsl_parser_extras.h4
-rw-r--r--src/glsl/ir.h26
-rw-r--r--src/glsl/ir_clone.cpp12
-rw-r--r--src/glsl/ir_print_visitor.cpp45
-rw-r--r--src/glsl/ir_print_visitor.h29
-rw-r--r--src/glsl/ir_validate.cpp21
-rw-r--r--src/glsl/ir_variable.cpp508
-rw-r--r--src/glsl/linker.cpp13
-rw-r--r--src/glsl/opt_copy_propagation_elements.cpp15
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();