Quellcode durchsuchen

Vulkan command buffer creation

BearishSun vor 9 Jahren
Ursprung
Commit
c53b75dbca

+ 2 - 0
Source/BansheeCore/Include/BsCommandBuffer.h

@@ -19,6 +19,8 @@ namespace BansheeEngine
 	class BS_CORE_EXPORT CommandBuffer
 	class BS_CORE_EXPORT CommandBuffer
 	{
 	{
 	public:
 	public:
+		virtual ~CommandBuffer() {}
+
 		/**
 		/**
 		 * Creates a new CommandBuffer.
 		 * Creates a new CommandBuffer.
 		 * 
 		 * 

+ 2 - 0
Source/BansheeCore/Include/BsCommandBufferManager.h

@@ -19,6 +19,8 @@ namespace BansheeEngine
 	class BS_CORE_EXPORT CommandBufferManager : public Module<CommandBufferManager>
 	class BS_CORE_EXPORT CommandBufferManager : public Module<CommandBufferManager>
 	{
 	{
 	public:
 	public:
+		virtual ~CommandBufferManager() {}
+
 		/** @copydoc CommandBuffer::create */
 		/** @copydoc CommandBuffer::create */
 		virtual SPtr<CommandBuffer> create(CommandBufferType type, UINT32 deviceIdx = 0, UINT32 syncMask = 0xFFFFFFFF, 
 		virtual SPtr<CommandBuffer> create(CommandBufferType type, UINT32 deviceIdx = 0, UINT32 syncMask = 0xFFFFFFFF, 
 			bool secondary = false) = 0;
 			bool secondary = false) = 0;

+ 9 - 1
Source/BansheeVulkanRenderAPI/Include/BsVulkanCommandBuffer.h

@@ -16,11 +16,19 @@ namespace BansheeEngine
 	class VulkanCommandBuffer : public CommandBuffer
 	class VulkanCommandBuffer : public CommandBuffer
 	{
 	{
 	public:
 	public:
+		~VulkanCommandBuffer();
+
+		/** Returns the internal Vulkan command buffer wrapped by this object. */
+		VkCommandBuffer getInternal() const { return mBuffer; }
 
 
 	private:
 	private:
 		friend class VulkanCommandBufferManager;
 		friend class VulkanCommandBufferManager;
 
 
-		VulkanCommandBuffer(CommandBufferType type, UINT32 deviceIdx, UINT32 syncMask, bool secondary);
+		VulkanCommandBuffer(const SPtr<VulkanDevice>& device, CommandBufferType type, UINT32 syncMask, bool secondary);
+
+		VkCommandBuffer mBuffer;
+		VkCommandPool mPool;
+		VkDevice mDevice;
 	};
 	};
 
 
 	/** @} */
 	/** @} */

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

@@ -19,9 +19,15 @@ namespace BansheeEngine
 	class VulkanCommandBufferManager : public CommandBufferManager
 	class VulkanCommandBufferManager : public CommandBufferManager
 	{
 	{
 	public:
 	public:
+		VulkanCommandBufferManager(const VulkanRenderAPI& rapi);
+		~VulkanCommandBufferManager();
+
 		/** @copydoc CommandBufferManager::create() */
 		/** @copydoc CommandBufferManager::create() */
 		SPtr<CommandBuffer> create(CommandBufferType type, UINT32 deviceIdx = 0, UINT32 syncMask = 0xFFFFFFFF, 
 		SPtr<CommandBuffer> create(CommandBufferType type, UINT32 deviceIdx = 0, UINT32 syncMask = 0xFFFFFFFF, 
 			bool secondary = false) override;
 			bool secondary = false) override;
+
+	private:
+		const VulkanRenderAPI& mRapi;
 	};
 	};
 
 
 	/** @} */
 	/** @} */

+ 12 - 17
Source/BansheeVulkanRenderAPI/Include/BsVulkanDevice.h

@@ -13,21 +13,6 @@ namespace BansheeEngine
 
 
 #define BS_MAX_VULKAN_QUEUES_PER_TYPE 4
 #define BS_MAX_VULKAN_QUEUES_PER_TYPE 4
 
 
-	 /** Types of GPU queues. */
-	enum VulkanQueueType
-	{
-		/**
-		 * Queue used for rendering. Allows the use of draw commands, but also all commands supported by compute
-		 * or upload buffers.
-		 */
-		VQT_GRAPHICS,
-		/** Discrete queue used for compute operations. Allows the use of dispatch and upload commands. */
-		VQT_COMPUTE,
-		/** Queue used for memory transfer operations only. No rendering or compute dispatch allowed. */
-		VQT_UPLOAD,
-		VQT_COUNT // Keep at end
-	};
-
 	/** Represents a single GPU device usable by Vulkan. */
 	/** Represents a single GPU device usable by Vulkan. */
 	class VulkanDevice
 	class VulkanDevice
 	{
 	{
@@ -53,12 +38,21 @@ namespace BansheeEngine
 		/** Returns the number of queue supported on the device, per type. */
 		/** Returns the number of queue supported on the device, per type. */
 		UINT32 getNumQueues(VulkanQueueType type) const { return (UINT32)mQueueInfos[(int)type].queues.size(); }
 		UINT32 getNumQueues(VulkanQueueType type) const { return (UINT32)mQueueInfos[(int)type].queues.size(); }
 
 
-		/** Returns queue of the specified type at the specified index. Index must be in range [0, getNumQueues()) */
+		/** Returns queue of the specified type at the specified index. Index must be in range [0, getNumQueues()). */
 		VkQueue getQueue(VulkanQueueType type, UINT32 idx) const { return mQueueInfos[(int)type].queues[idx]; }
 		VkQueue getQueue(VulkanQueueType type, UINT32 idx) const { return mQueueInfos[(int)type].queues[idx]; }
 
 
-		/** Returns index of the queue family for the specified queue type. */
+		/** 
+		 * Returns index of the queue family for the specified queue type. Returns -1 if no queues for the specified type 
+		 * exist. There will always be a queue family for the graphics type.
+		 */
 		UINT32 getQueueFamily(VulkanQueueType type) const { return mQueueInfos[(int)type].familyIdx; }
 		UINT32 getQueueFamily(VulkanQueueType type) const { return mQueueInfos[(int)type].familyIdx; }
 
 
+		/** 
+		 * Returns a command pool that may be used for allocating command buffers for this queue family. Only the graphics 
+		 * command pool is guaranteed to exist, others may return null.
+		 */
+		VkCommandPool getCommandPool(VulkanQueueType type) const { return mQueueInfos[(int)type].commandPool; }
+
 		/** Allocates memory for the provided image, and binds it to the image. */
 		/** Allocates memory for the provided image, and binds it to the image. */
 		VkDeviceMemory allocateMemory(VkImage image, VkMemoryPropertyFlags flags);
 		VkDeviceMemory allocateMemory(VkImage image, VkMemoryPropertyFlags flags);
 
 
@@ -87,6 +81,7 @@ namespace BansheeEngine
 		{
 		{
 			UINT32 familyIdx;
 			UINT32 familyIdx;
 			Vector<VkQueue> queues;
 			Vector<VkQueue> queues;
+			VkCommandPool commandPool;
 		};
 		};
 
 
 		QueueInfo mQueueInfos[VQT_COUNT];
 		QueueInfo mQueueInfos[VQT_COUNT];

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

@@ -45,6 +45,21 @@ namespace BansheeEngine
 	{
 	{
 		RenderStatObject_PipelineState = 100
 		RenderStatObject_PipelineState = 100
 	};
 	};
+
+	/** Types of GPU queues. */
+	enum VulkanQueueType
+	{
+		/**
+		 * Queue used for rendering. Allows the use of draw commands, but also all commands supported by compute
+		 * or upload buffers.
+		 */
+		VQT_GRAPHICS,
+		/** Discrete queue used for compute operations. Allows the use of dispatch and upload commands. */
+		VQT_COMPUTE,
+		/** Queue used for memory transfer operations only. No rendering or compute dispatch allowed. */
+		VQT_UPLOAD,
+		VQT_COUNT // Keep at end
+	};
 }
 }
 
 
 // Macro to get a procedure address based on a Vulkan instance.
 // Macro to get a procedure address based on a Vulkan instance.

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

@@ -54,6 +54,9 @@ namespace BansheeEngine
 
 
 		/** Gets Vulkan flags representing the number of samples in an image. Sample count must be a power of 2. */
 		/** Gets Vulkan flags representing the number of samples in an image. Sample count must be a power of 2. */
 		static VkSampleCountFlagBits getSampleFlags(UINT32 numSamples);
 		static VkSampleCountFlagBits getSampleFlags(UINT32 numSamples);
+
+		/** Converts between a command buffer type and a Vulkan queue type. */
+		static VulkanQueueType getQueueType(CommandBufferType type);
 	};
 	};
 
 
 	/** @} */
 	/** @} */

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

