summaryrefslogtreecommitdiffstats
path: root/Graphics
diff options
context:
space:
mode:
authorassiduous <assiduous@diligentgraphics.com>2020-04-24 03:55:17 +0000
committerassiduous <assiduous@diligentgraphics.com>2020-04-24 03:55:17 +0000
commit5cc8a3953c7986bec781d7c1f8a014195ca4bf6b (patch)
treecd5426ebffc0af628236d45ed70e25969065cab5 /Graphics
parentMerge pull request #128 from Dinolek/master (diff)
downloadDiligentCore-5cc8a3953c7986bec781d7c1f8a014195ca4bf6b.tar.gz
DiligentCore-5cc8a3953c7986bec781d7c1f8a014195ca4bf6b.zip
Added surface pretransform parameter to swap chain desc (API 240057)
Diffstat (limited to 'Graphics')
-rw-r--r--Graphics/GraphicsAccessories/interface/GraphicsAccessories.hpp2
-rw-r--r--Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp26
-rw-r--r--Graphics/GraphicsEngine/include/SwapChainBase.hpp19
-rw-r--r--Graphics/GraphicsEngine/interface/APIInfo.h2
-rw-r--r--Graphics/GraphicsEngine/interface/GraphicsTypes.h46
-rw-r--r--Graphics/GraphicsEngine/interface/SwapChain.h10
-rw-r--r--Graphics/GraphicsEngineD3D11/include/SwapChainD3D11Impl.hpp2
-rw-r--r--Graphics/GraphicsEngineD3D11/src/SwapChainD3D11Impl.cpp4
-rw-r--r--Graphics/GraphicsEngineD3D12/include/SwapChainD3D12Impl.hpp2
-rw-r--r--Graphics/GraphicsEngineD3D12/src/SwapChainD3D12Impl.cpp4
-rw-r--r--Graphics/GraphicsEngineD3DBase/include/SwapChainD3DBase.hpp31
-rw-r--r--Graphics/GraphicsEngineMetal/include/SwapChainMtlImpl.h2
-rw-r--r--Graphics/GraphicsEngineMetal/src/SwapChainMtlImpl.mm4
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/SwapChainGLBase.hpp13
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/SwapChainGLImpl.hpp2
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/SwapChainGLImpl.cpp15
-rw-r--r--Graphics/GraphicsEngineVulkan/include/SwapChainVkImpl.hpp9
-rw-r--r--Graphics/GraphicsEngineVulkan/include/VulkanTypeConversions.hpp12
-rw-r--r--Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp64
-rw-r--r--Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp49
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