Przeglądaj źródła

Added frame buffers to Vulkan's implementation of a render window

BearishSun 9 lat temu
rodzic
commit
1da1209680

+ 1 - 2
Source/BansheeVulkanRenderAPI/Include/BsVulkanFramebuffer.h

@@ -67,8 +67,7 @@ namespace BansheeEngine
 	private:
 	private:
 		VkRenderPass mRenderPass;
 		VkRenderPass mRenderPass;
 		VkFramebuffer mFramebuffer;
 		VkFramebuffer mFramebuffer;
-
-		SPtr<VulkanDevice> mDevice;
+		VkDevice mDevice;
 	};
 	};
 
 
 	/** @} */
 	/** @} */

+ 3 - 0
Source/BansheeVulkanRenderAPI/Include/BsVulkanPrerequisites.h

@@ -13,6 +13,8 @@
 	#define VK_USE_PLATFORM_WIN32_KHR
 	#define VK_USE_PLATFORM_WIN32_KHR
 #endif
 #endif
 
 
+#define BS_NUM_BACK_BUFFERS 1
+
 #include "vulkan/vulkan.h"
 #include "vulkan/vulkan.h"
 
 
 /** @addtogroup Plugins
 /** @addtogroup Plugins
@@ -37,6 +39,7 @@ namespace BansheeEngine
 	class VulkanDevice;
 	class VulkanDevice;
 	class VulkanGLSLProgramFactory;
 	class VulkanGLSLProgramFactory;
 	class VulkanSwapChain;
 	class VulkanSwapChain;
+	class VulkanFramebuffer;
 	class VulkanDescriptorLayout;
 	class VulkanDescriptorLayout;
 	class VulkanDescriptorSet;
 	class VulkanDescriptorSet;
 	class VulkanDescriptorManager;
 	class VulkanDescriptorManager;

+ 11 - 4
Source/BansheeVulkanRenderAPI/Include/BsVulkanSwapChain.h

@@ -10,8 +10,6 @@ namespace BansheeEngine
 	 *  @{
 	 *  @{
 	 */
 	 */
 
 
