[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