1324 lines
56 KiB
C
1324 lines
56 KiB
C
/*
|
|
* Copyright 2016-2017 Józef Kucia for CodeWeavers
|
|
* Copyright 2020-2021 Philip Rebohle for Valve Corporation
|
|
* Copyright 2020-2021 Joshua Ashton for Valve Corporation
|
|
* Copyright 2020-2021 Hans-Kristian Arntzen for Valve Corporation
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
*/
|
|
|
|
#define VKD3D_DBG_CHANNEL VKD3D_DBG_CHANNEL_API
|
|
#include "d3d12_crosstest.h"
|
|
|
|
void test_copy_texture(void)
|
|
{
|
|
D3D12_TEXTURE_COPY_LOCATION src_location, dst_location;
|
|
ID3D12Resource *src_texture, *dst_texture;
|
|
ID3D12PipelineState *pipeline_state_float;
|
|
ID3D12PipelineState *pipeline_state_uint;
|
|
ID3D12GraphicsCommandList *command_list;
|
|
D3D12_SUBRESOURCE_DATA texture_data;
|
|
D3D12_SHADER_RESOURCE_VIEW_DESC srv;
|
|
struct depth_stencil_resource ds;
|
|
struct test_context_desc desc;
|
|
struct test_context context;
|
|
struct resource_readback rb;
|
|
ID3D12DescriptorHeap *heap;
|
|
ID3D12CommandQueue *queue;
|
|
ID3D12Device *device;
|
|
unsigned int x, y, i;
|
|
D3D12_BOX box;
|
|
|
|
static const unsigned int clear_data[] =
|
|
{
|
|
0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
|
0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
|
0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
|
0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
|
};
|
|
static const unsigned int bitmap_data[] =
|
|
{
|
|
0xff00ff00, 0xff00ff01, 0xff00ff02, 0xff00ff03,
|
|
0xff00ff10, 0xff00ff11, 0xff00ff12, 0xff00ff13,
|
|
0xff00ff20, 0xff00ff21, 0xff00ff22, 0xff00ff23,
|
|
0xff00ff30, 0xff00ff31, 0xff00ff32, 0xff00ff33,
|
|
};
|
|
static const unsigned int result_data[] =
|
|
{
|
|
0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
|
0x00000000, 0xff00ff00, 0xff00ff01, 0x00000000,
|
|
0x00000000, 0xff00ff10, 0xff00ff11, 0x00000000,
|
|
0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
|
};
|
|
static const float white[] = {1.0f, 1.0f, 1.0f, 1.0f};
|
|
static const DWORD ps_code[] =
|
|
{
|
|
#if 0
|
|
Texture2D<float> t;
|
|
|
|
float main(float4 position : SV_Position) : SV_Target
|
|
{
|
|
return t[int2(position.x, position.y)];
|
|
}
|
|
#endif
|
|
0x43425844, 0x0beace24, 0x5e10b05b, 0x742de364, 0xb2b65d2b, 0x00000001, 0x00000140, 0x00000003,
|
|
0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
|
|
0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x7469736f, 0x006e6f69,
|
|
0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
|
|
0x00000000, 0x00000e01, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x000000a4, 0x00000040,
|
|
0x00000029, 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000,
|
|
0x00000001, 0x03000065, 0x00102012, 0x00000000, 0x02000068, 0x00000001, 0x0500001b, 0x00100032,
|
|
0x00000000, 0x00101046, 0x00000000, 0x08000036, 0x001000c2, 0x00000000, 0x00004002, 0x00000000,
|
|
0x00000000, 0x00000000, 0x00000000, 0x0700002d, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000,
|
|
0x00107e46, 0x00000000, 0x05000036, 0x00102012, 0x00000000, 0x0010000a, 0x00000000, 0x0100003e,
|
|
};
|
|
static const D3D12_SHADER_BYTECODE ps = {ps_code, sizeof(ps_code)};
|
|
|
|
static const DWORD ps_code_uint[] =
|
|
{
|
|
#if 0
|
|
Texture2D<uint> t;
|
|
|
|
float main(float4 position : SV_Position) : SV_Target
|
|
{
|
|
return float(t[int2(position.x, position.y)]);
|
|
}
|
|
#endif
|
|
0x43425844, 0x9a3fe38f, 0x3c222734, 0x1abb807b, 0xeb4ccda3, 0x00000001, 0x0000014c, 0x00000003,
|
|
0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
|
|
0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x7469736f, 0x006e6f69,
|
|
0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
|
|
0x00000000, 0x00000e01, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x000000b0, 0x00000050,
|
|
0x0000002c, 0x0100086a, 0x04001858, 0x00107000, 0x00000000, 0x00004444, 0x04002064, 0x00101032,
|
|
0x00000000, 0x00000001, 0x03000065, 0x00102012, 0x00000000, 0x02000068, 0x00000001, 0x0500001b,
|
|
0x00100032, 0x00000000, 0x00101046, 0x00000000, 0x08000036, 0x001000c2, 0x00000000, 0x00004002,
|
|
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8900002d, 0x800000c2, 0x00111103, 0x00100012,
|
|
0x00000000, 0x00100e46, 0x00000000, 0x00107e46, 0x00000000, 0x05000056, 0x00102012, 0x00000000,
|
|
0x0010000a, 0x00000000, 0x0100003e,
|
|
};
|
|
static const D3D12_SHADER_BYTECODE ps_uint = {ps_code_uint, sizeof(ps_code_uint)};
|
|
|
|
struct depth_copy_test
|
|
{
|
|
float depth_value;
|
|
UINT stencil_value;
|
|
DXGI_FORMAT ds_format;
|
|
DXGI_FORMAT ds_view_format;
|
|
DXGI_FORMAT readback_format;
|
|
bool stencil;
|
|
bool roundtrip;
|
|
bool requires_stencil_export;
|
|
};
|
|
static const struct depth_copy_test depth_copy_tests[] = {
|
|
{ 0.0f, 0, DXGI_FORMAT_D32_FLOAT, DXGI_FORMAT_D32_FLOAT, DXGI_FORMAT_R32_FLOAT, false, false },
|
|
{ 0.0f, 0, DXGI_FORMAT_D32_FLOAT, DXGI_FORMAT_D32_FLOAT, DXGI_FORMAT_R32_FLOAT, false, true },
|
|
{ 0.5f, 10, DXGI_FORMAT_D32_FLOAT_S8X24_UINT, DXGI_FORMAT_D32_FLOAT_S8X24_UINT, DXGI_FORMAT_R32_FLOAT, false, false },
|
|
{ 0.5f, 10, DXGI_FORMAT_D32_FLOAT_S8X24_UINT, DXGI_FORMAT_D32_FLOAT_S8X24_UINT, DXGI_FORMAT_R32_FLOAT, false, true },
|
|
{ 0.2f, 11, DXGI_FORMAT_D32_FLOAT_S8X24_UINT, DXGI_FORMAT_D32_FLOAT_S8X24_UINT, DXGI_FORMAT_R8_UINT, true, false },
|
|
{ 0.7f, 0, DXGI_FORMAT_R32_TYPELESS, DXGI_FORMAT_D32_FLOAT, DXGI_FORMAT_R32_FLOAT, false, false },
|
|
{ 0.7f, 0, DXGI_FORMAT_R32_TYPELESS, DXGI_FORMAT_D32_FLOAT, DXGI_FORMAT_R32_FLOAT, false, true },
|
|
{ 0.4f, 20, DXGI_FORMAT_R32G8X24_TYPELESS, DXGI_FORMAT_D32_FLOAT_S8X24_UINT, DXGI_FORMAT_R32_FLOAT, false, false },
|
|
{ 0.4f, 20, DXGI_FORMAT_R32G8X24_TYPELESS, DXGI_FORMAT_D32_FLOAT_S8X24_UINT, DXGI_FORMAT_R32_FLOAT, false, true },
|
|
{ 1.0f, 21, DXGI_FORMAT_R32G8X24_TYPELESS, DXGI_FORMAT_D32_FLOAT_S8X24_UINT, DXGI_FORMAT_R8_UINT, true, false },
|
|
|
|
/* Single aspect copies between depth-stencil images. Should hit plain vkCmdCopyImage paths. */
|
|
{ 0.4f, 40, DXGI_FORMAT_R32G8X24_TYPELESS, DXGI_FORMAT_D32_FLOAT_S8X24_UINT, DXGI_FORMAT_R32G8X24_TYPELESS, false, false },
|
|
{ 0.7f, 41, DXGI_FORMAT_R32G8X24_TYPELESS, DXGI_FORMAT_D32_FLOAT_S8X24_UINT, DXGI_FORMAT_R32G8X24_TYPELESS, true, false },
|
|
{ 0.2f, 42, DXGI_FORMAT_R32G8X24_TYPELESS, DXGI_FORMAT_D32_FLOAT_S8X24_UINT, DXGI_FORMAT_R32G8X24_TYPELESS, false, true },
|
|
{ 0.5f, 43, DXGI_FORMAT_R32G8X24_TYPELESS, DXGI_FORMAT_D32_FLOAT_S8X24_UINT, DXGI_FORMAT_R32G8X24_TYPELESS, true, true },
|
|
|
|
/* Test color <-> stencil copies. */
|
|
{ 1.0f, 44, DXGI_FORMAT_R32G8X24_TYPELESS, DXGI_FORMAT_D32_FLOAT_S8X24_UINT, DXGI_FORMAT_R8_UINT, true, false },
|
|
{ 1.0f, 45, DXGI_FORMAT_R32G8X24_TYPELESS, DXGI_FORMAT_D32_FLOAT_S8X24_UINT, DXGI_FORMAT_R8_UINT, true, true, true },
|
|
};
|
|
|
|
static const D3D12_RESOURCE_STATES resource_states[] =
|
|
{
|
|
D3D12_RESOURCE_STATE_COPY_SOURCE,
|
|
D3D12_RESOURCE_STATE_GENERIC_READ,
|
|
};
|
|
|
|
memset(&desc, 0, sizeof(desc));
|
|
desc.rt_format = DXGI_FORMAT_R32_FLOAT;
|
|
desc.no_root_signature = true;
|
|
if (!init_test_context(&context, &desc))
|
|
return;
|
|
device = context.device;
|
|
command_list = context.list;
|
|
queue = context.queue;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(resource_states); ++i)
|
|
{
|
|
src_texture = create_default_texture(device, 4, 4, DXGI_FORMAT_R8G8B8A8_UNORM,
|
|
0, D3D12_RESOURCE_STATE_COPY_DEST);
|
|
texture_data.pData = bitmap_data;
|
|
texture_data.RowPitch = 4 * sizeof(*bitmap_data);
|
|
texture_data.SlicePitch = texture_data.RowPitch * 4;
|
|
upload_texture_data(src_texture, &texture_data, 1, queue, command_list);
|
|
reset_command_list(command_list, context.allocator);
|
|
|
|
dst_texture = create_default_texture(device, 4, 4, DXGI_FORMAT_R8G8B8A8_UNORM,
|
|
0, D3D12_RESOURCE_STATE_COPY_DEST);
|
|
texture_data.pData = clear_data;
|
|
texture_data.RowPitch = 4 * sizeof(*clear_data);
|
|
texture_data.SlicePitch = texture_data.RowPitch * 4;
|
|
upload_texture_data(dst_texture, &texture_data, 1, queue, command_list);
|
|
reset_command_list(command_list, context.allocator);
|
|
transition_resource_state(command_list, src_texture,
|
|
D3D12_RESOURCE_STATE_COPY_DEST, resource_states[i]);
|
|
|
|
src_location.pResource = src_texture;
|
|
src_location.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
|
|
src_location.SubresourceIndex = 0;
|
|
dst_location.pResource = dst_texture;
|
|
dst_location.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
|
|
dst_location.SubresourceIndex = 0;
|
|
set_box(&box, 0, 0, 0, 2, 2, 1);
|
|
ID3D12GraphicsCommandList_CopyTextureRegion(command_list,
|
|
&dst_location, 1, 1, 0, &src_location, &box);
|
|
|
|
transition_resource_state(command_list, dst_texture,
|
|
D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_COPY_SOURCE);
|
|
get_texture_readback_with_command_list(dst_texture, 0, &rb, queue, command_list);
|
|
for (y = 0; y < 4; ++y)
|
|
{
|
|
for (x = 0; x < 4; ++x)
|
|
{
|
|
unsigned int color = get_readback_uint(&rb, x, y, 0);
|
|
unsigned int expected = result_data[y * 4 + x];
|
|
|
|
ok(color == expected,
|
|
"Got unexpected color 0x%08x at (%u, %u), expected 0x%08x.\n",
|
|
color, x, y, expected);
|
|
}
|
|
}
|
|
release_resource_readback(&rb);
|
|
ID3D12Resource_Release(src_texture);
|
|
ID3D12Resource_Release(dst_texture);
|
|
reset_command_list(command_list, context.allocator);
|
|
}
|
|
|
|
for (i = 0; i < ARRAY_SIZE(resource_states); ++i)
|
|
{
|
|
src_texture = create_default_texture(device, 4, 4, DXGI_FORMAT_R8G8B8A8_UNORM,
|
|
0, D3D12_RESOURCE_STATE_COPY_DEST);
|
|
texture_data.pData = bitmap_data;
|
|
texture_data.RowPitch = 4 * sizeof(*bitmap_data);
|
|
texture_data.SlicePitch = texture_data.RowPitch * 4;
|
|
upload_texture_data(src_texture, &texture_data, 1, queue, command_list);
|
|
reset_command_list(command_list, context.allocator);
|
|
|
|
dst_texture = create_default_texture(device, 4, 4, DXGI_FORMAT_R8G8B8A8_UNORM,
|
|
0, D3D12_RESOURCE_STATE_COPY_DEST);
|
|
texture_data.pData = clear_data;
|
|
texture_data.RowPitch = 4 * sizeof(*clear_data);
|
|
texture_data.SlicePitch = texture_data.RowPitch * 4;
|
|
upload_texture_data(dst_texture, &texture_data, 1, queue, command_list);
|
|
reset_command_list(command_list, context.allocator);
|
|
transition_resource_state(command_list, src_texture,
|
|
D3D12_RESOURCE_STATE_COPY_DEST, resource_states[i]);
|
|
|
|
src_location.pResource = src_texture;
|
|
src_location.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
|
|
src_location.SubresourceIndex = 0;
|
|
dst_location.pResource = dst_texture;
|
|
dst_location.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
|
|
dst_location.SubresourceIndex = 0;
|
|
ID3D12GraphicsCommandList_CopyTextureRegion(command_list,
|
|
&dst_location, 0, 0, 0, &src_location, 0);
|
|
|
|
transition_resource_state(command_list, dst_texture,
|
|
D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_COPY_SOURCE);
|
|
get_texture_readback_with_command_list(dst_texture, 0, &rb, queue, command_list);
|
|
for (y = 0; y < 4; ++y)
|
|
{
|
|
for (x = 0; x < 4; ++x)
|
|
{
|
|
unsigned int color = get_readback_uint(&rb, x, y, 0);
|
|
unsigned int expected = bitmap_data[y * 4 + x];
|
|
|
|
ok(color == expected,
|
|
"Got unexpected color 0x%08x at (%u, %u), expected 0x%08x.\n",
|
|
color, x, y, expected);
|
|
}
|
|
}
|
|
release_resource_readback(&rb);
|
|
ID3D12Resource_Release(src_texture);
|
|
ID3D12Resource_Release(dst_texture);
|
|
reset_command_list(command_list, context.allocator);
|
|
}
|
|
|
|
context.root_signature = create_texture_root_signature(device,
|
|
D3D12_SHADER_VISIBILITY_PIXEL, 0, 0);
|
|
pipeline_state_float = create_pipeline_state(device,
|
|
context.root_signature, context.render_target_desc.Format, NULL, &ps, NULL);
|
|
pipeline_state_uint = create_pipeline_state(device,
|
|
context.root_signature, context.render_target_desc.Format, NULL, &ps_uint, NULL);
|
|
|
|
heap = create_gpu_descriptor_heap(device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, 1);
|
|
|
|
for (i = 0; i < ARRAY_SIZE(depth_copy_tests); ++i)
|
|
{
|
|
init_depth_stencil(&ds, device, context.render_target_desc.Width,
|
|
context.render_target_desc.Height, 1, 1, depth_copy_tests[i].ds_format,
|
|
depth_copy_tests[i].ds_view_format, NULL);
|
|
|
|
if (depth_copy_tests[i].stencil)
|
|
{
|
|
ID3D12GraphicsCommandList_ClearDepthStencilView(command_list, ds.dsv_handle,
|
|
D3D12_CLEAR_FLAG_STENCIL, 0.0f, depth_copy_tests[i].stencil_value, 0, NULL);
|
|
}
|
|
else
|
|
{
|
|
ID3D12GraphicsCommandList_ClearDepthStencilView(command_list, ds.dsv_handle,
|
|
D3D12_CLEAR_FLAG_DEPTH, depth_copy_tests[i].depth_value, 0, 0, NULL);
|
|
}
|
|
transition_sub_resource_state(command_list, ds.texture, depth_copy_tests[i].stencil ? 1 : 0,
|
|
D3D12_RESOURCE_STATE_DEPTH_WRITE, resource_states[i % ARRAY_SIZE(resource_states)]);
|
|
|
|
dst_texture = create_default_texture(device, 32, 32, depth_copy_tests[i].readback_format,
|
|
0, D3D12_RESOURCE_STATE_COPY_DEST);
|
|
|
|
memset(&srv, 0, sizeof(srv));
|
|
srv.Format = depth_copy_tests[i].readback_format;
|
|
srv.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
|
|
srv.Texture2D.MipLevels = 1;
|
|
srv.Texture2D.PlaneSlice = depth_copy_tests[i].stencil &&
|
|
depth_copy_tests[i].readback_format != DXGI_FORMAT_R8_UINT ? 1 : 0;
|
|
if (srv.Format == DXGI_FORMAT_R32G8X24_TYPELESS)
|
|
srv.Format = srv.Texture2D.PlaneSlice ? DXGI_FORMAT_X32_TYPELESS_G8X24_UINT : DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS;
|
|
srv.Shader4ComponentMapping = srv.Texture2D.PlaneSlice ? D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING(1, 1, 1, 1) : D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
|
|
ID3D12Device_CreateShaderResourceView(device, dst_texture, &srv,
|
|
ID3D12DescriptorHeap_GetCPUDescriptorHandleForHeapStart(heap));
|
|
|
|
src_location.pResource = ds.texture;
|
|
src_location.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
|
|
src_location.SubresourceIndex = depth_copy_tests[i].stencil ? 1 : 0;
|
|
dst_location.pResource = dst_texture;
|
|
dst_location.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
|
|
dst_location.SubresourceIndex = srv.Texture2D.PlaneSlice;
|
|
ID3D12GraphicsCommandList_CopyTextureRegion(command_list, &dst_location, 0, 0, 0,
|
|
&src_location, NULL);
|
|
|
|
if (depth_copy_tests[i].roundtrip)
|
|
{
|
|
/* Test color to depth/stencil copy. */
|
|
D3D12_TEXTURE_COPY_LOCATION tmp_src_location = dst_location;
|
|
D3D12_TEXTURE_COPY_LOCATION tmp_dst_location = src_location;
|
|
transition_sub_resource_state(command_list, dst_texture, srv.Texture2D.PlaneSlice,
|
|
D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_COPY_SOURCE);
|
|
transition_sub_resource_state(command_list, ds.texture, depth_copy_tests[i].stencil ? 1 : 0,
|
|
resource_states[i % ARRAY_SIZE(resource_states)], D3D12_RESOURCE_STATE_COPY_DEST);
|
|
ID3D12GraphicsCommandList_CopyTextureRegion(command_list, &tmp_dst_location, 0, 0, 0,
|
|
&tmp_src_location, NULL);
|
|
transition_sub_resource_state(command_list, dst_texture, srv.Texture2D.PlaneSlice,
|
|
D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_COPY_DEST);
|
|
transition_sub_resource_state(command_list, ds.texture, depth_copy_tests[i].stencil ? 1 : 0,
|
|
D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_COPY_SOURCE);
|
|
ID3D12GraphicsCommandList_CopyTextureRegion(command_list, &dst_location, 0, 0, 0,
|
|
&src_location, NULL);
|
|
}
|
|
|
|
transition_sub_resource_state(command_list, dst_texture, srv.Texture2D.PlaneSlice,
|
|
D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
|
|
|
|
ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, white, 0, NULL);
|
|
ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &context.rtv, false, NULL);
|
|
ID3D12GraphicsCommandList_RSSetViewports(command_list, 1, &context.viewport);
|
|
ID3D12GraphicsCommandList_RSSetScissorRects(command_list, 1, &context.scissor_rect);
|
|
|
|
ID3D12GraphicsCommandList_SetDescriptorHeaps(command_list, 1, &heap);
|
|
|
|
ID3D12GraphicsCommandList_SetPipelineState(command_list, depth_copy_tests[i].stencil ? pipeline_state_uint : pipeline_state_float);
|
|
ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, context.root_signature);
|
|
ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(command_list, 0,
|
|
ID3D12DescriptorHeap_GetGPUDescriptorHandleForHeapStart(heap));
|
|
ID3D12GraphicsCommandList_IASetPrimitiveTopology(command_list, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
|
ID3D12GraphicsCommandList_DrawInstanced(command_list, 3, 1, 0, 0);
|
|
|
|
transition_sub_resource_state(command_list, context.render_target, 0,
|
|
D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE);
|
|
|
|
if (depth_copy_tests[i].stencil)
|
|
{
|
|
/* Supported on AMD, but not NV. Need buffer copy roundtrip workaround for that to work. */
|
|
todo_if(depth_copy_tests[i].requires_stencil_export)
|
|
check_sub_resource_float(context.render_target, 0, queue, command_list, (float)depth_copy_tests[i].stencil_value, 0);
|
|
}
|
|
else
|
|
{
|
|
check_sub_resource_float(context.render_target, 0, queue, command_list, depth_copy_tests[i].depth_value, 2);
|
|
}
|
|
|
|
destroy_depth_stencil(&ds);
|
|
ID3D12Resource_Release(dst_texture);
|
|
|
|
reset_command_list(command_list, context.allocator);
|
|
transition_sub_resource_state(command_list, context.render_target, 0,
|
|
D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET);
|
|
}
|
|
|
|
ID3D12PipelineState_Release(pipeline_state_float);
|
|
ID3D12PipelineState_Release(pipeline_state_uint);
|
|
ID3D12DescriptorHeap_Release(heap);
|
|
destroy_test_context(&context);
|
|
}
|
|
|
|
void test_copy_texture_buffer(void)
|
|
{
|
|
D3D12_TEXTURE_COPY_LOCATION src_location, dst_location;
|
|
ID3D12GraphicsCommandList *command_list;
|
|
D3D12_SUBRESOURCE_DATA texture_data;
|
|
ID3D12Resource *dst_buffers[4];
|
|
struct test_context_desc desc;
|
|
struct test_context context;
|
|
struct resource_readback rb;
|
|
ID3D12Resource *src_texture;
|
|
unsigned int got, expected;
|
|
ID3D12CommandQueue *queue;
|
|
ID3D12Device *device;
|
|
unsigned int x, y;
|
|
unsigned int *ptr;
|
|
unsigned int i;
|
|
D3D12_BOX box;
|
|
|
|
memset(&desc, 0, sizeof(desc));
|
|
desc.no_render_target = true;
|
|
if (!init_test_context(&context, &desc))
|
|
return;
|
|
device = context.device;
|
|
command_list = context.list;
|
|
queue = context.queue;
|
|
|
|
ptr = calloc(64 * 32, sizeof(*ptr));
|
|
ok(ptr, "Failed to allocate memory.\n");
|
|
|
|
for (i = 0; i < 64 * 32; ++i)
|
|
ptr[i] = i;
|
|
|
|
src_texture = create_default_texture(device,
|
|
64, 32, DXGI_FORMAT_R32_UINT, 0, D3D12_RESOURCE_STATE_COPY_DEST);
|
|
texture_data.pData = ptr;
|
|
texture_data.RowPitch = 64 * sizeof(*ptr);
|
|
texture_data.SlicePitch = texture_data.RowPitch * 32;
|
|
upload_texture_data(src_texture, &texture_data, 1, queue, command_list);
|
|
reset_command_list(command_list, context.allocator);
|
|
transition_resource_state(command_list, src_texture,
|
|
D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_COPY_SOURCE);
|
|
|
|
free(ptr);
|
|
|
|
for (i = 0; i < ARRAY_SIZE(dst_buffers); ++i)
|
|
{
|
|
dst_buffers[i] = create_default_buffer(device,
|
|
64 * 32 * sizeof(*ptr), 0, D3D12_RESOURCE_STATE_COPY_DEST);
|
|
}
|
|
|
|
dst_location.pResource = dst_buffers[0];
|
|
dst_location.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
|
|
dst_location.PlacedFootprint.Offset = 0;
|
|
dst_location.PlacedFootprint.Footprint.Format = DXGI_FORMAT_R32_UINT;
|
|
dst_location.PlacedFootprint.Footprint.Width = 64;
|
|
dst_location.PlacedFootprint.Footprint.Height = 32;
|
|
dst_location.PlacedFootprint.Footprint.Depth = 1;
|
|
dst_location.PlacedFootprint.Footprint.RowPitch = 64 * sizeof(*ptr);
|
|
|
|
src_location.pResource = src_texture;
|
|
src_location.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
|
|
src_location.SubresourceIndex = 0;
|
|
|
|
ID3D12GraphicsCommandList_CopyTextureRegion(command_list,
|
|
&dst_location, 0, 0, 0, &src_location, NULL);
|
|
|
|
dst_location.pResource = dst_buffers[1];
|
|
for (y = 0; y < 32; ++y)
|
|
{
|
|
set_box(&box, 0, y, 0, 64, y + 1, 1);
|
|
ID3D12GraphicsCommandList_CopyTextureRegion(command_list,
|
|
&dst_location, 0, 31 - y, 0, &src_location, &box);
|
|
}
|
|
|
|
dst_location.pResource = dst_buffers[2];
|
|
for (x = 0; x < 64; ++x)
|
|
{
|
|
set_box(&box, x, 0, 0, x + 1, 32, 1);
|
|
ID3D12GraphicsCommandList_CopyTextureRegion(command_list,
|
|
&dst_location, 63 - x, 0, 0, &src_location, &box);
|
|
}
|
|
|
|
dst_location.pResource = dst_buffers[3];
|
|
set_box(&box, 0, 0, 0, 32, 32, 1);
|
|
ID3D12GraphicsCommandList_CopyTextureRegion(command_list,
|
|
&dst_location, 0, 0, 0, &src_location, &box);
|
|
ID3D12GraphicsCommandList_CopyTextureRegion(command_list,
|
|
&dst_location, 32, 0, 0, &src_location, &box);
|
|
|
|
/* empty box */
|
|
set_box(&box, 128, 0, 0, 32, 32, 1);
|
|
ID3D12GraphicsCommandList_CopyTextureRegion(command_list,
|
|
&dst_location, 0, 0, 0, &src_location, &box);
|
|
|
|
for (i = 0; i < ARRAY_SIZE(dst_buffers); ++i)
|
|
{
|
|
transition_resource_state(command_list, dst_buffers[i],
|
|
D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_COPY_SOURCE);
|
|
}
|
|
|
|
got = expected = 0;
|
|
get_buffer_readback_with_command_list(dst_buffers[0], DXGI_FORMAT_R32_UINT, &rb, queue, command_list);
|
|
for (i = 0; i < 64 * 32; ++i)
|
|
{
|
|
got = get_readback_uint(&rb, i, 0, 0);
|
|
expected = i;
|
|
|
|
if (got != expected)
|
|
break;
|
|
}
|
|
release_resource_readback(&rb);
|
|
ok(got == expected, "Got unexpected value 0x%08x at %u, expected 0x%08x.\n", got, i, expected);
|
|
|
|
reset_command_list(command_list, context.allocator);
|
|
got = expected = 0;
|
|
get_buffer_readback_with_command_list(dst_buffers[1], DXGI_FORMAT_R32_UINT, &rb, queue, command_list);
|
|
for (y = 0; y < 32; ++y)
|
|
{
|
|
for (x = 0; x < 64; ++x)
|
|
{
|
|
got = get_readback_uint(&rb, 64 * y + x, 0, 0);
|
|
expected = 64 * (31 - y) + x;
|
|
|
|
if (got != expected)
|
|
break;
|
|
}
|
|
if (got != expected)
|
|
break;
|
|
}
|
|
release_resource_readback(&rb);
|
|
ok(got == expected, "Got unexpected value 0x%08x at (%u, %u), expected 0x%08x.\n", got, x, y, expected);
|
|
|
|
reset_command_list(command_list, context.allocator);
|
|
got = expected = 0;
|
|
get_buffer_readback_with_command_list(dst_buffers[2], DXGI_FORMAT_R32_UINT, &rb, queue, command_list);
|
|
for (y = 0; y < 32; ++y)
|
|
{
|
|
for (x = 0; x < 64; ++x)
|
|
{
|
|
got = get_readback_uint(&rb, 64 * y + x, 0, 0);
|
|
expected = 64 * y + 63 - x;
|
|
|
|
if (got != expected)
|
|
break;
|
|
}
|
|
if (got != expected)
|
|
break;
|
|
}
|
|
release_resource_readback(&rb);
|
|
ok(got == expected, "Got unexpected value 0x%08x at (%u, %u), expected 0x%08x.\n", got, x, y, expected);
|
|
|
|
reset_command_list(command_list, context.allocator);
|
|
got = expected = 0;
|
|
get_buffer_readback_with_command_list(dst_buffers[3], DXGI_FORMAT_R32_UINT, &rb, queue, command_list);
|
|
for (y = 0; y < 32; ++y)
|
|
{
|
|
for (x = 0; x < 64; ++x)
|
|
{
|
|
got = get_readback_uint(&rb, 64 * y + x, 0, 0);
|
|
expected = 64 * y + x % 32;
|
|
|
|
if (got != expected)
|
|
break;
|
|
}
|
|
if (got != expected)
|
|
break;
|
|
}
|
|
release_resource_readback(&rb);
|
|
ok(got == expected, "Got unexpected value 0x%08x at (%u, %u), expected 0x%08x.\n", got, x, y, expected);
|
|
|
|
ID3D12Resource_Release(src_texture);
|
|
for (i = 0; i < ARRAY_SIZE(dst_buffers); ++i)
|
|
ID3D12Resource_Release(dst_buffers[i]);
|
|
destroy_test_context(&context);
|
|
}
|
|
|
|
void test_copy_buffer_to_depth_stencil(void)
|
|
{
|
|
ID3D12Resource *src_buffer_stencil = NULL;
|
|
ID3D12GraphicsCommandList *command_list;
|
|
struct resource_readback rb_stencil;
|
|
struct resource_readback rb_depth;
|
|
ID3D12Resource *src_buffer_depth;
|
|
struct test_context_desc desc;
|
|
struct test_context context;
|
|
ID3D12Resource *dst_texture;
|
|
ID3D12CommandQueue *queue;
|
|
ID3D12Device *device;
|
|
unsigned int i, x, y;
|
|
|
|
struct test
|
|
{
|
|
DXGI_FORMAT format;
|
|
uint32_t input_depth;
|
|
uint32_t output_depth_24;
|
|
D3D12_RESOURCE_FLAGS flags;
|
|
bool stencil;
|
|
};
|
|
#define UNORM24_1 ((1 << 24) - 1)
|
|
#define FP32_1 0x3f800000
|
|
#define FP32_MASK24 (FP32_1 & UNORM24_1)
|
|
/* The footprint is 32-bit and AMD and NV seem to behave differently.
|
|
* The footprint for 24-bit depth is actually FP32 w/ rounding or something weird like that, not sure what is going on.
|
|
* Either way, there are two correct results we can expect here. */
|
|
static const struct test tests[] =
|
|
{
|
|
{ DXGI_FORMAT_D24_UNORM_S8_UINT, UNORM24_1, UNORM24_1, D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL, true },
|
|
{ DXGI_FORMAT_D24_UNORM_S8_UINT, FP32_1, FP32_MASK24, D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL, true },
|
|
{ DXGI_FORMAT_D24_UNORM_S8_UINT, FP32_1, FP32_MASK24, D3D12_RESOURCE_FLAG_NONE, true },
|
|
{ DXGI_FORMAT_D32_FLOAT, FP32_1, FP32_1, D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL, false },
|
|
{ DXGI_FORMAT_D32_FLOAT_S8X24_UINT, FP32_1, FP32_1, D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL, true },
|
|
{ DXGI_FORMAT_R24_UNORM_X8_TYPELESS, UNORM24_1, UNORM24_1, D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL, false },
|
|
{ DXGI_FORMAT_R24_UNORM_X8_TYPELESS, FP32_1, FP32_MASK24, D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL, false },
|
|
{ DXGI_FORMAT_R24_UNORM_X8_TYPELESS, FP32_1, FP32_MASK24, D3D12_RESOURCE_FLAG_NONE, false },
|
|
{ DXGI_FORMAT_R24G8_TYPELESS, UNORM24_1, UNORM24_1, D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL, true },
|
|
{ DXGI_FORMAT_R24G8_TYPELESS, FP32_1, FP32_MASK24, D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL, true },
|
|
{ DXGI_FORMAT_R24G8_TYPELESS, FP32_1, FP32_MASK24, D3D12_RESOURCE_FLAG_NONE, true },
|
|
{ DXGI_FORMAT_R32_TYPELESS, FP32_1, FP32_1, D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL, false },
|
|
{ DXGI_FORMAT_R32_TYPELESS, FP32_1, FP32_1, D3D12_RESOURCE_FLAG_NONE, false },
|
|
{ DXGI_FORMAT_R32G8X24_TYPELESS, FP32_1, FP32_1, D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL, true },
|
|
};
|
|
|
|
memset(&desc, 0, sizeof(desc));
|
|
desc.no_render_target = true;
|
|
if (!init_test_context(&context, &desc))
|
|
return;
|
|
device = context.device;
|
|
command_list = context.list;
|
|
queue = context.queue;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(tests); i++)
|
|
{
|
|
uint32_t depth_data[(D3D12_TEXTURE_DATA_PITCH_ALIGNMENT / 4) * 4];
|
|
uint8_t stencil_data[D3D12_TEXTURE_DATA_PITCH_ALIGNMENT * 4];
|
|
D3D12_TEXTURE_COPY_LOCATION dst, src;
|
|
D3D12_BOX src_box;
|
|
|
|
vkd3d_test_set_context("Test %u", i);
|
|
dst_texture = create_default_texture2d(device, 2, 2, 1, 1,
|
|
tests[i].format, tests[i].flags, D3D12_RESOURCE_STATE_COPY_DEST);
|
|
|
|
memset(depth_data, 0, sizeof(depth_data));
|
|
depth_data[0] = tests[i].input_depth;
|
|
depth_data[1] = tests[i].input_depth;
|
|
depth_data[D3D12_TEXTURE_DATA_PITCH_ALIGNMENT / 4] = tests[i].input_depth;
|
|
depth_data[D3D12_TEXTURE_DATA_PITCH_ALIGNMENT / 4 + 1] = tests[i].input_depth;
|
|
|
|
src_buffer_depth = create_upload_buffer(device, sizeof(depth_data), depth_data);
|
|
|
|
if (tests[i].stencil)
|
|
{
|
|
memset(stencil_data, 0, sizeof(stencil_data));
|
|
stencil_data[0] = 0xaa;
|
|
stencil_data[1] = 0xab;
|
|
stencil_data[D3D12_TEXTURE_DATA_PITCH_ALIGNMENT + 0] = 0xac;
|
|
stencil_data[D3D12_TEXTURE_DATA_PITCH_ALIGNMENT + 1] = 0xad;
|
|
src_buffer_stencil = create_upload_buffer(device, sizeof(stencil_data), stencil_data);
|
|
}
|
|
|
|
set_box(&src_box, 0, 0, 0, 2, 2, 1);
|
|
dst.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
|
|
src.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
|
|
dst.pResource = dst_texture;
|
|
src.PlacedFootprint.Offset = 0;
|
|
src.PlacedFootprint.Footprint.Width = 2;
|
|
src.PlacedFootprint.Footprint.Height = 2;
|
|
src.PlacedFootprint.Footprint.Depth = 1;
|
|
src.PlacedFootprint.Footprint.RowPitch = D3D12_TEXTURE_DATA_PITCH_ALIGNMENT;
|
|
|
|
src.PlacedFootprint.Footprint.Format = DXGI_FORMAT_R32_TYPELESS;
|
|
dst.SubresourceIndex = 0;
|
|
src.pResource = src_buffer_depth;
|
|
ID3D12GraphicsCommandList_CopyTextureRegion(command_list, &dst, 0, 0, 0, &src, &src_box);
|
|
|
|
if (tests[i].stencil)
|
|
{
|
|
src.PlacedFootprint.Footprint.Format = DXGI_FORMAT_R8_TYPELESS;
|
|
dst.SubresourceIndex = 1;
|
|
src.pResource = src_buffer_stencil;
|
|
ID3D12GraphicsCommandList_CopyTextureRegion(command_list, &dst, 0, 0, 0, &src, &src_box);
|
|
}
|
|
|
|
transition_resource_state(command_list, dst_texture, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_COPY_SOURCE);
|
|
|
|
get_texture_readback_with_command_list(dst_texture, 0, &rb_depth, queue, command_list);
|
|
reset_command_list(command_list, context.allocator);
|
|
if (tests[i].stencil)
|
|
{
|
|
get_texture_readback_with_command_list(dst_texture, 1, &rb_stencil, queue, command_list);
|
|
reset_command_list(command_list, context.allocator);
|
|
}
|
|
|
|
for (y = 0; y < 2; y++)
|
|
{
|
|
for (x = 0; x < 2; x++)
|
|
{
|
|
uint32_t v = get_readback_uint(&rb_depth, x, y, 0);
|
|
ok((v & 0xffffffu) == tests[i].output_depth_24 || v == tests[i].input_depth, "Depth is 0x%x\n", v);
|
|
}
|
|
}
|
|
|
|
if (tests[i].stencil)
|
|
{
|
|
for (y = 0; y < 2; y++)
|
|
{
|
|
for (x = 0; x < 2; x++)
|
|
{
|
|
uint8_t v = get_readback_uint8(&rb_stencil, x, y);
|
|
ok(v == 0xaa + y * 2 + x, "Stencil is 0x%x\n", v);
|
|
}
|
|
}
|
|
}
|
|
|
|
release_resource_readback(&rb_depth);
|
|
ID3D12Resource_Release(src_buffer_depth);
|
|
ID3D12Resource_Release(dst_texture);
|
|
if (tests[i].stencil)
|
|
{
|
|
ID3D12Resource_Release(src_buffer_stencil);
|
|
release_resource_readback(&rb_stencil);
|
|
}
|
|
}
|
|
vkd3d_test_set_context(NULL);
|
|
|
|
destroy_test_context(&context);
|
|
}
|
|
|
|
void test_copy_buffer_texture(void)
|
|
{
|
|
D3D12_TEXTURE_COPY_LOCATION src_location, dst_location;
|
|
ID3D12GraphicsCommandList *command_list;
|
|
struct test_context_desc desc;
|
|
struct test_context context;
|
|
struct resource_readback rb;
|
|
ID3D12Resource *zero_buffer;
|
|
ID3D12Resource *dst_texture;
|
|
ID3D12Resource *src_buffer;
|
|
unsigned int got, expected;
|
|
ID3D12CommandQueue *queue;
|
|
unsigned int buffer_size;
|
|
ID3D12Device *device;
|
|
unsigned int x, y, z;
|
|
unsigned int *ptr;
|
|
unsigned int i;
|
|
D3D12_BOX box;
|
|
HRESULT hr;
|
|
|
|
memset(&desc, 0, sizeof(desc));
|
|
desc.no_render_target = true;
|
|
if (!init_test_context(&context, &desc))
|
|
return;
|
|
device = context.device;
|
|
command_list = context.list;
|
|
queue = context.queue;
|
|
|
|
buffer_size = 128 * 100 * 64;
|
|
|
|
zero_buffer = create_upload_buffer(device, buffer_size * sizeof(*ptr) + D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT, NULL);
|
|
hr = ID3D12Resource_Map(zero_buffer, 0, NULL, (void **)&ptr);
|
|
ok(hr == S_OK, "Failed to map buffer, hr %#x.\n", hr);
|
|
memset(ptr, 0, buffer_size * sizeof(*ptr) + D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT);
|
|
for (i = 0; i < D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT / sizeof(*ptr); ++i)
|
|
ptr[i] = 0xdeadbeef;
|
|
ID3D12Resource_Unmap(zero_buffer, 0, NULL);
|
|
|
|
src_buffer = create_upload_buffer(device, buffer_size * sizeof(*ptr), NULL);
|
|
hr = ID3D12Resource_Map(src_buffer, 0, NULL, (void **)&ptr);
|
|
ok(hr == S_OK, "Failed to map buffer, hr %#x.\n", hr);
|
|
for (z = 0; z < 64; ++z)
|
|
{
|
|
for (y = 0; y < 100; ++y)
|
|
{
|
|
for (x = 0; x < 128; ++x)
|
|
{
|
|
ptr[z * 128 * 100 + y * 128 + x] = (z + 1) << 16 | (y + 1) << 8 | (x + 1);
|
|
}
|
|
}
|
|
}
|
|
ID3D12Resource_Unmap(src_buffer, 0, NULL);
|
|
|
|
dst_texture = create_default_texture3d(device, 128, 100, 64, 2,
|
|
DXGI_FORMAT_R32_UINT, 0, D3D12_RESOURCE_STATE_COPY_DEST);
|
|
|
|
dst_location.pResource = dst_texture;
|
|
dst_location.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
|
|
dst_location.SubresourceIndex = 0;
|
|
|
|
src_location.pResource = zero_buffer;
|
|
src_location.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
|
|
src_location.PlacedFootprint.Offset = D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT;
|
|
src_location.PlacedFootprint.Footprint.Format = DXGI_FORMAT_R32_UINT;
|
|
src_location.PlacedFootprint.Footprint.Width = 128;
|
|
src_location.PlacedFootprint.Footprint.Height = 100;
|
|
src_location.PlacedFootprint.Footprint.Depth = 64;
|
|
src_location.PlacedFootprint.Footprint.RowPitch = 128 * sizeof(*ptr);
|
|
|
|
/* fill with 0 */
|
|
ID3D12GraphicsCommandList_CopyTextureRegion(command_list,
|
|
&dst_location, 0, 0, 0, &src_location, NULL);
|
|
|
|
src_location.pResource = src_buffer;
|
|
src_location.PlacedFootprint.Offset = 0;
|
|
|
|
/* copy region 1 */
|
|
set_box(&box, 64, 16, 8, 128, 100, 64);
|
|
ID3D12GraphicsCommandList_CopyTextureRegion(command_list,
|
|
&dst_location, 64, 16, 8, &src_location, &box);
|
|
|
|
/* empty boxes */
|
|
for (z = 0; z < 2; ++z)
|
|
{
|
|
for (y = 0; y < 4; ++y)
|
|
{
|
|
for (x = 0; x < 8; ++x)
|
|
{
|
|
set_box(&box, x, y, z, x, y, z);
|
|
ID3D12GraphicsCommandList_CopyTextureRegion(command_list,
|
|
&dst_location, 0, 0, 0, &src_location, &box);
|
|
ID3D12GraphicsCommandList_CopyTextureRegion(command_list,
|
|
&dst_location, x, y, z, &src_location, &box);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* copy region 2 */
|
|
set_box(&box, 0, 0, 0, 4, 4, 4);
|
|
ID3D12GraphicsCommandList_CopyTextureRegion(command_list,
|
|
&dst_location, 2, 2, 2, &src_location, &box);
|
|
|
|
/* fill sub-resource 1 */
|
|
dst_location.SubresourceIndex = 1;
|
|
set_box(&box, 0, 0, 0, 64, 50, 32);
|
|
ID3D12GraphicsCommandList_CopyTextureRegion(command_list,
|
|
&dst_location, 0, 0, 0, &src_location, &box);
|
|
|
|
transition_resource_state(command_list, dst_texture,
|
|
D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_COPY_SOURCE);
|
|
|
|
got = expected = 0;
|
|
get_texture_readback_with_command_list(dst_texture, 0, &rb, queue, command_list);
|
|
for (z = 0; z < 64; ++z)
|
|
{
|
|
for (y = 0; y < 100; ++y)
|
|
{
|
|
for (x = 0; x < 128; ++x)
|
|
{
|
|
got = get_readback_uint(&rb, x, y, z);
|
|
|
|
if (2 <= x && x < 6 && 2 <= y && y < 6 && 2 <= z && z < 6)
|
|
expected = (z - 1) << 16 | (y - 1) << 8 | (x - 1); /* copy region 1 */
|
|
else if (64 <= x && 16 <= y && 8 <= z)
|
|
expected = (z + 1) << 16 | (y + 1) << 8 | (x + 1); /* copy region 2 */
|
|
else
|
|
expected = 0;
|
|
|
|
if (got != expected)
|
|
break;
|
|
}
|
|
if (got != expected)
|
|
break;
|
|
}
|
|
if (got != expected)
|
|
break;
|
|
}
|
|
release_resource_readback(&rb);
|
|
ok(got == expected,
|
|
"Got unexpected value 0x%08x at (%u, %u, %u), expected 0x%08x.\n",
|
|
got, x, y, z, expected);
|
|
|
|
reset_command_list(command_list, context.allocator);
|
|
got = expected = 0;
|
|
get_texture_readback_with_command_list(dst_texture, 1, &rb, queue, command_list);
|
|
for (z = 0; z < 32; ++z)
|
|
{
|
|
for (y = 0; y < 50; ++y)
|
|
{
|
|
for (x = 0; x < 64; ++x)
|
|
{
|
|
got = get_readback_uint(&rb, x, y, z);
|
|
expected = (z + 1) << 16 | (y + 1) << 8 | (x + 1);
|
|
|
|
if (got != expected)
|
|
break;
|
|
}
|
|
if (got != expected)
|
|
break;
|
|
}
|
|
if (got != expected)
|
|
break;
|
|
}
|
|
release_resource_readback(&rb);
|
|
ok(got == expected,
|
|
"Got unexpected value 0x%08x at (%u, %u, %u), expected 0x%08x.\n",
|
|
got, x, y, z, expected);
|
|
|
|
ID3D12Resource_Release(dst_texture);
|
|
ID3D12Resource_Release(src_buffer);
|
|
ID3D12Resource_Release(zero_buffer);
|
|
destroy_test_context(&context);
|
|
}
|
|
|
|
void test_copy_block_compressed_texture(void)
|
|
{
|
|
D3D12_TEXTURE_COPY_LOCATION src_location, dst_location;
|
|
ID3D12Resource *dst_buffer, *src_buffer;
|
|
ID3D12GraphicsCommandList *command_list;
|
|
struct test_context_desc desc;
|
|
unsigned int x, y, block_id;
|
|
struct test_context context;
|
|
struct resource_readback rb;
|
|
struct uvec4 got, expected;
|
|
ID3D12CommandQueue *queue;
|
|
ID3D12Resource *texture;
|
|
ID3D12Device *device;
|
|
unsigned int *ptr;
|
|
D3D12_BOX box;
|
|
HRESULT hr;
|
|
|
|
memset(&desc, 0, sizeof(desc));
|
|
desc.no_render_target = true;
|
|
if (!init_test_context(&context, &desc))
|
|
return;
|
|
device = context.device;
|
|
command_list = context.list;
|
|
queue = context.queue;
|
|
|
|
dst_buffer = create_default_buffer(device, 4096, 0, D3D12_RESOURCE_STATE_COPY_DEST);
|
|
src_buffer = create_upload_buffer(device, 4096, NULL);
|
|
hr = ID3D12Resource_Map(src_buffer, 0, NULL, (void **)&ptr);
|
|
ok(hr == S_OK, "Failed to map buffer, hr %#x.\n", hr);
|
|
for (x = 0; x < 4096 / format_size(DXGI_FORMAT_BC2_UNORM); ++x)
|
|
{
|
|
block_id = x << 8;
|
|
*ptr++ = block_id | 0;
|
|
*ptr++ = block_id | 1;
|
|
*ptr++ = block_id | 2;
|
|
*ptr++ = block_id | 3;
|
|
}
|
|
ID3D12Resource_Unmap(src_buffer, 0, NULL);
|
|
|
|
texture = create_default_texture2d(device, 8, 8, 1, 4, DXGI_FORMAT_BC2_UNORM,
|
|
D3D12_RESOURCE_FLAG_NONE, D3D12_RESOURCE_STATE_COPY_DEST);
|
|
|
|
/* copy from buffer to texture */
|
|
dst_location.pResource = texture;
|
|
dst_location.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
|
|
dst_location.SubresourceIndex = 0;
|
|
|
|
src_location.pResource = src_buffer;
|
|
src_location.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
|
|
src_location.PlacedFootprint.Offset = 0;
|
|
src_location.PlacedFootprint.Footprint.Format = DXGI_FORMAT_BC2_UNORM;
|
|
src_location.PlacedFootprint.Footprint.Width = 32;
|
|
src_location.PlacedFootprint.Footprint.Height = 32;
|
|
src_location.PlacedFootprint.Footprint.Depth = 1;
|
|
src_location.PlacedFootprint.Footprint.RowPitch
|
|
= 32 / format_block_width(DXGI_FORMAT_BC2_UNORM) * format_size(DXGI_FORMAT_BC2_UNORM);
|
|
src_location.PlacedFootprint.Footprint.RowPitch
|
|
= align(src_location.PlacedFootprint.Footprint.RowPitch, D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT);
|
|
|
|
set_box(&box, 4, 4, 0, 8, 8, 1);
|
|
ID3D12GraphicsCommandList_CopyTextureRegion(command_list,
|
|
&dst_location, 0, 0, 0, &src_location, &box);
|
|
set_box(&box, 28, 0, 0, 32, 4, 1);
|
|
ID3D12GraphicsCommandList_CopyTextureRegion(command_list,
|
|
&dst_location, 4, 0, 0, &src_location, &box);
|
|
set_box(&box, 0, 24, 0, 4, 28, 1);
|
|
ID3D12GraphicsCommandList_CopyTextureRegion(command_list,
|
|
&dst_location, 0, 4, 0, &src_location, &box);
|
|
set_box(&box, 16, 16, 0, 20, 20, 1);
|
|
ID3D12GraphicsCommandList_CopyTextureRegion(command_list,
|
|
&dst_location, 4, 4, 0, &src_location, &box);
|
|
|
|
/* miplevels smaller than 4x4 */
|
|
dst_location.SubresourceIndex = 2;
|
|
set_box(&box, 4, 0, 0, 8, 4, 1);
|
|
ID3D12GraphicsCommandList_CopyTextureRegion(command_list,
|
|
&dst_location, 0, 0, 0, &src_location, &box);
|
|
dst_location.SubresourceIndex = 3;
|
|
set_box(&box, 8, 0, 0, 12, 4, 1);
|
|
ID3D12GraphicsCommandList_CopyTextureRegion(command_list,
|
|
&dst_location, 0, 0, 0, &src_location, &box);
|
|
|
|
transition_resource_state(command_list, texture,
|
|
D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_COPY_SOURCE);
|
|
|
|
/* copy from texture to buffer */
|
|
dst_location.pResource = dst_buffer;
|
|
dst_location.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
|
|
dst_location.PlacedFootprint.Offset = 0;
|
|
dst_location.PlacedFootprint.Footprint.Format = DXGI_FORMAT_BC2_UNORM;
|
|
dst_location.PlacedFootprint.Footprint.Width = 8;
|
|
dst_location.PlacedFootprint.Footprint.Height = 24;
|
|
dst_location.PlacedFootprint.Footprint.Depth = 1;
|
|
dst_location.PlacedFootprint.Footprint.RowPitch
|
|
= 8 / format_block_width(DXGI_FORMAT_BC2_UNORM) * format_size(DXGI_FORMAT_BC2_UNORM);
|
|
dst_location.PlacedFootprint.Footprint.RowPitch
|
|
= align(dst_location.PlacedFootprint.Footprint.RowPitch, D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT);
|
|
|
|
src_location.pResource = texture;
|
|
src_location.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
|
|
src_location.SubresourceIndex = 0;
|
|
|
|
ID3D12GraphicsCommandList_CopyTextureRegion(command_list,
|
|
&dst_location, 0, 0, 0, &src_location, NULL);
|
|
ID3D12GraphicsCommandList_CopyTextureRegion(command_list,
|
|
&dst_location, 0, 8, 0, &src_location, NULL);
|
|
set_box(&box, 0, 0, 0, 8, 8, 1);
|
|
ID3D12GraphicsCommandList_CopyTextureRegion(command_list,
|
|
&dst_location, 0, 16, 0, &src_location, &box);
|
|
|
|
transition_resource_state(command_list, dst_buffer,
|
|
D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_COPY_SOURCE);
|
|
|
|
get_texture_readback_with_command_list(texture, 0, &rb, queue, command_list);
|
|
for (y = 0; y < 8 / format_block_height(DXGI_FORMAT_BC2_UNORM); ++y)
|
|
{
|
|
for (x = 0; x < 8 / format_block_width(DXGI_FORMAT_BC2_UNORM); ++x)
|
|
{
|
|
if (x == 0 && y == 0)
|
|
block_id = 33;
|
|
else if (x == 1 && y == 0)
|
|
block_id = 7;
|
|
else if (x == 0 && y == 1)
|
|
block_id = 192;
|
|
else
|
|
block_id = 132;
|
|
|
|
expected.x = block_id << 8 | 0;
|
|
expected.y = block_id << 8 | 1;
|
|
expected.z = block_id << 8 | 2;
|
|
expected.w = block_id << 8 | 3;
|
|
got = *get_readback_uvec4(&rb, x, y);
|
|
|
|
if (!compare_uvec4(&got, &expected))
|
|
break;
|
|
}
|
|
if (!compare_uvec4(&got, &expected))
|
|
break;
|
|
}
|
|
release_resource_readback(&rb);
|
|
ok(compare_uvec4(&got, &expected),
|
|
"Got {0x%08x, 0x%08x, 0x%08x, 0x%08x} at (%u, %u), expected {0x%08x, 0x%08x, 0x%08x, 0x%08x}.\n",
|
|
got.x, got.y, got.z, got.w, x, y, expected.x, expected.y, expected.z, expected.w);
|
|
|
|
reset_command_list(command_list, context.allocator);
|
|
get_texture_readback_with_command_list(texture, 2, &rb, queue, command_list);
|
|
block_id = 1;
|
|
expected.x = block_id << 8 | 0;
|
|
expected.y = block_id << 8 | 1;
|
|
expected.z = block_id << 8 | 2;
|
|
expected.w = block_id << 8 | 3;
|
|
got = *get_readback_uvec4(&rb, 0, 0);
|
|
release_resource_readback(&rb);
|
|
ok(compare_uvec4(&got, &expected),
|
|
"Got {0x%08x, 0x%08x, 0x%08x, 0x%08x}, expected {0x%08x, 0x%08x, 0x%08x, 0x%08x}.\n",
|
|
got.x, got.y, got.z, got.w, expected.x, expected.y, expected.z, expected.w);
|
|
|
|
reset_command_list(command_list, context.allocator);
|
|
get_texture_readback_with_command_list(texture, 3, &rb, queue, command_list);
|
|
block_id = 2;
|
|
expected.x = block_id << 8 | 0;
|
|
expected.y = block_id << 8 | 1;
|
|
expected.z = block_id << 8 | 2;
|
|
expected.w = block_id << 8 | 3;
|
|
got = *get_readback_uvec4(&rb, 0, 0);
|
|
release_resource_readback(&rb);
|
|
ok(compare_uvec4(&got, &expected),
|
|
"Got {0x%08x, 0x%08x, 0x%08x, 0x%08x}, expected {0x%08x, 0x%08x, 0x%08x, 0x%08x}.\n",
|
|
got.x, got.y, got.z, got.w, expected.x, expected.y, expected.z, expected.w);
|
|
|
|
reset_command_list(command_list, context.allocator);
|
|
get_buffer_readback_with_command_list(dst_buffer, DXGI_FORMAT_R32_UINT, &rb, queue, command_list);
|
|
for (y = 0; y < 24 / format_block_height(DXGI_FORMAT_BC2_UNORM); ++y)
|
|
{
|
|
unsigned int row_offset = dst_location.PlacedFootprint.Footprint.RowPitch / sizeof(got) * y;
|
|
|
|
for (x = 0; x < 4 / format_block_width(DXGI_FORMAT_BC2_UNORM); ++x)
|
|
{
|
|
if (x == 0 && y % 2 == 0)
|
|
block_id = 33;
|
|
else if (x == 1 && y % 2 == 0)
|
|
block_id = 7;
|
|
else if (x == 0 && y % 2 == 1)
|
|
block_id = 192;
|
|
else
|
|
block_id = 132;
|
|
|
|
expected.x = block_id << 8 | 0;
|
|
expected.y = block_id << 8 | 1;
|
|
expected.z = block_id << 8 | 2;
|
|
expected.w = block_id << 8 | 3;
|
|
got = *get_readback_uvec4(&rb, x + row_offset, 0);
|
|
|
|
if (!compare_uvec4(&got, &expected))
|
|
break;
|
|
}
|
|
if (!compare_uvec4(&got, &expected))
|
|
break;
|
|
}
|
|
release_resource_readback(&rb);
|
|
ok(compare_uvec4(&got, &expected),
|
|
"Got {0x%08x, 0x%08x, 0x%08x, 0x%08x} at (%u, %u), expected {0x%08x, 0x%08x, 0x%08x, 0x%08x}.\n",
|
|
got.x, got.y, got.z, got.w, x, y, expected.x, expected.y, expected.z, expected.w);
|
|
|
|
ID3D12Resource_Release(texture);
|
|
ID3D12Resource_Release(src_buffer);
|
|
ID3D12Resource_Release(dst_buffer);
|
|
destroy_test_context(&context);
|
|
}
|
|
|
|
void test_multisample_resolve(void)
|
|
{
|
|
D3D12_HEAP_PROPERTIES heap_properties;
|
|
ID3D12Resource *ms_render_target_copy;
|
|
D3D12_CPU_DESCRIPTOR_HANDLE ms_rtv;
|
|
D3D12_RESOURCE_DESC resource_desc;
|
|
ID3D12GraphicsCommandList1 *list1;
|
|
ID3D12Resource *ms_render_target;
|
|
ID3D12Resource *render_target;
|
|
struct test_context_desc desc;
|
|
struct test_context context;
|
|
struct resource_readback rb;
|
|
ID3D12DescriptorHeap *heap;
|
|
D3D12_RECT src_rect;
|
|
unsigned int x, y;
|
|
HRESULT hr;
|
|
|
|
static const uint32_t reference_color[4 * 4] = {
|
|
0x01010101, 0x02020202, 0x03030303, 0x04040404,
|
|
0x05050505, 0x06060606, 0x07070707, 0x08080808,
|
|
0x09090909, 0x0a0a0a0a, 0x0b0b0b0b, 0x0c0c0c0c,
|
|
0x0d0d0d0d, 0x0e0e0e0e, 0x0f0f0f0f, 0x10101010,
|
|
};
|
|
|
|
memset(&desc, 0, sizeof(desc));
|
|
desc.no_root_signature = true;
|
|
desc.no_render_target = true;
|
|
if (!init_test_context(&context, &desc))
|
|
return;
|
|
|
|
hr = ID3D12GraphicsCommandList_QueryInterface(context.list, &IID_ID3D12GraphicsCommandList1, (void **)&list1);
|
|
if (FAILED(hr))
|
|
{
|
|
destroy_test_context(&context);
|
|
skip("Failed to query ID3D12GraphicsCommandList1. Skipping tests.\n");
|
|
return;
|
|
}
|
|
|
|
heap = create_cpu_descriptor_heap(context.device, D3D12_DESCRIPTOR_HEAP_TYPE_RTV, 1);
|
|
|
|
memset(&heap_properties, 0, sizeof(heap_properties));
|
|
heap_properties.Type = D3D12_HEAP_TYPE_DEFAULT;
|
|
|
|
memset(&resource_desc, 0, sizeof(resource_desc));
|
|
resource_desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
|
|
resource_desc.Width = 4 * 2;
|
|
resource_desc.Height = 4;
|
|
resource_desc.DepthOrArraySize = 1;
|
|
resource_desc.MipLevels = 1;
|
|
resource_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
|
resource_desc.SampleDesc.Count = 4;
|
|
resource_desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
|
|
hr = ID3D12Device_CreateCommittedResource(context.device, &heap_properties, D3D12_HEAP_FLAG_NONE,
|
|
&resource_desc, D3D12_RESOURCE_STATE_RENDER_TARGET, NULL, &IID_ID3D12Resource, (void **)&ms_render_target);
|
|
ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
|
|
resource_desc.Width = 4;
|
|
hr = ID3D12Device_CreateCommittedResource(context.device, &heap_properties, D3D12_HEAP_FLAG_NONE,
|
|
&resource_desc, D3D12_RESOURCE_STATE_RESOLVE_DEST, NULL, &IID_ID3D12Resource, (void **)&ms_render_target_copy);
|
|
ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
|
|
resource_desc.SampleDesc.Count = 1;
|
|
resource_desc.Height = 8;
|
|
hr = ID3D12Device_CreateCommittedResource(context.device, &heap_properties, D3D12_HEAP_FLAG_NONE,
|
|
&resource_desc, D3D12_RESOURCE_STATE_RESOLVE_DEST, NULL, &IID_ID3D12Resource, (void **)&render_target);
|
|
ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
|
|
|
|
ms_rtv = ID3D12DescriptorHeap_GetCPUDescriptorHandleForHeapStart(heap);
|
|
ID3D12Device_CreateRenderTargetView(context.device, ms_render_target, NULL, ms_rtv);
|
|
|
|
for (y = 0; y < 4; y++)
|
|
{
|
|
for (x = 0; x < 4; x++)
|
|
{
|
|
const FLOAT float_color[4] = {
|
|
(float)((reference_color[y * 4 + x] >> 0) & 0xff) / 255.0f,
|
|
(float)((reference_color[y * 4 + x] >> 8) & 0xff) / 255.0f,
|
|
(float)((reference_color[y * 4 + x] >> 16) & 0xff) / 255.0f,
|
|
(float)((reference_color[y * 4 + x] >> 24) & 0xff) / 255.0f,
|
|
};
|
|
|
|
src_rect.left = x;
|
|
src_rect.right = x + 1;
|
|
src_rect.top = y;
|
|
src_rect.bottom = y + 1;
|
|
ID3D12GraphicsCommandList_ClearRenderTargetView(context.list, ms_rtv, float_color, 1, &src_rect);
|
|
}
|
|
}
|
|
|
|
transition_resource_state(context.list, ms_render_target, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_RESOLVE_SOURCE);
|
|
|
|
/* First, try decompress directly on the MSAA texture. Apparently, we have to be in RESOURCE_SOURCE here even if dst is used.
|
|
* For us, this should be a no-op. */
|
|
ID3D12GraphicsCommandList1_ResolveSubresourceRegion(list1, ms_render_target, 0, 0, 0, ms_render_target, 0, NULL, DXGI_FORMAT_R8G8B8A8_UNORM, D3D12_RESOLVE_MODE_DECOMPRESS);
|
|
|
|
/* Now, DECOMPRESS as in-place copy by decompressing to second half of the subresource. Here we'll have to use GENERAL layout. */
|
|
src_rect.left = 0;
|
|
src_rect.right = 4;
|
|
src_rect.top = 0;
|
|
src_rect.bottom = 4;
|
|
ID3D12GraphicsCommandList1_ResolveSubresourceRegion(list1, ms_render_target, 0, 4, 0, ms_render_target, 0, &src_rect, DXGI_FORMAT_R8G8B8A8_UNORM, D3D12_RESOLVE_MODE_DECOMPRESS);
|
|
|
|
/* DECOMPRESS to other resource MSAA <-> MSAA. vkCmdCopyImage2KHR path. */
|
|
ID3D12GraphicsCommandList1_ResolveSubresourceRegion(list1, ms_render_target_copy, 0, 0, 0, ms_render_target, 0, &src_rect, DXGI_FORMAT_R8G8B8A8_UNORM, D3D12_RESOLVE_MODE_DECOMPRESS);
|
|
transition_resource_state(context.list, ms_render_target_copy, D3D12_RESOURCE_STATE_RESOLVE_DEST, D3D12_RESOURCE_STATE_RESOLVE_SOURCE);
|
|
|
|
for (y = 0; y < 4; y++)
|
|
{
|
|
for (x = 0; x < 4; x++)
|
|
{
|
|
src_rect.left = x;
|
|
src_rect.right = x + 1;
|
|
src_rect.top = y;
|
|
src_rect.bottom = y + 1;
|
|
/* Test partial resolve with offset. */
|
|
ID3D12GraphicsCommandList1_ResolveSubresourceRegion(list1, render_target, 0, x, y + 4, ms_render_target_copy, 0, &src_rect, DXGI_FORMAT_R8G8B8A8_UNORM, D3D12_RESOLVE_MODE_AVERAGE);
|
|
}
|
|
}
|
|
transition_resource_state(context.list, render_target, D3D12_RESOURCE_STATE_RESOLVE_DEST, D3D12_RESOURCE_STATE_COPY_SOURCE);
|
|
get_texture_readback_with_command_list(render_target, 0, &rb, context.queue, context.list);
|
|
for (y = 0; y < 4; y++)
|
|
{
|
|
for (x = 0; x < 4; x++)
|
|
{
|
|
uint32_t v, reference;
|
|
v = get_readback_uint(&rb, x, y + 4, 0);
|
|
reference = reference_color[y * 4 + x];
|
|
ok(v == reference, "Pixel %u, %u failed, %x != %x.\n", x, y + 4, v, reference);
|
|
}
|
|
}
|
|
release_resource_readback(&rb);
|
|
|
|
ID3D12Resource_Release(ms_render_target_copy);
|
|
ID3D12Resource_Release(ms_render_target);
|
|
ID3D12Resource_Release(render_target);
|
|
ID3D12DescriptorHeap_Release(heap);
|
|
ID3D12GraphicsCommandList1_Release(list1);
|
|
destroy_test_context(&context);
|
|
}
|
|
|
|
void test_copy_buffer_overlap(void)
|
|
{
|
|
uint32_t reference_output[4][16 * 1024] = {{0}};
|
|
ID3D12Resource *dst_buffer[4];
|
|
uint32_t src_data[16 * 1024];
|
|
struct test_context context;
|
|
struct resource_readback rb;
|
|
ID3D12Resource *src_buffer;
|
|
unsigned int i, j;
|
|
|
|
struct copy_command
|
|
{
|
|
unsigned int buf_index;
|
|
unsigned int dst_index;
|
|
unsigned int src_index;
|
|
unsigned int count;
|
|
};
|
|
static const struct copy_command commands[] =
|
|
{
|
|
/* These should be able to run without any barriers. */
|
|
{ 0, 0, 0, 8192 },
|
|
{ 0, 8192, 8192, 8192 },
|
|
{ 1, 0, 0, 8192 },
|
|
{ 1, 8192, 8192, 8192 },
|
|
{ 2, 0, 0, 8192 },
|
|
{ 2, 8192, 8192, 8192 },
|
|
{ 3, 0, 0, 8192 },
|
|
{ 3, 8192, 8192, 8192 },
|
|
/* Needs barrier. */
|
|
{ 0, 1, 0, 8192 },
|
|
/* Needs barrier. */
|
|
{ 0, 8000, 4, 1 },
|
|
{ 1, 1000, 5001, 3},
|
|
/* Needs barrier. */
|
|
{ 1, 1000, 5000, 8192 },
|
|
{ 2, 0, 0, 8192 },
|
|
/* Needs barrier. */
|
|
{ 2, 1, 0, 8192 },
|
|
/* Needs barrier. */
|
|
{ 2, 2, 0, 8192 },
|
|
/* Needs barrier. */
|
|
{ 2, 3, 0, 8192 },
|
|
};
|
|
|
|
/* Drivers are required to implicitly synchronize any overlapping copies to same destination.
|
|
* There is no Transfer barrier after all, only UAV ...
|
|
* For images we do this implicitly through image layout transitions on entry/exit,
|
|
* but for buffers, we need to explicitly inject barriers as necessary.
|
|
* Verify that reordering of copy commands does not happen. */
|
|
|
|
if (!init_compute_test_context(&context))
|
|
return;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(src_data); i++)
|
|
src_data[i] = i;
|
|
|
|
src_buffer = create_upload_buffer(context.device, sizeof(src_data), src_data);
|
|
for (i = 0; i < ARRAY_SIZE(dst_buffer); i++)
|
|
{
|
|
dst_buffer[i] = create_default_buffer(context.device, sizeof(src_data),
|
|
D3D12_RESOURCE_FLAG_NONE, D3D12_RESOURCE_STATE_COPY_DEST);
|
|
}
|
|
|
|
for (i = 0; i < ARRAY_SIZE(commands); i++)
|
|
{
|
|
ID3D12GraphicsCommandList_CopyBufferRegion(context.list,
|
|
dst_buffer[commands[i].buf_index], commands[i].dst_index * sizeof(uint32_t),
|
|
src_buffer, commands[i].src_index * sizeof(uint32_t),
|
|
commands[i].count * sizeof(uint32_t));
|
|
|
|
for (j = 0; j < commands[i].count; j++)
|
|
reference_output[commands[i].buf_index][commands[i].dst_index + j] = commands[i].src_index + j;
|
|
}
|
|
|
|
for (i = 0; i < ARRAY_SIZE(dst_buffer); i++)
|
|
{
|
|
transition_resource_state(context.list, dst_buffer[i],
|
|
D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_COPY_SOURCE);
|
|
get_buffer_readback_with_command_list(dst_buffer[i], DXGI_FORMAT_R32_UINT, &rb, context.queue, context.list);
|
|
reset_command_list(context.list, context.allocator);
|
|
|
|
for (j = 0; j < ARRAY_SIZE(reference_output[i]); j++)
|
|
{
|
|
ok(get_readback_uint(&rb, j, 0, 0) == reference_output[i][j], "%u, %u: Expected %u, got %u.\n",
|
|
i, j, reference_output[i][j], get_readback_uint(&rb, j, 0, 0));
|
|
}
|
|
|
|
release_resource_readback(&rb);
|
|
}
|
|
|
|
for (i = 0; i < ARRAY_SIZE(dst_buffer); i++)
|
|
ID3D12Resource_Release(dst_buffer[i]);
|
|
ID3D12Resource_Release(src_buffer);
|
|
destroy_test_context(&context);
|
|
}
|
|
|