Skip to content

Commit

Permalink
MVKDescriptorPool pools its descriptor sets.
Browse files Browse the repository at this point in the history
  • Loading branch information
billhollings committed Mar 15, 2021
1 parent 392957d commit 4371ef4
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 55 deletions.
1 change: 1 addition & 0 deletions Docs/Whats_New.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Released TBD
and don't rely on _Metal_ default values.
- Avoid use of _Metal_ renderpass load and store actions on memoryless attachments.
- Remove project qualifiers from references to `SPIRV-Cross` header files.
- `MVKDescriptorPool` pools its descriptor sets.
- Add `MVKConfiguration::apiVersionToAdvertise` and `MVK_CONFIG_API_VERSION_TO_ADVERTISE`
env var to configure **MoltenVK** to advertise a particular _Vulkan_ version.
- Add `MVKConfiguration::advertiseExtensions` and `MVK_CONFIG_ADVERTISE_EXTENSIONS`
Expand Down
16 changes: 7 additions & 9 deletions MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,18 +127,16 @@ class MVKDescriptorSet : public MVKVulkanAPIDeviceObject {
VkBufferView* pTexelBufferView,
VkWriteDescriptorSetInlineUniformBlockEXT* pInlineUniformBlock);

MVKDescriptorSet(MVKDescriptorSetLayout* layout,
uint32_t variableDescriptorCount,
MVKDescriptorPool* pool);

~MVKDescriptorSet() override;
MVKDescriptorSet(MVKDescriptorPool* pool);

protected:
friend class MVKDescriptorSetLayoutBinding;
friend class MVKDescriptorPool;

void propagateDebugName() override {}
MVKDescriptor* getDescriptor(uint32_t binding, uint32_t elementIndex = 0);
VkResult allocate(MVKDescriptorSetLayout* layout, uint32_t variableDescriptorCount);
void free(bool isPoolReset);

MVKDescriptorSetLayout* _layout;
MVKDescriptorPool* _pool;
Expand Down Expand Up @@ -205,14 +203,14 @@ class MVKDescriptorPool : public MVKVulkanAPIDeviceObject {
friend class MVKDescriptorSet;

void propagateDebugName() override {}
VkResult allocateDescriptorSet(MVKDescriptorSetLayout* mvkDSL, uint32_t variableDescriptorCount, VkDescriptorSet* pVKDS);
const uint32_t* getVariableDecriptorCounts(const VkDescriptorSetAllocateInfo* pAllocateInfo);
void freeDescriptorSet(MVKDescriptorSet* mvkDS);
VkResult allocateDescriptorSet(MVKDescriptorSetLayout* mvkDSL, uint32_t variableDescriptorCount, VkDescriptorSet* pVKDS);
void freeDescriptorSet(MVKDescriptorSet* mvkDS, bool isPoolReset);
VkResult allocateDescriptor(VkDescriptorType descriptorType, MVKDescriptor** pMVKDesc);
void freeDescriptor(MVKDescriptor* mvkDesc);

uint32_t _maxSets;
std::unordered_set<MVKDescriptorSet*> _allocatedSets;
MVKSmallVector<MVKDescriptorSet> _descriptorSets;
MVKBitArray _descriptorSetAvailablility;

MVKDescriptorTypePreallocation<MVKUniformBufferDescriptor> _uniformBufferDescriptors;
MVKDescriptorTypePreallocation<MVKStorageBufferDescriptor> _storageBufferDescriptors;
Expand Down
101 changes: 55 additions & 46 deletions MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.mm
Original file line number Diff line number Diff line change
Expand Up @@ -281,13 +281,9 @@
}
}

