From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d/device.c | 16 +++++- libs/vkd3d/resource.c | 102 +++++++++++++++++++++++++++++++++++-- libs/vkd3d/vkd3d_private.h | 24 +++++++++ tests/d3d12.c | 38 ++++++++------ 4 files changed, 159 insertions(+), 21 deletions(-)
diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c index 007a6f651..69dbb8705 100644 --- a/libs/vkd3d/device.c +++ b/libs/vkd3d/device.c @@ -3890,12 +3890,24 @@ static void STDMETHODCALLTYPE d3d12_device_GetResourceTiling(ID3D12Device *iface UINT *sub_resource_tiling_count, UINT first_sub_resource_tiling, D3D12_SUBRESOURCE_TILING *sub_resource_tilings) { - FIXME("iface %p, resource %p, total_tile_count %p, packed_mip_info %p, " + const struct d3d12_resource *resource_impl = impl_from_ID3D12Resource(resource); + struct d3d12_device *device = impl_from_ID3D12Device(iface); + + TRACE("iface %p, resource %p, total_tile_count %p, packed_mip_info %p, " "standard_title_shape %p, sub_resource_tiling_count %p, " - "first_sub_resource_tiling %u, sub_resource_tilings %p stub!\n", + "first_sub_resource_tiling %u, sub_resource_tilings %p.\n", iface, resource, total_tile_count, packed_mip_info, standard_tile_shape, 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); }
static LUID * STDMETHODCALLTYPE d3d12_device_GetAdapterLuid(ID3D12Device *iface, LUID *luid) diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c index 3ca2ff98f..c50d6241f 100644 --- a/libs/vkd3d/resource.c +++ b/libs/vkd3d/resource.c @@ -972,6 +972,11 @@ HRESULT vkd3d_get_image_allocation_info(struct d3d12_device *device, return hr; }
+static void d3d12_resource_tile_info_cleanup(struct d3d12_resource *resource) +{ + vkd3d_free(resource->tiles.subresources); +} + static void d3d12_resource_destroy(struct d3d12_resource *resource, struct d3d12_device *device) { const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; @@ -987,6 +992,8 @@ static void d3d12_resource_destroy(struct d3d12_resource *resource, struct d3d12 else VK_CALL(vkDestroyImage(device->vk_device, resource->u.vk_image, NULL));
+ d3d12_resource_tile_info_cleanup(resource); + if (resource->heap) d3d12_heap_resource_destroyed(resource->heap); } @@ -1058,9 +1065,94 @@ static void d3d12_resource_get_level_box(const struct d3d12_resource *resource, box->back = d3d12_resource_desc_get_depth(&resource->desc, level); }
-static void d3d12_resource_init_tiles(struct d3d12_resource *resource) +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) { - resource->tiles.subresource_count = d3d12_resource_desc_get_sub_resource_count(&resource->desc); + unsigned int i, subresource, subresource_count, count; + const struct vkd3d_subresource_tile_info *tile_info; + const VkExtent3D *tile_extent; + + 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; + } + + if (standard_tile_shape) + { + /* D3D12 docs say tile shape is cleared to zero if there is no standard mip, but drivers don't seem to do this. */ + standard_tile_shape->WidthInTexels = tile_extent->width; + standard_tile_shape->HeightInTexels = tile_extent->height; + standard_tile_shape->DepthInTexels = tile_extent->depth; + } + + if (total_tile_count) + *total_tile_count = resource->tiles.total_count; + + if (!subresource_tiling_count) + return; + + subresource_count = resource->tiles.subresource_count; + + count = subresource_count - min(first_subresource_tiling, subresource_count); + count = min(count, *subresource_tiling_count); + + for (i = 0; i < count; ++i) + { + subresource = i + first_subresource_tiling; + tile_info = &resource->tiles.subresources[subresource]; + subresource_tilings[i].StartTileIndexInOverallResource = tile_info->offset; + subresource_tilings[i].WidthInTiles = tile_info->extent.width; + subresource_tilings[i].HeightInTiles = tile_info->extent.height; + subresource_tilings[i].DepthInTiles = tile_info->extent.depth; + } + *subresource_tiling_count = i; +} + +static bool d3d12_resource_init_tiles(struct d3d12_resource *resource, struct d3d12_device *device) +{ + struct vkd3d_subresource_tile_info *tile_info; + unsigned int subresource_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"); + return false; + } + + if (d3d12_resource_is_buffer(resource)) + { + tile_info = &resource->tiles.subresources[0]; + tile_info->offset = 0; + tile_info->extent.width = align(resource->desc.Width, D3D12_TILE_SIZE) / D3D12_TILE_SIZE; + tile_info->extent.height = 1; + tile_info->extent.depth = 1; + tile_info->count = tile_info->extent.width; + + resource->tiles.tile_extent.width = D3D12_TILE_SIZE; + resource->tiles.tile_extent.height = 1; + resource->tiles.tile_extent.depth = 1; + resource->tiles.total_count = tile_info->extent.width; + resource->tiles.subresource_count = 1; + resource->tiles.standard_mip_count = 1; + } + else + { + vkd3d_unreachable(); + } + + return true; }
/* ID3D12Resource */ @@ -2008,7 +2100,11 @@ HRESULT d3d12_reserved_resource_create(struct d3d12_device *device, desc, initial_state, optimized_clear_value, &object))) return hr;
- d3d12_resource_init_tiles(object); + if (!d3d12_resource_init_tiles(object, device)) + { + d3d12_resource_Release(&object->ID3D12Resource_iface); + return E_OUTOFMEMORY; + }
TRACE("Created reserved resource %p.\n", object);
diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h index 48d66ad4a..b545945a5 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -672,11 +672,31 @@ struct d3d12_heap *unsafe_impl_from_ID3D12Heap(ID3D12Heap *iface); #define VKD3D_RESOURCE_DEDICATED_HEAP 0x00000008 #define VKD3D_RESOURCE_LINEAR_TILING 0x00000010
+struct vkd3d_tiled_region_extent +{ + unsigned int width; + unsigned int height; + unsigned int depth; +}; + +struct vkd3d_subresource_tile_info +{ + unsigned int offset; + unsigned int count; + struct vkd3d_tiled_region_extent extent; +}; + struct d3d12_resource_tile_info { + VkExtent3D tile_extent; + unsigned int total_count; + unsigned int standard_mip_count; unsigned int subresource_count; + struct vkd3d_subresource_tile_info *subresources; };
+#define D3D12_TILE_SIZE 0x10000u + /* ID3D12Resource */ struct d3d12_resource { @@ -727,6 +747,10 @@ static inline bool d3d12_resource_is_texture(const struct d3d12_resource *resour
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); +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 *sub_resource_tiling_count, UINT first_sub_resource_tiling, + D3D12_SUBRESOURCE_TILING *sub_resource_tilings);
HRESULT d3d12_committed_resource_create(struct d3d12_device *device, const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags, diff --git a/tests/d3d12.c b/tests/d3d12.c index 9f00d74fb..2801ec45a 100644 --- a/tests/d3d12.c +++ b/tests/d3d12.c @@ -36619,6 +36619,12 @@ 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)); @@ -36651,23 +36657,23 @@ static void test_get_resource_tiling(void)
ID3D12Device_GetResourceTiling(context.device, resource, &num_resource_tiles, &packed_mip_info, &tile_shape, &num_tilings, 0, tilings);
- todo ok(num_resource_tiles != 0xdeadbeef && num_resource_tiles >= tests[i].expected_tile_count, + ok(num_resource_tiles != 0xdeadbeef && num_resource_tiles >= tests[i].expected_tile_count, "Unexpected resource tile count %u.\n", num_resource_tiles); - todo ok(num_tilings == tests[i].expected_tiling_count, "Unexpected subresource tiling count %u.\n", num_tilings); + ok(num_tilings == tests[i].expected_tiling_count, "Unexpected subresource tiling count %u.\n", num_tilings);
- todo ok(packed_mip_info.NumStandardMips != 0xaa && packed_mip_info.NumStandardMips >= tests[i].expected_standard_mips, + ok(packed_mip_info.NumStandardMips != 0xaa && packed_mip_info.NumStandardMips >= tests[i].expected_standard_mips, "Unexpected standard mip count %u.\n", packed_mip_info.NumStandardMips); - todo ok(packed_mip_info.NumPackedMips == (tests[i].dim == D3D12_RESOURCE_DIMENSION_BUFFER + ok(packed_mip_info.NumPackedMips == (tests[i].dim == D3D12_RESOURCE_DIMENSION_BUFFER ? 0 : tests[i].mip_levels - packed_mip_info.NumStandardMips), "Unexpected packed mip count %u.\n", packed_mip_info.NumPackedMips); - todo ok(packed_mip_info.NumPackedMips != 0xaa + ok(packed_mip_info.NumPackedMips != 0xaa && (packed_mip_info.NumTilesForPackedMips == 0) == (packed_mip_info.NumPackedMips == 0), "Unexpected packed tile count %u.\n", packed_mip_info.NumTilesForPackedMips);
/* Docs say that tile shape should be cleared to zero if there is no standard mip, but drivers don't seem to care about this. */ - todo ok(tile_shape.WidthInTexels == tests[i].tile_shape_w, "Unexpected tile width %u.\n", tile_shape.WidthInTexels); - todo ok(tile_shape.HeightInTexels == tests[i].tile_shape_h, "Unexpected tile height %u.\n", tile_shape.HeightInTexels); - todo ok(tile_shape.DepthInTexels == tests[i].tile_shape_d, "Unexpected tile depth %u.\n", tile_shape.DepthInTexels); + ok(tile_shape.WidthInTexels == tests[i].tile_shape_w, "Unexpected tile width %u.\n", tile_shape.WidthInTexels); + ok(tile_shape.HeightInTexels == tests[i].tile_shape_h, "Unexpected tile height %u.\n", tile_shape.HeightInTexels); + ok(tile_shape.DepthInTexels == tests[i].tile_shape_d, "Unexpected tile depth %u.\n", tile_shape.DepthInTexels);
for (j = 0; j < tests[i].expected_tiling_count; j++) { @@ -36682,28 +36688,28 @@ static void test_get_resource_tiling(void) if (tests[i].dim == D3D12_RESOURCE_DIMENSION_TEXTURE3D) expected_d = compute_tile_count(tests[i].depth_or_array_layers, mip, tests[i].tile_shape_d);
- todo ok(tilings[j].WidthInTiles == expected_w, "Unexpected width %u for subresource %u.\n", tilings[j].WidthInTiles, j); - todo ok(tilings[j].HeightInTiles == expected_h, "Unexpected width %u for subresource %u.\n", tilings[j].HeightInTiles, j); - todo ok(tilings[j].DepthInTiles == expected_d, "Unexpected width %u for subresource %u.\n", tilings[j].DepthInTiles, j); + ok(tilings[j].WidthInTiles == expected_w, "Unexpected width %u for subresource %u.\n", tilings[j].WidthInTiles, j); + ok(tilings[j].HeightInTiles == expected_h, "Unexpected width %u for subresource %u.\n", tilings[j].HeightInTiles, j); + ok(tilings[j].DepthInTiles == expected_d, "Unexpected width %u for subresource %u.\n", tilings[j].DepthInTiles, j);
- todo ok(tilings[j].StartTileIndexInOverallResource == tile_index, "Unexpected start tile index %u for subresource %u.\n", + ok(tilings[j].StartTileIndexInOverallResource == tile_index, "Unexpected start tile index %u for subresource %u.\n", tilings[j].StartTileIndexInOverallResource, j);
tile_index += tilings[j].WidthInTiles * tilings[j].HeightInTiles * tilings[j].DepthInTiles; } else { - todo ok(!tilings[j].WidthInTiles && !tilings[j].HeightInTiles && !tilings[j].DepthInTiles, + ok(!tilings[j].WidthInTiles && !tilings[j].HeightInTiles && !tilings[j].DepthInTiles, "Unexpected tile count (%u,%u,%u) for packed subresource %u.\n", tilings[j].WidthInTiles, tilings[j].HeightInTiles, tilings[j].DepthInTiles, j); - todo ok(tilings[j].StartTileIndexInOverallResource == 0xffffffff, "Unexpected start tile index %u for packed subresource %u.\n", + ok(tilings[j].StartTileIndexInOverallResource == 0xffffffff, "Unexpected start tile index %u for packed subresource %u.\n", tilings[j].StartTileIndexInOverallResource, j); } }
- todo ok(num_resource_tiles == tile_index + packed_mip_info.NumTilesForPackedMips, + ok(num_resource_tiles == tile_index + packed_mip_info.NumTilesForPackedMips, "Unexpected resource tile count %u.\n", num_resource_tiles); - todo ok(packed_mip_info.StartTileIndexInOverallResource == (packed_mip_info.NumPackedMips ? tile_index : 0), + ok(packed_mip_info.StartTileIndexInOverallResource == (packed_mip_info.NumPackedMips ? tile_index : 0), "Unexpected mip tail start tile index %u.\n", packed_mip_info.StartTileIndexInOverallResource);
ID3D12Resource_Release(resource);