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