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