• 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 #include "Resources.h"
17 
18 namespace gfxstream {
19 namespace vk {
20 
clearReifiedDescriptorSet(ReifiedDescriptorSet * set)21 void clearReifiedDescriptorSet(ReifiedDescriptorSet* set) {
22     set->pool = VK_NULL_HANDLE;
23     set->setLayout = VK_NULL_HANDLE;
24     set->poolId = -1;
25     set->allocationPending = false;
26     set->allWrites.clear();
27     set->pendingWriteArrayRanges.clear();
28 }
29 
initDescriptorWriteTable(const std::vector<VkDescriptorSetLayoutBinding> & layoutBindings,DescriptorWriteTable & table)30 void initDescriptorWriteTable(const std::vector<VkDescriptorSetLayoutBinding>& layoutBindings, DescriptorWriteTable& table) {
31     uint32_t highestBindingNumber = 0;
32 
33     for (uint32_t i = 0; i < layoutBindings.size(); ++i) {
34         if (layoutBindings[i].binding > highestBindingNumber) {
35             highestBindingNumber = layoutBindings[i].binding;
36         }
37     }
38 
39     std::vector<uint32_t> countsEachBinding(highestBindingNumber + 1, 0);
40 
41     for (uint32_t i = 0; i < layoutBindings.size(); ++i) {
42         countsEachBinding[layoutBindings[i].binding] =
43             layoutBindings[i].descriptorCount;
44     }
45 
46     table.resize(countsEachBinding.size());
47 
48     for (uint32_t i = 0; i < table.size(); ++i) {
49         table[i].resize(countsEachBinding[i]);
50 
51         for (uint32_t j = 0; j < countsEachBinding[i]; ++j) {
52             table[i][j].type = DescriptorWriteType::Empty;
53             table[i][j].dstArrayElement = 0;
54         }
55     }
56 }
57 
initializeReifiedDescriptorSet(VkDescriptorPool pool,VkDescriptorSetLayout setLayout,ReifiedDescriptorSet * set)58 static void initializeReifiedDescriptorSet(VkDescriptorPool pool, VkDescriptorSetLayout setLayout, ReifiedDescriptorSet* set) {
59 
60     set->pendingWriteArrayRanges.clear();
61 
62     const auto& layoutInfo = *(as_goldfish_VkDescriptorSetLayout(setLayout)->layoutInfo);
63 
64     initDescriptorWriteTable(layoutInfo.bindings, set->allWrites);
65 
66     for (size_t i = 0; i < layoutInfo.bindings.size(); ++i) {
67         // Bindings can be sparsely defined
68         const auto& binding = layoutInfo.bindings[i];
69         uint32_t bindingIndex = binding.binding;
70         if (set->bindingIsImmutableSampler.size() <= bindingIndex) {
71             set->bindingIsImmutableSampler.resize(bindingIndex + 1, false);
72         }
73         set->bindingIsImmutableSampler[bindingIndex] =
74             binding.descriptorCount > 0 &&
75             (binding.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER ||
76              binding.descriptorType ==
77              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, ReifiedDescriptorSet* dst) {
189     const DescriptorWriteTable& srcTable = src->allWrites;
190     DescriptorWriteTable& dstTable = dst->allWrites;
191 
192     // src/dst may be the same descriptor set, so we need to create a temporary array for that case.
193     // (TODO: Maybe just notice the pointers are the same? can aliasing in any other way happen?)
194 
195     std::vector<DescriptorWrite> toCopy;
196     uint32_t currBinding = copy->srcBinding;
197     uint32_t arrOffset = copy->srcArrayElement;
198     for (uint32_t i = 0; i < copy->descriptorCount; ++i, ++arrOffset) {
199         if (arrOffset >= srcTable[currBinding].size()) {
200             ++currBinding;
201             arrOffset = 0;
202         }
203         toCopy.push_back(srcTable[currBinding][arrOffset]);
204     }
205 
206     currBinding = copy->dstBinding;
207     arrOffset = copy->dstArrayElement;
208     for (uint32_t i = 0; i < copy->descriptorCount; ++i, ++arrOffset) {
209         if (arrOffset >= dstTable[currBinding].size()) {
210             ++currBinding;
211             arrOffset = 0;
212         }
213         dstTable[currBinding][arrOffset] = toCopy[i];
214     }
215 }
216 
doEmulatedDescriptorImageInfoWriteFromTemplate(VkDescriptorType descType,uint32_t binding,uint32_t dstArrayElement,uint32_t count,const VkDescriptorImageInfo * imageInfos,ReifiedDescriptorSet * set)217 void doEmulatedDescriptorImageInfoWriteFromTemplate(
218     VkDescriptorType descType,
219     uint32_t binding,
220     uint32_t dstArrayElement,
221     uint32_t count,
222     const VkDescriptorImageInfo* imageInfos,
223     ReifiedDescriptorSet* set) {
224 
225     DescriptorWriteTable& table = set->allWrites;
226 
227     uint32_t currBinding = binding;
228     uint32_t arrOffset = dstArrayElement;
229 
230     for (uint32_t i = 0; i < count; ++i, ++arrOffset) {
231         if (arrOffset >= table[currBinding].size()) {
232             ++currBinding;
233             arrOffset = 0;
234         }
235         auto& entry = table[currBinding][arrOffset];
236         entry.imageInfo = imageInfos[i];
237         entry.type = DescriptorWriteType::ImageInfo;
238         entry.descriptorType = descType;
239     }
240 }
241 
doEmulatedDescriptorBufferInfoWriteFromTemplate(VkDescriptorType descType,uint32_t binding,uint32_t dstArrayElement,uint32_t count,const VkDescriptorBufferInfo * bufferInfos,ReifiedDescriptorSet * set)242 void doEmulatedDescriptorBufferInfoWriteFromTemplate(
243     VkDescriptorType descType,
244     uint32_t binding,
245     uint32_t dstArrayElement,
246     uint32_t count,
247     const VkDescriptorBufferInfo* bufferInfos,
248     ReifiedDescriptorSet* set) {
249 
250     DescriptorWriteTable& table = set->allWrites;
251 
252     uint32_t currBinding = binding;
253     uint32_t arrOffset = dstArrayElement;
254 
255     for (uint32_t i = 0; i < count; ++i, ++arrOffset) {
256         if (arrOffset >= table[currBinding].size()) {
257             ++currBinding;
258             arrOffset = 0;
259         }
260         auto& entry = table[currBinding][dstArrayElement + i];
261         entry.bufferInfo = bufferInfos[i];
262         entry.type = DescriptorWriteType::BufferInfo;
263         entry.descriptorType = descType;
264     }
265 }
266 
doEmulatedDescriptorBufferViewWriteFromTemplate(VkDescriptorType descType,uint32_t binding,uint32_t dstArrayElement,uint32_t count,const VkBufferView * bufferViews,ReifiedDescriptorSet * set)267 void doEmulatedDescriptorBufferViewWriteFromTemplate(
268     VkDescriptorType descType,
269     uint32_t binding,
270     uint32_t dstArrayElement,
271     uint32_t count,
272     const VkBufferView* bufferViews,
273     ReifiedDescriptorSet* set) {
274 
275     DescriptorWriteTable& table = set->allWrites;
276 
277     uint32_t currBinding = binding;
278     uint32_t arrOffset = dstArrayElement;
279 
280     for (uint32_t i = 0; i < count; ++i, ++arrOffset) {
281         if (arrOffset >= table[currBinding].size()) {
282             ++currBinding;
283             arrOffset = 0;
284         }
285         auto& entry = table[currBinding][dstArrayElement + i];
286         entry.bufferView = bufferViews[i];
287         entry.type = DescriptorWriteType::BufferView;
288         entry.descriptorType = descType;
289     }
290 }
291 
doEmulatedDescriptorInlineUniformBlockFromTemplate(VkDescriptorType descType,uint32_t binding,uint32_t dstArrayElement,uint32_t count,const void * pData,ReifiedDescriptorSet * set)292 void doEmulatedDescriptorInlineUniformBlockFromTemplate(VkDescriptorType descType, uint32_t binding,
293                                                         uint32_t dstArrayElement, uint32_t count,
294                                                         const void* pData,
295                                                         ReifiedDescriptorSet* set) {
296     DescriptorWriteTable& table = set->allWrites;
297     auto& entry = table[binding][0];
298     entry.dstArrayElement = dstArrayElement;
299     entry.inlineUniformBlockBuffer.assign(static_cast<const uint8_t*>(pData),
300                                           static_cast<const uint8_t*>(pData) + count);
301     entry.type = DescriptorWriteType::InlineUniformBlock;
302     entry.descriptorType = descType;
303 }
304 
isBindingFeasibleForAlloc(const DescriptorPoolAllocationInfo::DescriptorCountInfo & countInfo,const VkDescriptorSetLayoutBinding & binding)305 static bool isBindingFeasibleForAlloc(
306     const DescriptorPoolAllocationInfo::DescriptorCountInfo& countInfo,
307     const VkDescriptorSetLayoutBinding& binding) {
308 
309     if (binding.descriptorCount && (countInfo.type != binding.descriptorType)) {
310         return false;
311     }
312 
313     uint32_t availDescriptorCount =
314         countInfo.descriptorCount - countInfo.used;
315 
316     if (availDescriptorCount < binding.descriptorCount) {
317         ALOGV("%s: Ran out of descriptors of type 0x%x. "
318               "Wanted %u from layout but "
319               "we only have %u free (total in pool: %u)\n", __func__,
320               binding.descriptorType,
321               binding.descriptorCount,
322               countInfo.descriptorCount - countInfo.used,
323               countInfo.descriptorCount);
324         return false;
325     }
326 
327     return true;
328 }
329 
isBindingFeasibleForFree(const DescriptorPoolAllocationInfo::DescriptorCountInfo & countInfo,const VkDescriptorSetLayoutBinding & binding)330 static bool isBindingFeasibleForFree(
331     const DescriptorPoolAllocationInfo::DescriptorCountInfo& countInfo,
332     const VkDescriptorSetLayoutBinding& binding) {
333 
334     if (countInfo.type != binding.descriptorType) return false;
335     if (countInfo.used < binding.descriptorCount) {
336         ALOGV("%s: Was a descriptor set double freed? "
337               "Ran out of descriptors of type 0x%x. "
338               "Wanted to free %u from layout but "
339               "we only have %u used (total in pool: %u)\n", __func__,
340               binding.descriptorType,
341               binding.descriptorCount,
342               countInfo.used,
343               countInfo.descriptorCount);
344         return false;
345     }
346     return true;
347 }
348 
allocBindingFeasible(const VkDescriptorSetLayoutBinding & binding,DescriptorPoolAllocationInfo::DescriptorCountInfo & poolState)349 static void allocBindingFeasible(
350     const VkDescriptorSetLayoutBinding& binding,
351     DescriptorPoolAllocationInfo::DescriptorCountInfo& poolState) {
352     poolState.used += binding.descriptorCount;
353 }
354 
freeBindingFeasible(const VkDescriptorSetLayoutBinding & binding,DescriptorPoolAllocationInfo::DescriptorCountInfo & poolState)355 static void freeBindingFeasible(
356     const VkDescriptorSetLayoutBinding& binding,
357     DescriptorPoolAllocationInfo::DescriptorCountInfo& poolState) {
358     poolState.used -= binding.descriptorCount;
359 }
360 
validateDescriptorSetAllocation(const VkDescriptorSetAllocateInfo * pAllocateInfo)361 static VkResult validateDescriptorSetAllocation(const VkDescriptorSetAllocateInfo* pAllocateInfo) {
362     VkDescriptorPool pool = pAllocateInfo->descriptorPool;
363     DescriptorPoolAllocationInfo* poolInfo = as_goldfish_VkDescriptorPool(pool)->allocInfo;
364 
365     // Check the number of sets available.
366     auto setsAvailable = poolInfo->maxSets - poolInfo->usedSets;
367 
368     if (setsAvailable < pAllocateInfo->descriptorSetCount) {
369         ALOGV("%s: Error: VkDescriptorSetAllocateInfo wants %u sets "
370               "but we only have %u available. "
371               "Bailing with VK_ERROR_OUT_OF_POOL_MEMORY.\n", __func__,
372               pAllocateInfo->descriptorSetCount,
373               setsAvailable);
374         return VK_ERROR_OUT_OF_POOL_MEMORY;
375     }
376 
377     // Perform simulated allocation and error out with
378     // VK_ERROR_OUT_OF_POOL_MEMORY if it fails.
379     std::vector<DescriptorPoolAllocationInfo::DescriptorCountInfo> descriptorCountCopy =
380         poolInfo->descriptorCountInfo;
381 
382     for (uint32_t i = 0; i < pAllocateInfo->descriptorSetCount; ++i) {
383         if (!pAllocateInfo->pSetLayouts[i]) {
384             ALOGV("%s: Error: Tried to allocate a descriptor set with null set layout.\n", __func__);
385             return VK_ERROR_INITIALIZATION_FAILED;
386         }
387 
388         auto setLayoutInfo = as_goldfish_VkDescriptorSetLayout(pAllocateInfo->pSetLayouts[i])->layoutInfo;
389         if (!setLayoutInfo) {
390             return VK_ERROR_INITIALIZATION_FAILED;
391         }
392 
393         for (const auto& binding : setLayoutInfo->bindings) {
394             bool success = false;
395             for (auto& pool : descriptorCountCopy) {
396                 if (!isBindingFeasibleForAlloc(pool, binding)) continue;
397 
398                 success = true;
399                 allocBindingFeasible(binding, pool);
400                 break;
401             }
402 
403             if (!success) {
404                 return VK_ERROR_OUT_OF_POOL_MEMORY;
405             }
406         }
407     }
408     return VK_SUCCESS;
409 }
410 
applyDescriptorSetAllocation(VkDescriptorPool pool,VkDescriptorSetLayout setLayout)411 void applyDescriptorSetAllocation(VkDescriptorPool pool, VkDescriptorSetLayout setLayout) {
412     auto allocInfo = as_goldfish_VkDescriptorPool(pool)->allocInfo;
413     auto setLayoutInfo = as_goldfish_VkDescriptorSetLayout(setLayout)->layoutInfo;
414 
415     ++allocInfo->usedSets;
416 
417     for (const auto& binding : setLayoutInfo->bindings) {
418         for (auto& countForPool : allocInfo->descriptorCountInfo) {
419             if (!isBindingFeasibleForAlloc(countForPool, binding)) continue;
420             allocBindingFeasible(binding, countForPool);
421             break;
422         }
423     }
424 }
425 
removeDescriptorSetAllocation(VkDescriptorPool pool,const std::vector<VkDescriptorSetLayoutBinding> & bindings)426 void removeDescriptorSetAllocation(VkDescriptorPool pool, const std::vector<VkDescriptorSetLayoutBinding>& bindings) {
427     auto allocInfo = as_goldfish_VkDescriptorPool(pool)->allocInfo;
428 
429     if (0 == allocInfo->usedSets) {
430         ALOGV("%s: Warning: a descriptor set was double freed.\n", __func__);
431         return;
432     }
433 
434     --allocInfo->usedSets;
435 
436     for (const auto& binding : bindings) {
437         for (auto& countForPool : allocInfo->descriptorCountInfo) {
438             if (!isBindingFeasibleForFree(countForPool, binding)) continue;
439             freeBindingFeasible(binding, countForPool);
440             break;
441         }
442     }
443 }
444 
fillDescriptorSetInfoForPool(VkDescriptorPool pool,VkDescriptorSetLayout setLayout,VkDescriptorSet set)445 void fillDescriptorSetInfoForPool(VkDescriptorPool pool, VkDescriptorSetLayout setLayout, VkDescriptorSet set) {
446     DescriptorPoolAllocationInfo* allocInfo = as_goldfish_VkDescriptorPool(pool)->allocInfo;
447 
448     ReifiedDescriptorSet* newReified = new ReifiedDescriptorSet;
449     newReified->poolId = as_goldfish_VkDescriptorSet(set)->underlying;
450     newReified->allocationPending = true;
451 
452     as_goldfish_VkDescriptorSet(set)->reified = newReified;
453 
454     allocInfo->allocedPoolIds.insert(newReified->poolId);
455     allocInfo->allocedSets.insert(set);
456 
457     initializeReifiedDescriptorSet(pool, setLayout, newReified);
458 }
459 
validateAndApplyVirtualDescriptorSetAllocation(const VkDescriptorSetAllocateInfo * pAllocateInfo,VkDescriptorSet * pSets)460 VkResult validateAndApplyVirtualDescriptorSetAllocation(const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pSets) {
461     VkResult validateRes = validateDescriptorSetAllocation(pAllocateInfo);
462 
463     if (validateRes != VK_SUCCESS) return validateRes;
464 
465     for (uint32_t i = 0; i < pAllocateInfo->descriptorSetCount; ++i) {
466         applyDescriptorSetAllocation(pAllocateInfo->descriptorPool, pAllocateInfo->pSetLayouts[i]);
467     }
468 
469     VkDescriptorPool pool = pAllocateInfo->descriptorPool;
470     DescriptorPoolAllocationInfo* allocInfo = as_goldfish_VkDescriptorPool(pool)->allocInfo;
471 
472     if (allocInfo->freePoolIds.size() < pAllocateInfo->descriptorSetCount) {
473         ALOGE("%s: FATAL: Somehow out of descriptor pool IDs. Wanted %u IDs but only have %u free IDs remaining. The count for maxSets was %u and used was %u\n", __func__,
474                 pAllocateInfo->descriptorSetCount,
475                 (uint32_t)allocInfo->freePoolIds.size(),
476                 allocInfo->maxSets,
477                 allocInfo->usedSets);
478         abort();
479     }
480 
481     for (uint32_t i = 0 ; i < pAllocateInfo->descriptorSetCount; ++i) {
482         uint64_t id = allocInfo->freePoolIds.back();
483         allocInfo->freePoolIds.pop_back();
484 
485         VkDescriptorSet newSet = new_from_host_VkDescriptorSet((VkDescriptorSet)id);
486         pSets[i] = newSet;
487 
488         fillDescriptorSetInfoForPool(pool, pAllocateInfo->pSetLayouts[i], newSet);
489     }
490 
491     return VK_SUCCESS;
492 }
493 
removeDescriptorSetFromPool(VkDescriptorSet set,bool usePoolIds)494 bool removeDescriptorSetFromPool(VkDescriptorSet set, bool usePoolIds) {
495     ReifiedDescriptorSet* reified = as_goldfish_VkDescriptorSet(set)->reified;
496 
497     VkDescriptorPool pool = reified->pool;
498     DescriptorPoolAllocationInfo* allocInfo = as_goldfish_VkDescriptorPool(pool)->allocInfo;
499 
500     if (usePoolIds) {
501         // Look for the set's pool Id in the pool. If not found, then this wasn't really allocated, and bail.
502         if (allocInfo->allocedPoolIds.find(reified->poolId) == allocInfo->allocedPoolIds.end()) {
503             return false;
504         }
505     }
506 
507     const std::vector<VkDescriptorSetLayoutBinding>& bindings = reified->bindings;
508     removeDescriptorSetAllocation(pool, bindings);
509 
510     if (usePoolIds) {
511         allocInfo->freePoolIds.push_back(reified->poolId);
512         allocInfo->allocedPoolIds.erase(reified->poolId);
513     }
514     allocInfo->allocedSets.erase(set);
515 
516     return true;
517 }
518 
clearDescriptorPool(VkDescriptorPool pool,bool usePoolIds)519 std::vector<VkDescriptorSet> clearDescriptorPool(VkDescriptorPool pool, bool usePoolIds) {
520     std::vector<VkDescriptorSet> toClear;
521     for (auto set : as_goldfish_VkDescriptorPool(pool)->allocInfo->allocedSets) {
522         toClear.push_back(set);
523     }
524 
525     for (auto set: toClear) {
526         removeDescriptorSetFromPool(set, usePoolIds);
527     }
528 
529     return toClear;
530 }
531 
532 }  // namespace vk
533 }  // namespace gfxstream
534