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 &currentValueAttribs = 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 &params,
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