BsVulkanDescriptorManager.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "BsVulkanDescriptorManager.h"
  4. #include "BsVulkanDescriptorLayout.h"
  5. #include "BsVulkanDescriptorSet.h"
  6. #include "BsVulkanDescriptorPool.h"
  7. #include "BsVulkanDevice.h"
  8. #include "BsVulkanResource.h"
  9. namespace BansheeEngine
  10. {
  11. VulkanLayoutKey::VulkanLayoutKey(VkDescriptorSetLayoutBinding* bindings, UINT32 numBindings)
  12. :bindings(bindings), numBindings(numBindings)
  13. { }
  14. bool VulkanLayoutKey::operator==(const VulkanLayoutKey& rhs) const
  15. {
  16. // If both have a layout, use that to compare directly, otherwise do it per-binding
  17. if (layout != nullptr && rhs.layout != nullptr)
  18. return layout == rhs.layout;
  19. if (numBindings != rhs.numBindings)
  20. return false;
  21. for (UINT32 i = 0; i < numBindings; i++)
  22. {
  23. if (bindings[i].binding != rhs.bindings[i].binding)
  24. return false;
  25. if (bindings[i].descriptorType != rhs.bindings[i].descriptorType)
  26. return false;
  27. if (bindings[i].descriptorCount != rhs.bindings[i].descriptorCount)
  28. return false;
  29. if (bindings[i].stageFlags != rhs.bindings[i].stageFlags)
  30. return false;
  31. }
  32. return true;
  33. }
  34. VulkanDescriptorManager::VulkanDescriptorManager(VulkanDevice& device)
  35. :mDevice(device)
  36. {
  37. mPools.push_back(bs_new<VulkanDescriptorPool>(device));
  38. }
  39. VulkanDescriptorManager::~VulkanDescriptorManager()
  40. {
  41. for (auto& entry : mLayouts)
  42. {
  43. bs_delete(entry.layout);
  44. bs_free(entry.bindings);
  45. }
  46. for (auto& entry : mPools)
  47. bs_delete(entry);
  48. }
  49. VulkanDescriptorLayout* VulkanDescriptorManager::getLayout(VkDescriptorSetLayoutBinding* bindings, UINT32 numBindings)
  50. {
  51. VulkanLayoutKey key(bindings, numBindings);
  52. auto iterFind = mLayouts.find(key);
  53. if (iterFind != mLayouts.end())
  54. return iterFind->layout;
  55. // Create new
  56. key.bindings = bs_allocN<VkDescriptorSetLayoutBinding>(numBindings);
  57. memcpy(key.bindings, bindings, numBindings * sizeof(VkDescriptorSetLayoutBinding));
  58. key.layout = bs_new<VulkanDescriptorLayout>(mDevice, key.bindings, numBindings);
  59. mLayouts.insert(key);
  60. return key.layout;
  61. }
  62. VulkanDescriptorSet* VulkanDescriptorManager::createSet(VulkanDescriptorLayout* layout)
  63. {
  64. // Note: We always retrieve the last created pool, even though there could be free room in earlier pools. However
  65. // that requires additional tracking. Since the assumption is that the first pool will be large enough for all
  66. // descriptors, and the only reason to create a second pool is fragmentation, this approach should not result in
  67. // a major resource waste.
  68. VkDescriptorSetLayout setLayout = layout->getHandle();
  69. VkDescriptorSetAllocateInfo allocateInfo;
  70. allocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
  71. allocateInfo.pNext = nullptr;
  72. allocateInfo.descriptorPool = mPools.back()->getHandle();
  73. allocateInfo.descriptorSetCount = 1;
  74. allocateInfo.pSetLayouts = &setLayout;
  75. VkDescriptorSet set;
  76. VkResult result = vkAllocateDescriptorSets(mDevice.getLogical(), &allocateInfo, &set);
  77. if(result < 0) // Possible fragmentation, try in a new pool
  78. {
  79. mPools.push_back(bs_new<VulkanDescriptorPool>(mDevice));
  80. allocateInfo.descriptorPool = mPools.back()->getHandle();
  81. result = vkAllocateDescriptorSets(mDevice.getLogical(), &allocateInfo, &set);
  82. assert(result == VK_SUCCESS);
  83. }
  84. return mDevice.getResourceManager().create<VulkanDescriptorSet>(set, allocateInfo.descriptorPool);
  85. }
  86. }