Skip to content

Commit

Permalink
Tearing support for UWP and PC DeviceResources
Browse files Browse the repository at this point in the history
  • Loading branch information
walbourn committed May 23, 2017
1 parent 301de0d commit 7553432
Show file tree
Hide file tree
Showing 15 changed files with 237 additions and 41 deletions.
44 changes: 38 additions & 6 deletions d3d11game_uwp_cppwinrt_dr/DeviceResources.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ namespace ScreenRotation
};

// Constructor for DeviceResources.
DX::DeviceResources::DeviceResources(DXGI_FORMAT backBufferFormat, DXGI_FORMAT depthBufferFormat, UINT backBufferCount, D3D_FEATURE_LEVEL minFeatureLevel) :
DX::DeviceResources::DeviceResources(DXGI_FORMAT backBufferFormat, DXGI_FORMAT depthBufferFormat, UINT backBufferCount, D3D_FEATURE_LEVEL minFeatureLevel, unsigned int flags) :
m_screenViewport{},
m_backBufferFormat(backBufferFormat),
m_depthBufferFormat(depthBufferFormat),
Expand All @@ -94,6 +94,7 @@ DX::DeviceResources::DeviceResources(DXGI_FORMAT backBufferFormat, DXGI_FORMAT d
m_rotation(DXGI_MODE_ROTATION_IDENTITY),
m_outputSize{0, 0, 1, 1},
m_orientationTransform3D(ScreenRotation::Rotation0),
m_options(flags),
m_deviceNotify(nullptr)
{
}
Expand Down Expand Up @@ -254,7 +255,7 @@ void DX::DeviceResources::CreateWindowSizeDependentResources()
backBufferWidth,
backBufferHeight,
backBufferFormat,
0
(m_options & c_AllowTearing) ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0
);

if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET)
Expand Down Expand Up @@ -301,6 +302,7 @@ void DX::DeviceResources::CreateWindowSizeDependentResources()
swapChainDesc.Scaling = DXGI_SCALING_ASPECT_RATIO_STRETCH;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE;
swapChainDesc.Flags = (m_options & c_AllowTearing) ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0;

ComPtr<IDXGISwapChain1> swapChain;
DX::ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow(
Expand Down Expand Up @@ -516,10 +518,19 @@ void DX::DeviceResources::Trim()
// Present the contents of the swap chain to the screen.
void DX::DeviceResources::Present()
{
// The first argument instructs DXGI to block until VSync, putting the application
// to sleep until the next VSync. This ensures we don't waste any cycles rendering
// frames that will never be displayed to the screen.
HRESULT hr = m_swapChain->Present(1, 0);
HRESULT hr;
if (m_options & c_AllowTearing)
{
// Recommended to always use tearing if supported when using a sync interval of 0.
hr = m_swapChain->Present(0, DXGI_PRESENT_ALLOW_TEARING);
}
else
{
// The first argument instructs DXGI to block until VSync, putting the application
// to sleep until the next VSync. This ensures we don't waste any cycles rendering
// frames that will never be displayed to the screen.
hr = m_swapChain->Present(1, 0);
}

// Discard the contents of the render target.
// This is a valid operation only when the existing contents will be entirely
Expand Down Expand Up @@ -576,6 +587,27 @@ void DX::DeviceResources::GetHardwareAdapter(IDXGIAdapter1** ppAdapter)

DX::ThrowIfFailed(CreateDXGIFactory1(IID_PPV_ARGS(dxgiFactory.GetAddressOf())));

// Determines whether tearing support is available for fullscreen borderless windows.
if (m_options & c_AllowTearing)
{
BOOL allowTearing = FALSE;

ComPtr<IDXGIFactory5> factory5;
HRESULT hr = dxgiFactory.As(&factory5);
if (SUCCEEDED(hr))
{
hr = factory5->CheckFeatureSupport(DXGI_FEATURE_PRESENT_ALLOW_TEARING, &allowTearing, sizeof(allowTearing));
}

if (FAILED(hr) || !allowTearing)
{
m_options &= ~c_AllowTearing;
#ifdef _DEBUG
OutputDebugStringA("WARNING: Variable refresh rate displays not supported");
#endif
}
}

ComPtr<IDXGIAdapter1> adapter;
for (UINT adapterIndex = 0; DXGI_ERROR_NOT_FOUND != dxgiFactory->EnumAdapters1(adapterIndex, adapter.ReleaseAndGetAddressOf()); adapterIndex++)
{
Expand Down
9 changes: 8 additions & 1 deletion d3d11game_uwp_cppwinrt_dr/DeviceResources.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,13 @@ namespace DX
class DeviceResources
{
public:
static const unsigned int c_AllowTearing = 0x1;

DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM,
DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D24_UNORM_S8_UINT,
UINT backBufferCount = 2,
D3D_FEATURE_LEVEL minFeatureLevel = D3D_FEATURE_LEVEL_9_3);
D3D_FEATURE_LEVEL minFeatureLevel = D3D_FEATURE_LEVEL_9_3,
unsigned int flags = 0);

void CreateDeviceResources();
void CreateWindowSizeDependentResources();
Expand Down Expand Up @@ -50,6 +53,7 @@ namespace DX
D3D11_VIEWPORT GetScreenViewport() const { return m_screenViewport; }
UINT GetBackBufferCount() const { return m_backBufferCount; }
DirectX::XMFLOAT4X4 GetOrientationTransform3D() const { return m_orientationTransform3D; }
unsigned int GetDeviceOptions() const { return m_options; }

private:
void GetHardwareAdapter(IDXGIAdapter1** ppAdapter);
Expand Down Expand Up @@ -81,6 +85,9 @@ namespace DX
// Transforms used for display orientation.
DirectX::XMFLOAT4X4 m_orientationTransform3D;

// DeviceResources options (see flags above)
unsigned int m_options;

// The IDeviceNotify can be held directly as it owns the DeviceResources.
IDeviceNotify* m_deviceNotify;
};
Expand Down
4 changes: 2 additions & 2 deletions d3d11game_uwp_cppwinrt_dr/pch.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@
#include <wrl/client.h>

#include <d3d11_3.h>
#include <dxgi1_4.h>
#include <dxgi1_5.h>
#include <DirectXMath.h>
#include <DirectXColors.h>

#include <algorithm>
#include <exception>
#include <future>
#include <future>
#include <memory>
#include <stdexcept>

Expand Down
44 changes: 38 additions & 6 deletions d3d11game_uwp_dr/DeviceResources.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ namespace ScreenRotation
};

// Constructor for DeviceResources.
DX::DeviceResources::DeviceResources(DXGI_FORMAT backBufferFormat, DXGI_FORMAT depthBufferFormat, UINT backBufferCount, D3D_FEATURE_LEVEL minFeatureLevel) :
DX::DeviceResources::DeviceResources(DXGI_FORMAT backBufferFormat, DXGI_FORMAT depthBufferFormat, UINT backBufferCount, D3D_FEATURE_LEVEL minFeatureLevel, unsigned int flags) :
m_screenViewport{},
m_backBufferFormat(backBufferFormat),
m_depthBufferFormat(depthBufferFormat),
Expand All @@ -94,6 +94,7 @@ DX::DeviceResources::DeviceResources(DXGI_FORMAT backBufferFormat, DXGI_FORMAT d
m_rotation(DXGI_MODE_ROTATION_IDENTITY),
m_outputSize{0, 0, 1, 1},
m_orientationTransform3D(ScreenRotation::Rotation0),
m_options(flags),
m_deviceNotify(nullptr)
{
}
Expand Down Expand Up @@ -254,7 +255,7 @@ void DX::DeviceResources::CreateWindowSizeDependentResources()
backBufferWidth,
backBufferHeight,
backBufferFormat,
0
(m_options & c_AllowTearing) ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0
);

if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET)
Expand Down Expand Up @@ -301,6 +302,7 @@ void DX::DeviceResources::CreateWindowSizeDependentResources()
swapChainDesc.Scaling = DXGI_SCALING_ASPECT_RATIO_STRETCH;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE;
swapChainDesc.Flags = (m_options & c_AllowTearing) ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0;

ComPtr<IDXGISwapChain1> swapChain;
DX::ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow(
Expand Down Expand Up @@ -516,10 +518,19 @@ void DX::DeviceResources::Trim()
// Present the contents of the swap chain to the screen.
void DX::DeviceResources::Present()
{
// The first argument instructs DXGI to block until VSync, putting the application
// to sleep until the next VSync. This ensures we don't waste any cycles rendering
// frames that will never be displayed to the screen.
HRESULT hr = m_swapChain->Present(1, 0);
HRESULT hr;
if (m_options & c_AllowTearing)
{
// Recommended to always use tearing if supported when using a sync interval of 0.
hr = m_swapChain->Present(0, DXGI_PRESENT_ALLOW_TEARING);
}
else
{
// The first argument instructs DXGI to block until VSync, putting the application
// to sleep until the next VSync. This ensures we don't waste any cycles rendering
// frames that will never be displayed to the screen.
hr = m_swapChain->Present(1, 0);
}

// Discard the contents of the render target.
// This is a valid operation only when the existing contents will be entirely
Expand Down Expand Up @@ -576,6 +587,27 @@ void DX::DeviceResources::GetHardwareAdapter(IDXGIAdapter1** ppAdapter)

DX::ThrowIfFailed(CreateDXGIFactory1(IID_PPV_ARGS(dxgiFactory.GetAddressOf())));

// Determines whether tearing support is available for fullscreen borderless windows.
if (m_options & c_AllowTearing)
{
BOOL allowTearing = FALSE;

ComPtr<IDXGIFactory5> factory5;
HRESULT hr = dxgiFactory.As(&factory5);
if (SUCCEEDED(hr))
{
hr = factory5->CheckFeatureSupport(DXGI_FEATURE_PRESENT_ALLOW_TEARING, &allowTearing, sizeof(allowTearing));
}

if (FAILED(hr) || !allowTearing)
{
m_options &= ~c_AllowTearing;
#ifdef _DEBUG
OutputDebugStringA("WARNING: Variable refresh rate displays not supported");
#endif
}
}

ComPtr<IDXGIAdapter1> adapter;
for (UINT adapterIndex = 0; DXGI_ERROR_NOT_FOUND != dxgiFactory->EnumAdapters1(adapterIndex, adapter.ReleaseAndGetAddressOf()); adapterIndex++)
{
Expand Down
9 changes: 8 additions & 1 deletion d3d11game_uwp_dr/DeviceResources.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,13 @@ namespace DX
class DeviceResources
{
public:
static const unsigned int c_AllowTearing = 0x1;

DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM,
DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D24_UNORM_S8_UINT,
UINT backBufferCount = 2,
D3D_FEATURE_LEVEL minFeatureLevel = D3D_FEATURE_LEVEL_9_3);
D3D_FEATURE_LEVEL minFeatureLevel = D3D_FEATURE_LEVEL_9_3,
unsigned int flags = 0);

void CreateDeviceResources();
void CreateWindowSizeDependentResources();
Expand Down Expand Up @@ -50,6 +53,7 @@ namespace DX
D3D11_VIEWPORT GetScreenViewport() const { return m_screenViewport; }
UINT GetBackBufferCount() const { return m_backBufferCount; }
DirectX::XMFLOAT4X4 GetOrientationTransform3D() const { return m_orientationTransform3D; }
unsigned int GetDeviceOptions() const { return m_options; }

private:
void GetHardwareAdapter(IDXGIAdapter1** ppAdapter);
Expand Down Expand Up @@ -81,6 +85,9 @@ namespace DX
// Transforms used for display orientation.
DirectX::XMFLOAT4X4 m_orientationTransform3D;

// DeviceResources options (see flags above)
unsigned int m_options;

// The IDeviceNotify can be held directly as it owns the DeviceResources.
IDeviceNotify* m_deviceNotify;
};
Expand Down
2 changes: 1 addition & 1 deletion d3d11game_uwp_dr/pch.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#include <wrl.h>

#include <d3d11_3.h>
#include <dxgi1_4.h>
#include <dxgi1_5.h>
#include <DirectXMath.h>
#include <DirectXColors.h>

Expand Down
44 changes: 38 additions & 6 deletions d3d12game_uwp_cppwinrt_dr/DeviceResources.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ namespace
};

