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