summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp')
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp4089
1 files changed, 0 insertions, 4089 deletions
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
deleted file mode 100644
index b0ef9abddc..0000000000
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
+++ /dev/null
@@ -1,4089 +0,0 @@
-//
-// Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Renderer11.cpp: Implements a back-end specific class for the D3D11 renderer.
-
-#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
-
-#include <EGL/eglext.h>
-#include <versionhelpers.h>
-#include <sstream>
-
-#include "common/tls.h"
-#include "common/utilities.h"
-#include "libANGLE/Buffer.h"
-#include "libANGLE/Context.h"
-#include "libANGLE/Display.h"
-#include "libANGLE/Framebuffer.h"
-#include "libANGLE/FramebufferAttachment.h"
-#include "libANGLE/Program.h"
-#include "libANGLE/State.h"
-#include "libANGLE/Surface.h"
-#include "libANGLE/formatutils.h"
-#include "libANGLE/histogram_macros.h"
-#include "libANGLE/renderer/d3d/CompilerD3D.h"
-#include "libANGLE/renderer/d3d/DeviceD3D.h"
-#include "libANGLE/renderer/d3d/DisplayD3D.h"
-#include "libANGLE/renderer/d3d/FramebufferD3D.h"
-#include "libANGLE/renderer/d3d/IndexDataManager.h"
-#include "libANGLE/renderer/d3d/ProgramD3D.h"
-#include "libANGLE/renderer/d3d/RenderbufferD3D.h"
-#include "libANGLE/renderer/d3d/ShaderD3D.h"
-#include "libANGLE/renderer/d3d/SurfaceD3D.h"
-#include "libANGLE/renderer/d3d/TextureD3D.h"
-#include "libANGLE/renderer/d3d/VertexDataManager.h"
-#include "libANGLE/renderer/d3d/d3d11/Blit11.h"
-#include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
-#include "libANGLE/renderer/d3d/d3d11/Clear11.h"
-#include "libANGLE/renderer/d3d/d3d11/Context11.h"
-#include "libANGLE/renderer/d3d/d3d11/Fence11.h"
-#include "libANGLE/renderer/d3d/d3d11/Framebuffer11.h"
-#include "libANGLE/renderer/d3d/d3d11/Image11.h"
-#include "libANGLE/renderer/d3d/d3d11/IndexBuffer11.h"
-#include "libANGLE/renderer/d3d/d3d11/PixelTransfer11.h"
-#include "libANGLE/renderer/d3d/d3d11/Query11.h"
-#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
-#include "libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h"
-#include "libANGLE/renderer/d3d/d3d11/StreamProducerNV12.h"
-#include "libANGLE/renderer/d3d/d3d11/SwapChain11.h"
-#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h"
-#include "libANGLE/renderer/d3d/d3d11/TransformFeedback11.h"
-#include "libANGLE/renderer/d3d/d3d11/Trim11.h"
-#include "libANGLE/renderer/d3d/d3d11/VertexArray11.h"
-#include "libANGLE/renderer/d3d/d3d11/VertexBuffer11.h"
-#include "libANGLE/renderer/d3d/d3d11/dxgi_support_table.h"
-#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
-#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
-#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
-#include "libANGLE/renderer/renderer_utils.h"
-#include "third_party/trace_event/trace_event.h"
-
-#ifdef ANGLE_ENABLE_WINDOWS_STORE
-#include "libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.h"
-#else
-#include "libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.h"
-#endif
-
-// Include the D3D9 debug annotator header for use by the desktop D3D11 renderer
-// because the D3D11 interface method ID3DUserDefinedAnnotation::GetStatus
-// doesn't work with the Graphics Diagnostics tools in Visual Studio 2013.
-#ifdef ANGLE_ENABLE_D3D9
-#include "libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h"
-#endif
-
-// Enable ANGLE_SKIP_DXGI_1_2_CHECK if there is not a possibility of using cross-process
-// HWNDs or the Windows 7 Platform Update (KB2670838) is expected to be installed.
-#ifndef ANGLE_SKIP_DXGI_1_2_CHECK
-#define ANGLE_SKIP_DXGI_1_2_CHECK 0
-#endif
-
-namespace rx
-{
-
-namespace
-{
-
-enum
-{
- MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 = 16
-};
-
-enum ANGLEFeatureLevel
-{
- ANGLE_FEATURE_LEVEL_INVALID,
- ANGLE_FEATURE_LEVEL_9_3,
- ANGLE_FEATURE_LEVEL_10_0,
- ANGLE_FEATURE_LEVEL_10_1,
- ANGLE_FEATURE_LEVEL_11_0,
- ANGLE_FEATURE_LEVEL_11_1,
- NUM_ANGLE_FEATURE_LEVELS
-};
-
-ANGLEFeatureLevel GetANGLEFeatureLevel(D3D_FEATURE_LEVEL d3dFeatureLevel)
-{
- switch (d3dFeatureLevel)
- {
- case D3D_FEATURE_LEVEL_9_3:
- return ANGLE_FEATURE_LEVEL_9_3;
- case D3D_FEATURE_LEVEL_10_0:
- return ANGLE_FEATURE_LEVEL_10_0;
- case D3D_FEATURE_LEVEL_10_1:
- return ANGLE_FEATURE_LEVEL_10_1;
- case D3D_FEATURE_LEVEL_11_0:
- return ANGLE_FEATURE_LEVEL_11_0;
- case D3D_FEATURE_LEVEL_11_1:
- return ANGLE_FEATURE_LEVEL_11_1;
- default:
- return ANGLE_FEATURE_LEVEL_INVALID;
- }
-}
-
-void SetLineLoopIndices(GLuint *dest, size_t count)
-{
- for (size_t i = 0; i < count; i++)
- {
- dest[i] = static_cast<GLuint>(i);
- }
- dest[count] = 0;
-}
-
-template <typename T>
-void CopyLineLoopIndices(const void *indices, GLuint *dest, size_t count)
-{
- const T *srcPtr = static_cast<const T *>(indices);
- for (size_t i = 0; i < count; ++i)
- {
- dest[i] = static_cast<GLuint>(srcPtr[i]);
- }
- dest[count] = static_cast<GLuint>(srcPtr[0]);
-}
-
-void SetTriangleFanIndices(GLuint *destPtr, size_t numTris)
-{
- for (size_t i = 0; i < numTris; i++)
- {
- destPtr[i * 3 + 0] = 0;
- destPtr[i * 3 + 1] = static_cast<GLuint>(i) + 1;
- destPtr[i * 3 + 2] = static_cast<GLuint>(i) + 2;
- }
-}
-
-template <typename T>
-void CopyLineLoopIndicesWithRestart(const void *indices,
- size_t count,
- GLenum indexType,
- std::vector<GLuint> *bufferOut)
-{
- GLuint restartIndex = gl::GetPrimitiveRestartIndex(indexType);
- GLuint d3dRestartIndex = static_cast<GLuint>(d3d11::GetPrimitiveRestartIndex());
- const T *srcPtr = static_cast<const T *>(indices);
- Optional<GLuint> currentLoopStart;
-
- bufferOut->clear();
-
- for (size_t indexIdx = 0; indexIdx < count; ++indexIdx)
- {
- GLuint value = static_cast<GLuint>(srcPtr[indexIdx]);
-
- if (value == restartIndex)
- {
- if (currentLoopStart.valid())
- {
- bufferOut->push_back(currentLoopStart.value());
- bufferOut->push_back(d3dRestartIndex);
- currentLoopStart.reset();
- }
- }
- else
- {
- bufferOut->push_back(value);
- if (!currentLoopStart.valid())
- {
- currentLoopStart = value;
- }
- }
- }
-
- if (currentLoopStart.valid())
- {
- bufferOut->push_back(currentLoopStart.value());
- }
-}
-
-void GetLineLoopIndices(const void *indices,
- GLenum indexType,
- GLuint count,
- bool usePrimitiveRestartFixedIndex,
- std::vector<GLuint> *bufferOut)
-{
- if (indexType != GL_NONE && usePrimitiveRestartFixedIndex)
- {
- switch (indexType)
- {
- case GL_UNSIGNED_BYTE:
- CopyLineLoopIndicesWithRestart<GLubyte>(indices, count, indexType, bufferOut);
- break;
- case GL_UNSIGNED_SHORT:
- CopyLineLoopIndicesWithRestart<GLushort>(indices, count, indexType, bufferOut);
- break;
- case GL_UNSIGNED_INT:
- CopyLineLoopIndicesWithRestart<GLuint>(indices, count, indexType, bufferOut);
- break;
- default:
- UNREACHABLE();
- break;
- }
- return;
- }
-
- // For non-primitive-restart draws, the index count is static.
- bufferOut->resize(static_cast<size_t>(count) + 1);
-
- switch (indexType)
- {
- // Non-indexed draw
- case GL_NONE:
- SetLineLoopIndices(&(*bufferOut)[0], count);
- break;
- case GL_UNSIGNED_BYTE:
- CopyLineLoopIndices<GLubyte>(indices, &(*bufferOut)[0], count);
- break;
- case GL_UNSIGNED_SHORT:
- CopyLineLoopIndices<GLushort>(indices, &(*bufferOut)[0], count);
- break;
- case GL_UNSIGNED_INT:
- CopyLineLoopIndices<GLuint>(indices, &(*bufferOut)[0], count);
- break;
- default:
- UNREACHABLE();
- break;
- }
-}
-
-template <typename T>
-void CopyTriangleFanIndices(const void *indices, GLuint *destPtr, size_t numTris)
-{
- const T *srcPtr = static_cast<const T *>(indices);
-
- for (size_t i = 0; i < numTris; i++)
- {
- destPtr[i * 3 + 0] = static_cast<GLuint>(srcPtr[0]);
- destPtr[i * 3 + 1] = static_cast<GLuint>(srcPtr[i + 1]);
- destPtr[i * 3 + 2] = static_cast<GLuint>(srcPtr[i + 2]);
- }
-}
-
-template <typename T>
-void CopyTriangleFanIndicesWithRestart(const void *indices,
- GLuint indexCount,
- GLenum indexType,
- std::vector<GLuint> *bufferOut)
-{
- GLuint restartIndex = gl::GetPrimitiveRestartIndex(indexType);
- GLuint d3dRestartIndex = gl::GetPrimitiveRestartIndex(GL_UNSIGNED_INT);
- const T *srcPtr = static_cast<const T *>(indices);
- Optional<GLuint> vertexA;
- Optional<GLuint> vertexB;
-
- bufferOut->clear();
-
- for (size_t indexIdx = 0; indexIdx < indexCount; ++indexIdx)
- {
- GLuint value = static_cast<GLuint>(srcPtr[indexIdx]);
-
- if (value == restartIndex)
- {
- bufferOut->push_back(d3dRestartIndex);
- vertexA.reset();
- vertexB.reset();
- }
- else
- {
- if (!vertexA.valid())
- {
- vertexA = value;
- }
- else if (!vertexB.valid())
- {
- vertexB = value;
- }
- else
- {
- bufferOut->push_back(vertexA.value());
- bufferOut->push_back(vertexB.value());
- bufferOut->push_back(value);
- vertexB = value;
- }
- }
- }
-}
-
-void GetTriFanIndices(const void *indices,
- GLenum indexType,
- GLuint count,
- bool usePrimitiveRestartFixedIndex,
- std::vector<GLuint> *bufferOut)
-{
- if (indexType != GL_NONE && usePrimitiveRestartFixedIndex)
- {
- switch (indexType)
- {
- case GL_UNSIGNED_BYTE:
- CopyTriangleFanIndicesWithRestart<GLubyte>(indices, count, indexType, bufferOut);
- break;
- case GL_UNSIGNED_SHORT:
- CopyTriangleFanIndicesWithRestart<GLushort>(indices, count, indexType, bufferOut);
- break;
- case GL_UNSIGNED_INT:
- CopyTriangleFanIndicesWithRestart<GLuint>(indices, count, indexType, bufferOut);
- break;
- default:
- UNREACHABLE();
- break;
- }
- return;
- }
-
- // For non-primitive-restart draws, the index count is static.
- GLuint numTris = count - 2;
- bufferOut->resize(numTris * 3);
-
- switch (indexType)
- {
- // Non-indexed draw
- case GL_NONE:
- SetTriangleFanIndices(&(*bufferOut)[0], numTris);
- break;
- case GL_UNSIGNED_BYTE:
- CopyTriangleFanIndices<GLubyte>(indices, &(*bufferOut)[0], numTris);
- break;
- case GL_UNSIGNED_SHORT:
- CopyTriangleFanIndices<GLushort>(indices, &(*bufferOut)[0], numTris);
- break;
- case GL_UNSIGNED_INT:
- CopyTriangleFanIndices<GLuint>(indices, &(*bufferOut)[0], numTris);
- break;
- default:
- UNREACHABLE();
- break;
- }
-}
-
-bool DrawCallNeedsTranslation(const gl::Context *context, GLenum mode)
-{
- const auto &glState = context->getGLState();
- const gl::VertexArray *vertexArray = glState.getVertexArray();
- VertexArray11 *vertexArray11 = GetImplAs<VertexArray11>(vertexArray);
- // Direct drawing doesn't support dynamic attribute storage since it needs the first and count
- // to translate when applyVertexBuffer. GL_LINE_LOOP and GL_TRIANGLE_FAN are not supported
- // either since we need to simulate them in D3D.
- if (vertexArray11->hasActiveDynamicAttrib(context) || mode == GL_LINE_LOOP ||
- mode == GL_TRIANGLE_FAN)
- {
- return true;
- }
-
- ProgramD3D *programD3D = GetImplAs<ProgramD3D>(glState.getProgram());
- if (InstancedPointSpritesActive(programD3D, mode))
- {
- return true;
- }
-
- return false;
-}
-
-bool IsArrayRTV(ID3D11RenderTargetView *rtv)
-{
- D3D11_RENDER_TARGET_VIEW_DESC desc;
- rtv->GetDesc(&desc);
- if (desc.ViewDimension == D3D11_RTV_DIMENSION_TEXTURE1DARRAY &&
- desc.Texture1DArray.ArraySize > 1)
- return true;
- if (desc.ViewDimension == D3D11_RTV_DIMENSION_TEXTURE2DARRAY &&
- desc.Texture2DArray.ArraySize > 1)
- return true;
- if (desc.ViewDimension == D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY &&
- desc.Texture2DMSArray.ArraySize > 1)
- return true;
- return false;
-}
-
-int GetAdjustedInstanceCount(const gl::Program *program, int instanceCount)
-{
- if (!program->usesMultiview())
- {
- return instanceCount;
- }
- if (instanceCount == 0)
- {
- return program->getNumViews();
- }
- return program->getNumViews() * instanceCount;
-}
-
-const uint32_t ScratchMemoryBufferLifetime = 1000;
-
-void PopulateFormatDeviceCaps(ID3D11Device *device,
- DXGI_FORMAT format,
- UINT *outSupport,
- UINT *outMaxSamples)
-{
- if (FAILED(device->CheckFormatSupport(format, outSupport)))
- {
- *outSupport = 0;
- }
-
- *outMaxSamples = 0;
- for (UINT sampleCount = 2; sampleCount <= D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; sampleCount *= 2)
- {
- UINT qualityCount = 0;
- if (FAILED(device->CheckMultisampleQualityLevels(format, sampleCount, &qualityCount)) ||
- qualityCount == 0)
- {
- break;
- }
-
- *outMaxSamples = sampleCount;
- }
-}
-
-bool CullsEverything(const gl::State &glState)
-{
- return (glState.getRasterizerState().cullFace &&
- glState.getRasterizerState().cullMode == gl::CullFaceMode::FrontAndBack);
-}
-
-} // anonymous namespace
-
-Renderer11DeviceCaps::Renderer11DeviceCaps() = default;
-
-Renderer11::Renderer11(egl::Display *display)
- : RendererD3D(display),
- mCreateDebugDevice(false),
- mStateCache(),
- mStateManager(this),
- mLastHistogramUpdateTime(
- ANGLEPlatformCurrent()->monotonicallyIncreasingTime(ANGLEPlatformCurrent())),
- mDebug(nullptr),
- mScratchMemoryBuffer(ScratchMemoryBufferLifetime),
- mAnnotator(nullptr)
-{
- mLineLoopIB = nullptr;
- mTriangleFanIB = nullptr;
-
- mBlit = nullptr;
- mPixelTransfer = nullptr;
-
- mClear = nullptr;
-
- mTrim = nullptr;
-
- mRenderer11DeviceCaps.supportsClearView = false;
- mRenderer11DeviceCaps.supportsConstantBufferOffsets = false;
- mRenderer11DeviceCaps.supportsVpRtIndexWriteFromVertexShader = false;
- mRenderer11DeviceCaps.supportsDXGI1_2 = false;
- mRenderer11DeviceCaps.B5G6R5support = 0;
- mRenderer11DeviceCaps.B4G4R4A4support = 0;
- mRenderer11DeviceCaps.B5G5R5A1support = 0;
-
- mD3d11Module = nullptr;
- mDxgiModule = nullptr;
- mDCompModule = nullptr;
- mCreatedWithDeviceEXT = false;
- mEGLDevice = nullptr;
-
- mDevice = nullptr;
- mDeviceContext = nullptr;
- mDeviceContext1 = nullptr;
- mDeviceContext3 = nullptr;
- mDxgiAdapter = nullptr;
- mDxgiFactory = nullptr;
-
- ZeroMemory(&mAdapterDescription, sizeof(mAdapterDescription));
-
- if (mDisplay->getPlatform() == EGL_PLATFORM_ANGLE_ANGLE)
- {
- const auto &attributes = mDisplay->getAttributeMap();
-
- EGLint requestedMajorVersion = static_cast<EGLint>(
- attributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE));
- EGLint requestedMinorVersion = static_cast<EGLint>(
- attributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE));
-
- if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 11)
- {
- if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 1)
- {
- // This could potentially lead to failed context creation if done on a system
- // without the platform update which installs DXGI 1.2. Currently, for Chrome users
- // D3D11 contexts are only created if the platform update is available, so this
- // should not cause any issues.
- mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_11_1);
- }
- if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 0)
- {
- mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_11_0);
- }
- }
-
- if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 10)
- {
- if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 1)
- {
- mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_10_1);
- }
- if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 0)
- {
- mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_10_0);
- }
- }
-
- if (requestedMajorVersion == 9 && requestedMinorVersion == 3)
- {
- if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 3)
- {
- mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_3);
- }
-#if defined(ANGLE_ENABLE_WINDOWS_STORE)
- if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 2)
- {
- mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_2);
- }
- if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 1)
- {
- mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_1);
- }
-#endif
- }
-
- EGLint requestedDeviceType = static_cast<EGLint>(attributes.get(
- EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE));
- switch (requestedDeviceType)
- {
- case EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE:
- mRequestedDriverType = D3D_DRIVER_TYPE_HARDWARE;
- break;
-
- case EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE:
- mRequestedDriverType = D3D_DRIVER_TYPE_WARP;
- break;
-
- case EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE:
- mRequestedDriverType = D3D_DRIVER_TYPE_REFERENCE;
- break;
-
- case EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE:
- mRequestedDriverType = D3D_DRIVER_TYPE_NULL;
- break;
-
- default:
- UNREACHABLE();
- }
-
- const EGLenum presentPath = static_cast<EGLenum>(attributes.get(
- EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE, EGL_EXPERIMENTAL_PRESENT_PATH_COPY_ANGLE));
- mPresentPathFastEnabled = (presentPath == EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE);
-
- mCreateDebugDevice = ShouldUseDebugLayers(attributes);
- }
- else if (display->getPlatform() == EGL_PLATFORM_DEVICE_EXT)
- {
- mEGLDevice = GetImplAs<DeviceD3D>(display->getDevice());
- ASSERT(mEGLDevice != nullptr);
- mCreatedWithDeviceEXT = true;
-
- // Also set EGL_PLATFORM_ANGLE_ANGLE variables, in case they're used elsewhere in ANGLE
- // mAvailableFeatureLevels defaults to empty
- mRequestedDriverType = D3D_DRIVER_TYPE_UNKNOWN;
- mPresentPathFastEnabled = false;
- }
-
-// The D3D11 renderer must choose the D3D9 debug annotator because the D3D11 interface
-// method ID3DUserDefinedAnnotation::GetStatus on desktop builds doesn't work with the Graphics
-// Diagnostics tools in Visual Studio 2013.
-// The D3D9 annotator works properly for both D3D11 and D3D9.
-// Incorrect status reporting can cause ANGLE to log unnecessary debug events.
-#ifdef ANGLE_ENABLE_D3D9
- mAnnotator = new DebugAnnotator9();
-#else
- mAnnotator = new DebugAnnotator11();
-#endif
- ASSERT(mAnnotator);
- gl::InitializeDebugAnnotations(mAnnotator);
-}
-
-Renderer11::~Renderer11()
-{
- release();
-}
-
-#ifndef __d3d11_1_h__
-#define D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET ((D3D11_MESSAGE_ID)3146081)
-#endif
-
-egl::Error Renderer11::initialize()
-{
- HRESULT result = S_OK;
-
- ANGLE_TRY(initializeD3DDevice());
-
-#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
-#if !ANGLE_SKIP_DXGI_1_2_CHECK
- {
- TRACE_EVENT0("gpu.angle", "Renderer11::initialize (DXGICheck)");
- // In order to create a swap chain for an HWND owned by another process, DXGI 1.2 is
- // required.
- // The easiest way to check is to query for a IDXGIDevice2.
- bool requireDXGI1_2 = false;
- HWND hwnd = WindowFromDC(mDisplay->getNativeDisplayId());
- if (hwnd)
- {
- DWORD currentProcessId = GetCurrentProcessId();
- DWORD wndProcessId;
- GetWindowThreadProcessId(hwnd, &wndProcessId);
- requireDXGI1_2 = (currentProcessId != wndProcessId);
- }
- else
- {
- requireDXGI1_2 = true;
- }
-
- if (requireDXGI1_2)
- {
- IDXGIDevice2 *dxgiDevice2 = nullptr;
- result = mDevice->QueryInterface(__uuidof(IDXGIDevice2), (void **)&dxgiDevice2);
- if (FAILED(result))
- {
- return egl::EglNotInitialized(D3D11_INIT_INCOMPATIBLE_DXGI)
- << "DXGI 1.2 required to present to HWNDs owned by another process.";
- }
- SafeRelease(dxgiDevice2);
- }
- }
-#endif
-#endif
-
- {
- TRACE_EVENT0("gpu.angle", "Renderer11::initialize (ComQueries)");
- // Cast the DeviceContext to a DeviceContext1 and DeviceContext3.
- // This could fail on Windows 7 without the Platform Update.
- // Don't error in this case- just don't use mDeviceContext1 or mDeviceContext3.
- mDeviceContext1 = d3d11::DynamicCastComObject<ID3D11DeviceContext1>(mDeviceContext);
- mDeviceContext3 = d3d11::DynamicCastComObject<ID3D11DeviceContext3>(mDeviceContext);
-
- IDXGIDevice *dxgiDevice = nullptr;
- result = mDevice->QueryInterface(__uuidof(IDXGIDevice), (void **)&dxgiDevice);
-
- if (FAILED(result))
- {
- return egl::EglNotInitialized(D3D11_INIT_OTHER_ERROR) << "Could not query DXGI device.";
- }
-
- result = dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void **)&mDxgiAdapter);
-
- if (FAILED(result))
- {
- return egl::EglNotInitialized(D3D11_INIT_OTHER_ERROR)
- << "Could not retrieve DXGI adapter";
- }
-
- SafeRelease(dxgiDevice);
-
- IDXGIAdapter2 *dxgiAdapter2 = d3d11::DynamicCastComObject<IDXGIAdapter2>(mDxgiAdapter);
-
- // On D3D_FEATURE_LEVEL_9_*, IDXGIAdapter::GetDesc returns "Software Adapter" for the
- // description string.
- // If DXGI1.2 is available then IDXGIAdapter2::GetDesc2 can be used to get the actual
- // hardware values.
- if (mRenderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3 && dxgiAdapter2 != nullptr)
- {
- DXGI_ADAPTER_DESC2 adapterDesc2 = {};
- result = dxgiAdapter2->GetDesc2(&adapterDesc2);
- if (SUCCEEDED(result))
- {
- // Copy the contents of the DXGI_ADAPTER_DESC2 into mAdapterDescription (a
- // DXGI_ADAPTER_DESC).
- memcpy(mAdapterDescription.Description, adapterDesc2.Description,
- sizeof(mAdapterDescription.Description));
- mAdapterDescription.VendorId = adapterDesc2.VendorId;
- mAdapterDescription.DeviceId = adapterDesc2.DeviceId;
- mAdapterDescription.SubSysId = adapterDesc2.SubSysId;
- mAdapterDescription.Revision = adapterDesc2.Revision;
- mAdapterDescription.DedicatedVideoMemory = adapterDesc2.DedicatedVideoMemory;
- mAdapterDescription.DedicatedSystemMemory = adapterDesc2.DedicatedSystemMemory;
- mAdapterDescription.SharedSystemMemory = adapterDesc2.SharedSystemMemory;
- mAdapterDescription.AdapterLuid = adapterDesc2.AdapterLuid;
- }
- }
- else
- {
- result = mDxgiAdapter->GetDesc(&mAdapterDescription);
- }
-
- SafeRelease(dxgiAdapter2);
-
- if (FAILED(result))
- {
- return egl::EglNotInitialized(D3D11_INIT_OTHER_ERROR)
- << "Could not read DXGI adaptor description.";
- }
-
- memset(mDescription, 0, sizeof(mDescription));
- wcstombs(mDescription, mAdapterDescription.Description, sizeof(mDescription) - 1);
-
- result = mDxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void **)&mDxgiFactory);
-
- if (!mDxgiFactory || FAILED(result))
- {
- return egl::EglNotInitialized(D3D11_INIT_OTHER_ERROR)
- << "Could not create DXGI factory.";
- }
- }
-
- // Disable some spurious D3D11 debug warnings to prevent them from flooding the output log
- if (mCreateDebugDevice)
- {
- TRACE_EVENT0("gpu.angle", "Renderer11::initialize (HideWarnings)");
- ID3D11InfoQueue *infoQueue;
- result = mDevice->QueryInterface(__uuidof(ID3D11InfoQueue), (void **)&infoQueue);
-
- if (SUCCEEDED(result))
- {
- D3D11_MESSAGE_ID hideMessages[] = {
- D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET};
-
- D3D11_INFO_QUEUE_FILTER filter = {};
- filter.DenyList.NumIDs = static_cast<unsigned int>(ArraySize(hideMessages));
- filter.DenyList.pIDList = hideMessages;
-
- infoQueue->AddStorageFilterEntries(&filter);
- SafeRelease(infoQueue);
- }
- }
-
-#if !defined(NDEBUG)
- mDebug = d3d11::DynamicCastComObject<ID3D11Debug>(mDevice);
-#endif
-
- ANGLE_TRY(initializeDevice());
-
- return egl::NoError();
-}
-
-HRESULT Renderer11::callD3D11CreateDevice(PFN_D3D11_CREATE_DEVICE createDevice, bool debug)
-{
- return createDevice(
- nullptr, mRequestedDriverType, nullptr, debug ? D3D11_CREATE_DEVICE_DEBUG : 0,
- mAvailableFeatureLevels.data(), static_cast<unsigned int>(mAvailableFeatureLevels.size()),
- D3D11_SDK_VERSION, &mDevice, &(mRenderer11DeviceCaps.featureLevel), &mDeviceContext);
-}
-
-egl::Error Renderer11::initializeD3DDevice()
-{
- HRESULT result = S_OK;
-
- if (!mCreatedWithDeviceEXT)
- {
-#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
- PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = nullptr;
- {
- SCOPED_ANGLE_HISTOGRAM_TIMER("GPU.ANGLE.Renderer11InitializeDLLsMS");
- TRACE_EVENT0("gpu.angle", "Renderer11::initialize (Load DLLs)");
- mDxgiModule = LoadLibrary(TEXT("dxgi.dll"));
- mD3d11Module = LoadLibrary(TEXT("d3d11.dll"));
- mDCompModule = LoadLibrary(TEXT("dcomp.dll"));
-
- if (mD3d11Module == nullptr || mDxgiModule == nullptr)
- {
- return egl::EglNotInitialized(D3D11_INIT_MISSING_DEP)
- << "Could not load D3D11 or DXGI library.";
- }
-
- // create the D3D11 device
- ASSERT(mDevice == nullptr);
- D3D11CreateDevice = reinterpret_cast<PFN_D3D11_CREATE_DEVICE>(
- GetProcAddress(mD3d11Module, "D3D11CreateDevice"));
-
- if (D3D11CreateDevice == nullptr)
- {
- return egl::EglNotInitialized(D3D11_INIT_MISSING_DEP)
- << "Could not retrieve D3D11CreateDevice address.";
- }
- }
-#endif
-
- if (mCreateDebugDevice)
- {
- TRACE_EVENT0("gpu.angle", "D3D11CreateDevice (Debug)");
- result = callD3D11CreateDevice(D3D11CreateDevice, true);
-
- if (result == E_INVALIDARG && mAvailableFeatureLevels.size() > 1u &&
- mAvailableFeatureLevels[0] == D3D_FEATURE_LEVEL_11_1)
- {
- // On older Windows platforms, D3D11.1 is not supported which returns E_INVALIDARG.
- // Try again without passing D3D_FEATURE_LEVEL_11_1 in case we have other feature
- // levels to fall back on.
- mAvailableFeatureLevels.erase(mAvailableFeatureLevels.begin());
- result = callD3D11CreateDevice(D3D11CreateDevice, true);
- }
-
- if (!mDevice || FAILED(result))
- {
- WARN() << "Failed creating Debug D3D11 device - falling back to release runtime.";
- }
- }
-
- if (!mDevice || FAILED(result))
- {
- SCOPED_ANGLE_HISTOGRAM_TIMER("GPU.ANGLE.D3D11CreateDeviceMS");
- TRACE_EVENT0("gpu.angle", "D3D11CreateDevice");
-
- result = callD3D11CreateDevice(D3D11CreateDevice, false);
-
- if (result == E_INVALIDARG && mAvailableFeatureLevels.size() > 1u &&
- mAvailableFeatureLevels[0] == D3D_FEATURE_LEVEL_11_1)
- {
- // On older Windows platforms, D3D11.1 is not supported which returns E_INVALIDARG.
- // Try again without passing D3D_FEATURE_LEVEL_11_1 in case we have other feature
- // levels to fall back on.
- mAvailableFeatureLevels.erase(mAvailableFeatureLevels.begin());
- result = callD3D11CreateDevice(D3D11CreateDevice, false);
- }
-
- // Cleanup done by destructor
- if (!mDevice || FAILED(result))
- {
- ANGLE_HISTOGRAM_SPARSE_SLOWLY("GPU.ANGLE.D3D11CreateDeviceError",
- static_cast<int>(result));
- return egl::EglNotInitialized(D3D11_INIT_CREATEDEVICE_ERROR)
- << "Could not create D3D11 device.";
- }
- }
- }
- else
- {
- // We should use the inputted D3D11 device instead
- void *device = nullptr;
- ANGLE_TRY(mEGLDevice->getDevice(&device));
-
- ID3D11Device *d3dDevice = reinterpret_cast<ID3D11Device *>(device);
- if (FAILED(d3dDevice->GetDeviceRemovedReason()))
- {
- return egl::EglNotInitialized() << "Inputted D3D11 device has been lost.";
- }
-
- if (d3dDevice->GetFeatureLevel() < D3D_FEATURE_LEVEL_9_3)
- {
- return egl::EglNotInitialized()
- << "Inputted D3D11 device must be Feature Level 9_3 or greater.";
- }
-
- // The Renderer11 adds a ref to the inputted D3D11 device, like D3D11CreateDevice does.
- mDevice = d3dDevice;
- mDevice->AddRef();
- mDevice->GetImmediateContext(&mDeviceContext);
- mRenderer11DeviceCaps.featureLevel = mDevice->GetFeatureLevel();
- }
-
- mResourceManager11.setAllocationsInitialized(mCreateDebugDevice);
-
- d3d11::SetDebugName(mDeviceContext, "DeviceContext");
-
- return egl::NoError();
-}
-
-// do any one-time device initialization
-// NOTE: this is also needed after a device lost/reset
-// to reset the scene status and ensure the default states are reset.
-egl::Error Renderer11::initializeDevice()
-{
- SCOPED_ANGLE_HISTOGRAM_TIMER("GPU.ANGLE.Renderer11InitializeDeviceMS");
- TRACE_EVENT0("gpu.angle", "Renderer11::initializeDevice");
-
- populateRenderer11DeviceCaps();
-
- mStateCache.clear();
-
- ASSERT(!mBlit);
- mBlit = new Blit11(this);
-
- ASSERT(!mClear);
- mClear = new Clear11(this);
-
- const auto &attributes = mDisplay->getAttributeMap();
- // If automatic trim is enabled, DXGIDevice3::Trim( ) is called for the application
- // automatically when an application is suspended by the OS. This feature is currently
- // only supported for Windows Store applications.
- EGLint enableAutoTrim = static_cast<EGLint>(
- attributes.get(EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_FALSE));
-
- if (enableAutoTrim == EGL_TRUE)
- {
- ASSERT(!mTrim);
- mTrim = new Trim11(this);
- }
-
- ASSERT(!mPixelTransfer);
- mPixelTransfer = new PixelTransfer11(this);
-
- const gl::Caps &rendererCaps = getNativeCaps();
-
- if (mStateManager.initialize(rendererCaps, getNativeExtensions()).isError())
- {
- return egl::EglBadAlloc() << "Error initializing state manager.";
- }
-
- // Gather stats on DXGI and D3D feature level
- ANGLE_HISTOGRAM_BOOLEAN("GPU.ANGLE.SupportsDXGI1_2", mRenderer11DeviceCaps.supportsDXGI1_2);
-
- ANGLEFeatureLevel angleFeatureLevel = GetANGLEFeatureLevel(mRenderer11DeviceCaps.featureLevel);
-
- // We don't actually request a 11_1 device, because of complications with the platform
- // update. Instead we check if the mDeviceContext1 pointer cast succeeded.
- // Note: we should support D3D11_0 always, but we aren't guaranteed to be at FL11_0
- // because the app can specify a lower version (such as 9_3) on Display creation.
- if (mDeviceContext1 != nullptr)
- {
- angleFeatureLevel = ANGLE_FEATURE_LEVEL_11_1;
- }
-
- ANGLE_HISTOGRAM_ENUMERATION("GPU.ANGLE.D3D11FeatureLevel", angleFeatureLevel,
- NUM_ANGLE_FEATURE_LEVELS);
-
- return egl::NoError();
-}
-
-void Renderer11::populateRenderer11DeviceCaps()
-{
- HRESULT hr = S_OK;
-
- LARGE_INTEGER version;
- hr = mDxgiAdapter->CheckInterfaceSupport(__uuidof(IDXGIDevice), &version);
- if (FAILED(hr))
- {
- mRenderer11DeviceCaps.driverVersion.reset();
- ERR() << "Error querying driver version from DXGI Adapter.";
- }
- else
- {
- mRenderer11DeviceCaps.driverVersion = version;
- }
-
- if (mDeviceContext1)
- {
- D3D11_FEATURE_DATA_D3D11_OPTIONS d3d11Options;
- HRESULT result = mDevice->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &d3d11Options,
- sizeof(D3D11_FEATURE_DATA_D3D11_OPTIONS));
- if (SUCCEEDED(result))
- {
- mRenderer11DeviceCaps.supportsClearView = (d3d11Options.ClearView != FALSE);
- mRenderer11DeviceCaps.supportsConstantBufferOffsets =
- (d3d11Options.ConstantBufferOffsetting != FALSE);
- }
- }
-
- if (mDeviceContext3)
- {
- D3D11_FEATURE_DATA_D3D11_OPTIONS3 d3d11Options3;
- HRESULT result = mDevice->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS3, &d3d11Options3,
- sizeof(D3D11_FEATURE_DATA_D3D11_OPTIONS3));
- if (SUCCEEDED(result))
- {
- mRenderer11DeviceCaps.supportsVpRtIndexWriteFromVertexShader =
- (d3d11Options3.VPAndRTArrayIndexFromAnyShaderFeedingRasterizer == TRUE);
- }
- }
-
- mRenderer11DeviceCaps.supportsMultisampledDepthStencilSRVs =
- mRenderer11DeviceCaps.featureLevel > D3D_FEATURE_LEVEL_10_0;
-
- if (getWorkarounds().disableB5G6R5Support)
- {
- mRenderer11DeviceCaps.B5G6R5support = 0;
- mRenderer11DeviceCaps.B5G6R5maxSamples = 0;
- }
- else
- {
- PopulateFormatDeviceCaps(mDevice, DXGI_FORMAT_B5G6R5_UNORM,
- &mRenderer11DeviceCaps.B5G6R5support,
- &mRenderer11DeviceCaps.B5G6R5maxSamples);
- }
-
- PopulateFormatDeviceCaps(mDevice, DXGI_FORMAT_B4G4R4A4_UNORM,
- &mRenderer11DeviceCaps.B4G4R4A4support,
- &mRenderer11DeviceCaps.B4G4R4A4maxSamples);
- PopulateFormatDeviceCaps(mDevice, DXGI_FORMAT_B5G5R5A1_UNORM,
- &mRenderer11DeviceCaps.B5G5R5A1support,
- &mRenderer11DeviceCaps.B5G5R5A1maxSamples);
-
- IDXGIAdapter2 *dxgiAdapter2 = d3d11::DynamicCastComObject<IDXGIAdapter2>(mDxgiAdapter);
- mRenderer11DeviceCaps.supportsDXGI1_2 = (dxgiAdapter2 != nullptr);
- SafeRelease(dxgiAdapter2);
-}
-
-gl::SupportedSampleSet Renderer11::generateSampleSetForEGLConfig(
- const gl::TextureCaps &colorBufferFormatCaps,
- const gl::TextureCaps &depthStencilBufferFormatCaps) const
-{
- gl::SupportedSampleSet sampleCounts;
-
-#if 0 // Disabling support for multisampling with Qt5 as it's causing a crash in the D3D11 shaders.
-
- // Generate a new set from the set intersection of sample counts between the color and depth
- // format caps.
- std::set_intersection(colorBufferFormatCaps.sampleCounts.begin(),
- colorBufferFormatCaps.sampleCounts.end(),
- depthStencilBufferFormatCaps.sampleCounts.begin(),
- depthStencilBufferFormatCaps.sampleCounts.end(),
- std::inserter(sampleCounts, sampleCounts.begin()));
-
- // Format of GL_NONE results in no supported sample counts.
- // Add back the color sample counts to the supported sample set.
- if (depthStencilBufferFormatCaps.sampleCounts.empty())
- {
- sampleCounts = colorBufferFormatCaps.sampleCounts;
- }
- else if (colorBufferFormatCaps.sampleCounts.empty())
- {
- // Likewise, add back the depth sample counts to the supported sample set.
- sampleCounts = depthStencilBufferFormatCaps.sampleCounts;
- }
-
-#endif
-
- // Always support 0 samples
- sampleCounts.insert(0);
-
- return sampleCounts;
-}
-
-egl::ConfigSet Renderer11::generateConfigs()
-{
- std::vector<GLenum> colorBufferFormats;
-
- // 32-bit supported formats
- colorBufferFormats.push_back(GL_BGRA8_EXT);
- colorBufferFormats.push_back(GL_RGBA8_OES);
-
- // 24-bit supported formats
- colorBufferFormats.push_back(GL_RGB8_OES);
-
- if (mRenderer11DeviceCaps.featureLevel >= D3D_FEATURE_LEVEL_10_0)
- {
- // Additional high bit depth formats added in D3D 10.0
- // https://msdn.microsoft.com/en-us/library/windows/desktop/bb173064.aspx
- colorBufferFormats.push_back(GL_RGBA16F);
- colorBufferFormats.push_back(GL_RGB10_A2);
- }
-
- if (!mPresentPathFastEnabled)
- {
- // 16-bit supported formats
- // These aren't valid D3D11 swapchain formats, so don't expose them as configs
- // if present path fast is active
- colorBufferFormats.push_back(GL_RGBA4);
- colorBufferFormats.push_back(GL_RGB5_A1);
- colorBufferFormats.push_back(GL_RGB565);
- }
-
- static const GLenum depthStencilBufferFormats[] = {
- GL_NONE, GL_DEPTH24_STENCIL8_OES, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT16,
- GL_STENCIL_INDEX8,
- };
-
- const gl::Caps &rendererCaps = getNativeCaps();
- const gl::TextureCapsMap &rendererTextureCaps = getNativeTextureCaps();
-
- const EGLint optimalSurfaceOrientation =
- mPresentPathFastEnabled ? 0 : EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE;
-
- egl::ConfigSet configs;
- for (GLenum colorBufferInternalFormat : colorBufferFormats)
- {
- const gl::TextureCaps &colorBufferFormatCaps =
- rendererTextureCaps.get(colorBufferInternalFormat);
- if (!colorBufferFormatCaps.renderable)
- {
- continue;
- }
-
- for (GLenum depthStencilBufferInternalFormat : depthStencilBufferFormats)
- {
- const gl::TextureCaps &depthStencilBufferFormatCaps =
- rendererTextureCaps.get(depthStencilBufferInternalFormat);
- if (!depthStencilBufferFormatCaps.renderable &&
- depthStencilBufferInternalFormat != GL_NONE)
- {
- continue;
- }
-
- const gl::InternalFormat &colorBufferFormatInfo =
- gl::GetSizedInternalFormatInfo(colorBufferInternalFormat);
- const gl::InternalFormat &depthStencilBufferFormatInfo =
- gl::GetSizedInternalFormatInfo(depthStencilBufferInternalFormat);
- const gl::Version &maxVersion = getMaxSupportedESVersion();
-
- const gl::SupportedSampleSet sampleCounts =
- generateSampleSetForEGLConfig(colorBufferFormatCaps, depthStencilBufferFormatCaps);
-
- for (GLuint sampleCount : sampleCounts)
- {
- egl::Config config;
- config.renderTargetFormat = colorBufferInternalFormat;
- config.depthStencilFormat = depthStencilBufferInternalFormat;
- config.bufferSize = colorBufferFormatInfo.pixelBytes * 8;
- config.redSize = colorBufferFormatInfo.redBits;
- config.greenSize = colorBufferFormatInfo.greenBits;
- config.blueSize = colorBufferFormatInfo.blueBits;
- config.luminanceSize = colorBufferFormatInfo.luminanceBits;
- config.alphaSize = colorBufferFormatInfo.alphaBits;
- config.alphaMaskSize = 0;
- config.bindToTextureRGB =
- ((colorBufferFormatInfo.format == GL_RGB) && (sampleCount <= 1));
- config.bindToTextureRGBA = (((colorBufferFormatInfo.format == GL_RGBA) ||
- (colorBufferFormatInfo.format == GL_BGRA_EXT)) &&
- (sampleCount <= 1));
- config.colorBufferType = EGL_RGB_BUFFER;
- config.configCaveat = EGL_NONE;
- config.configID = static_cast<EGLint>(configs.size() + 1);
-
- // PresentPathFast may not be conformant
- config.conformant = 0;
- if (!mPresentPathFastEnabled)
- {
- // Can only support a conformant ES2 with feature level greater than 10.0.
- if (mRenderer11DeviceCaps.featureLevel >= D3D_FEATURE_LEVEL_10_0)
- {
- config.conformant |= EGL_OPENGL_ES2_BIT;
- }
-
- // We can only support conformant ES3 on FL 10.1+
- if (maxVersion.major >= 3)
- {
- config.conformant |= EGL_OPENGL_ES3_BIT_KHR;
- }
- }
-
- config.depthSize = depthStencilBufferFormatInfo.depthBits;
- config.level = 0;
- config.matchNativePixmap = EGL_NONE;
- config.maxPBufferWidth = rendererCaps.max2DTextureSize;
- config.maxPBufferHeight = rendererCaps.max2DTextureSize;
- config.maxPBufferPixels =
- rendererCaps.max2DTextureSize * rendererCaps.max2DTextureSize;
- config.maxSwapInterval = 4;
- config.minSwapInterval = 0;
- config.nativeRenderable = EGL_FALSE;
- config.nativeVisualID = 0;
- config.nativeVisualType = EGL_NONE;
-
- // Can't support ES3 at all without feature level 10.1
- config.renderableType = EGL_OPENGL_ES2_BIT;
- if (maxVersion.major >= 3)
- {
- config.renderableType |= EGL_OPENGL_ES3_BIT_KHR;
- }
-
- config.sampleBuffers = (sampleCount == 0) ? 0 : 1;
- config.samples = sampleCount;
- config.stencilSize = depthStencilBufferFormatInfo.stencilBits;
- config.surfaceType =
- EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
- config.transparentType = EGL_NONE;
- config.transparentRedValue = 0;
- config.transparentGreenValue = 0;
- config.transparentBlueValue = 0;
- config.optimalOrientation = optimalSurfaceOrientation;
- config.colorComponentType = gl_egl::GLComponentTypeToEGLColorComponentType(
- colorBufferFormatInfo.componentType);
-
- configs.add(config);
- }
- }
- }
-
- ASSERT(configs.size() > 0);
- return configs;
-}
-
-void Renderer11::generateDisplayExtensions(egl::DisplayExtensions *outExtensions) const
-{
- outExtensions->createContextRobustness = true;
-
- if (getShareHandleSupport())
- {
- outExtensions->d3dShareHandleClientBuffer = true;
- outExtensions->surfaceD3DTexture2DShareHandle = true;
- }
- outExtensions->d3dTextureClientBuffer = true;
-
- outExtensions->keyedMutex = true;
- outExtensions->querySurfacePointer = true;
- outExtensions->windowFixedSize = true;
-
- // If present path fast is active then the surface orientation extension isn't supported
- outExtensions->surfaceOrientation = !mPresentPathFastEnabled;
-
- // D3D11 does not support present with dirty rectangles until DXGI 1.2.
- outExtensions->postSubBuffer = mRenderer11DeviceCaps.supportsDXGI1_2;
-
- outExtensions->deviceQuery = true;
-
- outExtensions->image = true;
- outExtensions->imageBase = true;
- outExtensions->glTexture2DImage = true;
- outExtensions->glTextureCubemapImage = true;
- outExtensions->glRenderbufferImage = true;
-
- outExtensions->stream = true;
- outExtensions->streamConsumerGLTexture = true;
- outExtensions->streamConsumerGLTextureYUV = true;
- // Not all D3D11 devices support NV12 textures
- if (getNV12TextureSupport())
- {
- outExtensions->streamProducerD3DTextureNV12 = true;
- }
-
- outExtensions->flexibleSurfaceCompatibility = true;
- outExtensions->directComposition = !!mDCompModule;
-
- // Contexts are virtualized so textures can be shared globally
- outExtensions->displayTextureShareGroup = true;
-
- // getSyncValues requires direct composition.
- outExtensions->getSyncValues = outExtensions->directComposition;
-
- // D3D11 can be used without a swap chain
- outExtensions->surfacelessContext = true;
-
- // All D3D feature levels support robust resource init
- outExtensions->robustResourceInitialization = true;
-}
-
-gl::Error Renderer11::flush()
-{
- mDeviceContext->Flush();
- return gl::NoError();
-}
-
-gl::Error Renderer11::finish()
-{
- if (!mSyncQuery.valid())
- {
- D3D11_QUERY_DESC queryDesc;
- queryDesc.Query = D3D11_QUERY_EVENT;
- queryDesc.MiscFlags = 0;
-
- ANGLE_TRY(allocateResource(queryDesc, &mSyncQuery));
- }
-
- mDeviceContext->End(mSyncQuery.get());
-
- HRESULT result = S_OK;
- unsigned int attempt = 0;
- do
- {
- unsigned int flushFrequency = 100;
- UINT flags = (attempt % flushFrequency == 0) ? 0 : D3D11_ASYNC_GETDATA_DONOTFLUSH;
- attempt++;
-
- result = mDeviceContext->GetData(mSyncQuery.get(), nullptr, 0, flags);
- if (FAILED(result))
- {
- return gl::OutOfMemory() << "Failed to get event query data, " << gl::FmtHR(result);
- }
-
- if (result == S_FALSE)
- {
- // Keep polling, but allow other threads to do something useful first
- ScheduleYield();
- }
-
- if (testDeviceLost())
- {
- mDisplay->notifyDeviceLost();
- return gl::OutOfMemory() << "Device was lost while waiting for sync.";
- }
- } while (result == S_FALSE);
-
- return gl::NoError();
-}
-
-bool Renderer11::isValidNativeWindow(EGLNativeWindowType window) const
-{
-#ifdef ANGLE_ENABLE_WINDOWS_STORE
- return NativeWindow11WinRT::IsValidNativeWindow(window);
-#else
- return NativeWindow11Win32::IsValidNativeWindow(window);
-#endif
-}
-
-NativeWindowD3D *Renderer11::createNativeWindow(EGLNativeWindowType window,
- const egl::Config *config,
- const egl::AttributeMap &attribs) const
-{
-#ifdef ANGLE_ENABLE_WINDOWS_STORE
- UNUSED_VARIABLE(attribs);
- return new NativeWindow11WinRT(window, config->alphaSize > 0);
-#else
- return new NativeWindow11Win32(
- window, config->alphaSize > 0,
- attribs.get(EGL_DIRECT_COMPOSITION_ANGLE, EGL_FALSE) == EGL_TRUE);
-#endif
-}
-
-egl::Error Renderer11::getD3DTextureInfo(const egl::Config *configuration,
- IUnknown *d3dTexture,
- EGLint *width,
- EGLint *height,
- GLenum *fboFormat) const
-{
- ID3D11Texture2D *texture = d3d11::DynamicCastComObject<ID3D11Texture2D>(d3dTexture);
- if (texture == nullptr)
- {
- return egl::EglBadParameter() << "client buffer is not a ID3D11Texture2D";
- }
-
- ID3D11Device *textureDevice = nullptr;
- texture->GetDevice(&textureDevice);
- if (textureDevice != mDevice)
- {
- SafeRelease(texture);
- return egl::EglBadParameter() << "Texture's device does not match.";
- }
- SafeRelease(textureDevice);
-
- D3D11_TEXTURE2D_DESC desc = {0};
- texture->GetDesc(&desc);
- SafeRelease(texture);
-
- if (width)
- {
- *width = static_cast<EGLint>(desc.Width);
- }
- if (height)
- {
- *height = static_cast<EGLint>(desc.Height);
- }
- if (static_cast<EGLint>(desc.SampleDesc.Count) != configuration->samples)
- {
- // Both the texture and EGL config sample count may not be the same when multi-sampling
- // is disabled. The EGL sample count can be 0 but a D3D texture is always 1. Therefore,
- // we must only check for a invalid match when the EGL config is non-zero or the texture is
- // not one.
- if (configuration->samples != 0 || desc.SampleDesc.Count != 1)
- {
- return egl::EglBadParameter() << "Texture's sample count does not match.";
- }
- }
- // From table egl.restrictions in EGL_ANGLE_d3d_texture_client_buffer.
- switch (desc.Format)
- {
- case DXGI_FORMAT_R8G8B8A8_UNORM:
- case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
- case DXGI_FORMAT_B8G8R8A8_UNORM:
- case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
- case DXGI_FORMAT_R16G16B16A16_FLOAT:
- case DXGI_FORMAT_R32G32B32A32_FLOAT:
- break;
-
- default:
- return egl::EglBadParameter()
- << "Unknown client buffer texture format: " << desc.Format;
- }
-
- if (fboFormat)
- {
- const angle::Format &angleFormat = d3d11_angle::GetFormat(desc.Format);
- *fboFormat = angleFormat.fboImplementationInternalFormat;
- }
-
- return egl::NoError();
-}
-
-egl::Error Renderer11::validateShareHandle(const egl::Config *config,
- HANDLE shareHandle,
- const egl::AttributeMap &attribs) const
-{
- if (shareHandle == nullptr)
- {
- return egl::EglBadParameter() << "NULL share handle.";
- }
-
- ID3D11Resource *tempResource11 = nullptr;
- HRESULT result = mDevice->OpenSharedResource(shareHandle, __uuidof(ID3D11Resource),
- (void **)&tempResource11);
- if (FAILED(result))
- {
- return egl::EglBadParameter() << "Failed to open share handle, " << gl::FmtHR(result);
- }
-
- ID3D11Texture2D *texture2D = d3d11::DynamicCastComObject<ID3D11Texture2D>(tempResource11);
- SafeRelease(tempResource11);
-
- if (texture2D == nullptr)
- {
- return egl::EglBadParameter()
- << "Failed to query ID3D11Texture2D object from share handle.";
- }
-
- D3D11_TEXTURE2D_DESC desc = {0};
- texture2D->GetDesc(&desc);
- SafeRelease(texture2D);
-
- EGLint width = attribs.getAsInt(EGL_WIDTH, 0);
- EGLint height = attribs.getAsInt(EGL_HEIGHT, 0);
- ASSERT(width != 0 && height != 0);
-
- const d3d11::Format &backbufferFormatInfo =
- d3d11::Format::Get(config->renderTargetFormat, getRenderer11DeviceCaps());
-
- if (desc.Width != static_cast<UINT>(width) || desc.Height != static_cast<UINT>(height) ||
- desc.Format != backbufferFormatInfo.texFormat || desc.MipLevels != 1 || desc.ArraySize != 1)
- {
- return egl::EglBadParameter() << "Invalid texture parameters in share handle texture.";
- }
-
- return egl::NoError();
-}
-
-SwapChainD3D *Renderer11::createSwapChain(NativeWindowD3D *nativeWindow,
- HANDLE shareHandle,
- IUnknown *d3dTexture,
- GLenum backBufferFormat,
- GLenum depthBufferFormat,
- EGLint orientation,
- EGLint samples)
-{
- return new SwapChain11(this, GetAs<NativeWindow11>(nativeWindow), shareHandle, d3dTexture,
- backBufferFormat, depthBufferFormat, orientation, samples);
-}
-
-void *Renderer11::getD3DDevice()
-{
- return reinterpret_cast<void *>(mDevice);
-}
-
-bool Renderer11::applyPrimitiveType(const gl::State &glState, GLenum mode, GLsizei count)
-{
- D3D11_PRIMITIVE_TOPOLOGY primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
-
- GLsizei minCount = 0;
-
- switch (mode)
- {
- case GL_POINTS:
- {
- bool usesPointSize = GetImplAs<ProgramD3D>(glState.getProgram())->usesPointSize();
-
- // ProgramBinary assumes non-point rendering if gl_PointSize isn't written,
- // which affects varying interpolation. Since the value of gl_PointSize is
- // undefined when not written, just skip drawing to avoid unexpected results.
- if (!usesPointSize && !glState.isTransformFeedbackActiveUnpaused())
- {
- // Notify developers of risking undefined behavior.
- WARN() << "Point rendering without writing to gl_PointSize.";
- return false;
- }
-
- // If instanced pointsprites are enabled and the shader uses gl_PointSize, the topology
- // must be D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST.
- if (usesPointSize && getWorkarounds().useInstancedPointSpriteEmulation)
- {
- primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
- }
- else
- {
- primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST;
- }
- minCount = 1;
- break;
- }
- case GL_LINES:
- primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINELIST;
- minCount = 2;
- break;
- case GL_LINE_LOOP:
- primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP;
- minCount = 2;
- break;
- case GL_LINE_STRIP:
- primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP;
- minCount = 2;
- break;
- case GL_TRIANGLES:
- primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
- minCount = CullsEverything(glState) ? std::numeric_limits<GLsizei>::max() : 3;
- break;
- case GL_TRIANGLE_STRIP:
- primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
- minCount = CullsEverything(glState) ? std::numeric_limits<GLsizei>::max() : 3;
- break;
- // emulate fans via rewriting index buffer
- case GL_TRIANGLE_FAN:
- primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
- minCount = CullsEverything(glState) ? std::numeric_limits<GLsizei>::max() : 3;
- break;
- default:
- UNREACHABLE();
- return false;
- }
-
- mStateManager.setPrimitiveTopology(primitiveTopology);
-
- return count >= minCount;
-}
-
-gl::Error Renderer11::drawArrays(const gl::Context *context,
- GLenum mode,
- GLint startVertex,
- GLsizei count,
- GLsizei instances)
-{
- const auto &glState = context->getGLState();
-
- if (!applyPrimitiveType(glState, mode, count))
- {
- return gl::NoError();
- }
-
- DrawCallVertexParams vertexParams(startVertex, count, instances);
- ANGLE_TRY(mStateManager.applyVertexBuffer(context, mode, vertexParams, false));
-
- if (glState.isTransformFeedbackActiveUnpaused())
- {
- ANGLE_TRY(markTransformFeedbackUsage(context));
- }
-
- gl::Program *program = glState.getProgram();
- ASSERT(program != nullptr);
- GLsizei adjustedInstanceCount = GetAdjustedInstanceCount(program, instances);
- ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
-
- if (programD3D->usesGeometryShader(mode) && glState.isTransformFeedbackActiveUnpaused())
- {
- // Since we use a geometry if-and-only-if we rewrite vertex streams, transform feedback
- // won't get the correct output. To work around this, draw with *only* the stream out
- // first (no pixel shader) to feed the stream out buffers and then draw again with the
- // geometry shader + pixel shader to rasterize the primitives.
- mStateManager.setPixelShader(nullptr);
-
- if (adjustedInstanceCount > 0)
- {
- mDeviceContext->DrawInstanced(count, adjustedInstanceCount, 0, 0);
- }
- else
- {
- mDeviceContext->Draw(count, 0);
- }
-
- rx::ShaderExecutableD3D *pixelExe = nullptr;
- ANGLE_TRY(programD3D->getPixelExecutableForCachedOutputLayout(&pixelExe, nullptr));
-
- // Skip the draw call if rasterizer discard is enabled (or no fragment shader).
- if (!pixelExe || glState.getRasterizerState().rasterizerDiscard)
- {
- return gl::NoError();
- }
-
- mStateManager.setPixelShader(&GetAs<ShaderExecutable11>(pixelExe)->getPixelShader());
-
- // Retrieve the geometry shader.
- rx::ShaderExecutableD3D *geometryExe = nullptr;
- ANGLE_TRY(programD3D->getGeometryExecutableForPrimitiveType(context, mode, &geometryExe,
- nullptr));
-
- mStateManager.setGeometryShader(
- &GetAs<ShaderExecutable11>(geometryExe)->getGeometryShader());
-
- if (adjustedInstanceCount > 0)
- {
- mDeviceContext->DrawInstanced(count, adjustedInstanceCount, 0, 0);
- }
- else
- {
- mDeviceContext->Draw(count, 0);
- }
- return gl::NoError();
- }
-
- if (mode == GL_LINE_LOOP)
- {
- return drawLineLoop(context, count, GL_NONE, nullptr, 0, adjustedInstanceCount);
- }
-
- if (mode == GL_TRIANGLE_FAN)
- {
- return drawTriangleFan(context, count, GL_NONE, nullptr, 0, adjustedInstanceCount);
- }
-
- bool useInstancedPointSpriteEmulation =
- programD3D->usesPointSize() && getWorkarounds().useInstancedPointSpriteEmulation;
-
- if (mode != GL_POINTS || !useInstancedPointSpriteEmulation)
- {
- if (adjustedInstanceCount == 0)
- {
- mDeviceContext->Draw(count, 0);
- }
- else
- {
- mDeviceContext->DrawInstanced(count, adjustedInstanceCount, 0, 0);
- }
- return gl::NoError();
- }
-
- // This code should not be reachable by multi-view programs.
- ASSERT(program->usesMultiview() == false);
-
- // If the shader is writing to gl_PointSize, then pointsprites are being rendered.
- // Emulating instanced point sprites for FL9_3 requires the topology to be
- // D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST and DrawIndexedInstanced is called instead.
- if (adjustedInstanceCount == 0)
- {
- mDeviceContext->DrawIndexedInstanced(6, count, 0, 0, 0);
- return gl::NoError();
- }
-
- // If pointsprite emulation is used with glDrawArraysInstanced then we need to take a less
- // efficent code path. Instanced rendering of emulated pointsprites requires a loop to draw each
- // batch of points. An offset into the instanced data buffer is calculated and applied on each
- // iteration to ensure all instances are rendered correctly. Each instance being rendered
- // requires the inputlayout cache to reapply buffers and offsets.
- for (GLsizei i = 0; i < instances; i++)
- {
- ANGLE_TRY(mStateManager.updateVertexOffsetsForPointSpritesEmulation(startVertex, i));
- mDeviceContext->DrawIndexedInstanced(6, count, 0, 0, 0);
- }
-
- // This required by updateVertexOffsets... above but is outside of the loop for speed.
- mStateManager.invalidateVertexBuffer();
- return gl::NoError();
-}
-
-gl::Error Renderer11::drawElements(const gl::Context *context,
- GLenum mode,
- GLsizei count,
- GLenum type,
- const void *indices,
- GLsizei instances)
-{
- const auto &glState = context->getGLState();
-
- if (!applyPrimitiveType(glState, mode, count))
- {
- return gl::NoError();
- }
-
- // Transform feedback is not allowed for DrawElements, this error should have been caught at the
- // API validation layer.
- ASSERT(!glState.isTransformFeedbackActiveUnpaused());
-
- const auto &lazyIndexRange = context->getParams<gl::HasIndexRange>();
-
- bool usePrimitiveRestartWorkaround =
- UsePrimitiveRestartWorkaround(glState.isPrimitiveRestartEnabled(), type);
- DrawCallVertexParams vertexParams(!usePrimitiveRestartWorkaround, lazyIndexRange, 0, instances);
-
- ANGLE_TRY(mStateManager.applyIndexBuffer(context, indices, count, type, lazyIndexRange,
- usePrimitiveRestartWorkaround));
- ANGLE_TRY(mStateManager.applyVertexBuffer(context, mode, vertexParams, true));
-
- int startVertex = static_cast<int>(vertexParams.firstVertex());
- int baseVertex = -startVertex;
-
- const gl::Program *program = glState.getProgram();
- GLsizei adjustedInstanceCount = GetAdjustedInstanceCount(program, instances);
-
- if (mode == GL_LINE_LOOP)
- {
- return drawLineLoop(context, count, type, indices, baseVertex, adjustedInstanceCount);
- }
-
- if (mode == GL_TRIANGLE_FAN)
- {
- return drawTriangleFan(context, count, type, indices, baseVertex, adjustedInstanceCount);
- }
-
- const ProgramD3D *programD3D = GetImplAs<ProgramD3D>(glState.getProgram());
-
- if (mode != GL_POINTS || !programD3D->usesInstancedPointSpriteEmulation())
- {
- if (adjustedInstanceCount == 0)
- {
- mDeviceContext->DrawIndexed(count, 0, baseVertex);
- }
- else
- {
- mDeviceContext->DrawIndexedInstanced(count, adjustedInstanceCount, 0, baseVertex, 0);
- }
- return gl::NoError();
- }
-
- // This code should not be reachable by multi-view programs.
- ASSERT(program->usesMultiview() == false);
-
- // If the shader is writing to gl_PointSize, then pointsprites are being rendered.
- // Emulating instanced point sprites for FL9_3 requires the topology to be
- // D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST and DrawIndexedInstanced is called instead.
- //
- // The count parameter passed to drawElements represents the total number of instances to be
- // rendered. Each instance is referenced by the bound index buffer from the the caller.
- //
- // Indexed pointsprite emulation replicates data for duplicate entries found in the index
- // buffer. This is not an efficent rendering mechanism and is only used on downlevel renderers
- // that do not support geometry shaders.
- if (instances == 0)
- {
- mDeviceContext->DrawIndexedInstanced(6, count, 0, 0, 0);
- return gl::NoError();
- }
-
- // If pointsprite emulation is used with glDrawElementsInstanced then we need to take a less
- // efficent code path. Instanced rendering of emulated pointsprites requires a loop to draw each
- // batch of points. An offset into the instanced data buffer is calculated and applied on each
- // iteration to ensure all instances are rendered correctly.
- GLsizei elementsToRender = vertexParams.vertexCount();
-
- // Each instance being rendered requires the inputlayout cache to reapply buffers and offsets.
- for (GLsizei i = 0; i < instances; i++)
- {
- ANGLE_TRY(mStateManager.updateVertexOffsetsForPointSpritesEmulation(startVertex, i));
- mDeviceContext->DrawIndexedInstanced(6, elementsToRender, 0, 0, 0);
- }
- mStateManager.invalidateVertexBuffer();
- return gl::NoError();
-}
-
-gl::Error Renderer11::drawArraysIndirect(const gl::Context *context,
- GLenum mode,
- const void *indirect)
-{
- const auto &glState = context->getGLState();
- ASSERT(!glState.isTransformFeedbackActiveUnpaused());
-
- if (!applyPrimitiveType(glState, mode, std::numeric_limits<int>::max() - 1))
- {
- return gl::NoError();
- }
-
- gl::Buffer *drawIndirectBuffer = glState.getTargetBuffer(gl::BufferBinding::DrawIndirect);
- ASSERT(drawIndirectBuffer);
- Buffer11 *storage = GetImplAs<Buffer11>(drawIndirectBuffer);
- uintptr_t offset = reinterpret_cast<uintptr_t>(indirect);
-
- if (!DrawCallNeedsTranslation(context, mode))
- {
- DrawCallVertexParams vertexParams(0, 0, 0);
- ANGLE_TRY(mStateManager.applyVertexBuffer(context, mode, vertexParams, false));
- ID3D11Buffer *buffer = nullptr;
- ANGLE_TRY_RESULT(storage->getBuffer(context, BUFFER_USAGE_INDIRECT), buffer);
- mDeviceContext->DrawInstancedIndirect(buffer, static_cast<unsigned int>(offset));
- return gl::NoError();
- }
-
- const uint8_t *bufferData = nullptr;
- ANGLE_TRY(storage->getData(context, &bufferData));
- ASSERT(bufferData);
- const gl::DrawArraysIndirectCommand *args =
- reinterpret_cast<const gl::DrawArraysIndirectCommand *>(bufferData + offset);
- GLuint count = args->count;
- GLuint instances = args->instanceCount;
- GLuint first = args->first;
-
- DrawCallVertexParams vertexParams(first, count, instances);
- ANGLE_TRY(mStateManager.applyVertexBuffer(context, mode, vertexParams, false));
-
- if (mode == GL_LINE_LOOP)
- {
- return drawLineLoop(context, count, GL_NONE, nullptr, 0, instances);
- }
- if (mode == GL_TRIANGLE_FAN)
- {
- return drawTriangleFan(context, count, GL_NONE, nullptr, 0, instances);
- }
-
- mDeviceContext->DrawInstanced(count, instances, 0, 0);
- return gl::NoError();
-}
-
-gl::Error Renderer11::drawElementsIndirect(const gl::Context *context,
- GLenum mode,
- GLenum type,
- const void *indirect)
-{
- const auto &glState = context->getGLState();
- ASSERT(!glState.isTransformFeedbackActiveUnpaused());
-
- if (!applyPrimitiveType(glState, mode, std::numeric_limits<int>::max() - 1))
- {
- return gl::NoError();
- }
-
- gl::Buffer *drawIndirectBuffer = glState.getTargetBuffer(gl::BufferBinding::DrawIndirect);
- ASSERT(drawIndirectBuffer);
- Buffer11 *storage = GetImplAs<Buffer11>(drawIndirectBuffer);
- uintptr_t offset = reinterpret_cast<uintptr_t>(indirect);
-
- // TODO(jmadill): Remove the if statement and compute indirect parameters lazily.
- bool usePrimitiveRestartWorkaround =
- UsePrimitiveRestartWorkaround(glState.isPrimitiveRestartEnabled(), type);
-
- if (!DrawCallNeedsTranslation(context, mode) && !IsStreamingIndexData(context, type))
- {
- ANGLE_TRY(mStateManager.applyIndexBuffer(context, nullptr, 0, type, gl::HasIndexRange(),
- usePrimitiveRestartWorkaround));
- DrawCallVertexParams vertexParams(0, 0, 0);
- ANGLE_TRY(mStateManager.applyVertexBuffer(context, mode, vertexParams, true));
- ID3D11Buffer *buffer = nullptr;
- ANGLE_TRY_RESULT(storage->getBuffer(context, BUFFER_USAGE_INDIRECT), buffer);
- mDeviceContext->DrawIndexedInstancedIndirect(buffer, static_cast<unsigned int>(offset));
- return gl::NoError();
- }
-
- const uint8_t *bufferData = nullptr;
- ANGLE_TRY(storage->getData(context, &bufferData));
- ASSERT(bufferData);
-
- const gl::DrawElementsIndirectCommand *cmd =
- reinterpret_cast<const gl::DrawElementsIndirectCommand *>(bufferData + offset);
- GLsizei count = cmd->count;
- GLuint instances = cmd->primCount;
- GLuint firstIndex = cmd->firstIndex;
- GLint baseVertex = cmd->baseVertex;
-
- // TODO(jmadill): Fix const cast.
- const gl::Type &typeInfo = gl::GetTypeInfo(type);
- const void *indices =
- reinterpret_cast<const void *>(static_cast<uintptr_t>(firstIndex * typeInfo.bytes));
- gl::HasIndexRange lazyIndexRange(const_cast<gl::Context *>(context), count, type, indices);
-
- ANGLE_TRY(mStateManager.applyIndexBuffer(context, indices, count, type, lazyIndexRange,
- usePrimitiveRestartWorkaround));
-
- DrawCallVertexParams vertexParams(false, lazyIndexRange, baseVertex, instances);
-
- ANGLE_TRY(mStateManager.applyVertexBuffer(context, mode, vertexParams, true));
-
- int baseVertexLocation = -static_cast<int>(lazyIndexRange.getIndexRange().value().start);
-
- if (mode == GL_LINE_LOOP)
- {
- return drawLineLoop(context, count, type, indices, baseVertexLocation, instances);
- }
-
- if (mode == GL_TRIANGLE_FAN)
- {
- return drawTriangleFan(context, count, type, indices, baseVertexLocation, instances);
- }
-
- mDeviceContext->DrawIndexedInstanced(count, instances, 0, baseVertexLocation, 0);
- return gl::NoError();
-}
-
-gl::Error Renderer11::drawLineLoop(const gl::Context *context,
- GLsizei count,
- GLenum type,
- const void *indexPointer,
- int baseVertex,
- int instances)
-{
- const gl::State &glState = context->getGLState();
- gl::VertexArray *vao = glState.getVertexArray();
- gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
-
- const void *indices = indexPointer;
-
- // Get the raw indices for an indexed draw
- if (type != GL_NONE && elementArrayBuffer)
- {
- BufferD3D *storage = GetImplAs<BufferD3D>(elementArrayBuffer);
- intptr_t offset = reinterpret_cast<intptr_t>(indices);
-
- const uint8_t *bufferData = nullptr;
- ANGLE_TRY(storage->getData(context, &bufferData));
-
- indices = bufferData + offset;
- }
-
- if (!mLineLoopIB)
- {
- mLineLoopIB = new StreamingIndexBufferInterface(this);
- gl::Error error =
- mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT);
- if (error.isError())
- {
- SafeDelete(mLineLoopIB);
- return error;
- }
- }
-
- // Checked by Renderer11::applyPrimitiveType
- ASSERT(count >= 0);
-
- if (static_cast<unsigned int>(count) + 1 >
- (std::numeric_limits<unsigned int>::max() / sizeof(unsigned int)))
- {
- return gl::OutOfMemory() << "Failed to create a 32-bit looping index buffer for "
- "GL_LINE_LOOP, too many indices required.";
- }
-
- GetLineLoopIndices(indices, type, static_cast<GLuint>(count),
- glState.isPrimitiveRestartEnabled(), &mScratchIndexDataBuffer);
-
- unsigned int spaceNeeded =
- static_cast<unsigned int>(sizeof(GLuint) * mScratchIndexDataBuffer.size());
- ANGLE_TRY(mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT));
-
- void *mappedMemory = nullptr;
- unsigned int offset;
- ANGLE_TRY(mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset));
-
- // Copy over the converted index data.
- memcpy(mappedMemory, &mScratchIndexDataBuffer[0],
- sizeof(GLuint) * mScratchIndexDataBuffer.size());
-
- ANGLE_TRY(mLineLoopIB->unmapBuffer());
-
- IndexBuffer11 *indexBuffer = GetAs<IndexBuffer11>(mLineLoopIB->getIndexBuffer());
- const d3d11::Buffer &d3dIndexBuffer = indexBuffer->getBuffer();
- DXGI_FORMAT indexFormat = indexBuffer->getIndexFormat();
-
- mStateManager.setIndexBuffer(d3dIndexBuffer.get(), indexFormat, offset);
-
- UINT indexCount = static_cast<UINT>(mScratchIndexDataBuffer.size());
-
- if (instances > 0)
- {
- mDeviceContext->DrawIndexedInstanced(indexCount, instances, 0, baseVertex, 0);
- }
- else
- {
- mDeviceContext->DrawIndexed(indexCount, 0, baseVertex);
- }
-
- return gl::NoError();
-}
-
-gl::Error Renderer11::drawTriangleFan(const gl::Context *context,
- GLsizei count,
- GLenum type,
- const void *indices,
- int baseVertex,
- int instances)
-{
- const gl::State &glState = context->getGLState();
- gl::VertexArray *vao = glState.getVertexArray();
- gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
-
- const void *indexPointer = indices;
-
- // Get the raw indices for an indexed draw
- if (type != GL_NONE && elementArrayBuffer)
- {
- BufferD3D *storage = GetImplAs<BufferD3D>(elementArrayBuffer);
- intptr_t offset = reinterpret_cast<intptr_t>(indices);
-
- const uint8_t *bufferData = nullptr;
- ANGLE_TRY(storage->getData(context, &bufferData));
-
- indexPointer = bufferData + offset;
- }
-
- if (!mTriangleFanIB)
- {
- mTriangleFanIB = new StreamingIndexBufferInterface(this);
- gl::Error error =
- mTriangleFanIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT);
- if (error.isError())
- {
- SafeDelete(mTriangleFanIB);
- return error;
- }
- }
-
- // Checked by Renderer11::applyPrimitiveType
- ASSERT(count >= 3);
-
- const GLuint numTris = count - 2;
-
- if (numTris > (std::numeric_limits<unsigned int>::max() / (sizeof(unsigned int) * 3)))
- {
- return gl::OutOfMemory() << "Failed to create a scratch index buffer for GL_TRIANGLE_FAN, "
- "too many indices required.";
- }
-
- GetTriFanIndices(indexPointer, type, count, glState.isPrimitiveRestartEnabled(),
- &mScratchIndexDataBuffer);
-
- const unsigned int spaceNeeded =
- static_cast<unsigned int>(mScratchIndexDataBuffer.size() * sizeof(unsigned int));
- ANGLE_TRY(mTriangleFanIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT));
-
- void *mappedMemory = nullptr;
- unsigned int offset;
- ANGLE_TRY(mTriangleFanIB->mapBuffer(spaceNeeded, &mappedMemory, &offset));
-
- memcpy(mappedMemory, &mScratchIndexDataBuffer[0], spaceNeeded);
-
- ANGLE_TRY(mTriangleFanIB->unmapBuffer());
-
- IndexBuffer11 *indexBuffer = GetAs<IndexBuffer11>(mTriangleFanIB->getIndexBuffer());
- const d3d11::Buffer &d3dIndexBuffer = indexBuffer->getBuffer();
- DXGI_FORMAT indexFormat = indexBuffer->getIndexFormat();
-
- mStateManager.setIndexBuffer(d3dIndexBuffer.get(), indexFormat, offset);
-
- UINT indexCount = static_cast<UINT>(mScratchIndexDataBuffer.size());
-
- if (instances > 0)
- {
- mDeviceContext->DrawIndexedInstanced(indexCount, instances, 0, baseVertex, 0);
- }
- else
- {
- mDeviceContext->DrawIndexed(indexCount, 0, baseVertex);
- }
-
- return gl::NoError();
-}
-
-void Renderer11::releaseDeviceResources()
-{
- mStateManager.deinitialize();
- mStateCache.clear();
-
- SafeDelete(mLineLoopIB);
- SafeDelete(mTriangleFanIB);
- SafeDelete(mBlit);
- SafeDelete(mClear);
- SafeDelete(mTrim);
- SafeDelete(mPixelTransfer);
-
- mSyncQuery.reset();
-
- mCachedResolveTexture.reset();
-}
-
-// set notify to true to broadcast a message to all contexts of the device loss
-bool Renderer11::testDeviceLost()
-{
- bool isLost = false;
-
- if (!mDevice)
- {
- return true;
- }
-
- // GetRemovedReason is used to test if the device is removed
- HRESULT result = mDevice->GetDeviceRemovedReason();
- isLost = d3d11::isDeviceLostError(result);
-
- if (isLost)
- {
- ERR() << "The D3D11 device was removed, " << gl::FmtHR(result);
- }
-
- return isLost;
-}
-
-bool Renderer11::testDeviceResettable()
-{
- // determine if the device is resettable by creating a dummy device
- PFN_D3D11_CREATE_DEVICE D3D11CreateDevice =
- (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice");
-
- if (D3D11CreateDevice == nullptr)
- {
- return false;
- }
-
- ID3D11Device *dummyDevice;
- D3D_FEATURE_LEVEL dummyFeatureLevel;
- ID3D11DeviceContext *dummyContext;
- UINT flags = (mCreateDebugDevice ? D3D11_CREATE_DEVICE_DEBUG : 0);
-
- ASSERT(mRequestedDriverType != D3D_DRIVER_TYPE_UNKNOWN);
- HRESULT result = D3D11CreateDevice(
- nullptr, mRequestedDriverType, nullptr, flags, mAvailableFeatureLevels.data(),
- static_cast<unsigned int>(mAvailableFeatureLevels.size()), D3D11_SDK_VERSION, &dummyDevice,
- &dummyFeatureLevel, &dummyContext);
-
- if (!mDevice || FAILED(result))
- {
- return false;
- }
-
- SafeRelease(dummyContext);
- SafeRelease(dummyDevice);
-
- return true;
-}
-
-void Renderer11::release()
-{
- RendererD3D::cleanup();
-
- mScratchMemoryBuffer.clear();
-
- if (mAnnotator != nullptr)
- {
- gl::UninitializeDebugAnnotations();
- SafeDelete(mAnnotator);
- }
-
- releaseDeviceResources();
-
- if (!mCreatedWithDeviceEXT)
- {
- // Only delete the device if the Renderer11 owns it
- // Otherwise we should keep it around in case we try to reinitialize the renderer later
- SafeDelete(mEGLDevice);
- }
-
- SafeRelease(mDxgiFactory);
- SafeRelease(mDxgiAdapter);
-
- SafeRelease(mDeviceContext3);
- SafeRelease(mDeviceContext1);
-
- if (mDeviceContext)
- {
- mDeviceContext->ClearState();
- mDeviceContext->Flush();
- SafeRelease(mDeviceContext);
- }
-
- SafeRelease(mDevice);
- SafeRelease(mDebug);
-
- if (mD3d11Module)
- {
- FreeLibrary(mD3d11Module);
- mD3d11Module = nullptr;
- }
-
- if (mDxgiModule)
- {
- FreeLibrary(mDxgiModule);
- mDxgiModule = nullptr;
- }
-
- if (mDCompModule)
- {
- FreeLibrary(mDCompModule);
- mDCompModule = nullptr;
- }
-
- mCompiler.release();
-
- mSupportsShareHandles.reset();
-}
-
-bool Renderer11::resetDevice()
-{
- // recreate everything
- release();
- egl::Error result = initialize();
-
- if (result.isError())
- {
- ERR() << "Could not reinitialize D3D11 device: " << result;
- return false;
- }
-
- return true;
-}
-
-std::string Renderer11::getRendererDescription() const
-{
- std::ostringstream rendererString;
-
- rendererString << mDescription;
- rendererString << " Direct3D11";
-
- rendererString << " vs_" << getMajorShaderModel() << "_" << getMinorShaderModel()
- << getShaderModelSuffix();
- rendererString << " ps_" << getMajorShaderModel() << "_" << getMinorShaderModel()
- << getShaderModelSuffix();
-
- return rendererString.str();
-}
-
-DeviceIdentifier Renderer11::getAdapterIdentifier() const
-{
- // Don't use the AdapterLuid here, since that doesn't persist across reboot.
- DeviceIdentifier deviceIdentifier = {0};
- deviceIdentifier.VendorId = mAdapterDescription.VendorId;
- deviceIdentifier.DeviceId = mAdapterDescription.DeviceId;
- deviceIdentifier.SubSysId = mAdapterDescription.SubSysId;
- deviceIdentifier.Revision = mAdapterDescription.Revision;
- deviceIdentifier.FeatureLevel = static_cast<UINT>(mRenderer11DeviceCaps.featureLevel);
-
- return deviceIdentifier;
-}
-
-unsigned int Renderer11::getReservedVertexUniformVectors() const
-{
- // Driver uniforms are stored in a separate constant buffer
- return d3d11_gl::GetReservedVertexUniformVectors(mRenderer11DeviceCaps.featureLevel);
-}
-
-unsigned int Renderer11::getReservedFragmentUniformVectors() const
-{
- // Driver uniforms are stored in a separate constant buffer
- return d3d11_gl::GetReservedFragmentUniformVectors(mRenderer11DeviceCaps.featureLevel);
-}
-
-unsigned int Renderer11::getReservedVertexUniformBuffers() const
-{
- // we reserve one buffer for the application uniforms, and one for driver uniforms
- return 2;
-}
-
-unsigned int Renderer11::getReservedFragmentUniformBuffers() const
-{
- // we reserve one buffer for the application uniforms, and one for driver uniforms
- return 2;
-}
-
-d3d11::ANGLED3D11DeviceType Renderer11::getDeviceType() const
-{
- if (mCreatedWithDeviceEXT)
- {
- return d3d11::GetDeviceType(mDevice);
- }
-
- if ((mRequestedDriverType == D3D_DRIVER_TYPE_SOFTWARE) ||
- (mRequestedDriverType == D3D_DRIVER_TYPE_REFERENCE) ||
- (mRequestedDriverType == D3D_DRIVER_TYPE_NULL))
- {
- return d3d11::ANGLE_D3D11_DEVICE_TYPE_SOFTWARE_REF_OR_NULL;
- }
-
- if (mRequestedDriverType == D3D_DRIVER_TYPE_WARP)
- {
- return d3d11::ANGLE_D3D11_DEVICE_TYPE_WARP;
- }
-
- return d3d11::ANGLE_D3D11_DEVICE_TYPE_HARDWARE;
-}
-
-bool Renderer11::getShareHandleSupport() const
-{
- if (mSupportsShareHandles.valid())
- {
- return mSupportsShareHandles.value();
- }
-
- // We only currently support share handles with BGRA surfaces, because
- // chrome needs BGRA. Once chrome fixes this, we should always support them.
- if (!getNativeExtensions().textureFormatBGRA8888)
- {
- mSupportsShareHandles = false;
- return false;
- }
-
- // PIX doesn't seem to support using share handles, so disable them.
- if (gl::DebugAnnotationsActive())
- {
- mSupportsShareHandles = false;
- return false;
- }
-
- // Qt: we don't care about the 9_3 limitation
-#if 0
- // Also disable share handles on Feature Level 9_3, since it doesn't support share handles on
- // RGBA8 textures/swapchains.
- if (mRenderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3)
- {
- mSupportsShareHandles = false;
- return false;
- }
-#endif
-
- // Find out which type of D3D11 device the Renderer11 is using
- d3d11::ANGLED3D11DeviceType deviceType = getDeviceType();
- if (deviceType == d3d11::ANGLE_D3D11_DEVICE_TYPE_UNKNOWN)
- {
- mSupportsShareHandles = false;
- return false;
- }
-
- if (deviceType == d3d11::ANGLE_D3D11_DEVICE_TYPE_SOFTWARE_REF_OR_NULL)
- {
- // Software/Reference/NULL devices don't support share handles
- mSupportsShareHandles = false;
- return false;
- }
-
- if (deviceType == d3d11::ANGLE_D3D11_DEVICE_TYPE_WARP)
- {
-#ifndef ANGLE_ENABLE_WINDOWS_STORE
- if (!IsWindows8OrGreater())
- {
- // WARP on Windows 7 doesn't support shared handles
- mSupportsShareHandles = false;
- return false;
- }
-#endif // ANGLE_ENABLE_WINDOWS_STORE
-
- // WARP on Windows 8.0+ supports shared handles when shared with another WARP device
- // TODO: allow applications to query for HARDWARE or WARP-specific share handles,
- // to prevent them trying to use a WARP share handle with an a HW device (or
- // vice-versa)
- // e.g. by creating EGL_D3D11_[HARDWARE/WARP]_DEVICE_SHARE_HANDLE_ANGLE
- mSupportsShareHandles = true;
- return true;
- }
-
- ASSERT(mCreatedWithDeviceEXT || mRequestedDriverType == D3D_DRIVER_TYPE_HARDWARE);
- mSupportsShareHandles = true;
- return true;
-}
-
-bool Renderer11::getNV12TextureSupport() const
-{
- HRESULT result;
- UINT formatSupport;
- result = mDevice->CheckFormatSupport(DXGI_FORMAT_NV12, &formatSupport);
- if (result == E_FAIL)
- {
- return false;
- }
- return (formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE2D) != 0;
-}
-
-int Renderer11::getMajorShaderModel() const
-{
- switch (mRenderer11DeviceCaps.featureLevel)
- {
- case D3D_FEATURE_LEVEL_11_1:
- case D3D_FEATURE_LEVEL_11_0:
- return D3D11_SHADER_MAJOR_VERSION; // 5
- case D3D_FEATURE_LEVEL_10_1:
- return D3D10_1_SHADER_MAJOR_VERSION; // 4
- case D3D_FEATURE_LEVEL_10_0:
- return D3D10_SHADER_MAJOR_VERSION; // 4
- case D3D_FEATURE_LEVEL_9_3:
- return D3D10_SHADER_MAJOR_VERSION; // 4
- default:
- UNREACHABLE();
- return 0;
- }
-}
-
-int Renderer11::getMinorShaderModel() const
-{
- switch (mRenderer11DeviceCaps.featureLevel)
- {
- case D3D_FEATURE_LEVEL_11_1:
- case D3D_FEATURE_LEVEL_11_0:
- return D3D11_SHADER_MINOR_VERSION; // 0
- case D3D_FEATURE_LEVEL_10_1:
- return D3D10_1_SHADER_MINOR_VERSION; // 1
- case D3D_FEATURE_LEVEL_10_0:
- return D3D10_SHADER_MINOR_VERSION; // 0
- case D3D_FEATURE_LEVEL_9_3:
- return D3D10_SHADER_MINOR_VERSION; // 0
- default:
- UNREACHABLE();
- return 0;
- }
-}
-
-std::string Renderer11::getShaderModelSuffix() const
-{
- switch (mRenderer11DeviceCaps.featureLevel)
- {
- case D3D_FEATURE_LEVEL_11_1:
- case D3D_FEATURE_LEVEL_11_0:
- return "";
- case D3D_FEATURE_LEVEL_10_1:
- return "";
- case D3D_FEATURE_LEVEL_10_0:
- return "";
- case D3D_FEATURE_LEVEL_9_3:
- return "_level_9_3";
- default:
- UNREACHABLE();
- return "";
- }
-}
-
-const angle::WorkaroundsD3D &RendererD3D::getWorkarounds() const
-{
- if (!mWorkaroundsInitialized)
- {
- mWorkarounds = generateWorkarounds();
- mWorkaroundsInitialized = true;
- }
-
- return mWorkarounds;
-}
-
-gl::Error Renderer11::copyImageInternal(const gl::Context *context,
- const gl::Framebuffer *framebuffer,
- const gl::Rectangle &sourceRect,
- GLenum destFormat,
- const gl::Offset &destOffset,
- RenderTargetD3D *destRenderTarget)
-{
- const gl::FramebufferAttachment *colorAttachment = framebuffer->getReadColorbuffer();
- ASSERT(colorAttachment);
-
- RenderTarget11 *sourceRenderTarget = nullptr;
- ANGLE_TRY(colorAttachment->getRenderTarget(context, &sourceRenderTarget));
- ASSERT(sourceRenderTarget);
-
- const d3d11::SharedSRV &source = sourceRenderTarget->getBlitShaderResourceView();
- ASSERT(source.valid());
-
- const d3d11::RenderTargetView &dest =
- GetAs<RenderTarget11>(destRenderTarget)->getRenderTargetView();
- ASSERT(dest.valid());
-
- gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1);
- gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1);
-
- const bool invertSource = UsePresentPathFast(this, colorAttachment);
- if (invertSource)
- {
- sourceArea.y = sourceSize.height - sourceRect.y;
- sourceArea.height = -sourceArea.height;
- }
-
- gl::Box destArea(destOffset.x, destOffset.y, 0, sourceRect.width, sourceRect.height, 1);
- gl::Extents destSize(destRenderTarget->getWidth(), destRenderTarget->getHeight(), 1);
-
- // Use nearest filtering because source and destination are the same size for the direct copy.
- // Convert to the unsized format before calling copyTexture.
- GLenum sourceFormat = colorAttachment->getFormat().info->format;
- ANGLE_TRY(mBlit->copyTexture(context, source, sourceArea, sourceSize, sourceFormat, dest,
- destArea, destSize, nullptr, gl::GetUnsizedFormat(destFormat),
- GL_NEAREST, false, false, false));
-
- return gl::NoError();
-}
-
-gl::Error Renderer11::copyImage2D(const gl::Context *context,
- const gl::Framebuffer *framebuffer,
- const gl::Rectangle &sourceRect,
- GLenum destFormat,
- const gl::Offset &destOffset,
- TextureStorage *storage,
- GLint level)
-{
- TextureStorage11_2D *storage11 = GetAs<TextureStorage11_2D>(storage);
- ASSERT(storage11);
-
- gl::ImageIndex index = gl::ImageIndex::Make2D(level);
- RenderTargetD3D *destRenderTarget = nullptr;
- ANGLE_TRY(storage11->getRenderTarget(context, index, &destRenderTarget));
- ASSERT(destRenderTarget);
-
- ANGLE_TRY(copyImageInternal(context, framebuffer, sourceRect, destFormat, destOffset,
- destRenderTarget));
-
- storage11->markLevelDirty(level);
-
- return gl::NoError();
-}
-
-gl::Error Renderer11::copyImageCube(const gl::Context *context,
- const gl::Framebuffer *framebuffer,
- const gl::Rectangle &sourceRect,
- GLenum destFormat,
- const gl::Offset &destOffset,
- TextureStorage *storage,
- GLenum target,
- GLint level)
-{
- TextureStorage11_Cube *storage11 = GetAs<TextureStorage11_Cube>(storage);
- ASSERT(storage11);
-
- gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level);
- RenderTargetD3D *destRenderTarget = nullptr;
- ANGLE_TRY(storage11->getRenderTarget(context, index, &destRenderTarget));
- ASSERT(destRenderTarget);
-
- ANGLE_TRY(copyImageInternal(context, framebuffer, sourceRect, destFormat, destOffset,
- destRenderTarget));
-
- storage11->markLevelDirty(level);
-
- return gl::NoError();
-}
-
-gl::Error Renderer11::copyImage3D(const gl::Context *context,
- const gl::Framebuffer *framebuffer,
- const gl::Rectangle &sourceRect,
- GLenum destFormat,
- const gl::Offset &destOffset,
- TextureStorage *storage,
- GLint level)
-{
- TextureStorage11_3D *storage11 = GetAs<TextureStorage11_3D>(storage);
- ASSERT(storage11);
-
- gl::ImageIndex index = gl::ImageIndex::Make3D(level, destOffset.z);
- RenderTargetD3D *destRenderTarget = nullptr;
- ANGLE_TRY(storage11->getRenderTarget(context, index, &destRenderTarget));
- ASSERT(destRenderTarget);
-
- ANGLE_TRY(copyImageInternal(context, framebuffer, sourceRect, destFormat, destOffset,
- destRenderTarget));
-
- storage11->markLevelDirty(level);
-
- return gl::NoError();
-}
-
-gl::Error Renderer11::copyImage2DArray(const gl::Context *context,
- const gl::Framebuffer *framebuffer,
- const gl::Rectangle &sourceRect,
- GLenum destFormat,
- const gl::Offset &destOffset,
- TextureStorage *storage,
- GLint level)
-{
- TextureStorage11_2DArray *storage11 = GetAs<TextureStorage11_2DArray>(storage);
- ASSERT(storage11);
-
- gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, destOffset.z);
- RenderTargetD3D *destRenderTarget = nullptr;
- ANGLE_TRY(storage11->getRenderTarget(context, index, &destRenderTarget));
- ASSERT(destRenderTarget);
-
- ANGLE_TRY(copyImageInternal(context, framebuffer, sourceRect, destFormat, destOffset,
- destRenderTarget));
- storage11->markLevelDirty(level);
-
- return gl::NoError();
-}
-
-gl::Error Renderer11::copyTexture(const gl::Context *context,
- const gl::Texture *source,
- GLint sourceLevel,
- const gl::Rectangle &sourceRect,
- GLenum destFormat,
- const gl::Offset &destOffset,
- TextureStorage *storage,
- GLenum destTarget,
- GLint destLevel,
- bool unpackFlipY,
- bool unpackPremultiplyAlpha,
- bool unpackUnmultiplyAlpha)
-{
- TextureD3D *sourceD3D = GetImplAs<TextureD3D>(source);
-
- TextureStorage *sourceStorage = nullptr;
- ANGLE_TRY(sourceD3D->getNativeTexture(context, &sourceStorage));
-
- TextureStorage11_2D *sourceStorage11 = GetAs<TextureStorage11_2D>(sourceStorage);
- ASSERT(sourceStorage11);
-
- TextureStorage11 *destStorage11 = GetAs<TextureStorage11>(storage);
- ASSERT(destStorage11);
-
- // Check for fast path where a CopySubresourceRegion can be used.
- if (unpackPremultiplyAlpha == unpackUnmultiplyAlpha && !unpackFlipY &&
- source->getFormat(GL_TEXTURE_2D, sourceLevel).info->format == destFormat &&
- sourceStorage11->getFormatSet().texFormat == destStorage11->getFormatSet().texFormat)
- {
- const TextureHelper11 *sourceResource = nullptr;
- ANGLE_TRY(sourceStorage11->getResource(context, &sourceResource));
-
- gl::ImageIndex sourceIndex = gl::ImageIndex::Make2D(sourceLevel);
- UINT sourceSubresource = sourceStorage11->getSubresourceIndex(sourceIndex);
-
- const TextureHelper11 *destResource = nullptr;
- ANGLE_TRY(destStorage11->getResource(context, &destResource));
-
- gl::ImageIndex destIndex = gl::ImageIndex::MakeGeneric(destTarget, destLevel);
- UINT destSubresource = destStorage11->getSubresourceIndex(destIndex);
-
- D3D11_BOX sourceBox{
- static_cast<UINT>(sourceRect.x),
- static_cast<UINT>(sourceRect.y),
- 0u,
- static_cast<UINT>(sourceRect.x + sourceRect.width),
- static_cast<UINT>(sourceRect.y + sourceRect.height),
- 1u,
- };
-
- mDeviceContext->CopySubresourceRegion(destResource->get(), destSubresource, destOffset.x,
- destOffset.y, destOffset.z, sourceResource->get(),
- sourceSubresource, &sourceBox);
- }
- else
- {
- const d3d11::SharedSRV *sourceSRV = nullptr;
- ANGLE_TRY(sourceStorage11->getSRVLevels(context, sourceLevel, sourceLevel, &sourceSRV));
-
- gl::ImageIndex destIndex = gl::ImageIndex::MakeGeneric(destTarget, destLevel);
- RenderTargetD3D *destRenderTargetD3D = nullptr;
- ANGLE_TRY(destStorage11->getRenderTarget(context, destIndex, &destRenderTargetD3D));
-
- RenderTarget11 *destRenderTarget11 = GetAs<RenderTarget11>(destRenderTargetD3D);
-
- const d3d11::RenderTargetView &destRTV = destRenderTarget11->getRenderTargetView();
- ASSERT(destRTV.valid());
-
- gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1);
- gl::Extents sourceSize(
- static_cast<int>(source->getWidth(source->getTarget(), sourceLevel)),
- static_cast<int>(source->getHeight(source->getTarget(), sourceLevel)), 1);
- if (unpackFlipY)
- {
- sourceArea.y += sourceArea.height;
- sourceArea.height = -sourceArea.height;
- }
-
- gl::Box destArea(destOffset.x, destOffset.y, 0, sourceRect.width, sourceRect.height, 1);
- gl::Extents destSize(destRenderTarget11->getWidth(), destRenderTarget11->getHeight(), 1);
-
- // Use nearest filtering because source and destination are the same size for the direct
- // copy
- GLenum sourceFormat = source->getFormat(GL_TEXTURE_2D, sourceLevel).info->format;
- ANGLE_TRY(mBlit->copyTexture(context, *sourceSRV, sourceArea, sourceSize, sourceFormat,
- destRTV, destArea, destSize, nullptr, destFormat, GL_NEAREST,
- false, unpackPremultiplyAlpha, unpackUnmultiplyAlpha));
- }
-
- destStorage11->markLevelDirty(destLevel);
-
- return gl::NoError();
-}
-
-gl::Error Renderer11::copyCompressedTexture(const gl::Context *context,
- const gl::Texture *source,
- GLint sourceLevel,
- TextureStorage *storage,
- GLint destLevel)
-{
- TextureStorage11_2D *destStorage11 = GetAs<TextureStorage11_2D>(storage);
- ASSERT(destStorage11);
-
- const TextureHelper11 *destResource = nullptr;
- ANGLE_TRY(destStorage11->getResource(context, &destResource));
-
- gl::ImageIndex destIndex = gl::ImageIndex::Make2D(destLevel);
- UINT destSubresource = destStorage11->getSubresourceIndex(destIndex);
-
- TextureD3D *sourceD3D = GetImplAs<TextureD3D>(source);
- ASSERT(sourceD3D);
-
- TextureStorage *sourceStorage = nullptr;
- ANGLE_TRY(sourceD3D->getNativeTexture(context, &sourceStorage));
-
- TextureStorage11_2D *sourceStorage11 = GetAs<TextureStorage11_2D>(sourceStorage);
- ASSERT(sourceStorage11);
-
- const TextureHelper11 *sourceResource = nullptr;
- ANGLE_TRY(sourceStorage11->getResource(context, &sourceResource));
-
- gl::ImageIndex sourceIndex = gl::ImageIndex::Make2D(sourceLevel);
- UINT sourceSubresource = sourceStorage11->getSubresourceIndex(sourceIndex);
-
- mDeviceContext->CopySubresourceRegion(destResource->get(), destSubresource, 0, 0, 0,
- sourceResource->get(), sourceSubresource, nullptr);
-
- return gl::NoError();
-}
-
-gl::Error Renderer11::createRenderTarget(int width,
- int height,
- GLenum format,
- GLsizei samples,
- RenderTargetD3D **outRT)
-{
- const d3d11::Format &formatInfo = d3d11::Format::Get(format, mRenderer11DeviceCaps);
-
- const gl::TextureCaps &textureCaps = getNativeTextureCaps().get(format);
- GLuint supportedSamples = textureCaps.getNearestSamples(samples);
-
- if (width > 0 && height > 0)
- {
- // Create texture resource
- D3D11_TEXTURE2D_DESC desc;
- desc.Width = width;
- desc.Height = height;
- desc.MipLevels = 1;
- desc.ArraySize = 1;
- desc.Format = formatInfo.texFormat;
- desc.SampleDesc.Count = (supportedSamples == 0) ? 1 : supportedSamples;
- desc.SampleDesc.Quality = 0;
- desc.Usage = D3D11_USAGE_DEFAULT;
- desc.CPUAccessFlags = 0;
- desc.MiscFlags = 0;
-
- // If a rendertarget or depthstencil format exists for this texture format,
- // we'll flag it to allow binding that way. Shader resource views are a little
- // more complicated.
- bool bindRTV = false, bindDSV = false, bindSRV = false;
- bindRTV = (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN);
- bindDSV = (formatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN);
- bindSRV = (formatInfo.srvFormat != DXGI_FORMAT_UNKNOWN);
-
- bool isMultisampledDepthStencil = bindDSV && desc.SampleDesc.Count > 1;
- if (isMultisampledDepthStencil &&
- !mRenderer11DeviceCaps.supportsMultisampledDepthStencilSRVs)
- {
- bindSRV = false;
- }
-
- desc.BindFlags = (bindRTV ? D3D11_BIND_RENDER_TARGET : 0) |
- (bindDSV ? D3D11_BIND_DEPTH_STENCIL : 0) |
- (bindSRV ? D3D11_BIND_SHADER_RESOURCE : 0);
-
- // The format must be either an RTV or a DSV
- ASSERT(bindRTV != bindDSV);
-
- TextureHelper11 texture;
- ANGLE_TRY(allocateTexture(desc, formatInfo, &texture));
-
- d3d11::SharedSRV srv;
- d3d11::SharedSRV blitSRV;
- if (bindSRV)
- {
- D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
- srvDesc.Format = formatInfo.srvFormat;
- srvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_SRV_DIMENSION_TEXTURE2D
- : D3D11_SRV_DIMENSION_TEXTURE2DMS;
- srvDesc.Texture2D.MostDetailedMip = 0;
- srvDesc.Texture2D.MipLevels = 1;
-
- ANGLE_TRY(allocateResource(srvDesc, texture.get(), &srv));
-
- if (formatInfo.blitSRVFormat != formatInfo.srvFormat)
- {
- D3D11_SHADER_RESOURCE_VIEW_DESC blitSRVDesc;
- blitSRVDesc.Format = formatInfo.blitSRVFormat;
- blitSRVDesc.ViewDimension = (supportedSamples == 0)
- ? D3D11_SRV_DIMENSION_TEXTURE2D
- : D3D11_SRV_DIMENSION_TEXTURE2DMS;
- blitSRVDesc.Texture2D.MostDetailedMip = 0;
- blitSRVDesc.Texture2D.MipLevels = 1;
-
- ANGLE_TRY(allocateResource(blitSRVDesc, texture.get(), &blitSRV));
- }
- else
- {
- blitSRV = srv.makeCopy();
- }
- }
-
- if (bindDSV)
- {
- D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
- dsvDesc.Format = formatInfo.dsvFormat;
- dsvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_DSV_DIMENSION_TEXTURE2D
- : D3D11_DSV_DIMENSION_TEXTURE2DMS;
- dsvDesc.Texture2D.MipSlice = 0;
- dsvDesc.Flags = 0;
-
- d3d11::DepthStencilView dsv;
- ANGLE_TRY(allocateResource(dsvDesc, texture.get(), &dsv));
-
- *outRT = new TextureRenderTarget11(std::move(dsv), texture, srv, format, formatInfo,
- width, height, 1, supportedSamples);
- }
- else if (bindRTV)
- {
- D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
- rtvDesc.Format = formatInfo.rtvFormat;
- rtvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_RTV_DIMENSION_TEXTURE2D
- : D3D11_RTV_DIMENSION_TEXTURE2DMS;
- rtvDesc.Texture2D.MipSlice = 0;
-
- d3d11::RenderTargetView rtv;
- ANGLE_TRY(allocateResource(rtvDesc, texture.get(), &rtv));
-
- if (formatInfo.dataInitializerFunction != nullptr)
- {
- const float clearValues[4] = {0.0f, 0.0f, 0.0f, 1.0f};
- mDeviceContext->ClearRenderTargetView(rtv.get(), clearValues);
- }
-
- *outRT = new TextureRenderTarget11(std::move(rtv), texture, srv, blitSRV, format,
- formatInfo, width, height, 1, supportedSamples);
- }
- else
- {
- UNREACHABLE();
- }
- }
- else
- {
- *outRT = new TextureRenderTarget11(d3d11::RenderTargetView(), TextureHelper11(),
- d3d11::SharedSRV(), d3d11::SharedSRV(), format,
- d3d11::Format::Get(GL_NONE, mRenderer11DeviceCaps),
- width, height, 1, supportedSamples);
- }
-
- return gl::NoError();
-}
-
-gl::Error Renderer11::createRenderTargetCopy(RenderTargetD3D *source, RenderTargetD3D **outRT)
-{
- ASSERT(source != nullptr);
-
- RenderTargetD3D *newRT = nullptr;
- ANGLE_TRY(createRenderTarget(source->getWidth(), source->getHeight(),
- source->getInternalFormat(), source->getSamples(), &newRT));
-
- RenderTarget11 *source11 = GetAs<RenderTarget11>(source);
- RenderTarget11 *dest11 = GetAs<RenderTarget11>(newRT);
-
- mDeviceContext->CopySubresourceRegion(dest11->getTexture().get(), dest11->getSubresourceIndex(),
- 0, 0, 0, source11->getTexture().get(),
- source11->getSubresourceIndex(), nullptr);
- *outRT = newRT;
- return gl::NoError();
-}
-
-gl::Error Renderer11::loadExecutable(const uint8_t *function,
- size_t length,
- gl::ShaderType type,
- const std::vector<D3DVarying> &streamOutVaryings,
- bool separatedOutputBuffers,
- ShaderExecutableD3D **outExecutable)
-{
- ShaderData shaderData(function, length);
-
- switch (type)
- {
- case gl::SHADER_VERTEX:
- {
- d3d11::VertexShader vertexShader;
- d3d11::GeometryShader streamOutShader;
- ANGLE_TRY(allocateResource(shaderData, &vertexShader));
-
- if (!streamOutVaryings.empty())
- {
- std::vector<D3D11_SO_DECLARATION_ENTRY> soDeclaration;
- soDeclaration.reserve(streamOutVaryings.size());
-
- for (const auto &streamOutVarying : streamOutVaryings)
- {
- D3D11_SO_DECLARATION_ENTRY entry = {0};
- entry.Stream = 0;
- entry.SemanticName = streamOutVarying.semanticName.c_str();
- entry.SemanticIndex = streamOutVarying.semanticIndex;
- entry.StartComponent = 0;
- entry.ComponentCount = static_cast<BYTE>(streamOutVarying.componentCount);
- entry.OutputSlot = static_cast<BYTE>(
- (separatedOutputBuffers ? streamOutVarying.outputSlot : 0));
- soDeclaration.push_back(entry);
- }
-
- ANGLE_TRY(allocateResource(shaderData, &soDeclaration, &streamOutShader));
- }
-
- *outExecutable = new ShaderExecutable11(function, length, std::move(vertexShader),
- std::move(streamOutShader));
- }
- break;
- case gl::SHADER_FRAGMENT:
- {
- d3d11::PixelShader pixelShader;
- ANGLE_TRY(allocateResource(shaderData, &pixelShader));
- *outExecutable = new ShaderExecutable11(function, length, std::move(pixelShader));
- }
- break;
- case gl::SHADER_GEOMETRY:
- {
- d3d11::GeometryShader geometryShader;
- ANGLE_TRY(allocateResource(shaderData, &geometryShader));
- *outExecutable = new ShaderExecutable11(function, length, std::move(geometryShader));
- }
- break;
- case gl::SHADER_COMPUTE:
- {
- d3d11::ComputeShader computeShader;
- ANGLE_TRY(allocateResource(shaderData, &computeShader));
- *outExecutable = new ShaderExecutable11(function, length, std::move(computeShader));
- }
- break;
- default:
- UNREACHABLE();
- return gl::InternalError();
- }
-
- return gl::NoError();
-}
-
-gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog,
- const std::string &shaderHLSL,
- gl::ShaderType type,
- const std::vector<D3DVarying> &streamOutVaryings,
- bool separatedOutputBuffers,
- const angle::CompilerWorkaroundsD3D &workarounds,
- ShaderExecutableD3D **outExectuable)
-{
- std::stringstream profileStream;
-
- switch (type)
- {
- case gl::SHADER_VERTEX:
- profileStream << "vs";
- break;
- case gl::SHADER_FRAGMENT:
- profileStream << "ps";
- break;
- case gl::SHADER_GEOMETRY:
- profileStream << "gs";
- break;
- case gl::SHADER_COMPUTE:
- profileStream << "cs";
- break;
- default:
- UNREACHABLE();
- return gl::InternalError();
- }
-
- profileStream << "_" << getMajorShaderModel() << "_" << getMinorShaderModel()
- << getShaderModelSuffix();
- std::string profile = profileStream.str();
-
- UINT flags = D3DCOMPILE_OPTIMIZATION_LEVEL2;
-
- if (gl::DebugAnnotationsActive())
- {
-#ifndef NDEBUG
- flags = D3DCOMPILE_SKIP_OPTIMIZATION;
-#endif
-
- flags |= D3DCOMPILE_DEBUG;
- }
-
- if (workarounds.enableIEEEStrictness)
- flags |= D3DCOMPILE_IEEE_STRICTNESS;
-
- // Sometimes D3DCompile will fail with the default compilation flags for complicated shaders
- // when it would otherwise pass with alternative options.
- // Try the default flags first and if compilation fails, try some alternatives.
- std::vector<CompileConfig> configs;
- configs.push_back(CompileConfig(flags, "default"));
- configs.push_back(CompileConfig(flags | D3DCOMPILE_SKIP_VALIDATION, "skip validation"));
- configs.push_back(CompileConfig(flags | D3DCOMPILE_SKIP_OPTIMIZATION, "skip optimization"));
-
- if (getMajorShaderModel() == 4 && getShaderModelSuffix() != "")
- {
- // Some shaders might cause a "blob content mismatch between level9 and d3d10 shader".
- // e.g. dEQP-GLES2.functional.shaders.struct.local.loop_nested_struct_array_*.
- // Using the [unroll] directive works around this, as does this D3DCompile flag.
- configs.push_back(
- CompileConfig(flags | D3DCOMPILE_AVOID_FLOW_CONTROL, "avoid flow control"));
- }
-
- D3D_SHADER_MACRO loopMacros[] = {{"ANGLE_ENABLE_LOOP_FLATTEN", "1"}, {0, 0}};
-
- // TODO(jmadill): Use ComPtr?
- ID3DBlob *binary = nullptr;
- std::string debugInfo;
- ANGLE_TRY(mCompiler.compileToBinary(infoLog, shaderHLSL, profile, configs, loopMacros, &binary,
- &debugInfo));
-
- // It's possible that binary is NULL if the compiler failed in all configurations. Set the
- // executable to NULL and return GL_NO_ERROR to signify that there was a link error but the
- // internal state is still OK.
- if (!binary)
- {
- *outExectuable = nullptr;
- return gl::NoError();
- }
-
- gl::Error error = loadExecutable(reinterpret_cast<const uint8_t *>(binary->GetBufferPointer()),
- binary->GetBufferSize(), type, streamOutVaryings,
- separatedOutputBuffers, outExectuable);
-
- SafeRelease(binary);
- if (error.isError())
- {
- return error;
- }
-
- if (!debugInfo.empty())
- {
- (*outExectuable)->appendDebugInfo(debugInfo);
- }
-
- return gl::NoError();
-}
-
-gl::Error Renderer11::ensureHLSLCompilerInitialized()
-{
- return mCompiler.ensureInitialized();
-}
-
-UniformStorageD3D *Renderer11::createUniformStorage(size_t storageSize)
-{
- return new UniformStorage11(storageSize);
-}
-
-VertexBuffer *Renderer11::createVertexBuffer()
-{
- return new VertexBuffer11(this);
-}
-
-IndexBuffer *Renderer11::createIndexBuffer()
-{
- return new IndexBuffer11(this);
-}
-
-StreamProducerImpl *Renderer11::createStreamProducerD3DTextureNV12(
- egl::Stream::ConsumerType consumerType,
- const egl::AttributeMap &attribs)
-{
- return new StreamProducerNV12(this);
-}
-
-bool Renderer11::supportsFastCopyBufferToTexture(GLenum internalFormat) const
-{
- ASSERT(getNativeExtensions().pixelBufferObject);
-
- const gl::InternalFormat &internalFormatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
- const d3d11::Format &d3d11FormatInfo =
- d3d11::Format::Get(internalFormat, mRenderer11DeviceCaps);
-
- // sRGB formats do not work with D3D11 buffer SRVs
- if (internalFormatInfo.colorEncoding == GL_SRGB)
- {
- return false;
- }
-
- // We cannot support direct copies to non-color-renderable formats
- if (d3d11FormatInfo.rtvFormat == DXGI_FORMAT_UNKNOWN)
- {
- return false;
- }
-
- // We skip all 3-channel formats since sometimes format support is missing
- if (internalFormatInfo.componentCount == 3)
- {
- return false;
- }
-
- // We don't support formats which we can't represent without conversion
- if (d3d11FormatInfo.format().glInternalFormat != internalFormat)
- {
- return false;
- }
-
- // Buffer SRV creation for this format was not working on Windows 10.
- if (d3d11FormatInfo.texFormat == DXGI_FORMAT_B5G5R5A1_UNORM)
- {
- return false;
- }
-
- // This format is not supported as a buffer SRV.
- if (d3d11FormatInfo.texFormat == DXGI_FORMAT_A8_UNORM)
- {
- return false;
- }
-
- return true;
-}
-
-gl::Error Renderer11::fastCopyBufferToTexture(const gl::Context *context,
- const gl::PixelUnpackState &unpack,
- unsigned int offset,
- RenderTargetD3D *destRenderTarget,
- GLenum destinationFormat,
- GLenum sourcePixelsType,
- const gl::Box &destArea)
-{
- ASSERT(supportsFastCopyBufferToTexture(destinationFormat));
- return mPixelTransfer->copyBufferToTexture(context, unpack, offset, destRenderTarget,
- destinationFormat, sourcePixelsType, destArea);
-}
-
-ImageD3D *Renderer11::createImage()
-{
- return new Image11(this);
-}
-
-gl::Error Renderer11::generateMipmap(const gl::Context *context, ImageD3D *dest, ImageD3D *src)
-{
- Image11 *dest11 = GetAs<Image11>(dest);
- Image11 *src11 = GetAs<Image11>(src);
- return Image11::GenerateMipmap(context, dest11, src11, mRenderer11DeviceCaps);
-}
-
-gl::Error Renderer11::generateMipmapUsingD3D(const gl::Context *context,
- TextureStorage *storage,
- const gl::TextureState &textureState)
-{
- TextureStorage11 *storage11 = GetAs<TextureStorage11>(storage);
-
- ASSERT(storage11->isRenderTarget());
- ASSERT(storage11->supportsNativeMipmapFunction());
-
- const d3d11::SharedSRV *srv = nullptr;
- ANGLE_TRY(storage11->getSRVLevels(context, textureState.getEffectiveBaseLevel(),
- textureState.getEffectiveMaxLevel(), &srv));
-
- mDeviceContext->GenerateMips(srv->get());
-
- return gl::NoError();
-}
-
-gl::Error Renderer11::copyImage(const gl::Context *context,
- ImageD3D *dest,
- ImageD3D *source,
- const gl::Rectangle &sourceRect,
- const gl::Offset &destOffset,
- bool unpackFlipY,
- bool unpackPremultiplyAlpha,
- bool unpackUnmultiplyAlpha)
-{
- Image11 *dest11 = GetAs<Image11>(dest);
- Image11 *src11 = GetAs<Image11>(source);
- return Image11::CopyImage(context, dest11, src11, sourceRect, destOffset, unpackFlipY,
- unpackPremultiplyAlpha, unpackUnmultiplyAlpha, mRenderer11DeviceCaps);
-}
-
-TextureStorage *Renderer11::createTextureStorage2D(SwapChainD3D *swapChain)
-{
- SwapChain11 *swapChain11 = GetAs<SwapChain11>(swapChain);
- return new TextureStorage11_2D(this, swapChain11);
-}
-
-TextureStorage *Renderer11::createTextureStorageEGLImage(EGLImageD3D *eglImage,
- RenderTargetD3D *renderTargetD3D)
-{
- return new TextureStorage11_EGLImage(this, eglImage, GetAs<RenderTarget11>(renderTargetD3D));
-}
-
-TextureStorage *Renderer11::createTextureStorageExternal(
- egl::Stream *stream,
- const egl::Stream::GLTextureDescription &desc)
-{
- return new TextureStorage11_External(this, stream, desc);
-}
-
-TextureStorage *Renderer11::createTextureStorage2D(GLenum internalformat,
- bool renderTarget,
- GLsizei width,
- GLsizei height,
- int levels,
- bool hintLevelZeroOnly)
-{
- return new TextureStorage11_2D(this, internalformat, renderTarget, width, height, levels,
- hintLevelZeroOnly);
-}
-
-TextureStorage *Renderer11::createTextureStorageCube(GLenum internalformat,
- bool renderTarget,
- int size,
- int levels,
- bool hintLevelZeroOnly)
-{
- return new TextureStorage11_Cube(this, internalformat, renderTarget, size, levels,
- hintLevelZeroOnly);
-}
-
-TextureStorage *Renderer11::createTextureStorage3D(GLenum internalformat,
- bool renderTarget,
- GLsizei width,
- GLsizei height,
- GLsizei depth,
- int levels)
-{
- return new TextureStorage11_3D(this, internalformat, renderTarget, width, height, depth,
- levels);
-}
-
-TextureStorage *Renderer11::createTextureStorage2DArray(GLenum internalformat,
- bool renderTarget,
- GLsizei width,
- GLsizei height,
- GLsizei depth,
- int levels)
-{
- return new TextureStorage11_2DArray(this, internalformat, renderTarget, width, height, depth,
- levels);
-}
-
-TextureStorage *Renderer11::createTextureStorage2DMultisample(GLenum internalformat,
- GLsizei width,
- GLsizei height,
- int levels,
- int samples,
- bool fixedSampleLocations)
-{
- return new TextureStorage11_2DMultisample(this, internalformat, width, height, levels, samples,
- fixedSampleLocations);
-}
-
-gl::Error Renderer11::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)
-{
- ASSERT(sourceArea.width >= 0);
- ASSERT(sourceArea.height >= 0);
-
- const bool invertTexture = UsePresentPathFast(this, &srcAttachment);
-
- RenderTarget11 *rt11 = nullptr;
- ANGLE_TRY(srcAttachment.getRenderTarget(context, &rt11));
- ASSERT(rt11->getTexture().valid());
-
- const TextureHelper11 &textureHelper = rt11->getTexture();
- unsigned int sourceSubResource = rt11->getSubresourceIndex();
-
- const gl::Extents &texSize = textureHelper.getExtents();
-
- gl::Rectangle actualArea = sourceArea;
- if (invertTexture)
- {
- actualArea.y = texSize.height - actualArea.y - actualArea.height;
- }
-
- // Clamp read region to the defined texture boundaries, preventing out of bounds reads
- // and reads of uninitialized data.
- gl::Rectangle safeArea;
- safeArea.x = gl::clamp(actualArea.x, 0, texSize.width);
- safeArea.y = gl::clamp(actualArea.y, 0, texSize.height);
- safeArea.width =
- gl::clamp(actualArea.width + std::min(actualArea.x, 0), 0, texSize.width - safeArea.x);
- safeArea.height =
- gl::clamp(actualArea.height + std::min(actualArea.y, 0), 0, texSize.height - safeArea.y);
-
- ASSERT(safeArea.x >= 0 && safeArea.y >= 0);
- ASSERT(safeArea.x + safeArea.width <= texSize.width);
- ASSERT(safeArea.y + safeArea.height <= texSize.height);
-
- if (safeArea.width == 0 || safeArea.height == 0)
- {
- // no work to do
- return gl::NoError();
- }
-
- gl::Extents safeSize(safeArea.width, safeArea.height, 1);
- TextureHelper11 stagingHelper;
- ANGLE_TRY_RESULT(
- createStagingTexture(textureHelper.getTextureType(), textureHelper.getFormatSet(), safeSize,
- StagingAccess::READ),
- stagingHelper);
-
- TextureHelper11 resolvedTextureHelper;
-
- // "srcTexture" usually points to the source texture.
- // For 2D multisampled textures, it points to the multisampled resolve texture.
- const TextureHelper11 *srcTexture = &textureHelper;
-
- if (textureHelper.is2D() && textureHelper.getSampleCount() > 1)
- {
- D3D11_TEXTURE2D_DESC resolveDesc;
- resolveDesc.Width = static_cast<UINT>(texSize.width);
- resolveDesc.Height = static_cast<UINT>(texSize.height);
- resolveDesc.MipLevels = 1;
- resolveDesc.ArraySize = 1;
- resolveDesc.Format = textureHelper.getFormat();
- resolveDesc.SampleDesc.Count = 1;
- resolveDesc.SampleDesc.Quality = 0;
- resolveDesc.Usage = D3D11_USAGE_DEFAULT;
- resolveDesc.BindFlags = 0;
- resolveDesc.CPUAccessFlags = 0;
- resolveDesc.MiscFlags = 0;
-
- ANGLE_TRY(
- allocateTexture(resolveDesc, textureHelper.getFormatSet(), &resolvedTextureHelper));
-
- mDeviceContext->ResolveSubresource(resolvedTextureHelper.get(), 0, textureHelper.get(),
- sourceSubResource, textureHelper.getFormat());
-
- sourceSubResource = 0;
- srcTexture = &resolvedTextureHelper;
- }
-
- D3D11_BOX srcBox;
- srcBox.left = static_cast<UINT>(safeArea.x);
- srcBox.right = static_cast<UINT>(safeArea.x + safeArea.width);
- srcBox.top = static_cast<UINT>(safeArea.y);
- srcBox.bottom = static_cast<UINT>(safeArea.y + safeArea.height);
-
- // Select the correct layer from a 3D attachment
- srcBox.front = 0;
- if (textureHelper.is3D())
- {
- srcBox.front = static_cast<UINT>(srcAttachment.layer());
- }
- srcBox.back = srcBox.front + 1;
-
- mDeviceContext->CopySubresourceRegion(stagingHelper.get(), 0, 0, 0, 0, srcTexture->get(),
- sourceSubResource, &srcBox);
-
- gl::Buffer *packBuffer = context->getGLState().getTargetBuffer(gl::BufferBinding::PixelPack);
- if (!invertTexture)
- {
- PackPixelsParams packParams(safeArea, format, type, outputPitch, pack, packBuffer, 0);
- return packPixels(stagingHelper, packParams, pixelsOut);
- }
-
- // Create a new PixelPackState with reversed row order. Note that we can't just assign
- // 'invertTexturePack' to be 'pack' (or memcpy) since that breaks the ref counting/object
- // tracking in the 'pixelBuffer' members, causing leaks. Instead we must use
- // pixelBuffer.set() twice, which performs the addRef/release correctly
- gl::PixelPackState invertTexturePack;
- invertTexturePack.alignment = pack.alignment;
- invertTexturePack.reverseRowOrder = !pack.reverseRowOrder;
-
- PackPixelsParams packParams(safeArea, format, type, outputPitch, invertTexturePack, packBuffer,
- 0);
- gl::Error error = packPixels(stagingHelper, packParams, pixelsOut);
- ANGLE_TRY(error);
- return gl::NoError();
-}
-
-gl::Error Renderer11::packPixels(const TextureHelper11 &textureHelper,
- const PackPixelsParams &params,
- uint8_t *pixelsOut)
-{
- ID3D11Resource *readResource = textureHelper.get();
-
- D3D11_MAPPED_SUBRESOURCE mapping;
- HRESULT hr = mDeviceContext->Map(readResource, 0, D3D11_MAP_READ, 0, &mapping);
- if (FAILED(hr))
- {
- ASSERT(hr == E_OUTOFMEMORY);
- return gl::OutOfMemory() << "Failed to map internal texture for reading, " << gl::FmtHR(hr);
- }
-
- uint8_t *source = static_cast<uint8_t *>(mapping.pData);
- int inputPitch = static_cast<int>(mapping.RowPitch);
-
- const auto &formatInfo = textureHelper.getFormatSet();
- ASSERT(formatInfo.format().glInternalFormat != GL_NONE);
-
- PackPixels(params, formatInfo.format(), inputPitch, source, pixelsOut);
-
- mDeviceContext->Unmap(readResource, 0);
-
- return gl::NoError();
-}
-
-gl::Error Renderer11::blitRenderbufferRect(const gl::Context *context,
- const gl::Rectangle &readRectIn,
- const gl::Rectangle &drawRectIn,
- RenderTargetD3D *readRenderTarget,
- RenderTargetD3D *drawRenderTarget,
- GLenum filter,
- const gl::Rectangle *scissor,
- bool colorBlit,
- bool depthBlit,
- bool stencilBlit)
-{
- // Since blitRenderbufferRect is called for each render buffer that needs to be blitted,
- // it should never be the case that both color and depth/stencil need to be blitted at
- // at the same time.
- ASSERT(colorBlit != (depthBlit || stencilBlit));
-
- RenderTarget11 *drawRenderTarget11 = GetAs<RenderTarget11>(drawRenderTarget);
- if (!drawRenderTarget11)
- {
- return gl::OutOfMemory()
- << "Failed to retrieve the internal draw render target from the draw framebuffer.";
- }
-
- const TextureHelper11 &drawTexture = drawRenderTarget11->getTexture();
- unsigned int drawSubresource = drawRenderTarget11->getSubresourceIndex();
-
- RenderTarget11 *readRenderTarget11 = GetAs<RenderTarget11>(readRenderTarget);
- if (!readRenderTarget11)
- {
- return gl::OutOfMemory()
- << "Failed to retrieve the internal read render target from the read framebuffer.";
- }
-
- TextureHelper11 readTexture;
- unsigned int readSubresource = 0;
- d3d11::SharedSRV readSRV;
-
- if (readRenderTarget->isMultisampled())
- {
- ANGLE_TRY_RESULT(
- resolveMultisampledTexture(context, readRenderTarget11, depthBlit, stencilBlit),
- readTexture);
-
- if (!stencilBlit)
- {
- const auto &readFormatSet = readTexture.getFormatSet();
-
- D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc;
- viewDesc.Format = readFormatSet.srvFormat;
- viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
- viewDesc.Texture2D.MipLevels = 1;
- viewDesc.Texture2D.MostDetailedMip = 0;
-
- ANGLE_TRY(allocateResource(viewDesc, readTexture.get(), &readSRV));
- }
- }
- else
- {
- ASSERT(readRenderTarget11);
- readTexture = readRenderTarget11->getTexture();
- readSubresource = readRenderTarget11->getSubresourceIndex();
- readSRV = readRenderTarget11->getBlitShaderResourceView().makeCopy();
- if (!readSRV.valid())
- {
- ASSERT(depthBlit || stencilBlit);
- readSRV = readRenderTarget11->getShaderResourceView().makeCopy();
- }
- ASSERT(readSRV.valid());
- }
-
- // Stencil blits don't use shaders.
- ASSERT(readSRV.valid() || stencilBlit);
-
- const gl::Extents readSize(readRenderTarget->getWidth(), readRenderTarget->getHeight(), 1);
- const gl::Extents drawSize(drawRenderTarget->getWidth(), drawRenderTarget->getHeight(), 1);
-
- // From the spec:
- // "The actual region taken from the read framebuffer is limited to the intersection of the
- // source buffers being transferred, which may include the color buffer selected by the read
- // buffer, the depth buffer, and / or the stencil buffer depending on mask."
- // This means negative x and y are out of bounds, and not to be read from. We handle this here
- // by internally scaling the read and draw rectangles.
- gl::Rectangle readRect = readRectIn;
- gl::Rectangle drawRect = drawRectIn;
-
- auto flip = [](int val) { return val >= 0 ? 1 : -1; };
-
- if (readRect.x > readSize.width && readRect.width < 0)
- {
- int delta = readRect.x - readSize.width;
- readRect.x -= delta;
- readRect.width += delta;
-
- int drawDelta = delta * flip(drawRect.width);
- drawRect.x += drawDelta;
- drawRect.width -= drawDelta;
- }
-
- if (readRect.y > readSize.height && readRect.height < 0)
- {
- int delta = readRect.y - readSize.height;
- readRect.y -= delta;
- readRect.height += delta;
-
- int drawDelta = delta * flip(drawRect.height);
- drawRect.y += drawDelta;
- drawRect.height -= drawDelta;
- }
-
- auto readToDrawX = [&drawRectIn, &readRectIn](int readOffset) {
- double readToDrawScale =
- static_cast<double>(drawRectIn.width) / static_cast<double>(readRectIn.width);
- return static_cast<int>(round(static_cast<double>(readOffset) * readToDrawScale));
- };
- if (readRect.x < 0)
- {
- int readOffset = -readRect.x;
- readRect.x += readOffset;
- readRect.width -= readOffset;
-
- int drawOffset = readToDrawX(readOffset);
- drawRect.x += drawOffset;
- drawRect.width -= drawOffset;
- }
-
- auto readToDrawY = [&drawRectIn, &readRectIn](int readOffset) {
- double readToDrawScale =
- static_cast<double>(drawRectIn.height) / static_cast<double>(readRectIn.height);
- return static_cast<int>(round(static_cast<double>(readOffset) * readToDrawScale));
- };
- if (readRect.y < 0)
- {
- int readOffset = -readRect.y;
- readRect.y += readOffset;
- readRect.height -= readOffset;
-
- int drawOffset = readToDrawY(readOffset);
- drawRect.y += drawOffset;
- drawRect.height -= drawOffset;
- }
-
- if (readRect.x1() < 0)
- {
- int readOffset = -readRect.x1();
- readRect.width += readOffset;
-
- int drawOffset = readToDrawX(readOffset);
- drawRect.width += drawOffset;
- }
-
- if (readRect.y1() < 0)
- {
- int readOffset = -readRect.y1();
- readRect.height += readOffset;
-
- int drawOffset = readToDrawY(readOffset);
- drawRect.height += drawOffset;
- }
-
- if (readRect.x1() > readSize.width)
- {
- int delta = readRect.x1() - readSize.width;
- readRect.width -= delta;
- drawRect.width -= delta * flip(drawRect.width);
- }
-
- if (readRect.y1() > readSize.height)
- {
- int delta = readRect.y1() - readSize.height;
- readRect.height -= delta;
- drawRect.height -= delta * flip(drawRect.height);
- }
-
- bool scissorNeeded = scissor && gl::ClipRectangle(drawRect, *scissor, nullptr);
-
- const auto &destFormatInfo =
- gl::GetSizedInternalFormatInfo(drawRenderTarget->getInternalFormat());
- const auto &srcFormatInfo =
- gl::GetSizedInternalFormatInfo(readRenderTarget->getInternalFormat());
- const auto &formatSet = drawRenderTarget11->getFormatSet();
- const auto &nativeFormat = formatSet.format();
-
- // Some blits require masking off emulated texture channels. eg: from RGBA8 to RGB8, we
- // emulate RGB8 with RGBA8, so we need to mask off the alpha channel when we copy.
-
- gl::Color<bool> colorMask;
- colorMask.red =
- (srcFormatInfo.redBits > 0) && (destFormatInfo.redBits == 0) && (nativeFormat.redBits > 0);
- colorMask.green = (srcFormatInfo.greenBits > 0) && (destFormatInfo.greenBits == 0) &&
- (nativeFormat.greenBits > 0);
- colorMask.blue = (srcFormatInfo.blueBits > 0) && (destFormatInfo.blueBits == 0) &&
- (nativeFormat.blueBits > 0);
- colorMask.alpha = (srcFormatInfo.alphaBits > 0) && (destFormatInfo.alphaBits == 0) &&
- (nativeFormat.alphaBits > 0);
-
- // We only currently support masking off the alpha channel.
- bool colorMaskingNeeded = colorMask.alpha;
- ASSERT(!colorMask.red && !colorMask.green && !colorMask.blue);
-
- bool wholeBufferCopy = !scissorNeeded && !colorMaskingNeeded && readRect.x == 0 &&
- readRect.width == readSize.width && readRect.y == 0 &&
- readRect.height == readSize.height && drawRect.x == 0 &&
- drawRect.width == drawSize.width && drawRect.y == 0 &&
- drawRect.height == drawSize.height;
-
- bool stretchRequired = readRect.width != drawRect.width || readRect.height != drawRect.height;
-
- bool flipRequired =
- readRect.width < 0 || readRect.height < 0 || drawRect.width < 0 || drawRect.height < 0;
-
- bool outOfBounds = readRect.x < 0 || readRect.x + readRect.width > readSize.width ||
- readRect.y < 0 || readRect.y + readRect.height > readSize.height ||
- drawRect.x < 0 || drawRect.x + drawRect.width > drawSize.width ||
- drawRect.y < 0 || drawRect.y + drawRect.height > drawSize.height;
-
- bool partialDSBlit =
- (nativeFormat.depthBits > 0 && depthBlit) != (nativeFormat.stencilBits > 0 && stencilBlit);
-
- if (readRenderTarget11->getFormatSet().formatID ==
- drawRenderTarget11->getFormatSet().formatID &&
- !stretchRequired && !outOfBounds && !flipRequired && !partialDSBlit &&
- !colorMaskingNeeded && (!(depthBlit || stencilBlit) || wholeBufferCopy))
- {
- UINT dstX = drawRect.x;
- UINT dstY = drawRect.y;
-
- D3D11_BOX readBox;
- readBox.left = readRect.x;
- readBox.right = readRect.x + readRect.width;
- readBox.top = readRect.y;
- readBox.bottom = readRect.y + readRect.height;
- readBox.front = 0;
- readBox.back = 1;
-
- if (scissorNeeded)
- {
- // drawRect is guaranteed to have positive width and height because stretchRequired is
- // false.
- ASSERT(drawRect.width >= 0 || drawRect.height >= 0);
-
- if (drawRect.x < scissor->x)
- {
- dstX = scissor->x;
- readBox.left += (scissor->x - drawRect.x);
- }
- if (drawRect.y < scissor->y)
- {
- dstY = scissor->y;
- readBox.top += (scissor->y - drawRect.y);
- }
- if (drawRect.x + drawRect.width > scissor->x + scissor->width)
- {
- readBox.right -= ((drawRect.x + drawRect.width) - (scissor->x + scissor->width));
- }
- if (drawRect.y + drawRect.height > scissor->y + scissor->height)
- {
- readBox.bottom -= ((drawRect.y + drawRect.height) - (scissor->y + scissor->height));
- }
- }
-
- // D3D11 needs depth-stencil CopySubresourceRegions to have a NULL pSrcBox
- // We also require complete framebuffer copies for depth-stencil blit.
- D3D11_BOX *pSrcBox = wholeBufferCopy ? nullptr : &readBox;
-
- mDeviceContext->CopySubresourceRegion(drawTexture.get(), drawSubresource, dstX, dstY, 0,
- readTexture.get(), readSubresource, pSrcBox);
- }
- else
- {
- gl::Box readArea(readRect.x, readRect.y, 0, readRect.width, readRect.height, 1);
- gl::Box drawArea(drawRect.x, drawRect.y, 0, drawRect.width, drawRect.height, 1);
-
- if (depthBlit && stencilBlit)
- {
- ANGLE_TRY(mBlit->copyDepthStencil(readTexture, readSubresource, readArea, readSize,
- drawTexture, drawSubresource, drawArea, drawSize,
- scissor));
- }
- else if (depthBlit)
- {
- const d3d11::DepthStencilView &drawDSV = drawRenderTarget11->getDepthStencilView();
- ASSERT(readSRV.valid());
- ANGLE_TRY(mBlit->copyDepth(context, readSRV, readArea, readSize, drawDSV, drawArea,
- drawSize, scissor));
- }
- else if (stencilBlit)
- {
- ANGLE_TRY(mBlit->copyStencil(context, readTexture, readSubresource, readArea, readSize,
- drawTexture, drawSubresource, drawArea, drawSize,
- scissor));
- }
- else
- {
- const d3d11::RenderTargetView &drawRTV = drawRenderTarget11->getRenderTargetView();
-
- // We don't currently support masking off any other channel than alpha
- bool maskOffAlpha = colorMaskingNeeded && colorMask.alpha;
- ASSERT(readSRV.valid());
- ANGLE_TRY(mBlit->copyTexture(
- context, readSRV, readArea, readSize, srcFormatInfo.format, drawRTV, drawArea,
- drawSize, scissor, destFormatInfo.format, filter, maskOffAlpha, false, false));
- }
- }
-
- return gl::NoError();
-}
-
-bool Renderer11::isES3Capable() const
-{
- return (d3d11_gl::GetMaximumClientVersion(mRenderer11DeviceCaps.featureLevel).major > 2);
-}
-
-RendererClass Renderer11::getRendererClass() const
-{
- return RENDERER_D3D11;
-}
-
-void Renderer11::onSwap()
-{
- // Send histogram updates every half hour
- const double kHistogramUpdateInterval = 30 * 60;
-
- auto *platform = ANGLEPlatformCurrent();
- const double currentTime = platform->monotonicallyIncreasingTime(platform);
- const double timeSinceLastUpdate = currentTime - mLastHistogramUpdateTime;
-
- if (timeSinceLastUpdate > kHistogramUpdateInterval)
- {
- updateHistograms();
- mLastHistogramUpdateTime = currentTime;
- }
-}
-
-void Renderer11::updateHistograms()
-{
- // Update the buffer CPU memory histogram
- {
- size_t sizeSum = 0;
- for (const Buffer11 *buffer : mAliveBuffers)
- {
- sizeSum += buffer->getTotalCPUBufferMemoryBytes();
- }
- const int kOneMegaByte = 1024 * 1024;
- ANGLE_HISTOGRAM_MEMORY_MB("GPU.ANGLE.Buffer11CPUMemoryMB",
- static_cast<int>(sizeSum) / kOneMegaByte);
- }
-}
-
-void Renderer11::onBufferCreate(const Buffer11 *created)
-{
- mAliveBuffers.insert(created);
-}
-
-void Renderer11::onBufferDelete(const Buffer11 *deleted)
-{
- mAliveBuffers.erase(deleted);
-}
-
-gl::ErrorOrResult<TextureHelper11> Renderer11::resolveMultisampledTexture(
- const gl::Context *context,
- RenderTarget11 *renderTarget,
- bool depth,
- bool stencil)
-{
- if (depth && !stencil)
- {
- return mBlit->resolveDepth(context, renderTarget);
- }
-
- if (stencil)
- {
- return mBlit->resolveStencil(context, renderTarget, depth);
- }
-
- const auto &formatSet = renderTarget->getFormatSet();
-
- ASSERT(renderTarget->isMultisampled());
- const d3d11::SharedSRV &sourceSRV = renderTarget->getShaderResourceView();
- D3D11_SHADER_RESOURCE_VIEW_DESC sourceSRVDesc;
- sourceSRV.get()->GetDesc(&sourceSRVDesc);
- ASSERT(sourceSRVDesc.ViewDimension == D3D_SRV_DIMENSION_TEXTURE2DMS);
-
- if (!mCachedResolveTexture.valid() ||
- mCachedResolveTexture.getExtents().width != renderTarget->getWidth() ||
- mCachedResolveTexture.getExtents().height != renderTarget->getHeight() ||
- mCachedResolveTexture.getFormat() != formatSet.texFormat)
- {
- D3D11_TEXTURE2D_DESC resolveDesc;
- resolveDesc.Width = renderTarget->getWidth();
- resolveDesc.Height = renderTarget->getHeight();
- resolveDesc.MipLevels = 1;
- resolveDesc.ArraySize = 1;
- resolveDesc.Format = formatSet.texFormat;
- resolveDesc.SampleDesc.Count = 1;
- resolveDesc.SampleDesc.Quality = 0;
- resolveDesc.Usage = D3D11_USAGE_DEFAULT;
- resolveDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
- resolveDesc.CPUAccessFlags = 0;
- resolveDesc.MiscFlags = 0;
-
- ANGLE_TRY(allocateTexture(resolveDesc, formatSet, &mCachedResolveTexture));
- }
-
- mDeviceContext->ResolveSubresource(mCachedResolveTexture.get(), 0,
- renderTarget->getTexture().get(),
- renderTarget->getSubresourceIndex(), formatSet.texFormat);
- return mCachedResolveTexture;
-}
-
-bool Renderer11::getLUID(LUID *adapterLuid) const
-{
- adapterLuid->HighPart = 0;
- adapterLuid->LowPart = 0;
-
- if (!mDxgiAdapter)
- {
- return false;
- }
-
- DXGI_ADAPTER_DESC adapterDesc;
- if (FAILED(mDxgiAdapter->GetDesc(&adapterDesc)))
- {
- return false;
- }
-
- *adapterLuid = adapterDesc.AdapterLuid;
- return true;
-}
-
-VertexConversionType Renderer11::getVertexConversionType(
- gl::VertexFormatType vertexFormatType) const
-{
- return d3d11::GetVertexFormatInfo(vertexFormatType, mRenderer11DeviceCaps.featureLevel)
- .conversionType;
-}
-
-GLenum Renderer11::getVertexComponentType(gl::VertexFormatType vertexFormatType) const
-{
- const auto &format =
- d3d11::GetVertexFormatInfo(vertexFormatType, mRenderer11DeviceCaps.featureLevel);
- return d3d11::GetComponentType(format.nativeFormat);
-}
-
-gl::ErrorOrResult<unsigned int> Renderer11::getVertexSpaceRequired(
- const gl::VertexAttribute &attrib,
- const gl::VertexBinding &binding,
- GLsizei count,
- GLsizei instances) const
-{
- if (!attrib.enabled)
- {
- return 16u;
- }
-
- unsigned int elementCount = 0;
- const unsigned int divisor = binding.getDivisor();
- if (instances == 0 || divisor == 0)
- {
- elementCount = count;
- }
- else
- {
- // Round up to divisor, if possible
- elementCount = UnsignedCeilDivide(static_cast<unsigned int>(instances), divisor);
- }
-
- gl::VertexFormatType formatType = gl::GetVertexFormatType(attrib);
- const D3D_FEATURE_LEVEL featureLevel = mRenderer11DeviceCaps.featureLevel;
- const d3d11::VertexFormat &vertexFormatInfo =
- d3d11::GetVertexFormatInfo(formatType, featureLevel);
- const d3d11::DXGIFormatSize &dxgiFormatInfo =
- d3d11::GetDXGIFormatSizeInfo(vertexFormatInfo.nativeFormat);
- unsigned int elementSize = dxgiFormatInfo.pixelBytes;
- if (elementSize > std::numeric_limits<unsigned int>::max() / elementCount)
- {
- return gl::OutOfMemory() << "New vertex buffer size would result in an overflow.";
- }
-
- return elementSize * elementCount;
-}
-
-void Renderer11::generateCaps(gl::Caps *outCaps,
- gl::TextureCapsMap *outTextureCaps,
- gl::Extensions *outExtensions,
- gl::Limitations *outLimitations) const
-{
- d3d11_gl::GenerateCaps(mDevice, mDeviceContext, mRenderer11DeviceCaps, outCaps, outTextureCaps,
- outExtensions, outLimitations);
-}
-
-angle::WorkaroundsD3D Renderer11::generateWorkarounds() const
-{
- return d3d11::GenerateWorkarounds(mRenderer11DeviceCaps, mAdapterDescription);
-}
-
-egl::Error Renderer11::getEGLDevice(DeviceImpl **device)
-{
- if (mEGLDevice == nullptr)
- {
- ASSERT(mDevice != nullptr);
- mEGLDevice = new DeviceD3D();
- egl::Error error = mEGLDevice->initialize(reinterpret_cast<void *>(mDevice),
- EGL_D3D11_DEVICE_ANGLE, EGL_FALSE);
-
- if (error.isError())
- {
- SafeDelete(mEGLDevice);
- return error;
- }
- }
-
- *device = static_cast<DeviceImpl *>(mEGLDevice);
- return egl::NoError();
-}
-
-ContextImpl *Renderer11::createContext(const gl::ContextState &state)
-{
- return new Context11(state, this);
-}
-
-FramebufferImpl *Renderer11::createDefaultFramebuffer(const gl::FramebufferState &state)
-{
- return new Framebuffer11(state, this);
-}
-
-gl::Error Renderer11::getScratchMemoryBuffer(size_t requestedSize, angle::MemoryBuffer **bufferOut)
-{
- if (!mScratchMemoryBuffer.get(requestedSize, bufferOut))
- {
- return gl::OutOfMemory() << "Failed to allocate internal buffer.";
- }
- return gl::NoError();
-}
-
-gl::Version Renderer11::getMaxSupportedESVersion() const
-{
- return d3d11_gl::GetMaximumClientVersion(mRenderer11DeviceCaps.featureLevel);
-}
-
-gl::DebugAnnotator *Renderer11::getAnnotator()
-{
- return mAnnotator;
-}
-
-gl::Error Renderer11::applyComputeShader(const gl::Context *context)
-{
- ANGLE_TRY(ensureHLSLCompilerInitialized());
-
- const auto &glState = context->getGLState();
- ProgramD3D *programD3D = GetImplAs<ProgramD3D>(glState.getProgram());
-
- ShaderExecutableD3D *computeExe = nullptr;
- ANGLE_TRY(programD3D->getComputeExecutable(&computeExe));
- ASSERT(computeExe != nullptr);
-
- mStateManager.setComputeShader(&GetAs<ShaderExecutable11>(computeExe)->getComputeShader());
- ANGLE_TRY(mStateManager.applyComputeUniforms(programD3D));
-
- return gl::NoError();
-}
-
-gl::Error Renderer11::dispatchCompute(const gl::Context *context,
- GLuint numGroupsX,
- GLuint numGroupsY,
- GLuint numGroupsZ)
-{
- ANGLE_TRY(mStateManager.updateStateForCompute(context, numGroupsX, numGroupsY, numGroupsZ));
- ANGLE_TRY(applyComputeShader(context));
-
- mDeviceContext->Dispatch(numGroupsX, numGroupsY, numGroupsZ);
-
- return gl::NoError();
-}
-
-gl::ErrorOrResult<TextureHelper11> Renderer11::createStagingTexture(
- ResourceType textureType,
- const d3d11::Format &formatSet,
- const gl::Extents &size,
- StagingAccess readAndWriteAccess)
-{
- if (textureType == ResourceType::Texture2D)
- {
- D3D11_TEXTURE2D_DESC stagingDesc;
- stagingDesc.Width = size.width;
- stagingDesc.Height = size.height;
- stagingDesc.MipLevels = 1;
- stagingDesc.ArraySize = 1;
- stagingDesc.Format = formatSet.texFormat;
- stagingDesc.SampleDesc.Count = 1;
- stagingDesc.SampleDesc.Quality = 0;
- stagingDesc.Usage = D3D11_USAGE_STAGING;
- stagingDesc.BindFlags = 0;
- stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
- stagingDesc.MiscFlags = 0;
-
- if (readAndWriteAccess == StagingAccess::READ_WRITE)
- {
- stagingDesc.CPUAccessFlags |= D3D11_CPU_ACCESS_WRITE;
- }
-
- TextureHelper11 stagingTex;
- ANGLE_TRY(allocateTexture(stagingDesc, formatSet, &stagingTex));
- return stagingTex;
- }
- ASSERT(textureType == ResourceType::Texture3D);
-
- D3D11_TEXTURE3D_DESC stagingDesc;
- stagingDesc.Width = size.width;
- stagingDesc.Height = size.height;
- stagingDesc.Depth = 1;
- stagingDesc.MipLevels = 1;
- stagingDesc.Format = formatSet.texFormat;
- stagingDesc.Usage = D3D11_USAGE_STAGING;
- stagingDesc.BindFlags = 0;
- stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
- stagingDesc.MiscFlags = 0;
-
- TextureHelper11 stagingTex;
- ANGLE_TRY(allocateTexture(stagingDesc, formatSet, &stagingTex));
- return stagingTex;
-}
-
-gl::Error Renderer11::allocateTexture(const D3D11_TEXTURE2D_DESC &desc,
- const d3d11::Format &format,
- const D3D11_SUBRESOURCE_DATA *initData,
- TextureHelper11 *textureOut)
-{
- d3d11::Texture2D texture;
- ANGLE_TRY(mResourceManager11.allocate(this, &desc, initData, &texture));
- textureOut->init(std::move(texture), desc, format);
- return gl::NoError();
-}
-
-gl::Error Renderer11::allocateTexture(const D3D11_TEXTURE3D_DESC &desc,
- const d3d11::Format &format,
- const D3D11_SUBRESOURCE_DATA *initData,
- TextureHelper11 *textureOut)
-{
- d3d11::Texture3D texture;
- ANGLE_TRY(mResourceManager11.allocate(this, &desc, initData, &texture));
- textureOut->init(std::move(texture), desc, format);
- return gl::NoError();
-}
-
-gl::Error Renderer11::getBlendState(const d3d11::BlendStateKey &key,
- const d3d11::BlendState **outBlendState)
-{
- return mStateCache.getBlendState(this, key, outBlendState);
-}
-
-gl::Error Renderer11::getRasterizerState(const gl::RasterizerState &rasterState,
- bool scissorEnabled,
- ID3D11RasterizerState **outRasterizerState)
-{
- return mStateCache.getRasterizerState(this, rasterState, scissorEnabled, outRasterizerState);
-}
-
-gl::Error Renderer11::getDepthStencilState(const gl::DepthStencilState &dsState,
- const d3d11::DepthStencilState **outDSState)
-{
- return mStateCache.getDepthStencilState(this, dsState, outDSState);
-}
-
-gl::Error Renderer11::getSamplerState(const gl::SamplerState &samplerState,
- ID3D11SamplerState **outSamplerState)
-{
- return mStateCache.getSamplerState(this, samplerState, outSamplerState);
-}
-
-gl::Error Renderer11::clearRenderTarget(RenderTargetD3D *renderTarget,
- const gl::ColorF &clearColorValue,
- const float clearDepthValue,
- const unsigned int clearStencilValue)
-{
- RenderTarget11 *rt11 = GetAs<RenderTarget11>(renderTarget);
-
- if (rt11->getDepthStencilView().valid())
- {
- const auto &format = rt11->getFormatSet();
- const UINT clearFlags = (format.format().depthBits > 0 ? D3D11_CLEAR_DEPTH : 0) |
- (format.format().stencilBits ? D3D11_CLEAR_STENCIL : 0);
- mDeviceContext->ClearDepthStencilView(rt11->getDepthStencilView().get(), clearFlags,
- clearDepthValue,
- static_cast<UINT8>(clearStencilValue));
- return gl::NoError();
- }
-
- ASSERT(rt11->getRenderTargetView().valid());
- ID3D11RenderTargetView *rtv = rt11->getRenderTargetView().get();
-
- // There are complications with some types of RTV and FL 9_3 with ClearRenderTargetView.
- // See https://msdn.microsoft.com/en-us/library/windows/desktop/ff476388(v=vs.85).aspx
- ASSERT(mRenderer11DeviceCaps.featureLevel > D3D_FEATURE_LEVEL_9_3 || !IsArrayRTV(rtv));
-
- const auto &d3d11Format = rt11->getFormatSet();
- const auto &glFormat = gl::GetSizedInternalFormatInfo(renderTarget->getInternalFormat());
-
- gl::ColorF safeClearColor = clearColorValue;
-
- if (d3d11Format.format().alphaBits > 0 && glFormat.alphaBits == 0)
- {
- safeClearColor.alpha = 1.0f;
- }
-
- mDeviceContext->ClearRenderTargetView(rtv, &safeClearColor.red);
- return gl::NoError();
-}
-
-bool Renderer11::canSelectViewInVertexShader() const
-{
- return !getWorkarounds().selectViewInGeometryShader &&
- getRenderer11DeviceCaps().supportsVpRtIndexWriteFromVertexShader;
-}
-
-gl::Error Renderer11::markTransformFeedbackUsage(const gl::Context *context)
-{
- const gl::State &glState = context->getGLState();
- const gl::TransformFeedback *transformFeedback = glState.getCurrentTransformFeedback();
- for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
- {
- const gl::OffsetBindingPointer<gl::Buffer> &binding =
- transformFeedback->getIndexedBuffer(i);
- if (binding.get() != nullptr)
- {
- BufferD3D *bufferD3D = GetImplAs<BufferD3D>(binding.get());
- ANGLE_TRY(bufferD3D->markTransformFeedbackUsage(context));
- }
- }
-
- return gl::NoError();
-}
-
-} // namespace rx