Reviewed-By: George Kyriazis
> -----Original Message----- > From: mesa-dev [mailto:[email protected]] On > Behalf Of BruceCherniak > Sent: Wednesday, March 9, 2016 7:30 PM > To: [email protected] > Subject: [Mesa-dev] [PATCH] gallium/swr: Resource management > > From: Bruce Cherniak <[email protected]> > > Better tracking of resource state and synchronization. > A follow on commit will clean up resource functions into a new > swr_resource.cpp file. > --- > src/gallium/drivers/swr/swr_clear.cpp | 4 +- > src/gallium/drivers/swr/swr_context.cpp | 103 ++++++++++++------------------ > - > src/gallium/drivers/swr/swr_draw.cpp | 64 +++++++++++++------ > src/gallium/drivers/swr/swr_fence.cpp | 29 ++++++--- > src/gallium/drivers/swr/swr_fence.h | 6 +- > src/gallium/drivers/swr/swr_query.cpp | 6 +- > src/gallium/drivers/swr/swr_resource.h | 54 +++++++++++++++- > src/gallium/drivers/swr/swr_screen.cpp | 57 ++++++++--------- > src/gallium/drivers/swr/swr_state.cpp | 83 ++++++++++++++++++++++--- > src/gallium/drivers/swr/swr_state.h | 2 +- > 10 files changed, 265 insertions(+), 143 deletions(-) > > diff --git a/src/gallium/drivers/swr/swr_clear.cpp > b/src/gallium/drivers/swr/swr_clear.cpp > index 9027f84..103bca9 100644 > --- a/src/gallium/drivers/swr/swr_clear.cpp > +++ b/src/gallium/drivers/swr/swr_clear.cpp > @@ -40,7 +40,7 @@ swr_clear(struct pipe_context *pipe, > return; > > if (ctx->dirty) > - swr_update_derived(ctx); > + swr_update_derived(pipe); > > /* Update clearMask/targetMask */ > #if 0 /* XXX SWR currently only clears SWR_ATTACHMENT_COLOR0, don't > bother \ > @@ -76,7 +76,7 @@ swr_clear(struct pipe_context *pipe, > vp.height = ctx->framebuffer.height; > SwrSetViewports(ctx->swrContext, 1, &vp, NULL); > > - swr_update_draw_context(ctx); > + swr_update_draw_context(ctx); > SwrClearRenderTarget(ctx->swrContext, clearMask, color->f, depth, > stencil); } > > diff --git a/src/gallium/drivers/swr/swr_context.cpp > b/src/gallium/drivers/swr/swr_context.cpp > index 0e7ebb7..c8cb145 100644 > --- a/src/gallium/drivers/swr/swr_context.cpp > +++ b/src/gallium/drivers/swr/swr_context.cpp > @@ -36,6 +36,7 @@ extern "C" { > #include "swr_resource.h" > #include "swr_scratch.h" > #include "swr_query.h" > +#include "swr_fence.h" > > #include "api.h" > #include "backend.h" > @@ -85,36 +86,10 @@ swr_surface_destroy(struct pipe_context *pipe, > struct pipe_surface *surf) > assert(surf->texture); > struct pipe_resource *resource = surf->texture; > > - /* If the surface being destroyed is a current render target, > - * call StoreTiles to resolve the hotTile state then set attachment > - * to NULL. > - */ > - if (resource->bind & (PIPE_BIND_RENDER_TARGET | > PIPE_BIND_DEPTH_STENCIL > - | PIPE_BIND_DISPLAY_TARGET)) { > - struct swr_context *ctx = swr_context(pipe); > - struct swr_resource *spr = swr_resource(resource); > - swr_draw_context *pDC = &ctx->swrDC; > - SWR_SURFACE_STATE *renderTargets = pDC->renderTargets; > - for (uint32_t i = 0; i < SWR_NUM_ATTACHMENTS; i++) > - if (renderTargets[i].pBaseAddress == spr->swr.pBaseAddress) { > - swr_store_render_target(ctx, i, SWR_TILE_RESOLVED); > - > - /* > - * Mesa thinks depth/stencil are fused, so we'll never get an > - * explicit resource for stencil. So, if checking depth, then > - * also check for stencil. > - */ > - if (spr->has_stencil && (i == SWR_ATTACHMENT_DEPTH)) { > - swr_store_render_target( > - ctx, SWR_ATTACHMENT_STENCIL, SWR_TILE_RESOLVED); > - } > - > - SwrWaitForIdle(ctx->swrContext); > - break; > - } > - } > + /* If the resource has been drawn to, store tiles. */ > + swr_store_dirty_resource(pipe, resource, SWR_TILE_RESOLVED); > > - pipe_resource_reference(&surf->texture, NULL); > + pipe_resource_reference(&resource, NULL); > FREE(surf); > } > > @@ -127,6 +102,7 @@ swr_transfer_map(struct pipe_context *pipe, > const struct pipe_box *box, > struct pipe_transfer **transfer) { > + struct swr_screen *screen = swr_screen(pipe->screen); > struct swr_resource *spr = swr_resource(resource); > struct pipe_transfer *pt; > enum pipe_format format = resource->format; @@ -134,30 +110,28 @@ > swr_transfer_map(struct pipe_context *pipe, > assert(resource); > assert(level <= resource->last_level); > > - /* > - * If mapping any attached rendertarget, store tiles and wait for idle > - * before giving CPU access to the surface. > - * (set postStoreTileState to SWR_TILE_INVALID so tiles are reloaded) > - */ > - if (resource->bind & (PIPE_BIND_RENDER_TARGET | > PIPE_BIND_DEPTH_STENCIL > - | PIPE_BIND_DISPLAY_TARGET)) { > - struct swr_context *ctx = swr_context(pipe); > - swr_draw_context *pDC = &ctx->swrDC; > - SWR_SURFACE_STATE *renderTargets = pDC->renderTargets; > - for (uint32_t i = 0; i < SWR_NUM_ATTACHMENTS; i++) > - if (renderTargets[i].pBaseAddress == spr->swr.pBaseAddress) { > - swr_store_render_target(ctx, i, SWR_TILE_INVALID); > - /* > - * Mesa thinks depth/stencil are fused, so we'll never get an > - * explicit map for stencil. So, if mapping depth, then also > - * store tile for stencil. > - */ > - if (spr->has_stencil && (i == SWR_ATTACHMENT_DEPTH)) > - swr_store_render_target( > - ctx, SWR_ATTACHMENT_STENCIL, SWR_TILE_INVALID); > - SwrWaitForIdle(ctx->swrContext); > - break; > + /* If mapping an attached rendertarget, store tiles to surface and set > + * postStoreTileState to SWR_TILE_INVALID so tiles get reloaded on next > use > + * and nothing needs to be done at unmap. */ > + swr_store_dirty_resource(pipe, resource, SWR_TILE_INVALID); > + > + if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) { > + /* If resource is in use, finish fence before mapping. > + * Unless requested not to block, then if not done return NULL map */ > + if (usage & PIPE_TRANSFER_DONTBLOCK) { > + if (swr_is_fence_pending(screen->flush_fence)) > + return NULL; > + } else { > + if (spr->status) { > + /* But, if there's no fence pending, submit one. > + * XXX: Remove once draw timestamps are finished. */ > + if (!swr_is_fence_pending(screen->flush_fence)) > + swr_fence_submit(swr_context(pipe), > + screen->flush_fence); > + > + swr_fence_finish(pipe->screen, screen->flush_fence, 0); > + swr_resource_unused(pipe, spr); > } > + } > } > > pt = CALLOC_STRUCT(pipe_transfer); > @@ -195,16 +169,7 @@ swr_transfer_unmap(struct pipe_context *pipe, > struct pipe_transfer *transfer) { > assert(transfer->resource); > > - /* > - * XXX TODO: use fences and come up with a real resource manager. > - * > - * If this resource has been mapped/unmapped, it's probably in use. Tag > it > - *with this context so > - * we'll know to check dependencies when it's deleted. > - */ > struct swr_resource *res = swr_resource(transfer->resource); > - res->bound_to_context = (void *)pipe; > - > /* if we're mapping the depth/stencil, copy out stencil */ > if (res->base.format == PIPE_FORMAT_Z24_UNORM_S8_UINT > && res->has_stencil) { > @@ -234,6 +199,16 @@ swr_resource_copy(struct pipe_context *pipe, > unsigned src_level, > const struct pipe_box *src_box) { > + struct swr_screen *screen = swr_screen(pipe->screen); > + > + /* If either the src or dst is a renderTarget, store tiles before copy */ > + swr_store_dirty_resource(pipe, src, SWR_TILE_RESOLVED); > + swr_store_dirty_resource(pipe, dst, SWR_TILE_RESOLVED); > + > + swr_fence_finish(pipe->screen, screen->flush_fence, 0); > + swr_resource_unused(pipe, swr_resource(src)); > + swr_resource_unused(pipe, swr_resource(dst)); > + > if ((dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) > || (dst->target != PIPE_BUFFER && src->target != PIPE_BUFFER)) { > util_resource_copy_region( > @@ -322,6 +297,8 @@ swr_destroy(struct pipe_context *pipe) > if (ctx->blitter) > util_blitter_destroy(ctx->blitter); > > + /* Idle core before deleting context */ > + SwrWaitForIdle(ctx->swrContext); > if (ctx->swrContext) > SwrDestroyContext(ctx->swrContext); > > @@ -346,7 +323,6 @@ swr_render_condition(struct pipe_context *pipe, > ctx->render_cond_cond = condition; > } > > - > struct pipe_context * > swr_create_context(struct pipe_screen *screen, void *priv, unsigned flags) { > @@ -392,9 +368,8 @@ swr_create_context(struct pipe_screen *screen, void > *priv, unsigned flags) > > ctx->pipe.blit = swr_blit; > ctx->blitter = util_blitter_create(&ctx->pipe); > - if (!ctx->blitter) { > + if (!ctx->blitter) > goto fail; > - } > > swr_init_scratch_buffers(ctx); > > diff --git a/src/gallium/drivers/swr/swr_draw.cpp > b/src/gallium/drivers/swr/swr_draw.cpp > index a775bd2..428bf78 100644 > --- a/src/gallium/drivers/swr/swr_draw.cpp > +++ b/src/gallium/drivers/swr/swr_draw.cpp > @@ -91,7 +91,7 @@ swr_draw_vbo(struct pipe_context *pipe, const struct > pipe_draw_info *info) > > /* Update derived state, pass draw info to update function */ > if (ctx->dirty) > - swr_update_derived(ctx, info); > + swr_update_derived(pipe, info); > > swr_update_draw_context(ctx); > > @@ -184,20 +184,14 @@ swr_flush(struct pipe_context *pipe, { > struct swr_context *ctx = swr_context(pipe); > struct swr_screen *screen = swr_screen(pipe->screen); > - > - /* If the current renderTarget is the display surface, store tiles back to > - * the surface, in > - * preparation for present (swr_flush_frontbuffer) > - */ > struct pipe_surface *cb = ctx->framebuffer.cbufs[0]; > - if (cb && swr_resource(cb->texture)->display_target) { > - swr_store_render_target(ctx, SWR_ATTACHMENT_COLOR0, > SWR_TILE_RESOLVED); > - swr_resource(cb->texture)->bound_to_context = (void*)pipe; > - } > > - // SwrStoreTiles is asynchronous, always submit the "flush" fence. > - // flush_frontbuffer needs it. > - swr_fence_submit(ctx, screen->flush_fence); > + /* If the current renderTarget is the display surface, store tiles back to > + * the surface, in preparation for present (swr_flush_frontbuffer). > + * Other renderTargets get stored back when attachment changes or > + * swr_surface_destroy */ > + if (cb && swr_resource(cb->texture)->display_target) > + swr_store_dirty_resource(pipe, cb->texture, SWR_TILE_RESOLVED); > > if (fence) > swr_fence_reference(pipe->screen, fence, screen->flush_fence); @@ - > 206,23 +200,23 @@ swr_flush(struct pipe_context *pipe, void > swr_finish(struct pipe_context *pipe) { > - struct swr_screen *screen = swr_screen(pipe->screen); > - struct pipe_fence_handle *fence = NULL; > + struct pipe_fence_handle *fence = nullptr; > > swr_flush(pipe, &fence, 0); > - swr_fence_finish(&screen->base, fence, 0); > - swr_fence_reference(&screen->base, &fence, NULL); > + swr_fence_finish(pipe->screen, fence, 0); > + swr_fence_reference(pipe->screen, &fence, NULL); > } > > > /* > - * Store SWR HotTiles back to RenderTarget surface. > + * Store SWR HotTiles back to renderTarget surface. > */ > void > -swr_store_render_target(struct swr_context *ctx, > +swr_store_render_target(struct pipe_context *pipe, > uint32_t attachment, > enum SWR_TILE_STATE post_tile_state) { > + struct swr_context *ctx = swr_context(pipe); > struct swr_draw_context *pDC = &ctx->swrDC; > struct SWR_SURFACE_STATE *renderTarget = &pDC- > >renderTargets[attachment]; > > @@ -262,6 +256,38 @@ swr_store_render_target(struct swr_context *ctx, > } > } > > +void > +swr_store_dirty_resource(struct pipe_context *pipe, > + struct pipe_resource *resource, > + enum SWR_TILE_STATE post_tile_state) { > + /* Only store resource if it has been written to */ > + if (swr_resource(resource)->status & SWR_RESOURCE_WRITE) { > + struct swr_context *ctx = swr_context(pipe); > + struct swr_screen *screen = swr_screen(pipe->screen); > + struct swr_resource *spr = swr_resource(resource); > + > + swr_draw_context *pDC = &ctx->swrDC; > + SWR_SURFACE_STATE *renderTargets = pDC->renderTargets; > + for (uint32_t i = 0; i < SWR_NUM_ATTACHMENTS; i++) > + if (renderTargets[i].pBaseAddress == spr->swr.pBaseAddress) { > + swr_store_render_target(pipe, i, post_tile_state); > + > + /* Mesa thinks depth/stencil are fused, so we'll never get an > + * explicit resource for stencil. So, if checking depth, then > + * also check for stencil. */ > + if (spr->has_stencil && (i == SWR_ATTACHMENT_DEPTH)) { > + swr_store_render_target( > + pipe, SWR_ATTACHMENT_STENCIL, post_tile_state); > + } > + > + /* This fence signals StoreTiles completion */ > + swr_fence_submit(ctx, screen->flush_fence); > + > + break; > + } > + } > +} > > void > swr_draw_init(struct pipe_context *pipe) diff --git > a/src/gallium/drivers/swr/swr_fence.cpp > b/src/gallium/drivers/swr/swr_fence.cpp > index e80faee..2e95b39 100644 > --- a/src/gallium/drivers/swr/swr_fence.cpp > +++ b/src/gallium/drivers/swr/swr_fence.cpp > @@ -30,8 +30,9 @@ > #include "swr_fence.h" > > #if defined(PIPE_CC_MSVC) // portable thread yield > - #define sched_yield SwitchToThread > + #define sched_yield SwitchToThread > #endif > + > /* > * Fence callback, called by back-end thread on completion of all rendering > up > * to SwrSync call. > @@ -41,7 +42,8 @@ swr_sync_cb(uint64_t userData, uint64_t userData2, > uint64_t userData3) { > struct swr_fence *fence = (struct swr_fence *)userData; > > - fence->read = fence->write; > + /* Correct value is in SwrSync data, and not the fence write field. */ > + fence->read = userData2; > } > > /* > @@ -53,7 +55,8 @@ swr_fence_submit(struct swr_context *ctx, struct > pipe_fence_handle *fh) > struct swr_fence *fence = swr_fence(fh); > > fence->write++; > - SwrSync(ctx->swrContext, swr_sync_cb, (uint64_t)fence, 0, 0); > + fence->pending = TRUE; > + SwrSync(ctx->swrContext, swr_sync_cb, (uint64_t)fence, fence->write, > + 0); > } > > /* > @@ -67,7 +70,6 @@ swr_fence_create() > if (!fence) > return NULL; > > - memset(fence, 0, sizeof(*fence)); > pipe_reference_init(&fence->reference, 1); > fence->id = fence_id++; > > @@ -103,6 +105,13 @@ swr_fence_reference(struct pipe_screen *screen, > swr_fence_destroy(old); > } > > +static INLINE boolean > +swr_is_fence_done(struct pipe_fence_handle *fence_handle) { > + struct swr_fence *fence = swr_fence(fence_handle); > + return (fence->read == fence->write); } > + > /* > * Wait for the fence to finish. > */ > @@ -111,11 +120,11 @@ swr_fence_finish(struct pipe_screen *screen, > struct pipe_fence_handle *fence_handle, > uint64_t timeout) > { > - struct swr_fence *fence = swr_fence(fence_handle); > - > - while (!swr_is_fence_done(fence)) > + while (!swr_is_fence_done(fence_handle)) > sched_yield(); > > + swr_fence(fence_handle)->pending = FALSE; > + > return TRUE; > } > > @@ -132,12 +141,10 @@ swr_fence_init(struct pipe_screen *p_screen) { > p_screen->fence_reference = swr_fence_reference; > p_screen->fence_finish = swr_fence_finish; > - > p_screen->get_timestamp = swr_get_timestamp; > > - /* > - * Create persistant "flush" fence, submitted when swr_flush is called. > - */ > + /* Create persistant StoreTiles "flush" fence, used to signal completion > + * of flushing tile state back to resource texture, via StoreTiles. > + */ > struct swr_screen *screen = swr_screen(p_screen); > screen->flush_fence = swr_fence_create(); } diff --git > a/src/gallium/drivers/swr/swr_fence.h > b/src/gallium/drivers/swr/swr_fence.h > index 257b240..df3776e 100644 > --- a/src/gallium/drivers/swr/swr_fence.h > +++ b/src/gallium/drivers/swr/swr_fence.h > @@ -33,6 +33,8 @@ struct swr_fence { > uint64_t read; > uint64_t write; > > + unsigned pending; > + > unsigned id; /* Just for reference */ }; > > @@ -44,9 +46,9 @@ swr_fence(struct pipe_fence_handle *fence) } > > static INLINE boolean > -swr_is_fence_done(struct swr_fence *fence) > +swr_is_fence_pending(struct pipe_fence_handle *fence_handle) > { > - return (fence->read == fence->write); > + return swr_fence(fence_handle)->pending; > } > > > diff --git a/src/gallium/drivers/swr/swr_query.cpp > b/src/gallium/drivers/swr/swr_query.cpp > index 2510b3a..810c50b 100644 > --- a/src/gallium/drivers/swr/swr_query.cpp > +++ b/src/gallium/drivers/swr/swr_query.cpp > @@ -62,7 +62,7 @@ swr_destroy_query(struct pipe_context *pipe, struct > pipe_query *q) > struct swr_query *pq = swr_query(q); > > if (pq->fence) { > - if (!swr_is_fence_done(swr_fence(pq->fence))) { > + if (!swr_is_fence_pending(pq->fence)) { > swr_fence_submit(swr_context(pipe), pq->fence); > swr_fence_finish(pipe->screen, pq->fence, 0); > } > @@ -85,7 +85,7 @@ swr_gather_stats(struct pipe_context *pipe, struct > swr_query *pq) > SWR_STATS swr_stats = {0}; > > if (pq->fence) { > - if (!swr_is_fence_done(swr_fence(pq->fence))) { > + if (!swr_is_fence_pending(pq->fence)) { > swr_fence_submit(ctx, pq->fence); > swr_fence_finish(pipe->screen, pq->fence, 0); > } > @@ -180,7 +180,7 @@ swr_get_query_result(struct pipe_context *pipe, > struct swr_query *pq = swr_query(q); > > if (pq->fence) { > - if (!swr_is_fence_done(swr_fence(pq->fence))) { > + if (!swr_is_fence_pending(pq->fence)) { > swr_fence_submit(ctx, pq->fence); > if (!wait) > return FALSE; > diff --git a/src/gallium/drivers/swr/swr_resource.h > b/src/gallium/drivers/swr/swr_resource.h > index 87a27ac..2fdc768 100644 > --- a/src/gallium/drivers/swr/swr_resource.h > +++ b/src/gallium/drivers/swr/swr_resource.h > @@ -29,6 +29,12 @@ > > struct sw_displaytarget; > > +enum swr_resource_status { > + SWR_RESOURCE_UNUSED = 0x0, > + SWR_RESOURCE_READ = 0x1, > + SWR_RESOURCE_WRITE = 0x2, > +}; > + > struct swr_resource { > struct pipe_resource base; > > @@ -39,7 +45,7 @@ struct swr_resource { > UINT alignedHeight; > > SWR_SURFACE_STATE swr; > - SWR_SURFACE_STATE secondary; // for faking depth/stencil merged > formats > + SWR_SURFACE_STATE secondary; /* for faking depth/stencil merged > + formats */ > > struct sw_displaytarget *display_target; > > @@ -47,8 +53,10 @@ struct swr_resource { > unsigned img_stride[PIPE_MAX_TEXTURE_LEVELS]; > unsigned mip_offsets[PIPE_MAX_TEXTURE_LEVELS]; > > - /* Opaque pointer to swr_context to mark resource in use */ > - void *bound_to_context; > + enum swr_resource_status status; > + > + /* pipe_context to which resource is currently bound. */ > + struct pipe_context *bound_to_context; > }; > > > @@ -91,7 +99,45 @@ swr_resource_data(struct pipe_resource *resource) } > > > -void swr_store_render_target(struct swr_context *ctx, > +void swr_store_render_target(struct pipe_context *pipe, > uint32_t attachment, > enum SWR_TILE_STATE post_tile_state); > + > +void swr_store_dirty_resource(struct pipe_context *pipe, > + struct pipe_resource *resource, > + enum SWR_TILE_STATE post_tile_state); > + > +void swr_update_resource_status(struct pipe_context *, > + const struct pipe_draw_info *); > + > +/* > + * Functions to indicate a resource's in-use status. > + */ > +static INLINE enum > +swr_resource_status & operator|=(enum swr_resource_status & a, > + enum swr_resource_status b) { > + return (enum swr_resource_status &)((int&)a |= (int)b); } > + > +static INLINE void > +swr_resource_read(struct pipe_context *pipe, struct swr_resource > +*resource) { > + resource->status |= SWR_RESOURCE_READ; > + resource->bound_to_context = pipe; > +} > + > +static INLINE void > +swr_resource_write(struct pipe_context *pipe, struct swr_resource > +*resource) { > + resource->status |= SWR_RESOURCE_WRITE; > + resource->bound_to_context = pipe; > +} > + > +static INLINE void > +swr_resource_unused(struct pipe_context *pipe, struct swr_resource > +*resource) { > + resource->status = SWR_RESOURCE_UNUSED; > + resource->bound_to_context = nullptr; } > + > #endif > diff --git a/src/gallium/drivers/swr/swr_screen.cpp > b/src/gallium/drivers/swr/swr_screen.cpp > index f0d48cd..7c95c58 100644 > --- a/src/gallium/drivers/swr/swr_screen.cpp > +++ b/src/gallium/drivers/swr/swr_screen.cpp > @@ -47,7 +47,7 @@ extern "C" { > > /* MSVC case instensitive compare */ > #if defined(PIPE_CC_MSVC) > - #define strcasecmp lstrcmpiA > + #define strcasecmp lstrcmpiA > #endif > > /* > @@ -619,37 +619,34 @@ static void > swr_resource_destroy(struct pipe_screen *p_screen, struct pipe_resource > *pt) { > struct swr_screen *screen = swr_screen(p_screen); > - struct swr_resource *res = swr_resource(pt); > - > - /* > - * If this resource is attached to a context it may still be in use, check > - * dependencies before freeing > - * XXX TODO: don't use SwrWaitForIdle, use fences and come up with a > real > - * resource manager. > - * XXX It's happened that we get a swr_destroy prior to freeing the > - * framebuffer resource. Don't wait on it. > - */ > - if (res->bound_to_context && !res->display_target) { > - struct swr_context *ctx = > - swr_context((pipe_context *)res->bound_to_context); > - // XXX, don't SwrWaitForIdle!!! Use a fence. > - SwrWaitForIdle(ctx->swrContext); > + struct swr_resource *spr = swr_resource(pt); > + struct pipe_context *pipe = spr->bound_to_context; > + > + /* Only wait on fence if the resource is being used */ > + if (pipe && spr->status) { > + /* But, if there's no fence pending, submit one. > + * XXX: Remove once draw timestamps are implmented. */ > + if (!swr_is_fence_pending(screen->flush_fence)) > + swr_fence_submit(swr_context(pipe), screen->flush_fence); > + > + swr_fence_finish(p_screen, screen->flush_fence, 0); > + swr_resource_unused(pipe, spr); > } > > /* > * Free resource primary surface. If resource is display target, winsys > * manages the buffer and will free it on displaytarget_destroy. > */ > - if (res->display_target) { > + if (spr->display_target) { > /* display target */ > struct sw_winsys *winsys = screen->winsys; > - winsys->displaytarget_destroy(winsys, res->display_target); > + winsys->displaytarget_destroy(winsys, spr->display_target); > } else > - _aligned_free(res->swr.pBaseAddress); > + _aligned_free(spr->swr.pBaseAddress); > > - _aligned_free(res->secondary.pBaseAddress); > + _aligned_free(spr->secondary.pBaseAddress); > > - FREE(res); > + FREE(spr); > } > > > @@ -663,17 +660,19 @@ swr_flush_frontbuffer(struct pipe_screen > *p_screen, { > struct swr_screen *screen = swr_screen(p_screen); > struct sw_winsys *winsys = screen->winsys; > - struct swr_resource *res = swr_resource(resource); > + struct swr_resource *spr = swr_resource(resource); > + struct pipe_context *pipe = spr->bound_to_context; > > - /* Ensure fence set at flush is finished, before reading frame buffer */ > - swr_fence_finish(p_screen, screen->flush_fence, 0); > - > - SwrEndFrame(swr_context((pipe_context *)res->bound_to_context)); > + if (pipe) { > + swr_fence_finish(p_screen, screen->flush_fence, 0); > + swr_resource_unused(pipe, spr); > + SwrEndFrame(swr_context(pipe)->swrContext); > + } > > - assert(res->display_target); > - if (res->display_target) > + debug_assert(spr->display_target); > + if (spr->display_target) > winsys->displaytarget_display( > - winsys, res->display_target, context_private, sub_box); > + winsys, spr->display_target, context_private, sub_box); > } > > > diff --git a/src/gallium/drivers/swr/swr_state.cpp > b/src/gallium/drivers/swr/swr_state.cpp > index 49035b5..92245d8 100644 > --- a/src/gallium/drivers/swr/swr_state.cpp > +++ b/src/gallium/drivers/swr/swr_state.cpp > @@ -42,6 +42,7 @@ > #include "swr_tex_sample.h" > #include "swr_scratch.h" > #include "swr_shader.h" > +#include "swr_fence.h" > > /* These should be pulled out into separate files as necessary > * Just initializing everything here to get going. */ @@ -629,11 +630,58 @@ > swr_set_sample_mask(struct pipe_context *pipe, unsigned sample_mask) > } > } > > +/* > + * Update resource in-use status > + * All resources bound to color or depth targets marked as WRITE > resources. > + * VBO Vertex/index buffers and texture views marked as READ resources. > + */ > +void > +swr_update_resource_status(struct pipe_context *pipe, > + const struct pipe_draw_info *p_draw_info) { > + struct swr_context *ctx = swr_context(pipe); > + struct pipe_framebuffer_state *fb = &ctx->framebuffer; > + > + /* colorbuffer targets */ > + if (fb->nr_cbufs) > + for (uint32_t i = 0; i < fb->nr_cbufs; ++i) > + if (fb->cbufs[i]) > + swr_resource_write(pipe, > + swr_resource(fb->cbufs[i]->texture)); > + > + /* depth/stencil target */ > + if (fb->zsbuf) > + swr_resource_write(pipe, swr_resource(fb->zsbuf->texture)); > + > + /* VBO vertex buffers */ > + for (uint32_t i = 0; i < ctx->num_vertex_buffers; i++) { > + struct pipe_vertex_buffer *vb = &ctx->vertex_buffer[i]; > + if (!vb->user_buffer) > + swr_resource_read(pipe, swr_resource(vb->buffer)); > + } > + > + /* VBO index buffer */ > + if (p_draw_info && p_draw_info->indexed) { > + struct pipe_index_buffer *ib = &ctx->index_buffer; > + if (!ib->user_buffer) > + swr_resource_read(pipe, swr_resource(ib->buffer)); > + } > + > + /* texture sampler views */ > + for (uint32_t i = 0; i < PIPE_MAX_SHADER_SAMPLER_VIEWS; i++) { > + struct pipe_sampler_view *view = > + ctx->sampler_views[PIPE_SHADER_FRAGMENT][i]; > + if (view) > + swr_resource_read(pipe, swr_resource(view->texture)); > + } > +} > > void > -swr_update_derived(struct swr_context *ctx, > +swr_update_derived(struct pipe_context *pipe, > const struct pipe_draw_info *p_draw_info) { > + struct swr_context *ctx = swr_context(pipe); > + struct swr_screen *screen = swr_screen(ctx->pipe.screen); > + > /* Any state that requires dirty flags to be re-triggered sets this mask > */ > /* For example, user_buffer vertex and index buffers. */ > unsigned post_update_dirty_flags = 0; @@ -671,17 +719,24 @@ > swr_update_derived(struct swr_context *ctx, > /* Make the attachment updates */ > swr_draw_context *pDC = &ctx->swrDC; > SWR_SURFACE_STATE *renderTargets = pDC->renderTargets; > + unsigned need_fence = FALSE; > for (i = 0; i < SWR_NUM_ATTACHMENTS; i++) { > void *new_base = nullptr; > if (new_attachment[i]) > new_base = new_attachment[i]->pBaseAddress; > - > + > /* StoreTile for changed target */ > if (renderTargets[i].pBaseAddress != new_base) { > if (renderTargets[i].pBaseAddress) { > + /* If changing attachment to a new target, mark tiles as > + * INVALID so they are reloaded from surface. > + * If detaching attachment, mark tiles as RESOLVED so core > + * won't try to load from non-existent target. */ > enum SWR_TILE_STATE post_state = (new_attachment[i] > ? SWR_TILE_INVALID : SWR_TILE_RESOLVED); > - swr_store_render_target(ctx, i, post_state); > + swr_store_render_target(pipe, i, post_state); > + > + need_fence |= TRUE; > } > > /* Make new attachment */ > @@ -692,6 +747,11 @@ swr_update_derived(struct swr_context *ctx, > renderTargets[i] = {0}; > } > } > + > + /* This fence ensures any attachment changes are resolved before the > + * next draw */ > + if (need_fence) > + swr_fence_submit(ctx, screen->flush_fence); > } > > /* Raster state */ > @@ -793,8 +853,7 @@ swr_update_derived(struct swr_context *ctx, > vpm->m32 = state->translate[2]; > > /* Now that the matrix is calculated, clip the view coords to screen > - * size. OpenGL allows for -ve x,y in the viewport. > - */ > + * size. OpenGL allows for -ve x,y in the viewport. */ > vp->x = std::max(vp->x, 0.0f); > vp->y = std::max(vp->y, 0.0f); > vp->width = std::min(vp->width, (float)fb->width); @@ -817,7 +876,7 > @@ swr_update_derived(struct swr_context *ctx, > /* vertex buffers */ > SWR_VERTEX_BUFFER_STATE swrVertexBuffers[PIPE_MAX_ATTRIBS]; > for (UINT i = 0; i < ctx->num_vertex_buffers; i++) { > - pipe_vertex_buffer *vb = &ctx->vertex_buffer[i]; > + struct pipe_vertex_buffer *vb = &ctx->vertex_buffer[i]; > > pitch = vb->stride; > if (!vb->user_buffer) { > @@ -871,7 +930,7 @@ swr_update_derived(struct swr_context *ctx, > /* index buffer, if required (info passed in by swr_draw_vbo) */ > SWR_FORMAT index_type = R32_UINT; /* Default for non-indexed draws > */ > if (info.indexed) { > - pipe_index_buffer *ib = &ctx->index_buffer; > + struct pipe_index_buffer *ib = &ctx->index_buffer; > > pitch = ib->index_size ? ib->index_size : sizeof(uint32_t); > index_type = swr_convert_index_type(pitch); @@ -1195,7 +1254,7 @@ > swr_update_derived(struct swr_context *ctx, > if (search != ctx->blendJIT->end()) { > func = search->second; > } else { > - HANDLE hJitMgr = swr_screen(ctx->pipe.screen)->hJitMgr; > + HANDLE hJitMgr = screen->hJitMgr; > func = JitCompileBlend(hJitMgr, compileState); > debug_printf("BLEND shader %p\n", func); > assert(func && "Error: BlendShader = NULL"); @@ -1253,9 > +1312,17 > @@ swr_update_derived(struct swr_context *ctx, > > SwrSetBackendState(ctx->swrContext, &backendState); > > + /* Ensure that any in-progress attachment change StoreTiles finish */ > + if (swr_is_fence_pending(screen->flush_fence)) > + swr_fence_finish(pipe->screen, screen->flush_fence, 0); > + > + /* Finally, update the in-use status of all resources involved in draw */ > + swr_update_resource_status(pipe, p_draw_info); > + > ctx->dirty = post_update_dirty_flags; } > > + > static struct pipe_stream_output_target * swr_create_so_target(struct > pipe_context *pipe, > struct pipe_resource *buffer, diff --git > a/src/gallium/drivers/swr/swr_state.h > b/src/gallium/drivers/swr/swr_state.h > index a2b4d80..f0a7ff3 100644 > --- a/src/gallium/drivers/swr/swr_state.h > +++ b/src/gallium/drivers/swr/swr_state.h > @@ -76,7 +76,7 @@ struct swr_derived_state { > SWR_VIEWPORT_MATRIX vpm; > }; > > -void swr_update_derived(struct swr_context *, > +void swr_update_derived(struct pipe_context *, > const struct pipe_draw_info * = nullptr); > > /* > -- > 1.7.1 > > _______________________________________________ > mesa-dev mailing list > [email protected] > https://lists.freedesktop.org/mailman/listinfo/mesa-dev _______________________________________________ mesa-dev mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/mesa-dev
