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_resource.h"
33 #include "d3d12_nir_passes.h"
34 
35 #include "pipebuffer/pb_bufmgr.h"
36 #include "util/debug.h"
37 #include "util/u_math.h"
38 #include "util/u_memory.h"
39 #include "util/u_screen.h"
40 #include "util/u_dl.h"
41 
42 #include "nir.h"
43 #include "frontend/sw_winsys.h"
44 
45 #include <directx/d3d12sdklayers.h>
46 
47 #include <dxguids/dxguids.h>
48 static GUID OpenGLOn12CreatorID = { 0x6bb3cd34, 0x0d19, 0x45ab, 0x97, 0xed, 0xd7, 0x20, 0xba, 0x3d, 0xfc, 0x80 };
49 
50 static const struct debug_named_value
51 d3d12_debug_options[] = {
52    { "verbose",      D3D12_DEBUG_VERBOSE,       NULL },
53    { "blit",         D3D12_DEBUG_BLIT,          "Trace blit and copy resource calls" },
54    { "experimental", D3D12_DEBUG_EXPERIMENTAL,  "Enable experimental shader models feature" },
55    { "dxil",         D3D12_DEBUG_DXIL,          "Dump DXIL during program compile" },
56    { "disass",       D3D12_DEBUG_DISASS,        "Dump disassambly of created DXIL shader" },
57    { "res",          D3D12_DEBUG_RESOURCE,      "Debug resources" },
58    { "debuglayer",   D3D12_DEBUG_DEBUG_LAYER,   "Enable debug layer" },
59    { "gpuvalidator", D3D12_DEBUG_GPU_VALIDATOR, "Enable GPU validator" },
60    DEBUG_NAMED_VALUE_END
61 };
62 
63 DEBUG_GET_ONCE_FLAGS_OPTION(d3d12_debug, "D3D12_DEBUG", d3d12_debug_options, 0)
64 
65 uint32_t
66 d3d12_debug;
67 
68 enum {
69     HW_VENDOR_AMD                   = 0x1002,
70     HW_VENDOR_INTEL                 = 0x8086,
71     HW_VENDOR_MICROSOFT             = 0x1414,
72     HW_VENDOR_NVIDIA                = 0x10de,
73 };
74 
75 static const char *
d3d12_get_vendor(struct pipe_screen * pscreen)76 d3d12_get_vendor(struct pipe_screen *pscreen)
77 {
78    return "Microsoft Corporation";
79 }
80 
81 static const char *
d3d12_get_device_vendor(struct pipe_screen * pscreen)82 d3d12_get_device_vendor(struct pipe_screen *pscreen)
83 {
84    struct d3d12_screen* screen = d3d12_screen(pscreen);
85 
86    switch (screen->vendor_id) {
87    case HW_VENDOR_MICROSOFT:
88       return "Microsoft";
89    case HW_VENDOR_AMD:
90       return "AMD";
91    case HW_VENDOR_NVIDIA:
92       return "NVIDIA";
93    case HW_VENDOR_INTEL:
94       return "Intel";
95    default:
96       return "Unknown";
97    }
98 }
99 
100 static int
d3d12_get_video_mem(struct pipe_screen * pscreen)101 d3d12_get_video_mem(struct pipe_screen *pscreen)
102 {
103    struct d3d12_screen* screen = d3d12_screen(pscreen);
104 
105    return screen->memory_size_megabytes;
106 }
107 
108 static int
d3d12_get_param(struct pipe_screen * pscreen,enum pipe_cap param)109 d3d12_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
110 {
111    struct d3d12_screen *screen = d3d12_screen(pscreen);
112 
113    switch (param) {
114    case PIPE_CAP_NPOT_TEXTURES:
115       return 1;
116 
117    case PIPE_CAP_MAX_DUAL_SOURCE_RENDER_TARGETS:
118       /* D3D12 only supports dual-source blending for a single
119        * render-target. From the D3D11 functional spec (which also defines
120        * this for D3D12):
121        *
122        * "When Dual Source Color Blending is enabled, the Pixel Shader must
123        *  have only a single RenderTarget bound, at slot 0, and must output
124        *  both o0 and o1. Writing to other outputs (o2, o3 etc.) produces
125        *  undefined results for the corresponding RenderTargets, if bound
126        *  illegally."
127        *
128        * Source: https://microsoft.github.io/DirectX-Specs/d3d/archive/D3D11_3_FunctionalSpec.htm#17.6%20Dual%20Source%20Color%20Blending
129        */
130       return 1;
131 
132    case PIPE_CAP_ANISOTROPIC_FILTER:
133       return 1;
134 
135    case PIPE_CAP_MAX_RENDER_TARGETS:
136       if (screen->max_feature_level >= D3D_FEATURE_LEVEL_10_0)
137          return 8;
138       else if (screen->max_feature_level == D3D_FEATURE_LEVEL_9_3)
139          return 4;
140       return 1;
141 
142    case PIPE_CAP_TEXTURE_SWIZZLE:
143       return 1;
144 
145    case PIPE_CAP_MAX_TEXTURE_2D_SIZE:
146       if (screen->max_feature_level >= D3D_FEATURE_LEVEL_11_0)
147          return 16384;
148       else if (screen->max_feature_level >= D3D_FEATURE_LEVEL_10_0)
149          return 8192;
150       else if (screen->max_feature_level >= D3D_FEATURE_LEVEL_9_3)
151          return 4096;
152       return 2048;
153 
154    case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
155       if (screen->max_feature_level >= D3D_FEATURE_LEVEL_10_0)
156          return 11;
157       return 9;
158 
159    case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
160       if (screen->max_feature_level >= D3D_FEATURE_LEVEL_11_0)
161          return 14;
162       else if (screen->max_feature_level >= D3D_FEATURE_LEVEL_10_0)
163          return 13;
164       else if (screen->max_feature_level == D3D_FEATURE_LEVEL_9_3)
165          return 12;
166       return 9;
167 
168    case PIPE_CAP_PRIMITIVE_RESTART:
169    case PIPE_CAP_INDEP_BLEND_ENABLE:
170    case PIPE_CAP_INDEP_BLEND_FUNC:
171    case PIPE_CAP_FRAGMENT_SHADER_TEXTURE_LOD:
172    case PIPE_CAP_FRAGMENT_SHADER_DERIVATIVES:
173    case PIPE_CAP_VERTEX_SHADER_SATURATE:
174    case PIPE_CAP_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION:
175    case PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY:
176    case PIPE_CAP_RGB_OVERRIDE_DST_ALPHA_BLEND:
177       return 1;
178 
179    /* We need to do some lowering that requires a link to the sampler */
180    case PIPE_CAP_NIR_SAMPLERS_AS_DEREF:
181       return 1;
182 
183    case PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS:
184       if (screen->max_feature_level >= D3D_FEATURE_LEVEL_11_0)
185          return 1 << 14;
186       else if (screen->max_feature_level >= D3D_FEATURE_LEVEL_10_0)
187          return 1 << 13;
188       return 0;
189 
190    case PIPE_CAP_DEPTH_CLIP_DISABLE:
191       return 1;
192 
193    case PIPE_CAP_TGSI_TEXCOORD:
194       return 0;
195 
196    case PIPE_CAP_MIXED_COLORBUFFER_FORMATS:
197       return 1;
198 
199    case PIPE_CAP_VERTEX_COLOR_UNCLAMPED:
200       return 1;
201 
202    case PIPE_CAP_GLSL_FEATURE_LEVEL:
203       return 330;
204    case PIPE_CAP_GLSL_FEATURE_LEVEL_COMPATIBILITY:
205       return 140;
206 
207 #if 0 /* TODO: Enable me */
208    case PIPE_CAP_COMPUTE:
209       return 0;
210 #endif
211 
212    case PIPE_CAP_TEXTURE_MULTISAMPLE:
213       return 1;
214 
215 #if 0 /* TODO: Enable me */
216    case PIPE_CAP_CUBE_MAP_ARRAY:
217       return screen->max_feature_level >= D3D_FEATURE_LEVEL_10_1;
218 #endif
219 
220    case PIPE_CAP_TEXTURE_BUFFER_OBJECTS:
221       return 1;
222 
223    case PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER:
224       return 0; /* unsure */
225 
226    case PIPE_CAP_ENDIANNESS:
227       return PIPE_ENDIAN_NATIVE; /* unsure */
228 
229    case PIPE_CAP_MAX_VIEWPORTS:
230       return 1; /* probably wrong */
231 
232    case PIPE_CAP_MIXED_FRAMEBUFFER_SIZES:
233       return 1;
234 
235 #if 0 /* TODO: Enable me. Enables ARB_texture_gather */
236    case PIPE_CAP_MAX_TEXTURE_GATHER_COMPONENTS:
237       return 4;
238 #endif
239 
240    case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER:
241    case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT:
242       return 1;
243 
244    case PIPE_CAP_TGSI_FS_FACE_IS_INTEGER_SYSVAL:
245       return 1;
246 
247    case PIPE_CAP_ACCELERATED:
248       return 1;
249 
250    case PIPE_CAP_VIDEO_MEMORY:
251       return d3d12_get_video_mem(pscreen);
252 
253    case PIPE_CAP_UMA:
254       return screen->architecture.UMA;
255 
256    case PIPE_CAP_MAX_VERTEX_ATTRIB_STRIDE:
257       return 2048; /* FIXME: no clue how to query this */
258 
259    case PIPE_CAP_TEXTURE_FLOAT_LINEAR:
260    case PIPE_CAP_TEXTURE_HALF_FLOAT_LINEAR:
261       return 1;
262 
263 #if 0 /* TODO: Enable me. Enables GL_ARB_shader_storage_buffer_object */
264    case PIPE_CAP_SHADER_BUFFER_OFFSET_ALIGNMENT:
265       return screen->max_feature_level >= D3D_FEATURE_LEVEL_10_0;
266 #endif
267 
268    case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT:
269       return 256;
270 
271    case PIPE_CAP_PCI_GROUP:
272    case PIPE_CAP_PCI_BUS:
273    case PIPE_CAP_PCI_DEVICE:
274    case PIPE_CAP_PCI_FUNCTION:
275       return 0; /* TODO: figure these out */
276 
277    case PIPE_CAP_GLSL_OPTIMIZE_CONSERVATIVELY:
278       return 0; /* not sure */
279 
280    case PIPE_CAP_FLATSHADE:
281    case PIPE_CAP_ALPHA_TEST:
282    case PIPE_CAP_TWO_SIDED_COLOR:
283    case PIPE_CAP_CLIP_PLANES:
284       return 0;
285 
286    case PIPE_CAP_SHADER_STENCIL_EXPORT:
287       return screen->opts.PSSpecifiedStencilRefSupported;
288 
289    case PIPE_CAP_SEAMLESS_CUBE_MAP:
290    case PIPE_CAP_TEXTURE_QUERY_LOD:
291    case PIPE_CAP_TGSI_INSTANCEID:
292    case PIPE_CAP_TGSI_TEX_TXF_LZ:
293    case PIPE_CAP_OCCLUSION_QUERY:
294    case PIPE_CAP_POINT_SPRITE:
295    case PIPE_CAP_VIEWPORT_TRANSFORM_LOWERED:
296    case PIPE_CAP_PSIZ_CLAMPED:
297    case PIPE_CAP_BLEND_EQUATION_SEPARATE:
298    case PIPE_CAP_CONDITIONAL_RENDER:
299    case PIPE_CAP_QUERY_TIMESTAMP:
300    case PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR:
301    case PIPE_CAP_VERTEX_ELEMENT_SRC_OFFSET_4BYTE_ALIGNED_ONLY:
302       return 1;
303 
304    case PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS:
305       return 4;
306 
307    case PIPE_CAP_MAX_STREAM_OUTPUT_SEPARATE_COMPONENTS:
308    case PIPE_CAP_MAX_STREAM_OUTPUT_INTERLEAVED_COMPONENTS:
309       return 16 * 4;
310 
311    /* Geometry shader output. */
312    case PIPE_CAP_MAX_GEOMETRY_OUTPUT_VERTICES:
313       return 256;
314    case PIPE_CAP_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS:
315       return 256 * 4;
316 
317    case PIPE_CAP_MAX_VARYINGS:
318       return 32;
319 
320    case PIPE_CAP_NIR_COMPACT_ARRAYS:
321       return 1;
322 
323    default:
324       return u_pipe_screen_get_param_defaults(pscreen, param);
325    }
326 }
327 
328 static float
d3d12_get_paramf(struct pipe_screen * pscreen,enum pipe_capf param)329 d3d12_get_paramf(struct pipe_screen *pscreen, enum pipe_capf param)
330 {
331    struct d3d12_screen *screen = d3d12_screen(pscreen);
332 
333    switch (param) {
334    case PIPE_CAPF_MAX_LINE_WIDTH:
335    case PIPE_CAPF_MAX_LINE_WIDTH_AA:
336       return 1.0f; /* no clue */
337 
338    case PIPE_CAPF_MAX_POINT_WIDTH:
339    case PIPE_CAPF_MAX_POINT_WIDTH_AA:
340       return D3D12_MAX_POINT_SIZE;
341 
342    case PIPE_CAPF_MAX_TEXTURE_ANISOTROPY:
343       return screen->max_feature_level >= D3D_FEATURE_LEVEL_10_0 ? 16.0f : 2.0f;
344 
345    case PIPE_CAPF_MAX_TEXTURE_LOD_BIAS:
346       return 15.99f;
347 
348    case PIPE_CAPF_MIN_CONSERVATIVE_RASTER_DILATE:
349    case PIPE_CAPF_MAX_CONSERVATIVE_RASTER_DILATE:
350    case PIPE_CAPF_CONSERVATIVE_RASTER_DILATE_GRANULARITY:
351       return 0.0f; /* not implemented */
352 
353    default:
354       unreachable("unknown pipe_capf");
355    }
356 
357    return 0.0;
358 }
359 
360 static int
d3d12_get_shader_param(struct pipe_screen * pscreen,enum pipe_shader_type shader,enum pipe_shader_cap param)361 d3d12_get_shader_param(struct pipe_screen *pscreen,
362                        enum pipe_shader_type shader,
363                        enum pipe_shader_cap param)
364 {
365    struct d3d12_screen *screen = d3d12_screen(pscreen);
366 
367    switch (param) {
368    case PIPE_SHADER_CAP_MAX_INSTRUCTIONS:
369    case PIPE_SHADER_CAP_MAX_ALU_INSTRUCTIONS:
370    case PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS:
371    case PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS:
372    case PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH:
373       if (shader == PIPE_SHADER_VERTEX ||
374           shader == PIPE_SHADER_FRAGMENT ||
375           shader == PIPE_SHADER_GEOMETRY)
376          return INT_MAX;
377       return 0;
378 
379    case PIPE_SHADER_CAP_MAX_INPUTS:
380       return screen->max_feature_level >= D3D_FEATURE_LEVEL_10_1 ? 32 : 16;
381 
382    case PIPE_SHADER_CAP_MAX_OUTPUTS:
383       if (shader == PIPE_SHADER_FRAGMENT) {
384          /* same as max MRTs (not sure if this is correct) */
385          if (screen->max_feature_level >= D3D_FEATURE_LEVEL_10_0)
386             return 8;
387          else if (screen->max_feature_level == D3D_FEATURE_LEVEL_9_3)
388             return 4;
389          return 1;
390       }
391       return screen->max_feature_level >= D3D_FEATURE_LEVEL_10_1 ? 32 : 16;
392 
393    case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS:
394       if (screen->opts.ResourceBindingTier == D3D12_RESOURCE_BINDING_TIER_1)
395          return 16;
396       return PIPE_MAX_SAMPLERS;
397 
398    case PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE:
399       return 65536;
400 
401    case PIPE_SHADER_CAP_MAX_CONST_BUFFERS:
402       return 13; /* 15 - 2 for lowered uniforms and state vars*/
403 
404    case PIPE_SHADER_CAP_MAX_TEMPS:
405       return INT_MAX;
406 
407    case PIPE_SHADER_CAP_INDIRECT_INPUT_ADDR:
408    case PIPE_SHADER_CAP_INDIRECT_OUTPUT_ADDR:
409    case PIPE_SHADER_CAP_INDIRECT_TEMP_ADDR:
410    case PIPE_SHADER_CAP_SUBROUTINES:
411       return 0; /* not implemented */
412 
413    case PIPE_SHADER_CAP_INDIRECT_CONST_ADDR:
414    case PIPE_SHADER_CAP_INTEGERS:
415       return 1;
416 
417    case PIPE_SHADER_CAP_INT64_ATOMICS:
418    case PIPE_SHADER_CAP_FP16:
419       return 0; /* not implemented */
420 
421    case PIPE_SHADER_CAP_PREFERRED_IR:
422       return PIPE_SHADER_IR_NIR;
423 
424    case PIPE_SHADER_CAP_TGSI_SQRT_SUPPORTED:
425       return 0; /* not implemented */
426 
427    case PIPE_SHADER_CAP_MAX_SAMPLER_VIEWS:
428       if (screen->opts.ResourceBindingTier == D3D12_RESOURCE_BINDING_TIER_1)
429          return 128;
430       return PIPE_MAX_SHADER_SAMPLER_VIEWS;
431 
432    case PIPE_SHADER_CAP_TGSI_DROUND_SUPPORTED:
433    case PIPE_SHADER_CAP_TGSI_DFRACEXP_DLDEXP_SUPPORTED:
434    case PIPE_SHADER_CAP_TGSI_FMA_SUPPORTED:
435       return 0; /* not implemented */
436 
437    case PIPE_SHADER_CAP_TGSI_ANY_INOUT_DECL_RANGE:
438       return 0; /* no idea */
439 
440    case PIPE_SHADER_CAP_MAX_UNROLL_ITERATIONS_HINT:
441       return 32; /* arbitrary */
442 
443 #if 0
444    case PIPE_SHADER_CAP_MAX_SHADER_BUFFERS:
445       return 8; /* no clue */
446 #endif
447 
448    case PIPE_SHADER_CAP_SUPPORTED_IRS:
449       return 1 << PIPE_SHADER_IR_NIR;
450 
451    case PIPE_SHADER_CAP_MAX_SHADER_IMAGES:
452       return 0; /* TODO: enable me */
453 
454    case PIPE_SHADER_CAP_LOWER_IF_THRESHOLD:
455    case PIPE_SHADER_CAP_TGSI_SKIP_MERGE_REGISTERS:
456       return 0; /* unsure */
457 
458    case PIPE_SHADER_CAP_TGSI_LDEXP_SUPPORTED:
459    case PIPE_SHADER_CAP_MAX_HW_ATOMIC_COUNTERS:
460    case PIPE_SHADER_CAP_MAX_HW_ATOMIC_COUNTER_BUFFERS:
461    case PIPE_SHADER_CAP_TGSI_CONT_SUPPORTED:
462       return 0; /* not implemented */
463 
464    /* should only get here on unhandled cases */
465    default: return 0;
466    }
467 }
468 
469 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)470 d3d12_is_format_supported(struct pipe_screen *pscreen,
471                           enum pipe_format format,
472                           enum pipe_texture_target target,
473                           unsigned sample_count,
474                           unsigned storage_sample_count,
475                           unsigned bind)
476 {
477    struct d3d12_screen *screen = d3d12_screen(pscreen);
478 
479    if (MAX2(1, sample_count) != MAX2(1, storage_sample_count))
480       return false;
481 
482    if (target == PIPE_BUFFER) {
483       /* Replace emulated vertex element formats for the tests */
484       format = d3d12_emulated_vtx_format(format);
485    } else {
486       /* Allow 3-comp 32 bit formats only for BOs (needed for ARB_tbo_rgb32) */
487       if ((format == PIPE_FORMAT_R32G32B32_FLOAT ||
488            format == PIPE_FORMAT_R32G32B32_SINT ||
489            format == PIPE_FORMAT_R32G32B32_UINT))
490          return false;
491    }
492 
493    /* Don't advertise alpha/luminance_alpha formats because they can't be used
494     * for render targets (except A8_UNORM) and can't be emulated by R/RG formats.
495     * Let the state tracker choose an RGBA format instead. */
496    if (format != PIPE_FORMAT_A8_UNORM &&
497        (util_format_is_alpha(format) ||
498         util_format_is_luminance_alpha(format)))
499       return false;
500 
501    DXGI_FORMAT dxgi_format = d3d12_get_format(format);
502    if (dxgi_format == DXGI_FORMAT_UNKNOWN)
503       return false;
504 
505    enum D3D12_FORMAT_SUPPORT1 dim_support = D3D12_FORMAT_SUPPORT1_NONE;
506    switch (target) {
507    case PIPE_TEXTURE_1D:
508    case PIPE_TEXTURE_1D_ARRAY:
509       dim_support = D3D12_FORMAT_SUPPORT1_TEXTURE1D;
510       break;
511    case PIPE_TEXTURE_2D:
512    case PIPE_TEXTURE_RECT:
513    case PIPE_TEXTURE_2D_ARRAY:
514       dim_support = D3D12_FORMAT_SUPPORT1_TEXTURE2D;
515       break;
516    case PIPE_TEXTURE_3D:
517       dim_support = D3D12_FORMAT_SUPPORT1_TEXTURE3D;
518       break;
519    case PIPE_TEXTURE_CUBE:
520    case PIPE_TEXTURE_CUBE_ARRAY:
521       dim_support = D3D12_FORMAT_SUPPORT1_TEXTURECUBE;
522       break;
523    case PIPE_BUFFER:
524       dim_support = D3D12_FORMAT_SUPPORT1_BUFFER;
525       break;
526    default:
527       unreachable("Unknown target");
528    }
529 
530    D3D12_FEATURE_DATA_FORMAT_SUPPORT fmt_info;
531    fmt_info.Format = d3d12_get_resource_rt_format(format);
532    if (FAILED(screen->dev->CheckFeatureSupport(D3D12_FEATURE_FORMAT_SUPPORT,
533                                                &fmt_info, sizeof(fmt_info))))
534       return false;
535 
536    if (!(fmt_info.Support1 & dim_support))
537       return false;
538 
539    if (target == PIPE_BUFFER) {
540       if (bind & PIPE_BIND_VERTEX_BUFFER &&
541           !(fmt_info.Support1 & D3D12_FORMAT_SUPPORT1_IA_VERTEX_BUFFER))
542          return false;
543 
544       if (bind & PIPE_BIND_INDEX_BUFFER) {
545          if (format != PIPE_FORMAT_R8_UINT &&
546              format != PIPE_FORMAT_R16_UINT &&
547              format != PIPE_FORMAT_R32_UINT)
548             return false;
549       }
550 
551       if (sample_count > 0)
552          return false;
553    } else {
554       /* all other targets are texture-targets */
555       if (bind & PIPE_BIND_RENDER_TARGET &&
556           !(fmt_info.Support1 & D3D12_FORMAT_SUPPORT1_RENDER_TARGET))
557          return false;
558 
559       if (bind & PIPE_BIND_BLENDABLE &&
560          !(fmt_info.Support1 & D3D12_FORMAT_SUPPORT1_BLENDABLE))
561          return false;
562 
563       D3D12_FEATURE_DATA_FORMAT_SUPPORT fmt_info_sv;
564       if (util_format_is_depth_or_stencil(format)) {
565          fmt_info_sv.Format = d3d12_get_resource_srv_format(format, target);
566          if (FAILED(screen->dev->CheckFeatureSupport(D3D12_FEATURE_FORMAT_SUPPORT,
567                                                      &fmt_info_sv, sizeof(fmt_info_sv))))
568             return false;
569       } else
570          fmt_info_sv = fmt_info;
571 
572       if (bind & PIPE_BIND_DISPLAY_TARGET &&
573          (!(fmt_info.Support1 & D3D12_FORMAT_SUPPORT1_DISPLAY) ||
574             // Disable formats that don't support flip model
575             dxgi_format == DXGI_FORMAT_B8G8R8X8_UNORM ||
576             dxgi_format == DXGI_FORMAT_B5G5R5A1_UNORM ||
577             dxgi_format == DXGI_FORMAT_B5G6R5_UNORM ||
578             dxgi_format == DXGI_FORMAT_B4G4R4A4_UNORM))
579          return false;
580 
581       if (bind & PIPE_BIND_DEPTH_STENCIL &&
582           !(fmt_info.Support1 & D3D12_FORMAT_SUPPORT1_DEPTH_STENCIL))
583             return false;
584 
585       if (sample_count > 0) {
586          if (!(fmt_info_sv.Support1 & D3D12_FORMAT_SUPPORT1_MULTISAMPLE_LOAD))
587             return false;
588 
589          if (!util_is_power_of_two_nonzero(sample_count))
590             return false;
591 
592          D3D12_FEATURE_DATA_MULTISAMPLE_QUALITY_LEVELS ms_info = {};
593          ms_info.Format = dxgi_format;
594          ms_info.SampleCount = sample_count;
595          if (FAILED(screen->dev->CheckFeatureSupport(D3D12_FEATURE_MULTISAMPLE_QUALITY_LEVELS,
596                                                      &ms_info,
597                                                      sizeof(ms_info))) ||
598              !ms_info.NumQualityLevels)
599             return false;
600       }
601    }
602    return true;
603 }
604 
605 static void
d3d12_destroy_screen(struct pipe_screen * pscreen)606 d3d12_destroy_screen(struct pipe_screen *pscreen)
607 {
608    struct d3d12_screen *screen = d3d12_screen(pscreen);
609    slab_destroy_parent(&screen->transfer_pool);
610    d3d12_descriptor_pool_free(screen->rtv_pool);
611    d3d12_descriptor_pool_free(screen->dsv_pool);
612    d3d12_descriptor_pool_free(screen->view_pool);
613    screen->readback_slab_bufmgr->destroy(screen->readback_slab_bufmgr);
614    screen->slab_bufmgr->destroy(screen->slab_bufmgr);
615    screen->cache_bufmgr->destroy(screen->cache_bufmgr);
616    screen->bufmgr->destroy(screen->bufmgr);
617    mtx_destroy(&screen->descriptor_pool_mutex);
618    FREE(screen);
619 }
620 
621 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)622 d3d12_flush_frontbuffer(struct pipe_screen * pscreen,
623                         struct pipe_context *pctx,
624                         struct pipe_resource *pres,
625                         unsigned level, unsigned layer,
626                         void *winsys_drawable_handle,
627                         struct pipe_box *sub_box)
628 {
629    struct d3d12_screen *screen = d3d12_screen(pscreen);
630    struct sw_winsys *winsys = screen->winsys;
631    struct d3d12_resource *res = d3d12_resource(pres);
632 
633    if (!winsys || !pctx)
634      return;
635 
636    assert(res->dt);
637    void *map = winsys->displaytarget_map(winsys, res->dt, 0);
638 
639    if (map) {
640       pipe_transfer *transfer = nullptr;
641       void *res_map = pipe_texture_map(pctx, pres, level, layer, PIPE_MAP_READ, 0, 0,
642                                         u_minify(pres->width0, level),
643                                         u_minify(pres->height0, level),
644                                         &transfer);
645       if (res_map) {
646          util_copy_rect((ubyte*)map, pres->format, res->dt_stride, 0, 0,
647                         transfer->box.width, transfer->box.height,
648                         (const ubyte*)res_map, transfer->stride, 0, 0);
649          pipe_texture_unmap(pctx, transfer);
650       }
651       winsys->displaytarget_unmap(winsys, res->dt);
652    }
653 
654 #ifdef _WIN32
655    // WindowFromDC is Windows-only, and this method requires an HWND, so only use it on Windows
656    ID3D12SharingContract *sharing_contract;
657    if (SUCCEEDED(screen->cmdqueue->QueryInterface(IID_PPV_ARGS(&sharing_contract)))) {
658       ID3D12Resource *d3d12_res = d3d12_resource_resource(res);
659       sharing_contract->Present(d3d12_res, 0, WindowFromDC((HDC)winsys_drawable_handle));
660    }
661 #endif
662 
663    winsys->displaytarget_display(winsys, res->dt, winsys_drawable_handle, sub_box);
664 }
665 
666 static ID3D12Debug *
get_debug_interface()667 get_debug_interface()
668 {
669    typedef HRESULT(WINAPI *PFN_D3D12_GET_DEBUG_INTERFACE)(REFIID riid, void **ppFactory);
670    PFN_D3D12_GET_DEBUG_INTERFACE D3D12GetDebugInterface;
671 
672    util_dl_library *d3d12_mod = util_dl_open(UTIL_DL_PREFIX "d3d12" UTIL_DL_EXT);
673    if (!d3d12_mod) {
674       debug_printf("D3D12: failed to load D3D12.DLL\n");
675       return NULL;
676    }
677 
678    D3D12GetDebugInterface = (PFN_D3D12_GET_DEBUG_INTERFACE)util_dl_get_proc_address(d3d12_mod, "D3D12GetDebugInterface");
679    if (!D3D12GetDebugInterface) {
680       debug_printf("D3D12: failed to load D3D12GetDebugInterface from D3D12.DLL\n");
681       return NULL;
682    }
683 
684    ID3D12Debug *debug;
685    if (FAILED(D3D12GetDebugInterface(IID_PPV_ARGS(&debug)))) {
686       debug_printf("D3D12: D3D12GetDebugInterface failed\n");
687       return NULL;
688    }
689 
690    return debug;
691 }
692 
693 static void
enable_d3d12_debug_layer()694 enable_d3d12_debug_layer()
695 {
696    ID3D12Debug *debug = get_debug_interface();
697    if (debug)
698       debug->EnableDebugLayer();
699 }
700 
701 static void
enable_gpu_validation()702 enable_gpu_validation()
703 {
704    ID3D12Debug *debug = get_debug_interface();
705    ID3D12Debug3 *debug3;
706    if (debug &&
707        SUCCEEDED(debug->QueryInterface(IID_PPV_ARGS(&debug3))))
708       debug3->SetEnableGPUBasedValidation(true);
709 }
710 
711 static ID3D12Device *
create_device(IUnknown * adapter)712 create_device(IUnknown *adapter)
713 {
714    typedef HRESULT(WINAPI *PFN_D3D12CREATEDEVICE)(IUnknown*, D3D_FEATURE_LEVEL, REFIID, void**);
715    typedef HRESULT(WINAPI *PFN_D3D12ENABLEEXPERIMENTALFEATURES)(UINT, const IID*, void*, UINT*);
716    PFN_D3D12CREATEDEVICE D3D12CreateDevice;
717    PFN_D3D12ENABLEEXPERIMENTALFEATURES D3D12EnableExperimentalFeatures;
718 
719    util_dl_library *d3d12_mod = util_dl_open(UTIL_DL_PREFIX "d3d12" UTIL_DL_EXT);
720    if (!d3d12_mod) {
721       debug_printf("D3D12: failed to load D3D12.DLL\n");
722       return NULL;
723    }
724 
725 #ifdef _WIN32
726    if (!(d3d12_debug & D3D12_DEBUG_EXPERIMENTAL)) {
727       struct d3d12_validation_tools *validation_tools = d3d12_validator_create();
728       if (!validation_tools) {
729          debug_printf("D3D12: failed to initialize validator with experimental shader models disabled\n");
730          return nullptr;
731       }
732       d3d12_validator_destroy(validation_tools);
733    } else
734 #endif
735    {
736       D3D12EnableExperimentalFeatures = (PFN_D3D12ENABLEEXPERIMENTALFEATURES)util_dl_get_proc_address(d3d12_mod, "D3D12EnableExperimentalFeatures");
737       if (FAILED(D3D12EnableExperimentalFeatures(1, &D3D12ExperimentalShaderModels, NULL, NULL))) {
738          debug_printf("D3D12: failed to enable experimental shader models\n");
739          return nullptr;
740       }
741    }
742 
743    D3D12CreateDevice = (PFN_D3D12CREATEDEVICE)util_dl_get_proc_address(d3d12_mod, "D3D12CreateDevice");
744    if (!D3D12CreateDevice) {
745       debug_printf("D3D12: failed to load D3D12CreateDevice from D3D12.DLL\n");
746       return NULL;
747    }
748 
749    ID3D12Device *dev;
750    if (SUCCEEDED(D3D12CreateDevice(adapter, D3D_FEATURE_LEVEL_11_0,
751                  IID_PPV_ARGS(&dev))))
752       return dev;
753 
754    debug_printf("D3D12: D3D12CreateDevice failed\n");
755    return NULL;
756 }
757 
758 static bool
can_attribute_at_vertex(struct d3d12_screen * screen)759 can_attribute_at_vertex(struct d3d12_screen *screen)
760 {
761    switch (screen->vendor_id)  {
762    case HW_VENDOR_MICROSOFT:
763       return true;
764    default:
765       return screen->opts3.BarycentricsSupported;
766    }
767 }
768 
769 static void
d3d12_init_null_srvs(struct d3d12_screen * screen)770 d3d12_init_null_srvs(struct d3d12_screen *screen)
771 {
772    for (unsigned i = 0; i < RESOURCE_DIMENSION_COUNT; ++i) {
773       D3D12_SHADER_RESOURCE_VIEW_DESC srv = {};
774 
775       srv.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
776       srv.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
777       switch (i) {
778       case RESOURCE_DIMENSION_BUFFER:
779       case RESOURCE_DIMENSION_UNKNOWN:
780          srv.ViewDimension = D3D12_SRV_DIMENSION_BUFFER;
781          srv.Buffer.FirstElement = 0;
782          srv.Buffer.NumElements = 0;
783          srv.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_NONE;
784          srv.Buffer.StructureByteStride = 0;
785          break;
786       case RESOURCE_DIMENSION_TEXTURE1D:
787          srv.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1D;
788          srv.Texture1D.MipLevels = 1;
789          srv.Texture1D.MostDetailedMip = 0;
790          srv.Texture1D.ResourceMinLODClamp = 0.0f;
791          break;
792       case RESOURCE_DIMENSION_TEXTURE1DARRAY:
793          srv.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1DARRAY;
794          srv.Texture1DArray.MipLevels = 1;
795          srv.Texture1DArray.ArraySize = 1;
796          srv.Texture1DArray.MostDetailedMip = 0;
797          srv.Texture1DArray.FirstArraySlice = 0;
798          srv.Texture1DArray.ResourceMinLODClamp = 0.0f;
799          break;
800       case RESOURCE_DIMENSION_TEXTURE2D:
801          srv.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
802          srv.Texture2D.MipLevels = 1;
803          srv.Texture2D.MostDetailedMip = 0;
804          srv.Texture2D.PlaneSlice = 0;
805          srv.Texture2D.ResourceMinLODClamp = 0.0f;
806          break;
807       case RESOURCE_DIMENSION_TEXTURE2DARRAY:
808          srv.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY;
809          srv.Texture2DArray.MipLevels = 1;
810          srv.Texture2DArray.ArraySize = 1;
811          srv.Texture2DArray.MostDetailedMip = 0;
812          srv.Texture2DArray.FirstArraySlice = 0;
813          srv.Texture2DArray.PlaneSlice = 0;
814          srv.Texture2DArray.ResourceMinLODClamp = 0.0f;
815          break;
816       case RESOURCE_DIMENSION_TEXTURE2DMS:
817          srv.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DMS;
818          break;
819       case RESOURCE_DIMENSION_TEXTURE2DMSARRAY:
820          srv.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY;
821          srv.Texture2DMSArray.ArraySize = 1;
822          srv.Texture2DMSArray.FirstArraySlice = 0;
823          break;
824       case RESOURCE_DIMENSION_TEXTURE3D:
825          srv.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE3D;
826          srv.Texture3D.MipLevels = 1;
827          srv.Texture3D.MostDetailedMip = 0;
828          srv.Texture3D.ResourceMinLODClamp = 0.0f;
829          break;
830       case RESOURCE_DIMENSION_TEXTURECUBE:
831          srv.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE;
832          srv.TextureCube.MipLevels = 1;
833          srv.TextureCube.MostDetailedMip = 0;
834          srv.TextureCube.ResourceMinLODClamp = 0.0f;
835          break;
836       case RESOURCE_DIMENSION_TEXTURECUBEARRAY:
837          srv.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBEARRAY;
838          srv.TextureCubeArray.MipLevels = 1;
839          srv.TextureCubeArray.NumCubes = 1;
840          srv.TextureCubeArray.MostDetailedMip = 0;
841          srv.TextureCubeArray.First2DArrayFace = 0;
842          srv.TextureCubeArray.ResourceMinLODClamp = 0.0f;
843          break;
844       }
845 
846       if (srv.ViewDimension != D3D12_SRV_DIMENSION_UNKNOWN)
847       {
848          d3d12_descriptor_pool_alloc_handle(screen->view_pool, &screen->null_srvs[i]);
849          screen->dev->CreateShaderResourceView(NULL, &srv, screen->null_srvs[i].cpu_handle);
850       }
851    }
852 }
853 
854 static void
d3d12_init_null_rtv(struct d3d12_screen * screen)855 d3d12_init_null_rtv(struct d3d12_screen *screen)
856 {
857    D3D12_RENDER_TARGET_VIEW_DESC rtv = {};
858    rtv.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
859    rtv.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
860    rtv.Texture2D.MipSlice = 0;
861    rtv.Texture2D.PlaneSlice = 0;
862    d3d12_descriptor_pool_alloc_handle(screen->rtv_pool, &screen->null_rtv);
863    screen->dev->CreateRenderTargetView(NULL, &rtv, screen->null_rtv.cpu_handle);
864 }
865 
866 bool
d3d12_init_screen(struct d3d12_screen * screen,struct sw_winsys * winsys,IUnknown * adapter)867 d3d12_init_screen(struct d3d12_screen *screen, struct sw_winsys *winsys, IUnknown *adapter)
868 {
869    d3d12_debug = debug_get_option_d3d12_debug();
870 
871    screen->winsys = winsys;
872    mtx_init(&screen->descriptor_pool_mutex, mtx_plain);
873 
874    screen->base.get_vendor = d3d12_get_vendor;
875    screen->base.get_device_vendor = d3d12_get_device_vendor;
876    screen->base.get_param = d3d12_get_param;
877    screen->base.get_paramf = d3d12_get_paramf;
878    screen->base.get_shader_param = d3d12_get_shader_param;
879    screen->base.is_format_supported = d3d12_is_format_supported;
880    screen->base.get_compiler_options = d3d12_get_compiler_options;
881    screen->base.context_create = d3d12_context_create;
882    screen->base.flush_frontbuffer = d3d12_flush_frontbuffer;
883    screen->base.destroy = d3d12_destroy_screen;
884 
885 #ifndef DEBUG
886    if (d3d12_debug & D3D12_DEBUG_DEBUG_LAYER)
887 #endif
888       enable_d3d12_debug_layer();
889 
890    if (d3d12_debug & D3D12_DEBUG_GPU_VALIDATOR)
891       enable_gpu_validation();
892 
893    screen->dev = create_device(adapter);
894 
895    if (!screen->dev) {
896       debug_printf("D3D12: failed to create device\n");
897       goto failed;
898    }
899 
900    ID3D12InfoQueue *info_queue;
901    if (SUCCEEDED(screen->dev->QueryInterface(IID_PPV_ARGS(&info_queue)))) {
902       D3D12_MESSAGE_SEVERITY severities[] = {
903          D3D12_MESSAGE_SEVERITY_INFO,
904          D3D12_MESSAGE_SEVERITY_WARNING,
905       };
906 
907       D3D12_MESSAGE_ID msg_ids[] = {
908          D3D12_MESSAGE_ID_CLEARRENDERTARGETVIEW_MISMATCHINGCLEARVALUE,
909       };
910 
911       D3D12_INFO_QUEUE_FILTER NewFilter = {};
912       NewFilter.DenyList.NumSeverities = ARRAY_SIZE(severities);
913       NewFilter.DenyList.pSeverityList = severities;
914       NewFilter.DenyList.NumIDs = ARRAY_SIZE(msg_ids);
915       NewFilter.DenyList.pIDList = msg_ids;
916 
917       info_queue->PushStorageFilter(&NewFilter);
918    }
919 
920    if (FAILED(screen->dev->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS,
921                                                &screen->opts,
922                                                sizeof(screen->opts)))) {
923       debug_printf("D3D12: failed to get device options\n");
924       goto failed;
925    }
926    if (FAILED(screen->dev->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS2,
927                                                &screen->opts2,
928                                                sizeof(screen->opts2)))) {
929       debug_printf("D3D12: failed to get device options\n");
930       goto failed;
931    }
932    if (FAILED(screen->dev->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS3,
933                                                &screen->opts3,
934                                                sizeof(screen->opts3)))) {
935       debug_printf("D3D12: failed to get device options\n");
936       goto failed;
937    }
938    if (FAILED(screen->dev->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS4,
939                                                &screen->opts4,
940                                                sizeof(screen->opts4)))) {
941       debug_printf("D3D12: failed to get device options\n");
942       goto failed;
943    }
944 
945    screen->architecture.NodeIndex = 0;
946    if (FAILED(screen->dev->CheckFeatureSupport(D3D12_FEATURE_ARCHITECTURE,
947                                                &screen->architecture,
948                                                sizeof(screen->architecture)))) {
949       debug_printf("D3D12: failed to get device architecture\n");
950       goto failed;
951    }
952 
953    D3D12_FEATURE_DATA_FEATURE_LEVELS feature_levels;
954    static const D3D_FEATURE_LEVEL levels[] = {
955       D3D_FEATURE_LEVEL_11_0,
956       D3D_FEATURE_LEVEL_11_1,
957       D3D_FEATURE_LEVEL_12_0,
958       D3D_FEATURE_LEVEL_12_1,
959    };
960    feature_levels.NumFeatureLevels = ARRAY_SIZE(levels);
961    feature_levels.pFeatureLevelsRequested = levels;
962    if (FAILED(screen->dev->CheckFeatureSupport(D3D12_FEATURE_FEATURE_LEVELS,
963                                                &feature_levels,
964                                                sizeof(feature_levels)))) {
965       debug_printf("D3D12: failed to get device feature levels\n");
966       goto failed;
967    }
968    screen->max_feature_level = feature_levels.MaxSupportedFeatureLevel;
969 
970    D3D12_COMMAND_QUEUE_DESC queue_desc;
971    queue_desc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
972    queue_desc.Priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL;
973    queue_desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
974    queue_desc.NodeMask = 0;
975 
976    ID3D12Device9 *device9;
977    if (SUCCEEDED(screen->dev->QueryInterface(&device9))) {
978       if (FAILED(device9->CreateCommandQueue1(&queue_desc, OpenGLOn12CreatorID,
979                                               IID_PPV_ARGS(&screen->cmdqueue))))
980          goto failed;
981       device9->Release();
982    } else {
983       if (FAILED(screen->dev->CreateCommandQueue(&queue_desc,
984                                                  IID_PPV_ARGS(&screen->cmdqueue))))
985          goto failed;
986    }
987 
988    UINT64 timestamp_freq;
989    if (FAILED(screen->cmdqueue->GetTimestampFrequency(&timestamp_freq)))
990        timestamp_freq = 10000000;
991    screen->timestamp_multiplier = 1000000000.0 / timestamp_freq;
992 
993    d3d12_screen_fence_init(&screen->base);
994    d3d12_screen_resource_init(&screen->base);
995    slab_create_parent(&screen->transfer_pool, sizeof(struct d3d12_transfer), 16);
996 
997    struct pb_desc desc;
998    desc.alignment = D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT;
999    desc.usage = (pb_usage_flags)(PB_USAGE_CPU_WRITE | PB_USAGE_GPU_READ);
1000 
1001    screen->bufmgr = d3d12_bufmgr_create(screen);
1002    screen->cache_bufmgr = pb_cache_manager_create(screen->bufmgr, 0xfffff, 2, 0, 64 * 1024 * 1024);
1003    screen->slab_bufmgr = pb_slab_range_manager_create(screen->cache_bufmgr, 16, 512,
1004                                                       D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT,
1005                                                       &desc);
1006    desc.usage = (pb_usage_flags)(PB_USAGE_CPU_READ_WRITE | PB_USAGE_GPU_WRITE);
1007    screen->readback_slab_bufmgr = pb_slab_range_manager_create(screen->cache_bufmgr, 16, 512,
1008                                                                D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT,
1009                                                                &desc);
1010 
1011    screen->rtv_pool = d3d12_descriptor_pool_new(screen,
1012                                                 D3D12_DESCRIPTOR_HEAP_TYPE_RTV,
1013                                                 64);
1014    screen->dsv_pool = d3d12_descriptor_pool_new(screen,
1015                                                 D3D12_DESCRIPTOR_HEAP_TYPE_DSV,
1016                                                 64);
1017    screen->view_pool = d3d12_descriptor_pool_new(screen,
1018                                                  D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
1019                                                  1024);
1020 
1021    d3d12_init_null_srvs(screen);
1022    d3d12_init_null_rtv(screen);
1023 
1024    screen->have_load_at_vertex = can_attribute_at_vertex(screen);
1025    return true;
1026 
1027 failed:
1028    return false;
1029 }
1030