nir: Use explicit deref information to provide real UBO ranges.

freedreno results (note that cat6 is loads from memory as opposed to
pushed constants from the constant file):

total instructions in shared programs: 8044344 -> 8022085 (-0.28%)
total constlen in shared programs: 1411384 -> 1461964 (3.58%)
total cat6 in shared programs: 89983 -> 87065 (-3.24%)

Over the last 3 commits, we increased Manhattan31 performance by ~10%

Reviewed-by: Kristian H. Kristensen <hoegsberg@google.com>
Reviewed-by: Rob Clark <robdclark@chromium.org>
Reviewed-by: Jason Ekstrand <jason@jlekstrand.net>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6359>
This commit is contained in:
Eric Anholt 2020-09-04 13:25:05 -07:00 committed by Marge Bot
parent 41b5aafef3
commit 1ed78bd247
1 changed files with 106 additions and 4 deletions

View File

@ -949,13 +949,113 @@ addr_is_in_bounds(nir_builder *b, nir_ssa_def *addr,
nir_iadd_imm(b, nir_channel(b, addr, 3), size));
}
static void
nir_get_explicit_deref_range(nir_deref_instr *deref,
nir_address_format addr_format,
uint32_t *out_base,
uint32_t *out_range)
{
uint32_t base = 0;
uint32_t range = glsl_get_explicit_size(deref->type, false);
while (true) {
nir_deref_instr *parent = nir_deref_instr_parent(deref);
switch (deref->deref_type) {
case nir_deref_type_array:
case nir_deref_type_array_wildcard:
case nir_deref_type_ptr_as_array: {
const unsigned stride = nir_deref_instr_array_stride(deref);
if (stride == 0)
goto fail;
if (!parent)
goto fail;
if (deref->deref_type != nir_deref_type_array_wildcard &&
nir_src_is_const(deref->arr.index))
base += stride * nir_src_as_uint(deref->arr.index);
else
range += stride * (glsl_get_length(parent->type) - 1);
break;
}
case nir_deref_type_struct: {
if (!parent)
goto fail;
base += glsl_get_struct_field_offset(parent->type, deref->strct.index);
break;
}
case nir_deref_type_cast: {
nir_instr *parent_instr = deref->parent.ssa->parent_instr;
switch (parent_instr->type) {
case nir_instr_type_load_const: {
nir_load_const_instr *load = nir_instr_as_load_const(parent_instr);
switch (addr_format) {
case nir_address_format_32bit_offset:
base += load->value[1].u32;
break;
case nir_address_format_32bit_index_offset:
base += load->value[1].u32;
break;
case nir_address_format_vec2_index_32bit_offset:
base += load->value[2].u32;
break;
default:
goto fail;
}
*out_base = base;
*out_range = range;
return;
}
case nir_instr_type_intrinsic: {
nir_intrinsic_instr *intr = nir_instr_as_intrinsic(parent_instr);
switch (intr->intrinsic) {
case nir_intrinsic_load_vulkan_descriptor:
/* Assume that a load_vulkan_descriptor won't contribute to an
* offset within the resource.
*/
break;
default:
goto fail;
}
*out_base = base;
*out_range = range;
return;
}
default:
goto fail;
}
}
default:
goto fail;
}
deref = parent;
}
fail:
*out_base = 0;
*out_range = ~0;
}
static nir_ssa_def *
build_explicit_io_load(nir_builder *b, nir_intrinsic_instr *intrin,
nir_ssa_def *addr, nir_address_format addr_format,
uint32_t align_mul, uint32_t align_offset,
unsigned num_components)
{
nir_variable_mode mode = nir_src_as_deref(intrin->src[0])->mode;
nir_deref_instr *deref = nir_src_as_deref(intrin->src[0]);
nir_variable_mode mode = deref->mode;
nir_intrinsic_op op;
switch (mode) {
@ -1030,9 +1130,11 @@ build_explicit_io_load(nir_builder *b, nir_intrinsic_instr *intrin,
nir_intrinsic_set_align(load, align_mul, align_offset);
if (op == nir_intrinsic_load_ubo) {
nir_intrinsic_set_range_base(load, 0);
nir_intrinsic_set_range(load, ~0);
if (nir_intrinsic_has_range_base(load)) {
unsigned base, range;
nir_get_explicit_deref_range(deref, addr_format, &base, &range);
nir_intrinsic_set_range_base(load, base);
nir_intrinsic_set_range(load, range);
}
assert(intrin->dest.is_ssa);