Refactor preallocated descriptor handling.
Add MVKBitArray class. Consolidate MVKPreallocatedDescriptors into MVKDescriptorPool and remove MVKPreallocatedDescriptors.
This commit is contained in:
parent
20b5067ee5
commit
984a74fffd
@ -325,6 +325,9 @@
|
||||
A9C96DD31DDC20C20053187F /* MVKMTLBufferAllocation.mm in Sources */ = {isa = PBXBuildFile; fileRef = A9C96DCF1DDC20C20053187F /* MVKMTLBufferAllocation.mm */; };
|
||||
A9CEAAD5227378D400FAF779 /* mvk_datatypes.hpp in Headers */ = {isa = PBXBuildFile; fileRef = A9CEAAD1227378D400FAF779 /* mvk_datatypes.hpp */; };
|
||||
A9CEAAD6227378D400FAF779 /* mvk_datatypes.hpp in Headers */ = {isa = PBXBuildFile; fileRef = A9CEAAD1227378D400FAF779 /* mvk_datatypes.hpp */; };
|
||||
A9D7104F25CDE05E00E38106 /* MVKBitArray.h in Headers */ = {isa = PBXBuildFile; fileRef = A9D7104E25CDE05E00E38106 /* MVKBitArray.h */; };
|
||||
A9D7105025CDE05E00E38106 /* MVKBitArray.h in Headers */ = {isa = PBXBuildFile; fileRef = A9D7104E25CDE05E00E38106 /* MVKBitArray.h */; };
|
||||
A9D7105125CDE05E00E38106 /* MVKBitArray.h in Headers */ = {isa = PBXBuildFile; fileRef = A9D7104E25CDE05E00E38106 /* MVKBitArray.h */; };
|
||||
A9E4B7891E1D8AF10046A4CE /* MVKMTLResourceBindings.h in Headers */ = {isa = PBXBuildFile; fileRef = A9E4B7881E1D8AF10046A4CE /* MVKMTLResourceBindings.h */; };
|
||||
A9E4B78A1E1D8AF10046A4CE /* MVKMTLResourceBindings.h in Headers */ = {isa = PBXBuildFile; fileRef = A9E4B7881E1D8AF10046A4CE /* MVKMTLResourceBindings.h */; };
|
||||
A9E53DD72100B197002781DD /* MTLSamplerDescriptor+MoltenVK.m in Sources */ = {isa = PBXBuildFile; fileRef = A9E53DCD2100B197002781DD /* MTLSamplerDescriptor+MoltenVK.m */; };
|
||||
@ -523,6 +526,7 @@
|
||||
A9C96DCF1DDC20C20053187F /* MVKMTLBufferAllocation.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MVKMTLBufferAllocation.mm; sourceTree = "<group>"; };
|
||||
A9CBEE011B6299D800E45FDC /* libMoltenVK.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libMoltenVK.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
A9CEAAD1227378D400FAF779 /* mvk_datatypes.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = mvk_datatypes.hpp; sourceTree = "<group>"; };
|
||||
A9D7104E25CDE05E00E38106 /* MVKBitArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVKBitArray.h; sourceTree = "<group>"; };
|
||||
A9DE1083200598C500F18F80 /* icd */ = {isa = PBXFileReference; lastKnownFileType = folder; path = icd; sourceTree = "<group>"; };
|
||||
A9E4B7881E1D8AF10046A4CE /* MVKMTLResourceBindings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVKMTLResourceBindings.h; sourceTree = "<group>"; };
|
||||
A9E53DCD2100B197002781DD /* MTLSamplerDescriptor+MoltenVK.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MTLSamplerDescriptor+MoltenVK.m"; sourceTree = "<group>"; };
|
||||
@ -678,6 +682,7 @@
|
||||
children = (
|
||||
A98149421FB6A3F7005F00B4 /* MVKBaseObject.h */,
|
||||
A98149411FB6A3F7005F00B4 /* MVKBaseObject.mm */,
|
||||
A9D7104E25CDE05E00E38106 /* MVKBitArray.h */,
|
||||
4553AEFA2251617100E8EBCD /* MVKBlockObserver.h */,
|
||||
4553AEF62251617100E8EBCD /* MVKBlockObserver.m */,
|
||||
45557A4D21C9EFF3008868BD /* MVKCodec.cpp */,
|
||||
@ -792,6 +797,7 @@
|
||||
2FEA0A4624902F9F00EEF3AD /* MVKSurface.h in Headers */,
|
||||
2FEA0A4724902F9F00EEF3AD /* MTLRenderPipelineDescriptor+MoltenVK.h in Headers */,
|
||||
2FEA0A4824902F9F00EEF3AD /* MVKInstance.h in Headers */,
|
||||
A9D7105025CDE05E00E38106 /* MVKBitArray.h in Headers */,
|
||||
2FEA0A4924902F9F00EEF3AD /* MVKCommandResourceFactory.h in Headers */,
|
||||
2FEA0A4A24902F9F00EEF3AD /* MVKQueryPool.h in Headers */,
|
||||
2FEA0A4B24902F9F00EEF3AD /* MVKCommandEncoderState.h in Headers */,
|
||||
@ -868,6 +874,7 @@
|
||||
A95B7D691D3EE486003183D3 /* MVKCommandEncoderState.h in Headers */,
|
||||
A94FB7D81C7DFB4800632CA3 /* MVKCommandPipelineStateFactoryShaderSource.h in Headers */,
|
||||
A94FB7E01C7DFB4800632CA3 /* MVKDescriptorSet.h in Headers */,
|
||||
A9D7104F25CDE05E00E38106 /* MVKBitArray.h in Headers */,
|
||||
A9E53DE12100B197002781DD /* NSString+MoltenVK.h in Headers */,
|
||||
A9E53DDF2100B197002781DD /* CAMetalLayer+MoltenVK.h in Headers */,
|
||||
45557A5421C9EFF3008868BD /* MVKCodec.h in Headers */,
|
||||
@ -940,6 +947,7 @@
|
||||
A95B7D6A1D3EE486003183D3 /* MVKCommandEncoderState.h in Headers */,
|
||||
A94FB7D91C7DFB4800632CA3 /* MVKCommandPipelineStateFactoryShaderSource.h in Headers */,
|
||||
A94FB7E11C7DFB4800632CA3 /* MVKDescriptorSet.h in Headers */,
|
||||
A9D7105125CDE05E00E38106 /* MVKBitArray.h in Headers */,
|
||||
A9E53DE22100B197002781DD /* NSString+MoltenVK.h in Headers */,
|
||||
A9E53DE02100B197002781DD /* CAMetalLayer+MoltenVK.h in Headers */,
|
||||
45557A5521C9EFF3008868BD /* MVKCodec.h in Headers */,
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
#include "MVKDescriptor.h"
|
||||
#include "MVKSmallVector.h"
|
||||
#include "MVKBitArray.h"
|
||||
#include <unordered_set>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
@ -155,59 +156,20 @@ 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);
|
||||
void reset();
|
||||
|
||||
MVKSmallVector<DescriptorClass> _descriptors;
|
||||
MVKSmallVector<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);
|
||||
MVKDescriptorTypePreallocation(size_t poolSize);
|
||||
|
||||
protected:
|
||||
friend class MVKDescriptorPool;
|
||||
|
||||
VkResult allocateDescriptor(VkDescriptorType descriptorType, MVKDescriptor** pMVKDesc);
|
||||
inline bool isPreallocated() { return _availability.size() > 0; }
|
||||
VkResult allocateDescriptor(MVKDescriptor** pMVKDesc);
|
||||
void freeDescriptor(MVKDescriptor* mvkDesc);
|
||||
void reset();
|
||||
|
||||
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;
|
||||
MVKSmallVector<DescriptorClass> _descriptors;
|
||||
MVKBitArray _availability;
|
||||
};
|
||||
|
||||
|
||||
@ -251,7 +213,19 @@ protected:
|
||||
|
||||
uint32_t _maxSets;
|
||||
std::unordered_set<MVKDescriptorSet*> _allocatedSets;
|
||||
MVKPreallocatedDescriptors* _preallocatedDescriptors;
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
|
||||
|
@ -312,217 +312,47 @@ MVKDescriptorSet::~MVKDescriptorSet() {
|
||||
#pragma mark -
|
||||
#pragma mark MVKDescriptorTypePreallocation
|
||||
|
||||
// If preallocated, find the next availalble descriptor.
|
||||
// If not preallocated, create one on the fly.
|
||||
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;
|
||||
}
|
||||
DescriptorClass* mvkDesc;
|
||||
if (isPreallocated()) {
|
||||
size_t availDescIdx = _availability.getIndexOfFirstSetBit(true);
|
||||
if (availDescIdx >= _availability.size()) { return VK_ERROR_OUT_OF_POOL_MEMORY; }
|
||||
mvkDesc = &_descriptors[availDescIdx];
|
||||
mvkDesc->reset(); // Clear before reusing.
|
||||
} else {
|
||||
mvkDesc = new DescriptorClass();
|
||||
}
|
||||
|
||||
// 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;
|
||||
*pMVKDesc = mvkDesc;
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
// 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
|
||||
// If preallocated, descriptors are held in contiguous memory, so the index of the returning
|
||||
// descriptor can be calculated by pointer differences, and it can be marked as available.
|
||||
// The descriptor will be reset when it is re-allocated. This streamlines the reset() of this pool.
|
||||
// If not preallocated, simply destroy returning descriptor.
|
||||
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;
|
||||
}
|
||||
}
|
||||
if (isPreallocated()) {
|
||||
size_t descIdx = (DescriptorClass*)mvkDesc - _descriptors.data();
|
||||
_availability.setBit(descIdx);
|
||||
} else {
|
||||
mvkDesc->destroy();
|
||||
}
|
||||
}
|
||||
|
||||
// Preallocated descriptors will be reset when they are reused
|
||||
template<typename DescriptorClass>
|
||||
void MVKDescriptorTypePreallocation<DescriptorClass>::reset() {
|
||||
_nextAvailableIndex = 0;
|
||||
_availability.setAllBits();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void MVKPreallocatedDescriptors::reset() {
|
||||
_uniformBufferDescriptors.reset();
|
||||
_storageBufferDescriptors.reset();
|
||||
_uniformBufferDynamicDescriptors.reset();
|
||||
_storageBufferDynamicDescriptors.reset();
|
||||
_inlineUniformBlockDescriptors.reset();
|
||||
_sampledImageDescriptors.reset();
|
||||
_storageImageDescriptors.reset();
|
||||
_inputAttachmentDescriptors.reset();
|
||||
_samplerDescriptors.reset();
|
||||
_combinedImageSamplerDescriptors.reset();
|
||||
_uniformTexelBufferDescriptors.reset();
|
||||
_storageTexelBufferDescriptors.reset();
|
||||
}
|
||||
|
||||
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) {
|
||||
}
|
||||
MVKDescriptorTypePreallocation<DescriptorClass>::MVKDescriptorTypePreallocation(size_t poolSize) :
|
||||
_descriptors(poolSize),
|
||||
_availability(poolSize, true) {}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
@ -578,11 +408,24 @@ VkResult MVKDescriptorPool::freeDescriptorSets(uint32_t count, const VkDescripto
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
// Destroy all allocated descriptor sets
|
||||
// Destroy all allocated descriptor sets and reset descriptor pools
|
||||
VkResult MVKDescriptorPool::reset(VkDescriptorPoolResetFlags flags) {
|
||||
for (auto& mvkDS : _allocatedSets) { freeDescriptorSet(mvkDS); }
|
||||
_allocatedSets.clear();
|
||||
if (_preallocatedDescriptors) { _preallocatedDescriptors->reset(); }
|
||||
|
||||
_uniformBufferDescriptors.reset();
|
||||
_storageBufferDescriptors.reset();
|
||||
_uniformBufferDynamicDescriptors.reset();
|
||||
_storageBufferDynamicDescriptors.reset();
|
||||
_inlineUniformBlockDescriptors.reset();
|
||||
_sampledImageDescriptors.reset();
|
||||
_storageImageDescriptors.reset();
|
||||
_inputAttachmentDescriptors.reset();
|
||||
_samplerDescriptors.reset();
|
||||
_combinedImageSamplerDescriptors.reset();
|
||||
_uniformTexelBufferDescriptors.reset();
|
||||
_storageTexelBufferDescriptors.reset();
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
@ -606,87 +449,126 @@ void MVKDescriptorPool::freeDescriptorSet(MVKDescriptorSet* mvkDS) { mvkDS->dest
|
||||
// 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 appropriate type now
|
||||
switch (descriptorType) {
|
||||
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
|
||||
*pMVKDesc = new MVKUniformBufferDescriptor();
|
||||
break;
|
||||
return _uniformBufferDescriptors.allocateDescriptor(pMVKDesc);
|
||||
|
||||
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
|
||||
*pMVKDesc = new MVKStorageBufferDescriptor();
|
||||
break;
|
||||
return _storageBufferDescriptors.allocateDescriptor(pMVKDesc);
|
||||
|
||||
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
|
||||
*pMVKDesc = new MVKUniformBufferDynamicDescriptor();
|
||||
break;
|
||||
return _uniformBufferDynamicDescriptors.allocateDescriptor(pMVKDesc);
|
||||
|
||||
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
|
||||
*pMVKDesc = new MVKStorageBufferDynamicDescriptor();
|
||||
break;
|
||||
return _storageBufferDynamicDescriptors.allocateDescriptor(pMVKDesc);
|
||||
|
||||
case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT:
|
||||
*pMVKDesc = new MVKInlineUniformBlockDescriptor();
|
||||
break;
|
||||
return _inlineUniformBlockDescriptors.allocateDescriptor(pMVKDesc);
|
||||
|
||||
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
|
||||
*pMVKDesc = new MVKSampledImageDescriptor();
|
||||
break;
|
||||
return _sampledImageDescriptors.allocateDescriptor(pMVKDesc);
|
||||
|
||||
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
|
||||
*pMVKDesc = new MVKStorageImageDescriptor();
|
||||
break;
|
||||
return _storageImageDescriptors.allocateDescriptor(pMVKDesc);
|
||||
|
||||
case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
|
||||
*pMVKDesc = new MVKInputAttachmentDescriptor();
|
||||
break;
|
||||
return _inputAttachmentDescriptors.allocateDescriptor(pMVKDesc);
|
||||
|
||||
case VK_DESCRIPTOR_TYPE_SAMPLER:
|
||||
*pMVKDesc = new MVKSamplerDescriptor();
|
||||
break;
|
||||
return _samplerDescriptors.allocateDescriptor(pMVKDesc);
|
||||
|
||||
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
|
||||
*pMVKDesc = new MVKCombinedImageSamplerDescriptor();
|
||||
break;
|
||||
return _combinedImageSamplerDescriptors.allocateDescriptor(pMVKDesc);
|
||||
|
||||
case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
|
||||
*pMVKDesc = new MVKUniformTexelBufferDescriptor();
|
||||
break;
|
||||
return _uniformTexelBufferDescriptors.allocateDescriptor(pMVKDesc);
|
||||
|
||||
case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
|
||||
*pMVKDesc = new MVKStorageTexelBufferDescriptor();
|
||||
break;
|
||||
return _storageTexelBufferDescriptors.allocateDescriptor(pMVKDesc);
|
||||
|
||||
default:
|
||||
return reportError(VK_ERROR_INITIALIZATION_FAILED, "Unrecognized VkDescriptorType %d.", descriptorType);
|
||||
}
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
// 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();
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
MVKDescriptorPool::MVKDescriptorPool(MVKDevice* device,
|
||||
const VkDescriptorPoolCreateInfo* pCreateInfo) : MVKVulkanAPIDeviceObject(device) {
|
||||
_maxSets = pCreateInfo->maxSets;
|
||||
_preallocatedDescriptors = mvkGetMVKConfiguration()->preallocateDescriptors ? new MVKPreallocatedDescriptors(pCreateInfo) : nullptr;
|
||||
// Return the size of the preallocated pool for descriptors of the specified type,
|
||||
// or zero if we are not preallocating descriptors in the pool.
|
||||
// There may be more than one poolSizeCount instance for the desired VkDescriptorType.
|
||||
// Accumulate the descriptor count for the desired VkDescriptorType accordingly.
|
||||
static size_t getPoolSize(const VkDescriptorPoolCreateInfo* pCreateInfo, VkDescriptorType descriptorType) {
|
||||
uint32_t descCnt = 0;
|
||||
if (mvkGetMVKConfiguration()->preallocateDescriptors) {
|
||||
uint32_t poolCnt = pCreateInfo->poolSizeCount;
|
||||
for (uint32_t poolIdx = 0; poolIdx < poolCnt; poolIdx++) {
|
||||
auto& poolSize = pCreateInfo->pPoolSizes[poolIdx];
|
||||
if (poolSize.type == descriptorType) { descCnt += poolSize.descriptorCount; }
|
||||
}
|
||||
}
|
||||
return descCnt;
|
||||
}
|
||||
|
||||
// Destroy all allocated descriptor sets and preallocated descriptors
|
||||
MVKDescriptorPool::MVKDescriptorPool(MVKDevice* device, const VkDescriptorPoolCreateInfo* pCreateInfo) :
|
||||
MVKVulkanAPIDeviceObject(device),
|
||||
_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)),
|
||||
_storageBufferDynamicDescriptors(getPoolSize(pCreateInfo, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC)),
|
||||
_inlineUniformBlockDescriptors(getPoolSize(pCreateInfo, VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT)),
|
||||
_sampledImageDescriptors(getPoolSize(pCreateInfo, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)),
|
||||
_storageImageDescriptors(getPoolSize(pCreateInfo, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)),
|
||||
_inputAttachmentDescriptors(getPoolSize(pCreateInfo, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)),
|
||||
_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) {}
|
||||
|
||||
MVKDescriptorPool::~MVKDescriptorPool() {
|
||||
reset(0);
|
||||
if (_preallocatedDescriptors) { _preallocatedDescriptors->destroy(); }
|
||||
}
|
||||
|
||||
|
||||
|
181
MoltenVK/MoltenVK/Utility/MVKBitArray.h
Executable file
181
MoltenVK/MoltenVK/Utility/MVKBitArray.h
Executable file
@ -0,0 +1,181 @@
|
||||
/*
|
||||
* MVKBitArray.h
|
||||
*
|
||||
* Copyright (c) 2020-2020 The Brenwill Workshop Ltd. (http://www.brenwill.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "MVKFoundation.h"
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark MVKBitArray
|
||||
|
||||
/** Represents an array of bits, optimized for reduced storage and fast scanning for bits that are set. */
|
||||
class MVKBitArray {
|
||||
|
||||
static constexpr size_t SectionMaskSize = 6; // 64 bits
|
||||
static constexpr size_t SectionBitCount = 1U << SectionMaskSize;
|
||||
static constexpr size_t SectionByteCount = SectionBitCount / 8;
|
||||
static constexpr uint64_t SectionMask = SectionBitCount - 1;
|
||||
|
||||
public:
|
||||
|
||||
/** Returns the value of the bit. */
|
||||
inline bool getBit(size_t bitIndex) {
|
||||
return mvkIsAnyFlagEnabled(_pSections[getIndexOfSection(bitIndex)], getSectionSetMask(bitIndex));
|
||||
}
|
||||
|
||||
/** Sets the value of the bit to 1. */
|
||||
inline void setBit(size_t bitIndex) {
|
||||
size_t secIdx = getIndexOfSection(bitIndex);
|
||||
mvkEnableFlags(_pSections[secIdx], getSectionSetMask(bitIndex));
|
||||
|
||||
if (secIdx < _minUnclearedSectionIndex) { _minUnclearedSectionIndex = secIdx; }
|
||||
}
|
||||
|
||||
/** Sets the value of the bit to 0. */
|
||||
inline void clearBit(size_t bitIndex) {
|
||||
size_t secIdx = getIndexOfSection(bitIndex);
|
||||
mvkDisableFlags(_pSections[secIdx], getSectionSetMask(bitIndex));
|
||||
|
||||
if (secIdx == _minUnclearedSectionIndex && !_pSections[secIdx]) { _minUnclearedSectionIndex++; }
|
||||
}
|
||||
|
||||
/** Sets the value of the bit to the value. */
|
||||
inline void setBit(size_t bitIndex, bool val) {
|
||||
if (val) {
|
||||
setBit(bitIndex);
|
||||
} else {
|
||||
clearBit(bitIndex);
|
||||
}
|
||||
}
|
||||
|
||||
/** Sets all bits in the array to 1. */
|
||||
inline void setAllBits() { setAllSections(~0); }
|
||||
|
||||
/** Clears all bits in the array to 0. */
|
||||
inline void clearAllBits() { setAllSections(0); }
|
||||
|
||||
/**
|
||||
* Returns the index of the first bit that is set, at or after the specified index,
|
||||
* and optionally clears that bit. If no bits are set, returns the size() of this bit array.
|
||||
*/
|
||||
size_t getIndexOfFirstSetBit(size_t startIndex, bool shouldClear) {
|
||||
size_t startSecIdx = std::max(getIndexOfSection(startIndex), _minUnclearedSectionIndex);
|
||||
size_t bitIdx = startSecIdx << SectionMaskSize;
|
||||
size_t secCnt = getSectionCount();
|
||||
for (size_t secIdx = startSecIdx; secIdx < secCnt; secIdx++) {
|
||||
size_t lclBitIdx = getIndexOfFirstSetBitInSection(_pSections[secIdx], getBitIndexInSection(startIndex));
|
||||
bitIdx += lclBitIdx;
|
||||
if (lclBitIdx < SectionBitCount) {
|
||||
if (startSecIdx == _minUnclearedSectionIndex && !_pSections[startSecIdx]) { _minUnclearedSectionIndex = secIdx; }
|
||||
if (shouldClear) { clearBit(bitIdx); }
|
||||
return bitIdx;
|
||||
}
|
||||
}
|
||||
return std::min(bitIdx, _bitCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of the first bit that is set, at or after the specified index.
|
||||
* If no bits are set, returns the size() of this bit array.
|
||||
*/
|
||||
inline size_t getIndexOfFirstSetBit(size_t startIndex) {
|
||||
return getIndexOfFirstSetBit(startIndex, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of the first bit that is set and optionally clears that bit.
|
||||
* If no bits are set, returns the size() of this bit array.
|
||||
*/
|
||||
inline size_t getIndexOfFirstSetBit(bool shouldClear) {
|
||||
return getIndexOfFirstSetBit(0, shouldClear);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of the first bit that is set.
|
||||
* If no bits are set, returns the size() of this bit array.
|
||||
*/
|
||||
inline size_t getIndexOfFirstSetBit() {
|
||||
return getIndexOfFirstSetBit(0, false);
|
||||
}
|
||||
|
||||
/** Returns the number of bits in this array. */
|
||||
inline size_t size() { return _bitCount; }
|
||||
|
||||
/** Returns whether this array is empty. */
|
||||
inline bool empty() { return !_bitCount; }
|
||||
|
||||
/** Constructs an instance for the specified number of bits, and sets the initial value of all the bits. */
|
||||
MVKBitArray(size_t size, bool val = false) {
|
||||
_bitCount = size;
|
||||
_pSections = _bitCount ? (uint64_t*)malloc(getSectionCount() * SectionByteCount) : nullptr;
|
||||
if (val) {
|
||||
setAllBits();
|
||||
} else {
|
||||
clearAllBits();
|
||||
}
|
||||
}
|
||||
|
||||
~MVKBitArray() { free(_pSections); }
|
||||
|
||||
protected:
|
||||
|
||||
// Returns the number of sections.
|
||||
inline size_t getSectionCount() {
|
||||
return _bitCount ? getIndexOfSection(_bitCount - 1) + 1 : 0;
|
||||
}
|
||||
|
||||
// Returns the index of the section that contains the specified bit.
|
||||
static inline size_t getIndexOfSection(size_t bitIndex) {
|
||||
return bitIndex >> SectionMaskSize;
|
||||
}
|
||||
|
||||
// Converts the bit index to a local bit index within a section, and returns that local bit index.
|
||||
static inline size_t getBitIndexInSection(size_t bitIndex) {
|
||||
return bitIndex & SectionMask;
|
||||
}
|
||||
|
||||
// Returns a section mask containing a single 1 value in the bit in the section that
|
||||
// corresponds to the specified global bit index, and 0 values in all other bits.
|
||||
static inline uint64_t getSectionSetMask(size_t bitIndex) {
|
||||
return (uint64_t)1U << ((SectionBitCount - 1) - getBitIndexInSection(bitIndex));
|
||||
}
|
||||
|
||||
// Returns the local index of the first set bit in the section, starting from the highest order bit.
|
||||
// Clears all bits ahead of the start bit so they will be ignored, then counts the number of zeros
|
||||
// ahead of the set bit. If there are no set bits, returns the number of bits in a section.
|
||||
static size_t getIndexOfFirstSetBitInSection(uint64_t section, size_t lclStartBitIndex) {
|
||||
uint64_t lclStartMask = ~(uint64_t)0;
|
||||
lclStartMask >>= lclStartBitIndex;
|
||||
section &= lclStartMask;
|
||||
return section ? __builtin_clzll(section) : SectionBitCount;
|
||||
}
|
||||
|
||||
// Sets the content of all sections to the value
|
||||
void setAllSections(uint64_t sectionValue) {
|
||||
size_t secCnt = getSectionCount();
|
||||
for (size_t secIdx = 0; secIdx < secCnt; secIdx++) {
|
||||
_pSections[secIdx] = sectionValue;
|
||||
}
|
||||
_minUnclearedSectionIndex = sectionValue ? 0 : secCnt;
|
||||
}
|
||||
|
||||
uint64_t* _pSections;
|
||||
size_t _bitCount;
|
||||
size_t _minUnclearedSectionIndex; // Tracks where to start looking for bits that are set
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user