Module: vkd3d Branch: master Commit: 4433dacb4f84346365d3be086eb1088a7c33c810 URL: https://gitlab.winehq.org/wine/vkd3d/-/commit/4433dacb4f84346365d3be086eb108...
Author: Conor McCarthy cmccarthy@codeweavers.com Date: Thu May 25 16:45:04 2023 +1000
vkd3d: Implement ID3D12Device::GetResourceTiling() for textures.
---
include/vkd3d_d3d12.idl | 1 + libs/vkd3d/resource.c | 124 +++++++++++++++++++++++++++++++++++++++------ libs/vkd3d/vkd3d_private.h | 1 + 3 files changed, 110 insertions(+), 16 deletions(-)
diff --git a/include/vkd3d_d3d12.idl b/include/vkd3d_d3d12.idl index 9af75f40..4db9e10f 100644 --- a/include/vkd3d_d3d12.idl +++ b/include/vkd3d_d3d12.idl @@ -45,6 +45,7 @@ const UINT D3D12_DEFAULT_STENCIL_WRITE_MASK = 0xff; const UINT D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND = 0xffffffff; cpp_quote("#define D3D12_FLOAT32_MAX (3.402823466e+38f)") const UINT D3D12_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT = 32; +const UINT D3D12_PACKED_TILE = 0xffffffff; const UINT D3D12_UAV_SLOT_COUNT = 64; const UINT D3D12_REQ_CONSTANT_BUFFER_ELEMENT_COUNT = 4096; const UINT D3D12_REQ_IMMEDIATE_CONSTANT_BUFFER_ELEMENT_COUNT = 4096; diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c index 7550e21f..cd3856c2 100644 --- a/libs/vkd3d/resource.c +++ b/libs/vkd3d/resource.c @@ -1064,29 +1064,38 @@ static void d3d12_resource_get_level_box(const struct d3d12_resource *resource, box->back = d3d12_resource_desc_get_depth(&resource->desc, level); }
+static void compute_image_subresource_size_in_tiles(const VkExtent3D *tile_extent, + const struct D3D12_RESOURCE_DESC *desc, unsigned int miplevel_idx, + struct vkd3d_tiled_region_extent *size) +{ + unsigned int width, height, depth; + + width = d3d12_resource_desc_get_width(desc, miplevel_idx); + height = d3d12_resource_desc_get_height(desc, miplevel_idx); + depth = d3d12_resource_desc_get_depth(desc, miplevel_idx); + size->width = (width + tile_extent->width - 1) / tile_extent->width; + size->height = (height + tile_extent->height - 1) / tile_extent->height; + size->depth = (depth + tile_extent->depth - 1) / tile_extent->depth; +} + void d3d12_resource_get_tiling(struct d3d12_device *device, const struct d3d12_resource *resource, UINT *total_tile_count, D3D12_PACKED_MIP_INFO *packed_mip_info, D3D12_TILE_SHAPE *standard_tile_shape, UINT *subresource_tiling_count, UINT first_subresource_tiling, D3D12_SUBRESOURCE_TILING *subresource_tilings) { - unsigned int i, subresource, subresource_count, count; + unsigned int i, subresource, subresource_count, miplevel_idx, count; const struct vkd3d_subresource_tile_info *tile_info; const VkExtent3D *tile_extent;
- if (d3d12_resource_is_texture(resource)) - { - FIXME("Not implemented for textures.\n"); - return; - } - tile_extent = &resource->tiles.tile_extent;
if (packed_mip_info) { packed_mip_info->NumStandardMips = resource->tiles.standard_mip_count; - packed_mip_info->NumPackedMips = 0; - packed_mip_info->NumTilesForPackedMips = 0; - packed_mip_info->StartTileIndexInOverallResource = 0; + packed_mip_info->NumPackedMips = resource->desc.MipLevels - packed_mip_info->NumStandardMips; + packed_mip_info->NumTilesForPackedMips = !!resource->tiles.packed_mip_tile_count; /* non-zero dummy value */ + packed_mip_info->StartTileIndexInOverallResource = packed_mip_info->NumPackedMips + ? resource->tiles.subresources[resource->tiles.standard_mip_count].offset : 0; }
if (standard_tile_shape) @@ -1111,6 +1120,14 @@ void d3d12_resource_get_tiling(struct d3d12_device *device, const struct d3d12_r for (i = 0; i < count; ++i) { subresource = i + first_subresource_tiling; + miplevel_idx = subresource % resource->desc.MipLevels; + if (miplevel_idx >= resource->tiles.standard_mip_count) + { + memset(&subresource_tilings[i], 0, sizeof(subresource_tilings[i])); + subresource_tilings[i].StartTileIndexInOverallResource = D3D12_PACKED_TILE; + continue; + } + tile_info = &resource->tiles.subresources[subresource]; subresource_tilings[i].StartTileIndexInOverallResource = tile_info->offset; subresource_tilings[i].WidthInTiles = tile_info->extent.width; @@ -1122,21 +1139,26 @@ void d3d12_resource_get_tiling(struct d3d12_device *device, const struct d3d12_r
static bool d3d12_resource_init_tiles(struct d3d12_resource *resource, struct d3d12_device *device) { + unsigned int i, start_idx, subresource_count, tile_count, miplevel_idx; const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; + VkSparseImageMemoryRequirements *sparse_requirements_array; + VkSparseImageMemoryRequirements sparse_requirements = {0}; struct vkd3d_subresource_tile_info *tile_info; VkMemoryRequirements requirements; - unsigned int subresource_count; + const VkExtent3D *tile_extent; + uint32_t requirement_count;
subresource_count = d3d12_resource_desc_get_sub_resource_count(&resource->desc);
+ if (!(resource->tiles.subresources = vkd3d_calloc(subresource_count, sizeof(*resource->tiles.subresources)))) + { + ERR("Failed to allocate subresource info array.\n"); + return false; + } + if (d3d12_resource_is_buffer(resource)) { assert(subresource_count == 1); - if (!(resource->tiles.subresources = vkd3d_calloc(subresource_count, sizeof(*resource->tiles.subresources)))) - { - ERR("Failed to allocate subresource info array.\n"); - return false; - }
VK_CALL(vkGetBufferMemoryRequirements(device->vk_device, resource->u.vk_buffer, &requirements)); if (requirements.alignment > D3D12_TILED_RESOURCE_TILE_SIZE_IN_BYTES) @@ -1156,6 +1178,76 @@ static bool d3d12_resource_init_tiles(struct d3d12_resource *resource, struct d3 resource->tiles.total_count = tile_info->extent.width; resource->tiles.subresource_count = 1; resource->tiles.standard_mip_count = 1; + resource->tiles.packed_mip_tile_count = 0; + } + else + { + VK_CALL(vkGetImageMemoryRequirements(device->vk_device, resource->u.vk_image, &requirements)); + if (requirements.alignment > D3D12_TILED_RESOURCE_TILE_SIZE_IN_BYTES) + FIXME("Vulkan device tile size is greater than the standard D3D12 tile size.\n"); + + requirement_count = 0; + VK_CALL(vkGetImageSparseMemoryRequirements(device->vk_device, resource->u.vk_image, &requirement_count, NULL)); + if (!(sparse_requirements_array = vkd3d_calloc(requirement_count, sizeof(*sparse_requirements_array)))) + { + ERR("Failed to allocate sparse requirements array.\n"); + return false; + } + VK_CALL(vkGetImageSparseMemoryRequirements(device->vk_device, resource->u.vk_image, + &requirement_count, sparse_requirements_array)); + + for (i = 0; i < requirement_count; ++i) + { + if (sparse_requirements_array[i].formatProperties.aspectMask & resource->format->vk_aspect_mask) + { + if (sparse_requirements.formatProperties.aspectMask) + { + WARN("Ignoring properties for aspect mask %#x.\n", + sparse_requirements_array[i].formatProperties.aspectMask); + } + else + { + sparse_requirements = sparse_requirements_array[i]; + } + } + } + vkd3d_free(sparse_requirements_array); + if (!sparse_requirements.formatProperties.aspectMask) + { + WARN("Failed to get sparse requirements.\n"); + return false; + } + + resource->tiles.tile_extent = sparse_requirements.formatProperties.imageGranularity; + resource->tiles.subresource_count = subresource_count; + resource->tiles.standard_mip_count = sparse_requirements.imageMipTailSize + ? sparse_requirements.imageMipTailFirstLod : resource->desc.MipLevels; + resource->tiles.packed_mip_tile_count = (resource->tiles.standard_mip_count < resource->desc.MipLevels) + ? sparse_requirements.imageMipTailSize / requirements.alignment : 0; + + for (i = 0, start_idx = 0; i < subresource_count; ++i) + { + miplevel_idx = i % resource->desc.MipLevels; + + tile_extent = &sparse_requirements.formatProperties.imageGranularity; + tile_info = &resource->tiles.subresources[i]; + compute_image_subresource_size_in_tiles(tile_extent, &resource->desc, miplevel_idx, &tile_info->extent); + tile_info->offset = start_idx; + tile_info->count = 0; + + if (miplevel_idx < resource->tiles.standard_mip_count) + { + tile_count = tile_info->extent.width * tile_info->extent.height * tile_info->extent.depth; + start_idx += tile_count; + tile_info->count = tile_count; + } + else if (miplevel_idx == resource->tiles.standard_mip_count) + { + tile_info->count = 1; /* Non-zero dummy value */ + start_idx += 1; + } + } + resource->tiles.total_count = start_idx; }
return true; diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h index 4f9177d2..e1127799 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -706,6 +706,7 @@ struct d3d12_resource_tile_info VkExtent3D tile_extent; unsigned int total_count; unsigned int standard_mip_count; + unsigned int packed_mip_tile_count; unsigned int subresource_count; struct vkd3d_subresource_tile_info *subresources; };