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