Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/drivers/d3d12/d3d12_screen.cpp
4570 views
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 *
76
d3d12_get_vendor(struct pipe_screen *pscreen)
77
{
78
return "Microsoft Corporation";
79
}
80
81
static const char *
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
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
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
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
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
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
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
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 *
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
694
enable_d3d12_debug_layer()
695
{
696
ID3D12Debug *debug = get_debug_interface();
697
if (debug)
698
debug->EnableDebugLayer();
699
}
700
701
static void
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 *
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
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
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
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
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
1031