vkd3d: Handle multiplanar formats in GetCopyableFootprints.

Signed-off-by: Hans-Kristian Arntzen <post@arntzen-software.no>
This commit is contained in:
Hans-Kristian Arntzen 2021-09-01 17:21:58 +02:00
parent b8881ff693
commit 5c2376faf5
3 changed files with 45 additions and 11 deletions

View File

@ -3846,10 +3846,12 @@ static void STDMETHODCALLTYPE d3d12_device_GetCopyableFootprints(d3d12_device_if
{
struct d3d12_device *device = impl_from_ID3D12Device(iface);
static const struct vkd3d_format vkd3d_format_unknown
= {DXGI_FORMAT_UNKNOWN, VK_FORMAT_UNDEFINED, 1, 1, 1, 1, 0};
= {DXGI_FORMAT_UNKNOWN, VK_FORMAT_UNDEFINED, 1, 1, 1, 1, 0, 1};
unsigned int i, sub_resource_idx, miplevel_idx, row_count, row_size, row_pitch;
unsigned int width, height, depth, array_size;
unsigned int width, height, depth, array_size, num_planes, num_subresources;
unsigned int num_subresources_per_plane, plane_idx;
const struct vkd3d_format *plane_format;
const struct vkd3d_format *format;
uint64_t offset, size, total;
@ -3883,10 +3885,13 @@ static void STDMETHODCALLTYPE d3d12_device_GetCopyableFootprints(d3d12_device_if
return;
}
num_planes = format->plane_count;
array_size = d3d12_resource_desc_get_layer_count(desc);
num_subresources_per_plane = d3d12_resource_desc_get_sub_resource_count_per_plane(desc);
num_subresources = num_subresources_per_plane * num_planes;
if (first_sub_resource >= desc->MipLevels * array_size
|| sub_resource_count > desc->MipLevels * array_size - first_sub_resource)
if (first_sub_resource >= num_subresources
|| sub_resource_count > num_subresources - first_sub_resource)
{
WARN("Invalid sub-resource range %u-%u for resource.\n", first_sub_resource, sub_resource_count);
return;
@ -3897,18 +3902,26 @@ static void STDMETHODCALLTYPE d3d12_device_GetCopyableFootprints(d3d12_device_if
for (i = 0; i < sub_resource_count; ++i)
{
sub_resource_idx = first_sub_resource + i;
plane_idx = sub_resource_idx / num_subresources_per_plane;
plane_format = vkd3d_format_footprint_for_plane(device, format, plane_idx);
miplevel_idx = sub_resource_idx % desc->MipLevels;
width = align(d3d12_resource_desc_get_width(desc, miplevel_idx), format->block_width);
height = align(d3d12_resource_desc_get_height(desc, miplevel_idx), format->block_height);
width = align(d3d12_resource_desc_get_width(desc, miplevel_idx), plane_format->block_width);
height = align(d3d12_resource_desc_get_height(desc, miplevel_idx), plane_format->block_height);
depth = d3d12_resource_desc_get_depth(desc, miplevel_idx);
row_count = height / format->block_height;
row_size = (width / format->block_width) * format->byte_count * format->block_byte_count;
row_pitch = align(row_size, D3D12_TEXTURE_DATA_PITCH_ALIGNMENT);
row_count = height / plane_format->block_height;
row_size = (width / plane_format->block_width) * plane_format->byte_count * plane_format->block_byte_count;
/* For whatever reason, we need to use 512 bytes of alignment for depth-stencil formats.
* This is not documented, but it is observed behavior on both NV and WARP drivers.
* See test_get_copyable_footprints_planar(). */
row_pitch = align(row_size, D3D12_TEXTURE_DATA_PITCH_ALIGNMENT * num_planes);
if (layouts)
{
layouts[i].Offset = base_offset + offset;
layouts[i].Footprint.Format = desc->Format;
layouts[i].Footprint.Format = plane_format->dxgi_format;
layouts[i].Footprint.Width = width;
layouts[i].Footprint.Height = height;
layouts[i].Footprint.Depth = depth;
@ -3920,7 +3933,7 @@ static void STDMETHODCALLTYPE d3d12_device_GetCopyableFootprints(d3d12_device_if
row_sizes[i] = row_size;
size = max(0, row_count - 1) * row_pitch + row_size;
size = max(0, depth - 1) * align(size, D3D12_TEXTURE_DATA_PITCH_ALIGNMENT) + size;
size = max(0, depth - 1) * align(size, D3D12_TEXTURE_DATA_PITCH_ALIGNMENT * num_planes) + size;
total = offset + size;
offset = align(total, D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT);

View File

@ -483,6 +483,25 @@ const struct vkd3d_format *vkd3d_get_format(const struct d3d12_device *device,
return format->dxgi_format ? format : NULL;
}
const struct vkd3d_format *vkd3d_format_footprint_for_plane(const struct d3d12_device *device,
const struct vkd3d_format *format, unsigned int plane_idx)
{
switch (format->dxgi_format)
{
case DXGI_FORMAT_R32G8X24_TYPELESS:
case DXGI_FORMAT_R24G8_TYPELESS:
case DXGI_FORMAT_D24_UNORM_S8_UINT:
case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
if (plane_idx == 0)
return vkd3d_get_format(device, DXGI_FORMAT_R32_TYPELESS, false);
else
return vkd3d_get_format(device, DXGI_FORMAT_R8_TYPELESS, false);
default:
return format;
}
}
VkFormat vkd3d_internal_get_vk_format(const struct d3d12_device *device, DXGI_FORMAT dxgi_format)
{
const struct vkd3d_format *format;

View File

@ -2878,6 +2878,8 @@ DXGI_FORMAT vkd3d_get_typeless_format(const struct d3d12_device *device, DXGI_FO
const struct vkd3d_format *vkd3d_find_uint_format(const struct d3d12_device *device,
DXGI_FORMAT dxgi_format);
VkFormat vkd3d_internal_get_vk_format(const struct d3d12_device *device, DXGI_FORMAT dxgi_format);
const struct vkd3d_format *vkd3d_format_footprint_for_plane(const struct d3d12_device *device,
const struct vkd3d_format *format, unsigned int plane_idx);
HRESULT vkd3d_init_format_info(struct d3d12_device *device);
void vkd3d_cleanup_format_info(struct d3d12_device *device);