diff options
Diffstat (limited to 'src/compiler')
-rw-r--r-- | src/compiler/Makefile.sources | 1 | ||||
-rw-r--r-- | src/compiler/glsl/gl_nir_lower_samplers.c | 128 | ||||
-rw-r--r-- | src/compiler/nir/meson.build | 1 | ||||
-rw-r--r-- | src/compiler/nir/nir.h | 2 | ||||
-rw-r--r-- | src/compiler/nir/nir_lower_samplers.c | 154 |
5 files changed, 159 insertions, 127 deletions
diff --git a/src/compiler/Makefile.sources b/src/compiler/Makefile.sources index edf1b936ac1..ac6c0670444 100644 --- a/src/compiler/Makefile.sources +++ b/src/compiler/Makefile.sources @@ -272,6 +272,7 @@ NIR_FILES = \ nir/nir_lower_phis_to_scalar.c \ nir/nir_lower_regs_to_ssa.c \ nir/nir_lower_returns.c \ + nir/nir_lower_samplers.c \ nir/nir_lower_scratch.c \ nir/nir_lower_subgroups.c \ nir/nir_lower_system_values.c \ diff --git a/src/compiler/glsl/gl_nir_lower_samplers.c b/src/compiler/glsl/gl_nir_lower_samplers.c index 85535c074dc..08817316b9c 100644 --- a/src/compiler/glsl/gl_nir_lower_samplers.c +++ b/src/compiler/glsl/gl_nir_lower_samplers.c @@ -24,142 +24,16 @@ */ #include "compiler/nir/nir.h" -#include "compiler/nir/nir_builder.h" #include "gl_nir.h" -#include "ir_uniform.h" - -#include "main/compiler.h" -#include "main/mtypes.h" - -static void -lower_tex_src_to_offset(nir_builder *b, - nir_tex_instr *instr, unsigned src_idx) -{ - nir_ssa_def *index = NULL; - unsigned base_index = 0; - unsigned array_elements = 1; - nir_tex_src *src = &instr->src[src_idx]; - bool is_sampler = src->src_type == nir_tex_src_sampler_deref; - - /* We compute first the offsets */ - nir_deref_instr *deref = nir_instr_as_deref(src->src.ssa->parent_instr); - while (deref->deref_type != nir_deref_type_var) { - assert(deref->parent.is_ssa); - nir_deref_instr *parent = - nir_instr_as_deref(deref->parent.ssa->parent_instr); - - assert(deref->deref_type == nir_deref_type_array); - - if (nir_src_is_const(deref->arr.index) && index == NULL) { - /* We're still building a direct index */ - base_index += nir_src_as_uint(deref->arr.index) * array_elements; - } else { - if (index == NULL) { - /* We used to be direct but not anymore */ - index = nir_imm_int(b, base_index); - base_index = 0; - } - - index = nir_iadd(b, index, - nir_imul(b, nir_imm_int(b, array_elements), - nir_ssa_for_src(b, deref->arr.index, 1))); - } - - array_elements *= glsl_get_length(parent->type); - - deref = parent; - } - - if (index) - index = nir_umin(b, index, nir_imm_int(b, array_elements - 1)); - - /* We hit the deref_var. This is the end of the line */ - assert(deref->deref_type == nir_deref_type_var); - - base_index += deref->var->data.binding; - - /* We have the offsets, we apply them, rewriting the source or removing - * instr if needed - */ - if (index) { - nir_instr_rewrite_src(&instr->instr, &src->src, - nir_src_for_ssa(index)); - - src->src_type = is_sampler ? - nir_tex_src_sampler_offset : - nir_tex_src_texture_offset; - - instr->texture_array_size = array_elements; - } else { - nir_tex_instr_remove_src(instr, src_idx); - } - - if (is_sampler) { - instr->sampler_index = base_index; - } else { - instr->texture_index = base_index; - instr->texture_array_size = array_elements; - } -} - -static bool -lower_sampler(nir_builder *b, nir_tex_instr *instr) -{ - int texture_idx = - nir_tex_instr_src_index(instr, nir_tex_src_texture_deref); - - if (texture_idx >= 0) { - b->cursor = nir_before_instr(&instr->instr); - - lower_tex_src_to_offset(b, instr, texture_idx); - } - - int sampler_idx = - nir_tex_instr_src_index(instr, nir_tex_src_sampler_deref); - - if (sampler_idx >= 0) { - lower_tex_src_to_offset(b, instr, sampler_idx); - } - - if (texture_idx < 0 && sampler_idx < 0) - return false; - - return true; -} - -static bool -lower_impl(nir_function_impl *impl) -{ - nir_builder b; - nir_builder_init(&b, impl); - bool progress = false; - - nir_foreach_block(block, impl) { - nir_foreach_instr(instr, block) { - if (instr->type == nir_instr_type_tex) - progress |= lower_sampler(&b, nir_instr_as_tex(instr)); - } - } - - return progress; -} bool gl_nir_lower_samplers(nir_shader *shader, const struct gl_shader_program *shader_program) { - bool progress = false; - /* First, use gl_nir_lower_samplers_as_derefs to set var->data.binding * based on the uniforms, and split structures to simplify derefs. */ gl_nir_lower_samplers_as_deref(shader, shader_program); - /* Next, lower derefs to offsets. */ - nir_foreach_function(function, shader) { - if (function->impl) - progress |= lower_impl(function->impl); - } - - return progress; + return nir_lower_samplers(shader); } diff --git a/src/compiler/nir/meson.build b/src/compiler/nir/meson.build index 04e4f729902..1da26ef561c 100644 --- a/src/compiler/nir/meson.build +++ b/src/compiler/nir/meson.build @@ -152,6 +152,7 @@ files_libnir = files( 'nir_lower_point_size.c', 'nir_lower_regs_to_ssa.c', 'nir_lower_returns.c', + 'nir_lower_samplers.c', 'nir_lower_scratch.c', 'nir_lower_subgroups.c', 'nir_lower_system_values.c', diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h index bad1d6af212..ab1aab774a0 100644 --- a/src/compiler/nir/nir.h +++ b/src/compiler/nir/nir.h @@ -3938,6 +3938,8 @@ bool nir_lower_phis_to_regs_block(nir_block *block); bool nir_lower_ssa_defs_to_regs_block(nir_block *block); bool nir_rematerialize_derefs_in_use_blocks_impl(nir_function_impl *impl); +bool nir_lower_samplers(nir_shader *shader); + /* This is here for unit tests. */ bool nir_opt_comparison_pre_impl(nir_function_impl *impl); diff --git a/src/compiler/nir/nir_lower_samplers.c b/src/compiler/nir/nir_lower_samplers.c new file mode 100644 index 00000000000..5a440f7117c --- /dev/null +++ b/src/compiler/nir/nir_lower_samplers.c @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2005-2007 Brian Paul All Rights Reserved. + * Copyright (C) 2008 VMware, Inc. All Rights Reserved. + * 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. + */ + +#include "nir/nir.h" +#include "nir_builder.h" + +static void +lower_tex_src_to_offset(nir_builder *b, + nir_tex_instr *instr, unsigned src_idx) +{ + nir_ssa_def *index = NULL; + unsigned base_index = 0; + unsigned array_elements = 1; + nir_tex_src *src = &instr->src[src_idx]; + bool is_sampler = src->src_type == nir_tex_src_sampler_deref; + + /* We compute first the offsets */ + nir_deref_instr *deref = nir_instr_as_deref(src->src.ssa->parent_instr); + while (deref->deref_type != nir_deref_type_var) { + assert(deref->parent.is_ssa); + nir_deref_instr *parent = + nir_instr_as_deref(deref->parent.ssa->parent_instr); + + assert(deref->deref_type == nir_deref_type_array); + + if (nir_src_is_const(deref->arr.index) && index == NULL) { + /* We're still building a direct index */ + base_index += nir_src_as_uint(deref->arr.index) * array_elements; + } else { + if (index == NULL) { + /* We used to be direct but not anymore */ + index = nir_imm_int(b, base_index); + base_index = 0; + } + + index = nir_iadd(b, index, + nir_imul(b, nir_imm_int(b, array_elements), + nir_ssa_for_src(b, deref->arr.index, 1))); + } + + array_elements *= glsl_get_length(parent->type); + + deref = parent; + } + + if (index) + index = nir_umin(b, index, nir_imm_int(b, array_elements - 1)); + + /* We hit the deref_var. This is the end of the line */ + assert(deref->deref_type == nir_deref_type_var); + + base_index += deref->var->data.binding; + + /* We have the offsets, we apply them, rewriting the source or removing + * instr if needed + */ + if (index) { + nir_instr_rewrite_src(&instr->instr, &src->src, + nir_src_for_ssa(index)); + + src->src_type = is_sampler ? + nir_tex_src_sampler_offset : + nir_tex_src_texture_offset; + + instr->texture_array_size = array_elements; + } else { + nir_tex_instr_remove_src(instr, src_idx); + } + + if (is_sampler) { + instr->sampler_index = base_index; + } else { + instr->texture_index = base_index; + instr->texture_array_size = array_elements; + } +} + +static bool +lower_sampler(nir_builder *b, nir_tex_instr *instr) +{ + int texture_idx = + nir_tex_instr_src_index(instr, nir_tex_src_texture_deref); + + if (texture_idx >= 0) { + b->cursor = nir_before_instr(&instr->instr); + + lower_tex_src_to_offset(b, instr, texture_idx); + } + + int sampler_idx = + nir_tex_instr_src_index(instr, nir_tex_src_sampler_deref); + + if (sampler_idx >= 0) { + lower_tex_src_to_offset(b, instr, sampler_idx); + } + + if (texture_idx < 0 && sampler_idx < 0) + return false; + + return true; +} + +static bool +lower_impl(nir_function_impl *impl) +{ + nir_builder b; + nir_builder_init(&b, impl); + bool progress = false; + + nir_foreach_block(block, impl) { + nir_foreach_instr(instr, block) { + if (instr->type == nir_instr_type_tex) + progress |= lower_sampler(&b, nir_instr_as_tex(instr)); + } + } + + return progress; +} + +bool +nir_lower_samplers(nir_shader *shader) +{ + bool progress = false; + + /* Next, lower derefs to offsets. */ + nir_foreach_function(function, shader) { + if (function->impl) + progress |= lower_impl(function->impl); + } + + return progress; +} |