Commit da3d2d2d authored by Sunny Sachanandani's avatar Sunny Sachanandani Committed by Commit Bot

gpu: Create swap chain with tearing support

Without this the 2D canvas demo https://codepen.io/miguelao/full/ZjJNNw
janks a lot since it enqueues too many presents which introduce implicit
synchronization without the DXGI_PRESENT_ALLOW_TEARING flag.  This moves
the swap chain tearing feature detection to a central place, and makes
shared image swap chain dependent on swap chain tearing.

Bug: 939657, 939659
Change-Id: Ic8a423a4e2742056dcbb8d3d4af473180e246a58
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1750199
Commit-Queue: Sunny Sachanandani <sunnyps@chromium.org>
Reviewed-by: default avatarKenneth Russell <kbr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#686665}
parent eaa08411
...@@ -204,6 +204,7 @@ class SharedImageBackingDXGISwapChain : public SharedImageBacking { ...@@ -204,6 +204,7 @@ class SharedImageBackingDXGISwapChain : public SharedImageBacking {
} }
bool PresentSwapChain() override { bool PresentSwapChain() override {
TRACE_EVENT0("gpu", "SharedImageBackingDXGISwapChain::PresentSwapChain");
if (buffer_index_ != 0) { if (buffer_index_ != 0) {
DLOG(ERROR) << "Swap chain backing does not correspond to back buffer"; DLOG(ERROR) << "Swap chain backing does not correspond to back buffer";
return false; return false;
...@@ -213,8 +214,9 @@ class SharedImageBackingDXGISwapChain : public SharedImageBacking { ...@@ -213,8 +214,9 @@ class SharedImageBackingDXGISwapChain : public SharedImageBacking {
params.DirtyRectsCount = 0; params.DirtyRectsCount = 0;
params.pDirtyRects = nullptr; params.pDirtyRects = nullptr;
HRESULT hr = UINT flags = DXGI_PRESENT_ALLOW_TEARING;
swap_chain_->Present1(0 /* interval */, 0 /* flags */, &params);
HRESULT hr = swap_chain_->Present1(0 /* interval */, flags, &params);
if (FAILED(hr)) { if (FAILED(hr)) {
DLOG(ERROR) << "Present1 failed with error " << std::hex << hr; DLOG(ERROR) << "Present1 failed with error " << std::hex << hr;
return false; return false;
...@@ -232,6 +234,9 @@ class SharedImageBackingDXGISwapChain : public SharedImageBacking { ...@@ -232,6 +234,9 @@ class SharedImageBackingDXGISwapChain : public SharedImageBacking {
DLOG(ERROR) << "GLImageDXGISwapChain::BindTexImage failed"; DLOG(ERROR) << "GLImageDXGISwapChain::BindTexImage failed";
return false; return false;
} }
TRACE_EVENT0("gpu",
"SharedImageBackingDXGISwapChain::PresentSwapChain::Flush");
// Flush device context through ANGLE otherwise present could be deferred. // Flush device context through ANGLE otherwise present could be deferred.
api->glFlushFn(); api->glFlushFn();
return true; return true;
...@@ -292,7 +297,8 @@ SwapChainFactoryDXGI::SwapChainBackings::operator=( ...@@ -292,7 +297,8 @@ SwapChainFactoryDXGI::SwapChainBackings::operator=(
// static // static
bool SwapChainFactoryDXGI::IsSupported() { bool SwapChainFactoryDXGI::IsSupported() {
return gl::DirectCompositionSurfaceWin::IsDirectCompositionSupported(); return gl::DirectCompositionSurfaceWin::IsDirectCompositionSupported() &&
gl::DirectCompositionSurfaceWin::IsSwapChainTearingSupported();
} }
std::unique_ptr<SharedImageBacking> SwapChainFactoryDXGI::MakeBacking( std::unique_ptr<SharedImageBacking> SwapChainFactoryDXGI::MakeBacking(
...@@ -415,7 +421,7 @@ SwapChainFactoryDXGI::SwapChainBackings SwapChainFactoryDXGI::CreateSwapChain( ...@@ -415,7 +421,7 @@ SwapChainFactoryDXGI::SwapChainBackings SwapChainFactoryDXGI::CreateSwapChain(
desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT; desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT;
desc.Scaling = DXGI_SCALING_STRETCH; desc.Scaling = DXGI_SCALING_STRETCH;
desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
desc.Flags = 0; desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
Microsoft::WRL::ComPtr<IDXGISwapChain1> swap_chain; Microsoft::WRL::ComPtr<IDXGISwapChain1> swap_chain;
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "base/win/windows_version.h" #include "base/win/windows_version.h"
#include "ui/gfx/native_widget_types.h" #include "ui/gfx/native_widget_types.h"
#include "ui/gl/color_space_utils.h" #include "ui/gl/color_space_utils.h"
#include "ui/gl/direct_composition_surface_win.h"
#include "ui/gl/egl_util.h" #include "ui/gl/egl_util.h"
#include "ui/gl/gl_angle_util_win.h" #include "ui/gl/gl_angle_util_win.h"
#include "ui/gl/gl_context.h" #include "ui/gl/gl_context.h"
...@@ -40,51 +41,11 @@ namespace { ...@@ -40,51 +41,11 @@ namespace {
// is made current, then this surface will be suspended. // is made current, then this surface will be suspended.
IDCompositionSurface* g_current_surface = nullptr; IDCompositionSurface* g_current_surface = nullptr;
// Returns true if swap chain tearing is supported. bool AllowTearing() {
bool IsSwapChainTearingSupported() { // Swap chain tearing is used only if vsync is disabled explicitly.
static const bool supported = [] { return base::CommandLine::ForCurrentProcess()->HasSwitch(
// Swap chain tearing is used only if vsync is disabled explicitly. switches::kDisableGpuVsync) &&
if (!base::CommandLine::ForCurrentProcess()->HasSwitch( DirectCompositionSurfaceWin::IsSwapChainTearingSupported();
switches::kDisableGpuVsync))
return false;
// Swap chain tearing is supported only on Windows 10 Anniversary Edition
// (Redstone 1) and above.
if (base::win::GetVersion() < base::win::Version::WIN10_RS1)
return false;
Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device =
QueryD3D11DeviceObjectFromANGLE();
if (!d3d11_device) {
DLOG(ERROR) << "Not using swap chain tearing because failed to retrieve "
"D3D11 device from ANGLE";
return false;
}
Microsoft::WRL::ComPtr<IDXGIDevice> dxgi_device;
d3d11_device.As(&dxgi_device);
DCHECK(dxgi_device);
Microsoft::WRL::ComPtr<IDXGIAdapter> dxgi_adapter;
dxgi_device->GetAdapter(&dxgi_adapter);
DCHECK(dxgi_adapter);
Microsoft::WRL::ComPtr<IDXGIFactory5> dxgi_factory;
if (FAILED(dxgi_adapter->GetParent(IID_PPV_ARGS(&dxgi_factory)))) {
DLOG(ERROR) << "Not using swap chain tearing because failed to retrieve "
"IDXGIFactory5 interface";
return false;
}
BOOL present_allow_tearing = FALSE;
DCHECK(dxgi_factory);
if (FAILED(dxgi_factory->CheckFeatureSupport(
DXGI_FEATURE_PRESENT_ALLOW_TEARING, &present_allow_tearing,
sizeof(present_allow_tearing)))) {
DLOG(ERROR)
<< "Not using swap chain tearing because CheckFeatureSupport failed";
return false;
}
return !!present_allow_tearing;
}();
return supported;
} }
} // namespace } // namespace
...@@ -156,9 +117,8 @@ bool DirectCompositionChildSurfaceWin::ReleaseDrawTexture(bool will_discard) { ...@@ -156,9 +117,8 @@ bool DirectCompositionChildSurfaceWin::ReleaseDrawTexture(bool will_discard) {
dcomp_surface_serial_++; dcomp_surface_serial_++;
} else if (!will_discard) { } else if (!will_discard) {
TRACE_EVENT0("gpu", "DirectCompositionChildSurfaceWin::PresentSwapChain"); TRACE_EVENT0("gpu", "DirectCompositionChildSurfaceWin::PresentSwapChain");
bool allow_tearing = IsSwapChainTearingSupported(); UINT interval = first_swap_ || !vsync_enabled_ || AllowTearing() ? 0 : 1;
UINT interval = first_swap_ || !vsync_enabled_ || allow_tearing ? 0 : 1; UINT flags = AllowTearing() ? DXGI_PRESENT_ALLOW_TEARING : 0;
UINT flags = allow_tearing ? DXGI_PRESENT_ALLOW_TEARING : 0;
DXGI_PRESENT_PARAMETERS params = {}; DXGI_PRESENT_PARAMETERS params = {};
RECT dirty_rect = swap_rect_.ToRECT(); RECT dirty_rect = swap_rect_.ToRECT();
params.DirtyRectsCount = 1; params.DirtyRectsCount = 1;
...@@ -336,8 +296,7 @@ bool DirectCompositionChildSurfaceWin::SetDrawRectangle( ...@@ -336,8 +296,7 @@ bool DirectCompositionChildSurfaceWin::SetDrawRectangle(
desc.AlphaMode = (has_alpha_ || enable_dc_layers_) desc.AlphaMode = (has_alpha_ || enable_dc_layers_)
? DXGI_ALPHA_MODE_PREMULTIPLIED ? DXGI_ALPHA_MODE_PREMULTIPLIED
: DXGI_ALPHA_MODE_IGNORE; : DXGI_ALPHA_MODE_IGNORE;
desc.Flags = desc.Flags = AllowTearing() ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0;
IsSwapChainTearingSupported() ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0;
HRESULT hr = dxgi_factory->CreateSwapChainForComposition( HRESULT hr = dxgi_factory->CreateSwapChainForComposition(
d3d11_device_.Get(), &desc, nullptr, &swap_chain_); d3d11_device_.Get(), &desc, nullptr, &swap_chain_);
first_swap_ = true; first_swap_ = true;
...@@ -439,8 +398,7 @@ bool DirectCompositionChildSurfaceWin::Resize(const gfx::Size& size, ...@@ -439,8 +398,7 @@ bool DirectCompositionChildSurfaceWin::Resize(const gfx::Size& size,
// ResizeBuffers can't change alpha blending mode. // ResizeBuffers can't change alpha blending mode.
if (swap_chain_ && resize_only) { if (swap_chain_ && resize_only) {
DXGI_FORMAT format = ColorSpaceUtils::GetDXGIFormat(color_space_); DXGI_FORMAT format = ColorSpaceUtils::GetDXGIFormat(color_space_);
UINT flags = UINT flags = AllowTearing() ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0;
IsSwapChainTearingSupported() ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0;
HRESULT hr = swap_chain_->ResizeBuffers(2 /* BufferCount */, size.width(), HRESULT hr = swap_chain_->ResizeBuffers(2 /* BufferCount */, size.width(),
size.height(), format, flags); size.height(), format, flags);
UMA_HISTOGRAM_BOOLEAN("GPU.DirectComposition.SwapChainResizeResult", UMA_HISTOGRAM_BOOLEAN("GPU.DirectComposition.SwapChainResizeResult",
......
...@@ -407,6 +407,43 @@ bool DirectCompositionSurfaceWin::IsHDRSupported() { ...@@ -407,6 +407,43 @@ bool DirectCompositionSurfaceWin::IsHDRSupported() {
return hdr_monitor_found; return hdr_monitor_found;
} }
// static
bool DirectCompositionSurfaceWin::IsSwapChainTearingSupported() {
static const bool supported = [] {
Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device =
QueryD3D11DeviceObjectFromANGLE();
if (!d3d11_device) {
DLOG(ERROR) << "Not using swap chain tearing because failed to retrieve "
"D3D11 device from ANGLE";
return false;
}
Microsoft::WRL::ComPtr<IDXGIDevice> dxgi_device;
d3d11_device.As(&dxgi_device);
DCHECK(dxgi_device);
Microsoft::WRL::ComPtr<IDXGIAdapter> dxgi_adapter;
dxgi_device->GetAdapter(&dxgi_adapter);
DCHECK(dxgi_adapter);
Microsoft::WRL::ComPtr<IDXGIFactory5> dxgi_factory;
if (FAILED(dxgi_adapter->GetParent(IID_PPV_ARGS(&dxgi_factory)))) {
DLOG(ERROR) << "Not using swap chain tearing because failed to retrieve "
"IDXGIFactory5 interface";
return false;
}
BOOL present_allow_tearing = FALSE;
DCHECK(dxgi_factory);
if (FAILED(dxgi_factory->CheckFeatureSupport(
DXGI_FEATURE_PRESENT_ALLOW_TEARING, &present_allow_tearing,
sizeof(present_allow_tearing)))) {
DLOG(ERROR)
<< "Not using swap chain tearing because CheckFeatureSupport failed";
return false;
}
return !!present_allow_tearing;
}();
return supported;
}
bool DirectCompositionSurfaceWin::Initialize(GLSurfaceFormat format) { bool DirectCompositionSurfaceWin::Initialize(GLSurfaceFormat format) {
d3d11_device_ = QueryD3D11DeviceObjectFromANGLE(); d3d11_device_ = QueryD3D11DeviceObjectFromANGLE();
if (!d3d11_device_) { if (!d3d11_device_) {
......
...@@ -77,6 +77,9 @@ class GL_EXPORT DirectCompositionSurfaceWin : public GLSurfaceEGL, ...@@ -77,6 +77,9 @@ class GL_EXPORT DirectCompositionSurfaceWin : public GLSurfaceEGL,
// Returns true if there is an HDR capable display connected. // Returns true if there is an HDR capable display connected.
static bool IsHDRSupported(); static bool IsHDRSupported();
// Returns true if swap chain tearing is supported.
static bool IsSwapChainTearingSupported();
static void SetScaledOverlaysSupportedForTesting(bool value); static void SetScaledOverlaysSupportedForTesting(bool value);
static void SetOverlayFormatUsedForTesting(DXGI_FORMAT format); static void SetOverlayFormatUsedForTesting(DXGI_FORMAT format);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment