junwei | d4ed5a81 | 2023-04-19 03:19:26 | [diff] [blame] | 1 | // Copyright 2023 The Chromium Authors |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #include "services/webnn/webnn_context_provider_impl.h" |
| 6 | |
| 7 | #include <memory> |
| 8 | #include <utility> |
| 9 | |
| 10 | #include "mojo/public/cpp/bindings/self_owned_receiver.h" |
Shiyi Zou | ff06a31 | 2023-09-15 05:18:05 | [diff] [blame] | 11 | #include "services/webnn/error.h" |
mingmingtasd | afe5ad4 | 2024-01-05 07:09:55 | [diff] [blame] | 12 | #include "services/webnn/public/mojom/webnn_error.mojom.h" |
junwei | d4ed5a81 | 2023-04-19 03:19:26 | [diff] [blame] | 13 | #include "services/webnn/webnn_context_impl.h" |
| 14 | |
Ningxin Hu | c8a5ff6 | 2023-08-04 03:53:28 | [diff] [blame] | 15 | #if BUILDFLAG(IS_WIN) |
| 16 | #include "services/webnn/dml/adapter.h" |
| 17 | #include "services/webnn/dml/context_impl.h" |
| 18 | #endif |
| 19 | |
sushraja | 189e93e | 2024-01-31 22:39:39 | [diff] [blame] | 20 | #if BUILDFLAG(IS_MAC) |
| 21 | #include "services/webnn/coreml/context_impl.h" |
| 22 | #endif |
| 23 | |
junwei | d4ed5a81 | 2023-04-19 03:19:26 | [diff] [blame] | 24 | namespace webnn { |
| 25 | |
| 26 | namespace { |
| 27 | |
junwei | 40fca56 | 2023-08-16 05:39:11 | [diff] [blame] | 28 | WebNNContextProviderImpl::BackendForTesting* g_backend_for_testing = nullptr; |
| 29 | |
junwei | d4ed5a81 | 2023-04-19 03:19:26 | [diff] [blame] | 30 | using webnn::mojom::CreateContextOptionsPtr; |
| 31 | using webnn::mojom::WebNNContextProvider; |
| 32 | |
| 33 | } // namespace |
| 34 | |
| 35 | WebNNContextProviderImpl::WebNNContextProviderImpl() = default; |
| 36 | |
| 37 | WebNNContextProviderImpl::~WebNNContextProviderImpl() = default; |
| 38 | |
| 39 | // static |
| 40 | void WebNNContextProviderImpl::Create( |
| 41 | mojo::PendingReceiver<WebNNContextProvider> receiver) { |
| 42 | mojo::MakeSelfOwnedReceiver<WebNNContextProvider>( |
| 43 | std::make_unique<WebNNContextProviderImpl>(), std::move(receiver)); |
| 44 | } |
| 45 | |
junwei | 3a4fa10 | 2023-05-30 03:37:20 | [diff] [blame] | 46 | void WebNNContextProviderImpl::OnConnectionError(WebNNContextImpl* impl) { |
| 47 | auto it = |
| 48 | base::ranges::find(impls_, impl, &std::unique_ptr<WebNNContextImpl>::get); |
| 49 | CHECK(it != impls_.end()); |
| 50 | impls_.erase(it); |
| 51 | } |
| 52 | |
junwei | 40fca56 | 2023-08-16 05:39:11 | [diff] [blame] | 53 | // static |
| 54 | void WebNNContextProviderImpl::SetBackendForTesting( |
| 55 | BackendForTesting* backend_for_testing) { |
| 56 | g_backend_for_testing = backend_for_testing; |
| 57 | } |
| 58 | |
junwei | d4ed5a81 | 2023-04-19 03:19:26 | [diff] [blame] | 59 | void WebNNContextProviderImpl::CreateWebNNContext( |
| 60 | CreateContextOptionsPtr options, |
| 61 | WebNNContextProvider::CreateWebNNContextCallback callback) { |
junwei | 40fca56 | 2023-08-16 05:39:11 | [diff] [blame] | 62 | if (g_backend_for_testing) { |
| 63 | g_backend_for_testing->CreateWebNNContext(impls_, this, std::move(options), |
| 64 | std::move(callback)); |
| 65 | return; |
| 66 | } |
| 67 | |
junwei | d4ed5a81 | 2023-04-19 03:19:26 | [diff] [blame] | 68 | #if BUILDFLAG(IS_WIN) |
Ningxin Hu | c8a5ff6 | 2023-08-04 03:53:28 | [diff] [blame] | 69 | // Get the default `Adapter` instance which is created for the adapter queried |
| 70 | // from ANGLE. At the current stage, all `ContextImpl` share this instance. |
| 71 | // |
| 72 | // TODO(crbug.com/1469755): Support getting `Adapter` instance based on |
| 73 | // `options`. |
Bryan Bernhart | 6e27fa16 | 2023-08-16 18:05:27 | [diff] [blame] | 74 | constexpr DML_FEATURE_LEVEL kMinDMLFeatureLevelForWebNN = |
| 75 | DML_FEATURE_LEVEL_4_0; |
mingmingtasd | a242540 | 2023-11-28 03:56:38 | [diff] [blame] | 76 | auto adapter_creation_result = |
Bryan Bernhart | 6e27fa16 | 2023-08-16 18:05:27 | [diff] [blame] | 77 | dml::Adapter::GetInstance(kMinDMLFeatureLevelForWebNN); |
mingmingtasd | a242540 | 2023-11-28 03:56:38 | [diff] [blame] | 78 | if (!adapter_creation_result.has_value()) { |
| 79 | std::move(callback).Run(mojom::CreateContextResult::NewError( |
| 80 | std::move(adapter_creation_result.error()))); |
Ningxin Hu | c8a5ff6 | 2023-08-04 03:53:28 | [diff] [blame] | 81 | return; |
| 82 | } |
junwei | d4ed5a81 | 2023-04-19 03:19:26 | [diff] [blame] | 83 | // The remote sent to the renderer. |
| 84 | mojo::PendingRemote<mojom::WebNNContext> blink_remote; |
| 85 | // The receiver bound to WebNNContextImpl. |
Ningxin Hu | c8a5ff6 | 2023-08-04 03:53:28 | [diff] [blame] | 86 | impls_.push_back(base::WrapUnique<WebNNContextImpl>(new dml::ContextImpl( |
mingmingtasd | a242540 | 2023-11-28 03:56:38 | [diff] [blame] | 87 | std::move(adapter_creation_result.value()), |
| 88 | blink_remote.InitWithNewPipeAndPassReceiver(), this))); |
Shiyi Zou | ff06a31 | 2023-09-15 05:18:05 | [diff] [blame] | 89 | std::move(callback).Run( |
| 90 | mojom::CreateContextResult::NewContextRemote(std::move(blink_remote))); |
sushraja | 189e93e | 2024-01-31 22:39:39 | [diff] [blame] | 91 | #elif BUILDFLAG(IS_MAC) |
| 92 | if (__builtin_available(macOS 13, *)) { |
| 93 | // The remote sent to the renderer. |
| 94 | mojo::PendingRemote<mojom::WebNNContext> blink_remote; |
| 95 | // The receiver bound to WebNNContextImpl. |
| 96 | impls_.push_back(base::WrapUnique<WebNNContextImpl>(new coreml::ContextImpl( |
| 97 | blink_remote.InitWithNewPipeAndPassReceiver(), this))); |
| 98 | std::move(callback).Run( |
| 99 | mojom::CreateContextResult::NewContextRemote(std::move(blink_remote))); |
| 100 | } else { |
| 101 | std::move(callback).Run(ToError<mojom::CreateContextResult>( |
| 102 | mojom::Error::Code::kNotSupportedError, |
| 103 | "WebNN Service is not supported on this platform.")); |
| 104 | DLOG(ERROR) << "WebNN Service is not supported on this platform."; |
| 105 | } |
junwei | d4ed5a81 | 2023-04-19 03:19:26 | [diff] [blame] | 106 | #else |
| 107 | // TODO(crbug.com/1273291): Supporting WebNN Service on the platform. |
Shiyi Zou | ff06a31 | 2023-09-15 05:18:05 | [diff] [blame] | 108 | std::move(callback).Run(ToError<mojom::CreateContextResult>( |
| 109 | mojom::Error::Code::kNotSupportedError, |
| 110 | "WebNN Service is not supported on this platform.")); |
| 111 | DLOG(ERROR) << "WebNN Service is not supported on this platform."; |
junwei | d4ed5a81 | 2023-04-19 03:19:26 | [diff] [blame] | 112 | #endif |
| 113 | } |
| 114 | |
| 115 | } // namespace webnn |