0

webnn: Switch to runtime flag to disable Core ML backend

This enables testing the TFLite backend on macOS without rebuilding
Chrome.

Bug: 394119734
Change-Id: I31a0715a46c27a13f1046f618c69b72d9f4d98fd
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6240633
Auto-Submit: Reilly Grant <reillyg@chromium.org>
Reviewed-by: Will Harris <wfh@chromium.org>
Commit-Queue: Reilly Grant <reillyg@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1417095}
This commit is contained in:
Reilly Grant
2025-02-06 17:06:19 -08:00
committed by Chromium LUCI CQ
parent 07fb32b93c
commit 47fed4067a
10 changed files with 56 additions and 34 deletions

@ -8329,6 +8329,12 @@ const FeatureEntry kFeatureEntries[] = {
FEATURE_VALUE_TYPE(
webnn::mojom::features::kExperimentalWebMachineLearningNeuralNetwork)},
#if BUILDFLAG(IS_MAC)
{"webnn-coreml", flag_descriptions::kWebNNCoreMLName,
flag_descriptions::kWebNNCoreMLDescription, kOsMac,
FEATURE_VALUE_TYPE(webnn::mojom::features::kWebNNCoreML)},
#endif // BUILDFLAG(IS_MAC)
#if BUILDFLAG(IS_WIN)
{"webnn-directml", flag_descriptions::kWebNNDirectMLName,
flag_descriptions::kWebNNDirectMLDescription, kOsWin,

@ -9281,6 +9281,11 @@
"owners": [ "mhochk@microsoft.com", "ericwilligers@google.com", "hatalat@microsoft.com" ],
"expiry_milestone": 135
},
{
"name": "webnn-coreml",
"owners": [ "reillyg@chromium.org", "phillis@chromium.org" ],
"expiry_milestone": 146
},
{
"name": "webnn-directml",
"owners": [ "reillyg@chromium.org", "rafael.cintron@microsoft.com" ],

@ -2459,6 +2459,12 @@ const char kExperimentalWebMachineLearningNeuralNetworkDescription[] =
"Enables additional, experimental features in Web Machine Learning Neural "
"Network (WebNN) API. Requires the \"WebNN API\" flag to be enabled.";
const char kWebNNCoreMLName[] = "Core ML backend for WebNN";
const char kWebNNCoreMLDescription[] =
"Enables using Core ML for GPU and "
"NPU inference with the WebNN API. Disabling this flag enables a "
"fallback to TFLite.";
const char kWebNNDirectMLName[] = "DirectML backend for WebNN";
const char kWebNNDirectMLDescription[] =
"Enables using DirectML for GPU and "

@ -1417,6 +1417,9 @@ extern const char kWebMachineLearningNeuralNetworkDescription[];
extern const char kExperimentalWebMachineLearningNeuralNetworkName[];
extern const char kExperimentalWebMachineLearningNeuralNetworkDescription[];
extern const char kWebNNCoreMLName[];
extern const char kWebNNCoreMLDescription[];
extern const char kWebNNDirectMLName[];
extern const char kWebNNDirectMLDescription[];

@ -12,7 +12,6 @@ import("//third_party/tflite/features.gni")
buildflag_header("buildflags") {
header = "buildflags.h"
flags = [
"WEBNN_USE_COREML=$webnn_use_coreml",
"WEBNN_USE_TFLITE=$webnn_use_tflite",
"WEBNN_ENABLE_TFLITE_PROFILER=$webnn_enable_tflite_profiler",
]
@ -91,8 +90,7 @@ component("webnn_service") {
libs = [ "dxgi.lib" ]
}
if (webnn_use_coreml) {
assert(is_mac)
if (is_mac) {
sources += [
"coreml/buffer_content_coreml.h",
"coreml/buffer_content_coreml.mm",
@ -147,15 +145,13 @@ component("webnn_service") {
}
if (enable_ml_internal) {
deps += [
"//services/on_device_model/ml",
]
deps += [ "//services/on_device_model/ml" ]
defines += [ "ENABLE_ML_INTERNAL" ]
}
}
if (webnn_use_coreml || webnn_use_tflite) {
if (is_mac || webnn_use_tflite) {
sources += [
"queueable_resource_state.h",
"queueable_resource_state_base.cc",
@ -191,7 +187,7 @@ source_set("tests") {
]
}
if (webnn_use_coreml || webnn_use_tflite || is_win) {
if (webnn_use_tflite || is_mac || is_win) {
sources += [
"webnn_graph_impl_backend_test.cc",
"webnn_tensor_impl_backend_test.cc",

@ -5,11 +5,8 @@
import("//build/config/features.gni")
declare_args() {
# Enable the Core ML backend by default on macOS. This flag allows it to be
# disabled for testing.
webnn_use_coreml = is_mac
webnn_use_tflite = is_android || is_chromeos || is_linux || is_win
# TFLite is used as a fallback option on macOS and Windows.
webnn_use_tflite = is_android || is_chromeos || is_linux || is_mac || is_win
# Enable logging of TFLite profiling information on MLGraph destruction.
webnn_enable_tflite_profiler = false

@ -17,7 +17,15 @@ feature kExperimentalWebMachineLearningNeuralNetwork {
const bool default_state = false;
};
// Enables the Core ML backend for WebNN.
[EnableIf=is_mac]
feature kWebNNCoreML {
const string name = "WebNNCoreML";
const bool default_state = true;
};
// Enables the DirectML backend for WebNN.
[EnableIf=is_win]
feature kWebNNDirectML {
const string name = "WebNNDirectML";
const bool default_state = true;

@ -30,7 +30,7 @@
#include "services/webnn/dml/utils.h"
#endif
#if BUILDFLAG(WEBNN_USE_COREML)
#if BUILDFLAG(IS_MAC)
#include "services/webnn/coreml/context_impl_coreml.h"
#endif
@ -288,14 +288,14 @@ void WebNNContextProviderImpl::CreateWebNNContext(
}
#endif // BUILDFLAG(IS_WIN)
#if BUILDFLAG(WEBNN_USE_COREML)
// TODO: crbug.com/325612086 - Consider using supporting older Macs either
// with TFLite or a more restrictive implementation on CoreML.
#if BUILDFLAG(IS_MAC)
if (__builtin_available(macOS 14, *)) {
context_impl = new coreml::ContextImplCoreml(std::move(receiver), this,
std::move(options));
if (base::FeatureList::IsEnabled(mojom::features::kWebNNCoreML)) {
context_impl = new coreml::ContextImplCoreml(std::move(receiver), this,
std::move(options));
}
}
#endif // BUILDFLAG(WEBNN_USE_COREML)
#endif // BUILDFLAG(IS_MAC)
#if BUILDFLAG(WEBNN_USE_TFLITE)
if (!context_impl) {

@ -264,14 +264,14 @@ struct OperandInfo {
OperandDataType type;
std::vector<uint32_t> dimensions;
std::vector<T> values;
#if BUILDFLAG(WEBNN_USE_COREML)
#if BUILDFLAG(IS_MAC)
OperandInfo<int32_t> ToInt32() {
return OperandInfo<int32_t>{
.type = OperandDataType::kInt32,
.dimensions = dimensions,
.values = std::vector<int32_t>(values.begin(), values.end())};
}
#endif // BUILDFLAG(WEBNN_USE_COREML)
#endif // BUILDFLAG(IS_MAC)
};
void VerifyIsEqual(base::span<const float> actual,
@ -376,7 +376,7 @@ void WebNNGraphImplBackendTest::SetUp() {
}
#endif // #if BUILDFLAG(IS_WIN)
#if BUILDFLAG(WEBNN_USE_COREML)
#if BUILDFLAG(IS_MAC)
class WebNNGraphImplBackendTest : public testing::Test {
public:
WebNNGraphImplBackendTest()
@ -420,11 +420,10 @@ void WebNNGraphImplBackendTest::SetUp() {
SetUpBase();
}
#endif // BUILDFLAG(WEBNN_USE_COREML)
#endif // BUILDFLAG(IS_MAC)
// TODO(crbug.com/325612086): Parameterize these tests for different backends.
#if BUILDFLAG(WEBNN_USE_TFLITE) && !BUILDFLAG(WEBNN_USE_COREML) && \
!BUILDFLAG(IS_WIN)
#if BUILDFLAG(WEBNN_USE_TFLITE) && !BUILDFLAG(IS_MAC) && !BUILDFLAG(IS_WIN)
class WebNNGraphImplBackendTest : public testing::Test {
public:
WebNNGraphImplBackendTest()
@ -1055,32 +1054,32 @@ struct ElementWiseBinaryTester {
uint64_t rhs_operand_id =
builder.BuildInput("rhs", rhs.dimensions, rhs.type);
auto graph_output_type = output.type;
#if BUILDFLAG(WEBNN_USE_COREML)
#if BUILDFLAG(IS_MAC)
if (output.type == OperandDataType::kUint8) {
// macOS only supports FP16,FP32,DOUBLE,INT32 as outputs of graph.
// For testing, we cast the output of the element-wise logical
// operators to Int32 and set the graph output to Int32.
graph_output_type = OperandDataType::kInt32;
}
#endif // BUILDFLAG(WEBNN_USE_COREML)
#endif // BUILDFLAG(IS_MAC)
uint64_t output_operand_id =
builder.BuildOutput("output", output.dimensions, graph_output_type);
uint64_t element_wise_binary_output_operand_id = output_operand_id;
#if BUILDFLAG(WEBNN_USE_COREML)
#if BUILDFLAG(IS_MAC)
if (output.type == OperandDataType::kUint8) {
element_wise_binary_output_operand_id = builder.BuildIntermediateOperand(
output.dimensions, OperandDataType::kUint8);
}
#endif // BUILDFLAG(WEBNN_USE_COREML)
#endif // BUILDFLAG(IS_MAC)
builder.BuildElementWiseBinary(kind, lhs_operand_id, rhs_operand_id,
element_wise_binary_output_operand_id);
#if BUILDFLAG(WEBNN_USE_COREML)
#if BUILDFLAG(IS_MAC)
if (output.type == OperandDataType::kUint8) {
builder.BuildElementWiseUnary(mojom::ElementWiseUnary::Kind::kCast,
element_wise_binary_output_operand_id,
output_operand_id);
}
#endif // BUILDFLAG(WEBNN_USE_COREML)
#endif // BUILDFLAG(IS_MAC)
base::flat_map<std::string, base::span<const I>> named_inputs;
named_inputs.insert({"lhs", lhs.values});
@ -1089,12 +1088,12 @@ struct ElementWiseBinaryTester {
BuildAndCompute<O>(std::move(remote), builder.TakeGraphInfo(),
std::move(named_inputs));
#if BUILDFLAG(WEBNN_USE_COREML)
#if BUILDFLAG(IS_MAC)
if (output.type == OperandDataType::kUint8) {
VerifyIsEqual(named_outputs["output"], output.ToInt32());
return;
}
#endif // BUILDFLAG(WEBNN_USE_COREML)
#endif // BUILDFLAG(IS_MAC)
VerifyIsEqual(named_outputs["output"], output);
}

@ -10790,6 +10790,7 @@ from previous Chrome versions.
<int value="-1321640296"
label="AutofillDownstreamCvcPromptUseGooglePayLogo:enabled"/>
<int value="-1321212159" label="MediaAppAnnotation:enabled"/>
<int value="-1320724945" label="WebNNCoreML:disabled"/>
<int value="-1319688939" label="ignore-gpu-blacklist"/>
<int value="-1318914924" label="OverflowIconsForMediaControls:enabled"/>
<int value="-1317782739" label="OmniboxAsyncViewInflation:enabled"/>
@ -19062,6 +19063,7 @@ from previous Chrome versions.
<int value="1927259098" label="TranslateLanguageByULP:enabled"/>
<int value="1927374573" label="EnterpriseRealtimeExtensionRequest:enabled"/>
<int value="1927572319" label="OmniboxShortcutExpanding:enabled"/>
<int value="1928193837" label="WebNNCoreML:enabled"/>
<int value="1928641476" label="enable-builtin-hls:disabled"/>
<int value="1928944156" label="ReadLaterNewBadgePromo:disabled"/>
<int value="1929174284" label="ChromeManagementPageAndroid:disabled"/>