Skip to content

Commit a5d4934

Browse files
fix all typos and get CMemoryPool to conform to new BlockBasedAllocator
1 parent 1f42ebb commit a5d4934

4 files changed

Lines changed: 93 additions & 98 deletions

File tree

include/nbl/core/alloc/SimpleBlockBasedAllocator.h

Lines changed: 21 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@ namespace nbl::core
2222
//! Does not resize memory arenas, therefore once allocated pointers shall not move
2323
//! Needs an address allocator that takes a Block Size after max alignment parameter
2424
template<class AddressAllocator>
25-
class SimpleBlockBasedAllocator final
25+
class SimpleBlockBasedAllocator
2626
{
2727
public:
2828
using addr_alloc_traits = address_allocator_traits<AddressAllocator>;
29-
using extra_params_t = tuple_transform_t<impl::identitiy,addr_alloc_traits::extra_ctor_param_types>;
29+
using extra_params_t = tuple_transform_t<impl::identitiy,typename addr_alloc_traits::extra_ctor_param_types>;
3030
using size_type = typename addr_alloc_traits::size_type;
3131
// The blocks will be allocated aligned to at least this value
3232
constexpr static inline size_type meta_alignment = 64u;
@@ -80,7 +80,7 @@ class SimpleBlockBasedAllocator final
8080
{
8181
std::apply([&params]<typename... Args>(const Args&... args)->void
8282
{
83-
addrAlloc = AddressAllocator(this+1,./*no address offset*/0u,/*no alignment offset needed*/0u,meta_alignment,params.blockSize,args...);
83+
addrAlloc = AddressAllocator(this+1,/*no address offset*/0u,/*no alignment offset needed*/0u,meta_alignment,params.blockSize,args...);
8484
},params.addrCreationArgs
8585
);
8686
assert(addr_alloc_traits::get_align_offset(addrAlloc) == 0ul);
@@ -116,33 +116,36 @@ class SimpleBlockBasedAllocator final
116116

117117
struct SCreationParams
118118
{
119-
smart_refctd_ptr<refctd_memory_resource> mem_resource;
119+
smart_refctd_ptr<refctd_memory_resource> mem_resource = nullptr;
120120
extra_params_t addrAllocCtorExtraParams;
121121
size_type blockSize = 128u<<10;
122122
size_type initBlockCount = 1;
123123
};
124124
inline SimpleBlockBasedAllocator(SCreationParams&& params) : m_blockCreationParams(params.blockSize,std::move(params.addrAllocCtorExtraParams)),
125-
m_initBlockCount(std::max<size_type>(_initBlockCount,1)), m_mem_resource(std::move(params.mem_resource))
125+
m_initBlockCount(std::max<size_type>(params.initBlockCount,1)), m_mem_resource(params.mem_resource ? std::move(params.mem_resource):core::getDefaultMemoryResource())
126126
{
127-
m_blocks.reserve(m_initBlockCount);
128127
for (auto i=0u; i<m_initBlockCount; i++)
129128
m_blocks.insert(createBlock());
130129
}
130+
SimpleBlockBasedAllocator(const SimpleBlockBasedAllocator&) = delete;
131+
SimpleBlockBasedAllocator(SimpleBlockBasedAllocator&&) = delete;
131132

132133
// deallocates everything
133134
inline void reset()
134135
{
135136
assert(m_blocks.size()>=m_initBlockCount);
136137
auto it = m_blocks.begin();
137-
for (auto i=0u; i<m_initBlockCount; i++)
138+
for (auto i=0u; i<m_initBlockCount; i++,it++)
138139
{
139-
auto* block = *(it++);
140+
Block* block = *it;
140141
if (i<m_initBlockCount)
141-
block->getAllocator().reset();
142+
block->addrAlloc.reset();
142143
else
144+
{
143145
deleteBlock(block);
146+
m_blocks.erase(it);
147+
}
144148
}
145-
m_blocks.erase(m_blocks.begin()+m_initBlockCount,m_blocks.end());
146149
}
147150

148151
//
@@ -181,7 +184,7 @@ class SimpleBlockBasedAllocator final
181184
m_blocks.erase(found);
182185
}
183186
}
184-
187+
#if 0 // what do we even need these for
185188
inline bool operator!=(const this_t& other) const noexcept
186189
{
187190
if (m_blockCreationParams != other.m_blockCreationParams)
@@ -190,22 +193,22 @@ class SimpleBlockBasedAllocator final
190193
return true;
191194
if (m_mem_resource != other.m_mem_resource)
192195
return true;
193-
if (m_backBlock != other.m_backBlock)
196+
if (m_blocks != other.m_blocks)
194197
return true;
195198
return false;
196199
}
197200
inline bool operator==(const this_t& other) const noexcept
198201
{
199202
return !operator!=(other);
200203
}
201-
204+
#endif
202205
protected:
203206
using block_map_t = gtl::btree_set<Block*>;
204207

