[Mesa-dev] [PATCH 093/133] nir: Add a pass for lowering input/output loads/stores
Connor Abbott
cwabbott0 at gmail.com
Sun Jan 4 20:29:11 PST 2015
I'd also like to rename or at least note that this is a scalar-only thing
for now... otherwise,
Reviewed-by: Connor Abbott <cwabbott0 at gmail.com>
On Tue, Dec 16, 2014 at 1:11 AM, Jason Ekstrand <jason at jlekstrand.net>
wrote:
> ---
> src/glsl/Makefile.sources | 1 +
> src/glsl/nir/nir.h | 2 +
> src/glsl/nir/nir_lower_io.c | 388
> ++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 391 insertions(+)
> create mode 100644 src/glsl/nir/nir_lower_io.c
>
> diff --git a/src/glsl/Makefile.sources b/src/glsl/Makefile.sources
> index 6230f49..53c3e98 100644
> --- a/src/glsl/Makefile.sources
> +++ b/src/glsl/Makefile.sources
> @@ -23,6 +23,7 @@ NIR_FILES = \
> $(GLSL_SRCDIR)/nir/nir_live_variables.c \
> $(GLSL_SRCDIR)/nir/nir_lower_atomics.c \
> $(GLSL_SRCDIR)/nir/nir_lower_locals_to_regs.c \
> + $(GLSL_SRCDIR)/nir/nir_lower_io.c \
> $(GLSL_SRCDIR)/nir/nir_lower_samplers.cpp \
> $(GLSL_SRCDIR)/nir/nir_lower_system_values.c \
> $(GLSL_SRCDIR)/nir/nir_lower_variables.c \
> diff --git a/src/glsl/nir/nir.h b/src/glsl/nir/nir.h
> index 7d7aec7..ec9ce07 100644
> --- a/src/glsl/nir/nir.h
> +++ b/src/glsl/nir/nir.h
> @@ -1360,6 +1360,8 @@ void nir_split_var_copies(nir_shader *shader);
>
> void nir_lower_locals_to_regs(nir_shader *shader);
>
> +void nir_lower_io(nir_shader *shader);
> +
> void nir_lower_variables(nir_shader *shader);
>
> void nir_lower_variables_scalar(nir_shader *shader, bool lower_globals,
> diff --git a/src/glsl/nir/nir_lower_io.c b/src/glsl/nir/nir_lower_io.c
> new file mode 100644
> index 0000000..a3b8186
> --- /dev/null
> +++ b/src/glsl/nir/nir_lower_io.c
> @@ -0,0 +1,388 @@
> +/*
> + * 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.
> + *
> + * Authors:
> + * Connor Abbott (cwabbott0 at gmail.com)
> + * Jason Ekstrand (jason at jlekstrand.net)
> + *
> + */
> +
> +/*
> + * This lowering pass converts references to input/output variables with
> + * loads/stores to actual input/output intrinsics.
> + */
> +
> +#include "nir.h"
> +
> +struct lower_io_state {
> + void *mem_ctx;
> +};
> +
> +static unsigned
> +type_size(const struct glsl_type *type)
> +{
> + unsigned int size, i;
> +
> + switch (glsl_get_base_type(type)) {
> + case GLSL_TYPE_UINT:
> + case GLSL_TYPE_INT:
> + case GLSL_TYPE_FLOAT:
> + case GLSL_TYPE_BOOL:
> + return glsl_get_components(type);
> + case GLSL_TYPE_ARRAY:
> + return type_size(glsl_get_array_element(type)) *
> glsl_get_length(type);
> + case GLSL_TYPE_STRUCT:
> + size = 0;
> + for (i = 0; i < glsl_get_length(type); i++) {
> + size += type_size(glsl_get_struct_field(type, i));
> + }
> + return size;
> + case GLSL_TYPE_SAMPLER:
> + return 0;
> + case GLSL_TYPE_ATOMIC_UINT:
> + return 0;
> + case GLSL_TYPE_INTERFACE:
> + return 0;
> + case GLSL_TYPE_IMAGE:
> + return 0;
> + case GLSL_TYPE_VOID:
> + case GLSL_TYPE_ERROR:
> + unreachable("not reached");
> + }
> +
> + return 0;
> +}
> +
> +static void
> +assign_var_locations(struct hash_table *ht, unsigned *size)
> +{
> + unsigned location = 0;
> +
> + struct hash_entry *entry;
> + hash_table_foreach(ht, entry) {
> + nir_variable *var = (nir_variable *) entry->data;
> +
> + /*
> + * UBO's have their own address spaces, so don't count them towards
> the
> + * number of global uniforms
> + */
> + if (var->data.mode == nir_var_uniform && var->interface_type !=
> NULL)
> + continue;
> +
> + var->data.driver_location = location;
> + location += type_size(var->type);
> + }
> +
> + *size = location;
> +}
> +
> +static void
> +assign_var_locations_shader(nir_shader *shader)
> +{
> + assign_var_locations(shader->inputs, &shader->num_inputs);
> + assign_var_locations(shader->outputs, &shader->num_outputs);
> + assign_var_locations(shader->uniforms, &shader->num_uniforms);
> +}
> +
> +static bool
> +deref_has_indirect(nir_deref_var *deref)
> +{
> + for (nir_deref *tail = deref->deref.child; tail; tail = tail->child) {
> + if (tail->deref_type == nir_deref_type_array) {
> + nir_deref_array *arr = nir_deref_as_array(tail);
> + if (arr->deref_array_type == nir_deref_array_type_indirect)
> + return true;
> + }
> + }
> +
> + return false;
> +}
> +
> +static unsigned
> +get_io_offset(nir_deref_var *deref, nir_instr *instr, nir_src *indirect,
> + struct lower_io_state *state)
> +{
> + bool found_indirect = false;
> + unsigned base_offset = 0;
> +
> + nir_deref *tail = &deref->deref;
> + while (tail->child != NULL) {
> + const struct glsl_type *parent_type = tail->type;
> + tail = tail->child;
> +
> + if (tail->deref_type == nir_deref_type_array) {
> + nir_deref_array *deref_array = nir_deref_as_array(tail);
> + unsigned size = type_size(tail->type);
> +
> + base_offset += size * deref_array->base_offset;
> +
> + if (deref_array->deref_array_type ==
> nir_deref_array_type_indirect) {
> + nir_load_const_instr *load_const =
> + nir_load_const_instr_create(state->mem_ctx);
> + load_const->num_components = 1;
> + load_const->value.u[0] = size;
> + load_const->dest.is_ssa = true;
> + nir_ssa_def_init(&load_const->instr, &load_const->dest.ssa,
> + 1, NULL);
> + nir_instr_insert_before(instr, &load_const->instr);
> +
> + nir_alu_instr *mul = nir_alu_instr_create(state->mem_ctx,
> + nir_op_imul);
> + mul->src[0].src.is_ssa = true;
> + mul->src[0].src.ssa = &load_const->dest.ssa;
> + mul->src[1].src = nir_src_copy(deref_array->indirect,
> + state->mem_ctx);
> + mul->dest.write_mask = 1;
> + mul->dest.dest.is_ssa = true;
> + nir_ssa_def_init(&mul->instr, &mul->dest.dest.ssa, 1, NULL);
> + nir_instr_insert_before(instr, &mul->instr);
> +
> + if (found_indirect) {
> + nir_alu_instr *add = nir_alu_instr_create(state->mem_ctx,
> + nir_op_iadd);
> + add->src[0].src = *indirect;
> + add->src[1].src.is_ssa = true;
> + add->src[1].src.ssa = &mul->dest.dest.ssa;
> + add->dest.write_mask = 1;
> + add->dest.dest.is_ssa = true;
> + nir_ssa_def_init(&add->instr, &add->dest.dest.ssa, 1,
> NULL);
> + nir_instr_insert_before(instr, &add->instr);
> +
> + indirect->is_ssa = true;
> + indirect->ssa = &add->dest.dest.ssa;
> + } else {
> + indirect->is_ssa = true;
> + indirect->ssa = &mul->dest.dest.ssa;
> + found_indirect = true;
> + }
> + }
> + } else if (tail->deref_type == nir_deref_type_struct) {
> + nir_deref_struct *deref_struct = nir_deref_as_struct(tail);
> +
> + for (unsigned i = 0; i < deref_struct->index; i++)
> + base_offset += type_size(glsl_get_struct_field(parent_type,
> i));
> + }
> + }
> +
> + return base_offset;
> +}
> +
> +static nir_intrinsic_op
> +get_load_op(nir_variable_mode mode, bool indirect, unsigned
> num_components)
> +{
> + if (indirect) {
> + switch (mode) {
> + case nir_var_shader_in:
> + switch (num_components) {
> + case 1: return nir_intrinsic_load_input_vec1_indirect;
> + case 2: return nir_intrinsic_load_input_vec2_indirect;
> + case 3: return nir_intrinsic_load_input_vec3_indirect;
> + case 4: return nir_intrinsic_load_input_vec4_indirect;
> + default: unreachable("Invalid number of components"); break;
> + }
> + break;
> +
> + case nir_var_uniform:
> + switch (num_components) {
> + case 1: return nir_intrinsic_load_uniform_vec1_indirect;
> + case 2: return nir_intrinsic_load_uniform_vec2_indirect;
> + case 3: return nir_intrinsic_load_uniform_vec3_indirect;
> + case 4: return nir_intrinsic_load_uniform_vec4_indirect;
> + default: unreachable("Invalid number of components"); break;
> + }
> + break;
> +
> + default:
> + unreachable("Invalid input type");
> + break;
> + }
> + } else {
> + switch (mode) {
> + case nir_var_shader_in:
> + switch (num_components) {
> + case 1: return nir_intrinsic_load_input_vec1;
> + case 2: return nir_intrinsic_load_input_vec2;
> + case 3: return nir_intrinsic_load_input_vec3;
> + case 4: return nir_intrinsic_load_input_vec4;
> + default: unreachable("Invalid number of components"); break;
> + }
> + break;
> +
> + case nir_var_uniform:
> + switch (num_components) {
> + case 1: return nir_intrinsic_load_uniform_vec1;
> + case 2: return nir_intrinsic_load_uniform_vec2;
> + case 3: return nir_intrinsic_load_uniform_vec3;
> + case 4: return nir_intrinsic_load_uniform_vec4;
> + default: unreachable("Invalid number of components"); break;
> + }
> + break;
> +
> + default:
> + unreachable("Invalid input type");
> + break;
> + }
> + }
> +
> + return nir_intrinsic_load_input_vec1;
> +}
> +
> +static bool
> +nir_lower_io_block(nir_block *block, void *void_state)
> +{
> + struct lower_io_state *state = void_state;
> +
> + nir_foreach_instr_safe(block, instr) {
> + if (instr->type != nir_instr_type_intrinsic)
> + continue;
> +
> + nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
> +
> + switch (intrin->intrinsic) {
> + case nir_intrinsic_load_var_vec1:
> + case nir_intrinsic_load_var_vec2:
> + case nir_intrinsic_load_var_vec3:
> + case nir_intrinsic_load_var_vec4: {
> + nir_variable_mode mode = intrin->variables[0]->var->data.mode;
> + if (mode != nir_var_shader_in && mode != nir_var_uniform)
> + continue;
> +
> + bool has_indirect = deref_has_indirect(intrin->variables[0]);
> + unsigned num_components =
> + nir_intrinsic_infos[intrin->intrinsic].dest_components;
> +
> + nir_intrinsic_op load_op = get_load_op(mode, has_indirect,
> + num_components);
> + nir_intrinsic_instr *load =
> nir_intrinsic_instr_create(state->mem_ctx,
> + load_op);
> +
> + nir_src indirect;
> + unsigned offset = get_io_offset(intrin->variables[0],
> + &intrin->instr, &indirect,
> state);
> + offset += intrin->variables[0]->var->data.driver_location;
> +
> + load->const_index[0] = offset;
> + load->const_index[1] = 1;
> +
> + if (has_indirect)
> + load->src[0] = indirect;
> +
> + if (intrin->dest.is_ssa) {
> + load->dest.is_ssa = true;
> + nir_ssa_def_init(&load->instr, &load->dest.ssa,
> + num_components, NULL);
> +
> + nir_src new_src = {
> + .is_ssa = true,
> + .ssa = &load->dest.ssa,
> + };
> +
> + nir_ssa_def_rewrite_uses(&intrin->dest.ssa, new_src,
> + state->mem_ctx);
> + } else {
> + load->dest = nir_dest_copy(intrin->dest, state->mem_ctx);
> + }
> +
> + nir_instr_insert_before(&intrin->instr, &load->instr);
> + nir_instr_remove(&intrin->instr);
> + break;
> + }
> +
> + case nir_intrinsic_store_var_vec1:
> + case nir_intrinsic_store_var_vec2:
> + case nir_intrinsic_store_var_vec3:
> + case nir_intrinsic_store_var_vec4: {
> + if (intrin->variables[0]->var->data.mode != nir_var_shader_out)
> + continue;
> +
> + bool has_indirect = deref_has_indirect(intrin->variables[0]);
> + unsigned num_components =
> + nir_intrinsic_infos[intrin->intrinsic].src_components[0];
> +
> + nir_intrinsic_op store_op;
> + if (has_indirect) {
> + switch (num_components) {
> + case 1: store_op = nir_intrinsic_store_output_vec1_indirect;
> break;
> + case 2: store_op = nir_intrinsic_store_output_vec2_indirect;
> break;
> + case 3: store_op = nir_intrinsic_store_output_vec3_indirect;
> break;
> + case 4: store_op = nir_intrinsic_store_output_vec4_indirect;
> break;
> + default: unreachable("Invalid number of components"); break;
> + }
> + } else {
> + switch (num_components) {
> + case 1: store_op = nir_intrinsic_store_output_vec1; break;
> + case 2: store_op = nir_intrinsic_store_output_vec2; break;
> + case 3: store_op = nir_intrinsic_store_output_vec3; break;
> + case 4: store_op = nir_intrinsic_store_output_vec4; break;
> + default: unreachable("Invalid number of components"); break;
> + }
> + }
> +
> + nir_intrinsic_instr *store =
> nir_intrinsic_instr_create(state->mem_ctx,
> +
> store_op);
> +
> + nir_src indirect;
> + unsigned offset = get_io_offset(intrin->variables[0],
> + &intrin->instr, &indirect,
> state);
> + offset += intrin->variables[0]->var->data.driver_location;
> +
> + store->const_index[0] = offset;
> + store->const_index[1] = 1;
> +
> + store->src[0] = nir_src_copy(intrin->src[0], state->mem_ctx);
> +
> + if (has_indirect)
> + store->src[1] = indirect;
> +
> + nir_instr_insert_before(&intrin->instr, &store->instr);
> + nir_instr_remove(&intrin->instr);
> + break;
> + }
> +
> + default:
> + break;
> + }
> + }
> +
> + return true;
> +}
> +
> +static void
> +nir_lower_io_impl(nir_function_impl *impl)
> +{
> + struct lower_io_state state;
> +
> + state.mem_ctx = ralloc_parent(impl);
> +
> + nir_foreach_block(impl, nir_lower_io_block, &state);
> +}
> +
> +void
> +nir_lower_io(nir_shader *shader)
> +{
> + assign_var_locations_shader(shader);
> +
> + nir_foreach_overload(shader, overload) {
> + if (overload->impl)
> + nir_lower_io_impl(overload->impl);
> + }
> +}
> --
> 2.2.0
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/mesa-dev/attachments/20150104/022bd0eb/attachment-0001.html>
More information about the mesa-dev
mailing list