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