-#define BS_NUM_BACK_BUFFERS 1
-
 	/** Description of a single swap chain surface. */
 	/** Description of a single swap chain surface. */
 	struct SwapChainSurface
 	struct SwapChainSurface
 	{
 	{
@@ -27,7 +25,10 @@ namespace BansheeEngine
 	public:
 	public:
 		~VulkanSwapChain();
 		~VulkanSwapChain();
 
 
-		/** Rebuilds the swap chain with the provided properties. Destroys any previously existing swap chain. */
+		/** 
+		 * Rebuilds the swap chain with the provided properties. Destroys any previously existing swap chain. Caller must
+		 * ensure the swap chain is not used at the device when this is called.
+		 */
 		void rebuild(const SPtr<VulkanDevice>& device, VkSurfaceKHR surface, UINT32 width, UINT32 height, bool vsync, 
 		void rebuild(const SPtr<VulkanDevice>& device, VkSurfaceKHR surface, UINT32 width, UINT32 height, bool vsync, 
 			VkFormat colorFormat, VkColorSpaceKHR colorSpace, bool createDepth, VkFormat depthFormat);
 			VkFormat colorFormat, VkColorSpaceKHR colorSpace, bool createDepth, VkFormat depthFormat);
 
 
@@ -58,8 +59,14 @@ namespace BansheeEngine
 		 */
 		 */
 		SwapChainSurface acquireBackBuffer();
 		SwapChainSurface acquireBackBuffer();
 
 
+		/** Returns the number of available color surfaces. */
+		UINT32 getNumColorSurfaces() const { return (UINT32)mSurfaces.size(); }
+
+		/** Returns an image view representing the color surface at the specified index. */
+		VkImageView getColorView(UINT32 index) const { return mSurfaces[index].view; }
+
 		/** Returns an image view representing the depth-stencil buffer, if any. */
 		/** Returns an image view representing the depth-stencil buffer, if any. */
-		VkImageView getDepthStencil() const { return mDepthStencilView; }
+		VkImageView getDepthStencilView() const { return mDepthStencilView; }
 	private:
 	private:
 		/** Destroys current swap chain and depth stencil image (if any). */
 		/** Destroys current swap chain and depth stencil image (if any). */
 		void clear(VkSwapchainKHR swapChain);
 		void clear(VkSwapchainKHR swapChain);

+ 11 - 1
Source/BansheeVulkanRenderAPI/Include/Win32/BsWin32RenderWindow.h

@@ -4,6 +4,7 @@
 
 
 #include "BsVulkanPrerequisites.h"
 #include "BsVulkanPrerequisites.h"
 #include "BsRenderWindow.h"
 #include "BsRenderWindow.h"
+#include "BsVulkanFramebuffer.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
@@ -101,6 +102,13 @@ namespace BansheeEngine
 		void syncProperties() override;
 		void syncProperties() override;
 
 
 	protected:
 	protected:
+		/** Contains an information regarding a framebuffer representing a single swap chain surface. */
+		struct FrameBufferInfo
+		{
+			UPtr<VulkanFramebuffer> framebuffer;
+			VULKAN_FRAMEBUFFER_DESC desc;
+		};
+
 		Win32Window* mWindow;
 		Win32Window* mWindow;
 		bool mIsChild;
 		bool mIsChild;
 		bool mShowOnSwap;
 		bool mShowOnSwap;
@@ -110,7 +118,9 @@ namespace BansheeEngine
 		VkSurfaceKHR mSurface;
 		VkSurfaceKHR mSurface;
 		VkColorSpaceKHR mColorSpace;
 		VkColorSpaceKHR mColorSpace;
 		VkFormat mColorFormat;
 		VkFormat mColorFormat;
+		VkFormat mDepthFormat;
 		SPtr<VulkanSwapChain> mSwapChain;
 		SPtr<VulkanSwapChain> mSwapChain;
+		FrameBufferInfo mFramebufferInfos[BS_NUM_BACK_BUFFERS + 1];
 
 
 		Win32RenderWindowProperties mProperties;
 		Win32RenderWindowProperties mProperties;
 		Win32RenderWindowProperties mSyncedProperties;
 		Win32RenderWindowProperties mSyncedProperties;
@@ -158,4 +168,4 @@ namespace BansheeEngine
 	};
 	};
 	
 	
 	/** @} */
 	/** @} */
-}
+}

+ 5 - 5
Source/BansheeVulkanRenderAPI/Source/BsVulkanFramebuffer.cpp

@@ -7,7 +7,7 @@
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
 	VulkanFramebuffer::VulkanFramebuffer(const SPtr<VulkanDevice>& device, const VULKAN_FRAMEBUFFER_DESC& desc)
 	VulkanFramebuffer::VulkanFramebuffer(const SPtr<VulkanDevice>& device, const VULKAN_FRAMEBUFFER_DESC& desc)
