1 /**************************************************************************** 2 * Copyright (C) 2016 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 "swr_context.h" 25 #include "swr_fence.h" 26 27 #include "util/u_inlines.h" 28 #include "util/u_memory.h" 29 30 /* 31 * Called by swr_fence_cb to complete the work queue 32 */ 33 void 34 swr_fence_do_work(struct swr_fence *fence) 35 { 36 struct swr_fence_work *work, *tmp; 37 38 if (fence->work.head.next) { 39 work = fence->work.head.next; 40 /* Immediately clear the head so any new work gets added to a new work 41 * queue */ 42 p_atomic_set(&fence->work.head.next, 0); 43 p_atomic_set(&fence->work.tail, &fence->work.head); 44 p_atomic_set(&fence->work.count, 0); 45 46 do { 47 tmp = work->next; 48 work->callback(work); 49 FREE(work); 50 work = tmp; 51 } while(work); 52 } 53 } 54 55 56 /* 57 * Called by one of the specialized work routines below 58 */ 59 static inline void 60 swr_add_fence_work(struct pipe_fence_handle *fh, 61 struct swr_fence_work *work) 62 { 63 /* If no fence, just do the work now */ 64 if (!fh) { 65 work->callback(work); 66 FREE(work); 67 return; 68 } 69 70 struct swr_fence *fence = swr_fence(fh); 71 p_atomic_set(&fence->work.tail->next, work); 72 p_atomic_set(&fence->work.tail, work); 73 p_atomic_inc(&fence->work.count); 74 } 75 76 77 /* 78 * Generic free/free_aligned, and delete vs/fs 79 */ 80 template<bool aligned_free> 81 static void 82 swr_free_cb(struct swr_fence_work *work) 83 { 84 if (aligned_free) 85 AlignedFree(work->free.data); 86 else 87 FREE(work->free.data); 88 } 89 90 static void 91 swr_delete_vs_cb(struct swr_fence_work *work) 92 { 93 delete work->free.swr_vs; 94 } 95 96 static void 97 swr_delete_fs_cb(struct swr_fence_work *work) 98 { 99 delete work->free.swr_fs; 100 } 101 102 static void 103 swr_delete_gs_cb(struct swr_fence_work *work) 104 { 105 delete work->free.swr_gs; 106 } 107 108 bool 109 swr_fence_work_free(struct pipe_fence_handle *fence, void *data, 110 bool aligned_free) 111 { 112 struct swr_fence_work *work = CALLOC_STRUCT(swr_fence_work); 113 if (!work) 114 return false; 115 if (aligned_free) 116 work->callback = swr_free_cb<true>; 117 else 118 work->callback = swr_free_cb<false>; 119 work->free.data = data; 120 121 swr_add_fence_work(fence, work); 122 123 return true; 124 } 125 126 bool 127 swr_fence_work_delete_vs(struct pipe_fence_handle *fence, 128 struct swr_vertex_shader *swr_vs) 129 { 130 struct swr_fence_work *work = CALLOC_STRUCT(swr_fence_work); 131 if (!work) 132 return false; 133 work->callback = swr_delete_vs_cb; 134 work->free.swr_vs = swr_vs; 135 136 swr_add_fence_work(fence, work); 137 138 return true; 139 } 140 141 bool 142 swr_fence_work_delete_fs(struct pipe_fence_handle *fence, 143 struct swr_fragment_shader *swr_fs) 144 { 145 struct swr_fence_work *work = CALLOC_STRUCT(swr_fence_work); 146 if (!work) 147 return false; 148 work->callback = swr_delete_fs_cb; 149 work->free.swr_fs = swr_fs; 150 151 swr_add_fence_work(fence, work); 152 153 return true; 154 } 155 156 bool 157 swr_fence_work_delete_gs(struct pipe_fence_handle *fence, 158 struct swr_geometry_shader *swr_gs) 159 { 160 struct swr_fence_work *work = CALLOC_STRUCT(swr_fence_work); 161 if (!work) 162 return false; 163 work->callback = swr_delete_gs_cb; 164 work->free.swr_gs = swr_gs; 165 166 swr_add_fence_work(fence, work); 167 168 return true; 169 } 170