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