summaryrefslogtreecommitdiffstats
path: root/Graphics/GraphicsEngineVulkan
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/GraphicsEngineVulkan
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/GraphicsEngineVulkan')
-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
4 files changed, 121 insertions, 13 deletions
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