• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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