MVKDescriptorSet::MVKDescriptorSet(MVKDescriptorSetLayout* layout,
uint32_t variableDescriptorCount,
MVKDescriptorPool* pool) :
MVKVulkanAPIDeviceObject(pool->_device),
_layout(layout),
_variableDescriptorCount(variableDescriptorCount),
_pool(pool) {
VkResult MVKDescriptorSet::allocate(MVKDescriptorSetLayout* layout, uint32_t variableDescriptorCount) {
_layout = layout;
_variableDescriptorCount = variableDescriptorCount;

_descriptors.reserve(layout->getDescriptorCount());
uint32_t bindCnt = (uint32_t)layout->_bindings.size();
Expand All @@ -297,15 +293,25 @@
for (uint32_t descIdx = 0; descIdx < descCnt; descIdx++) {
MVKDescriptor* mvkDesc = nullptr;
setConfigurationResult(_pool->allocateDescriptor(mvkDSLBind->getDescriptorType(), &mvkDesc));
if ( !wasConfigurationSuccessful() ) { break; }
if ( !wasConfigurationSuccessful() ) { return getConfigurationResult(); }
_descriptors.push_back(mvkDesc);
}
if ( !wasConfigurationSuccessful() ) { break; }
}
return getConfigurationResult();
}

MVKDescriptorSet::~MVKDescriptorSet() {
void MVKDescriptorSet::free(bool isPoolReset) {
_layout = nullptr;
_variableDescriptorCount = 0;

for (auto mvkDesc : _descriptors) { _pool->freeDescriptor(mvkDesc); }
_descriptors.clear();

clearConfigurationResult();
}

MVKDescriptorSet::MVKDescriptorSet(MVKDescriptorPool* pool) : MVKVulkanAPIDeviceObject(pool->_device), _pool(pool) {
free(true);
}


Expand Down Expand Up @@ -360,15 +366,6 @@

VkResult MVKDescriptorPool::allocateDescriptorSets(const VkDescriptorSetAllocateInfo* pAllocateInfo,
VkDescriptorSet* pDescriptorSets) {
if (_allocatedSets.size() + pAllocateInfo->descriptorSetCount > _maxSets) {
if (_device->_enabledExtensions.vk_KHR_maintenance1.enabled ||
_device->getInstance()->getAPIVersion() >= VK_API_VERSION_1_1) {
return VK_ERROR_OUT_OF_POOL_MEMORY; // Failure is an acceptable test...don't log as error.
} else {
return reportError(VK_ERROR_INITIALIZATION_FAILED, "The maximum number of descriptor sets that can be allocated by this descriptor pool is %d.", _maxSets);
}
}

VkResult rslt = VK_SUCCESS;
const auto* pVarDescCounts = getVariableDecriptorCounts(pAllocateInfo);
for (uint32_t dsIdx = 0; dsIdx < pAllocateInfo->descriptorSetCount; dsIdx++) {
Expand Down Expand Up @@ -397,21 +394,49 @@
return nullptr;
}

// Ensure descriptor set was actually allocated, then return to pool
// Retieves the first available descriptor set from the pool, and configures it.
// If none are available, returns an error.
VkResult MVKDescriptorPool::allocateDescriptorSet(MVKDescriptorSetLayout* mvkDSL,
uint32_t variableDescriptorCount,
VkDescriptorSet* pVKDS) {

size_t dsIdx = _descriptorSetAvailablility.getIndexOfFirstSetBit(true);
if (dsIdx >= _descriptorSets.size()) { return VK_ERROR_OUT_OF_POOL_MEMORY; }

MVKDescriptorSet* mvkDS = &_descriptorSets[dsIdx];
mvkDS->allocate(mvkDSL, variableDescriptorCount);
if (mvkDS->wasConfigurationSuccessful()) {
*pVKDS = (VkDescriptorSet)mvkDS;
} else {
freeDescriptorSet(mvkDS, false);
}
return mvkDS->getConfigurationResult();
}

VkResult MVKDescriptorPool::freeDescriptorSets(uint32_t count, const VkDescriptorSet* pDescriptorSets) {
for (uint32_t dsIdx = 0; dsIdx < count; dsIdx++) {
MVKDescriptorSet* mvkDS = (MVKDescriptorSet*)pDescriptorSets[dsIdx];
if (_allocatedSets.erase(mvkDS)) {
freeDescriptorSet(mvkDS);
}
freeDescriptorSet((MVKDescriptorSet*)pDescriptorSets[dsIdx], false);
}
return VK_SUCCESS;
}

// Destroy all allocated descriptor sets and reset descriptor pools
// Descriptor sets are held in contiguous memory, so the index of the returning descriptor
// set can be calculated by pointer differences, and it can be marked as available.
void MVKDescriptorPool::freeDescriptorSet(MVKDescriptorSet* mvkDS, bool isPoolReset) {
if ( !mvkDS ) { return; } // Vulkan allows NULL refs.

if (mvkDS->_pool == this) {
mvkDS->free(isPoolReset);
size_t dsIdx = mvkDS - _descriptorSets.data();
_descriptorSetAvailablility.setBit(dsIdx);
} else {
reportError(VK_ERROR_INITIALIZATION_FAILED, "A descriptor set is being returned to a descriptor pool that did not allocate it.");
}
}

// Free all descriptor sets and reset descriptor pools
VkResult MVKDescriptorPool::reset(VkDescriptorPoolResetFlags flags) {
for (auto& mvkDS : _allocatedSets) { freeDescriptorSet(mvkDS); }
_allocatedSets.clear();
for (auto& mvkDS : _descriptorSets) { freeDescriptorSet(&mvkDS, true); }

_uniformBufferDescriptors.reset();
_storageBufferDescriptors.reset();
Expand All @@ -429,23 +454,6 @@
return VK_SUCCESS;
}

VkResult MVKDescriptorPool::allocateDescriptorSet(MVKDescriptorSetLayout* mvkDSL,
uint32_t variableDescriptorCount,
VkDescriptorSet* pVKDS) {
MVKDescriptorSet* mvkDS = new MVKDescriptorSet(mvkDSL, variableDescriptorCount, this);
VkResult rslt = mvkDS->getConfigurationResult();

if (mvkDS->wasConfigurationSuccessful()) {
_allocatedSets.insert(mvkDS);
*pVKDS = (VkDescriptorSet)mvkDS;
} else {
freeDescriptorSet(mvkDS);
}
return rslt;
}

void MVKDescriptorPool::freeDescriptorSet(MVKDescriptorSet* mvkDS) { mvkDS->destroy(); }

// Allocate a descriptor of the specified type
VkResult MVKDescriptorPool::allocateDescriptor(VkDescriptorType descriptorType,
MVKDescriptor** pMVKDesc) {
Expand Down Expand Up @@ -553,6 +561,8 @@ static size_t getPoolSize(const VkDescriptorPoolCreateInfo* pCreateInfo, VkDescr

MVKDescriptorPool::MVKDescriptorPool(MVKDevice* device, const VkDescriptorPoolCreateInfo* pCreateInfo) :
MVKVulkanAPIDeviceObject(device),
_descriptorSets(pCreateInfo->maxSets, MVKDescriptorSet(this)),
_descriptorSetAvailablility(pCreateInfo->maxSets, true),
_uniformBufferDescriptors(getPoolSize(pCreateInfo, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER)),
_storageBufferDescriptors(getPoolSize(pCreateInfo, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)),
_uniformBufferDynamicDescriptors(getPoolSize(pCreateInfo, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC)),
Expand All @@ -564,8 +574,7 @@ static size_t getPoolSize(const VkDescriptorPoolCreateInfo* pCreateInfo, VkDescr
_samplerDescriptors(getPoolSize(pCreateInfo, VK_DESCRIPTOR_TYPE_SAMPLER)),
_combinedImageSamplerDescriptors(getPoolSize(pCreateInfo, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)),
_uniformTexelBufferDescriptors(getPoolSize(pCreateInfo, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER)),
_storageTexelBufferDescriptors(getPoolSize(pCreateInfo, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)),
_maxSets(pCreateInfo->maxSets) {}
_storageTexelBufferDescriptors(getPoolSize(pCreateInfo, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)) {}

MVKDescriptorPool::~MVKDescriptorPool() {
reset(0);
Expand Down

0 comments on commit 4371ef4

Please sign in to comment.