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
;
94 static uint32_t libresoc_surface_max_layer_count(struct libresoc_image_view
*iview
)
96 return iview
->type
== VK_IMAGE_VIEW_TYPE_3D
? iview
->extent
.depth
: (iview
->base_layer
+ iview
->layer_count
);
100 libresoc_free_memory(struct libresoc_device
*device
,
101 const VkAllocationCallbacks
* pAllocator
,
102 struct libresoc_device_memory
*mem
)
107 vk_object_base_finish(&mem
->base
);
108 vk_free2(&device
->vk
.alloc
, pAllocator
, mem
);
111 static VkResult
libresoc_alloc_memory(struct libresoc_device
*device
,
112 const VkMemoryAllocateInfo
* pAllocateInfo
,
113 const VkAllocationCallbacks
* pAllocator
,
114 VkDeviceMemory
* pMem
)
116 struct libresoc_device_memory
*mem
;
118 // uint32_t flags = 0;
120 assert(pAllocateInfo
->sType
== VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO
);
122 const VkImportMemoryFdInfoKHR
*import_info
=
123 vk_find_struct_const(pAllocateInfo
->pNext
, IMPORT_MEMORY_FD_INFO_KHR
);
124 // const VkMemoryDedicatedAllocateInfo *dedicate_info =
125 // vk_find_struct_const(pAllocateInfo->pNext, MEMORY_DEDICATED_ALLOCATE_INFO);
126 // const VkExportMemoryAllocateInfo *export_info =
127 // vk_find_struct_const(pAllocateInfo->pNext, EXPORT_MEMORY_ALLOCATE_INFO);
128 const VkImportMemoryHostPointerInfoEXT
*host_ptr_info
=
129 vk_find_struct_const(pAllocateInfo
->pNext
, IMPORT_MEMORY_HOST_POINTER_INFO_EXT
);
131 // const struct wsi_memory_allocate_info *wsi_info =
132 // vk_find_struct_const(pAllocateInfo->pNext, WSI_MEMORY_ALLOCATE_INFO_MESA);
135 mem
= vk_zalloc2(&device
->vk
.alloc
, pAllocator
, sizeof(*mem
), 8,
136 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
138 return vk_error(device
->instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
140 vk_object_base_init(&device
->vk
, &mem
->base
,
141 VK_OBJECT_TYPE_DEVICE_MEMORY
);
143 // if (dedicate_info) {
144 // mem->image = libresoc_image_from_handle(dedicate_info->image);
145 // mem->buffer = libresoc_buffer_from_handle(dedicate_info->buffer);
147 // mem->image = NULL;
148 // mem->buffer = NULL;
151 // float priority_float = 0.5;
152 // const struct VkMemoryPriorityAllocateInfoEXT *priority_ext =
153 // vk_find_struct_const(pAllocateInfo->pNext,
154 // MEMORY_PRIORITY_ALLOCATE_INFO_EXT);
156 // priority_float = priority_ext->priority;
158 // unsigned priority = MIN2(LIBRESOC_BO_PRIORITY_APPLICATION_MAX - 1,
159 // (int)(priority_float * LIBRESOC_BO_PRIORITY_APPLICATION_MAX));
161 mem
->user_ptr
= NULL
;
166 assert(import_info
->handleType
==
167 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT
||
168 import_info
->handleType
==
169 VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT
);
170 // mem->bo = device->ws->buffer_from_fd(device->ws, import_info->fd,
173 // result = VK_ERROR_INVALID_EXTERNAL_HANDLE;
176 // close(import_info->fd);
179 // if (mem->image && mem->image->plane_count == 1 &&
180 // !vk_format_is_depth_or_stencil(mem->image->vk_format)) {
181 // struct radeon_bo_metadata metadata;
182 // device->ws->buffer_get_metadata(mem->bo, &metadata);
184 // struct libresoc_image_create_info create_info = {
185 // .no_metadata_planes = true,
186 // .bo_metadata = &metadata
189 // /* This gives a basic ability to import radeonsi images
190 // * that don't have DCC. This is not guaranteed by any
191 // * spec and can be removed after we support modifiers. */
192 // result = libresoc_image_create_layout(device, create_info, mem->image);
193 // if (result != VK_SUCCESS) {
194 // device->ws->buffer_destroy(mem->bo);
198 } else if (host_ptr_info
) {
199 // assert(host_ptr_info->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT);
200 // mem->bo = device->ws->buffer_from_ptr(device->ws, host_ptr_info->pHostPointer,
201 // pAllocateInfo->allocationSize,
204 // result = VK_ERROR_INVALID_EXTERNAL_HANDLE;
207 // mem->user_ptr = host_ptr_info->pHostPointer;
210 uint64_t alloc_size
= align_u64(pAllocateInfo
->allocationSize
, 4096);
213 heap_index
= device
->physical_device
->memory_properties
.memoryTypes
[pAllocateInfo
->memoryTypeIndex
].heapIndex
;
214 // domain = device->physical_device->memory_domains[pAllocateInfo->memoryTypeIndex];
215 // flags |= device->physical_device->memory_flags[pAllocateInfo->memoryTypeIndex];
217 // if (!dedicate_info && !import_info && (!export_info || !export_info->handleTypes)) {
218 // flags |= RADEON_FLAG_NO_INTERPROCESS_SHARING;
219 // if (device->use_global_bo_list) {
220 // flags |= RADEON_FLAG_PREFER_LOCAL_BO;
224 if (device
->overallocation_disallowed
) {
225 uint64_t total_size
=
226 device
->physical_device
->memory_properties
.memoryHeaps
[heap_index
].size
;
228 mtx_lock(&device
->overallocation_mutex
);
229 if (device
->allocated_memory_size
[heap_index
] + alloc_size
> total_size
) {
230 mtx_unlock(&device
->overallocation_mutex
);
231 result
= VK_ERROR_OUT_OF_DEVICE_MEMORY
;
234 device
->allocated_memory_size
[heap_index
] += alloc_size
;
235 mtx_unlock(&device
->overallocation_mutex
);
238 mem
->bytes
= vk_zalloc2(&device
->vk
.alloc
, pAllocator
, alloc_size
, 8,
239 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
240 // mem->bo = device->ws->buffer_create(device->ws, alloc_size, device->physical_device->rad_info.max_alignment,
241 // domain, flags, priority);
244 // if (device->overallocation_disallowed) {
245 // mtx_lock(&device->overallocation_mutex);
246 // device->allocated_memory_size[heap_index] -= alloc_size;
247 // mtx_unlock(&device->overallocation_mutex);
249 // result = VK_ERROR_OUT_OF_DEVICE_MEMORY;
253 mem
->heap_index
= heap_index
;
254 mem
->alloc_size
= alloc_size
;
258 // result = libresoc_bo_list_add(device, mem->bo);
259 // if (result != VK_SUCCESS)
263 *pMem
= libresoc_device_memory_to_handle(mem
);
268 libresoc_free_memory(device
, pAllocator
,mem
);
273 VkResult
libresoc_AllocateMemory(
275 const VkMemoryAllocateInfo
* pAllocateInfo
,
276 const VkAllocationCallbacks
* pAllocator
,
277 VkDeviceMemory
* pMem
)
279 LIBRESOC_FROM_HANDLE(libresoc_device
, device
, _device
);
280 return libresoc_alloc_memory(device
, pAllocateInfo
, pAllocator
, pMem
);
283 void libresoc_FreeMemory(
286 const VkAllocationCallbacks
* pAllocator
)
288 LIBRESOC_FROM_HANDLE(libresoc_device
, device
, _device
);
289 LIBRESOC_FROM_HANDLE(libresoc_device_memory
, mem
, _mem
);
291 libresoc_free_memory(device
, pAllocator
, mem
);
294 libresoc_create_pthread_cond(pthread_cond_t
*cond
)
296 pthread_condattr_t condattr
;
297 if (pthread_condattr_init(&condattr
)) {
298 return VK_ERROR_INITIALIZATION_FAILED
;
301 if (pthread_condattr_setclock(&condattr
, CLOCK_MONOTONIC
)) {
302 pthread_condattr_destroy(&condattr
);
303 return VK_ERROR_INITIALIZATION_FAILED
;
305 if (pthread_cond_init(cond
, &condattr
)) {
306 pthread_condattr_destroy(&condattr
);
307 return VK_ERROR_INITIALIZATION_FAILED
;
309 pthread_condattr_destroy(&condattr
);
314 libresoc_EnumerateInstanceExtensionProperties(const char *pLayerName
,
315 uint32_t *pPropertyCount
,
316 VkExtensionProperties
*pProperties
)
318 if (getenv("LIBRESOC_TRACE")) {
319 fprintf(stderr
, "EnumerateInstanceExtensionProperties called for: %s \n", pLayerName
);
321 VK_OUTARRAY_MAKE(out
, pProperties
, pPropertyCount
);
323 for (int i
= 0; i
< LIBRESOC_INSTANCE_EXTENSION_COUNT
; i
++) {
324 if (libresoc_instance_extensions_supported
.extensions
[i
]) {
325 vk_outarray_append(&out
, prop
) {
326 *prop
= libresoc_instance_extensions
[i
];
331 return vk_outarray_status(&out
);
335 default_alloc_func(void *pUserData
, size_t size
, size_t align
,
336 VkSystemAllocationScope allocationScope
)
342 default_realloc_func(void *pUserData
, void *pOriginal
, size_t size
,
343 size_t align
, VkSystemAllocationScope allocationScope
)
345 return realloc(pOriginal
, size
);
349 default_free_func(void *pUserData
, void *pMemory
)
354 static const VkAllocationCallbacks default_alloc
= {
356 .pfnAllocation
= default_alloc_func
,
357 .pfnReallocation
= default_realloc_func
,
358 .pfnFree
= default_free_func
,
361 static const struct debug_control libresoc_debug_options
[] = {
362 {"nofastclears", LIBRESOC_DEBUG_NO_FAST_CLEARS
},
363 {"nodcc", LIBRESOC_DEBUG_NO_DCC
},
364 {"shaders", LIBRESOC_DEBUG_DUMP_SHADERS
},
365 {"nocache", LIBRESOC_DEBUG_NO_CACHE
},
366 {"shaderstats", LIBRESOC_DEBUG_DUMP_SHADER_STATS
},
367 {"nohiz", LIBRESOC_DEBUG_NO_HIZ
},
368 {"nocompute", LIBRESOC_DEBUG_NO_COMPUTE_QUEUE
},
369 {"allbos", LIBRESOC_DEBUG_ALL_BOS
},
370 {"noibs", LIBRESOC_DEBUG_NO_IBS
},
371 {"spirv", LIBRESOC_DEBUG_DUMP_SPIRV
},
372 {"vmfaults", LIBRESOC_DEBUG_VM_FAULTS
},
373 {"zerovram", LIBRESOC_DEBUG_ZERO_VRAM
},
374 {"syncshaders", LIBRESOC_DEBUG_SYNC_SHADERS
},
375 {"preoptir", LIBRESOC_DEBUG_PREOPTIR
},
376 {"nodynamicbounds", LIBRESOC_DEBUG_NO_DYNAMIC_BOUNDS
},
377 {"nooutoforder", LIBRESOC_DEBUG_NO_OUT_OF_ORDER
},
378 {"info", LIBRESOC_DEBUG_INFO
},
379 {"errors", LIBRESOC_DEBUG_ERRORS
},
380 {"startup", LIBRESOC_DEBUG_STARTUP
},
381 {"checkir", LIBRESOC_DEBUG_CHECKIR
},
382 {"nothreadllvm", LIBRESOC_DEBUG_NOTHREADLLVM
},
383 {"nobinning", LIBRESOC_DEBUG_NOBINNING
},
384 {"nongg", LIBRESOC_DEBUG_NO_NGG
},
385 {"allentrypoints", LIBRESOC_DEBUG_ALL_ENTRYPOINTS
},
386 {"metashaders", LIBRESOC_DEBUG_DUMP_META_SHADERS
},
387 {"nomemorycache", LIBRESOC_DEBUG_NO_MEMORY_CACHE
},
388 {"llvm", LIBRESOC_DEBUG_LLVM
},
389 {"forcecompress", LIBRESOC_DEBUG_FORCE_COMPRESS
},
390 {"nir", LIBRESOC_DEBUG_DUMP_NIR
},
395 libresoc_get_debug_option_name(int id
)
397 assert(id
< ARRAY_SIZE(libresoc_debug_options
) - 1);
398 return libresoc_debug_options
[id
].string
;
401 static const char libresoc_dri_options_xml
[] =
403 DRI_CONF_SECTION_PERFORMANCE
404 DRI_CONF_ADAPTIVE_SYNC("true")
405 DRI_CONF_VK_X11_OVERRIDE_MIN_IMAGE_COUNT(0)
406 DRI_CONF_VK_X11_STRICT_IMAGE_COUNT("false")
407 DRI_CONF_VK_X11_ENSURE_MIN_IMAGE_COUNT("false")
410 DRI_CONF_SECTION_DEBUG
411 DRI_CONF_VK_WSI_FORCE_BGRA8_UNORM_FIRST("false")
415 static void libresoc_init_dri_options(struct libresoc_instance
*instance
)
417 driParseOptionInfo(&instance
->available_dri_options
, libresoc_dri_options_xml
);
418 driParseConfigFiles(&instance
->dri_options
,
419 &instance
->available_dri_options
,
421 instance
->app_info
.app_name
,
422 instance
->app_info
.app_version
,
423 instance
->engineName
,
424 instance
->engineVersion
);
428 libresoc_CreateInstance(const VkInstanceCreateInfo
*pCreateInfo
,
429 const VkAllocationCallbacks
*pAllocator
,
430 VkInstance
*pInstance
)
432 if (getenv("LIBRESOC_TRACE")) {
433 fprintf(stderr
, "CreateInstance called. \n");
435 struct libresoc_instance
*instance
;
437 instance
= vk_zalloc2(&default_alloc
, pAllocator
, sizeof(*instance
), 8,
438 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE
);
440 return vk_error(NULL
, VK_ERROR_OUT_OF_HOST_MEMORY
);
442 vk_object_base_init(NULL
, &instance
->base
, VK_OBJECT_TYPE_INSTANCE
);
445 instance
->alloc
= *pAllocator
;
447 instance
->alloc
= default_alloc
;
448 if (pCreateInfo
->pApplicationInfo
) {
449 const VkApplicationInfo
*app
= pCreateInfo
->pApplicationInfo
;
451 instance
->engineName
=
452 vk_strdup(&instance
->alloc
, app
->pEngineName
,
453 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE
);
454 instance
->engineVersion
= app
->engineVersion
;
455 instance
->apiVersion
= app
->apiVersion
;
457 instance
->debug_flags
= parse_debug_string(getenv("LIBRESOC_DEBUG"),
458 libresoc_debug_options
);
459 /*TODO : enable extensions*/
460 for (uint32_t i
= 0; i
< pCreateInfo
->enabledExtensionCount
; i
++) {
462 for (idx
= 0; idx
< LIBRESOC_INSTANCE_EXTENSION_COUNT
; idx
++) {
463 if (!strcmp(pCreateInfo
->ppEnabledExtensionNames
[i
],
464 libresoc_instance_extensions
[idx
].extensionName
))
468 if (idx
>= LIBRESOC_INSTANCE_EXTENSION_COUNT
||
469 !libresoc_instance_extensions_supported
.extensions
[idx
]) {
470 vk_object_base_finish(&instance
->base
);
471 vk_free2(&default_alloc
, pAllocator
, instance
);
472 return vk_error(instance
, VK_ERROR_EXTENSION_NOT_PRESENT
);
475 instance
->enabled_extensions
.extensions
[idx
] = true;
477 for (unsigned i
= 0; i
< ARRAY_SIZE(instance
->dispatch
.entrypoints
); i
++) {
478 /* Vulkan requires that entrypoints for extensions which have
479 * not been enabled must not be advertised.
481 if (!libresoc_instance_entrypoint_is_enabled(i
, instance
->apiVersion
,
482 &instance
->enabled_extensions
)) {
483 instance
->dispatch
.entrypoints
[i
] = NULL
;
485 instance
->dispatch
.entrypoints
[i
] =
486 libresoc_instance_dispatch_table
.entrypoints
[i
];
489 for (unsigned i
= 0; i
< ARRAY_SIZE(instance
->physical_device_dispatch
.entrypoints
); i
++) {
490 /* Vulkan requires that entrypoints for extensions which have
491 * not been enabled must not be advertised.
493 if (!libresoc_physical_device_entrypoint_is_enabled(i
, instance
->apiVersion
,
494 &instance
->enabled_extensions
)) {
495 instance
->physical_device_dispatch
.entrypoints
[i
] = NULL
;
497 instance
->physical_device_dispatch
.entrypoints
[i
] =
498 libresoc_physical_device_dispatch_table
.entrypoints
[i
];
502 for (unsigned i
= 0; i
< ARRAY_SIZE(instance
->device_dispatch
.entrypoints
); i
++) {
503 /* Vulkan requires that entrypoints for extensions which have
504 * not been enabled must not be advertised.
506 if (!libresoc_device_entrypoint_is_enabled(i
, instance
->apiVersion
,
507 &instance
->enabled_extensions
, NULL
)) {
508 instance
->device_dispatch
.entrypoints
[i
] = NULL
;
510 instance
->device_dispatch
.entrypoints
[i
] =
511 libresoc_device_dispatch_table
.entrypoints
[i
];
514 instance
->physical_devices_enumerated
= false;
515 list_inithead(&instance
->physical_devices
);
516 glsl_type_singleton_init_or_ref();
517 libresoc_init_dri_options(instance
);
518 InitLLVM(&instance
->llvm_ref
);
519 *pInstance
= libresoc_instance_to_handle(instance
);
525 libresoc_DestroyInstance(VkInstance _instance
,
526 const VkAllocationCallbacks
*pAllocator
)
528 if (getenv("LIBRESOC_TRACE")) {
529 fprintf(stderr
, "DestroyInstance called. \n");
535 libresoc_physical_device_init_mem_types(struct libresoc_physical_device
*device
)
537 uint64_t visible_vram_size
= 65536; //TODO: some dummy value
538 uint64_t vram_size
= 65536; //TODO: some dummy value
539 int vram_index
= -1, visible_vram_index
= -1;
540 device
->memory_properties
.memoryHeapCount
= 0;
542 vram_index
= device
->memory_properties
.memoryHeapCount
++;
543 device
->memory_properties
.memoryHeaps
[vram_index
] = (VkMemoryHeap
) {
545 .flags
= VK_MEMORY_HEAP_DEVICE_LOCAL_BIT
,
549 if (visible_vram_size
) {
550 visible_vram_index
= device
->memory_properties
.memoryHeapCount
++;
551 device
->memory_properties
.memoryHeaps
[visible_vram_index
] = (VkMemoryHeap
) {
552 .size
= visible_vram_size
,
553 .flags
= VK_MEMORY_HEAP_DEVICE_LOCAL_BIT
,
556 unsigned type_count
= 0;
558 if (vram_index
>= 0 || visible_vram_index
>= 0) {
559 device
->memory_properties
.memoryTypes
[type_count
++] = (VkMemoryType
) {
560 .propertyFlags
= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
,
561 .heapIndex
= vram_index
>= 0 ? vram_index
: visible_vram_index
,
565 if (visible_vram_index
>= 0) {
566 device
->memory_properties
.memoryTypes
[type_count
++] = (VkMemoryType
) {
567 .propertyFlags
= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
|
568 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
|
569 VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
,
570 .heapIndex
= visible_vram_index
,
574 device
->memory_properties
.memoryTypeCount
= type_count
;
579 libresoc_physical_device_try_create(struct libresoc_instance
*instance
,
580 struct libresoc_physical_device
**device_out
)
586 struct libresoc_physical_device
*device
=
587 vk_zalloc2(&instance
->alloc
, NULL
, sizeof(*device
), 8,
588 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE
);
590 result
= vk_error(instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
594 device
->_loader_data
.loaderMagic
= ICD_LOADER_MAGIC
;
595 device
->instance
= instance
;
597 device
->master_fd
= master_fd
;
598 device
->local_fd
= fd
;
599 libresoc_physical_device_init_mem_types(device
);
601 libresoc_physical_device_get_supported_extensions(device
,
602 &device
->supported_extensions
);
603 result
= libresoc_init_wsi(device
);
604 if (result
!= VK_SUCCESS
) {
607 snprintf(device
->name
, sizeof(device
->name
),
609 *device_out
= device
;
610 //TODO: incase of failures need to deallocate and cleanup various allocation properly.
615 libresoc_enumerate_physical_devices(struct libresoc_instance
*instance
)
618 if (instance
->physical_devices_enumerated
)
621 instance
->physical_devices_enumerated
= true;
622 VkResult result
= VK_SUCCESS
;
623 /* the driver creates a null
624 * device that allows to test the compiler without having a physical device
626 struct libresoc_physical_device
*pdevice
;
628 result
= libresoc_physical_device_try_create(instance
, &pdevice
);
629 if (result
!= VK_SUCCESS
)
632 list_addtail(&pdevice
->link
, &instance
->physical_devices
);
638 libresoc_EnumeratePhysicalDevices(VkInstance _instance
,
639 uint32_t *pPhysicalDeviceCount
,
640 VkPhysicalDevice
*pPhysicalDevices
)
642 if (getenv("LIBRESOC_TRACE")) {
643 fprintf(stderr
, "EnumeratePhysicalDevices called\n");
645 LIBRESOC_FROM_HANDLE(libresoc_instance
, instance
, _instance
);
646 VK_OUTARRAY_MAKE(out
, pPhysicalDevices
, pPhysicalDeviceCount
);
648 VkResult result
= libresoc_enumerate_physical_devices(instance
);
649 if (result
!= VK_SUCCESS
)
652 list_for_each_entry(struct libresoc_physical_device
, pdevice
,
653 &instance
->physical_devices
, link
) {
654 vk_outarray_append(&out
, i
) {
655 *i
= libresoc_physical_device_to_handle(pdevice
);
659 return vk_outarray_status(&out
);
663 libresoc_GetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice
,
664 VkPhysicalDeviceFeatures
*pFeatures
)
666 if (getenv("LIBRESOC_TRACE")) {
667 fprintf(stderr
, "GetPhysicalDeviceFeatures called. \n");
669 //LIBRESOC_FROM_HANDLE(libresoc_physical_device, pdevice, physicalDevice);
670 memset(pFeatures
, 0, sizeof(*pFeatures
));
672 *pFeatures
= (VkPhysicalDeviceFeatures
) {
673 .robustBufferAccess
= true,
674 .fullDrawIndexUint32
= true,
675 .imageCubeArray
= true,
676 .independentBlend
= true,
677 .geometryShader
= true,
678 .tessellationShader
= true,
679 .sampleRateShading
= true,
680 .dualSrcBlend
= true,
682 .multiDrawIndirect
= true,
683 .drawIndirectFirstInstance
= true,
685 .depthBiasClamp
= true,
686 .fillModeNonSolid
= true,
691 .multiViewport
= true,
692 .samplerAnisotropy
= true,
693 .textureCompressionETC2
= false,
694 .textureCompressionASTC_LDR
= false,
695 .textureCompressionBC
= true,
696 .occlusionQueryPrecise
= true,
697 .pipelineStatisticsQuery
= true,
698 .vertexPipelineStoresAndAtomics
= true,
699 .fragmentStoresAndAtomics
= true,
700 .shaderTessellationAndGeometryPointSize
= true,
701 .shaderImageGatherExtended
= true,
702 .shaderStorageImageExtendedFormats
= true,
703 .shaderStorageImageMultisample
= true,
704 .shaderUniformBufferArrayDynamicIndexing
= true,
705 .shaderSampledImageArrayDynamicIndexing
= true,
706 .shaderStorageBufferArrayDynamicIndexing
= true,
707 .shaderStorageImageArrayDynamicIndexing
= true,
708 .shaderStorageImageReadWithoutFormat
= true,
709 .shaderStorageImageWriteWithoutFormat
= true,
710 .shaderClipDistance
= true,
711 .shaderCullDistance
= true,
712 .shaderFloat64
= true,
715 .sparseBinding
= true,
716 .variableMultisampleRate
= true,
717 .shaderResourceMinLod
= true,
718 .inheritedQueries
= true,
723 libresoc_max_descriptor_set_size()
725 /* make sure that the entire descriptor set is addressable with a signed
726 * 32-bit int. So the sum of all limits scaled by descriptor size has to
727 * be at most 2 GiB. the combined image & samples object count as one of
728 * both. This limit is for the pipeline layout, not for the set layout, but
729 * there is no set limit, so we just set a pipeline limit. I don't think
730 * any app is going to hit this soon. */
731 return ((1ull << 31) - 16 * MAX_DYNAMIC_BUFFERS
732 - MAX_INLINE_UNIFORM_BLOCK_SIZE
* MAX_INLINE_UNIFORM_BLOCK_COUNT
) /
733 (32 /* uniform buffer, 32 due to potential space wasted on alignment */ +
734 32 /* storage buffer, 32 due to potential space wasted on alignment */ +
735 32 /* sampler, largest when combined with image */ +
736 64 /* sampled image */ +
737 64 /* storage image */);
741 libresoc_GetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice
,
742 VkPhysicalDeviceProperties
*pProperties
)
744 if (getenv("LIBRESOC_TRACE")) {
745 fprintf(stderr
, "GetPhysicalDeviceProperties called. \n");
747 LIBRESOC_FROM_HANDLE(libresoc_physical_device
, pdevice
, physicalDevice
);
748 VkSampleCountFlags sample_counts
= 0xf;
750 size_t max_descriptor_set_size
= libresoc_max_descriptor_set_size();
752 VkPhysicalDeviceLimits limits
= {
753 .maxImageDimension1D
= (1 << 14),
754 .maxImageDimension2D
= (1 << 14),
755 .maxImageDimension3D
= (1 << 11),
756 .maxImageDimensionCube
= (1 << 14),
757 .maxImageArrayLayers
= (1 << 11),
758 .maxTexelBufferElements
= UINT32_MAX
,
759 .maxUniformBufferRange
= UINT32_MAX
,
760 .maxStorageBufferRange
= UINT32_MAX
,
761 .maxPushConstantsSize
= MAX_PUSH_CONSTANTS_SIZE
,
762 .maxMemoryAllocationCount
= UINT32_MAX
,
763 .maxSamplerAllocationCount
= 64 * 1024,
764 .bufferImageGranularity
= 64, /* A cache line */
765 .sparseAddressSpaceSize
= LIBRESOC_MAX_MEMORY_ALLOCATION_SIZE
, /* buffer max size */
766 .maxBoundDescriptorSets
= MAX_SETS
,
767 .maxPerStageDescriptorSamplers
= max_descriptor_set_size
,
768 .maxPerStageDescriptorUniformBuffers
= max_descriptor_set_size
,
769 .maxPerStageDescriptorStorageBuffers
= max_descriptor_set_size
,
770 .maxPerStageDescriptorSampledImages
= max_descriptor_set_size
,
771 .maxPerStageDescriptorStorageImages
= max_descriptor_set_size
,
772 .maxPerStageDescriptorInputAttachments
= max_descriptor_set_size
,
773 .maxPerStageResources
= max_descriptor_set_size
,
774 .maxDescriptorSetSamplers
= max_descriptor_set_size
,
775 .maxDescriptorSetUniformBuffers
= max_descriptor_set_size
,
776 .maxDescriptorSetUniformBuffersDynamic
= MAX_DYNAMIC_UNIFORM_BUFFERS
,
777 .maxDescriptorSetStorageBuffers
= max_descriptor_set_size
,
778 .maxDescriptorSetStorageBuffersDynamic
= MAX_DYNAMIC_STORAGE_BUFFERS
,
779 .maxDescriptorSetSampledImages
= max_descriptor_set_size
,
780 .maxDescriptorSetStorageImages
= max_descriptor_set_size
,
781 .maxDescriptorSetInputAttachments
= max_descriptor_set_size
,
782 .maxVertexInputAttributes
= MAX_VERTEX_ATTRIBS
,
783 .maxVertexInputBindings
= MAX_VBS
,
784 .maxVertexInputAttributeOffset
= 2047,
785 .maxVertexInputBindingStride
= 2048,
786 .maxVertexOutputComponents
= 128,
787 .maxTessellationGenerationLevel
= 64,
788 .maxTessellationPatchSize
= 32,
789 .maxTessellationControlPerVertexInputComponents
= 128,
790 .maxTessellationControlPerVertexOutputComponents
= 128,
791 .maxTessellationControlPerPatchOutputComponents
= 120,
792 .maxTessellationControlTotalOutputComponents
= 4096,
793 .maxTessellationEvaluationInputComponents
= 128,
794 .maxTessellationEvaluationOutputComponents
= 128,
795 .maxGeometryShaderInvocations
= 127,
796 .maxGeometryInputComponents
= 64,
797 .maxGeometryOutputComponents
= 128,
798 .maxGeometryOutputVertices
= 256,
799 .maxGeometryTotalOutputComponents
= 1024,
800 .maxFragmentInputComponents
= 128,
801 .maxFragmentOutputAttachments
= 8,
802 .maxFragmentDualSrcAttachments
= 1,
803 .maxFragmentCombinedOutputResources
= 8,
804 .maxComputeSharedMemorySize
= 32768,
805 .maxComputeWorkGroupCount
= { 65535, 65535, 65535 },
806 .maxComputeWorkGroupInvocations
= 1024,
807 .maxComputeWorkGroupSize
= {
812 .subPixelPrecisionBits
= 8,
813 .subTexelPrecisionBits
= 8,
814 .mipmapPrecisionBits
= 8,
815 .maxDrawIndexedIndexValue
= UINT32_MAX
,
816 .maxDrawIndirectCount
= UINT32_MAX
,
817 .maxSamplerLodBias
= 16,
818 .maxSamplerAnisotropy
= 16,
819 .maxViewports
= MAX_VIEWPORTS
,
820 .maxViewportDimensions
= { (1 << 14), (1 << 14) },
821 .viewportBoundsRange
= { INT16_MIN
, INT16_MAX
},
822 .viewportSubPixelBits
= 8,
823 .minMemoryMapAlignment
= 4096, /* A page */
824 .minTexelBufferOffsetAlignment
= 4,
825 .minUniformBufferOffsetAlignment
= 4,
826 .minStorageBufferOffsetAlignment
= 4,
827 .minTexelOffset
= -32,
828 .maxTexelOffset
= 31,
829 .minTexelGatherOffset
= -32,
830 .maxTexelGatherOffset
= 31,
831 .minInterpolationOffset
= -2,
832 .maxInterpolationOffset
= 2,
833 .subPixelInterpolationOffsetBits
= 8,
834 .maxFramebufferWidth
= (1 << 14),
835 .maxFramebufferHeight
= (1 << 14),
836 .maxFramebufferLayers
= (1 << 10),
837 .framebufferColorSampleCounts
= sample_counts
,
838 .framebufferDepthSampleCounts
= sample_counts
,
839 .framebufferStencilSampleCounts
= sample_counts
,
840 .framebufferNoAttachmentsSampleCounts
= sample_counts
,
841 .maxColorAttachments
= MAX_RTS
,
842 .sampledImageColorSampleCounts
= sample_counts
,
843 .sampledImageIntegerSampleCounts
= sample_counts
,
844 .sampledImageDepthSampleCounts
= sample_counts
,
845 .sampledImageStencilSampleCounts
= sample_counts
,
846 .storageImageSampleCounts
= sample_counts
,
847 .maxSampleMaskWords
= 1,
848 .timestampComputeAndGraphics
= true,
849 .timestampPeriod
= 1000000.0 /* FIXME /pdevice->rad_info.clock_crystal_freq*/,
850 .maxClipDistances
= 8,
851 .maxCullDistances
= 8,
852 .maxCombinedClipAndCullDistances
= 8,
853 .discreteQueuePriorities
= 2,
854 .pointSizeRange
= { 0.0, 8191.875 },
855 .lineWidthRange
= { 0.0, 8191.875 },
856 .pointSizeGranularity
= (1.0 / 8.0),
857 .lineWidthGranularity
= (1.0 / 8.0),
858 .strictLines
= false, /* FINISHME */
859 .standardSampleLocations
= true,
860 .optimalBufferCopyOffsetAlignment
= 128,
861 .optimalBufferCopyRowPitchAlignment
= 128,
862 .nonCoherentAtomSize
= 64,
865 *pProperties
= (VkPhysicalDeviceProperties
) {
866 .apiVersion
= libresoc_physical_device_api_version(pdevice
),
867 .driverVersion
= vk_get_driver_version(),
868 .vendorID
= 1, //TODO: some dummy value
869 .deviceID
= 1, //TODO: dome dummy value
870 .deviceType
= VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU
,
872 .sparseProperties
= {0},
875 strcpy(pProperties
->deviceName
, pdevice
->name
);
876 memcpy(pProperties
->pipelineCacheUUID
, pdevice
->cache_uuid
, VK_UUID_SIZE
);
879 static void libresoc_get_physical_device_queue_family_properties(
880 struct libresoc_physical_device
* pdevice
,
882 VkQueueFamilyProperties
** pQueueFamilyProperties
)
884 int num_queue_families
= 1;
887 if (pQueueFamilyProperties
== NULL
) {
888 *pCount
= num_queue_families
;
897 *pQueueFamilyProperties
[idx
] = (VkQueueFamilyProperties
) {
898 .queueFlags
= VK_QUEUE_GRAPHICS_BIT
|
899 VK_QUEUE_COMPUTE_BIT
|
900 VK_QUEUE_TRANSFER_BIT
|
901 VK_QUEUE_SPARSE_BINDING_BIT
,
903 .timestampValidBits
= 64,
904 .minImageTransferGranularity
= (VkExtent3D
) { 1, 1, 1 },
913 libresoc_GetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice
,
915 VkQueueFamilyProperties
*pQueueFamilyProperties
)
917 if (getenv("LIBRESOC_TRACE")) {
918 fprintf(stderr
, "GetPhysicalDeviceQueueFamilyProperites called. \n");
920 LIBRESOC_FROM_HANDLE(libresoc_physical_device
, pdevice
, physicalDevice
);
921 if (!pQueueFamilyProperties
) {
922 libresoc_get_physical_device_queue_family_properties(pdevice
, pCount
, NULL
);
925 VkQueueFamilyProperties
*properties
[] = {
926 pQueueFamilyProperties
+ 0,
927 pQueueFamilyProperties
+ 1,
928 pQueueFamilyProperties
+ 2,
930 libresoc_get_physical_device_queue_family_properties(pdevice
, pCount
, properties
);
931 assert(*pCount
<= 3);
935 libresoc_GetPhysicalDeviceMemoryProperties(VkPhysicalDevice physicalDevice
,
936 VkPhysicalDeviceMemoryProperties
*pMemoryProperties
)
938 if (getenv("LIBRESOC_TRACE")) {
939 fprintf(stderr
, "GetPhysicalDEviceMemoryProperties called. \n");
941 LIBRESOC_FROM_HANDLE(libresoc_physical_device
, physical_device
, physicalDevice
);
943 *pMemoryProperties
= physical_device
->memory_properties
;
948 //libresoc_GetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties *pFormatProperties) {
950 // if (getenv("LIBRESOC_TRACE")) {
951 // fprintf(stderr, "GetPhysicalDeviceFormatProperties called. \n");
957 // libresoc_GetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkImageFormatProperties* pImageFormatProperties)
959 // if (getenv("LIBRESOC_TRACE")) {
960 // fprintf(stderr, "GetPhysicalDEviceImageFormatProperties called. \n");
964 // return VK_SUCCESS;
967 // libresoc_GetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkSampleCountFlagBits samples, VkImageUsageFlags usage, VkImageTiling tiling, uint32_t* pPropertyCount, VkSparseImageFormatProperties* pProperties)
969 // if (getenv("LIBRESOC_TRACE")) {
970 // fprintf(stderr, "GetPhysicalDeviceSparseImageFormatProperties called. \n");
975 libresoc_GetInstanceProcAddr(VkInstance _instance
,
978 if (getenv("LIBRESOC_TRACE")) {
979 fprintf(stderr
, "GetInstanceProcAddr called for: %s \n", pName
);
981 LIBRESOC_FROM_HANDLE(libresoc_instance
, instance
, _instance
);
983 /* The Vulkan 1.0 spec for vkGetInstanceProcAddr has a table of exactly
984 * when we have to return valid function pointers, NULL, or it's left
985 * undefined. See the table for exact details.
990 #define LOOKUP_LIBRESOC_ENTRYPOINT(entrypoint) \
991 if (strcmp(pName, "vk" #entrypoint) == 0) \
992 return (PFN_vkVoidFunction)libresoc_##entrypoint
994 LOOKUP_LIBRESOC_ENTRYPOINT(EnumerateInstanceExtensionProperties
);
995 LOOKUP_LIBRESOC_ENTRYPOINT(CreateInstance
);
996 LOOKUP_LIBRESOC_ENTRYPOINT(DestroyInstance
);
997 LOOKUP_LIBRESOC_ENTRYPOINT(EnumeratePhysicalDevices
);
998 LOOKUP_LIBRESOC_ENTRYPOINT(GetPhysicalDeviceFeatures
);
999 LOOKUP_LIBRESOC_ENTRYPOINT(GetPhysicalDeviceFormatProperties
);
1000 LOOKUP_LIBRESOC_ENTRYPOINT(GetPhysicalDeviceImageFormatProperties
);
1001 LOOKUP_LIBRESOC_ENTRYPOINT(GetPhysicalDeviceProperties
);
1002 LOOKUP_LIBRESOC_ENTRYPOINT(GetPhysicalDeviceQueueFamilyProperties
);
1003 LOOKUP_LIBRESOC_ENTRYPOINT(GetPhysicalDeviceMemoryProperties
);
1004 LOOKUP_LIBRESOC_ENTRYPOINT(GetDeviceProcAddr
);
1005 LOOKUP_LIBRESOC_ENTRYPOINT(CreateDevice
);
1006 LOOKUP_LIBRESOC_ENTRYPOINT(EnumerateDeviceExtensionProperties
);
1007 LOOKUP_LIBRESOC_ENTRYPOINT(GetPhysicalDeviceSparseImageFormatProperties
);
1010 #undef LOOKUP_LIBRESOC_ENTRYPOINT
1012 if (instance
== NULL
)
1015 int idx
= libresoc_get_instance_entrypoint_index(pName
);
1017 return instance
->dispatch
.entrypoints
[idx
];
1019 idx
= libresoc_get_physical_device_entrypoint_index(pName
);
1021 return instance
->physical_device_dispatch
.entrypoints
[idx
];
1023 idx
= libresoc_get_device_entrypoint_index(pName
);
1025 return instance
->device_dispatch
.entrypoints
[idx
];
1030 /* With version 1+ of the loader interface the ICD should expose
1031 * vk_icdGetInstanceProcAddr to work around certain LD_PRELOAD issues seen in apps.
1034 VKAPI_ATTR PFN_vkVoidFunction
1035 VKAPI_CALL
vk_icdGetInstanceProcAddr(VkInstance instance
,
1039 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
1040 vk_icdGetInstanceProcAddr(VkInstance instance
,
1043 if (getenv("LIBRESOC_TRACE")) {
1044 fprintf(stderr
, "vk_icdGetInstanceProcAddr called for: %s \n", pName
);
1046 return libresoc_GetInstanceProcAddr(instance
, pName
);
1050 libresoc_GetDeviceProcAddr(VkDevice _device
,
1053 if (getenv("LIBRESOC_TRACE")) {
1054 fprintf(stderr
, "GetDeviceProcAddr called for: %s \n", pName
);
1056 LIBRESOC_FROM_HANDLE(libresoc_device
, device
, _device
);
1058 if (!device
|| !pName
)
1061 int idx
= libresoc_get_device_entrypoint_index(pName
);
1065 return device
->dispatch
.entrypoints
[idx
];
1068 /* With version 4+ of the loader interface the ICD should expose
1069 * vk_icdGetPhysicalDeviceProcAddr()
1072 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
1073 vk_icdGetPhysicalDeviceProcAddr(VkInstance _instance
,
1077 vk_icdGetPhysicalDeviceProcAddr(VkInstance _instance
,
1080 if (getenv("LIBRESOC_TRACE")) {
1081 fprintf(stderr
, "vk_icdGetPhysicalDeviceProcAddr called for: %s \n", pName
);
1083 LIBRESOC_FROM_HANDLE(libresoc_instance
, instance
, _instance
);
1085 if (!pName
|| !instance
)
1088 int idx
= libresoc_get_physical_device_entrypoint_index(pName
);
1092 return instance
->physical_device_dispatch
.entrypoints
[idx
];
1096 libresoc_EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice
,
1097 const char *pLayerName
,
1098 uint32_t *pPropertyCount
,
1099 VkExtensionProperties
*pProperties
)
1101 if (getenv("LIBRESOC_TRACE")) {
1102 fprintf(stderr
, "EnumerateDeviceExtensionProperties called for layer: %s \n", pLayerName
);
1104 LIBRESOC_FROM_HANDLE(libresoc_physical_device
, device
, physicalDevice
);
1105 VK_OUTARRAY_MAKE(out
, pProperties
, pPropertyCount
);
1107 for (int i
= 0; i
< LIBRESOC_DEVICE_EXTENSION_COUNT
; i
++) {
1108 if (device
->supported_extensions
.extensions
[i
]) {
1109 vk_outarray_append(&out
, prop
) {
1110 *prop
= libresoc_device_extensions
[i
];
1115 return vk_outarray_status(&out
);
1119 libresoc_device_init_dispatch(struct libresoc_device
*device
)
1121 const struct libresoc_instance
*instance
= device
->physical_device
->instance
;
1122 const struct libresoc_device_dispatch_table
*dispatch_table_layer
= NULL
;
1124 for (unsigned i
= 0; i
< ARRAY_SIZE(device
->dispatch
.entrypoints
); i
++) {
1125 /* Vulkan requires that entrypoints for extensions which have not been
1126 * enabled must not be advertised.
1128 if (!libresoc_device_entrypoint_is_enabled(i
, instance
->apiVersion
,
1129 &instance
->enabled_extensions
,
1130 &device
->enabled_extensions
)) {
1131 device
->dispatch
.entrypoints
[i
] = NULL
;
1132 } else if (dispatch_table_layer
&&
1133 dispatch_table_layer
->entrypoints
[i
]) {
1134 device
->dispatch
.entrypoints
[i
] =
1135 dispatch_table_layer
->entrypoints
[i
];
1137 device
->dispatch
.entrypoints
[i
] =
1138 libresoc_device_dispatch_table
.entrypoints
[i
];
1144 check_physical_device_features(VkPhysicalDevice physicalDevice
,
1145 const VkPhysicalDeviceFeatures
*features
)
1147 LIBRESOC_FROM_HANDLE(libresoc_physical_device
, physical_device
, physicalDevice
);
1148 VkPhysicalDeviceFeatures supported_features
;
1149 libresoc_GetPhysicalDeviceFeatures(physicalDevice
, &supported_features
);
1150 VkBool32
*supported_feature
= (VkBool32
*)&supported_features
;
1151 VkBool32
*enabled_feature
= (VkBool32
*)features
;
1152 unsigned num_features
= sizeof(VkPhysicalDeviceFeatures
) / sizeof(VkBool32
);
1153 for (uint32_t i
= 0; i
< num_features
; i
++) {
1154 if (enabled_feature
[i
] && !supported_feature
[i
])
1155 return vk_error(physical_device
->instance
, VK_ERROR_FEATURE_NOT_PRESENT
);
1160 static int libresoc_get_device_extension_index(const char *name
)
1162 for (unsigned i
= 0; i
< LIBRESOC_DEVICE_EXTENSION_COUNT
; ++i
) {
1163 if (strcmp(name
, libresoc_device_extensions
[i
].extensionName
) == 0)
1170 libresoc_queue_init(struct libresoc_device
*device
, struct libresoc_queue
*queue
,
1171 uint32_t queue_family_index
, int idx
,
1172 VkDeviceQueueCreateFlags flags
,
1173 const VkDeviceQueueGlobalPriorityCreateInfoEXT
*global_priority
)
1175 queue
->_loader_data
.loaderMagic
= ICD_LOADER_MAGIC
;
1176 queue
->device
= device
;
1177 queue
->queue_family_index
= queue_family_index
;
1178 queue
->queue_idx
= idx
;
1179 queue
->flags
= flags
;
1180 list_inithead(&queue
->pending_submissions
);
1181 pthread_mutex_init(&queue
->pending_mutex
, NULL
);
1183 pthread_mutex_init(&queue
->thread_mutex
, NULL
);
1184 //queue->thread_submission = NULL;
1185 queue
->thread_running
= queue
->thread_exit
= false;
1186 VkResult result
= libresoc_create_pthread_cond(&queue
->thread_cond
);
1187 if (result
!= VK_SUCCESS
)
1188 return vk_error(device
->instance
, result
);
1194 libresoc_queue_finish(struct libresoc_queue
*queue
)
1196 //TODO: understand and enable following code
1197 // if (queue->thread_running) {
1198 // p_atomic_set(&queue->thread_exit, true);
1199 // pthread_cond_broadcast(&queue->thread_cond);
1200 // pthread_join(queue->submission_thread, NULL);
1202 // pthread_cond_destroy(&queue->thread_cond);
1203 // pthread_mutex_destroy(&queue->pending_mutex);
1204 // pthread_mutex_destroy(&queue->thread_mutex);
1206 // if (queue->hw_ctx)
1207 // queue->device->ws->ctx_destroy(queue->hw_ctx);
1209 // if (queue->initial_full_flush_preamble_cs)
1210 // queue->device->ws->cs_destroy(queue->initial_full_flush_preamble_cs);
1211 // if (queue->initial_preamble_cs)
1212 // queue->device->ws->cs_destroy(queue->initial_preamble_cs);
1213 // if (queue->continue_preamble_cs)
1214 // queue->device->ws->cs_destroy(queue->continue_preamble_cs);
1215 // if (queue->descriptor_bo)
1216 // queue->device->ws->buffer_destroy(queue->descriptor_bo);
1217 // if (queue->scratch_bo)
1218 // queue->device->ws->buffer_destroy(queue->scratch_bo);
1219 // if (queue->esgs_ring_bo)
1220 // queue->device->ws->buffer_destroy(queue->esgs_ring_bo);
1221 // if (queue->gsvs_ring_bo)
1222 // queue->device->ws->buffer_destroy(queue->gsvs_ring_bo);
1223 // if (queue->tess_rings_bo)
1224 // queue->device->ws->buffer_destroy(queue->tess_rings_bo);
1225 // if (queue->gds_bo)
1226 // queue->device->ws->buffer_destroy(queue->gds_bo);
1227 // if (queue->gds_oa_bo)
1228 // queue->device->ws->buffer_destroy(queue->gds_oa_bo);
1229 // if (queue->compute_scratch_bo)
1230 // queue->device->ws->buffer_destroy(queue->compute_scratch_bo);
1233 libresoc_CreateDevice(VkPhysicalDevice physicalDevice
,
1234 const VkDeviceCreateInfo
*pCreateInfo
,
1235 const VkAllocationCallbacks
*pAllocator
,
1238 if (getenv("LIBRESOC_TRACE")) {
1239 fprintf(stderr
, "CreateDevice called \n");
1241 LIBRESOC_FROM_HANDLE(libresoc_physical_device
, physical_device
, physicalDevice
);
1243 struct libresoc_device
*device
;
1245 /* Check enabled features */
1246 if (pCreateInfo
->pEnabledFeatures
) {
1247 result
= check_physical_device_features(physicalDevice
,
1248 pCreateInfo
->pEnabledFeatures
);
1249 if (result
!= VK_SUCCESS
)
1253 device
= vk_zalloc2(&physical_device
->instance
->alloc
, pAllocator
,
1255 VK_SYSTEM_ALLOCATION_SCOPE_DEVICE
);
1257 return vk_error(physical_device
->instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
1259 vk_device_init(&device
->vk
, pCreateInfo
,
1260 &physical_device
->instance
->alloc
, pAllocator
);
1262 device
->instance
= physical_device
->instance
;
1263 device
->physical_device
= physical_device
;
1265 for (uint32_t i
= 0; i
< pCreateInfo
->enabledExtensionCount
; i
++) {
1266 const char *ext_name
= pCreateInfo
->ppEnabledExtensionNames
[i
];
1267 int index
= libresoc_get_device_extension_index(ext_name
);
1268 if (index
< 0 || !physical_device
->supported_extensions
.extensions
[index
]) {
1269 vk_free(&device
->vk
.alloc
, device
);
1270 return vk_error(physical_device
->instance
, VK_ERROR_EXTENSION_NOT_PRESENT
);
1273 device
->enabled_extensions
.extensions
[index
] = true;
1276 libresoc_device_init_dispatch(device
);
1278 for (unsigned i
= 0; i
< pCreateInfo
->queueCreateInfoCount
; i
++) {
1279 const VkDeviceQueueCreateInfo
*queue_create
= &pCreateInfo
->pQueueCreateInfos
[i
];
1280 uint32_t qfi
= queue_create
->queueFamilyIndex
;
1281 const VkDeviceQueueGlobalPriorityCreateInfoEXT
*global_priority
=
1282 vk_find_struct_const(queue_create
->pNext
, DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT
);
1285 device
->queues
[qfi
] = vk_alloc(&device
->vk
.alloc
,
1286 queue_create
->queueCount
* sizeof(struct libresoc_queue
), 8, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE
);
1287 if (!device
->queues
[qfi
]) {
1288 result
= VK_ERROR_OUT_OF_HOST_MEMORY
;
1292 memset(device
->queues
[qfi
], 0, queue_create
->queueCount
* sizeof(struct libresoc_queue
));
1294 device
->queue_count
[qfi
] = queue_create
->queueCount
;
1296 for (unsigned q
= 0; q
< queue_create
->queueCount
; q
++) {
1297 result
= libresoc_queue_init(device
, &device
->queues
[qfi
][q
],
1298 qfi
, q
, queue_create
->flags
,
1300 if (result
!= VK_SUCCESS
)
1305 if (result
!= VK_SUCCESS
)
1308 VkPipelineCacheCreateInfo ci
;
1309 ci
.sType
= VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO
;
1312 ci
.pInitialData
= NULL
;
1313 ci
.initialDataSize
= 0;
1315 result
= libresoc_CreatePipelineCache(libresoc_device_to_handle(device
),
1317 if (result
!= VK_SUCCESS
)
1320 *pDevice
= libresoc_device_to_handle(device
);
1324 libresoc_DestroyPipelineCache(libresoc_device_to_handle(device
), pc
, NULL
);
1325 for (unsigned i
= 0; i
< LIBRESOC_MAX_QUEUE_FAMILIES
; i
++) {
1326 for (unsigned q
= 0; q
< device
->queue_count
[i
]; q
++)
1327 libresoc_queue_finish(&device
->queues
[i
][q
]);
1328 if (device
->queue_count
[i
])
1329 vk_free(&device
->vk
.alloc
, device
->queues
[i
]);
1332 vk_free(&device
->vk
.alloc
, device
);
1337 libresoc_DestroyDevice(VkDevice _device
,
1338 const VkAllocationCallbacks
*pAllocator
)
1340 if (getenv("LIBRESOC_TRACE")) {
1341 fprintf(stderr
, "DestroyDevice called. \n");
1346 void libresoc_GetDeviceQueue(
1348 uint32_t queueFamilyIndex
,
1349 uint32_t queueIndex
,
1352 if (getenv("LIBRESOC_TRACE")) {
1353 fprintf(stderr
, "GetDeviceQueue called. \n");
1355 LIBRESOC_FROM_HANDLE(libresoc_device
, device
, _device
);
1356 struct libresoc_queue
*queue
;
1358 queue
= &device
->queues
[queueFamilyIndex
][queueIndex
];
1359 *pQueue
= libresoc_queue_to_handle(queue
);
1362 VkResult
libresoc_QueueWaitIdle(
1365 LIBRESOC_FROM_HANDLE(libresoc_queue
, queue
, _queue
);
1367 pthread_mutex_lock(&queue
->pending_mutex
);
1368 while (!list_is_empty(&queue
->pending_submissions
)) {
1369 pthread_cond_wait(&queue
->device
->timeline_cond
, &queue
->pending_mutex
);
1371 pthread_mutex_unlock(&queue
->pending_mutex
);
1376 VkResult
libresoc_DeviceWaitIdle(
1379 LIBRESOC_FROM_HANDLE(libresoc_device
, device
, _device
);
1381 for (unsigned i
= 0; i
< LIBRESOC_MAX_QUEUE_FAMILIES
; i
++) {
1382 for (unsigned q
= 0; q
< device
->queue_count
[i
]; q
++) {
1384 libresoc_QueueWaitIdle(libresoc_queue_to_handle(&device
->queues
[i
][q
]));
1386 if (result
!= VK_SUCCESS
)
1393 void libresoc_GetPhysicalDeviceProperties2(
1394 VkPhysicalDevice physicalDevice
,
1395 VkPhysicalDeviceProperties2
*pProperties
)
1397 // LIBRESOC_FROM_HANDLE(libresoc_physical_device, pdevice, physicalDevice);
1398 libresoc_GetPhysicalDeviceProperties(physicalDevice
, &pProperties
->properties
);
1399 //TODO: add more stuffs when required
1402 void libresoc_GetPhysicalDeviceFeatures2(
1403 VkPhysicalDevice physicalDevice
,
1404 VkPhysicalDeviceFeatures2
*pFeatures
)
1406 // LIBRESOC_FROM_HANDLE(libresoc_physical_device, pdevice, physicalDevice);
1407 libresoc_GetPhysicalDeviceFeatures(physicalDevice
, &pFeatures
->features
);
1410 void libresoc_GetPhysicalDeviceQueueFamilyProperties2(
1411 VkPhysicalDevice physicalDevice
,
1413 VkQueueFamilyProperties2
*pQueueFamilyProperties
)
1415 LIBRESOC_FROM_HANDLE(libresoc_physical_device
, pdevice
, physicalDevice
);
1416 if (!pQueueFamilyProperties
) {
1417 libresoc_get_physical_device_queue_family_properties(pdevice
, pCount
, NULL
);
1420 VkQueueFamilyProperties
*properties
[] = {
1421 &pQueueFamilyProperties
[0].queueFamilyProperties
,
1422 &pQueueFamilyProperties
[1].queueFamilyProperties
,
1423 &pQueueFamilyProperties
[2].queueFamilyProperties
,
1425 libresoc_get_physical_device_queue_family_properties(pdevice
, pCount
, properties
);
1426 assert(*pCount
<= 3);
1430 libresoc_get_memory_budget_properties(VkPhysicalDevice physicalDevice
,
1431 VkPhysicalDeviceMemoryBudgetPropertiesEXT
*memoryBudget
)
1436 void libresoc_GetPhysicalDeviceMemoryProperties2(
1437 VkPhysicalDevice physicalDevice
,
1438 VkPhysicalDeviceMemoryProperties2
*pMemoryProperties
)
1440 libresoc_GetPhysicalDeviceMemoryProperties(physicalDevice
,
1441 &pMemoryProperties
->memoryProperties
);
1443 VkPhysicalDeviceMemoryBudgetPropertiesEXT
*memory_budget
=
1444 vk_find_struct(pMemoryProperties
->pNext
,
1445 PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT
);
1447 libresoc_get_memory_budget_properties(physicalDevice
, memory_budget
);
1450 VkResult
libresoc_CreateSemaphore(
1452 const VkSemaphoreCreateInfo
* pCreateInfo
,
1453 const VkAllocationCallbacks
* pAllocator
,
1454 VkSemaphore
* pSemaphore
)
1456 //TODO: minimal things as of now, add more complex code as required
1457 LIBRESOC_FROM_HANDLE(libresoc_device
, device
, _device
);
1458 struct libresoc_semaphore
*sem
= vk_alloc2(&device
->vk
.alloc
, pAllocator
,
1460 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
1462 return vk_error(device
->instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
1464 vk_object_base_init(&device
->vk
, &sem
->base
,
1465 VK_OBJECT_TYPE_SEMAPHORE
);
1467 *pSemaphore
= libresoc_semaphore_to_handle(sem
);
1471 void libresoc_GetImageMemoryRequirements(
1474 VkMemoryRequirements
* pMemoryRequirements
)
1476 LIBRESOC_FROM_HANDLE(libresoc_device
, device
, _device
);
1477 LIBRESOC_FROM_HANDLE(libresoc_image
, image
, _image
);
1479 pMemoryRequirements
->memoryTypeBits
= (1u << device
->physical_device
->memory_properties
.memoryTypeCount
) - 1;
1481 pMemoryRequirements
->size
= image
->size
;
1482 pMemoryRequirements
->alignment
= image
->alignment
;
1485 void libresoc_GetImageMemoryRequirements2(
1487 const VkImageMemoryRequirementsInfo2
*pInfo
,
1488 VkMemoryRequirements2
*pMemoryRequirements
)
1490 libresoc_GetImageMemoryRequirements(device
, pInfo
->image
,
1491 &pMemoryRequirements
->memoryRequirements
);
1494 VkResult
libresoc_BindImageMemory2(VkDevice device
,
1495 uint32_t bindInfoCount
,
1496 const VkBindImageMemoryInfo
*pBindInfos
)
1498 for (uint32_t i
= 0; i
< bindInfoCount
; ++i
) {
1499 LIBRESOC_FROM_HANDLE(libresoc_device_memory
, mem
, pBindInfos
[i
].memory
);
1500 LIBRESOC_FROM_HANDLE(libresoc_image
, image
, pBindInfos
[i
].image
);
1503 image
->bytes
= mem
->bytes
;
1504 // image->offset = pBindInfos[i].memoryOffset;
1506 // image->bo = NULL;
1507 // image->offset = 0;
1514 VkResult
libresoc_BindImageMemory(
1517 VkDeviceMemory memory
,
1518 VkDeviceSize memoryOffset
)
1520 const VkBindImageMemoryInfo info
= {
1521 .sType
= VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO
,
1524 .memoryOffset
= memoryOffset
1527 return libresoc_BindImageMemory2(device
, 1, &info
);
1530 // static VkResult libresoc_queue_submit(struct libresoc_queue *queue,
1531 // const struct libresoc_queue_submission *submission)
1533 // return VK_SUCCESS;
1534 // struct libresoc_deferred_queue_submission *deferred = NULL;
1536 // VkResult result = libresoc_create_deferred_submission(queue, submission, &deferred);
1537 // if (result != VK_SUCCESS)
1540 // struct list_head processing_list;
1541 // list_inithead(&processing_list);
1543 // result = libresoc_queue_enqueue_submission(deferred, &processing_list);
1544 // if (result != VK_SUCCESS) {
1545 // /* If anything is in the list we leak. */
1546 // assert(list_is_empty(&processing_list));
1549 // return libresoc_process_submissions(&processing_list);
1552 /* Signals fence as soon as all the work currently put on queue is done. */
1553 // static VkResult libresoc_signal_fence(struct libresoc_queue *queue,
1556 // return libresoc_queue_submit(queue, &(struct libresoc_queue_submission) {
1561 // static bool libresoc_submit_has_effects(const VkSubmitInfo *info)
1563 // return info->commandBufferCount ||
1564 // info->waitSemaphoreCount ||
1565 // info->signalSemaphoreCount;
1568 static int double_triarea(const struct int4
*a
, const struct int4
*b
, const struct int4
*c
)
1570 return (b
->x
- a
->x
) * (c
->y
- a
->y
) - (b
->y
- a
->y
) * (c
->x
- a
->x
);
1573 static void MinMax(struct int4
*coords
, struct int4
*minwin
, struct int4
*maxwin
)
1575 minwin
->x
= INT_MAX
;
1576 minwin
->y
= INT_MAX
;
1577 minwin
->z
= INT_MAX
;
1578 minwin
->w
= INT_MAX
;
1579 maxwin
->x
= INT_MIN
;
1580 maxwin
->y
= INT_MIN
;
1581 maxwin
->z
= INT_MIN
;
1582 maxwin
->w
= INT_MIN
;
1584 for(int i
= 0; i
< 3; i
++)
1586 for(int c
= 0; c
< 4; c
++)
1588 minwin
->v
[c
] = (minwin
->v
[c
] < coords
[i
].v
[c
]) ? minwin
->v
[c
] : coords
[i
].v
[c
];
1589 maxwin
->v
[c
] = (maxwin
->v
[c
] > coords
[i
].v
[c
]) ? maxwin
->v
[c
] : coords
[i
].v
[c
];
1594 static float clamp01(float in
)
1596 return in
> 1.0f
? 1.0f
: (in
< 0.0f
? 0.0f
: in
);
1599 static void ProcessTriangles(struct TriangleWork
*work
)
1601 struct GPUState
*state
= work
->state
;
1602 LIBRESOC_FROM_HANDLE(libresoc_image
, img
, state
->col
[0]);
1603 LIBRESOC_FROM_HANDLE(libresoc_pipeline
, pipeline
, state
->pipeline
);
1604 const uint32_t w
= img
->width
;
1605 const uint32_t h
= img
->height
;
1606 byte
*bytes
= img
->bytes
;
1608 for(int y
= work
->minwin
.y
; y
< work
->maxwin
.y
; y
++)
1610 for(int x
= work
->minwin
.x
; x
< work
->maxwin
.x
; x
++)
1612 const int PAx
= work
->tri
[0].x
- x
;
1613 const int PAy
= work
->tri
[0].y
- y
;
1615 const int ux
= (work
->ACx
* PAy
) - (work
->ACy
* PAx
);
1616 const int uy
= (PAx
* work
->ABy
) - (PAy
* work
->ABx
);
1619 b
.x
= (work
->area2
- (ux
+ uy
));
1624 // if (b.x >= 0 && b.y >= 0 && b.z >= 0)
1631 float pixdepth
= n
.x
* work
->depth
.x
+ n
.y
* work
->depth
.y
+ n
.z
* work
->depth
.z
;
1633 n
.x
*= work
->invw
.x
;
1634 n
.y
*= work
->invw
.y
;
1635 n
.z
*= work
->invw
.z
;
1637 float invlen
= 1.0f
/ (n
.x
+ n
.y
+ n
.z
);
1644 pipeline
->fs(state
, pixdepth
, &n
, work
->vsout
, &pix
);
1645 bytes
[(y
* w
+ x
) * bpp
+ 2] = (byte
)(clamp01(pix
.x
) * 255.0f
);
1646 bytes
[(y
* w
+ x
) * bpp
+ 1] = (byte
)(clamp01(pix
.y
) * 255.0f
);
1647 bytes
[(y
* w
+ x
) * bpp
+ 0] = (byte
)(clamp01(pix
.z
) * 255.0f
);
1654 static uint32_t GetIndex(struct GPUState
*state
, uint32_t vertexIndex
, bool indexed
)
1656 LIBRESOC_FROM_HANDLE(libresoc_buffer
, buf
, state
->ib
.buffer
);
1660 const byte
*ib
= buf
->bytes
+ state
->ib
.offset
;
1662 if(state
->ib
.indexType
== VK_INDEX_TYPE_UINT16
)
1664 uint16_t *i16
= (uint16_t *)ib
;
1670 uint32_t *i32
= (uint32_t *)ib
;
1676 static void ClearTarget(VkImage target
, const VkClearColorValue
*col
)
1679 LIBRESOC_FROM_HANDLE(libresoc_image
, img
, target
);
1680 byte
*bits
= img
->bytes
;
1681 const uint32_t w
= img
->width
;
1682 const uint32_t h
= img
->height
;
1683 const uint32_t bpp
= 4;
1686 eval
[2] = (byte
)(col
->float32
[0] * 255.0f
);
1687 eval
[1] = (byte
)(col
->float32
[1] * 255.0f
);
1688 eval
[0] = (byte
)(col
->float32
[2] * 255.0f
);
1689 eval
[3] = (byte
)(col
->float32
[3] * 255.0f
);
1693 memset(bits
, eval
[2], w
* h
);
1697 for(uint32_t y
= 0; y
< h
; y
++)
1699 for(uint32_t x
= 0; x
< w
; x
++)
1701 memcpy(&bits
[(y
* w
+ x
) * bpp
], eval
, 4);
1707 static void DrawTriangles(struct GPUState
*state
, int numVerts
, uint32_t first
, bool indexed
)
1709 LIBRESOC_FROM_HANDLE(libresoc_image
, img
, state
->col
[0]);
1710 LIBRESOC_FROM_HANDLE(libresoc_pipeline
, pipeline
, state
->pipeline
);
1711 const uint32_t w
= img
->width
;
1712 const uint32_t h
= img
->height
;
1713 struct VertexCacheEntry
*vertices
;
1714 vertices
= (struct VertexCacheEntry
*)malloc(sizeof(struct VertexCacheEntry
) * numVerts
);
1716 int lastVert
= numVerts
- 3;
1717 uint32_t vertexIndex
= first
;
1719 struct VertexCacheEntry tri
[4];
1720 // For now we support only VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST
1721 for(int v
= 0; v
<= lastVert
; v
+= 3)
1723 pipeline
->vs(state
, GetIndex(state
, vertexIndex
, indexed
), &tri
[0]);
1725 pipeline
->vs(state
, GetIndex(state
, vertexIndex
, indexed
), &tri
[1]);
1727 pipeline
->vs(state
, GetIndex(state
, vertexIndex
, indexed
), &tri
[2]);
1729 vertices
[v
] = tri
[0];
1730 vertices
[v
+ 1] = tri
[1];
1731 vertices
[v
+ 2] = tri
[2];
1734 struct int4
*winCords
;
1735 winCords
= (struct int4
*)malloc(sizeof(struct int4
) * numVerts
);
1737 for(int v
=0; v
<= lastVert
; ++v
)
1741 win
.x
= (int)((vertices
[v
].position
.x
/ vertices
[v
].position
.w
+ 1.0f
) * 0.5f
* w
);
1742 win
.y
= (int)((vertices
[v
].position
.y
* -1.0f
/ vertices
[v
].position
.w
+ 1.0f
) * 0.5f
* h
);
1747 for(int i
= 0; i
<= lastVert
; i
+= 3)
1750 // culling can be done here
1751 int area2
= double_triarea(&winCords
[i
+ 0], &winCords
[i
+ 1], &winCords
[i
+ 2]);
1754 int area2_flipped
= area2
;
1755 struct TriangleWork work
;
1757 struct int4 minwin
, maxwin
;
1758 MinMax(&winCords
[i
], &minwin
, &maxwin
);
1760 minwin
.x
= (0 > minwin
.x
) ? 0 : minwin
.x
;
1761 minwin
.y
= (0 > minwin
.y
) ? 0 : minwin
.y
;
1762 maxwin
.x
= ((int)(w
- 1) < maxwin
.x
) ? (int)(w
- 1) : maxwin
.x
;
1763 maxwin
.y
= ((int)(h
- 1) < maxwin
.y
) ? (int)(h
- 1) : maxwin
.y
;
1766 work
.ABx
= winCords
[i
+ 1].x
- winCords
[i
+ 0].x
;
1767 work
.ABy
= winCords
[i
+ 1].y
- winCords
[i
+ 0].y
;
1768 work
.ACx
= winCords
[i
+ 2].x
- winCords
[i
+ 0].x
;
1769 work
.ACy
= winCords
[i
+ 2].y
- winCords
[i
+ 0].y
;
1770 work
.vsout
= &vertices
[i
];
1771 work
.tri
= &winCords
[i
];
1772 // work.barymul = barymul;
1774 work
.invarea
= 1.0f
/ (float)(area2_flipped
);
1775 work
.invw
.x
= 1.0f
/ vertices
[i
+ 0].position
.w
;
1776 work
.invw
.y
= 1.0f
/ vertices
[i
+ 1].position
.w
;
1777 work
.invw
.z
= 1.0f
/ vertices
[i
+ 2].position
.w
;
1779 work
.depth
.x
= vertices
[i
+ 0].position
.z
* work
.invw
.x
;
1780 work
.depth
.y
= vertices
[i
+ 1].position
.z
* work
.invw
.y
;
1781 work
.depth
.z
= vertices
[i
+ 2].position
.z
* work
.invw
.z
;
1782 work
.depth
.w
= 0.0f
;
1784 const int blockSize
= 32;
1786 int xblocks
= 1 + (maxwin
.x
- minwin
.x
) / blockSize
;
1787 int yblocks
= 1 + (maxwin
.y
- minwin
.y
) / blockSize
;
1791 for(int x
= 0; x
< xblocks
; x
++)
1793 for(int y
= 0; y
< yblocks
; y
++)
1795 work
.minwin
= minwin
;
1796 work
.minwin
.x
+= blockSize
* x
;
1797 work
.minwin
.y
+= blockSize
* y
;
1799 work
.maxwin
.x
= (maxwin
.x
< work
.minwin
.x
+ blockSize
) ? maxwin
.x
: work
.minwin
.x
+ blockSize
;
1800 work
.maxwin
.y
= (maxwin
.y
< work
.minwin
.y
+ blockSize
) ? maxwin
.y
: work
.minwin
.y
+ blockSize
;
1805 ProcessTriangles(&work
);
1810 static void execute(VkCommandBuffer commandBuffer
)
1812 LIBRESOC_FROM_HANDLE(libresoc_cmd_buffer
, cmd_buffer
, commandBuffer
);
1813 struct GPUState state
= {0};
1814 list_for_each_entry(struct libresoc_cmd
, lcmd
,
1815 &cmd_buffer
->cmd
.link
, link
) {
1816 int *commandId
= (int *)&lcmd
->command
;
1817 switch (*commandId
) {
1818 case BeginRenderPassID
:
1820 LIBRESOC_FROM_HANDLE(libresoc_render_pass
, render_pass
, lcmd
->command
.beginRenderPass
.renderPass
);
1821 LIBRESOC_FROM_HANDLE(libresoc_framebuffer
, frame_buffer
, lcmd
->command
.beginRenderPass
.framebuffer
);
1822 LIBRESOC_FROM_HANDLE(libresoc_image
, img
, state
.col
[0]);
1823 struct libresoc_subpass subpass
= render_pass
->subpasses
[0];
1824 struct libresoc_subpass_attachment attachment
= subpass
.attachments
[0];
1826 state
.col
[0] = (struct VkImage_T
*)frame_buffer
->attachments
[attachment
.attachment
]->image
;
1830 if(attachment
.clear
)
1832 ClearTarget(state
.col
[0], &lcmd
->command
.beginRenderPass
.clearval
[clearIdx
++].color
);
1835 // VkRenderPass_T::Attachment &depth = subpass.depthAttachment;
1837 // if(depth.idx >= 0)
1839 // state.depth = data.framebuffer->attachments[depth.idx]->image;
1843 // ClearTarget(state.depth, data.clearval[clearIdx++].depthStencil);
1848 case EndRenderPassID
:
1850 state
.col
[0] = VK_NULL_HANDLE
;
1853 case BindPipelineID
:
1855 state
.pipeline
= lcmd
->command
.bindPipeline
.pipeline
;
1858 case BindDescriptorSetsID
:
1860 state
.sets
[lcmd
->command
.bindDescriptorSets
.idx
] = lcmd
->command
.bindDescriptorSets
.set
;
1865 state
.vbs
[lcmd
->command
.bindVB
.slot
].buffer
= lcmd
->command
.bindVB
.buffer
;
1866 state
.vbs
[lcmd
->command
.bindVB
.slot
].offset
= lcmd
->command
.bindVB
.offset
;
1871 state
.ib
.buffer
= lcmd
->command
.bindIB
.buffer
;
1872 state
.ib
.offset
= lcmd
->command
.bindIB
.offset
;
1873 state
.ib
.indexType
= lcmd
->command
.bindIB
.indexType
;
1878 state
.view
= lcmd
->command
.setViewport
.view
;
1883 case PushConstantsID
:
1885 memcpy(state
.pushconsts
+ lcmd
->command
.pushConstants
.offset
,
1886 lcmd
->command
.pushConstants
.values
,
1887 lcmd
->command
.pushConstants
.size
);
1892 DrawTriangles(&state
, lcmd
->command
.draw
.vertexCount
, lcmd
->command
.draw
.firstVertex
, false);
1901 case PipelineBarrierID
:
1907 VkResult
libresoc_QueueSubmit(
1909 uint32_t submitCount
,
1910 const VkSubmitInfo
* pSubmits
,
1913 // LIBRESOC_FROM_HANDLE(libresoc_queue, queue, _queue);
1914 for(uint32_t i
= 0; i
< submitCount
; i
++)
1916 for(uint32_t c
= 0; c
< pSubmits
[i
].commandBufferCount
; c
++)
1918 execute(pSubmits
[i
].pCommandBuffers
[c
]);
1924 VkResult
libresoc_CreateFence(
1926 const VkFenceCreateInfo
* pCreateInfo
,
1927 const VkAllocationCallbacks
* pAllocator
,
1930 LIBRESOC_FROM_HANDLE(libresoc_device
, device
, _device
);
1931 // const VkExportFenceCreateInfo *export =
1932 // vk_find_struct_const(pCreateInfo->pNext, EXPORT_FENCE_CREATE_INFO);
1933 // VkExternalFenceHandleTypeFlags handleTypes =
1934 // export ? export->handleTypes : 0;
1935 struct libresoc_fence
*fence
;
1937 fence
= vk_zalloc2(&device
->vk
.alloc
, pAllocator
, sizeof(*fence
), 8,
1938 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
1940 return vk_error(device
->instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
1942 vk_object_base_init(&device
->vk
, &fence
->base
, VK_OBJECT_TYPE_FENCE
);
1944 // if (device->always_use_syncobj || handleTypes) {
1945 // fence->permanent.kind = LIBRESOC_FENCE_SYNCOBJ;
1947 // bool create_signaled = false;
1948 // if (pCreateInfo->flags & VK_FENCE_CREATE_SIGNALED_BIT)
1949 // create_signaled = true;
1951 // int ret = device->ws->create_syncobj(device->ws, create_signaled,
1952 // &fence->permanent.syncobj);
1954 // libresoc_destroy_fence(device, pAllocator, fence);
1955 // return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
1958 // fence->permanent.kind = LIBRESOC_FENCE_WINSYS;
1960 // fence->permanent.fence = device->ws->create_fence();
1961 // if (!fence->permanent.fence) {
1962 // vk_free2(&device->vk.alloc, pAllocator, fence);
1963 // libresoc_destroy_fence(device, pAllocator, fence);
1964 // return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
1966 // if (pCreateInfo->flags & VK_FENCE_CREATE_SIGNALED_BIT)
1967 // device->ws->signal_fence(fence->permanent.fence);
1970 *pFence
= libresoc_fence_to_handle(fence
);
1975 VkResult
libresoc_MapMemory(
1977 VkDeviceMemory _memory
,
1978 VkDeviceSize offset
,
1980 VkMemoryMapFlags flags
,
1983 LIBRESOC_FROM_HANDLE(libresoc_device
, device
, _device
);
1984 LIBRESOC_FROM_HANDLE(libresoc_device_memory
, mem
, _memory
);
1992 *ppData
= mem
->user_ptr
;
1994 *ppData
= mem
->bytes
;
1995 //*ppData = device->ws->buffer_map(mem->bo);
2002 return vk_error(device
->instance
, VK_ERROR_MEMORY_MAP_FAILED
);
2005 void libresoc_UnmapMemory(
2007 VkDeviceMemory _memory
)
2009 // LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
2010 LIBRESOC_FROM_HANDLE(libresoc_device_memory
, mem
, _memory
);
2015 // if (mem->user_ptr == NULL)
2016 // device->ws->buffer_unmap(mem->bo);
2019 VkResult
libresoc_WaitForFences(
2021 uint32_t fenceCount
,
2022 const VkFence
* pFences
,
2030 VkResult
libresoc_ResetFences(VkDevice _device
,
2031 uint32_t fenceCount
,
2032 const VkFence
*pFences
)
2039 VkResult
libresoc_CreateFramebuffer(
2041 const VkFramebufferCreateInfo
* pCreateInfo
,
2042 const VkAllocationCallbacks
* pAllocator
,
2043 VkFramebuffer
* pFramebuffer
)
2045 LIBRESOC_FROM_HANDLE(libresoc_device
, device
, _device
);
2046 struct libresoc_framebuffer
*framebuffer
;
2047 const VkFramebufferAttachmentsCreateInfo
*imageless_create_info
=
2048 vk_find_struct_const(pCreateInfo
->pNext
,
2049 FRAMEBUFFER_ATTACHMENTS_CREATE_INFO
);
2051 assert(pCreateInfo
->sType
== VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO
);
2053 size_t size
= sizeof(*framebuffer
);
2054 if (!imageless_create_info
)
2055 size
+= sizeof(struct libresoc_image_view
*) * pCreateInfo
->attachmentCount
;
2056 framebuffer
= vk_alloc2(&device
->vk
.alloc
, pAllocator
, size
, 8,
2057 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
2058 if (framebuffer
== NULL
)
2059 return vk_error(device
->instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
2061 vk_object_base_init(&device
->vk
, &framebuffer
->base
,
2062 VK_OBJECT_TYPE_FRAMEBUFFER
);
2064 framebuffer
->attachment_count
= pCreateInfo
->attachmentCount
;
2065 framebuffer
->width
= pCreateInfo
->width
;
2066 framebuffer
->height
= pCreateInfo
->height
;
2067 framebuffer
->layers
= pCreateInfo
->layers
;
2068 if (imageless_create_info
) {
2069 for (unsigned i
= 0; i
< imageless_create_info
->attachmentImageInfoCount
; ++i
) {
2070 const VkFramebufferAttachmentImageInfo
*attachment
=
2071 imageless_create_info
->pAttachmentImageInfos
+ i
;
2072 framebuffer
->width
= MIN2(framebuffer
->width
, attachment
->width
);
2073 framebuffer
->height
= MIN2(framebuffer
->height
, attachment
->height
);
2074 framebuffer
->layers
= MIN2(framebuffer
->layers
, attachment
->layerCount
);
2077 for (uint32_t i
= 0; i
< pCreateInfo
->attachmentCount
; i
++) {
2078 VkImageView _iview
= pCreateInfo
->pAttachments
[i
];
2079 struct libresoc_image_view
*iview
= libresoc_image_view_from_handle(_iview
);
2080 framebuffer
->attachments
[i
] = iview
;
2081 framebuffer
->width
= MIN2(framebuffer
->width
, iview
->extent
.width
);
2082 framebuffer
->height
= MIN2(framebuffer
->height
, iview
->extent
.height
);
2083 framebuffer
->layers
= MIN2(framebuffer
->layers
, libresoc_surface_max_layer_count(iview
));
2087 *pFramebuffer
= libresoc_framebuffer_to_handle(framebuffer
);
2091 void libresoc_DestroyFramebuffer(
2094 const VkAllocationCallbacks
* pAllocator
)
2097 VkResult
libresoc_CreateBuffer(
2099 const VkBufferCreateInfo
* pCreateInfo
,
2100 const VkAllocationCallbacks
* pAllocator
,
2103 LIBRESOC_FROM_HANDLE(libresoc_device
, device
, _device
);
2104 struct libresoc_buffer
*buffer
;
2106 buffer
= vk_alloc2(&device
->vk
.alloc
, pAllocator
, sizeof(*buffer
), 8,
2107 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
2109 return vk_error(device
->instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
2111 vk_object_base_init(&device
->vk
, &buffer
->base
, VK_OBJECT_TYPE_BUFFER
);
2113 buffer
->size
= pCreateInfo
->size
;
2114 buffer
->bytes
= NULL
;
2115 *pBuffer
= libresoc_buffer_to_handle(buffer
);
2120 void libresoc_DestroyBuffer(
2123 const VkAllocationCallbacks
* pAllocator
)
2126 void libresoc_GetBufferMemoryRequirements(
2129 VkMemoryRequirements
* pMemoryRequirements
)
2131 LIBRESOC_FROM_HANDLE(libresoc_device
, device
, _device
);
2132 LIBRESOC_FROM_HANDLE(libresoc_buffer
, buffer
, _buffer
);
2134 pMemoryRequirements
->memoryTypeBits
= (1u << device
->physical_device
->memory_properties
.memoryTypeCount
) - 1;
2136 pMemoryRequirements
->alignment
= 16;
2138 pMemoryRequirements
->size
= align64(buffer
->size
, pMemoryRequirements
->alignment
);
2141 VkResult
libresoc_BindBufferMemory(
2144 VkDeviceMemory _memory
,
2145 VkDeviceSize memoryOffset
)
2147 LIBRESOC_FROM_HANDLE(libresoc_buffer
, buffer
, _buffer
);
2148 LIBRESOC_FROM_HANDLE(libresoc_device_memory
, memory
, _memory
);
2149 buffer
->bytes
= memory
->bytes
+ memoryOffset
;
2153 void libresoc_DestroyFence(
2156 const VkAllocationCallbacks
* pAllocator
)
2160 void libresoc_DestroySemaphore(
2162 VkSemaphore _semaphore
,
2163 const VkAllocationCallbacks
* pAllocator
)