205208
inline Block* createBlock()
206209
{
207210
auto* block = reinterpret_cast<Block*>(m_mem_resource->allocate(m_blockCreationParams.totalSize,meta_alignment));
208-
std::construct_at(block,m_blockCreationArgs);
211+
std::construct_at(block,m_blockCreationParams);
209212
m_blocks.insert(block);
210213
return block;
211214
}
@@ -239,23 +242,7 @@ class SimpleBlockBasedAllocatorMT final
239242
public:
240243
using size_type = typename Composed::size_type;
241244

242-
template<typename... Args>
243-
inline SimpleBlockBasedAllocatorMT(size_type _blockSize, size_type _minBlockCount, size_type _maxBlockCount, Args&&... args) :
244-
m_composed(_blockSize,_minBlockCount,_maxBlockCount,std::forward<Args>(args)...), m_lock() {}
245-
246-
inline auto& operator=(this_t&& other)
247-
{
248-
// TODO: lock both locks till complete?
249-
std::swap(m_lock,other.m_lock);
250-
std::swap(m_composed,other.m_composed);
251-
return *this;
252-
}
253-
254-
inline SimpleBlockBasedAllocatorMT(this_t&& other)
255-
{
256-
operator=(std::move(other));
257-
}
258-
245+
inline SimpleBlockBasedAllocatorMT(Composed::SCreationParams&& params) : m_composed(std::move(params)), m_lock() {}
259246
virtual inline ~SimpleBlockBasedAllocatorMT() {}
260247

261248
//
@@ -285,7 +272,8 @@ class SimpleBlockBasedAllocatorMT final
285272
{
286273
return m_lock;
287274
}
288-
275+
276+
#if 0 // what do we even need these for
289277
inline bool operator!=(const SimpleBlockBasedAllocatorMT<AddressAllocator>& other) const noexcept
290278
{
291279
return m_composed!=other.m_composed || other.m_lock!=m_lock;
@@ -294,6 +282,7 @@ class SimpleBlockBasedAllocatorMT final
294282
{
295283
return m_composed==other.m_composed && other.m_lock==m_lock;
296284
}
285+
#endif
297286
};
298287
// no aliases
299288

Lines changed: 70 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1+
// Copyright (C) 2020-2026 - DevSH Graphics Programming Sp. z O.O.
2+
// This file is part of the "Nabla Engine".
3+
// For conditions of distribution and use, see copyright notice in nabla.h
14
#ifndef _NBL_CORE_C_MEMORY_POOL_H_INCLUDED_
25
#define _NBL_CORE_C_MEMORY_POOL_H_INCLUDED_
36

47

58
#include "nbl/core/decl/compile_config.h"
6-
#include "nbl/core/alloc/SimpleBlockBasedAllocator.h"
79
#include "nbl/core/decl/BaseClasses.h"
10+
#include "nbl/core/alloc/SimpleBlockBasedAllocator.h"
811

912
#include <memory>
1013
#include <type_traits>
@@ -13,80 +16,84 @@
1316
namespace nbl::core
1417
{
1518

16-
// TODO: change DataAllocator to PMR
17-
template <class AddressAllocator, template<class> class DataAllocator, bool isThreadSafe, typename... Args>
18-
class CMemoryPool : public Uncopyable
19+
template<typename C>
20+
concept MemoryPoolConfig = requires
1921
{
20-
public:
21-
using addr_allocator_type = AddressAllocator;
22-
using allocator_type = typename std::conditional<isThreadSafe,
23-
SimpleBlockBasedAllocatorMT<AddressAllocator,DataAllocator, std::recursive_mutex, Args...>,
24-
SimpleBlockBasedAllocatorST<AddressAllocator,DataAllocator, Args...>>::type;
25-
using size_type = typename core::address_allocator_traits<addr_allocator_type>::size_type;
26-
using addr_type = size_type;
22+
// {C::ThreadSafe} -> std::same_as<bool>; // TODO: how to do it
23+
typename C::AddressAllocator; // TODO: check its an Address Allocator
24+
};
2725

28-
CMemoryPool(size_type _blockSize, size_type _minBlockCount, size_type _maxBlockCount, Args... args) : // intentionally no && here, i dont wont to do here anything like reference collapsing, `Args` come from class template
29-
m_alctr(_blockSize,_minBlockCount,_maxBlockCount,std::forward<Args>(args)...)
30-
{
31-
}
32-
33-
void* allocate(size_type s, size_type a)
34-
{
35-
return m_alctr.allocate(s, a);
36-
}
37-
void deallocate(void* _ptr, size_type s)
38-
{
39-
m_alctr.deallocate(_ptr, s);
40-
}
26+
template<MemoryPoolConfig Config>
27+
class CMemoryPool final : public Uncopyable
28+
{
29+
using block_allocator_st_type = SimpleBlockBasedAllocatorST<typename Config::AddressAllocator>;
30+
public:
31+
using addr_allocator_type = Config::AddressAllocator;
32+
using size_type = typename core::address_allocator_traits<addr_allocator_type>::size_type;
4133

42-
template <typename T, typename... FuncArgs>
43-
T* emplace_n(uint32_t n, FuncArgs&&... args)
44-
{
45-
size_type s = static_cast<size_type>(n) * sizeof(T);
46-
size_type a = alignof(T);
47-
void* ptr = allocate(s, a);
48-
if (!ptr)
49-
return nullptr;
34+
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;
5037

51-
using traits_t = std::allocator_traits<DataAllocator<T>>;
52-
DataAllocator<T> data_alctr;
53-
if constexpr (sizeof...(FuncArgs)!=0u || !std::is_trivial_v<T>)
38+
inline CMemoryPool(block_allocator_st_type::SCreationParams&& params) : m_block_alctr(std::move(params)) {}
39+
40+
//
41+
inline void* allocate(const size_type s, const size_type a)
42+
{
43+
return m_block_alctr.allocate(s,a);
44+
}
45+
inline void deallocate(void* _ptr, const size_type s)
5446
{
55-
for (uint32_t i = 0u; i < n; ++i)
56-
traits_t::construct(data_alctr, reinterpret_cast<T*>(ptr) + i, std::forward<FuncArgs>(args)...);
47+
m_block_alctr.deallocate(_ptr,s);
5748
}
58-
return reinterpret_cast<T*>(ptr);
59-
}
60-
template <typename T, typename... FuncArgs>
61-
T* emplace(FuncArgs&&... args)
62-
{
63-
return emplace_n<T,FuncArgs...>(1u, std::forward<FuncArgs>(args)...);
64-
}
6549

66-
template <typename T>
67-
void free_n(void* _ptr, uint32_t n)
68-
{
69-
using traits_t = std::allocator_traits<DataAllocator<T>>;
70-
DataAllocator<T> data_alctr;
50+
//
51+
template <typename T, typename... FuncArgs> requires (!std::is_array_v<T>) // for now until we have a test
52+
inline T* emplace_n(const uint32_t n, FuncArgs&&... args)
53+
{
54+
size_type s = static_cast<size_type>(n)*sizeof(T);
55+
size_type a = alignof(T);
56+
T* const ptr = std::launder(reinterpret_cast<T*>(allocate(s,a)));
57+
if (!ptr)
58+
return nullptr;
59+
60+
if constexpr (!std::is_trivial_v<T>)
61+
{
62+
if constexpr (sizeof...(FuncArgs)!=0u)
63+
{
64+
for (uint32_t i=0u; i<n; ++i)
65+
std::construct_at(ptr+i,std::forward<FuncArgs>(args)...);
66+
}
67+
else
68+
std::uninitialized_default_construct_n(ptr,n);
69+
}
70+
return ptr;
71+
}
72+
template <typename T, typename... FuncArgs>
73+
inline T* emplace(FuncArgs&&... args)
74+
{
75+
return emplace_n<T,FuncArgs...>(1u,std::forward<FuncArgs>(args)...);
76+
}
7177

72-
T* ptr = reinterpret_cast<T*>(_ptr);
73-
if constexpr (!std::is_trivially_destructible_v<T>)
78+
// You must know the original type, we don't keep track of original size
79+
// TODO: this shouldn't be called `free` but `delete`
80+
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)
82+
{
83+
T* ptr = reinterpret_cast<T*>(_ptr);
84+
if constexpr (!std::is_trivially_destructible_v<T>)
85+
std::destroy_n(ptr,n);
86+
deallocate(_ptr,sizeof(T)*n);
87+
}
88+
template <typename T>
89+
inline void free(void* ptr)
7490
{
75-
for (uint32_t i = 0u; i < n; ++i)
76-
traits_t::destroy(data_alctr, ptr + i);
91+
return free_n<T>(ptr,1u);
7792
}
78-
deallocate(_ptr, sizeof(T)*n);
79-
}
80-
template <typename T>
81-
void free(void* ptr)
82-
{
83-
return free_n<T>(ptr, 1u);
84-
}
8593

86-
private:
87-
allocator_type m_alctr;
94+
private:
95+
block_allocator_type m_block_alctr;
8896
};
8997

