Signed-off-by: Conor McCarthy cmccarthy@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;