33
44#pragma once
55
6+ #include < array>
67#include < string>
78#include < vector>
89#include < iosfwd>
@@ -164,28 +165,19 @@ enum class ProgramTensorMetadataDependency : int {
164165};
165166OStringStream& operator <<(OStringStream& os, ProgramTensorMetadataDependency);
166167
167- #if defined(__GNUC__)
168- #pragma GCC diagnostic push
169- #pragma GCC diagnostic ignored "-Wstrict-aliasing"
170- #endif
171-
172168inline ProgramTensorMetadataDependency operator |(ProgramTensorMetadataDependency a, ProgramTensorMetadataDependency b) {
173- return ( ProgramTensorMetadataDependency)(( int &)a | ( int &)b );
169+ return static_cast < ProgramTensorMetadataDependency>( static_cast < int >(a) | static_cast < int >(b) );
174170}
175171inline ProgramTensorMetadataDependency operator &(ProgramTensorMetadataDependency a, ProgramTensorMetadataDependency b) {
176- return ( ProgramTensorMetadataDependency)(( int &)a & ( int &)b );
172+ return static_cast < ProgramTensorMetadataDependency>( static_cast < int >(a) & static_cast < int >(b) );
177173}
178174inline ProgramTensorMetadataDependency& operator |=(ProgramTensorMetadataDependency& a, ProgramTensorMetadataDependency b) {
179- return (ProgramTensorMetadataDependency&)(( int &)a |= ( int &)b) ;
175+ return a = a | b ;
180176}
181177inline ProgramTensorMetadataDependency& operator &=(ProgramTensorMetadataDependency& a, ProgramTensorMetadataDependency b) {
182- return (ProgramTensorMetadataDependency&)(( int &)a &= ( int &)b) ;
178+ return a = a & b ;
183179}
184180
185- #if defined(__GNUC__)
186- #pragma GCC diagnostic pop
187- #endif
188-
189181constexpr SafeInt<uint32_t > WORKGROUP_SIZE = 64 ;
190182
191183// data type of variable
@@ -417,133 +409,55 @@ class ProgramWrapper : public ProgramBase {
417409 ProgramWrapper (Args&&... args) : ProgramBase{std::forward<Args>(args)...} {}
418410};
419411
420- #if defined(ORT_WEBGPU_REGISTER_DERIVED_PROGRAM_CLASS_TYPE_CHECK)
421- #error "macro ORT_WEBGPU_REGISTER_DERIVED_PROGRAM_CLASS_TYPE_CHECK is already defined"
422- #endif
423-
424- #define ORT_WEBGPU_REGISTER_DERIVED_PROGRAM_CLASS_TYPE_CHECK (identifier, element_type ) \
425- private: \
426- template <typename U> \
427- static auto test_has_##identifier(int ) -> decltype (U::identifier, std::true_type{}); /* checks if member exists */ \
428- template <typename ...> \
429- static auto test_has_##identifier(...) -> std::false_type; \
430- \
431- template <typename U, /* The following type check uses SFINAE */ \
432- typename = std::enable_if_t < /* to ensure the specific member: */ \
433- is_const_std_array<decltype (U::identifier)>::value && /* - is a const std::array */ \
434- std::is_const_v<decltype (U::identifier)> && /* - has "const" modifier */ \
435- !std::is_member_pointer_v<decltype (&U::identifier)>>> /* - is static */ \
436- static auto test_has_##identifier##_with_correct_type(int ) -> std::true_type; \
437- template <typename ...> \
438- static auto test_has_##identifier##_with_correct_type(...) -> std::false_type; \
439- \
440- public: \
441- static constexpr bool has_##identifier = decltype (test_has_##identifier<T>(0 ))::value; \
442- static constexpr bool has_##identifier##_with_correct_type = decltype (test_has_##identifier##_with_correct_type<T>(0 ))::value
443-
444412// the following template class checks whether the type is a const std::array
445413template <typename T>
446414struct is_const_std_array : std::false_type {};
447415template <typename T, size_t N>
448416struct is_const_std_array <const std::array<T, N>> : std::true_type {};
449417
450- // the following template class checks whether certain static members exist in the derived class (SFINAE)
451- template <typename T>
452- class DerivedProgramClassTypeCheck {
453- ORT_WEBGPU_REGISTER_DERIVED_PROGRAM_CLASS_TYPE_CHECK (constants, ProgramConstant);
454- ORT_WEBGPU_REGISTER_DERIVED_PROGRAM_CLASS_TYPE_CHECK (overridable_constants, ProgramOverridableConstantDefinition);
455- ORT_WEBGPU_REGISTER_DERIVED_PROGRAM_CLASS_TYPE_CHECK (uniform_variables, ProgramUniformVariableDefinition);
456- };
457-
458- // compile-time tests for the type check
459- //
460- // TODO: move this to test folder
461- namespace test {
418+ // The following variable templates check whether certain static members exist in the derived class.
419+ // Uses std::void_t with decltype(T::member) for SFINAE-based detection of named static data members.
462420
421+ template <typename T, typename = void >
422+ inline constexpr bool has_member_constants = false ;
463423template <typename T>
464- class TestTypeCheck {
465- ORT_WEBGPU_REGISTER_DERIVED_PROGRAM_CLASS_TYPE_CHECK (a, int );
466- };
467-
468- struct TestClass_Empty {};
469- static_assert (!TestTypeCheck<TestClass_Empty>::has_a);
470- static_assert (!TestTypeCheck<TestClass_Empty>::has_a_with_correct_type);
471-
472- struct TestClass_NotArray_0 {
473- int b;
474- };
475- static_assert (!TestTypeCheck<TestClass_NotArray_0>::has_a);
476- static_assert (!TestTypeCheck<TestClass_NotArray_0>::has_a_with_correct_type);
424+ inline constexpr bool has_member_constants<T, std::void_t <decltype (T::constants)>> = true ;
477425
478- struct TestClass_NotArray_1 {
479- int a;
480- };
481- static_assert (TestTypeCheck<TestClass_NotArray_1>::has_a);
482- static_assert (!TestTypeCheck<TestClass_NotArray_1>::has_a_with_correct_type);
483-
484- struct TestClass_NotArray_2 {
485- const int a;
486- };
487- static_assert (TestTypeCheck<TestClass_NotArray_2>::has_a);
488- static_assert (!TestTypeCheck<TestClass_NotArray_2>::has_a_with_correct_type);
489-
490- struct TestClass_NotStdArray_0 {
491- const int a[2 ];
492- };
493- static_assert (TestTypeCheck<TestClass_NotStdArray_0>::has_a);
494- static_assert (!TestTypeCheck<TestClass_NotStdArray_0>::has_a_with_correct_type);
495-
496- struct TestClass_NotStdArray_1 {
497- static constexpr int a[] = {0 };
498- };
499- static_assert (TestTypeCheck<TestClass_NotStdArray_1>::has_a);
500- static_assert (!TestTypeCheck<TestClass_NotStdArray_1>::has_a_with_correct_type);
501-
502- struct TestClass_NotStdArray_2 {
503- static int a[];
504- };
505- static_assert (TestTypeCheck<TestClass_NotStdArray_2>::has_a);
506- static_assert (!TestTypeCheck<TestClass_NotStdArray_2>::has_a_with_correct_type);
507-
508- struct TestClass_NotStdArray_3 {
509- static const int a[];
510- };
511- static_assert (TestTypeCheck<TestClass_NotStdArray_3>::has_a);
512- static_assert (!TestTypeCheck<TestClass_NotStdArray_3>::has_a_with_correct_type);
426+ template <typename T, typename = void >
427+ inline constexpr bool has_member_overridable_constants = false ;
428+ template <typename T>
429+ inline constexpr bool has_member_overridable_constants<T, std::void_t <decltype (T::overridable_constants)>> = true ;
513430
514- struct TestClass_StdArray_0 {
515- std::array<int , 1 > a = {1 };
516- };
517- static_assert (TestTypeCheck<TestClass_StdArray_0>::has_a);
518- static_assert (!TestTypeCheck<TestClass_StdArray_0>::has_a_with_correct_type);
431+ template <typename T, typename = void >
432+ inline constexpr bool has_member_uniform_variables = false ;
433+ template <typename T>
434+ inline constexpr bool has_member_uniform_variables<T, std::void_t <decltype (T::uniform_variables)>> = true ;
519435
520- struct TestClass_StdArray_1 {
521- static constexpr std::array<int , 2 > a = {1 , 2 };
522- };
523- static_assert (TestTypeCheck<TestClass_StdArray_1>::has_a);
524- static_assert (TestTypeCheck<TestClass_StdArray_1>::has_a_with_correct_type);
436+ // C++20 concepts for checking whether the member has the correct type (static const std::array).
525437
526- struct TestClass_StdArray_2 {
527- static const std::array<int , 3 > a;
438+ template <typename T>
439+ concept has_constants_correct_type = requires {
440+ T::constants;
441+ requires is_const_std_array<decltype (T::constants)>::value;
442+ requires std::is_const_v<decltype (T::constants)>;
443+ requires !std::is_member_pointer_v<decltype (&T::constants)>;
528444};
529- static_assert (TestTypeCheck<TestClass_StdArray_2>::has_a);
530- static_assert (TestTypeCheck<TestClass_StdArray_2>::has_a_with_correct_type);
531445
532- struct TestClass_StdArray_3 {
533- static constexpr const std::array<int , 4 > a = {1 , 2 , 3 , 4 };
446+ template <typename T>
447+ concept has_overridable_constants_correct_type = requires {
448+ T::overridable_constants;
449+ requires is_const_std_array<decltype (T::overridable_constants)>::value;
450+ requires std::is_const_v<decltype (T::overridable_constants)>;
451+ requires !std::is_member_pointer_v<decltype (&T::overridable_constants)>;
534452};
535- static_assert (TestTypeCheck<TestClass_StdArray_3>::has_a);
536- static_assert (TestTypeCheck<TestClass_StdArray_3>::has_a_with_correct_type);
537453
538- struct TestClass_StdArray_4 {
539- static std::array<int , 5 > a;
454+ template <typename T>
455+ concept has_uniform_variables_correct_type = requires {
456+ T::uniform_variables;
457+ requires is_const_std_array<decltype (T::uniform_variables)>::value;
458+ requires std::is_const_v<decltype (T::uniform_variables)>;
459+ requires !std::is_member_pointer_v<decltype (&T::uniform_variables)>;
540460};
541- static_assert (TestTypeCheck<TestClass_StdArray_4>::has_a);
542- static_assert (!TestTypeCheck<TestClass_StdArray_4>::has_a_with_correct_type);
543-
544- } // namespace test
545-
546- #undef ORT_WEBGPU_REGISTER_DERIVED_PROGRAM_CLASS_TYPE_CHECK
547461
548462} // namespace details
549463
@@ -555,40 +469,40 @@ class Program : public details::ProgramWrapper {
555469
556470 static ProgramMetadata GetMetadata () {
557471 ProgramMetadata metadata;
558- if constexpr (details::DerivedProgramClassTypeCheck<T>::has_constants) {
559- constexpr const ProgramConstant* ptr = T::constants.data ();
560- constexpr size_t len = T::constants.size ();
561-
562- static_assert (details::DerivedProgramClassTypeCheck<T>::has_constants_with_correct_type,
472+ if constexpr (details::has_member_constants<T>) {
473+ static_assert (details::has_constants_correct_type<T>,
563474 " Derived class of \" Program\" has member \" constants\" but its type is incorrect. "
564475 " Please use macro WEBGPU_PROGRAM_DEFINE_CONSTANTS() or WEBGPU_PROGRAM_EXTEND_CONSTANTS() to declare constants." );
565476
477+ constexpr const ProgramConstant* ptr = T::constants.data ();
478+ constexpr size_t len = T::constants.size ();
479+
566480 metadata.constants = {ptr, len};
567481 } else {
568482 metadata.constants = {};
569483 }
570484
571- if constexpr (details::DerivedProgramClassTypeCheck<T>::has_overridable_constants) {
572- constexpr const ProgramOverridableConstantDefinition* ptr = T::overridable_constants.data ();
573- constexpr size_t len = T::overridable_constants.size ();
574-
575- static_assert (details::DerivedProgramClassTypeCheck<T>::has_overridable_constants_with_correct_type,
485+ if constexpr (details::has_member_overridable_constants<T>) {
486+ static_assert (details::has_overridable_constants_correct_type<T>,
576487 " Derived class of \" Program\" has member \" overridable_constants\" but its type is incorrect. "
577488 " Please use macro WEBGPU_PROGRAM_DEFINE_OVERRIDABLE_CONSTANTS() or WEBGPU_PROGRAM_EXTEND_OVERRIDABLE_CONSTANTS() to declare overridable constants." );
578489
490+ constexpr const ProgramOverridableConstantDefinition* ptr = T::overridable_constants.data ();
491+ constexpr size_t len = T::overridable_constants.size ();
492+
579493 metadata.overridable_constants = {ptr, len};
580494 } else {
581495 metadata.overridable_constants = {};
582496 }
583497
584- if constexpr (details::DerivedProgramClassTypeCheck<T>::has_uniform_variables) {
585- constexpr const ProgramUniformVariableDefinition* ptr = T::uniform_variables.data ();
586- constexpr size_t len = T::uniform_variables.size ();
587-
588- static_assert (details::DerivedProgramClassTypeCheck<T>::has_uniform_variables_with_correct_type,
498+ if constexpr (details::has_member_uniform_variables<T>) {
499+ static_assert (details::has_uniform_variables_correct_type<T>,
589500 " Derived class of \" Program\" has member \" uniform_variables\" but its type is incorrect. "
590501 " Please use macro WEBGPU_PROGRAM_DEFINE_UNIFORM_VARIABLES() or WEBGPU_PROGRAM_EXTEND_UNIFORM_VARIABLES() to declare uniform variables." );
591502
503+ constexpr const ProgramUniformVariableDefinition* ptr = T::uniform_variables.data ();
504+ constexpr size_t len = T::uniform_variables.size ();
505+
592506 metadata.uniform_variables = {ptr, len};
593507 } else {
594508 metadata.uniform_variables = {};
@@ -599,20 +513,6 @@ class Program : public details::ProgramWrapper {
599513};
600514
601515namespace details {
602- // helper function to convert a C-style array to std::array
603- //
604- // This is basically the same as std::to_array in C++20.
605- //
606- template <typename T, size_t N, size_t ... Idx>
607- constexpr auto _to_std_array_impl (T (&arr)[N], std::index_sequence<Idx...>) -> std::array<std::remove_cv_t<T>, N> {
608- return {{arr[Idx]...}};
609- }
610-
611- template <typename T, size_t N>
612- constexpr auto _to_std_array (T (&arr)[N]) -> std::array<std::remove_cv_t<T>, N> {
613- return _to_std_array_impl (arr, std::make_index_sequence<N>{});
614- }
615-
616516// helper function to concatenate a std::array and a C-style array to a std::array
617517//
618518template <typename T, size_t L, size_t ... IdxL, size_t R, size_t ... IdxR>
@@ -632,7 +532,7 @@ constexpr std::array<std::remove_cv_t<T>, L + R> _concat2(const std::array<T, L>
632532#define WEBGPU_PROGRAM_DEFINE_ (identifier, T, ...) \
633533 static constexpr const T identifier##_own[] = {__VA_ARGS__}; \
634534 static constexpr const auto identifier = \
635- onnxruntime::webgpu::details::_to_std_array (identifier##_own)
535+ std::to_array (identifier##_own)
636536
637537#define WEBGPU_PROGRAM_EXTEND_ (identifier, T, BASE , ...) \
638538 static constexpr const T identifier##_own[] = {__VA_ARGS__}; \
0 commit comments