1 //
2 // Copyright 2012 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6
7 // renderer11_utils.cpp: Conversion functions and other utility routines
8 // specific to the D3D11 renderer.
9
10 #include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
11
12 #include <algorithm>
13
14 #include "common/debug.h"
15 #include "libANGLE/Buffer.h"
16 #include "libANGLE/Context.h"
17 #include "libANGLE/Framebuffer.h"
18 #include "libANGLE/Program.h"
19 #include "libANGLE/State.h"
20 #include "libANGLE/VertexArray.h"
21 #include "libANGLE/formatutils.h"
22 #include "libANGLE/renderer/d3d/BufferD3D.h"
23 #include "libANGLE/renderer/d3d/FramebufferD3D.h"
24 #include "libANGLE/renderer/d3d/d3d11/Context11.h"
25 #include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
26 #include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
27 #include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
28 #include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
29 #include "libANGLE/renderer/driver_utils.h"
30 #include "libANGLE/renderer/dxgi_support_table.h"
31 #include "platform/PlatformMethods.h"
32 #include "platform/autogen/FeaturesD3D_autogen.h"
33
34 namespace rx
35 {
36
37 namespace d3d11_gl
38 {
39 namespace
40 {
41 // TODO(xinghua.cao@intel.com): Get a more accurate limit.
42 static D3D_FEATURE_LEVEL kMinimumFeatureLevelForES31 = D3D_FEATURE_LEVEL_11_0;
43
44 // Helper functor for querying DXGI support. Saves passing the parameters repeatedly.
45 class DXGISupportHelper : angle::NonCopyable
46 {
47 public:
DXGISupportHelper(ID3D11Device * device,D3D_FEATURE_LEVEL featureLevel)48 DXGISupportHelper(ID3D11Device *device, D3D_FEATURE_LEVEL featureLevel)
49 : mDevice(device), mFeatureLevel(featureLevel)
50 {}
51
query(DXGI_FORMAT dxgiFormat,UINT supportMask)52 bool query(DXGI_FORMAT dxgiFormat, UINT supportMask)
53 {
54 if (dxgiFormat == DXGI_FORMAT_UNKNOWN)
55 return false;
56
57 auto dxgiSupport = d3d11::GetDXGISupport(dxgiFormat, mFeatureLevel);
58
59 UINT supportedBits = dxgiSupport.alwaysSupportedFlags;
60
61 if ((dxgiSupport.optionallySupportedFlags & supportMask) != 0)
62 {
63 UINT formatSupport;
64 if (SUCCEEDED(mDevice->CheckFormatSupport(dxgiFormat, &formatSupport)))
65 {
66 supportedBits |= (formatSupport & supportMask);
67 }
68 else
69 {
70 // TODO(jmadill): find out why we fail this call sometimes in FL9_3
71 // ERR() << "Error checking format support for format 0x" << std::hex << dxgiFormat;
72 }
73 }
74
75 return ((supportedBits & supportMask) == supportMask);
76 }
77
78 private:
79 ID3D11Device *mDevice;
80 D3D_FEATURE_LEVEL mFeatureLevel;
81 };
82
GenerateTextureFormatCaps(gl::Version maxClientVersion,GLenum internalFormat,ID3D11Device * device,const Renderer11DeviceCaps & renderer11DeviceCaps)83 gl::TextureCaps GenerateTextureFormatCaps(gl::Version maxClientVersion,
84 GLenum internalFormat,
85 ID3D11Device *device,
86 const Renderer11DeviceCaps &renderer11DeviceCaps)
87 {
88 gl::TextureCaps textureCaps;
89
90 DXGISupportHelper support(device, renderer11DeviceCaps.featureLevel);
91 const d3d11::Format &formatInfo = d3d11::Format::Get(internalFormat, renderer11DeviceCaps);
92
93 const gl::InternalFormat &internalFormatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
94
95 UINT texSupportMask = D3D11_FORMAT_SUPPORT_TEXTURE2D;
96 if (internalFormatInfo.depthBits == 0 && internalFormatInfo.stencilBits == 0)
97 {
98 texSupportMask |= D3D11_FORMAT_SUPPORT_TEXTURECUBE;
99 if (maxClientVersion.major > 2)
100 {
101 texSupportMask |= D3D11_FORMAT_SUPPORT_TEXTURE3D;
102 }
103 }
104
105 textureCaps.texturable = support.query(formatInfo.texFormat, texSupportMask);
106 textureCaps.filterable =
107 support.query(formatInfo.srvFormat, D3D11_FORMAT_SUPPORT_SHADER_SAMPLE);
108 textureCaps.textureAttachment =
109 (support.query(formatInfo.rtvFormat, D3D11_FORMAT_SUPPORT_RENDER_TARGET)) ||
110 (support.query(formatInfo.dsvFormat, D3D11_FORMAT_SUPPORT_DEPTH_STENCIL));
111 textureCaps.renderbuffer = textureCaps.textureAttachment;
112 textureCaps.blendable = textureCaps.renderbuffer;
113
114 DXGI_FORMAT renderFormat = DXGI_FORMAT_UNKNOWN;
115 if (formatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN)
116 {
117 renderFormat = formatInfo.dsvFormat;
118 }
119 else if (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN)
120 {
121 renderFormat = formatInfo.rtvFormat;
122 }
123 if (renderFormat != DXGI_FORMAT_UNKNOWN &&
124 support.query(renderFormat, D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET))
125 {
126 // Assume 1x
127 textureCaps.sampleCounts.insert(1);
128
129 for (unsigned int sampleCount = 2; sampleCount <= D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT;
130 sampleCount *= 2)
131 {
132 UINT qualityCount = 0;
133 if (SUCCEEDED(device->CheckMultisampleQualityLevels(renderFormat, sampleCount,
134 &qualityCount)))
135 {
136 // Assume we always support lower sample counts
137 if (qualityCount == 0)
138 {
139 break;
140 }
141 textureCaps.sampleCounts.insert(sampleCount);
142 }
143 }
144 }
145
146 return textureCaps;
147 }
148
GetNPOTTextureSupport(D3D_FEATURE_LEVEL featureLevel)149 bool GetNPOTTextureSupport(D3D_FEATURE_LEVEL featureLevel)
150 {
151 switch (featureLevel)
152 {
153 case D3D_FEATURE_LEVEL_11_1:
154 case D3D_FEATURE_LEVEL_11_0:
155 case D3D_FEATURE_LEVEL_10_1:
156 case D3D_FEATURE_LEVEL_10_0:
157 return true;
158
159 // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx
160 case D3D_FEATURE_LEVEL_9_3:
161 case D3D_FEATURE_LEVEL_9_2:
162 case D3D_FEATURE_LEVEL_9_1:
163 return false;
164
165 default:
166 UNREACHABLE();
167 return false;
168 }
169 }
170
GetMaximumAnisotropy(D3D_FEATURE_LEVEL featureLevel)171 float GetMaximumAnisotropy(D3D_FEATURE_LEVEL featureLevel)
172 {
173 switch (featureLevel)
174 {
175 case D3D_FEATURE_LEVEL_11_1:
176 case D3D_FEATURE_LEVEL_11_0:
177 return D3D11_MAX_MAXANISOTROPY;
178
179 case D3D_FEATURE_LEVEL_10_1:
180 case D3D_FEATURE_LEVEL_10_0:
181 return D3D10_MAX_MAXANISOTROPY;
182
183 // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx
184 case D3D_FEATURE_LEVEL_9_3:
185 case D3D_FEATURE_LEVEL_9_2:
186 return 16;
187
188 case D3D_FEATURE_LEVEL_9_1:
189 return D3D_FL9_1_DEFAULT_MAX_ANISOTROPY;
190
191 default:
192 UNREACHABLE();
193 return 0;
194 }
195 }
196
GetOcclusionQuerySupport(D3D_FEATURE_LEVEL featureLevel)197 bool GetOcclusionQuerySupport(D3D_FEATURE_LEVEL featureLevel)
198 {
199 switch (featureLevel)
200 {
201 case D3D_FEATURE_LEVEL_11_1:
202 case D3D_FEATURE_LEVEL_11_0:
203 case D3D_FEATURE_LEVEL_10_1:
204 case D3D_FEATURE_LEVEL_10_0:
205 return true;
206
207 // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx
208 // ID3D11Device::CreateQuery
209 case D3D_FEATURE_LEVEL_9_3:
210 case D3D_FEATURE_LEVEL_9_2:
211 return true;
212 case D3D_FEATURE_LEVEL_9_1:
213 return false;
214
215 default:
216 UNREACHABLE();
217 return false;
218 }
219 }
220
GetEventQuerySupport(D3D_FEATURE_LEVEL featureLevel)221 bool GetEventQuerySupport(D3D_FEATURE_LEVEL featureLevel)
222 {
223 // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx
224 // ID3D11Device::CreateQuery
225
226 switch (featureLevel)
227 {
228 case D3D_FEATURE_LEVEL_11_1:
229 case D3D_FEATURE_LEVEL_11_0:
230 case D3D_FEATURE_LEVEL_10_1:
231 case D3D_FEATURE_LEVEL_10_0:
232 case D3D_FEATURE_LEVEL_9_3:
233 case D3D_FEATURE_LEVEL_9_2:
234 case D3D_FEATURE_LEVEL_9_1:
235 return true;
236
237 default:
238 UNREACHABLE();
239 return false;
240 }
241 }
242
GetInstancingSupport(D3D_FEATURE_LEVEL featureLevel)243 bool GetInstancingSupport(D3D_FEATURE_LEVEL featureLevel)
244 {
245 // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx
246 // ID3D11Device::CreateInputLayout
247
248 switch (featureLevel)
249 {
250 case D3D_FEATURE_LEVEL_11_1:
251 case D3D_FEATURE_LEVEL_11_0:
252 case D3D_FEATURE_LEVEL_10_1:
253 case D3D_FEATURE_LEVEL_10_0:
254 return true;
255
256 // Feature Level 9_3 supports instancing, but slot 0 in the input layout must not be
257 // instanced.
258 // D3D9 has a similar restriction, where stream 0 must not be instanced.
259 // This restriction can be worked around by remapping any non-instanced slot to slot
260 // 0.
261 // This works because HLSL uses shader semantics to match the vertex inputs to the
262 // elements in the input layout, rather than the slots.
263 // Note that we only support instancing via ANGLE_instanced_array on 9_3, since 9_3
264 // doesn't support OpenGL ES 3.0
265 case D3D_FEATURE_LEVEL_9_3:
266 return true;
267
268 case D3D_FEATURE_LEVEL_9_2:
269 case D3D_FEATURE_LEVEL_9_1:
270 return false;
271
272 default:
273 UNREACHABLE();
274 return false;
275 }
276 }
277
GetFramebufferMultisampleSupport(D3D_FEATURE_LEVEL featureLevel)278 bool GetFramebufferMultisampleSupport(D3D_FEATURE_LEVEL featureLevel)
279 {
280 switch (featureLevel)
281 {
282 case D3D_FEATURE_LEVEL_11_1:
283 case D3D_FEATURE_LEVEL_11_0:
284 case D3D_FEATURE_LEVEL_10_1:
285 case D3D_FEATURE_LEVEL_10_0:
286 return true;
287
288 case D3D_FEATURE_LEVEL_9_3:
289 case D3D_FEATURE_LEVEL_9_2:
290 case D3D_FEATURE_LEVEL_9_1:
291 return false;
292
293 default:
294 UNREACHABLE();
295 return false;
296 }
297 }
298
GetFramebufferBlitSupport(D3D_FEATURE_LEVEL featureLevel)299 bool GetFramebufferBlitSupport(D3D_FEATURE_LEVEL featureLevel)
300 {
301 switch (featureLevel)
302 {
303 case D3D_FEATURE_LEVEL_11_1:
304 case D3D_FEATURE_LEVEL_11_0:
305 case D3D_FEATURE_LEVEL_10_1:
306 case D3D_FEATURE_LEVEL_10_0:
307 return true;
308
309 case D3D_FEATURE_LEVEL_9_3:
310 case D3D_FEATURE_LEVEL_9_2:
311 case D3D_FEATURE_LEVEL_9_1:
312 return false;
313
314 default:
315 UNREACHABLE();
316 return false;
317 }
318 }
319
GetDerivativeInstructionSupport(D3D_FEATURE_LEVEL featureLevel)320 bool GetDerivativeInstructionSupport(D3D_FEATURE_LEVEL featureLevel)
321 {
322 // http://msdn.microsoft.com/en-us/library/windows/desktop/bb509588.aspx states that
323 // shader model
324 // ps_2_x is required for the ddx (and other derivative functions).
325
326 // http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx states that
327 // feature level
328 // 9.3 supports shader model ps_2_x.
329
330 switch (featureLevel)
331 {
332 case D3D_FEATURE_LEVEL_11_1:
333 case D3D_FEATURE_LEVEL_11_0:
334 case D3D_FEATURE_LEVEL_10_1:
335 case D3D_FEATURE_LEVEL_10_0:
336 case D3D_FEATURE_LEVEL_9_3:
337 return true;
338 case D3D_FEATURE_LEVEL_9_2:
339 case D3D_FEATURE_LEVEL_9_1:
340 return false;
341
342 default:
343 UNREACHABLE();
344 return false;
345 }
346 }
347
GetShaderTextureLODSupport(D3D_FEATURE_LEVEL featureLevel)348 bool GetShaderTextureLODSupport(D3D_FEATURE_LEVEL featureLevel)
349 {
350 switch (featureLevel)
351 {
352 case D3D_FEATURE_LEVEL_11_1:
353 case D3D_FEATURE_LEVEL_11_0:
354 case D3D_FEATURE_LEVEL_10_1:
355 case D3D_FEATURE_LEVEL_10_0:
356 return true;
357
358 case D3D_FEATURE_LEVEL_9_3:
359 case D3D_FEATURE_LEVEL_9_2:
360 case D3D_FEATURE_LEVEL_9_1:
361 return false;
362
363 default:
364 UNREACHABLE();
365 return false;
366 }
367 }
368
GetMaximumSimultaneousRenderTargets(D3D_FEATURE_LEVEL featureLevel)369 int GetMaximumSimultaneousRenderTargets(D3D_FEATURE_LEVEL featureLevel)
370 {
371 // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx
372 // ID3D11Device::CreateInputLayout
373
374 switch (featureLevel)
375 {
376 case D3D_FEATURE_LEVEL_11_1:
377 case D3D_FEATURE_LEVEL_11_0:
378 return D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT;
379
380 case D3D_FEATURE_LEVEL_10_1:
381 case D3D_FEATURE_LEVEL_10_0:
382 return D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT;
383
384 case D3D_FEATURE_LEVEL_9_3:
385 return D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT;
386 case D3D_FEATURE_LEVEL_9_2:
387 case D3D_FEATURE_LEVEL_9_1:
388 return D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT;
389
390 default:
391 UNREACHABLE();
392 return 0;
393 }
394 }
395
GetMaximum2DTextureSize(D3D_FEATURE_LEVEL featureLevel)396 int GetMaximum2DTextureSize(D3D_FEATURE_LEVEL featureLevel)
397 {
398 switch (featureLevel)
399 {
400 case D3D_FEATURE_LEVEL_11_1:
401 case D3D_FEATURE_LEVEL_11_0:
402 return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;
403
404 case D3D_FEATURE_LEVEL_10_1:
405 case D3D_FEATURE_LEVEL_10_0:
406 return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION;
407
408 case D3D_FEATURE_LEVEL_9_3:
409 return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION;
410 case D3D_FEATURE_LEVEL_9_2:
411 case D3D_FEATURE_LEVEL_9_1:
412 return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION;
413
414 default:
415 UNREACHABLE();
416 return 0;
417 }
418 }
419
GetMaximumCubeMapTextureSize(D3D_FEATURE_LEVEL featureLevel)420 int GetMaximumCubeMapTextureSize(D3D_FEATURE_LEVEL featureLevel)
421 {
422 switch (featureLevel)
423 {
424 case D3D_FEATURE_LEVEL_11_1:
425 case D3D_FEATURE_LEVEL_11_0:
426 return D3D11_REQ_TEXTURECUBE_DIMENSION;
427
428 case D3D_FEATURE_LEVEL_10_1:
429 case D3D_FEATURE_LEVEL_10_0:
430 return D3D10_REQ_TEXTURECUBE_DIMENSION;
431
432 case D3D_FEATURE_LEVEL_9_3:
433 return D3D_FL9_3_REQ_TEXTURECUBE_DIMENSION;
434 case D3D_FEATURE_LEVEL_9_2:
435 case D3D_FEATURE_LEVEL_9_1:
436 return D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION;
437
438 default:
439 UNREACHABLE();
440 return 0;
441 }
442 }
443
GetMaximum2DTextureArraySize(D3D_FEATURE_LEVEL featureLevel)444 int GetMaximum2DTextureArraySize(D3D_FEATURE_LEVEL featureLevel)
445 {
446 switch (featureLevel)
447 {
448 case D3D_FEATURE_LEVEL_11_1:
449 case D3D_FEATURE_LEVEL_11_0:
450 return D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION;
451
452 case D3D_FEATURE_LEVEL_10_1:
453 case D3D_FEATURE_LEVEL_10_0:
454 return D3D10_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION;
455
456 case D3D_FEATURE_LEVEL_9_3:
457 case D3D_FEATURE_LEVEL_9_2:
458 case D3D_FEATURE_LEVEL_9_1:
459 return 0;
460
461 default:
462 UNREACHABLE();
463 return 0;
464 }
465 }
466
GetMaximum3DTextureSize(D3D_FEATURE_LEVEL featureLevel)467 int GetMaximum3DTextureSize(D3D_FEATURE_LEVEL featureLevel)
468 {
469 switch (featureLevel)
470 {
471 case D3D_FEATURE_LEVEL_11_1:
472 case D3D_FEATURE_LEVEL_11_0:
473 return D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION;
474
475 case D3D_FEATURE_LEVEL_10_1:
476 case D3D_FEATURE_LEVEL_10_0:
477 return D3D10_REQ_TEXTURE3D_U_V_OR_W_DIMENSION;
478
479 case D3D_FEATURE_LEVEL_9_3:
480 case D3D_FEATURE_LEVEL_9_2:
481 case D3D_FEATURE_LEVEL_9_1:
482 return D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION;
483
484 default:
485 UNREACHABLE();
486 return 0;
487 }
488 }
489
GetMaximumViewportSize(D3D_FEATURE_LEVEL featureLevel)490 int GetMaximumViewportSize(D3D_FEATURE_LEVEL featureLevel)
491 {
492 switch (featureLevel)
493 {
494 case D3D_FEATURE_LEVEL_11_1:
495 case D3D_FEATURE_LEVEL_11_0:
496 return D3D11_VIEWPORT_BOUNDS_MAX;
497
498 case D3D_FEATURE_LEVEL_10_1:
499 case D3D_FEATURE_LEVEL_10_0:
500 return D3D10_VIEWPORT_BOUNDS_MAX;
501
502 // No constants for D3D11 Feature Level 9 viewport size limits, use the maximum
503 // texture sizes
504 case D3D_FEATURE_LEVEL_9_3:
505 return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION;
506 case D3D_FEATURE_LEVEL_9_2:
507 case D3D_FEATURE_LEVEL_9_1:
508 return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION;
509
510 default:
511 UNREACHABLE();
512 return 0;
513 }
514 }
515
GetMaximumDrawIndexedIndexCount(D3D_FEATURE_LEVEL featureLevel)516 int GetMaximumDrawIndexedIndexCount(D3D_FEATURE_LEVEL featureLevel)
517 {
518 // D3D11 allows up to 2^32 elements, but we report max signed int for convenience since
519 // that's what's
520 // returned from glGetInteger
521 static_assert(D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP == 32,
522 "Unexpected D3D11 constant value.");
523 static_assert(D3D10_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP == 32,
524 "Unexpected D3D11 constant value.");
525
526 switch (featureLevel)
527 {
528 case D3D_FEATURE_LEVEL_11_1:
529 case D3D_FEATURE_LEVEL_11_0:
530 case D3D_FEATURE_LEVEL_10_1:
531 case D3D_FEATURE_LEVEL_10_0:
532 return std::numeric_limits<GLint>::max();
533
534 case D3D_FEATURE_LEVEL_9_3:
535 case D3D_FEATURE_LEVEL_9_2:
536 return D3D_FL9_2_IA_PRIMITIVE_MAX_COUNT;
537 case D3D_FEATURE_LEVEL_9_1:
538 return D3D_FL9_1_IA_PRIMITIVE_MAX_COUNT;
539
540 default:
541 UNREACHABLE();
542 return 0;
543 }
544 }
545
GetMaximumDrawVertexCount(D3D_FEATURE_LEVEL featureLevel)546 int GetMaximumDrawVertexCount(D3D_FEATURE_LEVEL featureLevel)
547 {
548 // D3D11 allows up to 2^32 elements, but we report max signed int for convenience since
549 // that's what's
550 // returned from glGetInteger
551 static_assert(D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP == 32, "Unexpected D3D11 constant value.");
552 static_assert(D3D10_REQ_DRAW_VERTEX_COUNT_2_TO_EXP == 32, "Unexpected D3D11 constant value.");
553
554 switch (featureLevel)
555 {
556 case D3D_FEATURE_LEVEL_11_1:
557 case D3D_FEATURE_LEVEL_11_0:
558 case D3D_FEATURE_LEVEL_10_1:
559 case D3D_FEATURE_LEVEL_10_0:
560 return std::numeric_limits<GLint>::max();
561
562 case D3D_FEATURE_LEVEL_9_3:
563 case D3D_FEATURE_LEVEL_9_2:
564 return D3D_FL9_2_IA_PRIMITIVE_MAX_COUNT;
565 case D3D_FEATURE_LEVEL_9_1:
566 return D3D_FL9_1_IA_PRIMITIVE_MAX_COUNT;
567
568 default:
569 UNREACHABLE();
570 return 0;
571 }
572 }
573
GetMaximumVertexInputSlots(D3D_FEATURE_LEVEL featureLevel)574 int GetMaximumVertexInputSlots(D3D_FEATURE_LEVEL featureLevel)
575 {
576 switch (featureLevel)
577 {
578 case D3D_FEATURE_LEVEL_11_1:
579 case D3D_FEATURE_LEVEL_11_0:
580 return D3D11_STANDARD_VERTEX_ELEMENT_COUNT;
581
582 case D3D_FEATURE_LEVEL_10_1:
583 return D3D10_1_STANDARD_VERTEX_ELEMENT_COUNT;
584 case D3D_FEATURE_LEVEL_10_0:
585 return D3D10_STANDARD_VERTEX_ELEMENT_COUNT;
586
587 // From http://http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx
588 // "Max Input Slots"
589 case D3D_FEATURE_LEVEL_9_3:
590 case D3D_FEATURE_LEVEL_9_2:
591 case D3D_FEATURE_LEVEL_9_1:
592 return 16;
593
594 default:
595 UNREACHABLE();
596 return 0;
597 }
598 }
599
GetMaximumVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel)600 int GetMaximumVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel)
601 {
602 switch (featureLevel)
603 {
604 case D3D_FEATURE_LEVEL_11_1:
605 case D3D_FEATURE_LEVEL_11_0:
606 return D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT;
607
608 case D3D_FEATURE_LEVEL_10_1:
609 case D3D_FEATURE_LEVEL_10_0:
610 return D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT;
611
612 // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476149.aspx
613 // ID3D11DeviceContext::VSSetConstantBuffers
614 case D3D_FEATURE_LEVEL_9_3:
615 case D3D_FEATURE_LEVEL_9_2:
616 case D3D_FEATURE_LEVEL_9_1:
617 return 255 - d3d11_gl::GetReservedVertexUniformVectors(featureLevel);
618
619 default:
620 UNREACHABLE();
621 return 0;
622 }
623 }
624
GetMaximumVertexUniformBlocks(D3D_FEATURE_LEVEL featureLevel)625 int GetMaximumVertexUniformBlocks(D3D_FEATURE_LEVEL featureLevel)
626 {
627 switch (featureLevel)
628 {
629 case D3D_FEATURE_LEVEL_11_1:
630 case D3D_FEATURE_LEVEL_11_0:
631 return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT -
632 d3d11::RESERVED_CONSTANT_BUFFER_SLOT_COUNT;
633
634 case D3D_FEATURE_LEVEL_10_1:
635 case D3D_FEATURE_LEVEL_10_0:
636 return D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT -
637 d3d11::RESERVED_CONSTANT_BUFFER_SLOT_COUNT;
638
639 // Uniform blocks not supported on D3D11 Feature Level 9
640 case D3D_FEATURE_LEVEL_9_3:
641 case D3D_FEATURE_LEVEL_9_2:
642 case D3D_FEATURE_LEVEL_9_1:
643 return 0;
644
645 default:
646 UNREACHABLE();
647 return 0;
648 }
649 }
650
GetReservedVertexOutputVectors(D3D_FEATURE_LEVEL featureLevel)651 int GetReservedVertexOutputVectors(D3D_FEATURE_LEVEL featureLevel)
652 {
653 // According to The OpenGL ES Shading Language specifications
654 // (Language Version 1.00 section 10.16, Language Version 3.10 section 12.21)
655 // built-in special variables (e.g. gl_FragCoord, or gl_PointCoord)
656 // which are statically used in the shader should be included in the variable packing
657 // algorithm.
658 // Therefore, we should not reserve output vectors for them.
659
660 switch (featureLevel)
661 {
662 // We must reserve one output vector for dx_Position.
663 // We also reserve one for gl_Position, which we unconditionally output on Feature
664 // Levels 10_0+,
665 // even if it's unused in the shader (e.g. for transform feedback). TODO: This could
666 // be improved.
667 case D3D_FEATURE_LEVEL_11_1:
668 case D3D_FEATURE_LEVEL_11_0:
669 case D3D_FEATURE_LEVEL_10_1:
670 case D3D_FEATURE_LEVEL_10_0:
671 return 2;
672
673 // Just reserve dx_Position on Feature Level 9, since we don't ever need to output
674 // gl_Position.
675 case D3D_FEATURE_LEVEL_9_3:
676 case D3D_FEATURE_LEVEL_9_2:
677 case D3D_FEATURE_LEVEL_9_1:
678 return 1;
679
680 default:
681 UNREACHABLE();
682 return 0;
683 }
684 }
685
GetMaximumVertexOutputVectors(D3D_FEATURE_LEVEL featureLevel)686 int GetMaximumVertexOutputVectors(D3D_FEATURE_LEVEL featureLevel)
687 {
688 static_assert(gl::IMPLEMENTATION_MAX_VARYING_VECTORS == D3D11_VS_OUTPUT_REGISTER_COUNT,
689 "Unexpected D3D11 constant value.");
690
691 switch (featureLevel)
692 {
693 case D3D_FEATURE_LEVEL_11_1:
694 case D3D_FEATURE_LEVEL_11_0:
695 return D3D11_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel);
696
697 case D3D_FEATURE_LEVEL_10_1:
698 return D3D10_1_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel);
699 case D3D_FEATURE_LEVEL_10_0:
700 return D3D10_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel);
701
702 // Use Shader Model 2.X limits
703 case D3D_FEATURE_LEVEL_9_3:
704 case D3D_FEATURE_LEVEL_9_2:
705 case D3D_FEATURE_LEVEL_9_1:
706 return 8 - GetReservedVertexOutputVectors(featureLevel);
707
708 default:
709 UNREACHABLE();
710 return 0;
711 }
712 }
713
GetMaximumVertexTextureUnits(D3D_FEATURE_LEVEL featureLevel)714 int GetMaximumVertexTextureUnits(D3D_FEATURE_LEVEL featureLevel)
715 {
716 switch (featureLevel)
717 {
718 case D3D_FEATURE_LEVEL_11_1:
719 case D3D_FEATURE_LEVEL_11_0:
720 return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT;
721
722 case D3D_FEATURE_LEVEL_10_1:
723 case D3D_FEATURE_LEVEL_10_0:
724 return D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT;
725
726 // Vertex textures not supported on D3D11 Feature Level 9 according to
727 // http://msdn.microsoft.com/en-us/library/windows/desktop/ff476149.aspx
728 // ID3D11DeviceContext::VSSetSamplers and ID3D11DeviceContext::VSSetShaderResources
729 case D3D_FEATURE_LEVEL_9_3:
730 case D3D_FEATURE_LEVEL_9_2:
731 case D3D_FEATURE_LEVEL_9_1:
732 return 0;
733
734 default:
735 UNREACHABLE();
736 return 0;
737 }
738 }
739
GetMaximumPixelUniformVectors(D3D_FEATURE_LEVEL featureLevel)740 int GetMaximumPixelUniformVectors(D3D_FEATURE_LEVEL featureLevel)
741 {
742 // TODO(geofflang): Remove hard-coded limit once the gl-uniform-arrays test can pass
743 switch (featureLevel)
744 {
745 case D3D_FEATURE_LEVEL_11_1:
746 case D3D_FEATURE_LEVEL_11_0:
747 return 1024; // D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT;
748
749 case D3D_FEATURE_LEVEL_10_1:
750 case D3D_FEATURE_LEVEL_10_0:
751 return 1024; // D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT;
752
753 // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476149.aspx
754 // ID3D11DeviceContext::PSSetConstantBuffers
755 case D3D_FEATURE_LEVEL_9_3:
756 case D3D_FEATURE_LEVEL_9_2:
757 case D3D_FEATURE_LEVEL_9_1:
758 return 32 - d3d11_gl::GetReservedFragmentUniformVectors(featureLevel);
759
760 default:
761 UNREACHABLE();
762 return 0;
763 }
764 }
765
GetMaximumPixelUniformBlocks(D3D_FEATURE_LEVEL featureLevel)766 int GetMaximumPixelUniformBlocks(D3D_FEATURE_LEVEL featureLevel)
767 {
768 switch (featureLevel)
769 {
770 case D3D_FEATURE_LEVEL_11_1:
771 case D3D_FEATURE_LEVEL_11_0:
772 return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT -
773 d3d11::RESERVED_CONSTANT_BUFFER_SLOT_COUNT;
774
775 case D3D_FEATURE_LEVEL_10_1:
776 case D3D_FEATURE_LEVEL_10_0:
777 return D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT -
778 d3d11::RESERVED_CONSTANT_BUFFER_SLOT_COUNT;
779
780 // Uniform blocks not supported on D3D11 Feature Level 9
781 case D3D_FEATURE_LEVEL_9_3:
782 case D3D_FEATURE_LEVEL_9_2:
783 case D3D_FEATURE_LEVEL_9_1:
784 return 0;
785
786 default:
787 UNREACHABLE();
788 return 0;
789 }
790 }
791
GetMaximumPixelInputVectors(D3D_FEATURE_LEVEL featureLevel)792 int GetMaximumPixelInputVectors(D3D_FEATURE_LEVEL featureLevel)
793 {
794 switch (featureLevel)
795 {
796 case D3D_FEATURE_LEVEL_11_1:
797 case D3D_FEATURE_LEVEL_11_0:
798 return D3D11_PS_INPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel);
799
800 case D3D_FEATURE_LEVEL_10_1:
801 case D3D_FEATURE_LEVEL_10_0:
802 return D3D10_PS_INPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel);
803
804 // Use Shader Model 2.X limits
805 case D3D_FEATURE_LEVEL_9_3:
806 return 8 - GetReservedVertexOutputVectors(featureLevel);
807 case D3D_FEATURE_LEVEL_9_2:
808 case D3D_FEATURE_LEVEL_9_1:
809 return 8 - GetReservedVertexOutputVectors(featureLevel);
810
811 default:
812 UNREACHABLE();
813 return 0;
814 }
815 }
816
GetMaximumPixelTextureUnits(D3D_FEATURE_LEVEL featureLevel)817 int GetMaximumPixelTextureUnits(D3D_FEATURE_LEVEL featureLevel)
818 {
819 switch (featureLevel)
820 {
821 case D3D_FEATURE_LEVEL_11_1:
822 case D3D_FEATURE_LEVEL_11_0:
823 return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT;
824
825 case D3D_FEATURE_LEVEL_10_1:
826 case D3D_FEATURE_LEVEL_10_0:
827 return D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT;
828
829 // http://msdn.microsoft.com/en-us/library/windows/desktop/ff476149.aspx
830 // ID3D11DeviceContext::PSSetShaderResources
831 case D3D_FEATURE_LEVEL_9_3:
832 case D3D_FEATURE_LEVEL_9_2:
833 case D3D_FEATURE_LEVEL_9_1:
834 return 16;
835
836 default:
837 UNREACHABLE();
838 return 0;
839 }
840 }
841
GetMaxComputeWorkGroupCount(D3D_FEATURE_LEVEL featureLevel)842 std::array<GLint, 3> GetMaxComputeWorkGroupCount(D3D_FEATURE_LEVEL featureLevel)
843 {
844 switch (featureLevel)
845 {
846 case D3D_FEATURE_LEVEL_11_1:
847 case D3D_FEATURE_LEVEL_11_0:
848 return {{D3D11_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION,
849 D3D11_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION,
850 D3D11_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION}};
851 default:
852 return {{0, 0, 0}};
853 }
854 }
855
GetMaxComputeWorkGroupSize(D3D_FEATURE_LEVEL featureLevel)856 std::array<GLint, 3> GetMaxComputeWorkGroupSize(D3D_FEATURE_LEVEL featureLevel)
857 {
858 switch (featureLevel)
859 {
860 case D3D_FEATURE_LEVEL_11_1:
861 case D3D_FEATURE_LEVEL_11_0:
862 return {{D3D11_CS_THREAD_GROUP_MAX_X, D3D11_CS_THREAD_GROUP_MAX_Y,
863 D3D11_CS_THREAD_GROUP_MAX_Z}};
864 default:
865 return {{0, 0, 0}};
866 }
867 }
868
GetMaxComputeWorkGroupInvocations(D3D_FEATURE_LEVEL featureLevel)869 int GetMaxComputeWorkGroupInvocations(D3D_FEATURE_LEVEL featureLevel)
870 {
871 switch (featureLevel)
872 {
873 case D3D_FEATURE_LEVEL_11_1:
874 case D3D_FEATURE_LEVEL_11_0:
875 return D3D11_CS_THREAD_GROUP_MAX_THREADS_PER_GROUP;
876 default:
877 return 0;
878 }
879 }
880
GetMaxComputeSharedMemorySize(D3D_FEATURE_LEVEL featureLevel)881 int GetMaxComputeSharedMemorySize(D3D_FEATURE_LEVEL featureLevel)
882 {
883 switch (featureLevel)
884 {
885 // In D3D11 the maximum total size of all variables with the groupshared storage class is
886 // 32kb.
887 // https://docs.microsoft.com/en-us/windows/desktop/direct3dhlsl/dx-graphics-hlsl-variable-syntax
888 case D3D_FEATURE_LEVEL_11_1:
889 case D3D_FEATURE_LEVEL_11_0:
890 return 32768;
891 default:
892 return 0;
893 }
894 }
895
GetMaximumComputeUniformVectors(D3D_FEATURE_LEVEL featureLevel)896 int GetMaximumComputeUniformVectors(D3D_FEATURE_LEVEL featureLevel)
897 {
898 switch (featureLevel)
899 {
900 case D3D_FEATURE_LEVEL_11_1:
901 case D3D_FEATURE_LEVEL_11_0:
902 return D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT;
903 default:
904 return 0;
905 }
906 }
907
GetMaximumComputeUniformBlocks(D3D_FEATURE_LEVEL featureLevel)908 int GetMaximumComputeUniformBlocks(D3D_FEATURE_LEVEL featureLevel)
909 {
910 switch (featureLevel)
911 {
912 case D3D_FEATURE_LEVEL_11_1:
913 case D3D_FEATURE_LEVEL_11_0:
914 return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT -
915 d3d11::RESERVED_CONSTANT_BUFFER_SLOT_COUNT;
916 default:
917 return 0;
918 }
919 }
920
GetMaximumComputeTextureUnits(D3D_FEATURE_LEVEL featureLevel)921 int GetMaximumComputeTextureUnits(D3D_FEATURE_LEVEL featureLevel)
922 {
923 switch (featureLevel)
924 {
925 case D3D_FEATURE_LEVEL_11_1:
926 case D3D_FEATURE_LEVEL_11_0:
927 return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT;
928 default:
929 return 0;
930 }
931 }
932
SetUAVRelatedResourceLimits(D3D_FEATURE_LEVEL featureLevel,gl::Caps * caps)933 void SetUAVRelatedResourceLimits(D3D_FEATURE_LEVEL featureLevel, gl::Caps *caps)
934 {
935 ASSERT(caps);
936
937 GLuint reservedUAVsForAtomicCounterBuffers = 0u;
938
939 // For pixel shaders, the render targets and unordered access views share the same resource
940 // slots when being written out.
941 // https://msdn.microsoft.com/en-us/library/windows/desktop/ff476465(v=vs.85).aspx
942 GLuint maxNumRTVsAndUAVs = 0u;
943
944 switch (featureLevel)
945 {
946 case D3D_FEATURE_LEVEL_11_1:
947 // Currently we allocate 4 UAV slots for atomic counter buffers on feature level 11_1.
948 reservedUAVsForAtomicCounterBuffers = 4u;
949 maxNumRTVsAndUAVs = D3D11_1_UAV_SLOT_COUNT;
950 break;
951 case D3D_FEATURE_LEVEL_11_0:
952 // Currently we allocate 1 UAV slot for atomic counter buffers on feature level 11_0.
953 reservedUAVsForAtomicCounterBuffers = 1u;
954 maxNumRTVsAndUAVs = D3D11_PS_CS_UAV_REGISTER_COUNT;
955 break;
956 default:
957 return;
958 }
959
960 // Set limits on atomic counter buffers in fragment shaders and compute shaders.
961 caps->maxCombinedAtomicCounterBuffers = reservedUAVsForAtomicCounterBuffers;
962 caps->maxShaderAtomicCounterBuffers[gl::ShaderType::Compute] =
963 reservedUAVsForAtomicCounterBuffers;
964 caps->maxShaderAtomicCounterBuffers[gl::ShaderType::Fragment] =
965 reservedUAVsForAtomicCounterBuffers;
966 caps->maxAtomicCounterBufferBindings = reservedUAVsForAtomicCounterBuffers;
967
968 // Setting MAX_COMPUTE_ATOMIC_COUNTERS to a conservative number of 1024 * the number of UAV
969 // reserved for atomic counters. It could theoretically be set to max buffer size / 4 but that
970 // number could cause problems.
971 caps->maxCombinedAtomicCounters = reservedUAVsForAtomicCounterBuffers * 1024;
972 caps->maxShaderAtomicCounters[gl::ShaderType::Compute] = caps->maxCombinedAtomicCounters;
973
974 // See
975 // https://docs.microsoft.com/en-us/windows/desktop/direct3d11/overviews-direct3d-11-resources-limits
976 // Resource size (in MB) for any of the preceding resources is min(max(128,0.25f * (amount of
977 // dedicated VRAM)), 2048) MB. So we set it to 128MB to keep same with GL backend.
978 GLint maxResourceSize = D3D11_REQ_RESOURCE_SIZE_IN_MEGABYTES_EXPRESSION_A_TERM * 1024 * 1024;
979 caps->maxShaderStorageBlockSize = maxResourceSize;
980
981 caps->maxAtomicCounterBufferSize = maxResourceSize;
982
983 // Allocate the remaining slots for images and shader storage blocks.
984 // The maximum number of fragment shader outputs depends on the current context version, so we
985 // will not set it here. See comments in Context11::initialize().
986 caps->maxCombinedShaderOutputResources =
987 maxNumRTVsAndUAVs - reservedUAVsForAtomicCounterBuffers;
988
989 // Set limits on images and shader storage blocks in fragment shaders and compute shaders.
990 caps->maxCombinedShaderStorageBlocks = caps->maxCombinedShaderOutputResources;
991 caps->maxShaderStorageBlocks[gl::ShaderType::Compute] = caps->maxCombinedShaderOutputResources;
992 caps->maxShaderStorageBlocks[gl::ShaderType::Fragment] = caps->maxCombinedShaderOutputResources;
993 caps->maxShaderStorageBufferBindings = caps->maxCombinedShaderOutputResources;
994
995 caps->maxImageUnits = caps->maxCombinedShaderOutputResources;
996 caps->maxCombinedImageUniforms = caps->maxCombinedShaderOutputResources;
997 caps->maxShaderImageUniforms[gl::ShaderType::Compute] = caps->maxCombinedShaderOutputResources;
998 caps->maxShaderImageUniforms[gl::ShaderType::Fragment] = caps->maxCombinedShaderOutputResources;
999
1000 // On feature level 11_1, UAVs are also available in vertex shaders and geometry shaders.
1001 if (featureLevel == D3D_FEATURE_LEVEL_11_1)
1002 {
1003 caps->maxShaderAtomicCounterBuffers[gl::ShaderType::Vertex] =
1004 caps->maxCombinedAtomicCounterBuffers;
1005 caps->maxShaderAtomicCounterBuffers[gl::ShaderType::Geometry] =
1006 caps->maxCombinedAtomicCounterBuffers;
1007
1008 caps->maxShaderImageUniforms[gl::ShaderType::Vertex] =
1009 caps->maxCombinedShaderOutputResources;
1010 caps->maxShaderStorageBlocks[gl::ShaderType::Vertex] =
1011 caps->maxCombinedShaderOutputResources;
1012 caps->maxShaderImageUniforms[gl::ShaderType::Geometry] =
1013 caps->maxCombinedShaderOutputResources;
1014 caps->maxShaderStorageBlocks[gl::ShaderType::Geometry] =
1015 caps->maxCombinedShaderOutputResources;
1016 }
1017 }
1018
GetMinimumTexelOffset(D3D_FEATURE_LEVEL featureLevel)1019 int GetMinimumTexelOffset(D3D_FEATURE_LEVEL featureLevel)
1020 {
1021 switch (featureLevel)
1022 {
1023 case D3D_FEATURE_LEVEL_11_1:
1024 case D3D_FEATURE_LEVEL_11_0:
1025 return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE;
1026
1027 case D3D_FEATURE_LEVEL_10_1:
1028 case D3D_FEATURE_LEVEL_10_0:
1029 return D3D10_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE;
1030
1031 // Sampling functions with offsets are not available below shader model 4.0.
1032 case D3D_FEATURE_LEVEL_9_3:
1033 case D3D_FEATURE_LEVEL_9_2:
1034 case D3D_FEATURE_LEVEL_9_1:
1035 return 0;
1036
1037 default:
1038 UNREACHABLE();
1039 return 0;
1040 }
1041 }
1042
GetMaximumTexelOffset(D3D_FEATURE_LEVEL featureLevel)1043 int GetMaximumTexelOffset(D3D_FEATURE_LEVEL featureLevel)
1044 {
1045 switch (featureLevel)
1046 {
1047 case D3D_FEATURE_LEVEL_11_1:
1048 case D3D_FEATURE_LEVEL_11_0:
1049 return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE;
1050 case D3D_FEATURE_LEVEL_10_1:
1051 case D3D_FEATURE_LEVEL_10_0:
1052 return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE;
1053
1054 // Sampling functions with offsets are not available below shader model 4.0.
1055 case D3D_FEATURE_LEVEL_9_3:
1056 case D3D_FEATURE_LEVEL_9_2:
1057 case D3D_FEATURE_LEVEL_9_1:
1058 return 0;
1059
1060 default:
1061 UNREACHABLE();
1062 return 0;
1063 }
1064 }
1065
GetMinimumTextureGatherOffset(D3D_FEATURE_LEVEL featureLevel)1066 int GetMinimumTextureGatherOffset(D3D_FEATURE_LEVEL featureLevel)
1067 {
1068 switch (featureLevel)
1069 {
1070 // https://docs.microsoft.com/en-us/windows/desktop/direct3dhlsl/gather4-po--sm5---asm-
1071 case D3D_FEATURE_LEVEL_11_1:
1072 case D3D_FEATURE_LEVEL_11_0:
1073 return -32;
1074
1075 case D3D_FEATURE_LEVEL_10_1:
1076 case D3D_FEATURE_LEVEL_10_0:
1077 case D3D_FEATURE_LEVEL_9_3:
1078 case D3D_FEATURE_LEVEL_9_2:
1079 case D3D_FEATURE_LEVEL_9_1:
1080 return 0;
1081
1082 default:
1083 UNREACHABLE();
1084 return 0;
1085 }
1086 }
1087
GetMaximumTextureGatherOffset(D3D_FEATURE_LEVEL featureLevel)1088 int GetMaximumTextureGatherOffset(D3D_FEATURE_LEVEL featureLevel)
1089 {
1090 switch (featureLevel)
1091 {
1092 // https://docs.microsoft.com/en-us/windows/desktop/direct3dhlsl/gather4-po--sm5---asm-
1093 case D3D_FEATURE_LEVEL_11_1:
1094 case D3D_FEATURE_LEVEL_11_0:
1095 return 31;
1096
1097 case D3D_FEATURE_LEVEL_10_1:
1098 case D3D_FEATURE_LEVEL_10_0:
1099 case D3D_FEATURE_LEVEL_9_3:
1100 case D3D_FEATURE_LEVEL_9_2:
1101 case D3D_FEATURE_LEVEL_9_1:
1102 return 0;
1103
1104 default:
1105 UNREACHABLE();
1106 return 0;
1107 }
1108 }
1109
GetMaximumConstantBufferSize(D3D_FEATURE_LEVEL featureLevel)1110 size_t GetMaximumConstantBufferSize(D3D_FEATURE_LEVEL featureLevel)
1111 {
1112 // Returns a size_t despite the limit being a GLuint64 because size_t is the maximum
1113 // size of
1114 // any buffer that could be allocated.
1115
1116 const size_t bytesPerComponent = 4 * sizeof(float);
1117
1118 switch (featureLevel)
1119 {
1120 case D3D_FEATURE_LEVEL_11_1:
1121 case D3D_FEATURE_LEVEL_11_0:
1122 return D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * bytesPerComponent;
1123
1124 case D3D_FEATURE_LEVEL_10_1:
1125 case D3D_FEATURE_LEVEL_10_0:
1126 return D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * bytesPerComponent;
1127
1128 // Limits from http://msdn.microsoft.com/en-us/library/windows/desktop/ff476501.aspx
1129 // remarks section
1130 case D3D_FEATURE_LEVEL_9_3:
1131 case D3D_FEATURE_LEVEL_9_2:
1132 case D3D_FEATURE_LEVEL_9_1:
1133 return 4096 * bytesPerComponent;
1134
1135 default:
1136 UNREACHABLE();
1137 return 0;
1138 }
1139 }
1140
GetMaximumStreamOutputBuffers(D3D_FEATURE_LEVEL featureLevel)1141 int GetMaximumStreamOutputBuffers(D3D_FEATURE_LEVEL featureLevel)
1142 {
1143 switch (featureLevel)
1144 {
1145 case D3D_FEATURE_LEVEL_11_1:
1146 case D3D_FEATURE_LEVEL_11_0:
1147 return D3D11_SO_BUFFER_SLOT_COUNT;
1148
1149 case D3D_FEATURE_LEVEL_10_1:
1150 return D3D10_1_SO_BUFFER_SLOT_COUNT;
1151 case D3D_FEATURE_LEVEL_10_0:
1152 return D3D10_SO_BUFFER_SLOT_COUNT;
1153
1154 case D3D_FEATURE_LEVEL_9_3:
1155 case D3D_FEATURE_LEVEL_9_2:
1156 case D3D_FEATURE_LEVEL_9_1:
1157 return 0;
1158
1159 default:
1160 UNREACHABLE();
1161 return 0;
1162 }
1163 }
1164
GetMaximumStreamOutputInterleavedComponents(D3D_FEATURE_LEVEL featureLevel)1165 int GetMaximumStreamOutputInterleavedComponents(D3D_FEATURE_LEVEL featureLevel)
1166 {
1167 switch (featureLevel)
1168 {
1169 case D3D_FEATURE_LEVEL_11_1:
1170 case D3D_FEATURE_LEVEL_11_0:
1171
1172 case D3D_FEATURE_LEVEL_10_1:
1173 case D3D_FEATURE_LEVEL_10_0:
1174 return GetMaximumVertexOutputVectors(featureLevel) * 4;
1175
1176 case D3D_FEATURE_LEVEL_9_3:
1177 case D3D_FEATURE_LEVEL_9_2:
1178 case D3D_FEATURE_LEVEL_9_1:
1179 return 0;
1180
1181 default:
1182 UNREACHABLE();
1183 return 0;
1184 }
1185 }
1186
GetMaximumStreamOutputSeparateComponents(D3D_FEATURE_LEVEL featureLevel)1187 int GetMaximumStreamOutputSeparateComponents(D3D_FEATURE_LEVEL featureLevel)
1188 {
1189 switch (featureLevel)
1190 {
1191 case D3D_FEATURE_LEVEL_11_1:
1192 case D3D_FEATURE_LEVEL_11_0:
1193 return GetMaximumStreamOutputInterleavedComponents(featureLevel) /
1194 GetMaximumStreamOutputBuffers(featureLevel);
1195
1196 // D3D 10 and 10.1 only allow one output per output slot if an output slot other
1197 // than zero is used.
1198 case D3D_FEATURE_LEVEL_10_1:
1199 case D3D_FEATURE_LEVEL_10_0:
1200 return 4;
1201
1202 case D3D_FEATURE_LEVEL_9_3:
1203 case D3D_FEATURE_LEVEL_9_2:
1204 case D3D_FEATURE_LEVEL_9_1:
1205 return 0;
1206
1207 default:
1208 UNREACHABLE();
1209 return 0;
1210 }
1211 }
1212
GetMaximumRenderToBufferWindowSize(D3D_FEATURE_LEVEL featureLevel)1213 int GetMaximumRenderToBufferWindowSize(D3D_FEATURE_LEVEL featureLevel)
1214 {
1215 switch (featureLevel)
1216 {
1217 case D3D_FEATURE_LEVEL_11_1:
1218 case D3D_FEATURE_LEVEL_11_0:
1219 return D3D11_REQ_RENDER_TO_BUFFER_WINDOW_WIDTH;
1220 case D3D_FEATURE_LEVEL_10_1:
1221 case D3D_FEATURE_LEVEL_10_0:
1222 return D3D10_REQ_RENDER_TO_BUFFER_WINDOW_WIDTH;
1223
1224 // REQ_RENDER_TO_BUFFER_WINDOW_WIDTH not supported on D3D11 Feature Level 9,
1225 // use the maximum texture sizes
1226 case D3D_FEATURE_LEVEL_9_3:
1227 return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION;
1228 case D3D_FEATURE_LEVEL_9_2:
1229 case D3D_FEATURE_LEVEL_9_1:
1230 return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION;
1231
1232 default:
1233 UNREACHABLE();
1234 return 0;
1235 }
1236 }
1237
GetIntelDriverVersion(const Optional<LARGE_INTEGER> driverVersion)1238 angle::VersionTriple GetIntelDriverVersion(const Optional<LARGE_INTEGER> driverVersion)
1239 {
1240 if (!driverVersion.valid())
1241 {
1242 return angle::VersionTriple(0, 0, 0);
1243 }
1244
1245 DWORD lowPart = driverVersion.value().LowPart;
1246
1247 // Please refer the details at
1248 // http://www.intel.com/content/www/us/en/support/graphics-drivers/000005654.html.
1249 return angle::VersionTriple(HIWORD(lowPart), LOWORD(lowPart), 0);
1250 }
1251
1252 } // anonymous namespace
1253
GetReservedVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel)1254 unsigned int GetReservedVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel)
1255 {
1256 switch (featureLevel)
1257 {
1258 case D3D_FEATURE_LEVEL_11_1:
1259 case D3D_FEATURE_LEVEL_11_0:
1260 case D3D_FEATURE_LEVEL_10_1:
1261 case D3D_FEATURE_LEVEL_10_0:
1262 return 0;
1263
1264 case D3D_FEATURE_LEVEL_9_3:
1265 case D3D_FEATURE_LEVEL_9_2:
1266 case D3D_FEATURE_LEVEL_9_1:
1267 return 3; // dx_ViewAdjust, dx_ViewCoords and dx_ViewScale
1268
1269 default:
1270 UNREACHABLE();
1271 return 0;
1272 }
1273 }
1274
GetReservedFragmentUniformVectors(D3D_FEATURE_LEVEL featureLevel)1275 unsigned int GetReservedFragmentUniformVectors(D3D_FEATURE_LEVEL featureLevel)
1276 {
1277 switch (featureLevel)
1278 {
1279 case D3D_FEATURE_LEVEL_11_1:
1280 case D3D_FEATURE_LEVEL_11_0:
1281 case D3D_FEATURE_LEVEL_10_1:
1282 case D3D_FEATURE_LEVEL_10_0:
1283 return 0;
1284
1285 case D3D_FEATURE_LEVEL_9_3:
1286 case D3D_FEATURE_LEVEL_9_2:
1287 case D3D_FEATURE_LEVEL_9_1:
1288 return 4; // dx_ViewCoords, dx_DepthFront, dx_DepthRange, dx_FragCoordOffset
1289
1290 default:
1291 UNREACHABLE();
1292 return 0;
1293 }
1294 }
1295
GetMaximumClientVersion(const Renderer11DeviceCaps & caps)1296 gl::Version GetMaximumClientVersion(const Renderer11DeviceCaps &caps)
1297 {
1298 switch (caps.featureLevel)
1299 {
1300 case D3D_FEATURE_LEVEL_11_1:
1301 case D3D_FEATURE_LEVEL_11_0:
1302 return gl::Version(3, 1);
1303 case D3D_FEATURE_LEVEL_10_1:
1304 return gl::Version(3, 0);
1305
1306 case D3D_FEATURE_LEVEL_10_0:
1307 if (caps.allowES3OnFL10_0)
1308 {
1309 return gl::Version(3, 0);
1310 }
1311 else
1312 {
1313 return gl::Version(2, 0);
1314 }
1315 case D3D_FEATURE_LEVEL_9_3:
1316 case D3D_FEATURE_LEVEL_9_2:
1317 case D3D_FEATURE_LEVEL_9_1:
1318 return gl::Version(2, 0);
1319
1320 default:
1321 UNREACHABLE();
1322 return gl::Version(0, 0);
1323 }
1324 }
1325
GetMinimumFeatureLevelForES31()1326 D3D_FEATURE_LEVEL GetMinimumFeatureLevelForES31()
1327 {
1328 return kMinimumFeatureLevelForES31;
1329 }
1330
GetMaxViewportAndScissorRectanglesPerPipeline(D3D_FEATURE_LEVEL featureLevel)1331 unsigned int GetMaxViewportAndScissorRectanglesPerPipeline(D3D_FEATURE_LEVEL featureLevel)
1332 {
1333 switch (featureLevel)
1334 {
1335 case D3D_FEATURE_LEVEL_11_1:
1336 case D3D_FEATURE_LEVEL_11_0:
1337 return D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE;
1338 case D3D_FEATURE_LEVEL_10_1:
1339 case D3D_FEATURE_LEVEL_10_0:
1340 case D3D_FEATURE_LEVEL_9_3:
1341 case D3D_FEATURE_LEVEL_9_2:
1342 case D3D_FEATURE_LEVEL_9_1:
1343 return 1;
1344 default:
1345 UNREACHABLE();
1346 return 0;
1347 }
1348 }
1349
IsMultiviewSupported(D3D_FEATURE_LEVEL featureLevel)1350 bool IsMultiviewSupported(D3D_FEATURE_LEVEL featureLevel)
1351 {
1352 // The multiview extensions can always be supported in D3D11 through geometry shaders.
1353 switch (featureLevel)
1354 {
1355 case D3D_FEATURE_LEVEL_11_1:
1356 case D3D_FEATURE_LEVEL_11_0:
1357 return true;
1358 default:
1359 return false;
1360 }
1361 }
1362
GetMaxSampleMaskWords(D3D_FEATURE_LEVEL featureLevel)1363 int GetMaxSampleMaskWords(D3D_FEATURE_LEVEL featureLevel)
1364 {
1365 switch (featureLevel)
1366 {
1367 // D3D10+ only allows 1 sample mask.
1368 case D3D_FEATURE_LEVEL_11_1:
1369 case D3D_FEATURE_LEVEL_11_0:
1370 case D3D_FEATURE_LEVEL_10_1:
1371 case D3D_FEATURE_LEVEL_10_0:
1372 return 1;
1373 case D3D_FEATURE_LEVEL_9_3:
1374 case D3D_FEATURE_LEVEL_9_2:
1375 case D3D_FEATURE_LEVEL_9_1:
1376 return 0;
1377 default:
1378 UNREACHABLE();
1379 return 0;
1380 }
1381 }
1382
HasTextureBufferSupport(ID3D11Device * device,const Renderer11DeviceCaps & renderer11DeviceCaps)1383 bool HasTextureBufferSupport(ID3D11Device *device, const Renderer11DeviceCaps &renderer11DeviceCaps)
1384 {
1385 if (renderer11DeviceCaps.featureLevel < D3D_FEATURE_LEVEL_11_0)
1386 return false;
1387
1388 if (!renderer11DeviceCaps.supportsTypedUAVLoadAdditionalFormats)
1389 return false;
1390
1391 // https://docs.microsoft.com/en-us/windows/win32/direct3d12/typed-unordered-access-view-loads
1392 // we don't need to check the typed store. from the spec,
1393 // https://microsoft.github.io/DirectX-Specs/d3d/archive/D3D11_3_FunctionalSpec.htm#FormatList
1394 // all the following format support typed stored.
1395 // According to spec,
1396 // https://www.khronos.org/registry/OpenGL-Refpages/es3/html/glBindImageTexture.xhtml the
1397 // required image unit format are GL_RGBA32F, GL_RGBA32UI, GL_RGBA32I, GL_RGBA16F, GL_RGBA16UI,
1398 // GL_RGBA16I, GL_RGBA8, GL_RGBAUI, GL_RGBA8I, GL_RGBA8_SNORM, GL_R32F, GL_R32UI, GL_R32I,
1399 const std::array<DXGI_FORMAT, 2> &optionalFormats = {
1400 DXGI_FORMAT_R32G32B32A32_FLOAT, // test for GL_RGBA32(UIF), GL_RGBA16(UIF),
1401 // GL_RGBA8(UIUnorm)
1402 DXGI_FORMAT_R8G8B8A8_SNORM, // test for GL_RGBA8_SNORM,
1403 };
1404
1405 for (DXGI_FORMAT dxgiFormat : optionalFormats)
1406 {
1407 D3D11_FEATURE_DATA_FORMAT_SUPPORT FormatSupport = {dxgiFormat, 0};
1408 if (!SUCCEEDED(device->CheckFeatureSupport(D3D11_FEATURE_FORMAT_SUPPORT, &FormatSupport,
1409 sizeof(FormatSupport))))
1410 {
1411 WARN() << "Error checking typed load support for format 0x" << std::hex << dxgiFormat;
1412 return false;
1413 }
1414 if ((FormatSupport.OutFormatSupport & D3D11_FORMAT_SUPPORT2_UAV_TYPED_LOAD) == 0)
1415 return false;
1416 }
1417 return true;
1418 }
1419
GenerateCaps(ID3D11Device * device,ID3D11DeviceContext * deviceContext,const Renderer11DeviceCaps & renderer11DeviceCaps,const angle::FeaturesD3D & features,const char * description,gl::Caps * caps,gl::TextureCapsMap * textureCapsMap,gl::Extensions * extensions,gl::Limitations * limitations,ShPixelLocalStorageOptions * plsOptions)1420 void GenerateCaps(ID3D11Device *device,
1421 ID3D11DeviceContext *deviceContext,
1422 const Renderer11DeviceCaps &renderer11DeviceCaps,
1423 const angle::FeaturesD3D &features,
1424 const char *description,
1425 gl::Caps *caps,
1426 gl::TextureCapsMap *textureCapsMap,
1427 gl::Extensions *extensions,
1428 gl::Limitations *limitations,
1429 ShPixelLocalStorageOptions *plsOptions)
1430 {
1431 const D3D_FEATURE_LEVEL featureLevel = renderer11DeviceCaps.featureLevel;
1432 const gl::FormatSet &allFormats = gl::GetAllSizedInternalFormats();
1433 for (GLenum internalFormat : allFormats)
1434 {
1435 gl::TextureCaps textureCaps =
1436 GenerateTextureFormatCaps(GetMaximumClientVersion(renderer11DeviceCaps), internalFormat,
1437 device, renderer11DeviceCaps);
1438 textureCapsMap->insert(internalFormat, textureCaps);
1439 }
1440
1441 // GL core feature limits
1442 // Reserve MAX_UINT for D3D11's primitive restart.
1443 caps->maxElementIndex = static_cast<GLint64>(std::numeric_limits<unsigned int>::max() - 1);
1444 caps->max3DTextureSize = GetMaximum3DTextureSize(featureLevel);
1445 caps->max2DTextureSize = GetMaximum2DTextureSize(featureLevel);
1446 caps->maxCubeMapTextureSize = GetMaximumCubeMapTextureSize(featureLevel);
1447 caps->maxArrayTextureLayers = GetMaximum2DTextureArraySize(featureLevel);
1448
1449 // Unimplemented, set to minimum required
1450 caps->maxLODBias = 2.0f;
1451
1452 // No specific limits on render target size, maximum 2D texture size is equivalent
1453 caps->maxRenderbufferSize = caps->max2DTextureSize;
1454
1455 // Maximum draw buffers and color attachments are the same, max color attachments could
1456 // eventually be increased to 16
1457 caps->maxDrawBuffers = GetMaximumSimultaneousRenderTargets(featureLevel);
1458 caps->maxColorAttachments = GetMaximumSimultaneousRenderTargets(featureLevel);
1459
1460 // D3D11 has the same limit for viewport width and height
1461 caps->maxViewportWidth = GetMaximumViewportSize(featureLevel);
1462 caps->maxViewportHeight = caps->maxViewportWidth;
1463
1464 // Choose a reasonable maximum, enforced in the shader.
1465 caps->minAliasedPointSize = 1.0f;
1466 caps->maxAliasedPointSize = 1024.0f;
1467
1468 // Wide lines not supported
1469 caps->minAliasedLineWidth = 1.0f;
1470 caps->maxAliasedLineWidth = 1.0f;
1471
1472 // Primitive count limits
1473 caps->maxElementsIndices = GetMaximumDrawIndexedIndexCount(featureLevel);
1474 caps->maxElementsVertices = GetMaximumDrawVertexCount(featureLevel);
1475
1476 // Program and shader binary formats (no supported shader binary formats)
1477 caps->programBinaryFormats.push_back(GL_PROGRAM_BINARY_ANGLE);
1478
1479 caps->vertexHighpFloat.setIEEEFloat();
1480 caps->vertexMediumpFloat.setIEEEFloat();
1481 caps->vertexLowpFloat.setIEEEFloat();
1482 caps->fragmentHighpFloat.setIEEEFloat();
1483 caps->fragmentMediumpFloat.setIEEEFloat();
1484 caps->fragmentLowpFloat.setIEEEFloat();
1485
1486 // 32-bit integers are natively supported
1487 caps->vertexHighpInt.setTwosComplementInt(32);
1488 caps->vertexMediumpInt.setTwosComplementInt(32);
1489 caps->vertexLowpInt.setTwosComplementInt(32);
1490 caps->fragmentHighpInt.setTwosComplementInt(32);
1491 caps->fragmentMediumpInt.setTwosComplementInt(32);
1492 caps->fragmentLowpInt.setTwosComplementInt(32);
1493
1494 // We do not wait for server fence objects internally, so report a max timeout of zero.
1495 caps->maxServerWaitTimeout = 0;
1496
1497 // Vertex shader limits
1498 caps->maxVertexAttributes = GetMaximumVertexInputSlots(featureLevel);
1499 caps->maxVertexUniformVectors = GetMaximumVertexUniformVectors(featureLevel);
1500 if (features.skipVSConstantRegisterZero.enabled)
1501 {
1502 caps->maxVertexUniformVectors -= 1;
1503 }
1504 caps->maxShaderUniformComponents[gl::ShaderType::Vertex] = caps->maxVertexUniformVectors * 4;
1505 caps->maxShaderUniformBlocks[gl::ShaderType::Vertex] =
1506 GetMaximumVertexUniformBlocks(featureLevel);
1507 caps->maxVertexOutputComponents = GetMaximumVertexOutputVectors(featureLevel) * 4;
1508 caps->maxShaderTextureImageUnits[gl::ShaderType::Vertex] =
1509 GetMaximumVertexTextureUnits(featureLevel);
1510
1511 // Vertex Attribute Bindings are emulated on D3D11.
1512 caps->maxVertexAttribBindings = caps->maxVertexAttributes;
1513 // Experimental testing confirmed there is no explicit limit on maximum buffer offset in D3D11.
1514 caps->maxVertexAttribRelativeOffset = std::numeric_limits<GLint>::max();
1515 // Experimental testing confirmed 2048 is the maximum stride that D3D11 can support on all
1516 // platforms.
1517 caps->maxVertexAttribStride = 2048;
1518
1519 // Fragment shader limits
1520 caps->maxFragmentUniformVectors = GetMaximumPixelUniformVectors(featureLevel);
1521 caps->maxShaderUniformComponents[gl::ShaderType::Fragment] =
1522 caps->maxFragmentUniformVectors * 4;
1523 caps->maxShaderUniformBlocks[gl::ShaderType::Fragment] =
1524 GetMaximumPixelUniformBlocks(featureLevel);
1525 caps->maxFragmentInputComponents = GetMaximumPixelInputVectors(featureLevel) * 4;
1526 caps->maxShaderTextureImageUnits[gl::ShaderType::Fragment] =
1527 GetMaximumPixelTextureUnits(featureLevel);
1528 caps->minProgramTexelOffset = GetMinimumTexelOffset(featureLevel);
1529 caps->maxProgramTexelOffset = GetMaximumTexelOffset(featureLevel);
1530
1531 // Compute shader limits
1532 caps->maxComputeWorkGroupCount = GetMaxComputeWorkGroupCount(featureLevel);
1533 caps->maxComputeWorkGroupSize = GetMaxComputeWorkGroupSize(featureLevel);
1534 caps->maxComputeWorkGroupInvocations = GetMaxComputeWorkGroupInvocations(featureLevel);
1535 caps->maxComputeSharedMemorySize = GetMaxComputeSharedMemorySize(featureLevel);
1536 caps->maxShaderUniformComponents[gl::ShaderType::Compute] =
1537 GetMaximumComputeUniformVectors(featureLevel) * 4;
1538 caps->maxShaderUniformBlocks[gl::ShaderType::Compute] =
1539 GetMaximumComputeUniformBlocks(featureLevel);
1540 caps->maxShaderTextureImageUnits[gl::ShaderType::Compute] =
1541 GetMaximumComputeTextureUnits(featureLevel);
1542
1543 SetUAVRelatedResourceLimits(featureLevel, caps);
1544
1545 // Aggregate shader limits
1546 caps->maxUniformBufferBindings = caps->maxShaderUniformBlocks[gl::ShaderType::Vertex] +
1547 caps->maxShaderUniformBlocks[gl::ShaderType::Fragment];
1548 caps->maxUniformBlockSize = static_cast<GLuint64>(GetMaximumConstantBufferSize(featureLevel));
1549
1550 // TODO(oetuaho): Get a more accurate limit. For now using the minimum requirement for GLES 3.1.
1551 caps->maxUniformLocations = 1024;
1552
1553 // With DirectX 11.1, constant buffer offset and size must be a multiple of 16 constants of 16
1554 // bytes each.
1555 // https://msdn.microsoft.com/en-us/library/windows/desktop/hh404649%28v=vs.85%29.aspx
1556 // With DirectX 11.0, we emulate UBO offsets using copies of ranges of the UBO however
1557 // we still keep the same alignment as 11.1 for consistency.
1558 caps->uniformBufferOffsetAlignment = 256;
1559
1560 caps->maxCombinedUniformBlocks = caps->maxShaderUniformBlocks[gl::ShaderType::Vertex] +
1561 caps->maxShaderUniformBlocks[gl::ShaderType::Fragment];
1562
1563 // A shader storage block will be translated to a structure in HLSL. So We reference the HLSL
1564 // structure packing rules
1565 // https://msdn.microsoft.com/en-us/library/windows/desktop/bb509632(v=vs.85).aspx. The
1566 // resulting size of any structure will always be evenly divisible by sizeof(four-component
1567 // vector).
1568 caps->shaderStorageBufferOffsetAlignment = 16;
1569
1570 for (gl::ShaderType shaderType : gl::AllShaderTypes())
1571 {
1572 caps->maxCombinedShaderUniformComponents[shaderType] =
1573 static_cast<GLint64>(caps->maxShaderUniformBlocks[shaderType]) *
1574 static_cast<GLint64>(caps->maxUniformBlockSize / 4) +
1575 static_cast<GLint64>(caps->maxShaderUniformComponents[shaderType]);
1576 }
1577
1578 caps->maxVaryingComponents = GetMaximumVertexOutputVectors(featureLevel) * 4;
1579 caps->maxVaryingVectors = GetMaximumVertexOutputVectors(featureLevel);
1580 caps->maxCombinedTextureImageUnits = caps->maxShaderTextureImageUnits[gl::ShaderType::Vertex] +
1581 caps->maxShaderTextureImageUnits[gl::ShaderType::Fragment];
1582
1583 // Transform feedback limits
1584 caps->maxTransformFeedbackInterleavedComponents =
1585 GetMaximumStreamOutputInterleavedComponents(featureLevel);
1586 caps->maxTransformFeedbackSeparateAttributes = GetMaximumStreamOutputBuffers(featureLevel);
1587 caps->maxTransformFeedbackSeparateComponents =
1588 GetMaximumStreamOutputSeparateComponents(featureLevel);
1589
1590 // Defer the computation of multisample limits to Context::updateCaps() where max*Samples values
1591 // are determined according to available sample counts for each individual format.
1592 caps->maxSamples = std::numeric_limits<GLint>::max();
1593 caps->maxColorTextureSamples = std::numeric_limits<GLint>::max();
1594 caps->maxDepthTextureSamples = std::numeric_limits<GLint>::max();
1595 caps->maxIntegerSamples = std::numeric_limits<GLint>::max();
1596
1597 // Sample mask words limits
1598 caps->maxSampleMaskWords = GetMaxSampleMaskWords(featureLevel);
1599
1600 // Framebuffer limits
1601 caps->maxFramebufferSamples = std::numeric_limits<GLint>::max();
1602 caps->maxFramebufferWidth = GetMaximumRenderToBufferWindowSize(featureLevel);
1603 caps->maxFramebufferHeight = caps->maxFramebufferWidth;
1604
1605 // Texture gather offset limits
1606 caps->minProgramTextureGatherOffset = GetMinimumTextureGatherOffset(featureLevel);
1607 caps->maxProgramTextureGatherOffset = GetMaximumTextureGatherOffset(featureLevel);
1608
1609 caps->maxTextureAnisotropy = GetMaximumAnisotropy(featureLevel);
1610 caps->queryCounterBitsTimeElapsed = 64;
1611
1612 caps->queryCounterBitsTimestamp = features.enableTimestampQueries.enabled ? 64 : 0;
1613
1614 caps->maxDualSourceDrawBuffers = 1;
1615
1616 // GL extension support
1617 extensions->setTextureExtensionSupport(*textureCapsMap);
1618
1619 // Explicitly disable GL_OES_compressed_ETC1_RGB8_texture because it's emulated and never
1620 // becomes core. WebGL doesn't want to expose it unless there is native support.
1621 extensions->compressedETC1RGB8TextureOES = false;
1622 extensions->compressedETC1RGB8SubTextureEXT = false;
1623
1624 extensions->elementIndexUintOES = true;
1625 extensions->getProgramBinaryOES = true;
1626 extensions->rgb8Rgba8OES = true;
1627 extensions->readFormatBgraEXT = true;
1628 extensions->pixelBufferObjectNV = true;
1629 extensions->mapbufferOES = true;
1630 extensions->mapBufferRangeEXT = true;
1631 extensions->textureNpotOES = GetNPOTTextureSupport(featureLevel);
1632 extensions->drawBuffersEXT = GetMaximumSimultaneousRenderTargets(featureLevel) > 1;
1633 extensions->drawBuffersIndexedEXT = (featureLevel >= D3D_FEATURE_LEVEL_10_1);
1634 extensions->drawBuffersIndexedOES = extensions->drawBuffersIndexedEXT;
1635 extensions->textureStorageEXT = true;
1636 extensions->textureFilterAnisotropicEXT = true;
1637 extensions->occlusionQueryBooleanEXT = GetOcclusionQuerySupport(featureLevel);
1638 extensions->fenceNV = GetEventQuerySupport(featureLevel);
1639 extensions->disjointTimerQueryEXT = true;
1640 extensions->robustnessEXT = true;
1641 extensions->robustnessKHR = true;
1642 // Direct3D guarantees to return zero for any resource that is accessed out of bounds.
1643 // See https://msdn.microsoft.com/en-us/library/windows/desktop/ff476332(v=vs.85).aspx
1644 // and https://msdn.microsoft.com/en-us/library/windows/desktop/ff476900(v=vs.85).aspx
1645 extensions->robustBufferAccessBehaviorKHR = true;
1646 extensions->blendMinmaxEXT = true;
1647 // https://docs.microsoft.com/en-us/windows/desktop/direct3ddxgi/format-support-for-direct3d-11-0-feature-level-hardware
1648 extensions->floatBlendEXT = true;
1649 extensions->framebufferBlitANGLE = GetFramebufferBlitSupport(featureLevel);
1650 extensions->framebufferBlitNV = extensions->framebufferBlitANGLE;
1651 extensions->framebufferMultisampleANGLE = GetFramebufferMultisampleSupport(featureLevel);
1652 extensions->instancedArraysANGLE = GetInstancingSupport(featureLevel);
1653 extensions->instancedArraysEXT = GetInstancingSupport(featureLevel);
1654 extensions->packReverseRowOrderANGLE = true;
1655 extensions->standardDerivativesOES = GetDerivativeInstructionSupport(featureLevel);
1656 extensions->shaderTextureLodEXT = GetShaderTextureLODSupport(featureLevel);
1657 extensions->fragDepthEXT = true;
1658 extensions->conservativeDepthEXT = (featureLevel >= D3D_FEATURE_LEVEL_11_0);
1659 extensions->polygonModeANGLE = true;
1660 extensions->polygonOffsetClampEXT = (featureLevel >= D3D_FEATURE_LEVEL_10_0);
1661 extensions->depthClampEXT = true;
1662 extensions->stencilTexturingANGLE = (featureLevel >= D3D_FEATURE_LEVEL_10_1);
1663 extensions->multiviewOVR = IsMultiviewSupported(featureLevel);
1664 extensions->multiview2OVR = IsMultiviewSupported(featureLevel);
1665 if (extensions->multiviewOVR || extensions->multiview2OVR)
1666 {
1667 caps->maxViews = std::min(static_cast<GLuint>(GetMaximum2DTextureArraySize(featureLevel)),
1668 GetMaxViewportAndScissorRectanglesPerPipeline(featureLevel));
1669 }
1670 extensions->textureUsageANGLE = true; // This could be false since it has no effect in D3D11
1671 extensions->discardFramebufferEXT = true;
1672 extensions->translatedShaderSourceANGLE = true;
1673 extensions->fboRenderMipmapOES = true;
1674 extensions->debugMarkerEXT = true;
1675 extensions->EGLImageOES = true;
1676 extensions->EGLImageExternalOES = true;
1677 extensions->EGLImageExternalWrapModesEXT = true;
1678 extensions->EGLImageExternalEssl3OES = true;
1679 extensions->EGLStreamConsumerExternalNV = true;
1680 extensions->unpackSubimageEXT = true;
1681 extensions->packSubimageNV = true;
1682 extensions->lossyEtcDecodeANGLE = true;
1683 extensions->syncQueryCHROMIUM = GetEventQuerySupport(featureLevel);
1684 extensions->copyTextureCHROMIUM = true;
1685 extensions->copyCompressedTextureCHROMIUM = true;
1686 extensions->textureStorageMultisample2dArrayOES = true;
1687 extensions->textureMirrorClampToEdgeEXT = true;
1688 extensions->shaderNoperspectiveInterpolationNV = (featureLevel >= D3D_FEATURE_LEVEL_10_0);
1689 extensions->sampleVariablesOES = (featureLevel >= D3D_FEATURE_LEVEL_11_0);
1690 extensions->shaderMultisampleInterpolationOES = (featureLevel >= D3D_FEATURE_LEVEL_11_0);
1691 if (extensions->shaderMultisampleInterpolationOES)
1692 {
1693 caps->subPixelInterpolationOffsetBits = 4;
1694 caps->minInterpolationOffset = -0.5f;
1695 caps->maxInterpolationOffset = +0.4375f; // +0.5 - (2 ^ -4)
1696 }
1697 extensions->multiviewMultisampleANGLE =
1698 ((extensions->multiviewOVR || extensions->multiview2OVR) &&
1699 extensions->textureStorageMultisample2dArrayOES);
1700 extensions->copyTexture3dANGLE = true;
1701 extensions->textureBorderClampEXT = true;
1702 extensions->textureBorderClampOES = true;
1703 extensions->multiDrawIndirectEXT = true;
1704 extensions->textureMultisampleANGLE = true;
1705 extensions->provokingVertexANGLE = true;
1706 extensions->blendFuncExtendedEXT = true;
1707 // http://anglebug.com/42263500
1708 extensions->texture3DOES = false;
1709 extensions->baseInstanceEXT = true;
1710 extensions->baseVertexBaseInstanceANGLE = true;
1711 extensions->baseVertexBaseInstanceShaderBuiltinANGLE = true;
1712 extensions->drawElementsBaseVertexOES = true;
1713 extensions->drawElementsBaseVertexEXT = true;
1714 if (!strstr(description, "Adreno"))
1715 {
1716 extensions->multisampledRenderToTextureEXT = true;
1717 }
1718 extensions->videoTextureWEBGL = true;
1719
1720 // D3D11 cannot support reading depth texture as a luminance texture.
1721 // It treats it as a red-channel-only texture.
1722 extensions->depthTextureOES = false;
1723
1724 // readPixels on depth & stencil not working with D3D11 backend.
1725 extensions->readDepthNV = false;
1726 extensions->readStencilNV = false;
1727 extensions->depthBufferFloat2NV = false;
1728
1729 // GL_EXT_clip_control
1730 extensions->clipControlEXT = (featureLevel >= D3D_FEATURE_LEVEL_10_0);
1731
1732 // GL_APPLE_clip_distance / GL_EXT_clip_cull_distance / GL_ANGLE_clip_cull_distance
1733 extensions->clipDistanceAPPLE = true;
1734 extensions->clipCullDistanceEXT = true;
1735 extensions->clipCullDistanceANGLE = true;
1736 caps->maxClipDistances = D3D11_CLIP_OR_CULL_DISTANCE_COUNT;
1737 caps->maxCullDistances = D3D11_CLIP_OR_CULL_DISTANCE_COUNT;
1738 caps->maxCombinedClipAndCullDistances = D3D11_CLIP_OR_CULL_DISTANCE_COUNT;
1739
1740 // GL_KHR_parallel_shader_compile
1741 extensions->parallelShaderCompileKHR = true;
1742
1743 // GL_EXT_texture_buffer
1744 extensions->textureBufferEXT = HasTextureBufferSupport(device, renderer11DeviceCaps);
1745
1746 // GL_OES_texture_buffer
1747 extensions->textureBufferOES = extensions->textureBufferEXT;
1748
1749 // ANGLE_shader_pixel_local_storage -- fragment shader UAVs appear in D3D 11.0.
1750 if (featureLevel >= D3D_FEATURE_LEVEL_11_0)
1751 {
1752 extensions->shaderPixelLocalStorageANGLE = true;
1753 plsOptions->type = ShPixelLocalStorageType::ImageLoadStore;
1754 if (renderer11DeviceCaps.supportsRasterizerOrderViews)
1755 {
1756 extensions->shaderPixelLocalStorageCoherentANGLE = true;
1757 plsOptions->fragmentSyncType = ShFragmentSynchronizationType::RasterizerOrderViews_D3D;
1758 }
1759 // TODO(anglebug.com/40096838): If we add RG* support to pixel local storage, these are
1760 // *NOT* in the set of common formats, so we need to query support for each individualy:
1761 // https://learn.microsoft.com/en-us/windows/win32/direct3d11/typed-unordered-access-view-loads
1762 plsOptions->supportsNativeRGBA8ImageFormats =
1763 renderer11DeviceCaps.supportsUAVLoadStoreCommonFormats;
1764 }
1765
1766 // D3D11 Feature Level 10_0+ uses SV_IsFrontFace in HLSL to emulate gl_FrontFacing.
1767 // D3D11 Feature Level 9_3 doesn't support SV_IsFrontFace, and has no equivalent, so can't
1768 // support gl_FrontFacing.
1769 limitations->noFrontFacingSupport = (featureLevel <= D3D_FEATURE_LEVEL_9_3);
1770
1771 // D3D11 Feature Level 9_3 doesn't support alpha-to-coverage
1772 limitations->noSampleAlphaToCoverageSupport = (featureLevel <= D3D_FEATURE_LEVEL_9_3);
1773
1774 // D3D11 has no concept of separate masks and refs for front and back faces in the depth stencil
1775 // state.
1776 limitations->noSeparateStencilRefsAndMasks = true;
1777
1778 // D3D11 cannot support constant color and alpha blend funcs together
1779 limitations->noSimultaneousConstantColorAndAlphaBlendFunc = true;
1780
1781 // D3D11 does not support multiple transform feedback outputs writing to the same buffer.
1782 limitations->noDoubleBoundTransformFeedbackBuffers = true;
1783
1784 // D3D11 does not support vertex attribute aliasing
1785 limitations->noVertexAttributeAliasing = true;
1786
1787 // D3D11 does not support compressed textures where the base mip level is not a multiple of 4
1788 limitations->compressedBaseMipLevelMultipleOfFour = true;
1789
1790 if (extensions->textureBufferAny())
1791 {
1792 caps->maxTextureBufferSize = 1 << D3D11_REQ_BUFFER_RESOURCE_TEXEL_COUNT_2_TO_EXP;
1793 // this maybe touble for RGB32 format.
1794 caps->textureBufferOffsetAlignment = 16;
1795 }
1796
1797 #ifdef ANGLE_ENABLE_WINDOWS_UWP
1798 // Setting a non-zero divisor on attribute zero doesn't work on certain Windows Phone 8-era
1799 // devices. We should prevent developers from doing this on ALL Windows Store devices. This will
1800 // maintain consistency across all Windows devices. We allow non-zero divisors on attribute zero
1801 // if the Client Version >= 3, since devices affected by this issue don't support ES3+.
1802 limitations->attributeZeroRequiresZeroDivisorInEXT = true;
1803 #endif
1804 }
1805
1806 } // namespace d3d11_gl
1807
1808 namespace gl_d3d11
1809 {
1810
ConvertBlendFunc(gl::BlendFactorType glBlend,bool isAlpha)1811 D3D11_BLEND ConvertBlendFunc(gl::BlendFactorType glBlend, bool isAlpha)
1812 {
1813 D3D11_BLEND d3dBlend = D3D11_BLEND_ZERO;
1814
1815 switch (glBlend)
1816 {
1817 case gl::BlendFactorType::Zero:
1818 d3dBlend = D3D11_BLEND_ZERO;
1819 break;
1820 case gl::BlendFactorType::One:
1821 d3dBlend = D3D11_BLEND_ONE;
1822 break;
1823 case gl::BlendFactorType::SrcColor:
1824 d3dBlend = (isAlpha ? D3D11_BLEND_SRC_ALPHA : D3D11_BLEND_SRC_COLOR);
1825 break;
1826 case gl::BlendFactorType::OneMinusSrcColor:
1827 d3dBlend = (isAlpha ? D3D11_BLEND_INV_SRC_ALPHA : D3D11_BLEND_INV_SRC_COLOR);
1828 break;
1829 case gl::BlendFactorType::DstColor:
1830 d3dBlend = (isAlpha ? D3D11_BLEND_DEST_ALPHA : D3D11_BLEND_DEST_COLOR);
1831 break;
1832 case gl::BlendFactorType::OneMinusDstColor:
1833 d3dBlend = (isAlpha ? D3D11_BLEND_INV_DEST_ALPHA : D3D11_BLEND_INV_DEST_COLOR);
1834 break;
1835 case gl::BlendFactorType::SrcAlpha:
1836 d3dBlend = D3D11_BLEND_SRC_ALPHA;
1837 break;
1838 case gl::BlendFactorType::OneMinusSrcAlpha:
1839 d3dBlend = D3D11_BLEND_INV_SRC_ALPHA;
1840 break;
1841 case gl::BlendFactorType::DstAlpha:
1842 d3dBlend = D3D11_BLEND_DEST_ALPHA;
1843 break;
1844 case gl::BlendFactorType::OneMinusDstAlpha:
1845 d3dBlend = D3D11_BLEND_INV_DEST_ALPHA;
1846 break;
1847 case gl::BlendFactorType::ConstantColor:
1848 d3dBlend = D3D11_BLEND_BLEND_FACTOR;
1849 break;
1850 case gl::BlendFactorType::OneMinusConstantColor:
1851 d3dBlend = D3D11_BLEND_INV_BLEND_FACTOR;
1852 break;
1853 case gl::BlendFactorType::ConstantAlpha:
1854 d3dBlend = D3D11_BLEND_BLEND_FACTOR;
1855 break;
1856 case gl::BlendFactorType::OneMinusConstantAlpha:
1857 d3dBlend = D3D11_BLEND_INV_BLEND_FACTOR;
1858 break;
1859 case gl::BlendFactorType::SrcAlphaSaturate:
1860 d3dBlend = D3D11_BLEND_SRC_ALPHA_SAT;
1861 break;
1862 case gl::BlendFactorType::Src1Color:
1863 d3dBlend = (isAlpha ? D3D11_BLEND_SRC1_ALPHA : D3D11_BLEND_SRC1_COLOR);
1864 break;
1865 case gl::BlendFactorType::Src1Alpha:
1866 d3dBlend = D3D11_BLEND_SRC1_ALPHA;
1867 break;
1868 case gl::BlendFactorType::OneMinusSrc1Color:
1869 d3dBlend = (isAlpha ? D3D11_BLEND_INV_SRC1_ALPHA : D3D11_BLEND_INV_SRC1_COLOR);
1870 break;
1871 case gl::BlendFactorType::OneMinusSrc1Alpha:
1872 d3dBlend = D3D11_BLEND_INV_SRC1_ALPHA;
1873 break;
1874 default:
1875 UNREACHABLE();
1876 }
1877
1878 return d3dBlend;
1879 }
1880
ConvertBlendOp(gl::BlendEquationType glBlendOp)1881 D3D11_BLEND_OP ConvertBlendOp(gl::BlendEquationType glBlendOp)
1882 {
1883 D3D11_BLEND_OP d3dBlendOp = D3D11_BLEND_OP_ADD;
1884
1885 switch (glBlendOp)
1886 {
1887 case gl::BlendEquationType::Add:
1888 d3dBlendOp = D3D11_BLEND_OP_ADD;
1889 break;
1890 case gl::BlendEquationType::Subtract:
1891 d3dBlendOp = D3D11_BLEND_OP_SUBTRACT;
1892 break;
1893 case gl::BlendEquationType::ReverseSubtract:
1894 d3dBlendOp = D3D11_BLEND_OP_REV_SUBTRACT;
1895 break;
1896 case gl::BlendEquationType::Min:
1897 d3dBlendOp = D3D11_BLEND_OP_MIN;
1898 break;
1899 case gl::BlendEquationType::Max:
1900 d3dBlendOp = D3D11_BLEND_OP_MAX;
1901 break;
1902 default:
1903 UNREACHABLE();
1904 }
1905
1906 return d3dBlendOp;
1907 }
1908
ConvertColorMask(bool red,bool green,bool blue,bool alpha)1909 UINT8 ConvertColorMask(bool red, bool green, bool blue, bool alpha)
1910 {
1911 UINT8 mask = 0;
1912 if (red)
1913 {
1914 mask |= D3D11_COLOR_WRITE_ENABLE_RED;
1915 }
1916 if (green)
1917 {
1918 mask |= D3D11_COLOR_WRITE_ENABLE_GREEN;
1919 }
1920 if (blue)
1921 {
1922 mask |= D3D11_COLOR_WRITE_ENABLE_BLUE;
1923 }
1924 if (alpha)
1925 {
1926 mask |= D3D11_COLOR_WRITE_ENABLE_ALPHA;
1927 }
1928 return mask;
1929 }
1930
ConvertCullMode(bool cullEnabled,gl::CullFaceMode cullMode)1931 D3D11_CULL_MODE ConvertCullMode(bool cullEnabled, gl::CullFaceMode cullMode)
1932 {
1933 D3D11_CULL_MODE cull = D3D11_CULL_NONE;
1934
1935 if (cullEnabled)
1936 {
1937 switch (cullMode)
1938 {
1939 case gl::CullFaceMode::Front:
1940 cull = D3D11_CULL_FRONT;
1941 break;
1942 case gl::CullFaceMode::Back:
1943 cull = D3D11_CULL_BACK;
1944 break;
1945 case gl::CullFaceMode::FrontAndBack:
1946 cull = D3D11_CULL_NONE;
1947 break;
1948 default:
1949 UNREACHABLE();
1950 }
1951 }
1952 else
1953 {
1954 cull = D3D11_CULL_NONE;
1955 }
1956
1957 return cull;
1958 }
1959
ConvertComparison(GLenum comparison)1960 D3D11_COMPARISON_FUNC ConvertComparison(GLenum comparison)
1961 {
1962 D3D11_COMPARISON_FUNC d3dComp = D3D11_COMPARISON_NEVER;
1963 switch (comparison)
1964 {
1965 case GL_NEVER:
1966 d3dComp = D3D11_COMPARISON_NEVER;
1967 break;
1968 case GL_ALWAYS:
1969 d3dComp = D3D11_COMPARISON_ALWAYS;
1970 break;
1971 case GL_LESS:
1972 d3dComp = D3D11_COMPARISON_LESS;
1973 break;
1974 case GL_LEQUAL:
1975 d3dComp = D3D11_COMPARISON_LESS_EQUAL;
1976 break;
1977 case GL_EQUAL:
1978 d3dComp = D3D11_COMPARISON_EQUAL;
1979 break;
1980 case GL_GREATER:
1981 d3dComp = D3D11_COMPARISON_GREATER;
1982 break;
1983 case GL_GEQUAL:
1984 d3dComp = D3D11_COMPARISON_GREATER_EQUAL;
1985 break;
1986 case GL_NOTEQUAL:
1987 d3dComp = D3D11_COMPARISON_NOT_EQUAL;
1988 break;
1989 default:
1990 UNREACHABLE();
1991 }
1992
1993 return d3dComp;
1994 }
1995
ConvertDepthMask(bool depthWriteEnabled)1996 D3D11_DEPTH_WRITE_MASK ConvertDepthMask(bool depthWriteEnabled)
1997 {
1998 return depthWriteEnabled ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO;
1999 }
2000
ConvertStencilMask(GLuint stencilmask)2001 UINT8 ConvertStencilMask(GLuint stencilmask)
2002 {
2003 return static_cast<UINT8>(stencilmask);
2004 }
2005
ConvertStencilOp(GLenum stencilOp)2006 D3D11_STENCIL_OP ConvertStencilOp(GLenum stencilOp)
2007 {
2008 D3D11_STENCIL_OP d3dStencilOp = D3D11_STENCIL_OP_KEEP;
2009
2010 switch (stencilOp)
2011 {
2012 case GL_ZERO:
2013 d3dStencilOp = D3D11_STENCIL_OP_ZERO;
2014 break;
2015 case GL_KEEP:
2016 d3dStencilOp = D3D11_STENCIL_OP_KEEP;
2017 break;
2018 case GL_REPLACE:
2019 d3dStencilOp = D3D11_STENCIL_OP_REPLACE;
2020 break;
2021 case GL_INCR:
2022 d3dStencilOp = D3D11_STENCIL_OP_INCR_SAT;
2023 break;
2024 case GL_DECR:
2025 d3dStencilOp = D3D11_STENCIL_OP_DECR_SAT;
2026 break;
2027 case GL_INVERT:
2028 d3dStencilOp = D3D11_STENCIL_OP_INVERT;
2029 break;
2030 case GL_INCR_WRAP:
2031 d3dStencilOp = D3D11_STENCIL_OP_INCR;
2032 break;
2033 case GL_DECR_WRAP:
2034 d3dStencilOp = D3D11_STENCIL_OP_DECR;
2035 break;
2036 default:
2037 UNREACHABLE();
2038 }
2039
2040 return d3dStencilOp;
2041 }
2042
ConvertFilter(GLenum minFilter,GLenum magFilter,float maxAnisotropy,GLenum comparisonMode)2043 D3D11_FILTER ConvertFilter(GLenum minFilter,
2044 GLenum magFilter,
2045 float maxAnisotropy,
2046 GLenum comparisonMode)
2047 {
2048 bool comparison = comparisonMode != GL_NONE;
2049
2050 if (maxAnisotropy > 1.0f)
2051 {
2052 return D3D11_ENCODE_ANISOTROPIC_FILTER(static_cast<D3D11_COMPARISON_FUNC>(comparison));
2053 }
2054 else
2055 {
2056 D3D11_FILTER_TYPE dxMin = D3D11_FILTER_TYPE_POINT;
2057 D3D11_FILTER_TYPE dxMip = D3D11_FILTER_TYPE_POINT;
2058 switch (minFilter)
2059 {
2060 case GL_NEAREST:
2061 dxMin = D3D11_FILTER_TYPE_POINT;
2062 dxMip = D3D11_FILTER_TYPE_POINT;
2063 break;
2064 case GL_LINEAR:
2065 dxMin = D3D11_FILTER_TYPE_LINEAR;
2066 dxMip = D3D11_FILTER_TYPE_POINT;
2067 break;
2068 case GL_NEAREST_MIPMAP_NEAREST:
2069 dxMin = D3D11_FILTER_TYPE_POINT;
2070 dxMip = D3D11_FILTER_TYPE_POINT;
2071 break;
2072 case GL_LINEAR_MIPMAP_NEAREST:
2073 dxMin = D3D11_FILTER_TYPE_LINEAR;
2074 dxMip = D3D11_FILTER_TYPE_POINT;
2075 break;
2076 case GL_NEAREST_MIPMAP_LINEAR:
2077 dxMin = D3D11_FILTER_TYPE_POINT;
2078 dxMip = D3D11_FILTER_TYPE_LINEAR;
2079 break;
2080 case GL_LINEAR_MIPMAP_LINEAR:
2081 dxMin = D3D11_FILTER_TYPE_LINEAR;
2082 dxMip = D3D11_FILTER_TYPE_LINEAR;
2083 break;
2084 default:
2085 UNREACHABLE();
2086 }
2087
2088 D3D11_FILTER_TYPE dxMag = D3D11_FILTER_TYPE_POINT;
2089 switch (magFilter)
2090 {
2091 case GL_NEAREST:
2092 dxMag = D3D11_FILTER_TYPE_POINT;
2093 break;
2094 case GL_LINEAR:
2095 dxMag = D3D11_FILTER_TYPE_LINEAR;
2096 break;
2097 default:
2098 UNREACHABLE();
2099 }
2100
2101 return D3D11_ENCODE_BASIC_FILTER(dxMin, dxMag, dxMip,
2102 static_cast<D3D11_COMPARISON_FUNC>(comparison));
2103 }
2104 }
2105
ConvertTextureWrap(GLenum wrap)2106 D3D11_TEXTURE_ADDRESS_MODE ConvertTextureWrap(GLenum wrap)
2107 {
2108 switch (wrap)
2109 {
2110 case GL_REPEAT:
2111 return D3D11_TEXTURE_ADDRESS_WRAP;
2112 case GL_MIRRORED_REPEAT:
2113 return D3D11_TEXTURE_ADDRESS_MIRROR;
2114 case GL_CLAMP_TO_EDGE:
2115 return D3D11_TEXTURE_ADDRESS_CLAMP;
2116 case GL_CLAMP_TO_BORDER:
2117 return D3D11_TEXTURE_ADDRESS_BORDER;
2118 case GL_MIRROR_CLAMP_TO_EDGE_EXT:
2119 return D3D11_TEXTURE_ADDRESS_MIRROR_ONCE;
2120 default:
2121 UNREACHABLE();
2122 }
2123
2124 return D3D11_TEXTURE_ADDRESS_WRAP;
2125 }
2126
ConvertMaxAnisotropy(float maxAnisotropy,D3D_FEATURE_LEVEL featureLevel)2127 UINT ConvertMaxAnisotropy(float maxAnisotropy, D3D_FEATURE_LEVEL featureLevel)
2128 {
2129 return static_cast<UINT>(std::min(maxAnisotropy, d3d11_gl::GetMaximumAnisotropy(featureLevel)));
2130 }
2131
ConvertQueryType(gl::QueryType type)2132 D3D11_QUERY ConvertQueryType(gl::QueryType type)
2133 {
2134 switch (type)
2135 {
2136 case gl::QueryType::AnySamples:
2137 case gl::QueryType::AnySamplesConservative:
2138 return D3D11_QUERY_OCCLUSION;
2139 case gl::QueryType::TransformFeedbackPrimitivesWritten:
2140 return D3D11_QUERY_SO_STATISTICS;
2141 case gl::QueryType::TimeElapsed:
2142 // Two internal queries are also created for begin/end timestamps
2143 return D3D11_QUERY_TIMESTAMP_DISJOINT;
2144 case gl::QueryType::Timestamp:
2145 // A disjoint query is also created for timestamp
2146 return D3D11_QUERY_TIMESTAMP_DISJOINT;
2147 case gl::QueryType::CommandsCompleted:
2148 return D3D11_QUERY_EVENT;
2149 default:
2150 UNREACHABLE();
2151 return D3D11_QUERY_EVENT;
2152 }
2153 }
2154
2155 // Get the D3D11 write mask covering all color channels of a given format
GetColorMask(const gl::InternalFormat & format)2156 UINT8 GetColorMask(const gl::InternalFormat &format)
2157 {
2158 return ConvertColorMask(format.redBits > 0, format.greenBits > 0, format.blueBits > 0,
2159 format.alphaBits > 0);
2160 }
2161
2162 } // namespace gl_d3d11
2163
2164 namespace d3d11
2165 {
2166
GetDeviceType(ID3D11Device * device)2167 ANGLED3D11DeviceType GetDeviceType(ID3D11Device *device)
2168 {
2169 // Note that this function returns an ANGLED3D11DeviceType rather than a D3D_DRIVER_TYPE value,
2170 // since it is difficult to tell Software and Reference devices apart
2171
2172 IDXGIDevice *dxgiDevice = nullptr;
2173 IDXGIAdapter *dxgiAdapter = nullptr;
2174 IDXGIAdapter2 *dxgiAdapter2 = nullptr;
2175
2176 ANGLED3D11DeviceType retDeviceType = ANGLE_D3D11_DEVICE_TYPE_UNKNOWN;
2177
2178 HRESULT hr = device->QueryInterface(__uuidof(IDXGIDevice), (void **)&dxgiDevice);
2179 if (SUCCEEDED(hr))
2180 {
2181 hr = dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void **)&dxgiAdapter);
2182 if (SUCCEEDED(hr))
2183 {
2184 std::wstring adapterString;
2185 HRESULT adapter2hr =
2186 dxgiAdapter->QueryInterface(__uuidof(dxgiAdapter2), (void **)&dxgiAdapter2);
2187 if (SUCCEEDED(adapter2hr))
2188 {
2189 // On D3D_FEATURE_LEVEL_9_*, IDXGIAdapter::GetDesc returns "Software Adapter"
2190 // for the description string. Try to use IDXGIAdapter2::GetDesc2 to get the
2191 // actual hardware values if possible.
2192 DXGI_ADAPTER_DESC2 adapterDesc2;
2193 dxgiAdapter2->GetDesc2(&adapterDesc2);
2194 adapterString = std::wstring(adapterDesc2.Description);
2195 }
2196 else
2197 {
2198 DXGI_ADAPTER_DESC adapterDesc;
2199 dxgiAdapter->GetDesc(&adapterDesc);
2200 adapterString = std::wstring(adapterDesc.Description);
2201 }
2202
2203 // Both Reference and Software adapters will be 'Software Adapter'
2204 const bool isSoftwareDevice =
2205 (adapterString.find(std::wstring(L"Software Adapter")) != std::string::npos);
2206 const bool isNullDevice = (adapterString == L"");
2207 const bool isWARPDevice =
2208 (adapterString.find(std::wstring(L"Basic Render")) != std::string::npos);
2209
2210 if (isSoftwareDevice || isNullDevice)
2211 {
2212 ASSERT(!isWARPDevice);
2213 retDeviceType = ANGLE_D3D11_DEVICE_TYPE_SOFTWARE_REF_OR_NULL;
2214 }
2215 else if (isWARPDevice)
2216 {
2217 retDeviceType = ANGLE_D3D11_DEVICE_TYPE_WARP;
2218 }
2219 else
2220 {
2221 retDeviceType = ANGLE_D3D11_DEVICE_TYPE_HARDWARE;
2222 }
2223 }
2224 }
2225
2226 SafeRelease(dxgiDevice);
2227 SafeRelease(dxgiAdapter);
2228 SafeRelease(dxgiAdapter2);
2229
2230 return retDeviceType;
2231 }
2232
MakeValidSize(bool isImage,DXGI_FORMAT format,GLsizei * requestWidth,GLsizei * requestHeight,int * levelOffset)2233 void MakeValidSize(bool isImage,
2234 DXGI_FORMAT format,
2235 GLsizei *requestWidth,
2236 GLsizei *requestHeight,
2237 int *levelOffset)
2238 {
2239 const DXGIFormatSize &dxgiFormatInfo = d3d11::GetDXGIFormatSizeInfo(format);
2240 bool validFormat = format != DXGI_FORMAT_UNKNOWN;
2241 bool validImage = isImage && validFormat;
2242
2243 int upsampleCount = 0;
2244 // Don't expand the size of full textures that are at least (blockWidth x blockHeight) already.
2245 if (validImage || *requestWidth < static_cast<GLsizei>(dxgiFormatInfo.blockWidth) ||
2246 *requestHeight < static_cast<GLsizei>(dxgiFormatInfo.blockHeight))
2247 {
2248 while (*requestWidth % dxgiFormatInfo.blockWidth != 0 ||
2249 *requestHeight % dxgiFormatInfo.blockHeight != 0)
2250 {
2251 *requestWidth <<= 1;
2252 *requestHeight <<= 1;
2253 upsampleCount++;
2254 }
2255 }
2256 else if (validFormat)
2257 {
2258 if (*requestWidth % dxgiFormatInfo.blockWidth != 0)
2259 {
2260 *requestWidth = roundUp(*requestWidth, static_cast<GLsizei>(dxgiFormatInfo.blockWidth));
2261 }
2262
2263 if (*requestHeight % dxgiFormatInfo.blockHeight != 0)
2264 {
2265 *requestHeight =
2266 roundUp(*requestHeight, static_cast<GLsizei>(dxgiFormatInfo.blockHeight));
2267 }
2268 }
2269
2270 if (levelOffset)
2271 {
2272 *levelOffset = upsampleCount;
2273 }
2274 }
2275
GenerateInitialTextureData(const gl::Context * context,GLint internalFormat,const Renderer11DeviceCaps & renderer11DeviceCaps,GLuint width,GLuint height,GLuint depth,GLuint mipLevels,gl::TexLevelArray<D3D11_SUBRESOURCE_DATA> * outSubresourceData)2276 angle::Result GenerateInitialTextureData(
2277 const gl::Context *context,
2278 GLint internalFormat,
2279 const Renderer11DeviceCaps &renderer11DeviceCaps,
2280 GLuint width,
2281 GLuint height,
2282 GLuint depth,
2283 GLuint mipLevels,
2284 gl::TexLevelArray<D3D11_SUBRESOURCE_DATA> *outSubresourceData)
2285 {
2286 const d3d11::Format &d3dFormatInfo = d3d11::Format::Get(internalFormat, renderer11DeviceCaps);
2287 ASSERT(d3dFormatInfo.dataInitializerFunction != nullptr);
2288
2289 const d3d11::DXGIFormatSize &dxgiFormatInfo =
2290 d3d11::GetDXGIFormatSizeInfo(d3dFormatInfo.texFormat);
2291
2292 using CheckedSize = angle::CheckedNumeric<size_t>;
2293 CheckedSize rowPitch = CheckedSize(dxgiFormatInfo.pixelBytes) * CheckedSize(width);
2294 CheckedSize depthPitch = rowPitch * CheckedSize(height);
2295 CheckedSize maxImageSize = depthPitch * CheckedSize(depth);
2296
2297 Context11 *context11 = GetImplAs<Context11>(context);
2298 ANGLE_CHECK_GL_ALLOC(context11, maxImageSize.IsValid());
2299
2300 angle::MemoryBuffer *scratchBuffer = nullptr;
2301 ANGLE_CHECK_GL_ALLOC(context11,
2302 context->getScratchBuffer(maxImageSize.ValueOrDie(), &scratchBuffer));
2303
2304 d3dFormatInfo.dataInitializerFunction(width, height, depth, scratchBuffer->data(),
2305 rowPitch.ValueOrDie(), depthPitch.ValueOrDie());
2306
2307 for (unsigned int i = 0; i < mipLevels; i++)
2308 {
2309 unsigned int mipWidth = std::max(width >> i, 1U);
2310 unsigned int mipHeight = std::max(height >> i, 1U);
2311
2312 using CheckedUINT = angle::CheckedNumeric<UINT>;
2313 CheckedUINT mipRowPitch = CheckedUINT(dxgiFormatInfo.pixelBytes) * CheckedUINT(mipWidth);
2314 CheckedUINT mipDepthPitch = mipRowPitch * CheckedUINT(mipHeight);
2315
2316 ANGLE_CHECK_GL_ALLOC(context11, mipRowPitch.IsValid() && mipDepthPitch.IsValid());
2317
2318 outSubresourceData->at(i).pSysMem = scratchBuffer->data();
2319 outSubresourceData->at(i).SysMemPitch = mipRowPitch.ValueOrDie();
2320 outSubresourceData->at(i).SysMemSlicePitch = mipDepthPitch.ValueOrDie();
2321 }
2322
2323 return angle::Result::Continue;
2324 }
2325
GetPrimitiveRestartIndex()2326 UINT GetPrimitiveRestartIndex()
2327 {
2328 return std::numeric_limits<UINT>::max();
2329 }
2330
SetPositionTexCoordVertex(PositionTexCoordVertex * vertex,float x,float y,float u,float v)2331 void SetPositionTexCoordVertex(PositionTexCoordVertex *vertex, float x, float y, float u, float v)
2332 {
2333 vertex->x = x;
2334 vertex->y = y;
2335 vertex->u = u;
2336 vertex->v = v;
2337 }
2338
SetPositionLayerTexCoord3DVertex(PositionLayerTexCoord3DVertex * vertex,float x,float y,unsigned int layer,float u,float v,float s)2339 void SetPositionLayerTexCoord3DVertex(PositionLayerTexCoord3DVertex *vertex,
2340 float x,
2341 float y,
2342 unsigned int layer,
2343 float u,
2344 float v,
2345 float s)
2346 {
2347 vertex->x = x;
2348 vertex->y = y;
2349 vertex->l = layer;
2350 vertex->u = u;
2351 vertex->v = v;
2352 vertex->s = s;
2353 }
2354
BlendStateKey()2355 BlendStateKey::BlendStateKey()
2356 {
2357 memset(this, 0, sizeof(BlendStateKey));
2358 blendStateExt = gl::BlendStateExt();
2359 }
2360
BlendStateKey(const BlendStateKey & other)2361 BlendStateKey::BlendStateKey(const BlendStateKey &other)
2362 {
2363 memcpy(this, &other, sizeof(BlendStateKey));
2364 }
2365
operator ==(const BlendStateKey & a,const BlendStateKey & b)2366 bool operator==(const BlendStateKey &a, const BlendStateKey &b)
2367 {
2368 return memcmp(&a, &b, sizeof(BlendStateKey)) == 0;
2369 }
2370
operator !=(const BlendStateKey & a,const BlendStateKey & b)2371 bool operator!=(const BlendStateKey &a, const BlendStateKey &b)
2372 {
2373 return !(a == b);
2374 }
2375
RasterizerStateKey()2376 RasterizerStateKey::RasterizerStateKey()
2377 {
2378 memset(this, 0, sizeof(RasterizerStateKey));
2379 }
2380
operator ==(const RasterizerStateKey & a,const RasterizerStateKey & b)2381 bool operator==(const RasterizerStateKey &a, const RasterizerStateKey &b)
2382 {
2383 return memcmp(&a, &b, sizeof(RasterizerStateKey)) == 0;
2384 }
2385
operator !=(const RasterizerStateKey & a,const RasterizerStateKey & b)2386 bool operator!=(const RasterizerStateKey &a, const RasterizerStateKey &b)
2387 {
2388 return !(a == b);
2389 }
2390
SetDebugName(ID3D11DeviceChild * resource,const char * internalName,const std::string * khrDebugName)2391 HRESULT SetDebugName(ID3D11DeviceChild *resource,
2392 const char *internalName,
2393 const std::string *khrDebugName)
2394 {
2395 // Prepend ANGLE to separate names from other components in the same process.
2396 std::string d3dName = "ANGLE";
2397 bool sendNameToD3D = false;
2398 if (internalName && internalName[0] != '\0')
2399 {
2400 d3dName += std::string("_") + internalName;
2401 sendNameToD3D = true;
2402 }
2403 if (khrDebugName && !khrDebugName->empty())
2404 {
2405 d3dName += std::string("_") + *khrDebugName;
2406 sendNameToD3D = true;
2407 }
2408 // If both internalName and khrDebugName are empty, avoid sending the string to d3d.
2409 if (sendNameToD3D)
2410 {
2411 return resource->SetPrivateData(WKPDID_D3DDebugObjectName,
2412 static_cast<UINT>(d3dName.size()), d3dName.c_str());
2413 }
2414 return S_OK;
2415 }
2416
2417 // Keep this in cpp file where it has visibility of Renderer11.h, otherwise calling
2418 // allocateResource is only compatible with Clang and MSVS, which support calling a
2419 // method on a forward declared class in a template.
2420 template <ResourceType ResourceT>
resolveImpl(d3d::Context * context,Renderer11 * renderer,const GetDescType<ResourceT> & desc,GetInitDataType<ResourceT> * initData,const char * name)2421 angle::Result LazyResource<ResourceT>::resolveImpl(d3d::Context *context,
2422 Renderer11 *renderer,
2423 const GetDescType<ResourceT> &desc,
2424 GetInitDataType<ResourceT> *initData,
2425 const char *name)
2426 {
2427 if (!mResource.valid())
2428 {
2429 ANGLE_TRY(renderer->allocateResource(context, desc, initData, &mResource));
2430 mResource.setInternalName(name);
2431 }
2432 return angle::Result::Continue;
2433 }
2434
2435 template angle::Result LazyResource<ResourceType::BlendState>::resolveImpl(
2436 d3d::Context *context,
2437 Renderer11 *renderer,
2438 const D3D11_BLEND_DESC &desc,
2439 void *initData,
2440 const char *name);
2441 template angle::Result LazyResource<ResourceType::ComputeShader>::resolveImpl(
2442 d3d::Context *context,
2443 Renderer11 *renderer,
2444 const ShaderData &desc,
2445 void *initData,
2446 const char *name);
2447 template angle::Result LazyResource<ResourceType::GeometryShader>::resolveImpl(
2448 d3d::Context *context,
2449 Renderer11 *renderer,
2450 const ShaderData &desc,
2451 const std::vector<D3D11_SO_DECLARATION_ENTRY> *initData,
2452 const char *name);
2453 template angle::Result LazyResource<ResourceType::InputLayout>::resolveImpl(
2454 d3d::Context *context,
2455 Renderer11 *renderer,
2456 const InputElementArray &desc,
2457 const ShaderData *initData,
2458 const char *name);
2459 template angle::Result LazyResource<ResourceType::PixelShader>::resolveImpl(d3d::Context *context,
2460 Renderer11 *renderer,
2461 const ShaderData &desc,
2462 void *initData,
2463 const char *name);
2464 template angle::Result LazyResource<ResourceType::VertexShader>::resolveImpl(d3d::Context *context,
2465 Renderer11 *renderer,
2466 const ShaderData &desc,
2467 void *initData,
2468 const char *name);
2469
LazyInputLayout(const D3D11_INPUT_ELEMENT_DESC * inputDesc,size_t inputDescLen,const BYTE * byteCode,size_t byteCodeLen,const char * debugName)2470 LazyInputLayout::LazyInputLayout(const D3D11_INPUT_ELEMENT_DESC *inputDesc,
2471 size_t inputDescLen,
2472 const BYTE *byteCode,
2473 size_t byteCodeLen,
2474 const char *debugName)
2475 : mInputDesc(inputDesc, inputDescLen), mByteCode(byteCode, byteCodeLen), mDebugName(debugName)
2476 {}
2477
~LazyInputLayout()2478 LazyInputLayout::~LazyInputLayout() {}
2479
resolve(d3d::Context * context,Renderer11 * renderer)2480 angle::Result LazyInputLayout::resolve(d3d::Context *context, Renderer11 *renderer)
2481 {
2482 return resolveImpl(context, renderer, mInputDesc, &mByteCode, mDebugName);
2483 }
2484
LazyBlendState(const D3D11_BLEND_DESC & desc,const char * debugName)2485 LazyBlendState::LazyBlendState(const D3D11_BLEND_DESC &desc, const char *debugName)
2486 : mDesc(desc), mDebugName(debugName)
2487 {}
2488
resolve(d3d::Context * context,Renderer11 * renderer)2489 angle::Result LazyBlendState::resolve(d3d::Context *context, Renderer11 *renderer)
2490 {
2491 return resolveImpl(context, renderer, mDesc, nullptr, mDebugName);
2492 }
2493
InitializeFeatures(const Renderer11DeviceCaps & deviceCaps,const DXGI_ADAPTER_DESC & adapterDesc,angle::FeaturesD3D * features)2494 void InitializeFeatures(const Renderer11DeviceCaps &deviceCaps,
2495 const DXGI_ADAPTER_DESC &adapterDesc,
2496 angle::FeaturesD3D *features)
2497 {
2498 bool isNvidia = IsNvidia(adapterDesc.VendorId);
2499 bool isIntel = IsIntel(adapterDesc.VendorId);
2500 bool isSkylake = false;
2501 bool isBroadwell = false;
2502 bool isHaswell = false;
2503 bool isIvyBridge = false;
2504 bool isAMD = IsAMD(adapterDesc.VendorId);
2505 bool isFeatureLevel9_3 = deviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3;
2506
2507 angle::VersionTriple capsVersion;
2508 if (isIntel)
2509 {
2510 capsVersion = d3d11_gl::GetIntelDriverVersion(deviceCaps.driverVersion);
2511
2512 isSkylake = IsSkylake(adapterDesc.DeviceId);
2513 isBroadwell = IsBroadwell(adapterDesc.DeviceId);
2514 isHaswell = IsHaswell(adapterDesc.DeviceId);
2515 isIvyBridge = IsIvyBridge(adapterDesc.DeviceId);
2516 }
2517
2518 if (isNvidia)
2519 {
2520 // TODO(jmadill): Narrow problematic driver range.
2521 bool driverVersionValid = deviceCaps.driverVersion.valid();
2522 if (driverVersionValid)
2523 {
2524 angle::VersionTriple driverVersion(HIWORD(deviceCaps.driverVersion.value().LowPart),
2525 LOWORD(deviceCaps.driverVersion.value().LowPart), 0);
2526
2527 // Disable the workaround to fix a second driver bug on newer NVIDIA.
2528 ANGLE_FEATURE_CONDITION(features, depthStencilBlitExtraCopy,
2529 driverVersion < angle::VersionTriple(13, 6881, 0) && isNvidia &&
2530 driverVersionValid);
2531 }
2532 else
2533 {
2534 ANGLE_FEATURE_CONDITION(features, depthStencilBlitExtraCopy,
2535 isNvidia && !driverVersionValid);
2536 }
2537 }
2538
2539 ANGLE_FEATURE_CONDITION(features, mrtPerfWorkaround, true);
2540 ANGLE_FEATURE_CONDITION(features, zeroMaxLodWorkaround, isFeatureLevel9_3);
2541 ANGLE_FEATURE_CONDITION(features, allowES3OnFL100, false);
2542
2543 // TODO(jmadill): Disable workaround when we have a fixed compiler DLL.
2544 ANGLE_FEATURE_CONDITION(features, expandIntegerPowExpressions, true);
2545
2546 ANGLE_FEATURE_CONDITION(features, flushAfterEndingTransformFeedback, isNvidia);
2547 ANGLE_FEATURE_CONDITION(features, getDimensionsIgnoresBaseLevel, isNvidia);
2548 ANGLE_FEATURE_CONDITION(features, skipVSConstantRegisterZero, isNvidia);
2549 ANGLE_FEATURE_CONDITION(features, forceAtomicValueResolution, isNvidia);
2550
2551 ANGLE_FEATURE_CONDITION(features, preAddTexelFetchOffsets, isIntel);
2552 ANGLE_FEATURE_CONDITION(features, useSystemMemoryForConstantBuffers, isIntel);
2553
2554 ANGLE_FEATURE_CONDITION(features, callClearTwice,
2555 isIntel && isSkylake && capsVersion >= angle::VersionTriple(16, 0, 0) &&
2556 capsVersion < angle::VersionTriple(16, 4771, 0));
2557 ANGLE_FEATURE_CONDITION(features, emulateIsnanFloat,
2558 isIntel && isSkylake && capsVersion >= angle::VersionTriple(16, 0, 0) &&
2559 capsVersion < angle::VersionTriple(16, 4542, 0));
2560 ANGLE_FEATURE_CONDITION(features, rewriteUnaryMinusOperator,
2561 isIntel && (isBroadwell || isHaswell) &&
2562 capsVersion >= angle::VersionTriple(15, 0, 0) &&
2563 capsVersion < angle::VersionTriple(15, 4624, 0));
2564
2565 ANGLE_FEATURE_CONDITION(features, addMockTextureNoRenderTarget,
2566 isIntel && capsVersion >= angle::VersionTriple(16, 0, 0) &&
2567 capsVersion < angle::VersionTriple(16, 4815, 0));
2568
2569 // Haswell/Ivybridge drivers occasionally corrupt (small?) (vertex?) texture data uploads.
2570 ANGLE_FEATURE_CONDITION(features, setDataFasterThanImageUpload,
2571 !(isIvyBridge || isBroadwell || isHaswell));
2572
2573 ANGLE_FEATURE_CONDITION(features, disableB5G6R5Support,
2574 (isIntel && capsVersion >= angle::VersionTriple(15, 0, 0) &&
2575 capsVersion < angle::VersionTriple(15, 4539, 0)) ||
2576 isAMD);
2577
2578 // TODO(jmadill): Disable when we have a fixed driver version.
2579 // The tiny stencil texture workaround involves using CopySubresource or UpdateSubresource on a
2580 // depth stencil texture. This is not allowed until feature level 10.1 but since it is not
2581 // possible to support ES3 on these devices, there is no need for the workaround to begin with
2582 // (anglebug.com/42260536).
2583 ANGLE_FEATURE_CONDITION(features, emulateTinyStencilTextures,
2584 isAMD && !(deviceCaps.featureLevel < D3D_FEATURE_LEVEL_10_1));
2585
2586 // If the VPAndRTArrayIndexFromAnyShaderFeedingRasterizer feature is not available, we have to
2587 // select the viewport / RT array index in the geometry shader.
2588 ANGLE_FEATURE_CONDITION(features, selectViewInGeometryShader,
2589 !deviceCaps.supportsVpRtIndexWriteFromVertexShader);
2590
2591 // NVidia drivers have no trouble clearing textures without showing corruption.
2592 // Intel and AMD drivers that have trouble have been blocklisted by Chromium. In the case of
2593 // Intel, they've been blocklisted to the DX9 runtime.
2594 ANGLE_FEATURE_CONDITION(features, allowClearForRobustResourceInit, true);
2595
2596 // Allow translating uniform block to StructuredBuffer on Windows 10. This is targeted
2597 // to work around a slow fxc compile performance issue with dynamic uniform indexing.
2598 ANGLE_FEATURE_CONDITION(features, allowTranslateUniformBlockToStructuredBuffer,
2599 IsWindows10OrLater());
2600
2601 // D3D11 Feature Levels 9_3 and below do not support non-constant loop indexing and require
2602 // additional
2603 // pre-validation of the shader at compile time to produce a better error message.
2604 ANGLE_FEATURE_CONDITION(features, supportsNonConstantLoopIndexing, !isFeatureLevel9_3);
2605 }
2606
InitializeFrontendFeatures(const DXGI_ADAPTER_DESC & adapterDesc,angle::FrontendFeatures * features)2607 void InitializeFrontendFeatures(const DXGI_ADAPTER_DESC &adapterDesc,
2608 angle::FrontendFeatures *features)
2609 {
2610 bool isAMD = IsAMD(adapterDesc.VendorId);
2611
2612 ANGLE_FEATURE_CONDITION(features, forceDepthAttachmentInitOnClear, isAMD);
2613
2614 // The D3D backend's handling of compile and link is thread-safe
2615 ANGLE_FEATURE_CONDITION(features, compileJobIsThreadSafe, true);
2616 ANGLE_FEATURE_CONDITION(features, linkJobIsThreadSafe, true);
2617 }
2618
InitConstantBufferDesc(D3D11_BUFFER_DESC * constantBufferDescription,size_t byteWidth)2619 void InitConstantBufferDesc(D3D11_BUFFER_DESC *constantBufferDescription, size_t byteWidth)
2620 {
2621 constantBufferDescription->ByteWidth = static_cast<UINT>(byteWidth);
2622 constantBufferDescription->Usage = D3D11_USAGE_DYNAMIC;
2623 constantBufferDescription->BindFlags = D3D11_BIND_CONSTANT_BUFFER;
2624 constantBufferDescription->CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
2625 constantBufferDescription->MiscFlags = 0;
2626 constantBufferDescription->StructureByteStride = 0;
2627 }
2628
2629 } // namespace d3d11
2630
2631 // TextureHelper11 implementation.
TextureHelper11()2632 TextureHelper11::TextureHelper11() : mFormatSet(nullptr), mSampleCount(0) {}
2633
TextureHelper11(TextureHelper11 && toCopy)2634 TextureHelper11::TextureHelper11(TextureHelper11 &&toCopy) : TextureHelper11()
2635 {
2636 *this = std::move(toCopy);
2637 }
2638
TextureHelper11(const TextureHelper11 & other)2639 TextureHelper11::TextureHelper11(const TextureHelper11 &other)
2640 : mFormatSet(other.mFormatSet), mExtents(other.mExtents), mSampleCount(other.mSampleCount)
2641 {
2642 mData = other.mData;
2643 }
2644
~TextureHelper11()2645 TextureHelper11::~TextureHelper11() {}
2646
getDesc(D3D11_TEXTURE2D_DESC * desc) const2647 void TextureHelper11::getDesc(D3D11_TEXTURE2D_DESC *desc) const
2648 {
2649 static_cast<ID3D11Texture2D *>(mData->object)->GetDesc(desc);
2650 }
2651
getDesc(D3D11_TEXTURE3D_DESC * desc) const2652 void TextureHelper11::getDesc(D3D11_TEXTURE3D_DESC *desc) const
2653 {
2654 static_cast<ID3D11Texture3D *>(mData->object)->GetDesc(desc);
2655 }
2656
getDesc(D3D11_BUFFER_DESC * desc) const2657 void TextureHelper11::getDesc(D3D11_BUFFER_DESC *desc) const
2658 {
2659 static_cast<ID3D11Buffer *>(mData->object)->GetDesc(desc);
2660 }
2661
initDesc(const D3D11_TEXTURE2D_DESC & desc2D)2662 void TextureHelper11::initDesc(const D3D11_TEXTURE2D_DESC &desc2D)
2663 {
2664 mData->resourceType = ResourceType::Texture2D;
2665 mExtents.width = static_cast<int>(desc2D.Width);
2666 mExtents.height = static_cast<int>(desc2D.Height);
2667 mExtents.depth = 1;
2668 mSampleCount = desc2D.SampleDesc.Count;
2669 }
2670
initDesc(const D3D11_TEXTURE3D_DESC & desc3D)2671 void TextureHelper11::initDesc(const D3D11_TEXTURE3D_DESC &desc3D)
2672 {
2673 mData->resourceType = ResourceType::Texture3D;
2674 mExtents.width = static_cast<int>(desc3D.Width);
2675 mExtents.height = static_cast<int>(desc3D.Height);
2676 mExtents.depth = static_cast<int>(desc3D.Depth);
2677 mSampleCount = 1;
2678 }
2679
initDesc(const D3D11_BUFFER_DESC & descBuffer)2680 void TextureHelper11::initDesc(const D3D11_BUFFER_DESC &descBuffer)
2681 {
2682 mData->resourceType = ResourceType::Buffer;
2683 mExtents.width = static_cast<int>(descBuffer.ByteWidth);
2684 mExtents.height = 1;
2685 mExtents.depth = 1;
2686 mSampleCount = 1;
2687 }
2688
operator =(TextureHelper11 && other)2689 TextureHelper11 &TextureHelper11::operator=(TextureHelper11 &&other)
2690 {
2691 std::swap(mData, other.mData);
2692 std::swap(mExtents, other.mExtents);
2693 std::swap(mFormatSet, other.mFormatSet);
2694 std::swap(mSampleCount, other.mSampleCount);
2695 return *this;
2696 }
2697
operator =(const TextureHelper11 & other)2698 TextureHelper11 &TextureHelper11::operator=(const TextureHelper11 &other)
2699 {
2700 mData = other.mData;
2701 mExtents = other.mExtents;
2702 mFormatSet = other.mFormatSet;
2703 mSampleCount = other.mSampleCount;
2704 return *this;
2705 }
2706
operator ==(const TextureHelper11 & other) const2707 bool TextureHelper11::operator==(const TextureHelper11 &other) const
2708 {
2709 return mData->object == other.mData->object;
2710 }
2711
operator !=(const TextureHelper11 & other) const2712 bool TextureHelper11::operator!=(const TextureHelper11 &other) const
2713 {
2714 return mData->object != other.mData->object;
2715 }
2716
UsePresentPathFast(const Renderer11 * renderer,const gl::FramebufferAttachment * framebufferAttachment)2717 bool UsePresentPathFast(const Renderer11 *renderer,
2718 const gl::FramebufferAttachment *framebufferAttachment)
2719 {
2720 if (framebufferAttachment == nullptr)
2721 {
2722 return false;
2723 }
2724
2725 return (framebufferAttachment->type() == GL_FRAMEBUFFER_DEFAULT &&
2726 renderer->presentPathFastEnabled());
2727 }
2728
UsePrimitiveRestartWorkaround(bool primitiveRestartFixedIndexEnabled,gl::DrawElementsType type)2729 bool UsePrimitiveRestartWorkaround(bool primitiveRestartFixedIndexEnabled,
2730 gl::DrawElementsType type)
2731 {
2732 // We should never have to deal with primitive restart workaround issue with GL_UNSIGNED_INT
2733 // indices, since we restrict it via MAX_ELEMENT_INDEX.
2734 return (!primitiveRestartFixedIndexEnabled && type == gl::DrawElementsType::UnsignedShort);
2735 }
2736
ClassifyIndexStorage(const gl::State & glState,const gl::Buffer * elementArrayBuffer,gl::DrawElementsType elementType,gl::DrawElementsType destElementType,unsigned int offset)2737 IndexStorageType ClassifyIndexStorage(const gl::State &glState,
2738 const gl::Buffer *elementArrayBuffer,
2739 gl::DrawElementsType elementType,
2740 gl::DrawElementsType destElementType,
2741 unsigned int offset)
2742 {
2743 // No buffer bound means we are streaming from a client pointer.
2744 if (!elementArrayBuffer || !IsOffsetAligned(elementType, offset))
2745 {
2746 return IndexStorageType::Dynamic;
2747 }
2748
2749 // The buffer can be used directly if the storage supports it and no translation needed.
2750 BufferD3D *bufferD3D = GetImplAs<BufferD3D>(elementArrayBuffer);
2751 if (bufferD3D->supportsDirectBinding() && destElementType == elementType)
2752 {
2753 return IndexStorageType::Direct;
2754 }
2755
2756 // Use a static copy when available.
2757 StaticIndexBufferInterface *staticBuffer = bufferD3D->getStaticIndexBuffer();
2758 if (staticBuffer != nullptr)
2759 {
2760 return IndexStorageType::Static;
2761 }
2762
2763 // Static buffer not available, fall back to streaming.
2764 return IndexStorageType::Dynamic;
2765 }
2766
SwizzleRequired(const gl::TextureState & textureState)2767 bool SwizzleRequired(const gl::TextureState &textureState)
2768 {
2769 // When sampling stencil, a swizzle is needed to move the stencil channel from G to R.
2770 return textureState.swizzleRequired() || textureState.isStencilMode();
2771 }
2772
GetEffectiveSwizzle(const gl::TextureState & textureState)2773 gl::SwizzleState GetEffectiveSwizzle(const gl::TextureState &textureState)
2774 {
2775 const gl::SwizzleState &swizzle = textureState.getSwizzleState();
2776 if (textureState.isStencilMode())
2777 {
2778 // Per GL semantics, the stencil value should be in the red channel, while D3D11 formats
2779 // leave stencil in the green channel. So copy the stencil value from green to all
2780 // components requesting red. Green and blue become zero; alpha becomes one.
2781 std::unordered_map<GLenum, GLenum> map = {{GL_RED, GL_GREEN}, {GL_GREEN, GL_ZERO},
2782 {GL_BLUE, GL_ZERO}, {GL_ALPHA, GL_ONE},
2783 {GL_ZERO, GL_ZERO}, {GL_ONE, GL_ONE}};
2784
2785 return gl::SwizzleState(map[swizzle.swizzleRed], map[swizzle.swizzleGreen],
2786 map[swizzle.swizzleBlue], map[swizzle.swizzleAlpha]);
2787 }
2788 return swizzle;
2789 }
2790
2791 } // namespace rx
2792