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