diff --git a/tests/d3d12_sparse.c b/tests/d3d12_sparse.c index 174e42b406..c3cdd8dbbe 100644 --- a/tests/d3d12_sparse.c +++ b/tests/d3d12_sparse.c @@ -22,6 +22,8 @@ #define VKD3D_DBG_CHANNEL VKD3D_DBG_CHANNEL_API #include "d3d12_crosstest.h" +#define TILE_SIZE 65536 + static uint32_t compute_tile_count(uint32_t resource_size, uint32_t mip, uint32_t tile_size) { uint32_t mip_size = max(resource_size >> mip, 1u); @@ -323,6 +325,188 @@ static void set_region_size(D3D12_TILE_REGION_SIZE *region, uint32_t num_tiles, region->Depth = d; } +void test_update_tile_mappings_remap_stress(void) +{ + D3D12_FEATURE_DATA_D3D12_OPTIONS options; + D3D12_ROOT_SIGNATURE_DESC rs_desc; + D3D12_ROOT_PARAMETER rs_params[2]; + D3D12_RESOURCE_DESC resource_desc; + D3D12_HEAP_PROPERTIES heap_props; + ID3D12Resource *output_resource; + struct test_context_desc desc; + struct test_context context; + struct resource_readback rb; + D3D12_HEAP_DESC heap_desc; + ID3D12Resource *resource; + unsigned int i, j, iter; + ID3D12Heap *heap = NULL; + HRESULT hr; + +#include "shaders/sparse/headers/update_tile_mappings.h" + + memset(&desc, 0, sizeof(desc)); + desc.no_render_target = true; + desc.no_pipeline = true; + desc.no_root_signature = true; + if (!init_test_context(&context, &desc)) + return; + + hr = ID3D12Device_CheckFeatureSupport(context.device, D3D12_FEATURE_D3D12_OPTIONS, &options, sizeof(options)); + ok(hr == S_OK, "Failed to check feature support, hr %#x.\n", hr); + + if (!options.TiledResourcesTier) + { + skip("Tiled resources not supported by device.\n"); + destroy_test_context(&context); + return; + } + + memset(&heap_props, 0, sizeof(heap_props)); + heap_props.Type = D3D12_HEAP_TYPE_DEFAULT; + + heap_desc.Properties = heap_props; + heap_desc.Alignment = 0; + heap_desc.SizeInBytes = 64 * TILE_SIZE; + heap_desc.Flags = D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS; + + resource_desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; + resource_desc.Alignment = 0; + resource_desc.Width = 64 * TILE_SIZE; + resource_desc.Height = 1; + resource_desc.DepthOrArraySize = 1; + resource_desc.MipLevels = 1; + resource_desc.Format = DXGI_FORMAT_UNKNOWN; + resource_desc.SampleDesc.Count = 1; + resource_desc.SampleDesc.Quality = 0; + resource_desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; + resource_desc.Flags = 0; + + hr = ID3D12Device_CreateReservedResource(context.device, &resource_desc, + D3D12_RESOURCE_STATE_UNORDERED_ACCESS, NULL, &IID_ID3D12Resource, (void **)&resource); + ok(hr == S_OK, "Failed to create reserved buffer, hr %#x.\n", hr); + + output_resource = create_default_buffer(context.device, 64 * sizeof(uint32_t), + D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_UNORDERED_ACCESS); + + memset(rs_params, 0, sizeof(rs_params)); + memset(&rs_desc, 0, sizeof(rs_desc)); + rs_desc.NumParameters = ARRAY_SIZE(rs_params); + rs_desc.pParameters = rs_params; + rs_params[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_SRV; + rs_params[1].ParameterType = D3D12_ROOT_PARAMETER_TYPE_UAV; + create_root_signature(context.device, &rs_desc, &context.root_signature); + + context.pipeline_state = create_compute_pipeline_state( + context.device, context.root_signature, update_tile_mappings_dxbc); + + for (iter = 0; iter < 100; iter++) + { + D3D12_TILE_REGION_SIZE resource_tile_region_size; + D3D12_TILED_RESOURCE_COORDINATE resource_coord; + D3D12_TILE_RANGE_FLAGS heap_range_flags; + ID3D12Resource *placed_resource; + ID3D12Resource *upload; + UINT heap_tile_offset; + uint32_t *upload_data; + UINT heap_tile_count; + ID3D12Heap *new_heap; + + const struct mappings + { + UINT resource_tile; + UINT heap_tile; + UINT count; + D3D12_TILE_RANGE_FLAGS flags; + } mappings[] = { + { 0, 0, 64, D3D12_TILE_RANGE_FLAG_NULL }, + { 4 + (iter & 31), 8 + (iter & 1), 3, D3D12_TILE_RANGE_FLAG_NONE }, + { 1 + (iter & 14), 2 + (iter & 4), 40, D3D12_TILE_RANGE_FLAG_NONE }, + { 13 + (iter & 9), 0, 9, D3D12_TILE_RANGE_FLAG_NULL }, + { 13 + (iter & 7), 19 + (iter & 4), 8, D3D12_TILE_RANGE_FLAG_REUSE_SINGLE_TILE }, + { 30 + (iter & 5), 0, 7, D3D12_TILE_RANGE_FLAG_NULL }, + { 1 + (iter & 3), 0, 7, D3D12_TILE_RANGE_FLAG_NULL }, + }; + + hr = ID3D12Device_CreateHeap(context.device, &heap_desc, &IID_ID3D12Heap, (void **)&new_heap); + ok(hr == S_OK, "Failed to create heap, hr %#x.\n", hr); + + hr = ID3D12Device_CreatePlacedResource(context.device, new_heap, 0, &resource_desc, + D3D12_RESOURCE_STATE_COMMON, NULL, &IID_ID3D12Resource, (void **)&placed_resource); + ok(SUCCEEDED(hr), "Failed to create resource, hr #%x.\n", hr); + + /* Destroy the old heap while it has mappings to the heap, then rebind those pages. Should not explode. */ + if (heap) + ID3D12Heap_Release(heap); + heap = new_heap; + + upload_data = malloc(resource_desc.Width); + for (i = 0; i < resource_desc.Width / 4; i++) + upload_data[i] = i + 1; + upload = create_upload_buffer(context.device, resource_desc.Width, upload_data); + ID3D12GraphicsCommandList_CopyResource(context.list, placed_resource, upload); + ID3D12GraphicsCommandList_Close(context.list); + exec_command_list(context.queue, context.list); + ID3D12GraphicsCommandList_Reset(context.list, context.allocator, NULL); + free(upload_data); + + for (i = 0; i < ARRAY_SIZE(mappings); i++) + { + memset(&resource_coord, 0, sizeof(resource_coord)); + memset(&resource_tile_region_size, 0, sizeof(resource_tile_region_size)); + resource_coord.X = mappings[i].resource_tile; + resource_tile_region_size.NumTiles = mappings[i].count; + resource_tile_region_size.UseBox = FALSE; + heap_range_flags = mappings[i].flags; + heap_tile_offset = mappings[i].heap_tile; + heap_tile_count = mappings[i].count; + + ID3D12CommandQueue_UpdateTileMappings(context.queue, resource, + 1, &resource_coord, &resource_tile_region_size, heap, 1, + &heap_range_flags, &heap_tile_offset, &heap_tile_count, D3D12_TILE_MAPPING_FLAG_NONE); + } + +#define OFFSET_INTO_PAGE 50000 + + ID3D12GraphicsCommandList_SetComputeRootSignature(context.list, context.root_signature); + ID3D12GraphicsCommandList_SetPipelineState(context.list, context.pipeline_state); + ID3D12GraphicsCommandList_SetComputeRootShaderResourceView(context.list, 0, + ID3D12Resource_GetGPUVirtualAddress(resource) + OFFSET_INTO_PAGE); + ID3D12GraphicsCommandList_SetComputeRootUnorderedAccessView(context.list, 1, + ID3D12Resource_GetGPUVirtualAddress(output_resource)); + ID3D12GraphicsCommandList_Dispatch(context.list, 1, 1, 1); + transition_resource_state(context.list, output_resource, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, + D3D12_RESOURCE_STATE_COPY_SOURCE); + get_buffer_readback_with_command_list(output_resource, DXGI_FORMAT_R32_UINT, &rb, context.queue, context.list); + reset_command_list(context.list, context.allocator); + for (i = 0; i < 64; i++) + { + uint32_t expected = 0; + for (j = 0; j < ARRAY_SIZE(mappings); j++) + { + if (i >= mappings[j].resource_tile && i < mappings[j].resource_tile + mappings[j].count) + { + if (mappings[j].flags == D3D12_TILE_RANGE_FLAG_NULL) + expected = 0; + else if (mappings[j].flags == D3D12_TILE_RANGE_FLAG_REUSE_SINGLE_TILE) + expected = mappings[j].heap_tile * TILE_SIZE / 4 + OFFSET_INTO_PAGE / 4 + 1; + else + expected = (mappings[j].heap_tile + (i - mappings[j].resource_tile)) * TILE_SIZE / 4 + OFFSET_INTO_PAGE / 4 + 1; + } + } + ok(expected == get_readback_uint(&rb, i, 0, 0), + "Iter %u: value %u: Expected %u, got %u.\n", iter, i, expected, get_readback_uint(&rb, i, 0, 0)); + } + release_resource_readback(&rb); + ID3D12Resource_Release(placed_resource); + ID3D12Resource_Release(upload); + } + + ID3D12Resource_Release(resource); + ID3D12Resource_Release(output_resource); + ID3D12Heap_Release(heap); + destroy_test_context(&context); +} + void test_update_tile_mappings(void) { D3D12_TILED_RESOURCE_COORDINATE region_offsets[8]; @@ -1008,7 +1192,6 @@ void test_update_tile_mappings(void) void test_copy_tiles(void) { -#define TILE_SIZE 65536 ID3D12Resource *tiled_resource, *dst_buffer, *src_buffer; D3D12_TILED_RESOURCE_COORDINATE region_offset; D3D12_FEATURE_DATA_D3D12_OPTIONS options; @@ -1859,7 +2042,6 @@ static void test_texture_feedback_instructions(bool use_dxil) ID3D12Resource_Release(residency_rt); ID3D12RootSignature_Release(root_signature); destroy_test_context(&context); - #undef TILE_SIZE } void test_texture_feedback_instructions_sm51(void) diff --git a/tests/d3d12_tests.h b/tests/d3d12_tests.h index cb55d820b1..b9a529ce08 100644 --- a/tests/d3d12_tests.h +++ b/tests/d3d12_tests.h @@ -252,6 +252,7 @@ decl_test(test_stencil_export_dxil); decl_test(test_raytracing); decl_test(test_get_resource_tiling); decl_test(test_update_tile_mappings); +decl_test(test_update_tile_mappings_remap_stress); decl_test(test_sampler_border_color); decl_test(test_copy_tiles); decl_test(test_buffer_feedback_instructions_sm51);