From: Conor McCarthy cmccarthy@codeweavers.com
--- include/vkd3d_d3d12.idl | 1 + libs/vkd3d/device.c | 6 --- libs/vkd3d/resource.c | 90 ++++++++++++++++++++++++++++++++++---- libs/vkd3d/vkd3d_private.h | 1 + tests/d3d12.c | 14 ++---- 5 files changed, 87 insertions(+), 25 deletions(-)
diff --git a/include/vkd3d_d3d12.idl b/include/vkd3d_d3d12.idl index 06287f5a8..495a04678 100644 --- a/include/vkd3d_d3d12.idl +++ b/include/vkd3d_d3d12.idl @@ -75,6 +75,7 @@ const UINT D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT = 512; const UINT D3D12_UAV_COUNTER_PLACEMENT_ALIGNMENT = 4096; const UINT D3D12_VS_INPUT_REGISTER_COUNT = 32; const UINT D3D12_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE = 16; +const UINT D3D12_PACKED_TILE = 0xffffffff;
cpp_quote("#endif")
diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c index 69dbb8705..b1eba634f 100644 --- a/libs/vkd3d/device.c +++ b/libs/vkd3d/device.c @@ -3900,12 +3900,6 @@ static void STDMETHODCALLTYPE d3d12_device_GetResourceTiling(ID3D12Device *iface sub_resource_tiling_count, first_sub_resource_tiling, sub_resource_tilings);
- if (d3d12_resource_is_texture(resource_impl)) - { - FIXME("Not implemented for textures.\n"); - return; - } - d3d12_resource_get_tiling(device, resource_impl, total_tile_count, packed_mip_info, standard_tile_shape, sub_resource_tiling_count, first_sub_resource_tiling, sub_resource_tilings); } diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c index c50d6241f..a6e76f197 100644 --- a/libs/vkd3d/resource.c +++ b/libs/vkd3d/resource.c @@ -1065,12 +1065,26 @@ 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;
@@ -1079,9 +1093,10 @@ void d3d12_resource_get_tiling(struct d3d12_device *device, const struct d3d12_r 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) @@ -1106,6 +1121,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; @@ -1117,14 +1140,17 @@ 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_buf[3]; + VkSparseImageMemoryRequirements sparse_requirements; struct vkd3d_subresource_tile_info *tile_info; - unsigned int subresource_count; + VkMemoryRequirements requirements; + const VkExtent3D *tile_extent; + uint32_t requirement_count;
subresource_count = d3d12_resource_desc_get_sub_resource_count(&resource->desc);
- if (!d3d12_resource_is_buffer(resource)) - return true; - if (!(resource->tiles.subresources = vkd3d_calloc(subresource_count, sizeof(*resource->tiles.subresources)))) { ERR("Failed to allocate subresource info array.\n"); @@ -1146,10 +1172,56 @@ 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 { - vkd3d_unreachable(); + VK_CALL(vkGetImageMemoryRequirements(device->vk_device, resource->u.vk_image, &requirements)); + if (requirements.alignment > D3D12_TILE_SIZE) + FIXME("Vulkan device tile size is greater than the standard D3D12 tile size.\n"); + + requirement_count = ARRAY_SIZE(sparse_requirements_buf); + VK_CALL(vkGetImageSparseMemoryRequirements(device->vk_device, resource->u.vk_image, + &requirement_count, sparse_requirements_buf)); + for (i = 0; i < requirement_count; ++i) + { + if (!(sparse_requirements_buf[i].formatProperties.aspectMask & VK_IMAGE_ASPECT_METADATA_BIT)) + { + sparse_requirements = sparse_requirements_buf[i]; + break; + } + } + + 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 b545945a5..859844684 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -691,6 +691,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; }; diff --git a/tests/d3d12.c b/tests/d3d12.c index 2801ec45a..6db1a79d0 100644 --- a/tests/d3d12.c +++ b/tests/d3d12.c @@ -36588,18 +36588,18 @@ static void test_get_resource_tiling(void)
num_tilings = ARRAY_SIZE(tilings); ID3D12Device_GetResourceTiling(context.device, resource, NULL, NULL, NULL, &num_tilings, 10, tilings); - todo ok(num_tilings == 0, "Unexpected tiling count %u.\n", num_tilings); + ok(num_tilings == 0, "Unexpected tiling count %u.\n", num_tilings);
num_tilings = ARRAY_SIZE(tilings); ID3D12Device_GetResourceTiling(context.device, resource, NULL, NULL, NULL, &num_tilings, 2, tilings); - todo ok(num_tilings == 8, "Unexpected tiling count %u.\n", num_tilings); - todo ok(tilings[0].StartTileIndexInOverallResource == 20, "Unexpected start tile index %u.\n", tilings[0].StartTileIndexInOverallResource); + ok(num_tilings == 8, "Unexpected tiling count %u.\n", num_tilings); + ok(tilings[0].StartTileIndexInOverallResource == 20, "Unexpected start tile index %u.\n", tilings[0].StartTileIndexInOverallResource);
num_tilings = 1; memset(&tilings, 0xaa, sizeof(tilings)); ID3D12Device_GetResourceTiling(context.device, resource, NULL, NULL, NULL, &num_tilings, 2, tilings); ok(num_tilings == 1, "Unexpected tiling count %u.\n", num_tilings); - todo ok(tilings[0].StartTileIndexInOverallResource == 20, "Unexpected start tile index %u.\n", tilings[0].StartTileIndexInOverallResource); + ok(tilings[0].StartTileIndexInOverallResource == 20, "Unexpected start tile index %u.\n", tilings[0].StartTileIndexInOverallResource); ok(tilings[1].StartTileIndexInOverallResource == 0xaaaaaaaa, "Tiling array got modified.\n");
ID3D12Resource_Release(resource); @@ -36619,12 +36619,6 @@ static void test_get_resource_tiling(void) continue; }
- if (tests[i].dim != D3D12_RESOURCE_DIMENSION_BUFFER) - { - skip("Tiled textures not supported.\n"); - continue; - } - memset(&packed_mip_info, 0xaa, sizeof(packed_mip_info)); memset(&tile_shape, 0xaa, sizeof(tile_shape)); memset(&tilings, 0xaa, sizeof(tilings));