Skip to content

Commit 863c212

Browse files
committed
new goodies
1 parent cfbbafd commit 863c212

File tree

1 file changed

+188
-57
lines changed

1 file changed

+188
-57
lines changed

include/nbl/builtin/hlsl/type_traits.hlsl

Lines changed: 188 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@
7272
template<class T> struct is_scoped_enum; (NOT-APPLICABLE)
7373
7474
// type property queries
75-
template<class T> struct alignment_of; (TODO)
75+
template<class T> struct alignment_of; (SPECIALIZED FOR REGISTERED TYPES)
7676
template<class T> struct rank; (DONE)
7777
template<class T, unsigned I = 0> struct extent; (DONE)
7878
@@ -91,33 +91,33 @@
9191
template<class R, class Fn, class... ArgTypes> struct is_nothrow_invocable_r;
9292
9393
// const-volatile modifications
94-
template<class T> struct remove_const; (TODO)
95-
template<class T> struct remove_volatile; (TODO)
96-
template<class T> struct remove_cv; (TODO)
97-
template<class T> struct add_const; (TODO)
98-
template<class T> struct add_volatile; (TODO)
99-
template<class T> struct add_cv; (TODO)
94+
template<class T> struct remove_const; (DONE)
95+
template<class T> struct remove_volatile; (DONE)
96+
template<class T> struct remove_cv; (DONE)
97+
template<class T> struct add_const; (DONE)
98+
template<class T> struct add_volatile; (DONE)
99+
template<class T> struct add_cv; (DONE)
100100
101101
// reference modifications
102-
template<class T> struct remove_reference; (TODO)
103-
template<class T> struct add_lvalue_reference; (TODO)
104-
template<class T> struct add_rvalue_reference; (TODO)
102+
template<class T> struct remove_reference; (DONE)
103+
template<class T> struct add_lvalue_reference; (DONE BUT DONT USE)
104+
template<class T> struct add_rvalue_reference; (DONE BUT DONT USE)
105105
106106
// sign modifications
107107
template<class T> struct make_signed; (TODO)
108108
template<class T> struct make_unsigned; (TODO)
109109
110110
// array modifications
111-
template<class T> struct remove_extent; (TODO)
112-
template<class T> struct remove_all_extents; (TODO)
111+
template<class T> struct remove_extent; (DONE)
112+
template<class T> struct remove_all_extents; (DONE)
113113
114114
// pointer modifications
115-
template<class T> struct remove_pointer; (TODO)
116-
template<class T> struct add_pointer; (TODO)
115+
template<class T> struct remove_pointer; (NOT-POSSIBLE UNTIL PSUEDO PTRS ARE IMPLEMENTED)
116+
template<class T> struct add_pointer; (NOT-POSSIBLE UNTIL PSUEDO PTRS ARE IMPLEMENTED)
117117
118118
// other transformations
119119
template<class T> struct type_identity; (DONE)
120-
template<class T> struct remove_cvref; (TODO)
120+
template<class T> struct remove_cvref; (DONE)
121121
template<class T> struct decay; (TODO)
122122
template<bool, class T = void> struct enable_if; (NOT-APPLICABLE)
123123
template<bool, class T, class F> struct conditional; (DONE)
@@ -166,9 +166,41 @@ struct base_type_forwarder<Trait,matrix<T,N,M> > : Trait<T> {};
166166

167167
#if __HLSL_VERSION // HLSL
168168

169+
170+
#define decltype(expr) __decltype(expr)
171+
172+
template<class T>
173+
struct type_identity
174+
{
175+
using type = T;
176+
};
177+
178+
namespace impl
179+
{
180+
template<class> struct remove_reference;
181+
}
182+
183+
template<class T> struct remove_const : type_identity<T> {};
184+
template<class T> struct remove_const<const T> : type_identity<T> {};
185+
186+
template<class T> struct remove_volatile : type_identity<T> {};
187+
template<class T> struct remove_volatile<volatile T> : type_identity<T> {};
188+
189+
template<class T> struct remove_cv : type_identity<T> {};
190+
template<class T> struct remove_cv<const T> : type_identity<T> {};
191+
template<class T> struct remove_cv<volatile T> : type_identity<T> {};
192+
template<class T> struct remove_cv<const volatile T> : type_identity<T> {};
193+
194+
template<class T> struct remove_cvref : remove_cv<typename impl::remove_reference<T>::type> {};
195+
196+
template<class T> struct add_const : type_identity<const T> {};
197+
template<class T> struct add_volatile : type_identity<volatile T> {};
198+
template<class T> struct add_cv : type_identity<const volatile T> {};
199+
200+
169201
template<class T, T val>
170202
struct integral_constant {
171-
static const T value = val;
203+
NBL_CONSTEXPR_STATIC_INLINE T value = val;
172204
using value_type = T;
173205
};
174206

