From dacf22e0a34d4dc2595f3cb0dbee52318dc9d0d7 Mon Sep 17 00:00:00 2001 From: Ilia Mirkin Date: Thu, 2 Apr 2015 20:48:44 -0400 Subject: [PATCH] freedreno: mark resources as being read so that writes flush the queue Signed-off-by: Ilia Mirkin --- .../drivers/freedreno/freedreno_context.c | 10 +++++ .../drivers/freedreno/freedreno_context.h | 3 ++ .../drivers/freedreno/freedreno_draw.c | 38 +++++++++++++++++++ .../drivers/freedreno/freedreno_resource.c | 6 ++- .../drivers/freedreno/freedreno_resource.h | 3 ++ 5 files changed, 59 insertions(+), 1 deletion(-) diff --git a/src/gallium/drivers/freedreno/freedreno_context.c b/src/gallium/drivers/freedreno/freedreno_context.c index bb1b52797a8..5fca57c5a3a 100644 --- a/src/gallium/drivers/freedreno/freedreno_context.c +++ b/src/gallium/drivers/freedreno/freedreno_context.c @@ -95,6 +95,7 @@ fd_context_render(struct pipe_context *pctx) { struct fd_context *ctx = fd_context(pctx); struct pipe_framebuffer_state *pfb = &ctx->framebuffer; + struct fd_resource *rsc, *rsc_tmp; int i; DBG("needs_flush: %d", ctx->needs_flush); @@ -122,6 +123,15 @@ fd_context_render(struct pipe_context *pctx) fd_resource(pfb->cbufs[i]->texture)->dirty = false; if (pfb->zsbuf) fd_resource(pfb->zsbuf->texture)->dirty = false; + + /* go through all the used resources and clear their reading flag */ + LIST_FOR_EACH_ENTRY_SAFE(rsc, rsc_tmp, &ctx->used_resources, list) { + assert(rsc->reading); + rsc->reading = false; + list_delinit(&rsc->list); + } + + assert(LIST_IS_EMPTY(&ctx->used_resources)); } static void diff --git a/src/gallium/drivers/freedreno/freedreno_context.h b/src/gallium/drivers/freedreno/freedreno_context.h index 7b0424e65da..a648689cefd 100644 --- a/src/gallium/drivers/freedreno/freedreno_context.h +++ b/src/gallium/drivers/freedreno/freedreno_context.h @@ -165,6 +165,9 @@ struct fd_context { struct fd_bo *query_bo; uint32_t query_tile_stride; + /* list of resources used by currently-unsubmitted renders */ + struct list_head used_resources; + /* table with PIPE_PRIM_MAX entries mapping PIPE_PRIM_x to * DI_PT_x value to use for draw initiator. There are some * slight differences between generation: diff --git a/src/gallium/drivers/freedreno/freedreno_draw.c b/src/gallium/drivers/freedreno/freedreno_draw.c index 423ae23769c..fed3e64f202 100644 --- a/src/gallium/drivers/freedreno/freedreno_draw.c +++ b/src/gallium/drivers/freedreno/freedreno_draw.c @@ -39,6 +39,19 @@ #include "freedreno_query_hw.h" #include "freedreno_util.h" +static void +resource_reading(struct fd_context *ctx, struct pipe_resource *prsc) +{ + struct fd_resource *rsc; + + if (!prsc) + return; + + rsc = fd_resource(prsc); + rsc->reading = true; + list_delinit(&rsc->list); + list_addtail(&rsc->list, &ctx->used_resources); +} static void fd_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info) @@ -101,6 +114,29 @@ fd_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info) ctx->gmem_reason |= FD_GMEM_BLEND_ENABLED; } + /* Skip over buffer 0, that is sent along with the command stream */ + for (i = 1; i < PIPE_MAX_CONSTANT_BUFFERS; i++) { + resource_reading(ctx, ctx->constbuf[PIPE_SHADER_VERTEX].cb[i].buffer); + resource_reading(ctx, ctx->constbuf[PIPE_SHADER_FRAGMENT].cb[i].buffer); + } + + /* Mark VBOs as being read */ + for (i = 0; i < ctx->vtx.vertexbuf.count; i++) { + assert(!ctx->vtx.vertexbuf.vb[i].user_buffer); + resource_reading(ctx, ctx->vtx.vertexbuf.vb[i].buffer); + } + + /* Mark index buffer as being read */ + resource_reading(ctx, ctx->indexbuf.buffer); + + /* Mark textures as being read */ + for (i = 0; i < ctx->verttex.num_textures; i++) + if (ctx->verttex.textures[i]) + resource_reading(ctx, ctx->verttex.textures[i]->texture); + for (i = 0; i < ctx->fragtex.num_textures; i++) + if (ctx->fragtex.textures[i]) + resource_reading(ctx, ctx->fragtex.textures[i]->texture); + ctx->num_draws++; ctx->stats.draw_calls++; @@ -223,6 +259,8 @@ fd_clear_depth_stencil(struct pipe_context *pctx, struct pipe_surface *ps, void fd_draw_init(struct pipe_context *pctx) { + list_inithead(&fd_context(pctx)->used_resources); + pctx->draw_vbo = fd_draw_vbo; pctx->clear = fd_clear; pctx->clear_render_target = fd_clear_render_target; diff --git a/src/gallium/drivers/freedreno/freedreno_resource.c b/src/gallium/drivers/freedreno/freedreno_resource.c index 6e7958d42dd..000d1c210af 100644 --- a/src/gallium/drivers/freedreno/freedreno_resource.c +++ b/src/gallium/drivers/freedreno/freedreno_resource.c @@ -57,7 +57,8 @@ realloc_bo(struct fd_resource *rsc, uint32_t size) rsc->bo = fd_bo_new(screen->dev, size, flags); rsc->timestamp = 0; - rsc->dirty = false; + rsc->dirty = rsc->reading = false; + list_delinit(&rsc->list); } static void fd_resource_transfer_flush_region(struct pipe_context *pctx, @@ -170,6 +171,7 @@ fd_resource_destroy(struct pipe_screen *pscreen, struct fd_resource *rsc = fd_resource(prsc); if (rsc->bo) fd_bo_del(rsc->bo); + list_delinit(&rsc->list); FREE(rsc); } @@ -277,6 +279,7 @@ fd_resource_create(struct pipe_screen *pscreen, *prsc = *tmpl; pipe_reference_init(&prsc->reference, 1); + list_inithead(&rsc->list); prsc->screen = pscreen; rsc->base.vtbl = &fd_resource_vtbl; @@ -340,6 +343,7 @@ fd_resource_from_handle(struct pipe_screen *pscreen, *prsc = *tmpl; pipe_reference_init(&prsc->reference, 1); + list_inithead(&rsc->list); prsc->screen = pscreen; rsc->bo = fd_screen_bo_from_handle(pscreen, handle, &slice->pitch); diff --git a/src/gallium/drivers/freedreno/freedreno_resource.h b/src/gallium/drivers/freedreno/freedreno_resource.h index 1f246328969..1539fc9ad1a 100644 --- a/src/gallium/drivers/freedreno/freedreno_resource.h +++ b/src/gallium/drivers/freedreno/freedreno_resource.h @@ -29,6 +29,7 @@ #ifndef FREEDRENO_RESOURCE_H_ #define FREEDRENO_RESOURCE_H_ +#include "util/u_double_list.h" #include "util/u_transfer.h" #include "freedreno_util.h" @@ -67,6 +68,8 @@ struct fd_resource { struct fd_resource_slice slices[MAX_MIP_LEVELS]; uint32_t timestamp; bool dirty, reading; + + struct list_head list; }; static INLINE struct fd_resource * -- 2.30.2