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