Browse Source

Implemented Vulkan swapBuffers method on render window

BearishSun 9 years ago
parent
commit
a448b09b54

+ 10 - 2
Source/BansheeCore/Include/BsRenderTarget.h

@@ -218,8 +218,16 @@ namespace BansheeEngine
 		 */
 		void setPriority(INT32 priority);
 
-		/** Swaps the frame buffers to display the next frame. */
-		virtual void swapBuffers() {};
+		/** 
+		 * Swaps the frame buffers to display the next frame. 
+		 *
+		 * @param[in]	syncMask	Optional synchronization mask that determines for which queues should the system wait
+		 *							before performing the swap buffer operation. By default the system waits for all queues.
+		 *							Howvever if certain queues are performing non-rendering operations, or operations not 
+		 *							related to this render target, you can exclude them from the sync mask for potentially 
+		 *							better performance. You can use CommandSyncMask to generate a valid sync mask.
+		 */
+		virtual void swapBuffers(UINT32 syncMask = 0xFFFFFFFF) {}
 
 		/** Queries the render target for a custom attribute. This may be anything and is implementation specific. */
 		virtual void getCustomAttribute(const String& name, void* pData) const;

+ 2 - 2
Source/BansheeD3D11RenderAPI/Include/BsD3D11RenderWindow.h

@@ -77,7 +77,7 @@ namespace BansheeEngine
 		void copyToMemory(PixelData &dst, FrameBuffer buffer);
 
 		/** @copydoc RenderWindowCore::swapBuffers */
-		void swapBuffers() override;
+		void swapBuffers(UINT32 syncMask = 0xFFFFFFFF) override;
 
 		/** @copydoc RenderWindowCore::getCustomAttribute */
 		void getCustomAttribute(const String& name, void* pData) const override;
@@ -95,7 +95,7 @@ namespace BansheeEngine
 		friend class D3D11RenderWindow;
 
 		/** @copydoc CoreObjectCore::initialize */
-		virtual void initialize() override;
+		void initialize() override;
 
 		/**	Creates internal resources dependent on window size. */
 		void createSizeDependedD3DResources();

+ 1 - 1
Source/BansheeD3D11RenderAPI/Source/BsD3D11RenderWindow.cpp

@@ -161,7 +161,7 @@ namespace BansheeEngine
 		RenderWindowCore::initialize();
 	}
 
-	void D3D11RenderWindowCore::swapBuffers()
+	void D3D11RenderWindowCore::swapBuffers(UINT32 syncMask)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 

+ 3 - 3
Source/BansheeGLRenderAPI/Include/Win32/BsWin32RenderWindow.h

@@ -72,13 +72,13 @@ namespace BansheeEngine
 		void copyToMemory(PixelData& dst, FrameBuffer buffer);
 
 		/** @copydoc RenderWindowCore::swapBuffers */
-		void swapBuffers() override;
+		void swapBuffers(UINT32 syncMask) override;
 
 		/** @copydoc RenderWindowCore::getCustomAttribute */
 		void getCustomAttribute(const String& name, void* pData) const override;
 
 		/** @copydoc RenderWindowCore::setActive */
-		virtual void setActive(bool state) override;
+		void setActive(bool state) override;
 
 		/** @copydoc RenderWindowCore::_windowMovedOrResized */
 		void _windowMovedOrResized() override;
@@ -93,7 +93,7 @@ namespace BansheeEngine
 		friend class Win32GLSupport;
 
 		/** @copydoc CoreObjectCore::initialize */
-		virtual void initialize() override;
+		void initialize() override;
 
 		/** @copydoc RenderWindowCore::getProperties */
 		const RenderTargetProperties& getPropertiesInternal() const override { return mProperties; }

+ 1 - 1
Source/BansheeGLRenderAPI/Source/Win32/BsWin32RenderWindow.cpp

@@ -383,7 +383,7 @@ namespace BansheeEngine
 		mWindow->restore();
 	}
 
-	void Win32RenderWindowCore::swapBuffers()
+	void Win32RenderWindowCore::swapBuffers(UINT32 syncMask)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 

+ 6 - 0
Source/BansheeVulkanRenderAPI/Include/BsVulkanDevice.h

@@ -55,6 +55,12 @@ namespace BansheeEngine
 		 */
 		UINT32 getQueueFamily(GpuQueueType type) const { return mQueueInfos[(int)type].familyIdx; }
 
