gallium/swr: Resource management
Better tracking of resource state and synchronization. A follow on commit will clean up resource functions into a new swr_resource.cpp file. Reviewed-By: George Kyriazis <george.kyriazis@intel.com>
This commit is contained in:
parent
7a2333e4ef
commit
e9d68cc3da
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
/* If the resource has been drawn to, store tiles. */
|
||||
swr_store_dirty_resource(pipe, resource, 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;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
struct pipe_surface *cb = ctx->framebuffer.cbufs[0];
|
||||
|
||||
/* 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);
|
||||
* 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)
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
struct swr_resource *spr = swr_resource(pt);
|
||||
struct pipe_context *pipe = spr->bound_to_context;
|
||||
|
||||
/*
|
||||
* 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);
|
||||
/* 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);
|
||||
if (pipe) {
|
||||
swr_fence_finish(p_screen, screen->flush_fence, 0);
|
||||
swr_resource_unused(pipe, spr);
|
||||
SwrEndFrame(swr_context(pipe)->swrContext);
|
||||
}
|
||||
|
||||
SwrEndFrame(swr_context((pipe_context *)res->bound_to_context));
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue