• 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/dxgi_support_table.h"
29 #include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
30 #include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
31 #include "libANGLE/renderer/driver_utils.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             break;
853         default:
854             return {{0, 0, 0}};
855     }
856 }
857 
GetMaxComputeWorkGroupSize(D3D_FEATURE_LEVEL featureLevel)858 std::array<GLint, 3> GetMaxComputeWorkGroupSize(D3D_FEATURE_LEVEL featureLevel)
859 {
860     switch (featureLevel)
861     {
862         case D3D_FEATURE_LEVEL_11_1:
863         case D3D_FEATURE_LEVEL_11_0:
864             return {{D3D11_CS_THREAD_GROUP_MAX_X, D3D11_CS_THREAD_GROUP_MAX_Y,
865                      D3D11_CS_THREAD_GROUP_MAX_Z}};
866             break;
867         default:
868             return {{0, 0, 0}};
869     }
870 }
871 
GetMaxComputeWorkGroupInvocations(D3D_FEATURE_LEVEL featureLevel)872 int GetMaxComputeWorkGroupInvocations(D3D_FEATURE_LEVEL featureLevel)
873 {
874     switch (featureLevel)
875     {
876         case D3D_FEATURE_LEVEL_11_1:
877         case D3D_FEATURE_LEVEL_11_0:
878             return D3D11_CS_THREAD_GROUP_MAX_THREADS_PER_GROUP;
879         default:
880             return 0;
881     }
882 }
883 
GetMaxComputeSharedMemorySize(D3D_FEATURE_LEVEL featureLevel)884 int GetMaxComputeSharedMemorySize(D3D_FEATURE_LEVEL featureLevel)
885 {
886     switch (featureLevel)
887     {
888         // In D3D11 the maximum total size of all variables with the groupshared storage class is
889         // 32kb.
890         // https://docs.microsoft.com/en-us/windows/desktop/direct3dhlsl/dx-graphics-hlsl-variable-syntax
891         case D3D_FEATURE_LEVEL_11_1:
892         case D3D_FEATURE_LEVEL_11_0:
893             return 32768;
894         default:
895             return 0;
896     }
897 }
898 
GetMaximumComputeUniformVectors(D3D_FEATURE_LEVEL featureLevel)899 int GetMaximumComputeUniformVectors(D3D_FEATURE_LEVEL featureLevel)
900 {
901     switch (featureLevel)
902     {
903         case D3D_FEATURE_LEVEL_11_1:
904         case D3D_FEATURE_LEVEL_11_0:
905             return D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT;
906         default:
907             return 0;
908     }
909 }
910 
GetMaximumComputeUniformBlocks(D3D_FEATURE_LEVEL featureLevel)911 int GetMaximumComputeUniformBlocks(D3D_FEATURE_LEVEL featureLevel)
912 {
913     switch (featureLevel)
914     {
915         case D3D_FEATURE_LEVEL_11_1:
916         case D3D_FEATURE_LEVEL_11_0:
917             return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT -
918                    d3d11::RESERVED_CONSTANT_BUFFER_SLOT_COUNT;
919         default:
920             return 0;
921     }
922 }
923 
GetMaximumComputeTextureUnits(D3D_FEATURE_LEVEL featureLevel)924 int GetMaximumComputeTextureUnits(D3D_FEATURE_LEVEL featureLevel)
925 {
926     switch (featureLevel)
927     {
928         case D3D_FEATURE_LEVEL_11_1:
929         case D3D_FEATURE_LEVEL_11_0:
930             return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT;
931         default:
932             return 0;
933     }
934 }
935 
SetUAVRelatedResourceLimits(D3D_FEATURE_LEVEL featureLevel,gl::Caps * caps)936 void SetUAVRelatedResourceLimits(D3D_FEATURE_LEVEL featureLevel, gl::Caps *caps)
937 {
938     ASSERT(caps);
939 
940     GLuint reservedUAVsForAtomicCounterBuffers = 0u;
941 
942     // For pixel shaders, the render targets and unordered access views share the same resource
943     // slots when being written out.
944     // https://msdn.microsoft.com/en-us/library/windows/desktop/ff476465(v=vs.85).aspx
945     GLuint maxNumRTVsAndUAVs = 0u;
946 
947     switch (featureLevel)
948     {
949         case D3D_FEATURE_LEVEL_11_1:
950             // Currently we allocate 4 UAV slots for atomic counter buffers on feature level 11_1.
951             reservedUAVsForAtomicCounterBuffers = 4u;
952             maxNumRTVsAndUAVs                   = D3D11_1_UAV_SLOT_COUNT;
953             break;
954         case D3D_FEATURE_LEVEL_11_0:
955             // Currently we allocate 1 UAV slot for atomic counter buffers on feature level 11_0.
956             reservedUAVsForAtomicCounterBuffers = 1u;
957             maxNumRTVsAndUAVs                   = D3D11_PS_CS_UAV_REGISTER_COUNT;
958             break;
959         default:
960             return;
961     }
962 
963     // Set limits on atomic counter buffers in fragment shaders and compute shaders.
964     caps->maxCombinedAtomicCounterBuffers = reservedUAVsForAtomicCounterBuffers;
965     caps->maxShaderAtomicCounterBuffers[gl::ShaderType::Compute] =
966         reservedUAVsForAtomicCounterBuffers;
967     caps->maxShaderAtomicCounterBuffers[gl::ShaderType::Fragment] =
968         reservedUAVsForAtomicCounterBuffers;
969     caps->maxAtomicCounterBufferBindings = reservedUAVsForAtomicCounterBuffers;
970 
971     // Setting MAX_COMPUTE_ATOMIC_COUNTERS to a conservative number of 1024 * the number of UAV
972     // reserved for atomic counters. It could theoretically be set to max buffer size / 4 but that
973     // number could cause problems.
974     caps->maxCombinedAtomicCounters = reservedUAVsForAtomicCounterBuffers * 1024;
975     caps->maxShaderAtomicCounters[gl::ShaderType::Compute] = caps->maxCombinedAtomicCounters;
976 
977     // See
978     // https://docs.microsoft.com/en-us/windows/desktop/direct3d11/overviews-direct3d-11-resources-limits
979     // Resource size (in MB) for any of the preceding resources is min(max(128,0.25f * (amount of
980     // dedicated VRAM)), 2048) MB. So we set it to 128MB to keep same with GL backend.
981     caps->maxShaderStorageBlockSize =
982         D3D11_REQ_RESOURCE_SIZE_IN_MEGABYTES_EXPRESSION_A_TERM * 1024 * 1024;
983 
984     // Allocate the remaining slots for images and shader storage blocks.
985     // The maximum number of fragment shader outputs depends on the current context version, so we
986     // will not set it here. See comments in Context11::initialize().
987     caps->maxCombinedShaderOutputResources =
988         maxNumRTVsAndUAVs - reservedUAVsForAtomicCounterBuffers;
989 
990     // Set limits on images and shader storage blocks in fragment shaders and compute shaders.
991     caps->maxCombinedShaderStorageBlocks                   = caps->maxCombinedShaderOutputResources;
992     caps->maxShaderStorageBlocks[gl::ShaderType::Compute]  = caps->maxCombinedShaderOutputResources;
993     caps->maxShaderStorageBlocks[gl::ShaderType::Fragment] = caps->maxCombinedShaderOutputResources;
994     caps->maxShaderStorageBufferBindings                   = caps->maxCombinedShaderOutputResources;
995 
996     caps->maxImageUnits                                    = caps->maxCombinedShaderOutputResources;
997     caps->maxCombinedImageUniforms                         = caps->maxCombinedShaderOutputResources;
998     caps->maxShaderImageUniforms[gl::ShaderType::Compute]  = caps->maxCombinedShaderOutputResources;
999     caps->maxShaderImageUniforms[gl::ShaderType::Fragment] = caps->maxCombinedShaderOutputResources;
1000 
1001     // On feature level 11_1, UAVs are also available in vertex shaders and geometry shaders.
1002     if (featureLevel == D3D_FEATURE_LEVEL_11_1)
1003     {
1004         caps->maxShaderAtomicCounterBuffers[gl::ShaderType::Vertex] =
1005             caps->maxCombinedAtomicCounterBuffers;
1006         caps->maxShaderAtomicCounterBuffers[gl::ShaderType::Geometry] =
1007             caps->maxCombinedAtomicCounterBuffers;
1008 
1009         caps->maxShaderImageUniforms[gl::ShaderType::Vertex] =
1010             caps->maxCombinedShaderOutputResources;
1011         caps->maxShaderStorageBlocks[gl::ShaderType::Vertex] =
1012             caps->maxCombinedShaderOutputResources;
1013         caps->maxShaderImageUniforms[gl::ShaderType::Geometry] =
1014             caps->maxCombinedShaderOutputResources;
1015         caps->maxShaderStorageBlocks[gl::ShaderType::Geometry] =
1016             caps->maxCombinedShaderOutputResources;
1017     }
1018 }
1019 
GetMinimumTexelOffset(D3D_FEATURE_LEVEL featureLevel)1020 int GetMinimumTexelOffset(D3D_FEATURE_LEVEL featureLevel)
1021 {
1022     switch (featureLevel)
1023     {
1024         case D3D_FEATURE_LEVEL_11_1:
1025         case D3D_FEATURE_LEVEL_11_0:
1026             return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE;
1027 
1028         case D3D_FEATURE_LEVEL_10_1:
1029         case D3D_FEATURE_LEVEL_10_0:
1030             return D3D10_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE;
1031 
1032         // Sampling functions with offsets are not available below shader model 4.0.
1033         case D3D_FEATURE_LEVEL_9_3:
1034         case D3D_FEATURE_LEVEL_9_2:
1035         case D3D_FEATURE_LEVEL_9_1:
1036             return 0;
1037 
1038         default:
1039             UNREACHABLE();
1040             return 0;
1041     }
1042 }
1043 
GetMaximumTexelOffset(D3D_FEATURE_LEVEL featureLevel)1044 int GetMaximumTexelOffset(D3D_FEATURE_LEVEL featureLevel)
1045 {
1046     switch (featureLevel)
1047     {
1048         case D3D_FEATURE_LEVEL_11_1:
1049         case D3D_FEATURE_LEVEL_11_0:
1050             return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE;
1051         case D3D_FEATURE_LEVEL_10_1:
1052         case D3D_FEATURE_LEVEL_10_0:
1053             return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE;
1054 
1055         // Sampling functions with offsets are not available below shader model 4.0.
1056         case D3D_FEATURE_LEVEL_9_3:
1057         case D3D_FEATURE_LEVEL_9_2:
1058         case D3D_FEATURE_LEVEL_9_1:
1059             return 0;
1060 
1061         default:
1062             UNREACHABLE();
1063             return 0;
1064     }
1065 }
1066 
GetMinimumTextureGatherOffset(D3D_FEATURE_LEVEL featureLevel)1067 int GetMinimumTextureGatherOffset(D3D_FEATURE_LEVEL featureLevel)
1068 {
1069     switch (featureLevel)
1070     {
1071         // https://docs.microsoft.com/en-us/windows/desktop/direct3dhlsl/gather4-po--sm5---asm-
1072         case D3D_FEATURE_LEVEL_11_1:
1073         case D3D_FEATURE_LEVEL_11_0:
1074             return -32;
1075 
1076         case D3D_FEATURE_LEVEL_10_1:
1077         case D3D_FEATURE_LEVEL_10_0:
1078         case D3D_FEATURE_LEVEL_9_3:
1079         case D3D_FEATURE_LEVEL_9_2:
1080         case D3D_FEATURE_LEVEL_9_1:
1081             return 0;
1082 
1083         default:
1084             UNREACHABLE();
1085             return 0;
1086     }
1087 }
1088 
GetMaximumTextureGatherOffset(D3D_FEATURE_LEVEL featureLevel)1089 int GetMaximumTextureGatherOffset(D3D_FEATURE_LEVEL featureLevel)
1090 {
1091     switch (featureLevel)
1092     {
1093         // https://docs.microsoft.com/en-us/windows/desktop/direct3dhlsl/gather4-po--sm5---asm-
1094         case D3D_FEATURE_LEVEL_11_1:
1095         case D3D_FEATURE_LEVEL_11_0:
1096             return 31;
1097 
1098         case D3D_FEATURE_LEVEL_10_1:
1099         case D3D_FEATURE_LEVEL_10_0:
1100         case D3D_FEATURE_LEVEL_9_3:
1101         case D3D_FEATURE_LEVEL_9_2:
1102         case D3D_FEATURE_LEVEL_9_1:
1103             return 0;
1104 
1105         default:
1106             UNREACHABLE();
1107             return 0;
1108     }
1109 }
1110 
GetMaximumConstantBufferSize(D3D_FEATURE_LEVEL featureLevel)1111 size_t GetMaximumConstantBufferSize(D3D_FEATURE_LEVEL featureLevel)
1112 {
1113     // Returns a size_t despite the limit being a GLuint64 because size_t is the maximum
1114     // size of
1115     // any buffer that could be allocated.
1116 
1117     const size_t bytesPerComponent = 4 * sizeof(float);
1118 
1119     switch (featureLevel)
1120     {
1121         case D3D_FEATURE_LEVEL_11_1:
1122         case D3D_FEATURE_LEVEL_11_0:
1123             return D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * bytesPerComponent;
1124 
1125         case D3D_FEATURE_LEVEL_10_1:
1126         case D3D_FEATURE_LEVEL_10_0:
1127             return D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * bytesPerComponent;
1128 
1129         // Limits from http://msdn.microsoft.com/en-us/library/windows/desktop/ff476501.aspx
1130         // remarks section
1131         case D3D_FEATURE_LEVEL_9_3:
1132         case D3D_FEATURE_LEVEL_9_2:
1133         case D3D_FEATURE_LEVEL_9_1:
1134             return 4096 * bytesPerComponent;
1135 
1136         default:
1137             UNREACHABLE();
1138             return 0;
1139     }
1140 }
1141 
GetMaximumStreamOutputBuffers(D3D_FEATURE_LEVEL featureLevel)1142 int GetMaximumStreamOutputBuffers(D3D_FEATURE_LEVEL featureLevel)
1143 {
1144     switch (featureLevel)
1145     {
1146         case D3D_FEATURE_LEVEL_11_1:
1147         case D3D_FEATURE_LEVEL_11_0:
1148             return D3D11_SO_BUFFER_SLOT_COUNT;
1149 
1150         case D3D_FEATURE_LEVEL_10_1:
1151             return D3D10_1_SO_BUFFER_SLOT_COUNT;
1152         case D3D_FEATURE_LEVEL_10_0:
1153             return D3D10_SO_BUFFER_SLOT_COUNT;
1154 
1155         case D3D_FEATURE_LEVEL_9_3:
1156         case D3D_FEATURE_LEVEL_9_2:
1157         case D3D_FEATURE_LEVEL_9_1:
1158             return 0;
1159 
1160         default:
1161             UNREACHABLE();
1162             return 0;
1163     }
1164 }
1165 
GetMaximumStreamOutputInterleavedComponents(D3D_FEATURE_LEVEL featureLevel)1166 int GetMaximumStreamOutputInterleavedComponents(D3D_FEATURE_LEVEL featureLevel)
1167 {
1168     switch (featureLevel)
1169     {
1170         case D3D_FEATURE_LEVEL_11_1:
1171         case D3D_FEATURE_LEVEL_11_0:
1172 
1173         case D3D_FEATURE_LEVEL_10_1:
1174         case D3D_FEATURE_LEVEL_10_0:
1175             return GetMaximumVertexOutputVectors(featureLevel) * 4;
1176 
1177         case D3D_FEATURE_LEVEL_9_3:
1178         case D3D_FEATURE_LEVEL_9_2:
1179         case D3D_FEATURE_LEVEL_9_1:
1180             return 0;
1181 
1182         default:
1183             UNREACHABLE();
1184             return 0;
1185     }
1186 }
1187 
GetMaximumStreamOutputSeparateComponents(D3D_FEATURE_LEVEL featureLevel)1188 int GetMaximumStreamOutputSeparateComponents(D3D_FEATURE_LEVEL featureLevel)
1189 {
1190     switch (featureLevel)
1191     {
1192         case D3D_FEATURE_LEVEL_11_1:
1193         case D3D_FEATURE_LEVEL_11_0:
1194             return GetMaximumStreamOutputInterleavedComponents(featureLevel) /
1195                    GetMaximumStreamOutputBuffers(featureLevel);
1196 
1197         // D3D 10 and 10.1 only allow one output per output slot if an output slot other
1198         // than zero is used.
1199         case D3D_FEATURE_LEVEL_10_1:
1200         case D3D_FEATURE_LEVEL_10_0:
1201             return 4;
1202 
1203         case D3D_FEATURE_LEVEL_9_3:
1204         case D3D_FEATURE_LEVEL_9_2:
1205         case D3D_FEATURE_LEVEL_9_1:
1206             return 0;
1207 
1208         default:
1209             UNREACHABLE();
1210             return 0;
1211     }
1212 }
1213 
GetMaximumRenderToBufferWindowSize(D3D_FEATURE_LEVEL featureLevel)1214 int GetMaximumRenderToBufferWindowSize(D3D_FEATURE_LEVEL featureLevel)
1215 {
1216     switch (featureLevel)
1217     {
1218         case D3D_FEATURE_LEVEL_11_1:
1219         case D3D_FEATURE_LEVEL_11_0:
1220             return D3D11_REQ_RENDER_TO_BUFFER_WINDOW_WIDTH;
1221         case D3D_FEATURE_LEVEL_10_1:
1222         case D3D_FEATURE_LEVEL_10_0:
1223             return D3D10_REQ_RENDER_TO_BUFFER_WINDOW_WIDTH;
1224 
1225         // REQ_RENDER_TO_BUFFER_WINDOW_WIDTH not supported on D3D11 Feature Level 9,
1226         // use the maximum texture sizes
1227         case D3D_FEATURE_LEVEL_9_3:
1228             return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION;
1229         case D3D_FEATURE_LEVEL_9_2:
1230         case D3D_FEATURE_LEVEL_9_1:
1231             return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION;
1232 
1233         default:
1234             UNREACHABLE();
1235             return 0;
1236     }
1237 }
1238 
GetIntelDriverVersion(const Optional<LARGE_INTEGER> driverVersion)1239 IntelDriverVersion GetIntelDriverVersion(const Optional<LARGE_INTEGER> driverVersion)
1240 {
1241     if (!driverVersion.valid())
1242         return IntelDriverVersion(0);
1243 
1244     // According to http://www.intel.com/content/www/us/en/support/graphics-drivers/000005654.html,
1245     // only the fourth part is necessary since it stands for the driver specific unique version
1246     // number.
1247     WORD part = LOWORD(driverVersion.value().LowPart);
1248     return IntelDriverVersion(part);
1249 }
1250 
1251 }  // anonymous namespace
1252 
GetReservedVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel)1253 unsigned int GetReservedVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel)
1254 {
1255     switch (featureLevel)
1256     {
1257         case D3D_FEATURE_LEVEL_11_1:
1258         case D3D_FEATURE_LEVEL_11_0:
1259         case D3D_FEATURE_LEVEL_10_1:
1260         case D3D_FEATURE_LEVEL_10_0:
1261             return 0;
1262 
1263         case D3D_FEATURE_LEVEL_9_3:
1264         case D3D_FEATURE_LEVEL_9_2:
1265         case D3D_FEATURE_LEVEL_9_1:
1266             return 3;  // dx_ViewAdjust, dx_ViewCoords and dx_ViewScale
1267 
1268         default:
1269             UNREACHABLE();
1270             return 0;
1271     }
1272 }
1273 
GetReservedFragmentUniformVectors(D3D_FEATURE_LEVEL featureLevel)1274 unsigned int GetReservedFragmentUniformVectors(D3D_FEATURE_LEVEL featureLevel)
1275 {
1276     switch (featureLevel)
1277     {
1278         case D3D_FEATURE_LEVEL_11_1:
1279         case D3D_FEATURE_LEVEL_11_0:
1280         case D3D_FEATURE_LEVEL_10_1:
1281         case D3D_FEATURE_LEVEL_10_0:
1282             return 0;
1283 
1284         case D3D_FEATURE_LEVEL_9_3:
1285         case D3D_FEATURE_LEVEL_9_2:
1286         case D3D_FEATURE_LEVEL_9_1:
1287             return 3;
1288 
1289         default:
1290             UNREACHABLE();
1291             return 0;
1292     }
1293 }
1294 
GetMaximumClientVersion(D3D_FEATURE_LEVEL featureLevel)1295 gl::Version GetMaximumClientVersion(D3D_FEATURE_LEVEL featureLevel)
1296 {
1297     switch (featureLevel)
1298     {
1299         case D3D_FEATURE_LEVEL_11_1:
1300         case D3D_FEATURE_LEVEL_11_0:
1301             return gl::Version(3, 1);
1302         case D3D_FEATURE_LEVEL_10_1:
1303             return gl::Version(3, 0);
1304 
1305         case D3D_FEATURE_LEVEL_10_0:
1306         case D3D_FEATURE_LEVEL_9_3:
1307         case D3D_FEATURE_LEVEL_9_2:
1308         case D3D_FEATURE_LEVEL_9_1:
1309             return gl::Version(2, 0);
1310 
1311         default:
1312             UNREACHABLE();
1313             return gl::Version(0, 0);
1314     }
1315 }
1316 
GetMinimumFeatureLevelForES31()1317 D3D_FEATURE_LEVEL GetMinimumFeatureLevelForES31()
1318 {
1319     return kMinimumFeatureLevelForES31;
1320 }
1321 
GetMaxViewportAndScissorRectanglesPerPipeline(D3D_FEATURE_LEVEL featureLevel)1322 unsigned int GetMaxViewportAndScissorRectanglesPerPipeline(D3D_FEATURE_LEVEL featureLevel)
1323 {
1324     switch (featureLevel)
1325     {
1326         case D3D_FEATURE_LEVEL_11_1:
1327         case D3D_FEATURE_LEVEL_11_0:
1328             return D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE;
1329         case D3D_FEATURE_LEVEL_10_1:
1330         case D3D_FEATURE_LEVEL_10_0:
1331         case D3D_FEATURE_LEVEL_9_3:
1332         case D3D_FEATURE_LEVEL_9_2:
1333         case D3D_FEATURE_LEVEL_9_1:
1334             return 1;
1335         default:
1336             UNREACHABLE();
1337             return 0;
1338     }
1339 }
1340 
IsMultiviewSupported(D3D_FEATURE_LEVEL featureLevel)1341 bool IsMultiviewSupported(D3D_FEATURE_LEVEL featureLevel)
1342 {
1343     // The ANGLE_multiview extension can always be supported in D3D11 through geometry shaders.
1344     switch (featureLevel)
1345     {
1346         case D3D_FEATURE_LEVEL_11_1:
1347         case D3D_FEATURE_LEVEL_11_0:
1348             return true;
1349         default:
1350             return false;
1351     }
1352 }
1353 
GetMaxSampleMaskWords(D3D_FEATURE_LEVEL featureLevel)1354 int GetMaxSampleMaskWords(D3D_FEATURE_LEVEL featureLevel)
1355 {
1356     switch (featureLevel)
1357     {
1358         // D3D10+ only allows 1 sample mask.
1359         case D3D_FEATURE_LEVEL_11_1:
1360         case D3D_FEATURE_LEVEL_11_0:
1361         case D3D_FEATURE_LEVEL_10_1:
1362         case D3D_FEATURE_LEVEL_10_0:
1363             return 1;
1364         case D3D_FEATURE_LEVEL_9_3:
1365         case D3D_FEATURE_LEVEL_9_2:
1366         case D3D_FEATURE_LEVEL_9_1:
1367             return 0;
1368         default:
1369             UNREACHABLE();
1370             return 0;
1371     }
1372 }
1373 
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)1374 void GenerateCaps(ID3D11Device *device,
1375                   ID3D11DeviceContext *deviceContext,
1376                   const Renderer11DeviceCaps &renderer11DeviceCaps,
1377                   const angle::FeaturesD3D &features,
1378                   const char *description,
1379                   gl::Caps *caps,
1380                   gl::TextureCapsMap *textureCapsMap,
1381                   gl::Extensions *extensions,
1382                   gl::Limitations *limitations)
1383 {
1384     D3D_FEATURE_LEVEL featureLevel  = renderer11DeviceCaps.featureLevel;
1385     const gl::FormatSet &allFormats = gl::GetAllSizedInternalFormats();
1386     for (GLenum internalFormat : allFormats)
1387     {
1388         gl::TextureCaps textureCaps = GenerateTextureFormatCaps(
1389             GetMaximumClientVersion(featureLevel), internalFormat, device, renderer11DeviceCaps);
1390         textureCapsMap->insert(internalFormat, textureCaps);
1391 
1392         if (gl::GetSizedInternalFormatInfo(internalFormat).compressed)
1393         {
1394             caps->compressedTextureFormats.push_back(internalFormat);
1395         }
1396     }
1397 
1398     // GL core feature limits
1399     // Reserve MAX_UINT for D3D11's primitive restart.
1400     caps->maxElementIndex  = static_cast<GLint64>(std::numeric_limits<unsigned int>::max() - 1);
1401     caps->max3DTextureSize = GetMaximum3DTextureSize(featureLevel);
1402     caps->max2DTextureSize = GetMaximum2DTextureSize(featureLevel);
1403     caps->maxCubeMapTextureSize = GetMaximumCubeMapTextureSize(featureLevel);
1404     caps->maxArrayTextureLayers = GetMaximum2DTextureArraySize(featureLevel);
1405 
1406     // Unimplemented, set to minimum required
1407     caps->maxLODBias = 2.0f;
1408 
1409     // No specific limits on render target size, maximum 2D texture size is equivalent
1410     caps->maxRenderbufferSize = caps->max2DTextureSize;
1411 
1412     // Maximum draw buffers and color attachments are the same, max color attachments could
1413     // eventually be increased to 16
1414     caps->maxDrawBuffers      = GetMaximumSimultaneousRenderTargets(featureLevel);
1415     caps->maxColorAttachments = GetMaximumSimultaneousRenderTargets(featureLevel);
1416 
1417     // D3D11 has the same limit for viewport width and height
1418     caps->maxViewportWidth  = GetMaximumViewportSize(featureLevel);
1419     caps->maxViewportHeight = caps->maxViewportWidth;
1420 
1421     // Choose a reasonable maximum, enforced in the shader.
1422     caps->minAliasedPointSize = 1.0f;
1423     caps->maxAliasedPointSize = 1024.0f;
1424 
1425     // Wide lines not supported
1426     caps->minAliasedLineWidth = 1.0f;
1427     caps->maxAliasedLineWidth = 1.0f;
1428 
1429     // Primitive count limits
1430     caps->maxElementsIndices  = GetMaximumDrawIndexedIndexCount(featureLevel);
1431     caps->maxElementsVertices = GetMaximumDrawVertexCount(featureLevel);
1432 
1433     // Program and shader binary formats (no supported shader binary formats)
1434     caps->programBinaryFormats.push_back(GL_PROGRAM_BINARY_ANGLE);
1435 
1436     caps->vertexHighpFloat.setIEEEFloat();
1437     caps->vertexMediumpFloat.setIEEEFloat();
1438     caps->vertexLowpFloat.setIEEEFloat();
1439     caps->fragmentHighpFloat.setIEEEFloat();
1440     caps->fragmentMediumpFloat.setIEEEFloat();
1441     caps->fragmentLowpFloat.setIEEEFloat();
1442 
1443     // 32-bit integers are natively supported
1444     caps->vertexHighpInt.setTwosComplementInt(32);
1445     caps->vertexMediumpInt.setTwosComplementInt(32);
1446     caps->vertexLowpInt.setTwosComplementInt(32);
1447     caps->fragmentHighpInt.setTwosComplementInt(32);
1448     caps->fragmentMediumpInt.setTwosComplementInt(32);
1449     caps->fragmentLowpInt.setTwosComplementInt(32);
1450 
1451     // We do not wait for server fence objects internally, so report a max timeout of zero.
1452     caps->maxServerWaitTimeout = 0;
1453 
1454     // Vertex shader limits
1455     caps->maxVertexAttributes     = GetMaximumVertexInputSlots(featureLevel);
1456     caps->maxVertexUniformVectors = GetMaximumVertexUniformVectors(featureLevel);
1457     if (features.skipVSConstantRegisterZero.enabled)
1458     {
1459         caps->maxVertexUniformVectors -= 1;
1460     }
1461     caps->maxShaderUniformComponents[gl::ShaderType::Vertex] = caps->maxVertexUniformVectors * 4;
1462     caps->maxShaderUniformBlocks[gl::ShaderType::Vertex] =
1463         GetMaximumVertexUniformBlocks(featureLevel);
1464     caps->maxVertexOutputComponents = GetMaximumVertexOutputVectors(featureLevel) * 4;
1465     caps->maxShaderTextureImageUnits[gl::ShaderType::Vertex] =
1466         GetMaximumVertexTextureUnits(featureLevel);
1467 
1468     // Vertex Attribute Bindings are emulated on D3D11.
1469     caps->maxVertexAttribBindings = caps->maxVertexAttributes;
1470     // Experimental testing confirmed there is no explicit limit on maximum buffer offset in D3D11.
1471     caps->maxVertexAttribRelativeOffset = std::numeric_limits<GLint>::max();
1472     // Experimental testing confirmed 2048 is the maximum stride that D3D11 can support on all
1473     // platforms.
1474     caps->maxVertexAttribStride = 2048;
1475 
1476     // Fragment shader limits
1477     caps->maxFragmentUniformVectors = GetMaximumPixelUniformVectors(featureLevel);
1478     caps->maxShaderUniformComponents[gl::ShaderType::Fragment] =
1479         caps->maxFragmentUniformVectors * 4;
1480     caps->maxShaderUniformBlocks[gl::ShaderType::Fragment] =
1481         GetMaximumPixelUniformBlocks(featureLevel);
1482     caps->maxFragmentInputComponents = GetMaximumPixelInputVectors(featureLevel) * 4;
1483     caps->maxShaderTextureImageUnits[gl::ShaderType::Fragment] =
1484         GetMaximumPixelTextureUnits(featureLevel);
1485     caps->minProgramTexelOffset = GetMinimumTexelOffset(featureLevel);
1486     caps->maxProgramTexelOffset = GetMaximumTexelOffset(featureLevel);
1487 
1488     // Compute shader limits
1489     caps->maxComputeWorkGroupCount       = GetMaxComputeWorkGroupCount(featureLevel);
1490     caps->maxComputeWorkGroupSize        = GetMaxComputeWorkGroupSize(featureLevel);
1491     caps->maxComputeWorkGroupInvocations = GetMaxComputeWorkGroupInvocations(featureLevel);
1492     caps->maxComputeSharedMemorySize     = GetMaxComputeSharedMemorySize(featureLevel);
1493     caps->maxShaderUniformComponents[gl::ShaderType::Compute] =
1494         GetMaximumComputeUniformVectors(featureLevel) * 4;
1495     caps->maxShaderUniformBlocks[gl::ShaderType::Compute] =
1496         GetMaximumComputeUniformBlocks(featureLevel);
1497     caps->maxShaderTextureImageUnits[gl::ShaderType::Compute] =
1498         GetMaximumComputeTextureUnits(featureLevel);
1499 
1500     SetUAVRelatedResourceLimits(featureLevel, caps);
1501 
1502     // Aggregate shader limits
1503     caps->maxUniformBufferBindings = caps->maxShaderUniformBlocks[gl::ShaderType::Vertex] +
1504                                      caps->maxShaderUniformBlocks[gl::ShaderType::Fragment];
1505     caps->maxUniformBlockSize = static_cast<GLuint64>(GetMaximumConstantBufferSize(featureLevel));
1506 
1507     // TODO(oetuaho): Get a more accurate limit. For now using the minimum requirement for GLES 3.1.
1508     caps->maxUniformLocations = 1024;
1509 
1510     // With DirectX 11.1, constant buffer offset and size must be a multiple of 16 constants of 16
1511     // bytes each.
1512     // https://msdn.microsoft.com/en-us/library/windows/desktop/hh404649%28v=vs.85%29.aspx
1513     // With DirectX 11.0, we emulate UBO offsets using copies of ranges of the UBO however
1514     // we still keep the same alignment as 11.1 for consistency.
1515     caps->uniformBufferOffsetAlignment = 256;
1516 
1517     caps->maxCombinedUniformBlocks = caps->maxShaderUniformBlocks[gl::ShaderType::Vertex] +
1518                                      caps->maxShaderUniformBlocks[gl::ShaderType::Fragment];
1519 
1520     // A shader storage block will be translated to a structure in HLSL. So We reference the HLSL
1521     // structure packing rules
1522     // https://msdn.microsoft.com/en-us/library/windows/desktop/bb509632(v=vs.85).aspx. The
1523     // resulting size of any structure will always be evenly divisible by sizeof(four-component
1524     // vector).
1525     caps->shaderStorageBufferOffsetAlignment = 16;
1526 
1527     for (gl::ShaderType shaderType : gl::AllShaderTypes())
1528     {
1529         caps->maxCombinedShaderUniformComponents[shaderType] =
1530             static_cast<GLint64>(caps->maxShaderUniformBlocks[shaderType]) *
1531                 static_cast<GLint64>(caps->maxUniformBlockSize / 4) +
1532             static_cast<GLint64>(caps->maxShaderUniformComponents[shaderType]);
1533     }
1534 
1535     caps->maxVaryingComponents         = GetMaximumVertexOutputVectors(featureLevel) * 4;
1536     caps->maxVaryingVectors            = GetMaximumVertexOutputVectors(featureLevel);
1537     caps->maxCombinedTextureImageUnits = caps->maxShaderTextureImageUnits[gl::ShaderType::Vertex] +
1538                                          caps->maxShaderTextureImageUnits[gl::ShaderType::Fragment];
1539 
1540     // Transform feedback limits
1541     caps->maxTransformFeedbackInterleavedComponents =
1542         GetMaximumStreamOutputInterleavedComponents(featureLevel);
1543     caps->maxTransformFeedbackSeparateAttributes = GetMaximumStreamOutputBuffers(featureLevel);
1544     caps->maxTransformFeedbackSeparateComponents =
1545         GetMaximumStreamOutputSeparateComponents(featureLevel);
1546 
1547     // Defer the computation of multisample limits to Context::updateCaps() where max*Samples values
1548     // are determined according to available sample counts for each individual format.
1549     caps->maxSamples             = std::numeric_limits<GLint>::max();
1550     caps->maxColorTextureSamples = std::numeric_limits<GLint>::max();
1551     caps->maxDepthTextureSamples = std::numeric_limits<GLint>::max();
1552     caps->maxIntegerSamples      = std::numeric_limits<GLint>::max();
1553 
1554     // Sample mask words limits
1555     caps->maxSampleMaskWords = GetMaxSampleMaskWords(featureLevel);
1556 
1557     // Framebuffer limits
1558     caps->maxFramebufferSamples = std::numeric_limits<GLint>::max();
1559     caps->maxFramebufferWidth   = GetMaximumRenderToBufferWindowSize(featureLevel);
1560     caps->maxFramebufferHeight  = caps->maxFramebufferWidth;
1561 
1562     // Texture gather offset limits
1563     caps->minProgramTextureGatherOffset = GetMinimumTextureGatherOffset(featureLevel);
1564     caps->maxProgramTextureGatherOffset = GetMaximumTextureGatherOffset(featureLevel);
1565 
1566     // GL extension support
1567     extensions->setTextureExtensionSupport(*textureCapsMap);
1568 
1569     // Explicitly disable GL_OES_compressed_ETC1_RGB8_texture because it's emulated and never
1570     // becomes core. WebGL doesn't want to expose it unless there is native support.
1571     extensions->compressedETC1RGB8TextureOES = false;
1572     extensions->compressedETC1RGB8SubTexture = false;
1573 
1574     extensions->elementIndexUintOES = true;
1575     extensions->getProgramBinaryOES = true;
1576     extensions->rgb8rgba8OES        = true;
1577     extensions->readFormatBGRA      = true;
1578     extensions->pixelBufferObjectNV = true;
1579     extensions->mapBufferOES        = true;
1580     extensions->mapBufferRange      = true;
1581     extensions->textureNPOTOES      = GetNPOTTextureSupport(featureLevel);
1582     extensions->drawBuffers         = GetMaximumSimultaneousRenderTargets(featureLevel) > 1;
1583     extensions->drawBuffersIndexedEXT =
1584         (renderer11DeviceCaps.featureLevel >= D3D_FEATURE_LEVEL_10_1);
1585     extensions->drawBuffersIndexedOES       = extensions->drawBuffersIndexedEXT;
1586     extensions->textureStorage              = true;
1587     extensions->textureFilterAnisotropic    = true;
1588     extensions->maxTextureAnisotropy        = GetMaximumAnisotropy(featureLevel);
1589     extensions->occlusionQueryBoolean       = GetOcclusionQuerySupport(featureLevel);
1590     extensions->fenceNV                     = GetEventQuerySupport(featureLevel);
1591     extensions->disjointTimerQuery          = true;
1592     extensions->queryCounterBitsTimeElapsed = 64;
1593     extensions->queryCounterBitsTimestamp =
1594         0;  // Timestamps cannot be supported due to D3D11 limitations
1595     extensions->robustness = true;
1596     // Direct3D guarantees to return zero for any resource that is accessed out of bounds.
1597     // See https://msdn.microsoft.com/en-us/library/windows/desktop/ff476332(v=vs.85).aspx
1598     // and https://msdn.microsoft.com/en-us/library/windows/desktop/ff476900(v=vs.85).aspx
1599     extensions->robustBufferAccessBehavior = true;
1600     extensions->blendMinMax                = true;
1601     // https://docs.microsoft.com/en-us/windows/desktop/direct3ddxgi/format-support-for-direct3d-11-0-feature-level-hardware
1602     extensions->floatBlend             = true;
1603     extensions->framebufferBlit        = GetFramebufferBlitSupport(featureLevel);
1604     extensions->framebufferMultisample = GetFramebufferMultisampleSupport(featureLevel);
1605     extensions->instancedArraysANGLE   = GetInstancingSupport(featureLevel);
1606     extensions->instancedArraysEXT     = GetInstancingSupport(featureLevel);
1607     extensions->packReverseRowOrder    = true;
1608     extensions->standardDerivativesOES = GetDerivativeInstructionSupport(featureLevel);
1609     extensions->shaderTextureLOD       = GetShaderTextureLODSupport(featureLevel);
1610     extensions->fragDepth              = true;
1611     extensions->multiview              = IsMultiviewSupported(featureLevel);
1612     extensions->multiview2             = IsMultiviewSupported(featureLevel);
1613     if (extensions->multiview || extensions->multiview2)
1614     {
1615         extensions->maxViews =
1616             std::min(static_cast<GLuint>(gl::IMPLEMENTATION_ANGLE_MULTIVIEW_MAX_VIEWS),
1617                      std::min(static_cast<GLuint>(GetMaximum2DTextureArraySize(featureLevel)),
1618                               GetMaxViewportAndScissorRectanglesPerPipeline(featureLevel)));
1619     }
1620     extensions->textureUsage       = true;  // This could be false since it has no effect in D3D11
1621     extensions->discardFramebuffer = true;
1622     extensions->translatedShaderSource              = true;
1623     extensions->fboRenderMipmapOES                  = true;
1624     extensions->debugMarker                         = true;
1625     extensions->eglImageOES                         = true;
1626     extensions->eglImageExternalOES                 = true;
1627     extensions->eglImageExternalWrapModesEXT        = true;
1628     extensions->eglImageExternalEssl3OES            = true;
1629     extensions->eglStreamConsumerExternalNV         = true;
1630     extensions->unpackSubimage                      = true;
1631     extensions->packSubimage                        = true;
1632     extensions->lossyETCDecode                      = true;
1633     extensions->syncQuery                           = GetEventQuerySupport(featureLevel);
1634     extensions->copyTexture                         = true;
1635     extensions->copyCompressedTexture               = true;
1636     extensions->textureStorageMultisample2DArrayOES = true;
1637     extensions->multiviewMultisample      = ((extensions->multiview || extensions->multiview2) &&
1638                                         extensions->textureStorageMultisample2DArrayOES);
1639     extensions->copyTexture3d             = true;
1640     extensions->textureBorderClampOES     = true;
1641     extensions->textureMultisample        = true;
1642     extensions->provokingVertex           = true;
1643     extensions->blendFuncExtended         = true;
1644     extensions->maxDualSourceDrawBuffers  = 1;
1645     extensions->texture3DOES              = true;
1646     extensions->baseVertexBaseInstance    = true;
1647     extensions->drawElementsBaseVertexOES = true;
1648     extensions->drawElementsBaseVertexEXT = true;
1649     if (!strstr(description, "Adreno"))
1650     {
1651         extensions->multisampledRenderToTexture = true;
1652     }
1653     extensions->webglVideoTexture = true;
1654 
1655     // D3D11 cannot support reading depth texture as a luminance texture.
1656     // It treats it as a red-channel-only texture.
1657     extensions->depthTextureOES = false;
1658 
1659     // readPixels on depth & stencil not working with D3D11 backend.
1660     extensions->readDepthNV         = false;
1661     extensions->readStencilNV       = false;
1662     extensions->depthBufferFloat2NV = false;
1663 
1664     // D3D11 Feature Level 10_0+ uses SV_IsFrontFace in HLSL to emulate gl_FrontFacing.
1665     // D3D11 Feature Level 9_3 doesn't support SV_IsFrontFace, and has no equivalent, so can't
1666     // support gl_FrontFacing.
1667     limitations->noFrontFacingSupport =
1668         (renderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3);
1669 
1670     // D3D11 Feature Level 9_3 doesn't support alpha-to-coverage
1671     limitations->noSampleAlphaToCoverageSupport =
1672         (renderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3);
1673 
1674     // D3D11 Feature Levels 9_3 and below do not support non-constant loop indexing and require
1675     // additional
1676     // pre-validation of the shader at compile time to produce a better error message.
1677     limitations->shadersRequireIndexedLoopValidation =
1678         (renderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3);
1679 
1680     // D3D11 has no concept of separate masks and refs for front and back faces in the depth stencil
1681     // state.
1682     limitations->noSeparateStencilRefsAndMasks = true;
1683 
1684     // D3D11 cannot support constant color and alpha blend funcs together
1685     limitations->noSimultaneousConstantColorAndAlphaBlendFunc = true;
1686 
1687     // D3D11 does not support multiple transform feedback outputs writing to the same buffer.
1688     limitations->noDoubleBoundTransformFeedbackBuffers = true;
1689 
1690     // D3D11 does not support vertex attribute aliasing
1691     limitations->noVertexAttributeAliasing = true;
1692 
1693 #ifdef ANGLE_ENABLE_WINDOWS_UWP
1694     // Setting a non-zero divisor on attribute zero doesn't work on certain Windows Phone 8-era
1695     // devices. We should prevent developers from doing this on ALL Windows Store devices. This will
1696     // maintain consistency across all Windows devices. We allow non-zero divisors on attribute zero
1697     // if the Client Version >= 3, since devices affected by this issue don't support ES3+.
1698     limitations->attributeZeroRequiresZeroDivisorInEXT = true;
1699 #endif
1700 }
1701 
1702 }  // namespace d3d11_gl
1703 
1704 namespace gl_d3d11
1705 {
1706 
ConvertBlendFunc(GLenum glBlend,bool isAlpha)1707 D3D11_BLEND ConvertBlendFunc(GLenum glBlend, bool isAlpha)
1708 {
1709     D3D11_BLEND d3dBlend = D3D11_BLEND_ZERO;
1710 
1711     switch (glBlend)
1712     {
1713         case GL_ZERO:
1714             d3dBlend = D3D11_BLEND_ZERO;
1715             break;
1716         case GL_ONE:
1717             d3dBlend = D3D11_BLEND_ONE;
1718             break;
1719         case GL_SRC_COLOR:
1720             d3dBlend = (isAlpha ? D3D11_BLEND_SRC_ALPHA : D3D11_BLEND_SRC_COLOR);
1721             break;
1722         case GL_ONE_MINUS_SRC_COLOR:
1723             d3dBlend = (isAlpha ? D3D11_BLEND_INV_SRC_ALPHA : D3D11_BLEND_INV_SRC_COLOR);
1724             break;
1725         case GL_DST_COLOR:
1726             d3dBlend = (isAlpha ? D3D11_BLEND_DEST_ALPHA : D3D11_BLEND_DEST_COLOR);
1727             break;
1728         case GL_ONE_MINUS_DST_COLOR:
1729             d3dBlend = (isAlpha ? D3D11_BLEND_INV_DEST_ALPHA : D3D11_BLEND_INV_DEST_COLOR);
1730             break;
1731         case GL_SRC_ALPHA:
1732             d3dBlend = D3D11_BLEND_SRC_ALPHA;
1733             break;
1734         case GL_ONE_MINUS_SRC_ALPHA:
1735             d3dBlend = D3D11_BLEND_INV_SRC_ALPHA;
1736             break;
1737         case GL_DST_ALPHA:
1738             d3dBlend = D3D11_BLEND_DEST_ALPHA;
1739             break;
1740         case GL_ONE_MINUS_DST_ALPHA:
1741             d3dBlend = D3D11_BLEND_INV_DEST_ALPHA;
1742             break;
1743         case GL_CONSTANT_COLOR:
1744             d3dBlend = D3D11_BLEND_BLEND_FACTOR;
1745             break;
1746         case GL_ONE_MINUS_CONSTANT_COLOR:
1747             d3dBlend = D3D11_BLEND_INV_BLEND_FACTOR;
1748             break;
1749         case GL_CONSTANT_ALPHA:
1750             d3dBlend = D3D11_BLEND_BLEND_FACTOR;
1751             break;
1752         case GL_ONE_MINUS_CONSTANT_ALPHA:
1753             d3dBlend = D3D11_BLEND_INV_BLEND_FACTOR;
1754             break;
1755         case GL_SRC_ALPHA_SATURATE:
1756             d3dBlend = D3D11_BLEND_SRC_ALPHA_SAT;
1757             break;
1758         case GL_SRC1_COLOR_EXT:
1759             d3dBlend = (isAlpha ? D3D11_BLEND_SRC1_ALPHA : D3D11_BLEND_SRC1_COLOR);
1760             break;
1761         case GL_SRC1_ALPHA_EXT:
1762             d3dBlend = D3D11_BLEND_SRC1_ALPHA;
1763             break;
1764         case GL_ONE_MINUS_SRC1_COLOR_EXT:
1765             d3dBlend = (isAlpha ? D3D11_BLEND_INV_SRC1_ALPHA : D3D11_BLEND_INV_SRC1_COLOR);
1766             break;
1767         case GL_ONE_MINUS_SRC1_ALPHA_EXT:
1768             d3dBlend = D3D11_BLEND_INV_SRC1_ALPHA;
1769             break;
1770         default:
1771             UNREACHABLE();
1772     }
1773 
1774     return d3dBlend;
1775 }
1776 
ConvertBlendOp(GLenum glBlendOp)1777 D3D11_BLEND_OP ConvertBlendOp(GLenum glBlendOp)
1778 {
1779     D3D11_BLEND_OP d3dBlendOp = D3D11_BLEND_OP_ADD;
1780 
1781     switch (glBlendOp)
1782     {
1783         case GL_FUNC_ADD:
1784             d3dBlendOp = D3D11_BLEND_OP_ADD;
1785             break;
1786         case GL_FUNC_SUBTRACT:
1787             d3dBlendOp = D3D11_BLEND_OP_SUBTRACT;
1788             break;
1789         case GL_FUNC_REVERSE_SUBTRACT:
1790             d3dBlendOp = D3D11_BLEND_OP_REV_SUBTRACT;
1791             break;
1792         case GL_MIN:
1793             d3dBlendOp = D3D11_BLEND_OP_MIN;
1794             break;
1795         case GL_MAX:
1796             d3dBlendOp = D3D11_BLEND_OP_MAX;
1797             break;
1798         default:
1799             UNREACHABLE();
1800     }
1801 
1802     return d3dBlendOp;
1803 }
1804 
ConvertColorMask(bool red,bool green,bool blue,bool alpha)1805 UINT8 ConvertColorMask(bool red, bool green, bool blue, bool alpha)
1806 {
1807     UINT8 mask = 0;
1808     if (red)
1809     {
1810         mask |= D3D11_COLOR_WRITE_ENABLE_RED;
1811     }
1812     if (green)
1813     {
1814         mask |= D3D11_COLOR_WRITE_ENABLE_GREEN;
1815     }
1816     if (blue)
1817     {
1818         mask |= D3D11_COLOR_WRITE_ENABLE_BLUE;
1819     }
1820     if (alpha)
1821     {
1822         mask |= D3D11_COLOR_WRITE_ENABLE_ALPHA;
1823     }
1824     return mask;
1825 }
1826 
ConvertCullMode(bool cullEnabled,gl::CullFaceMode cullMode)1827 D3D11_CULL_MODE ConvertCullMode(bool cullEnabled, gl::CullFaceMode cullMode)
1828 {
1829     D3D11_CULL_MODE cull = D3D11_CULL_NONE;
1830 
1831     if (cullEnabled)
1832     {
1833         switch (cullMode)
1834         {
1835             case gl::CullFaceMode::Front:
1836                 cull = D3D11_CULL_FRONT;
1837                 break;
1838             case gl::CullFaceMode::Back:
1839                 cull = D3D11_CULL_BACK;
1840                 break;
1841             case gl::CullFaceMode::FrontAndBack:
1842                 cull = D3D11_CULL_NONE;
1843                 break;
1844             default:
1845                 UNREACHABLE();
1846         }
1847     }
1848     else
1849     {
1850         cull = D3D11_CULL_NONE;
1851     }
1852 
1853     return cull;
1854 }
1855 
ConvertComparison(GLenum comparison)1856 D3D11_COMPARISON_FUNC ConvertComparison(GLenum comparison)
1857 {
1858     D3D11_COMPARISON_FUNC d3dComp = D3D11_COMPARISON_NEVER;
1859     switch (comparison)
1860     {
1861         case GL_NEVER:
1862             d3dComp = D3D11_COMPARISON_NEVER;
1863             break;
1864         case GL_ALWAYS:
1865             d3dComp = D3D11_COMPARISON_ALWAYS;
1866             break;
1867         case GL_LESS:
1868             d3dComp = D3D11_COMPARISON_LESS;
1869             break;
1870         case GL_LEQUAL:
1871             d3dComp = D3D11_COMPARISON_LESS_EQUAL;
1872             break;
1873         case GL_EQUAL:
1874             d3dComp = D3D11_COMPARISON_EQUAL;
1875             break;
1876         case GL_GREATER:
1877             d3dComp = D3D11_COMPARISON_GREATER;
1878             break;
1879         case GL_GEQUAL:
1880             d3dComp = D3D11_COMPARISON_GREATER_EQUAL;
1881             break;
1882         case GL_NOTEQUAL:
1883             d3dComp = D3D11_COMPARISON_NOT_EQUAL;
1884             break;
1885         default:
1886             UNREACHABLE();
1887     }
1888 
1889     return d3dComp;
1890 }
1891 
ConvertDepthMask(bool depthWriteEnabled)1892 D3D11_DEPTH_WRITE_MASK ConvertDepthMask(bool depthWriteEnabled)
1893 {
1894     return depthWriteEnabled ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO;
1895 }
1896 
ConvertStencilMask(GLuint stencilmask)1897 UINT8 ConvertStencilMask(GLuint stencilmask)
1898 {
1899     return static_cast<UINT8>(stencilmask);
1900 }
1901 
ConvertStencilOp(GLenum stencilOp)1902 D3D11_STENCIL_OP ConvertStencilOp(GLenum stencilOp)
1903 {
1904     D3D11_STENCIL_OP d3dStencilOp = D3D11_STENCIL_OP_KEEP;
1905 
1906     switch (stencilOp)
1907     {
1908         case GL_ZERO:
1909             d3dStencilOp = D3D11_STENCIL_OP_ZERO;
1910             break;
1911         case GL_KEEP:
1912             d3dStencilOp = D3D11_STENCIL_OP_KEEP;
1913             break;
1914         case GL_REPLACE:
1915             d3dStencilOp = D3D11_STENCIL_OP_REPLACE;
1916             break;
1917         case GL_INCR:
1918             d3dStencilOp = D3D11_STENCIL_OP_INCR_SAT;
1919             break;
1920         case GL_DECR:
1921             d3dStencilOp = D3D11_STENCIL_OP_DECR_SAT;
1922             break;
1923         case GL_INVERT:
1924             d3dStencilOp = D3D11_STENCIL_OP_INVERT;
1925             break;
1926         case GL_INCR_WRAP:
1927             d3dStencilOp = D3D11_STENCIL_OP_INCR;
1928             break;
1929         case GL_DECR_WRAP:
1930             d3dStencilOp = D3D11_STENCIL_OP_DECR;
1931             break;
1932         default:
1933             UNREACHABLE();
1934     }
1935 
1936     return d3dStencilOp;
1937 }
1938 
ConvertFilter(GLenum minFilter,GLenum magFilter,float maxAnisotropy,GLenum comparisonMode)1939 D3D11_FILTER ConvertFilter(GLenum minFilter,
1940                            GLenum magFilter,
1941                            float maxAnisotropy,
1942                            GLenum comparisonMode)
1943 {
1944     bool comparison = comparisonMode != GL_NONE;
1945 
1946     if (maxAnisotropy > 1.0f)
1947     {
1948         return D3D11_ENCODE_ANISOTROPIC_FILTER(static_cast<D3D11_COMPARISON_FUNC>(comparison));
1949     }
1950     else
1951     {
1952         D3D11_FILTER_TYPE dxMin = D3D11_FILTER_TYPE_POINT;
1953         D3D11_FILTER_TYPE dxMip = D3D11_FILTER_TYPE_POINT;
1954         switch (minFilter)
1955         {
1956             case GL_NEAREST:
1957                 dxMin = D3D11_FILTER_TYPE_POINT;
1958                 dxMip = D3D11_FILTER_TYPE_POINT;
1959                 break;
1960             case GL_LINEAR:
1961                 dxMin = D3D11_FILTER_TYPE_LINEAR;
1962                 dxMip = D3D11_FILTER_TYPE_POINT;
1963                 break;
1964             case GL_NEAREST_MIPMAP_NEAREST:
1965                 dxMin = D3D11_FILTER_TYPE_POINT;
1966                 dxMip = D3D11_FILTER_TYPE_POINT;
1967                 break;
1968             case GL_LINEAR_MIPMAP_NEAREST:
1969                 dxMin = D3D11_FILTER_TYPE_LINEAR;
1970                 dxMip = D3D11_FILTER_TYPE_POINT;
1971                 break;
1972             case GL_NEAREST_MIPMAP_LINEAR:
1973                 dxMin = D3D11_FILTER_TYPE_POINT;
1974                 dxMip = D3D11_FILTER_TYPE_LINEAR;
1975                 break;
1976             case GL_LINEAR_MIPMAP_LINEAR:
1977                 dxMin = D3D11_FILTER_TYPE_LINEAR;
1978                 dxMip = D3D11_FILTER_TYPE_LINEAR;
1979                 break;
1980             default:
1981                 UNREACHABLE();
1982         }
1983 
1984         D3D11_FILTER_TYPE dxMag = D3D11_FILTER_TYPE_POINT;
1985         switch (magFilter)
1986         {
1987             case GL_NEAREST:
1988                 dxMag = D3D11_FILTER_TYPE_POINT;
1989                 break;
1990             case GL_LINEAR:
1991                 dxMag = D3D11_FILTER_TYPE_LINEAR;
1992                 break;
1993             default:
1994                 UNREACHABLE();
1995         }
1996 
1997         return D3D11_ENCODE_BASIC_FILTER(dxMin, dxMag, dxMip,
1998                                          static_cast<D3D11_COMPARISON_FUNC>(comparison));
1999     }
2000 }
2001 
ConvertTextureWrap(GLenum wrap)2002 D3D11_TEXTURE_ADDRESS_MODE ConvertTextureWrap(GLenum wrap)
2003 {
2004     switch (wrap)
2005     {
2006         case GL_REPEAT:
2007             return D3D11_TEXTURE_ADDRESS_WRAP;
2008         case GL_CLAMP_TO_EDGE:
2009             return D3D11_TEXTURE_ADDRESS_CLAMP;
2010         case GL_CLAMP_TO_BORDER:
2011             return D3D11_TEXTURE_ADDRESS_BORDER;
2012         case GL_MIRRORED_REPEAT:
2013             return D3D11_TEXTURE_ADDRESS_MIRROR;
2014         default:
2015             UNREACHABLE();
2016     }
2017 
2018     return D3D11_TEXTURE_ADDRESS_WRAP;
2019 }
2020 
ConvertMaxAnisotropy(float maxAnisotropy,D3D_FEATURE_LEVEL featureLevel)2021 UINT ConvertMaxAnisotropy(float maxAnisotropy, D3D_FEATURE_LEVEL featureLevel)
2022 {
2023     return static_cast<UINT>(std::min(maxAnisotropy, d3d11_gl::GetMaximumAnisotropy(featureLevel)));
2024 }
2025 
ConvertQueryType(gl::QueryType type)2026 D3D11_QUERY ConvertQueryType(gl::QueryType type)
2027 {
2028     switch (type)
2029     {
2030         case gl::QueryType::AnySamples:
2031         case gl::QueryType::AnySamplesConservative:
2032             return D3D11_QUERY_OCCLUSION;
2033         case gl::QueryType::TransformFeedbackPrimitivesWritten:
2034             return D3D11_QUERY_SO_STATISTICS;
2035         case gl::QueryType::TimeElapsed:
2036             // Two internal queries are also created for begin/end timestamps
2037             return D3D11_QUERY_TIMESTAMP_DISJOINT;
2038         case gl::QueryType::CommandsCompleted:
2039             return D3D11_QUERY_EVENT;
2040         default:
2041             UNREACHABLE();
2042             return D3D11_QUERY_EVENT;
2043     }
2044 }
2045 
2046 // Get the D3D11 write mask covering all color channels of a given format
GetColorMask(const gl::InternalFormat & format)2047 UINT8 GetColorMask(const gl::InternalFormat &format)
2048 {
2049     return ConvertColorMask(format.redBits > 0, format.greenBits > 0, format.blueBits > 0,
2050                             format.alphaBits > 0);
2051 }
2052 
2053 }  // namespace gl_d3d11
2054 
2055 namespace d3d11
2056 {
2057 
GetDeviceType(ID3D11Device * device)2058 ANGLED3D11DeviceType GetDeviceType(ID3D11Device *device)
2059 {
2060     // Note that this function returns an ANGLED3D11DeviceType rather than a D3D_DRIVER_TYPE value,
2061     // since it is difficult to tell Software and Reference devices apart
2062 
2063     IDXGIDevice *dxgiDevice     = nullptr;
2064     IDXGIAdapter *dxgiAdapter   = nullptr;
2065     IDXGIAdapter2 *dxgiAdapter2 = nullptr;
2066 
2067     ANGLED3D11DeviceType retDeviceType = ANGLE_D3D11_DEVICE_TYPE_UNKNOWN;
2068 
2069     HRESULT hr = device->QueryInterface(__uuidof(IDXGIDevice), (void **)&dxgiDevice);
2070     if (SUCCEEDED(hr))
2071     {
2072         hr = dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void **)&dxgiAdapter);
2073         if (SUCCEEDED(hr))
2074         {
2075             std::wstring adapterString;
2076             HRESULT adapter2hr =
2077                 dxgiAdapter->QueryInterface(__uuidof(dxgiAdapter2), (void **)&dxgiAdapter2);
2078             if (SUCCEEDED(adapter2hr))
2079             {
2080                 // On D3D_FEATURE_LEVEL_9_*, IDXGIAdapter::GetDesc returns "Software Adapter"
2081                 // for the description string. Try to use IDXGIAdapter2::GetDesc2 to get the
2082                 // actual hardware values if possible.
2083                 DXGI_ADAPTER_DESC2 adapterDesc2;
2084                 dxgiAdapter2->GetDesc2(&adapterDesc2);
2085                 adapterString = std::wstring(adapterDesc2.Description);
2086             }
2087             else
2088             {
2089                 DXGI_ADAPTER_DESC adapterDesc;
2090                 dxgiAdapter->GetDesc(&adapterDesc);
2091                 adapterString = std::wstring(adapterDesc.Description);
2092             }
2093 
2094             // Both Reference and Software adapters will be 'Software Adapter'
2095             const bool isSoftwareDevice =
2096                 (adapterString.find(std::wstring(L"Software Adapter")) != std::string::npos);
2097             const bool isNullDevice = (adapterString == L"");
2098             const bool isWARPDevice =
2099                 (adapterString.find(std::wstring(L"Basic Render")) != std::string::npos);
2100 
2101             if (isSoftwareDevice || isNullDevice)
2102             {
2103                 ASSERT(!isWARPDevice);
2104                 retDeviceType = ANGLE_D3D11_DEVICE_TYPE_SOFTWARE_REF_OR_NULL;
2105             }
2106             else if (isWARPDevice)
2107             {
2108                 retDeviceType = ANGLE_D3D11_DEVICE_TYPE_WARP;
2109             }
2110             else
2111             {
2112                 retDeviceType = ANGLE_D3D11_DEVICE_TYPE_HARDWARE;
2113             }
2114         }
2115     }
2116 
2117     SafeRelease(dxgiDevice);
2118     SafeRelease(dxgiAdapter);
2119     SafeRelease(dxgiAdapter2);
2120 
2121     return retDeviceType;
2122 }
2123 
MakeValidSize(bool isImage,DXGI_FORMAT format,GLsizei * requestWidth,GLsizei * requestHeight,int * levelOffset)2124 void MakeValidSize(bool isImage,
2125                    DXGI_FORMAT format,
2126                    GLsizei *requestWidth,
2127                    GLsizei *requestHeight,
2128                    int *levelOffset)
2129 {
2130     const DXGIFormatSize &dxgiFormatInfo = d3d11::GetDXGIFormatSizeInfo(format);
2131 
2132     int upsampleCount = 0;
2133     // Don't expand the size of full textures that are at least (blockWidth x blockHeight) already.
2134     if (isImage || *requestWidth < static_cast<GLsizei>(dxgiFormatInfo.blockWidth) ||
2135         *requestHeight < static_cast<GLsizei>(dxgiFormatInfo.blockHeight))
2136     {
2137         while (*requestWidth % dxgiFormatInfo.blockWidth != 0 ||
2138                *requestHeight % dxgiFormatInfo.blockHeight != 0)
2139         {
2140             *requestWidth <<= 1;
2141             *requestHeight <<= 1;
2142             upsampleCount++;
2143         }
2144     }
2145     if (levelOffset)
2146     {
2147         *levelOffset = upsampleCount;
2148     }
2149 }
2150 
GenerateInitialTextureData(const gl::Context * context,GLint internalFormat,const Renderer11DeviceCaps & renderer11DeviceCaps,GLuint width,GLuint height,GLuint depth,GLuint mipLevels,gl::TexLevelArray<D3D11_SUBRESOURCE_DATA> * outSubresourceData)2151 angle::Result GenerateInitialTextureData(
2152     const gl::Context *context,
2153     GLint internalFormat,
2154     const Renderer11DeviceCaps &renderer11DeviceCaps,
2155     GLuint width,
2156     GLuint height,
2157     GLuint depth,
2158     GLuint mipLevels,
2159     gl::TexLevelArray<D3D11_SUBRESOURCE_DATA> *outSubresourceData)
2160 {
2161     const d3d11::Format &d3dFormatInfo = d3d11::Format::Get(internalFormat, renderer11DeviceCaps);
2162     ASSERT(d3dFormatInfo.dataInitializerFunction != nullptr);
2163 
2164     const d3d11::DXGIFormatSize &dxgiFormatInfo =
2165         d3d11::GetDXGIFormatSizeInfo(d3dFormatInfo.texFormat);
2166 
2167     unsigned int rowPitch     = dxgiFormatInfo.pixelBytes * width;
2168     unsigned int depthPitch   = rowPitch * height;
2169     unsigned int maxImageSize = depthPitch * depth;
2170 
2171     angle::MemoryBuffer *scratchBuffer = nullptr;
2172     ANGLE_CHECK_GL_ALLOC(GetImplAs<Context11>(context),
2173                          context->getScratchBuffer(maxImageSize, &scratchBuffer));
2174 
2175     d3dFormatInfo.dataInitializerFunction(width, height, depth, scratchBuffer->data(), rowPitch,
2176                                           depthPitch);
2177 
2178     for (unsigned int i = 0; i < mipLevels; i++)
2179     {
2180         unsigned int mipWidth  = std::max(width >> i, 1U);
2181         unsigned int mipHeight = std::max(height >> i, 1U);
2182 
2183         unsigned int mipRowPitch   = dxgiFormatInfo.pixelBytes * mipWidth;
2184         unsigned int mipDepthPitch = mipRowPitch * mipHeight;
2185 
2186         outSubresourceData->at(i).pSysMem          = scratchBuffer->data();
2187         outSubresourceData->at(i).SysMemPitch      = mipRowPitch;
2188         outSubresourceData->at(i).SysMemSlicePitch = mipDepthPitch;
2189     }
2190 
2191     return angle::Result::Continue;
2192 }
2193 
GetPrimitiveRestartIndex()2194 UINT GetPrimitiveRestartIndex()
2195 {
2196     return std::numeric_limits<UINT>::max();
2197 }
2198 
SetPositionTexCoordVertex(PositionTexCoordVertex * vertex,float x,float y,float u,float v)2199 void SetPositionTexCoordVertex(PositionTexCoordVertex *vertex, float x, float y, float u, float v)
2200 {
2201     vertex->x = x;
2202     vertex->y = y;
2203     vertex->u = u;
2204     vertex->v = v;
2205 }
2206 
SetPositionLayerTexCoord3DVertex(PositionLayerTexCoord3DVertex * vertex,float x,float y,unsigned int layer,float u,float v,float s)2207 void SetPositionLayerTexCoord3DVertex(PositionLayerTexCoord3DVertex *vertex,
2208                                       float x,
2209                                       float y,
2210                                       unsigned int layer,
2211                                       float u,
2212                                       float v,
2213                                       float s)
2214 {
2215     vertex->x = x;
2216     vertex->y = y;
2217     vertex->l = layer;
2218     vertex->u = u;
2219     vertex->v = v;
2220     vertex->s = s;
2221 }
2222 
BlendStateKey()2223 BlendStateKey::BlendStateKey()
2224 {
2225     memset(this, 0, sizeof(BlendStateKey));
2226     blendStateExt = gl::BlendStateExt();
2227 }
2228 
BlendStateKey(const BlendStateKey & other)2229 BlendStateKey::BlendStateKey(const BlendStateKey &other)
2230 {
2231     memcpy(this, &other, sizeof(BlendStateKey));
2232 }
2233 
operator ==(const BlendStateKey & a,const BlendStateKey & b)2234 bool operator==(const BlendStateKey &a, const BlendStateKey &b)
2235 {
2236     return memcmp(&a, &b, sizeof(BlendStateKey)) == 0;
2237 }
2238 
operator !=(const BlendStateKey & a,const BlendStateKey & b)2239 bool operator!=(const BlendStateKey &a, const BlendStateKey &b)
2240 {
2241     return !(a == b);
2242 }
2243 
RasterizerStateKey()2244 RasterizerStateKey::RasterizerStateKey()
2245 {
2246     memset(this, 0, sizeof(RasterizerStateKey));
2247 }
2248 
operator ==(const RasterizerStateKey & a,const RasterizerStateKey & b)2249 bool operator==(const RasterizerStateKey &a, const RasterizerStateKey &b)
2250 {
2251     return memcmp(&a, &b, sizeof(RasterizerStateKey)) == 0;
2252 }
2253 
operator !=(const RasterizerStateKey & a,const RasterizerStateKey & b)2254 bool operator!=(const RasterizerStateKey &a, const RasterizerStateKey &b)
2255 {
2256     return !(a == b);
2257 }
2258 
SetDebugName(ID3D11DeviceChild * resource,const char * name)2259 HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name)
2260 {
2261 #if defined(_DEBUG)
2262     UINT existingDataSize = 0;
2263     resource->GetPrivateData(WKPDID_D3DDebugObjectName, &existingDataSize, nullptr);
2264     // Don't check the HRESULT- if it failed then that probably just means that no private data
2265     // exists yet
2266 
2267     if (existingDataSize > 0)
2268     {
2269         // In some cases, ANGLE will try to apply two names to one object, which causes
2270         // a D3D SDK Layers warning. This can occur if, for example, you 'create' two objects
2271         // (e.g.Rasterizer States) with identical DESCs on the same device. D3D11 will optimize
2272         // these calls and return the same object both times.
2273         static const char *multipleNamesUsed = "Multiple names set by ANGLE";
2274 
2275         // Remove the existing name
2276         HRESULT hr = resource->SetPrivateData(WKPDID_D3DDebugObjectName, 0, nullptr);
2277         if (FAILED(hr))
2278         {
2279             return hr;
2280         }
2281 
2282         // Apply the new name
2283         return resource->SetPrivateData(WKPDID_D3DDebugObjectName,
2284                                         static_cast<unsigned int>(strlen(multipleNamesUsed)),
2285                                         multipleNamesUsed);
2286     }
2287     else
2288     {
2289         return resource->SetPrivateData(WKPDID_D3DDebugObjectName,
2290                                         static_cast<unsigned int>(strlen(name)), name);
2291     }
2292 #else
2293     return S_OK;
2294 #endif
2295 }
2296 
2297 // Keep this in cpp file where it has visibility of Renderer11.h, otherwise calling
2298 // allocateResource is only compatible with Clang and MSVS, which support calling a
2299 // method on a forward declared class in a template.
2300 template <ResourceType ResourceT>
resolveImpl(d3d::Context * context,Renderer11 * renderer,const GetDescType<ResourceT> & desc,GetInitDataType<ResourceT> * initData,const char * name)2301 angle::Result LazyResource<ResourceT>::resolveImpl(d3d::Context *context,
2302                                                    Renderer11 *renderer,
2303                                                    const GetDescType<ResourceT> &desc,
2304                                                    GetInitDataType<ResourceT> *initData,
2305                                                    const char *name)
2306 {
2307     if (!mResource.valid())
2308     {
2309         ANGLE_TRY(renderer->allocateResource(context, desc, initData, &mResource));
2310         mResource.setDebugName(name);
2311     }
2312     return angle::Result::Continue;
2313 }
2314 
2315 template angle::Result LazyResource<ResourceType::BlendState>::resolveImpl(
2316     d3d::Context *context,
2317     Renderer11 *renderer,
2318     const D3D11_BLEND_DESC &desc,
2319     void *initData,
2320     const char *name);
2321 template angle::Result LazyResource<ResourceType::ComputeShader>::resolveImpl(
2322     d3d::Context *context,
2323     Renderer11 *renderer,
2324     const ShaderData &desc,
2325     void *initData,
2326     const char *name);
2327 template angle::Result LazyResource<ResourceType::GeometryShader>::resolveImpl(
2328     d3d::Context *context,
2329     Renderer11 *renderer,
2330     const ShaderData &desc,
2331     const std::vector<D3D11_SO_DECLARATION_ENTRY> *initData,
2332     const char *name);
2333 template angle::Result LazyResource<ResourceType::InputLayout>::resolveImpl(
2334     d3d::Context *context,
2335     Renderer11 *renderer,
2336     const InputElementArray &desc,
2337     const ShaderData *initData,
2338     const char *name);
2339 template angle::Result LazyResource<ResourceType::PixelShader>::resolveImpl(d3d::Context *context,
2340                                                                             Renderer11 *renderer,
2341                                                                             const ShaderData &desc,
2342                                                                             void *initData,
2343                                                                             const char *name);
2344 template angle::Result LazyResource<ResourceType::VertexShader>::resolveImpl(d3d::Context *context,
2345                                                                              Renderer11 *renderer,
2346                                                                              const ShaderData &desc,
2347                                                                              void *initData,
2348                                                                              const char *name);
2349 
LazyInputLayout(const D3D11_INPUT_ELEMENT_DESC * inputDesc,size_t inputDescLen,const BYTE * byteCode,size_t byteCodeLen,const char * debugName)2350 LazyInputLayout::LazyInputLayout(const D3D11_INPUT_ELEMENT_DESC *inputDesc,
2351                                  size_t inputDescLen,
2352                                  const BYTE *byteCode,
2353                                  size_t byteCodeLen,
2354                                  const char *debugName)
2355     : mInputDesc(inputDesc, inputDescLen), mByteCode(byteCode, byteCodeLen), mDebugName(debugName)
2356 {}
2357 
~LazyInputLayout()2358 LazyInputLayout::~LazyInputLayout() {}
2359 
resolve(d3d::Context * context,Renderer11 * renderer)2360 angle::Result LazyInputLayout::resolve(d3d::Context *context, Renderer11 *renderer)
2361 {
2362     return resolveImpl(context, renderer, mInputDesc, &mByteCode, mDebugName);
2363 }
2364 
LazyBlendState(const D3D11_BLEND_DESC & desc,const char * debugName)2365 LazyBlendState::LazyBlendState(const D3D11_BLEND_DESC &desc, const char *debugName)
2366     : mDesc(desc), mDebugName(debugName)
2367 {}
2368 
resolve(d3d::Context * context,Renderer11 * renderer)2369 angle::Result LazyBlendState::resolve(d3d::Context *context, Renderer11 *renderer)
2370 {
2371     return resolveImpl(context, renderer, mDesc, nullptr, mDebugName);
2372 }
2373 
InitializeFeatures(const Renderer11DeviceCaps & deviceCaps,const DXGI_ADAPTER_DESC & adapterDesc,angle::FeaturesD3D * features)2374 void InitializeFeatures(const Renderer11DeviceCaps &deviceCaps,
2375                         const DXGI_ADAPTER_DESC &adapterDesc,
2376                         angle::FeaturesD3D *features)
2377 {
2378     bool isNvidia          = IsNvidia(adapterDesc.VendorId);
2379     bool isIntel           = IsIntel(adapterDesc.VendorId);
2380     bool isSkylake         = false;
2381     bool isBroadwell       = false;
2382     bool isHaswell         = false;
2383     bool isIvyBridge       = false;
2384     bool isAMD             = IsAMD(adapterDesc.VendorId);
2385     bool isFeatureLevel9_3 = (deviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3);
2386 #if defined(ANGLE_ENABLE_WINDOWS_UWP)
2387     bool isWin10 = true;
2388 #else
2389     bool isWin10 = IsWindows10OrGreater();
2390 #endif
2391     IntelDriverVersion capsVersion = IntelDriverVersion(0);
2392     if (isIntel)
2393     {
2394         capsVersion = d3d11_gl::GetIntelDriverVersion(deviceCaps.driverVersion);
2395 
2396         isSkylake   = IsSkylake(adapterDesc.DeviceId);
2397         isBroadwell = IsBroadwell(adapterDesc.DeviceId);
2398         isHaswell   = IsHaswell(adapterDesc.DeviceId);
2399         isIvyBridge = IsIvyBridge(adapterDesc.DeviceId);
2400     }
2401 
2402     if (isNvidia)
2403     {
2404         // TODO(jmadill): Narrow problematic driver range.
2405         bool driverVersionValid = deviceCaps.driverVersion.valid();
2406         if (driverVersionValid)
2407         {
2408             WORD part1 = HIWORD(deviceCaps.driverVersion.value().LowPart);
2409             WORD part2 = LOWORD(deviceCaps.driverVersion.value().LowPart);
2410 
2411             // Disable the workaround to fix a second driver bug on newer NVIDIA.
2412             ANGLE_FEATURE_CONDITION(
2413                 features, depthStencilBlitExtraCopy,
2414                 (part1 <= 13u && part2 < 6881) && isNvidia && driverVersionValid);
2415         }
2416         else
2417         {
2418             ANGLE_FEATURE_CONDITION(features, depthStencilBlitExtraCopy,
2419                                     isNvidia && !driverVersionValid);
2420         }
2421     }
2422 
2423     ANGLE_FEATURE_CONDITION(features, mrtPerfWorkaround, true);
2424     ANGLE_FEATURE_CONDITION(features, zeroMaxLodWorkaround, isFeatureLevel9_3);
2425     ANGLE_FEATURE_CONDITION(features, useInstancedPointSpriteEmulation, isFeatureLevel9_3);
2426 
2427     // TODO(jmadill): Disable workaround when we have a fixed compiler DLL.
2428     ANGLE_FEATURE_CONDITION(features, expandIntegerPowExpressions, true);
2429 
2430     ANGLE_FEATURE_CONDITION(features, flushAfterEndingTransformFeedback, isNvidia);
2431     ANGLE_FEATURE_CONDITION(features, getDimensionsIgnoresBaseLevel, isNvidia);
2432     ANGLE_FEATURE_CONDITION(features, skipVSConstantRegisterZero, isNvidia);
2433     ANGLE_FEATURE_CONDITION(features, forceAtomicValueResolution, isNvidia);
2434 
2435     ANGLE_FEATURE_CONDITION(features, preAddTexelFetchOffsets, isIntel);
2436     ANGLE_FEATURE_CONDITION(features, useSystemMemoryForConstantBuffers, isIntel);
2437 
2438     ANGLE_FEATURE_CONDITION(features, callClearTwice,
2439                             isIntel && isSkylake && capsVersion < IntelDriverVersion(4771));
2440     ANGLE_FEATURE_CONDITION(features, emulateIsnanFloat,
2441                             isIntel && isSkylake && capsVersion < IntelDriverVersion(4542));
2442     ANGLE_FEATURE_CONDITION(
2443         features, rewriteUnaryMinusOperator,
2444         isIntel && (isBroadwell || isHaswell) && capsVersion < IntelDriverVersion(4624));
2445 
2446     ANGLE_FEATURE_CONDITION(features, addDummyTextureNoRenderTarget,
2447                             isIntel && capsVersion < IntelDriverVersion(4815));
2448 
2449     // Haswell/Ivybridge drivers occasionally corrupt (small?) (vertex?) texture data uploads.
2450     ANGLE_FEATURE_CONDITION(features, setDataFasterThanImageUpload,
2451                             !(isIvyBridge || isBroadwell || isHaswell));
2452 
2453     ANGLE_FEATURE_CONDITION(features, disableB5G6R5Support,
2454                             (isIntel && capsVersion < IntelDriverVersion(4539)) || isAMD);
2455 
2456     // TODO(jmadill): Disable when we have a fixed driver version.
2457     // The tiny stencil texture workaround involves using CopySubresource or UpdateSubresource on a
2458     // depth stencil texture.  This is not allowed until feature level 10.1 but since it is not
2459     // possible to support ES3 on these devices, there is no need for the workaround to begin with
2460     // (anglebug.com/1572).
2461     ANGLE_FEATURE_CONDITION(features, emulateTinyStencilTextures,
2462                             isAMD && !(deviceCaps.featureLevel < D3D_FEATURE_LEVEL_10_1));
2463 
2464     // If the VPAndRTArrayIndexFromAnyShaderFeedingRasterizer feature is not available, we have to
2465     // select the viewport / RT array index in the geometry shader.
2466     ANGLE_FEATURE_CONDITION(features, selectViewInGeometryShader,
2467                             !deviceCaps.supportsVpRtIndexWriteFromVertexShader);
2468 
2469     // NVidia drivers have no trouble clearing textures without showing corruption.
2470     // Intel and AMD drivers that have trouble have been blocklisted by Chromium. In the case of
2471     // Intel, they've been blocklisted to the DX9 runtime.
2472     ANGLE_FEATURE_CONDITION(features, allowClearForRobustResourceInit, true);
2473 
2474     // Don't translate uniform block to StructuredBuffer on Windows 7 and earlier. This is targeted
2475     // to work around a bug that fails to allocate ShaderResourceView for StructuredBuffer.
2476     ANGLE_FEATURE_CONDITION(features, dontTranslateUniformBlockToStructuredBuffer, !isWin10);
2477 
2478     // Call platform hooks for testing overrides.
2479     auto *platform = ANGLEPlatformCurrent();
2480     platform->overrideWorkaroundsD3D(platform, features);
2481 }
2482 
InitConstantBufferDesc(D3D11_BUFFER_DESC * constantBufferDescription,size_t byteWidth)2483 void InitConstantBufferDesc(D3D11_BUFFER_DESC *constantBufferDescription, size_t byteWidth)
2484 {
2485     constantBufferDescription->ByteWidth           = static_cast<UINT>(byteWidth);
2486     constantBufferDescription->Usage               = D3D11_USAGE_DYNAMIC;
2487     constantBufferDescription->BindFlags           = D3D11_BIND_CONSTANT_BUFFER;
2488     constantBufferDescription->CPUAccessFlags      = D3D11_CPU_ACCESS_WRITE;
2489     constantBufferDescription->MiscFlags           = 0;
2490     constantBufferDescription->StructureByteStride = 0;
2491 }
2492 
2493 }  // namespace d3d11
2494 
2495 // TextureHelper11 implementation.
TextureHelper11()2496 TextureHelper11::TextureHelper11() : mFormatSet(nullptr), mSampleCount(0) {}
2497 
TextureHelper11(TextureHelper11 && toCopy)2498 TextureHelper11::TextureHelper11(TextureHelper11 &&toCopy) : TextureHelper11()
2499 {
2500     *this = std::move(toCopy);
2501 }
2502 
TextureHelper11(const TextureHelper11 & other)2503 TextureHelper11::TextureHelper11(const TextureHelper11 &other)
2504     : mFormatSet(other.mFormatSet), mExtents(other.mExtents), mSampleCount(other.mSampleCount)
2505 {
2506     mData = other.mData;
2507 }
2508 
~TextureHelper11()2509 TextureHelper11::~TextureHelper11() {}
2510 
getDesc(D3D11_TEXTURE2D_DESC * desc) const2511 void TextureHelper11::getDesc(D3D11_TEXTURE2D_DESC *desc) const
2512 {
2513     static_cast<ID3D11Texture2D *>(mData->object)->GetDesc(desc);
2514 }
2515 
getDesc(D3D11_TEXTURE3D_DESC * desc) const2516 void TextureHelper11::getDesc(D3D11_TEXTURE3D_DESC *desc) const
2517 {
2518     static_cast<ID3D11Texture3D *>(mData->object)->GetDesc(desc);
2519 }
2520 
initDesc(const D3D11_TEXTURE2D_DESC & desc2D)2521 void TextureHelper11::initDesc(const D3D11_TEXTURE2D_DESC &desc2D)
2522 {
2523     mData->resourceType = ResourceType::Texture2D;
2524     mExtents.width      = static_cast<int>(desc2D.Width);
2525     mExtents.height     = static_cast<int>(desc2D.Height);
2526     mExtents.depth      = 1;
2527     mSampleCount        = desc2D.SampleDesc.Count;
2528 }
2529 
initDesc(const D3D11_TEXTURE3D_DESC & desc3D)2530 void TextureHelper11::initDesc(const D3D11_TEXTURE3D_DESC &desc3D)
2531 {
2532     mData->resourceType = ResourceType::Texture3D;
2533     mExtents.width      = static_cast<int>(desc3D.Width);
2534     mExtents.height     = static_cast<int>(desc3D.Height);
2535     mExtents.depth      = static_cast<int>(desc3D.Depth);
2536     mSampleCount        = 1;
2537 }
2538 
operator =(TextureHelper11 && other)2539 TextureHelper11 &TextureHelper11::operator=(TextureHelper11 &&other)
2540 {
2541     std::swap(mData, other.mData);
2542     std::swap(mExtents, other.mExtents);
2543     std::swap(mFormatSet, other.mFormatSet);
2544     std::swap(mSampleCount, other.mSampleCount);
2545     return *this;
2546 }
2547 
operator =(const TextureHelper11 & other)2548 TextureHelper11 &TextureHelper11::operator=(const TextureHelper11 &other)
2549 {
2550     mData        = other.mData;
2551     mExtents     = other.mExtents;
2552     mFormatSet   = other.mFormatSet;
2553     mSampleCount = other.mSampleCount;
2554     return *this;
2555 }
2556 
operator ==(const TextureHelper11 & other) const2557 bool TextureHelper11::operator==(const TextureHelper11 &other) const
2558 {
2559     return mData->object == other.mData->object;
2560 }
2561 
operator !=(const TextureHelper11 & other) const2562 bool TextureHelper11::operator!=(const TextureHelper11 &other) const
2563 {
2564     return mData->object != other.mData->object;
2565 }
2566 
UsePresentPathFast(const Renderer11 * renderer,const gl::FramebufferAttachment * framebufferAttachment)2567 bool UsePresentPathFast(const Renderer11 *renderer,
2568                         const gl::FramebufferAttachment *framebufferAttachment)
2569 {
2570     if (framebufferAttachment == nullptr)
2571     {
2572         return false;
2573     }
2574 
2575     return (framebufferAttachment->type() == GL_FRAMEBUFFER_DEFAULT &&
2576             renderer->presentPathFastEnabled());
2577 }
2578 
UsePrimitiveRestartWorkaround(bool primitiveRestartFixedIndexEnabled,gl::DrawElementsType type)2579 bool UsePrimitiveRestartWorkaround(bool primitiveRestartFixedIndexEnabled,
2580                                    gl::DrawElementsType type)
2581 {
2582     // We should never have to deal with primitive restart workaround issue with GL_UNSIGNED_INT
2583     // indices, since we restrict it via MAX_ELEMENT_INDEX.
2584     return (!primitiveRestartFixedIndexEnabled && type == gl::DrawElementsType::UnsignedShort);
2585 }
2586 
ClassifyIndexStorage(const gl::State & glState,const gl::Buffer * elementArrayBuffer,gl::DrawElementsType elementType,gl::DrawElementsType destElementType,unsigned int offset)2587 IndexStorageType ClassifyIndexStorage(const gl::State &glState,
2588                                       const gl::Buffer *elementArrayBuffer,
2589                                       gl::DrawElementsType elementType,
2590                                       gl::DrawElementsType destElementType,
2591                                       unsigned int offset)
2592 {
2593     // No buffer bound means we are streaming from a client pointer.
2594     if (!elementArrayBuffer || !IsOffsetAligned(elementType, offset))
2595     {
2596         return IndexStorageType::Dynamic;
2597     }
2598 
2599     // The buffer can be used directly if the storage supports it and no translation needed.
2600     BufferD3D *bufferD3D = GetImplAs<BufferD3D>(elementArrayBuffer);
2601     if (bufferD3D->supportsDirectBinding() && destElementType == elementType)
2602     {
2603         return IndexStorageType::Direct;
2604     }
2605 
2606     // Use a static copy when available.
2607     StaticIndexBufferInterface *staticBuffer = bufferD3D->getStaticIndexBuffer();
2608     if (staticBuffer != nullptr)
2609     {
2610         return IndexStorageType::Static;
2611     }
2612 
2613     // Static buffer not available, fall back to streaming.
2614     return IndexStorageType::Dynamic;
2615 }
2616 }  // namespace rx
2617