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