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 ¶ms,
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