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 #include "d3d12_format.h"
32 #include "d3d12_residency.h"
33 #include "d3d12_resource.h"
34 #include "d3d12_nir_passes.h"
35 
36 #include "pipebuffer/pb_bufmgr.h"
37 #include "util/debug.h"
38 #include "util/u_math.h"
39 #include "util/u_memory.h"
40 #include "util/u_screen.h"
41 #include "util/u_dl.h"
42 
43 #include "nir.h"
44 #include "frontend/sw_winsys.h"
45 
46 #include "nir_to_dxil.h"
47 
48 #include <directx/d3d12sdklayers.h>
49 
50 #include <dxguids/dxguids.h>
51 static GUID OpenGLOn12CreatorID = { 0x6bb3cd34, 0x0d19, 0x45ab, 0x97, 0xed, 0xd7, 0x20, 0xba, 0x3d, 0xfc, 0x80 };
52 
53 static const struct debug_named_value
54 d3d12_debug_options[] = {
55    { "verbose",      D3D12_DEBUG_VERBOSE,       NULL },
56    { "blit",         D3D12_DEBUG_BLIT,          "Trace blit and copy resource calls" },
57    { "experimental", D3D12_DEBUG_EXPERIMENTAL,  "Enable experimental shader models feature" },
58    { "dxil",         D3D12_DEBUG_DXIL,          "Dump DXIL during program compile" },
59    { "disass",       D3D12_DEBUG_DISASS,        "Dump disassambly of created DXIL shader" },
60    { "res",          D3D12_DEBUG_RESOURCE,      "Debug resources" },
61    { "debuglayer",   D3D12_DEBUG_DEBUG_LAYER,   "Enable debug layer" },
62    { "gpuvalidator", D3D12_DEBUG_GPU_VALIDATOR, "Enable GPU validator" },
63    DEBUG_NAMED_VALUE_END
64 };
65 
66 DEBUG_GET_ONCE_FLAGS_OPTION(d3d12_debug, "D3D12_DEBUG", d3d12_debug_options, 0)
67 
68 uint32_t
69 d3d12_debug;
70 
71 enum {
72     HW_VENDOR_AMD                   = 0x1002,
73     HW_VENDOR_INTEL                 = 0x8086,
74     HW_VENDOR_MICROSOFT             = 0x1414,
75     HW_VENDOR_NVIDIA                = 0x10de,
76 };
77 
78 static const char *
d3d12_get_vendor(struct pipe_screen * pscreen)79 d3d12_get_vendor(struct pipe_screen *pscreen)
80 {
81    return "Microsoft Corporation";
82 }
83 
84 static const char *
d3d12_get_device_vendor(struct pipe_screen * pscreen)85 d3d12_get_device_vendor(struct pipe_screen *pscreen)
86 {
87    struct d3d12_screen* screen = d3d12_screen(pscreen);
88 
89    switch (screen->vendor_id) {
90    case HW_VENDOR_MICROSOFT:
91       return "Microsoft";
92    case HW_VENDOR_AMD:
93       return "AMD";
94    case HW_VENDOR_NVIDIA:
95       return "NVIDIA";
96    case HW_VENDOR_INTEL:
97       return "Intel";
98    default:
99       return "Unknown";
100    }
101 }
102 
103 static int
d3d12_get_video_mem(struct pipe_screen * pscreen)104 d3d12_get_video_mem(struct pipe_screen *pscreen)
105 {
106    struct d3d12_screen* screen = d3d12_screen(pscreen);
107 
108    return screen->memory_size_megabytes;
109 }
110 
111 static int
d3d12_get_param(struct pipe_screen * pscreen,enum pipe_cap param)112 d3d12_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
113 {
114    struct d3d12_screen *screen = d3d12_screen(pscreen);
115 
116    switch (param) {
117    case PIPE_CAP_NPOT_TEXTURES:
118       return 1;
119 
120    case PIPE_CAP_MAX_DUAL_SOURCE_RENDER_TARGETS:
121       /* D3D12 only supports dual-source blending for a single
122        * render-target. From the D3D11 functional spec (which also defines
123        * this for D3D12):
124        *
125        * "When Dual Source Color Blending is enabled, the Pixel Shader must
126        *  have only a single RenderTarget bound, at slot 0, and must output
127        *  both o0 and o1. Writing to other outputs (o2, o3 etc.) produces
128        *  undefined results for the corresponding RenderTargets, if bound
129        *  illegally."
130        *
131        * Source: https://microsoft.github.io/DirectX-Specs/d3d/archive/D3D11_3_FunctionalSpec.htm#17.6%20Dual%20Source%20Color%20Blending
132        */
133       return 1;
134 
135    case PIPE_CAP_ANISOTROPIC_FILTER:
136       return 1;
137 
138    case PIPE_CAP_MAX_RENDER_TARGETS:
139       return D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT;
140 
141    case PIPE_CAP_TEXTURE_SWIZZLE:
142       return 1;
143 
144    case PIPE_CAP_MAX_TEXTURE_2D_SIZE:
145       return D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION;
146 
147    case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
148       return 11; // D3D12_REQ_TEXTURE3D_U_V_OR_W_DIMENSION == 2^10
149 
150    case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
151       return D3D12_REQ_MIP_LEVELS;
152 
153    case PIPE_CAP_PRIMITIVE_RESTART:
154    case PIPE_CAP_INDEP_BLEND_ENABLE:
155    case PIPE_CAP_INDEP_BLEND_FUNC:
156    case PIPE_CAP_FRAGMENT_SHADER_TEXTURE_LOD:
157    case PIPE_CAP_FRAGMENT_SHADER_DERIVATIVES:
158    case PIPE_CAP_VERTEX_SHADER_SATURATE:
159    case PIPE_CAP_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION:
160    case PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY:
161    case PIPE_CAP_RGB_OVERRIDE_DST_ALPHA_BLEND:
162    case PIPE_CAP_MIXED_COLOR_DEPTH_BITS:
163       return 1;
164 
165    /* We need to do some lowering that requires a link to the sampler */
166    case PIPE_CAP_NIR_SAMPLERS_AS_DEREF:
167       return 1;
168 
169    case PIPE_CAP_NIR_IMAGES_AS_DEREF:
170       return 1;
171 
172    case PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS:
173       /* Divide by 6 because this also applies to cubemaps */
174       return D3D12_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION / 6;
175 
176    case PIPE_CAP_DEPTH_CLIP_DISABLE:
177       return 1;
178 
179    case PIPE_CAP_TGSI_TEXCOORD:
180       return 1;
181 
182    case PIPE_CAP_MIXED_COLORBUFFER_FORMATS:
183       return 1;
184 
185    case PIPE_CAP_VERTEX_COLOR_UNCLAMPED:
186       return 1;
187 
188    case PIPE_CAP_GLSL_FEATURE_LEVEL:
189       return 420;
190    case PIPE_CAP_GLSL_FEATURE_LEVEL_COMPATIBILITY:
191       return 420;
192    case PIPE_CAP_ESSL_FEATURE_LEVEL:
193       return 310;
194 
195    case PIPE_CAP_COMPUTE:
196       return 1;
197 
198    case PIPE_CAP_TEXTURE_MULTISAMPLE:
199       return 1;
200 
201    case PIPE_CAP_CUBE_MAP_ARRAY:
202       return 1;
203 
204    case PIPE_CAP_TEXTURE_BUFFER_OBJECTS:
205       return 1;
206 
207    case PIPE_CAP_TEXTURE_TRANSFER_MODES:
208       return 0; /* unsure */
209 
210    case PIPE_CAP_ENDIANNESS:
211       return PIPE_ENDIAN_NATIVE; /* unsure */
212 
213    case PIPE_CAP_MAX_VIEWPORTS:
214       return D3D12_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE;
215 
216    case PIPE_CAP_MIXED_FRAMEBUFFER_SIZES:
217       return 1;
218 
219    case PIPE_CAP_MAX_TEXTURE_GATHER_COMPONENTS:
220       return 4;
221 
222    case PIPE_CAP_FS_COORD_PIXEL_CENTER_HALF_INTEGER:
223    case PIPE_CAP_FS_COORD_ORIGIN_UPPER_LEFT:
224       return 1;
225 
226    case PIPE_CAP_FS_FACE_IS_INTEGER_SYSVAL:
227       return 1;
228 
229    case PIPE_CAP_ACCELERATED:
230       return 1;
231 
232    case PIPE_CAP_VIDEO_MEMORY:
233       return d3d12_get_video_mem(pscreen);
234 
235    case PIPE_CAP_UMA:
236       return screen->architecture.UMA;
237 
238    case PIPE_CAP_MAX_VERTEX_ATTRIB_STRIDE:
239       return 2048; /* FIXME: no clue how to query this */
240 
241    case PIPE_CAP_TEXTURE_FLOAT_LINEAR:
242    case PIPE_CAP_TEXTURE_HALF_FLOAT_LINEAR:
243       return 1;
244 
245    case PIPE_CAP_SHADER_BUFFER_OFFSET_ALIGNMENT:
246       return D3D12_RAW_UAV_SRV_BYTE_ALIGNMENT;
247 
248    case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT:
249       return D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT;
250 
251    case PIPE_CAP_PCI_GROUP:
252    case PIPE_CAP_PCI_BUS:
253    case PIPE_CAP_PCI_DEVICE:
254    case PIPE_CAP_PCI_FUNCTION:
255       return 0; /* TODO: figure these out */
256 
257    case PIPE_CAP_GLSL_OPTIMIZE_CONSERVATIVELY:
258       return 0; /* not sure */
259 
260    case PIPE_CAP_FLATSHADE:
261    case PIPE_CAP_ALPHA_TEST:
262    case PIPE_CAP_TWO_SIDED_COLOR:
263    case PIPE_CAP_CLIP_PLANES:
264       return 0;
265 
266    case PIPE_CAP_SHADER_STENCIL_EXPORT:
267       return screen->opts.PSSpecifiedStencilRefSupported;
268 
269    case PIPE_CAP_SEAMLESS_CUBE_MAP:
270    case PIPE_CAP_TEXTURE_QUERY_LOD:
271    case PIPE_CAP_VS_INSTANCEID:
272    case PIPE_CAP_TGSI_TEX_TXF_LZ:
273    case PIPE_CAP_OCCLUSION_QUERY:
274    case PIPE_CAP_POINT_SPRITE:
275    case PIPE_CAP_VIEWPORT_TRANSFORM_LOWERED:
276    case PIPE_CAP_PSIZ_CLAMPED:
277    case PIPE_CAP_BLEND_EQUATION_SEPARATE:
278    case PIPE_CAP_CONDITIONAL_RENDER:
279    case PIPE_CAP_CONDITIONAL_RENDER_INVERTED:
280    case PIPE_CAP_QUERY_TIMESTAMP:
281    case PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR:
282    case PIPE_CAP_VERTEX_ELEMENT_SRC_OFFSET_4BYTE_ALIGNED_ONLY:
283    case PIPE_CAP_IMAGE_STORE_FORMATTED:
284    case PIPE_CAP_GLSL_TESS_LEVELS_AS_INPUTS:
285       return 1;
286 
287    case PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS:
288       return D3D12_SO_BUFFER_SLOT_COUNT;
289 
290    case PIPE_CAP_MAX_STREAM_OUTPUT_SEPARATE_COMPONENTS:
291    case PIPE_CAP_MAX_STREAM_OUTPUT_INTERLEAVED_COMPONENTS:
292       return D3D12_SO_OUTPUT_COMPONENT_COUNT;
293 
294    /* Geometry shader output. */
295    case PIPE_CAP_MAX_GEOMETRY_OUTPUT_VERTICES:
296       return D3D12_GS_MAX_OUTPUT_VERTEX_COUNT_ACROSS_INSTANCES;
297    case PIPE_CAP_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS:
298       return D3D12_REQ_GS_INVOCATION_32BIT_OUTPUT_COMPONENT_LIMIT;
299 
300    case PIPE_CAP_MAX_VARYINGS:
301       /* Subtract one so that implicit position can be added */
302       return D3D12_PS_INPUT_REGISTER_COUNT - 1;
303 
304    case PIPE_CAP_NIR_COMPACT_ARRAYS:
305       return 1;
306 
307    case PIPE_CAP_MAX_COMBINED_SHADER_OUTPUT_RESOURCES:
308       if (screen->max_feature_level <= D3D_FEATURE_LEVEL_11_0)
309          return D3D12_PS_CS_UAV_REGISTER_COUNT;
310       if (screen->opts.ResourceBindingTier <= D3D12_RESOURCE_BINDING_TIER_2)
311          return D3D12_UAV_SLOT_COUNT;
312       return 0;
313 
314    case PIPE_CAP_START_INSTANCE:
315    case PIPE_CAP_DRAW_PARAMETERS:
316    case PIPE_CAP_DRAW_INDIRECT:
317    case PIPE_CAP_MULTI_DRAW_INDIRECT:
318    case PIPE_CAP_MULTI_DRAW_INDIRECT_PARAMS:
319    case PIPE_CAP_FRAMEBUFFER_NO_ATTACHMENT:
320    case PIPE_CAP_SAMPLE_SHADING:
321    case PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME:
322    case PIPE_CAP_STREAM_OUTPUT_INTERLEAVE_BUFFERS:
323    case PIPE_CAP_INT64:
324    case PIPE_CAP_INT64_DIVMOD:
325    case PIPE_CAP_DOUBLES:
326       return 1;
327 
328    case PIPE_CAP_MAX_VERTEX_STREAMS:
329       return D3D12_SO_BUFFER_SLOT_COUNT;
330 
331    case PIPE_CAP_MAX_SHADER_PATCH_VARYINGS:
332       /* This is asking about varyings, not total registers, so remove the 2 tess factor registers. */
333       return D3D12_HS_OUTPUT_PATCH_CONSTANT_REGISTER_COUNT - 2;
334 
335    default:
336       return u_pipe_screen_get_param_defaults(pscreen, param);
337    }
338 }
339 
340 static float
d3d12_get_paramf(struct pipe_screen * pscreen,enum pipe_capf param)341 d3d12_get_paramf(struct pipe_screen *pscreen, enum pipe_capf param)
342 {
343    switch (param) {
344    case PIPE_CAPF_MIN_LINE_WIDTH:
345    case PIPE_CAPF_MIN_LINE_WIDTH_AA:
346    case PIPE_CAPF_MIN_POINT_SIZE:
347    case PIPE_CAPF_MIN_POINT_SIZE_AA:
348       return 1;
349 
350    case PIPE_CAPF_POINT_SIZE_GRANULARITY:
351    case PIPE_CAPF_LINE_WIDTH_GRANULARITY:
352       return 0.1;
353 
354    case PIPE_CAPF_MAX_LINE_WIDTH:
355    case PIPE_CAPF_MAX_LINE_WIDTH_AA:
356       return 1.0f; /* no clue */
357 
358    case PIPE_CAPF_MAX_POINT_SIZE:
359    case PIPE_CAPF_MAX_POINT_SIZE_AA:
360       return D3D12_MAX_POINT_SIZE;
361 
362    case PIPE_CAPF_MAX_TEXTURE_ANISOTROPY:
363       return D3D12_MAX_MAXANISOTROPY;
364 
365    case PIPE_CAPF_MAX_TEXTURE_LOD_BIAS:
366       return 15.99f;
367 
368    case PIPE_CAPF_MIN_CONSERVATIVE_RASTER_DILATE:
369    case PIPE_CAPF_MAX_CONSERVATIVE_RASTER_DILATE:
370    case PIPE_CAPF_CONSERVATIVE_RASTER_DILATE_GRANULARITY:
371       return 0.0f; /* not implemented */
372 
373    default:
374       unreachable("unknown pipe_capf");
375    }
376 
377    return 0.0;
378 }
379 
380 static int
d3d12_get_shader_param(struct pipe_screen * pscreen,enum pipe_shader_type shader,enum pipe_shader_cap param)381 d3d12_get_shader_param(struct pipe_screen *pscreen,
382                        enum pipe_shader_type shader,
383                        enum pipe_shader_cap param)
384 {
385    struct d3d12_screen *screen = d3d12_screen(pscreen);
386 
387    switch (param) {
388    case PIPE_SHADER_CAP_MAX_INSTRUCTIONS:
389    case PIPE_SHADER_CAP_MAX_ALU_INSTRUCTIONS:
390    case PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS:
391    case PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS:
392    case PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH:
393          return INT_MAX;
394       return 0;
395 
396    case PIPE_SHADER_CAP_MAX_INPUTS:
397       switch (shader) {
398       case PIPE_SHADER_VERTEX: return D3D12_VS_INPUT_REGISTER_COUNT;
399       case PIPE_SHADER_FRAGMENT: return D3D12_PS_INPUT_REGISTER_COUNT;
400       case PIPE_SHADER_GEOMETRY: return D3D12_GS_INPUT_REGISTER_COUNT;
401       case PIPE_SHADER_TESS_CTRL: return D3D12_HS_CONTROL_POINT_PHASE_INPUT_REGISTER_COUNT;
402       case PIPE_SHADER_TESS_EVAL: return D3D12_DS_INPUT_CONTROL_POINT_REGISTER_COUNT;
403       case PIPE_SHADER_COMPUTE: return 0;
404       default: unreachable("Unexpected shader");
405       }
406       break;
407 
408    case PIPE_SHADER_CAP_MAX_OUTPUTS:
409       switch (shader) {
410       case PIPE_SHADER_VERTEX: return D3D12_VS_OUTPUT_REGISTER_COUNT;
411       case PIPE_SHADER_FRAGMENT: return D3D12_PS_OUTPUT_REGISTER_COUNT;
412       case PIPE_SHADER_GEOMETRY: return D3D12_GS_OUTPUT_REGISTER_COUNT;
413       case PIPE_SHADER_TESS_CTRL: return D3D12_HS_CONTROL_POINT_PHASE_OUTPUT_REGISTER_COUNT;
414       case PIPE_SHADER_TESS_EVAL: return D3D12_DS_OUTPUT_REGISTER_COUNT;
415       case PIPE_SHADER_COMPUTE: return 0;
416       default: unreachable("Unexpected shader");
417       }
418       break;
419 
420    case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS:
421       if (screen->opts.ResourceBindingTier == D3D12_RESOURCE_BINDING_TIER_1)
422          return 16;
423       return PIPE_MAX_SAMPLERS;
424 
425    case PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE:
426       return 65536;
427 
428    case PIPE_SHADER_CAP_MAX_CONST_BUFFERS:
429       return 13; /* 15 - 2 for lowered uniforms and state vars*/
430 
431    case PIPE_SHADER_CAP_MAX_TEMPS:
432       return INT_MAX;
433 
434    case PIPE_SHADER_CAP_INDIRECT_INPUT_ADDR:
435    case PIPE_SHADER_CAP_INDIRECT_OUTPUT_ADDR:
436    case PIPE_SHADER_CAP_INDIRECT_TEMP_ADDR:
437    case PIPE_SHADER_CAP_SUBROUTINES:
438       return 0; /* not implemented */
439 
440    case PIPE_SHADER_CAP_INDIRECT_CONST_ADDR:
441    case PIPE_SHADER_CAP_INTEGERS:
442       return 1;
443 
444    case PIPE_SHADER_CAP_INT64_ATOMICS:
445    case PIPE_SHADER_CAP_FP16:
446       return 0; /* not implemented */
447 
448    case PIPE_SHADER_CAP_PREFERRED_IR:
449       return PIPE_SHADER_IR_NIR;
450 
451    case PIPE_SHADER_CAP_TGSI_SQRT_SUPPORTED:
452       return 0; /* not implemented */
453 
454    case PIPE_SHADER_CAP_MAX_SAMPLER_VIEWS:
455       /* Note: This is wrong, but this is the max value that
456        * TC can support to avoid overflowing an array.
457        */
458       return PIPE_MAX_SAMPLERS;
459 
460    case PIPE_SHADER_CAP_TGSI_DROUND_SUPPORTED:
461    case PIPE_SHADER_CAP_TGSI_DFRACEXP_DLDEXP_SUPPORTED:
462    case PIPE_SHADER_CAP_TGSI_FMA_SUPPORTED:
463       return 0; /* not implemented */
464 
465    case PIPE_SHADER_CAP_TGSI_ANY_INOUT_DECL_RANGE:
466       return 0; /* no idea */
467 
468    case PIPE_SHADER_CAP_MAX_UNROLL_ITERATIONS_HINT:
469       return 32; /* arbitrary */
470 
471    case PIPE_SHADER_CAP_MAX_SHADER_BUFFERS:
472       return
473          (screen->max_feature_level >= D3D_FEATURE_LEVEL_11_1 ||
474           screen->opts.ResourceBindingTier >= D3D12_RESOURCE_BINDING_TIER_3) ?
475          PIPE_MAX_SHADER_BUFFERS : D3D12_PS_CS_UAV_REGISTER_COUNT;
476 
477    case PIPE_SHADER_CAP_SUPPORTED_IRS:
478       return 1 << PIPE_SHADER_IR_NIR;
479 
480    case PIPE_SHADER_CAP_MAX_SHADER_IMAGES:
481       if (!screen->support_shader_images)
482          return 0;
483       return
484          (screen->max_feature_level >= D3D_FEATURE_LEVEL_11_1 ||
485           screen->opts.ResourceBindingTier >= D3D12_RESOURCE_BINDING_TIER_3) ?
486          PIPE_MAX_SHADER_IMAGES : D3D12_PS_CS_UAV_REGISTER_COUNT;
487 
488    case PIPE_SHADER_CAP_LOWER_IF_THRESHOLD:
489    case PIPE_SHADER_CAP_TGSI_SKIP_MERGE_REGISTERS:
490       return 0; /* unsure */
491 
492    case PIPE_SHADER_CAP_TGSI_LDEXP_SUPPORTED:
493    case PIPE_SHADER_CAP_MAX_HW_ATOMIC_COUNTERS:
494    case PIPE_SHADER_CAP_MAX_HW_ATOMIC_COUNTER_BUFFERS:
495    case PIPE_SHADER_CAP_TGSI_CONT_SUPPORTED:
496       return 0; /* not implemented */
497 
498    /* should only get here on unhandled cases */
499    default: return 0;
500    }
501 }
502 
503 static int
d3d12_get_compute_param(struct pipe_screen * pscreen,enum pipe_shader_ir ir,enum pipe_compute_cap cap,void * ret)504 d3d12_get_compute_param(struct pipe_screen *pscreen,
505                         enum pipe_shader_ir ir,
506                         enum pipe_compute_cap cap,
507                         void *ret)
508 {
509    switch (cap) {
510    case PIPE_COMPUTE_CAP_MAX_GRID_SIZE: {
511       uint64_t *grid = (uint64_t *)ret;
512       grid[0] = grid[1] = grid[2] = D3D12_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION;
513       return sizeof(uint64_t) * 3;
514    }
515    case PIPE_COMPUTE_CAP_MAX_BLOCK_SIZE: {
516       uint64_t *block = (uint64_t *)ret;
517       block[0] = D3D12_CS_THREAD_GROUP_MAX_X;
518       block[1] = D3D12_CS_THREAD_GROUP_MAX_Y;
519       block[2] = D3D12_CS_THREAD_GROUP_MAX_Z;
520       return sizeof(uint64_t) * 3;
521    }
522    case PIPE_COMPUTE_CAP_MAX_VARIABLE_THREADS_PER_BLOCK:
523    case PIPE_COMPUTE_CAP_MAX_THREADS_PER_BLOCK:
524       *(uint64_t *)ret = D3D12_CS_THREAD_GROUP_MAX_THREADS_PER_GROUP;
525       return sizeof(uint64_t);
526    case PIPE_COMPUTE_CAP_MAX_LOCAL_SIZE:
527       *(uint64_t *)ret = D3D12_CS_TGSM_REGISTER_COUNT /*DWORDs*/ * 4;
528       return sizeof(uint64_t);
529    default:
530       return 0;
531    }
532 }
533 
534 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)535 d3d12_is_format_supported(struct pipe_screen *pscreen,
536                           enum pipe_format format,
537                           enum pipe_texture_target target,
538                           unsigned sample_count,
539                           unsigned storage_sample_count,
540                           unsigned bind)
541 {
542    struct d3d12_screen *screen = d3d12_screen(pscreen);
543 
544    if (MAX2(1, sample_count) != MAX2(1, storage_sample_count))
545       return false;
546 
547    if (target == PIPE_BUFFER) {
548       /* Replace emulated vertex element formats for the tests */
549       format = d3d12_emulated_vtx_format(format);
550    } else {
551       /* Allow 3-comp 32 bit formats only for BOs (needed for ARB_tbo_rgb32) */
552       if ((format == PIPE_FORMAT_R32G32B32_FLOAT ||
553            format == PIPE_FORMAT_R32G32B32_SINT ||
554            format == PIPE_FORMAT_R32G32B32_UINT))
555          return false;
556    }
557 
558    /* Don't advertise alpha/luminance_alpha formats because they can't be used
559     * for render targets (except A8_UNORM) and can't be emulated by R/RG formats.
560     * Let the state tracker choose an RGBA format instead. For YUV formats, we
561     * want the state tracker to lower these to individual planes. */
562    if (format != PIPE_FORMAT_A8_UNORM &&
563        (util_format_is_alpha(format) ||
564         util_format_is_luminance_alpha(format) ||
565         util_format_is_yuv(format)))
566       return false;
567 
568    if (format == PIPE_FORMAT_NONE) {
569       /* For UAV-only rendering, aka ARB_framebuffer_no_attachments */
570       switch (sample_count) {
571       case 0:
572       case 1:
573       case 4:
574       case 8:
575       case 16:
576          return true;
577       default:
578          return false;
579       }
580    }
581 
582    DXGI_FORMAT dxgi_format = d3d12_get_format(format);
583    if (dxgi_format == DXGI_FORMAT_UNKNOWN)
584       return false;
585 
586    enum D3D12_FORMAT_SUPPORT1 dim_support = D3D12_FORMAT_SUPPORT1_NONE;
587    switch (target) {
588    case PIPE_TEXTURE_1D:
589    case PIPE_TEXTURE_1D_ARRAY:
590       dim_support = D3D12_FORMAT_SUPPORT1_TEXTURE1D;
591       break;
592    case PIPE_TEXTURE_2D:
593    case PIPE_TEXTURE_RECT:
594    case PIPE_TEXTURE_2D_ARRAY:
595       dim_support = D3D12_FORMAT_SUPPORT1_TEXTURE2D;
596       break;
597    case PIPE_TEXTURE_3D:
598       dim_support = D3D12_FORMAT_SUPPORT1_TEXTURE3D;
599       break;
600    case PIPE_TEXTURE_CUBE:
601    case PIPE_TEXTURE_CUBE_ARRAY:
602       dim_support = D3D12_FORMAT_SUPPORT1_TEXTURECUBE;
603       break;
604    case PIPE_BUFFER:
605       dim_support = D3D12_FORMAT_SUPPORT1_BUFFER;
606       break;
607    default:
608       unreachable("Unknown target");
609    }
610 
611    D3D12_FEATURE_DATA_FORMAT_SUPPORT fmt_info;
612    fmt_info.Format = d3d12_get_resource_rt_format(format);
613    if (FAILED(screen->dev->CheckFeatureSupport(D3D12_FEATURE_FORMAT_SUPPORT,
614                                                &fmt_info, sizeof(fmt_info))))
615       return false;
616 
617    if (!(fmt_info.Support1 & dim_support))
618       return false;
619 
620    if (target == PIPE_BUFFER) {
621       if (bind & PIPE_BIND_VERTEX_BUFFER &&
622           !(fmt_info.Support1 & D3D12_FORMAT_SUPPORT1_IA_VERTEX_BUFFER))
623          return false;
624 
625       if (bind & PIPE_BIND_INDEX_BUFFER) {
626          if (format != PIPE_FORMAT_R16_UINT &&
627              format != PIPE_FORMAT_R32_UINT)
628             return false;
629       }
630 
631       if (sample_count > 0)
632          return false;
633    } else {
634       /* all other targets are texture-targets */
635       if (bind & PIPE_BIND_RENDER_TARGET &&
636           !(fmt_info.Support1 & D3D12_FORMAT_SUPPORT1_RENDER_TARGET))
637          return false;
638 
639       if (bind & PIPE_BIND_BLENDABLE &&
640          !(fmt_info.Support1 & D3D12_FORMAT_SUPPORT1_BLENDABLE))
641          return false;
642 
643       if (bind & PIPE_BIND_SHADER_IMAGE &&
644          (fmt_info.Support2 & (D3D12_FORMAT_SUPPORT2_UAV_TYPED_LOAD | D3D12_FORMAT_SUPPORT2_UAV_TYPED_STORE)) !=
645             (D3D12_FORMAT_SUPPORT2_UAV_TYPED_LOAD | D3D12_FORMAT_SUPPORT2_UAV_TYPED_STORE))
646          return false;
647 
648       D3D12_FEATURE_DATA_FORMAT_SUPPORT fmt_info_sv;
649       if (util_format_is_depth_or_stencil(format)) {
650          fmt_info_sv.Format = d3d12_get_resource_srv_format(format, target);
651          if (FAILED(screen->dev->CheckFeatureSupport(D3D12_FEATURE_FORMAT_SUPPORT,
652                                                      &fmt_info_sv, sizeof(fmt_info_sv))))
653             return false;
654       } else
655          fmt_info_sv = fmt_info;
656 
657       if (bind & PIPE_BIND_DISPLAY_TARGET &&
658          (!(fmt_info.Support1 & D3D12_FORMAT_SUPPORT1_DISPLAY) ||
659             // Disable formats that don't support flip model
660             dxgi_format == DXGI_FORMAT_B8G8R8X8_UNORM ||
661             dxgi_format == DXGI_FORMAT_B5G5R5A1_UNORM ||
662             dxgi_format == DXGI_FORMAT_B5G6R5_UNORM ||
663             dxgi_format == DXGI_FORMAT_B4G4R4A4_UNORM))
664          return false;
665 
666       if (bind & PIPE_BIND_DEPTH_STENCIL &&
667           !(fmt_info.Support1 & D3D12_FORMAT_SUPPORT1_DEPTH_STENCIL))
668             return false;
669 
670       if (sample_count > 0) {
671          if (!(fmt_info_sv.Support1 & D3D12_FORMAT_SUPPORT1_MULTISAMPLE_LOAD))
672             return false;
673 
674          if (!util_is_power_of_two_nonzero(sample_count))
675             return false;
676 
677          if (bind & PIPE_BIND_SHADER_IMAGE)
678             return false;
679 
680          D3D12_FEATURE_DATA_MULTISAMPLE_QUALITY_LEVELS ms_info = {};
681          ms_info.Format = dxgi_format;
682          ms_info.SampleCount = sample_count;
683          if (FAILED(screen->dev->CheckFeatureSupport(D3D12_FEATURE_MULTISAMPLE_QUALITY_LEVELS,
684                                                      &ms_info,
685                                                      sizeof(ms_info))) ||
686              !ms_info.NumQualityLevels)
687             return false;
688       }
689    }
690    return true;
691 }
692 
693 static void
d3d12_destroy_screen(struct pipe_screen * pscreen)694 d3d12_destroy_screen(struct pipe_screen *pscreen)
695 {
696    struct d3d12_screen *screen = d3d12_screen(pscreen);
697    slab_destroy_parent(&screen->transfer_pool);
698    d3d12_descriptor_pool_free(screen->rtv_pool);
699    d3d12_descriptor_pool_free(screen->dsv_pool);
700    d3d12_descriptor_pool_free(screen->view_pool);
701    screen->readback_slab_bufmgr->destroy(screen->readback_slab_bufmgr);
702    screen->slab_bufmgr->destroy(screen->slab_bufmgr);
703    screen->cache_bufmgr->destroy(screen->cache_bufmgr);
704    screen->bufmgr->destroy(screen->bufmgr);
705    mtx_destroy(&screen->submit_mutex);
706    mtx_destroy(&screen->descriptor_pool_mutex);
707    FREE(screen);
708 }
709 
710 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)711 d3d12_flush_frontbuffer(struct pipe_screen * pscreen,
712                         struct pipe_context *pctx,
713                         struct pipe_resource *pres,
714                         unsigned level, unsigned layer,
715                         void *winsys_drawable_handle,
716                         struct pipe_box *sub_box)
717 {
718    struct d3d12_screen *screen = d3d12_screen(pscreen);
719    struct sw_winsys *winsys = screen->winsys;
720    struct d3d12_resource *res = d3d12_resource(pres);
721 
722    if (!winsys || !pctx)
723      return;
724 
725    assert(res->dt);
726    void *map = winsys->displaytarget_map(winsys, res->dt, 0);
727 
728    if (map) {
729       pctx = threaded_context_unwrap_sync(pctx);
730       pipe_transfer *transfer = nullptr;
731       void *res_map = pipe_texture_map(pctx, pres, level, layer, PIPE_MAP_READ, 0, 0,
732                                         u_minify(pres->width0, level),
733                                         u_minify(pres->height0, level),
734                                         &transfer);
735       if (res_map) {
736          util_copy_rect((ubyte*)map, pres->format, res->dt_stride, 0, 0,
737                         transfer->box.width, transfer->box.height,
738                         (const ubyte*)res_map, transfer->stride, 0, 0);
739          pipe_texture_unmap(pctx, transfer);
740       }
741       winsys->displaytarget_unmap(winsys, res->dt);
742    }
743 
744 #ifdef _WIN32
745    // WindowFromDC is Windows-only, and this method requires an HWND, so only use it on Windows
746    ID3D12SharingContract *sharing_contract;
747    if (SUCCEEDED(screen->cmdqueue->QueryInterface(IID_PPV_ARGS(&sharing_contract)))) {
748       ID3D12Resource *d3d12_res = d3d12_resource_resource(res);
749       sharing_contract->Present(d3d12_res, 0, WindowFromDC((HDC)winsys_drawable_handle));
750    }
751 #endif
752 
753    winsys->displaytarget_display(winsys, res->dt, winsys_drawable_handle, sub_box);
754 }
755 
756 static ID3D12Debug *
get_debug_interface()757 get_debug_interface()
758 {
759    typedef HRESULT(WINAPI *PFN_D3D12_GET_DEBUG_INTERFACE)(REFIID riid, void **ppFactory);
760    PFN_D3D12_GET_DEBUG_INTERFACE D3D12GetDebugInterface;
761 
762    util_dl_library *d3d12_mod = util_dl_open(UTIL_DL_PREFIX "d3d12" UTIL_DL_EXT);
763    if (!d3d12_mod) {
764       debug_printf("D3D12: failed to load D3D12.DLL\n");
765       return NULL;
766    }
767 
768    D3D12GetDebugInterface = (PFN_D3D12_GET_DEBUG_INTERFACE)util_dl_get_proc_address(d3d12_mod, "D3D12GetDebugInterface");
769    if (!D3D12GetDebugInterface) {
770       debug_printf("D3D12: failed to load D3D12GetDebugInterface from D3D12.DLL\n");
771       return NULL;
772    }
773 
774    ID3D12Debug *debug;
775    if (FAILED(D3D12GetDebugInterface(IID_PPV_ARGS(&debug)))) {
776       debug_printf("D3D12: D3D12GetDebugInterface failed\n");
777       return NULL;
778    }
779 
780    return debug;
781 }
782 
783 static void
enable_d3d12_debug_layer()784 enable_d3d12_debug_layer()
785 {
786    ID3D12Debug *debug = get_debug_interface();
787    if (debug)
788       debug->EnableDebugLayer();
789 }
790 
791 static void
enable_gpu_validation()792 enable_gpu_validation()
793 {
794    ID3D12Debug *debug = get_debug_interface();
795    ID3D12Debug3 *debug3;
796    if (debug &&
797        SUCCEEDED(debug->QueryInterface(IID_PPV_ARGS(&debug3))))
798       debug3->SetEnableGPUBasedValidation(true);
799 }
800 
801 static ID3D12Device3 *
create_device(IUnknown * adapter)802 create_device(IUnknown *adapter)
803 {
804    typedef HRESULT(WINAPI *PFN_D3D12CREATEDEVICE)(IUnknown*, D3D_FEATURE_LEVEL, REFIID, void**);
805    typedef HRESULT(WINAPI *PFN_D3D12ENABLEEXPERIMENTALFEATURES)(UINT, const IID*, void*, UINT*);
806    PFN_D3D12CREATEDEVICE D3D12CreateDevice;
807    PFN_D3D12ENABLEEXPERIMENTALFEATURES D3D12EnableExperimentalFeatures;
808 
809    util_dl_library *d3d12_mod = util_dl_open(UTIL_DL_PREFIX "d3d12" UTIL_DL_EXT);
810    if (!d3d12_mod) {
811       debug_printf("D3D12: failed to load D3D12.DLL\n");
812       return NULL;
813    }
814 
815 #ifdef _WIN32
816    if (!(d3d12_debug & D3D12_DEBUG_EXPERIMENTAL)) {
817       struct d3d12_validation_tools *validation_tools = d3d12_validator_create();
818       if (!validation_tools) {
819          debug_printf("D3D12: failed to initialize validator with experimental shader models disabled\n");
820          return nullptr;
821       }
822       d3d12_validator_destroy(validation_tools);
823    } else
824 #endif
825    {
826       D3D12EnableExperimentalFeatures = (PFN_D3D12ENABLEEXPERIMENTALFEATURES)util_dl_get_proc_address(d3d12_mod, "D3D12EnableExperimentalFeatures");
827       if (FAILED(D3D12EnableExperimentalFeatures(1, &D3D12ExperimentalShaderModels, NULL, NULL))) {
828          debug_printf("D3D12: failed to enable experimental shader models\n");
829          return nullptr;
830       }
831    }
832 
833    D3D12CreateDevice = (PFN_D3D12CREATEDEVICE)util_dl_get_proc_address(d3d12_mod, "D3D12CreateDevice");
834    if (!D3D12CreateDevice) {
835       debug_printf("D3D12: failed to load D3D12CreateDevice from D3D12.DLL\n");
836       return NULL;
837    }
838 
839    ID3D12Device3 *dev;
840    if (SUCCEEDED(D3D12CreateDevice(adapter, D3D_FEATURE_LEVEL_11_0,
841                  IID_PPV_ARGS(&dev))))
842       return dev;
843 
844    debug_printf("D3D12: D3D12CreateDevice failed\n");
845    return NULL;
846 }
847 
848 static bool
can_attribute_at_vertex(struct d3d12_screen * screen)849 can_attribute_at_vertex(struct d3d12_screen *screen)
850 {
851    switch (screen->vendor_id)  {
852    case HW_VENDOR_MICROSOFT:
853       return true;
854    default:
855       return screen->opts3.BarycentricsSupported;
856    }
857 }
858 
859 static bool
can_shader_image_load_all_formats(struct d3d12_screen * screen)860 can_shader_image_load_all_formats(struct d3d12_screen *screen)
861 {
862    if (!screen->opts.TypedUAVLoadAdditionalFormats)
863       return false;
864 
865    /* All of these are required by ARB_shader_image_load_store */
866    static const DXGI_FORMAT additional_formats[] = {
867       DXGI_FORMAT_R16G16B16A16_UNORM,
868       DXGI_FORMAT_R16G16B16A16_SNORM,
869       DXGI_FORMAT_R32G32_FLOAT,
870       DXGI_FORMAT_R32G32_UINT,
871       DXGI_FORMAT_R32G32_SINT,
872       DXGI_FORMAT_R10G10B10A2_UNORM,
873       DXGI_FORMAT_R10G10B10A2_UINT,
874       DXGI_FORMAT_R11G11B10_FLOAT,
875       DXGI_FORMAT_R8G8B8A8_SNORM,
876       DXGI_FORMAT_R16G16_FLOAT,
877       DXGI_FORMAT_R16G16_UNORM,
878       DXGI_FORMAT_R16G16_UINT,
879       DXGI_FORMAT_R16G16_SNORM,
880       DXGI_FORMAT_R16G16_SINT,
881       DXGI_FORMAT_R8G8_UNORM,
882       DXGI_FORMAT_R8G8_UINT,
883       DXGI_FORMAT_R8G8_SNORM,
884       DXGI_FORMAT_R8G8_SINT,
885       DXGI_FORMAT_R16_UNORM,
886       DXGI_FORMAT_R16_SNORM,
887       DXGI_FORMAT_R8_SNORM,
888    };
889 
890    for (unsigned i = 0; i < ARRAY_SIZE(additional_formats); ++i) {
891       D3D12_FEATURE_DATA_FORMAT_SUPPORT support = { additional_formats[i] };
892       if (FAILED(screen->dev->CheckFeatureSupport(D3D12_FEATURE_FORMAT_SUPPORT, &support, sizeof(support))) ||
893          (support.Support1 & D3D12_FORMAT_SUPPORT1_TYPED_UNORDERED_ACCESS_VIEW) == D3D12_FORMAT_SUPPORT1_NONE ||
894          (support.Support2 & (D3D12_FORMAT_SUPPORT2_UAV_TYPED_LOAD | D3D12_FORMAT_SUPPORT2_UAV_TYPED_STORE)) !=
895             (D3D12_FORMAT_SUPPORT2_UAV_TYPED_LOAD | D3D12_FORMAT_SUPPORT2_UAV_TYPED_STORE))
896          return false;
897    }
898 
899    return true;
900 }
901 
902 static void
d3d12_init_null_srvs(struct d3d12_screen * screen)903 d3d12_init_null_srvs(struct d3d12_screen *screen)
904 {
905    for (unsigned i = 0; i < RESOURCE_DIMENSION_COUNT; ++i) {
906       D3D12_SHADER_RESOURCE_VIEW_DESC srv = {};
907 
908       srv.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
909       srv.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
910       switch (i) {
911       case RESOURCE_DIMENSION_BUFFER:
912       case RESOURCE_DIMENSION_UNKNOWN:
913          srv.ViewDimension = D3D12_SRV_DIMENSION_BUFFER;
914          srv.Buffer.FirstElement = 0;
915          srv.Buffer.NumElements = 0;
916          srv.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_NONE;
917          srv.Buffer.StructureByteStride = 0;
918          break;
919       case RESOURCE_DIMENSION_TEXTURE1D:
920          srv.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1D;
921          srv.Texture1D.MipLevels = 1;
922          srv.Texture1D.MostDetailedMip = 0;
923          srv.Texture1D.ResourceMinLODClamp = 0.0f;
924          break;
925       case RESOURCE_DIMENSION_TEXTURE1DARRAY:
926          srv.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1DARRAY;
927          srv.Texture1DArray.MipLevels = 1;
928          srv.Texture1DArray.ArraySize = 1;
929          srv.Texture1DArray.MostDetailedMip = 0;
930          srv.Texture1DArray.FirstArraySlice = 0;
931          srv.Texture1DArray.ResourceMinLODClamp = 0.0f;
932          break;
933       case RESOURCE_DIMENSION_TEXTURE2D:
934          srv.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
935          srv.Texture2D.MipLevels = 1;
936          srv.Texture2D.MostDetailedMip = 0;
937          srv.Texture2D.PlaneSlice = 0;
938          srv.Texture2D.ResourceMinLODClamp = 0.0f;
939          break;
940       case RESOURCE_DIMENSION_TEXTURE2DARRAY:
941          srv.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY;
942          srv.Texture2DArray.MipLevels = 1;
943          srv.Texture2DArray.ArraySize = 1;
944          srv.Texture2DArray.MostDetailedMip = 0;
945          srv.Texture2DArray.FirstArraySlice = 0;
946          srv.Texture2DArray.PlaneSlice = 0;
947          srv.Texture2DArray.ResourceMinLODClamp = 0.0f;
948          break;
949       case RESOURCE_DIMENSION_TEXTURE2DMS:
950          srv.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DMS;
951          break;
952       case RESOURCE_DIMENSION_TEXTURE2DMSARRAY:
953          srv.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY;
954          srv.Texture2DMSArray.ArraySize = 1;
955          srv.Texture2DMSArray.FirstArraySlice = 0;
956          break;
957       case RESOURCE_DIMENSION_TEXTURE3D:
958          srv.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE3D;
959          srv.Texture3D.MipLevels = 1;
960          srv.Texture3D.MostDetailedMip = 0;
961          srv.Texture3D.ResourceMinLODClamp = 0.0f;
962          break;
963       case RESOURCE_DIMENSION_TEXTURECUBE:
964          srv.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE;
965          srv.TextureCube.MipLevels = 1;
966          srv.TextureCube.MostDetailedMip = 0;
967          srv.TextureCube.ResourceMinLODClamp = 0.0f;
968          break;
969       case RESOURCE_DIMENSION_TEXTURECUBEARRAY:
970          srv.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBEARRAY;
971          srv.TextureCubeArray.MipLevels = 1;
972          srv.TextureCubeArray.NumCubes = 1;
973          srv.TextureCubeArray.MostDetailedMip = 0;
974          srv.TextureCubeArray.First2DArrayFace = 0;
975          srv.TextureCubeArray.ResourceMinLODClamp = 0.0f;
976          break;
977       }
978 
979       if (srv.ViewDimension != D3D12_SRV_DIMENSION_UNKNOWN)
980       {
981          d3d12_descriptor_pool_alloc_handle(screen->view_pool, &screen->null_srvs[i]);
982          screen->dev->CreateShaderResourceView(NULL, &srv, screen->null_srvs[i].cpu_handle);
983       }
984    }
985 }
986 
987 static void
d3d12_init_null_uavs(struct d3d12_screen * screen)988 d3d12_init_null_uavs(struct d3d12_screen *screen)
989 {
990    for (unsigned i = 0; i < RESOURCE_DIMENSION_COUNT; ++i) {
991       D3D12_UNORDERED_ACCESS_VIEW_DESC uav = {};
992 
993       uav.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
994       switch (i) {
995       case RESOURCE_DIMENSION_BUFFER:
996       case RESOURCE_DIMENSION_UNKNOWN:
997          uav.ViewDimension = D3D12_UAV_DIMENSION_BUFFER;
998          uav.Buffer.FirstElement = 0;
999          uav.Buffer.NumElements = 0;
1000          uav.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_NONE;
1001          uav.Buffer.StructureByteStride = 0;
1002          uav.Buffer.CounterOffsetInBytes = 0;
1003          break;
1004       case RESOURCE_DIMENSION_TEXTURE1D:
1005          uav.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE1D;
1006          uav.Texture1D.MipSlice = 0;
1007          break;
1008       case RESOURCE_DIMENSION_TEXTURE1DARRAY:
1009          uav.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE1DARRAY;
1010          uav.Texture1DArray.MipSlice = 0;
1011          uav.Texture1DArray.ArraySize = 1;
1012          uav.Texture1DArray.FirstArraySlice = 0;
1013          break;
1014       case RESOURCE_DIMENSION_TEXTURE2D:
1015          uav.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D;
1016          uav.Texture2D.MipSlice = 0;
1017          uav.Texture2D.PlaneSlice = 0;
1018          break;
1019       case RESOURCE_DIMENSION_TEXTURE2DARRAY:
1020       case RESOURCE_DIMENSION_TEXTURECUBE:
1021       case RESOURCE_DIMENSION_TEXTURECUBEARRAY:
1022          uav.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2DARRAY;
1023          uav.Texture2DArray.MipSlice = 0;
1024          uav.Texture2DArray.ArraySize = 1;
1025          uav.Texture2DArray.FirstArraySlice = 0;
1026          uav.Texture2DArray.PlaneSlice = 0;
1027          break;
1028       case RESOURCE_DIMENSION_TEXTURE2DMS:
1029       case RESOURCE_DIMENSION_TEXTURE2DMSARRAY:
1030          break;
1031       case RESOURCE_DIMENSION_TEXTURE3D:
1032          uav.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE3D;
1033          uav.Texture3D.MipSlice = 0;
1034          uav.Texture3D.FirstWSlice = 0;
1035          uav.Texture3D.WSize = 1;
1036          break;
1037       }
1038 
1039       if (uav.ViewDimension != D3D12_UAV_DIMENSION_UNKNOWN)
1040       {
1041          d3d12_descriptor_pool_alloc_handle(screen->view_pool, &screen->null_uavs[i]);
1042          screen->dev->CreateUnorderedAccessView(NULL, NULL, &uav, screen->null_uavs[i].cpu_handle);
1043       }
1044    }
1045 }
1046 
1047 static void
d3d12_init_null_rtv(struct d3d12_screen * screen)1048 d3d12_init_null_rtv(struct d3d12_screen *screen)
1049 {
1050    D3D12_RENDER_TARGET_VIEW_DESC rtv = {};
1051    rtv.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
1052    rtv.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
1053    rtv.Texture2D.MipSlice = 0;
1054    rtv.Texture2D.PlaneSlice = 0;
1055    d3d12_descriptor_pool_alloc_handle(screen->rtv_pool, &screen->null_rtv);
1056    screen->dev->CreateRenderTargetView(NULL, &rtv, screen->null_rtv.cpu_handle);
1057 }
1058 
1059 bool
d3d12_init_screen(struct d3d12_screen * screen,struct sw_winsys * winsys,IUnknown * adapter)1060 d3d12_init_screen(struct d3d12_screen *screen, struct sw_winsys *winsys, IUnknown *adapter)
1061 {
1062    d3d12_debug = debug_get_option_d3d12_debug();
1063 
1064    screen->winsys = winsys;
1065    mtx_init(&screen->descriptor_pool_mutex, mtx_plain);
1066    mtx_init(&screen->submit_mutex, mtx_plain);
1067 
1068    screen->base.get_vendor = d3d12_get_vendor;
1069    screen->base.get_device_vendor = d3d12_get_device_vendor;
1070    screen->base.get_param = d3d12_get_param;
1071    screen->base.get_paramf = d3d12_get_paramf;
1072    screen->base.get_shader_param = d3d12_get_shader_param;
1073    screen->base.get_compute_param = d3d12_get_compute_param;
1074    screen->base.is_format_supported = d3d12_is_format_supported;
1075    screen->base.get_compiler_options = d3d12_get_compiler_options;
1076    screen->base.context_create = d3d12_context_create;
1077    screen->base.flush_frontbuffer = d3d12_flush_frontbuffer;
1078    screen->base.destroy = d3d12_destroy_screen;
1079 
1080 #ifndef DEBUG
1081    if (d3d12_debug & D3D12_DEBUG_DEBUG_LAYER)
1082 #endif
1083       enable_d3d12_debug_layer();
1084 
1085    if (d3d12_debug & D3D12_DEBUG_GPU_VALIDATOR)
1086       enable_gpu_validation();
1087 
1088    screen->dev = create_device(adapter);
1089 
1090    if (!screen->dev) {
1091       debug_printf("D3D12: failed to create device\n");
1092       goto failed;
1093    }
1094 
1095    ID3D12InfoQueue *info_queue;
1096    if (SUCCEEDED(screen->dev->QueryInterface(IID_PPV_ARGS(&info_queue)))) {
1097       D3D12_MESSAGE_SEVERITY severities[] = {
1098          D3D12_MESSAGE_SEVERITY_INFO,
1099          D3D12_MESSAGE_SEVERITY_WARNING,
1100       };
1101 
1102       D3D12_MESSAGE_ID msg_ids[] = {
1103          D3D12_MESSAGE_ID_CLEARRENDERTARGETVIEW_MISMATCHINGCLEARVALUE,
1104       };
1105 
1106       D3D12_INFO_QUEUE_FILTER NewFilter = {};
1107       NewFilter.DenyList.NumSeverities = ARRAY_SIZE(severities);
1108       NewFilter.DenyList.pSeverityList = severities;
1109       NewFilter.DenyList.NumIDs = ARRAY_SIZE(msg_ids);
1110       NewFilter.DenyList.pIDList = msg_ids;
1111 
1112       info_queue->PushStorageFilter(&NewFilter);
1113    }
1114 
1115    if (FAILED(screen->dev->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS,
1116                                                &screen->opts,
1117                                                sizeof(screen->opts)))) {
1118       debug_printf("D3D12: failed to get device options\n");
1119       goto failed;
1120    }
1121    if (FAILED(screen->dev->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS1,
1122                                                &screen->opts1,
1123                                                sizeof(screen->opts1)))) {
1124       debug_printf("D3D12: failed to get device options\n");
1125       goto failed;
1126    }
1127    if (FAILED(screen->dev->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS2,
1128                                                &screen->opts2,
1129                                                sizeof(screen->opts2)))) {
1130       debug_printf("D3D12: failed to get device options\n");
1131       goto failed;
1132    }
1133    if (FAILED(screen->dev->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS3,
1134                                                &screen->opts3,
1135                                                sizeof(screen->opts3)))) {
1136       debug_printf("D3D12: failed to get device options\n");
1137       goto failed;
1138    }
1139    if (FAILED(screen->dev->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS4,
1140                                                &screen->opts4,
1141                                                sizeof(screen->opts4)))) {
1142       debug_printf("D3D12: failed to get device options\n");
1143       goto failed;
1144    }
1145 
1146    screen->architecture.NodeIndex = 0;
1147    if (FAILED(screen->dev->CheckFeatureSupport(D3D12_FEATURE_ARCHITECTURE,
1148                                                &screen->architecture,
1149                                                sizeof(screen->architecture)))) {
1150       debug_printf("D3D12: failed to get device architecture\n");
1151       goto failed;
1152    }
1153 
1154    D3D12_FEATURE_DATA_FEATURE_LEVELS feature_levels;
1155    static const D3D_FEATURE_LEVEL levels[] = {
1156       D3D_FEATURE_LEVEL_11_0,
1157       D3D_FEATURE_LEVEL_11_1,
1158       D3D_FEATURE_LEVEL_12_0,
1159       D3D_FEATURE_LEVEL_12_1,
1160    };
1161    feature_levels.NumFeatureLevels = ARRAY_SIZE(levels);
1162    feature_levels.pFeatureLevelsRequested = levels;
1163    if (FAILED(screen->dev->CheckFeatureSupport(D3D12_FEATURE_FEATURE_LEVELS,
1164                                                &feature_levels,
1165                                                sizeof(feature_levels)))) {
1166       debug_printf("D3D12: failed to get device feature levels\n");
1167       goto failed;
1168    }
1169    screen->max_feature_level = feature_levels.MaxSupportedFeatureLevel;
1170 
1171    D3D12_COMMAND_QUEUE_DESC queue_desc;
1172    queue_desc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
1173    queue_desc.Priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL;
1174    queue_desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
1175    queue_desc.NodeMask = 0;
1176 
1177    ID3D12Device9 *device9;
1178    if (SUCCEEDED(screen->dev->QueryInterface(&device9))) {
1179       if (FAILED(device9->CreateCommandQueue1(&queue_desc, OpenGLOn12CreatorID,
1180                                               IID_PPV_ARGS(&screen->cmdqueue))))
1181          goto failed;
1182       device9->Release();
1183    } else {
1184       if (FAILED(screen->dev->CreateCommandQueue(&queue_desc,
1185                                                  IID_PPV_ARGS(&screen->cmdqueue))))
1186          goto failed;
1187    }
1188 
1189    if (FAILED(screen->dev->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&screen->fence))))
1190       goto failed;
1191 
1192    if (!d3d12_init_residency(screen))
1193       goto failed;
1194 
1195    UINT64 timestamp_freq;
1196    if (FAILED(screen->cmdqueue->GetTimestampFrequency(&timestamp_freq)))
1197        timestamp_freq = 10000000;
1198    screen->timestamp_multiplier = 1000000000.0 / timestamp_freq;
1199 
1200    d3d12_screen_fence_init(&screen->base);
1201    d3d12_screen_resource_init(&screen->base);
1202    slab_create_parent(&screen->transfer_pool, sizeof(struct d3d12_transfer), 16);
1203 
1204    struct pb_desc desc;
1205    desc.alignment = D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT;
1206    desc.usage = (pb_usage_flags)(PB_USAGE_CPU_WRITE | PB_USAGE_GPU_READ);
1207 
1208    screen->bufmgr = d3d12_bufmgr_create(screen);
1209    screen->cache_bufmgr = pb_cache_manager_create(screen->bufmgr, 0xfffff, 2, 0, 512 * 1024 * 1024);
1210    screen->slab_bufmgr = pb_slab_range_manager_create(screen->cache_bufmgr, 16,
1211                                                       D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT,
1212                                                       D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT,
1213                                                       &desc);
1214    desc.usage = (pb_usage_flags)(PB_USAGE_CPU_READ_WRITE | PB_USAGE_GPU_WRITE);
1215    screen->readback_slab_bufmgr = pb_slab_range_manager_create(screen->cache_bufmgr, 16,
1216                                                                D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT,
1217                                                                D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT,
1218                                                                &desc);
1219 
1220    screen->rtv_pool = d3d12_descriptor_pool_new(screen,
1221                                                 D3D12_DESCRIPTOR_HEAP_TYPE_RTV,
1222                                                 64);
1223    screen->dsv_pool = d3d12_descriptor_pool_new(screen,
1224                                                 D3D12_DESCRIPTOR_HEAP_TYPE_DSV,
1225                                                 64);
1226    screen->view_pool = d3d12_descriptor_pool_new(screen,
1227                                                  D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
1228                                                  1024);
1229 
1230    d3d12_init_null_srvs(screen);
1231    d3d12_init_null_uavs(screen);
1232    d3d12_init_null_rtv(screen);
1233 
1234    screen->have_load_at_vertex = can_attribute_at_vertex(screen);
1235    screen->support_shader_images = can_shader_image_load_all_formats(screen);
1236    ID3D12Device8 *dev8;
1237    if (SUCCEEDED(screen->dev->QueryInterface(&dev8))) {
1238       dev8->Release();
1239       screen->support_create_not_resident = true;
1240    }
1241 
1242    screen->nir_options = *dxil_get_nir_compiler_options();
1243 
1244    static constexpr uint64_t known_good_warp_version = 10ull << 48 | 22000ull << 16;
1245    if ((screen->vendor_id == HW_VENDOR_MICROSOFT &&
1246         screen->driver_version < known_good_warp_version) ||
1247       !screen->opts1.Int64ShaderOps) {
1248       /* Work around old versions of WARP that are completely broken for 64bit shifts */
1249       screen->nir_options.lower_pack_64_2x32_split = false;
1250       screen->nir_options.lower_unpack_64_2x32_split = false;
1251       screen->nir_options.lower_int64_options = (nir_lower_int64_options)~0;
1252    }
1253 
1254    if (!screen->opts.DoublePrecisionFloatShaderOps)
1255       screen->nir_options.lower_doubles_options = (nir_lower_doubles_options)~0;
1256 
1257    return true;
1258 
1259 failed:
1260    return false;
1261 }
1262