This is pretty weird. We should be able to generate a normal builtin function body here which consists of just the ir_emit_vertex, passing the stream parameter to it. This would then get inlined like any other function leaving a bare ir_emit_vertex / ir_end_primitive with a constant operand. If one of the optimization passes eats that, then it's broken.
On Wed, Jun 11, 2014 at 7:49 PM, Iago Toral Quiroga <ito...@igalia.com> wrote: > --- > src/glsl/ast_function.cpp | 37 +++++++++++++++++++++----- > src/glsl/builtin_functions.cpp | 60 > ++++++++++++++++++++++++++++++++++++++++++ > src/glsl/ir.h | 18 ++++++++----- > 3 files changed, 103 insertions(+), 12 deletions(-) > > diff --git a/src/glsl/ast_function.cpp b/src/glsl/ast_function.cpp > index 8e91a1e..1c4d7e7 100644 > --- a/src/glsl/ast_function.cpp > +++ b/src/glsl/ast_function.cpp > @@ -1722,15 +1722,40 @@ ast_function_expression::hir(exec_list *instructions, > ir_function_signature *sig = > match_function_by_name(func_name, &actual_parameters, state); > > + bool is_emit_stream_vertex = !strcmp(func_name, "EmitStreamVertex"); > + bool is_end_stream_primitive = !strcmp(func_name, > "EndStreamPrimitive"); > + > ir_rvalue *value = NULL; > if (sig == NULL) { > - no_matching_function_error(func_name, &loc, &actual_parameters, > state); > - value = ir_rvalue::error_value(ctx); > + no_matching_function_error(func_name, &loc, &actual_parameters, > state); > + value = ir_rvalue::error_value(ctx); > } else if (!verify_parameter_modes(state, sig, actual_parameters, > this->expressions)) { > - /* an error has already been emitted */ > - value = ir_rvalue::error_value(ctx); > - } else { > - value = generate_call(instructions, sig, &actual_parameters, state); > + /* an error has already been emitted */ > + value = ir_rvalue::error_value(ctx); > + } else if (is_emit_stream_vertex || is_end_stream_primitive) { > + /* See builtin_builder::_EmitStreamVertex() to undertand why we need > + * to handle these as a special case. > + */ > + ir_rvalue *stream_param = (ir_rvalue *) actual_parameters.head; > + ir_constant *stream_const = stream_param->as_constant(); > + /* stream_const should not be NULL if we got here */ > + assert(stream_const); > + int stream_id = stream_const->value.i[0]; > + if (stream_id < 0 || stream_id >= MAX_VERTEX_STREAMS) { > + _mesa_glsl_error(&loc, state, > + "Invalid call %s(%d). Accepted " > + "values for the stream parameter are in the " > + "range [0, %d].", > + func_name, stream_id, MAX_VERTEX_STREAMS - 1); > + } > + /* Only enable multi-stream if we emit vertices to non-zero streams > */ > + state->gs_uses_streams = state->gs_uses_streams || stream_id > 0; > + if (is_emit_stream_vertex) > + instructions->push_tail(new(ctx) ir_emit_vertex(stream_id)); > + else > + instructions->push_tail(new(ctx) ir_end_primitive(stream_id)); > + } else { > + value = generate_call(instructions, sig, &actual_parameters, state); > } > > return value; > diff --git a/src/glsl/builtin_functions.cpp b/src/glsl/builtin_functions.cpp > index f9f0686..412e8f3 100644 > --- a/src/glsl/builtin_functions.cpp > +++ b/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), > @@ -3878,6 +3896,35 @@ builtin_builder::_EmitVertex() > } > > ir_function_signature * > +builtin_builder::_EmitStreamVertex(builtin_available_predicate avail, > + const glsl_type *stream_type) > +{ > + ir_variable *stream = > + new(mem_ctx) ir_variable(stream_type, "stream", ir_var_const_in); > + > + /* EmitStreamVertex is a special kind of built-in function. It does > + * not really generate any IR when processed, instead, it only adds a > + * marker in the IR to know when we need to generate code for vertex > + * emission, just like EmitVertex(). However, in this case we have > + * an input parameter that we need to preserve and that the dead code > + * optimization passes will kill because it is apparently unused. > + * We will actually use it, but not until code generation time, after > + * the dead code elimination passes have run and kill the input variable. > + * > + * To deal with this situation, since the input parameter for > + * EmitStreamVertex() must be a constant expression, we don't generate a > + * function body here. Then, when we detect EmitVertexStream() calls the > + * AST, instead of producing an ir_call, we get the constant value of > + * the input parameter in that moment and produce a ir_emit_vertex > directly. > + * See ast_function_expression::hir(). > + */ > + > + MAKE_INTRINSIC(glsl_type::void_type, avail, 1, stream); > + > + return sig; > +} > + > +ir_function_signature * > builtin_builder::_EndPrimitive() > { > MAKE_SIG(glsl_type::void_type, gs_only, 0); > @@ -3888,6 +3935,19 @@ builtin_builder::_EndPrimitive() > } > > ir_function_signature * > +builtin_builder::_EndStreamPrimitive(builtin_available_predicate avail, > + const glsl_type *stream_type) > +{ > + ir_variable *stream = > + new(mem_ctx) ir_variable(stream_type, "stream", ir_var_const_in); > + > + /* See comment in builtin_builder::_EmitStreamVertex, same applies here */ > + MAKE_INTRINSIC(glsl_type::void_type, avail, 1, stream); > + > + return sig; > +} > + > +ir_function_signature * > builtin_builder::_textureQueryLod(const glsl_type *sampler_type, > const glsl_type *coord_type) > { > diff --git a/src/glsl/ir.h b/src/glsl/ir.h > index 8cc58af..7ae91ab 100644 > --- a/src/glsl/ir.h > +++ b/src/glsl/ir.h > @@ -2159,8 +2159,9 @@ private: > */ > class ir_emit_vertex : public ir_instruction { > public: > - ir_emit_vertex() > - : ir_instruction(ir_type_emit_vertex) > + ir_emit_vertex(unsigned stream = 0) > + : ir_instruction(ir_type_emit_vertex), > + stream(stream) > { > } > > @@ -2171,10 +2172,12 @@ public: > > virtual ir_emit_vertex *clone(void *mem_ctx, struct hash_table *) const > { > - return new(mem_ctx) ir_emit_vertex(); > + return new(mem_ctx) ir_emit_vertex(stream); > } > > virtual ir_visitor_status accept(ir_hierarchical_visitor *); > + > + unsigned stream; > }; > > /** > @@ -2183,8 +2186,9 @@ public: > */ > class ir_end_primitive : public ir_instruction { > public: > - ir_end_primitive() > - : ir_instruction(ir_type_end_primitive) > + ir_end_primitive(unsigned stream = 0) > + : ir_instruction(ir_type_end_primitive), > + stream(stream) > { > } > > @@ -2195,10 +2199,12 @@ public: > > virtual ir_end_primitive *clone(void *mem_ctx, struct hash_table *) const > { > - return new(mem_ctx) ir_end_primitive(); > + return new(mem_ctx) ir_end_primitive(stream); > } > > virtual ir_visitor_status accept(ir_hierarchical_visitor *); > + > + unsigned stream; > }; > > /*@}*/ > -- > 1.9.1 > > _______________________________________________ > mesa-dev mailing list > mesa-dev@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/mesa-dev _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev