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