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