diff options
| author | assiduous <assiduous@diligentgraphics.com> | 2020-04-24 03:55:17 +0000 |
|---|---|---|
| committer | assiduous <assiduous@diligentgraphics.com> | 2020-04-24 03:55:17 +0000 |
| commit | 5cc8a3953c7986bec781d7c1f8a014195ca4bf6b (patch) | |
| tree | cd5426ebffc0af628236d45ed70e25969065cab5 /Graphics | |
| parent | Merge pull request #128 from Dinolek/master (diff) | |
| download | DiligentCore-5cc8a3953c7986bec781d7c1f8a014195ca4bf6b.tar.gz DiligentCore-5cc8a3953c7986bec781d7c1f8a014195ca4bf6b.zip | |
Added surface pretransform parameter to swap chain desc (API 240057)
Diffstat (limited to 'Graphics')
20 files changed, 279 insertions, 39 deletions
diff --git a/Graphics/GraphicsAccessories/interface/GraphicsAccessories.hpp b/Graphics/GraphicsAccessories/interface/GraphicsAccessories.hpp index 9b0547cc..934cad26 100644 --- a/Graphics/GraphicsAccessories/interface/GraphicsAccessories.hpp +++ b/Graphics/GraphicsAccessories/interface/GraphicsAccessories.hpp @@ -376,6 +376,8 @@ inline String GetObjectDescString(const BufferDesc& BuffDesc) const char* GetQueryTypeString(QUERY_TYPE QueryType); +const char* GetSurfaceTransformString(SURFACE_TRANSFORM SrfTransform); + Uint32 ComputeMipLevelsCount(Uint32 Width); Uint32 ComputeMipLevelsCount(Uint32 Width, Uint32 Height); Uint32 ComputeMipLevelsCount(Uint32 Width, Uint32 Height, Uint32 Depth); diff --git a/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp b/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp index da247e31..fff50193 100644 --- a/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp +++ b/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp @@ -1083,6 +1083,32 @@ const char* GetQueryTypeString(QUERY_TYPE QueryType) // clang-format on } +const char* GetSurfaceTransformString(SURFACE_TRANSFORM SrfTransform) +{ + // clang-format off + switch (SrfTransform) + { +#define SRF_TRANSFORM_CASE(Transform) case Transform: return #Transform + + SRF_TRANSFORM_CASE(SURFACE_TRANSFORM_OPTIMAL); + SRF_TRANSFORM_CASE(SURFACE_TRANSFORM_IDENTITY); + SRF_TRANSFORM_CASE(SURFACE_TRANSFORM_ROTATE_90); + SRF_TRANSFORM_CASE(SURFACE_TRANSFORM_ROTATE_180); + SRF_TRANSFORM_CASE(SURFACE_TRANSFORM_ROTATE_270); + SRF_TRANSFORM_CASE(SURFACE_TRANSFORM_HORIZONTAL_MIRROR); + SRF_TRANSFORM_CASE(SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90); + SRF_TRANSFORM_CASE(SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180); + SRF_TRANSFORM_CASE(SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270); + +#undef SRF_TRANSFORM_CASE + + default: + UNEXPECTED("Unexpected surface transform"); + return "UNKNOWN"; + } + // clang-format on +} + Uint32 ComputeMipLevelsCount(Uint32 Width) { if (Width == 0) diff --git a/Graphics/GraphicsEngine/include/SwapChainBase.hpp b/Graphics/GraphicsEngine/include/SwapChainBase.hpp index 8610f0de..181826ac 100644 --- a/Graphics/GraphicsEngine/include/SwapChainBase.hpp +++ b/Graphics/GraphicsEngine/include/SwapChainBase.hpp @@ -62,10 +62,11 @@ public: IDeviceContext* pDeviceContext, const SwapChainDesc& SCDesc) : // clang-format off - TObjectBase {pRefCounters}, - m_pRenderDevice {pDevice }, - m_wpDeviceContext {pDeviceContext}, - m_SwapChainDesc {SCDesc } + TObjectBase {pRefCounters }, + m_pRenderDevice {pDevice }, + m_wpDeviceContext {pDeviceContext }, + m_SwapChainDesc {SCDesc }, + m_DesiredPreTransform{SCDesc.PreTransform} // clang-format on { } @@ -90,13 +91,16 @@ public: } protected: - bool Resize(Uint32 NewWidth, Uint32 NewHeight, Int32 Dummy = 0 /*To be different from virtual function*/) + bool Resize(Uint32 NewWidth, Uint32 NewHeight, SURFACE_TRANSFORM NewPreTransform, Int32 Dummy = 0 /*To be different from virtual function*/) { if (NewWidth != 0 && NewHeight != 0 && - (m_SwapChainDesc.Width != NewWidth || m_SwapChainDesc.Height != NewHeight)) + (m_SwapChainDesc.Width != NewWidth || + m_SwapChainDesc.Height != NewHeight || + m_DesiredPreTransform != NewPreTransform)) { m_SwapChainDesc.Width = NewWidth; m_SwapChainDesc.Height = NewHeight; + m_DesiredPreTransform = NewPreTransform; LOG_INFO_MESSAGE("Resizing the swap chain to ", m_SwapChainDesc.Width, "x", m_SwapChainDesc.Height); return true; } @@ -113,6 +117,9 @@ protected: /// Swap chain description SwapChainDesc m_SwapChainDesc; + + /// Desired surface pre-transformation. + SURFACE_TRANSFORM m_DesiredPreTransform = SURFACE_TRANSFORM_OPTIMAL; }; } // namespace Diligent diff --git a/Graphics/GraphicsEngine/interface/APIInfo.h b/Graphics/GraphicsEngine/interface/APIInfo.h index 93dec634..390ddeec 100644 --- a/Graphics/GraphicsEngine/interface/APIInfo.h +++ b/Graphics/GraphicsEngine/interface/APIInfo.h @@ -30,7 +30,7 @@ /// \file /// Diligent API information -#define DILIGENT_API_VERSION 240056 +#define DILIGENT_API_VERSION 240057 #include "../../../Primitives/interface/BasicTypes.h" diff --git a/Graphics/GraphicsEngine/interface/GraphicsTypes.h b/Graphics/GraphicsEngine/interface/GraphicsTypes.h index 77d613cd..ccaaeae2 100644 --- a/Graphics/GraphicsEngine/interface/GraphicsTypes.h +++ b/Graphics/GraphicsEngine/interface/GraphicsTypes.h @@ -1223,6 +1223,39 @@ DILIGENT_TYPED_ENUM(SWAP_CHAIN_USAGE_FLAGS, Uint32) }; DEFINE_FLAG_ENUM_OPERATORS(SWAP_CHAIN_USAGE_FLAGS) + +/// The transform applied to the image content prior to presentation. +DILIGENT_TYPED_ENUM(SURFACE_TRANSFORM, Uint32) +{ + /// Uset the most optimal surface transform. + SURFACE_TRANSFORM_OPTIMAL = 0, + + /// The image content is presented without being transformed. + SURFACE_TRANSFORM_IDENTITY, + + /// The image content is rotated 90 degrees clockwise. + SURFACE_TRANSFORM_ROTATE_90, + + /// The image content is rotated 180 degrees clockwise. + SURFACE_TRANSFORM_ROTATE_180, + + /// The image content is rotated 270 degrees clockwise. + SURFACE_TRANSFORM_ROTATE_270, + + /// The image content is mirrored horizontally. + SURFACE_TRANSFORM_HORIZONTAL_MIRROR, + + /// The image content is mirrored horizontally, then rotated 90 degrees clockwise. + SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90, + + /// The image content is mirrored horizontally, then rotated 180 degrees clockwise. + SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180, + + /// The image content is mirrored horizontally, then rotated 270 degrees clockwise. + SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270 +}; + + /// Swap chain description struct SwapChainDesc { @@ -1242,6 +1275,19 @@ struct SwapChainDesc /// Swap chain usage flags. Default value is Diligent::SWAP_CHAIN_USAGE_RENDER_TARGET SWAP_CHAIN_USAGE_FLAGS Usage DEFAULT_INITIALIZER(SWAP_CHAIN_USAGE_RENDER_TARGET); + /// The transform, relative to the presentation engine's natural orientation, + /// applied to the image content prior to presentation. + /// + /// \note When default value (SURFACE_TRANSFORM_OPTIMAL) is used, the engine will + /// select the most optimal surface transformation. An application may request + /// specific transform (e.g. SURFACE_TRANSFORM_IDENTITY) and the engine will + /// try to use that. However, if the transform is not available, the engine will + /// select the most optimal transform. + /// After the swap chain has been created, this member will contain the actual + /// transform selected by the engine and can be queried through ISwapChain::GetDesc() + /// method. + SURFACE_TRANSFORM PreTransform DEFAULT_INITIALIZER(SURFACE_TRANSFORM_OPTIMAL); + /// Number of buffers int the swap chain Uint32 BufferCount DEFAULT_INITIALIZER(2); diff --git a/Graphics/GraphicsEngine/interface/SwapChain.h b/Graphics/GraphicsEngine/interface/SwapChain.h index 2bbefca8..bda7c9f5 100644 --- a/Graphics/GraphicsEngine/interface/SwapChain.h +++ b/Graphics/GraphicsEngine/interface/SwapChain.h @@ -64,14 +64,16 @@ DILIGENT_BEGIN_INTERFACE(ISwapChain, IObject) /// Changes the swap chain's back buffer size - /// \param [in] NewWidth - New swap chain width, in pixels - /// \param [in] NewHeight - New swap chain height, in pixels + /// \param [in] NewWidth - New swap chain width, in pixels. + /// \param [in] NewHeight - New swap chain height, in pixels. + /// \param [in] NewTransform - New surface transform, see Diligent::SURFACE_TRANSFORM. /// /// \note When resizing non-primary swap chains, the engine unbinds the /// swap chain buffers from the output. VIRTUAL void METHOD(Resize)(THIS_ - Uint32 NewWidth, - Uint32 NewHeight) PURE; + Uint32 NewWidth, + Uint32 NewHeight, + SURFACE_TRANSFORM NewTransform DEFAULT_VALUE(SURFACE_TRANSFORM_OPTIMAL)) PURE; /// Sets fullscreen mode (only supported on Win32 platform) VIRTUAL void METHOD(SetFullscreenMode)(THIS_ const DisplayModeAttribs REF DisplayMode) PURE; diff --git a/Graphics/GraphicsEngineD3D11/include/SwapChainD3D11Impl.hpp b/Graphics/GraphicsEngineD3D11/include/SwapChainD3D11Impl.hpp index fbc3fd01..2e6efb6a 100644 --- a/Graphics/GraphicsEngineD3D11/include/SwapChainD3D11Impl.hpp +++ b/Graphics/GraphicsEngineD3D11/include/SwapChainD3D11Impl.hpp @@ -56,7 +56,7 @@ public: virtual void DILIGENT_CALL_TYPE Present(Uint32 SyncInterval) override final; /// Implementation of ISwapChain::Resize() in Direct3D11 backend. - virtual void DILIGENT_CALL_TYPE Resize(Uint32 NewWidth, Uint32 NewHeight) override final; + virtual void DILIGENT_CALL_TYPE Resize(Uint32 NewWidth, Uint32 NewHeight, SURFACE_TRANSFORM NewPreTransform) override final; /// Implementation of ISwapChainD3D11::GetDXGISwapChain() in Direct3D11 backend. virtual IDXGISwapChain* DILIGENT_CALL_TYPE GetDXGISwapChain() override final { return m_pSwapChain; } diff --git a/Graphics/GraphicsEngineD3D11/src/SwapChainD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/SwapChainD3D11Impl.cpp index 0d833427..d65df7f3 100644 --- a/Graphics/GraphicsEngineD3D11/src/SwapChainD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/SwapChainD3D11Impl.cpp @@ -210,9 +210,9 @@ void SwapChainD3D11Impl::UpdateSwapChain(bool CreateNew) } } -void SwapChainD3D11Impl::Resize(Uint32 NewWidth, Uint32 NewHeight) +void SwapChainD3D11Impl::Resize(Uint32 NewWidth, Uint32 NewHeight, SURFACE_TRANSFORM NewPreTransform) { - if (TSwapChainBase::Resize(NewWidth, NewHeight)) + if (TSwapChainBase::Resize(NewWidth, NewHeight, NewPreTransform)) { UpdateSwapChain(false); } diff --git a/Graphics/GraphicsEngineD3D12/include/SwapChainD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/SwapChainD3D12Impl.hpp index 2f32c6d7..7a0c78db 100644 --- a/Graphics/GraphicsEngineD3D12/include/SwapChainD3D12Impl.hpp +++ b/Graphics/GraphicsEngineD3D12/include/SwapChainD3D12Impl.hpp @@ -57,7 +57,7 @@ public: virtual void DILIGENT_CALL_TYPE Present(Uint32 SyncInterval) override final; /// Implementation of ISwapChain::Resize() in Direct3D12 backend. - virtual void DILIGENT_CALL_TYPE Resize(Uint32 NewWidth, Uint32 NewHeight) override final; + virtual void DILIGENT_CALL_TYPE Resize(Uint32 NewWidth, Uint32 NewHeight, SURFACE_TRANSFORM NewPreTransform) override final; /// Implementation of ISwapChainD3D12::GetDXGISwapChain(). virtual IDXGISwapChain* DILIGENT_CALL_TYPE GetDXGISwapChain() override final { return m_pSwapChain; } diff --git a/Graphics/GraphicsEngineD3D12/src/SwapChainD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/SwapChainD3D12Impl.cpp index 1703f4e9..301f8a1b 100644 --- a/Graphics/GraphicsEngineD3D12/src/SwapChainD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/SwapChainD3D12Impl.cpp @@ -231,9 +231,9 @@ void SwapChainD3D12Impl::UpdateSwapChain(bool CreateNew) } } -void SwapChainD3D12Impl::Resize(Uint32 NewWidth, Uint32 NewHeight) +void SwapChainD3D12Impl::Resize(Uint32 NewWidth, Uint32 NewHeight, SURFACE_TRANSFORM NewPreTransform) { - if (TSwapChainBase::Resize(NewWidth, NewHeight)) + if (TSwapChainBase::Resize(NewWidth, NewHeight, NewPreTransform)) { UpdateSwapChain(false); } diff --git a/Graphics/GraphicsEngineD3DBase/include/SwapChainD3DBase.hpp b/Graphics/GraphicsEngineD3DBase/include/SwapChainD3DBase.hpp index 18cb8bf0..d2b9387c 100644 --- a/Graphics/GraphicsEngineD3DBase/include/SwapChainD3DBase.hpp +++ b/Graphics/GraphicsEngineD3DBase/include/SwapChainD3DBase.hpp @@ -53,7 +53,17 @@ public: m_FSDesc {FSDesc}, m_Window {Window} // clang-format on - {} + { + if (m_DesiredPreTransform != SURFACE_TRANSFORM_OPTIMAL && + m_DesiredPreTransform != SURFACE_TRANSFORM_IDENTITY) + { + LOG_WARNING_MESSAGE(GetSurfaceTransformString(m_DesiredPreTransform), + " is not an allowed pretransform because Direct3D swap chains only support identity transform. " + "Use SURFACE_TRANSFORM_OPTIMAL (recommended) or SURFACE_TRANSFORM_IDENTITY."); + } + m_DesiredPreTransform = SURFACE_TRANSFORM_OPTIMAL; + m_SwapChainDesc.PreTransform = SURFACE_TRANSFORM_IDENTITY; + } ~SwapChainD3DBase() { @@ -71,6 +81,20 @@ public: protected: virtual void UpdateSwapChain(bool CreateNew) = 0; + bool Resize(Uint32 NewWidth, Uint32 NewHeight, SURFACE_TRANSFORM NewPreTransform, Int32 Dummy = 0 /*To be different from virtual function*/) + { + if (NewPreTransform != SURFACE_TRANSFORM_OPTIMAL && + NewPreTransform != SURFACE_TRANSFORM_IDENTITY) + { + LOG_WARNING_MESSAGE(GetSurfaceTransformString(NewPreTransform), + " is not an allowed pretransform because Direct3D swap chains only support identity transform. " + "Use SURFACE_TRANSFORM_OPTIMAL (recommended) or SURFACE_TRANSFORM_IDENTITY."); + } + NewPreTransform = SURFACE_TRANSFORM_OPTIMAL; + + return TBase::Resize(NewWidth, NewHeight, NewPreTransform); + } + void CreateDXGISwapChain(IUnknown* pD3D11DeviceOrD3D12CmdQueue) { #if PLATFORM_WIN32 @@ -92,6 +116,11 @@ protected: } #endif + VERIFY(m_DesiredPreTransform == SURFACE_TRANSFORM_OPTIMAL || m_DesiredPreTransform == SURFACE_TRANSFORM_IDENTITY, + "Direct3D swap chains only support identity transform."); + m_DesiredPreTransform = SURFACE_TRANSFORM_OPTIMAL; + m_SwapChainDesc.PreTransform = SURFACE_TRANSFORM_IDENTITY; + auto DXGIColorBuffFmt = TexFormatToDXGI_Format(m_SwapChainDesc.ColorBufferFormat); DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; diff --git a/Graphics/GraphicsEngineMetal/include/SwapChainMtlImpl.h b/Graphics/GraphicsEngineMetal/include/SwapChainMtlImpl.h index a868dd32..0cadd44b 100644 --- a/Graphics/GraphicsEngineMetal/include/SwapChainMtlImpl.h +++ b/Graphics/GraphicsEngineMetal/include/SwapChainMtlImpl.h @@ -48,7 +48,7 @@ public: virtual void QueryInterface(const Diligent::INTERFACE_ID& IID, IObject** ppInterface) override final; virtual void Present(Uint32 SyncInterval) override final; - virtual void Resize(Uint32 NewWidth, Uint32 NewHeight) override final; + virtual void Resize(Uint32 NewWidth, Uint32 NewHeight, SURFACE_TRANSFORM NewPreTransform) override final; virtual void SetFullscreenMode(const DisplayModeAttribs& DisplayMode) override final; diff --git a/Graphics/GraphicsEngineMetal/src/SwapChainMtlImpl.mm b/Graphics/GraphicsEngineMetal/src/SwapChainMtlImpl.mm index 87ba6a6b..7532f5cd 100644 --- a/Graphics/GraphicsEngineMetal/src/SwapChainMtlImpl.mm +++ b/Graphics/GraphicsEngineMetal/src/SwapChainMtlImpl.mm @@ -50,9 +50,9 @@ void SwapChainMtlImpl::Present(Uint32 SyncInterval) } -void SwapChainMtlImpl::Resize( Uint32 NewWidth, Uint32 NewHeight ) +void SwapChainMtlImpl::Resize( Uint32 NewWidth, Uint32 NewHeight, SURFACE_TRANSFORM NewPreTransform ) { - if( TSwapChainBase::Resize(NewWidth, NewHeight) ) + if( TSwapChainBase::Resize(NewWidth, NewHeight, NewPreTransform) ) { LOG_ERROR_MESSAGE("SwapChainMtlImpl::Resize() is not implemented"); } diff --git a/Graphics/GraphicsEngineOpenGL/include/SwapChainGLBase.hpp b/Graphics/GraphicsEngineOpenGL/include/SwapChainGLBase.hpp index 3fbd81e7..426d30ab 100644 --- a/Graphics/GraphicsEngineOpenGL/include/SwapChainGLBase.hpp +++ b/Graphics/GraphicsEngineOpenGL/include/SwapChainGLBase.hpp @@ -55,9 +55,18 @@ public: virtual ITextureView* DILIGENT_CALL_TYPE GetDepthBufferDSV() override final { return m_pDepthStencilView; } protected: - bool Resize(Uint32 NewWidth, Uint32 NewHeight, Int32 /*To be different from virtual function*/) + bool Resize(Uint32 NewWidth, Uint32 NewHeight, SURFACE_TRANSFORM NewPreTransform, Int32 /*To be different from virtual function*/) { - if (TSwapChainBase::Resize(NewWidth, NewHeight, 0)) + if (NewPreTransform != SURFACE_TRANSFORM_OPTIMAL && + NewPreTransform != SURFACE_TRANSFORM_IDENTITY) + { + LOG_WARNING_MESSAGE(GetSurfaceTransformString(NewPreTransform), + " is not an allowed pretransform because OpenGL swap chains only support identity transform. " + "Use SURFACE_TRANSFORM_OPTIMAL (recommended) or SURFACE_TRANSFORM_IDENTITY."); + } + NewPreTransform = SURFACE_TRANSFORM_OPTIMAL; + + if (TSwapChainBase::Resize(NewWidth, NewHeight, NewPreTransform)) { if (m_pRenderTargetView) { diff --git a/Graphics/GraphicsEngineOpenGL/include/SwapChainGLImpl.hpp b/Graphics/GraphicsEngineOpenGL/include/SwapChainGLImpl.hpp index f68079eb..8029df2f 100644 --- a/Graphics/GraphicsEngineOpenGL/include/SwapChainGLImpl.hpp +++ b/Graphics/GraphicsEngineOpenGL/include/SwapChainGLImpl.hpp @@ -53,7 +53,7 @@ public: virtual void DILIGENT_CALL_TYPE Present(Uint32 SyncInterval) override final; /// Implementation of ISwapChain::Resize() in OpenGL backend. - virtual void DILIGENT_CALL_TYPE Resize(Uint32 NewWidth, Uint32 NewHeight) override final; + virtual void DILIGENT_CALL_TYPE Resize(Uint32 NewWidth, Uint32 NewHeight, SURFACE_TRANSFORM NewPreTransform) override final; /// Implementation of ISwapChain::SetFullscreenMode() in OpenGL backend. virtual void DILIGENT_CALL_TYPE SetFullscreenMode(const DisplayModeAttribs& DisplayMode) override final; diff --git a/Graphics/GraphicsEngineOpenGL/src/SwapChainGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/SwapChainGLImpl.cpp index a9af9b5d..3b6ebe8e 100644 --- a/Graphics/GraphicsEngineOpenGL/src/SwapChainGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/SwapChainGLImpl.cpp @@ -29,6 +29,7 @@ #include "DeviceContextGLImpl.hpp" #include "RenderDeviceGLImpl.hpp" #include "SwapChainGLImpl.hpp" +#include "GraphicsAccessories.hpp" namespace Diligent { @@ -47,6 +48,16 @@ SwapChainGLImpl::SwapChainGLImpl(IReferenceCounters* pRefCounters, } // clang-format on { + if (m_DesiredPreTransform != SURFACE_TRANSFORM_OPTIMAL && + m_DesiredPreTransform != SURFACE_TRANSFORM_IDENTITY) + { + LOG_WARNING_MESSAGE(GetSurfaceTransformString(m_DesiredPreTransform), + " is not an allowed pretransform because OpenGL swap chains only support identity transform. " + "Use SURFACE_TRANSFORM_OPTIMAL (recommended) or SURFACE_TRANSFORM_IDENTITY."); + } + m_DesiredPreTransform = SURFACE_TRANSFORM_OPTIMAL; + m_SwapChainDesc.PreTransform = SURFACE_TRANSFORM_IDENTITY; + #if PLATFORM_WIN32 HWND hWnd = reinterpret_cast<HWND>(InitAttribs.Window.hWnd); RECT rc; @@ -104,7 +115,7 @@ void SwapChainGLImpl::Present(Uint32 SyncInterval) } } -void SwapChainGLImpl::Resize(Uint32 NewWidth, Uint32 NewHeight) +void SwapChainGLImpl::Resize(Uint32 NewWidth, Uint32 NewHeight, SURFACE_TRANSFORM NewPreTransform) { #if PLATFORM_ANDROID auto* pDeviceGL = m_pRenderDevice.RawPtr<RenderDeviceGLImpl>(); @@ -114,7 +125,7 @@ void SwapChainGLImpl::Resize(Uint32 NewWidth, Uint32 NewHeight) NewHeight = GLContext.GetScreenHeight(); #endif - TSwapChainGLBase::Resize(NewWidth, NewHeight, 0); + TSwapChainGLBase::Resize(NewWidth, NewHeight, NewPreTransform, 0); } void SwapChainGLImpl::SetFullscreenMode(const DisplayModeAttribs& DisplayMode) diff --git a/Graphics/GraphicsEngineVulkan/include/SwapChainVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/SwapChainVkImpl.hpp index 289dbe55..6bfc15ea 100644 --- a/Graphics/GraphicsEngineVulkan/include/SwapChainVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/SwapChainVkImpl.hpp @@ -58,7 +58,7 @@ public: virtual void DILIGENT_CALL_TYPE Present(Uint32 SyncInterval) override final; /// Implementation of ISwapChain::Resize() in Vulkan backend. - virtual void DILIGENT_CALL_TYPE Resize(Uint32 NewWidth, Uint32 NewHeight) override final; + virtual void DILIGENT_CALL_TYPE Resize(Uint32 NewWidth, Uint32 NewHeight, SURFACE_TRANSFORM NewPreTransform) override final; /// Implementation of ISwapChain::SetFullscreenMode() in Vulkan backend. virtual void DILIGENT_CALL_TYPE SetFullscreenMode(const DisplayModeAttribs& DisplayMode) override final; @@ -92,6 +92,13 @@ private: VkSwapchainKHR m_VkSwapChain = VK_NULL_HANDLE; VkFormat m_VkColorFormat = VK_FORMAT_UNDEFINED; +#if PLATFORM_ANDROID + // Surface extent corresponding to identity transform. We have to store this value, + // because on Android vkGetPhysicalDeviceSurfaceCapabilitiesKHR is not reliable and + // starts reporting incorrect dimensions after few rotations. + VkExtent2D m_SurfaceIdentityExtent = {}; +#endif + std::vector<RefCntAutoPtr<ManagedSemaphore>> m_ImageAcquiredSemaphores; std::vector<RefCntAutoPtr<ManagedSemaphore>> m_DrawCompleteSemaphores; std::vector<VulkanUtilities::FenceWrapper> m_ImageAcquiredFences; diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanTypeConversions.hpp b/Graphics/GraphicsEngineVulkan/include/VulkanTypeConversions.hpp index 1f752700..15420ead 100644 --- a/Graphics/GraphicsEngineVulkan/include/VulkanTypeConversions.hpp +++ b/Graphics/GraphicsEngineVulkan/include/VulkanTypeConversions.hpp @@ -32,6 +32,7 @@ #include <array> #include "GraphicsTypes.h" +#include "InputLayout.h" namespace Diligent { @@ -41,14 +42,14 @@ TEXTURE_FORMAT VkFormatToTexFormat(VkFormat VkFmt); VkFormat TypeToVkFormat(VALUE_TYPE ValType, Uint32 NumComponents, Bool bIsNormalized); -VkPipelineRasterizationStateCreateInfo RasterizerStateDesc_To_VkRasterizationStateCI(const RasterizerStateDesc& RasterizerDesc); -VkPipelineDepthStencilStateCreateInfo DepthStencilStateDesc_To_VkDepthStencilStateCI(const DepthStencilStateDesc& DepthStencilDesc); +VkPipelineRasterizationStateCreateInfo RasterizerStateDesc_To_VkRasterizationStateCI(const struct RasterizerStateDesc& RasterizerDesc); +VkPipelineDepthStencilStateCreateInfo DepthStencilStateDesc_To_VkDepthStencilStateCI(const struct DepthStencilStateDesc& DepthStencilDesc); -void BlendStateDesc_To_VkBlendStateCI(const BlendStateDesc& BSDesc, +void BlendStateDesc_To_VkBlendStateCI(const struct BlendStateDesc& BSDesc, VkPipelineColorBlendStateCreateInfo& ColorBlendStateCI, std::vector<VkPipelineColorBlendAttachmentState>& ColorBlendAttachments); -void InputLayoutDesc_To_VkVertexInputStateCI(const InputLayoutDesc& LayoutDesc, +void InputLayoutDesc_To_VkVertexInputStateCI(const struct InputLayoutDesc& LayoutDesc, VkPipelineVertexInputStateCreateInfo& VertexInputStateCI, std::array<VkVertexInputBindingDescription, MAX_LAYOUT_ELEMENTS>& BindingDescriptions, std::array<VkVertexInputAttributeDescription, MAX_LAYOUT_ELEMENTS>& AttributeDescription); @@ -69,4 +70,7 @@ VkImageLayout ResourceStateToVkImageLayout(RESOURCE_STATE StateFlag); RESOURCE_STATE VkAccessFlagsToResourceStates(VkAccessFlags AccessFlags); RESOURCE_STATE VkImageLayoutToResourceState(VkImageLayout Layout); +SURFACE_TRANSFORM VkSurfaceTransformFlagToSurfaceTransform(VkSurfaceTransformFlagBitsKHR vkTransformFlag); +VkSurfaceTransformFlagBitsKHR SurfaceTransformToVkSurfaceTransformFlag(SURFACE_TRANSFORM SrfTransform); + } // namespace Diligent diff --git a/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp index da2f9b98..69c8d5cc 100644 --- a/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp @@ -207,6 +207,35 @@ void SwapChainVkImpl::CreateVulkanSwapChain() CHECK_VK_ERROR_AND_THROW(err, "Failed to query surface present modes"); VERIFY_EXPR(presentModeCount == presentModes.size()); + + VkSurfaceTransformFlagBitsKHR vkPreTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; + if (m_DesiredPreTransform != SURFACE_TRANSFORM_OPTIMAL) + { + vkPreTransform = SurfaceTransformToVkSurfaceTransformFlag(m_DesiredPreTransform); + if ((surfCapabilities.supportedTransforms & vkPreTransform) != 0) + { + m_SwapChainDesc.PreTransform = m_DesiredPreTransform; + } + else + { + LOG_WARNING_MESSAGE(GetSurfaceTransformString(m_DesiredPreTransform), + " is not supported by the presentation engine. Optimal surface transform will be used instead." + " Query the swap chain description to get the actual surface transform."); + m_DesiredPreTransform = SURFACE_TRANSFORM_OPTIMAL; + } + } + + if (m_DesiredPreTransform == SURFACE_TRANSFORM_OPTIMAL) + { + // Use current surface transform to avoid extra cost of presenting the image. + // If preTransform does not match the currentTransform value returned by vkGetPhysicalDeviceSurfaceCapabilitiesKHR, + // the presentation engine will transform the image content as part of the presentation operation. + // https://android-developers.googleblog.com/2020/02/handling-device-orientation-efficiently.html + // https://community.arm.com/developer/tools-software/graphics/b/blog/posts/appropriate-use-of-surface-rotation + vkPreTransform = surfCapabilities.currentTransform; + m_SwapChainDesc.PreTransform = VkSurfaceTransformFlagToSurfaceTransform(vkPreTransform); + } + VkExtent2D swapchainExtent = {}; // width and height are either both 0xFFFFFFFF, or both not 0xFFFFFFFF. if (surfCapabilities.currentExtent.width == 0xFFFFFFFF && m_SwapChainDesc.Width != 0 && m_SwapChainDesc.Height != 0) @@ -221,6 +250,30 @@ void SwapChainVkImpl::CreateVulkanSwapChain() // If the surface size is defined, the swap chain size must match swapchainExtent = surfCapabilities.currentExtent; } + +#if PLATFORM_ANDROID + // On Android, vkGetPhysicalDeviceSurfaceCapabilitiesKHR is not reliable and starts reporting incorrect + // dimensions after few rotations. To alleviate the problem, we store the surface extent corresponding to + // identity rotation. + // https://android-developers.googleblog.com/2020/02/handling-device-orientation-efficiently.html + if (m_SurfaceIdentityExtent.width == 0 || m_SurfaceIdentityExtent.height == 0) + { + m_SurfaceIdentityExtent = surfCapabilities.currentExtent; + constexpr auto Rotate90TransformFlags = + VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR | + VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR | + VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR | + VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR; + if ((surfCapabilities.currentTransform & Rotate90TransformFlags) != 0) + std::swap(m_SurfaceIdentityExtent.width, m_SurfaceIdentityExtent.height); + } + + if (m_DesiredPreTransform == SURFACE_TRANSFORM_OPTIMAL) + { + swapchainExtent = m_SurfaceIdentityExtent; + } +#endif + swapchainExtent.width = std::max(swapchainExtent.width, 1u); swapchainExtent.height = std::max(swapchainExtent.height, 1u); m_SwapChainDesc.Width = swapchainExtent.width; @@ -273,11 +326,6 @@ void SwapChainVkImpl::CreateVulkanSwapChain() } uint32_t desiredNumberOfSwapChainImages = m_SwapChainDesc.BufferCount; - VkSurfaceTransformFlagBitsKHR preTransform = - (surfCapabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) ? - VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR : - surfCapabilities.currentTransform; - // Find a supported composite alpha mode - one of these is guaranteed to be set VkCompositeAlphaFlagBitsKHR compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; VkCompositeAlphaFlagBitsKHR compositeAlphaFlags[4] = // @@ -308,7 +356,7 @@ void SwapChainVkImpl::CreateVulkanSwapChain() swapchain_ci.imageFormat = m_VkColorFormat; swapchain_ci.imageExtent.width = swapchainExtent.width; swapchain_ci.imageExtent.height = swapchainExtent.height; - swapchain_ci.preTransform = preTransform; + swapchain_ci.preTransform = vkPreTransform; swapchain_ci.compositeAlpha = compositeAlpha; swapchain_ci.imageArrayLayers = 1; swapchain_ci.presentMode = swapchainPresentMode; @@ -705,9 +753,9 @@ void SwapChainVkImpl::RecreateVulkanSwapchain(DeviceContextVkImpl* pImmediateCtx InitBuffersAndViews(); } -void SwapChainVkImpl::Resize(Uint32 NewWidth, Uint32 NewHeight) +void SwapChainVkImpl::Resize(Uint32 NewWidth, Uint32 NewHeight, SURFACE_TRANSFORM NewPreTransform) { - if (TSwapChainBase::Resize(NewWidth, NewHeight)) + if (TSwapChainBase::Resize(NewWidth, NewHeight, NewPreTransform)) { auto pDeviceContext = m_wpDeviceContext.Lock(); VERIFY(pDeviceContext, "Immediate context has been released"); diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp index 26a2fcf5..d5e4f48b 100644 --- a/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp +++ b/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp @@ -31,6 +31,7 @@ #include "VulkanTypeConversions.hpp" #include "PlatformMisc.hpp" +#include "Align.hpp" namespace Diligent { @@ -1372,4 +1373,52 @@ RESOURCE_STATE VkImageLayoutToResourceState(VkImageLayout Layout) } } +SURFACE_TRANSFORM VkSurfaceTransformFlagToSurfaceTransform(VkSurfaceTransformFlagBitsKHR vkTransformFlag) +{ + VERIFY(IsPowerOfTwo(static_cast<Uint32>(vkTransformFlag)), "Only single transform bit is expected"); + + // clang-format off + switch (vkTransformFlag) + { + case VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR: return SURFACE_TRANSFORM_IDENTITY; + case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR: return SURFACE_TRANSFORM_ROTATE_90; + case VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR: return SURFACE_TRANSFORM_ROTATE_180; + case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR: return SURFACE_TRANSFORM_ROTATE_270; + case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR: return SURFACE_TRANSFORM_HORIZONTAL_MIRROR; + case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR: return SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90; + case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR: return SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180; + case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR: return SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270; + + default: + UNEXPECTED("Unexpected surface transform"); + return SURFACE_TRANSFORM_IDENTITY; + } + // clang-format on +} + +VkSurfaceTransformFlagBitsKHR SurfaceTransformToVkSurfaceTransformFlag(SURFACE_TRANSFORM SrfTransform) +{ + // clang-format off + switch (SrfTransform) + { + case SURFACE_TRANSFORM_OPTIMAL: + UNEXPECTED("Optimal transform does not have corresponding Vulkan flag"); + return VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; + + case SURFACE_TRANSFORM_IDENTITY: return VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; + case SURFACE_TRANSFORM_ROTATE_90: return VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR; + case SURFACE_TRANSFORM_ROTATE_180: return VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR; + case SURFACE_TRANSFORM_ROTATE_270: return VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR; + case SURFACE_TRANSFORM_HORIZONTAL_MIRROR: return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR; + case SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90: return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR; + case SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180: return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR; + case SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270: return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR; + + default: + UNEXPECTED("Unexpected surface transform"); + return VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; + } + // clang-format on +} + } // namespace Diligent |
