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