@@ -1,10 +1,34 @@
 //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
 //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
 //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
 //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
 #include "BsVulkanCommandBuffer.h"
 #include "BsVulkanCommandBuffer.h"
+#include "BsVulkanUtility.h"
+#include "BsVulkanDevice.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
-	VulkanCommandBuffer::VulkanCommandBuffer(CommandBufferType type, UINT32 deviceIdx, UINT32 syncMask, bool secondary)
+	VulkanCommandBuffer::VulkanCommandBuffer(const SPtr<VulkanDevice>& device, CommandBufferType type, UINT32 syncMask, 
+		bool secondary)
 		: CommandBuffer(type, syncMask, secondary)
 		: CommandBuffer(type, syncMask, secondary)
-	{ }
+	{
+		VulkanQueueType queueType = VulkanUtility::getQueueType(type);
+		mDevice = device->getLogical();
+		mPool = device->getCommandPool(queueType);
+
+		if(mPool == VK_NULL_HANDLE)
+			mPool = device->getCommandPool(VQT_GRAPHICS); // Graphics queue is guaranteed to exist
+
+		VkCommandBufferAllocateInfo bufferInfo = {};
+		bufferInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
+		bufferInfo.commandPool = mPool;
+		bufferInfo.level = secondary ? VK_COMMAND_BUFFER_LEVEL_SECONDARY : VK_COMMAND_BUFFER_LEVEL_PRIMARY;
+		bufferInfo.commandBufferCount = 1;
+
+		VkResult result = vkAllocateCommandBuffers(mDevice, &bufferInfo, &mBuffer);
+		assert(result == VK_SUCCESS);
+	}
+
+	VulkanCommandBuffer::~VulkanCommandBuffer()
+	{
+		vkFreeCommandBuffers(mDevice, mPool, 1, &mBuffer);
+	}
 }
 }

