[Mesa-dev] [PATCH v2 11/23] glsl: Add support for EmitStreamVertex() and EndStreamPrimitive().

Ian Romanick idr at freedesktop.org
Wed Jun 18 13:31:46 PDT 2014


This patch should be split into several patches:

1. Modify ir_emit_vertex to have a stream.  This patch also needs to update
ir_to_mesa.cpp and st_glsl_to_tgsi.cpp.

2. Modify ir_end_primitive to have a stream.  This patch also needs to update
ir_to_mesa.cpp and st_glsl_to_tgsi.cpp.

3. Add the new built-in functions.

A couple other minor comments below...

On 06/18/2014 02:51 AM, Iago Toral Quiroga wrote:
> ---
>  src/glsl/builtin_functions.cpp       | 52 ++++++++++++++++++++++++++++++++++--
>  src/glsl/ir.h                        | 34 +++++++++++++++++------
>  src/glsl/ir_hierarchical_visitor.cpp | 50 +++++++++++++++++++++-------------
>  src/glsl/ir_hierarchical_visitor.h   |  6 +++--
>  src/glsl/ir_hv_accept.cpp            | 21 ++++++++++++---
>  src/glsl/ir_rvalue_visitor.cpp       | 37 +++++++++++++++++++++++++
>  src/glsl/ir_rvalue_visitor.h         |  6 +++++
>  src/glsl/lower_output_reads.cpp      |  4 +--
>  src/glsl/lower_packed_varyings.cpp   |  4 +--
>  src/glsl/opt_dead_code_local.cpp     |  2 +-
>  10 files changed, 178 insertions(+), 38 deletions(-)
> 
> diff --git a/src/glsl/builtin_functions.cpp b/src/glsl/builtin_functions.cpp
> index f9f0686..07a0722 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),
> @@ -3872,7 +3890,22 @@ 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)
> +{

Please add a spec quotation for this.  I had to go look it up to be sure
ir_var_const_in was correct.

   /* Section 8.12 (Geometry Shader Functions) of the OpenGL 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_emit_vertex(var_ref(stream)));
>  
>     return sig;
>  }
> @@ -3882,7 +3915,22 @@ 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)
> +{

Same spec reference here.

> +   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/src/glsl/ir.h b/src/glsl/ir.h
> index dbbabb5..ea5ba27 100644
> --- a/src/glsl/ir.h
> +++ b/src/glsl/ir.h
> @@ -2159,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)
> @@ -2169,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;
>  };
>  
>  /**
> @@ -2183,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)
> @@ -2193,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/src/glsl/ir_hierarchical_visitor.cpp b/src/glsl/ir_hierarchical_visitor.cpp
> index 2e606dd..d3c00ec 100644
> --- a/src/glsl/ir_hierarchical_visitor.cpp
> +++ b/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/src/glsl/ir_hierarchical_visitor.h b/src/glsl/ir_hierarchical_visitor.h
> index 647d2e0..bc89a04 100644
> --- a/src/glsl/ir_hierarchical_visitor.h
> +++ b/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/src/glsl/ir_hv_accept.cpp b/src/glsl/ir_hv_accept.cpp
> index 2a1f70e..eed761f 100644
> --- a/src/glsl/ir_hv_accept.cpp
> +++ b/src/glsl/ir_hv_accept.cpp
> @@ -405,12 +405,27 @@ 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/src/glsl/ir_rvalue_visitor.cpp b/src/glsl/ir_rvalue_visitor.cpp
> index fcbe944..0370170 100644
> --- a/src/glsl/ir_rvalue_visitor.cpp
> +++ b/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/src/glsl/ir_rvalue_visitor.h b/src/glsl/ir_rvalue_visitor.h
> index 2179fa5..04ec0fa 100644
> --- a/src/glsl/ir_rvalue_visitor.h
> +++ b/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/src/glsl/lower_output_reads.cpp b/src/glsl/lower_output_reads.cpp
> index afe1776..1ee815d 100644
> --- a/src/glsl/lower_output_reads.cpp
> +++ b/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/src/glsl/lower_packed_varyings.cpp b/src/glsl/lower_packed_varyings.cpp
> index e865474..eda56a9 100644
> --- a/src/glsl/lower_packed_varyings.cpp
> +++ b/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/src/glsl/opt_dead_code_local.cpp b/src/glsl/opt_dead_code_local.cpp
> index c27c526..88895fb 100644
> --- a/src/glsl/opt_dead_code_local.cpp
> +++ b/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.
> 



More information about the mesa-dev mailing list