Support preallocated descriptor pooling via VkDescriptorPoolSize.
Add MVK_CONFIG_PREALLOCATE_DESCRIPTORS env var to enable descriptor preallocation
in pool. Add MVKDescriptor subclasses for all used VkDescriptorType values.
Support allocating MVKDescriptor subclasses via direct instantiation,
or referencing preallocated instances held in a fixed collection.
MVKDescriptor subclasses support resetting and reuse from preallocated collection.
MVKDescriptorPool optionally holds collections of preallocated descriptors,
one collection per VkDescriptorType value.
Support VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT to mark preallocated
descriptors as available when freed.
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptor.h b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptor.h
index 833656b..d4ef426 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptor.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptor.h
@@ -140,6 +140,8 @@
/** Returns the Vulkan API opaque object controlling this object. */
MVKVulkanAPIObject* getVulkanAPIObject() override { return nullptr; };
+ virtual VkDescriptorType getDescriptorType() = 0;
+
/** Encodes this descriptor (based on its layout binding index) on the the command encoder. */
virtual void bind(MVKCommandEncoder* cmdEncoder,
VkDescriptorType descriptorType,
@@ -180,6 +182,11 @@
/** Sets the binding layout. */
virtual void setLayout(MVKDescriptorSetLayoutBinding* dslBinding, uint32_t index) {}
+ /** Resets any internal content. */
+ virtual void reset() {}
+
+ ~MVKDescriptor() { reset(); }
+
};
@@ -212,7 +219,9 @@
VkBufferView* pTexelBufferView,
VkWriteDescriptorSetInlineUniformBlockEXT* inlineUniformBlock) override;
- ~MVKBufferDescriptor();
+ void reset() override;
+
+ ~MVKBufferDescriptor() { reset(); }
protected:
MVKBuffer* _mvkBuffer = nullptr;
@@ -222,12 +231,50 @@
#pragma mark -
-#pragma mark MVKInlineUniformDescriptor
+#pragma mark MVKUniformBufferDescriptor
+
+class MVKUniformBufferDescriptor : public MVKBufferDescriptor {
+public:
+ VkDescriptorType getDescriptorType() override { return VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; }
+};
+
+
+#pragma mark -
+#pragma mark MVKUniformBufferDynamicDescriptor
+
+class MVKUniformBufferDynamicDescriptor : public MVKBufferDescriptor {
+public:
+ VkDescriptorType getDescriptorType() override { return VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; }
+};
+
+
+#pragma mark -
+#pragma mark MVKStorageBufferDescriptor
+
+class MVKStorageBufferDescriptor : public MVKBufferDescriptor {
+public:
+ VkDescriptorType getDescriptorType() override { return VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; }
+};
+
+
+#pragma mark -
+#pragma mark MVKStorageBufferDynamicDescriptor
+
+class MVKStorageBufferDynamicDescriptor : public MVKBufferDescriptor {
+public:
+ VkDescriptorType getDescriptorType() override { return VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC; }
+};
+
+
+#pragma mark -
+#pragma mark MVKInlineUniformBlockDescriptor
/** Represents a Vulkan descriptor tracking an inline block of uniform data. */
-class MVKInlineUniformDescriptor : public MVKDescriptor {
+class MVKInlineUniformBlockDescriptor : public MVKDescriptor {
public:
+ VkDescriptorType getDescriptorType() override { return VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT; }
+
void bind(MVKCommandEncoder* cmdEncoder,
VkDescriptorType descriptorType,
uint32_t descriptorIndex,
@@ -250,11 +297,13 @@
VkBufferView* pTexelBufferView,
VkWriteDescriptorSetInlineUniformBlockEXT* inlineUniformBlock) override;
- ~MVKInlineUniformDescriptor();
+ void reset() override;
+
+ ~MVKInlineUniformBlockDescriptor() { reset(); }
protected:
id<MTLBuffer> _mtlBuffer = nil;
- uint32_t _dataSize;
+ uint32_t _dataSize = 0;
};
@@ -287,7 +336,9 @@
VkBufferView* pTexelBufferView,
VkWriteDescriptorSetInlineUniformBlockEXT* inlineUniformBlock) override;
- ~MVKImageDescriptor();
+ void reset() override;
+
+ ~MVKImageDescriptor() { reset(); }
protected:
MVKImageView* _mvkImageView = nullptr;
@@ -296,6 +347,33 @@
#pragma mark -
+#pragma mark MVKSampledImageDescriptor
+
+class MVKSampledImageDescriptor : public MVKImageDescriptor {
+public:
+ VkDescriptorType getDescriptorType() override { return VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; }
+};
+
+
+#pragma mark -
+#pragma mark MVKStorageImageDescriptor
+
+class MVKStorageImageDescriptor : public MVKImageDescriptor {
+public:
+ VkDescriptorType getDescriptorType() override { return VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; }
+};
+
+
+#pragma mark -
+#pragma mark MVKInputAttachmentDescriptor
+
+class MVKInputAttachmentDescriptor : public MVKImageDescriptor {
+public:
+ VkDescriptorType getDescriptorType() override { return VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; }
+};
+
+
+#pragma mark -
#pragma mark MVKSamplerDescriptorMixin
/**
@@ -332,7 +410,9 @@
void setLayout(MVKDescriptorSetLayoutBinding* dslBinding, uint32_t index);
- virtual ~MVKSamplerDescriptorMixin();
+ void reset();
+
+ ~MVKSamplerDescriptorMixin() { reset(); }
MVKSampler* _mvkSampler = nullptr;
bool _hasDynamicSampler = true;
@@ -346,6 +426,8 @@
class MVKSamplerDescriptor : public MVKDescriptor, public MVKSamplerDescriptorMixin {
public:
+ VkDescriptorType getDescriptorType() override { return VK_DESCRIPTOR_TYPE_SAMPLER; }
+
void bind(MVKCommandEncoder* cmdEncoder,
VkDescriptorType descriptorType,
uint32_t descriptorIndex,
@@ -370,6 +452,10 @@
void setLayout(MVKDescriptorSetLayoutBinding* dslBinding, uint32_t index) override;
+ void reset() override;
+
+ ~MVKSamplerDescriptor() { reset(); }
+
};
@@ -380,6 +466,8 @@
class MVKCombinedImageSamplerDescriptor : public MVKImageDescriptor, public MVKSamplerDescriptorMixin {
public:
+ VkDescriptorType getDescriptorType() override { return VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; }
+
void bind(MVKCommandEncoder* cmdEncoder,
VkDescriptorType descriptorType,
uint32_t descriptorIndex,
@@ -404,6 +492,10 @@
void setLayout(MVKDescriptorSetLayoutBinding* dslBinding, uint32_t index) override;
+ void reset() override;
+
+ ~MVKCombinedImageSamplerDescriptor() { reset(); }
+
};
@@ -436,8 +528,28 @@
VkBufferView* pTexelBufferView,
VkWriteDescriptorSetInlineUniformBlockEXT* inlineUniformBlock) override;
- ~MVKTexelBufferDescriptor();
+ void reset() override;
+
+ ~MVKTexelBufferDescriptor() { reset(); }
protected:
MVKBufferView* _mvkBufferView = nullptr;
};
+
+
+#pragma mark -
+#pragma mark MVKUniformTexelBufferDescriptor
+
+class MVKUniformTexelBufferDescriptor : public MVKTexelBufferDescriptor {
+public:
+ VkDescriptorType getDescriptorType() override { return VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; }
+};
+
+
+#pragma mark -
+#pragma mark MVKStorageTexelBufferDescriptor
+
+class MVKStorageTexelBufferDescriptor : public MVKTexelBufferDescriptor {
+public:
+ VkDescriptorType getDescriptorType() override { return VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; }
+};
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptor.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptor.mm
index 17f3445..74d0b4a 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptor.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptor.mm
@@ -20,9 +20,6 @@
#include "MVKDescriptorSet.h"
#include "MVKBuffer.h"
-using namespace std;
-using namespace mvk;
-
#pragma mark MVKShaderStageResourceBinding
@@ -45,15 +42,15 @@
#pragma mark MVKShaderResourceBinding
uint32_t MVKShaderResourceBinding::getMaxBufferIndex() {
- return max({stages[kMVKShaderStageVertex].bufferIndex, stages[kMVKShaderStageTessCtl].bufferIndex, stages[kMVKShaderStageTessEval].bufferIndex, stages[kMVKShaderStageFragment].bufferIndex, stages[kMVKShaderStageCompute].bufferIndex});
+ return std::max({stages[kMVKShaderStageVertex].bufferIndex, stages[kMVKShaderStageTessCtl].bufferIndex, stages[kMVKShaderStageTessEval].bufferIndex, stages[kMVKShaderStageFragment].bufferIndex, stages[kMVKShaderStageCompute].bufferIndex});
}
uint32_t MVKShaderResourceBinding::getMaxTextureIndex() {
- return max({stages[kMVKShaderStageVertex].textureIndex, stages[kMVKShaderStageTessCtl].textureIndex, stages[kMVKShaderStageTessEval].textureIndex, stages[kMVKShaderStageFragment].textureIndex, stages[kMVKShaderStageCompute].textureIndex});
+ return std::max({stages[kMVKShaderStageVertex].textureIndex, stages[kMVKShaderStageTessCtl].textureIndex, stages[kMVKShaderStageTessEval].textureIndex, stages[kMVKShaderStageFragment].textureIndex, stages[kMVKShaderStageCompute].textureIndex});
}
uint32_t MVKShaderResourceBinding::getMaxSamplerIndex() {
- return max({stages[kMVKShaderStageVertex].samplerIndex, stages[kMVKShaderStageTessCtl].samplerIndex, stages[kMVKShaderStageTessEval].samplerIndex, stages[kMVKShaderStageFragment].samplerIndex, stages[kMVKShaderStageCompute].samplerIndex});
+ return std::max({stages[kMVKShaderStageVertex].samplerIndex, stages[kMVKShaderStageTessCtl].samplerIndex, stages[kMVKShaderStageTessEval].samplerIndex, stages[kMVKShaderStageFragment].samplerIndex, stages[kMVKShaderStageCompute].samplerIndex});
}
MVKShaderResourceBinding MVKShaderResourceBinding::operator+ (const MVKShaderResourceBinding& rhs) {
@@ -303,7 +300,7 @@
return true;
}
-void MVKDescriptorSetLayoutBinding::populateShaderConverterContext(SPIRVToMSLConversionConfiguration& context,
+void MVKDescriptorSetLayoutBinding::populateShaderConverterContext(mvk::SPIRVToMSLConversionConfiguration& context,
MVKShaderResourceBinding& dslMTLRezIdxOffsets,
uint32_t dslIndex) {
@@ -534,16 +531,20 @@
}
}
-MVKBufferDescriptor::~MVKBufferDescriptor() {
+void MVKBufferDescriptor::reset() {
if (_mvkBuffer) { _mvkBuffer->release(); }
+ _mvkBuffer = nullptr;
+ _buffOffset = 0;
+ _buffRange = 0;
+ MVKDescriptor::reset();
}
#pragma mark -
-#pragma mark MVKInlineUniformDescriptor
+#pragma mark MVKInlineUniformBlockDescriptor
// A null cmdEncoder can be passed to perform a validation pass
-void MVKInlineUniformDescriptor::bind(MVKCommandEncoder* cmdEncoder,
+void MVKInlineUniformBlockDescriptor::bind(MVKCommandEncoder* cmdEncoder,
VkDescriptorType descriptorType,
uint32_t descriptorIndex,
bool stages[],
@@ -574,7 +575,7 @@
}
}
-void MVKInlineUniformDescriptor::write(MVKDescriptorSet* mvkDescSet,
+void MVKInlineUniformBlockDescriptor::write(MVKDescriptorSet* mvkDescSet,
VkDescriptorType descriptorType,
uint32_t srcIndex,
size_t stride,
@@ -602,7 +603,7 @@
}
}
-void MVKInlineUniformDescriptor::read(MVKDescriptorSet* mvkDescSet,
+void MVKInlineUniformBlockDescriptor::read(MVKDescriptorSet* mvkDescSet,
VkDescriptorType descriptorType,
uint32_t dstIndex,
VkDescriptorImageInfo* pImageInfo,
@@ -628,8 +629,11 @@
}
}
-MVKInlineUniformDescriptor::~MVKInlineUniformDescriptor() {
+void MVKInlineUniformBlockDescriptor::reset() {
[_mtlBuffer release];
+ _mtlBuffer = nil;
+ _dataSize = 0;
+ MVKDescriptor::reset();
}
@@ -726,8 +730,11 @@
}
}
-MVKImageDescriptor::~MVKImageDescriptor() {
+void MVKImageDescriptor::reset() {
if (_mvkImageView) { _mvkImageView->release(); }
+ _mvkImageView = nullptr;
+ _imageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ MVKDescriptor::reset();
}
@@ -845,8 +852,10 @@
if (oldSamp) { oldSamp->release(); }
}
-MVKSamplerDescriptorMixin::~MVKSamplerDescriptorMixin() {
+void MVKSamplerDescriptorMixin::reset() {
if (_mvkSampler) { _mvkSampler->release(); }
+ _mvkSampler = nullptr;
+ _hasDynamicSampler = true;
}
@@ -913,6 +922,11 @@
MVKSamplerDescriptorMixin::setLayout(dslBinding, index);
}
+void MVKSamplerDescriptor::reset() {
+ MVKSamplerDescriptorMixin::reset();
+ MVKDescriptor::reset();
+}
+
#pragma mark -
#pragma mark MVKCombinedImageSamplerDescriptor
@@ -982,6 +996,11 @@
MVKSamplerDescriptorMixin::setLayout(dslBinding, index);
}
+void MVKCombinedImageSamplerDescriptor::reset() {
+ MVKSamplerDescriptorMixin::reset();
+ MVKImageDescriptor::reset();
+}
+
#pragma mark -
#pragma mark MVKTexelBufferDescriptor
@@ -1062,6 +1081,8 @@
}
}
-MVKTexelBufferDescriptor::~MVKTexelBufferDescriptor() {
+void MVKTexelBufferDescriptor::reset() {
if (_mvkBufferView) { _mvkBufferView->release(); }
+ _mvkBufferView = nullptr;
+ MVKDescriptor::reset();
}
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.h b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.h
index ea8c4f4..212fc63 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.h
@@ -142,9 +142,70 @@
#pragma mark -
-#pragma mark MVKDescriptorPool
+#pragma mark MVKDescriptorTypePreallocation
-typedef MVKDeviceObjectPool<MVKDescriptorSet> MVKDescriptorSetPool;
+/** Support class for MVKDescriptorPool that holds preallocated instances of a single concrete descriptor class. */
+template<class DescriptorClass>
+class MVKDescriptorTypePreallocation : public MVKBaseObject {
+
+public:
+
+ /** Returns the Vulkan API opaque object controlling this object. */
+ MVKVulkanAPIObject* getVulkanAPIObject() override { return nullptr; };
+
+ MVKDescriptorTypePreallocation(const VkDescriptorPoolCreateInfo* pCreateInfo,
+ VkDescriptorType descriptorType);
+
+protected:
+ friend class MVKPreallocatedDescriptors;
+
+ VkResult allocateDescriptor(MVKDescriptor** pMVKDesc);
+ bool findDescriptor(uint32_t endIndex, MVKDescriptor** pMVKDesc);
+ void freeDescriptor(MVKDescriptor* mvkDesc);
+
+ std::vector<DescriptorClass> _descriptors;
+ std::vector<bool> _availability;
+ uint32_t _nextAvailableIndex;
+ bool _supportAvailability;
+};
+
+
+#pragma mark -
+#pragma mark MVKPreallocatedDescriptors
+
+/** Support class for MVKDescriptorPool that holds preallocated instances of all concrete descriptor classes. */
+class MVKPreallocatedDescriptors : public MVKBaseObject {
+
+public:
+
+ /** Returns the Vulkan API opaque object controlling this object. */
+ MVKVulkanAPIObject* getVulkanAPIObject() override { return nullptr; };
+
+ MVKPreallocatedDescriptors(const VkDescriptorPoolCreateInfo* pCreateInfo);
+
+protected:
+ friend class MVKDescriptorPool;
+
+ VkResult allocateDescriptor(VkDescriptorType descriptorType, MVKDescriptor** pMVKDesc);
+ void freeDescriptor(MVKDescriptor* mvkDesc);
+
+ MVKDescriptorTypePreallocation<MVKUniformBufferDescriptor> _uniformBufferDescriptors;
+ MVKDescriptorTypePreallocation<MVKStorageBufferDescriptor> _storageBufferDescriptors;
+ MVKDescriptorTypePreallocation<MVKUniformBufferDynamicDescriptor> _uniformBufferDynamicDescriptors;
+ MVKDescriptorTypePreallocation<MVKStorageBufferDynamicDescriptor> _storageBufferDynamicDescriptors;
+ MVKDescriptorTypePreallocation<MVKInlineUniformBlockDescriptor> _inlineUniformBlockDescriptors;
+ MVKDescriptorTypePreallocation<MVKSampledImageDescriptor> _sampledImageDescriptors;
+ MVKDescriptorTypePreallocation<MVKStorageImageDescriptor> _storageImageDescriptors;
+ MVKDescriptorTypePreallocation<MVKInputAttachmentDescriptor> _inputAttachmentDescriptors;
+ MVKDescriptorTypePreallocation<MVKSamplerDescriptor> _samplerDescriptors;
+ MVKDescriptorTypePreallocation<MVKCombinedImageSamplerDescriptor> _combinedImageSamplerDescriptors;
+ MVKDescriptorTypePreallocation<MVKUniformTexelBufferDescriptor> _uniformTexelBufferDescriptors;
+ MVKDescriptorTypePreallocation<MVKStorageTexelBufferDescriptor> _storageTexelBufferDescriptors;
+};
+
+
+#pragma mark -
+#pragma mark MVKDescriptorPool
/** Represents a Vulkan descriptor pool. */
class MVKDescriptorPool : public MVKVulkanAPIDeviceObject {
@@ -183,6 +244,7 @@
uint32_t _maxSets;
std::unordered_set<MVKDescriptorSet*> _allocatedSets;
+ MVKPreallocatedDescriptors* _preallocatedDescriptors;
};
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.mm
index a13b689..cfecbfd 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.mm
@@ -17,8 +17,7 @@
*/
#include "MVKDescriptorSet.h"
-
-using namespace mvk;
+#include "MVKOSExtensions.h"
#pragma mark -
@@ -174,7 +173,7 @@
}
}
-void MVKDescriptorSetLayout::populateShaderConverterContext(SPIRVToMSLConversionConfiguration& context,
+void MVKDescriptorSetLayout::populateShaderConverterContext(mvk::SPIRVToMSLConversionConfiguration& context,
MVKShaderResourceBinding& dslMTLRezIdxOffsets,
uint32_t dslIndex) {
uint32_t bindCnt = (uint32_t)_bindings.size();
@@ -270,6 +269,220 @@
#pragma mark -
+#pragma mark MVKDescriptorTypePreallocation
+
+#ifndef MVK_CONFIG_PREALLOCATE_DESCRIPTORS
+# define MVK_CONFIG_PREALLOCATE_DESCRIPTORS 0
+#endif
+
+static bool _mvkPreallocateDescriptors = MVK_CONFIG_PREALLOCATE_DESCRIPTORS;
+static bool _mvkPreallocateDescriptorsInitialized = false;
+
+// Returns whether descriptors should be preallocated in the descriptor pools
+// We do this once lazily instead of in a library constructor function to
+// ensure the NSProcessInfo environment is available when called upon.
+static inline bool getMVKPreallocateDescriptors() {
+ if ( !_mvkPreallocateDescriptorsInitialized ) {
+ _mvkPreallocateDescriptorsInitialized = true;
+ MVK_SET_FROM_ENV_OR_BUILD_BOOL(_mvkPreallocateDescriptors, MVK_CONFIG_PREALLOCATE_DESCRIPTORS);
+ }
+ return _mvkPreallocateDescriptors;
+}
+
+template<class DescriptorClass>
+VkResult MVKDescriptorTypePreallocation<DescriptorClass>::allocateDescriptor(MVKDescriptor** pMVKDesc) {
+
+ uint32_t descCnt = (uint32_t)_descriptors.size();
+
+ // Preallocated descriptors that CANNOT be freed.
+ // Next available index can only monotonically increase towards the limit.
+ if ( !_supportAvailability ) {
+ if (_nextAvailableIndex < descCnt) {
+ *pMVKDesc = &_descriptors[_nextAvailableIndex++];
+ return VK_SUCCESS;
+ } else {
+ return VK_ERROR_OUT_OF_POOL_MEMORY;
+ }
+ }
+
+ // Descriptors that CAN be freed.
+ // An available index might exist anywhere in the pool of descriptors.
+ uint32_t origNextAvailPoolIdx = _nextAvailableIndex;
+
+ // First start looking from most recently found available slot
+ if (findDescriptor(descCnt, pMVKDesc)) { return VK_SUCCESS; }
+
+ // Then look from beginning of the collection, in case any previous descriptors were freed
+ _nextAvailableIndex = 0;
+ if (findDescriptor(origNextAvailPoolIdx, pMVKDesc)) { return VK_SUCCESS; }
+
+ return VK_ERROR_OUT_OF_POOL_MEMORY;
+}
+
+// Find a descriptor within a range in a preallocated collection based on availability,
+// and return true if found, false if not
+template<typename DescriptorClass>
+bool MVKDescriptorTypePreallocation<DescriptorClass>::findDescriptor(uint32_t endIndex,
+ MVKDescriptor** pMVKDesc) {
+ while (_nextAvailableIndex < endIndex) {
+ if (_availability[_nextAvailableIndex]) {
+ _availability[_nextAvailableIndex] = false;
+ *pMVKDesc = &_descriptors[_nextAvailableIndex];
+ _nextAvailableIndex++;
+ return true;
+ }
+ _nextAvailableIndex++;
+ }
+ return false;
+}
+
+// Reset a descriptor and mark it available, if applicable
+template<typename DescriptorClass>
+void MVKDescriptorTypePreallocation<DescriptorClass>::freeDescriptor(MVKDescriptor* mvkDesc) {
+
+ mvkDesc->reset();
+
+ if (_supportAvailability) {
+ bool found = false;
+ size_t descCnt = _descriptors.size();
+ for (uint32_t descIdx = 0; !found && descIdx < descCnt; descIdx++) {
+ if (&_descriptors[descIdx] == mvkDesc) {
+ found = true;
+ _availability[descIdx] = true;
+ }
+ }
+ }
+}
+
+template<typename DescriptorClass>
+MVKDescriptorTypePreallocation<DescriptorClass>::MVKDescriptorTypePreallocation(const VkDescriptorPoolCreateInfo* pCreateInfo,
+ VkDescriptorType descriptorType) {
+ // There may be more than one poolSizeCount instance for the desired VkDescriptorType.
+ // Accumulate the descriptor count for the desired VkDescriptorType, and size the collections accordingly.
+ uint32_t descriptorCount = 0;
+ uint32_t poolCnt = pCreateInfo->poolSizeCount;
+ for (uint32_t poolIdx = 0; poolIdx < poolCnt; poolIdx++) {
+ auto& poolSize = pCreateInfo->pPoolSizes[poolIdx];
+ if (poolSize.type == descriptorType) { descriptorCount += poolSize.descriptorCount; }
+ }
+ _descriptors.resize(descriptorCount);
+
+ // Determine whether we need to track the availability of previously freed descriptors.
+ _supportAvailability = mvkIsAnyFlagEnabled(pCreateInfo->flags, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT);
+ if (_supportAvailability) { _availability.resize(descriptorCount, true); }
+ _nextAvailableIndex = 0;
+}
+
+
+#pragma mark -
+#pragma mark MVKPreallocatedDescriptors
+
+// Allocate a descriptor of the specified type
+VkResult MVKPreallocatedDescriptors::allocateDescriptor(VkDescriptorType descriptorType,
+ MVKDescriptor** pMVKDesc) {
+ switch (descriptorType) {
+ case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
+ return _uniformBufferDescriptors.allocateDescriptor(pMVKDesc);
+
+ case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
+ return _storageBufferDescriptors.allocateDescriptor(pMVKDesc);
+
+ case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
+ return _uniformBufferDynamicDescriptors.allocateDescriptor(pMVKDesc);
+
+ case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
+ return _storageBufferDynamicDescriptors.allocateDescriptor(pMVKDesc);
+
+ case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT:
+ return _inlineUniformBlockDescriptors.allocateDescriptor(pMVKDesc);
+
+ case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
+ return _sampledImageDescriptors.allocateDescriptor(pMVKDesc);
+
+ case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
+ return _storageImageDescriptors.allocateDescriptor(pMVKDesc);
+
+ case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
+ return _inputAttachmentDescriptors.allocateDescriptor(pMVKDesc);
+
+ case VK_DESCRIPTOR_TYPE_SAMPLER:
+ return _samplerDescriptors.allocateDescriptor(pMVKDesc);
+
+ case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
+ return _combinedImageSamplerDescriptors.allocateDescriptor(pMVKDesc);
+
+ case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
+ return _uniformTexelBufferDescriptors.allocateDescriptor(pMVKDesc);
+
+ case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
+ return _storageTexelBufferDescriptors.allocateDescriptor(pMVKDesc);
+
+ default:
+ return reportError(VK_ERROR_INITIALIZATION_FAILED, "Unrecognized VkDescriptorType %d.", descriptorType);
+ }
+}
+
+void MVKPreallocatedDescriptors::freeDescriptor(MVKDescriptor* mvkDesc) {
+ VkDescriptorType descriptorType = mvkDesc->getDescriptorType();
+ switch (descriptorType) {
+ case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
+ return _uniformBufferDescriptors.freeDescriptor(mvkDesc);
+
+ case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
+ return _storageBufferDescriptors.freeDescriptor(mvkDesc);
+
+ case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
+ return _uniformBufferDynamicDescriptors.freeDescriptor(mvkDesc);
+
+ case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
+ return _storageBufferDynamicDescriptors.freeDescriptor(mvkDesc);
+
+ case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT:
+ return _inlineUniformBlockDescriptors.freeDescriptor(mvkDesc);
+
+ case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
+ return _sampledImageDescriptors.freeDescriptor(mvkDesc);
+
+ case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
+ return _storageImageDescriptors.freeDescriptor(mvkDesc);
+
+ case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
+ return _inputAttachmentDescriptors.freeDescriptor(mvkDesc);
+
+ case VK_DESCRIPTOR_TYPE_SAMPLER:
+ return _samplerDescriptors.freeDescriptor(mvkDesc);
+
+ case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
+ return _combinedImageSamplerDescriptors.freeDescriptor(mvkDesc);
+
+ case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
+ return _uniformTexelBufferDescriptors.freeDescriptor(mvkDesc);
+
+ case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
+ return _storageTexelBufferDescriptors.freeDescriptor(mvkDesc);
+
+ default:
+ reportError(VK_ERROR_INITIALIZATION_FAILED, "Unrecognized VkDescriptorType %d.", descriptorType);
+ }
+}
+
+MVKPreallocatedDescriptors::MVKPreallocatedDescriptors(const VkDescriptorPoolCreateInfo* pCreateInfo) :
+ _uniformBufferDescriptors(pCreateInfo, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER),
+ _storageBufferDescriptors(pCreateInfo, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER),
+ _uniformBufferDynamicDescriptors(pCreateInfo, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC),
+ _storageBufferDynamicDescriptors(pCreateInfo, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC),
+ _inlineUniformBlockDescriptors(pCreateInfo, VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT),
+ _sampledImageDescriptors(pCreateInfo, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE),
+ _storageImageDescriptors(pCreateInfo, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE),
+ _inputAttachmentDescriptors(pCreateInfo, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT),
+ _samplerDescriptors(pCreateInfo, VK_DESCRIPTOR_TYPE_SAMPLER),
+ _combinedImageSamplerDescriptors(pCreateInfo, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER),
+ _uniformTexelBufferDescriptors(pCreateInfo, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER),
+ _storageTexelBufferDescriptors(pCreateInfo, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER) {
+}
+
+
+#pragma mark -
#pragma mark MVKDescriptorPool
VkResult MVKDescriptorPool::allocateDescriptorSets(uint32_t count,
@@ -327,54 +540,90 @@
void MVKDescriptorPool::freeDescriptorSet(MVKDescriptorSet* mvkDS) { mvkDS->destroy(); }
+// Allocate a descriptor of the specified type
VkResult MVKDescriptorPool::allocateDescriptor(VkDescriptorType descriptorType,
MVKDescriptor** pMVKDesc) {
+
+ // If descriptors are preallocated allocate from the preallocated pools
+ if (_preallocatedDescriptors) {
+ return _preallocatedDescriptors->allocateDescriptor(descriptorType, pMVKDesc);
+ }
+
+ // Otherwise instantiate one of the apporpriate type now
switch (descriptorType) {
- case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
- case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
+ *pMVKDesc = new MVKUniformBufferDescriptor();
+ break;
+
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
- *pMVKDesc = new MVKBufferDescriptor();
- return VK_SUCCESS;
+ *pMVKDesc = new MVKStorageBufferDescriptor();
+ break;
+
+ case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
+ *pMVKDesc = new MVKUniformBufferDynamicDescriptor();
+ break;
+
+ case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
+ *pMVKDesc = new MVKStorageBufferDynamicDescriptor();
+ break;
case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT:
- *pMVKDesc = new MVKInlineUniformDescriptor();
- return VK_SUCCESS;
+ *pMVKDesc = new MVKInlineUniformBlockDescriptor();
+ break;
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
+ *pMVKDesc = new MVKSampledImageDescriptor();
+ break;
+
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
+ *pMVKDesc = new MVKStorageImageDescriptor();
+ break;
+
case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
- *pMVKDesc = new MVKImageDescriptor();
- return VK_SUCCESS;
+ *pMVKDesc = new MVKInputAttachmentDescriptor();
+ break;
case VK_DESCRIPTOR_TYPE_SAMPLER:
*pMVKDesc = new MVKSamplerDescriptor();
- return VK_SUCCESS;
+ break;
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
*pMVKDesc = new MVKCombinedImageSamplerDescriptor();
- return VK_SUCCESS;
+ break;
case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
+ *pMVKDesc = new MVKUniformTexelBufferDescriptor();
+ break;
+
case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
- *pMVKDesc = new MVKTexelBufferDescriptor();
- return VK_SUCCESS;
+ *pMVKDesc = new MVKStorageTexelBufferDescriptor();
+ break;
default:
return reportError(VK_ERROR_INITIALIZATION_FAILED, "Unrecognized VkDescriptorType %d.", descriptorType);
}
+ return VK_SUCCESS;
}
-void MVKDescriptorPool::freeDescriptor(MVKDescriptor* mvkDesc) { mvkDesc->destroy(); }
+// Free a descriptor, either through the preallocated pool, or directly destroy it
+void MVKDescriptorPool::freeDescriptor(MVKDescriptor* mvkDesc) {
+ if (_preallocatedDescriptors) {
+ _preallocatedDescriptors->freeDescriptor(mvkDesc);
+ } else {
+ mvkDesc->destroy();
+ }
+}
MVKDescriptorPool::MVKDescriptorPool(MVKDevice* device,
const VkDescriptorPoolCreateInfo* pCreateInfo) : MVKVulkanAPIDeviceObject(device) {
_maxSets = pCreateInfo->maxSets;
+ _preallocatedDescriptors = getMVKPreallocateDescriptors() ? new MVKPreallocatedDescriptors(pCreateInfo) : nullptr;
}
-// Destroy all allocated descriptor sets
+// Destroy all allocated descriptor sets and preallocated descriptors
MVKDescriptorPool::~MVKDescriptorPool() {
reset(0);
+ if (_preallocatedDescriptors) { _preallocatedDescriptors->destroy(); }
}
@@ -478,13 +727,13 @@
}
}
-void mvkPopulateShaderConverterContext(SPIRVToMSLConversionConfiguration& context,
+void mvkPopulateShaderConverterContext(mvk::SPIRVToMSLConversionConfiguration& context,
MVKShaderStageResourceBinding& ssRB,
spv::ExecutionModel stage,
uint32_t descriptorSetIndex,
uint32_t bindingIndex,
MVKSampler* immutableSampler) {
- MSLResourceBinding rb;
+ mvk::MSLResourceBinding rb;
auto& rbb = rb.resourceBinding;
rbb.stage = stage;