Home | History | Annotate | Download | only in swr
      1 /****************************************************************************
      2  * Copyright (C) 2015 Intel Corporation.   All Rights Reserved.
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the "Software"),
      6  * to deal in the Software without restriction, including without limitation
      7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8  * and/or sell copies of the Software, and to permit persons to whom the
      9  * Software is furnished to do so, subject to the following conditions:
     10  *
     11  * The above copyright notice and this permission notice (including the next
     12  * paragraph) shall be included in all copies or substantial portions of the
     13  * Software.
     14  *
     15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
     21  * IN THE SOFTWARE.
     22  ***************************************************************************/
     23 
     24 #include "pipe/p_screen.h"
     25 #include "util/u_memory.h"
     26 #include "os/os_time.h"
     27 
     28 #include "swr_context.h"
     29 #include "swr_screen.h"
     30 #include "swr_fence.h"
     31 
     32 #if defined(PIPE_CC_MSVC) // portable thread yield
     33    #define sched_yield SwitchToThread
     34 #endif
     35 
     36 /*
     37  * Fence callback, called by back-end thread on completion of all rendering up
     38  * to SwrSync call.
     39  */
     40 static void
     41 swr_fence_cb(uint64_t userData, uint64_t userData2, uint64_t userData3)
     42 {
     43    struct swr_fence *fence = (struct swr_fence *)userData;
     44 
     45    /* Complete all work attached to the fence */
     46    swr_fence_do_work(fence);
     47 
     48    /* Correct value is in SwrSync data, and not the fence write field. */
     49    fence->read = userData2;
     50 }
     51 
     52 /*
     53  * Submit an existing fence.
     54  */
     55 void
     56 swr_fence_submit(struct swr_context *ctx, struct pipe_fence_handle *fh)
     57 {
     58    struct swr_fence *fence = swr_fence(fh);
     59 
     60    fence->write++;
     61    fence->pending = TRUE;
     62    SwrSync(ctx->swrContext, swr_fence_cb, (uint64_t)fence, fence->write, 0);
     63 }
     64 
     65 /*
     66  * Create a new fence object.
     67  */
     68 struct pipe_fence_handle *
     69 swr_fence_create()
     70 {
     71    static int fence_id = 0;
     72    struct swr_fence *fence = CALLOC_STRUCT(swr_fence);
     73    if (!fence)
     74       return NULL;
     75 
     76    pipe_reference_init(&fence->reference, 1);
     77    fence->id = fence_id++;
     78    fence->work.tail = &fence->work.head;
     79 
     80    return (struct pipe_fence_handle *)fence;
     81 }
     82 
     83 /** Destroy a fence.  Called when refcount hits zero. */
     84 static void
     85 swr_fence_destroy(struct swr_fence *fence)
     86 {
     87    /* Complete any work left if fence was not submitted */
     88    swr_fence_do_work(fence);
     89    FREE(fence);
     90 }
     91 
     92 /**
     93  * Set ptr = fence, with reference counting
     94  */
     95 void
     96 swr_fence_reference(struct pipe_screen *screen,
     97                     struct pipe_fence_handle **ptr,
     98                     struct pipe_fence_handle *f)
     99 {
    100    struct swr_fence *fence = swr_fence(f);
    101    struct swr_fence *old;
    102 
    103    if (likely(ptr)) {
    104       old = swr_fence(*ptr);
    105       *ptr = f;
    106    } else {
    107       old = NULL;
    108    }
    109 
    110    if (pipe_reference(&old->reference, &fence->reference)) {
    111       swr_fence_finish(screen, NULL, (struct pipe_fence_handle *) old, 0);
    112       swr_fence_destroy(old);
    113    }
    114 }
    115 
    116 
    117 /*
    118  * Wait for the fence to finish.
    119  */
    120 boolean
    121 swr_fence_finish(struct pipe_screen *screen,
    122                  struct pipe_context *ctx,
    123                  struct pipe_fence_handle *fence_handle,
    124                  uint64_t timeout)
    125 {
    126    while (!swr_is_fence_done(fence_handle))
    127       sched_yield();
    128 
    129    swr_fence(fence_handle)->pending = FALSE;
    130 
    131    return TRUE;
    132 }
    133 
    134 
    135 uint64_t
    136 swr_get_timestamp(struct pipe_screen *screen)
    137 {
    138    return os_time_get_nano();
    139 }
    140 
    141 
    142 void
    143 swr_fence_init(struct pipe_screen *p_screen)
    144 {
    145    p_screen->fence_reference = swr_fence_reference;
    146    p_screen->fence_finish = swr_fence_finish;
    147    p_screen->get_timestamp = swr_get_timestamp;
    148 
    149    /* Create persistant StoreTiles "flush" fence, used to signal completion
    150     * of flushing tile state back to resource texture, via StoreTiles. */
    151    struct swr_screen *screen = swr_screen(p_screen);
    152    screen->flush_fence = swr_fence_create();
    153 }
    154