9098
}
91-
9299
#endif

include/nbl/video/IGPUCommandPool.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ class IGPUCommandPool : public IBackendObject
3333
static inline constexpr uint32_t COMMAND_SEGMENT_ALIGNMENT = 64u;
3434
static inline constexpr uint32_t COMMAND_SEGMENT_SIZE = 128u << 10u;
3535

36-
static inline constexpr uint32_t MAX_COMMAND_SEGMENT_BLOCK_COUNT = 16u;
3736
static inline constexpr uint32_t COMMAND_SEGMENTS_PER_BLOCK = 256u;
3837
static inline constexpr uint32_t MIN_POOL_ALLOC_SIZE = COMMAND_SEGMENT_SIZE;
3938

@@ -511,7 +510,7 @@ class IGPUCommandPool : public IBackendObject
511510
CCommandSegment* tail = nullptr;
512511
};
513512

514-
inline CCommandSegmentListPool() : m_pool(COMMAND_SEGMENTS_PER_BLOCK*COMMAND_SEGMENT_SIZE, 0u, MAX_COMMAND_SEGMENT_BLOCK_COUNT, MIN_POOL_ALLOC_SIZE) {}
513+
inline CCommandSegmentListPool() : m_pool({.addrAllocCtorExtraParams={MIN_POOL_ALLOC_SIZE},.blockSize=COMMAND_SEGMENTS_PER_BLOCK*COMMAND_SEGMENT_SIZE}) {}
515514

516515
template <typename Cmd, typename... Args>
517516
Cmd* emplace(SCommandSegmentList& list, Args&&... args)

src/nbl/video/CVulkanLogicalDevice.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ using namespace nbl::video;
1414

1515
CVulkanLogicalDevice::CVulkanLogicalDevice(core::smart_refctd_ptr<const IAPIConnection>&& api, renderdoc_api_t* const rdoc, const IPhysicalDevice* const physicalDevice, const VkDevice vkdev, const SCreationParams& params)
1616
: ILogicalDevice(std::move(api),physicalDevice,params,rdoc),
17-
m_vkdev(vkdev), m_devf(vkdev), m_deferred_op_mempool(NODES_PER_BLOCK_DEFERRED_OP*sizeof(CVulkanDeferredOperation),1u,MAX_BLOCK_COUNT_DEFERRED_OP,static_cast<uint32_t>(sizeof(CVulkanDeferredOperation)))
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)})
1818
{
1919
// create actual queue objects
2020
for (uint32_t i=0u; i<ILogicalDevice::MaxQueueFamilies; ++i)

0 commit comments

Comments
 (0)