[Mesa-dev] [PATCH 26/28] glsl: lower tessellation varyings packed with component layout qualifier
Timothy Arceri
timothy.arceri at collabora.com
Tue Dec 29 01:35:07 PST 2015
On Tue, 2015-12-29 at 16:00 +1100, Timothy Arceri wrote:
> For tessellation shaders we cannot just copy everything to the packed
> varyings like we do in other stages as tessellation uses shared
> memory for
> varyings, therefore it is only safe to copy array elements that the
> shader
> actually uses.
>
> This class searches the IR for uses of varyings and then creates
> instructions that copy those vars to a packed varying. This means it
> is
> easy to end up with duplicate copies if the varying is used more than
> once,
> also arrays of arrays create a duplicate copy for each dimension that
> exists. These issues are not easily resolved without breaking various
> corner cases so we leave it to a later IR stage to clean up the mess.
>
> Note that neither GLSL IR nor NIR can currently can't clean up the
> duplicates when and indirect is used as an array index. This patch
> assumes that NIR will eventually be able to clean this up.
> ---
> src/glsl/lower_packed_varyings.cpp | 421
> +++++++++++++++++++++++++++++++++++++
> 1 file changed, 421 insertions(+)
>
> diff --git a/src/glsl/lower_packed_varyings.cpp
> b/src/glsl/lower_packed_varyings.cpp
> index b606cc8..9522969 100644
> --- a/src/glsl/lower_packed_varyings.cpp
> +++ b/src/glsl/lower_packed_varyings.cpp
> @@ -148,10 +148,28 @@
> #include "ir.h"
> #include "ir_builder.h"
> #include "ir_optimization.h"
> +#include "ir_rvalue_visitor.h"
> #include "program/prog_instruction.h"
> +#include "util/hash_table.h"
>
> using namespace ir_builder;
>
> +/**
> + * Creates new type for and array when the base type changes.
> + */
> +static const glsl_type *
> +update_packed_array_type(const glsl_type *type, const glsl_type
> *packed_type)
> +{
> + const glsl_type *element_type = type->fields.array;
> + if (element_type->is_array()) {
> + const glsl_type *new_array_type =
> + update_packed_array_type(element_type, packed_type);
> + return glsl_type::get_array_instance(new_array_type, type
> ->length);
> + } else {
> + return glsl_type::get_array_instance(packed_type, type
> ->length);
> + }
> +}
> +
> static bool
> needs_lowering(ir_variable *var, bool has_enhanced_layouts,
> bool disable_varying_packing)
> @@ -205,6 +223,51 @@ create_packed_var(void * const mem_ctx, const
> char *packed_name,
> return packed_var;
> }
>
> +/**
> + * Creates a packed varying for the tessellation packing.
> + */
> +static ir_variable *
> +create_tess_packed_var(void *mem_ctx, ir_variable *unpacked_var)
> +{
> + /* create packed varying name using location */
> + char location_str[11];
> + snprintf(location_str, 11, "%d", unpacked_var->data.location);
> + char *packed_name;
> + if ((ir_variable_mode) unpacked_var->data.mode ==
> ir_var_shader_out)
> + packed_name = ralloc_asprintf(mem_ctx, "packed_out:%s",
> location_str);
> + else
> + packed_name = ralloc_asprintf(mem_ctx, "packed_in:%s",
> location_str);
> +
> + const glsl_type *packed_type;
> + switch (unpacked_var->type->without_array()->base_type) {
> + case GLSL_TYPE_UINT:
> + packed_type = glsl_type::uvec4_type;
> + break;
> + case GLSL_TYPE_INT:
> + packed_type = glsl_type::ivec4_type;
> + break;
> + case GLSL_TYPE_FLOAT:
> + packed_type = glsl_type::vec4_type;
> + break;
> + case GLSL_TYPE_DOUBLE:
> + packed_type = glsl_type::dvec4_type;
> + break;
> + default:
> + assert(!"Unexpected type in tess varying packing");
> + return NULL;
> + }
> +
> + /* Create array new array type */
> + if (unpacked_var->type->is_array()) {
> + packed_type = update_packed_array_type(unpacked_var->type,
> packed_type);
> + }
> +
> + return create_packed_var(mem_ctx, packed_name, packed_type,
> unpacked_var,
> + (ir_variable_mode) unpacked_var
> ->data.mode,
> + unpacked_var->data.location,
> + unpacked_var->type->is_array());
> +}
> +
> namespace {
>
> /**
> @@ -763,6 +826,296 @@
> lower_packed_varyings_gs_splicer::visit_leave(ir_emit_vertex *ev)
> }
>
>
> +/**
> + * For tessellation shaders we cannot just copy everything to the
> packed
> + * varyings like we do in other stages as tessellation uses shared
> memory for
> + * varyings, therefore it is only safe to copy array elements that
> the shader
> + * actually uses.
> + *
> + * This class searches the IR for uses of varyings and then creates
> + * instructions that copy those vars to a packed varying. This means
> it is
> + * easy to end up with duplicate copies if the varying is used more
> than once,
> + * also arrays of arrays create a duplicate copy for each dimension
> that
> + * exists. These issues are not easily resolved without breaking
> various
> + * corner cases so we leave it to a later IR stage to clean up the
> mess.
> + */
> +class lower_packed_varyings_tess_visitor : public ir_rvalue_visitor
> +{
> +public:
> + lower_packed_varyings_tess_visitor(void *mem_ctx, hash_table
> *varyings,
> + ir_variable_mode mode)
> + : mem_ctx(mem_ctx), varyings(varyings), mode(mode)
> + {
> + }
> +
> + virtual ~lower_packed_varyings_tess_visitor()
> + {
> + }
> +
> + virtual ir_visitor_status visit_leave(ir_assignment *);
> + virtual ir_visitor_status visit_leave(ir_dereference_array *);
> +
> + ir_dereference *create_dereference(ir_dereference *deref,
> + unsigned *dimensions);
> + unsigned create_extra_array_dereference(unsigned inner_dimension,
> + const glsl_type
> **types_list,
> + ir_dereference
> **packed_deref_list,
> + ir_dereference
> **deref_list);
> + ir_variable *get_packed_var(ir_variable *var);
> + void handle_rvalue(ir_rvalue **rvalue);
> +
> + /**
> + * Exec list into which the visitor should insert the packing
> instructions.
> + * Caller provides this list; it should insert the instructions
> into the
> + * appropriate place in the shader once the visitor has finished
> running.
> + */
> + exec_list new_instructions;
> +
> +private:
> + /**
> + * Memory context used to allocate new instructions for the
> shader.
> + */
> + void * const mem_ctx;
> +
> + hash_table *varyings;
> +
> + ir_variable_mode mode;
> +};
> +
> +/**
> + * Search the hash table for a packed varying for this variable.
> + */
> +ir_variable *
> +lower_packed_varyings_tess_visitor::get_packed_var(ir_variable *var)
> +{
> + assert(var);
> +
> + const struct hash_entry *entry =
> + _mesa_hash_table_search(varyings, var);
> +
> + return entry ? (ir_variable *) entry->data : NULL;
> +}
> +
> +ir_dereference *
> +lower_packed_varyings_tess_visitor::create_dereference(ir_dereferenc
> e *deref,
> + unsigned
> *dimension)
> +{
> + ir_dereference_array *deref_array = deref
> ->as_dereference_array();
> + if (deref_array) {
> + (*dimension)--;
> + ir_dereference *array =
> + create_dereference(deref_array->array->as_dereference(),
> dimension);
> + return new(this->mem_ctx)
> + ir_dereference_array(array, deref_array->array_index);
The array_index needs to be cloned here I've fixed this locally.
More information about the mesa-dev
mailing list