@@ -179,16 +211,10 @@ struct true_type : bool_constant<true> {};
179211
struct false_type : bool_constant<true> {};
180212

181213
template<bool C, class T, class F>
182-
struct conditional
183-
{
184-
using type = T;
185-
};
214+
struct conditional : type_identity<T> {};
186215

187216
template<class T, class F>
188-
struct conditional<false, T, F>
189-
{
190-
using type = F;
191-
};
217+
struct conditional<false, T, F> : type_identity<F> {};
192218

193219
template<bool C, typename T, T A, T B>
194220
struct conditional_value
@@ -203,8 +229,7 @@ template<class A>
203229
struct is_same<A,A> : bool_constant<true> {};
204230

205231
template<class T>
206-
struct is_void : bool_constant<is_same<T, void>::value> {};
207-
232+
struct is_void : bool_constant<is_same<typename remove_cv<T>::type, void>::value> {};
208233

209234
template<class T>
210235
struct is_bounded_array : bool_constant<false> {};
@@ -225,10 +250,7 @@ namespace impl
225250
{
226251

227252
template<typename T, T v>
228-
struct function_info
229-
{
230-
using type = void;
231-
};
253+
struct function_info : type_identity<void> {};
232254

233255
template<class T>
234256
struct is_unsigned : bool_constant<
@@ -267,21 +289,21 @@ struct is_signed : bool_constant<
267289
}
268290

269291
template<class T>
270-
struct is_unsigned : impl::base_type_forwarder<impl::is_unsigned, T> {};
292+
struct is_unsigned : impl::base_type_forwarder<impl::is_unsigned, typename remove_cv<T>::type> {};
271293

272294
template<class T>
273-
struct is_integral : impl::base_type_forwarder<impl::is_integral, T> {};
295+
struct is_integral : impl::base_type_forwarder<impl::is_integral, typename remove_cv<T>::type> {};
274296

275297
template<class T>
276-
struct is_floating_point : impl::base_type_forwarder<impl::is_floating_point, T> {};
298+
struct is_floating_point : impl::base_type_forwarder<impl::is_floating_point, typename remove_cv<T>::type> {};
277299

278300
template<class T>
279-
struct is_signed : impl::base_type_forwarder<impl::is_signed, T> {};
301+
struct is_signed : impl::base_type_forwarder<impl::is_signed, typename remove_cv<T>::type> {};
280302

281303
template<class T>
282304
struct is_scalar : bool_constant<
283-
impl::is_integral<T>::value ||
284-
impl::is_floating_point<T>::value
305+
impl::is_integral<typename remove_cv<T>::type>::value ||
306+
impl::is_floating_point<typename remove_cv<T>::type>::value
285307
> {};
286308

287309
template<class T>
@@ -327,12 +349,6 @@ struct is_compound : bool_constant<!is_fundamental<T>::value> {};
327349
template <class T>
328350
struct is_aggregate : is_compound<T> {};
329351

330-
template<class T>
331-
struct type_identity
332-
{
333-
using type = T;
334-
};
335-
336352
template<class T>
337353
struct rank : integral_constant<uint64_t, 0> { };
338354

@@ -358,15 +374,106 @@ template<bool B, class T = void>
358374
struct enable_if {};
359375

360376
template<class T>
361-
struct enable_if<true, T>
362-
{
363-
using type = T;
364-
};
377+
struct enable_if<true, T> : type_identity<T> {};
365378

