11using System ;
22using System . Diagnostics ;
33using System . Runtime . CompilerServices ;
4+ using System . Runtime . Intrinsics ;
45using Unmanaged ;
56using Worlds . Pointers ;
67
@@ -12,7 +13,18 @@ namespace Worlds
1213 [ SkipLocalsInit ]
1314 public unsafe struct Chunk : IDisposable , IEquatable < Chunk >
1415 {
16+ /// <summary>
17+ /// Retrieves the component types stored in this chunk.
18+ /// </summary>
19+ public readonly BitMask componentTypes ;
20+
1521 internal ChunkPointer * chunk ;
22+ internal uint * componentOffsets ;
23+
24+ /// <summary>
25+ /// Retrieves the tag types stored in this chunk.
26+ /// </summary>
27+ public readonly BitMask tagTypes ;
1628
1729 /// <summary>
1830 /// Checks if this chunk is disposed.
@@ -29,6 +41,7 @@ public unsafe struct Chunk : IDisposable, IEquatable<Chunk>
2941 /// </summary>
3042 public readonly ReadOnlySpan < uint > Entities
3143 {
44+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
3245 get
3346 {
3447 MemoryAddress . ThrowIfDefault ( chunk ) ;
@@ -38,68 +51,69 @@ public readonly ReadOnlySpan<uint> Entities
3851 }
3952
4053 /// <summary>
41- /// Amount of entities stored in this chunk.
54+ /// Retrieves the array types stored in this chunk.
4255 /// </summary>
43- public readonly int Count
56+ public readonly BitMask ArrayTypes
4457 {
58+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
4559 get
4660 {
4761 MemoryAddress . ThrowIfDefault ( chunk ) ;
4862
49- return chunk ->count ;
63+ return chunk ->arrayTypes ;
5064 }
5165 }
5266
5367 /// <summary>
54- /// Returns the definition representing the types of components, arrays and tags
55- /// this chunk is for.
68+ /// Amount of entities stored in this chunk.
5669 /// </summary>
57- public readonly Definition Definition
70+ public readonly int Count
5871 {
72+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
5973 get
6074 {
6175 MemoryAddress . ThrowIfDefault ( chunk ) ;
6276
63- return chunk ->Definition ;
77+ return chunk ->count ;
6478 }
6579 }
6680
6781 /// <summary>
68- /// Retrieves the component types stored in this chunk .
82+ /// Checks if this definition describes a disabled entity .
6983 /// </summary>
70- public readonly BitMask ComponentTypes
84+ public readonly bool IsDisabled
7185 {
86+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
7287 get
7388 {
74- MemoryAddress . ThrowIfDefault ( chunk ) ;
75-
76- return chunk ->componentTypes ;
89+ return ( tagTypes . value . GetElement ( 3 ) & Schema . DisabledMask ) != 0 ;
7790 }
7891 }
7992
8093 /// <summary>
81- /// Retrieves the array types stored in this chunk .
94+ /// Checks if this definition describes an enabled entity .
8295 /// </summary>
83- public readonly BitMask ArrayTypes
96+ public readonly bool IsEnabled
8497 {
98+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
8599 get
86100 {
87- MemoryAddress . ThrowIfDefault ( chunk ) ;
88-
89- return chunk ->arrayTypes ;
101+ return ( tagTypes . value . GetElement ( 3 ) & Schema . DisabledMask ) == 0 ;
90102 }
91103 }
92104
93105 /// <summary>
94- /// Retrieves the tag types stored in this chunk.
106+ /// Returns the definition representing the types of components, arrays and tags
107+ /// this chunk is for.
95108 /// </summary>
96- public readonly BitMask TagTypes
109+ public readonly Definition Definition
97110 {
111+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
98112 get
99113 {
100114 MemoryAddress . ThrowIfDefault ( chunk ) ;
101115
102- return chunk -> tagTypes ;
116+ return new ( componentTypes , ArrayTypes , tagTypes ) ;
103117 }
104118 }
105119
@@ -108,12 +122,12 @@ public readonly BitMask TagTypes
108122 /// </summary>
109123 public readonly Row this [ int index ]
110124 {
125+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
111126 get
112127 {
113128 MemoryAddress . ThrowIfDefault ( chunk ) ;
114129
115- MemoryAddress row = chunk ->components [ index ] ;
116- return new Row ( chunk ->schema , row ) ;
130+ return new Row ( componentOffsets , chunk ->schema . schema ->sizes , chunk ->components [ index ] ) ;
117131 }
118132 }
119133
@@ -122,6 +136,7 @@ public readonly Row this[int index]
122136 /// </summary>
123137 public readonly int Version
124138 {
139+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
125140 get
126141 {
127142 MemoryAddress . ThrowIfDefault ( chunk ) ;
@@ -133,34 +148,81 @@ public readonly int Version
133148#if NET
134149 /// <inheritdoc/>
135150 [ Obsolete ( "Default constructor not supported" , true ) ]
136- public Chunk ( )
137- {
138- throw new NotSupportedException ( ) ;
139- }
151+ public Chunk ( ) { }
140152#endif
141153
142154 /// <summary>
143155 /// Creates a new chunk with the given <paramref name="definition"/>.
144156 /// </summary>
145157 public Chunk ( Schema schema , Definition definition = default )
146158 {
159+ componentOffsets = schema . componentOffsets ;
160+ MemoryAddress . ThrowIfDefault ( componentOffsets ) ;
161+
147162 chunk = MemoryAddress . AllocatePointer < ChunkPointer > ( ) ;
148163 chunk ->lastEntity = 0 ;
149164 chunk ->count = 0 ;
150165 chunk ->version = 0 ;
151166 chunk ->entities = new ( 4 ) ;
152- chunk ->entities . AddDefault ( ) ; //reserved
167+ chunk ->entities . AddDefault ( ) ; // reserved
153168 chunk ->components = new ( 4 , ( int ) schema . schema ->componentRowSize ) ;
154- chunk ->components . AddDefault ( ) ; //reserved
169+ chunk ->components . AddDefault ( ) ; // reserved
155170 chunk ->schema = schema ;
156171 chunk ->componentTypes = definition . componentTypes ;
157172 chunk ->arrayTypes = definition . arrayTypes ;
158173 chunk ->tagTypes = definition . tagTypes ;
174+ componentTypes = definition . componentTypes ;
175+ tagTypes = definition . tagTypes ;
176+ }
177+
178+ internal Chunk ( SchemaPointer * schema , BitMask componentTypes , BitMask arrayTypes , BitMask tagTypes )
179+ {
180+ componentOffsets = schema ->componentOffsets ;
181+ MemoryAddress . ThrowIfDefault ( componentOffsets ) ;
182+
183+ chunk = MemoryAddress . AllocatePointer < ChunkPointer > ( ) ;
184+ chunk ->lastEntity = 0 ;
185+ chunk ->count = 0 ;
186+ chunk ->version = 0 ;
187+ chunk ->entities = new ( 4 ) ;
188+ chunk ->entities . AddDefault ( ) ; // reserved
189+ chunk ->components = new ( 4 , ( int ) schema ->componentRowSize ) ;
190+ chunk ->components . AddDefault ( ) ; // reserved
191+ chunk ->schema = new ( schema ) ;
192+ chunk ->componentTypes = componentTypes ;
193+ chunk ->arrayTypes = arrayTypes ;
194+ chunk ->tagTypes = tagTypes ;
195+ this . componentTypes = componentTypes ;
196+ this . tagTypes = tagTypes ;
197+ }
198+
199+ internal Chunk ( SchemaPointer * schema )
200+ {
201+ componentOffsets = schema ->componentOffsets ;
202+ MemoryAddress . ThrowIfDefault ( componentOffsets ) ;
203+
204+ chunk = MemoryAddress . AllocatePointer < ChunkPointer > ( ) ;
205+ chunk ->lastEntity = 0 ;
206+ chunk ->count = 0 ;
207+ chunk ->version = 0 ;
208+ chunk ->entities = new ( 4 ) ;
209+ chunk ->entities . AddDefault ( ) ; // reserved
210+ chunk ->components = new ( 4 , ( int ) schema ->componentRowSize ) ;
211+ chunk ->components . AddDefault ( ) ; // reserved
212+ chunk ->schema = new ( schema ) ;
213+ chunk ->componentTypes = default ;
214+ chunk ->arrayTypes = default ;
215+ chunk ->tagTypes = default ;
216+ componentTypes = default ;
217+ tagTypes = default ;
159218 }
160219
161220 internal Chunk ( ChunkPointer * chunk )
162221 {
163222 this . chunk = chunk ;
223+ componentTypes = chunk ->componentTypes ;
224+ tagTypes = chunk ->tagTypes ;
225+ componentOffsets = chunk ->schema . componentOffsets ;
164226 }
165227
166228 /// <inheritdoc/>
@@ -173,17 +235,17 @@ public void Dispose()
173235 MemoryAddress . Free ( ref chunk ) ;
174236 }
175237
176- internal readonly void UpdateStrideToMatchSchema ( )
238+ internal readonly void UpdateStrideToMatchSchema ( uint componentRowSize )
177239 {
178240 chunk ->components . Dispose ( ) ;
179- chunk ->components = new ( 4 , ( int ) chunk -> schema . schema -> componentRowSize ) ;
180- chunk ->components . AddDefault ( ) ; //reserved
241+ chunk ->components = new ( 4 , ( int ) componentRowSize ) ;
242+ chunk ->components . AddDefault ( ) ; // reserved
181243 }
182244
183245 [ Conditional ( "DEBUG" ) ]
184246 private readonly void ThrowIfComponentTypeIsMissing ( int componentType )
185247 {
186- if ( ! chunk -> componentTypes . Contains ( componentType ) )
248+ if ( ! componentTypes . Contains ( componentType ) )
187249 {
188250 throw new ArgumentException ( $ "Component type `{ DataType . GetComponent ( componentType , chunk ->schema ) . ToString ( chunk ->schema ) } ` is missing from the chunk") ;
189251 }
@@ -221,10 +283,10 @@ public readonly int ToString(Span<char> destination)
221283 {
222284 int length = 0 ;
223285 length += chunk ->count . ToString ( destination ) ;
224- if ( chunk -> Definition != Definition . Default )
286+ if ( componentTypes != BitMask . Default && ArrayTypes != BitMask . Default && tagTypes != BitMask . Default )
225287 {
226288 destination [ length ++ ] = ' ' ;
227- length += chunk -> Definition . ToString ( chunk ->schema , destination . Slice ( length ) ) ;
289+ length += new Definition ( componentTypes , ArrayTypes , tagTypes ) . ToString ( chunk ->schema , destination . Slice ( length ) ) ;
228290 }
229291
230292 return length ;
@@ -233,39 +295,46 @@ public readonly int ToString(Span<char> destination)
233295 /// <inheritdoc/>
234296 public readonly override int GetHashCode ( )
235297 {
236- return chunk -> Definition . GetHashCode ( ) ;
298+ return ( int ) Definition . GetLongHashCode ( componentTypes , ArrayTypes , tagTypes ) ;
237299 }
238300
239301 /// <summary>
240302 /// Retrieves the byte offset of the <paramref name="componentType"/>
241303 /// </summary>
304+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
242305 public readonly int GetComponentOffset ( int componentType )
243306 {
244- MemoryAddress . ThrowIfDefault ( chunk ) ;
307+ MemoryAddress . ThrowIfDefault ( componentOffsets ) ;
308+ ThrowIfComponentTypeIsMissing ( componentType ) ;
245309
246- return ( int ) chunk -> schema . schema -> componentOffsets [ ( uint ) componentType ] ;
310+ return ( int ) componentOffsets [ ( uint ) componentType ] ;
247311 }
248312
249313 /// <summary>
250314 /// Retrieves an enumerator for iterating through each component of type <typeparamref name="T"/>.
251315 /// </summary>
316+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
252317 public readonly ComponentEnumerator < T > GetComponents < T > ( int componentType ) where T : unmanaged
253318 {
254- int componentOffset = ( int ) chunk ->schema . schema ->componentOffsets [ ( uint ) componentType ] ;
255- return new ( chunk ->components , componentOffset ) ;
319+ MemoryAddress . ThrowIfDefault ( chunk ) ;
320+ MemoryAddress . ThrowIfDefault ( componentOffsets ) ;
321+ ThrowIfComponentTypeIsMissing ( componentType ) ;
322+
323+ return new ( chunk ->components , ( int ) componentOffsets [ ( uint ) componentType ] ) ;
256324 }
257325
258326 /// <summary>
259327 /// Retrieves a reference to the component of type <paramref name="componentType"/>.
260328 /// </summary>
329+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
261330 public readonly ref T GetComponent < T > ( int index , int componentType ) where T : unmanaged
262331 {
263332 MemoryAddress . ThrowIfDefault ( chunk ) ;
333+ MemoryAddress . ThrowIfDefault ( componentOffsets ) ;
264334 ThrowIfIndexIsOutOfRange ( index ) ;
265335 ThrowIfComponentTypeIsMissing ( componentType ) ;
266336
267- int componentOffset = ( int ) chunk ->schema . schema ->componentOffsets [ ( uint ) componentType ] ;
268- return ref chunk ->components [ index ] . Read < T > ( componentOffset ) ;
337+ return ref chunk ->components [ index ] . Read < T > ( ( int ) componentOffsets [ ( uint ) componentType ] ) ;
269338 }
270339
271340 /// <inheritdoc/>
@@ -297,12 +366,14 @@ public readonly bool Equals(Chunk other)
297366 /// </summary>
298367 public readonly struct Row
299368 {
300- private readonly Schema schema ;
369+ private readonly uint * componentOffsets ;
370+ private readonly int * componentSizes ;
301371 internal readonly MemoryAddress row ;
302372
303- internal Row ( Schema schema , MemoryAddress row )
373+ internal Row ( uint * componentOffsets , int * componentSizes , MemoryAddress row )
304374 {
305- this . schema = schema ;
375+ this . componentOffsets = componentOffsets ;
376+ this . componentSizes = componentSizes ;
306377 this . row = row ;
307378 }
308379
@@ -311,31 +382,31 @@ internal Row(Schema schema, MemoryAddress row)
311382 /// </summary>
312383 public readonly MemoryAddress GetComponent ( int componentType )
313384 {
314- return new ( row . pointer + schema . schema -> componentOffsets [ ( uint ) componentType ] ) ;
385+ return new ( row . pointer + componentOffsets [ ( uint ) componentType ] ) ;
315386 }
316387
317388 /// <summary>
318389 /// Retrieves the component of type <typeparamref name="T"/>.
319390 /// </summary>
320391 public readonly ref T GetComponent < T > ( int componentType ) where T : unmanaged
321392 {
322- return ref * ( T * ) ( row . pointer + schema . schema -> componentOffsets [ ( uint ) componentType ] ) ;
393+ return ref * ( T * ) ( row . pointer + componentOffsets [ ( uint ) componentType ] ) ;
323394 }
324395
325396 /// <summary>
326397 /// Assigns the component of type <typeparamref name="T"/> to <paramref name="value"/>.
327398 /// </summary>
328399 public readonly void SetComponent < T > ( int componentType , T value ) where T : unmanaged
329400 {
330- * ( T * ) ( row . pointer + schema . schema -> componentOffsets [ ( uint ) componentType ] ) = value ;
401+ * ( T * ) ( row . pointer + componentOffsets [ ( uint ) componentType ] ) = value ;
331402 }
332403
333404 /// <summary>
334405 /// Retrieves all bytes for the given <paramref name="componentType"/>.
335406 /// </summary>
336407 public readonly Span < byte > GetSpan ( int componentType )
337408 {
338- return new Span < byte > ( row . pointer + schema . schema -> componentOffsets [ ( uint ) componentType ] , schema . schema -> sizes [ ( uint ) componentType ] ) ;
409+ return new Span < byte > ( row . pointer + componentOffsets [ ( uint ) componentType ] , componentSizes [ ( uint ) componentType ] ) ;
339410 }
340411 }
341412
0 commit comments