Mesa (main): vulkan/wsi: untangle buffer-images from prime

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Tue Feb 22 10:54:58 UTC 2022


Module: Mesa
Branch: main
Commit: 25a37fabb7a3aa0aff9880ec172efafe6ad190d7
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=25a37fabb7a3aa0aff9880ec172efafe6ad190d7

Author: Erik Faye-Lund <kusmabite at gmail.com>
Date:   Thu Feb  3 10:57:16 2022 +0100

vulkan/wsi: untangle buffer-images from prime

Not all Vulkan implementations allows rendering to linear images, so in
order to support scanning out from these on Windows we might have to copy
through a buffer like we do in the PRIME path.

To avoid reimplementing the same, let's instead generalize the code a
bit so it doesn't have to specfy any PRIME-specific details.

Reviewed-by: Jason Ekstrand <jason.ekstrand at collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12210>

---

 src/amd/vulkan/radv_image.c         |   2 +-
 src/amd/vulkan/radv_wsi.c           |   2 +-
 src/broadcom/vulkan/v3dv_image.c    |   2 +-
 src/virtio/vulkan/vn_wsi.c          |   2 +-
 src/vulkan/wsi/wsi_common.c         | 246 +++++++++++++++++++++++++++++++-----
 src/vulkan/wsi/wsi_common.h         |   8 +-
 src/vulkan/wsi/wsi_common_drm.c     | 170 ++++---------------------
 src/vulkan/wsi/wsi_common_private.h |  41 ++++--
 src/vulkan/wsi/wsi_common_x11.c     |   8 +-
 9 files changed, 279 insertions(+), 202 deletions(-)

