1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © Microsoft Corporation 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21bf215546Sopenharmony_ci * IN THE SOFTWARE. 22bf215546Sopenharmony_ci */ 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci#include "d3d12_fence.h" 25bf215546Sopenharmony_ci 26bf215546Sopenharmony_ci#include "d3d12_context.h" 27bf215546Sopenharmony_ci#include "d3d12_screen.h" 28bf215546Sopenharmony_ci 29bf215546Sopenharmony_ci#include "util/u_memory.h" 30bf215546Sopenharmony_ci 31bf215546Sopenharmony_ci#include <dxguids/dxguids.h> 32bf215546Sopenharmony_ci 33bf215546Sopenharmony_ciconstexpr uint64_t NsPerMs = 1000000; 34bf215546Sopenharmony_ciconstexpr uint64_t MaxTimeoutInNs = (uint64_t)UINT_MAX * NsPerMs; 35bf215546Sopenharmony_ci 36bf215546Sopenharmony_ci#ifdef _WIN32 37bf215546Sopenharmony_cistatic void 38bf215546Sopenharmony_ciclose_event(HANDLE event, int fd) 39bf215546Sopenharmony_ci{ 40bf215546Sopenharmony_ci if (event) 41bf215546Sopenharmony_ci CloseHandle(event); 42bf215546Sopenharmony_ci} 43bf215546Sopenharmony_ci 44bf215546Sopenharmony_cistatic HANDLE 45bf215546Sopenharmony_cicreate_event(int *fd) 46bf215546Sopenharmony_ci{ 47bf215546Sopenharmony_ci *fd = -1; 48bf215546Sopenharmony_ci return CreateEvent(NULL, FALSE, FALSE, NULL); 49bf215546Sopenharmony_ci} 50bf215546Sopenharmony_ci 51bf215546Sopenharmony_cistatic bool 52bf215546Sopenharmony_ciwait_event(HANDLE event, int event_fd, uint64_t timeout_ns) 53bf215546Sopenharmony_ci{ 54bf215546Sopenharmony_ci DWORD timeout_ms = (timeout_ns == PIPE_TIMEOUT_INFINITE || timeout_ns > MaxTimeoutInNs) ? INFINITE : timeout_ns / NsPerMs; 55bf215546Sopenharmony_ci return WaitForSingleObject(event, timeout_ms) == WAIT_OBJECT_0; 56bf215546Sopenharmony_ci} 57bf215546Sopenharmony_ci#else 58bf215546Sopenharmony_ci#include <sys/eventfd.h> 59bf215546Sopenharmony_ci#include <poll.h> 60bf215546Sopenharmony_ci#include <util/libsync.h> 61bf215546Sopenharmony_ci 62bf215546Sopenharmony_cistatic void 63bf215546Sopenharmony_ciclose_event(HANDLE event, int fd) 64bf215546Sopenharmony_ci{ 65bf215546Sopenharmony_ci if (fd != -1) 66bf215546Sopenharmony_ci close(fd); 67bf215546Sopenharmony_ci} 68bf215546Sopenharmony_ci 69bf215546Sopenharmony_cistatic HANDLE 70bf215546Sopenharmony_cicreate_event(int *fd) 71bf215546Sopenharmony_ci{ 72bf215546Sopenharmony_ci *fd = eventfd(0, 0); 73bf215546Sopenharmony_ci return (HANDLE)(size_t)*fd; 74bf215546Sopenharmony_ci} 75bf215546Sopenharmony_ci 76bf215546Sopenharmony_cistatic bool 77bf215546Sopenharmony_ciwait_event(HANDLE event, int event_fd, uint64_t timeout_ns) 78bf215546Sopenharmony_ci{ 79bf215546Sopenharmony_ci int timeout_ms = (timeout_ns == PIPE_TIMEOUT_INFINITE || timeout_ns > MaxTimeoutInNs) ? -1 : timeout_ns / NsPerMs; 80bf215546Sopenharmony_ci return sync_wait(event_fd, timeout_ms) == 0; 81bf215546Sopenharmony_ci} 82bf215546Sopenharmony_ci#endif 83bf215546Sopenharmony_ci 84bf215546Sopenharmony_cistatic void 85bf215546Sopenharmony_cidestroy_fence(struct d3d12_fence *fence) 86bf215546Sopenharmony_ci{ 87bf215546Sopenharmony_ci close_event(fence->event, fence->event_fd); 88bf215546Sopenharmony_ci FREE(fence); 89bf215546Sopenharmony_ci} 90bf215546Sopenharmony_ci 91bf215546Sopenharmony_cistruct d3d12_fence * 92bf215546Sopenharmony_cid3d12_create_fence(struct d3d12_screen *screen) 93bf215546Sopenharmony_ci{ 94bf215546Sopenharmony_ci struct d3d12_fence *ret = CALLOC_STRUCT(d3d12_fence); 95bf215546Sopenharmony_ci if (!ret) { 96bf215546Sopenharmony_ci debug_printf("CALLOC_STRUCT failed\n"); 97bf215546Sopenharmony_ci return NULL; 98bf215546Sopenharmony_ci } 99bf215546Sopenharmony_ci 100bf215546Sopenharmony_ci ret->cmdqueue_fence = screen->fence; 101bf215546Sopenharmony_ci ret->value = ++screen->fence_value; 102bf215546Sopenharmony_ci ret->event = create_event(&ret->event_fd); 103bf215546Sopenharmony_ci if (FAILED(screen->fence->SetEventOnCompletion(ret->value, ret->event))) 104bf215546Sopenharmony_ci goto fail; 105bf215546Sopenharmony_ci if (FAILED(screen->cmdqueue->Signal(screen->fence, ret->value))) 106bf215546Sopenharmony_ci goto fail; 107bf215546Sopenharmony_ci 108bf215546Sopenharmony_ci pipe_reference_init(&ret->reference, 1); 109bf215546Sopenharmony_ci return ret; 110bf215546Sopenharmony_ci 111bf215546Sopenharmony_cifail: 112bf215546Sopenharmony_ci destroy_fence(ret); 113bf215546Sopenharmony_ci return NULL; 114bf215546Sopenharmony_ci} 115bf215546Sopenharmony_ci 116bf215546Sopenharmony_cistruct d3d12_fence * 117bf215546Sopenharmony_cid3d12_open_fence(struct d3d12_screen *screen, HANDLE handle, const void *name) 118bf215546Sopenharmony_ci{ 119bf215546Sopenharmony_ci struct d3d12_fence *ret = CALLOC_STRUCT(d3d12_fence); 120bf215546Sopenharmony_ci if (!ret) { 121bf215546Sopenharmony_ci debug_printf("CALLOC_STRUCT failed\n"); 122bf215546Sopenharmony_ci return NULL; 123bf215546Sopenharmony_ci } 124bf215546Sopenharmony_ci 125bf215546Sopenharmony_ci HANDLE handle_to_close = nullptr; 126bf215546Sopenharmony_ci assert(!!handle ^ !!name); 127bf215546Sopenharmony_ci if (name) { 128bf215546Sopenharmony_ci screen->dev->OpenSharedHandleByName((LPCWSTR)name, GENERIC_ALL, &handle_to_close); 129bf215546Sopenharmony_ci handle = handle_to_close; 130bf215546Sopenharmony_ci } 131bf215546Sopenharmony_ci 132bf215546Sopenharmony_ci screen->dev->OpenSharedHandle(handle, IID_PPV_ARGS(&ret->cmdqueue_fence)); 133bf215546Sopenharmony_ci if (!ret->cmdqueue_fence) { 134bf215546Sopenharmony_ci free(ret); 135bf215546Sopenharmony_ci return NULL; 136bf215546Sopenharmony_ci } 137bf215546Sopenharmony_ci 138bf215546Sopenharmony_ci /* A new value will be assigned later */ 139bf215546Sopenharmony_ci ret->value = 0; 140bf215546Sopenharmony_ci pipe_reference_init(&ret->reference, 1); 141bf215546Sopenharmony_ci return ret; 142bf215546Sopenharmony_ci} 143bf215546Sopenharmony_ci 144bf215546Sopenharmony_civoid 145bf215546Sopenharmony_cid3d12_fence_reference(struct d3d12_fence **ptr, struct d3d12_fence *fence) 146bf215546Sopenharmony_ci{ 147bf215546Sopenharmony_ci if (pipe_reference(&(*ptr)->reference, &fence->reference)) 148bf215546Sopenharmony_ci destroy_fence((struct d3d12_fence *)*ptr); 149bf215546Sopenharmony_ci 150bf215546Sopenharmony_ci *ptr = fence; 151bf215546Sopenharmony_ci} 152bf215546Sopenharmony_ci 153bf215546Sopenharmony_cistatic void 154bf215546Sopenharmony_cifence_reference(struct pipe_screen *pscreen, 155bf215546Sopenharmony_ci struct pipe_fence_handle **pptr, 156bf215546Sopenharmony_ci struct pipe_fence_handle *pfence) 157bf215546Sopenharmony_ci{ 158bf215546Sopenharmony_ci d3d12_fence_reference((struct d3d12_fence **)pptr, d3d12_fence(pfence)); 159bf215546Sopenharmony_ci} 160bf215546Sopenharmony_ci 161bf215546Sopenharmony_cibool 162bf215546Sopenharmony_cid3d12_fence_finish(struct d3d12_fence *fence, uint64_t timeout_ns) 163bf215546Sopenharmony_ci{ 164bf215546Sopenharmony_ci if (fence->signaled) 165bf215546Sopenharmony_ci return true; 166bf215546Sopenharmony_ci 167bf215546Sopenharmony_ci bool complete = fence->cmdqueue_fence->GetCompletedValue() >= fence->value; 168bf215546Sopenharmony_ci if (!complete && timeout_ns) 169bf215546Sopenharmony_ci complete = wait_event(fence->event, fence->event_fd, timeout_ns); 170bf215546Sopenharmony_ci 171bf215546Sopenharmony_ci fence->signaled = complete; 172bf215546Sopenharmony_ci return complete; 173bf215546Sopenharmony_ci} 174bf215546Sopenharmony_ci 175bf215546Sopenharmony_cistatic bool 176bf215546Sopenharmony_cifence_finish(struct pipe_screen *pscreen, struct pipe_context *pctx, 177bf215546Sopenharmony_ci struct pipe_fence_handle *pfence, uint64_t timeout_ns) 178bf215546Sopenharmony_ci{ 179bf215546Sopenharmony_ci bool ret = d3d12_fence_finish(d3d12_fence(pfence), timeout_ns); 180bf215546Sopenharmony_ci if (ret && pctx) { 181bf215546Sopenharmony_ci pctx = threaded_context_unwrap_sync(pctx); 182bf215546Sopenharmony_ci struct d3d12_context *ctx = d3d12_context(pctx); 183bf215546Sopenharmony_ci d3d12_foreach_submitted_batch(ctx, batch) 184bf215546Sopenharmony_ci d3d12_reset_batch(ctx, batch, 0); 185bf215546Sopenharmony_ci } 186bf215546Sopenharmony_ci return ret; 187bf215546Sopenharmony_ci} 188bf215546Sopenharmony_ci 189bf215546Sopenharmony_civoid 190bf215546Sopenharmony_cid3d12_screen_fence_init(struct pipe_screen *pscreen) 191bf215546Sopenharmony_ci{ 192bf215546Sopenharmony_ci pscreen->fence_reference = fence_reference; 193bf215546Sopenharmony_ci pscreen->fence_finish = fence_finish; 194bf215546Sopenharmony_ci} 195