From 82dd0225e7e21a35ca66d439dce8cfa39d782470 Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Thu, 8 May 2008 15:28:42 +0900 Subject: pipebuffer: Preliminary buffer validation. Use table to store a list of buffers to validate. Unfortunately cso_hash shrinks/regrows the hash every time, so still has to be addressed. Multi-thread validation is still WIP. --- src/gallium/auxiliary/pipebuffer/pb_validate.h | 91 ++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 src/gallium/auxiliary/pipebuffer/pb_validate.h (limited to 'src/gallium/auxiliary/pipebuffer/pb_validate.h') diff --git a/src/gallium/auxiliary/pipebuffer/pb_validate.h b/src/gallium/auxiliary/pipebuffer/pb_validate.h new file mode 100644 index 0000000000..b0f05d3119 --- /dev/null +++ b/src/gallium/auxiliary/pipebuffer/pb_validate.h @@ -0,0 +1,91 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/** + * @file + * Buffer validation. + * + * @author Jose Fonseca + */ + +#ifndef PB_VALIDATE_H_ +#define PB_VALIDATE_H_ + + +#include "pipe/p_compiler.h" +#include "pipe/p_error.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +struct pb_buffer; +struct pipe_fence_handle; + + +/** + * Buffer validation list. + * + * It holds a list of buffers to be validated and fenced when flushing. + */ +struct pb_validate; + + +enum pipe_error +pb_validate_add_buffer(struct pb_validate *vl, + struct pb_buffer *buf); + +/** + * Validate all buffers for hardware access. + * + * Should be called right before issuing commands to the hardware. + */ +enum pipe_error +pb_validate_validate(struct pb_validate *vl); + +/** + * Fence all buffers and clear the list. + * + * Should be called right before issuing commands to the hardware. + */ +void +pb_validate_fence(struct pb_validate *vl, + struct pipe_fence_handle *fence); + +struct pb_validate * +pb_validate_create(); + +void +pb_validate_destroy(struct pb_validate *vl); + + +#ifdef __cplusplus +} +#endif + +#endif /*PB_VALIDATE_H_*/ -- cgit v1.2.3 From 7ffbfaccfb1484a4ffd5aea0e0e1fbb407977a56 Mon Sep 17 00:00:00 2001 From: Michel Dänzer Date: Thu, 8 May 2008 13:26:23 +0100 Subject: gallium: Make sure functions have proper prototypes and remove unused variable. --- src/gallium/auxiliary/pipebuffer/pb_validate.c | 2 +- src/gallium/auxiliary/pipebuffer/pb_validate.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/gallium/auxiliary/pipebuffer/pb_validate.h') diff --git a/src/gallium/auxiliary/pipebuffer/pb_validate.c b/src/gallium/auxiliary/pipebuffer/pb_validate.c index a0a0965a46..b32fe2252e 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_validate.c +++ b/src/gallium/auxiliary/pipebuffer/pb_validate.c @@ -42,6 +42,7 @@ #include "pb_buffer.h" #include "pb_buffer_fenced.h" +#include "pb_validate.h" struct pb_validate @@ -107,7 +108,6 @@ pb_validate_fence_cb(void *key, void *value, void *_data) { struct pb_buffer *buf = (struct pb_buffer *)key; struct pb_validate_fence_data *data = (struct pb_validate_fence_data *)_data; - struct pb_validate *vl = data->vl; struct pipe_fence_handle *fence = data->fence; assert(value == key); diff --git a/src/gallium/auxiliary/pipebuffer/pb_validate.h b/src/gallium/auxiliary/pipebuffer/pb_validate.h index b0f05d3119..3db1d5330b 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_validate.h +++ b/src/gallium/auxiliary/pipebuffer/pb_validate.h @@ -78,7 +78,7 @@ pb_validate_fence(struct pb_validate *vl, struct pipe_fence_handle *fence); struct pb_validate * -pb_validate_create(); +pb_validate_create(void); void pb_validate_destroy(struct pb_validate *vl); -- cgit v1.2.3 From a6d866f72c88d48d2bcfb3e3c882fdb639b5a8ce Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Mon, 24 Nov 2008 13:59:06 +0900 Subject: pipebuffer: Implement proper buffer validation. --- src/gallium/auxiliary/pipebuffer/pb_buffer.h | 36 ++++- .../auxiliary/pipebuffer/pb_buffer_fenced.c | 158 +++++++++++++-------- .../auxiliary/pipebuffer/pb_buffer_fenced.h | 21 +-- .../auxiliary/pipebuffer/pb_buffer_malloc.c | 20 +++ src/gallium/auxiliary/pipebuffer/pb_bufmgr.h | 2 +- src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c | 23 ++- src/gallium/auxiliary/pipebuffer/pb_bufmgr_debug.c | 26 +++- .../auxiliary/pipebuffer/pb_bufmgr_fenced.c | 2 +- src/gallium/auxiliary/pipebuffer/pb_bufmgr_mm.c | 25 +++- src/gallium/auxiliary/pipebuffer/pb_bufmgr_pool.c | 25 +++- src/gallium/auxiliary/pipebuffer/pb_bufmgr_slab.c | 21 +++ src/gallium/auxiliary/pipebuffer/pb_validate.c | 84 ++++++++--- src/gallium/auxiliary/pipebuffer/pb_validate.h | 10 +- src/gallium/auxiliary/pipebuffer/pb_winsys.c | 22 ++- 14 files changed, 367 insertions(+), 108 deletions(-) (limited to 'src/gallium/auxiliary/pipebuffer/pb_validate.h') diff --git a/src/gallium/auxiliary/pipebuffer/pb_buffer.h b/src/gallium/auxiliary/pipebuffer/pb_buffer.h index 8505d333bd..c9570d7be2 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_buffer.h +++ b/src/gallium/auxiliary/pipebuffer/pb_buffer.h @@ -37,7 +37,7 @@ * There is no obligation of a winsys driver to use this library. And a pipe * driver should be completly agnostic about it. * - * \author Jos� Fonseca + * \author Jose Fonseca */ #ifndef PB_BUFFER_H_ @@ -46,6 +46,7 @@ #include "pipe/p_compiler.h" #include "pipe/p_debug.h" +#include "pipe/p_error.h" #include "pipe/p_state.h" #include "pipe/p_inlines.h" @@ -56,6 +57,8 @@ extern "C" { struct pb_vtbl; +struct pb_validate; + /** * Buffer description. @@ -104,6 +107,13 @@ struct pb_vtbl void (*unmap)( struct pb_buffer *buf ); + enum pipe_error (*validate)( struct pb_buffer *buf, + struct pb_validate *vl, + unsigned flags ); + + void (*fence)( struct pb_buffer *buf, + struct pipe_fence_handle *fence ); + /** * Get the base buffer and the offset. * @@ -118,6 +128,7 @@ struct pb_vtbl void (*get_base_buffer)( struct pb_buffer *buf, struct pb_buffer **base_buf, unsigned *offset ); + }; @@ -173,10 +184,33 @@ pb_get_base_buffer( struct pb_buffer *buf, offset = 0; return; } + assert(buf->vtbl->get_base_buffer); buf->vtbl->get_base_buffer(buf, base_buf, offset); } +static INLINE enum pipe_error +pb_validate(struct pb_buffer *buf, struct pb_validate *vl, unsigned flags) +{ + assert(buf); + if(!buf) + return PIPE_ERROR; + assert(buf->vtbl->validate); + return buf->vtbl->validate(buf, vl, flags); +} + + +static INLINE void +pb_fence(struct pb_buffer *buf, struct pipe_fence_handle *fence) +{ + assert(buf); + if(!buf) + return; + assert(buf->vtbl->fence); + buf->vtbl->fence(buf, fence); +} + + static INLINE void pb_destroy(struct pb_buffer *buf) { diff --git a/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.c b/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.c index 17b2781052..17300cb553 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 + * \author Jose Fonseca * \author Thomas Hellström */ @@ -59,13 +59,6 @@ */ #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 { @@ -97,6 +90,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 +103,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; } @@ -274,6 +268,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 +310,101 @@ 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; + } + + /* Allow concurrent GPU reads, but serialize GPU writes */ + if(fenced_buf->flags & PIPE_BUFFER_USAGE_GPU_READ_WRITE) { + if((fenced_buf->flags | flags) & PIPE_BUFFER_USAGE_GPU_WRITE) { + _fenced_buffer_finish(fenced_buf); + } + } + + 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->flags & PIPE_BUFFER_USAGE_GPU_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 pipe_winsys *winsys; + + fenced_buf = fenced_buffer(buf); + fenced_list = fenced_buf->list; + winsys = fenced_list->winsys; + + 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) { + winsys->fence_reference(winsys, &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 +415,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,52 +454,6 @@ 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) { diff --git a/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.h b/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.h index 50d5891bdb..b15c676194 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.h +++ b/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.h @@ -44,7 +44,7 @@ * Between the handle's destruction, and the fence signalling, the buffer is * stored in a fenced buffer list. * - * \author José Fonseca + * \author Jose Fonseca */ #ifndef PB_BUFFER_FENCED_H_ @@ -70,14 +70,6 @@ struct pipe_fence_handle; struct fenced_buffer_list; -/** - * The fenced buffer's virtual function table. - * - * NOTE: Made public for debugging purposes. - */ -extern const struct pb_vtbl fenced_buffer_vtbl; - - /** * Create a fenced buffer list. * @@ -108,17 +100,6 @@ fenced_buffer_create(struct fenced_buffer_list *fenced, struct pb_buffer *buffer); -/** - * Set a buffer's fence. - * - * NOTE: Although it takes a generic pb_buffer argument, it will fail - * on everything but buffers returned by fenced_buffer_create. - */ -void -buffer_fence(struct pb_buffer *buf, - struct pipe_fence_handle *fence); - - #ifdef __cplusplus } #endif diff --git a/src/gallium/auxiliary/pipebuffer/pb_buffer_malloc.c b/src/gallium/auxiliary/pipebuffer/pb_buffer_malloc.c index 1bf22a2ec0..53f497cfb0 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_buffer_malloc.c +++ b/src/gallium/auxiliary/pipebuffer/pb_buffer_malloc.c @@ -81,6 +81,24 @@ malloc_buffer_unmap(struct pb_buffer *buf) } +static enum pipe_error +malloc_buffer_validate(struct pb_buffer *buf, + struct pb_validate *vl, + unsigned flags) +{ + assert(0); + return PIPE_ERROR; +} + + +static void +malloc_buffer_fence(struct pb_buffer *buf, + struct pipe_fence_handle *fence) +{ + assert(0); +} + + static void malloc_buffer_get_base_buffer(struct pb_buffer *buf, struct pb_buffer **base_buf, @@ -96,6 +114,8 @@ malloc_buffer_vtbl = { malloc_buffer_destroy, malloc_buffer_map, malloc_buffer_unmap, + malloc_buffer_validate, + malloc_buffer_fence, malloc_buffer_get_base_buffer }; diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr.h b/src/gallium/auxiliary/pipebuffer/pb_bufmgr.h index cafbee045a..8fe2704708 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr.h +++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr.h @@ -43,7 +43,7 @@ * - the fenced buffer manager, which will delay buffer destruction until the * the moment the card finishing processing it. * - * \author José Fonseca + * \author Jose Fonseca */ #ifndef PB_BUFMGR_H_ diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c index 8f118874ec..f57a7bffd7 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c +++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c @@ -29,7 +29,7 @@ * \file * Buffer cache. * - * \author José Fonseca + * \author Jose Fonseca * \author Thomas Hellström */ @@ -183,6 +183,25 @@ pb_cache_buffer_unmap(struct pb_buffer *_buf) } +static enum pipe_error +pb_cache_buffer_validate(struct pb_buffer *_buf, + struct pb_validate *vl, + unsigned flags) +{ + struct pb_cache_buffer *buf = pb_cache_buffer(_buf); + return pb_validate(buf->buffer, vl, flags); +} + + +static void +pb_cache_buffer_fence(struct pb_buffer *_buf, + struct pipe_fence_handle *fence) +{ + struct pb_cache_buffer *buf = pb_cache_buffer(_buf); + pb_fence(buf->buffer, fence); +} + + static void pb_cache_buffer_get_base_buffer(struct pb_buffer *_buf, struct pb_buffer **base_buf, @@ -198,6 +217,8 @@ pb_cache_buffer_vtbl = { pb_cache_buffer_destroy, pb_cache_buffer_map, pb_cache_buffer_unmap, + pb_cache_buffer_validate, + pb_cache_buffer_fence, pb_cache_buffer_get_base_buffer }; diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_debug.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_debug.c index 1675e6e182..62639fe1c8 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_debug.c +++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_debug.c @@ -29,7 +29,7 @@ * \file * Debug buffer manager to detect buffer under- and overflows. * - * \author José Fonseca + * \author Jose Fonseca */ @@ -255,11 +255,35 @@ pb_debug_buffer_get_base_buffer(struct pb_buffer *_buf, } +static enum pipe_error +pb_debug_buffer_validate(struct pb_buffer *_buf, + struct pb_validate *vl, + unsigned flags) +{ + struct pb_debug_buffer *buf = pb_debug_buffer(_buf); + + pb_debug_buffer_check(buf); + + return pb_validate(buf->buffer, vl, flags); +} + + +static void +pb_debug_buffer_fence(struct pb_buffer *_buf, + struct pipe_fence_handle *fence) +{ + struct pb_debug_buffer *buf = pb_debug_buffer(_buf); + pb_fence(buf->buffer, fence); +} + + const struct pb_vtbl pb_debug_buffer_vtbl = { pb_debug_buffer_destroy, pb_debug_buffer_map, pb_debug_buffer_unmap, + pb_debug_buffer_validate, + pb_debug_buffer_fence, pb_debug_buffer_get_base_buffer }; diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_fenced.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_fenced.c index 633ee70a75..f8fd2cd531 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_fenced.c +++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_fenced.c @@ -30,7 +30,7 @@ * \file * A buffer manager that wraps buffers in fenced buffers. * - * \author José Fonseca + * \author Jose Fonseca */ diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_mm.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_mm.c index fe80ca30ee..607f10bc73 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_mm.c +++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_mm.c @@ -29,7 +29,7 @@ * \file * Buffer manager using the old texture memory manager. * - * \author José Fonseca + * \author Jose Fonseca */ @@ -124,6 +124,27 @@ mm_buffer_unmap(struct pb_buffer *buf) } +static enum pipe_error +mm_buffer_validate(struct pb_buffer *buf, + struct pb_validate *vl, + unsigned flags) +{ + struct mm_buffer *mm_buf = mm_buffer(buf); + struct mm_pb_manager *mm = mm_buf->mgr; + return pb_validate(mm->buffer, vl, flags); +} + + +static void +mm_buffer_fence(struct pb_buffer *buf, + struct pipe_fence_handle *fence) +{ + struct mm_buffer *mm_buf = mm_buffer(buf); + struct mm_pb_manager *mm = mm_buf->mgr; + pb_fence(mm->buffer, fence); +} + + static void mm_buffer_get_base_buffer(struct pb_buffer *buf, struct pb_buffer **base_buf, @@ -141,6 +162,8 @@ mm_buffer_vtbl = { mm_buffer_destroy, mm_buffer_map, mm_buffer_unmap, + mm_buffer_validate, + mm_buffer_fence, mm_buffer_get_base_buffer }; diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_pool.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_pool.c index 61ac291ed7..a6ff37653e 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_pool.c +++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_pool.c @@ -30,7 +30,7 @@ * \file * Batch buffer pool management. * - * \author José Fonseca + * \author Jose Fonseca * \author Thomas Hellström */ @@ -138,6 +138,27 @@ pool_buffer_unmap(struct pb_buffer *buf) } +static enum pipe_error +pool_buffer_validate(struct pb_buffer *buf, + struct pb_validate *vl, + unsigned flags) +{ + struct pool_buffer *pool_buf = pool_buffer(buf); + struct pool_pb_manager *pool = pool_buf->mgr; + return pb_validate(pool->buffer, vl, flags); +} + + +static void +pool_buffer_fence(struct pb_buffer *buf, + struct pipe_fence_handle *fence) +{ + struct pool_buffer *pool_buf = pool_buffer(buf); + struct pool_pb_manager *pool = pool_buf->mgr; + pb_fence(pool->buffer, fence); +} + + static void pool_buffer_get_base_buffer(struct pb_buffer *buf, struct pb_buffer **base_buf, @@ -155,6 +176,8 @@ pool_buffer_vtbl = { pool_buffer_destroy, pool_buffer_map, pool_buffer_unmap, + pool_buffer_validate, + pool_buffer_fence, pool_buffer_get_base_buffer }; diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_slab.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_slab.c index 2a80154920..9b9fedccb4 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_slab.c +++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_slab.c @@ -248,6 +248,25 @@ pb_slab_buffer_unmap(struct pb_buffer *_buf) } +static enum pipe_error +pb_slab_buffer_validate(struct pb_buffer *_buf, + struct pb_validate *vl, + unsigned flags) +{ + struct pb_slab_buffer *buf = pb_slab_buffer(_buf); + return pb_validate(buf->slab->bo, vl, flags); +} + + +static void +pb_slab_buffer_fence(struct pb_buffer *_buf, + struct pipe_fence_handle *fence) +{ + struct pb_slab_buffer *buf = pb_slab_buffer(_buf); + pb_fence(buf->slab->bo, fence); +} + + static void pb_slab_buffer_get_base_buffer(struct pb_buffer *_buf, struct pb_buffer **base_buf, @@ -264,6 +283,8 @@ pb_slab_buffer_vtbl = { pb_slab_buffer_destroy, pb_slab_buffer_map, pb_slab_buffer_unmap, + pb_slab_buffer_validate, + pb_slab_buffer_fence, pb_slab_buffer_get_base_buffer }; diff --git a/src/gallium/auxiliary/pipebuffer/pb_validate.c b/src/gallium/auxiliary/pipebuffer/pb_validate.c index 1e54fc39d4..726ae1688e 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_validate.c +++ b/src/gallium/auxiliary/pipebuffer/pb_validate.c @@ -46,9 +46,16 @@ #define PB_VALIDATE_INITIAL_SIZE 1 /* 512 */ +struct pb_validate_entry +{ + struct pb_buffer *buf; + unsigned flags; +}; + + struct pb_validate { - struct pb_buffer **buffers; + struct pb_validate_entry *entries; unsigned used; unsigned size; }; @@ -56,54 +63,87 @@ struct pb_validate enum pipe_error pb_validate_add_buffer(struct pb_validate *vl, - struct pb_buffer *buf) + struct pb_buffer *buf, + unsigned flags) { assert(buf); if(!buf) return PIPE_ERROR; + assert(flags & PIPE_BUFFER_USAGE_GPU_READ_WRITE); + assert(!(flags & ~PIPE_BUFFER_USAGE_GPU_READ_WRITE)); + flags &= PIPE_BUFFER_USAGE_GPU_READ_WRITE; + /* We only need to store one reference for each buffer, so avoid storing - * consecutive references for the same buffer. It might not be the more - * common pasttern, but it is easy to implement. + * consecutive references for the same buffer. It might not be the most + * common pattern, but it is easy to implement. */ - if(vl->used && vl->buffers[vl->used - 1] == buf) { + if(vl->used && vl->entries[vl->used - 1].buf == buf) { + vl->entries[vl->used - 1].flags |= flags; return PIPE_OK; } /* Grow the table */ if(vl->used == vl->size) { unsigned new_size; - struct pb_buffer **new_buffers; + struct pb_validate_entry *new_entries; new_size = vl->size * 2; if(!new_size) return PIPE_ERROR_OUT_OF_MEMORY; - new_buffers = (struct pb_buffer **)REALLOC(vl->buffers, - vl->size*sizeof(struct pb_buffer *), - new_size*sizeof(struct pb_buffer *)); - if(!new_buffers) + new_entries = (struct pb_validate_entry *)REALLOC(vl->entries, + vl->size*sizeof(struct pb_validate_entry), + new_size*sizeof(struct pb_validate_entry)); + if(!new_entries) return PIPE_ERROR_OUT_OF_MEMORY; - memset(new_buffers + vl->size, 0, (new_size - vl->size)*sizeof(struct pb_buffer *)); + memset(new_entries + vl->size, 0, (new_size - vl->size)*sizeof(struct pb_validate_entry)); vl->size = new_size; - vl->buffers = new_buffers; + vl->entries = new_entries; } - assert(!vl->buffers[vl->used]); - pb_reference(&vl->buffers[vl->used], buf); + assert(!vl->entries[vl->used].buf); + pb_reference(&vl->entries[vl->used].buf, buf); + vl->entries[vl->used].flags = flags; ++vl->used; return PIPE_OK; } +enum pipe_error +pb_validate_foreach(struct pb_validate *vl, + enum pipe_error (*callback)(struct pb_buffer *buf, void *data), + void *data) +{ + unsigned i; + for(i = 0; i < vl->used; ++i) { + enum pipe_error ret; + ret = callback(vl->entries[i].buf, data); + if(ret != PIPE_OK) + return ret; + } + return PIPE_OK; +} + + enum pipe_error pb_validate_validate(struct pb_validate *vl) { - /* FIXME: go through each buffer, ensure its not mapped, its address is - * available -- requires a new pb_buffer interface */ + unsigned i; + + for(i = 0; i < vl->used; ++i) { + enum pipe_error ret; + ret = pb_validate(vl->entries[i].buf, vl, vl->entries[i].flags); + if(ret != PIPE_OK) { + while(i--) + pb_validate(vl->entries[i].buf, NULL, 0); + return ret; + } + } + return PIPE_OK; } @@ -114,8 +154,8 @@ pb_validate_fence(struct pb_validate *vl, { unsigned i; for(i = 0; i < vl->used; ++i) { - buffer_fence(vl->buffers[i], fence); - pb_reference(&vl->buffers[i], NULL); + pb_fence(vl->entries[i].buf, fence); + pb_reference(&vl->entries[i].buf, NULL); } vl->used = 0; } @@ -126,8 +166,8 @@ pb_validate_destroy(struct pb_validate *vl) { unsigned i; for(i = 0; i < vl->used; ++i) - pb_reference(&vl->buffers[i], NULL); - FREE(vl->buffers); + pb_reference(&vl->entries[i].buf, NULL); + FREE(vl->entries); FREE(vl); } @@ -142,8 +182,8 @@ pb_validate_create() return NULL; vl->size = PB_VALIDATE_INITIAL_SIZE; - vl->buffers = (struct pb_buffer **)CALLOC(vl->size, sizeof(struct pb_buffer *)); - if(!vl->buffers) { + vl->entries = (struct pb_validate_entry *)CALLOC(vl->size, sizeof(struct pb_buffer *)); + if(!vl->entries) { FREE(vl); return NULL; } diff --git a/src/gallium/auxiliary/pipebuffer/pb_validate.h b/src/gallium/auxiliary/pipebuffer/pb_validate.h index 3db1d5330b..dfb84df1ce 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_validate.h +++ b/src/gallium/auxiliary/pipebuffer/pb_validate.h @@ -58,7 +58,13 @@ struct pb_validate; enum pipe_error pb_validate_add_buffer(struct pb_validate *vl, - struct pb_buffer *buf); + struct pb_buffer *buf, + unsigned flags); + +enum pipe_error +pb_validate_foreach(struct pb_validate *vl, + enum pipe_error (*callback)(struct pb_buffer *buf, void *data), + void *data); /** * Validate all buffers for hardware access. @@ -71,7 +77,7 @@ pb_validate_validate(struct pb_validate *vl); /** * Fence all buffers and clear the list. * - * Should be called right before issuing commands to the hardware. + * Should be called right after issuing commands to the hardware. */ void pb_validate_fence(struct pb_validate *vl, diff --git a/src/gallium/auxiliary/pipebuffer/pb_winsys.c b/src/gallium/auxiliary/pipebuffer/pb_winsys.c index 28d137dbc4..45a883e532 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_winsys.c +++ b/src/gallium/auxiliary/pipebuffer/pb_winsys.c @@ -30,7 +30,7 @@ * Implementation of client buffer (also designated as "user buffers"), which * are just state-tracker owned data masqueraded as buffers. * - * \author José Fonseca + * \author Jose Fonseca */ @@ -91,6 +91,24 @@ pb_user_buffer_unmap(struct pb_buffer *buf) } +static enum pipe_error +pb_user_buffer_validate(struct pb_buffer *buf, + struct pb_validate *vl, + unsigned flags) +{ + assert(0); + return PIPE_ERROR; +} + + +static void +pb_user_buffer_fence(struct pb_buffer *buf, + struct pipe_fence_handle *fence) +{ + assert(0); +} + + static void pb_user_buffer_get_base_buffer(struct pb_buffer *buf, struct pb_buffer **base_buf, @@ -106,6 +124,8 @@ pb_user_buffer_vtbl = { pb_user_buffer_destroy, pb_user_buffer_map, pb_user_buffer_unmap, + pb_user_buffer_validate, + pb_user_buffer_fence, pb_user_buffer_get_base_buffer }; -- cgit v1.2.3 From aef455c4a7bbd7df97a6444ae332cb5fb976e627 Mon Sep 17 00:00:00 2001 From: Keith Whitwell Date: Fri, 12 Dec 2008 12:05:39 +0000 Subject: Revert "pipebuffer: Implement proper buffer validation." This reverts commit a6d866f72c88d48d2bcfb3e3c882fdb639b5a8ce. --- src/gallium/auxiliary/pipebuffer/pb_buffer.h | 36 +---- .../auxiliary/pipebuffer/pb_buffer_fenced.c | 158 ++++++++------------- .../auxiliary/pipebuffer/pb_buffer_fenced.h | 21 ++- .../auxiliary/pipebuffer/pb_buffer_malloc.c | 20 --- src/gallium/auxiliary/pipebuffer/pb_bufmgr.h | 2 +- src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c | 23 +-- src/gallium/auxiliary/pipebuffer/pb_bufmgr_debug.c | 26 +--- .../auxiliary/pipebuffer/pb_bufmgr_fenced.c | 2 +- src/gallium/auxiliary/pipebuffer/pb_bufmgr_mm.c | 25 +--- src/gallium/auxiliary/pipebuffer/pb_bufmgr_pool.c | 25 +--- src/gallium/auxiliary/pipebuffer/pb_bufmgr_slab.c | 21 --- src/gallium/auxiliary/pipebuffer/pb_validate.c | 84 +++-------- src/gallium/auxiliary/pipebuffer/pb_validate.h | 10 +- src/gallium/auxiliary/pipebuffer/pb_winsys.c | 22 +-- 14 files changed, 108 insertions(+), 367 deletions(-) (limited to 'src/gallium/auxiliary/pipebuffer/pb_validate.h') diff --git a/src/gallium/auxiliary/pipebuffer/pb_buffer.h b/src/gallium/auxiliary/pipebuffer/pb_buffer.h index c9570d7be2..8505d333bd 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_buffer.h +++ b/src/gallium/auxiliary/pipebuffer/pb_buffer.h @@ -37,7 +37,7 @@ * There is no obligation of a winsys driver to use this library. And a pipe * driver should be completly agnostic about it. * - * \author Jose Fonseca + * \author Jos� Fonseca */ #ifndef PB_BUFFER_H_ @@ -46,7 +46,6 @@ #include "pipe/p_compiler.h" #include "pipe/p_debug.h" -#include "pipe/p_error.h" #include "pipe/p_state.h" #include "pipe/p_inlines.h" @@ -57,8 +56,6 @@ extern "C" { struct pb_vtbl; -struct pb_validate; - /** * Buffer description. @@ -107,13 +104,6 @@ struct pb_vtbl void (*unmap)( struct pb_buffer *buf ); - enum pipe_error (*validate)( struct pb_buffer *buf, - struct pb_validate *vl, - unsigned flags ); - - void (*fence)( struct pb_buffer *buf, - struct pipe_fence_handle *fence ); - /** * Get the base buffer and the offset. * @@ -128,7 +118,6 @@ struct pb_vtbl void (*get_base_buffer)( struct pb_buffer *buf, struct pb_buffer **base_buf, unsigned *offset ); - }; @@ -184,33 +173,10 @@ pb_get_base_buffer( struct pb_buffer *buf, offset = 0; return; } - assert(buf->vtbl->get_base_buffer); buf->vtbl->get_base_buffer(buf, base_buf, offset); } -static INLINE enum pipe_error -pb_validate(struct pb_buffer *buf, struct pb_validate *vl, unsigned flags) -{ - assert(buf); - if(!buf) - return PIPE_ERROR; - assert(buf->vtbl->validate); - return buf->vtbl->validate(buf, vl, flags); -} - - -static INLINE void -pb_fence(struct pb_buffer *buf, struct pipe_fence_handle *fence) -{ - assert(buf); - if(!buf) - return; - assert(buf->vtbl->fence); - buf->vtbl->fence(buf, fence); -} - - static INLINE void pb_destroy(struct pb_buffer *buf) { diff --git a/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.c b/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.c index 17300cb553..17b2781052 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 Jose Fonseca + * \author José Fonseca * \author Thomas Hellström */ @@ -59,6 +59,13 @@ */ #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 { @@ -90,8 +97,6 @@ struct fenced_buffer unsigned flags; unsigned mapcount; - struct pb_validate *vl; - unsigned validation_flags; struct pipe_fence_handle *fence; struct list_head head; @@ -103,6 +108,7 @@ static INLINE struct fenced_buffer * fenced_buffer(struct pb_buffer *buf) { assert(buf); + assert(buf->vtbl == &fenced_buffer_vtbl); return (struct fenced_buffer *)buf; } @@ -268,7 +274,6 @@ 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; @@ -310,101 +315,6 @@ 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; - } - - /* Allow concurrent GPU reads, but serialize GPU writes */ - if(fenced_buf->flags & PIPE_BUFFER_USAGE_GPU_READ_WRITE) { - if((fenced_buf->flags | flags) & PIPE_BUFFER_USAGE_GPU_WRITE) { - _fenced_buffer_finish(fenced_buf); - } - } - - 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->flags & PIPE_BUFFER_USAGE_GPU_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 pipe_winsys *winsys; - - fenced_buf = fenced_buffer(buf); - fenced_list = fenced_buf->list; - winsys = fenced_list->winsys; - - 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) { - winsys->fence_reference(winsys, &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, @@ -415,13 +325,11 @@ fenced_buffer_get_base_buffer(struct pb_buffer *buf, } -static const struct pb_vtbl +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 }; @@ -454,6 +362,52 @@ 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) { diff --git a/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.h b/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.h index b15c676194..50d5891bdb 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.h +++ b/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.h @@ -44,7 +44,7 @@ * Between the handle's destruction, and the fence signalling, the buffer is * stored in a fenced buffer list. * - * \author Jose Fonseca + * \author José Fonseca */ #ifndef PB_BUFFER_FENCED_H_ @@ -70,6 +70,14 @@ struct pipe_fence_handle; struct fenced_buffer_list; +/** + * The fenced buffer's virtual function table. + * + * NOTE: Made public for debugging purposes. + */ +extern const struct pb_vtbl fenced_buffer_vtbl; + + /** * Create a fenced buffer list. * @@ -100,6 +108,17 @@ fenced_buffer_create(struct fenced_buffer_list *fenced, struct pb_buffer *buffer); +/** + * Set a buffer's fence. + * + * NOTE: Although it takes a generic pb_buffer argument, it will fail + * on everything but buffers returned by fenced_buffer_create. + */ +void +buffer_fence(struct pb_buffer *buf, + struct pipe_fence_handle *fence); + + #ifdef __cplusplus } #endif diff --git a/src/gallium/auxiliary/pipebuffer/pb_buffer_malloc.c b/src/gallium/auxiliary/pipebuffer/pb_buffer_malloc.c index 53f497cfb0..1bf22a2ec0 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_buffer_malloc.c +++ b/src/gallium/auxiliary/pipebuffer/pb_buffer_malloc.c @@ -81,24 +81,6 @@ malloc_buffer_unmap(struct pb_buffer *buf) } -static enum pipe_error -malloc_buffer_validate(struct pb_buffer *buf, - struct pb_validate *vl, - unsigned flags) -{ - assert(0); - return PIPE_ERROR; -} - - -static void -malloc_buffer_fence(struct pb_buffer *buf, - struct pipe_fence_handle *fence) -{ - assert(0); -} - - static void malloc_buffer_get_base_buffer(struct pb_buffer *buf, struct pb_buffer **base_buf, @@ -114,8 +96,6 @@ malloc_buffer_vtbl = { malloc_buffer_destroy, malloc_buffer_map, malloc_buffer_unmap, - malloc_buffer_validate, - malloc_buffer_fence, malloc_buffer_get_base_buffer }; diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr.h b/src/gallium/auxiliary/pipebuffer/pb_bufmgr.h index 8fe2704708..cafbee045a 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr.h +++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr.h @@ -43,7 +43,7 @@ * - the fenced buffer manager, which will delay buffer destruction until the * the moment the card finishing processing it. * - * \author Jose Fonseca + * \author José Fonseca */ #ifndef PB_BUFMGR_H_ diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c index f57a7bffd7..8f118874ec 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c +++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c @@ -29,7 +29,7 @@ * \file * Buffer cache. * - * \author Jose Fonseca + * \author José Fonseca * \author Thomas Hellström */ @@ -183,25 +183,6 @@ pb_cache_buffer_unmap(struct pb_buffer *_buf) } -static enum pipe_error -pb_cache_buffer_validate(struct pb_buffer *_buf, - struct pb_validate *vl, - unsigned flags) -{ - struct pb_cache_buffer *buf = pb_cache_buffer(_buf); - return pb_validate(buf->buffer, vl, flags); -} - - -static void -pb_cache_buffer_fence(struct pb_buffer *_buf, - struct pipe_fence_handle *fence) -{ - struct pb_cache_buffer *buf = pb_cache_buffer(_buf); - pb_fence(buf->buffer, fence); -} - - static void pb_cache_buffer_get_base_buffer(struct pb_buffer *_buf, struct pb_buffer **base_buf, @@ -217,8 +198,6 @@ pb_cache_buffer_vtbl = { pb_cache_buffer_destroy, pb_cache_buffer_map, pb_cache_buffer_unmap, - pb_cache_buffer_validate, - pb_cache_buffer_fence, pb_cache_buffer_get_base_buffer }; diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_debug.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_debug.c index 62639fe1c8..1675e6e182 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_debug.c +++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_debug.c @@ -29,7 +29,7 @@ * \file * Debug buffer manager to detect buffer under- and overflows. * - * \author Jose Fonseca + * \author José Fonseca */ @@ -255,35 +255,11 @@ pb_debug_buffer_get_base_buffer(struct pb_buffer *_buf, } -static enum pipe_error -pb_debug_buffer_validate(struct pb_buffer *_buf, - struct pb_validate *vl, - unsigned flags) -{ - struct pb_debug_buffer *buf = pb_debug_buffer(_buf); - - pb_debug_buffer_check(buf); - - return pb_validate(buf->buffer, vl, flags); -} - - -static void -pb_debug_buffer_fence(struct pb_buffer *_buf, - struct pipe_fence_handle *fence) -{ - struct pb_debug_buffer *buf = pb_debug_buffer(_buf); - pb_fence(buf->buffer, fence); -} - - const struct pb_vtbl pb_debug_buffer_vtbl = { pb_debug_buffer_destroy, pb_debug_buffer_map, pb_debug_buffer_unmap, - pb_debug_buffer_validate, - pb_debug_buffer_fence, pb_debug_buffer_get_base_buffer }; diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_fenced.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_fenced.c index f8fd2cd531..633ee70a75 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_fenced.c +++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_fenced.c @@ -30,7 +30,7 @@ * \file * A buffer manager that wraps buffers in fenced buffers. * - * \author Jose Fonseca + * \author José Fonseca */ diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_mm.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_mm.c index 607f10bc73..fe80ca30ee 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_mm.c +++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_mm.c @@ -29,7 +29,7 @@ * \file * Buffer manager using the old texture memory manager. * - * \author Jose Fonseca + * \author José Fonseca */ @@ -124,27 +124,6 @@ mm_buffer_unmap(struct pb_buffer *buf) } -static enum pipe_error -mm_buffer_validate(struct pb_buffer *buf, - struct pb_validate *vl, - unsigned flags) -{ - struct mm_buffer *mm_buf = mm_buffer(buf); - struct mm_pb_manager *mm = mm_buf->mgr; - return pb_validate(mm->buffer, vl, flags); -} - - -static void -mm_buffer_fence(struct pb_buffer *buf, - struct pipe_fence_handle *fence) -{ - struct mm_buffer *mm_buf = mm_buffer(buf); - struct mm_pb_manager *mm = mm_buf->mgr; - pb_fence(mm->buffer, fence); -} - - static void mm_buffer_get_base_buffer(struct pb_buffer *buf, struct pb_buffer **base_buf, @@ -162,8 +141,6 @@ mm_buffer_vtbl = { mm_buffer_destroy, mm_buffer_map, mm_buffer_unmap, - mm_buffer_validate, - mm_buffer_fence, mm_buffer_get_base_buffer }; diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_pool.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_pool.c index a6ff37653e..61ac291ed7 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_pool.c +++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_pool.c @@ -30,7 +30,7 @@ * \file * Batch buffer pool management. * - * \author Jose Fonseca + * \author José Fonseca * \author Thomas Hellström */ @@ -138,27 +138,6 @@ pool_buffer_unmap(struct pb_buffer *buf) } -static enum pipe_error -pool_buffer_validate(struct pb_buffer *buf, - struct pb_validate *vl, - unsigned flags) -{ - struct pool_buffer *pool_buf = pool_buffer(buf); - struct pool_pb_manager *pool = pool_buf->mgr; - return pb_validate(pool->buffer, vl, flags); -} - - -static void -pool_buffer_fence(struct pb_buffer *buf, - struct pipe_fence_handle *fence) -{ - struct pool_buffer *pool_buf = pool_buffer(buf); - struct pool_pb_manager *pool = pool_buf->mgr; - pb_fence(pool->buffer, fence); -} - - static void pool_buffer_get_base_buffer(struct pb_buffer *buf, struct pb_buffer **base_buf, @@ -176,8 +155,6 @@ pool_buffer_vtbl = { pool_buffer_destroy, pool_buffer_map, pool_buffer_unmap, - pool_buffer_validate, - pool_buffer_fence, pool_buffer_get_base_buffer }; diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_slab.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_slab.c index 9b9fedccb4..2a80154920 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_slab.c +++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_slab.c @@ -248,25 +248,6 @@ pb_slab_buffer_unmap(struct pb_buffer *_buf) } -static enum pipe_error -pb_slab_buffer_validate(struct pb_buffer *_buf, - struct pb_validate *vl, - unsigned flags) -{ - struct pb_slab_buffer *buf = pb_slab_buffer(_buf); - return pb_validate(buf->slab->bo, vl, flags); -} - - -static void -pb_slab_buffer_fence(struct pb_buffer *_buf, - struct pipe_fence_handle *fence) -{ - struct pb_slab_buffer *buf = pb_slab_buffer(_buf); - pb_fence(buf->slab->bo, fence); -} - - static void pb_slab_buffer_get_base_buffer(struct pb_buffer *_buf, struct pb_buffer **base_buf, @@ -283,8 +264,6 @@ pb_slab_buffer_vtbl = { pb_slab_buffer_destroy, pb_slab_buffer_map, pb_slab_buffer_unmap, - pb_slab_buffer_validate, - pb_slab_buffer_fence, pb_slab_buffer_get_base_buffer }; diff --git a/src/gallium/auxiliary/pipebuffer/pb_validate.c b/src/gallium/auxiliary/pipebuffer/pb_validate.c index 726ae1688e..1e54fc39d4 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_validate.c +++ b/src/gallium/auxiliary/pipebuffer/pb_validate.c @@ -46,16 +46,9 @@ #define PB_VALIDATE_INITIAL_SIZE 1 /* 512 */ -struct pb_validate_entry -{ - struct pb_buffer *buf; - unsigned flags; -}; - - struct pb_validate { - struct pb_validate_entry *entries; + struct pb_buffer **buffers; unsigned used; unsigned size; }; @@ -63,87 +56,54 @@ struct pb_validate enum pipe_error pb_validate_add_buffer(struct pb_validate *vl, - struct pb_buffer *buf, - unsigned flags) + struct pb_buffer *buf) { assert(buf); if(!buf) return PIPE_ERROR; - assert(flags & PIPE_BUFFER_USAGE_GPU_READ_WRITE); - assert(!(flags & ~PIPE_BUFFER_USAGE_GPU_READ_WRITE)); - flags &= PIPE_BUFFER_USAGE_GPU_READ_WRITE; - /* We only need to store one reference for each buffer, so avoid storing - * consecutive references for the same buffer. It might not be the most - * common pattern, but it is easy to implement. + * consecutive references for the same buffer. It might not be the more + * common pasttern, but it is easy to implement. */ - if(vl->used && vl->entries[vl->used - 1].buf == buf) { - vl->entries[vl->used - 1].flags |= flags; + if(vl->used && vl->buffers[vl->used - 1] == buf) { return PIPE_OK; } /* Grow the table */ if(vl->used == vl->size) { unsigned new_size; - struct pb_validate_entry *new_entries; + struct pb_buffer **new_buffers; new_size = vl->size * 2; if(!new_size) return PIPE_ERROR_OUT_OF_MEMORY; - new_entries = (struct pb_validate_entry *)REALLOC(vl->entries, - vl->size*sizeof(struct pb_validate_entry), - new_size*sizeof(struct pb_validate_entry)); - if(!new_entries) + new_buffers = (struct pb_buffer **)REALLOC(vl->buffers, + vl->size*sizeof(struct pb_buffer *), + new_size*sizeof(struct pb_buffer *)); + if(!new_buffers) return PIPE_ERROR_OUT_OF_MEMORY; - memset(new_entries + vl->size, 0, (new_size - vl->size)*sizeof(struct pb_validate_entry)); + memset(new_buffers + vl->size, 0, (new_size - vl->size)*sizeof(struct pb_buffer *)); vl->size = new_size; - vl->entries = new_entries; + vl->buffers = new_buffers; } - assert(!vl->entries[vl->used].buf); - pb_reference(&vl->entries[vl->used].buf, buf); - vl->entries[vl->used].flags = flags; + assert(!vl->buffers[vl->used]); + pb_reference(&vl->buffers[vl->used], buf); ++vl->used; return PIPE_OK; } -enum pipe_error -pb_validate_foreach(struct pb_validate *vl, - enum pipe_error (*callback)(struct pb_buffer *buf, void *data), - void *data) -{ - unsigned i; - for(i = 0; i < vl->used; ++i) { - enum pipe_error ret; - ret = callback(vl->entries[i].buf, data); - if(ret != PIPE_OK) - return ret; - } - return PIPE_OK; -} - - enum pipe_error pb_validate_validate(struct pb_validate *vl) { - unsigned i; - - for(i = 0; i < vl->used; ++i) { - enum pipe_error ret; - ret = pb_validate(vl->entries[i].buf, vl, vl->entries[i].flags); - if(ret != PIPE_OK) { - while(i--) - pb_validate(vl->entries[i].buf, NULL, 0); - return ret; - } - } - + /* FIXME: go through each buffer, ensure its not mapped, its address is + * available -- requires a new pb_buffer interface */ return PIPE_OK; } @@ -154,8 +114,8 @@ pb_validate_fence(struct pb_validate *vl, { unsigned i; for(i = 0; i < vl->used; ++i) { - pb_fence(vl->entries[i].buf, fence); - pb_reference(&vl->entries[i].buf, NULL); + buffer_fence(vl->buffers[i], fence); + pb_reference(&vl->buffers[i], NULL); } vl->used = 0; } @@ -166,8 +126,8 @@ pb_validate_destroy(struct pb_validate *vl) { unsigned i; for(i = 0; i < vl->used; ++i) - pb_reference(&vl->entries[i].buf, NULL); - FREE(vl->entries); + pb_reference(&vl->buffers[i], NULL); + FREE(vl->buffers); FREE(vl); } @@ -182,8 +142,8 @@ pb_validate_create() return NULL; vl->size = PB_VALIDATE_INITIAL_SIZE; - vl->entries = (struct pb_validate_entry *)CALLOC(vl->size, sizeof(struct pb_buffer *)); - if(!vl->entries) { + vl->buffers = (struct pb_buffer **)CALLOC(vl->size, sizeof(struct pb_buffer *)); + if(!vl->buffers) { FREE(vl); return NULL; } diff --git a/src/gallium/auxiliary/pipebuffer/pb_validate.h b/src/gallium/auxiliary/pipebuffer/pb_validate.h index dfb84df1ce..3db1d5330b 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_validate.h +++ b/src/gallium/auxiliary/pipebuffer/pb_validate.h @@ -58,13 +58,7 @@ struct pb_validate; enum pipe_error pb_validate_add_buffer(struct pb_validate *vl, - struct pb_buffer *buf, - unsigned flags); - -enum pipe_error -pb_validate_foreach(struct pb_validate *vl, - enum pipe_error (*callback)(struct pb_buffer *buf, void *data), - void *data); + struct pb_buffer *buf); /** * Validate all buffers for hardware access. @@ -77,7 +71,7 @@ pb_validate_validate(struct pb_validate *vl); /** * Fence all buffers and clear the list. * - * Should be called right after issuing commands to the hardware. + * Should be called right before issuing commands to the hardware. */ void pb_validate_fence(struct pb_validate *vl, diff --git a/src/gallium/auxiliary/pipebuffer/pb_winsys.c b/src/gallium/auxiliary/pipebuffer/pb_winsys.c index 45a883e532..28d137dbc4 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_winsys.c +++ b/src/gallium/auxiliary/pipebuffer/pb_winsys.c @@ -30,7 +30,7 @@ * Implementation of client buffer (also designated as "user buffers"), which * are just state-tracker owned data masqueraded as buffers. * - * \author Jose Fonseca + * \author José Fonseca */ @@ -91,24 +91,6 @@ pb_user_buffer_unmap(struct pb_buffer *buf) } -static enum pipe_error -pb_user_buffer_validate(struct pb_buffer *buf, - struct pb_validate *vl, - unsigned flags) -{ - assert(0); - return PIPE_ERROR; -} - - -static void -pb_user_buffer_fence(struct pb_buffer *buf, - struct pipe_fence_handle *fence) -{ - assert(0); -} - - static void pb_user_buffer_get_base_buffer(struct pb_buffer *buf, struct pb_buffer **base_buf, @@ -124,8 +106,6 @@ pb_user_buffer_vtbl = { pb_user_buffer_destroy, pb_user_buffer_map, pb_user_buffer_unmap, - pb_user_buffer_validate, - pb_user_buffer_fence, pb_user_buffer_get_base_buffer }; -- cgit v1.2.3 From e06474dbae6979177629fb6187331291ff230c65 Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Mon, 24 Nov 2008 13:59:06 +0900 Subject: pipebuffer: Implement proper buffer validation. --- src/gallium/auxiliary/pipebuffer/pb_buffer.h | 36 ++++- .../auxiliary/pipebuffer/pb_buffer_fenced.c | 150 +++++++++++++-------- .../auxiliary/pipebuffer/pb_buffer_fenced.h | 21 +-- .../auxiliary/pipebuffer/pb_buffer_malloc.c | 20 +++ src/gallium/auxiliary/pipebuffer/pb_bufmgr.h | 2 +- src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c | 23 +++- src/gallium/auxiliary/pipebuffer/pb_bufmgr_debug.c | 26 +++- .../auxiliary/pipebuffer/pb_bufmgr_fenced.c | 2 +- src/gallium/auxiliary/pipebuffer/pb_bufmgr_mm.c | 25 +++- src/gallium/auxiliary/pipebuffer/pb_bufmgr_pool.c | 25 +++- src/gallium/auxiliary/pipebuffer/pb_bufmgr_slab.c | 21 +++ src/gallium/auxiliary/pipebuffer/pb_validate.c | 84 +++++++++--- src/gallium/auxiliary/pipebuffer/pb_validate.h | 10 +- src/gallium/auxiliary/pipebuffer/pb_winsys.c | 22 ++- 14 files changed, 359 insertions(+), 108 deletions(-) (limited to 'src/gallium/auxiliary/pipebuffer/pb_validate.h') diff --git a/src/gallium/auxiliary/pipebuffer/pb_buffer.h b/src/gallium/auxiliary/pipebuffer/pb_buffer.h index fb0ba15948..7cba5fa441 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_buffer.h +++ b/src/gallium/auxiliary/pipebuffer/pb_buffer.h @@ -37,7 +37,7 @@ * There is no obligation of a winsys driver to use this library. And a pipe * driver should be completly agnostic about it. * - * \author Jos� Fonseca + * \author Jose Fonseca */ #ifndef PB_BUFFER_H_ @@ -46,6 +46,7 @@ #include "pipe/p_compiler.h" #include "pipe/p_debug.h" +#include "pipe/p_error.h" #include "pipe/p_state.h" #include "pipe/p_inlines.h" @@ -56,6 +57,8 @@ extern "C" { struct pb_vtbl; +struct pb_validate; + /** * Buffer description. @@ -104,6 +107,13 @@ struct pb_vtbl void (*unmap)( struct pb_buffer *buf ); + enum pipe_error (*validate)( struct pb_buffer *buf, + struct pb_validate *vl, + unsigned flags ); + + void (*fence)( struct pb_buffer *buf, + struct pipe_fence_handle *fence ); + /** * Get the base buffer and the offset. * @@ -118,6 +128,7 @@ struct pb_vtbl void (*get_base_buffer)( struct pb_buffer *buf, struct pb_buffer **base_buf, unsigned *offset ); + }; @@ -176,12 +187,35 @@ pb_get_base_buffer( struct pb_buffer *buf, return; } assert(buf->base.refcount > 0); + assert(buf->vtbl->get_base_buffer); buf->vtbl->get_base_buffer(buf, base_buf, offset); assert(*base_buf); assert(*offset < (*base_buf)->base.size); } +static INLINE enum pipe_error +pb_validate(struct pb_buffer *buf, struct pb_validate *vl, unsigned flags) +{ + assert(buf); + if(!buf) + return PIPE_ERROR; + assert(buf->vtbl->validate); + return buf->vtbl->validate(buf, vl, flags); +} + + +static INLINE void +pb_fence(struct pb_buffer *buf, struct pipe_fence_handle *fence) +{ + assert(buf); + if(!buf) + return; + assert(buf->vtbl->fence); + buf->vtbl->fence(buf, fence); +} + + static INLINE void pb_destroy(struct pb_buffer *buf) { diff --git a/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.c b/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.c index 17b2781052..aa4b096274 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 + * \author Jose Fonseca * \author Thomas Hellström */ @@ -59,13 +59,6 @@ */ #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 { @@ -97,6 +90,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 +103,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; } @@ -274,6 +268,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 +310,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 pipe_winsys *winsys; + + fenced_buf = fenced_buffer(buf); + fenced_list = fenced_buf->list; + winsys = fenced_list->winsys; + + 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) { + winsys->fence_reference(winsys, &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 +407,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,52 +446,6 @@ 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) { diff --git a/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.h b/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.h index 50d5891bdb..b15c676194 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.h +++ b/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.h @@ -44,7 +44,7 @@ * Between the handle's destruction, and the fence signalling, the buffer is * stored in a fenced buffer list. * - * \author José Fonseca + * \author Jose Fonseca */ #ifndef PB_BUFFER_FENCED_H_ @@ -70,14 +70,6 @@ struct pipe_fence_handle; struct fenced_buffer_list; -/** - * The fenced buffer's virtual function table. - * - * NOTE: Made public for debugging purposes. - */ -extern const struct pb_vtbl fenced_buffer_vtbl; - - /** * Create a fenced buffer list. * @@ -108,17 +100,6 @@ fenced_buffer_create(struct fenced_buffer_list *fenced, struct pb_buffer *buffer); -/** - * Set a buffer's fence. - * - * NOTE: Although it takes a generic pb_buffer argument, it will fail - * on everything but buffers returned by fenced_buffer_create. - */ -void -buffer_fence(struct pb_buffer *buf, - struct pipe_fence_handle *fence); - - #ifdef __cplusplus } #endif diff --git a/src/gallium/auxiliary/pipebuffer/pb_buffer_malloc.c b/src/gallium/auxiliary/pipebuffer/pb_buffer_malloc.c index 1bf22a2ec0..53f497cfb0 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_buffer_malloc.c +++ b/src/gallium/auxiliary/pipebuffer/pb_buffer_malloc.c @@ -81,6 +81,24 @@ malloc_buffer_unmap(struct pb_buffer *buf) } +static enum pipe_error +malloc_buffer_validate(struct pb_buffer *buf, + struct pb_validate *vl, + unsigned flags) +{ + assert(0); + return PIPE_ERROR; +} + + +static void +malloc_buffer_fence(struct pb_buffer *buf, + struct pipe_fence_handle *fence) +{ + assert(0); +} + + static void malloc_buffer_get_base_buffer(struct pb_buffer *buf, struct pb_buffer **base_buf, @@ -96,6 +114,8 @@ malloc_buffer_vtbl = { malloc_buffer_destroy, malloc_buffer_map, malloc_buffer_unmap, + malloc_buffer_validate, + malloc_buffer_fence, malloc_buffer_get_base_buffer }; diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr.h b/src/gallium/auxiliary/pipebuffer/pb_bufmgr.h index cafbee045a..8fe2704708 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr.h +++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr.h @@ -43,7 +43,7 @@ * - the fenced buffer manager, which will delay buffer destruction until the * the moment the card finishing processing it. * - * \author José Fonseca + * \author Jose Fonseca */ #ifndef PB_BUFMGR_H_ diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c index 8f118874ec..f57a7bffd7 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c +++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c @@ -29,7 +29,7 @@ * \file * Buffer cache. * - * \author José Fonseca + * \author Jose Fonseca * \author Thomas Hellström */ @@ -183,6 +183,25 @@ pb_cache_buffer_unmap(struct pb_buffer *_buf) } +static enum pipe_error +pb_cache_buffer_validate(struct pb_buffer *_buf, + struct pb_validate *vl, + unsigned flags) +{ + struct pb_cache_buffer *buf = pb_cache_buffer(_buf); + return pb_validate(buf->buffer, vl, flags); +} + + +static void +pb_cache_buffer_fence(struct pb_buffer *_buf, + struct pipe_fence_handle *fence) +{ + struct pb_cache_buffer *buf = pb_cache_buffer(_buf); + pb_fence(buf->buffer, fence); +} + + static void pb_cache_buffer_get_base_buffer(struct pb_buffer *_buf, struct pb_buffer **base_buf, @@ -198,6 +217,8 @@ pb_cache_buffer_vtbl = { pb_cache_buffer_destroy, pb_cache_buffer_map, pb_cache_buffer_unmap, + pb_cache_buffer_validate, + pb_cache_buffer_fence, pb_cache_buffer_get_base_buffer }; diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_debug.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_debug.c index 1675e6e182..62639fe1c8 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_debug.c +++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_debug.c @@ -29,7 +29,7 @@ * \file * Debug buffer manager to detect buffer under- and overflows. * - * \author José Fonseca + * \author Jose Fonseca */ @@ -255,11 +255,35 @@ pb_debug_buffer_get_base_buffer(struct pb_buffer *_buf, } +static enum pipe_error +pb_debug_buffer_validate(struct pb_buffer *_buf, + struct pb_validate *vl, + unsigned flags) +{ + struct pb_debug_buffer *buf = pb_debug_buffer(_buf); + + pb_debug_buffer_check(buf); + + return pb_validate(buf->buffer, vl, flags); +} + + +static void +pb_debug_buffer_fence(struct pb_buffer *_buf, + struct pipe_fence_handle *fence) +{ + struct pb_debug_buffer *buf = pb_debug_buffer(_buf); + pb_fence(buf->buffer, fence); +} + + const struct pb_vtbl pb_debug_buffer_vtbl = { pb_debug_buffer_destroy, pb_debug_buffer_map, pb_debug_buffer_unmap, + pb_debug_buffer_validate, + pb_debug_buffer_fence, pb_debug_buffer_get_base_buffer }; diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_fenced.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_fenced.c index e2594ea236..513ed28ca6 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_fenced.c +++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_fenced.c @@ -30,7 +30,7 @@ * \file * A buffer manager that wraps buffers in fenced buffers. * - * \author José Fonseca + * \author Jose Fonseca */ diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_mm.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_mm.c index d4434c6962..2f5a5d8ea0 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_mm.c +++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_mm.c @@ -29,7 +29,7 @@ * \file * Buffer manager using the old texture memory manager. * - * \author José Fonseca + * \author Jose Fonseca */ @@ -124,6 +124,27 @@ mm_buffer_unmap(struct pb_buffer *buf) } +static enum pipe_error +mm_buffer_validate(struct pb_buffer *buf, + struct pb_validate *vl, + unsigned flags) +{ + struct mm_buffer *mm_buf = mm_buffer(buf); + struct mm_pb_manager *mm = mm_buf->mgr; + return pb_validate(mm->buffer, vl, flags); +} + + +static void +mm_buffer_fence(struct pb_buffer *buf, + struct pipe_fence_handle *fence) +{ + struct mm_buffer *mm_buf = mm_buffer(buf); + struct mm_pb_manager *mm = mm_buf->mgr; + pb_fence(mm->buffer, fence); +} + + static void mm_buffer_get_base_buffer(struct pb_buffer *buf, struct pb_buffer **base_buf, @@ -141,6 +162,8 @@ mm_buffer_vtbl = { mm_buffer_destroy, mm_buffer_map, mm_buffer_unmap, + mm_buffer_validate, + mm_buffer_fence, mm_buffer_get_base_buffer }; diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_pool.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_pool.c index 61ac291ed7..a6ff37653e 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_pool.c +++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_pool.c @@ -30,7 +30,7 @@ * \file * Batch buffer pool management. * - * \author José Fonseca + * \author Jose Fonseca * \author Thomas Hellström */ @@ -138,6 +138,27 @@ pool_buffer_unmap(struct pb_buffer *buf) } +static enum pipe_error +pool_buffer_validate(struct pb_buffer *buf, + struct pb_validate *vl, + unsigned flags) +{ + struct pool_buffer *pool_buf = pool_buffer(buf); + struct pool_pb_manager *pool = pool_buf->mgr; + return pb_validate(pool->buffer, vl, flags); +} + + +static void +pool_buffer_fence(struct pb_buffer *buf, + struct pipe_fence_handle *fence) +{ + struct pool_buffer *pool_buf = pool_buffer(buf); + struct pool_pb_manager *pool = pool_buf->mgr; + pb_fence(pool->buffer, fence); +} + + static void pool_buffer_get_base_buffer(struct pb_buffer *buf, struct pb_buffer **base_buf, @@ -155,6 +176,8 @@ pool_buffer_vtbl = { pool_buffer_destroy, pool_buffer_map, pool_buffer_unmap, + pool_buffer_validate, + pool_buffer_fence, pool_buffer_get_base_buffer }; diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_slab.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_slab.c index 2a80154920..9b9fedccb4 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_slab.c +++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_slab.c @@ -248,6 +248,25 @@ pb_slab_buffer_unmap(struct pb_buffer *_buf) } +static enum pipe_error +pb_slab_buffer_validate(struct pb_buffer *_buf, + struct pb_validate *vl, + unsigned flags) +{ + struct pb_slab_buffer *buf = pb_slab_buffer(_buf); + return pb_validate(buf->slab->bo, vl, flags); +} + + +static void +pb_slab_buffer_fence(struct pb_buffer *_buf, + struct pipe_fence_handle *fence) +{ + struct pb_slab_buffer *buf = pb_slab_buffer(_buf); + pb_fence(buf->slab->bo, fence); +} + + static void pb_slab_buffer_get_base_buffer(struct pb_buffer *_buf, struct pb_buffer **base_buf, @@ -264,6 +283,8 @@ pb_slab_buffer_vtbl = { pb_slab_buffer_destroy, pb_slab_buffer_map, pb_slab_buffer_unmap, + pb_slab_buffer_validate, + pb_slab_buffer_fence, pb_slab_buffer_get_base_buffer }; diff --git a/src/gallium/auxiliary/pipebuffer/pb_validate.c b/src/gallium/auxiliary/pipebuffer/pb_validate.c index 1e54fc39d4..94532bb4ce 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_validate.c +++ b/src/gallium/auxiliary/pipebuffer/pb_validate.c @@ -46,9 +46,16 @@ #define PB_VALIDATE_INITIAL_SIZE 1 /* 512 */ +struct pb_validate_entry +{ + struct pb_buffer *buf; + unsigned flags; +}; + + struct pb_validate { - struct pb_buffer **buffers; + struct pb_validate_entry *entries; unsigned used; unsigned size; }; @@ -56,54 +63,87 @@ struct pb_validate enum pipe_error pb_validate_add_buffer(struct pb_validate *vl, - struct pb_buffer *buf) + struct pb_buffer *buf, + unsigned flags) { assert(buf); if(!buf) return PIPE_ERROR; + assert(flags & PIPE_BUFFER_USAGE_GPU_READ_WRITE); + assert(!(flags & ~PIPE_BUFFER_USAGE_GPU_READ_WRITE)); + flags &= PIPE_BUFFER_USAGE_GPU_READ_WRITE; + /* We only need to store one reference for each buffer, so avoid storing - * consecutive references for the same buffer. It might not be the more - * common pasttern, but it is easy to implement. + * consecutive references for the same buffer. It might not be the most + * common pattern, but it is easy to implement. */ - if(vl->used && vl->buffers[vl->used - 1] == buf) { + if(vl->used && vl->entries[vl->used - 1].buf == buf) { + vl->entries[vl->used - 1].flags |= flags; return PIPE_OK; } /* Grow the table */ if(vl->used == vl->size) { unsigned new_size; - struct pb_buffer **new_buffers; + struct pb_validate_entry *new_entries; new_size = vl->size * 2; if(!new_size) return PIPE_ERROR_OUT_OF_MEMORY; - new_buffers = (struct pb_buffer **)REALLOC(vl->buffers, - vl->size*sizeof(struct pb_buffer *), - new_size*sizeof(struct pb_buffer *)); - if(!new_buffers) + new_entries = (struct pb_validate_entry *)REALLOC(vl->entries, + vl->size*sizeof(struct pb_validate_entry), + new_size*sizeof(struct pb_validate_entry)); + if(!new_entries) return PIPE_ERROR_OUT_OF_MEMORY; - memset(new_buffers + vl->size, 0, (new_size - vl->size)*sizeof(struct pb_buffer *)); + memset(new_entries + vl->size, 0, (new_size - vl->size)*sizeof(struct pb_validate_entry)); vl->size = new_size; - vl->buffers = new_buffers; + vl->entries = new_entries; } - assert(!vl->buffers[vl->used]); - pb_reference(&vl->buffers[vl->used], buf); + assert(!vl->entries[vl->used].buf); + pb_reference(&vl->entries[vl->used].buf, buf); + vl->entries[vl->used].flags = flags; ++vl->used; return PIPE_OK; } +enum pipe_error +pb_validate_foreach(struct pb_validate *vl, + enum pipe_error (*callback)(struct pb_buffer *buf, void *data), + void *data) +{ + unsigned i; + for(i = 0; i < vl->used; ++i) { + enum pipe_error ret; + ret = callback(vl->entries[i].buf, data); + if(ret != PIPE_OK) + return ret; + } + return PIPE_OK; +} + + enum pipe_error pb_validate_validate(struct pb_validate *vl) { - /* FIXME: go through each buffer, ensure its not mapped, its address is - * available -- requires a new pb_buffer interface */ + unsigned i; + + for(i = 0; i < vl->used; ++i) { + enum pipe_error ret; + ret = pb_validate(vl->entries[i].buf, vl, vl->entries[i].flags); + if(ret != PIPE_OK) { + while(i--) + pb_validate(vl->entries[i].buf, NULL, 0); + return ret; + } + } + return PIPE_OK; } @@ -114,8 +154,8 @@ pb_validate_fence(struct pb_validate *vl, { unsigned i; for(i = 0; i < vl->used; ++i) { - buffer_fence(vl->buffers[i], fence); - pb_reference(&vl->buffers[i], NULL); + pb_fence(vl->entries[i].buf, fence); + pb_reference(&vl->entries[i].buf, NULL); } vl->used = 0; } @@ -126,8 +166,8 @@ pb_validate_destroy(struct pb_validate *vl) { unsigned i; for(i = 0; i < vl->used; ++i) - pb_reference(&vl->buffers[i], NULL); - FREE(vl->buffers); + pb_reference(&vl->entries[i].buf, NULL); + FREE(vl->entries); FREE(vl); } @@ -142,8 +182,8 @@ pb_validate_create() return NULL; vl->size = PB_VALIDATE_INITIAL_SIZE; - vl->buffers = (struct pb_buffer **)CALLOC(vl->size, sizeof(struct pb_buffer *)); - if(!vl->buffers) { + vl->entries = (struct pb_validate_entry *)CALLOC(vl->size, sizeof(struct pb_validate_entry)); + if(!vl->entries) { FREE(vl); return NULL; } diff --git a/src/gallium/auxiliary/pipebuffer/pb_validate.h b/src/gallium/auxiliary/pipebuffer/pb_validate.h index 3db1d5330b..dfb84df1ce 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_validate.h +++ b/src/gallium/auxiliary/pipebuffer/pb_validate.h @@ -58,7 +58,13 @@ struct pb_validate; enum pipe_error pb_validate_add_buffer(struct pb_validate *vl, - struct pb_buffer *buf); + struct pb_buffer *buf, + unsigned flags); + +enum pipe_error +pb_validate_foreach(struct pb_validate *vl, + enum pipe_error (*callback)(struct pb_buffer *buf, void *data), + void *data); /** * Validate all buffers for hardware access. @@ -71,7 +77,7 @@ pb_validate_validate(struct pb_validate *vl); /** * Fence all buffers and clear the list. * - * Should be called right before issuing commands to the hardware. + * Should be called right after issuing commands to the hardware. */ void pb_validate_fence(struct pb_validate *vl, diff --git a/src/gallium/auxiliary/pipebuffer/pb_winsys.c b/src/gallium/auxiliary/pipebuffer/pb_winsys.c index e2f1008cc2..452835fdad 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_winsys.c +++ b/src/gallium/auxiliary/pipebuffer/pb_winsys.c @@ -30,7 +30,7 @@ * Implementation of client buffer (also designated as "user buffers"), which * are just state-tracker owned data masqueraded as buffers. * - * \author José Fonseca + * \author Jose Fonseca */ @@ -92,6 +92,24 @@ pb_user_buffer_unmap(struct pb_buffer *buf) } +static enum pipe_error +pb_user_buffer_validate(struct pb_buffer *buf, + struct pb_validate *vl, + unsigned flags) +{ + assert(0); + return PIPE_ERROR; +} + + +static void +pb_user_buffer_fence(struct pb_buffer *buf, + struct pipe_fence_handle *fence) +{ + assert(0); +} + + static void pb_user_buffer_get_base_buffer(struct pb_buffer *buf, struct pb_buffer **base_buf, @@ -107,6 +125,8 @@ pb_user_buffer_vtbl = { pb_user_buffer_destroy, pb_user_buffer_map, pb_user_buffer_unmap, + pb_user_buffer_validate, + pb_user_buffer_fence, pb_user_buffer_get_base_buffer }; -- cgit v1.2.3