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