+		/** 
+		 * Fills out a mask that has bits set for every queue index that maps to the same physical queue as the provided 
+		 * index. This is useful as different queue indices will sometimes map to the same physical queue.
+		 */
+		UINT32 getQueueMask(GpuQueueType type, UINT32 queueIdx) const;
+
 		/** Returns a pool that can be used for allocating command buffers for all queues on this device. */
 		VulkanCmdBufferPool& getCmdBufferPool() const { return *mCommandBufferPool; }
 

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

@@ -47,10 +47,11 @@ namespace BansheeEngine
 		/** 
 		 * Presents the back buffer to the output device, swapping the buffers. 
 		 *
-		 * @param[in]	queue		Queue on which to queue the present operation. Must support present operations.
-		 * @param[in]	semaphore	Optional semaphore to wait on before presenting the queue.
+		 * @param[in]	queue			Queue on which to queue the present operation. Must support present operations.
+		 * @param[in]	semaphores		Optional semaphores to wait on before presenting the queue.
+		 * @param[in]	numSemaphores	Number of semaphores in the @p semaphores array.
 		 */
-		void present(VkQueue queue, VkSemaphore semaphore);
+		void present(VkQueue queue, VkSemaphore* semaphores, UINT32 numSemaphores);
 
 		/**
 		 * Returns the current back buffer image. 

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

@@ -76,7 +76,7 @@ namespace BansheeEngine
 		void copyToMemory(PixelData &dst, FrameBuffer buffer);
 
 		/** @copydoc RenderWindowCore::swapBuffers */
-		void swapBuffers() override;
+		void swapBuffers(UINT32 syncMask = 0xFFFFFFFF) override;
 
 		/** @copydoc RenderWindowCore::getCustomAttribute */
 		void getCustomAttribute(const String& name, void* pData) const override;
@@ -119,8 +119,10 @@ namespace BansheeEngine
 		VkColorSpaceKHR mColorSpace;
 		VkFormat mColorFormat;
 		VkFormat mDepthFormat;
+		UINT32 mPresentQueueFamily;
 		SPtr<VulkanSwapChain> mSwapChain;
 		FrameBufferInfo mFramebufferInfos[BS_NUM_BACK_BUFFERS + 1];
+		VkSemaphore mSemaphoresTemp[BS_MAX_COMMAND_BUFFERS];
 
 		Win32RenderWindowProperties mProperties;
 		Win32RenderWindowProperties mSyncedProperties;

+ 2 - 9
Source/BansheeVulkanRenderAPI/Source/BsVulkanCommandBuffer.cpp

@@ -443,7 +443,7 @@ namespace BansheeEngine
 			GpuQueueType otherQueueType = GQT_GRAPHICS;
 			for (UINT32 i = 0; i < GQT_COUNT; i++)
 			{
-				if (device.getQueueFamily(otherQueueType) != entryQueueFamily)
+				if (device.getQueueFamily((GpuQueueType)i) != entryQueueFamily)
 					continue;
 
 				UINT32 numQueues = device.getNumQueues(otherQueueType);
@@ -572,14 +572,7 @@ namespace BansheeEngine
 		}
 
 		mQueue = device.getQueue(mType, mQueueIdx % numQueues);
-
-		// If multiple command buffer IDs map to the same queue, mark them in the mask
-		UINT32 curIdx = mQueueIdx;
-		while (curIdx < BS_MAX_QUEUES_PER_TYPE)
-		{
-			mIdMask |= CommandSyncMask::getGlobalQueueIdx(mType, curIdx);
-			curIdx += numQueues;
-		}
+		mIdMask = device.getQueueMask(mType, mQueueIdx);
 
 		acquireNewBuffer();
 	}

+ 17 - 0
Source/BansheeVulkanRenderAPI/Source/BsVulkanDevice.cpp

@@ -138,6 +138,23 @@ namespace BansheeEngine
 		assert(result == VK_SUCCESS);
 	}
 
