2 * Copyright © 2019 Raspberry Pi
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
28 #include <sys/sysinfo.h>
31 #include "util/debug.h"
32 #include "util/driconf.h"
33 #include "libresoc_private.h"
37 struct libresoc_deferred_queue_submission
{
38 struct libresoc_queue
*queue
;
39 VkCommandBuffer
*cmd_buffers
;
40 uint32_t cmd_buffer_count
;
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
;
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
;
56 uint64_t *wait_values
;
57 uint64_t *signal_values
;
59 struct libresoc_semaphore_part
*temporary_semaphore_parts
;
60 uint32_t temporary_semaphore_part_count
;
62 struct list_head queue_pending_list
;
63 uint32_t submission_wait_count
;
64 struct libresoc_timeline_waiter
*wait_nodes
;
66 struct list_head processing_list
;
69 struct libresoc_queue_submission
{
70 const VkCommandBuffer
*cmd_buffers
;
71 uint32_t cmd_buffer_count
;
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
;
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
;
87 const uint64_t *wait_values
;
88 uint32_t wait_value_count
;
89 const uint64_t *signal_values
;
90 uint32_t signal_value_count
;
94 libresoc_free_memory(struct libresoc_device
*device
,
95 const VkAllocationCallbacks
* pAllocator
,
96 struct libresoc_device_memory
*mem
)
101 vk_object_base_finish(&mem
->base
);
102 vk_free2(&device
->vk
.alloc
, pAllocator
, mem
);
105 static VkResult
libresoc_alloc_memory(struct libresoc_device
*device
,
106 const VkMemoryAllocateInfo
* pAllocateInfo
,
107 const VkAllocationCallbacks
* pAllocator
,
108 VkDeviceMemory
* pMem
)
110 struct libresoc_device_memory
*mem
;
114 assert(pAllocateInfo
->sType
== VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO
);
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
);
125 const struct wsi_memory_allocate_info
*wsi_info
=
126 vk_find_struct_const(pAllocateInfo
->pNext
, WSI_MEMORY_ALLOCATE_INFO_MESA
);
129 mem
= vk_zalloc2(&device
->vk
.alloc
, pAllocator
, sizeof(*mem
), 8,
130 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
132 return vk_error(device
->instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
134 vk_object_base_init(&device
->vk
, &mem
->base
,
135 VK_OBJECT_TYPE_DEVICE_MEMORY
);
138 mem
->image
= libresoc_image_from_handle(dedicate_info
->image
);
139 //mem->buffer = libresoc_buffer_from_handle(dedicate_info->buffer);
142 //mem->buffer = NULL;
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);
150 // priority_float = priority_ext->priority;
152 // unsigned priority = MIN2(LIBRESOC_BO_PRIORITY_APPLICATION_MAX - 1,
153 // (int)(priority_float * LIBRESOC_BO_PRIORITY_APPLICATION_MAX));
155 mem
->user_ptr
= NULL
;
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,
167 // result = VK_ERROR_INVALID_EXTERNAL_HANDLE;
170 // close(import_info->fd);
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);
178 // struct libresoc_image_create_info create_info = {
179 // .no_metadata_planes = true,
180 // .bo_metadata = &metadata
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);
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,
198 // result = VK_ERROR_INVALID_EXTERNAL_HANDLE;
201 // mem->user_ptr = host_ptr_info->pHostPointer;
204 uint64_t alloc_size
= align_u64(pAllocateInfo
->allocationSize
, 4096);
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];
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;
218 if (device
->overallocation_disallowed
) {
219 uint64_t total_size
=
220 device
->physical_device
->memory_properties
.memoryHeaps
[heap_index
].size
;
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
;
228 device
->allocated_memory_size
[heap_index
] += alloc_size
;
229 mtx_unlock(&device
->overallocation_mutex
);
232 // mem->bo = device->ws->buffer_create(device->ws, alloc_size, device->physical_device->rad_info.max_alignment,
233 // domain, flags, priority);
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);
241 // result = VK_ERROR_OUT_OF_DEVICE_MEMORY;
245 mem
->heap_index
= heap_index
;
246 mem
->alloc_size
= alloc_size
;
250 // result = libresoc_bo_list_add(device, mem->bo);
251 // if (result != VK_SUCCESS)
255 *pMem
= libresoc_device_memory_to_handle(mem
);
260 libresoc_free_memory(device
, pAllocator
,mem
);
265 VkResult
libresoc_AllocateMemory(
267 const VkMemoryAllocateInfo
* pAllocateInfo
,
268 const VkAllocationCallbacks
* pAllocator
,
269 VkDeviceMemory
* pMem
)
271 LIBRESOC_FROM_HANDLE(libresoc_device
, device
, _device
);
272 return libresoc_alloc_memory(device
, pAllocateInfo
, pAllocator
, pMem
);
275 void libresoc_FreeMemory(
278 const VkAllocationCallbacks
* pAllocator
)
280 LIBRESOC_FROM_HANDLE(libresoc_device
, device
, _device
);
281 LIBRESOC_FROM_HANDLE(libresoc_device_memory
, mem
, _mem
);
283 libresoc_free_memory(device
, pAllocator
, mem
);
286 libresoc_create_pthread_cond(pthread_cond_t
*cond
)
288 pthread_condattr_t condattr
;
289 if (pthread_condattr_init(&condattr
)) {
290 return VK_ERROR_INITIALIZATION_FAILED
;
293 if (pthread_condattr_setclock(&condattr
, CLOCK_MONOTONIC
)) {
294 pthread_condattr_destroy(&condattr
);
295 return VK_ERROR_INITIALIZATION_FAILED
;
297 if (pthread_cond_init(cond
, &condattr
)) {
298 pthread_condattr_destroy(&condattr
);
299 return VK_ERROR_INITIALIZATION_FAILED
;
301 pthread_condattr_destroy(&condattr
);
306 libresoc_EnumerateInstanceExtensionProperties(const char *pLayerName
,
307 uint32_t *pPropertyCount
,
308 VkExtensionProperties
*pProperties
)
310 if (getenv("LIBRESOC_TRACE")) {
311 fprintf(stderr
, "EnumerateInstanceExtensionProperties called for: %s \n", pLayerName
);
313 VK_OUTARRAY_MAKE(out
, pProperties
, pPropertyCount
);
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
];
323 return vk_outarray_status(&out
);
327 default_alloc_func(void *pUserData
, size_t size
, size_t align
,
328 VkSystemAllocationScope allocationScope
)
334 default_realloc_func(void *pUserData
, void *pOriginal
, size_t size
,
335 size_t align
, VkSystemAllocationScope allocationScope
)
337 return realloc(pOriginal
, size
);
341 default_free_func(void *pUserData
, void *pMemory
)
346 static const VkAllocationCallbacks default_alloc
= {
348 .pfnAllocation
= default_alloc_func
,
349 .pfnReallocation
= default_realloc_func
,
350 .pfnFree
= default_free_func
,
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
},
386 libresoc_get_debug_option_name(int id
)
388 assert(id
< ARRAY_SIZE(libresoc_debug_options
) - 1);
389 return libresoc_debug_options
[id
].string
;
392 static const char libresoc_dri_options_xml
[] =
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")
401 DRI_CONF_SECTION_DEBUG
402 DRI_CONF_VK_WSI_FORCE_BGRA8_UNORM_FIRST("false")
406 static void libresoc_init_dri_options(struct libresoc_instance
*instance
)
408 driParseOptionInfo(&instance
->available_dri_options
, libresoc_dri_options_xml
);
409 driParseConfigFiles(&instance
->dri_options
,
410 &instance
->available_dri_options
,
412 instance
->app_info
.app_name
,
413 instance
->app_info
.app_version
,
414 instance
->engineName
,
415 instance
->engineVersion
);
419 libresoc_CreateInstance(const VkInstanceCreateInfo
*pCreateInfo
,
420 const VkAllocationCallbacks
*pAllocator
,
421 VkInstance
*pInstance
)
423 if (getenv("LIBRESOC_TRACE")) {
424 fprintf(stderr
, "CreateInstance called. \n");
426 struct libresoc_instance
*instance
;
428 instance
= vk_zalloc2(&default_alloc
, pAllocator
, sizeof(*instance
), 8,
429 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE
);
431 return vk_error(NULL
, VK_ERROR_OUT_OF_HOST_MEMORY
);
433 vk_object_base_init(NULL
, &instance
->base
, VK_OBJECT_TYPE_INSTANCE
);
436 instance
->alloc
= *pAllocator
;
438 instance
->alloc
= default_alloc
;
439 if (pCreateInfo
->pApplicationInfo
) {
440 const VkApplicationInfo
*app
= pCreateInfo
->pApplicationInfo
;
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
;
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
++) {
453 for (idx
= 0; idx
< LIBRESOC_INSTANCE_EXTENSION_COUNT
; idx
++) {
454 if (!strcmp(pCreateInfo
->ppEnabledExtensionNames
[i
],
455 libresoc_instance_extensions
[idx
].extensionName
))
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
);
466 instance
->enabled_extensions
.extensions
[idx
] = true;
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.
472 if (!libresoc_instance_entrypoint_is_enabled(i
, instance
->apiVersion
,
473 &instance
->enabled_extensions
)) {
474 instance
->dispatch
.entrypoints
[i
] = NULL
;
476 instance
->dispatch
.entrypoints
[i
] =
477 libresoc_instance_dispatch_table
.entrypoints
[i
];
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.
484 if (!libresoc_physical_device_entrypoint_is_enabled(i
, instance
->apiVersion
,
485 &instance
->enabled_extensions
)) {
486 instance
->physical_device_dispatch
.entrypoints
[i
] = NULL
;
488 instance
->physical_device_dispatch
.entrypoints
[i
] =
489 libresoc_physical_device_dispatch_table
.entrypoints
[i
];
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.
497 if (!libresoc_device_entrypoint_is_enabled(i
, instance
->apiVersion
,
498 &instance
->enabled_extensions
, NULL
)) {
499 instance
->device_dispatch
.entrypoints
[i
] = NULL
;
501 instance
->device_dispatch
.entrypoints
[i
] =
502 libresoc_device_dispatch_table
.entrypoints
[i
];
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
);
514 libresoc_DestroyInstance(VkInstance _instance
,
515 const VkAllocationCallbacks
*pAllocator
)
517 if (getenv("LIBRESOC_TRACE")) {
518 fprintf(stderr
, "DestroyInstance called. \n");
524 libresoc_physical_device_init_mem_types(struct libresoc_physical_device
*device
)
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;
531 vram_index
= device
->memory_properties
.memoryHeapCount
++;
532 device
->memory_properties
.memoryHeaps
[vram_index
] = (VkMemoryHeap
) {
534 .flags
= VK_MEMORY_HEAP_DEVICE_LOCAL_BIT
,
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
,
545 unsigned type_count
= 0;
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
,
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
,
563 device
->memory_properties
.memoryTypeCount
= type_count
;
568 libresoc_physical_device_try_create(struct libresoc_instance
*instance
,
569 struct libresoc_physical_device
**device_out
)
575 struct libresoc_physical_device
*device
=
576 vk_zalloc2(&instance
->alloc
, NULL
, sizeof(*device
), 8,
577 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE
);
579 result
= vk_error(instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
583 device
->_loader_data
.loaderMagic
= ICD_LOADER_MAGIC
;
584 device
->instance
= instance
;
586 device
->master_fd
= master_fd
;
587 device
->local_fd
= fd
;
588 libresoc_physical_device_init_mem_types(device
);
590 libresoc_physical_device_get_supported_extensions(device
,
591 &device
->supported_extensions
);
592 result
= libresoc_init_wsi(device
);
593 if (result
!= VK_SUCCESS
) {
596 snprintf(device
->name
, sizeof(device
->name
),
598 *device_out
= device
;
599 //TODO: incase of failures need to deallocate and cleanup various allocation properly.
604 libresoc_enumerate_physical_devices(struct libresoc_instance
*instance
)
607 if (instance
->physical_devices_enumerated
)
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
615 struct libresoc_physical_device
*pdevice
;
617 result
= libresoc_physical_device_try_create(instance
, &pdevice
);
618 if (result
!= VK_SUCCESS
)
621 list_addtail(&pdevice
->link
, &instance
->physical_devices
);
627 libresoc_EnumeratePhysicalDevices(VkInstance _instance
,
628 uint32_t *pPhysicalDeviceCount
,
629 VkPhysicalDevice
*pPhysicalDevices
)
631 if (getenv("LIBRESOC_TRACE")) {
632 fprintf(stderr
, "EnumeratePhysicalDevices called\n");
634 LIBRESOC_FROM_HANDLE(libresoc_instance
, instance
, _instance
);
635 VK_OUTARRAY_MAKE(out
, pPhysicalDevices
, pPhysicalDeviceCount
);
637 VkResult result
= libresoc_enumerate_physical_devices(instance
);
638 if (result
!= VK_SUCCESS
)
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
);
648 return vk_outarray_status(&out
);
652 libresoc_GetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice
,
653 VkPhysicalDeviceFeatures
*pFeatures
)
655 if (getenv("LIBRESOC_TRACE")) {
656 fprintf(stderr
, "GetPhysicalDeviceFeatures called. \n");
658 //LIBRESOC_FROM_HANDLE(libresoc_physical_device, pdevice, physicalDevice);
659 memset(pFeatures
, 0, sizeof(*pFeatures
));
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,
671 .multiDrawIndirect
= true,
672 .drawIndirectFirstInstance
= true,
674 .depthBiasClamp
= true,
675 .fillModeNonSolid
= 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,
704 .sparseBinding
= true,
705 .variableMultisampleRate
= true,
706 .shaderResourceMinLod
= true,
707 .inheritedQueries
= true,
712 libresoc_max_descriptor_set_size()
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 */);
730 libresoc_GetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice
,
731 VkPhysicalDeviceProperties
*pProperties
)
733 if (getenv("LIBRESOC_TRACE")) {
734 fprintf(stderr
, "GetPhysicalDeviceProperties called. \n");
736 LIBRESOC_FROM_HANDLE(libresoc_physical_device
, pdevice
, physicalDevice
);
737 VkSampleCountFlags sample_counts
= 0xf;
739 size_t max_descriptor_set_size
= libresoc_max_descriptor_set_size();
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
= {
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,
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
,
861 .sparseProperties
= {0},
864 strcpy(pProperties
->deviceName
, pdevice
->name
);
865 memcpy(pProperties
->pipelineCacheUUID
, pdevice
->cache_uuid
, VK_UUID_SIZE
);
868 static void libresoc_get_physical_device_queue_family_properties(
869 struct libresoc_physical_device
* pdevice
,
871 VkQueueFamilyProperties
** pQueueFamilyProperties
)
873 int num_queue_families
= 1;
876 if (pQueueFamilyProperties
== NULL
) {
877 *pCount
= num_queue_families
;
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
,
892 .timestampValidBits
= 64,
893 .minImageTransferGranularity
= (VkExtent3D
) { 1, 1, 1 },
902 libresoc_GetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice
,
904 VkQueueFamilyProperties
*pQueueFamilyProperties
)
906 if (getenv("LIBRESOC_TRACE")) {
907 fprintf(stderr
, "GetPhysicalDeviceQueueFamilyProperites called. \n");
909 LIBRESOC_FROM_HANDLE(libresoc_physical_device
, pdevice
, physicalDevice
);
910 if (!pQueueFamilyProperties
) {
911 libresoc_get_physical_device_queue_family_properties(pdevice
, pCount
, NULL
);
914 VkQueueFamilyProperties
*properties
[] = {
915 pQueueFamilyProperties
+ 0,
916 pQueueFamilyProperties
+ 1,
917 pQueueFamilyProperties
+ 2,
919 libresoc_get_physical_device_queue_family_properties(pdevice
, pCount
, properties
);
920 assert(*pCount
<= 3);
924 libresoc_GetPhysicalDeviceMemoryProperties(VkPhysicalDevice physicalDevice
,
925 VkPhysicalDeviceMemoryProperties
*pMemoryProperties
)
927 if (getenv("LIBRESOC_TRACE")) {
928 fprintf(stderr
, "GetPhysicalDEviceMemoryProperties called. \n");
930 LIBRESOC_FROM_HANDLE(libresoc_physical_device
, physical_device
, physicalDevice
);
932 *pMemoryProperties
= physical_device
->memory_properties
;
937 //libresoc_GetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties *pFormatProperties) {
939 // if (getenv("LIBRESOC_TRACE")) {
940 // fprintf(stderr, "GetPhysicalDeviceFormatProperties called. \n");
946 // libresoc_GetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkImageFormatProperties* pImageFormatProperties)
948 // if (getenv("LIBRESOC_TRACE")) {
949 // fprintf(stderr, "GetPhysicalDEviceImageFormatProperties called. \n");
953 // return VK_SUCCESS;
956 // libresoc_GetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkSampleCountFlagBits samples, VkImageUsageFlags usage, VkImageTiling tiling, uint32_t* pPropertyCount, VkSparseImageFormatProperties* pProperties)
958 // if (getenv("LIBRESOC_TRACE")) {
959 // fprintf(stderr, "GetPhysicalDeviceSparseImageFormatProperties called. \n");
964 libresoc_GetInstanceProcAddr(VkInstance _instance
,
967 if (getenv("LIBRESOC_TRACE")) {
968 fprintf(stderr
, "GetInstanceProcAddr called for: %s \n", pName
);
970 LIBRESOC_FROM_HANDLE(libresoc_instance
, instance
, _instance
);
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.
979 #define LOOKUP_LIBRESOC_ENTRYPOINT(entrypoint) \
980 if (strcmp(pName, "vk" #entrypoint) == 0) \
981 return (PFN_vkVoidFunction)libresoc_##entrypoint
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
);
999 #undef LOOKUP_LIBRESOC_ENTRYPOINT
1001 if (instance
== NULL
)
1004 int idx
= libresoc_get_instance_entrypoint_index(pName
);
1006 return instance
->dispatch
.entrypoints
[idx
];
1008 idx
= libresoc_get_physical_device_entrypoint_index(pName
);
1010 return instance
->physical_device_dispatch
.entrypoints
[idx
];
1012 idx
= libresoc_get_device_entrypoint_index(pName
);
1014 return instance
->device_dispatch
.entrypoints
[idx
];
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.
1023 VKAPI_ATTR PFN_vkVoidFunction
1024 VKAPI_CALL
vk_icdGetInstanceProcAddr(VkInstance instance
,
1028 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
1029 vk_icdGetInstanceProcAddr(VkInstance instance
,
1032 if (getenv("LIBRESOC_TRACE")) {
1033 fprintf(stderr
, "vk_icdGetInstanceProcAddr called for: %s \n", pName
);
1035 return libresoc_GetInstanceProcAddr(instance
, pName
);
1039 libresoc_GetDeviceProcAddr(VkDevice _device
,
1042 if (getenv("LIBRESOC_TRACE")) {
1043 fprintf(stderr
, "GetDeviceProcAddr called for: %s \n", pName
);
1045 LIBRESOC_FROM_HANDLE(libresoc_device
, device
, _device
);
1047 if (!device
|| !pName
)
1050 int idx
= libresoc_get_device_entrypoint_index(pName
);
1054 return device
->dispatch
.entrypoints
[idx
];
1057 /* With version 4+ of the loader interface the ICD should expose
1058 * vk_icdGetPhysicalDeviceProcAddr()
1061 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
1062 vk_icdGetPhysicalDeviceProcAddr(VkInstance _instance
,
1066 vk_icdGetPhysicalDeviceProcAddr(VkInstance _instance
,
1069 if (getenv("LIBRESOC_TRACE")) {
1070 fprintf(stderr
, "vk_icdGetPhysicalDeviceProcAddr called for: %s \n", pName
);
1072 LIBRESOC_FROM_HANDLE(libresoc_instance
, instance
, _instance
);
1074 if (!pName
|| !instance
)
1077 int idx
= libresoc_get_physical_device_entrypoint_index(pName
);
1081 return instance
->physical_device_dispatch
.entrypoints
[idx
];
1085 libresoc_EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice
,
1086 const char *pLayerName
,
1087 uint32_t *pPropertyCount
,
1088 VkExtensionProperties
*pProperties
)
1090 if (getenv("LIBRESOC_TRACE")) {
1091 fprintf(stderr
, "EnumerateDeviceExtensionProperties called for layer: %s \n", pLayerName
);
1093 LIBRESOC_FROM_HANDLE(libresoc_physical_device
, device
, physicalDevice
);
1094 VK_OUTARRAY_MAKE(out
, pProperties
, pPropertyCount
);
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
];
1104 return vk_outarray_status(&out
);
1108 libresoc_device_init_dispatch(struct libresoc_device
*device
)
1110 const struct libresoc_instance
*instance
= device
->physical_device
->instance
;
1111 const struct libresoc_device_dispatch_table
*dispatch_table_layer
= NULL
;
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.
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
];
1126 device
->dispatch
.entrypoints
[i
] =
1127 libresoc_device_dispatch_table
.entrypoints
[i
];
1133 check_physical_device_features(VkPhysicalDevice physicalDevice
,
1134 const VkPhysicalDeviceFeatures
*features
)
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
);
1149 static int libresoc_get_device_extension_index(const char *name
)
1151 for (unsigned i
= 0; i
< LIBRESOC_DEVICE_EXTENSION_COUNT
; ++i
) {
1152 if (strcmp(name
, libresoc_device_extensions
[i
].extensionName
) == 0)
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
)
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
);
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
);
1183 libresoc_queue_finish(struct libresoc_queue
*queue
)
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);
1191 // pthread_cond_destroy(&queue->thread_cond);
1192 // pthread_mutex_destroy(&queue->pending_mutex);
1193 // pthread_mutex_destroy(&queue->thread_mutex);
1195 // if (queue->hw_ctx)
1196 // queue->device->ws->ctx_destroy(queue->hw_ctx);
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);
1222 libresoc_CreateDevice(VkPhysicalDevice physicalDevice
,
1223 const VkDeviceCreateInfo
*pCreateInfo
,
1224 const VkAllocationCallbacks
*pAllocator
,
1227 if (getenv("LIBRESOC_TRACE")) {
1228 fprintf(stderr
, "CreateDevice called \n");
1230 LIBRESOC_FROM_HANDLE(libresoc_physical_device
, physical_device
, physicalDevice
);
1232 struct libresoc_device
*device
;
1234 /* Check enabled features */
1235 if (pCreateInfo
->pEnabledFeatures
) {
1236 result
= check_physical_device_features(physicalDevice
,
1237 pCreateInfo
->pEnabledFeatures
);
1238 if (result
!= VK_SUCCESS
)
1242 device
= vk_zalloc2(&physical_device
->instance
->alloc
, pAllocator
,
1244 VK_SYSTEM_ALLOCATION_SCOPE_DEVICE
);
1246 return vk_error(physical_device
->instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
1248 vk_device_init(&device
->vk
, pCreateInfo
,
1249 &physical_device
->instance
->alloc
, pAllocator
);
1251 device
->instance
= physical_device
->instance
;
1252 device
->physical_device
= physical_device
;
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
);
1262 device
->enabled_extensions
.extensions
[index
] = true;
1265 libresoc_device_init_dispatch(device
);
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
);
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
;
1281 memset(device
->queues
[qfi
], 0, queue_create
->queueCount
* sizeof(struct libresoc_queue
));
1283 device
->queue_count
[qfi
] = queue_create
->queueCount
;
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
,
1289 if (result
!= VK_SUCCESS
)
1294 if (result
!= VK_SUCCESS
)
1297 VkPipelineCacheCreateInfo ci
;
1298 ci
.sType
= VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO
;
1301 ci
.pInitialData
= NULL
;
1302 ci
.initialDataSize
= 0;
1304 result
= libresoc_CreatePipelineCache(libresoc_device_to_handle(device
),
1306 if (result
!= VK_SUCCESS
)
1309 *pDevice
= libresoc_device_to_handle(device
);
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
]);
1321 vk_free(&device
->vk
.alloc
, device
);
1326 libresoc_DestroyDevice(VkDevice _device
,
1327 const VkAllocationCallbacks
*pAllocator
)
1329 if (getenv("LIBRESOC_TRACE")) {
1330 fprintf(stderr
, "DestroyDevice called. \n");
1335 void libresoc_GetDeviceQueue(
1337 uint32_t queueFamilyIndex
,
1338 uint32_t queueIndex
,
1341 if (getenv("LIBRESOC_TRACE")) {
1342 fprintf(stderr
, "GetDeviceQueue called. \n");
1344 LIBRESOC_FROM_HANDLE(libresoc_device
, device
, _device
);
1345 struct libresoc_queue
*queue
;
1347 queue
= &device
->queues
[queueFamilyIndex
][queueIndex
];
1348 *pQueue
= libresoc_queue_to_handle(queue
);
1351 VkResult
libresoc_QueueWaitIdle(
1354 LIBRESOC_FROM_HANDLE(libresoc_queue
, queue
, _queue
);
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
);
1360 pthread_mutex_unlock(&queue
->pending_mutex
);
1365 VkResult
libresoc_DeviceWaitIdle(
1368 LIBRESOC_FROM_HANDLE(libresoc_device
, device
, _device
);
1370 for (unsigned i
= 0; i
< LIBRESOC_MAX_QUEUE_FAMILIES
; i
++) {
1371 for (unsigned q
= 0; q
< device
->queue_count
[i
]; q
++) {
1373 libresoc_QueueWaitIdle(libresoc_queue_to_handle(&device
->queues
[i
][q
]));
1375 if (result
!= VK_SUCCESS
)
1382 void libresoc_GetPhysicalDeviceProperties2(
1383 VkPhysicalDevice physicalDevice
,
1384 VkPhysicalDeviceProperties2
*pProperties
)
1386 LIBRESOC_FROM_HANDLE(libresoc_physical_device
, pdevice
, physicalDevice
);
1387 libresoc_GetPhysicalDeviceProperties(physicalDevice
, &pProperties
->properties
);
1388 //TODO: add more stuffs when required
1391 void libresoc_GetPhysicalDeviceFeatures2(
1392 VkPhysicalDevice physicalDevice
,
1393 VkPhysicalDeviceFeatures2
*pFeatures
)
1395 LIBRESOC_FROM_HANDLE(libresoc_physical_device
, pdevice
, physicalDevice
);
1396 libresoc_GetPhysicalDeviceFeatures(physicalDevice
, &pFeatures
->features
);
1399 void libresoc_GetPhysicalDeviceQueueFamilyProperties2(
1400 VkPhysicalDevice physicalDevice
,
1402 VkQueueFamilyProperties2
*pQueueFamilyProperties
)
1404 LIBRESOC_FROM_HANDLE(libresoc_physical_device
, pdevice
, physicalDevice
);
1405 if (!pQueueFamilyProperties
) {
1406 libresoc_get_physical_device_queue_family_properties(pdevice
, pCount
, NULL
);
1409 VkQueueFamilyProperties
*properties
[] = {
1410 &pQueueFamilyProperties
[0].queueFamilyProperties
,
1411 &pQueueFamilyProperties
[1].queueFamilyProperties
,
1412 &pQueueFamilyProperties
[2].queueFamilyProperties
,
1414 libresoc_get_physical_device_queue_family_properties(pdevice
, pCount
, properties
);
1415 assert(*pCount
<= 3);
1419 libresoc_get_memory_budget_properties(VkPhysicalDevice physicalDevice
,
1420 VkPhysicalDeviceMemoryBudgetPropertiesEXT
*memoryBudget
)
1425 void libresoc_GetPhysicalDeviceMemoryProperties2(
1426 VkPhysicalDevice physicalDevice
,
1427 VkPhysicalDeviceMemoryProperties2
*pMemoryProperties
)
1429 libresoc_GetPhysicalDeviceMemoryProperties(physicalDevice
,
1430 &pMemoryProperties
->memoryProperties
);
1432 VkPhysicalDeviceMemoryBudgetPropertiesEXT
*memory_budget
=
1433 vk_find_struct(pMemoryProperties
->pNext
,
1434 PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT
);
1436 libresoc_get_memory_budget_properties(physicalDevice
, memory_budget
);
1439 VkResult
libresoc_CreateSemaphore(
1441 const VkSemaphoreCreateInfo
* pCreateInfo
,
1442 const VkAllocationCallbacks
* pAllocator
,
1443 VkSemaphore
* pSemaphore
)
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
,
1449 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
1451 return vk_error(device
->instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
1453 vk_object_base_init(&device
->vk
, &sem
->base
,
1454 VK_OBJECT_TYPE_SEMAPHORE
);
1456 *pSemaphore
= libresoc_semaphore_to_handle(sem
);
1460 void libresoc_GetImageMemoryRequirements(
1463 VkMemoryRequirements
* pMemoryRequirements
)
1465 LIBRESOC_FROM_HANDLE(libresoc_device
, device
, _device
);
1466 LIBRESOC_FROM_HANDLE(libresoc_image
, image
, _image
);
1468 pMemoryRequirements
->memoryTypeBits
= (1u << device
->physical_device
->memory_properties
.memoryTypeCount
) - 1;
1470 pMemoryRequirements
->size
= image
->size
;
1471 pMemoryRequirements
->alignment
= image
->alignment
;
1474 void libresoc_GetImageMemoryRequirements2(
1476 const VkImageMemoryRequirementsInfo2
*pInfo
,
1477 VkMemoryRequirements2
*pMemoryRequirements
)
1479 libresoc_GetImageMemoryRequirements(device
, pInfo
->image
,
1480 &pMemoryRequirements
->memoryRequirements
);
1483 VkResult
libresoc_BindImageMemory2(VkDevice device
,
1484 uint32_t bindInfoCount
,
1485 const VkBindImageMemoryInfo
*pBindInfos
)
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
);
1492 // image->bo = mem->bo;
1493 // image->offset = pBindInfos[i].memoryOffset;
1495 // image->bo = NULL;
1496 // image->offset = 0;
1503 VkResult
libresoc_BindImageMemory(
1506 VkDeviceMemory memory
,
1507 VkDeviceSize memoryOffset
)
1509 const VkBindImageMemoryInfo info
= {
1510 .sType
= VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO
,
1513 .memoryOffset
= memoryOffset
1516 return libresoc_BindImageMemory2(device
, 1, &info
);
1519 static VkResult
libresoc_queue_submit(struct libresoc_queue
*queue
,
1520 const struct libresoc_queue_submission
*submission
)
1523 // struct libresoc_deferred_queue_submission *deferred = NULL;
1525 // VkResult result = libresoc_create_deferred_submission(queue, submission, &deferred);
1526 // if (result != VK_SUCCESS)
1529 // struct list_head processing_list;
1530 // list_inithead(&processing_list);
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));
1538 // return libresoc_process_submissions(&processing_list);
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
,
1545 return libresoc_queue_submit(queue
, &(struct libresoc_queue_submission
) {
1550 static bool libresoc_submit_has_effects(const VkSubmitInfo
*info
)
1552 return info
->commandBufferCount
||
1553 info
->waitSemaphoreCount
||
1554 info
->signalSemaphoreCount
;
1557 VkResult
libresoc_QueueSubmit(
1559 uint32_t submitCount
,
1560 const VkSubmitInfo
* pSubmits
,
1563 LIBRESOC_FROM_HANDLE(libresoc_queue
, queue
, _queue
);
1565 uint32_t fence_idx
= 0;
1566 bool flushed_caches
= false;
1568 if (fence
!= VK_NULL_HANDLE
) {
1569 for (uint32_t i
= 0; i
< submitCount
; ++i
)
1570 if (libresoc_submit_has_effects(pSubmits
+ i
))
1573 fence_idx
= UINT32_MAX
;
1575 for (uint32_t i
= 0; i
< submitCount
; i
++) {
1576 if (!libresoc_submit_has_effects(pSubmits
+ i
) && fence_idx
!= i
)
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
];
1584 const VkTimelineSemaphoreSubmitInfo
*timeline_info
=
1585 vk_find_struct_const(pSubmits
[i
].pNext
, TIMELINE_SEMAPHORE_SUBMIT_INFO
);
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,
1602 if (result
!= VK_SUCCESS
)
1605 flushed_caches
= true;
1608 if (fence
!= VK_NULL_HANDLE
&& !submitCount
) {
1609 result
= libresoc_signal_fence(queue
, fence
);
1610 if (result
!= VK_SUCCESS
)
1617 VkResult
libresoc_CreateFence(
1619 const VkFenceCreateInfo
* pCreateInfo
,
1620 const VkAllocationCallbacks
* pAllocator
,
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
;
1630 fence
= vk_zalloc2(&device
->vk
.alloc
, pAllocator
, sizeof(*fence
), 8,
1631 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
1633 return vk_error(device
->instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
1635 vk_object_base_init(&device
->vk
, &fence
->base
, VK_OBJECT_TYPE_FENCE
);
1637 // if (device->always_use_syncobj || handleTypes) {
1638 // fence->permanent.kind = LIBRESOC_FENCE_SYNCOBJ;
1640 // bool create_signaled = false;
1641 // if (pCreateInfo->flags & VK_FENCE_CREATE_SIGNALED_BIT)
1642 // create_signaled = true;
1644 // int ret = device->ws->create_syncobj(device->ws, create_signaled,
1645 // &fence->permanent.syncobj);
1647 // libresoc_destroy_fence(device, pAllocator, fence);
1648 // return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
1651 // fence->permanent.kind = LIBRESOC_FENCE_WINSYS;
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);
1659 // if (pCreateInfo->flags & VK_FENCE_CREATE_SIGNALED_BIT)
1660 // device->ws->signal_fence(fence->permanent.fence);
1663 *pFence
= libresoc_fence_to_handle(fence
);
1668 VkResult
libresoc_MapMemory(
1670 VkDeviceMemory _memory
,
1671 VkDeviceSize offset
,
1673 VkMemoryMapFlags flags
,
1676 LIBRESOC_FROM_HANDLE(libresoc_device
, device
, _device
);
1677 LIBRESOC_FROM_HANDLE(libresoc_device_memory
, mem
, _memory
);
1685 *ppData
= mem
->user_ptr
;
1687 // *ppData = device->ws->buffer_map(mem->bo);
1694 return vk_error(device
->instance
, VK_ERROR_MEMORY_MAP_FAILED
);
1697 void libresoc_UnmapMemory(
1699 VkDeviceMemory _memory
)
1701 LIBRESOC_FROM_HANDLE(libresoc_device
, device
, _device
);
1702 LIBRESOC_FROM_HANDLE(libresoc_device_memory
, mem
, _memory
);
1707 // if (mem->user_ptr == NULL)
1708 // device->ws->buffer_unmap(mem->bo);
1711 VkResult
libresoc_WaitForFences(
1713 uint32_t fenceCount
,
1714 const VkFence
* pFences
,
1722 VkResult
libresoc_ResetFences(VkDevice _device
,
1723 uint32_t fenceCount
,
1724 const VkFence
*pFences
)