[Mesa-dev] [PATCH 24/46] glsl: make lower_clip_distance work with tessellation shaders.

Dave Airlie airlied at gmail.com
Tue Jul 21 16:19:51 PDT 2015


On 17 June 2015 at 09:01, Marek Olšák <maraeo at gmail.com> wrote:
> From: Fabian Bieler <fabianbieler at fastmail.fm>

Reviewed-by: Dave Airlie <airlied at redhat.com>
>
> ---
>  src/glsl/lower_clip_distance.cpp | 185 ++++++++++++++++++++++-----------------
>  1 file changed, 105 insertions(+), 80 deletions(-)
>
> diff --git a/src/glsl/lower_clip_distance.cpp b/src/glsl/lower_clip_distance.cpp
> index 01f028b..1ada215 100644
> --- a/src/glsl/lower_clip_distance.cpp
> +++ b/src/glsl/lower_clip_distance.cpp
> @@ -55,9 +55,9 @@ namespace {
>  class lower_clip_distance_visitor : public ir_rvalue_visitor {
>  public:
>     explicit lower_clip_distance_visitor(gl_shader_stage shader_stage)
> -      : progress(false), old_clip_distance_1d_var(NULL),
> -        old_clip_distance_2d_var(NULL), new_clip_distance_1d_var(NULL),
> -        new_clip_distance_2d_var(NULL), shader_stage(shader_stage)
> +      : progress(false), old_clip_distance_out_var(NULL),
> +        old_clip_distance_in_var(NULL), new_clip_distance_out_var(NULL),
> +        new_clip_distance_in_var(NULL), shader_stage(shader_stage)
>     {
>     }
>
> @@ -80,20 +80,21 @@ public:
>      *
>      * Note:
>      *
> -    * - the 2d_var is for geometry shader input only.
> +    * - the in_var is for geometry and both tessellation shader inputs only.
>      *
> -    * - since gl_ClipDistance is available in geometry shaders as both an
> -    *   input and an output, it's possible for both old_clip_distance_1d_var
> -    *   and old_clip_distance_2d_var to be non-null.
> +    * - since gl_ClipDistance is available in tessellation control,
> +    *   tessellation evaluation and geometry shaders as both an input
> +    *   and an output, it's possible for both old_clip_distance_out_var
> +    *   and old_clip_distance_in_var to be non-null.
>      */
> -   ir_variable *old_clip_distance_1d_var;
> -   ir_variable *old_clip_distance_2d_var;
> +   ir_variable *old_clip_distance_out_var;
> +   ir_variable *old_clip_distance_in_var;
>
>     /**
>      * Pointer to the newly-created gl_ClipDistanceMESA variable.
>      */
> -   ir_variable *new_clip_distance_1d_var;
> -   ir_variable *new_clip_distance_2d_var;
> +   ir_variable *new_clip_distance_out_var;
> +   ir_variable *new_clip_distance_in_var;
>
>     /**
>      * Type of shader we are compiling (e.g. MESA_SHADER_VERTEX)
> @@ -110,62 +111,81 @@ public:
>  ir_visitor_status
>  lower_clip_distance_visitor::visit(ir_variable *ir)
>  {
> +   ir_variable **old_var;
> +   ir_variable **new_var;
> +
>     if (!ir->name || strcmp(ir->name, "gl_ClipDistance") != 0)
>        return visit_continue;
>     assert (ir->type->is_array());
>
> -   if (!ir->type->fields.array->is_array()) {
> -      /* 1D gl_ClipDistance (used for vertex and geometry output, and fragment
> -       * input).
> -       */
> -      if (this->old_clip_distance_1d_var)
> +   if (ir->data.mode == ir_var_shader_out) {
> +      if (this->old_clip_distance_out_var)
> +         return visit_continue;
> +      old_var = &old_clip_distance_out_var;
> +      new_var = &new_clip_distance_out_var;
> +   } else if (ir->data.mode == ir_var_shader_in) {
> +      if (this->old_clip_distance_in_var)
>           return visit_continue;
> +      old_var = &old_clip_distance_in_var;
> +      new_var = &new_clip_distance_in_var;
> +   } else {
> +      unreachable("not reached");
> +   }
>
> -      this->progress = true;
> -      this->old_clip_distance_1d_var = ir;
> +   this->progress = true;
> +
> +   if (!ir->type->fields.array->is_array()) {
> +      /* gl_ClipDistance (used for vertex, tessellation evaluation and
> +       * geometry output, and fragment input).
> +       */
> +      assert((ir->data.mode == ir_var_shader_in &&
> +              this->shader_stage == MESA_SHADER_FRAGMENT) ||
> +             (ir->data.mode == ir_var_shader_out &&
> +              (this->shader_stage == MESA_SHADER_VERTEX ||
> +               this->shader_stage == MESA_SHADER_TESS_EVAL ||
> +               this->shader_stage == MESA_SHADER_GEOMETRY)));
> +
> +      *old_var = ir;
>        assert (ir->type->fields.array == glsl_type::float_type);
>        unsigned new_size = (ir->type->array_size() + 3) / 4;
>
>        /* Clone the old var so that we inherit all of its properties */
> -      this->new_clip_distance_1d_var = ir->clone(ralloc_parent(ir), NULL);
> +      *new_var = ir->clone(ralloc_parent(ir), NULL);
>
>        /* And change the properties that we need to change */
> -      this->new_clip_distance_1d_var->name
> -         = ralloc_strdup(this->new_clip_distance_1d_var,
> -                         "gl_ClipDistanceMESA");
> -      this->new_clip_distance_1d_var->type
> -         = glsl_type::get_array_instance(glsl_type::vec4_type, new_size);
> -      this->new_clip_distance_1d_var->data.max_array_access
> -         = ir->data.max_array_access / 4;
> -
> -      ir->replace_with(this->new_clip_distance_1d_var);
> +      (*new_var)->name = ralloc_strdup(*new_var, "gl_ClipDistanceMESA");
> +      (*new_var)->type = glsl_type::get_array_instance(glsl_type::vec4_type,
> +                                                       new_size);
> +      (*new_var)->data.max_array_access = ir->data.max_array_access / 4;
> +
> +      ir->replace_with(*new_var);
>     } else {
> -      /* 2D gl_ClipDistance (used for geometry input). */
> -      assert(ir->data.mode == ir_var_shader_in &&
> -             this->shader_stage == MESA_SHADER_GEOMETRY);
> -      if (this->old_clip_distance_2d_var)
> -         return visit_continue;
> +      /* 2D gl_ClipDistance (used for tessellation control, tessellation
> +       * evaluation and geometry input, and tessellation control output).
> +       */
> +      assert((ir->data.mode == ir_var_shader_in &&
> +              (this->shader_stage == MESA_SHADER_GEOMETRY ||
> +               this->shader_stage == MESA_SHADER_TESS_EVAL)) ||
> +             this->shader_stage == MESA_SHADER_TESS_CTRL);
>
> -      this->progress = true;
> -      this->old_clip_distance_2d_var = ir;
> +      *old_var = ir;
>        assert (ir->type->fields.array->fields.array == glsl_type::float_type);
>        unsigned new_size = (ir->type->fields.array->array_size() + 3) / 4;
>
>        /* Clone the old var so that we inherit all of its properties */
> -      this->new_clip_distance_2d_var = ir->clone(ralloc_parent(ir), NULL);
> +      *new_var = ir->clone(ralloc_parent(ir), NULL);
>
>        /* And change the properties that we need to change */
> -      this->new_clip_distance_2d_var->name
> -         = ralloc_strdup(this->new_clip_distance_2d_var, "gl_ClipDistanceMESA");
> -      this->new_clip_distance_2d_var->type = glsl_type::get_array_instance(
> +      (*new_var)->name = ralloc_strdup(*new_var, "gl_ClipDistanceMESA");
> +      (*new_var)->type = glsl_type::get_array_instance(
>           glsl_type::get_array_instance(glsl_type::vec4_type,
>              new_size),
>           ir->type->array_size());
> -      this->new_clip_distance_2d_var->data.max_array_access
> -         = ir->data.max_array_access / 4;
> +      (*new_var)->data.max_array_access = ir->data.max_array_access / 4;
>
> -      ir->replace_with(this->new_clip_distance_2d_var);
> +      ir->replace_with(*new_var);
>     }
> +
>     return visit_continue;
>  }
>
> @@ -242,26 +262,27 @@ lower_clip_distance_visitor::is_clip_distance_vec8(ir_rvalue *ir)
>  {
>     /* Note that geometry shaders contain gl_ClipDistance both as an input
>      * (which is a 2D array) and an output (which is a 1D array), so it's
> -    * possible for both this->old_clip_distance_1d_var and
> -    * this->old_clip_distance_2d_var to be non-NULL in the same shader.
> +    * possible for both this->old_clip_distance_out_var and
> +    * this->old_clip_distance_in_var to be non-NULL in the same shader.
>      */
>
> -   if (this->old_clip_distance_1d_var) {
> -      ir_dereference_variable *var_ref = ir->as_dereference_variable();
> -      if (var_ref && var_ref->var == this->old_clip_distance_1d_var)
> +   if (!ir->type->is_array())
> +      return false;
> +   if (ir->type->fields.array != glsl_type::float_type)
> +      return false;
> +
> +   if (this->old_clip_distance_out_var) {
> +      if (ir->variable_referenced() == this->old_clip_distance_out_var)
>           return true;
>     }
> -   if (this->old_clip_distance_2d_var) {
> -      /* 2D clip distance is only possible as a geometry input */
> -      assert(this->shader_stage == MESA_SHADER_GEOMETRY);
> +   if (this->old_clip_distance_in_var) {
> +      assert(this->shader_stage == MESA_SHADER_TESS_CTRL ||
> +             this->shader_stage == MESA_SHADER_TESS_EVAL ||
> +             this->shader_stage == MESA_SHADER_GEOMETRY ||
> +             this->shader_stage == MESA_SHADER_FRAGMENT);
>
> -      ir_dereference_array *array_ref = ir->as_dereference_array();
> -      if (array_ref) {
> -         ir_dereference_variable *var_ref =
> -            array_ref->array->as_dereference_variable();
> -         if (var_ref && var_ref->var == this->old_clip_distance_2d_var)
> -            return true;
> -      }
> +      if (ir->variable_referenced() == this->old_clip_distance_in_var)
> +         return true;
>     }
>     return false;
>  }
> @@ -279,29 +300,33 @@ lower_clip_distance_visitor::is_clip_distance_vec8(ir_rvalue *ir)
>  ir_rvalue *
>  lower_clip_distance_visitor::lower_clip_distance_vec8(ir_rvalue *ir)
>  {
> -   if (this->old_clip_distance_1d_var) {
> -      ir_dereference_variable *var_ref = ir->as_dereference_variable();
> -      if (var_ref && var_ref->var == this->old_clip_distance_1d_var) {
> -         return new(ralloc_parent(ir))
> -            ir_dereference_variable(this->new_clip_distance_1d_var);
> -      }
> +   if (!ir->type->is_array())
> +      return NULL;
> +   if (ir->type->fields.array != glsl_type::float_type)
> +      return NULL;
> +
> +   ir_variable **new_var = NULL;
> +   if (this->old_clip_distance_out_var) {
> +      if (ir->variable_referenced() == this->old_clip_distance_out_var)
> +         new_var = &this->new_clip_distance_out_var;
> +   }
> +   if (this->old_clip_distance_in_var) {
> +      if (ir->variable_referenced() == this->old_clip_distance_in_var)
> +         new_var = &this->new_clip_distance_in_var;
>     }
> -   if (this->old_clip_distance_2d_var) {
> -      /* 2D clip distance is only possible as a geometry input */
> -      assert(this->shader_stage == MESA_SHADER_GEOMETRY);
> +   if (new_var == NULL)
> +      return NULL;
>
> +   if (ir->as_dereference_variable()) {
> +      return new(ralloc_parent(ir)) ir_dereference_variable(*new_var);
> +   } else {
>        ir_dereference_array *array_ref = ir->as_dereference_array();
> -      if (array_ref) {
> -         ir_dereference_variable *var_ref =
> -            array_ref->array->as_dereference_variable();
> -         if (var_ref && var_ref->var == this->old_clip_distance_2d_var) {
> -            return new(ralloc_parent(ir))
> -               ir_dereference_array(this->new_clip_distance_2d_var,
> -                                    array_ref->array_index);
> -         }
> -      }
> +      assert(array_ref);
> +      assert(array_ref->array->as_dereference_variable());
> +
> +      return new(ralloc_parent(ir))
> +         ir_dereference_array(*new_var, array_ref->array_index);
>     }
> -   return NULL;
>  }
>
>
> @@ -540,10 +565,10 @@ lower_clip_distance(gl_shader *shader)
>
>     visit_list_elements(&v, shader->ir);
>
> -   if (v.new_clip_distance_1d_var)
> -      shader->symbols->add_variable(v.new_clip_distance_1d_var);
> -   if (v.new_clip_distance_2d_var)
> -      shader->symbols->add_variable(v.new_clip_distance_2d_var);
> +   if (v.new_clip_distance_out_var)
> +      shader->symbols->add_variable(v.new_clip_distance_out_var);
> +   if (v.new_clip_distance_in_var)
> +      shader->symbols->add_variable(v.new_clip_distance_in_var);
>
>     return v.progress;
>  }
> --
> 2.1.0
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev


More information about the mesa-dev mailing list