From 46a3295b50cfedfe51fd85fe207c16c656ad2a97 Mon Sep 17 00:00:00 2001 From: Chuck Walbourn Date: Wed, 15 Feb 2017 13:24:21 -0800 Subject: [PATCH] Updated for DirectX Tool Kit February 2017 releases --- Kits/DirectXTK/DirectXTK_Windows10.vcxproj | 5 + Kits/DirectXTK/Inc/Keyboard.h | 2 +- Kits/DirectXTK/Readme.txt | 8 +- Kits/DirectXTK/Src/GamePad.cpp | 101 ++++++-- Kits/DirectXTK/Src/LoaderHelpers.h | 5 + Kits/DirectXTK/Src/ScreenGrab.cpp | 4 +- Kits/DirectXTK/Src/WICTextureLoader.cpp | 10 +- Kits/DirectXTK12/DirectXTK_Windows10.vcxproj | 5 + Kits/DirectXTK12/Inc/Keyboard.h | 2 +- Kits/DirectXTK12/Inc/RenderTargetState.h | 22 +- Kits/DirectXTK12/Readme.txt | 11 +- Kits/DirectXTK12/Src/CommonStates.cpp | 6 +- Kits/DirectXTK12/Src/DDSTextureLoader.cpp | 233 ++++++++++++++----- Kits/DirectXTK12/Src/DirectXHelpers.cpp | 14 +- Kits/DirectXTK12/Src/GamePad.cpp | 101 ++++++-- Kits/DirectXTK12/Src/LoaderHelpers.h | 5 + Kits/DirectXTK12/Src/ResourceUploadBatch.cpp | 86 ++++++- Kits/DirectXTK12/Src/ScreenGrab.cpp | 8 +- Kits/DirectXTK12/Src/SpriteBatch.cpp | 63 ++++- Kits/DirectXTK12/Src/WICTextureLoader.cpp | 8 +- Kits/DirectXTK12/Src/d3dx12.h | 114 +++++---- 21 files changed, 628 insertions(+), 185 deletions(-) diff --git a/Kits/DirectXTK/DirectXTK_Windows10.vcxproj b/Kits/DirectXTK/DirectXTK_Windows10.vcxproj index c811d8f8..9f146e60 100644 --- a/Kits/DirectXTK/DirectXTK_Windows10.vcxproj +++ b/Kits/DirectXTK/DirectXTK_Windows10.vcxproj @@ -639,4 +639,9 @@ + + + \ No newline at end of file diff --git a/Kits/DirectXTK/Inc/Keyboard.h b/Kits/DirectXTK/Inc/Keyboard.h index cfdb6aac..9c5d6002 100644 --- a/Kits/DirectXTK/Inc/Keyboard.h +++ b/Kits/DirectXTK/Inc/Keyboard.h @@ -404,7 +404,7 @@ namespace DirectX bool __cdecl IsKeyDown(Keys key) const { - if (key >= 0 && key <= 0xff) + if (key >= 0 && key <= 0xfe) { auto ptr = reinterpret_cast(this); unsigned int bf = 1u << (key & 0x1f); diff --git a/Kits/DirectXTK/Readme.txt b/Kits/DirectXTK/Readme.txt index 4727cf14..6c3a5145 100644 --- a/Kits/DirectXTK/Readme.txt +++ b/Kits/DirectXTK/Readme.txt @@ -4,7 +4,7 @@ DirectXTK - the DirectX Tool Kit for DirectX 11 Copyright (c) Microsoft Corporation. All rights reserved. -December 5, 2016 +February 10, 2017 This package contains the "DirectX Tool Kit", a collection of helper classes for writing Direct3D 11 C++ code for Universal Windows Platform (UWP) apps for Windows 10, @@ -79,6 +79,12 @@ https://opensource.microsoft.com/codeofconduct/ RELEASE HISTORY --------------- +February 10, 2017 + GamePad now supports special value of -1 for 'most recently connected controller' + WIC format 40bppCMYKAlpha should be converted to RGBA8 rather than RGBA16 + DDS support for L8A8 with bitcount 8 rather than 16 + Minor code cleanup + December 5, 2016 Mouse and Keyboard classes updated with IsConnected method Windows10 project /ZW switch removed to support use in C++/WinRT projection apps diff --git a/Kits/DirectXTK/Src/GamePad.cpp b/Kits/DirectXTK/Src/GamePad.cpp index c9cc8157..de040a9e 100644 --- a/Kits/DirectXTK/Src/GamePad.cpp +++ b/Kits/DirectXTK/Src/GamePad.cpp @@ -90,7 +90,8 @@ class GamePad::Impl Impl(GamePad* owner) : mOwner(owner), mCtrlChanged(INVALID_HANDLE_VALUE), - mUserChanged(INVALID_HANDLE_VALUE) + mUserChanged(INVALID_HANDLE_VALUE), + mMostRecentGamepad(0) { using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; @@ -169,6 +170,9 @@ class GamePad::Impl ScanGamePads(); } + if (player == -1) + player = mMostRecentGamepad; + if ( ( player >= 0 ) && ( player < MAX_PLAYER_COUNT ) ) { if ( mGamePad[ player ] ) @@ -201,11 +205,11 @@ class GamePad::Impl ApplyStickDeadZone( static_cast(reading.LeftThumbstickX), static_cast(reading.LeftThumbstickY), deadZoneMode, 1.f, .24f /* Recommended Xbox One deadzone */, - static_cast(state.thumbSticks.leftX), static_cast(state.thumbSticks.leftY) ); + state.thumbSticks.leftX, state.thumbSticks.leftY ); ApplyStickDeadZone( static_cast(reading.RightThumbstickX), static_cast(reading.RightThumbstickY), deadZoneMode, 1.f, .24f /* Recommended Xbox One deadzone */, - static_cast(state.thumbSticks.rightX), static_cast(state.thumbSticks.rightY) ); + state.thumbSticks.rightX, state.thumbSticks.rightY ); state.triggers.left = static_cast(reading.LeftTrigger); state.triggers.right = static_cast(reading.RightTrigger); @@ -229,6 +233,9 @@ class GamePad::Impl ScanGamePads(); } + if (player == -1) + player = mMostRecentGamepad; + if ( ( player >= 0 ) && ( player < MAX_PLAYER_COUNT ) ) { if ( mGamePad[ player ] ) @@ -265,6 +272,9 @@ class GamePad::Impl { using namespace ABI::Windows::Gaming::Input; + if (player == -1) + player = mMostRecentGamepad; + if ( ( player >= 0 ) && ( player < MAX_PLAYER_COUNT ) ) { if ( mGamePad[ player ] ) @@ -306,6 +316,8 @@ class GamePad::Impl HANDLE mUserChanged; private: + int mMostRecentGamepad; + void ScanGamePads() { using namespace Microsoft::WRL; @@ -362,6 +374,8 @@ class GamePad::Impl { if ( mGamePad[ k ] == pad ) { + if (j == (count - 1)) + mMostRecentGamepad = static_cast(k); break; } else if ( !mGamePad[ k ] ) @@ -377,6 +391,8 @@ class GamePad::Impl if ( empty < MAX_PLAYER_COUNT ) { mGamePad[ empty ] = pad; + if (j == (count - 1)) + mMostRecentGamepad = static_cast(empty); ComPtr ctrl; hr = pad.As(&ctrl); @@ -526,7 +542,8 @@ class GamePad::Impl Impl(GamePad *owner) : mOwner(owner), mCtrlChanged(INVALID_HANDLE_VALUE), - mUserChanged(INVALID_HANDLE_VALUE) + mUserChanged(INVALID_HANDLE_VALUE), + mMostRecentGamepad(0) { using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; @@ -596,6 +613,9 @@ class GamePad::Impl ScanGamePads(); } + if (player == -1) + player = mMostRecentGamepad; + if ( ( player >= 0 ) && ( player < MAX_PLAYER_COUNT ) ) { if ( mGamePad[ player ] ) @@ -655,6 +675,9 @@ class GamePad::Impl ScanGamePads(); } + if (player == -1) + player = mMostRecentGamepad; + if ( ( player >= 0 ) && ( player < MAX_PLAYER_COUNT ) ) { if ( mGamePad[ player ] ) @@ -703,6 +726,9 @@ class GamePad::Impl { using namespace ABI::Windows::Xbox::Input; + if (player == -1) + player = mMostRecentGamepad; + if ( ( player >= 0 ) && ( player < MAX_PLAYER_COUNT ) ) { if ( mGamePad[ player ] ) @@ -753,6 +779,8 @@ class GamePad::Impl HANDLE mUserChanged; private: + int mMostRecentGamepad; + void ScanGamePads() { using namespace ABI::Windows::Foundation::Collections; @@ -800,6 +828,8 @@ class GamePad::Impl { if ( mGamePad[ k ] == pad ) { + if (!j) + mMostRecentGamepad = static_cast(k); break; } else if ( !mGamePad[ k ] ) @@ -817,6 +847,8 @@ class GamePad::Impl } mGamePad[ empty ] = pad; + if (!j) + mMostRecentGamepad = static_cast(empty); } } } @@ -941,7 +973,12 @@ class GamePad::Impl void GetState( int player, _Out_ State& state, DeadZone deadZoneMode ) { - if ( !ThrottleRetry(player) ) + if (player == -1) + player = GetMostRecent(); + + ULONGLONG time = GetTickCount64(); + + if ( !ThrottleRetry(player, time) ) { #if (_WIN32_WINNT < _WIN32_WINNT_WIN8) if ( mSuspended ) @@ -956,10 +993,13 @@ class GamePad::Impl DWORD result = XInputGetState( DWORD(player), &xstate ); if ( result == ERROR_DEVICE_NOT_CONNECTED ) { - ClearSlot( player, GetTickCount64() ); + ClearSlot( player, time ); } else { + if (!mConnected[player]) + mLastReadTime[player] = time; + mConnected[ player ] = true; state.connected = true; @@ -1010,16 +1050,24 @@ class GamePad::Impl void GetCapabilities( int player, _Out_ Capabilities& caps ) { - if ( !ThrottleRetry(player) ) + if (player == -1) + player = GetMostRecent(); + + ULONGLONG time = GetTickCount64(); + + if ( !ThrottleRetry(player, time) ) { XINPUT_CAPABILITIES xcaps; DWORD result = XInputGetCapabilities( DWORD(player), 0, &xcaps ); if ( result == ERROR_DEVICE_NOT_CONNECTED ) { - ClearSlot( player, GetTickCount64() ); + ClearSlot( player, time ); } else { + if (!mConnected[player]) + mLastReadTime[player] = time; + mConnected[ player ] = true; caps.connected = true; @@ -1051,7 +1099,12 @@ class GamePad::Impl bool SetVibration( int player, float leftMotor, float rightMotor, float leftTrigger, float rightTrigger ) { - if ( ThrottleRetry(player) ) + if (player == -1) + player = GetMostRecent(); + + ULONGLONG time = GetTickCount64(); + + if ( ThrottleRetry(player, time) ) { return false; } @@ -1075,11 +1128,14 @@ class GamePad::Impl DWORD result = XInputSetState( DWORD(player), &xvibration ); if ( result == ERROR_DEVICE_NOT_CONNECTED ) { - ClearSlot( player, GetTickCount64() ); + ClearSlot( player, time ); return false; } else { + if (!mConnected[player]) + mLastReadTime[player] = time; + mConnected[ player ] = true; return (result == ERROR_SUCCESS); } @@ -1116,6 +1172,8 @@ class GamePad::Impl // For XInput 9.1.0, we have to emulate the behavior of XInputEnable( TRUE ) if ( mSuspended ) { + ULONGLONG time = GetTickCount64(); + for( int j = 0; j < XUSER_MAX_COUNT; ++j ) { if ( mConnected[ j ] ) @@ -1126,7 +1184,7 @@ class GamePad::Impl DWORD result = XInputSetState( DWORD(j), &xvibration ); if ( result == ERROR_DEVICE_NOT_CONNECTED ) { - ClearSlot( j, GetTickCount64() ); + ClearSlot( j, time ); } } } @@ -1151,7 +1209,7 @@ class GamePad::Impl bool mSuspended; #endif - bool ThrottleRetry( int player ) + bool ThrottleRetry( int player, ULONGLONG time ) { // This function minimizes a potential performance issue with XInput on Windows when // checking a disconnected controller slot which requires device enumeration. @@ -1163,8 +1221,6 @@ class GamePad::Impl if ( mConnected[ player ] ) return false; - ULONGLONG time = GetTickCount64(); - for( size_t j = 0; j < XUSER_MAX_COUNT; ++j ) { if ( !mConnected[j] ) @@ -1191,6 +1247,23 @@ class GamePad::Impl mLeftMotor[ player ] = mRightMotor[ player ] = 0.f; #endif } + + int GetMostRecent() + { + int player = -1; + ULONGLONG time = 0; + + for (size_t j = 0; j < XUSER_MAX_COUNT; ++j) + { + if (mConnected[j] && (mLastReadTime[j] > time)) + { + time = mLastReadTime[j]; + player = static_cast(j); + } + } + + return player; + } }; GamePad::Impl* GamePad::Impl::s_gamePad = nullptr; diff --git a/Kits/DirectXTK/Src/LoaderHelpers.h b/Kits/DirectXTK/Src/LoaderHelpers.h index d5f2de98..7885aa33 100644 --- a/Kits/DirectXTK/Src/LoaderHelpers.h +++ b/Kits/DirectXTK/Src/LoaderHelpers.h @@ -635,6 +635,11 @@ namespace DirectX } // No DXGI format maps to ISBITMASK(0x0f,0x00,0x00,0xf0) aka D3DFMT_A4L4 + + if (ISBITMASK(0x000000ff, 0x00000000, 0x00000000, 0x0000ff00)) + { + return DXGI_FORMAT_R8G8_UNORM; // Some DDS writers assume the bitcount should be 8 instead of 16 + } } if (16 == ddpf.RGBBitCount) diff --git a/Kits/DirectXTK/Src/ScreenGrab.cpp b/Kits/DirectXTK/Src/ScreenGrab.cpp index 1b7c317a..3829909a 100644 --- a/Kits/DirectXTK/Src/ScreenGrab.cpp +++ b/Kits/DirectXTK/Src/ScreenGrab.cpp @@ -431,7 +431,7 @@ HRESULT DirectX::SaveWICTextureToFile( ID3D11DeviceContext* pContext, { // Opt-in to the WIC2 support for writing 32-bit Windows BMP files with an alpha channel PROPBAG2 option = {}; - option.pstrName = L"EnableV5Header32bppBGRA"; + option.pstrName = const_cast(L"EnableV5Header32bppBGRA"); VARIANT varValue; varValue.vt = VT_BOOL; @@ -517,7 +517,7 @@ HRESULT DirectX::SaveWICTextureToFile( ID3D11DeviceContext* pContext, PropVariantInit( &value ); value.vt = VT_LPSTR; - value.pszVal = "DirectXTK"; + value.pszVal = const_cast("DirectXTK"); if ( memcmp( &guidContainerFormat, &GUID_ContainerFormatPng, sizeof(GUID) ) == 0 ) { diff --git a/Kits/DirectXTK/Src/WICTextureLoader.cpp b/Kits/DirectXTK/Src/WICTextureLoader.cpp index b24f4ae0..2aa9f171 100644 --- a/Kits/DirectXTK/Src/WICTextureLoader.cpp +++ b/Kits/DirectXTK/Src/WICTextureLoader.cpp @@ -130,9 +130,9 @@ namespace { GUID_WICPixelFormat128bppRGBFixedPoint, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT { GUID_WICPixelFormat32bppRGBE, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT - { GUID_WICPixelFormat32bppCMYK, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat32bppCMYK, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM { GUID_WICPixelFormat64bppCMYK, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM - { GUID_WICPixelFormat40bppCMYKAlpha, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM + { GUID_WICPixelFormat40bppCMYKAlpha, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM { GUID_WICPixelFormat80bppCMYKAlpha, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM #if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE) @@ -318,12 +318,12 @@ namespace if (width > height) { twidth = static_cast(maxsize); - theight = static_cast(static_cast(maxsize) * ar); + theight = std::max(1, static_cast(static_cast(maxsize) * ar)); } else { theight = static_cast(maxsize); - twidth = static_cast(static_cast(maxsize) / ar); + twidth = std::max(1, static_cast(static_cast(maxsize) / ar)); } assert(twidth <= maxsize && theight <= maxsize); } @@ -354,12 +354,14 @@ namespace { memcpy(&convertGUID, &GUID_WICPixelFormat96bppRGBFloat, sizeof(WICPixelFormatGUID)); format = DXGI_FORMAT_R32G32B32_FLOAT; + bpp = 96; } else #endif { memcpy(&convertGUID, &GUID_WICPixelFormat128bppRGBAFloat, sizeof(WICPixelFormatGUID)); format = DXGI_FORMAT_R32G32B32A32_FLOAT; + bpp = 128; } } else diff --git a/Kits/DirectXTK12/DirectXTK_Windows10.vcxproj b/Kits/DirectXTK12/DirectXTK_Windows10.vcxproj index 2e51ab46..f458a8f5 100644 --- a/Kits/DirectXTK12/DirectXTK_Windows10.vcxproj +++ b/Kits/DirectXTK12/DirectXTK_Windows10.vcxproj @@ -571,4 +571,9 @@ + + + \ No newline at end of file diff --git a/Kits/DirectXTK12/Inc/Keyboard.h b/Kits/DirectXTK12/Inc/Keyboard.h index cfdb6aac..9c5d6002 100644 --- a/Kits/DirectXTK12/Inc/Keyboard.h +++ b/Kits/DirectXTK12/Inc/Keyboard.h @@ -404,7 +404,7 @@ namespace DirectX bool __cdecl IsKeyDown(Keys key) const { - if (key >= 0 && key <= 0xff) + if (key >= 0 && key <= 0xfe) { auto ptr = reinterpret_cast(this); unsigned int bf = 1u << (key & 0x1f); diff --git a/Kits/DirectXTK12/Inc/RenderTargetState.h b/Kits/DirectXTK12/Inc/RenderTargetState.h index fb84b084..c7461d70 100644 --- a/Kits/DirectXTK12/Inc/RenderTargetState.h +++ b/Kits/DirectXTK12/Inc/RenderTargetState.h @@ -28,27 +28,27 @@ namespace DirectX class RenderTargetState { public: - RenderTargetState::RenderTargetState() - : sampleDesc{} - , rtvFormats{} - , sampleMask(~0U) + RenderTargetState() + : sampleMask(~0U) , numRenderTargets(0) + , rtvFormats{} , dsvFormat(DXGI_FORMAT_UNKNOWN) + , sampleDesc{} , nodeMask(0) { } - RenderTargetState::RenderTargetState(const RenderTargetState& o) = default; + RenderTargetState(const RenderTargetState&) = default; // Single render target convenience constructor - RenderTargetState::RenderTargetState( + RenderTargetState( _In_ DXGI_FORMAT rtFormat, _In_ DXGI_FORMAT dsFormat) : sampleMask(UINT_MAX) - , sampleDesc{} - , rtvFormats{} , numRenderTargets(1) + , rtvFormats{} , dsvFormat(dsFormat) + , sampleDesc{} , nodeMask(0) { sampleDesc.Count = 1; @@ -56,14 +56,14 @@ namespace DirectX } // Convenience constructor converting from DXGI_SWAPCHAIN_DESC - RenderTargetState::RenderTargetState( + RenderTargetState( _In_ const DXGI_SWAP_CHAIN_DESC* desc, _In_ DXGI_FORMAT dsFormat) : sampleMask(UINT_MAX) - , sampleDesc{} - , rtvFormats{} , numRenderTargets(1) + , rtvFormats{} , dsvFormat(dsFormat) + , sampleDesc{} , nodeMask(0) { rtvFormats[0] = desc->BufferDesc.Format; diff --git a/Kits/DirectXTK12/Readme.txt b/Kits/DirectXTK12/Readme.txt index 6107e470..754f4a10 100644 --- a/Kits/DirectXTK12/Readme.txt +++ b/Kits/DirectXTK12/Readme.txt @@ -4,7 +4,7 @@ DirectXTK - the DirectX Tool Kit for DirectX 12 Copyright (c) Microsoft Corporation. All rights reserved. -December 5, 2016 +February 10, 2017 This package contains the "DirectX Tool Kit", a collection of helper classes for writing Direct3D 12 C++ code for Universal Windows Platform (UWP) apps, Win32 desktop @@ -95,6 +95,15 @@ COMPARISONS TO DIRECTX 11 VERSION RELEASE HISTORY --------------- +February 10, 2017 + SpriteBatch default rasterizer state now matches DirectX 11 version + DDSTextureLoader now supports loading planar video format textures + GamePad now supports special value of -1 for 'most recently connected controller' + WIC format 40bppCMYKAlpha should be converted to RGBA8 rather than RGBA16 + DDS support for L8A8 with bitcount 8 rather than 16 + Updated D3DX12 internal copy to latest version + Minor code cleanup + December 5, 2016 Mouse and Keyboard classes updated with IsConnected method Windows10 project /ZW switch removed to support use in C++/WinRT projection apps diff --git a/Kits/DirectXTK12/Src/CommonStates.cpp b/Kits/DirectXTK12/Src/CommonStates.cpp index 0cd57943..d631a896 100644 --- a/Kits/DirectXTK12/Src/CommonStates.cpp +++ b/Kits/DirectXTK12/Src/CommonStates.cpp @@ -112,7 +112,7 @@ const D3D12_DEPTH_STENCIL_DESC CommonStates::DepthNone = D3D12_STENCIL_OP_KEEP, // StencilDepthFailOp D3D12_STENCIL_OP_KEEP, // StencilPassOp D3D12_COMPARISON_FUNC_ALWAYS // StencilFunc - }, // FrontFace, + }, // FrontFace { D3D12_STENCIL_OP_KEEP, // StencilFailOp D3D12_STENCIL_OP_KEEP, // StencilDepthFailOp @@ -134,7 +134,7 @@ const D3D12_DEPTH_STENCIL_DESC CommonStates::DepthDefault = D3D12_STENCIL_OP_KEEP, // StencilDepthFailOp D3D12_STENCIL_OP_KEEP, // StencilPassOp D3D12_COMPARISON_FUNC_ALWAYS // StencilFunc - }, // FrontFace, + }, // FrontFace { D3D12_STENCIL_OP_KEEP, // StencilFailOp D3D12_STENCIL_OP_KEEP, // StencilDepthFailOp @@ -156,7 +156,7 @@ const D3D12_DEPTH_STENCIL_DESC CommonStates::DepthRead = D3D12_STENCIL_OP_KEEP, // StencilDepthFailOp D3D12_STENCIL_OP_KEEP, // StencilPassOp D3D12_COMPARISON_FUNC_ALWAYS // StencilFunc - }, // FrontFace, + }, // FrontFace { D3D12_STENCIL_OP_KEEP, // StencilFailOp D3D12_STENCIL_OP_KEEP, // StencilDepthFailOp diff --git a/Kits/DirectXTK12/Src/DDSTextureLoader.cpp b/Kits/DirectXTK12/Src/DDSTextureLoader.cpp index 251c59b4..af953cea 100644 --- a/Kits/DirectXTK12/Src/DDSTextureLoader.cpp +++ b/Kits/DirectXTK12/Src/DDSTextureLoader.cpp @@ -41,6 +41,80 @@ static_assert(DDS_DIMENSION_TEXTURE3D == D3D12_RESOURCE_DIMENSION_TEXTURE3D, "dd namespace { + inline bool IsDepthStencil(DXGI_FORMAT fmt) + { + switch (fmt) + { + case DXGI_FORMAT_R32G8X24_TYPELESS: + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: + case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: + case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: + case DXGI_FORMAT_D32_FLOAT: + case DXGI_FORMAT_R24G8_TYPELESS: + case DXGI_FORMAT_D24_UNORM_S8_UINT: + case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: + case DXGI_FORMAT_X24_TYPELESS_G8_UINT: + case DXGI_FORMAT_D16_UNORM: + +#if defined(_XBOX_ONE) && defined(_TITLE) + case DXGI_FORMAT_D16_UNORM_S8_UINT: + case DXGI_FORMAT_R16_UNORM_X8_TYPELESS: + case DXGI_FORMAT_X16_TYPELESS_G8_UINT: +#endif + return true; + + default: + return false; + } + } + + //-------------------------------------------------------------------------------------- + inline void AdjustPlaneResource( + _In_ DXGI_FORMAT fmt, + _In_ size_t height, + _In_ size_t slicePlane, + _Inout_ D3D12_SUBRESOURCE_DATA& res) + { + switch (fmt) + { + case DXGI_FORMAT_NV12: + case DXGI_FORMAT_P010: + case DXGI_FORMAT_P016: + +#if defined(_XBOX_ONE) && defined(_TITLE) + case DXGI_FORMAT_D16_UNORM_S8_UINT: + case DXGI_FORMAT_R16_UNORM_X8_TYPELESS: + case DXGI_FORMAT_X16_TYPELESS_G8_UINT: +#endif + if (!slicePlane) + { + // Plane 0 + res.SlicePitch = res.RowPitch * height; + } + else + { + // Plane 1 + res.pData = reinterpret_cast(res.pData) + res.RowPitch * height; + res.SlicePitch = res.RowPitch * ((height + 1) >> 1); + } + break; + + case DXGI_FORMAT_NV11: + if (!slicePlane) + { + // Plane 0 + res.SlicePitch = res.RowPitch * height; + } + else + { + // Plane 1 + res.pData = reinterpret_cast(res.pData) + res.RowPitch * height; + res.RowPitch = (res.RowPitch >> 1); + res.SlicePitch = res.RowPitch * height; + } + break; + } + } //-------------------------------------------------------------------------------------- HRESULT FillInitData(_In_ size_t width, @@ -48,6 +122,7 @@ namespace _In_ size_t depth, _In_ size_t mipCount, _In_ size_t arraySize, + _In_ size_t numberOfPlanes, _In_ DXGI_FORMAT format, _In_ size_t maxsize, _In_ size_t bitSize, @@ -56,9 +131,9 @@ namespace _Out_ size_t& theight, _Out_ size_t& tdepth, _Out_ size_t& skipMip, - _Out_writes_(mipCount*arraySize) D3D12_SUBRESOURCE_DATA* initData) + std::vector& initData) { - if (!bitData || !initData) + if (!bitData) { return E_POINTER; } @@ -70,73 +145,82 @@ namespace size_t NumBytes = 0; size_t RowBytes = 0; - const uint8_t* pSrcBits = bitData; const uint8_t* pEndBits = bitData + bitSize; - size_t index = 0; - for (size_t j = 0; j < arraySize; j++) + initData.clear(); + + for (size_t p = 0; p < numberOfPlanes; ++p) { - size_t w = width; - size_t h = height; - size_t d = depth; - for (size_t i = 0; i < mipCount; i++) + const uint8_t* pSrcBits = bitData; + + for (size_t j = 0; j < arraySize; j++) { - GetSurfaceInfo(w, - h, - format, - &NumBytes, - &RowBytes, - nullptr - ); - - if ((mipCount <= 1) || !maxsize || (w <= maxsize && h <= maxsize && d <= maxsize)) + size_t w = width; + size_t h = height; + size_t d = depth; + for (size_t i = 0; i < mipCount; i++) { - if (!twidth) + GetSurfaceInfo(w, + h, + format, + &NumBytes, + &RowBytes, + nullptr + ); + + if ((mipCount <= 1) || !maxsize || (w <= maxsize && h <= maxsize && d <= maxsize)) { - twidth = w; - theight = h; - tdepth = d; + if (!twidth) + { + twidth = w; + theight = h; + tdepth = d; + } + + D3D12_SUBRESOURCE_DATA res = + { + reinterpret_cast(pSrcBits), + static_cast(RowBytes), + static_cast(NumBytes) + }; + + AdjustPlaneResource(format, h, p, res); + + initData.emplace_back(res); + } + else if (!j) + { + // Count number of skipped mipmaps (first item only) + ++skipMip; } - assert(index < mipCount * arraySize); - _Analysis_assume_(index < mipCount * arraySize); - initData[index].pData = reinterpret_cast(pSrcBits); - initData[index].RowPitch = RowBytes; - initData[index].SlicePitch = NumBytes; - ++index; - } - else if (!j) - { - // Count number of skipped mipmaps (first item only) - ++skipMip; - } - - if (pSrcBits + (NumBytes*d) > pEndBits) - { - return HRESULT_FROM_WIN32(ERROR_HANDLE_EOF); - } + if (pSrcBits + (NumBytes*d) > pEndBits) + { + return HRESULT_FROM_WIN32(ERROR_HANDLE_EOF); + } - pSrcBits += NumBytes * d; + pSrcBits += NumBytes * d; - w = w >> 1; - h = h >> 1; - d = d >> 1; - if (w == 0) - { - w = 1; - } - if (h == 0) - { - h = 1; - } - if (d == 0) - { - d = 1; + w = w >> 1; + h = h >> 1; + d = d >> 1; + if (w == 0) + { + w = 1; + } + if (h == 0) + { + h = 1; + } + if (d == 0) + { + d = 1; + } } } } - return (index > 0) ? S_OK : E_FAIL; + return initData.empty() ? E_FAIL : S_OK; } //-------------------------------------------------------------------------------------- @@ -373,21 +457,40 @@ namespace return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); } + UINT numberOfPlanes = D3D12GetFormatPlaneCount(d3dDevice, format); + if (!numberOfPlanes) + return E_INVALIDARG; + + if ((numberOfPlanes > 1) && IsDepthStencil(format)) + { + // DirectX 12 uses planes for stencil, DirectX 11 does not + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + if (outIsCubeMap != nullptr) { *outIsCubeMap = isCubeMap; } // Create the texture - std::vector initData; - initData.resize(mipCount * arraySize); + size_t numberOfResources = (resDim == D3D12_RESOURCE_DIMENSION_TEXTURE3D) + ? 1 : arraySize; + numberOfResources *= mipCount; + numberOfResources *= numberOfPlanes; + + if (numberOfResources > D3D12_REQ_SUBRESOURCES) + return E_INVALIDARG; + + subresources.reserve(numberOfResources); size_t skipMip = 0; size_t twidth = 0; size_t theight = 0; size_t tdepth = 0; - hr = FillInitData(width, height, depth, mipCount, arraySize, format, maxsize, bitSize, bitData, - twidth, theight, tdepth, skipMip, &initData[0]); + hr = FillInitData(width, height, depth, mipCount, arraySize, + numberOfPlanes, format, + maxsize, bitSize, bitData, + twidth, theight, tdepth, skipMip, subresources); if (SUCCEEDED(hr)) { @@ -402,12 +505,16 @@ namespace if (FAILED(hr) && !maxsize && (mipCount > 1)) { + subresources.clear(); + maxsize = (resDim == D3D12_RESOURCE_DIMENSION_TEXTURE3D) ? D3D12_REQ_TEXTURE3D_U_V_OR_W_DIMENSION : D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION; - hr = FillInitData(width, height, depth, mipCount, arraySize, format, maxsize, bitSize, bitData, - twidth, theight, tdepth, skipMip, &initData[0]); + hr = FillInitData(width, height, depth, mipCount, arraySize, + numberOfPlanes, format, + maxsize, bitSize, bitData, + twidth, theight, tdepth, skipMip, subresources); if (SUCCEEDED(hr)) { hr = CreateTextureResource(d3dDevice, resDim, twidth, theight, tdepth, mipCount - skipMip, arraySize, @@ -416,9 +523,9 @@ namespace } } - if (SUCCEEDED(hr)) + if (FAILED(hr)) { - subresources.insert(subresources.end(), initData.begin(), initData.end()); + subresources.clear(); } return hr; diff --git a/Kits/DirectXTK12/Src/DirectXHelpers.cpp b/Kits/DirectXTK12/Src/DirectXHelpers.cpp index bd4bc0bf..6c14a38d 100644 --- a/Kits/DirectXTK12/Src/DirectXHelpers.cpp +++ b/Kits/DirectXTK12/Src/DirectXHelpers.cpp @@ -32,7 +32,6 @@ void DirectX::CreateShaderResourceView( switch (desc.Dimension) { case D3D12_RESOURCE_DIMENSION_TEXTURE1D: - { if (desc.DepthOrArraySize > 1) { SRVDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1DARRAY; @@ -44,19 +43,15 @@ void DirectX::CreateShaderResourceView( SRVDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1D; SRVDesc.Texture1D.MipLevels = (!desc.MipLevels) ? -1 : desc.MipLevels; } - } - break; + break; case D3D12_RESOURCE_DIMENSION_TEXTURE2D: - { if (isCubeMap) { if (desc.DepthOrArraySize > 6) { SRVDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBEARRAY; SRVDesc.TextureCubeArray.MipLevels = (!desc.MipLevels) ? -1 : desc.MipLevels; - - // Earlier we set arraySize to (NumCubes * 6) SRVDesc.TextureCubeArray.NumCubes = static_cast(desc.DepthOrArraySize / 6); } else @@ -76,15 +71,12 @@ void DirectX::CreateShaderResourceView( SRVDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; SRVDesc.Texture2D.MipLevels = (!desc.MipLevels) ? -1 : desc.MipLevels; } - } - break; + break; case D3D12_RESOURCE_DIMENSION_TEXTURE3D: - { SRVDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE3D; SRVDesc.Texture3D.MipLevels = (!desc.MipLevels) ? -1 : desc.MipLevels; - } - break; + break; case D3D12_RESOURCE_DIMENSION_BUFFER: throw std::exception("CreateShaderResourceView cannot be used with DIMENSION_BUFFER."); diff --git a/Kits/DirectXTK12/Src/GamePad.cpp b/Kits/DirectXTK12/Src/GamePad.cpp index c9cc8157..de040a9e 100644 --- a/Kits/DirectXTK12/Src/GamePad.cpp +++ b/Kits/DirectXTK12/Src/GamePad.cpp @@ -90,7 +90,8 @@ class GamePad::Impl Impl(GamePad* owner) : mOwner(owner), mCtrlChanged(INVALID_HANDLE_VALUE), - mUserChanged(INVALID_HANDLE_VALUE) + mUserChanged(INVALID_HANDLE_VALUE), + mMostRecentGamepad(0) { using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; @@ -169,6 +170,9 @@ class GamePad::Impl ScanGamePads(); } + if (player == -1) + player = mMostRecentGamepad; + if ( ( player >= 0 ) && ( player < MAX_PLAYER_COUNT ) ) { if ( mGamePad[ player ] ) @@ -201,11 +205,11 @@ class GamePad::Impl ApplyStickDeadZone( static_cast(reading.LeftThumbstickX), static_cast(reading.LeftThumbstickY), deadZoneMode, 1.f, .24f /* Recommended Xbox One deadzone */, - static_cast(state.thumbSticks.leftX), static_cast(state.thumbSticks.leftY) ); + state.thumbSticks.leftX, state.thumbSticks.leftY ); ApplyStickDeadZone( static_cast(reading.RightThumbstickX), static_cast(reading.RightThumbstickY), deadZoneMode, 1.f, .24f /* Recommended Xbox One deadzone */, - static_cast(state.thumbSticks.rightX), static_cast(state.thumbSticks.rightY) ); + state.thumbSticks.rightX, state.thumbSticks.rightY ); state.triggers.left = static_cast(reading.LeftTrigger); state.triggers.right = static_cast(reading.RightTrigger); @@ -229,6 +233,9 @@ class GamePad::Impl ScanGamePads(); } + if (player == -1) + player = mMostRecentGamepad; + if ( ( player >= 0 ) && ( player < MAX_PLAYER_COUNT ) ) { if ( mGamePad[ player ] ) @@ -265,6 +272,9 @@ class GamePad::Impl { using namespace ABI::Windows::Gaming::Input; + if (player == -1) + player = mMostRecentGamepad; + if ( ( player >= 0 ) && ( player < MAX_PLAYER_COUNT ) ) { if ( mGamePad[ player ] ) @@ -306,6 +316,8 @@ class GamePad::Impl HANDLE mUserChanged; private: + int mMostRecentGamepad; + void ScanGamePads() { using namespace Microsoft::WRL; @@ -362,6 +374,8 @@ class GamePad::Impl { if ( mGamePad[ k ] == pad ) { + if (j == (count - 1)) + mMostRecentGamepad = static_cast(k); break; } else if ( !mGamePad[ k ] ) @@ -377,6 +391,8 @@ class GamePad::Impl if ( empty < MAX_PLAYER_COUNT ) { mGamePad[ empty ] = pad; + if (j == (count - 1)) + mMostRecentGamepad = static_cast(empty); ComPtr ctrl; hr = pad.As(&ctrl); @@ -526,7 +542,8 @@ class GamePad::Impl Impl(GamePad *owner) : mOwner(owner), mCtrlChanged(INVALID_HANDLE_VALUE), - mUserChanged(INVALID_HANDLE_VALUE) + mUserChanged(INVALID_HANDLE_VALUE), + mMostRecentGamepad(0) { using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; @@ -596,6 +613,9 @@ class GamePad::Impl ScanGamePads(); } + if (player == -1) + player = mMostRecentGamepad; + if ( ( player >= 0 ) && ( player < MAX_PLAYER_COUNT ) ) { if ( mGamePad[ player ] ) @@ -655,6 +675,9 @@ class GamePad::Impl ScanGamePads(); } + if (player == -1) + player = mMostRecentGamepad; + if ( ( player >= 0 ) && ( player < MAX_PLAYER_COUNT ) ) { if ( mGamePad[ player ] ) @@ -703,6 +726,9 @@ class GamePad::Impl { using namespace ABI::Windows::Xbox::Input; + if (player == -1) + player = mMostRecentGamepad; + if ( ( player >= 0 ) && ( player < MAX_PLAYER_COUNT ) ) { if ( mGamePad[ player ] ) @@ -753,6 +779,8 @@ class GamePad::Impl HANDLE mUserChanged; private: + int mMostRecentGamepad; + void ScanGamePads() { using namespace ABI::Windows::Foundation::Collections; @@ -800,6 +828,8 @@ class GamePad::Impl { if ( mGamePad[ k ] == pad ) { + if (!j) + mMostRecentGamepad = static_cast(k); break; } else if ( !mGamePad[ k ] ) @@ -817,6 +847,8 @@ class GamePad::Impl } mGamePad[ empty ] = pad; + if (!j) + mMostRecentGamepad = static_cast(empty); } } } @@ -941,7 +973,12 @@ class GamePad::Impl void GetState( int player, _Out_ State& state, DeadZone deadZoneMode ) { - if ( !ThrottleRetry(player) ) + if (player == -1) + player = GetMostRecent(); + + ULONGLONG time = GetTickCount64(); + + if ( !ThrottleRetry(player, time) ) { #if (_WIN32_WINNT < _WIN32_WINNT_WIN8) if ( mSuspended ) @@ -956,10 +993,13 @@ class GamePad::Impl DWORD result = XInputGetState( DWORD(player), &xstate ); if ( result == ERROR_DEVICE_NOT_CONNECTED ) { - ClearSlot( player, GetTickCount64() ); + ClearSlot( player, time ); } else { + if (!mConnected[player]) + mLastReadTime[player] = time; + mConnected[ player ] = true; state.connected = true; @@ -1010,16 +1050,24 @@ class GamePad::Impl void GetCapabilities( int player, _Out_ Capabilities& caps ) { - if ( !ThrottleRetry(player) ) + if (player == -1) + player = GetMostRecent(); + + ULONGLONG time = GetTickCount64(); + + if ( !ThrottleRetry(player, time) ) { XINPUT_CAPABILITIES xcaps; DWORD result = XInputGetCapabilities( DWORD(player), 0, &xcaps ); if ( result == ERROR_DEVICE_NOT_CONNECTED ) { - ClearSlot( player, GetTickCount64() ); + ClearSlot( player, time ); } else { + if (!mConnected[player]) + mLastReadTime[player] = time; + mConnected[ player ] = true; caps.connected = true; @@ -1051,7 +1099,12 @@ class GamePad::Impl bool SetVibration( int player, float leftMotor, float rightMotor, float leftTrigger, float rightTrigger ) { - if ( ThrottleRetry(player) ) + if (player == -1) + player = GetMostRecent(); + + ULONGLONG time = GetTickCount64(); + + if ( ThrottleRetry(player, time) ) { return false; } @@ -1075,11 +1128,14 @@ class GamePad::Impl DWORD result = XInputSetState( DWORD(player), &xvibration ); if ( result == ERROR_DEVICE_NOT_CONNECTED ) { - ClearSlot( player, GetTickCount64() ); + ClearSlot( player, time ); return false; } else { + if (!mConnected[player]) + mLastReadTime[player] = time; + mConnected[ player ] = true; return (result == ERROR_SUCCESS); } @@ -1116,6 +1172,8 @@ class GamePad::Impl // For XInput 9.1.0, we have to emulate the behavior of XInputEnable( TRUE ) if ( mSuspended ) { + ULONGLONG time = GetTickCount64(); + for( int j = 0; j < XUSER_MAX_COUNT; ++j ) { if ( mConnected[ j ] ) @@ -1126,7 +1184,7 @@ class GamePad::Impl DWORD result = XInputSetState( DWORD(j), &xvibration ); if ( result == ERROR_DEVICE_NOT_CONNECTED ) { - ClearSlot( j, GetTickCount64() ); + ClearSlot( j, time ); } } } @@ -1151,7 +1209,7 @@ class GamePad::Impl bool mSuspended; #endif - bool ThrottleRetry( int player ) + bool ThrottleRetry( int player, ULONGLONG time ) { // This function minimizes a potential performance issue with XInput on Windows when // checking a disconnected controller slot which requires device enumeration. @@ -1163,8 +1221,6 @@ class GamePad::Impl if ( mConnected[ player ] ) return false; - ULONGLONG time = GetTickCount64(); - for( size_t j = 0; j < XUSER_MAX_COUNT; ++j ) { if ( !mConnected[j] ) @@ -1191,6 +1247,23 @@ class GamePad::Impl mLeftMotor[ player ] = mRightMotor[ player ] = 0.f; #endif } + + int GetMostRecent() + { + int player = -1; + ULONGLONG time = 0; + + for (size_t j = 0; j < XUSER_MAX_COUNT; ++j) + { + if (mConnected[j] && (mLastReadTime[j] > time)) + { + time = mLastReadTime[j]; + player = static_cast(j); + } + } + + return player; + } }; GamePad::Impl* GamePad::Impl::s_gamePad = nullptr; diff --git a/Kits/DirectXTK12/Src/LoaderHelpers.h b/Kits/DirectXTK12/Src/LoaderHelpers.h index d5f2de98..7885aa33 100644 --- a/Kits/DirectXTK12/Src/LoaderHelpers.h +++ b/Kits/DirectXTK12/Src/LoaderHelpers.h @@ -635,6 +635,11 @@ namespace DirectX } // No DXGI format maps to ISBITMASK(0x0f,0x00,0x00,0xf0) aka D3DFMT_A4L4 + + if (ISBITMASK(0x000000ff, 0x00000000, 0x00000000, 0x0000ff00)) + { + return DXGI_FORMAT_R8G8_UNORM; // Some DDS writers assume the bitcount should be 8 instead of 16 + } } if (16 == ddpf.RGBBitCount) diff --git a/Kits/DirectXTK12/Src/ResourceUploadBatch.cpp b/Kits/DirectXTK12/Src/ResourceUploadBatch.cpp index 86771028..23742980 100644 --- a/Kits/DirectXTK12/Src/ResourceUploadBatch.cpp +++ b/Kits/DirectXTK12/Src/ResourceUploadBatch.cpp @@ -74,7 +74,7 @@ namespace } } - bool FormatRequiresSwizzle(DXGI_FORMAT format) + bool FormatIsBGR(DXGI_FORMAT format) { switch (format) { @@ -329,7 +329,7 @@ class ResourceUploadBatch::Impl { throw std::exception("GenerateMips only supports 2D textures of array size 1"); } - if (!FormatIsUAVCompatible(desc.Format) && !FormatIsSRGB(desc.Format) && !FormatRequiresSwizzle(desc.Format)) + if (!FormatIsUAVCompatible(desc.Format) && !FormatIsSRGB(desc.Format) && !FormatIsBGR(desc.Format)) { throw std::exception("GenerateMips doesn't support this texture format"); } @@ -341,11 +341,15 @@ class ResourceUploadBatch::Impl } // If the texture's format doesn't support UAVs we'll have to copy it to a texture that does first. - // This is true of BGRA (which need swizzling) or sRGB textures (which need de-gamma), for example. + // This is true of BGRA or sRGB textures, for example. if (FormatIsUAVCompatible(desc.Format)) { GenerateMips_UnorderedAccessPath(resource); } + else if (FormatIsBGR(desc.Format)) + { + GenerateMips_TexturePathBGR(resource); + } else { GenerateMips_TexturePath(resource); @@ -430,8 +434,7 @@ class ResourceUploadBatch::Impl _In_ ID3D12Resource* resource) { const auto& desc = resource->GetDesc(); - - assert(!FormatRequiresSwizzle(desc.Format) && !FormatIsSRGB(desc.Format)); + assert(!FormatIsBGR(desc.Format) && !FormatIsSRGB(desc.Format)); CD3DX12_HEAP_PROPERTIES defaultHeapProperties(D3D12_HEAP_TYPE_DEFAULT); @@ -604,7 +607,7 @@ class ResourceUploadBatch::Impl _In_ ID3D12Resource* resource) { const auto& resourceDesc = resource->GetDesc(); - assert(FormatRequiresSwizzle(resourceDesc.Format) || FormatIsSRGB(resourceDesc.Format)); + assert(!FormatIsBGR(resourceDesc.Format) || FormatIsSRGB(resourceDesc.Format)); auto copyDesc = resourceDesc; copyDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; @@ -643,6 +646,77 @@ class ResourceUploadBatch::Impl mTrackedObjects.push_back(resource); } + // Resource is not UAV compatible (copy via alias to avoid validation failure) + void GenerateMips_TexturePathBGR( + _In_ ID3D12Resource* resource) + { + const auto& resourceDesc = resource->GetDesc(); + assert(FormatIsBGR(resourceDesc.Format)); + + // Create a resource with the same description, but without SRGB, and with UAV flags + auto copyDesc = resourceDesc; + copyDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + copyDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS; + + D3D12_HEAP_DESC heapDesc = {}; + auto allocInfo = mDevice->GetResourceAllocationInfo(0, 1, &resourceDesc); + heapDesc.SizeInBytes = allocInfo.SizeInBytes; + heapDesc.Flags = D3D12_HEAP_FLAG_ALLOW_ONLY_NON_RT_DS_TEXTURES; + heapDesc.Properties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; + heapDesc.Properties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; + heapDesc.Properties.Type = D3D12_HEAP_TYPE_DEFAULT; + + ComPtr heap; + ThrowIfFailed(mDevice->CreateHeap(&heapDesc, IID_GRAPHICS_PPV_ARGS(heap.GetAddressOf()))); + + ComPtr resourceCopy; + ThrowIfFailed(mDevice->CreatePlacedResource( + heap.Get(), + 0, + ©Desc, + D3D12_RESOURCE_STATE_COPY_DEST, + nullptr, + IID_GRAPHICS_PPV_ARGS(resourceCopy.GetAddressOf()))); + + SetDebugObjectName(resourceCopy.Get(), L"GenerateMips Resource Copy"); + + // Create a BGRA alias + auto aliasDesc = resourceDesc; + aliasDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + + ComPtr aliasCopy; + ThrowIfFailed(mDevice->CreatePlacedResource( + heap.Get(), + 0, + &aliasDesc, + D3D12_RESOURCE_STATE_COPY_DEST, + nullptr, + IID_GRAPHICS_PPV_ARGS(aliasCopy.GetAddressOf()))); + + // Copy the resource data + AliasBarrier(nullptr, aliasCopy.Get()); + Transition(resource, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_COPY_SOURCE); + mList->CopyResource(aliasCopy.Get(), resource); + + // Generate the mips + AliasBarrier(aliasCopy.Get(), resourceCopy.Get()); + Transition(resourceCopy.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); + GenerateMips_UnorderedAccessPath(resourceCopy.Get()); + + // Direct copy back + AliasBarrier(resourceCopy.Get(), aliasCopy.Get()); + Transition(aliasCopy.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_COPY_SOURCE); + Transition(resource, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_COPY_DEST); + mList->CopyResource(resource, aliasCopy.Get()); + Transition(resource, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); + + // Track these object lifetimes on the GPU + mTrackedObjects.push_back(heap); + mTrackedObjects.push_back(resourceCopy); + mTrackedObjects.push_back(aliasCopy); + mTrackedObjects.push_back(resource); + } + void AliasBarrier(_In_opt_ ID3D12Resource* before, _In_ ID3D12Resource* after) { if (before == after) diff --git a/Kits/DirectXTK12/Src/ScreenGrab.cpp b/Kits/DirectXTK12/Src/ScreenGrab.cpp index 0b9827ca..d59aea49 100644 --- a/Kits/DirectXTK12/Src/ScreenGrab.cpp +++ b/Kits/DirectXTK12/Src/ScreenGrab.cpp @@ -55,6 +55,10 @@ namespace if (desc.Dimension != D3D12_RESOURCE_DIMENSION_TEXTURE2D) return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + UINT numberOfPlanes = D3D12GetFormatPlaneCount(device, desc.Format); + if (numberOfPlanes != 1) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + D3D12_HEAP_PROPERTIES sourceHeapProperties; D3D12_HEAP_FLAGS sourceHeapFlags; HRESULT hr = pSource->GetHeapProperties(&sourceHeapProperties, &sourceHeapFlags); @@ -538,7 +542,7 @@ HRESULT DirectX::SaveWICTextureToFile( { // Opt-in to the WIC2 support for writing 32-bit Windows BMP files with an alpha channel PROPBAG2 option = {}; - option.pstrName = L"EnableV5Header32bppBGRA"; + option.pstrName = const_cast(L"EnableV5Header32bppBGRA"); VARIANT varValue; varValue.vt = VT_BOOL; @@ -615,7 +619,7 @@ HRESULT DirectX::SaveWICTextureToFile( PropVariantInit(&value); value.vt = VT_LPSTR; - value.pszVal = "DirectXTK"; + value.pszVal = const_cast("DirectXTK"); if (memcmp(&guidContainerFormat, &GUID_ContainerFormatPng, sizeof(GUID)) == 0) { diff --git a/Kits/DirectXTK12/Src/SpriteBatch.cpp b/Kits/DirectXTK12/Src/SpriteBatch.cpp index 7a070345..45c371c0 100644 --- a/Kits/DirectXTK12/Src/SpriteBatch.cpp +++ b/Kits/DirectXTK12/Src/SpriteBatch.cpp @@ -225,9 +225,63 @@ const D3D12_SHADER_BYTECODE SpriteBatch::Impl::s_DefaultPixelShaderByteCodeHeap const D3D12_INPUT_LAYOUT_DESC SpriteBatch::Impl::s_DefaultInputLayoutDesc = VertexPositionColorTexture::InputLayout; -const D3D12_BLEND_DESC SpriteBatchPipelineStateDescription::s_DefaultBlendDesc = {FALSE, FALSE, {TRUE, FALSE, D3D12_BLEND_ONE, D3D12_BLEND_INV_SRC_ALPHA, D3D12_BLEND_OP_ADD, D3D12_BLEND_ONE, D3D12_BLEND_INV_SRC_ALPHA, D3D12_BLEND_OP_ADD, D3D12_LOGIC_OP_CLEAR, D3D12_COLOR_WRITE_ENABLE_ALL}}; -const D3D12_RASTERIZER_DESC SpriteBatchPipelineStateDescription::s_DefaultRasterizerDesc = {D3D12_FILL_MODE_SOLID, D3D12_CULL_MODE_NONE, FALSE, 0, 0, 0, FALSE, FALSE, FALSE, 0, D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF}; -const D3D12_DEPTH_STENCIL_DESC SpriteBatchPipelineStateDescription::s_DefaultDepthStencilDesc = {FALSE, D3D12_DEPTH_WRITE_MASK_ALL, D3D12_COMPARISON_FUNC_ALWAYS, FALSE, 0, 0}; +// Matches CommonStates::AlphaBlend +const D3D12_BLEND_DESC SpriteBatchPipelineStateDescription::s_DefaultBlendDesc = +{ + FALSE, // AlphaToCoverageEnable + FALSE, // IndependentBlendEnable + { + TRUE, // BlendEnable + FALSE, // LogicOpEnable + D3D12_BLEND_ONE, // SrcBlend + D3D12_BLEND_INV_SRC_ALPHA, // DestBlend + D3D12_BLEND_OP_ADD, // BlendOp + D3D12_BLEND_ONE, // SrcBlendAlpha + D3D12_BLEND_INV_SRC_ALPHA, // DestBlendAlpha + D3D12_BLEND_OP_ADD, // BlendOpAlpha + D3D12_LOGIC_OP_NOOP, + D3D12_COLOR_WRITE_ENABLE_ALL + } +}; + +// Same to CommonStates::CullCounterClockwise +const D3D12_RASTERIZER_DESC SpriteBatchPipelineStateDescription::s_DefaultRasterizerDesc = +{ + D3D12_FILL_MODE_SOLID, + D3D12_CULL_MODE_BACK, + FALSE, // FrontCounterClockwise + D3D12_DEFAULT_DEPTH_BIAS, + D3D12_DEFAULT_DEPTH_BIAS_CLAMP, + D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS, + TRUE, // DepthClipEnable + TRUE, // MultisampleEnable + FALSE, // AntialiasedLineEnable + 0, // ForcedSampleCount + D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF +}; + +// Same as CommonStates::DepthNone +const D3D12_DEPTH_STENCIL_DESC SpriteBatchPipelineStateDescription::s_DefaultDepthStencilDesc = +{ + FALSE, // DepthEnable + D3D12_DEPTH_WRITE_MASK_ZERO, + D3D12_COMPARISON_FUNC_LESS_EQUAL, // DepthFunc + FALSE, // StencilEnable + D3D12_DEFAULT_STENCIL_READ_MASK, + D3D12_DEFAULT_STENCIL_WRITE_MASK, + { + D3D12_STENCIL_OP_KEEP, // StencilFailOp + D3D12_STENCIL_OP_KEEP, // StencilDepthFailOp + D3D12_STENCIL_OP_KEEP, // StencilPassOp + D3D12_COMPARISON_FUNC_ALWAYS // StencilFunc + }, // FrontFace + { + D3D12_STENCIL_OP_KEEP, // StencilFailOp + D3D12_STENCIL_OP_KEEP, // StencilDepthFailOp + D3D12_STENCIL_OP_KEEP, // StencilPassOp + D3D12_COMPARISON_FUNC_ALWAYS // StencilFunc + } // BackFace +}; // Per-device constructor. SpriteBatch::Impl::DeviceResources::DeviceResources(_In_ ID3D12Device* device, ResourceUploadBatch& upload) @@ -284,6 +338,7 @@ void SpriteBatch::Impl::DeviceResources::CreateRootSignatures(_In_ ID3D12Device* CD3DX12_DESCRIPTOR_RANGE textureSRV(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 0); { + // Same as CommonStates::StaticLinearClamp CD3DX12_STATIC_SAMPLER_DESC sampler( 0, // register D3D12_FILTER_MIN_MAG_MIP_LINEAR, @@ -354,7 +409,7 @@ SpriteBatch::Impl::Impl(ID3D12Device* device, ResourceUploadBatch& upload, const mSampler{}, mTransformMatrix(MatrixIdentity), mDeviceResources(deviceResourcesPool.DemandCreate(device, upload)), - mVertexPageSize(sizeof(VertexPositionNormalColorTexture) * MaxBatchSize * VerticesPerSprite), + mVertexPageSize(sizeof(VertexPositionColorTexture) * MaxBatchSize * VerticesPerSprite), mVertexSegment {}, mSpriteCount(0) { diff --git a/Kits/DirectXTK12/Src/WICTextureLoader.cpp b/Kits/DirectXTK12/Src/WICTextureLoader.cpp index 9ec54577..a71b3e37 100644 --- a/Kits/DirectXTK12/Src/WICTextureLoader.cpp +++ b/Kits/DirectXTK12/Src/WICTextureLoader.cpp @@ -135,9 +135,9 @@ namespace { GUID_WICPixelFormat128bppRGBFixedPoint, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT { GUID_WICPixelFormat32bppRGBE, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT - { GUID_WICPixelFormat32bppCMYK, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat32bppCMYK, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM { GUID_WICPixelFormat64bppCMYK, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM - { GUID_WICPixelFormat40bppCMYKAlpha, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM + { GUID_WICPixelFormat40bppCMYKAlpha, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM { GUID_WICPixelFormat80bppCMYKAlpha, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM { GUID_WICPixelFormat32bppRGB, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM @@ -248,12 +248,12 @@ namespace if (width > height) { twidth = static_cast(maxsize); - theight = static_cast(static_cast(maxsize) * ar); + theight = std::max(1, static_cast(static_cast(maxsize) * ar)); } else { theight = static_cast(maxsize); - twidth = static_cast(static_cast(maxsize) / ar); + twidth = std::max(1, static_cast(static_cast(maxsize) / ar)); } assert(twidth <= maxsize && theight <= maxsize); } diff --git a/Kits/DirectXTK12/Src/d3dx12.h b/Kits/DirectXTK12/Src/d3dx12.h index cda6e036..793aee98 100644 --- a/Kits/DirectXTK12/Src/d3dx12.h +++ b/Kits/DirectXTK12/Src/d3dx12.h @@ -524,7 +524,7 @@ struct CD3DX12_SHADER_BYTECODE : public D3D12_SHADER_BYTECODE BytecodeLength = pShaderBlob->GetBufferSize(); } CD3DX12_SHADER_BYTECODE( - const void* _pShaderBytecode, + _In_reads_(bytecodeLength) const void* _pShaderBytecode, SIZE_T bytecodeLength ) { pShaderBytecode = _pShaderBytecode; @@ -1922,6 +1922,11 @@ inline HRESULT D3DX12SerializeVersionedRootSignature( _Outptr_ ID3DBlob** ppBlob, _Always_(_Outptr_opt_result_maybenull_) ID3DBlob** ppErrorBlob) { + if (ppErrorBlob != NULL) + { + *ppErrorBlob = NULL; + } + switch (MaxVersion) { case D3D_ROOT_SIGNATURE_VERSION_1_0: @@ -1932,65 +1937,88 @@ inline HRESULT D3DX12SerializeVersionedRootSignature( case D3D_ROOT_SIGNATURE_VERSION_1_1: { + HRESULT hr = S_OK; const D3D12_ROOT_SIGNATURE_DESC1& desc_1_1 = pRootSignatureDesc->Desc_1_1; - SIZE_T ParametersSize = sizeof(D3D12_ROOT_PARAMETER) * desc_1_1.NumParameters; + const SIZE_T ParametersSize = sizeof(D3D12_ROOT_PARAMETER) * desc_1_1.NumParameters; void* pParameters = (ParametersSize > 0) ? HeapAlloc(GetProcessHeap(), 0, ParametersSize) : NULL; + if (ParametersSize > 0 && pParameters == NULL) + { + hr = E_OUTOFMEMORY; + } D3D12_ROOT_PARAMETER* pParameters_1_0 = reinterpret_cast(pParameters); - for (UINT n = 0; n < desc_1_1.NumParameters; n++) + if (SUCCEEDED(hr)) { - pParameters_1_0[n].ParameterType = desc_1_1.pParameters[n].ParameterType; - pParameters_1_0[n].ShaderVisibility = desc_1_1.pParameters[n].ShaderVisibility; - - switch (desc_1_1.pParameters[n].ParameterType) + for (UINT n = 0; n < desc_1_1.NumParameters; n++) { - case D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS: - pParameters_1_0[n].Constants.Num32BitValues = desc_1_1.pParameters[n].Constants.Num32BitValues; - pParameters_1_0[n].Constants.RegisterSpace = desc_1_1.pParameters[n].Constants.RegisterSpace; - pParameters_1_0[n].Constants.ShaderRegister = desc_1_1.pParameters[n].Constants.ShaderRegister; - break; - - case D3D12_ROOT_PARAMETER_TYPE_CBV: - case D3D12_ROOT_PARAMETER_TYPE_SRV: - case D3D12_ROOT_PARAMETER_TYPE_UAV: - pParameters_1_0[n].Descriptor.RegisterSpace = desc_1_1.pParameters[n].Descriptor.RegisterSpace; - pParameters_1_0[n].Descriptor.ShaderRegister = desc_1_1.pParameters[n].Descriptor.ShaderRegister; - break; - - case D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE: - const D3D12_ROOT_DESCRIPTOR_TABLE1& table_1_1 = desc_1_1.pParameters[n].DescriptorTable; - - SIZE_T DescriptorRangesSize = sizeof(D3D12_DESCRIPTOR_RANGE) * table_1_1.NumDescriptorRanges; - void* pDescriptorRanges = (DescriptorRangesSize > 0) ? HeapAlloc(GetProcessHeap(), 0, DescriptorRangesSize) : NULL; - D3D12_DESCRIPTOR_RANGE* pDescriptorRanges_1_0 = reinterpret_cast(pDescriptorRanges); - - for (UINT x = 0; x < table_1_1.NumDescriptorRanges; x++) + __analysis_assume(ParametersSize == sizeof(D3D12_ROOT_PARAMETER) * desc_1_1.NumParameters); + pParameters_1_0[n].ParameterType = desc_1_1.pParameters[n].ParameterType; + pParameters_1_0[n].ShaderVisibility = desc_1_1.pParameters[n].ShaderVisibility; + + switch (desc_1_1.pParameters[n].ParameterType) { - pDescriptorRanges_1_0[x].BaseShaderRegister = table_1_1.pDescriptorRanges[x].BaseShaderRegister; - pDescriptorRanges_1_0[x].NumDescriptors = table_1_1.pDescriptorRanges[x].NumDescriptors; - pDescriptorRanges_1_0[x].OffsetInDescriptorsFromTableStart = table_1_1.pDescriptorRanges[x].OffsetInDescriptorsFromTableStart; - pDescriptorRanges_1_0[x].RangeType = table_1_1.pDescriptorRanges[x].RangeType; - pDescriptorRanges_1_0[x].RegisterSpace = table_1_1.pDescriptorRanges[x].RegisterSpace; + case D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS: + pParameters_1_0[n].Constants.Num32BitValues = desc_1_1.pParameters[n].Constants.Num32BitValues; + pParameters_1_0[n].Constants.RegisterSpace = desc_1_1.pParameters[n].Constants.RegisterSpace; + pParameters_1_0[n].Constants.ShaderRegister = desc_1_1.pParameters[n].Constants.ShaderRegister; + break; + + case D3D12_ROOT_PARAMETER_TYPE_CBV: + case D3D12_ROOT_PARAMETER_TYPE_SRV: + case D3D12_ROOT_PARAMETER_TYPE_UAV: + pParameters_1_0[n].Descriptor.RegisterSpace = desc_1_1.pParameters[n].Descriptor.RegisterSpace; + pParameters_1_0[n].Descriptor.ShaderRegister = desc_1_1.pParameters[n].Descriptor.ShaderRegister; + break; + + case D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE: + const D3D12_ROOT_DESCRIPTOR_TABLE1& table_1_1 = desc_1_1.pParameters[n].DescriptorTable; + + const SIZE_T DescriptorRangesSize = sizeof(D3D12_DESCRIPTOR_RANGE) * table_1_1.NumDescriptorRanges; + void* pDescriptorRanges = (DescriptorRangesSize > 0 && SUCCEEDED(hr)) ? HeapAlloc(GetProcessHeap(), 0, DescriptorRangesSize) : NULL; + if (DescriptorRangesSize > 0 && pDescriptorRanges == NULL) + { + hr = E_OUTOFMEMORY; + } + D3D12_DESCRIPTOR_RANGE* pDescriptorRanges_1_0 = reinterpret_cast(pDescriptorRanges); + + if (SUCCEEDED(hr)) + { + for (UINT x = 0; x < table_1_1.NumDescriptorRanges; x++) + { + __analysis_assume(DescriptorRangesSize == sizeof(D3D12_DESCRIPTOR_RANGE) * table_1_1.NumDescriptorRanges); + pDescriptorRanges_1_0[x].BaseShaderRegister = table_1_1.pDescriptorRanges[x].BaseShaderRegister; + pDescriptorRanges_1_0[x].NumDescriptors = table_1_1.pDescriptorRanges[x].NumDescriptors; + pDescriptorRanges_1_0[x].OffsetInDescriptorsFromTableStart = table_1_1.pDescriptorRanges[x].OffsetInDescriptorsFromTableStart; + pDescriptorRanges_1_0[x].RangeType = table_1_1.pDescriptorRanges[x].RangeType; + pDescriptorRanges_1_0[x].RegisterSpace = table_1_1.pDescriptorRanges[x].RegisterSpace; + } + } + + D3D12_ROOT_DESCRIPTOR_TABLE& table_1_0 = pParameters_1_0[n].DescriptorTable; + table_1_0.NumDescriptorRanges = table_1_1.NumDescriptorRanges; + table_1_0.pDescriptorRanges = pDescriptorRanges_1_0; } - - D3D12_ROOT_DESCRIPTOR_TABLE& table_1_0 = pParameters_1_0[n].DescriptorTable; - table_1_0.NumDescriptorRanges = table_1_1.NumDescriptorRanges; - table_1_0.pDescriptorRanges = pDescriptorRanges_1_0; } } - CD3DX12_ROOT_SIGNATURE_DESC desc_1_0(desc_1_1.NumParameters, pParameters_1_0, desc_1_1.NumStaticSamplers, desc_1_1.pStaticSamplers, desc_1_1.Flags); - HRESULT hr = D3D12SerializeRootSignature(&desc_1_0, D3D_ROOT_SIGNATURE_VERSION_1, ppBlob, ppErrorBlob); + if (SUCCEEDED(hr)) + { + CD3DX12_ROOT_SIGNATURE_DESC desc_1_0(desc_1_1.NumParameters, pParameters_1_0, desc_1_1.NumStaticSamplers, desc_1_1.pStaticSamplers, desc_1_1.Flags); + hr = D3D12SerializeRootSignature(&desc_1_0, D3D_ROOT_SIGNATURE_VERSION_1, ppBlob, ppErrorBlob); + } - for (UINT n = 0; n < desc_1_0.NumParameters; n++) + if (pParameters) { - if (desc_1_0.pParameters[n].ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE) + for (UINT n = 0; n < desc_1_1.NumParameters; n++) { - HeapFree(GetProcessHeap(), 0, reinterpret_cast(const_cast(pParameters_1_0[n].DescriptorTable.pDescriptorRanges))); + if (desc_1_1.pParameters[n].ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE) + { + HeapFree(GetProcessHeap(), 0, reinterpret_cast(const_cast(pParameters_1_0[n].DescriptorTable.pDescriptorRanges))); + } } + HeapFree(GetProcessHeap(), 0, pParameters); } - HeapFree(GetProcessHeap(), 0, pParameters); return hr; } }