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 {
}
bool PresentSwapChain() override {
TRACE_EVENT0("gpu", "SharedImageBackingDXGISwapChain::PresentSwapChain");
if (buffer_index_ != 0) {
DLOG(ERROR) << "Swap chain backing does not correspond to back buffer";
return false;
......@@ -213,8 +214,9 @@ class SharedImageBackingDXGISwapChain : public SharedImageBacking {
params.DirtyRectsCount = 0;
params.pDirtyRects = nullptr;
HRESULT hr =
swap_chain_->Present1(0 /* interval */, 0 /* flags */, &params);
UINT flags = DXGI_PRESENT_ALLOW_TEARING;
HRESULT hr = swap_chain_->Present1(0 /* interval */, flags, &params);
if (FAILED(hr)) {
DLOG(ERROR) << "Present1 failed with error " << std::hex << hr;
return false;
......@@ -232,6 +234,9 @@ class SharedImageBackingDXGISwapChain : public SharedImageBacking {
DLOG(ERROR) << "GLImageDXGISwapChain::BindTexImage failed";
return false;
}
TRACE_EVENT0("gpu",
"SharedImageBackingDXGISwapChain::PresentSwapChain::Flush");
// Flush device context through ANGLE otherwise present could be deferred.
api->glFlushFn();
return true;
......@@ -292,7 +297,8 @@ SwapChainFactoryDXGI::SwapChainBackings::operator=(
// static
bool SwapChainFactoryDXGI::IsSupported() {
return gl::DirectCompositionSurfaceWin::IsDirectCompositionSupported();
return gl::DirectCompositionSurfaceWin::IsDirectCompositionSupported() &&
gl::DirectCompositionSurfaceWin::IsSwapChainTearingSupported();
}
std::unique_ptr<SharedImageBacking> SwapChainFactoryDXGI::MakeBacking(
......@@ -415,7 +421,7 @@ SwapChainFactoryDXGI::SwapChainBackings SwapChainFactoryDXGI::CreateSwapChain(
desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT;
desc.Scaling = DXGI_SCALING_STRETCH;
desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
desc.Flags = 0;
desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
Microsoft::WRL::ComPtr<IDXGISwapChain1> swap_chain;
......
......@@ -15,6 +15,7 @@
#include "base/win/windows_version.h"
#include "ui/gfx/native_widget_types.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/gl_angle_util_win.h"
#include "ui/gl/gl_context.h"
......@@ -40,51 +41,11 @@ namespace {
// is made current, then this surface will be suspended.
IDCompositionSurface* g_current_surface = nullptr;
// Returns true if swap chain tearing is supported.
bool IsSwapChainTearingSupported() {
static const bool supported = [] {
// Swap chain tearing is used only if vsync is disabled explicitly.
if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
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;
bool AllowTearing() {
// Swap chain tearing is used only if vsync is disabled explicitly.
return base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableGpuVsync) &&
DirectCompositionSurfaceWin::IsSwapChainTearingSupported();
}
} // namespace
......@@ -156,9 +117,8 @@ bool DirectCompositionChildSurfaceWin::ReleaseDrawTexture(bool will_discard) {
dcomp_surface_serial_++;
} else if (!will_discard) {
TRACE_EVENT0("gpu", "DirectCompositionChildSurfaceWin::PresentSwapChain");
bool allow_tearing = IsSwapChainTearingSupported();
UINT interval = first_swap_ || !vsync_enabled_ || allow_tearing ? 0 : 1;
UINT flags = allow_tearing ? DXGI_PRESENT_ALLOW_TEARING : 0;
UINT interval = first_swap_ || !vsync_enabled_ || AllowTearing() ? 0 : 1;
UINT flags = AllowTearing() ? DXGI_PRESENT_ALLOW_TEARING : 0;
DXGI_PRESENT_PARAMETERS params = {};
RECT dirty_rect = swap_rect_.ToRECT();
params.DirtyRectsCount = 1;
......@@ -336,8 +296,7 @@ bool DirectCompositionChildSurfaceWin::SetDrawRectangle(
desc.AlphaMode = (has_alpha_ || enable_dc_layers_)
? DXGI_ALPHA_MODE_PREMULTIPLIED
: DXGI_ALPHA_MODE_IGNORE;
desc.Flags =
IsSwapChainTearingSupported() ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0;
desc.Flags = AllowTearing() ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0;
HRESULT hr = dxgi_factory->CreateSwapChainForComposition(
d3d11_device_.Get(), &desc, nullptr, &swap_chain_);
first_swap_ = true;
......@@ -439,8 +398,7 @@ bool DirectCompositionChildSurfaceWin::Resize(const gfx::Size& size,
// ResizeBuffers can't change alpha blending mode.
if (swap_chain_ && resize_only) {
DXGI_FORMAT format = ColorSpaceUtils::GetDXGIFormat(color_space_);
UINT flags =
IsSwapChainTearingSupported() ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0;
UINT flags = AllowTearing() ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0;
HRESULT hr = swap_chain_->ResizeBuffers(2 /* BufferCount */, size.width(),
size.height(), format, flags);
UMA_HISTOGRAM_BOOLEAN("GPU.DirectComposition.SwapChainResizeResult",
......
......@@ -407,6 +407,43 @@ bool DirectCompositionSurfaceWin::IsHDRSupported() {
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) {
d3d11_device_ = QueryD3D11DeviceObjectFromANGLE();
if (!d3d11_device_) {
......
......@@ -77,6 +77,9 @@ class GL_EXPORT DirectCompositionSurfaceWin : public GLSurfaceEGL,
// Returns true if there is an HDR capable display connected.
static bool IsHDRSupported();
// Returns true if swap chain tearing is supported.
static bool IsSwapChainTearingSupported();
static void SetScaledOverlaysSupportedForTesting(bool value);
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