diff options
Diffstat (limited to 'src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.c')
-rw-r--r-- | src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.c | 183 |
1 files changed, 111 insertions, 72 deletions
diff --git a/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.c b/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.c index 17b2781052..0cddc95aa6 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.c +++ b/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.c @@ -29,7 +29,7 @@ * \file * Implementation of fenced buffers. * - * \author José Fonseca <jrfonseca-at-tungstengraphics-dot-com> + * \author Jose Fonseca <jrfonseca-at-tungstengraphics-dot-com> * \author Thomas Hellström <thomas-at-tungstengraphics-dot-com> */ @@ -43,8 +43,7 @@ #include "pipe/p_compiler.h" #include "pipe/p_error.h" -#include "pipe/p_debug.h" -#include "pipe/p_winsys.h" +#include "util/u_debug.h" #include "pipe/p_thread.h" #include "util/u_memory.h" #include "util/u_double_list.h" @@ -59,19 +58,12 @@ */ #define SUPER(__derived) (&(__derived)->base) -#define PIPE_BUFFER_USAGE_CPU_READ_WRITE \ - ( PIPE_BUFFER_USAGE_CPU_READ | PIPE_BUFFER_USAGE_CPU_WRITE ) -#define PIPE_BUFFER_USAGE_GPU_READ_WRITE \ - ( PIPE_BUFFER_USAGE_GPU_READ | PIPE_BUFFER_USAGE_GPU_WRITE ) -#define PIPE_BUFFER_USAGE_WRITE \ - ( PIPE_BUFFER_USAGE_CPU_WRITE | PIPE_BUFFER_USAGE_GPU_WRITE ) - struct fenced_buffer_list { pipe_mutex mutex; - struct pipe_winsys *winsys; + struct pb_fence_ops *ops; size_t numDelayed; @@ -97,6 +89,8 @@ struct fenced_buffer unsigned flags; unsigned mapcount; + struct pb_validate *vl; + unsigned validation_flags; struct pipe_fence_handle *fence; struct list_head head; @@ -108,7 +102,6 @@ static INLINE struct fenced_buffer * fenced_buffer(struct pb_buffer *buf) { assert(buf); - assert(buf->vtbl == &fenced_buffer_vtbl); return (struct fenced_buffer *)buf; } @@ -146,12 +139,12 @@ static INLINE void _fenced_buffer_remove(struct fenced_buffer_list *fenced_list, struct fenced_buffer *fenced_buf) { - struct pipe_winsys *winsys = fenced_list->winsys; + struct pb_fence_ops *ops = fenced_list->ops; assert(fenced_buf->fence); assert(fenced_buf->list == fenced_list); - winsys->fence_reference(winsys, &fenced_buf->fence, NULL); + ops->fence_reference(ops, &fenced_buf->fence, NULL); fenced_buf->flags &= ~PIPE_BUFFER_USAGE_GPU_READ_WRITE; assert(fenced_buf->head.prev); @@ -174,7 +167,7 @@ static INLINE enum pipe_error _fenced_buffer_finish(struct fenced_buffer *fenced_buf) { struct fenced_buffer_list *fenced_list = fenced_buf->list; - struct pipe_winsys *winsys = fenced_list->winsys; + struct pb_fence_ops *ops = fenced_list->ops; #if 0 debug_warning("waiting for GPU"); @@ -182,7 +175,7 @@ _fenced_buffer_finish(struct fenced_buffer *fenced_buf) assert(fenced_buf->fence); if(fenced_buf->fence) { - if(winsys->fence_finish(winsys, fenced_buf->fence, 0) != 0) { + if(ops->fence_finish(ops, fenced_buf->fence, 0) != 0) { return PIPE_ERROR; } /* Remove from the fenced list */ @@ -202,7 +195,7 @@ static void _fenced_buffer_list_check_free(struct fenced_buffer_list *fenced_list, int wait) { - struct pipe_winsys *winsys = fenced_list->winsys; + struct pb_fence_ops *ops = fenced_list->ops; struct list_head *curr, *next; struct fenced_buffer *fenced_buf; struct pipe_fence_handle *prev_fence = NULL; @@ -215,15 +208,15 @@ _fenced_buffer_list_check_free(struct fenced_buffer_list *fenced_list, if(fenced_buf->fence != prev_fence) { int signaled; if (wait) - signaled = winsys->fence_finish(winsys, fenced_buf->fence, 0); + signaled = ops->fence_finish(ops, fenced_buf->fence, 0); else - signaled = winsys->fence_signalled(winsys, fenced_buf->fence, 0); + signaled = ops->fence_signalled(ops, fenced_buf->fence, 0); if (signaled != 0) break; prev_fence = fenced_buf->fence; } else { - assert(winsys->fence_signalled(winsys, fenced_buf->fence, 0) == 0); + assert(ops->fence_signalled(ops, fenced_buf->fence, 0) == 0); } _fenced_buffer_remove(fenced_list, fenced_buf); @@ -243,14 +236,14 @@ fenced_buffer_destroy(struct pb_buffer *buf) pipe_mutex_lock(fenced_list->mutex); assert(fenced_buf->base.base.refcount == 0); if (fenced_buf->fence) { - struct pipe_winsys *winsys = fenced_list->winsys; - if(winsys->fence_signalled(winsys, fenced_buf->fence, 0) == 0) { + struct pb_fence_ops *ops = fenced_list->ops; + if(ops->fence_signalled(ops, fenced_buf->fence, 0) == 0) { struct list_head *curr, *prev; curr = &fenced_buf->head; prev = curr->prev; do { fenced_buf = LIST_ENTRY(struct fenced_buffer, curr, head); - assert(winsys->fence_signalled(winsys, fenced_buf->fence, 0) == 0); + assert(ops->fence_signalled(ops, fenced_buf->fence, 0) == 0); _fenced_buffer_remove(fenced_list, fenced_buf); curr = prev; prev = curr->prev; @@ -274,6 +267,7 @@ fenced_buffer_map(struct pb_buffer *buf, struct fenced_buffer *fenced_buf = fenced_buffer(buf); void *map; + assert(flags & PIPE_BUFFER_USAGE_CPU_READ_WRITE); assert(!(flags & ~PIPE_BUFFER_USAGE_CPU_READ_WRITE)); flags &= PIPE_BUFFER_USAGE_CPU_READ_WRITE; @@ -315,6 +309,93 @@ fenced_buffer_unmap(struct pb_buffer *buf) } +static enum pipe_error +fenced_buffer_validate(struct pb_buffer *buf, + struct pb_validate *vl, + unsigned flags) +{ + struct fenced_buffer *fenced_buf = fenced_buffer(buf); + enum pipe_error ret; + + if(!vl) { + /* invalidate */ + fenced_buf->vl = NULL; + fenced_buf->validation_flags = 0; + return PIPE_OK; + } + + assert(flags & PIPE_BUFFER_USAGE_GPU_READ_WRITE); + assert(!(flags & ~PIPE_BUFFER_USAGE_GPU_READ_WRITE)); + flags &= PIPE_BUFFER_USAGE_GPU_READ_WRITE; + + /* Buffer cannot be validated in two different lists */ + if(fenced_buf->vl && fenced_buf->vl != vl) + return PIPE_ERROR_RETRY; + + /* Do not validate if buffer is still mapped */ + if(fenced_buf->flags & PIPE_BUFFER_USAGE_CPU_READ_WRITE) { + /* TODO: wait for the thread that mapped the buffer to unmap it */ + return PIPE_ERROR_RETRY; + } + + if(fenced_buf->vl == vl && + (fenced_buf->validation_flags & flags) == flags) { + /* Nothing to do -- buffer already validated */ + return PIPE_OK; + } + + /* Final sanity checking */ + assert(!(fenced_buf->flags & PIPE_BUFFER_USAGE_CPU_READ_WRITE)); + assert(!fenced_buf->mapcount); + + ret = pb_validate(fenced_buf->buffer, vl, flags); + if (ret != PIPE_OK) + return ret; + + fenced_buf->vl = vl; + fenced_buf->validation_flags |= flags; + + return PIPE_OK; +} + + +static void +fenced_buffer_fence(struct pb_buffer *buf, + struct pipe_fence_handle *fence) +{ + struct fenced_buffer *fenced_buf; + struct fenced_buffer_list *fenced_list; + struct pb_fence_ops *ops; + + fenced_buf = fenced_buffer(buf); + fenced_list = fenced_buf->list; + ops = fenced_list->ops; + + if(fence == fenced_buf->fence) { + /* Nothing to do */ + return; + } + + assert(fenced_buf->vl); + assert(fenced_buf->validation_flags); + + pipe_mutex_lock(fenced_list->mutex); + if (fenced_buf->fence) + _fenced_buffer_remove(fenced_list, fenced_buf); + if (fence) { + ops->fence_reference(ops, &fenced_buf->fence, fence); + fenced_buf->flags |= fenced_buf->validation_flags; + _fenced_buffer_add(fenced_buf); + } + pipe_mutex_unlock(fenced_list->mutex); + + pb_fence(fenced_buf->buffer, fence); + + fenced_buf->vl = NULL; + fenced_buf->validation_flags = 0; +} + + static void fenced_buffer_get_base_buffer(struct pb_buffer *buf, struct pb_buffer **base_buf, @@ -325,11 +406,13 @@ fenced_buffer_get_base_buffer(struct pb_buffer *buf, } -const struct pb_vtbl +static const struct pb_vtbl fenced_buffer_vtbl = { fenced_buffer_destroy, fenced_buffer_map, fenced_buffer_unmap, + fenced_buffer_validate, + fenced_buffer_fence, fenced_buffer_get_base_buffer }; @@ -362,54 +445,8 @@ fenced_buffer_create(struct fenced_buffer_list *fenced_list, } -void -buffer_fence(struct pb_buffer *buf, - struct pipe_fence_handle *fence) -{ - struct fenced_buffer *fenced_buf; - struct fenced_buffer_list *fenced_list; - struct pipe_winsys *winsys; - /* FIXME: receive this as a parameter */ - unsigned flags = fence ? PIPE_BUFFER_USAGE_GPU_READ_WRITE : 0; - - /* This is a public function, so be extra cautious with the buffer passed, - * as happens frequently to receive null buffers, or pointer to buffers - * other than fenced buffers. */ - assert(buf); - if(!buf) - return; - assert(buf->vtbl == &fenced_buffer_vtbl); - if(buf->vtbl != &fenced_buffer_vtbl) - return; - - fenced_buf = fenced_buffer(buf); - fenced_list = fenced_buf->list; - winsys = fenced_list->winsys; - - if(!fence || fence == fenced_buf->fence) { - /* Handle the same fence case specially, not only because it is a fast - * path, but mostly to avoid serializing two writes with the same fence, - * as that would bring the hardware down to synchronous operation without - * any benefit. - */ - fenced_buf->flags |= flags & PIPE_BUFFER_USAGE_GPU_READ_WRITE; - return; - } - - pipe_mutex_lock(fenced_list->mutex); - if (fenced_buf->fence) - _fenced_buffer_remove(fenced_list, fenced_buf); - if (fence) { - winsys->fence_reference(winsys, &fenced_buf->fence, fence); - fenced_buf->flags |= flags & PIPE_BUFFER_USAGE_GPU_READ_WRITE; - _fenced_buffer_add(fenced_buf); - } - pipe_mutex_unlock(fenced_list->mutex); -} - - struct fenced_buffer_list * -fenced_buffer_list_create(struct pipe_winsys *winsys) +fenced_buffer_list_create(struct pb_fence_ops *ops) { struct fenced_buffer_list *fenced_list; @@ -417,7 +454,7 @@ fenced_buffer_list_create(struct pipe_winsys *winsys) if (!fenced_list) return NULL; - fenced_list->winsys = winsys; + fenced_list->ops = ops; LIST_INITHEAD(&fenced_list->delayed); @@ -456,6 +493,8 @@ fenced_buffer_list_destroy(struct fenced_buffer_list *fenced_list) pipe_mutex_unlock(fenced_list->mutex); + fenced_list->ops->destroy(fenced_list->ops); + FREE(fenced_list); } |