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(const Renderer11DeviceCaps & caps)1295 gl::Version GetMaximumClientVersion(const Renderer11DeviceCaps &caps)
1296 {
1297     switch (caps.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             if (caps.allowES3OnFL10_0)
1307             {
1308                 return gl::Version(3, 0);
1309             }
1310             else
1311             {
1312                 return gl::Version(2, 0);
1313             }
1314         case D3D_FEATURE_LEVEL_9_3:
1315         case D3D_FEATURE_LEVEL_9_2:
1316         case D3D_FEATURE_LEVEL_9_1:
1317             return gl::Version(2, 0);
1318 
1319         default:
1320             UNREACHABLE();
1321             return gl::Version(0, 0);
1322     }
1323 }
1324 
GetMinimumFeatureLevelForES31()1325 D3D_FEATURE_LEVEL GetMinimumFeatureLevelForES31()
1326 {
1327     return kMinimumFeatureLevelForES31;
1328 }
1329 
GetMaxViewportAndScissorRectanglesPerPipeline(D3D_FEATURE_LEVEL featureLevel)1330 unsigned int GetMaxViewportAndScissorRectanglesPerPipeline(D3D_FEATURE_LEVEL featureLevel)
1331 {
1332     switch (featureLevel)
1333     {
1334         case D3D_FEATURE_LEVEL_11_1:
1335         case D3D_FEATURE_LEVEL_11_0:
1336             return D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE;
1337         case D3D_FEATURE_LEVEL_10_1:
1338         case D3D_FEATURE_LEVEL_10_0:
1339         case D3D_FEATURE_LEVEL_9_3:
1340         case D3D_FEATURE_LEVEL_9_2:
1341         case D3D_FEATURE_LEVEL_9_1:
1342             return 1;
1343         default:
1344             UNREACHABLE();
1345             return 0;
1346     }
1347 }
1348 
IsMultiviewSupported(D3D_FEATURE_LEVEL featureLevel)1349 bool IsMultiviewSupported(D3D_FEATURE_LEVEL featureLevel)
1350 {
1351     // The ANGLE_multiview extension can always be supported in D3D11 through geometry shaders.
1352     switch (featureLevel)
1353     {
1354         case D3D_FEATURE_LEVEL_11_1:
1355         case D3D_FEATURE_LEVEL_11_0:
1356             return true;
1357         default:
1358             return false;
1359     }
1360 }
1361 
GetMaxSampleMaskWords(D3D_FEATURE_LEVEL featureLevel)1362 int GetMaxSampleMaskWords(D3D_FEATURE_LEVEL featureLevel)
1363 {
1364     switch (featureLevel)
1365     {
1366         // D3D10+ only allows 1 sample mask.
1367         case D3D_FEATURE_LEVEL_11_1:
1368         case D3D_FEATURE_LEVEL_11_0:
1369         case D3D_FEATURE_LEVEL_10_1:
1370         case D3D_FEATURE_LEVEL_10_0:
1371             return 1;
1372         case D3D_FEATURE_LEVEL_9_3:
1373         case D3D_FEATURE_LEVEL_9_2:
1374         case D3D_FEATURE_LEVEL_9_1:
1375             return 0;
1376         default:
1377             UNREACHABLE();
1378             return 0;
1379     }
1380 }
1381 
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)1382 void GenerateCaps(ID3D11Device *device,
1383                   ID3D11DeviceContext *deviceContext,
1384                   const Renderer11DeviceCaps &renderer11DeviceCaps,
1385                   const angle::FeaturesD3D &features,
1386                   const char *description,
1387                   gl::Caps *caps,
1388                   gl::TextureCapsMap *textureCapsMap,
1389                   gl::Extensions *extensions,
1390                   gl::Limitations *limitations)
1391 {
1392     D3D_FEATURE_LEVEL featureLevel  = renderer11DeviceCaps.featureLevel;
1393     const gl::FormatSet &allFormats = gl::GetAllSizedInternalFormats();
1394     for (GLenum internalFormat : allFormats)
1395     {
1396         gl::TextureCaps textureCaps =
1397             GenerateTextureFormatCaps(GetMaximumClientVersion(renderer11DeviceCaps), internalFormat,
1398                                       device, renderer11DeviceCaps);
1399         textureCapsMap->insert(internalFormat, textureCaps);
1400 
1401         if (gl::GetSizedInternalFormatInfo(internalFormat).compressed)
1402         {
1403             caps->compressedTextureFormats.push_back(internalFormat);
1404         }
1405     }
1406 
1407     // GL core feature limits
1408     // Reserve MAX_UINT for D3D11's primitive restart.
1409     caps->maxElementIndex  = static_cast<GLint64>(std::numeric_limits<unsigned int>::max() - 1);
1410     caps->max3DTextureSize = GetMaximum3DTextureSize(featureLevel);
1411     caps->max2DTextureSize = GetMaximum2DTextureSize(featureLevel);
1412     caps->maxCubeMapTextureSize = GetMaximumCubeMapTextureSize(featureLevel);
1413     caps->maxArrayTextureLayers = GetMaximum2DTextureArraySize(featureLevel);
1414 
1415     // Unimplemented, set to minimum required
1416     caps->maxLODBias = 2.0f;
1417 
1418     // No specific limits on render target size, maximum 2D texture size is equivalent
1419     caps->maxRenderbufferSize = caps->max2DTextureSize;
1420 
1421     // Maximum draw buffers and color attachments are the same, max color attachments could
1422     // eventually be increased to 16
1423     caps->maxDrawBuffers      = GetMaximumSimultaneousRenderTargets(featureLevel);
1424     caps->maxColorAttachments = GetMaximumSimultaneousRenderTargets(featureLevel);
1425 
1426     // D3D11 has the same limit for viewport width and height
1427     caps->maxViewportWidth  = GetMaximumViewportSize(featureLevel);
1428     caps->maxViewportHeight = caps->maxViewportWidth;
1429 
1430     // Choose a reasonable maximum, enforced in the shader.
1431     caps->minAliasedPointSize = 1.0f;
1432     caps->maxAliasedPointSize = 1024.0f;
1433 
1434     // Wide lines not supported
1435     caps->minAliasedLineWidth = 1.0f;
1436     caps->maxAliasedLineWidth = 1.0f;
1437 
1438     // Primitive count limits
1439     caps->maxElementsIndices  = GetMaximumDrawIndexedIndexCount(featureLevel);
1440     caps->maxElementsVertices = GetMaximumDrawVertexCount(featureLevel);
1441 
1442     // Program and shader binary formats (no supported shader binary formats)
1443     caps->programBinaryFormats.push_back(GL_PROGRAM_BINARY_ANGLE);
1444 
1445     caps->vertexHighpFloat.setIEEEFloat();
1446     caps->vertexMediumpFloat.setIEEEFloat();
1447     caps->vertexLowpFloat.setIEEEFloat();
1448     caps->fragmentHighpFloat.setIEEEFloat();
1449     caps->fragmentMediumpFloat.setIEEEFloat();
1450     caps->fragmentLowpFloat.setIEEEFloat();
1451 
1452     // 32-bit integers are natively supported
1453     caps->vertexHighpInt.setTwosComplementInt(32);
1454     caps->vertexMediumpInt.setTwosComplementInt(32);
1455     caps->vertexLowpInt.setTwosComplementInt(32);
1456     caps->fragmentHighpInt.setTwosComplementInt(32);
1457     caps->fragmentMediumpInt.setTwosComplementInt(32);
1458     caps->fragmentLowpInt.setTwosComplementInt(32);
1459 
1460     // We do not wait for server fence objects internally, so report a max timeout of zero.
1461     caps->maxServerWaitTimeout = 0;
1462 
1463     // Vertex shader limits
1464     caps->maxVertexAttributes     = GetMaximumVertexInputSlots(featureLevel);
1465     caps->maxVertexUniformVectors = GetMaximumVertexUniformVectors(featureLevel);
1466     if (features.skipVSConstantRegisterZero.enabled)
1467     {
1468         caps->maxVertexUniformVectors -= 1;
1469     }
1470     caps->maxShaderUniformComponents[gl::ShaderType::Vertex] = caps->maxVertexUniformVectors * 4;
1471     caps->maxShaderUniformBlocks[gl::ShaderType::Vertex] =
1472         GetMaximumVertexUniformBlocks(featureLevel);
1473     caps->maxVertexOutputComponents = GetMaximumVertexOutputVectors(featureLevel) * 4;
1474     caps->maxShaderTextureImageUnits[gl::ShaderType::Vertex] =
1475         GetMaximumVertexTextureUnits(featureLevel);
1476 
1477     // Vertex Attribute Bindings are emulated on D3D11.
1478     caps->maxVertexAttribBindings = caps->maxVertexAttributes;
1479     // Experimental testing confirmed there is no explicit limit on maximum buffer offset in D3D11.
1480     caps->maxVertexAttribRelativeOffset = std::numeric_limits<GLint>::max();
1481     // Experimental testing confirmed 2048 is the maximum stride that D3D11 can support on all
1482     // platforms.
1483     caps->maxVertexAttribStride = 2048;
1484 
1485     // Fragment shader limits
1486     caps->maxFragmentUniformVectors = GetMaximumPixelUniformVectors(featureLevel);
1487     caps->maxShaderUniformComponents[gl::ShaderType::Fragment] =
1488         caps->maxFragmentUniformVectors * 4;
1489     caps->maxShaderUniformBlocks[gl::ShaderType::Fragment] =
1490         GetMaximumPixelUniformBlocks(featureLevel);
1491     caps->maxFragmentInputComponents = GetMaximumPixelInputVectors(featureLevel) * 4;
1492     caps->maxShaderTextureImageUnits[gl::ShaderType::Fragment] =
1493         GetMaximumPixelTextureUnits(featureLevel);
1494     caps->minProgramTexelOffset = GetMinimumTexelOffset(featureLevel);
1495     caps->maxProgramTexelOffset = GetMaximumTexelOffset(featureLevel);
1496 
1497     // Compute shader limits
1498     caps->maxComputeWorkGroupCount       = GetMaxComputeWorkGroupCount(featureLevel);
1499     caps->maxComputeWorkGroupSize        = GetMaxComputeWorkGroupSize(featureLevel);
1500     caps->maxComputeWorkGroupInvocations = GetMaxComputeWorkGroupInvocations(featureLevel);
1501     caps->maxComputeSharedMemorySize     = GetMaxComputeSharedMemorySize(featureLevel);
1502     caps->maxShaderUniformComponents[gl::ShaderType::Compute] =
1503         GetMaximumComputeUniformVectors(featureLevel) * 4;
1504     caps->maxShaderUniformBlocks[gl::ShaderType::Compute] =
1505         GetMaximumComputeUniformBlocks(featureLevel);
1506     caps->maxShaderTextureImageUnits[gl::ShaderType::Compute] =
1507         GetMaximumComputeTextureUnits(featureLevel);
1508 
1509     SetUAVRelatedResourceLimits(featureLevel, caps);
1510 
1511     // Aggregate shader limits
1512     caps->maxUniformBufferBindings = caps->maxShaderUniformBlocks[gl::ShaderType::Vertex] +
1513                                      caps->maxShaderUniformBlocks[gl::ShaderType::Fragment];
1514     caps->maxUniformBlockSize = static_cast<GLuint64>(GetMaximumConstantBufferSize(featureLevel));
1515 
1516     // TODO(oetuaho): Get a more accurate limit. For now using the minimum requirement for GLES 3.1.
1517     caps->maxUniformLocations = 1024;
1518 
1519     // With DirectX 11.1, constant buffer offset and size must be a multiple of 16 constants of 16
1520     // bytes each.
1521     // https://msdn.microsoft.com/en-us/library/windows/desktop/hh404649%28v=vs.85%29.aspx
1522     // With DirectX 11.0, we emulate UBO offsets using copies of ranges of the UBO however
1523     // we still keep the same alignment as 11.1 for consistency.
1524     caps->uniformBufferOffsetAlignment = 256;
1525 
1526     caps->maxCombinedUniformBlocks = caps->maxShaderUniformBlocks[gl::ShaderType::Vertex] +
1527                                      caps->maxShaderUniformBlocks[gl::ShaderType::Fragment];
1528 
1529     // A shader storage block will be translated to a structure in HLSL. So We reference the HLSL
1530     // structure packing rules
1531     // https://msdn.microsoft.com/en-us/library/windows/desktop/bb509632(v=vs.85).aspx. The
1532     // resulting size of any structure will always be evenly divisible by sizeof(four-component
1533     // vector).
1534     caps->shaderStorageBufferOffsetAlignment = 16;
1535 
1536     for (gl::ShaderType shaderType : gl::AllShaderTypes())
1537     {
1538         caps->maxCombinedShaderUniformComponents[shaderType] =
1539             static_cast<GLint64>(caps->maxShaderUniformBlocks[shaderType]) *
1540                 static_cast<GLint64>(caps->maxUniformBlockSize / 4) +
1541             static_cast<GLint64>(caps->maxShaderUniformComponents[shaderType]);
1542     }
1543 
1544     caps->maxVaryingComponents         = GetMaximumVertexOutputVectors(featureLevel) * 4;
1545     caps->maxVaryingVectors            = GetMaximumVertexOutputVectors(featureLevel);
1546     caps->maxCombinedTextureImageUnits = caps->maxShaderTextureImageUnits[gl::ShaderType::Vertex] +
1547                                          caps->maxShaderTextureImageUnits[gl::ShaderType::Fragment];
1548 
1549     // Transform feedback limits
1550     caps->maxTransformFeedbackInterleavedComponents =
1551         GetMaximumStreamOutputInterleavedComponents(featureLevel);
1552     caps->maxTransformFeedbackSeparateAttributes = GetMaximumStreamOutputBuffers(featureLevel);
1553     caps->maxTransformFeedbackSeparateComponents =
1554         GetMaximumStreamOutputSeparateComponents(featureLevel);
1555 
1556     // Defer the computation of multisample limits to Context::updateCaps() where max*Samples values
1557     // are determined according to available sample counts for each individual format.
1558     caps->maxSamples             = std::numeric_limits<GLint>::max();
1559     caps->maxColorTextureSamples = std::numeric_limits<GLint>::max();
1560     caps->maxDepthTextureSamples = std::numeric_limits<GLint>::max();
1561     caps->maxIntegerSamples      = std::numeric_limits<GLint>::max();
1562 
1563     // Sample mask words limits
1564     caps->maxSampleMaskWords = GetMaxSampleMaskWords(featureLevel);
1565 
1566     // Framebuffer limits
1567     caps->maxFramebufferSamples = std::numeric_limits<GLint>::max();
1568     caps->maxFramebufferWidth   = GetMaximumRenderToBufferWindowSize(featureLevel);
1569     caps->maxFramebufferHeight  = caps->maxFramebufferWidth;
1570 
1571     // Texture gather offset limits
1572     caps->minProgramTextureGatherOffset = GetMinimumTextureGatherOffset(featureLevel);
1573     caps->maxProgramTextureGatherOffset = GetMaximumTextureGatherOffset(featureLevel);
1574 
1575     // GL extension support
1576     extensions->setTextureExtensionSupport(*textureCapsMap);
1577 
1578     // Explicitly disable GL_OES_compressed_ETC1_RGB8_texture because it's emulated and never
1579     // becomes core. WebGL doesn't want to expose it unless there is native support.
1580     extensions->compressedETC1RGB8TextureOES = false;
1581     extensions->compressedETC1RGB8SubTexture = false;
1582 
1583     extensions->elementIndexUintOES = true;
1584     extensions->getProgramBinaryOES = true;
1585     extensions->rgb8rgba8OES        = true;
1586     extensions->readFormatBGRA      = true;
1587     extensions->pixelBufferObjectNV = true;
1588     extensions->mapBufferOES        = true;
1589     extensions->mapBufferRange      = true;
1590     extensions->textureNPOTOES      = GetNPOTTextureSupport(featureLevel);
1591     extensions->drawBuffers         = GetMaximumSimultaneousRenderTargets(featureLevel) > 1;
1592     extensions->drawBuffersIndexedEXT =
1593         (renderer11DeviceCaps.featureLevel >= D3D_FEATURE_LEVEL_10_1);
1594     extensions->drawBuffersIndexedOES       = extensions->drawBuffersIndexedEXT;
1595     extensions->textureStorage              = true;
1596     extensions->textureFilterAnisotropic    = true;
1597     extensions->maxTextureAnisotropy        = GetMaximumAnisotropy(featureLevel);
1598     extensions->occlusionQueryBoolean       = GetOcclusionQuerySupport(featureLevel);
1599     extensions->fenceNV                     = GetEventQuerySupport(featureLevel);
1600     extensions->disjointTimerQuery          = true;
1601     extensions->queryCounterBitsTimeElapsed = 64;
1602     extensions->queryCounterBitsTimestamp =
1603         0;  // Timestamps cannot be supported due to D3D11 limitations
1604     extensions->robustness = true;
1605     // Direct3D guarantees to return zero for any resource that is accessed out of bounds.
1606     // See https://msdn.microsoft.com/en-us/library/windows/desktop/ff476332(v=vs.85).aspx
1607     // and https://msdn.microsoft.com/en-us/library/windows/desktop/ff476900(v=vs.85).aspx
1608     extensions->robustBufferAccessBehavior = true;
1609     extensions->blendMinMax                = true;
1610     // https://docs.microsoft.com/en-us/windows/desktop/direct3ddxgi/format-support-for-direct3d-11-0-feature-level-hardware
1611     extensions->floatBlend             = true;
1612     extensions->framebufferBlitANGLE   = GetFramebufferBlitSupport(featureLevel);
1613     extensions->framebufferMultisample = GetFramebufferMultisampleSupport(featureLevel);
1614     extensions->instancedArraysANGLE   = GetInstancingSupport(featureLevel);
1615     extensions->instancedArraysEXT     = GetInstancingSupport(featureLevel);
1616     extensions->packReverseRowOrder    = true;
1617     extensions->standardDerivativesOES = GetDerivativeInstructionSupport(featureLevel);
1618     extensions->shaderTextureLOD       = GetShaderTextureLODSupport(featureLevel);
1619     extensions->fragDepth              = true;
1620     extensions->multiview              = IsMultiviewSupported(featureLevel);
1621     extensions->multiview2             = IsMultiviewSupported(featureLevel);
1622     if (extensions->multiview || extensions->multiview2)
1623     {
1624         extensions->maxViews =
1625             std::min(static_cast<GLuint>(gl::IMPLEMENTATION_ANGLE_MULTIVIEW_MAX_VIEWS),
1626                      std::min(static_cast<GLuint>(GetMaximum2DTextureArraySize(featureLevel)),
1627                               GetMaxViewportAndScissorRectanglesPerPipeline(featureLevel)));
1628     }
1629     extensions->textureUsage       = true;  // This could be false since it has no effect in D3D11
1630     extensions->discardFramebuffer = true;
1631     extensions->translatedShaderSource              = true;
1632     extensions->fboRenderMipmapOES                  = true;
1633     extensions->debugMarker                         = true;
1634     extensions->eglImageOES                         = true;
1635     extensions->eglImageExternalOES                 = true;
1636     extensions->eglImageExternalWrapModesEXT        = true;
1637     extensions->eglImageExternalEssl3OES            = true;
1638     extensions->eglStreamConsumerExternalNV         = true;
1639     extensions->unpackSubimage                      = true;
1640     extensions->packSubimage                        = true;
1641     extensions->lossyETCDecode                      = true;
1642     extensions->syncQuery                           = GetEventQuerySupport(featureLevel);
1643     extensions->copyTexture                         = true;
1644     extensions->copyCompressedTexture               = true;
1645     extensions->textureStorageMultisample2DArrayOES = true;
1646     extensions->multiviewMultisample     = ((extensions->multiview || extensions->multiview2) &&
1647                                         extensions->textureStorageMultisample2DArrayOES);
1648     extensions->copyTexture3d            = true;
1649     extensions->textureBorderClampOES    = true;
1650     extensions->textureMultisample       = true;
1651     extensions->provokingVertex          = true;
1652     extensions->blendFuncExtended        = true;
1653     extensions->maxDualSourceDrawBuffers = 1;
1654     // http://anglebug.com/4926
1655     extensions->texture3DOES              = false;
1656     extensions->baseVertexBaseInstance    = true;
1657     extensions->drawElementsBaseVertexOES = true;
1658     extensions->drawElementsBaseVertexEXT = true;
1659     if (!strstr(description, "Adreno"))
1660     {
1661         extensions->multisampledRenderToTexture = true;
1662     }
1663     extensions->webglVideoTexture = true;
1664 
1665     // D3D11 cannot support reading depth texture as a luminance texture.
1666     // It treats it as a red-channel-only texture.
1667     extensions->depthTextureOES = false;
1668 
1669     // readPixels on depth & stencil not working with D3D11 backend.
1670     extensions->readDepthNV         = false;
1671     extensions->readStencilNV       = false;
1672     extensions->depthBufferFloat2NV = false;
1673 
1674     // D3D11 Feature Level 10_0+ uses SV_IsFrontFace in HLSL to emulate gl_FrontFacing.
1675     // D3D11 Feature Level 9_3 doesn't support SV_IsFrontFace, and has no equivalent, so can't
1676     // support gl_FrontFacing.
1677     limitations->noFrontFacingSupport =
1678         (renderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3);
1679 
1680     // D3D11 Feature Level 9_3 doesn't support alpha-to-coverage
1681     limitations->noSampleAlphaToCoverageSupport =
1682         (renderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3);
1683 
1684     // D3D11 Feature Levels 9_3 and below do not support non-constant loop indexing and require
1685     // additional
1686     // pre-validation of the shader at compile time to produce a better error message.
1687     limitations->shadersRequireIndexedLoopValidation =
1688         (renderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3);
1689 
1690     // D3D11 has no concept of separate masks and refs for front and back faces in the depth stencil
1691     // state.
1692     limitations->noSeparateStencilRefsAndMasks = true;
1693 
1694     // D3D11 cannot support constant color and alpha blend funcs together
1695     limitations->noSimultaneousConstantColorAndAlphaBlendFunc = true;
1696 
1697     // D3D11 does not support multiple transform feedback outputs writing to the same buffer.
1698     limitations->noDoubleBoundTransformFeedbackBuffers = true;
1699 
1700     // D3D11 does not support vertex attribute aliasing
1701     limitations->noVertexAttributeAliasing = true;
1702 
1703 #ifdef ANGLE_ENABLE_WINDOWS_UWP
1704     // Setting a non-zero divisor on attribute zero doesn't work on certain Windows Phone 8-era
1705     // devices. We should prevent developers from doing this on ALL Windows Store devices. This will
1706     // maintain consistency across all Windows devices. We allow non-zero divisors on attribute zero
1707     // if the Client Version >= 3, since devices affected by this issue don't support ES3+.
1708     limitations->attributeZeroRequiresZeroDivisorInEXT = true;
1709 #endif
1710 }
1711 
1712 }  // namespace d3d11_gl
1713 
1714 namespace gl_d3d11
1715 {
1716 
ConvertBlendFunc(GLenum glBlend,bool isAlpha)1717 D3D11_BLEND ConvertBlendFunc(GLenum glBlend, bool isAlpha)
1718 {
1719     D3D11_BLEND d3dBlend = D3D11_BLEND_ZERO;
1720 
1721     switch (glBlend)
1722     {
1723         case GL_ZERO:
1724             d3dBlend = D3D11_BLEND_ZERO;
1725             break;
1726         case GL_ONE:
1727             d3dBlend = D3D11_BLEND_ONE;
1728             break;
1729         case GL_SRC_COLOR:
1730             d3dBlend = (isAlpha ? D3D11_BLEND_SRC_ALPHA : D3D11_BLEND_SRC_COLOR);
1731             break;
1732         case GL_ONE_MINUS_SRC_COLOR:
1733             d3dBlend = (isAlpha ? D3D11_BLEND_INV_SRC_ALPHA : D3D11_BLEND_INV_SRC_COLOR);
1734             break;
1735         case GL_DST_COLOR:
1736             d3dBlend = (isAlpha ? D3D11_BLEND_DEST_ALPHA : D3D11_BLEND_DEST_COLOR);
1737             break;
1738         case GL_ONE_MINUS_DST_COLOR:
1739             d3dBlend = (isAlpha ? D3D11_BLEND_INV_DEST_ALPHA : D3D11_BLEND_INV_DEST_COLOR);
1740             break;
1741         case GL_SRC_ALPHA:
1742             d3dBlend = D3D11_BLEND_SRC_ALPHA;
1743             break;
1744         case GL_ONE_MINUS_SRC_ALPHA:
1745             d3dBlend = D3D11_BLEND_INV_SRC_ALPHA;
1746             break;
1747         case GL_DST_ALPHA:
1748             d3dBlend = D3D11_BLEND_DEST_ALPHA;
1749             break;
1750         case GL_ONE_MINUS_DST_ALPHA:
1751             d3dBlend = D3D11_BLEND_INV_DEST_ALPHA;
1752             break;
1753         case GL_CONSTANT_COLOR:
1754             d3dBlend = D3D11_BLEND_BLEND_FACTOR;
1755             break;
1756         case GL_ONE_MINUS_CONSTANT_COLOR:
1757             d3dBlend = D3D11_BLEND_INV_BLEND_FACTOR;
1758             break;
1759         case GL_CONSTANT_ALPHA:
1760             d3dBlend = D3D11_BLEND_BLEND_FACTOR;
1761             break;
1762         case GL_ONE_MINUS_CONSTANT_ALPHA:
1763             d3dBlend = D3D11_BLEND_INV_BLEND_FACTOR;
1764             break;
1765         case GL_SRC_ALPHA_SATURATE:
1766             d3dBlend = D3D11_BLEND_SRC_ALPHA_SAT;
1767             break;
1768         case GL_SRC1_COLOR_EXT:
1769             d3dBlend = (isAlpha ? D3D11_BLEND_SRC1_ALPHA : D3D11_BLEND_SRC1_COLOR);
1770             break;
1771         case GL_SRC1_ALPHA_EXT:
1772             d3dBlend = D3D11_BLEND_SRC1_ALPHA;
1773             break;
1774         case GL_ONE_MINUS_SRC1_COLOR_EXT:
1775             d3dBlend = (isAlpha ? D3D11_BLEND_INV_SRC1_ALPHA : D3D11_BLEND_INV_SRC1_COLOR);
1776             break;
1777         case GL_ONE_MINUS_SRC1_ALPHA_EXT:
1778             d3dBlend = D3D11_BLEND_INV_SRC1_ALPHA;
1779             break;
1780         default:
1781             UNREACHABLE();
1782     }
1783 
1784     return d3dBlend;
1785 }
1786 
ConvertBlendOp(GLenum glBlendOp)1787 D3D11_BLEND_OP ConvertBlendOp(GLenum glBlendOp)
1788 {
1789     D3D11_BLEND_OP d3dBlendOp = D3D11_BLEND_OP_ADD;
1790 
1791     switch (glBlendOp)
1792     {
1793         case GL_FUNC_ADD:
1794             d3dBlendOp = D3D11_BLEND_OP_ADD;
1795             break;
1796         case GL_FUNC_SUBTRACT:
1797             d3dBlendOp = D3D11_BLEND_OP_SUBTRACT;
1798             break;
1799         case GL_FUNC_REVERSE_SUBTRACT:
1800             d3dBlendOp = D3D11_BLEND_OP_REV_SUBTRACT;
1801             break;
1802         case GL_MIN:
1803             d3dBlendOp = D3D11_BLEND_OP_MIN;
1804             break;
1805         case GL_MAX:
1806             d3dBlendOp = D3D11_BLEND_OP_MAX;
1807             break;
1808         default:
1809             UNREACHABLE();
1810     }
1811 
1812     return d3dBlendOp;
1813 }
1814 
ConvertColorMask(bool red,bool green,bool blue,bool alpha)1815 UINT8 ConvertColorMask(bool red, bool green, bool blue, bool alpha)
1816 {
1817     UINT8 mask = 0;
1818     if (red)
1819     {
1820         mask |= D3D11_COLOR_WRITE_ENABLE_RED;
1821     }
1822     if (green)
1823     {
1824         mask |= D3D11_COLOR_WRITE_ENABLE_GREEN;
1825     }
1826     if (blue)
1827     {
1828         mask |= D3D11_COLOR_WRITE_ENABLE_BLUE;
1829     }
1830     if (alpha)
1831     {
1832         mask |= D3D11_COLOR_WRITE_ENABLE_ALPHA;
1833     }
1834     return mask;
1835 }
1836 
ConvertCullMode(bool cullEnabled,gl::CullFaceMode cullMode)1837 D3D11_CULL_MODE ConvertCullMode(bool cullEnabled, gl::CullFaceMode cullMode)
1838 {
1839     D3D11_CULL_MODE cull = D3D11_CULL_NONE;
1840 
1841     if (cullEnabled)
1842     {
1843         switch (cullMode)
1844         {
1845             case gl::CullFaceMode::Front:
1846                 cull = D3D11_CULL_FRONT;
1847                 break;
1848             case gl::CullFaceMode::Back:
1849                 cull = D3D11_CULL_BACK;
1850                 break;
1851             case gl::CullFaceMode::FrontAndBack:
1852                 cull = D3D11_CULL_NONE;
1853                 break;
1854             default:
1855                 UNREACHABLE();
1856         }
1857     }
1858     else
1859     {
1860         cull = D3D11_CULL_NONE;
1861     }
1862 
1863     return cull;
1864 }
1865 
ConvertComparison(GLenum comparison)1866 D3D11_COMPARISON_FUNC ConvertComparison(GLenum comparison)
1867 {
1868     D3D11_COMPARISON_FUNC d3dComp = D3D11_COMPARISON_NEVER;
1869     switch (comparison)
1870     {
1871         case GL_NEVER:
1872             d3dComp = D3D11_COMPARISON_NEVER;
1873             break;
1874         case GL_ALWAYS:
1875             d3dComp = D3D11_COMPARISON_ALWAYS;
1876             break;
1877         case GL_LESS:
1878             d3dComp = D3D11_COMPARISON_LESS;
1879             break;
1880         case GL_LEQUAL:
1881             d3dComp = D3D11_COMPARISON_LESS_EQUAL;
1882             break;
1883         case GL_EQUAL:
1884             d3dComp = D3D11_COMPARISON_EQUAL;
1885             break;
1886         case GL_GREATER:
1887             d3dComp = D3D11_COMPARISON_GREATER;
1888             break;
1889         case GL_GEQUAL:
1890             d3dComp = D3D11_COMPARISON_GREATER_EQUAL;
1891             break;
1892         case GL_NOTEQUAL:
1893             d3dComp = D3D11_COMPARISON_NOT_EQUAL;
1894             break;
1895         default:
1896             UNREACHABLE();
1897     }
1898 
1899     return d3dComp;
1900 }
1901 
ConvertDepthMask(bool depthWriteEnabled)1902 D3D11_DEPTH_WRITE_MASK ConvertDepthMask(bool depthWriteEnabled)
1903 {
1904     return depthWriteEnabled ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO;
1905 }
1906 
ConvertStencilMask(GLuint stencilmask)1907 UINT8 ConvertStencilMask(GLuint stencilmask)
1908 {
1909     return static_cast<UINT8>(stencilmask);
1910 }
1911 
ConvertStencilOp(GLenum stencilOp)1912 D3D11_STENCIL_OP ConvertStencilOp(GLenum stencilOp)
1913 {
1914     D3D11_STENCIL_OP d3dStencilOp = D3D11_STENCIL_OP_KEEP;
1915 
1916     switch (stencilOp)
1917     {
1918         case GL_ZERO:
1919             d3dStencilOp = D3D11_STENCIL_OP_ZERO;
1920             break;
1921         case GL_KEEP:
1922             d3dStencilOp = D3D11_STENCIL_OP_KEEP;
1923             break;
1924         case GL_REPLACE:
1925             d3dStencilOp = D3D11_STENCIL_OP_REPLACE;
1926             break;
1927         case GL_INCR:
1928             d3dStencilOp = D3D11_STENCIL_OP_INCR_SAT;
1929             break;
1930         case GL_DECR:
1931             d3dStencilOp = D3D11_STENCIL_OP_DECR_SAT;
1932             break;
1933         case GL_INVERT:
1934             d3dStencilOp = D3D11_STENCIL_OP_INVERT;
1935             break;
1936         case GL_INCR_WRAP:
1937             d3dStencilOp = D3D11_STENCIL_OP_INCR;
1938             break;
1939         case GL_DECR_WRAP:
1940             d3dStencilOp = D3D11_STENCIL_OP_DECR;
1941             break;
1942         default:
1943             UNREACHABLE();
1944     }
1945 
1946     return d3dStencilOp;
1947 }
1948 
ConvertFilter(GLenum minFilter,GLenum magFilter,float maxAnisotropy,GLenum comparisonMode)1949 D3D11_FILTER ConvertFilter(GLenum minFilter,
1950                            GLenum magFilter,
1951                            float maxAnisotropy,
1952                            GLenum comparisonMode)
1953 {
1954     bool comparison = comparisonMode != GL_NONE;
1955 
1956     if (maxAnisotropy > 1.0f)
1957     {
1958         return D3D11_ENCODE_ANISOTROPIC_FILTER(static_cast<D3D11_COMPARISON_FUNC>(comparison));
1959     }
1960     else
1961     {
1962         D3D11_FILTER_TYPE dxMin = D3D11_FILTER_TYPE_POINT;
1963         D3D11_FILTER_TYPE dxMip = D3D11_FILTER_TYPE_POINT;
1964         switch (minFilter)
1965         {
1966             case GL_NEAREST:
1967                 dxMin = D3D11_FILTER_TYPE_POINT;
1968                 dxMip = D3D11_FILTER_TYPE_POINT;
1969                 break;
1970             case GL_LINEAR:
1971                 dxMin = D3D11_FILTER_TYPE_LINEAR;
1972                 dxMip = D3D11_FILTER_TYPE_POINT;
1973                 break;
1974             case GL_NEAREST_MIPMAP_NEAREST:
1975                 dxMin = D3D11_FILTER_TYPE_POINT;
1976                 dxMip = D3D11_FILTER_TYPE_POINT;
1977                 break;
1978             case GL_LINEAR_MIPMAP_NEAREST:
1979                 dxMin = D3D11_FILTER_TYPE_LINEAR;
1980                 dxMip = D3D11_FILTER_TYPE_POINT;
1981                 break;
1982             case GL_NEAREST_MIPMAP_LINEAR:
1983                 dxMin = D3D11_FILTER_TYPE_POINT;
1984                 dxMip = D3D11_FILTER_TYPE_LINEAR;
1985                 break;
1986             case GL_LINEAR_MIPMAP_LINEAR:
1987                 dxMin = D3D11_FILTER_TYPE_LINEAR;
1988                 dxMip = D3D11_FILTER_TYPE_LINEAR;
1989                 break;
1990             default:
1991                 UNREACHABLE();
1992         }
1993 
1994         D3D11_FILTER_TYPE dxMag = D3D11_FILTER_TYPE_POINT;
1995         switch (magFilter)
1996         {
1997             case GL_NEAREST:
1998                 dxMag = D3D11_FILTER_TYPE_POINT;
1999                 break;
2000             case GL_LINEAR:
2001                 dxMag = D3D11_FILTER_TYPE_LINEAR;
2002                 break;
2003             default:
2004                 UNREACHABLE();
2005         }
2006 
2007         return D3D11_ENCODE_BASIC_FILTER(dxMin, dxMag, dxMip,
2008                                          static_cast<D3D11_COMPARISON_FUNC>(comparison));
2009     }
2010 }
2011 
ConvertTextureWrap(GLenum wrap)2012 D3D11_TEXTURE_ADDRESS_MODE ConvertTextureWrap(GLenum wrap)
2013 {
2014     switch (wrap)
2015     {
2016         case GL_REPEAT:
2017             return D3D11_TEXTURE_ADDRESS_WRAP;
2018         case GL_CLAMP_TO_EDGE:
2019             return D3D11_TEXTURE_ADDRESS_CLAMP;
2020         case GL_CLAMP_TO_BORDER:
2021             return D3D11_TEXTURE_ADDRESS_BORDER;
2022         case GL_MIRRORED_REPEAT:
2023             return D3D11_TEXTURE_ADDRESS_MIRROR;
2024         default:
2025             UNREACHABLE();
2026     }
2027 
2028     return D3D11_TEXTURE_ADDRESS_WRAP;
2029 }
2030 
ConvertMaxAnisotropy(float maxAnisotropy,D3D_FEATURE_LEVEL featureLevel)2031 UINT ConvertMaxAnisotropy(float maxAnisotropy, D3D_FEATURE_LEVEL featureLevel)
2032 {
2033     return static_cast<UINT>(std::min(maxAnisotropy, d3d11_gl::GetMaximumAnisotropy(featureLevel)));
2034 }
2035 
ConvertQueryType(gl::QueryType type)2036 D3D11_QUERY ConvertQueryType(gl::QueryType type)
2037 {
2038     switch (type)
2039     {
2040         case gl::QueryType::AnySamples:
2041         case gl::QueryType::AnySamplesConservative:
2042             return D3D11_QUERY_OCCLUSION;
2043         case gl::QueryType::TransformFeedbackPrimitivesWritten:
2044             return D3D11_QUERY_SO_STATISTICS;
2045         case gl::QueryType::TimeElapsed:
2046             // Two internal queries are also created for begin/end timestamps
2047             return D3D11_QUERY_TIMESTAMP_DISJOINT;
2048         case gl::QueryType::CommandsCompleted:
2049             return D3D11_QUERY_EVENT;
2050         default:
2051             UNREACHABLE();
2052             return D3D11_QUERY_EVENT;
2053     }
2054 }
2055 
2056 // Get the D3D11 write mask covering all color channels of a given format
GetColorMask(const gl::InternalFormat & format)2057 UINT8 GetColorMask(const gl::InternalFormat &format)
2058 {
2059     return ConvertColorMask(format.redBits > 0, format.greenBits > 0, format.blueBits > 0,
2060                             format.alphaBits > 0);
2061 }
2062 
2063 }  // namespace gl_d3d11
2064 
2065 namespace d3d11
2066 {
2067 
GetDeviceType(ID3D11Device * device)2068 ANGLED3D11DeviceType GetDeviceType(ID3D11Device *device)
2069 {
2070     // Note that this function returns an ANGLED3D11DeviceType rather than a D3D_DRIVER_TYPE value,
2071     // since it is difficult to tell Software and Reference devices apart
2072 
2073     IDXGIDevice *dxgiDevice     = nullptr;
2074     IDXGIAdapter *dxgiAdapter   = nullptr;
2075     IDXGIAdapter2 *dxgiAdapter2 = nullptr;
2076 
2077     ANGLED3D11DeviceType retDeviceType = ANGLE_D3D11_DEVICE_TYPE_UNKNOWN;
2078 
2079     HRESULT hr = device->QueryInterface(__uuidof(IDXGIDevice), (void **)&dxgiDevice);
2080     if (SUCCEEDED(hr))
2081     {
2082         hr = dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void **)&dxgiAdapter);
2083         if (SUCCEEDED(hr))
2084         {
2085             std::wstring adapterString;
2086             HRESULT adapter2hr =
2087                 dxgiAdapter->QueryInterface(__uuidof(dxgiAdapter2), (void **)&dxgiAdapter2);
2088             if (SUCCEEDED(adapter2hr))
2089             {
2090                 // On D3D_FEATURE_LEVEL_9_*, IDXGIAdapter::GetDesc returns "Software Adapter"
2091                 // for the description string. Try to use IDXGIAdapter2::GetDesc2 to get the
2092                 // actual hardware values if possible.
2093                 DXGI_ADAPTER_DESC2 adapterDesc2;
2094                 dxgiAdapter2->GetDesc2(&adapterDesc2);
2095                 adapterString = std::wstring(adapterDesc2.Description);
2096             }
2097             else
2098             {
2099                 DXGI_ADAPTER_DESC adapterDesc;
2100                 dxgiAdapter->GetDesc(&adapterDesc);
2101                 adapterString = std::wstring(adapterDesc.Description);
2102             }
2103 
2104             // Both Reference and Software adapters will be 'Software Adapter'
2105             const bool isSoftwareDevice =
2106                 (adapterString.find(std::wstring(L"Software Adapter")) != std::string::npos);
2107             const bool isNullDevice = (adapterString == L"");
2108             const bool isWARPDevice =
2109                 (adapterString.find(std::wstring(L"Basic Render")) != std::string::npos);
2110 
2111             if (isSoftwareDevice || isNullDevice)
2112             {
2113                 ASSERT(!isWARPDevice);
2114                 retDeviceType = ANGLE_D3D11_DEVICE_TYPE_SOFTWARE_REF_OR_NULL;
2115             }
2116             else if (isWARPDevice)
2117             {
2118                 retDeviceType = ANGLE_D3D11_DEVICE_TYPE_WARP;
2119             }
2120             else
2121             {
2122                 retDeviceType = ANGLE_D3D11_DEVICE_TYPE_HARDWARE;
2123             }
2124         }
2125     }
2126 
2127     SafeRelease(dxgiDevice);
2128     SafeRelease(dxgiAdapter);
2129     SafeRelease(dxgiAdapter2);
2130 
2131     return retDeviceType;
2132 }
2133 
MakeValidSize(bool isImage,DXGI_FORMAT format,GLsizei * requestWidth,GLsizei * requestHeight,int * levelOffset)2134 void MakeValidSize(bool isImage,
2135                    DXGI_FORMAT format,
2136                    GLsizei *requestWidth,
2137                    GLsizei *requestHeight,
2138                    int *levelOffset)
2139 {
2140     const DXGIFormatSize &dxgiFormatInfo = d3d11::GetDXGIFormatSizeInfo(format);
2141     bool validFormat                     = format != DXGI_FORMAT_UNKNOWN;
2142     bool validImage                      = isImage && validFormat;
2143 
2144     int upsampleCount = 0;
2145     // Don't expand the size of full textures that are at least (blockWidth x blockHeight) already.
2146     if (validImage || *requestWidth < static_cast<GLsizei>(dxgiFormatInfo.blockWidth) ||
2147         *requestHeight < static_cast<GLsizei>(dxgiFormatInfo.blockHeight))
2148     {
2149         while (*requestWidth % dxgiFormatInfo.blockWidth != 0 ||
2150                *requestHeight % dxgiFormatInfo.blockHeight != 0)
2151         {
2152             *requestWidth <<= 1;
2153             *requestHeight <<= 1;
2154             upsampleCount++;
2155         }
2156     }
2157     else if (validFormat)
2158     {
2159         if (*requestWidth % dxgiFormatInfo.blockWidth != 0)
2160         {
2161             *requestWidth = roundUp(*requestWidth, static_cast<GLsizei>(dxgiFormatInfo.blockWidth));
2162         }
2163 
2164         if (*requestHeight % dxgiFormatInfo.blockHeight != 0)
2165         {
2166             *requestHeight =
2167                 roundUp(*requestHeight, static_cast<GLsizei>(dxgiFormatInfo.blockHeight));
2168         }
2169     }
2170 
2171     if (levelOffset)
2172     {
2173         *levelOffset = upsampleCount;
2174     }
2175 }
2176 
GenerateInitialTextureData(const gl::Context * context,GLint internalFormat,const Renderer11DeviceCaps & renderer11DeviceCaps,GLuint width,GLuint height,GLuint depth,GLuint mipLevels,gl::TexLevelArray<D3D11_SUBRESOURCE_DATA> * outSubresourceData)2177 angle::Result GenerateInitialTextureData(
2178     const gl::Context *context,
2179     GLint internalFormat,
2180     const Renderer11DeviceCaps &renderer11DeviceCaps,
2181     GLuint width,
2182     GLuint height,
2183     GLuint depth,
2184     GLuint mipLevels,
2185     gl::TexLevelArray<D3D11_SUBRESOURCE_DATA> *outSubresourceData)
2186 {
2187     const d3d11::Format &d3dFormatInfo = d3d11::Format::Get(internalFormat, renderer11DeviceCaps);
2188     ASSERT(d3dFormatInfo.dataInitializerFunction != nullptr);
2189 
2190     const d3d11::DXGIFormatSize &dxgiFormatInfo =
2191         d3d11::GetDXGIFormatSizeInfo(d3dFormatInfo.texFormat);
2192 
2193     using CheckedSize        = angle::CheckedNumeric<size_t>;
2194     CheckedSize rowPitch     = CheckedSize(dxgiFormatInfo.pixelBytes) * CheckedSize(width);
2195     CheckedSize depthPitch   = rowPitch * CheckedSize(height);
2196     CheckedSize maxImageSize = depthPitch * CheckedSize(depth);
2197 
2198     Context11 *context11 = GetImplAs<Context11>(context);
2199     ANGLE_CHECK_GL_ALLOC(context11, maxImageSize.IsValid());
2200 
2201     angle::MemoryBuffer *scratchBuffer = nullptr;
2202     ANGLE_CHECK_GL_ALLOC(context11,
2203                          context->getScratchBuffer(maxImageSize.ValueOrDie(), &scratchBuffer));
2204 
2205     d3dFormatInfo.dataInitializerFunction(width, height, depth, scratchBuffer->data(),
2206                                           rowPitch.ValueOrDie(), depthPitch.ValueOrDie());
2207 
2208     for (unsigned int i = 0; i < mipLevels; i++)
2209     {
2210         unsigned int mipWidth  = std::max(width >> i, 1U);
2211         unsigned int mipHeight = std::max(height >> i, 1U);
2212 
2213         using CheckedUINT         = angle::CheckedNumeric<UINT>;
2214         CheckedUINT mipRowPitch   = CheckedUINT(dxgiFormatInfo.pixelBytes) * CheckedUINT(mipWidth);
2215         CheckedUINT mipDepthPitch = mipRowPitch * CheckedUINT(mipHeight);
2216 
2217         ANGLE_CHECK_GL_ALLOC(context11, mipRowPitch.IsValid() && mipDepthPitch.IsValid());
2218 
2219         outSubresourceData->at(i).pSysMem          = scratchBuffer->data();
2220         outSubresourceData->at(i).SysMemPitch      = mipRowPitch.ValueOrDie();
2221         outSubresourceData->at(i).SysMemSlicePitch = mipDepthPitch.ValueOrDie();
2222     }
2223 
2224     return angle::Result::Continue;
2225 }
2226 
GetPrimitiveRestartIndex()2227 UINT GetPrimitiveRestartIndex()
2228 {
2229     return std::numeric_limits<UINT>::max();
2230 }
2231 
SetPositionTexCoordVertex(PositionTexCoordVertex * vertex,float x,float y,float u,float v)2232 void SetPositionTexCoordVertex(PositionTexCoordVertex *vertex, float x, float y, float u, float v)
2233 {
2234     vertex->x = x;
2235     vertex->y = y;
2236     vertex->u = u;
2237     vertex->v = v;
2238 }
2239 
SetPositionLayerTexCoord3DVertex(PositionLayerTexCoord3DVertex * vertex,float x,float y,unsigned int layer,float u,float v,float s)2240 void SetPositionLayerTexCoord3DVertex(PositionLayerTexCoord3DVertex *vertex,
2241                                       float x,
2242                                       float y,
2243                                       unsigned int layer,
2244                                       float u,
2245                                       float v,
2246                                       float s)
2247 {
2248     vertex->x = x;
2249     vertex->y = y;
2250     vertex->l = layer;
2251     vertex->u = u;
2252     vertex->v = v;
2253     vertex->s = s;
2254 }
2255 
BlendStateKey()2256 BlendStateKey::BlendStateKey()
2257 {
2258     memset(this, 0, sizeof(BlendStateKey));
2259     blendStateExt = gl::BlendStateExt();
2260 }
2261 
BlendStateKey(const BlendStateKey & other)2262 BlendStateKey::BlendStateKey(const BlendStateKey &other)
2263 {
2264     memcpy(this, &other, sizeof(BlendStateKey));
2265 }
2266 
operator ==(const BlendStateKey & a,const BlendStateKey & b)2267 bool operator==(const BlendStateKey &a, const BlendStateKey &b)
2268 {
2269     return memcmp(&a, &b, sizeof(BlendStateKey)) == 0;
2270 }
2271 
operator !=(const BlendStateKey & a,const BlendStateKey & b)2272 bool operator!=(const BlendStateKey &a, const BlendStateKey &b)
2273 {
2274     return !(a == b);
2275 }
2276 
RasterizerStateKey()2277 RasterizerStateKey::RasterizerStateKey()
2278 {
2279     memset(this, 0, sizeof(RasterizerStateKey));
2280 }
2281 
operator ==(const RasterizerStateKey & a,const RasterizerStateKey & b)2282 bool operator==(const RasterizerStateKey &a, const RasterizerStateKey &b)
2283 {
2284     return memcmp(&a, &b, sizeof(RasterizerStateKey)) == 0;
2285 }
2286 
operator !=(const RasterizerStateKey & a,const RasterizerStateKey & b)2287 bool operator!=(const RasterizerStateKey &a, const RasterizerStateKey &b)
2288 {
2289     return !(a == b);
2290 }
2291 
SetDebugName(ID3D11DeviceChild * resource,const char * name)2292 HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name)
2293 {
2294     UINT existingDataSize = 0;
2295     resource->GetPrivateData(WKPDID_D3DDebugObjectName, &existingDataSize, nullptr);
2296     // Don't check the HRESULT- if it failed then that probably just means that no private data
2297     // exists yet
2298 
2299     if (existingDataSize > 0)
2300     {
2301         // In some cases, ANGLE will try to apply two names to one object, which causes
2302         // a D3D SDK Layers warning. This can occur if, for example, you 'create' two objects
2303         // (e.g.Rasterizer States) with identical DESCs on the same device. D3D11 will optimize
2304         // these calls and return the same object both times.
2305         static const char *multipleNamesUsed = "MultipleNamesSetByANGLE";
2306 
2307         // Remove the existing name
2308         const HRESULT hr = resource->SetPrivateData(WKPDID_D3DDebugObjectName, 0, nullptr);
2309         if (FAILED(hr))
2310         {
2311             return hr;
2312         }
2313 
2314         name = multipleNamesUsed;
2315     }
2316 
2317     // Prepend ANGLE_ to separate names from other components in the same process.
2318     const std::string d3dName = std::string("ANGLE_") + name;
2319     return resource->SetPrivateData(WKPDID_D3DDebugObjectName, static_cast<UINT>(d3dName.size()),
2320                                     d3dName.c_str());
2321 }
2322 
2323 // Keep this in cpp file where it has visibility of Renderer11.h, otherwise calling
2324 // allocateResource is only compatible with Clang and MSVS, which support calling a
2325 // method on a forward declared class in a template.
2326 template <ResourceType ResourceT>
resolveImpl(d3d::Context * context,Renderer11 * renderer,const GetDescType<ResourceT> & desc,GetInitDataType<ResourceT> * initData,const char * name)2327 angle::Result LazyResource<ResourceT>::resolveImpl(d3d::Context *context,
2328                                                    Renderer11 *renderer,
2329                                                    const GetDescType<ResourceT> &desc,
2330                                                    GetInitDataType<ResourceT> *initData,
2331                                                    const char *name)
2332 {
2333     if (!mResource.valid())
2334     {
2335         ANGLE_TRY(renderer->allocateResource(context, desc, initData, &mResource));
2336         mResource.setDebugName(name);
2337     }
2338     return angle::Result::Continue;
2339 }
2340 
2341 template angle::Result LazyResource<ResourceType::BlendState>::resolveImpl(
2342     d3d::Context *context,
2343     Renderer11 *renderer,
2344     const D3D11_BLEND_DESC &desc,
2345     void *initData,
2346     const char *name);
2347 template angle::Result LazyResource<ResourceType::ComputeShader>::resolveImpl(
2348     d3d::Context *context,
2349     Renderer11 *renderer,
2350     const ShaderData &desc,
2351     void *initData,
2352     const char *name);
2353 template angle::Result LazyResource<ResourceType::GeometryShader>::resolveImpl(
2354     d3d::Context *context,
2355     Renderer11 *renderer,
2356     const ShaderData &desc,
2357     const std::vector<D3D11_SO_DECLARATION_ENTRY> *initData,
2358     const char *name);
2359 template angle::Result LazyResource<ResourceType::InputLayout>::resolveImpl(
2360     d3d::Context *context,
2361     Renderer11 *renderer,
2362     const InputElementArray &desc,
2363     const ShaderData *initData,
2364     const char *name);
2365 template angle::Result LazyResource<ResourceType::PixelShader>::resolveImpl(d3d::Context *context,
2366                                                                             Renderer11 *renderer,
2367                                                                             const ShaderData &desc,
2368                                                                             void *initData,
2369                                                                             const char *name);
2370 template angle::Result LazyResource<ResourceType::VertexShader>::resolveImpl(d3d::Context *context,
2371                                                                              Renderer11 *renderer,
2372                                                                              const ShaderData &desc,
2373                                                                              void *initData,
2374                                                                              const char *name);
2375 
LazyInputLayout(const D3D11_INPUT_ELEMENT_DESC * inputDesc,size_t inputDescLen,const BYTE * byteCode,size_t byteCodeLen,const char * debugName)2376 LazyInputLayout::LazyInputLayout(const D3D11_INPUT_ELEMENT_DESC *inputDesc,
2377                                  size_t inputDescLen,
2378                                  const BYTE *byteCode,
2379                                  size_t byteCodeLen,
2380                                  const char *debugName)
2381     : mInputDesc(inputDesc, inputDescLen), mByteCode(byteCode, byteCodeLen), mDebugName(debugName)
2382 {}
2383 
~LazyInputLayout()2384 LazyInputLayout::~LazyInputLayout() {}
2385 
resolve(d3d::Context * context,Renderer11 * renderer)2386 angle::Result LazyInputLayout::resolve(d3d::Context *context, Renderer11 *renderer)
2387 {
2388     return resolveImpl(context, renderer, mInputDesc, &mByteCode, mDebugName);
2389 }
2390 
LazyBlendState(const D3D11_BLEND_DESC & desc,const char * debugName)2391 LazyBlendState::LazyBlendState(const D3D11_BLEND_DESC &desc, const char *debugName)
2392     : mDesc(desc), mDebugName(debugName)
2393 {}
2394 
resolve(d3d::Context * context,Renderer11 * renderer)2395 angle::Result LazyBlendState::resolve(d3d::Context *context, Renderer11 *renderer)
2396 {
2397     return resolveImpl(context, renderer, mDesc, nullptr, mDebugName);
2398 }
2399 
InitializeFeatures(const Renderer11DeviceCaps & deviceCaps,const DXGI_ADAPTER_DESC & adapterDesc,angle::FeaturesD3D * features)2400 void InitializeFeatures(const Renderer11DeviceCaps &deviceCaps,
2401                         const DXGI_ADAPTER_DESC &adapterDesc,
2402                         angle::FeaturesD3D *features)
2403 {
2404     bool isNvidia          = IsNvidia(adapterDesc.VendorId);
2405     bool isIntel           = IsIntel(adapterDesc.VendorId);
2406     bool isSkylake         = false;
2407     bool isBroadwell       = false;
2408     bool isHaswell         = false;
2409     bool isIvyBridge       = false;
2410     bool isSandyBridge     = false;
2411     bool isAMD             = IsAMD(adapterDesc.VendorId);
2412     bool isFeatureLevel9_3 = (deviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3);
2413 
2414     IntelDriverVersion capsVersion = IntelDriverVersion(0);
2415     if (isIntel)
2416     {
2417         capsVersion = d3d11_gl::GetIntelDriverVersion(deviceCaps.driverVersion);
2418 
2419         isSkylake     = IsSkylake(adapterDesc.DeviceId);
2420         isBroadwell   = IsBroadwell(adapterDesc.DeviceId);
2421         isHaswell     = IsHaswell(adapterDesc.DeviceId);
2422         isIvyBridge   = IsIvyBridge(adapterDesc.DeviceId);
2423         isSandyBridge = IsSandyBridge(adapterDesc.DeviceId);
2424     }
2425 
2426     if (isNvidia)
2427     {
2428         // TODO(jmadill): Narrow problematic driver range.
2429         bool driverVersionValid = deviceCaps.driverVersion.valid();
2430         if (driverVersionValid)
2431         {
2432             WORD part1 = HIWORD(deviceCaps.driverVersion.value().LowPart);
2433             WORD part2 = LOWORD(deviceCaps.driverVersion.value().LowPart);
2434 
2435             // Disable the workaround to fix a second driver bug on newer NVIDIA.
2436             ANGLE_FEATURE_CONDITION(
2437                 features, depthStencilBlitExtraCopy,
2438                 (part1 <= 13u && part2 < 6881) && isNvidia && driverVersionValid);
2439         }
2440         else
2441         {
2442             ANGLE_FEATURE_CONDITION(features, depthStencilBlitExtraCopy,
2443                                     isNvidia && !driverVersionValid);
2444         }
2445     }
2446 
2447     ANGLE_FEATURE_CONDITION(features, mrtPerfWorkaround, true);
2448     ANGLE_FEATURE_CONDITION(features, zeroMaxLodWorkaround, isFeatureLevel9_3);
2449     ANGLE_FEATURE_CONDITION(features, useInstancedPointSpriteEmulation, isFeatureLevel9_3);
2450     ANGLE_FEATURE_CONDITION(features, allowES3OnFL10_0, false);
2451 
2452     // TODO(jmadill): Disable workaround when we have a fixed compiler DLL.
2453     ANGLE_FEATURE_CONDITION(features, expandIntegerPowExpressions, true);
2454 
2455     ANGLE_FEATURE_CONDITION(features, flushAfterEndingTransformFeedback, isNvidia);
2456     ANGLE_FEATURE_CONDITION(features, getDimensionsIgnoresBaseLevel, isNvidia);
2457     ANGLE_FEATURE_CONDITION(features, skipVSConstantRegisterZero, isNvidia);
2458     ANGLE_FEATURE_CONDITION(features, forceAtomicValueResolution, isNvidia);
2459 
2460     ANGLE_FEATURE_CONDITION(features, preAddTexelFetchOffsets, isIntel);
2461     ANGLE_FEATURE_CONDITION(features, useSystemMemoryForConstantBuffers, isIntel);
2462 
2463     ANGLE_FEATURE_CONDITION(features, callClearTwice,
2464                             isIntel && isSkylake && capsVersion < IntelDriverVersion(4771));
2465     ANGLE_FEATURE_CONDITION(features, emulateIsnanFloat,
2466                             isIntel && isSkylake && capsVersion < IntelDriverVersion(4542));
2467     ANGLE_FEATURE_CONDITION(
2468         features, rewriteUnaryMinusOperator,
2469         isIntel && (isBroadwell || isHaswell) && capsVersion < IntelDriverVersion(4624));
2470 
2471     ANGLE_FEATURE_CONDITION(features, addMockTextureNoRenderTarget,
2472                             isIntel && capsVersion < IntelDriverVersion(4815));
2473 
2474     // Haswell drivers occasionally corrupt (small?) (vertex?) texture data uploads for 128bit
2475     // formats.
2476     ANGLE_FEATURE_CONDITION(features, setDataFasterThanImageUpload, true);
2477     ANGLE_FEATURE_CONDITION(features, setDataFasterThanImageUploadOn128bitFormats,
2478                             !(isIvyBridge || isBroadwell || isHaswell));
2479 
2480     ANGLE_FEATURE_CONDITION(features, emulateClearViewAfterDualSourceBlending, isSandyBridge);
2481 
2482     ANGLE_FEATURE_CONDITION(features, disableB5G6R5Support,
2483                             (isIntel && capsVersion < IntelDriverVersion(4539)) || isAMD);
2484 
2485     // TODO(jmadill): Disable when we have a fixed driver version.
2486     // The tiny stencil texture workaround involves using CopySubresource or UpdateSubresource on a
2487     // depth stencil texture.  This is not allowed until feature level 10.1 but since it is not
2488     // possible to support ES3 on these devices, there is no need for the workaround to begin with
2489     // (anglebug.com/1572).
2490     ANGLE_FEATURE_CONDITION(features, emulateTinyStencilTextures,
2491                             isAMD && !(deviceCaps.featureLevel < D3D_FEATURE_LEVEL_10_1));
2492 
2493     // If the VPAndRTArrayIndexFromAnyShaderFeedingRasterizer feature is not available, we have to
2494     // select the viewport / RT array index in the geometry shader.
2495     ANGLE_FEATURE_CONDITION(features, selectViewInGeometryShader,
2496                             !deviceCaps.supportsVpRtIndexWriteFromVertexShader);
2497 
2498     // NVidia drivers have no trouble clearing textures without showing corruption.
2499     // Intel and AMD drivers that have trouble have been blocklisted by Chromium. In the case of
2500     // Intel, they've been blocklisted to the DX9 runtime.
2501     ANGLE_FEATURE_CONDITION(features, allowClearForRobustResourceInit, true);
2502 
2503     // Allow translating uniform block to StructuredBuffer on Windows 10. This is targeted
2504     // to work around a slow fxc compile performance issue with dynamic uniform indexing.
2505     ANGLE_FEATURE_CONDITION(features, allowTranslateUniformBlockToStructuredBuffer,
2506                             IsWin10OrGreater());
2507 
2508     // Call platform hooks for testing overrides.
2509     auto *platform = ANGLEPlatformCurrent();
2510     platform->overrideWorkaroundsD3D(platform, features);
2511 }
2512 
InitConstantBufferDesc(D3D11_BUFFER_DESC * constantBufferDescription,size_t byteWidth)2513 void InitConstantBufferDesc(D3D11_BUFFER_DESC *constantBufferDescription, size_t byteWidth)
2514 {
2515     constantBufferDescription->ByteWidth           = static_cast<UINT>(byteWidth);
2516     constantBufferDescription->Usage               = D3D11_USAGE_DYNAMIC;
2517     constantBufferDescription->BindFlags           = D3D11_BIND_CONSTANT_BUFFER;
2518     constantBufferDescription->CPUAccessFlags      = D3D11_CPU_ACCESS_WRITE;
2519     constantBufferDescription->MiscFlags           = 0;
2520     constantBufferDescription->StructureByteStride = 0;
2521 }
2522 
2523 }  // namespace d3d11
2524 
2525 // TextureHelper11 implementation.
TextureHelper11()2526 TextureHelper11::TextureHelper11() : mFormatSet(nullptr), mSampleCount(0) {}
2527 
TextureHelper11(TextureHelper11 && toCopy)2528 TextureHelper11::TextureHelper11(TextureHelper11 &&toCopy) : TextureHelper11()
2529 {
2530     *this = std::move(toCopy);
2531 }
2532 
TextureHelper11(const TextureHelper11 & other)2533 TextureHelper11::TextureHelper11(const TextureHelper11 &other)
2534     : mFormatSet(other.mFormatSet), mExtents(other.mExtents), mSampleCount(other.mSampleCount)
2535 {
2536     mData = other.mData;
2537 }
2538 
~TextureHelper11()2539 TextureHelper11::~TextureHelper11() {}
2540 
getDesc(D3D11_TEXTURE2D_DESC * desc) const2541 void TextureHelper11::getDesc(D3D11_TEXTURE2D_DESC *desc) const
2542 {
2543     static_cast<ID3D11Texture2D *>(mData->object)->GetDesc(desc);
2544 }
2545 
getDesc(D3D11_TEXTURE3D_DESC * desc) const2546 void TextureHelper11::getDesc(D3D11_TEXTURE3D_DESC *desc) const
2547 {
2548     static_cast<ID3D11Texture3D *>(mData->object)->GetDesc(desc);
2549 }
2550 
initDesc(const D3D11_TEXTURE2D_DESC & desc2D)2551 void TextureHelper11::initDesc(const D3D11_TEXTURE2D_DESC &desc2D)
2552 {
2553     mData->resourceType = ResourceType::Texture2D;
2554     mExtents.width      = static_cast<int>(desc2D.Width);
2555     mExtents.height     = static_cast<int>(desc2D.Height);
2556     mExtents.depth      = 1;
2557     mSampleCount        = desc2D.SampleDesc.Count;
2558 }
2559 
initDesc(const D3D11_TEXTURE3D_DESC & desc3D)2560 void TextureHelper11::initDesc(const D3D11_TEXTURE3D_DESC &desc3D)
2561 {
2562     mData->resourceType = ResourceType::Texture3D;
2563     mExtents.width      = static_cast<int>(desc3D.Width);
2564     mExtents.height     = static_cast<int>(desc3D.Height);
2565     mExtents.depth      = static_cast<int>(desc3D.Depth);
2566     mSampleCount        = 1;
2567 }
2568 
operator =(TextureHelper11 && other)2569 TextureHelper11 &TextureHelper11::operator=(TextureHelper11 &&other)
2570 {
2571     std::swap(mData, other.mData);
2572     std::swap(mExtents, other.mExtents);
2573     std::swap(mFormatSet, other.mFormatSet);
2574     std::swap(mSampleCount, other.mSampleCount);
2575     return *this;
2576 }
2577 
operator =(const TextureHelper11 & other)2578 TextureHelper11 &TextureHelper11::operator=(const TextureHelper11 &other)
2579 {
2580     mData        = other.mData;
2581     mExtents     = other.mExtents;
2582     mFormatSet   = other.mFormatSet;
2583     mSampleCount = other.mSampleCount;
2584     return *this;
2585 }
2586 
operator ==(const TextureHelper11 & other) const2587 bool TextureHelper11::operator==(const TextureHelper11 &other) const
2588 {
2589     return mData->object == other.mData->object;
2590 }
2591 
operator !=(const TextureHelper11 & other) const2592 bool TextureHelper11::operator!=(const TextureHelper11 &other) const
2593 {
2594     return mData->object != other.mData->object;
2595 }
2596 
UsePresentPathFast(const Renderer11 * renderer,const gl::FramebufferAttachment * framebufferAttachment)2597 bool UsePresentPathFast(const Renderer11 *renderer,
2598                         const gl::FramebufferAttachment *framebufferAttachment)
2599 {
2600     if (framebufferAttachment == nullptr)
2601     {
2602         return false;
2603     }
2604 
2605     return (framebufferAttachment->type() == GL_FRAMEBUFFER_DEFAULT &&
2606             renderer->presentPathFastEnabled());
2607 }
2608 
UsePrimitiveRestartWorkaround(bool primitiveRestartFixedIndexEnabled,gl::DrawElementsType type)2609 bool UsePrimitiveRestartWorkaround(bool primitiveRestartFixedIndexEnabled,
2610                                    gl::DrawElementsType type)
2611 {
2612     // We should never have to deal with primitive restart workaround issue with GL_UNSIGNED_INT
2613     // indices, since we restrict it via MAX_ELEMENT_INDEX.
2614     return (!primitiveRestartFixedIndexEnabled && type == gl::DrawElementsType::UnsignedShort);
2615 }
2616 
ClassifyIndexStorage(const gl::State & glState,const gl::Buffer * elementArrayBuffer,gl::DrawElementsType elementType,gl::DrawElementsType destElementType,unsigned int offset)2617 IndexStorageType ClassifyIndexStorage(const gl::State &glState,
2618                                       const gl::Buffer *elementArrayBuffer,
2619                                       gl::DrawElementsType elementType,
2620                                       gl::DrawElementsType destElementType,
2621                                       unsigned int offset)
2622 {
2623     // No buffer bound means we are streaming from a client pointer.
2624     if (!elementArrayBuffer || !IsOffsetAligned(elementType, offset))
2625     {
2626         return IndexStorageType::Dynamic;
2627     }
2628 
2629     // The buffer can be used directly if the storage supports it and no translation needed.
2630     BufferD3D *bufferD3D = GetImplAs<BufferD3D>(elementArrayBuffer);
2631     if (bufferD3D->supportsDirectBinding() && destElementType == elementType)
2632     {
2633         return IndexStorageType::Direct;
2634     }
2635 
2636     // Use a static copy when available.
2637     StaticIndexBufferInterface *staticBuffer = bufferD3D->getStaticIndexBuffer();
2638     if (staticBuffer != nullptr)
2639     {
2640         return IndexStorageType::Static;
2641     }
2642 
2643     // Static buffer not available, fall back to streaming.
2644     return IndexStorageType::Dynamic;
2645 }
2646 }  // namespace rx
2647