2
* Copyright © 2021 Intel Corporation
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:
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
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
29
#include "util/debug.h"
30
#include "util/macros.h"
31
#include "util/os_time.h"
34
#include "vk_device.h"
38
vk_sync_type_validate(const struct vk_sync_type *type)
43
assert(type->features & (VK_SYNC_FEATURE_BINARY |
44
VK_SYNC_FEATURE_TIMELINE));
46
if (type->features & VK_SYNC_FEATURE_TIMELINE) {
47
assert(type->features & VK_SYNC_FEATURE_GPU_WAIT);
48
assert(type->features & VK_SYNC_FEATURE_CPU_WAIT);
49
assert(type->features & VK_SYNC_FEATURE_CPU_SIGNAL);
50
assert(type->features & (VK_SYNC_FEATURE_WAIT_BEFORE_SIGNAL |
51
VK_SYNC_FEATURE_WAIT_PENDING));
53
assert(type->get_value);
56
if (!(type->features & VK_SYNC_FEATURE_BINARY)) {
57
assert(!(type->features & (VK_SYNC_FEATURE_GPU_MULTI_WAIT |
58
VK_SYNC_FEATURE_CPU_RESET)));
59
assert(!type->import_sync_file);
60
assert(!type->export_sync_file);
63
if (type->features & VK_SYNC_FEATURE_CPU_WAIT) {
64
assert(type->wait || type->wait_many);
66
assert(!(type->features & (VK_SYNC_FEATURE_WAIT_ANY |
67
VK_SYNC_FEATURE_WAIT_PENDING)));
70
if (type->features & VK_SYNC_FEATURE_GPU_MULTI_WAIT)
71
assert(type->features & VK_SYNC_FEATURE_GPU_WAIT);
73
if (type->features & VK_SYNC_FEATURE_CPU_RESET)
76
if (type->features & VK_SYNC_FEATURE_CPU_SIGNAL)
81
vk_sync_init(struct vk_device *device,
83
const struct vk_sync_type *type,
84
enum vk_sync_flags flags,
85
uint64_t initial_value)
87
vk_sync_type_validate(type);
89
if (flags & VK_SYNC_IS_TIMELINE)
90
assert(type->features & VK_SYNC_FEATURE_TIMELINE);
92
assert(type->features & VK_SYNC_FEATURE_BINARY);
94
assert(type->size >= sizeof(*sync));
95
memset(sync, 0, type->size);
99
return type->init(device, sync, initial_value);
103
vk_sync_finish(struct vk_device *device,
104
struct vk_sync *sync)
106
sync->type->finish(device, sync);
110
vk_sync_create(struct vk_device *device,
111
const struct vk_sync_type *type,
112
enum vk_sync_flags flags,
113
uint64_t initial_value,
114
struct vk_sync **sync_out)
116
struct vk_sync *sync;
118
sync = vk_alloc(&device->alloc, type->size, 8,
119
VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
121
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
123
VkResult result = vk_sync_init(device, sync, type, flags, initial_value);
124
if (result != VK_SUCCESS) {
125
vk_free(&device->alloc, sync);
135
vk_sync_destroy(struct vk_device *device,
136
struct vk_sync *sync)
138
vk_sync_finish(device, sync);
139
vk_free(&device->alloc, sync);
143
vk_sync_signal(struct vk_device *device,
144
struct vk_sync *sync,
147
assert(sync->type->features & VK_SYNC_FEATURE_CPU_SIGNAL);
149
if (sync->flags & VK_SYNC_IS_TIMELINE)
154
return sync->type->signal(device, sync, value);
158
vk_sync_get_value(struct vk_device *device,
159
struct vk_sync *sync,
162
assert(sync->flags & VK_SYNC_IS_TIMELINE);
163
return sync->type->get_value(device, sync, value);
167
vk_sync_reset(struct vk_device *device,
168
struct vk_sync *sync)
170
assert(sync->type->features & VK_SYNC_FEATURE_CPU_RESET);
171
assert(!(sync->flags & VK_SYNC_IS_TIMELINE));
172
return sync->type->reset(device, sync);
175
VkResult vk_sync_move(struct vk_device *device,
179
assert(!(dst->flags & VK_SYNC_IS_TIMELINE));
180
assert(!(src->flags & VK_SYNC_IS_TIMELINE));
181
assert(dst->type == src->type);
183
return src->type->move(device, dst, src);
187
assert_valid_wait(struct vk_sync *sync,
189
enum vk_sync_wait_flags wait_flags)
191
assert(sync->type->features & VK_SYNC_FEATURE_CPU_WAIT);
193
if (!(sync->flags & VK_SYNC_IS_TIMELINE))
194
assert(wait_value == 0);
196
if (wait_flags & VK_SYNC_WAIT_PENDING)
197
assert(sync->type->features & VK_SYNC_FEATURE_WAIT_PENDING);
201
get_max_abs_timeout_ns(void)
203
static int max_timeout_ms = -1;
204
if (max_timeout_ms < 0)
205
max_timeout_ms = env_var_as_unsigned("MESA_VK_MAX_TIMEOUT", 0);
207
if (max_timeout_ms == 0)
210
return os_time_get_absolute_timeout(max_timeout_ms * 1000000ull);
214
__vk_sync_wait(struct vk_device *device,
215
struct vk_sync *sync,
217
enum vk_sync_wait_flags wait_flags,
218
uint64_t abs_timeout_ns)
220
assert_valid_wait(sync, wait_value, wait_flags);
222
/* This doesn't make sense for a single wait */
223
assert(!(wait_flags & VK_SYNC_WAIT_ANY));
225
if (sync->type->wait) {
226
return sync->type->wait(device, sync, wait_value,
227
wait_flags, abs_timeout_ns);
229
struct vk_sync_wait wait = {
231
.stage_mask = ~(VkPipelineStageFlags2KHR)0,
232
.wait_value = wait_value,
234
return sync->type->wait_many(device, 1, &wait, wait_flags,
240
vk_sync_wait(struct vk_device *device,
241
struct vk_sync *sync,
243
enum vk_sync_wait_flags wait_flags,
244
uint64_t abs_timeout_ns)
246
uint64_t max_abs_timeout_ns = get_max_abs_timeout_ns();
247
if (abs_timeout_ns > max_abs_timeout_ns) {
249
__vk_sync_wait(device, sync, wait_value, wait_flags,
251
if (unlikely(result == VK_TIMEOUT))
252
return vk_device_set_lost(device, "Maximum timeout exceeded!");
255
return __vk_sync_wait(device, sync, wait_value, wait_flags,
261
can_wait_many(uint32_t wait_count,
262
const struct vk_sync_wait *waits,
263
enum vk_sync_wait_flags wait_flags)
265
if (waits[0].sync->type->wait_many == NULL)
268
if ((wait_flags & VK_SYNC_WAIT_ANY) &&
269
!(waits[0].sync->type->features & VK_SYNC_FEATURE_WAIT_ANY))
272
for (uint32_t i = 0; i < wait_count; i++) {
273
assert_valid_wait(waits[i].sync, waits[i].wait_value, wait_flags);
274
if (waits[i].sync->type != waits[0].sync->type)
282
__vk_sync_wait_many(struct vk_device *device,
284
const struct vk_sync_wait *waits,
285
enum vk_sync_wait_flags wait_flags,
286
uint64_t abs_timeout_ns)
291
if (wait_count == 1) {
292
return __vk_sync_wait(device, waits[0].sync, waits[0].wait_value,
293
wait_flags & ~VK_SYNC_WAIT_ANY, abs_timeout_ns);
296
if (can_wait_many(wait_count, waits, wait_flags)) {
297
return waits[0].sync->type->wait_many(device, wait_count, waits,
298
wait_flags, abs_timeout_ns);
299
} else if (wait_flags & VK_SYNC_WAIT_ANY) {
300
/* If we have multiple syncs and they don't support wait_any or they're
301
* not all the same type, there's nothing better we can do than spin.
304
for (uint32_t i = 0; i < wait_count; i++) {
305
VkResult result = __vk_sync_wait(device, waits[i].sync,
307
wait_flags & ~VK_SYNC_WAIT_ANY,
308
0 /* abs_timeout_ns */);
309
if (result != VK_TIMEOUT)
312
} while (os_time_get_nano() < abs_timeout_ns);
316
for (uint32_t i = 0; i < wait_count; i++) {
317
VkResult result = __vk_sync_wait(device, waits[i].sync,
319
wait_flags, abs_timeout_ns);
320
if (result != VK_SUCCESS)
328
vk_sync_wait_many(struct vk_device *device,
330
const struct vk_sync_wait *waits,
331
enum vk_sync_wait_flags wait_flags,
332
uint64_t abs_timeout_ns)
334
uint64_t max_abs_timeout_ns = get_max_abs_timeout_ns();
335
if (abs_timeout_ns > max_abs_timeout_ns) {
337
__vk_sync_wait_many(device, wait_count, waits, wait_flags,
339
if (unlikely(result == VK_TIMEOUT))
340
return vk_device_set_lost(device, "Maximum timeout exceeded!");
343
return __vk_sync_wait_many(device, wait_count, waits, wait_flags,
349
vk_sync_import_opaque_fd(struct vk_device *device,
350
struct vk_sync *sync,
353
VkResult result = sync->type->import_opaque_fd(device, sync, fd);
354
if (unlikely(result != VK_SUCCESS))
357
sync->flags |= VK_SYNC_IS_SHAREABLE |
364
vk_sync_export_opaque_fd(struct vk_device *device,
365
struct vk_sync *sync,
368
assert(sync->flags & VK_SYNC_IS_SHAREABLE);
370
VkResult result = sync->type->export_opaque_fd(device, sync, fd);
371
if (unlikely(result != VK_SUCCESS))
374
sync->flags |= VK_SYNC_IS_SHARED;
380
vk_sync_import_sync_file(struct vk_device *device,
381
struct vk_sync *sync,
384
assert(!(sync->flags & VK_SYNC_IS_TIMELINE));
386
/* Silently handle negative file descriptors in case the driver doesn't
389
if (sync_file < 0 && sync->type->signal)
390
return sync->type->signal(device, sync, 0);
392
return sync->type->import_sync_file(device, sync, sync_file);
396
vk_sync_export_sync_file(struct vk_device *device,
397
struct vk_sync *sync,
400
assert(!(sync->flags & VK_SYNC_IS_TIMELINE));
401
return sync->type->export_sync_file(device, sync, sync_file);