]> git.tdb.fi Git - libs/gl.git/blob - source/backends/vulkan/descriptorpool.cpp
Add files which were forgotten earlier
[libs/gl.git] / source / backends / vulkan / descriptorpool.cpp
1 #include <msp/core/algorithm.h>
2 #include "descriptorpool.h"
3 #include "device.h"
4 #include "pipelinestate.h"
5 #include "vulkan.h"
6
7 using namespace std;
8
9 namespace Msp {
10 namespace GL {
11
12 DescriptorPool::DescriptorPool(Device &d):
13         device(d)
14 {
15         add_pool(increment);
16 }
17
18 DescriptorPool::~DescriptorPool()
19 {
20         const VulkanFunctions &vk = device.get_functions();
21
22         for(VkDescriptorPool p: pools)
23                 vk.DestroyDescriptorPool(p);
24 }
25
26 void DescriptorPool::add_pool(const Counts &counts)
27 {
28         const VulkanFunctions &vk = device.get_functions();
29
30         VkDescriptorPoolSize pool_sizes[2] = { };
31         pool_sizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
32         pool_sizes[0].descriptorCount = counts.buffers;
33         pool_sizes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
34         pool_sizes[1].descriptorCount = counts.images;
35
36         VkDescriptorPoolCreateInfo pool_info = { };
37         pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
38         pool_info.maxSets = counts.sets;
39         pool_info.poolSizeCount = 2;
40         pool_info.pPoolSizes = pool_sizes;
41
42         VkDescriptorPool pool;
43         vk.CreateDescriptorPool(pool_info, pool);
44         pools.push_back(pool);
45 }
46
47 void DescriptorPool::begin_frame()
48 {
49         if(pools.size()>1)
50         {
51                 DestroyQueue &dq = device.get_destroy_queue();
52                 for(VkDescriptorPool p: pools)
53                         dq.destroy(p);
54                 pools.clear();
55
56                 Counts capacity = used;
57                 capacity += increment;
58                 add_pool(capacity);
59
60                 for(auto &s: sets)
61                         fill(s.begin(), s.end(), static_cast<VkDescriptorSet>(0));
62
63                 used = Counts();
64         }
65 }
66
67 unsigned DescriptorPool::get_descriptor_set_slot(const PipelineState &ps, unsigned index)
68 {
69         unsigned slot;
70
71         uint64_t hash = ps.compute_descriptor_set_hash(index);
72         auto i = lower_bound_member(slots, hash, &HashSlot::hash);
73         if(i!=slots.end() && i->hash==hash)
74                 slot = i->slot;
75         else
76         {
77                 slot = next_slot++;
78                 slots.emplace(i, hash, slot);
79                 for(auto &s: sets)
80                         s.push_back(0);
81         }
82
83         if(ps.is_descriptor_set_dynamic(index))
84                 slot |= DYNAMIC_SLOT;
85         return slot;
86 }
87
88 VkDescriptorSet DescriptorPool::get_descriptor_set(unsigned slot, const PipelineState &ps, unsigned index, unsigned frame)
89 {
90         if(!(slot&DYNAMIC_SLOT))
91                 frame = 0;
92         slot &= ~DYNAMIC_SLOT;
93
94         while(sets.size()<=frame)
95                 sets.emplace_back(slots.size());
96
97         VkDescriptorSet &desc_set = sets[frame][slot];
98         if(desc_set)
99                 return desc_set;
100
101         const VulkanFunctions &vk = device.get_functions();
102
103         Counts alloc;
104         alloc.sets = 1;
105
106         vector<char> buffer;
107         unsigned n_writes = ps.fill_descriptor_writes(index, frame, buffer);
108         VkWriteDescriptorSet *writes = reinterpret_cast<VkWriteDescriptorSet *>(buffer.data());
109         for(unsigned i=0; i<n_writes; ++i)
110         {
111                 if(writes[i].descriptorType==VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER)
112                         ++alloc.buffers;
113                 if(writes[i].descriptorType==VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
114                         ++alloc.images;
115         }
116
117         used += alloc;
118
119         VkDescriptorSetLayout layout = ps.get_descriptor_set_layout(index);
120
121         VkDescriptorSetAllocateInfo alloc_info = { };
122         alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
123         alloc_info.descriptorPool = handle_cast<::VkDescriptorPool>(pools.back());
124         alloc_info.descriptorSetCount = 1;
125         alloc_info.pSetLayouts = handle_cast<::VkDescriptorSetLayout *>(&layout);
126
127         Result result = vk.AllocateDescriptorSets(alloc_info, &desc_set);
128         if(result==VK_ERROR_OUT_OF_POOL_MEMORY)
129         {
130                 add_pool(increment);
131                 alloc_info.descriptorPool = handle_cast<::VkDescriptorPool>(pools.back());
132                 vk.AllocateDescriptorSets(alloc_info, &desc_set);
133         }
134
135         for(unsigned i=0; i<n_writes; ++i)
136                 writes[i].dstSet = handle_cast<::VkDescriptorSet>(desc_set);
137
138         vk.UpdateDescriptorSets(n_writes, writes, 0, 0);
139
140         return desc_set;
141 }
142
143
144 DescriptorPool::Counts::Counts(unsigned s, unsigned b, unsigned i):
145         sets(s),
146         buffers(b),
147         images(i)
148 { }
149
150 DescriptorPool::Counts &DescriptorPool::Counts::operator+=(const DescriptorPool::Counts &c)
151 {
152         sets += c.sets;
153         buffers += c.buffers;
154         images += c.images;
155         return *this;
156 }
157
158 } // namespace GL
159 } // namespace Msp