BearishSun 9 лет назад
Родитель
Сommit
ce07bf692b

+ 2 - 0
Source/BansheeVulkanRenderAPI/CMakeSources.cmake

@@ -26,6 +26,7 @@ set(BS_BANSHEEVULKANRENDERAPI_INC_NOFILTER
 	"Include/BsVulkanDescriptorLayout.h"
 	"Include/BsVulkanResource.h"
 	"Include/BsVulkanQueue.h"
+	"Include/BsVulkanDescriptorSet.h"
 )
 
 set(BS_BANSHEEVULKANRENDERAPI_INC_MANAGERS
@@ -69,6 +70,7 @@ set(BS_BANSHEEVULKANRENDERAPI_SRC_NOFILTER
 	"Source/BsVulkanDescriptorLayout.cpp"
 	"Source/BsVulkanResource.cpp"
 	"Source/BsVulkanQueue.cpp"
+	"Source/BsVulkanDescriptorSet.cpp"
 )
 
 set(BS_BANSHEEVULKANRENDERAPI_SRC_MANAGERS

+ 7 - 0
Source/BansheeVulkanRenderAPI/Include/BsVulkanDescriptorLayout.h

@@ -20,9 +20,16 @@ namespace BansheeEngine
 		/** Returns a handle to the Vulkan set layout object. */
 		VkDescriptorSetLayout getHandle() const { return mLayout; }
 
+		/** Returns a hash value for the descriptor layout. */
+		size_t getHash() const { return mHash; }
+
+		/** Calculates a has value for the provided descriptor set layout bindings. */
+		static size_t calculateHash(VkDescriptorSetLayoutBinding* bindings, UINT32 numBindings);
+
 	protected:
 		VulkanDevice& mDevice;
 		VkDescriptorSetLayout mLayout;
+		size_t mHash;
 	};
 
 	/** @} */

+ 10 - 5
Source/BansheeVulkanRenderAPI/Include/BsVulkanDescriptorManager.h

@@ -3,6 +3,7 @@
 #pragma once
 
 #include "BsVulkanPrerequisites.h"
+#include "BsVulkanDescriptorLayout.h"
 
 namespace BansheeEngine
 {
@@ -14,9 +15,6 @@ namespace BansheeEngine
 		/** Compares two descriptor layouts. */
 		bool operator==(const VulkanLayoutKey& rhs) const;
 
-		/** Calculates a hash value for a descriptor layout. */
-		size_t calculateHash() const;
-
 		UINT32 numBindings;
 		VkDescriptorSetLayoutBinding* bindings;
 
@@ -37,7 +35,10 @@ namespace std
 	{
 		size_t operator()(const BansheeEngine::VulkanLayoutKey& value) const
 		{
-			return (size_t)value.calculateHash();
+			if (value.layout != nullptr)
+				return value.layout->getHash();
+
+			return BansheeEngine::VulkanDescriptorLayout::calculateHash(value.bindings, value.numBindings);
 		}
 	};
 }
@@ -61,10 +62,14 @@ namespace BansheeEngine
 		/** Attempts to find an existing one, or allocates a new descriptor set layout from the provided set of bindings. */
 		VulkanDescriptorLayout* getLayout(VkDescriptorSetLayoutBinding* bindings, UINT32 numBindings);
 
+		/** Allocates a new empty descriptor set matching the provided layout. */
+		VulkanDescriptorSet* createSet(VulkanDescriptorLayout* layout);
+
 	protected:
 		VulkanDevice& mDevice;
 
-		UnorderedMap<VulkanLayoutKey, UINT32> mSets; // TODO - Just dummy value for now, keep a list of sets here normally
+		UnorderedSet<VulkanLayoutKey> mLayouts; 
+		Vector<VulkanDescriptorPool*> mPools;
 	};
 
 	/** @} */

+ 33 - 0
Source/BansheeVulkanRenderAPI/Include/BsVulkanDescriptorSet.h

