From 0e93af970014158ae8439dc39f784eeb6e5d29b6 Mon Sep 17 00:00:00 2001 From: Hans-Kristian Arntzen Date: Tue, 4 May 2021 12:54:35 +0200 Subject: [PATCH] vkd3d: Handle multiple planes in subresource conversion for copies. Signed-off-by: Hans-Kristian Arntzen --- libs/vkd3d/command.c | 46 +++++++++++++++++++++++++++++--------- libs/vkd3d/meta.c | 15 ++++++++++--- libs/vkd3d/resource.c | 28 +++++++++++++++++------ libs/vkd3d/vkd3d_private.h | 11 +++++++-- 4 files changed, 77 insertions(+), 23 deletions(-) diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c index 30fa873f..75627b1a 100644 --- a/libs/vkd3d/command.c +++ b/libs/vkd3d/command.c @@ -5166,11 +5166,15 @@ static void STDMETHODCALLTYPE d3d12_command_list_CopyBufferRegion(d3d12_command_ } static void vk_image_subresource_layers_from_d3d12(VkImageSubresourceLayers *subresource, - const struct vkd3d_format *format, unsigned int sub_resource_idx, unsigned int miplevel_count) + const struct vkd3d_format *format, unsigned int sub_resource_idx, + unsigned int miplevel_count, unsigned int layer_count, bool all_aspects) { - subresource->aspectMask = format->vk_aspect_mask; - subresource->mipLevel = sub_resource_idx % miplevel_count; - subresource->baseArrayLayer = sub_resource_idx / miplevel_count; + VkImageSubresource sub = vk_image_subresource_from_d3d12( + format, sub_resource_idx, miplevel_count, layer_count, all_aspects); + + subresource->aspectMask = sub.aspectMask; + subresource->mipLevel = sub.mipLevel; + subresource->baseArrayLayer = sub.arrayLayer; subresource->layerCount = 1; } @@ -5198,7 +5202,8 @@ static void vk_buffer_image_copy_from_d3d12(VkBufferImageCopy *copy, (format->byte_count * format->block_byte_count) * format->block_width; copy->bufferImageHeight = footprint->Footprint.Height; vk_image_subresource_layers_from_d3d12(©->imageSubresource, - format, sub_resource_idx, image_desc->MipLevels); + format, sub_resource_idx, image_desc->MipLevels, + d3d12_resource_desc_get_layer_count(image_desc), true); copy->imageOffset.x = dst_x; copy->imageOffset.y = dst_y; copy->imageOffset.z = dst_z; @@ -5236,7 +5241,8 @@ static void vk_image_buffer_copy_from_d3d12(VkBufferImageCopy *copy, (format->byte_count * format->block_byte_count) * format->block_width; copy->bufferImageHeight = footprint->Footprint.Height; vk_image_subresource_layers_from_d3d12(©->imageSubresource, - format, sub_resource_idx, image_desc->MipLevels); + format, sub_resource_idx, image_desc->MipLevels, + d3d12_resource_desc_get_layer_count(image_desc), false); copy->imageOffset.x = src_box ? src_box->left : 0; copy->imageOffset.y = src_box ? src_box->top : 0; copy->imageOffset.z = src_box ? src_box->front : 0; @@ -5260,12 +5266,14 @@ static void vk_image_copy_from_d3d12(VkImageCopy *image_copy, const D3D12_BOX *src_box, unsigned int dst_x, unsigned int dst_y, unsigned int dst_z) { vk_image_subresource_layers_from_d3d12(&image_copy->srcSubresource, - src_format, src_sub_resource_idx, src_desc->MipLevels); + src_format, src_sub_resource_idx, src_desc->MipLevels, + d3d12_resource_desc_get_sub_resource_count(src_desc), false); image_copy->srcOffset.x = src_box ? src_box->left : 0; image_copy->srcOffset.y = src_box ? src_box->top : 0; image_copy->srcOffset.z = src_box ? src_box->front : 0; vk_image_subresource_layers_from_d3d12(&image_copy->dstSubresource, - dst_format, dst_sub_resource_idx, dst_desc->MipLevels); + dst_format, dst_sub_resource_idx, dst_desc->MipLevels, + d3d12_resource_desc_get_layer_count(dst_desc), true); image_copy->dstOffset.x = dst_x; image_copy->dstOffset.y = dst_y; image_copy->dstOffset.z = dst_z; @@ -5368,6 +5376,13 @@ static void d3d12_command_list_copy_image(struct d3d12_command_list *list, vk_image_barriers[1].image = src_resource->res.vk_image; vk_image_barriers[1].subresourceRange = vk_subresource_range_from_layers(®ion->srcSubresource); + /* If we're copying from a depth or stencil image we can only sample from one aspect, + * but barriers needs to cover the entire resource. + * We can avoid this requirement with VK_KHR_separate_depth_stencil_layouts, + * but there is no compelling reason to require that just for this case. */ + vk_image_barriers[0].subresourceRange.aspectMask = dst_resource->format->vk_aspect_mask; + vk_image_barriers[1].subresourceRange.aspectMask = src_resource->format->vk_aspect_mask; + VK_CALL(vkCmdPipelineBarrier(list->vk_command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, src_stages | dst_stages, 0, 0, NULL, 0, NULL, ARRAY_SIZE(vk_image_barriers), @@ -5384,7 +5399,9 @@ static void d3d12_command_list_copy_image(struct d3d12_command_list *list, { dst_view = src_view = NULL; - if (!(dst_format = vkd3d_meta_get_copy_image_attachment_format(&list->device->meta_ops, dst_format, src_format))) + if (!(dst_format = vkd3d_meta_get_copy_image_attachment_format(&list->device->meta_ops, dst_format, src_format, + region->dstSubresource.aspectMask, + region->srcSubresource.aspectMask))) { ERR("No attachment format found for source format %u.\n", src_format->vk_format); goto cleanup; @@ -5413,6 +5430,7 @@ static void d3d12_command_list_copy_image(struct d3d12_command_list *list, dst_view_desc.miplevel_count = 1; dst_view_desc.layer_idx = region->dstSubresource.baseArrayLayer; dst_view_desc.layer_count = region->dstSubresource.layerCount; + dst_view_desc.aspect_mask = region->dstSubresource.aspectMask; dst_view_desc.allowed_swizzle = false; memset(&src_view_desc, 0, sizeof(src_view_desc)); @@ -5424,6 +5442,7 @@ static void d3d12_command_list_copy_image(struct d3d12_command_list *list, src_view_desc.miplevel_count = 1; src_view_desc.layer_idx = region->srcSubresource.baseArrayLayer; src_view_desc.layer_count = region->srcSubresource.layerCount; + src_view_desc.aspect_mask = region->srcSubresource.aspectMask; src_view_desc.allowed_swizzle = false; if (!vkd3d_create_texture_view(list->device, &dst_view_desc, &dst_view) || @@ -5969,10 +5988,14 @@ static void STDMETHODCALLTYPE d3d12_command_list_ResolveSubresource(d3d12_comman } vk_image_subresource_layers_from_d3d12(&vk_image_resolve.srcSubresource, - src_resource->format, src_sub_resource_idx, src_resource->desc.MipLevels); + src_resource->format, src_sub_resource_idx, + src_resource->desc.MipLevels, + d3d12_resource_desc_get_layer_count(&src_resource->desc), false); memset(&vk_image_resolve.srcOffset, 0, sizeof(vk_image_resolve.srcOffset)); vk_image_subresource_layers_from_d3d12(&vk_image_resolve.dstSubresource, - dst_resource->format, dst_sub_resource_idx, dst_resource->desc.MipLevels); + dst_resource->format, dst_sub_resource_idx, + dst_resource->desc.MipLevels, + d3d12_resource_desc_get_layer_count(&dst_resource->desc), false); memset(&vk_image_resolve.dstOffset, 0, sizeof(vk_image_resolve.dstOffset)); vk_extent_3d_from_d3d12_miplevel(&vk_image_resolve.extent, &dst_resource->desc, vk_image_resolve.dstSubresource.mipLevel); @@ -7489,6 +7512,7 @@ static void STDMETHODCALLTYPE d3d12_command_list_ClearUnorderedAccessViewUint(d3 view_desc.miplevel_count = 1; view_desc.layer_idx = base_view->info.texture.layer_idx; view_desc.layer_count = base_view->info.texture.layer_count; + view_desc.aspect_mask = view_desc.format->vk_aspect_mask; view_desc.allowed_swizzle = false; if (!vkd3d_create_texture_view(list->device, &view_desc, &args.u.view)) diff --git a/libs/vkd3d/meta.c b/libs/vkd3d/meta.c index eac0c4fc..8b2db19c 100644 --- a/libs/vkd3d/meta.c +++ b/libs/vkd3d/meta.c @@ -899,23 +899,32 @@ VkImageViewType vkd3d_meta_get_copy_image_view_type(D3D12_RESOURCE_DIMENSION dim } const struct vkd3d_format *vkd3d_meta_get_copy_image_attachment_format(struct vkd3d_meta_ops *meta_ops, - const struct vkd3d_format *dst_format, const struct vkd3d_format *src_format) + const struct vkd3d_format *dst_format, const struct vkd3d_format *src_format, + VkImageAspectFlags dst_aspect, VkImageAspectFlags src_aspect) { DXGI_FORMAT dxgi_format = DXGI_FORMAT_UNKNOWN; - if (dst_format->vk_aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT) + if (dst_aspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) return dst_format; - assert(src_format->vk_aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT); + assert(src_aspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)); switch (src_format->vk_format) { case VK_FORMAT_D16_UNORM: dxgi_format = DXGI_FORMAT_R16_UNORM; break; + case VK_FORMAT_D16_UNORM_S8_UINT: + dxgi_format = (src_aspect & VK_IMAGE_ASPECT_DEPTH_BIT) ? + DXGI_FORMAT_R16_UNORM : DXGI_FORMAT_R8_UINT; + break; case VK_FORMAT_D32_SFLOAT: dxgi_format = DXGI_FORMAT_R32_FLOAT; break; + case VK_FORMAT_D32_SFLOAT_S8_UINT: + dxgi_format = (src_aspect & VK_IMAGE_ASPECT_DEPTH_BIT) ? + DXGI_FORMAT_R32_FLOAT : DXGI_FORMAT_R8_UINT; + break; default: ERR("Unhandled format %u.\n", src_format->vk_format); return NULL; diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c index f036abfc..6240d9b8 100644 --- a/libs/vkd3d/resource.c +++ b/libs/vkd3d/resource.c @@ -1759,21 +1759,23 @@ struct d3d12_resource *unsafe_impl_from_ID3D12Resource(ID3D12Resource *iface) return unsafe_impl_from_ID3D12Resource1((ID3D12Resource1 *)iface); } -VkImageSubresource d3d12_resource_get_vk_subresource(const struct d3d12_resource *resource, uint32_t subresource_idx, bool all_aspects) +VkImageSubresource vk_image_subresource_from_d3d12( + const struct vkd3d_format *format, uint32_t subresource_idx, + unsigned int miplevel_count, unsigned int layer_count, + bool all_aspects) { - uint32_t layer_count = d3d12_resource_desc_get_layer_count(&resource->desc); VkImageSubresource subresource; - subresource.aspectMask = resource->format->vk_aspect_mask; - subresource.mipLevel = subresource_idx % resource->desc.MipLevels; - subresource.arrayLayer = (subresource_idx / resource->desc.MipLevels) % layer_count; + subresource.aspectMask = format->vk_aspect_mask; + subresource.mipLevel = subresource_idx % miplevel_count; + subresource.arrayLayer = (subresource_idx / miplevel_count) % layer_count; if (!all_aspects) { /* For all formats we currently handle, the n-th aspect bit in Vulkan * corresponds to the n-th plane in D3D12, so isolate the respective * bit in the aspect mask. */ - uint32_t i, plane_idx = subresource_idx / d3d12_resource_desc_get_sub_resource_count(&resource->desc); + uint32_t i, plane_idx = subresource_idx / (miplevel_count * layer_count); for (i = 0; i < plane_idx; i++) subresource.aspectMask &= (subresource.aspectMask - 1); @@ -1784,6 +1786,15 @@ VkImageSubresource d3d12_resource_get_vk_subresource(const struct d3d12_resource return subresource; } +VkImageSubresource d3d12_resource_get_vk_subresource(const struct d3d12_resource *resource, + uint32_t subresource_idx, bool all_aspects) +{ + return vk_image_subresource_from_d3d12( + resource->format, subresource_idx, + resource->desc.MipLevels, d3d12_resource_desc_get_layer_count(&resource->desc), + all_aspects); +} + static void d3d12_validate_resource_flags(D3D12_RESOURCE_FLAGS flags) { unsigned int unknown_flags = flags & ~(D3D12_RESOURCE_FLAG_NONE @@ -3281,6 +3292,7 @@ static bool init_default_texture_view_desc(struct vkd3d_texture_view_desc *desc, return false; } + desc->aspect_mask = desc->format->vk_aspect_mask; desc->image = resource->res.vk_image; desc->layout = resource->common_layout; desc->miplevel_idx = 0; @@ -3336,7 +3348,7 @@ bool vkd3d_create_texture_view(struct d3d12_device *device, const struct vkd3d_t vkd3d_set_view_swizzle_for_format(&view_desc.components, format, desc->allowed_swizzle); if (desc->allowed_swizzle) vk_component_mapping_compose(&view_desc.components, &desc->components); - view_desc.subresourceRange.aspectMask = format->vk_aspect_mask; + view_desc.subresourceRange.aspectMask = desc->aspect_mask; view_desc.subresourceRange.baseMipLevel = desc->miplevel_idx; view_desc.subresourceRange.levelCount = desc->miplevel_count; view_desc.subresourceRange.baseArrayLayer = desc->layer_idx; @@ -3840,6 +3852,7 @@ static void vkd3d_create_texture_srv(struct d3d12_desc *descriptor, key.u.texture.components.b = VK_COMPONENT_SWIZZLE_ZERO; key.u.texture.components.a = VK_COMPONENT_SWIZZLE_ZERO; key.u.texture.allowed_swizzle = true; + key.u.texture.aspect_mask = key.u.texture.format->vk_aspect_mask; if (!(view = vkd3d_view_map_create_view(&device->null_resources.view_map, device, &key))) return; @@ -4199,6 +4212,7 @@ static void vkd3d_create_texture_uav(struct d3d12_desc *descriptor, key.u.texture.components.b = VK_COMPONENT_SWIZZLE_B; key.u.texture.components.a = VK_COMPONENT_SWIZZLE_A; key.u.texture.allowed_swizzle = false; + key.u.texture.aspect_mask = key.u.texture.format->vk_aspect_mask; if (!(view = vkd3d_view_map_create_view(&device->null_resources.view_map, device, &key))) return; diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h index 33e2d0cd..23ba80f1 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -840,7 +840,12 @@ LONG64 vkd3d_allocate_cookie(); bool d3d12_resource_is_cpu_accessible(const struct d3d12_resource *resource); HRESULT d3d12_resource_validate_desc(const D3D12_RESOURCE_DESC *desc, struct d3d12_device *device); -VkImageSubresource d3d12_resource_get_vk_subresource(const struct d3d12_resource *resource, uint32_t subresource_idx, bool all_aspects); +VkImageSubresource d3d12_resource_get_vk_subresource(const struct d3d12_resource *resource, + uint32_t subresource_idx, bool all_aspects); +VkImageSubresource vk_image_subresource_from_d3d12( + const struct vkd3d_format *format, uint32_t subresource_idx, + unsigned int miplevel_count, unsigned int layer_count, + bool all_aspects); HRESULT d3d12_resource_create_committed(struct d3d12_device *device, const D3D12_RESOURCE_DESC *desc, const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags, D3D12_RESOURCE_STATES initial_state, @@ -922,6 +927,7 @@ struct vkd3d_texture_view_desc VkImage image; VkImageViewType view_type; VkImageLayout layout; + VkImageAspectFlags aspect_mask; const struct vkd3d_format *format; unsigned int miplevel_idx; unsigned int miplevel_count; @@ -2433,7 +2439,8 @@ HRESULT vkd3d_meta_get_copy_image_pipeline(struct vkd3d_meta_ops *meta_ops, const struct vkd3d_copy_image_pipeline_key *key, struct vkd3d_copy_image_info *info); VkImageViewType vkd3d_meta_get_copy_image_view_type(D3D12_RESOURCE_DIMENSION dim); const struct vkd3d_format *vkd3d_meta_get_copy_image_attachment_format(struct vkd3d_meta_ops *meta_ops, - const struct vkd3d_format *dst_format, const struct vkd3d_format *src_format); + const struct vkd3d_format *dst_format, const struct vkd3d_format *src_format, + VkImageAspectFlags dst_aspect, VkImageAspectFlags src_aspect); HRESULT vkd3d_meta_get_swapchain_pipeline(struct vkd3d_meta_ops *meta_ops, const struct vkd3d_swapchain_pipeline_key *key, struct vkd3d_swapchain_info *info);