From c994c8b3fd4aee5c7ffe66e5a282243fab2e9580 Mon Sep 17 00:00:00 2001 From: Jesse Natalie Date: Tue, 31 Jan 2023 16:29:06 -0800 Subject: [PATCH] microsoft/compiler: Pass an alignment to constant buffer load lowering This means we can stop doing conditionals and shifts if we know the alignment of a load for a small amount of data. Part-of: --- src/gallium/drivers/d3d12/d3d12_nir_passes.c | 5 ++-- src/microsoft/clc/clc_nir.c | 12 +++++--- src/microsoft/compiler/dxil_nir.c | 31 ++++++++++---------- src/microsoft/compiler/dxil_nir.h | 2 +- src/microsoft/spirv_to_dxil/dxil_spirv_nir.c | 14 ++++++--- 5 files changed, 37 insertions(+), 27 deletions(-) diff --git a/src/gallium/drivers/d3d12/d3d12_nir_passes.c b/src/gallium/drivers/d3d12/d3d12_nir_passes.c index 742239b709b..0f1cdce37b6 100644 --- a/src/gallium/drivers/d3d12/d3d12_nir_passes.c +++ b/src/gallium/drivers/d3d12/d3d12_nir_passes.c @@ -552,7 +552,7 @@ lower_instr(nir_intrinsic_instr *instr, nir_builder *b, nir_ssa_def *load = nir_load_ubo(b, instr->num_components, instr->dest.ssa.bit_size, ubo_idx, ubo_offset, - .align_mul = instr->dest.ssa.bit_size / 8, + .align_mul = 16, .align_offset = 0, .range_base = 0, .range = ~0, @@ -706,7 +706,8 @@ lower_load_ubo_packed_impl(nir_builder *b, nir_instr *instr, build_load_ubo_dxil(b, buffer, offset, nir_dest_num_components(intr->dest), - nir_dest_bit_size(intr->dest)); + nir_dest_bit_size(intr->dest), + nir_intrinsic_align(intr)); return result; } diff --git a/src/microsoft/clc/clc_nir.c b/src/microsoft/clc/clc_nir.c index 785004678d9..53c7143d171 100644 --- a/src/microsoft/clc/clc_nir.c +++ b/src/microsoft/clc/clc_nir.c @@ -43,7 +43,8 @@ lower_load_base_global_invocation_id(nir_builder *b, nir_intrinsic_instr *intr, offsetof(struct clc_work_properties_data, global_offset_x)), nir_dest_num_components(intr->dest), - nir_dest_bit_size(intr->dest)); + nir_dest_bit_size(intr->dest), + sizeof(uint32_t) * 4); nir_ssa_def_rewrite_uses(&intr->dest.ssa, offset); nir_instr_remove(&intr->instr); return true; @@ -61,7 +62,8 @@ lower_load_work_dim(nir_builder *b, nir_intrinsic_instr *intr, offsetof(struct clc_work_properties_data, work_dim)), nir_dest_num_components(intr->dest), - nir_dest_bit_size(intr->dest)); + nir_dest_bit_size(intr->dest), + sizeof(uint32_t)); nir_ssa_def_rewrite_uses(&intr->dest.ssa, dim); nir_instr_remove(&intr->instr); return true; @@ -79,7 +81,8 @@ lower_load_num_workgroups(nir_builder *b, nir_intrinsic_instr *intr, offsetof(struct clc_work_properties_data, group_count_total_x)), nir_dest_num_components(intr->dest), - nir_dest_bit_size(intr->dest)); + nir_dest_bit_size(intr->dest), + sizeof(uint32_t) * 4); nir_ssa_def_rewrite_uses(&intr->dest.ssa, count); nir_instr_remove(&intr->instr); return true; @@ -97,7 +100,8 @@ lower_load_base_workgroup_id(nir_builder *b, nir_intrinsic_instr *intr, offsetof(struct clc_work_properties_data, group_id_offset_x)), nir_dest_num_components(intr->dest), - nir_dest_bit_size(intr->dest)); + nir_dest_bit_size(intr->dest), + sizeof(uint32_t) * 4); nir_ssa_def_rewrite_uses(&intr->dest.ssa, offset); nir_instr_remove(&intr->instr); return true; diff --git a/src/microsoft/compiler/dxil_nir.c b/src/microsoft/compiler/dxil_nir.c index 1be32e501ea..3eb710e8675 100644 --- a/src/microsoft/compiler/dxil_nir.c +++ b/src/microsoft/compiler/dxil_nir.c @@ -132,15 +132,14 @@ lower_load_deref(nir_builder *b, nir_intrinsic_instr *intr) static nir_ssa_def * ubo_load_select_32b_comps(nir_builder *b, nir_ssa_def *vec32, - nir_ssa_def *offset, unsigned num_bytes) + nir_ssa_def *offset, unsigned alignment) { - assert(num_bytes == 16 || num_bytes == 12 || num_bytes == 8 || - num_bytes == 4 || num_bytes == 3 || num_bytes == 2 || - num_bytes == 1); + assert(alignment >= 16 || alignment == 8 || + alignment == 4 || alignment == 2 || + alignment == 1); assert(vec32->num_components == 4); - /* 16 and 12 byte types are always aligned on 16 bytes. */ - if (num_bytes > 8) + if (alignment > 8) return vec32; nir_ssa_def *comps[4]; @@ -149,7 +148,7 @@ ubo_load_select_32b_comps(nir_builder *b, nir_ssa_def *vec32, for (unsigned i = 0; i < 4; i++) comps[i] = nir_channel(b, vec32, i); - /* If we have 8bytes or less to load, select which half the vec4 should + /* If we have 8bytes alignment or less, select which half the vec4 should * be used. */ cond = nir_ine(b, nir_iand(b, offset, nir_imm_int(b, 0x8)), @@ -158,13 +157,11 @@ ubo_load_select_32b_comps(nir_builder *b, nir_ssa_def *vec32, comps[0] = nir_bcsel(b, cond, comps[2], comps[0]); comps[1] = nir_bcsel(b, cond, comps[3], comps[1]); - /* Thanks to the CL alignment constraints, if we want 8 bytes we're done. */ - if (num_bytes == 8) + if (alignment == 8) return nir_vec(b, comps, 2); - /* 4 bytes or less needed, select which of the 32bit component should be - * used and return it. The sub-32bit split is handled in - * extract_comps_from_vec32(). + /* 4 byte align or less needed, select which of the 32bit component should be + * used and return it. The sub-32bit split is handled in nir_extract_bits(). */ cond = nir_ine(b, nir_iand(b, offset, nir_imm_int(b, 0x4)), nir_imm_int(b, 0)); @@ -174,7 +171,7 @@ ubo_load_select_32b_comps(nir_builder *b, nir_ssa_def *vec32, nir_ssa_def * build_load_ubo_dxil(nir_builder *b, nir_ssa_def *buffer, nir_ssa_def *offset, unsigned num_components, - unsigned bit_size) + unsigned bit_size, unsigned alignment) { nir_ssa_def *idx = nir_ushr(b, offset, nir_imm_int(b, 4)); nir_ssa_def *comps[NIR_MAX_VEC_COMPONENTS]; @@ -193,12 +190,13 @@ build_load_ubo_dxil(nir_builder *b, nir_ssa_def *buffer, nir_load_ubo_dxil(b, 4, 32, buffer, nir_iadd(b, idx, nir_imm_int(b, i / (16 * 8)))); /* First re-arrange the vec32 to account for intra 16-byte offset. */ - vec32 = ubo_load_select_32b_comps(b, vec32, offset, subload_num_bits / 8); + assert(subload_num_bits / 8 <= alignment); + vec32 = ubo_load_select_32b_comps(b, vec32, offset, alignment); /* If we have 2 bytes or less to load we need to adjust the u32 value so * we can always extract the LSB. */ - if (subload_num_bits <= 16) { + if (alignment <= 2) { nir_ssa_def *shift = nir_imul(b, nir_iand(b, offset, nir_imm_int(b, 3)), nir_imm_int(b, 8)); @@ -680,7 +678,8 @@ lower_load_ubo(nir_builder *b, nir_intrinsic_instr *intr) nir_ssa_def *result = build_load_ubo_dxil(b, intr->src[0].ssa, intr->src[1].ssa, nir_dest_num_components(intr->dest), - nir_dest_bit_size(intr->dest)); + nir_dest_bit_size(intr->dest), + nir_intrinsic_align(intr)); nir_ssa_def_rewrite_uses(&intr->dest.ssa, result); nir_instr_remove(&intr->instr); diff --git a/src/microsoft/compiler/dxil_nir.h b/src/microsoft/compiler/dxil_nir.h index 65d302a856d..8238731fc73 100644 --- a/src/microsoft/compiler/dxil_nir.h +++ b/src/microsoft/compiler/dxil_nir.h @@ -55,7 +55,7 @@ bool dxil_nir_lower_vs_vertex_conversion(nir_shader *s, enum pipe_format target_ nir_ssa_def * build_load_ubo_dxil(nir_builder *b, nir_ssa_def *buffer, nir_ssa_def *offset, unsigned num_components, - unsigned bit_size); + unsigned bit_size, unsigned alignment); uint64_t dxil_sort_by_driver_location(nir_shader* s, nir_variable_mode modes); diff --git a/src/microsoft/spirv_to_dxil/dxil_spirv_nir.c b/src/microsoft/spirv_to_dxil/dxil_spirv_nir.c index 28488eaa670..8bebc1e1111 100644 --- a/src/microsoft/spirv_to_dxil/dxil_spirv_nir.c +++ b/src/microsoft/spirv_to_dxil/dxil_spirv_nir.c @@ -212,10 +212,15 @@ lower_shader_system_values(struct nir_builder *builder, nir_instr *instr, nir_address_format_bit_size(ubo_format), index, .desc_type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER); + unsigned num_components = nir_dest_num_components(intrin->dest); + unsigned alignment = (num_components == 3 ? 4 : num_components) * + nir_dest_bit_size(intrin->dest) / 8; + assert(offset % alignment == 0); nir_ssa_def *load_data = build_load_ubo_dxil( builder, nir_channel(builder, load_desc, 0), nir_imm_int(builder, offset), - nir_dest_num_components(intrin->dest), nir_dest_bit_size(intrin->dest)); + num_components, nir_dest_bit_size(intrin->dest), + alignment); nir_ssa_def_rewrite_uses(&intrin->dest.ssa, load_data); nir_instr_remove(instr); @@ -298,7 +303,8 @@ lower_load_push_constant(struct nir_builder *builder, nir_instr *instr, nir_ssa_def *load_data = build_load_ubo_dxil( builder, nir_channel(builder, load_desc, 0), nir_iadd_imm(builder, offset, base), - nir_dest_num_components(intrin->dest), nir_dest_bit_size(intrin->dest)); + nir_dest_num_components(intrin->dest), nir_dest_bit_size(intrin->dest), + nir_intrinsic_align(intrin)); nir_ssa_def_rewrite_uses(&intrin->dest.ssa, load_data); nir_instr_remove(instr); @@ -387,7 +393,7 @@ lower_yz_flip(struct nir_builder *builder, nir_instr *instr, dyn_yz_flip_mask = build_load_ubo_dxil(builder, nir_channel(builder, load_desc, 0), - nir_imm_int(builder, offset), 1, 32); + nir_imm_int(builder, offset), 1, 32, 4); *data->reads_sysval_ubo = true; } @@ -684,7 +690,7 @@ write_pntc_with_pos(nir_builder *b, nir_instr *instr, void *_data) nir_ssa_def *transform = nir_channels(b, build_load_ubo_dxil(b, nir_channel(b, load_desc, 0), - nir_imm_int(b, offset), 4, 32), + nir_imm_int(b, offset), 4, 32, 16), 0x6); nir_ssa_def *point_center_in_clip = nir_fmul(b, nir_channels(b, pos, 0x3), nir_frcp(b, nir_channel(b, pos, 3))); nir_ssa_def *point_center =