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