Making SWAPChain exntesions work.
authorVivek Pandya <vivekvpandya@gmail.com>
Sat, 5 Sep 2020 11:48:28 +0000 (17:18 +0530)
committerVivek Pandya <vivekvpandya@gmail.com>
Sat, 5 Sep 2020 11:50:32 +0000 (17:20 +0530)
There is lots of commented code.

src/libre-soc/vulkan/libresoc_cmd_buffer.c [new file with mode: 0644]
src/libre-soc/vulkan/libresoc_device.c
src/libre-soc/vulkan/libresoc_extensions.py
src/libre-soc/vulkan/libresoc_formats.c [new file with mode: 0644]
src/libre-soc/vulkan/libresoc_image.c [new file with mode: 0644]
src/libre-soc/vulkan/libresoc_meta_clear.c [new file with mode: 0644]
src/libre-soc/vulkan/libresoc_pipeline_cache.c [new file with mode: 0644]
src/libre-soc/vulkan/libresoc_private.h
src/libre-soc/vulkan/libresoc_wsi.c [new file with mode: 0644]
src/libre-soc/vulkan/libresoc_wsi_x11.c [new file with mode: 0644]
src/libre-soc/vulkan/meson.build

diff --git a/src/libre-soc/vulkan/libresoc_cmd_buffer.c b/src/libre-soc/vulkan/libresoc_cmd_buffer.c
new file mode 100644 (file)
index 0000000..a865f5b
--- /dev/null
@@ -0,0 +1,306 @@
+
+/*
+ * Copyright © 2016 Red Hat.
+ * Copyright © 2016 Bas Nieuwenhuizen
+ *
+ * based in part on anv driver which is:
+ * Copyright © 2015 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "libresoc_private.h"
+
+void libresoc_FreeCommandBuffers(
+       VkDevice device,
+       VkCommandPool commandPool,
+       uint32_t commandBufferCount,
+       const VkCommandBuffer *pCommandBuffers)
+{
+       //TODO: stub
+}
+
+VkResult libresoc_CreateCommandPool(
+       VkDevice                                    _device,
+       const VkCommandPoolCreateInfo*              pCreateInfo,
+       const VkAllocationCallbacks*                pAllocator,
+       VkCommandPool*                              pCmdPool)
+{
+       LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
+       struct libresoc_cmd_pool *pool;
+
+       pool = vk_alloc2(&device->vk.alloc, pAllocator, sizeof(*pool), 8,
+                          VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+       if (pool == NULL)
+               return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
+
+       vk_object_base_init(&device->vk, &pool->base,
+                           VK_OBJECT_TYPE_COMMAND_POOL);
+
+       if (pAllocator)
+               pool->alloc = *pAllocator;
+       else
+               pool->alloc = device->vk.alloc;
+
+       list_inithead(&pool->cmd_buffers);
+       list_inithead(&pool->free_cmd_buffers);
+
+       pool->queue_family_index = pCreateInfo->queueFamilyIndex;
+
+       *pCmdPool = libresoc_cmd_pool_to_handle(pool);
+
+       return VK_SUCCESS;
+
+}
+
+void libresoc_DestroyCommandPool(
+       VkDevice                                    _device,
+       VkCommandPool                               commandPool,
+       const VkAllocationCallbacks*                pAllocator)
+{
+       LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
+       LIBRESOC_FROM_HANDLE(libresoc_cmd_pool, pool, commandPool);
+
+       if (!pool)
+               return;
+
+       // list_for_each_entry_safe(struct libresoc_cmd_buffer, cmd_buffer,
+       //                       &pool->cmd_buffers, pool_link) {
+       //      libresoc_destroy_cmd_buffer(cmd_buffer);
+       // }
+
+       // list_for_each_entry_safe(struct libresoc_cmd_buffer, cmd_buffer,
+       //                       &pool->free_cmd_buffers, pool_link) {
+       //      libresoc_destroy_cmd_buffer(cmd_buffer);
+       // }
+
+       vk_object_base_finish(&pool->base);
+       vk_free2(&device->vk.alloc, pAllocator, pool);
+}
+
+static VkResult libresoc_create_cmd_buffer(
+       struct libresoc_device *                         device,
+       struct libresoc_cmd_pool *                       pool,
+       VkCommandBufferLevel                        level,
+       VkCommandBuffer*                            pCommandBuffer)
+{
+       struct libresoc_cmd_buffer *cmd_buffer;
+       unsigned ring;
+       cmd_buffer = vk_zalloc(&pool->alloc, sizeof(*cmd_buffer), 8,
+                              VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+       if (cmd_buffer == NULL)
+               return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
+
+       vk_object_base_init(&device->vk, &cmd_buffer->base,
+                           VK_OBJECT_TYPE_COMMAND_BUFFER);
+
+       cmd_buffer->device = device;
+       cmd_buffer->pool = pool;
+       cmd_buffer->level = level;
+
+       list_addtail(&cmd_buffer->pool_link, &pool->cmd_buffers);
+       cmd_buffer->queue_family_index = pool->queue_family_index;
+
+       // ring = libresoc_queue_family_to_ring(cmd_buffer->queue_family_index);
+
+       // cmd_buffer->cs = device->ws->cs_create(device->ws, ring);
+       // if (!cmd_buffer->cs) {
+       //      libresoc_destroy_cmd_buffer(cmd_buffer);
+       //      return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
+       // }
+
+       *pCommandBuffer = libresoc_cmd_buffer_to_handle(cmd_buffer);
+
+       list_inithead(&cmd_buffer->upload.list);
+
+       return VK_SUCCESS;
+}
+
+VkResult libresoc_AllocateCommandBuffers(
+       VkDevice _device,
+       const VkCommandBufferAllocateInfo *pAllocateInfo,
+       VkCommandBuffer *pCommandBuffers)
+{
+       LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
+       LIBRESOC_FROM_HANDLE(libresoc_cmd_pool, pool, pAllocateInfo->commandPool);
+
+       VkResult result = VK_SUCCESS;
+       uint32_t i;
+
+       for (i = 0; i < pAllocateInfo->commandBufferCount; i++) {
+
+               if (!list_is_empty(&pool->free_cmd_buffers)) {
+                       struct libresoc_cmd_buffer *cmd_buffer = list_first_entry(&pool->free_cmd_buffers, struct libresoc_cmd_buffer, pool_link);
+
+                       list_del(&cmd_buffer->pool_link);
+                       list_addtail(&cmd_buffer->pool_link, &pool->cmd_buffers);
+
+                       //result = libresoc_reset_cmd_buffer(cmd_buffer);
+                       cmd_buffer->level = pAllocateInfo->level;
+
+                       pCommandBuffers[i] = libresoc_cmd_buffer_to_handle(cmd_buffer);
+               } else {
+                       result = libresoc_create_cmd_buffer(device, pool, pAllocateInfo->level,
+                                                       &pCommandBuffers[i]);
+               }
+               if (result != VK_SUCCESS)
+                       break;
+       }
+
+       // if (result != VK_SUCCESS) {
+       //      libresoc_FreeCommandBuffers(_device, pAllocateInfo->commandPool,
+       //                              i, pCommandBuffers);
+
+       //      /* From the Vulkan 1.0.66 spec:
+       //       *
+       //       * "vkAllocateCommandBuffers can be used to create multiple
+       //       *  command buffers. If the creation of any of those command
+       //       *  buffers fails, the implementation must destroy all
+       //       *  successfully created command buffer objects from this
+       //       *  command, set all entries of the pCommandBuffers array to
+       //       *  NULL and return the error."
+       //       */
+       //      memset(pCommandBuffers, 0,
+       //             sizeof(*pCommandBuffers) * pAllocateInfo->commandBufferCount);
+       // }
+
+       return result;
+}
+
+VkResult libresoc_BeginCommandBuffer(
+       VkCommandBuffer commandBuffer,
+       const VkCommandBufferBeginInfo *pBeginInfo)
+{
+       LIBRESOC_FROM_HANDLE(libresoc_cmd_buffer, cmd_buffer, commandBuffer);
+       VkResult result = VK_SUCCESS;
+
+
+       // memset(&cmd_buffer->state, 0, sizeof(cmd_buffer->state));
+       // cmd_buffer->state.last_primitive_reset_en = -1;
+       // cmd_buffer->state.last_index_type = -1;
+       // cmd_buffer->state.last_num_instances = -1;
+       // cmd_buffer->state.last_vertex_offset = -1;
+       // cmd_buffer->state.last_first_instance = -1;
+       // cmd_buffer->state.predication_type = -1;
+       // cmd_buffer->state.last_sx_ps_downconvert = -1;
+       // cmd_buffer->state.last_sx_blend_opt_epsilon = -1;
+       // cmd_buffer->state.last_sx_blend_opt_control = -1;
+       cmd_buffer->usage_flags = pBeginInfo->flags;
+
+       // if (cmd_buffer->level == VK_COMMAND_BUFFER_LEVEL_SECONDARY &&
+       //     (pBeginInfo->flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT)) {
+       //      assert(pBeginInfo->pInheritanceInfo);
+       //      cmd_buffer->state.framebuffer = libresoc_framebuffer_from_handle(pBeginInfo->pInheritanceInfo->framebuffer);
+       //      cmd_buffer->state.pass = libresoc_render_pass_from_handle(pBeginInfo->pInheritanceInfo->renderPass);
+
+       //      struct libresoc_subpass *subpass =
+       //              &cmd_buffer->state.pass->subpasses[pBeginInfo->pInheritanceInfo->subpass];
+
+       //      if (cmd_buffer->state.framebuffer) {
+       //              result = libresoc_cmd_state_setup_attachments(cmd_buffer, cmd_buffer->state.pass, NULL);
+       //              if (result != VK_SUCCESS)
+       //                      return result;
+       //      }
+
+       //      cmd_buffer->state.inherited_pipeline_statistics =
+       //              pBeginInfo->pInheritanceInfo->pipelineStatistics;
+
+       //      libresoc_cmd_buffer_set_subpass(cmd_buffer, subpass);
+       // }
+
+       // if (unlikely(cmd_buffer->device->trace_bo))
+       //      libresoc_cmd_buffer_trace_emit(cmd_buffer);
+
+//     libresoc_describe_begin_cmd_buffer(cmd_buffer);
+
+       //cmd_buffer->status = LIBRESOC_CMD_BUFFER_STATUS_RECORDING;
+
+       return result;
+}
+
+void libresoc_CmdPipelineBarrier(
+       VkCommandBuffer                             commandBuffer,
+       VkPipelineStageFlags                        srcStageMask,
+       VkPipelineStageFlags                        destStageMask,
+       VkBool32                                    byRegion,
+       uint32_t                                    memoryBarrierCount,
+       const VkMemoryBarrier*                      pMemoryBarriers,
+       uint32_t                                    bufferMemoryBarrierCount,
+       const VkBufferMemoryBarrier*                pBufferMemoryBarriers,
+       uint32_t                                    imageMemoryBarrierCount,
+       const VkImageMemoryBarrier*                 pImageMemoryBarriers)
+{
+       // LIBRESOC_FROM_HANDLE(libresoc_cmd_buffer, cmd_buffer, commandBuffer);
+       // struct libresoc_barrier_info info;
+
+       // info.reason = RGP_BARRIER_EXTERNAL_CMD_PIPELINE_BARRIER;
+       // info.eventCount = 0;
+       // info.pEvents = NULL;
+       // info.srcStageMask = srcStageMask;
+       // info.dstStageMask = destStageMask;
+
+       // libresoc_barrier(cmd_buffer, memoryBarrierCount, pMemoryBarriers,
+       //           bufferMemoryBarrierCount, pBufferMemoryBarriers,
+       //           imageMemoryBarrierCount, pImageMemoryBarriers, &info);
+}
+
+VkResult libresoc_EndCommandBuffer(
+       VkCommandBuffer                             commandBuffer)
+{
+
+       LIBRESOC_FROM_HANDLE(libresoc_cmd_buffer, cmd_buffer, commandBuffer);
+
+       // if (cmd_buffer->queue_family_index != LIBRESOC_QUEUE_TRANSFER) {
+       //      if (cmd_buffer->device->physical_device->rad_info.chip_class == GFX6)
+       //              cmd_buffer->state.flush_bits |= LIBRESOC_CMD_FLAG_CS_PARTIAL_FLUSH | LIBRESOC_CMD_FLAG_PS_PARTIAL_FLUSH | LIBRESOC_CMD_FLAG_WB_L2;
+
+       //      /* Make sure to sync all pending active queries at the end of
+       //       * command buffer.
+       //       */
+       //      cmd_buffer->state.flush_bits |= cmd_buffer->active_query_flush_bits;
+
+       //      /* Since NGG streamout uses GDS, we need to make GDS idle when
+       //       * we leave the IB, otherwise another process might overwrite
+       //       * it while our shaders are busy.
+       //       */
+       //      if (cmd_buffer->gds_needed)
+       //              cmd_buffer->state.flush_bits |= LIBRESOC_CMD_FLAG_PS_PARTIAL_FLUSH;
+
+       //      si_emit_cache_flush(cmd_buffer);
+       // }
+
+       // /* Make sure CP DMA is idle at the end of IBs because the kernel
+       //  * doesn't wait for it.
+       //  */
+       // si_cp_dma_wait_for_idle(cmd_buffer);
+
+       // libresoc_describe_end_cmd_buffer(cmd_buffer);
+
+       // vk_free(&cmd_buffer->pool->alloc, cmd_buffer->state.attachments);
+       // vk_free(&cmd_buffer->pool->alloc, cmd_buffer->state.subpass_sample_locs);
+
+       // VkResult result = cmd_buffer->device->ws->cs_finalize(cmd_buffer->cs);
+       // if (result != VK_SUCCESS)
+       //      return vk_error(cmd_buffer->device->instance, result);
+
+       // cmd_buffer->status = LIBRESOC_CMD_BUFFER_STATUS_EXECUTABLE;
+
+       return cmd_buffer->record_result;
+}
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;
+}
index 3d83d41ed4c1890eeb83c53bcc6b8f4f943e2b0b..17e5265e46196edce5cc94503ee4c20e06d50aec 100644 (file)
@@ -53,16 +53,29 @@ API_PATCH_VERSION = 102
 # available.
 API_VERSIONS = [
     ApiVersion('1.0',   True),
+    ApiVersion('1.1',   False),
 
-    # FIXME: for now we only support 1.0. We maintain this support from anv just in case in
-    # the future we support more that one version supported.
-    # ApiVersion('1.1',   <condition> ),
 ]
 
 MAX_API_VERSION = None # Computed later
 
 EXTENSIONS = [
-    #FIXME: for now we don't support additional extensions beyond 1.0. Revisit later
+        #Extension('VK_KHR_display',                          23, 'VK_USE_PLATFORM_DISPLAY_KHR'),
+        #Extension('VK_KHR_external_memory',                   1, True),
+        #TODO: enabling following extension creates compilation problem
+        #Extension('VK_KHR_external_memory_capabilities',      1, True),
+        #Extension('VK_KHR_external_memory_fd',                1, True),
+        Extension('VK_KHR_get_physical_device_properties2',   1, True),
+        #Extension('VK_KHR_get_surface_capabilities2',         1, 'LIBRESOC_HAS_SURFACE'),
+       Extension('VK_KHR_surface',                          25, 'LIBRESOC_HAS_SURFACE'),
+       Extension('VK_KHR_swapchain',                        68, 'LIBRESOC_HAS_SURFACE'),
+       # Extension('VK_KHR_wayland_surface',                   6, 'VK_USE_PLATFORM_WAYLAND_KHR'),
+       Extension('VK_KHR_xcb_surface',                       6, 'VK_USE_PLATFORM_XCB_KHR'),
+       Extension('VK_KHR_xlib_surface',                      6, 'VK_USE_PLATFORM_XLIB_KHR'),
+       # Extension('VK_EXT_debug_report',                      9, True),
+       # Extension('VK_EXT_external_memory_dma_buf',           1, True),
+       # Extension('VK_EXT_image_drm_format_modifier',         1, False),
+
 ]
 
 # Sort the extension list the way we expect: KHR, then EXT, then vendors
