summaryrefslogtreecommitdiffstats
path: root/src/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/Makefile.sources2
-rw-r--r--src/compiler/glsl/ast.h16
-rw-r--r--src/compiler/glsl/ast_to_hir.cpp129
-rw-r--r--src/compiler/glsl/ast_type.cpp33
-rw-r--r--src/compiler/glsl/builtin_functions.cpp122
-rw-r--r--src/compiler/glsl/builtin_variables.cpp1
-rw-r--r--src/compiler/glsl/glcpp/glcpp-lex.l11
-rw-r--r--src/compiler/glsl/glcpp/glcpp-parse.y53
-rw-r--r--src/compiler/glsl/glcpp/glcpp.h1
-rw-r--r--src/compiler/glsl/glcpp/tests/129-define-non-identifier.c.expected2
-rw-r--r--src/compiler/glsl/glcpp/tests/144-implicit-version.c1
-rw-r--r--src/compiler/glsl/glcpp/tests/144-implicit-version.c.expected1
-rw-r--r--src/compiler/glsl/glcpp/tests/145-version-first.c2
-rw-r--r--src/compiler/glsl/glcpp/tests/145-version-first.c.expected3
-rw-r--r--src/compiler/glsl/glcpp/tests/146-version-first-hash.c2
-rw-r--r--src/compiler/glsl/glcpp/tests/146-version-first-hash.c.expected3
-rw-r--r--src/compiler/glsl/glsl_parser.yy71
-rw-r--r--src/compiler/glsl/glsl_parser_extras.cpp4
-rw-r--r--src/compiler/glsl/glsl_parser_extras.h2
-rw-r--r--src/compiler/glsl/ir.h2
-rw-r--r--src/compiler/glsl/ir_builder.cpp12
-rw-r--r--src/compiler/glsl/link_interface_blocks.cpp80
-rw-r--r--src/compiler/glsl/link_uniform_blocks.cpp5
-rw-r--r--src/compiler/glsl/link_uniforms.cpp151
-rw-r--r--src/compiler/glsl/link_varyings.cpp28
-rw-r--r--src/compiler/glsl/linker.cpp10
-rw-r--r--src/compiler/glsl/linker.h2
-rw-r--r--src/compiler/glsl/lower_buffer_access.cpp4
-rw-r--r--src/compiler/glsl/opt_array_splitting.cpp68
-rw-r--r--src/compiler/glsl_types.cpp5
-rw-r--r--src/compiler/glsl_types.h8
-rw-r--r--src/compiler/nir/Makefile.sources2
-rw-r--r--src/compiler/nir/glsl_to_nir.cpp51
-rw-r--r--src/compiler/nir/nir.c2
-rw-r--r--src/compiler/nir/nir.h4
-rw-r--r--src/compiler/nir/nir_lower_indirect_derefs.c2
-rw-r--r--src/compiler/nir/nir_opt_algebraic.py12
-rw-r--r--src/compiler/nir/nir_print.c12
-rw-r--r--src/compiler/nir/nir_validate.c2
39 files changed, 662 insertions, 259 deletions
diff --git a/src/compiler/Makefile.sources b/src/compiler/Makefile.sources
index 2a4568aa679..b0b8281869d 100644
--- a/src/compiler/Makefile.sources
+++ b/src/compiler/Makefile.sources
@@ -188,10 +188,10 @@ NIR_FILES = \
nir/nir_lower_clip.c \
nir/nir_lower_global_vars_to_local.c \
nir/nir_lower_gs_intrinsics.c \
- nir/nir_lower_indirect_derefs.c \
nir/nir_lower_load_const_to_scalar.c \
nir/nir_lower_locals_to_regs.c \
nir/nir_lower_idiv.c \
+ nir/nir_lower_indirect_derefs.c \
nir/nir_lower_io.c \
nir/nir_lower_outputs_to_temporaries.c \
nir/nir_lower_phis_to_scalar.c \
diff --git a/src/compiler/glsl/ast.h b/src/compiler/glsl/ast.h
index 9aa5bb99f49..727aa432631 100644
--- a/src/compiler/glsl/ast.h
+++ b/src/compiler/glsl/ast.h
@@ -479,6 +479,12 @@ struct ast_type_qualifier {
unsigned pixel_center_integer:1;
/*@}*/
+ /**
+ * Flag set if GL_ARB_enhanced_layouts "align" layout qualifier is
+ * used.
+ */
+ unsigned explicit_align:1;
+
/**
* Flag set if GL_ARB_explicit_attrib_location "location" layout
* qualifier is used.
@@ -577,6 +583,11 @@ struct ast_type_qualifier {
/** Precision of the type (highp/medium/lowp). */
unsigned precision:2;
+ /**
+ * Alignment specified via GL_ARB_enhanced_layouts "align" layout qualifier
+ */
+ ast_expression *align;
+
/** Geometry shader invocations for GL_ARB_gpu_shader5. */
ast_layout_expression *invocations;
@@ -1061,10 +1072,9 @@ public:
class ast_interface_block : public ast_node {
public:
- ast_interface_block(ast_type_qualifier layout,
- const char *instance_name,
+ ast_interface_block(const char *instance_name,
ast_array_specifier *array_specifier)
- : layout(layout), block_name(NULL), instance_name(instance_name),
+ : block_name(NULL), instance_name(instance_name),
array_specifier(array_specifier)
{
}
diff --git a/src/compiler/glsl/ast_to_hir.cpp b/src/compiler/glsl/ast_to_hir.cpp
index db5ec9a4ad9..5262bd87655 100644
--- a/src/compiler/glsl/ast_to_hir.cpp
+++ b/src/compiler/glsl/ast_to_hir.cpp
@@ -4223,6 +4223,18 @@ ast_declarator_list::hir(exec_list *instructions,
type_name);
} else {
if (decl_type->base_type == GLSL_TYPE_ARRAY) {
+ /* From Section 13.22 (Array Declarations) of the GLSL ES 3.2
+ * spec:
+ *
+ * "... any declaration that leaves the size undefined is
+ * disallowed as this would add complexity and there are no
+ * use-cases."
+ */
+ if (state->es_shader && decl_type->is_unsized_array()) {
+ _mesa_glsl_error(&loc, state, "array size must be explicitly "
+ "or implicitly defined");
+ }
+
/* From Section 4.12 (Empty Declarations) of the GLSL 4.5 spec:
*
* "The combinations of types and qualifiers that cause
@@ -6244,9 +6256,11 @@ ast_process_struct_or_iface_block_members(exec_list *instructions,
ir_variable_mode var_mode,
ast_type_qualifier *layout,
unsigned block_stream,
- unsigned expl_location)
+ unsigned expl_location,
+ unsigned expl_align)
{
unsigned decl_count = 0;
+ unsigned next_offset = 0;
/* Make an initial pass over the list of fields to determine how
* many there are. Each element in this list is an ast_declarator_list.
@@ -6460,13 +6474,93 @@ ast_process_struct_or_iface_block_members(exec_list *instructions,
}
}
+ /* Offset can only be used with std430 and std140 layouts an initial
+ * value of 0 is used for error detection.
+ */
+ unsigned align = 0;
+ unsigned size = 0;
+ if (layout) {
+ bool row_major;
+ if (qual->flags.q.row_major ||
+ matrix_layout == GLSL_MATRIX_LAYOUT_ROW_MAJOR) {
+ row_major = true;
+ } else {
+ row_major = false;
+ }
+
+ if(layout->flags.q.std140) {
+ align = field_type->std140_base_alignment(row_major);
+ size = field_type->std140_size(row_major);
+ } else if (layout->flags.q.std430) {
+ align = field_type->std430_base_alignment(row_major);
+ size = field_type->std430_size(row_major);
+ }
+ }
+
+ if (qual->flags.q.explicit_offset) {
+ unsigned qual_offset;
+ if (process_qualifier_constant(state, &loc, "offset",
+ qual->offset, &qual_offset)) {
+ if (align != 0 && size != 0) {
+ if (next_offset > qual_offset)
+ _mesa_glsl_error(&loc, state, "layout qualifier "
+ "offset overlaps previous member");
+
+ if (qual_offset % align) {
+ _mesa_glsl_error(&loc, state, "layout qualifier offset "
+ "must be a multiple of the base "
+ "alignment of %s", field_type->name);
+ }
+ fields[i].offset = qual_offset;
+ next_offset = glsl_align(qual_offset + size, align);
+ } else {
+ _mesa_glsl_error(&loc, state, "offset can only be used "
+ "with std430 and std140 layouts");
+ }
+ }
+ } else {
+ fields[i].offset = -1;
+ }
+
+ if (qual->flags.q.explicit_align || expl_align != 0) {
+ unsigned offset = fields[i].offset != -1 ? fields[i].offset :
+ next_offset;
+ if (align == 0 || size == 0) {
+ _mesa_glsl_error(&loc, state, "align can only be used with "
+ "std430 and std140 layouts");
+ } else if (qual->flags.q.explicit_align) {
+ unsigned member_align;
+ if (process_qualifier_constant(state, &loc, "align",
+ qual->align, &member_align)) {
+ if (member_align == 0 ||
+ member_align & (member_align - 1)) {
+ _mesa_glsl_error(&loc, state, "align layout qualifier "
+ "in not a power of 2");
+ } else {
+ fields[i].offset = glsl_align(offset, member_align);
+ next_offset = glsl_align(fields[i].offset + size, align);
+ }
+ }
+ } else {
+ fields[i].offset = glsl_align(offset, expl_align);
+ next_offset = glsl_align(fields[i].offset + size, align);
+ }
+ }
+
+ if (!qual->flags.q.explicit_offset) {
+ if (align != 0 && size != 0)
+ next_offset = glsl_align(next_offset + size, align);
+ }
+
/* Propogate row- / column-major information down the fields of the
* structure or interface block. Structures need this data because
* the structure may contain a structure that contains ... a matrix
* that need the proper layout.
*/
- if (field_type->without_array()->is_matrix()
- || field_type->without_array()->is_record()) {
+ if (is_interface &&
+ (layout->flags.q.uniform || layout->flags.q.buffer) &&
+ (field_type->without_array()->is_matrix()
+ || field_type->without_array()->is_record())) {
/* If no layout is specified for the field, inherit the layout
* from the block.
*/
@@ -6477,11 +6571,10 @@ ast_process_struct_or_iface_block_members(exec_list *instructions,
else if (qual->flags.q.column_major)
fields[i].matrix_layout = GLSL_MATRIX_LAYOUT_COLUMN_MAJOR;
- /* If we're processing an interface block, the matrix layout must
- * be decided by this point.
+ /* If we're processing an uniform or buffer block, the matrix
+ * layout must be decided by this point.
*/
- assert(!is_interface
- || fields[i].matrix_layout == GLSL_MATRIX_LAYOUT_ROW_MAJOR
+ assert(fields[i].matrix_layout == GLSL_MATRIX_LAYOUT_ROW_MAJOR
|| fields[i].matrix_layout == GLSL_MATRIX_LAYOUT_COLUMN_MAJOR);
}
@@ -6553,7 +6646,8 @@ ast_struct_specifier::hir(exec_list *instructions,
ir_var_auto,
layout,
0, /* for interface only */
- expl_location);
+ expl_location,
+ 0 /* for interface only */);
validate_identifier(this->name, loc, state);
@@ -6721,6 +6815,20 @@ ast_interface_block::hir(exec_list *instructions,
}
}
+ unsigned expl_align = 0;
+ if (layout.flags.q.explicit_align) {
+ if (!process_qualifier_constant(state, &loc, "align",
+ layout.align, &expl_align)) {
+ return NULL;
+ } else {
+ if (expl_align == 0 || expl_align & (expl_align - 1)) {
+ _mesa_glsl_error(&loc, state, "align layout qualifier in not a "
+ "power of 2.");
+ return NULL;
+ }
+ }
+ }
+
unsigned int num_variables =
ast_process_struct_or_iface_block_members(&declared_variables,
state,
@@ -6732,7 +6840,8 @@ ast_interface_block::hir(exec_list *instructions,
var_mode,
&this->layout,
qual_stream,
- expl_location);
+ expl_location,
+ expl_align);
if (!redeclaring_per_vertex) {
validate_identifier(this->block_name, loc, state);
@@ -6833,6 +6942,8 @@ ast_interface_block::hir(exec_list *instructions,
} else {
fields[i].location =
earlier_per_vertex->fields.structure[j].location;
+ fields[i].offset =
+ earlier_per_vertex->fields.structure[j].offset;
fields[i].interpolation =
earlier_per_vertex->fields.structure[j].interpolation;
fields[i].centroid =
diff --git a/src/compiler/glsl/ast_type.cpp b/src/compiler/glsl/ast_type.cpp
index dcd83efa6ff..07ed4f2356c 100644
--- a/src/compiler/glsl/ast_type.cpp
+++ b/src/compiler/glsl/ast_type.cpp
@@ -73,6 +73,7 @@ ast_type_qualifier::has_layout() const
|| this->flags.q.column_major
|| this->flags.q.row_major
|| this->flags.q.packed
+ || this->flags.q.explicit_align
|| this->flags.q.explicit_location
|| this->flags.q.explicit_image_format
|| this->flags.q.explicit_index
@@ -134,6 +135,28 @@ ast_type_qualifier::merge_qualifier(YYLTYPE *loc,
stream_layout_mask.flags.i = 0;
stream_layout_mask.flags.q.stream = 1;
+ /* FIXME: We should probably do interface and function param validation
+ * separately.
+ */
+ ast_type_qualifier input_layout_mask;
+ input_layout_mask.flags.i = 0;
+ input_layout_mask.flags.q.centroid = 1;
+ /* Function params can have constant */
+ input_layout_mask.flags.q.constant = 1;
+ input_layout_mask.flags.q.explicit_location = 1;
+ input_layout_mask.flags.q.flat = 1;
+ input_layout_mask.flags.q.in = 1;
+ input_layout_mask.flags.q.invariant = 1;
+ input_layout_mask.flags.q.noperspective = 1;
+ input_layout_mask.flags.q.origin_upper_left = 1;
+ /* Function params 'inout' will set this */
+ input_layout_mask.flags.q.out = 1;
+ input_layout_mask.flags.q.patch = 1;
+ input_layout_mask.flags.q.pixel_center_integer = 1;
+ input_layout_mask.flags.q.precise = 1;
+ input_layout_mask.flags.q.sample = 1;
+ input_layout_mask.flags.q.smooth = 1;
+
/* Uniform block layout qualifiers get to overwrite each
* other (rightmost having priority), while all other
* qualifiers currently don't allow duplicates.
@@ -258,6 +281,16 @@ ast_type_qualifier::merge_qualifier(YYLTYPE *loc,
this->flags.i |= q.flags.i;
+ if (this->flags.q.in &&
+ (this->flags.i & ~input_layout_mask.flags.i) != 0) {
+ _mesa_glsl_error(loc, state,
+ "invalid input layout qualifier used");
+ return false;
+ }
+
+ if (q.flags.q.explicit_align)
+ this->align = q.align;
+
if (q.flags.q.explicit_location)
this->location = q.location;
diff --git a/src/compiler/glsl/builtin_functions.cpp b/src/compiler/glsl/builtin_functions.cpp
index 0a0dcc68a05..ff6b628eb64 100644
--- a/src/compiler/glsl/builtin_functions.cpp
+++ b/src/compiler/glsl/builtin_functions.cpp
@@ -432,6 +432,12 @@ shader_atomic_counters(const _mesa_glsl_parse_state *state)
}
static bool
+shader_atomic_counter_ops(const _mesa_glsl_parse_state *state)
+{
+ return state->ARB_shader_atomic_counter_ops_enable;
+}
+
+static bool
shader_clock(const _mesa_glsl_parse_state *state)
{
return state->ARB_shader_clock_enable;
@@ -578,7 +584,7 @@ private:
ir_dereference_array *array_ref(ir_variable *var, int i);
ir_swizzle *matrix_elt(ir_variable *var, int col, int row);
- ir_expression *asin_expr(ir_variable *x);
+ ir_expression *asin_expr(ir_variable *x, float p0, float p1);
void do_atan(ir_factory &body, const glsl_type *type, ir_variable *res, operand y_over_x);
/**
@@ -792,8 +798,14 @@ private:
B1(interpolateAtSample)
ir_function_signature *_atomic_counter_intrinsic(builtin_available_predicate avail);
+ ir_function_signature *_atomic_counter_intrinsic1(builtin_available_predicate avail);
+ ir_function_signature *_atomic_counter_intrinsic2(builtin_available_predicate avail);
ir_function_signature *_atomic_counter_op(const char *intrinsic,
builtin_available_predicate avail);
+ ir_function_signature *_atomic_counter_op1(const char *intrinsic,
+ builtin_available_predicate avail);
+ ir_function_signature *_atomic_counter_op2(const char *intrinsic,
+ builtin_available_predicate avail);
ir_function_signature *_atomic_intrinsic2(builtin_available_predicate avail,
const glsl_type *type);
@@ -968,48 +980,59 @@ builtin_builder::create_intrinsics()
glsl_type::uint_type),
_atomic_intrinsic2(buffer_atomics_supported,
glsl_type::int_type),
+ _atomic_counter_intrinsic1(shader_atomic_counter_ops),
+ NULL);
+ add_function("__intrinsic_atomic_sub",
+ _atomic_counter_intrinsic1(shader_atomic_counter_ops),
NULL);
add_function("__intrinsic_atomic_min",
_atomic_intrinsic2(buffer_atomics_supported,
glsl_type::uint_type),
_atomic_intrinsic2(buffer_atomics_supported,
glsl_type::int_type),
+ _atomic_counter_intrinsic1(shader_atomic_counter_ops),
NULL);
add_function("__intrinsic_atomic_max",
_atomic_intrinsic2(buffer_atomics_supported,
glsl_type::uint_type),
_atomic_intrinsic2(buffer_atomics_supported,
glsl_type::int_type),
+ _atomic_counter_intrinsic1(shader_atomic_counter_ops),
NULL);
add_function("__intrinsic_atomic_and",
_atomic_intrinsic2(buffer_atomics_supported,
glsl_type::uint_type),
_atomic_intrinsic2(buffer_atomics_supported,
glsl_type::int_type),
+ _atomic_counter_intrinsic1(shader_atomic_counter_ops),
NULL);
add_function("__intrinsic_atomic_or",
_atomic_intrinsic2(buffer_atomics_supported,
glsl_type::uint_type),
_atomic_intrinsic2(buffer_atomics_supported,
glsl_type::int_type),
+ _atomic_counter_intrinsic1(shader_atomic_counter_ops),
NULL);
add_function("__intrinsic_atomic_xor",
_atomic_intrinsic2(buffer_atomics_supported,
glsl_type::uint_type),
_atomic_intrinsic2(buffer_atomics_supported,
glsl_type::int_type),
+ _atomic_counter_intrinsic1(shader_atomic_counter_ops),
NULL);
add_function("__intrinsic_atomic_exchange",
_atomic_intrinsic2(buffer_atomics_supported,
glsl_type::uint_type),
_atomic_intrinsic2(buffer_atomics_supported,
glsl_type::int_type),
+ _atomic_counter_intrinsic1(shader_atomic_counter_ops),
NULL);
add_function("__intrinsic_atomic_comp_swap",
_atomic_intrinsic3(buffer_atomics_supported,
glsl_type::uint_type),
_atomic_intrinsic3(buffer_atomics_supported,
glsl_type::int_type),
+ _atomic_counter_intrinsic2(shader_atomic_counter_ops),
NULL);
add_image_functions(false);
@@ -2714,6 +2737,43 @@ builtin_builder::create_builtins()
shader_atomic_counters),
NULL);
+ add_function("atomicCounterAddARB",
+ _atomic_counter_op1("__intrinsic_atomic_add",
+ shader_atomic_counter_ops),
+ NULL);
+ add_function("atomicCounterSubtractARB",
+ _atomic_counter_op1("__intrinsic_atomic_sub",
+ shader_atomic_counter_ops),
+ NULL);
+ add_function("atomicCounterMinARB",
+ _atomic_counter_op1("__intrinsic_atomic_min",
+ shader_atomic_counter_ops),
+ NULL);
+ add_function("atomicCounterMaxARB",
+ _atomic_counter_op1("__intrinsic_atomic_max",
+ shader_atomic_counter_ops),
+ NULL);
+ add_function("atomicCounterAndARB",
+ _atomic_counter_op1("__intrinsic_atomic_and",
+ shader_atomic_counter_ops),
+ NULL);
+ add_function("atomicCounterOrARB",
+ _atomic_counter_op1("__intrinsic_atomic_or",
+ shader_atomic_counter_ops),
+ NULL);
+ add_function("atomicCounterXorARB",
+ _atomic_counter_op1("__intrinsic_atomic_xor",
+ shader_atomic_counter_ops),
+ NULL);
+ add_function("atomicCounterExchangeARB",
+ _atomic_counter_op1("__intrinsic_atomic_exchange",
+ shader_atomic_counter_ops),
+ NULL);
+ add_function("atomicCounterCompSwapARB",
+ _atomic_counter_op2("__intrinsic_atomic_comp_swap",
+ shader_atomic_counter_ops),
+ NULL);
+
add_function("atomicAdd",
_atomic_op2("__intrinsic_atomic_add",
buffer_atomics_supported,
@@ -3212,7 +3272,7 @@ builtin_builder::_tan(const glsl_type *type)
}
ir_expression *
-builtin_builder::asin_expr(ir_variable *x)
+builtin_builder::asin_expr(ir_variable *x, float p0, float p1)
{
return mul(sign(x),
sub(imm(M_PI_2f),
@@ -3221,8 +3281,8 @@ builtin_builder::asin_expr(ir_variable *x)
mul(abs(x),
add(imm(M_PI_4f - 1.0f),
mul(abs(x),
- add(imm(0.086566724f),
- mul(abs(x), imm(-0.03102955f))))))))));
+ add(imm(p0),
+ mul(abs(x), imm(p1))))))))));
}
ir_call *
@@ -3251,7 +3311,7 @@ builtin_builder::_asin(const glsl_type *type)
ir_variable *x = in_var(type, "x");
MAKE_SIG(type, always_available, 1, x);
- body.emit(ret(asin_expr(x)));
+ body.emit(ret(asin_expr(x, 0.086566724f, -0.03102955f)));
return sig;
}
@@ -3262,7 +3322,7 @@ builtin_builder::_acos(const glsl_type *type)
ir_variable *x = in_var(type, "x");
MAKE_SIG(type, always_available, 1, x);
- body.emit(ret(sub(imm(M_PI_2f), asin_expr(x))));
+ body.emit(ret(sub(imm(M_PI_2f), asin_expr(x, 0.08132463f, -0.02363318f))));
return sig;
}
@@ -5145,6 +5205,25 @@ builtin_builder::_atomic_counter_intrinsic(builtin_available_predicate avail)
}
ir_function_signature *
+builtin_builder::_atomic_counter_intrinsic1(builtin_available_predicate avail)
+{
+ ir_variable *counter = in_var(glsl_type::atomic_uint_type, "counter");
+ ir_variable *data = in_var(glsl_type::uint_type, "data");
+ MAKE_INTRINSIC(glsl_type::uint_type, avail, 2, counter, data);
+ return sig;
+}
+
+ir_function_signature *
+builtin_builder::_atomic_counter_intrinsic2(builtin_available_predicate avail)
+{
+ ir_variable *counter = in_var(glsl_type::atomic_uint_type, "counter");
+ ir_variable *compare = in_var(glsl_type::uint_type, "compare");
+ ir_variable *data = in_var(glsl_type::uint_type, "data");
+ MAKE_INTRINSIC(glsl_type::uint_type, avail, 3, counter, compare, data);
+ return sig;
+}
+
+ir_function_signature *
builtin_builder::_atomic_intrinsic2(builtin_available_predicate avail,
const glsl_type *type)
{
@@ -5180,6 +5259,37 @@ builtin_builder::_atomic_counter_op(const char *intrinsic,
}
ir_function_signature *
+builtin_builder::_atomic_counter_op1(const char *intrinsic,
+ builtin_available_predicate avail)
+{
+ ir_variable *counter = in_var(glsl_type::atomic_uint_type, "atomic_counter");
+ ir_variable *data = in_var(glsl_type::uint_type, "data");
+ MAKE_SIG(glsl_type::uint_type, avail, 2, counter, data);
+
+ ir_variable *retval = body.make_temp(glsl_type::uint_type, "atomic_retval");
+ body.emit(call(shader->symbols->get_function(intrinsic), retval,
+ sig->parameters));
+ body.emit(ret(retval));
+ return sig;
+}
+
+ir_function_signature *
+builtin_builder::_atomic_counter_op2(const char *intrinsic,
+ builtin_available_predicate avail)
+{
+ ir_variable *counter = in_var(glsl_type::atomic_uint_type, "atomic_counter");
+ ir_variable *compare = in_var(glsl_type::uint_type, "compare");
+ ir_variable *data = in_var(glsl_type::uint_type, "data");
+ MAKE_SIG(glsl_type::uint_type, avail, 3, counter, compare, data);
+
+ ir_variable *retval = body.make_temp(glsl_type::uint_type, "atomic_retval");
+ body.emit(call(shader->symbols->get_function(intrinsic), retval,
+ sig->parameters));
+ body.emit(ret(retval));
+ return sig;
+}
+
+ir_function_signature *
builtin_builder::_atomic_op2(const char *intrinsic,
builtin_available_predicate avail,
const glsl_type *type)
diff --git a/src/compiler/glsl/builtin_variables.cpp b/src/compiler/glsl/builtin_variables.cpp
index d20fc4a816c..4e2de37fbba 100644
--- a/src/compiler/glsl/builtin_variables.cpp
+++ b/src/compiler/glsl/builtin_variables.cpp
@@ -323,6 +323,7 @@ per_vertex_accumulator::add_field(int slot, const glsl_type *type,
this->fields[this->num_fields].name = name;
this->fields[this->num_fields].matrix_layout = GLSL_MATRIX_LAYOUT_INHERITED;
this->fields[this->num_fields].location = slot;
+ this->fields[this->num_fields].offset = -1;
this->fields[this->num_fields].interpolation = INTERP_QUALIFIER_NONE;
this->fields[this->num_fields].centroid = 0;
this->fields[this->num_fields].sample = 0;
diff --git a/src/compiler/glsl/glcpp/glcpp-lex.l b/src/compiler/glsl/glcpp/glcpp-lex.l
index fa9aa506912..d09441aac88 100644
--- a/src/compiler/glsl/glcpp/glcpp-lex.l
+++ b/src/compiler/glsl/glcpp/glcpp-lex.l
@@ -120,6 +120,11 @@ void glcpp_set_column (int column_no , yyscan_t yyscanner);
static int
glcpp_lex_update_state_per_token (glcpp_parser_t *parser, int token)
{
+ if (token != NEWLINE && token != SPACE && token != HASH_TOKEN &&
+ !parser->lexing_version_directive) {
+ glcpp_parser_resolve_implicit_version(parser);
+ }
+
/* After the first non-space token in a line, we won't
* allow any '#' to introduce a directive. */
if (token == NEWLINE) {
@@ -285,6 +290,7 @@ HEXADECIMAL_INTEGER 0[xX][0-9a-fA-F]+[uU]?
<HASH>version{HSPACE}+ {
BEGIN INITIAL;
yyextra->space_tokens = 0;
+ yyextra->lexing_version_directive = 1;
RETURN_STRING_TOKEN (VERSION_TOKEN);
}
@@ -314,6 +320,9 @@ HEXADECIMAL_INTEGER 0[xX][0-9a-fA-F]+[uU]?
<HASH>{NEWLINE} {
BEGIN INITIAL;
+ yyextra->space_tokens = 0;
+ yylineno++;
+ yycolumn = 0;
RETURN_TOKEN_NEVER_SKIP (NEWLINE);
}
@@ -536,6 +545,7 @@ HEXADECIMAL_INTEGER 0[xX][0-9a-fA-F]+[uU]?
}
yyextra->space_tokens = 1;
yyextra->lexing_directive = 0;
+ yyextra->lexing_version_directive = 0;
yylineno++;
yycolumn = 0;
RETURN_TOKEN_NEVER_SKIP (NEWLINE);
@@ -546,6 +556,7 @@ HEXADECIMAL_INTEGER 0[xX][0-9a-fA-F]+[uU]?
glcpp_error(yylloc, yyextra, "Unterminated comment");
BEGIN DONE; /* Don't keep matching this rule forever. */
yyextra->lexing_directive = 0;
+ yyextra->lexing_version_directive = 0;
if (! parser->last_token_was_newline)
RETURN_TOKEN (NEWLINE);
}
diff --git a/src/compiler/glsl/glcpp/glcpp-parse.y b/src/compiler/glsl/glcpp/glcpp-parse.y
index 5c38f86d333..007b70b020d 100644
--- a/src/compiler/glsl/glcpp/glcpp-parse.y
+++ b/src/compiler/glsl/glcpp/glcpp-parse.y
@@ -266,45 +266,37 @@ control_line:
ralloc_asprintf_rewrite_tail (&parser->output, &parser->output_length, "\n");
}
| control_line_error
-| HASH_TOKEN LINE {
- glcpp_parser_resolve_implicit_version(parser);
- } pp_tokens NEWLINE {
+| HASH_TOKEN LINE pp_tokens NEWLINE {
if (parser->skip_stack == NULL ||
parser->skip_stack->type == SKIP_NO_SKIP)
{
_glcpp_parser_expand_and_lex_from (parser,
- LINE_EXPANDED, $4,
+ LINE_EXPANDED, $3,
EXPANSION_MODE_IGNORE_DEFINED);
}
}
;
control_line_success:
- HASH_TOKEN DEFINE_TOKEN {
- glcpp_parser_resolve_implicit_version(parser);
- } define
-| HASH_TOKEN UNDEF {
- glcpp_parser_resolve_implicit_version(parser);
- } IDENTIFIER NEWLINE {
+ HASH_TOKEN DEFINE_TOKEN define
+| HASH_TOKEN UNDEF IDENTIFIER NEWLINE {
macro_t *macro;
- if (strcmp("__LINE__", $4) == 0
- || strcmp("__FILE__", $4) == 0
- || strcmp("__VERSION__", $4) == 0
- || strncmp("GL_", $4, 3) == 0)
+ if (strcmp("__LINE__", $3) == 0
+ || strcmp("__FILE__", $3) == 0
+ || strcmp("__VERSION__", $3) == 0
+ || strncmp("GL_", $3, 3) == 0)
glcpp_error(& @1, parser, "Built-in (pre-defined)"
" macro names cannot be undefined.");
- macro = hash_table_find (parser->defines, $4);
+ macro = hash_table_find (parser->defines, $3);
if (macro) {
- hash_table_remove (parser->defines, $4);
+ hash_table_remove (parser->defines, $3);
ralloc_free (macro);
}
- ralloc_free ($4);
+ ralloc_free ($3);
}
-| HASH_TOKEN IF {
- glcpp_parser_resolve_implicit_version(parser);
- } pp_tokens NEWLINE {
+| HASH_TOKEN IF pp_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
@@ -316,7 +308,7 @@ control_line_success:
parser->skip_stack->type == SKIP_NO_SKIP)
{
_glcpp_parser_expand_and_lex_from (parser,
- IF_EXPANDED, $4,
+ IF_EXPANDED, $3,
EXPANSION_MODE_EVALUATE_DEFINED);
}
else
@@ -335,18 +327,14 @@ control_line_success:
}
_glcpp_parser_skip_stack_push_if (parser, & @1, 0);
}
-| HASH_TOKEN IFDEF {
- glcpp_parser_resolve_implicit_version(parser);
- } IDENTIFIER junk NEWLINE {
- macro_t *macro = hash_table_find (parser->defines, $4);
- ralloc_free ($4);
+| HASH_TOKEN IFDEF 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_TOKEN IFNDEF {
- glcpp_parser_resolve_implicit_version(parser);
- } IDENTIFIER junk NEWLINE {
- macro_t *macro = hash_table_find (parser->defines, $4);
- ralloc_free ($4);
+| HASH_TOKEN IFNDEF IDENTIFIER junk NEWLINE {
+ macro_t *macro = hash_table_find (parser->defines, $3);
+ ralloc_free ($3);
_glcpp_parser_skip_stack_push_if (parser, & @3, macro == NULL);
}
| HASH_TOKEN ELIF pp_tokens NEWLINE {
@@ -2494,6 +2482,9 @@ _glcpp_parser_handle_version_declaration(glcpp_parser_t *parser, intmax_t versio
if (extensions->ARB_shader_atomic_counters)
add_builtin_define(parser, "GL_ARB_shader_atomic_counters", 1);
+ if (extensions->ARB_shader_atomic_counter_ops)
+ add_builtin_define(parser, "GL_ARB_shader_atomic_counter_ops", 1);
+
if (extensions->ARB_viewport_array)
add_builtin_define(parser, "GL_ARB_viewport_array", 1);
diff --git a/src/compiler/glsl/glcpp/glcpp.h b/src/compiler/glsl/glcpp/glcpp.h
index 70aa14b6ec0..d87e6b77dc5 100644
--- a/src/compiler/glsl/glcpp/glcpp.h
+++ b/src/compiler/glsl/glcpp/glcpp.h
@@ -176,6 +176,7 @@ struct glcpp_parser {
struct hash_table *defines;
active_list_t *active;
int lexing_directive;
+ int lexing_version_directive;
int space_tokens;
int last_token_was_newline;
int last_token_was_space;
diff --git a/src/compiler/glsl/glcpp/tests/129-define-non-identifier.c.expected b/src/compiler/glsl/glcpp/tests/129-define-non-identifier.c.expected
index fd0b41347fa..5206a5c553c 100644
--- a/src/compiler/glsl/glcpp/tests/129-define-non-identifier.c.expected
+++ b/src/compiler/glsl/glcpp/tests/129-define-non-identifier.c.expected
@@ -1,2 +1,2 @@
0:1(9): preprocessor error: #define followed by a non-identifier: 123
-0:1(9): preprocessor error: syntax error, unexpected INTEGER_STRING, expecting FUNC_IDENTIFIER or OBJ_IDENTIFIER
+0:1(9): preprocessor error: syntax error, unexpected INTEGER_STRING, expecting FUNC_IDENTIFIER or OBJ_IDENTIFIER or NEWLINE
diff --git a/src/compiler/glsl/glcpp/tests/144-implicit-version.c b/src/compiler/glsl/glcpp/tests/144-implicit-version.c
new file mode 100644
index 00000000000..7bf72fc19e9
--- /dev/null
+++ b/src/compiler/glsl/glcpp/tests/144-implicit-version.c
@@ -0,0 +1 @@
+int x = __VERSION__;
diff --git a/src/compiler/glsl/glcpp/tests/144-implicit-version.c.expected b/src/compiler/glsl/glcpp/tests/144-implicit-version.c.expected
new file mode 100644
index 00000000000..8c2dfd9ce30
--- /dev/null
+++ b/src/compiler/glsl/glcpp/tests/144-implicit-version.c.expected
@@ -0,0 +1 @@
+int x = 110;
diff --git a/src/compiler/glsl/glcpp/tests/145-version-first.c b/src/compiler/glsl/glcpp/tests/145-version-first.c
new file mode 100644
index 00000000000..f9fcfb08246
--- /dev/null
+++ b/src/compiler/glsl/glcpp/tests/145-version-first.c
@@ -0,0 +1,2 @@
+123
+#version 120
diff --git a/src/compiler/glsl/glcpp/tests/145-version-first.c.expected b/src/compiler/glsl/glcpp/tests/145-version-first.c.expected
new file mode 100644
index 00000000000..f4092b04af7
--- /dev/null
+++ b/src/compiler/glsl/glcpp/tests/145-version-first.c.expected
@@ -0,0 +1,3 @@
+0:2(1): preprocessor error: #version must appear on the first line
+123
+
diff --git a/src/compiler/glsl/glcpp/tests/146-version-first-hash.c b/src/compiler/glsl/glcpp/tests/146-version-first-hash.c
new file mode 100644
index 00000000000..14dbe964bd6
--- /dev/null
+++ b/src/compiler/glsl/glcpp/tests/146-version-first-hash.c
@@ -0,0 +1,2 @@
+#
+#version 120
diff --git a/src/compiler/glsl/glcpp/tests/146-version-first-hash.c.expected b/src/compiler/glsl/glcpp/tests/146-version-first-hash.c.expected
new file mode 100644
index 00000000000..e8e449793fd
--- /dev/null
+++ b/src/compiler/glsl/glcpp/tests/146-version-first-hash.c.expected
@@ -0,0 +1,3 @@
+0:2(1): preprocessor error: #version must appear on the first line
+
+
diff --git a/src/compiler/glsl/glsl_parser.yy b/src/compiler/glsl/glsl_parser.yy
index 99bd0e61d0e..5ed051a6705 100644
--- a/src/compiler/glsl/glsl_parser.yy
+++ b/src/compiler/glsl/glsl_parser.yy
@@ -170,7 +170,6 @@ static bool match_layout_qualifier(const char *s1, const char *s2,
%token <identifier> IDENTIFIER TYPE_IDENTIFIER NEW_IDENTIFIER
%type <identifier> any_identifier
%type <interface_block> instance_name_opt
-%type <interface_block> buffer_instance_name_opt
%token <real> FLOATCONSTANT
%token <dreal> DOUBLECONSTANT
%token <n> INTCONSTANT UINTCONSTANT BOOLCONSTANT
@@ -220,6 +219,7 @@ static bool match_layout_qualifier(const char *s1, const char *s2,
%type <type_qualifier> subroutine_qualifier
%type <subroutine_list> subroutine_type_list
%type <type_qualifier> interface_qualifier
+%type <type_qualifier> uniform_interface_qualifier
%type <type_qualifier> buffer_interface_qualifier
%type <type_specifier> type_specifier
%type <type_specifier> type_specifier_nonarray
@@ -894,6 +894,7 @@ parameter_declarator:
$$->type->set_location(@1);
$$->type->specifier = $1;
$$->identifier = $2;
+ state->symbols->add_variable(new(state) ir_variable(NULL, $2, ir_var_auto));
}
| type_specifier any_identifier array_specifier
{
@@ -905,6 +906,7 @@ parameter_declarator:
$$->type->specifier = $1;
$$->identifier = $2;
$$->array_specifier = $3;
+ state->symbols->add_variable(new(state) ir_variable(NULL, $2, ir_var_auto));
}
;
@@ -1062,6 +1064,7 @@ single_declaration:
$$ = new(ctx) ast_declarator_list($1);
$$->set_location_range(@1, @2);
$$->declarations.push_tail(&decl->link);
+ state->symbols->add_variable(new(state) ir_variable(NULL, $2, ir_var_auto));
}
| fully_specified_type any_identifier array_specifier
{
@@ -1072,6 +1075,7 @@ single_declaration:
$$ = new(ctx) ast_declarator_list($1);
$$->set_location_range(@1, @3);
$$->declarations.push_tail(&decl->link);
+ state->symbols->add_variable(new(state) ir_variable(NULL, $2, ir_var_auto));
}
| fully_specified_type any_identifier array_specifier '=' initializer
{
@@ -1082,6 +1086,7 @@ single_declaration:
$$ = new(ctx) ast_declarator_list($1);
$$->set_location_range(@1, @3);
$$->declarations.push_tail(&decl->link);
+ state->symbols->add_variable(new(state) ir_variable(NULL, $2, ir_var_auto));
}
| fully_specified_type any_identifier '=' initializer
{
@@ -1092,6 +1097,7 @@ single_declaration:
$$ = new(ctx) ast_declarator_list($1);
$$->set_location_range(@1, @2);
$$->declarations.push_tail(&decl->link);
+ state->symbols->add_variable(new(state) ir_variable(NULL, $2, ir_var_auto));
}
| INVARIANT variable_identifier
{
@@ -1468,6 +1474,17 @@ layout_qualifier_id:
"GLSL 4.40 or ARB_enhanced_layouts");
}
+ if (match_layout_qualifier("align", $1, state) == 0) {
+ if (!state->has_enhanced_layouts()) {
+ _mesa_glsl_error(& @1, state,
+ "align qualifier requires "
+ "GLSL 4.40 or ARB_enhanced_layouts");
+ } else {
+ $$.flags.q.explicit_align = 1;
+ $$.align = $3;
+ }
+ }
+
if (match_layout_qualifier("location", $1, state) == 0) {
$$.flags.q.explicit_location = 1;
@@ -1498,7 +1515,8 @@ layout_qualifier_id:
$$.binding = $3;
}
- if (state->has_atomic_counters() &&
+ if ((state->has_atomic_counters() ||
+ state->has_enhanced_layouts()) &&
match_layout_qualifier("offset", $1, state) == 0) {
$$.flags.q.explicit_offset = 1;
$$.offset = $3;
@@ -2625,10 +2643,23 @@ basic_interface_block:
$$ = block;
}
- | buffer_interface_qualifier NEW_IDENTIFIER '{' member_list '}' buffer_instance_name_opt ';'
+ | uniform_interface_qualifier NEW_IDENTIFIER '{' member_list '}' instance_name_opt ';'
+ {
+ ast_interface_block *const block = $6;
+
+ block->layout = *state->default_uniform_qualifier;
+ block->block_name = $2;
+ block->declarations.push_degenerate_list_at_head(& $4->link);
+
+ _mesa_ast_process_interface_block(& @1, state, block, $1);
+
+ $$ = block;
+ }
+ | buffer_interface_qualifier NEW_IDENTIFIER '{' member_list '}' instance_name_opt ';'
{
ast_interface_block *const block = $6;
+ block->layout = *state->default_shader_storage_qualifier;
block->block_name = $2;
block->declarations.push_degenerate_list_at_head(& $4->link);
@@ -2649,7 +2680,10 @@ interface_qualifier:
memset(& $$, 0, sizeof($$));
$$.flags.q.out = 1;
}
- | UNIFORM
+ ;
+
+uniform_interface_qualifier:
+ UNIFORM
{
memset(& $$, 0, sizeof($$));
$$.flags.q.uniform = 1;
@@ -2667,39 +2701,16 @@ buffer_interface_qualifier:
instance_name_opt:
/* empty */
{
- $$ = new(state) ast_interface_block(*state->default_uniform_qualifier,
- NULL, NULL);
- }
- | NEW_IDENTIFIER
- {
- $$ = new(state) ast_interface_block(*state->default_uniform_qualifier,
- $1, NULL);
- $$->set_location(@1);
- }
- | NEW_IDENTIFIER array_specifier
- {
- $$ = new(state) ast_interface_block(*state->default_uniform_qualifier,
- $1, $2);
- $$->set_location_range(@1, @2);
- }
- ;
-
-buffer_instance_name_opt:
- /* empty */
- {
- $$ = new(state) ast_interface_block(*state->default_shader_storage_qualifier,
- NULL, NULL);
+ $$ = new(state) ast_interface_block(NULL, NULL);
}
| NEW_IDENTIFIER
{
- $$ = new(state) ast_interface_block(*state->default_shader_storage_qualifier,
- $1, NULL);
+ $$ = new(state) ast_interface_block($1, NULL);
$$->set_location(@1);
}
| NEW_IDENTIFIER array_specifier
{
- $$ = new(state) ast_interface_block(*state->default_shader_storage_qualifier,
- $1, $2);
+ $$ = new(state) ast_interface_block($1, $2);
$$->set_location_range(@1, @2);
}
;
diff --git a/src/compiler/glsl/glsl_parser_extras.cpp b/src/compiler/glsl/glsl_parser_extras.cpp
index fe8b3bb2e79..1ac8489b45a 100644
--- a/src/compiler/glsl/glsl_parser_extras.cpp
+++ b/src/compiler/glsl/glsl_parser_extras.cpp
@@ -575,6 +575,7 @@ static const _mesa_glsl_extension _mesa_glsl_supported_extensions[] = {
EXT(ARB_gpu_shader_fp64, true, false, ARB_gpu_shader_fp64),
EXT(ARB_sample_shading, true, false, ARB_sample_shading),
EXT(ARB_separate_shader_objects, true, false, dummy_true),
+ EXT(ARB_shader_atomic_counter_ops, true, false, ARB_shader_atomic_counter_ops),
EXT(ARB_shader_atomic_counters, true, false, ARB_shader_atomic_counters),
EXT(ARB_shader_bit_encoding, true, false, ARB_shader_bit_encoding),
EXT(ARB_shader_clock, true, false, ARB_shader_clock),
@@ -926,7 +927,8 @@ _mesa_ast_process_interface_block(YYLTYPE *locp,
block->layout.flags.i |= block_interface_qualifier;
if (state->stage == MESA_SHADER_GEOMETRY &&
- state->has_explicit_attrib_stream()) {
+ state->has_explicit_attrib_stream() &&
+ block->layout.flags.q.out) {
/* Assign global layout's stream value. */
block->layout.flags.q.stream = 1;
block->layout.flags.q.explicit_stream = 0;
diff --git a/src/compiler/glsl/glsl_parser_extras.h b/src/compiler/glsl/glsl_parser_extras.h
index 74825a0bd35..12a3a46928c 100644
--- a/src/compiler/glsl/glsl_parser_extras.h
+++ b/src/compiler/glsl/glsl_parser_extras.h
@@ -533,6 +533,8 @@ struct _mesa_glsl_parse_state {
bool ARB_sample_shading_warn;
bool ARB_separate_shader_objects_enable;
bool ARB_separate_shader_objects_warn;
+ bool ARB_shader_atomic_counter_ops_enable;
+ bool ARB_shader_atomic_counter_ops_warn;
bool ARB_shader_atomic_counters_enable;
bool ARB_shader_atomic_counters_warn;
bool ARB_shader_bit_encoding_enable;
diff --git a/src/compiler/glsl/ir.h b/src/compiler/glsl/ir.h
index f6ed16de0c3..f4519679ff3 100644
--- a/src/compiler/glsl/ir.h
+++ b/src/compiler/glsl/ir.h
@@ -866,7 +866,7 @@ public:
unsigned stream;
/**
- * Location an atomic counter is stored at.
+ * Atomic or block member offset.
*/
unsigned offset;
diff --git a/src/compiler/glsl/ir_builder.cpp b/src/compiler/glsl/ir_builder.cpp
index c9cf1240dfe..d68647f4234 100644
--- a/src/compiler/glsl/ir_builder.cpp
+++ b/src/compiler/glsl/ir_builder.cpp
@@ -51,7 +51,7 @@ assign(deref lhs, operand rhs, operand condition, int writemask)
void *mem_ctx = ralloc_parent(lhs.val);
ir_assignment *assign = new(mem_ctx) ir_assignment(lhs.val,
- rhs.val,
+ rhs.val,
condition.val,
writemask);
@@ -89,11 +89,11 @@ swizzle(operand a, int swizzle, int components)
void *mem_ctx = ralloc_parent(a.val);
return new(mem_ctx) ir_swizzle(a.val,
- GET_SWZ(swizzle, 0),
- GET_SWZ(swizzle, 1),
- GET_SWZ(swizzle, 2),
- GET_SWZ(swizzle, 3),
- components);
+ GET_SWZ(swizzle, 0),
+ GET_SWZ(swizzle, 1),
+ GET_SWZ(swizzle, 2),
+ GET_SWZ(swizzle, 3),
+ components);
}
ir_swizzle *
diff --git a/src/compiler/glsl/link_interface_blocks.cpp b/src/compiler/glsl/link_interface_blocks.cpp
index 64c30fea9a3..4c6fb56f891 100644
--- a/src/compiler/glsl/link_interface_blocks.cpp
+++ b/src/compiler/glsl/link_interface_blocks.cpp
@@ -81,6 +81,66 @@ intrastage_match(ir_variable *a,
return true;
}
+/**
+ * Return true if interface members mismatch and its not allowed by GLSL.
+ */
+static bool
+interstage_member_mismatch(struct gl_shader_program *prog,
+ const glsl_type *c, const glsl_type *p) {
+
+ if (c->length != p->length)
+ return true;
+
+ for (unsigned i = 0; i < c->length; i++) {
+ if (c->fields.structure[i].type != p->fields.structure[i].type)
+ return true;
+ if (strcmp(c->fields.structure[i].name,
+ p->fields.structure[i].name) != 0)
+ return true;
+ if (c->fields.structure[i].location !=
+ p->fields.structure[i].location)
+ return true;
+ if (c->fields.structure[i].patch !=
+ p->fields.structure[i].patch)
+ return true;
+
+ /* From Section 4.5 (Interpolation Qualifiers) of the GLSL 4.40 spec:
+ *
+ * "It is a link-time error if, within the same stage, the
+ * interpolation qualifiers of variables of the same name do not
+ * match."
+ */
+ if (prog->IsES || prog->Version < 440)
+ if (c->fields.structure[i].interpolation !=
+ p->fields.structure[i].interpolation)
+ return true;
+
+ /* From Section 4.3.4 (Input Variables) of the GLSL ES 3.0 spec:
+ *
+ * "The output of the vertex shader and the input of the fragment
+ * shader form an interface. For this interface, vertex shader
+ * output variables and fragment shader input variables of the same
+ * name must match in type and qualification (other than precision
+ * and out matching to in).
+ *
+ * The table in Section 9.2.1 Linked Shaders of the GLSL ES 3.1 spec
+ * says that centroid no longer needs to match for varyings.
+ *
+ * The table in Section 9.2.1 Linked Shaders of the GLSL ES 3.2 spec
+ * says that sample need not match for varyings.
+ */
+ if (!prog->IsES || prog->Version < 310)
+ if (c->fields.structure[i].centroid !=
+ p->fields.structure[i].centroid)
+ return true;
+ if (!prog->IsES)
+ if (c->fields.structure[i].sample !=
+ p->fields.structure[i].sample)
+ return true;
+ }
+
+ return false;
+}
/**
* Check if two interfaces match, according to interstage (in/out) interface
@@ -90,10 +150,9 @@ intrastage_match(ir_variable *a,
* an array and the producer interface is required to be a non-array.
* This is used for tessellation control and geometry shader consumers.
*/
-bool
-interstage_match(ir_variable *producer,
- ir_variable *consumer,
- bool extra_array_level)
+static bool
+interstage_match(struct gl_shader_program *prog, ir_variable *producer,
+ ir_variable *consumer, bool extra_array_level)
{
/* Unsized arrays should not occur during interstage linking. They
* should have all been assigned a size by link_intrastage_shaders.
@@ -106,9 +165,16 @@ interstage_match(ir_variable *producer,
/* Exception: if both the interface blocks are implicitly declared,
* don't force their types to match. They might mismatch due to the two
* shaders using different GLSL versions, and that's ok.
+ *
+ * Also we store some member information such as interpolation in
+ * glsl_type that doesn't always have to match across shader stages.
+ * Therefore we make a pass over the members glsl_struct_field to make
+ * sure we don't reject shaders where fields don't need to match.
*/
- if (consumer->data.how_declared != ir_var_declared_implicitly ||
- producer->data.how_declared != ir_var_declared_implicitly)
+ if ((consumer->data.how_declared != ir_var_declared_implicitly ||
+ producer->data.how_declared != ir_var_declared_implicitly) &&
+ interstage_member_mismatch(prog, consumer->get_interface_type(),
+ producer->get_interface_type()))
return false;
}
@@ -311,7 +377,7 @@ validate_interstage_inout_blocks(struct gl_shader_program *prog,
if (consumer_def == NULL)
continue;
- if (!interstage_match(var, consumer_def, extra_array_level)) {
+ if (!interstage_match(prog, var, consumer_def, extra_array_level)) {
linker_error(prog, "definitions of interface block `%s' do not "
"match\n", var->get_interface_type()->name);
return;
diff --git a/src/compiler/glsl/link_uniform_blocks.cpp b/src/compiler/glsl/link_uniform_blocks.cpp
index 7d755765852..c8fa181a15d 100644
--- a/src/compiler/glsl/link_uniform_blocks.cpp
+++ b/src/compiler/glsl/link_uniform_blocks.cpp
@@ -97,6 +97,11 @@ private:
this->offset, type->std140_base_alignment(row_major));
}
+ virtual void set_buffer_offset(unsigned offset)
+ {
+ this->offset = offset;
+ }
+
virtual void visit_field(const glsl_type *type, const char *name,
bool row_major, const glsl_type *,
const unsigned packing,
diff --git a/src/compiler/glsl/link_uniforms.cpp b/src/compiler/glsl/link_uniforms.cpp
index deaba94df1c..940cc61181d 100644
--- a/src/compiler/glsl/link_uniforms.cpp
+++ b/src/compiler/glsl/link_uniforms.cpp
@@ -188,12 +188,15 @@ program_resource_visitor::recursion(const glsl_type *t, char **name,
this->enter_record(t, *name, row_major, packing);
for (unsigned i = 0; i < t->length; i++) {
- const char *field = t->fields.structure[i].name;
- size_t new_length = name_length;
+ const char *field = t->fields.structure[i].name;
+ size_t new_length = name_length;
if (t->fields.structure[i].type->is_record())
this->visit_field(&t->fields.structure[i]);
+ if (t->is_interface() && t->fields.structure[i].offset != -1)
+ this->set_buffer_offset(t->fields.structure[i].offset);
+
/* Append '.field' to the current variable name. */
if (name_length == 0) {
ralloc_asprintf_rewrite_tail(name, &new_length, "%s", field);
@@ -247,10 +250,10 @@ program_resource_visitor::recursion(const glsl_type *t, char **name,
record_array_count *= length;
for (unsigned i = 0; i < length; i++) {
- size_t new_length = name_length;
+ size_t new_length = name_length;
- /* Append the subscript to the current variable name */
- ralloc_asprintf_rewrite_tail(name, &new_length, "[%u]", i);
+ /* Append the subscript to the current variable name */
+ ralloc_asprintf_rewrite_tail(name, &new_length, "[%u]", i);
recursion(t->fields.array, name, new_length, row_major,
record_type,
@@ -298,6 +301,11 @@ program_resource_visitor::leave_record(const glsl_type *, const char *, bool,
}
void
+program_resource_visitor::set_buffer_offset(unsigned)
+{
+}
+
+void
program_resource_visitor::set_record_array_count(unsigned)
{
}
@@ -415,19 +423,19 @@ private:
if(!is_shader_storage)
this->num_shader_uniform_components += values;
} else {
- /* Accumulate the total number of uniform slots used by this shader.
- * Note that samplers do not count against this limit because they
- * don't use any storage on current hardware.
- */
- if (!is_ubo_var && !is_shader_storage)
- this->num_shader_uniform_components += values;
+ /* Accumulate the total number of uniform slots used by this shader.
+ * Note that samplers do not count against this limit because they
+ * don't use any storage on current hardware.
+ */
+ if (!is_ubo_var && !is_shader_storage)
+ this->num_shader_uniform_components += values;
}
/* If the uniform is already in the map, there's nothing more to do.
*/
unsigned id;
if (this->map->get(id, name))
- return;
+ return;
if (this->current_var->data.how_declared == ir_var_hidden) {
this->hidden_map->put(this->num_hidden_uniforms, name);
@@ -473,8 +481,8 @@ class parcel_out_uniform_storage : public program_resource_visitor {
public:
parcel_out_uniform_storage(struct gl_shader_program *prog,
struct string_to_uint_map *map,
- struct gl_uniform_storage *uniforms,
- union gl_constant_value *values)
+ struct gl_uniform_storage *uniforms,
+ union gl_constant_value *values)
: prog(prog), map(map), uniforms(uniforms), values(values)
{
}
@@ -520,9 +528,9 @@ public:
ubo_block_index = i;
break;
}
- }
- }
- assert(ubo_block_index != -1);
+ }
+ }
+ assert(ubo_block_index != -1);
/* Uniform blocks that were specified with an instance name must be
* handled a little bit differently. The name of the variable is the
@@ -676,6 +684,11 @@ private:
}
}
+ virtual void set_buffer_offset(unsigned offset)
+ {
+ this->ubo_byte_offset = offset;
+ }
+
virtual void set_record_array_count(unsigned record_array_count)
{
this->record_array_count = record_array_count;
@@ -730,15 +743,15 @@ private:
assert(found);
if (!found)
- return;
+ return;
const glsl_type *base_type;
if (type->is_array()) {
- this->uniforms[id].array_elements = type->length;
- base_type = type->fields.array;
+ this->uniforms[id].array_elements = type->length;
+ base_type = type->fields.array;
} else {
- this->uniforms[id].array_elements = 0;
- base_type = type;
+ this->uniforms[id].array_elements = 0;
+ base_type = type;
}
/* Initialise opaque data */
@@ -822,11 +835,11 @@ private:
this->uniforms[id].array_stride =
glsl_align(type->without_array()->std140_size(row_major),
16);
- } else {
- this->uniforms[id].array_stride = 0;
- }
+ } else {
+ this->uniforms[id].array_stride = 0;
+ }
- if (type->without_array()->is_matrix()) {
+ if (type->without_array()->is_matrix()) {
const glsl_type *matrix = type->without_array();
const unsigned N = matrix->base_type == GLSL_TYPE_DOUBLE ? 8 : 4;
const unsigned items =
@@ -838,17 +851,17 @@ private:
glsl_align(items * N, 16);
else
this->uniforms[id].matrix_stride = glsl_align(items * N, 16);
- this->uniforms[id].row_major = row_major;
- } else {
- this->uniforms[id].matrix_stride = 0;
- this->uniforms[id].row_major = false;
- }
+ this->uniforms[id].row_major = row_major;
+ } else {
+ this->uniforms[id].matrix_stride = 0;
+ this->uniforms[id].row_major = false;
+ }
} else {
- this->uniforms[id].block_index = -1;
- this->uniforms[id].offset = -1;
- this->uniforms[id].array_stride = -1;
- this->uniforms[id].matrix_stride = -1;
- this->uniforms[id].row_major = false;
+ this->uniforms[id].block_index = -1;
+ this->uniforms[id].offset = -1;
+ this->uniforms[id].array_stride = -1;
+ this->uniforms[id].matrix_stride = -1;
+ this->uniforms[id].row_major = false;
}
this->values += values_for_type(type);
@@ -914,36 +927,36 @@ public:
*/
int
link_cross_validate_uniform_block(void *mem_ctx,
- struct gl_uniform_block **linked_blocks,
- unsigned int *num_linked_blocks,
- struct gl_uniform_block *new_block)
+ struct gl_uniform_block **linked_blocks,
+ unsigned int *num_linked_blocks,
+ struct gl_uniform_block *new_block)
{
for (unsigned int i = 0; i < *num_linked_blocks; i++) {
struct gl_uniform_block *old_block = &(*linked_blocks)[i];
if (strcmp(old_block->Name, new_block->Name) == 0)
- return link_uniform_blocks_are_compatible(old_block, new_block)
- ? i : -1;
+ return link_uniform_blocks_are_compatible(old_block, new_block)
+ ? i : -1;
}
*linked_blocks = reralloc(mem_ctx, *linked_blocks,
- struct gl_uniform_block,
- *num_linked_blocks + 1);
+ struct gl_uniform_block,
+ *num_linked_blocks + 1);
int linked_block_index = (*num_linked_blocks)++;
struct gl_uniform_block *linked_block = &(*linked_blocks)[linked_block_index];
memcpy(linked_block, new_block, sizeof(*new_block));
linked_block->Uniforms = ralloc_array(*linked_blocks,
- struct gl_uniform_buffer_variable,
- linked_block->NumUniforms);
+ struct gl_uniform_buffer_variable,
+ linked_block->NumUniforms);
memcpy(linked_block->Uniforms,
- new_block->Uniforms,
- sizeof(*linked_block->Uniforms) * linked_block->NumUniforms);
+ new_block->Uniforms,
+ sizeof(*linked_block->Uniforms) * linked_block->NumUniforms);
for (unsigned int i = 0; i < linked_block->NumUniforms; i++) {
struct gl_uniform_buffer_variable *ubo_var =
- &linked_block->Uniforms[i];
+ &linked_block->Uniforms[i];
if (ubo_var->Name == ubo_var->IndexName) {
ubo_var->Name = ralloc_strdup(*linked_blocks, ubo_var->Name);
@@ -970,7 +983,7 @@ link_update_uniform_buffer_variables(struct gl_shader *shader)
ir_variable *const var = node->as_variable();
if ((var == NULL) || !var->is_in_buffer_block())
- continue;
+ continue;
assert(var->data.mode == ir_var_uniform ||
var->data.mode == ir_var_shader_storage);
@@ -992,7 +1005,7 @@ link_update_uniform_buffer_variables(struct gl_shader *shader)
const unsigned l = strlen(var->name);
for (unsigned i = 0; i < shader->NumBufferInterfaceBlocks; i++) {
- for (unsigned j = 0; j < shader->BufferInterfaceBlocks[i].NumUniforms; j++) {
+ for (unsigned j = 0; j < shader->BufferInterfaceBlocks[i].NumUniforms; j++) {
if (sentinel) {
const char *begin = shader->BufferInterfaceBlocks[i].Uniforms[j].Name;
const char *end = strchr(begin, sentinel);
@@ -1010,13 +1023,13 @@ link_update_uniform_buffer_variables(struct gl_shader *shader)
}
} else if (!strcmp(var->name,
shader->BufferInterfaceBlocks[i].Uniforms[j].Name)) {
- found = true;
- var->data.location = j;
- break;
- }
- }
- if (found)
- break;
+ found = true;
+ var->data.location = j;
+ break;
+ }
+ }
+ if (found)
+ break;
}
assert(found);
}
@@ -1099,7 +1112,7 @@ link_assign_uniform_locations(struct gl_shader_program *prog,
struct gl_shader *sh = prog->_LinkedShaders[i];
if (sh == NULL)
- continue;
+ continue;
/* Uniforms that lack an initializer in the shader code have an initial
* value of zero. This includes sampler uniforms.
@@ -1120,13 +1133,13 @@ link_assign_uniform_locations(struct gl_shader_program *prog,
uniform_size.start_shader();
foreach_in_list(ir_instruction, node, sh->ir) {
- ir_variable *const var = node->as_variable();
+ ir_variable *const var = node->as_variable();
- if ((var == NULL) || (var->data.mode != ir_var_uniform &&
- var->data.mode != ir_var_shader_storage))
- continue;
+ if ((var == NULL) || (var->data.mode != ir_var_uniform &&
+ var->data.mode != ir_var_shader_storage))
+ continue;
- uniform_size.process(var);
+ uniform_size.process(var);
}
sh->num_samplers = uniform_size.num_shader_samplers;
@@ -1136,8 +1149,8 @@ link_assign_uniform_locations(struct gl_shader_program *prog,
for (unsigned i = 0; i < sh->NumBufferInterfaceBlocks; i++) {
if (!sh->BufferInterfaceBlocks[i].IsShaderStorage) {
- sh->num_combined_uniform_components +=
- sh->BufferInterfaceBlocks[i].UniformBufferSize / 4;
+ sh->num_combined_uniform_components +=
+ sh->BufferInterfaceBlocks[i].UniformBufferSize / 4;
}
}
}
@@ -1170,18 +1183,18 @@ link_assign_uniform_locations(struct gl_shader_program *prog,
for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
if (prog->_LinkedShaders[i] == NULL)
- continue;
+ continue;
parcel.start_shader((gl_shader_stage)i);
foreach_in_list(ir_instruction, node, prog->_LinkedShaders[i]->ir) {
- ir_variable *const var = node->as_variable();
+ ir_variable *const var = node->as_variable();
if ((var == NULL) || (var->data.mode != ir_var_uniform &&
var->data.mode != ir_var_shader_storage))
- continue;
+ continue;
- parcel.set_and_process(var);
+ parcel.set_and_process(var);
}
prog->_LinkedShaders[i]->active_samplers = parcel.shader_samplers_used;
diff --git a/src/compiler/glsl/link_varyings.cpp b/src/compiler/glsl/link_varyings.cpp
index 05cc1a2b7f8..34eb848a9c1 100644
--- a/src/compiler/glsl/link_varyings.cpp
+++ b/src/compiler/glsl/link_varyings.cpp
@@ -219,7 +219,7 @@ cross_validate_front_and_back_color(struct gl_shader_program *prog,
*/
void
cross_validate_outputs_to_inputs(struct gl_shader_program *prog,
- gl_shader *producer, gl_shader *consumer)
+ gl_shader *producer, gl_shader *consumer)
{
glsl_symbol_table parameters;
ir_variable *explicit_locations[MAX_VARYING] = { NULL, };
@@ -312,8 +312,14 @@ cross_validate_outputs_to_inputs(struct gl_shader_program *prog,
}
if (output != NULL) {
- cross_validate_types_and_qualifiers(prog, input, output,
- consumer->Stage, producer->Stage);
+ /* Interface blocks have their own validation elsewhere so don't
+ * try validating them here.
+ */
+ if (!(input->get_interface_type() &&
+ output->get_interface_type()))
+ cross_validate_types_and_qualifiers(prog, input, output,
+ consumer->Stage,
+ producer->Stage);
} else {
/* Check for input vars with unmatched output vars in prev stage
* taking into account that interface blocks could have a matching
@@ -348,7 +354,7 @@ remove_unused_shader_inputs_and_outputs(bool is_separate_shader_object,
ir_variable *const var = node->as_variable();
if ((var == NULL) || (var->data.mode != int(mode)))
- continue;
+ continue;
/* A shader 'in' or 'out' variable is only really an input or output if
* its value is used by other shader stages. This will cause the
@@ -356,7 +362,7 @@ remove_unused_shader_inputs_and_outputs(bool is_separate_shader_object,
*/
if (var->data.is_unmatched_generic_inout) {
assert(var->data.mode != ir_var_temporary);
- var->data.mode = ir_var_auto;
+ var->data.mode = ir_var_auto;
}
}
@@ -748,8 +754,8 @@ store_tfeedback_info(struct gl_context *ctx, struct gl_shader_program *prog,
prog->LinkedTransformFeedback.Varyings =
rzalloc_array(prog,
- struct gl_transform_feedback_varying_info,
- num_tfeedback_decls);
+ struct gl_transform_feedback_varying_info,
+ num_tfeedback_decls);
unsigned num_outputs = 0;
for (unsigned i = 0; i < num_tfeedback_decls; ++i)
@@ -1561,9 +1567,9 @@ reserved_varying_slot(struct gl_shader *stage, ir_variable_mode io_mode)
*/
bool
assign_varying_locations(struct gl_context *ctx,
- void *mem_ctx,
- struct gl_shader_program *prog,
- gl_shader *producer, gl_shader *consumer,
+ void *mem_ctx,
+ struct gl_shader_program *prog,
+ gl_shader *producer, gl_shader *consumer,
unsigned num_tfeedback_decls,
tfeedback_decl *tfeedback_decls)
{
@@ -1755,7 +1761,7 @@ assign_varying_locations(struct gl_context *ctx,
linker_error(prog, "%s shader varying %s not written "
"by %s shader\n.",
_mesa_shader_stage_to_string(consumer->Stage),
- var->name,
+ var->name,
_mesa_shader_stage_to_string(producer->Stage));
} else {
linker_warning(prog, "%s shader varying %s not written "
diff --git a/src/compiler/glsl/linker.cpp b/src/compiler/glsl/linker.cpp
index 3039232162a..76b700d3451 100644
--- a/src/compiler/glsl/linker.cpp
+++ b/src/compiler/glsl/linker.cpp
@@ -2417,7 +2417,8 @@ assign_attribute_or_color_locations(gl_shader_program *prog,
/* Reversed because we want a descending order sort below. */
return r->slots - l->slots;
}
- } to_assign[16];
+ } to_assign[32];
+ assert(max_index <= 32);
unsigned num_attr = 0;
@@ -2625,6 +2626,13 @@ assign_attribute_or_color_locations(gl_shader_program *prog,
continue;
}
+ if (num_attr >= max_index) {
+ linker_error(prog, "too many %s (max %u)",
+ target_index == MESA_SHADER_VERTEX ?
+ "vertex shader inputs" : "fragment shader outputs",
+ max_index);
+ return false;
+ }
to_assign[num_attr].slots = slots;
to_assign[num_attr].var = var;
num_attr++;
diff --git a/src/compiler/glsl/linker.h b/src/compiler/glsl/linker.h
index a60bb6ed087..4311d1659ec 100644
--- a/src/compiler/glsl/linker.h
+++ b/src/compiler/glsl/linker.h
@@ -182,6 +182,8 @@ protected:
virtual void leave_record(const glsl_type *type, const char *name,
bool row_major, const unsigned packing);
+ virtual void set_buffer_offset(unsigned offset);
+
virtual void set_record_array_count(unsigned record_array_count);
private:
diff --git a/src/compiler/glsl/lower_buffer_access.cpp b/src/compiler/glsl/lower_buffer_access.cpp
index 9ad811de9f1..f85b421cf27 100644
--- a/src/compiler/glsl/lower_buffer_access.cpp
+++ b/src/compiler/glsl/lower_buffer_access.cpp
@@ -440,6 +440,10 @@ lower_buffer_access::setup_buffer_access(void *mem_ctx,
else
field_align = type->std140_base_alignment(field_row_major);
+ if (struct_type->fields.structure[i].offset != -1) {
+ intra_struct_offset = struct_type->fields.structure[i].offset;
+ }
+
intra_struct_offset = glsl_align(intra_struct_offset, field_align);
if (strcmp(struct_type->fields.structure[i].name,
diff --git a/src/compiler/glsl/opt_array_splitting.cpp b/src/compiler/glsl/opt_array_splitting.cpp
index cceec6b6431..a294da56616 100644
--- a/src/compiler/glsl/opt_array_splitting.cpp
+++ b/src/compiler/glsl/opt_array_splitting.cpp
@@ -55,9 +55,9 @@ public:
this->components = NULL;
this->mem_ctx = NULL;
if (var->type->is_array())
- this->size = var->type->length;
+ this->size = var->type->length;
else
- this->size = var->type->matrix_columns;
+ this->size = var->type->matrix_columns;
}
ir_variable *var; /* The key: the variable's pointer. */
@@ -137,7 +137,7 @@ ir_array_reference_visitor::get_variable_entry(ir_variable *var)
foreach_in_list(variable_entry, entry, &this->variable_list) {
if (entry->var == var)
- return entry;
+ return entry;
}
variable_entry *entry = new(mem_ctx) variable_entry(var);
@@ -185,8 +185,18 @@ ir_array_reference_visitor::visit_enter(ir_dereference_array *ir)
/* If the access to the array has a variable index, we wouldn't
* know which split variable this dereference should go to.
*/
- if (entry && !ir->array_index->as_constant())
- entry->split = false;
+ if (!ir->array_index->as_constant()) {
+ if (entry)
+ entry->split = false;
+ /* This variable indexing could come from a different array dereference
+ * that also has variable indexing, that is, something like a[b[a[b[0]]]].
+ * If we return visit_continue_with_parent here for the first appearence
+ * of a, then we can miss that b also has indirect indexing (if this is
+ * the only place in the program where such indirect indexing into b
+ * happens), so keep going.
+ */
+ return visit_continue;
+ }
/* If the index is also array dereference, visit index. */
if (ir->array_index->as_dereference_array())
@@ -208,7 +218,7 @@ ir_array_reference_visitor::visit_enter(ir_function_signature *ir)
bool
ir_array_reference_visitor::get_split_list(exec_list *instructions,
- bool linked)
+ bool linked)
{
visit_list_elements(this, instructions);
@@ -217,25 +227,25 @@ ir_array_reference_visitor::get_split_list(exec_list *instructions,
*/
if (!linked) {
foreach_in_list(ir_instruction, node, instructions) {
- ir_variable *var = node->as_variable();
- if (var) {
- variable_entry *entry = get_variable_entry(var);
- if (entry)
- entry->remove();
- }
+ ir_variable *var = node->as_variable();
+ if (var) {
+ variable_entry *entry = get_variable_entry(var);
+ if (entry)
+ entry->remove();
+ }
}
}
/* Trim out variables we found that we can't split. */
foreach_in_list_safe(variable_entry, entry, &variable_list) {
if (debug) {
- printf("array %s@%p: decl %d, split %d\n",
- entry->var->name, (void *) entry->var, entry->declaration,
- entry->split);
+ printf("array %s@%p: decl %d, split %d\n",
+ entry->var->name, (void *) entry->var, entry->declaration,
+ entry->split);
}
if (!(entry->declaration && entry->split)) {
- entry->remove();
+ entry->remove();
}
}
@@ -273,7 +283,7 @@ ir_array_splitting_visitor::get_splitting_entry(ir_variable *var)
foreach_in_list(variable_entry, entry, this->variable_list) {
if (entry->var == var) {
- return entry;
+ return entry;
}
}
@@ -301,7 +311,7 @@ ir_array_splitting_visitor::split_deref(ir_dereference **deref)
if (constant->value.i[0] >= 0 && constant->value.i[0] < (int)entry->size) {
*deref = new(entry->mem_ctx)
- ir_dereference_variable(entry->components[constant->value.i[0]]);
+ ir_dereference_variable(entry->components[constant->value.i[0]]);
} else {
/* There was a constant array access beyond the end of the
* array. This might have happened due to constant folding
@@ -310,8 +320,8 @@ ir_array_splitting_visitor::split_deref(ir_dereference **deref)
* variable.
*/
ir_variable *temp = new(entry->mem_ctx) ir_variable(deref_array->type,
- "undef",
- ir_var_temporary);
+ "undef",
+ ir_var_temporary);
entry->components[0]->insert_before(temp);
*deref = new(entry->mem_ctx) ir_dereference_variable(temp);
}
@@ -373,23 +383,21 @@ optimize_split_arrays(exec_list *instructions, bool linked)
const struct glsl_type *subtype;
if (type->is_matrix())
- subtype = type->column_type();
+ subtype = type->column_type();
else
- subtype = type->fields.array;
+ subtype = type->fields.array;
entry->mem_ctx = ralloc_parent(entry->var);
- entry->components = ralloc_array(mem_ctx,
- ir_variable *,
- entry->size);
+ entry->components = ralloc_array(mem_ctx, ir_variable *, entry->size);
for (unsigned int i = 0; i < entry->size; i++) {
- const char *name = ralloc_asprintf(mem_ctx, "%s_%d",
- entry->var->name, i);
+ const char *name = ralloc_asprintf(mem_ctx, "%s_%d",
+ entry->var->name, i);
- entry->components[i] =
- new(entry->mem_ctx) ir_variable(subtype, name, ir_var_temporary);
- entry->var->insert_before(entry->components[i]);
+ entry->components[i] =
+ new(entry->mem_ctx) ir_variable(subtype, name, ir_var_temporary);
+ entry->var->insert_before(entry->components[i]);
}
entry->var->remove();
diff --git a/src/compiler/glsl_types.cpp b/src/compiler/glsl_types.cpp
index c549230a83c..2421bd61954 100644
--- a/src/compiler/glsl_types.cpp
+++ b/src/compiler/glsl_types.cpp
@@ -120,6 +120,7 @@ glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields,
this->fields.structure[i].name = ralloc_strdup(this->fields.structure,
fields[i].name);
this->fields.structure[i].location = fields[i].location;
+ this->fields.structure[i].offset = fields[i].offset;
this->fields.structure[i].interpolation = fields[i].interpolation;
this->fields.structure[i].centroid = fields[i].centroid;
this->fields.structure[i].sample = fields[i].sample;
@@ -159,6 +160,7 @@ glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields,
this->fields.structure[i].name = ralloc_strdup(this->fields.structure,
fields[i].name);
this->fields.structure[i].location = fields[i].location;
+ this->fields.structure[i].offset = fields[i].offset;
this->fields.structure[i].interpolation = fields[i].interpolation;
this->fields.structure[i].centroid = fields[i].centroid;
this->fields.structure[i].sample = fields[i].sample;
@@ -880,6 +882,9 @@ glsl_type::record_compare(const glsl_type *b) const
if (this->fields.structure[i].location
!= b->fields.structure[i].location)
return false;
+ if (this->fields.structure[i].offset
+ != b->fields.structure[i].offset)
+ return false;
if (this->fields.structure[i].interpolation
!= b->fields.structure[i].interpolation)
return false;
diff --git a/src/compiler/glsl_types.h b/src/compiler/glsl_types.h
index 2f612d8857d..b0e6f3f730f 100644
--- a/src/compiler/glsl_types.h
+++ b/src/compiler/glsl_types.h
@@ -838,6 +838,14 @@ struct glsl_struct_field {
int location;
/**
+ * For interface blocks, members may have an explicit byte offset
+ * specified; -1 otherwise.
+ *
+ * Ignored for structs.
+ */
+ int offset;
+
+ /**
* For interface blocks, the interpolation mode (as in
* ir_variable::interpolation). 0 otherwise.
*/
diff --git a/src/compiler/nir/Makefile.sources b/src/compiler/nir/Makefile.sources
index 04e8ab88a35..a876eff289a 100644
--- a/src/compiler/nir/Makefile.sources
+++ b/src/compiler/nir/Makefile.sources
@@ -32,10 +32,10 @@ NIR_FILES = \
nir_lower_clip.c \
nir_lower_global_vars_to_local.c \
nir_lower_gs_intrinsics.c \
- nir_lower_indirect_derefs.c \
nir_lower_load_const_to_scalar.c \
nir_lower_locals_to_regs.c \
nir_lower_idiv.c \
+ nir_lower_indirect_derefs.c \
nir_lower_io.c \
nir_lower_outputs_to_temporaries.c \
nir_lower_phis_to_scalar.c \
diff --git a/src/compiler/nir/glsl_to_nir.cpp b/src/compiler/nir/glsl_to_nir.cpp
index 6671691fd06..da5d730b49e 100644
--- a/src/compiler/nir/glsl_to_nir.cpp
+++ b/src/compiler/nir/glsl_to_nir.cpp
@@ -454,34 +454,8 @@ nir_visitor::create_function(ir_function_signature *ir)
nir_function *func = nir_function_create(shader, ir->function_name());
- unsigned num_params = ir->parameters.length();
- func->num_params = num_params;
- func->params = ralloc_array(shader, nir_parameter, num_params);
-
- unsigned i = 0;
- foreach_in_list(ir_variable, param, &ir->parameters) {
- switch (param->data.mode) {
- case ir_var_function_in:
- func->params[i].param_type = nir_parameter_in;
- break;
-
- case ir_var_function_out:
- func->params[i].param_type = nir_parameter_out;
- break;
-
- case ir_var_function_inout:
- func->params[i].param_type = nir_parameter_inout;
- break;
-
- default:
- unreachable("not reached");
- }
-
- func->params[i].type = param->type;
- i++;
- }
-
- func->return_type = ir->return_type;
+ assert(ir->parameters.is_empty());
+ assert(ir->return_type == glsl_type::void_type);
_mesa_hash_table_insert(this->overload_table, ir, func);
}
@@ -509,24 +483,9 @@ nir_visitor::visit(ir_function_signature *ir)
nir_function_impl *impl = nir_function_impl_create(func);
this->impl = impl;
- unsigned num_params = func->num_params;
- impl->num_params = num_params;
- impl->params = ralloc_array(this->shader, nir_variable *, num_params);
- unsigned i = 0;
- foreach_in_list(ir_variable, param, &ir->parameters) {
- param->accept(this);
- impl->params[i] = this->var;
- i++;
- }
-
- if (func->return_type == glsl_type::void_type) {
- impl->return_var = NULL;
- } else {
- impl->return_var = ralloc(this->shader, nir_variable);
- impl->return_var->name = ralloc_strdup(impl->return_var,
- "return_var");
- impl->return_var->type = func->return_type;
- }
+ assert(strcmp(func->name, "main") == 0);
+ assert(ir->parameters.is_empty());
+ assert(func->return_type == glsl_type::void_type);
this->is_global = false;
diff --git a/src/compiler/nir/nir.c b/src/compiler/nir/nir.c
index 91206a92717..7e41ed37b0d 100644
--- a/src/compiler/nir/nir.c
+++ b/src/compiler/nir/nir.c
@@ -323,6 +323,8 @@ nir_function_impl_create(nir_function *function)
impl->return_var->type = function->return_type;
impl->return_var->data.mode = nir_var_param;
impl->return_var->data.location = -1;
+ } else {
+ impl->return_var = NULL;
}
return impl;
diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h
index 0f8c78100bf..ae37cbf7325 100644
--- a/src/compiler/nir/nir.h
+++ b/src/compiler/nir/nir.h
@@ -2094,8 +2094,8 @@ void nir_index_blocks(nir_function_impl *impl);
void nir_print_shader(nir_shader *shader, FILE *fp);
void nir_print_instr(const nir_instr *instr, FILE *fp);
-nir_shader *nir_shader_clone(void *mem_ctx, const nir_shader *s);
-nir_function_impl *nir_function_impl_clone(const nir_function_impl *impl);
+nir_shader * nir_shader_clone(void *mem_ctx, const nir_shader *s);
+nir_function_impl *nir_function_impl_clone(const nir_function_impl *fi);
nir_constant *nir_constant_clone(const nir_constant *c, nir_variable *var);
#ifdef DEBUG
diff --git a/src/compiler/nir/nir_lower_indirect_derefs.c b/src/compiler/nir/nir_lower_indirect_derefs.c
index 69f2df4ba6d..a4affa7bdcf 100644
--- a/src/compiler/nir/nir_lower_indirect_derefs.c
+++ b/src/compiler/nir/nir_lower_indirect_derefs.c
@@ -134,7 +134,7 @@ emit_load_store(nir_builder *b, nir_intrinsic_instr *orig_instr,
nir_intrinsic_instr *store =
nir_intrinsic_instr_create(b->shader, nir_intrinsic_store_var);
store->num_components = orig_instr->num_components;
- store->const_index[0] = orig_instr->const_index[0]; /* writemask */
+ nir_intrinsic_set_write_mask(store, nir_intrinsic_write_mask(orig_instr));
store->variables[0] =
nir_deref_as_var(nir_copy_deref(store, &deref->deref));
store->src[0] = nir_src_for_ssa(src);
diff --git a/src/compiler/nir/nir_opt_algebraic.py b/src/compiler/nir/nir_opt_algebraic.py
index c9c917b77a5..54f7d86843a 100644
--- a/src/compiler/nir/nir_opt_algebraic.py
+++ b/src/compiler/nir/nir_opt_algebraic.py
@@ -164,6 +164,8 @@ optimizations = [
(('ishr', a, 0), a),
(('ushr', 0, a), 0),
(('ushr', a, 0), a),
+ (('iand', 0xff, ('ushr', a, 24)), ('ushr', a, 24)),
+ (('iand', 0xffff, ('ushr', a, 16)), ('ushr', a, 16)),
# Exponential/logarithmic identities
(('fexp2', ('flog2', a)), a), # 2^lg2(a) = a
(('flog2', ('fexp2', a)), a), # lg2(2^a) = a
@@ -215,6 +217,16 @@ optimizations = [
(('f2i', ('ftrunc', a)), ('f2i', a)),
(('f2u', ('ftrunc', a)), ('f2u', a)),
+ # Byte extraction
+ (('ushr', a, 24), ('extract_u8', a, 3), '!options->lower_extract_byte'),
+ (('iand', 0xff, ('ushr', a, 16)), ('extract_u8', a, 2), '!options->lower_extract_byte'),
+ (('iand', 0xff, ('ushr', a, 8)), ('extract_u8', a, 1), '!options->lower_extract_byte'),
+ (('iand', 0xff, a), ('extract_u8', a, 0), '!options->lower_extract_byte'),
+
+ # Word extraction
+ (('ushr', a, 16), ('extract_u16', a, 1), '!options->lower_extract_word'),
+ (('iand', 0xffff, a), ('extract_u16', a, 0), '!options->lower_extract_word'),
+
# Subtracts
(('fsub', a, ('fsub', 0.0, b)), ('fadd', a, b)),
(('isub', a, ('isub', 0, b)), ('iadd', a, b)),
diff --git a/src/compiler/nir/nir_print.c b/src/compiler/nir/nir_print.c
index 63e34ea5255..24d5281ec54 100644
--- a/src/compiler/nir/nir_print.c
+++ b/src/compiler/nir/nir_print.c
@@ -381,6 +381,14 @@ print_var(nir_variable *var, print_state *state)
}
static void
+print_arg(nir_variable *var, print_state *state)
+{
+ FILE *fp = state->fp;
+ glsl_print_type(var->type, fp);
+ fprintf(fp, " %s", get_var_name(var, state));
+}
+
+static void
print_deref_var(nir_deref_var *deref, print_state *state)
{
print_var(deref->var, state);
@@ -942,14 +950,14 @@ print_function_impl(nir_function_impl *impl, print_state *state)
if (i != 0)
fprintf(fp, ", ");
- print_var(impl->params[i], state);
+ print_arg(impl->params[i], state);
}
if (impl->return_var != NULL) {
if (impl->num_params != 0)
fprintf(fp, ", ");
fprintf(fp, "returning ");
- print_var(impl->return_var, state);
+ print_arg(impl->return_var, state);
}
fprintf(fp, "{\n");
diff --git a/src/compiler/nir/nir_validate.c b/src/compiler/nir/nir_validate.c
index a9d213b95c4..0c32d5fe07a 100644
--- a/src/compiler/nir/nir_validate.c
+++ b/src/compiler/nir/nir_validate.c
@@ -938,6 +938,7 @@ validate_function_impl(nir_function_impl *impl, validate_state *state)
assert(impl->num_params == impl->function->num_params);
for (unsigned i = 0; i < impl->num_params; i++) {
assert(impl->params[i]->type == impl->function->params[i].type);
+ assert(impl->params[i]->data.mode == nir_var_param);
assert(impl->params[i]->data.location == i);
validate_var_decl(impl->params[i], false, state);
}
@@ -946,6 +947,7 @@ validate_function_impl(nir_function_impl *impl, validate_state *state)
assert(impl->return_var == NULL);
} else {
assert(impl->return_var->type == impl->function->return_type);
+ assert(impl->return_var->data.mode == nir_var_param);
assert(impl->return_var->data.location == -1);
validate_var_decl(impl->return_var, false, state);
}