From 95c5bbae66af3ca1f805d94f6fe8d8e4ba2c9c43 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Tue, 17 May 2016 20:46:42 +0200 Subject: [PATCH] radeonsi: set some image descriptor fields at bind time MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit mainly the fields that can change by reallocating a texture and changing the tile mode Reviewed-by: Nicolai Hähnle Reviewed-by: Bas Nieuwenhuizen --- src/gallium/drivers/radeonsi/si_descriptors.c | 64 +++++++++--- src/gallium/drivers/radeonsi/si_pipe.h | 3 + src/gallium/drivers/radeonsi/si_state.c | 99 ++++++++----------- src/gallium/drivers/radeonsi/si_state.h | 16 ++- 4 files changed, 111 insertions(+), 71 deletions(-) diff --git a/src/gallium/drivers/radeonsi/si_descriptors.c b/src/gallium/drivers/radeonsi/si_descriptors.c index ec174742353..cc296f9d31e 100644 --- a/src/gallium/drivers/radeonsi/si_descriptors.c +++ b/src/gallium/drivers/radeonsi/si_descriptors.c @@ -60,6 +60,7 @@ #include "si_shader.h" #include "sid.h" +#include "util/u_format.h" #include "util/u_math.h" #include "util/u_memory.h" #include "util/u_suballoc.h" @@ -294,40 +295,70 @@ static void si_sampler_views_begin_new_cs(struct si_context *sctx, RADEON_USAGE_READWRITE, RADEON_PRIO_DESCRIPTORS); } +void si_set_mutable_tex_desc_fields(struct r600_texture *tex, + const struct radeon_surf_level *base_level_info, + unsigned base_level, unsigned block_width, + bool is_stencil, uint32_t *state) +{ + uint64_t va = tex->resource.gpu_address + base_level_info->offset; + unsigned pitch = base_level_info->nblk_x * block_width; + + state[1] &= C_008F14_BASE_ADDRESS_HI; + state[3] &= C_008F1C_TILING_INDEX; + state[4] &= C_008F20_PITCH; + state[6] &= C_008F28_COMPRESSION_EN; + + state[0] = va >> 8; + state[1] |= S_008F14_BASE_ADDRESS_HI(va >> 40); + state[3] |= S_008F1C_TILING_INDEX(si_tile_mode_index(tex, base_level, + is_stencil)); + state[4] |= S_008F20_PITCH(pitch - 1); + + if (tex->dcc_offset) { + state[6] |= S_008F28_COMPRESSION_EN(1); + state[7] = (tex->resource.gpu_address + + tex->dcc_offset + + base_level_info->dcc_offset) >> 8; + } +} + static void si_set_sampler_view(struct si_context *sctx, struct si_sampler_views *views, unsigned slot, struct pipe_sampler_view *view) { struct si_sampler_view *rview = (struct si_sampler_view*)view; - if (view && view->texture && view->texture->target != PIPE_BUFFER && - G_008F28_COMPRESSION_EN(rview->state[6]) && - ((struct r600_texture*)view->texture)->dcc_offset == 0) { - rview->state[6] &= C_008F28_COMPRESSION_EN & - C_008F28_ALPHA_IS_ON_MSB; - } else if (views->views[slot] == view) + if (views->views[slot] == view) return; if (view) { struct r600_texture *rtex = (struct r600_texture *)view->texture; + uint32_t *desc = views->desc.list + slot * 16; si_sampler_view_add_buffer(sctx, view->texture, RADEON_USAGE_READ); pipe_sampler_view_reference(&views->views[slot], view); - memcpy(views->desc.list + slot * 16, rview->state, 8*4); + memcpy(desc, rview->state, 8*4); + + if (view->texture && view->texture->target != PIPE_BUFFER) + si_set_mutable_tex_desc_fields(rtex, + rview->base_level_info, + rview->base_level, + rview->block_width, + false, desc); if (view->texture && view->texture->target != PIPE_BUFFER && rtex->fmask.size) { - memcpy(views->desc.list + slot*16 + 8, + memcpy(desc + 8, rview->fmask_state, 8*4); } else { /* Disable FMASK and bind sampler state in [12:15]. */ - memcpy(views->desc.list + slot*16 + 8, + memcpy(desc + 8, null_texture_descriptor, 4*4); if (views->sampler_states[slot]) - memcpy(views->desc.list + slot*16 + 12, + memcpy(desc + 12, views->sampler_states[slot], 4*4); } @@ -517,6 +548,7 @@ si_set_shader_images(struct pipe_context *pipe, unsigned shader, struct r600_texture *tex = (struct r600_texture *)res; unsigned level; unsigned width, height, depth; + uint32_t *desc = images->desc.list + slot * 8; assert(!tex->is_depth); assert(tex->fmask.size == 0); @@ -546,13 +578,17 @@ si_set_shader_images(struct pipe_context *pipe, unsigned shader, height = u_minify(res->b.b.height0, level); depth = u_minify(res->b.b.depth0, level); - si_make_texture_descriptor(screen, tex, false, res->b.b.target, + si_make_texture_descriptor(screen, tex, + false, res->b.b.target, views[i].format, swizzle, - level, 0, 0, + 0, 0, views[i].u.tex.first_layer, views[i].u.tex.last_layer, width, height, depth, - images->desc.list + slot * 8, - NULL); + desc, NULL); + si_set_mutable_tex_desc_fields(tex, tex->surface.level, + level, + util_format_get_blockwidth(views[i].format), + false, desc); } images->desc.enabled_mask |= 1u << slot; diff --git a/src/gallium/drivers/radeonsi/si_pipe.h b/src/gallium/drivers/radeonsi/si_pipe.h index b48b1bba4ad..b3fe6562c85 100644 --- a/src/gallium/drivers/radeonsi/si_pipe.h +++ b/src/gallium/drivers/radeonsi/si_pipe.h @@ -121,6 +121,9 @@ struct si_sampler_view { * [4..7] = buffer descriptor */ uint32_t state[8]; uint32_t fmask_state[8]; + const struct radeon_surf_level *base_level_info; + unsigned base_level; + unsigned block_width; bool is_stencil_sampler; }; diff --git a/src/gallium/drivers/radeonsi/si_state.c b/src/gallium/drivers/radeonsi/si_state.c index 58cbac4a4c0..fbd0b4f0833 100644 --- a/src/gallium/drivers/radeonsi/si_state.c +++ b/src/gallium/drivers/radeonsi/si_state.c @@ -1834,19 +1834,6 @@ boolean si_is_format_supported(struct pipe_screen *screen, return retval == usage; } -static unsigned si_tile_mode_index(struct r600_texture *rtex, unsigned level, - bool stencil) -{ - unsigned tile_mode_index = 0; - - if (stencil) { - tile_mode_index = rtex->surface.stencil_tiling_index[level]; - } else { - tile_mode_index = rtex->surface.tiling_index[level]; - } - return tile_mode_index; -} - /* * framebuffer handling */ @@ -2639,42 +2626,19 @@ si_make_texture_descriptor(struct si_screen *screen, enum pipe_texture_target target, enum pipe_format pipe_format, const unsigned char state_swizzle[4], - unsigned base_level, unsigned first_level, unsigned last_level, + 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) { struct pipe_resource *res = &tex->resource.b.b; - const struct radeon_surf_level *surflevel = tex->surface.level; const struct util_format_description *desc; unsigned char swizzle[4]; int first_non_void; unsigned num_format, data_format, type; - uint32_t pitch; uint64_t va; - /* Texturing with separate depth and stencil. */ - if (tex->is_depth && !tex->is_flushing_texture) { - switch (pipe_format) { - case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT: - pipe_format = PIPE_FORMAT_Z32_FLOAT; - break; - case PIPE_FORMAT_X8Z24_UNORM: - case PIPE_FORMAT_S8_UINT_Z24_UNORM: - /* Z24 is always stored like this. */ - pipe_format = PIPE_FORMAT_Z24X8_UNORM; - break; - case PIPE_FORMAT_X24S8_UINT: - case PIPE_FORMAT_S8X24_UINT: - case PIPE_FORMAT_X32_S8X24_UINT: - pipe_format = PIPE_FORMAT_S8_UINT; - surflevel = tex->surface.stencil_level; - break; - default:; - } - } - desc = util_format_description(pipe_format); if (desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) { @@ -2794,12 +2758,8 @@ si_make_texture_descriptor(struct si_screen *screen, } else if (type == V_008F1C_SQ_RSRC_IMG_CUBE) depth = res->array_size / 6; - pitch = surflevel[base_level].nblk_x * util_format_get_blockwidth(pipe_format); - va = tex->resource.gpu_address + surflevel[base_level].offset; - - state[0] = va >> 8; - state[1] = (S_008F14_BASE_ADDRESS_HI(va >> 40) | - S_008F14_DATA_FORMAT(data_format) | + state[0] = 0; + state[1] = (S_008F14_DATA_FORMAT(data_format) | S_008F14_NUM_FORMAT(num_format)); state[2] = (S_008F18_WIDTH(width - 1) | S_008F18_HEIGHT(height - 1)); @@ -2812,24 +2772,19 @@ si_make_texture_descriptor(struct si_screen *screen, S_008F1C_LAST_LEVEL(res->nr_samples > 1 ? util_logbase2(res->nr_samples) : last_level) | - S_008F1C_TILING_INDEX(si_tile_mode_index(tex, base_level, false)) | S_008F1C_POW2_PAD(res->last_level > 0) | S_008F1C_TYPE(type)); - state[4] = (S_008F20_DEPTH(depth - 1) | S_008F20_PITCH(pitch - 1)); + state[4] = S_008F20_DEPTH(depth - 1); state[5] = (S_008F24_BASE_ARRAY(first_layer) | S_008F24_LAST_ARRAY(last_layer)); + state[6] = 0; + state[7] = 0; if (tex->dcc_offset) { unsigned swap = r600_translate_colorswap(pipe_format, FALSE); - state[6] = S_008F28_COMPRESSION_EN(1) | S_008F28_ALPHA_IS_ON_MSB(swap <= 1); - state[7] = (tex->resource.gpu_address + - tex->dcc_offset + - surflevel[base_level].dcc_offset) >> 8; + state[6] = S_008F28_ALPHA_IS_ON_MSB(swap <= 1); } else { - state[6] = 0; - state[7] = 0; - /* The last dword is unused by hw. The shader uses it to clear * bits in the first dword of sampler state. */ @@ -2907,6 +2862,8 @@ si_create_sampler_view_custom(struct pipe_context *ctx, unsigned char state_swizzle[4]; unsigned height, depth, width; unsigned last_layer = state->u.tex.last_layer; + enum pipe_format pipe_format; + const struct radeon_surf_level *surflevel; if (!view) return NULL; @@ -2978,13 +2935,40 @@ si_create_sampler_view_custom(struct pipe_context *ctx, state->target == PIPE_TEXTURE_CUBE) last_layer = state->u.tex.first_layer; - si_make_texture_descriptor(sctx->screen, tmp, true, state->target, - state->format, state_swizzle, - base_level, first_level, last_level, + /* Texturing with separate depth and stencil. */ + pipe_format = state->format; + surflevel = tmp->surface.level; + + if (tmp->is_depth && !tmp->is_flushing_texture) { + switch (pipe_format) { + case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT: + pipe_format = PIPE_FORMAT_Z32_FLOAT; + break; + case PIPE_FORMAT_X8Z24_UNORM: + case PIPE_FORMAT_S8_UINT_Z24_UNORM: + /* Z24 is always stored like this. */ + pipe_format = PIPE_FORMAT_Z24X8_UNORM; + break; + case PIPE_FORMAT_X24S8_UINT: + case PIPE_FORMAT_S8X24_UINT: + case PIPE_FORMAT_X32_S8X24_UINT: + pipe_format = PIPE_FORMAT_S8_UINT; + surflevel = tmp->surface.stencil_level; + break; + default:; + } + } + + si_make_texture_descriptor(sctx->screen, tmp, true, + state->target, pipe_format, state_swizzle, + first_level, last_level, state->u.tex.first_layer, last_layer, width, height, depth, view->state, view->fmask_state); + view->base_level_info = &surflevel[base_level]; + view->base_level = base_level; + view->block_width = util_format_get_blockwidth(pipe_format); return &view->base; } @@ -3458,11 +3442,14 @@ static void si_query_opaque_metadata(struct r600_common_screen *rscreen, si_make_texture_descriptor(sscreen, rtex, true, res->target, res->format, - swizzle, 0, 0, res->last_level, 0, + swizzle, 0, res->last_level, 0, is_array ? res->array_size - 1 : 0, res->width0, res->height0, res->depth0, desc, NULL); + si_set_mutable_tex_desc_fields(rtex, &rtex->surface.level[0], 0, + rtex->surface.blk_w, false, desc); + /* Clear the base address and set the relative DCC offset. */ desc[0] = 0; desc[1] &= C_008F14_BASE_ADDRESS_HI; diff --git a/src/gallium/drivers/radeonsi/si_state.h b/src/gallium/drivers/radeonsi/si_state.h index 01b73f607ba..4d069934b18 100644 --- a/src/gallium/drivers/radeonsi/si_state.h +++ b/src/gallium/drivers/radeonsi/si_state.h @@ -251,6 +251,10 @@ struct si_buffer_resources { /* si_descriptors.c */ void si_ce_enable_loads(struct radeon_winsys_cs *ib); +void si_set_mutable_tex_desc_fields(struct r600_texture *tex, + const struct radeon_surf_level *base_level_info, + unsigned base_level, unsigned block_width, + bool is_stencil, uint32_t *state); void si_set_ring_buffer(struct pipe_context *ctx, uint slot, struct pipe_resource *buffer, unsigned stride, unsigned num_records, @@ -297,7 +301,7 @@ si_make_texture_descriptor(struct si_screen *screen, enum pipe_texture_target target, enum pipe_format pipe_format, const unsigned char state_swizzle[4], - unsigned base_level, unsigned first_level, unsigned last_level, + unsigned first_level, unsigned last_level, unsigned first_layer, unsigned last_layer, unsigned width, unsigned height, unsigned depth, uint32_t *state, @@ -323,4 +327,14 @@ void si_ce_post_draw_synchronization(struct si_context *sctx); void si_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *dinfo); void si_trace_emit(struct si_context *sctx); + +static inline unsigned +si_tile_mode_index(struct r600_texture *rtex, unsigned level, bool stencil) +{ + if (stencil) + return rtex->surface.stencil_tiling_index[level]; + else + return rtex->surface.tiling_index[level]; +} + #endif -- 2.30.2