@@ -13,15 +13,19 @@ namespace nbl
13
13
namespace scene
14
14
{
15
15
16
-
16
+ // TODO: split into ITT and ITTM because no need for multiple pipeline copies for multiple TTs
17
17
class ITransformTreeManager : public virtual core::IReferenceCounted
18
18
{
19
19
public:
20
20
using node_t = uint32_t ;
21
21
_NBL_STATIC_INLINE_CONSTEXPR node_t invalid_node = video::IPropertyPool::invalid_index;
22
22
23
23
using timestamp_t = video::IGPUAnimationLibrary::timestamp_t ;
24
+ // two timestamp values are reserved for initialization
25
+ _NBL_STATIC_INLINE_CONSTEXPR timestamp_t min_timestamp = 0u ;
26
+ _NBL_STATIC_INLINE_CONSTEXPR timestamp_t max_timestamp = 0xfffffffdu ;
24
27
28
+ _NBL_STATIC_INLINE_CONSTEXPR uint32_t parent_prop_ix = 0u ;
25
29
_NBL_STATIC_INLINE_CONSTEXPR uint32_t global_transform_prop_ix = 3u ;
26
30
private:
27
31
using parent_t = node_t ;
@@ -37,6 +41,42 @@ class ITransformTreeManager : public virtual core::IReferenceCounted
37
41
global_transform_t ,recomputed_stamp_t
38
42
>;
39
43
44
+ struct RelativeTransformModificationRequest
45
+ {
46
+ public:
47
+ enum E_TYPE : uint32_t
48
+ {
49
+ ET_OVERWRITE=0u , // exchange the value `This(vertex)`
50
+ ET_CONCATENATE_AFTER=1u , // apply transform after `This(Previous(vertex))`
51
+ ET_CONCATENATE_BEFORE=2u , // apply transform before `Previous(This(vertex))`
52
+ ET_WEIGHTED_ACCUMULATE=3u , // add to existing value `(Previous+This)(vertex)`
53
+ ET_COUNT
54
+ };
55
+ RelativeTransformModificationRequest (const E_TYPE type, const core::matrix3x4SIMD& _weightedModification) : storage(_weightedModification)
56
+ {
57
+ constexpr uint32_t log2ET_COUNT = 2u ;
58
+ static_assert (ET_COUNT<=(0x1u <<log2ET_COUNT)," Need to rewrite the type encoding routine!" );
59
+
60
+ uint32_t typeBits[log2ET_COUNT];
61
+ for (uint32_t i=0u ; i<log2ET_COUNT; i++)
62
+ typeBits[i] = (type>>i)&0x1u ;
63
+
64
+ // stuff the bits into x and z components of scale (without a rotation)
65
+ reinterpret_cast <uint32_t &>(storage.rows [0 ].x ) |= typeBits[0 ];
66
+ reinterpret_cast <uint32_t &>(storage.rows [2 ].z ) |= typeBits[1 ];
67
+ }
68
+ RelativeTransformModificationRequest (const E_TYPE type, const core::matrix3x4SIMD& _modification, const float weight) : RelativeTransformModificationRequest(type,_modification*weight) {}
69
+
70
+ inline E_TYPE getType () const
71
+ {
72
+ uint32_t retval = reinterpret_cast <const uint32_t &>(storage.rows [0 ].x )&0x1u ;
73
+ retval |= (reinterpret_cast <const uint32_t &>(storage.rows [2 ].z )&0x1u )<<1u ;
74
+ return static_cast <E_TYPE>(retval);
75
+ }
76
+ private:
77
+ core::matrix3x4SIMD storage;
78
+ };
79
+
40
80
// creation
41
81
static inline core::smart_refctd_ptr<ITransformTreeManager> create (video::IVideoDriver* _driver, asset::SBufferRange<video::IGPUBuffer>&& memoryBlock, core::allocator<uint8_t >&& alloc = core::allocator<uint8_t >())
42
82
{
@@ -71,6 +111,10 @@ class ITransformTreeManager : public virtual core::IReferenceCounted
71
111
asset::SBufferRange<video::IGPUBuffer> retval = {m_nodeStorage->getPropertyOffset (global_transform_prop_ix),m_nodeStorage->getCapacity ()*sizeof (global_transform_t ),m_nodeStorage->getMemoryBlock ().buffer };
72
112
return retval;
73
113
}
114
+
115
+ // need to at least initialize with the parent node property with the recompute and update timestamps at 0xfffffffeu and 0xffffffffu respectively
116
+ // but a function with optional relative transform would be nice
117
+ // need our own compute shader to initialize the properties ;(
74
118
#if 0
75
119
//
76
120
struct AllocationRequest
@@ -104,21 +148,23 @@ class ITransformTreeManager : public virtual core::IReferenceCounted
104
148
}
105
149
106
150
// TODO: make all these functions take a pipeline barrier type (future new API) with default being a full barrier
107
- void updateLocalTransforms (const asset::SBufferBinding<video::IGPUBuffer>& dispatchIndirectParameters, const asset::SBufferBinding<video::IGPUBuffer>& requestBuffer) // do we take a per-request nodeID buffer too?
151
+ template <typename ... Args>
152
+ inline void updateLocalTransforms (Args&&... args)
108
153
{
109
- assert ( false ); // TODO
154
+ soleUpdateOrFusedRecompute_impl (m_updatePipeline. get (),std::forward<Args>(args)...);
110
155
}
111
156
//
112
- void recomputeGlobalTransforms (/* dispatchIndirectParams,nodeList */ )
157
+ void recomputeGlobalTransforms (const asset::SBufferBinding<video::IGPUBuffer>& dispatchIndirectParameters, const asset::SBufferBinding<video::IGPUBuffer>& nodeIDBuffer )
113
158
{
114
159
// TODO: do it properly
115
160
auto out = getGlobalTransformationBufferRange ();
116
161
m_driver->copyBuffer (m_nodeStorage->getMemoryBlock ().buffer .get (),out.buffer .get (),m_nodeStorage->getPropertyOffset (1u ),out.offset ,out.size );
117
162
}
118
163
//
119
- void updateAndRecomputeGlobalTransforms (/* Same args as `updateLocalTransforms` and `recomputeGlobalTransforms`*/ )
164
+ template <typename ... Args>
165
+ inline void updateAndRecomputeTransforms (Args&&... args)
120
166
{
121
- assert ( false ); // TODO
167
+ soleUpdateOrFusedRecompute_impl (m_updateAndRecomputePipeline. get (),std::forward<Args>(args)...);
122
168
}
123
169
124
170
//
@@ -141,34 +187,30 @@ class ITransformTreeManager : public virtual core::IReferenceCounted
141
187
}
142
188
~ITransformTreeManager ()
143
189
{
144
- //
190
+ // everything drops itself automatically
145
191
}
146
192
147
- #if 0
148
- struct RootNodeParentIterator
193
+ void soleUpdateOrFusedRecompute_impl (
194
+ const video::IGPUComputePipeline* pipeline,
195
+ const asset::SBufferBinding<video::IGPUBuffer>& dispatchIndirectParameters,
196
+ const asset::SBufferBinding<video::IGPUBuffer>& nodeIDBuffer, // first uint in the nodeIDBuffer is used to denote how many requests we have
197
+ const asset::SBufferBinding<video::IGPUBuffer>& modificationRequestBuffer,
198
+ const asset::SBufferBinding<video::IGPUBuffer>& modificationRequestTimestampBuffer
199
+ )
149
200
{
150
- inline RootNodeParentIterator& operator++()
151
- {
152
- //do nothing
153
- return *this;
154
- }
155
- inline RootNodeParentIterator operator++(int)
156
- {
157
- //do nothing
158
- }
159
-
160
- inline node_t operator*() const
161
- {
162
- return invalid_node;
163
- }
164
-
165
- //using iterator_category = typename std::iterator_traits::;
166
- //using difference_type = ptrdiff_t;
167
- using value_type = node_t;
168
- };
169
- #endif
201
+ // TODO: first a dispatch to sort the modification requests and timestamps according to node frequency
202
+ m_driver->bindComputePipeline (pipeline);
203
+ assert (false ); // TODO: get a descriptor set to populate with our input buffers (plus indirect dispatch buffer + nodeIDBuffer if pipeline==m_updateAndRecomputePipeline)
204
+ const video::IGPUDescriptorSet* descSets[] = { m_transformHierarchyDS.get (),nullptr };
205
+ m_driver->bindDescriptorSets (video::EPBP_COMPUTE,pipeline->getLayout (),0u ,2u ,descSets,nullptr );
206
+ m_driver->dispatchIndirect (dispatchIndirectParameters.buffer .get (),dispatchIndirectParameters.offset );
207
+ // TODO: pipeline barrier for UBO, SSBO and TBO and if pipeline==m_updatePipeline then COMMAND_BIT too
208
+ }
209
+
170
210
video::IVideoDriver* m_driver;
171
211
core::smart_refctd_ptr<property_pool_t > m_nodeStorage;
212
+ core::smart_refctd_ptr<video::IGPUComputePipeline> m_updatePipeline,m_recomputePipeline,m_updateAndRecomputePipeline;
213
+ core::smart_refctd_ptr<video::IGPUDescriptorSet> m_transformHierarchyDS;
172
214
};
173
215
174
216
0 commit comments