pb_buffer_fenced.c revision 686a6c746851b4bc2572aaa1153d570717bdd77f
1b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)/************************************************************************** 2b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) * 3b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. 4b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) * All Rights Reserved. 5b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) * 6b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) * Permission is hereby granted, free of charge, to any person obtaining a 71675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch * copy of this software and associated documentation files (the 8a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) * "Software"), to deal in the Software without restriction, including 91675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch * without limitation the rights to use, copy, modify, merge, publish, 10f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * distribute, sub license, and/or sell copies of the Software, and to 11b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) * permit persons to whom the Software is furnished to do so, subject to 12b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) * the following conditions: 13b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) * 14b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) * The above copyright notice and this permission notice (including the 15b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) * next paragraph) shall be included in all copies or substantial portions 16b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) * of the Software. 17a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) * 18a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 22f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 231675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 241675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 251675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch * 261675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch **************************************************************************/ 27b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 28b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)/** 29b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) * \file 30b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) * Implementation of fenced buffers. 31868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) * 32868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) * \author José Fonseca <jrfonseca-at-tungstengraphics-dot-com> 33868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) * \author Thomas Hellström <thomas-at-tungstengraphics-dot-com> 34868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) */ 35868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 36868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 37868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "pipe/p_compiler.h" 38868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "pipe/p_debug.h" 3946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "pipe/p_winsys.h" 4046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "pipe/p_thread.h" 4146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "pipe/p_util.h" 4258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "util/u_double_list.h" 4358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 4458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "pb_buffer.h" 451675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch#include "pb_buffer_fenced.h" 461675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch 471675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch#ifndef WIN32 481675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch#include <unistd.h> 491675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch#endif 501675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch 511675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch 521675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch/** 531675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch * Convenience macro (type safe). 541675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch */ 551675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch#define SUPER(__derived) (&(__derived)->base) 561675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch 571675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch 581675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdochstruct fenced_buffer_list 591675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch{ 601675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch _glthread_Mutex mutex; 611675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch 621675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch struct pipe_winsys *winsys; 631675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch 641675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch size_t numDelayed; 651675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch size_t checkDelayed; 661675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch 671675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch struct list_head delayed; 681675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch}; 691675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch 701675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch 711675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch/** 721675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch * Wrapper around a pipe buffer which adds fencing and reference counting. 731675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch */ 741675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdochstruct fenced_buffer 751675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch{ 761675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch struct pb_buffer base; 771675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch 781675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch struct pb_buffer *buffer; 791675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch 801675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch struct pipe_fence_handle *fence; 811675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch 821675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch struct list_head head; 83b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) struct fenced_buffer_list *list; 84}; 85 86 87static INLINE struct fenced_buffer * 88fenced_buffer(struct pb_buffer *buf) 89{ 90 assert(buf); 91 assert(buf->vtbl == &fenced_buffer_vtbl); 92 return (struct fenced_buffer *)buf; 93} 94 95 96static void 97_fenced_buffer_list_check_free(struct fenced_buffer_list *fenced_list, 98 int wait) 99{ 100 struct pipe_winsys *winsys = fenced_list->winsys; 101 struct fenced_buffer *fenced_buf; 102 struct list_head *list, *prev; 103 int signaled = -1; 104 105 list = fenced_list->delayed.next; 106 prev = list->prev; 107 for (; list != &fenced_list->delayed; list = prev, prev = list->prev) { 108 109 fenced_buf = LIST_ENTRY(struct fenced_buffer, list, head); 110 111 if (signaled != 0) { 112 if (wait) { 113 signaled = winsys->fence_finish(winsys, fenced_buf->fence, 0); 114 } 115 else { 116 signaled = winsys->fence_signalled(winsys, fenced_buf->fence, 0); 117 } 118 } 119 120 if (signaled != 0) { 121#if 0 122 /* XXX: we are assuming that buffers are freed in the same order they 123 * are fenced which may not always be true... 124 */ 125 break; 126#else 127 signaled = -1; 128 continue; 129#endif 130 } 131 132 winsys->fence_reference(winsys, &fenced_buf->fence, NULL); 133 134 LIST_DEL(list); 135 fenced_list->numDelayed--; 136 137 /* Do the delayed destroy: 138 */ 139 pb_reference(&fenced_buf->buffer, NULL); 140 FREE(fenced_buf); 141 } 142} 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_finish(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