6
6
7
7
#include < type_traits>
8
8
9
- #include " nbl/core/alloc/null_allocator.h"
10
-
11
9
#include " nbl/asset/IBuffer.h"
12
10
#include " nbl/asset/IAsset.h"
13
11
#include " nbl/asset/IPreHashed.h"
14
12
13
+ #include " nbl/core/alloc/refctd_memory_resource.h"
14
+
15
15
namespace nbl ::asset
16
16
{
17
17
@@ -22,57 +22,80 @@ namespace nbl::asset
22
22
23
23
@see IAsset
24
24
*/
25
- class ICPUBuffer : public asset ::IBuffer, public IPreHashed
25
+ class ICPUBuffer final : public asset::IBuffer, public IPreHashed
26
26
{
27
- protected:
28
- // ! Non-allocating constructor for CCustormAllocatorCPUBuffer derivative
29
- ICPUBuffer (size_t sizeInBytes, void * dat) : asset::IBuffer({ dat ? sizeInBytes : 0 ,EUF_TRANSFER_DST_BIT }), data(dat) {}
30
-
31
27
public:
32
- // ! Constructor. TODO: remove, alloc can fail, should be a static create method instead!
33
- /* * @param sizeInBytes Size in bytes. If `dat` argument is present, it denotes size of data pointed by `dat`, otherwise - size of data to be allocated.
34
- */
35
- ICPUBuffer (size_t sizeInBytes) : asset::IBuffer({0 ,EUF_TRANSFER_DST_BIT})
28
+ struct SCreationParams : asset::IBuffer::SCreationParams
36
29
{
37
- data = _NBL_ALIGNED_MALLOC (sizeInBytes,_NBL_SIMD_ALIGNMENT);
38
- if (!data) // FIXME: cannot fail like that, need factory `create` methods
39
- return ;
30
+ size_t size;
31
+ void * data = nullptr ;
32
+ size_t alignment = _NBL_SIMD_ALIGNMENT;
33
+ core::smart_refctd_ptr<core::refctd_memory_resource> memoryResource = nullptr ;
34
+
35
+ SCreationParams& operator =(const asset::IBuffer::SCreationParams& rhs)
36
+ {
37
+ static_cast <asset::IBuffer::SCreationParams&>(*this ) = rhs;
38
+ return *this ;
39
+ }
40
+ };
41
+
42
+ // ! allocates uninitialized memory, copies `data` into allocation if `!data` not nullptr
43
+ core::smart_refctd_ptr<ICPUBuffer> static create (SCreationParams&& params)
44
+ {
45
+ if (!params.memoryResource )
46
+ params.memoryResource = core::getDefaultMemoryResource ();
47
+
48
+ auto data = params.memoryResource ->allocate (params.size , params.alignment );
49
+ if (!data)
50
+ return nullptr ;
51
+ if (params.data )
52
+ memcpy (data, params.data , params.size );
53
+ params.data = data;
54
+
55
+ return core::smart_refctd_ptr<ICPUBuffer>(new ICPUBuffer (std::move (params)), core::dont_grab);
56
+ }
40
57
41
- m_creationParams.size = sizeInBytes;
58
+ // ! does not allocate memory, adopts the `data` pointer, no copies done
59
+ core::smart_refctd_ptr<ICPUBuffer> static create (SCreationParams&& params, core::adopt_memory_t )
60
+ {
61
+ if (!params.data )
62
+ return nullptr ;
63
+ if (!params.memoryResource )
64
+ params.memoryResource = core::getDefaultMemoryResource ();
65
+ return core::smart_refctd_ptr<ICPUBuffer>(new ICPUBuffer (std::move (params)), core::dont_grab);
42
66
}
43
67
44
68
core::smart_refctd_ptr<IAsset> clone (uint32_t = ~0u ) const override final
45
69
{
46
- auto cp = core::make_smart_refctd_ptr<ICPUBuffer>( m_creationParams.size );
47
- memcpy (cp->getPointer (), data , m_creationParams.size );
70
+ auto cp = create ({ . size = m_creationParams.size , . data = m_data, . alignment = m_alignment } );
71
+ memcpy (cp->getPointer (), m_data , m_creationParams.size );
48
72
cp->setContentHash (getContentHash ());
49
73
return cp;
50
74
}
51
75
52
76
constexpr static inline auto AssetType = ET_BUFFER;
53
77
inline IAsset::E_TYPE getAssetType () const override final { return AssetType; }
54
78
55
- inline size_t getDependantCount () const override {return 0 ;}
79
+ inline size_t getDependantCount () const override { return 0 ; }
56
80
57
- //
58
81
inline core::blake3_hash_t computeContentHash () const override
59
82
{
60
- core::blake3_hasher hasher;
61
- if (data )
62
- hasher.update (data, m_creationParams.size );
63
- return static_cast <core::blake3_hash_t >(hasher);
83
+ core::blake3_hasher hasher;
84
+ if (m_data )
85
+ hasher.update (m_data, m_creationParams.size );
86
+ return static_cast <core::blake3_hash_t >(hasher);
64
87
}
65
88
66
- inline bool missingContent () const override {return !data; }
89
+ inline bool missingContent () const override { return !m_data; }
67
90
68
91
// ! Returns pointer to data.
69
- const void * getPointer () const {return data; }
70
- void * getPointer ()
71
- {
92
+ const void * getPointer () const { return m_data; }
93
+ void * getPointer ()
94
+ {
72
95
assert (isMutable ());
73
- return data ;
96
+ return m_data ;
74
97
}
75
-
98
+
76
99
inline core::bitflag<E_USAGE_FLAGS> getUsageFlags () const
77
100
{
78
101
return m_creationParams.usage ;
@@ -90,93 +113,33 @@ class ICPUBuffer : public asset::IBuffer, public IPreHashed
90
113
return true ;
91
114
}
92
115
93
- protected:
94
- inline IAsset* getDependant_impl (const size_t ix) override
95
- {
96
- return nullptr ;
97
- }
98
-
99
- inline void discardContent_impl () override
100
- {
101
- return freeData ();
102
- }
103
-
104
- // REMEMBER TO CALL FROM DTOR!
105
- // TODO: idea, make the `ICPUBuffer` an ADT, and use the default allocator CCPUBuffer instead for consistency
106
- // TODO: idea make a macro for overriding all `delete` operators of a class to enforce a finalizer that runs in reverse order to destructors (to allow polymorphic cleanups)
107
- virtual inline void freeData ()
108
- {
109
- if (data)
110
- _NBL_ALIGNED_FREE (data);
111
- data = nullptr ;
112
- m_creationParams.size = 0ull ;
113
- }
114
-
115
- void * data;
116
- };
117
-
118
-
119
- template <
120
- typename Allocator = _NBL_DEFAULT_ALLOCATOR_METATYPE<uint8_t >,
121
- bool = std::is_same<Allocator, core::null_allocator<typename Allocator::value_type> >::value
122
- >
123
- class CCustomAllocatorCPUBuffer ;
124
-
125
- using CDummyCPUBuffer = CCustomAllocatorCPUBuffer<core::null_allocator<uint8_t >, true >;
126
-
127
- // ! Specialization of ICPUBuffer capable of taking custom allocators
128
- /*
129
- Take a look that with this usage you have to specify custom alloctor
130
- passing an object type for allocation and a pointer to allocated
131
- data for it's storage by ICPUBuffer.
132
-
133
- So the need for the class existence is for common following tricks - among others creating an
134
- \bICPUBuffer\b over an already existing \bvoid*\b array without any \imemcpy\i or \itaking over the memory ownership\i.
135
- You can use it with a \bnull_allocator\b that adopts memory (it is a bit counter intuitive because \badopt = take\b ownership,
136
- but a \inull allocator\i doesn't do anything, even free the memory, so you're all good).
137
- */
138
-
139
- template <typename Allocator>
140
- class CCustomAllocatorCPUBuffer <Allocator,true > : public ICPUBuffer
141
- {
142
- static_assert (sizeof (typename Allocator::value_type) == 1u , " Allocator::value_type must be of size 1" );
143
- protected:
144
- Allocator m_allocator;
145
-
146
- virtual ~CCustomAllocatorCPUBuffer () final
147
- {
148
- freeData ();
149
- }
150
- inline void freeData () override
151
- {
152
- if (ICPUBuffer::data)
153
- m_allocator.deallocate (reinterpret_cast <typename Allocator::pointer>(ICPUBuffer::data), ICPUBuffer::m_creationParams.size );
154
- ICPUBuffer::data = nullptr ; // so that ICPUBuffer won't try deallocating
155
- }
156
-
157
- public:
158
- CCustomAllocatorCPUBuffer (size_t sizeInBytes, void * dat, core::adopt_memory_t , Allocator&& alctr = Allocator()) : ICPUBuffer(sizeInBytes,dat), m_allocator(std::move(alctr))
159
- {
160
- }
161
- };
162
-
163
- template <typename Allocator>
164
- class CCustomAllocatorCPUBuffer <Allocator, false > : public CCustomAllocatorCPUBuffer<Allocator, true >
165
- {
166
- using Base = CCustomAllocatorCPUBuffer<Allocator, true >;
167
-
168
- protected:
169
- virtual ~CCustomAllocatorCPUBuffer () = default ;
170
- inline void freeData () override {}
171
-
172
- public:
173
- using Base::Base;
174
-
175
- // TODO: remove, alloc can fail, should be a static create method instead!
176
- CCustomAllocatorCPUBuffer (size_t sizeInBytes, const void * dat, Allocator&& alctr = Allocator()) : Base(sizeInBytes, alctr.allocate(sizeInBytes), core::adopt_memory, std::move(alctr))
177
- {
178
- memcpy (Base::data,dat,sizeInBytes);
179
- }
116
+ protected:
117
+ inline IAsset* getDependant_impl (const size_t ix) override
118
+ {
119
+ return nullptr ;
120
+ }
121
+
122
+ inline void discardContent_impl () override
123
+ {
124
+ if (m_data)
125
+ m_mem_resource->deallocate (m_data, m_creationParams.size , m_alignment);
126
+ m_data = nullptr ;
127
+ m_mem_resource = nullptr ;
128
+ m_creationParams.size = 0ull ;
129
+ }
130
+
131
+ private:
132
+ ICPUBuffer (SCreationParams&& params) :
133
+ asset::IBuffer ({ params.size , EUF_TRANSFER_DST_BIT }), m_data(params.data),
134
+ m_mem_resource (params.memoryResource), m_alignment(params.alignment) {}
135
+
136
+ ~ICPUBuffer () override {
137
+ discardContent_impl ();
138
+ }
139
+
140
+ void * m_data;
141
+ core::smart_refctd_ptr<core::refctd_memory_resource> m_mem_resource;
142
+ size_t m_alignment;
180
143
};
181
144
182
145
} // end namespace nbl::asset
0 commit comments