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. _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev