diff --git a/cmake/onnxruntime_providers_webgpu.cmake b/cmake/onnxruntime_providers_webgpu.cmake index cd29e4dad0a17..921b20e4bab32 100644 --- a/cmake/onnxruntime_providers_webgpu.cmake +++ b/cmake/onnxruntime_providers_webgpu.cmake @@ -248,7 +248,6 @@ endif() endif() - target_compile_features(onnxruntime_providers_webgpu PRIVATE cxx_std_20) add_dependencies(onnxruntime_providers_webgpu onnx ${onnxruntime_EXTERNAL_DEPENDENCIES}) if (onnxruntime_WGSL_TEMPLATE) diff --git a/onnxruntime/contrib_ops/webgpu/bert/bias_add.cc b/onnxruntime/contrib_ops/webgpu/bert/bias_add.cc index 0f2e6d725007f..e53192bbed618 100644 --- a/onnxruntime/contrib_ops/webgpu/bert/bias_add.cc +++ b/onnxruntime/contrib_ops/webgpu/bert/bias_add.cc @@ -30,7 +30,7 @@ Status BiasAddProgram::GenerateShaderCode(ShaderHelper& shader) const { << " let value = " << input.GetByOffset("global_idx") << " + " << bias.GetByOffset("global_idx % uniforms.channels") << " + " << residual.GetByOffset("global_idx") << ";\n" - << " " + output.SetByOffset("global_idx", "value"); + << " " << output.SetByOffset("global_idx", "value"); return Status::OK(); } diff --git a/onnxruntime/contrib_ops/webgpu/bert/rotary_embedding.cc b/onnxruntime/contrib_ops/webgpu/bert/rotary_embedding.cc index 5536a26b3e00b..9f81e490971cd 100644 --- a/onnxruntime/contrib_ops/webgpu/bert/rotary_embedding.cc +++ b/onnxruntime/contrib_ops/webgpu/bert/rotary_embedding.cc @@ -40,7 +40,7 @@ Status RotaryEmbeddingProgram::GenerateShaderCode(ShaderHelper& shader) const { << " let j = i + select(half_rotary_emb_dim, 1, " << interleaved_str << ");\n" << " let re = " << input.GetByOffset("i") << " * " << cos_cache.GetByIndices("vec2(position_id, bsnh[3])") << " - " << input.GetByOffset("j") << " * " << sin_cache.GetByIndices("vec2(position_id, bsnh[3])") << ";\n" << " " << output.SetByOffset("i", "re") << "\n" - << " let im = " << input.GetByOffset("i") << " * " << sin_cache.GetByIndices("vec2(position_id, bsnh[3])") << " + " << input.GetByOffset("j") + " * " << cos_cache.GetByIndices("vec2(position_id, bsnh[3])") << ";\n" + << " let im = " << input.GetByOffset("i") << " * " << sin_cache.GetByIndices("vec2(position_id, bsnh[3])") << " + " << input.GetByOffset("j") << " * " << cos_cache.GetByIndices("vec2(position_id, bsnh[3])") << ";\n" << " " << output.SetByOffset("j", "im") << "\n" << " } else { \n" " let k = dot(bsnh, uniforms.input_output_stride) + half_rotary_emb_dim;\n" diff --git a/onnxruntime/core/providers/webgpu/math/einsum.cc b/onnxruntime/core/providers/webgpu/math/einsum.cc index e17c0281c738f..e608a13b68a1a 100644 --- a/onnxruntime/core/providers/webgpu/math/einsum.cc +++ b/onnxruntime/core/providers/webgpu/math/einsum.cc @@ -4,6 +4,7 @@ #include "core/providers/webgpu/math/einsum.h" #include +#include #include #include #include @@ -24,7 +25,7 @@ static const std::regex lhs_pattern("(([a-zA-Z]|\\.\\.\\.)*,)*([a-zA-Z]|\\.\\.\\ // Helper function to remove all whitespaces in a given string. std::string RemoveAllWhitespace(const std::string& str) { std::string result = str; - result.erase(std::remove_if(result.begin(), result.end(), ::isspace), result.end()); + std::erase_if(result, [](unsigned char c) { return std::isspace(c); }); return result; } @@ -318,7 +319,7 @@ Status EinsumProgram::GenerateShaderCode(ShaderHelper& shader) const { symbol)); // Check if we've already processed this symbol to avoid duplicate loop generation - if (uniform_symbol_set.find(symbol) == uniform_symbol_set.end()) { + if (!uniform_symbol_set.contains(symbol)) { // Add symbol to tracked set to prevent duplicate processing uniform_symbol_set.insert(symbol); diff --git a/onnxruntime/core/providers/webgpu/math/unary_elementwise_ops.cc b/onnxruntime/core/providers/webgpu/math/unary_elementwise_ops.cc index 7db65a42eac4d..b8a3f923e81cc 100644 --- a/onnxruntime/core/providers/webgpu/math/unary_elementwise_ops.cc +++ b/onnxruntime/core/providers/webgpu/math/unary_elementwise_ops.cc @@ -2,6 +2,7 @@ // Licensed under the MIT License. #include +#include #include #include "core/providers/webgpu/math/unary_elementwise_ops.h" @@ -194,10 +195,6 @@ class Clip final : public UnaryElementwise { "Clip", std::is_same_v ? ClipF16Impl : ClipImpl, "", ShaderUsage::UseElementTypeAlias} {} -#if defined(__GNUC__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wstrict-aliasing" -#endif Status ConfigureProgram(const ComputeContext& context, UnaryElementwiseProgram& program) const override { const auto* clip_min_tensor = context.Input(1); @@ -209,7 +206,9 @@ class Clip final : public UnaryElementwise { : std::numeric_limits::max()}; if constexpr (std::is_same_v) { // F16: stores span as a single float - float encoded_value = *reinterpret_cast(attr); + float encoded_value; + static_assert(sizeof(encoded_value) == 2 * sizeof(MLFloat16)); + std::memcpy(&encoded_value, attr, sizeof(encoded_value)); program.AddUniformVariable({encoded_value}); } else { static_assert(sizeof(T) == sizeof(float), "T must be f32, i32 or u32"); @@ -218,9 +217,6 @@ class Clip final : public UnaryElementwise { } return Status::OK(); } -#if defined(__GNUC__) -#pragma GCC diagnostic pop -#endif // uniforms.attr is a f32 value. It is encoded as a float for 2 f16 values. // bitcast>(uniforms.attr)[0] is clip_min, bitcast>(uniforms.attr)[1] is clip_max diff --git a/onnxruntime/core/providers/webgpu/nn/pool.cc b/onnxruntime/core/providers/webgpu/nn/pool.cc index 6698a831b0c1a..a4bc8638c4265 100644 --- a/onnxruntime/core/providers/webgpu/nn/pool.cc +++ b/onnxruntime/core/providers/webgpu/nn/pool.cc @@ -249,7 +249,7 @@ Status Pool::ComputeInternal(ComputeContext& context) const { Tensor* Y = context.Output(0, output_shape); std::vector kernel_strides(kernel_shape.size()); - ORT_ENFORCE(kernel_shape.size() > 0, "kernel_shape must have at least one element."); + ORT_ENFORCE(!kernel_shape.empty(), "kernel_shape must have at least one element."); // Calculate the kernel element strides for each dimension in reverse order. For example: // kernel_shape = [3, 2], kernel_strides = [2, 1] // kernel_shape = [2, 3, 2], kernel_strides = [6, 2, 1] diff --git a/onnxruntime/core/providers/webgpu/program.h b/onnxruntime/core/providers/webgpu/program.h index fa6ca1a8f6ba5..736111d2a18bc 100644 --- a/onnxruntime/core/providers/webgpu/program.h +++ b/onnxruntime/core/providers/webgpu/program.h @@ -3,6 +3,7 @@ #pragma once +#include #include #include #include @@ -164,28 +165,19 @@ enum class ProgramTensorMetadataDependency : int { }; OStringStream& operator<<(OStringStream& os, ProgramTensorMetadataDependency); -#if defined(__GNUC__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wstrict-aliasing" -#endif - inline ProgramTensorMetadataDependency operator|(ProgramTensorMetadataDependency a, ProgramTensorMetadataDependency b) { - return (ProgramTensorMetadataDependency)((int&)a | (int&)b); + return static_cast(static_cast(a) | static_cast(b)); } inline ProgramTensorMetadataDependency operator&(ProgramTensorMetadataDependency a, ProgramTensorMetadataDependency b) { - return (ProgramTensorMetadataDependency)((int&)a & (int&)b); + return static_cast(static_cast(a) & static_cast(b)); } inline ProgramTensorMetadataDependency& operator|=(ProgramTensorMetadataDependency& a, ProgramTensorMetadataDependency b) { - return (ProgramTensorMetadataDependency&)((int&)a |= (int&)b); + return a = a | b; } inline ProgramTensorMetadataDependency& operator&=(ProgramTensorMetadataDependency& a, ProgramTensorMetadataDependency b) { - return (ProgramTensorMetadataDependency&)((int&)a &= (int&)b); + return a = a & b; } -#if defined(__GNUC__) -#pragma GCC diagnostic pop -#endif - constexpr SafeInt WORKGROUP_SIZE = 64; // data type of variable @@ -417,133 +409,55 @@ class ProgramWrapper : public ProgramBase { ProgramWrapper(Args&&... args) : ProgramBase{std::forward(args)...} {} }; -#if defined(ORT_WEBGPU_REGISTER_DERIVED_PROGRAM_CLASS_TYPE_CHECK) -#error "macro ORT_WEBGPU_REGISTER_DERIVED_PROGRAM_CLASS_TYPE_CHECK is already defined" -#endif - -#define ORT_WEBGPU_REGISTER_DERIVED_PROGRAM_CLASS_TYPE_CHECK(identifier, element_type) \ - private: \ - template \ - static auto test_has_##identifier(int) -> decltype(U::identifier, std::true_type{}); /* checks if member exists */ \ - template \ - static auto test_has_##identifier(...) -> std::false_type; \ - \ - template ::value && /* - is a const std::array */ \ - std::is_const_v && /* - has "const" modifier */ \ - !std::is_member_pointer_v>> /* - is static */ \ - static auto test_has_##identifier##_with_correct_type(int) -> std::true_type; \ - template \ - static auto test_has_##identifier##_with_correct_type(...) -> std::false_type; \ - \ - public: \ - static constexpr bool has_##identifier = decltype(test_has_##identifier(0))::value; \ - static constexpr bool has_##identifier##_with_correct_type = decltype(test_has_##identifier##_with_correct_type(0))::value - // the following template class checks whether the type is a const std::array template struct is_const_std_array : std::false_type {}; template struct is_const_std_array> : std::true_type {}; -// the following template class checks whether certain static members exist in the derived class (SFINAE) -template -class DerivedProgramClassTypeCheck { - ORT_WEBGPU_REGISTER_DERIVED_PROGRAM_CLASS_TYPE_CHECK(constants, ProgramConstant); - ORT_WEBGPU_REGISTER_DERIVED_PROGRAM_CLASS_TYPE_CHECK(overridable_constants, ProgramOverridableConstantDefinition); - ORT_WEBGPU_REGISTER_DERIVED_PROGRAM_CLASS_TYPE_CHECK(uniform_variables, ProgramUniformVariableDefinition); -}; - -// compile-time tests for the type check -// -// TODO: move this to test folder -namespace test { +// The following variable templates check whether certain static members exist in the derived class. +// Uses std::void_t with decltype(T::member) for SFINAE-based detection of named static data members. +template +inline constexpr bool has_member_constants = false; template -class TestTypeCheck { - ORT_WEBGPU_REGISTER_DERIVED_PROGRAM_CLASS_TYPE_CHECK(a, int); -}; - -struct TestClass_Empty {}; -static_assert(!TestTypeCheck::has_a); -static_assert(!TestTypeCheck::has_a_with_correct_type); - -struct TestClass_NotArray_0 { - int b; -}; -static_assert(!TestTypeCheck::has_a); -static_assert(!TestTypeCheck::has_a_with_correct_type); +inline constexpr bool has_member_constants> = true; -struct TestClass_NotArray_1 { - int a; -}; -static_assert(TestTypeCheck::has_a); -static_assert(!TestTypeCheck::has_a_with_correct_type); - -struct TestClass_NotArray_2 { - const int a; -}; -static_assert(TestTypeCheck::has_a); -static_assert(!TestTypeCheck::has_a_with_correct_type); - -struct TestClass_NotStdArray_0 { - const int a[2]; -}; -static_assert(TestTypeCheck::has_a); -static_assert(!TestTypeCheck::has_a_with_correct_type); - -struct TestClass_NotStdArray_1 { - static constexpr int a[] = {0}; -}; -static_assert(TestTypeCheck::has_a); -static_assert(!TestTypeCheck::has_a_with_correct_type); - -struct TestClass_NotStdArray_2 { - static int a[]; -}; -static_assert(TestTypeCheck::has_a); -static_assert(!TestTypeCheck::has_a_with_correct_type); - -struct TestClass_NotStdArray_3 { - static const int a[]; -}; -static_assert(TestTypeCheck::has_a); -static_assert(!TestTypeCheck::has_a_with_correct_type); +template +inline constexpr bool has_member_overridable_constants = false; +template +inline constexpr bool has_member_overridable_constants> = true; -struct TestClass_StdArray_0 { - std::array a = {1}; -}; -static_assert(TestTypeCheck::has_a); -static_assert(!TestTypeCheck::has_a_with_correct_type); +template +inline constexpr bool has_member_uniform_variables = false; +template +inline constexpr bool has_member_uniform_variables> = true; -struct TestClass_StdArray_1 { - static constexpr std::array a = {1, 2}; -}; -static_assert(TestTypeCheck::has_a); -static_assert(TestTypeCheck::has_a_with_correct_type); +// C++20 concepts for checking whether the member has the correct type (static const std::array). -struct TestClass_StdArray_2 { - static const std::array a; +template +concept has_constants_correct_type = requires { + T::constants; + requires is_const_std_array::value; + requires std::is_const_v; + requires !std::is_member_pointer_v; }; -static_assert(TestTypeCheck::has_a); -static_assert(TestTypeCheck::has_a_with_correct_type); -struct TestClass_StdArray_3 { - static constexpr const std::array a = {1, 2, 3, 4}; +template +concept has_overridable_constants_correct_type = requires { + T::overridable_constants; + requires is_const_std_array::value; + requires std::is_const_v; + requires !std::is_member_pointer_v; }; -static_assert(TestTypeCheck::has_a); -static_assert(TestTypeCheck::has_a_with_correct_type); -struct TestClass_StdArray_4 { - static std::array a; +template +concept has_uniform_variables_correct_type = requires { + T::uniform_variables; + requires is_const_std_array::value; + requires std::is_const_v; + requires !std::is_member_pointer_v; }; -static_assert(TestTypeCheck::has_a); -static_assert(!TestTypeCheck::has_a_with_correct_type); - -} // namespace test - -#undef ORT_WEBGPU_REGISTER_DERIVED_PROGRAM_CLASS_TYPE_CHECK } // namespace details @@ -555,40 +469,40 @@ class Program : public details::ProgramWrapper { static ProgramMetadata GetMetadata() { ProgramMetadata metadata; - if constexpr (details::DerivedProgramClassTypeCheck::has_constants) { - constexpr const ProgramConstant* ptr = T::constants.data(); - constexpr size_t len = T::constants.size(); - - static_assert(details::DerivedProgramClassTypeCheck::has_constants_with_correct_type, + if constexpr (details::has_member_constants) { + static_assert(details::has_constants_correct_type, "Derived class of \"Program\" has member \"constants\" but its type is incorrect. " "Please use macro WEBGPU_PROGRAM_DEFINE_CONSTANTS() or WEBGPU_PROGRAM_EXTEND_CONSTANTS() to declare constants."); + constexpr const ProgramConstant* ptr = T::constants.data(); + constexpr size_t len = T::constants.size(); + metadata.constants = {ptr, len}; } else { metadata.constants = {}; } - if constexpr (details::DerivedProgramClassTypeCheck::has_overridable_constants) { - constexpr const ProgramOverridableConstantDefinition* ptr = T::overridable_constants.data(); - constexpr size_t len = T::overridable_constants.size(); - - static_assert(details::DerivedProgramClassTypeCheck::has_overridable_constants_with_correct_type, + if constexpr (details::has_member_overridable_constants) { + static_assert(details::has_overridable_constants_correct_type, "Derived class of \"Program\" has member \"overridable_constants\" but its type is incorrect. " "Please use macro WEBGPU_PROGRAM_DEFINE_OVERRIDABLE_CONSTANTS() or WEBGPU_PROGRAM_EXTEND_OVERRIDABLE_CONSTANTS() to declare overridable constants."); + constexpr const ProgramOverridableConstantDefinition* ptr = T::overridable_constants.data(); + constexpr size_t len = T::overridable_constants.size(); + metadata.overridable_constants = {ptr, len}; } else { metadata.overridable_constants = {}; } - if constexpr (details::DerivedProgramClassTypeCheck::has_uniform_variables) { - constexpr const ProgramUniformVariableDefinition* ptr = T::uniform_variables.data(); - constexpr size_t len = T::uniform_variables.size(); - - static_assert(details::DerivedProgramClassTypeCheck::has_uniform_variables_with_correct_type, + if constexpr (details::has_member_uniform_variables) { + static_assert(details::has_uniform_variables_correct_type, "Derived class of \"Program\" has member \"uniform_variables\" but its type is incorrect. " "Please use macro WEBGPU_PROGRAM_DEFINE_UNIFORM_VARIABLES() or WEBGPU_PROGRAM_EXTEND_UNIFORM_VARIABLES() to declare uniform variables."); + constexpr const ProgramUniformVariableDefinition* ptr = T::uniform_variables.data(); + constexpr size_t len = T::uniform_variables.size(); + metadata.uniform_variables = {ptr, len}; } else { metadata.uniform_variables = {}; @@ -599,20 +513,6 @@ class Program : public details::ProgramWrapper { }; namespace details { -// helper function to convert a C-style array to std::array -// -// This is basically the same as std::to_array in C++20. -// -template -constexpr auto _to_std_array_impl(T (&arr)[N], std::index_sequence) -> std::array, N> { - return {{arr[Idx]...}}; -} - -template -constexpr auto _to_std_array(T (&arr)[N]) -> std::array, N> { - return _to_std_array_impl(arr, std::make_index_sequence{}); -} - // helper function to concatenate a std::array and a C-style array to a std::array // template @@ -632,7 +532,7 @@ constexpr std::array, L + R> _concat2(const std::array #define WEBGPU_PROGRAM_DEFINE_(identifier, T, ...) \ static constexpr const T identifier##_own[] = {__VA_ARGS__}; \ static constexpr const auto identifier = \ - onnxruntime::webgpu::details::_to_std_array(identifier##_own) + std::to_array(identifier##_own) #define WEBGPU_PROGRAM_EXTEND_(identifier, T, BASE, ...) \ static constexpr const T identifier##_own[] = {__VA_ARGS__}; \ diff --git a/onnxruntime/core/providers/webgpu/program_test.cc b/onnxruntime/core/providers/webgpu/program_test.cc new file mode 100644 index 0000000000000..2a524cce7a756 --- /dev/null +++ b/onnxruntime/core/providers/webgpu/program_test.cc @@ -0,0 +1,146 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// Compile-time tests for the type detection utilities in program.h. +// These static_asserts verify that is_const_std_array, the has_member_* variable templates, +// and has_*_correct_type concepts correctly detect static const std::array members. + +#include "core/providers/webgpu/program.h" + +namespace onnxruntime { +namespace webgpu { +namespace details { +namespace test { + +// ============================================================================ +// Tests for is_const_std_array +// ============================================================================ + +static_assert(!is_const_std_array::value); +static_assert(!is_const_std_array::value); +static_assert(!is_const_std_array>::value); +static_assert(is_const_std_array>::value); +static_assert(is_const_std_array>::value); + +// ============================================================================ +// Tests for has_member_constants / has_constants_correct_type +// ============================================================================ + +struct NoMembers {}; +static_assert(!has_member_constants); +static_assert(!has_constants_correct_type); + +struct Constants_WrongName { + static constexpr std::array not_constants = {1}; +}; +static_assert(!has_member_constants); +static_assert(!has_constants_correct_type); + +struct Constants_PlainInt { + int constants; +}; +static_assert(has_member_constants); +static_assert(!has_constants_correct_type); + +struct Constants_ConstInt { + const int constants; +}; +static_assert(has_member_constants); +static_assert(!has_constants_correct_type); + +struct Constants_CArray { + const int constants[2]; +}; +static_assert(has_member_constants); +static_assert(!has_constants_correct_type); + +struct Constants_StaticCArray { + static constexpr int constants[] = {0}; +}; +static_assert(has_member_constants); +static_assert(!has_constants_correct_type); + +struct Constants_StaticNonConstCArray { + static int constants[]; +}; +static_assert(has_member_constants); +static_assert(!has_constants_correct_type); + +struct Constants_StaticConstCArray { + static const int constants[]; +}; +static_assert(has_member_constants); +static_assert(!has_constants_correct_type); + +struct Constants_NonConstStdArray { + std::array constants = {1}; +}; +static_assert(has_member_constants); +static_assert(!has_constants_correct_type); + +struct Constants_NonConstStaticStdArray { + static std::array constants; +}; +static_assert(has_member_constants); +static_assert(!has_constants_correct_type); + +struct Constants_StaticConstexprStdArray { + static constexpr std::array constants = {1, 2}; +}; +static_assert(has_member_constants); +static_assert(has_constants_correct_type); + +struct Constants_StaticConstStdArray { + static const std::array constants; +}; +static_assert(has_member_constants); +static_assert(has_constants_correct_type); + +struct Constants_StaticConstexprConstStdArray { + static constexpr const std::array constants = {1, 2, 3, 4}; +}; +static_assert(has_member_constants); +static_assert(has_constants_correct_type); + +// ============================================================================ +// Tests for has_member_overridable_constants / has_overridable_constants_correct_type +// ============================================================================ + +static_assert(!has_member_overridable_constants); +static_assert(!has_overridable_constants_correct_type); + +struct OverridableConstants_WrongType { + int overridable_constants; +}; +static_assert(has_member_overridable_constants); +static_assert(!has_overridable_constants_correct_type); + +struct OverridableConstants_Correct { + static constexpr std::array overridable_constants = {1}; +}; +static_assert(has_member_overridable_constants); +static_assert(has_overridable_constants_correct_type); + +// ============================================================================ +// Tests for has_member_uniform_variables / has_uniform_variables_correct_type +// ============================================================================ + +static_assert(!has_member_uniform_variables); +static_assert(!has_uniform_variables_correct_type); + +struct UniformVariables_WrongType { + int uniform_variables; +}; +static_assert(has_member_uniform_variables); +static_assert(!has_uniform_variables_correct_type); + +struct UniformVariables_Correct { + static constexpr std::array uniform_variables = {1}; +}; +static_assert(has_member_uniform_variables); +static_assert(has_uniform_variables_correct_type); + +} // namespace test +} // namespace details +} // namespace webgpu +} // namespace onnxruntime diff --git a/onnxruntime/core/providers/webgpu/reduction/reduction_ops.cc b/onnxruntime/core/providers/webgpu/reduction/reduction_ops.cc index 4b23f6fc67669..db51675e81513 100644 --- a/onnxruntime/core/providers/webgpu/reduction/reduction_ops.cc +++ b/onnxruntime/core/providers/webgpu/reduction/reduction_ops.cc @@ -187,7 +187,7 @@ std::unordered_map reduce_op_naive_code_map }; ReduceOpType StringToReduceOp(std::string name) { - ORT_ENFORCE(reduce_op_types.find(name) != reduce_op_types.end(), "Unsupported reduction op type: ", name); + ORT_ENFORCE(reduce_op_types.contains(name), "Unsupported reduction op type: ", name); return reduce_op_types[name]; } diff --git a/onnxruntime/core/providers/webgpu/reduction/reduction_ops.h b/onnxruntime/core/providers/webgpu/reduction/reduction_ops.h index 53abff9ca30c9..6958b52a6c880 100644 --- a/onnxruntime/core/providers/webgpu/reduction/reduction_ops.h +++ b/onnxruntime/core/providers/webgpu/reduction/reduction_ops.h @@ -17,12 +17,12 @@ namespace webgpu { // The first element is the loop header, the second element is the loop body, and the third element is the loop footer. // The loop header is the code that is executed before the loop starts. The loop body is the code that is executed for each element in the loop. // The loop footer is the code that is executed after the loop ends. The loop body should contain the code that accumulates the result of the reduction and -// the loop footer should contain the code that assigins output_value the result of the reduction. -typedef struct ReduceOpSpecificCode { +// the loop footer should contain the code that assigns output_value the result of the reduction. +struct ReduceOpSpecificCode { std::string loop_header_; std::string loop_body_; std::string loop_footer_; -} ReduceOpSpecificCode; +}; enum class ReduceOpType { Max, diff --git a/onnxruntime/core/providers/webgpu/shader_helper.cc b/onnxruntime/core/providers/webgpu/shader_helper.cc index 07e9e9e793c56..657fc3a6f45ad 100644 --- a/onnxruntime/core/providers/webgpu/shader_helper.cc +++ b/onnxruntime/core/providers/webgpu/shader_helper.cc @@ -499,7 +499,7 @@ Status ShaderHelper::GenerateSourceCode(std::string& code, std::vector& sha // store shape uniform ranks in shape_uniform_ranks bool use_any_shape_uniform = false; - ORT_ENFORCE(shape_uniform_ranks.size() == 0); + ORT_ENFORCE(shape_uniform_ranks.empty()); shape_uniform_ranks.reserve(input_vars_.size() + output_vars_.size() + indices_vars_.size()); for (const auto& input : input_vars_) { diff --git a/onnxruntime/core/providers/webgpu/shader_variable.cc b/onnxruntime/core/providers/webgpu/shader_variable.cc index 611a75065d509..57a90c972b228 100644 --- a/onnxruntime/core/providers/webgpu/shader_variable.cc +++ b/onnxruntime/core/providers/webgpu/shader_variable.cc @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +#include #include #include #include @@ -39,7 +40,7 @@ constexpr static const std::string_view STORAGE_TYPE_ARRAY[] = { "u32", // Uint4x8 "u32", // Int4x8 }; -constexpr static const auto STORAGE_TYPE = details::_to_std_array(STORAGE_TYPE_ARRAY); +constexpr static const auto STORAGE_TYPE = std::to_array(STORAGE_TYPE_ARRAY); constexpr static const std::string_view VALUE_TYPE_ARRAY[] = { "f32", // Float32 @@ -66,7 +67,7 @@ constexpr static const std::string_view VALUE_TYPE_ARRAY[] = { "u32", // Uint4x8 "u32", // Int4x8 }; -constexpr static const auto VALUE_TYPE = details::_to_std_array(VALUE_TYPE_ARRAY); +constexpr static const auto VALUE_TYPE = std::to_array(VALUE_TYPE_ARRAY); constexpr static const std::string_view ELEMENT_TYPE_ARRAY[] = { "f32", // Float32 @@ -93,7 +94,7 @@ constexpr static const std::string_view ELEMENT_TYPE_ARRAY[] = { "u32", // Uint4x8 "i32", // Int4x8 }; -constexpr static const auto ELEMENT_TYPE = details::_to_std_array(ELEMENT_TYPE_ARRAY); +constexpr static const auto ELEMENT_TYPE = std::to_array(ELEMENT_TYPE_ARRAY); constexpr static const uint32_t BYTES_ARRAY[] = { 4, // Float32 @@ -120,7 +121,7 @@ constexpr static const uint32_t BYTES_ARRAY[] = { 4, // Uint4x8 (packed in u32) 4, // Int4x8 (packed in u32) }; -constexpr static const auto BYTES = details::_to_std_array(BYTES_ARRAY); +constexpr static const auto BYTES = std::to_array(BYTES_ARRAY); inline std::string GetIndicesType(int rank) { return rank < 2 ? "u32" diff --git a/onnxruntime/core/providers/webgpu/shader_variable.h b/onnxruntime/core/providers/webgpu/shader_variable.h index c62eff0209df8..c50453c9b23f0 100644 --- a/onnxruntime/core/providers/webgpu/shader_variable.h +++ b/onnxruntime/core/providers/webgpu/shader_variable.h @@ -14,8 +14,8 @@ namespace onnxruntime { namespace webgpu { template || std::is_same_v>> + typename TRank> + requires(std::is_same_v || std::is_same_v) std::string GetElementAt(std::string_view var, const TIdx& idx, TRank rank, bool is_f16 = false) { if (var.starts_with("uniforms.")) { if (is_f16) { @@ -210,32 +210,25 @@ class ShaderVariableHelper : public ShaderIndicesHelper { friend class ShaderHelper; }; -#if defined(__GNUC__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wstrict-aliasing" -#endif inline ShaderUsage operator|(ShaderUsage a, ShaderUsage b) { - return (uint32_t)a.usage | (uint32_t)b.usage; + return static_cast(a.usage) | static_cast(b.usage); } inline ShaderUsage operator&(ShaderUsage a, ShaderUsage b) { - return (uint32_t)a.usage & (uint32_t)b.usage; + return static_cast(a.usage) & static_cast(b.usage); } inline ShaderUsage& operator|=(ShaderUsage& a, ShaderUsage b) { - (uint32_t&)a.usage |= (uint32_t)b.usage; + a = a | b; return a; } inline ShaderUsage& operator&=(ShaderUsage& a, ShaderUsage b) { - (uint32_t&)a.usage &= (uint32_t)b.usage; + a = a & b; return a; } -#if defined(__GNUC__) -#pragma GCC diagnostic pop -#endif - namespace detail { -template >> +template + requires std::is_integral_v std::string pass_as_string(T&& v) { return std::to_string(std::forward(v)); } diff --git a/onnxruntime/core/providers/webgpu/string_utils.h b/onnxruntime/core/providers/webgpu/string_utils.h index 1ed65fbc8d509..cc96d8482fe2b 100644 --- a/onnxruntime/core/providers/webgpu/string_utils.h +++ b/onnxruntime/core/providers/webgpu/string_utils.h @@ -75,8 +75,8 @@ class FastOStringStream { // Integer types template - std::enable_if_t && !std::is_same_v, FastOStringStream&> - operator<<(T value) { + requires(std::is_integral_v && !std::is_same_v) + FastOStringStream& operator<<(T value) { std::array buffer; auto [ptr, ec] = std::to_chars(buffer.data(), buffer.data() + buffer.size(), value); str_.append(buffer.data(), ptr - buffer.data()); @@ -85,8 +85,8 @@ class FastOStringStream { // Floating point types template - std::enable_if_t, FastOStringStream&> - operator<<(T value) { + requires std::is_floating_point_v + FastOStringStream& operator<<(T value) { std::array buffer; auto [ptr, ec] = std::to_chars(buffer.data(), buffer.data() + buffer.size(), value); str_.append(buffer.data(), ptr - buffer.data()); diff --git a/onnxruntime/core/providers/webgpu/tensor/split.cc b/onnxruntime/core/providers/webgpu/tensor/split.cc index 25d829c4e8bad..43de5cc4d32d5 100644 --- a/onnxruntime/core/providers/webgpu/tensor/split.cc +++ b/onnxruntime/core/providers/webgpu/tensor/split.cc @@ -82,7 +82,7 @@ Status Split::ComputeInternal(ComputeContext& context) const { split_sizes.assign(split_sizes_.begin(), split_sizes_.end()); // Compute split_sizes from the 'split' input tensor. - if (split_sizes_.size() == 0 && context.InputCount() > 1) { + if (split_sizes_.empty() && context.InputCount() > 1) { const Tensor* split_tensor = context.Input(1); // Check if split_tensor is valid. if (split_tensor != nullptr) { diff --git a/onnxruntime/core/providers/webgpu/tensor/upsample.cc b/onnxruntime/core/providers/webgpu/tensor/upsample.cc index 8f51ed45004bf..9b88731832fc4 100644 --- a/onnxruntime/core/providers/webgpu/tensor/upsample.cc +++ b/onnxruntime/core/providers/webgpu/tensor/upsample.cc @@ -19,7 +19,7 @@ Status Upsample::BaseCompute(ComputeContext& context, auto dims = X->Shape().GetDims(); ORT_ENFORCE(output_dims.size() == dims.size(), "Rank of input and output tensor should be same."); - if (dims.size() == 0) { + if (dims.empty()) { return Status(ONNXRUNTIME, INVALID_ARGUMENT, is_resize_ ? "Resize: input tensor cannot be scalar." : "Upsample: input tensor cannot be scalar."); diff --git a/onnxruntime/core/providers/webgpu/webgpu_context.cc b/onnxruntime/core/providers/webgpu/webgpu_context.cc index ec20bf2fdbdfb..ada9a2e8ab692 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_context.cc +++ b/onnxruntime/core/providers/webgpu/webgpu_context.cc @@ -86,7 +86,7 @@ void WebGpuContext::Initialize(const WebGpuContextConfig& config) { #endif std::vector required_features = GetAvailableRequiredFeatures(adapter); - if (required_features.size() > 0) { + if (!required_features.empty()) { device_desc.requiredFeatures = required_features.data(); device_desc.requiredFeatureCount = required_features.size(); } @@ -188,7 +188,7 @@ Status WebGpuContext::Run(ComputeContextBase& context, const ProgramBase& progra const auto& inputs = program.Inputs(); const auto& outputs = program.Outputs(); - if (outputs.size() == 0) { + if (outputs.empty()) { return Status::OK(); } diff --git a/onnxruntime/core/providers/webgpu/webgpu_context.h b/onnxruntime/core/providers/webgpu/webgpu_context.h index 10a5f278df88a..021c7f383a6d7 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_context.h +++ b/onnxruntime/core/providers/webgpu/webgpu_context.h @@ -170,7 +170,7 @@ class WebGpuContext final { const wgpu::AdapterInfo& AdapterInfo() const { return adapter_info_; } const wgpu::Limits& DeviceLimits() const { return device_limits_; } - bool DeviceHasFeature(wgpu::FeatureName feature) const { return device_features_.find(feature) != device_features_.end(); } + bool DeviceHasFeature(wgpu::FeatureName feature) const { return device_features_.contains(feature); } #if !defined(__wasm__) const wgpu::AdapterPropertiesSubgroupMatrixConfigs& SubgroupMatrixConfigs() const { return subgroup_matrix_configs_; } #endif diff --git a/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc b/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc index 28e207a9aa598..0cee96d41ce68 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc +++ b/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc @@ -1031,7 +1031,7 @@ std::vector> WebGpuExecutionProvider::GetCapa auto cpu_nodes = GetCpuPreferredNodes(graph, kernel_lookup, tenative_candidates, *GetLogger()); std::vector> result; for (auto& node_index : candidates) { - if (cpu_nodes.count(node_index) > 0) { + if (cpu_nodes.contains(node_index)) { continue; }