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