summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gallium/drivers/swr/swr_context.cpp14
-rw-r--r--src/gallium/drivers/swr/swr_draw.cpp19
-rw-r--r--src/gallium/drivers/swr/swr_resource.h3
-rw-r--r--src/gallium/drivers/swr/swr_state.cpp44
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;