pb_buffer_fenced.c revision ea4bf267e4b023b08043f91ac44592fed1736e7f
1579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson/************************************************************************** 2579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 3579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. 4579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * All Rights Reserved. 5579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 6579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Permission is hereby granted, free of charge, to any person obtaining a 7579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * copy of this software and associated documentation files (the 8579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * "Software"), to deal in the Software without restriction, including 9579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * without limitation the rights to use, copy, modify, merge, publish, 10579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * distribute, sub license, and/or sell copies of the Software, and to 11579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * permit persons to whom the Software is furnished to do so, subject to 12579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * the following conditions: 13579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 14579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * The above copyright notice and this permission notice (including the 15579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * next paragraph) shall be included in all copies or substantial portions 16579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * of the Software. 17579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 18579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 22579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 26579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson **************************************************************************/ 27579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 28579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson/** 29579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * \file 30579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Implementation of fenced buffers. 31579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 32579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * \author Jose Fonseca <jrfonseca-at-tungstengraphics-dot-com> 33579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * \author Thomas Hellström <thomas-at-tungstengraphics-dot-com> 34579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 35579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 36579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 37579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson#include "pipe/p_config.h" 38579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 39579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson#if defined(PIPE_OS_LINUX) 40579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson#include <unistd.h> 41579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson#include <sched.h> 42579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson#endif 43579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 44579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson#include "pipe/p_compiler.h" 45579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson#include "pipe/p_error.h" 46579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson#include "util/u_debug.h" 47579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson#include "pipe/p_thread.h" 48579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson#include "util/u_memory.h" 49579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson#include "util/u_double_list.h" 50579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 51579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson#include "pb_buffer.h" 52579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson#include "pb_buffer_fenced.h" 53579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 54579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 55579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 56579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson/** 57579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Convenience macro (type safe). 58579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 59579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson#define SUPER(__derived) (&(__derived)->base) 60579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 61579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 62579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonstruct fenced_buffer_list 63579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson{ 64579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson pipe_mutex mutex; 65579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 66579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson struct pb_fence_ops *ops; 67579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 68579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson size_t numDelayed; 69579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 70579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson struct list_head delayed; 71579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson}; 72579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 73579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 74579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson/** 75579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Wrapper around a pipe buffer which adds fencing and reference counting. 76579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 77579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonstruct fenced_buffer 78579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson{ 79579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson struct pb_buffer base; 80579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 81579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson struct pb_buffer *buffer; 82579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 83579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* FIXME: protect access with mutex */ 84579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 85579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 86579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * A bitmask of PIPE_BUFFER_USAGE_CPU/GPU_READ/WRITE describing the current 87579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * buffer usage. 88579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 89579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson unsigned flags; 90579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 91579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson unsigned mapcount; 92579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson struct pb_validate *vl; 93579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson unsigned validation_flags; 94579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson struct pipe_fence_handle *fence; 95579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 96579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson struct list_head head; 97579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson struct fenced_buffer_list *list; 98579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson}; 99579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 100579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 101579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonstatic INLINE struct fenced_buffer * 102579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonfenced_buffer(struct pb_buffer *buf) 103579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson{ 104579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assert(buf); 105579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return (struct fenced_buffer *)buf; 106579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson} 107579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 108579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 109579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonstatic INLINE void 110579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson_fenced_buffer_add(struct fenced_buffer *fenced_buf) 111579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson{ 112579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson struct fenced_buffer_list *fenced_list = fenced_buf->list; 113579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 114579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assert(fenced_buf->base.base.refcount); 115579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assert(fenced_buf->flags & PIPE_BUFFER_USAGE_GPU_READ_WRITE); 116579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assert(fenced_buf->fence); 117579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 118579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assert(!fenced_buf->head.prev); 119579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assert(!fenced_buf->head.next); 120579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson LIST_ADDTAIL(&fenced_buf->head, &fenced_list->delayed); 121579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson ++fenced_list->numDelayed; 122579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson} 123579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 124579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 125579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson/** 126579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Actually destroy the buffer. 127579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 128579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonstatic INLINE void 129579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson_fenced_buffer_destroy(struct fenced_buffer *fenced_buf) 130579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson{ 131579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assert(!fenced_buf->base.base.refcount); 132579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assert(!fenced_buf->fence); 133579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson pb_reference(&fenced_buf->buffer, NULL); 134579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson FREE(fenced_buf); 135579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson} 136579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 137579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 138579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonstatic INLINE void 139579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson_fenced_buffer_remove(struct fenced_buffer_list *fenced_list, 140579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson struct fenced_buffer *fenced_buf) 141579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson{ 142579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson struct pb_fence_ops *ops = fenced_list->ops; 143579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 144579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assert(fenced_buf->fence); 145579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assert(fenced_buf->list == fenced_list); 146579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 147579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson ops->fence_reference(ops, &fenced_buf->fence, NULL); 148579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fenced_buf->flags &= ~PIPE_BUFFER_USAGE_GPU_READ_WRITE; 149579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 150579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assert(fenced_buf->head.prev); 151579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assert(fenced_buf->head.next); 152579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson LIST_DEL(&fenced_buf->head); 153579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson#ifdef DEBUG 154579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fenced_buf->head.prev = NULL; 155579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fenced_buf->head.next = NULL; 156579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson#endif 157579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 158579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assert(fenced_list->numDelayed); 159579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson --fenced_list->numDelayed; 160579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 161579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if(!fenced_buf->base.base.refcount) 162579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson _fenced_buffer_destroy(fenced_buf); 163} 164 165 166static INLINE enum pipe_error 167_fenced_buffer_finish(struct fenced_buffer *fenced_buf) 168{ 169 struct fenced_buffer_list *fenced_list = fenced_buf->list; 170 struct pb_fence_ops *ops = fenced_list->ops; 171 172#if 0 173 debug_warning("waiting for GPU"); 174#endif 175 176 assert(fenced_buf->fence); 177 if(fenced_buf->fence) { 178 if(ops->fence_finish(ops, fenced_buf->fence, 0) != 0) { 179 return PIPE_ERROR; 180 } 181 /* Remove from the fenced list */ 182 /* TODO: remove consequents */ 183 _fenced_buffer_remove(fenced_list, fenced_buf); 184 } 185 186 fenced_buf->flags &= ~PIPE_BUFFER_USAGE_GPU_READ_WRITE; 187 return PIPE_OK; 188} 189 190 191/** 192 * Free as many fenced buffers from the list head as possible. 193 */ 194static void 195_fenced_buffer_list_check_free(struct fenced_buffer_list *fenced_list, 196 int wait) 197{ 198 struct pb_fence_ops *ops = fenced_list->ops; 199 struct list_head *curr, *next; 200 struct fenced_buffer *fenced_buf; 201 struct pipe_fence_handle *prev_fence = NULL; 202 203 curr = fenced_list->delayed.next; 204 next = curr->next; 205 while(curr != &fenced_list->delayed) { 206 fenced_buf = LIST_ENTRY(struct fenced_buffer, curr, head); 207 208 if(fenced_buf->fence != prev_fence) { 209 int signaled; 210 if (wait) 211 signaled = ops->fence_finish(ops, fenced_buf->fence, 0); 212 else 213 signaled = ops->fence_signalled(ops, fenced_buf->fence, 0); 214 if (signaled != 0) 215 break; 216 prev_fence = fenced_buf->fence; 217 } 218 else { 219 assert(ops->fence_signalled(ops, fenced_buf->fence, 0) == 0); 220 } 221 222 _fenced_buffer_remove(fenced_list, fenced_buf); 223 224 curr = next; 225 next = curr->next; 226 } 227} 228 229 230static void 231fenced_buffer_destroy(struct pb_buffer *buf) 232{ 233 struct fenced_buffer *fenced_buf = fenced_buffer(buf); 234 struct fenced_buffer_list *fenced_list = fenced_buf->list; 235 236 pipe_mutex_lock(fenced_list->mutex); 237 assert(fenced_buf->base.base.refcount == 0); 238 if (fenced_buf->fence) { 239 struct pb_fence_ops *ops = fenced_list->ops; 240 if(ops->fence_signalled(ops, fenced_buf->fence, 0) == 0) { 241 struct list_head *curr, *prev; 242 curr = &fenced_buf->head; 243 prev = curr->prev; 244 do { 245 fenced_buf = LIST_ENTRY(struct fenced_buffer, curr, head); 246 assert(ops->fence_signalled(ops, fenced_buf->fence, 0) == 0); 247 _fenced_buffer_remove(fenced_list, fenced_buf); 248 curr = prev; 249 prev = curr->prev; 250 } while (curr != &fenced_list->delayed); 251 } 252 else { 253 /* delay destruction */ 254 } 255 } 256 else { 257 _fenced_buffer_destroy(fenced_buf); 258 } 259 pipe_mutex_unlock(fenced_list->mutex); 260} 261 262 263static void * 264fenced_buffer_map(struct pb_buffer *buf, 265 unsigned flags) 266{ 267 struct fenced_buffer *fenced_buf = fenced_buffer(buf); 268 void *map; 269 270 assert(flags & PIPE_BUFFER_USAGE_CPU_READ_WRITE); 271 assert(!(flags & ~PIPE_BUFFER_USAGE_CPU_READ_WRITE)); 272 flags &= PIPE_BUFFER_USAGE_CPU_READ_WRITE; 273 274 /* Check for GPU read/write access */ 275 if(fenced_buf->flags & PIPE_BUFFER_USAGE_GPU_WRITE) { 276 /* Wait for the GPU to finish writing */ 277 _fenced_buffer_finish(fenced_buf); 278 } 279 280#if 0 281 /* Check for CPU write access (read is OK) */ 282 if(fenced_buf->flags & PIPE_BUFFER_USAGE_CPU_READ_WRITE) { 283 /* this is legal -- just for debugging */ 284 debug_warning("concurrent CPU writes"); 285 } 286#endif 287 288 map = pb_map(fenced_buf->buffer, flags); 289 if(map) { 290 ++fenced_buf->mapcount; 291 fenced_buf->flags |= flags; 292 } 293 294 return map; 295} 296 297 298static void 299fenced_buffer_unmap(struct pb_buffer *buf) 300{ 301 struct fenced_buffer *fenced_buf = fenced_buffer(buf); 302 assert(fenced_buf->mapcount); 303 if(fenced_buf->mapcount) { 304 pb_unmap(fenced_buf->buffer); 305 --fenced_buf->mapcount; 306 if(!fenced_buf->mapcount) 307 fenced_buf->flags &= ~PIPE_BUFFER_USAGE_CPU_READ_WRITE; 308 } 309} 310 311 312static enum pipe_error 313fenced_buffer_validate(struct pb_buffer *buf, 314 struct pb_validate *vl, 315 unsigned flags) 316{ 317 struct fenced_buffer *fenced_buf = fenced_buffer(buf); 318 enum pipe_error ret; 319 320 if(!vl) { 321 /* invalidate */ 322 fenced_buf->vl = NULL; 323 fenced_buf->validation_flags = 0; 324 return PIPE_OK; 325 } 326 327 assert(flags & PIPE_BUFFER_USAGE_GPU_READ_WRITE); 328 assert(!(flags & ~PIPE_BUFFER_USAGE_GPU_READ_WRITE)); 329 flags &= PIPE_BUFFER_USAGE_GPU_READ_WRITE; 330 331 /* Buffer cannot be validated in two different lists */ 332 if(fenced_buf->vl && fenced_buf->vl != vl) 333 return PIPE_ERROR_RETRY; 334 335 /* Do not validate if buffer is still mapped */ 336 if(fenced_buf->flags & PIPE_BUFFER_USAGE_CPU_READ_WRITE) { 337 /* TODO: wait for the thread that mapped the buffer to unmap it */ 338 return PIPE_ERROR_RETRY; 339 } 340 341 if(fenced_buf->vl == vl && 342 (fenced_buf->validation_flags & flags) == flags) { 343 /* Nothing to do -- buffer already validated */ 344 return PIPE_OK; 345 } 346 347 /* Final sanity checking */ 348 assert(!(fenced_buf->flags & PIPE_BUFFER_USAGE_CPU_READ_WRITE)); 349 assert(!fenced_buf->mapcount); 350 351 ret = pb_validate(fenced_buf->buffer, vl, flags); 352 if (ret != PIPE_OK) 353 return ret; 354 355 fenced_buf->vl = vl; 356 fenced_buf->validation_flags |= flags; 357 358 return PIPE_OK; 359} 360 361 362static void 363fenced_buffer_fence(struct pb_buffer *buf, 364 struct pipe_fence_handle *fence) 365{ 366 struct fenced_buffer *fenced_buf; 367 struct fenced_buffer_list *fenced_list; 368 struct pb_fence_ops *ops; 369 370 fenced_buf = fenced_buffer(buf); 371 fenced_list = fenced_buf->list; 372 ops = fenced_list->ops; 373 374 if(fence == fenced_buf->fence) { 375 /* Nothing to do */ 376 return; 377 } 378 379 assert(fenced_buf->vl); 380 assert(fenced_buf->validation_flags); 381 382 pipe_mutex_lock(fenced_list->mutex); 383 if (fenced_buf->fence) 384 _fenced_buffer_remove(fenced_list, fenced_buf); 385 if (fence) { 386 ops->fence_reference(ops, &fenced_buf->fence, fence); 387 fenced_buf->flags |= fenced_buf->validation_flags; 388 _fenced_buffer_add(fenced_buf); 389 } 390 pipe_mutex_unlock(fenced_list->mutex); 391 392 pb_fence(fenced_buf->buffer, fence); 393 394 fenced_buf->vl = NULL; 395 fenced_buf->validation_flags = 0; 396} 397 398 399static void 400fenced_buffer_get_base_buffer(struct pb_buffer *buf, 401 struct pb_buffer **base_buf, 402 unsigned *offset) 403{ 404 struct fenced_buffer *fenced_buf = fenced_buffer(buf); 405 pb_get_base_buffer(fenced_buf->buffer, base_buf, offset); 406} 407 408 409static const struct pb_vtbl 410fenced_buffer_vtbl = { 411 fenced_buffer_destroy, 412 fenced_buffer_map, 413 fenced_buffer_unmap, 414 fenced_buffer_validate, 415 fenced_buffer_fence, 416 fenced_buffer_get_base_buffer 417}; 418 419 420struct pb_buffer * 421fenced_buffer_create(struct fenced_buffer_list *fenced_list, 422 struct pb_buffer *buffer) 423{ 424 struct fenced_buffer *buf; 425 426 if(!buffer) 427 return NULL; 428 429 buf = CALLOC_STRUCT(fenced_buffer); 430 if(!buf) { 431 pb_reference(&buffer, NULL); 432 return NULL; 433 } 434 435 buf->base.base.refcount = 1; 436 buf->base.base.alignment = buffer->base.alignment; 437 buf->base.base.usage = buffer->base.usage; 438 buf->base.base.size = buffer->base.size; 439 440 buf->base.vtbl = &fenced_buffer_vtbl; 441 buf->buffer = buffer; 442 buf->list = fenced_list; 443 444 return &buf->base; 445} 446 447 448struct fenced_buffer_list * 449fenced_buffer_list_create(struct pb_fence_ops *ops) 450{ 451 struct fenced_buffer_list *fenced_list; 452 453 fenced_list = CALLOC_STRUCT(fenced_buffer_list); 454 if (!fenced_list) 455 return NULL; 456 457 fenced_list->ops = ops; 458 459 LIST_INITHEAD(&fenced_list->delayed); 460 461 fenced_list->numDelayed = 0; 462 463 pipe_mutex_init(fenced_list->mutex); 464 465 return fenced_list; 466} 467 468 469void 470fenced_buffer_list_check_free(struct fenced_buffer_list *fenced_list, 471 int wait) 472{ 473 pipe_mutex_lock(fenced_list->mutex); 474 _fenced_buffer_list_check_free(fenced_list, wait); 475 pipe_mutex_unlock(fenced_list->mutex); 476} 477 478 479void 480fenced_buffer_list_destroy(struct fenced_buffer_list *fenced_list) 481{ 482 pipe_mutex_lock(fenced_list->mutex); 483 484 /* Wait on outstanding fences */ 485 while (fenced_list->numDelayed) { 486 pipe_mutex_unlock(fenced_list->mutex); 487#if defined(PIPE_OS_LINUX) 488 sched_yield(); 489#endif 490 _fenced_buffer_list_check_free(fenced_list, 1); 491 pipe_mutex_lock(fenced_list->mutex); 492 } 493 494 pipe_mutex_unlock(fenced_list->mutex); 495 496 fenced_list->ops->destroy(fenced_list->ops); 497 498 FREE(fenced_list); 499} 500 501 502