瀏覽代碼

VulkanVertexInputManager now thread safe and returns a uniquely identifiable object

BearishSun 9 年之前
父節點
當前提交
1df7760fcc

+ 25 - 3
Source/BansheeVulkanRenderAPI/Include/BsVulkanVertexInputManager.h

@@ -11,6 +11,25 @@ namespace BansheeEngine
 	 *  @{
 	 *  @{
 	 */
 	 */
 
 
+	/** Contains data describing vertex inputs for a graphics pipeline. */
+	class VulkanVertexInput
+	{
+	public:
+		/** Returns an object contining the necessary information to initialize the vertex input on a pipeline. */
+		const VkPipelineVertexInputStateCreateInfo& getCreateInfo() const { return mCreateInfo; }
+
+		/** Returns an identifier which uniquely represents this vertex input configuration. */
+		UINT32 getId() const { return mId; }
+
+	private:
+		friend class VulkanVertexInputManager;
+
+		VulkanVertexInput(UINT32 id, const VkPipelineVertexInputStateCreateInfo& createInfo);
+
+		UINT32 mId;
+		VkPipelineVertexInputStateCreateInfo mCreateInfo;
+	};
+
 	/** 
 	/** 
 	 * Maps vertex buffer structure and vertex shader inputs in order to create vertex input description usable by Vulkan.  
 	 * Maps vertex buffer structure and vertex shader inputs in order to create vertex input description usable by Vulkan.  
 	 */
 	 */
@@ -45,7 +64,7 @@ namespace BansheeEngine
 
 
 			VkVertexInputAttributeDescription* attributes;
 			VkVertexInputAttributeDescription* attributes;
 			VkVertexInputBindingDescription* bindings;
 			VkVertexInputBindingDescription* bindings;
-			VkPipelineVertexInputStateCreateInfo vertexInputCI;
+			SPtr<VulkanVertexInput> vertexInput;
 			UINT32 lastUsedIdx;
 			UINT32 lastUsedIdx;
 		};
 		};
 
 
@@ -60,8 +79,8 @@ namespace BansheeEngine
 		 * @param[in]	shaderDecl	Describes the vertex element inputs expected by a vertex shader.
 		 * @param[in]	shaderDecl	Describes the vertex element inputs expected by a vertex shader.
 		 * @return					Vertex input state description, usable by Vulkan.
 		 * @return					Vertex input state description, usable by Vulkan.
 		 */
 		 */
-		const VkPipelineVertexInputStateCreateInfo& getVertexInfo(const SPtr<VertexDeclarationCore>& vbDecl, 
-			const SPtr<VertexDeclarationCore>& shaderDecl);
+		SPtr<VulkanVertexInput> getVertexInfo(const SPtr<VertexDeclarationCore>& vbDecl,
+											  const SPtr<VertexDeclarationCore>& shaderDecl);
 
 
 	private:
 	private:
 		/**	Creates a vertex input using the specified parameters and stores it in the input layout map. */
 		/**	Creates a vertex input using the specified parameters and stores it in the input layout map. */
@@ -76,8 +95,11 @@ namespace BansheeEngine
 
 
 		UnorderedMap<VertexDeclarationKey, VertexInputEntry*, HashFunc, EqualFunc> mVertexInputMap;
 		UnorderedMap<VertexDeclarationKey, VertexInputEntry*, HashFunc, EqualFunc> mVertexInputMap;
 
 
+		UINT32 mNextId;
 		bool mWarningShown;
 		bool mWarningShown;
 		UINT32 mLastUsedCounter;
 		UINT32 mLastUsedCounter;
+
+		Mutex mMutex;
     };
     };
 
 
 	/** @} */
 	/** @} */

+ 31 - 13
Source/BansheeVulkanRenderAPI/Source/BsVulkanVertexInputManager.cpp

@@ -7,6 +7,10 @@
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
+	VulkanVertexInput::VulkanVertexInput(UINT32 id, const VkPipelineVertexInputStateCreateInfo& createInfo)
+		:mId(id), mCreateInfo(createInfo)
+	{ }
+
 	size_t VulkanVertexInputManager::HashFunc::operator()(const VertexDeclarationKey& key) const
 	size_t VulkanVertexInputManager::HashFunc::operator()(const VertexDeclarationKey& key) const
 	{
 	{
 		size_t hash = 0;
 		size_t hash = 0;
@@ -28,11 +32,18 @@ namespace BansheeEngine
 	}
 	}
 
 
 	VulkanVertexInputManager::VulkanVertexInputManager()
 	VulkanVertexInputManager::VulkanVertexInputManager()
-		:mLastUsedCounter(0), mWarningShown(false)
-	{ }
+	{
+		Lock(mMutex);
+
+		mNextId = 1;
+		mWarningShown = false;
+		mLastUsedCounter = 0;
+	}
 
 
 	VulkanVertexInputManager::~VulkanVertexInputManager()
 	VulkanVertexInputManager::~VulkanVertexInputManager()
 	{
 	{
+		Lock(mMutex);
+
 		while (mVertexInputMap.begin() != mVertexInputMap.end())
 		while (mVertexInputMap.begin() != mVertexInputMap.end())
 		{
 		{
 			auto firstElem = mVertexInputMap.begin();
 			auto firstElem = mVertexInputMap.begin();
@@ -42,9 +53,11 @@ namespace BansheeEngine
 		}
 		}
 	}
 	}
 
 
