aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/glsl
diff options
context:
space:
mode:
authormarha <marha@users.sourceforge.net>2014-01-26 20:19:23 +0100
committermarha <marha@users.sourceforge.net>2014-01-26 20:19:23 +0100
commit5f455179ae4b279a82d99a7a3dabe61f58c42ad6 (patch)
treefdecec022cf1b8b782b90a64c14e374fa6d400cb /mesalib/src/glsl
parent78d84bd03c744b0ed420c450dd2807904ccaef21 (diff)
parent30af30b78075159fce477ae99cc72540133714d0 (diff)
downloadvcxsrv-5f455179ae4b279a82d99a7a3dabe61f58c42ad6.tar.gz
vcxsrv-5f455179ae4b279a82d99a7a3dabe61f58c42ad6.tar.bz2
vcxsrv-5f455179ae4b279a82d99a7a3dabe61f58c42ad6.zip
Merge remote-tracking branch 'origin/released'
* origin/released: xserver randrproto libxtrans fontconfig libxcb xcb-proto mesa git update 26 Jan 2014 Conflicts: X11/xtrans/Xtrans.c xorg-server/dix/dispatch.c xorg-server/os/xdmcp.c
Diffstat (limited to 'mesalib/src/glsl')
-rw-r--r--mesalib/src/glsl/Makefile.sources1
-rw-r--r--mesalib/src/glsl/ast.h102
-rw-r--r--mesalib/src/glsl/ast_array_index.cpp13
-rw-r--r--mesalib/src/glsl/ast_function.cpp8
-rw-r--r--mesalib/src/glsl/ast_to_hir.cpp231
-rw-r--r--mesalib/src/glsl/ast_type.cpp10
-rwxr-xr-xmesalib/src/glsl/builtin_functions.cpp137
-rw-r--r--mesalib/src/glsl/builtin_variables.cpp2
-rw-r--r--mesalib/src/glsl/glcpp/glcpp-parse.y301
-rw-r--r--mesalib/src/glsl/glcpp/glcpp.c1
-rw-r--r--mesalib/src/glsl/glcpp/glcpp.h7
-rw-r--r--mesalib/src/glsl/glcpp/pp.c4
-rw-r--r--mesalib/src/glsl/glsl_parser.yy173
-rw-r--r--mesalib/src/glsl/glsl_parser_extras.cpp173
-rw-r--r--mesalib/src/glsl/glsl_parser_extras.h4
-rw-r--r--mesalib/src/glsl/glsl_types.cpp83
-rw-r--r--mesalib/src/glsl/glsl_types.h7
-rw-r--r--mesalib/src/glsl/ir.h14
-rw-r--r--mesalib/src/glsl/ir_equals.cpp60
-rw-r--r--mesalib/src/glsl/ir_optimization.h1
-rw-r--r--mesalib/src/glsl/link_atomics.cpp3
-rw-r--r--mesalib/src/glsl/linker.cpp120
-rw-r--r--mesalib/src/glsl/opt_algebraic.cpp52
-rw-r--r--mesalib/src/glsl/opt_vectorize.cpp319
-rw-r--r--mesalib/src/glsl/standalone_scaffolding.cpp1
25 files changed, 1094 insertions, 733 deletions
diff --git a/mesalib/src/glsl/Makefile.sources b/mesalib/src/glsl/Makefile.sources
index 2e81dedda..e69c1ac61 100644
--- a/mesalib/src/glsl/Makefile.sources
+++ b/mesalib/src/glsl/Makefile.sources
@@ -99,6 +99,7 @@ LIBGLSL_FILES = \
$(GLSL_SRCDIR)/opt_structure_splitting.cpp \
$(GLSL_SRCDIR)/opt_swizzle_swizzle.cpp \
$(GLSL_SRCDIR)/opt_tree_grafting.cpp \
+ $(GLSL_SRCDIR)/opt_vectorize.cpp \
$(GLSL_SRCDIR)/s_expression.cpp \
$(GLSL_SRCDIR)/strtod.c
diff --git a/mesalib/src/glsl/ast.h b/mesalib/src/glsl/ast.h
index 344277803..502490200 100644
--- a/mesalib/src/glsl/ast.h
+++ b/mesalib/src/glsl/ast.h
@@ -280,6 +280,43 @@ private:
bool cons;
};
+class ast_array_specifier : public ast_node {
+public:
+ /** Unsized array specifier ([]) */
+ explicit ast_array_specifier(const struct YYLTYPE &locp)
+ : dimension_count(1), is_unsized_array(true)
+ {
+ set_location(locp);
+ }
+
+ /** Sized array specifier ([dim]) */
+ ast_array_specifier(const struct YYLTYPE &locp, ast_expression *dim)
+ : dimension_count(1), is_unsized_array(false)
+ {
+ set_location(locp);
+ array_dimensions.push_tail(&dim->link);
+ }
+
+ void add_dimension(ast_expression *dim)
+ {
+ array_dimensions.push_tail(&dim->link);
+ dimension_count++;
+ }
+
+ virtual void print(void) const;
+
+ /* Count including sized and unsized dimensions */
+ unsigned dimension_count;
+
+ /* If true, this means that the array has an unsized outermost dimension. */
+ bool is_unsized_array;
+
+ /* This list contains objects of type ast_node containing the
+ * sized dimensions only, in outermost-to-innermost order.
+ */
+ exec_list array_dimensions;
+};
+
/**
* C-style aggregate initialization class
*
@@ -300,7 +337,16 @@ public:
/* empty */
}
- ast_type_specifier *constructor_type;
+ /**
+ * glsl_type of the aggregate, which is inferred from the LHS of whatever
+ * the aggregate is being used to initialize. This can't be inferred at
+ * parse time (since the parser deals with ast_type_specifiers, not
+ * glsl_types), so the parser leaves it NULL. However, the ast-to-hir
+ * conversion code makes sure to fill it in with the appropriate type
+ * before hir() is called.
+ */
+ const glsl_type *constructor_type;
+
virtual ir_rvalue *hir(exec_list *instructions,
struct _mesa_glsl_parse_state *state);
};
@@ -329,14 +375,14 @@ public:
class ast_declaration : public ast_node {
public:
- ast_declaration(const char *identifier, bool is_array, ast_expression *array_size,
- ast_expression *initializer);
+ ast_declaration(const char *identifier,
+ ast_array_specifier *array_specifier,
+ ast_expression *initializer);
virtual void print(void) const;
const char *identifier;
-
- bool is_array;
- ast_expression *array_size;
+
+ ast_array_specifier *array_specifier;
ast_expression *initializer;
};
@@ -545,10 +591,10 @@ public:
* Use only if the objects are allocated from the same context and will not
* be modified. Zeros the inherited ast_node's fields.
*/
- ast_type_specifier(const ast_type_specifier *that, bool is_array,
- ast_expression *array_size)
+ ast_type_specifier(const ast_type_specifier *that,
+ ast_array_specifier *array_specifier)
: ast_node(), type_name(that->type_name), structure(that->structure),
- is_array(is_array), array_size(array_size),
+ array_specifier(array_specifier),
default_precision(that->default_precision)
{
/* empty */
@@ -556,8 +602,7 @@ public:
/** Construct a type specifier from a type name */
ast_type_specifier(const char *name)
- : type_name(name), structure(NULL),
- is_array(false), array_size(NULL),
+ : type_name(name), structure(NULL), array_specifier(NULL),
default_precision(ast_precision_none)
{
/* empty */
@@ -565,8 +610,7 @@ public:
/** Construct a type specifier from a structure definition */
ast_type_specifier(ast_struct_specifier *s)
- : type_name(s->name), structure(s),
- is_array(false), array_size(NULL),
+ : type_name(s->name), structure(s), array_specifier(NULL),
default_precision(ast_precision_none)
{
/* empty */
@@ -583,8 +627,7 @@ public:
const char *type_name;
ast_struct_specifier *structure;
- bool is_array;
- ast_expression *array_size;
+ ast_array_specifier *array_specifier;
/** For precision statements, this is the given precision; otherwise none. */
unsigned default_precision:2;
@@ -637,8 +680,7 @@ public:
ast_parameter_declarator() :
type(NULL),
identifier(NULL),
- is_array(false),
- array_size(NULL),
+ array_specifier(NULL),
formal_parameter(false),
is_void(false)
{
@@ -652,8 +694,7 @@ public:
ast_fully_specified_type *type;
const char *identifier;
- bool is_array;
- ast_expression *array_size;
+ ast_array_specifier *array_specifier;
static void parameters_to_hir(exec_list *ast_parameters,
bool formal, exec_list *ir_parameters,
@@ -900,13 +941,10 @@ class ast_interface_block : public ast_node {
public:
ast_interface_block(ast_type_qualifier layout,
const char *instance_name,
- bool is_array,
- ast_expression *array_size)
+ ast_array_specifier *array_specifier)
: layout(layout), block_name(NULL), instance_name(instance_name),
- is_array(is_array), array_size(array_size)
+ array_specifier(array_specifier)
{
- if (!is_array)
- assert(array_size == NULL);
}
virtual ir_rvalue *hir(exec_list *instructions,
@@ -927,21 +965,12 @@ public:
exec_list declarations;
/**
- * True if the block is declared as an array
- *
- * \note
- * A block can only be an array if it also has an instance name. If this
- * field is true, ::instance_name must also not be \c NULL.
- */
- bool is_array;
-
- /**
* Declared array size of the block instance
*
* If the block is not declared as an array or if the block instance array
* is unsized, this field will be \c NULL.
*/
- ast_expression *array_size;
+ ast_array_specifier *array_specifier;
};
@@ -982,9 +1011,8 @@ _mesa_ast_array_index_to_hir(void *mem_ctx,
YYLTYPE &loc, YYLTYPE &idx_loc);
extern void
-_mesa_ast_set_aggregate_type(const ast_type_specifier *type,
- ast_expression *expr,
- _mesa_glsl_parse_state *state);
+_mesa_ast_set_aggregate_type(const glsl_type *type,
+ ast_expression *expr);
void
emit_function(_mesa_glsl_parse_state *state, ir_function *f);
diff --git a/mesalib/src/glsl/ast_array_index.cpp b/mesalib/src/glsl/ast_array_index.cpp
index a5f23206a..f3b060ea6 100644
--- a/mesalib/src/glsl/ast_array_index.cpp
+++ b/mesalib/src/glsl/ast_array_index.cpp
@@ -25,6 +25,19 @@
#include "glsl_types.h"
#include "ir.h"
+void
+ast_array_specifier::print(void) const
+{
+ if (this->is_unsized_array) {
+ printf("[ ] ");
+ }
+
+ foreach_list_typed (ast_node, array_dimension, link, &this->array_dimensions) {
+ printf("[ ");
+ array_dimension->print();
+ printf("] ");
+ }
+}
/**
* If \c ir is a reference to an array for which we are tracking the max array
diff --git a/mesalib/src/glsl/ast_function.cpp b/mesalib/src/glsl/ast_function.cpp
index 2d05d0723..4c5b0e4aa 100644
--- a/mesalib/src/glsl/ast_function.cpp
+++ b/mesalib/src/glsl/ast_function.cpp
@@ -1687,14 +1687,12 @@ ast_aggregate_initializer::hir(exec_list *instructions,
{
void *ctx = state;
YYLTYPE loc = this->get_location();
- const char *name;
if (!this->constructor_type) {
_mesa_glsl_error(&loc, state, "type of C-style initializer unknown");
return ir_rvalue::error_value(ctx);
}
- const glsl_type *const constructor_type =
- this->constructor_type->glsl_type(&name, state);
+ const glsl_type *const constructor_type = this->constructor_type;
if (!state->ARB_shading_language_420pack_enable) {
_mesa_glsl_error(&loc, state, "C-style initialization requires the "
@@ -1702,12 +1700,12 @@ ast_aggregate_initializer::hir(exec_list *instructions,
return ir_rvalue::error_value(ctx);
}
- if (this->constructor_type->is_array) {
+ if (constructor_type->is_array()) {
return process_array_constructor(instructions, constructor_type, &loc,
&this->expressions, state);
}
- if (this->constructor_type->structure) {
+ if (constructor_type->is_record()) {
return process_record_constructor(instructions, constructor_type, &loc,
&this->expressions, state);
}
diff --git a/mesalib/src/glsl/ast_to_hir.cpp b/mesalib/src/glsl/ast_to_hir.cpp
index 4cc8eb18d..1bfb4e531 100644
--- a/mesalib/src/glsl/ast_to_hir.cpp
+++ b/mesalib/src/glsl/ast_to_hir.cpp
@@ -740,14 +740,15 @@ do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state,
{
void *ctx = state;
bool error_emitted = (lhs->type->is_error() || rhs->type->is_error());
+ ir_rvalue *extract_channel = NULL;
/* If the assignment LHS comes back as an ir_binop_vector_extract
* expression, move it to the RHS as an ir_triop_vector_insert.
*/
if (lhs->ir_type == ir_type_expression) {
- ir_expression *const expr = lhs->as_expression();
+ ir_expression *const lhs_expr = lhs->as_expression();
- if (unlikely(expr->operation == ir_binop_vector_extract)) {
+ if (unlikely(lhs_expr->operation == ir_binop_vector_extract)) {
ir_rvalue *new_rhs =
validate_assignment(state, lhs_loc, lhs->type,
rhs, is_initializer);
@@ -755,12 +756,24 @@ do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state,
if (new_rhs == NULL) {
return lhs;
} else {
+ /* This converts:
+ * - LHS: (expression float vector_extract <vec> <channel>)
+ * - RHS: <scalar>
+ * into:
+ * - LHS: <vec>
+ * - RHS: (expression vec2 vector_insert <vec> <channel> <scalar>)
+ *
+ * The LHS type is now a vector instead of a scalar. Since GLSL
+ * allows assignments to be used as rvalues, we need to re-extract
+ * the channel from assignment_temp when returning the rvalue.
+ */
+ extract_channel = lhs_expr->operands[1];
rhs = new(ctx) ir_expression(ir_triop_vector_insert,
- expr->operands[0]->type,
- expr->operands[0],
+ lhs_expr->operands[0]->type,
+ lhs_expr->operands[0],
new_rhs,
- expr->operands[1]);
- lhs = expr->operands[0]->clone(ctx, NULL);
+ extract_channel);
+ lhs = lhs_expr->operands[0]->clone(ctx, NULL);
}
}
}
@@ -830,8 +843,10 @@ do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state,
rhs->type->array_size());
d->type = var->type;
}
- mark_whole_array_access(rhs);
- mark_whole_array_access(lhs);
+ if (lhs->type->is_array()) {
+ mark_whole_array_access(rhs);
+ mark_whole_array_access(lhs);
+ }
}
/* Most callers of do_assignment (assign, add_assign, pre_inc/dec,
@@ -854,6 +869,11 @@ do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state,
if (!error_emitted)
instructions->push_tail(new(ctx) ir_assignment(lhs, deref_var));
+ if (extract_channel) {
+ return new(ctx) ir_expression(ir_binop_vector_extract,
+ new(ctx) ir_dereference_variable(var),
+ extract_channel->clone(ctx, NULL));
+ }
return new(ctx) ir_dereference_variable(var);
}
@@ -1771,64 +1791,108 @@ ast_compound_statement::hir(exec_list *instructions,
return NULL;
}
+/**
+ * Evaluate the given exec_node (which should be an ast_node representing
+ * a single array dimension) and return its integer value.
+ */
+static const unsigned
+process_array_size(exec_node *node,
+ struct _mesa_glsl_parse_state *state)
+{
+ exec_list dummy_instructions;
+
+ ast_node *array_size = exec_node_data(ast_node, node, link);
+ ir_rvalue *const ir = array_size->hir(& dummy_instructions,
+ state);
+ YYLTYPE loc = array_size->get_location();
+
+ if (ir == NULL) {
+ _mesa_glsl_error(& loc, state,
+ "array size could not be resolved");
+ return 0;
+ }
+
+ if (!ir->type->is_integer()) {
+ _mesa_glsl_error(& loc, state,
+ "array size must be integer type");
+ return 0;
+ }
+
+ if (!ir->type->is_scalar()) {
+ _mesa_glsl_error(& loc, state,
+ "array size must be scalar type");
+ return 0;
+ }
+
+ ir_constant *const size = ir->constant_expression_value();
+ if (size == NULL) {
+ _mesa_glsl_error(& loc, state, "array size must be a "
+ "constant valued expression");
+ return 0;
+ }
+
+ if (size->value.i[0] <= 0) {
+ _mesa_glsl_error(& loc, state, "array size must be > 0");
+ return 0;
+ }
+
+ assert(size->type == ir->type);
+
+ /* If the array size is const (and we've verified that
+ * it is) then no instructions should have been emitted
+ * when we converted it to HIR. If they were emitted,
+ * then either the array size isn't const after all, or
+ * we are emitting unnecessary instructions.
+ */
+ assert(dummy_instructions.is_empty());
+
+ return size->value.u[0];
+}
static const glsl_type *
-process_array_type(YYLTYPE *loc, const glsl_type *base, ast_node *array_size,
- struct _mesa_glsl_parse_state *state)
+process_array_type(YYLTYPE *loc, const glsl_type *base,
+ ast_array_specifier *array_specifier,
+ struct _mesa_glsl_parse_state *state)
{
- unsigned length = 0;
+ const glsl_type *array_type = base;
- if (base == NULL)
- return glsl_type::error_type;
+ if (array_specifier != NULL) {
+ if (base->is_array()) {
- /* From page 19 (page 25) of the GLSL 1.20 spec:
- *
- * "Only one-dimensional arrays may be declared."
- */
- if (base->is_array()) {
- _mesa_glsl_error(loc, state,
- "invalid array of `%s' (only one-dimensional arrays "
- "may be declared)",
- base->name);
- return glsl_type::error_type;
- }
+ /* From page 19 (page 25) of the GLSL 1.20 spec:
+ *
+ * "Only one-dimensional arrays may be declared."
+ */
+ if (!state->ARB_arrays_of_arrays_enable) {
+ _mesa_glsl_error(loc, state,
+ "invalid array of `%s'"
+ "GL_ARB_arrays_of_arrays "
+ "required for defining arrays of arrays",
+ base->name);
+ return glsl_type::error_type;
+ }
- if (array_size != NULL) {
- exec_list dummy_instructions;
- ir_rvalue *const ir = array_size->hir(& dummy_instructions, state);
- YYLTYPE loc = array_size->get_location();
+ if (base->length == 0) {
+ _mesa_glsl_error(loc, state,
+ "only the outermost array dimension can "
+ "be unsized",
+ base->name);
+ return glsl_type::error_type;
+ }
+ }
- if (ir != NULL) {
- if (!ir->type->is_integer()) {
- _mesa_glsl_error(& loc, state, "array size must be integer type");
- } else if (!ir->type->is_scalar()) {
- _mesa_glsl_error(& loc, state, "array size must be scalar type");
- } else {
- ir_constant *const size = ir->constant_expression_value();
-
- if (size == NULL) {
- _mesa_glsl_error(& loc, state, "array size must be a "
- "constant valued expression");
- } else if (size->value.i[0] <= 0) {
- _mesa_glsl_error(& loc, state, "array size must be > 0");
- } else {
- assert(size->type == ir->type);
- length = size->value.u[0];
-
- /* If the array size is const (and we've verified that
- * it is) then no instructions should have been emitted
- * when we converted it to HIR. If they were emitted,
- * then either the array size isn't const after all, or
- * we are emitting unnecessary instructions.
- */
- assert(dummy_instructions.is_empty());
- }
- }
+ for (exec_node *node = array_specifier->array_dimensions.tail_pred;
+ !node->is_head_sentinel(); node = node->prev) {
+ unsigned array_size = process_array_size(node, state);
+ array_type = glsl_type::get_array_instance(array_type,
+ array_size);
}
+
+ if (array_specifier->is_unsized_array)
+ array_type = glsl_type::get_array_instance(array_type, 0);
}
- const glsl_type *array_type = glsl_type::get_array_instance(base, length);
- return array_type != NULL ? array_type : glsl_type::error_type;
+ return array_type;
}
@@ -1841,10 +1905,8 @@ ast_type_specifier::glsl_type(const char **name,
type = state->symbols->get_type(this->type_name);
*name = this->type_name;
- if (this->is_array) {
- YYLTYPE loc = this->get_location();
- type = process_array_type(&loc, type, this->array_size, state);
- }
+ YYLTYPE loc = this->get_location();
+ type = process_array_type(&loc, type, this->array_specifier, state);
return type;
}
@@ -2593,6 +2655,13 @@ process_initializer(ir_variable *var, ast_declaration *decl,
? "attribute" : "varying");
}
+ /* If the initializer is an ast_aggregate_initializer, recursively store
+ * type information from the LHS into it, so that its hir() function can do
+ * type checking.
+ */
+ if (decl->initializer->oper == ast_aggregate)
+ _mesa_ast_set_aggregate_type(var->type, decl->initializer);
+
ir_dereference *const lhs = new(state) ir_dereference_variable(var);
ir_rvalue *rhs = decl->initializer->hir(initializer_instructions,
state);
@@ -2823,8 +2892,7 @@ ast_declarator_list::hir(exec_list *instructions,
}
foreach_list_typed (ast_declaration, decl, link, &this->declarations) {
- assert(!decl->is_array);
- assert(decl->array_size == NULL);
+ assert(decl->array_specifier == NULL);
assert(decl->initializer == NULL);
ir_variable *const earlier =
@@ -2959,14 +3027,8 @@ ast_declarator_list::hir(exec_list *instructions,
continue;
}
- if (decl->is_array) {
- var_type = process_array_type(&loc, decl_type, decl->array_size,
- state);
- if (var_type->is_error())
- continue;
- } else {
- var_type = decl_type;
- }
+ var_type = process_array_type(&loc, decl_type, decl->array_specifier,
+ state);
var = new(ctx) ir_variable(var_type, decl->identifier, ir_var_auto);
@@ -3098,8 +3160,9 @@ ast_declarator_list::hir(exec_list *instructions,
* vectors. Vertex shader inputs cannot be arrays or
* structures."
*/
- const glsl_type *check_type = var->type->is_array()
- ? var->type->fields.array : var->type;
+ const glsl_type *check_type = var->type;
+ while (check_type->is_array())
+ check_type = check_type->element_type();
switch (check_type->base_type) {
case GLSL_TYPE_FLOAT:
@@ -3523,9 +3586,7 @@ ast_parameter_declarator::hir(exec_list *instructions,
/* This only handles "vec4 foo[..]". The earlier specifier->glsl_type(...)
* call already handled the "vec4[..] foo" case.
*/
- if (this->is_array) {
- type = process_array_type(&loc, type, this->array_size, state);
- }
+ type = process_array_type(&loc, type, this->array_specifier, state);
if (!type->is_error() && type->is_unsized_array()) {
_mesa_glsl_error(&loc, state, "arrays passed as parameters must have "
@@ -4463,7 +4524,7 @@ ast_type_specifier::hir(exec_list *instructions,
return NULL;
}
- if (this->is_array) {
+ if (this->array_specifier != NULL) {
_mesa_glsl_error(&loc, state,
"default precision statements do not apply to "
"arrays");
@@ -4653,10 +4714,8 @@ ast_process_structure_or_interface_block(exec_list *instructions,
"members");
}
- if (decl->is_array) {
- field_type = process_array_type(&loc, decl_type, decl->array_size,
- state);
- }
+ field_type = process_array_type(&loc, decl_type,
+ decl->array_specifier, state);
fields[i].type = field_type;
fields[i].name = decl->identifier;
fields[i].location = -1;
@@ -4882,7 +4941,7 @@ ast_interface_block::hir(exec_list *instructions,
_mesa_shader_stage_to_string(state->stage));
}
if (this->instance_name == NULL ||
- strcmp(this->instance_name, "gl_in") != 0 || !this->is_array) {
+ strcmp(this->instance_name, "gl_in") != 0 || this->array_specifier == NULL) {
_mesa_glsl_error(&loc, state,
"gl_PerVertex input must be redeclared as "
"gl_in[]");
@@ -4984,7 +5043,7 @@ ast_interface_block::hir(exec_list *instructions,
* variable (or input block, see interface blocks below) needs to be
* declared as an array.
*/
- if (state->stage == MESA_SHADER_GEOMETRY && !this->is_array &&
+ if (state->stage == MESA_SHADER_GEOMETRY && this->array_specifier == NULL &&
var_mode == ir_var_shader_in) {
_mesa_glsl_error(&loc, state, "geometry shader inputs must be arrays");
}
@@ -5018,7 +5077,7 @@ ast_interface_block::hir(exec_list *instructions,
ir_variable *var;
- if (this->is_array) {
+ if (this->array_specifier != NULL) {
/* Section 4.3.7 (Interface Blocks) of the GLSL 1.50 spec says:
*
* For uniform blocks declared an array, each individual array
@@ -5038,7 +5097,7 @@ ast_interface_block::hir(exec_list *instructions,
* interface array size *doesn't* need to be specified is on a
* geometry shader input.
*/
- if (this->array_size == NULL &&
+ if (this->array_specifier->is_unsized_array &&
(state->stage != MESA_SHADER_GEOMETRY || !this->layout.flags.q.in)) {
_mesa_glsl_error(&loc, state,
"only geometry shader inputs may be unsized "
@@ -5047,7 +5106,7 @@ ast_interface_block::hir(exec_list *instructions,
}
const glsl_type *block_array_type =
- process_array_type(&loc, block_type, this->array_size, state);
+ process_array_type(&loc, block_type, this->array_specifier, state);
var = new(state) ir_variable(block_array_type,
this->instance_name,
@@ -5079,7 +5138,7 @@ ast_interface_block::hir(exec_list *instructions,
/* In order to have an array size, the block must also be declared with
* an instane name.
*/
- assert(!this->is_array);
+ assert(this->array_specifier == NULL);
for (unsigned i = 0; i < num_variables; i++) {
ir_variable *var =
diff --git a/mesalib/src/glsl/ast_type.cpp b/mesalib/src/glsl/ast_type.cpp
index d758bfa1f..637da0dfb 100644
--- a/mesalib/src/glsl/ast_type.cpp
+++ b/mesalib/src/glsl/ast_type.cpp
@@ -32,14 +32,8 @@ ast_type_specifier::print(void) const
printf("%s ", type_name);
}
- if (is_array) {
- printf("[ ");
-
- if (array_size) {
- array_size->print();
- }
-
- printf("] ");
+ if (array_specifier) {
+ array_specifier->print();
}
}
diff --git a/mesalib/src/glsl/builtin_functions.cpp b/mesalib/src/glsl/builtin_functions.cpp
index b1065f48d..ed58ddddb 100755
--- a/mesalib/src/glsl/builtin_functions.cpp
+++ b/mesalib/src/glsl/builtin_functions.cpp
@@ -576,20 +576,9 @@ private:
ir_function_signature *_atomic_op(const char *intrinsic,
builtin_available_predicate avail);
- ir_function_signature *_min3(builtin_available_predicate avail,
- const glsl_type *x_type,
- const glsl_type *y_type,
- const glsl_type *z_type);
-
- ir_function_signature *_max3(builtin_available_predicate avail,
- const glsl_type *x_type,
- const glsl_type *y_type,
- const glsl_type *z_type);
-
- ir_function_signature *_mid3(builtin_available_predicate avail,
- const glsl_type *x_type,
- const glsl_type *y_type,
- const glsl_type *z_type);
+ B1(min3)
+ B1(max3)
+ B1(mid3)
#undef B0
#undef B1
@@ -2128,54 +2117,54 @@ builtin_builder::create_builtins()
NULL);
add_function("min3",
- _min3(shader_trinary_minmax, glsl_type::float_type, glsl_type::float_type, glsl_type::float_type),
- _min3(shader_trinary_minmax, glsl_type::vec2_type, glsl_type::vec2_type, glsl_type::vec2_type),
- _min3(shader_trinary_minmax, glsl_type::vec3_type, glsl_type::vec3_type, glsl_type::vec3_type),
- _min3(shader_trinary_minmax, glsl_type::vec4_type, glsl_type::vec4_type, glsl_type::vec4_type),
-
- _min3(shader_trinary_minmax, glsl_type::int_type, glsl_type::int_type, glsl_type::int_type),
- _min3(shader_trinary_minmax, glsl_type::ivec2_type, glsl_type::ivec2_type, glsl_type::ivec2_type),
- _min3(shader_trinary_minmax, glsl_type::ivec3_type, glsl_type::ivec3_type, glsl_type::ivec3_type),
- _min3(shader_trinary_minmax, glsl_type::ivec4_type, glsl_type::ivec4_type, glsl_type::ivec4_type),
-
- _min3(shader_trinary_minmax, glsl_type::uint_type, glsl_type::uint_type, glsl_type::uint_type),
- _min3(shader_trinary_minmax, glsl_type::uvec2_type, glsl_type::uvec2_type, glsl_type::uvec2_type),
- _min3(shader_trinary_minmax, glsl_type::uvec3_type, glsl_type::uvec3_type, glsl_type::uvec3_type),
- _min3(shader_trinary_minmax, glsl_type::uvec4_type, glsl_type::uvec4_type, glsl_type::uvec4_type),
+ _min3(glsl_type::float_type),
+ _min3(glsl_type::vec2_type),
+ _min3(glsl_type::vec3_type),
+ _min3(glsl_type::vec4_type),
+
+ _min3(glsl_type::int_type),
+ _min3(glsl_type::ivec2_type),
+ _min3(glsl_type::ivec3_type),
+ _min3(glsl_type::ivec4_type),
+
+ _min3(glsl_type::uint_type),
+ _min3(glsl_type::uvec2_type),
+ _min3(glsl_type::uvec3_type),
+ _min3(glsl_type::uvec4_type),
NULL);
add_function("max3",
- _max3(shader_trinary_minmax, glsl_type::float_type, glsl_type::float_type, glsl_type::float_type),
- _max3(shader_trinary_minmax, glsl_type::vec2_type, glsl_type::vec2_type, glsl_type::vec2_type),
- _max3(shader_trinary_minmax, glsl_type::vec3_type, glsl_type::vec3_type, glsl_type::vec3_type),
- _max3(shader_trinary_minmax, glsl_type::vec4_type, glsl_type::vec4_type, glsl_type::vec4_type),
-
- _max3(shader_trinary_minmax, glsl_type::int_type, glsl_type::int_type, glsl_type::int_type),
- _max3(shader_trinary_minmax, glsl_type::ivec2_type, glsl_type::ivec2_type, glsl_type::ivec2_type),
- _max3(shader_trinary_minmax, glsl_type::ivec3_type, glsl_type::ivec3_type, glsl_type::ivec3_type),
- _max3(shader_trinary_minmax, glsl_type::ivec4_type, glsl_type::ivec4_type, glsl_type::ivec4_type),
-
- _max3(shader_trinary_minmax, glsl_type::uint_type, glsl_type::uint_type, glsl_type::uint_type),
- _max3(shader_trinary_minmax, glsl_type::uvec2_type, glsl_type::uvec2_type, glsl_type::uvec2_type),
- _max3(shader_trinary_minmax, glsl_type::uvec3_type, glsl_type::uvec3_type, glsl_type::uvec3_type),
- _max3(shader_trinary_minmax, glsl_type::uvec4_type, glsl_type::uvec4_type, glsl_type::uvec4_type),
+ _max3(glsl_type::float_type),
+ _max3(glsl_type::vec2_type),
+ _max3(glsl_type::vec3_type),
+ _max3(glsl_type::vec4_type),
+
+ _max3(glsl_type::int_type),
+ _max3(glsl_type::ivec2_type),
+ _max3(glsl_type::ivec3_type),
+ _max3(glsl_type::ivec4_type),
+
+ _max3(glsl_type::uint_type),
+ _max3(glsl_type::uvec2_type),
+ _max3(glsl_type::uvec3_type),
+ _max3(glsl_type::uvec4_type),
NULL);
add_function("mid3",
- _mid3(shader_trinary_minmax, glsl_type::float_type, glsl_type::float_type, glsl_type::float_type),
- _mid3(shader_trinary_minmax, glsl_type::vec2_type, glsl_type::vec2_type, glsl_type::vec2_type),
- _mid3(shader_trinary_minmax, glsl_type::vec3_type, glsl_type::vec3_type, glsl_type::vec3_type),
- _mid3(shader_trinary_minmax, glsl_type::vec4_type, glsl_type::vec4_type, glsl_type::vec4_type),
-
- _mid3(shader_trinary_minmax, glsl_type::int_type, glsl_type::int_type, glsl_type::int_type),
- _mid3(shader_trinary_minmax, glsl_type::ivec2_type, glsl_type::ivec2_type, glsl_type::ivec2_type),
- _mid3(shader_trinary_minmax, glsl_type::ivec3_type, glsl_type::ivec3_type, glsl_type::ivec3_type),
- _mid3(shader_trinary_minmax, glsl_type::ivec4_type, glsl_type::ivec4_type, glsl_type::ivec4_type),
-
- _mid3(shader_trinary_minmax, glsl_type::uint_type, glsl_type::uint_type, glsl_type::uint_type),
- _mid3(shader_trinary_minmax, glsl_type::uvec2_type, glsl_type::uvec2_type, glsl_type::uvec2_type),
- _mid3(shader_trinary_minmax, glsl_type::uvec3_type, glsl_type::uvec3_type, glsl_type::uvec3_type),
- _mid3(shader_trinary_minmax, glsl_type::uvec4_type, glsl_type::uvec4_type, glsl_type::uvec4_type),
+ _mid3(glsl_type::float_type),
+ _mid3(glsl_type::vec2_type),
+ _mid3(glsl_type::vec3_type),
+ _mid3(glsl_type::vec4_type),
+
+ _mid3(glsl_type::int_type),
+ _mid3(glsl_type::ivec2_type),
+ _mid3(glsl_type::ivec3_type),
+ _mid3(glsl_type::ivec4_type),
+
+ _mid3(glsl_type::uint_type),
+ _mid3(glsl_type::uvec2_type),
+ _mid3(glsl_type::uvec3_type),
+ _mid3(glsl_type::uvec4_type),
NULL);
#undef F
@@ -4064,14 +4053,12 @@ builtin_builder::_atomic_op(const char *intrinsic,
}
ir_function_signature *
-builtin_builder::_min3(builtin_available_predicate avail,
- const glsl_type *x_type, const glsl_type *y_type,
- const glsl_type *z_type)
+builtin_builder::_min3(const glsl_type *type)
{
- ir_variable *x = in_var(x_type, "x");
- ir_variable *y = in_var(y_type, "y");
- ir_variable *z = in_var(z_type, "z");
- MAKE_SIG(x_type, avail, 3, x, y, z);
+ ir_variable *x = in_var(type, "x");
+ ir_variable *y = in_var(type, "y");
+ ir_variable *z = in_var(type, "z");
+ MAKE_SIG(type, shader_trinary_minmax, 3, x, y, z);
ir_expression *min3 = min2(x, min2(y,z));
body.emit(ret(min3));
@@ -4080,14 +4067,12 @@ builtin_builder::_min3(builtin_available_predicate avail,
}
ir_function_signature *
-builtin_builder::_max3(builtin_available_predicate avail,
- const glsl_type *x_type, const glsl_type *y_type,
- const glsl_type *z_type)
+builtin_builder::_max3(const glsl_type *type)
{
- ir_variable *x = in_var(x_type, "x");
- ir_variable *y = in_var(y_type, "y");
- ir_variable *z = in_var(z_type, "z");
- MAKE_SIG(x_type, avail, 3, x, y, z);
+ ir_variable *x = in_var(type, "x");
+ ir_variable *y = in_var(type, "y");
+ ir_variable *z = in_var(type, "z");
+ MAKE_SIG(type, shader_trinary_minmax, 3, x, y, z);
ir_expression *max3 = max2(x, max2(y,z));
body.emit(ret(max3));
@@ -4096,14 +4081,12 @@ builtin_builder::_max3(builtin_available_predicate avail,
}
ir_function_signature *
-builtin_builder::_mid3(builtin_available_predicate avail,
- const glsl_type *x_type, const glsl_type *y_type,
- const glsl_type *z_type)
+builtin_builder::_mid3(const glsl_type *type)
{
- ir_variable *x = in_var(x_type, "x");
- ir_variable *y = in_var(y_type, "y");
- ir_variable *z = in_var(z_type, "z");
- MAKE_SIG(x_type, avail, 3, x, y, z);
+ ir_variable *x = in_var(type, "x");
+ ir_variable *y = in_var(type, "y");
+ ir_variable *z = in_var(type, "z");
+ MAKE_SIG(type, shader_trinary_minmax, 3, x, y, z);
ir_expression *mid3 = max2(min2(x, y), max2(min2(x, z), min2(y, z)));
body.emit(ret(mid3));
diff --git a/mesalib/src/glsl/builtin_variables.cpp b/mesalib/src/glsl/builtin_variables.cpp
index f630923ed..d6bc3c073 100644
--- a/mesalib/src/glsl/builtin_variables.cpp
+++ b/mesalib/src/glsl/builtin_variables.cpp
@@ -780,6 +780,8 @@ void
builtin_variable_generator::generate_gs_special_vars()
{
add_output(VARYING_SLOT_LAYER, int_t, "gl_Layer");
+ if (state->ARB_viewport_array_enable)
+ add_output(VARYING_SLOT_VIEWPORT, int_t, "gl_ViewportIndex");
/* Although gl_PrimitiveID appears in tessellation control and tessellation
* evaluation shaders, it has a different function there than it has in
diff --git a/mesalib/src/glsl/glcpp/glcpp-parse.y b/mesalib/src/glsl/glcpp/glcpp-parse.y
index 55c498195..184e5c237 100644
--- a/mesalib/src/glsl/glcpp/glcpp-parse.y
+++ b/mesalib/src/glsl/glcpp/glcpp-parse.y
@@ -30,7 +30,6 @@
#include "glcpp.h"
#include "main/core.h" /* for struct gl_extensions */
-#include "main/mtypes.h" /* for gl_api enum */
static void
yyerror (YYLTYPE *locp, glcpp_parser_t *parser, const char *error);
@@ -135,7 +134,7 @@ _glcpp_parser_skip_stack_pop (glcpp_parser_t *parser, YYLTYPE *loc);
static void
_glcpp_parser_handle_version_declaration(glcpp_parser_t *parser, intmax_t version,
- const char *ident);
+ const char *ident, bool explicitly_set);
static int
glcpp_parser_lex (YYSTYPE *yylval, YYLTYPE *yylloc, glcpp_parser_t *parser);
@@ -194,12 +193,15 @@ line:
control_line {
ralloc_asprintf_rewrite_tail (&parser->output, &parser->output_length, "\n");
}
-| HASH_LINE pp_tokens NEWLINE {
+| HASH_LINE {
+ glcpp_parser_resolve_version(parser);
+ } pp_tokens NEWLINE {
+
if (parser->skip_stack == NULL ||
parser->skip_stack->type == SKIP_NO_SKIP)
{
_glcpp_parser_expand_and_lex_from (parser,
- LINE_EXPANDED, $2);
+ LINE_EXPANDED, $3);
}
}
| text_line {
@@ -238,25 +240,35 @@ expanded_line:
}
;
-control_line:
- HASH_DEFINE OBJ_IDENTIFIER replacement_list NEWLINE {
- _define_object_macro (parser, & @2, $2, $3);
+define:
+ OBJ_IDENTIFIER replacement_list NEWLINE {
+ _define_object_macro (parser, & @1, $1, $2);
}
-| HASH_DEFINE FUNC_IDENTIFIER '(' ')' replacement_list NEWLINE {
- _define_function_macro (parser, & @2, $2, NULL, $5);
+| FUNC_IDENTIFIER '(' ')' replacement_list NEWLINE {
+ _define_function_macro (parser, & @1, $1, NULL, $4);
}
-| HASH_DEFINE FUNC_IDENTIFIER '(' identifier_list ')' replacement_list NEWLINE {
- _define_function_macro (parser, & @2, $2, $4, $6);
+| FUNC_IDENTIFIER '(' identifier_list ')' replacement_list NEWLINE {
+ _define_function_macro (parser, & @1, $1, $3, $5);
}
-| HASH_UNDEF IDENTIFIER NEWLINE {
- macro_t *macro = hash_table_find (parser->defines, $2);
+;
+
+control_line:
+ HASH_DEFINE {
+ glcpp_parser_resolve_version(parser);
+ } define
+| HASH_UNDEF {
+ glcpp_parser_resolve_version(parser);
+ } IDENTIFIER NEWLINE {
+ macro_t *macro = hash_table_find (parser->defines, $3);
if (macro) {
- hash_table_remove (parser->defines, $2);
+ hash_table_remove (parser->defines, $3);
ralloc_free (macro);
}
- ralloc_free ($2);
+ ralloc_free ($3);
}
-| HASH_IF conditional_tokens NEWLINE {
+| HASH_IF {
+ glcpp_parser_resolve_version(parser);
+ } conditional_tokens NEWLINE {
/* Be careful to only evaluate the 'if' expression if
* we are not skipping. When we are skipping, we
* simply push a new 0-valued 'if' onto the skip
@@ -268,7 +280,7 @@ control_line:
parser->skip_stack->type == SKIP_NO_SKIP)
{
_glcpp_parser_expand_and_lex_from (parser,
- IF_EXPANDED, $2);
+ IF_EXPANDED, $3);
}
else
{
@@ -286,15 +298,19 @@ control_line:
}
_glcpp_parser_skip_stack_push_if (parser, & @1, 0);
}
-| HASH_IFDEF IDENTIFIER junk NEWLINE {
- macro_t *macro = hash_table_find (parser->defines, $2);
- ralloc_free ($2);
+| HASH_IFDEF {
+ glcpp_parser_resolve_version(parser);
+ } IDENTIFIER junk NEWLINE {
+ macro_t *macro = hash_table_find (parser->defines, $3);
+ ralloc_free ($3);
_glcpp_parser_skip_stack_push_if (parser, & @1, macro != NULL);
}
-| HASH_IFNDEF IDENTIFIER junk NEWLINE {
- macro_t *macro = hash_table_find (parser->defines, $2);
- ralloc_free ($2);
- _glcpp_parser_skip_stack_push_if (parser, & @1, macro == NULL);
+| HASH_IFNDEF {
+ glcpp_parser_resolve_version(parser);
+ } IDENTIFIER junk NEWLINE {
+ macro_t *macro = hash_table_find (parser->defines, $3);
+ ralloc_free ($3);
+ _glcpp_parser_skip_stack_push_if (parser, & @2, macro == NULL);
}
| HASH_ELIF conditional_tokens NEWLINE {
/* Be careful to only evaluate the 'elif' expression
@@ -358,12 +374,14 @@ control_line:
_glcpp_parser_skip_stack_pop (parser, & @1);
} NEWLINE
| HASH_VERSION integer_constant NEWLINE {
- _glcpp_parser_handle_version_declaration(parser, $2, NULL);
+ _glcpp_parser_handle_version_declaration(parser, $2, NULL, true);
}
| HASH_VERSION integer_constant IDENTIFIER NEWLINE {
- _glcpp_parser_handle_version_declaration(parser, $2, $3);
+ _glcpp_parser_handle_version_declaration(parser, $2, $3, true);
+ }
+| HASH NEWLINE {
+ glcpp_parser_resolve_version(parser);
}
-| HASH NEWLINE
;
integer_constant:
@@ -1168,10 +1186,9 @@ static void add_builtin_define(glcpp_parser_t *parser,
}
glcpp_parser_t *
-glcpp_parser_create (const struct gl_extensions *extensions, int api)
+glcpp_parser_create (const struct gl_extensions *extensions)
{
glcpp_parser_t *parser;
- int language_version;
parser = ralloc (NULL, glcpp_parser_t);
@@ -1197,99 +1214,14 @@ glcpp_parser_create (const struct gl_extensions *extensions, int api)
parser->info_log_length = 0;
parser->error = 0;
+ parser->extensions = extensions;
+ parser->version_resolved = false;
+
parser->has_new_line_number = 0;
parser->new_line_number = 1;
parser->has_new_source_number = 0;
parser->new_source_number = 0;
- parser->is_gles = false;
-
- /* Add pre-defined macros. */
- if (api == API_OPENGLES2) {
- parser->is_gles = true;
- add_builtin_define(parser, "GL_ES", 1);
-
- if (extensions != NULL) {
- if (extensions->OES_EGL_image_external)
- add_builtin_define(parser, "GL_OES_EGL_image_external", 1);
- }
- } else {
- add_builtin_define(parser, "GL_ARB_draw_buffers", 1);
- add_builtin_define(parser, "GL_ARB_texture_rectangle", 1);
-
- if (extensions != NULL) {
- if (extensions->EXT_texture_array) {
- add_builtin_define(parser, "GL_EXT_texture_array", 1);
- }
-
- if (extensions->ARB_fragment_coord_conventions)
- add_builtin_define(parser, "GL_ARB_fragment_coord_conventions",
- 1);
-
- if (extensions->ARB_explicit_attrib_location)
- add_builtin_define(parser, "GL_ARB_explicit_attrib_location", 1);
-
- if (extensions->ARB_shader_texture_lod)
- add_builtin_define(parser, "GL_ARB_shader_texture_lod", 1);
-
- if (extensions->ARB_draw_instanced)
- add_builtin_define(parser, "GL_ARB_draw_instanced", 1);
-
- if (extensions->ARB_conservative_depth) {
- add_builtin_define(parser, "GL_AMD_conservative_depth", 1);
- add_builtin_define(parser, "GL_ARB_conservative_depth", 1);
- }
-
- if (extensions->ARB_shader_bit_encoding)
- add_builtin_define(parser, "GL_ARB_shader_bit_encoding", 1);
-
- if (extensions->ARB_uniform_buffer_object)
- add_builtin_define(parser, "GL_ARB_uniform_buffer_object", 1);
-
- if (extensions->ARB_texture_cube_map_array)
- add_builtin_define(parser, "GL_ARB_texture_cube_map_array", 1);
-
- if (extensions->ARB_shading_language_packing)
- add_builtin_define(parser, "GL_ARB_shading_language_packing", 1);
-
- if (extensions->ARB_texture_multisample)
- add_builtin_define(parser, "GL_ARB_texture_multisample", 1);
-
- if (extensions->ARB_texture_query_levels)
- add_builtin_define(parser, "GL_ARB_texture_query_levels", 1);
-
- if (extensions->ARB_texture_query_lod)
- add_builtin_define(parser, "GL_ARB_texture_query_lod", 1);
-
- if (extensions->ARB_gpu_shader5)
- add_builtin_define(parser, "GL_ARB_gpu_shader5", 1);
-
- if (extensions->AMD_vertex_shader_layer)
- add_builtin_define(parser, "GL_AMD_vertex_shader_layer", 1);
-
- if (extensions->ARB_shading_language_420pack)
- add_builtin_define(parser, "GL_ARB_shading_language_420pack", 1);
-
- if (extensions->ARB_sample_shading)
- add_builtin_define(parser, "GL_ARB_sample_shading", 1);
-
- if (extensions->EXT_shader_integer_mix)
- add_builtin_define(parser, "GL_EXT_shader_integer_mix", 1);
-
- if (extensions->ARB_texture_gather)
- add_builtin_define(parser, "GL_ARB_texture_gather", 1);
-
- if (extensions->ARB_shader_atomic_counters)
- add_builtin_define(parser, "GL_ARB_shader_atomic_counters", 1);
-
- if (extensions->AMD_shader_trinary_minmax)
- add_builtin_define(parser, "GL_AMD_shader_trinary_minmax", 1);
- }
- }
-
- language_version = 110;
- add_builtin_define(parser, "__VERSION__", language_version);
-
return parser;
}
@@ -2087,24 +2019,106 @@ _glcpp_parser_skip_stack_pop (glcpp_parser_t *parser, YYLTYPE *loc)
static void
_glcpp_parser_handle_version_declaration(glcpp_parser_t *parser, intmax_t version,
- const char *es_identifier)
+ const char *es_identifier,
+ bool explicitly_set)
{
- macro_t *macro = hash_table_find (parser->defines, "__VERSION__");
- if (macro) {
- hash_table_remove (parser->defines, "__VERSION__");
- ralloc_free (macro);
- }
+ const struct gl_extensions *extensions = parser->extensions;
+
+ parser->version_resolved = true;
+
add_builtin_define (parser, "__VERSION__", version);
- /* If we didn't have a GLES context to begin with, (indicated
- * by parser->api), then the version declaration here might
- * indicate GLES. */
- if (! parser->is_gles &&
- (version == 100 ||
- (es_identifier && (strcmp(es_identifier, "es") == 0))))
- {
- parser->is_gles = true;
- add_builtin_define (parser, "GL_ES", 1);
+ parser->is_gles = (version == 100) ||
+ (es_identifier &&
+ (strcmp(es_identifier, "es") == 0));
+
+ /* Add pre-defined macros. */
+ if (parser->is_gles) {
+ add_builtin_define(parser, "GL_ES", 1);
+
+ if (extensions != NULL) {
+ if (extensions->OES_EGL_image_external)
+ add_builtin_define(parser, "GL_OES_EGL_image_external", 1);
+ }
+ } else {
+ add_builtin_define(parser, "GL_ARB_draw_buffers", 1);
+ add_builtin_define(parser, "GL_ARB_texture_rectangle", 1);
+
+ if (extensions != NULL) {
+ if (extensions->EXT_texture_array)
+ add_builtin_define(parser, "GL_EXT_texture_array", 1);
+
+ if (extensions->ARB_arrays_of_arrays)
+ add_builtin_define(parser, "GL_ARB_arrays_of_arrays", 1);
+
+ if (extensions->ARB_fragment_coord_conventions)
+ add_builtin_define(parser, "GL_ARB_fragment_coord_conventions",
+ 1);
+
+ if (extensions->ARB_explicit_attrib_location)
+ add_builtin_define(parser, "GL_ARB_explicit_attrib_location", 1);
+
+ if (extensions->ARB_shader_texture_lod)
+ add_builtin_define(parser, "GL_ARB_shader_texture_lod", 1);
+
+ if (extensions->ARB_draw_instanced)
+ add_builtin_define(parser, "GL_ARB_draw_instanced", 1);
+
+ if (extensions->ARB_conservative_depth) {
+ add_builtin_define(parser, "GL_AMD_conservative_depth", 1);
+ add_builtin_define(parser, "GL_ARB_conservative_depth", 1);
+ }
+
+ if (extensions->ARB_shader_bit_encoding)
+ add_builtin_define(parser, "GL_ARB_shader_bit_encoding", 1);
+
+ if (extensions->ARB_uniform_buffer_object)
+ add_builtin_define(parser, "GL_ARB_uniform_buffer_object", 1);
+
+ if (extensions->ARB_texture_cube_map_array)
+ add_builtin_define(parser, "GL_ARB_texture_cube_map_array", 1);
+
+ if (extensions->ARB_shading_language_packing)
+ add_builtin_define(parser, "GL_ARB_shading_language_packing", 1);
+
+ if (extensions->ARB_texture_multisample)
+ add_builtin_define(parser, "GL_ARB_texture_multisample", 1);
+
+ if (extensions->ARB_texture_query_levels)
+ add_builtin_define(parser, "GL_ARB_texture_query_levels", 1);
+
+ if (extensions->ARB_texture_query_lod)
+ add_builtin_define(parser, "GL_ARB_texture_query_lod", 1);
+
+ if (extensions->ARB_gpu_shader5)
+ add_builtin_define(parser, "GL_ARB_gpu_shader5", 1);
+
+ if (extensions->AMD_vertex_shader_layer)
+ add_builtin_define(parser, "GL_AMD_vertex_shader_layer", 1);
+
+ if (extensions->ARB_shading_language_420pack)
+ add_builtin_define(parser, "GL_ARB_shading_language_420pack", 1);
+
+ if (extensions->ARB_sample_shading)
+ add_builtin_define(parser, "GL_ARB_sample_shading", 1);
+
+ if (extensions->ARB_texture_gather)
+ add_builtin_define(parser, "GL_ARB_texture_gather", 1);
+
+ if (extensions->ARB_shader_atomic_counters)
+ add_builtin_define(parser, "GL_ARB_shader_atomic_counters", 1);
+
+ if (extensions->AMD_shader_trinary_minmax)
+ add_builtin_define(parser, "GL_AMD_shader_trinary_minmax", 1);
+
+ if (extensions->ARB_viewport_array)
+ add_builtin_define(parser, "GL_ARB_viewport_array", 1);
+ }
+ }
+
+ if (extensions != NULL) {
+ if (extensions->EXT_shader_integer_mix)
+ add_builtin_define(parser, "GL_EXT_shader_integer_mix", 1);
}
if (version >= 150)
@@ -2118,8 +2132,23 @@ _glcpp_parser_handle_version_declaration(glcpp_parser_t *parser, intmax_t versio
if (version >= 130 || parser->is_gles)
add_builtin_define (parser, "GL_FRAGMENT_PRECISION_HIGH", 1);
- ralloc_asprintf_rewrite_tail (&parser->output, &parser->output_length,
- "#version %" PRIiMAX "%s%s", version,
- es_identifier ? " " : "",
- es_identifier ? es_identifier : "");
+ if (explicitly_set) {
+ ralloc_asprintf_rewrite_tail (&parser->output, &parser->output_length,
+ "#version %" PRIiMAX "%s%s", version,
+ es_identifier ? " " : "",
+ es_identifier ? es_identifier : "");
+ }
+}
+
+/* GLSL version is no version is explicitly specified. */
+#define IMPLICIT_GLSL_VERSION 110
+
+void
+glcpp_parser_resolve_version(glcpp_parser_t *parser)
+{
+ if (parser->version_resolved)
+ return;
+
+ _glcpp_parser_handle_version_declaration(parser, IMPLICIT_GLSL_VERSION,
+ NULL, false);
}
diff --git a/mesalib/src/glsl/glcpp/glcpp.c b/mesalib/src/glsl/glcpp/glcpp.c
index 13a32fd7d..b632f1715 100644
--- a/mesalib/src/glsl/glcpp/glcpp.c
+++ b/mesalib/src/glsl/glcpp/glcpp.c
@@ -109,7 +109,6 @@ load_text_file(void *ctx, const char *filename)
static void
init_fake_gl_context (struct gl_context *gl_ctx)
{
- gl_ctx->API = API_OPENGL_COMPAT;
gl_ctx->Const.DisableGLSLLineContinuations = false;
}
diff --git a/mesalib/src/glsl/glcpp/glcpp.h b/mesalib/src/glsl/glcpp/glcpp.h
index 85f3fdcd2..4aa200a63 100644
--- a/mesalib/src/glsl/glcpp/glcpp.h
+++ b/mesalib/src/glsl/glcpp/glcpp.h
@@ -182,6 +182,8 @@ struct glcpp_parser {
size_t output_length;
size_t info_log_length;
int error;
+ const struct gl_extensions *extensions;
+ bool version_resolved;
bool has_new_line_number;
int new_line_number;
bool has_new_source_number;
@@ -192,7 +194,7 @@ struct glcpp_parser {
struct gl_extensions;
glcpp_parser_t *
-glcpp_parser_create (const struct gl_extensions *extensions, int api);
+glcpp_parser_create (const struct gl_extensions *extensions);
int
glcpp_parser_parse (glcpp_parser_t *parser);
@@ -200,6 +202,9 @@ glcpp_parser_parse (glcpp_parser_t *parser);
void
glcpp_parser_destroy (glcpp_parser_t *parser);
+void
+glcpp_parser_resolve_version(glcpp_parser_t *parser);
+
int
glcpp_preprocess(void *ralloc_ctx, const char **shader, char **info_log,
const struct gl_extensions *extensions, struct gl_context *g_ctx);
diff --git a/mesalib/src/glsl/glcpp/pp.c b/mesalib/src/glsl/glcpp/pp.c
index 7e1b6c689..637a58f9c 100644
--- a/mesalib/src/glsl/glcpp/pp.c
+++ b/mesalib/src/glsl/glcpp/pp.c
@@ -139,7 +139,7 @@ glcpp_preprocess(void *ralloc_ctx, const char **shader, char **info_log,
const struct gl_extensions *extensions, struct gl_context *gl_ctx)
{
int errors;
- glcpp_parser_t *parser = glcpp_parser_create (extensions, gl_ctx->API);
+ glcpp_parser_t *parser = glcpp_parser_create (extensions);
if (! gl_ctx->Const.DisableGLSLLineContinuations)
*shader = remove_line_continuations(parser, *shader);
@@ -151,6 +151,8 @@ glcpp_preprocess(void *ralloc_ctx, const char **shader, char **info_log,
if (parser->skip_stack)
glcpp_error (&parser->skip_stack->loc, parser, "Unterminated #if\n");
+ glcpp_parser_resolve_version(parser);
+
ralloc_strcat(info_log, parser->info_log);
ralloc_steal(ralloc_ctx, parser->output);
diff --git a/mesalib/src/glsl/glsl_parser.yy b/mesalib/src/glsl/glsl_parser.yy
index 52f674b63..5d8dfac02 100644
--- a/mesalib/src/glsl/glsl_parser.yy
+++ b/mesalib/src/glsl/glsl_parser.yy
@@ -98,6 +98,7 @@ static bool match_layout_qualifier(const char *s1, const char *s2,
ast_node *node;
ast_type_specifier *type_specifier;
+ ast_array_specifier *array_specifier;
ast_fully_specified_type *fully_specified_type;
ast_function *function;
ast_parameter_declarator *parameter_declarator;
@@ -203,6 +204,7 @@ static bool match_layout_qualifier(const char *s1, const char *s2,
%type <type_qualifier> interface_qualifier
%type <type_specifier> type_specifier
%type <type_specifier> type_specifier_nonarray
+%type <array_specifier> array_specifier
%type <identifier> basic_type_specifier_nonarray
%type <fully_specified_type> fully_specified_type
%type <function> function_prototype
@@ -881,7 +883,7 @@ parameter_declarator:
$$->type->specifier = $1;
$$->identifier = $2;
}
- | type_specifier any_identifier '[' constant_expression ']'
+ | type_specifier any_identifier array_specifier
{
void *ctx = state;
$$ = new(ctx) ast_parameter_declarator();
@@ -890,8 +892,7 @@ parameter_declarator:
$$->type->set_location(yylloc);
$$->type->specifier = $1;
$$->identifier = $2;
- $$->is_array = true;
- $$->array_size = $4;
+ $$->array_specifier = $3;
}
;
@@ -977,76 +978,42 @@ init_declarator_list:
| init_declarator_list ',' any_identifier
{
void *ctx = state;
- ast_declaration *decl = new(ctx) ast_declaration($3, false, NULL, NULL);
+ ast_declaration *decl = new(ctx) ast_declaration($3, NULL, NULL);
decl->set_location(yylloc);
$$ = $1;
$$->declarations.push_tail(&decl->link);
state->symbols->add_variable(new(state) ir_variable(NULL, $3, ir_var_auto));
}
- | init_declarator_list ',' any_identifier '[' ']'
+ | init_declarator_list ',' any_identifier array_specifier
{
void *ctx = state;
- ast_declaration *decl = new(ctx) ast_declaration($3, true, NULL, NULL);
+ ast_declaration *decl = new(ctx) ast_declaration($3, $4, NULL);
decl->set_location(yylloc);
$$ = $1;
$$->declarations.push_tail(&decl->link);
state->symbols->add_variable(new(state) ir_variable(NULL, $3, ir_var_auto));
}
- | init_declarator_list ',' any_identifier '[' constant_expression ']'
+ | init_declarator_list ',' any_identifier array_specifier '=' initializer
{
void *ctx = state;
- ast_declaration *decl = new(ctx) ast_declaration($3, true, $5, NULL);
+ ast_declaration *decl = new(ctx) ast_declaration($3, $4, $6);
decl->set_location(yylloc);
$$ = $1;
$$->declarations.push_tail(&decl->link);
state->symbols->add_variable(new(state) ir_variable(NULL, $3, ir_var_auto));
}
- | init_declarator_list ',' any_identifier '[' ']' '=' initializer
- {
- void *ctx = state;
- ast_declaration *decl = new(ctx) ast_declaration($3, true, NULL, $7);
- decl->set_location(yylloc);
-
- $$ = $1;
- $$->declarations.push_tail(&decl->link);
- state->symbols->add_variable(new(state) ir_variable(NULL, $3, ir_var_auto));
- if ($7->oper == ast_aggregate) {
- ast_aggregate_initializer *ai = (ast_aggregate_initializer *)$7;
- ast_type_specifier *type = new(ctx) ast_type_specifier($1->type->specifier, true, NULL);
- _mesa_ast_set_aggregate_type(type, ai, state);
- }
- }
- | init_declarator_list ',' any_identifier '[' constant_expression ']' '=' initializer
- {
- void *ctx = state;
- ast_declaration *decl = new(ctx) ast_declaration($3, true, $5, $8);
- decl->set_location(yylloc);
-
- $$ = $1;
- $$->declarations.push_tail(&decl->link);
- state->symbols->add_variable(new(state) ir_variable(NULL, $3, ir_var_auto));
- if ($8->oper == ast_aggregate) {
- ast_aggregate_initializer *ai = (ast_aggregate_initializer *)$8;
- ast_type_specifier *type = new(ctx) ast_type_specifier($1->type->specifier, true, $5);
- _mesa_ast_set_aggregate_type(type, ai, state);
- }
- }
| init_declarator_list ',' any_identifier '=' initializer
{
void *ctx = state;
- ast_declaration *decl = new(ctx) ast_declaration($3, false, NULL, $5);
+ ast_declaration *decl = new(ctx) ast_declaration($3, NULL, $5);
decl->set_location(yylloc);
$$ = $1;
$$->declarations.push_tail(&decl->link);
state->symbols->add_variable(new(state) ir_variable(NULL, $3, ir_var_auto));
- if ($5->oper == ast_aggregate) {
- ast_aggregate_initializer *ai = (ast_aggregate_initializer *)$5;
- _mesa_ast_set_aggregate_type($1->type->specifier, ai, state);
- }
}
;
@@ -1062,74 +1029,43 @@ single_declaration:
| fully_specified_type any_identifier
{
void *ctx = state;
- ast_declaration *decl = new(ctx) ast_declaration($2, false, NULL, NULL);
+ ast_declaration *decl = new(ctx) ast_declaration($2, NULL, NULL);
$$ = new(ctx) ast_declarator_list($1);
$$->set_location(yylloc);
$$->declarations.push_tail(&decl->link);
}
- | fully_specified_type any_identifier '[' ']'
+ | fully_specified_type any_identifier array_specifier
{
void *ctx = state;
- ast_declaration *decl = new(ctx) ast_declaration($2, true, NULL, NULL);
+ ast_declaration *decl = new(ctx) ast_declaration($2, $3, NULL);
$$ = new(ctx) ast_declarator_list($1);
$$->set_location(yylloc);
$$->declarations.push_tail(&decl->link);
}
- | fully_specified_type any_identifier '[' constant_expression ']'
+ | fully_specified_type any_identifier array_specifier '=' initializer
{
void *ctx = state;
- ast_declaration *decl = new(ctx) ast_declaration($2, true, $4, NULL);
+ ast_declaration *decl = new(ctx) ast_declaration($2, $3, $5);
$$ = new(ctx) ast_declarator_list($1);
$$->set_location(yylloc);
$$->declarations.push_tail(&decl->link);
}
- | fully_specified_type any_identifier '[' ']' '=' initializer
- {
- void *ctx = state;
- ast_declaration *decl = new(ctx) ast_declaration($2, true, NULL, $6);
-
- $$ = new(ctx) ast_declarator_list($1);
- $$->set_location(yylloc);
- $$->declarations.push_tail(&decl->link);
- if ($6->oper == ast_aggregate) {
- ast_aggregate_initializer *ai = (ast_aggregate_initializer *)$6;
- ast_type_specifier *type = new(ctx) ast_type_specifier($1->specifier, true, NULL);
- _mesa_ast_set_aggregate_type(type, ai, state);
- }
- }
- | fully_specified_type any_identifier '[' constant_expression ']' '=' initializer
- {
- void *ctx = state;
- ast_declaration *decl = new(ctx) ast_declaration($2, true, $4, $7);
-
- $$ = new(ctx) ast_declarator_list($1);
- $$->set_location(yylloc);
- $$->declarations.push_tail(&decl->link);
- if ($7->oper == ast_aggregate) {
- ast_aggregate_initializer *ai = (ast_aggregate_initializer *)$7;
- ast_type_specifier *type = new(ctx) ast_type_specifier($1->specifier, true, $4);
- _mesa_ast_set_aggregate_type(type, ai, state);
- }
- }
| fully_specified_type any_identifier '=' initializer
{
void *ctx = state;
- ast_declaration *decl = new(ctx) ast_declaration($2, false, NULL, $4);
+ ast_declaration *decl = new(ctx) ast_declaration($2, NULL, $4);
$$ = new(ctx) ast_declarator_list($1);
$$->set_location(yylloc);
$$->declarations.push_tail(&decl->link);
- if ($4->oper == ast_aggregate) {
- _mesa_ast_set_aggregate_type($1->specifier, $4, state);
- }
}
| INVARIANT variable_identifier // Vertex only.
{
void *ctx = state;
- ast_declaration *decl = new(ctx) ast_declaration($2, false, NULL, NULL);
+ ast_declaration *decl = new(ctx) ast_declaration($2, NULL, NULL);
$$ = new(ctx) ast_declarator_list(NULL);
$$->set_location(yylloc);
@@ -1612,19 +1548,51 @@ storage_qualifier:
}
;
-type_specifier:
- type_specifier_nonarray
- | type_specifier_nonarray '[' ']'
+array_specifier:
+ '[' ']'
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_array_specifier(yylloc);
+ }
+ | '[' constant_expression ']'
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_array_specifier(yylloc, $2);
+ }
+ | array_specifier '[' ']'
{
$$ = $1;
- $$->is_array = true;
- $$->array_size = NULL;
+
+ if (!state->ARB_arrays_of_arrays_enable) {
+ _mesa_glsl_error(& @1, state,
+ "GL_ARB_arrays_of_arrays "
+ "required for defining arrays of arrays");
+ } else {
+ _mesa_glsl_error(& @1, state,
+ "only the outermost array dimension can "
+ "be unsized");
+ }
}
- | type_specifier_nonarray '[' constant_expression ']'
+ | array_specifier '[' constant_expression ']'
{
$$ = $1;
- $$->is_array = true;
- $$->array_size = $3;
+
+ if (!state->ARB_arrays_of_arrays_enable) {
+ _mesa_glsl_error(& @1, state,
+ "GL_ARB_arrays_of_arrays "
+ "required for defining arrays of arrays");
+ }
+
+ $$->add_dimension($3);
+ }
+ ;
+
+type_specifier:
+ type_specifier_nonarray
+ | type_specifier_nonarray array_specifier
+ {
+ $$ = $1;
+ $$->array_specifier = $2;
}
;
@@ -1804,19 +1772,13 @@ struct_declarator:
any_identifier
{
void *ctx = state;
- $$ = new(ctx) ast_declaration($1, false, NULL, NULL);
- $$->set_location(yylloc);
- }
- | any_identifier '[' ']'
- {
- void *ctx = state;
- $$ = new(ctx) ast_declaration($1, true, NULL, NULL);
+ $$ = new(ctx) ast_declaration($1, NULL, NULL);
$$->set_location(yylloc);
}
- | any_identifier '[' constant_expression ']'
+ | any_identifier array_specifier
{
void *ctx = state;
- $$ = new(ctx) ast_declaration($1, true, $3, NULL);
+ $$ = new(ctx) ast_declaration($1, $2, NULL);
$$->set_location(yylloc);
}
;
@@ -1974,7 +1936,7 @@ condition:
| fully_specified_type any_identifier '=' initializer
{
void *ctx = state;
- ast_declaration *decl = new(ctx) ast_declaration($2, false, NULL, $4);
+ ast_declaration *decl = new(ctx) ast_declaration($2, NULL, $4);
ast_declarator_list *declarator = new(ctx) ast_declarator_list($1);
decl->set_location(yylloc);
declarator->set_location(yylloc);
@@ -2309,22 +2271,17 @@ instance_name_opt:
/* empty */
{
$$ = new(state) ast_interface_block(*state->default_uniform_qualifier,
- NULL, false, NULL);
+ NULL, NULL);
}
| NEW_IDENTIFIER
{
$$ = new(state) ast_interface_block(*state->default_uniform_qualifier,
- $1, false, NULL);
- }
- | NEW_IDENTIFIER '[' constant_expression ']'
- {
- $$ = new(state) ast_interface_block(*state->default_uniform_qualifier,
- $1, true, $3);
+ $1, NULL);
}
- | NEW_IDENTIFIER '[' ']'
+ | NEW_IDENTIFIER array_specifier
{
$$ = new(state) ast_interface_block(*state->default_uniform_qualifier,
- $1, true, NULL);
+ $1, $2);
}
;
diff --git a/mesalib/src/glsl/glsl_parser_extras.cpp b/mesalib/src/glsl/glsl_parser_extras.cpp
index 21dc3abd7..87784ed69 100644
--- a/mesalib/src/glsl/glsl_parser_extras.cpp
+++ b/mesalib/src/glsl/glsl_parser_extras.cpp
@@ -50,7 +50,7 @@ glsl_compute_version_string(void *mem_ctx, bool is_es, unsigned version)
static unsigned known_desktop_glsl_versions[] =
- { 110, 120, 130, 140, 150, 330, 400, 410, 420, 430 };
+ { 110, 120, 130, 140, 150, 330, 400, 410, 420, 430, 440 };
_mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx,
@@ -291,6 +291,10 @@ _mesa_glsl_parse_state::process_version_directive(YYLTYPE *locp, int version,
}
}
+ if (this->es_shader) {
+ this->ARB_texture_rectangle_enable = false;
+ }
+
this->language_version = version;
bool supported = false;
@@ -484,6 +488,7 @@ struct _mesa_glsl_extension {
static const _mesa_glsl_extension _mesa_glsl_supported_extensions[] = {
/* API availability */
/* name GL ES supported flag */
+ EXT(ARB_arrays_of_arrays, true, false, ARB_arrays_of_arrays),
EXT(ARB_conservative_depth, true, false, ARB_conservative_depth),
EXT(ARB_draw_buffers, true, false, dummy_true),
EXT(ARB_draw_instanced, true, false, ARB_draw_instanced),
@@ -513,6 +518,7 @@ static const _mesa_glsl_extension _mesa_glsl_supported_extensions[] = {
EXT(ARB_shader_atomic_counters, true, false, ARB_shader_atomic_counters),
EXT(ARB_sample_shading, true, false, ARB_sample_shading),
EXT(AMD_shader_trinary_minmax, true, false, dummy_true),
+ EXT(ARB_viewport_array, true, false, ARB_viewport_array),
};
#undef EXT
@@ -634,25 +640,6 @@ _mesa_glsl_process_extension(const char *name, YYLTYPE *name_locp,
/**
- * Returns the name of the type of a column of a matrix. E.g.,
- *
- * "mat3" -> "vec3"
- * "mat4x2" -> "vec2"
- */
-static const char *
-_mesa_ast_get_matrix_column_type_name(const char *matrix_type_name)
-{
- static const char *vec_name[] = { "vec2", "vec3", "vec4" };
-
- /* The number of elements in a row of a matrix is specified by the last
- * character of the matrix type name.
- */
- long rows = strtol(matrix_type_name + strlen(matrix_type_name) - 1,
- NULL, 10);
- return vec_name[rows - 2];
-}
-
-/**
* Recurses through <type> and <expr> if <expr> is an aggregate initializer
* and sets <expr>'s <constructor_type> field to <type>. Gives later functions
* (process_array_constructor, et al) sufficient information to do type
@@ -699,37 +686,19 @@ _mesa_ast_get_matrix_column_type_name(const char *matrix_type_name)
* doesn't contain sufficient information to determine if the types match.
*/
void
-_mesa_ast_set_aggregate_type(const ast_type_specifier *type,
- ast_expression *expr,
- _mesa_glsl_parse_state *state)
+_mesa_ast_set_aggregate_type(const glsl_type *type,
+ ast_expression *expr)
{
- void *ctx = state;
ast_aggregate_initializer *ai = (ast_aggregate_initializer *)expr;
- ai->constructor_type = (ast_type_specifier *)type;
-
- bool is_declaration = ai->constructor_type->structure != NULL;
- if (!is_declaration) {
- /* Look up <type> name in the symbol table to see if it's a struct. */
- const ast_type_specifier *struct_type =
- state->symbols->get_type_ast(type->type_name);
- ai->constructor_type->structure =
- struct_type ? new(ctx) ast_struct_specifier(*struct_type->structure)
- : NULL;
- }
+ ai->constructor_type = type;
/* If the aggregate is an array, recursively set its elements' types. */
- if (type->is_array) {
- /* We want to set the element type which is not an array itself, so make
- * a copy of the array type and set its is_array field to false.
+ if (type->is_array()) {
+ /* Each array element has the type type->element_type().
*
* E.g., if <type> if struct S[2] we want to set each element's type to
* struct S.
- *
- * FINISHME: Update when ARB_array_of_arrays is supported.
*/
- const ast_type_specifier *non_array_type =
- new(ctx) ast_type_specifier(type, false, NULL);
-
for (exec_node *expr_node = ai->expressions.head;
!expr_node->is_tail_sentinel();
expr_node = expr_node->next) {
@@ -737,84 +706,33 @@ _mesa_ast_set_aggregate_type(const ast_type_specifier *type,
link);
if (expr->oper == ast_aggregate)
- _mesa_ast_set_aggregate_type(non_array_type, expr, state);
+ _mesa_ast_set_aggregate_type(type->element_type(), expr);
}
/* If the aggregate is a struct, recursively set its fields' types. */
- } else if (ai->constructor_type->structure) {
- ai->constructor_type->structure->is_declaration = is_declaration;
+ } else if (type->is_record()) {
exec_node *expr_node = ai->expressions.head;
- /* Iterate through the struct's fields' declarations. E.g., iterate from
- * "float a, b" to "int c" in the struct below.
- *
- * struct {
- * float a, b;
- * int c;
- * } s;
- */
- for (exec_node *decl_list_node =
- ai->constructor_type->structure->declarations.head;
- !decl_list_node->is_tail_sentinel();
- decl_list_node = decl_list_node->next) {
- ast_declarator_list *decl_list = exec_node_data(ast_declarator_list,
- decl_list_node, link);
-
- for (exec_node *decl_node = decl_list->declarations.head;
- !decl_node->is_tail_sentinel() && !expr_node->is_tail_sentinel();
- decl_node = decl_node->next, expr_node = expr_node->next) {
- ast_declaration *decl = exec_node_data(ast_declaration, decl_node,
- link);
- ast_expression *expr = exec_node_data(ast_expression, expr_node,
- link);
-
- bool is_array = decl_list->type->specifier->is_array;
- ast_expression *array_size = decl_list->type->specifier->array_size;
-
- /* Recognize variable declarations with the bracketed size attached
- * to the type rather than the variable name as arrays. E.g.,
- *
- * float a[2];
- * float[2] b;
- *
- * are both arrays, but <a>'s array_size is decl->array_size, while
- * <b>'s array_size is decl_list->type->specifier->array_size.
- */
- if (!is_array) {
- /* FINISHME: Update when ARB_array_of_arrays is supported. */
- is_array = decl->is_array;
- array_size = decl->array_size;
- }
-
- /* Declaration shadows the <type> parameter. */
- ast_type_specifier *type =
- new(ctx) ast_type_specifier(decl_list->type->specifier,
- is_array, array_size);
+ /* Iterate through the struct's fields. */
+ for (unsigned i = 0; !expr_node->is_tail_sentinel() && i < type->length;
+ i++, expr_node = expr_node->next) {
+ ast_expression *expr = exec_node_data(ast_expression, expr_node,
+ link);
- if (expr->oper == ast_aggregate)
- _mesa_ast_set_aggregate_type(type, expr, state);
+ if (expr->oper == ast_aggregate) {
+ _mesa_ast_set_aggregate_type(type->fields.structure[i].type, expr);
}
}
- } else {
- /* If the aggregate is a matrix, set its columns' types. */
- const char *name;
- const glsl_type *const constructor_type =
- ai->constructor_type->glsl_type(&name, state);
-
- if (constructor_type->is_matrix()) {
- for (exec_node *expr_node = ai->expressions.head;
- !expr_node->is_tail_sentinel();
- expr_node = expr_node->next) {
- ast_expression *expr = exec_node_data(ast_expression, expr_node,
- link);
-
- /* Declaration shadows the <type> parameter. */
- ast_type_specifier *type = new(ctx)
- ast_type_specifier(_mesa_ast_get_matrix_column_type_name(name));
-
- if (expr->oper == ast_aggregate)
- _mesa_ast_set_aggregate_type(type, expr, state);
- }
+ /* If the aggregate is a matrix, set its columns' types. */
+ } else if (type->is_matrix()) {
+ for (exec_node *expr_node = ai->expressions.head;
+ !expr_node->is_tail_sentinel();
+ expr_node = expr_node->next) {
+ ast_expression *expr = exec_node_data(ast_expression, expr_node,
+ link);
+
+ if (expr->oper == ast_aggregate)
+ _mesa_ast_set_aggregate_type(type->column_type(), expr);
}
}
}
@@ -876,16 +794,10 @@ ast_node::ast_node(void)
static void
-ast_opt_array_size_print(bool is_array, const ast_expression *array_size)
+ast_opt_array_dimensions_print(const ast_array_specifier *array_specifier)
{
- if (is_array) {
- printf("[ ");
-
- if (array_size)
- array_size->print();
-
- printf("] ");
- }
+ if (array_specifier)
+ array_specifier->print();
}
@@ -1108,7 +1020,7 @@ ast_parameter_declarator::print(void) const
type->print();
if (identifier)
printf("%s ", identifier);
- ast_opt_array_size_print(is_array, array_size);
+ ast_opt_array_dimensions_print(array_specifier);
}
@@ -1124,7 +1036,7 @@ void
ast_declaration::print(void) const
{
printf("%s ", identifier);
- ast_opt_array_size_print(is_array, array_size);
+ ast_opt_array_dimensions_print(array_specifier);
if (initializer) {
printf("= ");
@@ -1133,13 +1045,12 @@ ast_declaration::print(void) const
}
-ast_declaration::ast_declaration(const char *identifier, bool is_array,
- ast_expression *array_size,
+ast_declaration::ast_declaration(const char *identifier,
+ ast_array_specifier *array_specifier,
ast_expression *initializer)
{
this->identifier = identifier;
- this->is_array = is_array;
- this->array_size = array_size;
+ this->array_specifier = array_specifier;
this->initializer = initializer;
}
@@ -1560,9 +1471,13 @@ do_common_optimization(exec_list *ir, bool linked,
progress = do_copy_propagation(ir) || progress;
progress = do_copy_propagation_elements(ir) || progress;
- if (options->PreferDP4 && !linked)
+ if (options->OptimizeForAOS && !linked)
progress = opt_flip_matrices(ir) || progress;
+ if (linked && options->OptimizeForAOS) {
+ progress = do_vectorize(ir) || progress;
+ }
+
if (linked)
progress = do_dead_code(ir, uniform_locations_assigned) || progress;
else
diff --git a/mesalib/src/glsl/glsl_parser_extras.h b/mesalib/src/glsl/glsl_parser_extras.h
index 21a27c9ea..8c900e637 100644
--- a/mesalib/src/glsl/glsl_parser_extras.h
+++ b/mesalib/src/glsl/glsl_parser_extras.h
@@ -298,6 +298,8 @@ struct _mesa_glsl_parse_state {
* \name Enable bits for GLSL extensions
*/
/*@{*/
+ bool ARB_arrays_of_arrays_enable;
+ bool ARB_arrays_of_arrays_warn;
bool ARB_draw_buffers_enable;
bool ARB_draw_buffers_warn;
bool ARB_draw_instanced_enable;
@@ -356,6 +358,8 @@ struct _mesa_glsl_parse_state {
bool ARB_shader_atomic_counters_warn;
bool AMD_shader_trinary_minmax_enable;
bool AMD_shader_trinary_minmax_warn;
+ bool ARB_viewport_array_enable;
+ bool ARB_viewport_array_warn;
/*@}*/
/** Extensions supported by the OpenGL implementation. */
diff --git a/mesalib/src/glsl/glsl_types.cpp b/mesalib/src/glsl/glsl_types.cpp
index 12d4ac0ee..1b0b3ef88 100644
--- a/mesalib/src/glsl/glsl_types.cpp
+++ b/mesalib/src/glsl/glsl_types.cpp
@@ -300,8 +300,20 @@ glsl_type::glsl_type(const glsl_type *array, unsigned length) :
if (length == 0)
snprintf(n, name_length, "%s[]", array->name);
- else
- snprintf(n, name_length, "%s[%u]", array->name, length);
+ else {
+ /* insert outermost dimensions in the correct spot
+ * otherwise the dimension order will be backwards
+ */
+ const char *pos = strchr(array->name, '[');
+ if (pos) {
+ int idx = pos - array->name;
+ snprintf(n, idx+1, "%s", array->name);
+ snprintf(n + idx, name_length - idx, "[%u]%s",
+ length, array->name + idx);
+ } else {
+ snprintf(n, name_length, "%s[%u]", array->name, length);
+ }
+ }
this->name = n;
}
@@ -449,6 +461,42 @@ glsl_type::get_array_instance(const glsl_type *base, unsigned array_size)
}
+bool
+glsl_type::record_compare(const glsl_type *b) const
+{
+ if (this->length != b->length)
+ return false;
+
+ if (this->interface_packing != b->interface_packing)
+ return false;
+
+ for (unsigned i = 0; i < this->length; i++) {
+ if (this->fields.structure[i].type != b->fields.structure[i].type)
+ return false;
+ if (strcmp(this->fields.structure[i].name,
+ b->fields.structure[i].name) != 0)
+ return false;
+ if (this->fields.structure[i].row_major
+ != b->fields.structure[i].row_major)
+ return false;
+ if (this->fields.structure[i].location
+ != b->fields.structure[i].location)
+ return false;
+ if (this->fields.structure[i].interpolation
+ != b->fields.structure[i].interpolation)
+ return false;
+ if (this->fields.structure[i].centroid
+ != b->fields.structure[i].centroid)
+ return false;
+ if (this->fields.structure[i].sample
+ != b->fields.structure[i].sample)
+ return false;
+ }
+
+ return true;
+}
+
+
int
glsl_type::record_key_compare(const void *a, const void *b)
{
@@ -461,36 +509,7 @@ glsl_type::record_key_compare(const void *a, const void *b)
if (strcmp(key1->name, key2->name) != 0)
return 1;
- if (key1->length != key2->length)
- return 1;
-
- if (key1->interface_packing != key2->interface_packing)
- return 1;
-
- for (unsigned i = 0; i < key1->length; i++) {
- if (key1->fields.structure[i].type != key2->fields.structure[i].type)
- return 1;
- if (strcmp(key1->fields.structure[i].name,
- key2->fields.structure[i].name) != 0)
- return 1;
- if (key1->fields.structure[i].row_major
- != key2->fields.structure[i].row_major)
- return 1;
- if (key1->fields.structure[i].location
- != key2->fields.structure[i].location)
- return 1;
- if (key1->fields.structure[i].interpolation
- != key2->fields.structure[i].interpolation)
- return 1;
- if (key1->fields.structure[i].centroid
- != key2->fields.structure[i].centroid)
- return 1;
- if (key1->fields.structure[i].sample
- != key2->fields.structure[i].sample)
- return 1;
- }
-
- return 0;
+ return !key1->record_compare(key2);
}
diff --git a/mesalib/src/glsl/glsl_types.h b/mesalib/src/glsl/glsl_types.h
index fb7c9288d..f88758a9a 100644
--- a/mesalib/src/glsl/glsl_types.h
+++ b/mesalib/src/glsl/glsl_types.h
@@ -542,6 +542,13 @@ struct glsl_type {
*/
int sampler_coordinate_components() const;
+ /**
+ * Compare a record type against another record type.
+ *
+ * This is useful for matching record types declared across shader stages.
+ */
+ bool record_compare(const glsl_type *b) const;
+
private:
/**
* ralloc context for all glsl_type allocations
diff --git a/mesalib/src/glsl/ir.h b/mesalib/src/glsl/ir.h
index 2ae8513a6..19e8383b2 100644
--- a/mesalib/src/glsl/ir.h
+++ b/mesalib/src/glsl/ir.h
@@ -148,7 +148,7 @@ public:
* in particular. No support for other instruction types (assignments,
* jumps, calls, etc.) is planned.
*/
- virtual bool equals(ir_instruction *ir);
+ virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset);
protected:
ir_instruction()
@@ -1413,7 +1413,7 @@ public:
return this;
}
- virtual bool equals(ir_instruction *ir);
+ virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset);
virtual ir_expression *clone(void *mem_ctx, struct hash_table *ht) const;
@@ -1741,7 +1741,7 @@ public:
virtual ir_visitor_status accept(ir_hierarchical_visitor *);
- virtual bool equals(ir_instruction *ir);
+ virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset);
/**
* Return a string representing the ir_texture_opcode.
@@ -1847,7 +1847,7 @@ public:
virtual ir_visitor_status accept(ir_hierarchical_visitor *);
- virtual bool equals(ir_instruction *ir);
+ virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset);
bool is_lvalue() const
{
@@ -1913,7 +1913,7 @@ public:
return this;
}
- virtual bool equals(ir_instruction *ir);
+ virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset);
/**
* Get the variable that is ultimately referenced by an r-value
@@ -1973,7 +1973,7 @@ public:
return this;
}
- virtual bool equals(ir_instruction *ir);
+ virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset);
/**
* Get the variable that is ultimately referenced by an r-value
@@ -2109,7 +2109,7 @@ public:
virtual ir_visitor_status accept(ir_hierarchical_visitor *);
- virtual bool equals(ir_instruction *ir);
+ virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset);
/**
* Get a particular component of a constant as a specific type
diff --git a/mesalib/src/glsl/ir_equals.cpp b/mesalib/src/glsl/ir_equals.cpp
index 7cfe1e66b..484530019 100644
--- a/mesalib/src/glsl/ir_equals.cpp
+++ b/mesalib/src/glsl/ir_equals.cpp
@@ -28,12 +28,12 @@
* can't access a's vtable in that case.
*/
static bool
-possibly_null_equals(ir_instruction *a, ir_instruction *b)
+possibly_null_equals(ir_instruction *a, ir_instruction *b, enum ir_node_type ignore)
{
if (!a || !b)
return !a && !b;
- return a->equals(b);
+ return a->equals(b, ignore);
}
/**
@@ -41,13 +41,13 @@ possibly_null_equals(ir_instruction *a, ir_instruction *b)
* about.
*/
bool
-ir_instruction::equals(ir_instruction *ir)
+ir_instruction::equals(ir_instruction *ir, enum ir_node_type)
{
return false;
}
bool
-ir_constant::equals(ir_instruction *ir)
+ir_constant::equals(ir_instruction *ir, enum ir_node_type ignore)
{
const ir_constant *other = ir->as_constant();
if (!other)
@@ -65,7 +65,7 @@ ir_constant::equals(ir_instruction *ir)
}
bool
-ir_dereference_variable::equals(ir_instruction *ir)
+ir_dereference_variable::equals(ir_instruction *ir, enum ir_node_type ignore)
{
const ir_dereference_variable *other = ir->as_dereference_variable();
if (!other)
@@ -75,7 +75,7 @@ ir_dereference_variable::equals(ir_instruction *ir)
}
bool
-ir_dereference_array::equals(ir_instruction *ir)
+ir_dereference_array::equals(ir_instruction *ir, enum ir_node_type ignore)
{
const ir_dereference_array *other = ir->as_dereference_array();
if (!other)
@@ -84,17 +84,17 @@ ir_dereference_array::equals(ir_instruction *ir)
if (type != other->type)
return false;
- if (!array->equals(other->array))
+ if (!array->equals(other->array, ignore))
return false;
- if (!array_index->equals(other->array_index))
+ if (!array_index->equals(other->array_index, ignore))
return false;
return true;
}
bool
-ir_swizzle::equals(ir_instruction *ir)
+ir_swizzle::equals(ir_instruction *ir, enum ir_node_type ignore)
{
const ir_swizzle *other = ir->as_swizzle();
if (!other)
@@ -103,18 +103,20 @@ ir_swizzle::equals(ir_instruction *ir)
if (type != other->type)
return false;
- if (mask.x != other->mask.x ||
- mask.y != other->mask.y ||
- mask.z != other->mask.z ||
- mask.w != other->mask.w) {
- return false;
+ if (ignore != ir_type_swizzle) {
+ if (mask.x != other->mask.x ||
+ mask.y != other->mask.y ||
+ mask.z != other->mask.z ||
+ mask.w != other->mask.w) {
+ return false;
+ }
}
- return val->equals(other->val);
+ return val->equals(other->val, ignore);
}
bool
-ir_texture::equals(ir_instruction *ir)
+ir_texture::equals(ir_instruction *ir, enum ir_node_type ignore)
{
const ir_texture *other = ir->as_texture();
if (!other)
@@ -126,19 +128,19 @@ ir_texture::equals(ir_instruction *ir)
if (op != other->op)
return false;
- if (!possibly_null_equals(coordinate, other->coordinate))
+ if (!possibly_null_equals(coordinate, other->coordinate, ignore))
return false;
- if (!possibly_null_equals(projector, other->projector))
+ if (!possibly_null_equals(projector, other->projector, ignore))
return false;
- if (!possibly_null_equals(shadow_comparitor, other->shadow_comparitor))
+ if (!possibly_null_equals(shadow_comparitor, other->shadow_comparitor, ignore))
return false;
- if (!possibly_null_equals(offset, other->offset))
+ if (!possibly_null_equals(offset, other->offset, ignore))
return false;
- if (!sampler->equals(other->sampler))
+ if (!sampler->equals(other->sampler, ignore))
return false;
switch (op) {
@@ -147,26 +149,26 @@ ir_texture::equals(ir_instruction *ir)
case ir_query_levels:
break;
case ir_txb:
- if (!lod_info.bias->equals(other->lod_info.bias))
+ if (!lod_info.bias->equals(other->lod_info.bias, ignore))
return false;
break;
case ir_txl:
case ir_txf:
case ir_txs:
- if (!lod_info.lod->equals(other->lod_info.lod))
+ if (!lod_info.lod->equals(other->lod_info.lod, ignore))
return false;
break;
case ir_txd:
- if (!lod_info.grad.dPdx->equals(other->lod_info.grad.dPdx) ||
- !lod_info.grad.dPdy->equals(other->lod_info.grad.dPdy))
+ if (!lod_info.grad.dPdx->equals(other->lod_info.grad.dPdx, ignore) ||
+ !lod_info.grad.dPdy->equals(other->lod_info.grad.dPdy, ignore))
return false;
break;
case ir_txf_ms:
- if (!lod_info.sample_index->equals(other->lod_info.sample_index))
+ if (!lod_info.sample_index->equals(other->lod_info.sample_index, ignore))
return false;
break;
case ir_tg4:
- if (!lod_info.component->equals(other->lod_info.component))
+ if (!lod_info.component->equals(other->lod_info.component, ignore))
return false;
break;
default:
@@ -177,7 +179,7 @@ ir_texture::equals(ir_instruction *ir)
}
bool
-ir_expression::equals(ir_instruction *ir)
+ir_expression::equals(ir_instruction *ir, enum ir_node_type ignore)
{
const ir_expression *other = ir->as_expression();
if (!other)
@@ -190,7 +192,7 @@ ir_expression::equals(ir_instruction *ir)
return false;
for (unsigned i = 0; i < get_num_operands(); i++) {
- if (!operands[i]->equals(other->operands[i]))
+ if (!operands[i]->equals(other->operands[i], ignore))
return false;
}
diff --git a/mesalib/src/glsl/ir_optimization.h b/mesalib/src/glsl/ir_optimization.h
index 3ca9f5744..055d65547 100644
--- a/mesalib/src/glsl/ir_optimization.h
+++ b/mesalib/src/glsl/ir_optimization.h
@@ -98,6 +98,7 @@ bool do_mat_op_to_vec(exec_list *instructions);
bool do_noop_swizzle(exec_list *instructions);
bool do_structure_splitting(exec_list *instructions);
bool do_swizzle_swizzle(exec_list *instructions);
+bool do_vectorize(exec_list *instructions);
bool do_tree_grafting(exec_list *instructions);
bool do_vec_index_to_cond_assign(exec_list *instructions);
bool do_vec_index_to_swizzle(exec_list *instructions);
diff --git a/mesalib/src/glsl/link_atomics.cpp b/mesalib/src/glsl/link_atomics.cpp
index db9c53965..d92cdb117 100644
--- a/mesalib/src/glsl/link_atomics.cpp
+++ b/mesalib/src/glsl/link_atomics.cpp
@@ -105,9 +105,10 @@ namespace {
ir_variable *var = ((ir_instruction *)node)->as_variable();
if (var && var->type->contains_atomic()) {
- unsigned id;
+ unsigned id = 0;
bool found = prog->UniformHash->get(id, var->name);
assert(found);
+ (void) found;
active_atomic_buffer *buf = &buffers[var->data.binding];
/* If this is the first time the buffer is used, increment
diff --git a/mesalib/src/glsl/linker.cpp b/mesalib/src/glsl/linker.cpp
index 85a4d3883..93b475497 100644
--- a/mesalib/src/glsl/linker.cpp
+++ b/mesalib/src/glsl/linker.cpp
@@ -609,6 +609,10 @@ cross_validate_globals(struct gl_shader_program *prog,
if (var->type->length != 0) {
existing->type = var->type;
}
+ } else if (var->type->is_record()
+ && existing->type->is_record()
+ && existing->type->record_compare(var->type)) {
+ existing->type = var->type;
} else {
linker_error(prog, "%s `%s' declared as type "
"`%s' and type `%s'\n",
@@ -1992,19 +1996,14 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
/* Separate the shaders into groups based on their type.
*/
- struct gl_shader **vert_shader_list;
- unsigned num_vert_shaders = 0;
- struct gl_shader **frag_shader_list;
- unsigned num_frag_shaders = 0;
- struct gl_shader **geom_shader_list;
- unsigned num_geom_shaders = 0;
-
- vert_shader_list = (struct gl_shader **)
- calloc(prog->NumShaders, sizeof(struct gl_shader *));
- frag_shader_list = (struct gl_shader **)
- calloc(prog->NumShaders, sizeof(struct gl_shader *));
- geom_shader_list = (struct gl_shader **)
- calloc(prog->NumShaders, sizeof(struct gl_shader *));
+ struct gl_shader **shader_list[MESA_SHADER_STAGES];
+ unsigned num_shaders[MESA_SHADER_STAGES];
+
+ for (int i = 0; i < MESA_SHADER_STAGES; i++) {
+ shader_list[i] = (struct gl_shader **)
+ calloc(prog->NumShaders, sizeof(struct gl_shader *));
+ num_shaders[i] = 0;
+ }
unsigned min_version = UINT_MAX;
unsigned max_version = 0;
@@ -2020,20 +2019,9 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
goto done;
}
- switch (prog->Shaders[i]->Stage) {
- case MESA_SHADER_VERTEX:
- vert_shader_list[num_vert_shaders] = prog->Shaders[i];
- num_vert_shaders++;
- break;
- case MESA_SHADER_FRAGMENT:
- frag_shader_list[num_frag_shaders] = prog->Shaders[i];
- num_frag_shaders++;
- break;
- case MESA_SHADER_GEOMETRY:
- geom_shader_list[num_geom_shaders] = prog->Shaders[i];
- num_geom_shaders++;
- break;
- }
+ gl_shader_stage shader_type = prog->Shaders[i]->Stage;
+ shader_list[shader_type][num_shaders[shader_type]] = prog->Shaders[i];
+ num_shaders[shader_type]++;
}
/* In desktop GLSL, different shader versions may be linked together. In
@@ -2050,7 +2038,8 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
/* Geometry shaders have to be linked with vertex shaders.
*/
- if (num_geom_shaders > 0 && num_vert_shaders == 0) {
+ if (num_shaders[MESA_SHADER_GEOMETRY] > 0 &&
+ num_shaders[MESA_SHADER_VERTEX] == 0) {
linker_error(prog, "Geometry shader must be linked with "
"vertex shader\n");
goto done;
@@ -2065,55 +2054,39 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
/* Link all shaders for a particular stage and validate the result.
*/
- if (num_vert_shaders > 0) {
- gl_shader *const sh =
- link_intrastage_shaders(mem_ctx, ctx, prog, vert_shader_list,
- num_vert_shaders);
-
- if (!prog->LinkStatus)
- goto done;
-
- validate_vertex_shader_executable(prog, sh);
- if (!prog->LinkStatus)
- goto done;
- prog->LastClipDistanceArraySize = prog->Vert.ClipDistanceArraySize;
+ for (int stage = 0; stage < MESA_SHADER_STAGES; stage++) {
+ if (num_shaders[stage] > 0) {
+ gl_shader *const sh =
+ link_intrastage_shaders(mem_ctx, ctx, prog, shader_list[stage],
+ num_shaders[stage]);
- _mesa_reference_shader(ctx, &prog->_LinkedShaders[MESA_SHADER_VERTEX],
- sh);
- }
-
- if (num_frag_shaders > 0) {
- gl_shader *const sh =
- link_intrastage_shaders(mem_ctx, ctx, prog, frag_shader_list,
- num_frag_shaders);
-
- if (!prog->LinkStatus)
- goto done;
+ if (!prog->LinkStatus)
+ goto done;
- validate_fragment_shader_executable(prog, sh);
- if (!prog->LinkStatus)
- goto done;
+ switch (stage) {
+ case MESA_SHADER_VERTEX:
+ validate_vertex_shader_executable(prog, sh);
+ break;
+ case MESA_SHADER_GEOMETRY:
+ validate_geometry_shader_executable(prog, sh);
+ break;
+ case MESA_SHADER_FRAGMENT:
+ validate_fragment_shader_executable(prog, sh);
+ break;
+ }
+ if (!prog->LinkStatus)
+ goto done;
- _mesa_reference_shader(ctx, &prog->_LinkedShaders[MESA_SHADER_FRAGMENT],
- sh);
+ _mesa_reference_shader(ctx, &prog->_LinkedShaders[stage], sh);
+ }
}
- if (num_geom_shaders > 0) {
- gl_shader *const sh =
- link_intrastage_shaders(mem_ctx, ctx, prog, geom_shader_list,
- num_geom_shaders);
-
- if (!prog->LinkStatus)
- goto done;
-
- validate_geometry_shader_executable(prog, sh);
- if (!prog->LinkStatus)
- goto done;
+ if (num_shaders[MESA_SHADER_GEOMETRY] > 0)
prog->LastClipDistanceArraySize = prog->Geom.ClipDistanceArraySize;
-
- _mesa_reference_shader(ctx, &prog->_LinkedShaders[MESA_SHADER_GEOMETRY],
- sh);
- }
+ else if (num_shaders[MESA_SHADER_VERTEX] > 0)
+ prog->LastClipDistanceArraySize = prog->Vert.ClipDistanceArraySize;
+ else
+ prog->LastClipDistanceArraySize = 0; /* Not used */
/* Here begins the inter-stage linking phase. Some initial validation is
* performed, then locations are assigned for uniforms, attributes, and
@@ -2371,11 +2344,8 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
/* FINISHME: Assign fragment shader output locations. */
done:
- free(vert_shader_list);
- free(frag_shader_list);
- free(geom_shader_list);
-
for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
+ free(shader_list[i]);
if (prog->_LinkedShaders[i] == NULL)
continue;
diff --git a/mesalib/src/glsl/opt_algebraic.cpp b/mesalib/src/glsl/opt_algebraic.cpp
index 332f0b77b..d1f6435f4 100644
--- a/mesalib/src/glsl/opt_algebraic.cpp
+++ b/mesalib/src/glsl/opt_algebraic.cpp
@@ -285,6 +285,58 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir)
reassociate_constant(ir, 0, op_const[0], op_expr[1]);
if (op_const[1] && !op_const[0])
reassociate_constant(ir, 1, op_const[1], op_expr[0]);
+
+ /* Replace (-x + y) * a + x and commutative variations with lrp(x, y, a).
+ *
+ * (-x + y) * a + x
+ * (x * -a) + (y * a) + x
+ * x + (x * -a) + (y * a)
+ * x * (1 - a) + y * a
+ * lrp(x, y, a)
+ */
+ for (int mul_pos = 0; mul_pos < 2; mul_pos++) {
+ ir_expression *mul = op_expr[mul_pos];
+
+ if (!mul || mul->operation != ir_binop_mul)
+ continue;
+
+ /* Multiply found on one of the operands. Now check for an
+ * inner addition operation.
+ */
+ for (int inner_add_pos = 0; inner_add_pos < 2; inner_add_pos++) {
+ ir_expression *inner_add =
+ mul->operands[inner_add_pos]->as_expression();
+
+ if (!inner_add || inner_add->operation != ir_binop_add)
+ continue;
+
+ /* Inner addition found on one of the operands. Now check for
+ * one of the operands of the inner addition to be the negative
+ * of x_operand.
+ */
+ for (int neg_pos = 0; neg_pos < 2; neg_pos++) {
+ ir_expression *neg =
+ inner_add->operands[neg_pos]->as_expression();
+
+ if (!neg || neg->operation != ir_unop_neg)
+ continue;
+
+ ir_rvalue *x_operand = ir->operands[1 - mul_pos];
+
+ if (!neg->operands[0]->equals(x_operand))
+ continue;
+
+ ir_rvalue *y_operand = inner_add->operands[1 - neg_pos];
+ ir_rvalue *a_operand = mul->operands[1 - inner_add_pos];
+
+ if (x_operand->type != y_operand->type ||
+ x_operand->type != a_operand->type)
+ continue;
+
+ return lrp(x_operand, y_operand, a_operand);
+ }
+ }
+ }
break;
case ir_binop_sub:
diff --git a/mesalib/src/glsl/opt_vectorize.cpp b/mesalib/src/glsl/opt_vectorize.cpp
new file mode 100644
index 000000000..9ca811a86
--- /dev/null
+++ b/mesalib/src/glsl/opt_vectorize.cpp
@@ -0,0 +1,319 @@
+/*
+ * Copyright © 2013 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file opt_vectorize.cpp
+ *
+ * Combines scalar assignments of the same expression (modulo swizzle) to
+ * multiple channels of the same variable into a single vectorized expression
+ * and assignment.
+ *
+ * Many generated shaders contain scalarized code. That is, they contain
+ *
+ * r1.x = log2(v0.x);
+ * r1.y = log2(v0.y);
+ * r1.z = log2(v0.z);
+ *
+ * rather than
+ *
+ * r1.xyz = log2(v0.xyz);
+ *
+ * We look for consecutive assignments of the same expression (modulo swizzle)
+ * to each channel of the same variable.
+ *
+ * For instance, we want to convert these three scalar operations
+ *
+ * (assign (x) (var_ref r1) (expression float log2 (swiz x (var_ref v0))))
+ * (assign (y) (var_ref r1) (expression float log2 (swiz y (var_ref v0))))
+ * (assign (z) (var_ref r1) (expression float log2 (swiz z (var_ref v0))))
+ *
+ * into a single vector operation
+ *
+ * (assign (xyz) (var_ref r1) (expression vec3 log2 (swiz xyz (var_ref v0))))
+ */
+
+#include "ir.h"
+#include "ir_visitor.h"
+#include "ir_optimization.h"
+#include "glsl_types.h"
+#include "program/prog_instruction.h"
+
+namespace {
+
+class ir_vectorize_visitor : public ir_hierarchical_visitor {
+public:
+ void clear()
+ {
+ assignment[0] = NULL;
+ assignment[1] = NULL;
+ assignment[2] = NULL;
+ assignment[3] = NULL;
+ current_assignment = NULL;
+ last_assignment = NULL;
+ channels = 0;
+ has_swizzle = false;
+ }
+
+ ir_vectorize_visitor()
+ {
+ clear();
+ progress = false;
+ }
+
+ virtual ir_visitor_status visit_enter(ir_assignment *);
+ virtual ir_visitor_status visit_enter(ir_swizzle *);
+
+ virtual ir_visitor_status visit_leave(ir_assignment *);
+
+ void try_vectorize();
+
+ ir_assignment *assignment[4];
+ ir_assignment *current_assignment, *last_assignment;
+ unsigned channels;
+ bool has_swizzle;
+
+ bool progress;
+};
+
+} /* unnamed namespace */
+
+/**
+ * Rewrites the swizzles and types of a right-hand side of an assignment.
+ *
+ * From the example above, this function would be called (by visit_tree()) on
+ * the nodes of the tree (expression float log2 (swiz z (var_ref v0))),
+ * rewriting it into (expression vec3 log2 (swiz xyz (var_ref v0))).
+ *
+ * The function modifies only ir_expressions and ir_swizzles. For expressions
+ * it sets a new type and swizzles any scalar dereferences into appropriately
+ * sized vector arguments. For example, if combining
+ *
+ * (assign (x) (var_ref r1) (expression float + (swiz x (var_ref v0) (var_ref v1))))
+ * (assign (y) (var_ref r1) (expression float + (swiz y (var_ref v0) (var_ref v1))))
+ *
+ * where v1 is a scalar, rewrite_swizzle() would insert a swizzle on
+ * (var_ref v1) such that the final result was
+ *
+ * (assign (xy) (var_ref r1) (expression vec2 + (swiz xy (var_ref v0))
+ * (swiz xx (var_ref v1))))
+ *
+ * For swizzles, it sets a new type, and if the variable being swizzled is a
+ * vector it overwrites the swizzle mask with the ir_swizzle_mask passed as the
+ * data parameter. If the swizzled variable is scalar, then the swizzle was
+ * added by an earlier call to rewrite_swizzle() on an expression, so the
+ * mask should not be modified.
+ */
+static void
+rewrite_swizzle(ir_instruction *ir, void *data)
+{
+ ir_swizzle_mask *mask = (ir_swizzle_mask *)data;
+
+ switch (ir->ir_type) {
+ case ir_type_swizzle: {
+ ir_swizzle *swz = (ir_swizzle *)ir;
+ if (swz->val->type->is_vector()) {
+ swz->mask = *mask;
+ }
+ swz->type = glsl_type::get_instance(swz->type->base_type,
+ mask->num_components, 1);
+ break;
+ }
+ case ir_type_expression: {
+ ir_expression *expr = (ir_expression *)ir;
+ expr->type = glsl_type::get_instance(expr->type->base_type,
+ mask->num_components, 1);
+ for (unsigned i = 0; i < 4; i++) {
+ if (expr->operands[i]) {
+ ir_dereference *deref = expr->operands[i]->as_dereference();
+ if (deref && deref->type->is_scalar()) {
+ expr->operands[i] = new(ir) ir_swizzle(deref, 0, 0, 0, 0,
+ mask->num_components);
+ }
+ }
+ }
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+/**
+ * Attempt to vectorize the previously saved assignments, and clear them from
+ * consideration.
+ *
+ * If the assignments are able to be combined, it modifies in-place the last
+ * assignment seen to be an equivalent vector form of the scalar assignments.
+ * It then removes the other now obsolete scalar assignments.
+ */
+void
+ir_vectorize_visitor::try_vectorize()
+{
+ if (this->last_assignment && this->channels > 1) {
+ ir_swizzle_mask mask = {0, 1, 2, 3, channels, 0};
+
+ visit_tree(this->last_assignment->rhs, rewrite_swizzle, &mask);
+
+ this->last_assignment->write_mask = 0;
+
+ for (unsigned i = 0; i < 4; i++) {
+ if (this->assignment[i]) {
+ this->last_assignment->write_mask |= 1 << i;
+
+ if (this->assignment[i] != this->last_assignment) {
+ this->assignment[i]->remove();
+ }
+ }
+ }
+
+ this->progress = true;
+ }
+ clear();
+}
+
+/**
+ * Returns whether the write mask is a single channel.
+ */
+static bool
+single_channel_write_mask(unsigned write_mask)
+{
+ return write_mask != 0 && (write_mask & (write_mask - 1)) == 0;
+}
+
+/**
+ * Translates single-channeled write mask to single-channeled swizzle.
+ */
+static unsigned
+write_mask_to_swizzle(unsigned write_mask)
+{
+ switch (write_mask) {
+ case WRITEMASK_X: return SWIZZLE_X;
+ case WRITEMASK_Y: return SWIZZLE_Y;
+ case WRITEMASK_Z: return SWIZZLE_Z;
+ case WRITEMASK_W: return SWIZZLE_W;
+ }
+ assert(!"not reached");
+ unreachable();
+}
+
+/**
+ * Returns whether a single-channeled write mask matches a swizzle.
+ */
+static bool
+write_mask_matches_swizzle(unsigned write_mask,
+ const ir_swizzle *swz)
+{
+ return ((write_mask == WRITEMASK_X && swz->mask.x == SWIZZLE_X) ||
+ (write_mask == WRITEMASK_Y && swz->mask.x == SWIZZLE_Y) ||
+ (write_mask == WRITEMASK_Z && swz->mask.x == SWIZZLE_Z) ||
+ (write_mask == WRITEMASK_W && swz->mask.x == SWIZZLE_W));
+}
+
+/**
+ * Upon entering an ir_assignment, attempt to vectorize the currently tracked
+ * assignments if the current assignment is not suitable. Keep a pointer to
+ * the current assignment.
+ */
+ir_visitor_status
+ir_vectorize_visitor::visit_enter(ir_assignment *ir)
+{
+ ir_dereference *lhs = this->last_assignment != NULL ?
+ this->last_assignment->lhs : NULL;
+ ir_rvalue *rhs = this->last_assignment != NULL ?
+ this->last_assignment->rhs : NULL;
+
+ if (ir->condition ||
+ this->channels >= 4 ||
+ !single_channel_write_mask(ir->write_mask) ||
+ (lhs && !ir->lhs->equals(lhs)) ||
+ (rhs && !ir->rhs->equals(rhs, ir_type_swizzle))) {
+ try_vectorize();
+ }
+
+ this->current_assignment = ir;
+
+ return visit_continue;
+}
+
+/**
+ * Upon entering an ir_swizzle, set ::has_swizzle if we're visiting from an
+ * ir_assignment (i.e., that ::current_assignment is set) and the swizzle mask
+ * matches the current assignment's write mask.
+ *
+ * If the write mask doesn't match the swizzle mask, remove the current
+ * assignment from further consideration.
+ */
+ir_visitor_status
+ir_vectorize_visitor::visit_enter(ir_swizzle *ir)
+{
+ if (this->current_assignment) {
+ if (write_mask_matches_swizzle(this->current_assignment->write_mask, ir)) {
+ this->has_swizzle = true;
+ } else {
+ this->current_assignment = NULL;
+ }
+ }
+ return visit_continue;
+}
+
+/**
+ * Upon leaving an ir_assignment, save a pointer to it in ::assignment[] if
+ * the swizzle mask(s) found were appropriate. Also save a pointer in
+ * ::last_assignment so that we can compare future assignments with it.
+ *
+ * Finally, clear ::current_assignment and ::has_swizzle.
+ */
+ir_visitor_status
+ir_vectorize_visitor::visit_leave(ir_assignment *ir)
+{
+ if (this->has_swizzle && this->current_assignment) {
+ assert(this->current_assignment == ir);
+
+ unsigned channel = write_mask_to_swizzle(this->current_assignment->write_mask);
+ this->assignment[channel] = ir;
+ this->channels++;
+
+ this->last_assignment = this->current_assignment;
+ }
+ this->current_assignment = NULL;
+ this->has_swizzle = false;
+ return visit_continue;
+}
+
+/**
+ * Combines scalar assignments of the same expression (modulo swizzle) to
+ * multiple channels of the same variable into a single vectorized expression
+ * and assignment.
+ */
+bool
+do_vectorize(exec_list *instructions)
+{
+ ir_vectorize_visitor v;
+
+ v.run(instructions);
+
+ /* Try to vectorize the last assignments seen. */
+ v.try_vectorize();
+
+ return v.progress;
+}
diff --git a/mesalib/src/glsl/standalone_scaffolding.cpp b/mesalib/src/glsl/standalone_scaffolding.cpp
index 257d2e7a9..91794719b 100644
--- a/mesalib/src/glsl/standalone_scaffolding.cpp
+++ b/mesalib/src/glsl/standalone_scaffolding.cpp
@@ -110,6 +110,7 @@ void initialize_context_to_defaults(struct gl_context *ctx, gl_api api)
ctx->Extensions.ARB_texture_query_levels = true;
ctx->Extensions.ARB_texture_query_lod = true;
ctx->Extensions.ARB_uniform_buffer_object = true;
+ ctx->Extensions.ARB_viewport_array = true;
ctx->Extensions.OES_EGL_image_external = true;
ctx->Extensions.OES_standard_derivatives = true;