From 9e9d90c6c3814710b47001865967f27fcb68c4e4 Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Fri, 24 Feb 2023 14:13:24 -0500 Subject: [PATCH] lavapipe: VK_EXT_host_image_copy Acked-by: Konstantin Seurer Part-of: --- src/gallium/frontends/lavapipe/lvp_device.c | 43 ++++++++ src/gallium/frontends/lavapipe/lvp_formats.c | 4 + src/gallium/frontends/lavapipe/lvp_image.c | 145 +++++++++++++++++++++++++++ 3 files changed, 192 insertions(+) diff --git a/src/gallium/frontends/lavapipe/lvp_device.c b/src/gallium/frontends/lavapipe/lvp_device.c index 9e932ef..2bb5c71 100644 --- a/src/gallium/frontends/lavapipe/lvp_device.c +++ b/src/gallium/frontends/lavapipe/lvp_device.c @@ -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; diff --git a/src/gallium/frontends/lavapipe/lvp_formats.c b/src/gallium/frontends/lavapipe/lvp_formats.c index a1a2298..8576b3f 100644 --- a/src/gallium/frontends/lavapipe/lvp_formats.c +++ b/src/gallium/frontends/lavapipe/lvp_formats.c @@ -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; } diff --git a/src/gallium/frontends/lavapipe/lvp_image.c b/src/gallium/frontends/lavapipe/lvp_image.c index 2a21447..530a5ee 100644 --- a/src/gallium/frontends/lavapipe/lvp_image.c +++ b/src/gallium/frontends/lavapipe/lvp_image.c @@ -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; +} -- 2.7.4