Forráskód Böngészése

Vulkan swap chain now also creates a depth stencil surfaces
Vulkan swap chain now waits for the device to be idle before resizing itself

BearishSun 9 éve
szülő
commit
4b10b2c563

+ 12 - 1
Source/BansheeVulkanRenderAPI/Include/BsVulkanSwapChain.h

@@ -29,7 +29,7 @@ namespace BansheeEngine
 
 		/** Rebuilds the swap chain with the provided properties. Destroys any previously existing swap chain. */
 		void rebuild(const SPtr<VulkanDevice>& device, VkSurfaceKHR surface, UINT32 width, UINT32 height, bool vsync, 
-			VkFormat colorFormat, VkColorSpaceKHR colorSpace);
+			VkFormat colorFormat, VkColorSpaceKHR colorSpace, bool createDepth, VkFormat depthFormat);
 
 		/**
 		 * Returns the actual width of the swap chain, in pixels. This might differ from the requested size in case it
@@ -57,13 +57,24 @@ namespace BansheeEngine
 		 * @note Must only be called once in-between present() calls, or before the first present() call.
 		 */
 		SwapChainSurface acquireBackBuffer();
+
+		/** Returns an image view representing the depth-stencil buffer, if any. */
+		VkImageView getDepthStencil() const { return mDepthStencilView; }
 	private:
+		/** Destroys current swap chain and depth stencil image (if any). */
+		void clear(VkSwapchainKHR swapChain);
+
 		SPtr<VulkanDevice> mDevice;
 		VkSwapchainKHR mSwapChain = VK_NULL_HANDLE;
 
 		UINT32 mWidth = 0;
 		UINT32 mHeight = 0;
 		Vector<SwapChainSurface> mSurfaces;
+
+		VkImage mDepthStencilImage = VK_NULL_HANDLE;
+		VkImageView mDepthStencilView = VK_NULL_HANDLE;
+		VkDeviceMemory mDepthStencilMemory = nullptr;
+
 		UINT32 mCurrentSemaphoreIdx = 0;
 		UINT32 mCurrentBackBufferIdx = 0;
 	};

+ 84 - 23
Source/BansheeVulkanRenderAPI/Source/BsVulkanSwapChain.cpp

