summaryrefslogtreecommitdiffstats
path: root/src/compiler
diff options
context:
space:
mode:
authorJason Ekstrand <jason.ekstrand@intel.com>2016-04-01 14:59:38 -0700
committerJason Ekstrand <jason.ekstrand@intel.com>2016-04-01 15:16:21 -0700
commit95106f6bfbbb87b702e4bbba98e2eaea71924cd9 (patch)
tree9650d284ec7f7417b2bcf8a906dfa43dfc547cf7 /src/compiler
parentcf2257069cbde19fd177a02c079206914aac5d14 (diff)
parent14c46954c910efb1db94a068a866c7259deaa9d9 (diff)
downloadexternal_mesa3d-95106f6bfbbb87b702e4bbba98e2eaea71924cd9.zip
external_mesa3d-95106f6bfbbb87b702e4bbba98e2eaea71924cd9.tar.gz
external_mesa3d-95106f6bfbbb87b702e4bbba98e2eaea71924cd9.tar.bz2
Merge remote-tracking branch 'public/master' into vulkan
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/Makefile.sources4
-rw-r--r--src/compiler/glsl/ast.h35
-rw-r--r--src/compiler/glsl/ast_function.cpp4
-rw-r--r--src/compiler/glsl/ast_to_hir.cpp304
-rw-r--r--src/compiler/glsl/ast_type.cpp121
-rw-r--r--src/compiler/glsl/builtin_functions.cpp38
-rw-r--r--src/compiler/glsl/builtin_types.cpp22
-rw-r--r--src/compiler/glsl/builtin_variables.cpp26
-rw-r--r--src/compiler/glsl/glcpp/glcpp-parse.y8
-rw-r--r--src/compiler/glsl/glsl_lexer.ll21
-rw-r--r--src/compiler/glsl/glsl_parser.yy25
-rw-r--r--src/compiler/glsl/glsl_parser_extras.cpp39
-rw-r--r--src/compiler/glsl/glsl_parser_extras.h15
-rw-r--r--src/compiler/glsl/ir.h43
-rw-r--r--src/compiler/glsl/ir_uniform.h5
-rw-r--r--src/compiler/glsl/link_interface_blocks.cpp6
-rw-r--r--src/compiler/glsl/link_uniform_initializers.cpp6
-rw-r--r--src/compiler/glsl/link_uniforms.cpp108
-rw-r--r--src/compiler/glsl/link_varyings.cpp317
-rw-r--r--src/compiler/glsl/link_varyings.h39
-rw-r--r--src/compiler/glsl/linker.cpp195
-rw-r--r--src/compiler/glsl/linker.h3
-rw-r--r--src/compiler/glsl/lower_named_interface_blocks.cpp23
-rw-r--r--src/compiler/glsl/program.h3
-rw-r--r--src/compiler/glsl/standalone_scaffolding.cpp5
-rw-r--r--src/compiler/glsl/tests/set_uniform_initializer_tests.cpp19
-rw-r--r--src/compiler/glsl_types.cpp49
-rw-r--r--src/compiler/glsl_types.h29
-rw-r--r--src/compiler/nir/Makefile.sources4
-rw-r--r--src/compiler/nir/glsl_to_nir.cpp11
-rw-r--r--src/compiler/nir/nir.h2
-rw-r--r--src/compiler/nir/nir_opt_algebraic.py5
-rw-r--r--src/compiler/shader_enums.h2
33 files changed, 1220 insertions, 316 deletions
diff --git a/src/compiler/Makefile.sources b/src/compiler/Makefile.sources
index 43377f1..120ef29 100644
--- a/src/compiler/Makefile.sources
+++ b/src/compiler/Makefile.sources
@@ -179,10 +179,10 @@ NIR_FILES = \
nir/nir_gather_info.c \
nir/nir_gs_count_vertices.c \
nir/nir_inline_functions.c \
- nir/nir_intrinsics.c \
- nir/nir_intrinsics.h \
nir/nir_instr_set.c \
nir/nir_instr_set.h \
+ nir/nir_intrinsics.c \
+ nir/nir_intrinsics.h \
nir/nir_liveness.c \
nir/nir_lower_alu_to_scalar.c \
nir/nir_lower_atomics.c \
diff --git a/src/compiler/glsl/ast.h b/src/compiler/glsl/ast.h
index 727aa43..7436edc 100644
--- a/src/compiler/glsl/ast.h
+++ b/src/compiler/glsl/ast.h
@@ -214,6 +214,7 @@ public:
subexpressions[2] = NULL;
primary_expression.identifier = identifier;
this->non_lvalue_description = NULL;
+ this->is_lhs = false;
}
static const char *operator_string(enum ast_operators op);
@@ -263,6 +264,11 @@ public:
* This pointer may be \c NULL.
*/
const char *non_lvalue_description;
+
+ void set_is_lhs(bool new_value);
+
+private:
+ bool is_lhs;
};
class ast_expression_bin : public ast_expression {
@@ -556,6 +562,15 @@ struct ast_type_qualifier {
unsigned explicit_stream:1; /**< stream value assigned explicitly by shader code */
/** \} */
+ /** \name Layout qualifiers for GL_ARB_enhanced_layouts */
+ /** \{ */
+ unsigned explicit_xfb_offset:1; /**< xfb_offset value assigned explicitly by shader code */
+ unsigned xfb_buffer:1; /**< Has xfb_buffer value assigned */
+ unsigned explicit_xfb_buffer:1; /**< xfb_buffer value assigned explicitly by shader code */
+ unsigned xfb_stride:1; /**< Is xfb_stride value yet to be merged with global values */
+ unsigned explicit_xfb_stride:1; /**< xfb_stride value assigned explicitly by shader code */
+ /** \} */
+
/** \name Layout qualifiers for GL_ARB_tessellation_shader */
/** \{ */
/* tess eval input layout */
@@ -612,6 +627,15 @@ struct ast_type_qualifier {
/** Stream in GLSL 1.50 geometry shaders. */
ast_expression *stream;
+ /** xfb_buffer specified via the GL_ARB_enhanced_layouts keyword. */
+ ast_expression *xfb_buffer;
+
+ /** xfb_stride specified via the GL_ARB_enhanced_layouts keyword. */
+ ast_expression *xfb_stride;
+
+ /** global xfb_stride values for each buffer */
+ ast_layout_expression *out_xfb_stride[MAX_FEEDBACK_BUFFERS];
+
/**
* Input or output primitive type in GLSL 1.50 geometry shaders
* and tessellation shaders.
@@ -627,8 +651,9 @@ struct ast_type_qualifier {
ast_expression *binding;
/**
- * Offset specified via GL_ARB_shader_atomic_counter's "offset"
- * keyword.
+ * Offset specified via GL_ARB_shader_atomic_counter's or
+ * GL_ARB_enhanced_layouts "offset" keyword, or by GL_ARB_enhanced_layouts
+ * "xfb_offset" keyword.
*
* \note
* This field is only valid if \c explicit_offset is set.
@@ -1199,4 +1224,10 @@ extern void _mesa_ast_process_interface_block(YYLTYPE *locp,
ast_interface_block *const block,
const struct ast_type_qualifier &q);
+extern bool
+process_qualifier_constant(struct _mesa_glsl_parse_state *state,
+ YYLTYPE *loc,
+ const char *qual_indentifier,
+ ast_expression *const_expression,
+ unsigned *value);
#endif /* AST_H */
diff --git a/src/compiler/glsl/ast_function.cpp b/src/compiler/glsl/ast_function.cpp
index 1a44020..db68d5d 100644
--- a/src/compiler/glsl/ast_function.cpp
+++ b/src/compiler/glsl/ast_function.cpp
@@ -1727,6 +1727,10 @@ ast_function_expression::handle_method(exec_list *instructions,
const char *method;
method = field->primary_expression.identifier;
+ /* This would prevent to raise "uninitialized variable" warnings when
+ * calling array.length.
+ */
+ field->subexpressions[0]->set_is_lhs(true);
op = field->subexpressions[0]->hir(instructions, state);
if (strcmp(method, "length") == 0) {
if (!this->expressions.is_empty()) {
diff --git a/src/compiler/glsl/ast_to_hir.cpp b/src/compiler/glsl/ast_to_hir.cpp
index 35def8e..3fe9007 100644
--- a/src/compiler/glsl/ast_to_hir.cpp
+++ b/src/compiler/glsl/ast_to_hir.cpp
@@ -54,6 +54,7 @@
#include "ast.h"
#include "compiler/glsl_types.h"
#include "program/hash_table.h"
+#include "main/macros.h"
#include "main/shaderobj.h"
#include "ir.h"
#include "ir_builder.h"
@@ -819,7 +820,7 @@ validate_assignment(struct _mesa_glsl_parse_state *state,
* if the expression indicating the vertex number is not the identifier
* `gl_InvocationID`.
*/
- if (state->stage == MESA_SHADER_TESS_CTRL) {
+ if (state->stage == MESA_SHADER_TESS_CTRL && !lhs->type->is_error()) {
ir_variable *var = lhs->variable_referenced();
if (var->data.mode == ir_var_shader_out && !var->data.patch) {
ir_rvalue *index = find_innermost_array_index(lhs);
@@ -1248,6 +1249,24 @@ ast_expression::hir_no_rvalue(exec_list *instructions,
do_hir(instructions, state, false);
}
+void
+ast_expression::set_is_lhs(bool new_value)
+{
+ /* is_lhs is tracked only to print "variable used uninitialized" warnings,
+ * if we lack a identifier we can just skip it.
+ */
+ if (this->primary_expression.identifier == NULL)
+ return;
+
+ this->is_lhs = new_value;
+
+ /* We need to go through the subexpressions tree to cover cases like
+ * ast_field_selection
+ */
+ if (this->subexpressions[0] != NULL)
+ this->subexpressions[0]->set_is_lhs(new_value);
+}
+
ir_rvalue *
ast_expression::do_hir(exec_list *instructions,
struct _mesa_glsl_parse_state *state,
@@ -1323,6 +1342,7 @@ ast_expression::do_hir(exec_list *instructions,
break;
case ast_assign: {
+ this->subexpressions[0]->set_is_lhs(true);
op[0] = this->subexpressions[0]->hir(instructions, state);
op[1] = this->subexpressions[1]->hir(instructions, state);
@@ -1592,6 +1612,7 @@ ast_expression::do_hir(exec_list *instructions,
case ast_div_assign:
case ast_add_assign:
case ast_sub_assign: {
+ this->subexpressions[0]->set_is_lhs(true);
op[0] = this->subexpressions[0]->hir(instructions, state);
op[1] = this->subexpressions[1]->hir(instructions, state);
@@ -1618,6 +1639,7 @@ ast_expression::do_hir(exec_list *instructions,
}
case ast_mod_assign: {
+ this->subexpressions[0]->set_is_lhs(true);
op[0] = this->subexpressions[0]->hir(instructions, state);
op[1] = this->subexpressions[1]->hir(instructions, state);
@@ -1640,6 +1662,7 @@ ast_expression::do_hir(exec_list *instructions,
case ast_ls_assign:
case ast_rs_assign: {
+ this->subexpressions[0]->set_is_lhs(true);
op[0] = this->subexpressions[0]->hir(instructions, state);
op[1] = this->subexpressions[1]->hir(instructions, state);
type = shift_result_type(op[0]->type, op[1]->type, this->oper, state,
@@ -1658,6 +1681,7 @@ ast_expression::do_hir(exec_list *instructions,
case ast_and_assign:
case ast_xor_assign:
case ast_or_assign: {
+ this->subexpressions[0]->set_is_lhs(true);
op[0] = this->subexpressions[0]->hir(instructions, state);
op[1] = this->subexpressions[1]->hir(instructions, state);
type = bit_logic_result_type(op[0], op[1], this->oper, state, &loc);
@@ -1839,6 +1863,11 @@ ast_expression::do_hir(exec_list *instructions,
case ast_array_index: {
YYLTYPE index_loc = subexpressions[1]->get_location();
+ /* Getting if an array is being used uninitialized is beyond what we get
+ * from ir_value.data.assigned. Setting is_lhs as true would force to
+ * not raise a uninitialized warning when using an array
+ */
+ subexpressions[0]->set_is_lhs(true);
op[0] = subexpressions[0]->hir(instructions, state);
op[1] = subexpressions[1]->hir(instructions, state);
@@ -1873,6 +1902,14 @@ ast_expression::do_hir(exec_list *instructions,
if (var != NULL) {
var->data.used = true;
result = new(ctx) ir_dereference_variable(var);
+
+ if ((var->data.mode == ir_var_auto || var->data.mode == ir_var_shader_out)
+ && !this->is_lhs
+ && result->variable_referenced()->data.assigned != true
+ && !is_gl_identifier(var->name)) {
+ _mesa_glsl_warning(&loc, state, "`%s' used uninitialized",
+ this->primary_expression.identifier);
+ }
} else {
_mesa_glsl_error(& loc, state, "`%s' undeclared",
this->primary_expression.identifier);
@@ -2318,11 +2355,11 @@ get_type_name_for_precision_qualifier(const glsl_type *type)
return names[type_idx];
}
case GLSL_SAMPLER_DIM_BUF: {
- assert(type->base_type == GLSL_TYPE_SAMPLER);
- static const char *const names[4] = {
- "samplerBuffer", NULL, NULL, NULL
+ static const char *const names[8] = {
+ "samplerBuffer", NULL, NULL, NULL,
+ "imageBuffer", NULL, NULL, NULL
};
- return names[type_idx];
+ return names[offset + type_idx];
}
case GLSL_SAMPLER_DIM_EXTERNAL: {
assert(type->base_type == GLSL_TYPE_SAMPLER);
@@ -2380,11 +2417,11 @@ get_type_name_for_precision_qualifier(const glsl_type *type)
return names[type_idx];
}
case GLSL_SAMPLER_DIM_BUF: {
- assert(type->base_type == GLSL_TYPE_SAMPLER);
- static const char *const names[4] = {
- "isamplerBuffer", NULL, NULL, NULL
+ static const char *const names[8] = {
+ "isamplerBuffer", NULL, NULL, NULL,
+ "iimageBuffer", NULL, NULL, NULL
};
- return names[type_idx];
+ return names[offset + type_idx];
}
default:
unreachable("Unsupported isampler/iimage dimensionality");
@@ -2435,11 +2472,11 @@ get_type_name_for_precision_qualifier(const glsl_type *type)
return names[type_idx];
}
case GLSL_SAMPLER_DIM_BUF: {
- assert(type->base_type == GLSL_TYPE_SAMPLER);
- static const char *const names[4] = {
- "usamplerBuffer", NULL, NULL, NULL
+ static const char *const names[8] = {
+ "usamplerBuffer", NULL, NULL, NULL,
+ "uimageBuffer", NULL, NULL, NULL
};
- return names[type_idx];
+ return names[offset + type_idx];
}
default:
unreachable("Unsupported usampler/uimage dimensionality");
@@ -2550,43 +2587,79 @@ validate_matrix_layout_for_type(struct _mesa_glsl_parse_state *state,
}
static bool
-process_qualifier_constant(struct _mesa_glsl_parse_state *state,
- YYLTYPE *loc,
- const char *qual_indentifier,
- ast_expression *const_expression,
- unsigned *value)
-{
- exec_list dummy_instructions;
-
- if (const_expression == NULL) {
- *value = 0;
- return true;
+validate_xfb_buffer_qualifier(YYLTYPE *loc,
+ struct _mesa_glsl_parse_state *state,
+ unsigned xfb_buffer) {
+ if (xfb_buffer >= state->Const.MaxTransformFeedbackBuffers) {
+ _mesa_glsl_error(loc, state,
+ "invalid xfb_buffer specified %d is larger than "
+ "MAX_TRANSFORM_FEEDBACK_BUFFERS - 1 (%d).",
+ xfb_buffer,
+ state->Const.MaxTransformFeedbackBuffers - 1);
+ return false;
}
- ir_rvalue *const ir = const_expression->hir(&dummy_instructions, state);
+ return true;
+}
- ir_constant *const const_int = ir->constant_expression_value();
- if (const_int == NULL || !const_int->type->is_integer()) {
- _mesa_glsl_error(loc, state, "%s must be an integral constant "
- "expression", qual_indentifier);
- return false;
- }
+/* From the ARB_enhanced_layouts spec:
+ *
+ * "Variables and block members qualified with *xfb_offset* can be
+ * scalars, vectors, matrices, structures, and (sized) arrays of these.
+ * The offset must be a multiple of the size of the first component of
+ * the first qualified variable or block member, or a compile-time error
+ * results. Further, if applied to an aggregate containing a double,
+ * the offset must also be a multiple of 8, and the space taken in the
+ * buffer will be a multiple of 8.
+ */
+static bool
+validate_xfb_offset_qualifier(YYLTYPE *loc,
+ struct _mesa_glsl_parse_state *state,
+ int xfb_offset, const glsl_type *type,
+ unsigned component_size) {
+ const glsl_type *t_without_array = type->without_array();
- if (const_int->value.i[0] < 0) {
- _mesa_glsl_error(loc, state, "%s layout qualifier is invalid (%d < 0)",
- qual_indentifier, const_int->value.u[0]);
+ if (xfb_offset != -1 && type->is_unsized_array()) {
+ _mesa_glsl_error(loc, state,
+ "xfb_offset can't be used with unsized arrays.");
return false;
}
- /* If the location 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 location isn't const after all, or
- * we are emitting unnecessary instructions.
+ /* Make sure nested structs don't contain unsized arrays, and validate
+ * any xfb_offsets on interface members.
*/
- assert(dummy_instructions.is_empty());
+ if (t_without_array->is_record() || t_without_array->is_interface())
+ for (unsigned int i = 0; i < t_without_array->length; i++) {
+ const glsl_type *member_t = t_without_array->fields.structure[i].type;
+
+ /* When the interface block doesn't have an xfb_offset qualifier then
+ * we apply the component size rules at the member level.
+ */
+ if (xfb_offset == -1)
+ component_size = member_t->contains_double() ? 8 : 4;
+
+ int xfb_offset = t_without_array->fields.structure[i].offset;
+ validate_xfb_offset_qualifier(loc, state, xfb_offset, member_t,
+ component_size);
+ }
+
+ /* Nested structs or interface block without offset may not have had an
+ * offset applied yet so return.
+ */
+ if (xfb_offset == -1) {
+ return true;
+ }
+
+ if (xfb_offset % component_size) {
+ _mesa_glsl_error(loc, state,
+ "invalid qualifier xfb_offset=%d must be a multiple "
+ "of the first component size of the first qualified "
+ "variable or block member. Or double if an aggregate "
+ "that contains a double (%d).",
+ xfb_offset, component_size);
+ return false;
+ }
- *value = const_int->value.u[0];
return true;
}
@@ -3151,6 +3224,39 @@ apply_layout_qualifier_to_variable(const struct ast_type_qualifier *qual,
}
}
+ if (qual->flags.q.out && qual->flags.q.xfb_buffer) {
+ unsigned qual_xfb_buffer;
+ if (process_qualifier_constant(state, loc, "xfb_buffer",
+ qual->xfb_buffer, &qual_xfb_buffer) &&
+ validate_xfb_buffer_qualifier(loc, state, qual_xfb_buffer)) {
+ var->data.xfb_buffer = qual_xfb_buffer;
+ if (qual->flags.q.explicit_xfb_buffer)
+ var->data.explicit_xfb_buffer = true;
+ }
+ }
+
+ if (qual->flags.q.explicit_xfb_offset) {
+ unsigned qual_xfb_offset;
+ unsigned component_size = var->type->contains_double() ? 8 : 4;
+
+ if (process_qualifier_constant(state, loc, "xfb_offset",
+ qual->offset, &qual_xfb_offset) &&
+ validate_xfb_offset_qualifier(loc, state, (int) qual_xfb_offset,
+ var->type, component_size)) {
+ var->data.offset = qual_xfb_offset;
+ var->data.explicit_xfb_offset = true;
+ }
+ }
+
+ if (qual->flags.q.explicit_xfb_stride) {
+ unsigned qual_xfb_stride;
+ if (process_qualifier_constant(state, loc, "xfb_stride",
+ qual->xfb_stride, &qual_xfb_stride)) {
+ var->data.xfb_stride = qual_xfb_stride;
+ var->data.explicit_xfb_stride = true;
+ }
+ }
+
if (var->type->contains_atomic()) {
if (var->data.mode == ir_var_uniform) {
if (var->data.explicit_binding) {
@@ -5746,6 +5852,11 @@ ast_switch_statement::test_to_hir(exec_list *instructions,
{
void *ctx = state;
+ /* set to true to avoid a duplicate "use of uninitialized variable" warning
+ * on the switch test case. The first one would be already raised when
+ * getting the test_expression at ast_switch_statement::hir
+ */
+ test_expression->set_is_lhs(true);
/* Cache value of test expression. */
ir_rvalue *const test_val =
test_expression->hir(instructions,
@@ -6258,6 +6369,8 @@ ast_process_struct_or_iface_block_members(exec_list *instructions,
ir_variable_mode var_mode,
ast_type_qualifier *layout,
unsigned block_stream,
+ unsigned block_xfb_buffer,
+ unsigned block_xfb_offset,
unsigned expl_location,
unsigned expl_align)
{
@@ -6413,6 +6526,35 @@ ast_process_struct_or_iface_block_members(exec_list *instructions,
}
}
+ int xfb_buffer;
+ unsigned explicit_xfb_buffer = 0;
+ if (qual->flags.q.explicit_xfb_buffer) {
+ unsigned qual_xfb_buffer;
+ if (process_qualifier_constant(state, &loc, "xfb_buffer",
+ qual->xfb_buffer, &qual_xfb_buffer)) {
+ explicit_xfb_buffer = 1;
+ if (qual_xfb_buffer != block_xfb_buffer)
+ _mesa_glsl_error(&loc, state, "xfb_buffer layout qualifier on "
+ "interface block member does not match "
+ "the interface block (%u vs %u)",
+ qual_xfb_buffer, block_xfb_buffer);
+ }
+ xfb_buffer = (int) qual_xfb_buffer;
+ } else {
+ if (layout)
+ explicit_xfb_buffer = layout->flags.q.xfb_buffer;
+ xfb_buffer = (int) block_xfb_buffer;
+ }
+
+ int xfb_stride = -1;
+ if (qual->flags.q.explicit_xfb_stride) {
+ unsigned qual_xfb_stride;
+ if (process_qualifier_constant(state, &loc, "xfb_stride",
+ qual->xfb_stride, &qual_xfb_stride)) {
+ xfb_stride = (int) qual_xfb_stride;
+ }
+ }
+
if (qual->flags.q.uniform && qual->has_interpolation()) {
_mesa_glsl_error(&loc, state,
"interpolation qualifiers cannot be used "
@@ -6458,6 +6600,10 @@ ast_process_struct_or_iface_block_members(exec_list *instructions,
fields[i].sample = qual->flags.q.sample ? 1 : 0;
fields[i].patch = qual->flags.q.patch ? 1 : 0;
fields[i].precision = qual->precision;
+ fields[i].offset = -1;
+ fields[i].explicit_xfb_buffer = explicit_xfb_buffer;
+ fields[i].xfb_buffer = xfb_buffer;
+ fields[i].xfb_stride = xfb_stride;
if (qual->flags.q.explicit_location) {
unsigned qual_location;
@@ -6520,8 +6666,6 @@ ast_process_struct_or_iface_block_members(exec_list *instructions,
"with std430 and std140 layouts");
}
}
- } else {
- fields[i].offset = -1;
}
if (qual->flags.q.explicit_align || expl_align != 0) {
@@ -6554,6 +6698,32 @@ ast_process_struct_or_iface_block_members(exec_list *instructions,
next_offset = glsl_align(next_offset + size, align);
}
+ /* From the ARB_enhanced_layouts spec:
+ *
+ * "The given offset applies to the first component of the first
+ * member of the qualified entity. Then, within the qualified
+ * entity, subsequent components are each assigned, in order, to
+ * the next available offset aligned to a multiple of that
+ * component's size. Aggregate types are flattened down to the
+ * component level to get this sequence of components."
+ */
+ if (qual->flags.q.explicit_xfb_offset) {
+ unsigned xfb_offset;
+ if (process_qualifier_constant(state, &loc, "xfb_offset",
+ qual->offset, &xfb_offset)) {
+ fields[i].offset = xfb_offset;
+ block_xfb_offset = fields[i].offset +
+ MAX2(xfb_stride, (int) (4 * field_type->component_slots()));
+ }
+ } else {
+ if (layout && layout->flags.q.explicit_xfb_offset) {
+ unsigned align = field_type->is_double() ? 8 : 4;
+ fields[i].offset = glsl_align(block_xfb_offset, align);
+ block_xfb_offset +=
+ MAX2(xfb_stride, (int) (4 * field_type->component_slots()));
+ }
+ }
+
/* 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
@@ -6648,6 +6818,8 @@ ast_struct_specifier::hir(exec_list *instructions,
ir_var_auto,
layout,
0, /* for interface only */
+ 0, /* for interface only */
+ 0, /* for interface only */
expl_location,
0 /* for interface only */);
@@ -6807,6 +6979,29 @@ ast_interface_block::hir(exec_list *instructions,
return NULL;
}
+ unsigned qual_xfb_buffer;
+ if (!process_qualifier_constant(state, &loc, "xfb_buffer",
+ layout.xfb_buffer, &qual_xfb_buffer) ||
+ !validate_xfb_buffer_qualifier(&loc, state, qual_xfb_buffer)) {
+ return NULL;
+ }
+
+ unsigned qual_xfb_offset;
+ if (layout.flags.q.explicit_xfb_offset) {
+ if (!process_qualifier_constant(state, &loc, "xfb_offset",
+ layout.offset, &qual_xfb_offset)) {
+ return NULL;
+ }
+ }
+
+ unsigned qual_xfb_stride;
+ if (layout.flags.q.explicit_xfb_stride) {
+ if (!process_qualifier_constant(state, &loc, "xfb_stride",
+ layout.xfb_stride, &qual_xfb_stride)) {
+ return NULL;
+ }
+ }
+
unsigned expl_location = 0;
if (layout.flags.q.explicit_location) {
if (!process_qualifier_constant(state, &loc, "location",
@@ -6842,6 +7037,8 @@ ast_interface_block::hir(exec_list *instructions,
var_mode,
&this->layout,
qual_stream,
+ qual_xfb_buffer,
+ qual_xfb_offset,
expl_location,
expl_align);
@@ -6956,6 +7153,12 @@ ast_interface_block::hir(exec_list *instructions,
earlier_per_vertex->fields.structure[j].patch;
fields[i].precision =
earlier_per_vertex->fields.structure[j].precision;
+ fields[i].explicit_xfb_buffer =
+ earlier_per_vertex->fields.structure[j].explicit_xfb_buffer;
+ fields[i].xfb_buffer =
+ earlier_per_vertex->fields.structure[j].xfb_buffer;
+ fields[i].xfb_stride =
+ earlier_per_vertex->fields.structure[j].xfb_stride;
}
}
@@ -6986,6 +7189,12 @@ ast_interface_block::hir(exec_list *instructions,
packing,
this->block_name);
+ unsigned component_size = block_type->contains_double() ? 8 : 4;
+ int xfb_offset =
+ layout.flags.q.explicit_xfb_offset ? (int) qual_xfb_offset : -1;
+ validate_xfb_offset_qualifier(&loc, state, xfb_offset, block_type,
+ component_size);
+
if (!state->symbols->add_interface(block_type->name, block_type, var_mode)) {
YYLTYPE loc = this->get_location();
_mesa_glsl_error(&loc, state, "interface block `%s' with type `%s' "
@@ -7207,8 +7416,17 @@ ast_interface_block::hir(exec_list *instructions,
var->data.patch = fields[i].patch;
var->data.stream = qual_stream;
var->data.location = fields[i].location;
+
if (fields[i].location != -1)
var->data.explicit_location = true;
+
+ var->data.explicit_xfb_buffer = fields[i].explicit_xfb_buffer;
+ var->data.xfb_buffer = fields[i].xfb_buffer;
+
+ if (fields[i].offset != -1)
+ var->data.explicit_xfb_offset = true;
+ var->data.offset = fields[i].offset;
+
var->init_interface_type(block_type);
if (var_mode == ir_var_shader_in || var_mode == ir_var_uniform)
diff --git a/src/compiler/glsl/ast_type.cpp b/src/compiler/glsl/ast_type.cpp
index 07ed4f2..c3d38cb 100644
--- a/src/compiler/glsl/ast_type.cpp
+++ b/src/compiler/glsl/ast_type.cpp
@@ -79,7 +79,10 @@ ast_type_qualifier::has_layout() const
|| this->flags.q.explicit_index
|| this->flags.q.explicit_binding
|| this->flags.q.explicit_offset
- || this->flags.q.explicit_stream;
+ || this->flags.q.explicit_stream
+ || this->flags.q.explicit_xfb_buffer
+ || this->flags.q.explicit_xfb_offset
+ || this->flags.q.explicit_xfb_stride;
}
bool
@@ -229,6 +232,43 @@ ast_type_qualifier::merge_qualifier(YYLTYPE *loc,
}
}
+ if (state->has_enhanced_layouts()) {
+ if (!this->flags.q.explicit_xfb_buffer) {
+ if (q.flags.q.xfb_buffer) {
+ this->flags.q.xfb_buffer = 1;
+ this->xfb_buffer = q.xfb_buffer;
+ } else if (!this->flags.q.xfb_buffer && this->flags.q.out) {
+ /* Assign global xfb_buffer value */
+ this->flags.q.xfb_buffer = 1;
+ this->xfb_buffer = state->out_qualifier->xfb_buffer;
+ }
+ }
+
+ if (q.flags.q.explicit_xfb_stride)
+ this->xfb_stride = q.xfb_stride;
+
+ /* Merge all we xfb_stride qualifiers into the global out */
+ if (q.flags.q.explicit_xfb_stride || this->flags.q.xfb_stride) {
+
+ /* Set xfb_stride flag to 0 to avoid adding duplicates every time
+ * there is a merge.
+ */
+ this->flags.q.xfb_stride = 0;
+
+ unsigned buff_idx;
+ if (process_qualifier_constant(state, loc, "xfb_buffer",
+ this->xfb_buffer, &buff_idx)) {
+ if (state->out_qualifier->out_xfb_stride[buff_idx]) {
+ state->out_qualifier->out_xfb_stride[buff_idx]->merge_qualifier(
+ new(state) ast_layout_expression(*loc, this->xfb_stride));
+ } else {
+ state->out_qualifier->out_xfb_stride[buff_idx] =
+ new(state) ast_layout_expression(*loc, this->xfb_stride);
+ }
+ }
+ }
+ }
+
if (q.flags.q.vertices) {
if (this->vertices) {
this->vertices->merge_qualifier(q.vertices);
@@ -300,7 +340,7 @@ ast_type_qualifier::merge_qualifier(YYLTYPE *loc,
if (q.flags.q.explicit_binding)
this->binding = q.binding;
- if (q.flags.q.explicit_offset)
+ if (q.flags.q.explicit_offset || q.flags.q.explicit_xfb_offset)
this->offset = q.offset;
if (q.precision != ast_precision_none)
@@ -322,6 +362,8 @@ ast_type_qualifier::merge_out_qualifier(YYLTYPE *loc,
{
void *mem_ctx = state;
const bool r = this->merge_qualifier(loc, state, q, false);
+ ast_type_qualifier valid_out_mask;
+ valid_out_mask.flags.i = 0;
if (state->stage == MESA_SHADER_GEOMETRY) {
if (q.flags.q.prim_type) {
@@ -340,13 +382,45 @@ ast_type_qualifier::merge_out_qualifier(YYLTYPE *loc,
/* Allow future assigments of global out's stream id value */
this->flags.q.explicit_stream = 0;
+
+ valid_out_mask.flags.q.stream = 1;
+ valid_out_mask.flags.q.explicit_stream = 1;
+ valid_out_mask.flags.q.explicit_xfb_buffer = 1;
+ valid_out_mask.flags.q.xfb_buffer = 1;
+ valid_out_mask.flags.q.explicit_xfb_stride = 1;
+ valid_out_mask.flags.q.xfb_stride = 1;
+ valid_out_mask.flags.q.max_vertices = 1;
+ valid_out_mask.flags.q.prim_type = 1;
} else if (state->stage == MESA_SHADER_TESS_CTRL) {
if (create_node) {
node = new(mem_ctx) ast_tcs_output_layout(*loc);
}
+ valid_out_mask.flags.q.vertices = 1;
+ valid_out_mask.flags.q.explicit_xfb_buffer = 1;
+ valid_out_mask.flags.q.xfb_buffer = 1;
+ valid_out_mask.flags.q.explicit_xfb_stride = 1;
+ valid_out_mask.flags.q.xfb_stride = 1;
+ } else if (state->stage == MESA_SHADER_TESS_EVAL ||
+ state->stage == MESA_SHADER_VERTEX) {
+ valid_out_mask.flags.q.explicit_xfb_buffer = 1;
+ valid_out_mask.flags.q.xfb_buffer = 1;
+ valid_out_mask.flags.q.explicit_xfb_stride = 1;
+ valid_out_mask.flags.q.xfb_stride = 1;
} else {
_mesa_glsl_error(loc, state, "out layout qualifiers only valid in "
- "tessellation control or geometry shaders");
+ "geometry, tessellation and vertex shaders");
+ return false;
+ }
+
+ /* Allow future assigments of global out's */
+ this->flags.q.explicit_xfb_buffer = 0;
+ this->flags.q.explicit_xfb_stride = 0;
+
+ /* Generate an error when invalid input layout qualifiers are used. */
+ if ((q.flags.i & ~valid_out_mask.flags.i) != 0) {
+ _mesa_glsl_error(loc, state,
+ "invalid output layout qualifiers used");
+ return false;
}
return r;
@@ -566,3 +640,44 @@ ast_layout_expression::process_qualifier_constant(struct _mesa_glsl_parse_state
return true;
}
+
+bool
+process_qualifier_constant(struct _mesa_glsl_parse_state *state,
+ YYLTYPE *loc,
+ const char *qual_indentifier,
+ ast_expression *const_expression,
+ unsigned *value)
+{
+ exec_list dummy_instructions;
+
+ if (const_expression == NULL) {
+ *value = 0;
+ return true;
+ }
+
+ ir_rvalue *const ir = const_expression->hir(&dummy_instructions, state);
+
+ ir_constant *const const_int = ir->constant_expression_value();
+ if (const_int == NULL || !const_int->type->is_integer()) {
+ _mesa_glsl_error(loc, state, "%s must be an integral constant "
+ "expression", qual_indentifier);
+ return false;
+ }
+
+ if (const_int->value.i[0] < 0) {
+ _mesa_glsl_error(loc, state, "%s layout qualifier is invalid (%d < 0)",
+ qual_indentifier, const_int->value.u[0]);
+ return false;
+ }
+
+ /* If the location 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 location isn't const after all, or
+ * we are emitting unnecessary instructions.
+ */
+ assert(dummy_instructions.is_empty());
+
+ *value = const_int->value.u[0];
+ return true;
+}
diff --git a/src/compiler/glsl/builtin_functions.cpp b/src/compiler/glsl/builtin_functions.cpp
index ff6b628..65309fd 100644
--- a/src/compiler/glsl/builtin_functions.cpp
+++ b/src/compiler/glsl/builtin_functions.cpp
@@ -130,12 +130,6 @@ v130_fs_only(const _mesa_glsl_parse_state *state)
}
static bool
-v140(const _mesa_glsl_parse_state *state)
-{
- return state->is_version(140, 0);
-}
-
-static bool
v140_or_es3(const _mesa_glsl_parse_state *state)
{
return state->is_version(140, 300);
@@ -184,6 +178,14 @@ v110_lod(const _mesa_glsl_parse_state *state)
}
static bool
+texture_buffer(const _mesa_glsl_parse_state *state)
+{
+ return state->is_version(140, 320) ||
+ state->EXT_texture_buffer_enable ||
+ state->OES_texture_buffer_enable;
+}
+
+static bool
shader_texture_lod(const _mesa_glsl_parse_state *state)
{
return state->ARB_shader_texture_lod_enable;
@@ -262,10 +264,12 @@ shader_packing_or_es31_or_gpu_shader5(const _mesa_glsl_parse_state *state)
}
static bool
-fs_gpu_shader5(const _mesa_glsl_parse_state *state)
+fs_interpolate_at(const _mesa_glsl_parse_state *state)
{
return state->stage == MESA_SHADER_FRAGMENT &&
- (state->is_version(400, 0) || state->ARB_gpu_shader5_enable);
+ (state->is_version(400, 320) ||
+ state->ARB_gpu_shader5_enable ||
+ state->OES_shader_multisample_interpolation_enable);
}
@@ -1581,9 +1585,9 @@ builtin_builder::create_builtins()
_textureSize(v130, glsl_type::ivec2_type, glsl_type::usampler2DRect_type),
_textureSize(v130, glsl_type::ivec2_type, glsl_type::sampler2DRectShadow_type),
- _textureSize(v140, glsl_type::int_type, glsl_type::samplerBuffer_type),
- _textureSize(v140, glsl_type::int_type, glsl_type::isamplerBuffer_type),
- _textureSize(v140, glsl_type::int_type, glsl_type::usamplerBuffer_type),
+ _textureSize(texture_buffer, glsl_type::int_type, glsl_type::samplerBuffer_type),
+ _textureSize(texture_buffer, glsl_type::int_type, glsl_type::isamplerBuffer_type),
+ _textureSize(texture_buffer, glsl_type::int_type, glsl_type::usamplerBuffer_type),
_textureSize(texture_multisample, glsl_type::ivec2_type, glsl_type::sampler2DMS_type),
_textureSize(texture_multisample, glsl_type::ivec2_type, glsl_type::isampler2DMS_type),
_textureSize(texture_multisample, glsl_type::ivec2_type, glsl_type::usampler2DMS_type),
@@ -1855,9 +1859,9 @@ builtin_builder::create_builtins()
_texelFetch(v130, glsl_type::ivec4_type, glsl_type::isampler2DArray_type, glsl_type::ivec3_type),
_texelFetch(v130, glsl_type::uvec4_type, glsl_type::usampler2DArray_type, glsl_type::ivec3_type),
- _texelFetch(v140, glsl_type::vec4_type, glsl_type::samplerBuffer_type, glsl_type::int_type),
- _texelFetch(v140, glsl_type::ivec4_type, glsl_type::isamplerBuffer_type, glsl_type::int_type),
- _texelFetch(v140, glsl_type::uvec4_type, glsl_type::usamplerBuffer_type, glsl_type::int_type),
+ _texelFetch(texture_buffer, glsl_type::vec4_type, glsl_type::samplerBuffer_type, glsl_type::int_type),
+ _texelFetch(texture_buffer, glsl_type::ivec4_type, glsl_type::isamplerBuffer_type, glsl_type::int_type),
+ _texelFetch(texture_buffer, glsl_type::uvec4_type, glsl_type::usamplerBuffer_type, glsl_type::int_type),
_texelFetch(texture_multisample, glsl_type::vec4_type, glsl_type::sampler2DMS_type, glsl_type::ivec2_type),
_texelFetch(texture_multisample, glsl_type::ivec4_type, glsl_type::isampler2DMS_type, glsl_type::ivec2_type),
@@ -5163,7 +5167,7 @@ builtin_builder::_interpolateAtCentroid(const glsl_type *type)
{
ir_variable *interpolant = in_var(type, "interpolant");
interpolant->data.must_be_shader_input = 1;
- MAKE_SIG(type, fs_gpu_shader5, 1, interpolant);
+ MAKE_SIG(type, fs_interpolate_at, 1, interpolant);
body.emit(ret(interpolate_at_centroid(interpolant)));
@@ -5176,7 +5180,7 @@ builtin_builder::_interpolateAtOffset(const glsl_type *type)
ir_variable *interpolant = in_var(type, "interpolant");
interpolant->data.must_be_shader_input = 1;
ir_variable *offset = in_var(glsl_type::vec2_type, "offset");
- MAKE_SIG(type, fs_gpu_shader5, 2, interpolant, offset);
+ MAKE_SIG(type, fs_interpolate_at, 2, interpolant, offset);
body.emit(ret(interpolate_at_offset(interpolant, offset)));
@@ -5189,7 +5193,7 @@ builtin_builder::_interpolateAtSample(const glsl_type *type)
ir_variable *interpolant = in_var(type, "interpolant");
interpolant->data.must_be_shader_input = 1;
ir_variable *sample_num = in_var(glsl_type::int_type, "sample_num");
- MAKE_SIG(type, fs_gpu_shader5, 2, interpolant, sample_num);
+ MAKE_SIG(type, fs_interpolate_at, 2, interpolant, sample_num);
body.emit(ret(interpolate_at_sample(interpolant, sample_num)));
diff --git a/src/compiler/glsl/builtin_types.cpp b/src/compiler/glsl/builtin_types.cpp
index ee24bd5..d250234 100644
--- a/src/compiler/glsl/builtin_types.cpp
+++ b/src/compiler/glsl/builtin_types.cpp
@@ -179,7 +179,7 @@ static const struct builtin_type_versions {
T(sampler2DArray, 130, 300)
T(samplerCubeArray, 400, 999)
T(sampler2DRect, 140, 999)
- T(samplerBuffer, 140, 999)
+ T(samplerBuffer, 140, 320)
T(sampler2DMS, 150, 310)
T(sampler2DMSArray, 150, 999)
@@ -191,7 +191,7 @@ static const struct builtin_type_versions {
T(isampler2DArray, 130, 300)
T(isamplerCubeArray, 400, 999)
T(isampler2DRect, 140, 999)
- T(isamplerBuffer, 140, 999)
+ T(isamplerBuffer, 140, 320)
T(isampler2DMS, 150, 310)
T(isampler2DMSArray, 150, 999)
@@ -203,7 +203,7 @@ static const struct builtin_type_versions {
T(usampler2DArray, 130, 300)
T(usamplerCubeArray, 400, 999)
T(usampler2DRect, 140, 999)
- T(usamplerBuffer, 140, 999)
+ T(usamplerBuffer, 140, 320)
T(usampler2DMS, 150, 310)
T(usampler2DMSArray, 150, 999)
@@ -222,7 +222,7 @@ static const struct builtin_type_versions {
T(image3D, 420, 310)
T(image2DRect, 420, 999)
T(imageCube, 420, 310)
- T(imageBuffer, 420, 999)
+ T(imageBuffer, 420, 320)
T(image1DArray, 420, 999)
T(image2DArray, 420, 310)
T(imageCubeArray, 420, 999)
@@ -233,7 +233,7 @@ static const struct builtin_type_versions {
T(iimage3D, 420, 310)
T(iimage2DRect, 420, 999)
T(iimageCube, 420, 310)
- T(iimageBuffer, 420, 999)
+ T(iimageBuffer, 420, 320)
T(iimage1DArray, 420, 999)
T(iimage2DArray, 420, 310)
T(iimageCubeArray, 420, 999)
@@ -244,7 +244,7 @@ static const struct builtin_type_versions {
T(uimage3D, 420, 310)
T(uimage2DRect, 420, 999)
T(uimageCube, 420, 310)
- T(uimageBuffer, 420, 999)
+ T(uimageBuffer, 420, 320)
T(uimage1DArray, 420, 999)
T(uimage2DArray, 420, 310)
T(uimageCubeArray, 420, 999)
@@ -371,6 +371,16 @@ _mesa_glsl_initialize_types(struct _mesa_glsl_parse_state *state)
add_type(symbols, glsl_type::uimage2DMSArray_type);
}
+ if (state->EXT_texture_buffer_enable || state->OES_texture_buffer_enable) {
+ add_type(symbols, glsl_type::samplerBuffer_type);
+ add_type(symbols, glsl_type::isamplerBuffer_type);
+ add_type(symbols, glsl_type::usamplerBuffer_type);
+
+ add_type(symbols, glsl_type::imageBuffer_type);
+ add_type(symbols, glsl_type::iimageBuffer_type);
+ add_type(symbols, glsl_type::uimageBuffer_type);
+ }
+
if (state->has_atomic_counters()) {
add_type(symbols, glsl_type::atomic_uint_type);
}
diff --git a/src/compiler/glsl/builtin_variables.cpp b/src/compiler/glsl/builtin_variables.cpp
index 4e2de37..7d77f70 100644
--- a/src/compiler/glsl/builtin_variables.cpp
+++ b/src/compiler/glsl/builtin_variables.cpp
@@ -334,6 +334,9 @@ per_vertex_accumulator::add_field(int slot, const glsl_type *type,
this->fields[this->num_fields].image_coherent = 0;
this->fields[this->num_fields].image_volatile = 0;
this->fields[this->num_fields].image_restrict = 0;
+ this->fields[this->num_fields].explicit_xfb_buffer = 0;
+ this->fields[this->num_fields].xfb_buffer = -1;
+ this->fields[this->num_fields].xfb_stride = -1;
this->num_fields++;
}
@@ -812,6 +815,13 @@ builtin_variable_generator::generate_constants()
*/
}
+ if (state->has_enhanced_layouts()) {
+ add_const("gl_MaxTransformFeedbackBuffers",
+ state->Const.MaxTransformFeedbackBuffers);
+ add_const("gl_MaxTransformFeedbackInterleavedComponents",
+ state->Const.MaxTransformFeedbackInterleavedComponents);
+ }
+
if (state->is_version(420, 310) ||
state->ARB_shader_image_load_store_enable) {
add_const("gl_MaxImageUnits",
@@ -868,6 +878,10 @@ builtin_variable_generator::generate_constants()
add_const("gl_MaxTessControlUniformComponents", state->Const.MaxTessControlUniformComponents);
add_const("gl_MaxTessEvaluationUniformComponents", state->Const.MaxTessEvaluationUniformComponents);
}
+
+ if (state->is_version(450, 320) ||
+ state->OES_sample_variables_enable)
+ add_const("gl_MaxSamples", state->Const.MaxSamples);
}
@@ -877,7 +891,9 @@ builtin_variable_generator::generate_constants()
void
builtin_variable_generator::generate_uniforms()
{
- if (state->is_version(400, 0) || state->ARB_sample_shading_enable)
+ if (state->is_version(400, 320) ||
+ state->ARB_sample_shading_enable ||
+ state->OES_sample_variables_enable)
add_uniform(int_t, "gl_NumSamples");
add_uniform(type("gl_DepthRangeParameters"), "gl_DepthRange");
add_uniform(array(vec4_t, VERT_ATTRIB_MAX), "gl_CurrentAttribVertMESA");
@@ -1130,7 +1146,9 @@ builtin_variable_generator::generate_fs_special_vars()
var->enable_extension_warning("GL_AMD_shader_stencil_export");
}
- if (state->is_version(400, 0) || state->ARB_sample_shading_enable) {
+ if (state->is_version(400, 320) ||
+ state->ARB_sample_shading_enable ||
+ state->OES_sample_variables_enable) {
add_system_value(SYSTEM_VALUE_SAMPLE_ID, int_t, "gl_SampleID");
add_system_value(SYSTEM_VALUE_SAMPLE_POS, vec2_t, "gl_SamplePosition");
/* From the ARB_sample_shading specification:
@@ -1143,7 +1161,9 @@ builtin_variable_generator::generate_fs_special_vars()
add_output(FRAG_RESULT_SAMPLE_MASK, array(int_t, 1), "gl_SampleMask");
}
- if (state->is_version(400, 0) || state->ARB_gpu_shader5_enable) {
+ if (state->is_version(400, 320) ||
+ state->ARB_gpu_shader5_enable ||
+ state->OES_sample_variables_enable) {
add_system_value(SYSTEM_VALUE_SAMPLE_MASK_IN, array(int_t, 1), "gl_SampleMaskIn");
}
diff --git a/src/compiler/glsl/glcpp/glcpp-parse.y b/src/compiler/glsl/glcpp/glcpp-parse.y
index 007b70b..e8646c0 100644
--- a/src/compiler/glsl/glcpp/glcpp-parse.y
+++ b/src/compiler/glsl/glcpp/glcpp-parse.y
@@ -2371,6 +2371,10 @@ _glcpp_parser_handle_version_declaration(glcpp_parser_t *parser, intmax_t versio
if (extensions != NULL) {
if (extensions->OES_EGL_image_external)
add_builtin_define(parser, "GL_OES_EGL_image_external", 1);
+ if (extensions->OES_sample_variables) {
+ add_builtin_define(parser, "GL_OES_sample_variables", 1);
+ add_builtin_define(parser, "GL_OES_shader_multisample_interpolation", 1);
+ }
if (extensions->OES_standard_derivatives)
add_builtin_define(parser, "GL_OES_standard_derivatives", 1);
if (extensions->ARB_texture_multisample)
@@ -2390,6 +2394,10 @@ _glcpp_parser_handle_version_declaration(glcpp_parser_t *parser, intmax_t versio
add_builtin_define(parser, "GL_EXT_gpu_shader5", 1);
add_builtin_define(parser, "GL_OES_gpu_shader5", 1);
}
+ if (extensions->OES_texture_buffer) {
+ add_builtin_define(parser, "GL_EXT_texture_buffer", 1);
+ add_builtin_define(parser, "GL_OES_texture_buffer", 1);
+ }
}
}
} else {
diff --git a/src/compiler/glsl/glsl_lexer.ll b/src/compiler/glsl/glsl_lexer.ll
index 1f12265..0b7695f 100644
--- a/src/compiler/glsl/glsl_lexer.ll
+++ b/src/compiler/glsl/glsl_lexer.ll
@@ -369,7 +369,7 @@ image2D KEYWORD_WITH_ALT(130, 300, 420, 310, yyextra->ARB_shader_image_l
image3D KEYWORD_WITH_ALT(130, 300, 420, 310, yyextra->ARB_shader_image_load_store_enable, IMAGE3D);
image2DRect KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IMAGE2DRECT);
imageCube KEYWORD_WITH_ALT(130, 300, 420, 310, yyextra->ARB_shader_image_load_store_enable, IMAGECUBE);
-imageBuffer KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IMAGEBUFFER);
+imageBuffer KEYWORD_WITH_ALT(130, 300, 420, 320, yyextra->ARB_shader_image_load_store_enable || yyextra->EXT_texture_buffer_enable || yyextra->OES_texture_buffer_enable, IMAGEBUFFER);
image1DArray KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IMAGE1DARRAY);
image2DArray KEYWORD_WITH_ALT(130, 300, 420, 310, yyextra->ARB_shader_image_load_store_enable, IMAGE2DARRAY);
imageCubeArray KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IMAGECUBEARRAY);
@@ -380,7 +380,7 @@ iimage2D KEYWORD_WITH_ALT(130, 300, 420, 310, yyextra->ARB_shader_image_l
iimage3D KEYWORD_WITH_ALT(130, 300, 420, 310, yyextra->ARB_shader_image_load_store_enable, IIMAGE3D);
iimage2DRect KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IIMAGE2DRECT);
iimageCube KEYWORD_WITH_ALT(130, 300, 420, 310, yyextra->ARB_shader_image_load_store_enable, IIMAGECUBE);
-iimageBuffer KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IIMAGEBUFFER);
+iimageBuffer KEYWORD_WITH_ALT(130, 300, 420, 320, yyextra->ARB_shader_image_load_store_enable || yyextra->EXT_texture_buffer_enable || yyextra->OES_texture_buffer_enable, IIMAGEBUFFER);
iimage1DArray KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IIMAGE1DARRAY);
iimage2DArray KEYWORD_WITH_ALT(130, 300, 420, 310, yyextra->ARB_shader_image_load_store_enable, IIMAGE2DARRAY);
iimageCubeArray KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IIMAGECUBEARRAY);
@@ -391,7 +391,7 @@ uimage2D KEYWORD_WITH_ALT(130, 300, 420, 310, yyextra->ARB_shader_image_l
uimage3D KEYWORD_WITH_ALT(130, 300, 420, 310, yyextra->ARB_shader_image_load_store_enable, UIMAGE3D);
uimage2DRect KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, UIMAGE2DRECT);
uimageCube KEYWORD_WITH_ALT(130, 300, 420, 310, yyextra->ARB_shader_image_load_store_enable, UIMAGECUBE);
-uimageBuffer KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, UIMAGEBUFFER);
+uimageBuffer KEYWORD_WITH_ALT(130, 300, 420, 320, yyextra->ARB_shader_image_load_store_enable || yyextra->EXT_texture_buffer_enable || yyextra->OES_texture_buffer_enable, UIMAGEBUFFER);
uimage1DArray KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, UIMAGE1DARRAY);
uimage2DArray KEYWORD_WITH_ALT(130, 300, 420, 310, yyextra->ARB_shader_image_load_store_enable, UIMAGE2DARRAY);
uimageCubeArray KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, UIMAGECUBEARRAY);
@@ -472,6 +472,13 @@ layout {
\.[0-9]+([eE][+-]?[0-9]+)?[fF]? |
[0-9]+\.([eE][+-]?[0-9]+)?[fF]? |
[0-9]+[eE][+-]?[0-9]+[fF]? {
+ struct _mesa_glsl_parse_state *state = yyextra;
+ char suffix = yytext[strlen(yytext) - 1];
+ if (!state->is_version(120, 300) &&
+ (suffix == 'f' || suffix == 'F')) {
+ _mesa_glsl_error(yylloc, state,
+ "Float suffixes are invalid in GLSL 1.10");
+ }
yylval->real = _mesa_strtof(yytext, NULL);
return FLOATCONSTANT;
}
@@ -565,19 +572,19 @@ common KEYWORD(130, 300, 0, 0, COMMON);
partition KEYWORD(130, 300, 0, 0, PARTITION);
active KEYWORD(130, 300, 0, 0, ACTIVE);
superp KEYWORD(130, 100, 0, 0, SUPERP);
-samplerBuffer KEYWORD(130, 300, 140, 0, SAMPLERBUFFER);
+samplerBuffer KEYWORD_WITH_ALT(130, 300, 140, 320, yyextra->EXT_texture_buffer_enable || yyextra->OES_texture_buffer_enable, SAMPLERBUFFER);
filter KEYWORD(130, 300, 0, 0, FILTER);
row_major KEYWORD_WITH_ALT(130, 0, 140, 0, yyextra->ARB_uniform_buffer_object_enable && !yyextra->es_shader, ROW_MAJOR);
/* Additional reserved words in GLSL 1.40 */
isampler2DRect KEYWORD(140, 300, 140, 0, ISAMPLER2DRECT);
usampler2DRect KEYWORD(140, 300, 140, 0, USAMPLER2DRECT);
-isamplerBuffer KEYWORD(140, 300, 140, 0, ISAMPLERBUFFER);
-usamplerBuffer KEYWORD(140, 300, 140, 0, USAMPLERBUFFER);
+isamplerBuffer KEYWORD_WITH_ALT(140, 300, 140, 320, yyextra->EXT_texture_buffer_enable || yyextra->OES_texture_buffer_enable, ISAMPLERBUFFER);
+usamplerBuffer KEYWORD_WITH_ALT(140, 300, 140, 320, yyextra->EXT_texture_buffer_enable || yyextra->OES_texture_buffer_enable, USAMPLERBUFFER);
/* Additional reserved words in GLSL ES 3.00 */
resource KEYWORD(0, 300, 0, 0, RESOURCE);
-sample KEYWORD_WITH_ALT(400, 300, 400, 0, yyextra->ARB_gpu_shader5_enable, SAMPLE);
+sample KEYWORD_WITH_ALT(400, 300, 400, 320, yyextra->ARB_gpu_shader5_enable || yyextra->OES_shader_multisample_interpolation_enable, SAMPLE);
subroutine KEYWORD_WITH_ALT(400, 300, 400, 0, yyextra->ARB_shader_subroutine_enable, SUBROUTINE);
diff --git a/src/compiler/glsl/glsl_parser.yy b/src/compiler/glsl/glsl_parser.yy
index 5ed051a..1cecc09 100644
--- a/src/compiler/glsl/glsl_parser.yy
+++ b/src/compiler/glsl/glsl_parser.yy
@@ -1541,6 +1541,25 @@ layout_qualifier_id:
}
}
+ if (state->has_enhanced_layouts()) {
+ if (match_layout_qualifier("xfb_buffer", $1, state) == 0) {
+ $$.flags.q.xfb_buffer = 1;
+ $$.flags.q.explicit_xfb_buffer = 1;
+ $$.xfb_buffer = $3;
+ }
+
+ if (match_layout_qualifier("xfb_offset", $1, state) == 0) {
+ $$.flags.q.explicit_xfb_offset = 1;
+ $$.offset = $3;
+ }
+
+ if (match_layout_qualifier("xfb_stride", $1, state) == 0) {
+ $$.flags.q.xfb_stride = 1;
+ $$.flags.q.explicit_xfb_stride = 1;
+ $$.xfb_stride = $3;
+ }
+ }
+
static const char * const local_size_qualifiers[3] = {
"local_size_x",
"local_size_y",
@@ -1915,6 +1934,12 @@ storage_qualifier:
$$.flags.q.explicit_stream = 0;
$$.stream = state->out_qualifier->stream;
}
+
+ if (state->has_enhanced_layouts()) {
+ $$.flags.q.xfb_buffer = 1;
+ $$.flags.q.explicit_xfb_buffer = 0;
+ $$.xfb_buffer = state->out_qualifier->xfb_buffer;
+ }
}
| UNIFORM
{
diff --git a/src/compiler/glsl/glsl_parser_extras.cpp b/src/compiler/glsl/glsl_parser_extras.cpp
index 5d010fd..2941277 100644
--- a/src/compiler/glsl/glsl_parser_extras.cpp
+++ b/src/compiler/glsl/glsl_parser_extras.cpp
@@ -140,6 +140,10 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx,
this->Const.MaxAtomicCounterBufferSize =
ctx->Const.MaxAtomicBufferSize;
+ /* ARB_enhanced_layouts constants */
+ this->Const.MaxTransformFeedbackBuffers = ctx->Const.MaxTransformFeedbackBuffers;
+ this->Const.MaxTransformFeedbackInterleavedComponents = ctx->Const.MaxTransformFeedbackInterleavedComponents;
+
/* Compute shader constants */
for (unsigned i = 0; i < ARRAY_SIZE(this->Const.MaxComputeWorkGroupCount); i++)
this->Const.MaxComputeWorkGroupCount[i] = ctx->Const.MaxComputeWorkGroupCount[i];
@@ -177,6 +181,9 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx,
this->Const.MaxTessControlUniformComponents = ctx->Const.Program[MESA_SHADER_TESS_CTRL].MaxUniformComponents;
this->Const.MaxTessEvaluationUniformComponents = ctx->Const.Program[MESA_SHADER_TESS_EVAL].MaxUniformComponents;
+ /* GL 4.5 / OES_sample_variables */
+ this->Const.MaxSamples = ctx->Const.MaxSamples;
+
this->current_function = NULL;
this->toplevel_ir = NULL;
this->found_return = false;
@@ -610,9 +617,12 @@ static const _mesa_glsl_extension _mesa_glsl_supported_extensions[] = {
EXT(OES_geometry_point_size, false, true, OES_geometry_shader),
EXT(OES_geometry_shader, false, true, OES_geometry_shader),
EXT(OES_gpu_shader5, false, true, ARB_gpu_shader5),
+ EXT(OES_sample_variables, false, true, OES_sample_variables),
EXT(OES_shader_image_atomic, false, true, ARB_shader_image_load_store),
+ EXT(OES_shader_multisample_interpolation, false, true, OES_sample_variables),
EXT(OES_standard_derivatives, false, true, OES_standard_derivatives),
EXT(OES_texture_3D, false, true, dummy_true),
+ EXT(OES_texture_buffer, false, true, OES_texture_buffer),
EXT(OES_texture_storage_multisample_2d_array, false, true, ARB_texture_multisample),
/* All other extensions go here, sorted alphabetically.
@@ -629,6 +639,7 @@ static const _mesa_glsl_extension _mesa_glsl_supported_extensions[] = {
EXT(EXT_shader_integer_mix, true, true, EXT_shader_integer_mix),
EXT(EXT_shader_samples_identical, true, true, EXT_shader_samples_identical),
EXT(EXT_texture_array, true, false, EXT_texture_array),
+ EXT(EXT_texture_buffer, false, true, OES_texture_buffer),
};
#undef EXT
@@ -935,6 +946,13 @@ _mesa_ast_process_interface_block(YYLTYPE *locp,
block->layout.stream = state->out_qualifier->stream;
}
+ if (state->has_enhanced_layouts() && block->layout.flags.q.out) {
+ /* Assign global layout's xfb_buffer value. */
+ block->layout.flags.q.xfb_buffer = 1;
+ block->layout.flags.q.explicit_xfb_buffer = 0;
+ block->layout.xfb_buffer = state->out_qualifier->xfb_buffer;
+ }
+
foreach_list_typed (ast_declarator_list, member, link, &block->declarations) {
ast_type_qualifier& qualifier = member->type->qualifier;
if ((qualifier.flags.i & interface_type_mask) == 0) {
@@ -1206,6 +1224,7 @@ ast_expression::ast_expression(int oper,
this->subexpressions[1] = ex1;
this->subexpressions[2] = ex2;
this->non_lvalue_description = NULL;
+ this->is_lhs = false;
}
@@ -1583,13 +1602,12 @@ set_shader_inout_layout(struct gl_shader *shader,
struct _mesa_glsl_parse_state *state)
{
/* Should have been prevented by the parser. */
- if (shader->Stage == MESA_SHADER_TESS_CTRL) {
+ if (shader->Stage == MESA_SHADER_TESS_CTRL ||
+ shader->Stage == MESA_SHADER_VERTEX) {
assert(!state->in_qualifier->flags.i);
- } else if (shader->Stage == MESA_SHADER_TESS_EVAL) {
- assert(!state->out_qualifier->flags.i);
- } else if (shader->Stage != MESA_SHADER_GEOMETRY) {
+ } else if (shader->Stage != MESA_SHADER_GEOMETRY &&
+ shader->Stage != MESA_SHADER_TESS_EVAL) {
assert(!state->in_qualifier->flags.i);
- assert(!state->out_qualifier->flags.i);
}
if (shader->Stage != MESA_SHADER_COMPUTE) {
@@ -1606,6 +1624,17 @@ set_shader_inout_layout(struct gl_shader *shader,
assert(!state->fs_early_fragment_tests);
}
+ for (unsigned i = 0; i < MAX_FEEDBACK_BUFFERS; i++) {
+ if (state->out_qualifier->out_xfb_stride[i]) {
+ unsigned xfb_stride;
+ if (state->out_qualifier->out_xfb_stride[i]->
+ process_qualifier_constant(state, "xfb_stride", &xfb_stride,
+ true)) {
+ shader->TransformFeedback.BufferStride[i] = xfb_stride;
+ }
+ }
+ }
+
switch (shader->Stage) {
case MESA_SHADER_TESS_CTRL:
shader->TessCtrl.VerticesOut = 0;
diff --git a/src/compiler/glsl/glsl_parser_extras.h b/src/compiler/glsl/glsl_parser_extras.h
index 12a3a46..0cc2d25 100644
--- a/src/compiler/glsl/glsl_parser_extras.h
+++ b/src/compiler/glsl/glsl_parser_extras.h
@@ -383,6 +383,10 @@ struct _mesa_glsl_parse_state {
/* ARB_draw_buffers */
unsigned MaxDrawBuffers;
+ /* ARB_enhanced_layouts */
+ unsigned MaxTransformFeedbackBuffers;
+ unsigned MaxTransformFeedbackInterleavedComponents;
+
/* ARB_blend_func_extended */
unsigned MaxDualSourceDrawBuffers;
@@ -457,6 +461,9 @@ struct _mesa_glsl_parse_state {
unsigned MaxTessControlTotalOutputComponents;
unsigned MaxTessControlUniformComponents;
unsigned MaxTessEvaluationUniformComponents;
+
+ /* GL 4.5 / OES_sample_variables */
+ unsigned MaxSamples;
} Const;
/**
@@ -597,12 +604,18 @@ struct _mesa_glsl_parse_state {
bool OES_geometry_shader_warn;
bool OES_gpu_shader5_enable;
bool OES_gpu_shader5_warn;
+ bool OES_sample_variables_enable;
+ bool OES_sample_variables_warn;
bool OES_shader_image_atomic_enable;
bool OES_shader_image_atomic_warn;
+ bool OES_shader_multisample_interpolation_enable;
+ bool OES_shader_multisample_interpolation_warn;
bool OES_standard_derivatives_enable;
bool OES_standard_derivatives_warn;
bool OES_texture_3D_enable;
bool OES_texture_3D_warn;
+ bool OES_texture_buffer_enable;
+ bool OES_texture_buffer_warn;
bool OES_texture_storage_multisample_2d_array_enable;
bool OES_texture_storage_multisample_2d_array_warn;
@@ -632,6 +645,8 @@ struct _mesa_glsl_parse_state {
bool EXT_shader_samples_identical_warn;
bool EXT_texture_array_enable;
bool EXT_texture_array_warn;
+ bool EXT_texture_buffer_enable;
+ bool EXT_texture_buffer_warn;
/*@}*/
/** Extensions supported by the OpenGL implementation. */
diff --git a/src/compiler/glsl/ir.h b/src/compiler/glsl/ir.h
index b74d68a..b1a1d56 100644
--- a/src/compiler/glsl/ir.h
+++ b/src/compiler/glsl/ir.h
@@ -727,6 +727,21 @@ public:
unsigned is_xfb_only:1;
/**
+ * Was a transfor feedback buffer set in the shader?
+ */
+ unsigned explicit_xfb_buffer:1;
+
+ /**
+ * Was a transfor feedback offset set in the shader?
+ */
+ unsigned explicit_xfb_offset:1;
+
+ /**
+ * Was a transfor feedback stride set in the shader?
+ */
+ unsigned explicit_xfb_stride:1;
+
+ /**
* If non-zero, then this variable may be packed along with other variables
* into a single varying slot, so this offset should be applied when
* accessing components. For example, an offset of 1 means that the x
@@ -742,21 +757,9 @@ public:
/**
* Non-zero if this variable was created by lowering a named interface
- * block which was not an array.
- *
- * Note that this variable and \c from_named_ifc_block_array will never
- * both be non-zero.
+ * block.
*/
- unsigned from_named_ifc_block_nonarray:1;
-
- /**
- * Non-zero if this variable was created by lowering a named interface
- * block which was an array.
- *
- * Note that this variable and \c from_named_ifc_block_nonarray will never
- * both be non-zero.
- */
- unsigned from_named_ifc_block_array:1;
+ unsigned from_named_ifc_block:1;
/**
* Non-zero if the variable must be a shader input. This is useful for
@@ -873,7 +876,7 @@ public:
unsigned stream;
/**
- * Atomic or block member offset.
+ * Atomic, transform feedback or block member offset.
*/
unsigned offset;
@@ -885,6 +888,16 @@ public:
unsigned max_array_access;
/**
+ * Transform feedback buffer.
+ */
+ unsigned xfb_buffer;
+
+ /**
+ * Transform feedback stride.
+ */
+ unsigned xfb_stride;
+
+ /**
* Allow (only) ir_variable direct access private members.
*/
friend class ir_variable;
diff --git a/src/compiler/glsl/ir_uniform.h b/src/compiler/glsl/ir_uniform.h
index 1854279..e72e7b4 100644
--- a/src/compiler/glsl/ir_uniform.h
+++ b/src/compiler/glsl/ir_uniform.h
@@ -105,11 +105,6 @@ struct gl_uniform_storage {
*/
unsigned array_elements;
- /**
- * Has this uniform ever been set?
- */
- bool initialized;
-
struct gl_opaque_uniform_index opaque[MESA_SHADER_STAGES];
/**
diff --git a/src/compiler/glsl/link_interface_blocks.cpp b/src/compiler/glsl/link_interface_blocks.cpp
index 4c6fb56..2607259 100644
--- a/src/compiler/glsl/link_interface_blocks.cpp
+++ b/src/compiler/glsl/link_interface_blocks.cpp
@@ -242,7 +242,8 @@ public:
return entry ? (ir_variable *) entry->data : NULL;
} else {
const struct hash_entry *entry =
- _mesa_hash_table_search(ht, var->get_interface_type()->name);
+ _mesa_hash_table_search(ht,
+ var->get_interface_type()->without_array()->name);
return entry ? (ir_variable *) entry->data : NULL;
}
}
@@ -263,7 +264,8 @@ public:
snprintf(location_str, 11, "%d", var->data.location);
_mesa_hash_table_insert(ht, ralloc_strdup(mem_ctx, location_str), var);
} else {
- _mesa_hash_table_insert(ht, var->get_interface_type()->name, var);
+ _mesa_hash_table_insert(ht,
+ var->get_interface_type()->without_array()->name, var);
}
}
diff --git a/src/compiler/glsl/link_uniform_initializers.cpp b/src/compiler/glsl/link_uniform_initializers.cpp
index 3609f81..870bc5b 100644
--- a/src/compiler/glsl/link_uniform_initializers.cpp
+++ b/src/compiler/glsl/link_uniform_initializers.cpp
@@ -162,8 +162,6 @@ set_opaque_binding(void *mem_ctx, gl_shader_program *prog,
}
}
}
-
- storage->initialized = true;
}
}
@@ -183,7 +181,7 @@ set_block_binding(gl_shader_program *prog, const char *block_name, int binding)
if (stage_index != -1) {
struct gl_shader *sh = prog->_LinkedShaders[i];
- sh->BufferInterfaceBlocks[stage_index].Binding = binding;
+ sh->BufferInterfaceBlocks[stage_index]->Binding = binding;
}
}
}
@@ -267,8 +265,6 @@ set_uniform_initializer(void *mem_ctx, gl_shader_program *prog,
}
}
}
-
- storage->initialized = true;
}
}
diff --git a/src/compiler/glsl/link_uniforms.cpp b/src/compiler/glsl/link_uniforms.cpp
index 940cc61..0a230ca 100644
--- a/src/compiler/glsl/link_uniforms.cpp
+++ b/src/compiler/glsl/link_uniforms.cpp
@@ -68,7 +68,7 @@ program_resource_visitor::process(const glsl_type *type, const char *name)
unsigned packing = type->interface_packing;
recursion(type, &name_copy, strlen(name), false, NULL, packing, false,
- record_array_count);
+ record_array_count, NULL);
ralloc_free(name_copy);
}
@@ -76,8 +76,6 @@ void
program_resource_visitor::process(ir_variable *var)
{
unsigned record_array_count = 1;
- const glsl_type *t = var->type;
- const glsl_type *t_without_array = var->type->without_array();
const bool row_major =
var->data.matrix_layout == GLSL_MATRIX_LAYOUT_ROW_MAJOR;
@@ -85,80 +83,28 @@ program_resource_visitor::process(ir_variable *var)
var->get_interface_type()->interface_packing :
var->type->interface_packing;
+ const glsl_type *t =
+ var->data.from_named_ifc_block ? var->get_interface_type() : var->type;
+ const glsl_type *t_without_array = t->without_array();
+
/* false is always passed for the row_major parameter to the other
* processing functions because no information is available to do
* otherwise. See the warning in linker.h.
*/
-
- /* Only strdup the name if we actually will need to modify it. */
- if (var->data.from_named_ifc_block_array) {
- /* lower_named_interface_blocks created this variable by lowering an
- * interface block array to an array variable. For example if the
- * original source code was:
- *
- * out Blk { vec4 bar } foo[3];
- *
- * Then the variable is now:
- *
- * out vec4 bar[3];
- *
- * We need to visit each array element using the names constructed like
- * so:
- *
- * Blk[0].bar
- * Blk[1].bar
- * Blk[2].bar
- */
- assert(t->is_array());
- const glsl_type *ifc_type = var->get_interface_type();
- char *name = ralloc_strdup(NULL, ifc_type->name);
- size_t name_length = strlen(name);
- for (unsigned i = 0; i < t->length; i++) {
- size_t new_length = name_length;
- ralloc_asprintf_rewrite_tail(&name, &new_length, "[%u].%s", i,
- var->name);
- /* Note: row_major is only meaningful for uniform blocks, and
- * lowering is only applied to non-uniform interface blocks, so we
- * can safely pass false for row_major.
- */
- recursion(var->type, &name, new_length, row_major, NULL, packing,
- false, record_array_count);
- }
- ralloc_free(name);
- } else if (var->data.from_named_ifc_block_nonarray) {
- /* lower_named_interface_blocks created this variable by lowering a
- * named interface block (non-array) to an ordinary variable. For
- * example if the original source code was:
- *
- * out Blk { vec4 bar } foo;
- *
- * Then the variable is now:
- *
- * out vec4 bar;
- *
- * We need to visit this variable using the name:
- *
- * Blk.bar
- */
- const glsl_type *ifc_type = var->get_interface_type();
- char *name = ralloc_asprintf(NULL, "%s.%s", ifc_type->name, var->name);
- /* Note: row_major is only meaningful for uniform blocks, and lowering
- * is only applied to non-uniform interface blocks, so we can safely
- * pass false for row_major.
- */
- recursion(var->type, &name, strlen(name), row_major, NULL, packing,
- false, record_array_count);
- ralloc_free(name);
- } else if (t_without_array->is_record() ||
+ if (t_without_array->is_record() ||
(t->is_array() && t->fields.array->is_array())) {
char *name = ralloc_strdup(NULL, var->name);
recursion(var->type, &name, strlen(name), row_major, NULL, packing,
- false, record_array_count);
+ false, record_array_count, NULL);
ralloc_free(name);
} else if (t_without_array->is_interface()) {
char *name = ralloc_strdup(NULL, t_without_array->name);
- recursion(var->type, &name, strlen(name), row_major, NULL, packing,
- false, record_array_count);
+ const glsl_struct_field *ifc_member = var->data.from_named_ifc_block ?
+ &t_without_array->
+ fields.structure[t_without_array->field_index(var->name)] : NULL;
+
+ recursion(t, &name, strlen(name), row_major, NULL, packing,
+ false, record_array_count, ifc_member);
ralloc_free(name);
} else {
this->set_record_array_count(record_array_count);
@@ -172,7 +118,8 @@ program_resource_visitor::recursion(const glsl_type *t, char **name,
const glsl_type *record_type,
const unsigned packing,
bool last_field,
- unsigned record_array_count)
+ unsigned record_array_count,
+ const glsl_struct_field *named_ifc_member)
{
/* Records need to have each field processed individually.
*
@@ -180,7 +127,12 @@ program_resource_visitor::recursion(const glsl_type *t, char **name,
* individually, then each field of the resulting array elements processed
* individually.
*/
- if (t->is_record() || t->is_interface()) {
+ if (t->is_interface() && named_ifc_member) {
+ ralloc_asprintf_rewrite_tail(name, &name_length, ".%s",
+ named_ifc_member->name);
+ recursion(named_ifc_member->type, name, name_length, row_major, NULL,
+ packing, false, record_array_count, NULL);
+ } else if (t->is_record() || t->is_interface()) {
if (record_type == NULL && t->is_record())
record_type = t;
@@ -223,7 +175,7 @@ program_resource_visitor::recursion(const glsl_type *t, char **name,
field_row_major,
record_type,
packing,
- (i + 1) == t->length, record_array_count);
+ (i + 1) == t->length, record_array_count, NULL);
/* Only the first leaf-field of the record gets called with the
* record type pointer.
@@ -258,7 +210,8 @@ program_resource_visitor::recursion(const glsl_type *t, char **name,
recursion(t->fields.array, name, new_length, row_major,
record_type,
packing,
- (i + 1) == t->length, record_array_count);
+ (i + 1) == t->length, record_array_count,
+ named_ifc_member);
/* Only the first leaf-field of the record gets called with the
* record type pointer.
@@ -799,7 +752,6 @@ private:
this->uniforms[id].name = ralloc_strdup(this->uniforms, name);
this->uniforms[id].type = base_type;
- this->uniforms[id].initialized = 0;
this->uniforms[id].num_driver_storage = 0;
this->uniforms[id].driver_storage = NULL;
this->uniforms[id].atomic_buffer_index = -1;
@@ -954,6 +906,8 @@ link_cross_validate_uniform_block(void *mem_ctx,
new_block->Uniforms,
sizeof(*linked_block->Uniforms) * linked_block->NumUniforms);
+ linked_block->Name = ralloc_strdup(*linked_blocks, linked_block->Name);
+
for (unsigned int i = 0; i < linked_block->NumUniforms; i++) {
struct gl_uniform_buffer_variable *ubo_var =
&linked_block->Uniforms[i];
@@ -1005,9 +959,9 @@ 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 *begin = shader->BufferInterfaceBlocks[i]->Uniforms[j].Name;
const char *end = strchr(begin, sentinel);
if (end == NULL)
@@ -1022,7 +976,7 @@ link_update_uniform_buffer_variables(struct gl_shader *shader)
break;
}
} else if (!strcmp(var->name,
- shader->BufferInterfaceBlocks[i].Uniforms[j].Name)) {
+ shader->BufferInterfaceBlocks[i]->Uniforms[j].Name)) {
found = true;
var->data.location = j;
break;
@@ -1148,9 +1102,9 @@ link_assign_uniform_locations(struct gl_shader_program *prog,
sh->num_combined_uniform_components = sh->num_uniform_components;
for (unsigned i = 0; i < sh->NumBufferInterfaceBlocks; i++) {
- if (!sh->BufferInterfaceBlocks[i].IsShaderStorage) {
+ if (!sh->BufferInterfaceBlocks[i]->IsShaderStorage) {
sh->num_combined_uniform_components +=
- sh->BufferInterfaceBlocks[i].UniformBufferSize / 4;
+ sh->BufferInterfaceBlocks[i]->UniformBufferSize / 4;
}
}
}
diff --git a/src/compiler/glsl/link_varyings.cpp b/src/compiler/glsl/link_varyings.cpp
index 44fc8f6..848668c 100644
--- a/src/compiler/glsl/link_varyings.cpp
+++ b/src/compiler/glsl/link_varyings.cpp
@@ -63,6 +63,125 @@ get_varying_type(const ir_variable *var, gl_shader_stage stage)
return type;
}
+static void
+create_xfb_varying_names(void *mem_ctx, const glsl_type *t, char **name,
+ size_t name_length, unsigned *count,
+ const char *ifc_member_name,
+ const glsl_type *ifc_member_t, char ***varying_names)
+{
+ if (t->is_interface()) {
+ size_t new_length = name_length;
+
+ assert(ifc_member_name && ifc_member_t);
+ ralloc_asprintf_rewrite_tail(name, &new_length, ".%s", ifc_member_name);
+
+ create_xfb_varying_names(mem_ctx, ifc_member_t, name, new_length, count,
+ NULL, NULL, varying_names);
+ } else if (t->is_record()) {
+ for (unsigned i = 0; i < t->length; i++) {
+ const char *field = t->fields.structure[i].name;
+ size_t new_length = name_length;
+
+ ralloc_asprintf_rewrite_tail(name, &new_length, ".%s", field);
+
+ create_xfb_varying_names(mem_ctx, t->fields.structure[i].type, name,
+ new_length, count, NULL, NULL,
+ varying_names);
+ }
+ } else if (t->without_array()->is_record() ||
+ t->without_array()->is_interface() ||
+ (t->is_array() && t->fields.array->is_array())) {
+ for (unsigned i = 0; i < t->length; i++) {
+ size_t new_length = name_length;
+
+ /* Append the subscript to the current variable name */
+ ralloc_asprintf_rewrite_tail(name, &new_length, "[%u]", i);
+
+ create_xfb_varying_names(mem_ctx, t->fields.array, name, new_length,
+ count, ifc_member_name, ifc_member_t,
+ varying_names);
+ }
+ } else {
+ (*varying_names)[(*count)++] = ralloc_strdup(mem_ctx, *name);
+ }
+}
+
+bool
+process_xfb_layout_qualifiers(void *mem_ctx, const gl_shader *sh,
+ unsigned *num_tfeedback_decls,
+ char ***varying_names)
+{
+ bool has_xfb_qualifiers = false;
+
+ /* We still need to enable transform feedback mode even if xfb_stride is
+ * only applied to a global out. Also we don't bother to propagate
+ * xfb_stride to interface block members so this will catch that case also.
+ */
+ for (unsigned j = 0; j < MAX_FEEDBACK_BUFFERS; j++) {
+ if (sh->TransformFeedback.BufferStride[j]) {
+ has_xfb_qualifiers = true;
+ }
+ }
+
+ foreach_in_list(ir_instruction, node, sh->ir) {
+ ir_variable *var = node->as_variable();
+ if (!var || var->data.mode != ir_var_shader_out)
+ continue;
+
+ /* From the ARB_enhanced_layouts spec:
+ *
+ * "Any shader making any static use (after preprocessing) of any of
+ * these *xfb_* qualifiers will cause the shader to be in a
+ * transform feedback capturing mode and hence responsible for
+ * describing the transform feedback setup. This mode will capture
+ * any output selected by *xfb_offset*, directly or indirectly, to
+ * a transform feedback buffer."
+ */
+ if (var->data.explicit_xfb_buffer || var->data.explicit_xfb_stride) {
+ has_xfb_qualifiers = true;
+ }
+
+ if (var->data.explicit_xfb_offset) {
+ *num_tfeedback_decls += var->type->varying_count();
+ has_xfb_qualifiers = true;
+ }
+ }
+
+ if (*num_tfeedback_decls == 0)
+ return has_xfb_qualifiers;
+
+ unsigned i = 0;
+ *varying_names = ralloc_array(mem_ctx, char *, *num_tfeedback_decls);
+ foreach_in_list(ir_instruction, node, sh->ir) {
+ ir_variable *var = node->as_variable();
+ if (!var || var->data.mode != ir_var_shader_out)
+ continue;
+
+ if (var->data.explicit_xfb_offset) {
+ char *name;
+ const glsl_type *type, *member_type;
+
+ if (var->data.from_named_ifc_block) {
+ type = var->get_interface_type();
+ /* Find the member type before it was altered by lowering */
+ member_type =
+ type->fields.structure[type->field_index(var->name)].type;
+ name = ralloc_strdup(NULL, type->without_array()->name);
+ } else {
+ type = var->type;
+ member_type = NULL;
+ name = ralloc_strdup(NULL, var->name);
+ }
+ create_xfb_varying_names(mem_ctx, type, &name, strlen(name), &i,
+ var->name, member_type, varying_names);
+ ralloc_free(name);
+ }
+ }
+
+ assert(i == *num_tfeedback_decls);
+ return has_xfb_qualifiers;
+}
+
/**
* Validate the types and qualifiers of an output from one stage against the
* matching input to another stage.
@@ -397,6 +516,8 @@ tfeedback_decl::init(struct gl_context *ctx, const void *mem_ctx,
this->next_buffer_separator = false;
this->matched_candidate = NULL;
this->stream_id = 0;
+ this->buffer = 0;
+ this->offset = 0;
if (ctx->Extensions.ARB_transform_feedback3) {
/* Parse gl_NextBuffer. */
@@ -489,6 +610,8 @@ tfeedback_decl::assign_location(struct gl_context *ctx,
= this->matched_candidate->toplevel_var->data.location * 4
+ this->matched_candidate->toplevel_var->data.location_frac
+ this->matched_candidate->offset;
+ const unsigned dmul =
+ this->matched_candidate->type->without_array()->is_double() ? 2 : 1;
if (this->matched_candidate->type->is_array()) {
/* Array variable */
@@ -496,8 +619,6 @@ tfeedback_decl::assign_location(struct gl_context *ctx,
this->matched_candidate->type->fields.array->matrix_columns;
const unsigned vector_elements =
this->matched_candidate->type->fields.array->vector_elements;
- const unsigned dmul =
- this->matched_candidate->type->fields.array->is_double() ? 2 : 1;
unsigned actual_array_size;
switch (this->lowered_builtin_array_variable) {
case clip_distance:
@@ -575,6 +696,12 @@ tfeedback_decl::assign_location(struct gl_context *ctx,
*/
this->stream_id = this->matched_candidate->toplevel_var->data.stream;
+ unsigned array_offset = this->array_subscript * 4 * dmul;
+ unsigned struct_offset = this->matched_candidate->offset * 4 * dmul;
+ this->buffer = this->matched_candidate->toplevel_var->data.xfb_buffer;
+ this->offset = this->matched_candidate->toplevel_var->data.offset +
+ array_offset + struct_offset;
+
return true;
}
@@ -598,55 +725,108 @@ tfeedback_decl::get_num_outputs() const
bool
tfeedback_decl::store(struct gl_context *ctx, struct gl_shader_program *prog,
struct gl_transform_feedback_info *info,
- unsigned buffer, const unsigned max_outputs) const
+ unsigned buffer, unsigned buffer_index,
+ const unsigned max_outputs, bool *explicit_stride,
+ bool has_xfb_qualifiers) const
{
assert(!this->next_buffer_separator);
/* Handle gl_SkipComponents. */
if (this->skip_components) {
- info->BufferStride[buffer] += this->skip_components;
+ info->Buffers[buffer].Stride += this->skip_components;
return true;
}
+ unsigned xfb_offset = 0;
+ if (has_xfb_qualifiers) {
+ xfb_offset = this->offset / 4;
+ } else {
+ xfb_offset = info->Buffers[buffer].Stride;
+ }
+ info->Varyings[info->NumVarying].Offset = xfb_offset * 4;
+
+ unsigned location = this->location;
+ unsigned location_frac = this->location_frac;
+ unsigned num_components = this->num_components();
+ while (num_components > 0) {
+ unsigned output_size = MIN2(num_components, 4 - location_frac);
+ assert((info->NumOutputs == 0 && max_outputs == 0) ||
+ info->NumOutputs < max_outputs);
+
+ /* From the ARB_enhanced_layouts spec:
+ *
+ * "If such a block member or variable is not written during a shader
+ * invocation, the buffer contents at the assigned offset will be
+ * undefined. Even if there are no static writes to a variable or
+ * member that is assigned a transform feedback offset, the space is
+ * still allocated in the buffer and still affects the stride."
+ */
+ if (this->is_varying_written()) {
+ info->Outputs[info->NumOutputs].ComponentOffset = location_frac;
+ info->Outputs[info->NumOutputs].OutputRegister = location;
+ info->Outputs[info->NumOutputs].NumComponents = output_size;
+ info->Outputs[info->NumOutputs].StreamId = stream_id;
+ info->Outputs[info->NumOutputs].OutputBuffer = buffer;
+ info->Outputs[info->NumOutputs].DstOffset = xfb_offset;
+ ++info->NumOutputs;
+ }
+ info->Buffers[buffer].Stream = this->stream_id;
+ xfb_offset += output_size;
+
+ num_components -= output_size;
+ location++;
+ location_frac = 0;
+ }
+
+ if (explicit_stride && explicit_stride[buffer]) {
+ if (this->is_double() && info->Buffers[buffer].Stride % 2) {
+ linker_error(prog, "invalid qualifier xfb_stride=%d must be a "
+ "multiple of 8 as its applied to a type that is or "
+ "contains a double.",
+ info->Buffers[buffer].Stride * 4);
+ return false;
+ }
+
+ if ((this->offset / 4) / info->Buffers[buffer].Stride !=
+ (xfb_offset - 1) / info->Buffers[buffer].Stride) {
+ linker_error(prog, "xfb_offset (%d) overflows xfb_stride (%d) for "
+ "buffer (%d)", xfb_offset * 4,
+ info->Buffers[buffer].Stride * 4, buffer);
+ return false;
+ }
+ } else {
+ info->Buffers[buffer].Stride = xfb_offset;
+ }
+
/* From GL_EXT_transform_feedback:
* A program will fail to link if:
*
* * the total number of components to capture is greater than
* the constant MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_EXT
* and the buffer mode is INTERLEAVED_ATTRIBS_EXT.
+ *
+ * From GL_ARB_enhanced_layouts:
+ *
+ * "The resulting stride (implicit or explicit) must be less than or
+ * equal to the implementation-dependent constant
+ * gl_MaxTransformFeedbackInterleavedComponents."
*/
- if (prog->TransformFeedback.BufferMode == GL_INTERLEAVED_ATTRIBS &&
- info->BufferStride[buffer] + this->num_components() >
+ if ((prog->TransformFeedback.BufferMode == GL_INTERLEAVED_ATTRIBS ||
+ has_xfb_qualifiers) &&
+ info->Buffers[buffer].Stride >
ctx->Const.MaxTransformFeedbackInterleavedComponents) {
linker_error(prog, "The MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS "
"limit has been exceeded.");
return false;
}
- unsigned location = this->location;
- unsigned location_frac = this->location_frac;
- unsigned num_components = this->num_components();
- while (num_components > 0) {
- unsigned output_size = MIN2(num_components, 4 - location_frac);
- assert(info->NumOutputs < max_outputs);
- info->Outputs[info->NumOutputs].ComponentOffset = location_frac;
- info->Outputs[info->NumOutputs].OutputRegister = location;
- info->Outputs[info->NumOutputs].NumComponents = output_size;
- info->Outputs[info->NumOutputs].StreamId = stream_id;
- info->Outputs[info->NumOutputs].OutputBuffer = buffer;
- info->Outputs[info->NumOutputs].DstOffset = info->BufferStride[buffer];
- ++info->NumOutputs;
- info->BufferStride[buffer] += output_size;
- info->BufferStream[buffer] = this->stream_id;
- num_components -= output_size;
- location++;
- location_frac = 0;
- }
-
- info->Varyings[info->NumVarying].Name = ralloc_strdup(prog, this->orig_name);
+ info->Varyings[info->NumVarying].Name = ralloc_strdup(prog,
+ this->orig_name);
info->Varyings[info->NumVarying].Type = this->type;
info->Varyings[info->NumVarying].Size = this->size;
+ info->Varyings[info->NumVarying].BufferIndex = buffer_index;
info->NumVarying++;
+ info->Buffers[buffer].NumVaryings++;
return true;
}
@@ -731,6 +911,17 @@ parse_tfeedback_decls(struct gl_context *ctx, struct gl_shader_program *prog,
}
+static int
+cmp_xfb_offset(const void * x_generic, const void * y_generic)
+{
+ tfeedback_decl *x = (tfeedback_decl *) x_generic;
+ tfeedback_decl *y = (tfeedback_decl *) y_generic;
+
+ if (x->get_buffer() != y->get_buffer())
+ return x->get_buffer() - y->get_buffer();
+ return x->get_offset() - y->get_offset();
+}
+
/**
* Store transform feedback location assignments into
* prog->LinkedTransformFeedback based on the data stored in tfeedback_decls.
@@ -741,8 +932,13 @@ parse_tfeedback_decls(struct gl_context *ctx, struct gl_shader_program *prog,
bool
store_tfeedback_info(struct gl_context *ctx, struct gl_shader_program *prog,
unsigned num_tfeedback_decls,
- tfeedback_decl *tfeedback_decls)
+ tfeedback_decl *tfeedback_decls, bool has_xfb_qualifiers)
{
+ /* Make sure MaxTransformFeedbackBuffers is less than 32 so the bitmask for
+ * tracking the number of buffers doesn't overflow.
+ */
+ assert(ctx->Const.MaxTransformFeedbackBuffers < 32);
+
bool separate_attribs_mode =
prog->TransformFeedback.BufferMode == GL_SEPARATE_ATTRIBS;
@@ -752,14 +948,24 @@ store_tfeedback_info(struct gl_context *ctx, struct gl_shader_program *prog,
memset(&prog->LinkedTransformFeedback, 0,
sizeof(prog->LinkedTransformFeedback));
+ /* The xfb_offset qualifier does not have to be used in increasing order
+ * however some drivers expect to receive the list of transform feedback
+ * declarations in order so sort it now for convenience.
+ */
+ if (has_xfb_qualifiers)
+ qsort(tfeedback_decls, num_tfeedback_decls, sizeof(*tfeedback_decls),
+ cmp_xfb_offset);
+
prog->LinkedTransformFeedback.Varyings =
rzalloc_array(prog,
struct gl_transform_feedback_varying_info,
num_tfeedback_decls);
unsigned num_outputs = 0;
- for (unsigned i = 0; i < num_tfeedback_decls; ++i)
- num_outputs += tfeedback_decls[i].get_num_outputs();
+ for (unsigned i = 0; i < num_tfeedback_decls; ++i) {
+ if (tfeedback_decls[i].is_varying_written())
+ num_outputs += tfeedback_decls[i].get_num_outputs();
+ }
prog->LinkedTransformFeedback.Outputs =
rzalloc_array(prog,
@@ -767,21 +973,47 @@ store_tfeedback_info(struct gl_context *ctx, struct gl_shader_program *prog,
num_outputs);
unsigned num_buffers = 0;
+ unsigned buffers = 0;
- if (separate_attribs_mode) {
+ if (!has_xfb_qualifiers && separate_attribs_mode) {
/* GL_SEPARATE_ATTRIBS */
for (unsigned i = 0; i < num_tfeedback_decls; ++i) {
if (!tfeedback_decls[i].store(ctx, prog, &prog->LinkedTransformFeedback,
- num_buffers, num_outputs))
+ num_buffers, num_buffers, num_outputs,
+ NULL, has_xfb_qualifiers))
return false;
+ buffers |= 1 << num_buffers;
num_buffers++;
}
}
else {
/* GL_INVERLEAVED_ATTRIBS */
int buffer_stream_id = -1;
+ unsigned buffer =
+ num_tfeedback_decls ? tfeedback_decls[0].get_buffer() : 0;
+ bool explicit_stride[MAX_FEEDBACK_BUFFERS] = { false };
+
+ /* Apply any xfb_stride global qualifiers */
+ if (has_xfb_qualifiers) {
+ for (unsigned j = 0; j < MAX_FEEDBACK_BUFFERS; j++) {
+ if (prog->TransformFeedback.BufferStride[j]) {
+ buffers |= 1 << j;
+ explicit_stride[j] = true;
+ prog->LinkedTransformFeedback.Buffers[j].Stride =
+ prog->TransformFeedback.BufferStride[j] / 4;
+ }
+ }
+ }
+
for (unsigned i = 0; i < num_tfeedback_decls; ++i) {
+ if (has_xfb_qualifiers &&
+ buffer != tfeedback_decls[i].get_buffer()) {
+ /* we have moved to the next buffer so reset stream id */
+ buffer_stream_id = -1;
+ num_buffers++;
+ }
+
if (tfeedback_decls[i].is_next_buffer_separator()) {
num_buffers++;
buffer_stream_id = -1;
@@ -803,17 +1035,24 @@ store_tfeedback_info(struct gl_context *ctx, struct gl_shader_program *prog,
return false;
}
+ if (has_xfb_qualifiers) {
+ buffer = tfeedback_decls[i].get_buffer();
+ } else {
+ buffer = num_buffers;
+ }
+ buffers |= 1 << buffer;
+
if (!tfeedback_decls[i].store(ctx, prog,
&prog->LinkedTransformFeedback,
- num_buffers, num_outputs))
+ buffer, num_buffers, num_outputs,
+ explicit_stride, has_xfb_qualifiers))
return false;
}
- num_buffers++;
}
assert(prog->LinkedTransformFeedback.NumOutputs == num_outputs);
- prog->LinkedTransformFeedback.NumBuffers = num_buffers;
+ prog->LinkedTransformFeedback.ActiveBuffers = buffers;
return true;
}
@@ -1466,8 +1705,8 @@ populate_consumer_input_sets(void *mem_ctx, exec_list *ir,
} else if (input_var->get_interface_type() != NULL) {
char *const iface_field_name =
ralloc_asprintf(mem_ctx, "%s.%s",
- input_var->get_interface_type()->name,
- input_var->name);
+ input_var->get_interface_type()->without_array()->name,
+ input_var->name);
hash_table_insert(consumer_interface_inputs, input_var,
iface_field_name);
} else {
@@ -1498,8 +1737,8 @@ get_matching_input(void *mem_ctx,
} else if (output_var->get_interface_type() != NULL) {
char *const iface_field_name =
ralloc_asprintf(mem_ctx, "%s.%s",
- output_var->get_interface_type()->name,
- output_var->name);
+ output_var->get_interface_type()->without_array()->name,
+ output_var->name);
input_var =
(ir_variable *) hash_table_find(consumer_interface_inputs,
iface_field_name);
diff --git a/src/compiler/glsl/link_varyings.h b/src/compiler/glsl/link_varyings.h
index b2812614..543b80f 100644
--- a/src/compiler/glsl/link_varyings.h
+++ b/src/compiler/glsl/link_varyings.h
@@ -98,7 +98,8 @@ public:
unsigned get_num_outputs() const;
bool store(struct gl_context *ctx, struct gl_shader_program *prog,
struct gl_transform_feedback_info *info, unsigned buffer,
- const unsigned max_outputs) const;
+ unsigned buffer_index, const unsigned max_outputs,
+ bool *explicit_stride, bool has_xfb_qualifiers) const;
const tfeedback_candidate *find_candidate(gl_shader_program *prog,
hash_table *tfeedback_candidates);
@@ -107,6 +108,14 @@ public:
return this->next_buffer_separator;
}
+ bool is_varying_written() const
+ {
+ if (this->next_buffer_separator || this->skip_components)
+ return false;
+
+ return this->matched_candidate->toplevel_var->data.assigned;
+ }
+
bool is_varying() const
{
return !this->next_buffer_separator && !this->skip_components;
@@ -122,6 +131,16 @@ public:
return this->stream_id;
}
+ unsigned get_buffer() const
+ {
+ return this->buffer;
+ }
+
+ unsigned get_offset() const
+ {
+ return this->offset;
+ }
+
/**
* The total number of varying components taken up by this variable. Only
* valid if assign_location() has been called.
@@ -202,6 +221,16 @@ private:
int location;
/**
+ * Used to store the buffer assigned by xfb_buffer.
+ */
+ unsigned buffer;
+
+ /**
+ * Used to store the offset assigned by xfb_offset.
+ */
+ unsigned offset;
+
+ /**
* If non-zero, then this variable may be packed along with other variables
* into a single varying slot, so this offset should be applied when
* accessing components. For example, an offset of 1 means that the x
@@ -268,6 +297,11 @@ parse_tfeedback_decls(struct gl_context *ctx, struct gl_shader_program *prog,
const void *mem_ctx, unsigned num_names,
char **varying_names, tfeedback_decl *decls);
+bool
+process_xfb_layout_qualifiers(void *mem_ctx, const gl_shader *sh,
+ unsigned *num_tfeedback_decls,
+ char ***varying_names);
+
void
remove_unused_shader_inputs_and_outputs(bool is_separate_shader_object,
gl_shader *sh,
@@ -276,7 +310,8 @@ remove_unused_shader_inputs_and_outputs(bool is_separate_shader_object,
bool
store_tfeedback_info(struct gl_context *ctx, struct gl_shader_program *prog,
unsigned num_tfeedback_decls,
- tfeedback_decl *tfeedback_decls);
+ tfeedback_decl *tfeedback_decls,
+ bool has_xfb_qualifiers);
bool
assign_varying_locations(struct gl_context *ctx,
diff --git a/src/compiler/glsl/linker.cpp b/src/compiler/glsl/linker.cpp
index 76b700d..510a22e 100644
--- a/src/compiler/glsl/linker.cpp
+++ b/src/compiler/glsl/linker.cpp
@@ -1192,11 +1192,11 @@ interstage_cross_validate_uniform_blocks(struct gl_shader_program *prog)
int index = link_cross_validate_uniform_block(prog,
&prog->BufferInterfaceBlocks,
&prog->NumBufferInterfaceBlocks,
- &sh->BufferInterfaceBlocks[j]);
+ sh->BufferInterfaceBlocks[j]);
if (index == -1) {
linker_error(prog, "uniform block `%s' has mismatching definitions\n",
- sh->BufferInterfaceBlocks[j].Name);
+ sh->BufferInterfaceBlocks[j]->Name);
return false;
}
@@ -1204,6 +1204,23 @@ interstage_cross_validate_uniform_blocks(struct gl_shader_program *prog)
}
}
+ /* Update per stage block pointers to point to the program list.
+ * FIXME: We should be able to free the per stage blocks here.
+ */
+ for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
+ for (unsigned j = 0; j < prog->NumBufferInterfaceBlocks; j++) {
+ int stage_index =
+ prog->InterfaceBlockStageIndex[i][j];
+
+ if (stage_index != -1) {
+ struct gl_shader *sh = prog->_LinkedShaders[i];
+
+ sh->BufferInterfaceBlocks[stage_index] =
+ &prog->BufferInterfaceBlocks[j];
+ }
+ }
+ }
+
return true;
}
@@ -1567,6 +1584,69 @@ private:
hash_table *unnamed_interfaces;
};
+/**
+ * Check for conflicting xfb_stride default qualifiers and store buffer stride
+ * for later use.
+ */
+static void
+link_xfb_stride_layout_qualifiers(struct gl_context *ctx,
+ struct gl_shader_program *prog,
+ struct gl_shader *linked_shader,
+ struct gl_shader **shader_list,
+ unsigned num_shaders)
+{
+ for (unsigned i = 0; i < MAX_FEEDBACK_BUFFERS; i++) {
+ linked_shader->TransformFeedback.BufferStride[i] = 0;
+ }
+
+ for (unsigned i = 0; i < num_shaders; i++) {
+ struct gl_shader *shader = shader_list[i];
+
+ for (unsigned j = 0; j < MAX_FEEDBACK_BUFFERS; j++) {
+ if (shader->TransformFeedback.BufferStride[j]) {
+ if (linked_shader->TransformFeedback.BufferStride[j] != 0 &&
+ shader->TransformFeedback.BufferStride[j] != 0 &&
+ linked_shader->TransformFeedback.BufferStride[j] !=
+ shader->TransformFeedback.BufferStride[j]) {
+ linker_error(prog,
+ "intrastage shaders defined with conflicting "
+ "xfb_stride for buffer %d (%d and %d)\n", j,
+ linked_shader->TransformFeedback.BufferStride[j],
+ shader->TransformFeedback.BufferStride[j]);
+ return;
+ }
+
+ if (shader->TransformFeedback.BufferStride[j])
+ linked_shader->TransformFeedback.BufferStride[j] =
+ shader->TransformFeedback.BufferStride[j];
+ }
+ }
+ }
+
+ for (unsigned j = 0; j < MAX_FEEDBACK_BUFFERS; j++) {
+ if (linked_shader->TransformFeedback.BufferStride[j]) {
+ prog->TransformFeedback.BufferStride[j] =
+ linked_shader->TransformFeedback.BufferStride[j];
+
+ /* We will validate doubles at a later stage */
+ if (prog->TransformFeedback.BufferStride[j] % 4) {
+ linker_error(prog, "invalid qualifier xfb_stride=%d must be a "
+ "multiple of 4 or if its applied to a type that is "
+ "or contains a double a multiple of 8.",
+ prog->TransformFeedback.BufferStride[j]);
+ return;
+ }
+
+ if (prog->TransformFeedback.BufferStride[j] / 4 >
+ ctx->Const.MaxTransformFeedbackInterleavedComponents) {
+ linker_error(prog,
+ "The MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS "
+ "limit has been exceeded.");
+ return;
+ }
+ }
+ }
+}
/**
* Performs the cross-validation of tessellation control shader vertices and
@@ -2069,15 +2149,23 @@ link_intrastage_shaders(void *mem_ctx,
linked->ir = new(linked) exec_list;
clone_ir_list(mem_ctx, linked->ir, main->ir);
- linked->BufferInterfaceBlocks = uniform_blocks;
+ linked->BufferInterfaceBlocks =
+ ralloc_array(linked, gl_uniform_block *, num_uniform_blocks);
+
+ ralloc_steal(linked, uniform_blocks);
+ for (unsigned i = 0; i < num_uniform_blocks; i++) {
+ linked->BufferInterfaceBlocks[i] = &uniform_blocks[i];
+ }
+
linked->NumBufferInterfaceBlocks = num_uniform_blocks;
- ralloc_steal(linked, linked->BufferInterfaceBlocks);
link_fs_input_layout_qualifiers(prog, linked, shader_list, num_shaders);
link_tcs_out_layout_qualifiers(prog, linked, shader_list, num_shaders);
link_tes_in_layout_qualifiers(prog, linked, shader_list, num_shaders);
link_gs_inout_layout_qualifiers(prog, linked, shader_list, num_shaders);
link_cs_input_layout_qualifiers(prog, linked, shader_list, num_shaders);
+ link_xfb_stride_layout_qualifiers(ctx, prog, linked, shader_list,
+ num_shaders);
populate_symbol_table(linked);
@@ -2869,7 +2957,8 @@ check_resources(struct gl_context *ctx, struct gl_shader_program *prog)
if (prog->InterfaceBlockStageIndex[j][i] != -1) {
struct gl_shader *sh = prog->_LinkedShaders[j];
int stage_index = prog->InterfaceBlockStageIndex[j][i];
- if (sh && sh->BufferInterfaceBlocks[stage_index].IsShaderStorage) {
+ if (sh &&
+ sh->BufferInterfaceBlocks[stage_index]->IsShaderStorage) {
shader_blocks[j]++;
total_shader_storage_blocks++;
} else {
@@ -2986,7 +3075,8 @@ check_image_resources(struct gl_context *ctx, struct gl_shader_program *prog)
for (unsigned j = 0; j < prog->NumBufferInterfaceBlocks; j++) {
int stage_index = prog->InterfaceBlockStageIndex[i][j];
- if (stage_index != -1 && sh->BufferInterfaceBlocks[stage_index].IsShaderStorage)
+ if (stage_index != -1 &&
+ sh->BufferInterfaceBlocks[stage_index]->IsShaderStorage)
total_shader_storage_blocks++;
}
@@ -3762,7 +3852,8 @@ write_top_level_array_size_and_stride:
* resource data.
*/
void
-build_program_resource_list(struct gl_shader_program *shProg)
+build_program_resource_list(struct gl_context *ctx,
+ struct gl_shader_program *shProg)
{
/* Rebuild resource list. */
if (shProg->ProgramResourceList) {
@@ -3820,6 +3911,17 @@ build_program_resource_list(struct gl_shader_program *shProg)
}
}
+ /* Add transform feedback buffers. */
+ for (unsigned i = 0; i < ctx->Const.MaxTransformFeedbackBuffers; i++) {
+ if ((shProg->LinkedTransformFeedback.ActiveBuffers >> i) & 1) {
+ shProg->LinkedTransformFeedback.Buffers[i].Binding = i;
+ if (!add_program_resource(shProg, GL_TRANSFORM_FEEDBACK_BUFFER,
+ &shProg->LinkedTransformFeedback.Buffers[i],
+ 0))
+ return;
+ }
+ }
+
/* Add uniforms from uniform storage. */
for (unsigned i = 0; i < shProg->NumUniformStorage; i++) {
/* Do not add uniforms internally used by Mesa. */
@@ -4006,20 +4108,22 @@ link_assign_subroutine_types(struct gl_shader_program *prog)
static void
split_ubos_and_ssbos(void *mem_ctx,
- struct gl_uniform_block *blocks,
+ struct gl_uniform_block **s_blks,
+ struct gl_uniform_block *p_blks,
unsigned num_blocks,
struct gl_uniform_block ***ubos,
unsigned *num_ubos,
- unsigned **ubo_interface_block_indices,
struct gl_uniform_block ***ssbos,
- unsigned *num_ssbos,
- unsigned **ssbo_interface_block_indices)
+ unsigned *num_ssbos)
{
unsigned num_ubo_blocks = 0;
unsigned num_ssbo_blocks = 0;
+ /* Are we spliting the list of blocks for the shader or the program */
+ bool is_shader = p_blks == NULL;
+
for (unsigned i = 0; i < num_blocks; i++) {
- if (blocks[i].IsShaderStorage)
+ if (is_shader ? s_blks[i]->IsShaderStorage : p_blks[i].IsShaderStorage)
num_ssbo_blocks++;
else
num_ubo_blocks++;
@@ -4031,24 +4135,13 @@ split_ubos_and_ssbos(void *mem_ctx,
*ssbos = ralloc_array(mem_ctx, gl_uniform_block *, num_ssbo_blocks);
*num_ssbos = 0;
- if (ubo_interface_block_indices)
- *ubo_interface_block_indices =
- ralloc_array(mem_ctx, unsigned, num_ubo_blocks);
-
- if (ssbo_interface_block_indices)
- *ssbo_interface_block_indices =
- ralloc_array(mem_ctx, unsigned, num_ssbo_blocks);
-
for (unsigned i = 0; i < num_blocks; i++) {
- if (blocks[i].IsShaderStorage) {
- (*ssbos)[*num_ssbos] = &blocks[i];
- if (ssbo_interface_block_indices)
- (*ssbo_interface_block_indices)[*num_ssbos] = i;
+ struct gl_uniform_block *blk = is_shader ? s_blks[i] : &p_blks[i];
+ if (blk->IsShaderStorage) {
+ (*ssbos)[*num_ssbos] = blk;
(*num_ssbos)++;
} else {
- (*ubos)[*num_ubos] = &blocks[i];
- if (ubo_interface_block_indices)
- (*ubo_interface_block_indices)[*num_ubos] = i;
+ (*ubos)[*num_ubos] = blk;
(*num_ubos)++;
}
}
@@ -4153,9 +4246,11 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
return;
}
- tfeedback_decl *tfeedback_decls = NULL;
- unsigned num_tfeedback_decls = prog->TransformFeedback.NumVarying;
+ unsigned num_tfeedback_decls = 0;
unsigned int num_explicit_uniform_locs = 0;
+ bool has_xfb_qualifiers = false;
+ char **varying_names = NULL;
+ tfeedback_decl *tfeedback_decls = NULL;
void *mem_ctx = ralloc_context(NULL); // temporary linker context
@@ -4465,6 +4560,30 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
goto done;
}
+ /* From the ARB_enhanced_layouts spec:
+ *
+ * "If the shader used to record output variables for transform feedback
+ * varyings uses the "xfb_buffer", "xfb_offset", or "xfb_stride" layout
+ * qualifiers, the values specified by TransformFeedbackVaryings are
+ * ignored, and the set of variables captured for transform feedback is
+ * instead derived from the specified layout qualifiers."
+ */
+ for (int i = MESA_SHADER_FRAGMENT - 1; i >= 0; i--) {
+ /* Find last stage before fragment shader */
+ if (prog->_LinkedShaders[i]) {
+ has_xfb_qualifiers =
+ process_xfb_layout_qualifiers(mem_ctx, prog->_LinkedShaders[i],
+ &num_tfeedback_decls,
+ &varying_names);
+ break;
+ }
+ }
+
+ if (!has_xfb_qualifiers) {
+ num_tfeedback_decls = prog->TransformFeedback.NumVarying;
+ varying_names = prog->TransformFeedback.VaryingNames;
+ }
+
if (num_tfeedback_decls != 0) {
/* From GL_EXT_transform_feedback:
* A program will fail to link if:
@@ -4481,10 +4600,9 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
}
tfeedback_decls = ralloc_array(mem_ctx, tfeedback_decl,
- prog->TransformFeedback.NumVarying);
+ num_tfeedback_decls);
if (!parse_tfeedback_decls(ctx, prog, mem_ctx, num_tfeedback_decls,
- prog->TransformFeedback.VaryingNames,
- tfeedback_decls))
+ varying_names, tfeedback_decls))
goto done;
}
@@ -4564,7 +4682,8 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
}
}
- if (!store_tfeedback_info(ctx, prog, num_tfeedback_decls, tfeedback_decls))
+ if (!store_tfeedback_info(ctx, prog, num_tfeedback_decls, tfeedback_decls,
+ has_xfb_qualifiers))
goto done;
update_array_sizes(prog);
@@ -4627,25 +4746,23 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
gl_shader *sh = prog->_LinkedShaders[i];
split_ubos_and_ssbos(sh,
sh->BufferInterfaceBlocks,
+ NULL,
sh->NumBufferInterfaceBlocks,
&sh->UniformBlocks,
&sh->NumUniformBlocks,
- NULL,
&sh->ShaderStorageBlocks,
- &sh->NumShaderStorageBlocks,
- NULL);
+ &sh->NumShaderStorageBlocks);
}
}
split_ubos_and_ssbos(prog,
+ NULL,
prog->BufferInterfaceBlocks,
prog->NumBufferInterfaceBlocks,
&prog->UniformBlocks,
&prog->NumUniformBlocks,
- &prog->UboInterfaceBlockIndex,
&prog->ShaderStorageBlocks,
- &prog->NumShaderStorageBlocks,
- &prog->SsboInterfaceBlockIndex);
+ &prog->NumShaderStorageBlocks);
for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
if (prog->_LinkedShaders[i] == NULL)
diff --git a/src/compiler/glsl/linker.h b/src/compiler/glsl/linker.h
index 4311d16..97144df 100644
--- a/src/compiler/glsl/linker.h
+++ b/src/compiler/glsl/linker.h
@@ -197,7 +197,8 @@ private:
void recursion(const glsl_type *t, char **name, size_t name_length,
bool row_major, const glsl_type *record_type,
const unsigned packing,
- bool last_field, unsigned record_array_count);
+ bool last_field, unsigned record_array_count,
+ const glsl_struct_field *named_ifc_member);
};
void
diff --git a/src/compiler/glsl/lower_named_interface_blocks.cpp b/src/compiler/glsl/lower_named_interface_blocks.cpp
index f29eba4..f780eca 100644
--- a/src/compiler/glsl/lower_named_interface_blocks.cpp
+++ b/src/compiler/glsl/lower_named_interface_blocks.cpp
@@ -169,7 +169,6 @@ flatten_named_interface_blocks_declarations::run(exec_list *instructions)
new(mem_ctx) ir_variable(iface_t->fields.structure[i].type,
var_name,
(ir_variable_mode) var->data.mode);
- new_var->data.from_named_ifc_block_nonarray = 1;
} else {
const glsl_type *new_array_type =
process_array_type(var->type, i);
@@ -177,10 +176,16 @@ flatten_named_interface_blocks_declarations::run(exec_list *instructions)
new(mem_ctx) ir_variable(new_array_type,
var_name,
(ir_variable_mode) var->data.mode);
- new_var->data.from_named_ifc_block_array = 1;
}
new_var->data.location = iface_t->fields.structure[i].location;
new_var->data.explicit_location = (new_var->data.location >= 0);
+ new_var->data.offset = iface_t->fields.structure[i].offset;
+ new_var->data.explicit_xfb_offset =
+ (iface_t->fields.structure[i].offset >= 0);
+ new_var->data.xfb_buffer =
+ iface_t->fields.structure[i].xfb_buffer;
+ new_var->data.explicit_xfb_buffer =
+ iface_t->fields.structure[i].explicit_xfb_buffer;
new_var->data.interpolation =
iface_t->fields.structure[i].interpolation;
new_var->data.centroid = iface_t->fields.structure[i].centroid;
@@ -188,8 +193,9 @@ flatten_named_interface_blocks_declarations::run(exec_list *instructions)
new_var->data.patch = iface_t->fields.structure[i].patch;
new_var->data.stream = var->data.stream;
new_var->data.how_declared = var->data.how_declared;
+ new_var->data.from_named_ifc_block = 1;
- new_var->init_interface_type(iface_t);
+ new_var->init_interface_type(var->type);
hash_table_insert(interface_namespace, new_var,
iface_field_name);
insert_pos->insert_after(new_var);
@@ -211,12 +217,23 @@ ir_visitor_status
flatten_named_interface_blocks_declarations::visit_leave(ir_assignment *ir)
{
ir_dereference_record *lhs_rec = ir->lhs->as_dereference_record();
+
+ ir_variable *lhs_var = ir->lhs->variable_referenced();
+ if (lhs_var && lhs_var->get_interface_type()) {
+ lhs_var->data.assigned = 1;
+ }
+
if (lhs_rec) {
ir_rvalue *lhs_rec_tmp = lhs_rec;
handle_rvalue(&lhs_rec_tmp);
if (lhs_rec_tmp != lhs_rec) {
ir->set_lhs(lhs_rec_tmp);
}
+
+ ir_variable *lhs_var = lhs_rec_tmp->variable_referenced();
+ if (lhs_var) {
+ lhs_var->data.assigned = 1;
+ }
}
return rvalue_visit(ir);
}
diff --git a/src/compiler/glsl/program.h b/src/compiler/glsl/program.h
index 31bb9aa..8f5a31b 100644
--- a/src/compiler/glsl/program.h
+++ b/src/compiler/glsl/program.h
@@ -43,7 +43,8 @@ extern void
link_shaders(struct gl_context *ctx, struct gl_shader_program *prog);
extern void
-build_program_resource_list(struct gl_shader_program *shProg);
+build_program_resource_list(struct gl_context *ctx,
+ struct gl_shader_program *shProg);
extern void
linker_error(struct gl_shader_program *prog, const char *fmt, ...)
diff --git a/src/compiler/glsl/standalone_scaffolding.cpp b/src/compiler/glsl/standalone_scaffolding.cpp
index 0f7a16a..5ce804e 100644
--- a/src/compiler/glsl/standalone_scaffolding.cpp
+++ b/src/compiler/glsl/standalone_scaffolding.cpp
@@ -130,11 +130,6 @@ _mesa_clear_shader_program_data(struct gl_shader_program *shProg)
shProg->InterfaceBlockStageIndex[i] = NULL;
}
- ralloc_free(shProg->UboInterfaceBlockIndex);
- shProg->UboInterfaceBlockIndex = NULL;
- ralloc_free(shProg->SsboInterfaceBlockIndex);
- shProg->SsboInterfaceBlockIndex = NULL;
-
ralloc_free(shProg->AtomicBuffers);
shProg->AtomicBuffers = NULL;
shProg->NumAtomicBuffers = 0;
diff --git a/src/compiler/glsl/tests/set_uniform_initializer_tests.cpp b/src/compiler/glsl/tests/set_uniform_initializer_tests.cpp
index 0b1f66c..a36ffdc 100644
--- a/src/compiler/glsl/tests/set_uniform_initializer_tests.cpp
+++ b/src/compiler/glsl/tests/set_uniform_initializer_tests.cpp
@@ -115,7 +115,6 @@ establish_uniform_storage(struct gl_shader_program *prog, unsigned num_storage,
prog->UniformStorage[index_to_set].name = (char *) name;
prog->UniformStorage[index_to_set].type = type;
prog->UniformStorage[index_to_set].array_elements = array_size;
- prog->UniformStorage[index_to_set].initialized = false;
for (int sh = 0; sh < MESA_SHADER_STAGES; sh++) {
prog->UniformStorage[index_to_set].opaque[sh].index = ~0;
prog->UniformStorage[index_to_set].opaque[sh].active = false;
@@ -136,7 +135,6 @@ establish_uniform_storage(struct gl_shader_program *prog, unsigned num_storage,
prog->UniformStorage[i].name = (char *) "invalid slot";
prog->UniformStorage[i].type = glsl_type::void_type;
prog->UniformStorage[i].array_elements = 0;
- prog->UniformStorage[i].initialized = false;
for (int sh = 0; sh < MESA_SHADER_STAGES; sh++) {
prog->UniformStorage[i].opaque[sh].index = ~0;
prog->UniformStorage[i].opaque[sh].active = false;
@@ -149,21 +147,6 @@ establish_uniform_storage(struct gl_shader_program *prog, unsigned num_storage,
return red_zone_components;
}
-/**
- * Verify that the correct uniform is marked as having been initialized.
- */
-static void
-verify_initialization(struct gl_shader_program *prog, unsigned actual_index)
-{
- for (unsigned i = 0; i < prog->NumUniformStorage; i++) {
- if (i == actual_index) {
- EXPECT_TRUE(prog->UniformStorage[actual_index].initialized);
- } else {
- EXPECT_FALSE(prog->UniformStorage[i].initialized);
- }
- }
-}
-
static void
non_array_test(void *mem_ctx, struct gl_shader_program *prog,
unsigned actual_index, const char *name,
@@ -181,7 +164,6 @@ non_array_test(void *mem_ctx, struct gl_shader_program *prog,
linker::set_uniform_initializer(mem_ctx, prog, name, type, val, 0xF00F);
- verify_initialization(prog, actual_index);
verify_data(prog->UniformStorage[actual_index].storage, 0, val,
red_zone_components, 0xF00F);
}
@@ -338,7 +320,6 @@ array_test(void *mem_ctx, struct gl_shader_program *prog,
linker::set_uniform_initializer(mem_ctx, prog, name, element_type, val,
0xF00F);
- verify_initialization(prog, actual_index);
verify_data(prog->UniformStorage[actual_index].storage, array_size,
val, red_zone_components, 0xF00F);
}
diff --git a/src/compiler/glsl_types.cpp b/src/compiler/glsl_types.cpp
index 2421bd6..39585bf 100644
--- a/src/compiler/glsl_types.cpp
+++ b/src/compiler/glsl_types.cpp
@@ -132,6 +132,10 @@ glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields,
this->fields.structure[i].image_volatile = fields[i].image_volatile;
this->fields.structure[i].image_restrict = fields[i].image_restrict;
this->fields.structure[i].precision = fields[i].precision;
+ this->fields.structure[i].explicit_xfb_buffer =
+ fields[i].explicit_xfb_buffer;
+ this->fields.structure[i].xfb_buffer = fields[i].xfb_buffer;
+ this->fields.structure[i].xfb_stride = fields[i].xfb_stride;
}
mtx_unlock(&glsl_type::mutex);
@@ -172,6 +176,10 @@ glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields,
this->fields.structure[i].image_volatile = fields[i].image_volatile;
this->fields.structure[i].image_restrict = fields[i].image_restrict;
this->fields.structure[i].precision = fields[i].precision;
+ this->fields.structure[i].explicit_xfb_buffer =
+ fields[i].explicit_xfb_buffer;
+ this->fields.structure[i].xfb_buffer = fields[i].xfb_buffer;
+ this->fields.structure[i].xfb_stride = fields[i].xfb_stride;
}
mtx_unlock(&glsl_type::mutex);
@@ -915,6 +923,15 @@ glsl_type::record_compare(const glsl_type *b) const
if (this->fields.structure[i].precision
!= b->fields.structure[i].precision)
return false;
+ if (this->fields.structure[i].explicit_xfb_buffer
+ != b->fields.structure[i].explicit_xfb_buffer)
+ return false;
+ if (this->fields.structure[i].xfb_buffer
+ != b->fields.structure[i].xfb_buffer)
+ return false;
+ if (this->fields.structure[i].xfb_stride
+ != b->fields.structure[i].xfb_stride)
+ return false;
}
return true;
@@ -1333,6 +1350,38 @@ glsl_type::uniform_locations() const
}
}
+unsigned
+glsl_type::varying_count() const
+{
+ unsigned size = 0;
+
+ switch (this->base_type) {
+ case GLSL_TYPE_UINT:
+ case GLSL_TYPE_INT:
+ case GLSL_TYPE_FLOAT:
+ case GLSL_TYPE_DOUBLE:
+ case GLSL_TYPE_BOOL:
+ return 1;
+
+ case GLSL_TYPE_STRUCT:
+ case GLSL_TYPE_INTERFACE:
+ for (unsigned i = 0; i < this->length; i++)
+ size += this->fields.structure[i].type->varying_count();
+ return size;
+ case GLSL_TYPE_ARRAY:
+ /* Don't count innermost array elements */
+ if (this->without_array()->is_record() ||
+ this->without_array()->is_interface() ||
+ this->fields.array->is_array())
+ return this->length * this->fields.array->varying_count();
+ else
+ return this->fields.array->varying_count();
+ default:
+ assert(!"unsupported varying type");
+ return 0;
+ }
+}
+
bool
glsl_type::can_implicitly_convert_to(const glsl_type *desired,
_mesa_glsl_parse_state *state) const
diff --git a/src/compiler/glsl_types.h b/src/compiler/glsl_types.h
index b0e6f3f..dd46479 100644
--- a/src/compiler/glsl_types.h
+++ b/src/compiler/glsl_types.h
@@ -327,6 +327,12 @@ struct glsl_type {
unsigned uniform_locations() const;
/**
+ * Used to count the number of varyings contained in the type ignoring
+ * innermost array elements.
+ */
+ unsigned varying_count() const;
+
+ /**
* Calculate the number of attribute slots required to hold this type
*
* This implements the language rules of GLSL 1.50 for counting the number
@@ -839,13 +845,25 @@ struct glsl_struct_field {
/**
* For interface blocks, members may have an explicit byte offset
- * specified; -1 otherwise.
+ * specified; -1 otherwise. Also used for xfb_offset layout qualifier.
*
- * Ignored for structs.
+ * Unless used for xfb_offset this field is ignored for structs.
*/
int offset;
/**
+ * For interface blocks, members may define a transform feedback buffer;
+ * -1 otherwise.
+ */
+ int xfb_buffer;
+
+ /**
+ * For interface blocks, members may define a transform feedback stride;
+ * -1 otherwise.
+ */
+ int xfb_stride;
+
+ /**
* For interface blocks, the interpolation mode (as in
* ir_variable::interpolation). 0 otherwise.
*/
@@ -889,6 +907,13 @@ struct glsl_struct_field {
unsigned image_volatile:1;
unsigned image_restrict:1;
+ /**
+ * Any of the xfb_* qualifiers trigger the shader to be in transform
+ * feedback mode so we need to keep track of whether the buffer was
+ * explicitly set or if its just been assigned the default global value.
+ */
+ unsigned explicit_xfb_buffer:1;
+
#ifdef __cplusplus
glsl_struct_field(const struct glsl_type *_type, const char *_name)
: type(_type), name(_name), location(-1), interpolation(0), centroid(0),
diff --git a/src/compiler/nir/Makefile.sources b/src/compiler/nir/Makefile.sources
index a876eff..e6367d9 100644
--- a/src/compiler/nir/Makefile.sources
+++ b/src/compiler/nir/Makefile.sources
@@ -22,10 +22,10 @@ NIR_FILES = \
nir_gather_info.c \
nir_gs_count_vertices.c \
nir_inline_functions.c \
- nir_intrinsics.c \
- nir_intrinsics.h \
nir_instr_set.c \
nir_instr_set.h \
+ nir_intrinsics.c \
+ nir_intrinsics.h \
nir_liveness.c \
nir_lower_alu_to_scalar.c \
nir_lower_atomics.c \
diff --git a/src/compiler/nir/glsl_to_nir.cpp b/src/compiler/nir/glsl_to_nir.cpp
index 2a469ec..14affee 100644
--- a/src/compiler/nir/glsl_to_nir.cpp
+++ b/src/compiler/nir/glsl_to_nir.cpp
@@ -143,16 +143,7 @@ glsl_to_nir(const struct gl_shader_program *shader_prog,
v2.run(sh->ir);
visit_exec_list(sh->ir, &v1);
- nir_function *main = NULL;
- nir_foreach_function(shader, func) {
- if (strcmp(func->name, "main") == 0) {
- main = func;
- break;
- }
- }
- assert(main);
-
- nir_lower_outputs_to_temporaries(shader, main);
+ nir_lower_outputs_to_temporaries(shader, nir_shader_get_entrypoint(shader));
shader->info.name = ralloc_asprintf(shader, "GLSL%d", shader_prog->Name);
if (shader_prog->Label)
diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h
index de6b93c..d9e0d67 100644
--- a/src/compiler/nir/nir.h
+++ b/src/compiler/nir/nir.h
@@ -1822,6 +1822,8 @@ nir_shader_get_entrypoint(nir_shader *shader)
assert(exec_list_length(&shader->functions) == 1);
struct exec_node *func_node = exec_list_get_head(&shader->functions);
nir_function *func = exec_node_data(nir_function, func_node, node);
+ assert(func->return_type == glsl_void_type());
+ assert(func->num_params == 0);
return func;
}
diff --git a/src/compiler/nir/nir_opt_algebraic.py b/src/compiler/nir/nir_opt_algebraic.py
index 2e9cd5f..ddfe94d 100644
--- a/src/compiler/nir/nir_opt_algebraic.py
+++ b/src/compiler/nir/nir_opt_algebraic.py
@@ -127,6 +127,7 @@ optimizations = [
(('bcsel', ('flt', a, b), b, a), ('fmax', a, b)),
(('bcsel', ('inot', 'a@bool'), b, c), ('bcsel', a, c, b)),
(('bcsel', a, ('bcsel', a, b, c), d), ('bcsel', a, b, d)),
+ (('bcsel', a, True, 'b@bool'), ('ior', a, b)),
(('fmin', a, a), a),
(('fmax', a, a), a),
(('imin', a, a), a),
@@ -270,6 +271,10 @@ optimizations = [
(('fabs', ('fsub', 0.0, a)), ('fabs', a)),
(('iabs', ('isub', 0, a)), ('iabs', a)),
+ # Propagate negation up multiplication chains
+ (('fmul', ('fneg', a), b), ('fneg', ('fmul', a, b))),
+ (('imul', ('ineg', a), b), ('ineg', ('imul', a, b))),
+
# Misc. lowering
(('fmod', a, b), ('fsub', a, ('fmul', b, ('ffloor', ('fdiv', a, b)))), 'options->lower_fmod'),
(('frem', a, b), ('fsub', a, ('fmul', b, ('ftrunc', ('fdiv', a, b)))), 'options->lower_fmod'),
diff --git a/src/compiler/shader_enums.h b/src/compiler/shader_enums.h
index d44aabf..0c27408 100644
--- a/src/compiler/shader_enums.h
+++ b/src/compiler/shader_enums.h
@@ -31,7 +31,7 @@ extern "C" {
#endif
/**
- * Shader stages. Note that these will become 5 with tessellation.
+ * Shader stages.
*
* The order must match how shaders are ordered in the pipeline.
* The GLSL linker assumes that if i<j, then the j-th shader is