CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
Path: blob/master/Common/GPU/Vulkan/VulkanDescSet.cpp
Views: 1401
#include "Common/GPU/Vulkan/VulkanDescSet.h"12VulkanDescSetPool::~VulkanDescSetPool() {3_assert_msg_(descPool_ == VK_NULL_HANDLE, "VulkanDescSetPool %s never destroyed", tag_);4}56void VulkanDescSetPool::Create(VulkanContext *vulkan, const BindingType *bindingTypes, uint32_t bindingTypesCount, uint32_t descriptorCount) {7_assert_msg_(descPool_ == VK_NULL_HANDLE, "VulkanDescSetPool::Create when already exists");89vulkan_ = vulkan;10info_ = { VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO };11info_.maxSets = descriptorCount;12_dbg_assert_(sizes_.empty());1314uint32_t storageImageCount = 0;15uint32_t storageBufferCount = 0;16uint32_t combinedImageSamplerCount = 0;17uint32_t uniformBufferDynamicCount = 0;18for (uint32_t i = 0; i < bindingTypesCount; i++) {19switch (bindingTypes[i]) {20case BindingType::COMBINED_IMAGE_SAMPLER: combinedImageSamplerCount++; break;21case BindingType::UNIFORM_BUFFER_DYNAMIC_VERTEX:22case BindingType::UNIFORM_BUFFER_DYNAMIC_ALL: uniformBufferDynamicCount++; break;23case BindingType::STORAGE_BUFFER_VERTEX:24case BindingType::STORAGE_BUFFER_COMPUTE: storageBufferCount++; break;25case BindingType::STORAGE_IMAGE_COMPUTE: storageImageCount++; break;26}27}28if (combinedImageSamplerCount) {29sizes_.push_back(VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, combinedImageSamplerCount * descriptorCount });30}31if (uniformBufferDynamicCount) {32sizes_.push_back(VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, uniformBufferDynamicCount * descriptorCount });33}34if (storageBufferCount) {35sizes_.push_back(VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, storageBufferCount * descriptorCount });36}37if (storageImageCount) {38sizes_.push_back(VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, storageImageCount * descriptorCount });39}40VkResult res = Recreate(false);41_assert_msg_(res == VK_SUCCESS, "Could not create VulkanDescSetPool %s", tag_);42}4344bool VulkanDescSetPool::Allocate(VkDescriptorSet *descriptorSets, int count, const VkDescriptorSetLayout *layouts) {45if (descPool_ == VK_NULL_HANDLE || usage_ + count >= info_.maxSets) {46// Missing or out of space, need to recreate.47VkResult res = Recreate(grow_);48_assert_msg_(res == VK_SUCCESS, "Could not grow VulkanDescSetPool %s on usage %d", tag_, (int)usage_);49}5051VkDescriptorSetAllocateInfo descAlloc{ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO };52descAlloc.descriptorPool = descPool_;53descAlloc.descriptorSetCount = count;54descAlloc.pSetLayouts = layouts;55VkResult result = vkAllocateDescriptorSets(vulkan_->GetDevice(), &descAlloc, descriptorSets);5657if (result == VK_ERROR_FRAGMENTED_POOL || result < 0) {58WARN_LOG(Log::G3D, "Pool %s %s - recreating", tag_, result == VK_ERROR_FRAGMENTED_POOL ? "fragmented" : "full");59// There seems to have been a spec revision. Here we should apparently recreate the descriptor pool,60// so let's do that. See https://www.khronos.org/registry/vulkan/specs/1.0/man/html/vkAllocateDescriptorSets.html61// Fragmentation shouldn't really happen though since we wipe the pool every frame.62VkResult res = Recreate(false);63_assert_msg_(res == VK_SUCCESS, "Ran out of descriptor space (frag?) and failed to recreate a descriptor pool. sz=%d res=%d", usage_, (int)res);6465// Need to update this pointer since we have allocated a new one.66descAlloc.descriptorPool = descPool_;67result = vkAllocateDescriptorSets(vulkan_->GetDevice(), &descAlloc, descriptorSets);68_assert_msg_(result == VK_SUCCESS, "Ran out of descriptor space (frag?) and failed to allocate after recreating a descriptor pool. res=%d", (int)result);69}7071if (result != VK_SUCCESS) {72return false;73}7475usage_ += count;76return true;77}7879void VulkanDescSetPool::Reset() {80_assert_msg_(descPool_ != VK_NULL_HANDLE, "VulkanDescSetPool::Reset without valid pool");81vkResetDescriptorPool(vulkan_->GetDevice(), descPool_, 0);8283usage_ = 0;84}8586void VulkanDescSetPool::Destroy() {87if (descPool_ != VK_NULL_HANDLE) {88vulkan_->Delete().QueueDeleteDescriptorPool(descPool_);89usage_ = 0;90}91sizes_.clear();92}9394void VulkanDescSetPool::DestroyImmediately() {95if (descPool_ != VK_NULL_HANDLE) {96vkDestroyDescriptorPool(vulkan_->GetDevice(), descPool_, nullptr);97descPool_ = VK_NULL_HANDLE;98usage_ = 0;99}100sizes_.clear();101}102103VkResult VulkanDescSetPool::Recreate(bool grow) {104_assert_msg_(vulkan_ != nullptr, "VulkanDescSetPool::Recreate without VulkanContext");105106uint32_t prevSize = info_.maxSets;107if (grow) {108info_.maxSets *= 2;109for (auto &size : sizes_)110size.descriptorCount *= 2;111}112113// Delete the pool if it already exists.114if (descPool_ != VK_NULL_HANDLE) {115INFO_LOG(Log::G3D, "Reallocating %s desc pool from %d to %d", tag_, prevSize, info_.maxSets);116vulkan_->Delete().QueueDeleteDescriptorPool(descPool_);117usage_ = 0;118}119120info_.pPoolSizes = &sizes_[0];121info_.poolSizeCount = (uint32_t)sizes_.size();122123VkResult result = vkCreateDescriptorPool(vulkan_->GetDevice(), &info_, nullptr, &descPool_);124if (result == VK_SUCCESS) {125vulkan_->SetDebugName(descPool_, VK_OBJECT_TYPE_DESCRIPTOR_POOL, tag_);126}127return result;128}129130131