@@ -0,0 +1,33 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsVulkanPrerequisites.h"
+#include "BsVulkanResource.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Vulkan
+	 *  @{
+	 */
+
+	/** Wrapper for the Vulkan descriptor set object. */
+	class VulkanDescriptorSet : public VulkanResource
+	{
+	public:
+		VulkanDescriptorSet(VulkanResourceManager* owner, VkDescriptorSet set, VkDescriptorPool pool);
+		~VulkanDescriptorSet();
+
+		/** Returns a handle to the Vulkan descriptor set object. */
+		VkDescriptorSet getHandle() const { return mSet; }
+
+		/** Updates the descriptor set with the provided values. */
+		void write(VkWriteDescriptorSet* entries, UINT32 count);
+
+	protected:
+		VkDescriptorSet mSet;
+		VkDescriptorPool mPool;
+	};
+
+	/** @} */
+}

+ 1 - 0
Source/BansheeVulkanRenderAPI/Include/BsVulkanGpuParams.h

@@ -48,6 +48,7 @@ namespace BansheeEngine
 		struct PerSetData
 		{
 			VulkanDescriptorLayout* layout;
+			VulkanDescriptorSet* set;
 
 			VkWriteDescriptorSet* writeSetInfos;
 			WriteInfo* writeInfos;

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

@@ -38,6 +38,7 @@ namespace BansheeEngine
 	class VulkanGLSLProgramFactory;
 	class VulkanSwapChain;
 	class VulkanDescriptorLayout;
+	class VulkanDescriptorSet;
 	class VulkanDescriptorManager;
 	class VulkanCmdBufferPool;
 	class VulkanCmdBuffer;
@@ -46,6 +47,7 @@ namespace BansheeEngine
 	class VulkanResourceManager;
 	class VulkanGpuParamBlockBufferCore;
 	class VulkanBuffer;
+	class VulkanDescriptorPool;
 
 	VkAllocationCallbacks* gVulkanAllocator = nullptr;
 

+ 8 - 4
Source/BansheeVulkanRenderAPI/Include/BsVulkanResource.h

@@ -95,18 +95,17 @@ namespace BansheeEngine
 	class VulkanResourceManager
 	{
 	public:
+		VulkanResourceManager(VulkanDevice& device);
 		~VulkanResourceManager();
 
 		/** 
 		 * Creates a new Vulkan resource of the specified type. User must call VulkanResource::destroy() when done using
 		 * the resource. 
-		 * 
-		 * @param[in]	concurrency		If true, the resource is allowed to be used on multiple queue types at once.
 		 */
 		template<class Type, class... Args>
-		VulkanResource* create(bool concurrency, Args &&...args)
+		Type* create(Args &&...args)
 		{
-			VulkanResource* resource = new (bs_alloc(sizeof(Type))) Type(this, concurrency, std::forward<Args>(args)...);
+			Type* resource = new (bs_alloc(sizeof(Type))) Type(this, std::forward<Args>(args)...);
 
 #if BS_DEBUG_MODE
 			mResources.insert(resource);
@@ -115,6 +114,9 @@ namespace BansheeEngine
 			return resource;
 		}
 
+		/** Returns the device that owns this manager. */
+		VulkanDevice& getDevice() const { return mDevice; }
+
 	private:
 		friend VulkanResource;
 
@@ -124,6 +126,8 @@ namespace BansheeEngine
 		 */
 		void destroy(VulkanResource* resource);
 
+		VulkanDevice& mDevice;
+
 #if BS_DEBUG_MODE
 		UnorderedSet<VulkanResource*> mResources;
 #endif

+ 20 - 0
Source/BansheeVulkanRenderAPI/Source/BsVulkanDescriptorLayout.cpp

@@ -7,6 +7,8 @@ namespace BansheeEngine
 		UINT32 numBindings)
 		:mDevice(device)
 	{
+		mHash = calculateHash(bindings, numBindings);
+
 		VkDescriptorSetLayoutCreateInfo layoutCI;
 		layoutCI.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
 		layoutCI.pNext = nullptr;
@@ -22,4 +24,22 @@ namespace BansheeEngine
 	{
 		vkDestroyDescriptorSetLayout(mDevice.getLogical(), mLayout, gVulkanAllocator);
 	}
+
+	size_t VulkanDescriptorLayout::calculateHash(VkDescriptorSetLayoutBinding* bindings, UINT32 numBindings)
+	{
+		size_t hash = 0;
+		for (UINT32 i = 0; i < numBindings; i++)
+		{
+			size_t bindingHash = 0;
+			hash_combine(bindingHash, bindings[i].binding);
+			hash_combine(bindingHash, bindings[i].descriptorCount);
+			hash_combine(bindingHash, bindings[i].descriptorType);
+			hash_combine(bindingHash, bindings[i].stageFlags);
+			assert(bindings[i].pImmutableSamplers == nullptr); // Not accounted for in hash, assumed always null
+
+			hash_combine(hash, bindingHash);
+		}
+
+		return hash;
+	}
 }

+ 46 - 27
Source/BansheeVulkanRenderAPI/Source/BsVulkanDescriptorManager.cpp

@@ -2,6 +2,9 @@
 //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
 #include "BsVulkanDescriptorManager.h"
 #include "BsVulkanDescriptorLayout.h"
+#include "BsVulkanDescriptorPool.h"
+#include "BsVulkanDevice.h"
+#include "BsVulkanResource.h"
 
 namespace BansheeEngine
 {
@@ -11,6 +14,10 @@ namespace BansheeEngine
 
 	bool VulkanLayoutKey::operator==(const VulkanLayoutKey& rhs) const
 	{
+		// If both have a layout, use that to compare directly, otherwise do it per-binding
+		if (layout != nullptr && rhs.layout != nullptr)
+			return layout == rhs.layout;
+
 		if (numBindings != rhs.numBindings)
 			return false;
 
@@ -32,56 +39,68 @@ namespace BansheeEngine
 		return true;
 	}
 
-	size_t VulkanLayoutKey::calculateHash() const
-	{
-		size_t hash = 0;
-		for (UINT32 i = 0; i < numBindings; i++)
-		{
-			size_t bindingHash = 0;
-			hash_combine(bindingHash, bindings[i].binding);
-			hash_combine(bindingHash, bindings[i].descriptorCount);
-			hash_combine(bindingHash, bindings[i].descriptorType);
-			hash_combine(bindingHash, bindings[i].stageFlags);
-			assert(bindings[i].pImmutableSamplers == nullptr); // Not accounted for in hash, assumed always null
-
-			hash_combine(hash, bindingHash);
-		}
-
-		return hash;
-	}
-
 	VulkanDescriptorManager::VulkanDescriptorManager(VulkanDevice& device)
 		:mDevice(device)
 	{
-
+		mPools.push_back(bs_new<VulkanDescriptorPool>(device));
 	}
 
 	VulkanDescriptorManager::~VulkanDescriptorManager()
 	{
-		for (auto& entry : mSets)
+		for (auto& entry : mLayouts)
 		{
-			bs_delete(entry.first.layout);
-			bs_free(entry.first.bindings);
+			bs_delete(entry.layout);
+			bs_free(entry.bindings);
 		}
 
-		// TODO - Ensure all sets get released
+		for (auto& entry : mPools)
+			bs_delete(entry);
 	}
 
 	VulkanDescriptorLayout* VulkanDescriptorManager::getLayout(VkDescriptorSetLayoutBinding* bindings, UINT32 numBindings)
 	{
 		VulkanLayoutKey key(bindings, numBindings);
 
-		auto iterFind = mSets.find(key);
-		if (iterFind != mSets.end())
-			return iterFind->first.layout;
+		auto iterFind = mLayouts.find(key);
+		if (iterFind != mLayouts.end())
+			return iterFind->layout;
 
 		// Create new
 		key.bindings = bs_allocN<VkDescriptorSetLayoutBinding>(numBindings);
 		memcpy(key.bindings, bindings, numBindings * sizeof(VkDescriptorSetLayoutBinding));
 
 		key.layout = bs_new<VulkanDescriptorLayout>(mDevice, key.bindings, numBindings);
-		mSets.insert(std::make_pair(key, 0));
+		mLayouts.insert(key);
 		
 		return key.layout;
 	}
+
+	VulkanDescriptorSet* VulkanDescriptorManager::createSet(VulkanDescriptorLayout* layout)
+	{
+		// Note: We always retrieve the last created pool, even though there could be free room in earlier pools. However
+		// that requires additional tracking. Since the assumption is that the first pool will be large enough for all
+		// descriptors, and the only reason to create a second pool is fragmentation, this approach should not result in
+		// a major resource waste.
+		VkDescriptorSetLayout setLayout = layout->getHandle();
+
+		VkDescriptorSetAllocateInfo allocateInfo;
+		allocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
+		allocateInfo.pNext = nullptr;
+		allocateInfo.descriptorPool = mPools.back()->getHandle();
+		allocateInfo.descriptorSetCount = 1;
+		allocateInfo.pSetLayouts = &setLayout;
+
+		VkDescriptorSet set;
+		VkResult result = vkAllocateDescriptorSets(mDevice.getLogical(), &allocateInfo, &set);
+		if(result < 0) // Possible fragmentation, try in a new pool
+		{
+			mPools.push_back(bs_new<VulkanDescriptorPool>(mDevice));
+			allocateInfo.descriptorPool = mPools.back()->getHandle();
+
+			result = vkAllocateDescriptorSets(mDevice.getLogical(), &allocateInfo, &set);
+			assert(result == VK_SUCCESS);
+		}
+
+		return mDevice.getResourceManager().create<VulkanDescriptorSet>(set, allocateInfo.descriptorPool);
+	}
 }

+ 5 - 7
Source/BansheeVulkanRenderAPI/Source/BsVulkanDescriptorPool.cpp

@@ -8,26 +8,24 @@ namespace BansheeEngine
 	VulkanDescriptorPool::VulkanDescriptorPool(VulkanDevice& device)
 		:mDevice(device)
 	{
-		const VkPhysicalDeviceLimits& limits = device.getDeviceProperties().limits;
-
 		VkDescriptorPoolSize poolSizes[4];
 		poolSizes[0].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
-		poolSizes[0].descriptorCount = std::min(limits.maxPerStageDescriptorSampledImages, sMaxSampledImages);
+		poolSizes[0].descriptorCount = sMaxSampledImages;
 
 		poolSizes[1].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
-		poolSizes[1].descriptorCount = std::min(limits.maxPerStageDescriptorUniformBuffers, sMaxUniformBuffers);
+		poolSizes[1].descriptorCount = sMaxUniformBuffers;
 
 		poolSizes[2].type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
-		poolSizes[2].descriptorCount = std::min(limits.maxPerStageDescriptorStorageImages, sMaxImages);
+		poolSizes[2].descriptorCount = sMaxImages;
 
 		poolSizes[3].type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
-		poolSizes[3].descriptorCount = std::min(limits.maxPerStageDescriptorStorageBuffers, sMaxBuffers);
+		poolSizes[3].descriptorCount = sMaxBuffers;
 
 		VkDescriptorPoolCreateInfo poolCI;
 		poolCI.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
 		poolCI.pNext = nullptr;
 		poolCI.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
-		poolCI.maxSets = std::min(limits.maxBoundDescriptorSets, sMaxSets);
+		poolCI.maxSets = sMaxSets;
 		poolCI.poolSizeCount = sizeof(poolSizes)/sizeof(poolSizes[0]);
 		poolCI.pPoolSizes = poolSizes;
 

+ 25 - 0
Source/BansheeVulkanRenderAPI/Source/BsVulkanDescriptorSet.cpp

@@ -0,0 +1,25 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#include "BsVulkanDescriptorSet.h"
+#include "BsVulkanDevice.h"
+
+namespace BansheeEngine
+{
+	VulkanDescriptorSet::VulkanDescriptorSet(VulkanResourceManager* owner, VkDescriptorSet set, VkDescriptorPool pool)
+		:VulkanResource(owner, true), mSet(set), mPool(pool)
+	{ }
+
+	VulkanDescriptorSet::~VulkanDescriptorSet()
+	{
+		VkResult result = vkFreeDescriptorSets(mOwner->getDevice().getLogical(), mPool, 1, &mSet);
+		assert(result == VK_SUCCESS);
+	}
+
+	void VulkanDescriptorSet::write(VkWriteDescriptorSet* entries, UINT32 count)
+	{
+		for (UINT32 i = 0; i < count; i++)
+			entries[i].dstSet = mSet;
+
+		vkUpdateDescriptorSets(mOwner->getDevice().getLogical(), count, entries, 0, nullptr);
+	}
+}

+ 1 - 1
Source/BansheeVulkanRenderAPI/Source/BsVulkanDevice.cpp

@@ -111,7 +111,7 @@ namespace BansheeEngine
 		// Create pools/managers
 		mCommandBufferPool = bs_new<VulkanCmdBufferPool>(*this);
 		mDescriptorManager = bs_new<VulkanDescriptorManager>(*this);
-		mResourceManager = bs_new<VulkanResourceManager>();
+		mResourceManager = bs_new<VulkanResourceManager>(*this);
 	}
 
 	VulkanDevice::~VulkanDevice()

+ 7 - 9
Source/BansheeVulkanRenderAPI/Source/BsVulkanGpuParams.cpp

@@ -7,6 +7,7 @@
 #include "BsVulkanGpuParamBlockBuffer.h"
 #include "BsVulkanGpuBuffer.h"
 #include "BsVulkanTexture.h"
+#include "BsVulkanDescriptorSet.h"
 #include "BsVulkanSamplerState.h"
 #include "BsGpuParamDesc.h"
 
@@ -156,6 +157,7 @@ namespace BansheeEngine
 
 				VkDescriptorSetLayoutBinding* perSetBindings = &bindings[bindingOffset];
 				perSetData.layout = descManager.getLayout(perSetBindings, numBindingsPerSet);
+				perSetData.set = descManager.createSet(perSetData.layout);
 				perSetData.numElements = numBindingsPerSet;
 
 				for(UINT32 k = 0; k < numBindingsPerSet; k++)
@@ -207,21 +209,17 @@ namespace BansheeEngine
 		bs_stack_free(bindingOffsets);
 		bs_stack_free(bindings);
 		bs_stack_free(bindingsPerSet);
-
-		// TODO - Create sets
-		// TODO - Prepare write descs
-		// TODO - Update write descs as params change
 	}
 
 	VulkanGpuParams::~VulkanGpuParams()
 	{
-		// TODO - Need to wait to ensure it isn't used on the GPU anymore
+		for (UINT32 i = 0; i < mNumDevices; i++)
+		{
+			for (UINT32 j = 0; j < mPerDeviceData[i].numSets; j++)
+				mPerDeviceData[i].perSetData[j].set->destroy();
+		}
 
 		bs_free(mData); // Everything allocated under a single buffer to a single free is enough
-
-		// TODO - CLean up mSets
-		// - Queue for destroy, remember fence counters for all available queues, only destroy after all queues execute?
-		// - Or ensure the object knows which queue it was used on?
 	}
 
 	void VulkanGpuParams::setParamBlockBuffer(UINT32 set, UINT32 slot, const SPtr<GpuParamBlockBufferCore>& paramBlockBuffer)

+ 4 - 0
Source/BansheeVulkanRenderAPI/Source/BsVulkanResource.cpp

@@ -98,6 +98,10 @@ namespace BansheeEngine
 			mOwner->destroy(this);
 	}
 
+	VulkanResourceManager::VulkanResourceManager(VulkanDevice& device)
+		:mDevice(device)
+	{ }
+
 	VulkanResourceManager::~VulkanResourceManager()
 	{
 #if BS_DEBUG_MODE

+ 1 - 1
Source/CMake/Modules/FindVulkan.cmake

@@ -9,7 +9,7 @@
 
 # TODO: Set default install paths for mac/unix
 # TODO: Don't hardcode the version (instead use regex or GLOB to match latest)
-set(Vulkan_INSTALL_DIRS "C:/VulkanSDK/1.0.17.0" CACHE PATH "")
+set(Vulkan_INSTALL_DIRS "C:/VulkanSDK/1.0.30.0" CACHE PATH "")
 set(Vulkan_INCLUDE_SEARCH_DIRS "${Vulkan_INSTALL_DIRS}/Include")
 
 if(BS_64BIT)