+ LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
+ struct libresoc_queue *queue;
+
+ queue = &device->queues[queueFamilyIndex][queueIndex];
+ *pQueue = libresoc_queue_to_handle(queue);
+}
+
+VkResult libresoc_QueueWaitIdle(
+ VkQueue _queue)
+{
+ LIBRESOC_FROM_HANDLE(libresoc_queue, queue, _queue);
+
+ pthread_mutex_lock(&queue->pending_mutex);
+ while (!list_is_empty(&queue->pending_submissions)) {
+ pthread_cond_wait(&queue->device->timeline_cond, &queue->pending_mutex);
+ }
+ pthread_mutex_unlock(&queue->pending_mutex);
+
+ return VK_SUCCESS;
+}
+
+VkResult libresoc_DeviceWaitIdle(
+ VkDevice _device)
+{
+ LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
+
+ for (unsigned i = 0; i < LIBRESOC_MAX_QUEUE_FAMILIES; i++) {
+ for (unsigned q = 0; q < device->queue_count[i]; q++) {
+ VkResult result =
+ libresoc_QueueWaitIdle(libresoc_queue_to_handle(&device->queues[i][q]));
+
+ if (result != VK_SUCCESS)
+ return result;
+ }
+ }
+ return VK_SUCCESS;
+}
+
+void libresoc_GetPhysicalDeviceProperties2(
+ VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceProperties2 *pProperties)
+{
+ LIBRESOC_FROM_HANDLE(libresoc_physical_device, pdevice, physicalDevice);
+ libresoc_GetPhysicalDeviceProperties(physicalDevice, &pProperties->properties);
+ //TODO: add more stuffs when required
+}
+
+void libresoc_GetPhysicalDeviceFeatures2(
+ VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceFeatures2 *pFeatures)
+{
+ LIBRESOC_FROM_HANDLE(libresoc_physical_device, pdevice, physicalDevice);
+ libresoc_GetPhysicalDeviceFeatures(physicalDevice, &pFeatures->features);
+}
+
+void libresoc_GetPhysicalDeviceQueueFamilyProperties2(
+ VkPhysicalDevice physicalDevice,
+ uint32_t* pCount,
+ VkQueueFamilyProperties2 *pQueueFamilyProperties)
+{
+ LIBRESOC_FROM_HANDLE(libresoc_physical_device, pdevice, physicalDevice);
+ if (!pQueueFamilyProperties) {
+ libresoc_get_physical_device_queue_family_properties(pdevice, pCount, NULL);
+ return;
+ }
+ VkQueueFamilyProperties *properties[] = {
+ &pQueueFamilyProperties[0].queueFamilyProperties,
+ &pQueueFamilyProperties[1].queueFamilyProperties,
+ &pQueueFamilyProperties[2].queueFamilyProperties,
+ };
+ libresoc_get_physical_device_queue_family_properties(pdevice, pCount, properties);
+ assert(*pCount <= 3);
+}
+
+static void
+libresoc_get_memory_budget_properties(VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceMemoryBudgetPropertiesEXT *memoryBudget)
+{
+//TODO: stub
+}
+
+void libresoc_GetPhysicalDeviceMemoryProperties2(
+ VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceMemoryProperties2 *pMemoryProperties)
+{
+ libresoc_GetPhysicalDeviceMemoryProperties(physicalDevice,
+ &pMemoryProperties->memoryProperties);
+
+ VkPhysicalDeviceMemoryBudgetPropertiesEXT *memory_budget =
+ vk_find_struct(pMemoryProperties->pNext,
+ PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT);
+ if (memory_budget)
+ libresoc_get_memory_budget_properties(physicalDevice, memory_budget);
+}
+
+VkResult libresoc_CreateSemaphore(
+ VkDevice _device,
+ const VkSemaphoreCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkSemaphore* pSemaphore)
+{
+ //TODO: minimal things as of now, add more complex code as required
+ LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
+ struct libresoc_semaphore *sem = vk_alloc2(&device->vk.alloc, pAllocator,
+ sizeof(*sem), 8,
+ VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+ if (!sem)
+ return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
+
+ vk_object_base_init(&device->vk, &sem->base,
+ VK_OBJECT_TYPE_SEMAPHORE);
+
+ *pSemaphore = libresoc_semaphore_to_handle(sem);
+ return VK_SUCCESS;
+}
+
+void libresoc_GetImageMemoryRequirements(
+ VkDevice _device,
+ VkImage _image,
+ VkMemoryRequirements* pMemoryRequirements)
+{
+ LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
+ LIBRESOC_FROM_HANDLE(libresoc_image, image, _image);
+
+ pMemoryRequirements->memoryTypeBits = (1u << device->physical_device->memory_properties.memoryTypeCount) - 1;
+
+ pMemoryRequirements->size = image->size;
+ pMemoryRequirements->alignment = image->alignment;
+}
+
+void libresoc_GetImageMemoryRequirements2(
+ VkDevice device,
+ const VkImageMemoryRequirementsInfo2 *pInfo,
+ VkMemoryRequirements2 *pMemoryRequirements)
+{
+ libresoc_GetImageMemoryRequirements(device, pInfo->image,
+ &pMemoryRequirements->memoryRequirements);
+}
+
+VkResult libresoc_BindImageMemory2(VkDevice device,
+ uint32_t bindInfoCount,
+ const VkBindImageMemoryInfo *pBindInfos)
+{
+ for (uint32_t i = 0; i < bindInfoCount; ++i) {
+ LIBRESOC_FROM_HANDLE(libresoc_device_memory, mem, pBindInfos[i].memory);
+ LIBRESOC_FROM_HANDLE(libresoc_image, image, pBindInfos[i].image);
+
+ if (mem) {
+ // image->bo = mem->bo;
+ // image->offset = pBindInfos[i].memoryOffset;
+ } else {
+ // image->bo = NULL;
+ // image->offset = 0;
+ }
+ }
+ return VK_SUCCESS;
+}
+
+
+VkResult libresoc_BindImageMemory(
+ VkDevice device,
+ VkImage image,
+ VkDeviceMemory memory,
+ VkDeviceSize memoryOffset)
+{
+ const VkBindImageMemoryInfo info = {
+ .sType = VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO,
+ .image = image,
+ .memory = memory,
+ .memoryOffset = memoryOffset
+ };
+
+ return libresoc_BindImageMemory2(device, 1, &info);
+}
+
+static VkResult libresoc_queue_submit(struct libresoc_queue *queue,
+ const struct libresoc_queue_submission *submission)
+{
+ return VK_SUCCESS;
+ // struct libresoc_deferred_queue_submission *deferred = NULL;
+
+ // VkResult result = libresoc_create_deferred_submission(queue, submission, &deferred);
+ // if (result != VK_SUCCESS)
+ // return result;
+
+ // struct list_head processing_list;
+ // list_inithead(&processing_list);
+
+ // result = libresoc_queue_enqueue_submission(deferred, &processing_list);
+ // if (result != VK_SUCCESS) {
+ // /* If anything is in the list we leak. */
+ // assert(list_is_empty(&processing_list));
+ // return result;
+ // }
+ // return libresoc_process_submissions(&processing_list);
+}
+
+/* Signals fence as soon as all the work currently put on queue is done. */
+static VkResult libresoc_signal_fence(struct libresoc_queue *queue,
+ VkFence fence)
+{
+ return libresoc_queue_submit(queue, &(struct libresoc_queue_submission) {
+ .fence = fence
+ });
+}
+
+static bool libresoc_submit_has_effects(const VkSubmitInfo *info)
+{
+ return info->commandBufferCount ||
+ info->waitSemaphoreCount ||
+ info->signalSemaphoreCount;
+}
+
+VkResult libresoc_QueueSubmit(
+ VkQueue _queue,
+ uint32_t submitCount,
+ const VkSubmitInfo* pSubmits,
+ VkFence fence)
+{
+ LIBRESOC_FROM_HANDLE(libresoc_queue, queue, _queue);
+ VkResult result;
+ uint32_t fence_idx = 0;
+ bool flushed_caches = false;
+
+ if (fence != VK_NULL_HANDLE) {
+ for (uint32_t i = 0; i < submitCount; ++i)
+ if (libresoc_submit_has_effects(pSubmits + i))
+ fence_idx = i;
+ } else
+ fence_idx = UINT32_MAX;
+
+ for (uint32_t i = 0; i < submitCount; i++) {
+ if (!libresoc_submit_has_effects(pSubmits + i) && fence_idx != i)
+ continue;
+
+ VkPipelineStageFlags wait_dst_stage_mask = 0;
+ for (unsigned j = 0; j < pSubmits[i].waitSemaphoreCount; ++j) {
+ wait_dst_stage_mask |= pSubmits[i].pWaitDstStageMask[j];
+ }
+
+ const VkTimelineSemaphoreSubmitInfo *timeline_info =
+ vk_find_struct_const(pSubmits[i].pNext, TIMELINE_SEMAPHORE_SUBMIT_INFO);
+
+ result = libresoc_queue_submit(queue, &(struct libresoc_queue_submission) {
+ .cmd_buffers = pSubmits[i].pCommandBuffers,
+ .cmd_buffer_count = pSubmits[i].commandBufferCount,
+ .wait_dst_stage_mask = wait_dst_stage_mask,
+ .flush_caches = !flushed_caches,
+ .wait_semaphores = pSubmits[i].pWaitSemaphores,
+ .wait_semaphore_count = pSubmits[i].waitSemaphoreCount,
+ .signal_semaphores = pSubmits[i].pSignalSemaphores,
+ .signal_semaphore_count = pSubmits[i].signalSemaphoreCount,
+ .fence = i == fence_idx ? fence : VK_NULL_HANDLE,
+ .wait_values = timeline_info ? timeline_info->pWaitSemaphoreValues : NULL,
+ .wait_value_count = timeline_info && timeline_info->pWaitSemaphoreValues ? timeline_info->waitSemaphoreValueCount : 0,
+ .signal_values = timeline_info ? timeline_info->pSignalSemaphoreValues : NULL,
+ .signal_value_count = timeline_info && timeline_info->pSignalSemaphoreValues ? timeline_info->signalSemaphoreValueCount : 0,
+ });
+ if (result != VK_SUCCESS)
+ return result;
+
+ flushed_caches = true;
+ }
+
+ if (fence != VK_NULL_HANDLE && !submitCount) {
+ result = libresoc_signal_fence(queue, fence);
+ if (result != VK_SUCCESS)
+ return result;
+ }
+
+ return VK_SUCCESS;
+}
+
+VkResult libresoc_CreateFence(
+ VkDevice _device,
+ const VkFenceCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkFence* pFence)
+{
+ LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
+ const VkExportFenceCreateInfo *export =
+ vk_find_struct_const(pCreateInfo->pNext, EXPORT_FENCE_CREATE_INFO);
+ VkExternalFenceHandleTypeFlags handleTypes =
+ export ? export->handleTypes : 0;
+ struct libresoc_fence *fence;
+
+ fence = vk_zalloc2(&device->vk.alloc, pAllocator, sizeof(*fence), 8,
+ VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+ if (!fence)
+ return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
+
+ vk_object_base_init(&device->vk, &fence->base, VK_OBJECT_TYPE_FENCE);
+
+ // if (device->always_use_syncobj || handleTypes) {
+ // fence->permanent.kind = LIBRESOC_FENCE_SYNCOBJ;
+
+ // bool create_signaled = false;
+ // if (pCreateInfo->flags & VK_FENCE_CREATE_SIGNALED_BIT)
+ // create_signaled = true;
+
+ // int ret = device->ws->create_syncobj(device->ws, create_signaled,
+ // &fence->permanent.syncobj);
+ // if (ret) {
+ // libresoc_destroy_fence(device, pAllocator, fence);
+ // return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
+ // }
+ // } else {
+ // fence->permanent.kind = LIBRESOC_FENCE_WINSYS;
+
+ // fence->permanent.fence = device->ws->create_fence();
+ // if (!fence->permanent.fence) {
+ // vk_free2(&device->vk.alloc, pAllocator, fence);
+ // libresoc_destroy_fence(device, pAllocator, fence);
+ // return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
+ // }
+ // if (pCreateInfo->flags & VK_FENCE_CREATE_SIGNALED_BIT)
+ // device->ws->signal_fence(fence->permanent.fence);
+ // }
+
+ *pFence = libresoc_fence_to_handle(fence);
+
+ return VK_SUCCESS;
+}
+
+VkResult libresoc_MapMemory(
+ VkDevice _device,
+ VkDeviceMemory _memory,
+ VkDeviceSize offset,
+ VkDeviceSize size,
+ VkMemoryMapFlags flags,
+ void** ppData)
+{
+ LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
+ LIBRESOC_FROM_HANDLE(libresoc_device_memory, mem, _memory);
+
+ if (mem == NULL) {
+ *ppData = NULL;
+ return VK_SUCCESS;
+ }
+
+ if (mem->user_ptr)
+ *ppData = mem->user_ptr;
+ // else
+ // *ppData = device->ws->buffer_map(mem->bo);
+
+ if (*ppData) {
+ *ppData += offset;
+ return VK_SUCCESS;
+ }
+
+ return vk_error(device->instance, VK_ERROR_MEMORY_MAP_FAILED);
+}
+
+void libresoc_UnmapMemory(
+ VkDevice _device,
+ VkDeviceMemory _memory)
+{
+ LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
+ LIBRESOC_FROM_HANDLE(libresoc_device_memory, mem, _memory);
+
+ if (mem == NULL)
+ return;
+
+ // if (mem->user_ptr == NULL)
+ // device->ws->buffer_unmap(mem->bo);
+}
+
+VkResult libresoc_WaitForFences(
+ VkDevice _device,
+ uint32_t fenceCount,
+ const VkFence* pFences,
+ VkBool32 waitAll,
+ uint64_t timeout)
+{
+ //TODO: stub
+ return VK_SUCCESS;
+}
+
+VkResult libresoc_ResetFences(VkDevice _device,
+ uint32_t fenceCount,
+ const VkFence *pFences)
+{
+
+ //TODO: stub
+ return VK_SUCCESS;
+}
+
+VkResult libresoc_CreateFramebuffer(
+ VkDevice _device,
+ const VkFramebufferCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkFramebuffer* pFramebuffer)
+{
+ //TODO: stub
+ return VK_SUCCESS;