Skip to content

Commit 073e705

Browse files
committed
Merge pull request #32 from Microsoft/develop
Merge develop into master
2 parents 8f64a67 + 3106a7a commit 073e705

File tree

4 files changed

+166
-30
lines changed

4 files changed

+166
-30
lines changed

Templates/DirectX12App/App.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,10 @@ void App::OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args)
181181

182182
void App::OnDpiChanged(DisplayInformation^ sender, Object^ args)
183183
{
184+
// Note: The value for LogicalDpi retrieved here may not match the effective DPI of the app
185+
// if it is being scaled for high resolution devices. Once the DPI is set on DeviceResources,
186+
// you should always retrieve it using the GetDpi method.
187+
// See DeviceResources.cpp for more details.
184188
GetDeviceResources()->SetDpi(sender->LogicalDpi);
185189
m_main->OnWindowSizeChanged();
186190
}

Templates/DirectX12App/Common/DeviceResources.cpp

Lines changed: 137 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,23 @@ using namespace Windows::UI::Core;
1010
using namespace Windows::UI::Xaml::Controls;
1111
using namespace Platform;
1212

13+
namespace DisplayMetrics
14+
{
15+
// High resolution displays can require a lot of GPU and battery power to render.
16+
// High resolution phones, for example, may suffer from poor battery life if
17+
// games attempt to render at 60 frames per second at full fidelity.
18+
// The decision to render at full fidelity across all platforms and form factors
19+
// should be deliberate.
20+
static const bool SupportHighResolutions = false;
21+
22+
// The default thresholds that define a "high resolution" display. If the thresholds
23+
// are exceeded and SupportHighResolutions is false, the dimensions will be scaled
24+
// by 50%.
25+
static const float DpiThreshold = 192.0f; // 200% of standard desktop display.
26+
static const float WidthThreshold = 1920.0f; // 1080p width.
27+
static const float HeightThreshold = 1080.0f; // 1080p height.
28+
};
29+
1330
// Constants used to calculate screen rotations.
1431
namespace ScreenRotation
1532
{
@@ -58,6 +75,7 @@ DX::DeviceResources::DeviceResources() :
5875
m_nativeOrientation(DisplayOrientations::None),
5976
m_currentOrientation(DisplayOrientations::None),
6077
m_dpi(-1.0f),
78+
m_effectiveDpi(-1.0f),
6179
m_deviceRemoved(false)
6280
{
6381
ZeroMemory(m_fenceValues, sizeof(m_fenceValues));
@@ -86,9 +104,12 @@ void DX::DeviceResources::CreateDeviceResources()
86104

87105
DX::ThrowIfFailed(CreateDXGIFactory1(IID_PPV_ARGS(&m_dxgiFactory)));
88106

107+
ComPtr<IDXGIAdapter1> adapter;
108+
GetHardwareAdapter(m_dxgiFactory.Get(), &adapter);
109+
89110
// Create the Direct3D 12 API device object
90111
HRESULT hr = D3D12CreateDevice(
91-
nullptr, // Specify nullptr to use the default adapter.
112+
adapter.Get(), // The hardware adapter.
92113
D3D_FEATURE_LEVEL_11_0, // Minimum feature level this app can support.
93114
IID_PPV_ARGS(&m_d3dDevice) // Returns the Direct3D device created.
94115
);
@@ -145,13 +166,7 @@ void DX::DeviceResources::CreateWindowSizeDependentResources()
145166
}
146167
m_rtvHeap = nullptr;
147168

148-
// Calculate the necessary render target size in pixels.
149-
m_outputSize.Width = DX::ConvertDipsToPixels(m_logicalSize.Width, m_dpi);
150-
m_outputSize.Height = DX::ConvertDipsToPixels(m_logicalSize.Height, m_dpi);
151-
152-
// Prevent zero size DirectX content from being created.
153-
m_outputSize.Width = max(m_outputSize.Width, 1);
154-
m_outputSize.Height = max(m_outputSize.Height, 1);
169+
UpdateRenderTargetSize();
155170

156171
// The width and height of the swap chain must be based on the window's
157172
// natively-oriented width and height. If the window is not in the native
@@ -189,6 +204,7 @@ void DX::DeviceResources::CreateWindowSizeDependentResources()
189204
else
190205
{
191206
// Otherwise, create a new one using the same adapter as the existing Direct3D device.
207+
DXGI_SCALING scaling = DisplayMetrics::SupportHighResolutions ? DXGI_SCALING_NONE : DXGI_SCALING_STRETCH;
192208
DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {};
193209

194210
swapChainDesc.Width = lround(m_d3dRenderTargetSize.Width); // Match the size of the window.
@@ -201,13 +217,13 @@ void DX::DeviceResources::CreateWindowSizeDependentResources()
201217
swapChainDesc.BufferCount = c_frameCount; // Use triple-buffering to minimize latency.
202218
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; // All Windows Universal apps must use _FLIP_ SwapEffects
203219
swapChainDesc.Flags = 0;
204-
swapChainDesc.Scaling = DXGI_SCALING_NONE;
220+
swapChainDesc.Scaling = scaling;
205221
swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE;
206222

207223
ComPtr<IDXGISwapChain1> swapChain;
208224
DX::ThrowIfFailed(
209225
m_dxgiFactory->CreateSwapChainForCoreWindow(
210-
m_commandQueue.Get(),
226+
m_commandQueue.Get(), // Swap chains need a reference to the command queue in DirectX 12.
211227
reinterpret_cast<IUnknown*>(m_window.Get()),
212228
&swapChainDesc,
213229
nullptr,
@@ -248,22 +264,15 @@ void DX::DeviceResources::CreateWindowSizeDependentResources()
248264
m_swapChain->SetRotation(displayRotation)
249265
);
250266

251-
// Create a render target view of the swap chain back buffer.
267+
// Create render target views of the swap chain back buffer.
252268
{
253-
D3D12_DESCRIPTOR_HEAP_DESC desc = {};
254-
desc.NumDescriptors = c_frameCount;
255-
desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
256-
desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
257-
DX::ThrowIfFailed(m_d3dDevice->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&m_rtvHeap)));
269+
D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc = {};
270+
rtvHeapDesc.NumDescriptors = c_frameCount;
271+
rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
272+
rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
273+
DX::ThrowIfFailed(m_d3dDevice->CreateDescriptorHeap(&rtvHeapDesc, IID_PPV_ARGS(&m_rtvHeap)));
258274
m_rtvHeap->SetName(L"Render Target View Descriptor Heap");
259275

260-
// All pending GPU work was already finished. Update the tracked fence values
261-
// to the last value signaled.
262-
for (UINT n = 0; n < c_frameCount; n++)
263-
{
264-
m_fenceValues[n] = m_fenceValues[m_currentFrame];
265-
}
266-
267276
m_currentFrame = 0;
268277
CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor(m_rtvHeap->GetCPUDescriptorHandleForHeapStart());
269278
m_rtvDescriptorSize = m_d3dDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
@@ -279,10 +288,85 @@ void DX::DeviceResources::CreateWindowSizeDependentResources()
279288
}
280289
}
281290

