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