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