diff --git a/src/angle/build.yml b/src/angle/build.yml index dc5c1f3..b145066 100644 --- a/src/angle/build.yml +++ b/src/angle/build.yml @@ -1,5 +1,5 @@ repo: https://chromium.googlesource.com/angle/angle.git -ver: 115 +ver: 118 tag_prefix: '' tag_dot2ul: false cb_tool: gn diff --git a/src/angle/build/config/win/BUILD.gn b/src/angle/build/config/win/BUILD.gn index 7596462..f6c2734 100644 --- a/src/angle/build/config/win/BUILD.gn +++ b/src/angle/build/config/win/BUILD.gn @@ -99,7 +99,7 @@ config("compiler") { cflags += [ "/D__WRL_ENABLE_FUNCTION_STATICS__" ] # Tell clang which version of MSVC to emulate. - cflags += [ "-fmsc-version=1934" ] + cflags += [ "-fmsc-version=1937" ] if (is_component_build) { cflags += [ @@ -122,7 +122,7 @@ config("compiler") { cflags += [ "--target=x86_64-windows" ] } } else if (current_cpu == "arm64") { - cflags += [ "--target=arm64-windows" ] + cflags += [ "--target=aarch64-pc-windows" ] } else { assert(false, "unknown current_cpu " + current_cpu) } @@ -399,18 +399,32 @@ config("cfi_linker") { } # This is a superset of all the delayloads needed for chrome.exe, chrome.dll, -# chrome_child.dll, and chrome_elf.dll. The linker will automatically ignore -# anything which is not linked to the binary at all. -# Most of the dlls are simply not required at startup (or at all, depending -# on how the browser is used). The following dlls are interconnected and need to -# be delayloaded together to ensure user32 does not load too early or at all, -# depending on the process type: user32, gdi32, comctl32, comdlg32, cryptui, -# d3d9, dwmapi, imm32, msi, ole32, oleacc, rstrtmgr, shell32, shlwapi, and -# uxtheme. -# There are some exceptions to this list which need to be declared separately. -# Some dlls cannot be delayloaded by chrome_child.dll due to the sandbox -# restrictions that prevent them from being loaded properly. Those dlls are -# specified in the separate config below. +# and chrome_elf.dll. The linker will automatically ignore anything which is not +# linked to the binary at all (it is harmless to have an unmatched /delayload). +# +# We delayload most libraries as the dlls are simply not required at startup (or +# at all, depending on the process type). In unsandboxed process they will load +# when first needed. +# +# Some dlls open handles when they are loaded, and we may not want them to be +# loaded in renderers or other sandboxed processes. Conversely, some dlls must +# be loaded before sandbox lockdown. +# +# Some dlls themselves load others - in particular, to avoid unconditionally +# loading user32.dll - we require that the following dlls are all delayloaded: +# user32, gdi32, comctl32, comdlg32, cryptui, d3d9, dwmapi, imm32, msi, ole32, +# oleacc, rstrtmgr, shell32, shlwapi, and uxtheme. +# +# Advapi32.dll is unconditionally loaded at process startup on Windows 10, but +# on Windows 11 it is not, which makes it worthwhile to delay load it. +# Additionally, advapi32.dll exports several functions that are forwarded to +# other DLLs such as cryptbase.dll. If calls to those functions are present but +# there are some processes where the functions are never called then delay +# loading of advapi32.dll avoids pulling in those DLLs (such as cryptbase.dll) +# unnecessarily, even if advapi32.dll itself is loaded. +# +# This config applies to chrome.exe, chrome.dll, chrome_elf.dll (& others). +# # This config should also be used for any test binary whose goal is to run # tests with the full browser. config("delayloads") { @@ -418,6 +432,7 @@ config("delayloads") { "/DELAYLOAD:api-ms-win-core-winrt-error-l1-1-0.dll", "/DELAYLOAD:api-ms-win-core-winrt-l1-1-0.dll", "/DELAYLOAD:api-ms-win-core-winrt-string-l1-1-0.dll", + "/DELAYLOAD:advapi32.dll", "/DELAYLOAD:comctl32.dll", "/DELAYLOAD:comdlg32.dll", "/DELAYLOAD:credui.dll", @@ -444,6 +459,7 @@ config("delayloads") { "/DELAYLOAD:setupapi.dll", "/DELAYLOAD:shell32.dll", "/DELAYLOAD:shlwapi.dll", + "/DELAYLOAD:uiautomationcore.dll", "/DELAYLOAD:urlmon.dll", "/DELAYLOAD:user32.dll", "/DELAYLOAD:usp10.dll", @@ -457,9 +473,10 @@ config("delayloads") { ] } +# This config (along with `:delayloads`) applies to chrome.exe & chrome_elf.dll. +# Entries should not appear in both configs. config("delayloads_not_for_child_dll") { ldflags = [ - "/DELAYLOAD:advapi32.dll", "/DELAYLOAD:crypt32.dll", "/DELAYLOAD:dbghelp.dll", "/DELAYLOAD:dhcpcsvc.dll", @@ -467,7 +484,6 @@ config("delayloads_not_for_child_dll") { "/DELAYLOAD:iphlpapi.dll", "/DELAYLOAD:oleaut32.dll", "/DELAYLOAD:secur32.dll", - "/DELAYLOAD:uiautomationcore.dll", "/DELAYLOAD:userenv.dll", "/DELAYLOAD:winhttp.dll", "/DELAYLOAD:winmm.dll", @@ -652,6 +668,10 @@ config("default_incremental_linking") { # TODO(thakis): /INCREMENTAL is on by default in link.exe, but not in # lld. ldflags += [ "/OPT:NOREF" ] + + # TODO(crbug.com/1444129): Mixing incrememntal and icf produces an error + # in lld-link. + ldflags += [ "/OPT:NOICF" ] } } else { ldflags = [ "/INCREMENTAL:NO" ] diff --git a/src/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp b/src/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp index 9ff74b8..47a67b5 100644 --- a/src/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp +++ b/src/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp @@ -9,10 +9,10 @@ #include "libANGLE/renderer/d3d/d3d11/Renderer11.h" #include -#include #include #include "anglebase/no_destructor.h" +#include "common/debug.h" #include "common/tls.h" #include "common/utilities.h" #include "libANGLE/Buffer.h" @@ -336,17 +336,17 @@ bool IsArrayRTV(ID3D11RenderTargetView *rtv) return false; } -GLsizei GetAdjustedInstanceCount(const ProgramD3D *program, GLsizei instanceCount) +GLsizei GetAdjustedInstanceCount(const ProgramExecutableD3D *executable, GLsizei instanceCount) { - if (!program->getState().usesMultiview()) + if (!executable->getExecutable()->usesMultiview()) { return instanceCount; } if (instanceCount == 0) { - return program->getState().getNumViews(); + return executable->getExecutable()->getNumViews(); } - return program->getState().getNumViews() * instanceCount; + return executable->getExecutable()->getNumViews() * instanceCount; } const uint32_t ScratchMemoryBufferLifetime = 1000; @@ -440,7 +440,6 @@ Renderer11::Renderer11(egl::Display *display) mD3d11Module = nullptr; mD3d12Module = nullptr; - mDxgiModule = nullptr; mDCompModule = nullptr; mCreatedWithDeviceEXT = false; @@ -483,9 +482,22 @@ Renderer11::Renderer11(egl::Display *display) } } - if (requestedMajorVersion == 9 && requestedMinorVersion == 3) + if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 9) { - mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_3); + if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 3) + { + mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_3); + } +#if defined(ANGLE_ENABLE_WINDOWS_UWP) + 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(attributes.get( @@ -542,6 +554,7 @@ egl::Error Renderer11::initialize() { HRESULT result = S_OK; + ANGLE_TRY(initializeDXGIAdapter()); ANGLE_TRY(initializeD3DDevice()); #if !defined(ANGLE_ENABLE_WINDOWS_UWP) @@ -587,22 +600,6 @@ egl::Error Renderer11::initialize() mDeviceContext.As(&mDeviceContext1); mDeviceContext.As(&mDeviceContext3); - angle::ComPtr dxgiDevice; - result = mDevice.As(&dxgiDevice); - - if (FAILED(result)) - { - return egl::EglNotInitialized(D3D11_INIT_OTHER_ERROR) << "Could not query DXGI device."; - } - - result = dxgiDevice->GetParent(IID_PPV_ARGS(&mDxgiAdapter)); - - if (FAILED(result)) - { - return egl::EglNotInitialized(D3D11_INIT_OTHER_ERROR) - << "Could not retrieve DXGI adapter"; - } - angle::ComPtr dxgiAdapter2; mDxgiAdapter.As(&dxgiAdapter2); @@ -688,23 +685,81 @@ egl::Error Renderer11::initialize() HRESULT Renderer11::callD3D11CreateDevice(PFN_D3D11_CREATE_DEVICE createDevice, bool debug) { - angle::ComPtr adapter; +#if defined(ANGLE_ENABLE_D3D11_WRAP_FALLBACK) + if(mRequestedDriverType == D3D_DRIVER_TYPE_WARP) { + return createDevice( + nullptr, mRequestedDriverType, nullptr, + debug ? D3D11_CREATE_DEVICE_DEBUG : 0, mAvailableFeatureLevels.data(), + static_cast(mAvailableFeatureLevels.size()), D3D11_SDK_VERSION, &mDevice, + &(mRenderer11DeviceCaps.featureLevel), &mDeviceContext); + } +#endif + // If adapter is not nullptr, the driver type must be D3D_DRIVER_TYPE_UNKNOWN or + // D3D11CreateDevice will return E_INVALIDARG. + return createDevice( + mDxgiAdapter.Get(), mDxgiAdapter ? D3D_DRIVER_TYPE_UNKNOWN : mRequestedDriverType, nullptr, + debug ? D3D11_CREATE_DEVICE_DEBUG : 0, mAvailableFeatureLevels.data(), + static_cast(mAvailableFeatureLevels.size()), D3D11_SDK_VERSION, &mDevice, + &(mRenderer11DeviceCaps.featureLevel), &mDeviceContext); +} - const egl::AttributeMap &attributes = mDisplay->getAttributeMap(); - // Check EGL_ANGLE_platform_angle_d3d_luid - long high = static_cast(attributes.get(EGL_PLATFORM_ANGLE_D3D_LUID_HIGH_ANGLE, 0)); - unsigned long low = - static_cast(attributes.get(EGL_PLATFORM_ANGLE_D3D_LUID_LOW_ANGLE, 0)); - // Check EGL_ANGLE_platform_angle_device_id - if (high == 0 && low == 0) +egl::Error Renderer11::initializeDXGIAdapter() +{ + if (mCreatedWithDeviceEXT) { - high = static_cast(attributes.get(EGL_PLATFORM_ANGLE_DEVICE_ID_HIGH_ANGLE, 0)); - low = static_cast(attributes.get(EGL_PLATFORM_ANGLE_DEVICE_ID_LOW_ANGLE, 0)); + ASSERT(mRequestedDriverType == D3D_DRIVER_TYPE_UNKNOWN); + + DeviceD3D *deviceD3D = GetImplAs(mDisplay->getDevice()); + ASSERT(deviceD3D != nullptr); + + // We should use the inputted D3D11 device instead + void *device = nullptr; + ANGLE_TRY(deviceD3D->getAttribute(mDisplay, EGL_D3D11_DEVICE_ANGLE, &device)); + + ID3D11Device *d3dDevice = static_cast(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->GetImmediateContext(&mDeviceContext); + mRenderer11DeviceCaps.featureLevel = mDevice->GetFeatureLevel(); + + return initializeAdapterFromDevice(); } - if (high != 0 || low != 0) + else { angle::ComPtr factory; - if (SUCCEEDED(CreateDXGIFactory1(IID_PPV_ARGS(&factory)))) + HRESULT hr = CreateDXGIFactory1(IID_PPV_ARGS(&factory)); + if (FAILED(hr)) + { + return egl::EglNotInitialized(D3D11_INIT_OTHER_ERROR) + << "Could not create DXGI factory"; + } + + // If the developer requests a specific adapter, honor their request regardless of the value + // of EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE. + const egl::AttributeMap &attributes = mDisplay->getAttributeMap(); + // Check EGL_ANGLE_platform_angle_d3d_luid + long high = static_cast(attributes.get(EGL_PLATFORM_ANGLE_D3D_LUID_HIGH_ANGLE, 0)); + unsigned long low = + static_cast(attributes.get(EGL_PLATFORM_ANGLE_D3D_LUID_LOW_ANGLE, 0)); + // Check EGL_ANGLE_platform_angle_device_id + if (high == 0 && low == 0) + { + high = static_cast(attributes.get(EGL_PLATFORM_ANGLE_DEVICE_ID_HIGH_ANGLE, 0)); + low = static_cast( + attributes.get(EGL_PLATFORM_ANGLE_DEVICE_ID_LOW_ANGLE, 0)); + } + if (high != 0 || low != 0) { angle::ComPtr temp; for (UINT i = 0; SUCCEEDED(factory->EnumAdapters(i, &temp)); i++) @@ -715,7 +770,7 @@ HRESULT Renderer11::callD3D11CreateDevice(PFN_D3D11_CREATE_DEVICE createDevice, // EGL_ANGLE_platform_angle_d3d_luid if (desc.AdapterLuid.HighPart == high && desc.AdapterLuid.LowPart == low) { - adapter = temp; + mDxgiAdapter = std::move(temp); break; } @@ -726,49 +781,86 @@ HRESULT Renderer11::callD3D11CreateDevice(PFN_D3D11_CREATE_DEVICE createDevice, if ((high == 0 || desc.VendorId == static_cast(high)) && (low == 0 || desc.DeviceId == static_cast(low))) { - adapter = temp; + mDxgiAdapter = std::move(temp); break; } } } } + + // For requested driver types besides Hardware such as Warp, Reference, or Null + // allow D3D11CreateDevice to pick the adapter by passing it the driver type. + if (!mDxgiAdapter && mRequestedDriverType == D3D_DRIVER_TYPE_HARDWARE) + { + hr = factory->EnumAdapters(0, &mDxgiAdapter); + if (FAILED(hr)) + { +#if defined(ANGLE_ENABLE_D3D11_WRAP_FALLBACK) + WARN() << "Could not retrieve DXGI adapter"; +#else + return egl::EglNotInitialized(D3D11_INIT_OTHER_ERROR) + << "Could not retrieve DXGI adapter"; +#endif + } + } } + return egl::NoError(); +} - // If adapter is not nullptr, the driver type must be D3D_DRIVER_TYPE_UNKNOWN or - // D3D11CreateDevice will return E_INVALIDARG. - return createDevice( - adapter.Get(), adapter ? D3D_DRIVER_TYPE_UNKNOWN : mRequestedDriverType, nullptr, - debug ? D3D11_CREATE_DEVICE_DEBUG : 0, mAvailableFeatureLevels.data(), - static_cast(mAvailableFeatureLevels.size()), D3D11_SDK_VERSION, &mDevice, - &(mRenderer11DeviceCaps.featureLevel), &mDeviceContext); +egl::Error Renderer11::initializeAdapterFromDevice() +{ + ASSERT(mDevice); + ASSERT(!mDxgiAdapter); + + angle::ComPtr dxgiDevice; + HRESULT result = mDevice.As(&dxgiDevice); + if (FAILED(result)) + { + return egl::EglNotInitialized(D3D11_INIT_OTHER_ERROR) << "Could not query DXGI device."; + } + + result = dxgiDevice->GetParent(IID_PPV_ARGS(&mDxgiAdapter)); + if (FAILED(result)) + { + return egl::EglNotInitialized(D3D11_INIT_OTHER_ERROR) << "Could not retrieve DXGI adapter"; + } + + return egl::NoError(); } HRESULT Renderer11::callD3D11On12CreateDevice(PFN_D3D12_CREATE_DEVICE createDevice12, PFN_D3D11ON12_CREATE_DEVICE createDevice11on12, bool debug) { - angle::ComPtr factory; - HRESULT result = CreateDXGIFactory1(IID_PPV_ARGS(&factory)); - if (FAILED(result)) + HRESULT result = S_OK; + if (mDxgiAdapter) { - return result; + // Passing nullptr into pAdapter chooses the default adapter which will be the hardware + // adapter if it exists. + result = createDevice12(mDxgiAdapter.Get(), mAvailableFeatureLevels[0], + IID_PPV_ARGS(&mDevice12)); } - - if (mRequestedDriverType == D3D_DRIVER_TYPE_WARP) + else if (mRequestedDriverType == D3D_DRIVER_TYPE_WARP) { - angle::ComPtr warpAdapter; - result = factory->EnumWarpAdapter(IID_PPV_ARGS(&warpAdapter)); + angle::ComPtr factory; + result = CreateDXGIFactory1(IID_PPV_ARGS(&factory)); + if (FAILED(result)) + { + return result; + } + + result = factory->EnumWarpAdapter(IID_PPV_ARGS(&mDxgiAdapter)); if (SUCCEEDED(result)) { - result = createDevice12(warpAdapter.Get(), mAvailableFeatureLevels[0], + result = createDevice12(mDxgiAdapter.Get(), mAvailableFeatureLevels[0], IID_PPV_ARGS(&mDevice12)); } } else { - // Passing nullptr into pAdapter chooses the default adapter which will be the hardware - // adapter if it exists. - result = createDevice12(nullptr, mAvailableFeatureLevels[0], IID_PPV_ARGS(&mDevice12)); + ASSERT(mRequestedDriverType == D3D_DRIVER_TYPE_REFERENCE || + mRequestedDriverType == D3D_DRIVER_TYPE_NULL); + result = E_INVALIDARG; } if (SUCCEEDED(result)) @@ -804,7 +896,6 @@ egl::Error Renderer11::initializeD3DDevice() PFN_D3D11ON12_CREATE_DEVICE D3D11On12CreateDevice = nullptr; { ANGLE_TRACE_EVENT0("gpu.angle", "Renderer11::initialize (Load DLLs)"); - mDxgiModule = LoadLibrary(TEXT("dxgi.dll")); mD3d11Module = LoadLibrary(TEXT("d3d11.dll")); mDCompModule = LoadLibrary(TEXT("dcomp.dll")); @@ -842,10 +933,10 @@ egl::Error Renderer11::initializeD3DDevice() } else { - if (mD3d11Module == nullptr || mDxgiModule == nullptr) + if (mD3d11Module == nullptr) { return egl::EglNotInitialized(D3D11_INIT_MISSING_DEP) - << "Could not load D3D11 or DXGI library."; + << "Could not load D3D11 library."; } D3D11CreateDevice = reinterpret_cast( @@ -925,7 +1016,7 @@ egl::Error Renderer11::initializeD3DDevice() result = callD3D11CreateDevice(D3D11CreateDevice, false); } } - + #if defined(ANGLE_ENABLE_D3D11_WRAP_FALLBACK) // Try again with software driver type if (result == DXGI_ERROR_UNSUPPORTED) @@ -944,33 +1035,13 @@ egl::Error Renderer11::initializeD3DDevice() << "Could not create D3D11 device."; } } - } - else - { - DeviceD3D *deviceD3D = GetImplAs(mDisplay->getDevice()); - ASSERT(deviceD3D != nullptr); - - // We should use the inputted D3D11 device instead - void *device = nullptr; - ANGLE_TRY(deviceD3D->getAttribute(mDisplay, EGL_D3D11_DEVICE_ANGLE, &device)); - - ID3D11Device *d3dDevice = static_cast(device); - if (FAILED(d3dDevice->GetDeviceRemovedReason())) - { - return egl::EglNotInitialized() << "Inputted D3D11 device has been lost."; - } - if (d3dDevice->GetFeatureLevel() < D3D_FEATURE_LEVEL_9_3) + if (!mDxgiAdapter) { - return egl::EglNotInitialized() - << "Inputted D3D11 device must be Feature Level 9_3 or greater."; + // If the D3D11CreateDevice was asked to create the adapter via mRequestedDriverType, + // fill in the adapter here. + ANGLE_TRY(initializeAdapterFromDevice()); } - - // 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); @@ -986,10 +1057,10 @@ egl::Error Renderer11::initializeD3DDevice() void Renderer11::setGlobalDebugAnnotator() { - static std::mutex gMutex; + static angle::base::NoDestructor gMutex; static angle::base::NoDestructor gGlobalAnnotator; - std::lock_guard lg(gMutex); + std::lock_guard lg(*gMutex); gl::InitializeDebugAnnotations(gGlobalAnnotator.get()); } @@ -1425,7 +1496,7 @@ angle::Result Renderer11::finish(Context11 *context11) if (result == S_FALSE) { // Keep polling, but allow other threads to do something useful first - ScheduleYield(); + std::this_thread::yield(); } // Attempt is incremented before checking if we should test for device loss so that device @@ -1752,8 +1823,8 @@ angle::Result Renderer11::drawWithGeometryShaderAndTransformFeedback(Context11 * UINT instanceCount, UINT vertexCount) { - const gl::State &glState = context11->getState(); - ProgramD3D *programD3D = mStateManager.getProgramD3D(); + const gl::State &glState = context11->getState(); + ProgramExecutableD3D *executableD3D = mStateManager.getProgramExecutableD3D(); // 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 @@ -1771,7 +1842,8 @@ angle::Result Renderer11::drawWithGeometryShaderAndTransformFeedback(Context11 * } rx::ShaderExecutableD3D *pixelExe = nullptr; - ANGLE_TRY(programD3D->getPixelExecutableForCachedOutputLayout(context11, &pixelExe, nullptr)); + ANGLE_TRY(executableD3D->getPixelExecutableForCachedOutputLayout( + context11, context11->getRenderer(), &pixelExe, nullptr)); // Skip the draw call if rasterizer discard is enabled (or no fragment shader). if (!pixelExe || glState.getRasterizerState().rasterizerDiscard) @@ -1783,8 +1855,9 @@ angle::Result Renderer11::drawWithGeometryShaderAndTransformFeedback(Context11 * // Retrieve the geometry shader. rx::ShaderExecutableD3D *geometryExe = nullptr; - ANGLE_TRY(programD3D->getGeometryExecutableForPrimitiveType(context11, glState, mode, - &geometryExe, nullptr)); + ANGLE_TRY(executableD3D->getGeometryExecutableForPrimitiveType( + context11, context11->getRenderer(), glState.getCaps(), glState.getProvokingVertex(), mode, + &geometryExe, nullptr)); mStateManager.setGeometryShader(&GetAs(geometryExe)->getGeometryShader()); @@ -1813,10 +1886,12 @@ angle::Result Renderer11::drawArrays(const gl::Context *context, return angle::Result::Continue; } + Context11 *context11 = GetImplAs(context); + ANGLE_TRY(markRawBufferUsage(context)); - ProgramD3D *programD3D = mStateManager.getProgramD3D(); - GLsizei adjustedInstanceCount = GetAdjustedInstanceCount(programD3D, instanceCount); + ProgramExecutableD3D *executableD3D = mStateManager.getProgramExecutableD3D(); + GLsizei adjustedInstanceCount = GetAdjustedInstanceCount(executableD3D, instanceCount); // Note: vertex indexes can be arbitrarily large. UINT clampedVertexCount = gl::GetClampedVertexCount(vertexCount); @@ -1826,10 +1901,11 @@ angle::Result Renderer11::drawArrays(const gl::Context *context, { ANGLE_TRY(markTransformFeedbackUsage(context)); - if (programD3D->usesGeometryShader(glState, mode)) + if (executableD3D->usesGeometryShader(context11->getRenderer(), + glState.getProvokingVertex(), mode)) { return drawWithGeometryShaderAndTransformFeedback( - GetImplAs(context), mode, adjustedInstanceCount, clampedVertexCount); + context11, mode, adjustedInstanceCount, clampedVertexCount); } } @@ -1845,7 +1921,7 @@ angle::Result Renderer11::drawArrays(const gl::Context *context, if (getFeatures().useInstancedPointSpriteEmulation.enabled) { // This code should not be reachable by multi-view programs. - ASSERT(programD3D->getState().usesMultiview() == false); + ASSERT(executableD3D->getExecutable()->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 @@ -1907,6 +1983,8 @@ angle::Result Renderer11::drawElements(const gl::Context *context, return angle::Result::Continue; } + Context11 *context11 = GetImplAs(context); + ANGLE_TRY(markRawBufferUsage(context)); // Transform feedback is not allowed for DrawElements, this error should have been caught at the @@ -1917,8 +1995,8 @@ angle::Result Renderer11::drawElements(const gl::Context *context, // If this draw call is coming from an indirect call, offset by the indirect call's base vertex. GLint baseVertexAdjusted = baseVertex - startVertex; - const ProgramD3D *programD3D = mStateManager.getProgramD3D(); - GLsizei adjustedInstanceCount = GetAdjustedInstanceCount(programD3D, instanceCount); + const ProgramExecutableD3D *executableD3D = mStateManager.getProgramExecutableD3D(); + GLsizei adjustedInstanceCount = GetAdjustedInstanceCount(executableD3D, instanceCount); if (mode == gl::PrimitiveMode::LineLoop) { @@ -1932,7 +2010,8 @@ angle::Result Renderer11::drawElements(const gl::Context *context, adjustedInstanceCount); } - if (mode != gl::PrimitiveMode::Points || !programD3D->usesInstancedPointSpriteEmulation()) + if (mode != gl::PrimitiveMode::Points || + !executableD3D->usesInstancedPointSpriteEmulation(context11->getRenderer())) { if (!isInstancedDraw && adjustedInstanceCount == 0) { @@ -1947,7 +2026,7 @@ angle::Result Renderer11::drawElements(const gl::Context *context, } // This code should not be reachable by multi-view programs. - ASSERT(programD3D->getState().usesMultiview() == false); + ASSERT(executableD3D->getExecutable()->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 @@ -2291,12 +2370,6 @@ void Renderer11::release() mD3d11Module = nullptr; } - if (mDxgiModule) - { - FreeLibrary(mDxgiModule); - mDxgiModule = nullptr; - } - if (mDCompModule) { FreeLibrary(mDCompModule); @@ -2337,7 +2410,10 @@ std::string Renderer11::getRendererDescription() const std::ostringstream rendererString; rendererString << mDescription; + rendererString << " (" << gl::FmtHex(mAdapterDescription.DeviceId) << ")"; rendererString << " Direct3D11"; + if (mD3d12Module) + rendererString << "on12"; rendererString << " vs_" << getMajorShaderModel() << "_" << getMinorShaderModel() << getShaderModelSuffix(); @@ -2452,14 +2528,12 @@ bool Renderer11::getShareHandleSupport() const if (deviceType == d3d11::ANGLE_D3D11_DEVICE_TYPE_WARP) { -#if !defined(ANGLE_ENABLE_WINDOWS_UWP) - if (!IsWindows8OrGreater()) + if (!IsWindows8OrLater()) { // WARP on Windows 7 doesn't support shared handles mSupportsShareHandles = false; return false; } -#endif // !defined(ANGLE_ENABLE_WINDOWS_UWP) // 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, @@ -3524,42 +3598,108 @@ angle::Result Renderer11::readFromAttachment(const gl::Context *context, } gl::Extents safeSize(safeArea.width, safeArea.height, 1); - TextureHelper11 stagingHelper; - ANGLE_TRY(createStagingTexture(context, textureHelper.getTextureType(), - textureHelper.getFormatSet(), safeSize, StagingAccess::READ, - &stagingHelper)); - stagingHelper.setInternalName("readFromAttachment::stagingHelper"); - TextureHelper11 resolvedTextureHelper; + // Intermediate texture used for copy for multiplanar formats or resolving multisampled + // textures. + TextureHelper11 intermediateTextureHelper; // "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) + if (textureHelper.is2D()) { - D3D11_TEXTURE2D_DESC resolveDesc; - resolveDesc.Width = static_cast(texSize.width); - resolveDesc.Height = static_cast(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; + // For multiplanar d3d11 textures, perform a copy before reading. + if (d3d11::IsSupportedMultiplanarFormat(textureHelper.getFormat())) + { + D3D11_TEXTURE2D_DESC planeDesc; + planeDesc.Width = static_cast(safeSize.width); + planeDesc.Height = static_cast(safeSize.height); + planeDesc.MipLevels = 1; + planeDesc.ArraySize = 1; + planeDesc.Format = textureHelper.getFormatSet().srvFormat; + planeDesc.SampleDesc.Count = 1; + planeDesc.SampleDesc.Quality = 0; + planeDesc.Usage = D3D11_USAGE_DEFAULT; + planeDesc.BindFlags = D3D11_BIND_RENDER_TARGET; + planeDesc.CPUAccessFlags = 0; + planeDesc.MiscFlags = 0; + + GLenum internalFormat = textureHelper.getFormatSet().internalFormat; + ANGLE_TRY(allocateTexture(GetImplAs(context), planeDesc, + d3d11::Format::Get(internalFormat, mRenderer11DeviceCaps), + &intermediateTextureHelper)); + intermediateTextureHelper.setInternalName( + "readFromAttachment::intermediateTextureHelper"); + + Context11 *context11 = GetImplAs(context); + d3d11::RenderTargetView rtv; + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = textureHelper.getFormatSet().rtvFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + rtvDesc.Texture2D.MipSlice = 0; + + ANGLE_TRY(allocateResource(context11, rtvDesc, intermediateTextureHelper.get(), &rtv)); + rtv.setInternalName("readFromAttachment.RTV"); + + d3d11::SharedSRV srv; + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = textureHelper.getFormatSet().srvFormat; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + srvDesc.Texture2D.MostDetailedMip = 0; + srvDesc.Texture2D.MipLevels = 1; + + ANGLE_TRY(allocateResource(context11, srvDesc, textureHelper.get(), &srv)); + srv.setInternalName("readFromAttachment.SRV"); - ANGLE_TRY(allocateTexture(GetImplAs(context), resolveDesc, - textureHelper.getFormatSet(), &resolvedTextureHelper)); - resolvedTextureHelper.setInternalName("readFromAttachment::resolvedTextureHelper"); + gl::Box srcGlBox(safeArea.x, safeArea.y, 0, safeArea.width, safeArea.height, 1); + gl::Box destGlBox(0, 0, 0, safeSize.width, safeSize.height, 1); - mDeviceContext->ResolveSubresource(resolvedTextureHelper.get(), 0, textureHelper.get(), - sourceSubResource, textureHelper.getFormat()); + // Perform a copy to planeTexture as we cannot read directly from NV12 d3d11 textures. + ANGLE_TRY(mBlit->copyTexture( + context, srv, srcGlBox, safeSize, internalFormat, rtv, destGlBox, safeSize, nullptr, + gl::GetUnsizedFormat(internalFormat), GL_NONE, GL_NEAREST, false, false, false)); - sourceSubResource = 0; - srcTexture = &resolvedTextureHelper; + // Update safeArea based on the destination. + safeArea.x = destGlBox.x; + safeArea.y = destGlBox.y; + safeArea.width = destGlBox.width; + safeArea.height = destGlBox.height; + + sourceSubResource = 0; + srcTexture = &intermediateTextureHelper; + } + else + { + if (textureHelper.getSampleCount() > 1) + { + D3D11_TEXTURE2D_DESC resolveDesc; + resolveDesc.Width = static_cast(texSize.width); + resolveDesc.Height = static_cast(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(GetImplAs(context), resolveDesc, + textureHelper.getFormatSet(), + &intermediateTextureHelper)); + intermediateTextureHelper.setInternalName( + "readFromAttachment::intermediateTextureHelper"); + + mDeviceContext->ResolveSubresource(intermediateTextureHelper.get(), 0, + textureHelper.get(), sourceSubResource, + textureHelper.getFormat()); + + sourceSubResource = 0; + srcTexture = &intermediateTextureHelper; + } + } } D3D11_BOX srcBox; @@ -3576,6 +3716,12 @@ angle::Result Renderer11::readFromAttachment(const gl::Context *context, } srcBox.back = srcBox.front + 1; + TextureHelper11 stagingHelper; + ANGLE_TRY(createStagingTexture(context, textureHelper.getTextureType(), + srcTexture->getFormatSet(), safeSize, StagingAccess::READ, + &stagingHelper)); + stagingHelper.setInternalName("readFromAttachment::stagingHelper"); + mDeviceContext->CopySubresourceRegion(stagingHelper.get(), 0, 0, 0, 0, srcTexture->get(), sourceSubResource, &srcBox); @@ -4083,20 +4229,20 @@ void Renderer11::generateCaps(gl::Caps *outCaps, void Renderer11::initializeFeatures(angle::FeaturesD3D *features) const { + ApplyFeatureOverrides(features, mDisplay->getState()); if (!mDisplay->getState().featuresAllDisabled) { d3d11::InitializeFeatures(mRenderer11DeviceCaps, mAdapterDescription, features); } - ApplyFeatureOverrides(features, mDisplay->getState()); } void Renderer11::initializeFrontendFeatures(angle::FrontendFeatures *features) const { + ApplyFeatureOverrides(features, mDisplay->getState()); if (!mDisplay->getState().featuresAllDisabled) { d3d11::InitializeFrontendFeatures(mAdapterDescription, features); } - ApplyFeatureOverrides(features, mDisplay->getState()); } DeviceImpl *Renderer11::createEGLDevice() @@ -4143,10 +4289,10 @@ angle::Result Renderer11::dispatchCompute(const gl::Context *context, GLuint numGroupsY, GLuint numGroupsZ) { - const gl::State &glState = context->getState(); - const gl::Program *program = glState.getProgram(); - if (program->getActiveShaderStorageBlockCount() > 0 || - program->getActiveAtomicCounterBufferCount() > 0) + const gl::State &glState = context->getState(); + const gl::ProgramExecutable *executable = glState.getProgramExecutable(); + if (executable->getActiveShaderStorageBlockCount() > 0 || + executable->getActiveAtomicCounterBufferCount() > 0) { ANGLE_TRY(markRawBufferUsage(context)); } @@ -4158,10 +4304,10 @@ angle::Result Renderer11::dispatchCompute(const gl::Context *context, } angle::Result Renderer11::dispatchComputeIndirect(const gl::Context *context, GLintptr indirect) { - const auto &glState = context->getState(); - const gl::Program *program = glState.getProgram(); - if (program->getActiveShaderStorageBlockCount() > 0 || - program->getActiveAtomicCounterBufferCount() > 0) + const auto &glState = context->getState(); + const gl::ProgramExecutable *executable = glState.getProgramExecutable(); + if (executable->getActiveShaderStorageBlockCount() > 0 || + executable->getActiveAtomicCounterBufferCount() > 0) { ANGLE_TRY(markRawBufferUsage(context)); } @@ -4365,12 +4511,13 @@ angle::Result Renderer11::mapResource(const gl::Context *context, angle::Result Renderer11::markTypedBufferUsage(const gl::Context *context) { const gl::State &glState = context->getState(); - ProgramD3D *programD3D = GetImplAs(glState.getProgram()); - gl::RangeUI imageRange = programD3D->getUsedImageRange(gl::ShaderType::Compute, false); + ProgramExecutableD3D *executableD3D = + GetImplAs(glState.getProgramExecutable()); + gl::RangeUI imageRange = executableD3D->getUsedImageRange(gl::ShaderType::Compute, false); for (unsigned int imageIndex = imageRange.low(); imageIndex < imageRange.high(); imageIndex++) { - GLint imageUnitIndex = programD3D->getImageMapping(gl::ShaderType::Compute, imageIndex, - false, context->getCaps()); + GLint imageUnitIndex = executableD3D->getImageMapping(gl::ShaderType::Compute, imageIndex, + false, context->getCaps()); ASSERT(imageUnitIndex != -1); const gl::ImageUnit &imageUnit = glState.getImageUnit(imageUnitIndex); if (imageUnit.texture.get()->getType() == gl::TextureType::Buffer)