1 // Copyright (C) 2021 The Android Open Source Project
2 // Copyright (C) 2021 Google Inc.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 #include "DescriptorSetVirtualization.h"
16 
17 #include "Resources.h"
18 #include "util/log.h"
19 
20 namespace gfxstream {
21 namespace vk {
22 
clearReifiedDescriptorSet(ReifiedDescriptorSet * set)23 void clearReifiedDescriptorSet(ReifiedDescriptorSet* set) {
24     set->pool = VK_NULL_HANDLE;
25     set->setLayout = VK_NULL_HANDLE;
26     set->poolId = -1;
27     set->allocationPending = false;
28     set->allWrites.clear();
29     set->pendingWriteArrayRanges.clear();
30 }
31 
initDescriptorWriteTable(const std::vector<VkDescriptorSetLayoutBinding> & layoutBindings,DescriptorWriteTable & table)32 void initDescriptorWriteTable(const std::vector<VkDescriptorSetLayoutBinding>& layoutBindings,
33                               DescriptorWriteTable& table) {
34     uint32_t highestBindingNumber = 0;
35 
36     for (uint32_t i = 0; i < layoutBindings.size(); ++i) {
37         if (layoutBindings[i].binding > highestBindingNumber) {
38             highestBindingNumber = layoutBindings[i].binding;
39         }
40     }
41 
42     std::vector<uint32_t> countsEachBinding(highestBindingNumber + 1, 0);
43 
44     for (uint32_t i = 0; i < layoutBindings.size(); ++i) {
45         countsEachBinding[layoutBindings[i].binding] = layoutBindings[i].descriptorCount;
46     }
47 
48     table.resize(countsEachBinding.size());
49 
50     for (uint32_t i = 0; i < table.size(); ++i) {
51         table[i].resize(countsEachBinding[i]);
52 
53         for (uint32_t j = 0; j < countsEachBinding[i]; ++j) {
54             table[i][j].type = DescriptorWriteType::Empty;
55             table[i][j].dstArrayElement = 0;
56         }
57     }
58 }
59 
initializeReifiedDescriptorSet(VkDescriptorPool pool,VkDescriptorSetLayout setLayout,ReifiedDescriptorSet * set)60 static void initializeReifiedDescriptorSet(VkDescriptorPool pool, VkDescriptorSetLayout setLayout,
61                                            ReifiedDescriptorSet* set) {
62     set->pendingWriteArrayRanges.clear();
63 
64     const auto& layoutInfo = *(as_goldfish_VkDescriptorSetLayout(setLayout)->layoutInfo);
65 
66     initDescriptorWriteTable(layoutInfo.bindings, set->allWrites);
67 
68     for (size_t i = 0; i < layoutInfo.bindings.size(); ++i) {
69         // Bindings can be sparsely defined
70         const auto& binding = layoutInfo.bindings[i];
71         uint32_t bindingIndex = binding.binding;
72         if (set->bindingIsImmutableSampler.size() <= bindingIndex) {
73             set->bindingIsImmutableSampler.resize(bindingIndex + 1, false);
74         }
75         set->bindingIsImmutableSampler[bindingIndex] =
76             binding.descriptorCount > 0 &&
77             (binding.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER ||
78              binding.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) &&
79             binding.pImmutableSamplers;
80     }
81 
82     set->pool = pool;
83     set->setLayout = setLayout;
84     set->allocationPending = true;
85     set->bindings = layoutInfo.bindings;
86 }
87 
isDescriptorTypeImageInfo(VkDescriptorType descType)88 bool isDescriptorTypeImageInfo(VkDescriptorType descType) {
89     return (descType == VK_DESCRIPTOR_TYPE_SAMPLER) ||
90            (descType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) ||
91            (descType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE) ||
92            (descType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) ||
93            (descType == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT);
94 }
95 
isDescriptorTypeBufferInfo(VkDescriptorType descType)96 bool isDescriptorTypeBufferInfo(VkDescriptorType descType) {
97     return (descType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) ||
98            (descType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) ||
99            (descType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER) ||
100            (descType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC);
101 }
102 
isDescriptorTypeBufferView(VkDescriptorType descType)103 bool isDescriptorTypeBufferView(VkDescriptorType descType) {
104     return (descType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER) ||
105            (descType == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER);
106 }
107 
isDescriptorTypeInlineUniformBlock(VkDescriptorType descType)108 bool isDescriptorTypeInlineUniformBlock(VkDescriptorType descType) {
109     return descType == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT;
110 }
111 
isDescriptorTypeAccelerationStructure(VkDescriptorType descType)112 bool isDescriptorTypeAccelerationStructure(VkDescriptorType descType) {
113     return descType == VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR;
114 }
115 
doEmulatedDescriptorWrite(const VkWriteDescriptorSet * write,ReifiedDescriptorSet * toWrite)116 void doEmulatedDescriptorWrite(const VkWriteDescriptorSet* write, ReifiedDescriptorSet* toWrite) {
117     VkDescriptorType descType = write->descriptorType;
118     uint32_t dstBinding = write->dstBinding;
119     uint32_t dstArrayElement = write->dstArrayElement;
120     uint32_t descriptorCount = write->descriptorCount;
121 
122     DescriptorWriteTable& table = toWrite->allWrites;
123 
124     uint32_t arrOffset = dstArrayElement;
125 
126     if (isDescriptorTypeImageInfo(descType)) {
127         uint32_t i = 0;
128         while (i < descriptorCount) {
129             assert(dstBinding < table.size());
130             if (arrOffset >= table[dstBinding].size()) {
131                 ++dstBinding;
132                 arrOffset = 0;
133                 continue;
134             }
135             auto& entry = table[dstBinding][arrOffset];
136             entry.imageInfo = write->pImageInfo[i];
137             entry.type = DescriptorWriteType::ImageInfo;
138             entry.descriptorType = descType;
139             ++i;
140             ++arrOffset;
141         }
142     } else if (isDescriptorTypeBufferInfo(descType)) {
143         uint32_t i = 0;
144         while (i < descriptorCount) {
145             assert(dstBinding < table.size());
146             if (arrOffset >= table[dstBinding].size()) {
147                 ++dstBinding;
148                 arrOffset = 0;
149                 continue;
150             }
151             auto& entry = table[dstBinding][arrOffset];
152             entry.bufferInfo = write->pBufferInfo[i];
153             entry.type = DescriptorWriteType::BufferInfo;
154             entry.descriptorType = descType;
155             ++i;
156             ++arrOffset;
157         }
158     } else if (isDescriptorTypeBufferView(descType)) {
159         uint32_t i = 0;
160         while (i < descriptorCount) {
161             assert(dstBinding < table.size());
162             if (arrOffset >= table[dstBinding].size()) {
163                 ++dstBinding;
164                 arrOffset = 0;
165                 continue;
166             }
167             auto& entry = table[dstBinding][arrOffset];
168             entry.bufferView = write->pTexelBufferView[i];
169             entry.type = DescriptorWriteType::BufferView;
170             entry.descriptorType = descType;
171             ++i;
172             ++arrOffset;
173         }
174     } else if (isDescriptorTypeInlineUniformBlock(descType)) {
175         const VkWriteDescriptorSetInlineUniformBlock* descInlineUniformBlock =
176             static_cast<const VkWriteDescriptorSetInlineUniformBlock*>(write->pNext);
177         while (descInlineUniformBlock &&
178                descInlineUniformBlock->sType !=
179                    VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK) {
180             descInlineUniformBlock = static_cast<const VkWriteDescriptorSetInlineUniformBlock*>(
181                 descInlineUniformBlock->pNext);
182         }
183         if (!descInlineUniformBlock) {
184             mesa_loge("%s: did not find inline uniform block\n", __func__);
185             return;
186         }
187         auto& entry = table[dstBinding][0];
188         entry.inlineUniformBlock = *descInlineUniformBlock;
189         entry.inlineUniformBlockBuffer.assign(
190             static_cast<const uint8_t*>(descInlineUniformBlock->pData),
191             static_cast<const uint8_t*>(descInlineUniformBlock->pData) +
192                 descInlineUniformBlock->dataSize);
193         entry.type = DescriptorWriteType::InlineUniformBlock;
194         entry.descriptorType = descType;
195         entry.dstArrayElement = dstArrayElement;
196     } else if (isDescriptorTypeAccelerationStructure(descType)) {
197         // TODO
198         // Look for pNext inline uniform block or acceleration structure.
199         // Append new DescriptorWrite entry that holds the buffer
200         ALOGW("%s: Ignoring emulated write for descriptor type 0x%x\n", __func__, descType);
201     }
202 }
203 
doEmulatedDescriptorCopy(const VkCopyDescriptorSet * copy,const ReifiedDescriptorSet * src,ReifiedDescriptorSet * dst)204 void doEmulatedDescriptorCopy(const VkCopyDescriptorSet* copy, const ReifiedDescriptorSet* src,
205                               ReifiedDescriptorSet* dst) {
206     const DescriptorWriteTable& srcTable = src->allWrites;
207     DescriptorWriteTable& dstTable = dst->allWrites;
208 
209     // src/dst may be the same descriptor set, so we need to create a temporary array for that case.
210     // (TODO: Maybe just notice the pointers are the same? can aliasing in any other way happen?)
211 
212     std::vector<DescriptorWrite> toCopy;
213     uint32_t currBinding = copy->srcBinding;
214     uint32_t arrOffset = copy->srcArrayElement;
215     uint32_t i = 0;
216     while (i < copy->descriptorCount) {
217         assert(currBinding < srcTable.size());
218         if (arrOffset >= srcTable[currBinding].size()) {
219             ++currBinding;
220             arrOffset = 0;
221             continue;
222         }
223         toCopy.push_back(srcTable[currBinding][arrOffset]);
224         ++i;
225         ++arrOffset;
226     }
227 
228     currBinding = copy->dstBinding;
229     arrOffset = copy->dstArrayElement;
230     i = 0;
231     while (i < copy->descriptorCount) {
232         assert(currBinding < dstTable.size());
233         if (arrOffset >= dstTable[currBinding].size()) {
234             ++currBinding;
235             arrOffset = 0;
236             continue;
237         }
238         dstTable[currBinding][arrOffset] = toCopy[i];
239         ++i;
240         ++arrOffset;
241     }
242 }
243 
doEmulatedDescriptorImageInfoWriteFromTemplate(VkDescriptorType descType,uint32_t binding,uint32_t dstArrayElement,uint32_t count,const VkDescriptorImageInfo * imageInfos,ReifiedDescriptorSet * set)244 void doEmulatedDescriptorImageInfoWriteFromTemplate(VkDescriptorType descType, uint32_t binding,
245                                                     uint32_t dstArrayElement, uint32_t count,
246                                                     const VkDescriptorImageInfo* imageInfos,
247                                                     ReifiedDescriptorSet* set) {
248     DescriptorWriteTable& table = set->allWrites;
249 
250     uint32_t currBinding = binding;
251     uint32_t arrOffset = dstArrayElement;
252     uint32_t i = 0;
253     while (i < count) {
254         assert(currBinding < table.size());
255         if (arrOffset >= table[currBinding].size()) {
256             ++currBinding;
257             arrOffset = 0;
258             continue;
259         }
260         auto& entry = table[currBinding][arrOffset];
261         entry.imageInfo = imageInfos[i];
262         entry.type = DescriptorWriteType::ImageInfo;
263         entry.descriptorType = descType;
264         ++i;
265         ++arrOffset;
266     }
267 }
268 
doEmulatedDescriptorBufferInfoWriteFromTemplate(VkDescriptorType descType,uint32_t binding,uint32_t dstArrayElement,uint32_t count,const VkDescriptorBufferInfo * bufferInfos,ReifiedDescriptorSet * set)269 void doEmulatedDescriptorBufferInfoWriteFromTemplate(VkDescriptorType descType, uint32_t binding,
270                                                      uint32_t dstArrayElement, uint32_t count,
271                                                      const VkDescriptorBufferInfo* bufferInfos,
272                                                      ReifiedDescriptorSet* set) {
273     DescriptorWriteTable& table = set->allWrites;
274 
275     uint32_t currBinding = binding;
276     uint32_t arrOffset = dstArrayElement;
277     uint32_t i = 0;
278     while (i < count) {
279         assert(currBinding < table.size());
280         if (arrOffset >= table[currBinding].size()) {
281             ++currBinding;
282             arrOffset = 0;
283             continue;
284         }
285         auto& entry = table[currBinding][arrOffset];
286         entry.bufferInfo = bufferInfos[i];
287         entry.type = DescriptorWriteType::BufferInfo;
288         entry.descriptorType = descType;
289         ++i;
290         ++arrOffset;
291     }
292 }
293 
doEmulatedDescriptorBufferViewWriteFromTemplate(VkDescriptorType descType,uint32_t binding,uint32_t dstArrayElement,uint32_t count,const VkBufferView * bufferViews,ReifiedDescriptorSet * set)294 void doEmulatedDescriptorBufferViewWriteFromTemplate(VkDescriptorType descType, uint32_t binding,
295                                                      uint32_t dstArrayElement, uint32_t count,
296                                                      const VkBufferView* bufferViews,
297                                                      ReifiedDescriptorSet* set) {
298     DescriptorWriteTable& table = set->allWrites;
299 
300     uint32_t currBinding = binding;
301     uint32_t arrOffset = dstArrayElement;
302     uint32_t i = 0;
303     while (i < count) {
304         assert(currBinding < table.size());
305         if (arrOffset >= table[currBinding].size()) {
306             ++currBinding;
307             arrOffset = 0;
308             continue;
309         }
310         auto& entry = table[currBinding][arrOffset];
311         entry.bufferView = bufferViews[i];
312         entry.type = DescriptorWriteType::BufferView;
313         entry.descriptorType = descType;
314         ++i;
315         ++arrOffset;
316     }
317 }
318 
doEmulatedDescriptorInlineUniformBlockFromTemplate(VkDescriptorType descType,uint32_t binding,uint32_t dstArrayElement,uint32_t count,const void * pData,ReifiedDescriptorSet * set)319 void doEmulatedDescriptorInlineUniformBlockFromTemplate(VkDescriptorType descType, uint32_t binding,
320                                                         uint32_t dstArrayElement, uint32_t count,
321                                                         const void* pData,
322                                                         ReifiedDescriptorSet* set) {
323     DescriptorWriteTable& table = set->allWrites;
324     auto& entry = table[binding][0];
325     entry.dstArrayElement = dstArrayElement;
326     entry.inlineUniformBlockBuffer.assign(static_cast<const uint8_t*>(pData),
327                                           static_cast<const uint8_t*>(pData) + count);
328     entry.type = DescriptorWriteType::InlineUniformBlock;
329     entry.descriptorType = descType;
330 }
331 
isBindingFeasibleForAlloc(const DescriptorPoolAllocationInfo::DescriptorCountInfo & countInfo,const VkDescriptorSetLayoutBinding & binding)332 static bool isBindingFeasibleForAlloc(
333     const DescriptorPoolAllocationInfo::DescriptorCountInfo& countInfo,
334     const VkDescriptorSetLayoutBinding& binding) {
335     if (binding.descriptorCount && (countInfo.type != binding.descriptorType)) {
336         return false;
337     }
338 
339     uint32_t availDescriptorCount = countInfo.descriptorCount - countInfo.used;
340 
341     if (availDescriptorCount < binding.descriptorCount) {
342         ALOGV(
343             "%s: Ran out of descriptors of type 0x%x. "
344             "Wanted %u from layout but "
345             "we only have %u free (total in pool: %u)\n",
346             __func__, binding.descriptorType, binding.descriptorCount,
347             countInfo.descriptorCount - countInfo.used, countInfo.descriptorCount);
348         return false;
349     }
350 
351     return true;
352 }
353 
isBindingFeasibleForFree(const DescriptorPoolAllocationInfo::DescriptorCountInfo & countInfo,const VkDescriptorSetLayoutBinding & binding)354 static bool isBindingFeasibleForFree(
355     const DescriptorPoolAllocationInfo::DescriptorCountInfo& countInfo,
356     const VkDescriptorSetLayoutBinding& binding) {
357     if (countInfo.type != binding.descriptorType) return false;
358     if (countInfo.used < binding.descriptorCount) {
359         ALOGV(
360             "%s: Was a descriptor set double freed? "
361             "Ran out of descriptors of type 0x%x. "
362             "Wanted to free %u from layout but "
363             "we only have %u used (total in pool: %u)\n",
364             __func__, binding.descriptorType, binding.descriptorCount, countInfo.used,
365             countInfo.descriptorCount);
366         return false;
367     }
368     return true;
369 }
370 
allocBindingFeasible(const VkDescriptorSetLayoutBinding & binding,DescriptorPoolAllocationInfo::DescriptorCountInfo & poolState)371 static void allocBindingFeasible(const VkDescriptorSetLayoutBinding& binding,
372                                  DescriptorPoolAllocationInfo::DescriptorCountInfo& poolState) {
373     poolState.used += binding.descriptorCount;
374 }
375 
freeBindingFeasible(const VkDescriptorSetLayoutBinding & binding,DescriptorPoolAllocationInfo::DescriptorCountInfo & poolState)376 static void freeBindingFeasible(const VkDescriptorSetLayoutBinding& binding,
377                                 DescriptorPoolAllocationInfo::DescriptorCountInfo& poolState) {
378     poolState.used -= binding.descriptorCount;
379 }
380 
validateDescriptorSetAllocation(const VkDescriptorSetAllocateInfo * pAllocateInfo)381 static VkResult validateDescriptorSetAllocation(const VkDescriptorSetAllocateInfo* pAllocateInfo) {
382     VkDescriptorPool pool = pAllocateInfo->descriptorPool;
383     DescriptorPoolAllocationInfo* poolInfo = as_goldfish_VkDescriptorPool(pool)->allocInfo;
384 
385     // Check the number of sets available.
386     auto setsAvailable = poolInfo->maxSets - poolInfo->usedSets;
387 
388     if (setsAvailable < pAllocateInfo->descriptorSetCount) {
389         ALOGV(
390             "%s: Error: VkDescriptorSetAllocateInfo wants %u sets "
391             "but we only have %u available. "
392             "Bailing with VK_ERROR_OUT_OF_POOL_MEMORY.\n",
393             __func__, pAllocateInfo->descriptorSetCount, setsAvailable);
394         return VK_ERROR_OUT_OF_POOL_MEMORY;
395     }
396 
397     // Perform simulated allocation and error out with
398     // VK_ERROR_OUT_OF_POOL_MEMORY if it fails.
399     std::vector<DescriptorPoolAllocationInfo::DescriptorCountInfo> descriptorCountCopy =
400         poolInfo->descriptorCountInfo;
401 
402     for (uint32_t i = 0; i < pAllocateInfo->descriptorSetCount; ++i) {
403         if (!pAllocateInfo->pSetLayouts[i]) {
404             ALOGV("%s: Error: Tried to allocate a descriptor set with null set layout.\n",
405                   __func__);
406             return VK_ERROR_INITIALIZATION_FAILED;
407         }
408 
409         auto setLayoutInfo =
410             as_goldfish_VkDescriptorSetLayout(pAllocateInfo->pSetLayouts[i])->layoutInfo;
411         if (!setLayoutInfo) {
412             return VK_ERROR_INITIALIZATION_FAILED;
413         }
414 
415         for (const auto& binding : setLayoutInfo->bindings) {
416             bool success = false;
417             for (auto& pool : descriptorCountCopy) {
418                 if (!isBindingFeasibleForAlloc(pool, binding)) continue;
419 
420                 success = true;
421                 allocBindingFeasible(binding, pool);
422                 break;
423             }
424 
425             if (!success) {
426                 return VK_ERROR_OUT_OF_POOL_MEMORY;
427             }
428         }
429     }
430     return VK_SUCCESS;
431 }
432 
applyDescriptorSetAllocation(VkDescriptorPool pool,VkDescriptorSetLayout setLayout)433 void applyDescriptorSetAllocation(VkDescriptorPool pool, VkDescriptorSetLayout setLayout) {
434     auto allocInfo = as_goldfish_VkDescriptorPool(pool)->allocInfo;
435     auto setLayoutInfo = as_goldfish_VkDescriptorSetLayout(setLayout)->layoutInfo;
436 
437     ++allocInfo->usedSets;
438 
439     for (const auto& binding : setLayoutInfo->bindings) {
440         for (auto& countForPool : allocInfo->descriptorCountInfo) {
441             if (!isBindingFeasibleForAlloc(countForPool, binding)) continue;
442             allocBindingFeasible(binding, countForPool);
443             break;
444         }
445     }
446 }
447 
removeDescriptorSetAllocation(VkDescriptorPool pool,const std::vector<VkDescriptorSetLayoutBinding> & bindings)448 void removeDescriptorSetAllocation(VkDescriptorPool pool,
449                                    const std::vector<VkDescriptorSetLayoutBinding>& bindings) {
450     auto allocInfo = as_goldfish_VkDescriptorPool(pool)->allocInfo;
451 
452     if (0 == allocInfo->usedSets) {
453         ALOGV("%s: Warning: a descriptor set was double freed.\n", __func__);
454         return;
455     }
456 
457     --allocInfo->usedSets;
458 
459     for (const auto& binding : bindings) {
460         for (auto& countForPool : allocInfo->descriptorCountInfo) {
461             if (!isBindingFeasibleForFree(countForPool, binding)) continue;
462             freeBindingFeasible(binding, countForPool);
463             break;
464         }
465     }
466 }
467 
fillDescriptorSetInfoForPool(VkDescriptorPool pool,VkDescriptorSetLayout setLayout,VkDescriptorSet set)468 void fillDescriptorSetInfoForPool(VkDescriptorPool pool, VkDescriptorSetLayout setLayout,
469                                   VkDescriptorSet set) {
470     DescriptorPoolAllocationInfo* allocInfo = as_goldfish_VkDescriptorPool(pool)->allocInfo;
471 
472     ReifiedDescriptorSet* newReified = new ReifiedDescriptorSet;
473     newReified->poolId = as_goldfish_VkDescriptorSet(set)->underlying;
474     newReified->allocationPending = true;
475 
476     as_goldfish_VkDescriptorSet(set)->reified = newReified;
477 
478     allocInfo->allocedPoolIds.insert(newReified->poolId);
479     allocInfo->allocedSets.insert(set);
480 
481     initializeReifiedDescriptorSet(pool, setLayout, newReified);
482 }
483 
validateAndApplyVirtualDescriptorSetAllocation(const VkDescriptorSetAllocateInfo * pAllocateInfo,VkDescriptorSet * pSets)484 VkResult validateAndApplyVirtualDescriptorSetAllocation(
485     const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pSets) {
486     VkResult validateRes = validateDescriptorSetAllocation(pAllocateInfo);
487 
488     if (validateRes != VK_SUCCESS) return validateRes;
489 
490     for (uint32_t i = 0; i < pAllocateInfo->descriptorSetCount; ++i) {
491         applyDescriptorSetAllocation(pAllocateInfo->descriptorPool, pAllocateInfo->pSetLayouts[i]);
492     }
493 
494     VkDescriptorPool pool = pAllocateInfo->descriptorPool;
495     DescriptorPoolAllocationInfo* allocInfo = as_goldfish_VkDescriptorPool(pool)->allocInfo;
496 
497     if (allocInfo->freePoolIds.size() < pAllocateInfo->descriptorSetCount) {
498         mesa_loge(
499             "%s: FATAL: Somehow out of descriptor pool IDs. Wanted %u IDs but only have %u free "
500             "IDs remaining. The count for maxSets was %u and used was %u\n",
501             __func__, pAllocateInfo->descriptorSetCount, (uint32_t)allocInfo->freePoolIds.size(),
502             allocInfo->maxSets, allocInfo->usedSets);
503         abort();
504     }
505 
506     for (uint32_t i = 0; i < pAllocateInfo->descriptorSetCount; ++i) {
507         uint64_t id = allocInfo->freePoolIds.back();
508         allocInfo->freePoolIds.pop_back();
509 
510         VkDescriptorSet newSet = new_from_host_VkDescriptorSet((VkDescriptorSet)id);
511         pSets[i] = newSet;
512 
513         fillDescriptorSetInfoForPool(pool, pAllocateInfo->pSetLayouts[i], newSet);
514     }
515 
516     return VK_SUCCESS;
517 }
518 
removeDescriptorSetFromPool(VkDescriptorSet set,bool usePoolIds)519 bool removeDescriptorSetFromPool(VkDescriptorSet set, bool usePoolIds) {
520     ReifiedDescriptorSet* reified = as_goldfish_VkDescriptorSet(set)->reified;
521 
522     VkDescriptorPool pool = reified->pool;
523     DescriptorPoolAllocationInfo* allocInfo = as_goldfish_VkDescriptorPool(pool)->allocInfo;
524 
525     if (usePoolIds) {
526         // Look for the set's pool Id in the pool. If not found, then this wasn't really allocated,
527         // and bail.
528         if (allocInfo->allocedPoolIds.find(reified->poolId) == allocInfo->allocedPoolIds.end()) {
529             return false;
530         }
531     }
532 
533     const std::vector<VkDescriptorSetLayoutBinding>& bindings = reified->bindings;
534     removeDescriptorSetAllocation(pool, bindings);
535 
536     if (usePoolIds) {
537         allocInfo->freePoolIds.push_back(reified->poolId);
538         allocInfo->allocedPoolIds.erase(reified->poolId);
539     }
540     allocInfo->allocedSets.erase(set);
541 
542     return true;
543 }
544 
clearDescriptorPool(VkDescriptorPool pool,bool usePoolIds)545 std::vector<VkDescriptorSet> clearDescriptorPool(VkDescriptorPool pool, bool usePoolIds) {
546     std::vector<VkDescriptorSet> toClear;
547     for (auto set : as_goldfish_VkDescriptorPool(pool)->allocInfo->allocedSets) {
548         toClear.push_back(set);
549     }
550 
551     for (auto set : toClear) {
552         removeDescriptorSetFromPool(set, usePoolIds);
553     }
554 
555     return toClear;
556 }
557 
558 }  // namespace vk
559 }  // namespace gfxstream
560