vkd3d: Handle multiple planes in subresource conversion for copies.

Signed-off-by: Hans-Kristian Arntzen <post@arntzen-software.no>
This commit is contained in:
Hans-Kristian Arntzen 2021-05-04 12:54:35 +02:00
parent e02031220a
commit 0e93af9700
4 changed files with 77 additions and 23 deletions

View File

@ -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(&copy->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(&copy->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(&region->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))

View File

@ -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;

View File

@ -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;

View File

@ -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);