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.cpp: Implements a back-end specific class for the D3D11 renderer.
8
9 #include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
10
11 #include <EGL/eglext.h>
12 #include <versionhelpers.h>
13 #include <sstream>
14
15 #include "common/tls.h"
16 #include "common/utilities.h"
17 #include "libANGLE/Buffer.h"
18 #include "libANGLE/Context.h"
19 #include "libANGLE/Display.h"
20 #include "libANGLE/Framebuffer.h"
21 #include "libANGLE/FramebufferAttachment.h"
22 #include "libANGLE/Program.h"
23 #include "libANGLE/State.h"
24 #include "libANGLE/Surface.h"
25 #include "libANGLE/formatutils.h"
26 #include "libANGLE/histogram_macros.h"
27 #include "libANGLE/renderer/d3d/CompilerD3D.h"
28 #include "libANGLE/renderer/d3d/DeviceD3D.h"
29 #include "libANGLE/renderer/d3d/DisplayD3D.h"
30 #include "libANGLE/renderer/d3d/FramebufferD3D.h"
31 #include "libANGLE/renderer/d3d/IndexDataManager.h"
32 #include "libANGLE/renderer/d3d/ProgramD3D.h"
33 #include "libANGLE/renderer/d3d/RenderbufferD3D.h"
34 #include "libANGLE/renderer/d3d/ShaderD3D.h"
35 #include "libANGLE/renderer/d3d/SurfaceD3D.h"
36 #include "libANGLE/renderer/d3d/TextureD3D.h"
37 #include "libANGLE/renderer/d3d/VertexDataManager.h"
38 #include "libANGLE/renderer/d3d/d3d11/Blit11.h"
39 #include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
40 #include "libANGLE/renderer/d3d/d3d11/Clear11.h"
41 #include "libANGLE/renderer/d3d/d3d11/Context11.h"
42 #include "libANGLE/renderer/d3d/d3d11/Fence11.h"
43 #include "libANGLE/renderer/d3d/d3d11/Framebuffer11.h"
44 #include "libANGLE/renderer/d3d/d3d11/Image11.h"
45 #include "libANGLE/renderer/d3d/d3d11/IndexBuffer11.h"
46 #include "libANGLE/renderer/d3d/d3d11/PixelTransfer11.h"
47 #include "libANGLE/renderer/d3d/d3d11/Query11.h"
48 #include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
49 #include "libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h"
50 #include "libANGLE/renderer/d3d/d3d11/StreamProducerNV12.h"
51 #include "libANGLE/renderer/d3d/d3d11/SwapChain11.h"
52 #include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h"
53 #include "libANGLE/renderer/d3d/d3d11/TransformFeedback11.h"
54 #include "libANGLE/renderer/d3d/d3d11/Trim11.h"
55 #include "libANGLE/renderer/d3d/d3d11/VertexArray11.h"
56 #include "libANGLE/renderer/d3d/d3d11/VertexBuffer11.h"
57 #include "libANGLE/renderer/d3d/d3d11/dxgi_support_table.h"
58 #include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
59 #include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
60 #include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
61 #include "libANGLE/renderer/renderer_utils.h"
62 #include "third_party/trace_event/trace_event.h"
63
64 #ifdef ANGLE_ENABLE_WINDOWS_STORE
65 #include "libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.h"
66 #else
67 #include "libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.h"
68 #endif
69
70 // Include the D3D9 debug annotator header for use by the desktop D3D11 renderer
71 // because the D3D11 interface method ID3DUserDefinedAnnotation::GetStatus
72 // doesn't work with the Graphics Diagnostics tools in Visual Studio 2013.
73 #ifdef ANGLE_ENABLE_D3D9
74 #include "libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h"
75 #endif
76
77 // Enable ANGLE_SKIP_DXGI_1_2_CHECK if there is not a possibility of using cross-process
78 // HWNDs or the Windows 7 Platform Update (KB2670838) is expected to be installed.
79 #ifndef ANGLE_SKIP_DXGI_1_2_CHECK
80 #define ANGLE_SKIP_DXGI_1_2_CHECK 0
81 #endif
82
83 namespace rx
84 {
85
86 namespace
87 {
88
89 enum
90 {
91 MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 = 16
92 };
93
94 enum ANGLEFeatureLevel
95 {
96 ANGLE_FEATURE_LEVEL_INVALID,
97 ANGLE_FEATURE_LEVEL_9_3,
98 ANGLE_FEATURE_LEVEL_10_0,
99 ANGLE_FEATURE_LEVEL_10_1,
100 ANGLE_FEATURE_LEVEL_11_0,
101 ANGLE_FEATURE_LEVEL_11_1,
102 NUM_ANGLE_FEATURE_LEVELS
103 };
104
GetANGLEFeatureLevel(D3D_FEATURE_LEVEL d3dFeatureLevel)105 ANGLEFeatureLevel GetANGLEFeatureLevel(D3D_FEATURE_LEVEL d3dFeatureLevel)
106 {
107 switch (d3dFeatureLevel)
108 {
109 case D3D_FEATURE_LEVEL_9_3:
110 return ANGLE_FEATURE_LEVEL_9_3;
111 case D3D_FEATURE_LEVEL_10_0:
112 return ANGLE_FEATURE_LEVEL_10_0;
113 case D3D_FEATURE_LEVEL_10_1:
114 return ANGLE_FEATURE_LEVEL_10_1;
115 case D3D_FEATURE_LEVEL_11_0:
116 return ANGLE_FEATURE_LEVEL_11_0;
117 case D3D_FEATURE_LEVEL_11_1:
118 return ANGLE_FEATURE_LEVEL_11_1;
119 default:
120 return ANGLE_FEATURE_LEVEL_INVALID;
121 }
122 }
123
SetLineLoopIndices(GLuint * dest,size_t count)124 void SetLineLoopIndices(GLuint *dest, size_t count)
125 {
126 for (size_t i = 0; i < count; i++)
127 {
128 dest[i] = static_cast<GLuint>(i);
129 }
130 dest[count] = 0;
131 }
132
133 template <typename T>
CopyLineLoopIndices(const void * indices,GLuint * dest,size_t count)134 void CopyLineLoopIndices(const void *indices, GLuint *dest, size_t count)
135 {
136 const T *srcPtr = static_cast<const T *>(indices);
137 for (size_t i = 0; i < count; ++i)
138 {
139 dest[i] = static_cast<GLuint>(srcPtr[i]);
140 }
141 dest[count] = static_cast<GLuint>(srcPtr[0]);
142 }
143
SetTriangleFanIndices(GLuint * destPtr,size_t numTris)144 void SetTriangleFanIndices(GLuint *destPtr, size_t numTris)
145 {
146 for (size_t i = 0; i < numTris; i++)
147 {
148 destPtr[i * 3 + 0] = 0;
149 destPtr[i * 3 + 1] = static_cast<GLuint>(i) + 1;
150 destPtr[i * 3 + 2] = static_cast<GLuint>(i) + 2;
151 }
152 }
153
154 template <typename T>
CopyLineLoopIndicesWithRestart(const void * indices,size_t count,GLenum indexType,std::vector<GLuint> * bufferOut)155 void CopyLineLoopIndicesWithRestart(const void *indices,
156 size_t count,
157 GLenum indexType,
158 std::vector<GLuint> *bufferOut)
159 {
160 GLuint restartIndex = gl::GetPrimitiveRestartIndex(indexType);
161 GLuint d3dRestartIndex = static_cast<GLuint>(d3d11::GetPrimitiveRestartIndex());
162 const T *srcPtr = static_cast<const T *>(indices);
163 Optional<GLuint> currentLoopStart;
164
165 bufferOut->clear();
166
167 for (size_t indexIdx = 0; indexIdx < count; ++indexIdx)
168 {
169 GLuint value = static_cast<GLuint>(srcPtr[indexIdx]);
170
171 if (value == restartIndex)
172 {
173 if (currentLoopStart.valid())
174 {
175 bufferOut->push_back(currentLoopStart.value());
176 bufferOut->push_back(d3dRestartIndex);
177 currentLoopStart.reset();
178 }
179 }
180 else
181 {
182 bufferOut->push_back(value);
183 if (!currentLoopStart.valid())
184 {
185 currentLoopStart = value;
186 }
187 }
188 }
189
190 if (currentLoopStart.valid())
191 {
192 bufferOut->push_back(currentLoopStart.value());
193 }
194 }
195
GetLineLoopIndices(const void * indices,GLenum indexType,GLuint count,bool usePrimitiveRestartFixedIndex,std::vector<GLuint> * bufferOut)196 void GetLineLoopIndices(const void *indices,
197 GLenum indexType,
198 GLuint count,
199 bool usePrimitiveRestartFixedIndex,
200 std::vector<GLuint> *bufferOut)
201 {
202 if (indexType != GL_NONE && usePrimitiveRestartFixedIndex)
203 {
204 switch (indexType)
205 {
206 case GL_UNSIGNED_BYTE:
207 CopyLineLoopIndicesWithRestart<GLubyte>(indices, count, indexType, bufferOut);
208 break;
209 case GL_UNSIGNED_SHORT:
210 CopyLineLoopIndicesWithRestart<GLushort>(indices, count, indexType, bufferOut);
211 break;
212 case GL_UNSIGNED_INT:
213 CopyLineLoopIndicesWithRestart<GLuint>(indices, count, indexType, bufferOut);
214 break;
215 default:
216 UNREACHABLE();
217 break;
218 }
219 return;
220 }
221
222 // For non-primitive-restart draws, the index count is static.
223 bufferOut->resize(static_cast<size_t>(count) + 1);
224
225 switch (indexType)
226 {
227 // Non-indexed draw
228 case GL_NONE:
229 SetLineLoopIndices(&(*bufferOut)[0], count);
230 break;
231 case GL_UNSIGNED_BYTE:
232 CopyLineLoopIndices<GLubyte>(indices, &(*bufferOut)[0], count);
233 break;
234 case GL_UNSIGNED_SHORT:
235 CopyLineLoopIndices<GLushort>(indices, &(*bufferOut)[0], count);
236 break;
237 case GL_UNSIGNED_INT:
238 CopyLineLoopIndices<GLuint>(indices, &(*bufferOut)[0], count);
239 break;
240 default:
241 UNREACHABLE();
242 break;
243 }
244 }
245
246 template <typename T>
CopyTriangleFanIndices(const void * indices,GLuint * destPtr,size_t numTris)247 void CopyTriangleFanIndices(const void *indices, GLuint *destPtr, size_t numTris)
248 {
249 const T *srcPtr = static_cast<const T *>(indices);
250
251 for (size_t i = 0; i < numTris; i++)
252 {
253 destPtr[i * 3 + 0] = static_cast<GLuint>(srcPtr[0]);
254 destPtr[i * 3 + 1] = static_cast<GLuint>(srcPtr[i + 1]);
255 destPtr[i * 3 + 2] = static_cast<GLuint>(srcPtr[i + 2]);
256 }
257 }
258
259 template <typename T>
CopyTriangleFanIndicesWithRestart(const void * indices,GLuint indexCount,GLenum indexType,std::vector<GLuint> * bufferOut)260 void CopyTriangleFanIndicesWithRestart(const void *indices,
261 GLuint indexCount,
262 GLenum indexType,
263 std::vector<GLuint> *bufferOut)
264 {
265 GLuint restartIndex = gl::GetPrimitiveRestartIndex(indexType);
266 GLuint d3dRestartIndex = gl::GetPrimitiveRestartIndex(GL_UNSIGNED_INT);
267 const T *srcPtr = static_cast<const T *>(indices);
268 Optional<GLuint> vertexA;
269 Optional<GLuint> vertexB;
270
271 bufferOut->clear();
272
273 for (size_t indexIdx = 0; indexIdx < indexCount; ++indexIdx)
274 {
275 GLuint value = static_cast<GLuint>(srcPtr[indexIdx]);
276
277 if (value == restartIndex)
278 {
279 bufferOut->push_back(d3dRestartIndex);
280 vertexA.reset();
281 vertexB.reset();
282 }
283 else
284 {
285 if (!vertexA.valid())
286 {
287 vertexA = value;
288 }
289 else if (!vertexB.valid())
290 {
291 vertexB = value;
292 }
293 else
294 {
295 bufferOut->push_back(vertexA.value());
296 bufferOut->push_back(vertexB.value());
297 bufferOut->push_back(value);
298 vertexB = value;
299 }
300 }
301 }
302 }
303
GetTriFanIndices(const void * indices,GLenum indexType,GLuint count,bool usePrimitiveRestartFixedIndex,std::vector<GLuint> * bufferOut)304 void GetTriFanIndices(const void *indices,
305 GLenum indexType,
306 GLuint count,
307 bool usePrimitiveRestartFixedIndex,
308 std::vector<GLuint> *bufferOut)
309 {
310 if (indexType != GL_NONE && usePrimitiveRestartFixedIndex)
311 {
312 switch (indexType)
313 {
314 case GL_UNSIGNED_BYTE:
315 CopyTriangleFanIndicesWithRestart<GLubyte>(indices, count, indexType, bufferOut);
316 break;
317 case GL_UNSIGNED_SHORT:
318 CopyTriangleFanIndicesWithRestart<GLushort>(indices, count, indexType, bufferOut);
319 break;
320 case GL_UNSIGNED_INT:
321 CopyTriangleFanIndicesWithRestart<GLuint>(indices, count, indexType, bufferOut);
322 break;
323 default:
324 UNREACHABLE();
325 break;
326 }
327 return;
328 }
329
330 // For non-primitive-restart draws, the index count is static.
331 GLuint numTris = count - 2;
332 bufferOut->resize(numTris * 3);
333
334 switch (indexType)
335 {
336 // Non-indexed draw
337 case GL_NONE:
338 SetTriangleFanIndices(&(*bufferOut)[0], numTris);
339 break;
340 case GL_UNSIGNED_BYTE:
341 CopyTriangleFanIndices<GLubyte>(indices, &(*bufferOut)[0], numTris);
342 break;
343 case GL_UNSIGNED_SHORT:
344 CopyTriangleFanIndices<GLushort>(indices, &(*bufferOut)[0], numTris);
345 break;
346 case GL_UNSIGNED_INT:
347 CopyTriangleFanIndices<GLuint>(indices, &(*bufferOut)[0], numTris);
348 break;
349 default:
350 UNREACHABLE();
351 break;
352 }
353 }
354
DrawCallNeedsTranslation(const gl::Context * context,GLenum mode)355 bool DrawCallNeedsTranslation(const gl::Context *context, GLenum mode)
356 {
357 const auto &glState = context->getGLState();
358 const gl::VertexArray *vertexArray = glState.getVertexArray();
359 VertexArray11 *vertexArray11 = GetImplAs<VertexArray11>(vertexArray);
360 // Direct drawing doesn't support dynamic attribute storage since it needs the first and count
361 // to translate when applyVertexBuffer. GL_LINE_LOOP and GL_TRIANGLE_FAN are not supported
362 // either since we need to simulate them in D3D.
363 if (vertexArray11->hasActiveDynamicAttrib(context) || mode == GL_LINE_LOOP ||
364 mode == GL_TRIANGLE_FAN)
365 {
366 return true;
367 }
368
369 ProgramD3D *programD3D = GetImplAs<ProgramD3D>(glState.getProgram());
370 if (InstancedPointSpritesActive(programD3D, mode))
371 {
372 return true;
373 }
374
375 return false;
376 }
377
IsArrayRTV(ID3D11RenderTargetView * rtv)378 bool IsArrayRTV(ID3D11RenderTargetView *rtv)
379 {
380 D3D11_RENDER_TARGET_VIEW_DESC desc;
381 rtv->GetDesc(&desc);
382 if (desc.ViewDimension == D3D11_RTV_DIMENSION_TEXTURE1DARRAY &&
383 desc.Texture1DArray.ArraySize > 1)
384 return true;
385 if (desc.ViewDimension == D3D11_RTV_DIMENSION_TEXTURE2DARRAY &&
386 desc.Texture2DArray.ArraySize > 1)
387 return true;
388 if (desc.ViewDimension == D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY &&
389 desc.Texture2DMSArray.ArraySize > 1)
390 return true;
391 return false;
392 }
393
GetAdjustedInstanceCount(const gl::Program * program,int instanceCount)394 int GetAdjustedInstanceCount(const gl::Program *program, int instanceCount)
395 {
396 if (!program->usesMultiview())
397 {
398 return instanceCount;
399 }
400 if (instanceCount == 0)
401 {
402 return program->getNumViews();
403 }
404 return program->getNumViews() * instanceCount;
405 }
406
407 const uint32_t ScratchMemoryBufferLifetime = 1000;
408
PopulateFormatDeviceCaps(ID3D11Device * device,DXGI_FORMAT format,UINT * outSupport,UINT * outMaxSamples)409 void PopulateFormatDeviceCaps(ID3D11Device *device,
410 DXGI_FORMAT format,
411 UINT *outSupport,
412 UINT *outMaxSamples)
413 {
414 if (FAILED(device->CheckFormatSupport(format, outSupport)))
415 {
416 *outSupport = 0;
417 }
418
419 *outMaxSamples = 0;
420 for (UINT sampleCount = 2; sampleCount <= D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; sampleCount *= 2)
421 {
422 UINT qualityCount = 0;
423 if (FAILED(device->CheckMultisampleQualityLevels(format, sampleCount, &qualityCount)) ||
424 qualityCount == 0)
425 {
426 break;
427 }
428
429 *outMaxSamples = sampleCount;
430 }
431 }
432
CullsEverything(const gl::State & glState)433 bool CullsEverything(const gl::State &glState)
434 {
435 return (glState.getRasterizerState().cullFace &&
436 glState.getRasterizerState().cullMode == gl::CullFaceMode::FrontAndBack);
437 }
438
439 } // anonymous namespace
440
441 Renderer11DeviceCaps::Renderer11DeviceCaps() = default;
442
Renderer11(egl::Display * display)443 Renderer11::Renderer11(egl::Display *display)
444 : RendererD3D(display),
445 mCreateDebugDevice(false),
446 mStateCache(),
447 mStateManager(this),
448 mLastHistogramUpdateTime(
449 ANGLEPlatformCurrent()->monotonicallyIncreasingTime(ANGLEPlatformCurrent())),
450 mDebug(nullptr),
451 mScratchMemoryBuffer(ScratchMemoryBufferLifetime),
452 mAnnotator(nullptr)
453 {
454 mLineLoopIB = nullptr;
455 mTriangleFanIB = nullptr;
456
457 mBlit = nullptr;
458 mPixelTransfer = nullptr;
459
460 mClear = nullptr;
461
462 mTrim = nullptr;
463
464 mRenderer11DeviceCaps.supportsClearView = false;
465 mRenderer11DeviceCaps.supportsConstantBufferOffsets = false;
466 mRenderer11DeviceCaps.supportsVpRtIndexWriteFromVertexShader = false;
467 mRenderer11DeviceCaps.supportsDXGI1_2 = false;
468 mRenderer11DeviceCaps.B5G6R5support = 0;
469 mRenderer11DeviceCaps.B4G4R4A4support = 0;
470 mRenderer11DeviceCaps.B5G5R5A1support = 0;
471
472 mD3d11Module = nullptr;
473 mDxgiModule = nullptr;
474 mDCompModule = nullptr;
475 mCreatedWithDeviceEXT = false;
476 mEGLDevice = nullptr;
477
478 mDevice = nullptr;
479 mDeviceContext = nullptr;
480 mDeviceContext1 = nullptr;
481 mDeviceContext3 = nullptr;
482 mDxgiAdapter = nullptr;
483 mDxgiFactory = nullptr;
484
485 ZeroMemory(&mAdapterDescription, sizeof(mAdapterDescription));
486
487 if (mDisplay->getPlatform() == EGL_PLATFORM_ANGLE_ANGLE)
488 {
489 const auto &attributes = mDisplay->getAttributeMap();
490
491 EGLint requestedMajorVersion = static_cast<EGLint>(
492 attributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE));
493 EGLint requestedMinorVersion = static_cast<EGLint>(
494 attributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE));
495
496 if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 11)
497 {
498 if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 1)
499 {
500 // This could potentially lead to failed context creation if done on a system
501 // without the platform update which installs DXGI 1.2. Currently, for Chrome users
502 // D3D11 contexts are only created if the platform update is available, so this
503 // should not cause any issues.
504 mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_11_1);
505 }
506 if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 0)
507 {
508 mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_11_0);
509 }
510 }
511
512 if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 10)
513 {
514 if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 1)
515 {
516 mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_10_1);
517 }
518 if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 0)
519 {
520 mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_10_0);
521 }
522 }
523
524 if (requestedMajorVersion == 9 && requestedMinorVersion == 3)
525 {
526 if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 3)
527 {
528 mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_3);
529 }
530 #if defined(ANGLE_ENABLE_WINDOWS_STORE)
531 if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 2)
532 {
533 mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_2);
534 }
535 if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 1)
536 {
537 mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_1);
538 }
539 #endif
540 }
541
542 EGLint requestedDeviceType = static_cast<EGLint>(attributes.get(
543 EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE));
544 switch (requestedDeviceType)
545 {
546 case EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE:
547 mRequestedDriverType = D3D_DRIVER_TYPE_HARDWARE;
548 break;
549
550 case EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE:
551 mRequestedDriverType = D3D_DRIVER_TYPE_WARP;
552 break;
553
554 case EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE:
555 mRequestedDriverType = D3D_DRIVER_TYPE_REFERENCE;
556 break;
557
558 case EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE:
559 mRequestedDriverType = D3D_DRIVER_TYPE_NULL;
560 break;
561
562 default:
563 UNREACHABLE();
564 }
565
566 const EGLenum presentPath = static_cast<EGLenum>(attributes.get(
567 EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE, EGL_EXPERIMENTAL_PRESENT_PATH_COPY_ANGLE));
568 mPresentPathFastEnabled = (presentPath == EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE);
569
570 mCreateDebugDevice = ShouldUseDebugLayers(attributes);
571 }
572 else if (display->getPlatform() == EGL_PLATFORM_DEVICE_EXT)
573 {
574 mEGLDevice = GetImplAs<DeviceD3D>(display->getDevice());
575 ASSERT(mEGLDevice != nullptr);
576 mCreatedWithDeviceEXT = true;
577
578 // Also set EGL_PLATFORM_ANGLE_ANGLE variables, in case they're used elsewhere in ANGLE
579 // mAvailableFeatureLevels defaults to empty
580 mRequestedDriverType = D3D_DRIVER_TYPE_UNKNOWN;
581 mPresentPathFastEnabled = false;
582 }
583
584 // The D3D11 renderer must choose the D3D9 debug annotator because the D3D11 interface
585 // method ID3DUserDefinedAnnotation::GetStatus on desktop builds doesn't work with the Graphics
586 // Diagnostics tools in Visual Studio 2013.
587 // The D3D9 annotator works properly for both D3D11 and D3D9.
588 // Incorrect status reporting can cause ANGLE to log unnecessary debug events.
589 #ifdef ANGLE_ENABLE_D3D9
590 mAnnotator = new DebugAnnotator9();
591 #else
592 mAnnotator = new DebugAnnotator11();
593 #endif
594 ASSERT(mAnnotator);
595 gl::InitializeDebugAnnotations(mAnnotator);
596 }
597
~Renderer11()598 Renderer11::~Renderer11()
599 {
600 release();
601 }
602
603 #ifndef __d3d11_1_h__
604 #define D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET ((D3D11_MESSAGE_ID)3146081)
605 #endif
606
initialize()607 egl::Error Renderer11::initialize()
608 {
609 HRESULT result = S_OK;
610
611 ANGLE_TRY(initializeD3DDevice());
612
613 #if !defined(ANGLE_ENABLE_WINDOWS_STORE)
614 #if !ANGLE_SKIP_DXGI_1_2_CHECK
615 {
616 TRACE_EVENT0("gpu.angle", "Renderer11::initialize (DXGICheck)");
617 // In order to create a swap chain for an HWND owned by another process, DXGI 1.2 is
618 // required.
619 // The easiest way to check is to query for a IDXGIDevice2.
620 bool requireDXGI1_2 = false;
621 HWND hwnd = WindowFromDC(mDisplay->getNativeDisplayId());
622 if (hwnd)
623 {
624 DWORD currentProcessId = GetCurrentProcessId();
625 DWORD wndProcessId;
626 GetWindowThreadProcessId(hwnd, &wndProcessId);
627 requireDXGI1_2 = (currentProcessId != wndProcessId);
628 }
629 else
630 {
631 requireDXGI1_2 = true;
632 }
633
634 if (requireDXGI1_2)
635 {
636 IDXGIDevice2 *dxgiDevice2 = nullptr;
637 result = mDevice->QueryInterface(__uuidof(IDXGIDevice2), (void **)&dxgiDevice2);
638 if (FAILED(result))
639 {
640 return egl::EglNotInitialized(D3D11_INIT_INCOMPATIBLE_DXGI)
641 << "DXGI 1.2 required to present to HWNDs owned by another process.";
642 }
643 SafeRelease(dxgiDevice2);
644 }
645 }
646 #endif
647 #endif
648
649 {
650 TRACE_EVENT0("gpu.angle", "Renderer11::initialize (ComQueries)");
651 // Cast the DeviceContext to a DeviceContext1 and DeviceContext3.
652 // This could fail on Windows 7 without the Platform Update.
653 // Don't error in this case- just don't use mDeviceContext1 or mDeviceContext3.
654 mDeviceContext1 = d3d11::DynamicCastComObject<ID3D11DeviceContext1>(mDeviceContext);
655 mDeviceContext3 = d3d11::DynamicCastComObject<ID3D11DeviceContext3>(mDeviceContext);
656
657 IDXGIDevice *dxgiDevice = nullptr;
658 result = mDevice->QueryInterface(__uuidof(IDXGIDevice), (void **)&dxgiDevice);
659
660 if (FAILED(result))
661 {
662 return egl::EglNotInitialized(D3D11_INIT_OTHER_ERROR) << "Could not query DXGI device.";
663 }
664
665 result = dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void **)&mDxgiAdapter);
666
667 if (FAILED(result))
668 {
669 return egl::EglNotInitialized(D3D11_INIT_OTHER_ERROR)
670 << "Could not retrieve DXGI adapter";
671 }
672
673 SafeRelease(dxgiDevice);
674
675 IDXGIAdapter2 *dxgiAdapter2 = d3d11::DynamicCastComObject<IDXGIAdapter2>(mDxgiAdapter);
676
677 // On D3D_FEATURE_LEVEL_9_*, IDXGIAdapter::GetDesc returns "Software Adapter" for the
678 // description string.
679 // If DXGI1.2 is available then IDXGIAdapter2::GetDesc2 can be used to get the actual
680 // hardware values.
681 if (mRenderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3 && dxgiAdapter2 != nullptr)
682 {
683 DXGI_ADAPTER_DESC2 adapterDesc2 = {};
684 result = dxgiAdapter2->GetDesc2(&adapterDesc2);
685 if (SUCCEEDED(result))
686 {
687 // Copy the contents of the DXGI_ADAPTER_DESC2 into mAdapterDescription (a
688 // DXGI_ADAPTER_DESC).
689 memcpy(mAdapterDescription.Description, adapterDesc2.Description,
690 sizeof(mAdapterDescription.Description));
691 mAdapterDescription.VendorId = adapterDesc2.VendorId;
692 mAdapterDescription.DeviceId = adapterDesc2.DeviceId;
693 mAdapterDescription.SubSysId = adapterDesc2.SubSysId;
694 mAdapterDescription.Revision = adapterDesc2.Revision;
695 mAdapterDescription.DedicatedVideoMemory = adapterDesc2.DedicatedVideoMemory;
696 mAdapterDescription.DedicatedSystemMemory = adapterDesc2.DedicatedSystemMemory;
697 mAdapterDescription.SharedSystemMemory = adapterDesc2.SharedSystemMemory;
698 mAdapterDescription.AdapterLuid = adapterDesc2.AdapterLuid;
699 }
700 }
701 else
702 {
703 result = mDxgiAdapter->GetDesc(&mAdapterDescription);
704 }
705
706 SafeRelease(dxgiAdapter2);
707
708 if (FAILED(result))
709 {
710 return egl::EglNotInitialized(D3D11_INIT_OTHER_ERROR)
711 << "Could not read DXGI adaptor description.";
712 }
713
714 memset(mDescription, 0, sizeof(mDescription));
715 wcstombs(mDescription, mAdapterDescription.Description, sizeof(mDescription) - 1);
716
717 result = mDxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void **)&mDxgiFactory);
718
719 if (!mDxgiFactory || FAILED(result))
720 {
721 return egl::EglNotInitialized(D3D11_INIT_OTHER_ERROR)
722 << "Could not create DXGI factory.";
723 }
724 }
725
726 // Disable some spurious D3D11 debug warnings to prevent them from flooding the output log
727 if (mCreateDebugDevice)
728 {
729 TRACE_EVENT0("gpu.angle", "Renderer11::initialize (HideWarnings)");
730 ID3D11InfoQueue *infoQueue;
731 result = mDevice->QueryInterface(__uuidof(ID3D11InfoQueue), (void **)&infoQueue);
732
733 if (SUCCEEDED(result))
734 {
735 D3D11_MESSAGE_ID hideMessages[] = {
736 D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET};
737
738 D3D11_INFO_QUEUE_FILTER filter = {};
739 filter.DenyList.NumIDs = static_cast<unsigned int>(ArraySize(hideMessages));
740 filter.DenyList.pIDList = hideMessages;
741
742 infoQueue->AddStorageFilterEntries(&filter);
743 SafeRelease(infoQueue);
744 }
745 }
746
747 #if !defined(NDEBUG)
748 mDebug = d3d11::DynamicCastComObject<ID3D11Debug>(mDevice);
749 #endif
750
751 ANGLE_TRY(initializeDevice());
752
753 return egl::NoError();
754 }
755
callD3D11CreateDevice(PFN_D3D11_CREATE_DEVICE createDevice,bool debug)756 HRESULT Renderer11::callD3D11CreateDevice(PFN_D3D11_CREATE_DEVICE createDevice, bool debug)
757 {
758 return createDevice(
759 nullptr, mRequestedDriverType, nullptr, debug ? D3D11_CREATE_DEVICE_DEBUG : 0,
760 mAvailableFeatureLevels.data(), static_cast<unsigned int>(mAvailableFeatureLevels.size()),
761 D3D11_SDK_VERSION, &mDevice, &(mRenderer11DeviceCaps.featureLevel), &mDeviceContext);
762 }
763
initializeD3DDevice()764 egl::Error Renderer11::initializeD3DDevice()
765 {
766 HRESULT result = S_OK;
767
768 if (!mCreatedWithDeviceEXT)
769 {
770 #if !defined(ANGLE_ENABLE_WINDOWS_STORE)
771 PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = nullptr;
772 {
773 SCOPED_ANGLE_HISTOGRAM_TIMER("GPU.ANGLE.Renderer11InitializeDLLsMS");
774 TRACE_EVENT0("gpu.angle", "Renderer11::initialize (Load DLLs)");
775 mDxgiModule = LoadLibrary(TEXT("dxgi.dll"));
776 mD3d11Module = LoadLibrary(TEXT("d3d11.dll"));
777 mDCompModule = LoadLibrary(TEXT("dcomp.dll"));
778
779 if (mD3d11Module == nullptr || mDxgiModule == nullptr)
780 {
781 return egl::EglNotInitialized(D3D11_INIT_MISSING_DEP)
782 << "Could not load D3D11 or DXGI library.";
783 }
784
785 // create the D3D11 device
786 ASSERT(mDevice == nullptr);
787 D3D11CreateDevice = reinterpret_cast<PFN_D3D11_CREATE_DEVICE>(
788 GetProcAddress(mD3d11Module, "D3D11CreateDevice"));
789
790 if (D3D11CreateDevice == nullptr)
791 {
792 return egl::EglNotInitialized(D3D11_INIT_MISSING_DEP)
793 << "Could not retrieve D3D11CreateDevice address.";
794 }
795 }
796 #endif
797
798 if (mCreateDebugDevice)
799 {
800 TRACE_EVENT0("gpu.angle", "D3D11CreateDevice (Debug)");
801 result = callD3D11CreateDevice(D3D11CreateDevice, true);
802
803 if (result == E_INVALIDARG && mAvailableFeatureLevels.size() > 1u &&
804 mAvailableFeatureLevels[0] == D3D_FEATURE_LEVEL_11_1)
805 {
806 // On older Windows platforms, D3D11.1 is not supported which returns E_INVALIDARG.
807 // Try again without passing D3D_FEATURE_LEVEL_11_1 in case we have other feature
808 // levels to fall back on.
809 mAvailableFeatureLevels.erase(mAvailableFeatureLevels.begin());
810 result = callD3D11CreateDevice(D3D11CreateDevice, true);
811 }
812
813 if (!mDevice || FAILED(result))
814 {
815 WARN() << "Failed creating Debug D3D11 device - falling back to release runtime.";
816 }
817 }
818
819 if (!mDevice || FAILED(result))
820 {
821 SCOPED_ANGLE_HISTOGRAM_TIMER("GPU.ANGLE.D3D11CreateDeviceMS");
822 TRACE_EVENT0("gpu.angle", "D3D11CreateDevice");
823
824 result = callD3D11CreateDevice(D3D11CreateDevice, false);
825
826 if (result == E_INVALIDARG && mAvailableFeatureLevels.size() > 1u &&
827 mAvailableFeatureLevels[0] == D3D_FEATURE_LEVEL_11_1)
828 {
829 // On older Windows platforms, D3D11.1 is not supported which returns E_INVALIDARG.
830 // Try again without passing D3D_FEATURE_LEVEL_11_1 in case we have other feature
831 // levels to fall back on.
832 mAvailableFeatureLevels.erase(mAvailableFeatureLevels.begin());
833 result = callD3D11CreateDevice(D3D11CreateDevice, false);
834 }
835
836 // Cleanup done by destructor
837 if (!mDevice || FAILED(result))
838 {
839 ANGLE_HISTOGRAM_SPARSE_SLOWLY("GPU.ANGLE.D3D11CreateDeviceError",
840 static_cast<int>(result));
841 return egl::EglNotInitialized(D3D11_INIT_CREATEDEVICE_ERROR)
842 << "Could not create D3D11 device.";
843 }
844 }
845 }
846 else
847 {
848 // We should use the inputted D3D11 device instead
849 void *device = nullptr;
850 ANGLE_TRY(mEGLDevice->getDevice(&device));
851
852 ID3D11Device *d3dDevice = reinterpret_cast<ID3D11Device *>(device);
853 if (FAILED(d3dDevice->GetDeviceRemovedReason()))
854 {
855 return egl::EglNotInitialized() << "Inputted D3D11 device has been lost.";
856 }
857
858 if (d3dDevice->GetFeatureLevel() < D3D_FEATURE_LEVEL_9_3)
859 {
860 return egl::EglNotInitialized()
861 << "Inputted D3D11 device must be Feature Level 9_3 or greater.";
862 }
863
864 // The Renderer11 adds a ref to the inputted D3D11 device, like D3D11CreateDevice does.
865 mDevice = d3dDevice;
866 mDevice->AddRef();
867 mDevice->GetImmediateContext(&mDeviceContext);
868 mRenderer11DeviceCaps.featureLevel = mDevice->GetFeatureLevel();
869 }
870
871 mResourceManager11.setAllocationsInitialized(mCreateDebugDevice);
872
873 d3d11::SetDebugName(mDeviceContext, "DeviceContext");
874
875 return egl::NoError();
876 }
877
878 // do any one-time device initialization
879 // NOTE: this is also needed after a device lost/reset
880 // to reset the scene status and ensure the default states are reset.
initializeDevice()881 egl::Error Renderer11::initializeDevice()
882 {
883 SCOPED_ANGLE_HISTOGRAM_TIMER("GPU.ANGLE.Renderer11InitializeDeviceMS");
884 TRACE_EVENT0("gpu.angle", "Renderer11::initializeDevice");
885
886 populateRenderer11DeviceCaps();
887
888 mStateCache.clear();
889
890 ASSERT(!mBlit);
891 mBlit = new Blit11(this);
892
893 ASSERT(!mClear);
894 mClear = new Clear11(this);
895
896 const auto &attributes = mDisplay->getAttributeMap();
897 // If automatic trim is enabled, DXGIDevice3::Trim( ) is called for the application
898 // automatically when an application is suspended by the OS. This feature is currently
899 // only supported for Windows Store applications.
900 EGLint enableAutoTrim = static_cast<EGLint>(
901 attributes.get(EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_FALSE));
902
903 if (enableAutoTrim == EGL_TRUE)
904 {
905 ASSERT(!mTrim);
906 mTrim = new Trim11(this);
907 }
908
909 ASSERT(!mPixelTransfer);
910 mPixelTransfer = new PixelTransfer11(this);
911
912 const gl::Caps &rendererCaps = getNativeCaps();
913
914 if (mStateManager.initialize(rendererCaps, getNativeExtensions()).isError())
915 {
916 return egl::EglBadAlloc() << "Error initializing state manager.";
917 }
918
919 // Gather stats on DXGI and D3D feature level
920 ANGLE_HISTOGRAM_BOOLEAN("GPU.ANGLE.SupportsDXGI1_2", mRenderer11DeviceCaps.supportsDXGI1_2);
921
922 ANGLEFeatureLevel angleFeatureLevel = GetANGLEFeatureLevel(mRenderer11DeviceCaps.featureLevel);
923
924 // We don't actually request a 11_1 device, because of complications with the platform
925 // update. Instead we check if the mDeviceContext1 pointer cast succeeded.
926 // Note: we should support D3D11_0 always, but we aren't guaranteed to be at FL11_0
927 // because the app can specify a lower version (such as 9_3) on Display creation.
928 if (mDeviceContext1 != nullptr)
929 {
930 angleFeatureLevel = ANGLE_FEATURE_LEVEL_11_1;
931 }
932
933 ANGLE_HISTOGRAM_ENUMERATION("GPU.ANGLE.D3D11FeatureLevel", angleFeatureLevel,
934 NUM_ANGLE_FEATURE_LEVELS);
935
936 return egl::NoError();
937 }
938
populateRenderer11DeviceCaps()939 void Renderer11::populateRenderer11DeviceCaps()
940 {
941 HRESULT hr = S_OK;
942
943 LARGE_INTEGER version;
944 hr = mDxgiAdapter->CheckInterfaceSupport(__uuidof(IDXGIDevice), &version);
945 if (FAILED(hr))
946 {
947 mRenderer11DeviceCaps.driverVersion.reset();
948 ERR() << "Error querying driver version from DXGI Adapter.";
949 }
950 else
951 {
952 mRenderer11DeviceCaps.driverVersion = version;
953 }
954
955 if (mDeviceContext1)
956 {
957 D3D11_FEATURE_DATA_D3D11_OPTIONS d3d11Options;
958 HRESULT result = mDevice->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &d3d11Options,
959 sizeof(D3D11_FEATURE_DATA_D3D11_OPTIONS));
960 if (SUCCEEDED(result))
961 {
962 mRenderer11DeviceCaps.supportsClearView = (d3d11Options.ClearView != FALSE);
963 mRenderer11DeviceCaps.supportsConstantBufferOffsets =
964 (d3d11Options.ConstantBufferOffsetting != FALSE);
965 }
966 }
967
968 if (mDeviceContext3)
969 {
970 D3D11_FEATURE_DATA_D3D11_OPTIONS3 d3d11Options3;
971 HRESULT result = mDevice->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS3, &d3d11Options3,
972 sizeof(D3D11_FEATURE_DATA_D3D11_OPTIONS3));
973 if (SUCCEEDED(result))
974 {
975 mRenderer11DeviceCaps.supportsVpRtIndexWriteFromVertexShader =
976 (d3d11Options3.VPAndRTArrayIndexFromAnyShaderFeedingRasterizer == TRUE);
977 }
978 }
979
980 mRenderer11DeviceCaps.supportsMultisampledDepthStencilSRVs =
981 mRenderer11DeviceCaps.featureLevel > D3D_FEATURE_LEVEL_10_0;
982
983 if (getWorkarounds().disableB5G6R5Support)
984 {
985 mRenderer11DeviceCaps.B5G6R5support = 0;
986 mRenderer11DeviceCaps.B5G6R5maxSamples = 0;
987 }
988 else
989 {
990 PopulateFormatDeviceCaps(mDevice, DXGI_FORMAT_B5G6R5_UNORM,
991 &mRenderer11DeviceCaps.B5G6R5support,
992 &mRenderer11DeviceCaps.B5G6R5maxSamples);
993 }
994
995 PopulateFormatDeviceCaps(mDevice, DXGI_FORMAT_B4G4R4A4_UNORM,
996 &mRenderer11DeviceCaps.B4G4R4A4support,
997 &mRenderer11DeviceCaps.B4G4R4A4maxSamples);
998 PopulateFormatDeviceCaps(mDevice, DXGI_FORMAT_B5G5R5A1_UNORM,
999 &mRenderer11DeviceCaps.B5G5R5A1support,
1000 &mRenderer11DeviceCaps.B5G5R5A1maxSamples);
1001
1002 IDXGIAdapter2 *dxgiAdapter2 = d3d11::DynamicCastComObject<IDXGIAdapter2>(mDxgiAdapter);
1003 mRenderer11DeviceCaps.supportsDXGI1_2 = (dxgiAdapter2 != nullptr);
1004 SafeRelease(dxgiAdapter2);
1005 }
1006
generateSampleSetForEGLConfig(const gl::TextureCaps & colorBufferFormatCaps,const gl::TextureCaps & depthStencilBufferFormatCaps) const1007 gl::SupportedSampleSet Renderer11::generateSampleSetForEGLConfig(
1008 const gl::TextureCaps &colorBufferFormatCaps,
1009 const gl::TextureCaps &depthStencilBufferFormatCaps) const
1010 {
1011 gl::SupportedSampleSet sampleCounts;
1012
1013 #if 0 // Disabling support for multisampling with Qt5 as it's causing a crash in the D3D11 shaders.
1014
1015 // Generate a new set from the set intersection of sample counts between the color and depth
1016 // format caps.
1017 std::set_intersection(colorBufferFormatCaps.sampleCounts.begin(),
1018 colorBufferFormatCaps.sampleCounts.end(),
1019 depthStencilBufferFormatCaps.sampleCounts.begin(),
1020 depthStencilBufferFormatCaps.sampleCounts.end(),
1021 std::inserter(sampleCounts, sampleCounts.begin()));
1022
1023 // Format of GL_NONE results in no supported sample counts.
1024 // Add back the color sample counts to the supported sample set.
1025 if (depthStencilBufferFormatCaps.sampleCounts.empty())
1026 {
1027 sampleCounts = colorBufferFormatCaps.sampleCounts;
1028 }
1029 else if (colorBufferFormatCaps.sampleCounts.empty())
1030 {
1031 // Likewise, add back the depth sample counts to the supported sample set.
1032 sampleCounts = depthStencilBufferFormatCaps.sampleCounts;
1033 }
1034
1035 #endif
1036
1037 // Always support 0 samples
1038 sampleCounts.insert(0);
1039
1040 return sampleCounts;
1041 }
1042
generateConfigs()1043 egl::ConfigSet Renderer11::generateConfigs()
1044 {
1045 std::vector<GLenum> colorBufferFormats;
1046
1047 // 32-bit supported formats
1048 colorBufferFormats.push_back(GL_BGRA8_EXT);
1049 colorBufferFormats.push_back(GL_RGBA8_OES);
1050
1051 // 24-bit supported formats
1052 colorBufferFormats.push_back(GL_RGB8_OES);
1053
1054 if (mRenderer11DeviceCaps.featureLevel >= D3D_FEATURE_LEVEL_10_0)
1055 {
1056 // Additional high bit depth formats added in D3D 10.0
1057 // https://msdn.microsoft.com/en-us/library/windows/desktop/bb173064.aspx
1058 colorBufferFormats.push_back(GL_RGBA16F);
1059 colorBufferFormats.push_back(GL_RGB10_A2);
1060 }
1061
1062 if (!mPresentPathFastEnabled)
1063 {
1064 // 16-bit supported formats
1065 // These aren't valid D3D11 swapchain formats, so don't expose them as configs
1066 // if present path fast is active
1067 colorBufferFormats.push_back(GL_RGBA4);
1068 colorBufferFormats.push_back(GL_RGB5_A1);
1069 colorBufferFormats.push_back(GL_RGB565);
1070 }
1071
1072 static const GLenum depthStencilBufferFormats[] = {
1073 GL_NONE, GL_DEPTH24_STENCIL8_OES, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT16,
1074 GL_STENCIL_INDEX8,
1075 };
1076
1077 const gl::Caps &rendererCaps = getNativeCaps();
1078 const gl::TextureCapsMap &rendererTextureCaps = getNativeTextureCaps();
1079
1080 const EGLint optimalSurfaceOrientation =
1081 mPresentPathFastEnabled ? 0 : EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE;
1082
1083 egl::ConfigSet configs;
1084 for (GLenum colorBufferInternalFormat : colorBufferFormats)
1085 {
1086 const gl::TextureCaps &colorBufferFormatCaps =
1087 rendererTextureCaps.get(colorBufferInternalFormat);
1088 if (!colorBufferFormatCaps.renderable)
1089 {
1090 continue;
1091 }
1092
1093 for (GLenum depthStencilBufferInternalFormat : depthStencilBufferFormats)
1094 {
1095 const gl::TextureCaps &depthStencilBufferFormatCaps =
1096 rendererTextureCaps.get(depthStencilBufferInternalFormat);
1097 if (!depthStencilBufferFormatCaps.renderable &&
1098 depthStencilBufferInternalFormat != GL_NONE)
1099 {
1100 continue;
1101 }
1102
1103 const gl::InternalFormat &colorBufferFormatInfo =
1104 gl::GetSizedInternalFormatInfo(colorBufferInternalFormat);
1105 const gl::InternalFormat &depthStencilBufferFormatInfo =
1106 gl::GetSizedInternalFormatInfo(depthStencilBufferInternalFormat);
1107 const gl::Version &maxVersion = getMaxSupportedESVersion();
1108
1109 const gl::SupportedSampleSet sampleCounts =
1110 generateSampleSetForEGLConfig(colorBufferFormatCaps, depthStencilBufferFormatCaps);
1111
1112 for (GLuint sampleCount : sampleCounts)
1113 {
1114 egl::Config config;
1115 config.renderTargetFormat = colorBufferInternalFormat;
1116 config.depthStencilFormat = depthStencilBufferInternalFormat;
1117 config.bufferSize = colorBufferFormatInfo.pixelBytes * 8;
1118 config.redSize = colorBufferFormatInfo.redBits;
1119 config.greenSize = colorBufferFormatInfo.greenBits;
1120 config.blueSize = colorBufferFormatInfo.blueBits;
1121 config.luminanceSize = colorBufferFormatInfo.luminanceBits;
1122 config.alphaSize = colorBufferFormatInfo.alphaBits;
1123 config.alphaMaskSize = 0;
1124 config.bindToTextureRGB =
1125 ((colorBufferFormatInfo.format == GL_RGB) && (sampleCount <= 1));
1126 config.bindToTextureRGBA = (((colorBufferFormatInfo.format == GL_RGBA) ||
1127 (colorBufferFormatInfo.format == GL_BGRA_EXT)) &&
1128 (sampleCount <= 1));
1129 config.colorBufferType = EGL_RGB_BUFFER;
1130 config.configCaveat = EGL_NONE;
1131 config.configID = static_cast<EGLint>(configs.size() + 1);
1132
1133 // PresentPathFast may not be conformant
1134 config.conformant = 0;
1135 if (!mPresentPathFastEnabled)
1136 {
1137 // Can only support a conformant ES2 with feature level greater than 10.0.
1138 if (mRenderer11DeviceCaps.featureLevel >= D3D_FEATURE_LEVEL_10_0)
1139 {
1140 config.conformant |= EGL_OPENGL_ES2_BIT;
1141 }
1142
1143 // We can only support conformant ES3 on FL 10.1+
1144 if (maxVersion.major >= 3)
1145 {
1146 config.conformant |= EGL_OPENGL_ES3_BIT_KHR;
1147 }
1148 }
1149
1150 config.depthSize = depthStencilBufferFormatInfo.depthBits;
1151 config.level = 0;
1152 config.matchNativePixmap = EGL_NONE;
1153 config.maxPBufferWidth = rendererCaps.max2DTextureSize;
1154 config.maxPBufferHeight = rendererCaps.max2DTextureSize;
1155 config.maxPBufferPixels =
1156 rendererCaps.max2DTextureSize * rendererCaps.max2DTextureSize;
1157 config.maxSwapInterval = 4;
1158 config.minSwapInterval = 0;
1159 config.nativeRenderable = EGL_FALSE;
1160 config.nativeVisualID = 0;
1161 config.nativeVisualType = EGL_NONE;
1162
1163 // Can't support ES3 at all without feature level 10.1
1164 config.renderableType = EGL_OPENGL_ES2_BIT;
1165 if (maxVersion.major >= 3)
1166 {
1167 config.renderableType |= EGL_OPENGL_ES3_BIT_KHR;
1168 }
1169
1170 config.sampleBuffers = (sampleCount == 0) ? 0 : 1;
1171 config.samples = sampleCount;
1172 config.stencilSize = depthStencilBufferFormatInfo.stencilBits;
1173 config.surfaceType =
1174 EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
1175 config.transparentType = EGL_NONE;
1176 config.transparentRedValue = 0;
1177 config.transparentGreenValue = 0;
1178 config.transparentBlueValue = 0;
1179 config.optimalOrientation = optimalSurfaceOrientation;
1180 config.colorComponentType = gl_egl::GLComponentTypeToEGLColorComponentType(
1181 colorBufferFormatInfo.componentType);
1182
1183 configs.add(config);
1184 }
1185 }
1186 }
1187
1188 ASSERT(configs.size() > 0);
1189 return configs;
1190 }
1191
generateDisplayExtensions(egl::DisplayExtensions * outExtensions) const1192 void Renderer11::generateDisplayExtensions(egl::DisplayExtensions *outExtensions) const
1193 {
1194 outExtensions->createContextRobustness = true;
1195
1196 if (getShareHandleSupport())
1197 {
1198 outExtensions->d3dShareHandleClientBuffer = true;
1199 outExtensions->surfaceD3DTexture2DShareHandle = true;
1200 }
1201 outExtensions->d3dTextureClientBuffer = true;
1202
1203 outExtensions->keyedMutex = true;
1204 outExtensions->querySurfacePointer = true;
1205 outExtensions->windowFixedSize = true;
1206
1207 // If present path fast is active then the surface orientation extension isn't supported
1208 outExtensions->surfaceOrientation = !mPresentPathFastEnabled;
1209
1210 // D3D11 does not support present with dirty rectangles until DXGI 1.2.
1211 outExtensions->postSubBuffer = mRenderer11DeviceCaps.supportsDXGI1_2;
1212
1213 outExtensions->deviceQuery = true;
1214
1215 outExtensions->image = true;
1216 outExtensions->imageBase = true;
1217 outExtensions->glTexture2DImage = true;
1218 outExtensions->glTextureCubemapImage = true;
1219 outExtensions->glRenderbufferImage = true;
1220
1221 outExtensions->stream = true;
1222 outExtensions->streamConsumerGLTexture = true;
1223 outExtensions->streamConsumerGLTextureYUV = true;
1224 // Not all D3D11 devices support NV12 textures
1225 if (getNV12TextureSupport())
1226 {
1227 outExtensions->streamProducerD3DTextureNV12 = true;
1228 }
1229
1230 outExtensions->flexibleSurfaceCompatibility = true;
1231 outExtensions->directComposition = !!mDCompModule;
1232
1233 // Contexts are virtualized so textures can be shared globally
1234 outExtensions->displayTextureShareGroup = true;
1235
1236 // getSyncValues requires direct composition.
1237 outExtensions->getSyncValues = outExtensions->directComposition;
1238
1239 // D3D11 can be used without a swap chain
1240 outExtensions->surfacelessContext = true;
1241
1242 // All D3D feature levels support robust resource init
1243 outExtensions->robustResourceInitialization = true;
1244 }
1245
flush()1246 gl::Error Renderer11::flush()
1247 {
1248 mDeviceContext->Flush();
1249 return gl::NoError();
1250 }
1251
finish()1252 gl::Error Renderer11::finish()
1253 {
1254 if (!mSyncQuery.valid())
1255 {
1256 D3D11_QUERY_DESC queryDesc;
1257 queryDesc.Query = D3D11_QUERY_EVENT;
1258 queryDesc.MiscFlags = 0;
1259
1260 ANGLE_TRY(allocateResource(queryDesc, &mSyncQuery));
1261 }
1262
1263 mDeviceContext->End(mSyncQuery.get());
1264
1265 HRESULT result = S_OK;
1266 unsigned int attempt = 0;
1267 do
1268 {
1269 unsigned int flushFrequency = 100;
1270 UINT flags = (attempt % flushFrequency == 0) ? 0 : D3D11_ASYNC_GETDATA_DONOTFLUSH;
1271 attempt++;
1272
1273 result = mDeviceContext->GetData(mSyncQuery.get(), nullptr, 0, flags);
1274 if (FAILED(result))
1275 {
1276 return gl::OutOfMemory() << "Failed to get event query data, " << gl::FmtHR(result);
1277 }
1278
1279 if (result == S_FALSE)
1280 {
1281 // Keep polling, but allow other threads to do something useful first
1282 ScheduleYield();
1283 }
1284
1285 if (testDeviceLost())
1286 {
1287 mDisplay->notifyDeviceLost();
1288 return gl::OutOfMemory() << "Device was lost while waiting for sync.";
1289 }
1290 } while (result == S_FALSE);
1291
1292 return gl::NoError();
1293 }
1294
isValidNativeWindow(EGLNativeWindowType window) const1295 bool Renderer11::isValidNativeWindow(EGLNativeWindowType window) const
1296 {
1297 #ifdef ANGLE_ENABLE_WINDOWS_STORE
1298 return NativeWindow11WinRT::IsValidNativeWindow(window);
1299 #else
1300 return NativeWindow11Win32::IsValidNativeWindow(window);
1301 #endif
1302 }
1303
createNativeWindow(EGLNativeWindowType window,const egl::Config * config,const egl::AttributeMap & attribs) const1304 NativeWindowD3D *Renderer11::createNativeWindow(EGLNativeWindowType window,
1305 const egl::Config *config,
1306 const egl::AttributeMap &attribs) const
1307 {
1308 #ifdef ANGLE_ENABLE_WINDOWS_STORE
1309 UNUSED_VARIABLE(attribs);
1310 return new NativeWindow11WinRT(window, config->alphaSize > 0);
1311 #else
1312 return new NativeWindow11Win32(
1313 window, config->alphaSize > 0,
1314 attribs.get(EGL_DIRECT_COMPOSITION_ANGLE, EGL_FALSE) == EGL_TRUE);
1315 #endif
1316 }
1317
getD3DTextureInfo(const egl::Config * configuration,IUnknown * d3dTexture,EGLint * width,EGLint * height,GLenum * fboFormat) const1318 egl::Error Renderer11::getD3DTextureInfo(const egl::Config *configuration,
1319 IUnknown *d3dTexture,
1320 EGLint *width,
1321 EGLint *height,
1322 GLenum *fboFormat) const
1323 {
1324 ID3D11Texture2D *texture = d3d11::DynamicCastComObject<ID3D11Texture2D>(d3dTexture);
1325 if (texture == nullptr)
1326 {
1327 return egl::EglBadParameter() << "client buffer is not a ID3D11Texture2D";
1328 }
1329
1330 ID3D11Device *textureDevice = nullptr;
1331 texture->GetDevice(&textureDevice);
1332 if (textureDevice != mDevice)
1333 {
1334 SafeRelease(texture);
1335 return egl::EglBadParameter() << "Texture's device does not match.";
1336 }
1337 SafeRelease(textureDevice);
1338
1339 D3D11_TEXTURE2D_DESC desc = {0};
1340 texture->GetDesc(&desc);
1341 SafeRelease(texture);
1342
1343 if (width)
1344 {
1345 *width = static_cast<EGLint>(desc.Width);
1346 }
1347 if (height)
1348 {
1349 *height = static_cast<EGLint>(desc.Height);
1350 }
1351 if (static_cast<EGLint>(desc.SampleDesc.Count) != configuration->samples)
1352 {
1353 // Both the texture and EGL config sample count may not be the same when multi-sampling
1354 // is disabled. The EGL sample count can be 0 but a D3D texture is always 1. Therefore,
1355 // we must only check for a invalid match when the EGL config is non-zero or the texture is
1356 // not one.
1357 if (configuration->samples != 0 || desc.SampleDesc.Count != 1)
1358 {
1359 return egl::EglBadParameter() << "Texture's sample count does not match.";
1360 }
1361 }
1362 // From table egl.restrictions in EGL_ANGLE_d3d_texture_client_buffer.
1363 switch (desc.Format)
1364 {
1365 case DXGI_FORMAT_R8G8B8A8_UNORM:
1366 case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
1367 case DXGI_FORMAT_B8G8R8A8_UNORM:
1368 case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
1369 case DXGI_FORMAT_R16G16B16A16_FLOAT:
1370 case DXGI_FORMAT_R32G32B32A32_FLOAT:
1371 break;
1372
1373 default:
1374 return egl::EglBadParameter()
1375 << "Unknown client buffer texture format: " << desc.Format;
1376 }
1377
1378 if (fboFormat)
1379 {
1380 const angle::Format &angleFormat = d3d11_angle::GetFormat(desc.Format);
1381 *fboFormat = angleFormat.fboImplementationInternalFormat;
1382 }
1383
1384 return egl::NoError();
1385 }
1386
validateShareHandle(const egl::Config * config,HANDLE shareHandle,const egl::AttributeMap & attribs) const1387 egl::Error Renderer11::validateShareHandle(const egl::Config *config,
1388 HANDLE shareHandle,
1389 const egl::AttributeMap &attribs) const
1390 {
1391 if (shareHandle == nullptr)
1392 {
1393 return egl::EglBadParameter() << "NULL share handle.";
1394 }
1395
1396 ID3D11Resource *tempResource11 = nullptr;
1397 HRESULT result = mDevice->OpenSharedResource(shareHandle, __uuidof(ID3D11Resource),
1398 (void **)&tempResource11);
1399 if (FAILED(result))
1400 {
1401 return egl::EglBadParameter() << "Failed to open share handle, " << gl::FmtHR(result);
1402 }
1403
1404 ID3D11Texture2D *texture2D = d3d11::DynamicCastComObject<ID3D11Texture2D>(tempResource11);
1405 SafeRelease(tempResource11);
1406
1407 if (texture2D == nullptr)
1408 {
1409 return egl::EglBadParameter()
1410 << "Failed to query ID3D11Texture2D object from share handle.";
1411 }
1412
1413 D3D11_TEXTURE2D_DESC desc = {0};
1414 texture2D->GetDesc(&desc);
1415 SafeRelease(texture2D);
1416
1417 EGLint width = attribs.getAsInt(EGL_WIDTH, 0);
1418 EGLint height = attribs.getAsInt(EGL_HEIGHT, 0);
1419 ASSERT(width != 0 && height != 0);
1420
1421 const d3d11::Format &backbufferFormatInfo =
1422 d3d11::Format::Get(config->renderTargetFormat, getRenderer11DeviceCaps());
1423
1424 if (desc.Width != static_cast<UINT>(width) || desc.Height != static_cast<UINT>(height) ||
1425 desc.Format != backbufferFormatInfo.texFormat || desc.MipLevels != 1 || desc.ArraySize != 1)
1426 {
1427 return egl::EglBadParameter() << "Invalid texture parameters in share handle texture.";
1428 }
1429
1430 return egl::NoError();
1431 }
1432
createSwapChain(NativeWindowD3D * nativeWindow,HANDLE shareHandle,IUnknown * d3dTexture,GLenum backBufferFormat,GLenum depthBufferFormat,EGLint orientation,EGLint samples)1433 SwapChainD3D *Renderer11::createSwapChain(NativeWindowD3D *nativeWindow,
1434 HANDLE shareHandle,
1435 IUnknown *d3dTexture,
1436 GLenum backBufferFormat,
1437 GLenum depthBufferFormat,
1438 EGLint orientation,
1439 EGLint samples)
1440 {
1441 return new SwapChain11(this, GetAs<NativeWindow11>(nativeWindow), shareHandle, d3dTexture,
1442 backBufferFormat, depthBufferFormat, orientation, samples);
1443 }
1444
getD3DDevice()1445 void *Renderer11::getD3DDevice()
1446 {
1447 return reinterpret_cast<void *>(mDevice);
1448 }
1449
applyPrimitiveType(const gl::State & glState,GLenum mode,GLsizei count)1450 bool Renderer11::applyPrimitiveType(const gl::State &glState, GLenum mode, GLsizei count)
1451 {
1452 D3D11_PRIMITIVE_TOPOLOGY primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
1453
1454 GLsizei minCount = 0;
1455
1456 switch (mode)
1457 {
1458 case GL_POINTS:
1459 {
1460 bool usesPointSize = GetImplAs<ProgramD3D>(glState.getProgram())->usesPointSize();
1461
1462 // ProgramBinary assumes non-point rendering if gl_PointSize isn't written,
1463 // which affects varying interpolation. Since the value of gl_PointSize is
1464 // undefined when not written, just skip drawing to avoid unexpected results.
1465 if (!usesPointSize && !glState.isTransformFeedbackActiveUnpaused())
1466 {
1467 // Notify developers of risking undefined behavior.
1468 WARN() << "Point rendering without writing to gl_PointSize.";
1469 return false;
1470 }
1471
1472 // If instanced pointsprites are enabled and the shader uses gl_PointSize, the topology
1473 // must be D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST.
1474 if (usesPointSize && getWorkarounds().useInstancedPointSpriteEmulation)
1475 {
1476 primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
1477 }
1478 else
1479 {
1480 primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST;
1481 }
1482 minCount = 1;
1483 break;
1484 }
1485 case GL_LINES:
1486 primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINELIST;
1487 minCount = 2;
1488 break;
1489 case GL_LINE_LOOP:
1490 primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP;
1491 minCount = 2;
1492 break;
1493 case GL_LINE_STRIP:
1494 primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP;
1495 minCount = 2;
1496 break;
1497 case GL_TRIANGLES:
1498 primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
1499 minCount = CullsEverything(glState) ? std::numeric_limits<GLsizei>::max() : 3;
1500 break;
1501 case GL_TRIANGLE_STRIP:
1502 primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
1503 minCount = CullsEverything(glState) ? std::numeric_limits<GLsizei>::max() : 3;
1504 break;
1505 // emulate fans via rewriting index buffer
1506 case GL_TRIANGLE_FAN:
1507 primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
1508 minCount = CullsEverything(glState) ? std::numeric_limits<GLsizei>::max() : 3;
1509 break;
1510 default:
1511 UNREACHABLE();
1512 return false;
1513 }
1514
1515 mStateManager.setPrimitiveTopology(primitiveTopology);
1516
1517 return count >= minCount;
1518 }
1519
drawArrays(const gl::Context * context,GLenum mode,GLint startVertex,GLsizei count,GLsizei instances)1520 gl::Error Renderer11::drawArrays(const gl::Context *context,
1521 GLenum mode,
1522 GLint startVertex,
1523 GLsizei count,
1524 GLsizei instances)
1525 {
1526 const auto &glState = context->getGLState();
1527
1528 if (!applyPrimitiveType(glState, mode, count))
1529 {
1530 return gl::NoError();
1531 }
1532
1533 DrawCallVertexParams vertexParams(startVertex, count, instances);
1534 ANGLE_TRY(mStateManager.applyVertexBuffer(context, mode, vertexParams, false));
1535
1536 if (glState.isTransformFeedbackActiveUnpaused())
1537 {
1538 ANGLE_TRY(markTransformFeedbackUsage(context));
1539 }
1540
1541 gl::Program *program = glState.getProgram();
1542 ASSERT(program != nullptr);
1543 GLsizei adjustedInstanceCount = GetAdjustedInstanceCount(program, instances);
1544 ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
1545
1546 if (programD3D->usesGeometryShader(mode) && glState.isTransformFeedbackActiveUnpaused())
1547 {
1548 // Since we use a geometry if-and-only-if we rewrite vertex streams, transform feedback
1549 // won't get the correct output. To work around this, draw with *only* the stream out
1550 // first (no pixel shader) to feed the stream out buffers and then draw again with the
1551 // geometry shader + pixel shader to rasterize the primitives.
1552 mStateManager.setPixelShader(nullptr);
1553
1554 if (adjustedInstanceCount > 0)
1555 {
1556 mDeviceContext->DrawInstanced(count, adjustedInstanceCount, 0, 0);
1557 }
1558 else
1559 {
1560 mDeviceContext->Draw(count, 0);
1561 }
1562
1563 rx::ShaderExecutableD3D *pixelExe = nullptr;
1564 ANGLE_TRY(programD3D->getPixelExecutableForCachedOutputLayout(&pixelExe, nullptr));
1565
1566 // Skip the draw call if rasterizer discard is enabled (or no fragment shader).
1567 if (!pixelExe || glState.getRasterizerState().rasterizerDiscard)
1568 {
1569 return gl::NoError();
1570 }
1571
1572 mStateManager.setPixelShader(&GetAs<ShaderExecutable11>(pixelExe)->getPixelShader());
1573
1574 // Retrieve the geometry shader.
1575 rx::ShaderExecutableD3D *geometryExe = nullptr;
1576 ANGLE_TRY(programD3D->getGeometryExecutableForPrimitiveType(context, mode, &geometryExe,
1577 nullptr));
1578
1579 mStateManager.setGeometryShader(
1580 &GetAs<ShaderExecutable11>(geometryExe)->getGeometryShader());
1581
1582 if (adjustedInstanceCount > 0)
1583 {
1584 mDeviceContext->DrawInstanced(count, adjustedInstanceCount, 0, 0);
1585 }
1586 else
1587 {
1588 mDeviceContext->Draw(count, 0);
1589 }
1590 return gl::NoError();
1591 }
1592
1593 if (mode == GL_LINE_LOOP)
1594 {
1595 return drawLineLoop(context, count, GL_NONE, nullptr, 0, adjustedInstanceCount);
1596 }
1597
1598 if (mode == GL_TRIANGLE_FAN)
1599 {
1600 return drawTriangleFan(context, count, GL_NONE, nullptr, 0, adjustedInstanceCount);
1601 }
1602
1603 bool useInstancedPointSpriteEmulation =
1604 programD3D->usesPointSize() && getWorkarounds().useInstancedPointSpriteEmulation;
1605
1606 if (mode != GL_POINTS || !useInstancedPointSpriteEmulation)
1607 {
1608 if (adjustedInstanceCount == 0)
1609 {
1610 mDeviceContext->Draw(count, 0);
1611 }
1612 else
1613 {
1614 mDeviceContext->DrawInstanced(count, adjustedInstanceCount, 0, 0);
1615 }
1616 return gl::NoError();
1617 }
1618
1619 // This code should not be reachable by multi-view programs.
1620 ASSERT(program->usesMultiview() == false);
1621
1622 // If the shader is writing to gl_PointSize, then pointsprites are being rendered.
1623 // Emulating instanced point sprites for FL9_3 requires the topology to be
1624 // D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST and DrawIndexedInstanced is called instead.
1625 if (adjustedInstanceCount == 0)
1626 {
1627 mDeviceContext->DrawIndexedInstanced(6, count, 0, 0, 0);
1628 return gl::NoError();
1629 }
1630
1631 // If pointsprite emulation is used with glDrawArraysInstanced then we need to take a less
1632 // efficent code path. Instanced rendering of emulated pointsprites requires a loop to draw each
1633 // batch of points. An offset into the instanced data buffer is calculated and applied on each
1634 // iteration to ensure all instances are rendered correctly. Each instance being rendered
1635 // requires the inputlayout cache to reapply buffers and offsets.
1636 for (GLsizei i = 0; i < instances; i++)
1637 {
1638 ANGLE_TRY(mStateManager.updateVertexOffsetsForPointSpritesEmulation(startVertex, i));
1639 mDeviceContext->DrawIndexedInstanced(6, count, 0, 0, 0);
1640 }
1641
1642 // This required by updateVertexOffsets... above but is outside of the loop for speed.
1643 mStateManager.invalidateVertexBuffer();
1644 return gl::NoError();
1645 }
1646
drawElements(const gl::Context * context,GLenum mode,GLsizei count,GLenum type,const void * indices,GLsizei instances)1647 gl::Error Renderer11::drawElements(const gl::Context *context,
1648 GLenum mode,
1649 GLsizei count,
1650 GLenum type,
1651 const void *indices,
1652 GLsizei instances)
1653 {
1654 const auto &glState = context->getGLState();
1655
1656 if (!applyPrimitiveType(glState, mode, count))
1657 {
1658 return gl::NoError();
1659 }
1660
1661 // Transform feedback is not allowed for DrawElements, this error should have been caught at the
1662 // API validation layer.
1663 ASSERT(!glState.isTransformFeedbackActiveUnpaused());
1664
1665 const auto &lazyIndexRange = context->getParams<gl::HasIndexRange>();
1666
1667 bool usePrimitiveRestartWorkaround =
1668 UsePrimitiveRestartWorkaround(glState.isPrimitiveRestartEnabled(), type);
1669 DrawCallVertexParams vertexParams(!usePrimitiveRestartWorkaround, lazyIndexRange, 0, instances);
1670
1671 ANGLE_TRY(mStateManager.applyIndexBuffer(context, indices, count, type, lazyIndexRange,
1672 usePrimitiveRestartWorkaround));
1673 ANGLE_TRY(mStateManager.applyVertexBuffer(context, mode, vertexParams, true));
1674
1675 int startVertex = static_cast<int>(vertexParams.firstVertex());
1676 int baseVertex = -startVertex;
1677
1678 const gl::Program *program = glState.getProgram();
1679 GLsizei adjustedInstanceCount = GetAdjustedInstanceCount(program, instances);
1680
1681 if (mode == GL_LINE_LOOP)
1682 {
1683 return drawLineLoop(context, count, type, indices, baseVertex, adjustedInstanceCount);
1684 }
1685
1686 if (mode == GL_TRIANGLE_FAN)
1687 {
1688 return drawTriangleFan(context, count, type, indices, baseVertex, adjustedInstanceCount);
1689 }
1690
1691 const ProgramD3D *programD3D = GetImplAs<ProgramD3D>(glState.getProgram());
1692
1693 if (mode != GL_POINTS || !programD3D->usesInstancedPointSpriteEmulation())
1694 {
1695 if (adjustedInstanceCount == 0)
1696 {
1697 mDeviceContext->DrawIndexed(count, 0, baseVertex);
1698 }
1699 else
1700 {
1701 mDeviceContext->DrawIndexedInstanced(count, adjustedInstanceCount, 0, baseVertex, 0);
1702 }
1703 return gl::NoError();
1704 }
1705
1706 // This code should not be reachable by multi-view programs.
1707 ASSERT(program->usesMultiview() == false);
1708
1709 // If the shader is writing to gl_PointSize, then pointsprites are being rendered.
1710 // Emulating instanced point sprites for FL9_3 requires the topology to be
1711 // D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST and DrawIndexedInstanced is called instead.
1712 //
1713 // The count parameter passed to drawElements represents the total number of instances to be
1714 // rendered. Each instance is referenced by the bound index buffer from the the caller.
1715 //
1716 // Indexed pointsprite emulation replicates data for duplicate entries found in the index
1717 // buffer. This is not an efficent rendering mechanism and is only used on downlevel renderers
1718 // that do not support geometry shaders.
1719 if (instances == 0)
1720 {
1721 mDeviceContext->DrawIndexedInstanced(6, count, 0, 0, 0);
1722 return gl::NoError();
1723 }
1724
1725 // If pointsprite emulation is used with glDrawElementsInstanced then we need to take a less
1726 // efficent code path. Instanced rendering of emulated pointsprites requires a loop to draw each
1727 // batch of points. An offset into the instanced data buffer is calculated and applied on each
1728 // iteration to ensure all instances are rendered correctly.
1729 GLsizei elementsToRender = vertexParams.vertexCount();
1730
1731 // Each instance being rendered requires the inputlayout cache to reapply buffers and offsets.
1732 for (GLsizei i = 0; i < instances; i++)
1733 {
1734 ANGLE_TRY(mStateManager.updateVertexOffsetsForPointSpritesEmulation(startVertex, i));
1735 mDeviceContext->DrawIndexedInstanced(6, elementsToRender, 0, 0, 0);
1736 }
1737 mStateManager.invalidateVertexBuffer();
1738 return gl::NoError();
1739 }
1740
drawArraysIndirect(const gl::Context * context,GLenum mode,const void * indirect)1741 gl::Error Renderer11::drawArraysIndirect(const gl::Context *context,
1742 GLenum mode,
1743 const void *indirect)
1744 {
1745 const auto &glState = context->getGLState();
1746 ASSERT(!glState.isTransformFeedbackActiveUnpaused());
1747
1748 if (!applyPrimitiveType(glState, mode, std::numeric_limits<int>::max() - 1))
1749 {
1750 return gl::NoError();
1751 }
1752
1753 gl::Buffer *drawIndirectBuffer = glState.getTargetBuffer(gl::BufferBinding::DrawIndirect);
1754 ASSERT(drawIndirectBuffer);
1755 Buffer11 *storage = GetImplAs<Buffer11>(drawIndirectBuffer);
1756 uintptr_t offset = reinterpret_cast<uintptr_t>(indirect);
1757
1758 if (!DrawCallNeedsTranslation(context, mode))
1759 {
1760 DrawCallVertexParams vertexParams(0, 0, 0);
1761 ANGLE_TRY(mStateManager.applyVertexBuffer(context, mode, vertexParams, false));
1762 ID3D11Buffer *buffer = nullptr;
1763 ANGLE_TRY_RESULT(storage->getBuffer(context, BUFFER_USAGE_INDIRECT), buffer);
1764 mDeviceContext->DrawInstancedIndirect(buffer, static_cast<unsigned int>(offset));
1765 return gl::NoError();
1766 }
1767
1768 const uint8_t *bufferData = nullptr;
1769 ANGLE_TRY(storage->getData(context, &bufferData));
1770 ASSERT(bufferData);
1771 const gl::DrawArraysIndirectCommand *args =
1772 reinterpret_cast<const gl::DrawArraysIndirectCommand *>(bufferData + offset);
1773 GLuint count = args->count;
1774 GLuint instances = args->instanceCount;
1775 GLuint first = args->first;
1776
1777 DrawCallVertexParams vertexParams(first, count, instances);
1778 ANGLE_TRY(mStateManager.applyVertexBuffer(context, mode, vertexParams, false));
1779
1780 if (mode == GL_LINE_LOOP)
1781 {
1782 return drawLineLoop(context, count, GL_NONE, nullptr, 0, instances);
1783 }
1784 if (mode == GL_TRIANGLE_FAN)
1785 {
1786 return drawTriangleFan(context, count, GL_NONE, nullptr, 0, instances);
1787 }
1788
1789 mDeviceContext->DrawInstanced(count, instances, 0, 0);
1790 return gl::NoError();
1791 }
1792
drawElementsIndirect(const gl::Context * context,GLenum mode,GLenum type,const void * indirect)1793 gl::Error Renderer11::drawElementsIndirect(const gl::Context *context,
1794 GLenum mode,
1795 GLenum type,
1796 const void *indirect)
1797 {
1798 const auto &glState = context->getGLState();
1799 ASSERT(!glState.isTransformFeedbackActiveUnpaused());
1800
1801 if (!applyPrimitiveType(glState, mode, std::numeric_limits<int>::max() - 1))
1802 {
1803 return gl::NoError();
1804 }
1805
1806 gl::Buffer *drawIndirectBuffer = glState.getTargetBuffer(gl::BufferBinding::DrawIndirect);
1807 ASSERT(drawIndirectBuffer);
1808 Buffer11 *storage = GetImplAs<Buffer11>(drawIndirectBuffer);
1809 uintptr_t offset = reinterpret_cast<uintptr_t>(indirect);
1810
1811 // TODO(jmadill): Remove the if statement and compute indirect parameters lazily.
1812 bool usePrimitiveRestartWorkaround =
1813 UsePrimitiveRestartWorkaround(glState.isPrimitiveRestartEnabled(), type);
1814
1815 if (!DrawCallNeedsTranslation(context, mode) && !IsStreamingIndexData(context, type))
1816 {
1817 ANGLE_TRY(mStateManager.applyIndexBuffer(context, nullptr, 0, type, gl::HasIndexRange(),
1818 usePrimitiveRestartWorkaround));
1819 DrawCallVertexParams vertexParams(0, 0, 0);
1820 ANGLE_TRY(mStateManager.applyVertexBuffer(context, mode, vertexParams, true));
1821 ID3D11Buffer *buffer = nullptr;
1822 ANGLE_TRY_RESULT(storage->getBuffer(context, BUFFER_USAGE_INDIRECT), buffer);
1823 mDeviceContext->DrawIndexedInstancedIndirect(buffer, static_cast<unsigned int>(offset));
1824 return gl::NoError();
1825 }
1826
1827 const uint8_t *bufferData = nullptr;
1828 ANGLE_TRY(storage->getData(context, &bufferData));
1829 ASSERT(bufferData);
1830
1831 const gl::DrawElementsIndirectCommand *cmd =
1832 reinterpret_cast<const gl::DrawElementsIndirectCommand *>(bufferData + offset);
1833 GLsizei count = cmd->count;
1834 GLuint instances = cmd->primCount;
1835 GLuint firstIndex = cmd->firstIndex;
1836 GLint baseVertex = cmd->baseVertex;
1837
1838 // TODO(jmadill): Fix const cast.
1839 const gl::Type &typeInfo = gl::GetTypeInfo(type);
1840 const void *indices =
1841 reinterpret_cast<const void *>(static_cast<uintptr_t>(firstIndex * typeInfo.bytes));
1842 gl::HasIndexRange lazyIndexRange(const_cast<gl::Context *>(context), count, type, indices);
1843
1844 ANGLE_TRY(mStateManager.applyIndexBuffer(context, indices, count, type, lazyIndexRange,
1845 usePrimitiveRestartWorkaround));
1846
1847 DrawCallVertexParams vertexParams(false, lazyIndexRange, baseVertex, instances);
1848
1849 ANGLE_TRY(mStateManager.applyVertexBuffer(context, mode, vertexParams, true));
1850
1851 int baseVertexLocation = -static_cast<int>(lazyIndexRange.getIndexRange().value().start);
1852
1853 if (mode == GL_LINE_LOOP)
1854 {
1855 return drawLineLoop(context, count, type, indices, baseVertexLocation, instances);
1856 }
1857
1858 if (mode == GL_TRIANGLE_FAN)
1859 {
1860 return drawTriangleFan(context, count, type, indices, baseVertexLocation, instances);
1861 }
1862
1863 mDeviceContext->DrawIndexedInstanced(count, instances, 0, baseVertexLocation, 0);
1864 return gl::NoError();
1865 }
1866
drawLineLoop(const gl::Context * context,GLsizei count,GLenum type,const void * indexPointer,int baseVertex,int instances)1867 gl::Error Renderer11::drawLineLoop(const gl::Context *context,
1868 GLsizei count,
1869 GLenum type,
1870 const void *indexPointer,
1871 int baseVertex,
1872 int instances)
1873 {
1874 const gl::State &glState = context->getGLState();
1875 gl::VertexArray *vao = glState.getVertexArray();
1876 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
1877
1878 const void *indices = indexPointer;
1879
1880 // Get the raw indices for an indexed draw
1881 if (type != GL_NONE && elementArrayBuffer)
1882 {
1883 BufferD3D *storage = GetImplAs<BufferD3D>(elementArrayBuffer);
1884 intptr_t offset = reinterpret_cast<intptr_t>(indices);
1885
1886 const uint8_t *bufferData = nullptr;
1887 ANGLE_TRY(storage->getData(context, &bufferData));
1888
1889 indices = bufferData + offset;
1890 }
1891
1892 if (!mLineLoopIB)
1893 {
1894 mLineLoopIB = new StreamingIndexBufferInterface(this);
1895 gl::Error error =
1896 mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT);
1897 if (error.isError())
1898 {
1899 SafeDelete(mLineLoopIB);
1900 return error;
1901 }
1902 }
1903
1904 // Checked by Renderer11::applyPrimitiveType
1905 ASSERT(count >= 0);
1906
1907 if (static_cast<unsigned int>(count) + 1 >
1908 (std::numeric_limits<unsigned int>::max() / sizeof(unsigned int)))
1909 {
1910 return gl::OutOfMemory() << "Failed to create a 32-bit looping index buffer for "
1911 "GL_LINE_LOOP, too many indices required.";
1912 }
1913
1914 GetLineLoopIndices(indices, type, static_cast<GLuint>(count),
1915 glState.isPrimitiveRestartEnabled(), &mScratchIndexDataBuffer);
1916
1917 unsigned int spaceNeeded =
1918 static_cast<unsigned int>(sizeof(GLuint) * mScratchIndexDataBuffer.size());
1919 ANGLE_TRY(mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT));
1920
1921 void *mappedMemory = nullptr;
1922 unsigned int offset;
1923 ANGLE_TRY(mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset));
1924
1925 // Copy over the converted index data.
1926 memcpy(mappedMemory, &mScratchIndexDataBuffer[0],
1927 sizeof(GLuint) * mScratchIndexDataBuffer.size());
1928
1929 ANGLE_TRY(mLineLoopIB->unmapBuffer());
1930
1931 IndexBuffer11 *indexBuffer = GetAs<IndexBuffer11>(mLineLoopIB->getIndexBuffer());
1932 const d3d11::Buffer &d3dIndexBuffer = indexBuffer->getBuffer();
1933 DXGI_FORMAT indexFormat = indexBuffer->getIndexFormat();
1934
1935 mStateManager.setIndexBuffer(d3dIndexBuffer.get(), indexFormat, offset);
1936
1937 UINT indexCount = static_cast<UINT>(mScratchIndexDataBuffer.size());
1938
1939 if (instances > 0)
1940 {
1941 mDeviceContext->DrawIndexedInstanced(indexCount, instances, 0, baseVertex, 0);
1942 }
1943 else
1944 {
1945 mDeviceContext->DrawIndexed(indexCount, 0, baseVertex);
1946 }
1947
1948 return gl::NoError();
1949 }
1950
drawTriangleFan(const gl::Context * context,GLsizei count,GLenum type,const void * indices,int baseVertex,int instances)1951 gl::Error Renderer11::drawTriangleFan(const gl::Context *context,
1952 GLsizei count,
1953 GLenum type,
1954 const void *indices,
1955 int baseVertex,
1956 int instances)
1957 {
1958 const gl::State &glState = context->getGLState();
1959 gl::VertexArray *vao = glState.getVertexArray();
1960 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
1961
1962 const void *indexPointer = indices;
1963
1964 // Get the raw indices for an indexed draw
1965 if (type != GL_NONE && elementArrayBuffer)
1966 {
1967 BufferD3D *storage = GetImplAs<BufferD3D>(elementArrayBuffer);
1968 intptr_t offset = reinterpret_cast<intptr_t>(indices);
1969
1970 const uint8_t *bufferData = nullptr;
1971 ANGLE_TRY(storage->getData(context, &bufferData));
1972
1973 indexPointer = bufferData + offset;
1974 }
1975
1976 if (!mTriangleFanIB)
1977 {
1978 mTriangleFanIB = new StreamingIndexBufferInterface(this);
1979 gl::Error error =
1980 mTriangleFanIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT);
1981 if (error.isError())
1982 {
1983 SafeDelete(mTriangleFanIB);
1984 return error;
1985 }
1986 }
1987
1988 // Checked by Renderer11::applyPrimitiveType
1989 ASSERT(count >= 3);
1990
1991 const GLuint numTris = count - 2;
1992
1993 if (numTris > (std::numeric_limits<unsigned int>::max() / (sizeof(unsigned int) * 3)))
1994 {
1995 return gl::OutOfMemory() << "Failed to create a scratch index buffer for GL_TRIANGLE_FAN, "
1996 "too many indices required.";
1997 }
1998
1999 GetTriFanIndices(indexPointer, type, count, glState.isPrimitiveRestartEnabled(),
2000 &mScratchIndexDataBuffer);
2001
2002 const unsigned int spaceNeeded =
2003 static_cast<unsigned int>(mScratchIndexDataBuffer.size() * sizeof(unsigned int));
2004 ANGLE_TRY(mTriangleFanIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT));
2005
2006 void *mappedMemory = nullptr;
2007 unsigned int offset;
2008 ANGLE_TRY(mTriangleFanIB->mapBuffer(spaceNeeded, &mappedMemory, &offset));
2009
2010 memcpy(mappedMemory, &mScratchIndexDataBuffer[0], spaceNeeded);
2011
2012 ANGLE_TRY(mTriangleFanIB->unmapBuffer());
2013
2014 IndexBuffer11 *indexBuffer = GetAs<IndexBuffer11>(mTriangleFanIB->getIndexBuffer());
2015 const d3d11::Buffer &d3dIndexBuffer = indexBuffer->getBuffer();
2016 DXGI_FORMAT indexFormat = indexBuffer->getIndexFormat();
2017
2018 mStateManager.setIndexBuffer(d3dIndexBuffer.get(), indexFormat, offset);
2019
2020 UINT indexCount = static_cast<UINT>(mScratchIndexDataBuffer.size());
2021
2022 if (instances > 0)
2023 {
2024 mDeviceContext->DrawIndexedInstanced(indexCount, instances, 0, baseVertex, 0);
2025 }
2026 else
2027 {
2028 mDeviceContext->DrawIndexed(indexCount, 0, baseVertex);
2029 }
2030
2031 return gl::NoError();
2032 }
2033
releaseDeviceResources()2034 void Renderer11::releaseDeviceResources()
2035 {
2036 mStateManager.deinitialize();
2037 mStateCache.clear();
2038
2039 SafeDelete(mLineLoopIB);
2040 SafeDelete(mTriangleFanIB);
2041 SafeDelete(mBlit);
2042 SafeDelete(mClear);
2043 SafeDelete(mTrim);
2044 SafeDelete(mPixelTransfer);
2045
2046 mSyncQuery.reset();
2047
2048 mCachedResolveTexture.reset();
2049 }
2050
2051 // set notify to true to broadcast a message to all contexts of the device loss
testDeviceLost()2052 bool Renderer11::testDeviceLost()
2053 {
2054 bool isLost = false;
2055
2056 if (!mDevice)
2057 {
2058 return true;
2059 }
2060
2061 // GetRemovedReason is used to test if the device is removed
2062 HRESULT result = mDevice->GetDeviceRemovedReason();
2063 isLost = d3d11::isDeviceLostError(result);
2064
2065 if (isLost)
2066 {
2067 ERR() << "The D3D11 device was removed, " << gl::FmtHR(result);
2068 }
2069
2070 return isLost;
2071 }
2072
testDeviceResettable()2073 bool Renderer11::testDeviceResettable()
2074 {
2075 // determine if the device is resettable by creating a dummy device
2076 PFN_D3D11_CREATE_DEVICE D3D11CreateDevice =
2077 (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice");
2078
2079 if (D3D11CreateDevice == nullptr)
2080 {
2081 return false;
2082 }
2083
2084 ID3D11Device *dummyDevice;
2085 D3D_FEATURE_LEVEL dummyFeatureLevel;
2086 ID3D11DeviceContext *dummyContext;
2087 UINT flags = (mCreateDebugDevice ? D3D11_CREATE_DEVICE_DEBUG : 0);
2088
2089 ASSERT(mRequestedDriverType != D3D_DRIVER_TYPE_UNKNOWN);
2090 HRESULT result = D3D11CreateDevice(
2091 nullptr, mRequestedDriverType, nullptr, flags, mAvailableFeatureLevels.data(),
2092 static_cast<unsigned int>(mAvailableFeatureLevels.size()), D3D11_SDK_VERSION, &dummyDevice,
2093 &dummyFeatureLevel, &dummyContext);
2094
2095 if (!mDevice || FAILED(result))
2096 {
2097 return false;
2098 }
2099
2100 SafeRelease(dummyContext);
2101 SafeRelease(dummyDevice);
2102
2103 return true;
2104 }
2105
release()2106 void Renderer11::release()
2107 {
2108 RendererD3D::cleanup();
2109
2110 mScratchMemoryBuffer.clear();
2111
2112 if (mAnnotator != nullptr)
2113 {
2114 gl::UninitializeDebugAnnotations();
2115 SafeDelete(mAnnotator);
2116 }
2117
2118 releaseDeviceResources();
2119
2120 if (!mCreatedWithDeviceEXT)
2121 {
2122 // Only delete the device if the Renderer11 owns it
2123 // Otherwise we should keep it around in case we try to reinitialize the renderer later
2124 SafeDelete(mEGLDevice);
2125 }
2126
2127 SafeRelease(mDxgiFactory);
2128 SafeRelease(mDxgiAdapter);
2129
2130 SafeRelease(mDeviceContext3);
2131 SafeRelease(mDeviceContext1);
2132
2133 if (mDeviceContext)
2134 {
2135 mDeviceContext->ClearState();
2136 mDeviceContext->Flush();
2137 SafeRelease(mDeviceContext);
2138 }
2139
2140 SafeRelease(mDevice);
2141 SafeRelease(mDebug);
2142
2143 if (mD3d11Module)
2144 {
2145 FreeLibrary(mD3d11Module);
2146 mD3d11Module = nullptr;
2147 }
2148
2149 if (mDxgiModule)
2150 {
2151 FreeLibrary(mDxgiModule);
2152 mDxgiModule = nullptr;
2153 }
2154
2155 if (mDCompModule)
2156 {
2157 FreeLibrary(mDCompModule);
2158 mDCompModule = nullptr;
2159 }
2160
2161 mCompiler.release();
2162
2163 mSupportsShareHandles.reset();
2164 }
2165
resetDevice()2166 bool Renderer11::resetDevice()
2167 {
2168 // recreate everything
2169 release();
2170 egl::Error result = initialize();
2171
2172 if (result.isError())
2173 {
2174 ERR() << "Could not reinitialize D3D11 device: " << result;
2175 return false;
2176 }
2177
2178 return true;
2179 }
2180
getRendererDescription() const2181 std::string Renderer11::getRendererDescription() const
2182 {
2183 std::ostringstream rendererString;
2184
2185 rendererString << mDescription;
2186 rendererString << " Direct3D11";
2187
2188 rendererString << " vs_" << getMajorShaderModel() << "_" << getMinorShaderModel()
2189 << getShaderModelSuffix();
2190 rendererString << " ps_" << getMajorShaderModel() << "_" << getMinorShaderModel()
2191 << getShaderModelSuffix();
2192
2193 return rendererString.str();
2194 }
2195
getAdapterIdentifier() const2196 DeviceIdentifier Renderer11::getAdapterIdentifier() const
2197 {
2198 // Don't use the AdapterLuid here, since that doesn't persist across reboot.
2199 DeviceIdentifier deviceIdentifier = {0};
2200 deviceIdentifier.VendorId = mAdapterDescription.VendorId;
2201 deviceIdentifier.DeviceId = mAdapterDescription.DeviceId;
2202 deviceIdentifier.SubSysId = mAdapterDescription.SubSysId;
2203 deviceIdentifier.Revision = mAdapterDescription.Revision;
2204 deviceIdentifier.FeatureLevel = static_cast<UINT>(mRenderer11DeviceCaps.featureLevel);
2205
2206 return deviceIdentifier;
2207 }
2208
getReservedVertexUniformVectors() const2209 unsigned int Renderer11::getReservedVertexUniformVectors() const
2210 {
2211 // Driver uniforms are stored in a separate constant buffer
2212 return d3d11_gl::GetReservedVertexUniformVectors(mRenderer11DeviceCaps.featureLevel);
2213 }
2214
getReservedFragmentUniformVectors() const2215 unsigned int Renderer11::getReservedFragmentUniformVectors() const
2216 {
2217 // Driver uniforms are stored in a separate constant buffer
2218 return d3d11_gl::GetReservedFragmentUniformVectors(mRenderer11DeviceCaps.featureLevel);
2219 }
2220
getReservedVertexUniformBuffers() const2221 unsigned int Renderer11::getReservedVertexUniformBuffers() const
2222 {
2223 // we reserve one buffer for the application uniforms, and one for driver uniforms
2224 return 2;
2225 }
2226
getReservedFragmentUniformBuffers() const2227 unsigned int Renderer11::getReservedFragmentUniformBuffers() const
2228 {
2229 // we reserve one buffer for the application uniforms, and one for driver uniforms
2230 return 2;
2231 }
2232
getDeviceType() const2233 d3d11::ANGLED3D11DeviceType Renderer11::getDeviceType() const
2234 {
2235 if (mCreatedWithDeviceEXT)
2236 {
2237 return d3d11::GetDeviceType(mDevice);
2238 }
2239
2240 if ((mRequestedDriverType == D3D_DRIVER_TYPE_SOFTWARE) ||
2241 (mRequestedDriverType == D3D_DRIVER_TYPE_REFERENCE) ||
2242 (mRequestedDriverType == D3D_DRIVER_TYPE_NULL))
2243 {
2244 return d3d11::ANGLE_D3D11_DEVICE_TYPE_SOFTWARE_REF_OR_NULL;
2245 }
2246
2247 if (mRequestedDriverType == D3D_DRIVER_TYPE_WARP)
2248 {
2249 return d3d11::ANGLE_D3D11_DEVICE_TYPE_WARP;
2250 }
2251
2252 return d3d11::ANGLE_D3D11_DEVICE_TYPE_HARDWARE;
2253 }
2254
getShareHandleSupport() const2255 bool Renderer11::getShareHandleSupport() const
2256 {
2257 if (mSupportsShareHandles.valid())
2258 {
2259 return mSupportsShareHandles.value();
2260 }
2261
2262 // We only currently support share handles with BGRA surfaces, because
2263 // chrome needs BGRA. Once chrome fixes this, we should always support them.
2264 if (!getNativeExtensions().textureFormatBGRA8888)
2265 {
2266 mSupportsShareHandles = false;
2267 return false;
2268 }
2269
2270 // PIX doesn't seem to support using share handles, so disable them.
2271 if (gl::DebugAnnotationsActive())
2272 {
2273 mSupportsShareHandles = false;
2274 return false;
2275 }
2276
2277 // Qt: we don't care about the 9_3 limitation
2278 #if 0
2279 // Also disable share handles on Feature Level 9_3, since it doesn't support share handles on
2280 // RGBA8 textures/swapchains.
2281 if (mRenderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3)
2282 {
2283 mSupportsShareHandles = false;
2284 return false;
2285 }
2286 #endif
2287
2288 // Find out which type of D3D11 device the Renderer11 is using
2289 d3d11::ANGLED3D11DeviceType deviceType = getDeviceType();
2290 if (deviceType == d3d11::ANGLE_D3D11_DEVICE_TYPE_UNKNOWN)
2291 {
2292 mSupportsShareHandles = false;
2293 return false;
2294 }
2295
2296 if (deviceType == d3d11::ANGLE_D3D11_DEVICE_TYPE_SOFTWARE_REF_OR_NULL)
2297 {
2298 // Software/Reference/NULL devices don't support share handles
2299 mSupportsShareHandles = false;
2300 return false;
2301 }
2302
2303 if (deviceType == d3d11::ANGLE_D3D11_DEVICE_TYPE_WARP)
2304 {
2305 #ifndef ANGLE_ENABLE_WINDOWS_STORE
2306 if (!IsWindows8OrGreater())
2307 {
2308 // WARP on Windows 7 doesn't support shared handles
2309 mSupportsShareHandles = false;
2310 return false;
2311 }
2312 #endif // ANGLE_ENABLE_WINDOWS_STORE
2313
2314 // WARP on Windows 8.0+ supports shared handles when shared with another WARP device
2315 // TODO: allow applications to query for HARDWARE or WARP-specific share handles,
2316 // to prevent them trying to use a WARP share handle with an a HW device (or
2317 // vice-versa)
2318 // e.g. by creating EGL_D3D11_[HARDWARE/WARP]_DEVICE_SHARE_HANDLE_ANGLE
2319 mSupportsShareHandles = true;
2320 return true;
2321 }
2322
2323 ASSERT(mCreatedWithDeviceEXT || mRequestedDriverType == D3D_DRIVER_TYPE_HARDWARE);
2324 mSupportsShareHandles = true;
2325 return true;
2326 }
2327
getNV12TextureSupport() const2328 bool Renderer11::getNV12TextureSupport() const
2329 {
2330 HRESULT result;
2331 UINT formatSupport;
2332 result = mDevice->CheckFormatSupport(DXGI_FORMAT_NV12, &formatSupport);
2333 if (result == E_FAIL)
2334 {
2335 return false;
2336 }
2337 return (formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE2D) != 0;
2338 }
2339
getMajorShaderModel() const2340 int Renderer11::getMajorShaderModel() const
2341 {
2342 switch (mRenderer11DeviceCaps.featureLevel)
2343 {
2344 case D3D_FEATURE_LEVEL_11_1:
2345 case D3D_FEATURE_LEVEL_11_0:
2346 return D3D11_SHADER_MAJOR_VERSION; // 5
2347 case D3D_FEATURE_LEVEL_10_1:
2348 return D3D10_1_SHADER_MAJOR_VERSION; // 4
2349 case D3D_FEATURE_LEVEL_10_0:
2350 return D3D10_SHADER_MAJOR_VERSION; // 4
2351 case D3D_FEATURE_LEVEL_9_3:
2352 return D3D10_SHADER_MAJOR_VERSION; // 4
2353 default:
2354 UNREACHABLE();
2355 return 0;
2356 }
2357 }
2358
getMinorShaderModel() const2359 int Renderer11::getMinorShaderModel() const
2360 {
2361 switch (mRenderer11DeviceCaps.featureLevel)
2362 {
2363 case D3D_FEATURE_LEVEL_11_1:
2364 case D3D_FEATURE_LEVEL_11_0:
2365 return D3D11_SHADER_MINOR_VERSION; // 0
2366 case D3D_FEATURE_LEVEL_10_1:
2367 return D3D10_1_SHADER_MINOR_VERSION; // 1
2368 case D3D_FEATURE_LEVEL_10_0:
2369 return D3D10_SHADER_MINOR_VERSION; // 0
2370 case D3D_FEATURE_LEVEL_9_3:
2371 return D3D10_SHADER_MINOR_VERSION; // 0
2372 default:
2373 UNREACHABLE();
2374 return 0;
2375 }
2376 }
2377
getShaderModelSuffix() const2378 std::string Renderer11::getShaderModelSuffix() const
2379 {
2380 switch (mRenderer11DeviceCaps.featureLevel)
2381 {
2382 case D3D_FEATURE_LEVEL_11_1:
2383 case D3D_FEATURE_LEVEL_11_0:
2384 return "";
2385 case D3D_FEATURE_LEVEL_10_1:
2386 return "";
2387 case D3D_FEATURE_LEVEL_10_0:
2388 return "";
2389 case D3D_FEATURE_LEVEL_9_3:
2390 return "_level_9_3";
2391 default:
2392 UNREACHABLE();
2393 return "";
2394 }
2395 }
2396
getWorkarounds() const2397 const angle::WorkaroundsD3D &RendererD3D::getWorkarounds() const
2398 {
2399 if (!mWorkaroundsInitialized)
2400 {
2401 mWorkarounds = generateWorkarounds();
2402 mWorkaroundsInitialized = true;
2403 }
2404
2405 return mWorkarounds;
2406 }
2407
copyImageInternal(const gl::Context * context,const gl::Framebuffer * framebuffer,const gl::Rectangle & sourceRect,GLenum destFormat,const gl::Offset & destOffset,RenderTargetD3D * destRenderTarget)2408 gl::Error Renderer11::copyImageInternal(const gl::Context *context,
2409 const gl::Framebuffer *framebuffer,
2410 const gl::Rectangle &sourceRect,
2411 GLenum destFormat,
2412 const gl::Offset &destOffset,
2413 RenderTargetD3D *destRenderTarget)
2414 {
2415 const gl::FramebufferAttachment *colorAttachment = framebuffer->getReadColorbuffer();
2416 ASSERT(colorAttachment);
2417
2418 RenderTarget11 *sourceRenderTarget = nullptr;
2419 ANGLE_TRY(colorAttachment->getRenderTarget(context, &sourceRenderTarget));
2420 ASSERT(sourceRenderTarget);
2421
2422 const d3d11::SharedSRV &source = sourceRenderTarget->getBlitShaderResourceView();
2423 ASSERT(source.valid());
2424
2425 const d3d11::RenderTargetView &dest =
2426 GetAs<RenderTarget11>(destRenderTarget)->getRenderTargetView();
2427 ASSERT(dest.valid());
2428
2429 gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1);
2430 gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1);
2431
2432 const bool invertSource = UsePresentPathFast(this, colorAttachment);
2433 if (invertSource)
2434 {
2435 sourceArea.y = sourceSize.height - sourceRect.y;
2436 sourceArea.height = -sourceArea.height;
2437 }
2438
2439 gl::Box destArea(destOffset.x, destOffset.y, 0, sourceRect.width, sourceRect.height, 1);
2440 gl::Extents destSize(destRenderTarget->getWidth(), destRenderTarget->getHeight(), 1);
2441
2442 // Use nearest filtering because source and destination are the same size for the direct copy.
2443 // Convert to the unsized format before calling copyTexture.
2444 GLenum sourceFormat = colorAttachment->getFormat().info->format;
2445 ANGLE_TRY(mBlit->copyTexture(context, source, sourceArea, sourceSize, sourceFormat, dest,
2446 destArea, destSize, nullptr, gl::GetUnsizedFormat(destFormat),
2447 GL_NEAREST, false, false, false));
2448
2449 return gl::NoError();
2450 }
2451
copyImage2D(const gl::Context * context,const gl::Framebuffer * framebuffer,const gl::Rectangle & sourceRect,GLenum destFormat,const gl::Offset & destOffset,TextureStorage * storage,GLint level)2452 gl::Error Renderer11::copyImage2D(const gl::Context *context,
2453 const gl::Framebuffer *framebuffer,
2454 const gl::Rectangle &sourceRect,
2455 GLenum destFormat,
2456 const gl::Offset &destOffset,
2457 TextureStorage *storage,
2458 GLint level)
2459 {
2460 TextureStorage11_2D *storage11 = GetAs<TextureStorage11_2D>(storage);
2461 ASSERT(storage11);
2462
2463 gl::ImageIndex index = gl::ImageIndex::Make2D(level);
2464 RenderTargetD3D *destRenderTarget = nullptr;
2465 ANGLE_TRY(storage11->getRenderTarget(context, index, &destRenderTarget));
2466 ASSERT(destRenderTarget);
2467
2468 ANGLE_TRY(copyImageInternal(context, framebuffer, sourceRect, destFormat, destOffset,
2469 destRenderTarget));
2470
2471 storage11->markLevelDirty(level);
2472
2473 return gl::NoError();
2474 }
2475
copyImageCube(const gl::Context * context,const gl::Framebuffer * framebuffer,const gl::Rectangle & sourceRect,GLenum destFormat,const gl::Offset & destOffset,TextureStorage * storage,GLenum target,GLint level)2476 gl::Error Renderer11::copyImageCube(const gl::Context *context,
2477 const gl::Framebuffer *framebuffer,
2478 const gl::Rectangle &sourceRect,
2479 GLenum destFormat,
2480 const gl::Offset &destOffset,
2481 TextureStorage *storage,
2482 GLenum target,
2483 GLint level)
2484 {
2485 TextureStorage11_Cube *storage11 = GetAs<TextureStorage11_Cube>(storage);
2486 ASSERT(storage11);
2487
2488 gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level);
2489 RenderTargetD3D *destRenderTarget = nullptr;
2490 ANGLE_TRY(storage11->getRenderTarget(context, index, &destRenderTarget));
2491 ASSERT(destRenderTarget);
2492
2493 ANGLE_TRY(copyImageInternal(context, framebuffer, sourceRect, destFormat, destOffset,
2494 destRenderTarget));
2495
2496 storage11->markLevelDirty(level);
2497
2498 return gl::NoError();
2499 }
2500
copyImage3D(const gl::Context * context,const gl::Framebuffer * framebuffer,const gl::Rectangle & sourceRect,GLenum destFormat,const gl::Offset & destOffset,TextureStorage * storage,GLint level)2501 gl::Error Renderer11::copyImage3D(const gl::Context *context,
2502 const gl::Framebuffer *framebuffer,
2503 const gl::Rectangle &sourceRect,
2504 GLenum destFormat,
2505 const gl::Offset &destOffset,
2506 TextureStorage *storage,
2507 GLint level)
2508 {
2509 TextureStorage11_3D *storage11 = GetAs<TextureStorage11_3D>(storage);
2510 ASSERT(storage11);
2511
2512 gl::ImageIndex index = gl::ImageIndex::Make3D(level, destOffset.z);
2513 RenderTargetD3D *destRenderTarget = nullptr;
2514 ANGLE_TRY(storage11->getRenderTarget(context, index, &destRenderTarget));
2515 ASSERT(destRenderTarget);
2516
2517 ANGLE_TRY(copyImageInternal(context, framebuffer, sourceRect, destFormat, destOffset,
2518 destRenderTarget));
2519
2520 storage11->markLevelDirty(level);
2521
2522 return gl::NoError();
2523 }
2524
copyImage2DArray(const gl::Context * context,const gl::Framebuffer * framebuffer,const gl::Rectangle & sourceRect,GLenum destFormat,const gl::Offset & destOffset,TextureStorage * storage,GLint level)2525 gl::Error Renderer11::copyImage2DArray(const gl::Context *context,
2526 const gl::Framebuffer *framebuffer,
2527 const gl::Rectangle &sourceRect,
2528 GLenum destFormat,
2529 const gl::Offset &destOffset,
2530 TextureStorage *storage,
2531 GLint level)
2532 {
2533 TextureStorage11_2DArray *storage11 = GetAs<TextureStorage11_2DArray>(storage);
2534 ASSERT(storage11);
2535
2536 gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, destOffset.z);
2537 RenderTargetD3D *destRenderTarget = nullptr;
2538 ANGLE_TRY(storage11->getRenderTarget(context, index, &destRenderTarget));
2539 ASSERT(destRenderTarget);
2540
2541 ANGLE_TRY(copyImageInternal(context, framebuffer, sourceRect, destFormat, destOffset,
2542 destRenderTarget));
2543 storage11->markLevelDirty(level);
2544
2545 return gl::NoError();
2546 }
2547
copyTexture(const gl::Context * context,const gl::Texture * source,GLint sourceLevel,const gl::Rectangle & sourceRect,GLenum destFormat,const gl::Offset & destOffset,TextureStorage * storage,GLenum destTarget,GLint destLevel,bool unpackFlipY,bool unpackPremultiplyAlpha,bool unpackUnmultiplyAlpha)2548 gl::Error Renderer11::copyTexture(const gl::Context *context,
2549 const gl::Texture *source,
2550 GLint sourceLevel,
2551 const gl::Rectangle &sourceRect,
2552 GLenum destFormat,
2553 const gl::Offset &destOffset,
2554 TextureStorage *storage,
2555 GLenum destTarget,
2556 GLint destLevel,
2557 bool unpackFlipY,
2558 bool unpackPremultiplyAlpha,
2559 bool unpackUnmultiplyAlpha)
2560 {
2561 TextureD3D *sourceD3D = GetImplAs<TextureD3D>(source);
2562
2563 TextureStorage *sourceStorage = nullptr;
2564 ANGLE_TRY(sourceD3D->getNativeTexture(context, &sourceStorage));
2565
2566 TextureStorage11_2D *sourceStorage11 = GetAs<TextureStorage11_2D>(sourceStorage);
2567 ASSERT(sourceStorage11);
2568
2569 TextureStorage11 *destStorage11 = GetAs<TextureStorage11>(storage);
2570 ASSERT(destStorage11);
2571
2572 // Check for fast path where a CopySubresourceRegion can be used.
2573 if (unpackPremultiplyAlpha == unpackUnmultiplyAlpha && !unpackFlipY &&
2574 source->getFormat(GL_TEXTURE_2D, sourceLevel).info->format == destFormat &&
2575 sourceStorage11->getFormatSet().texFormat == destStorage11->getFormatSet().texFormat)
2576 {
2577 const TextureHelper11 *sourceResource = nullptr;
2578 ANGLE_TRY(sourceStorage11->getResource(context, &sourceResource));
2579
2580 gl::ImageIndex sourceIndex = gl::ImageIndex::Make2D(sourceLevel);
2581 UINT sourceSubresource = sourceStorage11->getSubresourceIndex(sourceIndex);
2582
2583 const TextureHelper11 *destResource = nullptr;
2584 ANGLE_TRY(destStorage11->getResource(context, &destResource));
2585
2586 gl::ImageIndex destIndex = gl::ImageIndex::MakeGeneric(destTarget, destLevel);
2587 UINT destSubresource = destStorage11->getSubresourceIndex(destIndex);
2588
2589 D3D11_BOX sourceBox{
2590 static_cast<UINT>(sourceRect.x),
2591 static_cast<UINT>(sourceRect.y),
2592 0u,
2593 static_cast<UINT>(sourceRect.x + sourceRect.width),
2594 static_cast<UINT>(sourceRect.y + sourceRect.height),
2595 1u,
2596 };
2597
2598 mDeviceContext->CopySubresourceRegion(destResource->get(), destSubresource, destOffset.x,
2599 destOffset.y, destOffset.z, sourceResource->get(),
2600 sourceSubresource, &sourceBox);
2601 }
2602 else
2603 {
2604 const d3d11::SharedSRV *sourceSRV = nullptr;
2605 ANGLE_TRY(sourceStorage11->getSRVLevels(context, sourceLevel, sourceLevel, &sourceSRV));
2606
2607 gl::ImageIndex destIndex = gl::ImageIndex::MakeGeneric(destTarget, destLevel);
2608 RenderTargetD3D *destRenderTargetD3D = nullptr;
2609 ANGLE_TRY(destStorage11->getRenderTarget(context, destIndex, &destRenderTargetD3D));
2610
2611 RenderTarget11 *destRenderTarget11 = GetAs<RenderTarget11>(destRenderTargetD3D);
2612
2613 const d3d11::RenderTargetView &destRTV = destRenderTarget11->getRenderTargetView();
2614 ASSERT(destRTV.valid());
2615
2616 gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1);
2617 gl::Extents sourceSize(
2618 static_cast<int>(source->getWidth(source->getTarget(), sourceLevel)),
2619 static_cast<int>(source->getHeight(source->getTarget(), sourceLevel)), 1);
2620 if (unpackFlipY)
2621 {
2622 sourceArea.y += sourceArea.height;
2623 sourceArea.height = -sourceArea.height;
2624 }
2625
2626 gl::Box destArea(destOffset.x, destOffset.y, 0, sourceRect.width, sourceRect.height, 1);
2627 gl::Extents destSize(destRenderTarget11->getWidth(), destRenderTarget11->getHeight(), 1);
2628
2629 // Use nearest filtering because source and destination are the same size for the direct
2630 // copy
2631 GLenum sourceFormat = source->getFormat(GL_TEXTURE_2D, sourceLevel).info->format;
2632 ANGLE_TRY(mBlit->copyTexture(context, *sourceSRV, sourceArea, sourceSize, sourceFormat,
2633 destRTV, destArea, destSize, nullptr, destFormat, GL_NEAREST,
2634 false, unpackPremultiplyAlpha, unpackUnmultiplyAlpha));
2635 }
2636
2637 destStorage11->markLevelDirty(destLevel);
2638
2639 return gl::NoError();
2640 }
2641
copyCompressedTexture(const gl::Context * context,const gl::Texture * source,GLint sourceLevel,TextureStorage * storage,GLint destLevel)2642 gl::Error Renderer11::copyCompressedTexture(const gl::Context *context,
2643 const gl::Texture *source,
2644 GLint sourceLevel,
2645 TextureStorage *storage,
2646 GLint destLevel)
2647 {
2648 TextureStorage11_2D *destStorage11 = GetAs<TextureStorage11_2D>(storage);
2649 ASSERT(destStorage11);
2650
2651 const TextureHelper11 *destResource = nullptr;
2652 ANGLE_TRY(destStorage11->getResource(context, &destResource));
2653
2654 gl::ImageIndex destIndex = gl::ImageIndex::Make2D(destLevel);
2655 UINT destSubresource = destStorage11->getSubresourceIndex(destIndex);
2656
2657 TextureD3D *sourceD3D = GetImplAs<TextureD3D>(source);
2658 ASSERT(sourceD3D);
2659
2660 TextureStorage *sourceStorage = nullptr;
2661 ANGLE_TRY(sourceD3D->getNativeTexture(context, &sourceStorage));
2662
2663 TextureStorage11_2D *sourceStorage11 = GetAs<TextureStorage11_2D>(sourceStorage);
2664 ASSERT(sourceStorage11);
2665
2666 const TextureHelper11 *sourceResource = nullptr;
2667 ANGLE_TRY(sourceStorage11->getResource(context, &sourceResource));
2668
2669 gl::ImageIndex sourceIndex = gl::ImageIndex::Make2D(sourceLevel);
2670 UINT sourceSubresource = sourceStorage11->getSubresourceIndex(sourceIndex);
2671
2672 mDeviceContext->CopySubresourceRegion(destResource->get(), destSubresource, 0, 0, 0,
2673 sourceResource->get(), sourceSubresource, nullptr);
2674
2675 return gl::NoError();
2676 }
2677
createRenderTarget(int width,int height,GLenum format,GLsizei samples,RenderTargetD3D ** outRT)2678 gl::Error Renderer11::createRenderTarget(int width,
2679 int height,
2680 GLenum format,
2681 GLsizei samples,
2682 RenderTargetD3D **outRT)
2683 {
2684 const d3d11::Format &formatInfo = d3d11::Format::Get(format, mRenderer11DeviceCaps);
2685
2686 const gl::TextureCaps &textureCaps = getNativeTextureCaps().get(format);
2687 GLuint supportedSamples = textureCaps.getNearestSamples(samples);
2688
2689 if (width > 0 && height > 0)
2690 {
2691 // Create texture resource
2692 D3D11_TEXTURE2D_DESC desc;
2693 desc.Width = width;
2694 desc.Height = height;
2695 desc.MipLevels = 1;
2696 desc.ArraySize = 1;
2697 desc.Format = formatInfo.texFormat;
2698 desc.SampleDesc.Count = (supportedSamples == 0) ? 1 : supportedSamples;
2699 desc.SampleDesc.Quality = 0;
2700 desc.Usage = D3D11_USAGE_DEFAULT;
2701 desc.CPUAccessFlags = 0;
2702 desc.MiscFlags = 0;
2703
2704 // If a rendertarget or depthstencil format exists for this texture format,
2705 // we'll flag it to allow binding that way. Shader resource views are a little
2706 // more complicated.
2707 bool bindRTV = false, bindDSV = false, bindSRV = false;
2708 bindRTV = (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN);
2709 bindDSV = (formatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN);
2710 bindSRV = (formatInfo.srvFormat != DXGI_FORMAT_UNKNOWN);
2711
2712 bool isMultisampledDepthStencil = bindDSV && desc.SampleDesc.Count > 1;
2713 if (isMultisampledDepthStencil &&
2714 !mRenderer11DeviceCaps.supportsMultisampledDepthStencilSRVs)
2715 {
2716 bindSRV = false;
2717 }
2718
2719 desc.BindFlags = (bindRTV ? D3D11_BIND_RENDER_TARGET : 0) |
2720 (bindDSV ? D3D11_BIND_DEPTH_STENCIL : 0) |
2721 (bindSRV ? D3D11_BIND_SHADER_RESOURCE : 0);
2722
2723 // The format must be either an RTV or a DSV
2724 ASSERT(bindRTV != bindDSV);
2725
2726 TextureHelper11 texture;
2727 ANGLE_TRY(allocateTexture(desc, formatInfo, &texture));
2728
2729 d3d11::SharedSRV srv;
2730 d3d11::SharedSRV blitSRV;
2731 if (bindSRV)
2732 {
2733 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
2734 srvDesc.Format = formatInfo.srvFormat;
2735 srvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_SRV_DIMENSION_TEXTURE2D
2736 : D3D11_SRV_DIMENSION_TEXTURE2DMS;
2737 srvDesc.Texture2D.MostDetailedMip = 0;
2738 srvDesc.Texture2D.MipLevels = 1;
2739
2740 ANGLE_TRY(allocateResource(srvDesc, texture.get(), &srv));
2741
2742 if (formatInfo.blitSRVFormat != formatInfo.srvFormat)
2743 {
2744 D3D11_SHADER_RESOURCE_VIEW_DESC blitSRVDesc;
2745 blitSRVDesc.Format = formatInfo.blitSRVFormat;
2746 blitSRVDesc.ViewDimension = (supportedSamples == 0)
2747 ? D3D11_SRV_DIMENSION_TEXTURE2D
2748 : D3D11_SRV_DIMENSION_TEXTURE2DMS;
2749 blitSRVDesc.Texture2D.MostDetailedMip = 0;
2750 blitSRVDesc.Texture2D.MipLevels = 1;
2751
2752 ANGLE_TRY(allocateResource(blitSRVDesc, texture.get(), &blitSRV));
2753 }
2754 else
2755 {
2756 blitSRV = srv.makeCopy();
2757 }
2758 }
2759
2760 if (bindDSV)
2761 {
2762 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
2763 dsvDesc.Format = formatInfo.dsvFormat;
2764 dsvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_DSV_DIMENSION_TEXTURE2D
2765 : D3D11_DSV_DIMENSION_TEXTURE2DMS;
2766 dsvDesc.Texture2D.MipSlice = 0;
2767 dsvDesc.Flags = 0;
2768
2769 d3d11::DepthStencilView dsv;
2770 ANGLE_TRY(allocateResource(dsvDesc, texture.get(), &dsv));
2771
2772 *outRT = new TextureRenderTarget11(std::move(dsv), texture, srv, format, formatInfo,
2773 width, height, 1, supportedSamples);
2774 }
2775 else if (bindRTV)
2776 {
2777 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
2778 rtvDesc.Format = formatInfo.rtvFormat;
2779 rtvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_RTV_DIMENSION_TEXTURE2D
2780 : D3D11_RTV_DIMENSION_TEXTURE2DMS;
2781 rtvDesc.Texture2D.MipSlice = 0;
2782
2783 d3d11::RenderTargetView rtv;
2784 ANGLE_TRY(allocateResource(rtvDesc, texture.get(), &rtv));
2785
2786 if (formatInfo.dataInitializerFunction != nullptr)
2787 {
2788 const float clearValues[4] = {0.0f, 0.0f, 0.0f, 1.0f};
2789 mDeviceContext->ClearRenderTargetView(rtv.get(), clearValues);
2790 }
2791
2792 *outRT = new TextureRenderTarget11(std::move(rtv), texture, srv, blitSRV, format,
2793 formatInfo, width, height, 1, supportedSamples);
2794 }
2795 else
2796 {
2797 UNREACHABLE();
2798 }
2799 }
2800 else
2801 {
2802 *outRT = new TextureRenderTarget11(d3d11::RenderTargetView(), TextureHelper11(),
2803 d3d11::SharedSRV(), d3d11::SharedSRV(), format,
2804 d3d11::Format::Get(GL_NONE, mRenderer11DeviceCaps),
2805 width, height, 1, supportedSamples);
2806 }
2807
2808 return gl::NoError();
2809 }
2810
createRenderTargetCopy(RenderTargetD3D * source,RenderTargetD3D ** outRT)2811 gl::Error Renderer11::createRenderTargetCopy(RenderTargetD3D *source, RenderTargetD3D **outRT)
2812 {
2813 ASSERT(source != nullptr);
2814
2815 RenderTargetD3D *newRT = nullptr;
2816 ANGLE_TRY(createRenderTarget(source->getWidth(), source->getHeight(),
2817 source->getInternalFormat(), source->getSamples(), &newRT));
2818
2819 RenderTarget11 *source11 = GetAs<RenderTarget11>(source);
2820 RenderTarget11 *dest11 = GetAs<RenderTarget11>(newRT);
2821
2822 mDeviceContext->CopySubresourceRegion(dest11->getTexture().get(), dest11->getSubresourceIndex(),
2823 0, 0, 0, source11->getTexture().get(),
2824 source11->getSubresourceIndex(), nullptr);
2825 *outRT = newRT;
2826 return gl::NoError();
2827 }
2828
loadExecutable(const uint8_t * function,size_t length,gl::ShaderType type,const std::vector<D3DVarying> & streamOutVaryings,bool separatedOutputBuffers,ShaderExecutableD3D ** outExecutable)2829 gl::Error Renderer11::loadExecutable(const uint8_t *function,
2830 size_t length,
2831 gl::ShaderType type,
2832 const std::vector<D3DVarying> &streamOutVaryings,
2833 bool separatedOutputBuffers,
2834 ShaderExecutableD3D **outExecutable)
2835 {
2836 ShaderData shaderData(function, length);
2837
2838 switch (type)
2839 {
2840 case gl::SHADER_VERTEX:
2841 {
2842 d3d11::VertexShader vertexShader;
2843 d3d11::GeometryShader streamOutShader;
2844 ANGLE_TRY(allocateResource(shaderData, &vertexShader));
2845
2846 if (!streamOutVaryings.empty())
2847 {
2848 std::vector<D3D11_SO_DECLARATION_ENTRY> soDeclaration;
2849 soDeclaration.reserve(streamOutVaryings.size());
2850
2851 for (const auto &streamOutVarying : streamOutVaryings)
2852 {
2853 D3D11_SO_DECLARATION_ENTRY entry = {0};
2854 entry.Stream = 0;
2855 entry.SemanticName = streamOutVarying.semanticName.c_str();
2856 entry.SemanticIndex = streamOutVarying.semanticIndex;
2857 entry.StartComponent = 0;
2858 entry.ComponentCount = static_cast<BYTE>(streamOutVarying.componentCount);
2859 entry.OutputSlot = static_cast<BYTE>(
2860 (separatedOutputBuffers ? streamOutVarying.outputSlot : 0));
2861 soDeclaration.push_back(entry);
2862 }
2863
2864 ANGLE_TRY(allocateResource(shaderData, &soDeclaration, &streamOutShader));
2865 }
2866
2867 *outExecutable = new ShaderExecutable11(function, length, std::move(vertexShader),
2868 std::move(streamOutShader));
2869 }
2870 break;
2871 case gl::SHADER_FRAGMENT:
2872 {
2873 d3d11::PixelShader pixelShader;
2874 ANGLE_TRY(allocateResource(shaderData, &pixelShader));
2875 *outExecutable = new ShaderExecutable11(function, length, std::move(pixelShader));
2876 }
2877 break;
2878 case gl::SHADER_GEOMETRY:
2879 {
2880 d3d11::GeometryShader geometryShader;
2881 ANGLE_TRY(allocateResource(shaderData, &geometryShader));
2882 *outExecutable = new ShaderExecutable11(function, length, std::move(geometryShader));
2883 }
2884 break;
2885 case gl::SHADER_COMPUTE:
2886 {
2887 d3d11::ComputeShader computeShader;
2888 ANGLE_TRY(allocateResource(shaderData, &computeShader));
2889 *outExecutable = new ShaderExecutable11(function, length, std::move(computeShader));
2890 }
2891 break;
2892 default:
2893 UNREACHABLE();
2894 return gl::InternalError();
2895 }
2896
2897 return gl::NoError();
2898 }
2899
compileToExecutable(gl::InfoLog & infoLog,const std::string & shaderHLSL,gl::ShaderType type,const std::vector<D3DVarying> & streamOutVaryings,bool separatedOutputBuffers,const angle::CompilerWorkaroundsD3D & workarounds,ShaderExecutableD3D ** outExectuable)2900 gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog,
2901 const std::string &shaderHLSL,
2902 gl::ShaderType type,
2903 const std::vector<D3DVarying> &streamOutVaryings,
2904 bool separatedOutputBuffers,
2905 const angle::CompilerWorkaroundsD3D &workarounds,
2906 ShaderExecutableD3D **outExectuable)
2907 {
2908 std::stringstream profileStream;
2909
2910 switch (type)
2911 {
2912 case gl::SHADER_VERTEX:
2913 profileStream << "vs";
2914 break;
2915 case gl::SHADER_FRAGMENT:
2916 profileStream << "ps";
2917 break;
2918 case gl::SHADER_GEOMETRY:
2919 profileStream << "gs";
2920 break;
2921 case gl::SHADER_COMPUTE:
2922 profileStream << "cs";
2923 break;
2924 default:
2925 UNREACHABLE();
2926 return gl::InternalError();
2927 }
2928
2929 profileStream << "_" << getMajorShaderModel() << "_" << getMinorShaderModel()
2930 << getShaderModelSuffix();
2931 std::string profile = profileStream.str();
2932
2933 UINT flags = D3DCOMPILE_OPTIMIZATION_LEVEL2;
2934
2935 if (gl::DebugAnnotationsActive())
2936 {
2937 #ifndef NDEBUG
2938 flags = D3DCOMPILE_SKIP_OPTIMIZATION;
2939 #endif
2940
2941 flags |= D3DCOMPILE_DEBUG;
2942 }
2943
2944 if (workarounds.enableIEEEStrictness)
2945 flags |= D3DCOMPILE_IEEE_STRICTNESS;
2946
2947 // Sometimes D3DCompile will fail with the default compilation flags for complicated shaders
2948 // when it would otherwise pass with alternative options.
2949 // Try the default flags first and if compilation fails, try some alternatives.
2950 std::vector<CompileConfig> configs;
2951 configs.push_back(CompileConfig(flags, "default"));
2952 configs.push_back(CompileConfig(flags | D3DCOMPILE_SKIP_VALIDATION, "skip validation"));
2953 configs.push_back(CompileConfig(flags | D3DCOMPILE_SKIP_OPTIMIZATION, "skip optimization"));
2954
2955 if (getMajorShaderModel() == 4 && getShaderModelSuffix() != "")
2956 {
2957 // Some shaders might cause a "blob content mismatch between level9 and d3d10 shader".
2958 // e.g. dEQP-GLES2.functional.shaders.struct.local.loop_nested_struct_array_*.
2959 // Using the [unroll] directive works around this, as does this D3DCompile flag.
2960 configs.push_back(
2961 CompileConfig(flags | D3DCOMPILE_AVOID_FLOW_CONTROL, "avoid flow control"));
2962 }
2963
2964 D3D_SHADER_MACRO loopMacros[] = {{"ANGLE_ENABLE_LOOP_FLATTEN", "1"}, {0, 0}};
2965
2966 // TODO(jmadill): Use ComPtr?
2967 ID3DBlob *binary = nullptr;
2968 std::string debugInfo;
2969 ANGLE_TRY(mCompiler.compileToBinary(infoLog, shaderHLSL, profile, configs, loopMacros, &binary,
2970 &debugInfo));
2971
2972 // It's possible that binary is NULL if the compiler failed in all configurations. Set the
2973 // executable to NULL and return GL_NO_ERROR to signify that there was a link error but the
2974 // internal state is still OK.
2975 if (!binary)
2976 {
2977 *outExectuable = nullptr;
2978 return gl::NoError();
2979 }
2980
2981 gl::Error error = loadExecutable(reinterpret_cast<const uint8_t *>(binary->GetBufferPointer()),
2982 binary->GetBufferSize(), type, streamOutVaryings,
2983 separatedOutputBuffers, outExectuable);
2984
2985 SafeRelease(binary);
2986 if (error.isError())
2987 {
2988 return error;
2989 }
2990
2991 if (!debugInfo.empty())
2992 {
2993 (*outExectuable)->appendDebugInfo(debugInfo);
2994 }
2995
2996 return gl::NoError();
2997 }
2998
ensureHLSLCompilerInitialized()2999 gl::Error Renderer11::ensureHLSLCompilerInitialized()
3000 {
3001 return mCompiler.ensureInitialized();
3002 }
3003
createUniformStorage(size_t storageSize)3004 UniformStorageD3D *Renderer11::createUniformStorage(size_t storageSize)
3005 {
3006 return new UniformStorage11(storageSize);
3007 }
3008
createVertexBuffer()3009 VertexBuffer *Renderer11::createVertexBuffer()
3010 {
3011 return new VertexBuffer11(this);
3012 }
3013
createIndexBuffer()3014 IndexBuffer *Renderer11::createIndexBuffer()
3015 {
3016 return new IndexBuffer11(this);
3017 }
3018
createStreamProducerD3DTextureNV12(egl::Stream::ConsumerType consumerType,const egl::AttributeMap & attribs)3019 StreamProducerImpl *Renderer11::createStreamProducerD3DTextureNV12(
3020 egl::Stream::ConsumerType consumerType,
3021 const egl::AttributeMap &attribs)
3022 {
3023 return new StreamProducerNV12(this);
3024 }
3025
supportsFastCopyBufferToTexture(GLenum internalFormat) const3026 bool Renderer11::supportsFastCopyBufferToTexture(GLenum internalFormat) const
3027 {
3028 ASSERT(getNativeExtensions().pixelBufferObject);
3029
3030 const gl::InternalFormat &internalFormatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
3031 const d3d11::Format &d3d11FormatInfo =
3032 d3d11::Format::Get(internalFormat, mRenderer11DeviceCaps);
3033
3034 // sRGB formats do not work with D3D11 buffer SRVs
3035 if (internalFormatInfo.colorEncoding == GL_SRGB)
3036 {
3037 return false;
3038 }
3039
3040 // We cannot support direct copies to non-color-renderable formats
3041 if (d3d11FormatInfo.rtvFormat == DXGI_FORMAT_UNKNOWN)
3042 {
3043 return false;
3044 }
3045
3046 // We skip all 3-channel formats since sometimes format support is missing
3047 if (internalFormatInfo.componentCount == 3)
3048 {
3049 return false;
3050 }
3051
3052 // We don't support formats which we can't represent without conversion
3053 if (d3d11FormatInfo.format().glInternalFormat != internalFormat)
3054 {
3055 return false;
3056 }
3057
3058 // Buffer SRV creation for this format was not working on Windows 10.
3059 if (d3d11FormatInfo.texFormat == DXGI_FORMAT_B5G5R5A1_UNORM)
3060 {
3061 return false;
3062 }
3063
3064 // This format is not supported as a buffer SRV.
3065 if (d3d11FormatInfo.texFormat == DXGI_FORMAT_A8_UNORM)
3066 {
3067 return false;
3068 }
3069
3070 return true;
3071 }
3072
fastCopyBufferToTexture(const gl::Context * context,const gl::PixelUnpackState & unpack,unsigned int offset,RenderTargetD3D * destRenderTarget,GLenum destinationFormat,GLenum sourcePixelsType,const gl::Box & destArea)3073 gl::Error Renderer11::fastCopyBufferToTexture(const gl::Context *context,
3074 const gl::PixelUnpackState &unpack,
3075 unsigned int offset,
3076 RenderTargetD3D *destRenderTarget,
3077 GLenum destinationFormat,
3078 GLenum sourcePixelsType,
3079 const gl::Box &destArea)
3080 {
3081 ASSERT(supportsFastCopyBufferToTexture(destinationFormat));
3082 return mPixelTransfer->copyBufferToTexture(context, unpack, offset, destRenderTarget,
3083 destinationFormat, sourcePixelsType, destArea);
3084 }
3085
createImage()3086 ImageD3D *Renderer11::createImage()
3087 {
3088 return new Image11(this);
3089 }
3090
generateMipmap(const gl::Context * context,ImageD3D * dest,ImageD3D * src)3091 gl::Error Renderer11::generateMipmap(const gl::Context *context, ImageD3D *dest, ImageD3D *src)
3092 {
3093 Image11 *dest11 = GetAs<Image11>(dest);
3094 Image11 *src11 = GetAs<Image11>(src);
3095 return Image11::GenerateMipmap(context, dest11, src11, mRenderer11DeviceCaps);
3096 }
3097
generateMipmapUsingD3D(const gl::Context * context,TextureStorage * storage,const gl::TextureState & textureState)3098 gl::Error Renderer11::generateMipmapUsingD3D(const gl::Context *context,
3099 TextureStorage *storage,
3100 const gl::TextureState &textureState)
3101 {
3102 TextureStorage11 *storage11 = GetAs<TextureStorage11>(storage);
3103
3104 ASSERT(storage11->isRenderTarget());
3105 ASSERT(storage11->supportsNativeMipmapFunction());
3106
3107 const d3d11::SharedSRV *srv = nullptr;
3108 ANGLE_TRY(storage11->getSRVLevels(context, textureState.getEffectiveBaseLevel(),
3109 textureState.getEffectiveMaxLevel(), &srv));
3110
3111 mDeviceContext->GenerateMips(srv->get());
3112
3113 return gl::NoError();
3114 }
3115
copyImage(const gl::Context * context,ImageD3D * dest,ImageD3D * source,const gl::Rectangle & sourceRect,const gl::Offset & destOffset,bool unpackFlipY,bool unpackPremultiplyAlpha,bool unpackUnmultiplyAlpha)3116 gl::Error Renderer11::copyImage(const gl::Context *context,
3117 ImageD3D *dest,
3118 ImageD3D *source,
3119 const gl::Rectangle &sourceRect,
3120 const gl::Offset &destOffset,
3121 bool unpackFlipY,
3122 bool unpackPremultiplyAlpha,
3123 bool unpackUnmultiplyAlpha)
3124 {
3125 Image11 *dest11 = GetAs<Image11>(dest);
3126 Image11 *src11 = GetAs<Image11>(source);
3127 return Image11::CopyImage(context, dest11, src11, sourceRect, destOffset, unpackFlipY,
3128 unpackPremultiplyAlpha, unpackUnmultiplyAlpha, mRenderer11DeviceCaps);
3129 }
3130
createTextureStorage2D(SwapChainD3D * swapChain)3131 TextureStorage *Renderer11::createTextureStorage2D(SwapChainD3D *swapChain)
3132 {
3133 SwapChain11 *swapChain11 = GetAs<SwapChain11>(swapChain);
3134 return new TextureStorage11_2D(this, swapChain11);
3135 }
3136
createTextureStorageEGLImage(EGLImageD3D * eglImage,RenderTargetD3D * renderTargetD3D)3137 TextureStorage *Renderer11::createTextureStorageEGLImage(EGLImageD3D *eglImage,
3138 RenderTargetD3D *renderTargetD3D)
3139 {
3140 return new TextureStorage11_EGLImage(this, eglImage, GetAs<RenderTarget11>(renderTargetD3D));
3141 }
3142
createTextureStorageExternal(egl::Stream * stream,const egl::Stream::GLTextureDescription & desc)3143 TextureStorage *Renderer11::createTextureStorageExternal(
3144 egl::Stream *stream,
3145 const egl::Stream::GLTextureDescription &desc)
3146 {
3147 return new TextureStorage11_External(this, stream, desc);
3148 }
3149
createTextureStorage2D(GLenum internalformat,bool renderTarget,GLsizei width,GLsizei height,int levels,bool hintLevelZeroOnly)3150 TextureStorage *Renderer11::createTextureStorage2D(GLenum internalformat,
3151 bool renderTarget,
3152 GLsizei width,
3153 GLsizei height,
3154 int levels,
3155 bool hintLevelZeroOnly)
3156 {
3157 return new TextureStorage11_2D(this, internalformat, renderTarget, width, height, levels,
3158 hintLevelZeroOnly);
3159 }
3160
createTextureStorageCube(GLenum internalformat,bool renderTarget,int size,int levels,bool hintLevelZeroOnly)3161 TextureStorage *Renderer11::createTextureStorageCube(GLenum internalformat,
3162 bool renderTarget,
3163 int size,
3164 int levels,
3165 bool hintLevelZeroOnly)
3166 {
3167 return new TextureStorage11_Cube(this, internalformat, renderTarget, size, levels,
3168 hintLevelZeroOnly);
3169 }
3170
createTextureStorage3D(GLenum internalformat,bool renderTarget,GLsizei width,GLsizei height,GLsizei depth,int levels)3171 TextureStorage *Renderer11::createTextureStorage3D(GLenum internalformat,
3172 bool renderTarget,
3173 GLsizei width,
3174 GLsizei height,
3175 GLsizei depth,
3176 int levels)
3177 {
3178 return new TextureStorage11_3D(this, internalformat, renderTarget, width, height, depth,
3179 levels);
3180 }
3181
createTextureStorage2DArray(GLenum internalformat,bool renderTarget,GLsizei width,GLsizei height,GLsizei depth,int levels)3182 TextureStorage *Renderer11::createTextureStorage2DArray(GLenum internalformat,
3183 bool renderTarget,
3184 GLsizei width,
3185 GLsizei height,
3186 GLsizei depth,
3187 int levels)
3188 {
3189 return new TextureStorage11_2DArray(this, internalformat, renderTarget, width, height, depth,
3190 levels);
3191 }
3192
createTextureStorage2DMultisample(GLenum internalformat,GLsizei width,GLsizei height,int levels,int samples,bool fixedSampleLocations)3193 TextureStorage *Renderer11::createTextureStorage2DMultisample(GLenum internalformat,
3194 GLsizei width,
3195 GLsizei height,
3196 int levels,
3197 int samples,
3198 bool fixedSampleLocations)
3199 {
3200 return new TextureStorage11_2DMultisample(this, internalformat, width, height, levels, samples,
3201 fixedSampleLocations);
3202 }
3203
readFromAttachment(const gl::Context * context,const gl::FramebufferAttachment & srcAttachment,const gl::Rectangle & sourceArea,GLenum format,GLenum type,GLuint outputPitch,const gl::PixelPackState & pack,uint8_t * pixelsOut)3204 gl::Error Renderer11::readFromAttachment(const gl::Context *context,
3205 const gl::FramebufferAttachment &srcAttachment,
3206 const gl::Rectangle &sourceArea,
3207 GLenum format,
3208 GLenum type,
3209 GLuint outputPitch,
3210 const gl::PixelPackState &pack,
3211 uint8_t *pixelsOut)
3212 {
3213 ASSERT(sourceArea.width >= 0);
3214 ASSERT(sourceArea.height >= 0);
3215
3216 const bool invertTexture = UsePresentPathFast(this, &srcAttachment);
3217
3218 RenderTarget11 *rt11 = nullptr;
3219 ANGLE_TRY(srcAttachment.getRenderTarget(context, &rt11));
3220 ASSERT(rt11->getTexture().valid());
3221
3222 const TextureHelper11 &textureHelper = rt11->getTexture();
3223 unsigned int sourceSubResource = rt11->getSubresourceIndex();
3224
3225 const gl::Extents &texSize = textureHelper.getExtents();
3226
3227 gl::Rectangle actualArea = sourceArea;
3228 if (invertTexture)
3229 {
3230 actualArea.y = texSize.height - actualArea.y - actualArea.height;
3231 }
3232
3233 // Clamp read region to the defined texture boundaries, preventing out of bounds reads
3234 // and reads of uninitialized data.
3235 gl::Rectangle safeArea;
3236 safeArea.x = gl::clamp(actualArea.x, 0, texSize.width);
3237 safeArea.y = gl::clamp(actualArea.y, 0, texSize.height);
3238 safeArea.width =
3239 gl::clamp(actualArea.width + std::min(actualArea.x, 0), 0, texSize.width - safeArea.x);
3240 safeArea.height =
3241 gl::clamp(actualArea.height + std::min(actualArea.y, 0), 0, texSize.height - safeArea.y);
3242
3243 ASSERT(safeArea.x >= 0 && safeArea.y >= 0);
3244 ASSERT(safeArea.x + safeArea.width <= texSize.width);
3245 ASSERT(safeArea.y + safeArea.height <= texSize.height);
3246
3247 if (safeArea.width == 0 || safeArea.height == 0)
3248 {
3249 // no work to do
3250 return gl::NoError();
3251 }
3252
3253 gl::Extents safeSize(safeArea.width, safeArea.height, 1);
3254 TextureHelper11 stagingHelper;
3255 ANGLE_TRY_RESULT(
3256 createStagingTexture(textureHelper.getTextureType(), textureHelper.getFormatSet(), safeSize,
3257 StagingAccess::READ),
3258 stagingHelper);
3259
3260 TextureHelper11 resolvedTextureHelper;
3261
3262 // "srcTexture" usually points to the source texture.
3263 // For 2D multisampled textures, it points to the multisampled resolve texture.
3264 const TextureHelper11 *srcTexture = &textureHelper;
3265
3266 if (textureHelper.is2D() && textureHelper.getSampleCount() > 1)
3267 {
3268 D3D11_TEXTURE2D_DESC resolveDesc;
3269 resolveDesc.Width = static_cast<UINT>(texSize.width);
3270 resolveDesc.Height = static_cast<UINT>(texSize.height);
3271 resolveDesc.MipLevels = 1;
3272 resolveDesc.ArraySize = 1;
3273 resolveDesc.Format = textureHelper.getFormat();
3274 resolveDesc.SampleDesc.Count = 1;
3275 resolveDesc.SampleDesc.Quality = 0;
3276 resolveDesc.Usage = D3D11_USAGE_DEFAULT;
3277 resolveDesc.BindFlags = 0;
3278 resolveDesc.CPUAccessFlags = 0;
3279 resolveDesc.MiscFlags = 0;
3280
3281 ANGLE_TRY(
3282 allocateTexture(resolveDesc, textureHelper.getFormatSet(), &resolvedTextureHelper));
3283
3284 mDeviceContext->ResolveSubresource(resolvedTextureHelper.get(), 0, textureHelper.get(),
3285 sourceSubResource, textureHelper.getFormat());
3286
3287 sourceSubResource = 0;
3288 srcTexture = &resolvedTextureHelper;
3289 }
3290
3291 D3D11_BOX srcBox;
3292 srcBox.left = static_cast<UINT>(safeArea.x);
3293 srcBox.right = static_cast<UINT>(safeArea.x + safeArea.width);
3294 srcBox.top = static_cast<UINT>(safeArea.y);
3295 srcBox.bottom = static_cast<UINT>(safeArea.y + safeArea.height);
3296
3297 // Select the correct layer from a 3D attachment
3298 srcBox.front = 0;
3299 if (textureHelper.is3D())
3300 {
3301 srcBox.front = static_cast<UINT>(srcAttachment.layer());
3302 }
3303 srcBox.back = srcBox.front + 1;
3304
3305 mDeviceContext->CopySubresourceRegion(stagingHelper.get(), 0, 0, 0, 0, srcTexture->get(),
3306 sourceSubResource, &srcBox);
3307
3308 gl::Buffer *packBuffer = context->getGLState().getTargetBuffer(gl::BufferBinding::PixelPack);
3309 if (!invertTexture)
3310 {
3311 PackPixelsParams packParams(safeArea, format, type, outputPitch, pack, packBuffer, 0);
3312 return packPixels(stagingHelper, packParams, pixelsOut);
3313 }
3314
3315 // Create a new PixelPackState with reversed row order. Note that we can't just assign
3316 // 'invertTexturePack' to be 'pack' (or memcpy) since that breaks the ref counting/object
3317 // tracking in the 'pixelBuffer' members, causing leaks. Instead we must use
3318 // pixelBuffer.set() twice, which performs the addRef/release correctly
3319 gl::PixelPackState invertTexturePack;
3320 invertTexturePack.alignment = pack.alignment;
3321 invertTexturePack.reverseRowOrder = !pack.reverseRowOrder;
3322
3323 PackPixelsParams packParams(safeArea, format, type, outputPitch, invertTexturePack, packBuffer,
3324 0);
3325 gl::Error error = packPixels(stagingHelper, packParams, pixelsOut);
3326 ANGLE_TRY(error);
3327 return gl::NoError();
3328 }
3329
packPixels(const TextureHelper11 & textureHelper,const PackPixelsParams & params,uint8_t * pixelsOut)3330 gl::Error Renderer11::packPixels(const TextureHelper11 &textureHelper,
3331 const PackPixelsParams ¶ms,
3332 uint8_t *pixelsOut)
3333 {
3334 ID3D11Resource *readResource = textureHelper.get();
3335
3336 D3D11_MAPPED_SUBRESOURCE mapping;
3337 HRESULT hr = mDeviceContext->Map(readResource, 0, D3D11_MAP_READ, 0, &mapping);
3338 if (FAILED(hr))
3339 {
3340 ASSERT(hr == E_OUTOFMEMORY);
3341 return gl::OutOfMemory() << "Failed to map internal texture for reading, " << gl::FmtHR(hr);
3342 }
3343
3344 uint8_t *source = static_cast<uint8_t *>(mapping.pData);
3345 int inputPitch = static_cast<int>(mapping.RowPitch);
3346
3347 const auto &formatInfo = textureHelper.getFormatSet();
3348 ASSERT(formatInfo.format().glInternalFormat != GL_NONE);
3349
3350 PackPixels(params, formatInfo.format(), inputPitch, source, pixelsOut);
3351
3352 mDeviceContext->Unmap(readResource, 0);
3353
3354 return gl::NoError();
3355 }
3356
blitRenderbufferRect(const gl::Context * context,const gl::Rectangle & readRectIn,const gl::Rectangle & drawRectIn,RenderTargetD3D * readRenderTarget,RenderTargetD3D * drawRenderTarget,GLenum filter,const gl::Rectangle * scissor,bool colorBlit,bool depthBlit,bool stencilBlit)3357 gl::Error Renderer11::blitRenderbufferRect(const gl::Context *context,
3358 const gl::Rectangle &readRectIn,
3359 const gl::Rectangle &drawRectIn,
3360 RenderTargetD3D *readRenderTarget,
3361 RenderTargetD3D *drawRenderTarget,
3362 GLenum filter,
3363 const gl::Rectangle *scissor,
3364 bool colorBlit,
3365 bool depthBlit,
3366 bool stencilBlit)
3367 {
3368 // Since blitRenderbufferRect is called for each render buffer that needs to be blitted,
3369 // it should never be the case that both color and depth/stencil need to be blitted at
3370 // at the same time.
3371 ASSERT(colorBlit != (depthBlit || stencilBlit));
3372
3373 RenderTarget11 *drawRenderTarget11 = GetAs<RenderTarget11>(drawRenderTarget);
3374 if (!drawRenderTarget11)
3375 {
3376 return gl::OutOfMemory()
3377 << "Failed to retrieve the internal draw render target from the draw framebuffer.";
3378 }
3379
3380 const TextureHelper11 &drawTexture = drawRenderTarget11->getTexture();
3381 unsigned int drawSubresource = drawRenderTarget11->getSubresourceIndex();
3382
3383 RenderTarget11 *readRenderTarget11 = GetAs<RenderTarget11>(readRenderTarget);
3384 if (!readRenderTarget11)
3385 {
3386 return gl::OutOfMemory()
3387 << "Failed to retrieve the internal read render target from the read framebuffer.";
3388 }
3389
3390 TextureHelper11 readTexture;
3391 unsigned int readSubresource = 0;
3392 d3d11::SharedSRV readSRV;
3393
3394 if (readRenderTarget->isMultisampled())
3395 {
3396 ANGLE_TRY_RESULT(
3397 resolveMultisampledTexture(context, readRenderTarget11, depthBlit, stencilBlit),
3398 readTexture);
3399
3400 if (!stencilBlit)
3401 {
3402 const auto &readFormatSet = readTexture.getFormatSet();
3403
3404 D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc;
3405 viewDesc.Format = readFormatSet.srvFormat;
3406 viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
3407 viewDesc.Texture2D.MipLevels = 1;
3408 viewDesc.Texture2D.MostDetailedMip = 0;
3409
3410 ANGLE_TRY(allocateResource(viewDesc, readTexture.get(), &readSRV));
3411 }
3412 }
3413 else
3414 {
3415 ASSERT(readRenderTarget11);
3416 readTexture = readRenderTarget11->getTexture();
3417 readSubresource = readRenderTarget11->getSubresourceIndex();
3418 readSRV = readRenderTarget11->getBlitShaderResourceView().makeCopy();
3419 if (!readSRV.valid())
3420 {
3421 ASSERT(depthBlit || stencilBlit);
3422 readSRV = readRenderTarget11->getShaderResourceView().makeCopy();
3423 }
3424 ASSERT(readSRV.valid());
3425 }
3426
3427 // Stencil blits don't use shaders.
3428 ASSERT(readSRV.valid() || stencilBlit);
3429
3430 const gl::Extents readSize(readRenderTarget->getWidth(), readRenderTarget->getHeight(), 1);
3431 const gl::Extents drawSize(drawRenderTarget->getWidth(), drawRenderTarget->getHeight(), 1);
3432
3433 // From the spec:
3434 // "The actual region taken from the read framebuffer is limited to the intersection of the
3435 // source buffers being transferred, which may include the color buffer selected by the read
3436 // buffer, the depth buffer, and / or the stencil buffer depending on mask."
3437 // This means negative x and y are out of bounds, and not to be read from. We handle this here
3438 // by internally scaling the read and draw rectangles.
3439 gl::Rectangle readRect = readRectIn;
3440 gl::Rectangle drawRect = drawRectIn;
3441
3442 auto flip = [](int val) { return val >= 0 ? 1 : -1; };
3443
3444 if (readRect.x > readSize.width && readRect.width < 0)
3445 {
3446 int delta = readRect.x - readSize.width;
3447 readRect.x -= delta;
3448 readRect.width += delta;
3449
3450 int drawDelta = delta * flip(drawRect.width);
3451 drawRect.x += drawDelta;
3452 drawRect.width -= drawDelta;
3453 }
3454
3455 if (readRect.y > readSize.height && readRect.height < 0)
3456 {
3457 int delta = readRect.y - readSize.height;
3458 readRect.y -= delta;
3459 readRect.height += delta;
3460
3461 int drawDelta = delta * flip(drawRect.height);
3462 drawRect.y += drawDelta;
3463 drawRect.height -= drawDelta;
3464 }
3465
3466 auto readToDrawX = [&drawRectIn, &readRectIn](int readOffset) {
3467 double readToDrawScale =
3468 static_cast<double>(drawRectIn.width) / static_cast<double>(readRectIn.width);
3469 return static_cast<int>(round(static_cast<double>(readOffset) * readToDrawScale));
3470 };
3471 if (readRect.x < 0)
3472 {
3473 int readOffset = -readRect.x;
3474 readRect.x += readOffset;
3475 readRect.width -= readOffset;
3476
3477 int drawOffset = readToDrawX(readOffset);
3478 drawRect.x += drawOffset;
3479 drawRect.width -= drawOffset;
3480 }
3481
3482 auto readToDrawY = [&drawRectIn, &readRectIn](int readOffset) {
3483 double readToDrawScale =
3484 static_cast<double>(drawRectIn.height) / static_cast<double>(readRectIn.height);
3485 return static_cast<int>(round(static_cast<double>(readOffset) * readToDrawScale));
3486 };
3487 if (readRect.y < 0)
3488 {
3489 int readOffset = -readRect.y;
3490 readRect.y += readOffset;
3491 readRect.height -= readOffset;
3492
3493 int drawOffset = readToDrawY(readOffset);
3494 drawRect.y += drawOffset;
3495 drawRect.height -= drawOffset;
3496 }
3497
3498 if (readRect.x1() < 0)
3499 {
3500 int readOffset = -readRect.x1();
3501 readRect.width += readOffset;
3502
3503 int drawOffset = readToDrawX(readOffset);
3504 drawRect.width += drawOffset;
3505 }
3506
3507 if (readRect.y1() < 0)
3508 {
3509 int readOffset = -readRect.y1();
3510 readRect.height += readOffset;
3511
3512 int drawOffset = readToDrawY(readOffset);
3513 drawRect.height += drawOffset;
3514 }
3515
3516 if (readRect.x1() > readSize.width)
3517 {
3518 int delta = readRect.x1() - readSize.width;
3519 readRect.width -= delta;
3520 drawRect.width -= delta * flip(drawRect.width);
3521 }
3522
3523 if (readRect.y1() > readSize.height)
3524 {
3525 int delta = readRect.y1() - readSize.height;
3526 readRect.height -= delta;
3527 drawRect.height -= delta * flip(drawRect.height);
3528 }
3529
3530 bool scissorNeeded = scissor && gl::ClipRectangle(drawRect, *scissor, nullptr);
3531
3532 const auto &destFormatInfo =
3533 gl::GetSizedInternalFormatInfo(drawRenderTarget->getInternalFormat());
3534 const auto &srcFormatInfo =
3535 gl::GetSizedInternalFormatInfo(readRenderTarget->getInternalFormat());
3536 const auto &formatSet = drawRenderTarget11->getFormatSet();
3537 const auto &nativeFormat = formatSet.format();
3538
3539 // Some blits require masking off emulated texture channels. eg: from RGBA8 to RGB8, we
3540 // emulate RGB8 with RGBA8, so we need to mask off the alpha channel when we copy.
3541
3542 gl::Color<bool> colorMask;
3543 colorMask.red =
3544 (srcFormatInfo.redBits > 0) && (destFormatInfo.redBits == 0) && (nativeFormat.redBits > 0);
3545 colorMask.green = (srcFormatInfo.greenBits > 0) && (destFormatInfo.greenBits == 0) &&
3546 (nativeFormat.greenBits > 0);
3547 colorMask.blue = (srcFormatInfo.blueBits > 0) && (destFormatInfo.blueBits == 0) &&
3548 (nativeFormat.blueBits > 0);
3549 colorMask.alpha = (srcFormatInfo.alphaBits > 0) && (destFormatInfo.alphaBits == 0) &&
3550 (nativeFormat.alphaBits > 0);
3551
3552 // We only currently support masking off the alpha channel.
3553 bool colorMaskingNeeded = colorMask.alpha;
3554 ASSERT(!colorMask.red && !colorMask.green && !colorMask.blue);
3555
3556 bool wholeBufferCopy = !scissorNeeded && !colorMaskingNeeded && readRect.x == 0 &&
3557 readRect.width == readSize.width && readRect.y == 0 &&
3558 readRect.height == readSize.height && drawRect.x == 0 &&
3559 drawRect.width == drawSize.width && drawRect.y == 0 &&
3560 drawRect.height == drawSize.height;
3561
3562 bool stretchRequired = readRect.width != drawRect.width || readRect.height != drawRect.height;
3563
3564 bool flipRequired =
3565 readRect.width < 0 || readRect.height < 0 || drawRect.width < 0 || drawRect.height < 0;
3566
3567 bool outOfBounds = readRect.x < 0 || readRect.x + readRect.width > readSize.width ||
3568 readRect.y < 0 || readRect.y + readRect.height > readSize.height ||
3569 drawRect.x < 0 || drawRect.x + drawRect.width > drawSize.width ||
3570 drawRect.y < 0 || drawRect.y + drawRect.height > drawSize.height;
3571
3572 bool partialDSBlit =
3573 (nativeFormat.depthBits > 0 && depthBlit) != (nativeFormat.stencilBits > 0 && stencilBlit);
3574
3575 if (readRenderTarget11->getFormatSet().formatID ==
3576 drawRenderTarget11->getFormatSet().formatID &&
3577 !stretchRequired && !outOfBounds && !flipRequired && !partialDSBlit &&
3578 !colorMaskingNeeded && (!(depthBlit || stencilBlit) || wholeBufferCopy))
3579 {
3580 UINT dstX = drawRect.x;
3581 UINT dstY = drawRect.y;
3582
3583 D3D11_BOX readBox;
3584 readBox.left = readRect.x;
3585 readBox.right = readRect.x + readRect.width;
3586 readBox.top = readRect.y;
3587 readBox.bottom = readRect.y + readRect.height;
3588 readBox.front = 0;
3589 readBox.back = 1;
3590
3591 if (scissorNeeded)
3592 {
3593 // drawRect is guaranteed to have positive width and height because stretchRequired is
3594 // false.
3595 ASSERT(drawRect.width >= 0 || drawRect.height >= 0);
3596
3597 if (drawRect.x < scissor->x)
3598 {
3599 dstX = scissor->x;
3600 readBox.left += (scissor->x - drawRect.x);
3601 }
3602 if (drawRect.y < scissor->y)
3603 {
3604 dstY = scissor->y;
3605 readBox.top += (scissor->y - drawRect.y);
3606 }
3607 if (drawRect.x + drawRect.width > scissor->x + scissor->width)
3608 {
3609 readBox.right -= ((drawRect.x + drawRect.width) - (scissor->x + scissor->width));
3610 }
3611 if (drawRect.y + drawRect.height > scissor->y + scissor->height)
3612 {
3613 readBox.bottom -= ((drawRect.y + drawRect.height) - (scissor->y + scissor->height));
3614 }
3615 }
3616
3617 // D3D11 needs depth-stencil CopySubresourceRegions to have a NULL pSrcBox
3618 // We also require complete framebuffer copies for depth-stencil blit.
3619 D3D11_BOX *pSrcBox = wholeBufferCopy ? nullptr : &readBox;
3620
3621 mDeviceContext->CopySubresourceRegion(drawTexture.get(), drawSubresource, dstX, dstY, 0,
3622 readTexture.get(), readSubresource, pSrcBox);
3623 }
3624 else
3625 {
3626 gl::Box readArea(readRect.x, readRect.y, 0, readRect.width, readRect.height, 1);
3627 gl::Box drawArea(drawRect.x, drawRect.y, 0, drawRect.width, drawRect.height, 1);
3628
3629 if (depthBlit && stencilBlit)
3630 {
3631 ANGLE_TRY(mBlit->copyDepthStencil(readTexture, readSubresource, readArea, readSize,
3632 drawTexture, drawSubresource, drawArea, drawSize,
3633 scissor));
3634 }
3635 else if (depthBlit)
3636 {
3637 const d3d11::DepthStencilView &drawDSV = drawRenderTarget11->getDepthStencilView();
3638 ASSERT(readSRV.valid());
3639 ANGLE_TRY(mBlit->copyDepth(context, readSRV, readArea, readSize, drawDSV, drawArea,
3640 drawSize, scissor));
3641 }
3642 else if (stencilBlit)
3643 {
3644 ANGLE_TRY(mBlit->copyStencil(context, readTexture, readSubresource, readArea, readSize,
3645 drawTexture, drawSubresource, drawArea, drawSize,
3646 scissor));
3647 }
3648 else
3649 {
3650 const d3d11::RenderTargetView &drawRTV = drawRenderTarget11->getRenderTargetView();
3651
3652 // We don't currently support masking off any other channel than alpha
3653 bool maskOffAlpha = colorMaskingNeeded && colorMask.alpha;
3654 ASSERT(readSRV.valid());
3655 ANGLE_TRY(mBlit->copyTexture(
3656 context, readSRV, readArea, readSize, srcFormatInfo.format, drawRTV, drawArea,
3657 drawSize, scissor, destFormatInfo.format, filter, maskOffAlpha, false, false));
3658 }
3659 }
3660
3661 return gl::NoError();
3662 }
3663
isES3Capable() const3664 bool Renderer11::isES3Capable() const
3665 {
3666 return (d3d11_gl::GetMaximumClientVersion(mRenderer11DeviceCaps.featureLevel).major > 2);
3667 }
3668
getRendererClass() const3669 RendererClass Renderer11::getRendererClass() const
3670 {
3671 return RENDERER_D3D11;
3672 }
3673
onSwap()3674 void Renderer11::onSwap()
3675 {
3676 // Send histogram updates every half hour
3677 const double kHistogramUpdateInterval = 30 * 60;
3678
3679 auto *platform = ANGLEPlatformCurrent();
3680 const double currentTime = platform->monotonicallyIncreasingTime(platform);
3681 const double timeSinceLastUpdate = currentTime - mLastHistogramUpdateTime;
3682
3683 if (timeSinceLastUpdate > kHistogramUpdateInterval)
3684 {
3685 updateHistograms();
3686 mLastHistogramUpdateTime = currentTime;
3687 }
3688 }
3689
updateHistograms()3690 void Renderer11::updateHistograms()
3691 {
3692 // Update the buffer CPU memory histogram
3693 {
3694 size_t sizeSum = 0;
3695 for (const Buffer11 *buffer : mAliveBuffers)
3696 {
3697 sizeSum += buffer->getTotalCPUBufferMemoryBytes();
3698 }
3699 const int kOneMegaByte = 1024 * 1024;
3700 ANGLE_HISTOGRAM_MEMORY_MB("GPU.ANGLE.Buffer11CPUMemoryMB",
3701 static_cast<int>(sizeSum) / kOneMegaByte);
3702 }
3703 }
3704
onBufferCreate(const Buffer11 * created)3705 void Renderer11::onBufferCreate(const Buffer11 *created)
3706 {
3707 mAliveBuffers.insert(created);
3708 }
3709
onBufferDelete(const Buffer11 * deleted)3710 void Renderer11::onBufferDelete(const Buffer11 *deleted)
3711 {
3712 mAliveBuffers.erase(deleted);
3713 }
3714
resolveMultisampledTexture(const gl::Context * context,RenderTarget11 * renderTarget,bool depth,bool stencil)3715 gl::ErrorOrResult<TextureHelper11> Renderer11::resolveMultisampledTexture(
3716 const gl::Context *context,
3717 RenderTarget11 *renderTarget,
3718 bool depth,
3719 bool stencil)
3720 {
3721 if (depth && !stencil)
3722 {
3723 return mBlit->resolveDepth(context, renderTarget);
3724 }
3725
3726 if (stencil)
3727 {
3728 return mBlit->resolveStencil(context, renderTarget, depth);
3729 }
3730
3731 const auto &formatSet = renderTarget->getFormatSet();
3732
3733 ASSERT(renderTarget->isMultisampled());
3734 const d3d11::SharedSRV &sourceSRV = renderTarget->getShaderResourceView();
3735 D3D11_SHADER_RESOURCE_VIEW_DESC sourceSRVDesc;
3736 sourceSRV.get()->GetDesc(&sourceSRVDesc);
3737 ASSERT(sourceSRVDesc.ViewDimension == D3D_SRV_DIMENSION_TEXTURE2DMS);
3738
3739 if (!mCachedResolveTexture.valid() ||
3740 mCachedResolveTexture.getExtents().width != renderTarget->getWidth() ||
3741 mCachedResolveTexture.getExtents().height != renderTarget->getHeight() ||
3742 mCachedResolveTexture.getFormat() != formatSet.texFormat)
3743 {
3744 D3D11_TEXTURE2D_DESC resolveDesc;
3745 resolveDesc.Width = renderTarget->getWidth();
3746 resolveDesc.Height = renderTarget->getHeight();
3747 resolveDesc.MipLevels = 1;
3748 resolveDesc.ArraySize = 1;
3749 resolveDesc.Format = formatSet.texFormat;
3750 resolveDesc.SampleDesc.Count = 1;
3751 resolveDesc.SampleDesc.Quality = 0;
3752 resolveDesc.Usage = D3D11_USAGE_DEFAULT;
3753 resolveDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
3754 resolveDesc.CPUAccessFlags = 0;
3755 resolveDesc.MiscFlags = 0;
3756
3757 ANGLE_TRY(allocateTexture(resolveDesc, formatSet, &mCachedResolveTexture));
3758 }
3759
3760 mDeviceContext->ResolveSubresource(mCachedResolveTexture.get(), 0,
3761 renderTarget->getTexture().get(),
3762 renderTarget->getSubresourceIndex(), formatSet.texFormat);
3763 return mCachedResolveTexture;
3764 }
3765
getLUID(LUID * adapterLuid) const3766 bool Renderer11::getLUID(LUID *adapterLuid) const
3767 {
3768 adapterLuid->HighPart = 0;
3769 adapterLuid->LowPart = 0;
3770
3771 if (!mDxgiAdapter)
3772 {
3773 return false;
3774 }
3775
3776 DXGI_ADAPTER_DESC adapterDesc;
3777 if (FAILED(mDxgiAdapter->GetDesc(&adapterDesc)))
3778 {
3779 return false;
3780 }
3781
3782 *adapterLuid = adapterDesc.AdapterLuid;
3783 return true;
3784 }
3785
getVertexConversionType(gl::VertexFormatType vertexFormatType) const3786 VertexConversionType Renderer11::getVertexConversionType(
3787 gl::VertexFormatType vertexFormatType) const
3788 {
3789 return d3d11::GetVertexFormatInfo(vertexFormatType, mRenderer11DeviceCaps.featureLevel)
3790 .conversionType;
3791 }
3792
getVertexComponentType(gl::VertexFormatType vertexFormatType) const3793 GLenum Renderer11::getVertexComponentType(gl::VertexFormatType vertexFormatType) const
3794 {
3795 const auto &format =
3796 d3d11::GetVertexFormatInfo(vertexFormatType, mRenderer11DeviceCaps.featureLevel);
3797 return d3d11::GetComponentType(format.nativeFormat);
3798 }
3799
getVertexSpaceRequired(const gl::VertexAttribute & attrib,const gl::VertexBinding & binding,GLsizei count,GLsizei instances) const3800 gl::ErrorOrResult<unsigned int> Renderer11::getVertexSpaceRequired(
3801 const gl::VertexAttribute &attrib,
3802 const gl::VertexBinding &binding,
3803 GLsizei count,
3804 GLsizei instances) const
3805 {
3806 if (!attrib.enabled)
3807 {
3808 return 16u;
3809 }
3810
3811 unsigned int elementCount = 0;
3812 const unsigned int divisor = binding.getDivisor();
3813 if (instances == 0 || divisor == 0)
3814 {
3815 elementCount = count;
3816 }
3817 else
3818 {
3819 // Round up to divisor, if possible
3820 elementCount = UnsignedCeilDivide(static_cast<unsigned int>(instances), divisor);
3821 }
3822
3823 gl::VertexFormatType formatType = gl::GetVertexFormatType(attrib);
3824 const D3D_FEATURE_LEVEL featureLevel = mRenderer11DeviceCaps.featureLevel;
3825 const d3d11::VertexFormat &vertexFormatInfo =
3826 d3d11::GetVertexFormatInfo(formatType, featureLevel);
3827 const d3d11::DXGIFormatSize &dxgiFormatInfo =
3828 d3d11::GetDXGIFormatSizeInfo(vertexFormatInfo.nativeFormat);
3829 unsigned int elementSize = dxgiFormatInfo.pixelBytes;
3830 if (elementSize > std::numeric_limits<unsigned int>::max() / elementCount)
3831 {
3832 return gl::OutOfMemory() << "New vertex buffer size would result in an overflow.";
3833 }
3834
3835 return elementSize * elementCount;
3836 }
3837
generateCaps(gl::Caps * outCaps,gl::TextureCapsMap * outTextureCaps,gl::Extensions * outExtensions,gl::Limitations * outLimitations) const3838 void Renderer11::generateCaps(gl::Caps *outCaps,
3839 gl::TextureCapsMap *outTextureCaps,
3840 gl::Extensions *outExtensions,
3841 gl::Limitations *outLimitations) const
3842 {
3843 d3d11_gl::GenerateCaps(mDevice, mDeviceContext, mRenderer11DeviceCaps, outCaps, outTextureCaps,
3844 outExtensions, outLimitations);
3845 }
3846
generateWorkarounds() const3847 angle::WorkaroundsD3D Renderer11::generateWorkarounds() const
3848 {
3849 return d3d11::GenerateWorkarounds(mRenderer11DeviceCaps, mAdapterDescription);
3850 }
3851
getEGLDevice(DeviceImpl ** device)3852 egl::Error Renderer11::getEGLDevice(DeviceImpl **device)
3853 {
3854 if (mEGLDevice == nullptr)
3855 {
3856 ASSERT(mDevice != nullptr);
3857 mEGLDevice = new DeviceD3D();
3858 egl::Error error = mEGLDevice->initialize(reinterpret_cast<void *>(mDevice),
3859 EGL_D3D11_DEVICE_ANGLE, EGL_FALSE);
3860
3861 if (error.isError())
3862 {
3863 SafeDelete(mEGLDevice);
3864 return error;
3865 }
3866 }
3867
3868 *device = static_cast<DeviceImpl *>(mEGLDevice);
3869 return egl::NoError();
3870 }
3871
createContext(const gl::ContextState & state)3872 ContextImpl *Renderer11::createContext(const gl::ContextState &state)
3873 {
3874 return new Context11(state, this);
3875 }
3876
createDefaultFramebuffer(const gl::FramebufferState & state)3877 FramebufferImpl *Renderer11::createDefaultFramebuffer(const gl::FramebufferState &state)
3878 {
3879 return new Framebuffer11(state, this);
3880 }
3881
getScratchMemoryBuffer(size_t requestedSize,angle::MemoryBuffer ** bufferOut)3882 gl::Error Renderer11::getScratchMemoryBuffer(size_t requestedSize, angle::MemoryBuffer **bufferOut)
3883 {
3884 if (!mScratchMemoryBuffer.get(requestedSize, bufferOut))
3885 {
3886 return gl::OutOfMemory() << "Failed to allocate internal buffer.";
3887 }
3888 return gl::NoError();
3889 }
3890
getMaxSupportedESVersion() const3891 gl::Version Renderer11::getMaxSupportedESVersion() const
3892 {
3893 return d3d11_gl::GetMaximumClientVersion(mRenderer11DeviceCaps.featureLevel);
3894 }
3895
getAnnotator()3896 gl::DebugAnnotator *Renderer11::getAnnotator()
3897 {
3898 return mAnnotator;
3899 }
3900
applyComputeShader(const gl::Context * context)3901 gl::Error Renderer11::applyComputeShader(const gl::Context *context)
3902 {
3903 ANGLE_TRY(ensureHLSLCompilerInitialized());
3904
3905 const auto &glState = context->getGLState();
3906 ProgramD3D *programD3D = GetImplAs<ProgramD3D>(glState.getProgram());
3907
3908 ShaderExecutableD3D *computeExe = nullptr;
3909 ANGLE_TRY(programD3D->getComputeExecutable(&computeExe));
3910 ASSERT(computeExe != nullptr);
3911
3912 mStateManager.setComputeShader(&GetAs<ShaderExecutable11>(computeExe)->getComputeShader());
3913 ANGLE_TRY(mStateManager.applyComputeUniforms(programD3D));
3914
3915 return gl::NoError();
3916 }
3917
dispatchCompute(const gl::Context * context,GLuint numGroupsX,GLuint numGroupsY,GLuint numGroupsZ)3918 gl::Error Renderer11::dispatchCompute(const gl::Context *context,
3919 GLuint numGroupsX,
3920 GLuint numGroupsY,
3921 GLuint numGroupsZ)
3922 {
3923 ANGLE_TRY(mStateManager.updateStateForCompute(context, numGroupsX, numGroupsY, numGroupsZ));
3924 ANGLE_TRY(applyComputeShader(context));
3925
3926 mDeviceContext->Dispatch(numGroupsX, numGroupsY, numGroupsZ);
3927
3928 return gl::NoError();
3929 }
3930
createStagingTexture(ResourceType textureType,const d3d11::Format & formatSet,const gl::Extents & size,StagingAccess readAndWriteAccess)3931 gl::ErrorOrResult<TextureHelper11> Renderer11::createStagingTexture(
3932 ResourceType textureType,
3933 const d3d11::Format &formatSet,
3934 const gl::Extents &size,
3935 StagingAccess readAndWriteAccess)
3936 {
3937 if (textureType == ResourceType::Texture2D)
3938 {
3939 D3D11_TEXTURE2D_DESC stagingDesc;
3940 stagingDesc.Width = size.width;
3941 stagingDesc.Height = size.height;
3942 stagingDesc.MipLevels = 1;
3943 stagingDesc.ArraySize = 1;
3944 stagingDesc.Format = formatSet.texFormat;
3945 stagingDesc.SampleDesc.Count = 1;
3946 stagingDesc.SampleDesc.Quality = 0;
3947 stagingDesc.Usage = D3D11_USAGE_STAGING;
3948 stagingDesc.BindFlags = 0;
3949 stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
3950 stagingDesc.MiscFlags = 0;
3951
3952 if (readAndWriteAccess == StagingAccess::READ_WRITE)
3953 {
3954 stagingDesc.CPUAccessFlags |= D3D11_CPU_ACCESS_WRITE;
3955 }
3956
3957 TextureHelper11 stagingTex;
3958 ANGLE_TRY(allocateTexture(stagingDesc, formatSet, &stagingTex));
3959 return stagingTex;
3960 }
3961 ASSERT(textureType == ResourceType::Texture3D);
3962
3963 D3D11_TEXTURE3D_DESC stagingDesc;
3964 stagingDesc.Width = size.width;
3965 stagingDesc.Height = size.height;
3966 stagingDesc.Depth = 1;
3967 stagingDesc.MipLevels = 1;
3968 stagingDesc.Format = formatSet.texFormat;
3969 stagingDesc.Usage = D3D11_USAGE_STAGING;
3970 stagingDesc.BindFlags = 0;
3971 stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
3972 stagingDesc.MiscFlags = 0;
3973
3974 TextureHelper11 stagingTex;
3975 ANGLE_TRY(allocateTexture(stagingDesc, formatSet, &stagingTex));
3976 return stagingTex;
3977 }
3978
allocateTexture(const D3D11_TEXTURE2D_DESC & desc,const d3d11::Format & format,const D3D11_SUBRESOURCE_DATA * initData,TextureHelper11 * textureOut)3979 gl::Error Renderer11::allocateTexture(const D3D11_TEXTURE2D_DESC &desc,
3980 const d3d11::Format &format,
3981 const D3D11_SUBRESOURCE_DATA *initData,
3982 TextureHelper11 *textureOut)
3983 {
3984 d3d11::Texture2D texture;
3985 ANGLE_TRY(mResourceManager11.allocate(this, &desc, initData, &texture));
3986 textureOut->init(std::move(texture), desc, format);
3987 return gl::NoError();
3988 }
3989
allocateTexture(const D3D11_TEXTURE3D_DESC & desc,const d3d11::Format & format,const D3D11_SUBRESOURCE_DATA * initData,TextureHelper11 * textureOut)3990 gl::Error Renderer11::allocateTexture(const D3D11_TEXTURE3D_DESC &desc,
3991 const d3d11::Format &format,
3992 const D3D11_SUBRESOURCE_DATA *initData,
3993 TextureHelper11 *textureOut)
3994 {
3995 d3d11::Texture3D texture;
3996 ANGLE_TRY(mResourceManager11.allocate(this, &desc, initData, &texture));
3997 textureOut->init(std::move(texture), desc, format);
3998 return gl::NoError();
3999 }
4000
getBlendState(const d3d11::BlendStateKey & key,const d3d11::BlendState ** outBlendState)4001 gl::Error Renderer11::getBlendState(const d3d11::BlendStateKey &key,
4002 const d3d11::BlendState **outBlendState)
4003 {
4004 return mStateCache.getBlendState(this, key, outBlendState);
4005 }
4006
getRasterizerState(const gl::RasterizerState & rasterState,bool scissorEnabled,ID3D11RasterizerState ** outRasterizerState)4007 gl::Error Renderer11::getRasterizerState(const gl::RasterizerState &rasterState,
4008 bool scissorEnabled,
4009 ID3D11RasterizerState **outRasterizerState)
4010 {
4011 return mStateCache.getRasterizerState(this, rasterState, scissorEnabled, outRasterizerState);
4012 }
4013
getDepthStencilState(const gl::DepthStencilState & dsState,const d3d11::DepthStencilState ** outDSState)4014 gl::Error Renderer11::getDepthStencilState(const gl::DepthStencilState &dsState,
4015 const d3d11::DepthStencilState **outDSState)
4016 {
4017 return mStateCache.getDepthStencilState(this, dsState, outDSState);
4018 }
4019
getSamplerState(const gl::SamplerState & samplerState,ID3D11SamplerState ** outSamplerState)4020 gl::Error Renderer11::getSamplerState(const gl::SamplerState &samplerState,
4021 ID3D11SamplerState **outSamplerState)
4022 {
4023 return mStateCache.getSamplerState(this, samplerState, outSamplerState);
4024 }
4025
clearRenderTarget(RenderTargetD3D * renderTarget,const gl::ColorF & clearColorValue,const float clearDepthValue,const unsigned int clearStencilValue)4026 gl::Error Renderer11::clearRenderTarget(RenderTargetD3D *renderTarget,
4027 const gl::ColorF &clearColorValue,
4028 const float clearDepthValue,
4029 const unsigned int clearStencilValue)
4030 {
4031 RenderTarget11 *rt11 = GetAs<RenderTarget11>(renderTarget);
4032
4033 if (rt11->getDepthStencilView().valid())
4034 {
4035 const auto &format = rt11->getFormatSet();
4036 const UINT clearFlags = (format.format().depthBits > 0 ? D3D11_CLEAR_DEPTH : 0) |
4037 (format.format().stencilBits ? D3D11_CLEAR_STENCIL : 0);
4038 mDeviceContext->ClearDepthStencilView(rt11->getDepthStencilView().get(), clearFlags,
4039 clearDepthValue,
4040 static_cast<UINT8>(clearStencilValue));
4041 return gl::NoError();
4042 }
4043
4044 ASSERT(rt11->getRenderTargetView().valid());
4045 ID3D11RenderTargetView *rtv = rt11->getRenderTargetView().get();
4046
4047 // There are complications with some types of RTV and FL 9_3 with ClearRenderTargetView.
4048 // See https://msdn.microsoft.com/en-us/library/windows/desktop/ff476388(v=vs.85).aspx
4049 ASSERT(mRenderer11DeviceCaps.featureLevel > D3D_FEATURE_LEVEL_9_3 || !IsArrayRTV(rtv));
4050
4051 const auto &d3d11Format = rt11->getFormatSet();
4052 const auto &glFormat = gl::GetSizedInternalFormatInfo(renderTarget->getInternalFormat());
4053
4054 gl::ColorF safeClearColor = clearColorValue;
4055
4056 if (d3d11Format.format().alphaBits > 0 && glFormat.alphaBits == 0)
4057 {
4058 safeClearColor.alpha = 1.0f;
4059 }
4060
4061 mDeviceContext->ClearRenderTargetView(rtv, &safeClearColor.red);
4062 return gl::NoError();
4063 }
4064
canSelectViewInVertexShader() const4065 bool Renderer11::canSelectViewInVertexShader() const
4066 {
4067 return !getWorkarounds().selectViewInGeometryShader &&
4068 getRenderer11DeviceCaps().supportsVpRtIndexWriteFromVertexShader;
4069 }
4070
markTransformFeedbackUsage(const gl::Context * context)4071 gl::Error Renderer11::markTransformFeedbackUsage(const gl::Context *context)
4072 {
4073 const gl::State &glState = context->getGLState();
4074 const gl::TransformFeedback *transformFeedback = glState.getCurrentTransformFeedback();
4075 for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
4076 {
4077 const gl::OffsetBindingPointer<gl::Buffer> &binding =
4078 transformFeedback->getIndexedBuffer(i);
4079 if (binding.get() != nullptr)
4080 {
4081 BufferD3D *bufferD3D = GetImplAs<BufferD3D>(binding.get());
4082 ANGLE_TRY(bufferD3D->markTransformFeedbackUsage(context));
4083 }
4084 }
4085
4086 return gl::NoError();
4087 }
4088
4089 } // namespace rx
4090