Making SWAPChain exntesions work.
[mesa.git] / src / libre-soc / vulkan / libresoc_device.c
index 229fd172a0d7819579ec68af934c2c0bd5e165b2..92a901657e9e1cd9a7a75997c6808de55a34af7b 100644 (file)
 #include <unistd.h>
 
 #include "util/debug.h"
+#include "util/driconf.h"
 #include "libresoc_private.h"
 #include "vk_util.h"
 #include "vk_alloc.h"
 
+struct libresoc_deferred_queue_submission {
+       struct libresoc_queue *queue;
+       VkCommandBuffer *cmd_buffers;
+       uint32_t cmd_buffer_count;
+
+       /* Sparse bindings that happen on a queue. */
+       VkSparseBufferMemoryBindInfo *buffer_binds;
+       uint32_t buffer_bind_count;
+       VkSparseImageOpaqueMemoryBindInfo *image_opaque_binds;
+       uint32_t image_opaque_bind_count;
+
+       bool flush_caches;
+       VkShaderStageFlags wait_dst_stage_mask;
+       struct libresoc_semaphore_part **wait_semaphores;
+       uint32_t wait_semaphore_count;
+       struct libresoc_semaphore_part **signal_semaphores;
+       uint32_t signal_semaphore_count;
+       VkFence fence;
+
+       uint64_t *wait_values;
+       uint64_t *signal_values;
+
+       struct libresoc_semaphore_part *temporary_semaphore_parts;
+       uint32_t temporary_semaphore_part_count;
+
+       struct list_head queue_pending_list;
+       uint32_t submission_wait_count;
+       struct libresoc_timeline_waiter *wait_nodes;
+
+       struct list_head processing_list;
+};
+
+struct libresoc_queue_submission {
+       const VkCommandBuffer *cmd_buffers;
+       uint32_t cmd_buffer_count;
+
+       /* Sparse bindings that happen on a queue. */
+       const VkSparseBufferMemoryBindInfo *buffer_binds;
+       uint32_t buffer_bind_count;
+       const VkSparseImageOpaqueMemoryBindInfo *image_opaque_binds;
+       uint32_t image_opaque_bind_count;
+
+       bool flush_caches;
+       VkPipelineStageFlags wait_dst_stage_mask;
+       const VkSemaphore *wait_semaphores;
+       uint32_t wait_semaphore_count;
+       const VkSemaphore *signal_semaphores;
+       uint32_t signal_semaphore_count;
+       VkFence fence;
+
+       const uint64_t *wait_values;
+       uint32_t wait_value_count;
+       const uint64_t *signal_values;
+       uint32_t signal_value_count;
+};
+
+void
+libresoc_free_memory(struct libresoc_device *device,
+                const VkAllocationCallbacks* pAllocator,
+                struct libresoc_device_memory *mem)
+{
+       if (mem == NULL)
+               return;
+
+       vk_object_base_finish(&mem->base);
+       vk_free2(&device->vk.alloc, pAllocator, mem);
+}
+
+static VkResult libresoc_alloc_memory(struct libresoc_device *device,
+                                 const VkMemoryAllocateInfo*     pAllocateInfo,
+                                 const VkAllocationCallbacks*    pAllocator,
+                                 VkDeviceMemory*                 pMem)
+{
+       struct libresoc_device_memory *mem;
+       VkResult result;
+       uint32_t flags = 0;
+
+       assert(pAllocateInfo->sType == VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO);
+
+       const VkImportMemoryFdInfoKHR *import_info =
+               vk_find_struct_const(pAllocateInfo->pNext, IMPORT_MEMORY_FD_INFO_KHR);
+       const VkMemoryDedicatedAllocateInfo *dedicate_info =
+               vk_find_struct_const(pAllocateInfo->pNext, MEMORY_DEDICATED_ALLOCATE_INFO);
+       const VkExportMemoryAllocateInfo *export_info =
+               vk_find_struct_const(pAllocateInfo->pNext, EXPORT_MEMORY_ALLOCATE_INFO);
+       const VkImportMemoryHostPointerInfoEXT *host_ptr_info =
+               vk_find_struct_const(pAllocateInfo->pNext, IMPORT_MEMORY_HOST_POINTER_INFO_EXT);
+
+       const struct wsi_memory_allocate_info *wsi_info =
+               vk_find_struct_const(pAllocateInfo->pNext, WSI_MEMORY_ALLOCATE_INFO_MESA);
+
+
+       mem = vk_zalloc2(&device->vk.alloc, pAllocator, sizeof(*mem), 8,
+                         VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+       if (mem == NULL)
+               return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
+
+       vk_object_base_init(&device->vk, &mem->base,
+                           VK_OBJECT_TYPE_DEVICE_MEMORY);
+
+       if (dedicate_info) {
+               mem->image = libresoc_image_from_handle(dedicate_info->image);
+               //mem->buffer = libresoc_buffer_from_handle(dedicate_info->buffer);
+       } else {
+               mem->image = NULL;
+               //mem->buffer = NULL;
+       }
+
+       // float priority_float = 0.5;
+       // const struct VkMemoryPriorityAllocateInfoEXT *priority_ext =
+       //      vk_find_struct_const(pAllocateInfo->pNext,
+       //                           MEMORY_PRIORITY_ALLOCATE_INFO_EXT);
+       // if (priority_ext)
+       //      priority_float = priority_ext->priority;
+
+       // unsigned priority = MIN2(LIBRESOC_BO_PRIORITY_APPLICATION_MAX - 1,
+       //                          (int)(priority_float * LIBRESOC_BO_PRIORITY_APPLICATION_MAX));
+
+       mem->user_ptr = NULL;
+       //mem->bo = NULL;
+
+
+       if (import_info) {
+               assert(import_info->handleType ==
+                      VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT ||
+                      import_info->handleType ==
+                      VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
+               // mem->bo = device->ws->buffer_from_fd(device->ws, import_info->fd,
+               //                                   priority, NULL);
+               // if (!mem->bo) {
+               //      result = VK_ERROR_INVALID_EXTERNAL_HANDLE;
+               //      goto fail;
+               // } else {
+               //      close(import_info->fd);
+               // }
+
+               // if (mem->image && mem->image->plane_count == 1 &&
+               //     !vk_format_is_depth_or_stencil(mem->image->vk_format)) {
+               //      struct radeon_bo_metadata metadata;
+               //      device->ws->buffer_get_metadata(mem->bo, &metadata);
+
+               //      struct libresoc_image_create_info create_info = {
+               //              .no_metadata_planes = true,
+               //              .bo_metadata = &metadata
+               //      };
+
+               //      /* This gives a basic ability to import radeonsi images
+               //       * that don't have DCC. This is not guaranteed by any
+               //       * spec and can be removed after we support modifiers. */
+               //      result = libresoc_image_create_layout(device, create_info, mem->image);
+               //      if (result != VK_SUCCESS) {
+               //              device->ws->buffer_destroy(mem->bo);
+               //              goto fail;
+               //      }
+               // }
+       } else if (host_ptr_info) {
+               // assert(host_ptr_info->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT);
+               // mem->bo = device->ws->buffer_from_ptr(device->ws, host_ptr_info->pHostPointer,
+               //                                       pAllocateInfo->allocationSize,
+               //                                       priority);
+               // if (!mem->bo) {
+               //      result = VK_ERROR_INVALID_EXTERNAL_HANDLE;
+               //      goto fail;
+               // } else {
+               //      mem->user_ptr = host_ptr_info->pHostPointer;
+               // }
+       } else {
+               uint64_t alloc_size = align_u64(pAllocateInfo->allocationSize, 4096);
+               uint32_t heap_index;
+
+               heap_index = device->physical_device->memory_properties.memoryTypes[pAllocateInfo->memoryTypeIndex].heapIndex;
+               // domain = device->physical_device->memory_domains[pAllocateInfo->memoryTypeIndex];
+               // flags |= device->physical_device->memory_flags[pAllocateInfo->memoryTypeIndex];
+
+               // if (!dedicate_info && !import_info && (!export_info || !export_info->handleTypes)) {
+               //      flags |= RADEON_FLAG_NO_INTERPROCESS_SHARING;
+               //      if (device->use_global_bo_list) {
+               //              flags |= RADEON_FLAG_PREFER_LOCAL_BO;
+               //      }
+               // }
+
+               if (device->overallocation_disallowed) {
+                       uint64_t total_size =
+                               device->physical_device->memory_properties.memoryHeaps[heap_index].size;
+
+                       mtx_lock(&device->overallocation_mutex);
+                       if (device->allocated_memory_size[heap_index] + alloc_size > total_size) {
+                               mtx_unlock(&device->overallocation_mutex);
+                               result = VK_ERROR_OUT_OF_DEVICE_MEMORY;
+                               goto fail;
+                       }
+                       device->allocated_memory_size[heap_index] += alloc_size;
+                       mtx_unlock(&device->overallocation_mutex);
+               }
+
+               // mem->bo = device->ws->buffer_create(device->ws, alloc_size, device->physical_device->rad_info.max_alignment,
+               //                                     domain, flags, priority);
+
+               // if (!mem->bo) {
+               //      if (device->overallocation_disallowed) {
+               //              mtx_lock(&device->overallocation_mutex);
+               //              device->allocated_memory_size[heap_index] -= alloc_size;
+               //              mtx_unlock(&device->overallocation_mutex);
+               //      }
+               //      result = VK_ERROR_OUT_OF_DEVICE_MEMORY;
+               //      goto fail;
+               // }
+
+               mem->heap_index = heap_index;
+               mem->alloc_size = alloc_size;
+       }
+
+       // if (!wsi_info) {
+       //      result = libresoc_bo_list_add(device, mem->bo);
+       //      if (result != VK_SUCCESS)
+       //              goto fail;
+       // }
+
+       *pMem = libresoc_device_memory_to_handle(mem);
+
+       return VK_SUCCESS;
+
+fail:
+       libresoc_free_memory(device, pAllocator,mem);
+
+       return result;
+}
+
+VkResult libresoc_AllocateMemory(
+       VkDevice                                    _device,
+       const VkMemoryAllocateInfo*                 pAllocateInfo,
+       const VkAllocationCallbacks*                pAllocator,
+       VkDeviceMemory*                             pMem)
+{
+       LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
+       return libresoc_alloc_memory(device, pAllocateInfo, pAllocator, pMem);
+}
+
+void libresoc_FreeMemory(
+       VkDevice                                    _device,
+       VkDeviceMemory                              _mem,
+       const VkAllocationCallbacks*                pAllocator)
+{
+       LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
+       LIBRESOC_FROM_HANDLE(libresoc_device_memory, mem, _mem);
+
+       libresoc_free_memory(device, pAllocator, mem);
+}
+static VkResult
+libresoc_create_pthread_cond(pthread_cond_t *cond)
+{
+       pthread_condattr_t condattr;
+       if (pthread_condattr_init(&condattr)) {
+               return VK_ERROR_INITIALIZATION_FAILED;
+       }
+
+       if (pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC)) {
+               pthread_condattr_destroy(&condattr);
+               return VK_ERROR_INITIALIZATION_FAILED;
+       }
+       if (pthread_cond_init(cond, &condattr)) {
+               pthread_condattr_destroy(&condattr);
+               return VK_ERROR_INITIALIZATION_FAILED;
+       }
+       pthread_condattr_destroy(&condattr);
+       return VK_SUCCESS;
+}
+
 VkResult
 libresoc_EnumerateInstanceExtensionProperties(const char *pLayerName,
                                           uint32_t *pPropertyCount,
@@ -119,6 +388,33 @@ libresoc_get_debug_option_name(int id)
        assert(id < ARRAY_SIZE(libresoc_debug_options) - 1);
        return libresoc_debug_options[id].string;
 }
+
+static const char libresoc_dri_options_xml[] =
+DRI_CONF_BEGIN
+       DRI_CONF_SECTION_PERFORMANCE
+               DRI_CONF_ADAPTIVE_SYNC("true")
+               DRI_CONF_VK_X11_OVERRIDE_MIN_IMAGE_COUNT(0)
+               DRI_CONF_VK_X11_STRICT_IMAGE_COUNT("false")
+               DRI_CONF_VK_X11_ENSURE_MIN_IMAGE_COUNT("false")
+       DRI_CONF_SECTION_END
+
+       DRI_CONF_SECTION_DEBUG
+               DRI_CONF_VK_WSI_FORCE_BGRA8_UNORM_FIRST("false")
+       DRI_CONF_SECTION_END
+DRI_CONF_END;
+
+static void  libresoc_init_dri_options(struct libresoc_instance *instance)
+{
+       driParseOptionInfo(&instance->available_dri_options, libresoc_dri_options_xml);
+       driParseConfigFiles(&instance->dri_options,
+                           &instance->available_dri_options,
+                           0, "libresoc", NULL,
+                           instance->app_info.app_name,
+                           instance->app_info.app_version,
+                           instance->engineName,
+                           instance->engineVersion);
+}
+
 VkResult
 libresoc_CreateInstance(const VkInstanceCreateInfo *pCreateInfo,
                     const VkAllocationCallbacks *pAllocator,
@@ -208,6 +504,7 @@ libresoc_CreateInstance(const VkInstanceCreateInfo *pCreateInfo,
        }
        instance->physical_devices_enumerated = false;
        list_inithead(&instance->physical_devices);
+       libresoc_init_dri_options(instance);
        *pInstance = libresoc_instance_to_handle(instance);
 
        return VK_SUCCESS;
@@ -223,11 +520,57 @@ libresoc_DestroyInstance(VkInstance _instance,
    /* FIXME: stub */
 }
 
+static void
+libresoc_physical_device_init_mem_types(struct libresoc_physical_device *device)
+{
+       uint64_t visible_vram_size = 65536; //TODO: some dummy value
+       uint64_t vram_size = 65536; //TODO: some dummy value
+       int vram_index = -1, visible_vram_index = -1;
+       device->memory_properties.memoryHeapCount = 0;
+       if (vram_size > 0) {
+               vram_index = device->memory_properties.memoryHeapCount++;
+               device->memory_properties.memoryHeaps[vram_index] = (VkMemoryHeap) {
+                       .size = vram_size,
+                       .flags = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT,
+               };
+       }
+
+       if (visible_vram_size) {
+               visible_vram_index = device->memory_properties.memoryHeapCount++;
+               device->memory_properties.memoryHeaps[visible_vram_index] = (VkMemoryHeap) {
+                       .size = visible_vram_size,
+                       .flags = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT,
+               };
+       }
+       unsigned type_count = 0;
+
+       if (vram_index >= 0 || visible_vram_index >= 0) {
+               device->memory_properties.memoryTypes[type_count++] = (VkMemoryType) {
+                       .propertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
+                       .heapIndex = vram_index >= 0 ? vram_index : visible_vram_index,
+               };
+       }
+
+       if (visible_vram_index >= 0) {
+               device->memory_properties.memoryTypes[type_count++] = (VkMemoryType) {
+                       .propertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
+                       VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
+                       VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
+                       .heapIndex = visible_vram_index,
+               };
+       }
+
+       device->memory_properties.memoryTypeCount = type_count;
+
+
+}
 static VkResult
 libresoc_physical_device_try_create(struct libresoc_instance *instance,
                                struct libresoc_physical_device **device_out)
 {
        VkResult result;
+       int fd = -1;
+       int master_fd = -1;
 
        struct libresoc_physical_device *device =
                vk_zalloc2(&instance->alloc, NULL, sizeof(*device), 8,
@@ -240,10 +583,20 @@ libresoc_physical_device_try_create(struct libresoc_instance *instance,
        device->_loader_data.loaderMagic = ICD_LOADER_MAGIC;
        device->instance = instance;
 
+       device->master_fd = master_fd;
+       device->local_fd = fd;
+       libresoc_physical_device_init_mem_types(device);
+
+       libresoc_physical_device_get_supported_extensions(device,
+                                                     &device->supported_extensions);
+       result = libresoc_init_wsi(device);
+       if (result != VK_SUCCESS) {
+               return result;
+       }
        snprintf(device->name, sizeof(device->name),
                 "LIBRE-SOC DEVICE");
        *device_out = device;
-
+//TODO: incase of failures need to deallocate and cleanup various allocation properly.
        return VK_SUCCESS;
 
 }
@@ -502,7 +855,7 @@ libresoc_GetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice,
                .apiVersion = libresoc_physical_device_api_version(pdevice),
                .driverVersion = vk_get_driver_version(),
                .vendorID = 1, //TODO: some dummy value
-               .deviceID = 1, //TODO: dome dummay value
+               .deviceID = 1, //TODO: dome dummy value
                .deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU,
                .limits = limits,
                .sparseProperties = {0},
@@ -574,36 +927,39 @@ libresoc_GetPhysicalDeviceMemoryProperties(VkPhysicalDevice physicalDevice,
        if (getenv("LIBRESOC_TRACE")) {
                fprintf(stderr, "GetPhysicalDEviceMemoryProperties called. \n");
        }
-   /* FIXME: stub */
-}
+       LIBRESOC_FROM_HANDLE(libresoc_physical_device, physical_device, physicalDevice);
 
-void
-libresoc_GetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties *pFormatProperties) {
-       if (getenv("LIBRESOC_TRACE")) {
-               fprintf(stderr, "GetPhysicalDeviceFormatProperties called. \n");
-       }
+       *pMemoryProperties = physical_device->memory_properties;
    /* FIXME: stub */
 }
 
-VkResult
-      libresoc_GetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkImageFormatProperties* pImageFormatProperties)
-{
-       if (getenv("LIBRESOC_TRACE")) {
-               fprintf(stderr, "GetPhysicalDEviceImageFormatProperties called. \n");
-       }
-      
-   /* FIXME: stub */
-   return VK_SUCCESS;
-}
-      void 
-      libresoc_GetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkSampleCountFlagBits samples, VkImageUsageFlags usage, VkImageTiling tiling, uint32_t* pPropertyCount, VkSparseImageFormatProperties* pProperties)
-      {
-       if (getenv("LIBRESOC_TRACE")) {
-               fprintf(stderr, "GetPhysicalDeviceSparseImageFormatProperties called. \n");
-       }
-   /* FIXME: stub */
-      }
+//void
+//libresoc_GetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties *pFormatProperties) {
+// 
+//     if (getenv("LIBRESOC_TRACE")) {
+//             fprintf(stderr, "GetPhysicalDeviceFormatProperties called. \n");
+//     }
+//   /* FIXME: stub */
+//}
+
+//VkResult
+//      libresoc_GetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkImageFormatProperties* pImageFormatProperties)
+//{
+//     if (getenv("LIBRESOC_TRACE")) {
+//             fprintf(stderr, "GetPhysicalDEviceImageFormatProperties called. \n");
+//     }
+//      
+//   /* FIXME: stub */
+//   return VK_SUCCESS;
+//}
+//      void 
+//      libresoc_GetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkSampleCountFlagBits samples, VkImageUsageFlags usage, VkImageTiling tiling, uint32_t* pPropertyCount, VkSparseImageFormatProperties* pProperties)
+//      {
+//     if (getenv("LIBRESOC_TRACE")) {
+//             fprintf(stderr, "GetPhysicalDeviceSparseImageFormatProperties called. \n");
+//     }
+//   /* FIXME: stub */
+//      }
 PFN_vkVoidFunction
 libresoc_GetInstanceProcAddr(VkInstance _instance,
                          const char *pName)
@@ -773,27 +1129,6 @@ libresoc_device_init_dispatch(struct libresoc_device *device)
        }
 }
 
