From e3c6ed0685dbbdbb6bfe3d217bb8f51fefb79968 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Thu, 27 Oct 2022 13:23:23 -0400 Subject: [PATCH] radeonsi: add an emulated image descriptor for gfx940 Reviewed-by: Pierre-Eric Pelloux-Prayer Part-of: --- src/gallium/drivers/radeonsi/si_descriptors.c | 10 +- src/gallium/drivers/radeonsi/si_pipe.h | 4 +- src/gallium/drivers/radeonsi/si_state.c | 121 +++++++++++++++++- src/gallium/drivers/radeonsi/si_texture.c | 2 +- 4 files changed, 127 insertions(+), 10 deletions(-) diff --git a/src/gallium/drivers/radeonsi/si_descriptors.c b/src/gallium/drivers/radeonsi/si_descriptors.c index 9adda13fc78..8116d33c2e9 100644 --- a/src/gallium/drivers/radeonsi/si_descriptors.c +++ b/src/gallium/drivers/radeonsi/si_descriptors.c @@ -309,6 +309,13 @@ void si_set_mutable_tex_desc_fields(struct si_screen *sscreen, struct si_texture va += (uint64_t)base_level_info->offset_256B * 256; } + if (!sscreen->info.has_image_opcodes) { + /* Set it as a buffer descriptor. */ + state[0] = va; + state[1] |= S_008F04_BASE_ADDRESS_HI(va >> 32); + return; + } + state[0] = va >> 8; state[1] |= S_008F14_BASE_ADDRESS_HI(va >> 40); @@ -822,7 +829,8 @@ static void si_set_shader_image_desc(struct si_context *ctx, const struct pipe_i screen->make_texture_descriptor( screen, tex, false, res->b.b.target, view->format, swizzle, hw_level, hw_level, - view->u.tex.first_layer, view->u.tex.last_layer, width, height, depth, desc, fmask_desc); + view->u.tex.first_layer, view->u.tex.last_layer, width, height, depth, false, + desc, fmask_desc); si_set_mutable_tex_desc_fields(screen, tex, &tex->surface.u.legacy.level[level], level, level, util_format_get_blockwidth(view->format), false, access, desc); diff --git a/src/gallium/drivers/radeonsi/si_pipe.h b/src/gallium/drivers/radeonsi/si_pipe.h index 91efb8b188d..0bc0cd09699 100644 --- a/src/gallium/drivers/radeonsi/si_pipe.h +++ b/src/gallium/drivers/radeonsi/si_pipe.h @@ -561,8 +561,8 @@ struct si_screen { enum pipe_texture_target target, enum pipe_format pipe_format, const unsigned char state_swizzle[4], unsigned first_level, unsigned last_level, unsigned first_layer, unsigned last_layer, - unsigned width, unsigned height, unsigned depth, uint32_t *state, - uint32_t *fmask_state); + unsigned width, unsigned height, unsigned depth, + bool get_bo_metadata, uint32_t *state, uint32_t *fmask_state); unsigned max_memory_usage_kb; unsigned pa_sc_raster_config; diff --git a/src/gallium/drivers/radeonsi/si_state.c b/src/gallium/drivers/radeonsi/si_state.c index 6e856449031..a29504ab831 100644 --- a/src/gallium/drivers/radeonsi/si_state.c +++ b/src/gallium/drivers/radeonsi/si_state.c @@ -4047,6 +4047,101 @@ static unsigned gfx9_border_color_swizzle(const unsigned char swizzle[4]) return bc_swizzle; } +/** + * Translate the parameters to an image descriptor for CDNA image emulation. + * In this function, we choose our own image descriptor format because we emulate image opcodes + * using buffer opcodes. + */ +static void cdna_emu_make_image_descriptor(struct si_screen *screen, struct si_texture *tex, + bool sampler, enum pipe_texture_target target, + enum pipe_format pipe_format, + const unsigned char state_swizzle[4], unsigned first_level, + unsigned last_level, unsigned first_layer, + unsigned last_layer, unsigned width, unsigned height, + unsigned depth, uint32_t *state, uint32_t *fmask_state) +{ + const struct util_format_description *desc = util_format_description(pipe_format); + + /* We don't need support these. We only need enough to support VAAPI and OpenMAX. */ + if (target == PIPE_TEXTURE_CUBE || + target == PIPE_TEXTURE_CUBE_ARRAY || + tex->buffer.b.b.last_level > 0 || + tex->buffer.b.b.nr_samples >= 2 || + desc->colorspace != UTIL_FORMAT_COLORSPACE_RGB || + desc->layout == UTIL_FORMAT_LAYOUT_SUBSAMPLED || + util_format_is_compressed(pipe_format)) { + assert(!"unexpected texture type"); + memset(state, 0, 8 * 4); + return; + } + + /* Adjust the image parameters according to the texture type. */ + switch (target) { + case PIPE_TEXTURE_1D: + height = 1; + FALLTHROUGH; + case PIPE_TEXTURE_2D: + case PIPE_TEXTURE_RECT: + depth = 1; + break; + + case PIPE_TEXTURE_1D_ARRAY: + height = 1; + FALLTHROUGH; + case PIPE_TEXTURE_2D_ARRAY: + first_layer = MIN2(first_layer, tex->buffer.b.b.array_size - 1); + last_layer = MIN2(last_layer, tex->buffer.b.b.array_size - 1); + last_layer = MAX2(last_layer, first_layer); + depth = last_layer - first_layer + 1; + break; + + case PIPE_TEXTURE_3D: + first_layer = 0; + break; + + default: + unreachable("invalid texture target"); + } + + unsigned stride = desc->block.bits / 8; + uint64_t num_records = tex->surface.surf_size / stride; + assert(num_records <= UINT32_MAX); + + /* Prepare the format fields. */ + unsigned char swizzle[4]; + util_format_compose_swizzles(desc->swizzle, state_swizzle, swizzle); + + /* Buffer descriptor */ + state[0] = 0; + state[1] = S_008F04_STRIDE(stride); + state[2] = num_records; + state[3] = S_008F0C_DST_SEL_X(si_map_swizzle(swizzle[0])) | + S_008F0C_DST_SEL_Y(si_map_swizzle(swizzle[1])) | + S_008F0C_DST_SEL_Z(si_map_swizzle(swizzle[2])) | + S_008F0C_DST_SEL_W(si_map_swizzle(swizzle[3])); + + if (screen->info.gfx_level >= GFX10) { + const struct gfx10_format *fmt = &ac_get_gfx10_format_table(&screen->info)[pipe_format]; + + state[3] |= S_008F0C_FORMAT(fmt->img_format) | + S_008F0C_OOB_SELECT(V_008F0C_OOB_SELECT_STRUCTURED_WITH_OFFSET) | + S_008F0C_RESOURCE_LEVEL(screen->info.gfx_level < GFX11); + } else { + int first_non_void = util_format_get_first_non_void_channel(pipe_format); + unsigned num_format = si_translate_buffer_numformat(&screen->b, desc, first_non_void); + unsigned data_format = si_translate_buffer_dataformat(&screen->b, desc, first_non_void); + + state[3] |= S_008F0C_NUM_FORMAT(num_format) | + S_008F0C_DATA_FORMAT(data_format); + } + + /* Additional fields used by image opcode emulation. */ + state[4] = width | (height << 16); + state[5] = depth | (first_layer << 16); + state[6] = tex->surface.u.gfx9.surf_pitch; + state[7] = (uint32_t)tex->surface.u.gfx9.surf_pitch * tex->surface.u.gfx9.surf_height; +} + /** * Build the sampler view descriptor for a texture. */ @@ -4054,8 +4149,15 @@ static void gfx10_make_texture_descriptor( struct si_screen *screen, struct si_texture *tex, bool sampler, enum pipe_texture_target target, enum pipe_format pipe_format, const unsigned char state_swizzle[4], unsigned first_level, unsigned last_level, unsigned first_layer, unsigned last_layer, unsigned width, unsigned height, - unsigned depth, uint32_t *state, uint32_t *fmask_state) + unsigned depth, bool get_bo_metadata, uint32_t *state, uint32_t *fmask_state) { + if (!screen->info.has_image_opcodes && !get_bo_metadata) { + cdna_emu_make_image_descriptor(screen, tex, sampler, target, pipe_format, state_swizzle, + first_level, last_level, first_layer, last_layer, width, + height, depth, state, fmask_state); + return; + } + struct pipe_resource *res = &tex->buffer.b.b; const struct util_format_description *desc; unsigned img_format; @@ -4240,8 +4342,16 @@ static void si_make_texture_descriptor(struct si_screen *screen, struct si_textu const unsigned char state_swizzle[4], unsigned first_level, unsigned last_level, unsigned first_layer, unsigned last_layer, unsigned width, unsigned height, - unsigned depth, uint32_t *state, uint32_t *fmask_state) + unsigned depth, bool get_bo_metadata, + uint32_t *state, uint32_t *fmask_state) { + if (!screen->info.has_image_opcodes && !get_bo_metadata) { + cdna_emu_make_image_descriptor(screen, tex, sampler, target, pipe_format, state_swizzle, + first_level, last_level, first_layer, last_layer, width, + height, depth, state, fmask_state); + return; + } + struct pipe_resource *res = &tex->buffer.b.b; const struct util_format_description *desc; unsigned char swizzle[4]; @@ -4671,7 +4781,7 @@ static struct pipe_sampler_view *si_create_sampler_view(struct pipe_context *ctx sctx->screen, tex, true, state->target, pipe_format, state_swizzle, state->u.tex.first_level, state->u.tex.last_level, state->u.tex.first_layer, last_layer, texture->width0, texture->height0, texture->depth0, - view->state, view->fmask_state); + false, view->state, view->fmask_state); view->base_level_info = &surflevel[0]; view->block_width = util_format_get_blockwidth(pipe_format); @@ -5514,11 +5624,10 @@ void si_init_screen_state_functions(struct si_screen *sscreen) sscreen->b.create_vertex_state = si_pipe_create_vertex_state; sscreen->b.vertex_state_destroy = si_pipe_vertex_state_destroy; - if (sscreen->info.gfx_level >= GFX10) { + if (sscreen->info.gfx_level >= GFX10) sscreen->make_texture_descriptor = gfx10_make_texture_descriptor; - } else { + else sscreen->make_texture_descriptor = si_make_texture_descriptor; - } util_vertex_state_cache_init(&sscreen->vertex_state_cache, si_create_vertex_state, si_vertex_state_destroy); diff --git a/src/gallium/drivers/radeonsi/si_texture.c b/src/gallium/drivers/radeonsi/si_texture.c index 3abc59b6346..a93a417e730 100644 --- a/src/gallium/drivers/radeonsi/si_texture.c +++ b/src/gallium/drivers/radeonsi/si_texture.c @@ -549,7 +549,7 @@ static void si_set_tex_bo_metadata(struct si_screen *sscreen, struct si_texture sscreen->make_texture_descriptor(sscreen, tex, true, res->target, res->format, swizzle, 0, res->last_level, 0, is_array ? res->array_size - 1 : 0, - res->width0, res->height0, res->depth0, desc, NULL); + res->width0, res->height0, res->depth0, true, desc, NULL); si_set_mutable_tex_desc_fields(sscreen, tex, &tex->surface.u.legacy.level[0], 0, 0, tex->surface.blk_w, false, 0, desc);