From ee7a6dad302ff5568566e325df56fd582be1afec Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Mon, 18 Mar 2013 14:45:53 -0700 Subject: [PATCH] glsl: Add lowering pass for ir_triop_vector_insert 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. v3: Use a series of scalar compares instead of a single vector compare. Suggested by Eric and Ken. It still uses 'if (cond) v.x = y;' instead of conditional assignments because ir_builder doesn't do conditional assignments, and I'd rather keep the code simple. Signed-off-by: Ian Romanick Reviewed-by: Eric Anholt Reviewed-by: Kenneth Graunke --- src/glsl/Makefile.sources | 1 + src/glsl/glsl_parser_extras.cpp | 1 + src/glsl/ir_optimization.h | 1 + src/glsl/lower_vector_insert.cpp | 139 +++++++++++++++++++++ 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, 145 insertions(+) create mode 100644 src/glsl/lower_vector_insert.cpp diff --git a/src/glsl/Makefile.sources b/src/glsl/Makefile.sources index df03cf806c4..e1112c3572a 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 a6e6dde8564..f7d8f4a4b6c 100644 --- a/src/glsl/glsl_parser_extras.cpp +++ b/src/glsl/glsl_parser_extras.cpp @@ -1243,6 +1243,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 28093cfe1a1..1c3bc60088f 100644 --- a/src/glsl/ir_optimization.h +++ b/src/glsl/ir_optimization.h @@ -109,6 +109,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 00000000000..0e640cc3240 --- /dev/null +++ b/src/glsl/lower_vector_insert.cpp @@ -0,0 +1,139 @@ +/* + * 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"); + + ir_variable *const src_temp = + factory.make_temp(expr->operands[1]->type, "src_temp"); + + factory.emit(assign(temp, expr->operands[0])); + factory.emit(assign(src_temp, expr->operands[1])); + + for (unsigned i = 0; i < expr->type->vector_elements; i++) { + ir_constant *const cmp_index = + new(factory.mem_ctx) ir_constant(int(i)); + + ir_variable *const cmp_result = + factory.make_temp(glsl_type::bool_type, "index_condition"); + + factory.emit(assign(cmp_result, + equal(expr->operands[2]->clone(factory.mem_ctx, + NULL), + cmp_index))); + + factory.emit(if_tree(cmp_result, + assign(temp, src_temp, WRITEMASK_X << i))); + } + + 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 8dcab75a433..03e43297023 100644 --- a/src/mesa/drivers/dri/i965/brw_shader.cpp +++ b/src/mesa/drivers/dri/i965/brw_shader.cpp @@ -174,6 +174,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 e9c332d1543..b3b55a5247c 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -3055,6 +3055,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 d175be602f4..cbd706d6e59 100644 --- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp +++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp @@ -5243,6 +5243,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) { -- 2.30.2