2 * Copyright 2016-2018 Józef Kucia for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include "d3d12_crosstest.h"
21 VKD3D_AGILITY_SDK_EXPORTS
23 struct test_options test_options
= {0};
25 #define recreate_command_list(a, b, c) recreate_command_list_(__FILE__, __LINE__, a, b, c)
26 static void recreate_command_list_(const char *file
, unsigned int line
, ID3D12Device
*device
,
27 ID3D12CommandAllocator
*allocator
, ID3D12GraphicsCommandList
**command_list
)
31 hr
= ID3D12CommandAllocator_Reset(allocator
);
32 ok_(file
, line
)(hr
== S_OK
, "Failed to reset command allocator, hr %#x.\n", hr
);
33 ID3D12GraphicsCommandList_Release(*command_list
);
34 hr
= ID3D12Device_CreateCommandList(device
, 0, D3D12_COMMAND_LIST_TYPE_DIRECT
,
35 allocator
, NULL
, &IID_ID3D12GraphicsCommandList
, (void **)command_list
);
36 ok_(file
, line
)(hr
== S_OK
, "Failed to create command list, hr %#x.\n", hr
);
39 static void test_invalid_resource_barriers(void)
41 ID3D12Resource
*texture
, *readback_buffer
, *upload_buffer
;
42 ID3D12CommandAllocator
*command_allocator
;
43 ID3D12GraphicsCommandList
*command_list
;
44 ID3D12CommandQueue
*queue
;
49 if (!(device
= create_device()))
51 skip("Failed to create device.\n");
55 queue
= create_command_queue(device
, D3D12_COMMAND_LIST_TYPE_DIRECT
, D3D12_COMMAND_QUEUE_PRIORITY_NORMAL
);
57 hr
= ID3D12Device_CreateCommandAllocator(device
, D3D12_COMMAND_LIST_TYPE_DIRECT
,
58 &IID_ID3D12CommandAllocator
, (void **)&command_allocator
);
59 ok(hr
== S_OK
, "Failed to create command allocator, hr %#x.\n", hr
);
61 hr
= ID3D12Device_CreateCommandList(device
, 0, D3D12_COMMAND_LIST_TYPE_DIRECT
,
62 command_allocator
, NULL
, &IID_ID3D12GraphicsCommandList
, (void **)&command_list
);
63 ok(hr
== S_OK
, "Failed to create command list, hr %#x.\n", hr
);
65 texture
= create_default_texture(device
, 32, 32, DXGI_FORMAT_R8G8B8A8_UNORM
,
66 D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS
, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
);
67 upload_buffer
= create_upload_buffer(device
, 32, NULL
);
68 readback_buffer
= create_readback_buffer(device
, 32);
70 /* The following invalid barrier is not detected by the runtime. */
71 transition_resource_state(command_list
, texture
,
72 D3D12_RESOURCE_STATE_UNORDERED_ACCESS
, D3D12_RESOURCE_STATE_COPY_SOURCE
);
73 hr
= ID3D12GraphicsCommandList_Close(command_list
);
74 ok(hr
== S_OK
, "Failed to close command list, hr %#x.\n", hr
);
76 reset_command_list(command_list
, command_allocator
);
78 /* The before state does not match with the previous state. */
79 transition_resource_state(command_list
, texture
,
80 D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
, D3D12_RESOURCE_STATE_COPY_SOURCE
);
81 transition_resource_state(command_list
, texture
,
82 D3D12_RESOURCE_STATE_UNORDERED_ACCESS
, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE
);
83 hr
= ID3D12GraphicsCommandList_Close(command_list
);
84 /* The returned error code has changed after a Windows update. */
85 ok(hr
== S_OK
|| hr
== E_INVALIDARG
, "Got unexpected hr %#x.\n", hr
);
88 exec_command_list(queue
, command_list
);
89 wait_queue_idle(device
, queue
);
92 recreate_command_list(device
, command_allocator
, &command_list
);
94 /* The before state does not match with the previous state. */
95 transition_resource_state(command_list
, texture
,
96 D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE
,
97 D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE
| D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
);
98 transition_resource_state(command_list
, texture
,
99 D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
, D3D12_RESOURCE_STATE_UNORDERED_ACCESS
);
100 hr
= ID3D12GraphicsCommandList_Close(command_list
);
101 /* The returned error code has changed after a Windows update. */
102 ok(hr
== S_OK
|| hr
== E_INVALIDARG
, "Got unexpected hr %#x.\n", hr
);
105 exec_command_list(queue
, command_list
);
106 wait_queue_idle(device
, queue
);
109 recreate_command_list(device
, command_allocator
, &command_list
);
111 /* Exactly one write state or a combination of read-only states are allowed. */
112 transition_resource_state(command_list
, texture
,
113 D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
,
114 D3D12_RESOURCE_STATE_UNORDERED_ACCESS
| D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE
);
115 hr
= ID3D12GraphicsCommandList_Close(command_list
);
116 ok(hr
== E_INVALIDARG
, "Got unexpected hr %#x.\n", hr
);
118 recreate_command_list(device
, command_allocator
, &command_list
);
120 /* Readback resources cannot transition from D3D12_RESOURCE_STATE_COPY_DEST. */
121 transition_resource_state(command_list
, readback_buffer
,
122 D3D12_RESOURCE_STATE_COPY_DEST
, D3D12_RESOURCE_STATE_COMMON
);
123 hr
= ID3D12GraphicsCommandList_Close(command_list
);
124 todo
ok(hr
== E_INVALIDARG
, "Got unexpected hr %#x.\n", hr
);
126 recreate_command_list(device
, command_allocator
, &command_list
);
128 /* Upload resources cannot transition from D3D12_RESOURCE_STATE_GENERIC_READ. */
129 transition_resource_state(command_list
, upload_buffer
,
130 D3D12_RESOURCE_STATE_GENERIC_READ
, D3D12_RESOURCE_STATE_COMMON
);
131 hr
= ID3D12GraphicsCommandList_Close(command_list
);
132 todo
ok(hr
== E_INVALIDARG
, "Got unexpected hr %#x.\n", hr
);
134 recreate_command_list(device
, command_allocator
, &command_list
);
137 transition_resource_state(command_list
, NULL
,
138 D3D12_RESOURCE_STATE_RENDER_TARGET
, D3D12_RESOURCE_STATE_COPY_SOURCE
);
139 hr
= ID3D12GraphicsCommandList_Close(command_list
);
140 ok(hr
== E_INVALIDARG
, "Got unexpected hr %#x.\n", hr
);
142 ID3D12CommandAllocator_Release(command_allocator
);
143 ID3D12CommandQueue_Release(queue
);
144 ID3D12GraphicsCommandList_Release(command_list
);
145 ID3D12Resource_Release(readback_buffer
);
146 ID3D12Resource_Release(texture
);
147 ID3D12Resource_Release(upload_buffer
);
148 refcount
= ID3D12Device_Release(device
);
149 ok(!refcount
, "ID3D12Device has %u references left.\n", (unsigned int)refcount
);
152 static void test_invalid_copy_texture_region(void)
154 ID3D12Resource
*dst_texture
, *src_texture
, *dst_buffer
, *src_buffer
;
155 D3D12_TEXTURE_COPY_LOCATION src_location
, dst_location
;
156 ID3D12CommandAllocator
*command_allocator
;
157 ID3D12GraphicsCommandList
*command_list
;
158 ID3D12Device
*device
;
163 if (!(device
= create_device()))
165 skip("Failed to create device.\n");
169 hr
= ID3D12Device_CreateCommandAllocator(device
, D3D12_COMMAND_LIST_TYPE_DIRECT
,
170 &IID_ID3D12CommandAllocator
, (void **)&command_allocator
);
171 ok(hr
== S_OK
, "Failed to create command allocator, hr %#x.\n", hr
);
173 hr
= ID3D12Device_CreateCommandList(device
, 0, D3D12_COMMAND_LIST_TYPE_DIRECT
,
174 command_allocator
, NULL
, &IID_ID3D12GraphicsCommandList
, (void **)&command_list
);
175 ok(hr
== S_OK
, "Failed to create command list, hr %#x.\n", hr
);
177 src_buffer
= create_upload_buffer(device
, 0x40000, NULL
);
178 dst_buffer
= create_default_buffer(device
, 0x40000, 0, D3D12_RESOURCE_STATE_COPY_DEST
);
180 src_texture
= create_default_texture(device
, 64, 64,
181 DXGI_FORMAT_BC3_UNORM
, 0, D3D12_RESOURCE_STATE_COPY_SOURCE
);
182 dst_texture
= create_default_texture(device
, 64, 64,
183 DXGI_FORMAT_BC3_UNORM
, 0, D3D12_RESOURCE_STATE_COPY_DEST
);
185 dst_location
.pResource
= dst_texture
;
186 dst_location
.Type
= D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX
;
187 dst_location
.SubresourceIndex
= 0;
189 src_location
.pResource
= src_buffer
;
190 src_location
.Type
= D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT
;
191 src_location
.PlacedFootprint
.Offset
= D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT
;
192 src_location
.PlacedFootprint
.Footprint
.Format
= DXGI_FORMAT_BC3_UNORM
;
193 src_location
.PlacedFootprint
.Footprint
.Width
= 64;
194 src_location
.PlacedFootprint
.Footprint
.Height
= 63; /* height must be multiple of block size */
195 src_location
.PlacedFootprint
.Footprint
.Depth
= 1;
196 src_location
.PlacedFootprint
.Footprint
.RowPitch
197 = 64 / format_block_width(DXGI_FORMAT_BC3_UNORM
) * format_size(DXGI_FORMAT_BC3_UNORM
);
199 ID3D12GraphicsCommandList_CopyTextureRegion(command_list
,
200 &dst_location
, 0, 0, 0, &src_location
, NULL
);
202 hr
= ID3D12GraphicsCommandList_Close(command_list
);
203 todo
ok(hr
== E_INVALIDARG
, "Got unexpected hr %#x.\n", hr
);
205 recreate_command_list(device
, command_allocator
, &command_list
);
207 src_location
.PlacedFootprint
.Footprint
.Width
= 4;
208 src_location
.PlacedFootprint
.Footprint
.Height
= 4;
210 /* dst y must be multiple of block size */
211 ID3D12GraphicsCommandList_CopyTextureRegion(command_list
,
212 &dst_location
, 0, 3, 0, &src_location
, NULL
);
214 hr
= ID3D12GraphicsCommandList_Close(command_list
);
215 todo
ok(hr
== E_INVALIDARG
, "Got unexpected hr %#x.\n", hr
);
217 recreate_command_list(device
, command_allocator
, &command_list
);
219 /* row pitch must be multiple of D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT */
220 src_location
.PlacedFootprint
.Footprint
.RowPitch
221 = 64 / format_block_width(DXGI_FORMAT_BC3_UNORM
) * format_size(DXGI_FORMAT_BC3_UNORM
) + 1;
223 ID3D12GraphicsCommandList_CopyTextureRegion(command_list
,
224 &dst_location
, 0, 0, 0, &src_location
, NULL
);
226 hr
= ID3D12GraphicsCommandList_Close(command_list
);
227 todo
ok(hr
== E_INVALIDARG
, "Got unexpected hr %#x.\n", hr
);
229 recreate_command_list(device
, command_allocator
, &command_list
);
231 dst_location
.pResource
= dst_buffer
;
232 dst_location
.Type
= D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT
;
233 dst_location
.PlacedFootprint
.Offset
= D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT
;
234 dst_location
.PlacedFootprint
.Footprint
.Format
= DXGI_FORMAT_BC3_UNORM
;
235 dst_location
.PlacedFootprint
.Footprint
.Width
= 64;
236 dst_location
.PlacedFootprint
.Footprint
.Height
= 64;
237 dst_location
.PlacedFootprint
.Footprint
.Depth
= 1;
238 dst_location
.PlacedFootprint
.Footprint
.RowPitch
239 = 64 / format_block_width(DXGI_FORMAT_BC3_UNORM
) * format_size(DXGI_FORMAT_BC3_UNORM
);
241 src_location
.pResource
= src_texture
;
242 src_location
.Type
= D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX
;
243 src_location
.SubresourceIndex
= 0;
245 /* coordinates must be multiple of block size */
246 set_box(&box
, 0, 0, 0, 31, 31, 1);
247 ID3D12GraphicsCommandList_CopyTextureRegion(command_list
,
248 &dst_location
, 0, 0, 0, &src_location
, &box
);
250 hr
= ID3D12GraphicsCommandList_Close(command_list
);
251 todo
ok(hr
== E_INVALIDARG
, "Got unexpected hr %#x.\n", hr
);
253 recreate_command_list(device
, command_allocator
, &command_list
);
255 ID3D12Resource_Release(src_texture
);
256 src_texture
= create_default_texture2d(device
, 4, 4, 1, 3, DXGI_FORMAT_BC3_UNORM
,
257 D3D12_RESOURCE_FLAG_NONE
, D3D12_RESOURCE_STATE_COPY_SOURCE
);
259 src_location
.pResource
= src_texture
;
260 src_location
.Type
= D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX
;
261 src_location
.SubresourceIndex
= 1;
263 /* coordinates must be multiple of block size even for smallest miplevels */
264 set_box(&box
, 0, 0, 0, 2, 2, 1);
265 ID3D12GraphicsCommandList_CopyTextureRegion(command_list
,
266 &dst_location
, 0, 0, 0, &src_location
, &box
);
268 hr
= ID3D12GraphicsCommandList_Close(command_list
);
269 todo
ok(hr
== E_INVALIDARG
, "Got unexpected hr %#x.\n", hr
);
271 recreate_command_list(device
, command_allocator
, &command_list
);
273 src_location
.SubresourceIndex
= 2;
275 /* coordinates must be multiple of block size even for smallest miplevels */
276 set_box(&box
, 0, 0, 0, 1, 1, 1);
277 ID3D12GraphicsCommandList_CopyTextureRegion(command_list
,
278 &dst_location
, 0, 0, 0, &src_location
, &box
);
280 hr
= ID3D12GraphicsCommandList_Close(command_list
);
281 todo
ok(hr
== E_INVALIDARG
, "Got unexpected hr %#x.\n", hr
);
283 ID3D12CommandAllocator_Release(command_allocator
);
284 ID3D12GraphicsCommandList_Release(command_list
);
285 ID3D12Resource_Release(dst_buffer
);
286 ID3D12Resource_Release(src_buffer
);
287 ID3D12Resource_Release(src_texture
);
288 ID3D12Resource_Release(dst_texture
);
289 refcount
= ID3D12Device_Release(device
);
290 ok(!refcount
, "ID3D12Device has %u references left.\n", (unsigned int)refcount
);
293 static void test_invalid_unordered_access_views(void)
295 D3D12_UNORDERED_ACCESS_VIEW_DESC uav_desc
;
296 D3D12_CPU_DESCRIPTOR_HANDLE cpu_handle
;
297 ID3D12DescriptorHeap
*heap
;
298 ID3D12Resource
*buffer
;
299 ID3D12Device
*device
;
302 if (!(device
= create_device()))
304 skip("Failed to create device.\n");
308 heap
= create_gpu_descriptor_heap(device
, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV
, 16);
310 buffer
= create_default_buffer(device
, 64 * sizeof(float),
311 D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS
, D3D12_RESOURCE_STATE_UNORDERED_ACCESS
);
313 cpu_handle
= ID3D12DescriptorHeap_GetCPUDescriptorHandleForHeapStart(heap
);
315 /* Buffer views cannot be created for compressed formats. */
316 uav_desc
.Format
= DXGI_FORMAT_BC1_UNORM
;
317 uav_desc
.ViewDimension
= D3D12_UAV_DIMENSION_BUFFER
;
318 uav_desc
.Buffer
.FirstElement
= 0;
319 uav_desc
.Buffer
.NumElements
= 64;
320 uav_desc
.Buffer
.StructureByteStride
= 0;
321 uav_desc
.Buffer
.CounterOffsetInBytes
= 0;
322 uav_desc
.Buffer
.Flags
= D3D12_BUFFER_UAV_FLAG_NONE
;
323 ID3D12Device_CreateUnorderedAccessView(device
, buffer
, NULL
, &uav_desc
, cpu_handle
);
325 ID3D12DescriptorHeap_Release(heap
);
326 ID3D12Resource_Release(buffer
);
327 refcount
= ID3D12Device_Release(device
);
328 ok(!refcount
, "ID3D12Device has %u references left.\n", (unsigned int)refcount
);
331 START_TEST(d3d12_invalid_usage
)
333 parse_args(argc
, argv
);
334 enable_d3d12_debug_layer();
337 run_test(test_invalid_resource_barriers
);
338 run_test(test_invalid_copy_texture_region
);
339 run_test(test_invalid_unordered_access_views
);