-/*
-static VkResult
-libresoc_create_pthread_cond(pthread_cond_t *cond)
-{
-       pthread_condattr_t condattr;
-       if (pthread_condattr_init(&condattr)) {
-               return VK_ERROR_INITIALIZATION_FAILED;
-       }
-
-       if (pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC)) {
-               pthread_condattr_destroy(&condattr);
-               return VK_ERROR_INITIALIZATION_FAILED;
-       }
-       if (pthread_cond_init(cond, &condattr)) {
-               pthread_condattr_destroy(&condattr);
-               return VK_ERROR_INITIALIZATION_FAILED;
-       }
-       pthread_condattr_destroy(&condattr);
-       return VK_SUCCESS;
-}
-*/
 static VkResult
 check_physical_device_features(VkPhysicalDevice physicalDevice,
                               const VkPhysicalDeviceFeatures *features)
@@ -831,6 +1166,16 @@ libresoc_queue_init(struct libresoc_device *device, struct libresoc_queue *queue
        queue->queue_family_index = queue_family_index;
        queue->queue_idx = idx;
        queue->flags = flags;
+       list_inithead(&queue->pending_submissions);
+       pthread_mutex_init(&queue->pending_mutex, NULL);
+
+       pthread_mutex_init(&queue->thread_mutex, NULL);
+       //queue->thread_submission = NULL;
+       queue->thread_running = queue->thread_exit = false;
+       VkResult result = libresoc_create_pthread_cond(&queue->thread_cond);
+       if (result != VK_SUCCESS)
+               return vk_error(device->instance, result);
+
        return VK_SUCCESS;
 }
 
@@ -1033,3 +1378,352 @@ VkResult libresoc_DeviceWaitIdle(
        }
        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;
+}