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 #ifndef __VKD3D_D3D12_CROSSTEST_H
20 #define __VKD3D_D3D12_CROSSTEST_H
21
22 /* Hack for MinGW-w64 headers.
23 *
24 * We want to use WIDL C inline wrappers because some methods
25 * in D3D12 interfaces return aggregate objects. Unfortunately,
26 * WIDL C inline wrappers are broken when used with MinGW-w64
27 * headers because FORCEINLINE expands to extern inline
28 * which leads to the "multiple storage classes in declaration
29 * specifiers" compiler error.
30 */
31 #ifdef __MINGW32__
32 # include <_mingw.h>
33 # ifdef __MINGW64_VERSION_MAJOR
34 # undef __forceinline
35 # define __forceinline __inline__ __attribute__((__always_inline__,__gnu_inline__))
36 # endif
37
38 # define _HRESULT_DEFINED
39 typedef int HRESULT;
40 #endif
41
42 #define COBJMACROS
43 #define INITGUID
44 #include "vkd3d_test.h"
45 #include "vkd3d_windows.h"
46 #define WIDL_C_INLINE_WRAPPERS
47 #include "vkd3d_d3d12.h"
48 #include "vkd3d_d3d12sdklayers.h"
49
50 #include <inttypes.h>
51 #include <limits.h>
52 #include <math.h>
53 #include <time.h>
54
55 #ifdef _WIN32
56 # include "vkd3d_dxgi1_4.h"
57 #else
58 # define VKD3D_UTILS_API_VERSION VKD3D_API_VERSION_1_2
59 # include <pthread.h>
60 # include "vkd3d.h"
61 # include "vkd3d_utils.h"
62 #endif
63
64 #include "d3d12_test_utils.h"
65
66 #ifdef _WIN32
create_event(void)67 static inline HANDLE create_event(void)
68 {
69 return CreateEventA(NULL, FALSE, FALSE, NULL);
70 }
71
signal_event(HANDLE event)72 static inline void signal_event(HANDLE event)
73 {
74 SetEvent(event);
75 }
76
wait_event(HANDLE event,unsigned int milliseconds)77 static inline unsigned int wait_event(HANDLE event, unsigned int milliseconds)
78 {
79 return WaitForSingleObject(event, milliseconds);
80 }
81
destroy_event(HANDLE event)82 static inline void destroy_event(HANDLE event)
83 {
84 CloseHandle(event);
85 }
86
87 #define get_d3d12_pfn(name) get_d3d12_pfn_(#name)
get_d3d12_pfn_(const char * name)88 static inline void *get_d3d12_pfn_(const char *name)
89 {
90 return GetProcAddress(GetModuleHandleA("d3d12.dll"), name);
91 }
92 #else
93 #define INFINITE VKD3D_INFINITE
94 #define WAIT_OBJECT_0 VKD3D_WAIT_OBJECT_0
95 #define WAIT_TIMEOUT VKD3D_WAIT_TIMEOUT
96
create_event(void)97 static inline HANDLE create_event(void)
98 {
99 return vkd3d_create_event();
100 }
101
signal_event(HANDLE event)102 static inline void signal_event(HANDLE event)
103 {
104 vkd3d_signal_event(event);
105 }
106
wait_event(HANDLE event,unsigned int milliseconds)107 static inline unsigned int wait_event(HANDLE event, unsigned int milliseconds)
108 {
109 return vkd3d_wait_event(event, milliseconds);
110 }
111
destroy_event(HANDLE event)112 static inline void destroy_event(HANDLE event)
113 {
114 vkd3d_destroy_event(event);
115 }
116
117 #define get_d3d12_pfn(name) (name)
118 #endif
119
120 typedef void (*thread_main_pfn)(void *data);
121
122 struct test_thread_data
123 {
124 thread_main_pfn main_pfn;
125 void *user_data;
126 };
127
128 #ifdef _WIN32
test_thread_main(void * untyped_data)129 static inline DWORD WINAPI test_thread_main(void *untyped_data)
130 {
131 struct test_thread_data *data = untyped_data;
132 data->main_pfn(data->user_data);
133 free(untyped_data);
134 return 0;
135 }
136
create_thread(thread_main_pfn main_pfn,void * user_data)137 static inline HANDLE create_thread(thread_main_pfn main_pfn, void *user_data)
138 {
139 struct test_thread_data *data;
140
141 if (!(data = malloc(sizeof(*data))))
142 return NULL;
143 data->main_pfn = main_pfn;
144 data->user_data = user_data;
145
146 return CreateThread(NULL, 0, test_thread_main, data, 0, NULL);
147 }
148
join_thread(HANDLE thread)149 static inline bool join_thread(HANDLE thread)
150 {
151 unsigned int ret;
152
153 ret = WaitForSingleObject(thread, INFINITE);
154 CloseHandle(thread);
155 return ret == WAIT_OBJECT_0;
156 }
157 #else
test_thread_main(void * untyped_data)158 static void *test_thread_main(void *untyped_data)
159 {
160 struct test_thread_data *data = untyped_data;
161 data->main_pfn(data->user_data);
162 free(untyped_data);
163 return NULL;
164 }
165
create_thread(thread_main_pfn main_pfn,void * user_data)166 static inline HANDLE create_thread(thread_main_pfn main_pfn, void *user_data)
167 {
168 struct test_thread_data *data;
169 pthread_t *thread;
170
171 if (!(thread = malloc(sizeof(*thread))))
172 return NULL;
173
174 if (!(data = malloc(sizeof(*data))))
175 {
176 free(thread);
177 return NULL;
178 }
179 data->main_pfn = main_pfn;
180 data->user_data = user_data;
181
182 if (pthread_create(thread, NULL, test_thread_main, data))
183 {
184 free(data);
185 free(thread);
186 return NULL;
187 }
188
189 return thread;
190 }
191
join_thread(HANDLE untyped_thread)192 static inline bool join_thread(HANDLE untyped_thread)
193 {
194 pthread_t *thread = untyped_thread;
195 int rc;
196
197 rc = pthread_join(*thread, NULL);
198 free(thread);
199 return !rc;
200 }
201 #endif
202
wait_for_fence(ID3D12Fence * fence,uint64_t value)203 static HRESULT wait_for_fence(ID3D12Fence *fence, uint64_t value)
204 {
205 unsigned int ret;
206 HANDLE event;
207 HRESULT hr;
208
209 if (ID3D12Fence_GetCompletedValue(fence) >= value)
210 return S_OK;
211
212 if (!(event = create_event()))
213 return E_FAIL;
214
215 if (FAILED(hr = ID3D12Fence_SetEventOnCompletion(fence, value, event)))
216 {
217 destroy_event(event);
218 return hr;
219 }
220
221 ret = wait_event(event, INFINITE);
222 destroy_event(event);
223 return ret == WAIT_OBJECT_0 ? S_OK : E_FAIL;
224 }
225
wait_queue_idle_(unsigned int line,ID3D12Device * device,ID3D12CommandQueue * queue)226 static void wait_queue_idle_(unsigned int line, ID3D12Device *device, ID3D12CommandQueue *queue)
227 {
228 ID3D12Fence *fence;
229 HRESULT hr;
230
231 hr = ID3D12Device_CreateFence(device, 0, D3D12_FENCE_FLAG_NONE,
232 &IID_ID3D12Fence, (void **)&fence);
233 assert_that_(line)(hr == S_OK, "Failed to create fence, hr %#x.\n", hr);
234
235 hr = ID3D12CommandQueue_Signal(queue, fence, 1);
236 assert_that_(line)(hr == S_OK, "Failed to signal fence, hr %#x.\n", hr);
237 hr = wait_for_fence(fence, 1);
238 assert_that_(line)(hr == S_OK, "Failed to wait for fence, hr %#x.\n", hr);
239
240 ID3D12Fence_Release(fence);
241 }
242
243 static bool use_warp_device;
244 static unsigned int use_adapter_idx;
245
246 #ifdef _WIN32
create_warp_adapter(IDXGIFactory4 * factory)247 static IUnknown *create_warp_adapter(IDXGIFactory4 *factory)
248 {
249 IUnknown *adapter;
250 HRESULT hr;
251
252 adapter = NULL;
253 hr = IDXGIFactory4_EnumWarpAdapter(factory, &IID_IUnknown, (void **)&adapter);
254 if (FAILED(hr))
255 trace("Failed to get WARP adapter, hr %#x.\n", hr);
256 return adapter;
257 }
258
create_adapter(void)259 static IUnknown *create_adapter(void)
260 {
261 IUnknown *adapter = NULL;
262 IDXGIFactory4 *factory;
263 HRESULT hr;
264
265 hr = CreateDXGIFactory1(&IID_IDXGIFactory4, (void **)&factory);
266 ok(hr == S_OK, "Failed to create IDXGIFactory4, hr %#x.\n", hr);
267
268 if (use_warp_device && (adapter = create_warp_adapter(factory)))
269 {
270 IDXGIFactory4_Release(factory);
271 return adapter;
272 }
273
274 hr = IDXGIFactory4_EnumAdapters(factory, use_adapter_idx, (IDXGIAdapter **)&adapter);
275 IDXGIFactory4_Release(factory);
276 if (FAILED(hr))
277 trace("Failed to get adapter, hr %#x.\n", hr);
278 return adapter;
279 }
280
create_device(void)281 static ID3D12Device *create_device(void)
282 {
283 IUnknown *adapter = NULL;
284 ID3D12Device *device;
285 HRESULT hr;
286
287 if ((use_warp_device || use_adapter_idx) && !(adapter = create_adapter()))
288 {
289 trace("Failed to create adapter.\n");
290 return NULL;
291 }
292
293 hr = D3D12CreateDevice(adapter, D3D_FEATURE_LEVEL_11_0, &IID_ID3D12Device, (void **)&device);
294 if (adapter)
295 IUnknown_Release(adapter);
296
297 return SUCCEEDED(hr) ? device : NULL;
298 }
299
init_adapter_info(void)300 static void init_adapter_info(void)
301 {
302 char name[MEMBER_SIZE(DXGI_ADAPTER_DESC, Description)];
303 IDXGIAdapter *dxgi_adapter;
304 DXGI_ADAPTER_DESC desc;
305 IUnknown *adapter;
306 unsigned int i;
307 HRESULT hr;
308
309 if (!(adapter = create_adapter()))
310 return;
311
312 hr = IUnknown_QueryInterface(adapter, &IID_IDXGIAdapter, (void **)&dxgi_adapter);
313 ok(hr == S_OK, "Failed to query IDXGIAdapter, hr %#x.\n", hr);
314 IUnknown_Release(adapter);
315
316 hr = IDXGIAdapter_GetDesc(dxgi_adapter, &desc);
317 ok(hr == S_OK, "Failed to get adapter desc, hr %#x.\n", hr);
318
319 /* FIXME: Use debugstr_w(). */
320 for (i = 0; i < ARRAY_SIZE(desc.Description) && isprint(desc.Description[i]); ++i)
321 name[i] = desc.Description[i];
322 name[min(i, ARRAY_SIZE(name) - 1)] = '\0';
323
324 trace("Adapter: %s, %04x:%04x.\n", name, desc.VendorId, desc.DeviceId);
325
326 if (desc.VendorId == 0x1414 && desc.DeviceId == 0x008c)
327 {
328 trace("Using WARP device.\n");
329 use_warp_device = true;
330 }
331
332 IDXGIAdapter_Release(dxgi_adapter);
333 }
334
get_adapter_desc(ID3D12Device * device,DXGI_ADAPTER_DESC * desc)335 static inline bool get_adapter_desc(ID3D12Device *device, DXGI_ADAPTER_DESC *desc)
336 {
337 IDXGIFactory4 *factory;
338 IDXGIAdapter *adapter;
339 HRESULT hr;
340 LUID luid;
341
342 memset(desc, 0, sizeof(*desc));
343
344 if (!vkd3d_test_platform_is_windows())
345 return false;
346
347 luid = ID3D12Device_GetAdapterLuid(device);
348
349 hr = CreateDXGIFactory1(&IID_IDXGIFactory4, (void **)&factory);
350 ok(hr == S_OK, "Failed to create IDXGIFactory4, hr %#x.\n", hr);
351
352 hr = IDXGIFactory4_EnumAdapterByLuid(factory, luid, &IID_IDXGIAdapter, (void **)&adapter);
353 if (SUCCEEDED(hr))
354 {
355 hr = IDXGIAdapter_GetDesc(adapter, desc);
356 ok(hr == S_OK, "Failed to get adapter desc, hr %#x.\n", hr);
357 IDXGIAdapter_Release(adapter);
358 }
359
360 IDXGIFactory4_Release(factory);
361 return SUCCEEDED(hr);
362 }
363
is_amd_windows_device(ID3D12Device * device)364 static inline bool is_amd_windows_device(ID3D12Device *device)
365 {
366 DXGI_ADAPTER_DESC desc;
367
368 return get_adapter_desc(device, &desc) && desc.VendorId == 0x1002;
369 }
370
is_intel_windows_device(ID3D12Device * device)371 static inline bool is_intel_windows_device(ID3D12Device *device)
372 {
373 DXGI_ADAPTER_DESC desc;
374
375 return get_adapter_desc(device, &desc) && desc.VendorId == 0x8086;
376 }
377
is_mesa_device(ID3D12Device * device)378 static inline bool is_mesa_device(ID3D12Device *device)
379 {
380 return false;
381 }
382
is_mesa_intel_device(ID3D12Device * device)383 static inline bool is_mesa_intel_device(ID3D12Device *device)
384 {
385 return false;
386 }
387
is_nvidia_device(ID3D12Device * device)388 static inline bool is_nvidia_device(ID3D12Device *device)
389 {
390 return false;
391 }
392
is_radv_device(ID3D12Device * device)393 static inline bool is_radv_device(ID3D12Device *device)
394 {
395 return false;
396 }
397
is_depth_clip_enable_supported(ID3D12Device * device)398 static inline bool is_depth_clip_enable_supported(ID3D12Device *device)
399 {
400 return true;
401 }
402
403 #else
404
check_device_extension(VkPhysicalDevice vk_physical_device,const char * name)405 static bool check_device_extension(VkPhysicalDevice vk_physical_device, const char *name)
406 {
407 VkExtensionProperties *properties;
408 bool ret = false;
409 unsigned int i;
410 uint32_t count;
411 VkResult vr;
412
413 vr = vkEnumerateDeviceExtensionProperties(vk_physical_device, NULL, &count, NULL);
414 ok(vr == VK_SUCCESS, "Got unexpected VkResult %d.\n", vr);
415 if (!count)
416 return false;
417
418 properties = calloc(count, sizeof(*properties));
419 ok(properties, "Failed to allocate memory.\n");
420
421 vr = vkEnumerateDeviceExtensionProperties(vk_physical_device, NULL, &count, properties);
422 ok(vr == VK_SUCCESS, "Got unexpected VkResult %d.\n", vr);
423 for (i = 0; i < count; ++i)
424 {
425 if (!strcmp(properties[i].extensionName, name))
426 {
427 ret = true;
428 break;
429 }
430 }
431
432 free(properties);
433 return ret;
434 }
435
create_vkd3d_instance(struct vkd3d_instance ** instance)436 static HRESULT create_vkd3d_instance(struct vkd3d_instance **instance)
437 {
438 struct vkd3d_optional_instance_extensions_info optional_extensions_info;
439 struct vkd3d_instance_create_info instance_create_info;
440
441 static const char * const optional_instance_extensions[] =
442 {
443 VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,
444 };
445
446 memset(&optional_extensions_info, 0, sizeof(optional_extensions_info));
447 optional_extensions_info.type = VKD3D_STRUCTURE_TYPE_OPTIONAL_INSTANCE_EXTENSIONS_INFO;
448 optional_extensions_info.extensions = optional_instance_extensions;
449 optional_extensions_info.extension_count = ARRAY_SIZE(optional_instance_extensions);
450
451 memset(&instance_create_info, 0, sizeof(instance_create_info));
452 instance_create_info.type = VKD3D_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
453 instance_create_info.next = &optional_extensions_info;
454 instance_create_info.pfn_signal_event = vkd3d_signal_event;
455 instance_create_info.wchar_size = sizeof(WCHAR);
456
457 return vkd3d_create_instance(&instance_create_info, instance);
458 }
459
select_physical_device(struct vkd3d_instance * instance)460 static VkPhysicalDevice select_physical_device(struct vkd3d_instance *instance)
461 {
462 VkPhysicalDevice *vk_physical_devices;
463 VkPhysicalDevice vk_physical_device;
464 VkInstance vk_instance;
465 uint32_t count;
466 VkResult vr;
467
468 vk_instance = vkd3d_instance_get_vk_instance(instance);
469
470 vr = vkEnumeratePhysicalDevices(vk_instance, &count, NULL);
471 ok(vr == VK_SUCCESS, "Got unexpected VkResult %d.\n", vr);
472
473 if (use_adapter_idx >= count)
474 {
475 trace("Invalid physical device index %u.\n", use_adapter_idx);
476 return VK_NULL_HANDLE;
477 }
478
479 vk_physical_devices = calloc(count, sizeof(*vk_physical_devices));
480 ok(vk_physical_devices, "Failed to allocate memory.\n");
481 vr = vkEnumeratePhysicalDevices(vk_instance, &count, vk_physical_devices);
482 ok(vr == VK_SUCCESS, "Got unexpected VkResult %d.\n", vr);
483
484 vk_physical_device = vk_physical_devices[use_adapter_idx];
485
486 free(vk_physical_devices);
487
488 return vk_physical_device;
489 }
490
create_vkd3d_device(struct vkd3d_instance * instance,D3D_FEATURE_LEVEL minimum_feature_level,REFIID iid,void ** device)491 static HRESULT create_vkd3d_device(struct vkd3d_instance *instance,
492 D3D_FEATURE_LEVEL minimum_feature_level, REFIID iid, void **device)
493 {
494 static const char * const device_extensions[] =
495 {
496 VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME,
497 };
498 static const struct vkd3d_optional_device_extensions_info optional_extensions =
499 {
500 .type = VKD3D_STRUCTURE_TYPE_OPTIONAL_DEVICE_EXTENSIONS_INFO,
501 .extensions = device_extensions,
502 .extension_count = ARRAY_SIZE(device_extensions),
503 };
504
505 struct vkd3d_device_create_info device_create_info;
506 VkPhysicalDevice vk_physical_device;
507
508 if (!(vk_physical_device = select_physical_device(instance)))
509 return E_INVALIDARG;
510
511 memset(&device_create_info, 0, sizeof(device_create_info));
512 device_create_info.type = VKD3D_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
513 device_create_info.next = &optional_extensions;
514 device_create_info.minimum_feature_level = minimum_feature_level;
515 device_create_info.instance = instance;
516 device_create_info.vk_physical_device = vk_physical_device;
517
518 return vkd3d_create_device(&device_create_info, iid, device);
519 }
520
create_device(void)521 static ID3D12Device *create_device(void)
522 {
523 struct vkd3d_instance *instance;
524 ID3D12Device *device;
525 HRESULT hr;
526
527 if (SUCCEEDED(hr = create_vkd3d_instance(&instance)))
528 {
529 hr = create_vkd3d_device(instance, D3D_FEATURE_LEVEL_11_0, &IID_ID3D12Device, (void **)&device);
530 vkd3d_instance_decref(instance);
531 }
532
533 return SUCCEEDED(hr) ? device : NULL;
534 }
535
get_driver_properties(ID3D12Device * device,VkPhysicalDeviceDriverPropertiesKHR * driver_properties)536 static bool get_driver_properties(ID3D12Device *device, VkPhysicalDeviceDriverPropertiesKHR *driver_properties)
537 {
538 PFN_vkGetPhysicalDeviceProperties2KHR pfn_vkGetPhysicalDeviceProperties2KHR;
539 VkPhysicalDeviceProperties2 device_properties2;
540 VkPhysicalDevice vk_physical_device;
541
542 memset(driver_properties, 0, sizeof(*driver_properties));
543 driver_properties->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR;
544
545 vk_physical_device = vkd3d_get_vk_physical_device(device);
546
547 if (check_device_extension(vk_physical_device, VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME))
548 {
549 struct vkd3d_instance *instance = vkd3d_instance_from_device(device);
550 VkInstance vk_instance = vkd3d_instance_get_vk_instance(instance);
551
552 pfn_vkGetPhysicalDeviceProperties2KHR
553 = (void *)vkGetInstanceProcAddr(vk_instance, "vkGetPhysicalDeviceProperties2KHR");
554 ok(pfn_vkGetPhysicalDeviceProperties2KHR, "vkGetPhysicalDeviceProperties2KHR is NULL.\n");
555
556 memset(&device_properties2, 0, sizeof(device_properties2));
557 device_properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
558 device_properties2.pNext = driver_properties;
559 pfn_vkGetPhysicalDeviceProperties2KHR(vk_physical_device, &device_properties2);
560 return true;
561 }
562
563 return false;
564 }
565
init_adapter_info(void)566 static void init_adapter_info(void)
567 {
568 VkPhysicalDeviceDriverPropertiesKHR driver_properties;
569 struct vkd3d_instance *instance;
570 ID3D12Device *device;
571 HRESULT hr;
572
573 if (FAILED(hr = create_vkd3d_instance(&instance)))
574 return;
575
576 if (SUCCEEDED(hr = create_vkd3d_device(instance, D3D_FEATURE_LEVEL_11_0, &IID_ID3D12Device, (void **)&device)))
577 {
578 if (get_driver_properties(device, &driver_properties))
579 trace("Driver name: %s, driver info: %s.\n", driver_properties.driverName, driver_properties.driverInfo);
580
581 ID3D12Device_Release(device);
582 }
583
584 vkd3d_instance_decref(instance);
585 }
586
is_amd_windows_device(ID3D12Device * device)587 static inline bool is_amd_windows_device(ID3D12Device *device)
588 {
589 return false;
590 }
591
is_intel_windows_device(ID3D12Device * device)592 static inline bool is_intel_windows_device(ID3D12Device *device)
593 {
594 return false;
595 }
596
is_mesa_device(ID3D12Device * device)597 static inline bool is_mesa_device(ID3D12Device *device)
598 {
599 VkPhysicalDeviceDriverPropertiesKHR properties;
600
601 get_driver_properties(device, &properties);
602 return properties.driverID == VK_DRIVER_ID_MESA_RADV_KHR
603 || properties.driverID == VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA_KHR;
604 }
605
is_mesa_intel_device(ID3D12Device * device)606 static inline bool is_mesa_intel_device(ID3D12Device *device)
607 {
608 VkPhysicalDeviceDriverPropertiesKHR properties;
609
610 get_driver_properties(device, &properties);
611 return properties.driverID == VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA_KHR;
612 }
613
is_nvidia_device(ID3D12Device * device)614 static inline bool is_nvidia_device(ID3D12Device *device)
615 {
616 VkPhysicalDeviceDriverPropertiesKHR properties;
617
618 get_driver_properties(device, &properties);
619 return properties.driverID == VK_DRIVER_ID_NVIDIA_PROPRIETARY_KHR;
620 }
621
is_radv_device(ID3D12Device * device)622 static inline bool is_radv_device(ID3D12Device *device)
623 {
624 VkPhysicalDeviceDriverPropertiesKHR properties;
625
626 get_driver_properties(device, &properties);
627 return properties.driverID == VK_DRIVER_ID_MESA_RADV_KHR;
628 }
629
is_depth_clip_enable_supported(ID3D12Device * device)630 static inline bool is_depth_clip_enable_supported(ID3D12Device *device)
631 {
632 VkPhysicalDevice vk_physical_device = vkd3d_get_vk_physical_device(device);
633 return check_device_extension(vk_physical_device, VK_EXT_DEPTH_CLIP_ENABLE_EXTENSION_NAME);
634 }
635 #endif
636
parse_args(int argc,char ** argv)637 static void parse_args(int argc, char **argv)
638 {
639 unsigned int i;
640
641 for (i = 1; i < argc; ++i)
642 {
643 if (!strcmp(argv[i], "--warp"))
644 use_warp_device = true;
645 else if (!strcmp(argv[i], "--adapter") && i + 1 < argc)
646 use_adapter_idx = atoi(argv[++i]);
647 }
648 }
649
enable_d3d12_debug_layer(int argc,char ** argv)650 static void enable_d3d12_debug_layer(int argc, char **argv)
651 {
652 bool enable_debug_layer = false, enable_gpu_based_validation = false;
653 ID3D12Debug1 *debug1;
654 ID3D12Debug *debug;
655 unsigned int i;
656
657 for (i = 1; i < argc; ++i)
658 {
659 if (!strcmp(argv[i], "--validate"))
660 enable_debug_layer = true;
661 else if (!strcmp(argv[i], "--gbv"))
662 enable_gpu_based_validation = true;
663 }
664
665 if (enable_gpu_based_validation)
666 {
667 if (SUCCEEDED(D3D12GetDebugInterface(&IID_ID3D12Debug1, (void **)&debug1)))
668 {
669 ID3D12Debug1_SetEnableGPUBasedValidation(debug1, true);
670 ID3D12Debug1_Release(debug1);
671 enable_debug_layer = true;
672 }
673 else
674 {
675 trace("Failed to enable GPU-based validation.\n");
676 }
677 }
678
679 if (enable_debug_layer && SUCCEEDED(D3D12GetDebugInterface(&IID_ID3D12Debug, (void **)&debug)))
680 {
681 ID3D12Debug_EnableDebugLayer(debug);
682 ID3D12Debug_Release(debug);
683 }
684 }
685
686 #endif /* __VKD3D_D3D12_CROSSTEST_H */
687