Renderer: Expose present mode and allow to query/set it

This commit is contained in:
SirLynix
2023-08-13 18:16:03 +02:00
parent 28d69ab552
commit e8620894f7
21 changed files with 420 additions and 43 deletions

View File

@@ -6,7 +6,6 @@
#include <Nazara/OpenGLRenderer/OpenGLCommandPool.hpp>
#include <Nazara/OpenGLRenderer/OpenGLRenderer.hpp>
#include <Nazara/Renderer/CommandPool.hpp>
#include <Nazara/Renderer/WindowSwapchain.hpp>
#include <Nazara/OpenGLRenderer/Debug.hpp>
namespace Nz
@@ -54,6 +53,23 @@ namespace Nz
else
depthFormat = PixelFormat::Undefined;
m_supportedPresentModes = m_context->GetSupportedPresentModes();
#ifdef NAZARA_PLATFORM_WEB
m_presentMode = PresentMode::Immediate; //< default present mode
#else
m_presentMode = PresentMode::VerticalSync; //< default present mode
#endif
for (PresentMode presentMode : parameters.presentMode)
{
if (m_supportedPresentModes & presentMode)
{
SetPresentMode(presentMode);
break;
}
}
std::vector<RenderPass::Attachment> attachments;
std::vector<RenderPass::SubpassDescription> subpassDescriptions;
std::vector<RenderPass::SubpassDependency> subpassDependencies;
@@ -78,7 +94,7 @@ namespace Nz
std::shared_ptr<CommandPool> OpenGLSwapchain::CreateCommandPool(QueueType /*queueType*/)
{
return std::make_unique<OpenGLCommandPool>();
return std::make_shared<OpenGLCommandPool>();
}
const OpenGLFramebuffer& OpenGLSwapchain::GetFramebuffer(std::size_t i) const
@@ -98,11 +114,21 @@ namespace Nz
return *m_renderPass;
}
PresentMode OpenGLSwapchain::GetPresentMode() const
{
return m_presentMode;
}
const Vector2ui& OpenGLSwapchain::GetSize() const
{
return m_size;
}
PresentModeFlags OpenGLSwapchain::GetSupportedPresentModes() const
{
return m_supportedPresentModes;
}
void OpenGLSwapchain::NotifyResize(const Vector2ui& newSize)
{
OnRenderTargetSizeChange(this, newSize);
@@ -117,6 +143,17 @@ namespace Nz
m_currentFrame = (m_currentFrame + 1) % m_renderImage.size();
}
void OpenGLSwapchain::SetPresentMode(PresentMode presentMode)
{
NazaraAssert(m_supportedPresentModes & presentMode, "unsupported present mode");
if (m_presentMode != presentMode)
{
m_context->SetPresentMode(presentMode);
m_presentMode = presentMode;
}
}
TransientResources& OpenGLSwapchain::Transient()
{
return *m_renderImage[m_currentFrame];

View File

@@ -670,8 +670,6 @@ namespace Nz::GL
m_state.renderStates.scissorTest = false;
m_state.renderStates.stencilTest = false;
EnableVerticalSync(false);
return true;
}

View File

@@ -87,9 +87,33 @@ namespace Nz::GL
}
}
void EGLContextBase::EnableVerticalSync(bool enabled)
PresentModeFlags EGLContextBase::GetSupportedPresentModes() const
{
// TODO
PresentModeFlags supportedModes;
if (m_maxSwapInterval >= 1)
supportedModes |= PresentMode::VerticalSync;
if (m_minSwapInterval <= 0)
supportedModes |= PresentMode::Immediate;
if (m_minSwapInterval <= -1)
supportedModes |= PresentMode::RelaxedVerticalSync;
return supportedModes;
}
void EGLContextBase::SetPresentMode(PresentMode presentMode)
{
int interval = 0;
switch (presentMode)
{
case PresentMode::Immediate: interval = 0; break;
case PresentMode::RelaxedVerticalSync: interval = -1; break;
case PresentMode::VerticalSync: interval = 1; break;
default: return; // TODO: Unreachable
}
m_loader.eglSwapInterval(m_display, interval);
}
void EGLContextBase::SwapBuffers()
@@ -247,6 +271,9 @@ namespace Nz::GL
return false;
}
m_loader.eglGetConfigAttrib(m_display, config, EGL_MAX_SWAP_INTERVAL, &m_maxSwapInterval);
m_loader.eglGetConfigAttrib(m_display, config, EGL_MIN_SWAP_INTERVAL, &m_minSwapInterval);
LoadEGLExt();
return true;

