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