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 */ 33void 34swr_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 */ 59static inline void 60swr_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 */ 80template<bool aligned_free> 81static void 82swr_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 90static void 91swr_delete_vs_cb(struct swr_fence_work *work) 92{ 93 delete work->free.swr_vs; 94} 95 96static void 97swr_delete_fs_cb(struct swr_fence_work *work) 98{ 99 delete work->free.swr_fs; 100} 101 102static void 103swr_delete_gs_cb(struct swr_fence_work *work) 104{ 105 delete work->free.swr_gs; 106} 107 108static void 109swr_delete_tcs_cb(struct swr_fence_work *work) 110{ 111 delete work->free.swr_tcs; 112} 113 114static void 115swr_delete_tes_cb(struct swr_fence_work *work) 116{ 117 delete work->free.swr_tes; 118} 119 120 121bool 122swr_fence_work_free(struct pipe_fence_handle *fence, void *data, 123 bool aligned_free) 124{ 125 struct swr_fence_work *work = CALLOC_STRUCT(swr_fence_work); 126 if (!work) 127 return false; 128 if (aligned_free) 129 work->callback = swr_free_cb<true>; 130 else 131 work->callback = swr_free_cb<false>; 132 work->free.data = data; 133 134 swr_add_fence_work(fence, work); 135 136 return true; 137} 138 139bool 140swr_fence_work_delete_vs(struct pipe_fence_handle *fence, 141 struct swr_vertex_shader *swr_vs) 142{ 143 struct swr_fence_work *work = CALLOC_STRUCT(swr_fence_work); 144 if (!work) 145 return false; 146 work->callback = swr_delete_vs_cb; 147 work->free.swr_vs = swr_vs; 148 149 swr_add_fence_work(fence, work); 150 151 return true; 152} 153 154bool 155swr_fence_work_delete_fs(struct pipe_fence_handle *fence, 156 struct swr_fragment_shader *swr_fs) 157{ 158 struct swr_fence_work *work = CALLOC_STRUCT(swr_fence_work); 159 if (!work) 160 return false; 161 work->callback = swr_delete_fs_cb; 162 work->free.swr_fs = swr_fs; 163 164 swr_add_fence_work(fence, work); 165 166 return true; 167} 168 169bool 170swr_fence_work_delete_gs(struct pipe_fence_handle *fence, 171 struct swr_geometry_shader *swr_gs) 172{ 173 struct swr_fence_work *work = CALLOC_STRUCT(swr_fence_work); 174 if (!work) 175 return false; 176 work->callback = swr_delete_gs_cb; 177 work->free.swr_gs = swr_gs; 178 179 swr_add_fence_work(fence, work); 180 181 return true; 182} 183 184bool 185swr_fence_work_delete_tcs(struct pipe_fence_handle *fence, 186 struct swr_tess_control_shader *swr_tcs) 187{ 188 struct swr_fence_work *work = CALLOC_STRUCT(swr_fence_work); 189 if (!work) 190 return false; 191 work->callback = swr_delete_tcs_cb; 192 work->free.swr_tcs = swr_tcs; 193 194 swr_add_fence_work(fence, work); 195 196 return true; 197} 198 199 200bool 201swr_fence_work_delete_tes(struct pipe_fence_handle *fence, 202 struct swr_tess_evaluation_shader *swr_tes) 203{ 204 struct swr_fence_work *work = CALLOC_STRUCT(swr_fence_work); 205 if (!work) 206 return false; 207 work->callback = swr_delete_tes_cb; 208 work->free.swr_tes = swr_tes; 209 210 swr_add_fence_work(fence, work); 211 212 return true; 213}