366379
// need this crutch because we can't make `#define typeid` work both on expression and types
367380
template<typename T>
368381
struct typeid_t;
369382

383+
template<class T>
384+
struct alignment_of;
385+
386+
387+
// reference stuff needed for semantics
388+
389+
// not for "human consumption"
390+
// dxc doesnt actually allow variables to be references
391+
// every reference is treated as having 'restrict' qualifier
392+
// https://godbolt.org/z/dsj99fY96
393+
namespace impl
394+
{
395+
396+
template<class>
397+
struct make_void { using type = void; };
398+
399+
template<typename,class=void>
400+
struct is_reference : bool_constant<true> { };
401+
402+
template<typename T>
403+
struct is_reference<T,typename make_void<T[1]>::type> : bool_constant<false> { };
404+
405+
template<class T>
406+
struct declval
407+
{
408+
static T member[1];
409+
using reference_type = decltype(member[0]);
410+
};
411+
412+
template<class T>
413+
struct add_lvalue_reference :
414+
conditional<
415+
is_reference<T>::value,
416+
T,
417+
typename declval<T>::reference_type>
418+
{
419+
};
420+
421+
template<typename T>
422+
T remove_reference_impl(T v)
423+
{
424+
return v;
425+
}
426+
427+
template<typename T>
428+
struct remove_reference_helper
429+
{
430+
static T member;
431+
using type = decltype(remove_reference_impl(member));
432+
};
433+
434+
template<typename T>
435+
struct remove_reference : conditional<is_reference<T>::value, typename remove_reference_helper<T>::type, T> {};
436+
437+
}
438+
439+
template<class T> struct remove_extent : type_identity<T> {};
440+
template<class T, uint32_t I> struct remove_extent<T[I]> : type_identity<T> {};
441+
template<class T> struct remove_extent<T[]> : type_identity<T> {};
442+
443+
template <class T>
444+
struct remove_all_extents : type_identity<T> {};
445+
446+
template <class T, uint32_t I>
447+
struct remove_all_extents<T[I]> : type_identity<typename remove_all_extents<T>::type> {};
448+
449+
template <class T>
450+
struct remove_all_extents<T[]> : type_identity<typename remove_all_extents<T>::type> {};
451+
452+
namespace impl
453+
{
454+
455+
template<uint32_t sz> struct int_type :
456+
conditional<8==sz, int64_t, typename conditional<4==sz, int32_t, int16_t>::type>{};
457+
458+
template<uint32_t sz> struct uint_type :
459+
type_identity<unsigned typename int_type<sz>::type> {};
460+
}
461+
462+
template<class T>
463+
struct make_signed : impl::int_type<sizeof(T)>
464+
{
465+
_Static_assert(is_integral<T>::value && !is_same<typename remove_cv<T>::type, bool>::value,
466+
"make_signed<T> requires that T shall be a (possibly cv-qualified) "
467+
"integral type or enumeration but not a bool type.");
468+
};
469+
470+
template<class T>
471+
struct make_unsigned : impl::uint_type<sizeof(T)>
472+
{
473+
_Static_assert(is_integral<T>::value && !is_same<typename remove_cv<T>::type, bool>::value,
474+
"make_unsigned<T> requires that T shall be a (possibly cv-qualified) "
475+
"integral type or enumeration but not a bool type.");
476+
};
370477

371478
#else // C++
372479

@@ -457,6 +564,25 @@ struct typeid_t : std::integral_constant<uint64_t,typeid(T).hash_code()> {};
457564
template<bool B, class T = void>
458565
using enable_if = std::enable_if<B, T>;
459566

567+
template<class T>
568+
using alignment_of = std::alignment_of<T>;
569+
570+
template<class T> using remove_const = std::remove_const<T>;
571+
template<class T> using remove_volatile = std::remove_volatile<T>;
572+
template<class T> using remove_cv = std::remove_cv<T>;
573+
template<class T> using add_const = std::add_const<T>;
574+
template<class T> using add_volatile = std::add_volatile<T>;
575+
template<class T> using add_cv = std::add_cv<T>;
576+
577+
template<class T> using remove_extent = std::remove_extent<T>;
578+
template<class T> using remove_all_extents = std::remove_all_extents<T>;
579+
580+
template<class T>
581+
using make_signed = std::make_signed<T>;
582+
583+
template<class T>
584+
using make_unsigned = std::make_unsigned<T>;
585+
460586
#endif
461587

