xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/d3d12/d3d12_screen.cpp (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 "d3d12_screen.h"
25 
26 #include "d3d12_bufmgr.h"
27 #include "d3d12_compiler.h"
28 #include "d3d12_context.h"
29 #include "d3d12_debug.h"
30 #include "d3d12_fence.h"
31 #ifdef HAVE_GALLIUM_D3D12_VIDEO
32 #include "d3d12_video_screen.h"
33 #endif
34 #include "d3d12_format.h"
35 #include "d3d12_interop_public.h"
36 #include "d3d12_residency.h"
37 #include "d3d12_resource.h"
38 #include "d3d12_nir_passes.h"
39 
40 #include "pipebuffer/pb_bufmgr.h"
41 #include "util/u_debug.h"
42 #include "util/u_math.h"
43 #include "util/u_memory.h"
44 #include "util/u_screen.h"
45 #include "util/u_dl.h"
46 #include "util/mesa-sha1.h"
47 
48 #include "nir.h"
49 #include "frontend/sw_winsys.h"
50 
51 #include "nir_to_dxil.h"
52 #include "git_sha1.h"
53 
54 #ifndef _GAMING_XBOX
55 #include <directx/d3d12sdklayers.h>
56 #endif
57 
58 #if defined(_WIN32) && defined(_WIN64) && !defined(_GAMING_XBOX)
59 #include <filesystem>
60 #include <shlobj.h>
61 #endif
62 
63 #include <dxguids/dxguids.h>
64 static GUID OpenGLOn12CreatorID = { 0x6bb3cd34, 0x0d19, 0x45ab, { 0x97, 0xed, 0xd7, 0x20, 0xba, 0x3d, 0xfc, 0x80 } };
65 
66 static const struct debug_named_value
67 d3d12_debug_options[] = {
68    { "verbose",      D3D12_DEBUG_VERBOSE,       NULL },
69    { "blit",         D3D12_DEBUG_BLIT,          "Trace blit and copy resource calls" },
70    { "experimental", D3D12_DEBUG_EXPERIMENTAL,  "Enable experimental shader models feature" },
71    { "dxil",         D3D12_DEBUG_DXIL,          "Dump DXIL during program compile" },
72    { "disass",       D3D12_DEBUG_DISASS,        "Dump disassambly of created DXIL shader" },
73    { "res",          D3D12_DEBUG_RESOURCE,      "Debug resources" },
74    { "debuglayer",   D3D12_DEBUG_DEBUG_LAYER,   "Enable debug layer" },
75    { "gpuvalidator", D3D12_DEBUG_GPU_VALIDATOR, "Enable GPU validator" },
76    { "singleton",    D3D12_DEBUG_SINGLETON,     "Disallow use of device factory" },
77    { "pix",          D3D12_DEBUG_PIX,           "Load WinPixGpuCaptuerer.dll" },
78    DEBUG_NAMED_VALUE_END
79 };
80 
81 DEBUG_GET_ONCE_FLAGS_OPTION(d3d12_debug, "D3D12_DEBUG", d3d12_debug_options, 0)
82 
83 uint32_t
84 d3d12_debug;
85 
86 enum {
87     HW_VENDOR_AMD                   = 0x1002,
88     HW_VENDOR_INTEL                 = 0x8086,
89     HW_VENDOR_MICROSOFT             = 0x1414,
90     HW_VENDOR_NVIDIA                = 0x10de,
91 };
92 
93 static const char *
d3d12_get_vendor(struct pipe_screen * pscreen)94 d3d12_get_vendor(struct pipe_screen *pscreen)
95 {
96    return "Microsoft Corporation";
97 }
98 
99 static const char *
d3d12_get_device_vendor(struct pipe_screen * pscreen)100 d3d12_get_device_vendor(struct pipe_screen *pscreen)
101 {
102    struct d3d12_screen* screen = d3d12_screen(pscreen);
103 
104    switch (screen->vendor_id) {
105    case HW_VENDOR_MICROSOFT:
106       return "Microsoft";
107    case HW_VENDOR_AMD:
108       return "AMD";
109    case HW_VENDOR_NVIDIA:
110       return "NVIDIA";
111    case HW_VENDOR_INTEL:
112       return "Intel";
113    default:
114       return "Unknown";
115    }
116 }
117 
118 static int
d3d12_get_video_mem(struct pipe_screen * pscreen)119 d3d12_get_video_mem(struct pipe_screen *pscreen)
120 {
121    struct d3d12_screen* screen = d3d12_screen(pscreen);
122 
123    return screen->memory_size_megabytes;
124 }
125 
126 static int
d3d12_get_param_default(struct pipe_screen * pscreen,enum pipe_cap param)127 d3d12_get_param_default(struct pipe_screen *pscreen, enum pipe_cap param)
128 {
129    struct d3d12_screen *screen = d3d12_screen(pscreen);
130 
131    switch (param) {
132    case PIPE_CAP_NPOT_TEXTURES:
133       return 1;
134 
135    case PIPE_CAP_MAX_DUAL_SOURCE_RENDER_TARGETS:
136       /* D3D12 only supports dual-source blending for a single
137        * render-target. From the D3D11 functional spec (which also defines
138        * this for D3D12):
139        *
140        * "When Dual Source Color Blending is enabled, the Pixel Shader must
141        *  have only a single RenderTarget bound, at slot 0, and must output
142        *  both o0 and o1. Writing to other outputs (o2, o3 etc.) produces
143        *  undefined results for the corresponding RenderTargets, if bound
144        *  illegally."
145        *
146        * Source: https://microsoft.github.io/DirectX-Specs/d3d/archive/D3D11_3_FunctionalSpec.htm#17.6%20Dual%20Source%20Color%20Blending
147        */
148       return 1;
149 
150    case PIPE_CAP_ANISOTROPIC_FILTER:
151       return 1;
152 
153    case PIPE_CAP_MAX_RENDER_TARGETS:
154       return D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT;
155 
156    case PIPE_CAP_TEXTURE_SWIZZLE:
157       return 1;
158 
159    case PIPE_CAP_MAX_TEXEL_BUFFER_ELEMENTS_UINT:
160       return 1 << D3D12_REQ_BUFFER_RESOURCE_TEXEL_COUNT_2_TO_EXP;
161 
162    case PIPE_CAP_MAX_TEXTURE_2D_SIZE:
163       return D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION;
164 
165    case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
166       static_assert(D3D12_REQ_TEXTURE3D_U_V_OR_W_DIMENSION == (1 << 11),
167                     "D3D12_REQ_TEXTURE3D_U_V_OR_W_DIMENSION");
168       return 12;
169 
170    case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
171       return D3D12_REQ_MIP_LEVELS;
172 
173    case PIPE_CAP_PRIMITIVE_RESTART:
174    case PIPE_CAP_INDEP_BLEND_ENABLE:
175    case PIPE_CAP_INDEP_BLEND_FUNC:
176    case PIPE_CAP_FRAGMENT_SHADER_TEXTURE_LOD:
177    case PIPE_CAP_FRAGMENT_SHADER_DERIVATIVES:
178    case PIPE_CAP_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION:
179    case PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY:
180    case PIPE_CAP_MIXED_COLOR_DEPTH_BITS:
181       return 1;
182 
183    /* We need to do some lowering that requires a link to the sampler */
184    case PIPE_CAP_NIR_SAMPLERS_AS_DEREF:
185       return 1;
186 
187    case PIPE_CAP_NIR_IMAGES_AS_DEREF:
188       return 1;
189 
190    case PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS:
191       return D3D12_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION;
192 
193    case PIPE_CAP_DEPTH_CLIP_DISABLE:
194       return 1;
195 
196    case PIPE_CAP_TGSI_TEXCOORD:
197       return 1;
198 
199    case PIPE_CAP_VERTEX_COLOR_UNCLAMPED:
200       return 1;
201 
202    case PIPE_CAP_GLSL_FEATURE_LEVEL:
203       return 460;
204    case PIPE_CAP_GLSL_FEATURE_LEVEL_COMPATIBILITY:
205       return 460;
206    case PIPE_CAP_ESSL_FEATURE_LEVEL:
207       return 310;
208 
209    case PIPE_CAP_COMPUTE:
210       return 1;
211 
212    case PIPE_CAP_TEXTURE_MULTISAMPLE:
213       return 1;
214 
215    case PIPE_CAP_CUBE_MAP_ARRAY:
216       return 1;
217 
218    case PIPE_CAP_TEXTURE_BUFFER_OBJECTS:
219       return 1;
220 
221    case PIPE_CAP_TEXTURE_TRANSFER_MODES:
222       return PIPE_TEXTURE_TRANSFER_BLIT;
223 
224    case PIPE_CAP_ENDIANNESS:
225       return PIPE_ENDIAN_NATIVE; /* unsure */
226 
227    case PIPE_CAP_MAX_VIEWPORTS:
228       return D3D12_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE;
229 
230    case PIPE_CAP_MIXED_FRAMEBUFFER_SIZES:
231       return 1;
232 
233    case PIPE_CAP_MAX_TEXTURE_GATHER_COMPONENTS:
234       return 4;
235 
236    case PIPE_CAP_FS_COORD_PIXEL_CENTER_HALF_INTEGER:
237    case PIPE_CAP_FS_COORD_ORIGIN_UPPER_LEFT:
238       return 1;
239 
240    case PIPE_CAP_ACCELERATED:
241       return screen->vendor_id != HW_VENDOR_MICROSOFT;
242 
243    case PIPE_CAP_VIDEO_MEMORY:
244       return d3d12_get_video_mem(pscreen);
245 
246    case PIPE_CAP_UMA:
247       return screen->architecture.UMA;
248 
249    case PIPE_CAP_MAX_VERTEX_ATTRIB_STRIDE:
250       return 2048; /* FIXME: no clue how to query this */
251 
252    case PIPE_CAP_TEXTURE_FLOAT_LINEAR:
253    case PIPE_CAP_TEXTURE_HALF_FLOAT_LINEAR:
254       return 1;
255 
256    case PIPE_CAP_SHADER_BUFFER_OFFSET_ALIGNMENT:
257       return D3D12_RAW_UAV_SRV_BYTE_ALIGNMENT;
258 
259    case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT:
260       return D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT;
261 
262    case PIPE_CAP_PCI_GROUP:
263    case PIPE_CAP_PCI_BUS:
264    case PIPE_CAP_PCI_DEVICE:
265    case PIPE_CAP_PCI_FUNCTION:
266       return 0; /* TODO: figure these out */
267 
268    case PIPE_CAP_FLATSHADE:
269    case PIPE_CAP_ALPHA_TEST:
270    case PIPE_CAP_TWO_SIDED_COLOR:
271    case PIPE_CAP_CLIP_PLANES:
272       return 0;
273 
274    case PIPE_CAP_SHADER_STENCIL_EXPORT:
275       return screen->opts.PSSpecifiedStencilRefSupported;
276 
277    case PIPE_CAP_SEAMLESS_CUBE_MAP:
278    case PIPE_CAP_TEXTURE_QUERY_LOD:
279    case PIPE_CAP_VS_INSTANCEID:
280    case PIPE_CAP_TGSI_TEX_TXF_LZ:
281    case PIPE_CAP_OCCLUSION_QUERY:
282    case PIPE_CAP_VIEWPORT_TRANSFORM_LOWERED:
283    case PIPE_CAP_PSIZ_CLAMPED:
284    case PIPE_CAP_BLEND_EQUATION_SEPARATE:
285    case PIPE_CAP_CONDITIONAL_RENDER:
286    case PIPE_CAP_CONDITIONAL_RENDER_INVERTED:
287    case PIPE_CAP_QUERY_TIMESTAMP:
288    case PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR:
289    case PIPE_CAP_VERTEX_ELEMENT_SRC_OFFSET_4BYTE_ALIGNED_ONLY:
290    case PIPE_CAP_IMAGE_STORE_FORMATTED:
291    case PIPE_CAP_GLSL_TESS_LEVELS_AS_INPUTS:
292       return 1;
293 
294    case PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS:
295       return D3D12_SO_BUFFER_SLOT_COUNT;
296 
297    case PIPE_CAP_MAX_STREAM_OUTPUT_SEPARATE_COMPONENTS:
298    case PIPE_CAP_MAX_STREAM_OUTPUT_INTERLEAVED_COMPONENTS:
299       return D3D12_SO_OUTPUT_COMPONENT_COUNT;
300 
301    /* Geometry shader output. */
302    case PIPE_CAP_MAX_GEOMETRY_OUTPUT_VERTICES:
303       return D3D12_GS_MAX_OUTPUT_VERTEX_COUNT_ACROSS_INSTANCES;
304    case PIPE_CAP_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS:
305       return D3D12_REQ_GS_INVOCATION_32BIT_OUTPUT_COMPONENT_LIMIT;
306 
307    case PIPE_CAP_MAX_VARYINGS:
308       /* Subtract one so that implicit position can be added */
309       return D3D12_PS_INPUT_REGISTER_COUNT - 1;
310 
311    case PIPE_CAP_MAX_COMBINED_SHADER_OUTPUT_RESOURCES:
312       if (screen->max_feature_level <= D3D_FEATURE_LEVEL_11_0)
313          return D3D12_PS_CS_UAV_REGISTER_COUNT;
314       if (screen->opts.ResourceBindingTier <= D3D12_RESOURCE_BINDING_TIER_2)
315          return D3D12_UAV_SLOT_COUNT;
316       return 0;
317 
318    case PIPE_CAP_START_INSTANCE:
319    case PIPE_CAP_DRAW_PARAMETERS:
320    case PIPE_CAP_DRAW_INDIRECT:
321    case PIPE_CAP_MULTI_DRAW_INDIRECT:
322    case PIPE_CAP_MULTI_DRAW_INDIRECT_PARAMS:
323    case PIPE_CAP_FRAMEBUFFER_NO_ATTACHMENT:
324    case PIPE_CAP_SAMPLE_SHADING:
325    case PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME:
326    case PIPE_CAP_STREAM_OUTPUT_INTERLEAVE_BUFFERS:
327    case PIPE_CAP_INT64:
328    case PIPE_CAP_DOUBLES:
329    case PIPE_CAP_DEVICE_RESET_STATUS_QUERY:
330    case PIPE_CAP_ROBUST_BUFFER_ACCESS_BEHAVIOR:
331    case PIPE_CAP_MEMOBJ:
332    case PIPE_CAP_FENCE_SIGNAL:
333    case PIPE_CAP_TIMELINE_SEMAPHORE_IMPORT:
334    case PIPE_CAP_CLIP_HALFZ:
335    case PIPE_CAP_VS_LAYER_VIEWPORT:
336    case PIPE_CAP_COPY_BETWEEN_COMPRESSED_AND_PLAIN_FORMATS:
337    case PIPE_CAP_SHADER_ARRAY_COMPONENTS:
338    case PIPE_CAP_TEXTURE_MIRROR_CLAMP_TO_EDGE:
339    case PIPE_CAP_QUERY_TIME_ELAPSED:
340    case PIPE_CAP_FS_FINE_DERIVATIVE:
341    case PIPE_CAP_CULL_DISTANCE:
342    case PIPE_CAP_TEXTURE_QUERY_SAMPLES:
343    case PIPE_CAP_TEXTURE_BARRIER:
344    case PIPE_CAP_GL_SPIRV:
345    case PIPE_CAP_POLYGON_OFFSET_CLAMP:
346    case PIPE_CAP_SHADER_GROUP_VOTE:
347    case PIPE_CAP_SHADER_BALLOT:
348    case PIPE_CAP_QUERY_PIPELINE_STATISTICS:
349    case PIPE_CAP_QUERY_SO_OVERFLOW:
350       return 1;
351 
352    case PIPE_CAP_QUERY_BUFFER_OBJECT:
353       return (screen->opts3.WriteBufferImmediateSupportFlags & D3D12_COMMAND_LIST_SUPPORT_FLAG_DIRECT) != 0;
354 
355    case PIPE_CAP_MAX_VERTEX_STREAMS:
356       return D3D12_SO_BUFFER_SLOT_COUNT;
357 
358    case PIPE_CAP_MAX_SHADER_PATCH_VARYINGS:
359       /* This is asking about varyings, not total registers, so remove the 2 tess factor registers. */
360       return D3D12_HS_OUTPUT_PATCH_CONSTANT_REGISTER_COUNT - 2;
361 
362    case PIPE_CAP_MAX_TEXTURE_UPLOAD_MEMORY_BUDGET:
363       /* Picking a value in line with other drivers. Without this, we can end up easily hitting OOM
364        * if an app just creates, initializes, and destroys resources without explicitly flushing. */
365       return 64 * 1024 * 1024;
366 
367    case PIPE_CAP_SAMPLER_VIEW_TARGET:
368       return screen->opts12.RelaxedFormatCastingSupported;
369 
370    default:
371       return u_pipe_screen_get_param_defaults(pscreen, param);
372    }
373 }
374 
375 static int
d3d12_get_generic_param(struct pipe_screen * pscreen,enum pipe_cap param)376 d3d12_get_generic_param(struct pipe_screen *pscreen, enum pipe_cap param)
377 {
378    struct d3d12_screen *screen = d3d12_screen(pscreen);
379    switch (param) {
380       case PIPE_CAP_ACCELERATED:
381          return screen->vendor_id != HW_VENDOR_MICROSOFT;
382       case PIPE_CAP_VIDEO_MEMORY:
383          return d3d12_get_video_mem(pscreen);
384       case PIPE_CAP_UMA:
385          return screen->architecture.UMA;
386       default:
387          return 0;
388    }
389 }
390 
391 static int
d3d12_get_param(struct pipe_screen * pscreen,enum pipe_cap param)392 d3d12_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
393 {
394    struct d3d12_screen *screen = d3d12_screen(pscreen);
395    if (screen->max_feature_level < D3D_FEATURE_LEVEL_11_0)
396       return d3d12_get_generic_param(pscreen, param);
397 
398    return d3d12_get_param_default(pscreen, param);
399 }
400 
401 static float
d3d12_get_paramf(struct pipe_screen * pscreen,enum pipe_capf param)402 d3d12_get_paramf(struct pipe_screen *pscreen, enum pipe_capf param)
403 {
404    switch (param) {
405    case PIPE_CAPF_MIN_LINE_WIDTH:
406    case PIPE_CAPF_MIN_LINE_WIDTH_AA:
407    case PIPE_CAPF_MIN_POINT_SIZE:
408    case PIPE_CAPF_MIN_POINT_SIZE_AA:
409       return 1;
410 
411    case PIPE_CAPF_POINT_SIZE_GRANULARITY:
412    case PIPE_CAPF_LINE_WIDTH_GRANULARITY:
413       return 0.1;
414 
415    case PIPE_CAPF_MAX_LINE_WIDTH:
416    case PIPE_CAPF_MAX_LINE_WIDTH_AA:
417       return 1.0f; /* no clue */
418 
419    case PIPE_CAPF_MAX_POINT_SIZE:
420    case PIPE_CAPF_MAX_POINT_SIZE_AA:
421       return D3D12_MAX_POINT_SIZE;
422 
423    case PIPE_CAPF_MAX_TEXTURE_ANISOTROPY:
424       return D3D12_MAX_MAXANISOTROPY;
425 
426    case PIPE_CAPF_MAX_TEXTURE_LOD_BIAS:
427       return 15.99f;
428 
429    case PIPE_CAPF_MIN_CONSERVATIVE_RASTER_DILATE:
430    case PIPE_CAPF_MAX_CONSERVATIVE_RASTER_DILATE:
431    case PIPE_CAPF_CONSERVATIVE_RASTER_DILATE_GRANULARITY:
432       return 0.0f; /* not implemented */
433 
434    default:
435       unreachable("unknown pipe_capf");
436    }
437 
438    return 0.0;
439 }
440 
441 static int
d3d12_get_shader_param(struct pipe_screen * pscreen,enum pipe_shader_type shader,enum pipe_shader_cap param)442 d3d12_get_shader_param(struct pipe_screen *pscreen,
443                        enum pipe_shader_type shader,
444                        enum pipe_shader_cap param)
445 {
446    struct d3d12_screen *screen = d3d12_screen(pscreen);
447 
448    if (shader == PIPE_SHADER_TASK ||
449        shader == PIPE_SHADER_MESH)
450       return 0;
451 
452    switch (param) {
453    case PIPE_SHADER_CAP_MAX_INSTRUCTIONS:
454    case PIPE_SHADER_CAP_MAX_ALU_INSTRUCTIONS:
455    case PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS:
456    case PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS:
457    case PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH:
458          return INT_MAX;
459       return 0;
460 
461    case PIPE_SHADER_CAP_MAX_INPUTS:
462       switch (shader) {
463       case PIPE_SHADER_VERTEX: return D3D12_VS_INPUT_REGISTER_COUNT;
464       case PIPE_SHADER_FRAGMENT: return D3D12_PS_INPUT_REGISTER_COUNT;
465       case PIPE_SHADER_GEOMETRY: return D3D12_GS_INPUT_REGISTER_COUNT;
466       case PIPE_SHADER_TESS_CTRL: return D3D12_HS_CONTROL_POINT_PHASE_INPUT_REGISTER_COUNT;
467       case PIPE_SHADER_TESS_EVAL: return D3D12_DS_INPUT_CONTROL_POINT_REGISTER_COUNT;
468       case PIPE_SHADER_COMPUTE: return 0;
469       default: unreachable("Unexpected shader");
470       }
471       break;
472 
473    case PIPE_SHADER_CAP_MAX_OUTPUTS:
474       switch (shader) {
475       case PIPE_SHADER_VERTEX: return D3D12_VS_OUTPUT_REGISTER_COUNT;
476       case PIPE_SHADER_FRAGMENT: return D3D12_PS_OUTPUT_REGISTER_COUNT;
477       case PIPE_SHADER_GEOMETRY: return D3D12_GS_OUTPUT_REGISTER_COUNT;
478       case PIPE_SHADER_TESS_CTRL: return D3D12_HS_CONTROL_POINT_PHASE_OUTPUT_REGISTER_COUNT;
479       case PIPE_SHADER_TESS_EVAL: return D3D12_DS_OUTPUT_REGISTER_COUNT;
480       case PIPE_SHADER_COMPUTE: return 0;
481       default: unreachable("Unexpected shader");
482       }
483       break;
484 
485    case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS:
486       if (screen->opts.ResourceBindingTier == D3D12_RESOURCE_BINDING_TIER_1)
487          return 16;
488       return PIPE_MAX_SAMPLERS;
489 
490    case PIPE_SHADER_CAP_MAX_CONST_BUFFER0_SIZE:
491       return 65536;
492 
493    case PIPE_SHADER_CAP_MAX_CONST_BUFFERS:
494       if (screen->opts.ResourceBindingTier < D3D12_RESOURCE_BINDING_TIER_3)
495          return 13; /* 15 - 2 for lowered uniforms and state vars*/
496       return 15;
497 
498    case PIPE_SHADER_CAP_MAX_TEMPS:
499       return INT_MAX;
500 
501    case PIPE_SHADER_CAP_INDIRECT_INPUT_ADDR:
502    case PIPE_SHADER_CAP_INDIRECT_OUTPUT_ADDR:
503    case PIPE_SHADER_CAP_INDIRECT_TEMP_ADDR:
504    case PIPE_SHADER_CAP_SUBROUTINES:
505       return 0; /* not implemented */
506 
507    case PIPE_SHADER_CAP_INDIRECT_CONST_ADDR:
508    case PIPE_SHADER_CAP_INTEGERS:
509       return 1;
510 
511    case PIPE_SHADER_CAP_INT64_ATOMICS:
512    case PIPE_SHADER_CAP_FP16:
513       return 0; /* not implemented */
514 
515    case PIPE_SHADER_CAP_TGSI_SQRT_SUPPORTED:
516       return 0; /* not implemented */
517 
518    case PIPE_SHADER_CAP_MAX_SAMPLER_VIEWS:
519       /* Note: This is wrong, but this is the max value that
520        * TC can support to avoid overflowing an array.
521        */
522       return PIPE_MAX_SAMPLERS;
523 
524    case PIPE_SHADER_CAP_TGSI_ANY_INOUT_DECL_RANGE:
525       return 0; /* no idea */
526 
527    case PIPE_SHADER_CAP_MAX_SHADER_BUFFERS:
528       return
529          (screen->max_feature_level >= D3D_FEATURE_LEVEL_11_1 ||
530           screen->opts.ResourceBindingTier >= D3D12_RESOURCE_BINDING_TIER_3) ?
531          PIPE_MAX_SHADER_BUFFERS : D3D12_PS_CS_UAV_REGISTER_COUNT;
532 
533    case PIPE_SHADER_CAP_SUPPORTED_IRS:
534       return 1 << PIPE_SHADER_IR_NIR;
535 
536    case PIPE_SHADER_CAP_MAX_SHADER_IMAGES:
537       if (!screen->support_shader_images)
538          return 0;
539       return
540          (screen->max_feature_level >= D3D_FEATURE_LEVEL_11_1 ||
541           screen->opts.ResourceBindingTier >= D3D12_RESOURCE_BINDING_TIER_3) ?
542          PIPE_MAX_SHADER_IMAGES : D3D12_PS_CS_UAV_REGISTER_COUNT;
543 
544    case PIPE_SHADER_CAP_MAX_HW_ATOMIC_COUNTERS:
545    case PIPE_SHADER_CAP_MAX_HW_ATOMIC_COUNTER_BUFFERS:
546    case PIPE_SHADER_CAP_CONT_SUPPORTED:
547       return 0; /* not implemented */
548 
549    /* should only get here on unhandled cases */
550    default: return 0;
551    }
552 }
553 
554 static int
d3d12_get_compute_param(struct pipe_screen * pscreen,enum pipe_shader_ir ir,enum pipe_compute_cap cap,void * ret)555 d3d12_get_compute_param(struct pipe_screen *pscreen,
556                         enum pipe_shader_ir ir,
557                         enum pipe_compute_cap cap,
558                         void *ret)
559 {
560    switch (cap) {
561    case PIPE_COMPUTE_CAP_MAX_GRID_SIZE: {
562       uint64_t *grid = (uint64_t *)ret;
563       grid[0] = grid[1] = grid[2] = D3D12_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION;
564       return sizeof(uint64_t) * 3;
565    }
566    case PIPE_COMPUTE_CAP_MAX_BLOCK_SIZE: {
567       uint64_t *block = (uint64_t *)ret;
568       block[0] = D3D12_CS_THREAD_GROUP_MAX_X;
569       block[1] = D3D12_CS_THREAD_GROUP_MAX_Y;
570       block[2] = D3D12_CS_THREAD_GROUP_MAX_Z;
571       return sizeof(uint64_t) * 3;
572    }
573    case PIPE_COMPUTE_CAP_MAX_VARIABLE_THREADS_PER_BLOCK:
574    case PIPE_COMPUTE_CAP_MAX_THREADS_PER_BLOCK:
575       *(uint64_t *)ret = D3D12_CS_THREAD_GROUP_MAX_THREADS_PER_GROUP;
576       return sizeof(uint64_t);
577    case PIPE_COMPUTE_CAP_MAX_LOCAL_SIZE:
578       *(uint64_t *)ret = D3D12_CS_TGSM_REGISTER_COUNT /*DWORDs*/ * 4;
579       return sizeof(uint64_t);
580    default:
581       return 0;
582    }
583 }
584 
585 static bool
d3d12_is_format_supported(struct pipe_screen * pscreen,enum pipe_format format,enum pipe_texture_target target,unsigned sample_count,unsigned storage_sample_count,unsigned bind)586 d3d12_is_format_supported(struct pipe_screen *pscreen,
587                           enum pipe_format format,
588                           enum pipe_texture_target target,
589                           unsigned sample_count,
590                           unsigned storage_sample_count,
591                           unsigned bind)
592 {
593    struct d3d12_screen *screen = d3d12_screen(pscreen);
594 
595    if (MAX2(1, sample_count) != MAX2(1, storage_sample_count))
596       return false;
597 
598    if (target == PIPE_BUFFER) {
599       /* Replace emulated vertex element formats for the tests */
600       format = d3d12_emulated_vtx_format(format);
601    } else {
602       /* Allow 3-comp 32 bit formats only for BOs (needed for ARB_tbo_rgb32) */
603       if ((format == PIPE_FORMAT_R32G32B32_FLOAT ||
604            format == PIPE_FORMAT_R32G32B32_SINT ||
605            format == PIPE_FORMAT_R32G32B32_UINT))
606          return false;
607    }
608 
609    /* Don't advertise alpha/luminance_alpha formats because they can't be used
610     * for render targets (except A8_UNORM) and can't be emulated by R/RG formats.
611     * Let the state tracker choose an RGBA format instead. For YUV formats, we
612     * want the state tracker to lower these to individual planes. */
613    if (format != PIPE_FORMAT_A8_UNORM &&
614        (util_format_is_alpha(format) ||
615         util_format_is_luminance_alpha(format) ||
616         util_format_is_yuv(format)))
617       return false;
618 
619    if (format == PIPE_FORMAT_NONE) {
620       /* For UAV-only rendering, aka ARB_framebuffer_no_attachments */
621       switch (sample_count) {
622       case 0:
623       case 1:
624       case 4:
625       case 8:
626       case 16:
627          return true;
628       default:
629          return false;
630       }
631    }
632 
633    DXGI_FORMAT dxgi_format = d3d12_get_format(format);
634    if (dxgi_format == DXGI_FORMAT_UNKNOWN)
635       return false;
636 
637    enum D3D12_FORMAT_SUPPORT1 dim_support = D3D12_FORMAT_SUPPORT1_NONE;
638    switch (target) {
639    case PIPE_TEXTURE_1D:
640    case PIPE_TEXTURE_1D_ARRAY:
641       dim_support = D3D12_FORMAT_SUPPORT1_TEXTURE1D;
642       break;
643    case PIPE_TEXTURE_2D:
644    case PIPE_TEXTURE_RECT:
645    case PIPE_TEXTURE_2D_ARRAY:
646       dim_support = D3D12_FORMAT_SUPPORT1_TEXTURE2D;
647       break;
648    case PIPE_TEXTURE_3D:
649       dim_support = D3D12_FORMAT_SUPPORT1_TEXTURE3D;
650       break;
651    case PIPE_TEXTURE_CUBE:
652    case PIPE_TEXTURE_CUBE_ARRAY:
653       dim_support = D3D12_FORMAT_SUPPORT1_TEXTURECUBE;
654       break;
655    case PIPE_BUFFER:
656       dim_support = D3D12_FORMAT_SUPPORT1_BUFFER;
657       break;
658    default:
659       unreachable("Unknown target");
660    }
661 
662    if (bind & PIPE_BIND_DISPLAY_TARGET) {
663       enum pipe_format dt_format = format == PIPE_FORMAT_R16G16B16A16_FLOAT ? PIPE_FORMAT_R8G8B8A8_UNORM : format;
664       if (!screen->winsys->is_displaytarget_format_supported(screen->winsys, bind, dt_format))
665          return false;
666    }
667 
668    D3D12_FEATURE_DATA_FORMAT_SUPPORT fmt_info;
669    fmt_info.Format = d3d12_get_resource_rt_format(format);
670    if (FAILED(screen->dev->CheckFeatureSupport(D3D12_FEATURE_FORMAT_SUPPORT,
671                                                &fmt_info, sizeof(fmt_info))))
672       return false;
673 
674    if (!(fmt_info.Support1 & dim_support))
675       return false;
676 
677    if (target == PIPE_BUFFER) {
678       if (bind & PIPE_BIND_VERTEX_BUFFER &&
679           !(fmt_info.Support1 & D3D12_FORMAT_SUPPORT1_IA_VERTEX_BUFFER))
680          return false;
681 
682       if (bind & PIPE_BIND_INDEX_BUFFER) {
683          if (format != PIPE_FORMAT_R16_UINT &&
684              format != PIPE_FORMAT_R32_UINT)
685             return false;
686       }
687 
688       if (sample_count > 0)
689          return false;
690    } else {
691       /* all other targets are texture-targets */
692       if (bind & PIPE_BIND_RENDER_TARGET &&
693           !(fmt_info.Support1 & D3D12_FORMAT_SUPPORT1_RENDER_TARGET))
694          return false;
695 
696       if (bind & PIPE_BIND_BLENDABLE &&
697          !(fmt_info.Support1 & D3D12_FORMAT_SUPPORT1_BLENDABLE))
698          return false;
699 
700       if (bind & PIPE_BIND_SHADER_IMAGE &&
701          (fmt_info.Support2 & (D3D12_FORMAT_SUPPORT2_UAV_TYPED_LOAD | D3D12_FORMAT_SUPPORT2_UAV_TYPED_STORE)) !=
702             (D3D12_FORMAT_SUPPORT2_UAV_TYPED_LOAD | D3D12_FORMAT_SUPPORT2_UAV_TYPED_STORE))
703          return false;
704 
705       D3D12_FEATURE_DATA_FORMAT_SUPPORT fmt_info_sv;
706       if (util_format_is_depth_or_stencil(format)) {
707          fmt_info_sv.Format = d3d12_get_resource_srv_format(format, target);
708          if (FAILED(screen->dev->CheckFeatureSupport(D3D12_FEATURE_FORMAT_SUPPORT,
709                                                      &fmt_info_sv, sizeof(fmt_info_sv))))
710             return false;
711       } else
712          fmt_info_sv = fmt_info;
713 
714       if (bind & PIPE_BIND_DEPTH_STENCIL &&
715           !(fmt_info.Support1 & D3D12_FORMAT_SUPPORT1_DEPTH_STENCIL))
716             return false;
717 
718       if (sample_count > 0) {
719          if (!(fmt_info_sv.Support1 & D3D12_FORMAT_SUPPORT1_MULTISAMPLE_LOAD))
720             return false;
721 
722          if (!util_is_power_of_two_nonzero(sample_count))
723             return false;
724 
725          if (bind & PIPE_BIND_SHADER_IMAGE)
726             return false;
727 
728          D3D12_FEATURE_DATA_MULTISAMPLE_QUALITY_LEVELS ms_info = {};
729          ms_info.Format = dxgi_format;
730          ms_info.SampleCount = sample_count;
731          if (FAILED(screen->dev->CheckFeatureSupport(D3D12_FEATURE_MULTISAMPLE_QUALITY_LEVELS,
732                                                      &ms_info,
733                                                      sizeof(ms_info))) ||
734              !ms_info.NumQualityLevels)
735             return false;
736       }
737    }
738    return true;
739 }
740 
741 void
d3d12_deinit_screen(struct d3d12_screen * screen)742 d3d12_deinit_screen(struct d3d12_screen *screen)
743 {
744 #ifdef HAVE_GALLIUM_D3D12_GRAPHICS
745    if (screen->max_feature_level >= D3D_FEATURE_LEVEL_11_0) {
746       if (screen->rtv_pool) {
747          d3d12_descriptor_pool_free(screen->rtv_pool);
748          screen->rtv_pool = nullptr;
749       }
750       if (screen->dsv_pool) {
751          d3d12_descriptor_pool_free(screen->dsv_pool);
752          screen->dsv_pool = nullptr;
753       }
754       if (screen->view_pool) {
755          d3d12_descriptor_pool_free(screen->view_pool);
756          screen->view_pool = nullptr;
757       }
758    }
759 #endif // HAVE_GALLIUM_D3D12_GRAPHICS
760    if (screen->readback_slab_bufmgr) {
761       screen->readback_slab_bufmgr->destroy(screen->readback_slab_bufmgr);
762       screen->readback_slab_bufmgr = nullptr;
763    }
764    if (screen->slab_bufmgr) {
765       screen->slab_bufmgr->destroy(screen->slab_bufmgr);
766       screen->slab_bufmgr = nullptr;
767    }
768    if (screen->cache_bufmgr) {
769       screen->cache_bufmgr->destroy(screen->cache_bufmgr);
770       screen->cache_bufmgr = nullptr;
771    }
772    if (screen->slab_cache_bufmgr) {
773       screen->slab_cache_bufmgr->destroy(screen->slab_cache_bufmgr);
774       screen->slab_cache_bufmgr = nullptr;
775    }
776    if (screen->readback_slab_cache_bufmgr) {
777       screen->readback_slab_cache_bufmgr->destroy(screen->readback_slab_cache_bufmgr);
778       screen->readback_slab_cache_bufmgr = nullptr;
779    }
780    if (screen->bufmgr) {
781       screen->bufmgr->destroy(screen->bufmgr);
782       screen->bufmgr = nullptr;
783    }
784    d3d12_deinit_residency(screen);
785    if (screen->fence) {
786       screen->fence->Release();
787       screen->fence = nullptr;
788    }
789    if (screen->cmdqueue) {
790       screen->cmdqueue->Release();
791       screen->cmdqueue = nullptr;
792    }
793    if (screen->dev10) {
794       screen->dev10->Release();
795       screen->dev10 = nullptr;
796    }
797    if (screen->dev) {
798       screen->dev->Release();
799       screen->dev = nullptr;
800    }
801 }
802 
803 void
d3d12_destroy_screen(struct d3d12_screen * screen)804 d3d12_destroy_screen(struct d3d12_screen *screen)
805 {
806    slab_destroy_parent(&screen->transfer_pool);
807    mtx_destroy(&screen->submit_mutex);
808    mtx_destroy(&screen->descriptor_pool_mutex);
809 
810 #ifdef HAVE_GALLIUM_D3D12_GRAPHICS
811    d3d12_varying_cache_destroy(screen);
812    mtx_destroy(&screen->varying_info_mutex);
813 #endif // HAVE_GALLIUM_D3D12_GRAPHICS
814 
815    if (screen->d3d12_mod)
816       util_dl_close(screen->d3d12_mod);
817    glsl_type_singleton_decref();
818    FREE(screen);
819 }
820 
821 static void
d3d12_flush_frontbuffer(struct pipe_screen * pscreen,struct pipe_context * pctx,struct pipe_resource * pres,unsigned level,unsigned layer,void * winsys_drawable_handle,unsigned nboxes,struct pipe_box * sub_box)822 d3d12_flush_frontbuffer(struct pipe_screen * pscreen,
823                         struct pipe_context *pctx,
824                         struct pipe_resource *pres,
825                         unsigned level, unsigned layer,
826                         void *winsys_drawable_handle,
827                         unsigned nboxes,
828                         struct pipe_box *sub_box)
829 {
830    struct d3d12_screen *screen = d3d12_screen(pscreen);
831    struct sw_winsys *winsys = screen->winsys;
832    struct d3d12_resource *res = d3d12_resource(pres);
833 
834    if (!winsys || !pctx)
835      return;
836 
837    assert(res->dt || res->dt_proxy);
838    if (res->dt_proxy) {
839      struct pipe_blit_info blit;
840 
841      memset(&blit, 0, sizeof(blit));
842      blit.dst.resource = res->dt_proxy;
843      blit.dst.box.width = blit.dst.resource->width0;
844      blit.dst.box.height = blit.dst.resource->height0;
845      blit.dst.box.depth = 1;
846      blit.dst.format = blit.dst.resource->format;
847      blit.src.resource = pres;
848      blit.src.box.width = blit.src.resource->width0;
849      blit.src.box.height = blit.src.resource->height0;
850      blit.src.box.depth = 1;
851      blit.src.format = blit.src.resource->format;
852      blit.mask = PIPE_MASK_RGBA;
853      blit.filter = PIPE_TEX_FILTER_NEAREST;
854 
855      pctx->blit(pctx, &blit);
856      pres = res->dt_proxy;
857      res = d3d12_resource(pres);
858    }
859 
860    assert(res->dt);
861    void *map = winsys->displaytarget_map(winsys, res->dt, 0);
862 
863    if (map) {
864       pctx = threaded_context_unwrap_sync(pctx);
865       pipe_transfer *transfer = nullptr;
866       void *res_map = pipe_texture_map(pctx, pres, level, layer, PIPE_MAP_READ, 0, 0,
867                                         u_minify(pres->width0, level),
868                                         u_minify(pres->height0, level),
869                                         &transfer);
870       if (res_map) {
871          util_copy_rect((uint8_t*)map, pres->format, res->dt_stride, 0, 0,
872                         transfer->box.width, transfer->box.height,
873                         (const uint8_t*)res_map, transfer->stride, 0, 0);
874          pipe_texture_unmap(pctx, transfer);
875       }
876       winsys->displaytarget_unmap(winsys, res->dt);
877    }
878 
879 #if defined(_WIN32) && !defined(_GAMING_XBOX) && defined(HAVE_GALLIUM_D3D12_GRAPHICS)
880    // WindowFromDC is Windows-only, and this method requires an HWND, so only use it on Windows
881    ID3D12SharingContract *sharing_contract;
882    if (SUCCEEDED(screen->cmdqueue->QueryInterface(IID_PPV_ARGS(&sharing_contract)))) {
883       ID3D12Resource *d3d12_res = d3d12_resource_resource(res);
884       sharing_contract->Present(d3d12_res, 0, WindowFromDC((HDC)winsys_drawable_handle));
885       sharing_contract->Release();
886    }
887 #endif
888 
889    winsys->displaytarget_display(winsys, res->dt, winsys_drawable_handle, nboxes, sub_box);
890 }
891 
892 #ifndef _GAMING_XBOX
893 static ID3D12Debug *
get_debug_interface(util_dl_library * d3d12_mod,ID3D12DeviceFactory * factory)894 get_debug_interface(util_dl_library *d3d12_mod, ID3D12DeviceFactory *factory)
895 {
896    ID3D12Debug *debug = nullptr;
897    if (factory) {
898       factory->GetConfigurationInterface(CLSID_D3D12Debug, IID_PPV_ARGS(&debug));
899       return debug;
900    }
901 
902    typedef HRESULT(WINAPI *PFN_D3D12_GET_DEBUG_INTERFACE)(REFIID riid, void **ppFactory);
903    PFN_D3D12_GET_DEBUG_INTERFACE D3D12GetDebugInterface;
904 
905    D3D12GetDebugInterface = (PFN_D3D12_GET_DEBUG_INTERFACE)util_dl_get_proc_address(d3d12_mod, "D3D12GetDebugInterface");
906    if (!D3D12GetDebugInterface) {
907       debug_printf("D3D12: failed to load D3D12GetDebugInterface from D3D12.DLL\n");
908       return NULL;
909    }
910 
911    if (FAILED(D3D12GetDebugInterface(IID_PPV_ARGS(&debug)))) {
912       debug_printf("D3D12: D3D12GetDebugInterface failed\n");
913       return NULL;
914    }
915 
916    return debug;
917 }
918 
919 static void
enable_d3d12_debug_layer(util_dl_library * d3d12_mod,ID3D12DeviceFactory * factory)920 enable_d3d12_debug_layer(util_dl_library *d3d12_mod, ID3D12DeviceFactory *factory)
921 {
922    ID3D12Debug *debug = get_debug_interface(d3d12_mod, factory);
923    if (debug) {
924       debug->EnableDebugLayer();
925       debug->Release();
926    }
927 }
928 
929 static void
enable_gpu_validation(util_dl_library * d3d12_mod,ID3D12DeviceFactory * factory)930 enable_gpu_validation(util_dl_library *d3d12_mod, ID3D12DeviceFactory *factory)
931 {
932    ID3D12Debug *debug = get_debug_interface(d3d12_mod, factory);
933    ID3D12Debug3 *debug3;
934    if (debug) {
935       if (SUCCEEDED(debug->QueryInterface(IID_PPV_ARGS(&debug3)))) {
936          debug3->SetEnableGPUBasedValidation(true);
937          debug3->Release();
938       }
939       debug->Release();
940    }
941 }
942 #endif
943 
944 #ifdef _GAMING_XBOX
945 
946 static ID3D12Device3 *
create_device(util_dl_library * d3d12_mod,IUnknown * adapter)947 create_device(util_dl_library *d3d12_mod, IUnknown *adapter)
948 {
949    D3D12XBOX_PROCESS_DEBUG_FLAGS debugFlags =
950       D3D12XBOX_PROCESS_DEBUG_FLAG_ENABLE_COMMON_STATE_PROMOTION; /* For compatibility with desktop D3D12 */
951 
952    if (d3d12_debug & D3D12_DEBUG_EXPERIMENTAL) {
953       debug_printf("D3D12: experimental shader models are not supported on GDKX\n");
954       return nullptr;
955    }
956 
957    if (d3d12_debug & D3D12_DEBUG_GPU_VALIDATOR) {
958       debug_printf("D3D12: gpu validation is not supported on GDKX\n"); /* FIXME: Is this right? */
959       return nullptr;
960    }
961 
962    if (d3d12_debug & D3D12_DEBUG_DEBUG_LAYER)
963       debugFlags |= D3D12XBOX_PROCESS_DEBUG_FLAG_DEBUG;
964 
965    D3D12XBOX_CREATE_DEVICE_PARAMETERS params = {};
966    params.Version = D3D12_SDK_VERSION;
967    params.ProcessDebugFlags = debugFlags;
968    params.GraphicsCommandQueueRingSizeBytes = D3D12XBOX_DEFAULT_SIZE_BYTES;
969    params.GraphicsScratchMemorySizeBytes = D3D12XBOX_DEFAULT_SIZE_BYTES;
970    params.ComputeScratchMemorySizeBytes = D3D12XBOX_DEFAULT_SIZE_BYTES;
971 
972    ID3D12Device3 *dev = nullptr;
973 
974    typedef HRESULT(WINAPI * PFN_D3D12XBOXCREATEDEVICE)(IGraphicsUnknown *, const D3D12XBOX_CREATE_DEVICE_PARAMETERS *, REFIID, void **);
975    PFN_D3D12XBOXCREATEDEVICE D3D12XboxCreateDevice =
976       (PFN_D3D12XBOXCREATEDEVICE) util_dl_get_proc_address(d3d12_mod, "D3D12XboxCreateDevice");
977    if (!D3D12XboxCreateDevice) {
978       debug_printf("D3D12: failed to load D3D12XboxCreateDevice from D3D12 DLL\n");
979       return NULL;
980    }
981    if (FAILED(D3D12XboxCreateDevice((IGraphicsUnknown*) adapter, &params, IID_PPV_ARGS(&dev))))
982       debug_printf("D3D12: D3D12XboxCreateDevice failed\n");
983 
984    return dev;
985 }
986 
987 #else
988 
989 static ID3D12Device3 *
create_device(util_dl_library * d3d12_mod,IUnknown * adapter,ID3D12DeviceFactory * factory)990 create_device(util_dl_library *d3d12_mod, IUnknown *adapter, ID3D12DeviceFactory *factory)
991 {
992 
993 #ifdef _WIN32
994    if (d3d12_debug & D3D12_DEBUG_EXPERIMENTAL)
995 #endif
996    {
997       if (factory) {
998          if (FAILED(factory->EnableExperimentalFeatures(1, &D3D12ExperimentalShaderModels, nullptr, nullptr))) {
999             debug_printf("D3D12: failed to enable experimental shader models\n");
1000             return nullptr;
1001          }
1002       } else {
1003          typedef HRESULT(WINAPI *PFN_D3D12ENABLEEXPERIMENTALFEATURES)(UINT, const IID*, void*, UINT*);
1004          PFN_D3D12ENABLEEXPERIMENTALFEATURES D3D12EnableExperimentalFeatures =
1005             (PFN_D3D12ENABLEEXPERIMENTALFEATURES)util_dl_get_proc_address(d3d12_mod, "D3D12EnableExperimentalFeatures");
1006 
1007          if (!D3D12EnableExperimentalFeatures ||
1008              FAILED(D3D12EnableExperimentalFeatures(1, &D3D12ExperimentalShaderModels, NULL, NULL))) {
1009             debug_printf("D3D12: failed to enable experimental shader models\n");
1010             return nullptr;
1011          }
1012       }
1013    }
1014 
1015    ID3D12Device3 *dev = nullptr;
1016    if (factory) {
1017       factory->SetFlags(D3D12_DEVICE_FACTORY_FLAG_ALLOW_RETURNING_EXISTING_DEVICE |
1018          D3D12_DEVICE_FACTORY_FLAG_ALLOW_RETURNING_INCOMPATIBLE_EXISTING_DEVICE);
1019       /* Fallback to D3D_FEATURE_LEVEL_11_0 for D3D12 versions without generic support */
1020       if (FAILED(factory->CreateDevice(adapter, D3D_FEATURE_LEVEL_1_0_GENERIC, IID_PPV_ARGS(&dev))))
1021          if (FAILED(factory->CreateDevice(adapter, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&dev))))
1022             debug_printf("D3D12: D3D12CreateDevice failed\n");
1023    } else {
1024       typedef HRESULT(WINAPI *PFN_D3D12CREATEDEVICE)(IUnknown*, D3D_FEATURE_LEVEL, REFIID, void**);
1025       PFN_D3D12CREATEDEVICE D3D12CreateDevice = (PFN_D3D12CREATEDEVICE)util_dl_get_proc_address(d3d12_mod, "D3D12CreateDevice");
1026       if (!D3D12CreateDevice) {
1027          debug_printf("D3D12: failed to load D3D12CreateDevice from D3D12.DLL\n");
1028          return NULL;
1029       }
1030       /* Fallback to D3D_FEATURE_LEVEL_11_0 for D3D12 versions without generic support */
1031       if (FAILED(D3D12CreateDevice(adapter, D3D_FEATURE_LEVEL_1_0_GENERIC, IID_PPV_ARGS(&dev))))
1032          if (FAILED(D3D12CreateDevice(adapter, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&dev))))
1033             debug_printf("D3D12: D3D12CreateDevice failed\n");
1034    }
1035 
1036    return dev;
1037 }
1038 
1039 #endif /* _GAMING_XBOX */
1040 
1041 static bool
can_attribute_at_vertex(struct d3d12_screen * screen)1042 can_attribute_at_vertex(struct d3d12_screen *screen)
1043 {
1044    switch (screen->vendor_id)  {
1045    case HW_VENDOR_MICROSOFT:
1046       return true;
1047    default:
1048       return screen->opts3.BarycentricsSupported;
1049    }
1050 }
1051 
1052 static bool
can_shader_image_load_all_formats(struct d3d12_screen * screen)1053 can_shader_image_load_all_formats(struct d3d12_screen *screen)
1054 {
1055    if (!screen->opts.TypedUAVLoadAdditionalFormats)
1056       return false;
1057 
1058    /* All of these are required by ARB_shader_image_load_store */
1059    static const DXGI_FORMAT additional_formats[] = {
1060       DXGI_FORMAT_R16G16B16A16_UNORM,
1061       DXGI_FORMAT_R16G16B16A16_SNORM,
1062       DXGI_FORMAT_R32G32_FLOAT,
1063       DXGI_FORMAT_R32G32_UINT,
1064       DXGI_FORMAT_R32G32_SINT,
1065       DXGI_FORMAT_R10G10B10A2_UNORM,
1066       DXGI_FORMAT_R10G10B10A2_UINT,
1067       DXGI_FORMAT_R11G11B10_FLOAT,
1068       DXGI_FORMAT_R8G8B8A8_SNORM,
1069       DXGI_FORMAT_R16G16_FLOAT,
1070       DXGI_FORMAT_R16G16_UNORM,
1071       DXGI_FORMAT_R16G16_UINT,
1072       DXGI_FORMAT_R16G16_SNORM,
1073       DXGI_FORMAT_R16G16_SINT,
1074       DXGI_FORMAT_R8G8_UNORM,
1075       DXGI_FORMAT_R8G8_UINT,
1076       DXGI_FORMAT_R8G8_SNORM,
1077       DXGI_FORMAT_R8G8_SINT,
1078       DXGI_FORMAT_R16_UNORM,
1079       DXGI_FORMAT_R16_SNORM,
1080       DXGI_FORMAT_R8_SNORM,
1081    };
1082 
1083    for (unsigned i = 0; i < ARRAY_SIZE(additional_formats); ++i) {
1084       D3D12_FEATURE_DATA_FORMAT_SUPPORT support = { additional_formats[i] };
1085       if (FAILED(screen->dev->CheckFeatureSupport(D3D12_FEATURE_FORMAT_SUPPORT, &support, sizeof(support))) ||
1086          (support.Support1 & D3D12_FORMAT_SUPPORT1_TYPED_UNORDERED_ACCESS_VIEW) == D3D12_FORMAT_SUPPORT1_NONE ||
1087          (support.Support2 & (D3D12_FORMAT_SUPPORT2_UAV_TYPED_LOAD | D3D12_FORMAT_SUPPORT2_UAV_TYPED_STORE)) !=
1088             (D3D12_FORMAT_SUPPORT2_UAV_TYPED_LOAD | D3D12_FORMAT_SUPPORT2_UAV_TYPED_STORE))
1089          return false;
1090    }
1091 
1092    return true;
1093 }
1094 
1095 static void
d3d12_init_null_srvs(struct d3d12_screen * screen)1096 d3d12_init_null_srvs(struct d3d12_screen *screen)
1097 {
1098    for (unsigned i = 0; i < RESOURCE_DIMENSION_COUNT; ++i) {
1099       D3D12_SHADER_RESOURCE_VIEW_DESC srv = {};
1100 
1101       srv.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
1102       srv.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
1103       switch (i) {
1104       case RESOURCE_DIMENSION_BUFFER:
1105       case RESOURCE_DIMENSION_UNKNOWN:
1106          srv.ViewDimension = D3D12_SRV_DIMENSION_BUFFER;
1107          srv.Buffer.FirstElement = 0;
1108          srv.Buffer.NumElements = 0;
1109          srv.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_NONE;
1110          srv.Buffer.StructureByteStride = 0;
1111          break;
1112       case RESOURCE_DIMENSION_TEXTURE1D:
1113          srv.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1D;
1114          srv.Texture1D.MipLevels = 1;
1115          srv.Texture1D.MostDetailedMip = 0;
1116          srv.Texture1D.ResourceMinLODClamp = 0.0f;
1117          break;
1118       case RESOURCE_DIMENSION_TEXTURE1DARRAY:
1119          srv.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1DARRAY;
1120          srv.Texture1DArray.MipLevels = 1;
1121          srv.Texture1DArray.ArraySize = 1;
1122          srv.Texture1DArray.MostDetailedMip = 0;
1123          srv.Texture1DArray.FirstArraySlice = 0;
1124          srv.Texture1DArray.ResourceMinLODClamp = 0.0f;
1125          break;
1126       case RESOURCE_DIMENSION_TEXTURE2D:
1127          srv.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
1128          srv.Texture2D.MipLevels = 1;
1129          srv.Texture2D.MostDetailedMip = 0;
1130          srv.Texture2D.PlaneSlice = 0;
1131          srv.Texture2D.ResourceMinLODClamp = 0.0f;
1132          break;
1133       case RESOURCE_DIMENSION_TEXTURE2DARRAY:
1134          srv.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY;
1135          srv.Texture2DArray.MipLevels = 1;
1136          srv.Texture2DArray.ArraySize = 1;
1137          srv.Texture2DArray.MostDetailedMip = 0;
1138          srv.Texture2DArray.FirstArraySlice = 0;
1139          srv.Texture2DArray.PlaneSlice = 0;
1140          srv.Texture2DArray.ResourceMinLODClamp = 0.0f;
1141          break;
1142       case RESOURCE_DIMENSION_TEXTURE2DMS:
1143          srv.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DMS;
1144          break;
1145       case RESOURCE_DIMENSION_TEXTURE2DMSARRAY:
1146          srv.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY;
1147          srv.Texture2DMSArray.ArraySize = 1;
1148          srv.Texture2DMSArray.FirstArraySlice = 0;
1149          break;
1150       case RESOURCE_DIMENSION_TEXTURE3D:
1151          srv.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE3D;
1152          srv.Texture3D.MipLevels = 1;
1153          srv.Texture3D.MostDetailedMip = 0;
1154          srv.Texture3D.ResourceMinLODClamp = 0.0f;
1155          break;
1156       case RESOURCE_DIMENSION_TEXTURECUBE:
1157          srv.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE;
1158          srv.TextureCube.MipLevels = 1;
1159          srv.TextureCube.MostDetailedMip = 0;
1160          srv.TextureCube.ResourceMinLODClamp = 0.0f;
1161          break;
1162       case RESOURCE_DIMENSION_TEXTURECUBEARRAY:
1163          srv.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBEARRAY;
1164          srv.TextureCubeArray.MipLevels = 1;
1165          srv.TextureCubeArray.NumCubes = 1;
1166          srv.TextureCubeArray.MostDetailedMip = 0;
1167          srv.TextureCubeArray.First2DArrayFace = 0;
1168          srv.TextureCubeArray.ResourceMinLODClamp = 0.0f;
1169          break;
1170       }
1171 
1172       if (srv.ViewDimension != D3D12_SRV_DIMENSION_UNKNOWN)
1173       {
1174          d3d12_descriptor_pool_alloc_handle(screen->view_pool, &screen->null_srvs[i]);
1175          screen->dev->CreateShaderResourceView(NULL, &srv, screen->null_srvs[i].cpu_handle);
1176       }
1177    }
1178 }
1179 
1180 static void
d3d12_init_null_uavs(struct d3d12_screen * screen)1181 d3d12_init_null_uavs(struct d3d12_screen *screen)
1182 {
1183    for (unsigned i = 0; i < RESOURCE_DIMENSION_COUNT; ++i) {
1184       D3D12_UNORDERED_ACCESS_VIEW_DESC uav = {};
1185 
1186       uav.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
1187       switch (i) {
1188       case RESOURCE_DIMENSION_BUFFER:
1189       case RESOURCE_DIMENSION_UNKNOWN:
1190          uav.ViewDimension = D3D12_UAV_DIMENSION_BUFFER;
1191          uav.Buffer.FirstElement = 0;
1192          uav.Buffer.NumElements = 0;
1193          uav.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_NONE;
1194          uav.Buffer.StructureByteStride = 0;
1195          uav.Buffer.CounterOffsetInBytes = 0;
1196          break;
1197       case RESOURCE_DIMENSION_TEXTURE1D:
1198          uav.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE1D;
1199          uav.Texture1D.MipSlice = 0;
1200          break;
1201       case RESOURCE_DIMENSION_TEXTURE1DARRAY:
1202          uav.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE1DARRAY;
1203          uav.Texture1DArray.MipSlice = 0;
1204          uav.Texture1DArray.ArraySize = 1;
1205          uav.Texture1DArray.FirstArraySlice = 0;
1206          break;
1207       case RESOURCE_DIMENSION_TEXTURE2D:
1208          uav.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D;
1209          uav.Texture2D.MipSlice = 0;
1210          uav.Texture2D.PlaneSlice = 0;
1211          break;
1212       case RESOURCE_DIMENSION_TEXTURE2DARRAY:
1213       case RESOURCE_DIMENSION_TEXTURECUBE:
1214       case RESOURCE_DIMENSION_TEXTURECUBEARRAY:
1215          uav.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2DARRAY;
1216          uav.Texture2DArray.MipSlice = 0;
1217          uav.Texture2DArray.ArraySize = 1;
1218          uav.Texture2DArray.FirstArraySlice = 0;
1219          uav.Texture2DArray.PlaneSlice = 0;
1220          break;
1221       case RESOURCE_DIMENSION_TEXTURE2DMS:
1222       case RESOURCE_DIMENSION_TEXTURE2DMSARRAY:
1223          break;
1224       case RESOURCE_DIMENSION_TEXTURE3D:
1225          uav.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE3D;
1226          uav.Texture3D.MipSlice = 0;
1227          uav.Texture3D.FirstWSlice = 0;
1228          uav.Texture3D.WSize = 1;
1229          break;
1230       }
1231 
1232       if (uav.ViewDimension != D3D12_UAV_DIMENSION_UNKNOWN)
1233       {
1234          d3d12_descriptor_pool_alloc_handle(screen->view_pool, &screen->null_uavs[i]);
1235          screen->dev->CreateUnorderedAccessView(NULL, NULL, &uav, screen->null_uavs[i].cpu_handle);
1236       }
1237    }
1238 }
1239 
1240 static void
d3d12_init_null_rtv(struct d3d12_screen * screen)1241 d3d12_init_null_rtv(struct d3d12_screen *screen)
1242 {
1243    D3D12_RENDER_TARGET_VIEW_DESC rtv = {};
1244    rtv.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
1245    rtv.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
1246    rtv.Texture2D.MipSlice = 0;
1247    rtv.Texture2D.PlaneSlice = 0;
1248    d3d12_descriptor_pool_alloc_handle(screen->rtv_pool, &screen->null_rtv);
1249    screen->dev->CreateRenderTargetView(NULL, &rtv, screen->null_rtv.cpu_handle);
1250 }
1251 
1252 static void
d3d12_get_adapter_luid(struct pipe_screen * pscreen,char * luid)1253 d3d12_get_adapter_luid(struct pipe_screen *pscreen, char *luid)
1254 {
1255    struct d3d12_screen *screen = d3d12_screen(pscreen);
1256    memcpy(luid, &screen->adapter_luid, PIPE_LUID_SIZE);
1257 }
1258 
1259 static void
d3d12_get_device_uuid(struct pipe_screen * pscreen,char * uuid)1260 d3d12_get_device_uuid(struct pipe_screen *pscreen, char *uuid)
1261 {
1262    struct d3d12_screen *screen = d3d12_screen(pscreen);
1263    memcpy(uuid, &screen->device_uuid, PIPE_UUID_SIZE);
1264 }
1265 
1266 static void
d3d12_get_driver_uuid(struct pipe_screen * pscreen,char * uuid)1267 d3d12_get_driver_uuid(struct pipe_screen *pscreen, char *uuid)
1268 {
1269    struct d3d12_screen *screen = d3d12_screen(pscreen);
1270    memcpy(uuid, &screen->driver_uuid, PIPE_UUID_SIZE);
1271 }
1272 
1273 static uint32_t
d3d12_get_node_mask(struct pipe_screen * pscreen)1274 d3d12_get_node_mask(struct pipe_screen *pscreen)
1275 {
1276    /* This implementation doesn't support linked adapters */
1277    return 1;
1278 }
1279 
1280 static void
d3d12_create_fence_win32(struct pipe_screen * pscreen,struct pipe_fence_handle ** pfence,void * handle,const void * name,enum pipe_fd_type type)1281 d3d12_create_fence_win32(struct pipe_screen *pscreen, struct pipe_fence_handle **pfence, void *handle, const void *name, enum pipe_fd_type type)
1282 {
1283    d3d12_fence_reference((struct d3d12_fence **)pfence, nullptr);
1284    if(type == PIPE_FD_TYPE_TIMELINE_SEMAPHORE)
1285       *pfence = (struct pipe_fence_handle*) d3d12_open_fence(d3d12_screen(pscreen), handle, name);
1286 }
1287 
1288 static void
d3d12_set_fence_timeline_value(struct pipe_screen * pscreen,struct pipe_fence_handle * pfence,uint64_t value)1289 d3d12_set_fence_timeline_value(struct pipe_screen *pscreen, struct pipe_fence_handle *pfence, uint64_t value)
1290 {
1291    d3d12_fence(pfence)->value = value;
1292 }
1293 
1294 static uint32_t
d3d12_interop_query_device_info(struct pipe_screen * pscreen,uint32_t data_size,void * data)1295 d3d12_interop_query_device_info(struct pipe_screen *pscreen, uint32_t data_size, void *data)
1296 {
1297    if (data_size < sizeof(d3d12_interop_device_info) || !data)
1298       return 0;
1299    d3d12_interop_device_info *info = (d3d12_interop_device_info *)data;
1300    struct d3d12_screen *screen = d3d12_screen(pscreen);
1301 
1302    static_assert(sizeof(info->adapter_luid) == sizeof(screen->adapter_luid),
1303                  "Using uint64_t instead of Windows-specific type");
1304    memcpy(&info->adapter_luid, &screen->adapter_luid, sizeof(screen->adapter_luid));
1305    info->device = screen->dev;
1306    info->queue = screen->cmdqueue;
1307    return sizeof(*info);
1308 }
1309 
1310 static uint32_t
d3d12_interop_export_object(struct pipe_screen * pscreen,struct pipe_resource * res,uint32_t data_size,void * data,bool * need_export_dmabuf)1311 d3d12_interop_export_object(struct pipe_screen *pscreen, struct pipe_resource *res,
1312                               uint32_t data_size, void *data, bool *need_export_dmabuf)
1313 {
1314    if (data_size < sizeof(d3d12_interop_resource_info) || !data)
1315       return 0;
1316    d3d12_interop_resource_info *info = (d3d12_interop_resource_info *)data;
1317 
1318    info->resource = d3d12_resource_underlying(d3d12_resource(res), &info->buffer_offset);
1319    *need_export_dmabuf = false;
1320    return sizeof(*info);
1321 }
1322 
1323 static int
d3d12_screen_get_fd(struct pipe_screen * pscreen)1324 d3d12_screen_get_fd(struct pipe_screen *pscreen)
1325 {
1326    struct d3d12_screen *screen = d3d12_screen(pscreen);
1327    struct sw_winsys *winsys = screen->winsys;
1328 
1329    if (winsys->get_fd)
1330       return winsys->get_fd(winsys);
1331    else
1332       return -1;
1333 }
1334 
1335 #ifdef _WIN32
d3d12_fence_get_win32_handle(struct pipe_screen * pscreen,struct pipe_fence_handle * fence_handle,uint64_t * fence_value)1336 static void* d3d12_fence_get_win32_handle(struct pipe_screen *pscreen,
1337                                           struct pipe_fence_handle *fence_handle,
1338                                           uint64_t *fence_value)
1339 {
1340    struct d3d12_screen *screen = d3d12_screen(pscreen);
1341    struct d3d12_fence* fence = (struct d3d12_fence*) fence_handle;
1342    HANDLE shared_handle = nullptr;
1343    screen->dev->CreateSharedHandle(fence->cmdqueue_fence,
1344                                    NULL,
1345                                    GENERIC_ALL,
1346                                    NULL,
1347                                    &shared_handle);
1348    if(shared_handle)
1349       *fence_value = fence->value;
1350 
1351    return (void*) shared_handle;
1352 }
1353 #endif
1354 
1355 bool
d3d12_init_screen_base(struct d3d12_screen * screen,struct sw_winsys * winsys,LUID * adapter_luid)1356 d3d12_init_screen_base(struct d3d12_screen *screen, struct sw_winsys *winsys, LUID *adapter_luid)
1357 {
1358    glsl_type_singleton_init_or_ref();
1359    d3d12_debug = debug_get_option_d3d12_debug();
1360 
1361    screen->winsys = winsys;
1362    if (adapter_luid)
1363       screen->adapter_luid = *adapter_luid;
1364    mtx_init(&screen->descriptor_pool_mutex, mtx_plain);
1365    mtx_init(&screen->submit_mutex, mtx_plain);
1366 
1367    list_inithead(&screen->context_list);
1368    screen->context_id_count = 16;
1369 
1370    // Fill the array backwards, because we'll pop off the back to assign ids
1371    for (unsigned i = 0; i < 16; ++i)
1372       screen->context_id_list[i] = 15 - i;
1373 
1374 #ifdef HAVE_GALLIUM_D3D12_GRAPHICS
1375    d3d12_varying_cache_init(screen);
1376    mtx_init(&screen->varying_info_mutex, mtx_plain);
1377    screen->base.get_compiler_options = d3d12_get_compiler_options;
1378 #endif // HAVE_GALLIUM_D3D12_GRAPHICS
1379 
1380    slab_create_parent(&screen->transfer_pool, sizeof(struct d3d12_transfer), 16);
1381 
1382    screen->base.get_vendor = d3d12_get_vendor;
1383    screen->base.get_device_vendor = d3d12_get_device_vendor;
1384    screen->base.get_screen_fd = d3d12_screen_get_fd;
1385    screen->base.get_param = d3d12_get_param;
1386    screen->base.get_paramf = d3d12_get_paramf;
1387    screen->base.get_shader_param = d3d12_get_shader_param;
1388    screen->base.get_compute_param = d3d12_get_compute_param;
1389    screen->base.is_format_supported = d3d12_is_format_supported;
1390 
1391    screen->base.context_create = d3d12_context_create;
1392    screen->base.flush_frontbuffer = d3d12_flush_frontbuffer;
1393    screen->base.get_device_luid = d3d12_get_adapter_luid;
1394    screen->base.get_device_uuid = d3d12_get_device_uuid;
1395    screen->base.get_driver_uuid = d3d12_get_driver_uuid;
1396    screen->base.get_device_node_mask = d3d12_get_node_mask;
1397    screen->base.create_fence_win32 = d3d12_create_fence_win32;
1398    screen->base.set_fence_timeline_value = d3d12_set_fence_timeline_value;
1399    screen->base.interop_query_device_info = d3d12_interop_query_device_info;
1400    screen->base.interop_export_object = d3d12_interop_export_object;
1401 #ifdef _WIN32
1402    screen->base.fence_get_win32_handle = d3d12_fence_get_win32_handle;
1403 #endif
1404 
1405    screen->d3d12_mod = util_dl_open(
1406       UTIL_DL_PREFIX
1407 #ifdef _GAMING_XBOX_SCARLETT
1408       "d3d12_xs"
1409 #elif defined(_GAMING_XBOX)
1410       "d3d12_x"
1411 #else
1412       "d3d12"
1413 #endif
1414       UTIL_DL_EXT
1415    );
1416    if (!screen->d3d12_mod) {
1417       debug_printf("D3D12: failed to load D3D12.DLL\n");
1418       return false;
1419    }
1420    return true;
1421 }
1422 
1423 #ifdef _WIN32
1424 extern "C" IMAGE_DOS_HEADER __ImageBase;
1425 static const char *
try_find_d3d12core_next_to_self(char * path,size_t path_arr_size)1426 try_find_d3d12core_next_to_self(char *path, size_t path_arr_size)
1427 {
1428    uint32_t path_size = GetModuleFileNameA((HINSTANCE)&__ImageBase,
1429                                            path, path_arr_size);
1430    if (!path_arr_size || path_size == path_arr_size) {
1431       debug_printf("Unable to get path to self\n");
1432       return nullptr;
1433    }
1434 
1435    auto last_slash = strrchr(path, '\\');
1436    if (!last_slash) {
1437       debug_printf("Unable to get path to self\n");
1438       return nullptr;
1439    }
1440 
1441    *(last_slash + 1) = '\0';
1442    if (strcat_s(path, path_arr_size, "D3D12Core.dll") != 0) {
1443       debug_printf("Unable to get path to D3D12Core.dll next to self\n");
1444       return nullptr;
1445    }
1446 
1447    if (GetFileAttributesA(path) == INVALID_FILE_ATTRIBUTES) {
1448       debug_printf("No D3D12Core.dll exists next to self\n");
1449       return nullptr;
1450    }
1451 
1452    *(last_slash + 1) = '\0';
1453    return path;
1454 }
1455 #endif
1456 
1457 #ifndef _GAMING_XBOX
1458 static ID3D12DeviceFactory *
try_create_device_factory(util_dl_library * d3d12_mod)1459 try_create_device_factory(util_dl_library *d3d12_mod)
1460 {
1461 #if defined(_WIN32) && defined(_WIN64)
1462    if (d3d12_debug & D3D12_DEBUG_PIX) {
1463       if (GetModuleHandleW(L"WinPixGpuCapturer.dll") == nullptr) {
1464          LPWSTR program_files_path = nullptr;
1465          SHGetKnownFolderPath(FOLDERID_ProgramFiles, KF_FLAG_DEFAULT, NULL, &program_files_path);
1466 
1467          auto pix_installation_path = std::filesystem::path(program_files_path) / "Microsoft PIX";
1468          std::wstring newest_version;
1469          for (auto const &directory : std::filesystem::directory_iterator(pix_installation_path)) {
1470             if (directory.is_directory() &&
1471                 (newest_version.empty() || newest_version < directory.path().filename().c_str()))
1472                newest_version = directory.path().filename().wstring();
1473          }
1474          if (newest_version.empty()) {
1475             debug_printf("D3D12: Failed to find any PIX installations\n");
1476          }
1477          else if (!LoadLibraryW((pix_installation_path / newest_version / L"WinPixGpuCapturer.dll").c_str()) &&
1478                   // Try the x64 subdirectory for x64-on-arm64
1479                   !LoadLibraryW((pix_installation_path / newest_version / L"x64/WinPixGpuCapturer.dll").c_str())) {
1480             debug_printf("D3D12: Failed to load WinPixGpuCapturer.dll from %S\n", newest_version.c_str());
1481          }
1482       }
1483    }
1484 #endif
1485 
1486    if (d3d12_debug & D3D12_DEBUG_SINGLETON)
1487       return nullptr;
1488 
1489    /* A device factory allows us to isolate things like debug layer enablement from other callers,
1490     * and can potentially even refer to a different D3D12 redist implementation from others.
1491     */
1492    ID3D12DeviceFactory *factory = nullptr;
1493 
1494    typedef HRESULT(WINAPI *PFN_D3D12_GET_INTERFACE)(REFCLSID clsid, REFIID riid, void **ppFactory);
1495    PFN_D3D12_GET_INTERFACE D3D12GetInterface = (PFN_D3D12_GET_INTERFACE)util_dl_get_proc_address(d3d12_mod, "D3D12GetInterface");
1496    if (!D3D12GetInterface) {
1497       debug_printf("D3D12: Failed to retrieve D3D12GetInterface");
1498       return nullptr;
1499    }
1500 
1501 #ifdef _WIN32
1502    /* First, try to create a device factory from a DLL-parallel D3D12Core.dll */
1503    ID3D12SDKConfiguration *sdk_config = nullptr;
1504    if (SUCCEEDED(D3D12GetInterface(CLSID_D3D12SDKConfiguration, IID_PPV_ARGS(&sdk_config)))) {
1505       ID3D12SDKConfiguration1 *sdk_config1 = nullptr;
1506       if (SUCCEEDED(sdk_config->QueryInterface(&sdk_config1))) {
1507          char self_path[MAX_PATH];
1508          const char *d3d12core_path = try_find_d3d12core_next_to_self(self_path, sizeof(self_path));
1509          if (d3d12core_path) {
1510             if (SUCCEEDED(sdk_config1->CreateDeviceFactory(D3D12_PREVIEW_SDK_VERSION, d3d12core_path, IID_PPV_ARGS(&factory))) ||
1511                 SUCCEEDED(sdk_config1->CreateDeviceFactory(D3D12_SDK_VERSION, d3d12core_path, IID_PPV_ARGS(&factory)))) {
1512                sdk_config->Release();
1513                sdk_config1->Release();
1514                return factory;
1515             }
1516          }
1517 
1518          /* Nope, seems we don't have a matching D3D12Core.dll next to ourselves */
1519          sdk_config1->Release();
1520       }
1521 
1522       /* It's possible there's a D3D12Core.dll next to the .exe, for development/testing purposes. If so, we'll be notified
1523        * by environment variables what the relative path is and the version to use.
1524        */
1525       const char *d3d12core_relative_path = getenv("D3D12_AGILITY_RELATIVE_PATH");
1526       const char *d3d12core_sdk_version = getenv("D3D12_AGILITY_SDK_VERSION");
1527       if (d3d12core_relative_path && d3d12core_sdk_version) {
1528          (void)sdk_config->SetSDKVersion(atoi(d3d12core_sdk_version), d3d12core_relative_path);
1529       }
1530       sdk_config->Release();
1531    }
1532 #endif
1533 
1534    (void)D3D12GetInterface(CLSID_D3D12DeviceFactory, IID_PPV_ARGS(&factory));
1535    return factory;
1536 }
1537 #endif
1538 
1539 bool
d3d12_init_screen(struct d3d12_screen * screen,IUnknown * adapter)1540 d3d12_init_screen(struct d3d12_screen *screen, IUnknown *adapter)
1541 {
1542    assert(screen->base.destroy != nullptr);
1543 
1544    // Device can be imported with d3d12_create_dxcore_screen_from_d3d12_device
1545    if (!screen->dev) {
1546 #ifndef _GAMING_XBOX
1547       ID3D12DeviceFactory *factory = try_create_device_factory(screen->d3d12_mod);
1548 
1549 #if !MESA_DEBUG
1550       if (d3d12_debug & D3D12_DEBUG_DEBUG_LAYER)
1551 #endif
1552          enable_d3d12_debug_layer(screen->d3d12_mod, factory);
1553 
1554       if (d3d12_debug & D3D12_DEBUG_GPU_VALIDATOR)
1555          enable_gpu_validation(screen->d3d12_mod, factory);
1556 
1557       screen->dev = create_device(screen->d3d12_mod, adapter, factory);
1558 
1559       if (factory)
1560          factory->Release();
1561 #else
1562       screen->dev = create_device(screen->d3d12_mod, adapter);
1563 #endif
1564 
1565       if (!screen->dev) {
1566          debug_printf("D3D12: failed to create device\n");
1567          return false;
1568       }
1569    }
1570    screen->adapter_luid = GetAdapterLuid(screen->dev);
1571 
1572 #ifndef _GAMING_XBOX
1573    ID3D12InfoQueue *info_queue;
1574    if (SUCCEEDED(screen->dev->QueryInterface(IID_PPV_ARGS(&info_queue)))) {
1575       D3D12_MESSAGE_SEVERITY severities[] = {
1576          D3D12_MESSAGE_SEVERITY_INFO,
1577          D3D12_MESSAGE_SEVERITY_WARNING,
1578       };
1579 
1580       D3D12_MESSAGE_ID msg_ids[] = {
1581          D3D12_MESSAGE_ID_CLEARRENDERTARGETVIEW_MISMATCHINGCLEARVALUE,
1582       };
1583 
1584       D3D12_INFO_QUEUE_FILTER NewFilter = {};
1585       NewFilter.DenyList.NumSeverities = ARRAY_SIZE(severities);
1586       NewFilter.DenyList.pSeverityList = severities;
1587       NewFilter.DenyList.NumIDs = ARRAY_SIZE(msg_ids);
1588       NewFilter.DenyList.pIDList = msg_ids;
1589 
1590       info_queue->PushStorageFilter(&NewFilter);
1591       info_queue->Release();
1592    }
1593 #endif /* !_GAMING_XBOX */
1594 
1595    if (FAILED(screen->dev->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS,
1596                                                &screen->opts,
1597                                                sizeof(screen->opts)))) {
1598       debug_printf("D3D12: failed to get device options\n");
1599       return false;
1600    }
1601    if (FAILED(screen->dev->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS1,
1602                                                &screen->opts1,
1603                                                sizeof(screen->opts1)))) {
1604       debug_printf("D3D12: failed to get device options\n");
1605       return false;
1606    }
1607    if (FAILED(screen->dev->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS2,
1608                                                &screen->opts2,
1609                                                sizeof(screen->opts2)))) {
1610       debug_printf("D3D12: failed to get device options\n");
1611       return false;
1612    }
1613    if (FAILED(screen->dev->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS3,
1614                                                &screen->opts3,
1615                                                sizeof(screen->opts3)))) {
1616       debug_printf("D3D12: failed to get device options\n");
1617       return false;
1618    }
1619    if (FAILED(screen->dev->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS4,
1620                                                &screen->opts4,
1621                                                sizeof(screen->opts4)))) {
1622       debug_printf("D3D12: failed to get device options\n");
1623       return false;
1624    }
1625    screen->dev->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS12, &screen->opts12, sizeof(screen->opts12));
1626    screen->dev->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS14, &screen->opts14, sizeof(screen->opts14));
1627 #ifndef _GAMING_XBOX
1628    screen->dev->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS19, &screen->opts19, sizeof(screen->opts19));
1629 #endif
1630 
1631    screen->architecture.NodeIndex = 0;
1632    if (FAILED(screen->dev->CheckFeatureSupport(D3D12_FEATURE_ARCHITECTURE,
1633                                                &screen->architecture,
1634                                                sizeof(screen->architecture)))) {
1635       debug_printf("D3D12: failed to get device architecture\n");
1636       return false;
1637    }
1638 
1639    D3D12_FEATURE_DATA_FEATURE_LEVELS feature_levels;
1640    static const D3D_FEATURE_LEVEL levels[] = {
1641 #ifndef _GAMING_XBOX
1642       D3D_FEATURE_LEVEL_1_0_GENERIC,
1643       D3D_FEATURE_LEVEL_1_0_CORE,
1644 #endif
1645       D3D_FEATURE_LEVEL_11_0,
1646       D3D_FEATURE_LEVEL_11_1,
1647       D3D_FEATURE_LEVEL_12_0,
1648       D3D_FEATURE_LEVEL_12_1,
1649    };
1650    feature_levels.NumFeatureLevels = ARRAY_SIZE(levels);
1651    feature_levels.pFeatureLevelsRequested = levels;
1652    if (FAILED(screen->dev->CheckFeatureSupport(D3D12_FEATURE_FEATURE_LEVELS,
1653                                                &feature_levels,
1654                                                sizeof(feature_levels)))) {
1655       debug_printf("D3D12: failed to get device feature levels\n");
1656       return false;
1657    }
1658 
1659 #ifdef HAVE_GALLIUM_D3D12_GRAPHICS
1660    screen->max_feature_level = feature_levels.MaxSupportedFeatureLevel;
1661 #else
1662    screen->max_feature_level = D3D_FEATURE_LEVEL_1_0_GENERIC;
1663 #endif // HAVE_GALLIUM_D3D12_GRAPHICS
1664 
1665    screen->queue_type = (screen->max_feature_level >= D3D_FEATURE_LEVEL_11_0) ? D3D12_COMMAND_LIST_TYPE_DIRECT : D3D12_COMMAND_LIST_TYPE_COMPUTE;
1666 
1667 #ifdef HAVE_GALLIUM_D3D12_GRAPHICS
1668    if (screen->max_feature_level >= D3D_FEATURE_LEVEL_11_0) {
1669       static const D3D_SHADER_MODEL valid_shader_models[] = {
1670 #ifndef _GAMING_XBOX
1671          D3D_SHADER_MODEL_6_8,
1672 #endif
1673          D3D_SHADER_MODEL_6_7, D3D_SHADER_MODEL_6_6, D3D_SHADER_MODEL_6_5, D3D_SHADER_MODEL_6_4,
1674          D3D_SHADER_MODEL_6_3, D3D_SHADER_MODEL_6_2, D3D_SHADER_MODEL_6_1, D3D_SHADER_MODEL_6_0,
1675       };
1676       for (UINT i = 0; i < ARRAY_SIZE(valid_shader_models); ++i) {
1677          D3D12_FEATURE_DATA_SHADER_MODEL shader_model = { valid_shader_models[i] };
1678          if (SUCCEEDED(screen->dev->CheckFeatureSupport(D3D12_FEATURE_SHADER_MODEL, &shader_model, sizeof(shader_model)))) {
1679             static_assert(D3D_SHADER_MODEL_6_0 == 0x60 && SHADER_MODEL_6_0 == 0x60000, "Validating math below");
1680 #ifndef _GAMING_XBOX
1681             static_assert(D3D_SHADER_MODEL_6_8 == 0x68 && SHADER_MODEL_6_8 == 0x60008, "Validating math below");
1682 #endif
1683             screen->max_shader_model = static_cast<dxil_shader_model>(((shader_model.HighestShaderModel & 0xf0) << 12) |
1684                                                                      (shader_model.HighestShaderModel & 0xf));
1685             break;
1686          }
1687       }
1688    }
1689 #endif // HAVE_GALLIUM_D3D12_GRAPHICS
1690 
1691    D3D12_COMMAND_QUEUE_DESC queue_desc;
1692    queue_desc.Type = screen->queue_type;
1693    queue_desc.Priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL;
1694    queue_desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
1695    queue_desc.NodeMask = 0;
1696 
1697 #ifndef _GAMING_XBOX
1698    ID3D12Device9 *device9;
1699    if (SUCCEEDED(screen->dev->QueryInterface(&device9))) {
1700       if (FAILED(device9->CreateCommandQueue1(&queue_desc, OpenGLOn12CreatorID,
1701                                               IID_PPV_ARGS(&screen->cmdqueue))))
1702          return false;
1703       device9->Release();
1704    } else
1705 #endif
1706    {
1707       if (FAILED(screen->dev->CreateCommandQueue(&queue_desc,
1708                                                  IID_PPV_ARGS(&screen->cmdqueue))))
1709          return false;
1710    }
1711 
1712    if (FAILED(screen->dev->CreateFence(0, D3D12_FENCE_FLAG_SHARED, IID_PPV_ARGS(&screen->fence))))
1713       return false;
1714 
1715    if (!d3d12_init_residency(screen))
1716       return false;
1717 
1718    UINT64 timestamp_freq;
1719    if (FAILED(screen->cmdqueue->GetTimestampFrequency(&timestamp_freq)))
1720        timestamp_freq = 10000000;
1721    screen->timestamp_multiplier = 1000000000.0f / timestamp_freq;
1722 
1723    d3d12_screen_fence_init(&screen->base);
1724    d3d12_screen_resource_init(&screen->base);
1725 #ifdef HAVE_GALLIUM_D3D12_VIDEO
1726    d3d12_screen_video_init(&screen->base);
1727 #endif
1728 
1729    struct pb_desc desc;
1730    desc.alignment = D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT;
1731    desc.usage = (pb_usage_flags)(PB_USAGE_CPU_WRITE | PB_USAGE_GPU_READ);
1732 
1733    screen->bufmgr = d3d12_bufmgr_create(screen);
1734    if (!screen->bufmgr)
1735       return false;
1736 
1737    screen->cache_bufmgr = pb_cache_manager_create(screen->bufmgr, 0xfffff, 2, 0, 512 * 1024 * 1024);
1738    if (!screen->cache_bufmgr)
1739       return false;
1740 
1741    screen->slab_cache_bufmgr = pb_cache_manager_create(screen->bufmgr, 0xfffff, 2, 0, 512 * 1024 * 1024);
1742    if (!screen->slab_cache_bufmgr)
1743       return false;
1744 
1745    screen->slab_bufmgr = pb_slab_range_manager_create(screen->slab_cache_bufmgr, 16,
1746                                                       D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT,
1747                                                       D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT,
1748                                                       &desc);
1749    if (!screen->slab_bufmgr)
1750       return false;
1751 
1752    screen->readback_slab_cache_bufmgr = pb_cache_manager_create(screen->bufmgr, 0xfffff, 2, 0, 512 * 1024 * 1024);
1753    if (!screen->readback_slab_cache_bufmgr)
1754       return false;
1755 
1756    desc.usage = (pb_usage_flags)(PB_USAGE_CPU_READ_WRITE | PB_USAGE_GPU_WRITE);
1757    screen->readback_slab_bufmgr = pb_slab_range_manager_create(screen->readback_slab_cache_bufmgr, 16,
1758                                                                D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT,
1759                                                                D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT,
1760                                                                &desc);
1761    if (!screen->readback_slab_bufmgr)
1762       return false;
1763 
1764 #ifdef HAVE_GALLIUM_D3D12_GRAPHICS
1765    if (screen->max_feature_level >= D3D_FEATURE_LEVEL_11_0) {
1766       screen->rtv_pool = d3d12_descriptor_pool_new(screen,
1767                                                    D3D12_DESCRIPTOR_HEAP_TYPE_RTV,
1768                                                    64);
1769       screen->dsv_pool = d3d12_descriptor_pool_new(screen,
1770                                                    D3D12_DESCRIPTOR_HEAP_TYPE_DSV,
1771                                                    64);
1772       screen->view_pool = d3d12_descriptor_pool_new(screen,
1773                                                    D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
1774                                                    1024);
1775       if (!screen->rtv_pool || !screen->dsv_pool || !screen->view_pool)
1776          return false;
1777 
1778       d3d12_init_null_srvs(screen);
1779       d3d12_init_null_uavs(screen);
1780       d3d12_init_null_rtv(screen);
1781 
1782       screen->have_load_at_vertex = can_attribute_at_vertex(screen);
1783       screen->support_shader_images = can_shader_image_load_all_formats(screen);
1784       static constexpr uint64_t known_good_warp_version = 10ull << 48 | 22000ull << 16;
1785       bool warp_with_broken_int64 =
1786          (screen->vendor_id == HW_VENDOR_MICROSOFT && screen->driver_version < known_good_warp_version);
1787       unsigned supported_int_sizes = 32 | (screen->opts1.Int64ShaderOps && !warp_with_broken_int64 ? 64 : 0);
1788       unsigned supported_float_sizes = 32 | (screen->opts.DoublePrecisionFloatShaderOps ? 64 : 0);
1789       dxil_get_nir_compiler_options(&screen->nir_options,
1790                                     screen->max_shader_model,
1791                                     supported_int_sizes,
1792                                     supported_float_sizes);
1793    }
1794 #endif // HAVE_GALLIUM_D3D12_GRAPHICS
1795 
1796 #ifndef _GAMING_XBOX
1797       ID3D12Device8 *dev8;
1798       if (SUCCEEDED(screen->dev->QueryInterface(&dev8))) {
1799          dev8->Release();
1800          screen->support_create_not_resident = true;
1801       }
1802       screen->dev->QueryInterface(&screen->dev10);
1803 #endif
1804 
1805    const char *mesa_version = "Mesa " PACKAGE_VERSION MESA_GIT_SHA1;
1806    struct mesa_sha1 sha1_ctx;
1807    uint8_t sha1[SHA1_DIGEST_LENGTH];
1808    STATIC_ASSERT(PIPE_UUID_SIZE <= sizeof(sha1));
1809 
1810    /* The driver UUID is used for determining sharability of images and memory
1811     * between two instances in separate processes.  People who want to
1812     * share memory need to also check the device UUID or LUID so all this
1813     * needs to be is the build-id.
1814     */
1815    _mesa_sha1_compute(mesa_version, strlen(mesa_version), sha1);
1816    memcpy(screen->driver_uuid, sha1, PIPE_UUID_SIZE);
1817 
1818    /* The device UUID uniquely identifies the given device within the machine. */
1819    _mesa_sha1_init(&sha1_ctx);
1820    _mesa_sha1_update(&sha1_ctx, &screen->vendor_id, sizeof(screen->vendor_id));
1821    _mesa_sha1_update(&sha1_ctx, &screen->device_id, sizeof(screen->device_id));
1822    _mesa_sha1_update(&sha1_ctx, &screen->subsys_id, sizeof(screen->subsys_id));
1823    _mesa_sha1_update(&sha1_ctx, &screen->revision, sizeof(screen->revision));
1824    _mesa_sha1_final(&sha1_ctx, sha1);
1825    memcpy(screen->device_uuid, sha1, PIPE_UUID_SIZE);
1826 
1827    return true;
1828 }
1829