From 7b1f97ce5d74b04221db6da29fb31fe500335c73 Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Sat, 26 Apr 2014 00:18:54 -0700 Subject: [PATCH] glsl: Lower constant arrays to uniform arrays. XXX: We should probably make this optional; I don't know if other drivers want it or not. Probably worth asking on mesa-dev. XXX: Not sure about the max_array_access code. without it, the uniform gets chopped down to length 1 for some reason. XXX: This changes the const-ness of the expression. Is that a problem? Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=77957 Signed-off-by: Kenneth Graunke --- src/glsl/Makefile.sources | 1 + src/glsl/ir_optimization.h | 1 + src/glsl/linker.cpp | 2 + src/glsl/lower_const_arrays_to_uniforms.cpp | 101 ++++++++++++++++++++++++++++ 4 files changed, 105 insertions(+) create mode 100644 src/glsl/lower_const_arrays_to_uniforms.cpp diff --git a/src/glsl/Makefile.sources b/src/glsl/Makefile.sources index 5945590..9ec2f25 100644 --- a/src/glsl/Makefile.sources +++ b/src/glsl/Makefile.sources @@ -59,6 +59,7 @@ LIBGLSL_FILES = \ $(GLSL_SRCDIR)/loop_analysis.cpp \ $(GLSL_SRCDIR)/loop_controls.cpp \ $(GLSL_SRCDIR)/loop_unroll.cpp \ + $(GLSL_SRCDIR)/lower_const_arrays_to_uniforms.cpp \ $(GLSL_SRCDIR)/lower_clip_distance.cpp \ $(GLSL_SRCDIR)/lower_discard.cpp \ $(GLSL_SRCDIR)/lower_discard_flow.cpp \ diff --git a/src/glsl/ir_optimization.h b/src/glsl/ir_optimization.h index 40bb613..0bcaf86 100644 --- a/src/glsl/ir_optimization.h +++ b/src/glsl/ir_optimization.h @@ -108,6 +108,7 @@ bool lower_noise(exec_list *instructions); bool lower_variable_index_to_cond_assign(exec_list *instructions, bool lower_input, bool lower_output, bool lower_temp, bool lower_uniform); bool lower_quadop_vector(exec_list *instructions, bool dont_lower_swz); +bool lower_const_arrays_to_uniforms(exec_list *instructions); bool lower_clip_distance(gl_shader *shader); void lower_output_reads(exec_list *instructions); bool lower_packing_builtins(exec_list *instructions, int op_mask); diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp index c2f7f48..fd5035b 100644 --- a/src/glsl/linker.cpp +++ b/src/glsl/linker.cpp @@ -2300,6 +2300,8 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) &ctx->ShaderCompilerOptions[i], ctx->Const.NativeIntegers)) ; + + lower_const_arrays_to_uniforms(prog->_LinkedShaders[i]->ir); } /* Mark all generic shader inputs and outputs as unpaired. */ diff --git a/src/glsl/lower_const_arrays_to_uniforms.cpp b/src/glsl/lower_const_arrays_to_uniforms.cpp new file mode 100644 index 0000000..516a259 --- /dev/null +++ b/src/glsl/lower_const_arrays_to_uniforms.cpp @@ -0,0 +1,101 @@ +/* + * Copyright © 2014 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. + */ + +/** + * \file lower_const_arrays_to_uniforms.cpp + * + * Lower constant arrays to uniform arrays. + * + * Some driver backends (such as i965) don't handle constant arrays gracefully, + * instead treating them as ordinary writable temporary arrays. Since arrays + * can be large, this often means spilling them to scratch memory, which + * usually involves a large number of instructions. + * + * This must be called prior to link_set_uniform_initializers(); we need the + * linker to process our new uniform's constant initializer. + * + * This should be called after optimizations, since those can result in + * splitting and removing arrays that are indexed by constant expressions. + */ +#include "ir.h" +#include "ir_visitor.h" +#include "ir_rvalue_visitor.h" +#include "glsl_types.h" + +namespace { +class lower_const_array_visitor : public ir_rvalue_visitor { +public: + lower_const_array_visitor(exec_list *insts) + { + instructions = insts; + progress = false; + } + + bool run() + { + visit_list_elements(this, instructions); + return progress; + } + + void handle_rvalue(ir_rvalue **rvalue); + +private: + exec_list *instructions; + bool progress; +}; + +void +lower_const_array_visitor::handle_rvalue(ir_rvalue **rvalue) +{ + if (!*rvalue) + return; + + ir_constant *con = (*rvalue)->as_constant(); + if (!con || !con->type->is_array()) + return; + + void *mem_ctx = ralloc_parent(con); + + ir_variable *uni = + new(mem_ctx) ir_variable(con->type, "constarray", ir_var_uniform); + uni->constant_initializer = con; + uni->constant_value = con; + uni->data.has_initializer = true; + uni->data.read_only = true; + /* Assume the whole thing is accessed. */ + uni->data.max_array_access = uni->type->length - 1; + instructions->push_head(uni); + + *rvalue = new(mem_ctx) ir_dereference_variable(uni); + + progress = true; +} + +} /* anonymous namespace */ + +bool +lower_const_arrays_to_uniforms(exec_list *instructions) +{ + lower_const_array_visitor v(instructions); + return v.run(); +} -- 1.9.2