diff --git a/src/amd/common/ac_descriptors.c b/src/amd/common/ac_descriptors.c index b951e490d03..421f9df866f 100644 --- a/src/amd/common/ac_descriptors.c +++ b/src/amd/common/ac_descriptors.c @@ -6,8 +6,10 @@ */ #include "ac_descriptors.h" +#include "ac_formats.h" #include "ac_surface.h" +#include "gfx10_format_table.h" #include "sid.h" #include "util/u_math.h" @@ -484,3 +486,104 @@ ac_set_mutable_tex_desc_fields(const struct radeon_info *info, const struct ac_m } } } + +void +ac_build_buffer_descriptor(const enum amd_gfx_level gfx_level, const struct ac_buffer_state *state, uint32_t desc[4]) +{ + uint32_t rsrc_word1 = S_008F04_BASE_ADDRESS_HI(state->va >> 32) | S_008F04_STRIDE(state->stride); + + if (gfx_level >= GFX11) { + rsrc_word1 |= S_008F04_SWIZZLE_ENABLE_GFX11(state->swizzle_enable); + } else { + rsrc_word1 |= S_008F04_SWIZZLE_ENABLE_GFX6(state->swizzle_enable); + } + + uint32_t rsrc_word3 = S_008F0C_DST_SEL_X(ac_map_swizzle(state->swizzle[0])) | + S_008F0C_DST_SEL_Y(ac_map_swizzle(state->swizzle[1])) | + S_008F0C_DST_SEL_Z(ac_map_swizzle(state->swizzle[2])) | + S_008F0C_DST_SEL_W(ac_map_swizzle(state->swizzle[3])) | + S_008F0C_INDEX_STRIDE(state->index_stride) | + S_008F0C_ADD_TID_ENABLE(state->add_tid); + + if (gfx_level >= GFX10) { + const struct gfx10_format *fmt = &ac_get_gfx10_format_table(gfx_level)[state->format]; + + /* OOB_SELECT chooses the out-of-bounds check. + * + * GFX10: + * - 0: (index >= NUM_RECORDS) || (offset >= STRIDE) + * - 1: index >= NUM_RECORDS + * - 2: NUM_RECORDS == 0 + * - 3: if SWIZZLE_ENABLE: + * swizzle_address >= NUM_RECORDS + * else: + * offset >= NUM_RECORDS + * + * GFX11+: + * - 0: (index >= NUM_RECORDS) || (offset+payload > STRIDE) + * - 1: index >= NUM_RECORDS + * - 2: NUM_RECORDS == 0 + * - 3: if SWIZZLE_ENABLE && STRIDE: + * (index >= NUM_RECORDS) || ( offset+payload > STRIDE) + * else: + * offset+payload > NUM_RECORDS + */ + rsrc_word3 |= gfx_level >= GFX12 ? S_008F0C_FORMAT_GFX12(fmt->img_format) : + S_008F0C_FORMAT_GFX10(fmt->img_format) | + S_008F0C_OOB_SELECT(state->gfx10_oob_select) | + S_008F0C_RESOURCE_LEVEL(gfx_level < GFX11); + } else { + const struct util_format_description * desc = util_format_description(state->format); + const int first_non_void = util_format_get_first_non_void_channel(state->format); + const uint32_t num_format = ac_translate_buffer_numformat(desc, first_non_void); + + /* DATA_FORMAT is STRIDE[14:17] for MUBUF with ADD_TID_ENABLE=1 */ + const uint32_t data_format = + gfx_level >= GFX8 && state->add_tid ? 0 : ac_translate_buffer_dataformat(desc, first_non_void); + + rsrc_word3 |= S_008F0C_NUM_FORMAT(num_format) | + S_008F0C_DATA_FORMAT(data_format) | + S_008F0C_ELEMENT_SIZE(state->element_size); + } + + desc[0] = state->va; + desc[1] = rsrc_word1; + desc[2] = state->size; + desc[3] = rsrc_word3; +} + +void +ac_build_raw_buffer_descriptor(const enum amd_gfx_level gfx_level, uint64_t va, uint32_t size, uint32_t desc[4]) +{ + const struct ac_buffer_state ac_state = { + .va = va, + .size = size, + .format = PIPE_FORMAT_R32_FLOAT, + .swizzle = { + PIPE_SWIZZLE_X, PIPE_SWIZZLE_Y, PIPE_SWIZZLE_Z, PIPE_SWIZZLE_W, + }, + .gfx10_oob_select = V_008F0C_OOB_SELECT_RAW, + }; + + ac_build_buffer_descriptor(gfx_level, &ac_state, desc); +} + +void +ac_build_attr_ring_descriptor(const enum amd_gfx_level gfx_level, uint64_t va, uint32_t size, uint32_t desc[4]) +{ + assert(gfx_level >= GFX11); + + const struct ac_buffer_state ac_state = { + .va = va, + .size = size, + .format = PIPE_FORMAT_R32G32B32A32_FLOAT, + .swizzle = { + PIPE_SWIZZLE_X, PIPE_SWIZZLE_Y, PIPE_SWIZZLE_Z, PIPE_SWIZZLE_W, + }, + .gfx10_oob_select = V_008F0C_OOB_SELECT_STRUCTURED_WITH_OFFSET, + .swizzle_enable = 3, /* 16B */ + .index_stride = 2, /* 32 elements */ + }; + + ac_build_buffer_descriptor(gfx_level, &ac_state, desc); +} diff --git a/src/amd/common/ac_descriptors.h b/src/amd/common/ac_descriptors.h index ebdd39189f9..723cfa588d3 100644 --- a/src/amd/common/ac_descriptors.h +++ b/src/amd/common/ac_descriptors.h @@ -11,6 +11,8 @@ #include "ac_gpu_info.h" #include "ac_surface.h" +#include "util/format/u_format.h" + #ifdef __cplusplus extern "C" { #endif @@ -98,6 +100,36 @@ ac_set_mutable_tex_desc_fields(const struct radeon_info *info, const struct ac_mutable_tex_state *state, uint32_t desc[8]); +struct ac_buffer_state { + uint64_t va; + uint32_t size; + enum pipe_format format; + enum pipe_swizzle swizzle[4]; + uint32_t stride; + uint32_t swizzle_enable : 2; + uint32_t element_size : 2; + uint32_t index_stride : 2; + uint32_t add_tid : 1; + uint32_t gfx10_oob_select : 2; +}; + +void +ac_build_buffer_descriptor(const enum amd_gfx_level gfx_level, + const struct ac_buffer_state *state, + uint32_t desc[4]); + +void +ac_build_raw_buffer_descriptor(const enum amd_gfx_level gfx_level, + uint64_t va, + uint32_t size, + uint32_t desc[4]); + +void +ac_build_attr_ring_descriptor(const enum amd_gfx_level gfx_level, + uint64_t va, + uint32_t size, + uint32_t desc[4]); + #ifdef __cplusplus } #endif