[PATCH 1/2] vkd3d: Implement ID3D12Resource::ReadFromSubresource().

Conor McCarthy cmccarthy at codeweavers.com
Wed Jul 31 06:23:49 CDT 2019


Signed-off-by: Conor McCarthy <cmccarthy at codeweavers.com>
---
 libs/vkd3d/command.c       |  2 +-
 libs/vkd3d/resource.c      | 93 ++++++++++++++++++++++++++++++++++++--
 libs/vkd3d/vkd3d_private.h |  2 +
 3 files changed, 93 insertions(+), 4 deletions(-)

diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c
index bbd398c..16613e5 100644
--- a/libs/vkd3d/command.c
+++ b/libs/vkd3d/command.c
@@ -3126,7 +3126,7 @@ static void STDMETHODCALLTYPE d3d12_command_list_CopyBufferRegion(ID3D12Graphics
             src_resource->u.vk_buffer, dst_resource->u.vk_buffer, 1, &buffer_copy));
 }
 
-static void vk_image_subresource_layers_from_d3d12(VkImageSubresourceLayers *subresource,
+void vk_image_subresource_layers_from_d3d12(VkImageSubresourceLayers *subresource,
         const struct vkd3d_format *format, unsigned int sub_resource_idx, unsigned int miplevel_count)
 {
     subresource->aspectMask = format->vk_aspect_mask;
diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c
index e0e1aad..35290f3 100644
--- a/libs/vkd3d/resource.c
+++ b/libs/vkd3d/resource.c
@@ -1205,12 +1205,99 @@ static HRESULT STDMETHODCALLTYPE d3d12_resource_ReadFromSubresource(ID3D12Resour
         void *dst_data, UINT dst_row_pitch, UINT dst_slice_pitch,
         UINT src_sub_resource, const D3D12_BOX *src_box)
 {
-    FIXME("iface %p, dst_data %p, dst_row_pitch %u, dst_slice_pitch %u, "
-            "src_sub_resource %u, src_box %p stub!\n",
+    struct d3d12_resource *resource = impl_from_ID3D12Resource(iface);
+    const struct vkd3d_vk_device_procs *vk_procs;
+    VkImageSubresourceLayers vk_sub_layers;
+    VkImageSubresource vk_sub_resource;
+    const struct vkd3d_format *format;
+    VkSubresourceLayout vk_layout;
+    struct d3d12_device *device;
+    void *src_map_ptr;
+    D3D12_BOX box;
+    HRESULT hr;
+    BYTE *dst;
+    UINT z;
+
+    TRACE("iface %p, dst_data %p, dst_row_pitch %u, dst_slice_pitch %u, "
+            "src_sub_resource %u, src_box %p\n",
             iface, dst_data, dst_row_pitch, dst_slice_pitch,
             src_sub_resource, src_box);
 
-    return E_NOTIMPL;
+    if (src_box)
+    {
+        box = *src_box;
+    }
+    else
+    {
+        box.left = 0;
+        box.top = 0;
+        box.front = 0;
+        box.right = resource->desc.Width;
+        box.bottom = resource->desc.Height;
+        box.back = d3d12_resource_desc_get_depth(&resource->desc, 0);
+    }
+    if (box.right <= box.left || box.bottom <= box.top || box.back <= box.front)
+        return S_OK;
+
+    if (d3d12_resource_is_buffer(resource))
+    {
+        WARN("Buffers are not supported.\n");
+        return E_INVALIDARG;
+    }
+
+    if (!resource->heap)
+    {
+        FIXME("Not implemented for this resource type.\n");
+        return E_NOTIMPL;
+    }
+
+    device = resource->device;
+    vk_procs = &device->vk_procs;
+
+    if (!(format = vkd3d_format_from_d3d12_resource_desc(device, &resource->desc, 0)))
+    {
+        WARN("Invalid DXGI format %#x.\n", resource->desc.Format);
+        return E_INVALIDARG;
+    }
+
+    if (FAILED(hr = d3d12_heap_map(resource->heap, resource->heap_offset, resource, &src_map_ptr)))
+    {
+        WARN("Failed to map resource %p, hr %#x.\n", resource, hr);
+        return hr;
+    }
+
+    if (resource->desc.Layout != D3D12_TEXTURE_LAYOUT_ROW_MAJOR)
+        FIXME_ONCE("Layouts other than D3D12_TEXTURE_LAYOUT_ROW_MAJOR are not supported and results are implementation-dependent.\n");
+
+    vk_image_subresource_layers_from_d3d12(&vk_sub_layers, format, src_sub_resource, resource->desc.MipLevels);
+    vk_sub_resource.arrayLayer = vk_sub_layers.baseArrayLayer;
+    vk_sub_resource.mipLevel = vk_sub_layers.mipLevel;
+    vk_sub_resource.aspectMask = vk_sub_layers.aspectMask;
+
+    VK_CALL(vkGetImageSubresourceLayout(device->vk_device, resource->u.vk_image, &vk_sub_resource, &vk_layout));
+    TRACE("offset %#"PRIx64", size %#"PRIx64", rowPitch %#"PRIx64", arrayPitch %#"PRIx64", depthPitch %#"PRIx64".\n",
+            vk_layout.offset, vk_layout.size, vk_layout.rowPitch, vk_layout.arrayPitch, vk_layout.depthPitch);
+
+    src_map_ptr = (BYTE*)src_map_ptr + vk_layout.offset;
+    for (z = box.front; z < box.back; ++z)
+    {
+        UINT y;
+        dst = dst_data + (z - box.front) * dst_slice_pitch;
+        for (y = box.top; y < box.bottom; y += format->block_height)
+        {
+            SIZE_T size = (box.right - box.left) / format->block_width
+                    * format->byte_count * format->block_byte_count;
+            const BYTE *src = (BYTE*)src_map_ptr + z * vk_layout.depthPitch
+                    + y / format->block_height * vk_layout.rowPitch
+                    + box.left / format->block_width * format->byte_count * format->block_byte_count;
+            memcpy(dst, src, size);
+            dst += dst_row_pitch;
+        }
+    }
+
+    d3d12_heap_unmap(resource->heap, resource);
+
+    return S_OK;
 }
 
 static HRESULT STDMETHODCALLTYPE d3d12_resource_GetHeapProperties(ID3D12Resource *iface,
diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h
index 82d56c2..cd3f904 100644
--- a/libs/vkd3d/vkd3d_private.h
+++ b/libs/vkd3d/vkd3d_private.h
@@ -1176,6 +1176,8 @@ static inline unsigned int d3d12_resource_desc_get_sub_resource_count(const D3D1
 }
 
 VkCompareOp vk_compare_op_from_d3d12(D3D12_COMPARISON_FUNC op) DECLSPEC_HIDDEN;
+void vk_image_subresource_layers_from_d3d12(VkImageSubresourceLayers *subresource,
+        const struct vkd3d_format *format, unsigned int sub_resource_idx, unsigned int miplevel_count) DECLSPEC_HIDDEN;
 VkSampleCountFlagBits vk_samples_from_dxgi_sample_desc(const DXGI_SAMPLE_DESC *desc) DECLSPEC_HIDDEN;
 VkSampleCountFlagBits vk_samples_from_sample_count(unsigned int sample_count) DECLSPEC_HIDDEN;
 
-- 
2.22.0




More information about the wine-devel mailing list