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