mirror of
https://github.com/AxioDL/boo.git
synced 2025-07-14 00:56:12 +00:00
Vulkan window resize fixes
This commit is contained in:
parent
bfd912b0a9
commit
3197142d1f
@ -10,6 +10,7 @@
|
|||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <queue>
|
||||||
#include "boo/graphicsdev/VulkanDispatchTable.hpp"
|
#include "boo/graphicsdev/VulkanDispatchTable.hpp"
|
||||||
|
|
||||||
namespace boo
|
namespace boo
|
||||||
@ -77,7 +78,26 @@ struct VulkanContext
|
|||||||
bool enumerateDevices();
|
bool enumerateDevices();
|
||||||
void initDevice();
|
void initDevice();
|
||||||
void initSwapChain(Window& windowCtx, VkSurfaceKHR surface, VkFormat format, VkColorSpaceKHR colorspace);
|
void initSwapChain(Window& windowCtx, VkSurfaceKHR surface, VkFormat format, VkColorSpaceKHR colorspace);
|
||||||
void resizeSwapChain(Window& windowCtx, VkSurfaceKHR surface, VkFormat format, VkColorSpaceKHR colorspace);
|
|
||||||
|
struct SwapChainResize
|
||||||
|
{
|
||||||
|
Window& m_windowCtx;
|
||||||
|
VkSurfaceKHR m_surface;
|
||||||
|
VkFormat m_format;
|
||||||
|
VkColorSpaceKHR m_colorspace;
|
||||||
|
SWindowRect m_rect;
|
||||||
|
SwapChainResize(Window& windowCtx, VkSurfaceKHR surface,
|
||||||
|
VkFormat format, VkColorSpaceKHR colorspace,
|
||||||
|
const SWindowRect& rect)
|
||||||
|
: m_windowCtx(windowCtx), m_surface(surface),
|
||||||
|
m_format(format), m_colorspace(colorspace), m_rect(rect) {}
|
||||||
|
};
|
||||||
|
std::queue<SwapChainResize> m_deferredResizes;
|
||||||
|
std::mutex m_resizeLock;
|
||||||
|
void resizeSwapChain(Window& windowCtx, VkSurfaceKHR surface,
|
||||||
|
VkFormat format, VkColorSpaceKHR colorspace,
|
||||||
|
const SWindowRect& rect);
|
||||||
|
bool _resizeSwapChains();
|
||||||
};
|
};
|
||||||
extern VulkanContext g_VulkanContext;
|
extern VulkanContext g_VulkanContext;
|
||||||
|
|
||||||
|
@ -544,17 +544,32 @@ void VulkanContext::initSwapChain(VulkanContext::Window& windowCtx, VkSurfaceKHR
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VulkanContext::resizeSwapChain(VulkanContext::Window& windowCtx, VkSurfaceKHR surface,
|
||||||
void VulkanContext::resizeSwapChain(VulkanContext::Window& windowCtx, VkSurfaceKHR surface, VkFormat format, VkColorSpaceKHR colorspace)
|
VkFormat format, VkColorSpaceKHR colorspace,
|
||||||
|
const SWindowRect& rect)
|
||||||
{
|
{
|
||||||
|
std::unique_lock<std::mutex> lk(m_resizeLock);
|
||||||
|
m_deferredResizes.emplace(windowCtx, surface, format, colorspace, rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VulkanContext::_resizeSwapChains()
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lk(m_resizeLock);
|
||||||
|
if (m_deferredResizes.empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
while (m_deferredResizes.size())
|
||||||
|
{
|
||||||
|
SwapChainResize& resize = m_deferredResizes.front();
|
||||||
|
|
||||||
VkSurfaceCapabilitiesKHR surfCapabilities;
|
VkSurfaceCapabilitiesKHR surfCapabilities;
|
||||||
ThrowIfFailed(vk::GetPhysicalDeviceSurfaceCapabilitiesKHR(m_gpus[0], surface, &surfCapabilities));
|
ThrowIfFailed(vk::GetPhysicalDeviceSurfaceCapabilitiesKHR(m_gpus[0], resize.m_surface, &surfCapabilities));
|
||||||
|
|
||||||
uint32_t presentModeCount;
|
uint32_t presentModeCount;
|
||||||
ThrowIfFailed(vk::GetPhysicalDeviceSurfacePresentModesKHR(m_gpus[0], surface, &presentModeCount, nullptr));
|
ThrowIfFailed(vk::GetPhysicalDeviceSurfacePresentModesKHR(m_gpus[0], resize.m_surface, &presentModeCount, nullptr));
|
||||||
std::unique_ptr<VkPresentModeKHR[]> presentModes(new VkPresentModeKHR[presentModeCount]);
|
std::unique_ptr<VkPresentModeKHR[]> presentModes(new VkPresentModeKHR[presentModeCount]);
|
||||||
|
|
||||||
ThrowIfFailed(vk::GetPhysicalDeviceSurfacePresentModesKHR(m_gpus[0], surface, &presentModeCount, presentModes.get()));
|
ThrowIfFailed(vk::GetPhysicalDeviceSurfacePresentModesKHR(m_gpus[0], resize.m_surface, &presentModeCount, presentModes.get()));
|
||||||
|
|
||||||
VkExtent2D swapChainExtent;
|
VkExtent2D swapChainExtent;
|
||||||
// width and height are either both -1, or both not -1.
|
// width and height are either both -1, or both not -1.
|
||||||
@ -607,30 +622,33 @@ void VulkanContext::resizeSwapChain(VulkanContext::Window& windowCtx, VkSurfaceK
|
|||||||
else
|
else
|
||||||
preTransform = surfCapabilities.currentTransform;
|
preTransform = surfCapabilities.currentTransform;
|
||||||
|
|
||||||
|
Window::SwapChain& oldSc = resize.m_windowCtx.m_swapChains[resize.m_windowCtx.m_activeSwapChain];
|
||||||
|
|
||||||
VkSwapchainCreateInfoKHR swapChainInfo = {};
|
VkSwapchainCreateInfoKHR swapChainInfo = {};
|
||||||
swapChainInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
|
swapChainInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
|
||||||
swapChainInfo.pNext = nullptr;
|
swapChainInfo.pNext = nullptr;
|
||||||
swapChainInfo.surface = surface;
|
swapChainInfo.surface = resize.m_surface;
|
||||||
swapChainInfo.minImageCount = desiredNumberOfSwapChainImages;
|
swapChainInfo.minImageCount = desiredNumberOfSwapChainImages;
|
||||||
swapChainInfo.imageFormat = format;
|
swapChainInfo.imageFormat = resize.m_format;
|
||||||
swapChainInfo.imageExtent.width = swapChainExtent.width;
|
swapChainInfo.imageExtent.width = swapChainExtent.width;
|
||||||
swapChainInfo.imageExtent.height = swapChainExtent.height;
|
swapChainInfo.imageExtent.height = swapChainExtent.height;
|
||||||
swapChainInfo.preTransform = preTransform;
|
swapChainInfo.preTransform = preTransform;
|
||||||
swapChainInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
|
swapChainInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
|
||||||
swapChainInfo.imageArrayLayers = 1;
|
swapChainInfo.imageArrayLayers = 1;
|
||||||
swapChainInfo.presentMode = swapchainPresentMode;
|
swapChainInfo.presentMode = swapchainPresentMode;
|
||||||
swapChainInfo.oldSwapchain = nullptr;
|
swapChainInfo.oldSwapchain = oldSc.m_swapChain;
|
||||||
swapChainInfo.clipped = true;
|
swapChainInfo.clipped = true;
|
||||||
swapChainInfo.imageColorSpace = colorspace;
|
swapChainInfo.imageColorSpace = resize.m_colorspace;
|
||||||
swapChainInfo.imageUsage = VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
swapChainInfo.imageUsage = VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||||
swapChainInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
swapChainInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||||
swapChainInfo.queueFamilyIndexCount = 0;
|
swapChainInfo.queueFamilyIndexCount = 0;
|
||||||
swapChainInfo.pQueueFamilyIndices = nullptr;
|
swapChainInfo.pQueueFamilyIndices = nullptr;
|
||||||
|
|
||||||
Window::SwapChain& sc = windowCtx.m_swapChains[windowCtx.m_activeSwapChain ^ 1];
|
resize.m_windowCtx.m_activeSwapChain ^= 1;
|
||||||
|
Window::SwapChain& sc = resize.m_windowCtx.m_swapChains[resize.m_windowCtx.m_activeSwapChain];
|
||||||
sc.destroy(m_dev);
|
sc.destroy(m_dev);
|
||||||
ThrowIfFailed(vk::CreateSwapchainKHR(m_dev, &swapChainInfo, nullptr, &sc.m_swapChain));
|
ThrowIfFailed(vk::CreateSwapchainKHR(m_dev, &swapChainInfo, nullptr, &sc.m_swapChain));
|
||||||
sc.m_format = format;
|
sc.m_format = resize.m_format;
|
||||||
|
|
||||||
uint32_t swapchainImageCount;
|
uint32_t swapchainImageCount;
|
||||||
ThrowIfFailed(vk::GetSwapchainImagesKHR(m_dev, sc.m_swapChain, &swapchainImageCount, nullptr));
|
ThrowIfFailed(vk::GetSwapchainImagesKHR(m_dev, sc.m_swapChain, &swapchainImageCount, nullptr));
|
||||||
@ -645,6 +663,11 @@ void VulkanContext::resizeSwapChain(VulkanContext::Window& windowCtx, VkSurfaceK
|
|||||||
Window::SwapChain::Buffer& buf = sc.m_bufs[i];
|
Window::SwapChain::Buffer& buf = sc.m_bufs[i];
|
||||||
buf.m_image = swapchainImages[i];
|
buf.m_image = swapchainImages[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_deferredResizes.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct VulkanData : IGraphicsDataPriv<VulkanData>
|
struct VulkanData : IGraphicsDataPriv<VulkanData>
|
||||||
@ -3298,6 +3321,8 @@ void VulkanCommandQueue::execute()
|
|||||||
ThrowIfFailed(vk::QueueSubmit(m_ctx->m_queue, 1, &submitInfo, m_dynamicBufFence));
|
ThrowIfFailed(vk::QueueSubmit(m_ctx->m_queue, 1, &submitInfo, m_dynamicBufFence));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vk::CmdEndRenderPass(m_cmdBufs[m_fillBuf]);
|
||||||
|
|
||||||
/* Check on fence */
|
/* Check on fence */
|
||||||
if (m_submitted && vk::GetFenceStatus(m_ctx->m_dev, m_drawCompleteFence) == VK_NOT_READY)
|
if (m_submitted && vk::GetFenceStatus(m_ctx->m_dev, m_drawCompleteFence) == VK_NOT_READY)
|
||||||
{
|
{
|
||||||
@ -3307,6 +3332,9 @@ void VulkanCommandQueue::execute()
|
|||||||
m_resolveDispSource = nullptr;
|
m_resolveDispSource = nullptr;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
m_submitted = false;
|
||||||
|
|
||||||
|
vk::ResetFences(m_ctx->m_dev, 1, &m_drawCompleteFence);
|
||||||
|
|
||||||
/* Clear dead data */
|
/* Clear dead data */
|
||||||
datalk.lock();
|
datalk.lock();
|
||||||
@ -3333,8 +3361,8 @@ void VulkanCommandQueue::execute()
|
|||||||
}
|
}
|
||||||
datalk.unlock();
|
datalk.unlock();
|
||||||
|
|
||||||
/* Perform texture resizes */
|
/* Perform texture and swap-chain resizes */
|
||||||
if (m_texResizes.size())
|
if (m_ctx->_resizeSwapChains() || m_texResizes.size())
|
||||||
{
|
{
|
||||||
for (const auto& resize : m_texResizes)
|
for (const auto& resize : m_texResizes)
|
||||||
{
|
{
|
||||||
@ -3346,20 +3374,9 @@ void VulkanCommandQueue::execute()
|
|||||||
resetCommandBuffer();
|
resetCommandBuffer();
|
||||||
m_dynamicNeedsReset = true;
|
m_dynamicNeedsReset = true;
|
||||||
m_resolveDispSource = nullptr;
|
m_resolveDispSource = nullptr;
|
||||||
|
|
||||||
VulkanContext::Window::SwapChain& otherSc = m_windowCtx->m_swapChains[m_windowCtx->m_activeSwapChain ^ 1];
|
|
||||||
if (otherSc.m_swapChain)
|
|
||||||
{
|
|
||||||
VulkanContext::Window::SwapChain& thisSc = m_windowCtx->m_swapChains[m_windowCtx->m_activeSwapChain];
|
|
||||||
thisSc.destroy(m_ctx->m_dev);
|
|
||||||
m_windowCtx->m_activeSwapChain ^= 1;
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
vk::ResetFences(m_ctx->m_dev, 1, &m_drawCompleteFence);
|
|
||||||
vk::CmdEndRenderPass(m_cmdBufs[m_fillBuf]);
|
|
||||||
|
|
||||||
m_drawBuf = m_fillBuf;
|
m_drawBuf = m_fillBuf;
|
||||||
m_fillBuf ^= 1;
|
m_fillBuf ^= 1;
|
||||||
|
|
||||||
|
@ -54,6 +54,11 @@ struct GraphicsContextWin32 : IGraphicsContext
|
|||||||
m_pf(EPixelFormat::RGBA8),
|
m_pf(EPixelFormat::RGBA8),
|
||||||
m_parentWindow(parentWindow),
|
m_parentWindow(parentWindow),
|
||||||
m_3dCtx(b3dCtx) {}
|
m_3dCtx(b3dCtx) {}
|
||||||
|
|
||||||
|
virtual void resized(const SWindowRect& rect)
|
||||||
|
{
|
||||||
|
m_3dCtx.resize(m_parentWindow, rect.size[0], rect.size[1]);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GraphicsContextWin32D3D : GraphicsContextWin32
|
struct GraphicsContextWin32D3D : GraphicsContextWin32
|
||||||
@ -461,10 +466,10 @@ public:
|
|||||||
|
|
||||||
VulkanContext::Window* m_windowCtx = nullptr;
|
VulkanContext::Window* m_windowCtx = nullptr;
|
||||||
|
|
||||||
void resized(SWindowRect& rect)
|
void resized(const SWindowRect& rect)
|
||||||
{
|
{
|
||||||
if (m_windowCtx)
|
if (m_windowCtx)
|
||||||
m_ctx->resizeSwapChain(*m_windowCtx, m_surface, m_format, m_colorspace);
|
m_ctx->resizeSwapChain(*m_windowCtx, m_surface, m_format, m_colorspace, rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _setCallback(IWindowCallback* cb)
|
void _setCallback(IWindowCallback* cb)
|
||||||
@ -1290,7 +1295,7 @@ public:
|
|||||||
getWindowFrame(rect.location[0], rect.location[1], rect.size[0], rect.size[1]);
|
getWindowFrame(rect.location[0], rect.location[1], rect.size[0], rect.size[1]);
|
||||||
if (!rect.size[0] || !rect.size[1])
|
if (!rect.size[0] || !rect.size[1])
|
||||||
return;
|
return;
|
||||||
m_gfxCtx->m_3dCtx.resize(this, rect.size[0], rect.size[1]);
|
m_gfxCtx->resized(rect);
|
||||||
if (m_callback)
|
if (m_callback)
|
||||||
m_callback->resized(rect, m_openGL);
|
m_callback->resized(rect, m_openGL);
|
||||||
return;
|
return;
|
||||||
|
@ -297,7 +297,7 @@ struct GraphicsContextXlib : IGraphicsContext
|
|||||||
m_parentWindow(parentWindow),
|
m_parentWindow(parentWindow),
|
||||||
m_xDisp(disp) {}
|
m_xDisp(disp) {}
|
||||||
virtual void destroy()=0;
|
virtual void destroy()=0;
|
||||||
virtual void resized(SWindowRect& rect)=0;
|
virtual void resized(const SWindowRect& rect)=0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GraphicsContextXlibGLX : GraphicsContextXlib
|
struct GraphicsContextXlibGLX : GraphicsContextXlib
|
||||||
@ -414,7 +414,7 @@ public:
|
|||||||
|
|
||||||
~GraphicsContextXlibGLX() {destroy();}
|
~GraphicsContextXlibGLX() {destroy();}
|
||||||
|
|
||||||
void resized(SWindowRect& rect)
|
void resized(const SWindowRect& rect)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -650,10 +650,10 @@ public:
|
|||||||
|
|
||||||
VulkanContext::Window* m_windowCtx = nullptr;
|
VulkanContext::Window* m_windowCtx = nullptr;
|
||||||
|
|
||||||
void resized(SWindowRect& rect)
|
void resized(const SWindowRect& rect)
|
||||||
{
|
{
|
||||||
if (m_windowCtx)
|
if (m_windowCtx)
|
||||||
m_ctx->resizeSwapChain(*m_windowCtx, m_surface, m_format, m_colorspace);
|
m_ctx->resizeSwapChain(*m_windowCtx, m_surface, m_format, m_colorspace, rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _setCallback(IWindowCallback* cb)
|
void _setCallback(IWindowCallback* cb)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user