pipebuffer: Temporarily allow simultaneous CPU writes.
authorJosé Fonseca <jrfonseca@tungstengraphics.com>
Tue, 22 Apr 2008 10:47:02 +0000 (19:47 +0900)
committerJosé Fonseca <jrfonseca@tungstengraphics.com>
Tue, 22 Apr 2008 10:47:12 +0000 (19:47 +0900)
Also, fast path for re-fencing the same buffer multiple times with the same fence.

src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.c

index 65b6584003a7d69dddb1b7ca850363541eec9a05..27032b0c4c021a828d75288122a2543d6216bded 100644 (file)
@@ -215,15 +215,21 @@ fenced_buffer_serialize(struct fenced_buffer *fenced_buf, unsigned flags)
    struct fenced_buffer_list *fenced_list = fenced_buf->list;
    struct pipe_winsys *winsys = fenced_list->winsys;
 
+   /* Allow concurrent reads */
    if(((fenced_buf->flags | flags) & PIPE_BUFFER_USAGE_WRITE) == 0)
       return PIPE_OK;
 
+   /* Wait for the CPU to finish */
    if(fenced_buf->mapcount) {
-      /* FIXME */
+      /* FIXME: Use thread conditions variables to signal when mapcount 
+       * reaches zero */
       debug_warning("attemp to write concurrently to buffer");
+      /* XXX: we must not fail here in order to support texture mipmap generation
       return PIPE_ERROR_RETRY;
+       */
    }
 
+   /* Wait for the GPU to finish */
    if(fenced_buf->fence) {
       if(winsys->fence_finish(winsys, fenced_buf->fence, 0) != 0)
         return PIPE_ERROR_RETRY; 
@@ -353,6 +359,16 @@ buffer_fence(struct pb_buffer *buf,
    /* FIXME: receive this as a parameter */
    unsigned flags = fence ? PIPE_BUFFER_USAGE_GPU_READ_WRITE : 0;
    
+   if(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;
+   }
+   
    if(fenced_buffer_serialize(fenced_buf, flags) != PIPE_OK) {
       /* FIXME: propagate error */
       (void)0;