@@ -8,24 +8,19 @@ namespace BansheeEngine
 {
 	VulkanSwapChain::~VulkanSwapChain()
 	{
-		if (mSwapChain != VK_NULL_HANDLE)
-		{
-			VkDevice logicalDevice = mDevice->getLogical();
-			for (auto& surface : mSurfaces)
-			{
-				vkDestroySemaphore(logicalDevice, surface.sync, gVulkanAllocator);
-				vkDestroyImageView(logicalDevice, surface.view, gVulkanAllocator);
-			}
-
-			vkDestroySwapchainKHR(logicalDevice, mSwapChain, gVulkanAllocator);
-		}
+		clear(mSwapChain);
 	}
 
-	void VulkanSwapChain::rebuild(const SPtr<VulkanDevice>& device, VkSurfaceKHR surface, UINT32 width, UINT32 height, bool vsync,
-		VkFormat colorFormat, VkColorSpaceKHR colorSpace)
+	void VulkanSwapChain::rebuild(const SPtr<VulkanDevice>& device, VkSurfaceKHR surface, UINT32 width, UINT32 height, 
+		bool vsync, VkFormat colorFormat, VkColorSpaceKHR colorSpace, bool createDepth, VkFormat depthFormat)
 	{
 		mDevice = device;
 
+		// Need to make sure nothing is using the swap buffer before we re-create it
+		// Note: Optionally I can detect exactly on which queues (if any) are the swap chain images used on, and only wait
+		// on those
+		mDevice->waitIdle();
+
 		VkResult result;
 		VkPhysicalDevice physicalDevice = device->getPhysical();
 
@@ -119,13 +114,7 @@ namespace BansheeEngine
 		result = vkCreateSwapchainKHR(logicalDevice, &swapChainCI, gVulkanAllocator, &mSwapChain);
 		assert(result == VK_SUCCESS);
 
-		if (oldSwapChain != VK_NULL_HANDLE)
-		{
-			for(auto& entry : mSurfaces)
-				vkDestroyImageView(logicalDevice, entry.view, gVulkanAllocator);
-
-			vkDestroySwapchainKHR(logicalDevice, oldSwapChain, gVulkanAllocator);
-		}
+		clear(oldSwapChain);
 
 		result = vkGetSwapchainImagesKHR(logicalDevice, mSwapChain, &numImages, nullptr);
 		assert(result == VK_SUCCESS);
@@ -142,6 +131,8 @@ namespace BansheeEngine
 			colorViewCI.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
 			colorViewCI.pNext = nullptr;
 			colorViewCI.flags = 0;
+			colorViewCI.viewType = VK_IMAGE_VIEW_TYPE_2D;
+			colorViewCI.image = images[i];
 			colorViewCI.format = colorFormat;
 			colorViewCI.components = {
 				VK_COMPONENT_SWIZZLE_R,
@@ -154,9 +145,7 @@ namespace BansheeEngine
 			colorViewCI.subresourceRange.levelCount = 1;
 			colorViewCI.subresourceRange.baseArrayLayer = 0;
 			colorViewCI.subresourceRange.layerCount = 1;
-			colorViewCI.viewType = VK_IMAGE_VIEW_TYPE_2D;
-			colorViewCI.image = images[i];
-
+			
 			mSurfaces[i].acquired = false;
 			mSurfaces[i].image = images[i];
 			result = vkCreateImageView(logicalDevice, &colorViewCI, gVulkanAllocator, &mSurfaces[i].view);
@@ -172,6 +161,54 @@ namespace BansheeEngine
 		}
 
 		bs_stack_free(images);
+
+		// Create depth stencil image
+		if (createDepth)
+		{
+			VkImageCreateInfo depthStencilImageCI;
+			depthStencilImageCI.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
+			depthStencilImageCI.pNext = nullptr;
+			depthStencilImageCI.flags = 0;
+			depthStencilImageCI.imageType = VK_IMAGE_TYPE_2D;
+			depthStencilImageCI.format = depthFormat;
+			depthStencilImageCI.extent = { width, height, 1 };
+			depthStencilImageCI.mipLevels = 1;
+			depthStencilImageCI.arrayLayers = 1;
+			depthStencilImageCI.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+			depthStencilImageCI.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
+			depthStencilImageCI.samples = VK_SAMPLE_COUNT_1_BIT;
+			depthStencilImageCI.tiling = VK_IMAGE_TILING_OPTIMAL;
+			depthStencilImageCI.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
+			depthStencilImageCI.pQueueFamilyIndices = nullptr;
+			depthStencilImageCI.queueFamilyIndexCount = 0;
+
+			result = vkCreateImage(logicalDevice, &depthStencilImageCI, gVulkanAllocator, &mDepthStencilImage);
+			assert(result == VK_SUCCESS);
+
+			mDepthStencilMemory = mDevice->allocateMemory(mDepthStencilImage, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
+
+			VkImageViewCreateInfo depthStencilViewCI;
+			depthStencilViewCI.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
+			depthStencilViewCI.pNext = nullptr;
+			depthStencilViewCI.flags = 0;
+			depthStencilViewCI.viewType = VK_IMAGE_VIEW_TYPE_2D;
+			depthStencilViewCI.image = mDepthStencilImage;
+			depthStencilViewCI.format = depthFormat;
+			depthStencilViewCI.components = {
+				VK_COMPONENT_SWIZZLE_R,
+				VK_COMPONENT_SWIZZLE_G,
+				VK_COMPONENT_SWIZZLE_B,
+				VK_COMPONENT_SWIZZLE_A
+			};
+			depthStencilViewCI.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
+			depthStencilViewCI.subresourceRange.baseMipLevel = 0;
+			depthStencilViewCI.subresourceRange.levelCount = 1;
+			depthStencilViewCI.subresourceRange.baseArrayLayer = 0;
+			depthStencilViewCI.subresourceRange.layerCount = 1;
+
+			result = vkCreateImageView(logicalDevice, &depthStencilViewCI, gVulkanAllocator, &mDepthStencilView);
+			assert(result == VK_SUCCESS);
+		}
 	}
 
 	void VulkanSwapChain::present(VkQueue queue, VkSemaphore semaphore)
@@ -224,4 +261,28 @@ namespace BansheeEngine
 		mCurrentBackBufferIdx = imageIndex;
 		return mSurfaces[imageIndex];
 	}
+
+	void VulkanSwapChain::clear(VkSwapchainKHR swapChain)
+	{
+		VkDevice logicalDevice = mDevice->getLogical();
+		if (swapChain != VK_NULL_HANDLE)
+		{
+			for (auto& surface : mSurfaces)
+			{
+				vkDestroySemaphore(logicalDevice, surface.sync, gVulkanAllocator);
+				vkDestroyImageView(logicalDevice, surface.view, gVulkanAllocator);
+			}
+
+			vkDestroySwapchainKHR(logicalDevice, swapChain, gVulkanAllocator);
+		}
+
+		if (mDepthStencilImage != VK_NULL_HANDLE)
+		{
+			vkDestroyImageView(logicalDevice, mDepthStencilView, gVulkanAllocator);
+			vkDestroyImage(logicalDevice, mDepthStencilImage, gVulkanAllocator);
+
+			mDevice->freeMemory(mDepthStencilMemory);
+			mDepthStencilImage = VK_NULL_HANDLE;
+		}
+	}
 }

+ 4 - 3
Source/BansheeVulkanRenderAPI/Source/BsVulkanTexture.cpp

@@ -15,10 +15,11 @@ namespace BansheeEngine
 
 	VulkanImage::~VulkanImage()
 	{
-		VkDevice device = mOwner->getDevice().getLogical();
+		VulkanDevice& device = mOwner->getDevice();
+		VkDevice vkDevice = device.getLogical();
 
-		vkDestroyImage(device, mImage, gVulkanAllocator);
-		vkFreeMemory(device, mMemory, gVulkanAllocator);
+		vkDestroyImage(vkDevice, mImage, gVulkanAllocator);
+		device.freeMemory(mMemory);
 	}
 
 	VulkanTextureCore::VulkanTextureCore(const TEXTURE_DESC& desc, const SPtr<PixelData>& initialData,