291+
// Create a depth stencil view.
292+
{
293+
D3D12_DESCRIPTOR_HEAP_DESC dsvHeapDesc = {};
294+
dsvHeapDesc.NumDescriptors = 1;
295+
dsvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV;
296+
dsvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
297+
ThrowIfFailed(m_d3dDevice->CreateDescriptorHeap(&dsvHeapDesc, IID_PPV_ARGS(&m_dsvHeap)));
298+
299+
D3D12_HEAP_PROPERTIES depthHeapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT);
300+
D3D12_RESOURCE_DESC depthResourceDesc = CD3DX12_RESOURCE_DESC::Tex2D(
301+
DXGI_FORMAT_D32_FLOAT,
302+
static_cast<UINT>(m_d3dRenderTargetSize.Width),
303+
static_cast<UINT>(m_d3dRenderTargetSize.Height),
304+
1,
305+
0,
306+
1,
307+
0,
308+
D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL);
309+
310+
D3D12_CLEAR_VALUE depthOptimizedClearValue = {};
311+
depthOptimizedClearValue.Format = DXGI_FORMAT_D32_FLOAT;
312+
depthOptimizedClearValue.DepthStencil.Depth = 1.0f;
313+
depthOptimizedClearValue.DepthStencil.Stencil = 0;
314+
315+
ThrowIfFailed(m_d3dDevice->CreateCommittedResource(
316+
&depthHeapProperties,
317+
D3D12_HEAP_FLAG_NONE,
318+
&depthResourceDesc,
319+
D3D12_RESOURCE_STATE_DEPTH_WRITE,
320+
&depthOptimizedClearValue,
321+
IID_PPV_ARGS(&m_depthStencil)
322+
));
323+
324+
D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = {};
325+
dsvDesc.Format = DXGI_FORMAT_D32_FLOAT;
326+
dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D;
327+
dsvDesc.Flags = D3D12_DSV_FLAG_NONE;
328+
329+
m_d3dDevice->CreateDepthStencilView(m_depthStencil.Get(), &dsvDesc, m_dsvHeap->GetCPUDescriptorHandleForHeapStart());
330+
}
331+
332+
// All pending GPU work was already finished. Update the tracked fence values
333+
// to the last value signaled.
334+
for (UINT n = 0; n < c_frameCount; n++)
335+
{
336+
m_fenceValues[n] = m_fenceValues[m_currentFrame];
337+
}
338+
282339
// Set the 3D rendering viewport to target the entire window.
283340
m_screenViewport = { 0.0f, 0.0f, m_d3dRenderTargetSize.Width, m_d3dRenderTargetSize.Height, 0.0f, 1.0f };
284341
}
285342

