1 //
2 // Copyright 2012 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 // renderer11_utils.cpp: Conversion functions and other utility routines
8 // specific to the D3D11 renderer.
9 
10 #include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
11 
12 #include <versionhelpers.h>
13 #include <algorithm>
14 
15 #include "common/debug.h"
16 #include "libANGLE/Buffer.h"
17 #include "libANGLE/Context.h"
18 #include "libANGLE/Framebuffer.h"
19 #include "libANGLE/Program.h"
20 #include "libANGLE/State.h"
21 #include "libANGLE/VertexArray.h"
22 #include "libANGLE/formatutils.h"
23 #include "libANGLE/renderer/d3d/BufferD3D.h"
24 #include "libANGLE/renderer/d3d/FramebufferD3D.h"
25 #include "libANGLE/renderer/d3d/d3d11/Context11.h"
26 #include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
27 #include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
28 #include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
29 #include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
30 #include "libANGLE/renderer/driver_utils.h"
31 #include "libANGLE/renderer/dxgi_support_table.h"
32 #include "platform/FeaturesD3D.h"
33 #include "platform/PlatformMethods.h"
34 
35 namespace rx
36 {
37 
38 namespace d3d11_gl
39 {
40 namespace
41 {
42 // TODO(xinghua.cao@intel.com): Get a more accurate limit.
43 static D3D_FEATURE_LEVEL kMinimumFeatureLevelForES31 = D3D_FEATURE_LEVEL_11_0;
44 
45 // Helper functor for querying DXGI support. Saves passing the parameters repeatedly.
46 class DXGISupportHelper : angle::NonCopyable
47 {
48   public:
DXGISupportHelper(ID3D11Device * device,D3D_FEATURE_LEVEL featureLevel)49     DXGISupportHelper(ID3D11Device *device, D3D_FEATURE_LEVEL featureLevel)
50         : mDevice(device), mFeatureLevel(featureLevel)
51     {}
52 
query(DXGI_FORMAT dxgiFormat,UINT supportMask)53     bool query(DXGI_FORMAT dxgiFormat, UINT supportMask)
54     {
55         if (dxgiFormat == DXGI_FORMAT_UNKNOWN)
56             return false;
57 
58         auto dxgiSupport = d3d11::GetDXGISupport(dxgiFormat, mFeatureLevel);
59 
60         UINT supportedBits = dxgiSupport.alwaysSupportedFlags;
61 
62         if ((dxgiSupport.optionallySupportedFlags & supportMask) != 0)
63         {
64             UINT formatSupport;
65             if (SUCCEEDED(mDevice->CheckFormatSupport(dxgiFormat, &formatSupport)))
66             {
67                 supportedBits |= (formatSupport & supportMask);
68             }
69             else
70             {
71                 // TODO(jmadill): find out why we fail this call sometimes in FL9_3
72                 // ERR() << "Error checking format support for format 0x" << std::hex << dxgiFormat;
73             }
74         }
75 
76         return ((supportedBits & supportMask) == supportMask);
77     }
78 
79   private:
80     ID3D11Device *mDevice;
81     D3D_FEATURE_LEVEL mFeatureLevel;
82 };
83 
GenerateTextureFormatCaps(gl::Version maxClientVersion,GLenum internalFormat,ID3D11Device * device,const Renderer11DeviceCaps & renderer11DeviceCaps)84 gl::TextureCaps GenerateTextureFormatCaps(gl::Version maxClientVersion,
85                                           GLenum internalFormat,
86                                           ID3D11Device *device,
87                                           const Renderer11DeviceCaps &renderer11DeviceCaps)
88 {
89     gl::TextureCaps textureCaps;
90 
91     DXGISupportHelper support(device, renderer11DeviceCaps.featureLevel);
92     const d3d11::Format &formatInfo = d3d11::Format::Get(internalFormat, renderer11DeviceCaps);
93 
94     const gl::InternalFormat &internalFormatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
95 
96     UINT texSupportMask = D3D11_FORMAT_SUPPORT_TEXTURE2D;
97     if (internalFormatInfo.depthBits == 0 && internalFormatInfo.stencilBits == 0)
98     {
99         texSupportMask |= D3D11_FORMAT_SUPPORT_TEXTURECUBE;
100         if (maxClientVersion.major > 2)
101         {
102             texSupportMask |= D3D11_FORMAT_SUPPORT_TEXTURE3D;
103         }
104     }
105 
106     textureCaps.texturable = support.query(formatInfo.texFormat, texSupportMask);
107     textureCaps.filterable =
108         support.query(formatInfo.srvFormat, D3D11_FORMAT_SUPPORT_SHADER_SAMPLE);
109     textureCaps.textureAttachment =
110         (support.query(formatInfo.rtvFormat, D3D11_FORMAT_SUPPORT_RENDER_TARGET)) ||
111         (support.query(formatInfo.dsvFormat, D3D11_FORMAT_SUPPORT_DEPTH_STENCIL));
112     textureCaps.renderbuffer = textureCaps.textureAttachment;
113     textureCaps.blendable    = textureCaps.renderbuffer;
114 
115     DXGI_FORMAT renderFormat = DXGI_FORMAT_UNKNOWN;
116     if (formatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN)
117     {
118         renderFormat = formatInfo.dsvFormat;
119     }
120     else if (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN)
121     {
122         renderFormat = formatInfo.rtvFormat;
123     }
124     if (renderFormat != DXGI_FORMAT_UNKNOWN &&
125         support.query(renderFormat, D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET))
126     {
127         // Assume 1x
128         textureCaps.sampleCounts.insert(1);
129 
130         for (unsigned int sampleCount = 2; sampleCount <= D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT;
131              sampleCount *= 2)
132         {
133             UINT qualityCount = 0;
134             if (SUCCEEDED(device->CheckMultisampleQualityLevels(renderFormat, sampleCount,
135                                                                 &qualityCount)))
136             {
137                 // Assume we always support lower sample counts
138                 if (qualityCount == 0)
139                 {
140                     break;
141                 }
142                 textureCaps.sampleCounts.insert(sampleCount);
143             }
144         }
145     }
146 
147     return textureCaps;
148 }
149 
GetNPOTTextureSupport(D3D_FEATURE_LEVEL featureLevel)150 bool GetNPOTTextureSupport(D3D_FEATURE_LEVEL featureLevel)
151 {
152     switch (featureLevel)
153     {
154         case D3D_FEATURE_LEVEL_11_1:
155         case D3D_FEATURE_LEVEL_11_0:
156         case D3D_FEATURE_LEVEL_10_1:
157         case D3D_FEATURE_LEVEL_10_0:
158             return true;
159 
160         // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx
161         case D3D_FEATURE_LEVEL_9_3:
162         case D3D_FEATURE_LEVEL_9_2:
163         case D3D_FEATURE_LEVEL_9_1:
164             return false;
165 
166         default:
167             UNREACHABLE();
168             return false;
169     }
170 }
171 
GetMaximumAnisotropy(D3D_FEATURE_LEVEL featureLevel)172 float GetMaximumAnisotropy(D3D_FEATURE_LEVEL featureLevel)
173 {
174     switch (featureLevel)
175     {
176         case D3D_FEATURE_LEVEL_11_1:
177         case D3D_FEATURE_LEVEL_11_0:
178             return D3D11_MAX_MAXANISOTROPY;
179 
180         case D3D_FEATURE_LEVEL_10_1:
181         case D3D_FEATURE_LEVEL_10_0:
182             return D3D10_MAX_MAXANISOTROPY;
183 
184         // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx
185         case D3D_FEATURE_LEVEL_9_3:
186         case D3D_FEATURE_LEVEL_9_2:
187             return 16;
188 
189         case D3D_FEATURE_LEVEL_9_1:
190             return D3D_FL9_1_DEFAULT_MAX_ANISOTROPY;
191 
192         default:
193             UNREACHABLE();
194             return 0;
195     }
196 }
197 
GetOcclusionQuerySupport(D3D_FEATURE_LEVEL featureLevel)198 bool GetOcclusionQuerySupport(D3D_FEATURE_LEVEL featureLevel)
199 {
200     switch (featureLevel)
201     {
202         case D3D_FEATURE_LEVEL_11_1:
203         case D3D_FEATURE_LEVEL_11_0:
204         case D3D_FEATURE_LEVEL_10_1:
205         case D3D_FEATURE_LEVEL_10_0:
206             return true;
207 
208         // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx
209         // ID3D11Device::CreateQuery
210         case D3D_FEATURE_LEVEL_9_3:
211         case D3D_FEATURE_LEVEL_9_2:
212             return true;
213         case D3D_FEATURE_LEVEL_9_1:
214             return false;
215 
216         default:
217             UNREACHABLE();
218             return false;
219     }
220 }
221 
GetEventQuerySupport(D3D_FEATURE_LEVEL featureLevel)222 bool GetEventQuerySupport(D3D_FEATURE_LEVEL featureLevel)
223 {
224     // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx
225     // ID3D11Device::CreateQuery
226 
227     switch (featureLevel)
228     {
229         case D3D_FEATURE_LEVEL_11_1:
230         case D3D_FEATURE_LEVEL_11_0:
231         case D3D_FEATURE_LEVEL_10_1:
232         case D3D_FEATURE_LEVEL_10_0:
233         case D3D_FEATURE_LEVEL_9_3:
234         case D3D_FEATURE_LEVEL_9_2:
235         case D3D_FEATURE_LEVEL_9_1:
236             return true;
237 
238         default:
239             UNREACHABLE();
240             return false;
241     }
242 }
243 
GetInstancingSupport(D3D_FEATURE_LEVEL featureLevel)244 bool GetInstancingSupport(D3D_FEATURE_LEVEL featureLevel)
245 {
246     // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx
247     // ID3D11Device::CreateInputLayout
248 
249     switch (featureLevel)
250     {
251         case D3D_FEATURE_LEVEL_11_1:
252         case D3D_FEATURE_LEVEL_11_0:
253         case D3D_FEATURE_LEVEL_10_1:
254         case D3D_FEATURE_LEVEL_10_0:
255             return true;
256 
257         // Feature Level 9_3 supports instancing, but slot 0 in the input layout must not be
258         // instanced.
259         // D3D9 has a similar restriction, where stream 0 must not be instanced.
260         // This restriction can be worked around by remapping any non-instanced slot to slot
261         // 0.
262         // This works because HLSL uses shader semantics to match the vertex inputs to the
263         // elements in the input layout, rather than the slots.
264         // Note that we only support instancing via ANGLE_instanced_array on 9_3, since 9_3
265         // doesn't support OpenGL ES 3.0
266         case D3D_FEATURE_LEVEL_9_3:
267             return true;
268 
269         case D3D_FEATURE_LEVEL_9_2:
270         case D3D_FEATURE_LEVEL_9_1:
271             return false;
272 
273         default:
274             UNREACHABLE();
275             return false;
276     }
277 }
278 
GetFramebufferMultisampleSupport(D3D_FEATURE_LEVEL featureLevel)279 bool GetFramebufferMultisampleSupport(D3D_FEATURE_LEVEL featureLevel)
280 {
281     switch (featureLevel)
282     {
283         case D3D_FEATURE_LEVEL_11_1:
284         case D3D_FEATURE_LEVEL_11_0:
285         case D3D_FEATURE_LEVEL_10_1:
286         case D3D_FEATURE_LEVEL_10_0:
287             return true;
288 
289         case D3D_FEATURE_LEVEL_9_3:
290         case D3D_FEATURE_LEVEL_9_2:
291         case D3D_FEATURE_LEVEL_9_1:
292             return false;
293 
294         default:
295             UNREACHABLE();
296             return false;
297     }
298 }
299 
GetFramebufferBlitSupport(D3D_FEATURE_LEVEL featureLevel)300 bool GetFramebufferBlitSupport(D3D_FEATURE_LEVEL featureLevel)
301 {
302     switch (featureLevel)
303     {
304         case D3D_FEATURE_LEVEL_11_1:
305         case D3D_FEATURE_LEVEL_11_0:
306         case D3D_FEATURE_LEVEL_10_1:
307         case D3D_FEATURE_LEVEL_10_0:
308             return true;
309 
310         case D3D_FEATURE_LEVEL_9_3:
311         case D3D_FEATURE_LEVEL_9_2:
312         case D3D_FEATURE_LEVEL_9_1:
313             return false;
314 
315         default:
316             UNREACHABLE();
317             return false;
318     }
319 }
320 
GetDerivativeInstructionSupport(D3D_FEATURE_LEVEL featureLevel)321 bool GetDerivativeInstructionSupport(D3D_FEATURE_LEVEL featureLevel)
322 {
323     // http://msdn.microsoft.com/en-us/library/windows/desktop/bb509588.aspx states that
324     // shader model
325     // ps_2_x is required for the ddx (and other derivative functions).
326 
327     // http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx states that
328     // feature level
329     // 9.3 supports shader model ps_2_x.
330 
331     switch (featureLevel)
332     {
333         case D3D_FEATURE_LEVEL_11_1:
334         case D3D_FEATURE_LEVEL_11_0:
335         case D3D_FEATURE_LEVEL_10_1:
336         case D3D_FEATURE_LEVEL_10_0:
337         case D3D_FEATURE_LEVEL_9_3:
338             return true;
339         case D3D_FEATURE_LEVEL_9_2:
340         case D3D_FEATURE_LEVEL_9_1:
341             return false;
342 
343         default:
344             UNREACHABLE();
345             return false;
346     }
347 }
348 
GetShaderTextureLODSupport(D3D_FEATURE_LEVEL featureLevel)349 bool GetShaderTextureLODSupport(D3D_FEATURE_LEVEL featureLevel)
350 {
351     switch (featureLevel)
352     {
353         case D3D_FEATURE_LEVEL_11_1:
354         case D3D_FEATURE_LEVEL_11_0:
355         case D3D_FEATURE_LEVEL_10_1:
356         case D3D_FEATURE_LEVEL_10_0:
357             return true;
358 
359         case D3D_FEATURE_LEVEL_9_3:
360         case D3D_FEATURE_LEVEL_9_2:
361         case D3D_FEATURE_LEVEL_9_1:
362             return false;
363 
364         default:
365             UNREACHABLE();
366             return false;
367     }
368 }
369 
GetMaximumSimultaneousRenderTargets(D3D_FEATURE_LEVEL featureLevel)370 int GetMaximumSimultaneousRenderTargets(D3D_FEATURE_LEVEL featureLevel)
371 {
372     // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx
373     // ID3D11Device::CreateInputLayout
374 
375     switch (featureLevel)
376     {
377         case D3D_FEATURE_LEVEL_11_1:
378         case D3D_FEATURE_LEVEL_11_0:
379             return D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT;
380 
381         case D3D_FEATURE_LEVEL_10_1:
382         case D3D_FEATURE_LEVEL_10_0:
383             return D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT;
384 
385         case D3D_FEATURE_LEVEL_9_3:
386             return D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT;
387         case D3D_FEATURE_LEVEL_9_2:
388         case D3D_FEATURE_LEVEL_9_1:
389             return D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT;
390 
391         default:
392             UNREACHABLE();
393             return 0;
394     }
395 }
396 
GetMaximum2DTextureSize(D3D_FEATURE_LEVEL featureLevel)397 int GetMaximum2DTextureSize(D3D_FEATURE_LEVEL featureLevel)
398 {
399     switch (featureLevel)
400     {
401         case D3D_FEATURE_LEVEL_11_1:
402         case D3D_FEATURE_LEVEL_11_0:
403             return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;
404 
405         case D3D_FEATURE_LEVEL_10_1:
406         case D3D_FEATURE_LEVEL_10_0:
407             return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION;
408 
409         case D3D_FEATURE_LEVEL_9_3:
410             return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION;
411         case D3D_FEATURE_LEVEL_9_2:
412         case D3D_FEATURE_LEVEL_9_1:
413             return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION;
414 
415         default:
416             UNREACHABLE();
417             return 0;
418     }
419 }
420 
GetMaximumCubeMapTextureSize(D3D_FEATURE_LEVEL featureLevel)421 int GetMaximumCubeMapTextureSize(D3D_FEATURE_LEVEL featureLevel)
422 {
423     switch (featureLevel)
424     {
425         case D3D_FEATURE_LEVEL_11_1:
426         case D3D_FEATURE_LEVEL_11_0:
427             return D3D11_REQ_TEXTURECUBE_DIMENSION;
428 
429         case D3D_FEATURE_LEVEL_10_1:
430         case D3D_FEATURE_LEVEL_10_0:
431             return D3D10_REQ_TEXTURECUBE_DIMENSION;
432 
433         case D3D_FEATURE_LEVEL_9_3:
434             return D3D_FL9_3_REQ_TEXTURECUBE_DIMENSION;
435         case D3D_FEATURE_LEVEL_9_2:
436         case D3D_FEATURE_LEVEL_9_1:
437             return D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION;
438 
439         default:
440             UNREACHABLE();
441             return 0;
442     }
443 }
444 
GetMaximum2DTextureArraySize(D3D_FEATURE_LEVEL featureLevel)445 int GetMaximum2DTextureArraySize(D3D_FEATURE_LEVEL featureLevel)
446 {
447     switch (featureLevel)
448     {
449         case D3D_FEATURE_LEVEL_11_1:
450         case D3D_FEATURE_LEVEL_11_0:
451             return D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION;
452 
453         case D3D_FEATURE_LEVEL_10_1:
454         case D3D_FEATURE_LEVEL_10_0:
455             return D3D10_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION;
456 
457         case D3D_FEATURE_LEVEL_9_3:
458         case D3D_FEATURE_LEVEL_9_2:
459         case D3D_FEATURE_LEVEL_9_1:
460             return 0;
461 
462         default:
463             UNREACHABLE();
464             return 0;
465     }
466 }
467 
GetMaximum3DTextureSize(D3D_FEATURE_LEVEL featureLevel)468 int GetMaximum3DTextureSize(D3D_FEATURE_LEVEL featureLevel)
469 {
470     switch (featureLevel)
471     {
472         case D3D_FEATURE_LEVEL_11_1:
473         case D3D_FEATURE_LEVEL_11_0:
474             return D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION;
475 
476         case D3D_FEATURE_LEVEL_10_1:
477         case D3D_FEATURE_LEVEL_10_0:
478             return D3D10_REQ_TEXTURE3D_U_V_OR_W_DIMENSION;
479 
480         case D3D_FEATURE_LEVEL_9_3:
481         case D3D_FEATURE_LEVEL_9_2:
482         case D3D_FEATURE_LEVEL_9_1:
483             return D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION;
484 
485         default:
486             UNREACHABLE();
487             return 0;
488     }
489 }
490 
GetMaximumViewportSize(D3D_FEATURE_LEVEL featureLevel)491 int GetMaximumViewportSize(D3D_FEATURE_LEVEL featureLevel)
492 {
493     switch (featureLevel)
494     {
495         case D3D_FEATURE_LEVEL_11_1:
496         case D3D_FEATURE_LEVEL_11_0:
497             return D3D11_VIEWPORT_BOUNDS_MAX;
498 
499         case D3D_FEATURE_LEVEL_10_1:
500         case D3D_FEATURE_LEVEL_10_0:
501             return D3D10_VIEWPORT_BOUNDS_MAX;
502 
503         // No constants for D3D11 Feature Level 9 viewport size limits, use the maximum
504         // texture sizes
505         case D3D_FEATURE_LEVEL_9_3:
506             return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION;
507         case D3D_FEATURE_LEVEL_9_2:
508         case D3D_FEATURE_LEVEL_9_1:
509             return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION;
510 
511         default:
512             UNREACHABLE();
513             return 0;
514     }
515 }
516 
GetMaximumDrawIndexedIndexCount(D3D_FEATURE_LEVEL featureLevel)517 int GetMaximumDrawIndexedIndexCount(D3D_FEATURE_LEVEL featureLevel)
518 {
519     // D3D11 allows up to 2^32 elements, but we report max signed int for convenience since
520     // that's what's
521     // returned from glGetInteger
522     static_assert(D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP == 32,
523                   "Unexpected D3D11 constant value.");
524     static_assert(D3D10_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP == 32,
525                   "Unexpected D3D11 constant value.");
526 
527     switch (featureLevel)
528     {
529         case D3D_FEATURE_LEVEL_11_1:
530         case D3D_FEATURE_LEVEL_11_0:
531         case D3D_FEATURE_LEVEL_10_1:
532         case D3D_FEATURE_LEVEL_10_0:
533             return std::numeric_limits<GLint>::max();
534 
535         case D3D_FEATURE_LEVEL_9_3:
536         case D3D_FEATURE_LEVEL_9_2:
537             return D3D_FL9_2_IA_PRIMITIVE_MAX_COUNT;
538         case D3D_FEATURE_LEVEL_9_1:
539             return D3D_FL9_1_IA_PRIMITIVE_MAX_COUNT;
540 
541         default:
542             UNREACHABLE();
543             return 0;
544     }
545 }
546 
GetMaximumDrawVertexCount(D3D_FEATURE_LEVEL featureLevel)547 int GetMaximumDrawVertexCount(D3D_FEATURE_LEVEL featureLevel)
548 {
549     // D3D11 allows up to 2^32 elements, but we report max signed int for convenience since
550     // that's what's
551     // returned from glGetInteger
552     static_assert(D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP == 32, "Unexpected D3D11 constant value.");
553     static_assert(D3D10_REQ_DRAW_VERTEX_COUNT_2_TO_EXP == 32, "Unexpected D3D11 constant value.");
554 
555     switch (featureLevel)
556     {
557         case D3D_FEATURE_LEVEL_11_1:
558         case D3D_FEATURE_LEVEL_11_0:
559         case D3D_FEATURE_LEVEL_10_1:
560         case D3D_FEATURE_LEVEL_10_0:
561             return std::numeric_limits<GLint>::max();
562 
563         case D3D_FEATURE_LEVEL_9_3:
564         case D3D_FEATURE_LEVEL_9_2:
565             return D3D_FL9_2_IA_PRIMITIVE_MAX_COUNT;
566         case D3D_FEATURE_LEVEL_9_1:
567             return D3D_FL9_1_IA_PRIMITIVE_MAX_COUNT;
568 
569         default:
570             UNREACHABLE();
571             return 0;
572     }
573 }
574 
GetMaximumVertexInputSlots(D3D_FEATURE_LEVEL featureLevel)575 int GetMaximumVertexInputSlots(D3D_FEATURE_LEVEL featureLevel)
576 {
577     switch (featureLevel)
578     {
579         case D3D_FEATURE_LEVEL_11_1:
580         case D3D_FEATURE_LEVEL_11_0:
581             return D3D11_STANDARD_VERTEX_ELEMENT_COUNT;
582 
583         case D3D_FEATURE_LEVEL_10_1:
584             return D3D10_1_STANDARD_VERTEX_ELEMENT_COUNT;
585         case D3D_FEATURE_LEVEL_10_0:
586             return D3D10_STANDARD_VERTEX_ELEMENT_COUNT;
587 
588         // From http://http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx
589         // "Max Input Slots"
590         case D3D_FEATURE_LEVEL_9_3:
591         case D3D_FEATURE_LEVEL_9_2:
592         case D3D_FEATURE_LEVEL_9_1:
593             return 16;
594 
595         default:
596             UNREACHABLE();
597             return 0;
598     }
599 }
600 
GetMaximumVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel)601 int GetMaximumVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel)
602 {
603     switch (featureLevel)
604     {
605         case D3D_FEATURE_LEVEL_11_1:
606         case D3D_FEATURE_LEVEL_11_0:
607             return D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT;
608 
609         case D3D_FEATURE_LEVEL_10_1:
610         case D3D_FEATURE_LEVEL_10_0:
611             return D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT;
612 
613         // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476149.aspx
614         // ID3D11DeviceContext::VSSetConstantBuffers
615         case D3D_FEATURE_LEVEL_9_3:
616         case D3D_FEATURE_LEVEL_9_2:
617         case D3D_FEATURE_LEVEL_9_1:
618             return 255 - d3d11_gl::GetReservedVertexUniformVectors(featureLevel);
619 
620         default:
621             UNREACHABLE();
622             return 0;
623     }
624 }
625 
GetMaximumVertexUniformBlocks(D3D_FEATURE_LEVEL featureLevel)626 int GetMaximumVertexUniformBlocks(D3D_FEATURE_LEVEL featureLevel)
627 {
628     switch (featureLevel)
629     {
630         case D3D_FEATURE_LEVEL_11_1:
631         case D3D_FEATURE_LEVEL_11_0:
632             return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT -
633                    d3d11::RESERVED_CONSTANT_BUFFER_SLOT_COUNT;
634 
635         case D3D_FEATURE_LEVEL_10_1:
636         case D3D_FEATURE_LEVEL_10_0:
637             return D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT -
638                    d3d11::RESERVED_CONSTANT_BUFFER_SLOT_COUNT;
639 
640         // Uniform blocks not supported on D3D11 Feature Level 9
641         case D3D_FEATURE_LEVEL_9_3:
642         case D3D_FEATURE_LEVEL_9_2:
643         case D3D_FEATURE_LEVEL_9_1:
644             return 0;
645 
646         default:
647             UNREACHABLE();
648             return 0;
649     }
650 }
651 
GetReservedVertexOutputVectors(D3D_FEATURE_LEVEL featureLevel)652 int GetReservedVertexOutputVectors(D3D_FEATURE_LEVEL featureLevel)
653 {
654     // According to The OpenGL ES Shading Language specifications
655     // (Language Version 1.00 section 10.16, Language Version 3.10 section 12.21)
656     // built-in special variables (e.g. gl_FragCoord, or gl_PointCoord)
657     // which are statically used in the shader should be included in the variable packing
658     // algorithm.
659     // Therefore, we should not reserve output vectors for them.
660 
661     switch (featureLevel)
662     {
663         // We must reserve one output vector for dx_Position.
664         // We also reserve one for gl_Position, which we unconditionally output on Feature
665         // Levels 10_0+,
666         // even if it's unused in the shader (e.g. for transform feedback). TODO: This could
667         // be improved.
668         case D3D_FEATURE_LEVEL_11_1:
669         case D3D_FEATURE_LEVEL_11_0:
670         case D3D_FEATURE_LEVEL_10_1:
671         case D3D_FEATURE_LEVEL_10_0:
672             return 2;
673 
674         // Just reserve dx_Position on Feature Level 9, since we don't ever need to output
675         // gl_Position.
676         case D3D_FEATURE_LEVEL_9_3:
677         case D3D_FEATURE_LEVEL_9_2:
678         case D3D_FEATURE_LEVEL_9_1:
679             return 1;
680 
681         default:
682             UNREACHABLE();
683             return 0;
684     }
685 }
686 
GetMaximumVertexOutputVectors(D3D_FEATURE_LEVEL featureLevel)687 int GetMaximumVertexOutputVectors(D3D_FEATURE_LEVEL featureLevel)
688 {
689     static_assert(gl::IMPLEMENTATION_MAX_VARYING_VECTORS == D3D11_VS_OUTPUT_REGISTER_COUNT,
690                   "Unexpected D3D11 constant value.");
691 
692     switch (featureLevel)
693     {
694         case D3D_FEATURE_LEVEL_11_1:
695         case D3D_FEATURE_LEVEL_11_0:
696             return D3D11_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel);
697 
698         case D3D_FEATURE_LEVEL_10_1:
699             return D3D10_1_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel);
700         case D3D_FEATURE_LEVEL_10_0:
701             return D3D10_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel);
702 
703         // Use Shader Model 2.X limits
704         case D3D_FEATURE_LEVEL_9_3:
705         case D3D_FEATURE_LEVEL_9_2:
706         case D3D_FEATURE_LEVEL_9_1:
707             return 8 - GetReservedVertexOutputVectors(featureLevel);
708 
709         default:
710             UNREACHABLE();
711             return 0;
712     }
713 }
714 
GetMaximumVertexTextureUnits(D3D_FEATURE_LEVEL featureLevel)715 int GetMaximumVertexTextureUnits(D3D_FEATURE_LEVEL featureLevel)
716 {
717     switch (featureLevel)
718     {
719         case D3D_FEATURE_LEVEL_11_1:
720         case D3D_FEATURE_LEVEL_11_0:
721             return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT;
722 
723         case D3D_FEATURE_LEVEL_10_1:
724         case D3D_FEATURE_LEVEL_10_0:
725             return D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT;
726 
727         // Vertex textures not supported on D3D11 Feature Level 9 according to
728         // http://msdn.microsoft.com/en-us/library/windows/desktop/ff476149.aspx
729         // ID3D11DeviceContext::VSSetSamplers and ID3D11DeviceContext::VSSetShaderResources
730         case D3D_FEATURE_LEVEL_9_3:
731         case D3D_FEATURE_LEVEL_9_2:
732         case D3D_FEATURE_LEVEL_9_1:
733             return 0;
734 
735         default:
736             UNREACHABLE();
737             return 0;
738     }
739 }
740 
GetMaximumPixelUniformVectors(D3D_FEATURE_LEVEL featureLevel)741 int GetMaximumPixelUniformVectors(D3D_FEATURE_LEVEL featureLevel)
742 {
743     // TODO(geofflang): Remove hard-coded limit once the gl-uniform-arrays test can pass
744     switch (featureLevel)
745     {
746         case D3D_FEATURE_LEVEL_11_1:
747         case D3D_FEATURE_LEVEL_11_0:
748             return 1024;  // D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT;
749 
750         case D3D_FEATURE_LEVEL_10_1:
751         case D3D_FEATURE_LEVEL_10_0:
752             return 1024;  // D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT;
753 
754         // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476149.aspx
755         // ID3D11DeviceContext::PSSetConstantBuffers
756         case D3D_FEATURE_LEVEL_9_3:
757         case D3D_FEATURE_LEVEL_9_2:
758         case D3D_FEATURE_LEVEL_9_1:
759             return 32 - d3d11_gl::GetReservedFragmentUniformVectors(featureLevel);
760 
761         default:
762             UNREACHABLE();
763             return 0;
764     }
765 }
766 
GetMaximumPixelUniformBlocks(D3D_FEATURE_LEVEL featureLevel)767 int GetMaximumPixelUniformBlocks(D3D_FEATURE_LEVEL featureLevel)
768 {
769     switch (featureLevel)
770     {
771         case D3D_FEATURE_LEVEL_11_1:
772         case D3D_FEATURE_LEVEL_11_0:
773             return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT -
774                    d3d11::RESERVED_CONSTANT_BUFFER_SLOT_COUNT;
775 
776         case D3D_FEATURE_LEVEL_10_1:
777         case D3D_FEATURE_LEVEL_10_0:
778             return D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT -
779                    d3d11::RESERVED_CONSTANT_BUFFER_SLOT_COUNT;
780 
781         // Uniform blocks not supported on D3D11 Feature Level 9
782         case D3D_FEATURE_LEVEL_9_3:
783         case D3D_FEATURE_LEVEL_9_2:
784         case D3D_FEATURE_LEVEL_9_1:
785             return 0;
786 
787         default:
788             UNREACHABLE();
789             return 0;
790     }
791 }
792 
GetMaximumPixelInputVectors(D3D_FEATURE_LEVEL featureLevel)793 int GetMaximumPixelInputVectors(D3D_FEATURE_LEVEL featureLevel)
794 {
795     switch (featureLevel)
796     {
797         case D3D_FEATURE_LEVEL_11_1:
798         case D3D_FEATURE_LEVEL_11_0:
799             return D3D11_PS_INPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel);
800 
801         case D3D_FEATURE_LEVEL_10_1:
802         case D3D_FEATURE_LEVEL_10_0:
803             return D3D10_PS_INPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel);
804 
805         // Use Shader Model 2.X limits
806         case D3D_FEATURE_LEVEL_9_3:
807             return 8 - GetReservedVertexOutputVectors(featureLevel);
808         case D3D_FEATURE_LEVEL_9_2:
809         case D3D_FEATURE_LEVEL_9_1:
810             return 8 - GetReservedVertexOutputVectors(featureLevel);
811 
812         default:
813             UNREACHABLE();
814             return 0;
815     }
816 }
817 
GetMaximumPixelTextureUnits(D3D_FEATURE_LEVEL featureLevel)818 int GetMaximumPixelTextureUnits(D3D_FEATURE_LEVEL featureLevel)
819 {
820     switch (featureLevel)
821     {
822         case D3D_FEATURE_LEVEL_11_1:
823         case D3D_FEATURE_LEVEL_11_0:
824             return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT;
825 
826         case D3D_FEATURE_LEVEL_10_1:
827         case D3D_FEATURE_LEVEL_10_0:
828             return D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT;
829 
830         // http://msdn.microsoft.com/en-us/library/windows/desktop/ff476149.aspx
831         // ID3D11DeviceContext::PSSetShaderResources
832         case D3D_FEATURE_LEVEL_9_3:
833         case D3D_FEATURE_LEVEL_9_2:
834         case D3D_FEATURE_LEVEL_9_1:
835             return 16;
836 
837         default:
838             UNREACHABLE();
839             return 0;
840     }
841 }
842 
GetMaxComputeWorkGroupCount(D3D_FEATURE_LEVEL featureLevel)843 std::array<GLint, 3> GetMaxComputeWorkGroupCount(D3D_FEATURE_LEVEL featureLevel)
844 {
845     switch (featureLevel)
846     {
847         case D3D_FEATURE_LEVEL_11_1:
848         case D3D_FEATURE_LEVEL_11_0:
849             return {{D3D11_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION,
850                      D3D11_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION,
851                      D3D11_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION}};
852             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     // http://anglebug.com/4926
1646     extensions->texture3DOES              = false;
1647     extensions->baseVertexBaseInstance    = true;
1648     extensions->drawElementsBaseVertexOES = true;
1649     extensions->drawElementsBaseVertexEXT = true;
1650     if (!strstr(description, "Adreno"))
1651     {
1652         extensions->multisampledRenderToTexture = true;
1653     }
1654     extensions->webglVideoTexture = true;
1655 
1656     // D3D11 cannot support reading depth texture as a luminance texture.
1657     // It treats it as a red-channel-only texture.
1658     extensions->depthTextureOES = false;
1659 
1660     // readPixels on depth & stencil not working with D3D11 backend.
1661     extensions->readDepthNV         = false;
1662     extensions->readStencilNV       = false;
1663     extensions->depthBufferFloat2NV = false;
1664 
1665     // D3D11 Feature Level 10_0+ uses SV_IsFrontFace in HLSL to emulate gl_FrontFacing.
1666     // D3D11 Feature Level 9_3 doesn't support SV_IsFrontFace, and has no equivalent, so can't
1667     // support gl_FrontFacing.
1668     limitations->noFrontFacingSupport =
1669         (renderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3);
1670 
1671     // D3D11 Feature Level 9_3 doesn't support alpha-to-coverage
1672     limitations->noSampleAlphaToCoverageSupport =
1673         (renderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3);
1674 
1675     // D3D11 Feature Levels 9_3 and below do not support non-constant loop indexing and require
1676     // additional
1677     // pre-validation of the shader at compile time to produce a better error message.
1678     limitations->shadersRequireIndexedLoopValidation =
1679         (renderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3);
1680 
1681     // D3D11 has no concept of separate masks and refs for front and back faces in the depth stencil
1682     // state.
1683     limitations->noSeparateStencilRefsAndMasks = true;
1684 
1685     // D3D11 cannot support constant color and alpha blend funcs together
1686     limitations->noSimultaneousConstantColorAndAlphaBlendFunc = true;
1687 
1688     // D3D11 does not support multiple transform feedback outputs writing to the same buffer.
1689     limitations->noDoubleBoundTransformFeedbackBuffers = true;
1690 
1691     // D3D11 does not support vertex attribute aliasing
1692     limitations->noVertexAttributeAliasing = true;
1693 
1694 #ifdef ANGLE_ENABLE_WINDOWS_UWP
1695     // Setting a non-zero divisor on attribute zero doesn't work on certain Windows Phone 8-era
1696     // devices. We should prevent developers from doing this on ALL Windows Store devices. This will
1697     // maintain consistency across all Windows devices. We allow non-zero divisors on attribute zero
1698     // if the Client Version >= 3, since devices affected by this issue don't support ES3+.
1699     limitations->attributeZeroRequiresZeroDivisorInEXT = true;
1700 #endif
1701 }
1702 
1703 }  // namespace d3d11_gl
1704 
1705 namespace gl_d3d11
1706 {
1707 
ConvertBlendFunc(GLenum glBlend,bool isAlpha)1708 D3D11_BLEND ConvertBlendFunc(GLenum glBlend, bool isAlpha)
1709 {
1710     D3D11_BLEND d3dBlend = D3D11_BLEND_ZERO;
1711 
1712     switch (glBlend)
1713     {
1714         case GL_ZERO:
1715             d3dBlend = D3D11_BLEND_ZERO;
1716             break;
1717         case GL_ONE:
1718             d3dBlend = D3D11_BLEND_ONE;
1719             break;
1720         case GL_SRC_COLOR:
1721             d3dBlend = (isAlpha ? D3D11_BLEND_SRC_ALPHA : D3D11_BLEND_SRC_COLOR);
1722             break;
1723         case GL_ONE_MINUS_SRC_COLOR:
1724             d3dBlend = (isAlpha ? D3D11_BLEND_INV_SRC_ALPHA : D3D11_BLEND_INV_SRC_COLOR);
1725             break;
1726         case GL_DST_COLOR:
1727             d3dBlend = (isAlpha ? D3D11_BLEND_DEST_ALPHA : D3D11_BLEND_DEST_COLOR);
1728             break;
1729         case GL_ONE_MINUS_DST_COLOR:
1730             d3dBlend = (isAlpha ? D3D11_BLEND_INV_DEST_ALPHA : D3D11_BLEND_INV_DEST_COLOR);
1731             break;
1732         case GL_SRC_ALPHA:
1733             d3dBlend = D3D11_BLEND_SRC_ALPHA;
1734             break;
1735         case GL_ONE_MINUS_SRC_ALPHA:
1736             d3dBlend = D3D11_BLEND_INV_SRC_ALPHA;
1737             break;
1738         case GL_DST_ALPHA:
1739             d3dBlend = D3D11_BLEND_DEST_ALPHA;
1740             break;
1741         case GL_ONE_MINUS_DST_ALPHA:
1742             d3dBlend = D3D11_BLEND_INV_DEST_ALPHA;
1743             break;
1744         case GL_CONSTANT_COLOR:
1745             d3dBlend = D3D11_BLEND_BLEND_FACTOR;
1746             break;
1747         case GL_ONE_MINUS_CONSTANT_COLOR:
1748             d3dBlend = D3D11_BLEND_INV_BLEND_FACTOR;
1749             break;
1750         case GL_CONSTANT_ALPHA:
1751             d3dBlend = D3D11_BLEND_BLEND_FACTOR;
1752             break;
1753         case GL_ONE_MINUS_CONSTANT_ALPHA:
1754             d3dBlend = D3D11_BLEND_INV_BLEND_FACTOR;
1755             break;
1756         case GL_SRC_ALPHA_SATURATE:
1757             d3dBlend = D3D11_BLEND_SRC_ALPHA_SAT;
1758             break;
1759         case GL_SRC1_COLOR_EXT:
1760             d3dBlend = (isAlpha ? D3D11_BLEND_SRC1_ALPHA : D3D11_BLEND_SRC1_COLOR);
1761             break;
1762         case GL_SRC1_ALPHA_EXT:
1763             d3dBlend = D3D11_BLEND_SRC1_ALPHA;
1764             break;
1765         case GL_ONE_MINUS_SRC1_COLOR_EXT:
1766             d3dBlend = (isAlpha ? D3D11_BLEND_INV_SRC1_ALPHA : D3D11_BLEND_INV_SRC1_COLOR);
1767             break;
1768         case GL_ONE_MINUS_SRC1_ALPHA_EXT:
1769             d3dBlend = D3D11_BLEND_INV_SRC1_ALPHA;
1770             break;
1771         default:
1772             UNREACHABLE();
1773     }
1774 
1775     return d3dBlend;
1776 }
1777 
ConvertBlendOp(GLenum glBlendOp)1778 D3D11_BLEND_OP ConvertBlendOp(GLenum glBlendOp)
1779 {
1780     D3D11_BLEND_OP d3dBlendOp = D3D11_BLEND_OP_ADD;
1781 
1782     switch (glBlendOp)
1783     {
1784         case GL_FUNC_ADD:
1785             d3dBlendOp = D3D11_BLEND_OP_ADD;
1786             break;
1787         case GL_FUNC_SUBTRACT:
1788             d3dBlendOp = D3D11_BLEND_OP_SUBTRACT;
1789             break;
1790         case GL_FUNC_REVERSE_SUBTRACT:
1791             d3dBlendOp = D3D11_BLEND_OP_REV_SUBTRACT;
1792             break;
1793         case GL_MIN:
1794             d3dBlendOp = D3D11_BLEND_OP_MIN;
1795             break;
1796         case GL_MAX:
1797             d3dBlendOp = D3D11_BLEND_OP_MAX;
1798             break;
1799         default:
1800             UNREACHABLE();
1801     }
1802 
1803     return d3dBlendOp;
1804 }
1805 
ConvertColorMask(bool red,bool green,bool blue,bool alpha)1806 UINT8 ConvertColorMask(bool red, bool green, bool blue, bool alpha)
1807 {
1808     UINT8 mask = 0;
1809     if (red)
1810     {
1811         mask |= D3D11_COLOR_WRITE_ENABLE_RED;
1812     }
1813     if (green)
1814     {
1815         mask |= D3D11_COLOR_WRITE_ENABLE_GREEN;
1816     }
1817     if (blue)
1818     {
1819         mask |= D3D11_COLOR_WRITE_ENABLE_BLUE;
1820     }
1821     if (alpha)
1822     {
1823         mask |= D3D11_COLOR_WRITE_ENABLE_ALPHA;
1824     }
1825     return mask;
1826 }
1827 
ConvertCullMode(bool cullEnabled,gl::CullFaceMode cullMode)1828 D3D11_CULL_MODE ConvertCullMode(bool cullEnabled, gl::CullFaceMode cullMode)
1829 {
1830     D3D11_CULL_MODE cull = D3D11_CULL_NONE;
1831 
1832     if (cullEnabled)
1833     {
1834         switch (cullMode)
1835         {
1836             case gl::CullFaceMode::Front:
1837                 cull = D3D11_CULL_FRONT;
1838                 break;
1839             case gl::CullFaceMode::Back:
1840                 cull = D3D11_CULL_BACK;
1841                 break;
1842             case gl::CullFaceMode::FrontAndBack:
1843                 cull = D3D11_CULL_NONE;
1844                 break;
1845             default:
1846                 UNREACHABLE();
1847         }
1848     }
1849     else
1850     {
1851         cull = D3D11_CULL_NONE;
1852     }
1853 
1854     return cull;
1855 }
1856 
ConvertComparison(GLenum comparison)1857 D3D11_COMPARISON_FUNC ConvertComparison(GLenum comparison)
1858 {
1859     D3D11_COMPARISON_FUNC d3dComp = D3D11_COMPARISON_NEVER;
1860     switch (comparison)
1861     {
1862         case GL_NEVER:
1863             d3dComp = D3D11_COMPARISON_NEVER;
1864             break;
1865         case GL_ALWAYS:
1866             d3dComp = D3D11_COMPARISON_ALWAYS;
1867             break;
1868         case GL_LESS:
1869             d3dComp = D3D11_COMPARISON_LESS;
1870             break;
1871         case GL_LEQUAL:
1872             d3dComp = D3D11_COMPARISON_LESS_EQUAL;
1873             break;
1874         case GL_EQUAL:
1875             d3dComp = D3D11_COMPARISON_EQUAL;
1876             break;
1877         case GL_GREATER:
1878             d3dComp = D3D11_COMPARISON_GREATER;
1879             break;
1880         case GL_GEQUAL:
1881             d3dComp = D3D11_COMPARISON_GREATER_EQUAL;
1882             break;
1883         case GL_NOTEQUAL:
1884             d3dComp = D3D11_COMPARISON_NOT_EQUAL;
1885             break;
1886         default:
1887             UNREACHABLE();
1888     }
1889 
1890     return d3dComp;
1891 }
1892 
ConvertDepthMask(bool depthWriteEnabled)1893 D3D11_DEPTH_WRITE_MASK ConvertDepthMask(bool depthWriteEnabled)
1894 {
1895     return depthWriteEnabled ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO;
1896 }
1897 
ConvertStencilMask(GLuint stencilmask)1898 UINT8 ConvertStencilMask(GLuint stencilmask)
1899 {
1900     return static_cast<UINT8>(stencilmask);
1901 }
1902 
ConvertStencilOp(GLenum stencilOp)1903 D3D11_STENCIL_OP ConvertStencilOp(GLenum stencilOp)
1904 {
1905     D3D11_STENCIL_OP d3dStencilOp = D3D11_STENCIL_OP_KEEP;
1906 
1907     switch (stencilOp)
1908     {
1909         case GL_ZERO:
1910             d3dStencilOp = D3D11_STENCIL_OP_ZERO;
1911             break;
1912         case GL_KEEP:
1913             d3dStencilOp = D3D11_STENCIL_OP_KEEP;
1914             break;
1915         case GL_REPLACE:
1916             d3dStencilOp = D3D11_STENCIL_OP_REPLACE;
1917             break;
1918         case GL_INCR:
1919             d3dStencilOp = D3D11_STENCIL_OP_INCR_SAT;
1920             break;
1921         case GL_DECR:
1922             d3dStencilOp = D3D11_STENCIL_OP_DECR_SAT;
1923             break;
1924         case GL_INVERT:
1925             d3dStencilOp = D3D11_STENCIL_OP_INVERT;
1926             break;
1927         case GL_INCR_WRAP:
1928             d3dStencilOp = D3D11_STENCIL_OP_INCR;
1929             break;
1930         case GL_DECR_WRAP:
1931             d3dStencilOp = D3D11_STENCIL_OP_DECR;
1932             break;
1933         default:
1934             UNREACHABLE();
1935     }
1936 
1937     return d3dStencilOp;
1938 }
1939 
ConvertFilter(GLenum minFilter,GLenum magFilter,float maxAnisotropy,GLenum comparisonMode)1940 D3D11_FILTER ConvertFilter(GLenum minFilter,
1941                            GLenum magFilter,
1942                            float maxAnisotropy,
1943                            GLenum comparisonMode)
1944 {
1945     bool comparison = comparisonMode != GL_NONE;
1946 
1947     if (maxAnisotropy > 1.0f)
1948     {
1949         return D3D11_ENCODE_ANISOTROPIC_FILTER(static_cast<D3D11_COMPARISON_FUNC>(comparison));
1950     }
1951     else
1952     {
1953         D3D11_FILTER_TYPE dxMin = D3D11_FILTER_TYPE_POINT;
1954         D3D11_FILTER_TYPE dxMip = D3D11_FILTER_TYPE_POINT;
1955         switch (minFilter)
1956         {
1957             case GL_NEAREST:
1958                 dxMin = D3D11_FILTER_TYPE_POINT;
1959                 dxMip = D3D11_FILTER_TYPE_POINT;
1960                 break;
1961             case GL_LINEAR:
1962                 dxMin = D3D11_FILTER_TYPE_LINEAR;
1963                 dxMip = D3D11_FILTER_TYPE_POINT;
1964                 break;
1965             case GL_NEAREST_MIPMAP_NEAREST:
1966                 dxMin = D3D11_FILTER_TYPE_POINT;
1967                 dxMip = D3D11_FILTER_TYPE_POINT;
1968                 break;
1969             case GL_LINEAR_MIPMAP_NEAREST:
1970                 dxMin = D3D11_FILTER_TYPE_LINEAR;
1971                 dxMip = D3D11_FILTER_TYPE_POINT;
1972                 break;
1973             case GL_NEAREST_MIPMAP_LINEAR:
1974                 dxMin = D3D11_FILTER_TYPE_POINT;
1975                 dxMip = D3D11_FILTER_TYPE_LINEAR;
1976                 break;
1977             case GL_LINEAR_MIPMAP_LINEAR:
1978                 dxMin = D3D11_FILTER_TYPE_LINEAR;
1979                 dxMip = D3D11_FILTER_TYPE_LINEAR;
1980                 break;
1981             default:
1982                 UNREACHABLE();
1983         }
1984 
1985         D3D11_FILTER_TYPE dxMag = D3D11_FILTER_TYPE_POINT;
1986         switch (magFilter)
1987         {
1988             case GL_NEAREST:
1989                 dxMag = D3D11_FILTER_TYPE_POINT;
1990                 break;
1991             case GL_LINEAR:
1992                 dxMag = D3D11_FILTER_TYPE_LINEAR;
1993                 break;
1994             default:
1995                 UNREACHABLE();
1996         }
1997 
1998         return D3D11_ENCODE_BASIC_FILTER(dxMin, dxMag, dxMip,
1999                                          static_cast<D3D11_COMPARISON_FUNC>(comparison));
2000     }
2001 }
2002 
ConvertTextureWrap(GLenum wrap)2003 D3D11_TEXTURE_ADDRESS_MODE ConvertTextureWrap(GLenum wrap)
2004 {
2005     switch (wrap)
2006     {
2007         case GL_REPEAT:
2008             return D3D11_TEXTURE_ADDRESS_WRAP;
2009         case GL_CLAMP_TO_EDGE:
2010             return D3D11_TEXTURE_ADDRESS_CLAMP;
2011         case GL_CLAMP_TO_BORDER:
2012             return D3D11_TEXTURE_ADDRESS_BORDER;
2013         case GL_MIRRORED_REPEAT:
2014             return D3D11_TEXTURE_ADDRESS_MIRROR;
2015         default:
2016             UNREACHABLE();
2017     }
2018 
2019     return D3D11_TEXTURE_ADDRESS_WRAP;
2020 }
2021 
ConvertMaxAnisotropy(float maxAnisotropy,D3D_FEATURE_LEVEL featureLevel)2022 UINT ConvertMaxAnisotropy(float maxAnisotropy, D3D_FEATURE_LEVEL featureLevel)
2023 {
2024     return static_cast<UINT>(std::min(maxAnisotropy, d3d11_gl::GetMaximumAnisotropy(featureLevel)));
2025 }
2026 
ConvertQueryType(gl::QueryType type)2027 D3D11_QUERY ConvertQueryType(gl::QueryType type)
2028 {
2029     switch (type)
2030     {
2031         case gl::QueryType::AnySamples:
2032         case gl::QueryType::AnySamplesConservative:
2033             return D3D11_QUERY_OCCLUSION;
2034         case gl::QueryType::TransformFeedbackPrimitivesWritten:
2035             return D3D11_QUERY_SO_STATISTICS;
2036         case gl::QueryType::TimeElapsed:
2037             // Two internal queries are also created for begin/end timestamps
2038             return D3D11_QUERY_TIMESTAMP_DISJOINT;
2039         case gl::QueryType::CommandsCompleted:
2040             return D3D11_QUERY_EVENT;
2041         default:
2042             UNREACHABLE();
2043             return D3D11_QUERY_EVENT;
2044     }
2045 }
2046 
2047 // Get the D3D11 write mask covering all color channels of a given format
GetColorMask(const gl::InternalFormat & format)2048 UINT8 GetColorMask(const gl::InternalFormat &format)
2049 {
2050     return ConvertColorMask(format.redBits > 0, format.greenBits > 0, format.blueBits > 0,
2051                             format.alphaBits > 0);
2052 }
2053 
2054 }  // namespace gl_d3d11
2055 
2056 namespace d3d11
2057 {
2058 
GetDeviceType(ID3D11Device * device)2059 ANGLED3D11DeviceType GetDeviceType(ID3D11Device *device)
2060 {
2061     // Note that this function returns an ANGLED3D11DeviceType rather than a D3D_DRIVER_TYPE value,
2062     // since it is difficult to tell Software and Reference devices apart
2063 
2064     IDXGIDevice *dxgiDevice     = nullptr;
2065     IDXGIAdapter *dxgiAdapter   = nullptr;
2066     IDXGIAdapter2 *dxgiAdapter2 = nullptr;
2067 
2068     ANGLED3D11DeviceType retDeviceType = ANGLE_D3D11_DEVICE_TYPE_UNKNOWN;
2069 
2070     HRESULT hr = device->QueryInterface(__uuidof(IDXGIDevice), (void **)&dxgiDevice);
2071     if (SUCCEEDED(hr))
2072     {
2073         hr = dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void **)&dxgiAdapter);
2074         if (SUCCEEDED(hr))
2075         {
2076             std::wstring adapterString;
2077             HRESULT adapter2hr =
2078                 dxgiAdapter->QueryInterface(__uuidof(dxgiAdapter2), (void **)&dxgiAdapter2);
2079             if (SUCCEEDED(adapter2hr))
2080             {
2081                 // On D3D_FEATURE_LEVEL_9_*, IDXGIAdapter::GetDesc returns "Software Adapter"
2082                 // for the description string. Try to use IDXGIAdapter2::GetDesc2 to get the
2083                 // actual hardware values if possible.
2084                 DXGI_ADAPTER_DESC2 adapterDesc2;
2085                 dxgiAdapter2->GetDesc2(&adapterDesc2);
2086                 adapterString = std::wstring(adapterDesc2.Description);
2087             }
2088             else
2089             {
2090                 DXGI_ADAPTER_DESC adapterDesc;
2091                 dxgiAdapter->GetDesc(&adapterDesc);
2092                 adapterString = std::wstring(adapterDesc.Description);
2093             }
2094 
2095             // Both Reference and Software adapters will be 'Software Adapter'
2096             const bool isSoftwareDevice =
2097                 (adapterString.find(std::wstring(L"Software Adapter")) != std::string::npos);
2098             const bool isNullDevice = (adapterString == L"");
2099             const bool isWARPDevice =
2100                 (adapterString.find(std::wstring(L"Basic Render")) != std::string::npos);
2101 
2102             if (isSoftwareDevice || isNullDevice)
2103             {
2104                 ASSERT(!isWARPDevice);
2105                 retDeviceType = ANGLE_D3D11_DEVICE_TYPE_SOFTWARE_REF_OR_NULL;
2106             }
2107             else if (isWARPDevice)
2108             {
2109                 retDeviceType = ANGLE_D3D11_DEVICE_TYPE_WARP;
2110             }
2111             else
2112             {
2113                 retDeviceType = ANGLE_D3D11_DEVICE_TYPE_HARDWARE;
2114             }
2115         }
2116     }
2117 
2118     SafeRelease(dxgiDevice);
2119     SafeRelease(dxgiAdapter);
2120     SafeRelease(dxgiAdapter2);
2121 
2122     return retDeviceType;
2123 }
2124 
MakeValidSize(bool isImage,DXGI_FORMAT format,GLsizei * requestWidth,GLsizei * requestHeight,int * levelOffset)2125 void MakeValidSize(bool isImage,
2126                    DXGI_FORMAT format,
2127                    GLsizei *requestWidth,
2128                    GLsizei *requestHeight,
2129                    int *levelOffset)
2130 {
2131     const DXGIFormatSize &dxgiFormatInfo = d3d11::GetDXGIFormatSizeInfo(format);
2132 
2133     int upsampleCount = 0;
2134     // Don't expand the size of full textures that are at least (blockWidth x blockHeight) already.
2135     if (isImage || *requestWidth < static_cast<GLsizei>(dxgiFormatInfo.blockWidth) ||
2136         *requestHeight < static_cast<GLsizei>(dxgiFormatInfo.blockHeight))
2137     {
2138         while (*requestWidth % dxgiFormatInfo.blockWidth != 0 ||
2139                *requestHeight % dxgiFormatInfo.blockHeight != 0)
2140         {
2141             *requestWidth <<= 1;
2142             *requestHeight <<= 1;
2143             upsampleCount++;
2144         }
2145     }
2146     else
2147     {
2148         if (*requestWidth % dxgiFormatInfo.blockWidth != 0)
2149         {
2150             *requestWidth = roundUp(*requestWidth, static_cast<GLsizei>(dxgiFormatInfo.blockWidth));
2151         }
2152 
2153         if (*requestHeight % dxgiFormatInfo.blockHeight != 0)
2154         {
2155             *requestHeight =
2156                 roundUp(*requestHeight, static_cast<GLsizei>(dxgiFormatInfo.blockHeight));
2157         }
2158     }
2159 
2160     if (levelOffset)
2161     {
2162         *levelOffset = upsampleCount;
2163     }
2164 }
2165 
GenerateInitialTextureData(const gl::Context * context,GLint internalFormat,const Renderer11DeviceCaps & renderer11DeviceCaps,GLuint width,GLuint height,GLuint depth,GLuint mipLevels,gl::TexLevelArray<D3D11_SUBRESOURCE_DATA> * outSubresourceData)2166 angle::Result GenerateInitialTextureData(
2167     const gl::Context *context,
2168     GLint internalFormat,
2169     const Renderer11DeviceCaps &renderer11DeviceCaps,
2170     GLuint width,
2171     GLuint height,
2172     GLuint depth,
2173     GLuint mipLevels,
2174     gl::TexLevelArray<D3D11_SUBRESOURCE_DATA> *outSubresourceData)
2175 {
2176     const d3d11::Format &d3dFormatInfo = d3d11::Format::Get(internalFormat, renderer11DeviceCaps);
2177     ASSERT(d3dFormatInfo.dataInitializerFunction != nullptr);
2178 
2179     const d3d11::DXGIFormatSize &dxgiFormatInfo =
2180         d3d11::GetDXGIFormatSizeInfo(d3dFormatInfo.texFormat);
2181 
2182     unsigned int rowPitch     = dxgiFormatInfo.pixelBytes * width;
2183     unsigned int depthPitch   = rowPitch * height;
2184     unsigned int maxImageSize = depthPitch * depth;
2185 
2186     angle::MemoryBuffer *scratchBuffer = nullptr;
2187     ANGLE_CHECK_GL_ALLOC(GetImplAs<Context11>(context),
2188                          context->getScratchBuffer(maxImageSize, &scratchBuffer));
2189 
2190     d3dFormatInfo.dataInitializerFunction(width, height, depth, scratchBuffer->data(), rowPitch,
2191                                           depthPitch);
2192 
2193     for (unsigned int i = 0; i < mipLevels; i++)
2194     {
2195         unsigned int mipWidth  = std::max(width >> i, 1U);
2196         unsigned int mipHeight = std::max(height >> i, 1U);
2197 
2198         unsigned int mipRowPitch   = dxgiFormatInfo.pixelBytes * mipWidth;
2199         unsigned int mipDepthPitch = mipRowPitch * mipHeight;
2200 
2201         outSubresourceData->at(i).pSysMem          = scratchBuffer->data();
2202         outSubresourceData->at(i).SysMemPitch      = mipRowPitch;
2203         outSubresourceData->at(i).SysMemSlicePitch = mipDepthPitch;
2204     }
2205 
2206     return angle::Result::Continue;
2207 }
2208 
GetPrimitiveRestartIndex()2209 UINT GetPrimitiveRestartIndex()
2210 {
2211     return std::numeric_limits<UINT>::max();
2212 }
2213 
SetPositionTexCoordVertex(PositionTexCoordVertex * vertex,float x,float y,float u,float v)2214 void SetPositionTexCoordVertex(PositionTexCoordVertex *vertex, float x, float y, float u, float v)
2215 {
2216     vertex->x = x;
2217     vertex->y = y;
2218     vertex->u = u;
2219     vertex->v = v;
2220 }
2221 
SetPositionLayerTexCoord3DVertex(PositionLayerTexCoord3DVertex * vertex,float x,float y,unsigned int layer,float u,float v,float s)2222 void SetPositionLayerTexCoord3DVertex(PositionLayerTexCoord3DVertex *vertex,
2223                                       float x,
2224                                       float y,
2225                                       unsigned int layer,
2226                                       float u,
2227                                       float v,
2228                                       float s)
2229 {
2230     vertex->x = x;
2231     vertex->y = y;
2232     vertex->l = layer;
2233     vertex->u = u;
2234     vertex->v = v;
2235     vertex->s = s;
2236 }
2237 
BlendStateKey()2238 BlendStateKey::BlendStateKey()
2239 {
2240     memset(this, 0, sizeof(BlendStateKey));
2241     blendStateExt = gl::BlendStateExt();
2242 }
2243 
BlendStateKey(const BlendStateKey & other)2244 BlendStateKey::BlendStateKey(const BlendStateKey &other)
2245 {
2246     memcpy(this, &other, sizeof(BlendStateKey));
2247 }
2248 
operator ==(const BlendStateKey & a,const BlendStateKey & b)2249 bool operator==(const BlendStateKey &a, const BlendStateKey &b)
2250 {
2251     return memcmp(&a, &b, sizeof(BlendStateKey)) == 0;
2252 }
2253 
operator !=(const BlendStateKey & a,const BlendStateKey & b)2254 bool operator!=(const BlendStateKey &a, const BlendStateKey &b)
2255 {
2256     return !(a == b);
2257 }
2258 
RasterizerStateKey()2259 RasterizerStateKey::RasterizerStateKey()
2260 {
2261     memset(this, 0, sizeof(RasterizerStateKey));
2262 }
2263 
operator ==(const RasterizerStateKey & a,const RasterizerStateKey & b)2264 bool operator==(const RasterizerStateKey &a, const RasterizerStateKey &b)
2265 {
2266     return memcmp(&a, &b, sizeof(RasterizerStateKey)) == 0;
2267 }
2268 
operator !=(const RasterizerStateKey & a,const RasterizerStateKey & b)2269 bool operator!=(const RasterizerStateKey &a, const RasterizerStateKey &b)
2270 {
2271     return !(a == b);
2272 }
2273 
SetDebugName(ID3D11DeviceChild * resource,const char * name)2274 HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name)
2275 {
2276 #if defined(_DEBUG)
2277     UINT existingDataSize = 0;
2278     resource->GetPrivateData(WKPDID_D3DDebugObjectName, &existingDataSize, nullptr);
2279     // Don't check the HRESULT- if it failed then that probably just means that no private data
2280     // exists yet
2281 
2282     if (existingDataSize > 0)
2283     {
2284         // In some cases, ANGLE will try to apply two names to one object, which causes
2285         // a D3D SDK Layers warning. This can occur if, for example, you 'create' two objects
2286         // (e.g.Rasterizer States) with identical DESCs on the same device. D3D11 will optimize
2287         // these calls and return the same object both times.
2288         static const char *multipleNamesUsed = "Multiple names set by ANGLE";
2289 
2290         // Remove the existing name
2291         HRESULT hr = resource->SetPrivateData(WKPDID_D3DDebugObjectName, 0, nullptr);
2292         if (FAILED(hr))
2293         {
2294             return hr;
2295         }
2296 
2297         // Apply the new name
2298         return resource->SetPrivateData(WKPDID_D3DDebugObjectName,
2299                                         static_cast<unsigned int>(strlen(multipleNamesUsed)),
2300                                         multipleNamesUsed);
2301     }
2302     else
2303     {
2304         return resource->SetPrivateData(WKPDID_D3DDebugObjectName,
2305                                         static_cast<unsigned int>(strlen(name)), name);
2306     }
2307 #else
2308     return S_OK;
2309 #endif
2310 }
2311 
2312 // Keep this in cpp file where it has visibility of Renderer11.h, otherwise calling
2313 // allocateResource is only compatible with Clang and MSVS, which support calling a
2314 // method on a forward declared class in a template.
2315 template <ResourceType ResourceT>
resolveImpl(d3d::Context * context,Renderer11 * renderer,const GetDescType<ResourceT> & desc,GetInitDataType<ResourceT> * initData,const char * name)2316 angle::Result LazyResource<ResourceT>::resolveImpl(d3d::Context *context,
2317                                                    Renderer11 *renderer,
2318                                                    const GetDescType<ResourceT> &desc,
2319                                                    GetInitDataType<ResourceT> *initData,
2320                                                    const char *name)
2321 {
2322     if (!mResource.valid())
2323     {
2324         ANGLE_TRY(renderer->allocateResource(context, desc, initData, &mResource));
2325         mResource.setDebugName(name);
2326     }
2327     return angle::Result::Continue;
2328 }
2329 
2330 template angle::Result LazyResource<ResourceType::BlendState>::resolveImpl(
2331     d3d::Context *context,
2332     Renderer11 *renderer,
2333     const D3D11_BLEND_DESC &desc,
2334     void *initData,
2335     const char *name);
2336 template angle::Result LazyResource<ResourceType::ComputeShader>::resolveImpl(
2337     d3d::Context *context,
2338     Renderer11 *renderer,
2339     const ShaderData &desc,
2340     void *initData,
2341     const char *name);
2342 template angle::Result LazyResource<ResourceType::GeometryShader>::resolveImpl(
2343     d3d::Context *context,
2344     Renderer11 *renderer,
2345     const ShaderData &desc,
2346     const std::vector<D3D11_SO_DECLARATION_ENTRY> *initData,
2347     const char *name);
2348 template angle::Result LazyResource<ResourceType::InputLayout>::resolveImpl(
2349     d3d::Context *context,
2350     Renderer11 *renderer,
2351     const InputElementArray &desc,
2352     const ShaderData *initData,
2353     const char *name);
2354 template angle::Result LazyResource<ResourceType::PixelShader>::resolveImpl(d3d::Context *context,
2355                                                                             Renderer11 *renderer,
2356                                                                             const ShaderData &desc,
2357                                                                             void *initData,
2358                                                                             const char *name);
2359 template angle::Result LazyResource<ResourceType::VertexShader>::resolveImpl(d3d::Context *context,
2360                                                                              Renderer11 *renderer,
2361                                                                              const ShaderData &desc,
2362                                                                              void *initData,
2363                                                                              const char *name);
2364 
LazyInputLayout(const D3D11_INPUT_ELEMENT_DESC * inputDesc,size_t inputDescLen,const BYTE * byteCode,size_t byteCodeLen,const char * debugName)2365 LazyInputLayout::LazyInputLayout(const D3D11_INPUT_ELEMENT_DESC *inputDesc,
2366                                  size_t inputDescLen,
2367                                  const BYTE *byteCode,
2368                                  size_t byteCodeLen,
2369                                  const char *debugName)
2370     : mInputDesc(inputDesc, inputDescLen), mByteCode(byteCode, byteCodeLen), mDebugName(debugName)
2371 {}
2372 
~LazyInputLayout()2373 LazyInputLayout::~LazyInputLayout() {}
2374 
resolve(d3d::Context * context,Renderer11 * renderer)2375 angle::Result LazyInputLayout::resolve(d3d::Context *context, Renderer11 *renderer)
2376 {
2377     return resolveImpl(context, renderer, mInputDesc, &mByteCode, mDebugName);
2378 }
2379 
LazyBlendState(const D3D11_BLEND_DESC & desc,const char * debugName)2380 LazyBlendState::LazyBlendState(const D3D11_BLEND_DESC &desc, const char *debugName)
2381     : mDesc(desc), mDebugName(debugName)
2382 {}
2383 
resolve(d3d::Context * context,Renderer11 * renderer)2384 angle::Result LazyBlendState::resolve(d3d::Context *context, Renderer11 *renderer)
2385 {
2386     return resolveImpl(context, renderer, mDesc, nullptr, mDebugName);
2387 }
2388 
InitializeFeatures(const Renderer11DeviceCaps & deviceCaps,const DXGI_ADAPTER_DESC & adapterDesc,angle::FeaturesD3D * features)2389 void InitializeFeatures(const Renderer11DeviceCaps &deviceCaps,
2390                         const DXGI_ADAPTER_DESC &adapterDesc,
2391                         angle::FeaturesD3D *features)
2392 {
2393     bool isNvidia          = IsNvidia(adapterDesc.VendorId);
2394     bool isIntel           = IsIntel(adapterDesc.VendorId);
2395     bool isSkylake         = false;
2396     bool isBroadwell       = false;
2397     bool isHaswell         = false;
2398     bool isIvyBridge       = false;
2399     bool isAMD             = IsAMD(adapterDesc.VendorId);
2400     bool isFeatureLevel9_3 = (deviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3);
2401 
2402     IntelDriverVersion capsVersion = IntelDriverVersion(0);
2403     if (isIntel)
2404     {
2405         capsVersion = d3d11_gl::GetIntelDriverVersion(deviceCaps.driverVersion);
2406 
2407         isSkylake   = IsSkylake(adapterDesc.DeviceId);
2408         isBroadwell = IsBroadwell(adapterDesc.DeviceId);
2409         isHaswell   = IsHaswell(adapterDesc.DeviceId);
2410         isIvyBridge = IsIvyBridge(adapterDesc.DeviceId);
2411     }
2412 
2413     if (isNvidia)
2414     {
2415         // TODO(jmadill): Narrow problematic driver range.
2416         bool driverVersionValid = deviceCaps.driverVersion.valid();
2417         if (driverVersionValid)
2418         {
2419             WORD part1 = HIWORD(deviceCaps.driverVersion.value().LowPart);
2420             WORD part2 = LOWORD(deviceCaps.driverVersion.value().LowPart);
2421 
2422             // Disable the workaround to fix a second driver bug on newer NVIDIA.
2423             ANGLE_FEATURE_CONDITION(
2424                 features, depthStencilBlitExtraCopy,
2425                 (part1 <= 13u && part2 < 6881) && isNvidia && driverVersionValid);
2426         }
2427         else
2428         {
2429             ANGLE_FEATURE_CONDITION(features, depthStencilBlitExtraCopy,
2430                                     isNvidia && !driverVersionValid);
2431         }
2432     }
2433 
2434     ANGLE_FEATURE_CONDITION(features, mrtPerfWorkaround, true);
2435     ANGLE_FEATURE_CONDITION(features, zeroMaxLodWorkaround, isFeatureLevel9_3);
2436     ANGLE_FEATURE_CONDITION(features, useInstancedPointSpriteEmulation, isFeatureLevel9_3);
2437 
2438     // TODO(jmadill): Disable workaround when we have a fixed compiler DLL.
2439     ANGLE_FEATURE_CONDITION(features, expandIntegerPowExpressions, true);
2440 
2441     ANGLE_FEATURE_CONDITION(features, flushAfterEndingTransformFeedback, isNvidia);
2442     ANGLE_FEATURE_CONDITION(features, getDimensionsIgnoresBaseLevel, isNvidia);
2443     ANGLE_FEATURE_CONDITION(features, skipVSConstantRegisterZero, isNvidia);
2444     ANGLE_FEATURE_CONDITION(features, forceAtomicValueResolution, isNvidia);
2445 
2446     ANGLE_FEATURE_CONDITION(features, preAddTexelFetchOffsets, isIntel);
2447     ANGLE_FEATURE_CONDITION(features, useSystemMemoryForConstantBuffers, isIntel);
2448 
2449     ANGLE_FEATURE_CONDITION(features, callClearTwice,
2450                             isIntel && isSkylake && capsVersion < IntelDriverVersion(4771));
2451     ANGLE_FEATURE_CONDITION(features, emulateIsnanFloat,
2452                             isIntel && isSkylake && capsVersion < IntelDriverVersion(4542));
2453     ANGLE_FEATURE_CONDITION(
2454         features, rewriteUnaryMinusOperator,
2455         isIntel && (isBroadwell || isHaswell) && capsVersion < IntelDriverVersion(4624));
2456 
2457     ANGLE_FEATURE_CONDITION(features, addMockTextureNoRenderTarget,
2458                             isIntel && capsVersion < IntelDriverVersion(4815));
2459 
2460     // Haswell/Ivybridge drivers occasionally corrupt (small?) (vertex?) texture data uploads.
2461     ANGLE_FEATURE_CONDITION(features, setDataFasterThanImageUpload,
2462                             !(isIvyBridge || isBroadwell || isHaswell));
2463 
2464     ANGLE_FEATURE_CONDITION(features, disableB5G6R5Support,
2465                             (isIntel && capsVersion < IntelDriverVersion(4539)) || isAMD);
2466 
2467     // TODO(jmadill): Disable when we have a fixed driver version.
2468     // The tiny stencil texture workaround involves using CopySubresource or UpdateSubresource on a
2469     // depth stencil texture.  This is not allowed until feature level 10.1 but since it is not
2470     // possible to support ES3 on these devices, there is no need for the workaround to begin with
2471     // (anglebug.com/1572).
2472     ANGLE_FEATURE_CONDITION(features, emulateTinyStencilTextures,
2473                             isAMD && !(deviceCaps.featureLevel < D3D_FEATURE_LEVEL_10_1));
2474 
2475     // If the VPAndRTArrayIndexFromAnyShaderFeedingRasterizer feature is not available, we have to
2476     // select the viewport / RT array index in the geometry shader.
2477     ANGLE_FEATURE_CONDITION(features, selectViewInGeometryShader,
2478                             !deviceCaps.supportsVpRtIndexWriteFromVertexShader);
2479 
2480     // NVidia drivers have no trouble clearing textures without showing corruption.
2481     // Intel and AMD drivers that have trouble have been blocklisted by Chromium. In the case of
2482     // Intel, they've been blocklisted to the DX9 runtime.
2483     ANGLE_FEATURE_CONDITION(features, allowClearForRobustResourceInit, true);
2484 
2485     // Allow translating uniform block to StructuredBuffer on Windows 10. This is targeted
2486     // to work around a slow fxc compile performance issue with dynamic uniform indexing.
2487     ANGLE_FEATURE_CONDITION(features, allowTranslateUniformBlockToStructuredBuffer,
2488                             IsWin10OrGreater());
2489 
2490     // Call platform hooks for testing overrides.
2491     auto *platform = ANGLEPlatformCurrent();
2492     platform->overrideWorkaroundsD3D(platform, features);
2493 }
2494 
InitConstantBufferDesc(D3D11_BUFFER_DESC * constantBufferDescription,size_t byteWidth)2495 void InitConstantBufferDesc(D3D11_BUFFER_DESC *constantBufferDescription, size_t byteWidth)
2496 {
2497     constantBufferDescription->ByteWidth           = static_cast<UINT>(byteWidth);
2498     constantBufferDescription->Usage               = D3D11_USAGE_DYNAMIC;
2499     constantBufferDescription->BindFlags           = D3D11_BIND_CONSTANT_BUFFER;
2500     constantBufferDescription->CPUAccessFlags      = D3D11_CPU_ACCESS_WRITE;
2501     constantBufferDescription->MiscFlags           = 0;
2502     constantBufferDescription->StructureByteStride = 0;
2503 }
2504 
2505 }  // namespace d3d11
2506 
2507 // TextureHelper11 implementation.
TextureHelper11()2508 TextureHelper11::TextureHelper11() : mFormatSet(nullptr), mSampleCount(0) {}
2509 
TextureHelper11(TextureHelper11 && toCopy)2510 TextureHelper11::TextureHelper11(TextureHelper11 &&toCopy) : TextureHelper11()
2511 {
2512     *this = std::move(toCopy);
2513 }
2514 
TextureHelper11(const TextureHelper11 & other)2515 TextureHelper11::TextureHelper11(const TextureHelper11 &other)
2516     : mFormatSet(other.mFormatSet), mExtents(other.mExtents), mSampleCount(other.mSampleCount)
2517 {
2518     mData = other.mData;
2519 }
2520 
~TextureHelper11()2521 TextureHelper11::~TextureHelper11() {}
2522 
getDesc(D3D11_TEXTURE2D_DESC * desc) const2523 void TextureHelper11::getDesc(D3D11_TEXTURE2D_DESC *desc) const
2524 {
2525     static_cast<ID3D11Texture2D *>(mData->object)->GetDesc(desc);
2526 }
2527 
getDesc(D3D11_TEXTURE3D_DESC * desc) const2528 void TextureHelper11::getDesc(D3D11_TEXTURE3D_DESC *desc) const
2529 {
2530     static_cast<ID3D11Texture3D *>(mData->object)->GetDesc(desc);
2531 }
2532 
initDesc(const D3D11_TEXTURE2D_DESC & desc2D)2533 void TextureHelper11::initDesc(const D3D11_TEXTURE2D_DESC &desc2D)
2534 {
2535     mData->resourceType = ResourceType::Texture2D;
2536     mExtents.width      = static_cast<int>(desc2D.Width);
2537     mExtents.height     = static_cast<int>(desc2D.Height);
2538     mExtents.depth      = 1;
2539     mSampleCount        = desc2D.SampleDesc.Count;
2540 }
2541 
initDesc(const D3D11_TEXTURE3D_DESC & desc3D)2542 void TextureHelper11::initDesc(const D3D11_TEXTURE3D_DESC &desc3D)
2543 {
2544     mData->resourceType = ResourceType::Texture3D;
2545     mExtents.width      = static_cast<int>(desc3D.Width);
2546     mExtents.height     = static_cast<int>(desc3D.Height);
2547     mExtents.depth      = static_cast<int>(desc3D.Depth);
2548     mSampleCount        = 1;
2549 }
2550 
operator =(TextureHelper11 && other)2551 TextureHelper11 &TextureHelper11::operator=(TextureHelper11 &&other)
2552 {
2553     std::swap(mData, other.mData);
2554     std::swap(mExtents, other.mExtents);
2555     std::swap(mFormatSet, other.mFormatSet);
2556     std::swap(mSampleCount, other.mSampleCount);
2557     return *this;
2558 }
2559 
operator =(const TextureHelper11 & other)2560 TextureHelper11 &TextureHelper11::operator=(const TextureHelper11 &other)
2561 {
2562     mData        = other.mData;
2563     mExtents     = other.mExtents;
2564     mFormatSet   = other.mFormatSet;
2565     mSampleCount = other.mSampleCount;
2566     return *this;
2567 }
2568 
operator ==(const TextureHelper11 & other) const2569 bool TextureHelper11::operator==(const TextureHelper11 &other) const
2570 {
2571     return mData->object == other.mData->object;
2572 }
2573 
operator !=(const TextureHelper11 & other) const2574 bool TextureHelper11::operator!=(const TextureHelper11 &other) const
2575 {
2576     return mData->object != other.mData->object;
2577 }
2578 
UsePresentPathFast(const Renderer11 * renderer,const gl::FramebufferAttachment * framebufferAttachment)2579 bool UsePresentPathFast(const Renderer11 *renderer,
2580                         const gl::FramebufferAttachment *framebufferAttachment)
2581 {
2582     if (framebufferAttachment == nullptr)
2583     {
2584         return false;
2585     }
2586 
2587     return (framebufferAttachment->type() == GL_FRAMEBUFFER_DEFAULT &&
2588             renderer->presentPathFastEnabled());
2589 }
2590 
UsePrimitiveRestartWorkaround(bool primitiveRestartFixedIndexEnabled,gl::DrawElementsType type)2591 bool UsePrimitiveRestartWorkaround(bool primitiveRestartFixedIndexEnabled,
2592                                    gl::DrawElementsType type)
2593 {
2594     // We should never have to deal with primitive restart workaround issue with GL_UNSIGNED_INT
2595     // indices, since we restrict it via MAX_ELEMENT_INDEX.
2596     return (!primitiveRestartFixedIndexEnabled && type == gl::DrawElementsType::UnsignedShort);
2597 }
2598 
ClassifyIndexStorage(const gl::State & glState,const gl::Buffer * elementArrayBuffer,gl::DrawElementsType elementType,gl::DrawElementsType destElementType,unsigned int offset)2599 IndexStorageType ClassifyIndexStorage(const gl::State &glState,
2600                                       const gl::Buffer *elementArrayBuffer,
2601                                       gl::DrawElementsType elementType,
2602                                       gl::DrawElementsType destElementType,
2603                                       unsigned int offset)
2604 {
2605     // No buffer bound means we are streaming from a client pointer.
2606     if (!elementArrayBuffer || !IsOffsetAligned(elementType, offset))
2607     {
2608         return IndexStorageType::Dynamic;
2609     }
2610 
2611     // The buffer can be used directly if the storage supports it and no translation needed.
2612     BufferD3D *bufferD3D = GetImplAs<BufferD3D>(elementArrayBuffer);
2613     if (bufferD3D->supportsDirectBinding() && destElementType == elementType)
2614     {
2615         return IndexStorageType::Direct;
2616     }
2617 
2618     // Use a static copy when available.
2619     StaticIndexBufferInterface *staticBuffer = bufferD3D->getStaticIndexBuffer();
2620     if (staticBuffer != nullptr)
2621     {
2622         return IndexStorageType::Static;
2623     }
2624 
2625     // Static buffer not available, fall back to streaming.
2626     return IndexStorageType::Dynamic;
2627 }
2628 }  // namespace rx
2629