diff --git a/src/imagination/pco/pco_nir.c b/src/imagination/pco/pco_nir.c index 3a7eef6445e..db5610faf51 100644 --- a/src/imagination/pco/pco_nir.c +++ b/src/imagination/pco/pco_nir.c @@ -21,6 +21,8 @@ static const struct spirv_to_nir_options spirv_options = { .environment = NIR_SPIRV_VULKAN, + .ubo_addr_format = nir_address_format_vec2_index_32bit_offset, + .min_ubo_alignment = PVR_UNIFORM_BUFFER_OFFSET_ALIGNMENT, .min_ssbo_alignment = PVR_STORAGE_BUFFER_OFFSET_ALIGNMENT, }; @@ -82,6 +84,20 @@ void pco_preprocess_nir(pco_ctx *ctx, nir_shader *nir) nir, nir_split_array_vars, nir_var_function_temp | nir_var_shader_temp); + + NIR_PASS(_, + nir, + nir_lower_io_vars_to_temporaries, + nir_shader_get_entrypoint(nir), + true, + true); + + NIR_PASS(_, nir, nir_split_var_copies); + NIR_PASS(_, nir, nir_lower_var_copies); + NIR_PASS(_, nir, nir_lower_global_vars_to_local); + NIR_PASS(_, nir, nir_lower_vars_to_ssa); + NIR_PASS(_, nir, nir_remove_dead_derefs); + NIR_PASS(_, nir, nir_lower_indirect_derefs, @@ -93,7 +109,9 @@ void pco_preprocess_nir(pco_ctx *ctx, nir_shader *nir) nir_remove_dead_variables, nir_var_function_temp | nir_var_shader_temp, NULL); + NIR_PASS(_, nir, nir_copy_prop); NIR_PASS(_, nir, nir_opt_dce); + NIR_PASS(_, nir, nir_opt_cse); if (pco_should_print_nir(nir)) { puts("after pco_preprocess_nir:"); @@ -166,6 +184,14 @@ static bool frag_pos_filter(const nir_instr *instr, UNUSED const void *data) */ void pco_lower_nir(pco_ctx *ctx, nir_shader *nir, pco_data *data) { + NIR_PASS(_, + nir, + nir_lower_explicit_io, + nir_var_mem_ubo, + spirv_options.ubo_addr_format); + + NIR_PASS(_, nir, pco_nir_lower_vk, &data->common); + NIR_PASS(_, nir, nir_lower_io, @@ -204,6 +230,13 @@ void pco_lower_nir(pco_ctx *ctx, nir_shader *nir, pco_data *data) NIR_PASS(_, nir, nir_lower_pack); NIR_PASS(_, nir, nir_opt_algebraic); NIR_PASS(_, nir, pco_nir_lower_algebraic); + NIR_PASS(_, nir, nir_opt_constant_folding); + NIR_PASS(_, nir, nir_opt_algebraic); + NIR_PASS(_, nir, pco_nir_lower_algebraic); + NIR_PASS(_, nir, nir_opt_constant_folding); + + NIR_PASS(_, nir, nir_lower_alu_to_scalar, NULL, NULL); + do { progress = false; @@ -237,8 +270,6 @@ void pco_lower_nir(pco_ctx *ctx, nir_shader *nir, pco_data *data) NULL); } - NIR_PASS(_, nir, nir_lower_alu_to_scalar, NULL, NULL); - do { progress = false; @@ -339,6 +370,9 @@ static void gather_data(nir_shader *nir, pco_data *data) */ void pco_postprocess_nir(pco_ctx *ctx, nir_shader *nir, pco_data *data) { + NIR_PASS(_, nir, nir_opt_sink, ~0U); + NIR_PASS(_, nir, nir_opt_move, ~0U); + NIR_PASS(_, nir, nir_move_vec_src_uses_to_dest, false); /* Re-index everything. */ diff --git a/src/imagination/pco/pco_trans_nir.c b/src/imagination/pco/pco_trans_nir.c index 560d09c9296..51eaeed494a 100644 --- a/src/imagination/pco/pco_trans_nir.c +++ b/src/imagination/pco/pco_trans_nir.c @@ -408,6 +408,70 @@ trans_store_output_fs(trans_ctx *tctx, nir_intrinsic_instr *intr, pco_ref src) return pco_mov(&tctx->b, dest, src, .olchk = true); } +static unsigned fetch_resource_base_reg(const pco_common_data *common, + uint32_t packed_desc, + unsigned elem) +{ + unsigned desc_set; + unsigned binding; + pco_unpack_desc(packed_desc, &desc_set, &binding); + + assert(desc_set < ARRAY_SIZE(common->desc_sets)); + const pco_descriptor_set_data *desc_set_data = &common->desc_sets[desc_set]; + assert(desc_set_data->used); + assert(desc_set_data->bindings && binding < desc_set_data->binding_count); + + const pco_binding_data *binding_data = &desc_set_data->bindings[binding]; + assert(binding_data->used); + + unsigned reg_offset = elem * binding_data->range.stride; + assert(reg_offset < binding_data->range.count); + + unsigned reg_index = binding_data->range.start + reg_offset; + + return reg_index; +} + +static pco_instr *trans_load_ubo(trans_ctx *tctx, + nir_intrinsic_instr *intr, + pco_ref dest, + pco_ref offset_src) +{ + const pco_common_data *common = &tctx->shader->data.common; + + unsigned chans = pco_ref_get_chans(dest); + ASSERTED unsigned bits = pco_ref_get_bits(dest); + assert(bits == 32); + + uint32_t packed_desc = nir_src_comp_as_uint(intr->src[0], 0); + unsigned elem = nir_src_comp_as_uint(intr->src[0], 1); + unsigned sh_index = fetch_resource_base_reg(common, packed_desc, elem); + + pco_ref base_addr[2]; + pco_ref_hwreg_addr_comps(sh_index, PCO_REG_CLASS_SHARED, base_addr); + + pco_ref addr_comps[2]; + pco_ref_new_ssa_addr_comps(tctx->func, addr_comps); + + pco_add64_32(&tctx->b, + addr_comps[0], + addr_comps[1], + base_addr[0], + base_addr[1], + offset_src, + pco_ref_null(), + .s = true); + + pco_ref addr = pco_ref_new_ssa_addr(tctx->func); + pco_vec(&tctx->b, addr, ARRAY_SIZE(addr_comps), addr_comps); + + return pco_ld(&tctx->b, + dest, + pco_ref_drc(PCO_DRC_0), + pco_ref_imm8(chans), + addr); +} + /** * \brief Translates a NIR intrinsic instruction into PCO. * @@ -446,6 +510,10 @@ static pco_instr *trans_intr(trans_ctx *tctx, nir_intrinsic_instr *intr) unreachable("Unsupported stage for \"nir_intrinsic_store_output\"."); break; + case nir_intrinsic_load_ubo: + instr = trans_load_ubo(tctx, intr, dest, src[1]); + break; + default: printf("Unsupported intrinsic: \""); nir_print_instr(&intr->instr, stdout);