summaryrefslogtreecommitdiff
path: root/src/gallium/drivers/softpipe
diff options
context:
space:
mode:
authorJosé Fonseca <jfonseca@vmware.com>2010-04-25 17:03:48 +0100
committerJosé Fonseca <jfonseca@vmware.com>2010-04-25 23:41:48 +0100
commit53e94bd4adb218c5974c522389c3bcf40f3fa7e8 (patch)
treebc8061898c4f8b0852645124a0c2a6cccdf16880 /src/gallium/drivers/softpipe
parent43b85af56efbe6eb06f4e62d23e9f6f583c5ec2e (diff)
softpipe: Make softpipe transfers in-order.
Transfer, being now a context operation, should happen in order with all other contexts operations. If there is rendering pending on the resource then the driver must flush and potentially wait itself internally. Instead of avoiding using transfers internally (as done in llvmpipe) I've opted to simply pass PIPE_TRANSFER_UNSYNCHRONIZED in all internal transfers, to avoid infinite recursion.
Diffstat (limited to 'src/gallium/drivers/softpipe')
-rw-r--r--src/gallium/drivers/softpipe/sp_flush.c68
-rw-r--r--src/gallium/drivers/softpipe/sp_flush.h17
-rw-r--r--src/gallium/drivers/softpipe/sp_tex_tile_cache.c3
-rw-r--r--src/gallium/drivers/softpipe/sp_texture.c22
-rw-r--r--src/gallium/drivers/softpipe/sp_tile_cache.c3
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 508fe8f764..5024fc8a81 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 68d9b5fa83..cb97482a71 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 c79f5fb05a..fbce9e042b 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 167b6b1161..3533c4fd4f 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 4e5a13ba05..f4db6f6ef0 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 ||