0aadfe769a4027b864f41d35db3190b0b3fb2861
[mesa.git] / src / libre-soc / vulkan / libresoc_device.c
1 /*
2 * Copyright © 2019 Raspberry Pi
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 <assert.h>
25 #include <stdbool.h>
26 #include <string.h>
27 #include <sys/mman.h>
28 #include <sys/sysinfo.h>
29 #include <unistd.h>
30
31 #include "util/debug.h"
32 #include "util/driconf.h"
33 #include "libresoc_private.h"
34 #include "vk_util.h"
35 #include "vk_alloc.h"
36
37 struct libresoc_deferred_queue_submission {
38 struct libresoc_queue *queue;
39 VkCommandBuffer *cmd_buffers;
40 uint32_t cmd_buffer_count;
41
42 /* Sparse bindings that happen on a queue. */
43 VkSparseBufferMemoryBindInfo *buffer_binds;
44 uint32_t buffer_bind_count;
45 VkSparseImageOpaqueMemoryBindInfo *image_opaque_binds;
46 uint32_t image_opaque_bind_count;
47
48 bool flush_caches;
49 VkShaderStageFlags wait_dst_stage_mask;
50 struct libresoc_semaphore_part **wait_semaphores;
51 uint32_t wait_semaphore_count;
52 struct libresoc_semaphore_part **signal_semaphores;
53 uint32_t signal_semaphore_count;
54 VkFence fence;
55
56 uint64_t *wait_values;
57 uint64_t *signal_values;
58
59 struct libresoc_semaphore_part *temporary_semaphore_parts;
60 uint32_t temporary_semaphore_part_count;
61
62 struct list_head queue_pending_list;
63 uint32_t submission_wait_count;
64 struct libresoc_timeline_waiter *wait_nodes;
65
66 struct list_head processing_list;
67 };
68
69 struct libresoc_queue_submission {
70 const VkCommandBuffer *cmd_buffers;
71 uint32_t cmd_buffer_count;
72
73 /* Sparse bindings that happen on a queue. */
74 const VkSparseBufferMemoryBindInfo *buffer_binds;
75 uint32_t buffer_bind_count;
76 const VkSparseImageOpaqueMemoryBindInfo *image_opaque_binds;
77 uint32_t image_opaque_bind_count;
78
79 bool flush_caches;
80 VkPipelineStageFlags wait_dst_stage_mask;
81 const VkSemaphore *wait_semaphores;
82 uint32_t wait_semaphore_count;
83 const VkSemaphore *signal_semaphores;
84 uint32_t signal_semaphore_count;
85 VkFence fence;
86
87 const uint64_t *wait_values;
88 uint32_t wait_value_count;
89 const uint64_t *signal_values;
90 uint32_t signal_value_count;
91 };
92
93 void
94 libresoc_free_memory(struct libresoc_device *device,
95 const VkAllocationCallbacks* pAllocator,
96 struct libresoc_device_memory *mem)
97 {
98 if (mem == NULL)
99 return;
100
101 vk_object_base_finish(&mem->base);
102 vk_free2(&device->vk.alloc, pAllocator, mem);
103 }
104
105 static VkResult libresoc_alloc_memory(struct libresoc_device *device,
106 const VkMemoryAllocateInfo* pAllocateInfo,
107 const VkAllocationCallbacks* pAllocator,
108 VkDeviceMemory* pMem)
109 {
110 struct libresoc_device_memory *mem;
111 VkResult result;
112 uint32_t flags = 0;
113
114 assert(pAllocateInfo->sType == VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO);
115
116 const VkImportMemoryFdInfoKHR *import_info =
117 vk_find_struct_const(pAllocateInfo->pNext, IMPORT_MEMORY_FD_INFO_KHR);
118 const VkMemoryDedicatedAllocateInfo *dedicate_info =
119 vk_find_struct_const(pAllocateInfo->pNext, MEMORY_DEDICATED_ALLOCATE_INFO);
120 const VkExportMemoryAllocateInfo *export_info =
121 vk_find_struct_const(pAllocateInfo->pNext, EXPORT_MEMORY_ALLOCATE_INFO);
122 const VkImportMemoryHostPointerInfoEXT *host_ptr_info =
123 vk_find_struct_const(pAllocateInfo->pNext, IMPORT_MEMORY_HOST_POINTER_INFO_EXT);
124
125 const struct wsi_memory_allocate_info *wsi_info =
126 vk_find_struct_const(pAllocateInfo->pNext, WSI_MEMORY_ALLOCATE_INFO_MESA);
127
128
129 mem = vk_zalloc2(&device->vk.alloc, pAllocator, sizeof(*mem), 8,
130 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
131 if (mem == NULL)
132 return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
133
134 vk_object_base_init(&device->vk, &mem->base,
135 VK_OBJECT_TYPE_DEVICE_MEMORY);
136
137 if (dedicate_info) {
138 mem->image = libresoc_image_from_handle(dedicate_info->image);
139 //mem->buffer = libresoc_buffer_from_handle(dedicate_info->buffer);
140 } else {
141 mem->image = NULL;
142 //mem->buffer = NULL;
143 }
144
145 // float priority_float = 0.5;
146 // const struct VkMemoryPriorityAllocateInfoEXT *priority_ext =
147 // vk_find_struct_const(pAllocateInfo->pNext,
148 // MEMORY_PRIORITY_ALLOCATE_INFO_EXT);
149 // if (priority_ext)
150 // priority_float = priority_ext->priority;
151
152 // unsigned priority = MIN2(LIBRESOC_BO_PRIORITY_APPLICATION_MAX - 1,
153 // (int)(priority_float * LIBRESOC_BO_PRIORITY_APPLICATION_MAX));
154
155 mem->user_ptr = NULL;
156 //mem->bo = NULL;
157
158
159 if (import_info) {
160 assert(import_info->handleType ==
161 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT ||
162 import_info->handleType ==
163 VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
164 // mem->bo = device->ws->buffer_from_fd(device->ws, import_info->fd,
165 // priority, NULL);
166 // if (!mem->bo) {
167 // result = VK_ERROR_INVALID_EXTERNAL_HANDLE;
168 // goto fail;
169 // } else {
170 // close(import_info->fd);
171 // }
172
173 // if (mem->image && mem->image->plane_count == 1 &&
174 // !vk_format_is_depth_or_stencil(mem->image->vk_format)) {
175 // struct radeon_bo_metadata metadata;
176 // device->ws->buffer_get_metadata(mem->bo, &metadata);
177
178 // struct libresoc_image_create_info create_info = {
179 // .no_metadata_planes = true,
180 // .bo_metadata = &metadata
181 // };
182
183 // /* This gives a basic ability to import radeonsi images
184 // * that don't have DCC. This is not guaranteed by any
185 // * spec and can be removed after we support modifiers. */
186 // result = libresoc_image_create_layout(device, create_info, mem->image);
187 // if (result != VK_SUCCESS) {
188 // device->ws->buffer_destroy(mem->bo);
189 // goto fail;
190 // }
191 // }
192 } else if (host_ptr_info) {
193 // assert(host_ptr_info->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT);
194 // mem->bo = device->ws->buffer_from_ptr(device->ws, host_ptr_info->pHostPointer,
195 // pAllocateInfo->allocationSize,
196 // priority);
197 // if (!mem->bo) {
198 // result = VK_ERROR_INVALID_EXTERNAL_HANDLE;
199 // goto fail;
200 // } else {
201 // mem->user_ptr = host_ptr_info->pHostPointer;
202 // }
203 } else {
204 uint64_t alloc_size = align_u64(pAllocateInfo->allocationSize, 4096);
205 uint32_t heap_index;
206
207 heap_index = device->physical_device->memory_properties.memoryTypes[pAllocateInfo->memoryTypeIndex].heapIndex;
208 // domain = device->physical_device->memory_domains[pAllocateInfo->memoryTypeIndex];
209 // flags |= device->physical_device->memory_flags[pAllocateInfo->memoryTypeIndex];
210
211 // if (!dedicate_info && !import_info && (!export_info || !export_info->handleTypes)) {
212 // flags |= RADEON_FLAG_NO_INTERPROCESS_SHARING;
213 // if (device->use_global_bo_list) {
214 // flags |= RADEON_FLAG_PREFER_LOCAL_BO;
215 // }
216 // }
217
218 if (device->overallocation_disallowed) {
219 uint64_t total_size =
220 device->physical_device->memory_properties.memoryHeaps[heap_index].size;
221
222 mtx_lock(&device->overallocation_mutex);
223 if (device->allocated_memory_size[heap_index] + alloc_size > total_size) {
224 mtx_unlock(&device->overallocation_mutex);
225 result = VK_ERROR_OUT_OF_DEVICE_MEMORY;
226 goto fail;
227 }
228 device->allocated_memory_size[heap_index] += alloc_size;
229 mtx_unlock(&device->overallocation_mutex);
230 }
231
232 // mem->bo = device->ws->buffer_create(device->ws, alloc_size, device->physical_device->rad_info.max_alignment,
233 // domain, flags, priority);
234
235 // if (!mem->bo) {
236 // if (device->overallocation_disallowed) {
237 // mtx_lock(&device->overallocation_mutex);
238 // device->allocated_memory_size[heap_index] -= alloc_size;
239 // mtx_unlock(&device->overallocation_mutex);
240 // }
241 // result = VK_ERROR_OUT_OF_DEVICE_MEMORY;
242 // goto fail;
243 // }
244
245 mem->heap_index = heap_index;
246 mem->alloc_size = alloc_size;
247 }
248
249 // if (!wsi_info) {
250 // result = libresoc_bo_list_add(device, mem->bo);
251 // if (result != VK_SUCCESS)
252 // goto fail;
253 // }
254
255 *pMem = libresoc_device_memory_to_handle(mem);
256
257 return VK_SUCCESS;
258
259 fail:
260 libresoc_free_memory(device, pAllocator,mem);
261
262 return result;
263 }
264
265 VkResult libresoc_AllocateMemory(
266 VkDevice _device,
267 const VkMemoryAllocateInfo* pAllocateInfo,
268 const VkAllocationCallbacks* pAllocator,
269 VkDeviceMemory* pMem)
270 {
271 LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
272 return libresoc_alloc_memory(device, pAllocateInfo, pAllocator, pMem);
273 }
274
275 void libresoc_FreeMemory(
276 VkDevice _device,
277 VkDeviceMemory _mem,
278 const VkAllocationCallbacks* pAllocator)
279 {
280 LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
281 LIBRESOC_FROM_HANDLE(libresoc_device_memory, mem, _mem);
282
283 libresoc_free_memory(device, pAllocator, mem);
284 }
285 static VkResult
286 libresoc_create_pthread_cond(pthread_cond_t *cond)
287 {
288 pthread_condattr_t condattr;
289 if (pthread_condattr_init(&condattr)) {
290 return VK_ERROR_INITIALIZATION_FAILED;
291 }
292
293 if (pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC)) {
294 pthread_condattr_destroy(&condattr);
295 return VK_ERROR_INITIALIZATION_FAILED;
296 }
297 if (pthread_cond_init(cond, &condattr)) {
298 pthread_condattr_destroy(&condattr);
299 return VK_ERROR_INITIALIZATION_FAILED;
300 }
301 pthread_condattr_destroy(&condattr);
302 return VK_SUCCESS;
303 }
304
305 VkResult
306 libresoc_EnumerateInstanceExtensionProperties(const char *pLayerName,
307 uint32_t *pPropertyCount,
308 VkExtensionProperties *pProperties)
309 {
310 if (getenv("LIBRESOC_TRACE")) {
311 fprintf(stderr, "EnumerateInstanceExtensionProperties called for: %s \n", pLayerName);
312 }
313 VK_OUTARRAY_MAKE(out, pProperties, pPropertyCount);
314
315 for (int i = 0; i < LIBRESOC_INSTANCE_EXTENSION_COUNT; i++) {
316 if (libresoc_instance_extensions_supported.extensions[i]) {
317 vk_outarray_append(&out, prop) {
318 *prop = libresoc_instance_extensions[i];
319 }
320 }
321 }
322
323 return vk_outarray_status(&out);
324 }
325
326 static void *
327 default_alloc_func(void *pUserData, size_t size, size_t align,
328 VkSystemAllocationScope allocationScope)
329 {
330 return malloc(size);
331 }
332
333 static void *
334 default_realloc_func(void *pUserData, void *pOriginal, size_t size,
335 size_t align, VkSystemAllocationScope allocationScope)
336 {
337 return realloc(pOriginal, size);
338 }
339
340 static void
341 default_free_func(void *pUserData, void *pMemory)
342 {
343 free(pMemory);
344 }
345
346 static const VkAllocationCallbacks default_alloc = {
347 .pUserData = NULL,
348 .pfnAllocation = default_alloc_func,
349 .pfnReallocation = default_realloc_func,
350 .pfnFree = default_free_func,
351 };
352
353 static const struct debug_control libresoc_debug_options[] = {
354 {"nofastclears", LIBRESOC_DEBUG_NO_FAST_CLEARS},
355 {"nodcc", LIBRESOC_DEBUG_NO_DCC},
356 {"shaders", LIBRESOC_DEBUG_DUMP_SHADERS},
357 {"nocache", LIBRESOC_DEBUG_NO_CACHE},
358 {"shaderstats", LIBRESOC_DEBUG_DUMP_SHADER_STATS},
359 {"nohiz", LIBRESOC_DEBUG_NO_HIZ},
360 {"nocompute", LIBRESOC_DEBUG_NO_COMPUTE_QUEUE},
361 {"allbos", LIBRESOC_DEBUG_ALL_BOS},
362 {"noibs", LIBRESOC_DEBUG_NO_IBS},
363 {"spirv", LIBRESOC_DEBUG_DUMP_SPIRV},
364 {"vmfaults", LIBRESOC_DEBUG_VM_FAULTS},
365 {"zerovram", LIBRESOC_DEBUG_ZERO_VRAM},
366 {"syncshaders", LIBRESOC_DEBUG_SYNC_SHADERS},
367 {"preoptir", LIBRESOC_DEBUG_PREOPTIR},
368 {"nodynamicbounds", LIBRESOC_DEBUG_NO_DYNAMIC_BOUNDS},
369 {"nooutoforder", LIBRESOC_DEBUG_NO_OUT_OF_ORDER},
370 {"info", LIBRESOC_DEBUG_INFO},
371 {"errors", LIBRESOC_DEBUG_ERRORS},
372 {"startup", LIBRESOC_DEBUG_STARTUP},
373 {"checkir", LIBRESOC_DEBUG_CHECKIR},
374 {"nothreadllvm", LIBRESOC_DEBUG_NOTHREADLLVM},
375 {"nobinning", LIBRESOC_DEBUG_NOBINNING},
376 {"nongg", LIBRESOC_DEBUG_NO_NGG},
377 {"allentrypoints", LIBRESOC_DEBUG_ALL_ENTRYPOINTS},
378 {"metashaders", LIBRESOC_DEBUG_DUMP_META_SHADERS},
379 {"nomemorycache", LIBRESOC_DEBUG_NO_MEMORY_CACHE},
380 {"llvm", LIBRESOC_DEBUG_LLVM},
381 {"forcecompress", LIBRESOC_DEBUG_FORCE_COMPRESS},
382 {NULL, 0}
383 };
384
385 const char *
386 libresoc_get_debug_option_name(int id)
387 {
388 assert(id < ARRAY_SIZE(libresoc_debug_options) - 1);
389 return libresoc_debug_options[id].string;
390 }
391
392 static const char libresoc_dri_options_xml[] =
393 DRI_CONF_BEGIN
394 DRI_CONF_SECTION_PERFORMANCE
395 DRI_CONF_ADAPTIVE_SYNC("true")
396 DRI_CONF_VK_X11_OVERRIDE_MIN_IMAGE_COUNT(0)
397 DRI_CONF_VK_X11_STRICT_IMAGE_COUNT("false")
398 DRI_CONF_VK_X11_ENSURE_MIN_IMAGE_COUNT("false")
399 DRI_CONF_SECTION_END
400
401 DRI_CONF_SECTION_DEBUG
402 DRI_CONF_VK_WSI_FORCE_BGRA8_UNORM_FIRST("false")
403 DRI_CONF_SECTION_END
404 DRI_CONF_END;
405
406 static void libresoc_init_dri_options(struct libresoc_instance *instance)
407 {
408 driParseOptionInfo(&instance->available_dri_options, libresoc_dri_options_xml);
409 driParseConfigFiles(&instance->dri_options,
410 &instance->available_dri_options,
411 0, "libresoc", NULL,
412 instance->app_info.app_name,
413 instance->app_info.app_version,
414 instance->engineName,
415 instance->engineVersion);
416 }
417
418 VkResult
419 libresoc_CreateInstance(const VkInstanceCreateInfo *pCreateInfo,
420 const VkAllocationCallbacks *pAllocator,
421 VkInstance *pInstance)
422 {
423 if (getenv("LIBRESOC_TRACE")) {
424 fprintf(stderr, "CreateInstance called. \n");
425 }
426 struct libresoc_instance *instance;
427
428 instance = vk_zalloc2(&default_alloc, pAllocator, sizeof(*instance), 8,
429 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
430 if (!instance)
431 return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
432
433 vk_object_base_init(NULL, &instance->base, VK_OBJECT_TYPE_INSTANCE);
434
435 if (pAllocator)
436 instance->alloc = *pAllocator;
437 else
438 instance->alloc = default_alloc;
439 if (pCreateInfo->pApplicationInfo) {
440 const VkApplicationInfo *app = pCreateInfo->pApplicationInfo;
441
442 instance->engineName =
443 vk_strdup(&instance->alloc, app->pEngineName,
444 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
445 instance->engineVersion = app->engineVersion;
446 instance->apiVersion = app->apiVersion;
447 }
448 instance->debug_flags = parse_debug_string(getenv("LIBRESOC_DEBUG"),
449 libresoc_debug_options);
450 /*TODO : enable extensions*/
451 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
452 int idx;
453 for (idx = 0; idx < LIBRESOC_INSTANCE_EXTENSION_COUNT; idx++) {
454 if (!strcmp(pCreateInfo->ppEnabledExtensionNames[i],
455 libresoc_instance_extensions[idx].extensionName))
456 break;
457 }
458
459 if (idx >= LIBRESOC_INSTANCE_EXTENSION_COUNT ||
460 !libresoc_instance_extensions_supported.extensions[idx]) {
461 vk_object_base_finish(&instance->base);
462 vk_free2(&default_alloc, pAllocator, instance);
463 return vk_error(instance, VK_ERROR_EXTENSION_NOT_PRESENT);
464 }
465
466 instance->enabled_extensions.extensions[idx] = true;
467 }
468 for (unsigned i = 0; i < ARRAY_SIZE(instance->dispatch.entrypoints); i++) {
469 /* Vulkan requires that entrypoints for extensions which have
470 * not been enabled must not be advertised.
471 */
472 if (!libresoc_instance_entrypoint_is_enabled(i, instance->apiVersion,
473 &instance->enabled_extensions)) {
474 instance->dispatch.entrypoints[i] = NULL;
475 } else {
476 instance->dispatch.entrypoints[i] =
477 libresoc_instance_dispatch_table.entrypoints[i];
478 }
479 }
480 for (unsigned i = 0; i < ARRAY_SIZE(instance->physical_device_dispatch.entrypoints); i++) {
481 /* Vulkan requires that entrypoints for extensions which have
482 * not been enabled must not be advertised.
483 */
484 if (!libresoc_physical_device_entrypoint_is_enabled(i, instance->apiVersion,
485 &instance->enabled_extensions)) {
486 instance->physical_device_dispatch.entrypoints[i] = NULL;
487 } else {
488 instance->physical_device_dispatch.entrypoints[i] =
489 libresoc_physical_device_dispatch_table.entrypoints[i];
490 }
491 }
492
493 for (unsigned i = 0; i < ARRAY_SIZE(instance->device_dispatch.entrypoints); i++) {
494 /* Vulkan requires that entrypoints for extensions which have
495 * not been enabled must not be advertised.
496 */
497 if (!libresoc_device_entrypoint_is_enabled(i, instance->apiVersion,
498 &instance->enabled_extensions, NULL)) {
499 instance->device_dispatch.entrypoints[i] = NULL;
500 } else {
501 instance->device_dispatch.entrypoints[i] =
502 libresoc_device_dispatch_table.entrypoints[i];
503 }
504 }
505 instance->physical_devices_enumerated = false;
506 list_inithead(&instance->physical_devices);
507 libresoc_init_dri_options(instance);
508 *pInstance = libresoc_instance_to_handle(instance);
509
510 return VK_SUCCESS;
511 }
512
513 void
514 libresoc_DestroyInstance(VkInstance _instance,
515 const VkAllocationCallbacks *pAllocator)
516 {
517 if (getenv("LIBRESOC_TRACE")) {
518 fprintf(stderr, "DestroyInstance called. \n");
519 }
520 /* FIXME: stub */
521 }
522
523 static void
524 libresoc_physical_device_init_mem_types(struct libresoc_physical_device *device)
525 {
526 uint64_t visible_vram_size = 65536; //TODO: some dummy value
527 uint64_t vram_size = 65536; //TODO: some dummy value
528 int vram_index = -1, visible_vram_index = -1;
529 device->memory_properties.memoryHeapCount = 0;
530 if (vram_size > 0) {
531 vram_index = device->memory_properties.memoryHeapCount++;
532 device->memory_properties.memoryHeaps[vram_index] = (VkMemoryHeap) {
533 .size = vram_size,
534 .flags = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT,
535 };
536 }
537
538 if (visible_vram_size) {
539 visible_vram_index = device->memory_properties.memoryHeapCount++;
540 device->memory_properties.memoryHeaps[visible_vram_index] = (VkMemoryHeap) {
541 .size = visible_vram_size,
542 .flags = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT,
543 };
544 }
545 unsigned type_count = 0;
546
547 if (vram_index >= 0 || visible_vram_index >= 0) {
548 device->memory_properties.memoryTypes[type_count++] = (VkMemoryType) {
549 .propertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
550 .heapIndex = vram_index >= 0 ? vram_index : visible_vram_index,
551 };
552 }
553
554 if (visible_vram_index >= 0) {
555 device->memory_properties.memoryTypes[type_count++] = (VkMemoryType) {
556 .propertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
557 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
558 VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
559 .heapIndex = visible_vram_index,
560 };
561 }
562
563 device->memory_properties.memoryTypeCount = type_count;
564
565
566 }
567 static VkResult
568 libresoc_physical_device_try_create(struct libresoc_instance *instance,
569 struct libresoc_physical_device **device_out)
570 {
571 VkResult result;
572 int fd = -1;
573 int master_fd = -1;
574
575 struct libresoc_physical_device *device =
576 vk_zalloc2(&instance->alloc, NULL, sizeof(*device), 8,
577 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
578 if (!device) {
579 result = vk_error(instance, VK_ERROR_OUT_OF_HOST_MEMORY);
580 return result;
581 }
582
583 device->_loader_data.loaderMagic = ICD_LOADER_MAGIC;
584 device->instance = instance;
585
586 device->master_fd = master_fd;
587 device->local_fd = fd;
588 libresoc_physical_device_init_mem_types(device);
589
590 libresoc_physical_device_get_supported_extensions(device,
591 &device->supported_extensions);
592 result = libresoc_init_wsi(device);
593 if (result != VK_SUCCESS) {
594 return result;
595 }
596 snprintf(device->name, sizeof(device->name),
597 "LIBRE-SOC DEVICE");
598 *device_out = device;
599 //TODO: incase of failures need to deallocate and cleanup various allocation properly.
600 return VK_SUCCESS;
601
602 }
603 static VkResult
604 libresoc_enumerate_physical_devices(struct libresoc_instance *instance)
605 {
606
607 if (instance->physical_devices_enumerated)
608 return VK_SUCCESS;
609
610 instance->physical_devices_enumerated = true;
611 VkResult result = VK_SUCCESS;
612 /* the driver creates a null
613 * device that allows to test the compiler without having a physical device
614 */
615 struct libresoc_physical_device *pdevice;
616
617 result = libresoc_physical_device_try_create(instance, &pdevice);
618 if (result != VK_SUCCESS)
619 return result;
620
621 list_addtail(&pdevice->link, &instance->physical_devices);
622 return VK_SUCCESS;
623
624 }
625
626 VkResult
627 libresoc_EnumeratePhysicalDevices(VkInstance _instance,
628 uint32_t *pPhysicalDeviceCount,
629 VkPhysicalDevice *pPhysicalDevices)
630 {
631 if (getenv("LIBRESOC_TRACE")) {
632 fprintf(stderr, "EnumeratePhysicalDevices called\n");
633 }
634 LIBRESOC_FROM_HANDLE(libresoc_instance, instance, _instance);
635 VK_OUTARRAY_MAKE(out, pPhysicalDevices, pPhysicalDeviceCount);
636
637 VkResult result = libresoc_enumerate_physical_devices(instance);
638 if (result != VK_SUCCESS)
639 return result;
640
641 list_for_each_entry(struct libresoc_physical_device, pdevice,
642 &instance->physical_devices, link) {
643 vk_outarray_append(&out, i) {
644 *i = libresoc_physical_device_to_handle(pdevice);
645 }
646 }
647
648 return vk_outarray_status(&out);
649 }
650
651 void
652 libresoc_GetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice,
653 VkPhysicalDeviceFeatures *pFeatures)
654 {
655 if (getenv("LIBRESOC_TRACE")) {
656 fprintf(stderr, "GetPhysicalDeviceFeatures called. \n");
657 }
658 //LIBRESOC_FROM_HANDLE(libresoc_physical_device, pdevice, physicalDevice);
659 memset(pFeatures, 0, sizeof(*pFeatures));
660
661 *pFeatures = (VkPhysicalDeviceFeatures) {
662 .robustBufferAccess = true,
663 .fullDrawIndexUint32 = true,
664 .imageCubeArray = true,
665 .independentBlend = true,
666 .geometryShader = true,
667 .tessellationShader = true,
668 .sampleRateShading = true,
669 .dualSrcBlend = true,
670 .logicOp = true,
671 .multiDrawIndirect = true,
672 .drawIndirectFirstInstance = true,
673 .depthClamp = true,
674 .depthBiasClamp = true,
675 .fillModeNonSolid = true,
676 .depthBounds = true,
677 .wideLines = true,
678 .largePoints = true,
679 .alphaToOne = true,
680 .multiViewport = true,
681 .samplerAnisotropy = true,
682 .textureCompressionETC2 = false,
683 .textureCompressionASTC_LDR = false,
684 .textureCompressionBC = true,
685 .occlusionQueryPrecise = true,
686 .pipelineStatisticsQuery = true,
687 .vertexPipelineStoresAndAtomics = true,
688 .fragmentStoresAndAtomics = true,
689 .shaderTessellationAndGeometryPointSize = true,
690 .shaderImageGatherExtended = true,
691 .shaderStorageImageExtendedFormats = true,
692 .shaderStorageImageMultisample = true,
693 .shaderUniformBufferArrayDynamicIndexing = true,
694 .shaderSampledImageArrayDynamicIndexing = true,
695 .shaderStorageBufferArrayDynamicIndexing = true,
696 .shaderStorageImageArrayDynamicIndexing = true,
697 .shaderStorageImageReadWithoutFormat = true,
698 .shaderStorageImageWriteWithoutFormat = true,
699 .shaderClipDistance = true,
700 .shaderCullDistance = true,
701 .shaderFloat64 = true,
702 .shaderInt64 = true,
703 .shaderInt16 = true,
704 .sparseBinding = true,
705 .variableMultisampleRate = true,
706 .shaderResourceMinLod = true,
707 .inheritedQueries = true,
708 };
709 }
710
711 static size_t
712 libresoc_max_descriptor_set_size()
713 {
714 /* make sure that the entire descriptor set is addressable with a signed
715 * 32-bit int. So the sum of all limits scaled by descriptor size has to
716 * be at most 2 GiB. the combined image & samples object count as one of
717 * both. This limit is for the pipeline layout, not for the set layout, but
718 * there is no set limit, so we just set a pipeline limit. I don't think
719 * any app is going to hit this soon. */
720 return ((1ull << 31) - 16 * MAX_DYNAMIC_BUFFERS
721 - MAX_INLINE_UNIFORM_BLOCK_SIZE * MAX_INLINE_UNIFORM_BLOCK_COUNT) /
722 (32 /* uniform buffer, 32 due to potential space wasted on alignment */ +
723 32 /* storage buffer, 32 due to potential space wasted on alignment */ +
724 32 /* sampler, largest when combined with image */ +
725 64 /* sampled image */ +
726 64 /* storage image */);
727 }
728
729 void
730 libresoc_GetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice,
731 VkPhysicalDeviceProperties *pProperties)
732 {
733 if (getenv("LIBRESOC_TRACE")) {
734 fprintf(stderr, "GetPhysicalDeviceProperties called. \n");
735 }
736 LIBRESOC_FROM_HANDLE(libresoc_physical_device, pdevice, physicalDevice);
737 VkSampleCountFlags sample_counts = 0xf;
738
739 size_t max_descriptor_set_size = libresoc_max_descriptor_set_size();
740
741 VkPhysicalDeviceLimits limits = {
742 .maxImageDimension1D = (1 << 14),
743 .maxImageDimension2D = (1 << 14),
744 .maxImageDimension3D = (1 << 11),
745 .maxImageDimensionCube = (1 << 14),
746 .maxImageArrayLayers = (1 << 11),
747 .maxTexelBufferElements = UINT32_MAX,
748 .maxUniformBufferRange = UINT32_MAX,
749 .maxStorageBufferRange = UINT32_MAX,
750 .maxPushConstantsSize = MAX_PUSH_CONSTANTS_SIZE,
751 .maxMemoryAllocationCount = UINT32_MAX,
752 .maxSamplerAllocationCount = 64 * 1024,
753 .bufferImageGranularity = 64, /* A cache line */
754 .sparseAddressSpaceSize = LIBRESOC_MAX_MEMORY_ALLOCATION_SIZE, /* buffer max size */
755 .maxBoundDescriptorSets = MAX_SETS,
756 .maxPerStageDescriptorSamplers = max_descriptor_set_size,
757 .maxPerStageDescriptorUniformBuffers = max_descriptor_set_size,
758 .maxPerStageDescriptorStorageBuffers = max_descriptor_set_size,
759 .maxPerStageDescriptorSampledImages = max_descriptor_set_size,
760 .maxPerStageDescriptorStorageImages = max_descriptor_set_size,
761 .maxPerStageDescriptorInputAttachments = max_descriptor_set_size,
762 .maxPerStageResources = max_descriptor_set_size,
763 .maxDescriptorSetSamplers = max_descriptor_set_size,
764 .maxDescriptorSetUniformBuffers = max_descriptor_set_size,
765 .maxDescriptorSetUniformBuffersDynamic = MAX_DYNAMIC_UNIFORM_BUFFERS,
766 .maxDescriptorSetStorageBuffers = max_descriptor_set_size,
767 .maxDescriptorSetStorageBuffersDynamic = MAX_DYNAMIC_STORAGE_BUFFERS,
768 .maxDescriptorSetSampledImages = max_descriptor_set_size,
769 .maxDescriptorSetStorageImages = max_descriptor_set_size,
770 .maxDescriptorSetInputAttachments = max_descriptor_set_size,
771 .maxVertexInputAttributes = MAX_VERTEX_ATTRIBS,
772 .maxVertexInputBindings = MAX_VBS,
773 .maxVertexInputAttributeOffset = 2047,
774 .maxVertexInputBindingStride = 2048,
775 .maxVertexOutputComponents = 128,
776 .maxTessellationGenerationLevel = 64,
777 .maxTessellationPatchSize = 32,
778 .maxTessellationControlPerVertexInputComponents = 128,
779 .maxTessellationControlPerVertexOutputComponents = 128,
780 .maxTessellationControlPerPatchOutputComponents = 120,
781 .maxTessellationControlTotalOutputComponents = 4096,
782 .maxTessellationEvaluationInputComponents = 128,
783 .maxTessellationEvaluationOutputComponents = 128,
784 .maxGeometryShaderInvocations = 127,
785 .maxGeometryInputComponents = 64,
786 .maxGeometryOutputComponents = 128,
787 .maxGeometryOutputVertices = 256,
788 .maxGeometryTotalOutputComponents = 1024,
789 .maxFragmentInputComponents = 128,
790 .maxFragmentOutputAttachments = 8,
791 .maxFragmentDualSrcAttachments = 1,
792 .maxFragmentCombinedOutputResources = 8,
793 .maxComputeSharedMemorySize = 32768,
794 .maxComputeWorkGroupCount = { 65535, 65535, 65535 },
795 .maxComputeWorkGroupInvocations = 1024,
796 .maxComputeWorkGroupSize = {
797 1024,
798 1024,
799 1024
800 },
801 .subPixelPrecisionBits = 8,
802 .subTexelPrecisionBits = 8,
803 .mipmapPrecisionBits = 8,
804 .maxDrawIndexedIndexValue = UINT32_MAX,
805 .maxDrawIndirectCount = UINT32_MAX,
806 .maxSamplerLodBias = 16,
807 .maxSamplerAnisotropy = 16,
808 .maxViewports = MAX_VIEWPORTS,
809 .maxViewportDimensions = { (1 << 14), (1 << 14) },
810 .viewportBoundsRange = { INT16_MIN, INT16_MAX },
811 .viewportSubPixelBits = 8,
812 .minMemoryMapAlignment = 4096, /* A page */
813 .minTexelBufferOffsetAlignment = 4,
814 .minUniformBufferOffsetAlignment = 4,
815 .minStorageBufferOffsetAlignment = 4,
816 .minTexelOffset = -32,
817 .maxTexelOffset = 31,
818 .minTexelGatherOffset = -32,
819 .maxTexelGatherOffset = 31,
820 .minInterpolationOffset = -2,
821 .maxInterpolationOffset = 2,
822 .subPixelInterpolationOffsetBits = 8,
823 .maxFramebufferWidth = (1 << 14),
824 .maxFramebufferHeight = (1 << 14),
825 .maxFramebufferLayers = (1 << 10),
826 .framebufferColorSampleCounts = sample_counts,
827 .framebufferDepthSampleCounts = sample_counts,
828 .framebufferStencilSampleCounts = sample_counts,
829 .framebufferNoAttachmentsSampleCounts = sample_counts,
830 .maxColorAttachments = MAX_RTS,
831 .sampledImageColorSampleCounts = sample_counts,
832 .sampledImageIntegerSampleCounts = sample_counts,
833 .sampledImageDepthSampleCounts = sample_counts,
834 .sampledImageStencilSampleCounts = sample_counts,
835 .storageImageSampleCounts = sample_counts,
836 .maxSampleMaskWords = 1,
837 .timestampComputeAndGraphics = true,
838 .timestampPeriod = 1000000.0 /* FIXME /pdevice->rad_info.clock_crystal_freq*/,
839 .maxClipDistances = 8,
840 .maxCullDistances = 8,
841 .maxCombinedClipAndCullDistances = 8,
842 .discreteQueuePriorities = 2,
843 .pointSizeRange = { 0.0, 8191.875 },
844 .lineWidthRange = { 0.0, 8191.875 },
845 .pointSizeGranularity = (1.0 / 8.0),
846 .lineWidthGranularity = (1.0 / 8.0),
847 .strictLines = false, /* FINISHME */
848 .standardSampleLocations = true,
849 .optimalBufferCopyOffsetAlignment = 128,
850 .optimalBufferCopyRowPitchAlignment = 128,
851 .nonCoherentAtomSize = 64,
852 };
853
854 *pProperties = (VkPhysicalDeviceProperties) {
855 .apiVersion = libresoc_physical_device_api_version(pdevice),
856 .driverVersion = vk_get_driver_version(),
857 .vendorID = 1, //TODO: some dummy value
858 .deviceID = 1, //TODO: dome dummy value
859 .deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU,
860 .limits = limits,
861 .sparseProperties = {0},
862 };
863
864 strcpy(pProperties->deviceName, pdevice->name);
865 memcpy(pProperties->pipelineCacheUUID, pdevice->cache_uuid, VK_UUID_SIZE);
866 }
867
868 static void libresoc_get_physical_device_queue_family_properties(
869 struct libresoc_physical_device* pdevice,
870 uint32_t* pCount,
871 VkQueueFamilyProperties** pQueueFamilyProperties)
872 {
873 int num_queue_families = 1;
874 int idx;
875
876 if (pQueueFamilyProperties == NULL) {
877 *pCount = num_queue_families;
878 return;
879 }
880
881 if (!*pCount)
882 return;
883
884 idx = 0;
885 if (*pCount >= 1) {
886 *pQueueFamilyProperties[idx] = (VkQueueFamilyProperties) {
887 .queueFlags = VK_QUEUE_GRAPHICS_BIT |
888 VK_QUEUE_COMPUTE_BIT |
889 VK_QUEUE_TRANSFER_BIT |
890 VK_QUEUE_SPARSE_BINDING_BIT,
891 .queueCount = 1,
892 .timestampValidBits = 64,
893 .minImageTransferGranularity = (VkExtent3D) { 1, 1, 1 },
894 };
895 idx++;
896 }
897
898 *pCount = idx;
899 }
900
901 void
902 libresoc_GetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice,
903 uint32_t *pCount,
904 VkQueueFamilyProperties *pQueueFamilyProperties)
905 {
906 if (getenv("LIBRESOC_TRACE")) {
907 fprintf(stderr, "GetPhysicalDeviceQueueFamilyProperites called. \n");
908 }
909 LIBRESOC_FROM_HANDLE(libresoc_physical_device, pdevice, physicalDevice);
910 if (!pQueueFamilyProperties) {
911 libresoc_get_physical_device_queue_family_properties(pdevice, pCount, NULL);
912 return;
913 }
914 VkQueueFamilyProperties *properties[] = {
915 pQueueFamilyProperties + 0,
916 pQueueFamilyProperties + 1,
917 pQueueFamilyProperties + 2,
918 };
919 libresoc_get_physical_device_queue_family_properties(pdevice, pCount, properties);
920 assert(*pCount <= 3);
921 }
922
923 void
924 libresoc_GetPhysicalDeviceMemoryProperties(VkPhysicalDevice physicalDevice,
925 VkPhysicalDeviceMemoryProperties *pMemoryProperties)
926 {
927 if (getenv("LIBRESOC_TRACE")) {
928 fprintf(stderr, "GetPhysicalDEviceMemoryProperties called. \n");
929 }
930 LIBRESOC_FROM_HANDLE(libresoc_physical_device, physical_device, physicalDevice);
931
932 *pMemoryProperties = physical_device->memory_properties;
933 /* FIXME: stub */
934 }
935
936 //void
937 //libresoc_GetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties *pFormatProperties) {
938 //
939 // if (getenv("LIBRESOC_TRACE")) {
940 // fprintf(stderr, "GetPhysicalDeviceFormatProperties called. \n");
941 // }
942 // /* FIXME: stub */
943 //}
944
945 //VkResult
946 // libresoc_GetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkImageFormatProperties* pImageFormatProperties)
947 //{
948 // if (getenv("LIBRESOC_TRACE")) {
949 // fprintf(stderr, "GetPhysicalDEviceImageFormatProperties called. \n");
950 // }
951 //
952 // /* FIXME: stub */
953 // return VK_SUCCESS;
954 //}
955 // void
956 // libresoc_GetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkSampleCountFlagBits samples, VkImageUsageFlags usage, VkImageTiling tiling, uint32_t* pPropertyCount, VkSparseImageFormatProperties* pProperties)
957 // {
958 // if (getenv("LIBRESOC_TRACE")) {
959 // fprintf(stderr, "GetPhysicalDeviceSparseImageFormatProperties called. \n");
960 // }
961 // /* FIXME: stub */
962 // }
963 PFN_vkVoidFunction
964 libresoc_GetInstanceProcAddr(VkInstance _instance,
965 const char *pName)
966 {
967 if (getenv("LIBRESOC_TRACE")) {
968 fprintf(stderr, "GetInstanceProcAddr called for: %s \n", pName);
969 }
970 LIBRESOC_FROM_HANDLE(libresoc_instance, instance, _instance);
971
972 /* The Vulkan 1.0 spec for vkGetInstanceProcAddr has a table of exactly
973 * when we have to return valid function pointers, NULL, or it's left
974 * undefined. See the table for exact details.
975 */
976 if (pName == NULL)
977 return NULL;
978
979 #define LOOKUP_LIBRESOC_ENTRYPOINT(entrypoint) \
980 if (strcmp(pName, "vk" #entrypoint) == 0) \
981 return (PFN_vkVoidFunction)libresoc_##entrypoint
982
983 LOOKUP_LIBRESOC_ENTRYPOINT(EnumerateInstanceExtensionProperties);
984 LOOKUP_LIBRESOC_ENTRYPOINT(CreateInstance);
985 LOOKUP_LIBRESOC_ENTRYPOINT(DestroyInstance);
986 LOOKUP_LIBRESOC_ENTRYPOINT(EnumeratePhysicalDevices);
987 LOOKUP_LIBRESOC_ENTRYPOINT(GetPhysicalDeviceFeatures);
988 LOOKUP_LIBRESOC_ENTRYPOINT(GetPhysicalDeviceFormatProperties);
989 LOOKUP_LIBRESOC_ENTRYPOINT(GetPhysicalDeviceImageFormatProperties);
990 LOOKUP_LIBRESOC_ENTRYPOINT(GetPhysicalDeviceProperties);
991 LOOKUP_LIBRESOC_ENTRYPOINT(GetPhysicalDeviceQueueFamilyProperties);
992 LOOKUP_LIBRESOC_ENTRYPOINT(GetPhysicalDeviceMemoryProperties);
993 LOOKUP_LIBRESOC_ENTRYPOINT(GetDeviceProcAddr);
994 LOOKUP_LIBRESOC_ENTRYPOINT(CreateDevice);
995 LOOKUP_LIBRESOC_ENTRYPOINT(EnumerateDeviceExtensionProperties);
996 LOOKUP_LIBRESOC_ENTRYPOINT(GetPhysicalDeviceSparseImageFormatProperties);
997
998
999 #undef LOOKUP_LIBRESOC_ENTRYPOINT
1000
1001 if (instance == NULL)
1002 return NULL;
1003
1004 int idx = libresoc_get_instance_entrypoint_index(pName);
1005 if (idx >= 0)
1006 return instance->dispatch.entrypoints[idx];
1007
1008 idx = libresoc_get_physical_device_entrypoint_index(pName);
1009 if (idx >= 0)
1010 return instance->physical_device_dispatch.entrypoints[idx];
1011
1012 idx = libresoc_get_device_entrypoint_index(pName);
1013 if (idx >= 0)
1014 return instance->device_dispatch.entrypoints[idx];
1015
1016 return NULL;
1017 }
1018
1019 /* With version 1+ of the loader interface the ICD should expose
1020 * vk_icdGetInstanceProcAddr to work around certain LD_PRELOAD issues seen in apps.
1021 */
1022 PUBLIC
1023 VKAPI_ATTR PFN_vkVoidFunction
1024 VKAPI_CALL vk_icdGetInstanceProcAddr(VkInstance instance,
1025 const char *pName);
1026
1027 PUBLIC
1028 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
1029 vk_icdGetInstanceProcAddr(VkInstance instance,
1030 const char* pName)
1031 {
1032 if (getenv("LIBRESOC_TRACE")) {
1033 fprintf(stderr, "vk_icdGetInstanceProcAddr called for: %s \n", pName);
1034 }
1035 return libresoc_GetInstanceProcAddr(instance, pName);
1036 }
1037
1038 PFN_vkVoidFunction
1039 libresoc_GetDeviceProcAddr(VkDevice _device,
1040 const char *pName)
1041 {
1042 if (getenv("LIBRESOC_TRACE")) {
1043 fprintf(stderr, "GetDeviceProcAddr called for: %s \n", pName);
1044 }
1045 LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
1046
1047 if (!device || !pName)
1048 return NULL;
1049
1050 int idx = libresoc_get_device_entrypoint_index(pName);
1051 if (idx < 0)
1052 return NULL;
1053
1054 return device->dispatch.entrypoints[idx];
1055 }
1056
1057 /* With version 4+ of the loader interface the ICD should expose
1058 * vk_icdGetPhysicalDeviceProcAddr()
1059 */
1060 PUBLIC
1061 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
1062 vk_icdGetPhysicalDeviceProcAddr(VkInstance _instance,
1063 const char* pName);
1064
1065 PFN_vkVoidFunction
1066 vk_icdGetPhysicalDeviceProcAddr(VkInstance _instance,
1067 const char* pName)
1068 {
1069 if (getenv("LIBRESOC_TRACE")) {
1070 fprintf(stderr, "vk_icdGetPhysicalDeviceProcAddr called for: %s \n", pName);
1071 }
1072 LIBRESOC_FROM_HANDLE(libresoc_instance, instance, _instance);
1073
1074 if (!pName || !instance)
1075 return NULL;
1076
1077 int idx = libresoc_get_physical_device_entrypoint_index(pName);
1078 if (idx < 0)
1079 return NULL;
1080
1081 return instance->physical_device_dispatch.entrypoints[idx];
1082 }
1083
1084 VkResult
1085 libresoc_EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
1086 const char *pLayerName,
1087 uint32_t *pPropertyCount,
1088 VkExtensionProperties *pProperties)
1089 {
1090 if (getenv("LIBRESOC_TRACE")) {
1091 fprintf(stderr, "EnumerateDeviceExtensionProperties called for layer: %s \n", pLayerName);
1092 }
1093 LIBRESOC_FROM_HANDLE(libresoc_physical_device, device, physicalDevice);
1094 VK_OUTARRAY_MAKE(out, pProperties, pPropertyCount);
1095
1096 for (int i = 0; i < LIBRESOC_DEVICE_EXTENSION_COUNT; i++) {
1097 if (device->supported_extensions.extensions[i]) {
1098 vk_outarray_append(&out, prop) {
1099 *prop = libresoc_device_extensions[i];
1100 }
1101 }
1102 }
1103
1104 return vk_outarray_status(&out);
1105 }
1106
1107 static void
1108 libresoc_device_init_dispatch(struct libresoc_device *device)
1109 {
1110 const struct libresoc_instance *instance = device->physical_device->instance;
1111 const struct libresoc_device_dispatch_table *dispatch_table_layer = NULL;
1112
1113 for (unsigned i = 0; i < ARRAY_SIZE(device->dispatch.entrypoints); i++) {
1114 /* Vulkan requires that entrypoints for extensions which have not been
1115 * enabled must not be advertised.
1116 */
1117 if (!libresoc_device_entrypoint_is_enabled(i, instance->apiVersion,
1118 &instance->enabled_extensions,
1119 &device->enabled_extensions)) {
1120 device->dispatch.entrypoints[i] = NULL;
1121 } else if (dispatch_table_layer &&
1122 dispatch_table_layer->entrypoints[i]) {
1123 device->dispatch.entrypoints[i] =
1124 dispatch_table_layer->entrypoints[i];
1125 } else {
1126 device->dispatch.entrypoints[i] =
1127 libresoc_device_dispatch_table.entrypoints[i];
1128 }
1129 }
1130 }
1131
1132 static VkResult
1133 check_physical_device_features(VkPhysicalDevice physicalDevice,
1134 const VkPhysicalDeviceFeatures *features)
1135 {
1136 LIBRESOC_FROM_HANDLE(libresoc_physical_device, physical_device, physicalDevice);
1137 VkPhysicalDeviceFeatures supported_features;
1138 libresoc_GetPhysicalDeviceFeatures(physicalDevice, &supported_features);
1139 VkBool32 *supported_feature = (VkBool32 *)&supported_features;
1140 VkBool32 *enabled_feature = (VkBool32 *)features;
1141 unsigned num_features = sizeof(VkPhysicalDeviceFeatures) / sizeof(VkBool32);
1142 for (uint32_t i = 0; i < num_features; i++) {
1143 if (enabled_feature[i] && !supported_feature[i])
1144 return vk_error(physical_device->instance, VK_ERROR_FEATURE_NOT_PRESENT);
1145 }
1146
1147 return VK_SUCCESS;
1148 }
1149 static int libresoc_get_device_extension_index(const char *name)
1150 {
1151 for (unsigned i = 0; i < LIBRESOC_DEVICE_EXTENSION_COUNT; ++i) {
1152 if (strcmp(name, libresoc_device_extensions[i].extensionName) == 0)
1153 return i;
1154 }
1155 return -1;
1156 }
1157
1158 static int
1159 libresoc_queue_init(struct libresoc_device *device, struct libresoc_queue *queue,
1160 uint32_t queue_family_index, int idx,
1161 VkDeviceQueueCreateFlags flags,
1162 const VkDeviceQueueGlobalPriorityCreateInfoEXT *global_priority)
1163 {
1164 queue->_loader_data.loaderMagic = ICD_LOADER_MAGIC;
1165 queue->device = device;
1166 queue->queue_family_index = queue_family_index;
1167 queue->queue_idx = idx;
1168 queue->flags = flags;
1169 list_inithead(&queue->pending_submissions);
1170 pthread_mutex_init(&queue->pending_mutex, NULL);
1171
1172 pthread_mutex_init(&queue->thread_mutex, NULL);
1173 //queue->thread_submission = NULL;
1174 queue->thread_running = queue->thread_exit = false;
1175 VkResult result = libresoc_create_pthread_cond(&queue->thread_cond);
1176 if (result != VK_SUCCESS)
1177 return vk_error(device->instance, result);
1178
1179 return VK_SUCCESS;
1180 }
1181
1182 static void
1183 libresoc_queue_finish(struct libresoc_queue *queue)
1184 {
1185 //TODO: understand and enable following code
1186 // if (queue->thread_running) {
1187 // p_atomic_set(&queue->thread_exit, true);
1188 // pthread_cond_broadcast(&queue->thread_cond);
1189 // pthread_join(queue->submission_thread, NULL);
1190 // }
1191 // pthread_cond_destroy(&queue->thread_cond);
1192 // pthread_mutex_destroy(&queue->pending_mutex);
1193 // pthread_mutex_destroy(&queue->thread_mutex);
1194 //
1195 // if (queue->hw_ctx)
1196 // queue->device->ws->ctx_destroy(queue->hw_ctx);
1197 //
1198 // if (queue->initial_full_flush_preamble_cs)
1199 // queue->device->ws->cs_destroy(queue->initial_full_flush_preamble_cs);
1200 // if (queue->initial_preamble_cs)
1201 // queue->device->ws->cs_destroy(queue->initial_preamble_cs);
1202 // if (queue->continue_preamble_cs)
1203 // queue->device->ws->cs_destroy(queue->continue_preamble_cs);
1204 // if (queue->descriptor_bo)
1205 // queue->device->ws->buffer_destroy(queue->descriptor_bo);
1206 // if (queue->scratch_bo)
1207 // queue->device->ws->buffer_destroy(queue->scratch_bo);
1208 // if (queue->esgs_ring_bo)
1209 // queue->device->ws->buffer_destroy(queue->esgs_ring_bo);
1210 // if (queue->gsvs_ring_bo)
1211 // queue->device->ws->buffer_destroy(queue->gsvs_ring_bo);
1212 // if (queue->tess_rings_bo)
1213 // queue->device->ws->buffer_destroy(queue->tess_rings_bo);
1214 // if (queue->gds_bo)
1215 // queue->device->ws->buffer_destroy(queue->gds_bo);
1216 // if (queue->gds_oa_bo)
1217 // queue->device->ws->buffer_destroy(queue->gds_oa_bo);
1218 // if (queue->compute_scratch_bo)
1219 // queue->device->ws->buffer_destroy(queue->compute_scratch_bo);
1220 }
1221 VkResult
1222 libresoc_CreateDevice(VkPhysicalDevice physicalDevice,
1223 const VkDeviceCreateInfo *pCreateInfo,
1224 const VkAllocationCallbacks *pAllocator,
1225 VkDevice *pDevice)
1226 {
1227 if (getenv("LIBRESOC_TRACE")) {
1228 fprintf(stderr, "CreateDevice called \n");
1229 }
1230 LIBRESOC_FROM_HANDLE(libresoc_physical_device, physical_device, physicalDevice);
1231 VkResult result;
1232 struct libresoc_device *device;
1233
1234 /* Check enabled features */
1235 if (pCreateInfo->pEnabledFeatures) {
1236 result = check_physical_device_features(physicalDevice,
1237 pCreateInfo->pEnabledFeatures);
1238 if (result != VK_SUCCESS)
1239 return result;
1240 }
1241
1242 device = vk_zalloc2(&physical_device->instance->alloc, pAllocator,
1243 sizeof(*device), 8,
1244 VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
1245 if (!device)
1246 return vk_error(physical_device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
1247
1248 vk_device_init(&device->vk, pCreateInfo,
1249 &physical_device->instance->alloc, pAllocator);
1250
1251 device->instance = physical_device->instance;
1252 device->physical_device = physical_device;
1253
1254 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
1255 const char *ext_name = pCreateInfo->ppEnabledExtensionNames[i];
1256 int index = libresoc_get_device_extension_index(ext_name);
1257 if (index < 0 || !physical_device->supported_extensions.extensions[index]) {
1258 vk_free(&device->vk.alloc, device);
1259 return vk_error(physical_device->instance, VK_ERROR_EXTENSION_NOT_PRESENT);
1260 }
1261
1262 device->enabled_extensions.extensions[index] = true;
1263 }
1264
1265 libresoc_device_init_dispatch(device);
1266
1267 for (unsigned i = 0; i < pCreateInfo->queueCreateInfoCount; i++) {
1268 const VkDeviceQueueCreateInfo *queue_create = &pCreateInfo->pQueueCreateInfos[i];
1269 uint32_t qfi = queue_create->queueFamilyIndex;
1270 const VkDeviceQueueGlobalPriorityCreateInfoEXT *global_priority =
1271 vk_find_struct_const(queue_create->pNext, DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT);
1272
1273
1274 device->queues[qfi] = vk_alloc(&device->vk.alloc,
1275 queue_create->queueCount * sizeof(struct libresoc_queue), 8, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
1276 if (!device->queues[qfi]) {
1277 result = VK_ERROR_OUT_OF_HOST_MEMORY;
1278 goto fail;
1279 }
1280
1281 memset(device->queues[qfi], 0, queue_create->queueCount * sizeof(struct libresoc_queue));
1282
1283 device->queue_count[qfi] = queue_create->queueCount;
1284
1285 for (unsigned q = 0; q < queue_create->queueCount; q++) {
1286 result = libresoc_queue_init(device, &device->queues[qfi][q],
1287 qfi, q, queue_create->flags,
1288 global_priority);
1289 if (result != VK_SUCCESS)
1290 goto fail;
1291 }
1292 }
1293
1294 if (result != VK_SUCCESS)
1295 goto fail;
1296
1297 VkPipelineCacheCreateInfo ci;
1298 ci.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
1299 ci.pNext = NULL;
1300 ci.flags = 0;
1301 ci.pInitialData = NULL;
1302 ci.initialDataSize = 0;
1303 VkPipelineCache pc;
1304 result = libresoc_CreatePipelineCache(libresoc_device_to_handle(device),
1305 &ci, NULL, &pc);
1306 if (result != VK_SUCCESS)
1307 goto fail;
1308
1309 *pDevice = libresoc_device_to_handle(device);
1310 return VK_SUCCESS;
1311
1312 fail:
1313 libresoc_DestroyPipelineCache(libresoc_device_to_handle(device), pc, NULL);
1314 for (unsigned i = 0; i < LIBRESOC_MAX_QUEUE_FAMILIES; i++) {
1315 for (unsigned q = 0; q < device->queue_count[i]; q++)
1316 libresoc_queue_finish(&device->queues[i][q]);
1317 if (device->queue_count[i])
1318 vk_free(&device->vk.alloc, device->queues[i]);
1319 }
1320
1321 vk_free(&device->vk.alloc, device);
1322 return result;
1323 }
1324
1325 void
1326 libresoc_DestroyDevice(VkDevice _device,
1327 const VkAllocationCallbacks *pAllocator)
1328 {
1329 if (getenv("LIBRESOC_TRACE")) {
1330 fprintf(stderr, "DestroyDevice called. \n");
1331 }
1332 /* FIXME: stub */
1333 }
1334
1335 void libresoc_GetDeviceQueue(
1336 VkDevice _device,
1337 uint32_t queueFamilyIndex,
1338 uint32_t queueIndex,
1339 VkQueue* pQueue)
1340 {
1341 if (getenv("LIBRESOC_TRACE")) {
1342 fprintf(stderr, "GetDeviceQueue called. \n");
1343 }
1344 LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
1345 struct libresoc_queue *queue;
1346
1347 queue = &device->queues[queueFamilyIndex][queueIndex];
1348 *pQueue = libresoc_queue_to_handle(queue);
1349 }
1350
1351 VkResult libresoc_QueueWaitIdle(
1352 VkQueue _queue)
1353 {
1354 LIBRESOC_FROM_HANDLE(libresoc_queue, queue, _queue);
1355
1356 pthread_mutex_lock(&queue->pending_mutex);
1357 while (!list_is_empty(&queue->pending_submissions)) {
1358 pthread_cond_wait(&queue->device->timeline_cond, &queue->pending_mutex);
1359 }
1360 pthread_mutex_unlock(&queue->pending_mutex);
1361
1362 return VK_SUCCESS;
1363 }
1364
1365 VkResult libresoc_DeviceWaitIdle(
1366 VkDevice _device)
1367 {
1368 LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
1369
1370 for (unsigned i = 0; i < LIBRESOC_MAX_QUEUE_FAMILIES; i++) {
1371 for (unsigned q = 0; q < device->queue_count[i]; q++) {
1372 VkResult result =
1373 libresoc_QueueWaitIdle(libresoc_queue_to_handle(&device->queues[i][q]));
1374
1375 if (result != VK_SUCCESS)
1376 return result;
1377 }
1378 }
1379 return VK_SUCCESS;
1380 }
1381
1382 void libresoc_GetPhysicalDeviceProperties2(
1383 VkPhysicalDevice physicalDevice,
1384 VkPhysicalDeviceProperties2 *pProperties)
1385 {
1386 LIBRESOC_FROM_HANDLE(libresoc_physical_device, pdevice, physicalDevice);
1387 libresoc_GetPhysicalDeviceProperties(physicalDevice, &pProperties->properties);
1388 //TODO: add more stuffs when required
1389 }
1390
1391 void libresoc_GetPhysicalDeviceFeatures2(
1392 VkPhysicalDevice physicalDevice,
1393 VkPhysicalDeviceFeatures2 *pFeatures)
1394 {
1395 LIBRESOC_FROM_HANDLE(libresoc_physical_device, pdevice, physicalDevice);
1396 libresoc_GetPhysicalDeviceFeatures(physicalDevice, &pFeatures->features);
1397 }
1398
1399 void libresoc_GetPhysicalDeviceQueueFamilyProperties2(
1400 VkPhysicalDevice physicalDevice,
1401 uint32_t* pCount,
1402 VkQueueFamilyProperties2 *pQueueFamilyProperties)
1403 {
1404 LIBRESOC_FROM_HANDLE(libresoc_physical_device, pdevice, physicalDevice);
1405 if (!pQueueFamilyProperties) {
1406 libresoc_get_physical_device_queue_family_properties(pdevice, pCount, NULL);
1407 return;
1408 }
1409 VkQueueFamilyProperties *properties[] = {
1410 &pQueueFamilyProperties[0].queueFamilyProperties,
1411 &pQueueFamilyProperties[1].queueFamilyProperties,
1412 &pQueueFamilyProperties[2].queueFamilyProperties,
1413 };
1414 libresoc_get_physical_device_queue_family_properties(pdevice, pCount, properties);
1415 assert(*pCount <= 3);
1416 }
1417
1418 static void
1419 libresoc_get_memory_budget_properties(VkPhysicalDevice physicalDevice,
1420 VkPhysicalDeviceMemoryBudgetPropertiesEXT *memoryBudget)
1421 {
1422 //TODO: stub
1423 }
1424
1425 void libresoc_GetPhysicalDeviceMemoryProperties2(
1426 VkPhysicalDevice physicalDevice,
1427 VkPhysicalDeviceMemoryProperties2 *pMemoryProperties)
1428 {
1429 libresoc_GetPhysicalDeviceMemoryProperties(physicalDevice,
1430 &pMemoryProperties->memoryProperties);
1431
1432 VkPhysicalDeviceMemoryBudgetPropertiesEXT *memory_budget =
1433 vk_find_struct(pMemoryProperties->pNext,
1434 PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT);
1435 if (memory_budget)
1436 libresoc_get_memory_budget_properties(physicalDevice, memory_budget);
1437 }
1438
1439 VkResult libresoc_CreateSemaphore(
1440 VkDevice _device,
1441 const VkSemaphoreCreateInfo* pCreateInfo,
1442 const VkAllocationCallbacks* pAllocator,
1443 VkSemaphore* pSemaphore)
1444 {
1445 //TODO: minimal things as of now, add more complex code as required
1446 LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
1447 struct libresoc_semaphore *sem = vk_alloc2(&device->vk.alloc, pAllocator,
1448 sizeof(*sem), 8,
1449 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
1450 if (!sem)
1451 return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
1452
1453 vk_object_base_init(&device->vk, &sem->base,
1454 VK_OBJECT_TYPE_SEMAPHORE);
1455
1456 *pSemaphore = libresoc_semaphore_to_handle(sem);
1457 return VK_SUCCESS;
1458 }
1459
1460 void libresoc_GetImageMemoryRequirements(
1461 VkDevice _device,
1462 VkImage _image,
1463 VkMemoryRequirements* pMemoryRequirements)
1464 {
1465 LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
1466 LIBRESOC_FROM_HANDLE(libresoc_image, image, _image);
1467
1468 pMemoryRequirements->memoryTypeBits = (1u << device->physical_device->memory_properties.memoryTypeCount) - 1;
1469
1470 pMemoryRequirements->size = image->size;
1471 pMemoryRequirements->alignment = image->alignment;
1472 }
1473
1474 void libresoc_GetImageMemoryRequirements2(
1475 VkDevice device,
1476 const VkImageMemoryRequirementsInfo2 *pInfo,
1477 VkMemoryRequirements2 *pMemoryRequirements)
1478 {
1479 libresoc_GetImageMemoryRequirements(device, pInfo->image,
1480 &pMemoryRequirements->memoryRequirements);
1481 }
1482
1483 VkResult libresoc_BindImageMemory2(VkDevice device,
1484 uint32_t bindInfoCount,
1485 const VkBindImageMemoryInfo *pBindInfos)
1486 {
1487 for (uint32_t i = 0; i < bindInfoCount; ++i) {
1488 LIBRESOC_FROM_HANDLE(libresoc_device_memory, mem, pBindInfos[i].memory);
1489 LIBRESOC_FROM_HANDLE(libresoc_image, image, pBindInfos[i].image);
1490
1491 if (mem) {
1492 // image->bo = mem->bo;
1493 // image->offset = pBindInfos[i].memoryOffset;
1494 } else {
1495 // image->bo = NULL;
1496 // image->offset = 0;
1497 }
1498 }
1499 return VK_SUCCESS;
1500 }
1501
1502
1503 VkResult libresoc_BindImageMemory(
1504 VkDevice device,
1505 VkImage image,
1506 VkDeviceMemory memory,
1507 VkDeviceSize memoryOffset)
1508 {
1509 const VkBindImageMemoryInfo info = {
1510 .sType = VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO,
1511 .image = image,
1512 .memory = memory,
1513 .memoryOffset = memoryOffset
1514 };
1515
1516 return libresoc_BindImageMemory2(device, 1, &info);
1517 }
1518
1519 static VkResult libresoc_queue_submit(struct libresoc_queue *queue,
1520 const struct libresoc_queue_submission *submission)
1521 {
1522 return VK_SUCCESS;
1523 // struct libresoc_deferred_queue_submission *deferred = NULL;
1524
1525 // VkResult result = libresoc_create_deferred_submission(queue, submission, &deferred);
1526 // if (result != VK_SUCCESS)
1527 // return result;
1528
1529 // struct list_head processing_list;
1530 // list_inithead(&processing_list);
1531
1532 // result = libresoc_queue_enqueue_submission(deferred, &processing_list);
1533 // if (result != VK_SUCCESS) {
1534 // /* If anything is in the list we leak. */
1535 // assert(list_is_empty(&processing_list));
1536 // return result;
1537 // }
1538 // return libresoc_process_submissions(&processing_list);
1539 }
1540
1541 /* Signals fence as soon as all the work currently put on queue is done. */
1542 static VkResult libresoc_signal_fence(struct libresoc_queue *queue,
1543 VkFence fence)
1544 {
1545 return libresoc_queue_submit(queue, &(struct libresoc_queue_submission) {
1546 .fence = fence
1547 });
1548 }
1549
1550 static bool libresoc_submit_has_effects(const VkSubmitInfo *info)
1551 {
1552 return info->commandBufferCount ||
1553 info->waitSemaphoreCount ||
1554 info->signalSemaphoreCount;
1555 }
1556
1557 VkResult libresoc_QueueSubmit(
1558 VkQueue _queue,
1559 uint32_t submitCount,
1560 const VkSubmitInfo* pSubmits,
1561 VkFence fence)
1562 {
1563 LIBRESOC_FROM_HANDLE(libresoc_queue, queue, _queue);
1564 VkResult result;
1565 uint32_t fence_idx = 0;
1566 bool flushed_caches = false;
1567
1568 if (fence != VK_NULL_HANDLE) {
1569 for (uint32_t i = 0; i < submitCount; ++i)
1570 if (libresoc_submit_has_effects(pSubmits + i))
1571 fence_idx = i;
1572 } else
1573 fence_idx = UINT32_MAX;
1574
1575 for (uint32_t i = 0; i < submitCount; i++) {
1576 if (!libresoc_submit_has_effects(pSubmits + i) && fence_idx != i)
1577 continue;
1578
1579 VkPipelineStageFlags wait_dst_stage_mask = 0;
1580 for (unsigned j = 0; j < pSubmits[i].waitSemaphoreCount; ++j) {
1581 wait_dst_stage_mask |= pSubmits[i].pWaitDstStageMask[j];
1582 }
1583
1584 const VkTimelineSemaphoreSubmitInfo *timeline_info =
1585 vk_find_struct_const(pSubmits[i].pNext, TIMELINE_SEMAPHORE_SUBMIT_INFO);
1586
1587 result = libresoc_queue_submit(queue, &(struct libresoc_queue_submission) {
1588 .cmd_buffers = pSubmits[i].pCommandBuffers,
1589 .cmd_buffer_count = pSubmits[i].commandBufferCount,
1590 .wait_dst_stage_mask = wait_dst_stage_mask,
1591 .flush_caches = !flushed_caches,
1592 .wait_semaphores = pSubmits[i].pWaitSemaphores,
1593 .wait_semaphore_count = pSubmits[i].waitSemaphoreCount,
1594 .signal_semaphores = pSubmits[i].pSignalSemaphores,
1595 .signal_semaphore_count = pSubmits[i].signalSemaphoreCount,
1596 .fence = i == fence_idx ? fence : VK_NULL_HANDLE,
1597 .wait_values = timeline_info ? timeline_info->pWaitSemaphoreValues : NULL,
1598 .wait_value_count = timeline_info && timeline_info->pWaitSemaphoreValues ? timeline_info->waitSemaphoreValueCount : 0,
1599 .signal_values = timeline_info ? timeline_info->pSignalSemaphoreValues : NULL,
1600 .signal_value_count = timeline_info && timeline_info->pSignalSemaphoreValues ? timeline_info->signalSemaphoreValueCount : 0,
1601 });
1602 if (result != VK_SUCCESS)
1603 return result;
1604
1605 flushed_caches = true;
1606 }
1607
1608 if (fence != VK_NULL_HANDLE && !submitCount) {
1609 result = libresoc_signal_fence(queue, fence);
1610 if (result != VK_SUCCESS)
1611 return result;
1612 }
1613
1614 return VK_SUCCESS;
1615 }
1616
1617 VkResult libresoc_CreateFence(
1618 VkDevice _device,
1619 const VkFenceCreateInfo* pCreateInfo,
1620 const VkAllocationCallbacks* pAllocator,
1621 VkFence* pFence)
1622 {
1623 LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
1624 const VkExportFenceCreateInfo *export =
1625 vk_find_struct_const(pCreateInfo->pNext, EXPORT_FENCE_CREATE_INFO);
1626 VkExternalFenceHandleTypeFlags handleTypes =
1627 export ? export->handleTypes : 0;
1628 struct libresoc_fence *fence;
1629
1630 fence = vk_zalloc2(&device->vk.alloc, pAllocator, sizeof(*fence), 8,
1631 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
1632 if (!fence)
1633 return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
1634
1635 vk_object_base_init(&device->vk, &fence->base, VK_OBJECT_TYPE_FENCE);
1636
1637 // if (device->always_use_syncobj || handleTypes) {
1638 // fence->permanent.kind = LIBRESOC_FENCE_SYNCOBJ;
1639
1640 // bool create_signaled = false;
1641 // if (pCreateInfo->flags & VK_FENCE_CREATE_SIGNALED_BIT)
1642 // create_signaled = true;
1643
1644 // int ret = device->ws->create_syncobj(device->ws, create_signaled,
1645 // &fence->permanent.syncobj);
1646 // if (ret) {
1647 // libresoc_destroy_fence(device, pAllocator, fence);
1648 // return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
1649 // }
1650 // } else {
1651 // fence->permanent.kind = LIBRESOC_FENCE_WINSYS;
1652
1653 // fence->permanent.fence = device->ws->create_fence();
1654 // if (!fence->permanent.fence) {
1655 // vk_free2(&device->vk.alloc, pAllocator, fence);
1656 // libresoc_destroy_fence(device, pAllocator, fence);
1657 // return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
1658 // }
1659 // if (pCreateInfo->flags & VK_FENCE_CREATE_SIGNALED_BIT)
1660 // device->ws->signal_fence(fence->permanent.fence);
1661 // }
1662
1663 *pFence = libresoc_fence_to_handle(fence);
1664
1665 return VK_SUCCESS;
1666 }
1667
1668 VkResult libresoc_MapMemory(
1669 VkDevice _device,
1670 VkDeviceMemory _memory,
1671 VkDeviceSize offset,
1672 VkDeviceSize size,
1673 VkMemoryMapFlags flags,
1674 void** ppData)
1675 {
1676 LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
1677 LIBRESOC_FROM_HANDLE(libresoc_device_memory, mem, _memory);
1678
1679 if (mem == NULL) {
1680 *ppData = NULL;
1681 return VK_SUCCESS;
1682 }
1683
1684 if (mem->user_ptr)
1685 *ppData = mem->user_ptr;
1686 // else
1687 // *ppData = device->ws->buffer_map(mem->bo);
1688
1689 if (*ppData) {
1690 *ppData += offset;
1691 return VK_SUCCESS;
1692 }
1693
1694 return vk_error(device->instance, VK_ERROR_MEMORY_MAP_FAILED);
1695 }
1696
1697 void libresoc_UnmapMemory(
1698 VkDevice _device,
1699 VkDeviceMemory _memory)
1700 {
1701 LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
1702 LIBRESOC_FROM_HANDLE(libresoc_device_memory, mem, _memory);
1703
1704 if (mem == NULL)
1705 return;
1706
1707 // if (mem->user_ptr == NULL)
1708 // device->ws->buffer_unmap(mem->bo);
1709 }
1710
1711 VkResult libresoc_WaitForFences(
1712 VkDevice _device,
1713 uint32_t fenceCount,
1714 const VkFence* pFences,
1715 VkBool32 waitAll,
1716 uint64_t timeout)
1717 {
1718 //TODO: stub
1719 return VK_SUCCESS;
1720 }
1721
1722 VkResult libresoc_ResetFences(VkDevice _device,
1723 uint32_t fenceCount,
1724 const VkFence *pFences)
1725 {
1726
1727 //TODO: stub
1728 return VK_SUCCESS;
1729 }
1730
1731 VkResult libresoc_CreateFramebuffer(
1732 VkDevice _device,
1733 const VkFramebufferCreateInfo* pCreateInfo,
1734 const VkAllocationCallbacks* pAllocator,
1735 VkFramebuffer* pFramebuffer)
1736 {
1737 //TODO: stub
1738 return VK_SUCCESS;
1739 }
1740 void libresoc_DestroyBuffer(
1741 VkDevice _device,
1742 VkBuffer _buffer,
1743 const VkAllocationCallbacks* pAllocator)
1744 {}
1745
1746 void libresoc_DestroyFence(
1747 VkDevice _device,
1748 VkFence _fence,
1749 const VkAllocationCallbacks* pAllocator)
1750 {}