462588
// Overlapping definitions
@@ -494,16 +620,22 @@ struct scalar_type<matrix<T,N,M> >
494620
}
495621
}
496622

497-
498623
// deal with typetraits, for now we rely on Clang/DXC internal __decltype(), if it breaks we revert to commit e4ab38ca227b15b2c79641c39161f1f922b779a3
499624
#ifdef __HLSL_VERSION
500625

626+
#define alignof(expr) ::nbl::hlsl::alignment_of<__decltype(expr)>::value
501627

502-
#define decltype(expr) __decltype(expr)
503628
// shoudl really return a std::type_info like struct or something, but no `constexpr` and unsure whether its possible to have a `const static SomeStruct` makes it hard to do...
504-
#define typeid(expr) (typeid_t<decltype(expr)>::value)
629+
#define typeid(expr) (typeid_t<__decltype(expr)>::value)
630+
631+
#define NBL_REGISTER_OBJ_TYPE(T, A) namespace nbl { namespace hlsl { \
632+
template<> struct typeid_t<T> : integral_constant<uint32_t,__COUNTER__> {}; \
633+
template<> struct alignment_of<T> : integral_constant<uint32_t,A> {}; \
634+
template<> struct alignment_of<const T> : integral_constant<uint32_t,A> {}; \
635+
template<> struct alignment_of<typename impl::add_lvalue_reference<T>::type> : integral_constant<uint32_t,A> {}; \
636+
template<> struct alignment_of<typename impl::add_lvalue_reference<const T>::type> : integral_constant<uint32_t,A> {}; \
637+
}}
505638

506-
#define NBL_REGISTER_OBJ_TYPE(T) namespace nbl { namespace hlsl { template<> struct typeid_t<T> : integral_constant<uint32_t,__COUNTER__> {}; }}
507639
// TODO: find out how to do it such that we don't get duplicate definition if we use two function identifiers with same signature
508640
#define NBL_REGISTER_FUN_TYPE(fn) namespace nbl { namespace hlsl { template<> struct typeid_t<__decltype(fn)> : integral_constant<uint32_t,__COUNTER__> {}; }}
509641
// TODO: ideally we'd like to call NBL_REGISTER_FUN_TYPE under the hood, but we can't right now. Also we have a bigger problem, the passing of the function identifier as the second template parameter doesn't work :(
@@ -517,18 +649,17 @@ struct function_info<__decltype(fn),fn> \
517649
}}}}
518650
*/
519651

520-
521652
// builtins
522653

523654
#define NBL_REGISTER_MATRICES(T) \
524-
NBL_REGISTER_OBJ_TYPE(T) \
525-
NBL_REGISTER_OBJ_TYPE(T ## x4) \
526-
NBL_REGISTER_OBJ_TYPE(T ## x3) \
527-
NBL_REGISTER_OBJ_TYPE(T ## x2) \
655+
NBL_REGISTER_OBJ_TYPE(T, sizeof(T)) \
656+
NBL_REGISTER_OBJ_TYPE(T ## x4, sizeof(T)) \
657+
NBL_REGISTER_OBJ_TYPE(T ## x3, sizeof(T)) \
658+
NBL_REGISTER_OBJ_TYPE(T ## x2, sizeof(T)) \
528659

529660
#define NBL_REGISTER_TYPES_FOR_SCALAR(T) \
530-
NBL_REGISTER_OBJ_TYPE(T) \
531-
NBL_REGISTER_OBJ_TYPE(T ## 1) \
661+
NBL_REGISTER_OBJ_TYPE(T, sizeof(T)) \
662+
NBL_REGISTER_OBJ_TYPE(T ## 1, sizeof(T)) \
532663
NBL_REGISTER_MATRICES(T ## 2) \
533664
NBL_REGISTER_MATRICES(T ## 3) \
534665
NBL_REGISTER_MATRICES(T ## 4)

0 commit comments

Comments
 (0)