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