diff options
Diffstat (limited to 'src/gallium/drivers/r600/r600_pipe.c')
-rw-r--r-- | src/gallium/drivers/r600/r600_pipe.c | 142 |
1 files changed, 124 insertions, 18 deletions
diff --git a/src/gallium/drivers/r600/r600_pipe.c b/src/gallium/drivers/r600/r600_pipe.c index e4a35cfe06c..c72ee8f8571 100644 --- a/src/gallium/drivers/r600/r600_pipe.c +++ b/src/gallium/drivers/r600/r600_pipe.c @@ -53,9 +53,7 @@ static struct r600_fence *r600_create_fence(struct r600_context *rctx) R600_ERR("r600: failed to create bo for fence objects\n"); goto out; } - rscreen->fences.data = rctx->ws->buffer_map(rscreen->fences.bo->cs_buf, - rctx->cs, - PIPE_TRANSFER_READ_WRITE); + rscreen->fences.data = r600_buffer_mmap_sync_with_rings(rctx, rscreen->fences.bo, PIPE_TRANSFER_READ_WRITE); } if (!LIST_IS_EMPTY(&rscreen->fences.pool)) { @@ -108,25 +106,20 @@ static struct r600_fence *r600_create_fence(struct r600_context *rctx) pipe_buffer_create(&rctx->screen->screen, PIPE_BIND_CUSTOM, PIPE_USAGE_STAGING, 1); /* Add the fence as a dummy relocation. */ - r600_context_bo_reloc(rctx, fence->sleep_bo, RADEON_USAGE_READWRITE); + r600_context_bo_reloc(rctx, &rctx->rings.gfx, fence->sleep_bo, RADEON_USAGE_READWRITE); out: pipe_mutex_unlock(rscreen->fences.mutex); return fence; } - -void r600_flush(struct pipe_context *ctx, struct pipe_fence_handle **fence, - unsigned flags) +static void r600_flush(struct pipe_context *ctx, unsigned flags) { struct r600_context *rctx = (struct r600_context *)ctx; - struct r600_fence **rfence = (struct r600_fence**)fence; struct pipe_query *render_cond = NULL; unsigned render_cond_mode = 0; - if (rfence) - *rfence = r600_create_fence(rctx); - + rctx->rings.gfx.flushing = true; /* Disable render condition. */ if (rctx->current_render_cond) { render_cond = rctx->current_render_cond; @@ -140,19 +133,119 @@ void r600_flush(struct pipe_context *ctx, struct pipe_fence_handle **fence, if (render_cond) { ctx->render_condition(ctx, render_cond, render_cond_mode); } + rctx->rings.gfx.flushing = false; } static void r600_flush_from_st(struct pipe_context *ctx, struct pipe_fence_handle **fence, enum pipe_flush_flags flags) { - r600_flush(ctx, fence, - flags & PIPE_FLUSH_END_OF_FRAME ? RADEON_FLUSH_END_OF_FRAME : 0); + struct r600_context *rctx = (struct r600_context *)ctx; + struct r600_fence **rfence = (struct r600_fence**)fence; + unsigned fflags; + + fflags = flags & PIPE_FLUSH_END_OF_FRAME ? RADEON_FLUSH_END_OF_FRAME : 0; + if (rfence) { + *rfence = r600_create_fence(rctx); + } + /* flush gfx & dma ring, order does not matter as only one can be live */ + rctx->rings.dma.flush(rctx, fflags); + rctx->rings.gfx.flush(rctx, fflags); +} + +static void r600_flush_gfx_ring(void *ctx, unsigned flags) +{ + r600_flush((struct pipe_context*)ctx, flags); +} + +static void r600_flush_dma_ring(void *ctx, unsigned flags) +{ + struct r600_context *rctx = (struct r600_context *)ctx; + + if (!rctx->rings.dma.cs->cdw) { + return; + } + rctx->rings.dma.flushing = true; + rctx->ws->cs_flush(rctx->rings.dma.cs, flags); + rctx->rings.dma.flushing = false; +} + +boolean r600_rings_is_buffer_referenced(struct r600_context *ctx, + struct radeon_winsys_cs_handle *buf, + enum radeon_bo_usage usage) +{ + if (ctx->ws->cs_is_buffer_referenced(ctx->rings.gfx.cs, buf, usage)) { + return TRUE; + } + if (ctx->ws->cs_is_buffer_referenced(ctx->rings.dma.cs, buf, usage)) { + return TRUE; + } + return FALSE; +} + +void *r600_buffer_mmap_sync_with_rings(struct r600_context *ctx, + struct r600_resource *resource, + unsigned usage) +{ + enum radeon_bo_usage rusage = RADEON_USAGE_READWRITE; + unsigned flags = 0; + bool sync_flush = TRUE; + + if (usage & PIPE_TRANSFER_UNSYNCHRONIZED) { + return ctx->ws->buffer_map(resource->cs_buf, NULL, usage); + } + + if (!(usage & PIPE_TRANSFER_WRITE)) { + /* have to wait for pending read */ + rusage = RADEON_USAGE_WRITE; + } + if (usage & PIPE_TRANSFER_DONTBLOCK) { + flags |= RADEON_FLUSH_ASYNC; + } + + if (ctx->ws->cs_is_buffer_referenced(ctx->rings.gfx.cs, resource->cs_buf, rusage) && ctx->rings.gfx.cs->cdw) { + ctx->rings.gfx.flush(ctx, flags); + if (usage & PIPE_TRANSFER_DONTBLOCK) { + return NULL; + } + } + if (ctx->ws->cs_is_buffer_referenced(ctx->rings.dma.cs, resource->cs_buf, rusage) && ctx->rings.dma.cs->cdw) { + ctx->rings.dma.flush(ctx, flags); + if (usage & PIPE_TRANSFER_DONTBLOCK) { + return NULL; + } + } + + if (usage & PIPE_TRANSFER_DONTBLOCK) { + if (ctx->ws->buffer_is_busy(resource->buf, rusage)) { + return NULL; + } + } + if (sync_flush) { + /* Try to avoid busy-waiting in radeon_bo_wait. */ + ctx->ws->cs_sync_flush(ctx->rings.gfx.cs); + if (ctx->rings.dma.cs) { + ctx->ws->cs_sync_flush(ctx->rings.dma.cs); + } + } + ctx->ws->buffer_wait(resource->buf, rusage); + + /* at this point everything is synchronized */ + return ctx->ws->buffer_map(resource->cs_buf, NULL, usage | PIPE_TRANSFER_UNSYNCHRONIZED); } static void r600_flush_from_winsys(void *ctx, unsigned flags) { - r600_flush((struct pipe_context*)ctx, NULL, flags); + struct r600_context *rctx = (struct r600_context *)ctx; + + rctx->rings.gfx.flush(rctx, flags); +} + +static void r600_flush_dma_from_winsys(void *ctx, unsigned flags) +{ + struct r600_context *rctx = (struct r600_context *)ctx; + + rctx->rings.dma.flush(rctx, flags); } static void r600_destroy_context(struct pipe_context *context) @@ -197,8 +290,11 @@ static void r600_destroy_context(struct pipe_context *context) r600_release_command_buffer(&rctx->start_cs_cmd); - if (rctx->cs) { - rctx->ws->cs_destroy(rctx->cs); + if (rctx->rings.gfx.cs) { + rctx->ws->cs_destroy(rctx->rings.gfx.cs); + } + if (rctx->rings.dma.cs) { + rctx->ws->cs_destroy(rctx->rings.dma.cs); } FREE(rctx->range); @@ -289,8 +385,18 @@ static struct pipe_context *r600_create_context(struct pipe_screen *screen, void goto fail; } - rctx->cs = rctx->ws->cs_create(rctx->ws, RING_GFX); - rctx->ws->cs_set_flush_callback(rctx->cs, r600_flush_from_winsys, rctx); + rctx->rings.gfx.cs = rctx->ws->cs_create(rctx->ws, RING_GFX); + rctx->rings.gfx.flush = r600_flush_gfx_ring; + rctx->ws->cs_set_flush_callback(rctx->rings.gfx.cs, r600_flush_from_winsys, rctx); + rctx->rings.gfx.flushing = false; + + rctx->rings.dma.cs = NULL; + if (rscreen->info.r600_has_dma) { + rctx->rings.dma.cs = rctx->ws->cs_create(rctx->ws, RING_DMA); + rctx->rings.dma.flush = r600_flush_dma_ring; + rctx->ws->cs_set_flush_callback(rctx->rings.dma.cs, r600_flush_dma_from_winsys, rctx); + rctx->rings.dma.flushing = false; + } rctx->uploader = u_upload_create(&rctx->context, 1024 * 1024, 256, PIPE_BIND_INDEX_BUFFER | |