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