--- src/gallium/drivers/r600/r600_blit.c | 8 +-- src/gallium/drivers/r600/r600_buffer.c | 65 +++++++++++++++++++++++++++----- src/gallium/drivers/r600/r600_pipe.c | 2 +- src/gallium/drivers/r600/r600_pipe.h | 3 + 4 files changed, 62 insertions(+), 16 deletions(-)
diff --git a/src/gallium/drivers/r600/r600_blit.c b/src/gallium/drivers/r600/r600_blit.c index 0d9618d..6c740ce 100644 --- a/src/gallium/drivers/r600/r600_blit.c +++ b/src/gallium/drivers/r600/r600_blit.c @@ -246,11 +246,9 @@ static void r600_clear_depth_stencil(struct pipe_context *ctx, r600_blitter_end(ctx); } -static void r600_copy_buffer(struct pipe_context *ctx, - struct pipe_resource *dst, - unsigned dstx, - struct pipe_resource *src, - const struct pipe_box *src_box) +void r600_copy_buffer(struct pipe_context *ctx, struct + pipe_resource *dst, unsigned dstx, + struct pipe_resource *src, const struct pipe_box *src_box) { struct r600_context *rctx = (struct r600_context*)ctx; diff --git a/src/gallium/drivers/r600/r600_buffer.c b/src/gallium/drivers/r600/r600_buffer.c index 733d707..0e7b948 100644 --- a/src/gallium/drivers/r600/r600_buffer.c +++ b/src/gallium/drivers/r600/r600_buffer.c @@ -53,22 +53,30 @@ static struct pipe_transfer *r600_get_transfer(struct pipe_context *ctx, const struct pipe_box *box) { struct r600_context *rctx = (struct r600_context*)ctx; - struct pipe_transfer *transfer = util_slab_alloc(&rctx->pool_transfers); + struct r600_transfer *transfer = util_slab_alloc(&rctx->pool_transfers); - transfer->resource = resource; - transfer->level = level; - transfer->usage = usage; - transfer->box = *box; - transfer->stride = 0; - transfer->layer_stride = 0; - transfer->data = NULL; + assert(box->x + box->width <= resource->width0); + + transfer->transfer.resource = resource; + transfer->transfer.level = level; + transfer->transfer.usage = usage; + transfer->transfer.box = *box; + transfer->transfer.stride = 0; + transfer->transfer.layer_stride = 0; + transfer->transfer.data = NULL; + transfer->staging = NULL; + transfer->offset = 0; /* Note strides are zero, this is ok for buffers, but not for * textures 2d & higher at least. */ - return transfer; + return &transfer->transfer; } +/* XXX this isn't reliable yet; there are no piglit regressions, + * but some apps may lock up (tested on evergreen). I guess streamout is buggy. */ +DEBUG_GET_ONCE_BOOL_OPTION(transfer_nowait, "R600_TRANSFER_NOWAIT", FALSE); + static void *r600_buffer_transfer_map(struct pipe_context *pipe, struct pipe_transfer *transfer) { @@ -79,6 +87,30 @@ static void *r600_buffer_transfer_map(struct pipe_context *pipe, if (rbuffer->b.user_ptr) return (uint8_t*)rbuffer->b.user_ptr + transfer->box.x; + /* At least one of the DISCARD flags and none of {READ, DONTBLOCK, UNSYNCHRONIZED} must be present. + * The buffer range must be aligned to 4. */ + if ((transfer->usage & (PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE | PIPE_TRANSFER_DISCARD_RANGE)) && + !(transfer->usage & (PIPE_TRANSFER_READ | PIPE_TRANSFER_DONTBLOCK | PIPE_TRANSFER_UNSYNCHRONIZED)) && + debug_get_option_transfer_nowait() && + rctx->screen->info.r600_has_streamout && + transfer->box.x % 4 == 0 && transfer->box.width % 4 == 0) { + /* When mapping for read, we only need to check if the GPU is writing to it. */ + enum radeon_bo_usage rusage = transfer->usage & PIPE_TRANSFER_WRITE ? + RADEON_USAGE_READWRITE : RADEON_USAGE_WRITE; + + /* Check if mapping this buffer would cause waiting for the GPU. */ + if (rctx->ws->cs_is_buffer_referenced(rctx->cs, rbuffer->cs_buf, rusage) || + rctx->ws->buffer_is_busy(rbuffer->buf, rusage)) { + /* Do a wait-free write-only transfer using a temporary buffer. */ + struct r600_transfer *rtransfer = (struct r600_transfer*)transfer; + + rtransfer->staging = (struct r600_resource*) + pipe_buffer_create(pipe->screen, PIPE_BIND_VERTEX_BUFFER, + PIPE_USAGE_STAGING, transfer->box.width); + return rctx->ws->buffer_map(rtransfer->staging->buf, rctx->cs, PIPE_TRANSFER_WRITE); + } + } + data = rctx->ws->buffer_map(rbuffer->buf, rctx->cs, transfer->usage); if (!data) return NULL; @@ -91,11 +123,24 @@ static void r600_buffer_transfer_unmap(struct pipe_context *pipe, { struct r600_resource *rbuffer = r600_resource(transfer->resource); struct r600_context *rctx = (struct r600_context*)pipe; + struct r600_transfer *rtransfer = (struct r600_transfer*)transfer; if (rbuffer->b.user_ptr) return; - rctx->ws->buffer_unmap(rbuffer->buf); + if (rtransfer->staging) { + struct pipe_box box; + u_box_1d(0, transfer->box.width, &box); + + rctx->ws->buffer_unmap(rtransfer->staging->buf); + + /* Copy the staging buffer into the original one. */ + r600_copy_buffer(pipe, transfer->resource, transfer->box.x, + &rtransfer->staging->b.b.b, &box); + pipe_resource_reference((struct pipe_resource**)&rtransfer->staging, NULL); + } else { + rctx->ws->buffer_unmap(rbuffer->buf); + } } static void r600_transfer_destroy(struct pipe_context *ctx, diff --git a/src/gallium/drivers/r600/r600_pipe.c b/src/gallium/drivers/r600/r600_pipe.c index db1bf0e..97c2511 100644 --- a/src/gallium/drivers/r600/r600_pipe.c +++ b/src/gallium/drivers/r600/r600_pipe.c @@ -235,7 +235,7 @@ static struct pipe_context *r600_create_context(struct pipe_screen *screen, void return NULL; util_slab_create(&rctx->pool_transfers, - sizeof(struct pipe_transfer), 64, + sizeof(struct r600_transfer), 64, UTIL_SLAB_SINGLETHREADED); r600_update_num_contexts(rscreen, 1); diff --git a/src/gallium/drivers/r600/r600_pipe.h b/src/gallium/drivers/r600/r600_pipe.h index 08441d1..f70a4eb 100644 --- a/src/gallium/drivers/r600/r600_pipe.h +++ b/src/gallium/drivers/r600/r600_pipe.h @@ -399,6 +399,9 @@ boolean evergreen_is_format_supported(struct pipe_screen *screen, void evergreen_set_rasterizer_discard(struct pipe_context *ctx, boolean discard); /* r600_blit.c */ +void r600_copy_buffer(struct pipe_context *ctx, struct + pipe_resource *dst, unsigned dstx, + struct pipe_resource *src, const struct pipe_box *src_box); void r600_init_blit_functions(struct r600_context *rctx); void r600_blit_uncompress_depth(struct pipe_context *ctx, struct r600_resource_texture *texture); void r600_blit_push_depth(struct pipe_context *ctx, struct r600_resource_texture *texture); -- 1.7.5.4 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev