Skip to content

Commit 8a78c80

Browse files
Force PoT Block sizes on the SimpleBlockBasedAllocator, also make allocate return some metadata, not just a pointer
And fix bugs
1 parent a5d4934 commit 8a78c80

5 files changed

Lines changed: 56 additions & 40 deletions

File tree

include/nbl/core/alloc/SimpleBlockBasedAllocator.h

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,9 @@ class SimpleBlockBasedAllocator
6464
struct SCreationParams
6565
{
6666
inline SCreationParams(const size_type _blockSize, const extra_params_t& extraArgs) : addrCreationArgs(extraArgs), blockSize(_blockSize),
67-
reservedSize(std::apply([blockSize]<typename... Args>(const Args&... args)->size_type
67+
reservedSize(std::apply([_blockSize]<typename... Args>(const Args&... args)->size_type
6868
{
69-
return addr_alloc_traits::reserved_size(meta_alignment,blockSize,args...);
69+
return addr_alloc_traits::reserved_size(meta_alignment,_blockSize,args...);
7070
},addrCreationArgs)
7171
), totalSize(core::alignUp(sizeof(Block)+reservedSize,meta_alignment)+blockSize) {}
7272

@@ -78,7 +78,7 @@ class SimpleBlockBasedAllocator
7878
//
7979
inline Block(const SCreationParams& params) : addrAlloc(AddressAllocator())
8080
{
81-
std::apply([&params]<typename... Args>(const Args&... args)->void
81+
std::apply([&]<typename... Args>(const Args&... args)->void
8282
{
8383
addrAlloc = AddressAllocator(this+1,/*no address offset*/0u,/*no alignment offset needed*/0u,meta_alignment,params.blockSize,args...);
8484
},params.addrCreationArgs
@@ -88,11 +88,12 @@ class SimpleBlockBasedAllocator
8888
}
8989

9090
inline uint8_t* data(const SCreationParams& params) {return reinterpret_cast<uint8_t*>(this)+params.totalSize-params.blockSize;}
91-
inline const uint8_t* data() const
91+
inline const uint8_t* data(const SCreationParams& params) const
9292
{
93-
return const_cast<Block*>(this)->data();
93+
return const_cast<const uint8_t*>(const_cast<Block*>(this)->data(params));
9494
}
9595

96+
AddressAllocator& getAllocator() {return addrAlloc;}
9697
const AddressAllocator& getAllocator() const {return addrAlloc;}
9798

9899
size_type alloc(size_type bytes, size_type alignment)
@@ -118,10 +119,10 @@ class SimpleBlockBasedAllocator
118119
{
119120
smart_refctd_ptr<refctd_memory_resource> mem_resource = nullptr;
120121
extra_params_t addrAllocCtorExtraParams;
121-
size_type blockSize = 128u<<10;
122-
size_type initBlockCount = 1;
122+
uint16_t blockSizeKBLog2 : 5 = 7;
123+
uint16_t initBlockCount : 11 = 1;
123124
};
124-
inline SimpleBlockBasedAllocator(SCreationParams&& params) : m_blockCreationParams(params.blockSize,std::move(params.addrAllocCtorExtraParams)),
125+
inline SimpleBlockBasedAllocator(SCreationParams&& params) : m_blockCreationParams(1024u<<params.blockSizeKBLog2,std::move(params.addrAllocCtorExtraParams)),
125126
m_initBlockCount(std::max<size_type>(params.initBlockCount,1)), m_mem_resource(params.mem_resource ? std::move(params.mem_resource):core::getDefaultMemoryResource())
126127
{
127128
for (auto i=0u; i<m_initBlockCount; i++)
@@ -130,6 +131,9 @@ class SimpleBlockBasedAllocator
130131
SimpleBlockBasedAllocator(const SimpleBlockBasedAllocator&) = delete;
131132
SimpleBlockBasedAllocator(SimpleBlockBasedAllocator&&) = delete;
132133

134+
//
135+
inline const Block::SCreationParams getBlockCreationParams() const {return m_blockCreationParams;}
136+
133137
// deallocates everything
134138
inline void reset()
135139
{
@@ -149,34 +153,49 @@ class SimpleBlockBasedAllocator
149153
}
150154

151155
//
152-
inline void* allocate(const size_type bytes, const size_type alignment) noexcept
156+
struct SAllocResult
157+
{
158+
explicit inline operator bool() const {return blockData;}
159+
inline operator void*() const
160+
{
161+
if (blockData)
162+
return blockData+addr;
163+
return nullptr;
164+
}
165+
166+
uint8_t* blockData = nullptr;
167+
size_type addr : (sizeof(size_type)*8-1);
168+
size_type newBlock : 1 = false;
169+
};
170+
inline SAllocResult allocate(const size_type bytes, const size_type alignment) noexcept
153171
{
154172
constexpr auto invalid_address = AddressAllocator::invalid_address;
155173
// TODO: better allocation strategies like tlsf
156174
for (auto& entry : m_blocks)
157175
{
158-
auto* block = entry;
176+
Block* block = const_cast<Block*>(entry);
159177
if (const auto addr=block->alloc(bytes,alignment); addr!=invalid_address)
160-
return block->data()+addr;
178+
return {.blockData=block->data(m_blockCreationParams),.addr=addr};
161179
}
162-
auto* block = createBlock();
180+
Block* block = createBlock();
163181
if (const auto addr=block->alloc(bytes,alignment); addr!=invalid_address)
164182
{
165183
m_blocks.insert(block);
166-
return block->data()+addr;
184+
return {.blockData=block->data(m_blockCreationParams),.addr=addr,.newBlock=true};
167185
}
168186
else
169187
deleteBlock(block);
170-
return nullptr;
188+
return {};
171189
}
172190
inline void deallocate(void* p, const size_type bytes) noexcept
173191
{
174192
assert(m_blocks.size()>=m_initBlockCount);
175193
auto found = m_blocks.lower_bound(reinterpret_cast<Block*>(p));
176194
assert(found!=m_blocks.end());
177195
auto* block = *found;
178-
assert(block->data()<=p && p<block->data()+m_blockCreationParams.blockSize);
179-
const size_type addr = reinterpret_cast<uint8_t*>(p)-block->data();
196+
uint8_t* blockData = block->data(m_blockCreationParams);
197+
assert(blockData<=p && p<blockData+m_blockCreationParams.blockSize);
198+
const size_type addr = reinterpret_cast<uint8_t*>(p)-blockData;
180199
block->free(addr,bytes);
181200
if (m_blocks.size()>m_initBlockCount && addr_alloc_traits::get_allocated_size(block->getAllocator())==size_type(0u))
182201
{

include/nbl/core/containers/CMemoryPool.h

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,6 @@ class CMemoryPool final : public Uncopyable
3232
using size_type = typename core::address_allocator_traits<addr_allocator_type>::size_type;
3333

3434
using block_allocator_type = std::conditional_t<Config::ThreadSafe,SimpleBlockBasedAllocatorMT<block_allocator_st_type,std::recursive_mutex>,block_allocator_st_type>;
35-
// TODO: not appropriate
36-
// using addr_type = size_type;
3735

3836
inline CMemoryPool(block_allocator_st_type::SCreationParams&& params) : m_block_alctr(std::move(params)) {}
3937

@@ -76,19 +74,17 @@ class CMemoryPool final : public Uncopyable
7674
}
7775

7876
// You must know the original type, we don't keep track of original size
79-
// TODO: this shouldn't be called `free` but `delete`
8077
template <typename T> requires (!std::is_array_v<T>) // for now until we have a test
81-
inline void free_n(void* _ptr, const uint32_t n)
78+
inline void _delete(const std::span<T> _range)
8279
{
83-
T* ptr = reinterpret_cast<T*>(_ptr);
8480
if constexpr (!std::is_trivially_destructible_v<T>)
85-
std::destroy_n(ptr,n);
86-
deallocate(_ptr,sizeof(T)*n);
81+
std::destroy_n(_range.data(),_range.size());
82+
deallocate(_range.data(),sizeof(T)*_range.size());
8783
}
8884
template <typename T>
89-
inline void free(void* ptr)
85+
inline void _delete(T* const ptr)
9086
{
91-
return free_n<T>(ptr,1u);
87+
return _delete<T>({ptr,1u});
9288
}
9389

9490
private:

include/nbl/video/IGPUCommandPool.h

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,11 @@ class IGPUCommandPool : public IBackendObject
3131

3232
static inline constexpr uint32_t COMMAND_ALIGNMENT = 64u;
3333
static inline constexpr uint32_t COMMAND_SEGMENT_ALIGNMENT = 64u;
34-
static inline constexpr uint32_t COMMAND_SEGMENT_SIZE = 128u << 10u;
34+
static inline constexpr uint8_t CommandSegmentSizeLog2 = 17;
35+
static inline constexpr uint32_t CommandSegmentSize = 0x1u<<CommandSegmentSizeLog2;
3536

36-
static inline constexpr uint32_t COMMAND_SEGMENTS_PER_BLOCK = 256u;
37-
static inline constexpr uint32_t MIN_POOL_ALLOC_SIZE = COMMAND_SEGMENT_SIZE;
37+
static inline constexpr uint8_t CommandSegmentsPerBlockLog2 = 2;
38+
static inline constexpr uint32_t MinPoolAllocSize = CommandSegmentSize;
3839

3940
public:
4041
enum class CREATE_FLAGS : uint8_t
@@ -207,7 +208,7 @@ class IGPUCommandPool : public IBackendObject
207208
else
208209
{
209210
advance -= localCount-localPos;
210-
for (constexpr auto MaxTracked=CCommandSegment::STORAGE_SIZE/sizeof(value_t); true; advance-=MaxTracked)
211+
for (constexpr auto MaxTracked=CCommandSegment::StorageSize/sizeof(value_t); true; advance-=MaxTracked)
211212
{
212213
retval.m_cmd = retval.m_cmd->m_next;
213214
if (!retval.m_cmd)
@@ -312,7 +313,7 @@ class IGPUCommandPool : public IBackendObject
312313
static inline uint32_t calc_size(const Args&...)
313314
{
314315
static_assert(std::is_final_v<CRTP>);
315-
//static_assert(sizeof(CRTP)<=CCommandSegment::STORAGE_SIZE);
316+
//static_assert(sizeof(CRTP)<=CCommandSegment::StorageSize);
316317
return sizeof(CRTP);
317318
}
318319

@@ -401,10 +402,10 @@ class IGPUCommandPool : public IBackendObject
401402
} m_header;
402403

403404
public:
404-
static inline constexpr uint32_t STORAGE_SIZE = COMMAND_SEGMENT_SIZE - core::roundUp(sizeof(header_t),alignof(ICommand));
405+
static inline constexpr uint32_t StorageSize = CommandSegmentSize - core::roundUp(sizeof(header_t),alignof(ICommand));
405406

406407
inline CCommandSegment(CCommandSegment* prev):
407-
m_header(nullptr, 0u, 0u, alignof(ICommand), STORAGE_SIZE)
408+
m_header(nullptr, 0u, 0u, alignof(ICommand), StorageSize)
408409
{
409410
static_assert(alignof(ICommand) <= COMMAND_ALIGNMENT);
410411
static_assert(COMMAND_ALIGNMENT <= COMMAND_SEGMENT_ALIGNMENT);
@@ -471,7 +472,7 @@ class IGPUCommandPool : public IBackendObject
471472
}
472473

473474
private:
474-
alignas(ICommand) uint8_t m_data[STORAGE_SIZE];
475+
alignas(ICommand) uint8_t m_data[StorageSize];
475476

476477
void wipeNextCommandSize()
477478
{
@@ -481,7 +482,7 @@ class IGPUCommandPool : public IBackendObject
481482
*(const_cast<uint32_t*>(&(reinterpret_cast<ICommand*>(m_data + nextCmdOffset)->m_size))) = 0;
482483
}
483484
};
484-
static_assert(sizeof(CCommandSegment)==COMMAND_SEGMENT_SIZE);
485+
static_assert(sizeof(CCommandSegment)==CommandSegmentSize);
485486

486487
private:
487488
class CExtraResourceTrackingBlock final : public IVariableSizeCommandBase
@@ -490,7 +491,7 @@ class IGPUCommandPool : public IBackendObject
490491
static SConstructionParams calc_size(const uint32_t extraResourceCount)
491492
{
492493
static_assert(alignof(CExtraResourceTrackingBlock)>=alignof(CTrackedIterator::value_t));
493-
return IVariableSizeCommandBase::calc_size(CCommandSegment::STORAGE_SIZE,sizeof(CExtraResourceTrackingBlock),extraResourceCount);
494+
return IVariableSizeCommandBase::calc_size(CCommandSegment::StorageSize,sizeof(CExtraResourceTrackingBlock),extraResourceCount);
494495
}
495496

496497
// this command will always be created at the start of a new segment, the whole reason it exists is because previous command has overflown the segment
@@ -510,7 +511,7 @@ class IGPUCommandPool : public IBackendObject
510511
CCommandSegment* tail = nullptr;
511512
};
512513

513-
inline CCommandSegmentListPool() : m_pool({.addrAllocCtorExtraParams={MIN_POOL_ALLOC_SIZE},.blockSize=COMMAND_SEGMENTS_PER_BLOCK*COMMAND_SEGMENT_SIZE}) {}
514+
inline CCommandSegmentListPool() : m_pool({.addrAllocCtorExtraParams={MinPoolAllocSize},.blockSizeKBLog2=CommandSegmentsPerBlockLog2+CommandSegmentSizeLog2-10}) {}
514515

515516
template <typename Cmd, typename... Args>
516517
Cmd* emplace(SCommandSegmentList& list, Args&&... args)
@@ -586,7 +587,7 @@ class IGPUCommandPool : public IBackendObject
586587
{
587588
auto nextSegment = segment->getNext();
588589
segment->~CCommandSegment();
589-
m_pool.deallocate(segment,COMMAND_SEGMENT_SIZE);
590+
m_pool.deallocate(segment,CommandSegmentSize);
590591
segment = nextSegment;
591592
}
592593
}

src/nbl/video/CVulkanLogicalDevice.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@
1212
using namespace nbl;
1313
using namespace nbl::video;
1414

15+
1516
CVulkanLogicalDevice::CVulkanLogicalDevice(core::smart_refctd_ptr<const IAPIConnection>&& api, renderdoc_api_t* const rdoc, const IPhysicalDevice* const physicalDevice, const VkDevice vkdev, const SCreationParams& params)
1617
: ILogicalDevice(std::move(api),physicalDevice,params,rdoc),
17-
m_vkdev(vkdev), m_devf(vkdev), m_deferred_op_mempool({.addrAllocCtorExtraParams={static_cast<uint32_t>(sizeof(CVulkanDeferredOperation))},.blockSize=NODES_PER_BLOCK_DEFERRED_OP*sizeof(CVulkanDeferredOperation)})
18+
m_vkdev(vkdev), m_devf(vkdev), m_deferred_op_mempool({.addrAllocCtorExtraParams={static_cast<uint32_t>(sizeof(CVulkanDeferredOperation))},.blockSizeKBLog2=12})
1819
{
20+
static_assert(sizeof(CVulkanDeferredOperation)<=1024);
1921
// create actual queue objects
2022
for (uint32_t i=0u; i<ILogicalDevice::MaxQueueFamilies; ++i)
2123
{

src/nbl/video/CVulkanLogicalDevice.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -318,8 +318,6 @@ class CVulkanLogicalDevice final : public ILogicalDevice
318318
const VkDevice m_vkdev;
319319
CVulkanDeviceFunctionTable m_devf;
320320

321-
constexpr static inline uint32_t NODES_PER_BLOCK_DEFERRED_OP = 4096u;
322-
constexpr static inline uint32_t MAX_BLOCK_COUNT_DEFERRED_OP = 256u;
323321
memory_pool_mt_t m_deferred_op_mempool;
324322

325323
VkDescriptorSetLayout m_dummyDSLayout;

0 commit comments

Comments
 (0)