343+
void DX::DeviceResources::UpdateRenderTargetSize()
344+
{
345+
m_effectiveDpi = m_dpi;
346+
347+
// To improve battery life on high resolution devices, render to a smaller render target
348+
// and allow the GPU to scale the output when it is presented.
349+
if (!DisplayMetrics::SupportHighResolutions && m_dpi > DisplayMetrics::DpiThreshold)
350+
{
351+
float width = DX::ConvertDipsToPixels(m_logicalSize.Width, m_dpi);
352+
float height = DX::ConvertDipsToPixels(m_logicalSize.Height, m_dpi);
353+
354+
if (width > DisplayMetrics::WidthThreshold && height > DisplayMetrics::HeightThreshold)
355+
{
356+
// To scale the app we change the effective DPI. Logical size does not change.
357+
m_effectiveDpi /= 2.0f;
358+
}
359+
}
360+
361+
// Calculate the necessary render target size in pixels.
362+
m_outputSize.Width = DX::ConvertDipsToPixels(m_logicalSize.Width, m_effectiveDpi);
363+
m_outputSize.Height = DX::ConvertDipsToPixels(m_logicalSize.Height, m_effectiveDpi);
364+
365+
// Prevent zero size DirectX content from being created.
366+
m_outputSize.Width = max(m_outputSize.Width, 1);
367+
m_outputSize.Height = max(m_outputSize.Height, 1);
368+
}
369+
286370
// This method is called when the CoreWindow is created (or re-created).
287371
void DX::DeviceResources::SetWindow(CoreWindow^ window)
288372
{
@@ -473,4 +557,33 @@ DXGI_MODE_ROTATION DX::DeviceResources::ComputeDisplayRotation()
473557
break;
474558
}
475559
return rotation;
476-
}
560+
}
561+
562+
// This method acquires the first available hardware adapter that supports Direct3D 12.
563+
// If no such adapter can be found, *ppAdapter will be set to nullptr.
564+
void DX::DeviceResources::GetHardwareAdapter(IDXGIFactory4* pFactory, IDXGIAdapter1** ppAdapter)
565+
{
566+
ComPtr<IDXGIAdapter1> adapter;
567+
*ppAdapter = nullptr;
568+
569+
for (UINT adapterIndex = 0; DXGI_ERROR_NOT_FOUND != pFactory->EnumAdapters1(adapterIndex, &adapter); ++adapterIndex)
570+
{
571+
DXGI_ADAPTER_DESC1 desc;
572+
adapter->GetDesc1(&desc);
573+
574+
if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE)
575+
{
576+
// Don't select the Basic Render Driver adapter.
577+
continue;
578+
}
579+
580+
// Check to see if the adapter supports Direct3D 12, but don't create the
581+
// actual device yet.
582+
if (SUCCEEDED(D3D12CreateDevice(adapter.Get(), D3D_FEATURE_LEVEL_11_0, _uuidof(ID3D12Device), nullptr)))
583+
{
584+
break;
585+
}
586+
}
587+
588+
*ppAdapter = adapter.Detach();
589+
}