+ 22 - 1
Source/BansheeVulkanRenderAPI/Source/BsVulkanCommandBufferManager.cpp

@@ -2,14 +2,35 @@
 //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
 //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
 #include "BsVulkanCommandBufferManager.h"
 #include "BsVulkanCommandBufferManager.h"
 #include "BsVulkanCommandBuffer.h"
 #include "BsVulkanCommandBuffer.h"
+#include "BsVulkanRenderAPI.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
+	VulkanCommandBufferManager::VulkanCommandBufferManager(const VulkanRenderAPI& rapi)
+		:mRapi(rapi)
+	{ }
+
+	VulkanCommandBufferManager::~VulkanCommandBufferManager()
+	{
+		
+	}
+
 	SPtr<CommandBuffer> VulkanCommandBufferManager::create(CommandBufferType type, UINT32 deviceIdx, UINT32 syncMask,
 	SPtr<CommandBuffer> VulkanCommandBufferManager::create(CommandBufferType type, UINT32 deviceIdx, UINT32 syncMask,
 		bool secondary)
 		bool secondary)
 	{
 	{
+		UINT32 numDevices = mRapi._getNumDevices();
+		if(deviceIdx >= numDevices)
+		{
+			LOGERR("Cannot create command buffer, invalid device index: " + toString(deviceIdx) + 
+				". Valid range: [0, " + toString(numDevices) + ").");
+
+			return nullptr;
+		}
+
+		SPtr<VulkanDevice> device = mRapi._getDevice(deviceIdx);
+
 		CommandBuffer* buffer = 
 		CommandBuffer* buffer = 
-			new (bs_alloc<VulkanCommandBuffer>()) VulkanCommandBuffer(type, deviceIdx, syncMask, secondary);
+			new (bs_alloc<VulkanCommandBuffer>()) VulkanCommandBuffer(device, type, syncMask, secondary);
 
 
 		return bs_shared_ptr(buffer);
 		return bs_shared_ptr(buffer);
 	}
 	}

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

@@ -7,6 +7,10 @@ namespace BansheeEngine
 	VulkanDevice::VulkanDevice(VkPhysicalDevice device)
 	VulkanDevice::VulkanDevice(VkPhysicalDevice device)
 		:mPhysicalDevice(device), mLogicalDevice(nullptr), mQueueInfos{}
 		:mPhysicalDevice(device), mLogicalDevice(nullptr), mQueueInfos{}
 	{
 	{
+		// Set to default
+		for (UINT32 i = 0; i < VQT_COUNT; i++)
+			mQueueInfos[i].familyIdx = (UINT32)-1;
+
 		vkGetPhysicalDeviceProperties(device, &mDeviceProperties);
 		vkGetPhysicalDeviceProperties(device, &mDeviceProperties);
 		vkGetPhysicalDeviceFeatures(device, &mDeviceFeatures);
 		vkGetPhysicalDeviceFeatures(device, &mDeviceFeatures);
 		vkGetPhysicalDeviceMemoryProperties(device, &mMemoryProperties);
 		vkGetPhysicalDeviceMemoryProperties(device, &mMemoryProperties);
@@ -95,11 +99,35 @@ namespace BansheeEngine
 			for(UINT32 j = 0; j < numQueues; j++)
 			for(UINT32 j = 0; j < numQueues; j++)
 				vkGetDeviceQueue(mLogicalDevice, mQueueInfos[i].familyIdx, j, &mQueueInfos[i].queues[j]);
 				vkGetDeviceQueue(mLogicalDevice, mQueueInfos[i].familyIdx, j, &mQueueInfos[i].queues[j]);
 		}
 		}
