diff --git a/Kits/ATGTK/ControllerHelp.h b/Kits/ATGTK/ControllerHelp.h index 75b38e29..e08a0cc0 100644 --- a/Kits/ATGTK/ControllerHelp.h +++ b/Kits/ATGTK/ControllerHelp.h @@ -67,6 +67,13 @@ namespace ATG public: Help(_In_z_ const wchar_t* title, _In_z_ const wchar_t* description, _In_count_(buttonCount) const HelpButtonAssignment* buttons, size_t buttonCount, bool linearColors = false); + + Help(Help&&) = default; + Help& operator= (Help&&) = default; + + Help(Help const&) = delete; + Help& operator= (Help const&) = delete; + ~Help(); #if defined(__d3d12_h__) || defined(__d3d12_x_h__) diff --git a/Kits/ATGTK/PBREffect/PBREffect_Math.hlsli b/Kits/ATGTK/PBREffect/PBREffect_Math.hlsli index ad7d6b72..00bacddc 100644 --- a/Kits/ATGTK/PBREffect/PBREffect_Math.hlsli +++ b/Kits/ATGTK/PBREffect/PBREffect_Math.hlsli @@ -12,6 +12,11 @@ static const float PI = 3.14159265f; +float3 BiasX2(float3 x) +{ + return 2.0f * x - 1.0f; +} + // Given a local normal, transform it into a tangent space given by surface normal and tangent float3 PeturbNormal(float3 localNormal, float3 surfaceNormalWS, float3 surfaceTangentWS) { diff --git a/Kits/ATGTK/PBREffect/PBREffect_PSTextured.hlsl b/Kits/ATGTK/PBREffect/PBREffect_PSTextured.hlsl index 96804836..30ae0608 100644 --- a/Kits/ATGTK/PBREffect/PBREffect_PSTextured.hlsl +++ b/Kits/ATGTK/PBREffect/PBREffect_PSTextured.hlsl @@ -18,7 +18,7 @@ float4 PSTextured(PSInputPixelLightingTxTangent pin) : SV_Target0 const float3 L = normalize(-PBR_LightDirection[0]); // light vector ("to light" oppositve of light's direction) // Before lighting, peturb the surface's normal by the one given in normal map. - float3 localNormal = (PBR_NormalTexture.Sample(PBR_SurfaceSampler, pin.TexCoord).xyz * 2) - 1; + float3 localNormal = BiasX2(PBR_NormalTexture.Sample(PBR_SurfaceSampler, pin.TexCoord).xyz); float3 N = PeturbNormal( localNormal, pin.NormalWS, pin.TangentWS); diff --git a/Kits/ATGTK/RenderTexture.cpp b/Kits/ATGTK/RenderTexture.cpp new file mode 100644 index 00000000..0887f5e9 --- /dev/null +++ b/Kits/ATGTK/RenderTexture.cpp @@ -0,0 +1,303 @@ +//-------------------------------------------------------------------------------------- +// File: RenderTexture.cpp +// +// Helper for managing offscreen render targets +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------------------------------- + +#pragma once + +#include "pch.h" +#include "RenderTexture.h" + +#include "DirectXHelpers.h" + +#include +#include +#include + +#include + +using namespace DirectX; +using namespace DX; + +using Microsoft::WRL::ComPtr; + +#if defined(__d3d12_h__) || defined(__d3d12_x_h__) +//====================================================================================== +// Direct3D 12 +//====================================================================================== +RenderTexture::RenderTexture(DXGI_FORMAT format) : + m_format(format), + m_width(0), + m_height(0), + m_state(D3D12_RESOURCE_STATE_COMMON), + m_srvDescriptor{}, + m_rtvDescriptor{}, + m_clearColor{} +{ +} + +void RenderTexture::SetDevice(_In_ ID3D12Device* device, D3D12_CPU_DESCRIPTOR_HANDLE srvDescriptor, D3D12_CPU_DESCRIPTOR_HANDLE rtvDescriptor) +{ + if (device == m_device.Get() + && srvDescriptor.ptr == m_srvDescriptor.ptr + && rtvDescriptor.ptr == m_rtvDescriptor.ptr) + return; + + if (m_device) + { + ReleaseDevice(); + } + + { + D3D12_FEATURE_DATA_FORMAT_SUPPORT formatSupport = { m_format }; + if (FAILED(device->CheckFeatureSupport(D3D12_FEATURE_FORMAT_SUPPORT, &formatSupport, sizeof(formatSupport)))) + { + throw std::exception("CheckFeatureSupport"); + } + + UINT required = D3D12_FORMAT_SUPPORT1_TEXTURE2D | D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE | D3D12_FORMAT_SUPPORT1_RENDER_TARGET; + if ((formatSupport.Support1 & required) != required) + { +#ifdef _DEBUG + char buff[128] = {}; + sprintf_s(buff, "RenderTexture: Device does not support the requested format (%u)!\n", m_format); + OutputDebugStringA(buff); +#endif + throw std::exception("RenderTexture"); + } + } + + if (!srvDescriptor.ptr || !rtvDescriptor.ptr) + { + throw std::exception("Invalid descriptors"); + } + + m_device = device; + + m_srvDescriptor = srvDescriptor; + m_rtvDescriptor = rtvDescriptor; +} + +void RenderTexture::SizeResources(size_t width, size_t height) +{ + if (width == m_width && height == m_height) + return; + + if (m_width > UINT32_MAX || m_height > UINT32_MAX) + { + throw std::out_of_range("Invalid width/height"); + } + + if (!m_device) + return; + + m_width = m_height = 0; + + auto heapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT); + + D3D12_RESOURCE_DESC desc = CD3DX12_RESOURCE_DESC::Tex2D(m_format, + static_cast(width), + static_cast(height), + 1, 1, 1, 0, D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET); + + D3D12_CLEAR_VALUE clearValue = { m_format }; + memcpy(clearValue.Color, m_clearColor, sizeof(clearValue.Color)); + + m_state = D3D12_RESOURCE_STATE_RENDER_TARGET; + + // Create a render target + ThrowIfFailed( + m_device->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_ALLOW_ALL_BUFFERS_AND_TEXTURES, + &desc, + m_state, &clearValue, + IID_GRAPHICS_PPV_ARGS(m_resource.ReleaseAndGetAddressOf())) + ); + + SetDebugObjectName(m_resource.Get(), L"RenderTexture RT"); + + // Create RTV. + m_device->CreateRenderTargetView(m_resource.Get(), nullptr, m_rtvDescriptor); + + // Create SRV. + m_device->CreateShaderResourceView(m_resource.Get(), nullptr, m_srvDescriptor); + + m_width = width; + m_height = height; +} + +void RenderTexture::ReleaseDevice() +{ + m_resource.Reset(); + m_device.Reset(); + + m_state = D3D12_RESOURCE_STATE_COMMON; + m_width = m_height = 0; + + m_srvDescriptor.ptr = m_rtvDescriptor.ptr = 0; +} + +void RenderTexture::TransitionTo(_In_ ID3D12GraphicsCommandList* commandList, D3D12_RESOURCE_STATES afterState) +{ + TransitionResource(commandList, m_resource.Get(), m_state, afterState); + m_state = afterState; +} + +#else +//====================================================================================== +// Direct3D 11 +//====================================================================================== +RenderTexture::RenderTexture(DXGI_FORMAT format) : + m_format(format), + m_width(0), + m_height(0) +{ +} + +void RenderTexture::SetDevice(_In_ ID3D11Device* device) +{ + if (device == m_device.Get()) + return; + + if (m_device) + { + ReleaseDevice(); + } + + { + UINT formatSupport = 0; + if (FAILED(device->CheckFormatSupport(m_format, &formatSupport))) + { + throw std::exception("CheckFormatSupport"); + } + + UINT32 required = D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_SHADER_SAMPLE | D3D11_FORMAT_SUPPORT_RENDER_TARGET; + if ((formatSupport & required) != required) + { +#ifdef _DEBUG + char buff[128] = {}; + sprintf_s(buff, "RenderTexture: Device does not support the requested format (%u)!\n", m_format); + OutputDebugStringA(buff); +#endif + throw std::exception("RenderTexture"); + } + } + + m_device = device; + +#if defined(_XBOX_ONE) && defined(_TITLE) + m_fastSemantics = (device->GetCreationFlags() & D3D11_CREATE_DEVICE_IMMEDIATE_CONTEXT_FAST_SEMANTICS) != 0; +#endif +} + + +void RenderTexture::SizeResources(size_t width, size_t height) +{ + if (width == m_width && height == m_height) + return; + + if (m_width > UINT32_MAX || m_height > UINT32_MAX) + { + throw std::out_of_range("Invalid width/height"); + } + + if (!m_device) + return; + + m_width = m_height = 0; + + // Create a render target + CD3D11_TEXTURE2D_DESC renderTargetDesc( + m_format, + static_cast(width), + static_cast(height), + 1, // The render target view has only one texture. + 1, // Use a single mipmap level. + D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE, + D3D11_USAGE_DEFAULT, + 0, + 1 + ); + + ThrowIfFailed(m_device->CreateTexture2D( + &renderTargetDesc, + nullptr, + m_renderTarget.ReleaseAndGetAddressOf() + )); + + SetDebugObjectName(m_renderTarget.Get(), "RenderTexture RT"); + + // Create RTV. + CD3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc(D3D11_RTV_DIMENSION_TEXTURE2D, m_format); + + ThrowIfFailed(m_device->CreateRenderTargetView( + m_renderTarget.Get(), + &renderTargetViewDesc, + m_renderTargetView.ReleaseAndGetAddressOf() + )); + + SetDebugObjectName(m_renderTargetView.Get(), "RenderTexture RTV"); + + // Create SRV. + CD3D11_SHADER_RESOURCE_VIEW_DESC shaderResourceViewDesc(D3D11_SRV_DIMENSION_TEXTURE2D, m_format); + + ThrowIfFailed(m_device->CreateShaderResourceView( + m_renderTarget.Get(), + &shaderResourceViewDesc, + m_shaderResourceView.ReleaseAndGetAddressOf() + )); + + SetDebugObjectName(m_shaderResourceView.Get(), "RenderTexture SRV"); + + m_width = width; + m_height = height; +} + + +void RenderTexture::ReleaseDevice() +{ + m_renderTargetView.Reset(); + m_shaderResourceView.Reset(); + m_renderTarget.Reset(); + + m_device.Reset(); + + m_width = m_height = 0; +} + +#if defined(_XBOX_ONE) && defined(_TITLE) +void RenderTexture::EndScene(_In_ ID3D11DeviceContextX* context) +{ + if (m_fastSemantics) + { + context->FlushGpuCacheRange( + D3D11_FLUSH_ENSURE_CB0_COHERENCY + | D3D11_FLUSH_COLOR_BLOCK_INVALIDATE + | D3D11_FLUSH_TEXTURE_L1_INVALIDATE + | D3D11_FLUSH_TEXTURE_L2_INVALIDATE, + nullptr, D3D11_FLUSH_GPU_CACHE_RANGE_ALL); + context->DecompressResource(m_renderTarget.Get(), 0, nullptr, + m_renderTarget.Get(), 0, nullptr, + m_format, D3D11X_DECOMPRESS_PROPAGATE_COLOR_CLEAR); + } +} +#endif + +#endif + +void RenderTexture::SetWindow(const RECT& output) +{ + // Determine the render target size in pixels. + size_t width = std::max(output.right - output.left, 1); + size_t height = std::max(output.bottom - output.top, 1); + + SizeResources(width, height); +} + diff --git a/Kits/ATGTK/RenderTexture.h b/Kits/ATGTK/RenderTexture.h new file mode 100644 index 00000000..9e7391ae --- /dev/null +++ b/Kits/ATGTK/RenderTexture.h @@ -0,0 +1,102 @@ +//-------------------------------------------------------------------------------------- +// File: RenderTexture.h +// +// Helper for managing offscreen render targets +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------------------------------- + +#pragma once + +namespace DX +{ + class RenderTexture + { + public: + RenderTexture(DXGI_FORMAT format); + + RenderTexture(RenderTexture&&) = default; + RenderTexture& operator= (RenderTexture&&) = default; + + RenderTexture(RenderTexture const&) = delete; + RenderTexture& operator= (RenderTexture const&) = delete; + +#if defined(__d3d12_h__) || defined(__d3d12_x_h__) + + void SetDevice(_In_ ID3D12Device* device, D3D12_CPU_DESCRIPTOR_HANDLE srvDescriptor, D3D12_CPU_DESCRIPTOR_HANDLE rtvDescriptor); + + void SizeResources(size_t width, size_t height); + + void ReleaseDevice(); + + void TransitionTo(_In_ ID3D12GraphicsCommandList* commandList, D3D12_RESOURCE_STATES afterState); + + void BeginScene(_In_ ID3D12GraphicsCommandList* commandList) + { + TransitionTo(commandList, D3D12_RESOURCE_STATE_RENDER_TARGET); + } + + void EndScene(_In_ ID3D12GraphicsCommandList* commandList) + { + TransitionTo(commandList, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); + } + + void SetClearColor(DirectX::FXMVECTOR color) + { + DirectX::XMStoreFloat4(reinterpret_cast(m_clearColor), color); + } + + private: + Microsoft::WRL::ComPtr m_device; + Microsoft::WRL::ComPtr m_resource; + D3D12_RESOURCE_STATES m_state; + D3D12_CPU_DESCRIPTOR_HANDLE m_srvDescriptor; + D3D12_CPU_DESCRIPTOR_HANDLE m_rtvDescriptor; + float m_clearColor[4]; + +#elif defined(__d3d11_h__) || defined(__d3d11_x_h__) + + void SetDevice(_In_ ID3D11Device* device); + + void SizeResources(size_t width, size_t height); + + void ReleaseDevice(); + +#if defined(_XBOX_ONE) && defined(_TITLE) + void EndScene(_In_ ID3D11DeviceContextX* context); +#endif + + ID3D11Texture2D* GetRenderTarget() const { return m_renderTarget.Get(); } + ID3D11RenderTargetView* GetRenderTargetView() const { return m_renderTargetView.Get(); } + ID3D11ShaderResourceView* GetShaderResourceView() const { return m_shaderResourceView.Get(); } + + private: + Microsoft::WRL::ComPtr m_device; + Microsoft::WRL::ComPtr m_renderTarget; + Microsoft::WRL::ComPtr m_renderTargetView; + Microsoft::WRL::ComPtr m_shaderResourceView; +#if defined(_XBOX_ONE) && defined(_TITLE) + bool m_fastSemantics; +#endif + +#else +# error Please #include or +#endif + + public: + void SetWindow(const RECT& rect); + + DXGI_FORMAT GetFormat() const { return m_format; } + + private: + DXGI_FORMAT m_format; + + size_t m_width; + size_t m_height; + }; +} \ No newline at end of file diff --git a/Kits/ATGTK/Skybox/Skybox.h b/Kits/ATGTK/Skybox/Skybox.h index a1bf08aa..5efd5104 100644 --- a/Kits/ATGTK/Skybox/Skybox.h +++ b/Kits/ATGTK/Skybox/Skybox.h @@ -1,7 +1,7 @@ //-------------------------------------------------------------------------------------- // Skybox.h // -// A sky box rendering helper. Takes DDS cubemap as input. +// A sky box rendering helper for DirectX 12. Takes DDS cubemap as input. // // Advanced Technology Group (ATG) // Copyright (C) Microsoft Corporation. All rights reserved. @@ -36,8 +36,8 @@ namespace ATG m_effect = std::make_unique(device, skyPSD); m_effect->SetTexture(cubeTexture, commonStates.LinearWrap()); - // Create cube with corners at ([-1, 1], [-1, 1], [-1, 1]) - m_cube = DirectX::GeometricPrimitive::CreateGeoSphere(2.f); + // "Skybox" geometry + m_sky = DirectX::GeometricPrimitive::CreateGeoSphere(2.f); } void XM_CALLCONV Update(DirectX::FXMMATRIX view, DirectX::CXMMATRIX projection) @@ -48,11 +48,11 @@ namespace ATG void Render(ID3D12GraphicsCommandList* cmdList) { m_effect->Apply(cmdList); - m_cube->Draw(cmdList); + m_sky->Draw(cmdList); } private: - std::unique_ptr m_cube; + std::unique_ptr m_sky; std::unique_ptr m_effect; }; } \ No newline at end of file diff --git a/Kits/ATGTK/Skybox/SkyboxEffect.cpp b/Kits/ATGTK/Skybox/SkyboxEffect.cpp index 0b03b274..2cb8aa57 100644 --- a/Kits/ATGTK/Skybox/SkyboxEffect.cpp +++ b/Kits/ATGTK/Skybox/SkyboxEffect.cpp @@ -1,7 +1,7 @@ //-------------------------------------------------------------------------------------- -// ToneMapEffect.cpp +// SkyboxEffect.cpp // -// A simple flimic tonemapping effect for DirectX 12. +// A sky box rendering helper for DirectX 12. // // Advanced Technology Group (ATG) // Copyright (C) Microsoft Corporation. All rights reserved. @@ -87,7 +87,7 @@ const int EffectBase::PixelShaderIndices[] = 0, // basic }; -// Global pool of per-device ToneMapEffect resources. +// Global pool of per-device SkyboxEffect resources. SharedResourcePool::DeviceResources> EffectBase::deviceResourcesPool; diff --git a/Kits/ATGTK/Skybox/SkyboxEffect.h b/Kits/ATGTK/Skybox/SkyboxEffect.h index 4128296b..8dc05919 100644 --- a/Kits/ATGTK/Skybox/SkyboxEffect.h +++ b/Kits/ATGTK/Skybox/SkyboxEffect.h @@ -1,7 +1,7 @@ //-------------------------------------------------------------------------------------- -// ToneMapEffect.h +// SkyboxEffect.h // -// A simple flimic tonemapping effect for DirectX 12. +// A sky box rendering helper for DirectX 12. // // Advanced Technology Group (ATG) // Copyright (C) Microsoft Corporation. All rights reserved. diff --git a/Kits/ATGTK/Skybox/SkyboxEffect_Common.hlsli b/Kits/ATGTK/Skybox/SkyboxEffect_Common.hlsli index 6ffeb6c8..8e8dd866 100644 --- a/Kits/ATGTK/Skybox/SkyboxEffect_Common.hlsli +++ b/Kits/ATGTK/Skybox/SkyboxEffect_Common.hlsli @@ -1,7 +1,7 @@ //-------------------------------------------------------------------------------------- // SkyboxEffect_Common.hlsli // -// A simple flimic tonemapping effect for DirectX 12. +// A sky box rendering helper for DirectX 12. // // Advanced Technology Group (ATG) // Copyright (C) Microsoft Corporation. All rights reserved. diff --git a/Kits/ATGTK/Skybox/SkyboxEffect_PS.hlsl b/Kits/ATGTK/Skybox/SkyboxEffect_PS.hlsl index 310032e2..f6787c16 100644 --- a/Kits/ATGTK/Skybox/SkyboxEffect_PS.hlsl +++ b/Kits/ATGTK/Skybox/SkyboxEffect_PS.hlsl @@ -1,7 +1,7 @@ //-------------------------------------------------------------------------------------- // SkyboxEffect_PS.hlsl // -// A simple flimic tonemapping effect for DirectX 12. +// A sky box rendering helper for DirectX 12. // // Advanced Technology Group (ATG) // Copyright (C) Microsoft Corporation. All rights reserved. diff --git a/Kits/ATGTK/Skybox/SkyboxEffect_VS.hlsl b/Kits/ATGTK/Skybox/SkyboxEffect_VS.hlsl index f05f71af..a8e9de5f 100644 --- a/Kits/ATGTK/Skybox/SkyboxEffect_VS.hlsl +++ b/Kits/ATGTK/Skybox/SkyboxEffect_VS.hlsl @@ -1,7 +1,7 @@ //-------------------------------------------------------------------------------------- // SkyboxEffect_VS.hlsl // -// A simple flimic tonemapping effect for DirectX 12. +// A sky box rendering helper for DirectX 12. // // Advanced Technology Group (ATG) // Copyright (C) Microsoft Corporation. All rights reserved. diff --git a/Kits/ATGTK/TextConsole.h b/Kits/ATGTK/TextConsole.h index d5c0b49f..6be66432 100644 --- a/Kits/ATGTK/TextConsole.h +++ b/Kits/ATGTK/TextConsole.h @@ -31,6 +31,12 @@ namespace DX TextConsole(); TextConsole(ID3D11DeviceContext* context, const wchar_t* fontName); + TextConsole(TextConsole&&) = default; + TextConsole& operator= (TextConsole&&) = default; + + TextConsole(TextConsole const&) = delete; + TextConsole& operator= (TextConsole const&) = delete; + void Render(); void Clear(); @@ -83,6 +89,13 @@ namespace DX TextConsoleImage(); TextConsoleImage(ID3D11DeviceContext* context, const wchar_t* fontName, const wchar_t* image); + TextConsoleImage(TextConsoleImage&&) = default; + TextConsoleImage& operator= (TextConsoleImage&&) = default; + + TextConsoleImage(TextConsoleImage const&) = delete; + TextConsoleImage& operator= (TextConsoleImage const&) = delete; + + void Render(); void SetWindow(const RECT& layout) = delete; diff --git a/Kits/ATGTK/ToneMapEffect/ToneMapEffect.cpp b/Kits/ATGTK/ToneMapEffect/ToneMapEffect.cpp deleted file mode 100644 index a4e7eeed..00000000 --- a/Kits/ATGTK/ToneMapEffect/ToneMapEffect.cpp +++ /dev/null @@ -1,204 +0,0 @@ -//-------------------------------------------------------------------------------------- -// ToneMapEffect.cpp -// -// A simple flimic tonemapping effect for DirectX 12. -// -// Advanced Technology Group (ATG) -// Copyright (C) Microsoft Corporation. All rights reserved. -//-------------------------------------------------------------------------------------- - -#include "pch.h" -#include "ToneMapEffect.h" - -#include <..\Src\EffectCommon.h> - -using namespace DirectX; -using namespace ATG; - -// Include the precompiled shader code. -namespace -{ -#if defined(_XBOX_ONE) && defined(_TITLE) -#include "Compiled/XboxOneToneMapEffect_VS.inc" -#include "Compiled/XboxOneToneMapEffect_PS.inc" -#else -#include "Compiled/ToneMapEffect_VS.inc" -#include "Compiled/ToneMapEffect_PS.inc" -#endif -} - -struct __declspec(align(16)) ToneMapEffectConstants -{ -// no constants - XMVECTOR _dummy; -}; - -// Traits type describes our characteristics to the EffectBase template. -struct ToneMapEffectTraits -{ - typedef ToneMapEffectConstants ConstantBufferType; - - static const int VertexShaderCount = 1; - static const int PixelShaderCount = 1; - static const int ShaderPermutationCount = 1; - static const int RootSignatureCount = 1; -}; - - -class ATG::ToneMapEffect::Impl : public EffectBase -{ -public: - - Impl(_In_ ID3D12Device* device, DXGI_FORMAT outputTargetFormat); - void Apply(_In_ ID3D12GraphicsCommandList* commandList); - - int GetPipelineStatePermutation() const; - - enum Descriptors - { - InputSRV, - InputSampler, - DescriptorsCount - }; - - D3D12_GPU_DESCRIPTOR_HANDLE descriptors[DescriptorsCount]; -}; - -const D3D12_SHADER_BYTECODE EffectBase::VertexShaderBytecode[] = -{ - { ToneMapEffect_VS, sizeof(ToneMapEffect_VS) }, -}; - - -const int EffectBase::VertexShaderIndices[] = -{ - 0, // basic -}; - - -const D3D12_SHADER_BYTECODE EffectBase::PixelShaderBytecode[] = -{ - { ToneMapEffect_PS, sizeof(ToneMapEffect_PS) }, -}; - - -const int EffectBase::PixelShaderIndices[] = -{ - 0, // basic -}; - -// Global pool of per-device ToneMapEffect resources. -SharedResourcePool::DeviceResources> EffectBase::deviceResourcesPool; - - -ToneMapEffect::Impl::Impl(_In_ ID3D12Device* device, DXGI_FORMAT outputTargetFormat) - : EffectBase(device), - descriptors{} -{ - static_assert(_countof(EffectBase::VertexShaderIndices) == ToneMapEffectTraits::ShaderPermutationCount, "array/max mismatch"); - static_assert(_countof(EffectBase::VertexShaderBytecode) == ToneMapEffectTraits::VertexShaderCount, "array/max mismatch"); - static_assert(_countof(EffectBase::PixelShaderBytecode) == ToneMapEffectTraits::PixelShaderCount, "array/max mismatch"); - static_assert(_countof(EffectBase::PixelShaderIndices) == ToneMapEffectTraits::ShaderPermutationCount, "array/max mismatch"); - - // Create root signature - D3D12_ROOT_SIGNATURE_FLAGS rootSignatureFlags = - D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT | // Only the input assembler stage needs access to the constant buffer. - D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS | - D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS | - D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS; - - CD3DX12_DESCRIPTOR_RANGE textureSRVs(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 0); - CD3DX12_DESCRIPTOR_RANGE textureSamplers(D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, 1, 0); - - CD3DX12_ROOT_PARAMETER rootParameters[2]; - rootParameters[0].InitAsDescriptorTable(1, &textureSRVs); - rootParameters[1].InitAsDescriptorTable(1, &textureSamplers); - - CD3DX12_ROOT_SIGNATURE_DESC rsigDesc; - rsigDesc.Init(_countof(rootParameters), rootParameters, 0, nullptr, rootSignatureFlags); - - // Create the root signature - mRootSignature = GetRootSignature(0, rsigDesc); - - // Get shaders - int sp = GetPipelineStatePermutation(); - int vi = EffectBase::VertexShaderIndices[sp]; - int pi = EffectBase::PixelShaderIndices[sp]; - - // Create pipeline state - RenderTargetState rtState(outputTargetFormat, DXGI_FORMAT_UNKNOWN); // no DSV - - EffectPipelineStateDescription tonemapPSD(&VertexType::InputLayout, - CommonStates::Opaque, - CommonStates::DepthNone, - CommonStates::CullNone, - rtState, - D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE); - - tonemapPSD.CreatePipelineState( - device, - mRootSignature, - EffectBase::VertexShaderBytecode[vi], - EffectBase::PixelShaderBytecode[pi], - mPipelineState.ReleaseAndGetAddressOf()); -} - -int ToneMapEffect::Impl::GetPipelineStatePermutation() const -{ - return 0; -} - - -// Sets our state onto the D3D device. -void ToneMapEffect::Impl::Apply(_In_ ID3D12GraphicsCommandList* commandList) -{ - // Set the root signature - commandList->SetGraphicsRootSignature(mRootSignature); - - // Set the root parameters - // TODO don't assume these are contiguous - commandList->SetGraphicsRootDescriptorTable(0, descriptors[InputSRV]); - commandList->SetGraphicsRootDescriptorTable(1, descriptors[InputSampler]); - - // Set the pipeline state - commandList->SetPipelineState(EffectBase::mPipelineState.Get()); -} - -// Public constructor. -ToneMapEffect::ToneMapEffect(_In_ ID3D12Device* device, DXGI_FORMAT outputTargetFormat) - : pImpl(new Impl(device, outputTargetFormat)) -{ -} - -// Move constructor. -ToneMapEffect::ToneMapEffect(ToneMapEffect&& moveFrom) - : pImpl(std::move(moveFrom.pImpl)) -{ -} - - -// Move assignment. -ToneMapEffect& ToneMapEffect::operator= (ToneMapEffect&& moveFrom) -{ - pImpl = std::move(moveFrom.pImpl); - return *this; -} - - -// Public destructor. -ToneMapEffect::~ToneMapEffect() -{ -} - -// IEffect methods. -void ToneMapEffect::Apply(_In_ ID3D12GraphicsCommandList* commandList) -{ - pImpl->Apply(commandList); -} - -// Texture settings. -void ToneMapEffect::SetTexture(_In_ D3D12_GPU_DESCRIPTOR_HANDLE srvDescriptor, _In_ D3D12_GPU_DESCRIPTOR_HANDLE samplerDescriptor) -{ - pImpl->descriptors[Impl::InputSRV] = srvDescriptor; - pImpl->descriptors[Impl::InputSampler] = samplerDescriptor; -} \ No newline at end of file diff --git a/Kits/ATGTK/ToneMapEffect/ToneMapEffect.h b/Kits/ATGTK/ToneMapEffect/ToneMapEffect.h deleted file mode 100644 index ba43cce9..00000000 --- a/Kits/ATGTK/ToneMapEffect/ToneMapEffect.h +++ /dev/null @@ -1,40 +0,0 @@ -//-------------------------------------------------------------------------------------- -// ToneMapEffect.h -// -// A simple flimic tonemapping effect for DirectX 12. -// -// Advanced Technology Group (ATG) -// Copyright (C) Microsoft Corporation. All rights reserved. -//-------------------------------------------------------------------------------------- - -#pragma once - -#include - -namespace ATG -{ - class ToneMapEffect : public DirectX::IEffect - { - public: - // Use this to render tonemap quad (defined here so PSO can use it). - using VertexType = DirectX::VertexPositionTexture; - - explicit ToneMapEffect(_In_ ID3D12Device* device, DXGI_FORMAT outputBufferFormat); - ToneMapEffect(ToneMapEffect&& moveFrom); - ToneMapEffect& operator= (ToneMapEffect&& moveFrom); - - ToneMapEffect(ToneMapEffect const&) = delete; - ToneMapEffect& operator= (ToneMapEffect const&) = delete; - - virtual ~ToneMapEffect(); - - void SetTexture(_In_ D3D12_GPU_DESCRIPTOR_HANDLE srvDescriptor, _In_ D3D12_GPU_DESCRIPTOR_HANDLE samplerDescriptor); - - void __cdecl Apply(_In_ ID3D12GraphicsCommandList* commandList) override; - private: - // Private implementation. - class Impl; - - std::unique_ptr pImpl; - }; -} \ No newline at end of file diff --git a/Kits/ATGTK/ToneMapEffect/ToneMapEffect_Common.hlsli b/Kits/ATGTK/ToneMapEffect/ToneMapEffect_Common.hlsli deleted file mode 100644 index 2ea9dff4..00000000 --- a/Kits/ATGTK/ToneMapEffect/ToneMapEffect_Common.hlsli +++ /dev/null @@ -1,21 +0,0 @@ -//-------------------------------------------------------------------------------------- -// ToneMapEffect_Common.hlsli -// -// A simple flimic tonemapping effect for DirectX 12. -// -// Advanced Technology Group (ATG) -// Copyright (C) Microsoft Corporation. All rights reserved. -//-------------------------------------------------------------------------------------- - -#ifndef __TONEMAPEFFECT_COMMON_HLSLI__ -#define __TONEMAPEFFECT_COMMON_HLSLI__ - -#define ToneMapRS \ -"RootFlags ( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |" \ -" DENY_DOMAIN_SHADER_ROOT_ACCESS |" \ -" DENY_GEOMETRY_SHADER_ROOT_ACCESS |" \ -" DENY_HULL_SHADER_ROOT_ACCESS )," \ -"DescriptorTable ( SRV(t0) ),"\ -"DescriptorTable ( Sampler(s0) )" - -#endif \ No newline at end of file diff --git a/Kits/ATGTK/ToneMapEffect/ToneMapEffect_PS.hlsl b/Kits/ATGTK/ToneMapEffect/ToneMapEffect_PS.hlsl deleted file mode 100644 index 1b86f53e..00000000 --- a/Kits/ATGTK/ToneMapEffect/ToneMapEffect_PS.hlsl +++ /dev/null @@ -1,35 +0,0 @@ -//-------------------------------------------------------------------------------------- -// ToneMapEffect_PS.hlsl -// -// A simple flimic tonemapping effect for DirectX 12. -// -// Advanced Technology Group (ATG) -// Copyright (C) Microsoft Corporation. All rights reserved. -//-------------------------------------------------------------------------------------- - -#include "ToneMapEffect_Common.hlsli" - -Texture2D HDRTexture : register(t0); -SamplerState PointSampler : register(s0); // Point sample the HDR scene - -// HDR to SDR tone mapping using a simple Reinhard operator -float3 TonemapReinhard(float3 HDRSceneValue) -{ - return HDRSceneValue / (1.0f + HDRSceneValue); -} - -// HDR to SDR tone mapping using a simple Filmic operator -float3 TonemapFilmic(float3 HDRSceneValue) -{ - float3 x = max(0.0f, HDRSceneValue - 0.004f); - return pow((x * (6.2f * x + 0.5f)) / (x * (6.2f * x + 1.7f) + 0.06f), 2.2f); -} - -[RootSignature(ToneMapRS)] -float4 main(float2 texCoord : TEXCOORD0) : SV_TARGET0 -{ - float4 hdr = HDRTexture.Sample(PointSampler, texCoord); - float4 sdr = float4(TonemapReinhard(hdr.xyz),1); - - return sdr; -} \ No newline at end of file diff --git a/Kits/ATGTK/ToneMapEffect/ToneMapEffect_VS.hlsl b/Kits/ATGTK/ToneMapEffect/ToneMapEffect_VS.hlsl deleted file mode 100644 index acf63da3..00000000 --- a/Kits/ATGTK/ToneMapEffect/ToneMapEffect_VS.hlsl +++ /dev/null @@ -1,16 +0,0 @@ -//-------------------------------------------------------------------------------------- -// ToneMapEffect_VS.hlsl -// -// A simple flimic tonemapping effect for DirectX 12. -// -// Advanced Technology Group (ATG) -// Copyright (C) Microsoft Corporation. All rights reserved. -//-------------------------------------------------------------------------------------- - -#include "ToneMapEffect_Common.hlsli" - -[RootSignature(ToneMapRS)] -void main(inout float2 texCoord : TEXCOORD0, - inout float4 position : SV_Position) -{ -} \ No newline at end of file diff --git a/Media/Fonts/XboxOneControllerLegend.spritefont b/Media/Fonts/XboxOneControllerLegend.spritefont new file mode 100644 index 00000000..d4207854 Binary files /dev/null and b/Media/Fonts/XboxOneControllerLegend.spritefont differ diff --git a/Media/Meshes/AliasSampleCityBlock/CityBlockConcrete.sdkmesh b/Media/Meshes/AliasSampleCityBlock/CityBlockConcrete.sdkmesh new file mode 100644 index 00000000..47081433 Binary files /dev/null and b/Media/Meshes/AliasSampleCityBlock/CityBlockConcrete.sdkmesh differ diff --git a/Media/Meshes/AliasSampleCityBlock/Concrete.dds b/Media/Meshes/AliasSampleCityBlock/Concrete.dds new file mode 100644 index 00000000..1a777704 Binary files /dev/null and b/Media/Meshes/AliasSampleCityBlock/Concrete.dds differ diff --git a/Media/Meshes/AliasSampleCityBlock/Lightmap.dds b/Media/Meshes/AliasSampleCityBlock/Lightmap.dds new file mode 100644 index 00000000..a4f4ffa8 Binary files /dev/null and b/Media/Meshes/AliasSampleCityBlock/Lightmap.dds differ diff --git a/Samples/Graphics/SimplePBR12/Assets/Models/ToyRobot/Floor/Floor.sdkmesh b/Media/PBR/ToyRobot/Floor/Floor.sdkmesh similarity index 100% rename from Samples/Graphics/SimplePBR12/Assets/Models/ToyRobot/Floor/Floor.sdkmesh rename to Media/PBR/ToyRobot/Floor/Floor.sdkmesh diff --git a/Samples/Graphics/SimplePBR12/Assets/Models/ToyRobot/Floor/Floor_BaseColor.dds b/Media/PBR/ToyRobot/Floor/Floor_BaseColor.dds similarity index 100% rename from Samples/Graphics/SimplePBR12/Assets/Models/ToyRobot/Floor/Floor_BaseColor.dds rename to Media/PBR/ToyRobot/Floor/Floor_BaseColor.dds diff --git a/Samples/Graphics/SimplePBR12/Assets/Models/ToyRobot/Floor/Floor_Normal.DDS b/Media/PBR/ToyRobot/Floor/Floor_Normal.DDS similarity index 100% rename from Samples/Graphics/SimplePBR12/Assets/Models/ToyRobot/Floor/Floor_Normal.DDS rename to Media/PBR/ToyRobot/Floor/Floor_Normal.DDS diff --git a/Samples/Graphics/SimplePBR12/Assets/Models/ToyRobot/Floor/Floor_RMA.DDS b/Media/PBR/ToyRobot/Floor/Floor_RMA.DDS similarity index 100% rename from Samples/Graphics/SimplePBR12/Assets/Models/ToyRobot/Floor/Floor_RMA.DDS rename to Media/PBR/ToyRobot/Floor/Floor_RMA.DDS diff --git a/Samples/Graphics/SimplePBR12/Assets/Models/ToyRobot/ToyRobot/ToyRobot.sdkmesh b/Media/PBR/ToyRobot/ToyRobot/ToyRobot.sdkmesh similarity index 100% rename from Samples/Graphics/SimplePBR12/Assets/Models/ToyRobot/ToyRobot/ToyRobot.sdkmesh rename to Media/PBR/ToyRobot/ToyRobot/ToyRobot.sdkmesh diff --git a/Samples/Graphics/SimplePBR12/Assets/Models/ToyRobot/ToyRobot/ToyRobot_BaseColor.dds b/Media/PBR/ToyRobot/ToyRobot/ToyRobot_BaseColor.dds similarity index 100% rename from Samples/Graphics/SimplePBR12/Assets/Models/ToyRobot/ToyRobot/ToyRobot_BaseColor.dds rename to Media/PBR/ToyRobot/ToyRobot/ToyRobot_BaseColor.dds diff --git a/Samples/Graphics/SimplePBR12/Assets/Models/ToyRobot/ToyRobot/Toyrobot_Normal.DDS b/Media/PBR/ToyRobot/ToyRobot/Toyrobot_Normal.DDS similarity index 100% rename from Samples/Graphics/SimplePBR12/Assets/Models/ToyRobot/ToyRobot/Toyrobot_Normal.DDS rename to Media/PBR/ToyRobot/ToyRobot/Toyrobot_Normal.DDS diff --git a/Samples/Graphics/SimplePBR12/Assets/Models/ToyRobot/ToyRobot/Toyrobot_RMA.DDS b/Media/PBR/ToyRobot/ToyRobot/Toyrobot_RMA.DDS similarity index 100% rename from Samples/Graphics/SimplePBR12/Assets/Models/ToyRobot/ToyRobot/Toyrobot_RMA.DDS rename to Media/PBR/ToyRobot/ToyRobot/Toyrobot_RMA.DDS diff --git a/Samples/Graphics/SimplePBR12/Assets/Models/ToyRobot/WoodBlocks/WoodBlocks.sdkmesh b/Media/PBR/ToyRobot/WoodBlocks/WoodBlocks.sdkmesh similarity index 100% rename from Samples/Graphics/SimplePBR12/Assets/Models/ToyRobot/WoodBlocks/WoodBlocks.sdkmesh rename to Media/PBR/ToyRobot/WoodBlocks/WoodBlocks.sdkmesh diff --git a/Samples/Graphics/SimplePBR12/Assets/Models/ToyRobot/WoodBlocks/WoodBlocks_BaseColor.dds b/Media/PBR/ToyRobot/WoodBlocks/WoodBlocks_BaseColor.dds similarity index 100% rename from Samples/Graphics/SimplePBR12/Assets/Models/ToyRobot/WoodBlocks/WoodBlocks_BaseColor.dds rename to Media/PBR/ToyRobot/WoodBlocks/WoodBlocks_BaseColor.dds diff --git a/Samples/Graphics/SimplePBR12/Assets/Models/ToyRobot/WoodBlocks/WoodBlocks_Normal.DDS b/Media/PBR/ToyRobot/WoodBlocks/WoodBlocks_Normal.DDS similarity index 100% rename from Samples/Graphics/SimplePBR12/Assets/Models/ToyRobot/WoodBlocks/WoodBlocks_Normal.DDS rename to Media/PBR/ToyRobot/WoodBlocks/WoodBlocks_Normal.DDS diff --git a/Samples/Graphics/SimplePBR12/Assets/Models/ToyRobot/WoodBlocks/WoodBlocks_RMA.DDS b/Media/PBR/ToyRobot/WoodBlocks/WoodBlocks_RMA.DDS similarity index 100% rename from Samples/Graphics/SimplePBR12/Assets/Models/ToyRobot/WoodBlocks/WoodBlocks_RMA.DDS rename to Media/PBR/ToyRobot/WoodBlocks/WoodBlocks_RMA.DDS diff --git a/Samples/Graphics/SimplePBR12/Assets/Models/XboxOrb/XboxOrb.sdkmesh b/Media/PBR/XboxOrb/XboxOrb.sdkmesh similarity index 100% rename from Samples/Graphics/SimplePBR12/Assets/Models/XboxOrb/XboxOrb.sdkmesh rename to Media/PBR/XboxOrb/XboxOrb.sdkmesh diff --git a/Samples/Audio/SimplePlay3DSoundUWP/Readme.docx b/Samples/Audio/SimplePlay3DSoundUWP/Readme.docx index b8c828c7..b7b94a0f 100644 Binary files a/Samples/Audio/SimplePlay3DSoundUWP/Readme.docx and b/Samples/Audio/SimplePlay3DSoundUWP/Readme.docx differ diff --git a/Samples/Audio/SimplePlay3DSoundUWP/SimplePlay3DSound.vcxproj b/Samples/Audio/SimplePlay3DSoundUWP/SimplePlay3DSound.vcxproj index b0529cd0..fbfec737 100644 --- a/Samples/Audio/SimplePlay3DSoundUWP/SimplePlay3DSound.vcxproj +++ b/Samples/Audio/SimplePlay3DSoundUWP/SimplePlay3DSound.vcxproj @@ -98,7 +98,7 @@ false - false + false diff --git a/Samples/Audio/SimplePlaySoundUWP/Readme.docx b/Samples/Audio/SimplePlaySoundUWP/Readme.docx index 08c44eb8..22b2673e 100644 Binary files a/Samples/Audio/SimplePlaySoundUWP/Readme.docx and b/Samples/Audio/SimplePlaySoundUWP/Readme.docx differ diff --git a/Samples/Audio/SimplePlaySoundUWP/SimplePlaySound.vcxproj b/Samples/Audio/SimplePlaySoundUWP/SimplePlaySound.vcxproj index e4170a31..734210de 100644 --- a/Samples/Audio/SimplePlaySoundUWP/SimplePlaySound.vcxproj +++ b/Samples/Audio/SimplePlaySoundUWP/SimplePlaySound.vcxproj @@ -98,7 +98,7 @@ false - false + false diff --git a/Samples/Audio/SimpleWASAPICaptureUWP/Readme.docx b/Samples/Audio/SimpleWASAPICaptureUWP/Readme.docx index a1c33919..0ad6d2e2 100644 Binary files a/Samples/Audio/SimpleWASAPICaptureUWP/Readme.docx and b/Samples/Audio/SimpleWASAPICaptureUWP/Readme.docx differ diff --git a/Samples/Audio/SimpleWASAPICaptureUWP/SimpleWASAPICaptureUWP.vcxproj b/Samples/Audio/SimpleWASAPICaptureUWP/SimpleWASAPICaptureUWP.vcxproj index c5dfc235..b7dcb55a 100644 --- a/Samples/Audio/SimpleWASAPICaptureUWP/SimpleWASAPICaptureUWP.vcxproj +++ b/Samples/Audio/SimpleWASAPICaptureUWP/SimpleWASAPICaptureUWP.vcxproj @@ -98,7 +98,7 @@ false - false + false diff --git a/Samples/Audio/SimpleWASAPIPlaySoundUWP/Readme.docx b/Samples/Audio/SimpleWASAPIPlaySoundUWP/Readme.docx index f306d724..edfdb399 100644 Binary files a/Samples/Audio/SimpleWASAPIPlaySoundUWP/Readme.docx and b/Samples/Audio/SimpleWASAPIPlaySoundUWP/Readme.docx differ diff --git a/Samples/Audio/SimpleWASAPIPlaySoundUWP/SimpleWASAPIPlaySound.vcxproj b/Samples/Audio/SimpleWASAPIPlaySoundUWP/SimpleWASAPIPlaySound.vcxproj index f1a3830d..a26b3b47 100644 --- a/Samples/Audio/SimpleWASAPIPlaySoundUWP/SimpleWASAPIPlaySound.vcxproj +++ b/Samples/Audio/SimpleWASAPIPlaySoundUWP/SimpleWASAPIPlaySound.vcxproj @@ -98,7 +98,7 @@ false - false + false diff --git a/Samples/Graphics/SimplePBR12/Readme.docx b/Samples/Graphics/SimplePBR12/Readme.docx index dd9d885e..b4005e42 100644 Binary files a/Samples/Graphics/SimplePBR12/Readme.docx and b/Samples/Graphics/SimplePBR12/Readme.docx differ diff --git a/Samples/Graphics/SimplePBR12/Shared/DescriptorPile.h b/Samples/Graphics/SimplePBR12/Shared/DescriptorPile.h deleted file mode 100644 index ce9431d9..00000000 --- a/Samples/Graphics/SimplePBR12/Shared/DescriptorPile.h +++ /dev/null @@ -1,82 +0,0 @@ -//-------------------------------------------------------------------------------------- -// DescriptorPile.h -// -// A wrapper to help sharing a descriptor heap. This class removes the need for a -// global enumeration of all SRVs used in a sample. The pile is statically sized and will -// throw an exception if it becomes full. -// -// Advanced Technology Group (ATG) -// Copyright (C) Microsoft Corporation. All rights reserved. -//-------------------------------------------------------------------------------------- - -#pragma once -#include -#include - -namespace ATG -{ - class DescriptorPile - { - public: - using IndexType = size_t; - static const IndexType INVALID_INDEX = size_t(-1); - - DescriptorPile( - _In_ ID3D12Device* device, - _In_ D3D12_DESCRIPTOR_HEAP_TYPE type, - _In_ D3D12_DESCRIPTOR_HEAP_FLAGS flags, - size_t initialSize) - : m_top(0) - { - m_heap = std::make_unique(device, type, flags, initialSize); - } - - // Return the start of a batch of descriptors, throws exception if no room - IndexType Allocate() - { - IndexType start, end; - AllocateRange(1, start, end); - - return start; - } - - // Return the start of a batch of descriptors, throws exception if no room - void AllocateRange(size_t numDescriptors, _Out_ IndexType& start, _Out_ IndexType& end) - { - // make sure we didn't allocate zero - if (numDescriptors == 0) - { - throw std::out_of_range("Can't allocate zero slots on DescriptorPile"); - } - - // get the current top - start = m_top; - - // increment top with new request - m_top += numDescriptors; - end = m_top; - - // make sure we have enough room - if (m_top >= m_heap->Count()) - { - throw std::out_of_range("DescriptorPile can't allocate more descriptors"); - } - } - - D3D12_GPU_DESCRIPTOR_HANDLE GetGpuHandle(_In_ size_t index) const - { - return m_heap->GetGpuHandle(index); - } - - D3D12_CPU_DESCRIPTOR_HANDLE GetCpuHandle(_In_ size_t index) const - { - return m_heap->GetCpuHandle(index); - } - - ID3D12DescriptorHeap* Heap() const { return m_heap->Heap(); } - - private: - std::unique_ptr m_heap; - IndexType m_top; - }; -} \ No newline at end of file diff --git a/Samples/Graphics/SimplePBR12/Shared/PBRModel.h b/Samples/Graphics/SimplePBR12/Shared/PBRModel.h index b0d4deee..fe5d3ed1 100644 --- a/Samples/Graphics/SimplePBR12/Shared/PBRModel.h +++ b/Samples/Graphics/SimplePBR12/Shared/PBRModel.h @@ -17,7 +17,6 @@ #pragma once #include -#include "DescriptorPile.h" #include "PBREffect\PBREffect.h" namespace ATG @@ -30,18 +29,21 @@ namespace ATG { // Remove extension and path auto lastSlash = m_modelFullPath.find_last_of(L"\\"); - m_modelBasePath = m_modelFullPath.substr(0, lastSlash); + if (lastSlash != size_t(-1)) + m_modelBasePath = m_modelFullPath.substr(0, lastSlash); + else + m_modelBasePath = L"."; auto lastDot = m_modelFullPath.find_last_of(L"."); m_modelName = m_modelFullPath.substr( lastSlash + 1, lastDot - lastSlash - 1); } void Create( - ID3D12Device* device, + _In_ ID3D12Device* device, const DirectX::RenderTargetState& rtState, const DirectX::CommonStates* commonStates, DirectX::ResourceUploadBatch& resourceUpload, - ATG::DescriptorPile* pile) + _In_ DirectX::DescriptorPile* pile) { using namespace DirectX; using namespace DirectX::SimpleMath; diff --git a/Samples/Graphics/SimplePBR12/Shared/SharedSimplePBR.cpp b/Samples/Graphics/SimplePBR12/Shared/SharedSimplePBR.cpp index 161fc4fd..8d0c1030 100644 --- a/Samples/Graphics/SimplePBR12/Shared/SharedSimplePBR.cpp +++ b/Samples/Graphics/SimplePBR12/Shared/SharedSimplePBR.cpp @@ -15,6 +15,8 @@ #include "DDSTextureLoader.h" #include "GeometricPrimitive.h" +//#define TEST_SCENE + #if defined(_XBOX_ONE) && defined(_TITLE) #include "../Xbox/SimplePBRXbox12.h" // get sample definition #else @@ -31,9 +33,9 @@ namespace // PBR Assest paths. const wchar_t* s_modelPaths[] = { - L"Assets\\Models\\ToyRobot\\Floor\\Floor.sdkmesh", - L"Assets\\Models\\ToyRobot\\ToyRobot\\ToyRobot.sdkmesh", - L"Assets\\Models\\ToyRobot\\WoodBlocks\\WoodBlocks.sdkmesh" + L"Floor.sdkmesh", + L"ToyRobot.sdkmesh", + L"WoodBlocks.sdkmesh" }; // A simple test scene for material parameters @@ -70,7 +72,7 @@ namespace sampler); // Model - m_model = Model::CreateFromSDKMESH(L"Assets\\Models\\XboxOrb\\XboxOrb.sdkmesh"); + m_model = Model::CreateFromSDKMESH(L"XboxOrb.sdkmesh"); } void XM_CALLCONV Render(ID3D12GraphicsCommandList* commandList, FXMMATRIX camView, CXMMATRIX camProj) @@ -123,10 +125,11 @@ namespace SharedSimplePBR::SharedSimplePBR(Sample* sample) : m_sample(sample), - m_radTexDescIndex(ATG::DescriptorPile::INVALID_INDEX), - m_HDRBufferDescIndex(ATG::DescriptorPile::INVALID_INDEX) + m_gamepadConnected(false) { m_gamePad = std::make_unique(); + + m_hdrScene = std::make_unique(Sample::GetHDRRenderFormat()); } void SharedSimplePBR::Update(DX::StepTimer const& timer) @@ -137,6 +140,8 @@ void SharedSimplePBR::Update(DX::StepTimer const& timer) auto pad = m_gamePad->GetState(0); if (pad.IsConnected()) { + m_gamepadConnected = true; + m_gamePadButtons.Update(pad); if (pad.IsViewPressed()) @@ -146,6 +151,8 @@ void SharedSimplePBR::Update(DX::StepTimer const& timer) } else { + m_gamepadConnected = false; + m_gamePadButtons.Reset(); } m_camera->Update(elapsedSeconds, pad); @@ -183,6 +190,8 @@ void SharedSimplePBR::Render() PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Render"); // Draw to HDR buffer + m_hdrScene->BeginScene(commandList); + PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Render HDR"); auto depthStencilDescriptor = deviceResources->GetDepthStencilView(); @@ -215,24 +224,12 @@ void SharedSimplePBR::Render() { auto rtv = static_cast(deviceResources->GetRenderTargetView()); commandList->OMSetRenderTargets(1, &rtv, FALSE, NULL); - - D3D12_RESOURCE_BARRIER b1 = CD3DX12_RESOURCE_BARRIER::Transition(m_rtvHDRBuffer.Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); - commandList->ResourceBarrier(1, &b1); - - // Set up tonemap effect - m_toneMapEffect->SetTexture(m_srvPile->GetGpuHandle(m_HDRBufferDescIndex), m_commonStates->LinearClamp()); - m_toneMapEffect->Apply(commandList); - - // Draw quad - m_toneMapBatch->Begin(commandList); - m_toneMapBatch->DrawQuad(ToneMapVert(Vector3(-1, 1, 0), Vector2(0, 0)), - ToneMapVert(Vector3(1, 1, 0), Vector2(1, 0)), - ToneMapVert(Vector3(1, -1, 0), Vector2(1, 1)), - ToneMapVert(Vector3(-1, -1, 0), Vector2(0, 1))); - m_toneMapBatch->End(); - - D3D12_RESOURCE_BARRIER b2 = CD3DX12_RESOURCE_BARRIER::Transition(m_rtvHDRBuffer.Get(), D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET); - commandList->ResourceBarrier(1, &b2); + + m_hdrScene->EndScene(commandList); + + // Tonemap + m_toneMap->SetHDRSourceTexture(m_srvPile->GetGpuHandle(StaticDescriptors::SceneTex)); + m_toneMap->Process(commandList); } PIXEndEvent(commandList); // Tonemap @@ -243,9 +240,13 @@ void SharedSimplePBR::Render() m_smallFont->DrawString(m_hudBatch.get(), L"SimplePBR Sample", XMFLOAT2(float(safe.left), float(safe.top)), ATG::Colors::LightGrey); + const wchar_t* legendStr = (m_gamepadConnected) ? + L"[RThumb] [LThumb]: Move Camera [View] Exit " + : L"Mouse, W,A,S,D: Move Camera Esc: Exit "; + DX::DrawControllerString(m_hudBatch.get(), m_smallFont.get(), m_ctrlFont.get(), - L"[RThumb] [LThumb] Mouse, W,A,S,D : Move Camera [View] Exit ", + legendStr, XMFLOAT2(float(safe.left), float(safe.bottom) - m_smallFont->GetLineSpacing()), ATG::Colors::LightGrey); @@ -265,8 +266,15 @@ void SharedSimplePBR::CreateDeviceDependentResources() m_commonStates = std::make_unique(device); // create heaps - m_srvPile = std::make_unique(device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE, 128); + m_srvPile = std::make_unique(device, + D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, + D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE, + 128, // Maximum descriptors for both static and dynamic + StaticDescriptors::Reserve); m_rtvHeap = std::make_unique(device, D3D12_DESCRIPTOR_HEAP_TYPE_RTV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE, 1); + + // Set up HDR render target. + m_hdrScene->SetDevice(device, m_srvPile->GetCpuHandle(StaticDescriptors::SceneTex), m_rtvHeap->GetFirstCpuHandle()); // Begin uploading texture resources ResourceUploadBatch resourceUpload(device); @@ -282,8 +290,7 @@ void SharedSimplePBR::CreateDeviceDependentResources() false )); - m_radTexDescIndex = m_srvPile->Allocate(); - DirectX::CreateShaderResourceView(device, m_radianceTexture.Get(), m_srvPile->GetCpuHandle(m_radTexDescIndex), true); + DirectX::CreateShaderResourceView(device, m_radianceTexture.Get(), m_srvPile->GetCpuHandle(StaticDescriptors::RadianceTex), true); // Irradiance (diffuse environment) texture DX::ThrowIfFailed( @@ -295,8 +302,7 @@ void SharedSimplePBR::CreateDeviceDependentResources() false )); - m_irrTexDescIndex = m_srvPile->Allocate(); - DirectX::CreateShaderResourceView(device, m_irradianceTexture.Get(), m_srvPile->GetCpuHandle(m_irrTexDescIndex), true); + DirectX::CreateShaderResourceView(device, m_irradianceTexture.Get(), m_srvPile->GetCpuHandle(StaticDescriptors::IrradianceTex), true); // Pipeline state - for rendering direct to back buffer { @@ -309,23 +315,9 @@ void SharedSimplePBR::CreateDeviceDependentResources() m_hudBatch = std::make_unique(device, resourceUpload, hudpd); - auto segoeDescIndex = m_srvPile->Allocate(); - m_smallFont = std::make_unique(device, resourceUpload, - L"SegoeUI_18.spritefont", - m_srvPile->GetCpuHandle(segoeDescIndex), - m_srvPile->GetGpuHandle(segoeDescIndex)); - - auto legendDescInex = m_srvPile->Allocate(); - m_ctrlFont = std::make_unique(device, resourceUpload, - L"XboxOneControllerLegendSmall.spritefont", - m_srvPile->GetCpuHandle(legendDescInex), - m_srvPile->GetGpuHandle(legendDescInex)); - // Create tone mapping effect - m_toneMapEffect = std::make_unique(device, Sample::GetBackBufferFormat()); - - // Tone map batch - m_toneMapBatch = std::make_unique>(device); + m_toneMap = std::make_unique(device, backBufferRts, + ToneMapPostProcess::ACESFilmic, ToneMapPostProcess::SRGB); } // Pipeline state - for rendering to HDR buffer @@ -346,7 +338,7 @@ void SharedSimplePBR::CreateDeviceDependentResources() } // Skybox - m_skybox = std::make_unique(device, m_srvPile->GetGpuHandle(m_radTexDescIndex), hdrBufferRts, *m_commonStates); + m_skybox = std::make_unique(device, m_srvPile->GetGpuHandle(StaticDescriptors::RadianceTex), hdrBufferRts, *m_commonStates); } // The current map has too much detail removed at last mips, scale back down to @@ -357,16 +349,16 @@ void SharedSimplePBR::CreateDeviceDependentResources() for (auto& m : m_pbrModels) { m->GetEffect()->SetIBLTextures( - m_srvPile->GetGpuHandle(m_radTexDescIndex), + m_srvPile->GetGpuHandle(StaticDescriptors::RadianceTex), numMips, - m_srvPile->GetGpuHandle(m_irrTexDescIndex), + m_srvPile->GetGpuHandle(StaticDescriptors::IrradianceTex), m_commonStates->LinearWrap()); } s_testScene = std::make_unique(); - s_testScene->Init(device, m_srvPile->GetGpuHandle(m_radTexDescIndex), + s_testScene->Init(device, m_srvPile->GetGpuHandle(StaticDescriptors::RadianceTex), numMips, - m_srvPile->GetGpuHandle(m_irrTexDescIndex), + m_srvPile->GetGpuHandle(StaticDescriptors::IrradianceTex), m_commonStates->LinearWrap()); auto finished = resourceUpload.End(m_sample->m_deviceResources->GetCommandQueue()); @@ -396,41 +388,24 @@ void SharedSimplePBR::CreateWindowSizeDependentResources() } // HDR render target resource - { - D3D12_RESOURCE_DESC desc = CD3DX12_RESOURCE_DESC::Tex2D( - Sample::GetHDRRenderFormat(), - size.right, - size.bottom, - 1, - 1 // Use a single mipmap level. - ); - desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS; - - // create resource - CD3DX12_HEAP_PROPERTIES rtvHeapProperties(D3D12_HEAP_TYPE_DEFAULT); - DX::ThrowIfFailed(device->CreateCommittedResource( - &rtvHeapProperties, - D3D12_HEAP_FLAG_NONE, - &desc, - D3D12_RESOURCE_STATE_RENDER_TARGET, - nullptr, // &depthOptimizedClearValue, - IID_GRAPHICS_PPV_ARGS(m_rtvHDRBuffer.ReleaseAndGetAddressOf()) - )); - m_rtvHDRBuffer->SetName(L"HDR buffer"); - } + m_hdrScene->SetWindow(size); - // HDR render target view - { - D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = {}; - rtvDesc.Format = Sample::GetHDRRenderFormat(); - rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; - device->CreateRenderTargetView(m_rtvHDRBuffer.Get(), &rtvDesc, m_rtvHeap->GetFirstCpuHandle()); + // Begin uploading texture resources + ResourceUploadBatch resourceUpload(device); + resourceUpload.Begin(); - // create SR view and put in heap - if (m_HDRBufferDescIndex == ATG::DescriptorPile::INVALID_INDEX) m_HDRBufferDescIndex = m_srvPile->Allocate(); + m_smallFont = std::make_unique(device, resourceUpload, + (size.bottom > 1200) ? L"SegoeUI_36.spritefont" : L"SegoeUI_18.spritefont", + m_srvPile->GetCpuHandle(StaticDescriptors::Font), + m_srvPile->GetGpuHandle(StaticDescriptors::Font)); - DirectX::CreateShaderResourceView(device, m_rtvHDRBuffer.Get(), m_srvPile->GetCpuHandle(m_HDRBufferDescIndex)); - } + m_ctrlFont = std::make_unique(device, resourceUpload, + (size.bottom > 1200) ? L"XboxOneControllerLegend.spritefont" : L"XboxOneControllerLegendSmall.spritefont", + m_srvPile->GetCpuHandle(StaticDescriptors::CtrlFont), + m_srvPile->GetGpuHandle(StaticDescriptors::CtrlFont)); + + auto finished = resourceUpload.End(m_sample->m_deviceResources->GetCommandQueue()); + finished.wait(); } // For UWP only @@ -440,16 +415,15 @@ void SharedSimplePBR::OnDeviceLost() m_smallFont.reset(); m_ctrlFont.reset(); - m_gamePad.reset(); m_camera.reset(); m_commonStates.reset(); m_srvPile.reset(); m_spriteBatch.reset(); - m_toneMapEffect.reset(); - m_toneMapBatch.reset(); + m_toneMap.reset(); + m_hdrScene->ReleaseDevice(); m_rtvHeap.reset(); for (auto& m : m_pbrModels) diff --git a/Samples/Graphics/SimplePBR12/Shared/SharedSimplePBR.h b/Samples/Graphics/SimplePBR12/Shared/SharedSimplePBR.h index 78227d3c..d09e36cd 100644 --- a/Samples/Graphics/SimplePBR12/Shared/SharedSimplePBR.h +++ b/Samples/Graphics/SimplePBR12/Shared/SharedSimplePBR.h @@ -13,11 +13,10 @@ #include "StepTimer.h" #include "PBREffect/PBREffect.h" -#include "ToneMapEffect/ToneMapEffect.h" #include "Skybox/Skybox.h" #include "GeometricPrimitive.h" #include "PBRModel.h" -#include "DescriptorPile.h" +#include "RenderTexture.h" class Sample; @@ -45,34 +44,38 @@ class SharedSimplePBR std::unique_ptr m_gamePad; DirectX::GamePad::ButtonStateTracker m_gamePadButtons; std::unique_ptr m_camera; + bool m_gamepadConnected; // Render states std::unique_ptr m_commonStates; // All SRV descriptors for sample - std::unique_ptr m_srvPile; + std::unique_ptr m_srvPile; + + enum StaticDescriptors + { + Font, + CtrlFont, + SceneTex, + RadianceTex, + IrradianceTex, + Reserve + }; // Drawing using DebugVert = DirectX::VertexPositionColor; - using ToneMapVert = ATG::ToneMapEffect::VertexType; - std::unique_ptr m_spriteBatch; - std::unique_ptr m_toneMapEffect; - std::unique_ptr> m_toneMapBatch; + std::unique_ptr m_spriteBatch; + std::unique_ptr m_toneMap; // Render target view for tonemapping + std::unique_ptr m_hdrScene; std::unique_ptr m_rtvHeap; - Microsoft::WRL::ComPtr m_rtvHDRBuffer; - - // Shader resource view for tonemapping - ATG::DescriptorPile::IndexType m_HDRBufferDescIndex; // Sky/Environment textures - ATG::DescriptorPile::IndexType m_radTexDescIndex; Microsoft::WRL::ComPtr m_radianceTexture; // Irradiance texture - ATG::DescriptorPile::IndexType m_irrTexDescIndex; Microsoft::WRL::ComPtr m_irradianceTexture; // Model diff --git a/Samples/Graphics/SimplePBR12/SimplePBRUWP12.vcxproj b/Samples/Graphics/SimplePBR12/SimplePBRUWP12.vcxproj index ee3e59c9..03715da4 100644 --- a/Samples/Graphics/SimplePBR12/SimplePBRUWP12.vcxproj +++ b/Samples/Graphics/SimplePBR12/SimplePBRUWP12.vcxproj @@ -35,7 +35,7 @@ true Windows Store 10.0.15063.0 - 10.0.10240.0 + 10.0.14393.0 10.0 true @@ -99,7 +99,7 @@ false - false + false @@ -107,7 +107,7 @@ ..\..\..\Kits\Telemetry\$(Platform); %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\arm; $(VCInstallDir)\lib\arm - Shared\pch.h + pch.h $(IntDir)pch.pch $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;..\..\..\Kits\Telemetry;%(AdditionalIncludeDirectories) /bigobj %(AdditionalOptions) @@ -125,7 +125,7 @@ ..\..\..\Kits\Telemetry\$(Platform); %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\arm; $(VCInstallDir)\lib\arm - Shared\pch.h + pch.h $(IntDir)pch.pch $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;..\..\..\Kits\Telemetry;%(AdditionalIncludeDirectories) /bigobj %(AdditionalOptions) @@ -143,7 +143,7 @@ ..\..\..\Kits\Telemetry\$(Platform); %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store; $(VCInstallDir)\lib - Shared\pch.h + pch.h $(IntDir)pch.pch $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;..\..\..\Kits\Telemetry;%(AdditionalIncludeDirectories) /bigobj %(AdditionalOptions) @@ -162,7 +162,7 @@ ..\..\..\Kits\Telemetry\$(Platform); %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store; $(VCInstallDir)\lib - Shared\pch.h + pch.h $(IntDir)pch.pch $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;..\..\..\Kits\Telemetry;%(AdditionalIncludeDirectories) /bigobj %(AdditionalOptions) @@ -181,7 +181,7 @@ ..\..\..\Kits\Telemetry\$(Platform); %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\amd64; $(VCInstallDir)\lib\amd64 - Shared\pch.h + pch.h $(IntDir)pch.pch $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;..\..\..\Kits\Telemetry;%(AdditionalIncludeDirectories) /bigobj %(AdditionalOptions) @@ -199,7 +199,7 @@ ..\..\..\Kits\Telemetry\$(Platform); %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\amd64; $(VCInstallDir)\lib\amd64 - Shared\pch.h + pch.h $(IntDir)pch.pch $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;..\..\..\Kits\Telemetry;%(AdditionalIncludeDirectories) /bigobj %(AdditionalOptions) @@ -217,14 +217,13 @@ + - - - + @@ -245,6 +244,7 @@ pch.h pch.h + pch.h pch.h @@ -253,14 +253,6 @@ pch.h pch.h - - pch.h - pch.h - pch.h - pch.h - pch.h - pch.h - pch.h pch.h @@ -293,7 +285,7 @@ pch.h pch.h - + Create Create Create @@ -312,7 +304,6 @@ - true true @@ -321,6 +312,22 @@ true true + + true + true + true + true + true + true + + + true + true + true + true + true + true + true true @@ -329,7 +336,7 @@ true true - + true true true @@ -337,7 +344,7 @@ true true - + true true true @@ -345,7 +352,7 @@ true true - + true true true @@ -353,7 +360,7 @@ true true - + true true true @@ -367,15 +374,15 @@ - - - - - - - - - + + + + + + + + + @@ -570,70 +577,6 @@ Vertex Vertex - - %(Filename) - %(ProjectDir)Compiled\%(Filename).inc - - - %(Filename) - %(ProjectDir)Compiled\%(Filename).inc - - - %(Filename) - %(ProjectDir)Compiled\%(Filename).inc - - - %(Filename) - %(ProjectDir)Compiled\%(Filename).inc - - - %(Filename) - %(ProjectDir)Compiled\%(Filename).inc - - - %(Filename) - %(ProjectDir)Compiled\%(Filename).inc - - - Pixel - Pixel - Pixel - Pixel - Pixel - Pixel - - - %(Filename) - %(ProjectDir)Compiled\%(Filename).inc - - - %(Filename) - %(ProjectDir)Compiled\%(Filename).inc - - - %(Filename) - %(ProjectDir)Compiled\%(Filename).inc - - - %(Filename) - %(ProjectDir)Compiled\%(Filename).inc - - - %(Filename) - %(ProjectDir)Compiled\%(Filename).inc - - - %(Filename) - %(ProjectDir)Compiled\%(Filename).inc - - - Vertex - Vertex - Vertex - Vertex - Vertex - Vertex - diff --git a/Samples/Graphics/SimplePBR12/SimplePBRUWP12.vcxproj.filters b/Samples/Graphics/SimplePBR12/SimplePBRUWP12.vcxproj.filters index 71c67356..341deeac 100644 --- a/Samples/Graphics/SimplePBR12/SimplePBRUWP12.vcxproj.filters +++ b/Samples/Graphics/SimplePBR12/SimplePBRUWP12.vcxproj.filters @@ -29,9 +29,6 @@ {a8d8dfff-b806-4fd1-a936-d06c0e1c4584} - - {72dc149d-78d0-4a74-9107-eff7ac649ab3} - {475e1100-2c53-4f97-a0c3-edd7af1b1bde} @@ -73,7 +70,7 @@ UWP - + Shared @@ -91,24 +88,21 @@ Shared - - Shared - ATG Tool Kit ATG Tool Kit\PBREffect - - ATG Tool Kit\ToneMapEffect - ATG Tool Kit\Skybox ATG Tool Kit\Skybox + + ATG Tool Kit + @@ -123,7 +117,7 @@ UWP - + Shared @@ -132,12 +126,12 @@ ATG Tool Kit\PBREffect - - ATG Tool Kit\ToneMapEffect - ATG Tool Kit\Skybox + + ATG Tool Kit + @@ -155,13 +149,13 @@ Assets\Logo - + Assets\Models\ToyRobot\WoodBlocks - + Assets\Models\ToyRobot\ToyRobot - + Assets\Models\ToyRobot\Floor @@ -170,27 +164,27 @@ Assets\Backgrounds - + Assets\Models\ToyRobot\WoodBlocks - + Assets\Models\ToyRobot\WoodBlocks - + Assets\Models\ToyRobot\ToyRobot - + Assets\Models\ToyRobot\ToyRobot - + Assets\Models\ToyRobot\Floor - + Assets\Models\ToyRobot\Floor - + Assets\Models\XboxOrb @@ -200,16 +194,13 @@ ATG Tool Kit\PBREffect - - ATG Tool Kit\ToneMapEffect - - + Assets\Models\ToyRobot\Floor - + Assets\Models\ToyRobot\ToyRobot - + Assets\Models\ToyRobot\WoodBlocks @@ -230,6 +221,12 @@ UWP\Telemetry\Win32 + + Assets\Fonts + + + Assets\Fonts + @@ -246,12 +243,6 @@ ATG Tool Kit\PBREffect - - ATG Tool Kit\ToneMapEffect - - - ATG Tool Kit\ToneMapEffect - ATG Tool Kit\Skybox diff --git a/Samples/Graphics/SimplePBR12/UWP/DeviceResources.cpp b/Samples/Graphics/SimplePBR12/UWP/DeviceResources.cpp index a77ccff2..5e3a68f6 100644 --- a/Samples/Graphics/SimplePBR12/UWP/DeviceResources.cpp +++ b/Samples/Graphics/SimplePBR12/UWP/DeviceResources.cpp @@ -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), @@ -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) @@ -99,7 +100,9 @@ DX::DeviceResources::~DeviceResources() void DX::DeviceResources::CreateDeviceResources() { #if defined(_DEBUG) - // Enable the debug layer (only available if the Graphics Tools feature-on-demand is enabled). + // Enable the debug layer (requires the Graphics Tools "optional feature"). + // + // NOTE: Enabling the debug layer after device creation will invalidate the active device. bool debugDXGI = false; { ComPtr debugController; @@ -129,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 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 adapter; GetAdapter(adapter.GetAddressOf()); @@ -262,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) @@ -298,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 swapChain; @@ -554,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) @@ -655,7 +689,7 @@ void DX::DeviceResources::GetAdapter(IDXGIAdapter1** ppAdapter) // Try WARP12 instead if (FAILED(m_dxgiFactory->EnumWarpAdapter(IID_PPV_ARGS(adapter.ReleaseAndGetAddressOf())))) { - throw std::exception("WARP12 not available. Enable the 'Graphics Tools' feature-on-demand"); + throw std::exception("WARP12 not available. Enable the 'Graphics Tools' optional feature"); } OutputDebugStringA("Direct3D Adapter - WARP12\n"); diff --git a/Samples/Graphics/SimplePBR12/UWP/DeviceResources.h b/Samples/Graphics/SimplePBR12/UWP/DeviceResources.h index 5eaa373a..a52a8c70 100644 --- a/Samples/Graphics/SimplePBR12/UWP/DeviceResources.h +++ b/Samples/Graphics/SimplePBR12/UWP/DeviceResources.h @@ -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(); @@ -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 { @@ -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; diff --git a/Samples/Graphics/SimplePBR12/UWP/Main.cpp b/Samples/Graphics/SimplePBR12/UWP/Main.cpp index 242afbdd..79940e95 100644 --- a/Samples/Graphics/SimplePBR12/UWP/Main.cpp +++ b/Samples/Graphics/SimplePBR12/UWP/Main.cpp @@ -208,7 +208,7 @@ ref class ViewProvider sealed : public IFrameworkView void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) { - SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral(); + auto deferral = args->SuspendingOperation->GetDeferral(); create_task([this, deferral]() { @@ -407,10 +407,8 @@ ref class ViewProviderFactory : IFrameworkViewSource // Entry point [Platform::MTAThread] -int main(Platform::Array^ argv) +int __cdecl main(Platform::Array^ /*argv*/) { - UNREFERENCED_PARAMETER(argv); - if (!XMVerifyCPUSupport()) { throw std::exception("XMVerifyCPUSupport"); @@ -420,3 +418,10 @@ int main(Platform::Array^ argv) CoreApplication::Run(viewProviderFactory); return 0; } + + +// Exit helper +void ExitSample() +{ + Windows::ApplicationModel::Core::CoreApplication::Exit(); +} \ No newline at end of file diff --git a/Samples/Graphics/SimplePBR12/UWP/SimplePBRUWP12.cpp b/Samples/Graphics/SimplePBR12/UWP/SimplePBRUWP12.cpp index 7aaa5ee5..1a8c9317 100644 --- a/Samples/Graphics/SimplePBR12/UWP/SimplePBRUWP12.cpp +++ b/Samples/Graphics/SimplePBR12/UWP/SimplePBRUWP12.cpp @@ -10,6 +10,8 @@ #include "ATGColors.h" +extern void ExitSample(); + using namespace DirectX; using Microsoft::WRL::ComPtr; @@ -63,7 +65,7 @@ void Sample::Update(DX::StepTimer const& timer) if (kb.Escape) { - Windows::ApplicationModel::Core::CoreApplication::Exit(); + ExitSample(); } // Update core sample diff --git a/Samples/Graphics/SimplePBR12/UWP/SimplePBRUWP12.h b/Samples/Graphics/SimplePBR12/UWP/SimplePBRUWP12.h index 25dd8ea8..7336e66a 100644 --- a/Samples/Graphics/SimplePBR12/UWP/SimplePBRUWP12.h +++ b/Samples/Graphics/SimplePBR12/UWP/SimplePBRUWP12.h @@ -41,8 +41,8 @@ class Sample : public DX::IDeviceNotify // Properties void GetDefaultSize( int& width, int& height ) const; - inline static DXGI_FORMAT GetHDRRenderFormat() { return DXGI_FORMAT_R16G16B16A16_FLOAT; } - inline static DXGI_FORMAT GetBackBufferFormat() { return DXGI_FORMAT_R16G16B16A16_FLOAT; } + inline static DXGI_FORMAT GetHDRRenderFormat() { return DXGI_FORMAT_R11G11B10_FLOAT; } + inline static DXGI_FORMAT GetBackBufferFormat() { return DXGI_FORMAT_R10G10B10A2_UNORM; } inline static DXGI_FORMAT GetDepthFormat() { return DXGI_FORMAT_D32_FLOAT; } private: diff --git a/Samples/Graphics/SimplePBR12/Shared/pch.cpp b/Samples/Graphics/SimplePBR12/pch.cpp similarity index 100% rename from Samples/Graphics/SimplePBR12/Shared/pch.cpp rename to Samples/Graphics/SimplePBR12/pch.cpp diff --git a/Samples/Graphics/SimplePBR12/Shared/pch.h b/Samples/Graphics/SimplePBR12/pch.h similarity index 91% rename from Samples/Graphics/SimplePBR12/Shared/pch.h rename to Samples/Graphics/SimplePBR12/pch.h index c410c61a..33e33c57 100644 --- a/Samples/Graphics/SimplePBR12/Shared/pch.h +++ b/Samples/Graphics/SimplePBR12/pch.h @@ -16,6 +16,12 @@ #if defined(_XBOX_ONE) && defined(_TITLE) +#include + +#if _XDK_VER < 0x38390403 /* XDK Edition 160800 */ +#error This sample requires the August 2016 XDK or later +#endif + #include #include @@ -23,7 +29,7 @@ #include #include "d3dx12.h" -#include +#include #ifdef _DEBUG #include @@ -53,6 +59,7 @@ #include #include #include +#include #include #include #include diff --git a/Samples/IntroGraphics/DirectXTKSimpleSampleUWP/DeviceResources.cpp b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP/DeviceResources.cpp index d00acd30..6c890acb 100644 --- a/Samples/IntroGraphics/DirectXTKSimpleSampleUWP/DeviceResources.cpp +++ b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP/DeviceResources.cpp @@ -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), @@ -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) { } @@ -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) @@ -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 swapChain; DX::ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( @@ -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 @@ -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 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 adapter; for (UINT adapterIndex = 0; DXGI_ERROR_NOT_FOUND != dxgiFactory->EnumAdapters1(adapterIndex, adapter.ReleaseAndGetAddressOf()); adapterIndex++) { diff --git a/Samples/IntroGraphics/DirectXTKSimpleSampleUWP/DeviceResources.h b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP/DeviceResources.h index ed0f0874..8d8f8837 100644 --- a/Samples/IntroGraphics/DirectXTKSimpleSampleUWP/DeviceResources.h +++ b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP/DeviceResources.h @@ -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(); @@ -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); @@ -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; }; diff --git a/Samples/IntroGraphics/DirectXTKSimpleSampleUWP/DirectXTKSimpleSample.cpp b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP/DirectXTKSimpleSample.cpp index 4425e05f..f58b442f 100644 --- a/Samples/IntroGraphics/DirectXTKSimpleSampleUWP/DirectXTKSimpleSample.cpp +++ b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP/DirectXTKSimpleSample.cpp @@ -8,6 +8,8 @@ #include "pch.h" #include "DirectXTKSimpleSample.h" +extern void ExitSample(); + using namespace DirectX; using namespace DirectX::SimpleMath; @@ -125,14 +127,14 @@ void Sample::Update(DX::StepTimer const& timer) { if (pad.IsViewPressed()) { - Windows::ApplicationModel::Core::CoreApplication::Exit(); + ExitSample(); } } auto kb = m_keyboard->GetState(); if (kb.Escape) { - Windows::ApplicationModel::Core::CoreApplication::Exit(); + ExitSample(); } PIXEndEvent(); diff --git a/Samples/IntroGraphics/DirectXTKSimpleSampleUWP/DirectXTKSimpleSample.vcxproj b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP/DirectXTKSimpleSample.vcxproj index e97c0425..4fbf3344 100644 --- a/Samples/IntroGraphics/DirectXTKSimpleSampleUWP/DirectXTKSimpleSample.vcxproj +++ b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP/DirectXTKSimpleSample.vcxproj @@ -98,7 +98,7 @@ false - false + false diff --git a/Samples/IntroGraphics/DirectXTKSimpleSampleUWP/Main.cpp b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP/Main.cpp index 453ee511..94671def 100644 --- a/Samples/IntroGraphics/DirectXTKSimpleSampleUWP/Main.cpp +++ b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP/Main.cpp @@ -218,7 +218,7 @@ ref class ViewProvider sealed : public IFrameworkView void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) { - SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral(); + auto deferral = args->SuspendingOperation->GetDeferral(); create_task([this, deferral]() { @@ -431,10 +431,8 @@ ref class ViewProviderFactory : IFrameworkViewSource // Entry point [Platform::MTAThread] -int main(Platform::Array^ argv) +int __cdecl main(Platform::Array^ /*argv*/) { - UNREFERENCED_PARAMETER(argv); - if (!XMVerifyCPUSupport()) { throw std::exception("XMVerifyCPUSupport"); @@ -444,3 +442,10 @@ int main(Platform::Array^ argv) CoreApplication::Run(viewProviderFactory); return 0; } + + +// Exit helper +void ExitSample() +{ + Windows::ApplicationModel::Core::CoreApplication::Exit(); +} \ No newline at end of file diff --git a/Samples/IntroGraphics/DirectXTKSimpleSampleUWP/Readme.docx b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP/Readme.docx index c150ae98..c3cafc42 100644 Binary files a/Samples/IntroGraphics/DirectXTKSimpleSampleUWP/Readme.docx and b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP/Readme.docx differ diff --git a/Samples/IntroGraphics/DirectXTKSimpleSampleUWP/pch.h b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP/pch.h index 69040457..d1ceee4d 100644 --- a/Samples/IntroGraphics/DirectXTKSimpleSampleUWP/pch.h +++ b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP/pch.h @@ -15,7 +15,7 @@ #include #include -#include +#include #include #include diff --git a/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/DeviceResources.cpp b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/DeviceResources.cpp index a77ccff2..5e3a68f6 100644 --- a/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/DeviceResources.cpp +++ b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/DeviceResources.cpp @@ -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), @@ -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) @@ -99,7 +100,9 @@ DX::DeviceResources::~DeviceResources() void DX::DeviceResources::CreateDeviceResources() { #if defined(_DEBUG) - // Enable the debug layer (only available if the Graphics Tools feature-on-demand is enabled). + // Enable the debug layer (requires the Graphics Tools "optional feature"). + // + // NOTE: Enabling the debug layer after device creation will invalidate the active device. bool debugDXGI = false; { ComPtr debugController; @@ -129,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 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 adapter; GetAdapter(adapter.GetAddressOf()); @@ -262,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) @@ -298,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 swapChain; @@ -554,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) @@ -655,7 +689,7 @@ void DX::DeviceResources::GetAdapter(IDXGIAdapter1** ppAdapter) // Try WARP12 instead if (FAILED(m_dxgiFactory->EnumWarpAdapter(IID_PPV_ARGS(adapter.ReleaseAndGetAddressOf())))) { - throw std::exception("WARP12 not available. Enable the 'Graphics Tools' feature-on-demand"); + throw std::exception("WARP12 not available. Enable the 'Graphics Tools' optional feature"); } OutputDebugStringA("Direct3D Adapter - WARP12\n"); diff --git a/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/DeviceResources.h b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/DeviceResources.h index 5eaa373a..a52a8c70 100644 --- a/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/DeviceResources.h +++ b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/DeviceResources.h @@ -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(); @@ -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 { @@ -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; diff --git a/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/DirectXTKSimpleSample12.cpp b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/DirectXTKSimpleSample12.cpp index b8a2ade9..2b64688f 100644 --- a/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/DirectXTKSimpleSample12.cpp +++ b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/DirectXTKSimpleSample12.cpp @@ -8,6 +8,8 @@ #include "pch.h" #include "DirectXTKSimpleSample12.h" +extern void ExitSample(); + using namespace DirectX; using namespace DirectX::SimpleMath; @@ -126,7 +128,7 @@ void Sample::Update(DX::StepTimer const& timer) if (pad.IsViewPressed()) { - Windows::ApplicationModel::Core::CoreApplication::Exit(); + ExitSample(); } } else @@ -139,7 +141,7 @@ void Sample::Update(DX::StepTimer const& timer) if (kb.Escape) { - Windows::ApplicationModel::Core::CoreApplication::Exit(); + ExitSample(); } auto mouse = m_mouse->GetState(); diff --git a/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/DirectXTKSimpleSample12.vcxproj b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/DirectXTKSimpleSample12.vcxproj index 03a33876..0262415a 100644 --- a/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/DirectXTKSimpleSample12.vcxproj +++ b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/DirectXTKSimpleSample12.vcxproj @@ -98,7 +98,7 @@ false - false + false diff --git a/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/Main.cpp b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/Main.cpp index 0debed02..db40bcdc 100644 --- a/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/Main.cpp +++ b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/Main.cpp @@ -218,7 +218,7 @@ ref class ViewProvider sealed : public IFrameworkView void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) { - SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral(); + auto deferral = args->SuspendingOperation->GetDeferral(); create_task([this, deferral]() { @@ -431,11 +431,9 @@ ref class ViewProviderFactory : IFrameworkViewSource // Entry point [Platform::MTAThread] -int main(Platform::Array^ argv) +int __cdecl main(Platform::Array^ /*argv*/) { - UNREFERENCED_PARAMETER(argv); - - if (!XMVerifyCPUSupport()) + if (!XMVerifyCPUSupport()) { throw std::exception("XMVerifyCPUSupport"); } @@ -444,3 +442,10 @@ int main(Platform::Array^ argv) CoreApplication::Run(viewProviderFactory); return 0; } + + +// Exit helper +void ExitSample() +{ + Windows::ApplicationModel::Core::CoreApplication::Exit(); +} \ No newline at end of file diff --git a/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/Readme.docx b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/Readme.docx index c8e4e011..ed8b2dae 100644 Binary files a/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/Readme.docx and b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/Readme.docx differ diff --git a/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/pch.h b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/pch.h index 71bb4102..01342a0d 100644 --- a/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/pch.h +++ b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/pch.h @@ -15,7 +15,7 @@ #include #include -#include +#include #include #include diff --git a/Samples/IntroGraphics/SimpleBezierUWP/DeviceResources.cpp b/Samples/IntroGraphics/SimpleBezierUWP/DeviceResources.cpp index d00acd30..6c890acb 100644 --- a/Samples/IntroGraphics/SimpleBezierUWP/DeviceResources.cpp +++ b/Samples/IntroGraphics/SimpleBezierUWP/DeviceResources.cpp @@ -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), @@ -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) { } @@ -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) @@ -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 swapChain; DX::ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( @@ -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 @@ -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 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 adapter; for (UINT adapterIndex = 0; DXGI_ERROR_NOT_FOUND != dxgiFactory->EnumAdapters1(adapterIndex, adapter.ReleaseAndGetAddressOf()); adapterIndex++) { diff --git a/Samples/IntroGraphics/SimpleBezierUWP/DeviceResources.h b/Samples/IntroGraphics/SimpleBezierUWP/DeviceResources.h index ed0f0874..8d8f8837 100644 --- a/Samples/IntroGraphics/SimpleBezierUWP/DeviceResources.h +++ b/Samples/IntroGraphics/SimpleBezierUWP/DeviceResources.h @@ -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(); @@ -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); @@ -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; }; diff --git a/Samples/IntroGraphics/SimpleBezierUWP/Main.cpp b/Samples/IntroGraphics/SimpleBezierUWP/Main.cpp index 5e63a104..93e2966d 100644 --- a/Samples/IntroGraphics/SimpleBezierUWP/Main.cpp +++ b/Samples/IntroGraphics/SimpleBezierUWP/Main.cpp @@ -208,7 +208,7 @@ ref class ViewProvider sealed : public IFrameworkView void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) { - SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral(); + auto deferral = args->SuspendingOperation->GetDeferral(); create_task([this, deferral]() { @@ -407,10 +407,8 @@ ref class ViewProviderFactory : IFrameworkViewSource // Entry point [Platform::MTAThread] -int main(Platform::Array^ argv) +int __cdecl main(Platform::Array^ /*argv*/) { - UNREFERENCED_PARAMETER(argv); - if (!XMVerifyCPUSupport()) { throw std::exception("XMVerifyCPUSupport"); @@ -420,3 +418,10 @@ int main(Platform::Array^ argv) CoreApplication::Run(viewProviderFactory); return 0; } + + +// Exit helper +void ExitSample() +{ + Windows::ApplicationModel::Core::CoreApplication::Exit(); +} \ No newline at end of file diff --git a/Samples/IntroGraphics/SimpleBezierUWP/Readme.docx b/Samples/IntroGraphics/SimpleBezierUWP/Readme.docx index 38b5717f..d97e1edc 100644 Binary files a/Samples/IntroGraphics/SimpleBezierUWP/Readme.docx and b/Samples/IntroGraphics/SimpleBezierUWP/Readme.docx differ diff --git a/Samples/IntroGraphics/SimpleBezierUWP/SimpleBezier.cpp b/Samples/IntroGraphics/SimpleBezierUWP/SimpleBezier.cpp index 4e4096cd..dcd6bbed 100644 --- a/Samples/IntroGraphics/SimpleBezierUWP/SimpleBezier.cpp +++ b/Samples/IntroGraphics/SimpleBezierUWP/SimpleBezier.cpp @@ -15,6 +15,8 @@ #include "ATGColors.h" #include "ReadData.h" +extern void ExitSample(); + using namespace DirectX; using Microsoft::WRL::ComPtr; @@ -188,7 +190,7 @@ void Sample::Update(DX::StepTimer const&) if ((!m_showHelp && m_keyboardButtons.IsKeyPressed(Keyboard::Escape)) || pad.IsViewPressed()) { - Windows::ApplicationModel::Core::CoreApplication::Exit(); + ExitSample(); } if (m_keyboardButtons.IsKeyPressed(Keyboard::F1) || m_gamePadButtons.menu == GamePad::ButtonStateTracker::PRESSED) diff --git a/Samples/IntroGraphics/SimpleBezierUWP/SimpleBezier.vcxproj b/Samples/IntroGraphics/SimpleBezierUWP/SimpleBezier.vcxproj index 885dc84e..125eb3d6 100644 --- a/Samples/IntroGraphics/SimpleBezierUWP/SimpleBezier.vcxproj +++ b/Samples/IntroGraphics/SimpleBezierUWP/SimpleBezier.vcxproj @@ -98,7 +98,7 @@ false - false + false diff --git a/Samples/IntroGraphics/SimpleBezierUWP/pch.h b/Samples/IntroGraphics/SimpleBezierUWP/pch.h index a0123a9b..127e6ab3 100644 --- a/Samples/IntroGraphics/SimpleBezierUWP/pch.h +++ b/Samples/IntroGraphics/SimpleBezierUWP/pch.h @@ -15,7 +15,7 @@ #include #include -#include +#include #include #include diff --git a/Samples/IntroGraphics/SimpleBezierUWP12/DeviceResources.cpp b/Samples/IntroGraphics/SimpleBezierUWP12/DeviceResources.cpp index a77ccff2..5e3a68f6 100644 --- a/Samples/IntroGraphics/SimpleBezierUWP12/DeviceResources.cpp +++ b/Samples/IntroGraphics/SimpleBezierUWP12/DeviceResources.cpp @@ -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), @@ -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) @@ -99,7 +100,9 @@ DX::DeviceResources::~DeviceResources() void DX::DeviceResources::CreateDeviceResources() { #if defined(_DEBUG) - // Enable the debug layer (only available if the Graphics Tools feature-on-demand is enabled). + // Enable the debug layer (requires the Graphics Tools "optional feature"). + // + // NOTE: Enabling the debug layer after device creation will invalidate the active device. bool debugDXGI = false; { ComPtr debugController; @@ -129,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 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 adapter; GetAdapter(adapter.GetAddressOf()); @@ -262,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) @@ -298,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 swapChain; @@ -554,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) @@ -655,7 +689,7 @@ void DX::DeviceResources::GetAdapter(IDXGIAdapter1** ppAdapter) // Try WARP12 instead if (FAILED(m_dxgiFactory->EnumWarpAdapter(IID_PPV_ARGS(adapter.ReleaseAndGetAddressOf())))) { - throw std::exception("WARP12 not available. Enable the 'Graphics Tools' feature-on-demand"); + throw std::exception("WARP12 not available. Enable the 'Graphics Tools' optional feature"); } OutputDebugStringA("Direct3D Adapter - WARP12\n"); diff --git a/Samples/IntroGraphics/SimpleBezierUWP12/DeviceResources.h b/Samples/IntroGraphics/SimpleBezierUWP12/DeviceResources.h index 5eaa373a..a52a8c70 100644 --- a/Samples/IntroGraphics/SimpleBezierUWP12/DeviceResources.h +++ b/Samples/IntroGraphics/SimpleBezierUWP12/DeviceResources.h @@ -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(); @@ -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 { @@ -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; diff --git a/Samples/IntroGraphics/SimpleBezierUWP12/Main.cpp b/Samples/IntroGraphics/SimpleBezierUWP12/Main.cpp index 5e63a104..34b456b0 100644 --- a/Samples/IntroGraphics/SimpleBezierUWP12/Main.cpp +++ b/Samples/IntroGraphics/SimpleBezierUWP12/Main.cpp @@ -208,7 +208,7 @@ ref class ViewProvider sealed : public IFrameworkView void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) { - SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral(); + auto deferral = args->SuspendingOperation->GetDeferral(); create_task([this, deferral]() { @@ -407,10 +407,8 @@ ref class ViewProviderFactory : IFrameworkViewSource // Entry point [Platform::MTAThread] -int main(Platform::Array^ argv) +int __cdecl main(Platform::Array^ /*argv*/) { - UNREFERENCED_PARAMETER(argv); - if (!XMVerifyCPUSupport()) { throw std::exception("XMVerifyCPUSupport"); @@ -420,3 +418,10 @@ int main(Platform::Array^ argv) CoreApplication::Run(viewProviderFactory); return 0; } + + +// Exit helper +void ExitSample() +{ + Windows::ApplicationModel::Core::CoreApplication::Exit(); +} diff --git a/Samples/IntroGraphics/SimpleBezierUWP12/Readme.docx b/Samples/IntroGraphics/SimpleBezierUWP12/Readme.docx index 6bc22271..c8caf93c 100644 Binary files a/Samples/IntroGraphics/SimpleBezierUWP12/Readme.docx and b/Samples/IntroGraphics/SimpleBezierUWP12/Readme.docx differ diff --git a/Samples/IntroGraphics/SimpleBezierUWP12/SimpleBezier.cpp b/Samples/IntroGraphics/SimpleBezierUWP12/SimpleBezier.cpp index ace6c4ef..b185010e 100644 --- a/Samples/IntroGraphics/SimpleBezierUWP12/SimpleBezier.cpp +++ b/Samples/IntroGraphics/SimpleBezierUWP12/SimpleBezier.cpp @@ -11,6 +11,8 @@ #include "ATGColors.h" #include "ReadData.h" +extern void ExitSample(); + using namespace DirectX; using Microsoft::WRL::ComPtr; @@ -189,7 +191,7 @@ void Sample::Update(DX::StepTimer const&) if ((!m_showHelp && m_keyboardButtons.IsKeyPressed(Keyboard::Escape)) || pad.IsViewPressed()) { - Windows::ApplicationModel::Core::CoreApplication::Exit(); + ExitSample(); } if (m_keyboardButtons.IsKeyPressed(Keyboard::F1) || m_gamePadButtons.menu == GamePad::ButtonStateTracker::PRESSED) diff --git a/Samples/IntroGraphics/SimpleBezierUWP12/SimpleBezier.vcxproj b/Samples/IntroGraphics/SimpleBezierUWP12/SimpleBezier.vcxproj index 1b1f9e1b..f07fd424 100644 --- a/Samples/IntroGraphics/SimpleBezierUWP12/SimpleBezier.vcxproj +++ b/Samples/IntroGraphics/SimpleBezierUWP12/SimpleBezier.vcxproj @@ -98,7 +98,7 @@ false - false + false diff --git a/Samples/IntroGraphics/SimpleBezierUWP12/pch.h b/Samples/IntroGraphics/SimpleBezierUWP12/pch.h index d8fa4ae5..35411612 100644 --- a/Samples/IntroGraphics/SimpleBezierUWP12/pch.h +++ b/Samples/IntroGraphics/SimpleBezierUWP12/pch.h @@ -15,7 +15,7 @@ #include #include -#include +#include #include #include diff --git a/Samples/IntroGraphics/SimpleInstancingUWP/DeviceResources.cpp b/Samples/IntroGraphics/SimpleInstancingUWP/DeviceResources.cpp index d00acd30..6c890acb 100644 --- a/Samples/IntroGraphics/SimpleInstancingUWP/DeviceResources.cpp +++ b/Samples/IntroGraphics/SimpleInstancingUWP/DeviceResources.cpp @@ -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), @@ -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) { } @@ -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) @@ -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 swapChain; DX::ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( @@ -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 @@ -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 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 adapter; for (UINT adapterIndex = 0; DXGI_ERROR_NOT_FOUND != dxgiFactory->EnumAdapters1(adapterIndex, adapter.ReleaseAndGetAddressOf()); adapterIndex++) { diff --git a/Samples/IntroGraphics/SimpleInstancingUWP/DeviceResources.h b/Samples/IntroGraphics/SimpleInstancingUWP/DeviceResources.h index ed0f0874..8d8f8837 100644 --- a/Samples/IntroGraphics/SimpleInstancingUWP/DeviceResources.h +++ b/Samples/IntroGraphics/SimpleInstancingUWP/DeviceResources.h @@ -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(); @@ -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); @@ -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; }; diff --git a/Samples/IntroGraphics/SimpleInstancingUWP/Main.cpp b/Samples/IntroGraphics/SimpleInstancingUWP/Main.cpp index 66dfbbce..764126d1 100644 --- a/Samples/IntroGraphics/SimpleInstancingUWP/Main.cpp +++ b/Samples/IntroGraphics/SimpleInstancingUWP/Main.cpp @@ -210,7 +210,7 @@ ref class ViewProvider sealed : public IFrameworkView void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) { - SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral(); + auto deferral = args->SuspendingOperation->GetDeferral(); create_task([this, deferral]() { @@ -411,10 +411,8 @@ ref class ViewProviderFactory : IFrameworkViewSource // Entry point [Platform::MTAThread] -int main(Platform::Array^ argv) +int __cdecl main(Platform::Array^ /*argv*/) { - UNREFERENCED_PARAMETER(argv); - if (!XMVerifyCPUSupport()) { throw std::exception("XMVerifyCPUSupport"); @@ -424,3 +422,10 @@ int main(Platform::Array^ argv) CoreApplication::Run(viewProviderFactory); return 0; } + + +// Exit helper +void ExitSample() +{ + Windows::ApplicationModel::Core::CoreApplication::Exit(); +} \ No newline at end of file diff --git a/Samples/IntroGraphics/SimpleInstancingUWP/Readme.docx b/Samples/IntroGraphics/SimpleInstancingUWP/Readme.docx index fbcb3f5b..0ebfe4eb 100644 Binary files a/Samples/IntroGraphics/SimpleInstancingUWP/Readme.docx and b/Samples/IntroGraphics/SimpleInstancingUWP/Readme.docx differ diff --git a/Samples/IntroGraphics/SimpleInstancingUWP/SimpleInstancing.cpp b/Samples/IntroGraphics/SimpleInstancingUWP/SimpleInstancing.cpp index 477bb846..6ba18737 100644 --- a/Samples/IntroGraphics/SimpleInstancingUWP/SimpleInstancing.cpp +++ b/Samples/IntroGraphics/SimpleInstancingUWP/SimpleInstancing.cpp @@ -12,6 +12,8 @@ #include "ControllerFont.h" #include "ReadData.h" +extern void ExitSample(); + using namespace DirectX; using namespace DirectX::PackedVector; @@ -105,7 +107,7 @@ void Sample::Update(DX::StepTimer const& timer) if (pad.IsViewPressed()) { - Windows::ApplicationModel::Core::CoreApplication::Exit(); + ExitSample(); } if (m_gamePadButtons.a == GamePad::ButtonStateTracker::ButtonState::PRESSED) @@ -173,7 +175,7 @@ void Sample::Update(DX::StepTimer const& timer) if (kb.Escape) { - Windows::ApplicationModel::Core::CoreApplication::Exit(); + ExitSample(); } if (m_keyboardButtons.IsKeyPressed(Keyboard::Q)) diff --git a/Samples/IntroGraphics/SimpleInstancingUWP/SimpleInstancing.vcxproj b/Samples/IntroGraphics/SimpleInstancingUWP/SimpleInstancing.vcxproj index e4edc140..9ff2f21e 100644 --- a/Samples/IntroGraphics/SimpleInstancingUWP/SimpleInstancing.vcxproj +++ b/Samples/IntroGraphics/SimpleInstancingUWP/SimpleInstancing.vcxproj @@ -98,7 +98,7 @@ false - false + false diff --git a/Samples/IntroGraphics/SimpleInstancingUWP/pch.h b/Samples/IntroGraphics/SimpleInstancingUWP/pch.h index 0eaffaf8..1efec9ca 100644 --- a/Samples/IntroGraphics/SimpleInstancingUWP/pch.h +++ b/Samples/IntroGraphics/SimpleInstancingUWP/pch.h @@ -15,7 +15,7 @@ #include #include -#include +#include #include #include diff --git a/Samples/IntroGraphics/SimpleInstancingUWP12/DeviceResources.cpp b/Samples/IntroGraphics/SimpleInstancingUWP12/DeviceResources.cpp index a77ccff2..5e3a68f6 100644 --- a/Samples/IntroGraphics/SimpleInstancingUWP12/DeviceResources.cpp +++ b/Samples/IntroGraphics/SimpleInstancingUWP12/DeviceResources.cpp @@ -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), @@ -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) @@ -99,7 +100,9 @@ DX::DeviceResources::~DeviceResources() void DX::DeviceResources::CreateDeviceResources() { #if defined(_DEBUG) - // Enable the debug layer (only available if the Graphics Tools feature-on-demand is enabled). + // Enable the debug layer (requires the Graphics Tools "optional feature"). + // + // NOTE: Enabling the debug layer after device creation will invalidate the active device. bool debugDXGI = false; { ComPtr debugController; @@ -129,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 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 adapter; GetAdapter(adapter.GetAddressOf()); @@ -262,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) @@ -298,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 swapChain; @@ -554,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) @@ -655,7 +689,7 @@ void DX::DeviceResources::GetAdapter(IDXGIAdapter1** ppAdapter) // Try WARP12 instead if (FAILED(m_dxgiFactory->EnumWarpAdapter(IID_PPV_ARGS(adapter.ReleaseAndGetAddressOf())))) { - throw std::exception("WARP12 not available. Enable the 'Graphics Tools' feature-on-demand"); + throw std::exception("WARP12 not available. Enable the 'Graphics Tools' optional feature"); } OutputDebugStringA("Direct3D Adapter - WARP12\n"); diff --git a/Samples/IntroGraphics/SimpleInstancingUWP12/DeviceResources.h b/Samples/IntroGraphics/SimpleInstancingUWP12/DeviceResources.h index 5eaa373a..a52a8c70 100644 --- a/Samples/IntroGraphics/SimpleInstancingUWP12/DeviceResources.h +++ b/Samples/IntroGraphics/SimpleInstancingUWP12/DeviceResources.h @@ -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(); @@ -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 { @@ -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; diff --git a/Samples/IntroGraphics/SimpleInstancingUWP12/Main.cpp b/Samples/IntroGraphics/SimpleInstancingUWP12/Main.cpp index fab98e63..fc55dc30 100644 --- a/Samples/IntroGraphics/SimpleInstancingUWP12/Main.cpp +++ b/Samples/IntroGraphics/SimpleInstancingUWP12/Main.cpp @@ -210,7 +210,7 @@ ref class ViewProvider sealed : public IFrameworkView void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) { - SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral(); + auto deferral = args->SuspendingOperation->GetDeferral(); create_task([this, deferral]() { @@ -411,10 +411,8 @@ ref class ViewProviderFactory : IFrameworkViewSource // Entry point [Platform::MTAThread] -int main(Platform::Array^ argv) +int __cdecl main(Platform::Array^ /*argv*/) { - UNREFERENCED_PARAMETER(argv); - if (!XMVerifyCPUSupport()) { throw std::exception("XMVerifyCPUSupport"); @@ -424,3 +422,10 @@ int main(Platform::Array^ argv) CoreApplication::Run(viewProviderFactory); return 0; } + + +// Exit helper +void ExitSample() +{ + Windows::ApplicationModel::Core::CoreApplication::Exit(); +} \ No newline at end of file diff --git a/Samples/IntroGraphics/SimpleInstancingUWP12/Readme.docx b/Samples/IntroGraphics/SimpleInstancingUWP12/Readme.docx index 051df83b..216d6641 100644 Binary files a/Samples/IntroGraphics/SimpleInstancingUWP12/Readme.docx and b/Samples/IntroGraphics/SimpleInstancingUWP12/Readme.docx differ diff --git a/Samples/IntroGraphics/SimpleInstancingUWP12/SimpleInstancing12.cpp b/Samples/IntroGraphics/SimpleInstancingUWP12/SimpleInstancing12.cpp index f462839c..eabb6288 100644 --- a/Samples/IntroGraphics/SimpleInstancingUWP12/SimpleInstancing12.cpp +++ b/Samples/IntroGraphics/SimpleInstancingUWP12/SimpleInstancing12.cpp @@ -12,6 +12,8 @@ #include "ControllerFont.h" #include "ReadData.h" +extern void ExitSample(); + #pragma warning(disable : 4238) using namespace DirectX; @@ -114,7 +116,7 @@ void Sample::Update(DX::StepTimer const& timer) if (pad.IsViewPressed()) { - Windows::ApplicationModel::Core::CoreApplication::Exit(); + ExitSample(); } if (m_gamePadButtons.a == GamePad::ButtonStateTracker::ButtonState::PRESSED) @@ -182,7 +184,7 @@ void Sample::Update(DX::StepTimer const& timer) if (kb.Escape) { - Windows::ApplicationModel::Core::CoreApplication::Exit(); + ExitSample(); } if (m_keyboardButtons.IsKeyPressed(Keyboard::Q)) diff --git a/Samples/IntroGraphics/SimpleInstancingUWP12/SimpleInstancing12.vcxproj b/Samples/IntroGraphics/SimpleInstancingUWP12/SimpleInstancing12.vcxproj index ece50797..e2346799 100644 --- a/Samples/IntroGraphics/SimpleInstancingUWP12/SimpleInstancing12.vcxproj +++ b/Samples/IntroGraphics/SimpleInstancingUWP12/SimpleInstancing12.vcxproj @@ -98,7 +98,7 @@ false - false + false diff --git a/Samples/IntroGraphics/SimpleInstancingUWP12/pch.h b/Samples/IntroGraphics/SimpleInstancingUWP12/pch.h index 578e29d6..476d1a49 100644 --- a/Samples/IntroGraphics/SimpleInstancingUWP12/pch.h +++ b/Samples/IntroGraphics/SimpleInstancingUWP12/pch.h @@ -15,7 +15,7 @@ #include #include -#include +#include #include #include diff --git a/Samples/IntroGraphics/SimpleLightingUWP/DeviceResources.cpp b/Samples/IntroGraphics/SimpleLightingUWP/DeviceResources.cpp index d00acd30..6c890acb 100644 --- a/Samples/IntroGraphics/SimpleLightingUWP/DeviceResources.cpp +++ b/Samples/IntroGraphics/SimpleLightingUWP/DeviceResources.cpp @@ -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), @@ -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) { } @@ -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) @@ -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 swapChain; DX::ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( @@ -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 @@ -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 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 adapter; for (UINT adapterIndex = 0; DXGI_ERROR_NOT_FOUND != dxgiFactory->EnumAdapters1(adapterIndex, adapter.ReleaseAndGetAddressOf()); adapterIndex++) { diff --git a/Samples/IntroGraphics/SimpleLightingUWP/DeviceResources.h b/Samples/IntroGraphics/SimpleLightingUWP/DeviceResources.h index ed0f0874..8d8f8837 100644 --- a/Samples/IntroGraphics/SimpleLightingUWP/DeviceResources.h +++ b/Samples/IntroGraphics/SimpleLightingUWP/DeviceResources.h @@ -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(); @@ -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); @@ -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; }; diff --git a/Samples/IntroGraphics/SimpleLightingUWP/Main.cpp b/Samples/IntroGraphics/SimpleLightingUWP/Main.cpp index b623b35e..b190c47c 100644 --- a/Samples/IntroGraphics/SimpleLightingUWP/Main.cpp +++ b/Samples/IntroGraphics/SimpleLightingUWP/Main.cpp @@ -208,7 +208,7 @@ ref class ViewProvider sealed : public IFrameworkView void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) { - SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral(); + auto deferral = args->SuspendingOperation->GetDeferral(); create_task([this, deferral]() { @@ -407,10 +407,8 @@ ref class ViewProviderFactory : IFrameworkViewSource // Entry point [Platform::MTAThread] -int main(Platform::Array^ argv) +int __cdecl main(Platform::Array^ /*argv*/) { - UNREFERENCED_PARAMETER(argv); - if (!XMVerifyCPUSupport()) { throw std::exception("XMVerifyCPUSupport"); @@ -420,3 +418,10 @@ int main(Platform::Array^ argv) CoreApplication::Run(viewProviderFactory); return 0; } + + +// Exit helper +void ExitSample() +{ + Windows::ApplicationModel::Core::CoreApplication::Exit(); +} \ No newline at end of file diff --git a/Samples/IntroGraphics/SimpleLightingUWP/Readme.docx b/Samples/IntroGraphics/SimpleLightingUWP/Readme.docx index 08f3d2ba..cd5ce5ab 100644 Binary files a/Samples/IntroGraphics/SimpleLightingUWP/Readme.docx and b/Samples/IntroGraphics/SimpleLightingUWP/Readme.docx differ diff --git a/Samples/IntroGraphics/SimpleLightingUWP/SimpleLightingUWP.cpp b/Samples/IntroGraphics/SimpleLightingUWP/SimpleLightingUWP.cpp index 9390edba..86ff3890 100644 --- a/Samples/IntroGraphics/SimpleLightingUWP/SimpleLightingUWP.cpp +++ b/Samples/IntroGraphics/SimpleLightingUWP/SimpleLightingUWP.cpp @@ -10,6 +10,8 @@ #include "ATGColors.h" #include "ReadData.h" +extern void ExitSample(); + using namespace DirectX; using Microsoft::WRL::ComPtr; @@ -110,7 +112,7 @@ void Sample::Update(DX::StepTimer const& timer) if (pad.IsViewPressed()) { - Windows::ApplicationModel::Core::CoreApplication::Exit(); + ExitSample(); } } else @@ -123,7 +125,7 @@ void Sample::Update(DX::StepTimer const& timer) if (kb.Escape) { - Windows::ApplicationModel::Core::CoreApplication::Exit(); + ExitSample(); } PIXEndEvent(); diff --git a/Samples/IntroGraphics/SimpleLightingUWP/SimpleLightingUWP.vcxproj b/Samples/IntroGraphics/SimpleLightingUWP/SimpleLightingUWP.vcxproj index abc916d0..1373fef9 100644 --- a/Samples/IntroGraphics/SimpleLightingUWP/SimpleLightingUWP.vcxproj +++ b/Samples/IntroGraphics/SimpleLightingUWP/SimpleLightingUWP.vcxproj @@ -99,7 +99,7 @@ false - false + false diff --git a/Samples/IntroGraphics/SimpleLightingUWP/pch.h b/Samples/IntroGraphics/SimpleLightingUWP/pch.h index a0123a9b..127e6ab3 100644 --- a/Samples/IntroGraphics/SimpleLightingUWP/pch.h +++ b/Samples/IntroGraphics/SimpleLightingUWP/pch.h @@ -15,7 +15,7 @@ #include #include -#include +#include #include #include diff --git a/Samples/IntroGraphics/SimpleLightingUWP12/DeviceResources.cpp b/Samples/IntroGraphics/SimpleLightingUWP12/DeviceResources.cpp index a77ccff2..5e3a68f6 100644 --- a/Samples/IntroGraphics/SimpleLightingUWP12/DeviceResources.cpp +++ b/Samples/IntroGraphics/SimpleLightingUWP12/DeviceResources.cpp @@ -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), @@ -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) @@ -99,7 +100,9 @@ DX::DeviceResources::~DeviceResources() void DX::DeviceResources::CreateDeviceResources() { #if defined(_DEBUG) - // Enable the debug layer (only available if the Graphics Tools feature-on-demand is enabled). + // Enable the debug layer (requires the Graphics Tools "optional feature"). + // + // NOTE: Enabling the debug layer after device creation will invalidate the active device. bool debugDXGI = false; { ComPtr debugController; @@ -129,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 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 adapter; GetAdapter(adapter.GetAddressOf()); @@ -262,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) @@ -298,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 swapChain; @@ -554,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) @@ -655,7 +689,7 @@ void DX::DeviceResources::GetAdapter(IDXGIAdapter1** ppAdapter) // Try WARP12 instead if (FAILED(m_dxgiFactory->EnumWarpAdapter(IID_PPV_ARGS(adapter.ReleaseAndGetAddressOf())))) { - throw std::exception("WARP12 not available. Enable the 'Graphics Tools' feature-on-demand"); + throw std::exception("WARP12 not available. Enable the 'Graphics Tools' optional feature"); } OutputDebugStringA("Direct3D Adapter - WARP12\n"); diff --git a/Samples/IntroGraphics/SimpleLightingUWP12/DeviceResources.h b/Samples/IntroGraphics/SimpleLightingUWP12/DeviceResources.h index 5eaa373a..a52a8c70 100644 --- a/Samples/IntroGraphics/SimpleLightingUWP12/DeviceResources.h +++ b/Samples/IntroGraphics/SimpleLightingUWP12/DeviceResources.h @@ -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(); @@ -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 { @@ -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; diff --git a/Samples/IntroGraphics/SimpleLightingUWP12/Main.cpp b/Samples/IntroGraphics/SimpleLightingUWP12/Main.cpp index c18b8c17..2f65e5ca 100644 --- a/Samples/IntroGraphics/SimpleLightingUWP12/Main.cpp +++ b/Samples/IntroGraphics/SimpleLightingUWP12/Main.cpp @@ -208,7 +208,7 @@ ref class ViewProvider sealed : public IFrameworkView void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) { - SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral(); + auto deferral = args->SuspendingOperation->GetDeferral(); create_task([this, deferral]() { @@ -407,10 +407,8 @@ ref class ViewProviderFactory : IFrameworkViewSource // Entry point [Platform::MTAThread] -int main(Platform::Array^ argv) +int __cdecl main(Platform::Array^ /*argv*/) { - UNREFERENCED_PARAMETER(argv); - if (!XMVerifyCPUSupport()) { throw std::exception("XMVerifyCPUSupport"); @@ -420,3 +418,10 @@ int main(Platform::Array^ argv) CoreApplication::Run(viewProviderFactory); return 0; } + + +// Exit helper +void ExitSample() +{ + Windows::ApplicationModel::Core::CoreApplication::Exit(); +} diff --git a/Samples/IntroGraphics/SimpleLightingUWP12/Readme.docx b/Samples/IntroGraphics/SimpleLightingUWP12/Readme.docx index 4474f635..17260fc6 100644 Binary files a/Samples/IntroGraphics/SimpleLightingUWP12/Readme.docx and b/Samples/IntroGraphics/SimpleLightingUWP12/Readme.docx differ diff --git a/Samples/IntroGraphics/SimpleLightingUWP12/SimpleLightingUWP12.cpp b/Samples/IntroGraphics/SimpleLightingUWP12/SimpleLightingUWP12.cpp index 0280ed3c..96b746ff 100644 --- a/Samples/IntroGraphics/SimpleLightingUWP12/SimpleLightingUWP12.cpp +++ b/Samples/IntroGraphics/SimpleLightingUWP12/SimpleLightingUWP12.cpp @@ -11,6 +11,8 @@ #include "ATGColors.h" #include "ReadData.h" +extern void ExitSample(); + using namespace DirectX; using Microsoft::WRL::ComPtr; @@ -106,7 +108,7 @@ void Sample::Update(DX::StepTimer const& timer) if (pad.IsViewPressed()) { - Windows::ApplicationModel::Core::CoreApplication::Exit(); + ExitSample(); } } else @@ -119,7 +121,7 @@ void Sample::Update(DX::StepTimer const& timer) if (kb.Escape) { - Windows::ApplicationModel::Core::CoreApplication::Exit(); + ExitSample(); } PIXEndEvent(); diff --git a/Samples/IntroGraphics/SimpleLightingUWP12/SimpleLightingUWP12.vcxproj b/Samples/IntroGraphics/SimpleLightingUWP12/SimpleLightingUWP12.vcxproj index 33e9d4b4..79f9b1ef 100644 --- a/Samples/IntroGraphics/SimpleLightingUWP12/SimpleLightingUWP12.vcxproj +++ b/Samples/IntroGraphics/SimpleLightingUWP12/SimpleLightingUWP12.vcxproj @@ -99,7 +99,7 @@ false - false + false diff --git a/Samples/IntroGraphics/SimpleLightingUWP12/pch.h b/Samples/IntroGraphics/SimpleLightingUWP12/pch.h index f833ce4d..2c38fd9d 100644 --- a/Samples/IntroGraphics/SimpleLightingUWP12/pch.h +++ b/Samples/IntroGraphics/SimpleLightingUWP12/pch.h @@ -15,7 +15,7 @@ #include #include -#include +#include #include #include diff --git a/Samples/IntroGraphics/SimpleMSAA_UWP/Assets/Logo.png b/Samples/IntroGraphics/SimpleMSAA_UWP/Assets/Logo.png new file mode 100644 index 00000000..6e7e704a Binary files /dev/null and b/Samples/IntroGraphics/SimpleMSAA_UWP/Assets/Logo.png differ diff --git a/Samples/IntroGraphics/SimpleMSAA_UWP/Assets/SmallLogo.png b/Samples/IntroGraphics/SimpleMSAA_UWP/Assets/SmallLogo.png new file mode 100644 index 00000000..98b09d91 Binary files /dev/null and b/Samples/IntroGraphics/SimpleMSAA_UWP/Assets/SmallLogo.png differ diff --git a/Samples/IntroGraphics/SimpleMSAA_UWP/Assets/SplashScreen.png b/Samples/IntroGraphics/SimpleMSAA_UWP/Assets/SplashScreen.png new file mode 100644 index 00000000..c352b156 Binary files /dev/null and b/Samples/IntroGraphics/SimpleMSAA_UWP/Assets/SplashScreen.png differ diff --git a/Samples/IntroGraphics/SimpleMSAA_UWP/Assets/StoreLogo.png b/Samples/IntroGraphics/SimpleMSAA_UWP/Assets/StoreLogo.png new file mode 100644 index 00000000..315472e1 Binary files /dev/null and b/Samples/IntroGraphics/SimpleMSAA_UWP/Assets/StoreLogo.png differ diff --git a/Samples/IntroGraphics/SimpleMSAA_UWP/Assets/WideLogo.png b/Samples/IntroGraphics/SimpleMSAA_UWP/Assets/WideLogo.png new file mode 100644 index 00000000..c70f68e2 Binary files /dev/null and b/Samples/IntroGraphics/SimpleMSAA_UWP/Assets/WideLogo.png differ diff --git a/Samples/IntroGraphics/SimpleMSAA_UWP/DeviceResources.cpp b/Samples/IntroGraphics/SimpleMSAA_UWP/DeviceResources.cpp new file mode 100644 index 00000000..6c890acb --- /dev/null +++ b/Samples/IntroGraphics/SimpleMSAA_UWP/DeviceResources.cpp @@ -0,0 +1,633 @@ +// +// DeviceResources.cpp - A wrapper for the Direct3D 11 device and swapchain +// (requires DirectX 11.3 Runtime) +// + + +#include "pch.h" +#include "DeviceResources.h" + +using namespace DirectX; + +using Microsoft::WRL::ComPtr; + +namespace +{ +#if defined(_DEBUG) + // Check for SDK Layer support. + inline bool SdkLayersAvailable() + { + HRESULT hr = D3D11CreateDevice( + nullptr, + D3D_DRIVER_TYPE_NULL, // There is no need to create a real hardware device. + 0, + D3D11_CREATE_DEVICE_DEBUG, // Check for the SDK layers. + nullptr, // Any feature level will do. + 0, + D3D11_SDK_VERSION, + nullptr, // No need to keep the D3D device reference. + nullptr, // No need to know the feature level. + nullptr // No need to keep the D3D device context reference. + ); + + return SUCCEEDED(hr); + } +#endif + + inline DXGI_FORMAT NoSRGB(DXGI_FORMAT fmt) + { + switch (fmt) + { + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: return DXGI_FORMAT_R8G8B8A8_UNORM; + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: return DXGI_FORMAT_B8G8R8A8_UNORM; + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: return DXGI_FORMAT_B8G8R8X8_UNORM; + default: return fmt; + } + } +}; + +// Constants used to calculate screen rotations +namespace ScreenRotation +{ + // 0-degree Z-rotation + static const XMFLOAT4X4 Rotation0( + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + ); + + // 90-degree Z-rotation + static const XMFLOAT4X4 Rotation90( + 0.0f, 1.0f, 0.0f, 0.0f, + -1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + ); + + // 180-degree Z-rotation + static const XMFLOAT4X4 Rotation180( + -1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, -1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + ); + + // 270-degree Z-rotation + static const XMFLOAT4X4 Rotation270( + 0.0f, -1.0f, 0.0f, 0.0f, + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + ); +}; + +// Constructor for DeviceResources. +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), + m_backBufferCount(backBufferCount), + m_d3dMinFeatureLevel(minFeatureLevel), + m_window(nullptr), + m_d3dFeatureLevel(D3D_FEATURE_LEVEL_9_1), + m_rotation(DXGI_MODE_ROTATION_IDENTITY), + m_outputSize{0, 0, 1, 1}, + m_orientationTransform3D(ScreenRotation::Rotation0), + m_options(flags), + m_deviceNotify(nullptr) +{ +} + +// Configures the Direct3D device, and stores handles to it and the device context. +void DX::DeviceResources::CreateDeviceResources() +{ + UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; + +#if defined(_DEBUG) + if (SdkLayersAvailable()) + { + // If the project is in a debug build, enable debugging via SDK Layers with this flag. + creationFlags |= D3D11_CREATE_DEVICE_DEBUG; + } + else + { + OutputDebugStringA("WARNING: Direct3D Debug Device is not available\n"); + } +#endif + + // Determine DirectX hardware feature levels this app will support. + static const D3D_FEATURE_LEVEL s_featureLevels[] = + { + D3D_FEATURE_LEVEL_12_1, + D3D_FEATURE_LEVEL_12_0, + D3D_FEATURE_LEVEL_11_1, + D3D_FEATURE_LEVEL_11_0, + D3D_FEATURE_LEVEL_10_1, + D3D_FEATURE_LEVEL_10_0, + D3D_FEATURE_LEVEL_9_3, + D3D_FEATURE_LEVEL_9_2, + D3D_FEATURE_LEVEL_9_1, + }; + + UINT featLevelCount = 0; + for (; featLevelCount < _countof(s_featureLevels); ++featLevelCount) + { + if (s_featureLevels[featLevelCount] < m_d3dMinFeatureLevel) + break; + } + + if (!featLevelCount) + { + throw std::out_of_range("minFeatureLevel too high"); + } + + ComPtr adapter; + GetHardwareAdapter(adapter.GetAddressOf()); + + // Create the Direct3D 11 API device object and a corresponding context. + ComPtr device; + ComPtr context; + + HRESULT hr = E_FAIL; + if (adapter) + { + hr = D3D11CreateDevice( + adapter.Get(), + D3D_DRIVER_TYPE_UNKNOWN, + 0, + creationFlags, // Set debug and Direct2D compatibility flags. + s_featureLevels, + featLevelCount, + D3D11_SDK_VERSION, + device.GetAddressOf(), // Returns the Direct3D device created. + &m_d3dFeatureLevel, // Returns feature level of device created. + context.GetAddressOf() // Returns the device immediate context. + ); + } +#if defined(NDEBUG) + else + { + throw std::exception("No Direct3D hardware device found"); + } +#else + if (FAILED(hr)) + { + // If the initialization fails, fall back to the WARP device. + // For more information on WARP, see: + // http://go.microsoft.com/fwlink/?LinkId=286690 + hr = D3D11CreateDevice( + nullptr, + D3D_DRIVER_TYPE_WARP, // Create a WARP device instead of a hardware device. + 0, + creationFlags, + s_featureLevels, + featLevelCount, + D3D11_SDK_VERSION, + device.GetAddressOf(), + &m_d3dFeatureLevel, + context.GetAddressOf() + ); + + if (SUCCEEDED(hr)) + { + OutputDebugStringA("Direct3D Adapter - WARP\n"); + } + } +#endif + + DX::ThrowIfFailed(hr); + +#ifndef NDEBUG + ComPtr d3dDebug; + if (SUCCEEDED(device.As(&d3dDebug))) + { + ComPtr d3dInfoQueue; + if (SUCCEEDED(d3dDebug.As(&d3dInfoQueue))) + { +#ifdef _DEBUG + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_CORRUPTION, true); + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, true); +#endif + D3D11_MESSAGE_ID hide[] = + { + D3D11_MESSAGE_ID_SETPRIVATEDATA_CHANGINGPARAMS, + }; + D3D11_INFO_QUEUE_FILTER filter = {}; + filter.DenyList.NumIDs = _countof(hide); + filter.DenyList.pIDList = hide; + d3dInfoQueue->AddStorageFilterEntries(&filter); + } + } +#endif + + DX::ThrowIfFailed(device.As(&m_d3dDevice)); + DX::ThrowIfFailed(context.As(&m_d3dContext)); +} + +// These resources need to be recreated every time the window size is changed. +void DX::DeviceResources::CreateWindowSizeDependentResources() +{ + if (!m_window) + { + throw std::exception("Call SetWindow with a valid CoreWindow pointer"); + } + + // Clear the previous window size specific context. + ID3D11RenderTargetView* nullViews[] = {nullptr}; + m_d3dContext->OMSetRenderTargets(_countof(nullViews), nullViews, nullptr); + m_d3dRenderTargetView.Reset(); + m_d3dDepthStencilView.Reset(); + m_renderTarget.Reset(); + m_depthStencil.Reset(); + m_d3dContext->Flush(); + + // Determine the render target size in pixels. + UINT backBufferWidth = std::max(m_outputSize.right - m_outputSize.left, 1); + UINT backBufferHeight = std::max(m_outputSize.bottom - m_outputSize.top, 1); + DXGI_FORMAT backBufferFormat = NoSRGB(m_backBufferFormat); + + if (m_swapChain) + { + // If the swap chain already exists, resize it. + HRESULT hr = m_swapChain->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + backBufferFormat, + (m_options & c_AllowTearing) ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0 + ); + + if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) + { +#ifdef _DEBUG + char buff[64] = {}; + sprintf_s(buff, "Device Lost on ResizeBuffers: Reason code 0x%08X\n", (hr == DXGI_ERROR_DEVICE_REMOVED) ? m_d3dDevice->GetDeviceRemovedReason() : hr); + OutputDebugStringA(buff); +#endif + // If the device was removed for any reason, a new device and swap chain will need to be created. + HandleDeviceLost(); + + // Everything is set up now. Do not continue execution of this method. HandleDeviceLost will reenter this method + // and correctly set up the new device. + return; + } + else + { + DX::ThrowIfFailed(hr); + } + } + else + { + // Otherwise, create a new one using the same adapter as the existing Direct3D device. + + // This sequence obtains the DXGI factory that was used to create the Direct3D device above. + ComPtr dxgiDevice; + DX::ThrowIfFailed(m_d3dDevice.As(&dxgiDevice)); + + ComPtr dxgiAdapter; + DX::ThrowIfFailed(dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf())); + + ComPtr dxgiFactory; + DX::ThrowIfFailed(dxgiAdapter->GetParent(IID_PPV_ARGS(dxgiFactory.GetAddressOf()))); + + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; + swapChainDesc.Width = backBufferWidth; + swapChainDesc.Height = backBufferHeight; + swapChainDesc.Format = backBufferFormat; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = m_backBufferCount; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + 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 swapChain; + DX::ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), + m_window, + &swapChainDesc, + nullptr, + swapChain.GetAddressOf() + )); + + DX::ThrowIfFailed(swapChain.As(&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 power consumption. + DX::ThrowIfFailed(dxgiDevice->SetMaximumFrameLatency(1)); + } + + // Set the proper orientation for the swap chain, and generate + // matrix transformations for rendering to the rotated swap chain. + switch (m_rotation) + { + default: + case DXGI_MODE_ROTATION_IDENTITY: + m_orientationTransform3D = ScreenRotation::Rotation0; + break; + + case DXGI_MODE_ROTATION_ROTATE90: + m_orientationTransform3D = ScreenRotation::Rotation270; + break; + + case DXGI_MODE_ROTATION_ROTATE180: + m_orientationTransform3D = ScreenRotation::Rotation180; + break; + + case DXGI_MODE_ROTATION_ROTATE270: + m_orientationTransform3D = ScreenRotation::Rotation90; + break; + } + + DX::ThrowIfFailed(m_swapChain->SetRotation(m_rotation)); + + // Create a render target view of the swap chain back buffer. + DX::ThrowIfFailed(m_swapChain->GetBuffer(0, IID_PPV_ARGS(m_renderTarget.ReleaseAndGetAddressOf()))); + + CD3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc(D3D11_RTV_DIMENSION_TEXTURE2D, m_backBufferFormat); + DX::ThrowIfFailed(m_d3dDevice->CreateRenderTargetView( + m_renderTarget.Get(), + &renderTargetViewDesc, + m_d3dRenderTargetView.ReleaseAndGetAddressOf() + )); + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + // Create a depth stencil view for use with 3D rendering if needed. + CD3D11_TEXTURE2D_DESC depthStencilDesc( + m_depthBufferFormat, + backBufferWidth, + backBufferHeight, + 1, // This depth stencil view has only one texture. + 1, // Use a single mipmap level. + D3D11_BIND_DEPTH_STENCIL + ); + + DX::ThrowIfFailed(m_d3dDevice->CreateTexture2D( + &depthStencilDesc, + nullptr, + m_depthStencil.ReleaseAndGetAddressOf() + )); + + CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2D); + DX::ThrowIfFailed(m_d3dDevice->CreateDepthStencilView( + m_depthStencil.Get(), + &depthStencilViewDesc, + m_d3dDepthStencilView.ReleaseAndGetAddressOf() + )); + } + + // Set the 3D rendering viewport to target the entire window. + m_screenViewport = CD3D11_VIEWPORT( + 0.0f, + 0.0f, + static_cast(backBufferWidth), + static_cast(backBufferHeight) + ); +} + +// This method is called when the CoreWindow is created (or re-created). +void DX::DeviceResources::SetWindow(IUnknown* window, int width, int height, DXGI_MODE_ROTATION rotation) +{ + m_window = window; + + m_outputSize.left = m_outputSize.top = 0; + m_outputSize.right = width; + m_outputSize.bottom = height; + + m_rotation = rotation; +} + +// This method is called when the window changes size +bool DX::DeviceResources::WindowSizeChanged(int width, int height, DXGI_MODE_ROTATION rotation) +{ + RECT newRc; + newRc.left = newRc.top = 0; + newRc.right = width; + newRc.bottom = height; + if (newRc == m_outputSize && rotation == m_rotation) + { + return false; + } + + m_outputSize = newRc; + m_rotation = rotation; + CreateWindowSizeDependentResources(); + return true; +} + +// This method is called in the event handler for the DisplayContentsInvalidated event. +void DX::DeviceResources::ValidateDevice() +{ + // The D3D Device is no longer valid if the default adapter changed since the device + // was created or if the device has been removed. + + DXGI_ADAPTER_DESC previousDesc; + { + ComPtr dxgiDevice; + DX::ThrowIfFailed(m_d3dDevice.As(&dxgiDevice)); + + ComPtr deviceAdapter; + DX::ThrowIfFailed(dxgiDevice->GetAdapter(deviceAdapter.GetAddressOf())); + + ComPtr deviceFactory; + DX::ThrowIfFailed(deviceAdapter->GetParent(IID_PPV_ARGS(deviceFactory.GetAddressOf()))); + + ComPtr previousDefaultAdapter; + DX::ThrowIfFailed(deviceFactory->EnumAdapters1(0, previousDefaultAdapter.GetAddressOf())); + + DX::ThrowIfFailed(previousDefaultAdapter->GetDesc(&previousDesc)); + } + + DXGI_ADAPTER_DESC currentDesc; + { + ComPtr currentFactory; + DX::ThrowIfFailed(CreateDXGIFactory1(IID_PPV_ARGS(currentFactory.GetAddressOf()))); + + ComPtr currentDefaultAdapter; + DX::ThrowIfFailed(currentFactory->EnumAdapters1(0, currentDefaultAdapter.GetAddressOf())); + + DX::ThrowIfFailed(currentDefaultAdapter->GetDesc(¤tDesc)); + } + + // If the adapter LUIDs don't match, or if the device reports that it has been removed, + // a new D3D device must be created. + + if (previousDesc.AdapterLuid.LowPart != currentDesc.AdapterLuid.LowPart + || previousDesc.AdapterLuid.HighPart != currentDesc.AdapterLuid.HighPart + || FAILED(m_d3dDevice->GetDeviceRemovedReason())) + { +#ifdef _DEBUG + OutputDebugStringA("Device Lost on ValidateDevice\n"); +#endif + + // Create a new device and swap chain. + HandleDeviceLost(); + } +} + +// Recreate all device resources and set them back to the current state. +void DX::DeviceResources::HandleDeviceLost() +{ + if (m_deviceNotify) + { + m_deviceNotify->OnDeviceLost(); + } + + m_d3dDepthStencilView.Reset(); + m_d3dRenderTargetView.Reset(); + m_renderTarget.Reset(); + m_depthStencil.Reset(); + m_swapChain.Reset(); + m_d3dContext.Reset(); + m_d3dDevice.Reset(); + +#ifdef _DEBUG + { + ComPtr dxgiDebug; + if (SUCCEEDED(DXGIGetDebugInterface1(0, IID_PPV_ARGS(&dxgiDebug)))) + { + dxgiDebug->ReportLiveObjects(DXGI_DEBUG_ALL, DXGI_DEBUG_RLO_FLAGS(DXGI_DEBUG_RLO_SUMMARY | DXGI_DEBUG_RLO_IGNORE_INTERNAL)); + } + } +#endif + + CreateDeviceResources(); + CreateWindowSizeDependentResources(); + + if (m_deviceNotify) + { + m_deviceNotify->OnDeviceRestored(); + } +} + +// Call this method when the app suspends. It provides a hint to the driver that the app +// is entering an idle state and that temporary buffers can be reclaimed for use by other apps. +void DX::DeviceResources::Trim() +{ + ComPtr dxgiDevice; + if (SUCCEEDED(m_d3dDevice.As(&dxgiDevice))) + { + dxgiDevice->Trim(); + } +} + +// Present the contents of the swap chain to the screen. +void DX::DeviceResources::Present() +{ + 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 + // overwritten. If dirty or scroll rects are used, this call should be removed. + m_d3dContext->DiscardView(m_d3dRenderTargetView.Get()); + + if (m_d3dDepthStencilView) + { + // Discard the contents of the depth stencil. + m_d3dContext->DiscardView(m_d3dDepthStencilView.Get()); + } + + // If the device was removed either by a disconnection or a driver upgrade, we + // must recreate all device resources. + if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) + { +#ifdef _DEBUG + char buff[64] = {}; + sprintf_s(buff, "Device Lost on Present: Reason code 0x%08X\n", (hr == DXGI_ERROR_DEVICE_REMOVED) ? m_d3dDevice->GetDeviceRemovedReason() : hr); + OutputDebugStringA(buff); +#endif + HandleDeviceLost(); + } + else + { + DX::ThrowIfFailed(hr); + } +} + +// This method acquires the first available hardware adapter. +// If no such adapter can be found, *ppAdapter will be set to nullptr. +void DX::DeviceResources::GetHardwareAdapter(IDXGIAdapter1** ppAdapter) +{ + *ppAdapter = nullptr; + + ComPtr dxgiFactory; +#ifdef _DEBUG + bool debugDXGI = false; + { + ComPtr dxgiInfoQueue; + if (SUCCEEDED(DXGIGetDebugInterface1(0, IID_PPV_ARGS(dxgiInfoQueue.GetAddressOf())))) + { + debugDXGI = true; + + DX::ThrowIfFailed(CreateDXGIFactory2(DXGI_CREATE_FACTORY_DEBUG, IID_PPV_ARGS(dxgiFactory.GetAddressOf()))); + + dxgiInfoQueue->SetBreakOnSeverity(DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_ERROR, true); + dxgiInfoQueue->SetBreakOnSeverity(DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_CORRUPTION, true); + } + } + + if (!debugDXGI) +#endif + + 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 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 adapter; + for (UINT adapterIndex = 0; DXGI_ERROR_NOT_FOUND != dxgiFactory->EnumAdapters1(adapterIndex, adapter.ReleaseAndGetAddressOf()); adapterIndex++) + { + DXGI_ADAPTER_DESC1 desc; + adapter->GetDesc1(&desc); + + if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) + { + // Don't select the Basic Render Driver adapter. + continue; + } + +#ifdef _DEBUG + wchar_t buff[256] = {}; + swprintf_s(buff, L"Direct3D Adapter (%u): VID:%04X, PID:%04X - %ls\n", adapterIndex, desc.VendorId, desc.DeviceId, desc.Description); + OutputDebugStringW(buff); +#endif + + break; + } + + *ppAdapter = adapter.Detach(); +} \ No newline at end of file diff --git a/Samples/IntroGraphics/SimpleMSAA_UWP/DeviceResources.h b/Samples/IntroGraphics/SimpleMSAA_UWP/DeviceResources.h new file mode 100644 index 00000000..8d8f8837 --- /dev/null +++ b/Samples/IntroGraphics/SimpleMSAA_UWP/DeviceResources.h @@ -0,0 +1,94 @@ +// +// DeviceResources.h - A wrapper for the Direct3D 11 device and swapchain +// + +#pragma once + +namespace DX +{ + // Provides an interface for an application that owns DeviceResources to be notified of the device being lost or created. + interface IDeviceNotify + { + virtual void OnDeviceLost() = 0; + virtual void OnDeviceRestored() = 0; + }; + + // Controls all the DirectX device resources. + 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, + unsigned int flags = 0); + + void CreateDeviceResources(); + void CreateWindowSizeDependentResources(); + void SetWindow(IUnknown* window, int width, int height, DXGI_MODE_ROTATION rotation); + bool WindowSizeChanged(int width, int height, DXGI_MODE_ROTATION rotation); + void ValidateDevice(); + void HandleDeviceLost(); + void RegisterDeviceNotify(IDeviceNotify* deviceNotify) { m_deviceNotify = deviceNotify; } + void Trim(); + void Present(); + + // Device Accessors. + RECT GetOutputSize() const { return m_outputSize; } + DXGI_MODE_ROTATION GetRotation() const { return m_rotation; } + + // Direct3D Accessors. + ID3D11Device2* GetD3DDevice() const { return m_d3dDevice.Get(); } + ID3D11DeviceContext2* GetD3DDeviceContext() const { return m_d3dContext.Get(); } + IDXGISwapChain3* GetSwapChain() const { return m_swapChain.Get(); } + D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; } + ID3D11Texture2D* GetRenderTarget() const { return m_renderTarget.Get(); } + ID3D11Texture2D* GetDepthStencil() const { return m_depthStencil.Get(); } + ID3D11RenderTargetView* GetRenderTargetView() const { return m_d3dRenderTargetView.Get(); } + ID3D11DepthStencilView* GetDepthStencilView() const { return m_d3dDepthStencilView.Get(); } + DXGI_FORMAT GetBackBufferFormat() const { return m_backBufferFormat; } + DXGI_FORMAT GetDepthBufferFormat() const { return m_depthBufferFormat; } + 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); + + // Direct3D objects. + Microsoft::WRL::ComPtr m_d3dDevice; + Microsoft::WRL::ComPtr m_d3dContext; + Microsoft::WRL::ComPtr m_swapChain; + + // Direct3D rendering objects. Required for 3D. + Microsoft::WRL::ComPtr m_renderTarget; + Microsoft::WRL::ComPtr m_depthStencil; + Microsoft::WRL::ComPtr m_d3dRenderTargetView; + Microsoft::WRL::ComPtr m_d3dDepthStencilView; + D3D11_VIEWPORT m_screenViewport; + + // Direct3D properties. + DXGI_FORMAT m_backBufferFormat; + DXGI_FORMAT m_depthBufferFormat; + UINT m_backBufferCount; + D3D_FEATURE_LEVEL m_d3dMinFeatureLevel; + + // Cached device properties. + IUnknown* m_window; + D3D_FEATURE_LEVEL m_d3dFeatureLevel; + DXGI_MODE_ROTATION m_rotation; + RECT m_outputSize; + + // 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; + }; +} \ No newline at end of file diff --git a/Samples/IntroGraphics/SimpleMSAA_UWP/Main.cpp b/Samples/IntroGraphics/SimpleMSAA_UWP/Main.cpp new file mode 100644 index 00000000..e3db753a --- /dev/null +++ b/Samples/IntroGraphics/SimpleMSAA_UWP/Main.cpp @@ -0,0 +1,431 @@ +//-------------------------------------------------------------------------------------- +// Main.cpp +// +// Entry point for Universal Windows Platform (UWP) app. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SimpleMSAA.h" + +#include "Telemetry.h" + +#include + +using namespace concurrency; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Core; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::UI::Core; +using namespace Windows::UI::Input; +using namespace Windows::UI::ViewManagement; +using namespace Windows::System; +using namespace Windows::Foundation; +using namespace Windows::Graphics::Display; +using namespace DirectX; + +ref class ViewProvider sealed : public IFrameworkView +{ +public: + ViewProvider() : + m_exit(false), + m_visible(true), + m_in_sizemove(false), + m_DPI(96.f), + m_logicalWidth(800.f), + m_logicalHeight(600.f), + m_nativeOrientation(DisplayOrientations::None), + m_currentOrientation(DisplayOrientations::None) + { + } + + // IFrameworkView methods + virtual void Initialize(CoreApplicationView^ applicationView) + { + applicationView->Activated += + ref new TypedEventHandler(this, &ViewProvider::OnActivated); + + CoreApplication::Suspending += + ref new EventHandler(this, &ViewProvider::OnSuspending); + + CoreApplication::Resuming += + ref new EventHandler(this, &ViewProvider::OnResuming); + + m_sample = std::make_unique(); + + // Sample Usage Telemetry + // + // Disable or remove this code block to opt-out of sample usage telemetry + // + if (ATG::EventRegisterATGSampleTelemetry() == ERROR_SUCCESS) + { + wchar_t exeName[MAX_PATH + 1] = {}; + if (!GetModuleFileNameW(nullptr, exeName, MAX_PATH)) + { + wcscpy_s(exeName, L"Unknown"); + } + wchar_t fname[_MAX_FNAME] = {}; + wchar_t ext[_MAX_EXT] = {}; + (void)_wsplitpath_s(exeName, nullptr, 0, nullptr, 0, fname, _MAX_FNAME, ext, _MAX_EXT); + (void)_wmakepath_s(exeName, nullptr, nullptr, fname, ext); // keep only the filename + extension + + ATG::EventWriteSampleLoaded(exeName); + } + } + + virtual void Uninitialize() + { + m_sample.reset(); + } + + virtual void SetWindow(CoreWindow^ window) + { + window->SizeChanged += + ref new TypedEventHandler(this, &ViewProvider::OnWindowSizeChanged); + +#if defined(NTDDI_WIN10_RS2) && (NTDDI_VERSION >= NTDDI_WIN10_RS2) + try + { + window->ResizeStarted += + ref new TypedEventHandler(this, &ViewProvider::OnResizeStarted); + + window->ResizeCompleted += + ref new TypedEventHandler(this, &ViewProvider::OnResizeCompleted); + } + catch (...) + { + // Requires Windows 10 Creators Update (10.0.15063) or later + } +#endif + + window->VisibilityChanged += + ref new TypedEventHandler(this, &ViewProvider::OnVisibilityChanged); + + window->Closed += + ref new TypedEventHandler(this, &ViewProvider::OnWindowClosed); + + auto dispatcher = CoreWindow::GetForCurrentThread()->Dispatcher; + + dispatcher->AcceleratorKeyActivated += + ref new TypedEventHandler(this, &ViewProvider::OnAcceleratorKeyActivated); + + auto currentDisplayInformation = DisplayInformation::GetForCurrentView(); + + currentDisplayInformation->DpiChanged += + ref new TypedEventHandler(this, &ViewProvider::OnDpiChanged); + + currentDisplayInformation->OrientationChanged += + ref new TypedEventHandler(this, &ViewProvider::OnOrientationChanged); + + DisplayInformation::DisplayContentsInvalidated += + ref new TypedEventHandler(this, &ViewProvider::OnDisplayContentsInvalidated); + + m_DPI = currentDisplayInformation->LogicalDpi; + + m_logicalWidth = window->Bounds.Width; + m_logicalHeight = window->Bounds.Height; + + m_nativeOrientation = currentDisplayInformation->NativeOrientation; + m_currentOrientation = currentDisplayInformation->CurrentOrientation; + + int outputWidth = ConvertDipsToPixels(m_logicalWidth); + int outputHeight = ConvertDipsToPixels(m_logicalHeight); + + DXGI_MODE_ROTATION rotation = ComputeDisplayRotation(); + + if (rotation == DXGI_MODE_ROTATION_ROTATE90 || rotation == DXGI_MODE_ROTATION_ROTATE270) + { + std::swap(outputWidth, outputHeight); + } + + m_sample->Initialize(reinterpret_cast(window), + outputWidth, outputHeight, rotation ); + + Mouse::SetDpi(m_DPI); + } + + virtual void Load(Platform::String^ entryPoint) + { + } + + virtual void Run() + { + while (!m_exit) + { + if (m_visible) + { + m_sample->Tick(); + + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); + } + else + { + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessOneAndAllPending); + } + } + } + +protected: + // Event handlers + void OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) + { + if (args->Kind == ActivationKind::Launch) + { + auto launchArgs = static_cast(args); + + if (launchArgs->PrelaunchActivated) + { + // Opt-out of Prelaunch + CoreApplication::Exit(); + return; + } + } + + int w, h; + m_sample->GetDefaultSize(w, h); + + m_DPI = DisplayInformation::GetForCurrentView()->LogicalDpi; + + ApplicationView::PreferredLaunchWindowingMode = ApplicationViewWindowingMode::PreferredLaunchViewSize; + // Change to ApplicationViewWindowingMode::FullScreen to default to full screen + + auto desiredSize = Size(ConvertPixelsToDips(w), ConvertPixelsToDips(h)); + + ApplicationView::PreferredLaunchViewSize = desiredSize; + + auto view = ApplicationView::GetForCurrentView(); + + auto minSize = Size(ConvertPixelsToDips(320), ConvertPixelsToDips(200)); + + view->SetPreferredMinSize(minSize); + + CoreWindow::GetForCurrentThread()->Activate(); + + view->FullScreenSystemOverlayMode = FullScreenSystemOverlayMode::Minimal; + + view->TryResizeView(desiredSize); + } + + void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) + { + auto deferral = args->SuspendingOperation->GetDeferral(); + + create_task([this, deferral]() + { + m_sample->OnSuspending(); + + deferral->Complete(); + }); + } + + void OnResuming(Platform::Object^ sender, Platform::Object^ args) + { + m_sample->OnResuming(); + } + + void OnWindowSizeChanged(CoreWindow^ sender, WindowSizeChangedEventArgs^ args) + { + m_logicalWidth = sender->Bounds.Width; + m_logicalHeight = sender->Bounds.Height; + + if (m_in_sizemove) + return; + + HandleWindowSizeChanged(); + } + +#if defined(NTDDI_WIN10_RS2) && (NTDDI_VERSION >= NTDDI_WIN10_RS2) + void OnResizeStarted(CoreWindow^ sender, Platform::Object^ args) + { + m_in_sizemove = true; + } + + void OnResizeCompleted(CoreWindow^ sender, Platform::Object^ args) + { + m_in_sizemove = false; + + HandleWindowSizeChanged(); + } +#endif + + void OnVisibilityChanged(CoreWindow^ sender, VisibilityChangedEventArgs^ args) + { + m_visible = args->Visible; + if (m_visible) + m_sample->OnActivated(); + else + m_sample->OnDeactivated(); + } + + void OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) + { + m_exit = true; + } + + void OnAcceleratorKeyActivated(CoreDispatcher^, AcceleratorKeyEventArgs^ args) + { + if (args->EventType == CoreAcceleratorKeyEventType::SystemKeyDown + && args->VirtualKey == VirtualKey::Enter + && args->KeyStatus.IsMenuKeyDown + && !args->KeyStatus.WasKeyDown) + { + // Implements the classic ALT+ENTER fullscreen toggle + auto view = ApplicationView::GetForCurrentView(); + + if (view->IsFullScreenMode) + view->ExitFullScreenMode(); + else + view->TryEnterFullScreenMode(); + + args->Handled = true; + } + } + + void OnDpiChanged(DisplayInformation^ sender, Object^ args) + { + m_DPI = sender->LogicalDpi; + + HandleWindowSizeChanged(); + + Mouse::SetDpi(m_DPI); + } + + void OnOrientationChanged(DisplayInformation^ sender, Object^ args) + { + auto resizeManager = CoreWindowResizeManager::GetForCurrentView(); + resizeManager->ShouldWaitForLayoutCompletion = true; + + m_currentOrientation = sender->CurrentOrientation; + + HandleWindowSizeChanged(); + + resizeManager->NotifyLayoutCompleted(); + } + + void OnDisplayContentsInvalidated(DisplayInformation^ sender, Object^ args) + { + m_sample->ValidateDevice(); + } + +private: + bool m_exit; + bool m_visible; + bool m_in_sizemove; + float m_DPI; + float m_logicalWidth; + float m_logicalHeight; + std::unique_ptr m_sample; + + Windows::Graphics::Display::DisplayOrientations m_nativeOrientation; + Windows::Graphics::Display::DisplayOrientations m_currentOrientation; + + inline int ConvertDipsToPixels(float dips) const + { + return int(dips * m_DPI / 96.f + 0.5f); + } + + inline float ConvertPixelsToDips(int pixels) const + { + return (float(pixels) * 96.f / m_DPI); + } + + DXGI_MODE_ROTATION ComputeDisplayRotation() const + { + DXGI_MODE_ROTATION rotation = DXGI_MODE_ROTATION_UNSPECIFIED; + + switch (m_nativeOrientation) + { + case DisplayOrientations::Landscape: + switch (m_currentOrientation) + { + case DisplayOrientations::Landscape: + rotation = DXGI_MODE_ROTATION_IDENTITY; + break; + + case DisplayOrientations::Portrait: + rotation = DXGI_MODE_ROTATION_ROTATE270; + break; + + case DisplayOrientations::LandscapeFlipped: + rotation = DXGI_MODE_ROTATION_ROTATE180; + break; + + case DisplayOrientations::PortraitFlipped: + rotation = DXGI_MODE_ROTATION_ROTATE90; + break; + } + break; + + case DisplayOrientations::Portrait: + switch (m_currentOrientation) + { + case DisplayOrientations::Landscape: + rotation = DXGI_MODE_ROTATION_ROTATE90; + break; + + case DisplayOrientations::Portrait: + rotation = DXGI_MODE_ROTATION_IDENTITY; + break; + + case DisplayOrientations::LandscapeFlipped: + rotation = DXGI_MODE_ROTATION_ROTATE270; + break; + + case DisplayOrientations::PortraitFlipped: + rotation = DXGI_MODE_ROTATION_ROTATE180; + break; + } + break; + } + + return rotation; + } + + void HandleWindowSizeChanged() + { + int outputWidth = ConvertDipsToPixels(m_logicalWidth); + int outputHeight = ConvertDipsToPixels(m_logicalHeight); + + DXGI_MODE_ROTATION rotation = ComputeDisplayRotation(); + + if (rotation == DXGI_MODE_ROTATION_ROTATE90 || rotation == DXGI_MODE_ROTATION_ROTATE270) + { + std::swap(outputWidth, outputHeight); + } + + m_sample->OnWindowSizeChanged(outputWidth, outputHeight, rotation); + } +}; + +ref class ViewProviderFactory : IFrameworkViewSource +{ +public: + virtual IFrameworkView^ CreateView() + { + return ref new ViewProvider(); + } +}; + + +// Entry point +[Platform::MTAThread] +int __cdecl main(Platform::Array^ /*argv*/) +{ + if (!XMVerifyCPUSupport()) + { + throw std::exception("XMVerifyCPUSupport"); + } + + auto viewProviderFactory = ref new ViewProviderFactory(); + CoreApplication::Run(viewProviderFactory); + return 0; +} + + +// Exit helper +void ExitSample() +{ + Windows::ApplicationModel::Core::CoreApplication::Exit(); +} diff --git a/Samples/IntroGraphics/SimpleMSAA_UWP/Package.appxmanifest b/Samples/IntroGraphics/SimpleMSAA_UWP/Package.appxmanifest new file mode 100644 index 00000000..a1e9bee2 --- /dev/null +++ b/Samples/IntroGraphics/SimpleMSAA_UWP/Package.appxmanifest @@ -0,0 +1,49 @@ + + + + + + + + + + SimpleMSAA + Xbox Advanced Technology Group + Assets\StoreLogo.png + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Samples/IntroGraphics/SimpleMSAA_UWP/Readme.docx b/Samples/IntroGraphics/SimpleMSAA_UWP/Readme.docx new file mode 100644 index 00000000..6f87e2dc Binary files /dev/null and b/Samples/IntroGraphics/SimpleMSAA_UWP/Readme.docx differ diff --git a/Samples/IntroGraphics/SimpleMSAA_UWP/SimpleMSAA.cpp b/Samples/IntroGraphics/SimpleMSAA_UWP/SimpleMSAA.cpp new file mode 100644 index 00000000..bf5e9c85 --- /dev/null +++ b/Samples/IntroGraphics/SimpleMSAA_UWP/SimpleMSAA.cpp @@ -0,0 +1,418 @@ +//-------------------------------------------------------------------------------------- +// SimpleMSAA.cpp +// +// This sample demonstrates setting up a MSAA render target for DirectX 11 +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SimpleMSAA.h" + +#include "ATGColors.h" +#include "ControllerFont.h" + +extern void ExitSample(); + +using namespace DirectX; +using namespace DirectX::SimpleMath; + +using Microsoft::WRL::ComPtr; + +namespace +{ + const DXGI_FORMAT c_backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM_SRGB; + const DXGI_FORMAT c_depthBufferFormat = DXGI_FORMAT_D32_FLOAT; + + // This is a workaround for a bug in the Windows 10 validation layer when using sRGB formats. + const DXGI_FORMAT c_msaaFormat = DXGI_FORMAT_B8G8R8A8_TYPELESS; + const DXGI_FORMAT c_resolveFormat = DXGI_FORMAT_B8G8R8A8_UNORM; + + unsigned int c_targetSampleCount = 4; +} + +Sample::Sample() : + m_sampleCount(0), + m_msaa(true), + m_gamepadPresent(false) +{ + m_deviceResources = std::make_unique( + c_backBufferFormat, + c_depthBufferFormat, /* If we were only doing MSAA rendering, we could skip the non-MSAA depth/stencil buffer with DXGI_FORMAT_UNKNOWN */ + 2); + m_deviceResources->RegisterDeviceNotify(this); + + // + // In Win32 'classic' DirectX 11, you can create the 'swapchain' backbuffer as a multisample buffer. Present took care of the + // resolve as part of the swapchain management. This implicit resolve behavior is not supported for UWP. + // +} + +// Initialize the Direct3D resources required to run. +void Sample::Initialize(::IUnknown* window, int width, int height, DXGI_MODE_ROTATION rotation) +{ + m_gamePad = std::make_unique(); + + m_keyboard = std::make_unique(); + m_keyboard->SetWindow(reinterpret_cast(window)); + + m_deviceResources->SetWindow(window, width, height, rotation); + + m_deviceResources->CreateDeviceResources(); + CreateDeviceDependentResources(); + + m_deviceResources->CreateWindowSizeDependentResources(); + CreateWindowSizeDependentResources(); +} + +#pragma region Frame Update +// Executes basic render loop. +void Sample::Tick() +{ + m_timer.Tick([&]() + { + Update(m_timer); + }); + + Render(); +} + +// Updates the world. +void Sample::Update(DX::StepTimer const& timer) +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Update"); + + float time = float(timer.GetTotalSeconds()); + + m_world = Matrix::CreateRotationZ(cosf(time / 4.f)); + + auto pad = m_gamePad->GetState(0); + m_gamepadPresent = pad.IsConnected(); + if (m_gamepadPresent) + { + m_gamePadButtons.Update(pad); + + if (pad.IsViewPressed()) + { + ExitSample(); + } + + if (m_gamePadButtons.a == GamePad::ButtonStateTracker::PRESSED) + { + m_msaa = !m_msaa; + } + } + else + { + m_gamePadButtons.Reset(); + } + + auto kb = m_keyboard->GetState(); + m_keyboardButtons.Update(kb); + + if (kb.Escape) + { + ExitSample(); + } + + if (m_keyboardButtons.IsKeyPressed(Keyboard::Keys::Space)) + { + m_msaa = !m_msaa; + } + + PIXEndEvent(); +} +#pragma endregion + +#pragma region Frame Render +// Draws the scene. +void Sample::Render() +{ + // Don't try to render anything before the first Update. + if (m_timer.GetFrameCount() == 0) + { + return; + } + + // Prepare the render target to render a new frame. + Clear(); + + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Render"); + + // Draw the scene. + m_model->Draw(context, *m_states, m_world, m_view, m_proj); + + PIXEndEvent(context); + + if (m_msaa) + { + // Resolve the MSAA render target. + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Resolve"); + + auto backBuffer = m_deviceResources->GetRenderTarget(); + context->ResolveSubresource(backBuffer, 0, m_msaaRenderTarget.Get(), 0, c_resolveFormat); + + PIXEndEvent(context); + + // Set render target for UI which is typically rendered without MSAA. + auto renderTarget = m_deviceResources->GetRenderTargetView(); + context->OMSetRenderTargets(1, &renderTarget, nullptr); + } + + // Draw UI + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Draw UI"); + + auto size = m_deviceResources->GetOutputSize(); + auto safe = SimpleMath::Viewport::ComputeTitleSafeArea(size.right, size.bottom); + + m_batch->Begin(); + + wchar_t str[32] = {}; + swprintf_s(str, L"Sample count: %u", m_msaa ? m_sampleCount : 1); + m_smallFont->DrawString(m_batch.get(), str, XMFLOAT2(float(safe.left), float(safe.top)), ATG::Colors::White); + + const wchar_t* legend = m_gamepadPresent + ? L"[A] Toggle MSAA [View] Exit" + : L"Space: Toggle MSAA Esc: Exit"; + + DX::DrawControllerString(m_batch.get(), + m_smallFont.get(), m_ctrlFont.get(), + legend, + XMFLOAT2(float(safe.left), + float(safe.bottom) - m_smallFont->GetLineSpacing()), + ATG::Colors::LightGrey); + + m_batch->End(); + + PIXEndEvent(context); + + // Show the new frame. + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Present"); + m_deviceResources->Present(); + PIXEndEvent(); +} + +// Helper method to clear the back buffers. +void Sample::Clear() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Clear"); + + // Clear the views. + + if (m_msaa) + { + // + // Rather than operate on the swapchain render target, we set up to render the scene to our MSAA resources instead. + // + + context->ClearRenderTargetView(m_msaaRenderTargetView.Get(), ATG::ColorsLinear::Background); + context->ClearDepthStencilView(m_msaaDepthStencilView.Get(), D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0); + + context->OMSetRenderTargets(1, m_msaaRenderTargetView.GetAddressOf(), m_msaaDepthStencilView.Get()); + } + else + { + auto renderTarget = m_deviceResources->GetRenderTargetView(); + auto depthStencil = m_deviceResources->GetDepthStencilView(); + + context->ClearRenderTargetView(renderTarget, ATG::ColorsLinear::Background); + context->ClearDepthStencilView(depthStencil, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0); + + context->OMSetRenderTargets(1, &renderTarget, depthStencil); + } + + // Set the viewport. + auto viewport = m_deviceResources->GetScreenViewport(); + context->RSSetViewports(1, &viewport); + + PIXEndEvent(context); +} +#pragma endregion + +#pragma region Message Handlers +// Message handlers +void Sample::OnActivated() +{ +} + +void Sample::OnDeactivated() +{ +} + +void Sample::OnSuspending() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->ClearState(); + + m_deviceResources->Trim(); +} + +void Sample::OnResuming() +{ + m_timer.ResetElapsedTime(); + m_gamePadButtons.Reset(); + m_keyboardButtons.Reset(); +} + +void Sample::OnWindowSizeChanged(int width, int height, DXGI_MODE_ROTATION rotation) +{ + if (!m_deviceResources->WindowSizeChanged(width, height, rotation)) + return; + + CreateWindowSizeDependentResources(); +} + +void Sample::ValidateDevice() +{ + m_deviceResources->ValidateDevice(); +} + +// Properties +void Sample::GetDefaultSize(int& width, int& height) const +{ + width = 1280; + height = 720; +} +#pragma endregion + +#pragma region Direct3D Resources +// These are the resources that depend on the device. +void Sample::CreateDeviceDependentResources() +{ + auto device = m_deviceResources->GetD3DDevice(); + + auto context = m_deviceResources->GetD3DDeviceContext(); + m_batch = std::make_unique(context); + + m_states = std::make_unique(device); + + m_fxFactory = std::make_unique(device); + + m_model = Model::CreateFromSDKMESH(device, L"CityBlockConcrete.sdkmesh", *m_fxFactory); + + m_world = Matrix::Identity; + + // Load UI. + m_smallFont = std::make_unique(device, L"SegoeUI_18.spritefont"); + m_ctrlFont = std::make_unique(device, L"XboxOneControllerLegendSmall.spritefont"); + + // + // Check for MSAA support. + // + // Note that 4x MSAA is required for Direct3D Feature Level 10.1 or better + // 8x MSAA is required for Direct3D Feature Level 11.0 or better + // + + for (m_sampleCount = c_targetSampleCount; m_sampleCount > 1; m_sampleCount--) + { + UINT levels = 0; + if (FAILED(device->CheckMultisampleQualityLevels(c_backBufferFormat, m_sampleCount, &levels))) + continue; + + if (levels > 0) + break; + } + + if (m_sampleCount < 2) + { + throw std::exception("MSAA not supported"); + } +} + +// Allocate all memory resources that change on a window SizeChanged event. +void Sample::CreateWindowSizeDependentResources() +{ + auto output = m_deviceResources->GetOutputSize(); + + // Determine the render target size in pixels. + UINT backBufferWidth = std::max(output.right - output.left, 1); + UINT backBufferHeight = std::max(output.bottom - output.top, 1); + + // Create an MSAA render target. + CD3D11_TEXTURE2D_DESC renderTargetDesc( + c_msaaFormat, + backBufferWidth, + backBufferHeight, + 1, // The render target view has only one texture. + 1, // Use a single mipmap level. + D3D11_BIND_RENDER_TARGET, + D3D11_USAGE_DEFAULT, + 0, + m_sampleCount + ); + + auto device = m_deviceResources->GetD3DDevice(); + DX::ThrowIfFailed(device->CreateTexture2D( + &renderTargetDesc, + nullptr, + m_msaaRenderTarget.ReleaseAndGetAddressOf() + )); + + CD3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc(D3D11_RTV_DIMENSION_TEXTURE2DMS, c_backBufferFormat); + + DX::ThrowIfFailed(device->CreateRenderTargetView( + m_msaaRenderTarget.Get(), + &renderTargetViewDesc, + m_msaaRenderTargetView.ReleaseAndGetAddressOf() + )); + + // Create an MSAA depth stencil view. + CD3D11_TEXTURE2D_DESC depthStencilDesc( + c_depthBufferFormat, + backBufferWidth, + backBufferHeight, + 1, // This depth stencil view has only one texture. + 1, // Use a single mipmap level. + D3D11_BIND_DEPTH_STENCIL, + D3D11_USAGE_DEFAULT, + 0, + m_sampleCount + ); + + ComPtr depthStencil; + DX::ThrowIfFailed(device->CreateTexture2D( + &depthStencilDesc, + nullptr, + depthStencil.GetAddressOf() + )); + + DX::ThrowIfFailed(device->CreateDepthStencilView( + depthStencil.Get(), + nullptr, + m_msaaDepthStencilView.ReleaseAndGetAddressOf() + )); + + // Setup test scene. + m_view = Matrix::CreateLookAt(Vector3(0, -211.f, -23.f), Vector3(6.f, 0.f, -37.f), -Vector3::UnitZ); + + m_proj = Matrix::CreatePerspectiveFieldOfView(XM_PI / 4.f, + float(backBufferWidth) / float(backBufferHeight), 0.1f, 1000.f); + + auto viewport = m_deviceResources->GetScreenViewport(); + m_batch->SetViewport(viewport); +} + +void Sample::OnDeviceLost() +{ + m_msaaRenderTarget.Reset(); + m_msaaRenderTargetView.Reset(); + m_msaaDepthStencilView.Reset(); + + m_batch.reset(); + m_smallFont.reset(); + m_ctrlFont.reset(); + m_states.reset(); + m_model.reset(); + m_fxFactory.reset(); +} + +void Sample::OnDeviceRestored() +{ + CreateDeviceDependentResources(); + + CreateWindowSizeDependentResources(); +} +#pragma endregion diff --git a/Samples/IntroGraphics/SimpleMSAA_UWP/SimpleMSAA.h b/Samples/IntroGraphics/SimpleMSAA_UWP/SimpleMSAA.h new file mode 100644 index 00000000..5ddee6fd --- /dev/null +++ b/Samples/IntroGraphics/SimpleMSAA_UWP/SimpleMSAA.h @@ -0,0 +1,90 @@ +//-------------------------------------------------------------------------------------- +// SimpleMSAA.h +// +// This sample demonstrates setting up a MSAA render target for DirectX 11 +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "DeviceResources.h" +#include "StepTimer.h" + + +// A basic sample implementation that creates a D3D11 device and +// provides a render loop. +class Sample : public DX::IDeviceNotify +{ +public: + + Sample(); + + // Initialization and management + void Initialize(::IUnknown* window, int width, int height, DXGI_MODE_ROTATION rotation); + + // Basic render loop + void Tick(); + + // IDeviceNotify + virtual void OnDeviceLost() override; + virtual void OnDeviceRestored() override; + + // Messages + void OnActivated(); + void OnDeactivated(); + void OnSuspending(); + void OnResuming(); + void OnWindowSizeChanged(int width, int height, DXGI_MODE_ROTATION rotation); + void ValidateDevice(); + + // Properties + void GetDefaultSize( int& width, int& height ) const; + +private: + + void Update(DX::StepTimer const& timer); + void Render(); + + void Clear(); + + void CreateDeviceDependentResources(); + void CreateWindowSizeDependentResources(); + + // Device resources. + std::unique_ptr m_deviceResources; + + // MSAA resources. + Microsoft::WRL::ComPtr m_msaaRenderTarget; + + Microsoft::WRL::ComPtr m_msaaRenderTargetView; + Microsoft::WRL::ComPtr m_msaaDepthStencilView; + + unsigned int m_sampleCount; + bool m_msaa; + + // Rendering loop timer. + DX::StepTimer m_timer; + + // Input devices. + std::unique_ptr m_gamePad; + std::unique_ptr m_keyboard; + + DirectX::GamePad::ButtonStateTracker m_gamePadButtons; + DirectX::Keyboard::KeyboardStateTracker m_keyboardButtons; + bool m_gamepadPresent; + + // DirectXTK objects. + std::unique_ptr m_batch; + std::unique_ptr m_smallFont; + std::unique_ptr m_ctrlFont; + + std::unique_ptr m_states; + std::unique_ptr m_model; + std::unique_ptr m_fxFactory; + + DirectX::SimpleMath::Matrix m_world; + DirectX::SimpleMath::Matrix m_view; + DirectX::SimpleMath::Matrix m_proj; +}; \ No newline at end of file diff --git a/Samples/IntroGraphics/SimpleMSAA_UWP/SimpleMSAA.sln b/Samples/IntroGraphics/SimpleMSAA_UWP/SimpleMSAA.sln new file mode 100644 index 00000000..4f047bfd --- /dev/null +++ b/Samples/IntroGraphics/SimpleMSAA_UWP/SimpleMSAA.sln @@ -0,0 +1,54 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2017 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SimpleMSAA", "SimpleMSAA.vcxproj", "{FEEAFAAD-E18F-4AF2-9C47-98B63C8A4454}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTK", "..\..\..\Kits\DirectXTK\DirectXTK_Windows10.vcxproj", "{F4776924-619C-42C7-88B2-82C947CCC9E7}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|ARM = Debug|ARM + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|ARM = Release|ARM + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {FEEAFAAD-E18F-4AF2-9C47-98B63C8A4454}.Debug|ARM.ActiveCfg = Debug|ARM + {FEEAFAAD-E18F-4AF2-9C47-98B63C8A4454}.Debug|ARM.Build.0 = Debug|ARM + {FEEAFAAD-E18F-4AF2-9C47-98B63C8A4454}.Debug|ARM.Deploy.0 = Debug|ARM + {FEEAFAAD-E18F-4AF2-9C47-98B63C8A4454}.Debug|x64.ActiveCfg = Debug|x64 + {FEEAFAAD-E18F-4AF2-9C47-98B63C8A4454}.Debug|x64.Build.0 = Debug|x64 + {FEEAFAAD-E18F-4AF2-9C47-98B63C8A4454}.Debug|x64.Deploy.0 = Debug|x64 + {FEEAFAAD-E18F-4AF2-9C47-98B63C8A4454}.Debug|x86.ActiveCfg = Debug|Win32 + {FEEAFAAD-E18F-4AF2-9C47-98B63C8A4454}.Debug|x86.Build.0 = Debug|Win32 + {FEEAFAAD-E18F-4AF2-9C47-98B63C8A4454}.Debug|x86.Deploy.0 = Debug|Win32 + {FEEAFAAD-E18F-4AF2-9C47-98B63C8A4454}.Release|ARM.ActiveCfg = Release|ARM + {FEEAFAAD-E18F-4AF2-9C47-98B63C8A4454}.Release|ARM.Build.0 = Release|ARM + {FEEAFAAD-E18F-4AF2-9C47-98B63C8A4454}.Release|ARM.Deploy.0 = Release|ARM + {FEEAFAAD-E18F-4AF2-9C47-98B63C8A4454}.Release|x64.ActiveCfg = Release|x64 + {FEEAFAAD-E18F-4AF2-9C47-98B63C8A4454}.Release|x64.Build.0 = Release|x64 + {FEEAFAAD-E18F-4AF2-9C47-98B63C8A4454}.Release|x64.Deploy.0 = Release|x64 + {FEEAFAAD-E18F-4AF2-9C47-98B63C8A4454}.Release|x86.ActiveCfg = Release|Win32 + {FEEAFAAD-E18F-4AF2-9C47-98B63C8A4454}.Release|x86.Build.0 = Release|Win32 + {FEEAFAAD-E18F-4AF2-9C47-98B63C8A4454}.Release|x86.Deploy.0 = Release|Win32 + {F4776924-619C-42C7-88B2-82C947CCC9E7}.Debug|ARM.ActiveCfg = Debug|ARM + {F4776924-619C-42C7-88B2-82C947CCC9E7}.Debug|ARM.Build.0 = Debug|ARM + {F4776924-619C-42C7-88B2-82C947CCC9E7}.Debug|x64.ActiveCfg = Debug|x64 + {F4776924-619C-42C7-88B2-82C947CCC9E7}.Debug|x64.Build.0 = Debug|x64 + {F4776924-619C-42C7-88B2-82C947CCC9E7}.Debug|x86.ActiveCfg = Debug|Win32 + {F4776924-619C-42C7-88B2-82C947CCC9E7}.Debug|x86.Build.0 = Debug|Win32 + {F4776924-619C-42C7-88B2-82C947CCC9E7}.Release|ARM.ActiveCfg = Release|ARM + {F4776924-619C-42C7-88B2-82C947CCC9E7}.Release|ARM.Build.0 = Release|ARM + {F4776924-619C-42C7-88B2-82C947CCC9E7}.Release|x64.ActiveCfg = Release|x64 + {F4776924-619C-42C7-88B2-82C947CCC9E7}.Release|x64.Build.0 = Release|x64 + {F4776924-619C-42C7-88B2-82C947CCC9E7}.Release|x86.ActiveCfg = Release|Win32 + {F4776924-619C-42C7-88B2-82C947CCC9E7}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/IntroGraphics/SimpleMSAA_UWP/SimpleMSAA.vcxproj b/Samples/IntroGraphics/SimpleMSAA_UWP/SimpleMSAA.vcxproj new file mode 100644 index 00000000..1baad028 --- /dev/null +++ b/Samples/IntroGraphics/SimpleMSAA_UWP/SimpleMSAA.vcxproj @@ -0,0 +1,316 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + Debug + ARM + + + Release + ARM + + + + {feeafaad-e18f-4af2-9c47-98b63c8a4454} + DirectXApp + SimpleMSAA + en-US + 14.0 + true + Windows Store + 10.0.15063.0 + 10.0.14393.0 + 10.0 + + + + Application + true + v141 + x64 + + + Application + true + v141 + x64 + + + Application + true + v141 + x64 + + + Application + false + true + v141 + x64 + + + Application + false + true + v141 + x64 + + + Application + false + true + v141 + x64 + + + + + + + + + + + + + + + + + + + + + + + + + + + false + false + + + + ATGTelemetryUWP.lib; d2d1.lib; d3d11.lib; dxgi.lib; dxguid.lib; windowscodecs.lib; dwrite.lib; %(AdditionalDependencies) + ..\..\..\Kits\Telemetry\$(Platform); %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\arm; $(VCInstallDir)\lib\arm + true + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;..\..\..\Kits\Telemetry;%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + Level4 + _DEBUG;%(PreprocessorDefinitions) + Fast + + + 4.0_level_9_3 + + + + + ATGTelemetryUWP.lib; d2d1.lib; d3d11.lib; dxgi.lib; dxguid.lib; windowscodecs.lib; dwrite.lib; %(AdditionalDependencies) + ..\..\..\Kits\Telemetry\$(Platform); %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\arm; $(VCInstallDir)\lib\arm + true + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;..\..\..\Kits\Telemetry;%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + Level4 + NDEBUG;%(PreprocessorDefinitions) + Fast + + + 4.0_level_9_3 + + + + + ATGTelemetryUWP.lib; d2d1.lib; d3d11.lib; dxgi.lib; dxguid.lib; windowscodecs.lib; dwrite.lib; %(AdditionalDependencies) + ..\..\..\Kits\Telemetry\$(Platform); %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store; $(VCInstallDir)\lib + true + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;..\..\..\Kits\Telemetry;%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + Level4 + _DEBUG;%(PreprocessorDefinitions) + Fast + StreamingSIMDExtensions2 + + + 4.0_level_9_3 + + + + + ATGTelemetryUWP.lib; d2d1.lib; d3d11.lib; dxgi.lib; dxguid.lib; windowscodecs.lib; dwrite.lib; %(AdditionalDependencies) + ..\..\..\Kits\Telemetry\$(Platform); %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store; $(VCInstallDir)\lib + true + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;..\..\..\Kits\Telemetry;%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + Level4 + NDEBUG;%(PreprocessorDefinitions) + Fast + StreamingSIMDExtensions2 + + + 4.0_level_9_3 + + + + + ATGTelemetryUWP.lib; d2d1.lib; d3d11.lib; dxgi.lib; dxguid.lib; windowscodecs.lib; dwrite.lib; %(AdditionalDependencies) + ..\..\..\Kits\Telemetry\$(Platform); %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\amd64; $(VCInstallDir)\lib\amd64 + true + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;..\..\..\Kits\Telemetry;%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + Level4 + _DEBUG;%(PreprocessorDefinitions) + Fast + + + 4.0_level_9_3 + + + + + ATGTelemetryUWP.lib; d2d1.lib; d3d11.lib; dxgi.lib; dxguid.lib; windowscodecs.lib; dwrite.lib; %(AdditionalDependencies) + ..\..\..\Kits\Telemetry\$(Platform); %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\amd64; $(VCInstallDir)\lib\amd64 + true + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;..\..\..\Kits\Telemetry;%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + Level4 + NDEBUG;%(PreprocessorDefinitions) + Fast + + + 4.0_level_9_3 + + + + + + + + + + + + + + + + Create + Create + Create + Create + Create + Create + + + + + Designer + + + + + + + + + + + + + + true + true + true + ATGTelemetryUWP.dll + + + true + true + true + ATGTelemetryUWP.dll + + + true + true + true + ATGTelemetryUWP.dll + + + true + true + true + true + true + true + + + true + true + true + true + true + true + + + true + true + true + true + true + true + + + + + + {f4776924-619c-42c7-88b2-82c947ccc9e7} + + + + + + + + + \ No newline at end of file diff --git a/Samples/IntroGraphics/SimpleMSAA_UWP/SimpleMSAA.vcxproj.filters b/Samples/IntroGraphics/SimpleMSAA_UWP/SimpleMSAA.vcxproj.filters new file mode 100644 index 00000000..2bea0bb5 --- /dev/null +++ b/Samples/IntroGraphics/SimpleMSAA_UWP/SimpleMSAA.vcxproj.filters @@ -0,0 +1,98 @@ + + + + + bfa5030b-6e84-4e4f-8ca7-b9f6cabd3fa5 + + + b5b78849-75f3-4ab6-a803-71e50219b752 + bmp;dds;fbx;gif;jpg;jpeg;tga;tiff;tif;png + + + 15f5618b-42bb-4232-96d4-286ec90d2d13 + + + b1127067-cea4-4311-988b-696b8a6dc33e + + + 5ce52ecb-7bbd-46f4-951a-982484bf7307 + + + db189b92-f386-4adc-8306-8d580d0496b9 + + + 10a7c63e-ca5d-4bec-b78f-2435e8ab60f2 + + + + + + + Common + + + Common + + + ATG Tool Kit + + + ATG Tool Kit + + + + + + + + Common + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + + + Common\Telemetry\ARM + + + Common\Telemetry\Win32 + + + Common\Telemetry\x64 + + + Assets + + + Assets + + + Assets + + + + + + + \ No newline at end of file diff --git a/Samples/IntroGraphics/SimpleMSAA_UWP/StepTimer.h b/Samples/IntroGraphics/SimpleMSAA_UWP/StepTimer.h new file mode 100644 index 00000000..f55db2f8 --- /dev/null +++ b/Samples/IntroGraphics/SimpleMSAA_UWP/StepTimer.h @@ -0,0 +1,188 @@ +// +// StepTimer.h - A simple timer that provides elapsed time information +// + +#pragma once + +#include +#include + +namespace DX +{ + // Helper class for animation and simulation timing. + class StepTimer + { + public: + StepTimer() : + m_elapsedTicks(0), + m_totalTicks(0), + m_leftOverTicks(0), + m_frameCount(0), + m_framesPerSecond(0), + m_framesThisSecond(0), + m_qpcSecondCounter(0), + m_isFixedTimeStep(false), + m_targetElapsedTicks(TicksPerSecond / 60) + { + if (!QueryPerformanceFrequency(&m_qpcFrequency)) + { + throw std::exception( "QueryPerformanceFrequency" ); + } + + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + // Initialize max delta to 1/10 of a second. + m_qpcMaxDelta = m_qpcFrequency.QuadPart / 10; + } + + // Get elapsed time since the previous Update call. + uint64_t GetElapsedTicks() const { return m_elapsedTicks; } + double GetElapsedSeconds() const { return TicksToSeconds(m_elapsedTicks); } + + // Get total time since the start of the program. + uint64_t GetTotalTicks() const { return m_totalTicks; } + double GetTotalSeconds() const { return TicksToSeconds(m_totalTicks); } + + // Get total number of updates since start of the program. + uint32_t GetFrameCount() const { return m_frameCount; } + + // Get the current framerate. + uint32_t GetFramesPerSecond() const { return m_framesPerSecond; } + + // Set whether to use fixed or variable timestep mode. + void SetFixedTimeStep(bool isFixedTimestep) { m_isFixedTimeStep = isFixedTimestep; } + + // Set how often to call Update when in fixed timestep mode. + void SetTargetElapsedTicks(uint64_t targetElapsed) { m_targetElapsedTicks = targetElapsed; } + void SetTargetElapsedSeconds(double targetElapsed) { m_targetElapsedTicks = SecondsToTicks(targetElapsed); } + + // Integer format represents time using 10,000,000 ticks per second. + static const uint64_t TicksPerSecond = 10000000; + + static double TicksToSeconds(uint64_t ticks) { return static_cast(ticks) / TicksPerSecond; } + static uint64_t SecondsToTicks(double seconds) { return static_cast(seconds * TicksPerSecond); } + + // After an intentional timing discontinuity (for instance a blocking IO operation) + // call this to avoid having the fixed timestep logic attempt a set of catch-up + // Update calls. + + void ResetElapsedTime() + { + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception("QueryPerformanceCounter"); + } + + m_leftOverTicks = 0; + m_framesPerSecond = 0; + m_framesThisSecond = 0; + m_qpcSecondCounter = 0; + } + + // Update timer state, calling the specified Update function the appropriate number of times. + template + void Tick(const TUpdate& update) + { + // Query the current time. + LARGE_INTEGER currentTime; + + if (!QueryPerformanceCounter(¤tTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + uint64_t timeDelta = currentTime.QuadPart - m_qpcLastTime.QuadPart; + + m_qpcLastTime = currentTime; + m_qpcSecondCounter += timeDelta; + + // Clamp excessively large time deltas (e.g. after paused in the debugger). + if (timeDelta > m_qpcMaxDelta) + { + timeDelta = m_qpcMaxDelta; + } + + // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. + timeDelta *= TicksPerSecond; + timeDelta /= m_qpcFrequency.QuadPart; + + uint32_t lastFrameCount = m_frameCount; + + if (m_isFixedTimeStep) + { + // Fixed timestep update logic + + // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp + // the clock to exactly match the target value. This prevents tiny and irrelevant errors + // from accumulating over time. Without this clamping, a game that requested a 60 fps + // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually + // accumulate enough tiny errors that it would drop a frame. It is better to just round + // small deviations down to zero to leave things running smoothly. + + if (abs(static_cast(timeDelta - m_targetElapsedTicks)) < TicksPerSecond / 4000) + { + timeDelta = m_targetElapsedTicks; + } + + m_leftOverTicks += timeDelta; + + while (m_leftOverTicks >= m_targetElapsedTicks) + { + m_elapsedTicks = m_targetElapsedTicks; + m_totalTicks += m_targetElapsedTicks; + m_leftOverTicks -= m_targetElapsedTicks; + m_frameCount++; + + update(); + } + } + else + { + // Variable timestep update logic. + m_elapsedTicks = timeDelta; + m_totalTicks += timeDelta; + m_leftOverTicks = 0; + m_frameCount++; + + update(); + } + + // Track the current framerate. + if (m_frameCount != lastFrameCount) + { + m_framesThisSecond++; + } + + if (m_qpcSecondCounter >= static_cast(m_qpcFrequency.QuadPart)) + { + m_framesPerSecond = m_framesThisSecond; + m_framesThisSecond = 0; + m_qpcSecondCounter %= m_qpcFrequency.QuadPart; + } + } + + private: + // Source timing data uses QPC units. + LARGE_INTEGER m_qpcFrequency; + LARGE_INTEGER m_qpcLastTime; + uint64_t m_qpcMaxDelta; + + // Derived timing data uses a canonical tick format. + uint64_t m_elapsedTicks; + uint64_t m_totalTicks; + uint64_t m_leftOverTicks; + + // Members for tracking the framerate. + uint32_t m_frameCount; + uint32_t m_framesPerSecond; + uint32_t m_framesThisSecond; + uint64_t m_qpcSecondCounter; + + // Members for configuring fixed timestep mode. + bool m_isFixedTimeStep; + uint64_t m_targetElapsedTicks; + }; +} diff --git a/Samples/IntroGraphics/SimpleMSAA_UWP/pch.cpp b/Samples/IntroGraphics/SimpleMSAA_UWP/pch.cpp new file mode 100644 index 00000000..373fab97 --- /dev/null +++ b/Samples/IntroGraphics/SimpleMSAA_UWP/pch.cpp @@ -0,0 +1,10 @@ +//-------------------------------------------------------------------------------------- +// pch.cpp +// +// Include the standard header and generate the precompiled header. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" diff --git a/Samples/IntroGraphics/SimpleMSAA_UWP/pch.h b/Samples/IntroGraphics/SimpleMSAA_UWP/pch.h new file mode 100644 index 00000000..4ee62621 --- /dev/null +++ b/Samples/IntroGraphics/SimpleMSAA_UWP/pch.h @@ -0,0 +1,75 @@ +//-------------------------------------------------------------------------------------- +// pch.h +// +// Header for standard system include files. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +// Use the C++ standard templated min/max +#define NOMINMAX + +#pragma warning(push) +#pragma warning(disable : 4467) +#include +#pragma warning(pop) + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#ifdef _DEBUG +#include +#endif + +#include "CommonStates.h" +#include "Effects.h" +#include "GamePad.h" +#include "GraphicsMemory.h" +#include "Keyboard.h" +#include "Model.h" +#include "Mouse.h" +#include "SpriteBatch.h" +#include "SimpleMath.h" +#include "SpriteFont.h" + +namespace DX +{ + // Helper class for COM exceptions + class com_exception : public std::exception + { + public: + com_exception(HRESULT hr) : result(hr) {} + + virtual const char* what() const override + { + static char s_str[64] = { 0 }; + sprintf_s(s_str, "Failure with HRESULT of %08X", result); + return s_str; + } + + private: + HRESULT result; + }; + + // Helper utility converts D3D API failures into exceptions. + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + throw com_exception(hr); + } + } +} \ No newline at end of file diff --git a/Samples/IntroGraphics/SimpleMSAA_UWP12/Assets/Logo.png b/Samples/IntroGraphics/SimpleMSAA_UWP12/Assets/Logo.png new file mode 100644 index 00000000..6e7e704a Binary files /dev/null and b/Samples/IntroGraphics/SimpleMSAA_UWP12/Assets/Logo.png differ diff --git a/Samples/IntroGraphics/SimpleMSAA_UWP12/Assets/SmallLogo.png b/Samples/IntroGraphics/SimpleMSAA_UWP12/Assets/SmallLogo.png new file mode 100644 index 00000000..98b09d91 Binary files /dev/null and b/Samples/IntroGraphics/SimpleMSAA_UWP12/Assets/SmallLogo.png differ diff --git a/Samples/IntroGraphics/SimpleMSAA_UWP12/Assets/SplashScreen.png b/Samples/IntroGraphics/SimpleMSAA_UWP12/Assets/SplashScreen.png new file mode 100644 index 00000000..c352b156 Binary files /dev/null and b/Samples/IntroGraphics/SimpleMSAA_UWP12/Assets/SplashScreen.png differ diff --git a/Samples/IntroGraphics/SimpleMSAA_UWP12/Assets/StoreLogo.png b/Samples/IntroGraphics/SimpleMSAA_UWP12/Assets/StoreLogo.png new file mode 100644 index 00000000..315472e1 Binary files /dev/null and b/Samples/IntroGraphics/SimpleMSAA_UWP12/Assets/StoreLogo.png differ diff --git a/Samples/IntroGraphics/SimpleMSAA_UWP12/Assets/WideLogo.png b/Samples/IntroGraphics/SimpleMSAA_UWP12/Assets/WideLogo.png new file mode 100644 index 00000000..c70f68e2 Binary files /dev/null and b/Samples/IntroGraphics/SimpleMSAA_UWP12/Assets/WideLogo.png differ diff --git a/Samples/IntroGraphics/SimpleMSAA_UWP12/DeviceResources.cpp b/Samples/IntroGraphics/SimpleMSAA_UWP12/DeviceResources.cpp new file mode 100644 index 00000000..5e3a68f6 --- /dev/null +++ b/Samples/IntroGraphics/SimpleMSAA_UWP12/DeviceResources.cpp @@ -0,0 +1,705 @@ +// +// DeviceResources.cpp - A wrapper for the Direct3D 12 device and swapchain +// + +#include "pch.h" +#include "DeviceResources.h" + +using namespace DirectX; + +using Microsoft::WRL::ComPtr; + +// Constants used to calculate screen rotations +namespace ScreenRotation +{ + // 0-degree Z-rotation + static const XMFLOAT4X4 Rotation0( + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + ); + + // 90-degree Z-rotation + static const XMFLOAT4X4 Rotation90( + 0.0f, 1.0f, 0.0f, 0.0f, + -1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + ); + + // 180-degree Z-rotation + static const XMFLOAT4X4 Rotation180( + -1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, -1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + ); + + // 270-degree Z-rotation + static const XMFLOAT4X4 Rotation270( + 0.0f, -1.0f, 0.0f, 0.0f, + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + ); +}; + +namespace +{ + inline DXGI_FORMAT NoSRGB(DXGI_FORMAT fmt) + { + switch (fmt) + { + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: return DXGI_FORMAT_R8G8B8A8_UNORM; + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: return DXGI_FORMAT_B8G8R8A8_UNORM; + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: return DXGI_FORMAT_B8G8R8X8_UNORM; + default: return fmt; + } + } +}; + +// Constructor for DeviceResources. +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), + m_screenViewport{}, + m_scissorRect{}, + m_backBufferFormat(backBufferFormat), + m_depthBufferFormat(depthBufferFormat), + m_backBufferCount(backBufferCount), + m_d3dMinFeatureLevel(minFeatureLevel), + m_window(0), + m_d3dFeatureLevel(D3D_FEATURE_LEVEL_11_0), + 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) + { + throw std::out_of_range("backBufferCount too large"); + } + + if (minFeatureLevel < D3D_FEATURE_LEVEL_11_0) + { + throw std::out_of_range("minFeatureLevel too low"); + } +} + +// Destructor for DeviceResources. +DX::DeviceResources::~DeviceResources() +{ + // Ensure that the GPU is no longer referencing resources that are about to be destroyed. + WaitForGpu(); +} + +// Configures the Direct3D device, and stores handles to it and the device context. +void DX::DeviceResources::CreateDeviceResources() +{ +#if defined(_DEBUG) + // Enable the debug layer (requires the Graphics Tools "optional feature"). + // + // NOTE: Enabling the debug layer after device creation will invalidate the active device. + bool debugDXGI = false; + { + ComPtr debugController; + if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(debugController.GetAddressOf())))) + { + debugController->EnableDebugLayer(); + } + else + { + OutputDebugStringA("WARNING: Direct3D Debug Device is not available\n"); + } + + ComPtr dxgiInfoQueue; + if (SUCCEEDED(DXGIGetDebugInterface1(0, IID_PPV_ARGS(dxgiInfoQueue.GetAddressOf())))) + { + debugDXGI = true; + + DX::ThrowIfFailed(CreateDXGIFactory2(DXGI_CREATE_FACTORY_DEBUG, IID_PPV_ARGS(m_dxgiFactory.ReleaseAndGetAddressOf()))); + + dxgiInfoQueue->SetBreakOnSeverity(DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_ERROR, true); + dxgiInfoQueue->SetBreakOnSeverity(DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_CORRUPTION, true); + } + } + + if (!debugDXGI) +#endif + + 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 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 adapter; + GetAdapter(adapter.GetAddressOf()); + + // Create the DX12 API device object. + DX::ThrowIfFailed(D3D12CreateDevice( + adapter.Get(), + m_d3dMinFeatureLevel, + IID_PPV_ARGS(m_d3dDevice.ReleaseAndGetAddressOf()) + )); + +#ifndef NDEBUG + // Configure debug device (if active). + ComPtr d3dInfoQueue; + if (SUCCEEDED(m_d3dDevice.As(&d3dInfoQueue))) + { +#ifdef _DEBUG + d3dInfoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_CORRUPTION, true); + d3dInfoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_ERROR, true); +#endif + D3D12_MESSAGE_ID hide[] = + { + D3D12_MESSAGE_ID_MAP_INVALID_NULLRANGE, + D3D12_MESSAGE_ID_UNMAP_INVALID_NULLRANGE + }; + D3D12_INFO_QUEUE_FILTER filter = {}; + filter.DenyList.NumIDs = _countof(hide); + filter.DenyList.pIDList = hide; + d3dInfoQueue->AddStorageFilterEntries(&filter); + } +#endif + + // Determine maximum supported feature level for this device + static const D3D_FEATURE_LEVEL s_featureLevels[] = + { + D3D_FEATURE_LEVEL_12_1, + D3D_FEATURE_LEVEL_12_0, + D3D_FEATURE_LEVEL_11_1, + D3D_FEATURE_LEVEL_11_0, + }; + + D3D12_FEATURE_DATA_FEATURE_LEVELS featLevels = + { + _countof(s_featureLevels), s_featureLevels, D3D_FEATURE_LEVEL_11_0 + }; + + HRESULT hr = m_d3dDevice->CheckFeatureSupport(D3D12_FEATURE_FEATURE_LEVELS, &featLevels, sizeof(featLevels)); + if (SUCCEEDED(hr)) + { + m_d3dFeatureLevel = featLevels.MaxSupportedFeatureLevel; + } + else + { + m_d3dFeatureLevel = m_d3dMinFeatureLevel; + } + + // Create the command queue. + D3D12_COMMAND_QUEUE_DESC queueDesc = {}; + queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; + queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; + + DX::ThrowIfFailed(m_d3dDevice->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(m_commandQueue.ReleaseAndGetAddressOf()))); + + // Create descriptor heaps for render target views and depth stencil views. + D3D12_DESCRIPTOR_HEAP_DESC rtvDescriptorHeapDesc = {}; + rtvDescriptorHeapDesc.NumDescriptors = m_backBufferCount; + rtvDescriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; + + DX::ThrowIfFailed(m_d3dDevice->CreateDescriptorHeap(&rtvDescriptorHeapDesc, IID_PPV_ARGS(m_rtvDescriptorHeap.ReleaseAndGetAddressOf()))); + + m_rtvDescriptorSize = m_d3dDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + D3D12_DESCRIPTOR_HEAP_DESC dsvDescriptorHeapDesc = {}; + dsvDescriptorHeapDesc.NumDescriptors = 1; + dsvDescriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV; + + DX::ThrowIfFailed(m_d3dDevice->CreateDescriptorHeap(&dsvDescriptorHeapDesc, IID_PPV_ARGS(m_dsvDescriptorHeap.ReleaseAndGetAddressOf()))); + } + + // Create a command allocator for each back buffer that will be rendered to. + for (UINT n = 0; n < m_backBufferCount; n++) + { + DX::ThrowIfFailed(m_d3dDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(m_commandAllocators[n].ReleaseAndGetAddressOf()))); + } + + // Create a command list for recording graphics commands. + DX::ThrowIfFailed(m_d3dDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_commandAllocators[0].Get(), nullptr, IID_PPV_ARGS(m_commandList.ReleaseAndGetAddressOf()))); + DX::ThrowIfFailed(m_commandList->Close()); + + // Create a fence for tracking GPU execution progress. + DX::ThrowIfFailed(m_d3dDevice->CreateFence(m_fenceValues[m_backBufferIndex], D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(m_fence.ReleaseAndGetAddressOf()))); + m_fenceValues[m_backBufferIndex]++; + + m_fenceEvent.Attach(CreateEvent(nullptr, FALSE, FALSE, nullptr)); + if (!m_fenceEvent.IsValid()) + { + throw std::exception("CreateEvent"); + } +} + +// These resources need to be recreated every time the window size is changed. +void DX::DeviceResources::CreateWindowSizeDependentResources() +{ + if (!m_window) + { + throw std::exception("Call SetWindow with a valid CoreWindow pointer"); + } + + // Wait until all previous GPU work is complete. + WaitForGpu(); + + // Release resources that are tied to the swap chain and update fence values. + for (UINT n = 0; n < m_backBufferCount; n++) + { + m_renderTargets[n].Reset(); + m_fenceValues[n] = m_fenceValues[m_backBufferIndex]; + } + + // Determine the render target size in pixels. + UINT backBufferWidth = std::max(m_outputSize.right - m_outputSize.left, 1); + UINT backBufferHeight = std::max(m_outputSize.bottom - m_outputSize.top, 1); + DXGI_FORMAT backBufferFormat = NoSRGB(m_backBufferFormat); + + // If the swap chain already exists, resize it, otherwise create one. + if (m_swapChain) + { + // If the swap chain already exists, resize it. + HRESULT hr = m_swapChain->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + backBufferFormat, + (m_options & c_AllowTearing) ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0 + ); + + if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) + { +#ifdef _DEBUG + char buff[64] = {}; + sprintf_s(buff, "Device Lost on ResizeBuffers: Reason code 0x%08X\n", (hr == DXGI_ERROR_DEVICE_REMOVED) ? m_d3dDevice->GetDeviceRemovedReason() : hr); + OutputDebugStringA(buff); +#endif + // If the device was removed for any reason, a new device and swap chain will need to be created. + HandleDeviceLost(); + + // Everything is set up now. Do not continue execution of this method. HandleDeviceLost will reenter this method + // and correctly set up the new device. + return; + } + else + { + DX::ThrowIfFailed(hr); + } + } + else + { + // Create a descriptor for the swap chain. + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; + swapChainDesc.Width = backBufferWidth; + swapChainDesc.Height = backBufferHeight; + swapChainDesc.Format = backBufferFormat; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = m_backBufferCount; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + 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 swapChain; + DX::ThrowIfFailed(m_dxgiFactory->CreateSwapChainForCoreWindow( + m_commandQueue.Get(), + m_window, + &swapChainDesc, + nullptr, + swapChain.GetAddressOf() + )); + + DX::ThrowIfFailed(swapChain.As(&m_swapChain)); + } + + // Set the proper orientation for the swap chain, and generate + // matrix transformations for rendering to the rotated swap chain. + switch (m_rotation) + { + default: + case DXGI_MODE_ROTATION_IDENTITY: + m_orientationTransform3D = ScreenRotation::Rotation0; + break; + + case DXGI_MODE_ROTATION_ROTATE90: + m_orientationTransform3D = ScreenRotation::Rotation270; + break; + + case DXGI_MODE_ROTATION_ROTATE180: + m_orientationTransform3D = ScreenRotation::Rotation180; + break; + + case DXGI_MODE_ROTATION_ROTATE270: + m_orientationTransform3D = ScreenRotation::Rotation90; + break; + } + + DX::ThrowIfFailed(m_swapChain->SetRotation(m_rotation)); + + // Obtain the back buffers for this window which will be the final render targets + // and create render target views for each of them. + for (UINT n = 0; n < m_backBufferCount; n++) + { + DX::ThrowIfFailed(m_swapChain->GetBuffer(n, IID_PPV_ARGS(m_renderTargets[n].GetAddressOf()))); + + wchar_t name[25] = {}; + swprintf_s(name, L"Render target %u", n); + m_renderTargets[n]->SetName(name); + + D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = {}; + rtvDesc.Format = m_backBufferFormat; + rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; + + CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor(m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), n, m_rtvDescriptorSize); + m_d3dDevice->CreateRenderTargetView(m_renderTargets[n].Get(), &rtvDesc, rtvDescriptor); + } + + // Reset the index to the current back buffer. + m_backBufferIndex = m_swapChain->GetCurrentBackBufferIndex(); + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + // Allocate a 2-D surface as the depth/stencil buffer and create a depth/stencil view + // on this surface. + CD3DX12_HEAP_PROPERTIES depthHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + + D3D12_RESOURCE_DESC depthStencilDesc = CD3DX12_RESOURCE_DESC::Tex2D( + m_depthBufferFormat, + backBufferWidth, + backBufferHeight, + 1, // This depth stencil view has only one texture. + 1 // Use a single mipmap level. + ); + depthStencilDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL; + + D3D12_CLEAR_VALUE depthOptimizedClearValue = {}; + depthOptimizedClearValue.Format = m_depthBufferFormat; + depthOptimizedClearValue.DepthStencil.Depth = 1.0f; + depthOptimizedClearValue.DepthStencil.Stencil = 0; + + DX::ThrowIfFailed(m_d3dDevice->CreateCommittedResource( + &depthHeapProperties, + D3D12_HEAP_FLAG_NONE, + &depthStencilDesc, + D3D12_RESOURCE_STATE_DEPTH_WRITE, + &depthOptimizedClearValue, + IID_PPV_ARGS(m_depthStencil.ReleaseAndGetAddressOf()) + )); + + m_depthStencil->SetName(L"Depth stencil"); + + D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = {}; + dsvDesc.Format = m_depthBufferFormat; + dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D; + + m_d3dDevice->CreateDepthStencilView(m_depthStencil.Get(), &dsvDesc, m_dsvDescriptorHeap->GetCPUDescriptorHandleForHeapStart()); + } + + // Set the 3D rendering viewport and scissor rectangle to target the entire window. + m_screenViewport.TopLeftX = m_screenViewport.TopLeftY = 0.f; + m_screenViewport.Width = static_cast(backBufferWidth); + m_screenViewport.Height = static_cast(backBufferHeight); + m_screenViewport.MinDepth = D3D12_MIN_DEPTH; + m_screenViewport.MaxDepth = D3D12_MAX_DEPTH; + + m_scissorRect.left = m_scissorRect.top = 0; + m_scissorRect.right = backBufferWidth; + m_scissorRect.bottom = backBufferHeight; +} + +// This method is called when the CoreWindow is created (or re-created). +void DX::DeviceResources::SetWindow(IUnknown* window, int width, int height, DXGI_MODE_ROTATION rotation) +{ + m_window = window; + + m_outputSize.left = m_outputSize.top = 0; + m_outputSize.right = width; + m_outputSize.bottom = height; + + m_rotation = rotation; +} + +// This method is called when the window changes size. +bool DX::DeviceResources::WindowSizeChanged(int width, int height, DXGI_MODE_ROTATION rotation) +{ + RECT newRc; + newRc.left = newRc.top = 0; + newRc.right = width; + newRc.bottom = height; + if (newRc.left == m_outputSize.left + && newRc.top == m_outputSize.top + && newRc.right == m_outputSize.right + && newRc.bottom == m_outputSize.bottom + && rotation == m_rotation) + { + return false; + } + + m_outputSize = newRc; + m_rotation = rotation; + CreateWindowSizeDependentResources(); + return true; +} + +// This method is called in the event handler for the DisplayContentsInvalidated event. +void DX::DeviceResources::ValidateDevice() +{ + // The D3D Device is no longer valid if the default adapter changed since the device + // was created or if the device has been removed. + + DXGI_ADAPTER_DESC previousDesc; + { + ComPtr previousDefaultAdapter; + DX::ThrowIfFailed(m_dxgiFactory->EnumAdapters1(0, previousDefaultAdapter.GetAddressOf())); + + DX::ThrowIfFailed(previousDefaultAdapter->GetDesc(&previousDesc)); + } + + DXGI_ADAPTER_DESC currentDesc; + { + ComPtr currentFactory; + DX::ThrowIfFailed(CreateDXGIFactory1(IID_PPV_ARGS(currentFactory.GetAddressOf()))); + + ComPtr currentDefaultAdapter; + DX::ThrowIfFailed(currentFactory->EnumAdapters1(0, currentDefaultAdapter.GetAddressOf())); + + DX::ThrowIfFailed(currentDefaultAdapter->GetDesc(¤tDesc)); + } + + // If the adapter LUIDs don't match, or if the device reports that it has been removed, + // a new D3D device must be created. + + if (previousDesc.AdapterLuid.LowPart != currentDesc.AdapterLuid.LowPart + || previousDesc.AdapterLuid.HighPart != currentDesc.AdapterLuid.HighPart + || FAILED(m_d3dDevice->GetDeviceRemovedReason())) + { +#ifdef _DEBUG + OutputDebugStringA("Device Lost on ValidateDevice\n"); +#endif + + // Create a new device and swap chain. + HandleDeviceLost(); + } +} + +// Recreate all device resources and set them back to the current state. +void DX::DeviceResources::HandleDeviceLost() +{ + if (m_deviceNotify) + { + m_deviceNotify->OnDeviceLost(); + } + + for (UINT n = 0; n < m_backBufferCount; n++) + { + m_commandAllocators[n].Reset(); + m_renderTargets[n].Reset(); + } + + m_depthStencil.Reset(); + m_commandQueue.Reset(); + m_commandList.Reset(); + m_fence.Reset(); + m_rtvDescriptorHeap.Reset(); + m_dsvDescriptorHeap.Reset(); + m_swapChain.Reset(); + m_d3dDevice.Reset(); + m_dxgiFactory.Reset(); + +#ifdef _DEBUG + { + ComPtr dxgiDebug; + if (SUCCEEDED(DXGIGetDebugInterface1(0, IID_PPV_ARGS(&dxgiDebug)))) + { + dxgiDebug->ReportLiveObjects(DXGI_DEBUG_ALL, DXGI_DEBUG_RLO_FLAGS(DXGI_DEBUG_RLO_SUMMARY | DXGI_DEBUG_RLO_IGNORE_INTERNAL)); + } + } +#endif + + CreateDeviceResources(); + CreateWindowSizeDependentResources(); + + if (m_deviceNotify) + { + m_deviceNotify->OnDeviceRestored(); + } +} + +// Prepare the command list and render target for rendering. +void DX::DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState) +{ + // Reset command list and allocator. + DX::ThrowIfFailed(m_commandAllocators[m_backBufferIndex]->Reset()); + DX::ThrowIfFailed(m_commandList->Reset(m_commandAllocators[m_backBufferIndex].Get(), nullptr)); + + if (beforeState != D3D12_RESOURCE_STATE_RENDER_TARGET) + { + // Transition the render target into the correct state to allow for drawing into it. + D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_RENDER_TARGET); + m_commandList->ResourceBarrier(1, &barrier); + } +} + +// Present the contents of the swap chain to the screen. +void DX::DeviceResources::Present(D3D12_RESOURCE_STATES beforeState) +{ + if (beforeState != D3D12_RESOURCE_STATE_PRESENT) + { + // Transition the render target to the state that allows it to be presented to the display. + D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_PRESENT); + m_commandList->ResourceBarrier(1, &barrier); + } + + // Send the command list off to the GPU for processing. + DX::ThrowIfFailed(m_commandList->Close()); + m_commandQueue->ExecuteCommandLists(1, CommandListCast(m_commandList.GetAddressOf())); + + 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) + { +#ifdef _DEBUG + char buff[64] = {}; + sprintf_s(buff, "Device Lost on Present: Reason code 0x%08X\n", (hr == DXGI_ERROR_DEVICE_REMOVED) ? m_d3dDevice->GetDeviceRemovedReason() : hr); + OutputDebugStringA(buff); +#endif + HandleDeviceLost(); + } + else + { + DX::ThrowIfFailed(hr); + + MoveToNextFrame(); + } +} + +// Wait for pending GPU work to complete. +void DX::DeviceResources::WaitForGpu() noexcept +{ + if (m_commandQueue && m_fence && m_fenceEvent.IsValid()) + { + // Schedule a Signal command in the GPU queue. + UINT64 fenceValue = m_fenceValues[m_backBufferIndex]; + if (SUCCEEDED(m_commandQueue->Signal(m_fence.Get(), fenceValue))) + { + // Wait until the Signal has been processed. + if (SUCCEEDED(m_fence->SetEventOnCompletion(fenceValue, m_fenceEvent.Get()))) + { + WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + + // Increment the fence value for the current frame. + m_fenceValues[m_backBufferIndex]++; + } + } + } +} + +// Prepare to render the next frame. +void DX::DeviceResources::MoveToNextFrame() +{ + // Schedule a Signal command in the queue. + const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; + DX::ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); + + // Update the back buffer index. + m_backBufferIndex = m_swapChain->GetCurrentBackBufferIndex(); + + // If the next frame is not ready to be rendered yet, wait until it is ready. + if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) + { + DX::ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); + WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + } + + // Set the fence value for the next frame. + m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; +} + +// This method acquires the first available hardware adapter that supports Direct3D 12. +// If no such adapter can be found, try WARP. Otherwise throw an exception. +void DX::DeviceResources::GetAdapter(IDXGIAdapter1** ppAdapter) +{ + *ppAdapter = nullptr; + + ComPtr adapter; + for (UINT adapterIndex = 0; DXGI_ERROR_NOT_FOUND != m_dxgiFactory->EnumAdapters1(adapterIndex, adapter.ReleaseAndGetAddressOf()); ++adapterIndex) + { + DXGI_ADAPTER_DESC1 desc; + DX::ThrowIfFailed(adapter->GetDesc1(&desc)); + + if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) + { + // Don't select the Basic Render Driver adapter. + continue; + } + + // Check to see if the adapter supports Direct3D 12, but don't create the actual device yet. + if (SUCCEEDED(D3D12CreateDevice(adapter.Get(), m_d3dMinFeatureLevel, _uuidof(ID3D12Device), nullptr))) + { +#ifdef _DEBUG + wchar_t buff[256] = {}; + swprintf_s(buff, L"Direct3D Adapter (%u): VID:%04X, PID:%04X - %ls\n", adapterIndex, desc.VendorId, desc.DeviceId, desc.Description); + OutputDebugStringW(buff); +#endif + break; + } + } + +#if !defined(NDEBUG) + if (!adapter) + { + // Try WARP12 instead + if (FAILED(m_dxgiFactory->EnumWarpAdapter(IID_PPV_ARGS(adapter.ReleaseAndGetAddressOf())))) + { + throw std::exception("WARP12 not available. Enable the 'Graphics Tools' optional feature"); + } + + OutputDebugStringA("Direct3D Adapter - WARP12\n"); + } +#endif + + if (!adapter) + { + throw std::exception("No Direct3D 12 device found"); + } + + *ppAdapter = adapter.Detach(); +} diff --git a/Samples/IntroGraphics/SimpleMSAA_UWP12/DeviceResources.h b/Samples/IntroGraphics/SimpleMSAA_UWP12/DeviceResources.h new file mode 100644 index 00000000..a52a8c70 --- /dev/null +++ b/Samples/IntroGraphics/SimpleMSAA_UWP12/DeviceResources.h @@ -0,0 +1,124 @@ +// +// DeviceResources.h - A wrapper for the Direct3D 12 device and swapchain +// + +#pragma once + +namespace DX +{ + // Provides an interface for an application that owns DeviceResources to be notified of the device being lost or created. + interface IDeviceNotify + { + virtual void OnDeviceLost() = 0; + virtual void OnDeviceRestored() = 0; + }; + + // Controls all the DirectX device resources. + 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, + unsigned int flags = 0); + ~DeviceResources(); + + void CreateDeviceResources(); + void CreateWindowSizeDependentResources(); + void SetWindow(IUnknown* window, int width, int height, DXGI_MODE_ROTATION rotation); + bool WindowSizeChanged(int width, int height, DXGI_MODE_ROTATION rotation); + void ValidateDevice(); + void HandleDeviceLost(); + void RegisterDeviceNotify(IDeviceNotify* deviceNotify) { m_deviceNotify = deviceNotify; } + void Prepare(D3D12_RESOURCE_STATES beforeState = D3D12_RESOURCE_STATE_PRESENT); + void Present(D3D12_RESOURCE_STATES beforeState = D3D12_RESOURCE_STATE_RENDER_TARGET); + void WaitForGpu() noexcept; + + // Device Accessors. + RECT GetOutputSize() const { return m_outputSize; } + DXGI_MODE_ROTATION GetRotation() const { return m_rotation; } + + // Direct3D Accessors. + ID3D12Device* GetD3DDevice() const { return m_d3dDevice.Get(); } + IDXGISwapChain3* GetSwapChain() const { return m_swapChain.Get(); } + D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; } + ID3D12Resource* GetRenderTarget() const { return m_renderTargets[m_backBufferIndex].Get(); } + ID3D12Resource* GetDepthStencil() const { return m_depthStencil.Get(); } + ID3D12CommandQueue* GetCommandQueue() const { return m_commandQueue.Get(); } + ID3D12CommandAllocator* GetCommandAllocator() const { return m_commandAllocators[m_backBufferIndex].Get(); } + ID3D12GraphicsCommandList* GetCommandList() const { return m_commandList.Get(); } + DXGI_FORMAT GetBackBufferFormat() const { return m_backBufferFormat; } + DXGI_FORMAT GetDepthBufferFormat() const { return m_depthBufferFormat; } + D3D12_VIEWPORT GetScreenViewport() const { return m_screenViewport; } + D3D12_RECT GetScissorRect() const { return m_scissorRect; } + 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 + { + return CD3DX12_CPU_DESCRIPTOR_HANDLE(m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), m_backBufferIndex, m_rtvDescriptorSize); + } + CD3DX12_CPU_DESCRIPTOR_HANDLE GetDepthStencilView() const + { + return CD3DX12_CPU_DESCRIPTOR_HANDLE(m_dsvDescriptorHeap->GetCPUDescriptorHandleForHeapStart()); + } + + private: + void MoveToNextFrame(); + void GetAdapter(IDXGIAdapter1** ppAdapter); + + const static size_t MAX_BACK_BUFFER_COUNT = 3; + + UINT m_backBufferIndex; + + // Direct3D objects. + Microsoft::WRL::ComPtr m_d3dDevice; + Microsoft::WRL::ComPtr m_commandQueue; + Microsoft::WRL::ComPtr m_commandList; + Microsoft::WRL::ComPtr m_commandAllocators[MAX_BACK_BUFFER_COUNT]; + + // Swap chain objects. + Microsoft::WRL::ComPtr m_dxgiFactory; + Microsoft::WRL::ComPtr m_swapChain; + Microsoft::WRL::ComPtr m_renderTargets[MAX_BACK_BUFFER_COUNT]; + Microsoft::WRL::ComPtr m_depthStencil; + + // Presentation fence objects. + Microsoft::WRL::ComPtr m_fence; + UINT64 m_fenceValues[MAX_BACK_BUFFER_COUNT]; + Microsoft::WRL::Wrappers::Event m_fenceEvent; + + // Direct3D rendering objects. + Microsoft::WRL::ComPtr m_rtvDescriptorHeap; + Microsoft::WRL::ComPtr m_dsvDescriptorHeap; + UINT m_rtvDescriptorSize; + D3D12_VIEWPORT m_screenViewport; + D3D12_RECT m_scissorRect; + + // Direct3D properties. + DXGI_FORMAT m_backBufferFormat; + DXGI_FORMAT m_depthBufferFormat; + UINT m_backBufferCount; + D3D_FEATURE_LEVEL m_d3dMinFeatureLevel; + + // Cached device properties. + IUnknown* m_window; + D3D_FEATURE_LEVEL m_d3dFeatureLevel; + 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; + + // The IDeviceNotify can be held directly as it owns the DeviceResources. + IDeviceNotify* m_deviceNotify; + }; +} diff --git a/Samples/IntroGraphics/SimpleMSAA_UWP12/Main.cpp b/Samples/IntroGraphics/SimpleMSAA_UWP12/Main.cpp new file mode 100644 index 00000000..e3db753a --- /dev/null +++ b/Samples/IntroGraphics/SimpleMSAA_UWP12/Main.cpp @@ -0,0 +1,431 @@ +//-------------------------------------------------------------------------------------- +// Main.cpp +// +// Entry point for Universal Windows Platform (UWP) app. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SimpleMSAA.h" + +#include "Telemetry.h" + +#include + +using namespace concurrency; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Core; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::UI::Core; +using namespace Windows::UI::Input; +using namespace Windows::UI::ViewManagement; +using namespace Windows::System; +using namespace Windows::Foundation; +using namespace Windows::Graphics::Display; +using namespace DirectX; + +ref class ViewProvider sealed : public IFrameworkView +{ +public: + ViewProvider() : + m_exit(false), + m_visible(true), + m_in_sizemove(false), + m_DPI(96.f), + m_logicalWidth(800.f), + m_logicalHeight(600.f), + m_nativeOrientation(DisplayOrientations::None), + m_currentOrientation(DisplayOrientations::None) + { + } + + // IFrameworkView methods + virtual void Initialize(CoreApplicationView^ applicationView) + { + applicationView->Activated += + ref new TypedEventHandler(this, &ViewProvider::OnActivated); + + CoreApplication::Suspending += + ref new EventHandler(this, &ViewProvider::OnSuspending); + + CoreApplication::Resuming += + ref new EventHandler(this, &ViewProvider::OnResuming); + + m_sample = std::make_unique(); + + // Sample Usage Telemetry + // + // Disable or remove this code block to opt-out of sample usage telemetry + // + if (ATG::EventRegisterATGSampleTelemetry() == ERROR_SUCCESS) + { + wchar_t exeName[MAX_PATH + 1] = {}; + if (!GetModuleFileNameW(nullptr, exeName, MAX_PATH)) + { + wcscpy_s(exeName, L"Unknown"); + } + wchar_t fname[_MAX_FNAME] = {}; + wchar_t ext[_MAX_EXT] = {}; + (void)_wsplitpath_s(exeName, nullptr, 0, nullptr, 0, fname, _MAX_FNAME, ext, _MAX_EXT); + (void)_wmakepath_s(exeName, nullptr, nullptr, fname, ext); // keep only the filename + extension + + ATG::EventWriteSampleLoaded(exeName); + } + } + + virtual void Uninitialize() + { + m_sample.reset(); + } + + virtual void SetWindow(CoreWindow^ window) + { + window->SizeChanged += + ref new TypedEventHandler(this, &ViewProvider::OnWindowSizeChanged); + +#if defined(NTDDI_WIN10_RS2) && (NTDDI_VERSION >= NTDDI_WIN10_RS2) + try + { + window->ResizeStarted += + ref new TypedEventHandler(this, &ViewProvider::OnResizeStarted); + + window->ResizeCompleted += + ref new TypedEventHandler(this, &ViewProvider::OnResizeCompleted); + } + catch (...) + { + // Requires Windows 10 Creators Update (10.0.15063) or later + } +#endif + + window->VisibilityChanged += + ref new TypedEventHandler(this, &ViewProvider::OnVisibilityChanged); + + window->Closed += + ref new TypedEventHandler(this, &ViewProvider::OnWindowClosed); + + auto dispatcher = CoreWindow::GetForCurrentThread()->Dispatcher; + + dispatcher->AcceleratorKeyActivated += + ref new TypedEventHandler(this, &ViewProvider::OnAcceleratorKeyActivated); + + auto currentDisplayInformation = DisplayInformation::GetForCurrentView(); + + currentDisplayInformation->DpiChanged += + ref new TypedEventHandler(this, &ViewProvider::OnDpiChanged); + + currentDisplayInformation->OrientationChanged += + ref new TypedEventHandler(this, &ViewProvider::OnOrientationChanged); + + DisplayInformation::DisplayContentsInvalidated += + ref new TypedEventHandler(this, &ViewProvider::OnDisplayContentsInvalidated); + + m_DPI = currentDisplayInformation->LogicalDpi; + + m_logicalWidth = window->Bounds.Width; + m_logicalHeight = window->Bounds.Height; + + m_nativeOrientation = currentDisplayInformation->NativeOrientation; + m_currentOrientation = currentDisplayInformation->CurrentOrientation; + + int outputWidth = ConvertDipsToPixels(m_logicalWidth); + int outputHeight = ConvertDipsToPixels(m_logicalHeight); + + DXGI_MODE_ROTATION rotation = ComputeDisplayRotation(); + + if (rotation == DXGI_MODE_ROTATION_ROTATE90 || rotation == DXGI_MODE_ROTATION_ROTATE270) + { + std::swap(outputWidth, outputHeight); + } + + m_sample->Initialize(reinterpret_cast(window), + outputWidth, outputHeight, rotation ); + + Mouse::SetDpi(m_DPI); + } + + virtual void Load(Platform::String^ entryPoint) + { + } + + virtual void Run() + { + while (!m_exit) + { + if (m_visible) + { + m_sample->Tick(); + + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); + } + else + { + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessOneAndAllPending); + } + } + } + +protected: + // Event handlers + void OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) + { + if (args->Kind == ActivationKind::Launch) + { + auto launchArgs = static_cast(args); + + if (launchArgs->PrelaunchActivated) + { + // Opt-out of Prelaunch + CoreApplication::Exit(); + return; + } + } + + int w, h; + m_sample->GetDefaultSize(w, h); + + m_DPI = DisplayInformation::GetForCurrentView()->LogicalDpi; + + ApplicationView::PreferredLaunchWindowingMode = ApplicationViewWindowingMode::PreferredLaunchViewSize; + // Change to ApplicationViewWindowingMode::FullScreen to default to full screen + + auto desiredSize = Size(ConvertPixelsToDips(w), ConvertPixelsToDips(h)); + + ApplicationView::PreferredLaunchViewSize = desiredSize; + + auto view = ApplicationView::GetForCurrentView(); + + auto minSize = Size(ConvertPixelsToDips(320), ConvertPixelsToDips(200)); + + view->SetPreferredMinSize(minSize); + + CoreWindow::GetForCurrentThread()->Activate(); + + view->FullScreenSystemOverlayMode = FullScreenSystemOverlayMode::Minimal; + + view->TryResizeView(desiredSize); + } + + void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) + { + auto deferral = args->SuspendingOperation->GetDeferral(); + + create_task([this, deferral]() + { + m_sample->OnSuspending(); + + deferral->Complete(); + }); + } + + void OnResuming(Platform::Object^ sender, Platform::Object^ args) + { + m_sample->OnResuming(); + } + + void OnWindowSizeChanged(CoreWindow^ sender, WindowSizeChangedEventArgs^ args) + { + m_logicalWidth = sender->Bounds.Width; + m_logicalHeight = sender->Bounds.Height; + + if (m_in_sizemove) + return; + + HandleWindowSizeChanged(); + } + +#if defined(NTDDI_WIN10_RS2) && (NTDDI_VERSION >= NTDDI_WIN10_RS2) + void OnResizeStarted(CoreWindow^ sender, Platform::Object^ args) + { + m_in_sizemove = true; + } + + void OnResizeCompleted(CoreWindow^ sender, Platform::Object^ args) + { + m_in_sizemove = false; + + HandleWindowSizeChanged(); + } +#endif + + void OnVisibilityChanged(CoreWindow^ sender, VisibilityChangedEventArgs^ args) + { + m_visible = args->Visible; + if (m_visible) + m_sample->OnActivated(); + else + m_sample->OnDeactivated(); + } + + void OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) + { + m_exit = true; + } + + void OnAcceleratorKeyActivated(CoreDispatcher^, AcceleratorKeyEventArgs^ args) + { + if (args->EventType == CoreAcceleratorKeyEventType::SystemKeyDown + && args->VirtualKey == VirtualKey::Enter + && args->KeyStatus.IsMenuKeyDown + && !args->KeyStatus.WasKeyDown) + { + // Implements the classic ALT+ENTER fullscreen toggle + auto view = ApplicationView::GetForCurrentView(); + + if (view->IsFullScreenMode) + view->ExitFullScreenMode(); + else + view->TryEnterFullScreenMode(); + + args->Handled = true; + } + } + + void OnDpiChanged(DisplayInformation^ sender, Object^ args) + { + m_DPI = sender->LogicalDpi; + + HandleWindowSizeChanged(); + + Mouse::SetDpi(m_DPI); + } + + void OnOrientationChanged(DisplayInformation^ sender, Object^ args) + { + auto resizeManager = CoreWindowResizeManager::GetForCurrentView(); + resizeManager->ShouldWaitForLayoutCompletion = true; + + m_currentOrientation = sender->CurrentOrientation; + + HandleWindowSizeChanged(); + + resizeManager->NotifyLayoutCompleted(); + } + + void OnDisplayContentsInvalidated(DisplayInformation^ sender, Object^ args) + { + m_sample->ValidateDevice(); + } + +private: + bool m_exit; + bool m_visible; + bool m_in_sizemove; + float m_DPI; + float m_logicalWidth; + float m_logicalHeight; + std::unique_ptr m_sample; + + Windows::Graphics::Display::DisplayOrientations m_nativeOrientation; + Windows::Graphics::Display::DisplayOrientations m_currentOrientation; + + inline int ConvertDipsToPixels(float dips) const + { + return int(dips * m_DPI / 96.f + 0.5f); + } + + inline float ConvertPixelsToDips(int pixels) const + { + return (float(pixels) * 96.f / m_DPI); + } + + DXGI_MODE_ROTATION ComputeDisplayRotation() const + { + DXGI_MODE_ROTATION rotation = DXGI_MODE_ROTATION_UNSPECIFIED; + + switch (m_nativeOrientation) + { + case DisplayOrientations::Landscape: + switch (m_currentOrientation) + { + case DisplayOrientations::Landscape: + rotation = DXGI_MODE_ROTATION_IDENTITY; + break; + + case DisplayOrientations::Portrait: + rotation = DXGI_MODE_ROTATION_ROTATE270; + break; + + case DisplayOrientations::LandscapeFlipped: + rotation = DXGI_MODE_ROTATION_ROTATE180; + break; + + case DisplayOrientations::PortraitFlipped: + rotation = DXGI_MODE_ROTATION_ROTATE90; + break; + } + break; + + case DisplayOrientations::Portrait: + switch (m_currentOrientation) + { + case DisplayOrientations::Landscape: + rotation = DXGI_MODE_ROTATION_ROTATE90; + break; + + case DisplayOrientations::Portrait: + rotation = DXGI_MODE_ROTATION_IDENTITY; + break; + + case DisplayOrientations::LandscapeFlipped: + rotation = DXGI_MODE_ROTATION_ROTATE270; + break; + + case DisplayOrientations::PortraitFlipped: + rotation = DXGI_MODE_ROTATION_ROTATE180; + break; + } + break; + } + + return rotation; + } + + void HandleWindowSizeChanged() + { + int outputWidth = ConvertDipsToPixels(m_logicalWidth); + int outputHeight = ConvertDipsToPixels(m_logicalHeight); + + DXGI_MODE_ROTATION rotation = ComputeDisplayRotation(); + + if (rotation == DXGI_MODE_ROTATION_ROTATE90 || rotation == DXGI_MODE_ROTATION_ROTATE270) + { + std::swap(outputWidth, outputHeight); + } + + m_sample->OnWindowSizeChanged(outputWidth, outputHeight, rotation); + } +}; + +ref class ViewProviderFactory : IFrameworkViewSource +{ +public: + virtual IFrameworkView^ CreateView() + { + return ref new ViewProvider(); + } +}; + + +// Entry point +[Platform::MTAThread] +int __cdecl main(Platform::Array^ /*argv*/) +{ + if (!XMVerifyCPUSupport()) + { + throw std::exception("XMVerifyCPUSupport"); + } + + auto viewProviderFactory = ref new ViewProviderFactory(); + CoreApplication::Run(viewProviderFactory); + return 0; +} + + +// Exit helper +void ExitSample() +{ + Windows::ApplicationModel::Core::CoreApplication::Exit(); +} diff --git a/Samples/IntroGraphics/SimpleMSAA_UWP12/Package.appxmanifest b/Samples/IntroGraphics/SimpleMSAA_UWP12/Package.appxmanifest new file mode 100644 index 00000000..f59fa036 --- /dev/null +++ b/Samples/IntroGraphics/SimpleMSAA_UWP12/Package.appxmanifest @@ -0,0 +1,49 @@ + + + + + + + + + + SimpleMSAA + Xbox Advanced Technology Group + Assets\StoreLogo.png + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Samples/IntroGraphics/SimpleMSAA_UWP12/Readme.docx b/Samples/IntroGraphics/SimpleMSAA_UWP12/Readme.docx new file mode 100644 index 00000000..6abe9605 Binary files /dev/null and b/Samples/IntroGraphics/SimpleMSAA_UWP12/Readme.docx differ diff --git a/Samples/IntroGraphics/SimpleMSAA_UWP12/SimpleMSAA.cpp b/Samples/IntroGraphics/SimpleMSAA_UWP12/SimpleMSAA.cpp new file mode 100644 index 00000000..f7b34f38 --- /dev/null +++ b/Samples/IntroGraphics/SimpleMSAA_UWP12/SimpleMSAA.cpp @@ -0,0 +1,579 @@ +//-------------------------------------------------------------------------------------- +// SimpleMSAA.cpp +// +// This sample demonstrates setting up a MSAA render target for DirectX 12 +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SimpleMSAA.h" + +#include "ATGColors.h" +#include "ControllerFont.h" + +extern void ExitSample(); + +using namespace DirectX; +using namespace DirectX::SimpleMath; + +using Microsoft::WRL::ComPtr; + +namespace +{ + const DXGI_FORMAT c_backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM_SRGB; + const DXGI_FORMAT c_depthBufferFormat = DXGI_FORMAT_D32_FLOAT; + + unsigned int c_targetSampleCount = 4; +} + +Sample::Sample() : + m_sampleCount(0), + m_msaa(true), + m_gamepadPresent(false) +{ + m_deviceResources = std::make_unique( + c_backBufferFormat, + c_depthBufferFormat, /* If we were only doing MSAA rendering, we could skip the non-MSAA depth/stencil buffer with DXGI_FORMAT_UNKNOWN */ + 2); + m_deviceResources->RegisterDeviceNotify(this); + + // + // In Win32 'classic' DirectX 11, you can create the 'swapchain' backbuffer as a multisample buffer. Present took care of the + // resolve as part of the swapchain management. This implicit resolve behavior is not supported for UWP. + // +} + +// Initialize the Direct3D resources required to run. +void Sample::Initialize(::IUnknown* window, int width, int height, DXGI_MODE_ROTATION rotation) +{ + m_gamePad = std::make_unique(); + + m_keyboard = std::make_unique(); + m_keyboard->SetWindow(reinterpret_cast(window)); + + m_deviceResources->SetWindow(window, width, height, rotation); + + m_deviceResources->CreateDeviceResources(); + CreateDeviceDependentResources(); + + m_deviceResources->CreateWindowSizeDependentResources(); + CreateWindowSizeDependentResources(); +} + +#pragma region Frame Update +// Executes basic render loop. +void Sample::Tick() +{ + m_timer.Tick([&]() + { + Update(m_timer); + }); + + Render(); +} + +// Updates the world. +void Sample::Update(DX::StepTimer const& timer) +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Update"); + + float time = float(timer.GetTotalSeconds()); + + m_world = Matrix::CreateRotationZ(cosf(time / 4.f)); + + auto pad = m_gamePad->GetState(0); + m_gamepadPresent = pad.IsConnected(); + if (m_gamepadPresent) + { + m_gamePadButtons.Update(pad); + + if (pad.IsViewPressed()) + { + ExitSample(); + } + + if (m_gamePadButtons.a == GamePad::ButtonStateTracker::PRESSED) + { + m_msaa = !m_msaa; + } + } + else + { + m_gamePadButtons.Reset(); + } + + auto kb = m_keyboard->GetState(); + m_keyboardButtons.Update(kb); + + if (kb.Escape) + { + ExitSample(); + } + + if (m_keyboardButtons.IsKeyPressed(Keyboard::Keys::Space)) + { + m_msaa = !m_msaa; + } + + PIXEndEvent(); +} +#pragma endregion + +#pragma region Frame Render +// Draws the scene. +void Sample::Render() +{ + // Don't try to render anything before the first Update. + if (m_timer.GetFrameCount() == 0) + { + return; + } + + // Prepare the command list to render a new frame. + m_deviceResources->Prepare(m_msaa ? D3D12_RESOURCE_STATE_RENDER_TARGET : D3D12_RESOURCE_STATE_PRESENT); + Clear(); + + auto commandList = m_deviceResources->GetCommandList(); + PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Render"); + + // Draw the scene. + ID3D12DescriptorHeap* heaps[] = { m_modelResources->Heap(), m_states->Heap() }; + commandList->SetDescriptorHeaps(_countof(heaps), heaps); + + // Must use PSOs with MSAA sample counts that match our render target. + if (m_msaa) + { + Model::UpdateEffectMatrices(m_modelMSAA, m_world, m_view, m_proj); + + m_model->Draw(commandList, m_modelMSAA.cbegin()); + } + else + { + Model::UpdateEffectMatrices(m_modelStandard, m_world, m_view, m_proj); + + m_model->Draw(commandList, m_modelStandard.cbegin()); + } + + PIXEndEvent(commandList); + + if (m_msaa) + { + // Resolve the MSAA render target. + PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Resolve"); + + auto backBuffer = m_deviceResources->GetRenderTarget(); + + { + D3D12_RESOURCE_BARRIER barriers[2] = + { + CD3DX12_RESOURCE_BARRIER::Transition( + m_msaaRenderTarget.Get(), + D3D12_RESOURCE_STATE_RENDER_TARGET, + D3D12_RESOURCE_STATE_RESOLVE_SOURCE), + CD3DX12_RESOURCE_BARRIER::Transition( + backBuffer, + D3D12_RESOURCE_STATE_PRESENT, + D3D12_RESOURCE_STATE_RESOLVE_DEST) + }; + + commandList->ResourceBarrier(2, barriers); + } + + commandList->ResolveSubresource(backBuffer, 0, m_msaaRenderTarget.Get(), 0, c_backBufferFormat); + + PIXEndEvent(commandList); + + // Set render target for UI which is typically rendered without MSAA. + { + D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition( + backBuffer, + D3D12_RESOURCE_STATE_RESOLVE_DEST, + D3D12_RESOURCE_STATE_RENDER_TARGET); + commandList->ResourceBarrier(1, &barrier); + } + } + + // Unbind depth/stencil for UI. + auto rtvDescriptor = m_deviceResources->GetRenderTargetView(); + commandList->OMSetRenderTargets(1, &rtvDescriptor, FALSE, nullptr); + + // Draw UI. + PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Draw UI"); + + auto size = m_deviceResources->GetOutputSize(); + auto safe = SimpleMath::Viewport::ComputeTitleSafeArea(size.right, size.bottom); + + heaps[0] = m_resourceDescriptors->Heap(); + commandList->SetDescriptorHeaps(1, heaps); + + m_batch->Begin(commandList); + + wchar_t str[32] = {}; + swprintf_s(str, L"Sample count: %u", m_msaa ? m_sampleCount : 1); + m_smallFont->DrawString(m_batch.get(), str, XMFLOAT2(float(safe.left), float(safe.top)), ATG::Colors::White); + + const wchar_t* legend = m_gamepadPresent + ? L"[A] Toggle MSAA [View] Exit" + : L"Space: Toggle MSAA Esc: Exit"; + + DX::DrawControllerString(m_batch.get(), + m_smallFont.get(), m_ctrlFont.get(), + legend, + XMFLOAT2(float(safe.left), + float(safe.bottom) - m_smallFont->GetLineSpacing()), + ATG::Colors::LightGrey); + + m_batch->End(); + + PIXEndEvent(commandList); + + // Show the new frame. + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Present"); + m_deviceResources->Present(); + m_graphicsMemory->Commit(m_deviceResources->GetCommandQueue()); + PIXEndEvent(); +} + +// Helper method to clear the back buffers. +void Sample::Clear() +{ + auto commandList = m_deviceResources->GetCommandList(); + + PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Clear"); + + // Clear the views. + + if (m_msaa) + { + D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition( + m_msaaRenderTarget.Get(), + D3D12_RESOURCE_STATE_RESOLVE_SOURCE, + D3D12_RESOURCE_STATE_RENDER_TARGET); + commandList->ResourceBarrier(1, &barrier); + + // + // Rather than operate on the swapchain render target, we set up to render the scene to our MSAA resources instead. + // + + auto rtvDescriptor = m_msaaRTVDescriptorHeap->GetCPUDescriptorHandleForHeapStart(); + auto dsvDescriptor = m_msaaDSVDescriptorHeap->GetCPUDescriptorHandleForHeapStart(); + + commandList->OMSetRenderTargets(1, &rtvDescriptor, FALSE, &dsvDescriptor); + + commandList->ClearRenderTargetView(rtvDescriptor, ATG::ColorsLinear::Background, 0, nullptr); + commandList->ClearDepthStencilView(dsvDescriptor, D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr); + } + else + { + auto rtvDescriptor = m_deviceResources->GetRenderTargetView(); + auto dsvDescriptor = m_deviceResources->GetDepthStencilView(); + + commandList->OMSetRenderTargets(1, &rtvDescriptor, FALSE, &dsvDescriptor); + + commandList->ClearRenderTargetView(rtvDescriptor, ATG::ColorsLinear::Background, 0, nullptr); + commandList->ClearDepthStencilView(dsvDescriptor, D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr); + } + + // Set the viewport and scissor rect. + auto viewport = m_deviceResources->GetScreenViewport(); + auto scissorRect = m_deviceResources->GetScissorRect(); + commandList->RSSetViewports(1, &viewport); + commandList->RSSetScissorRects(1, &scissorRect); + + PIXEndEvent(commandList); +} +#pragma endregion + +#pragma region Message Handlers +// Message handlers +void Sample::OnActivated() +{ +} + +void Sample::OnDeactivated() +{ +} + +void Sample::OnSuspending() +{ +} + +void Sample::OnResuming() +{ + m_timer.ResetElapsedTime(); + m_gamePadButtons.Reset(); + m_keyboardButtons.Reset(); +} + +void Sample::OnWindowSizeChanged(int width, int height, DXGI_MODE_ROTATION rotation) +{ + if (!m_deviceResources->WindowSizeChanged(width, height, rotation)) + return; + + CreateWindowSizeDependentResources(); +} + +void Sample::ValidateDevice() +{ + m_deviceResources->ValidateDevice(); +} + +// Properties +void Sample::GetDefaultSize(int& width, int& height) const +{ + width = 1280; + height = 720; +} +#pragma endregion + +#pragma region Direct3D Resources +// These are the resources that depend on the device. +void Sample::CreateDeviceDependentResources() +{ + auto device = m_deviceResources->GetD3DDevice(); + + m_graphicsMemory = std::make_unique(device); + + // Create descriptor heaps for MSAA render target views and depth stencil views. + D3D12_DESCRIPTOR_HEAP_DESC rtvDescriptorHeapDesc = {}; + rtvDescriptorHeapDesc.NumDescriptors = 1; + rtvDescriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; + + DX::ThrowIfFailed(device->CreateDescriptorHeap(&rtvDescriptorHeapDesc, + IID_PPV_ARGS(m_msaaRTVDescriptorHeap.ReleaseAndGetAddressOf()))); + + D3D12_DESCRIPTOR_HEAP_DESC dsvDescriptorHeapDesc = {}; + dsvDescriptorHeapDesc.NumDescriptors = 1; + dsvDescriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV; + + DX::ThrowIfFailed(device->CreateDescriptorHeap(&dsvDescriptorHeapDesc, + IID_PPV_ARGS(m_msaaDSVDescriptorHeap.ReleaseAndGetAddressOf()))); + + // + // Check for MSAA support. + // + // Note that 4x MSAA and 8x MSAA is required for Direct3D Feature Level 11.0 or better + // + + for (m_sampleCount = c_targetSampleCount; m_sampleCount > 1; m_sampleCount--) + { + D3D12_FEATURE_DATA_MULTISAMPLE_QUALITY_LEVELS levels = { c_backBufferFormat, m_sampleCount }; + if (FAILED(device->CheckFeatureSupport(D3D12_FEATURE_MULTISAMPLE_QUALITY_LEVELS, &levels, sizeof(levels)))) + continue; + + if (levels.NumQualityLevels > 0) + break; + } + + if (m_sampleCount < 2) + { + throw std::exception("MSAA not supported"); + } + + // Setup test scene. + m_resourceDescriptors = std::make_unique(device, + D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, + D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE, + Descriptors::Count); + + m_states = std::make_unique(device); + + m_model = Model::CreateFromSDKMESH(L"CityBlockConcrete.sdkmesh"); + + ResourceUploadBatch resourceUpload(device); + resourceUpload.Begin(); + + m_modelResources = m_model->LoadTextures(device, resourceUpload); + + m_fxFactory = std::make_unique(m_modelResources->Heap(), m_states->Heap()); + + { + RenderTargetState rtStateUI(c_backBufferFormat, DXGI_FORMAT_UNKNOWN); + SpriteBatchPipelineStateDescription pd(rtStateUI); + + m_batch = std::make_unique(device, resourceUpload, pd); + } + + auto uploadResourcesFinished = resourceUpload.End(m_deviceResources->GetCommandQueue()); + uploadResourcesFinished.wait(); + + { + RenderTargetState rtState(c_backBufferFormat, c_depthBufferFormat); + rtState.sampleDesc.Count = m_sampleCount; + + EffectPipelineStateDescription pd( + nullptr, + CommonStates::Opaque, + CommonStates::DepthDefault, + CommonStates::CullClockwise, + rtState); + + EffectPipelineStateDescription pdAlpha( + nullptr, + CommonStates::AlphaBlend, + CommonStates::DepthDefault, + CommonStates::CullClockwise, + rtState); + + m_modelMSAA = m_model->CreateEffects(*m_fxFactory, pd, pdAlpha); + } + + { + RenderTargetState rtState(c_backBufferFormat, c_depthBufferFormat); + + EffectPipelineStateDescription pd( + nullptr, + CommonStates::Opaque, + CommonStates::DepthDefault, + CommonStates::CullClockwise, + rtState); + + EffectPipelineStateDescription pdAlpha( + nullptr, + CommonStates::AlphaBlend, + CommonStates::DepthDefault, + CommonStates::CullClockwise, + rtState); + + m_modelStandard = m_model->CreateEffects(*m_fxFactory, pd, pdAlpha); + } +} + +// Allocate all memory resources that change on a window SizeChanged event. +void Sample::CreateWindowSizeDependentResources() +{ + auto output = m_deviceResources->GetOutputSize(); + + // Determine the render target size in pixels. + UINT backBufferWidth = std::max(output.right - output.left, 1); + UINT backBufferHeight = std::max(output.bottom - output.top, 1); + + CD3DX12_HEAP_PROPERTIES heapProperties(D3D12_HEAP_TYPE_DEFAULT); + + // Create an MSAA render target. + D3D12_RESOURCE_DESC msaaRTDesc = CD3DX12_RESOURCE_DESC::Tex2D( + c_backBufferFormat, + backBufferWidth, + backBufferHeight, + 1, // This render target view has only one texture. + 1, // Use a single mipmap level + m_sampleCount + ); + msaaRTDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; + + D3D12_CLEAR_VALUE msaaOptimizedClearValue = {}; + msaaOptimizedClearValue.Format = c_backBufferFormat; + memcpy(msaaOptimizedClearValue.Color, ATG::ColorsLinear::Background, sizeof(float) * 4); + + auto device = m_deviceResources->GetD3DDevice(); + DX::ThrowIfFailed(device->CreateCommittedResource( + &heapProperties, + D3D12_HEAP_FLAG_NONE, + &msaaRTDesc, + D3D12_RESOURCE_STATE_RESOLVE_SOURCE, + &msaaOptimizedClearValue, + IID_PPV_ARGS(m_msaaRenderTarget.ReleaseAndGetAddressOf()) + )); + + m_msaaRenderTarget->SetName(L"MSAA Render Target"); + + D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = {}; + rtvDesc.Format = c_backBufferFormat; + rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DMS; + + device->CreateRenderTargetView( + m_msaaRenderTarget.Get(), &rtvDesc, + m_msaaRTVDescriptorHeap->GetCPUDescriptorHandleForHeapStart()); + + // Create an MSAA depth stencil view. + D3D12_RESOURCE_DESC depthStencilDesc = CD3DX12_RESOURCE_DESC::Tex2D( + c_depthBufferFormat, + backBufferWidth, + backBufferHeight, + 1, // This depth stencil view has only one texture. + 1, // Use a single mipmap level. + m_sampleCount + ); + depthStencilDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL; + + D3D12_CLEAR_VALUE depthOptimizedClearValue = {}; + depthOptimizedClearValue.Format = c_depthBufferFormat; + depthOptimizedClearValue.DepthStencil.Depth = 1.0f; + depthOptimizedClearValue.DepthStencil.Stencil = 0; + + DX::ThrowIfFailed(device->CreateCommittedResource( + &heapProperties, + D3D12_HEAP_FLAG_NONE, + &depthStencilDesc, + D3D12_RESOURCE_STATE_DEPTH_WRITE, + &depthOptimizedClearValue, + IID_PPV_ARGS(m_msaaDepthStencil.ReleaseAndGetAddressOf()) + )); + + D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = {}; + dsvDesc.Format = c_depthBufferFormat; + dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2DMS; + + device->CreateDepthStencilView( + m_msaaDepthStencil.Get(), &dsvDesc, + m_msaaDSVDescriptorHeap->GetCPUDescriptorHandleForHeapStart()); + + // Load UI. + ResourceUploadBatch resourceUpload(device); + resourceUpload.Begin(); + + m_smallFont = std::make_unique(device, resourceUpload, + L"SegoeUI_18.spritefont", + m_resourceDescriptors->GetCpuHandle(Descriptors::UIFont), + m_resourceDescriptors->GetGpuHandle(Descriptors::UIFont)); + + m_ctrlFont = std::make_unique(device, resourceUpload, + L"XboxOneControllerLegendSmall.spritefont", + m_resourceDescriptors->GetCpuHandle(Descriptors::CtrlFont), + m_resourceDescriptors->GetGpuHandle(Descriptors::CtrlFont)); + + auto uploadResourcesFinished = resourceUpload.End(m_deviceResources->GetCommandQueue()); + uploadResourcesFinished.wait(); + + // Setup test scene. + m_view = Matrix::CreateLookAt(Vector3(0, -211.f, -23.f), Vector3(6.f, 0.f, -37.f), -Vector3::UnitZ); + + m_proj = Matrix::CreatePerspectiveFieldOfView(XM_PI / 4.f, + float(backBufferWidth) / float(backBufferHeight), 0.1f, 1000.f); + + auto viewport = m_deviceResources->GetScreenViewport(); + m_batch->SetViewport(viewport); +} + +void Sample::OnDeviceLost() +{ + m_msaaRenderTarget.Reset(); + m_msaaDepthStencil.Reset(); + + m_msaaRTVDescriptorHeap.Reset(); + m_msaaDSVDescriptorHeap.Reset(); + + m_modelMSAA.clear(); + m_modelStandard.clear(); + m_model.reset(); + + m_batch.reset(); + m_resourceDescriptors.reset(); + m_smallFont.reset(); + m_ctrlFont.reset(); + m_states.reset(); + m_modelResources.reset(); + m_fxFactory.reset(); + + m_graphicsMemory.reset(); +} + +void Sample::OnDeviceRestored() +{ + CreateDeviceDependentResources(); + + CreateWindowSizeDependentResources(); +} +#pragma endregion diff --git a/Samples/IntroGraphics/SimpleMSAA_UWP12/SimpleMSAA.h b/Samples/IntroGraphics/SimpleMSAA_UWP12/SimpleMSAA.h new file mode 100644 index 00000000..0547af64 --- /dev/null +++ b/Samples/IntroGraphics/SimpleMSAA_UWP12/SimpleMSAA.h @@ -0,0 +1,106 @@ +//-------------------------------------------------------------------------------------- +// SimpleMSAA.h +// +// This sample demonstrates setting up a MSAA render target for DirectX 12 +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "DeviceResources.h" +#include "StepTimer.h" + + +// A basic sample implementation that creates a D3D12 device and +// provides a render loop. +class Sample : public DX::IDeviceNotify +{ +public: + + Sample(); + + // Initialization and management + void Initialize(::IUnknown* window, int width, int height, DXGI_MODE_ROTATION rotation); + + // Basic render loop + void Tick(); + + // IDeviceNotify + virtual void OnDeviceLost() override; + virtual void OnDeviceRestored() override; + + // Messages + void OnActivated(); + void OnDeactivated(); + void OnSuspending(); + void OnResuming(); + void OnWindowSizeChanged(int width, int height, DXGI_MODE_ROTATION rotation); + void ValidateDevice(); + + // Properties + void GetDefaultSize( int& width, int& height ) const; + +private: + + void Update(DX::StepTimer const& timer); + void Render(); + + void Clear(); + + void CreateDeviceDependentResources(); + void CreateWindowSizeDependentResources(); + + // Device resources. + std::unique_ptr m_deviceResources; + + // MSAA resources. + Microsoft::WRL::ComPtr m_msaaRenderTarget; + Microsoft::WRL::ComPtr m_msaaDepthStencil; + + Microsoft::WRL::ComPtr m_msaaRTVDescriptorHeap; + Microsoft::WRL::ComPtr m_msaaDSVDescriptorHeap; + + unsigned int m_sampleCount; + bool m_msaa; + + // Rendering loop timer. + DX::StepTimer m_timer; + + // Input devices. + std::unique_ptr m_gamePad; + std::unique_ptr m_keyboard; + + DirectX::GamePad::ButtonStateTracker m_gamePadButtons; + DirectX::Keyboard::KeyboardStateTracker m_keyboardButtons; + bool m_gamepadPresent; + + // DirectXTK objects. + std::unique_ptr m_graphicsMemory; + std::unique_ptr m_batch; + + std::unique_ptr m_resourceDescriptors; + + enum Descriptors + { + UIFont, + CtrlFont, + Count + }; + + std::unique_ptr m_smallFont; + std::unique_ptr m_ctrlFont; + + std::unique_ptr m_states; + std::unique_ptr m_model; + std::unique_ptr m_modelResources; + std::unique_ptr m_fxFactory; + + std::vector> m_modelMSAA; + std::vector> m_modelStandard; + + DirectX::SimpleMath::Matrix m_world; + DirectX::SimpleMath::Matrix m_view; + DirectX::SimpleMath::Matrix m_proj; +}; \ No newline at end of file diff --git a/Samples/IntroGraphics/SimpleMSAA_UWP12/SimpleMSAA.sln b/Samples/IntroGraphics/SimpleMSAA_UWP12/SimpleMSAA.sln new file mode 100644 index 00000000..457a8ed6 --- /dev/null +++ b/Samples/IntroGraphics/SimpleMSAA_UWP12/SimpleMSAA.sln @@ -0,0 +1,54 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2017 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SimpleMSAA", "SimpleMSAA.vcxproj", "{D6E2F153-4A12-41D1-A77E-EC6F2160A69F}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTK12", "..\..\..\Kits\DirectXTK12\DirectXTK_Windows10.vcxproj", "{945B8F0E-AE5F-447C-933A-9D069532D3E4}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|ARM = Debug|ARM + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|ARM = Release|ARM + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D6E2F153-4A12-41D1-A77E-EC6F2160A69F}.Debug|ARM.ActiveCfg = Debug|ARM + {D6E2F153-4A12-41D1-A77E-EC6F2160A69F}.Debug|ARM.Build.0 = Debug|ARM + {D6E2F153-4A12-41D1-A77E-EC6F2160A69F}.Debug|ARM.Deploy.0 = Debug|ARM + {D6E2F153-4A12-41D1-A77E-EC6F2160A69F}.Debug|x64.ActiveCfg = Debug|x64 + {D6E2F153-4A12-41D1-A77E-EC6F2160A69F}.Debug|x64.Build.0 = Debug|x64 + {D6E2F153-4A12-41D1-A77E-EC6F2160A69F}.Debug|x64.Deploy.0 = Debug|x64 + {D6E2F153-4A12-41D1-A77E-EC6F2160A69F}.Debug|x86.ActiveCfg = Debug|Win32 + {D6E2F153-4A12-41D1-A77E-EC6F2160A69F}.Debug|x86.Build.0 = Debug|Win32 + {D6E2F153-4A12-41D1-A77E-EC6F2160A69F}.Debug|x86.Deploy.0 = Debug|Win32 + {D6E2F153-4A12-41D1-A77E-EC6F2160A69F}.Release|ARM.ActiveCfg = Release|ARM + {D6E2F153-4A12-41D1-A77E-EC6F2160A69F}.Release|ARM.Build.0 = Release|ARM + {D6E2F153-4A12-41D1-A77E-EC6F2160A69F}.Release|ARM.Deploy.0 = Release|ARM + {D6E2F153-4A12-41D1-A77E-EC6F2160A69F}.Release|x64.ActiveCfg = Release|x64 + {D6E2F153-4A12-41D1-A77E-EC6F2160A69F}.Release|x64.Build.0 = Release|x64 + {D6E2F153-4A12-41D1-A77E-EC6F2160A69F}.Release|x64.Deploy.0 = Release|x64 + {D6E2F153-4A12-41D1-A77E-EC6F2160A69F}.Release|x86.ActiveCfg = Release|Win32 + {D6E2F153-4A12-41D1-A77E-EC6F2160A69F}.Release|x86.Build.0 = Release|Win32 + {D6E2F153-4A12-41D1-A77E-EC6F2160A69F}.Release|x86.Deploy.0 = Release|Win32 + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Debug|ARM.ActiveCfg = Debug|ARM + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Debug|ARM.Build.0 = Debug|ARM + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Debug|x64.ActiveCfg = Debug|x64 + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Debug|x64.Build.0 = Debug|x64 + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Debug|x86.ActiveCfg = Debug|Win32 + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Debug|x86.Build.0 = Debug|Win32 + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Release|ARM.ActiveCfg = Release|ARM + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Release|ARM.Build.0 = Release|ARM + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Release|x64.ActiveCfg = Release|x64 + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Release|x64.Build.0 = Release|x64 + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Release|x86.ActiveCfg = Release|Win32 + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/IntroGraphics/SimpleMSAA_UWP12/SimpleMSAA.vcxproj b/Samples/IntroGraphics/SimpleMSAA_UWP12/SimpleMSAA.vcxproj new file mode 100644 index 00000000..08755db3 --- /dev/null +++ b/Samples/IntroGraphics/SimpleMSAA_UWP12/SimpleMSAA.vcxproj @@ -0,0 +1,317 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + Debug + ARM + + + Release + ARM + + + + {d6e2f153-4a12-41d1-a77e-ec6f2160a69f} + DirectXApp + SimpleMSAA + en-US + 14.0 + true + Windows Store + 10.0.15063.0 + 10.0.14393.0 + 10.0 + + + + Application + true + v141 + x64 + + + Application + true + v141 + x64 + + + Application + true + v141 + x64 + + + Application + false + true + v141 + x64 + + + Application + false + true + v141 + x64 + + + Application + false + true + v141 + x64 + + + + + + + + + + + + + + + + + + + + + + + + + + + false + false + + + + ATGTelemetryUWP.lib; d2d1.lib; d3d12.lib; dxgi.lib; dxguid.lib; windowscodecs.lib; dwrite.lib; %(AdditionalDependencies) + ..\..\..\Kits\Telemetry\$(Platform); %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\arm; $(VCInstallDir)\lib\arm + true + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;..\..\..\Kits\Telemetry;%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + Level4 + _DEBUG;%(PreprocessorDefinitions) + Fast + + + 5.1 + + + + + ATGTelemetryUWP.lib; d2d1.lib; d3d12.lib; dxgi.lib; dxguid.lib; windowscodecs.lib; dwrite.lib; %(AdditionalDependencies) + ..\..\..\Kits\Telemetry\$(Platform); %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\arm; $(VCInstallDir)\lib\arm + true + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;..\..\..\Kits\Telemetry;%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + Level4 + NDEBUG;%(PreprocessorDefinitions) + Fast + + + 5.1 + + + + + ATGTelemetryUWP.lib; d2d1.lib; d3d12.lib; dxgi.lib; dxguid.lib; windowscodecs.lib; dwrite.lib; %(AdditionalDependencies) + ..\..\..\Kits\Telemetry\$(Platform); %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store; $(VCInstallDir)\lib + true + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;..\..\..\Kits\Telemetry;%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + Level4 + _DEBUG;%(PreprocessorDefinitions) + Fast + StreamingSIMDExtensions2 + + + 5.1 + + + + + ATGTelemetryUWP.lib; d2d1.lib; d3d12.lib; dxgi.lib; dxguid.lib; windowscodecs.lib; dwrite.lib; %(AdditionalDependencies) + ..\..\..\Kits\Telemetry\$(Platform); %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store; $(VCInstallDir)\lib + true + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;..\..\..\Kits\Telemetry;%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + Level4 + NDEBUG;%(PreprocessorDefinitions) + Fast + StreamingSIMDExtensions2 + + + 5.1 + + + + + ATGTelemetryUWP.lib; d2d1.lib; d3d12.lib; dxgi.lib; dxguid.lib; windowscodecs.lib; dwrite.lib; %(AdditionalDependencies) + ..\..\..\Kits\Telemetry\$(Platform); %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\amd64; $(VCInstallDir)\lib\amd64 + true + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;..\..\..\Kits\Telemetry;%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + Level4 + _DEBUG;%(PreprocessorDefinitions) + Fast + + + 5.1 + + + + + ATGTelemetryUWP.lib; d2d1.lib; d3d12.lib; dxgi.lib; dxguid.lib; windowscodecs.lib; dwrite.lib; %(AdditionalDependencies) + ..\..\..\Kits\Telemetry\$(Platform); %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\amd64; $(VCInstallDir)\lib\amd64 + true + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;..\..\..\Kits\Telemetry;%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + Level4 + NDEBUG;%(PreprocessorDefinitions) + Fast + + + 5.1 + + + + + + + + + + + + + + + + + Create + Create + Create + Create + Create + Create + + + + + Designer + + + + + + + + + + + + + + true + true + true + ATGTelemetryUWP.dll + + + true + true + true + ATGTelemetryUWP.dll + + + true + true + true + ATGTelemetryUWP.dll + + + true + true + true + true + true + true + + + true + true + true + true + true + true + + + true + true + true + true + true + true + + + + + + {945b8f0e-ae5f-447c-933a-9d069532d3e4} + + + + + + + + + \ No newline at end of file diff --git a/Samples/IntroGraphics/SimpleMSAA_UWP12/SimpleMSAA.vcxproj.filters b/Samples/IntroGraphics/SimpleMSAA_UWP12/SimpleMSAA.vcxproj.filters new file mode 100644 index 00000000..e9cdea6f --- /dev/null +++ b/Samples/IntroGraphics/SimpleMSAA_UWP12/SimpleMSAA.vcxproj.filters @@ -0,0 +1,101 @@ + + + + + f0e37bfd-aedb-4fa9-a307-71d88c13eb8f + + + 3ff1b298-6472-4a7c-99f6-7618c23aac1d + bmp;dds;fbx;gif;jpg;jpeg;tga;tiff;tif;png + + + 24017e59-e780-4377-a6e4-36fd8d36f934 + + + c270197c-3acb-4f81-892b-0d9631c07f10 + + + a992a104-e143-459c-86e3-3daad22ea607 + + + bc162c17-fffe-42b9-88b4-5a0062d36045 + + + 19de601a-c18e-44ac-bd6b-cba8c021e4fb + + + + + + + Common + + + Common + + + ATG Tool Kit + + + ATG Tool Kit + + + ATG Tool Kit + + + + + + + + Common + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + + + Common\Telemetry\ARM + + + Common\Telemetry\Win32 + + + Common\Telemetry\x64 + + + Assets + + + Assets + + + Assets + + + + + + + \ No newline at end of file diff --git a/Samples/IntroGraphics/SimpleMSAA_UWP12/StepTimer.h b/Samples/IntroGraphics/SimpleMSAA_UWP12/StepTimer.h new file mode 100644 index 00000000..f55db2f8 --- /dev/null +++ b/Samples/IntroGraphics/SimpleMSAA_UWP12/StepTimer.h @@ -0,0 +1,188 @@ +// +// StepTimer.h - A simple timer that provides elapsed time information +// + +#pragma once + +#include +#include + +namespace DX +{ + // Helper class for animation and simulation timing. + class StepTimer + { + public: + StepTimer() : + m_elapsedTicks(0), + m_totalTicks(0), + m_leftOverTicks(0), + m_frameCount(0), + m_framesPerSecond(0), + m_framesThisSecond(0), + m_qpcSecondCounter(0), + m_isFixedTimeStep(false), + m_targetElapsedTicks(TicksPerSecond / 60) + { + if (!QueryPerformanceFrequency(&m_qpcFrequency)) + { + throw std::exception( "QueryPerformanceFrequency" ); + } + + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + // Initialize max delta to 1/10 of a second. + m_qpcMaxDelta = m_qpcFrequency.QuadPart / 10; + } + + // Get elapsed time since the previous Update call. + uint64_t GetElapsedTicks() const { return m_elapsedTicks; } + double GetElapsedSeconds() const { return TicksToSeconds(m_elapsedTicks); } + + // Get total time since the start of the program. + uint64_t GetTotalTicks() const { return m_totalTicks; } + double GetTotalSeconds() const { return TicksToSeconds(m_totalTicks); } + + // Get total number of updates since start of the program. + uint32_t GetFrameCount() const { return m_frameCount; } + + // Get the current framerate. + uint32_t GetFramesPerSecond() const { return m_framesPerSecond; } + + // Set whether to use fixed or variable timestep mode. + void SetFixedTimeStep(bool isFixedTimestep) { m_isFixedTimeStep = isFixedTimestep; } + + // Set how often to call Update when in fixed timestep mode. + void SetTargetElapsedTicks(uint64_t targetElapsed) { m_targetElapsedTicks = targetElapsed; } + void SetTargetElapsedSeconds(double targetElapsed) { m_targetElapsedTicks = SecondsToTicks(targetElapsed); } + + // Integer format represents time using 10,000,000 ticks per second. + static const uint64_t TicksPerSecond = 10000000; + + static double TicksToSeconds(uint64_t ticks) { return static_cast(ticks) / TicksPerSecond; } + static uint64_t SecondsToTicks(double seconds) { return static_cast(seconds * TicksPerSecond); } + + // After an intentional timing discontinuity (for instance a blocking IO operation) + // call this to avoid having the fixed timestep logic attempt a set of catch-up + // Update calls. + + void ResetElapsedTime() + { + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception("QueryPerformanceCounter"); + } + + m_leftOverTicks = 0; + m_framesPerSecond = 0; + m_framesThisSecond = 0; + m_qpcSecondCounter = 0; + } + + // Update timer state, calling the specified Update function the appropriate number of times. + template + void Tick(const TUpdate& update) + { + // Query the current time. + LARGE_INTEGER currentTime; + + if (!QueryPerformanceCounter(¤tTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + uint64_t timeDelta = currentTime.QuadPart - m_qpcLastTime.QuadPart; + + m_qpcLastTime = currentTime; + m_qpcSecondCounter += timeDelta; + + // Clamp excessively large time deltas (e.g. after paused in the debugger). + if (timeDelta > m_qpcMaxDelta) + { + timeDelta = m_qpcMaxDelta; + } + + // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. + timeDelta *= TicksPerSecond; + timeDelta /= m_qpcFrequency.QuadPart; + + uint32_t lastFrameCount = m_frameCount; + + if (m_isFixedTimeStep) + { + // Fixed timestep update logic + + // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp + // the clock to exactly match the target value. This prevents tiny and irrelevant errors + // from accumulating over time. Without this clamping, a game that requested a 60 fps + // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually + // accumulate enough tiny errors that it would drop a frame. It is better to just round + // small deviations down to zero to leave things running smoothly. + + if (abs(static_cast(timeDelta - m_targetElapsedTicks)) < TicksPerSecond / 4000) + { + timeDelta = m_targetElapsedTicks; + } + + m_leftOverTicks += timeDelta; + + while (m_leftOverTicks >= m_targetElapsedTicks) + { + m_elapsedTicks = m_targetElapsedTicks; + m_totalTicks += m_targetElapsedTicks; + m_leftOverTicks -= m_targetElapsedTicks; + m_frameCount++; + + update(); + } + } + else + { + // Variable timestep update logic. + m_elapsedTicks = timeDelta; + m_totalTicks += timeDelta; + m_leftOverTicks = 0; + m_frameCount++; + + update(); + } + + // Track the current framerate. + if (m_frameCount != lastFrameCount) + { + m_framesThisSecond++; + } + + if (m_qpcSecondCounter >= static_cast(m_qpcFrequency.QuadPart)) + { + m_framesPerSecond = m_framesThisSecond; + m_framesThisSecond = 0; + m_qpcSecondCounter %= m_qpcFrequency.QuadPart; + } + } + + private: + // Source timing data uses QPC units. + LARGE_INTEGER m_qpcFrequency; + LARGE_INTEGER m_qpcLastTime; + uint64_t m_qpcMaxDelta; + + // Derived timing data uses a canonical tick format. + uint64_t m_elapsedTicks; + uint64_t m_totalTicks; + uint64_t m_leftOverTicks; + + // Members for tracking the framerate. + uint32_t m_frameCount; + uint32_t m_framesPerSecond; + uint32_t m_framesThisSecond; + uint64_t m_qpcSecondCounter; + + // Members for configuring fixed timestep mode. + bool m_isFixedTimeStep; + uint64_t m_targetElapsedTicks; + }; +} diff --git a/Samples/IntroGraphics/SimpleMSAA_UWP12/pch.cpp b/Samples/IntroGraphics/SimpleMSAA_UWP12/pch.cpp new file mode 100644 index 00000000..373fab97 --- /dev/null +++ b/Samples/IntroGraphics/SimpleMSAA_UWP12/pch.cpp @@ -0,0 +1,10 @@ +//-------------------------------------------------------------------------------------- +// pch.cpp +// +// Include the standard header and generate the precompiled header. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" diff --git a/Samples/IntroGraphics/SimpleMSAA_UWP12/pch.h b/Samples/IntroGraphics/SimpleMSAA_UWP12/pch.h new file mode 100644 index 00000000..2dec6e7a --- /dev/null +++ b/Samples/IntroGraphics/SimpleMSAA_UWP12/pch.h @@ -0,0 +1,80 @@ +//-------------------------------------------------------------------------------------- +// pch.h +// +// Header for standard system include files. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +// Use the C++ standard templated min/max +#define NOMINMAX + +#pragma warning(push) +#pragma warning(disable : 4467) +#include +#pragma warning(pop) + +#include +#include +#include +#include + +#include "d3dx12.h" + +#include +#include +#include +#include + +#include +#include + +#ifdef _DEBUG +#include +#endif + +#include "CommonStates.h" +#include "DescriptorHeap.h" +#include "Effects.h" +#include "GamePad.h" +#include "GraphicsMemory.h" +#include "Keyboard.h" +#include "Model.h" +#include "Mouse.h" +#include "RenderTargetState.h" +#include "ResourceUploadBatch.h" +#include "SpriteBatch.h" +#include "SimpleMath.h" +#include "SpriteFont.h" + +namespace DX +{ + // Helper class for COM exceptions + class com_exception : public std::exception + { + public: + com_exception(HRESULT hr) : result(hr) {} + + virtual const char* what() const override + { + static char s_str[64] = { 0 }; + sprintf_s(s_str, "Failure with HRESULT of %08X", result); + return s_str; + } + + private: + HRESULT result; + }; + + // Helper utility converts D3D API failures into exceptions. + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + throw com_exception(hr); + } + } +} \ No newline at end of file diff --git a/Samples/IntroGraphics/SimpleTextureUWP/DeviceResources.cpp b/Samples/IntroGraphics/SimpleTextureUWP/DeviceResources.cpp index d00acd30..6c890acb 100644 --- a/Samples/IntroGraphics/SimpleTextureUWP/DeviceResources.cpp +++ b/Samples/IntroGraphics/SimpleTextureUWP/DeviceResources.cpp @@ -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), @@ -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) { } @@ -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) @@ -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 swapChain; DX::ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( @@ -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 @@ -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 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 adapter; for (UINT adapterIndex = 0; DXGI_ERROR_NOT_FOUND != dxgiFactory->EnumAdapters1(adapterIndex, adapter.ReleaseAndGetAddressOf()); adapterIndex++) { diff --git a/Samples/IntroGraphics/SimpleTextureUWP/DeviceResources.h b/Samples/IntroGraphics/SimpleTextureUWP/DeviceResources.h index ed0f0874..8d8f8837 100644 --- a/Samples/IntroGraphics/SimpleTextureUWP/DeviceResources.h +++ b/Samples/IntroGraphics/SimpleTextureUWP/DeviceResources.h @@ -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(); @@ -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); @@ -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; }; diff --git a/Samples/IntroGraphics/SimpleTextureUWP/Main.cpp b/Samples/IntroGraphics/SimpleTextureUWP/Main.cpp index 951ef2b0..949b2b25 100644 --- a/Samples/IntroGraphics/SimpleTextureUWP/Main.cpp +++ b/Samples/IntroGraphics/SimpleTextureUWP/Main.cpp @@ -208,7 +208,7 @@ ref class ViewProvider sealed : public IFrameworkView void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) { - SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral(); + auto deferral = args->SuspendingOperation->GetDeferral(); create_task([this, deferral]() { @@ -407,10 +407,8 @@ ref class ViewProviderFactory : IFrameworkViewSource // Entry point [Platform::MTAThread] -int main(Platform::Array^ argv) +int __cdecl main(Platform::Array^ /*argv*/) { - UNREFERENCED_PARAMETER(argv); - if (!XMVerifyCPUSupport()) { throw std::exception("XMVerifyCPUSupport"); @@ -420,3 +418,10 @@ int main(Platform::Array^ argv) CoreApplication::Run(viewProviderFactory); return 0; } + + +// Exit helper +void ExitSample() +{ + Windows::ApplicationModel::Core::CoreApplication::Exit(); +} \ No newline at end of file diff --git a/Samples/IntroGraphics/SimpleTextureUWP/Readme.docx b/Samples/IntroGraphics/SimpleTextureUWP/Readme.docx index f04823b0..e31d84a5 100644 Binary files a/Samples/IntroGraphics/SimpleTextureUWP/Readme.docx and b/Samples/IntroGraphics/SimpleTextureUWP/Readme.docx differ diff --git a/Samples/IntroGraphics/SimpleTextureUWP/SimpleTextureUWP.cpp b/Samples/IntroGraphics/SimpleTextureUWP/SimpleTextureUWP.cpp index cd6fb742..697b90dd 100644 --- a/Samples/IntroGraphics/SimpleTextureUWP/SimpleTextureUWP.cpp +++ b/Samples/IntroGraphics/SimpleTextureUWP/SimpleTextureUWP.cpp @@ -11,6 +11,8 @@ #include "ATGColors.h" #include "ReadData.h" +extern void ExitSample(); + using namespace DirectX; using Microsoft::WRL::ComPtr; @@ -61,7 +63,8 @@ namespace throw std::exception("CanConvert"); } - DX::ThrowIfFailed(formatConverter->Initialize(frame.Get(), GUID_WICPixelFormat32bppBGRA, WICBitmapDitherTypeErrorDiffusion, 0, 0, WICBitmapPaletteTypeCustom)); + DX::ThrowIfFailed(formatConverter->Initialize(frame.Get(), GUID_WICPixelFormat32bppBGRA, + WICBitmapDitherTypeErrorDiffusion, nullptr, 0, WICBitmapPaletteTypeMedianCut)); DX::ThrowIfFailed(formatConverter->CopyPixels(0, rowPitch, imageSize, reinterpret_cast(image.data()))); } @@ -116,14 +119,14 @@ void Sample::Update(DX::StepTimer const&) { if (pad.IsViewPressed()) { - Windows::ApplicationModel::Core::CoreApplication::Exit(); + ExitSample(); } } auto kb = m_keyboard->GetState(); if (kb.Escape) { - Windows::ApplicationModel::Core::CoreApplication::Exit(); + ExitSample(); } PIXEndEvent(); diff --git a/Samples/IntroGraphics/SimpleTextureUWP/SimpleTextureUWP.vcxproj b/Samples/IntroGraphics/SimpleTextureUWP/SimpleTextureUWP.vcxproj index 0025bb16..54f9b51e 100644 --- a/Samples/IntroGraphics/SimpleTextureUWP/SimpleTextureUWP.vcxproj +++ b/Samples/IntroGraphics/SimpleTextureUWP/SimpleTextureUWP.vcxproj @@ -98,7 +98,7 @@ false - false + false diff --git a/Samples/IntroGraphics/SimpleTextureUWP/pch.h b/Samples/IntroGraphics/SimpleTextureUWP/pch.h index cd1f735a..3386c9a4 100644 --- a/Samples/IntroGraphics/SimpleTextureUWP/pch.h +++ b/Samples/IntroGraphics/SimpleTextureUWP/pch.h @@ -15,7 +15,7 @@ #include #include -#include +#include #include #include #include diff --git a/Samples/IntroGraphics/SimpleTextureUWP12/DeviceResources.cpp b/Samples/IntroGraphics/SimpleTextureUWP12/DeviceResources.cpp index a77ccff2..5e3a68f6 100644 --- a/Samples/IntroGraphics/SimpleTextureUWP12/DeviceResources.cpp +++ b/Samples/IntroGraphics/SimpleTextureUWP12/DeviceResources.cpp @@ -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), @@ -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) @@ -99,7 +100,9 @@ DX::DeviceResources::~DeviceResources() void DX::DeviceResources::CreateDeviceResources() { #if defined(_DEBUG) - // Enable the debug layer (only available if the Graphics Tools feature-on-demand is enabled). + // Enable the debug layer (requires the Graphics Tools "optional feature"). + // + // NOTE: Enabling the debug layer after device creation will invalidate the active device. bool debugDXGI = false; { ComPtr debugController; @@ -129,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 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 adapter; GetAdapter(adapter.GetAddressOf()); @@ -262,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) @@ -298,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 swapChain; @@ -554,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) @@ -655,7 +689,7 @@ void DX::DeviceResources::GetAdapter(IDXGIAdapter1** ppAdapter) // Try WARP12 instead if (FAILED(m_dxgiFactory->EnumWarpAdapter(IID_PPV_ARGS(adapter.ReleaseAndGetAddressOf())))) { - throw std::exception("WARP12 not available. Enable the 'Graphics Tools' feature-on-demand"); + throw std::exception("WARP12 not available. Enable the 'Graphics Tools' optional feature"); } OutputDebugStringA("Direct3D Adapter - WARP12\n"); diff --git a/Samples/IntroGraphics/SimpleTextureUWP12/DeviceResources.h b/Samples/IntroGraphics/SimpleTextureUWP12/DeviceResources.h index 5eaa373a..a52a8c70 100644 --- a/Samples/IntroGraphics/SimpleTextureUWP12/DeviceResources.h +++ b/Samples/IntroGraphics/SimpleTextureUWP12/DeviceResources.h @@ -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(); @@ -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 { @@ -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; diff --git a/Samples/IntroGraphics/SimpleTextureUWP12/Main.cpp b/Samples/IntroGraphics/SimpleTextureUWP12/Main.cpp index f23c8a46..7243c155 100644 --- a/Samples/IntroGraphics/SimpleTextureUWP12/Main.cpp +++ b/Samples/IntroGraphics/SimpleTextureUWP12/Main.cpp @@ -208,7 +208,7 @@ ref class ViewProvider sealed : public IFrameworkView void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) { - SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral(); + auto deferral = args->SuspendingOperation->GetDeferral(); create_task([this, deferral]() { @@ -407,10 +407,8 @@ ref class ViewProviderFactory : IFrameworkViewSource // Entry point [Platform::MTAThread] -int main(Platform::Array^ argv) +int __cdecl main(Platform::Array^ /*argv*/) { - UNREFERENCED_PARAMETER(argv); - if (!XMVerifyCPUSupport()) { throw std::exception("XMVerifyCPUSupport"); @@ -420,3 +418,10 @@ int main(Platform::Array^ argv) CoreApplication::Run(viewProviderFactory); return 0; } + + +// Exit helper +void ExitSample() +{ + Windows::ApplicationModel::Core::CoreApplication::Exit(); +} \ No newline at end of file diff --git a/Samples/IntroGraphics/SimpleTextureUWP12/Readme.docx b/Samples/IntroGraphics/SimpleTextureUWP12/Readme.docx index a2b1a49a..41e722cd 100644 Binary files a/Samples/IntroGraphics/SimpleTextureUWP12/Readme.docx and b/Samples/IntroGraphics/SimpleTextureUWP12/Readme.docx differ diff --git a/Samples/IntroGraphics/SimpleTextureUWP12/SimpleTextureUWP12.cpp b/Samples/IntroGraphics/SimpleTextureUWP12/SimpleTextureUWP12.cpp index a6c04a38..4440b2d4 100644 --- a/Samples/IntroGraphics/SimpleTextureUWP12/SimpleTextureUWP12.cpp +++ b/Samples/IntroGraphics/SimpleTextureUWP12/SimpleTextureUWP12.cpp @@ -11,6 +11,8 @@ #include "ATGColors.h" #include "ReadData.h" +extern void ExitSample(); + using namespace DirectX; using Microsoft::WRL::ComPtr; @@ -63,7 +65,8 @@ namespace throw std::exception("CanConvert"); } - DX::ThrowIfFailed(formatConverter->Initialize(frame.Get(), GUID_WICPixelFormat32bppBGRA, WICBitmapDitherTypeErrorDiffusion, 0, 0, WICBitmapPaletteTypeCustom)); + DX::ThrowIfFailed(formatConverter->Initialize(frame.Get(), GUID_WICPixelFormat32bppBGRA, + WICBitmapDitherTypeErrorDiffusion, nullptr, 0, WICBitmapPaletteTypeMedianCut)); DX::ThrowIfFailed(formatConverter->CopyPixels(0, rowPitch, imageSize, reinterpret_cast(image.data()))); } @@ -118,14 +121,14 @@ void Sample::Update(DX::StepTimer const&) { if (pad.IsViewPressed()) { - Windows::ApplicationModel::Core::CoreApplication::Exit(); + ExitSample(); } } auto kb = m_keyboard->GetState(); if (kb.Escape) { - Windows::ApplicationModel::Core::CoreApplication::Exit(); + ExitSample(); } PIXEndEvent(); diff --git a/Samples/IntroGraphics/SimpleTextureUWP12/SimpleTextureUWP12.vcxproj b/Samples/IntroGraphics/SimpleTextureUWP12/SimpleTextureUWP12.vcxproj index 60a0703c..d0513ab4 100644 --- a/Samples/IntroGraphics/SimpleTextureUWP12/SimpleTextureUWP12.vcxproj +++ b/Samples/IntroGraphics/SimpleTextureUWP12/SimpleTextureUWP12.vcxproj @@ -98,7 +98,7 @@ false - false + false diff --git a/Samples/IntroGraphics/SimpleTextureUWP12/pch.h b/Samples/IntroGraphics/SimpleTextureUWP12/pch.h index 83689677..1fabc7fa 100644 --- a/Samples/IntroGraphics/SimpleTextureUWP12/pch.h +++ b/Samples/IntroGraphics/SimpleTextureUWP12/pch.h @@ -15,7 +15,7 @@ #include #include -#include +#include #include #include #include diff --git a/Samples/IntroGraphics/SimpleTriangleUWP/DeviceResources.cpp b/Samples/IntroGraphics/SimpleTriangleUWP/DeviceResources.cpp index d00acd30..6c890acb 100644 --- a/Samples/IntroGraphics/SimpleTriangleUWP/DeviceResources.cpp +++ b/Samples/IntroGraphics/SimpleTriangleUWP/DeviceResources.cpp @@ -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), @@ -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) { } @@ -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) @@ -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 swapChain; DX::ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( @@ -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 @@ -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 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 adapter; for (UINT adapterIndex = 0; DXGI_ERROR_NOT_FOUND != dxgiFactory->EnumAdapters1(adapterIndex, adapter.ReleaseAndGetAddressOf()); adapterIndex++) { diff --git a/Samples/IntroGraphics/SimpleTriangleUWP/DeviceResources.h b/Samples/IntroGraphics/SimpleTriangleUWP/DeviceResources.h index ed0f0874..8d8f8837 100644 --- a/Samples/IntroGraphics/SimpleTriangleUWP/DeviceResources.h +++ b/Samples/IntroGraphics/SimpleTriangleUWP/DeviceResources.h @@ -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(); @@ -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); @@ -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; }; diff --git a/Samples/IntroGraphics/SimpleTriangleUWP/Main.cpp b/Samples/IntroGraphics/SimpleTriangleUWP/Main.cpp index 1cc35e32..5ba97f1d 100644 --- a/Samples/IntroGraphics/SimpleTriangleUWP/Main.cpp +++ b/Samples/IntroGraphics/SimpleTriangleUWP/Main.cpp @@ -208,7 +208,7 @@ ref class ViewProvider sealed : public IFrameworkView void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) { - SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral(); + auto deferral = args->SuspendingOperation->GetDeferral(); create_task([this, deferral]() { @@ -407,10 +407,8 @@ ref class ViewProviderFactory : IFrameworkViewSource // Entry point [Platform::MTAThread] -int main(Platform::Array^ argv) +int __cdecl main(Platform::Array^ /*argv*/) { - UNREFERENCED_PARAMETER(argv); - if (!XMVerifyCPUSupport()) { throw std::exception("XMVerifyCPUSupport"); @@ -420,3 +418,10 @@ int main(Platform::Array^ argv) CoreApplication::Run(viewProviderFactory); return 0; } + + +// Exit helper +void ExitSample() +{ + Windows::ApplicationModel::Core::CoreApplication::Exit(); +} diff --git a/Samples/IntroGraphics/SimpleTriangleUWP/Readme.docx b/Samples/IntroGraphics/SimpleTriangleUWP/Readme.docx index 38e0b908..33d72125 100644 Binary files a/Samples/IntroGraphics/SimpleTriangleUWP/Readme.docx and b/Samples/IntroGraphics/SimpleTriangleUWP/Readme.docx differ diff --git a/Samples/IntroGraphics/SimpleTriangleUWP/SimpleTriangleUWP.cpp b/Samples/IntroGraphics/SimpleTriangleUWP/SimpleTriangleUWP.cpp index b9e5c719..5bb0e970 100644 --- a/Samples/IntroGraphics/SimpleTriangleUWP/SimpleTriangleUWP.cpp +++ b/Samples/IntroGraphics/SimpleTriangleUWP/SimpleTriangleUWP.cpp @@ -11,6 +11,8 @@ #include "ATGColors.h" #include "ReadData.h" +extern void ExitSample(); + using namespace DirectX; using Microsoft::WRL::ComPtr; @@ -27,7 +29,13 @@ namespace Sample::Sample() { // Use gamma-correct rendering. - m_deviceResources = std::make_unique(DXGI_FORMAT_B8G8R8A8_UNORM_SRGB); + m_deviceResources = std::make_unique( + DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, + DXGI_FORMAT_D24_UNORM_S8_UINT, + 2, + D3D_FEATURE_LEVEL_9_3, + DX::DeviceResources::c_AllowTearing + ); m_deviceResources->RegisterDeviceNotify(this); } @@ -70,14 +78,14 @@ void Sample::Update(DX::StepTimer const&) { if (pad.IsViewPressed()) { - Windows::ApplicationModel::Core::CoreApplication::Exit(); + ExitSample(); } } auto kb = m_keyboard->GetState(); if (kb.Escape) { - Windows::ApplicationModel::Core::CoreApplication::Exit(); + ExitSample(); } PIXEndEvent(); diff --git a/Samples/IntroGraphics/SimpleTriangleUWP/SimpleTriangleUWP.vcxproj b/Samples/IntroGraphics/SimpleTriangleUWP/SimpleTriangleUWP.vcxproj index 8b2eb7a9..cb347627 100644 --- a/Samples/IntroGraphics/SimpleTriangleUWP/SimpleTriangleUWP.vcxproj +++ b/Samples/IntroGraphics/SimpleTriangleUWP/SimpleTriangleUWP.vcxproj @@ -98,7 +98,7 @@ false - false + false diff --git a/Samples/IntroGraphics/SimpleTriangleUWP/pch.h b/Samples/IntroGraphics/SimpleTriangleUWP/pch.h index 317fb6c9..3882779d 100644 --- a/Samples/IntroGraphics/SimpleTriangleUWP/pch.h +++ b/Samples/IntroGraphics/SimpleTriangleUWP/pch.h @@ -15,7 +15,7 @@ #include #include -#include +#include #include #include diff --git a/Samples/IntroGraphics/SimpleTriangleUWP12/DeviceResources.cpp b/Samples/IntroGraphics/SimpleTriangleUWP12/DeviceResources.cpp index a77ccff2..5e3a68f6 100644 --- a/Samples/IntroGraphics/SimpleTriangleUWP12/DeviceResources.cpp +++ b/Samples/IntroGraphics/SimpleTriangleUWP12/DeviceResources.cpp @@ -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), @@ -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) @@ -99,7 +100,9 @@ DX::DeviceResources::~DeviceResources() void DX::DeviceResources::CreateDeviceResources() { #if defined(_DEBUG) - // Enable the debug layer (only available if the Graphics Tools feature-on-demand is enabled). + // Enable the debug layer (requires the Graphics Tools "optional feature"). + // + // NOTE: Enabling the debug layer after device creation will invalidate the active device. bool debugDXGI = false; { ComPtr debugController; @@ -129,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 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 adapter; GetAdapter(adapter.GetAddressOf()); @@ -262,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) @@ -298,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 swapChain; @@ -554,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) @@ -655,7 +689,7 @@ void DX::DeviceResources::GetAdapter(IDXGIAdapter1** ppAdapter) // Try WARP12 instead if (FAILED(m_dxgiFactory->EnumWarpAdapter(IID_PPV_ARGS(adapter.ReleaseAndGetAddressOf())))) { - throw std::exception("WARP12 not available. Enable the 'Graphics Tools' feature-on-demand"); + throw std::exception("WARP12 not available. Enable the 'Graphics Tools' optional feature"); } OutputDebugStringA("Direct3D Adapter - WARP12\n"); diff --git a/Samples/IntroGraphics/SimpleTriangleUWP12/DeviceResources.h b/Samples/IntroGraphics/SimpleTriangleUWP12/DeviceResources.h index 5eaa373a..a52a8c70 100644 --- a/Samples/IntroGraphics/SimpleTriangleUWP12/DeviceResources.h +++ b/Samples/IntroGraphics/SimpleTriangleUWP12/DeviceResources.h @@ -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(); @@ -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 { @@ -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; diff --git a/Samples/IntroGraphics/SimpleTriangleUWP12/Main.cpp b/Samples/IntroGraphics/SimpleTriangleUWP12/Main.cpp index ded62b17..2ae50972 100644 --- a/Samples/IntroGraphics/SimpleTriangleUWP12/Main.cpp +++ b/Samples/IntroGraphics/SimpleTriangleUWP12/Main.cpp @@ -208,7 +208,7 @@ ref class ViewProvider sealed : public IFrameworkView void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) { - SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral(); + auto deferral = args->SuspendingOperation->GetDeferral(); create_task([this, deferral]() { @@ -407,10 +407,8 @@ ref class ViewProviderFactory : IFrameworkViewSource // Entry point [Platform::MTAThread] -int main(Platform::Array^ argv) +int __cdecl main(Platform::Array^ /*argv*/) { - UNREFERENCED_PARAMETER(argv); - if (!XMVerifyCPUSupport()) { throw std::exception("XMVerifyCPUSupport"); @@ -420,3 +418,10 @@ int main(Platform::Array^ argv) CoreApplication::Run(viewProviderFactory); return 0; } + + +// Exit helper +void ExitSample() +{ + Windows::ApplicationModel::Core::CoreApplication::Exit(); +} \ No newline at end of file diff --git a/Samples/IntroGraphics/SimpleTriangleUWP12/Readme.docx b/Samples/IntroGraphics/SimpleTriangleUWP12/Readme.docx index 71b3f634..c1001cf1 100644 Binary files a/Samples/IntroGraphics/SimpleTriangleUWP12/Readme.docx and b/Samples/IntroGraphics/SimpleTriangleUWP12/Readme.docx differ diff --git a/Samples/IntroGraphics/SimpleTriangleUWP12/SimpleTriangleUWP12.cpp b/Samples/IntroGraphics/SimpleTriangleUWP12/SimpleTriangleUWP12.cpp index ef8e221e..94d883d2 100644 --- a/Samples/IntroGraphics/SimpleTriangleUWP12/SimpleTriangleUWP12.cpp +++ b/Samples/IntroGraphics/SimpleTriangleUWP12/SimpleTriangleUWP12.cpp @@ -11,6 +11,8 @@ #include "ATGColors.h" #include "ReadData.h" +extern void ExitSample(); + using namespace DirectX; using Microsoft::WRL::ComPtr; @@ -29,7 +31,13 @@ namespace Sample::Sample() { // Use gamma-correct rendering. - m_deviceResources = std::make_unique(DXGI_FORMAT_B8G8R8A8_UNORM_SRGB); + m_deviceResources = std::make_unique( + DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, + DXGI_FORMAT_D32_FLOAT, + 2, + D3D_FEATURE_LEVEL_11_0, + DX::DeviceResources::c_AllowTearing + ); m_deviceResources->RegisterDeviceNotify(this); } @@ -72,14 +80,14 @@ void Sample::Update(DX::StepTimer const&) { if (pad.IsViewPressed()) { - Windows::ApplicationModel::Core::CoreApplication::Exit(); + ExitSample(); } } auto kb = m_keyboard->GetState(); if (kb.Escape) { - Windows::ApplicationModel::Core::CoreApplication::Exit(); + ExitSample(); } PIXEndEvent(); diff --git a/Samples/IntroGraphics/SimpleTriangleUWP12/SimpleTriangleUWP12.vcxproj b/Samples/IntroGraphics/SimpleTriangleUWP12/SimpleTriangleUWP12.vcxproj index 02cf9817..bce01b38 100644 --- a/Samples/IntroGraphics/SimpleTriangleUWP12/SimpleTriangleUWP12.vcxproj +++ b/Samples/IntroGraphics/SimpleTriangleUWP12/SimpleTriangleUWP12.vcxproj @@ -98,7 +98,7 @@ false - false + false diff --git a/Samples/IntroGraphics/SimpleTriangleUWP12/pch.h b/Samples/IntroGraphics/SimpleTriangleUWP12/pch.h index 722fc29e..07c42de4 100644 --- a/Samples/IntroGraphics/SimpleTriangleUWP12/pch.h +++ b/Samples/IntroGraphics/SimpleTriangleUWP12/pch.h @@ -15,7 +15,7 @@ #include #include -#include +#include #include #include diff --git a/Samples/System/CPUSets/CPUSets.vcxproj b/Samples/System/CPUSets/CPUSets.vcxproj index ff8193d9..79703e6b 100644 --- a/Samples/System/CPUSets/CPUSets.vcxproj +++ b/Samples/System/CPUSets/CPUSets.vcxproj @@ -98,7 +98,7 @@ false - false + false diff --git a/Samples/System/CPUSets/Readme.docx b/Samples/System/CPUSets/Readme.docx index b53fd6e0..0b940b8c 100644 Binary files a/Samples/System/CPUSets/Readme.docx and b/Samples/System/CPUSets/Readme.docx differ diff --git a/Samples/System/CollisionUWP/Collision.vcxproj b/Samples/System/CollisionUWP/Collision.vcxproj index 2d78425c..8bb4d81d 100644 --- a/Samples/System/CollisionUWP/Collision.vcxproj +++ b/Samples/System/CollisionUWP/Collision.vcxproj @@ -98,7 +98,7 @@ false - false + false diff --git a/Samples/System/CollisionUWP/Readme.docx b/Samples/System/CollisionUWP/Readme.docx index 168814d7..0606cb95 100644 Binary files a/Samples/System/CollisionUWP/Readme.docx and b/Samples/System/CollisionUWP/Readme.docx differ diff --git a/Samples/System/ExtendedExecutionUWP/ExtendedExecutionOnSuspend/ExtendedExecutionOnSuspend.vcxproj b/Samples/System/ExtendedExecutionUWP/ExtendedExecutionOnSuspend/ExtendedExecutionOnSuspend.vcxproj index 286a66c8..1ef4bf02 100644 --- a/Samples/System/ExtendedExecutionUWP/ExtendedExecutionOnSuspend/ExtendedExecutionOnSuspend.vcxproj +++ b/Samples/System/ExtendedExecutionUWP/ExtendedExecutionOnSuspend/ExtendedExecutionOnSuspend.vcxproj @@ -98,7 +98,7 @@ false - false + false diff --git a/Samples/System/ExtendedExecutionUWP/PreemptiveExtendedExecution/PreemptiveExtendedExecution.vcxproj b/Samples/System/ExtendedExecutionUWP/PreemptiveExtendedExecution/PreemptiveExtendedExecution.vcxproj index 68309a9f..803c748c 100644 --- a/Samples/System/ExtendedExecutionUWP/PreemptiveExtendedExecution/PreemptiveExtendedExecution.vcxproj +++ b/Samples/System/ExtendedExecutionUWP/PreemptiveExtendedExecution/PreemptiveExtendedExecution.vcxproj @@ -98,7 +98,7 @@ false - false + false diff --git a/Samples/System/ExtendedExecutionUWP/Readme.docx b/Samples/System/ExtendedExecutionUWP/Readme.docx index 96bb292a..3f910e6b 100644 Binary files a/Samples/System/ExtendedExecutionUWP/Readme.docx and b/Samples/System/ExtendedExecutionUWP/Readme.docx differ diff --git a/Samples/System/GamepadCppWinRT_UWP/GamepadCppWinRT_UWP.vcxproj b/Samples/System/GamepadCppWinRT_UWP/GamepadCppWinRT_UWP.vcxproj index be4f4a41..7894f3e4 100644 --- a/Samples/System/GamepadCppWinRT_UWP/GamepadCppWinRT_UWP.vcxproj +++ b/Samples/System/GamepadCppWinRT_UWP/GamepadCppWinRT_UWP.vcxproj @@ -100,7 +100,7 @@ false - false + false diff --git a/Samples/System/GamepadCppWinRT_UWP/Readme.docx b/Samples/System/GamepadCppWinRT_UWP/Readme.docx index 5a195e97..51d98915 100644 Binary files a/Samples/System/GamepadCppWinRT_UWP/Readme.docx and b/Samples/System/GamepadCppWinRT_UWP/Readme.docx differ diff --git a/Samples/System/GamepadUWP/GamepadUWP.vcxproj b/Samples/System/GamepadUWP/GamepadUWP.vcxproj index 4ddc66c4..a011e3fe 100644 --- a/Samples/System/GamepadUWP/GamepadUWP.vcxproj +++ b/Samples/System/GamepadUWP/GamepadUWP.vcxproj @@ -98,7 +98,7 @@ false - false + false diff --git a/Samples/System/GamepadUWP/Readme.docx b/Samples/System/GamepadUWP/Readme.docx index 5d017123..8d692ad3 100644 Binary files a/Samples/System/GamepadUWP/Readme.docx and b/Samples/System/GamepadUWP/Readme.docx differ diff --git a/Samples/System/GamepadVibrationUWP/GamepadVibrationUWP.vcxproj b/Samples/System/GamepadVibrationUWP/GamepadVibrationUWP.vcxproj index bfed0f07..beff93a3 100644 --- a/Samples/System/GamepadVibrationUWP/GamepadVibrationUWP.vcxproj +++ b/Samples/System/GamepadVibrationUWP/GamepadVibrationUWP.vcxproj @@ -98,7 +98,7 @@ false - false + false diff --git a/Samples/System/GamepadVibrationUWP/Readme.docx b/Samples/System/GamepadVibrationUWP/Readme.docx index 58816893..36a3bac9 100644 Binary files a/Samples/System/GamepadVibrationUWP/Readme.docx and b/Samples/System/GamepadVibrationUWP/Readme.docx differ diff --git a/Samples/System/InputInterfacingUWP/Readme.docx b/Samples/System/InputInterfacingUWP/Readme.docx index fecaa21e..f2c669b5 100644 Binary files a/Samples/System/InputInterfacingUWP/Readme.docx and b/Samples/System/InputInterfacingUWP/Readme.docx differ diff --git a/Samples/System/MemoryStatisticsUWP/MemoryStatistics.vcxproj b/Samples/System/MemoryStatisticsUWP/MemoryStatistics.vcxproj index a079dce4..3ccf2506 100644 --- a/Samples/System/MemoryStatisticsUWP/MemoryStatistics.vcxproj +++ b/Samples/System/MemoryStatisticsUWP/MemoryStatistics.vcxproj @@ -98,7 +98,7 @@ false - false + false diff --git a/Samples/System/MemoryStatisticsUWP/Readme.docx b/Samples/System/MemoryStatisticsUWP/Readme.docx index 5d2bf9c8..cb6d7880 100644 Binary files a/Samples/System/MemoryStatisticsUWP/Readme.docx and b/Samples/System/MemoryStatisticsUWP/Readme.docx differ diff --git a/Samples/System/MouseCursor/MouseCursor.vcxproj b/Samples/System/MouseCursor/MouseCursor.vcxproj index f6604191..b799a82f 100644 --- a/Samples/System/MouseCursor/MouseCursor.vcxproj +++ b/Samples/System/MouseCursor/MouseCursor.vcxproj @@ -99,7 +99,7 @@ false - false + false diff --git a/Samples/System/MouseCursor/Readme.docx b/Samples/System/MouseCursor/Readme.docx index 0289ef56..37257269 100644 Binary files a/Samples/System/MouseCursor/Readme.docx and b/Samples/System/MouseCursor/Readme.docx differ diff --git a/Samples/System/NLSAndLocalizationUWP/NLSAndLocalizationUWP.vcxproj b/Samples/System/NLSAndLocalizationUWP/NLSAndLocalizationUWP.vcxproj index 3243b1c4..51ee6540 100644 --- a/Samples/System/NLSAndLocalizationUWP/NLSAndLocalizationUWP.vcxproj +++ b/Samples/System/NLSAndLocalizationUWP/NLSAndLocalizationUWP.vcxproj @@ -99,7 +99,7 @@ false - false + false diff --git a/Samples/System/NLSAndLocalizationUWP/Readme.docx b/Samples/System/NLSAndLocalizationUWP/Readme.docx index 0587448e..42fbf28c 100644 Binary files a/Samples/System/NLSAndLocalizationUWP/Readme.docx and b/Samples/System/NLSAndLocalizationUWP/Readme.docx differ diff --git a/Samples/System/RawGameControllerUWP/Readme.docx b/Samples/System/RawGameControllerUWP/Readme.docx index 2aa59386..2e337917 100644 Binary files a/Samples/System/RawGameControllerUWP/Readme.docx and b/Samples/System/RawGameControllerUWP/Readme.docx differ diff --git a/Samples/System/SimplePLM_UWP/Readme.docx b/Samples/System/SimplePLM_UWP/Readme.docx index 509176f9..fc4d2687 100644 Binary files a/Samples/System/SimplePLM_UWP/Readme.docx and b/Samples/System/SimplePLM_UWP/Readme.docx differ diff --git a/Samples/System/SimplePLM_UWP/SimplePLM.vcxproj b/Samples/System/SimplePLM_UWP/SimplePLM.vcxproj index d7151d7f..0d8a6e70 100644 --- a/Samples/System/SimplePLM_UWP/SimplePLM.vcxproj +++ b/Samples/System/SimplePLM_UWP/SimplePLM.vcxproj @@ -98,7 +98,7 @@ false - false + false diff --git a/Samples/System/SystemInfoUWP/Readme.docx b/Samples/System/SystemInfoUWP/Readme.docx index aa63328f..0afeb763 100644 Binary files a/Samples/System/SystemInfoUWP/Readme.docx and b/Samples/System/SystemInfoUWP/Readme.docx differ diff --git a/Samples/System/SystemInfoUWP/SystemInfo.cpp b/Samples/System/SystemInfoUWP/SystemInfo.cpp index af845f2c..ab3b9dc6 100644 --- a/Samples/System/SystemInfoUWP/SystemInfo.cpp +++ b/Samples/System/SystemInfoUWP/SystemInfo.cpp @@ -375,7 +375,10 @@ void Sample::Render() bool isuniversal1 = ApiInformation::IsApiContractPresent("Windows.Foundation.UniversalApiContract", 1, 0); bool isuniversal2 = ApiInformation::IsApiContractPresent("Windows.Foundation.UniversalApiContract", 2, 0); bool isuniversal3 = ApiInformation::IsApiContractPresent("Windows.Foundation.UniversalApiContract", 3, 0); + bool isuniversal4 = ApiInformation::IsApiContractPresent("Windows.Foundation.UniversalApiContract", 4, 0); bool isphone = ApiInformation::IsApiContractPresent("Windows.Phone.PhoneContract", 1, 0); + bool isstore = ApiInformation::IsApiContractPresent("Windows.Services.Store.StoreContract", 1, 0); + bool isstore2 = ApiInformation::IsApiContractPresent("Windows.Services.Store.StoreContract", 2, 0); DrawStringLeft(m_batch.get(), m_smallFont.get(), L"FoundationContract 1.0", left, y, m_scale); y += DrawStringRight(m_batch.get(), m_smallFont.get(), isfoundation ? L"true" : L"false", right, y, m_scale); @@ -389,8 +392,17 @@ void Sample::Render() DrawStringLeft(m_batch.get(), m_smallFont.get(), L"UniversalApiContract 3.0", left, y, m_scale); y += DrawStringRight(m_batch.get(), m_smallFont.get(), isuniversal3 ? L"true" : L"false", right, y, m_scale); + DrawStringLeft(m_batch.get(), m_smallFont.get(), L"UniversalApiContract 4.0", left, y, m_scale); + y += DrawStringRight(m_batch.get(), m_smallFont.get(), isuniversal4 ? L"true" : L"false", right, y, m_scale); + DrawStringLeft(m_batch.get(), m_smallFont.get(), L"PhoneContract 1.0", left, y, m_scale); y += DrawStringRight(m_batch.get(), m_smallFont.get(), isphone ? L"true" : L"false", right, y, m_scale); + + DrawStringLeft(m_batch.get(), m_smallFont.get(), L"StoreContract 1.0", left, y, m_scale); + y += DrawStringRight(m_batch.get(), m_smallFont.get(), isstore ? L"true" : L"false", right, y, m_scale); + + DrawStringLeft(m_batch.get(), m_smallFont.get(), L"StoreContract 2.0", left, y, m_scale); + y += DrawStringRight(m_batch.get(), m_smallFont.get(), isstore2 ? L"true" : L"false", right, y, m_scale); } break; diff --git a/Samples/System/SystemInfoUWP/SystemInfo.vcxproj b/Samples/System/SystemInfoUWP/SystemInfo.vcxproj index 20de0bcc..441cbcf4 100644 --- a/Samples/System/SystemInfoUWP/SystemInfo.vcxproj +++ b/Samples/System/SystemInfoUWP/SystemInfo.vcxproj @@ -98,7 +98,7 @@ false - false + false diff --git a/Samples/System/UserGamepadPairingUWP/Readme.docx b/Samples/System/UserGamepadPairingUWP/Readme.docx index a3e270fc..d6e7a3d2 100644 Binary files a/Samples/System/UserGamepadPairingUWP/Readme.docx and b/Samples/System/UserGamepadPairingUWP/Readme.docx differ diff --git a/Samples/System/UserGamepadPairingUWP/UserGamepadPairingUWP.vcxproj b/Samples/System/UserGamepadPairingUWP/UserGamepadPairingUWP.vcxproj index d0d08f64..40946ba9 100644 --- a/Samples/System/UserGamepadPairingUWP/UserGamepadPairingUWP.vcxproj +++ b/Samples/System/UserGamepadPairingUWP/UserGamepadPairingUWP.vcxproj @@ -99,7 +99,7 @@ false - false + false diff --git a/Samples/Tools/errorlookup/errorlookup/README.docx b/Samples/Tools/errorlookup/errorlookup/README.docx index cd7bfcd0..de4a9f40 100644 Binary files a/Samples/Tools/errorlookup/errorlookup/README.docx and b/Samples/Tools/errorlookup/errorlookup/README.docx differ diff --git a/Samples/Tools/errorlookup/errorlookup/errorlookup.csproj b/Samples/Tools/errorlookup/errorlookup/errorlookup.csproj index ee6eeec3..03757801 100644 --- a/Samples/Tools/errorlookup/errorlookup/errorlookup.csproj +++ b/Samples/Tools/errorlookup/errorlookup/errorlookup.csproj @@ -17,6 +17,7 @@ 512 {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} false + win10-arm;win10-arm-aot;win10-x86;win10-x86-aot;win10-x64;win10-x64-aot true @@ -92,7 +93,6 @@ PreserveNewest - @@ -138,6 +138,20 @@ Designer + + + 1.0.0 + + + 1.0.0 + + + 1.0.0 + + + 5.0.0 + + 14.0 diff --git a/Samples/Tools/errorlookup/errorlookup/project.json b/Samples/Tools/errorlookup/errorlookup/project.json deleted file mode 100644 index e3b2dba2..00000000 --- a/Samples/Tools/errorlookup/errorlookup/project.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "dependencies": { - "Microsoft.ApplicationInsights": "1.0.0", - "Microsoft.ApplicationInsights.PersistenceChannel": "1.0.0", - "Microsoft.ApplicationInsights.WindowsApps": "1.0.0", - "Microsoft.NETCore.UniversalWindowsPlatform": "5.0.0" - }, - "frameworks": { - "uap10.0": {} - }, - "runtimes": { - "win10-arm": {}, - "win10-arm-aot": {}, - "win10-x86": {}, - "win10-x86-aot": {}, - "win10-x64": {}, - "win10-x64-aot": {} - } -} \ No newline at end of file