From 78062fbb7566991f27a0612435509db9e3375f3c Mon Sep 17 00:00:00 2001 From: Simon Perretta Date: Fri, 14 Mar 2025 00:55:36 +0000 Subject: [PATCH] pvr, pco: improved image write (with format) support, handle 111110 Signed-off-by: Simon Perretta Acked-by: Erik Faye-Lund Part-of: --- src/compiler/nir/nir_constant_expressions.py | 20 ++ src/compiler/nir/nir_opcodes.py | 11 + src/imagination/pco/pco_nir_tex.c | 221 ++++++++++++++++++- src/imagination/pco/pco_trans_nir.c | 34 +++ 4 files changed, 285 insertions(+), 1 deletion(-) diff --git a/src/compiler/nir/nir_constant_expressions.py b/src/compiler/nir/nir_constant_expressions.py index 777baf746cc..7e526666b67 100644 --- a/src/compiler/nir/nir_constant_expressions.py +++ b/src/compiler/nir/nir_constant_expressions.py @@ -112,6 +112,16 @@ pack_snorm_1x8(float x) _mesa_roundevenf(CLAMP(x, -1.0f, +1.0f) * 127.0f); } +/** + * Evaluate component [0,2] of packSnorm3x10_1x2. + */ +static uint16_t +pack_snorm_1x10(float x) +{ + return (uint16_t) (int) + _mesa_roundevenf(CLAMP(x, -1.0f, +1.0f) * 511.0f); +} + /** * Evaluate one component of packSnorm2x16. */ @@ -152,6 +162,16 @@ unpack_snorm_1x8(uint8_t u) return CLAMP((int8_t) u / 127.0f, -1.0f, +1.0f); } +/** + * Evaluate component [0,2] of unpackSnorm3x10_1x2. + */ +static float +unpack_snorm_1x10(uint16_t u) +{ + u &= 0x03FF; + return CLAMP((int16_t) u / 511.0f, -1.0f, +1.0f); +} + /** * Evaluate one component of unpackSnorm2x16. */ diff --git a/src/compiler/nir/nir_opcodes.py b/src/compiler/nir/nir_opcodes.py index b629cb17c5d..23a39158b87 100644 --- a/src/compiler/nir/nir_opcodes.py +++ b/src/compiler/nir/nir_opcodes.py @@ -1846,12 +1846,23 @@ pack_rg("unorm", 8, 8) pack_rgb("snorm", 8, 8, 8) pack_rgb("unorm", 8, 8, 8) +pack_r("snorm", 10) +pack_r("unorm", 10) + pack_r("snorm", 16) pack_r("unorm", 16) pack_r("half", 16) pack_rgba("unorm", 10, 10, 10, 2) +unop_horiz(f"pack_float_10", 1, tuint32, 1, tfloat32, f""" +dst.x = f32_to_uf10(src0.x) & 0x3ff; +""") + +unop_horiz(f"pack_float_11", 1, tuint32, 1, tfloat32, f""" +dst.x = f32_to_uf11(src0.x) & 0x7ff; +""") + unop_horiz(f"pack_float_11_11_10", 1, tuint32, 3, tfloat32, f""" dst.x = f32_to_uf11(src0.x) & 0x7ff; dst.x |= (f32_to_uf11(src0.y) & 0x7ff) << 11; diff --git a/src/imagination/pco/pco_nir_tex.c b/src/imagination/pco/pco_nir_tex.c index bf18ab93a07..d87f8653a37 100644 --- a/src/imagination/pco/pco_nir_tex.c +++ b/src/imagination/pco/pco_nir_tex.c @@ -717,6 +717,39 @@ bool pco_nir_lower_tex(nir_shader *shader) return nir_shader_lower_instructions(shader, is_tex, lower_tex, NULL); } +static enum util_format_type nir_type_to_util_type(nir_alu_type nir_type) +{ + switch (nir_alu_type_get_base_type(nir_type)) { + case nir_type_int: + return UTIL_FORMAT_TYPE_SIGNED; + + case nir_type_uint: + return UTIL_FORMAT_TYPE_UNSIGNED; + + case nir_type_float: + return UTIL_FORMAT_TYPE_FLOAT; + + default: + break; + } + + UNREACHABLE("Unsupported nir_alu_type."); +} + +static enum pipe_format nir_type_to_pipe_format(nir_alu_type nir_type, + unsigned num_components) +{ + enum util_format_type format_type = nir_type_to_util_type(nir_type); + unsigned bits = nir_alu_type_get_type_size(nir_type); + bool pure_integer = format_type != UTIL_FORMAT_TYPE_FLOAT; + + return util_format_get_array(format_type, + bits, + num_components, + false, + pure_integer); +} + static nir_def *lower_image(nir_builder *b, nir_instr *instr, void *cb_data) { nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr); @@ -728,6 +761,24 @@ static nir_def *lower_image(nir_builder *b, nir_instr *instr, void *cb_data) unsigned binding = nir_src_comp_as_uint(intr->src[0], 1); nir_def *elem = nir_channel(b, intr->src[0].ssa, 2); + nir_def *lod; + switch (intr->intrinsic) { + case nir_intrinsic_image_deref_load: + lod = intr->src[3].ssa; + break; + + case nir_intrinsic_image_deref_store: + lod = intr->src[4].ssa; + break; + + case nir_intrinsic_image_deref_size: + lod = intr->src[1].ssa; + break; + + default: + UNREACHABLE(""); + } + if (intr->intrinsic == nir_intrinsic_image_deref_size) { if (image_dim == GLSL_SAMPLER_DIM_BUF) { assert(intr->def.num_components == 1); @@ -764,7 +815,6 @@ static nir_def *lower_image(nir_builder *b, nir_instr *instr, void *cb_data) }; nir_def *base_level = STATE_UNPACK(b, tex_state_word, 3, 28, 4); - nir_def *lod = intr->src[0].ssa; lod = nir_iadd(b, lod, base_level); for (unsigned c = 0; c < num_comps; ++c) @@ -795,6 +845,173 @@ static nir_def *lower_image(nir_builder *b, nir_instr *instr, void *cb_data) if (write_data) { assert(intr->num_components == 4); assert(write_data->num_components == 4); + + /* TODO: formatless write support */ + assert(format != PIPE_FORMAT_NONE); + + const struct util_format_description *desc = + util_format_description(format); + + enum pipe_format data_format = + nir_type_to_pipe_format(type, desc->nr_channels); + + /* TODO: u/sint need clamping? */ + + if (format != data_format) { + nir_def *write_data_comps[4]; + for (unsigned c = 0; c < desc->nr_channels; ++c) { + enum pipe_swizzle chan = desc->swizzle[c]; + nir_def *input = nir_channel(b, write_data, c); + + switch (format) { + case PIPE_FORMAT_R8_UINT: + case PIPE_FORMAT_R8G8_UINT: + case PIPE_FORMAT_R8G8B8_UINT: + case PIPE_FORMAT_R8G8B8A8_UINT: + + case PIPE_FORMAT_R8_SINT: + case PIPE_FORMAT_R8G8_SINT: + case PIPE_FORMAT_R8G8B8_SINT: + case PIPE_FORMAT_R8G8B8A8_SINT: + write_data_comps[chan] = + nir_bitfield_insert_imm(b, nir_imm_int(b, 0), input, 0, 8); + break; + + case PIPE_FORMAT_R8_UNORM: + case PIPE_FORMAT_R8G8_UNORM: + case PIPE_FORMAT_R8G8B8_UNORM: + case PIPE_FORMAT_R8G8B8A8_UNORM: + write_data_comps[chan] = nir_pack_unorm_8(b, input); + break; + + case PIPE_FORMAT_R8_SNORM: + case PIPE_FORMAT_R8G8_SNORM: + case PIPE_FORMAT_R8G8B8_SNORM: + case PIPE_FORMAT_R8G8B8A8_SNORM: + write_data_comps[chan] = nir_pack_snorm_8(b, input); + break; + + case PIPE_FORMAT_R11G11B10_FLOAT: + switch (chan) { + case PIPE_SWIZZLE_X: + case PIPE_SWIZZLE_Y: + write_data_comps[chan] = nir_pack_float_11(b, input); + break; + + case PIPE_SWIZZLE_Z: + write_data_comps[chan] = nir_pack_float_10(b, input); + break; + + default: + UNREACHABLE(""); + } + break; + + case PIPE_FORMAT_R10G10B10A2_UINT: + + case PIPE_FORMAT_R10G10B10A2_SINT: + + switch (chan) { + case PIPE_SWIZZLE_X: + case PIPE_SWIZZLE_Y: + case PIPE_SWIZZLE_Z: + write_data_comps[chan] = + nir_bitfield_insert_imm(b, nir_imm_int(b, 0), input, 0, 10); + break; + + case PIPE_SWIZZLE_W: + write_data_comps[chan] = + nir_bitfield_insert_imm(b, nir_imm_int(b, 0), input, 0, 2); + break; + + default: + UNREACHABLE(""); + } + break; + + /* TODO: better way to do the 1x2 component. */ + case PIPE_FORMAT_R10G10B10A2_UNORM: + switch (chan) { + case PIPE_SWIZZLE_X: + case PIPE_SWIZZLE_Y: + case PIPE_SWIZZLE_Z: + write_data_comps[chan] = nir_pack_unorm_10(b, input); + break; + + case PIPE_SWIZZLE_W: + write_data_comps[chan] = + nir_f2i32_rtne(b, + nir_fmul_imm(b, nir_fsat(b, input), 3.0f)); + break; + + default: + UNREACHABLE(""); + } + break; + + /* TODO: better way to do the 1x2 component. */ + case PIPE_FORMAT_R10G10B10A2_SNORM: + switch (chan) { + case PIPE_SWIZZLE_X: + case PIPE_SWIZZLE_Y: + case PIPE_SWIZZLE_Z: + write_data_comps[chan] = nir_pack_snorm_10(b, input); + break; + + case PIPE_SWIZZLE_W: + write_data_comps[chan] = + nir_f2i32_rtne(b, nir_fsat_signed(b, input)); + break; + + default: + UNREACHABLE(""); + } + break; + + case PIPE_FORMAT_R16_UINT: + case PIPE_FORMAT_R16G16_UINT: + case PIPE_FORMAT_R16G16B16_UINT: + case PIPE_FORMAT_R16G16B16A16_UINT: + + case PIPE_FORMAT_R16_SINT: + case PIPE_FORMAT_R16G16_SINT: + case PIPE_FORMAT_R16G16B16_SINT: + case PIPE_FORMAT_R16G16B16A16_SINT: + write_data_comps[chan] = + nir_bitfield_insert_imm(b, nir_imm_int(b, 0), input, 0, 16); + break; + + case PIPE_FORMAT_R16_FLOAT: + case PIPE_FORMAT_R16G16_FLOAT: + case PIPE_FORMAT_R16G16B16_FLOAT: + case PIPE_FORMAT_R16G16B16A16_FLOAT: + write_data_comps[chan] = nir_pack_half_16(b, input); + break; + + case PIPE_FORMAT_R16_UNORM: + case PIPE_FORMAT_R16G16_UNORM: + case PIPE_FORMAT_R16G16B16_UNORM: + case PIPE_FORMAT_R16G16B16A16_UNORM: + write_data_comps[chan] = nir_pack_unorm_16(b, input); + break; + + case PIPE_FORMAT_R16_SNORM: + case PIPE_FORMAT_R16G16_SNORM: + case PIPE_FORMAT_R16G16B16_SNORM: + case PIPE_FORMAT_R16G16B16A16_SNORM: + write_data_comps[chan] = nir_pack_snorm_16(b, input); + break; + + default: + printf("Unsupported image write pack format %s.\n", + util_format_name(format)); + UNREACHABLE(""); + } + } + + write_data = nir_vec(b, write_data_comps, desc->nr_channels); + write_data = nir_pad_vector(b, write_data, 4); + } } bool ia = image_dim == GLSL_SAMPLER_DIM_SUBPASS || @@ -867,6 +1084,8 @@ static nir_def *lower_image(nir_builder *b, nir_instr *instr, void *cb_data) .write_data = write_data, + .lod_replace = lod, + .sample_components = intr->intrinsic == nir_intrinsic_image_deref_load ? intr->def.num_components : 0, diff --git a/src/imagination/pco/pco_trans_nir.c b/src/imagination/pco/pco_trans_nir.c index deba18b2136..42bbc2fe01b 100644 --- a/src/imagination/pco/pco_trans_nir.c +++ b/src/imagination/pco/pco_trans_nir.c @@ -2528,6 +2528,40 @@ static pco_instr *trans_alu(trans_ctx *tctx, nir_alu_instr *alu) .scale = true); break; + case nir_op_pack_unorm_10: + instr = pco_pck(&tctx->b, + dest, + src[0], + .rpt = 1, + .pck_fmt = PCO_PCK_FMT_U1010102, + .scale = true); + break; + + case nir_op_pack_snorm_10: + instr = pco_pck(&tctx->b, + dest, + src[0], + .rpt = 1, + .pck_fmt = PCO_PCK_FMT_S1010102, + .scale = true); + break; + + case nir_op_pack_float_10: + instr = pco_pck(&tctx->b, + dest, + src[0], + .rpt = 1, + .pck_fmt = PCO_PCK_FMT_2F10F10F10); + break; + + case nir_op_pack_float_11: + instr = pco_pck(&tctx->b, + dest, + src[0], + .rpt = 1, + .pck_fmt = PCO_PCK_FMT_F111110); + break; + case nir_op_pack_float_11_11_10: instr = pco_pck(&tctx->b, dest,