xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/d3d12/d3d12_fence.cpp (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © Microsoft Corporation
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 "d3d12_fence.h"
25 
26 #include "d3d12_context.h"
27 #include "d3d12_screen.h"
28 
29 #include "util/u_memory.h"
30 
31 #include <dxguids/dxguids.h>
32 
33 static void
destroy_fence(struct d3d12_fence * fence)34 destroy_fence(struct d3d12_fence *fence)
35 {
36    d3d12_fence_close_event(fence->event, fence->event_fd);
37    FREE(fence);
38 }
39 
40 struct d3d12_fence *
d3d12_create_fence(struct d3d12_screen * screen)41 d3d12_create_fence(struct d3d12_screen *screen)
42 {
43    struct d3d12_fence *ret = CALLOC_STRUCT(d3d12_fence);
44    if (!ret) {
45       debug_printf("CALLOC_STRUCT failed\n");
46       return NULL;
47    }
48 
49    ret->cmdqueue_fence = screen->fence;
50    ret->value = ++screen->fence_value;
51    ret->event = d3d12_fence_create_event(&ret->event_fd);
52    if (FAILED(screen->cmdqueue->Signal(screen->fence, ret->value)))
53       goto fail;
54    if (FAILED(screen->fence->SetEventOnCompletion(ret->value, ret->event)))
55       goto fail;
56 
57    pipe_reference_init(&ret->reference, 1);
58    return ret;
59 
60 fail:
61    destroy_fence(ret);
62    return NULL;
63 }
64 
65 struct d3d12_fence *
d3d12_open_fence(struct d3d12_screen * screen,HANDLE handle,const void * name)66 d3d12_open_fence(struct d3d12_screen *screen, HANDLE handle, const void *name)
67 {
68    struct d3d12_fence *ret = CALLOC_STRUCT(d3d12_fence);
69    if (!ret) {
70       debug_printf("CALLOC_STRUCT failed\n");
71       return NULL;
72    }
73 
74    HANDLE handle_to_close = nullptr;
75    assert(!!handle ^ !!name);
76    if (name) {
77       screen->dev->OpenSharedHandleByName((LPCWSTR)name, GENERIC_ALL, &handle_to_close);
78       handle = handle_to_close;
79    }
80 
81    screen->dev->OpenSharedHandle(handle, IID_PPV_ARGS(&ret->cmdqueue_fence));
82    if (!ret->cmdqueue_fence) {
83       free(ret);
84       return NULL;
85    }
86 
87    /* A new value will be assigned later */
88    ret->value = 0;
89    pipe_reference_init(&ret->reference, 1);
90    return ret;
91 }
92 
93 void
d3d12_fence_reference(struct d3d12_fence ** ptr,struct d3d12_fence * fence)94 d3d12_fence_reference(struct d3d12_fence **ptr, struct d3d12_fence *fence)
95 {
96    if (pipe_reference(&(*ptr)->reference, &fence->reference))
97       destroy_fence((struct d3d12_fence *)*ptr);
98 
99    *ptr = fence;
100 }
101 
102 static void
fence_reference(struct pipe_screen * pscreen,struct pipe_fence_handle ** pptr,struct pipe_fence_handle * pfence)103 fence_reference(struct pipe_screen *pscreen,
104                 struct pipe_fence_handle **pptr,
105                 struct pipe_fence_handle *pfence)
106 {
107    d3d12_fence_reference((struct d3d12_fence **)pptr, d3d12_fence(pfence));
108 }
109 
110 bool
d3d12_fence_finish(struct d3d12_fence * fence,uint64_t timeout_ns)111 d3d12_fence_finish(struct d3d12_fence *fence, uint64_t timeout_ns)
112 {
113    if (fence->signaled)
114       return true;
115 
116    bool complete = fence->cmdqueue_fence->GetCompletedValue() >= fence->value;
117    if (!complete && timeout_ns)
118       complete = d3d12_fence_wait_event(fence->event, fence->event_fd, timeout_ns);
119 
120    fence->signaled = complete;
121    return complete;
122 }
123 
124 static bool
fence_finish(struct pipe_screen * pscreen,struct pipe_context * pctx,struct pipe_fence_handle * pfence,uint64_t timeout_ns)125 fence_finish(struct pipe_screen *pscreen, struct pipe_context *pctx,
126              struct pipe_fence_handle *pfence, uint64_t timeout_ns)
127 {
128    bool ret = d3d12_fence_finish(d3d12_fence(pfence), timeout_ns);
129    if (ret && pctx) {
130       pctx = threaded_context_unwrap_sync(pctx);
131       struct d3d12_context *ctx = d3d12_context(pctx);
132       d3d12_foreach_submitted_batch(ctx, batch)
133          d3d12_reset_batch(ctx, batch, 0);
134    }
135    return ret;
136 }
137 
138 void
d3d12_screen_fence_init(struct pipe_screen * pscreen)139 d3d12_screen_fence_init(struct pipe_screen *pscreen)
140 {
141    pscreen->fence_reference = fence_reference;
142    pscreen->fence_finish = fence_finish;
143 }
144