lavapipe: VK_EXT_host_image_copy
authorMike Blumenkrantz <michael.blumenkrantz@gmail.com>
Fri, 24 Feb 2023 19:13:24 +0000 (14:13 -0500)
committerMarge Bot <emma+marge@anholt.net>
Thu, 3 Aug 2023 10:38:23 +0000 (10:38 +0000)
Acked-by: Konstantin Seurer <konstantin.seurer@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24278>

src/gallium/frontends/lavapipe/lvp_device.c
src/gallium/frontends/lavapipe/lvp_formats.c
src/gallium/frontends/lavapipe/lvp_image.c

index 9e932ef..2bb5c71 100644 (file)
@@ -167,6 +167,7 @@ static const struct vk_device_extension_table lvp_device_extensions_supported =
    .EXT_extended_dynamic_state3           = true,
    .EXT_external_memory_host              = true,
    .EXT_graphics_pipeline_library         = true,
+   .EXT_host_image_copy                   = true,
    .EXT_host_query_reset                  = true,
    .EXT_image_2d_view_of_3d               = true,
    .EXT_image_sliced_view_of_3d           = true,
@@ -576,6 +577,9 @@ lvp_get_features(const struct lvp_physical_device *pdevice,
       .multiviewMeshShader = false,
       .primitiveFragmentShadingRateMeshShader = false,
       .meshShaderQueries = true,
+
+      /* host_image_copy */
+      .hostImageCopy = true,
    };
 }
 
@@ -1109,6 +1113,45 @@ VKAPI_ATTR void VKAPI_CALL lvp_GetPhysicalDeviceProperties2(
          properties->pointClippingBehavior = VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES;
          break;
       }
+      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_IMAGE_COPY_PROPERTIES_EXT: {
+         VkPhysicalDeviceHostImageCopyPropertiesEXT *props =
+            (VkPhysicalDeviceHostImageCopyPropertiesEXT *)ext;
+         VkImageLayout layouts[] = {
+            VK_IMAGE_LAYOUT_UNDEFINED,
+            VK_IMAGE_LAYOUT_GENERAL,
+            VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+            VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
+            VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL,
+            VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
+            VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+            VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+            VK_IMAGE_LAYOUT_PREINITIALIZED,
+            VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL,
+            VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL,
+            VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL,
+            VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL,
+            VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL,
+            VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL,
+            VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL,
+            VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL,
+            VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
+            VK_IMAGE_LAYOUT_VIDEO_DECODE_DST_KHR,
+            VK_IMAGE_LAYOUT_VIDEO_DECODE_SRC_KHR,
+            VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR,
+            VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR,
+            VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT,
+            VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR,
+         };
+         if (props->copySrcLayoutCount)
+            typed_memcpy(props->pCopySrcLayouts, layouts, props->copySrcLayoutCount);
+         props->copySrcLayoutCount = ARRAY_SIZE(layouts);
+         if (props->copyDstLayoutCount)
+            typed_memcpy(props->pCopyDstLayouts, layouts, props->copyDstLayoutCount);
+         props->copyDstLayoutCount = ARRAY_SIZE(layouts);
+         lvp_device_get_cache_uuid(props->optimalTilingLayoutUUID);
+         props->identicalMemoryTypeRequirements = VK_FALSE;
+         break;
+      }
       case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT: {
          VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT *props =
             (VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT *)ext;
index a1a2298..8576b3f 100644 (file)
@@ -193,6 +193,10 @@ lvp_physical_device_get_format_properties(struct lvp_physical_device *physical_d
    out_properties->linearTilingFeatures = features;
    out_properties->optimalTilingFeatures = features;
    out_properties->bufferFeatures = buffer_features;
+   if (out_properties->linearTilingFeatures)
+      out_properties->linearTilingFeatures |= VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT_EXT;
+   if (out_properties->optimalTilingFeatures)
+      out_properties->optimalTilingFeatures |= VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT_EXT;
 }
 
 
index 2a21447..530a5ee 100644 (file)
@@ -24,6 +24,7 @@
 #include "lvp_private.h"
 #include "util/format/u_format.h"
 #include "util/u_inlines.h"
+#include "util/u_surface.h"
 #include "pipe/p_state.h"
 
 static VkResult
@@ -386,6 +387,18 @@ VKAPI_ATTR void VKAPI_CALL lvp_GetImageSubresourceLayout(
    }
 }
 
