Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/vulkan/util/vk_object.c
7130 views
1
/*
2
* Copyright © 2020 Intel 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 "vk_object.h"
25
26
#include "vk_alloc.h"
27
#include "vk_common_entrypoints.h"
28
#include "vk_device.h"
29
#include "util/hash_table.h"
30
#include "util/ralloc.h"
31
32
static void
33
vk_object_base_reinit(struct vk_object_base *base)
34
{
35
base->_loader_data.loaderMagic = ICD_LOADER_MAGIC;
36
util_sparse_array_init(&base->private_data, sizeof(uint64_t), 8);
37
}
38
39
void
40
vk_object_base_init(struct vk_device *device,
41
struct vk_object_base *base,
42
UNUSED VkObjectType obj_type)
43
{
44
vk_object_base_reinit(base);
45
base->type = obj_type;
46
base->device = device;
47
}
48
49
void
50
vk_object_base_finish(struct vk_object_base *base)
51
{
52
util_sparse_array_finish(&base->private_data);
53
}
54
55
void
56
vk_object_base_reset(struct vk_object_base *base)
57
{
58
vk_object_base_finish(base);
59
vk_object_base_reinit(base);
60
}
61
62
void *
63
vk_object_alloc(struct vk_device *device,
64
const VkAllocationCallbacks *alloc,
65
size_t size,
66
VkObjectType obj_type)
67
{
68
void *ptr = vk_alloc2(&device->alloc, alloc, size, 8,
69
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
70
if (ptr == NULL)
71
return NULL;
72
73
vk_object_base_init(device, (struct vk_object_base *)ptr, obj_type);
74
75
return ptr;
76
}
77
78
void *
79
vk_object_zalloc(struct vk_device *device,
80
const VkAllocationCallbacks *alloc,
81
size_t size,
82
VkObjectType obj_type)
83
{
84
void *ptr = vk_zalloc2(&device->alloc, alloc, size, 8,
85
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
86
if (ptr == NULL)
87
return NULL;
88
89
vk_object_base_init(device, (struct vk_object_base *)ptr, obj_type);
90
91
return ptr;
92
}
93
94
void *
95
vk_object_multialloc(struct vk_device *device,
96
struct vk_multialloc *ma,
97
const VkAllocationCallbacks *alloc,
98
VkObjectType obj_type)
99
{
100
void *ptr = vk_multialloc_alloc2(ma, &device->alloc, alloc,
101
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
102
if (ptr == NULL)
103
return NULL;
104
105
vk_object_base_init(device, (struct vk_object_base *)ptr, obj_type);
106
107
return ptr;
108
}
109
110
void *
111
vk_object_multizalloc(struct vk_device *device,
112
struct vk_multialloc *ma,
113
const VkAllocationCallbacks *alloc,
114
VkObjectType obj_type)
115
{
116
void *ptr = vk_multialloc_alloc2(ma, &device->alloc, alloc,
117
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
118
if (ptr == NULL)
119
return NULL;
120
121
memset(ptr, 0, ma->size);
122
vk_object_base_init(device, (struct vk_object_base *)ptr, obj_type);
123
124
return ptr;
125
}
126
127
void
128
vk_object_free(struct vk_device *device,
129
const VkAllocationCallbacks *alloc,
130
void *data)
131
{
132
vk_object_base_finish((struct vk_object_base *)data);
133
vk_free2(&device->alloc, alloc, data);
134
}
135
136
VkResult
137
vk_private_data_slot_create(struct vk_device *device,
138
const VkPrivateDataSlotCreateInfoEXT* pCreateInfo,
139
const VkAllocationCallbacks* pAllocator,
140
VkPrivateDataSlotEXT* pPrivateDataSlot)
141
{
142
struct vk_private_data_slot *slot =
143
vk_alloc2(&device->alloc, pAllocator, sizeof(*slot), 8,
144
VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
145
if (slot == NULL)
146
return VK_ERROR_OUT_OF_HOST_MEMORY;
147
148
vk_object_base_init(device, &slot->base,
149
VK_OBJECT_TYPE_PRIVATE_DATA_SLOT_EXT);
150
slot->index = p_atomic_inc_return(&device->private_data_next_index);
151
152
*pPrivateDataSlot = vk_private_data_slot_to_handle(slot);
153
154
return VK_SUCCESS;
155
}
156
157
void
158
vk_private_data_slot_destroy(struct vk_device *device,
159
VkPrivateDataSlotEXT privateDataSlot,
160
const VkAllocationCallbacks *pAllocator)
161
{
162
VK_FROM_HANDLE(vk_private_data_slot, slot, privateDataSlot);
163
if (slot == NULL)
164
return;
165
166
vk_object_base_finish(&slot->base);
167
vk_free2(&device->alloc, pAllocator, slot);
168
}
169
170
#ifdef ANDROID
171
static VkResult
172
get_swapchain_private_data_locked(struct vk_device *device,
173
uint64_t objectHandle,
174
struct vk_private_data_slot *slot,
175
uint64_t **private_data)
176
{
177
if (unlikely(device->swapchain_private == NULL)) {
178
/* Even though VkSwapchain is a non-dispatchable object, we know a
179
* priori that Android swapchains are actually pointers so we can use
180
* the pointer hash table for them.
181
*/
182
device->swapchain_private = _mesa_pointer_hash_table_create(NULL);
183
if (device->swapchain_private == NULL)
184
return VK_ERROR_OUT_OF_HOST_MEMORY;
185
}
186
187
struct hash_entry *entry =
188
_mesa_hash_table_search(device->swapchain_private,
189
(void *)(uintptr_t)objectHandle);
190
if (unlikely(entry == NULL)) {
191
struct util_sparse_array *swapchain_private =
192
ralloc(device->swapchain_private, struct util_sparse_array);
193
util_sparse_array_init(swapchain_private, sizeof(uint64_t), 8);
194
195
entry = _mesa_hash_table_insert(device->swapchain_private,
196
(void *)(uintptr_t)objectHandle,
197
swapchain_private);
198
if (entry == NULL)
199
return VK_ERROR_OUT_OF_HOST_MEMORY;
200
}
201
202
struct util_sparse_array *swapchain_private = entry->data;
203
*private_data = util_sparse_array_get(swapchain_private, slot->index);
204
205
return VK_SUCCESS;
206
}
207
#endif /* ANDROID */
208
209
static VkResult
210
vk_object_base_private_data(struct vk_device *device,
211
VkObjectType objectType,
212
uint64_t objectHandle,
213
VkPrivateDataSlotEXT privateDataSlot,
214
uint64_t **private_data)
215
{
216
VK_FROM_HANDLE(vk_private_data_slot, slot, privateDataSlot);
217
218
#ifdef ANDROID
219
/* There is an annoying spec corner here on Android. Because WSI is
220
* implemented in the Vulkan loader which doesn't know about the
221
* VK_EXT_private_data extension, we have to handle VkSwapchainKHR in the
222
* driver as a special case. On future versions of Android where the
223
* loader does understand VK_EXT_private_data, we'll never see a
224
* vkGet/SetPrivateDataEXT call on a swapchain because the loader will
225
* handle it.
226
*/
227
if (objectType == VK_OBJECT_TYPE_SWAPCHAIN_KHR) {
228
mtx_lock(&device->swapchain_private_mtx);
229
VkResult result = get_swapchain_private_data_locked(device, objectHandle,
230
slot, private_data);
231
mtx_unlock(&device->swapchain_private_mtx);
232
return result;
233
}
234
#endif /* ANDROID */
235
236
struct vk_object_base *obj =
237
vk_object_base_from_u64_handle(objectHandle, objectType);
238
*private_data = util_sparse_array_get(&obj->private_data, slot->index);
239
240
return VK_SUCCESS;
241
}
242
243
VkResult
244
vk_object_base_set_private_data(struct vk_device *device,
245
VkObjectType objectType,
246
uint64_t objectHandle,
247
VkPrivateDataSlotEXT privateDataSlot,
248
uint64_t data)
249
{
250
uint64_t *private_data;
251
VkResult result = vk_object_base_private_data(device,
252
objectType, objectHandle,
253
privateDataSlot,
254
&private_data);
255
if (unlikely(result != VK_SUCCESS))
256
return result;
257
258
*private_data = data;
259
return VK_SUCCESS;
260
}
261
262
void
263
vk_object_base_get_private_data(struct vk_device *device,
264
VkObjectType objectType,
265
uint64_t objectHandle,
266
VkPrivateDataSlotEXT privateDataSlot,
267
uint64_t *pData)
268
{
269
uint64_t *private_data;
270
VkResult result = vk_object_base_private_data(device,
271
objectType, objectHandle,
272
privateDataSlot,
273
&private_data);
274
if (likely(result == VK_SUCCESS)) {
275
*pData = *private_data;
276
} else {
277
*pData = 0;
278
}
279
}
280
281
VKAPI_ATTR VkResult VKAPI_CALL
282
vk_common_CreatePrivateDataSlotEXT(VkDevice _device,
283
const VkPrivateDataSlotCreateInfoEXT *pCreateInfo,
284
const VkAllocationCallbacks *pAllocator,
285
VkPrivateDataSlotEXT *pPrivateDataSlot)
286
{
287
VK_FROM_HANDLE(vk_device, device, _device);
288
return vk_private_data_slot_create(device, pCreateInfo, pAllocator,
289
pPrivateDataSlot);
290
}
291
292
VKAPI_ATTR void VKAPI_CALL
293
vk_common_DestroyPrivateDataSlotEXT(VkDevice _device,
294
VkPrivateDataSlotEXT privateDataSlot,
295
const VkAllocationCallbacks *pAllocator)
296
{
297
VK_FROM_HANDLE(vk_device, device, _device);
298
vk_private_data_slot_destroy(device, privateDataSlot, pAllocator);
299
}
300
301
VKAPI_ATTR VkResult VKAPI_CALL
302
vk_common_SetPrivateDataEXT(VkDevice _device,
303
VkObjectType objectType,
304
uint64_t objectHandle,
305
VkPrivateDataSlotEXT privateDataSlot,
306
uint64_t data)
307
{
308
VK_FROM_HANDLE(vk_device, device, _device);
309
return vk_object_base_set_private_data(device,
310
objectType, objectHandle,
311
privateDataSlot, data);
312
}
313
314
VKAPI_ATTR void VKAPI_CALL
315
vk_common_GetPrivateDataEXT(VkDevice _device,
316
VkObjectType objectType,
317
uint64_t objectHandle,
318
VkPrivateDataSlotEXT privateDataSlot,
319
uint64_t *pData)
320
{
321
VK_FROM_HANDLE(vk_device, device, _device);
322
vk_object_base_get_private_data(device,
323
objectType, objectHandle,
324
privateDataSlot, pData);
325
}
326
327