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:
Bruce Cherniak 2016-03-09 19:30:00 -06:00 committed by Tim Rowley
parent 7a2333e4ef
commit e9d68cc3da
10 changed files with 264 additions and 142 deletions

View File

@ -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);
}

View File

@ -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);

View File

@ -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)

View File

@ -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();
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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

View File

@ -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);
}

View File

@ -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,

View File

@ -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);
/*