Go to the source code of this file.
Data Structures | |
struct | fenced_buffer_list |
struct | fenced_buffer |
Wrapper around a pipe buffer which adds fencing and reference counting. More... | |
Defines | |
#define | SUPER(__derived) (&(__derived)->base) |
Convenience macro (type safe). | |
#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 ) |
Functions | |
static struct fenced_buffer * | fenced_buffer (struct pb_buffer *buf) |
static void | _fenced_buffer_add (struct fenced_buffer *fenced_buf) |
static void | _fenced_buffer_destroy (struct fenced_buffer *fenced_buf) |
Actually destroy the buffer. | |
static void | _fenced_buffer_remove (struct fenced_buffer_list *fenced_list, struct fenced_buffer *fenced_buf) |
static enum pipe_error | _fenced_buffer_finish (struct fenced_buffer *fenced_buf) |
static void | _fenced_buffer_list_check_free (struct fenced_buffer_list *fenced_list, int wait) |
Free as many fenced buffers from the list head as possible. | |
static void | fenced_buffer_destroy (struct pb_buffer *buf) |
static void * | fenced_buffer_map (struct pb_buffer *buf, unsigned flags) |
static void | fenced_buffer_unmap (struct pb_buffer *buf) |
static void | fenced_buffer_get_base_buffer (struct pb_buffer *buf, struct pb_buffer **base_buf, unsigned *offset) |
struct pb_buffer * | fenced_buffer_create (struct fenced_buffer_list *fenced_list, struct pb_buffer *buffer) |
Wrap a buffer in a fenced buffer. | |
void | buffer_fence (struct pb_buffer *buf, struct pipe_fence_handle *fence) |
Set a buffer's fence. | |
struct fenced_buffer_list * | fenced_buffer_list_create (struct pipe_winsys *winsys) |
Create a fenced buffer list. | |
void | fenced_buffer_list_check_free (struct fenced_buffer_list *fenced_list, int wait) |
Walk the fenced buffer list to check and free signalled buffers. | |
void | fenced_buffer_list_destroy (struct fenced_buffer_list *fenced_list) |
Variables | |
struct pb_vtbl | fenced_buffer_vtbl |
The fenced buffer's virtual function table. |
Definition in file pb_buffer_fenced.c.
#define PIPE_BUFFER_USAGE_CPU_READ_WRITE ( PIPE_BUFFER_USAGE_CPU_READ | PIPE_BUFFER_USAGE_CPU_WRITE ) |
Definition at line 62 of file pb_buffer_fenced.c.
#define PIPE_BUFFER_USAGE_GPU_READ_WRITE ( PIPE_BUFFER_USAGE_GPU_READ | PIPE_BUFFER_USAGE_GPU_WRITE ) |
Definition at line 64 of file pb_buffer_fenced.c.
#define PIPE_BUFFER_USAGE_WRITE ( PIPE_BUFFER_USAGE_CPU_WRITE | PIPE_BUFFER_USAGE_GPU_WRITE ) |
Definition at line 66 of file pb_buffer_fenced.c.
#define SUPER | ( | __derived | ) | (&(__derived)->base) |
static void _fenced_buffer_add | ( | struct fenced_buffer * | fenced_buf | ) | [static] |
Definition at line 121 of file pb_buffer_fenced.c.
References assert, pb_buffer::base, fenced_buffer::base, fenced_buffer_list::delayed, fenced_buffer::fence, fenced_buffer::flags, fenced_buffer::head, fenced_buffer::list, LIST_ADDTAIL, LIST_DEL, fenced_buffer_list::numDelayed, PIPE_BUFFER_USAGE_GPU_READ_WRITE, and pipe_buffer::refcount.
00122 { 00123 struct fenced_buffer_list *fenced_list = fenced_buf->list; 00124 00125 assert(fenced_buf->base.base.refcount); 00126 assert(fenced_buf->flags & PIPE_BUFFER_USAGE_GPU_READ_WRITE); 00127 assert(fenced_buf->fence); 00128 00129 #ifdef DEBUG 00130 LIST_DEL(&fenced_buf->head); 00131 assert(fenced_list->numUnfenced); 00132 --fenced_list->numUnfenced; 00133 #endif 00134 LIST_ADDTAIL(&fenced_buf->head, &fenced_list->delayed); 00135 ++fenced_list->numDelayed; 00136 }
static void _fenced_buffer_destroy | ( | struct fenced_buffer * | fenced_buf | ) | [static] |
Actually destroy the buffer.
Definition at line 143 of file pb_buffer_fenced.c.
References assert, pb_buffer::base, fenced_buffer::base, fenced_buffer::buffer, fenced_buffer::fence, FREE, fenced_buffer::head, fenced_buffer::list, LIST_DEL, list_head::next, pb_reference(), list_head::prev, and pipe_buffer::refcount.
00144 { 00145 struct fenced_buffer_list *fenced_list = fenced_buf->list; 00146 00147 assert(!fenced_buf->base.base.refcount); 00148 assert(!fenced_buf->fence); 00149 #ifdef DEBUG 00150 assert(fenced_buf->head.prev); 00151 assert(fenced_buf->head.next); 00152 LIST_DEL(&fenced_buf->head); 00153 assert(fenced_list->numUnfenced); 00154 --fenced_list->numUnfenced; 00155 #else 00156 (void)fenced_list; 00157 #endif 00158 pb_reference(&fenced_buf->buffer, NULL); 00159 FREE(fenced_buf); 00160 }
static enum pipe_error _fenced_buffer_finish | ( | struct fenced_buffer * | fenced_buf | ) | [static] |
Definition at line 193 of file pb_buffer_fenced.c.
References _fenced_buffer_remove(), assert, debug_warning, fenced_buffer::fence, pipe_winsys::fence_finish, fenced_buffer::flags, fenced_buffer::list, PIPE_BUFFER_USAGE_GPU_READ_WRITE, PIPE_ERROR, PIPE_OK, and fenced_buffer_list::winsys.
00194 { 00195 struct fenced_buffer_list *fenced_list = fenced_buf->list; 00196 struct pipe_winsys *winsys = fenced_list->winsys; 00197 00198 #if 0 00199 debug_warning("waiting for GPU"); 00200 #endif 00201 00202 assert(fenced_buf->fence); 00203 if(fenced_buf->fence) { 00204 if(winsys->fence_finish(winsys, fenced_buf->fence, 0) != 0) { 00205 return PIPE_ERROR; 00206 } 00207 /* Remove from the fenced list */ 00208 /* TODO: remove consequents */ 00209 _fenced_buffer_remove(fenced_list, fenced_buf); 00210 } 00211 00212 fenced_buf->flags &= ~PIPE_BUFFER_USAGE_GPU_READ_WRITE; 00213 return PIPE_OK; 00214 }
static void _fenced_buffer_list_check_free | ( | struct fenced_buffer_list * | fenced_list, | |
int | wait | |||
) | [static] |
Free as many fenced buffers from the list head as possible.
Definition at line 221 of file pb_buffer_fenced.c.
References _fenced_buffer_remove(), assert, fenced_buffer_list::delayed, fenced_buffer::fence, pipe_winsys::fence_finish, pipe_winsys::fence_signalled, LIST_ENTRY, list_head::next, and fenced_buffer_list::winsys.
00223 { 00224 struct pipe_winsys *winsys = fenced_list->winsys; 00225 struct list_head *curr, *next; 00226 struct fenced_buffer *fenced_buf; 00227 struct pipe_fence_handle *prev_fence = NULL; 00228 00229 curr = fenced_list->delayed.next; 00230 next = curr->next; 00231 while(curr != &fenced_list->delayed) { 00232 fenced_buf = LIST_ENTRY(struct fenced_buffer, curr, head); 00233 00234 if(fenced_buf->fence != prev_fence) { 00235 int signaled; 00236 if (wait) 00237 signaled = winsys->fence_finish(winsys, fenced_buf->fence, 0); 00238 else 00239 signaled = winsys->fence_signalled(winsys, fenced_buf->fence, 0); 00240 if (signaled != 0) 00241 break; 00242 prev_fence = fenced_buf->fence; 00243 } 00244 else { 00245 assert(winsys->fence_signalled(winsys, fenced_buf->fence, 0) == 0); 00246 } 00247 00248 _fenced_buffer_remove(fenced_list, fenced_buf); 00249 00250 curr = next; 00251 next = curr->next; 00252 } 00253 }
static void _fenced_buffer_remove | ( | struct fenced_buffer_list * | fenced_list, | |
struct fenced_buffer * | fenced_buf | |||
) | [static] |
Definition at line 164 of file pb_buffer_fenced.c.
References _fenced_buffer_destroy(), assert, pb_buffer::base, fenced_buffer::base, fenced_buffer::fence, pipe_winsys::fence_reference, fenced_buffer::flags, fenced_buffer::head, fenced_buffer::list, LIST_ADDTAIL, LIST_DEL, list_head::next, fenced_buffer_list::numDelayed, PIPE_BUFFER_USAGE_GPU_READ_WRITE, list_head::prev, pipe_buffer::refcount, and fenced_buffer_list::winsys.
00166 { 00167 struct pipe_winsys *winsys = fenced_list->winsys; 00168 00169 assert(fenced_buf->fence); 00170 assert(fenced_buf->list == fenced_list); 00171 00172 winsys->fence_reference(winsys, &fenced_buf->fence, NULL); 00173 fenced_buf->flags &= ~PIPE_BUFFER_USAGE_GPU_READ_WRITE; 00174 00175 assert(fenced_buf->head.prev); 00176 assert(fenced_buf->head.next); 00177 00178 LIST_DEL(&fenced_buf->head); 00179 assert(fenced_list->numDelayed); 00180 --fenced_list->numDelayed; 00181 00182 #ifdef DEBUG 00183 LIST_ADDTAIL(&fenced_buf->head, &fenced_list->unfenced); 00184 ++fenced_list->numUnfenced; 00185 #endif 00186 00187 if(!fenced_buf->base.base.refcount) 00188 _fenced_buffer_destroy(fenced_buf); 00189 }
void buffer_fence | ( | struct pb_buffer * | buf, | |
struct pipe_fence_handle * | fence | |||
) |
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.
Definition at line 403 of file pb_buffer_fenced.c.
References _fenced_buffer_add(), _fenced_buffer_remove(), assert, fenced_buffer::fence, pipe_winsys::fence_reference, fenced_buffer(), fenced_buffer::flags, fenced_buffer::list, fenced_buffer_list::mutex, PIPE_BUFFER_USAGE_GPU_READ_WRITE, pipe_mutex_lock, pipe_mutex_unlock, pb_buffer::vtbl, and fenced_buffer_list::winsys.
00405 { 00406 struct fenced_buffer *fenced_buf; 00407 struct fenced_buffer_list *fenced_list; 00408 struct pipe_winsys *winsys; 00409 /* FIXME: receive this as a parameter */ 00410 unsigned flags = fence ? PIPE_BUFFER_USAGE_GPU_READ_WRITE : 0; 00411 00412 /* This is a public function, so be extra cautious with the buffer passed, 00413 * as happens frequently to receive null buffers, or pointer to buffers 00414 * other than fenced buffers. */ 00415 assert(buf); 00416 if(!buf) 00417 return; 00418 assert(buf->vtbl == &fenced_buffer_vtbl); 00419 if(buf->vtbl != &fenced_buffer_vtbl) 00420 return; 00421 00422 if(!fence) 00423 return; 00424 00425 fenced_buf = fenced_buffer(buf); 00426 fenced_list = fenced_buf->list; 00427 winsys = fenced_list->winsys; 00428 00429 if(fence == fenced_buf->fence) { 00430 fenced_buf->flags |= flags & PIPE_BUFFER_USAGE_GPU_READ_WRITE; 00431 return; 00432 } 00433 00434 pipe_mutex_lock(fenced_list->mutex); 00435 if (fenced_buf->fence) 00436 _fenced_buffer_remove(fenced_list, fenced_buf); 00437 winsys->fence_reference(winsys, &fenced_buf->fence, fence); 00438 fenced_buf->flags |= flags & PIPE_BUFFER_USAGE_GPU_READ_WRITE; 00439 _fenced_buffer_add(fenced_buf); 00440 pipe_mutex_unlock(fenced_list->mutex); 00441 }
static struct fenced_buffer* fenced_buffer | ( | struct pb_buffer * | buf | ) | [static, read] |
Definition at line 112 of file pb_buffer_fenced.c.
References assert, fenced_buffer_vtbl, and pb_buffer::vtbl.
00113 { 00114 assert(buf); 00115 assert(buf->vtbl == &fenced_buffer_vtbl); 00116 return (struct fenced_buffer *)buf; 00117 }
struct pb_buffer* fenced_buffer_create | ( | struct fenced_buffer_list * | fenced, | |
struct pb_buffer * | buffer | |||
) | [read] |
Wrap a buffer in a fenced buffer.
NOTE: this will not increase the buffer reference count.
Definition at line 368 of file pb_buffer_fenced.c.
References pipe_buffer::alignment, pb_buffer::base, fenced_buffer::base, fenced_buffer::buffer, CALLOC_STRUCT, fenced_buffer::head, fenced_buffer::list, LIST_ADDTAIL, fenced_buffer_list::mutex, pb_reference(), pipe_mutex_lock, pipe_mutex_unlock, pipe_buffer::refcount, pipe_buffer::size, pipe_buffer::usage, and pb_buffer::vtbl.
00370 { 00371 struct fenced_buffer *buf; 00372 00373 if(!buffer) 00374 return NULL; 00375 00376 buf = CALLOC_STRUCT(fenced_buffer); 00377 if(!buf) { 00378 pb_reference(&buffer, NULL); 00379 return NULL; 00380 } 00381 00382 buf->base.base.refcount = 1; 00383 buf->base.base.alignment = buffer->base.alignment; 00384 buf->base.base.usage = buffer->base.usage; 00385 buf->base.base.size = buffer->base.size; 00386 00387 buf->base.vtbl = &fenced_buffer_vtbl; 00388 buf->buffer = buffer; 00389 buf->list = fenced_list; 00390 00391 #ifdef DEBUG 00392 pipe_mutex_lock(fenced_list->mutex); 00393 LIST_ADDTAIL(&buf->head, &fenced_list->unfenced); 00394 ++fenced_list->numUnfenced; 00395 pipe_mutex_unlock(fenced_list->mutex); 00396 #endif 00397 00398 return &buf->base; 00399 }
static void fenced_buffer_destroy | ( | struct pb_buffer * | buf | ) | [static] |
Definition at line 257 of file pb_buffer_fenced.c.
References _fenced_buffer_destroy(), _fenced_buffer_remove(), assert, pb_buffer::base, fenced_buffer::base, fenced_buffer_list::delayed, fenced_buffer::fence, pipe_winsys::fence_signalled, fenced_buffer(), fenced_buffer::head, fenced_buffer::list, LIST_ENTRY, fenced_buffer_list::mutex, pipe_mutex_lock, pipe_mutex_unlock, list_head::prev, pipe_buffer::refcount, and fenced_buffer_list::winsys.
00258 { 00259 struct fenced_buffer *fenced_buf = fenced_buffer(buf); 00260 struct fenced_buffer_list *fenced_list = fenced_buf->list; 00261 00262 pipe_mutex_lock(fenced_list->mutex); 00263 assert(fenced_buf->base.base.refcount == 0); 00264 if (fenced_buf->fence) { 00265 struct pipe_winsys *winsys = fenced_list->winsys; 00266 if(winsys->fence_signalled(winsys, fenced_buf->fence, 0) == 0) { 00267 struct list_head *curr, *prev; 00268 curr = &fenced_buf->head; 00269 prev = curr->prev; 00270 do { 00271 fenced_buf = LIST_ENTRY(struct fenced_buffer, curr, head); 00272 assert(winsys->fence_signalled(winsys, fenced_buf->fence, 0) == 0); 00273 _fenced_buffer_remove(fenced_list, fenced_buf); 00274 curr = prev; 00275 prev = curr->prev; 00276 } while (curr != &fenced_list->delayed); 00277 } 00278 else { 00279 /* delay destruction */ 00280 } 00281 } 00282 else { 00283 _fenced_buffer_destroy(fenced_buf); 00284 } 00285 pipe_mutex_unlock(fenced_list->mutex); 00286 }
static void fenced_buffer_get_base_buffer | ( | struct pb_buffer * | buf, | |
struct pb_buffer ** | base_buf, | |||
unsigned * | offset | |||
) | [static] |
Definition at line 349 of file pb_buffer_fenced.c.
References fenced_buffer::buffer, fenced_buffer(), and pb_get_base_buffer().
00352 { 00353 struct fenced_buffer *fenced_buf = fenced_buffer(buf); 00354 pb_get_base_buffer(fenced_buf->buffer, base_buf, offset); 00355 }
void fenced_buffer_list_check_free | ( | struct fenced_buffer_list * | fenced_list, | |
int | wait | |||
) |
Walk the fenced buffer list to check and free signalled buffers.
Definition at line 470 of file pb_buffer_fenced.c.
References _fenced_buffer_list_check_free(), fenced_buffer_list::mutex, pipe_mutex_lock, and pipe_mutex_unlock.
00472 { 00473 pipe_mutex_lock(fenced_list->mutex); 00474 _fenced_buffer_list_check_free(fenced_list, wait); 00475 pipe_mutex_unlock(fenced_list->mutex); 00476 }
struct fenced_buffer_list* fenced_buffer_list_create | ( | struct pipe_winsys * | winsys | ) | [read] |
Create a fenced buffer list.
See also fenced_bufmgr_create for a more convenient way to use this.
Definition at line 445 of file pb_buffer_fenced.c.
References CALLOC_STRUCT, fenced_buffer_list::delayed, LIST_INITHEAD, fenced_buffer_list::mutex, fenced_buffer_list::numDelayed, pipe_mutex_init, and fenced_buffer_list::winsys.
00446 { 00447 struct fenced_buffer_list *fenced_list; 00448 00449 fenced_list = CALLOC_STRUCT(fenced_buffer_list); 00450 if (!fenced_list) 00451 return NULL; 00452 00453 fenced_list->winsys = winsys; 00454 00455 LIST_INITHEAD(&fenced_list->delayed); 00456 fenced_list->numDelayed = 0; 00457 00458 #ifdef DEBUG 00459 LIST_INITHEAD(&fenced_list->unfenced); 00460 fenced_list->numUnfenced = 0; 00461 #endif 00462 00463 pipe_mutex_init(fenced_list->mutex); 00464 00465 return fenced_list; 00466 }
void fenced_buffer_list_destroy | ( | struct fenced_buffer_list * | fenced_list | ) |
Definition at line 525 of file pb_buffer_fenced.c.
References _fenced_buffer_list_check_free(), FREE, fenced_buffer_list::mutex, fenced_buffer_list::numDelayed, pipe_mutex_lock, and pipe_mutex_unlock.
00526 { 00527 pipe_mutex_lock(fenced_list->mutex); 00528 00529 /* Wait on outstanding fences */ 00530 while (fenced_list->numDelayed) { 00531 pipe_mutex_unlock(fenced_list->mutex); 00532 #if defined(PIPE_OS_LINUX) 00533 sched_yield(); 00534 #endif 00535 _fenced_buffer_list_check_free(fenced_list, 1); 00536 pipe_mutex_lock(fenced_list->mutex); 00537 } 00538 00539 #ifdef DEBUG 00540 //assert(!fenced_list->numUnfenced); 00541 #endif 00542 00543 pipe_mutex_unlock(fenced_list->mutex); 00544 00545 FREE(fenced_list); 00546 }
static void* fenced_buffer_map | ( | struct pb_buffer * | buf, | |
unsigned | flags | |||
) | [static] |
Definition at line 290 of file pb_buffer_fenced.c.
References _fenced_buffer_finish(), _fenced_buffer_remove(), assert, fenced_buffer::buffer, debug_warning, fenced_buffer::fence, pipe_winsys::fence_signalled, fenced_buffer(), fenced_buffer::flags, fenced_buffer::list, fenced_buffer::mapcount, pb_map(), PIPE_BUFFER_USAGE_CPU_READ_WRITE, PIPE_BUFFER_USAGE_CPU_WRITE, PIPE_BUFFER_USAGE_DONTBLOCK, PIPE_BUFFER_USAGE_GPU_READ, PIPE_BUFFER_USAGE_GPU_READ_WRITE, PIPE_BUFFER_USAGE_GPU_WRITE, and fenced_buffer_list::winsys.
00292 { 00293 struct fenced_buffer *fenced_buf = fenced_buffer(buf); 00294 struct fenced_buffer_list *fenced_list = fenced_buf->list; 00295 struct pipe_winsys *winsys = fenced_list->winsys; 00296 void *map; 00297 00298 assert(!(flags & PIPE_BUFFER_USAGE_GPU_READ_WRITE)); 00299 00300 /* Serialize writes */ 00301 if((fenced_buf->flags & PIPE_BUFFER_USAGE_GPU_WRITE) || 00302 ((fenced_buf->flags & PIPE_BUFFER_USAGE_GPU_READ) && (flags & PIPE_BUFFER_USAGE_CPU_WRITE))) { 00303 if(flags & PIPE_BUFFER_USAGE_DONTBLOCK) { 00304 /* Don't wait for the GPU to finish writing */ 00305 if(winsys->fence_signalled(winsys, fenced_buf->fence, 0) == 0) 00306 _fenced_buffer_remove(fenced_list, fenced_buf); 00307 else 00308 return NULL; 00309 } 00310 else { 00311 /* Wait for the GPU to finish writing */ 00312 _fenced_buffer_finish(fenced_buf); 00313 } 00314 } 00315 00316 #if 0 00317 /* Check for CPU write access (read is OK) */ 00318 if(fenced_buf->flags & PIPE_BUFFER_USAGE_CPU_READ_WRITE) { 00319 /* this is legal -- just for debugging */ 00320 debug_warning("concurrent CPU writes"); 00321 } 00322 #endif 00323 00324 map = pb_map(fenced_buf->buffer, flags); 00325 if(map) { 00326 ++fenced_buf->mapcount; 00327 fenced_buf->flags |= flags & PIPE_BUFFER_USAGE_CPU_READ_WRITE; 00328 } 00329 00330 return map; 00331 }
static void fenced_buffer_unmap | ( | struct pb_buffer * | buf | ) | [static] |
Definition at line 335 of file pb_buffer_fenced.c.
References assert, fenced_buffer::buffer, fenced_buffer(), fenced_buffer::flags, fenced_buffer::mapcount, pb_unmap(), and PIPE_BUFFER_USAGE_CPU_READ_WRITE.
00336 { 00337 struct fenced_buffer *fenced_buf = fenced_buffer(buf); 00338 assert(fenced_buf->mapcount); 00339 if(fenced_buf->mapcount) { 00340 pb_unmap(fenced_buf->buffer); 00341 --fenced_buf->mapcount; 00342 if(!fenced_buf->mapcount) 00343 fenced_buf->flags &= ~PIPE_BUFFER_USAGE_CPU_READ_WRITE; 00344 } 00345 }
struct pb_vtbl fenced_buffer_vtbl |
Initial value:
The fenced buffer's virtual function table.NOTE: Made public for debugging purposes.
Definition at line 359 of file pb_buffer_fenced.c.