Nebula
Loading...
Searching...
No Matches
tablesignature.h
Go to the documentation of this file.
1#pragma once
2//------------------------------------------------------------------------------
17//------------------------------------------------------------------------------
18#include "ids/id.h"
19#include "util/fixedarray.h"
20#include "attributeid.h"
21
22namespace MemDb
23{
24
26{
27public:
29 TableSignature() : mask(nullptr), size(0) {};
35 TableSignature(std::initializer_list<AttributeId> descriptors);
37 TableSignature(AttributeId const* descriptors, SizeT num);
43 bool const operator==(TableSignature const& rhs) const;
45 bool const IsValid() const { return size > 0; }
47 bool const IsSet(AttributeId component) const;
49 void FlipBit(AttributeId component);
51 void SetBit(AttributeId component);
53 void ClearBit(AttributeId component);
54
56 static bool const CheckBits(TableSignature const& src, TableSignature const& mask);
58 static bool const HasAny(TableSignature const& src, TableSignature const& mask);
59
60protected:
62 void Setup(AttributeId const* descriptors, SizeT num);
63
65 __m128i* mask;
67 uint8_t size;
68};
69
70//------------------------------------------------------------------------------
73inline
75{
76 this->Setup(descriptors.Begin(), descriptors.Size());
77}
78
79//------------------------------------------------------------------------------
82inline
83TableSignature::TableSignature(std::initializer_list<AttributeId> descriptors)
84{
85 this->Setup(descriptors.begin(), (SizeT)descriptors.size());
86}
87
88//------------------------------------------------------------------------------
91inline
93{
94 this->Setup(descriptors, num);
95}
96
97//------------------------------------------------------------------------------
100inline
101void
102TableSignature::Setup(AttributeId const* componentBuffer, SizeT num)
103{
104 if (num > 0)
105 {
106 Util::Array<AttributeId> descriptors(componentBuffer, num);
107 descriptors.Sort();
108 AttributeId const last = *(descriptors.End() - 1);
109 n_assert(last != AttributeId::Invalid());
110 uint const largestBit = last.id;
111 this->size = (largestBit / 128) + 1;
112 this->mask = (__m128i*)Memory::Alloc(Memory::HeapType::ObjectHeap, this->size * 16);
113
114 for (int i = 0; i < this->size; i++)
115 this->mask[i] = _mm_setzero_si128();
116
117 alignas(16) uint64_t partialMask[2] = { 0, 0 };
118 // offsets start at first values offset
119 uint64_t offset = descriptors[0].id / 128;
120 uint64_t prevOffset = offset;
121 for (AttributeId i : descriptors)
122 {
123 n_assert(i != AttributeId::Invalid());
124 offset = i.id / 128;
125 if (offset != prevOffset)
126 {
127 // Write value and reset partial mask
128 *(this->mask + prevOffset) = _mm_set_epi64x(partialMask[0], partialMask[1]);
129 prevOffset = offset;
130 memset(&partialMask, 0, sizeof(partialMask));
131 }
132 uint32_t mod = (i.id % 128);
133 partialMask[mod / 64] |= 1ull << mod;
134 }
135
136 *(this->mask + offset) = _mm_set_epi64x(partialMask[0], partialMask[1]);
137 }
138 else
139 {
140 this->mask = nullptr;
141 this->size = 0;
142 }
143}
144
145
146//------------------------------------------------------------------------------
149inline
151 size(rhs.size)
152{
153 if (size > 0)
154 {
155 this->mask = (__m128i*)Memory::Alloc(Memory::HeapType::ObjectHeap, this->size * 16);
156 for (int i = 0; i < this->size; i++)
157 this->mask[i] = _mm_load_si128(rhs.mask + i);
158 }
159 else
160 {
161 this->mask = nullptr;
162 }
163};
164
165//------------------------------------------------------------------------------
168inline
170{
171 if (this->mask != nullptr)
172 Memory::Free(Memory::HeapType::ObjectHeap, this->mask);
173}
174
175//------------------------------------------------------------------------------
178inline bool const
180{
181 if (this->size != rhs.size || this->size == 0 || rhs.size == 0)
182 {
183 return false;
184 }
185
186 for (int i = 0; i < this->size; i++)
187 {
188 __m128i temp = _mm_cmpeq_epi32(this->mask[i], rhs.mask[i]);
189 if ((_mm_movemask_epi8(temp) != 0xFFFF))
190 return false;
191 };
192
193 return true;
194}
195
196//------------------------------------------------------------------------------
199inline bool const
201{
202 int offset = component.id / 128;
203 if (offset < this->size)
204 {
205 alignas(16) uint64_t partialMask[2] = { 0, 0 };
206 uint64_t const bit = component.id % 128;
207 partialMask[bit / 64] |= 1ull << bit;
208 __m128i temp = _mm_set_epi64x(partialMask[0], partialMask[1]);
209 int const isSet = !_mm_testz_si128(temp, this->mask[offset]);
210 return isSet;
211 }
212
213 return false;
214}
215
216//------------------------------------------------------------------------------
219inline void
221{
222 int offset = component.id / 128;
223 n_assert(offset < this->size); // currently, we can't flip a bit that is outside the signatures size.
224 alignas(16) uint64_t partialMask[2] = { 0, 0 };
225 uint64_t bit = component.id % 128;
226 partialMask[bit / 64] |= 1ull << bit;
227 __m128i temp = _mm_set_epi64x(partialMask[0], partialMask[1]);
228 this->mask[offset] = _mm_xor_si128(this->mask[offset], temp);
229}
230
231//------------------------------------------------------------------------------
234inline void
236{
237 int offset = component.id / 128;
238 if (offset >= this->size)
239 {
240 uint8_t newSize = offset + 1;
241 __m128i* newMask = (__m128i*)Memory::Alloc(Memory::HeapType::ObjectHeap, newSize * 16);
242 if (this->mask != nullptr)
243 {
244 for (int i = 0; i < this->size; i++)
245 newMask[i] = _mm_load_si128(this->mask + i);
246
247 Memory::Free(Memory::HeapType::ObjectHeap, this->mask);
248 }
249 this->mask = newMask;
250 this->size = newSize;
251 }
252 alignas(16) uint64_t partialMask[2] = {0, 0};
253 uint64_t bit = component.id % 128;
254 partialMask[bit / 64] |= 1ull << bit;
255 __m128i temp = _mm_set_epi64x(partialMask[0], partialMask[1]);
256 this->mask[offset] = _mm_or_si128(this->mask[offset], temp);
257}
258
259//------------------------------------------------------------------------------
262inline void
264{
265 int offset = component.id / 128;
266 n_assert(offset < this->size); // currently, we can't set a bit that is outside the signatures size.
267 alignas(16) uint64_t partialMask[2] = {0, 0};
268 uint64_t bit = component.id % 128;
269 partialMask[bit / 64] |= 1ull << bit;
270 __m128i temp = _mm_set_epi64x(partialMask[0], partialMask[1]);
271 this->mask[offset] = _mm_andnot_si128(temp, this->mask[offset]);
272}
273
274//------------------------------------------------------------------------------
277inline TableSignature&
279{
280 this->size = rhs.size;
281 if (this->size > 0)
282 {
283 this->mask = (__m128i*)Memory::Alloc(Memory::HeapType::ObjectHeap, this->size * 16);
284 for (int i = 0; i < this->size; i++)
285 this->mask[i] = _mm_load_si128(rhs.mask + i);
286 }
287 else
288 {
289 this->mask = nullptr;
290 }
291 return *this;
292}
293
294//------------------------------------------------------------------------------
299inline bool const
301{
302 if (src.size == 0 || mask.size == 0)
303 return false;
304
305#ifdef NEBULA_DEBUG
306 {
307 // validation
308 __m128i cmp = _mm_cmpeq_epi32(mask.mask[mask.size - 1], _mm_setzero_si128());
309 n_assert(_mm_movemask_epi8(cmp) != 0xFFFF);
310 }
311#endif
312
313 if (mask.size > src.size)
314 {
315 return false;
316 }
317
318 for (int i = 0; i < mask.size; i++)
319 {
320 __m128i temp = _mm_and_si128(src.mask[i], mask.mask[i]);
321 __m128i cmp = _mm_cmpeq_epi32(temp, mask.mask[i]);
322 if ((_mm_movemask_epi8(cmp) != 0xFFFF))
323 return false;
324 };
325
326 return true;
327}
328
329//------------------------------------------------------------------------------
334inline bool const
336{
337 if (src.size == 0 || mask.size == 0)
338 return false;
339
340#ifdef NEBULA_DEBUG
341 {
342 // validation
343 __m128i cmp = _mm_cmpeq_epi32(mask.mask[mask.size - 1], _mm_setzero_si128());
344 n_assert(_mm_movemask_epi8(cmp) != 0xFFFF);
345 }
346#endif
347
348 const int size = Math::min(mask.size, src.size);
349
350 for (int i = 0; i < size; i++)
351 {
352 __m128i temp = _mm_and_si128(src.mask[i], mask.mask[i]);
353 __m128i cmp = _mm_cmpeq_epi32(temp, _mm_setzero_si128());
354 if ((_mm_movemask_epi8(cmp) == 0xFFFF))
355 return false;
356 };
357
358 return true;
359}
360
361} // namespace MemDb
Basically a bitfield with packed ComponentIds.
Definition tablesignature.h:26
static bool const CheckBits(TableSignature const &src, TableSignature const &mask)
(src & mask) == mask
Definition tablesignature.h:300
bool const operator==(TableSignature const &rhs) const
equality operator
Definition tablesignature.h:179
void FlipBit(AttributeId component)
flip a bit.
Definition tablesignature.h:220
TableSignature & operator=(TableSignature const &rhs)
assignment operator
Definition tablesignature.h:278
uint8_t size
number of SSE regs allocated
Definition tablesignature.h:67
TableSignature()
default constructor.
Definition tablesignature.h:29
~TableSignature()
destructor
Definition tablesignature.h:169
bool const IsValid() const
check if signature is valid
Definition tablesignature.h:45
void SetBit(AttributeId component)
set a bit.
Definition tablesignature.h:235
__m128i * mask
large bit field, using SSE registers
Definition tablesignature.h:65
bool const IsSet(AttributeId component) const
check if a single bit is set
Definition tablesignature.h:200
void Setup(AttributeId const *descriptors, SizeT num)
create bitfield from fixed array.
Definition tablesignature.h:102
void ClearBit(AttributeId component)
clear a bit.
Definition tablesignature.h:263
static bool const HasAny(TableSignature const &src, TableSignature const &mask)
check if src has any of the bits in mask set ((src & mask) == 0)
Definition tablesignature.h:335
Nebula's dynamic array class.
Definition array.h:60
Iterator End() const
return iterator to end of array
Definition array.h:1265
void Sort()
sort the array
Definition array.h:1434
Implements a fixed size one-dimensional array.
Definition fixedarray.h:20
Iterator Begin() const
get iterator to first element
Definition fixedarray.h:598
const SizeT Size() const
get number of elements
Definition fixedarray.h:532
#define n_assert(exp)
Definition debug.h:50
__forceinline TYPE min(TYPE a, TYPE b)
Definition scalar.h:390
Attribute.
Definition attribute.h:26
void * Alloc(HeapType heapType, size_t size, size_t alignment)
Allocate a block of memory from one of the global heaps.
Definition osxmemory.cc:56
void Free(HeapType heapType, void *ptr)
Free a block of memory.
Definition osxmemory.cc:136
Definition attributeid.h:19
int SizeT
Definition types.h:49
unsigned int uint
Definition types.h:31