xref: /aosp_15_r20/external/mesa3d/src/microsoft/vulkan/dzn_util.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © Microsoft Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  */
23 
24 #include "dzn_private.h"
25 
26 #define D3D12_IGNORE_SDK_LAYERS
27 #define COBJMACROS
28 #include <directx/d3d12.h>
29 
30 #include <vulkan/vulkan.h>
31 
32 #include "util/format/u_format.h"
33 #include "util/log.h"
34 
35 #include <directx/d3d12sdklayers.h>
36 #include <util/u_dl.h>
37 
38 static const DXGI_FORMAT formats[PIPE_FORMAT_COUNT] = {
39 #define MAP_FORMAT_NORM(FMT) \
40    [PIPE_FORMAT_ ## FMT ## _UNORM] = DXGI_FORMAT_ ## FMT ## _UNORM, \
41    [PIPE_FORMAT_ ## FMT ## _SNORM] = DXGI_FORMAT_ ## FMT ## _SNORM,
42 
43 #define MAP_FORMAT_INT(FMT) \
44    [PIPE_FORMAT_ ## FMT ## _UINT] = DXGI_FORMAT_ ## FMT ## _UINT, \
45    [PIPE_FORMAT_ ## FMT ## _SINT] = DXGI_FORMAT_ ## FMT ## _SINT,
46 
47 #define MAP_FORMAT_SRGB(FMT) \
48    [PIPE_FORMAT_ ## FMT ## _SRGB] = DXGI_FORMAT_ ## FMT ## _UNORM_SRGB,
49 
50 #define MAP_FORMAT_FLOAT(FMT) \
51    [PIPE_FORMAT_ ## FMT ## _FLOAT] = DXGI_FORMAT_ ## FMT ## _FLOAT,
52 
53 #define MAP_EMU_FORMAT_NO_ALPHA(BITS, TYPE) \
54    [PIPE_FORMAT_L ## BITS ## _ ## TYPE] = DXGI_FORMAT_R ## BITS ## _ ## TYPE, \
55    [PIPE_FORMAT_I ## BITS ## _ ## TYPE] = DXGI_FORMAT_R ## BITS ## _ ## TYPE, \
56    [PIPE_FORMAT_L ## BITS ## A ## BITS ## _ ## TYPE] = \
57           DXGI_FORMAT_R ## BITS ## G ## BITS ## _ ## TYPE,
58 
59 #define MAP_EMU_FORMAT(BITS, TYPE) \
60    [PIPE_FORMAT_A ## BITS ## _ ## TYPE] = DXGI_FORMAT_R ## BITS ## _ ## TYPE, \
61    MAP_EMU_FORMAT_NO_ALPHA(BITS, TYPE)
62 
63    MAP_FORMAT_NORM(R8)
64    MAP_FORMAT_INT(R8)
65 
66    MAP_FORMAT_NORM(R8G8)
67    MAP_FORMAT_INT(R8G8)
68 
69    MAP_FORMAT_NORM(R8G8B8A8)
70    MAP_FORMAT_INT(R8G8B8A8)
71    MAP_FORMAT_SRGB(R8G8B8A8)
72 
73    [PIPE_FORMAT_B8G8R8X8_UNORM] = DXGI_FORMAT_B8G8R8X8_UNORM,
74    [PIPE_FORMAT_B8G8R8A8_UNORM] = DXGI_FORMAT_B8G8R8A8_UNORM,
75    [PIPE_FORMAT_B4G4R4A4_UNORM] = DXGI_FORMAT_B4G4R4A4_UNORM,
76    [PIPE_FORMAT_A4R4G4B4_UNORM] = DXGI_FORMAT_A4B4G4R4_UNORM,
77    [PIPE_FORMAT_A4B4G4R4_UNORM] = DXGI_FORMAT_A4B4G4R4_UNORM,
78    [PIPE_FORMAT_B5G6R5_UNORM] = DXGI_FORMAT_B5G6R5_UNORM,
79    [PIPE_FORMAT_B5G5R5A1_UNORM] = DXGI_FORMAT_B5G5R5A1_UNORM,
80 
81    MAP_FORMAT_SRGB(B8G8R8A8)
82 
83    MAP_FORMAT_INT(R32)
84    MAP_FORMAT_FLOAT(R32)
85    MAP_FORMAT_INT(R32G32)
86    MAP_FORMAT_FLOAT(R32G32)
87    MAP_FORMAT_INT(R32G32B32)
88    MAP_FORMAT_FLOAT(R32G32B32)
89    MAP_FORMAT_INT(R32G32B32A32)
90    MAP_FORMAT_FLOAT(R32G32B32A32)
91 
92    MAP_FORMAT_NORM(R16)
93    MAP_FORMAT_INT(R16)
94    MAP_FORMAT_FLOAT(R16)
95 
96    MAP_FORMAT_NORM(R16G16)
97    MAP_FORMAT_INT(R16G16)
98    MAP_FORMAT_FLOAT(R16G16)
99 
100    MAP_FORMAT_NORM(R16G16B16A16)
101    MAP_FORMAT_INT(R16G16B16A16)
102    MAP_FORMAT_FLOAT(R16G16B16A16)
103 
104    [PIPE_FORMAT_A8_UNORM] = DXGI_FORMAT_A8_UNORM,
105    MAP_EMU_FORMAT_NO_ALPHA(8, UNORM)
106    MAP_EMU_FORMAT(8, SNORM)
107    MAP_EMU_FORMAT(8, SINT)
108    MAP_EMU_FORMAT(8, UINT)
109    MAP_EMU_FORMAT(16, UNORM)
110    MAP_EMU_FORMAT(16, SNORM)
111    MAP_EMU_FORMAT(16, SINT)
112    MAP_EMU_FORMAT(16, UINT)
113    MAP_EMU_FORMAT(16, FLOAT)
114    MAP_EMU_FORMAT(32, SINT)
115    MAP_EMU_FORMAT(32, UINT)
116    MAP_EMU_FORMAT(32, FLOAT)
117 
118    [PIPE_FORMAT_R9G9B9E5_FLOAT] = DXGI_FORMAT_R9G9B9E5_SHAREDEXP,
119    [PIPE_FORMAT_R11G11B10_FLOAT] = DXGI_FORMAT_R11G11B10_FLOAT,
120    [PIPE_FORMAT_R10G10B10A2_UINT] = DXGI_FORMAT_R10G10B10A2_UINT,
121    [PIPE_FORMAT_R10G10B10A2_UNORM] = DXGI_FORMAT_R10G10B10A2_UNORM,
122 
123    [PIPE_FORMAT_DXT1_RGB] = DXGI_FORMAT_BC1_UNORM,
124    [PIPE_FORMAT_DXT1_RGBA] = DXGI_FORMAT_BC1_UNORM,
125    [PIPE_FORMAT_DXT3_RGBA] = DXGI_FORMAT_BC2_UNORM,
126    [PIPE_FORMAT_DXT5_RGBA] = DXGI_FORMAT_BC3_UNORM,
127 
128    [PIPE_FORMAT_DXT1_SRGB] = DXGI_FORMAT_BC1_UNORM_SRGB,
129    [PIPE_FORMAT_DXT1_SRGBA] = DXGI_FORMAT_BC1_UNORM_SRGB,
130    [PIPE_FORMAT_DXT3_SRGBA] = DXGI_FORMAT_BC2_UNORM_SRGB,
131    [PIPE_FORMAT_DXT5_SRGBA] = DXGI_FORMAT_BC3_UNORM_SRGB,
132 
133    [PIPE_FORMAT_RGTC1_UNORM] = DXGI_FORMAT_BC4_UNORM,
134    [PIPE_FORMAT_RGTC1_SNORM] = DXGI_FORMAT_BC4_SNORM,
135    [PIPE_FORMAT_RGTC2_UNORM] = DXGI_FORMAT_BC5_UNORM,
136    [PIPE_FORMAT_RGTC2_SNORM] = DXGI_FORMAT_BC5_SNORM,
137 
138    [PIPE_FORMAT_BPTC_RGB_UFLOAT] = DXGI_FORMAT_BC6H_UF16,
139    [PIPE_FORMAT_BPTC_RGB_FLOAT] = DXGI_FORMAT_BC6H_SF16,
140    [PIPE_FORMAT_BPTC_RGBA_UNORM] = DXGI_FORMAT_BC7_UNORM,
141    [PIPE_FORMAT_BPTC_SRGBA] = DXGI_FORMAT_BC7_UNORM_SRGB,
142 
143    [PIPE_FORMAT_Z32_FLOAT] = DXGI_FORMAT_R32_TYPELESS,
144    [PIPE_FORMAT_Z16_UNORM] = DXGI_FORMAT_R16_TYPELESS,
145    [PIPE_FORMAT_Z24X8_UNORM] = DXGI_FORMAT_R24G8_TYPELESS,
146    [PIPE_FORMAT_X24S8_UINT] = DXGI_FORMAT_R24G8_TYPELESS,
147 
148    [PIPE_FORMAT_Z24_UNORM_S8_UINT] = DXGI_FORMAT_R24G8_TYPELESS,
149    [PIPE_FORMAT_Z32_FLOAT_S8X24_UINT] = DXGI_FORMAT_R32G8X24_TYPELESS,
150    [PIPE_FORMAT_X32_S8X24_UINT] = DXGI_FORMAT_R32G8X24_TYPELESS,
151 };
152 
153 DXGI_FORMAT
dzn_pipe_to_dxgi_format(enum pipe_format in)154 dzn_pipe_to_dxgi_format(enum pipe_format in)
155 {
156    return formats[in];
157 }
158 
159 DXGI_FORMAT
dzn_get_typeless_dxgi_format(DXGI_FORMAT in)160 dzn_get_typeless_dxgi_format(DXGI_FORMAT in)
161 {
162    if (in >= DXGI_FORMAT_R32G32B32A32_TYPELESS && in <= DXGI_FORMAT_R32G32B32A32_SINT)
163       return DXGI_FORMAT_R32G32B32A32_TYPELESS;
164    if (in >= DXGI_FORMAT_R32G32B32_TYPELESS && in <= DXGI_FORMAT_R32G32B32_SINT)
165       return DXGI_FORMAT_R32G32B32_TYPELESS;
166    if (in >= DXGI_FORMAT_R16G16B16A16_TYPELESS && in <= DXGI_FORMAT_R16G16B16A16_SINT)
167       return DXGI_FORMAT_R16G16B16A16_TYPELESS;
168    if (in >= DXGI_FORMAT_R32G32_TYPELESS && in <= DXGI_FORMAT_R32G32_SINT)
169       return DXGI_FORMAT_R32G32_TYPELESS;
170    if (in >= DXGI_FORMAT_R32G8X24_TYPELESS && in <= DXGI_FORMAT_X32_TYPELESS_G8X24_UINT)
171       return DXGI_FORMAT_R32G8X24_TYPELESS;
172    if (in >= DXGI_FORMAT_R10G10B10A2_TYPELESS && in <= DXGI_FORMAT_R10G10B10A2_UINT)
173       return DXGI_FORMAT_R10G10B10A2_TYPELESS;
174    if (in >= DXGI_FORMAT_R8G8B8A8_TYPELESS && in <= DXGI_FORMAT_R8G8B8A8_SINT)
175       return DXGI_FORMAT_R8G8B8A8_TYPELESS;
176    if (in >= DXGI_FORMAT_R16G16_TYPELESS && in <= DXGI_FORMAT_R16G16_SINT)
177       return DXGI_FORMAT_R16G16_TYPELESS;
178    if (in >= DXGI_FORMAT_R32_TYPELESS && in <= DXGI_FORMAT_R32_SINT)
179       return DXGI_FORMAT_R32_TYPELESS;
180    if (in >= DXGI_FORMAT_R24G8_TYPELESS && in <= DXGI_FORMAT_X24_TYPELESS_G8_UINT)
181       return DXGI_FORMAT_R24G8_TYPELESS;
182    if (in >= DXGI_FORMAT_R8G8_TYPELESS && in <= DXGI_FORMAT_R8G8_SINT)
183       return DXGI_FORMAT_R8G8_TYPELESS;
184    if (in >= DXGI_FORMAT_R16_TYPELESS && in <= DXGI_FORMAT_R16_SINT)
185       return DXGI_FORMAT_R16_TYPELESS;
186    if (in >= DXGI_FORMAT_R8_TYPELESS && in <= DXGI_FORMAT_R8_SINT)
187       return DXGI_FORMAT_R8_TYPELESS;
188    if (in >= DXGI_FORMAT_BC1_TYPELESS && in <= DXGI_FORMAT_BC1_UNORM_SRGB)
189       return DXGI_FORMAT_BC1_TYPELESS;
190    if (in >= DXGI_FORMAT_BC2_TYPELESS && in <= DXGI_FORMAT_BC2_UNORM_SRGB)
191       return DXGI_FORMAT_BC2_TYPELESS;
192    if (in >= DXGI_FORMAT_BC3_TYPELESS && in <= DXGI_FORMAT_BC3_UNORM_SRGB)
193       return DXGI_FORMAT_BC3_TYPELESS;
194    if (in >= DXGI_FORMAT_BC4_TYPELESS && in <= DXGI_FORMAT_BC4_SNORM)
195       return DXGI_FORMAT_BC4_TYPELESS;
196    if (in >= DXGI_FORMAT_BC5_TYPELESS && in <= DXGI_FORMAT_BC5_SNORM)
197       return DXGI_FORMAT_BC5_TYPELESS;
198    if (in == DXGI_FORMAT_B8G8R8A8_UNORM ||
199        (in >= DXGI_FORMAT_B8G8R8A8_TYPELESS && in <= DXGI_FORMAT_B8G8R8A8_UNORM_SRGB))
200       return DXGI_FORMAT_B8G8R8A8_TYPELESS;
201    if (in == DXGI_FORMAT_B8G8R8X8_UNORM ||
202        (in >= DXGI_FORMAT_B8G8R8X8_TYPELESS && in <= DXGI_FORMAT_B8G8R8X8_UNORM_SRGB))
203       return DXGI_FORMAT_B8G8R8X8_TYPELESS;
204    if (in >= DXGI_FORMAT_BC6H_TYPELESS && in <= DXGI_FORMAT_BC6H_SF16)
205       return DXGI_FORMAT_BC6H_TYPELESS;
206    if (in >= DXGI_FORMAT_BC7_TYPELESS && in <= DXGI_FORMAT_BC7_UNORM_SRGB)
207       return DXGI_FORMAT_BC7_TYPELESS;
208 
209    return in;
210 }
211 
212 static D3D12_FILTER_TYPE
translate_filter_type(VkFilter type)213 translate_filter_type(VkFilter type)
214 {
215    switch (type) {
216    case VK_FILTER_NEAREST: return D3D12_FILTER_TYPE_POINT;
217    case VK_FILTER_LINEAR: return D3D12_FILTER_TYPE_LINEAR;
218    default:
219       assert(!"Unsupported filter mode");
220       return D3D12_FILTER_TYPE_POINT;
221    }
222 }
223 
224 static D3D12_FILTER_TYPE
translate_mip_filter_type(VkSamplerMipmapMode type)225 translate_mip_filter_type(VkSamplerMipmapMode type)
226 {
227    switch (type) {
228    case VK_SAMPLER_MIPMAP_MODE_NEAREST: return D3D12_FILTER_TYPE_POINT;
229    case VK_SAMPLER_MIPMAP_MODE_LINEAR: return D3D12_FILTER_TYPE_LINEAR;
230    default:
231       assert(!"Unsupported filter mode");
232       return D3D12_FILTER_TYPE_POINT;
233    }
234 }
235 
236 D3D12_FILTER
dzn_translate_sampler_filter(const struct dzn_physical_device * pdev,const VkSamplerCreateInfo * create_info)237 dzn_translate_sampler_filter(const struct dzn_physical_device *pdev,
238                              const VkSamplerCreateInfo *create_info)
239 {
240    D3D12_FILTER_REDUCTION_TYPE reduction = create_info->compareEnable ?
241       D3D12_FILTER_REDUCTION_TYPE_COMPARISON : D3D12_FILTER_REDUCTION_TYPE_STANDARD;
242 
243    if (create_info->anisotropyEnable) {
244       if (create_info->mipmapMode == VK_SAMPLER_MIPMAP_MODE_NEAREST &&
245           pdev->options19.AnisoFilterWithPointMipSupported)
246          return D3D12_ENCODE_MIN_MAG_ANISOTROPIC_MIP_POINT_FILTER(reduction);
247       return D3D12_ENCODE_ANISOTROPIC_FILTER(reduction);
248    }
249 
250    return D3D12_ENCODE_BASIC_FILTER(
251       translate_filter_type(create_info->minFilter),
252       translate_filter_type(create_info->magFilter),
253       translate_mip_filter_type(create_info->mipmapMode),
254       reduction);
255 }
256 
257 D3D12_COMPARISON_FUNC
dzn_translate_compare_op(VkCompareOp in)258 dzn_translate_compare_op(VkCompareOp in)
259 {
260    switch (in) {
261    case VK_COMPARE_OP_NEVER: return D3D12_COMPARISON_FUNC_NEVER;
262    case VK_COMPARE_OP_LESS: return D3D12_COMPARISON_FUNC_LESS;
263    case VK_COMPARE_OP_EQUAL: return D3D12_COMPARISON_FUNC_EQUAL;
264    case VK_COMPARE_OP_LESS_OR_EQUAL: return D3D12_COMPARISON_FUNC_LESS_EQUAL;
265    case VK_COMPARE_OP_GREATER: return D3D12_COMPARISON_FUNC_GREATER;
266    case VK_COMPARE_OP_NOT_EQUAL: return D3D12_COMPARISON_FUNC_NOT_EQUAL;
267    case VK_COMPARE_OP_GREATER_OR_EQUAL: return D3D12_COMPARISON_FUNC_GREATER_EQUAL;
268    case VK_COMPARE_OP_ALWAYS: return D3D12_COMPARISON_FUNC_ALWAYS;
269    default: unreachable("Invalid compare op");
270    }
271 }
272 
273 void
dzn_translate_viewport(D3D12_VIEWPORT * out,const VkViewport * in)274 dzn_translate_viewport(D3D12_VIEWPORT *out,
275                        const VkViewport *in)
276 {
277    out->TopLeftX = in->x;
278    out->TopLeftY = in->height < 0 ? in->height + in->y : in->y;
279    out->Width = in->width;
280    out->Height = fabs(in->height);
281    out->MinDepth = MIN2(in->minDepth, in->maxDepth);
282    out->MaxDepth = MAX2(in->maxDepth, in->minDepth);
283 }
284 
285 void
dzn_translate_rect(D3D12_RECT * out,const VkRect2D * in)286 dzn_translate_rect(D3D12_RECT *out,
287                    const VkRect2D *in)
288 {
289    out->left = in->offset.x;
290    out->top = in->offset.y;
291    out->right = in->offset.x + in->extent.width;
292    out->bottom = in->offset.y + in->extent.height;
293 }
294 
295 static ID3D12Debug *
get_debug_interface(struct util_dl_library * d3d12_mod,ID3D12DeviceFactory * factory)296 get_debug_interface(struct util_dl_library *d3d12_mod, ID3D12DeviceFactory *factory)
297 {
298    typedef HRESULT(WINAPI *PFN_D3D12_GET_DEBUG_INTERFACE)(REFIID riid, void **ppFactory);
299    PFN_D3D12_GET_DEBUG_INTERFACE D3D12GetDebugInterface;
300 
301    ID3D12Debug *debug;
302    if (factory) {
303       if (FAILED(ID3D12DeviceFactory_GetConfigurationInterface(factory, &CLSID_D3D12Debug, &IID_ID3D12Debug, (void **)&debug))) {
304          mesa_loge("Failed to retrieve ID3D12Debug from device factory\n");
305          return NULL;
306       }
307    } else {
308       D3D12GetDebugInterface = (PFN_D3D12_GET_DEBUG_INTERFACE)util_dl_get_proc_address(d3d12_mod, "D3D12GetDebugInterface");
309       if (!D3D12GetDebugInterface) {
310          mesa_loge("failed to load D3D12GetDebugInterface from D3D12.DLL\n");
311          return NULL;
312       }
313 
314       if (FAILED(D3D12GetDebugInterface(&IID_ID3D12Debug, (void **)&debug))) {
315          mesa_loge("D3D12GetDebugInterface failed\n");
316          return NULL;
317       }
318    }
319 
320    return debug;
321 }
322 
323 void
d3d12_enable_debug_layer(struct util_dl_library * d3d12_mod,ID3D12DeviceFactory * factory)324 d3d12_enable_debug_layer(struct util_dl_library *d3d12_mod, ID3D12DeviceFactory *factory)
325 {
326    ID3D12Debug *debug = get_debug_interface(d3d12_mod, factory);
327    if (debug) {
328       ID3D12Debug_EnableDebugLayer(debug);
329       ID3D12Debug_Release(debug);
330    }
331 }
332 
333 void
d3d12_enable_gpu_validation(struct util_dl_library * d3d12_mod,ID3D12DeviceFactory * factory)334 d3d12_enable_gpu_validation(struct util_dl_library *d3d12_mod, ID3D12DeviceFactory *factory)
335 {
336    ID3D12Debug *debug = get_debug_interface(d3d12_mod, factory);
337    if (debug) {
338       ID3D12Debug3 *debug3;
339       if (SUCCEEDED(ID3D12Debug_QueryInterface(debug,
340                                                &IID_ID3D12Debug3,
341                                                (void **)&debug3))) {
342          ID3D12Debug3_SetEnableGPUBasedValidation(debug3, true);
343          ID3D12Debug3_Release(debug3);
344       }
345       ID3D12Debug_Release(debug);
346    }
347 }
348 
349 ID3D12Device4 *
d3d12_create_device(struct util_dl_library * d3d12_mod,IUnknown * adapter,ID3D12DeviceFactory * factory,bool experimental_features)350 d3d12_create_device(struct util_dl_library *d3d12_mod, IUnknown *adapter, ID3D12DeviceFactory *factory, bool experimental_features)
351 {
352 #ifdef _WIN32
353    if (experimental_features)
354 #endif
355    {
356       if (factory) {
357          if (FAILED(ID3D12DeviceFactory_EnableExperimentalFeatures(factory, 1, &D3D12ExperimentalShaderModels, NULL, NULL))) {
358             mesa_loge("failed to enable experimental shader models\n");
359             return NULL;
360          }
361       } else {
362          typedef HRESULT(WINAPI *PFN_D3D12ENABLEEXPERIMENTALFEATURES)(UINT, const IID *, void *, UINT *);
363          PFN_D3D12ENABLEEXPERIMENTALFEATURES D3D12EnableExperimentalFeatures =
364             (PFN_D3D12ENABLEEXPERIMENTALFEATURES)util_dl_get_proc_address(d3d12_mod, "D3D12EnableExperimentalFeatures");
365          if (FAILED(D3D12EnableExperimentalFeatures(1, &D3D12ExperimentalShaderModels, NULL, NULL))) {
366             mesa_loge("failed to enable experimental shader models\n");
367             return NULL;
368          }
369       }
370    }
371 
372    ID3D12Device4 *dev;
373    if (factory) {
374       ID3D12DeviceFactory_SetFlags(factory, D3D12_DEVICE_FACTORY_FLAG_ALLOW_RETURNING_EXISTING_DEVICE |
375                                             D3D12_DEVICE_FACTORY_FLAG_ALLOW_RETURNING_INCOMPATIBLE_EXISTING_DEVICE);
376       if (FAILED(ID3D12DeviceFactory_CreateDevice(factory, adapter, D3D_FEATURE_LEVEL_11_0,
377                                                   &IID_ID3D12Device4,
378                                                   (void **)&dev))) {
379          mesa_loge("ID3D12DeviceFactory::CreateDevice failed\n");
380          return NULL;
381       }
382    } else {
383       typedef HRESULT(WINAPI *PFN_D3D12CREATEDEVICE)(IUnknown *, D3D_FEATURE_LEVEL, REFIID, void **);
384       PFN_D3D12CREATEDEVICE D3D12CreateDevice;
385 
386       D3D12CreateDevice = (PFN_D3D12CREATEDEVICE)util_dl_get_proc_address(d3d12_mod, "D3D12CreateDevice");
387       if (!D3D12CreateDevice) {
388          mesa_loge("failed to load D3D12CreateDevice from D3D12\n");
389          return NULL;
390       }
391 
392       if (FAILED(D3D12CreateDevice(adapter, D3D_FEATURE_LEVEL_11_0,
393                                    &IID_ID3D12Device4,
394                                    (void **)&dev))) {
395          mesa_loge("D3D12CreateDevice failed\n");
396          return NULL;
397       }
398    }
399    return dev;
400 }
401 
402 PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE
d3d12_get_serialize_root_sig(struct util_dl_library * d3d12_mod)403 d3d12_get_serialize_root_sig(struct util_dl_library *d3d12_mod)
404 {
405    return (PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE)
406       util_dl_get_proc_address(d3d12_mod, "D3D12SerializeVersionedRootSignature");
407 }
408