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