CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
hrydgard

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: hrydgard/ppsspp
Path: blob/master/Common/GPU/Vulkan/VulkanDescSet.cpp
Views: 1401
1
#include "Common/GPU/Vulkan/VulkanDescSet.h"
2
3
VulkanDescSetPool::~VulkanDescSetPool() {
4
_assert_msg_(descPool_ == VK_NULL_HANDLE, "VulkanDescSetPool %s never destroyed", tag_);
5
}
6
7
void VulkanDescSetPool::Create(VulkanContext *vulkan, const BindingType *bindingTypes, uint32_t bindingTypesCount, uint32_t descriptorCount) {
8
_assert_msg_(descPool_ == VK_NULL_HANDLE, "VulkanDescSetPool::Create when already exists");
9
10
vulkan_ = vulkan;
11
info_ = { VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO };
12
info_.maxSets = descriptorCount;
13
_dbg_assert_(sizes_.empty());
14
15
uint32_t storageImageCount = 0;
16
uint32_t storageBufferCount = 0;
17
uint32_t combinedImageSamplerCount = 0;
18
uint32_t uniformBufferDynamicCount = 0;
19
for (uint32_t i = 0; i < bindingTypesCount; i++) {
20
switch (bindingTypes[i]) {
21
case BindingType::COMBINED_IMAGE_SAMPLER: combinedImageSamplerCount++; break;
22
case BindingType::UNIFORM_BUFFER_DYNAMIC_VERTEX:
23
case BindingType::UNIFORM_BUFFER_DYNAMIC_ALL: uniformBufferDynamicCount++; break;
24
case BindingType::STORAGE_BUFFER_VERTEX:
25
case BindingType::STORAGE_BUFFER_COMPUTE: storageBufferCount++; break;
26
case BindingType::STORAGE_IMAGE_COMPUTE: storageImageCount++; break;
27
}
28
}
29
if (combinedImageSamplerCount) {
30
sizes_.push_back(VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, combinedImageSamplerCount * descriptorCount });
31
}
32
if (uniformBufferDynamicCount) {
33
sizes_.push_back(VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, uniformBufferDynamicCount * descriptorCount });
34
}
35
if (storageBufferCount) {
36
sizes_.push_back(VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, storageBufferCount * descriptorCount });
37
}
38
if (storageImageCount) {
39
sizes_.push_back(VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, storageImageCount * descriptorCount });
40
}
41
VkResult res = Recreate(false);
42
_assert_msg_(res == VK_SUCCESS, "Could not create VulkanDescSetPool %s", tag_);
43
}
44
45
bool VulkanDescSetPool::Allocate(VkDescriptorSet *descriptorSets, int count, const VkDescriptorSetLayout *layouts) {
46
if (descPool_ == VK_NULL_HANDLE || usage_ + count >= info_.maxSets) {
47
// Missing or out of space, need to recreate.
48
VkResult res = Recreate(grow_);
49
_assert_msg_(res == VK_SUCCESS, "Could not grow VulkanDescSetPool %s on usage %d", tag_, (int)usage_);
50
}
51
52
VkDescriptorSetAllocateInfo descAlloc{ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO };
53
descAlloc.descriptorPool = descPool_;
54
descAlloc.descriptorSetCount = count;
55
descAlloc.pSetLayouts = layouts;
56
VkResult result = vkAllocateDescriptorSets(vulkan_->GetDevice(), &descAlloc, descriptorSets);
57
58
if (result == VK_ERROR_FRAGMENTED_POOL || result < 0) {
59
WARN_LOG(Log::G3D, "Pool %s %s - recreating", tag_, result == VK_ERROR_FRAGMENTED_POOL ? "fragmented" : "full");
60
// There seems to have been a spec revision. Here we should apparently recreate the descriptor pool,
61
// so let's do that. See https://www.khronos.org/registry/vulkan/specs/1.0/man/html/vkAllocateDescriptorSets.html
62
// Fragmentation shouldn't really happen though since we wipe the pool every frame.
63
VkResult res = Recreate(false);
64
_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);
65
66
// Need to update this pointer since we have allocated a new one.
67
descAlloc.descriptorPool = descPool_;
68
result = vkAllocateDescriptorSets(vulkan_->GetDevice(), &descAlloc, descriptorSets);
69
_assert_msg_(result == VK_SUCCESS, "Ran out of descriptor space (frag?) and failed to allocate after recreating a descriptor pool. res=%d", (int)result);
70
}
71
72
if (result != VK_SUCCESS) {
73
return false;
74
}
75
76
usage_ += count;
77
return true;
78
}
79
80
void VulkanDescSetPool::Reset() {
81
_assert_msg_(descPool_ != VK_NULL_HANDLE, "VulkanDescSetPool::Reset without valid pool");
82
vkResetDescriptorPool(vulkan_->GetDevice(), descPool_, 0);
83
84
usage_ = 0;
85
}
86
87
void VulkanDescSetPool::Destroy() {
88
if (descPool_ != VK_NULL_HANDLE) {
89
vulkan_->Delete().QueueDeleteDescriptorPool(descPool_);
90
usage_ = 0;
91
}
92
sizes_.clear();
93
}
94
95
void VulkanDescSetPool::DestroyImmediately() {
96
if (descPool_ != VK_NULL_HANDLE) {
97
vkDestroyDescriptorPool(vulkan_->GetDevice(), descPool_, nullptr);
98
descPool_ = VK_NULL_HANDLE;
99
usage_ = 0;
100
}
101
sizes_.clear();
102
}
103
104
VkResult VulkanDescSetPool::Recreate(bool grow) {
105
_assert_msg_(vulkan_ != nullptr, "VulkanDescSetPool::Recreate without VulkanContext");
106
107
uint32_t prevSize = info_.maxSets;
108
if (grow) {
109
info_.maxSets *= 2;
110
for (auto &size : sizes_)
111
size.descriptorCount *= 2;
112
}
113
114
// Delete the pool if it already exists.
115
if (descPool_ != VK_NULL_HANDLE) {
116
INFO_LOG(Log::G3D, "Reallocating %s desc pool from %d to %d", tag_, prevSize, info_.maxSets);
117
vulkan_->Delete().QueueDeleteDescriptorPool(descPool_);
118
usage_ = 0;
119
}
120
121
info_.pPoolSizes = &sizes_[0];
122
info_.poolSizeCount = (uint32_t)sizes_.size();
123
124
VkResult result = vkCreateDescriptorPool(vulkan_->GetDevice(), &info_, nullptr, &descPool_);
125
if (result == VK_SUCCESS) {
126
vulkan_->SetDebugName(descPool_, VK_OBJECT_TYPE_DESCRIPTOR_POOL, tag_);
127
}
128
return result;
129
}
130
131