Browse Source

vulkan: fix love.window.setVsync

niki 2 years ago
parent
commit
ccca355664

+ 40 - 24
src/modules/graphics/vulkan/Graphics.cpp

@@ -436,9 +436,9 @@ void Graphics::present(void *screenshotCallbackdata)
 
 
 	VkResult result = vkQueuePresentKHR(presentQueue, &presentInfo);
 	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();
 		recreateSwapChain();
 	}
 	}
 	else if (result != VK_SUCCESS)
 	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)
 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->width = width;
 	this->height = height;
 	this->height = height;
 	this->pixelWidth = pixelwidth;
 	this->pixelWidth = pixelwidth;
@@ -1772,8 +1775,6 @@ VkSurfaceFormatKHR Graphics::chooseSwapSurfaceFormat(const std::vector<VkSurface
 
 
 VkPresentModeKHR Graphics::chooseSwapPresentMode(const std::vector<VkPresentModeKHR> &availablePresentModes)
 VkPresentModeKHR Graphics::chooseSwapPresentMode(const std::vector<VkPresentModeKHR> &availablePresentModes)
 {
 {
-	int vsync = Vulkan::getVsync();
-
 	const auto begin = availablePresentModes.begin();
 	const auto begin = availablePresentModes.begin();
 	const auto end = availablePresentModes.end();
 	const auto end = availablePresentModes.end();
 
 
@@ -2295,30 +2296,10 @@ void Graphics::setDefaultRenderPass()
 	renderPassState.msaa = msaaSamples;
 	renderPassState.msaa = msaaSamples;
 	renderPassState.numColorAttachments = 1;
 	renderPassState.numColorAttachments = 1;
 	renderPassState.transitionImages.clear();
 	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)
 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<float>(pixelw);
-	viewport.height = static_cast<float>(pixelh);
-	viewport.minDepth = 0.0f;
-	viewport.maxDepth = 1.0f;
-
-	vkCmdSetViewport(commandBuffers.at(currentFrame), 0, 1, &viewport);
-
 	auto currentCommandBuffer = commandBuffers.at(currentFrame);
 	auto currentCommandBuffer = commandBuffers.at(currentFrame);
 
 
 	// fixme: hasSRGBtexture
 	// fixme: hasSRGBtexture
@@ -2373,6 +2354,16 @@ void Graphics::startRenderPass()
 {
 {
 	renderPassState.active = true;
 	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)
 	if (renderPassState.useConfigurations)
 	{
 	{
 		auto &renderPassConfiguration = renderPassState.renderPassConfiguration;
 		auto &renderPassConfiguration = renderPassState.renderPassConfiguration;
@@ -2485,6 +2476,14 @@ void Graphics::cleanupUnusedObjects()
 	eraseUnusedObjects(graphicsPipelines, pipelineUsages, vkDestroyPipeline, device);
 	eraseUnusedObjects(graphicsPipelines, pipelineUsages, vkDestroyPipeline, device);
 }
 }
 
 
+void Graphics::requestSwapchainRecreation()
+{
+	if (swapChain != VK_NULL_HANDLE)
+	{
+		swapChainRecreationRequested = true;
+	}
+}
+
 void Graphics::setComputeShader(Shader *shader)
 void Graphics::setComputeShader(Shader *shader)
 {
 {
 	computeShader = shader;
 	computeShader = shader;
@@ -2707,6 +2706,21 @@ VkSampleCountFlagBits Graphics::getMsaaCount(int requestedMsaa) const
 		return VK_SAMPLE_COUNT_1_BIT;
 		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()
 void Graphics::createColorResources()
 {
 {
 	if (msaaSamples & VK_SAMPLE_COUNT_1_BIT)
 	if (msaaSamples & VK_SAMPLE_COUNT_1_BIT)
@@ -2947,6 +2961,8 @@ void Graphics::cleanupSwapChain()
 		vkDestroyImageView(device, swapChainImageView, nullptr);
 		vkDestroyImageView(device, swapChainImageView, nullptr);
 	swapChainImageViews.clear();
 	swapChainImageViews.clear();
 	vkDestroySwapchainKHR(device, swapChain, nullptr);
 	vkDestroySwapchainKHR(device, swapChain, nullptr);
+
+	swapChain = VK_NULL_HANDLE;
 }
 }
 
 
 void Graphics::recreateSwapChain()
 void Graphics::recreateSwapChain()

+ 5 - 1
src/modules/graphics/vulkan/Graphics.h

@@ -299,6 +299,8 @@ public:
 	graphics::Shader::BuiltinUniformData getCurrentBuiltinUniformData();
 	graphics::Shader::BuiltinUniformData getCurrentBuiltinUniformData();
 	const OptionalDeviceFeatures &getEnabledOptionalDeviceExtensions() const;
 	const OptionalDeviceFeatures &getEnabledOptionalDeviceExtensions() const;
 	VkSampleCountFlagBits getMsaaCount(int requestedMsaa) const;
 	VkSampleCountFlagBits getMsaaCount(int requestedMsaa) const;
+	void setVsync(int vsync);
+	int getVsync() const;
 
 
 protected:
 protected:
 	graphics::ShaderStage *newShaderStageInternal(ShaderStageType stage, const std::string &cachekey, const std::string &source, bool gles) override;
 	graphics::ShaderStage *newShaderStageInternal(ShaderStageType stage, const std::string &cachekey, const std::string &source, bool gles) override;
@@ -365,6 +367,7 @@ private:
 	void endRenderPass();
 	void endRenderPass();
 	VkSampler createSampler(const SamplerState &sampler);
 	VkSampler createSampler(const SamplerState &sampler);
 	void cleanupUnusedObjects();
 	void cleanupUnusedObjects();
+	void requestSwapchainRecreation();
 
 
 	VkInstance instance = VK_NULL_HANDLE;
 	VkInstance instance = VK_NULL_HANDLE;
 	VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;
 	VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;
@@ -407,12 +410,13 @@ private:
 	std::vector<VkSemaphore> renderFinishedSemaphores;
 	std::vector<VkSemaphore> renderFinishedSemaphores;
 	std::vector<VkFence> inFlightFences;
 	std::vector<VkFence> inFlightFences;
 	std::vector<VkFence> imagesInFlight;
 	std::vector<VkFence> imagesInFlight;
+	int vsync = 1;
 	VkDeviceSize minUniformBufferOffsetAlignment = 0;
 	VkDeviceSize minUniformBufferOffsetAlignment = 0;
 	bool imageRequested = false;
 	bool imageRequested = false;
 	uint32_t frameCounter = 0;
 	uint32_t frameCounter = 0;
 	size_t currentFrame = 0;
 	size_t currentFrame = 0;
 	uint32_t imageIndex = 0;
 	uint32_t imageIndex = 0;
-	bool framebufferResized = false;
+	bool swapChainRecreationRequested = false;
 	bool transitionColorDepthLayouts = false;
 	bool transitionColorDepthLayouts = false;
 	VmaAllocator vmaAllocator = VK_NULL_HANDLE;
 	VmaAllocator vmaAllocator = VK_NULL_HANDLE;
 	StrongRef<love::graphics::Texture> defaultTexture;
 	StrongRef<love::graphics::Texture> defaultTexture;

+ 0 - 11
src/modules/graphics/vulkan/Vulkan.cpp

@@ -31,7 +31,6 @@ namespace vulkan
 {
 {
 
 
 static uint32_t numShaderSwitches;
 static uint32_t numShaderSwitches;
-static int vsync = 1;
 
 
 void Vulkan::shaderSwitch()
 void Vulkan::shaderSwitch()
 {
 {
@@ -48,16 +47,6 @@ void Vulkan::resetShaderSwitches()
 	numShaderSwitches = 0;
 	numShaderSwitches = 0;
 }
 }
 
 
-void Vulkan::setVsync(int value)
-{
-	vsync = value;
-}
-
-int Vulkan::getVsync()
-{
-	return vsync;
-}
-
 VkFormat Vulkan::getVulkanVertexFormat(DataFormat format)
 VkFormat Vulkan::getVulkanVertexFormat(DataFormat format)
 {
 {
 	switch (format)
 	switch (format)

+ 0 - 3
src/modules/graphics/vulkan/Vulkan.h

@@ -58,9 +58,6 @@ public:
 	static uint32_t getNumShaderSwitches();
 	static uint32_t getNumShaderSwitches();
 	static void resetShaderSwitches();
 	static void resetShaderSwitches();
 
 
-	static void setVsync(int vsync);
-	static int getVsync();
-
 	static VkFormat getVulkanVertexFormat(DataFormat format);
 	static VkFormat getVulkanVertexFormat(DataFormat format);
 	static TextureFormat getTextureFormat(PixelFormat, bool sRGB);
 	static TextureFormat getTextureFormat(PixelFormat, bool sRGB);
 	static std::string getVendorName(uint32_t vendorId);
 	static std::string getVendorName(uint32_t vendorId);

+ 6 - 2
src/modules/window/sdl/Window.cpp

@@ -1101,7 +1101,8 @@ void Window::setVSync(int vsync)
 
 
 #ifdef LOVE_GRAPHICS_VULKAN
 #ifdef LOVE_GRAPHICS_VULKAN
 	// TODO: this doesn't update the swap-chain, but it should.
 	// TODO: this doesn't update the swap-chain, but it should.
-	love::graphics::vulkan::Vulkan::setVsync(vsync);
+	auto vgfx = dynamic_cast<love::graphics::vulkan::Graphics*>(graphics.get());
+	vgfx->setVsync(vsync);
 #endif
 #endif
 
 
 #if defined(LOVE_GRAPHICS_METAL) && defined(LOVE_MACOS)
 #if defined(LOVE_GRAPHICS_METAL) && defined(LOVE_MACOS)
@@ -1132,7 +1133,10 @@ int Window::getVSync() const
 
 
 #ifdef LOVE_GRAPHICS_VULKAN
 #ifdef LOVE_GRAPHICS_VULKAN
 	if (windowRenderer == love::graphics::RENDERER_VULKAN)
 	if (windowRenderer == love::graphics::RENDERER_VULKAN)
-		return love::graphics::vulkan::Vulkan::getVsync();
+	{
+		auto vgfx = dynamic_cast<love::graphics::vulkan::Graphics*>(graphics.get());
+		return vgfx->getVsync();
+	}
 #endif
 #endif
 
 
 	return 0;
 	return 0;