diff --git a/src/libre-soc/vulkan/libresoc_formats.c b/src/libre-soc/vulkan/libresoc_formats.c
new file mode 100644 (file)
index 0000000..4c55016
--- /dev/null
@@ -0,0 +1,1355 @@
+/*
+ * Copyright © 2016 Red Hat.
+ * Copyright © 2016 Bas Nieuwenhuizen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "libresoc_private.h"
+
+#include "vk_format.h"
+
+#include "vk_util.h"
+
+#include "util/u_half.h"
+#include "util/format_srgb.h"
+#include "util/format_r11g11b10f.h"
+
+//uint32_t libresoc_translate_buffer_dataformat(const struct vk_format_description *desc,
+//                                       int first_non_void)
+//{
+//     unsigned type;
+//     int i;
+//
+//     assert(desc->layout != VK_FORMAT_LAYOUT_MULTIPLANE);
+//
+//     if (desc->format == VK_FORMAT_B10G11R11_UFLOAT_PACK32)
+//             return V_008F0C_BUF_DATA_FORMAT_10_11_11;
+//
+//     if (first_non_void < 0)
+//             return V_008F0C_BUF_DATA_FORMAT_INVALID;
+//     type = desc->channel[first_non_void].type;
+//
+//     if (type == VK_FORMAT_TYPE_FIXED)
+//             return V_008F0C_BUF_DATA_FORMAT_INVALID;
+//     if (desc->nr_channels == 4 &&
+//         desc->channel[0].size == 10 &&
+//         desc->channel[1].size == 10 &&
+//         desc->channel[2].size == 10 &&
+//         desc->channel[3].size == 2)
+//             return V_008F0C_BUF_DATA_FORMAT_2_10_10_10;
+//
+//     /* See whether the components are of the same size. */
+//     for (i = 0; i < desc->nr_channels; i++) {
+//             if (desc->channel[first_non_void].size != desc->channel[i].size)
+//                     return V_008F0C_BUF_DATA_FORMAT_INVALID;
+//     }
+//
+//     switch (desc->channel[first_non_void].size) {
+//     case 8:
+//             switch (desc->nr_channels) {
+//             case 1:
+//                     return V_008F0C_BUF_DATA_FORMAT_8;
+//             case 2:
+//                     return V_008F0C_BUF_DATA_FORMAT_8_8;
+//             case 4:
+//                     return V_008F0C_BUF_DATA_FORMAT_8_8_8_8;
+//             }
+//             break;
+//     case 16:
+//             switch (desc->nr_channels) {
+//             case 1:
+//                     return V_008F0C_BUF_DATA_FORMAT_16;
+//             case 2:
+//                     return V_008F0C_BUF_DATA_FORMAT_16_16;
+//             case 4:
+//                     return V_008F0C_BUF_DATA_FORMAT_16_16_16_16;
+//             }
+//             break;
+//     case 32:
+//             /* From the Southern Islands ISA documentation about MTBUF:
+//              * 'Memory reads of data in memory that is 32 or 64 bits do not
+//              * undergo any format conversion.'
+//              */
+//             if (type != VK_FORMAT_TYPE_FLOAT &&
+//                 !desc->channel[first_non_void].pure_integer)
+//                     return V_008F0C_BUF_DATA_FORMAT_INVALID;
+//
+//             switch (desc->nr_channels) {
+//             case 1:
+//                     return V_008F0C_BUF_DATA_FORMAT_32;
+//             case 2:
+//                     return V_008F0C_BUF_DATA_FORMAT_32_32;
+//             case 3:
+//                     return V_008F0C_BUF_DATA_FORMAT_32_32_32;
+//             case 4:
+//                     return V_008F0C_BUF_DATA_FORMAT_32_32_32_32;
+//             }
+//             break;
+//     }
+//
+//     return V_008F0C_BUF_DATA_FORMAT_INVALID;
+//}
+
+//uint32_t libresoc_translate_buffer_numformat(const struct vk_format_description *desc,
+//                                      int first_non_void)
+//{
+//     assert(desc->layout != VK_FORMAT_LAYOUT_MULTIPLANE);
+//
+//     if (desc->format == VK_FORMAT_B10G11R11_UFLOAT_PACK32)
+//             return V_008F0C_BUF_NUM_FORMAT_FLOAT;
+//
+//     if (first_non_void < 0)
+//             return ~0;
+//
+//     switch (desc->channel[first_non_void].type) {
+//     case VK_FORMAT_TYPE_SIGNED:
+//             if (desc->channel[first_non_void].normalized)
+//                     return V_008F0C_BUF_NUM_FORMAT_SNORM;
+//             else if (desc->channel[first_non_void].pure_integer)
+//                     return V_008F0C_BUF_NUM_FORMAT_SINT;
+//             else
+//                     return V_008F0C_BUF_NUM_FORMAT_SSCALED;
+//             break;
+//     case VK_FORMAT_TYPE_UNSIGNED:
+//             if (desc->channel[first_non_void].normalized)
+//                     return V_008F0C_BUF_NUM_FORMAT_UNORM;
+//             else if (desc->channel[first_non_void].pure_integer)
+//                     return V_008F0C_BUF_NUM_FORMAT_UINT;
+//             else
+//                     return V_008F0C_BUF_NUM_FORMAT_USCALED;
+//             break;
+//     case VK_FORMAT_TYPE_FLOAT:
+//     default:
+//             return V_008F0C_BUF_NUM_FORMAT_FLOAT;
+//     }
+//}
+
+//uint32_t libresoc_translate_tex_dataformat(VkFormat format,
+//                                    const struct vk_format_description *desc,
+//                                    int first_non_void)
+//{
+//     bool uniform = true;
+//     int i;
+//
+//     assert(vk_format_get_plane_count(format) == 1);
+//
+//     if (!desc)
+//             return ~0;
+//     /* Colorspace (return non-RGB formats directly). */
+//     switch (desc->colorspace) {
+//             /* Depth stencil formats */
+//     case VK_FORMAT_COLORSPACE_ZS:
+//             switch (format) {
+//             case VK_FORMAT_D16_UNORM:
+//                     return V_008F14_IMG_DATA_FORMAT_16;
+//             case VK_FORMAT_D24_UNORM_S8_UINT:
+//             case VK_FORMAT_X8_D24_UNORM_PACK32:
+//                     return V_008F14_IMG_DATA_FORMAT_8_24;
+//             case VK_FORMAT_S8_UINT:
+//                     return V_008F14_IMG_DATA_FORMAT_8;
+//             case VK_FORMAT_D32_SFLOAT:
+//                     return V_008F14_IMG_DATA_FORMAT_32;
+//             case VK_FORMAT_D32_SFLOAT_S8_UINT:
+//                     return V_008F14_IMG_DATA_FORMAT_X24_8_32;
+//             default:
+//                     goto out_unknown;
+//             }
+//
+//     case VK_FORMAT_COLORSPACE_YUV:
+//             goto out_unknown; /* TODO */
+//
+//     case VK_FORMAT_COLORSPACE_SRGB:
+//             if (desc->nr_channels != 4 && desc->nr_channels != 1)
+//                     goto out_unknown;
+//             break;
+//
+//     default:
+//             break;
+//     }
+//
+//     if (desc->layout == VK_FORMAT_LAYOUT_SUBSAMPLED) {
+//             switch(format) {
+//             /* Don't ask me why this looks inverted. PAL does the same. */
+//             case VK_FORMAT_G8B8G8R8_422_UNORM:
+//                     return V_008F14_IMG_DATA_FORMAT_BG_RG;
+//             case VK_FORMAT_B8G8R8G8_422_UNORM:
+//                     return V_008F14_IMG_DATA_FORMAT_GB_GR;
+//             default:
+//                     goto out_unknown;
+//             }
+//     }
+//
+//     if (desc->layout == VK_FORMAT_LAYOUT_RGTC) {
+//             switch(format) {
+//             case VK_FORMAT_BC4_UNORM_BLOCK:
+//             case VK_FORMAT_BC4_SNORM_BLOCK:
+//                     return V_008F14_IMG_DATA_FORMAT_BC4;
+//             case VK_FORMAT_BC5_UNORM_BLOCK:
+//             case VK_FORMAT_BC5_SNORM_BLOCK:
+//                     return V_008F14_IMG_DATA_FORMAT_BC5;
+//             default:
+//                     break;
+//             }
+//     }
+//
+//     if (desc->layout == VK_FORMAT_LAYOUT_S3TC) {
+//             switch(format) {
+//             case VK_FORMAT_BC1_RGB_UNORM_BLOCK:
+//             case VK_FORMAT_BC1_RGB_SRGB_BLOCK:
+//             case VK_FORMAT_BC1_RGBA_UNORM_BLOCK:
+//             case VK_FORMAT_BC1_RGBA_SRGB_BLOCK:
+//                     return V_008F14_IMG_DATA_FORMAT_BC1;
+//             case VK_FORMAT_BC2_UNORM_BLOCK:
+//             case VK_FORMAT_BC2_SRGB_BLOCK:
+//                     return V_008F14_IMG_DATA_FORMAT_BC2;
+//             case VK_FORMAT_BC3_UNORM_BLOCK:
+//             case VK_FORMAT_BC3_SRGB_BLOCK:
+//                     return V_008F14_IMG_DATA_FORMAT_BC3;
+//             default:
+//                     break;
+//             }
+//     }
+//
+//     if (desc->layout == VK_FORMAT_LAYOUT_BPTC) {
+//             switch(format) {
+//             case VK_FORMAT_BC6H_UFLOAT_BLOCK:
+//             case VK_FORMAT_BC6H_SFLOAT_BLOCK:
+//                     return V_008F14_IMG_DATA_FORMAT_BC6;
+//             case VK_FORMAT_BC7_UNORM_BLOCK:
+//             case VK_FORMAT_BC7_SRGB_BLOCK:
+//                     return V_008F14_IMG_DATA_FORMAT_BC7;
+//             default:
+//                     break;
+//             }
+//     }
+//
+//     if (desc->layout == VK_FORMAT_LAYOUT_ETC) {
+//             switch (format) {
+//             case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK:
+//             case VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK:
+//                     return V_008F14_IMG_DATA_FORMAT_ETC2_RGB;
+//             case VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK:
+//             case VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK:
+//                     return V_008F14_IMG_DATA_FORMAT_ETC2_RGBA1;
+//             case VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK:
+//             case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK:
+//                     return V_008F14_IMG_DATA_FORMAT_ETC2_RGBA;
+//             case VK_FORMAT_EAC_R11_UNORM_BLOCK:
+//             case VK_FORMAT_EAC_R11_SNORM_BLOCK:
+//                     return V_008F14_IMG_DATA_FORMAT_ETC2_R;
+//             case VK_FORMAT_EAC_R11G11_UNORM_BLOCK:
+//             case VK_FORMAT_EAC_R11G11_SNORM_BLOCK:
+//                     return V_008F14_IMG_DATA_FORMAT_ETC2_RG;
+//             default:
+//                     break;
+//             }
+//     }
+//
+//     if (format == VK_FORMAT_E5B9G9R9_UFLOAT_PACK32) {
+//             return V_008F14_IMG_DATA_FORMAT_5_9_9_9;
+//     } else if (format == VK_FORMAT_B10G11R11_UFLOAT_PACK32) {
+//             return V_008F14_IMG_DATA_FORMAT_10_11_11;
+//     }
+//
+//     /* R8G8Bx_SNORM - TODO CxV8U8 */
+//
+//     /* hw cannot support mixed formats (except depth/stencil, since only
+//      * depth is read).*/
+//     if (desc->is_mixed && desc->colorspace != VK_FORMAT_COLORSPACE_ZS)
+//             goto out_unknown;
+//
+//     /* See whether the components are of the same size. */
+//     for (i = 1; i < desc->nr_channels; i++) {
+//             uniform = uniform && desc->channel[0].size == desc->channel[i].size;
+//     }
+//
+//     /* Non-uniform formats. */
+//     if (!uniform) {
+//             switch(desc->nr_channels) {
+//             case 3:
+//                     if (desc->channel[0].size == 5 &&
+//                         desc->channel[1].size == 6 &&
+//                         desc->channel[2].size == 5) {
+//                             return V_008F14_IMG_DATA_FORMAT_5_6_5;
+//                     }
+//                     goto out_unknown;
+//             case 4:
+//                     if (desc->channel[0].size == 5 &&
+//                         desc->channel[1].size == 5 &&
+//                         desc->channel[2].size == 5 &&
+//                         desc->channel[3].size == 1) {
+//                             return V_008F14_IMG_DATA_FORMAT_1_5_5_5;
+//                     }
+//                     if (desc->channel[0].size == 1 &&
+//                         desc->channel[1].size == 5 &&
+//                         desc->channel[2].size == 5 &&
+//                         desc->channel[3].size == 5) {
+//                             return V_008F14_IMG_DATA_FORMAT_5_5_5_1;
+//                     }
+//                     if (desc->channel[0].size == 10 &&
+//                         desc->channel[1].size == 10 &&
+//                         desc->channel[2].size == 10 &&
+//                         desc->channel[3].size == 2) {
+//                             /* Closed VK driver does this also no 2/10/10/10 snorm */
+//                             if (desc->channel[0].type == VK_FORMAT_TYPE_SIGNED &&
+//                                 desc->channel[0].normalized)
+//                                     goto out_unknown;
+//                             return V_008F14_IMG_DATA_FORMAT_2_10_10_10;
+//                     }
+//                     goto out_unknown;
+//             }
+//             goto out_unknown;
+//     }
+//
+//     if (first_non_void < 0 || first_non_void > 3)
+//             goto out_unknown;
+//
+//     /* uniform formats */
+//     switch (desc->channel[first_non_void].size) {
+//     case 4:
+//             switch (desc->nr_channels) {
+//#if 0 /* Not supported for render targets */
+//             case 2:
+//                     return V_008F14_IMG_DATA_FORMAT_4_4;
+//#endif
+//             case 4:
+//                     return V_008F14_IMG_DATA_FORMAT_4_4_4_4;
+//             }
+//             break;
+//     case 8:
+//             switch (desc->nr_channels) {
+//             case 1:
+//                     return V_008F14_IMG_DATA_FORMAT_8;
+//             case 2:
+//                     return V_008F14_IMG_DATA_FORMAT_8_8;
+//             case 4:
+//                     return V_008F14_IMG_DATA_FORMAT_8_8_8_8;
+//             }
+//             break;
+//     case 16:
+//             switch (desc->nr_channels) {
+//             case 1:
+//                     return V_008F14_IMG_DATA_FORMAT_16;
+//             case 2:
+//                     return V_008F14_IMG_DATA_FORMAT_16_16;
+//             case 4:
+//                     return V_008F14_IMG_DATA_FORMAT_16_16_16_16;
+//             }
+//             break;
+//     case 32:
+//             switch (desc->nr_channels) {
+//             case 1:
+//                     return V_008F14_IMG_DATA_FORMAT_32;
+//             case 2:
+//                     return V_008F14_IMG_DATA_FORMAT_32_32;
+//             case 3:
+//                     return V_008F14_IMG_DATA_FORMAT_32_32_32;
+//             case 4:
+//                     return V_008F14_IMG_DATA_FORMAT_32_32_32_32;
+//             }
+//     }
+//
+//out_unknown:
+//     /* R600_ERR("Unable to handle texformat %d %s\n", format, vk_format_name(format)); */
+//     return ~0;
+//}
+
+//uint32_t libresoc_translate_tex_numformat(VkFormat format,
+//                                   const struct vk_format_description *desc,
+//                                   int first_non_void)
+//{
+//     assert(vk_format_get_plane_count(format) == 1);
+//
+//     switch (format) {
+//     case VK_FORMAT_D24_UNORM_S8_UINT:
+//             return V_008F14_IMG_NUM_FORMAT_UNORM;
+//     default:
+//             if (first_non_void < 0) {
+//                     if (vk_format_is_compressed(format)) {
+//                             switch (format) {
+//                             case VK_FORMAT_BC1_RGB_SRGB_BLOCK:
+//                             case VK_FORMAT_BC1_RGBA_SRGB_BLOCK:
+//                             case VK_FORMAT_BC2_SRGB_BLOCK:
+//                             case VK_FORMAT_BC3_SRGB_BLOCK:
+//                             case VK_FORMAT_BC7_SRGB_BLOCK:
+//                             case VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK:
+//                             case VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK:
+//                             case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK:
+//                                     return V_008F14_IMG_NUM_FORMAT_SRGB;
+//                             case VK_FORMAT_BC4_SNORM_BLOCK:
+//                             case VK_FORMAT_BC5_SNORM_BLOCK:
+//                             case VK_FORMAT_BC6H_SFLOAT_BLOCK:
+//                             case VK_FORMAT_EAC_R11_SNORM_BLOCK:
+//                             case VK_FORMAT_EAC_R11G11_SNORM_BLOCK:
+//                                     return V_008F14_IMG_NUM_FORMAT_SNORM;
+//                             default:
+//                                     return V_008F14_IMG_NUM_FORMAT_UNORM;
+//                             }
+//                     } else if (desc->layout == VK_FORMAT_LAYOUT_SUBSAMPLED) {
+//                             return V_008F14_IMG_NUM_FORMAT_UNORM;
+//                     } else {
+//                             return V_008F14_IMG_NUM_FORMAT_FLOAT;
+//                     }
+//             } else if (desc->colorspace == VK_FORMAT_COLORSPACE_SRGB) {
+//                     return V_008F14_IMG_NUM_FORMAT_SRGB;
+//             } else {
+//                     switch (desc->channel[first_non_void].type) {
+//                     case VK_FORMAT_TYPE_FLOAT:
+//                             return V_008F14_IMG_NUM_FORMAT_FLOAT;
+//                     case VK_FORMAT_TYPE_SIGNED:
+//                             if (desc->channel[first_non_void].normalized)
+//                                     return V_008F14_IMG_NUM_FORMAT_SNORM;
+//                             else if (desc->channel[first_non_void].pure_integer)
+//                                     return V_008F14_IMG_NUM_FORMAT_SINT;
+//                             else
+//                                     return V_008F14_IMG_NUM_FORMAT_SSCALED;
+//                     case VK_FORMAT_TYPE_UNSIGNED:
+//                             if (desc->channel[first_non_void].normalized)
+//                                     return V_008F14_IMG_NUM_FORMAT_UNORM;
+//                             else if (desc->channel[first_non_void].pure_integer)
+//                                     return V_008F14_IMG_NUM_FORMAT_UINT;
+//                             else
+//                                     return V_008F14_IMG_NUM_FORMAT_USCALED;
+//                     default:
+//                             return V_008F14_IMG_NUM_FORMAT_UNORM;
+//                     }
+//             }
+//     }
+//}
+
+//uint32_t libresoc_translate_color_numformat(VkFormat format,
+//                                     const struct vk_format_description *desc,
+//                                     int first_non_void)
+//{
+//     unsigned ntype;
+//
+//     assert(vk_format_get_plane_count(format) == 1);
+//
+//     if (first_non_void == -1 || desc->channel[first_non_void].type == VK_FORMAT_TYPE_FLOAT)
+//             ntype = V_028C70_NUMBER_FLOAT;
+//     else {
+//             ntype = V_028C70_NUMBER_UNORM;
+//             if (desc->colorspace == VK_FORMAT_COLORSPACE_SRGB)
+//                     ntype = V_028C70_NUMBER_SRGB;
+//             else if (desc->channel[first_non_void].type == VK_FORMAT_TYPE_SIGNED) {
+//                     if (desc->channel[first_non_void].pure_integer) {
+//                             ntype = V_028C70_NUMBER_SINT;
+//                     } else if (desc->channel[first_non_void].normalized) {
+//                             ntype = V_028C70_NUMBER_SNORM;
+//                     } else
+//                             ntype = ~0u;
+//             } else if (desc->channel[first_non_void].type == VK_FORMAT_TYPE_UNSIGNED) {
+//                     if (desc->channel[first_non_void].pure_integer) {
+//                             ntype = V_028C70_NUMBER_UINT;
+//                     } else if (desc->channel[first_non_void].normalized) {
+//                             ntype = V_028C70_NUMBER_UNORM;
+//                     } else
+//                             ntype = ~0u;
+//             }
+//     }
+//     return ntype;
+//}
+
+static bool libresoc_is_sampler_format_supported(VkFormat format, bool *linear_sampling)
+{
+       const struct vk_format_description *desc = vk_format_description(format);
+       uint32_t num_format;
+       if (!desc || format == VK_FORMAT_UNDEFINED)
+               return false;
+
+       //TODO: stub, enables everything
+       return true;
+}
+
+
+static bool libresoc_is_storage_image_format_supported(struct libresoc_physical_device *physical_device,
+                                                  VkFormat format)
+{
+       const struct vk_format_description *desc = vk_format_description(format);
+       unsigned data_format, num_format;
+       if (!desc || format == VK_FORMAT_UNDEFINED)
+               return false;
+       //TODO: stub, enables everything
+       return true;
+}
+
+bool libresoc_is_buffer_format_supported(VkFormat format, bool *scaled)
+{
+       const struct vk_format_description *desc = vk_format_description(format);
+       unsigned data_format, num_format;
+       if (!desc || format == VK_FORMAT_UNDEFINED)
+               return false;
+
+       //TODO: stub, enables everything
+       return true;
+}
+
+bool libresoc_is_colorbuffer_format_supported(VkFormat format, bool *blendable)
+{
+       //TODO: stub, enables everything
+       return true;
+}
+
+static bool libresoc_is_zs_format_supported(VkFormat format)
+{
+       //TODO: stub, enables everything
+       return true;
+}
+
+static bool libresoc_is_filter_minmax_format_supported(VkFormat format)
+{
+       /* From the Vulkan spec 1.1.71:
+        *
+        * "The following formats must support the
+        *  VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT feature with
+        *  VK_IMAGE_TILING_OPTIMAL, if they support
+        *  VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT."
+        */
+       /* TODO: enable more formats. */
+       switch (format) {
+       case VK_FORMAT_R8_UNORM:
+       case VK_FORMAT_R8_SNORM:
+       case VK_FORMAT_R16_UNORM:
+       case VK_FORMAT_R16_SNORM:
+       case VK_FORMAT_R16_SFLOAT:
+       case VK_FORMAT_R32_SFLOAT:
+       case VK_FORMAT_D16_UNORM:
+       case VK_FORMAT_X8_D24_UNORM_PACK32:
+       case VK_FORMAT_D32_SFLOAT:
+       case VK_FORMAT_D16_UNORM_S8_UINT:
+       case VK_FORMAT_D24_UNORM_S8_UINT:
+       case VK_FORMAT_D32_SFLOAT_S8_UINT:
+               return true;
+       default:
+               return false;
+       }
+}
+
+bool
+libresoc_device_supports_etc(struct libresoc_physical_device *physical_device)
+{
+       //TODO: stub, enables everything
+       return true;
+}
+
+static void
+libresoc_physical_device_get_format_properties(struct libresoc_physical_device *physical_device,
+                                          VkFormat format,
+                                          VkFormatProperties *out_properties)
+{
+       VkFormatFeatureFlags linear = 0, tiled = 0, buffer = 0;
+       const struct vk_format_description *desc = vk_format_description(format);
+       bool blendable;
+       bool scaled = false;
+       /* TODO: implement some software emulation of SUBSAMPLED formats. */
+       if (!desc || desc->layout == VK_FORMAT_LAYOUT_SUBSAMPLED) {
+               out_properties->linearTilingFeatures = linear;
+               out_properties->optimalTilingFeatures = tiled;
+               out_properties->bufferFeatures = buffer;
+               return;
+       }
+
+       if (desc->layout == VK_FORMAT_LAYOUT_ETC &&
+           !libresoc_device_supports_etc(physical_device)) {
+               out_properties->linearTilingFeatures = linear;
+               out_properties->optimalTilingFeatures = tiled;
+               out_properties->bufferFeatures = buffer;
+               return;
+       }
+
+       if (desc->layout == VK_FORMAT_LAYOUT_MULTIPLANE ||
+           desc->layout == VK_FORMAT_LAYOUT_SUBSAMPLED) {
+               uint32_t tiling = VK_FORMAT_FEATURE_TRANSFER_SRC_BIT |
+                                 VK_FORMAT_FEATURE_TRANSFER_DST_BIT |
+                                 VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
+                                 VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT |
+                                 VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT;
+
+               /* The subsampled formats have no support for linear filters. */
+               if (desc->layout != VK_FORMAT_LAYOUT_SUBSAMPLED) {
+                       tiling |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT;
+               }
+
+               /* Fails for unknown reasons with linear tiling & subsampled formats. */
+               out_properties->linearTilingFeatures = desc->layout == VK_FORMAT_LAYOUT_SUBSAMPLED ? 0 : tiling;
+               out_properties->optimalTilingFeatures = tiling;
+               out_properties->bufferFeatures = 0;
+               return;
+       }
+
+       if (libresoc_is_storage_image_format_supported(physical_device, format)) {
+               tiled |= VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;
+               linear |= VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;
+       }
+
+       if (libresoc_is_buffer_format_supported(format, &scaled)) {
+               buffer |= VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT;
+               if (!scaled)
+                       buffer |= VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT |
+                               VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT;
+       }
+
+       if (vk_format_is_depth_or_stencil(format)) {
+               if (libresoc_is_zs_format_supported(format)) {
+                       tiled |= VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
+                       tiled |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
+                       tiled |= VK_FORMAT_FEATURE_BLIT_SRC_BIT |
+                                VK_FORMAT_FEATURE_BLIT_DST_BIT;
+                       tiled |= VK_FORMAT_FEATURE_TRANSFER_SRC_BIT |
+                                VK_FORMAT_FEATURE_TRANSFER_DST_BIT;
+
+                       if (libresoc_is_filter_minmax_format_supported(format))
+                                tiled |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT;
+
+                       /* Don't support blitting surfaces with depth/stencil. */
+                       if (vk_format_is_depth(format) && vk_format_is_stencil(format))
+                               tiled &= ~VK_FORMAT_FEATURE_BLIT_DST_BIT;
+
+                       /* Don't support linear depth surfaces */
+                       linear = 0;
+               }
+       } else {
+               bool linear_sampling;
+               if (libresoc_is_sampler_format_supported(format, &linear_sampling)) {
+                       linear |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
+                               VK_FORMAT_FEATURE_BLIT_SRC_BIT;
+                       tiled |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
+                               VK_FORMAT_FEATURE_BLIT_SRC_BIT;
+
+                       if (libresoc_is_filter_minmax_format_supported(format))
+                                tiled |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT;
+
+                       if (linear_sampling) {
+                               linear |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
+                               tiled |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
+                       }
+
+                       /* Don't support blitting for R32G32B32 formats. */
+                       if (format == VK_FORMAT_R32G32B32_SFLOAT ||
+                           format == VK_FORMAT_R32G32B32_UINT ||
+                           format == VK_FORMAT_R32G32B32_SINT) {
+                               linear &= ~VK_FORMAT_FEATURE_BLIT_SRC_BIT;
+                       }
+               }
+               if (libresoc_is_colorbuffer_format_supported(format, &blendable)) {
+                       linear |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT;
+                       tiled |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT;
+                       if (blendable) {
+                               linear |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT;
+                               tiled |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT;
+                       }
+               }
+               if (tiled && !scaled) {
+                       tiled |= VK_FORMAT_FEATURE_TRANSFER_SRC_BIT |
+                                VK_FORMAT_FEATURE_TRANSFER_DST_BIT;
+               }
+
+               /* Tiled formatting does not support NPOT pixel sizes */
+               if (!util_is_power_of_two_or_zero(vk_format_get_blocksize(format)))
+                       tiled = 0;
+       }
+
+       if (linear && !scaled) {
+               linear |= VK_FORMAT_FEATURE_TRANSFER_SRC_BIT |
+                         VK_FORMAT_FEATURE_TRANSFER_DST_BIT;
+       }
+
+       if (format == VK_FORMAT_R32_UINT ||
+           format == VK_FORMAT_R32_SINT ||
+           format == VK_FORMAT_R32_SFLOAT) {
+               buffer |= VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT;
+               linear |= VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT;
+               tiled |= VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT;
+       }
+
+
+       out_properties->linearTilingFeatures = linear;
+       out_properties->optimalTilingFeatures = tiled;
+       out_properties->bufferFeatures = buffer;
+}
+
+//uint32_t libresoc_translate_colorformat(VkFormat format)
+//{
+//     const struct vk_format_description *desc = vk_format_description(format);
+//
+//#define HAS_SIZE(x,y,z,w)                                            \
+//     (desc->channel[0].size == (x) && desc->channel[1].size == (y) && \
+//         desc->channel[2].size == (z) && desc->channel[3].size == (w))
+//
+//     if (format == VK_FORMAT_B10G11R11_UFLOAT_PACK32) /* isn't plain */
+//             return V_028C70_COLOR_10_11_11;
+//
+//     if (desc->layout != VK_FORMAT_LAYOUT_PLAIN)
+//             return V_028C70_COLOR_INVALID;
+//
+//     /* hw cannot support mixed formats (except depth/stencil, since
+//      * stencil is not written to). */
+//     if (desc->is_mixed && desc->colorspace != VK_FORMAT_COLORSPACE_ZS)
+//             return V_028C70_COLOR_INVALID;
+//
+//     switch (desc->nr_channels) {
+//     case 1:
+//             switch (desc->channel[0].size) {
+//             case 8:
+//                     return V_028C70_COLOR_8;
+//             case 16:
+//                     return V_028C70_COLOR_16;
+//             case 32:
+//                     return V_028C70_COLOR_32;
+//             }
+//             break;
+//     case 2:
+//             if (desc->channel[0].size == desc->channel[1].size) {
+//                     switch (desc->channel[0].size) {
+//                     case 8:
+//                             return V_028C70_COLOR_8_8;
+//                     case 16:
+//                             return V_028C70_COLOR_16_16;
+//                     case 32:
+//                             return V_028C70_COLOR_32_32;
+//                     }
+//             } else if (HAS_SIZE(8,24,0,0)) {
+//                     return V_028C70_COLOR_24_8;
+//             } else if (HAS_SIZE(24,8,0,0)) {
+//                     return V_028C70_COLOR_8_24;
+//             }
+//             break;
+//     case 3:
+//             if (HAS_SIZE(5,6,5,0)) {
+//                     return V_028C70_COLOR_5_6_5;
+//             } else if (HAS_SIZE(32,8,24,0)) {
+//                     return V_028C70_COLOR_X24_8_32_FLOAT;
+//             }
+//             break;
+//     case 4:
+//             if (desc->channel[0].size == desc->channel[1].size &&
+//                 desc->channel[0].size == desc->channel[2].size &&
+//                 desc->channel[0].size == desc->channel[3].size) {
+//                     switch (desc->channel[0].size) {
+//                     case 4:
+//                             return V_028C70_COLOR_4_4_4_4;
+//                     case 8:
+//                             return V_028C70_COLOR_8_8_8_8;
+//                     case 16:
+//                             return V_028C70_COLOR_16_16_16_16;
+//                     case 32:
+//                             return V_028C70_COLOR_32_32_32_32;
+//                     }
+//             } else if (HAS_SIZE(5,5,5,1)) {
+//                     return V_028C70_COLOR_1_5_5_5;
+//             } else if (HAS_SIZE(1,5,5,5)) {
+//                     return V_028C70_COLOR_5_5_5_1;
+//             } else if (HAS_SIZE(10,10,10,2)) {
+//                     return V_028C70_COLOR_2_10_10_10;
+//             }
+//             break;
+//     }
+//     return V_028C70_COLOR_INVALID;
+//}
+
+//uint32_t libresoc_colorformat_endian_swap(uint32_t colorformat)
+//{
+//     if (0/*SI_BIG_ENDIAN*/) {
+//             switch(colorformat) {
+//                     /* 8-bit buffers. */
+//             case V_028C70_COLOR_8:
+//                     return V_028C70_ENDIAN_NONE;
+//
+//                     /* 16-bit buffers. */
+//             case V_028C70_COLOR_5_6_5:
+//             case V_028C70_COLOR_1_5_5_5:
+//             case V_028C70_COLOR_4_4_4_4:
+//             case V_028C70_COLOR_16:
+//             case V_028C70_COLOR_8_8:
+//                     return V_028C70_ENDIAN_8IN16;
+//
+//                     /* 32-bit buffers. */
+//             case V_028C70_COLOR_8_8_8_8:
+//             case V_028C70_COLOR_2_10_10_10:
+//             case V_028C70_COLOR_8_24:
+//             case V_028C70_COLOR_24_8:
+//             case V_028C70_COLOR_16_16:
+//                     return V_028C70_ENDIAN_8IN32;
+//
+//                     /* 64-bit buffers. */
+//             case V_028C70_COLOR_16_16_16_16:
+//                     return V_028C70_ENDIAN_8IN16;
+//
+//             case V_028C70_COLOR_32_32:
+//                     return V_028C70_ENDIAN_8IN32;
+//
+//                     /* 128-bit buffers. */
+//             case V_028C70_COLOR_32_32_32_32:
+//                     return V_028C70_ENDIAN_8IN32;
+//             default:
+//                     return V_028C70_ENDIAN_NONE; /* Unsupported. */
+//             }
+//     } else {
+//             return V_028C70_ENDIAN_NONE;
+//     }
+//}
+
+//uint32_t libresoc_translate_dbformat(VkFormat format)
+//{
+//     switch (format) {
+//     case VK_FORMAT_D16_UNORM:
+//     case VK_FORMAT_D16_UNORM_S8_UINT:
+//             return V_028040_Z_16;
+//     case VK_FORMAT_D32_SFLOAT:
+//     case VK_FORMAT_D32_SFLOAT_S8_UINT:
+//             return V_028040_Z_32_FLOAT;
+//     default:
+//             return V_028040_Z_INVALID;
+//     }
+//}
+
+//unsigned libresoc_translate_colorswap(VkFormat format, bool do_endian_swap)
+//{
+//     const struct vk_format_description *desc = vk_format_description(format);
+//
+//#define HAS_SWIZZLE(chan,swz) (desc->swizzle[chan] == VK_SWIZZLE_##swz)
+//
+//     if (format == VK_FORMAT_B10G11R11_UFLOAT_PACK32)
+//             return V_028C70_SWAP_STD;
+//
+//     if (desc->layout != VK_FORMAT_LAYOUT_PLAIN)
+//             return ~0U;
+//
+//     switch (desc->nr_channels) {
+//     case 1:
+//             if (HAS_SWIZZLE(0,X))
+//                     return V_028C70_SWAP_STD; /* X___ */
+//             else if (HAS_SWIZZLE(3,X))
+//                     return V_028C70_SWAP_ALT_REV; /* ___X */
+//             break;
+//     case 2:
+//             if ((HAS_SWIZZLE(0,X) && HAS_SWIZZLE(1,Y)) ||
+//                 (HAS_SWIZZLE(0,X) && HAS_SWIZZLE(1,NONE)) ||
+//                 (HAS_SWIZZLE(0,NONE) && HAS_SWIZZLE(1,Y)))
+//                     return V_028C70_SWAP_STD; /* XY__ */
+//             else if ((HAS_SWIZZLE(0,Y) && HAS_SWIZZLE(1,X)) ||
+//                      (HAS_SWIZZLE(0,Y) && HAS_SWIZZLE(1,NONE)) ||
+//                      (HAS_SWIZZLE(0,NONE) && HAS_SWIZZLE(1,X)))
+//                     /* YX__ */
+//                     return (do_endian_swap ? V_028C70_SWAP_STD : V_028C70_SWAP_STD_REV);
+//             else if (HAS_SWIZZLE(0,X) && HAS_SWIZZLE(3,Y))
+//                     return V_028C70_SWAP_ALT; /* X__Y */
+//             else if (HAS_SWIZZLE(0,Y) && HAS_SWIZZLE(3,X))
+//                     return V_028C70_SWAP_ALT_REV; /* Y__X */
+//             break;
+//     case 3:
+//             if (HAS_SWIZZLE(0,X))
+//                     return (do_endian_swap ? V_028C70_SWAP_STD_REV : V_028C70_SWAP_STD);
+//             else if (HAS_SWIZZLE(0,Z))
+//                     return V_028C70_SWAP_STD_REV; /* ZYX */
+//             break;
+//     case 4:
+//             /* check the middle channels, the 1st and 4th channel can be NONE */
+//             if (HAS_SWIZZLE(1,Y) && HAS_SWIZZLE(2,Z)) {
+//                     return V_028C70_SWAP_STD; /* XYZW */
+//             } else if (HAS_SWIZZLE(1,Z) && HAS_SWIZZLE(2,Y)) {
+//                     return V_028C70_SWAP_STD_REV; /* WZYX */
+//             } else if (HAS_SWIZZLE(1,Y) && HAS_SWIZZLE(2,X)) {
+//                     return V_028C70_SWAP_ALT; /* ZYXW */
+//             } else if (HAS_SWIZZLE(1,Z) && HAS_SWIZZLE(2,W)) {
+//                     /* YZWX */
+//                     if (desc->is_array)
+//                             return V_028C70_SWAP_ALT_REV;
+//                     else
+//                             return (do_endian_swap ? V_028C70_SWAP_ALT : V_028C70_SWAP_ALT_REV);
+//             }
+//             break;
+//     }
+//     return ~0U;
+//}
+
+//bool libresoc_format_pack_clear_color(VkFormat format,
+//                               uint32_t clear_vals[2],
+//                               VkClearColorValue *value)
+//{
+//     const struct vk_format_description *desc = vk_format_description(format);
+//
+//     if (format == VK_FORMAT_B10G11R11_UFLOAT_PACK32) {
+//             clear_vals[0] = float3_to_r11g11b10f(value->float32);
+//             clear_vals[1] = 0;
+//             return true;
+//     }
+//
+//     if (desc->layout != VK_FORMAT_LAYOUT_PLAIN) {
+//             fprintf(stderr, "failed to fast clear for non-plain format %d\n", format);
+//             return false;
+//     }
+//
+//     if (!util_is_power_of_two_or_zero(desc->block.bits)) {
+//             fprintf(stderr, "failed to fast clear for NPOT format %d\n", format);
+//             return false;
+//     }
+//
+//     if (desc->block.bits > 64) {
+//             /*
+//              * We have a 128 bits format, check if the first 3 components are the same.
+//              * Every elements has to be 32 bits since we don't support 64-bit formats,
+//              * and we can skip swizzling checks as alpha always comes last for these and
+//              * we do not care about the rest as they have to be the same.
+//              */
+//             if (desc->channel[0].type == VK_FORMAT_TYPE_FLOAT) {
+//                     if (value->float32[0] != value->float32[1] ||
+//                         value->float32[0] != value->float32[2])
+//                             return false;
+//             } else {
+//                     if (value->uint32[0] != value->uint32[1] ||
+//                         value->uint32[0] != value->uint32[2])
+//                             return false;
+//             }
+//             clear_vals[0] = value->uint32[0];
+//             clear_vals[1] = value->uint32[3];
+//             return true;
+//     }
+//     uint64_t clear_val = 0;
+//
+//     for (unsigned c = 0; c < 4; ++c) {
+//             if (desc->swizzle[c] >= 4)
+//                     continue;
+//
+//             const struct vk_format_channel_description *channel = &desc->channel[desc->swizzle[c]];
+//             assert(channel->size);
+//
+//             uint64_t v = 0;
+//             if (channel->pure_integer) {
+//                     v = value->uint32[c]  & ((1ULL << channel->size) - 1);
+//             } else if (channel->normalized) {
+//                     if (channel->type == VK_FORMAT_TYPE_UNSIGNED &&
+//                         desc->swizzle[c] < 3 &&
+//                         desc->colorspace == VK_FORMAT_COLORSPACE_SRGB) {
+//                             assert(channel->size == 8);
+//
+//                             v = util_format_linear_float_to_srgb_8unorm(value->float32[c]);
+//                     } else {
+//                             float f = MIN2(value->float32[c], 1.0f);
+//
+//                             if (channel->type == VK_FORMAT_TYPE_UNSIGNED) {
+//                                     f = MAX2(f, 0.0f) * ((1ULL << channel->size) - 1);
+//                             } else {
+//                                     f = MAX2(f, -1.0f) * ((1ULL << (channel->size - 1)) - 1);
+//                             }
+//
+//                             /* The hardware rounds before conversion. */
+//                             if (f > 0)
+//                                     f += 0.5f;
+//                             else
+//                                     f -= 0.5f;
+//
+//                             v = (uint64_t)f;
+//                     }
+//             } else if (channel->type == VK_FORMAT_TYPE_FLOAT) {
+//                     if (channel->size == 32) {
+//                             memcpy(&v, &value->float32[c], 4);
+//                     } else if(channel->size == 16) {
+//                             v = util_float_to_half_rtz(value->float32[c]);
+//                     } else {
+//                             fprintf(stderr, "failed to fast clear for unhandled float size in format %d\n", format);
+//                             return false;
+//                     }
+//             } else {
+//                     fprintf(stderr, "failed to fast clear for unhandled component type in format %d\n", format);
+//                     return false;
+//             }
+//             clear_val |= (v & ((1ULL << channel->size) - 1)) << channel->shift;
+//     }
+//
+//     clear_vals[0] = clear_val;
+//     clear_vals[1] = clear_val >> 32;
+//
+//     return true;
+//}
+
+void libresoc_GetPhysicalDeviceFormatProperties(
+       VkPhysicalDevice                            physicalDevice,
+       VkFormat                                    format,
+       VkFormatProperties*                         pFormatProperties)
+{
+       LIBRESOC_FROM_HANDLE(libresoc_physical_device, physical_device, physicalDevice);
+
+       libresoc_physical_device_get_format_properties(physical_device,
+                                                  format,
+                                                  pFormatProperties);
+}
+
+//void libresoc_GetPhysicalDeviceFormatProperties2(
+//     VkPhysicalDevice                            physicalDevice,
+//     VkFormat                                    format,
+//     VkFormatProperties2*                        pFormatProperties)
+//{
+//     LIBRESOC_FROM_HANDLE(libresoc_physical_device, physical_device, physicalDevice);
+//
+//     libresoc_physical_device_get_format_properties(physical_device,
+//                                                format,
+//                                                &pFormatProperties->formatProperties);
+//}
+
+static VkResult libresoc_get_image_format_properties(struct libresoc_physical_device *physical_device,
+                                                const VkPhysicalDeviceImageFormatInfo2 *info,
+                                                VkFormat format,
+                                                VkImageFormatProperties *pImageFormatProperties)
+
+{
+       VkFormatProperties format_props;
+       VkFormatFeatureFlags format_feature_flags;
+       VkExtent3D maxExtent;
+       uint32_t maxMipLevels;
+       uint32_t maxArraySize;
+       VkSampleCountFlags sampleCounts = VK_SAMPLE_COUNT_1_BIT;
+       const struct vk_format_description *desc = vk_format_description(format);
+
+       libresoc_physical_device_get_format_properties(physical_device, format,
+                                                  &format_props);
+       if (info->tiling == VK_IMAGE_TILING_LINEAR) {
+               format_feature_flags = format_props.linearTilingFeatures;
+       } else if (info->tiling == VK_IMAGE_TILING_OPTIMAL) {
+               format_feature_flags = format_props.optimalTilingFeatures;
+       } else {
+               unreachable("bad VkImageTiling");
+       }
+
+       if (format_feature_flags == 0)
+               goto unsupported;
+
+       if (info->type != VK_IMAGE_TYPE_2D && vk_format_is_depth_or_stencil(format))
+               goto unsupported;
+
+       switch (info->type) {
+       default:
+               unreachable("bad vkimage type\n");
+       case VK_IMAGE_TYPE_1D:
+               maxExtent.width = 16384;
+               maxExtent.height = 1;
+               maxExtent.depth = 1;
+               maxMipLevels = 15; /* log2(maxWidth) + 1 */
+               maxArraySize =  2048;
+               break;
+       case VK_IMAGE_TYPE_2D:
+               maxExtent.width = 16384;
+               maxExtent.height = 16384;
+               maxExtent.depth = 1;
+               maxMipLevels = 15; /* log2(maxWidth) + 1 */
+               maxArraySize =  2048;
+               break;
+       case VK_IMAGE_TYPE_3D:
+                       maxExtent.width = 2048;
+                       maxExtent.height = 2048;
+                       maxExtent.depth = 2048;
+               maxMipLevels = util_logbase2(maxExtent.width) + 1;
+               maxArraySize = 1;
+               break;
+       }
+
+       if (desc->layout == VK_FORMAT_LAYOUT_SUBSAMPLED) {
+               /* Might be able to support but the entire format support is
+                * messy, so taking the lazy way out. */
+               maxArraySize = 1;
+       }
+
+       if (info->tiling == VK_IMAGE_TILING_OPTIMAL &&
+           info->type == VK_IMAGE_TYPE_2D &&
+           (format_feature_flags & (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT |
+                                    VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) &&
+           !(info->flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT)) {
+               sampleCounts |= VK_SAMPLE_COUNT_2_BIT | VK_SAMPLE_COUNT_4_BIT | VK_SAMPLE_COUNT_8_BIT;
+       }
+
+       if (info->tiling == VK_IMAGE_TILING_LINEAR &&
+           (format == VK_FORMAT_R32G32B32_SFLOAT ||
+            format == VK_FORMAT_R32G32B32_SINT ||
+            format == VK_FORMAT_R32G32B32_UINT)) {
+               /* R32G32B32 is a weird format and the driver currently only
+                * supports the barely minimum.
+                * TODO: Implement more if we really need to.
+                */
+               maxArraySize = 1;
+               maxMipLevels = 1;
+       }
+
+
+
+       *pImageFormatProperties = (VkImageFormatProperties) {
+               .maxExtent = maxExtent,
+               .maxMipLevels = maxMipLevels,
+               .maxArrayLayers = maxArraySize,
+               .sampleCounts = sampleCounts,
+
+               /* FINISHME: Accurately calculate
+                * VkImageFormatProperties::maxResourceSize.
+                */
+               .maxResourceSize = UINT32_MAX,
+       };
+
+       return VK_SUCCESS;
+//TODO: for now we support everything
+unsupported:
+       *pImageFormatProperties = (VkImageFormatProperties) {
+               .maxExtent = { 0, 0, 0 },
+               .maxMipLevels = 0,
+               .maxArrayLayers = 0,
+               .sampleCounts = 0,
+               .maxResourceSize = 0,
+       };
+
+       return VK_ERROR_FORMAT_NOT_SUPPORTED;
+}
+
+VkResult libresoc_GetPhysicalDeviceImageFormatProperties(
+       VkPhysicalDevice                            physicalDevice,
+       VkFormat                                    format,
+       VkImageType                                 type,
+       VkImageTiling                               tiling,
+       VkImageUsageFlags                           usage,
+       VkImageCreateFlags                          createFlags,
+       VkImageFormatProperties*                    pImageFormatProperties)
+{
+       LIBRESOC_FROM_HANDLE(libresoc_physical_device, physical_device, physicalDevice);
+
+       const VkPhysicalDeviceImageFormatInfo2 info = {
+               .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
+               .pNext = NULL,
+               .format = format,
+               .type = type,
+               .tiling = tiling,
+               .usage = usage,
+               .flags = createFlags,
+       };
+
+       return libresoc_get_image_format_properties(physical_device, &info, format,
+                                               pImageFormatProperties);
+}
+
+static void
+get_external_image_format_properties(struct libresoc_physical_device *physical_device,
+                                    const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo,
+                                    VkExternalMemoryHandleTypeFlagBits handleType,
+                                    VkExternalMemoryProperties *external_properties,
+                                    VkImageFormatProperties *format_properties)
+{
+       VkExternalMemoryFeatureFlagBits flags = 0;
+       VkExternalMemoryHandleTypeFlags export_flags = 0;
+       VkExternalMemoryHandleTypeFlags compat_flags = 0;
+
+       if (pImageFormatInfo->flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT)
+               return;
+
+       switch (handleType) {
+       case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:
+       case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
+               switch (pImageFormatInfo->type) {
+               case VK_IMAGE_TYPE_2D:
+                       flags = VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT|VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
+                       if (pImageFormatInfo->tiling != VK_IMAGE_TILING_LINEAR)
+                               flags |= VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT;
+
+                       compat_flags = export_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT |
+                                                     VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
+                       break;
+               default:
+                       break;
+               }
+               break;
+       case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT:
+               flags = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
+               compat_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT;
+               break;
+       default:
+               break;
+       }
+
+       *external_properties = (VkExternalMemoryProperties) {
+               .externalMemoryFeatures = flags,
+               .exportFromImportedHandleTypes = export_flags,
+               .compatibleHandleTypes = compat_flags,
+       };
+}
+
+//VkResult libresoc_GetPhysicalDeviceImageFormatProperties2(
+//     VkPhysicalDevice                            physicalDevice,
+//     const VkPhysicalDeviceImageFormatInfo2     *base_info,
+//     VkImageFormatProperties2                   *base_props)
+//{
+//     LIBRESOC_FROM_HANDLE(libresoc_physical_device, physical_device, physicalDevice);
+//     const VkPhysicalDeviceExternalImageFormatInfo *external_info = NULL;
+//     VkExternalImageFormatProperties *external_props = NULL;
+//     struct VkAndroidHardwareBufferUsageANDROID *android_usage = NULL;
+//     VkSamplerYcbcrConversionImageFormatProperties *ycbcr_props = NULL;
+//     VkTextureLODGatherFormatPropertiesAMD *texture_lod_props = NULL;
+//     VkResult result;
+//     VkFormat format = libresoc_select_android_external_format(base_info->pNext, base_info->format);
+//
+//     result = libresoc_get_image_format_properties(physical_device, base_info, format,
+//                                             &base_props->imageFormatProperties);
+//     if (result != VK_SUCCESS)
+//             return result;
+//
+//        /* Extract input structs */
+//     vk_foreach_struct_const(s, base_info->pNext) {
+//             switch (s->sType) {
+//             case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO:
+//                     external_info = (const void *) s;
+//                     break;
+//             default:
+//                     break;
+//             }
+//     }
+//
+//     /* Extract output structs */
+//     vk_foreach_struct(s, base_props->pNext) {
+//             switch (s->sType) {
+//             case VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES:
+//                     external_props = (void *) s;
+//                     break;
+//             case VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES:
+//                     ycbcr_props = (void *) s;
+//                     break;
+//             case VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID:
+//                     android_usage = (void *) s;
+//                     break;
+//             case VK_STRUCTURE_TYPE_TEXTURE_LOD_GATHER_FORMAT_PROPERTIES_AMD:
+//                     texture_lod_props = (void *) s;
+//                     break;
+//             default:
+//                     break;
+//             }
+//     }
+//
+//     bool ahb_supported = physical_device->supported_extensions.ANDROID_external_memory_android_hardware_buffer;
+//     if (android_usage && ahb_supported) {
+//#if LIBRESOC_SUPPORT_ANDROID_HARDWARE_BUFFER
+//             android_usage->androidHardwareBufferUsage =
+//                     libresoc_ahb_usage_from_vk_usage(base_info->flags,
+//                                                  base_info->usage);
+//#endif
+//     }
+//
+//     /* From the Vulkan 1.0.97 spec:
+//      *
+//      *    If handleType is 0, vkGetPhysicalDeviceImageFormatProperties2 will
+//      *    behave as if VkPhysicalDeviceExternalImageFormatInfo was not
+//      *    present and VkExternalImageFormatProperties will be ignored.
+//      */
+//     if (external_info && external_info->handleType != 0) {
+//             get_external_image_format_properties(physical_device, base_info, external_info->handleType,
+//                                                  &external_props->externalMemoryProperties,
+//                                                  &base_props->imageFormatProperties);
+//             if (!external_props->externalMemoryProperties.externalMemoryFeatures) {
+//                     /* From the Vulkan 1.0.97 spec:
+//                      *
+//                      *    If handleType is not compatible with the [parameters] specified
+//                      *    in VkPhysicalDeviceImageFormatInfo2, then
+//                      *    vkGetPhysicalDeviceImageFormatProperties2 returns
+//                      *    VK_ERROR_FORMAT_NOT_SUPPORTED.
+//                      */
+//                     result = vk_errorf(physical_device->instance, VK_ERROR_FORMAT_NOT_SUPPORTED,
+//                                        "unsupported VkExternalMemoryTypeFlagBitsKHR 0x%x",
+//                                        external_info->handleType);
+//                     goto fail;
+//             }
+//     }
+//
+//     if (ycbcr_props) {
+//             ycbcr_props->combinedImageSamplerDescriptorCount = vk_format_get_plane_count(format);
+//     }
+//
+//     if (texture_lod_props) {
+//             if (physical_device->rad_info.chip_class >= GFX9) {
+//                     texture_lod_props->supportsTextureGatherLODBiasAMD = true;
+//             } else {
+//                     texture_lod_props->supportsTextureGatherLODBiasAMD = !vk_format_is_int(format);
+//             }
+//     }
+//
+//     return VK_SUCCESS;
+//
+//fail:
+//     if (result == VK_ERROR_FORMAT_NOT_SUPPORTED) {
+//             /* From the Vulkan 1.0.97 spec:
+//              *
+//              *    If the combination of parameters to
+//              *    vkGetPhysicalDeviceImageFormatProperties2 is not supported by
+//              *    the implementation for use in vkCreateImage, then all members of
+//              *    imageFormatProperties will be filled with zero.
+//              */
+//             base_props->imageFormatProperties = (VkImageFormatProperties) {0};
+//     }
+//
+//     return result;
+//}
+
+void libresoc_GetPhysicalDeviceSparseImageFormatProperties(
+       VkPhysicalDevice                            physicalDevice,
+       VkFormat                                    format,
+       VkImageType                                 type,
+       uint32_t                                    samples,
+       VkImageUsageFlags                           usage,
+       VkImageTiling                               tiling,
+       uint32_t*                                   pNumProperties,
+       VkSparseImageFormatProperties*              pProperties)
+{
+       /* Sparse images are not yet supported. */
+       *pNumProperties = 0;
+}
+
+//void libresoc_GetPhysicalDeviceSparseImageFormatProperties2(
+//     VkPhysicalDevice                            physicalDevice,
+//     const VkPhysicalDeviceSparseImageFormatInfo2 *pFormatInfo,
+//     uint32_t                                   *pPropertyCount,
+//     VkSparseImageFormatProperties2             *pProperties)
+//{
+//     /* Sparse images are not yet supported. */
+//     *pPropertyCount = 0;
+//}
+
+
+//void libresoc_GetPhysicalDeviceExternalBufferProperties(
+//     VkPhysicalDevice                            physicalDevice,
+//     const VkPhysicalDeviceExternalBufferInfo    *pExternalBufferInfo,
+//     VkExternalBufferProperties                  *pExternalBufferProperties)
+//{
+//     VkExternalMemoryFeatureFlagBits flags = 0;
+//     VkExternalMemoryHandleTypeFlags export_flags = 0;
+//     VkExternalMemoryHandleTypeFlags compat_flags = 0;
+//     switch(pExternalBufferInfo->handleType) {
+//     case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:
+//     case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
+//             flags = VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT |
+//                     VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
+//             compat_flags = export_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT |
+//                                           VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
+//             break;
+//     case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT:
+//             flags = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
+//             compat_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT;
+//             break;
+//     default:
+//             break;
+//     }
+//     pExternalBufferProperties->externalMemoryProperties = (VkExternalMemoryProperties) {
+//             .externalMemoryFeatures = flags,
+//             .exportFromImportedHandleTypes = export_flags,
+//             .compatibleHandleTypes = compat_flags,
+//     };
+//}
+
diff --git a/src/libre-soc/vulkan/libresoc_image.c b/src/libre-soc/vulkan/libresoc_image.c
new file mode 100644 (file)
index 0000000..46b9acb
--- /dev/null
@@ -0,0 +1,159 @@
+
+/*
+ * Copyright © 2016 Red Hat.
+ * Copyright © 2016 Bas Nieuwenhuizen
+ *
+ * based in part on anv driver which is:
+ * Copyright © 2015 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "vk_util.h"
+#include "libresoc_private.h"
+
+
+VkResult
+libresoc_image_create(VkDevice _device,
+                 const struct libresoc_image_create_info *create_info,
+                 const VkAllocationCallbacks* alloc,
+                 VkImage *pImage)
+{
+       LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
+       const VkImageCreateInfo *pCreateInfo = create_info->vk_info;
+       struct libresoc_image *image = NULL;
+       assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO);
+
+       // const unsigned plane_count = vk_format_get_plane_count(format);
+       // const size_t image_struct_size = sizeof(*image) + sizeof(struct libresoc_image_plane) * plane_count;
+
+       const size_t image_struct_size = sizeof(*image);
+       // libresoc_assert(pCreateInfo->mipLevels > 0);
+       // libresoc_assert(pCreateInfo->arrayLayers > 0);
+       // libresoc_assert(pCreateInfo->samples > 0);
+       // libresoc_assert(pCreateInfo->extent.width > 0);
+       // libresoc_assert(pCreateInfo->extent.height > 0);
+       // libresoc_assert(pCreateInfo->extent.depth > 0);
+
+       image = vk_zalloc2(&device->vk.alloc, alloc, image_struct_size, 8,
+                          VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+       if (!image)
+               return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
+
+       vk_object_base_init(&device->vk, &image->base, VK_OBJECT_TYPE_IMAGE);
+
+       image->type = pCreateInfo->imageType;
+       // image->info.width = pCreateInfo->extent.width;
+       // image->info.height = pCreateInfo->extent.height;
+       // image->info.depth = pCreateInfo->extent.depth;
+       // image->info.samples = pCreateInfo->samples;
+       // image->info.storage_samples = pCreateInfo->samples;
+       // image->info.array_size = pCreateInfo->arrayLayers;
+       // image->info.levels = pCreateInfo->mipLevels;
+       // image->info.num_channels = vk_format_get_nr_components(format);
+
+       //image->vk_format = format;
+       image->tiling = pCreateInfo->tiling;
+       image->usage = pCreateInfo->usage;
+       image->flags = pCreateInfo->flags;
+       //image->plane_count = plane_count;
+
+       image->exclusive = pCreateInfo->sharingMode == VK_SHARING_MODE_EXCLUSIVE;
+       // if (pCreateInfo->sharingMode == VK_SHARING_MODE_CONCURRENT) {
+       //      for (uint32_t i = 0; i < pCreateInfo->queueFamilyIndexCount; ++i)
+       //              if (pCreateInfo->pQueueFamilyIndices[i] == VK_QUEUE_FAMILY_EXTERNAL ||
+       //                  pCreateInfo->pQueueFamilyIndices[i] == VK_QUEUE_FAMILY_FOREIGN_EXT)
+       //                      image->queue_family_mask |= (1u << LIBRESOC_MAX_QUEUE_FAMILIES) - 1u;
+       //              else
+       //                      image->queue_family_mask |= 1u << pCreateInfo->pQueueFamilyIndices[i];
+       // }
+
+       // const VkExternalMemoryImageCreateInfo *external_info =
+       //      vk_find_struct_const(pCreateInfo->pNext,
+       //                           EXTERNAL_MEMORY_IMAGE_CREATE_INFO) ;
+
+       // image->shareable = external_info;
+       // if (!vk_format_is_depth_or_stencil(format) && !image->shareable) {
+       //      image->info.surf_index = &device->image_mrt_offset_counter;
+       // }
+
+       // for (unsigned plane = 0; plane < image->plane_count; ++plane) {
+       //      image->planes[plane].surface.flags =
+       //              libresoc_get_surface_flags(device, image, plane, pCreateInfo, format);
+       // }
+
+       // bool delay_layout = external_info &&
+       //      (external_info->handleTypes & VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID);
+
+       // if (delay_layout) {
+       //      *pImage = libresoc_image_to_handle(image);
+       //      assert (!(image->flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT));
+       //      return VK_SUCCESS;
+       // }
+
+       // ASSERTED VkResult result = libresoc_image_create_layout(device, *create_info, image);
+       // assert(result == VK_SUCCESS);
+
+       // if (image->flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT) {
+       //      image->alignment = MAX2(image->alignment, 4096);
+       //      image->size = align64(image->size, image->alignment);
+       //      image->offset = 0;
+
+       //      image->bo = device->ws->buffer_create(device->ws, image->size, image->alignment,
+       //                                            0, RADEON_FLAG_VIRTUAL, LIBRESOC_BO_PRIORITY_VIRTUAL);
+       //      if (!image->bo) {
+       //              libresoc_destroy_image(device, alloc, image);
+       //              return vk_error(device->instance, VK_ERROR_OUT_OF_DEVICE_MEMORY);
+       //      }
+       // }
+
+       *pImage = libresoc_image_to_handle(image);
+
+       return VK_SUCCESS;
+}
+
+
+VkResult
+libresoc_CreateImage(VkDevice device,
+                const VkImageCreateInfo *pCreateInfo,
+                const VkAllocationCallbacks *pAllocator,
+                VkImage *pImage)
+{
+
+       const struct wsi_image_create_info *wsi_info =
+               vk_find_struct_const(pCreateInfo->pNext, WSI_IMAGE_CREATE_INFO_MESA);
+       bool scanout = wsi_info && wsi_info->scanout;
+
+       return libresoc_image_create(device,
+                                &(struct libresoc_image_create_info) {
+                                        .vk_info = pCreateInfo,
+                                        .scanout = scanout,
+                                },
+                                pAllocator,
+                                pImage);
+}
+void libresoc_GetImageSubresourceLayout(
+       VkDevice                                    _device,
+       VkImage                                     _image,
+       const VkImageSubresource*                   pSubresource,
+       VkSubresourceLayout*                        pLayout)
+{
+//TODO: stub
+}
diff --git a/src/libre-soc/vulkan/libresoc_meta_clear.c b/src/libre-soc/vulkan/libresoc_meta_clear.c
new file mode 100644 (file)
index 0000000..a0a0f41
--- /dev/null
@@ -0,0 +1,36 @@
+
+/*
+ * Copyright © 2015 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "libresoc_private.h"
+
+void libresoc_CmdClearColorImage(
+       VkCommandBuffer                             commandBuffer,
+       VkImage                                     image_h,
+       VkImageLayout                               imageLayout,
+       const VkClearColorValue*                    pColor,
+       uint32_t                                    rangeCount,
+       const VkImageSubresourceRange*              pRanges)
+{
+//TODO: stub
+}
diff --git a/src/libre-soc/vulkan/libresoc_pipeline_cache.c b/src/libre-soc/vulkan/libresoc_pipeline_cache.c
new file mode 100644 (file)
index 0000000..e00dde6
--- /dev/null
@@ -0,0 +1,646 @@
+/*
+ * Copyright © 2015 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "util/mesa-sha1.h"
+#include "util/debug.h"
+#include "util/disk_cache.h"
+#include "util/u_atomic.h"
+#include "libresoc_debug.h"
+#include "libresoc_private.h"
+//#include "libresoc_shader.h"
+#include "vulkan/util/vk_util.h"
+
+//#include "ac_nir_to_llvm.h"
+
+struct cache_entry {
+       union {
+               unsigned char sha1[20];
+               uint32_t sha1_dw[5];
+       };
+       uint32_t binary_sizes[MESA_SHADER_STAGES];
+       struct libresoc_shader_variant *variants[MESA_SHADER_STAGES];
+       char code[0];
+};
+
+static void
+libresoc_pipeline_cache_lock(struct libresoc_pipeline_cache *cache)
+{
+       if (cache->flags & VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT_EXT)
+               return;
+
+       pthread_mutex_lock(&cache->mutex);
+}
+
+static void
+libresoc_pipeline_cache_unlock(struct libresoc_pipeline_cache *cache)
+{
+       if (cache->flags & VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT_EXT)
+               return;
+
+       pthread_mutex_unlock(&cache->mutex);
+}
+
+void
+libresoc_pipeline_cache_init(struct libresoc_pipeline_cache *cache,
+                        struct libresoc_device *device)
+{
+       cache->device = device;
+       pthread_mutex_init(&cache->mutex, NULL);
+       cache->flags = 0;
+
+       cache->modified = false;
+       cache->kernel_count = 0;
+       cache->total_size = 0;
+       cache->table_size = 1024;
+       const size_t byte_size = cache->table_size * sizeof(cache->hash_table[0]);
+       cache->hash_table = malloc(byte_size);
+
+       /* We don't consider allocation failure fatal, we just start with a 0-sized
+        * cache. Disable caching when we want to keep shader debug info, since
+        * we don't get the debug info on cached shaders. */
+       if (cache->hash_table == NULL ||
+           (device->instance->debug_flags & LIBRESOC_DEBUG_NO_CACHE))
+               cache->table_size = 0;
+       else
+               memset(cache->hash_table, 0, byte_size);
+}
+
+void
+libresoc_pipeline_cache_finish(struct libresoc_pipeline_cache *cache)
+{
+       for (unsigned i = 0; i < cache->table_size; ++i)
+               if (cache->hash_table[i]) {
+                       for(int j = 0; j < MESA_SHADER_STAGES; ++j)  {
+                               // TODO: uncomment following lines
+                               //if (cache->hash_table[i]->variants[j])
+                               //      libresoc_shader_variant_destroy(cache->device,
+                               //                                  cache->hash_table[i]->variants[j]);
+                       }
+                       vk_free(&cache->alloc, cache->hash_table[i]);
+               }
+       pthread_mutex_destroy(&cache->mutex);
+       free(cache->hash_table);
+}
+
+static uint32_t
+entry_size(struct cache_entry *entry)
+{
+       size_t ret = sizeof(*entry);
+       for (int i = 0; i < MESA_SHADER_STAGES; ++i)
+               if (entry->binary_sizes[i])
+                       ret += entry->binary_sizes[i];
+       return ret;
+}
+
+/*
+void
+libresoc_hash_shaders(unsigned char *hash,
+                 const VkPipelineShaderStageCreateInfo **stages,
+                 const struct libresoc_pipeline_layout *layout,
+                 const struct libresoc_pipeline_key *key,
+                 uint32_t flags)
+{
+       struct mesa_sha1 ctx;
+
+       _mesa_sha1_init(&ctx);
+       if (key)
+               _mesa_sha1_update(&ctx, key, sizeof(*key));
+       if (layout)
+               _mesa_sha1_update(&ctx, layout->sha1, sizeof(layout->sha1));
+
+       for (int i = 0; i < MESA_SHADER_STAGES; ++i) {
+               if (stages[i]) {
+                       LIBRESOC_FROM_HANDLE(libresoc_shader_module, module, stages[i]->module);
+                       const VkSpecializationInfo *spec_info = stages[i]->pSpecializationInfo;
+
+                       _mesa_sha1_update(&ctx, module->sha1, sizeof(module->sha1));
+                       _mesa_sha1_update(&ctx, stages[i]->pName, strlen(stages[i]->pName));
+                       if (spec_info) {
+                               _mesa_sha1_update(&ctx, spec_info->pMapEntries,
+                                                 spec_info->mapEntryCount * sizeof spec_info->pMapEntries[0]);
+                               _mesa_sha1_update(&ctx, spec_info->pData, spec_info->dataSize);
+                       }
+               }
+       }
+       _mesa_sha1_update(&ctx, &flags, 4);
+       _mesa_sha1_final(&ctx, hash);
+}*/
+
+
+static struct cache_entry *
+libresoc_pipeline_cache_search_unlocked(struct libresoc_pipeline_cache *cache,
+                                   const unsigned char *sha1)
+{
+       const uint32_t mask = cache->table_size - 1;
+       const uint32_t start = (*(uint32_t *) sha1);
+
+       if (cache->table_size == 0)
+               return NULL;
+
+       for (uint32_t i = 0; i < cache->table_size; i++) {
+               const uint32_t index = (start + i) & mask;
+               struct cache_entry *entry = cache->hash_table[index];
+
+               if (!entry)
+                       return NULL;
+
+               if (memcmp(entry->sha1, sha1, sizeof(entry->sha1)) == 0) {
+                       return entry;
+               }
+       }
+
+       unreachable("hash table should never be full");
+}
+
+static struct cache_entry *
+libresoc_pipeline_cache_search(struct libresoc_pipeline_cache *cache,
+                          const unsigned char *sha1)
+{
+       struct cache_entry *entry;
+
+       libresoc_pipeline_cache_lock(cache);
+
+       entry = libresoc_pipeline_cache_search_unlocked(cache, sha1);
+
+       libresoc_pipeline_cache_unlock(cache);
+
+       return entry;
+}
+
+static void
+libresoc_pipeline_cache_set_entry(struct libresoc_pipeline_cache *cache,
+                             struct cache_entry *entry)
+{
+       const uint32_t mask = cache->table_size - 1;
+       const uint32_t start = entry->sha1_dw[0];
+
+       /* We'll always be able to insert when we get here. */
+       assert(cache->kernel_count < cache->table_size / 2);
+
+       for (uint32_t i = 0; i < cache->table_size; i++) {
+               const uint32_t index = (start + i) & mask;
+               if (!cache->hash_table[index]) {
+                       cache->hash_table[index] = entry;
+                       break;
+               }
+       }
+
+       cache->total_size += entry_size(entry);
+       cache->kernel_count++;
+}
+
+
+static VkResult
+libresoc_pipeline_cache_grow(struct libresoc_pipeline_cache *cache)
+{
+       const uint32_t table_size = cache->table_size * 2;
+       const uint32_t old_table_size = cache->table_size;
+       const size_t byte_size = table_size * sizeof(cache->hash_table[0]);
+       struct cache_entry **table;
+       struct cache_entry **old_table = cache->hash_table;
+
+       table = malloc(byte_size);
+       if (table == NULL)
+               return vk_error(cache->device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
+
+       cache->hash_table = table;
+       cache->table_size = table_size;
+       cache->kernel_count = 0;
+       cache->total_size = 0;
+
+       memset(cache->hash_table, 0, byte_size);
+       for (uint32_t i = 0; i < old_table_size; i++) {
+               struct cache_entry *entry = old_table[i];
+               if (!entry)
+                       continue;
+
+               libresoc_pipeline_cache_set_entry(cache, entry);
+       }
+
+       free(old_table);
+
+       return VK_SUCCESS;
+}
+
+static void
+libresoc_pipeline_cache_add_entry(struct libresoc_pipeline_cache *cache,
+                             struct cache_entry *entry)
+{
+       if (cache->kernel_count == cache->table_size / 2)
+               libresoc_pipeline_cache_grow(cache);
+
+       /* Failing to grow that hash table isn't fatal, but may mean we don't
+        * have enough space to add this new kernel. Only add it if there's room.
+        */
+       if (cache->kernel_count < cache->table_size / 2)
+               libresoc_pipeline_cache_set_entry(cache, entry);
+}
+
+static bool
+libresoc_is_cache_disabled(struct libresoc_device *device)
+{
+       /* Pipeline caches can be disabled with LIBRESOC_DEBUG=nocache, with
+        * MESA_GLSL_CACHE_DISABLE=1, and when VK_AMD_shader_info is requested.
+        */
+       return (device->instance->debug_flags & LIBRESOC_DEBUG_NO_CACHE);
+}
+
+/*
+bool
+libresoc_create_shader_variants_from_pipeline_cache(struct libresoc_device *device,
+                                               struct libresoc_pipeline_cache *cache,
+                                               const unsigned char *sha1,
+                                               struct libresoc_shader_variant **variants,
+                                               bool *found_in_application_cache)
+{
+       struct cache_entry *entry;
+
+       if (!cache) {
+               cache = device->mem_cache;
+               *found_in_application_cache = false;
+       }
+
+       libresoc_pipeline_cache_lock(cache);
+
+       entry = libresoc_pipeline_cache_search_unlocked(cache, sha1);
+
+       if (!entry) {
+               *found_in_application_cache = false;
+
+*/             /* Don't cache when we want debug info, since this isn't
+                * present in the cache.
+                */
+/*             if (libresoc_is_cache_disabled(device) || !device->physical_device->disk_cache) {
+                       libresoc_pipeline_cache_unlock(cache);
+                       return false;
+               }
+
+               uint8_t disk_sha1[20];
+               disk_cache_compute_key(device->physical_device->disk_cache,
+                                      sha1, 20, disk_sha1);
+
+               entry = (struct cache_entry *)
+                       disk_cache_get(device->physical_device->disk_cache,
+                                      disk_sha1, NULL);
+               if (!entry) {
+                       libresoc_pipeline_cache_unlock(cache);
+                       return false;
+               } else {
+                       size_t size = entry_size(entry);
+                       struct cache_entry *new_entry = vk_alloc(&cache->alloc, size, 8,
+                                                                VK_SYSTEM_ALLOCATION_SCOPE_CACHE);
+                       if (!new_entry) {
+                               free(entry);
+                               libresoc_pipeline_cache_unlock(cache);
+                               return false;
+                       }
+
+                       memcpy(new_entry, entry, entry_size(entry));
+                       free(entry);
+                       entry = new_entry;
+
+                       if (!(device->instance->debug_flags & LIBRESOC_DEBUG_NO_MEMORY_CACHE) ||
+                           cache != device->mem_cache)
+                               libresoc_pipeline_cache_add_entry(cache, new_entry);
+               }
+       }
+
+       char *p = entry->code;
+       for(int i = 0; i < MESA_SHADER_STAGES; ++i) {
+               if (!entry->variants[i] && entry->binary_sizes[i]) {
+                       struct libresoc_shader_binary *binary = calloc(1, entry->binary_sizes[i]);
+                       memcpy(binary, p, entry->binary_sizes[i]);
+                       p += entry->binary_sizes[i];
+
+                       entry->variants[i] = libresoc_shader_variant_create(device, binary, false);
+                       free(binary);
+               } else if (entry->binary_sizes[i]) {
+                       p += entry->binary_sizes[i];
+               }
+
+       }
+
+       memcpy(variants, entry->variants, sizeof(entry->variants));
+
+       if (device->instance->debug_flags & LIBRESOC_DEBUG_NO_MEMORY_CACHE &&
+           cache == device->mem_cache)
+               vk_free(&cache->alloc, entry);
+       else {
+               for (int i = 0; i < MESA_SHADER_STAGES; ++i)
+                       if (entry->variants[i])
+                               p_atomic_inc(&entry->variants[i]->ref_count);
+       }
+
+       libresoc_pipeline_cache_unlock(cache);
+       return true;
+}*/
+
+/*
+void
+libresoc_pipeline_cache_insert_shaders(struct libresoc_device *device,
+                                  struct libresoc_pipeline_cache *cache,
+                                  const unsigned char *sha1,
+                                  struct libresoc_shader_variant **variants,
+                                  struct libresoc_shader_binary *const *binaries)
+{
+       if (!cache)
+               cache = device->mem_cache;
+
+       libresoc_pipeline_cache_lock(cache);
+       struct cache_entry *entry = libresoc_pipeline_cache_search_unlocked(cache, sha1);
+       if (entry) {
+               for (int i = 0; i < MESA_SHADER_STAGES; ++i) {
+                       if (entry->variants[i]) {
+                               libresoc_shader_variant_destroy(cache->device, variants[i]);
+                               variants[i] = entry->variants[i];
+                       } else {
+                               entry->variants[i] = variants[i];
+                       }
+                       if (variants[i])
+                               p_atomic_inc(&variants[i]->ref_count);
+               }
+               libresoc_pipeline_cache_unlock(cache);
+               return;
+       }
+
+*/     /* Don't cache when we want debug info, since this isn't
+        * present in the cache.
+        */
+/*     if (libresoc_is_cache_disabled(device)) {
+               libresoc_pipeline_cache_unlock(cache);
+               return;
+       }
+
+       size_t size = sizeof(*entry);
+       for (int i = 0; i < MESA_SHADER_STAGES; ++i)
+               if (variants[i])
+                       size += binaries[i]->total_size;
+
+
+       entry = vk_alloc(&cache->alloc, size, 8,
+                          VK_SYSTEM_ALLOCATION_SCOPE_CACHE);
+       if (!entry) {
+               libresoc_pipeline_cache_unlock(cache);
+               return;
+       }
+
+       memset(entry, 0, sizeof(*entry));
+       memcpy(entry->sha1, sha1, 20);
+
+       char* p = entry->code;
+
+       for (int i = 0; i < MESA_SHADER_STAGES; ++i) {
+               if (!variants[i])
+                       continue;
+
+               entry->binary_sizes[i] = binaries[i]->total_size;
+
+               memcpy(p, binaries[i], binaries[i]->total_size);
+               p += binaries[i]->total_size;
+       }
+
+*/     /* Always add cache items to disk. This will allow collection of
+        * compiled shaders by third parties such as steam, even if the app
+        * implements its own pipeline cache.
+        */
+/*     if (device->physical_device->disk_cache) {
+               uint8_t disk_sha1[20];
+               disk_cache_compute_key(device->physical_device->disk_cache, sha1, 20,
+                              disk_sha1);
+
+               disk_cache_put(device->physical_device->disk_cache, disk_sha1,
+                              entry, entry_size(entry), NULL);
+       }
+
+       if (device->instance->debug_flags & LIBRESOC_DEBUG_NO_MEMORY_CACHE &&
+           cache == device->mem_cache) {
+               vk_free2(&cache->alloc, NULL, entry);
+               libresoc_pipeline_cache_unlock(cache);
+               return;
+       }
+
+*/     /* We delay setting the variant so we have reproducible disk cache
+        * items.
+        */
+/*     for (int i = 0; i < MESA_SHADER_STAGES; ++i) {
+               if (!variants[i])
+                       continue;
+
+               entry->variants[i] = variants[i];
+               p_atomic_inc(&variants[i]->ref_count);
+       }
+
+       libresoc_pipeline_cache_add_entry(cache, entry);
+
+       cache->modified = true;
+       libresoc_pipeline_cache_unlock(cache);
+       return;
+}*/
+
+bool
+libresoc_pipeline_cache_load(struct libresoc_pipeline_cache *cache,
+                        const void *data, size_t size)
+{
+       struct libresoc_device *device = cache->device;
+       struct vk_pipeline_cache_header header;
+
+       if (size < sizeof(header))
+               return false;
+       memcpy(&header, data, sizeof(header));
+       if (header.header_size < sizeof(header))
+               return false;
+       if (header.header_version != VK_PIPELINE_CACHE_HEADER_VERSION_ONE)
+               return false;
+       if (header.vendor_id != 1) //TODO: just dummy value
+               return false;
+       if (header.device_id != 1) //TODO: just dummy value
+               return false;
+       if (memcmp(header.uuid, device->physical_device->cache_uuid, VK_UUID_SIZE) != 0)
+               return false;
+
+       char *end = (void *) data + size;
+       char *p = (void *) data + header.header_size;
+
+       while (end - p >= sizeof(struct cache_entry)) {
+               struct cache_entry *entry = (struct cache_entry*)p;
+               struct cache_entry *dest_entry;
+               size_t size = entry_size(entry);
+               if(end - p < size)
+                       break;
+
+               dest_entry = vk_alloc(&cache->alloc, size,
+                                       8, VK_SYSTEM_ALLOCATION_SCOPE_CACHE);
+               if (dest_entry) {
+                       memcpy(dest_entry, entry, size);
+                       for (int i = 0; i < MESA_SHADER_STAGES; ++i)
+                               dest_entry->variants[i] = NULL;
+                       libresoc_pipeline_cache_add_entry(cache, dest_entry);
+               }
+               p += size;
+       }
+
+       return true;
+}
+
+VkResult libresoc_CreatePipelineCache(
+       VkDevice                                    _device,
+       const VkPipelineCacheCreateInfo*            pCreateInfo,
+       const VkAllocationCallbacks*                pAllocator,
+       VkPipelineCache*                            pPipelineCache)
+{
+       LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
+       struct libresoc_pipeline_cache *cache;
+
+       assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO);
+       assert(pCreateInfo->flags == 0);
+
+       cache = vk_alloc2(&device->vk.alloc, pAllocator,
+                           sizeof(*cache), 8,
+                           VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+       if (cache == NULL)
+               return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
+
+       vk_object_base_init(&device->vk, &cache->base,
+                           VK_OBJECT_TYPE_PIPELINE_CACHE);
+
+       if (pAllocator)
+               cache->alloc = *pAllocator;
+       else
+               cache->alloc = device->vk.alloc;
+
+       libresoc_pipeline_cache_init(cache, device);
+       cache->flags = pCreateInfo->flags;
+
+       /*if (pCreateInfo->initialDataSize > 0) {
+               libresoc_pipeline_cache_load(cache,
+                                        pCreateInfo->pInitialData,
+                                        pCreateInfo->initialDataSize);
+       }*/
+
+       *pPipelineCache = libresoc_pipeline_cache_to_handle(cache);
+
+       return VK_SUCCESS;
+}
+
+void libresoc_DestroyPipelineCache(
+       VkDevice                                    _device,
+       VkPipelineCache                             _cache,
+       const VkAllocationCallbacks*                pAllocator)
+{
+       LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
+       LIBRESOC_FROM_HANDLE(libresoc_pipeline_cache, cache, _cache);
+
+       if (!cache)
+               return;
+       libresoc_pipeline_cache_finish(cache);
+
+       vk_object_base_finish(&cache->base);
+       vk_free2(&device->vk.alloc, pAllocator, cache);
+}
+
+VkResult libresoc_GetPipelineCacheData(
+       VkDevice                                    _device,
+       VkPipelineCache                             _cache,
+       size_t*                                     pDataSize,
+       void*                                       pData)
+{
+       LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
+       LIBRESOC_FROM_HANDLE(libresoc_pipeline_cache, cache, _cache);
+       struct vk_pipeline_cache_header *header;
+       VkResult result = VK_SUCCESS;
+
+       libresoc_pipeline_cache_lock(cache);
+
+       const size_t size = sizeof(*header) + cache->total_size;
+       if (pData == NULL) {
+               libresoc_pipeline_cache_unlock(cache);
+               *pDataSize = size;
+               return VK_SUCCESS;
+       }
+       if (*pDataSize < sizeof(*header)) {
+               libresoc_pipeline_cache_unlock(cache);
+               *pDataSize = 0;
+               return VK_INCOMPLETE;
+       }
+       void *p = pData, *end = pData + *pDataSize;
+       header = p;
+       header->header_size = sizeof(*header);
+       header->header_version = VK_PIPELINE_CACHE_HEADER_VERSION_ONE;
+       header->vendor_id = 1; //TODO: some dummy value
+       header->device_id = 1; //TODO: some dummy value
+       memcpy(header->uuid, device->physical_device->cache_uuid, VK_UUID_SIZE);
+       p += header->header_size;
+
+       struct cache_entry *entry;
+       for (uint32_t i = 0; i < cache->table_size; i++) {
+               if (!cache->hash_table[i])
+                       continue;
+               entry = cache->hash_table[i];
+               const uint32_t size = entry_size(entry);
+               if (end < p + size) {
+                       result = VK_INCOMPLETE;
+                       break;
+               }
+
+               memcpy(p, entry, size);
+               for(int j = 0; j < MESA_SHADER_STAGES; ++j)
+                       ((struct cache_entry*)p)->variants[j] = NULL;
+               p += size;
+       }
+       *pDataSize = p - pData;
+
+       libresoc_pipeline_cache_unlock(cache);
+       return result;
+}
+
+static void
+libresoc_pipeline_cache_merge(struct libresoc_pipeline_cache *dst,
+                         struct libresoc_pipeline_cache *src)
+{
+       for (uint32_t i = 0; i < src->table_size; i++) {
+               struct cache_entry *entry = src->hash_table[i];
+               if (!entry || libresoc_pipeline_cache_search(dst, entry->sha1))
+                       continue;
+
+               libresoc_pipeline_cache_add_entry(dst, entry);
+
+               src->hash_table[i] = NULL;
+       }
+}
+
+VkResult libresoc_MergePipelineCaches(
+       VkDevice                                    _device,
+       VkPipelineCache                             destCache,
+       uint32_t                                    srcCacheCount,
+       const VkPipelineCache*                      pSrcCaches)
+{
+       LIBRESOC_FROM_HANDLE(libresoc_pipeline_cache, dst, destCache);
+
+       for (uint32_t i = 0; i < srcCacheCount; i++) {
+               LIBRESOC_FROM_HANDLE(libresoc_pipeline_cache, src, pSrcCaches[i]);
+
+               libresoc_pipeline_cache_merge(dst, src);
+       }
+
+       return VK_SUCCESS;
+}
index 60f12937448a0dc5dbfb7a0887d65c8b962d7eaa..0c2d1e5eea258170594364870e4842e8857d1ec4 100644 (file)
 #include "libresoc_constants.h"
 #include "libresoc_debug.h"
 
+#include "wsi_common.h"
 #define LIBRESOC_MAX_QUEUE_FAMILIES 1 
+
+static inline uint32_t
+align_u32(uint32_t v, uint32_t a)
+{
+       assert(a != 0 && a == (a & -a));
+       return (v + a - 1) & ~(a - 1);
+}
+
+static inline uint32_t
+align_u32_npot(uint32_t v, uint32_t a)
+{
+       return (v + a - 1) / a * a;
+}
+
+static inline uint64_t
+align_u64(uint64_t v, uint64_t a)
+{
+       assert(a != 0 && a == (a & -a));
+       return (v + a - 1) & ~(a - 1);
+}
+
+static inline int32_t
+align_i32(int32_t v, int32_t a)
+{
+       assert(a != 0 && a == (a & -a));
+       return (v + a - 1) & ~(a - 1);
+}
+
+/** Alignment must be a power of 2. */
+static inline bool
+libresoc_is_aligned(uintmax_t n, uintmax_t a)
+{
+       assert(a == (a & -a));
+       return (n & (a - 1)) == 0;
+}
+
+static inline uint32_t
+round_up_u32(uint32_t v, uint32_t a)
+{
+       return (v + a - 1) / a;
+}
+
+static inline uint64_t
+round_up_u64(uint64_t v, uint64_t a)
+{
+       return (v + a - 1) / a;
+}
+
+static inline uint32_t
+libresoc_minify(uint32_t n, uint32_t levels)
+{
+       if (unlikely(n == 0))
+               return 0;
+       else
+               return MAX2(n >> levels, 1);
+}
+static inline float
+libresoc_clamp_f(float f, float min, float max)
+{
+       assert(min < max);
+
+       if (f > max)
+               return max;
+       else if (f < min)
+               return min;
+       else
+               return f;
+}
+
+static inline bool
+libresoc_clear_mask(uint32_t *inout_mask, uint32_t clear_mask)
+{
+       if (*inout_mask & clear_mask) {
+               *inout_mask &= ~clear_mask;
+               return true;
+       } else {
+               return false;
+       }
+}
+
+struct libresoc_fence {
+       struct vk_object_base base;
+};
+
+struct libresoc_image_create_info {
+       const VkImageCreateInfo *vk_info;
+       bool scanout;
+       bool no_metadata_planes;
+};
+
+struct libresoc_image {
+       struct vk_object_base base;
+       VkImageType type;
+       /* The original VkFormat provided by the client.  This may not match any
+        * of the actual surface formats.
+        */
+       VkFormat vk_format;
+       VkImageAspectFlags aspects;
+       VkImageUsageFlags usage; /**< Superset of VkImageCreateInfo::usage. */
+       VkImageTiling tiling; /** VkImageCreateInfo::tiling */
+       VkImageCreateFlags flags; /** VkImageCreateInfo::flags */
+
+       VkDeviceSize size;
+       uint32_t alignment;
+
+       unsigned queue_family_mask;
+       bool exclusive;
+       bool shareable;
+
+};
+
+VkResult libresoc_image_create(VkDevice _device,
+                          const struct libresoc_image_create_info *info,
+                          const VkAllocationCallbacks* alloc,
+                          VkImage *pImage);
+
+struct libresoc_cmd_pool {
+       struct vk_object_base                        base;
+       VkAllocationCallbacks                        alloc;
+       struct list_head                             cmd_buffers;
+       struct list_head                             free_cmd_buffers;
+       uint32_t queue_family_index;
+};
+
+struct libresoc_semaphore {
+       struct vk_object_base base;
+};
+
 struct libresoc_instance;
 struct libresoc_device;
 struct cache_entry;
@@ -92,6 +221,10 @@ libresoc_pipeline_cache_insert_shaders(struct libresoc_device *device,
                                   const unsigned char *sha1,
                                   struct libresoc_shader_variant **variants,
                                   struct libresoc_shader_binary *const *binaries);
+
+VkResult libresoc_init_wsi(struct libresoc_physical_device *physical_device);
+void libresoc_finish_wsi(struct libresoc_physical_device *physical_device);
+
 struct libresoc_device {
 
    struct vk_device vk;
@@ -112,6 +245,10 @@ struct libresoc_device {
    /* Condition variable for legacy timelines, to notify waiters when a
     * new point gets submitted. */
    pthread_cond_t timeline_cond;
+   /* Overallocation. */
+   bool overallocation_disallowed;
+   uint64_t allocated_memory_size[VK_MAX_MEMORY_HEAPS];
+   mtx_t overallocation_mutex;
    /* FIXME: stub */
 };
 
@@ -121,7 +258,7 @@ struct libresoc_physical_device {
 
    struct list_head                            link;
    struct libresoc_instance *instance;
-
+   struct wsi_device wsi_device;
    struct libresoc_device_extension_table supported_extensions;
    struct libresoc_physical_device_dispatch_table dispatch;
 
@@ -129,6 +266,9 @@ struct libresoc_physical_device {
    uint8_t                                     driver_uuid[VK_UUID_SIZE];
    uint8_t                                     device_uuid[VK_UUID_SIZE];
    uint8_t                                     cache_uuid[VK_UUID_SIZE];
+   int local_fd;
+   int master_fd;
+   VkPhysicalDeviceMemoryProperties memory_properties;
    /* FIXME: stub */
 };
 
@@ -160,9 +300,12 @@ struct libresoc_instance {
    int physical_device_count;
    struct list_head physical_devices;
 
+   struct driOptionCache dri_options;
+   struct driOptionCache available_dri_options;
    struct vk_debug_report_instance debug_report_callbacks;
 };
 
+struct libresoc_deferred_queue_submission;
 struct libresoc_queue {
    VK_LOADER_DATA _loader_data;
 
@@ -174,16 +317,83 @@ struct libresoc_queue {
 
    struct list_head pending_submissions;
    pthread_mutex_t pending_mutex;
+   pthread_mutex_t thread_mutex;
+   pthread_cond_t thread_cond;
+   //struct libresoc_deferred_queue_submission *thread_submission;
+   pthread_t submission_thread;
+   bool thread_exit;
+   bool thread_running;
    /* FIXME: stub */
 };
 
+struct libresoc_cmd_buffer_upload {
+       uint8_t *map;
+       unsigned offset;
+       uint64_t size;
+       struct list_head list;
+};
+
+enum libresoc_cmd_buffer_status {
+       LIBRESOC_CMD_BUFFER_STATUS_INVALID,
+       LIBRESOC_CMD_BUFFER_STATUS_INITIAL,
+       LIBRESOC_CMD_BUFFER_STATUS_RECORDING,
+       LIBRESOC_CMD_BUFFER_STATUS_EXECUTABLE,
+       LIBRESOC_CMD_BUFFER_STATUS_PENDING,
+};
+
 struct libresoc_cmd_buffer {
+       struct vk_object_base                         base;
 
-   struct libresoc_device *device;
+       struct libresoc_device *                          device;
+
+       struct libresoc_cmd_pool *                        pool;
+       struct list_head                             pool_link;
+
+       VkCommandBufferUsageFlags                    usage_flags;
+       VkCommandBufferLevel                         level;
+       enum libresoc_cmd_buffer_status status;
+       //struct radeon_cmdbuf *cs;
+       // struct libresoc_cmd_state state;
+       // struct libresoc_vertex_binding                   vertex_bindings[MAX_VBS];
+       // struct libresoc_streamout_binding                streamout_bindings[MAX_SO_BUFFERS];
+       uint32_t queue_family_index;
+
+       uint8_t push_constants[MAX_PUSH_CONSTANTS_SIZE];
+       VkShaderStageFlags push_constant_stages;
+       // struct libresoc_descriptor_set meta_push_descriptors;
+
+       // struct libresoc_descriptor_state descriptors[MAX_BIND_POINTS];
+
+       struct libresoc_cmd_buffer_upload upload;
+
+       uint32_t scratch_size_per_wave_needed;
+       uint32_t scratch_waves_wanted;
+       uint32_t compute_scratch_size_per_wave_needed;
+       uint32_t compute_scratch_waves_wanted;
+       uint32_t esgs_ring_size_needed;
+       uint32_t gsvs_ring_size_needed;
+       bool tess_rings_needed;
+       bool sample_positions_needed;
+
+       VkResult record_result;
 
-   /* FIXME: stub */
 };
 
+struct libresoc_device_memory {
+       struct vk_object_base                        base;
+       /* for dedicated allocations */
+       struct libresoc_image                            *image;
+       //struct libresoc_buffer                           *buffer;
+       uint32_t                                     heap_index;
+       uint64_t                                     alloc_size;
+       void *                                       map;
+       void *                                       user_ptr;
+};
+
+void libresoc_free_memory(struct libresoc_device *device,
+                     const VkAllocationCallbacks* pAllocator,
+                     struct libresoc_device_memory *mem);
+
 uint32_t libresoc_physical_device_api_version(struct libresoc_physical_device *dev);
 
 int libresoc_get_instance_entrypoint_index(const char *name);
@@ -210,6 +420,65 @@ void *libresoc_lookup_entrypoint(const char *name);
 const char *
 libresoc_get_debug_option_name(int id);
 
+struct libresoc_binning_settings {
+       unsigned context_states_per_bin; /* allowed range: [1, 6] */
+       unsigned persistent_states_per_bin; /* allowed range: [1, 32] */
+       unsigned fpovs_per_batch; /* allowed range: [0, 255], 0 = unlimited */
+};
+
+struct libresoc_binning_settings
+libresoc_get_binning_settings(const struct libresoc_physical_device *pdev);
+
+struct vk_format_description;
+uint32_t libresoc_translate_buffer_dataformat(const struct vk_format_description *desc,
+                                         int first_non_void);
+uint32_t libresoc_translate_buffer_numformat(const struct vk_format_description *desc,
+                                        int first_non_void);
+bool libresoc_is_buffer_format_supported(VkFormat format, bool *scaled);
+uint32_t libresoc_translate_colorformat(VkFormat format);
+uint32_t libresoc_translate_color_numformat(VkFormat format,
+                                       const struct vk_format_description *desc,
+                                       int first_non_void);
+uint32_t libresoc_colorformat_endian_swap(uint32_t colorformat);
+unsigned libresoc_translate_colorswap(VkFormat format, bool do_endian_swap);
+uint32_t libresoc_translate_dbformat(VkFormat format);
+uint32_t libresoc_translate_tex_dataformat(VkFormat format,
+                                      const struct vk_format_description *desc,
+                                      int first_non_void);
+uint32_t libresoc_translate_tex_numformat(VkFormat format,
+                                     const struct vk_format_description *desc,
+                                     int first_non_void);
+bool libresoc_format_pack_clear_color(VkFormat format,
+                                 uint32_t clear_vals[2],
+                                 VkClearColorValue *value);
+bool libresoc_is_colorbuffer_format_supported(VkFormat format, bool *blendable);
+bool libresoc_dcc_formats_compatible(VkFormat format1,
+                                 VkFormat format2);
+bool libresoc_device_supports_etc(struct libresoc_physical_device *physical_device);
+
+
+/* Whether the image has a htile  that is known consistent with the contents of
+ * the image and is allowed to be in compressed form.
+ *
+ * If this is false reads that don't use the htile should be able to return
+ * correct results.
+ */
+bool libresoc_layout_is_htile_compressed(const struct libresoc_image *image,
+                                     VkImageLayout layout,
+                                     bool in_render_loop,
+                                     unsigned queue_mask);
+
+bool libresoc_layout_can_fast_clear(const struct libresoc_image *image,
+                               VkImageLayout layout,
+                               bool in_render_loop,
+                               unsigned queue_mask);
+
+bool libresoc_layout_dcc_compressed(const struct libresoc_device *device,
+                               const struct libresoc_image *image,
+                               VkImageLayout layout,
+                               bool in_render_loop,
+                               unsigned queue_mask);
+
 #define libresoc_printflike(a, b) __attribute__((__format__(__printf__, a, b)))
 
 VkResult __vk_errorf(struct libresoc_instance *instance, VkResult error,
@@ -259,18 +528,18 @@ LIBRESOC_DEFINE_HANDLE_CASTS(libresoc_instance, VkInstance)
 LIBRESOC_DEFINE_HANDLE_CASTS(libresoc_physical_device, VkPhysicalDevice)
 LIBRESOC_DEFINE_HANDLE_CASTS(libresoc_queue, VkQueue)
 
-//LIBRESOC_DEFINE_NONDISP_HANDLE_CASTS(libresoc_cmd_pool, VkCommandPool)
+LIBRESOC_DEFINE_NONDISP_HANDLE_CASTS(libresoc_cmd_pool, VkCommandPool)
 //LIBRESOC_DEFINE_NONDISP_HANDLE_CASTS(libresoc_buffer, VkBuffer)
 //LIBRESOC_DEFINE_NONDISP_HANDLE_CASTS(libresoc_buffer_view, VkBufferView)
 //LIBRESOC_DEFINE_NONDISP_HANDLE_CASTS(libresoc_descriptor_pool, VkDescriptorPool)
 //LIBRESOC_DEFINE_NONDISP_HANDLE_CASTS(libresoc_descriptor_set, VkDescriptorSet)
 //LIBRESOC_DEFINE_NONDISP_HANDLE_CASTS(libresoc_descriptor_set_layout, VkDescriptorSetLayout)
 //LIBRESOC_DEFINE_NONDISP_HANDLE_CASTS(libresoc_descriptor_update_template, VkDescriptorUpdateTemplate)
-//LIBRESOC_DEFINE_NONDISP_HANDLE_CASTS(libresoc_device_memory, VkDeviceMemory)
-//LIBRESOC_DEFINE_NONDISP_HANDLE_CASTS(libresoc_fence, VkFence)
+LIBRESOC_DEFINE_NONDISP_HANDLE_CASTS(libresoc_device_memory, VkDeviceMemory)
+LIBRESOC_DEFINE_NONDISP_HANDLE_CASTS(libresoc_fence, VkFence)
 //LIBRESOC_DEFINE_NONDISP_HANDLE_CASTS(libresoc_event, VkEvent)
 //LIBRESOC_DEFINE_NONDISP_HANDLE_CASTS(libresoc_framebuffer, VkFramebuffer)
-//LIBRESOC_DEFINE_NONDISP_HANDLE_CASTS(libresoc_image, VkImage)
+LIBRESOC_DEFINE_NONDISP_HANDLE_CASTS(libresoc_image, VkImage)
 //LIBRESOC_DEFINE_NONDISP_HANDLE_CASTS(libresoc_image_view, VkImageView);
 LIBRESOC_DEFINE_NONDISP_HANDLE_CASTS(libresoc_pipeline_cache, VkPipelineCache)
 //LIBRESOC_DEFINE_NONDISP_HANDLE_CASTS(libresoc_pipeline, VkPipeline)
@@ -280,6 +549,6 @@ LIBRESOC_DEFINE_NONDISP_HANDLE_CASTS(libresoc_pipeline_cache, VkPipelineCache)
 //LIBRESOC_DEFINE_NONDISP_HANDLE_CASTS(libresoc_sampler, VkSampler)
 //LIBRESOC_DEFINE_NONDISP_HANDLE_CASTS(libresoc_sampler_ycbcr_conversion, VkSamplerYcbcrConversion)
 //LIBRESOC_DEFINE_NONDISP_HANDLE_CASTS(libresoc_shader_module, VkShaderModule)
-//LIBRESOC_DEFINE_NONDISP_HANDLE_CASTS(libresoc_semaphore, VkSemaphore)
+LIBRESOC_DEFINE_NONDISP_HANDLE_CASTS(libresoc_semaphore, VkSemaphore)
 
 #endif /* LIBRESOC_PRIVATE_H */
diff --git a/src/libre-soc/vulkan/libresoc_wsi.c b/src/libre-soc/vulkan/libresoc_wsi.c
new file mode 100644 (file)
index 0000000..2cd0fa1
--- /dev/null
@@ -0,0 +1,351 @@
+/*
+ * Copyright © 2016 Red Hat
+ * based on intel anv code:
+ * Copyright © 2015 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "libresoc_private.h"
+//#include "libresoc_meta.h"
+#include "wsi_common.h"
+#include "vk_util.h"
+#include "util/macros.h"
+
+static PFN_vkVoidFunction
+libresoc_wsi_proc_addr(VkPhysicalDevice physicalDevice, const char *pName)
+{
+       return libresoc_lookup_entrypoint(pName);
+}
+
+static void
+libresoc_wsi_set_memory_ownership(VkDevice _device,
+                              VkDeviceMemory _mem,
+                              VkBool32 ownership)
+{
+       //TODO: enable when required
+       //LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
+       //LIBRESOC_FROM_HANDLE(libresoc_device_memory, mem, _mem);
+
+       //if (ownership)
+       //      libresoc_bo_list_add(device, mem->bo);
+       //else
+       //      libresoc_bo_list_remove(device, mem->bo);
+}
+
+VkResult
+libresoc_init_wsi(struct libresoc_physical_device *physical_device)
+{
+       //TODO: stub
+       //return VK_SUCCESS;
+       VkResult result =  wsi_device_init(&physical_device->wsi_device,
+                                          libresoc_physical_device_to_handle(physical_device),
+                                          libresoc_wsi_proc_addr,
+                                          &physical_device->instance->alloc,
+                                          physical_device->master_fd,
+                                          &physical_device->instance->dri_options,
+                                          true); //TODO: for now this is sw_device
+       if (result != VK_SUCCESS)
+               return result;
+
+       physical_device->wsi_device.set_memory_ownership = libresoc_wsi_set_memory_ownership;
+       return VK_SUCCESS;
+}
+
+void
+libresoc_finish_wsi(struct libresoc_physical_device *physical_device)
+{
+       wsi_device_finish(&physical_device->wsi_device,
+                         &physical_device->instance->alloc);
+}
+
+void libresoc_DestroySurfaceKHR(
+       VkInstance                                   _instance,
+       VkSurfaceKHR                                 _surface,
+       const VkAllocationCallbacks*                 pAllocator)
+{
+       LIBRESOC_FROM_HANDLE(libresoc_instance, instance, _instance);
+       ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
+
+       vk_free2(&instance->alloc, pAllocator, surface);
+}
+
+VkResult libresoc_GetPhysicalDeviceSurfaceSupportKHR(
+       VkPhysicalDevice                            physicalDevice,
+       uint32_t                                    queueFamilyIndex,
+       VkSurfaceKHR                                surface,
+       VkBool32*                                   pSupported)
+{
+       LIBRESOC_FROM_HANDLE(libresoc_physical_device, device, physicalDevice);
+
+       return wsi_common_get_surface_support(&device->wsi_device,
+                                             queueFamilyIndex,
+                                             surface,
+                                             pSupported);
+}
+
+VkResult libresoc_GetPhysicalDeviceSurfaceCapabilitiesKHR(
+       VkPhysicalDevice                            physicalDevice,
+       VkSurfaceKHR                                surface,
+       VkSurfaceCapabilitiesKHR*                   pSurfaceCapabilities)
+{
+       LIBRESOC_FROM_HANDLE(libresoc_physical_device, device, physicalDevice);
+
+       return wsi_common_get_surface_capabilities(&device->wsi_device,
+                                                  surface,
+                                                  pSurfaceCapabilities);
+}
+
+// VkResult libresoc_GetPhysicalDeviceSurfaceCapabilities2KHR(
+//     VkPhysicalDevice                            physicalDevice,
+//     const VkPhysicalDeviceSurfaceInfo2KHR*      pSurfaceInfo,
+//     VkSurfaceCapabilities2KHR*                  pSurfaceCapabilities)
+// {
+//     LIBRESOC_FROM_HANDLE(libresoc_physical_device, device, physicalDevice);
+
+//     return wsi_common_get_surface_capabilities2(&device->wsi_device,
+//                                                 pSurfaceInfo,
+//                                                 pSurfaceCapabilities);
+// }
+
+// VkResult libresoc_GetPhysicalDeviceSurfaceCapabilities2EXT(
+//     VkPhysicalDevice                            physicalDevice,
+//     VkSurfaceKHR                                surface,
+//     VkSurfaceCapabilities2EXT*                  pSurfaceCapabilities)
+// {
+//     LIBRESOC_FROM_HANDLE(libresoc_physical_device, device, physicalDevice);
+
+//     return wsi_common_get_surface_capabilities2ext(&device->wsi_device,
+//                                                    surface,
+//                                                    pSurfaceCapabilities);
+// }
+
+VkResult libresoc_GetPhysicalDeviceSurfaceFormatsKHR(
+       VkPhysicalDevice                            physicalDevice,
+       VkSurfaceKHR                                surface,
+       uint32_t*                                   pSurfaceFormatCount,
+       VkSurfaceFormatKHR*                         pSurfaceFormats)
+{
+       LIBRESOC_FROM_HANDLE(libresoc_physical_device, device, physicalDevice);
+
+       return wsi_common_get_surface_formats(&device->wsi_device,
+                                             surface,
+                                             pSurfaceFormatCount,
+                                             pSurfaceFormats);
+}
+
+// VkResult libresoc_GetPhysicalDeviceSurfaceFormats2KHR(
+//     VkPhysicalDevice                            physicalDevice,
+//     const VkPhysicalDeviceSurfaceInfo2KHR*      pSurfaceInfo,
+//     uint32_t*                                   pSurfaceFormatCount,
+//     VkSurfaceFormat2KHR*                        pSurfaceFormats)
+// {
+//     LIBRESOC_FROM_HANDLE(libresoc_physical_device, device, physicalDevice);
+
+//     return wsi_common_get_surface_formats2(&device->wsi_device,
+//                                            pSurfaceInfo,
+//                                            pSurfaceFormatCount,
+//                                            pSurfaceFormats);
+// }
+
+VkResult libresoc_GetPhysicalDeviceSurfacePresentModesKHR(
+       VkPhysicalDevice                            physicalDevice,
+       VkSurfaceKHR                                surface,
+       uint32_t*                                   pPresentModeCount,
+       VkPresentModeKHR*                           pPresentModes)
+{
+       LIBRESOC_FROM_HANDLE(libresoc_physical_device, device, physicalDevice);
+
+       return wsi_common_get_surface_present_modes(&device->wsi_device,
+                                                   surface,
+                                                   pPresentModeCount,
+                                                   pPresentModes);
+}
+
+VkResult libresoc_CreateSwapchainKHR(
+       VkDevice                                     _device,
+       const VkSwapchainCreateInfoKHR*              pCreateInfo,
+       const VkAllocationCallbacks*                 pAllocator,
+       VkSwapchainKHR*                              pSwapchain)
+{
+       LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
+       const VkAllocationCallbacks *alloc;
+       if (pAllocator)
+               alloc = pAllocator;
+       else
+               alloc = &device->vk.alloc;
+
+       return wsi_common_create_swapchain(&device->physical_device->wsi_device,
+                                          libresoc_device_to_handle(device),
+                                          pCreateInfo,
+                                          alloc,
+                                          pSwapchain);
+}
+
+void libresoc_DestroySwapchainKHR(
+       VkDevice                                     _device,
+       VkSwapchainKHR                               swapchain,
+       const VkAllocationCallbacks*                 pAllocator)
+{
+       LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
+       const VkAllocationCallbacks *alloc;
+
+       if (pAllocator)
+               alloc = pAllocator;
+       else
+               alloc = &device->vk.alloc;
+
+       wsi_common_destroy_swapchain(_device, swapchain, alloc);
+}
+
+VkResult libresoc_GetSwapchainImagesKHR(
+       VkDevice                                     device,
+       VkSwapchainKHR                               swapchain,
+       uint32_t*                                    pSwapchainImageCount,
+       VkImage*                                     pSwapchainImages)
+{
+       return wsi_common_get_images(swapchain,
+                                    pSwapchainImageCount,
+                                    pSwapchainImages);
+}
+
+VkResult libresoc_AcquireNextImageKHR(
+       VkDevice                                     device,
+       VkSwapchainKHR                               swapchain,
+       uint64_t                                     timeout,
+       VkSemaphore                                  semaphore,
+       VkFence                                      fence,
+       uint32_t*                                    pImageIndex)
+{
+       VkAcquireNextImageInfoKHR acquire_info = {
+               .sType = VK_STRUCTURE_TYPE_ACQUIRE_NEXT_IMAGE_INFO_KHR,
+               .swapchain = swapchain,
+               .timeout = timeout,
+               .semaphore = semaphore,
+               .fence = fence,
+               .deviceMask = 0,
+       };
+
+       return libresoc_AcquireNextImage2KHR(device, &acquire_info, pImageIndex);
+}
+
+VkResult libresoc_AcquireNextImage2KHR(
+       VkDevice                                     _device,
+       const VkAcquireNextImageInfoKHR*             pAcquireInfo,
+       uint32_t*                                    pImageIndex)
+{
+       LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
+       struct libresoc_physical_device *pdevice = device->physical_device;
+       //LIBRESOC_FROM_HANDLE(libresoc_fence, fence, pAcquireInfo->fence);
+       //LIBRESOC_FROM_HANDLE(libresoc_semaphore, semaphore, pAcquireInfo->semaphore);
+
+       VkResult result = wsi_common_acquire_next_image2(&pdevice->wsi_device,
+                                                        _device,
+                                                         pAcquireInfo,
+                                                        pImageIndex);
+       //TODO: enable if required
+       // if (result == VK_SUCCESS || result == VK_SUBOPTIMAL_KHR) {
+       //      if (fence) {
+       //              struct libresoc_fence_part *part =
+       //                      fence->temporary.kind != LIBRESOC_FENCE_NONE ?
+       //                      &fence->temporary : &fence->permanent;
+
+       //              switch (part->kind) {
+       //              case LIBRESOC_FENCE_NONE:
+       //                      break;
+       //              case LIBRESOC_FENCE_WINSYS:
+       //                      device->ws->signal_fence(part->fence);
+       //                      break;
+       //              case LIBRESOC_FENCE_SYNCOBJ:
+       //                      device->ws->signal_syncobj(device->ws, part->syncobj, 0);
+       //                      break;
+       //              default:
+       //                      unreachable("Invalid WSI fence type");
+       //              }
+       //      }
+       //      if (semaphore) {
+       //              struct libresoc_semaphore_part *part =
+       //                      semaphore->temporary.kind != LIBRESOC_SEMAPHORE_NONE ?
+       //                              &semaphore->temporary : &semaphore->permanent;
+
+       //              switch (part->kind) {
+       //              case LIBRESOC_SEMAPHORE_NONE:
+       //              case LIBRESOC_SEMAPHORE_WINSYS:
+       //                      /* Do not need to do anything. */
+       //                      break;
+       //              case LIBRESOC_SEMAPHORE_TIMELINE:
+       //              case LIBRESOC_SEMAPHORE_TIMELINE_SYNCOBJ:
+       //                      unreachable("WSI only allows binary semaphores.");
+       //              case LIBRESOC_SEMAPHORE_SYNCOBJ:
+       //                      device->ws->signal_syncobj(device->ws, part->syncobj, 0);
+       //                      break;
+       //              }
+       //      }
+       // }
+       return result;
+}
+
+VkResult libresoc_QueuePresentKHR(
+       VkQueue                                  _queue,
+       const VkPresentInfoKHR*                  pPresentInfo)
+{
+       LIBRESOC_FROM_HANDLE(libresoc_queue, queue, _queue);
+       return wsi_common_queue_present(&queue->device->physical_device->wsi_device,
+                                       libresoc_device_to_handle(queue->device),
+                                       _queue,
+                                       queue->queue_family_index,
+                                       pPresentInfo);
+}
+
+
+VkResult libresoc_GetDeviceGroupPresentCapabilitiesKHR(
+    VkDevice                                    device,
+    VkDeviceGroupPresentCapabilitiesKHR*        pCapabilities)
+{
+   memset(pCapabilities->presentMask, 0,
+          sizeof(pCapabilities->presentMask));
+   pCapabilities->presentMask[0] = 0x1;
+   pCapabilities->modes = VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR;
+
+   return VK_SUCCESS;
+}
+
+VkResult libresoc_GetDeviceGroupSurfacePresentModesKHR(
+    VkDevice                                    device,
+    VkSurfaceKHR                                surface,
+    VkDeviceGroupPresentModeFlagsKHR*           pModes)
+{
+   *pModes = VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR;
+
+   return VK_SUCCESS;
+}
+
+VkResult libresoc_GetPhysicalDevicePresentRectanglesKHR(
+       VkPhysicalDevice                            physicalDevice,
+       VkSurfaceKHR                                surface,
+       uint32_t*                                   pRectCount,
+       VkRect2D*                                   pRects)
+{
+       LIBRESOC_FROM_HANDLE(libresoc_physical_device, device, physicalDevice);
+
+       return wsi_common_get_present_rectangles(&device->wsi_device,
+                                                surface,
+                                                pRectCount, pRects);
+}
diff --git a/src/libre-soc/vulkan/libresoc_wsi_x11.c b/src/libre-soc/vulkan/libresoc_wsi_x11.c
new file mode 100644 (file)
index 0000000..9185dac
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * Copyright © 2016 Red Hat.
+ * Copyright © 2016 Bas Nieuwenhuizen
+ *
+ * based mostly on anv driver which is:
+ * Copyright © 2015 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include <X11/Xlib-xcb.h>
+#include <X11/xshmfence.h>
+#include <xcb/xcb.h>
+#include <xcb/dri3.h>
+#include <xcb/present.h>
+
+#include "wsi_common_x11.h"
+#include "libresoc_private.h"
+
+
+VkBool32 libresoc_GetPhysicalDeviceXcbPresentationSupportKHR(
+    VkPhysicalDevice                            physicalDevice,
+    uint32_t                                    queueFamilyIndex,
+    xcb_connection_t*                           connection,
+    xcb_visualid_t                              visual_id)
+{
+   LIBRESOC_FROM_HANDLE(libresoc_physical_device, device, physicalDevice);
+
+   return true;
+   //TODO: for now always allow
+/*   return wsi_get_physical_device_xcb_presentation_support(
+      &device->wsi_device,
+      queueFamilyIndex,
+      connection, visual_id);*/
+}
+
+VkBool32 libresoc_GetPhysicalDeviceXlibPresentationSupportKHR(
+    VkPhysicalDevice                            physicalDevice,
+    uint32_t                                    queueFamilyIndex,
+    Display*                                    dpy,
+    VisualID                                    visualID)
+{
+   LIBRESOC_FROM_HANDLE(libresoc_physical_device, device, physicalDevice);
+
+   return true;
+   //TODO: for now always allow
+/*   return wsi_get_physical_device_xcb_presentation_support(
+      &device->wsi_device,
+      queueFamilyIndex,
+      XGetXCBConnection(dpy), visualID);*/
+}
+
+VkResult libresoc_CreateXcbSurfaceKHR(
+    VkInstance                                  _instance,
+    const VkXcbSurfaceCreateInfoKHR*            pCreateInfo,
+    const VkAllocationCallbacks*                pAllocator,
+    VkSurfaceKHR*                               pSurface)
+{
+   LIBRESOC_FROM_HANDLE(libresoc_instance, instance, _instance);
+   const VkAllocationCallbacks *alloc;
+   assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR);
+
+   if (pAllocator)
+     alloc = pAllocator;
+   else
+     alloc = &instance->alloc;
+
+   return wsi_create_xcb_surface(alloc, pCreateInfo, pSurface);
+}
+
+VkResult libresoc_CreateXlibSurfaceKHR(
+    VkInstance                                  _instance,
+    const VkXlibSurfaceCreateInfoKHR*           pCreateInfo,
+    const VkAllocationCallbacks*                pAllocator,
+    VkSurfaceKHR*                               pSurface)
+{
+   LIBRESOC_FROM_HANDLE(libresoc_instance, instance, _instance);
+   const VkAllocationCallbacks *alloc;
+
+   assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR);
+
+   if (pAllocator)
+     alloc = pAllocator;
+   else
+     alloc = &instance->alloc;
+
+   return wsi_create_xlib_surface(alloc, pCreateInfo, pSurface);
+}
index 1c4e84314c826c55f5dddc6327aa7cc377e2f54c..d5e6f9baaebd4fe2c7f19c43463358f4f06b3e44 100644 (file)
@@ -51,26 +51,6 @@ libresoc_entrypoints = custom_target(
     ],
   depend_files : files('libresoc_extensions.py'),
   )
-#libresoc_entrypoints = custom_target(
-#  'libresoc_entrypoints.[ch]',
-#  input : ['libresoc_entrypoints_gen.py', vk_api_xml],
-#  output : ['libresoc_entrypoints.h', 'libresoc_entrypoints.c'],
-#  command : [
-#    prog_python, '@INPUT0@', '--xml', '@INPUT1@', '--outdir',
-#    meson.current_build_dir()
-#  ],
-#  depend_files : files('libresoc_extensions.py'),
-#)
-#
-#libresoc_extensions_c = custom_target(
-#  'libresoc_extensions.c',
-#  input : ['libresoc_extensions.py', vk_api_xml],
-#  output : ['libresoc_extensions.c', 'libresoc_extensions.h'],
-#  command : [
-#    prog_python, '@INPUT0@', '--xml', '@INPUT1@', '--out-c', '@OUTPUT0@',
-#    '--out-h', '@OUTPUT1@'
-#  ],
-#)
 
 libresoc_vk_format_table_c = custom_target(
   'libresoc_vk_format_table.c',
@@ -83,59 +63,44 @@ libresoc_vk_format_table_c = custom_target(
 
 liblibresoc_files = files(
   'libresoc_device.c',
+  'libresoc_meta_clear.c',
+  'libresoc_image.c',
+  'libresoc_cmd_buffer.c',
+  'libresoc_formats.c',
   'libresoc_pipeline.c',
   'libresoc_pipeline_cache.c',
   'libresoc_util.c',
+  'libresoc_wsi.c',
+  'libresoc_private.h',
+  'vk_format.h',
 )
 
 libresoc_deps = []
 libresoc_flags = []
-
 libresoc_flags += '-DVK_USE_PLATFORM_DISPLAY_KHR'
+libresoc_flags += '-DVK_USE_PLATFORM_XLIB_KHR'
+libresoc_flags += '-DVK_USE_PLATFORM_XCB_KHR'
 if with_platform_x11
-  #libresoc_deps += dep_xcb_dri3
-  #libresoc_flags += [
-  #  '-DVK_USE_PLATFORM_XCB_KHR',
-  #  '-DVK_USE_PLATFORM_XLIB_KHR',
-  #]
-  #liblibresoc_files += files('libresoc_wsi_x11.c')
-endif
-
-if with_platform_wayland
-  #libresoc_deps += dep_wayland_client
-  #libresoc_flags += '-DVK_USE_PLATFORM_WAYLAND_KHR'
-  #liblibresoc_files += files('libresoc_wsi_wayland.c')
-endif
-
-if system_has_kms_drm and not with_platform_android
-  #libresoc_flags += '-DVK_USE_PLATFORM_DISPLAY_KHR'
-  #liblibresoc_files += files('libresoc_wsi_display.c')
-endif
-
-if with_xlib_lease
-  #libresoc_deps += [dep_xcb_xrandr, dep_xlib_xrandr]
-  #libresoc_flags += '-DVK_USE_PLATFORM_XLIB_XRANDR_EXT'
-endif
-
-if with_platform_android
-  #libresoc_deps += dep_android
-  #libresoc_flags += [
-  #  '-DVK_USE_PLATFORM_ANDROID_KHR'
-  #]
+ libresoc_deps += dep_xcb_dri3
+ libresoc_flags += [
+   '-DVK_USE_PLATFORM_XCB_KHR',
+   '-DVK_USE_PLATFORM_XLIB_KHR',
+ ]
+ liblibresoc_files += files('libresoc_wsi_x11.c')
 endif
 
 libvulkan_libresoc = shared_library(
   'vulkan_libresoc',
   [liblibresoc_files, libresoc_entrypoints, libresoc_extensions_c, libresoc_extensions_h, libresoc_vk_format_table_c, sha1_h],
   include_directories : [
-    inc_include, inc_src, inc_mapi, inc_mesa,  inc_compiler, inc_util, inc_vulkan_wsi, #inc_gallium, inc_gallium_aux, inc_amd, inc_amd_common, inc_amd_common_llvm,
+    inc_include, inc_src, inc_mapi, inc_mesa,  inc_compiler, inc_util, inc_vulkan_wsi, inc_gallium_aux, inc_gallium, #inc_amd, inc_amd_common, inc_amd_common_llvm,
   ],
   link_with : [
     libvulkan_wsi, #libamd_common, libamd_common_llvm, libamdgpu_addrlib, 
   ],
   dependencies : [idep_vulkan_util, libresoc_deps,idep_xmlconfig, dep_libdrm,
         dep_llvm, dep_thread, dep_elf, dep_dl, dep_m,dep_valgrind, idep_mesautil, idep_nir,
-    # libresoc_deps, idep_aco, dep_libdrm_amdgpu,
+     libresoc_deps, #idep_aco, dep_libdrm_amdgpu,
     #  idep_amdgfxregs_h, 
   ],
   c_args : [no_override_init_args, libresoc_flags],