[Mesa-dev] [RFC PATCH 61/65] radeonsi: upload new descriptors when resident buffers are invalidated
Samuel Pitoiset
samuel.pitoiset at gmail.com
Fri May 19 16:53:06 UTC 2017
When texture buffers are invalidated the addr in the resident
descriptor has to be updated but we can't create a new descriptor
because the resident handle has to be the same.
Instead, use the WRITE_DATA packet which allows to update memory
directly but graphics/compute have to be idle in case the GPU is
reading the descriptor.
Signed-off-by: Samuel Pitoiset <samuel.pitoiset at gmail.com>
---
src/gallium/drivers/radeon/r600_pipe_common.h | 4 +
src/gallium/drivers/radeonsi/si_descriptors.c | 121 ++++++++++++++++++++++++++
src/gallium/drivers/radeonsi/si_pipe.h | 3 +
3 files changed, 128 insertions(+)
diff --git a/src/gallium/drivers/radeon/r600_pipe_common.h b/src/gallium/drivers/radeon/r600_pipe_common.h
index b17b690fab..6c4df2e733 100644
--- a/src/gallium/drivers/radeon/r600_pipe_common.h
+++ b/src/gallium/drivers/radeon/r600_pipe_common.h
@@ -181,6 +181,10 @@ struct r600_resource {
/* Whether the resource has been exported via resource_get_handle. */
unsigned external_usage; /* PIPE_HANDLE_USAGE_* */
+
+ /* Whether this resource is referenced by bindless handles. */
+ bool texture_handle_allocated;
+ bool image_handle_allocated;
};
struct r600_transfer {
diff --git a/src/gallium/drivers/radeonsi/si_descriptors.c b/src/gallium/drivers/radeonsi/si_descriptors.c
index 05559d90d7..6adad06757 100644
--- a/src/gallium/drivers/radeonsi/si_descriptors.c
+++ b/src/gallium/drivers/radeonsi/si_descriptors.c
@@ -1849,6 +1849,55 @@ static void si_rebind_buffer(struct pipe_context *ctx, struct pipe_resource *buf
}
}
}
+
+ /* Bindless texture handles */
+ if (rbuffer->texture_handle_allocated) {
+ for (i = 0; i < sctx->num_resident_tex_handles; i++) {
+ struct si_texture_handle *tex_handle =
+ sctx->resident_tex_handles[i];
+ struct si_sampler_view *sview = tex_handle->view;
+ struct si_resident_descriptor *desc = tex_handle->desc;
+
+ if (sview->base.texture == buf) {
+ si_set_buf_desc_address(rbuffer,
+ sview->base.u.buf.offset,
+ &desc->desc_list[4]);
+ desc->dirty = true;
+ sctx->resident_descriptors_dirty = true;
+
+ radeon_add_to_buffer_list_check_mem(
+ &sctx->b, &sctx->b.gfx, rbuffer,
+ RADEON_USAGE_READ,
+ RADEON_PRIO_SAMPLER_BUFFER, true);
+ }
+ }
+ }
+
+ /* Bindless image handles */
+ if (rbuffer->image_handle_allocated) {
+ for (i = 0; i < sctx->num_resident_img_handles; i++) {
+ struct si_image_handle *img_handle =
+ sctx->resident_img_handles[i];
+ struct pipe_image_view *view = &img_handle->view;
+ struct si_resident_descriptor *desc = img_handle->desc;
+
+ if (view->resource == buf) {
+ if (view->access & PIPE_IMAGE_ACCESS_WRITE)
+ si_mark_image_range_valid(view);
+
+ si_set_buf_desc_address(rbuffer,
+ view->u.buf.offset,
+ &desc->desc_list[4]);
+ desc->dirty = true;
+ sctx->resident_descriptors_dirty = true;
+
+ radeon_add_to_buffer_list_check_mem(
+ &sctx->b, &sctx->b.gfx, rbuffer,
+ RADEON_USAGE_READWRITE,
+ RADEON_PRIO_SAMPLER_BUFFER, true);
+ }
+ }
+ }
}
/* Reallocate a buffer a update all resource bindings where the buffer is
@@ -2365,6 +2414,8 @@ si_create_resident_descriptor(struct si_context *sctx, uint32_t *desc_list,
util_memcpy_cpu_to_le32(ptr + desc->offset, desc_list, size);
sscreen->b.ws->buffer_unmap(desc->buffer->buf);
+ memcpy(desc->desc_list, desc_list, sizeof(desc->desc_list));
+
return desc;
}
@@ -2415,6 +2466,8 @@ static uint64_t si_create_texture_handle(struct pipe_context *ctx,
return 0;
}
+ r600_resource(sview->base.texture)->texture_handle_allocated = true;
+
return handle;
}
@@ -2521,6 +2574,8 @@ static uint64_t si_create_image_handle(struct pipe_context *ctx,
return 0;
}
+ r600_resource(view->resource)->image_handle_allocated = true;
+
return handle;
}
@@ -2800,6 +2855,67 @@ void si_init_all_descriptors(struct si_context *sctx)
si_set_user_data_base(sctx, PIPE_SHADER_FRAGMENT, R_00B030_SPI_SHADER_USER_DATA_PS_0);
}
+static void si_upload_resident_descriptor(struct si_context *sctx,
+ struct si_resident_descriptor *desc)
+{
+ struct radeon_winsys_cs *cs = sctx->b.gfx.cs;
+ uint64_t va = desc->buffer->gpu_address + desc->offset;
+ unsigned num_dwords = sizeof(desc->desc_list) / 4;
+
+ radeon_emit(cs, PKT3(PKT3_WRITE_DATA, 2 + num_dwords, 0));
+ radeon_emit(cs, S_370_DST_SEL(V_370_TC_L2) |
+ S_370_WR_CONFIRM(1) |
+ S_370_ENGINE_SEL(V_370_PFP));
+ radeon_emit(cs, va);
+ radeon_emit(cs, va >> 32);
+ radeon_emit_array(cs, desc->desc_list, num_dwords);
+}
+
+static void si_upload_resident_descriptors(struct si_context *sctx)
+{
+ unsigned i;
+
+ if (!sctx->resident_descriptors_dirty)
+ return;
+
+ /* Wait for graphics/compute to be idle before updating the resident
+ * descriptors directly in memory, in case the GPU is using them.
+ */
+ sctx->b.flags |= SI_CONTEXT_PS_PARTIAL_FLUSH;
+ sctx->b.flags |= SI_CONTEXT_CS_PARTIAL_FLUSH;
+ si_emit_cache_flush(sctx);
+
+ for (i = 0; i < sctx->num_resident_tex_handles; i++) {
+ struct si_texture_handle *tex_handle =
+ sctx->resident_tex_handles[i];
+ struct si_resident_descriptor *desc = tex_handle->desc;
+
+ if (!desc->dirty)
+ continue;
+
+ si_upload_resident_descriptor(sctx, desc);
+ desc->dirty = false;
+ }
+
+ for (i = 0; i < sctx->num_resident_img_handles; i++) {
+ struct si_image_handle *img_handle =
+ sctx->resident_img_handles[i];
+ struct si_resident_descriptor *desc = img_handle->desc;
+
+ if (!desc->dirty)
+ continue;
+
+ si_upload_resident_descriptor(sctx, desc);
+ desc->dirty = false;
+ }
+
+ /* Invalidate L1 because it doesn't know that L2 changed. */
+ sctx->b.flags |= SI_CONTEXT_INV_SMEM_L1;
+ si_emit_cache_flush(sctx);
+
+ sctx->resident_descriptors_dirty = false;
+}
+
bool si_upload_graphics_shader_descriptors(struct si_context *sctx)
{
const unsigned mask = u_bit_consecutive(0, SI_DESCS_FIRST_COMPUTE);
@@ -2817,6 +2933,9 @@ bool si_upload_graphics_shader_descriptors(struct si_context *sctx)
}
sctx->descriptors_dirty &= ~mask;
+
+ si_upload_resident_descriptors(sctx);
+
return true;
}
@@ -2841,6 +2960,8 @@ bool si_upload_compute_shader_descriptors(struct si_context *sctx)
sctx->descriptors_dirty &= ~mask;
+ si_upload_resident_descriptors(sctx);
+
return true;
}
diff --git a/src/gallium/drivers/radeonsi/si_pipe.h b/src/gallium/drivers/radeonsi/si_pipe.h
index c52b364959..f15881c51f 100644
--- a/src/gallium/drivers/radeonsi/si_pipe.h
+++ b/src/gallium/drivers/radeonsi/si_pipe.h
@@ -229,6 +229,8 @@ struct si_resident_descriptor
struct pb_slab_entry entry;
struct r600_resource *buffer;
unsigned offset;
+ uint32_t desc_list[16];
+ bool dirty;
};
struct si_texture_handle
@@ -415,6 +417,7 @@ struct si_context {
struct r600_resource **resident_descriptors;
unsigned num_resident_descriptors;
unsigned max_resident_descriptors;
+ bool resident_descriptors_dirty;
/* Allocatd bindless handles */
struct hash_table *tex_handles;
--
2.13.0
More information about the mesa-dev
mailing list