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