summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/radeonsi/cik_sdma.c
diff options
context:
space:
mode:
authorMarek Olšák <[email protected]>2016-12-24 22:52:45 +0100
committerMarek Olšák <[email protected]>2017-01-05 18:43:23 +0100
commitd4c0ad4de8c4eeec1cc0478b12ce542e9a7faa0f (patch)
tree31c5a2d5025b412fddfeb158bd1ad24b6c4dfcf9 /src/gallium/drivers/radeonsi/cik_sdma.c
parent431742dbba46b66e61a22f7186ec82a818685a31 (diff)
radeonsi: implement SDMA-based buffer clearing for CIK-VI
Reviewed-by: Nicolai Hähnle <[email protected]>
Diffstat (limited to 'src/gallium/drivers/radeonsi/cik_sdma.c')
-rw-r--r--src/gallium/drivers/radeonsi/cik_sdma.c42
1 files changed, 42 insertions, 0 deletions
diff --git a/src/gallium/drivers/radeonsi/cik_sdma.c b/src/gallium/drivers/radeonsi/cik_sdma.c
index b3eaed58fc0..698f8f6bbb2 100644
--- a/src/gallium/drivers/radeonsi/cik_sdma.c
+++ b/src/gallium/drivers/radeonsi/cik_sdma.c
@@ -82,6 +82,47 @@ static void cik_sdma_copy_buffer(struct si_context *ctx,
r600_dma_emit_wait_idle(&ctx->b);
}
+static void cik_sdma_clear_buffer(struct pipe_context *ctx,
+ struct pipe_resource *dst,
+ uint64_t offset,
+ uint64_t size,
+ unsigned clear_value)
+{
+ struct si_context *sctx = (struct si_context *)ctx;
+ struct radeon_winsys_cs *cs = sctx->b.dma.cs;
+ unsigned i, ncopy, csize;
+ struct r600_resource *rdst = r600_resource(dst);
+
+ if (!cs || offset % 4 != 0 || size % 4 != 0) {
+ ctx->clear_buffer(ctx, dst, offset, size, &clear_value, 4);
+ return;
+ }
+
+ /* Mark the buffer range of destination as valid (initialized),
+ * so that transfer_map knows it should wait for the GPU when mapping
+ * that range. */
+ util_range_add(&rdst->valid_buffer_range, offset, offset + size);
+
+ offset += rdst->gpu_address;
+
+ /* the same maximum size as for copying */
+ ncopy = DIV_ROUND_UP(size, CIK_SDMA_COPY_MAX_SIZE);
+ r600_need_dma_space(&sctx->b, ncopy * 5, rdst, NULL);
+
+ for (i = 0; i < ncopy; i++) {
+ csize = MIN2(size, CIK_SDMA_COPY_MAX_SIZE);
+ radeon_emit(cs, CIK_SDMA_PACKET(CIK_SDMA_PACKET_CONSTANT_FILL, 0,
+ 0x8000 /* dword copy */));
+ radeon_emit(cs, offset);
+ radeon_emit(cs, offset >> 32);
+ radeon_emit(cs, clear_value);
+ radeon_emit(cs, csize);
+ offset += csize;
+ size -= csize;
+ }
+ r600_dma_emit_wait_idle(&sctx->b);
+}
+
static unsigned minify_as_blocks(unsigned width, unsigned level, unsigned blk_w)
{
width = u_minify(width, level);
@@ -525,4 +566,5 @@ fallback:
void cik_init_sdma_functions(struct si_context *sctx)
{
sctx->b.dma_copy = cik_sdma_copy;
+ sctx->b.dma_clear_buffer = cik_sdma_clear_buffer;
}