Templates/DirectX12App/Common/DeviceResources.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,20 @@ namespace DX
1717
void Present();
1818
void WaitForGpu();
1919

20-
// Device Accessors.
20+
// The size of the render target, in pixels.
2121
Windows::Foundation::Size GetOutputSize() const { return m_outputSize; }
22+
23+
// The size of the render target, in dips.
2224
Windows::Foundation::Size GetLogicalSize() const { return m_logicalSize; }
25+
26+
float GetDpi() const { return m_effectiveDpi; }
2327
bool IsDeviceRemoved() const { return m_deviceRemoved; }
2428

2529
// D3D Accessors.
2630
ID3D12Device* GetD3DDevice() const { return m_d3dDevice.Get(); }
2731
IDXGISwapChain3* GetSwapChain() const { return m_swapChain.Get(); }
2832
ID3D12Resource* GetRenderTarget() const { return m_renderTargets[m_currentFrame].Get(); }
33+
ID3D12Resource* GetDepthStencil() const { return m_depthStencil.Get(); }
2934
ID3D12CommandQueue* GetCommandQueue() const { return m_commandQueue.Get(); }
3035
ID3D12CommandAllocator* GetCommandAllocator() const { return m_commandAllocators[m_currentFrame].Get(); }
3136
D3D12_VIEWPORT GetScreenViewport() const { return m_screenViewport; }
@@ -36,13 +41,19 @@ namespace DX
3641
{
3742
return CD3DX12_CPU_DESCRIPTOR_HANDLE(m_rtvHeap->GetCPUDescriptorHandleForHeapStart(), m_currentFrame, m_rtvDescriptorSize);
3843
}
44+
CD3DX12_CPU_DESCRIPTOR_HANDLE GetDepthStencilView() const
45+
{
46+
return CD3DX12_CPU_DESCRIPTOR_HANDLE(m_dsvHeap->GetCPUDescriptorHandleForHeapStart());
47+
}
3948

4049
private:
4150
void CreateDeviceIndependentResources();
4251
void CreateDeviceResources();
4352
void CreateWindowSizeDependentResources();
53+
void UpdateRenderTargetSize();
4454
void MoveToNextFrame();
4555
DXGI_MODE_ROTATION ComputeDisplayRotation();
56+
void GetHardwareAdapter(IDXGIFactory4* pFactory, IDXGIAdapter1** ppAdapter);
4657

4758
UINT m_currentFrame;
4859

