diff options
-rw-r--r-- | src/gallium/drivers/swr/swr_context.cpp | 14 | ||||
-rw-r--r-- | src/gallium/drivers/swr/swr_draw.cpp | 19 | ||||
-rw-r--r-- | src/gallium/drivers/swr/swr_resource.h | 3 | ||||
-rw-r--r-- | src/gallium/drivers/swr/swr_state.cpp | 44 |
4 files changed, 70 insertions, 10 deletions
diff --git a/src/gallium/drivers/swr/swr_context.cpp b/src/gallium/drivers/swr/swr_context.cpp index e95bd3bcaa4..34d9a259fee 100644 --- a/src/gallium/drivers/swr/swr_context.cpp +++ b/src/gallium/drivers/swr/swr_context.cpp @@ -365,10 +365,20 @@ swr_destroy(struct pipe_context *pipe) util_blitter_destroy(ctx->blitter); for (unsigned i = 0; i < PIPE_MAX_COLOR_BUFS; i++) { - pipe_surface_reference(&ctx->framebuffer.cbufs[i], NULL); + if (ctx->framebuffer.cbufs[i]) { + struct swr_resource *res = swr_resource(ctx->framebuffer.cbufs[i]->texture); + /* NULL curr_pipe, so we don't have a reference to a deleted pipe */ + res->curr_pipe = NULL; + pipe_surface_reference(&ctx->framebuffer.cbufs[i], NULL); + } } - pipe_surface_reference(&ctx->framebuffer.zsbuf, NULL); + if (ctx->framebuffer.zsbuf) { + struct swr_resource *res = swr_resource(ctx->framebuffer.zsbuf->texture); + /* NULL curr_pipe, so we don't have a reference to a deleted pipe */ + res->curr_pipe = NULL; + pipe_surface_reference(&ctx->framebuffer.zsbuf, NULL); + } for (unsigned i = 0; i < ARRAY_SIZE(ctx->sampler_views[0]); i++) { pipe_sampler_view_reference(&ctx->sampler_views[PIPE_SHADER_FRAGMENT][i], NULL); diff --git a/src/gallium/drivers/swr/swr_draw.cpp b/src/gallium/drivers/swr/swr_draw.cpp index d7f24d6e346..57660c7464d 100644 --- a/src/gallium/drivers/swr/swr_draw.cpp +++ b/src/gallium/drivers/swr/swr_draw.cpp @@ -239,14 +239,17 @@ 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). - * 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); + + for (int i=0; i < ctx->framebuffer.nr_cbufs; i++) { + struct pipe_surface *cb = ctx->framebuffer.cbufs[i]; + if (cb) { + swr_store_dirty_resource(pipe, cb->texture, SWR_TILE_RESOLVED); + } + } + if (ctx->framebuffer.zsbuf) { + swr_store_dirty_resource(pipe, ctx->framebuffer.zsbuf->texture, + SWR_TILE_RESOLVED); + } if (fence) swr_fence_reference(pipe->screen, fence, screen->flush_fence); diff --git a/src/gallium/drivers/swr/swr_resource.h b/src/gallium/drivers/swr/swr_resource.h index 4a2d66906a6..12694332add 100644 --- a/src/gallium/drivers/swr/swr_resource.h +++ b/src/gallium/drivers/swr/swr_resource.h @@ -54,6 +54,9 @@ struct swr_resource { size_t secondary_mip_offsets[PIPE_MAX_TEXTURE_LEVELS]; enum swr_resource_status status; + + /* last pipe that used (validated) this resource */ + struct pipe_context *curr_pipe; }; diff --git a/src/gallium/drivers/swr/swr_state.cpp b/src/gallium/drivers/swr/swr_state.cpp index 93108de0655..893bd6e5bcc 100644 --- a/src/gallium/drivers/swr/swr_state.cpp +++ b/src/gallium/drivers/swr/swr_state.cpp @@ -953,6 +953,47 @@ swr_change_rt(struct swr_context *ctx, return need_fence; } +/* + * for cases where resources are shared between contexts, invalidate + * this ctx's resource. so it can be fetched fresh. Old ctx's resource + * is already stored during a flush + */ +static inline void +swr_invalidate_buffers_after_ctx_change(struct pipe_context *pipe) +{ + struct swr_context *ctx = swr_context(pipe); + + for (uint32_t i = 0; i < ctx->framebuffer.nr_cbufs; i++) { + struct pipe_surface *cb = ctx->framebuffer.cbufs[i]; + if (cb) { + struct swr_resource *res = swr_resource(cb->texture); + if (res->curr_pipe != pipe) { + /* if curr_pipe is NULL (first use), status should not be WRITE */ + assert(res->curr_pipe || !(res->status & SWR_RESOURCE_WRITE)); + if (res->status & SWR_RESOURCE_WRITE) { + swr_invalidate_render_target(pipe, i, cb->width, cb->height); + } + } + res->curr_pipe = pipe; + } + } + if (ctx->framebuffer.zsbuf) { + struct pipe_surface *zb = ctx->framebuffer.zsbuf; + if (zb) { + struct swr_resource *res = swr_resource(zb->texture); + if (res->curr_pipe != pipe) { + /* if curr_pipe is NULL (first use), status should not be WRITE */ + assert(res->curr_pipe || !(res->status & SWR_RESOURCE_WRITE)); + if (res->status & SWR_RESOURCE_WRITE) { + swr_invalidate_render_target(pipe, SWR_ATTACHMENT_DEPTH, zb->width, zb->height); + swr_invalidate_render_target(pipe, SWR_ATTACHMENT_STENCIL, zb->width, zb->height); + } + } + res->curr_pipe = pipe; + } + } +} + static inline void swr_user_vbuf_range(const struct pipe_draw_info *info, const struct swr_vertex_element_state *velems, @@ -1040,6 +1081,9 @@ swr_update_derived(struct pipe_context *pipe, /* For example, user_buffer vertex and index buffers. */ unsigned post_update_dirty_flags = 0; + /* bring resources that changed context up-to-date */ + swr_invalidate_buffers_after_ctx_change(pipe); + /* Render Targets */ if (ctx->dirty & SWR_NEW_FRAMEBUFFER) { struct pipe_framebuffer_state *fb = &ctx->framebuffer; |