View File

@@ -73,15 +73,34 @@ namespace Nz::GL
}
}
void WGLContext::EnableVerticalSync(bool enabled)
PresentModeFlags WGLContext::GetSupportedPresentModes() const
{
PresentModeFlags supportedModes = PresentMode::Immediate;
if (wglSwapIntervalEXT)
{
if (!SetCurrentContext(this))
return;
wglSwapIntervalEXT(enabled);
supportedModes |= PresentMode::VerticalSync;
if (HasPlatformExtension("WGL_EXT_swap_control_tear"))
supportedModes |= PresentMode::RelaxedVerticalSync;
}
return supportedModes;
}
void WGLContext::SetPresentMode(PresentMode presentMode)
{
if (!SetCurrentContext(this))
return;
int interval = 0;
switch (presentMode)
{
case PresentMode::Immediate: interval = 0; break;
case PresentMode::RelaxedVerticalSync: interval = -1; break; //< WGL_EXT_swap_control_tear
case PresentMode::VerticalSync: interval = 1; break;
default: return; // TODO: Unreachable
}
wglSwapIntervalEXT(interval);
}
void WGLContext::SwapBuffers()

View File

@@ -64,9 +64,15 @@ namespace Nz::GL
}
}
void WebContext::EnableVerticalSync(bool /*enabled*/)
PresentModeFlags WebContext::GetSupportedPresentModes() const
{
// TODO
// WebGL does not support disabling V-Sync
return PresentMode::VerticalSync;
}
void WebContext::SetPresentMode(PresentMode /*presentMode*/)
{
// Nothing to do
}
void WebContext::SwapBuffers()

View File

@@ -151,6 +151,27 @@ namespace Nz
throw std::runtime_error("failed to find a support depth-stencil format");
}
std::vector<VkPresentModeKHR> presentModes;
if (!m_surface.GetPresentModes(physDeviceInfo.physDevice, &presentModes))
throw std::runtime_error("failed to query supported present modes");
m_supportedPresentModes.Clear();
for (VkPresentModeKHR vkPresentMode : presentModes)
{
if (auto presentModeOpt = FromVulkan(vkPresentMode))
m_supportedPresentModes |= *presentModeOpt;
}
m_presentMode = PresentMode::VerticalSync; //< guaranteed to be supported
for (PresentMode presentMode : parameters.presentMode)
{
if (m_supportedPresentModes & presentMode)
{
m_presentMode = presentMode;
break;
}
}
if (!SetupRenderPass())
throw std::runtime_error("failed to create renderpass");
@@ -292,6 +313,16 @@ namespace Nz
return m_swapchainSize;
}
PresentMode VulkanSwapchain::GetPresentMode() const
{
return m_presentMode;
}
PresentModeFlags VulkanSwapchain::GetSupportedPresentModes() const
{
return m_supportedPresentModes;
}
void VulkanSwapchain::NotifyResize(const Vector2ui& newSize)
{
OnRenderTargetSizeChange(this, newSize);
@@ -332,6 +363,17 @@ namespace Nz
}
}
void VulkanSwapchain::SetPresentMode(PresentMode presentMode)
{
NazaraAssert(m_supportedPresentModes & presentMode, "unsupported present mode");
if (m_presentMode != presentMode)
{
m_presentMode = presentMode;
m_shouldRecreateSwapchain = true;
}
}
TransientResources& VulkanSwapchain::Transient()
{
return *m_concurrentImageData[m_currentFrame];
@@ -566,26 +608,6 @@ namespace Nz
else
extent = surfaceCapabilities.currentExtent;
std::vector<VkPresentModeKHR> presentModes;
if (!m_surface.GetPresentModes(deviceInfo.physDevice, &presentModes))
{
NazaraError("Failed to query supported present modes");
return false;
}
VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR;
for (VkPresentModeKHR presentMode : presentModes)
{
if (presentMode == VK_PRESENT_MODE_MAILBOX_KHR)
{
swapchainPresentMode = VK_PRESENT_MODE_MAILBOX_KHR;
break;
}
if (presentMode == VK_PRESENT_MODE_IMMEDIATE_KHR)
swapchainPresentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
}
VkCompositeAlphaFlagBitsKHR compositeAlpha;
if (surfaceCapabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR)
compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
@@ -610,7 +632,7 @@ namespace Nz
0, nullptr,
surfaceCapabilities.currentTransform,
compositeAlpha,
swapchainPresentMode,
ToVulkan(m_presentMode),
VK_TRUE,
m_swapchain
};