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