From: Ian Romanick <ian.d.roman...@intel.com> This will eventually replace do_vec_index_to_cond_assign. This lowering pass is called in all the places where do_vec_index_to_cond_assign or do_vec_index_to_swizzle is called.
v2: Use WRITEMASK_* instead of integer literals. Use a more concise method of generating broadcast_index. Both suggested by Eric. Signed-off-by: Ian Romanick <ian.d.roman...@intel.com> Reviewed-by: Eric Anholt <e...@anholt.net> --- src/glsl/Makefile.sources | 1 + src/glsl/glsl_parser_extras.cpp | 1 + src/glsl/ir_optimization.h | 1 + src/glsl/lower_vector_insert.cpp | 160 +++++++++++++++++++++++++++++ src/mesa/drivers/dri/i965/brw_shader.cpp | 1 + src/mesa/program/ir_to_mesa.cpp | 1 + src/mesa/state_tracker/st_glsl_to_tgsi.cpp | 1 + 7 files changed, 166 insertions(+) create mode 100644 src/glsl/lower_vector_insert.cpp diff --git a/src/glsl/Makefile.sources b/src/glsl/Makefile.sources index 674a05f..8e2dc1b 100644 --- a/src/glsl/Makefile.sources +++ b/src/glsl/Makefile.sources @@ -69,6 +69,7 @@ LIBGLSL_FILES = \ $(GLSL_SRCDIR)/lower_vec_index_to_cond_assign.cpp \ $(GLSL_SRCDIR)/lower_vec_index_to_swizzle.cpp \ $(GLSL_SRCDIR)/lower_vector.cpp \ + $(GLSL_SRCDIR)/lower_vector_insert.cpp \ $(GLSL_SRCDIR)/lower_output_reads.cpp \ $(GLSL_SRCDIR)/lower_ubo_reference.cpp \ $(GLSL_SRCDIR)/opt_algebraic.cpp \ diff --git a/src/glsl/glsl_parser_extras.cpp b/src/glsl/glsl_parser_extras.cpp index 0992294..d38e967 100644 --- a/src/glsl/glsl_parser_extras.cpp +++ b/src/glsl/glsl_parser_extras.cpp @@ -1236,6 +1236,7 @@ do_common_optimization(exec_list *ir, bool linked, progress = do_algebraic(ir) || progress; progress = do_lower_jumps(ir) || progress; progress = do_vec_index_to_swizzle(ir) || progress; + progress = lower_vector_insert(ir, false) || progress; progress = do_swizzle_swizzle(ir) || progress; progress = do_noop_swizzle(ir) || progress; diff --git a/src/glsl/ir_optimization.h b/src/glsl/ir_optimization.h index a8885d7..0216e46 100644 --- a/src/glsl/ir_optimization.h +++ b/src/glsl/ir_optimization.h @@ -106,6 +106,7 @@ void lower_ubo_reference(struct gl_shader *shader, exec_list *instructions); void lower_packed_varyings(void *mem_ctx, unsigned location_base, unsigned locations_used, ir_variable_mode mode, gl_shader *shader); +bool lower_vector_insert(exec_list *instructions, bool lower_nonconstant_index); bool optimize_redundant_jumps(exec_list *instructions); bool optimize_split_arrays(exec_list *instructions, bool linked); diff --git a/src/glsl/lower_vector_insert.cpp b/src/glsl/lower_vector_insert.cpp new file mode 100644 index 0000000..3dbc263 --- /dev/null +++ b/src/glsl/lower_vector_insert.cpp @@ -0,0 +1,160 @@ +/* + * Copyright © 2013 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ +#include "ir.h" +#include "ir_builder.h" +#include "ir_rvalue_visitor.h" +#include "ir_optimization.h" + +using namespace ir_builder; + +class vector_insert_visitor : public ir_rvalue_visitor { +public: + vector_insert_visitor(bool lower_nonconstant_index) + : progress(false), lower_nonconstant_index(lower_nonconstant_index) + { + factory.instructions = &factory_instructions; + } + + virtual ~vector_insert_visitor() + { + assert(factory_instructions.is_empty()); + } + + virtual void handle_rvalue(ir_rvalue **rv); + + ir_factory factory; + exec_list factory_instructions; + bool progress; + bool lower_nonconstant_index; +}; + + +void +vector_insert_visitor::handle_rvalue(ir_rvalue **rv) +{ + if (*rv == NULL || (*rv)->ir_type != ir_type_expression) + return; + + ir_expression *const expr = (ir_expression *) *rv; + + if (likely(expr->operation != ir_triop_vector_insert)) + return; + + factory.mem_ctx = ralloc_parent(expr); + + ir_constant *const idx = expr->operands[2]->constant_expression_value(); + if (idx != NULL) { + /* Replace (vector_insert (vec) (scalar) (index)) with a dereference of + * a new temporary. The new temporary gets assigned as + * + * t = vec + * t.mask = scalar + * + * where mask is the component selected by index. + */ + ir_variable *const temp = + factory.make_temp(expr->operands[0]->type, "vec_tmp"); + + const int mask = 1 << idx->value.i[0]; + + factory.emit(assign(temp, expr->operands[0])); + factory.emit(assign(temp, expr->operands[1], mask)); + + this->progress = true; + *rv = new(factory.mem_ctx) ir_dereference_variable(temp); + } else if (this->lower_nonconstant_index) { + /* Replace (vector_insert (vec) (scalar) (index)) with a dereference of + * a new temporary. The new temporary gets assigned as + * + * t = vec + * if (index == 0) + * t.x = scalar + * if (index == 1) + * t.y = scalar + * if (index == 2) + * t.z = scalar + * if (index == 3) + * t.w = scalar + */ + ir_variable *const temp = + factory.make_temp(expr->operands[0]->type, "vec_tmp"); + + const unsigned components = expr->type->vector_elements; + + ir_constant_data cmp_indices_data; + memset(&cmp_indices_data, 0, sizeof(cmp_indices_data)); + cmp_indices_data.i[0] = 0; + cmp_indices_data.i[1] = 1; + cmp_indices_data.i[2] = 2; + cmp_indices_data.i[3] = 3; + + ir_constant *const cmp_indices = + new(factory.mem_ctx) ir_constant(glsl_type::get_instance(GLSL_TYPE_INT, + components, + 1), + &cmp_indices_data); + + ir_variable *const cmp_result = + factory.make_temp(glsl_type::get_instance(GLSL_TYPE_BOOL, + components, + 1), + "index_condition"); + + ir_variable *const src_temp = + factory.make_temp(expr->operands[1]->type, "src_temp"); + + ir_rvalue *broadcast_index = + swizzle_for_size(swizzle_xxxx(expr->operands[2]), components); + + factory.emit(assign(temp, expr->operands[0])); + factory.emit(assign(src_temp, expr->operands[1])); + factory.emit(assign(cmp_result, equal(broadcast_index, cmp_indices))); + factory.emit(if_tree(swizzle_x(cmp_result), + assign(temp, src_temp, WRITEMASK_X))); + factory.emit(if_tree(swizzle_y(cmp_result), + assign(temp, src_temp, WRITEMASK_Y))); + + if (components > 2) + factory.emit(if_tree(swizzle_z(cmp_result), + assign(temp, src_temp, WRITEMASK_Z))); + + if (components > 3) + factory.emit(if_tree(swizzle_w(cmp_result), + assign(temp, src_temp, WRITEMASK_W))); + + this->progress = true; + *rv = new(factory.mem_ctx) ir_dereference_variable(temp); + } + + base_ir->insert_before(factory.instructions); +} + +bool +lower_vector_insert(exec_list *instructions, bool lower_nonconstant_index) +{ + vector_insert_visitor v(lower_nonconstant_index); + + visit_list_elements(&v, instructions); + + return v.progress; +} diff --git a/src/mesa/drivers/dri/i965/brw_shader.cpp b/src/mesa/drivers/dri/i965/brw_shader.cpp index 75468b1..6dd1419 100644 --- a/src/mesa/drivers/dri/i965/brw_shader.cpp +++ b/src/mesa/drivers/dri/i965/brw_shader.cpp @@ -170,6 +170,7 @@ brw_link_shader(struct gl_context *ctx, struct gl_shader_program *shProg) do_lower_texture_projection(shader->ir); brw_lower_texture_gradients(intel, shader->ir); do_vec_index_to_cond_assign(shader->ir); + lower_vector_insert(shader->ir, true); brw_do_cubemap_normalize(shader->ir); lower_noise(shader->ir); lower_quadop_vector(shader->ir, false); diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index eb64347..bcc8af6 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -3041,6 +3041,7 @@ _mesa_ir_link_shader(struct gl_context *ctx, struct gl_shader_program *prog) || progress; progress = do_vec_index_to_cond_assign(ir) || progress; + progress = lower_vector_insert(ir, true) || progress; } while (progress); validate_ir_tree(ir); diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp index f2eb3e7..5ec9c41 100644 --- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp +++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp @@ -5233,6 +5233,7 @@ st_link_shader(struct gl_context *ctx, struct gl_shader_program *prog) lower_ubo_reference(prog->_LinkedShaders[i], ir); do_vec_index_to_cond_assign(ir); + lower_vector_insert(ir, true); lower_quadop_vector(ir, false); lower_noise(ir); if (options->MaxIfDepth == 0) { -- 1.8.1.4 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev