//// Copyright (c) Microsoft Corporation. All rights reserved
#include "pch.h"
-#include "DirectXBase.h"
+#include "DirectXBase.h"
using namespace Windows::UI::Core;
using namespace Windows::Foundation;
using namespace Microsoft::WRL;
+using namespace Windows::Graphics::Display;
using namespace D2D1;
// Constructor.
DirectXBase::DirectXBase() :
- m_dpi(-1.0f)
+ m_dpi(-1.0f),
+ m_numBuffers(2)
{
}
// Note the ordering should be preserved.
// Don't forget to declare your application's minimum required feature level in its
// description. All applications are assumed to support 9.1 unless otherwise stated.
- D3D_FEATURE_LEVEL featureLevels[] =
+ D3D_FEATURE_LEVEL featureLevels[] =
{
D3D_FEATURE_LEVEL_11_1,
D3D_FEATURE_LEVEL_11_0,
{
// Save the DPI of this display in our class.
m_dpi = dpi;
-
+
// Update Direct2D's stored DPI.
m_d2dContext->SetDpi(m_dpi, m_dpi);
- // Often a DPI change implies a window size change. In some cases Windows will issues
- // both a size changed event and a DPI changed event. In this case, the resulting bounds
+ // Often a DPI change implies a window size change. In some cases Windows will issue
+ // both a size changed event and a DPI changed event. In this case, the resulting bounds
// will not change, and the window resize code will only be executed once.
UpdateForWindowSizeChange();
}
// This routine is called in the event handler for the view SizeChanged event.
void DirectXBase::UpdateForWindowSizeChange()
{
+ // Only handle window size changed if there is no pending DPI change.
+ if (m_dpi != DisplayProperties::LogicalDpi)
+ {
+ return;
+ }
+
if (m_window->Bounds.Width != m_windowBounds.Width ||
m_window->Bounds.Height != m_windowBounds.Height)
{
m_windowBounds = m_window->Bounds;
// If the swap chain already exists, resize it.
- if(m_swapChain != nullptr)
+ if (m_swapChain != nullptr)
{
DX::ThrowIfFailed(
- m_swapChain->ResizeBuffers(2, 0, 0, DXGI_FORMAT_B8G8R8A8_UNORM, 0)
+ m_swapChain->ResizeBuffers(m_numBuffers, 0, 0, DXGI_FORMAT_B8G8R8A8_UNORM, 0)
);
}
- // Otherwise, create a new one.
- else
+ else // Otherwise, create a new one.
{
// Allocate a descriptor.
DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0};
swapChainDesc.Width = 0; // use automatic sizing
swapChainDesc.Height = 0;
swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; // this is the most common swapchain format
- swapChainDesc.Stereo = false;
+ swapChainDesc.Stereo = false;
swapChainDesc.SampleDesc.Count = 1; // don't use multi-sampling
swapChainDesc.SampleDesc.Quality = 0;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
- swapChainDesc.BufferCount = 2; // use double buffering to enable flip
+ swapChainDesc.BufferCount = m_numBuffers; // use multiple buffering to enable flip
swapChainDesc.Scaling = DXGI_SCALING_NONE;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; // all Metro style apps must use this SwapEffect
swapChainDesc.Flags = 0;
// Once the desired swap chain description is configured, it must be created on the same adapter as our D3D Device
// First, retrieve the underlying DXGI Device from the D3D Device.
- ComPtr<IDXGIDevice1> dxgiDevice;
+ ComPtr<IDXGIDevice1> dxgiDevice;
DX::ThrowIfFailed(
m_d3dDevice.As(&dxgiDevice)
);
);
// Obtain the final swap chain for this window from the DXGI factory.
+ CoreWindow^ window = m_window.Get();
DX::ThrowIfFailed(
dxgiFactory->CreateSwapChainForCoreWindow(
m_d3dDevice.Get(),
- reinterpret_cast<IUnknown*>(m_window),
+ reinterpret_cast<IUnknown*>(window),
&swapChainDesc,
nullptr, // allow on all displays
&m_swapChain
)
);
- // Ensure that DXGI does not queue more than one frame at a time. This both reduces
- // latency and ensures that the application will only render after each VSync, minimizing
+ // Ensure that DXGI does not queue too many frames. This reduces latency and
+ // ensures that the application will only render after each VSync, minimizing
// power consumption.
DX::ThrowIfFailed(
- dxgiDevice->SetMaximumFrameLatency(1)
+ dxgiDevice->SetMaximumFrameLatency(m_numBuffers - 1)
);
-
}
// Obtain the backbuffer for this window which will be the final 3D rendertarget.
// Create a descriptor for the depth/stencil buffer.
CD3D11_TEXTURE2D_DESC depthStencilDesc(
- DXGI_FORMAT_D24_UNORM_S8_UINT,
+ DXGI_FORMAT_D24_UNORM_S8_UINT,
backBufferDesc.Width,
backBufferDesc.Height,
1,
);
// Create a DepthStencil view on this surface to use on bind.
+ auto viewDesc = CD3D11_DEPTH_STENCIL_VIEW_DESC(D3D11_DSV_DIMENSION_TEXTURE2D);
DX::ThrowIfFailed(
m_d3dDevice->CreateDepthStencilView(
depthStencil.Get(),
- &CD3D11_DEPTH_STENCIL_VIEW_DESC(D3D11_DSV_DIMENSION_TEXTURE2D),
+ &viewDesc,
&m_depthStencilView
)
);
// Set the current viewport using the descriptor.
m_d3dContext->RSSetViewports(1, &viewport);
- // Now we set up the Direct2D render target bitmap linked to the swapchain.
- // Whenever we render to this bitmap, it will be directly rendered to the
+ // Now we set up the Direct2D render target bitmap linked to the swapchain.
+ // Whenever we render to this bitmap, it will be directly rendered to the
// swapchain associated with the window.
- D2D1_BITMAP_PROPERTIES1 bitmapProperties =
+ D2D1_BITMAP_PROPERTIES1 bitmapProperties =
BitmapProperties1(
D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW,
PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED),
parameters.pDirtyRects = nullptr;
parameters.pScrollRect = nullptr;
parameters.pScrollOffset = nullptr;
-
+
// 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->Present1(1, 0, ¶meters);
- // If the device was removed either by a disconnect or a driver upgrade, we
+ // If the device was removed either by a disconnect or a driver upgrade, we
// must completely reinitialize the renderer.
if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET)
{
- Initialize(m_window, m_dpi);
+ Initialize(m_window.Get(), m_dpi);
}
else
{