// Constructor for DeviceResources.
DX::DeviceResources::DeviceResources(DXGI_FORMAT backBufferFormat, DXGI_FORMAT depthBufferFormat, UINT backBufferCount, D3D_FEATURE_LEVEL minFeatureLevel) :
DX::DeviceResources::DeviceResources(DXGI_FORMAT backBufferFormat, DXGI_FORMAT depthBufferFormat, UINT backBufferCount, D3D_FEATURE_LEVEL minFeatureLevel, unsigned int flags) :
m_backBufferIndex(0),
m_fenceValues{},
m_rtvDescriptorSize(0),
Expand All @@ -75,6 +75,7 @@ DX::DeviceResources::DeviceResources(DXGI_FORMAT backBufferFormat, DXGI_FORMAT d
m_rotation(DXGI_MODE_ROTATION_IDENTITY),
m_outputSize{0, 0, 1, 1},
m_orientationTransform3D(ScreenRotation::Rotation0),
m_options(flags),
m_deviceNotify(nullptr)
{
if (backBufferCount > MAX_BACK_BUFFER_COUNT)
Expand Down Expand Up @@ -131,6 +132,27 @@ void DX::DeviceResources::CreateDeviceResources()

DX::ThrowIfFailed(CreateDXGIFactory1(IID_PPV_ARGS(m_dxgiFactory.ReleaseAndGetAddressOf())));

// Determines whether tearing support is available for fullscreen borderless windows.
if (m_options & c_AllowTearing)
{
BOOL allowTearing = FALSE;

ComPtr<IDXGIFactory5> factory5;
HRESULT hr = m_dxgiFactory.As(&factory5);
if (SUCCEEDED(hr))
{
hr = factory5->CheckFeatureSupport(DXGI_FEATURE_PRESENT_ALLOW_TEARING, &allowTearing, sizeof(allowTearing));
}

if (FAILED(hr) || !allowTearing)
{
m_options &= ~c_AllowTearing;
#ifdef _DEBUG
OutputDebugStringA("WARNING: Variable refresh rate displays not supported");
#endif
}
}

ComPtr<IDXGIAdapter1> adapter;
GetAdapter(adapter.GetAddressOf());

Expand Down Expand Up @@ -264,7 +286,7 @@ void DX::DeviceResources::CreateWindowSizeDependentResources()
backBufferWidth,
backBufferHeight,
backBufferFormat,
0
(m_options & c_AllowTearing) ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0
);

if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET)
Expand Down Expand Up @@ -300,6 +322,7 @@ void DX::DeviceResources::CreateWindowSizeDependentResources()
swapChainDesc.Scaling = DXGI_SCALING_ASPECT_RATIO_STRETCH;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE;
swapChainDesc.Flags = (m_options & c_AllowTearing) ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0;

// Create a swap chain for the window.
ComPtr<IDXGISwapChain1> swapChain;
Expand Down Expand Up @@ -556,10 +579,19 @@ void DX::DeviceResources::Present(D3D12_RESOURCE_STATES beforeState)
DX::ThrowIfFailed(m_commandList->Close());
m_commandQueue->ExecuteCommandLists(1, CommandListCast(m_commandList.GetAddressOf()));

// The first argument instructs DXGI to block until VSync, putting the application
// to sleep until the next VSync. This ensures we don't waste any cycles rendering
// frames that will never be displayed to the screen.
HRESULT hr = m_swapChain->Present(1, 0);
HRESULT hr;
if (m_options & c_AllowTearing)
{
// Recommended to always use tearing if supported when using a sync interval of 0.
hr = m_swapChain->Present(0, DXGI_PRESENT_ALLOW_TEARING);
}
else
{
// The first argument instructs DXGI to block until VSync, putting the application
// to sleep until the next VSync. This ensures we don't waste any cycles rendering
// frames that will never be displayed to the screen.
hr = m_swapChain->Present(1, 0);
}

// If the device was reset we must completely reinitialize the renderer.
if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET)
Expand Down
9 changes: 8 additions & 1 deletion d3d12game_uwp_cppwinrt_dr/DeviceResources.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,13 @@ namespace DX
class DeviceResources
{
public:
static const unsigned int c_AllowTearing = 0x1;

DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM,
DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT,
UINT backBufferCount = 2,
D3D_FEATURE_LEVEL minFeatureLevel = D3D_FEATURE_LEVEL_11_0);
D3D_FEATURE_LEVEL minFeatureLevel = D3D_FEATURE_LEVEL_11_0,
unsigned int flags = 0);
~DeviceResources();

void CreateDeviceResources();
Expand Down Expand Up @@ -54,6 +57,7 @@ namespace DX
UINT GetCurrentFrameIndex() const { return m_backBufferIndex; }
UINT GetBackBufferCount() const { return m_backBufferCount; }
DirectX::XMFLOAT4X4 GetOrientationTransform3D() const { return m_orientationTransform3D; }
unsigned int GetDeviceOptions() const { return m_options; }

CD3DX12_CPU_DESCRIPTOR_HANDLE GetRenderTargetView() const
{
Expand Down Expand Up @@ -108,6 +112,9 @@ namespace DX
DXGI_MODE_ROTATION m_rotation;
RECT m_outputSize;

// DeviceResources options (see flags above)
unsigned int m_options;

// Transforms used for display orientation.
DirectX::XMFLOAT4X4 m_orientationTransform3D;

Expand Down
2 changes: 1 addition & 1 deletion d3d12game_uwp_cppwinrt_dr/pch.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
#include <wrl/event.h>

#include <d3d12.h>
#include <dxgi1_4.h>
#include <dxgi1_5.h>
#include <DirectXMath.h>
#include <DirectXColors.h>

Expand Down
Loading

0 comments on commit 7553432

Please sign in to comment.