aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/glsl
diff options
context:
space:
mode:
Diffstat (limited to 'mesalib/src/glsl')
-rw-r--r--mesalib/src/glsl/ast.h5
-rw-r--r--mesalib/src/glsl/ast_to_hir.cpp19
-rw-r--r--mesalib/src/glsl/ast_type.cpp39
-rwxr-xr-xmesalib/src/glsl/builtin_functions.cpp64
-rw-r--r--mesalib/src/glsl/builtin_variables.cpp12
-rw-r--r--mesalib/src/glsl/glsl_parser.yy53
-rw-r--r--mesalib/src/glsl/glsl_parser_extras.h18
-rw-r--r--mesalib/src/glsl/glsl_types.h6
-rw-r--r--mesalib/src/glsl/ir.h39
-rw-r--r--mesalib/src/glsl/ir_hierarchical_visitor.cpp50
-rw-r--r--mesalib/src/glsl/ir_hierarchical_visitor.h6
-rw-r--r--mesalib/src/glsl/ir_hv_accept.cpp20
-rw-r--r--mesalib/src/glsl/ir_print_visitor.cpp20
-rw-r--r--mesalib/src/glsl/ir_reader.cpp28
-rw-r--r--mesalib/src/glsl/ir_rvalue_visitor.cpp37
-rw-r--r--mesalib/src/glsl/ir_rvalue_visitor.h6
-rw-r--r--mesalib/src/glsl/link_atomics.cpp13
-rw-r--r--mesalib/src/glsl/link_uniform_blocks.cpp6
-rw-r--r--mesalib/src/glsl/link_varyings.cpp41
-rw-r--r--mesalib/src/glsl/link_varyings.h17
-rw-r--r--mesalib/src/glsl/linker.cpp150
-rw-r--r--mesalib/src/glsl/lower_output_reads.cpp4
-rw-r--r--mesalib/src/glsl/lower_packed_varyings.cpp4
-rw-r--r--mesalib/src/glsl/opt_dead_code_local.cpp2
24 files changed, 581 insertions, 78 deletions
diff --git a/mesalib/src/glsl/ast.h b/mesalib/src/glsl/ast.h
index fc80e780e..83dfafd75 100644
--- a/mesalib/src/glsl/ast.h
+++ b/mesalib/src/glsl/ast.h
@@ -513,6 +513,8 @@ struct ast_type_qualifier {
/** \name Layout qualifiers for GL_ARB_gpu_shader5 */
/** \{ */
unsigned invocations:1;
+ unsigned stream:1; /**< Has stream value assigned */
+ unsigned explicit_stream:1; /**< stream value assigned explicitly by shader code */
/** \} */
}
/** \brief Set of flags, accessed by name. */
@@ -546,6 +548,9 @@ struct ast_type_qualifier {
/** Maximum output vertices in GLSL 1.50 geometry shaders. */
int max_vertices;
+ /** Stream in GLSL 1.50 geometry shaders. */
+ unsigned stream;
+
/** Input or output primitive type in GLSL 1.50 geometry shaders */
GLenum prim_type;
diff --git a/mesalib/src/glsl/ast_to_hir.cpp b/mesalib/src/glsl/ast_to_hir.cpp
index 7ba04a808..042ef243b 100644
--- a/mesalib/src/glsl/ast_to_hir.cpp
+++ b/mesalib/src/glsl/ast_to_hir.cpp
@@ -2461,6 +2461,11 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
if (qual->flags.q.sample)
var->data.sample = 1;
+ if (state->stage == MESA_SHADER_GEOMETRY &&
+ qual->flags.q.out && qual->flags.q.stream) {
+ var->data.stream = qual->stream;
+ }
+
if (qual->flags.q.attribute && state->stage != MESA_SHADER_VERTEX) {
var->type = glsl_type::error_type;
_mesa_glsl_error(loc, state,
@@ -5100,6 +5105,9 @@ ast_process_structure_or_interface_block(exec_list *instructions,
fields[i].centroid = qual->flags.q.centroid ? 1 : 0;
fields[i].sample = qual->flags.q.sample ? 1 : 0;
+ /* Only save explicitly defined streams in block's field */
+ fields[i].stream = qual->flags.q.explicit_stream ? qual->stream : -1;
+
if (qual->flags.q.row_major || qual->flags.q.column_major) {
if (!qual->flags.q.uniform) {
_mesa_glsl_error(&loc, state,
@@ -5548,6 +5556,17 @@ ast_interface_block::hir(exec_list *instructions,
var->data.sample = fields[i].sample;
var->init_interface_type(block_type);
+ if (fields[i].stream != -1 &&
+ ((unsigned)fields[i].stream) != this->layout.stream) {
+ _mesa_glsl_error(&loc, state,
+ "stream layout qualifier on "
+ "interface block member `%s' does not match "
+ "the interface block (%d vs %d)",
+ var->name, fields[i].stream, this->layout.stream);
+ }
+
+ var->data.stream = this->layout.stream;
+
if (redeclaring_per_vertex) {
ir_variable *earlier =
get_variable_being_redeclared(var, loc, state,
diff --git a/mesalib/src/glsl/ast_type.cpp b/mesalib/src/glsl/ast_type.cpp
index 77053d5b1..017f23d0e 100644
--- a/mesalib/src/glsl/ast_type.cpp
+++ b/mesalib/src/glsl/ast_type.cpp
@@ -125,9 +125,13 @@ ast_type_qualifier::merge_qualifier(YYLTYPE *loc,
/* Uniform block layout qualifiers get to overwrite each
* other (rightmost having priority), while all other
* qualifiers currently don't allow duplicates.
+ *
+ * Geometry shaders can have several layout qualifiers
+ * assigning different stream values.
*/
- if ((this->flags.i & q.flags.i & ~(ubo_mat_mask.flags.i |
+ if ((state->stage != MESA_SHADER_GEOMETRY) &&
+ (this->flags.i & q.flags.i & ~(ubo_mat_mask.flags.i |
ubo_layout_mask.flags.i |
ubo_binding_mask.flags.i)) != 0) {
_mesa_glsl_error(loc, state,
@@ -154,6 +158,39 @@ ast_type_qualifier::merge_qualifier(YYLTYPE *loc,
this->max_vertices = q.max_vertices;
}
+ if (state->stage == MESA_SHADER_GEOMETRY &&
+ state->has_explicit_attrib_stream()) {
+ if (q.flags.q.stream && q.stream >= state->ctx->Const.MaxVertexStreams) {
+ _mesa_glsl_error(loc, state,
+ "`stream' value is larger than MAX_VERTEX_STREAMS - 1 "
+ "(%d > %d)",
+ q.stream, state->ctx->Const.MaxVertexStreams - 1);
+ }
+ if (this->flags.q.explicit_stream &&
+ this->stream >= state->ctx->Const.MaxVertexStreams) {
+ _mesa_glsl_error(loc, state,
+ "`stream' value is larger than MAX_VERTEX_STREAMS - 1 "
+ "(%d > %d)",
+ this->stream, state->ctx->Const.MaxVertexStreams - 1);
+ }
+
+ if (!this->flags.q.explicit_stream) {
+ if (q.flags.q.stream) {
+ this->flags.q.stream = 1;
+ this->stream = q.stream;
+ } else if (!this->flags.q.stream && this->flags.q.out) {
+ /* Assign default global stream value */
+ this->flags.q.stream = 1;
+ this->stream = state->out_qualifier->stream;
+ }
+ } else {
+ if (q.flags.q.explicit_stream) {
+ _mesa_glsl_error(loc, state,
+ "duplicate layout `stream' qualifier");
+ }
+ }
+ }
+
if ((q.flags.i & ubo_mat_mask.flags.i) != 0)
this->flags.i &= ~ubo_mat_mask.flags.i;
if ((q.flags.i & ubo_layout_mask.flags.i) != 0)
diff --git a/mesalib/src/glsl/builtin_functions.cpp b/mesalib/src/glsl/builtin_functions.cpp
index 7e225b0d5..ee92384d6 100755
--- a/mesalib/src/glsl/builtin_functions.cpp
+++ b/mesalib/src/glsl/builtin_functions.cpp
@@ -359,6 +359,12 @@ shader_image_load_store(const _mesa_glsl_parse_state *state)
state->ARB_shader_image_load_store_enable);
}
+static bool
+gs_streams(const _mesa_glsl_parse_state *state)
+{
+ return gpu_shader5(state) && gs_only(state);
+}
+
/** @} */
/******************************************************************************/
@@ -594,6 +600,10 @@ private:
B0(EmitVertex)
B0(EndPrimitive)
+ ir_function_signature *_EmitStreamVertex(builtin_available_predicate avail,
+ const glsl_type *stream_type);
+ ir_function_signature *_EndStreamPrimitive(builtin_available_predicate avail,
+ const glsl_type *stream_type);
B2(textureQueryLod);
B1(textureQueryLevels);
@@ -1708,6 +1718,14 @@ builtin_builder::create_builtins()
add_function("EmitVertex", _EmitVertex(), NULL);
add_function("EndPrimitive", _EndPrimitive(), NULL);
+ add_function("EmitStreamVertex",
+ _EmitStreamVertex(gs_streams, glsl_type::uint_type),
+ _EmitStreamVertex(gs_streams, glsl_type::int_type),
+ NULL);
+ add_function("EndStreamPrimitive",
+ _EndStreamPrimitive(gs_streams, glsl_type::uint_type),
+ _EndStreamPrimitive(gs_streams, glsl_type::int_type),
+ NULL);
add_function("textureQueryLOD",
_textureQueryLod(glsl_type::sampler1D_type, glsl_type::float_type),
@@ -3872,7 +3890,28 @@ builtin_builder::_EmitVertex()
{
MAKE_SIG(glsl_type::void_type, gs_only, 0);
- body.emit(new(mem_ctx) ir_emit_vertex());
+ ir_rvalue *stream = new(mem_ctx) ir_constant(0, 1);
+ body.emit(new(mem_ctx) ir_emit_vertex(stream));
+
+ return sig;
+}
+
+ir_function_signature *
+builtin_builder::_EmitStreamVertex(builtin_available_predicate avail,
+ const glsl_type *stream_type)
+{
+ /* Section 8.12 (Geometry Shader Functions) of the GLSL 4.0 spec says:
+ *
+ * "Emit the current values of output variables to the current output
+ * primitive on stream stream. The argument to stream must be a constant
+ * integral expression."
+ */
+ ir_variable *stream =
+ new(mem_ctx) ir_variable(stream_type, "stream", ir_var_const_in);
+
+ MAKE_SIG(glsl_type::void_type, avail, 1, stream);
+
+ body.emit(new(mem_ctx) ir_emit_vertex(var_ref(stream)));
return sig;
}
@@ -3882,7 +3921,28 @@ builtin_builder::_EndPrimitive()
{
MAKE_SIG(glsl_type::void_type, gs_only, 0);
- body.emit(new(mem_ctx) ir_end_primitive());
+ ir_rvalue *stream = new(mem_ctx) ir_constant(0, 1);
+ body.emit(new(mem_ctx) ir_end_primitive(stream));
+
+ return sig;
+}
+
+ir_function_signature *
+builtin_builder::_EndStreamPrimitive(builtin_available_predicate avail,
+ const glsl_type *stream_type)
+{
+ /* Section 8.12 (Geometry Shader Functions) of the GLSL 4.0 spec says:
+ *
+ * "Completes the current output primitive on stream stream and starts
+ * a new one. The argument to stream must be a constant integral
+ * expression."
+ */
+ ir_variable *stream =
+ new(mem_ctx) ir_variable(stream_type, "stream", ir_var_const_in);
+
+ MAKE_SIG(glsl_type::void_type, avail, 1, stream);
+
+ body.emit(new(mem_ctx) ir_end_primitive(var_ref(stream)));
return sig;
}
diff --git a/mesalib/src/glsl/builtin_variables.cpp b/mesalib/src/glsl/builtin_variables.cpp
index b9c69d23c..9f9571619 100644
--- a/mesalib/src/glsl/builtin_variables.cpp
+++ b/mesalib/src/glsl/builtin_variables.cpp
@@ -160,14 +160,6 @@ static const struct gl_builtin_uniform_element gl_NormalScale_elements[] = {
{NULL, {STATE_NORMAL_SCALE}, SWIZZLE_XXXX},
};
-static const struct gl_builtin_uniform_element gl_BumpRotMatrix0MESA_elements[] = {
- {NULL, {STATE_INTERNAL, STATE_ROT_MATRIX_0}, SWIZZLE_XYZW},
-};
-
-static const struct gl_builtin_uniform_element gl_BumpRotMatrix1MESA_elements[] = {
- {NULL, {STATE_INTERNAL, STATE_ROT_MATRIX_1}, SWIZZLE_XYZW},
-};
-
static const struct gl_builtin_uniform_element gl_FogParamsOptimizedMESA_elements[] = {
{NULL, {STATE_INTERNAL, STATE_FOG_PARAMS_OPTIMIZED}, SWIZZLE_XYZW},
};
@@ -284,8 +276,6 @@ static const struct gl_builtin_uniform_desc _mesa_builtin_uniform_desc[] = {
STATEVAR(gl_NormalMatrix),
STATEVAR(gl_NormalScale),
- STATEVAR(gl_BumpRotMatrix0MESA),
- STATEVAR(gl_BumpRotMatrix1MESA),
STATEVAR(gl_FogParamsOptimizedMESA),
STATEVAR(gl_CurrentAttribVertMESA),
STATEVAR(gl_CurrentAttribFragMESA),
@@ -761,8 +751,6 @@ builtin_variable_generator::generate_uniforms()
add_uniform(mat4_t, "gl_ModelViewProjectionMatrixInverseTranspose");
add_uniform(float_t, "gl_NormalScale");
add_uniform(type("gl_LightModelParameters"), "gl_LightModel");
- add_uniform(vec2_t, "gl_BumpRotMatrix0MESA");
- add_uniform(vec2_t, "gl_BumpRotMatrix1MESA");
add_uniform(vec4_t, "gl_FogParamsOptimizedMESA");
const glsl_type *const mat4_array_type =
diff --git a/mesalib/src/glsl/glsl_parser.yy b/mesalib/src/glsl/glsl_parser.yy
index 2b2de3047..980acc8ae 100644
--- a/mesalib/src/glsl/glsl_parser.yy
+++ b/mesalib/src/glsl/glsl_parser.yy
@@ -1396,6 +1396,22 @@ layout_qualifier_id:
}
}
+ if (state->stage == MESA_SHADER_GEOMETRY) {
+ if (match_layout_qualifier("stream", $1, state) == 0 &&
+ state->check_explicit_attrib_stream_allowed(& @3)) {
+ $$.flags.q.stream = 1;
+
+ if ($3 < 0) {
+ _mesa_glsl_error(& @3, state,
+ "invalid stream %d specified", $3);
+ YYERROR;
+ } else {
+ $$.flags.q.explicit_stream = 1;
+ $$.stream = $3;
+ }
+ }
+ }
+
static const char * const local_size_qualifiers[3] = {
"local_size_x",
"local_size_y",
@@ -1694,6 +1710,20 @@ storage_qualifier:
{
memset(& $$, 0, sizeof($$));
$$.flags.q.out = 1;
+
+ if (state->stage == MESA_SHADER_GEOMETRY &&
+ state->has_explicit_attrib_stream()) {
+ /* Section 4.3.8.2 (Output Layout Qualifiers) of the GLSL 4.00
+ * spec says:
+ *
+ * "If the block or variable is declared with the stream
+ * identifier, it is associated with the specified stream;
+ * otherwise, it is associated with the current default stream."
+ */
+ $$.flags.q.stream = 1;
+ $$.flags.q.explicit_stream = 0;
+ $$.stream = state->out_qualifier->stream;
+ }
}
| UNIFORM
{
@@ -2362,6 +2392,18 @@ interface_block:
if (!block->layout.merge_qualifier(& @1, state, $1)) {
YYERROR;
}
+
+ foreach_list_typed (ast_declarator_list, member, link, &block->declarations) {
+ ast_type_qualifier& qualifier = member->type->qualifier;
+ if (qualifier.flags.q.stream && qualifier.stream != block->layout.stream) {
+ _mesa_glsl_error(& @1, state,
+ "stream layout qualifier on "
+ "interface block member does not match "
+ "the interface block (%d vs %d)",
+ qualifier.stream, block->layout.stream);
+ YYERROR;
+ }
+ }
$$ = block;
}
;
@@ -2435,6 +2477,14 @@ basic_interface_block:
block->layout.flags.i |= block_interface_qualifier;
+ if (state->stage == MESA_SHADER_GEOMETRY &&
+ state->has_explicit_attrib_stream()) {
+ /* Assign global layout's stream value. */
+ block->layout.flags.q.stream = 1;
+ block->layout.flags.q.explicit_stream = 0;
+ block->layout.stream = state->out_qualifier->stream;
+ }
+
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) {
@@ -2577,6 +2627,9 @@ layout_defaults:
}
if (!state->out_qualifier->merge_qualifier(& @1, state, $1))
YYERROR;
+
+ /* Allow future assigments of global out's stream id value */
+ state->out_qualifier->flags.q.explicit_stream = 0;
}
$$ = NULL;
}
diff --git a/mesalib/src/glsl/glsl_parser_extras.h b/mesalib/src/glsl/glsl_parser_extras.h
index 2a5aea477..fd1391c2a 100644
--- a/mesalib/src/glsl/glsl_parser_extras.h
+++ b/mesalib/src/glsl/glsl_parser_extras.h
@@ -123,6 +123,19 @@ struct _mesa_glsl_parse_state {
return check_version(130, 300, locp, "bit-wise operations are forbidden");
}
+ bool check_explicit_attrib_stream_allowed(YYLTYPE *locp)
+ {
+ if (!this->has_explicit_attrib_stream()) {
+ const char *const requirement = "GL_ARB_gpu_shader5 extension or GLSL 400";
+
+ _mesa_glsl_error(locp, this, "explicit stream requires %s",
+ requirement);
+ return false;
+ }
+
+ return true;
+ }
+
bool check_explicit_attrib_location_allowed(YYLTYPE *locp,
const ir_variable *var)
{
@@ -170,6 +183,11 @@ struct _mesa_glsl_parse_state {
return true;
}
+ bool has_explicit_attrib_stream() const
+ {
+ return ARB_gpu_shader5_enable || is_version(400, 0);
+ }
+
bool has_explicit_attrib_location() const
{
return ARB_explicit_attrib_location_enable || is_version(330, 300);
diff --git a/mesalib/src/glsl/glsl_types.h b/mesalib/src/glsl/glsl_types.h
index f6d4a02ab..0b63d4850 100644
--- a/mesalib/src/glsl/glsl_types.h
+++ b/mesalib/src/glsl/glsl_types.h
@@ -671,6 +671,12 @@ struct glsl_struct_field {
* in ir_variable::sample). 0 otherwise.
*/
unsigned sample:1;
+
+ /**
+ * For interface blocks, it has a value if this variable uses multiple vertex
+ * streams (as in ir_variable::stream). -1 otherwise.
+ */
+ int stream;
};
static inline unsigned int
diff --git a/mesalib/src/glsl/ir.h b/mesalib/src/glsl/ir.h
index b4e52d3d0..d5239d4de 100644
--- a/mesalib/src/glsl/ir.h
+++ b/mesalib/src/glsl/ir.h
@@ -706,6 +706,11 @@ public:
int location;
/**
+ * Vertex stream output identifier.
+ */
+ unsigned stream;
+
+ /**
* output index for dual source blending.
*/
int index;
@@ -2154,9 +2159,11 @@ private:
*/
class ir_emit_vertex : public ir_instruction {
public:
- ir_emit_vertex()
- : ir_instruction(ir_type_emit_vertex)
+ ir_emit_vertex(ir_rvalue *stream)
+ : ir_instruction(ir_type_emit_vertex),
+ stream(stream)
{
+ assert(stream);
}
virtual void accept(ir_visitor *v)
@@ -2164,12 +2171,19 @@ public:
v->visit(this);
}
- virtual ir_emit_vertex *clone(void *mem_ctx, struct hash_table *) const
+ virtual ir_emit_vertex *clone(void *mem_ctx, struct hash_table *ht) const
{
- return new(mem_ctx) ir_emit_vertex();
+ return new(mem_ctx) ir_emit_vertex(this->stream->clone(mem_ctx, ht));
}
virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+ int stream_id() const
+ {
+ return stream->as_constant()->value.i[0];
+ }
+
+ ir_rvalue *stream;
};
/**
@@ -2178,9 +2192,11 @@ public:
*/
class ir_end_primitive : public ir_instruction {
public:
- ir_end_primitive()
- : ir_instruction(ir_type_end_primitive)
+ ir_end_primitive(ir_rvalue *stream)
+ : ir_instruction(ir_type_end_primitive),
+ stream(stream)
{
+ assert(stream);
}
virtual void accept(ir_visitor *v)
@@ -2188,12 +2204,19 @@ public:
v->visit(this);
}
- virtual ir_end_primitive *clone(void *mem_ctx, struct hash_table *) const
+ virtual ir_end_primitive *clone(void *mem_ctx, struct hash_table *ht) const
{
- return new(mem_ctx) ir_end_primitive();
+ return new(mem_ctx) ir_end_primitive(this->stream->clone(mem_ctx, ht));
}
virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+ int stream_id() const
+ {
+ return stream->as_constant()->value.i[0];
+ }
+
+ ir_rvalue *stream;
};
/*@}*/
diff --git a/mesalib/src/glsl/ir_hierarchical_visitor.cpp b/mesalib/src/glsl/ir_hierarchical_visitor.cpp
index 2e606dda4..d3c00ecdb 100644
--- a/mesalib/src/glsl/ir_hierarchical_visitor.cpp
+++ b/mesalib/src/glsl/ir_hierarchical_visitor.cpp
@@ -69,24 +69,6 @@ ir_hierarchical_visitor::visit(ir_loop_jump *ir)
}
ir_visitor_status
-ir_hierarchical_visitor::visit(ir_emit_vertex *ir)
-{
- if (this->callback != NULL)
- this->callback(ir, this->data);
-
- return visit_continue;
-}
-
-ir_visitor_status
-ir_hierarchical_visitor::visit(ir_end_primitive *ir)
-{
- if (this->callback != NULL)
- this->callback(ir, this->data);
-
- return visit_continue;
-}
-
-ir_visitor_status
ir_hierarchical_visitor::visit(ir_dereference_variable *ir)
{
if (this->callback != NULL)
@@ -303,6 +285,38 @@ ir_hierarchical_visitor::visit_leave(ir_if *ir)
return visit_continue;
}
+ir_visitor_status
+ir_hierarchical_visitor::visit_enter(ir_emit_vertex *ir)
+{
+ if (this->callback != NULL)
+ this->callback(ir, this->data);
+
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_leave(ir_emit_vertex *ir)
+{
+ (void) ir;
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_enter(ir_end_primitive *ir)
+{
+ if (this->callback != NULL)
+ this->callback(ir, this->data);
+
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_leave(ir_end_primitive *ir)
+{
+ (void) ir;
+ return visit_continue;
+}
+
void
ir_hierarchical_visitor::run(exec_list *instructions)
{
diff --git a/mesalib/src/glsl/ir_hierarchical_visitor.h b/mesalib/src/glsl/ir_hierarchical_visitor.h
index 647d2e002..bc89a04d8 100644
--- a/mesalib/src/glsl/ir_hierarchical_visitor.h
+++ b/mesalib/src/glsl/ir_hierarchical_visitor.h
@@ -87,8 +87,6 @@ public:
virtual ir_visitor_status visit(class ir_variable *);
virtual ir_visitor_status visit(class ir_constant *);
virtual ir_visitor_status visit(class ir_loop_jump *);
- virtual ir_visitor_status visit(class ir_emit_vertex *);
- virtual ir_visitor_status visit(class ir_end_primitive *);
/**
* ir_dereference_variable isn't technically a leaf, but it is treated as a
@@ -137,6 +135,10 @@ public:
virtual ir_visitor_status visit_leave(class ir_discard *);
virtual ir_visitor_status visit_enter(class ir_if *);
virtual ir_visitor_status visit_leave(class ir_if *);
+ virtual ir_visitor_status visit_enter(class ir_emit_vertex *);
+ virtual ir_visitor_status visit_leave(class ir_emit_vertex *);
+ virtual ir_visitor_status visit_enter(class ir_end_primitive *);
+ virtual ir_visitor_status visit_leave(class ir_end_primitive *);
/*@}*/
diff --git a/mesalib/src/glsl/ir_hv_accept.cpp b/mesalib/src/glsl/ir_hv_accept.cpp
index 2a1f70e5b..3ca7a5887 100644
--- a/mesalib/src/glsl/ir_hv_accept.cpp
+++ b/mesalib/src/glsl/ir_hv_accept.cpp
@@ -405,12 +405,28 @@ ir_if::accept(ir_hierarchical_visitor *v)
ir_visitor_status
ir_emit_vertex::accept(ir_hierarchical_visitor *v)
{
- return v->visit(this);
+ ir_visitor_status s = v->visit_enter(this);
+ if (s != visit_continue)
+ return (s == visit_continue_with_parent) ? visit_continue : s;
+
+ s = this->stream->accept(v);
+ if (s != visit_continue)
+ return (s == visit_continue_with_parent) ? visit_continue : s;
+
+ return (s == visit_stop) ? s : v->visit_leave(this);
}
ir_visitor_status
ir_end_primitive::accept(ir_hierarchical_visitor *v)
{
- return v->visit(this);
+ ir_visitor_status s = v->visit_enter(this);
+ if (s != visit_continue)
+ return (s == visit_continue_with_parent) ? visit_continue : s;
+
+ s = this->stream->accept(v);
+ if (s != visit_continue)
+ return (s == visit_continue_with_parent) ? visit_continue : s;
+
+ return (s == visit_stop) ? s : v->visit_leave(this);
}
diff --git a/mesalib/src/glsl/ir_print_visitor.cpp b/mesalib/src/glsl/ir_print_visitor.cpp
index c4a6f9c9f..72ad4223f 100644
--- a/mesalib/src/glsl/ir_print_visitor.cpp
+++ b/mesalib/src/glsl/ir_print_visitor.cpp
@@ -169,11 +169,14 @@ void ir_print_visitor::visit(ir_variable *ir)
"in ", "out ", "inout ",
"const_in ", "sys ", "temporary " };
STATIC_ASSERT(ARRAY_SIZE(mode) == ir_var_mode_count);
+ const char *const stream [] = {"", "stream1 ", "stream2 ", "stream3 "};
const char *const interp[] = { "", "smooth", "flat", "noperspective" };
STATIC_ASSERT(ARRAY_SIZE(interp) == INTERP_QUALIFIER_COUNT);
- fprintf(f, "(%s%s%s%s%s) ",
- cent, samp, inv, mode[ir->data.mode], interp[ir->data.interpolation]);
+ fprintf(f, "(%s%s%s%s%s%s) ",
+ cent, samp, inv, mode[ir->data.mode],
+ stream[ir->data.stream],
+ interp[ir->data.interpolation]);
print_type(f, ir->type);
fprintf(f, " %s)", unique_name(ir));
@@ -560,13 +563,18 @@ ir_print_visitor::visit(ir_loop_jump *ir)
}
void
-ir_print_visitor::visit(ir_emit_vertex *)
+ir_print_visitor::visit(ir_emit_vertex *ir)
{
- fprintf(f, "(emit-vertex)");
+ fprintf(f, "(emit-vertex ");
+ ir->stream->accept(this);
+ fprintf(f, ")\n");
}
void
-ir_print_visitor::visit(ir_end_primitive *)
+ir_print_visitor::visit(ir_end_primitive *ir)
{
- fprintf(f, "(end-primitive)");
+ fprintf(f, "(end-primitive ");
+ ir->stream->accept(this);
+ fprintf(f, ")\n");
+
}
diff --git a/mesalib/src/glsl/ir_reader.cpp b/mesalib/src/glsl/ir_reader.cpp
index 28923f3b8..a178c82b5 100644
--- a/mesalib/src/glsl/ir_reader.cpp
+++ b/mesalib/src/glsl/ir_reader.cpp
@@ -437,6 +437,12 @@ ir_reader::read_declaration(s_expression *expr)
var->data.mode = ir_var_function_inout;
} else if (strcmp(qualifier->value(), "temporary") == 0) {
var->data.mode = ir_var_temporary;
+ } else if (strcmp(qualifier->value(), "stream1") == 0) {
+ var->data.stream = 1;
+ } else if (strcmp(qualifier->value(), "stream2") == 0) {
+ var->data.stream = 2;
+ } else if (strcmp(qualifier->value(), "stream3") == 0) {
+ var->data.stream = 3;
} else if (strcmp(qualifier->value(), "smooth") == 0) {
var->data.interpolation = INTERP_QUALIFIER_SMOOTH;
} else if (strcmp(qualifier->value(), "flat") == 0) {
@@ -1109,10 +1115,17 @@ ir_reader::read_texture(s_expression *expr)
ir_emit_vertex *
ir_reader::read_emit_vertex(s_expression *expr)
{
- s_pattern pat[] = { "emit-vertex" };
+ s_expression *s_stream = NULL;
+
+ s_pattern pat[] = { "emit-vertex", s_stream };
if (MATCH(expr, pat)) {
- return new(mem_ctx) ir_emit_vertex();
+ ir_rvalue *stream = read_dereference(s_stream);
+ if (stream == NULL) {
+ ir_read_error(NULL, "when reading stream info in emit-vertex");
+ return NULL;
+ }
+ return new(mem_ctx) ir_emit_vertex(stream);
}
ir_read_error(NULL, "when reading emit-vertex");
return NULL;
@@ -1121,10 +1134,17 @@ ir_reader::read_emit_vertex(s_expression *expr)
ir_end_primitive *
ir_reader::read_end_primitive(s_expression *expr)
{
- s_pattern pat[] = { "end-primitive" };
+ s_expression *s_stream = NULL;
+
+ s_pattern pat[] = { "end-primitive", s_stream };
if (MATCH(expr, pat)) {
- return new(mem_ctx) ir_end_primitive();
+ ir_rvalue *stream = read_dereference(s_stream);
+ if (stream == NULL) {
+ ir_read_error(NULL, "when reading stream info in end-primitive");
+ return NULL;
+ }
+ return new(mem_ctx) ir_end_primitive(stream);
}
ir_read_error(NULL, "when reading end-primitive");
return NULL;
diff --git a/mesalib/src/glsl/ir_rvalue_visitor.cpp b/mesalib/src/glsl/ir_rvalue_visitor.cpp
index fcbe9448d..0370170b3 100644
--- a/mesalib/src/glsl/ir_rvalue_visitor.cpp
+++ b/mesalib/src/glsl/ir_rvalue_visitor.cpp
@@ -149,6 +149,19 @@ ir_rvalue_base_visitor::rvalue_visit(ir_if *ir)
return visit_continue;
}
+ir_visitor_status
+ir_rvalue_base_visitor::rvalue_visit(ir_emit_vertex *ir)
+{
+ handle_rvalue(&ir->stream);
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_rvalue_base_visitor::rvalue_visit(ir_end_primitive *ir)
+{
+ handle_rvalue(&ir->stream);
+ return visit_continue;
+}
ir_visitor_status
ir_rvalue_visitor::visit_leave(ir_expression *ir)
@@ -205,6 +218,18 @@ ir_rvalue_visitor::visit_leave(ir_if *ir)
}
ir_visitor_status
+ir_rvalue_visitor::visit_leave(ir_emit_vertex *ir)
+{
+ return rvalue_visit(ir);
+}
+
+ir_visitor_status
+ir_rvalue_visitor::visit_leave(ir_end_primitive *ir)
+{
+ return rvalue_visit(ir);
+}
+
+ir_visitor_status
ir_rvalue_enter_visitor::visit_enter(ir_expression *ir)
{
return rvalue_visit(ir);
@@ -257,3 +282,15 @@ ir_rvalue_enter_visitor::visit_enter(ir_if *ir)
{
return rvalue_visit(ir);
}
+
+ir_visitor_status
+ir_rvalue_enter_visitor::visit_enter(ir_emit_vertex *ir)
+{
+ return rvalue_visit(ir);
+}
+
+ir_visitor_status
+ir_rvalue_enter_visitor::visit_enter(ir_end_primitive *ir)
+{
+ return rvalue_visit(ir);
+}
diff --git a/mesalib/src/glsl/ir_rvalue_visitor.h b/mesalib/src/glsl/ir_rvalue_visitor.h
index 2179fa5a8..04ec0fa39 100644
--- a/mesalib/src/glsl/ir_rvalue_visitor.h
+++ b/mesalib/src/glsl/ir_rvalue_visitor.h
@@ -41,6 +41,8 @@ public:
ir_visitor_status rvalue_visit(ir_return *);
ir_visitor_status rvalue_visit(ir_swizzle *);
ir_visitor_status rvalue_visit(ir_texture *);
+ ir_visitor_status rvalue_visit(ir_emit_vertex *);
+ ir_visitor_status rvalue_visit(ir_end_primitive *);
virtual void handle_rvalue(ir_rvalue **rvalue) = 0;
};
@@ -57,6 +59,8 @@ public:
virtual ir_visitor_status visit_leave(ir_return *);
virtual ir_visitor_status visit_leave(ir_swizzle *);
virtual ir_visitor_status visit_leave(ir_texture *);
+ virtual ir_visitor_status visit_leave(ir_emit_vertex *);
+ virtual ir_visitor_status visit_leave(ir_end_primitive *);
};
class ir_rvalue_enter_visitor : public ir_rvalue_base_visitor {
@@ -71,4 +75,6 @@ public:
virtual ir_visitor_status visit_enter(ir_return *);
virtual ir_visitor_status visit_enter(ir_swizzle *);
virtual ir_visitor_status visit_enter(ir_texture *);
+ virtual ir_visitor_status visit_enter(ir_emit_vertex *);
+ virtual ir_visitor_status visit_enter(ir_end_primitive *);
};
diff --git a/mesalib/src/glsl/link_atomics.cpp b/mesalib/src/glsl/link_atomics.cpp
index d92cdb117..fbe4e7364 100644
--- a/mesalib/src/glsl/link_atomics.cpp
+++ b/mesalib/src/glsl/link_atomics.cpp
@@ -54,9 +54,18 @@ namespace {
void push_back(unsigned id, ir_variable *var)
{
- counters = (active_atomic_counter *)
- realloc(counters, sizeof(active_atomic_counter) * (num_counters + 1));
+ active_atomic_counter *new_counters;
+ new_counters = (active_atomic_counter *)
+ realloc(counters, sizeof(active_atomic_counter) *
+ (num_counters + 1));
+
+ if (new_counters == NULL) {
+ _mesa_error_no_memory(__func__);
+ return;
+ }
+
+ counters = new_counters;
counters[num_counters].id = id;
counters[num_counters].var = var;
num_counters++;
diff --git a/mesalib/src/glsl/link_uniform_blocks.cpp b/mesalib/src/glsl/link_uniform_blocks.cpp
index 1a0e64318..53a18c934 100644
--- a/mesalib/src/glsl/link_uniform_blocks.cpp
+++ b/mesalib/src/glsl/link_uniform_blocks.cpp
@@ -170,6 +170,12 @@ link_uniform_blocks(void *mem_ctx,
struct hash_table *block_hash =
_mesa_hash_table_create(mem_ctx, _mesa_key_string_equal);
+ if (block_hash == NULL) {
+ _mesa_error_no_memory(__func__);
+ linker_error(prog, "out of memory\n");
+ return 0;
+ }
+
/* Determine which uniform blocks are active.
*/
link_uniform_block_active_visitor v(mem_ctx, block_hash, prog);
diff --git a/mesalib/src/glsl/link_varyings.cpp b/mesalib/src/glsl/link_varyings.cpp
index 686329857..520a51a27 100644
--- a/mesalib/src/glsl/link_varyings.cpp
+++ b/mesalib/src/glsl/link_varyings.cpp
@@ -291,6 +291,7 @@ tfeedback_decl::init(struct gl_context *ctx, const void *mem_ctx,
this->skip_components = 0;
this->next_buffer_separator = false;
this->matched_candidate = NULL;
+ this->stream_id = 0;
if (ctx->Extensions.ARB_transform_feedback3) {
/* Parse gl_NextBuffer. */
@@ -355,8 +356,8 @@ tfeedback_decl::is_same(const tfeedback_decl &x, const tfeedback_decl &y)
/**
- * Assign a location for this tfeedback_decl object based on the transform
- * feedback candidate found by find_candidate.
+ * Assign a location and stream ID for this tfeedback_decl object based on the
+ * transform feedback candidate found by find_candidate.
*
* If an error occurs, the error is reported through linker_error() and false
* is returned.
@@ -437,6 +438,11 @@ tfeedback_decl::assign_location(struct gl_context *ctx,
return false;
}
+ /* Only transform feedback varyings can be assigned to non-zero streams,
+ * so assign the stream id here.
+ */
+ this->stream_id = this->matched_candidate->toplevel_var->data.stream;
+
return true;
}
@@ -495,6 +501,7 @@ tfeedback_decl::store(struct gl_context *ctx, struct gl_shader_program *prog,
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;
@@ -628,10 +635,27 @@ store_tfeedback_info(struct gl_context *ctx, struct gl_shader_program *prog,
}
else {
/* GL_INVERLEAVED_ATTRIBS */
+ int buffer_stream_id = -1;
for (unsigned i = 0; i < num_tfeedback_decls; ++i) {
if (tfeedback_decls[i].is_next_buffer_separator()) {
num_buffers++;
+ buffer_stream_id = -1;
continue;
+ } else if (buffer_stream_id == -1) {
+ /* First varying writing to this buffer: remember its stream */
+ buffer_stream_id = (int) tfeedback_decls[i].get_stream_id();
+ } else if (buffer_stream_id !=
+ (int) tfeedback_decls[i].get_stream_id()) {
+ /* Varying writes to the same buffer from a different stream */
+ linker_error(prog,
+ "Transform feedback can't capture varyings belonging "
+ "to different vertex streams in a single buffer. "
+ "Varying %s writes to buffer from stream %u, other "
+ "varyings in the same buffer write from stream %u.",
+ tfeedback_decls[i].name(),
+ tfeedback_decls[i].get_stream_id(),
+ buffer_stream_id);
+ return false;
}
if (!tfeedback_decls[i].store(ctx, prog,
@@ -1323,6 +1347,11 @@ assign_varying_locations(struct gl_context *ctx,
(output_var->data.mode != ir_var_shader_out))
continue;
+ /* Only geometry shaders can use non-zero streams */
+ assert(output_var->data.stream == 0 ||
+ (output_var->data.stream < MAX_VERTEX_STREAMS &&
+ producer->Stage == MESA_SHADER_GEOMETRY));
+
tfeedback_candidate_generator g(mem_ctx, tfeedback_candidates);
g.process(output_var);
@@ -1338,6 +1367,14 @@ assign_varying_locations(struct gl_context *ctx,
if (input_var || (prog->SeparateShader && consumer == NULL)) {
matches.record(output_var, input_var);
}
+
+ /* Only stream 0 outputs can be consumed in the next stage */
+ if (input_var && output_var->data.stream != 0) {
+ linker_error(prog, "output %s is assigned to stream=%d but "
+ "is linked to an input, which requires stream=0",
+ output_var->name, output_var->data.stream);
+ return false;
+ }
}
} else {
/* If there's no producer stage, then this must be a separable program.
diff --git a/mesalib/src/glsl/link_varyings.h b/mesalib/src/glsl/link_varyings.h
index 6fa268176..afc16a8ba 100644
--- a/mesalib/src/glsl/link_varyings.h
+++ b/mesalib/src/glsl/link_varyings.h
@@ -112,6 +112,16 @@ public:
return !this->next_buffer_separator && !this->skip_components;
}
+ const char *name() const
+ {
+ return this->orig_name;
+ }
+
+ unsigned get_stream_id() const
+ {
+ return this->stream_id;
+ }
+
/**
* The total number of varying components taken up by this variable. Only
* valid if assign_location() has been called.
@@ -210,6 +220,13 @@ private:
* data structure that was found. Otherwise NULL.
*/
const tfeedback_candidate *matched_candidate;
+
+ /**
+ * StreamId assigned to this varying (defaults to 0). Can only be set to
+ * values other than 0 in geometry shaders that use the stream layout
+ * modifier. Accepted values must be in the range [0, MAX_VERTEX_STREAMS-1].
+ */
+ unsigned stream_id;
};
diff --git a/mesalib/src/glsl/linker.cpp b/mesalib/src/glsl/linker.cpp
index 0b6a71679..3036ebcb3 100644
--- a/mesalib/src/glsl/linker.cpp
+++ b/mesalib/src/glsl/linker.cpp
@@ -250,31 +250,100 @@ public:
}
};
-
/**
- * Visitor that determines whether or not a shader uses ir_end_primitive.
+ * Visitor that determines the highest stream id to which a (geometry) shader
+ * emits vertices. It also checks whether End{Stream}Primitive is ever called.
*/
-class find_end_primitive_visitor : public ir_hierarchical_visitor {
+class find_emit_vertex_visitor : public ir_hierarchical_visitor {
public:
- find_end_primitive_visitor()
- : found(false)
+ find_emit_vertex_visitor(int max_allowed)
+ : max_stream_allowed(max_allowed),
+ invalid_stream_id(0),
+ invalid_stream_id_from_emit_vertex(false),
+ end_primitive_found(false),
+ uses_non_zero_stream(false)
{
/* empty */
}
- virtual ir_visitor_status visit(ir_end_primitive *)
+ virtual ir_visitor_status visit_leave(ir_emit_vertex *ir)
{
- found = true;
- return visit_stop;
+ int stream_id = ir->stream_id();
+
+ if (stream_id < 0) {
+ invalid_stream_id = stream_id;
+ invalid_stream_id_from_emit_vertex = true;
+ return visit_stop;
+ }
+
+ if (stream_id > max_stream_allowed) {
+ invalid_stream_id = stream_id;
+ invalid_stream_id_from_emit_vertex = true;
+ return visit_stop;
+ }
+
+ if (stream_id != 0)
+ uses_non_zero_stream = true;
+
+ return visit_continue;
}
- bool end_primitive_found()
+ virtual ir_visitor_status visit_leave(ir_end_primitive *ir)
{
- return found;
+ end_primitive_found = true;
+
+ int stream_id = ir->stream_id();
+
+ if (stream_id < 0) {
+ invalid_stream_id = stream_id;
+ invalid_stream_id_from_emit_vertex = false;
+ return visit_stop;
+ }
+
+ if (stream_id > max_stream_allowed) {
+ invalid_stream_id = stream_id;
+ invalid_stream_id_from_emit_vertex = false;
+ return visit_stop;
+ }
+
+ if (stream_id != 0)
+ uses_non_zero_stream = true;
+
+ return visit_continue;
+ }
+
+ bool error()
+ {
+ return invalid_stream_id != 0;
+ }
+
+ const char *error_func()
+ {
+ return invalid_stream_id_from_emit_vertex ?
+ "EmitStreamVertex" : "EndStreamPrimitive";
+ }
+
+ int error_stream()
+ {
+ return invalid_stream_id;
+ }
+
+ bool uses_streams()
+ {
+ return uses_non_zero_stream;
+ }
+
+ bool uses_end_primitive()
+ {
+ return end_primitive_found;
}
private:
- bool found;
+ int max_stream_allowed;
+ int invalid_stream_id;
+ bool invalid_stream_id_from_emit_vertex;
+ bool end_primitive_found;
+ bool uses_non_zero_stream;
};
} /* anonymous namespace */
@@ -551,10 +620,58 @@ validate_geometry_shader_executable(struct gl_shader_program *prog,
analyze_clip_usage(prog, shader, &prog->Geom.UsesClipDistance,
&prog->Geom.ClipDistanceArraySize);
+}
+
+/**
+ * Check if geometry shaders emit to non-zero streams and do corresponding
+ * validations.
+ */
+static void
+validate_geometry_shader_emissions(struct gl_context *ctx,
+ struct gl_shader_program *prog)
+{
+ if (prog->_LinkedShaders[MESA_SHADER_GEOMETRY] != NULL) {
+ find_emit_vertex_visitor emit_vertex(ctx->Const.MaxVertexStreams - 1);
+ emit_vertex.run(prog->_LinkedShaders[MESA_SHADER_GEOMETRY]->ir);
+ if (emit_vertex.error()) {
+ linker_error(prog, "Invalid call %s(%d). Accepted values for the "
+ "stream parameter are in the range [0, %d].",
+ emit_vertex.error_func(),
+ emit_vertex.error_stream(),
+ ctx->Const.MaxVertexStreams - 1);
+ }
+ prog->Geom.UsesStreams = emit_vertex.uses_streams();
+ prog->Geom.UsesEndPrimitive = emit_vertex.uses_end_primitive();
- find_end_primitive_visitor end_primitive;
- end_primitive.run(shader->ir);
- prog->Geom.UsesEndPrimitive = end_primitive.end_primitive_found();
+ /* From the ARB_gpu_shader5 spec:
+ *
+ * "Multiple vertex streams are supported only if the output primitive
+ * type is declared to be "points". A program will fail to link if it
+ * contains a geometry shader calling EmitStreamVertex() or
+ * EndStreamPrimitive() if its output primitive type is not "points".
+ *
+ * However, in the same spec:
+ *
+ * "The function EmitVertex() is equivalent to calling EmitStreamVertex()
+ * with <stream> set to zero."
+ *
+ * And:
+ *
+ * "The function EndPrimitive() is equivalent to calling
+ * EndStreamPrimitive() with <stream> set to zero."
+ *
+ * Since we can call EmitVertex() and EndPrimitive() when we output
+ * primitives other than points, calling EmitStreamVertex(0) or
+ * EmitEndPrimitive(0) should not produce errors. This it also what Nvidia
+ * does. Currently we only set prog->Geom.UsesStreams to TRUE when
+ * EmitStreamVertex() or EmitEndPrimitive() are called with a non-zero
+ * stream.
+ */
+ if (prog->Geom.UsesStreams && prog->Geom.OutputType != GL_POINTS) {
+ linker_error(prog, "EmitStreamVertex(n) and EndStreamPrimitive(n) "
+ "with n>0 requires point output");
+ }
+ }
}
@@ -1479,6 +1596,8 @@ link_intrastage_shaders(void *mem_ctx,
const unsigned num_uniform_blocks =
link_uniform_blocks(mem_ctx, prog, shader_list, num_shaders,
&uniform_blocks);
+ if (!prog->LinkStatus)
+ return NULL;
/* Check that there is only a single definition of each function signature
* across all shaders.
@@ -2556,6 +2675,9 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
;
}
+ /* Check and validate stream emissions in geometry shaders */
+ validate_geometry_shader_emissions(ctx, prog);
+
/* Mark all generic shader inputs and outputs as unpaired. */
for (unsigned i = MESA_SHADER_VERTEX; i <= MESA_SHADER_FRAGMENT; i++) {
if (prog->_LinkedShaders[i] != NULL) {
diff --git a/mesalib/src/glsl/lower_output_reads.cpp b/mesalib/src/glsl/lower_output_reads.cpp
index afe17766b..1ee815d5e 100644
--- a/mesalib/src/glsl/lower_output_reads.cpp
+++ b/mesalib/src/glsl/lower_output_reads.cpp
@@ -52,7 +52,7 @@ public:
output_read_remover();
~output_read_remover();
virtual ir_visitor_status visit(class ir_dereference_variable *);
- virtual ir_visitor_status visit(class ir_emit_vertex *);
+ virtual ir_visitor_status visit_leave(class ir_emit_vertex *);
virtual ir_visitor_status visit_leave(class ir_return *);
virtual ir_visitor_status visit_leave(class ir_function_signature *);
};
@@ -148,7 +148,7 @@ output_read_remover::visit_leave(ir_return *ir)
}
ir_visitor_status
-output_read_remover::visit(ir_emit_vertex *ir)
+output_read_remover::visit_leave(ir_emit_vertex *ir)
{
hash_table_call_foreach(replacements, emit_return_copy, ir);
hash_table_clear(replacements);
diff --git a/mesalib/src/glsl/lower_packed_varyings.cpp b/mesalib/src/glsl/lower_packed_varyings.cpp
index e8654748f..eda56a97b 100644
--- a/mesalib/src/glsl/lower_packed_varyings.cpp
+++ b/mesalib/src/glsl/lower_packed_varyings.cpp
@@ -613,7 +613,7 @@ public:
explicit lower_packed_varyings_gs_splicer(void *mem_ctx,
const exec_list *instructions);
- virtual ir_visitor_status visit(ir_emit_vertex *ev);
+ virtual ir_visitor_status visit_leave(ir_emit_vertex *ev);
private:
/**
@@ -637,7 +637,7 @@ lower_packed_varyings_gs_splicer::lower_packed_varyings_gs_splicer(
ir_visitor_status
-lower_packed_varyings_gs_splicer::visit(ir_emit_vertex *ev)
+lower_packed_varyings_gs_splicer::visit_leave(ir_emit_vertex *ev)
{
foreach_list(node, this->instructions) {
ir_instruction *ir = (ir_instruction *) node;
diff --git a/mesalib/src/glsl/opt_dead_code_local.cpp b/mesalib/src/glsl/opt_dead_code_local.cpp
index c27c526f9..88895fb0e 100644
--- a/mesalib/src/glsl/opt_dead_code_local.cpp
+++ b/mesalib/src/glsl/opt_dead_code_local.cpp
@@ -114,7 +114,7 @@ public:
return visit_continue_with_parent;
}
- virtual ir_visitor_status visit(ir_emit_vertex *)
+ virtual ir_visitor_status visit_leave(ir_emit_vertex *)
{
/* For the purpose of dead code elimination, emitting a vertex counts as
* "reading" all of the currently assigned output variables.