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