+	UINT32 VulkanDevice::getQueueMask(GpuQueueType type, UINT32 queueIdx) const
+	{
+		UINT32 numQueues = getNumQueues(type);
+		if (numQueues == 0)
+			return 0;
+
+		UINT32 idMask = 0;
+		UINT32 curIdx = queueIdx;
+		while (curIdx < BS_MAX_QUEUES_PER_TYPE)
+		{
+			idMask |= CommandSyncMask::getGlobalQueueIdx(type, curIdx);
+			curIdx += numQueues;
+		}
+
+		return idMask;
+	}
+
 	VkDeviceMemory VulkanDevice::allocateMemory(VkImage image, VkMemoryPropertyFlags flags)
 	{
 		VkMemoryRequirements memReq;

+ 4 - 4
Source/BansheeVulkanRenderAPI/Source/BsVulkanSwapChain.cpp

@@ -206,7 +206,7 @@ namespace BansheeEngine
 		}
 	}
 
-	void VulkanSwapChain::present(VkQueue queue, VkSemaphore semaphore)
+	void VulkanSwapChain::present(VkQueue queue, VkSemaphore* semaphores, UINT32 numSemaphores)
 	{
 		assert(mSurfaces[mCurrentBackBufferIdx].acquired && "Attempting to present an unacquired back buffer.");
 		mSurfaces[mCurrentBackBufferIdx].acquired = false;
@@ -220,10 +220,10 @@ namespace BansheeEngine
 		presentInfo.pResults = nullptr;
 
 		// Wait before presenting, if required
-		if (semaphore != VK_NULL_HANDLE)
+		if (numSemaphores > 0)
 		{
-			presentInfo.pWaitSemaphores = &semaphore;
-			presentInfo.waitSemaphoreCount = 1;
+			presentInfo.pWaitSemaphores = semaphores;
+			presentInfo.waitSemaphoreCount = numSemaphores;
 		}
 		else
 		{

+ 27 - 4
Source/BansheeVulkanRenderAPI/Source/Win32/BsWin32RenderWindow.cpp

@@ -10,6 +10,10 @@
 #include "BsVulkanRenderAPI.h"
 #include "BsVulkanDevice.h"
 #include "BsVulkanSwapChain.h"
+#include "BsVulkanDevice.h"
+#include "BsVulkanCommandBuffer.h"
+#include "BsVulkanCommandBufferManager.h"
+#include "BsVulkanQueue.h"
 #include "BsMath.h"
 
 namespace BansheeEngine
@@ -124,10 +128,10 @@ namespace BansheeEngine
 		SPtr<VulkanDevice> presentDevice = mRenderAPI._getPresentDevice();
 		VkPhysicalDevice physicalDevice = presentDevice->getPhysical();
 
-		UINT32 presentQueueIdx = presentDevice->getQueueFamily(GQT_GRAPHICS);
+		mPresentQueueFamily = presentDevice->getQueueFamily(GQT_GRAPHICS);
 		
 		VkBool32 supportsPresent;
-		vkGetPhysicalDeviceSurfaceSupportKHR(physicalDevice, presentQueueIdx, mSurface, &supportsPresent);
+		vkGetPhysicalDeviceSurfaceSupportKHR(physicalDevice, mPresentQueueFamily, mSurface, &supportsPresent);
 
 		if(!supportsPresent)
 		{
@@ -266,14 +270,33 @@ namespace BansheeEngine
 		RenderWindowCore::initialize();
 	}
 
-	void Win32RenderWindowCore::swapBuffers()
+	void Win32RenderWindowCore::swapBuffers(UINT32 syncMask)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
 		if (mShowOnSwap)
 			setHidden(false);
 
-		// TODO - Swap buffers
+		// Get a command buffer on which we'll submit
+		SPtr<VulkanDevice> presentDevice = mRenderAPI._getPresentDevice();
+
+		// Assuming present queue is always graphics
+		assert(presentDevice->getQueueFamily(GQT_GRAPHICS) == mPresentQueueFamily);
+
+		// Find an appropriate queue to execute on
+		VulkanQueue* queue = presentDevice->getQueue(GQT_GRAPHICS, 0);
+		UINT32 queueMask = presentDevice->getQueueMask(GQT_GRAPHICS, 0);
+
+		// Ignore myself
+		syncMask &= ~queueMask;
+
+		UINT32 deviceIdx = presentDevice->getIndex();
+		VulkanCommandBufferManager& cbm = static_cast<VulkanCommandBufferManager&>(CommandBufferManager::instance());
+
+		UINT32 numSemaphores;
+		cbm.getSyncSemaphores(deviceIdx, syncMask, mSemaphoresTemp, numSemaphores);
+
+		mSwapChain->present(queue->getHandle(), mSemaphoresTemp, numSemaphores);
 	}
 
 	void Win32RenderWindowCore::move(INT32 left, INT32 top)