diff --git a/src/modules/graphics/vulkan/Graphics.cpp b/src/modules/graphics/vulkan/Graphics.cpp index d1995fcf4..02ec07095 100644 --- a/src/modules/graphics/vulkan/Graphics.cpp +++ b/src/modules/graphics/vulkan/Graphics.cpp @@ -436,9 +436,9 @@ void Graphics::present(void *screenshotCallbackdata) VkResult result = vkQueuePresentKHR(presentQueue, &presentInfo); - if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || framebufferResized) + if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || swapChainRecreationRequested) { - framebufferResized = false; + swapChainRecreationRequested = false; recreateSwapChain(); } else if (result != VK_SUCCESS) @@ -463,6 +463,9 @@ void Graphics::present(void *screenshotCallbackdata) void Graphics::setViewportSize(int width, int height, int pixelwidth, int pixelheight) { + if (swapChain != VK_NULL_HANDLE && (pixelWidth != this->pixelWidth || pixelHeight != this->pixelHeight || width != this->width || height != this->height)) + requestSwapchainRecreation(); + this->width = width; this->height = height; this->pixelWidth = pixelwidth; @@ -1772,8 +1775,6 @@ VkSurfaceFormatKHR Graphics::chooseSwapSurfaceFormat(const std::vector &availablePresentModes) { - int vsync = Vulkan::getVsync(); - const auto begin = availablePresentModes.begin(); const auto end = availablePresentModes.end(); @@ -2295,30 +2296,10 @@ void Graphics::setDefaultRenderPass() renderPassState.msaa = msaaSamples; renderPassState.numColorAttachments = 1; renderPassState.transitionImages.clear(); - - VkViewport viewport{}; - viewport.x = 0.0f; - viewport.y = 0.0f; - viewport.width = renderPassState.width; - viewport.height = renderPassState.height; - viewport.minDepth = 0.0f; - viewport.maxDepth = 1.0f; - - vkCmdSetViewport(commandBuffers.at(currentFrame), 0, 1, &viewport); } void Graphics::setRenderPass(const RenderTargets &rts, int pixelw, int pixelh, bool hasSRGBtexture) { - VkViewport viewport{}; - viewport.x = 0.0f; - viewport.y = 0.0f; - viewport.width = static_cast(pixelw); - viewport.height = static_cast(pixelh); - viewport.minDepth = 0.0f; - viewport.maxDepth = 1.0f; - - vkCmdSetViewport(commandBuffers.at(currentFrame), 0, 1, &viewport); - auto currentCommandBuffer = commandBuffers.at(currentFrame); // fixme: hasSRGBtexture @@ -2373,6 +2354,16 @@ void Graphics::startRenderPass() { renderPassState.active = true; + VkViewport viewport{}; + viewport.x = 0.0f; + viewport.y = 0.0f; + viewport.width = renderPassState.width; + viewport.height = renderPassState.height; + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + + vkCmdSetViewport(commandBuffers.at(currentFrame), 0, 1, &viewport); + if (renderPassState.useConfigurations) { auto &renderPassConfiguration = renderPassState.renderPassConfiguration; @@ -2485,6 +2476,14 @@ void Graphics::cleanupUnusedObjects() eraseUnusedObjects(graphicsPipelines, pipelineUsages, vkDestroyPipeline, device); } +void Graphics::requestSwapchainRecreation() +{ + if (swapChain != VK_NULL_HANDLE) + { + swapChainRecreationRequested = true; + } +} + void Graphics::setComputeShader(Shader *shader) { computeShader = shader; @@ -2707,6 +2706,21 @@ VkSampleCountFlagBits Graphics::getMsaaCount(int requestedMsaa) const return VK_SAMPLE_COUNT_1_BIT; } +void Graphics::setVsync(int vsync) +{ + if (vsync != this->vsync) + { + this->vsync = vsync; + + requestSwapchainRecreation(); + } +} + +int Graphics::getVsync() const +{ + return vsync; +} + void Graphics::createColorResources() { if (msaaSamples & VK_SAMPLE_COUNT_1_BIT) @@ -2947,6 +2961,8 @@ void Graphics::cleanupSwapChain() vkDestroyImageView(device, swapChainImageView, nullptr); swapChainImageViews.clear(); vkDestroySwapchainKHR(device, swapChain, nullptr); + + swapChain = VK_NULL_HANDLE; } void Graphics::recreateSwapChain() diff --git a/src/modules/graphics/vulkan/Graphics.h b/src/modules/graphics/vulkan/Graphics.h index 444f18739..8e389bd72 100644 --- a/src/modules/graphics/vulkan/Graphics.h +++ b/src/modules/graphics/vulkan/Graphics.h @@ -299,6 +299,8 @@ public: graphics::Shader::BuiltinUniformData getCurrentBuiltinUniformData(); const OptionalDeviceFeatures &getEnabledOptionalDeviceExtensions() const; VkSampleCountFlagBits getMsaaCount(int requestedMsaa) const; + void setVsync(int vsync); + int getVsync() const; protected: graphics::ShaderStage *newShaderStageInternal(ShaderStageType stage, const std::string &cachekey, const std::string &source, bool gles) override; @@ -365,6 +367,7 @@ private: void endRenderPass(); VkSampler createSampler(const SamplerState &sampler); void cleanupUnusedObjects(); + void requestSwapchainRecreation(); VkInstance instance = VK_NULL_HANDLE; VkPhysicalDevice physicalDevice = VK_NULL_HANDLE; @@ -407,12 +410,13 @@ private: std::vector renderFinishedSemaphores; std::vector inFlightFences; std::vector imagesInFlight; + int vsync = 1; VkDeviceSize minUniformBufferOffsetAlignment = 0; bool imageRequested = false; uint32_t frameCounter = 0; size_t currentFrame = 0; uint32_t imageIndex = 0; - bool framebufferResized = false; + bool swapChainRecreationRequested = false; bool transitionColorDepthLayouts = false; VmaAllocator vmaAllocator = VK_NULL_HANDLE; StrongRef defaultTexture; diff --git a/src/modules/graphics/vulkan/Vulkan.cpp b/src/modules/graphics/vulkan/Vulkan.cpp index 742f0cf93..2e344e433 100644 --- a/src/modules/graphics/vulkan/Vulkan.cpp +++ b/src/modules/graphics/vulkan/Vulkan.cpp @@ -31,7 +31,6 @@ namespace vulkan { static uint32_t numShaderSwitches; -static int vsync = 1; void Vulkan::shaderSwitch() { @@ -48,16 +47,6 @@ void Vulkan::resetShaderSwitches() numShaderSwitches = 0; } -void Vulkan::setVsync(int value) -{ - vsync = value; -} - -int Vulkan::getVsync() -{ - return vsync; -} - VkFormat Vulkan::getVulkanVertexFormat(DataFormat format) { switch (format) diff --git a/src/modules/graphics/vulkan/Vulkan.h b/src/modules/graphics/vulkan/Vulkan.h index 580f06cab..9db8ffa90 100644 --- a/src/modules/graphics/vulkan/Vulkan.h +++ b/src/modules/graphics/vulkan/Vulkan.h @@ -58,9 +58,6 @@ public: static uint32_t getNumShaderSwitches(); static void resetShaderSwitches(); - static void setVsync(int vsync); - static int getVsync(); - static VkFormat getVulkanVertexFormat(DataFormat format); static TextureFormat getTextureFormat(PixelFormat, bool sRGB); static std::string getVendorName(uint32_t vendorId); diff --git a/src/modules/window/sdl/Window.cpp b/src/modules/window/sdl/Window.cpp index 01f44dd76..0997d1863 100644 --- a/src/modules/window/sdl/Window.cpp +++ b/src/modules/window/sdl/Window.cpp @@ -1101,7 +1101,8 @@ void Window::setVSync(int vsync) #ifdef LOVE_GRAPHICS_VULKAN // TODO: this doesn't update the swap-chain, but it should. - love::graphics::vulkan::Vulkan::setVsync(vsync); + auto vgfx = dynamic_cast(graphics.get()); + vgfx->setVsync(vsync); #endif #if defined(LOVE_GRAPHICS_METAL) && defined(LOVE_MACOS) @@ -1132,7 +1133,10 @@ int Window::getVSync() const #ifdef LOVE_GRAPHICS_VULKAN if (windowRenderer == love::graphics::RENDERER_VULKAN) - return love::graphics::vulkan::Vulkan::getVsync(); + { + auto vgfx = dynamic_cast(graphics.get()); + return vgfx->getVsync(); + } #endif return 0;