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