@@ -51,7 +62,9 @@ namespace DX
5162
Microsoft::WRL::ComPtr<IDXGIFactory4> m_dxgiFactory;
5263
Microsoft::WRL::ComPtr<IDXGISwapChain3> m_swapChain;
5364
Microsoft::WRL::ComPtr<ID3D12Resource> m_renderTargets[c_frameCount];
65+
Microsoft::WRL::ComPtr<ID3D12Resource> m_depthStencil;
5466
Microsoft::WRL::ComPtr<ID3D12DescriptorHeap> m_rtvHeap;
67+
Microsoft::WRL::ComPtr<ID3D12DescriptorHeap> m_dsvHeap;
5568
UINT m_rtvDescriptorSize;
5669
Microsoft::WRL::ComPtr<ID3D12CommandQueue> m_commandQueue;
5770
Microsoft::WRL::ComPtr<ID3D12CommandAllocator> m_commandAllocators[c_frameCount];
@@ -74,6 +87,9 @@ namespace DX
7487
Windows::Graphics::Display::DisplayOrientations m_currentOrientation;
7588
float m_dpi;
7689

90+
// This is the DPI that will be reported back to the app. It takes into account whether the app supports high resolution screens or not.
91+
float m_effectiveDpi;
92+
7793
// Transforms used for display orientation.
7894
DirectX::XMFLOAT4X4 m_orientationTransform3D;
7995
};

Templates/DirectX12App/Content/Sample3DSceneRenderer.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -92,12 +92,12 @@ void Sample3DSceneRenderer::CreateDeviceDependentResources()
9292
state.PS = { &m_pixelShader[0], m_pixelShader.size() };
9393
state.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT);
9494
state.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT);
95-
state.DepthStencilState.DepthEnable = FALSE;
96-
state.DepthStencilState.StencilEnable = FALSE;
95+
state.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT);
9796
state.SampleMask = UINT_MAX;
9897
state.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
9998
state.NumRenderTargets = 1;
10099
state.RTVFormats[0] = DXGI_FORMAT_B8G8R8A8_UNORM;
100+
state.DSVFormat = DXGI_FORMAT_D32_FLOAT;
101101
state.SampleDesc.Count = 1;
102102

103103
DX::ThrowIfFailed(m_deviceResources->GetD3DDevice()->CreateGraphicsPipelineState(&state, IID_PPV_ARGS(&m_pipelineState)));
@@ -229,7 +229,7 @@ void Sample3DSceneRenderer::CreateDeviceDependentResources()
229229
UpdateSubresources(m_commandList.Get(), m_indexBuffer.Get(), indexBufferUpload.Get(), 0, 0, 1, &indexData);
230230

231231
CD3DX12_RESOURCE_BARRIER indexBufferResourceBarrier =
232-
CD3DX12_RESOURCE_BARRIER::Transition(m_indexBuffer.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);
232+
CD3DX12_RESOURCE_BARRIER::Transition(m_indexBuffer.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_INDEX_BUFFER);
233233
m_commandList->ResourceBarrier(1, &indexBufferResourceBarrier);
234234
}
235235

@@ -463,9 +463,12 @@ bool Sample3DSceneRenderer::Render()
463463
m_commandList->ResourceBarrier(1, &renderTargetResourceBarrier);
464464

465465
// Record drawing commands.
466-
m_commandList->ClearRenderTargetView(m_deviceResources->GetRenderTargetView(), DirectX::Colors::CornflowerBlue, 0, nullptr);
467466
D3D12_CPU_DESCRIPTOR_HANDLE renderTargetView = m_deviceResources->GetRenderTargetView();
468-
m_commandList->OMSetRenderTargets(1, &renderTargetView, false, nullptr);
467+
D3D12_CPU_DESCRIPTOR_HANDLE depthStencilView = m_deviceResources->GetDepthStencilView();
468+
m_commandList->ClearRenderTargetView(renderTargetView, DirectX::Colors::CornflowerBlue, 0, nullptr);
469+
m_commandList->ClearDepthStencilView(depthStencilView, D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr);
470+
471+
m_commandList->OMSetRenderTargets(1, &renderTargetView, false, &depthStencilView);
469472

470473
m_commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
471474
m_commandList->IASetVertexBuffers(0, 1, &m_vertexBufferView);

0 commit comments

Comments
 (0)