-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathType.h
921 lines (730 loc) · 35.3 KB
/
Type.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
#pragma once
#include "List.h"
#include "SpvDefines.h"
#include "FNV1aHasher.h"
namespace spvgentwo
{
// forward decls
class IAllocator;
#pragma region decls
// opaque types
struct event_t {};
struct device_event_t {};
struct reserve_id_t {};
struct queue_t {};
struct pipe_t {};
struct pipe_storage_t {};
struct named_barrier_t {};
struct sampler_t {};
struct ray_query_khr_t {};
struct acceleration_structure_khr_t {};
struct dyn_scalar_t
{
struct dyntype_desc_tag {};
spv::Op baseType = spv::Op::OpTypeFloat; // OpTypeInt or OpTypeFloat
unsigned int bits = 32u; // bit width of int / float
bool sign = false; // integer sign
};
constexpr dyn_scalar_t DynScalarVoid = { spv::Op::OpTypeVoid, 0u, false };
constexpr dyn_scalar_t DynScalarF32 = { spv::Op::OpTypeFloat, 32u, false };
struct dyn_image_t
{
struct dyntype_desc_tag {};
dyn_scalar_t sampledType{ DynScalarF32 };
spv::Dim dimension = spv::Dim::Dim2D;
unsigned int depth = 1u;
bool array = false;
bool multiSampled = false;
SamplerImageAccess samplerAccess = SamplerImageAccess::Unknown;
spv::ImageFormat format = spv::ImageFormat::Unknown;
spv::AccessQualifier accessQualifier = spv::AccessQualifier::Max;
};
struct dyn_sampled_image_t { dyn_image_t imageType{}; struct dyntype_desc_tag {}; };
struct dyn_vector_t { dyn_scalar_t elementType{}; unsigned int elements{}; struct dyntype_desc_tag {}; };
struct dyn_matrix_t { dyn_vector_t columnType{}; unsigned int columns{}; /*length of the row*/ struct dyntype_desc_tag {}; };
template<class T, unsigned int N>
struct array_t {
using array_element_type = T;
static constexpr unsigned int Elements = N;
};
template<class T, unsigned int N>
struct vector_t {
using vec_element_type = T;
static constexpr unsigned int Elements = N;
};
template<class T, unsigned int _Columns, unsigned int _Rows>
struct matrix_t {
using mat_column_type = vector_t<T, _Rows>;
using mat_row_type = vector_t<T, _Columns>;
static constexpr unsigned int Columns = _Columns;
static constexpr unsigned int Rows = _Rows;
};
#pragma endregion
class Type
{
public:
using Iterator = List<Type>::Iterator;
constexpr Type(IAllocator* _pAllocator = nullptr, spv::Op _type = spv::Op::OpTypeVoid);
Type(IAllocator* _pAllocator, const Type& _subType, spv::Op _baseType = spv::Op::OpTypeVoid);
Type(IAllocator* _pAllocator, Type&& _subType, spv::Op _baseType = spv::Op::OpTypeVoid);
Type(Type&& _other) noexcept;
Type(const Type& _other);
~Type();
Type& operator=(Type&& _other) noexcept;
Type& operator=(const Type& _other);
bool operator==(const Type& _other) const;
bool operator!=(const Type& _other) const { return !operator==(_other); }
bool operator==(spv::Op _type) const { return m_Type == _type; }
bool operator!=(spv::Op _type) const { return m_Type != _type; }
void reset();
constexpr spv::Op getType() const { return m_Type; }
void setType(const spv::Op _type) { if(spv::IsTypeOp(_type)) m_Type = _type; }
// get inner most subtype
constexpr const Type& getBaseType() const;
constexpr Type& getBaseType();
// fundamentals only
const char* getString() const;
constexpr spv::Op getBaseTypeOp() const { return getBaseType().m_Type; }
constexpr bool isBaseTypeOf(spv::Op _type) const { return getBaseType().getType() == _type; }
constexpr bool hasSameBase(const Type& _other, bool _onlyCheckTypeOp = false) const;
// checks if this, or any subtype equals _sub/_type
bool containsType(const Type& _sub) const;
bool containsType(spv::Op _type) const;
// dimension, bits, elements
constexpr unsigned int getIntWidth() const { return m_IntWidth; }
void setIntWidth(unsigned int _width) { m_IntWidth = _width; }
constexpr unsigned int getFloatWidth() const { return m_FloatWidth; }
void setFloatWidth(unsigned int _width) { m_FloatWidth = _width; }
constexpr unsigned int getImageDepth() const { return m_ImgDepth; }
void setImageDepth(unsigned int _depth) { m_ImgDepth = _depth; }
constexpr bool getIntSign() const { return m_IntSign; }
void setIntSign(bool _sign) { m_IntSign = _sign; }
constexpr spv::Dim getImageDimension() const { return m_ImgDimension; }
void setImageDimension(spv::Dim _dim) { m_ImgDimension = _dim; }
constexpr bool getImageArray() const { return m_ImgArray; }
void setImageArray(bool _array) { m_ImgArray = _array; }
constexpr bool getImageMultiSampled() const { return m_ImgMultiSampled; }
void setImageMultiSampled(bool _ms) { m_ImgMultiSampled = _ms; }
constexpr SamplerImageAccess getImageSamplerAccess() const { return m_ImgSamplerAccess; }
void setImageSamplerAccess(SamplerImageAccess _access) { m_ImgSamplerAccess = _access; }
constexpr spv::ImageFormat getImageFormat() const { return m_ImgFormat; }
void setImageFormat(spv::ImageFormat _format) { m_ImgFormat = _format; }
constexpr unsigned int getVectorComponentCount() const { return m_VecComponentCount; }
void setVectorComponentCount(unsigned int _count) { m_VecComponentCount = _count; }
constexpr unsigned int getMatrixColumnCount() const { return m_MatColumnCount; }
void setMatrixColumnCount(unsigned int _count) { m_MatColumnCount = _count; }
unsigned int getMatrixRowCount() const { return isMatrix() ? front().getVectorComponentCount() : 0u; }
void getMatrixRowCount(unsigned int _rows) { if(isMatrix()) front().setVectorComponentCount(_rows); }
constexpr unsigned int getArrayLength() const { return m_ArrayLength; }
void setArrayLength(unsigned int _legnth) { m_ArrayLength = _legnth;}
constexpr spv::StorageClass getStorageClass() const { return m_StorageClass; }
void setStorageClass(spv::StorageClass _storageClass) { m_StorageClass = _storageClass; }
constexpr spv::AccessQualifier getAccessQualifier() const { return m_AccessQualifier; }
void setAccessQualifier(spv::AccessQualifier _access) { m_AccessQualifier = _access; }
constexpr const List<Type>& getSubTypes() const { return m_subTypes; }
constexpr List<Type>& getSubTypes() { return m_subTypes; }
// return new subtype, if _pSubType is not nullptr, returned member type is a copy of _pSubType
Type& Member(const Type* _pSubType = nullptr);
// return new subtype, if _pSubType is not nullptr, returns this structure
Type& MemberM(const Type* _pSubType = nullptr) { Member(_pSubType); return *this; }
// makes this a void type
Type& Void();
// adds a new member of type void but returns this structure
Type& VoidM() { Member().Void(); return *this; }
Type& Bool();
Type& BoolM() { Member().Bool(); return *this; }
Type& Int(unsigned int _bits = 32u, bool _sign = true);
Type& IntM(unsigned int _bits = 32u, bool _sign = true) { Member().Int(_bits, _sign); return *this; }
Type& UInt(unsigned int _bits = 32u) { return Int(_bits, false); }
Type& UIntM(unsigned int _bits = 32u) { return IntM(_bits, false); }
Type& Float(unsigned int _bits = 32u);
Type& FloatM(unsigned int _bits = 32u) { Member().Float(_bits); return *this; }
Type& Double() { return Float(64u); };
Type& DoubleM() { Member().Float(64u); return *this; }
Type& Scalar(spv::Op _base, unsigned int _bits, bool _sign);
Type& Scalar(const dyn_scalar_t& _scalarType);
// makes this a struct
Type& Struct(const Type* _pSubType = nullptr);
// make this a struct with _firstMember and _memberTypes as subtypes, returns this sturcture
template <class ...Types>
Type& Struct(const Type& _firstMember, const Types& ... _memberTypes);
// makes this an array
Type& Array(unsigned int _elements = 0u, const Type* _elementType = nullptr);
// add new member of type run-time array, returns this structure
Type& ArrayM(unsigned int _elements = 0u, const Type* _elementType = nullptr) { Member().Array(_elements, _elementType); return *this; }
// makes this an array, returns element type
Type& ArrayElement(unsigned int _elements) { Array(_elements); return Member(); }
// makes this an run-time
Type& RuntimeArray(const Type* _elementType = nullptr);
// add new member of type run-time array, returns this structure
Type& RuntimeArrayM(const Type* _elementType = nullptr) { Member().RuntimeArray(_elementType); return *this; }
// makes this an run-time array, returns element type
Type& RuntimeArrayElement() { RuntimeArray(); return Member(); }
// makes this a function
Type& Function();
// make this a pointer
Type& Pointer(spv::StorageClass _storageClass = spv::StorageClass::Generic, const Type* _innerType = nullptr);
Type& ForwardPointer(spv::StorageClass _storageClass = spv::StorageClass::Generic, const Type* _innerType = nullptr);
Type& Sampler();
Type& Image(
dyn_scalar_t _sampledType = {spv::Op::OpTypeFloat},
spv::Dim _dim = spv::Dim::Dim2D,
unsigned int _depth = 1u,
bool _array = false,
bool _multiSampled = false,
SamplerImageAccess _sampled = SamplerImageAccess::Unknown,
spv::ImageFormat _format = spv::ImageFormat::Unknown,
spv::AccessQualifier _access = spv::AccessQualifier::Max);
Type& Image(const dyn_image_t& _imageType);
Type& SampledImage(const Type* _imageType = nullptr);
Type& SampledImage(const dyn_image_t& _imageType);
Type& SampledImage(const dyn_sampled_image_t& _sampledImageType) { return SampledImage(_sampledImageType.imageType); }
Type& Event();
Type& DeviceEvent();
Type& ReserveId();
Type& Queue();
Type& Pipe();
Type& PipeStorage();
Type& NamedBarrier();
Type& Vector(unsigned int _elements = 0u, const Type* _elementType = nullptr);
Type& VectorM(unsigned int _elements = 0u, const Type* _elementType = nullptr) { Member().Vector(_elements, _elementType); return *this; }
Type& Vector(const dyn_vector_t& _vectorType);
// makes this a vector type, returns element type
Type& VectorElement(unsigned int _elements) { Vector(_elements); return Member(); }
Type& Matrix(unsigned int _columns = 0, const Type* _columnType = nullptr);
Type& Matrix(const dyn_matrix_t& _matrixType);
Type& Matrix(unsigned int _columns, unsigned int _rows, const Type* _componentType);
// makes this a matrix type, returns column vector type
Type& MatrixColumn(unsigned int _columns) { Matrix(_columns); return Member().Vector(); }
Type& RayQueryKHR();
Type& AccelerationStructureKHR();
// form a vector or scalar type from ImageFormat, one channel per vector component
// packed formats like R11fG11fB10f and Rgb10A2 etc are not supported and the result type will be void
// _NormAsFloat interprets signed normalized component formats as floats instead of integers
Type& fromImageFormat(spv::ImageFormat _format, bool _normAsFloat);
constexpr Iterator begin() const { return m_subTypes.begin(); }
constexpr Iterator end() const { return m_subTypes.end(); }
constexpr Type& front() { return m_subTypes.front(); }
constexpr const Type& front() const { return m_subTypes.front(); }
constexpr Type& back() { return m_subTypes.back(); }
constexpr const Type& back() const { return m_subTypes.back(); }
template <class T>
Type& fundamental([[maybe_unused]] const T* _typeInfo = nullptr) { /*static_assert(false, "incompatible type"); GCC doesnt like this*/ return *this; }
template <class T, class ... Props>
Type& make(const Props& ... _props);
// set Properties by type: spv::Dim -> image Dimension etc
template <class Prop, class ...Props>
void setProperties(const Prop& _first, const Props& ... _props);
constexpr bool isVoid() const { return m_Type == spv::Op::OpTypeVoid; }
constexpr bool isBool() const { return m_Type == spv::Op::OpTypeBool; }
constexpr bool isPointer() const { return m_Type == spv::Op::OpTypePointer; }
constexpr bool isPointer(spv::StorageClass _storageClass) const { return isPointer() && m_StorageClass == _storageClass; }
constexpr bool isForwardPointer() const { return m_Type == spv::Op::OpTypeForwardPointer; }
constexpr bool isForwardPointer(spv::StorageClass _storageClass) const { return isForwardPointer() && m_StorageClass == _storageClass; }
constexpr bool isStruct() const { return m_Type == spv::Op::OpTypeStruct; }
constexpr bool isArray() const { return m_Type == spv::Op::OpTypeArray; }
constexpr bool isRuntimeArray() const { return m_Type == spv::Op::OpTypeRuntimeArray; }
constexpr bool isImage() const { return m_Type == spv::Op::OpTypeImage; }
constexpr bool isSampler() const { return m_Type == spv::Op::OpTypeSampler; }
constexpr bool isSampledImage() const { return m_Type == spv::Op::OpTypeSampledImage; }
constexpr bool isVector() const { return m_Type == spv::Op::OpTypeVector; }
constexpr bool isMatrix() const { return m_Type == spv::Op::OpTypeMatrix; }
constexpr bool isInt(unsigned int _bitWidth = 0u, Sign _sign = Sign::Any) const { return m_Type == spv::Op::OpTypeInt && (_bitWidth == 0u || _bitWidth == m_IntWidth) && hasSign(_sign); }
constexpr bool isUInt(unsigned int _bitWidth = 0u) const { return isInt(_bitWidth) && m_IntSign == false; }
constexpr bool isSInt(unsigned int _bitWidth = 0u) const { return isInt(_bitWidth) && m_IntSign; }
constexpr bool isI8() const { return isInt(8u); }
constexpr bool isU8() const { return isUInt(8u); }
constexpr bool isS8() const { return isSInt(8u); }
constexpr bool isI16() const { return isInt(16u); }
constexpr bool isU16() const { return isUInt(16u); }
constexpr bool isS16() const { return isSInt(16u); }
constexpr bool isI32() const { return isInt(32u); }
constexpr bool isU32() const { return isUInt(32u); }
constexpr bool isS32() const { return isSInt(32u); }
constexpr bool isI64() const { return isInt(64u); }
constexpr bool isU64() const { return isUInt(64u); }
constexpr bool isS64() const { return isSInt(64u); }
constexpr bool isFloat(unsigned int _bitWidth = 0u) const { return m_Type == spv::Op::OpTypeFloat && (_bitWidth == 0u || _bitWidth == m_FloatWidth); }
constexpr bool isF16() const { return m_Type == spv::Op::OpTypeFloat && m_FloatWidth == 16u; }
constexpr bool isF32() const { return m_Type == spv::Op::OpTypeFloat && m_FloatWidth == 32u; }
constexpr bool isF64() const { return m_Type == spv::Op::OpTypeFloat && m_FloatWidth == 64u; }
constexpr bool isNumerial() const { return isInt() || isFloat(); }
constexpr bool isScalar() const { return isNumerial() || isBool(); }
constexpr bool isAggregate() const { return isStruct() || isArray(); }
constexpr bool isComposite() const { return isAggregate() || isMatrix() || isVector(); }
// check if this type has same sign as _sign
constexpr bool hasSign(Sign _sign) const { return _sign == Sign::Any || ((_sign == Sign::Signed) == getBaseType().isSInt()); }
constexpr void setSign(bool _signum) { getBaseType().m_IntSign = _signum; }
// check for base sign of int
constexpr bool isSigned() const { return getBaseType().isSInt(); }
constexpr bool isUnsigned() const { return getBaseType().isUInt(); }
constexpr bool isOpaque() const { return m_Type == spv::Op::OpTypeOpaque; }
constexpr bool isFunction() const { return m_Type == spv::Op::OpTypeFunction; }
constexpr bool isEvent() const { return m_Type == spv::Op::OpTypeEvent; }
constexpr bool isDeviceEvent() const { return m_Type == spv::Op::OpTypeDeviceEvent; }
constexpr bool isReservedId() const { return m_Type == spv::Op::OpTypeReserveId; }
constexpr bool isPipe() const { return m_Type == spv::Op::OpTypePipe; }
constexpr bool isPipeStorage() const { return m_Type == spv::Op::OpTypePipeStorage; }
constexpr bool isQueue() const { return m_Type == spv::Op::OpTypeQueue; }
constexpr bool isRayQueryKHR() const { return m_Type == spv::Op::OpTypeRayQueryKHR; }
constexpr bool isAccelerationStructure() const { return m_Type == spv::Op::OpTypeAccelerationStructureKHR; }
constexpr bool isVectorOf(spv::Op _type, unsigned int _length = 0u, unsigned int _componentWidth = 0u, Sign _sign = Sign::Any) const { return isVector() && front().getType() == _type && (_length == 0u || m_VecComponentCount == _length) && (_componentWidth == 0u || front().getIntWidth() == _componentWidth) && front().hasSign(_sign); }
// does not check for component type
constexpr bool isVectorOfLength(unsigned int _length, unsigned int _componentWidth = 0u, Sign _sign = Sign::Any) const { return isVector() && front().hasSign(_sign) && (_length == 0u || m_VecComponentCount == _length) && (_componentWidth == 0u || front().getIntWidth() == _componentWidth); }
constexpr bool isVectorOfInt(unsigned int _length = 0u, unsigned int _componentWidth = 0u, Sign _sign = Sign::Any) const { return isVectorOfLength(_length, _componentWidth, _sign) && front().isInt(); }
constexpr bool isVectorOfSInt(unsigned int _length = 0u, unsigned int _componentWidth = 0u) const { return isVectorOfInt(_length, _componentWidth, Sign::Signed); }
constexpr bool isVectorOfUInt(unsigned int _length = 0u, unsigned int _componentWidth = 0u) const { return isVectorOfInt(_length, _componentWidth, Sign::Unsigned); }
constexpr bool isVectorOfFloat(unsigned int _length = 0u, unsigned int _componentWidth = 0u) const { return isVectorOfLength(_length, _componentWidth) && front().isFloat(); }
constexpr bool isVectorOfBool(unsigned int _length = 0u) const { return isVectorOfLength(_length) && front().isBool(); }
constexpr bool isScalarOrVectorOf(spv::Op _type, unsigned int _length = 0u, unsigned int _componentWidth = 0u, Sign _sign = Sign::Any) const { return (m_Type == _type && (_componentWidth == 0u || m_IntWidth == _componentWidth) && hasSign(_sign)) || isVectorOf(_type, _length, _componentWidth, _sign); }
constexpr bool isNumericalScalarOrVector(unsigned int _length = 0u, unsigned int _componentWidth = 0u, Sign _sign = Sign::Any) const { return (isNumerial() && (_componentWidth == 0u || m_IntWidth == _componentWidth) && hasSign(_sign)) || (isVectorOfLength(_length, _componentWidth, _sign) && front().isNumerial()); }
constexpr bool hasSameVectorLength(const Type& _other) const { return isVector() && _other.isVector() && m_VecComponentCount == _other.m_VecComponentCount; }
constexpr bool hasSameVectorLength(const Type& _other, const spv::Op _componentType) const { return isVectorOf(_componentType) && _other.isVectorOf(_componentType) && m_VecComponentCount == _other.m_VecComponentCount; }
constexpr bool isScalarOrVectorOfSameLength(const Type& _other, bool _sameComponentWidth = true) const { return (!_sameComponentWidth || getBaseType().getIntWidth() == _other.getBaseType().getIntWidth()) && (hasSameVectorLength(_other) || (isScalar() && _other.isScalar())); }
constexpr bool isScalarOrVectorOfSameLength(spv::Op _type, const Type& _other, bool _sameComponentWidth = true) const { return (!_sameComponentWidth || getBaseType().getIntWidth() == _other.getBaseType().getIntWidth()) && (hasSameVectorLength(_other, _type) || (m_Type == _type && _other.m_Type == _type && isScalar() && _other.isScalar())); }
constexpr bool hasSameComponentWidth(const Type& _other) const { const Type& a = getBaseType(); const Type& b = _other.getBaseType(); return a.isNumerial() && b.isNumerial() && a.getIntWidth() == b.getIntWidth(); }
constexpr bool isMatrixOf(spv::Op _baseType, unsigned int _columns = 0u, unsigned int _rows = 0u, unsigned int _componentWidth = 0u, Sign _sign = Sign::Any) const { return isMatrix() && getBaseTypeOp() == _baseType && (_columns == 0u || (getMatrixColumnCount() == _columns)) && (_rows == 0u || (front().getVectorComponentCount() == _rows)) && (_componentWidth == 0u || getBaseType().getFloatWidth() == _componentWidth) && getBaseType().hasSign(_sign); }
constexpr bool isMatrixOfFloat(unsigned int _columns = 0u, unsigned int _rows = 0u, unsigned int _componentWidth = 0u) const { return isMatrixOf(spv::Op::OpTypeFloat, _columns, _rows, _componentWidth); }
constexpr bool isMatrixOfInt(unsigned int _columns = 0u, unsigned int _rows = 0u, unsigned int _componentWidth = 0u, const Sign _sign = Sign::Any) const { return isMatrixOf(spv::Op::OpTypeInt, _columns, _rows, _componentWidth, _sign); }
constexpr bool isSqareMatrix() const { return isMatrix() && m_MatColumnCount == front().getVectorComponentCount(); }
constexpr bool isSqareMatrixOf(spv::Op _baseType) const { return isMatrixOf(_baseType) && m_MatColumnCount == front().getVectorComponentCount(); }
// return 1 if type is a scalar, return component count if type is vector, 0 otherwise
constexpr unsigned int getScalarOrVectorLength() const { return isScalar() ? 1u : isVector() ? getVectorComponentCount() : 0u; }
// depth first traversal of type hierarchy using integer indices (static variant), returns the iterator of the last valid type accessed by index
template<class... Indices>
Iterator getSubType(unsigned int _i, Indices... _indices) const;
// depth first traversal of type hierarchy using integer indices (dynamic variant), returns the iterator of the last valid type accessed by index
Iterator getSubType(const List<unsigned int>& _indices) const;
// creates a new empty type from this types allocator
Type New() const;
// wraps a copy of this type in a new type of _baseType
Type wrap(spv::Op _baseType) const;
// moves this into wrap type of _baseType
Type moveWrap(spv::Op _baseType);
// wraps a copy of this into a new pointer of this type
Type wrapPointer(spv::StorageClass _storageClass = spv::StorageClass::Generic) const;
// wraps a copy of this into a new vector of _elements
Type wrapVector(unsigned int _elements) const;
// wraps a copy of this column type into a matrix of _columns
Type wrapMatrix(unsigned int _columns) const;
// wraps a copy of this into a new array of _elements
Type wrapArray(unsigned int _elements) const;
// wraps this type into a new struct
Type wrapStruct() const;
private:
spv::Op m_Type = spv::Op::OpTypeVoid; // base type
union
{
unsigned int m_ImgDepth = 0u;
unsigned int m_FloatWidth;
unsigned int m_IntWidth;
unsigned int m_VecComponentCount;
unsigned int m_MatColumnCount;
unsigned int m_ArrayLength;
};
bool m_IntSign = false;
// for OpTypePointer
spv::StorageClass m_StorageClass = spv::StorageClass::Generic;
// image
spv::Dim m_ImgDimension = spv::Dim::Max;
bool m_ImgArray = false;
bool m_ImgMultiSampled = false;
SamplerImageAccess m_ImgSamplerAccess = SamplerImageAccess::Unknown;
spv::ImageFormat m_ImgFormat = spv::ImageFormat::Unknown;
// image and pipe
spv::AccessQualifier m_AccessQualifier = spv::AccessQualifier::Max;
List<Type> m_subTypes;
};
inline constexpr Type::Type(IAllocator* _pAllocator, spv::Op _type) :
m_Type(_type),
m_subTypes(_pAllocator)
{
}
inline constexpr const Type& Type::getBaseType() const
{
if (m_subTypes.empty())
{
return *this;
}
return front().getBaseType();
}
inline constexpr Type& Type::getBaseType()
{
if (m_subTypes.empty())
{
return *this;
}
return front().getBaseType();
}
inline constexpr bool Type::hasSameBase(const Type& _other, bool _onlyCheckTyeOp) const
{
const Type& lBase = getBaseType();
const Type& rBase = _other.getBaseType();
return _onlyCheckTyeOp ? lBase.m_Type == rBase.m_Type : lBase == rBase;
}
// more decls
struct dyn_array_t { Type elementType; unsigned int length; struct dyntype_desc_tag {};};
struct dyn_runtime_array_t { Type elementType; struct dyntype_desc_tag {};};
//template <class S, class T = stdrep::remove_cv_t<stdrep::remove_reference_t<S>>>
template<class, class = stdrep::void_t<> >
struct is_dyntype_desc : stdrep::false_type { };
template<class T>
struct is_dyntype_desc<T, stdrep::void_t<typename T::dyntype_desc_tag>> : stdrep::true_type { };
template <class T>
constexpr bool is_dyntype_desc_v = is_dyntype_desc<traits::remove_cvref_ptr_t<T>>::value;
template<class, class = stdrep::void_t<>>
struct is_array : stdrep::false_type {};
template<class T>
struct is_array<T, stdrep::void_t<typename T::array_element_type>> : stdrep::true_type {};
template<class T>
constexpr bool is_array_v = is_array<T>::value;
template<class, class = stdrep::void_t<>>
struct is_vector: stdrep::false_type {};
template<class T>
struct is_vector<T, stdrep::void_t<typename T::vec_element_type>> : stdrep::true_type {};
template<class T>
constexpr bool is_vector_v = is_vector<T>::value;
template<class, class = stdrep::void_t<>>
struct is_matrix : stdrep::false_type{};
template<class T>
struct is_matrix<T, stdrep::void_t<typename T::mat_column_type>> : stdrep::true_type {};
template<class T>
constexpr bool is_matrix_v = is_matrix<T>::value;
#pragma region const_types
template <class T>
struct const_null_t
{
using const_null_type = T;
};
template<class, class = stdrep::void_t<>>
struct is_const_null : stdrep::false_type {};
template<class T>
struct is_const_null<T, stdrep::void_t<typename T::const_null_type>> : stdrep::true_type {};
template<class T>
constexpr bool is_const_null_v = is_const_null<T>::value;
struct const_sampler_t
{
using const_sampler_type = sampler_t;
spv::SamplerAddressingMode addressMode = spv::SamplerAddressingMode::None;
ConstantSamplerCoordMode coordMode = ConstantSamplerCoordMode::UnNormalized;
spv::SamplerFilterMode filterMode = spv::SamplerFilterMode::Nearest;
};
template<class, class = stdrep::void_t<>>
struct is_const_sampler : stdrep::false_type {};
template<class T>
struct is_const_sampler<T, stdrep::void_t<typename T::const_sampler_type>> : stdrep::true_type {};
template<class T>
constexpr bool is_const_sampler_v = is_const_sampler<T>::value;
template <class T, unsigned int N>
struct const_vector_t
{
using const_vector_type = vector_t<T, N>;
using element_type = T;
static constexpr unsigned int Elements = N;
T data[N]{};
};
template<class, class = stdrep::void_t<>>
struct is_const_vector : stdrep::false_type {};
template<class T>
struct is_const_vector<T, stdrep::void_t<typename T::const_vector_type>> : stdrep::true_type {};
template<class T>
constexpr bool is_const_vector_v = is_const_vector<T>::value;
template <class T, class ...Elems>
auto make_vector(T&& first, T&& second, Elems&& ... _elements) {
return const_vector_t<traits::remove_cvref_t<T>, 2 + sizeof...(_elements)>{stdrep::forward<T>(first), stdrep::forward<T>(second), stdrep::forward<Elems>(_elements)...};
}
template <class T, unsigned int N>
auto make_vector(const T (&val)[N]) {
const_vector_t<traits::remove_cvref_t<T>, N> v;
for (auto i = 0u; i < N; ++i)
{
v.data[i] = val[i];
}
return v;
}
template <class T, unsigned int _Columns, unsigned int _Rows>
struct const_matrix_t
{
using const_matrix_type = matrix_t<T, _Columns, _Rows>;
using element_type = T;
static constexpr unsigned int Columns = _Columns;
static constexpr unsigned int Rows = _Rows;
const_vector_t<T, Rows> data[Columns]{}; // columns
};
template<class, class = stdrep::void_t<>>
struct is_const_matrix : stdrep::false_type {};
template<class T>
struct is_const_matrix<T, stdrep::void_t<typename T::const_matrix_type>> : stdrep::true_type {};
template<class T>
constexpr bool is_const_matrix_v = is_const_matrix<T>::value;
template <class T, unsigned int Rows, class ...Columns>
auto make_matrix(const_vector_t<T, Rows> col0, Columns ... _columns) {
return const_matrix_t<traits::remove_cvref_t<T>, 1 + sizeof...(_columns), Rows>{col0, _columns...};
}
template <class T, unsigned int Columns, unsigned int Rows>
auto make_matrix(const T(&val)[Columns][Rows]) {
const_matrix_t<traits::remove_cvref_t<T>, Columns, Rows> m;
for (auto c = 0u; c < Columns; ++c)
{
for (auto r = 0u; r < Rows; ++r)
{
m.data[c].data[r] = val[c][r];
}
}
return m;
}
template <class T, unsigned int N>
struct const_array_t
{
using const_array_type = array_t<T, N>;
using element_type = T;
static constexpr unsigned int Elements = N;
T data[N]{};
};
template<class, class = stdrep::void_t<>>
struct is_const_array : stdrep::false_type {};
template<class T>
struct is_const_array<T, stdrep::void_t<typename T::const_array_type>> : stdrep::true_type {};
template<class T>
constexpr bool is_const_array_v = is_const_array<T>::value;
template <class T, unsigned int N>
auto make_array(const T(&val)[N]) {
const_array_t<traits::remove_cvref_t<T>, N> a;
for (auto i = 0u; i < N; ++i)
{
a.data[i] = val[i];
}
return a;
}
template <class T, class ...Elems>
auto make_array(T&& first, T&& second, Elems&& ... _elements) {
return const_array_t<traits::remove_cvref_t<T>, 2 + sizeof...(_elements)>{stdrep::forward<T>(first), stdrep::forward<T>(second), stdrep::forward<Elems>(_elements)...};
}
#pragma endregion
template <>
struct Hasher<Type>
{
constexpr Hash64 operator()(const Type& _type, Hash64 _seed) const
{
FNV1aHasher h(_seed);
return operator()(_type, h);
}
constexpr Hash64 operator()(const Type& _type, FNV1aHasher& _hasher) const
{
_hasher << _type.getType();
_hasher << _type.getIntWidth(); // image depth, float width
_hasher << _type.getIntSign(); // float sign
_hasher << _type.getStorageClass(); // pointer
_hasher << _type.getImageDimension();
_hasher << _type.getImageArray();
_hasher << _type.getImageMultiSampled();
_hasher << _type.getImageSamplerAccess();
_hasher << _type.getImageFormat();
_hasher << _type.getAccessQualifier();
for (const Type& sub : _type.getSubTypes()) {
operator()(sub, _hasher); // go deeper
}
return _hasher;
}
};
template<class ...Indices>
inline List<Type>::Iterator Type::getSubType(unsigned int _i, Indices ..._indices) const
{
auto it = m_subTypes.begin() + (_i < m_subTypes.size() ? _i : 0u);
if constexpr (sizeof...(_indices) > 0)
{
if (it != nullptr && it->m_subTypes.empty() == false)
{
return it->getSubType(_indices...);
}
}
return it;
}
template<class Prop, class ...Props>
inline void Type::setProperties([[maybe_unused]] const Prop& _first, const Props& ..._props)
{
// check for properties first
if constexpr (stdrep::is_same_v<Prop, spv::StorageClass>)
{
m_StorageClass = _first;
}
if constexpr (stdrep::is_same_v<Prop, spv::Dim>)
{
m_ImgDimension = _first;
}
else if constexpr (stdrep::is_same_v<Prop, spv::Op>)
{
m_Type = _first;
}
else if constexpr (stdrep::is_same_v<Prop, spv::AccessQualifier>)
{
m_AccessQualifier = _first;
}
else if constexpr (stdrep::is_same_v<Prop, SamplerImageAccess>)
{
m_ImgSamplerAccess = _first;
}
else if constexpr (stdrep::is_same_v<Prop, spv::ImageFormat>)
{
m_ImgFormat = _first;
}
else if constexpr (stdrep::is_same_v<Prop, Type>)
{
m_subTypes.emplace_back(_first);
}
if constexpr (sizeof...(_props) > 0)
{
setProperties(_props...);
}
}
template<class ...Types>
inline Type& Type::Struct(const Type& _firstMember, const Types& ..._memberTypes)
{
reset();
m_Type = spv::Op::OpTypeStruct;
m_subTypes.emplace_back(_firstMember);
(m_subTypes.emplace_back(_memberTypes), ...);
return *this;
}
template<class T, class ...Props>
inline Type& Type::make(const Props& ..._props)
{
if constexpr (sizeof...(_props) > 0)
{
setProperties(_props...);
}
// first process types that need to be unwraped (non dynamic composite types)
if constexpr (stdrep::is_pointer_v<T>)
{
using S = stdrep::remove_pointer_t<T>;
if (const S* dyn = traits::selectTypeFromArgs<S>(_props...); dyn != nullptr)
{
Pointer(m_StorageClass).Member().make<S>(*dyn);
}
else
{
Pointer(m_StorageClass).Member().make<S>();
}
}
else if constexpr (is_array_v<T>)
{
Array(T::Elements).Member().template make<typename T::array_element_type>();
}
else if constexpr (is_const_array_v<T>)
{
make<typename T::const_array_type>();
}
else if constexpr (is_vector_v<T>)
{
Vector(T::Elements).Member().template make<typename T::vec_element_type>();
}
else if constexpr (is_const_vector_v<T>)
{
make<typename T::const_vector_type>();
}
else if constexpr(is_matrix_v<T>)
{
Matrix(T::Columns).Member().template make<typename T::mat_column_type>();
}
else if constexpr (is_const_matrix_v<T>)
{
make<typename T::const_matrix_type>();
}
else if constexpr (is_const_sampler_v<T>)
{
make<typename T::const_sampler_type>();
}
else if constexpr (is_const_null_v<T>)
{
make<typename T::const_null_type>();
}
else
{
fundamental<T>(traits::selectTypeFromArgs<T>(_props...));
}
return *this;
}
template <>
inline Type& Type::fundamental<sampler_t>(const sampler_t*) { return Sampler(); }
template <>
inline Type& Type::fundamental<dyn_sampled_image_t>(const dyn_sampled_image_t* _prop)
{
return _prop == nullptr ? SampledImage(nullptr) : SampledImage(*_prop);
}
template <>
inline Type& Type::fundamental<dyn_image_t>(const dyn_image_t* _prop)
{
return _prop == nullptr ? Image() : Image(*_prop);
}
template <>
inline Type& Type::fundamental<event_t>(const event_t*) { return Event(); }
template <>
inline Type& Type::fundamental<device_event_t>(const device_event_t*) { return DeviceEvent(); }
template <>
inline Type& Type::fundamental<reserve_id_t>(const reserve_id_t*) { return ReserveId(); }
template <>
inline Type& Type::fundamental<queue_t>(const queue_t*) { return Queue(); }
template <>
inline Type& Type::fundamental<pipe_t>(const pipe_t*) { return Pipe(); }
template <>
inline Type& Type::fundamental<pipe_storage_t>(const pipe_storage_t*) { return PipeStorage(); }
template <>
inline Type& Type::fundamental<named_barrier_t>(const named_barrier_t*) { return NamedBarrier(); }
template <>
inline Type& Type::fundamental<ray_query_khr_t>(const ray_query_khr_t*) { return RayQueryKHR(); }
template <>
inline Type& Type::fundamental<acceleration_structure_khr_t>(const acceleration_structure_khr_t*) { return AccelerationStructureKHR(); }
template <>
inline Type& Type::fundamental<dyn_scalar_t>(const dyn_scalar_t* _prop)
{
return _prop == nullptr ? Void() : Scalar(_prop->baseType, _prop->bits, _prop->sign);
}
template <>
inline Type& Type::fundamental<dyn_array_t>(const dyn_array_t* _prop)
{
return _prop == nullptr ? Array(0) : Array(_prop->length, &_prop->elementType);
}
template <>
inline Type& Type::fundamental<dyn_runtime_array_t>(const dyn_runtime_array_t* _prop)
{
return RuntimeArray(_prop == nullptr ? nullptr : &_prop->elementType);
}
template <>
inline Type& Type::fundamental<dyn_vector_t>(const dyn_vector_t* _prop)
{
return _prop == nullptr ? Vector(0) : Vector(*_prop);
}
template <>
inline Type& Type::fundamental<dyn_matrix_t>(const dyn_matrix_t* _prop)
{
return _prop == nullptr ? Matrix(0) : Matrix(*_prop);
}
template <>
inline Type& Type::fundamental<void>(const void*) { return Void(); }
template <>
inline Type& Type::fundamental<bool>(const bool*) { return Bool(); }
template <>
inline Type& Type::fundamental<char>(const char*) { return Int(8u); }
template <>
inline Type& Type::fundamental<unsigned char>(const unsigned char*) { return UInt(8u); }
template <>
inline Type& Type::fundamental<short>(const short*) { return Int(16u); }
template <>
inline Type& Type::fundamental<unsigned short>(const unsigned short*) { return UInt(16u); }
template <>
inline Type& Type::fundamental<int>(const int*) { return Int(); }
template <>
inline Type& Type::fundamental<unsigned int>(const unsigned int*) { return UInt(); }
template <>
inline Type& Type::fundamental<long>(const long*) { return Int(); }
template <>
inline Type& Type::fundamental<unsigned long>(const unsigned long*) { return UInt(); }
template <>
inline Type& Type::fundamental<long long>(const long long*) { return Int(64u); }
template <>
inline Type& Type::fundamental<unsigned long long>(const unsigned long long*) { return UInt(64u); }
template <>
inline Type& Type::fundamental<float>(const float*) { return Float(); }
template <>
inline Type& Type::fundamental<double>(const double*) { return Double(); }
} // !spvgentwo