-		:mDevice(device)
+		:mDevice(device->getLogical())
 	{
 	{
 		// Create render state
 		// Create render state
 		VkAttachmentDescription attachments[BS_MAX_MULTIPLE_RENDER_TARGETS + 1];
 		VkAttachmentDescription attachments[BS_MAX_MULTIPLE_RENDER_TARGETS + 1];
@@ -121,7 +121,7 @@ namespace BansheeEngine
 		renderPassCI.dependencyCount = 2;
 		renderPassCI.dependencyCount = 2;
 		renderPassCI.pDependencies = dependencies;
 		renderPassCI.pDependencies = dependencies;
 
 
-		VkResult result = vkCreateRenderPass(device->getLogical(), &renderPassCI, gVulkanAllocator, &mRenderPass);
+		VkResult result = vkCreateRenderPass(mDevice, &renderPassCI, gVulkanAllocator, &mRenderPass);
 		assert(result == VK_SUCCESS);
 		assert(result == VK_SUCCESS);
 
 
 		// Create frame buffer
 		// Create frame buffer
@@ -136,13 +136,13 @@ namespace BansheeEngine
 		framebufferCI.height = desc.height;
 		framebufferCI.height = desc.height;
 		framebufferCI.layers = desc.layers;
 		framebufferCI.layers = desc.layers;
 
 
-		result = vkCreateFramebuffer(device->getLogical(), &framebufferCI, gVulkanAllocator, &mFramebuffer);
+		result = vkCreateFramebuffer(mDevice, &framebufferCI, gVulkanAllocator, &mFramebuffer);
 		assert(result == VK_SUCCESS);
 		assert(result == VK_SUCCESS);
 	}
 	}
 
 
 	VulkanFramebuffer::~VulkanFramebuffer()
 	VulkanFramebuffer::~VulkanFramebuffer()
 	{
 	{
-		vkDestroyFramebuffer(mDevice->getLogical(), mFramebuffer, gVulkanAllocator);
-		vkDestroyRenderPass(mDevice->getLogical(), mRenderPass, gVulkanAllocator);
+		vkDestroyFramebuffer(mDevice, mFramebuffer, gVulkanAllocator);
+		vkDestroyRenderPass(mDevice, mRenderPass, gVulkanAllocator);
 	}
 	}
 }
 }

+ 0 - 5
Source/BansheeVulkanRenderAPI/Source/BsVulkanSwapChain.cpp

@@ -16,11 +16,6 @@ namespace BansheeEngine
 	{
 	{
 		mDevice = device;
 		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;
 		VkResult result;
 		VkPhysicalDevice physicalDevice = device->getPhysical();
 		VkPhysicalDevice physicalDevice = device->getPhysical();
 
 

+ 56 - 6
Source/BansheeVulkanRenderAPI/Source/Win32/BsWin32RenderWindow.cpp

@@ -34,6 +34,10 @@ namespace BansheeEngine
 			mWindow = nullptr;
 			mWindow = nullptr;
 		}
 		}
 
 
+		UINT32 numFramebuffers = sizeof(mFramebufferInfos) / sizeof(mFramebufferInfos[0]);
+		for (UINT32 i = 0; i < numFramebuffers; i++)
+			mFramebufferInfos[i].framebuffer = nullptr;
+
 		mSwapChain = nullptr;
 		mSwapChain = nullptr;
 		vkDestroySurfaceKHR(mRenderAPI._getInstance(), mSurface, gVulkanAllocator);
 		vkDestroySurfaceKHR(mRenderAPI._getInstance(), mSurface, gVulkanAllocator);
 	}
 	}
@@ -96,6 +100,8 @@ namespace BansheeEngine
 		props.mHeight = mWindow->getHeight();
 		props.mHeight = mWindow->getHeight();
 		props.mTop = mWindow->getTop();
 		props.mTop = mWindow->getTop();
 		props.mLeft = mWindow->getLeft();
 		props.mLeft = mWindow->getLeft();
+		props.mHwGamma = mDesc.gamma;
+		props.mMultisampleCount = 1;
 
 
 		if (!windowDesc.external)
 		if (!windowDesc.external)
 		{
 		{
@@ -190,14 +196,34 @@ namespace BansheeEngine
 					LOGERR("Cannot find a valid sRGB format for a render window surface, falling back to a default format.");
 					LOGERR("Cannot find a valid sRGB format for a render window surface, falling back to a default format.");
 			}
 			}
 		}
 		}
+
+		mDepthFormat = VK_FORMAT_D24_UNORM_S8_UINT;
 		
 		
 		bs_stack_free(formats);
 		bs_stack_free(formats);
 
 
 		// Create swap chain
 		// Create swap chain
 		mSwapChain = bs_shared_ptr_new<VulkanSwapChain>();
 		mSwapChain = bs_shared_ptr_new<VulkanSwapChain>();
