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"
34 #include "compiler/glsl_types.h"
38 struct libresoc_deferred_queue_submission
{
39 struct libresoc_queue
*queue
;
40 VkCommandBuffer
*cmd_buffers
;
41 uint32_t cmd_buffer_count
;
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
;
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
;
57 uint64_t *wait_values
;
58 uint64_t *signal_values
;
60 struct libresoc_semaphore_part
*temporary_semaphore_parts
;
61 uint32_t temporary_semaphore_part_count
;
63 struct list_head queue_pending_list
;
64 uint32_t submission_wait_count
;
65 struct libresoc_timeline_waiter
*wait_nodes
;
67 struct list_head processing_list
;
70 struct libresoc_queue_submission
{
71 const VkCommandBuffer
*cmd_buffers
;
72 uint32_t cmd_buffer_count
;
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
;
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
;
88 const uint64_t *wait_values
;
89 uint32_t wait_value_count
;
90 const uint64_t *signal_values
;
91 uint32_t signal_value_count
;
95 libresoc_free_memory(struct libresoc_device
*device
,
96 const VkAllocationCallbacks
* pAllocator
,
97 struct libresoc_device_memory
*mem
)
102 vk_object_base_finish(&mem
->base
);
103 vk_free2(&device
->vk
.alloc
, pAllocator
, mem
);
106 static VkResult
libresoc_alloc_memory(struct libresoc_device
*device
,
107 const VkMemoryAllocateInfo
* pAllocateInfo
,
108 const VkAllocationCallbacks
* pAllocator
,
109 VkDeviceMemory
* pMem
)
111 struct libresoc_device_memory
*mem
;
115 assert(pAllocateInfo
->sType
== VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO
);
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
);
126 const struct wsi_memory_allocate_info
*wsi_info
=
127 vk_find_struct_const(pAllocateInfo
->pNext
, WSI_MEMORY_ALLOCATE_INFO_MESA
);
130 mem
= vk_zalloc2(&device
->vk
.alloc
, pAllocator
, sizeof(*mem
), 8,
131 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
133 return vk_error(device
->instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
135 vk_object_base_init(&device
->vk
, &mem
->base
,
136 VK_OBJECT_TYPE_DEVICE_MEMORY
);
139 mem
->image
= libresoc_image_from_handle(dedicate_info
->image
);
140 //mem->buffer = libresoc_buffer_from_handle(dedicate_info->buffer);
143 //mem->buffer = NULL;
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);
151 // priority_float = priority_ext->priority;
153 // unsigned priority = MIN2(LIBRESOC_BO_PRIORITY_APPLICATION_MAX - 1,
154 // (int)(priority_float * LIBRESOC_BO_PRIORITY_APPLICATION_MAX));
156 mem
->user_ptr
= NULL
;
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,
168 // result = VK_ERROR_INVALID_EXTERNAL_HANDLE;
171 // close(import_info->fd);
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);
179 // struct libresoc_image_create_info create_info = {
180 // .no_metadata_planes = true,
181 // .bo_metadata = &metadata
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);
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,
199 // result = VK_ERROR_INVALID_EXTERNAL_HANDLE;
202 // mem->user_ptr = host_ptr_info->pHostPointer;
205 uint64_t alloc_size
= align_u64(pAllocateInfo
->allocationSize
, 4096);
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];
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;
219 if (device
->overallocation_disallowed
) {
220 uint64_t total_size
=
221 device
->physical_device
->memory_properties
.memoryHeaps
[heap_index
].size
;
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
;
229 device
->allocated_memory_size
[heap_index
] += alloc_size
;
230 mtx_unlock(&device
->overallocation_mutex
);
233 // mem->bo = device->ws->buffer_create(device->ws, alloc_size, device->physical_device->rad_info.max_alignment,
234 // domain, flags, priority);
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);
242 // result = VK_ERROR_OUT_OF_DEVICE_MEMORY;
246 mem
->heap_index
= heap_index
;
247 mem
->alloc_size
= alloc_size
;
251 // result = libresoc_bo_list_add(device, mem->bo);
252 // if (result != VK_SUCCESS)
256 *pMem
= libresoc_device_memory_to_handle(mem
);
261 libresoc_free_memory(device
, pAllocator
,mem
);
266 VkResult
libresoc_AllocateMemory(
268 const VkMemoryAllocateInfo
* pAllocateInfo
,
269 const VkAllocationCallbacks
* pAllocator
,
270 VkDeviceMemory
* pMem
)
272 LIBRESOC_FROM_HANDLE(libresoc_device
, device
, _device
);
273 return libresoc_alloc_memory(device
, pAllocateInfo
, pAllocator
, pMem
);
276 void libresoc_FreeMemory(
279 const VkAllocationCallbacks
* pAllocator
)
281 LIBRESOC_FROM_HANDLE(libresoc_device
, device
, _device
);
282 LIBRESOC_FROM_HANDLE(libresoc_device_memory
, mem
, _mem
);
284 libresoc_free_memory(device
, pAllocator
, mem
);
287 libresoc_create_pthread_cond(pthread_cond_t
*cond
)
289 pthread_condattr_t condattr
;
290 if (pthread_condattr_init(&condattr
)) {
291 return VK_ERROR_INITIALIZATION_FAILED
;
294 if (pthread_condattr_setclock(&condattr
, CLOCK_MONOTONIC
)) {
295 pthread_condattr_destroy(&condattr
);
296 return VK_ERROR_INITIALIZATION_FAILED
;
298 if (pthread_cond_init(cond
, &condattr
)) {
299 pthread_condattr_destroy(&condattr
);
300 return VK_ERROR_INITIALIZATION_FAILED
;
302 pthread_condattr_destroy(&condattr
);
307 libresoc_EnumerateInstanceExtensionProperties(const char *pLayerName
,
308 uint32_t *pPropertyCount
,
309 VkExtensionProperties
*pProperties
)
311 if (getenv("LIBRESOC_TRACE")) {
312 fprintf(stderr
, "EnumerateInstanceExtensionProperties called for: %s \n", pLayerName
);
314 VK_OUTARRAY_MAKE(out
, pProperties
, pPropertyCount
);
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
];
324 return vk_outarray_status(&out
);
328 default_alloc_func(void *pUserData
, size_t size
, size_t align
,
329 VkSystemAllocationScope allocationScope
)
335 default_realloc_func(void *pUserData
, void *pOriginal
, size_t size
,
336 size_t align
, VkSystemAllocationScope allocationScope
)
338 return realloc(pOriginal
, size
);
342 default_free_func(void *pUserData
, void *pMemory
)
347 static const VkAllocationCallbacks default_alloc
= {
349 .pfnAllocation
= default_alloc_func
,
350 .pfnReallocation
= default_realloc_func
,
351 .pfnFree
= default_free_func
,
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
},
388 libresoc_get_debug_option_name(int id
)
390 assert(id
< ARRAY_SIZE(libresoc_debug_options
) - 1);
391 return libresoc_debug_options
[id
].string
;
394 static const char libresoc_dri_options_xml
[] =
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")
403 DRI_CONF_SECTION_DEBUG
404 DRI_CONF_VK_WSI_FORCE_BGRA8_UNORM_FIRST("false")
408 static void libresoc_init_dri_options(struct libresoc_instance
*instance
)
410 driParseOptionInfo(&instance
->available_dri_options
, libresoc_dri_options_xml
);
411 driParseConfigFiles(&instance
->dri_options
,
412 &instance
->available_dri_options
,
414 instance
->app_info
.app_name
,
415 instance
->app_info
.app_version
,
416 instance
->engineName
,
417 instance
->engineVersion
);
421 libresoc_CreateInstance(const VkInstanceCreateInfo
*pCreateInfo
,
422 const VkAllocationCallbacks
*pAllocator
,
423 VkInstance
*pInstance
)
425 if (getenv("LIBRESOC_TRACE")) {
426 fprintf(stderr
, "CreateInstance called. \n");
428 struct libresoc_instance
*instance
;
430 instance
= vk_zalloc2(&default_alloc
, pAllocator
, sizeof(*instance
), 8,
431 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE
);
433 return vk_error(NULL
, VK_ERROR_OUT_OF_HOST_MEMORY
);
435 vk_object_base_init(NULL
, &instance
->base
, VK_OBJECT_TYPE_INSTANCE
);
438 instance
->alloc
= *pAllocator
;
440 instance
->alloc
= default_alloc
;
441 if (pCreateInfo
->pApplicationInfo
) {
442 const VkApplicationInfo
*app
= pCreateInfo
->pApplicationInfo
;
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
;
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
++) {
455 for (idx
= 0; idx
< LIBRESOC_INSTANCE_EXTENSION_COUNT
; idx
++) {
456 if (!strcmp(pCreateInfo
->ppEnabledExtensionNames
[i
],
457 libresoc_instance_extensions
[idx
].extensionName
))
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
);
468 instance
->enabled_extensions
.extensions
[idx
] = true;
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.
474 if (!libresoc_instance_entrypoint_is_enabled(i
, instance
->apiVersion
,
475 &instance
->enabled_extensions
)) {
476 instance
->dispatch
.entrypoints
[i
] = NULL
;
478 instance
->dispatch
.entrypoints
[i
] =
479 libresoc_instance_dispatch_table
.entrypoints
[i
];
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.
486 if (!libresoc_physical_device_entrypoint_is_enabled(i
, instance
->apiVersion
,
487 &instance
->enabled_extensions
)) {
488 instance
->physical_device_dispatch
.entrypoints
[i
] = NULL
;
490 instance
->physical_device_dispatch
.entrypoints
[i
] =
491 libresoc_physical_device_dispatch_table
.entrypoints
[i
];
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.
499 if (!libresoc_device_entrypoint_is_enabled(i
, instance
->apiVersion
,
500 &instance
->enabled_extensions
, NULL
)) {
501 instance
->device_dispatch
.entrypoints
[i
] = NULL
;
503 instance
->device_dispatch
.entrypoints
[i
] =
504 libresoc_device_dispatch_table
.entrypoints
[i
];
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
);
517 libresoc_DestroyInstance(VkInstance _instance
,
518 const VkAllocationCallbacks
*pAllocator
)
520 if (getenv("LIBRESOC_TRACE")) {
521 fprintf(stderr
, "DestroyInstance called. \n");
527 libresoc_physical_device_init_mem_types(struct libresoc_physical_device
*device
)
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;
534 vram_index
= device
->memory_properties
.memoryHeapCount
++;
535 device
->memory_properties
.memoryHeaps
[vram_index
] = (VkMemoryHeap
) {
537 .flags
= VK_MEMORY_HEAP_DEVICE_LOCAL_BIT
,
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
,
548 unsigned type_count
= 0;
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
,
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
,
566 device
->memory_properties
.memoryTypeCount
= type_count
;
571 libresoc_physical_device_try_create(struct libresoc_instance
*instance
,
572 struct libresoc_physical_device
**device_out
)
578 struct libresoc_physical_device
*device
=
579 vk_zalloc2(&instance
->alloc
, NULL
, sizeof(*device
), 8,
580 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE
);
582 result
= vk_error(instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
586 device
->_loader_data
.loaderMagic
= ICD_LOADER_MAGIC
;
587 device
->instance
= instance
;
589 device
->master_fd
= master_fd
;
590 device
->local_fd
= fd
;
591 libresoc_physical_device_init_mem_types(device
);
593 libresoc_physical_device_get_supported_extensions(device
,
594 &device
->supported_extensions
);
595 result
= libresoc_init_wsi(device
);
596 if (result
!= VK_SUCCESS
) {
599 snprintf(device
->name
, sizeof(device
->name
),
601 *device_out
= device
;
602 //TODO: incase of failures need to deallocate and cleanup various allocation properly.
607 libresoc_enumerate_physical_devices(struct libresoc_instance
*instance
)
610 if (instance
->physical_devices_enumerated
)
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
618 struct libresoc_physical_device
*pdevice
;
620 result
= libresoc_physical_device_try_create(instance
, &pdevice
);
621 if (result
!= VK_SUCCESS
)
624 list_addtail(&pdevice
->link
, &instance
->physical_devices
);
630 libresoc_EnumeratePhysicalDevices(VkInstance _instance
,
631 uint32_t *pPhysicalDeviceCount
,
632 VkPhysicalDevice
*pPhysicalDevices
)
634 if (getenv("LIBRESOC_TRACE")) {
635 fprintf(stderr
, "EnumeratePhysicalDevices called\n");
637 LIBRESOC_FROM_HANDLE(libresoc_instance
, instance
, _instance
);
638 VK_OUTARRAY_MAKE(out
, pPhysicalDevices
, pPhysicalDeviceCount
);
640 VkResult result
= libresoc_enumerate_physical_devices(instance
);
641 if (result
!= VK_SUCCESS
)
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
);
651 return vk_outarray_status(&out
);
655 libresoc_GetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice
,
656 VkPhysicalDeviceFeatures
*pFeatures
)
658 if (getenv("LIBRESOC_TRACE")) {
659 fprintf(stderr
, "GetPhysicalDeviceFeatures called. \n");
661 //LIBRESOC_FROM_HANDLE(libresoc_physical_device, pdevice, physicalDevice);
662 memset(pFeatures
, 0, sizeof(*pFeatures
));
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,
674 .multiDrawIndirect
= true,
675 .drawIndirectFirstInstance
= true,
677 .depthBiasClamp
= true,
678 .fillModeNonSolid
= 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,
707 .sparseBinding
= true,
708 .variableMultisampleRate
= true,
709 .shaderResourceMinLod
= true,
710 .inheritedQueries
= true,
715 libresoc_max_descriptor_set_size()
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 */);
733 libresoc_GetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice
,
734 VkPhysicalDeviceProperties
*pProperties
)
736 if (getenv("LIBRESOC_TRACE")) {
737 fprintf(stderr
, "GetPhysicalDeviceProperties called. \n");
739 LIBRESOC_FROM_HANDLE(libresoc_physical_device
, pdevice
, physicalDevice
);
740 VkSampleCountFlags sample_counts
= 0xf;
742 size_t max_descriptor_set_size
= libresoc_max_descriptor_set_size();
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
= {
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,
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
,
864 .sparseProperties
= {0},
867 strcpy(pProperties
->deviceName
, pdevice
->name
);
868 memcpy(pProperties
->pipelineCacheUUID
, pdevice
->cache_uuid
, VK_UUID_SIZE
);
871 static void libresoc_get_physical_device_queue_family_properties(
872 struct libresoc_physical_device
* pdevice
,
874 VkQueueFamilyProperties
** pQueueFamilyProperties
)
876 int num_queue_families
= 1;
879 if (pQueueFamilyProperties
== NULL
) {
880 *pCount
= num_queue_families
;
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
,
895 .timestampValidBits
= 64,
896 .minImageTransferGranularity
= (VkExtent3D
) { 1, 1, 1 },
905 libresoc_GetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice
,
907 VkQueueFamilyProperties
*pQueueFamilyProperties
)
909 if (getenv("LIBRESOC_TRACE")) {
910 fprintf(stderr
, "GetPhysicalDeviceQueueFamilyProperites called. \n");
912 LIBRESOC_FROM_HANDLE(libresoc_physical_device
, pdevice
, physicalDevice
);
913 if (!pQueueFamilyProperties
) {
914 libresoc_get_physical_device_queue_family_properties(pdevice
, pCount
, NULL
);
917 VkQueueFamilyProperties
*properties
[] = {
918 pQueueFamilyProperties
+ 0,
919 pQueueFamilyProperties
+ 1,
920 pQueueFamilyProperties
+ 2,
922 libresoc_get_physical_device_queue_family_properties(pdevice
, pCount
, properties
);
923 assert(*pCount
<= 3);
927 libresoc_GetPhysicalDeviceMemoryProperties(VkPhysicalDevice physicalDevice
,
928 VkPhysicalDeviceMemoryProperties
*pMemoryProperties
)
930 if (getenv("LIBRESOC_TRACE")) {
931 fprintf(stderr
, "GetPhysicalDEviceMemoryProperties called. \n");
933 LIBRESOC_FROM_HANDLE(libresoc_physical_device
, physical_device
, physicalDevice
);
935 *pMemoryProperties
= physical_device
->memory_properties
;
940 //libresoc_GetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties *pFormatProperties) {
942 // if (getenv("LIBRESOC_TRACE")) {
943 // fprintf(stderr, "GetPhysicalDeviceFormatProperties called. \n");
949 // libresoc_GetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkImageFormatProperties* pImageFormatProperties)
951 // if (getenv("LIBRESOC_TRACE")) {
952 // fprintf(stderr, "GetPhysicalDEviceImageFormatProperties called. \n");
956 // return VK_SUCCESS;
959 // libresoc_GetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkSampleCountFlagBits samples, VkImageUsageFlags usage, VkImageTiling tiling, uint32_t* pPropertyCount, VkSparseImageFormatProperties* pProperties)
961 // if (getenv("LIBRESOC_TRACE")) {
962 // fprintf(stderr, "GetPhysicalDeviceSparseImageFormatProperties called. \n");
967 libresoc_GetInstanceProcAddr(VkInstance _instance
,
970 if (getenv("LIBRESOC_TRACE")) {
971 fprintf(stderr
, "GetInstanceProcAddr called for: %s \n", pName
);
973 LIBRESOC_FROM_HANDLE(libresoc_instance
, instance
, _instance
);
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.
982 #define LOOKUP_LIBRESOC_ENTRYPOINT(entrypoint) \
983 if (strcmp(pName, "vk" #entrypoint) == 0) \
984 return (PFN_vkVoidFunction)libresoc_##entrypoint
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
);
1002 #undef LOOKUP_LIBRESOC_ENTRYPOINT
1004 if (instance
== NULL
)
1007 int idx
= libresoc_get_instance_entrypoint_index(pName
);
1009 return instance
->dispatch
.entrypoints
[idx
];
1011 idx
= libresoc_get_physical_device_entrypoint_index(pName
);
1013 return instance
->physical_device_dispatch
.entrypoints
[idx
];
1015 idx
= libresoc_get_device_entrypoint_index(pName
);
1017 return instance
->device_dispatch
.entrypoints
[idx
];
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.
1026 VKAPI_ATTR PFN_vkVoidFunction
1027 VKAPI_CALL
vk_icdGetInstanceProcAddr(VkInstance instance
,
1031 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
1032 vk_icdGetInstanceProcAddr(VkInstance instance
,
1035 if (getenv("LIBRESOC_TRACE")) {
1036 fprintf(stderr
, "vk_icdGetInstanceProcAddr called for: %s \n", pName
);
1038 return libresoc_GetInstanceProcAddr(instance
, pName
);
1042 libresoc_GetDeviceProcAddr(VkDevice _device
,
1045 if (getenv("LIBRESOC_TRACE")) {
1046 fprintf(stderr
, "GetDeviceProcAddr called for: %s \n", pName
);
1048 LIBRESOC_FROM_HANDLE(libresoc_device
, device
, _device
);
1050 if (!device
|| !pName
)
1053 int idx
= libresoc_get_device_entrypoint_index(pName
);
1057 return device
->dispatch
.entrypoints
[idx
];
1060 /* With version 4+ of the loader interface the ICD should expose
1061 * vk_icdGetPhysicalDeviceProcAddr()
1064 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
1065 vk_icdGetPhysicalDeviceProcAddr(VkInstance _instance
,
1069 vk_icdGetPhysicalDeviceProcAddr(VkInstance _instance
,
1072 if (getenv("LIBRESOC_TRACE")) {
1073 fprintf(stderr
, "vk_icdGetPhysicalDeviceProcAddr called for: %s \n", pName
);
1075 LIBRESOC_FROM_HANDLE(libresoc_instance
, instance
, _instance
);
1077 if (!pName
|| !instance
)
1080 int idx
= libresoc_get_physical_device_entrypoint_index(pName
);
1084 return instance
->physical_device_dispatch
.entrypoints
[idx
];
1088 libresoc_EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice
,
1089 const char *pLayerName
,
1090 uint32_t *pPropertyCount
,
1091 VkExtensionProperties
*pProperties
)
1093 if (getenv("LIBRESOC_TRACE")) {
1094 fprintf(stderr
, "EnumerateDeviceExtensionProperties called for layer: %s \n", pLayerName
);
1096 LIBRESOC_FROM_HANDLE(libresoc_physical_device
, device
, physicalDevice
);
1097 VK_OUTARRAY_MAKE(out
, pProperties
, pPropertyCount
);
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
];
1107 return vk_outarray_status(&out
);
1111 libresoc_device_init_dispatch(struct libresoc_device
*device
)
1113 const struct libresoc_instance
*instance
= device
->physical_device
->instance
;
1114 const struct libresoc_device_dispatch_table
*dispatch_table_layer
= NULL
;
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.
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
];
1129 device
->dispatch
.entrypoints
[i
] =
1130 libresoc_device_dispatch_table
.entrypoints
[i
];
1136 check_physical_device_features(VkPhysicalDevice physicalDevice
,
1137 const VkPhysicalDeviceFeatures
*features
)
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
);
1152 static int libresoc_get_device_extension_index(const char *name
)
1154 for (unsigned i
= 0; i
< LIBRESOC_DEVICE_EXTENSION_COUNT
; ++i
) {
1155 if (strcmp(name
, libresoc_device_extensions
[i
].extensionName
) == 0)
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
)
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
);
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
);
1186 libresoc_queue_finish(struct libresoc_queue
*queue
)
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);
1194 // pthread_cond_destroy(&queue->thread_cond);
1195 // pthread_mutex_destroy(&queue->pending_mutex);
1196 // pthread_mutex_destroy(&queue->thread_mutex);
1198 // if (queue->hw_ctx)
1199 // queue->device->ws->ctx_destroy(queue->hw_ctx);
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);
1225 libresoc_CreateDevice(VkPhysicalDevice physicalDevice
,
1226 const VkDeviceCreateInfo
*pCreateInfo
,
1227 const VkAllocationCallbacks
*pAllocator
,
1230 if (getenv("LIBRESOC_TRACE")) {
1231 fprintf(stderr
, "CreateDevice called \n");
1233 LIBRESOC_FROM_HANDLE(libresoc_physical_device
, physical_device
, physicalDevice
);
1235 struct libresoc_device
*device
;
1237 /* Check enabled features */
1238 if (pCreateInfo
->pEnabledFeatures
) {
1239 result
= check_physical_device_features(physicalDevice
,
1240 pCreateInfo
->pEnabledFeatures
);
1241 if (result
!= VK_SUCCESS
)
1245 device
= vk_zalloc2(&physical_device
->instance
->alloc
, pAllocator
,
1247 VK_SYSTEM_ALLOCATION_SCOPE_DEVICE
);
1249 return vk_error(physical_device
->instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
1251 vk_device_init(&device
->vk
, pCreateInfo
,
1252 &physical_device
->instance
->alloc
, pAllocator
);
1254 device
->instance
= physical_device
->instance
;
1255 device
->physical_device
= physical_device
;
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
);
1265 device
->enabled_extensions
.extensions
[index
] = true;
1268 libresoc_device_init_dispatch(device
);
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
);
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
;
1284 memset(device
->queues
[qfi
], 0, queue_create
->queueCount
* sizeof(struct libresoc_queue
));
1286 device
->queue_count
[qfi
] = queue_create
->queueCount
;
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
,
1292 if (result
!= VK_SUCCESS
)
1297 if (result
!= VK_SUCCESS
)
1300 VkPipelineCacheCreateInfo ci
;
1301 ci
.sType
= VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO
;
1304 ci
.pInitialData
= NULL
;
1305 ci
.initialDataSize
= 0;
1307 result
= libresoc_CreatePipelineCache(libresoc_device_to_handle(device
),
1309 if (result
!= VK_SUCCESS
)
1312 *pDevice
= libresoc_device_to_handle(device
);
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
]);
1324 vk_free(&device
->vk
.alloc
, device
);
1329 libresoc_DestroyDevice(VkDevice _device
,
1330 const VkAllocationCallbacks
*pAllocator
)
1332 if (getenv("LIBRESOC_TRACE")) {
1333 fprintf(stderr
, "DestroyDevice called. \n");
1338 void libresoc_GetDeviceQueue(
1340 uint32_t queueFamilyIndex
,
1341 uint32_t queueIndex
,
1344 if (getenv("LIBRESOC_TRACE")) {
1345 fprintf(stderr
, "GetDeviceQueue called. \n");
1347 LIBRESOC_FROM_HANDLE(libresoc_device
, device
, _device
);
1348 struct libresoc_queue
*queue
;
1350 queue
= &device
->queues
[queueFamilyIndex
][queueIndex
];
1351 *pQueue
= libresoc_queue_to_handle(queue
);
1354 VkResult
libresoc_QueueWaitIdle(
1357 LIBRESOC_FROM_HANDLE(libresoc_queue
, queue
, _queue
);
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
);
1363 pthread_mutex_unlock(&queue
->pending_mutex
);
1368 VkResult
libresoc_DeviceWaitIdle(
1371 LIBRESOC_FROM_HANDLE(libresoc_device
, device
, _device
);
1373 for (unsigned i
= 0; i
< LIBRESOC_MAX_QUEUE_FAMILIES
; i
++) {
1374 for (unsigned q
= 0; q
< device
->queue_count
[i
]; q
++) {
1376 libresoc_QueueWaitIdle(libresoc_queue_to_handle(&device
->queues
[i
][q
]));
1378 if (result
!= VK_SUCCESS
)
1385 void libresoc_GetPhysicalDeviceProperties2(
1386 VkPhysicalDevice physicalDevice
,
1387 VkPhysicalDeviceProperties2
*pProperties
)
1389 LIBRESOC_FROM_HANDLE(libresoc_physical_device
, pdevice
, physicalDevice
);
1390 libresoc_GetPhysicalDeviceProperties(physicalDevice
, &pProperties
->properties
);
1391 //TODO: add more stuffs when required
1394 void libresoc_GetPhysicalDeviceFeatures2(
1395 VkPhysicalDevice physicalDevice
,
1396 VkPhysicalDeviceFeatures2
*pFeatures
)
1398 LIBRESOC_FROM_HANDLE(libresoc_physical_device
, pdevice
, physicalDevice
);
1399 libresoc_GetPhysicalDeviceFeatures(physicalDevice
, &pFeatures
->features
);
1402 void libresoc_GetPhysicalDeviceQueueFamilyProperties2(
1403 VkPhysicalDevice physicalDevice
,
1405 VkQueueFamilyProperties2
*pQueueFamilyProperties
)
1407 LIBRESOC_FROM_HANDLE(libresoc_physical_device
, pdevice
, physicalDevice
);
1408 if (!pQueueFamilyProperties
) {
1409 libresoc_get_physical_device_queue_family_properties(pdevice
, pCount
, NULL
);
1412 VkQueueFamilyProperties
*properties
[] = {
1413 &pQueueFamilyProperties
[0].queueFamilyProperties
,
1414 &pQueueFamilyProperties
[1].queueFamilyProperties
,
1415 &pQueueFamilyProperties
[2].queueFamilyProperties
,
1417 libresoc_get_physical_device_queue_family_properties(pdevice
, pCount
, properties
);
1418 assert(*pCount
<= 3);
1422 libresoc_get_memory_budget_properties(VkPhysicalDevice physicalDevice
,
1423 VkPhysicalDeviceMemoryBudgetPropertiesEXT
*memoryBudget
)
1428 void libresoc_GetPhysicalDeviceMemoryProperties2(
1429 VkPhysicalDevice physicalDevice
,
1430 VkPhysicalDeviceMemoryProperties2
*pMemoryProperties
)
1432 libresoc_GetPhysicalDeviceMemoryProperties(physicalDevice
,
1433 &pMemoryProperties
->memoryProperties
);
1435 VkPhysicalDeviceMemoryBudgetPropertiesEXT
*memory_budget
=
1436 vk_find_struct(pMemoryProperties
->pNext
,
1437 PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT
);
1439 libresoc_get_memory_budget_properties(physicalDevice
, memory_budget
);
1442 VkResult
libresoc_CreateSemaphore(
1444 const VkSemaphoreCreateInfo
* pCreateInfo
,
1445 const VkAllocationCallbacks
* pAllocator
,
1446 VkSemaphore
* pSemaphore
)
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
,
1452 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
1454 return vk_error(device
->instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
1456 vk_object_base_init(&device
->vk
, &sem
->base
,
1457 VK_OBJECT_TYPE_SEMAPHORE
);
1459 *pSemaphore
= libresoc_semaphore_to_handle(sem
);
1463 void libresoc_GetImageMemoryRequirements(
1466 VkMemoryRequirements
* pMemoryRequirements
)
1468 LIBRESOC_FROM_HANDLE(libresoc_device
, device
, _device
);
1469 LIBRESOC_FROM_HANDLE(libresoc_image
, image
, _image
);
1471 pMemoryRequirements
->memoryTypeBits
= (1u << device
->physical_device
->memory_properties
.memoryTypeCount
) - 1;
1473 pMemoryRequirements
->size
= image
->size
;
1474 pMemoryRequirements
->alignment
= image
->alignment
;
1477 void libresoc_GetImageMemoryRequirements2(
1479 const VkImageMemoryRequirementsInfo2
*pInfo
,
1480 VkMemoryRequirements2
*pMemoryRequirements
)
1482 libresoc_GetImageMemoryRequirements(device
, pInfo
->image
,
1483 &pMemoryRequirements
->memoryRequirements
);
1486 VkResult
libresoc_BindImageMemory2(VkDevice device
,
1487 uint32_t bindInfoCount
,
1488 const VkBindImageMemoryInfo
*pBindInfos
)
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
);
1495 // image->bo = mem->bo;
1496 // image->offset = pBindInfos[i].memoryOffset;
1498 // image->bo = NULL;
1499 // image->offset = 0;
1506 VkResult
libresoc_BindImageMemory(
1509 VkDeviceMemory memory
,
1510 VkDeviceSize memoryOffset
)
1512 const VkBindImageMemoryInfo info
= {
1513 .sType
= VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO
,
1516 .memoryOffset
= memoryOffset
1519 return libresoc_BindImageMemory2(device
, 1, &info
);
1522 static VkResult
libresoc_queue_submit(struct libresoc_queue
*queue
,
1523 const struct libresoc_queue_submission
*submission
)
1526 // struct libresoc_deferred_queue_submission *deferred = NULL;
1528 // VkResult result = libresoc_create_deferred_submission(queue, submission, &deferred);
1529 // if (result != VK_SUCCESS)
1532 // struct list_head processing_list;
1533 // list_inithead(&processing_list);
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));
1541 // return libresoc_process_submissions(&processing_list);
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
,
1548 return libresoc_queue_submit(queue
, &(struct libresoc_queue_submission
) {
1553 static bool libresoc_submit_has_effects(const VkSubmitInfo
*info
)
1555 return info
->commandBufferCount
||
1556 info
->waitSemaphoreCount
||
1557 info
->signalSemaphoreCount
;
1560 VkResult
libresoc_QueueSubmit(
1562 uint32_t submitCount
,
1563 const VkSubmitInfo
* pSubmits
,
1566 LIBRESOC_FROM_HANDLE(libresoc_queue
, queue
, _queue
);
1568 uint32_t fence_idx
= 0;
1569 bool flushed_caches
= false;
1571 if (fence
!= VK_NULL_HANDLE
) {
1572 for (uint32_t i
= 0; i
< submitCount
; ++i
)
1573 if (libresoc_submit_has_effects(pSubmits
+ i
))
1576 fence_idx
= UINT32_MAX
;
1578 for (uint32_t i
= 0; i
< submitCount
; i
++) {
1579 if (!libresoc_submit_has_effects(pSubmits
+ i
) && fence_idx
!= i
)
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
];
1587 const VkTimelineSemaphoreSubmitInfo
*timeline_info
=
1588 vk_find_struct_const(pSubmits
[i
].pNext
, TIMELINE_SEMAPHORE_SUBMIT_INFO
);
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,
1605 if (result
!= VK_SUCCESS
)
1608 flushed_caches
= true;
1611 if (fence
!= VK_NULL_HANDLE
&& !submitCount
) {
1612 result
= libresoc_signal_fence(queue
, fence
);
1613 if (result
!= VK_SUCCESS
)
1620 VkResult
libresoc_CreateFence(
1622 const VkFenceCreateInfo
* pCreateInfo
,
1623 const VkAllocationCallbacks
* pAllocator
,
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
;
1633 fence
= vk_zalloc2(&device
->vk
.alloc
, pAllocator
, sizeof(*fence
), 8,
1634 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
1636 return vk_error(device
->instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
1638 vk_object_base_init(&device
->vk
, &fence
->base
, VK_OBJECT_TYPE_FENCE
);
1640 // if (device->always_use_syncobj || handleTypes) {
1641 // fence->permanent.kind = LIBRESOC_FENCE_SYNCOBJ;
1643 // bool create_signaled = false;
1644 // if (pCreateInfo->flags & VK_FENCE_CREATE_SIGNALED_BIT)
1645 // create_signaled = true;
1647 // int ret = device->ws->create_syncobj(device->ws, create_signaled,
1648 // &fence->permanent.syncobj);
1650 // libresoc_destroy_fence(device, pAllocator, fence);
1651 // return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
1654 // fence->permanent.kind = LIBRESOC_FENCE_WINSYS;
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);
1662 // if (pCreateInfo->flags & VK_FENCE_CREATE_SIGNALED_BIT)
1663 // device->ws->signal_fence(fence->permanent.fence);
1666 *pFence
= libresoc_fence_to_handle(fence
);
1671 VkResult
libresoc_MapMemory(
1673 VkDeviceMemory _memory
,
1674 VkDeviceSize offset
,
1676 VkMemoryMapFlags flags
,
1679 LIBRESOC_FROM_HANDLE(libresoc_device
, device
, _device
);
1680 LIBRESOC_FROM_HANDLE(libresoc_device_memory
, mem
, _memory
);
1688 *ppData
= mem
->user_ptr
;
1690 // *ppData = device->ws->buffer_map(mem->bo);
1697 return vk_error(device
->instance
, VK_ERROR_MEMORY_MAP_FAILED
);
1700 void libresoc_UnmapMemory(
1702 VkDeviceMemory _memory
)
1704 LIBRESOC_FROM_HANDLE(libresoc_device
, device
, _device
);
1705 LIBRESOC_FROM_HANDLE(libresoc_device_memory
, mem
, _memory
);
1710 // if (mem->user_ptr == NULL)
1711 // device->ws->buffer_unmap(mem->bo);
1714 VkResult
libresoc_WaitForFences(
1716 uint32_t fenceCount
,
1717 const VkFence
* pFences
,
1725 VkResult
libresoc_ResetFences(VkDevice _device
,
1726 uint32_t fenceCount
,
1727 const VkFence
*pFences
)
1734 VkResult
libresoc_CreateFramebuffer(
1736 const VkFramebufferCreateInfo
* pCreateInfo
,
1737 const VkAllocationCallbacks
* pAllocator
,
1738 VkFramebuffer
* pFramebuffer
)
1743 void libresoc_DestroyBuffer(
1746 const VkAllocationCallbacks
* pAllocator
)
1749 void libresoc_DestroyFence(
1752 const VkAllocationCallbacks
* pAllocator
)
1756 void libresoc_DestroySemaphore(
1758 VkSemaphore _semaphore
,
1759 const VkAllocationCallbacks
* pAllocator
)