+
+		// Create command buffer pools
+		for (UINT32 i = 0; i < VQT_COUNT; i++)
+		{
+			if (mQueueInfos[i].familyIdx == (UINT32)-1)
+				continue;
+
+			VkCommandPoolCreateInfo poolInfo;
+			poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
+			poolInfo.pNext = nullptr;
+			poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
+			poolInfo.queueFamilyIndex = mQueueInfos[i].familyIdx;
+
+			vkCreateCommandPool(mLogicalDevice, &poolInfo, gVulkanAllocator, &mQueueInfos[i].commandPool);
+		}
 	}
 	}
 
 
 	VulkanDevice::~VulkanDevice()
 	VulkanDevice::~VulkanDevice()
 	{
 	{
 		vkDeviceWaitIdle(mLogicalDevice);
 		vkDeviceWaitIdle(mLogicalDevice);
+
+		for (UINT32 i = 0; i < VQT_COUNT; i++)
+		{
+			if (mQueueInfos[i].commandPool == VK_NULL_HANDLE)
+				continue;
+
+			vkDestroyCommandPool(mLogicalDevice, mQueueInfos[i].commandPool, gVulkanAllocator);
+		}
+
 		vkDestroyDevice(mLogicalDevice, gVulkanAllocator);
 		vkDestroyDevice(mLogicalDevice, gVulkanAllocator);
 	}
 	}
 
 

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

@@ -12,6 +12,7 @@
 #include "BsGpuProgramManager.h"
 #include "BsGpuProgramManager.h"
 #include "BsVulkanQueryManager.h"
 #include "BsVulkanQueryManager.h"
 #include "BsVulkanGLSLProgramFactory.h"
 #include "BsVulkanGLSLProgramFactory.h"
+#include "BsVulkanCommandBufferManager.h"
 #include "Win32/BsWin32VideoModeInfo.h"
 #include "Win32/BsWin32VideoModeInfo.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
@@ -211,6 +212,9 @@ namespace BansheeEngine
 		GET_DEVICE_PROC_ADDR(presentDevice, AcquireNextImageKHR);
 		GET_DEVICE_PROC_ADDR(presentDevice, AcquireNextImageKHR);
 		GET_DEVICE_PROC_ADDR(presentDevice, QueuePresentKHR);
 		GET_DEVICE_PROC_ADDR(presentDevice, QueuePresentKHR);
 
 
+		// Create command buffer manager
+		CommandBufferManager::startUp<VulkanCommandBufferManager>(*this);
+
 		// Create the texture manager for use by others		
 		// Create the texture manager for use by others		
 		TextureManager::startUp<VulkanTextureManager>();
 		TextureManager::startUp<VulkanTextureManager>();
 		TextureCoreManager::startUp<VulkanTextureCoreManager>();
 		TextureCoreManager::startUp<VulkanTextureCoreManager>();
@@ -257,6 +261,7 @@ namespace BansheeEngine
 		HardwareBufferManager::shutDown();
 		HardwareBufferManager::shutDown();
 		TextureCoreManager::shutDown();
 		TextureCoreManager::shutDown();
 		TextureManager::shutDown();
 		TextureManager::shutDown();
+		CommandBufferManager::shutDown();
 
 
 		mPrimaryDevices.clear();
 		mPrimaryDevices.clear();
 		mDevices.clear();
 		mDevices.clear();

+ 16 - 0
Source/BansheeVulkanRenderAPI/Source/BsVulkanUtility.cpp

@@ -401,4 +401,20 @@ namespace BansheeEngine
 		// Unsupported type
 		// Unsupported type
 		return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
 		return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
 	}
 	}
+
+	VulkanQueueType VulkanUtility::getQueueType(CommandBufferType type)
+	{
+		switch(type)
+		{
+		case CBT_GRAPHICS:
+			return VQT_GRAPHICS;
+		case CBT_COMPUTE:
+			return VQT_COMPUTE;
+		case CBT_UPLOAD:
+			return VQT_UPLOAD;
+		}
+
+		// Unsupported type
+		return VQT_GRAPHICS;
+	}
 }
 }