-		mSwapChain->rebuild(presentDevice, mSurface, props.mWidth, props.mHeight, props.mVSync, mColorFormat, mColorSpace);
+		mSwapChain->rebuild(presentDevice, mSurface, props.mWidth, props.mHeight, props.mVSync, mColorFormat, mColorSpace, 
+			mDesc.depthBuffer, mDepthFormat);
 
 
-		// TODO - Create a framebuffer for each swap chain buffer
+		// Create a framebuffer for each swap chain buffer
+		UINT32 numFramebuffers = sizeof(mFramebufferInfos) / sizeof(mFramebufferInfos[0]);
+		assert(numFramebuffers == mSwapChain->getNumColorSurfaces());
+		for(UINT32 i = 0; i < numFramebuffers; i++)
+		{
+			FrameBufferInfo& framebufferInfo = mFramebufferInfos[i];
+			framebufferInfo.desc.width = mSwapChain->getWidth();
+			framebufferInfo.desc.height = mSwapChain->getHeight();
+			framebufferInfo.desc.layers = 1;
+			framebufferInfo.desc.numSamples = 1;
+			framebufferInfo.desc.offscreen = false;
+			framebufferInfo.desc.color[0].format = mColorFormat;
+			framebufferInfo.desc.color[0].view = mSwapChain->getColorView(i);
+			framebufferInfo.desc.depth.format = mDepthFormat;
+			framebufferInfo.desc.depth.view = mSwapChain->getDepthStencilView();
+
+			framebufferInfo.framebuffer = bs_unique_ptr_new<VulkanFramebuffer>(presentDevice, framebufferInfo.desc);
+		}
 
 
 		// Make the window full screen if required
 		// Make the window full screen if required
 		if (!windowDesc.external)
 		if (!windowDesc.external)
@@ -231,8 +257,6 @@ namespace BansheeEngine
 			}
 			}
 		}
 		}
 
 
-		// TODO - Set hwGamma and multisample properties
-
 		{
 		{
 			ScopedSpinLock lock(mLock);
 			ScopedSpinLock lock(mLock);
 			mSyncedProperties = props;
 			mSyncedProperties = props;
@@ -485,10 +509,36 @@ namespace BansheeEngine
 			props.mHeight = mWindow->getHeight();
 			props.mHeight = mWindow->getHeight();
 		}
 		}
 
 
+		// Resize swap chain and update framebuffers
+		
+		//// 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
 		SPtr<VulkanDevice> presentDevice = mRenderAPI._getPresentDevice();
 		SPtr<VulkanDevice> presentDevice = mRenderAPI._getPresentDevice();
-		mSwapChain->rebuild(presentDevice, mSurface, props.mWidth, props.mHeight, props.mVSync, mColorFormat, mColorSpace);
+		presentDevice->waitIdle();
 
 
-		// TODO - Update framebuffer?
+		UINT32 numFramebuffers = sizeof(mFramebufferInfos) / sizeof(mFramebufferInfos[0]);
+
+		//// First destroy existing frame buffers
+		for (UINT32 i = 0; i < numFramebuffers; i++)
+			mFramebufferInfos[i].framebuffer = nullptr;
+
+		//// Rebuild swap chain
+		mSwapChain->rebuild(presentDevice, mSurface, props.mWidth, props.mHeight, props.mVSync, mColorFormat, mColorSpace, 
+			mDesc.depthBuffer, mDepthFormat);
+
+		//// Rebuild framebuffers
+		assert(numFramebuffers == mSwapChain->getNumColorSurfaces());
+		for (UINT32 i = 0; i < numFramebuffers; i++)
+		{
+			FrameBufferInfo& framebufferInfo = mFramebufferInfos[i];
+			framebufferInfo.desc.width = mSwapChain->getWidth();
+			framebufferInfo.desc.height = mSwapChain->getHeight();
+			framebufferInfo.desc.color[0].view = mSwapChain->getColorView(i);
+			framebufferInfo.desc.depth.view = mSwapChain->getDepthStencilView();
+
+			framebufferInfo.framebuffer = bs_unique_ptr_new<VulkanFramebuffer>(presentDevice, framebufferInfo.desc);
+		}
 
 
 		RenderWindowCore::_windowMovedOrResized();
 		RenderWindowCore::_windowMovedOrResized();
 	}
 	}