Skip to content

Commit 0da8774

Browse files
crea IGPUSkeleton.h and attempt CPU to GPU conversion
1 parent 799d183 commit 0da8774

File tree

8 files changed

+254
-31
lines changed

8 files changed

+254
-31
lines changed

examples_tests/04.Keyframe/main.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,30 @@ int main()
8989
auto* driver = device->getVideoDriver();
9090
auto* smgr = device->getSceneManager();
9191

92+
//
93+
constexpr uint32_t kJointCount = 2u;
94+
asset::SBufferBinding<asset::ICPUBuffer> parentIDs,inverseBindPoses;
95+
{
96+
parentIDs.buffer = core::make_smart_refctd_ptr<asset::ICPUBuffer>(sizeof(asset::ICPUSkeleton)*kJointCount);
97+
{
98+
asset::ICPUSkeleton::joint_id_t parentJointIDs[] = { asset::ICPUSkeleton::invalid_joint_id,0u };
99+
memcpy(parentIDs.buffer->getPointer(),parentJointIDs,sizeof(parentJointIDs));
100+
}
101+
inverseBindPoses.buffer = core::make_smart_refctd_ptr<asset::ICPUBuffer>(sizeof(matrix3x4SIMD)*kJointCount);
102+
{
103+
auto* invBindPoses = reinterpret_cast<matrix3x4SIMD*>(inverseBindPoses.buffer->getPointer());
104+
for (auto i=0u; i<kJointCount; i++)
105+
{
106+
matrix3x4SIMD tmp;
107+
tmp.setTranslation(core::vectorSIMDf(0.f,float(i)*2.f-1.f,0.f));
108+
tmp.getInverse(invBindPoses[i]);
109+
}
110+
}
111+
}
112+
const char* jointNames[] = {"root","bendy"};
113+
auto skeleton = core::make_smart_refctd_ptr<asset::ICPUSkeleton>(std::move(parentIDs),std::move(inverseBindPoses),&jointNames[0],&jointNames[0]+kJointCount);
114+
//auto gpuSkeleton = driver->getGPUObjectsFromAssets<asset::ICPUSkeleton>(&skeleton,&skeleton+1u); // TODO: Test conversion path, linker error
115+
92116
//
93117
core::smart_refctd_ptr<video::IGPUMeshBuffer> mb;
94118
{

include/nbl/asset/IAsset.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ class IAsset : virtual public core::IReferenceCounted
164164
Additionally the size is used to determine compression level while writing process is performed.
165165
As you expect, the bigger the size returned the more likely it is to be compressed with a more expensive (slower) algorithm.
166166
*/
167-
virtual size_t conservativeSizeEstimate() const = 0;
167+
virtual size_t conservativeSizeEstimate() const = 0; // TODO: this shouldn't be a method of IAsset but BlobSerializable ?
168168

169169
//! creates a copy of the asset, duplicating dependant resources up to a certain depth (default duplicate everything)
170170
virtual core::smart_refctd_ptr<IAsset> clone(uint32_t _depth = ~0u) const = 0;

include/nbl/asset/ICPUSkeleton.h

Lines changed: 67 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -13,35 +13,39 @@ namespace nbl
1313
namespace asset
1414
{
1515

16-
class ICPUSkeleton : public ISkeleton<ICPUBuffer>, /*TODO: public BlobSerializable, */public IAsset
16+
class ICPUSkeleton final : public ISkeleton<ICPUBuffer>, /*TODO: public BlobSerializable, */public IAsset
1717
{
1818
public:
19-
using Base = ISkeleton<ICPUBuffer>;
19+
using base_t = ISkeleton<ICPUBuffer>;
2020

2121
template<typename NameIterator>
22-
ICPUSkeleton(SBufferBinding<BufferType>&& _parentJointIDsBinding, SBufferBinding<BufferType>&& _inverseBindPosesBinding, NameIterator begin, NameIterator end) : Base(std::move(_parentJointIDsBinding),std::move(_inverseBindPosesBinding))
22+
inline ICPUSkeleton(SBufferBinding<ICPUBuffer>&& _parentJointIDsBinding, SBufferBinding<ICPUBuffer>&& _inverseBindPosesBinding, NameIterator begin, NameIterator end) : base_t(std::move(_parentJointIDsBinding),std::move(_inverseBindPosesBinding),std::distance(begin,end))
2323
{
24-
Base::setJointNames<NameIterator>(begin,end);
24+
base_t::setJointNames<NameIterator>(begin,end);
2525
}
26+
template<typename... Args>
27+
inline ICPUSkeleton(Args&&... args) : base_t(std::forward<Args>(args)...) {}
2628

2729
//
28-
inline const core::matrix3x4SIMD& getInversePoseBindMatrix(Base::joint_id_t jointID) const
30+
inline const core::matrix3x4SIMD& getInversePoseBindMatrix(base_t::joint_id_t jointID) const
2931
{
30-
return reinterpret_cast<const core::matrix3x4SIMD*>(m_inverseBindPoses.buffer->getPointer()+m_inverseBindPoses.offset)[jointID];
32+
const uint8_t* ptr = reinterpret_cast<const uint8_t*>(m_inverseBindPoses.buffer->getPointer());
33+
return reinterpret_cast<const core::matrix3x4SIMD*>(ptr+m_inverseBindPoses.offset)[jointID];
3134
}
32-
inline core::matrix3x4SIMD& getInversePoseBindMatrix(Base::joint_id_t jointID)
35+
inline core::matrix3x4SIMD& getInversePoseBindMatrix(base_t::joint_id_t jointID)
3336
{
3437
return const_cast<core::matrix3x4SIMD&>(const_cast<const ICPUSkeleton*>(this)->getInversePoseBindMatrix(jointID));
3538
}
3639

3740
//
38-
inline const Base::joint_id_t& getParentJointID(Base::joint_id_t jointID) const
41+
inline const base_t::joint_id_t& getParentJointID(base_t::joint_id_t jointID) const
3942
{
40-
return reinterpret_cast<const Base::joint_id_t*>(m_parentJointIDs.buffer->getPointer()+m_parentJointIDs.offset)[jointID];
43+
const uint8_t* ptr = reinterpret_cast<const uint8_t*>(m_parentJointIDs.buffer->getPointer());
44+
return reinterpret_cast<const base_t::joint_id_t*>(ptr+m_parentJointIDs.offset)[jointID];
4145
}
42-
inline Base::joint_id_t& getParentJointID(Base::joint_id_t jointID)
46+
inline base_t::joint_id_t& getParentJointID(base_t::joint_id_t jointID)
4347
{
44-
return const_cast<Base::joint_id_t&>(const_cast<const ICPUSkeleton*>(this)->getParentJointID(jointID));
48+
return const_cast<base_t::joint_id_t&>(const_cast<const ICPUSkeleton*>(this)->getParentJointID(jointID));
4549
}
4650

4751
//! Serializes mesh to blob for *.baw file format.
@@ -55,31 +59,65 @@ class ICPUSkeleton : public ISkeleton<ICPUBuffer>, /*TODO: public BlobSerializab
5559
}
5660
*/
5761

62+
core::smart_refctd_ptr<IAsset> clone(uint32_t _depth = ~0u) const override
63+
{
64+
SBufferBinding<ICPUBuffer> _parentJointIDsBinding = {m_parentJointIDs.offset,_depth>0u&&m_parentJointIDs.buffer ? core::smart_refctd_ptr_static_cast<ICPUBuffer>(m_parentJointIDs.buffer->clone(_depth-1u)):m_parentJointIDs.buffer};
65+
SBufferBinding<ICPUBuffer> _inverseBindPosesBinding = {m_inverseBindPoses.offset,_depth>0u&&m_inverseBindPoses.buffer ? core::smart_refctd_ptr_static_cast<ICPUBuffer>(m_inverseBindPoses.buffer->clone(_depth-1u)):m_inverseBindPoses.buffer};
66+
67+
auto cp = core::make_smart_refctd_ptr<ICPUSkeleton>(std::move(_parentJointIDsBinding),std::move(_inverseBindPosesBinding),m_jointCount);
68+
clone_common(cp.get());
69+
assert(!cp->m_stringPool);
70+
cp->m_stringPoolSize = m_stringPoolSize;
71+
cp->m_stringPool = _NBL_NEW_ARRAY(char,m_stringPoolSize);
72+
memcpy(cp->m_stringPool,m_stringPool,m_stringPoolSize);
73+
for (auto stringToID : m_nameToJointID)
74+
cp->m_nameToJointID.emplace(stringToID.first-m_stringPool+cp->m_stringPool,stringToID.second);
75+
76+
return cp;
77+
}
78+
5879
virtual void convertToDummyObject(uint32_t referenceLevelsBelowToConvert=0u) override
5980
{
6081
convertToDummyObject_common(referenceLevelsBelowToConvert);
6182

6283
if (referenceLevelsBelowToConvert)
63-
for (auto i=0u; i<getMeshBufferCount(); i++)
64-
getMeshBuffer(i)->convertToDummyObject(referenceLevelsBelowToConvert-1u);
84+
{
85+
m_parentJointIDs.buffer->convertToDummyObject(referenceLevelsBelowToConvert-1u);
86+
m_inverseBindPoses.buffer->convertToDummyObject(referenceLevelsBelowToConvert-1u);
87+
// TODO: do we clear out the string pool and the name to bone ID mapping?
88+
}
6589
}
6690

6791
_NBL_STATIC_INLINE_CONSTEXPR auto AssetType = ET_SKELETON;
6892
inline E_TYPE getAssetType() const override { return AssetType; }
69-
/* TODO
93+
7094
virtual size_t conservativeSizeEstimate() const override
7195
{
72-
size_t estimate = m_nameToJointID.size()*sizeof(std::pair<const char*,joint_id_t>);
96+
size_t estimate = sizeof(SBufferBinding<ICPUBuffer>)*2ull;
97+
estimate += sizeof(uint16_t);
98+
estimate += m_stringPoolSize;
99+
estimate += m_nameToJointID.size()*sizeof(std::pair<uint32_t,joint_id_t>);
73100
// do we add other things to the size estimate?
74101
return estimate;
75102
}
76-
*/
103+
77104
bool canBeRestoredFrom(const IAsset* _other) const override
78105
{
79106
auto other = static_cast<const ICPUSkeleton*>(_other);
80-
if (getJointCount()!=other->getJointCount())
81-
return false;
82-
if (!getMeshBuffer(i)->canBeRestoredFrom(other->getMeshBuffer(i)))
107+
// if we decide to get rid of the string pool when converting to dummy, then we need to start checking stringpool and map properties here
108+
if (m_parentJointIDs.offset != other->m_parentJointIDs.offset)
109+
return false;
110+
if ((!m_parentJointIDs.buffer) != (!other->m_parentJointIDs.buffer))
111+
return false;
112+
if (m_parentJointIDs.buffer && !m_parentJointIDs.buffer->canBeRestoredFrom(other->m_parentJointIDs.buffer.get()))
113+
return false;
114+
if (m_inverseBindPoses.offset != other->m_inverseBindPoses.offset)
115+
return false;
116+
if ((!m_inverseBindPoses.buffer) != (!other->m_inverseBindPoses.buffer))
117+
return false;
118+
if (m_inverseBindPoses.buffer && !m_inverseBindPoses.buffer->canBeRestoredFrom(other->m_inverseBindPoses.buffer.get()))
119+
return false;
120+
if (m_jointCount != other->m_jointCount)
83121
return false;
84122

85123
return true;
@@ -93,15 +131,21 @@ class ICPUSkeleton : public ISkeleton<ICPUBuffer>, /*TODO: public BlobSerializab
93131
if (_levelsBelow)
94132
{
95133
--_levelsBelow;
96-
//for (uint32_t i = 0u; i < getMeshBufferCount(); i++)
97-
//restoreFromDummy_impl_call(getMeshBuffer(i), other->getMeshBuffer(i), _levelsBelow);
134+
135+
if (m_parentJointIDs.buffer)
136+
restoreFromDummy_impl_call(m_parentJointIDs.buffer.get(),other->m_parentJointIDs.buffer.get(),_levelsBelow);
137+
if (m_inverseBindPoses.buffer)
138+
restoreFromDummy_impl_call(m_inverseBindPoses.buffer.get(),other->m_inverseBindPoses.buffer.get(),_levelsBelow);
98139
}
99140
}
100141

101142
bool isAnyDependencyDummy_impl(uint32_t _levelsBelow) const override
102143
{
103-
// TODO
104-
return false;
144+
--_levelsBelow;
145+
if (m_parentJointIDs.buffer && m_parentJointIDs.buffer->isAnyDependencyDummy(_levelsBelow))
146+
return true;
147+
148+
return m_inverseBindPoses.buffer && m_inverseBindPoses.buffer->isAnyDependencyDummy(_levelsBelow);
105149
}
106150
};
107151

include/nbl/asset/ISkeleton.h

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,14 @@ namespace asset
2222
class ISkeleton : public virtual core::IReferenceCounted
2323
{
2424
public:
25-
using joint_id_t = uint32_t;
25+
using joint_id_t = uint16_t;
2626
_NBL_STATIC_INLINE_CONSTEXPR joint_id_t invalid_joint_id = 0xffffu;
2727

2828

29+
inline const auto& getJointNameToIDMap() const
30+
{
31+
return m_nameToJointID;
32+
}
2933
inline joint_id_t getJointIDFromName(const char* jointName) const
3034
{
3135
auto found = m_nameToJointID.find(jointName);
@@ -34,9 +38,9 @@ namespace asset
3438
return invalid_joint_id;
3539
}
3640

37-
inline uint32_t getJointCount() const
41+
inline joint_id_t getJointCount() const
3842
{
39-
return jointCount;
43+
return m_jointCount;
4044
}
4145

4246
inline SBufferBinding<BufferType>& getParentJointIDBinding()
@@ -59,10 +63,15 @@ namespace asset
5963

6064

6165
protected:
62-
ISkeleton(SBufferBinding<BufferType>&& _parentJointIDsBinding, SBufferBinding<BufferType>&& _inverseBindPosesBinding)
63-
: m_nameToJointID(), m_stringPoolSize(0ull), m_stringPool(nullptr), m_jointCount(0u),
66+
ISkeleton(SBufferBinding<BufferType>&& _parentJointIDsBinding, SBufferBinding<BufferType>&& _inverseBindPosesBinding, joint_id_t _jointCount = 0u)
67+
: m_nameToJointID(), m_stringPoolSize(0ull), m_stringPool(nullptr), m_jointCount(_jointCount),
6468
m_parentJointIDs(std::move(_parentJointIDsBinding)), m_inverseBindPoses(std::move(_inverseBindPosesBinding))
6569
{
70+
if (m_jointCount==0u)
71+
return;
72+
73+
assert(m_parentJointIDs.buffer->getSize()>=m_parentJointIDs.offset+sizeof(joint_id_t)*m_jointCount);
74+
assert(m_inverseBindPoses.buffer->getSize()>=m_inverseBindPoses.offset+sizeof(core::matrix3x4SIMD)*m_jointCount);
6675
}
6776
virtual ~ISkeleton()
6877
{
@@ -121,9 +130,8 @@ namespace asset
121130
size_t m_stringPoolSize;
122131
char* m_stringPool;
123132

124-
uint32_t m_jointCount;
125-
126133
SBufferBinding<BufferType> m_parentJointIDs,m_inverseBindPoses;
134+
joint_id_t m_jointCount;
127135
};
128136

129137
} // end namespace asset

include/nbl/asset/asset.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,12 @@
4646
#include "nbl/asset/utils/IBuiltinIncludeLoader.h"
4747
#include "nbl/asset/utils/IGLSLCompiler.h"
4848
#include "nbl/asset/utils/CShaderIntrospector.h"
49+
4950
// pipelines
5051

52+
// skinning
53+
#include "nbl/asset/ICPUSkeleton.h"
54+
5155
// meshes
5256
#include "nbl/asset/ICPUMeshBuffer.h"
5357
#include "nbl/asset/ICPUMesh.h"

include/nbl/video/IGPUObjectFromAssetConverter.h

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
#ifndef __NBL_VIDEO_I_GPU_OBJECT_FROM_ASSET_CONVERTER_H_INCLUDED__
77
#define __NBL_VIDEO_I_GPU_OBJECT_FROM_ASSET_CONVERTER_H_INCLUDED__
88

9+
#include <iterator>
10+
911
#include "nbl/core/core.h"
1012
#include "nbl/asset/asset.h"
1113

@@ -83,6 +85,7 @@ class IGPUObjectFromAssetConverter
8385
virtual ~IGPUObjectFromAssetConverter() = default;
8486

8587
inline virtual created_gpu_object_array<asset::ICPUBuffer> create(const asset::ICPUBuffer** const _begin, const asset::ICPUBuffer** const _end, const SParams& _params);
88+
inline virtual created_gpu_object_array<asset::ICPUSkeleton> create(const asset::ICPUSkeleton** const _begin, const asset::ICPUSkeleton** const _end, const SParams& _params);
8689
inline virtual created_gpu_object_array<asset::ICPUMeshBuffer> create(const asset::ICPUMeshBuffer** const _begin, const asset::ICPUMeshBuffer** const _end, const SParams& _params);
8790
inline virtual created_gpu_object_array<asset::ICPUMesh> create(const asset::ICPUMesh** const _begin, const asset::ICPUMesh** const _end, const SParams& _params);
8891
inline virtual created_gpu_object_array<asset::ICPUImage> create(const asset::ICPUImage** const _begin, const asset::ICPUImage** const _end, const SParams& _params);
@@ -327,6 +330,103 @@ auto IGPUObjectFromAssetConverter::create(const asset::ICPUBuffer** const _begin
327330

328331
return res;
329332
}
333+
namespace impl
334+
{
335+
template<typename MapIterator>
336+
struct CustomBoneNameIterator
337+
{
338+
inline CustomBoneNameIterator(const MapIterator& it) : m_it(it) {}
339+
inline CustomBoneNameIterator(MapIterator&& it) : m_it(std::move(it)) {}
340+
341+
inline bool operator!=(const CustomBoneNameIterator<MapIterator>& other) const
342+
{
343+
return m_it!=other.m_it;
344+
}
345+
346+
inline CustomBoneNameIterator<MapIterator>& operator++()
347+
{
348+
++m_it;
349+
return *this;
350+
}
351+
inline CustomBoneNameIterator<MapIterator> operator++(int)
352+
{
353+
return m_it++;
354+
}
355+
356+
inline CustomBoneNameIterator<MapIterator> operator-(const CustomBoneNameIterator<MapIterator>& other) const
357+
{
358+
return m_it-other.m_it;
359+
}
360+
361+
inline const auto& operator*() const
362+
{
363+
return m_it->first;
364+
}
365+
inline auto& operator*()
366+
{
367+
return m_it->first;
368+
}
369+
370+
using iterator_category = typename std::iterator_traits<MapIterator>::iterator_category;
371+
using difference_type = typename std::iterator_traits<MapIterator>::difference_type;
372+
using value_type = const char*;
373+
using reference = std::add_lvalue_reference_t<value_type>;
374+
using pointer = std::add_pointer_t<value_type>;
375+
376+
private:
377+
MapIterator m_it;
378+
};
379+
}
380+
auto IGPUObjectFromAssetConverter::create(const asset::ICPUSkeleton** _begin, const asset::ICPUSkeleton** _end, const SParams& _params) -> created_gpu_object_array<asset::ICPUSkeleton>
381+
{
382+
const size_t assetCount = std::distance(_begin, _end);
383+
auto res = core::make_refctd_dynamic_array<created_gpu_object_array<asset::ICPUSkeleton> >(assetCount);
384+
385+
core::vector<const asset::ICPUBuffer*> cpuBuffers;
386+
cpuBuffers.reserve(assetCount*2u);
387+
388+
for (ptrdiff_t i=0u; i<assetCount; i++)
389+
{
390+
const asset::ICPUSkeleton* cpusk = _begin[i];
391+
if (const asset::ICPUBuffer* buf = cpusk->getParentJointIDBinding().buffer.get())
392+
cpuBuffers.push_back(buf);;
393+
if (const asset::ICPUBuffer* buf = cpusk->getInverseBindPosesBinding().buffer.get())
394+
cpuBuffers.push_back(buf);
395+
}
396+
397+
using redirs_t = core::vector<size_t>;
398+
redirs_t bufRedirs = eliminateDuplicatesAndGenRedirs(cpuBuffers);
399+
400+
auto gpuBuffers = getGPUObjectsFromAssets<asset::ICPUBuffer>(cpuBuffers.data(), cpuBuffers.data()+cpuBuffers.size(), _params);
401+
402+
size_t bufIter = 0ull;
403+
for (ptrdiff_t i = 0u; i < assetCount; ++i)
404+
{
405+
const asset::ICPUSkeleton* cpusk = _begin[i];
406+
407+
asset::SBufferBinding<IGPUBuffer> parentJointIDBinding;
408+
if (cpusk->getParentJointIDBinding().buffer)
409+
{
410+
parentJointIDBinding.offset = cpusk->getParentJointIDBinding().offset;
411+
auto& gpubuf = (*gpuBuffers)[bufRedirs[bufIter++]];
412+
parentJointIDBinding.offset += gpubuf->getOffset();
413+
parentJointIDBinding.buffer = core::smart_refctd_ptr<IGPUBuffer>(gpubuf->getBuffer());
414+
}
415+
asset::SBufferBinding<IGPUBuffer> inverseBindPosesBinding;
416+
if (cpusk->getInverseBindPosesBinding().buffer)
417+
{
418+
inverseBindPosesBinding.offset = cpusk->getInverseBindPosesBinding().offset;
419+
auto& gpubuf = (*gpuBuffers)[bufRedirs[bufIter++]];
420+
inverseBindPosesBinding.offset += gpubuf->getOffset();
421+
inverseBindPosesBinding.buffer = core::smart_refctd_ptr<IGPUBuffer>(gpubuf->getBuffer());
422+
}
423+
424+
const auto& nameMap = cpusk->getJointNameToIDMap();
425+
(*res)[i] = core::make_smart_refctd_ptr<IGPUSkeleton>(std::move(parentJointIDBinding),std::move(inverseBindPosesBinding),impl::CustomBoneNameIterator(nameMap.begin()),impl::CustomBoneNameIterator(nameMap.end()));
426+
}
427+
428+
return res;
429+
}
330430
auto IGPUObjectFromAssetConverter::create(const asset::ICPUMeshBuffer** _begin, const asset::ICPUMeshBuffer** _end, const SParams& _params) -> created_gpu_object_array<asset::ICPUMeshBuffer>
331431
{
332432
const size_t assetCount = std::distance(_begin, _end);

0 commit comments

Comments
 (0)