From: Marek Olšák <marek.ol...@amd.com> Cc: 17.1 <mesa-sta...@lists.freedesktop.org> --- src/gallium/drivers/radeonsi/si_state.c | 35 ++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-)
diff --git a/src/gallium/drivers/radeonsi/si_state.c b/src/gallium/drivers/radeonsi/si_state.c index a55f024..8a8705f 100644 --- a/src/gallium/drivers/radeonsi/si_state.c +++ b/src/gallium/drivers/radeonsi/si_state.c @@ -2969,21 +2969,54 @@ si_make_buffer_descriptor(struct si_screen *screen, struct r600_resource *buf, desc = util_format_description(format); first_non_void = util_format_get_first_non_void_channel(format); stride = desc->block.bits / 8; num_format = si_translate_buffer_numformat(&screen->b.b, desc, first_non_void); data_format = si_translate_buffer_dataformat(&screen->b.b, desc, first_non_void); num_records = size / stride; num_records = MIN2(num_records, (buf->b.b.width0 - offset) / stride); - if (screen->b.chip_class == VI) + /* The NUM_RECORDS field has a different meaning depending on the chip, + * instruction type, STRIDE, and SWIZZLE_ENABLE. + * + * SI-CIK: + * - If STRIDE == 0, it's in byte units. + * - If STRIDE != 0, it's in units of STRIDE, used with inst.IDXEN. + * + * VI: + * - For SMEM and STRIDE == 0, it's in byte units. + * - For SMEM and STRIDE != 0, it's in units of STRIDE. + * - For VMEM and STRIDE == 0 or SWIZZLE_ENABLE == 0, it's in byte units. + * - For VMEM and STRIDE != 0 and SWIZZLE_ENABLE == 1, it's in units of STRIDE. + * NOTE: There is incompatibility between VMEM and SMEM opcodes due to SWIZZLE_- + * ENABLE. The workaround is to set STRIDE = 0 if SWIZZLE_ENABLE == 0 when + * using SMEM. This can be done in the shader by clearing STRIDE with s_and. + * That way the same descriptor can be used by both SMEM and VMEM. + * + * GFX9: + * - For SMEM and STRIDE == 0, it's in byte units. + * - For SMEM and STRIDE != 0, it's in units of STRIDE. + * - For VMEM and inst.IDXEN == 0 or STRIDE == 0, it's in byte units. + * - For VMEM and inst.IDXEN == 1 and STRIDE != 0, it's in units of STRIDE. + */ + if (screen->b.chip_class >= GFX9) + /* When vindex == 0, LLVM sets IDXEN = 0, thus changing units + * from STRIDE to bytes. This works around it by setting + * NUM_RECORDS to at least the size of one element, so that + * the first element is readable when IDXEN == 0. + * + * TODO: Fix this in LLVM, but do we need a new intrinsic where + * IDXEN is enforced? + */ + num_records = num_records ? MAX2(num_records, stride) : 0; + else if (screen->b.chip_class == VI) num_records *= stride; state[4] = 0; state[5] = S_008F04_STRIDE(stride); state[6] = num_records; state[7] = S_008F0C_DST_SEL_X(si_map_swizzle(desc->swizzle[0])) | S_008F0C_DST_SEL_Y(si_map_swizzle(desc->swizzle[1])) | S_008F0C_DST_SEL_Z(si_map_swizzle(desc->swizzle[2])) | S_008F0C_DST_SEL_W(si_map_swizzle(desc->swizzle[3])) | S_008F0C_NUM_FORMAT(num_format) | -- 2.7.4 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev