diff options
-rw-r--r-- | src/compiler/nir/nir_lower_io.c | 105 |
1 files changed, 37 insertions, 68 deletions
diff --git a/src/compiler/nir/nir_lower_io.c b/src/compiler/nir/nir_lower_io.c index 622b625b29a..3bdacee66bf 100644 --- a/src/compiler/nir/nir_lower_io.c +++ b/src/compiler/nir/nir_lower_io.c @@ -33,6 +33,7 @@ #include "nir.h" #include "nir_builder.h" +#include "nir_deref.h" struct lower_io_state { void *dead_ctx; @@ -86,35 +87,35 @@ nir_is_per_vertex_io(const nir_variable *var, gl_shader_stage stage) } static nir_ssa_def * -get_io_offset(nir_builder *b, nir_deref_var *deref, +get_io_offset(nir_builder *b, nir_deref_instr *deref, nir_ssa_def **vertex_index, int (*type_size)(const struct glsl_type *), unsigned *component) { - nir_deref *tail = &deref->deref; + nir_deref_path path; + nir_deref_path_init(&path, deref, NULL); + + assert(path.path[0]->deref_type == nir_deref_type_var); + nir_deref_instr **p = &path.path[1]; /* For per-vertex input arrays (i.e. geometry shader inputs), keep the * outermost array index separate. Process the rest normally. */ if (vertex_index != NULL) { - tail = tail->child; - nir_deref_array *deref_array = nir_deref_as_array(tail); - - nir_ssa_def *vtx = nir_imm_int(b, deref_array->base_offset); - if (deref_array->deref_array_type == nir_deref_array_type_indirect) { - vtx = nir_iadd(b, vtx, nir_ssa_for_src(b, deref_array->indirect, 1)); - } - *vertex_index = vtx; + assert((*p)->deref_type == nir_deref_type_array); + *vertex_index = nir_ssa_for_src(b, (*p)->arr.index, 1); + p++; } - if (deref->var->data.compact) { - assert(tail->child->deref_type == nir_deref_type_array); - assert(glsl_type_is_scalar(glsl_without_array(deref->var->type))); - nir_deref_array *deref_array = nir_deref_as_array(tail->child); + if (path.path[0]->var->data.compact) { + assert((*p)->deref_type == nir_deref_type_array); + assert(glsl_type_is_scalar((*p)->type)); + /* We always lower indirect dereferences for "compact" array vars. */ - assert(deref_array->deref_array_type == nir_deref_array_type_direct); + nir_const_value *const_index = nir_src_as_const_value((*p)->arr.index); + assert(const_index); - const unsigned total_offset = *component + deref_array->base_offset; + const unsigned total_offset = *component + const_index->u32[0]; const unsigned slot_offset = total_offset / 4; *component = total_offset % 4; return nir_imm_int(b, type_size(glsl_vec4_type()) * slot_offset); @@ -123,35 +124,31 @@ get_io_offset(nir_builder *b, nir_deref_var *deref, /* Just emit code and let constant-folding go to town */ nir_ssa_def *offset = nir_imm_int(b, 0); - 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); - - offset = nir_iadd(b, offset, - nir_imm_int(b, size * deref_array->base_offset)); + for (; *p; p++) { + if ((*p)->deref_type == nir_deref_type_array) { + unsigned size = type_size((*p)->type); - if (deref_array->deref_array_type == nir_deref_array_type_indirect) { - nir_ssa_def *mul = - nir_imul(b, nir_imm_int(b, size), - nir_ssa_for_src(b, deref_array->indirect, 1)); + nir_ssa_def *mul = + nir_imul(b, nir_imm_int(b, size), + nir_ssa_for_src(b, (*p)->arr.index, 1)); - offset = nir_iadd(b, offset, mul); - } - } else if (tail->deref_type == nir_deref_type_struct) { - nir_deref_struct *deref_struct = nir_deref_as_struct(tail); + offset = nir_iadd(b, offset, mul); + } else if ((*p)->deref_type == nir_deref_type_struct) { + /* p starts at path[1], so this is safe */ + nir_deref_instr *parent = *(p - 1); unsigned field_offset = 0; - for (unsigned i = 0; i < deref_struct->index; i++) { - field_offset += type_size(glsl_get_struct_field(parent_type, i)); + for (unsigned i = 0; i < (*p)->strct.index; i++) { + field_offset += type_size(glsl_get_struct_field(parent->type, i)); } offset = nir_iadd(b, offset, nir_imm_int(b, field_offset)); + } else { + unreachable("Unsupported deref type"); } } + nir_deref_path_finish(&path); + return offset; } @@ -247,10 +244,7 @@ lower_store(nir_intrinsic_instr *intrin, struct lower_io_state *state, nir_intrinsic_instr_create(state->builder.shader, op); store->num_components = intrin->num_components; - if (intrin->intrinsic == nir_intrinsic_store_var) - nir_src_copy(&store->src[0], &intrin->src[0], store); - else - nir_src_copy(&store->src[0], &intrin->src[1], store); + nir_src_copy(&store->src[0], &intrin->src[1], store); nir_intrinsic_set_base(store, var->data.driver_location); @@ -318,17 +312,14 @@ lower_interpolate_at(nir_intrinsic_instr *intrin, struct lower_io_state *state, nir_intrinsic_op bary_op; switch (intrin->intrinsic) { - case nir_intrinsic_interp_var_at_centroid: case nir_intrinsic_interp_deref_at_centroid: bary_op = (state->options & nir_lower_io_force_sample_interpolation) ? nir_intrinsic_load_barycentric_sample : nir_intrinsic_load_barycentric_centroid; break; - case nir_intrinsic_interp_var_at_sample: case nir_intrinsic_interp_deref_at_sample: bary_op = nir_intrinsic_load_barycentric_at_sample; break; - case nir_intrinsic_interp_var_at_offset: case nir_intrinsic_interp_deref_at_offset: bary_op = nir_intrinsic_load_barycentric_at_offset; break; @@ -342,10 +333,6 @@ lower_interpolate_at(nir_intrinsic_instr *intrin, struct lower_io_state *state, nir_ssa_dest_init(&bary_setup->instr, &bary_setup->dest, 2, 32, NULL); nir_intrinsic_set_interp_mode(bary_setup, var->data.interpolation); - if (intrin->intrinsic == nir_intrinsic_interp_var_at_sample || - intrin->intrinsic == nir_intrinsic_interp_var_at_offset) - nir_src_copy(&bary_setup->src[0], &intrin->src[0], bary_setup); - if (intrin->intrinsic == nir_intrinsic_interp_deref_at_sample || intrin->intrinsic == nir_intrinsic_interp_deref_at_offset) nir_src_copy(&bary_setup->src[0], &intrin->src[1], bary_setup); @@ -381,9 +368,7 @@ nir_lower_io_block(nir_block *block, nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr); switch (intrin->intrinsic) { - case nir_intrinsic_load_var: case nir_intrinsic_load_deref: - case nir_intrinsic_store_var: case nir_intrinsic_store_deref: case nir_intrinsic_deref_atomic_add: case nir_intrinsic_deref_atomic_imin: @@ -397,9 +382,6 @@ nir_lower_io_block(nir_block *block, case nir_intrinsic_deref_atomic_comp_swap: /* We can lower the io for this nir instrinsic */ break; - case nir_intrinsic_interp_var_at_centroid: - case nir_intrinsic_interp_var_at_sample: - case nir_intrinsic_interp_var_at_offset: case nir_intrinsic_interp_deref_at_centroid: case nir_intrinsic_interp_deref_at_sample: case nir_intrinsic_interp_deref_at_offset: @@ -411,17 +393,9 @@ nir_lower_io_block(nir_block *block, continue; } - nir_deref_var *deref; - nir_deref_instr *deref_instr = NULL; - if (nir_intrinsic_infos[intrin->intrinsic].num_variables > 0) { - assert(nir_intrinsic_infos[intrin->intrinsic].num_variables == 1); - deref = intrin->variables[0]; - } else { - deref_instr = nir_src_as_deref(intrin->src[0]); - deref = nir_deref_instr_to_deref(deref_instr, state->dead_ctx); - } + nir_deref_instr *deref = nir_src_as_deref(intrin->src[0]); - nir_variable *var = deref->var; + nir_variable *var = nir_deref_instr_get_variable(deref); nir_variable_mode mode = var->data.mode; if ((state->modes & mode) == 0) @@ -447,13 +421,11 @@ nir_lower_io_block(nir_block *block, nir_intrinsic_instr *replacement; switch (intrin->intrinsic) { - case nir_intrinsic_load_var: case nir_intrinsic_load_deref: replacement = lower_load(intrin, state, vertex_index, var, offset, component_offset); break; - case nir_intrinsic_store_var: case nir_intrinsic_store_deref: replacement = lower_store(intrin, state, vertex_index, var, offset, component_offset); @@ -473,9 +445,6 @@ nir_lower_io_block(nir_block *block, replacement = lower_atomic(intrin, state, var, offset); break; - case nir_intrinsic_interp_var_at_centroid: - case nir_intrinsic_interp_var_at_sample: - case nir_intrinsic_interp_var_at_offset: case nir_intrinsic_interp_deref_at_centroid: case nir_intrinsic_interp_deref_at_sample: case nir_intrinsic_interp_deref_at_offset: @@ -541,7 +510,7 @@ nir_lower_io(nir_shader *shader, nir_variable_mode modes, { bool progress = false; - nir_assert_unlowered_derefs(shader, nir_lower_atomic_derefs); + nir_assert_unlowered_derefs(shader, nir_lower_load_store_derefs | nir_lower_interp_derefs | nir_lower_atomic_derefs); nir_foreach_function(function, shader) { if (function->impl) { |