|
|
@@ -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);
|
|
|
+ }
|
|
|
}
|