[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