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