-	const VkPipelineVertexInputStateCreateInfo& VulkanVertexInputManager::getVertexInfo(
+	SPtr<VulkanVertexInput> VulkanVertexInputManager::getVertexInfo(
 		const SPtr<VertexDeclarationCore>& vbDecl, const SPtr<VertexDeclarationCore>& shaderDecl)
 		const SPtr<VertexDeclarationCore>& vbDecl, const SPtr<VertexDeclarationCore>& shaderDecl)
 	{
 	{
+		Lock(mMutex);
+
 		VertexDeclarationKey pair;
 		VertexDeclarationKey pair;
 		pair.bufferDeclId = vbDecl->getId();
 		pair.bufferDeclId = vbDecl->getId();
 		pair.shaderDeclId = shaderDecl->getId();
 		pair.shaderDeclId = shaderDecl->getId();
@@ -61,7 +74,7 @@ namespace BansheeEngine
 		}
 		}
 
 
 		iterFind->second->lastUsedIdx = ++mLastUsedCounter;
 		iterFind->second->lastUsedIdx = ++mLastUsedCounter;
-		return iterFind->second->vertexInputCI;
+		return iterFind->second->vertexInput;
 	}
 	}
 
 
 	void VulkanVertexInputManager::addNew(const SPtr<VertexDeclarationCore>& vbDecl, 
 	void VulkanVertexInputManager::addNew(const SPtr<VertexDeclarationCore>& vbDecl, 
@@ -106,8 +119,6 @@ namespace BansheeEngine
 		newEntry->bindings = (VkVertexInputBindingDescription*)data;
 		newEntry->bindings = (VkVertexInputBindingDescription*)data;
 		data += bindingBytes;
 		data += bindingBytes;
 
 
-		newEntry->lastUsedIdx = ++mLastUsedCounter;
-
 		for (UINT32 i = 0; i < numBindings; i++)
 		for (UINT32 i = 0; i < numBindings; i++)
 		{
 		{
 			VkVertexInputBindingDescription& binding = newEntry->bindings[i];
 			VkVertexInputBindingDescription& binding = newEntry->bindings[i];
@@ -162,24 +173,31 @@ namespace BansheeEngine
 
 
 		numAttributes = attribIdx; // It's possible some attributes were invalid, in which case we keep the memory allocated but ignore them otherwise
 		numAttributes = attribIdx; // It's possible some attributes were invalid, in which case we keep the memory allocated but ignore them otherwise
 
 
-		newEntry->vertexInputCI.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
-		newEntry->vertexInputCI.pNext = nullptr;
-		newEntry->vertexInputCI.flags = 0;
-		newEntry->vertexInputCI.pVertexBindingDescriptions = newEntry->bindings;
-		newEntry->vertexInputCI.vertexBindingDescriptionCount = numBindings;
-		newEntry->vertexInputCI.pVertexAttributeDescriptions = newEntry->attributes;
-		newEntry->vertexInputCI.vertexAttributeDescriptionCount = numAttributes;
+		VkPipelineVertexInputStateCreateInfo vertexInputCI;
+		vertexInputCI.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
+		vertexInputCI.pNext = nullptr;
+		vertexInputCI.flags = 0;
+		vertexInputCI.pVertexBindingDescriptions = newEntry->bindings;
+		vertexInputCI.vertexBindingDescriptionCount = numBindings;
+		vertexInputCI.pVertexAttributeDescriptions = newEntry->attributes;
+		vertexInputCI.vertexAttributeDescriptionCount = numAttributes;
 
 
 		// Create key and add to the layout map
 		// Create key and add to the layout map
 		VertexDeclarationKey pair;
 		VertexDeclarationKey pair;
 		pair.bufferDeclId = vbDecl->getId();
 		pair.bufferDeclId = vbDecl->getId();
 		pair.shaderDeclId = shaderInputDecl->getId();
 		pair.shaderDeclId = shaderInputDecl->getId();
 
 
+		Lock(mMutex);
+		newEntry->vertexInput = bs_shared_ptr_new<VulkanVertexInput>(mNextId++, vertexInputCI);
+		newEntry->lastUsedIdx = ++mLastUsedCounter;
+
 		mVertexInputMap[pair] = newEntry;
 		mVertexInputMap[pair] = newEntry;
 	}
 	}
 
 
 	void VulkanVertexInputManager::removeLeastUsed()
 	void VulkanVertexInputManager::removeLeastUsed()
 	{
 	{
+		Lock(mMutex);
+
 		if (!mWarningShown)
 		if (!mWarningShown)
 		{
 		{
 			LOGWRN("Vertex input buffer is full, pruning last " + toString(NUM_ELEMENTS_TO_PRUNE) + " elements. This is "
 			LOGWRN("Vertex input buffer is full, pruning last " + toString(NUM_ELEMENTS_TO_PRUNE) + " elements. This is "