pb_buffer_fenced.c revision f1efef809caddff442ed45a59645b3f39498f521
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/************************************************************************** 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * All Rights Reserved. 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Permission is hereby granted, free of charge, to any person obtaining a 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * copy of this software and associated documentation files (the 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * "Software"), to deal in the Software without restriction, including 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * without limitation the rights to use, copy, modify, merge, publish, 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * distribute, sub license, and/or sell copies of the Software, and to 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * permit persons to whom the Software is furnished to do so, subject to 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the following conditions: 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The above copyright notice and this permission notice (including the 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * next paragraph) shall be included in all copies or substantial portions 16eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * of the Software. 17eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * 18eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 22eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * 26eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch **************************************************************************/ 27eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 28eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch/** 29eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * \file 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Implementation of fenced buffers. 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * \author José Fonseca <jrfonseca-at-tungstengraphics-dot-com> 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * \author Thomas Hellström <thomas-at-tungstengraphics-dot-com> 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "pipe/p_compiler.h" 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "pipe/p_debug.h" 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "pipe/p_winsys.h" 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "pipe/p_thread.h" 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "pipe/p_util.h" 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "util/u_double_list.h" 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "pb_buffer.h" 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "pb_buffer_fenced.h" 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 47eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#ifndef WIN32 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <unistd.h> 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Convenience macro (type safe). 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SUPER(__derived) (&(__derived)->base) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct fenced_buffer_list 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) _glthread_Mutex mutex; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct pipe_winsys *winsys; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t numDelayed; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t checkDelayed; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct list_head delayed; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Wrapper around a pipe buffer which adds fencing and reference counting. 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct fenced_buffer 75eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch{ 76eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch struct pb_buffer base; 77eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 78eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch struct pb_buffer *buffer; 79eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 80eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch struct pipe_fence_handle *fence; 81eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 82eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch struct list_head head; 83eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch struct fenced_buffer_list *list; 84eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static INLINE struct fenced_buffer * 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)fenced_buffer(struct pb_buffer *buf) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(buf); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(buf->vtbl == &fenced_buffer_vtbl); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (struct fenced_buffer *)buf; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_fenced_buffer_list_check_free(struct fenced_buffer_list *fenced_list, 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int wait) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct pipe_winsys *winsys = fenced_list->winsys; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct fenced_buffer *fenced_buf; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct list_head *list, *prev; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int signaled = -1; 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) list = fenced_list->delayed.next; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prev = list->prev; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (; list != &fenced_list->delayed; list = prev, prev = list->prev) { 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fenced_buf = LIST_ENTRY(struct fenced_buffer, list, head); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (signaled != 0) { 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (wait) { 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) signaled = winsys->fence_finish(winsys, fenced_buf->fence, 0); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else { 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) signaled = winsys->fence_signalled(winsys, fenced_buf->fence, 0); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (signaled != 0) { 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if 0 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* XXX: we are assuming that buffers are freed in the same order they 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * are fenced which may not always be true... 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) signaled = -1; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winsys->fence_reference(winsys, &fenced_buf->fence, NULL); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LIST_DEL(list); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fenced_list->numDelayed--; 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Do the delayed destroy: 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pb_reference(&fenced_buf->buffer, NULL); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FREE(fenced_buf); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 143 144 145static void 146fenced_buffer_destroy(struct pb_buffer *buf) 147{ 148 struct fenced_buffer *fenced_buf = fenced_buffer(buf); 149 struct fenced_buffer_list *fenced_list = fenced_buf->list; 150 151 if (fenced_buf->fence) { 152 struct pipe_winsys *winsys = fenced_list->winsys; 153 if(winsys->fence_signalled(winsys, fenced_buf->fence, 0) != 0) { 154 LIST_ADDTAIL(&fenced_buf->head, &fenced_list->delayed); 155 fenced_list->numDelayed++; 156 } 157 else { 158 winsys->fence_reference(winsys, &fenced_buf->fence, NULL); 159 pb_reference(&fenced_buf->buffer, NULL); 160 FREE(fenced_buf); 161 } 162 } 163 else { 164 pb_reference(&fenced_buf->buffer, NULL); 165 FREE(fenced_buf); 166 } 167 168 if ((fenced_list->numDelayed % fenced_list->checkDelayed) == 0) 169 _fenced_buffer_list_check_free(fenced_list, 0); 170} 171 172 173static void * 174fenced_buffer_map(struct pb_buffer *buf, 175 unsigned flags) 176{ 177 struct fenced_buffer *fenced_buf = fenced_buffer(buf); 178 return pb_map(fenced_buf->buffer, flags); 179} 180 181 182static void 183fenced_buffer_unmap(struct pb_buffer *buf) 184{ 185 struct fenced_buffer *fenced_buf = fenced_buffer(buf); 186 pb_unmap(fenced_buf->buffer); 187} 188 189 190static void 191fenced_buffer_get_base_buffer(struct pb_buffer *buf, 192 struct pb_buffer **base_buf, 193 unsigned *offset) 194{ 195 struct fenced_buffer *fenced_buf = fenced_buffer(buf); 196 pb_get_base_buffer(fenced_buf->buffer, base_buf, offset); 197} 198 199 200const struct pb_vtbl 201fenced_buffer_vtbl = { 202 fenced_buffer_destroy, 203 fenced_buffer_map, 204 fenced_buffer_unmap, 205 fenced_buffer_get_base_buffer 206}; 207 208 209struct pb_buffer * 210fenced_buffer_create(struct fenced_buffer_list *fenced_list, 211 struct pb_buffer *buffer) 212{ 213 struct fenced_buffer *buf; 214 215 if(!buffer) 216 return NULL; 217 218 buf = CALLOC_STRUCT(fenced_buffer); 219 if(!buf) 220 return NULL; 221 222 buf->base.base.refcount = 1; 223 buf->base.base.alignment = buffer->base.alignment; 224 buf->base.base.usage = buffer->base.usage; 225 buf->base.base.size = buffer->base.size; 226 227 buf->base.vtbl = &fenced_buffer_vtbl; 228 buf->buffer = buffer; 229 buf->list = fenced_list; 230 231 return &buf->base; 232} 233 234 235void 236buffer_fence(struct pb_buffer *buf, 237 struct pipe_fence_handle *fence) 238{ 239 struct fenced_buffer *fenced_buf = fenced_buffer(buf); 240 struct fenced_buffer_list *fenced_list = fenced_buf->list; 241 struct pipe_winsys *winsys = fenced_list->winsys; 242 243 _glthread_LOCK_MUTEX(fenced_list->mutex); 244 winsys->fence_reference(winsys, &fenced_buf->fence, fence); 245 _glthread_UNLOCK_MUTEX(fenced_list->mutex); 246} 247 248 249struct fenced_buffer_list * 250fenced_buffer_list_create(struct pipe_winsys *winsys) 251{ 252 struct fenced_buffer_list *fenced_list; 253 254 fenced_list = (struct fenced_buffer_list *)CALLOC(1, sizeof(*fenced_list)); 255 if (!fenced_list) 256 return NULL; 257 258 fenced_list->winsys = winsys; 259 260 LIST_INITHEAD(&fenced_list->delayed); 261 262 fenced_list->numDelayed = 0; 263 264 /* TODO: don't hard code this */ 265 fenced_list->checkDelayed = 5; 266 267 _glthread_INIT_MUTEX(fenced_list->mutex); 268 269 return fenced_list; 270} 271 272 273void 274fenced_buffer_list_check_free(struct fenced_buffer_list *fenced_list, 275 int wait) 276{ 277 _glthread_LOCK_MUTEX(fenced_list->mutex); 278 _fenced_buffer_list_check_free(fenced_list, wait); 279 _glthread_UNLOCK_MUTEX(fenced_list->mutex); 280} 281 282 283void 284fenced_buffer_list_destroy(struct fenced_buffer_list *fenced_list) 285{ 286 _glthread_LOCK_MUTEX(fenced_list->mutex); 287 288 /* Wait on outstanding fences */ 289 while (fenced_list->numDelayed) { 290 _glthread_UNLOCK_MUTEX(fenced_list->mutex); 291#ifndef WIN32 292 sched_yield(); 293#endif 294 _fenced_buffer_list_check_free(fenced_list, 1); 295 _glthread_LOCK_MUTEX(fenced_list->mutex); 296 } 297 298 _glthread_UNLOCK_MUTEX(fenced_list->mutex); 299 300 FREE(fenced_list); 301} 302 303 304