diff options
Diffstat (limited to 'src/gallium/drivers/softpipe')
-rw-r--r-- | src/gallium/drivers/softpipe/sp_flush.c | 68 | ||||
-rw-r--r-- | src/gallium/drivers/softpipe/sp_flush.h | 17 | ||||
-rw-r--r-- | src/gallium/drivers/softpipe/sp_tex_tile_cache.c | 3 | ||||
-rw-r--r-- | src/gallium/drivers/softpipe/sp_texture.c | 22 | ||||
-rw-r--r-- | src/gallium/drivers/softpipe/sp_tile_cache.c | 3 |
5 files changed, 109 insertions, 4 deletions
diff --git a/src/gallium/drivers/softpipe/sp_flush.c b/src/gallium/drivers/softpipe/sp_flush.c index 508fe8f764d..5024fc8a819 100644 --- a/src/gallium/drivers/softpipe/sp_flush.c +++ b/src/gallium/drivers/softpipe/sp_flush.c @@ -104,3 +104,71 @@ softpipe_flush( struct pipe_context *pipe, *fence = NULL; } + +/** + * Flush context if necessary. + * + * Returns FALSE if it would have block, but do_not_block was set, TRUE + * otherwise. + * + * TODO: move this logic to an auxiliary library? + */ +boolean +softpipe_flush_resource(struct pipe_context *pipe, + struct pipe_resource *texture, + unsigned face, + unsigned level, + unsigned flush_flags, + boolean read_only, + boolean cpu_access, + boolean do_not_block) +{ + unsigned referenced; + + referenced = pipe->is_resource_referenced(pipe, texture, face, level); + + if ((referenced & PIPE_REFERENCED_FOR_WRITE) || + ((referenced & PIPE_REFERENCED_FOR_READ) && !read_only)) { + + /* + * TODO: The semantics of these flush flags are too obtuse. They should + * disappear and the pipe driver should just ensure that all visible + * side-effects happen when they need to happen. + */ + if (referenced & PIPE_REFERENCED_FOR_WRITE) + flush_flags |= PIPE_FLUSH_RENDER_CACHE; + + if (referenced & PIPE_REFERENCED_FOR_READ) + flush_flags |= PIPE_FLUSH_TEXTURE_CACHE; + + if (cpu_access) { + /* + * Flush and wait. + */ + + struct pipe_fence_handle *fence = NULL; + + if (do_not_block) + return FALSE; + + pipe->flush(pipe, flush_flags, &fence); + + if (fence) { + /* + * This is for illustrative purposes only, as softpipe does not + * have fences. + */ + pipe->screen->fence_finish(pipe->screen, fence, 0); + pipe->screen->fence_reference(pipe->screen, &fence, NULL); + } + } else { + /* + * Just flush. + */ + + pipe->flush(pipe, flush_flags, NULL); + } + } + + return TRUE; +} diff --git a/src/gallium/drivers/softpipe/sp_flush.h b/src/gallium/drivers/softpipe/sp_flush.h index 68d9b5fa835..cb97482a71b 100644 --- a/src/gallium/drivers/softpipe/sp_flush.h +++ b/src/gallium/drivers/softpipe/sp_flush.h @@ -28,10 +28,23 @@ #ifndef SP_FLUSH_H #define SP_FLUSH_H +#include "pipe/p_compiler.h" + struct pipe_context; struct pipe_fence_handle; -void softpipe_flush(struct pipe_context *pipe, unsigned flags, - struct pipe_fence_handle **fence); +void +softpipe_flush(struct pipe_context *pipe, unsigned flags, + struct pipe_fence_handle **fence); + +boolean +softpipe_flush_resource(struct pipe_context *pipe, + struct pipe_resource *texture, + unsigned face, + unsigned level, + unsigned flush_flags, + boolean read_only, + boolean cpu_access, + boolean do_not_block); #endif diff --git a/src/gallium/drivers/softpipe/sp_tex_tile_cache.c b/src/gallium/drivers/softpipe/sp_tex_tile_cache.c index c79f5fb05a1..fbce9e042ba 100644 --- a/src/gallium/drivers/softpipe/sp_tex_tile_cache.c +++ b/src/gallium/drivers/softpipe/sp_tex_tile_cache.c @@ -248,7 +248,8 @@ sp_find_cached_tile_tex(struct softpipe_tex_tile_cache *tc, addr.bits.face, addr.bits.level, addr.bits.z, - PIPE_TRANSFER_READ, 0, 0, + PIPE_TRANSFER_READ | PIPE_TRANSFER_UNSYNCHRONIZED, + 0, 0, u_minify(tc->texture->width0, addr.bits.level), u_minify(tc->texture->height0, addr.bits.level)); diff --git a/src/gallium/drivers/softpipe/sp_texture.c b/src/gallium/drivers/softpipe/sp_texture.c index 167b6b11617..3533c4fd4f0 100644 --- a/src/gallium/drivers/softpipe/sp_texture.c +++ b/src/gallium/drivers/softpipe/sp_texture.c @@ -39,6 +39,7 @@ #include "util/u_transfer.h" #include "sp_context.h" +#include "sp_flush.h" #include "sp_texture.h" #include "sp_screen.h" @@ -301,6 +302,27 @@ softpipe_get_transfer(struct pipe_context *pipe, assert(box->y + box->height <= u_minify(resource->height0, sr.level)); assert(box->z + box->depth <= u_minify(resource->depth0, sr.level)); + /* + * Transfers, like other pipe operations, must happen in order, so flush the + * context if necessary. + */ + if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) { + boolean read_only = !(usage & PIPE_TRANSFER_WRITE); + boolean do_not_block = !!(usage & PIPE_TRANSFER_DONTBLOCK); + if (!softpipe_flush_resource(pipe, resource, + sr.face, sr.level, + 0, /* flush_flags */ + read_only, + TRUE, /* cpu_access */ + do_not_block)) { + /* + * It would have blocked, but state tracker requested no to. + */ + assert(do_not_block); + return NULL; + } + } + spr = CALLOC_STRUCT(softpipe_transfer); if (spr) { struct pipe_transfer *pt = &spr->base; diff --git a/src/gallium/drivers/softpipe/sp_tile_cache.c b/src/gallium/drivers/softpipe/sp_tile_cache.c index 4e5a13ba051..f4db6f6ef00 100644 --- a/src/gallium/drivers/softpipe/sp_tile_cache.c +++ b/src/gallium/drivers/softpipe/sp_tile_cache.c @@ -155,7 +155,8 @@ sp_tile_cache_set_surface(struct softpipe_tile_cache *tc, if (ps) { tc->transfer = pipe_get_transfer(pipe, ps->texture, ps->face, ps->level, ps->zslice, - PIPE_TRANSFER_READ_WRITE, + PIPE_TRANSFER_READ_WRITE | + PIPE_TRANSFER_UNSYNCHRONIZED, 0, 0, ps->width, ps->height); tc->depth_stencil = (ps->format == PIPE_FORMAT_Z24_UNORM_S8_USCALED || |