1 /*
2 * Copyright 2016-2018 Józef Kucia for CodeWeavers
3 *
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.
8 *
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.
13 *
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
17 */
18
19 #include "d3d12_crosstest.h"
20
21 #define recreate_command_list(a, b, c) recreate_command_list_(__LINE__, a, b, c)
recreate_command_list_(unsigned int line,ID3D12Device * device,ID3D12CommandAllocator * allocator,ID3D12GraphicsCommandList ** command_list)22 static void recreate_command_list_(unsigned int line, ID3D12Device *device,
23 ID3D12CommandAllocator *allocator, ID3D12GraphicsCommandList **command_list)
24 {
25 HRESULT hr;
26
27 hr = ID3D12CommandAllocator_Reset(allocator);
28 ok_(line)(hr == S_OK, "Failed to reset command allocator, hr %#x.\n", hr);
29 ID3D12GraphicsCommandList_Release(*command_list);
30 hr = ID3D12Device_CreateCommandList(device, 0, D3D12_COMMAND_LIST_TYPE_DIRECT,
31 allocator, NULL, &IID_ID3D12GraphicsCommandList, (void **)command_list);
32 ok_(line)(hr == S_OK, "Failed to create command list, hr %#x.\n", hr);
33 }
34
test_invalid_resource_barriers(void)35 static void test_invalid_resource_barriers(void)
36 {
37 ID3D12Resource *texture, *readback_buffer, *upload_buffer;
38 ID3D12CommandAllocator *command_allocator;
39 ID3D12GraphicsCommandList *command_list;
40 ID3D12CommandQueue *queue;
41 ID3D12Device *device;
42 ULONG refcount;
43 HRESULT hr;
44
45 if (!(device = create_device()))
46 {
47 skip("Failed to create device.\n");
48 return;
49 }
50
51 queue = create_command_queue(device, D3D12_COMMAND_LIST_TYPE_DIRECT, D3D12_COMMAND_QUEUE_PRIORITY_NORMAL);
52
53 hr = ID3D12Device_CreateCommandAllocator(device, D3D12_COMMAND_LIST_TYPE_DIRECT,
54 &IID_ID3D12CommandAllocator, (void **)&command_allocator);
55 ok(hr == S_OK, "Failed to create command allocator, hr %#x.\n", hr);
56
57 hr = ID3D12Device_CreateCommandList(device, 0, D3D12_COMMAND_LIST_TYPE_DIRECT,
58 command_allocator, NULL, &IID_ID3D12GraphicsCommandList, (void **)&command_list);
59 ok(hr == S_OK, "Failed to create command list, hr %#x.\n", hr);
60
61 texture = create_default_texture(device, 32, 32, DXGI_FORMAT_R8G8B8A8_UNORM,
62 D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);
63 upload_buffer = create_upload_buffer(device, 32, NULL);
64 readback_buffer = create_readback_buffer(device, 32);
65
66 /* The following invalid barrier is not detected by the runtime. */
67 transition_resource_state(command_list, texture,
68 D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_COPY_SOURCE);
69 hr = ID3D12GraphicsCommandList_Close(command_list);
70 ok(hr == S_OK, "Failed to close command list, hr %#x.\n", hr);
71
72 reset_command_list(command_list, command_allocator);
73
74 /* The before state does not match with the previous state. */
75 transition_resource_state(command_list, texture,
76 D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_COPY_SOURCE);
77 transition_resource_state(command_list, texture,
78 D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
79 hr = ID3D12GraphicsCommandList_Close(command_list);
80 /* The returned error code has changed after a Windows update. */
81 ok(hr == S_OK || hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
82 if (hr == S_OK)
83 {
84 exec_command_list(queue, command_list);
85 wait_queue_idle(device, queue);
86 }
87
88 recreate_command_list(device, command_allocator, &command_list);
89
90 /* The before state does not match with the previous state. */
91 transition_resource_state(command_list, texture,
92 D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
93 D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);
94 transition_resource_state(command_list, texture,
95 D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
96 hr = ID3D12GraphicsCommandList_Close(command_list);
97 /* The returned error code has changed after a Windows update. */
98 ok(hr == S_OK || hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
99 if (hr == S_OK)
100 {
101 exec_command_list(queue, command_list);
102 wait_queue_idle(device, queue);
103 }
104
105 recreate_command_list(device, command_allocator, &command_list);
106
107 /* Exactly one write state or a combination of read-only states are allowed. */
108 transition_resource_state(command_list, texture,
109 D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE,
110 D3D12_RESOURCE_STATE_UNORDERED_ACCESS | D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
111 hr = ID3D12GraphicsCommandList_Close(command_list);
112 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
113
114 recreate_command_list(device, command_allocator, &command_list);
115
116 /* Readback resources cannot transition from D3D12_RESOURCE_STATE_COPY_DEST. */
117 transition_resource_state(command_list, readback_buffer,
118 D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_COMMON);
119 hr = ID3D12GraphicsCommandList_Close(command_list);
120 todo ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
121
122 recreate_command_list(device, command_allocator, &command_list);
123
124 /* Upload resources cannot transition from D3D12_RESOURCE_STATE_GENERIC_READ. */
125 transition_resource_state(command_list, upload_buffer,
126 D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_COMMON);
127 hr = ID3D12GraphicsCommandList_Close(command_list);
128 todo ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
129
130 recreate_command_list(device, command_allocator, &command_list);
131
132 /* NULL resource. */
133 transition_resource_state(command_list, NULL,
134 D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE);
135 hr = ID3D12GraphicsCommandList_Close(command_list);
136 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
137
138 ID3D12CommandAllocator_Release(command_allocator);
139 ID3D12CommandQueue_Release(queue);
140 ID3D12GraphicsCommandList_Release(command_list);
141 ID3D12Resource_Release(readback_buffer);
142 ID3D12Resource_Release(texture);
143 ID3D12Resource_Release(upload_buffer);
144 refcount = ID3D12Device_Release(device);
145 ok(!refcount, "ID3D12Device has %u references left.\n", (unsigned int)refcount);
146 }
147
test_invalid_copy_texture_region(void)148 static void test_invalid_copy_texture_region(void)
149 {
150 ID3D12Resource *dst_texture, *src_texture, *dst_buffer, *src_buffer;
151 D3D12_TEXTURE_COPY_LOCATION src_location, dst_location;
152 ID3D12CommandAllocator *command_allocator;
153 ID3D12GraphicsCommandList *command_list;
154 ID3D12Device *device;
155 ULONG refcount;
156 D3D12_BOX box;
157 HRESULT hr;
158
159 if (!(device = create_device()))
160 {
161 skip("Failed to create device.\n");
162 return;
163 }
164
165 hr = ID3D12Device_CreateCommandAllocator(device, D3D12_COMMAND_LIST_TYPE_DIRECT,
166 &IID_ID3D12CommandAllocator, (void **)&command_allocator);
167 ok(hr == S_OK, "Failed to create command allocator, hr %#x.\n", hr);
168
169 hr = ID3D12Device_CreateCommandList(device, 0, D3D12_COMMAND_LIST_TYPE_DIRECT,
170 command_allocator, NULL, &IID_ID3D12GraphicsCommandList, (void **)&command_list);
171 ok(hr == S_OK, "Failed to create command list, hr %#x.\n", hr);
172
173 src_buffer = create_upload_buffer(device, 0x40000, NULL);
174 dst_buffer = create_default_buffer(device, 0x40000, 0, D3D12_RESOURCE_STATE_COPY_DEST);
175
176 src_texture = create_default_texture(device, 64, 64,
177 DXGI_FORMAT_BC3_UNORM, 0, D3D12_RESOURCE_STATE_COPY_SOURCE);
178 dst_texture = create_default_texture(device, 64, 64,
179 DXGI_FORMAT_BC3_UNORM, 0, D3D12_RESOURCE_STATE_COPY_DEST);
180
181 dst_location.pResource = dst_texture;
182 dst_location.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
183 dst_location.SubresourceIndex = 0;
184
185 src_location.pResource = src_buffer;
186 src_location.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
187 src_location.PlacedFootprint.Offset = D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT;
188 src_location.PlacedFootprint.Footprint.Format = DXGI_FORMAT_BC3_UNORM;
189 src_location.PlacedFootprint.Footprint.Width = 64;
190 src_location.PlacedFootprint.Footprint.Height = 63; /* height must be multiple of block size */
191 src_location.PlacedFootprint.Footprint.Depth = 1;
192 src_location.PlacedFootprint.Footprint.RowPitch
193 = 64 / format_block_width(DXGI_FORMAT_BC3_UNORM) * format_size(DXGI_FORMAT_BC3_UNORM);
194
195 ID3D12GraphicsCommandList_CopyTextureRegion(command_list,
196 &dst_location, 0, 0, 0, &src_location, NULL);
197
198 hr = ID3D12GraphicsCommandList_Close(command_list);
199 todo ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
200
201 recreate_command_list(device, command_allocator, &command_list);
202
203 src_location.PlacedFootprint.Footprint.Width = 4;
204 src_location.PlacedFootprint.Footprint.Height = 4;
205
206 /* dst y must be multiple of block size */
207 ID3D12GraphicsCommandList_CopyTextureRegion(command_list,
208 &dst_location, 0, 3, 0, &src_location, NULL);
209
210 hr = ID3D12GraphicsCommandList_Close(command_list);
211 todo ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
212
213 recreate_command_list(device, command_allocator, &command_list);
214
215 /* row pitch must be multiple of D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT */
216 src_location.PlacedFootprint.Footprint.RowPitch
217 = 64 / format_block_width(DXGI_FORMAT_BC3_UNORM) * format_size(DXGI_FORMAT_BC3_UNORM) + 1;
218
219 ID3D12GraphicsCommandList_CopyTextureRegion(command_list,
220 &dst_location, 0, 0, 0, &src_location, NULL);
221
222 hr = ID3D12GraphicsCommandList_Close(command_list);
223 todo ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
224
225 recreate_command_list(device, command_allocator, &command_list);
226
227 dst_location.pResource = dst_buffer;
228 dst_location.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
229 dst_location.PlacedFootprint.Offset = D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT;
230 dst_location.PlacedFootprint.Footprint.Format = DXGI_FORMAT_BC3_UNORM;
231 dst_location.PlacedFootprint.Footprint.Width = 64;
232 dst_location.PlacedFootprint.Footprint.Height = 64;
233 dst_location.PlacedFootprint.Footprint.Depth = 1;
234 dst_location.PlacedFootprint.Footprint.RowPitch
235 = 64 / format_block_width(DXGI_FORMAT_BC3_UNORM) * format_size(DXGI_FORMAT_BC3_UNORM);
236
237 src_location.pResource = src_texture;
238 src_location.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
239 src_location.SubresourceIndex = 0;
240
241 /* coordinates must be multiple of block size */
242 set_box(&box, 0, 0, 0, 31, 31, 1);
243 ID3D12GraphicsCommandList_CopyTextureRegion(command_list,
244 &dst_location, 0, 0, 0, &src_location, &box);
245
246 hr = ID3D12GraphicsCommandList_Close(command_list);
247 todo ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
248
249 recreate_command_list(device, command_allocator, &command_list);
250
251 ID3D12Resource_Release(src_texture);
252 src_texture = create_default_texture2d(device, 4, 4, 1, 3, DXGI_FORMAT_BC3_UNORM,
253 D3D12_RESOURCE_FLAG_NONE, D3D12_RESOURCE_STATE_COPY_SOURCE);
254
255 src_location.pResource = src_texture;
256 src_location.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
257 src_location.SubresourceIndex = 1;
258
259 /* coordinates must be multiple of block size even for smallest miplevels */
260 set_box(&box, 0, 0, 0, 2, 2, 1);
261 ID3D12GraphicsCommandList_CopyTextureRegion(command_list,
262 &dst_location, 0, 0, 0, &src_location, &box);
263
264 hr = ID3D12GraphicsCommandList_Close(command_list);
265 todo ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
266
267 recreate_command_list(device, command_allocator, &command_list);
268
269 src_location.SubresourceIndex = 2;
270
271 /* coordinates must be multiple of block size even for smallest miplevels */
272 set_box(&box, 0, 0, 0, 1, 1, 1);
273 ID3D12GraphicsCommandList_CopyTextureRegion(command_list,
274 &dst_location, 0, 0, 0, &src_location, &box);
275
276 hr = ID3D12GraphicsCommandList_Close(command_list);
277 todo ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
278
279 ID3D12CommandAllocator_Release(command_allocator);
280 ID3D12GraphicsCommandList_Release(command_list);
281 ID3D12Resource_Release(dst_buffer);
282 ID3D12Resource_Release(src_buffer);
283 ID3D12Resource_Release(src_texture);
284 ID3D12Resource_Release(dst_texture);
285 refcount = ID3D12Device_Release(device);
286 ok(!refcount, "ID3D12Device has %u references left.\n", (unsigned int)refcount);
287 }
288
test_invalid_unordered_access_views(void)289 static void test_invalid_unordered_access_views(void)
290 {
291 D3D12_UNORDERED_ACCESS_VIEW_DESC uav_desc;
292 D3D12_CPU_DESCRIPTOR_HANDLE cpu_handle;
293 ID3D12DescriptorHeap *heap;
294 ID3D12Resource *buffer;
295 ID3D12Device *device;
296 ULONG refcount;
297
298 if (!(device = create_device()))
299 {
300 skip("Failed to create device.\n");
301 return;
302 }
303
304 heap = create_gpu_descriptor_heap(device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, 16);
305
306 buffer = create_default_buffer(device, 64 * sizeof(float),
307 D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
308
309 cpu_handle = ID3D12DescriptorHeap_GetCPUDescriptorHandleForHeapStart(heap);
310
311 /* Buffer views cannot be created for compressed formats. */
312 uav_desc.Format = DXGI_FORMAT_BC1_UNORM;
313 uav_desc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER;
314 uav_desc.Buffer.FirstElement = 0;
315 uav_desc.Buffer.NumElements = 64;
316 uav_desc.Buffer.StructureByteStride = 0;
317 uav_desc.Buffer.CounterOffsetInBytes = 0;
318 uav_desc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_NONE;
319 ID3D12Device_CreateUnorderedAccessView(device, buffer, NULL, &uav_desc, cpu_handle);
320
321 ID3D12DescriptorHeap_Release(heap);
322 ID3D12Resource_Release(buffer);
323 refcount = ID3D12Device_Release(device);
324 ok(!refcount, "ID3D12Device has %u references left.\n", (unsigned int)refcount);
325 }
326
START_TEST(d3d12_invalid_usage)327 START_TEST(d3d12_invalid_usage)
328 {
329 parse_args(argc, argv);
330 enable_d3d12_debug_layer(argc, argv);
331 init_adapter_info();
332
333 run_test(test_invalid_resource_barriers);
334 run_test(test_invalid_copy_texture_region);
335 run_test(test_invalid_unordered_access_views);
336 }
337