diff --git a/src/amd/vulkan/radv_image.c b/src/amd/vulkan/radv_image.c
index 712dfe3c81b..c90f016e755 100644
--- a/src/amd/vulkan/radv_image.c
+++ b/src/amd/vulkan/radv_image.c
@@ -2327,7 +2327,7 @@ radv_CreateImage(VkDevice device, const VkImageCreateInfo *pCreateInfo,
    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;
-   bool prime_blit_src = wsi_info && wsi_info->prime_blit_src;
+   bool prime_blit_src = wsi_info && wsi_info->buffer_blit_src;
 
    return radv_image_create(device,
                             &(struct radv_image_create_info){
diff --git a/src/amd/vulkan/radv_wsi.c b/src/amd/vulkan/radv_wsi.c
index 9793653b326..57743ac0e2c 100644
--- a/src/amd/vulkan/radv_wsi.c
+++ b/src/amd/vulkan/radv_wsi.c
@@ -95,7 +95,7 @@ radv_init_wsi(struct radv_physical_device *physical_device)
 
    physical_device->wsi_device.supports_modifiers = physical_device->rad_info.chip_class >= GFX9;
    physical_device->wsi_device.set_memory_ownership = radv_wsi_set_memory_ownership;
-   physical_device->wsi_device.get_prime_blit_queue = radv_wsi_get_prime_blit_queue;
+   physical_device->wsi_device.get_buffer_blit_queue = radv_wsi_get_prime_blit_queue;
    physical_device->wsi_device.signal_semaphore_with_memory = true;
    physical_device->wsi_device.signal_fence_with_memory = true;
 
diff --git a/src/broadcom/vulkan/v3dv_image.c b/src/broadcom/vulkan/v3dv_image.c
index e0ee210afa4..cb0880370ff 100644
--- a/src/broadcom/vulkan/v3dv_image.c
+++ b/src/broadcom/vulkan/v3dv_image.c
@@ -257,7 +257,7 @@ create_image(struct v3dv_device *device,
    /* When using the simulator the WSI common code will see that our
     * driver wsi device doesn't match the display device and because of that
     * it will not attempt to present directly from the swapchain images,
-    * instead it will use the prime blit path (use_prime_blit flag in
+    * instead it will use the prime blit path (use_buffer_blit flag in
     * struct wsi_swapchain), where it copies the contents of the swapchain
     * images to a linear buffer with appropriate row stride for presentation.
     * As a result, on that path, swapchain images do not have any special
diff --git a/src/virtio/vulkan/vn_wsi.c b/src/virtio/vulkan/vn_wsi.c
index 7419b587ea8..7f0ed9dbc37 100644
--- a/src/virtio/vulkan/vn_wsi.c
+++ b/src/virtio/vulkan/vn_wsi.c
@@ -133,7 +133,7 @@ vn_wsi_create_image(struct vn_device *dev,
       return result;
 
    img->wsi.is_wsi = true;
-   img->wsi.is_prime_blit_src = wsi_info->prime_blit_src;
+   img->wsi.is_prime_blit_src = wsi_info->buffer_blit_src;
    img->wsi.tiling_override = create_info->tiling;
 
    if (create_info->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) {
diff --git a/src/vulkan/wsi/wsi_common.c b/src/vulkan/wsi/wsi_common.c
index ecd4a4b3b54..e755d76d3bb 100644
--- a/src/vulkan/wsi/wsi_common.c
+++ b/src/vulkan/wsi/wsi_common.c
@@ -28,6 +28,7 @@
 #include "util/xmlconfig.h"
 #include "vk_device.h"
 #include "vk_fence.h"
+#include "vk_format.h"
 #include "vk_instance.h"
 #include "vk_physical_device.h"
 #include "vk_queue.h"
@@ -223,7 +224,7 @@ wsi_swapchain_init(const struct wsi_device *wsi,
                    VkDevice device,
                    const VkSwapchainCreateInfoKHR *pCreateInfo,
                    const VkAllocationCallbacks *pAllocator,
-                   bool use_prime_blit)
+                   bool use_buffer_blit)
 {
    VkResult result;
 
@@ -234,12 +235,12 @@ wsi_swapchain_init(const struct wsi_device *wsi,
    chain->wsi = wsi;
    chain->device = device;
    chain->alloc = *pAllocator;
-   chain->use_prime_blit = use_prime_blit;
-   chain->prime_blit_queue = VK_NULL_HANDLE;
-   if (use_prime_blit && wsi->get_prime_blit_queue)
-      chain->prime_blit_queue = wsi->get_prime_blit_queue(device);
+   chain->use_buffer_blit = use_buffer_blit;
+   chain->buffer_blit_queue = VK_NULL_HANDLE;
+   if (use_buffer_blit && wsi->get_buffer_blit_queue)
+      chain->buffer_blit_queue = wsi->get_buffer_blit_queue(device);
 
-   int cmd_pools_count = chain->prime_blit_queue != VK_NULL_HANDLE ? 1 : wsi->queue_family_count;
+   int cmd_pools_count = chain->buffer_blit_queue != VK_NULL_HANDLE ? 1 : wsi->queue_family_count;
 
    chain->cmd_pools =
       vk_zalloc(pAllocator, sizeof(VkCommandPool) * cmd_pools_count, 8,
@@ -250,8 +251,8 @@ wsi_swapchain_init(const struct wsi_device *wsi,
    for (uint32_t i = 0; i < cmd_pools_count; i++) {
       int queue_family_index = i;
 
-      if (chain->prime_blit_queue != VK_NULL_HANDLE) {
-         VK_FROM_HANDLE(vk_queue, queue, chain->prime_blit_queue);
+      if (chain->buffer_blit_queue != VK_NULL_HANDLE) {
+         VK_FROM_HANDLE(vk_queue, queue, chain->buffer_blit_queue);
          queue_family_index = queue->queue_family_index;
       }
       const VkCommandPoolCreateInfo cmd_pool_info = {
@@ -335,14 +336,14 @@ wsi_swapchain_finish(struct wsi_swapchain *chain)
 
       vk_free(&chain->alloc, chain->fences);
    }
-   if (chain->prime_blit_semaphores) {
+   if (chain->buffer_blit_semaphores) {
       for (unsigned i = 0; i < chain->image_count; i++)
-         chain->wsi->DestroySemaphore(chain->device, chain->prime_blit_semaphores[i], &chain->alloc);
+         chain->wsi->DestroySemaphore(chain->device, chain->buffer_blit_semaphores[i], &chain->alloc);
 
-      vk_free(&chain->alloc, chain->prime_blit_semaphores);
+      vk_free(&chain->alloc, chain->buffer_blit_semaphores);
    }
 
-   int cmd_pools_count = chain->prime_blit_queue != VK_NULL_HANDLE ?
+   int cmd_pools_count = chain->buffer_blit_queue != VK_NULL_HANDLE ?
       1 : chain->wsi->queue_family_count;
    for (uint32_t i = 0; i < cmd_pools_count; i++) {
       chain->wsi->DestroyCommandPool(chain->device, chain->cmd_pools[i],
@@ -500,18 +501,18 @@ wsi_destroy_image(const struct wsi_swapchain *chain,
 {
    const struct wsi_device *wsi = chain->wsi;
 
-   if (image->prime.blit_cmd_buffers) {
+   if (image->buffer.blit_cmd_buffers) {
       for (uint32_t i = 0; i < wsi->queue_family_count; i++) {
          wsi->FreeCommandBuffers(chain->device, chain->cmd_pools[i],
-                                 1, &image->prime.blit_cmd_buffers[i]);
+                                 1, &image->buffer.blit_cmd_buffers[i]);
       }
-      vk_free(&chain->alloc, image->prime.blit_cmd_buffers);
+      vk_free(&chain->alloc, image->buffer.blit_cmd_buffers);
    }
 
    wsi->FreeMemory(chain->device, image->memory, &chain->alloc);
    wsi->DestroyImage(chain->device, image->image, &chain->alloc);
-   wsi->FreeMemory(chain->device, image->prime.memory, &chain->alloc);
-   wsi->DestroyBuffer(chain->device, image->prime.buffer, &chain->alloc);
+   wsi->FreeMemory(chain->device, image->buffer.memory, &chain->alloc);
+   wsi->DestroyBuffer(chain->device, image->buffer.buffer, &chain->alloc);
 }
 
 VKAPI_ATTR VkResult VKAPI_CALL
@@ -707,12 +708,12 @@ wsi_CreateSwapchainKHR(VkDevice _device,
       return VK_ERROR_OUT_OF_HOST_MEMORY;
    }
 
-   if (swapchain->prime_blit_queue != VK_NULL_HANDLE) {
-      swapchain->prime_blit_semaphores = vk_zalloc(alloc,
-                                         sizeof (*swapchain->prime_blit_semaphores) * swapchain->image_count,
-                                         sizeof (*swapchain->prime_blit_semaphores),
+   if (swapchain->buffer_blit_queue != VK_NULL_HANDLE) {
+      swapchain->buffer_blit_semaphores = vk_zalloc(alloc,
+                                         sizeof (*swapchain->buffer_blit_semaphores) * swapchain->image_count,
+                                         sizeof (*swapchain->buffer_blit_semaphores),
                                          VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
-      if (!swapchain->prime_blit_semaphores) {
+      if (!swapchain->buffer_blit_semaphores) {
          swapchain->destroy(swapchain, alloc);
          return VK_ERROR_OUT_OF_HOST_MEMORY;
       }
@@ -894,7 +895,7 @@ wsi_common_queue_present(const struct wsi_device *wsi,
          if (result != VK_SUCCESS)
             goto fail_present;
 
-         if (swapchain->use_prime_blit && swapchain->prime_blit_queue != VK_NULL_HANDLE) {
+         if (swapchain->use_buffer_blit && swapchain->buffer_blit_queue != VK_NULL_HANDLE) {
             const VkSemaphoreCreateInfo sem_info = {
                .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
                .pNext = NULL,
@@ -902,7 +903,7 @@ wsi_common_queue_present(const struct wsi_device *wsi,
             };
             result = wsi->CreateSemaphore(device, &sem_info,
                                           &swapchain->alloc,
-                                          &swapchain->prime_blit_semaphores[image_index]);
+                                          &swapchain->buffer_blit_semaphores[image_index]);
             if (result != VK_SUCCESS)
                goto fail_present;
          }
@@ -958,22 +959,22 @@ wsi_common_queue_present(const struct wsi_device *wsi,
       }
 
       VkFence fence = swapchain->fences[image_index];
-      if (swapchain->use_prime_blit) {
-         if (swapchain->prime_blit_queue == VK_NULL_HANDLE) {
-            /* If we are using default prime blits, we need to perform the blit now.  The
+      if (swapchain->use_buffer_blit) {
+         if (swapchain->buffer_blit_queue == VK_NULL_HANDLE) {
+            /* If we are using default buffer blits, we need to perform the blit now.  The
              * command buffer is attached to the image.
              */
             submit_info.commandBufferCount = 1;
             submit_info.pCommandBuffers =
-               &image->prime.blit_cmd_buffers[queue_family_index];
-            mem_signal.memory = image->prime.memory;
+               &image->buffer.blit_cmd_buffers[queue_family_index];
+            mem_signal.memory = image->buffer.memory;
          } else {
             /* If we are using a blit using the driver's private queue, then do an empty
              * submit signalling a semaphore, and then submit the blit.
              */
             fence = VK_NULL_HANDLE;
             submit_info.signalSemaphoreCount = 1;
-            submit_info.pSignalSemaphores = &swapchain->prime_blit_semaphores[image_index];
+            submit_info.pSignalSemaphores = &swapchain->buffer_blit_semaphores[image_index];
          }
       }
 
@@ -982,22 +983,22 @@ wsi_common_queue_present(const struct wsi_device *wsi,
       if (result != VK_SUCCESS)
          goto fail_present;
 
-      if (swapchain->use_prime_blit && swapchain->prime_blit_queue != VK_NULL_HANDLE) {
+      if (swapchain->use_buffer_blit && swapchain->buffer_blit_queue != VK_NULL_HANDLE) {
          submit_info.commandBufferCount = 1;
 
-         if (swapchain->prime_blit_queue != VK_NULL_HANDLE) {
-            submit_info.pCommandBuffers = &image->prime.blit_cmd_buffers[0];
+         if (swapchain->buffer_blit_queue != VK_NULL_HANDLE) {
+            submit_info.pCommandBuffers = &image->buffer.blit_cmd_buffers[0];
             submit_info.waitSemaphoreCount = 1;
             submit_info.pWaitSemaphores = submit_info.pSignalSemaphores;
             submit_info.signalSemaphoreCount = 0;
             submit_info.pSignalSemaphores = NULL;
             /* Submit the copy to the private transfer queue */
-            result = wsi->QueueSubmit(swapchain->prime_blit_queue,
+            result = wsi->QueueSubmit(swapchain->buffer_blit_queue,
                                       1,
                                       &submit_info,
                                       swapchain->fences[image_index]);
          }
-         mem_signal.memory = image->prime.memory;
+         mem_signal.memory = image->buffer.memory;
       }
 
       if (wsi->sw)
@@ -1130,3 +1131,178 @@ wsi_common_bind_swapchain_image(const struct wsi_device *wsi,
 
    return wsi->BindImageMemory(chain->device, vk_image, image->memory, 0);
 }
+
+VkResult
+wsi_create_buffer_image_mem(const struct wsi_swapchain *chain,
+                            const struct wsi_image_info *info,
+                            struct wsi_image *image,
+                            VkExternalMemoryHandleTypeFlags handle_types,
+                            bool implicit_sync)
+{
+   const struct wsi_device *wsi = chain->wsi;
+   VkResult result;
+
+   uint32_t linear_size = info->linear_stride * info->create.extent.height;
+   linear_size = ALIGN_POT(linear_size, info->size_align);
+
+   const VkExternalMemoryBufferCreateInfo buffer_external_info = {
+      .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO,
+      .pNext = NULL,
+      .handleTypes = handle_types,
+   };
+   const VkBufferCreateInfo buffer_info = {
+      .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
+      .pNext = &buffer_external_info,
+      .size = linear_size,
+      .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT,
+      .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
+   };
+   result = wsi->CreateBuffer(chain->device, &buffer_info,
+                              &chain->alloc, &image->buffer.buffer);
+   if (result != VK_SUCCESS)
+      return result;
+
+   VkMemoryRequirements reqs;
+   wsi->GetBufferMemoryRequirements(chain->device, image->buffer.buffer, &reqs);
+   assert(reqs.size <= linear_size);
+
+   const struct wsi_memory_allocate_info memory_wsi_info = {
+      .sType = VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA,
+      .pNext = NULL,
+      .implicit_sync = implicit_sync,
+   };
+   const VkExportMemoryAllocateInfo memory_export_info = {
+      .sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO,
+      .pNext = &memory_wsi_info,
+      .handleTypes = handle_types,
+   };
+   const VkMemoryDedicatedAllocateInfo buf_mem_dedicated_info = {
+      .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
+      .pNext = &memory_export_info,
+      .image = VK_NULL_HANDLE,
+      .buffer = image->buffer.buffer,
+   };
+   const VkMemoryAllocateInfo buf_mem_info = {
+      .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
+      .pNext = &buf_mem_dedicated_info,
+      .allocationSize = linear_size,
+      .memoryTypeIndex =
+         info->select_buffer_memory_type(wsi, reqs.memoryTypeBits),
+   };
+   result = wsi->AllocateMemory(chain->device, &buf_mem_info,
+                                &chain->alloc, &image->buffer.memory);
+   if (result != VK_SUCCESS)
+      return result;
+
+   result = wsi->BindBufferMemory(chain->device, image->buffer.buffer,
+                                  image->buffer.memory, 0);
+   if (result != VK_SUCCESS)
+      return result;
+
+   wsi->GetImageMemoryRequirements(chain->device, image->image, &reqs);
+
+   const VkMemoryDedicatedAllocateInfo memory_dedicated_info = {
+      .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
+      .pNext = NULL,
+      .image = image->image,
+      .buffer = VK_NULL_HANDLE,
+   };
+   const VkMemoryAllocateInfo memory_info = {
+      .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
+      .pNext = &memory_dedicated_info,
+      .allocationSize = reqs.size,
+      .memoryTypeIndex =
+         info->select_image_memory_type(wsi, reqs.memoryTypeBits),
+   };
+
+   result = wsi->AllocateMemory(chain->device, &memory_info,
+                                &chain->alloc, &image->memory);
+   if (result != VK_SUCCESS)
+      return result;
+
+   image->num_planes = 1;
+   image->sizes[0] = linear_size;
+   image->row_pitches[0] = info->linear_stride;
+   image->offsets[0] = 0;
+
+   return VK_SUCCESS;
+}
+
+VkResult
+wsi_finish_create_buffer_image(const struct wsi_swapchain *chain,
+                               const struct wsi_image_info *info,
+                               struct wsi_image *image)
+{
+   const struct wsi_device *wsi = chain->wsi;
+   VkResult result;
+
+   int cmd_buffer_count =
+      chain->buffer_blit_queue != VK_NULL_HANDLE ? 1 : wsi->queue_family_count;
+   image->buffer.blit_cmd_buffers =
+      vk_zalloc(&chain->alloc,
+                sizeof(VkCommandBuffer) * cmd_buffer_count, 8,
+                VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+   if (!image->buffer.blit_cmd_buffers)
+      return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+   for (uint32_t i = 0; i < cmd_buffer_count; i++) {
+      const VkCommandBufferAllocateInfo cmd_buffer_info = {
+         .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
+         .pNext = NULL,
+         .commandPool = chain->cmd_pools[i],
+         .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
+         .commandBufferCount = 1,
+      };
+      result = wsi->AllocateCommandBuffers(chain->device, &cmd_buffer_info,
+                                           &image->buffer.blit_cmd_buffers[i]);
+      if (result != VK_SUCCESS)
+         return result;
+
+      const VkCommandBufferBeginInfo begin_info = {
+         .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
+      };
+      wsi->BeginCommandBuffer(image->buffer.blit_cmd_buffers[i], &begin_info);
+      struct VkBufferImageCopy buffer_image_copy = {
+         .bufferOffset = 0,
+         .bufferRowLength = info->linear_stride /
+                            vk_format_get_blocksize(info->create.format),
+         .bufferImageHeight = 0,
+         .imageSubresource = {
+            .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
+            .mipLevel = 0,
+            .baseArrayLayer = 0,
+            .layerCount = 1,
+         },
+         .imageOffset = { .x = 0, .y = 0, .z = 0 },
+         .imageExtent = info->create.extent,
+      };
+      wsi->CmdCopyImageToBuffer(image->buffer.blit_cmd_buffers[i],
+                                image->image,
+                                VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
+                                image->buffer.buffer,
+                                1, &buffer_image_copy);
+
+      result = wsi->EndCommandBuffer(image->buffer.blit_cmd_buffers[i]);
+      if (result != VK_SUCCESS)
+         return result;
+   }
+
+   return VK_SUCCESS;
+}
+
+VkResult
+wsi_configure_buffer_image(UNUSED const struct wsi_swapchain *chain,
+                           const VkSwapchainCreateInfoKHR *pCreateInfo,
+                           struct wsi_image_info *info)
+{
+   VkResult result = wsi_configure_image(chain, pCreateInfo,
+                                         0 /* handle_types */, info);
+   if (result != VK_SUCCESS)
+      return result;
+
+   info->create.usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
+   info->wsi.buffer_blit_src = true;
+   info->finish_create = wsi_finish_create_buffer_image;
+
+   return VK_SUCCESS;
+}
diff --git a/src/vulkan/wsi/wsi_common.h b/src/vulkan/wsi/wsi_common.h
index 696f6b40bac..52411a0a604 100644
--- a/src/vulkan/wsi/wsi_common.h
+++ b/src/vulkan/wsi/wsi_common.h
@@ -60,8 +60,8 @@ struct wsi_image_create_info {
     const void *pNext;
     bool scanout;
 
-    /* if true, the image is a prime blit source */
-    bool prime_blit_src;
+    /* if true, the image is a buffer blit source */
+    bool buffer_blit_src;
 };
 
 struct wsi_memory_allocate_info {
@@ -176,9 +176,9 @@ struct wsi_device {
 
    /*
     * A driver can implement this callback to return a special queue to execute
-    * prime blits.
+    * buffer blits.
     */
-   VkQueue (*get_prime_blit_queue)(VkDevice device);
+   VkQueue (*get_buffer_blit_queue)(VkDevice device);
 
 #define WSI_CB(cb) PFN_vk##cb cb
    WSI_CB(AllocateMemory);
diff --git a/src/vulkan/wsi/wsi_common_drm.c b/src/vulkan/wsi/wsi_common_drm.c
index 8982ba225f2..72af5b2c820 100644
--- a/src/vulkan/wsi/wsi_common_drm.c
+++ b/src/vulkan/wsi/wsi_common_drm.c
@@ -115,6 +115,20 @@ select_memory_type(const struct wsi_device *wsi,
    unreachable("No memory type found");
 }
 
+static uint32_t
+prime_select_buffer_memory_type(const struct wsi_device *wsi,
+                                uint32_t type_bits)
+{
+   return select_memory_type(wsi, false, type_bits);
+}
+
+static uint32_t
+prime_select_image_memory_type(const struct wsi_device *wsi,
+                               uint32_t type_bits)
+{
+   return select_memory_type(wsi, true, type_bits);
+}
+
 static const struct VkDrmFormatModifierPropertiesEXT *
 get_modifier_props(const struct wsi_image_info *info, uint64_t modifier)
 {
@@ -416,87 +430,17 @@ wsi_create_prime_image_mem(const struct wsi_swapchain *chain,
                            struct wsi_image *image)
 {
    const struct wsi_device *wsi = chain->wsi;
-   VkResult result;
-
-   uint32_t linear_size = info->linear_stride * info->create.extent.height;
-   linear_size = ALIGN_POT(linear_size, 4096);
-
-   const VkExternalMemoryBufferCreateInfo prime_buffer_external_info = {
-      .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO,
-      .pNext = NULL,
-      .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
-   };
-   const VkBufferCreateInfo prime_buffer_info = {
-      .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
-      .pNext = &prime_buffer_external_info,
-      .size = linear_size,
-      .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT,
-      .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
-   };
-   result = wsi->CreateBuffer(chain->device, &prime_buffer_info,
-                              &chain->alloc, &image->prime.buffer);
-   if (result != VK_SUCCESS)
-      return result;
-
-   VkMemoryRequirements reqs;
-   wsi->GetBufferMemoryRequirements(chain->device, image->prime.buffer, &reqs);
-   assert(reqs.size <= linear_size);
-
-   const struct wsi_memory_allocate_info memory_wsi_info = {
-      .sType = VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA,
-      .pNext = NULL,
-      .implicit_sync = true,
-   };
-   const VkExportMemoryAllocateInfo prime_memory_export_info = {
-      .sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO,
-      .pNext = &memory_wsi_info,
-      .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
-   };
-   const VkMemoryDedicatedAllocateInfo prime_memory_dedicated_info = {
-      .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
-      .pNext = &prime_memory_export_info,
-      .image = VK_NULL_HANDLE,
-      .buffer = image->prime.buffer,
-   };
-   const VkMemoryAllocateInfo prime_memory_info = {
-      .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
-      .pNext = &prime_memory_dedicated_info,
-      .allocationSize = linear_size,
-      .memoryTypeIndex = select_memory_type(wsi, false, reqs.memoryTypeBits),
-   };
-   result = wsi->AllocateMemory(chain->device, &prime_memory_info,
-                                &chain->alloc, &image->prime.memory);
-   if (result != VK_SUCCESS)
-      return result;
-
-   result = wsi->BindBufferMemory(chain->device, image->prime.buffer,
-                                  image->prime.memory, 0);
-   if (result != VK_SUCCESS)
-      return result;
-
-   wsi->GetImageMemoryRequirements(chain->device, image->image, &reqs);
-
-   const VkMemoryDedicatedAllocateInfo memory_dedicated_info = {
-      .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
-      .pNext = NULL,
-      .image = image->image,
-      .buffer = VK_NULL_HANDLE,
-   };
-   const VkMemoryAllocateInfo memory_info = {
-      .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
-      .pNext = &memory_dedicated_info,
-      .allocationSize = reqs.size,
-      .memoryTypeIndex = select_memory_type(wsi, true, reqs.memoryTypeBits),
-   };
-   result = wsi->AllocateMemory(chain->device, &memory_info,
-                                &chain->alloc, &image->memory);
+   VkResult result =
+      wsi_create_buffer_image_mem(chain, info, image,
+                                  VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
+                                  true);
    if (result != VK_SUCCESS)
       return result;
 
    const VkMemoryGetFdInfoKHR linear_memory_get_fd_info = {
       .sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR,
       .pNext = NULL,
-      .memory = image->prime.memory,
+      .memory = image->buffer.memory,
       .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
    };
    int fd;
@@ -506,98 +450,32 @@ wsi_create_prime_image_mem(const struct wsi_swapchain *chain,
 
    image->drm_modifier = info->prime_use_linear_modifier ?
                          DRM_FORMAT_MOD_LINEAR : DRM_FORMAT_MOD_INVALID;
-   image->num_planes = 1;
-   image->sizes[0] = linear_size;
-   image->row_pitches[0] = info->linear_stride;
-   image->offsets[0] = 0;
    image->fds[0] = fd;
 
    return VK_SUCCESS;
 }
 
-static VkResult
-wsi_finish_create_prime_image(const struct wsi_swapchain *chain,
-                              const struct wsi_image_info *info,
-                              struct wsi_image *image)
-{
-   const struct wsi_device *wsi = chain->wsi;
-   VkResult result;
-
-   image->prime.blit_cmd_buffers =
-      vk_zalloc(&chain->alloc,
-                sizeof(VkCommandBuffer) * wsi->queue_family_count, 8,
-                VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
-   if (!image->prime.blit_cmd_buffers)
-      return VK_ERROR_OUT_OF_HOST_MEMORY;
-
-   int cmd_buffer_count = chain->prime_blit_queue != VK_NULL_HANDLE ? 1 : wsi->queue_family_count;
-   for (uint32_t i = 0; i < cmd_buffer_count; i++) {
-      const VkCommandBufferAllocateInfo cmd_buffer_info = {
-         .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
-         .pNext = NULL,
-         .commandPool = chain->cmd_pools[i],
-         .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
-         .commandBufferCount = 1,
-      };
-      result = wsi->AllocateCommandBuffers(chain->device, &cmd_buffer_info,
-                                           &image->prime.blit_cmd_buffers[i]);
-      if (result != VK_SUCCESS)
-         return result;
-
-      const VkCommandBufferBeginInfo begin_info = {
-         .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
-      };
-      wsi->BeginCommandBuffer(image->prime.blit_cmd_buffers[i], &begin_info);
-
-      struct VkBufferImageCopy buffer_image_copy = {
-         .bufferOffset = 0,
-         .bufferRowLength = info->linear_stride /
-                            vk_format_get_blocksize(info->create.format),
-         .bufferImageHeight = 0,
-         .imageSubresource = {
-            .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
-            .mipLevel = 0,
-            .baseArrayLayer = 0,
-            .layerCount = 1,
-         },
-         .imageOffset = { .x = 0, .y = 0, .z = 0 },
-         .imageExtent = info->create.extent,
-      };
-      wsi->CmdCopyImageToBuffer(image->prime.blit_cmd_buffers[i],
-                                image->image,
-                                VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
-                                image->prime.buffer,
-                                1, &buffer_image_copy);
-
-      result = wsi->EndCommandBuffer(image->prime.blit_cmd_buffers[i]);
-      if (result != VK_SUCCESS)
-         return result;
-   }
-
-   return VK_SUCCESS;
-}
-
 VkResult
 wsi_configure_prime_image(UNUSED const struct wsi_swapchain *chain,
                           const VkSwapchainCreateInfoKHR *pCreateInfo,
                           bool use_modifier,
                           struct wsi_image_info *info)
 {
-   VkResult result = wsi_configure_image(chain, pCreateInfo,
-                                         0 /* handle_types */, info);
+   VkResult result =
+      wsi_configure_buffer_image(chain, pCreateInfo, info);
    if (result != VK_SUCCESS)
       return result;
 
-   info->create.usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
-   info->wsi.prime_blit_src = true,
    info->prime_use_linear_modifier = use_modifier;
 
    const uint32_t cpp = vk_format_get_blocksize(info->create.format);
    info->linear_stride = ALIGN_POT(info->create.extent.width * cpp,
                                    WSI_PRIME_LINEAR_STRIDE_ALIGN);
+   info->size_align = 4096;
 
    info->create_mem = wsi_create_prime_image_mem;
-   info->finish_create = wsi_finish_create_prime_image;
+   info->select_buffer_memory_type = prime_select_buffer_memory_type;
+   info->select_image_memory_type = prime_select_image_memory_type;
 
    return VK_SUCCESS;
 }
diff --git a/src/vulkan/wsi/wsi_common_private.h b/src/vulkan/wsi/wsi_common_private.h
index b41cd16a96a..af190ce501b 100644
--- a/src/vulkan/wsi/wsi_common_private.h
+++ b/src/vulkan/wsi/wsi_common_private.h
@@ -44,8 +44,14 @@ struct wsi_image_info {
    uint32_t modifier_prop_count;
    struct VkDrmFormatModifierPropertiesEXT *modifier_props;
 
-   /* For prime blit images, the linear stride in bytes */
+   /* For buffer blit images, the linear stride in bytes */
    uint32_t linear_stride;
+   uint32_t size_align;
+
+   uint32_t (*select_image_memory_type)(const struct wsi_device *wsi,
+                                        uint32_t type_bits);
+   uint32_t (*select_buffer_memory_type)(const struct wsi_device *wsi,
+                                         uint32_t type_bits);
 
    uint8_t *(*alloc_shm)(struct wsi_image *image, unsigned size);
 
@@ -66,7 +72,7 @@ struct wsi_image {
       VkBuffer buffer;
       VkDeviceMemory memory;
       VkCommandBuffer *blit_cmd_buffers;
-   } prime;
+   } buffer;
 
    uint64_t drm_modifier;
    int num_planes;
@@ -84,20 +90,20 @@ struct wsi_swapchain {
    VkDevice device;
    VkAllocationCallbacks alloc;
    VkFence* fences;
-   VkSemaphore* prime_blit_semaphores;
+   VkSemaphore* buffer_blit_semaphores;
    VkPresentModeKHR present_mode;
 
    struct wsi_image_info image_info;
    uint32_t image_count;
 
-   bool use_prime_blit;
+   bool use_buffer_blit;
 
-   /* If the driver wants to use a special queue to execute the prime blit,
-    * it'll implement the wsi_device::get_prime_blit_queue callback.
+   /* If the driver wants to use a special queue to execute the buffer blit,
+    * it'll implement the wsi_device::get_buffer_blit_queue callback.
     * The created queue will be stored here and will be used to execute the
-    * prime blit instead of using the present queue.
+    * buffer blit instead of using the present queue.
     */
-   VkQueue prime_blit_queue;
+   VkQueue buffer_blit_queue;
 
    /* Command pools, one per queue family */
    VkCommandPool *cmd_pools;
@@ -123,7 +129,7 @@ wsi_swapchain_init(const struct wsi_device *wsi,
                    VkDevice device,
                    const VkSwapchainCreateInfoKHR *pCreateInfo,
                    const VkAllocationCallbacks *pAllocator,
-                   bool use_prime_blit);
+                   bool use_buffer_blit);
 
 enum VkPresentModeKHR
 wsi_swapchain_get_present_mode(struct wsi_device *wsi,
@@ -147,6 +153,23 @@ wsi_configure_prime_image(UNUSED const struct wsi_swapchain *chain,
                           bool use_modifier,
                           struct wsi_image_info *info);
 
+VkResult
+wsi_create_buffer_image_mem(const struct wsi_swapchain *chain,
+                            const struct wsi_image_info *info,
+                            struct wsi_image *image,
+                            VkExternalMemoryHandleTypeFlags handle_types,
+                            bool implicit_sync);
+
+VkResult
+wsi_finish_create_buffer_image(const struct wsi_swapchain *chain,
+                               const struct wsi_image_info *info,
+                               struct wsi_image *image);
+
+VkResult
+wsi_configure_buffer_image(UNUSED const struct wsi_swapchain *chain,
+                           const VkSwapchainCreateInfoKHR *pCreateInfo,
+                           struct wsi_image_info *info);
+
 VkResult
 wsi_configure_image(const struct wsi_swapchain *chain,
                     const VkSwapchainCreateInfoKHR *pCreateInfo,
diff --git a/src/vulkan/wsi/wsi_common_x11.c b/src/vulkan/wsi/wsi_common_x11.c
index 6faecb636bd..85a66a95dab 100644
--- a/src/vulkan/wsi/wsi_common_x11.c
+++ b/src/vulkan/wsi/wsi_common_x11.c
@@ -1858,13 +1858,13 @@ x11_surface_create_swapchain(VkIcdSurfaceBase *icd_surface,
    /* When our local device is not compatible with the DRI3 device provided by
     * the X server we assume this is a PRIME system.
     */
-   bool use_prime_blit = false;
+   bool use_buffer_blit = false;
    if (!wsi_device->sw)
       if (!wsi_x11_check_dri3_compatible(wsi_device, conn))
-         use_prime_blit = true;
+         use_buffer_blit = true;
 
    result = wsi_swapchain_init(wsi_device, &chain->base, device,
-                               pCreateInfo, pAllocator, use_prime_blit);
+                               pCreateInfo, pAllocator, use_buffer_blit);
    if (result != VK_SUCCESS)
       goto fail_alloc;
 
@@ -1957,7 +1957,7 @@ x11_surface_create_swapchain(VkIcdSurfaceBase *icd_surface,
                                  modifiers, num_modifiers, &num_tranches,
                                  pAllocator);
 
-   if (chain->base.use_prime_blit) {
+   if (chain->base.use_buffer_blit) {
       bool use_modifier = num_tranches > 0;
       result = wsi_configure_prime_image(&chain->base, pCreateInfo,
                                          use_modifier,



More information about the mesa-commit mailing list