+VKAPI_ATTR void VKAPI_CALL lvp_GetImageSubresourceLayout2EXT(
+    VkDevice                       _device,
+    VkImage                        _image,
+    const VkImageSubresource2EXT*  pSubresource,
+    VkSubresourceLayout2EXT*       pLayout)
+{
+   lvp_GetImageSubresourceLayout(_device, _image, &pSubresource->imageSubresource, &pLayout->subresourceLayout);
+   VkSubresourceHostMemcpySizeEXT *size = vk_find_struct(pLayout, SUBRESOURCE_HOST_MEMCPY_SIZE_EXT);
+   if (size)
+      size->size = pLayout->subresourceLayout.size;
+}
+
 VKAPI_ATTR VkResult VKAPI_CALL lvp_CreateBuffer(
     VkDevice                                    _device,
     const VkBufferCreateInfo*                   pCreateInfo,
@@ -596,3 +609,135 @@ lvp_DestroyBufferView(VkDevice _device, VkBufferView bufferView,
    vk_object_base_finish(&view->base);
    vk_free2(&device->vk.alloc, pAllocator, view);
 }
+
+VKAPI_ATTR VkResult VKAPI_CALL
+lvp_CopyMemoryToImageEXT(VkDevice _device, const VkCopyMemoryToImageInfoEXT *pCopyMemoryToImageInfo)
+{
+   LVP_FROM_HANDLE(lvp_device, device, _device);
+   LVP_FROM_HANDLE(lvp_image, image, pCopyMemoryToImageInfo->dstImage);
+   for (unsigned i = 0; i < pCopyMemoryToImageInfo->regionCount; i++) {
+      const VkMemoryToImageCopyEXT *copy = &pCopyMemoryToImageInfo->pRegions[i];
+      struct pipe_box box = {
+         .x = copy->imageOffset.x,
+         .y = copy->imageOffset.y,
+         .width = copy->imageExtent.width,
+         .height = copy->imageExtent.height,
+         .depth = 1,
+      };
+      switch (image->bo->target) {
+      case PIPE_TEXTURE_CUBE:
+      case PIPE_TEXTURE_CUBE_ARRAY:
+      case PIPE_TEXTURE_2D_ARRAY:
+      case PIPE_TEXTURE_1D_ARRAY:
+         /* these use layer */
+         box.z = copy->imageSubresource.baseArrayLayer;
+         box.depth = copy->imageSubresource.layerCount;
+         break;
+      case PIPE_TEXTURE_3D:
+         /* this uses depth */
+         box.z = copy->imageOffset.z;
+         box.depth = copy->imageExtent.depth;
+         break;
+      default:
+         break;
+      }
+
+      unsigned stride = util_format_get_stride(image->bo->format, copy->memoryRowLength ? copy->memoryRowLength : box.width);
+      unsigned layer_stride = util_format_get_2d_size(image->bo->format, stride, copy->memoryImageHeight ? copy->memoryImageHeight : box.height);
+      device->queue.ctx->texture_subdata(device->queue.ctx, image->bo, copy->imageSubresource.mipLevel, 0,
+                                         &box, copy->pHostPointer, stride, layer_stride);
+   }
+   return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL
+lvp_CopyImageToMemoryEXT(VkDevice _device, const VkCopyImageToMemoryInfoEXT *pCopyImageToMemoryInfo)
+{
+   LVP_FROM_HANDLE(lvp_device, device, _device);
+   LVP_FROM_HANDLE(lvp_image, image, pCopyImageToMemoryInfo->srcImage);
+
+   for (unsigned i = 0; i < pCopyImageToMemoryInfo->regionCount; i++) {
+      const VkImageToMemoryCopyEXT *copy = &pCopyImageToMemoryInfo->pRegions[i];
+      struct pipe_box box = {
+         box.x = copy->imageOffset.x,
+         box.y = copy->imageOffset.y,
+         box.width = copy->imageExtent.width,
+         box.height = copy->imageExtent.height,
+         .depth = 1,
+      };
+      switch (image->bo->target) {
+      case PIPE_TEXTURE_CUBE:
+      case PIPE_TEXTURE_CUBE_ARRAY:
+      case PIPE_TEXTURE_2D_ARRAY:
+      case PIPE_TEXTURE_1D_ARRAY:
+         /* these use layer */
+         box.z = copy->imageSubresource.baseArrayLayer;
+         box.depth = copy->imageSubresource.layerCount;
+         break;
+      case PIPE_TEXTURE_3D:
+         /* this uses depth */
+         box.z = copy->imageOffset.z;
+         box.depth = copy->imageExtent.depth;
+         break;
+      default:
+         break;
+      }
+      struct pipe_transfer *xfer;
+      uint8_t *data = device->queue.ctx->texture_map(device->queue.ctx, image->bo, copy->imageSubresource.mipLevel,
+                                                     PIPE_MAP_READ | PIPE_MAP_UNSYNCHRONIZED | PIPE_MAP_THREAD_SAFE, &box, &xfer);
+      if (!data)
+         return VK_ERROR_MEMORY_MAP_FAILED;
+
+      unsigned stride = util_format_get_stride(image->bo->format, copy->memoryRowLength ? copy->memoryRowLength : box.width);
+      unsigned layer_stride = util_format_get_2d_size(image->bo->format, stride, copy->memoryImageHeight ? copy->memoryImageHeight : box.height);
+      util_copy_box(copy->pHostPointer, image->bo->format, stride, layer_stride,
+                    /* offsets are all zero because texture_map handles the offset */
+                    0, 0, 0, box.width, box.height, box.depth, data, xfer->stride, xfer->layer_stride, 0, 0, 0);
+      pipe_texture_unmap(device->queue.ctx, xfer);
+   }
+   return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL
+lvp_CopyImageToImageEXT(VkDevice _device, const VkCopyImageToImageInfoEXT *pCopyImageToImageInfo)
+{
+   LVP_FROM_HANDLE(lvp_device, device, _device);
+   LVP_FROM_HANDLE(lvp_image, src_image, pCopyImageToImageInfo->srcImage);
+   LVP_FROM_HANDLE(lvp_image, dst_image, pCopyImageToImageInfo->dstImage);
+
+   /* basically the same as handle_copy_image() */
+   for (unsigned i = 0; i < pCopyImageToImageInfo->regionCount; i++) {
+      struct pipe_box src_box;
+      src_box.x = pCopyImageToImageInfo->pRegions[i].srcOffset.x;
+      src_box.y = pCopyImageToImageInfo->pRegions[i].srcOffset.y;
+      src_box.width = pCopyImageToImageInfo->pRegions[i].extent.width;
+      src_box.height = pCopyImageToImageInfo->pRegions[i].extent.height;
+      if (src_image->bo->target == PIPE_TEXTURE_3D) {
+         src_box.depth = pCopyImageToImageInfo->pRegions[i].extent.depth;
+         src_box.z = pCopyImageToImageInfo->pRegions[i].srcOffset.z;
+      } else {
+         src_box.depth = pCopyImageToImageInfo->pRegions[i].srcSubresource.layerCount;
+         src_box.z = pCopyImageToImageInfo->pRegions[i].srcSubresource.baseArrayLayer;
+      }
+
+      unsigned dstz = dst_image->bo->target == PIPE_TEXTURE_3D ?
+                      pCopyImageToImageInfo->pRegions[i].dstOffset.z :
+                      pCopyImageToImageInfo->pRegions[i].dstSubresource.baseArrayLayer;
+      device->queue.ctx->resource_copy_region(device->queue.ctx, dst_image->bo,
+                                              pCopyImageToImageInfo->pRegions[i].dstSubresource.mipLevel,
+                                              pCopyImageToImageInfo->pRegions[i].dstOffset.x,
+                                              pCopyImageToImageInfo->pRegions[i].dstOffset.y,
+                                              dstz,
+                                              src_image->bo,
+                                              pCopyImageToImageInfo->pRegions[i].srcSubresource.mipLevel,
+                                              &src_box);
+   }
+   return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL
+lvp_TransitionImageLayoutEXT(VkDevice device, uint32_t transitionCount, const VkHostImageLayoutTransitionInfoEXT *pTransitions)
+{
+   /* no-op */
+   return VK_SUCCESS;
+}