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