diff --git a/onnxruntime/core/providers/webgpu/webgpu_context.cc b/onnxruntime/core/providers/webgpu/webgpu_context.cc index f2c2b0e99c1c8..0e4004db35b10 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_context.cc +++ b/onnxruntime/core/providers/webgpu/webgpu_context.cc @@ -43,7 +43,7 @@ void WebGpuContext::Initialize(const WebGpuBufferCacheConfig& buffer_cache_confi // Create wgpu::Adapter wgpu::RequestAdapterOptions req_adapter_options = {}; req_adapter_options.backendType = static_cast(backend_type); - req_adapter_options.powerPreference = wgpu::PowerPreference::HighPerformance; + req_adapter_options.powerPreference = static_cast(power_preference_); #if !defined(__wasm__) auto enabled_adapter_toggles = GetEnabledAdapterToggles(); @@ -955,7 +955,7 @@ WebGpuContext& WebGpuContextFactory::CreateContext(const WebGpuContextConfig& co auto it = contexts_.find(context_id); if (it == contexts_.end()) { GSL_SUPPRESS(r.11) - auto context = std::unique_ptr(new WebGpuContext(instance, device, config.validation_mode, config.preserve_device, config.small_storage_buffer_binding_size_for_testing)); + auto context = std::unique_ptr(new WebGpuContext(instance, device, config.validation_mode, config.preserve_device, config.small_storage_buffer_binding_size_for_testing, config.power_preference)); it = contexts_.emplace(context_id, WebGpuContextFactory::WebGpuContextInfo{std::move(context), 0}).first; } else if (context_id != 0) { ORT_ENFORCE(it->second.context->instance_.Get() == instance && diff --git a/onnxruntime/core/providers/webgpu/webgpu_context.h b/onnxruntime/core/providers/webgpu/webgpu_context.h index e21a0e577311f..f1bebc0d52738 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_context.h +++ b/onnxruntime/core/providers/webgpu/webgpu_context.h @@ -41,6 +41,7 @@ struct WebGpuContextConfig { ValidationMode validation_mode; bool preserve_device; bool small_storage_buffer_binding_size_for_testing; + int power_preference; }; struct WebGpuBufferCacheConfig { @@ -177,8 +178,8 @@ class WebGpuContext final { AtPasses }; - WebGpuContext(WGPUInstance instance, WGPUDevice device, webgpu::ValidationMode validation_mode, bool preserve_device, bool small_storage_buffer_binding_size_for_testing = false) - : instance_{instance}, device_{device}, validation_mode_{validation_mode}, query_type_{TimestampQueryType::None}, preserve_device_{preserve_device}, small_storage_buffer_binding_size_for_testing_{small_storage_buffer_binding_size_for_testing} {} + WebGpuContext(WGPUInstance instance, WGPUDevice device, webgpu::ValidationMode validation_mode, bool preserve_device, bool small_storage_buffer_binding_size_for_testing = false, int power_preference = static_cast(wgpu::PowerPreference::HighPerformance)) + : instance_{instance}, device_{device}, validation_mode_{validation_mode}, query_type_{TimestampQueryType::None}, preserve_device_{preserve_device}, small_storage_buffer_binding_size_for_testing_{small_storage_buffer_binding_size_for_testing}, power_preference_{power_preference} {} ORT_DISALLOW_COPY_ASSIGNMENT_AND_MOVE(WebGpuContext); void LaunchComputePipeline(const wgpu::ComputePassEncoder& compute_pass_encoder, @@ -267,6 +268,7 @@ class WebGpuContext final { bool is_profiling_ = false; bool preserve_device_; bool small_storage_buffer_binding_size_for_testing_; + int power_preference_; GraphCaptureState graph_capture_state_{GraphCaptureState::Default}; // External vector to store captured commands, owned by EP diff --git a/onnxruntime/core/providers/webgpu/webgpu_provider_factory.cc b/onnxruntime/core/providers/webgpu/webgpu_provider_factory.cc index 60934bef574fa..efd3cf08364f9 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_provider_factory.cc +++ b/onnxruntime/core/providers/webgpu/webgpu_provider_factory.cc @@ -168,6 +168,20 @@ std::shared_ptr WebGpuProviderFactoryCreator::Create( } LOGS_DEFAULT(VERBOSE) << "WebGPU EP small storage buffer binding size for testing: " << small_storage_buffer_binding_size_for_testing; + // power preference + int power_preference = static_cast(WGPUPowerPreference_HighPerformance); // default + std::string power_preference_str; + if (config_options.TryGetConfigEntry(kPowerPreference, power_preference_str)) { + if (power_preference_str == kPowerPreference_HighPerformance) { + power_preference = static_cast(WGPUPowerPreference_HighPerformance); + } else if (power_preference_str == kPowerPreference_LowPower) { + power_preference = static_cast(WGPUPowerPreference_LowPower); + } else { + ORT_THROW("Invalid power preference: ", power_preference_str); + } + } + LOGS_DEFAULT(VERBOSE) << "WebGPU EP power preference: " << power_preference; + webgpu::WebGpuContextConfig context_config{ context_id, reinterpret_cast(webgpu_instance), @@ -176,6 +190,7 @@ std::shared_ptr WebGpuProviderFactoryCreator::Create( validation_mode, preserve_device, small_storage_buffer_binding_size_for_testing, + power_preference, }; LOGS_DEFAULT(VERBOSE) << "WebGPU EP Device ID: " << context_id; @@ -184,6 +199,7 @@ std::shared_ptr WebGpuProviderFactoryCreator::Create( LOGS_DEFAULT(VERBOSE) << "WebGPU EP DawnProcTable: " << dawn_proc_table; LOGS_DEFAULT(VERBOSE) << "WebGPU EP ValidationMode: " << validation_mode; LOGS_DEFAULT(VERBOSE) << "WebGPU EP PreserveDevice: " << preserve_device; + LOGS_DEFAULT(VERBOSE) << "WebGPU EP PowerPreference: " << power_preference; // // STEP.3 - prepare parameters for WebGPU context initialization. diff --git a/onnxruntime/core/providers/webgpu/webgpu_provider_options.h b/onnxruntime/core/providers/webgpu/webgpu_provider_options.h index 761ff0d85fc98..a2ecd7f21f618 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_provider_options.h +++ b/onnxruntime/core/providers/webgpu/webgpu_provider_options.h @@ -15,6 +15,7 @@ constexpr const char* kEnableGraphCapture = "ep.webgpuexecutionprovider.enableGr constexpr const char* kDawnProcTable = "ep.webgpuexecutionprovider.dawnProcTable"; constexpr const char* kDawnBackendType = "ep.webgpuexecutionprovider.dawnBackendType"; +constexpr const char* kPowerPreference = "ep.webgpuexecutionprovider.powerPreference"; constexpr const char* kDeviceId = "ep.webgpuexecutionprovider.deviceId"; constexpr const char* kWebGpuInstance = "ep.webgpuexecutionprovider.webgpuInstance"; @@ -39,6 +40,9 @@ constexpr const char* kSmallStorageBufferBindingSizeForTesting = "ep.webgpuexecu constexpr const char* kDawnBackendType_D3D12 = "D3D12"; constexpr const char* kDawnBackendType_Vulkan = "Vulkan"; +constexpr const char* kPowerPreference_HighPerformance = "high-performance"; +constexpr const char* kPowerPreference_LowPower = "low-power"; + constexpr const char* kPreferredLayout_NCHW = "NCHW"; constexpr const char* kPreferredLayout_NHWC = "NHWC";