diff --git a/ci/run-wasi-nn-example.sh b/ci/run-wasi-nn-example.sh index e24ffa75ac51..49c472c95eee 100755 --- a/ci/run-wasi-nn-example.sh +++ b/ci/run-wasi-nn-example.sh @@ -7,7 +7,7 @@ # executed with the Wasmtime CLI. set -e WASMTIME_DIR=$(dirname "$0" | xargs dirname) -FIXTURE=https://github.com/intel/openvino-rs/raw/main/crates/openvino/tests/fixtures/alexnet +FIXTURE=https://github.com/intel/openvino-rs/raw/main/crates/openvino/tests/fixtures/mobilenet if [ -z "${1+x}" ]; then # If no temporary directory is specified, create one. TMP_DIR=$(mktemp -d -t ci-XXXXXXXXXX) @@ -26,9 +26,9 @@ source /opt/intel/openvino/bin/setupvars.sh OPENVINO_INSTALL_DIR=/opt/intel/openvino cargo build -p wasmtime-cli --features wasi-nn # Download all necessary test fixtures to the temporary directory. -wget --no-clobber --directory-prefix=$TMP_DIR $FIXTURE/alexnet.bin -wget --no-clobber --directory-prefix=$TMP_DIR $FIXTURE/alexnet.xml -wget --no-clobber --directory-prefix=$TMP_DIR $FIXTURE/tensor-1x3x227x227-f32.bgr +wget --no-clobber $FIXTURE/mobilenet.bin --output-document=$TMP_DIR/model.bin +wget --no-clobber $FIXTURE/mobilenet.xml --output-document=$TMP_DIR/model.xml +wget --no-clobber $FIXTURE/tensor-1x224x224x3-f32.bgr --output-document=$TMP_DIR/tensor.bgr # Now build an example that uses the wasi-nn API. pushd $WASMTIME_DIR/crates/wasi-nn/examples/classification-example @@ -42,4 +42,4 @@ OPENVINO_INSTALL_DIR=/opt/intel/openvino cargo run --features wasi-nn -- run --m # Clean up the temporary directory only if it was not specified (users may want to keep the directory around). if [[ $REMOVE_TMP_DIR -eq 1 ]]; then rm -rf $TMP_DIR -fi \ No newline at end of file +fi diff --git a/crates/wasi-nn/examples/classification-example/Cargo.lock b/crates/wasi-nn/examples/classification-example/Cargo.lock index f98a1e19a803..0a2414873852 100644 --- a/crates/wasi-nn/examples/classification-example/Cargo.lock +++ b/crates/wasi-nn/examples/classification-example/Cargo.lock @@ -3,11 +3,12 @@ [[package]] name = "wasi-nn" version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c909acded993dc129e02f64a7646eb7b53079f522a814024a88772f41558996" [[package]] name = "wasi-nn-example" version = "0.19.0" dependencies = [ - "wasi-nn 0.1.0", + "wasi-nn", ] - diff --git a/crates/wasi-nn/examples/classification-example/Cargo.toml b/crates/wasi-nn/examples/classification-example/Cargo.toml index 52bf2dac321b..f74c4eab8468 100644 --- a/crates/wasi-nn/examples/classification-example/Cargo.toml +++ b/crates/wasi-nn/examples/classification-example/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" publish = false [dependencies] -wasi-nn = { path = "../wasi-nn-rust-bindings", version = "0.1.0" } +wasi-nn = "0.1.0" # This crate is built with the wasm32-wasi target, so it's separate # from the main Wasmtime build, so use this directive to exclude it diff --git a/crates/wasi-nn/examples/classification-example/src/main.rs b/crates/wasi-nn/examples/classification-example/src/main.rs index 5f0a7f4e5ae9..6b415fb96bf9 100644 --- a/crates/wasi-nn/examples/classification-example/src/main.rs +++ b/crates/wasi-nn/examples/classification-example/src/main.rs @@ -3,10 +3,10 @@ use std::fs; use wasi_nn; pub fn main() { - let xml = fs::read_to_string("fixture/alexnet.xml").unwrap(); + let xml = fs::read_to_string("fixture/model.xml").unwrap(); println!("Read graph XML, first 50 characters: {}", &xml[..50]); - let weights = fs::read("fixture/alexnet.bin").unwrap(); + let weights = fs::read("fixture/model.bin").unwrap(); println!("Read graph weights, size in bytes: {}", weights.len()); let graph = unsafe { @@ -24,10 +24,10 @@ pub fn main() { // Load a tensor that precisely matches the graph input tensor (see // `fixture/frozen_inference_graph.xml`). - let tensor_data = fs::read("fixture/tensor-1x3x227x227-f32.bgr").unwrap(); + let tensor_data = fs::read("fixture/tensor.bgr").unwrap(); println!("Read input tensor, size in bytes: {}", tensor_data.len()); let tensor = wasi_nn::Tensor { - dimensions: &[1, 3, 227, 227], + dimensions: &[1, 3, 224, 224], r#type: wasi_nn::TENSOR_TYPE_F32, data: &tensor_data, }; @@ -42,7 +42,7 @@ pub fn main() { println!("Executed graph inference"); // Retrieve the output. - let mut output_buffer = vec![0f32; 1000]; + let mut output_buffer = vec![0f32; 1001]; unsafe { wasi_nn::get_output( context, @@ -60,10 +60,13 @@ pub fn main() { // Sort the buffer of probabilities. The graph places the match probability for each class at the // index for that class (e.g. the probability of class 42 is placed at buffer[42]). Here we convert -// to a wrapping InferenceResult and sort the results. +// to a wrapping InferenceResult and sort the results. It is unclear why the MobileNet output +// indices are "off by one" but the `.skip(1)` below seems necessary to get results that make sense +// (e.g. 763 = "revolver" vs 762 = "restaurant") fn sort_results(buffer: &[f32]) -> Vec { let mut results: Vec = buffer .iter() + .skip(1) .enumerate() .map(|(c, p)| InferenceResult(c, *p)) .collect(); diff --git a/crates/wasi-nn/examples/wasi-nn-rust-bindings/.gitignore b/crates/wasi-nn/examples/wasi-nn-rust-bindings/.gitignore deleted file mode 100644 index ea8c4bf7f35f..000000000000 --- a/crates/wasi-nn/examples/wasi-nn-rust-bindings/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/target diff --git a/crates/wasi-nn/examples/wasi-nn-rust-bindings/Cargo.lock b/crates/wasi-nn/examples/wasi-nn-rust-bindings/Cargo.lock deleted file mode 100644 index b8e596de2fc4..000000000000 --- a/crates/wasi-nn/examples/wasi-nn-rust-bindings/Cargo.lock +++ /dev/null @@ -1,5 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -[[package]] -name = "wasi-nn" -version = "0.1.0" diff --git a/crates/wasi-nn/examples/wasi-nn-rust-bindings/Cargo.toml b/crates/wasi-nn/examples/wasi-nn-rust-bindings/Cargo.toml deleted file mode 100644 index c26f0807110b..000000000000 --- a/crates/wasi-nn/examples/wasi-nn-rust-bindings/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -name = "wasi-nn" -version = "0.1.0" -authors = ["The Wasmtime Project Developers"] -readme = "README.md" -edition = "2018" -publish = false - -[dependencies] - -# This crate is only used when building the example, so it's separate -# from the main Wasmtime build, so use this directive to exclude it -# from the parent directory's workspace. -[workspace] diff --git a/crates/wasi-nn/examples/wasi-nn-rust-bindings/LICENSE b/crates/wasi-nn/examples/wasi-nn-rust-bindings/LICENSE deleted file mode 100644 index 16fe87b06e80..000000000000 --- a/crates/wasi-nn/examples/wasi-nn-rust-bindings/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [yyyy] [name of copyright owner] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/crates/wasi-nn/examples/wasi-nn-rust-bindings/README.md b/crates/wasi-nn/examples/wasi-nn-rust-bindings/README.md deleted file mode 100644 index b11ef16773ab..000000000000 --- a/crates/wasi-nn/examples/wasi-nn-rust-bindings/README.md +++ /dev/null @@ -1,65 +0,0 @@ -wasi-nn Rust Bindings -===================== - -This crate contains API bindings for [wasi-nn] system calls in Rust. It is similar in purpose to the [wasi bindings] but -this crate provides access to the optional neural network functionality from WebAssembly. - -[wasi-nn]: https://github.com/WebAssembly/wasi-nn -[wasi bindings]: https://github.com/bytecodealliance/wasi - -> __NOTE__: These bindings are experimental (use at your own risk) and subject to upstream changes in the wasi-nn -> specification. - -> __NOTE__: In the future this crate may be (should be) moved to its own repository, like the [wasi bindings]. - -### Use - -Depend on this crate in your `Cargo.toml`: - -```toml -[dependencies] -wasi-nn = "0.1.0" -``` - -Use the wasi-nn APIs in your application: - -```rust -use wasi_nn; - -unsafe { - wasi_nn::load( - &[&xml.into_bytes(), &weights], - wasi_nn::GRAPH_ENCODING_OPENVINO, - wasi_nn::EXECUTION_TARGET_CPU, - ) - .unwrap() -} -``` - -Compile the application to WebAssembly: - -```shell script -cargo build --target=wasm32-wasi -``` - -Run the generated Wasm in a runtime supporting wasi-nn. Currently Wasmtime has experimental support using the Wasmtime -APIs; see [main.rs](../main.rs) for an example of how this is accomplished. - -### Generation - -This crate contains code ([`src/generated.rs`](src/generated.rs)) generated by -[`witx-bindgen`](https://github.com/bytecodealliance/wasi/tree/main/crates/witx-bindgen). -To regenerate this code, run `witx-bindgen` against the [`wasi-nn` WITX file](https://github.com/WebAssembly/wasi-nn/blob/master/phases/ephemeral/witx/wasi_ephemeral_nn.witx): - -```shell script -.../crates/witx-bindgen$ cargo run .../wasi-nn/phases/ephemeral/witx/wasi_ephemeral_nn.witx -``` - -### License - -This project is licensed under the Apache 2.0 license. See [LICENSE](LICENSE) for more details. - -### Contribution - -Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this project by you, -as defined in the Apache-2.0 license, shall be licensed as above, without any additional terms or conditions. diff --git a/crates/wasi-nn/examples/wasi-nn-rust-bindings/src/error.rs b/crates/wasi-nn/examples/wasi-nn-rust-bindings/src/error.rs deleted file mode 100644 index 7ae1a50edb74..000000000000 --- a/crates/wasi-nn/examples/wasi-nn-rust-bindings/src/error.rs +++ /dev/null @@ -1,76 +0,0 @@ -use super::NnErrno; -use core::fmt; -use core::num::NonZeroU16; - -/// A raw error returned by wasi-nn APIs, internally containing a 16-bit error -/// code. -#[derive(Copy, Clone, PartialEq, Eq, Ord, PartialOrd)] -pub struct Error { - code: NonZeroU16, -} - -impl Error { - /// Constructs a new error from a raw error code, returning `None` if the - /// error code is zero (which means success). - pub fn from_raw_error(error: NnErrno) -> Option { - Some(Error { - code: NonZeroU16::new(error)?, - }) - } - - /// Returns the raw error code that this error represents. - pub fn raw_error(&self) -> u16 { - self.code.get() - } -} - -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{} (error {})", strerror(self.code.get()), self.code)?; - Ok(()) - } -} - -impl fmt::Debug for Error { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Error") - .field("code", &self.code) - .field("message", &strerror(self.code.get())) - .finish() - } -} - -/// This should be generated automatically by witx-bindgen but is not yet for enums other than -/// `Errno` (this API uses `NnErrno` to avoid naming conflicts). TODO: https://github.com/bytecodealliance/wasi/issues/52. -fn strerror(code: u16) -> &'static str { - match code { - super::NN_ERRNO_SUCCESS => "No error occurred.", - super::NN_ERRNO_INVALID_ARGUMENT => "Caller module passed an invalid argument.", - super::NN_ERRNO_MISSING_MEMORY => "Caller module is missing a memory export.", - super::NN_ERRNO_BUSY => "Device or resource busy.", - _ => "Unknown error.", - } -} - -#[cfg(feature = "std")] -extern crate std; -#[cfg(feature = "std")] -impl std::error::Error for Error {} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn error_from_success_code() { - assert_eq!(None, Error::from_raw_error(0)); - } - - #[test] - fn error_from_invalid_argument_code() { - assert_eq!( - "Caller module passed an invalid argument. (error 1)", - Error::from_raw_error(1).unwrap().to_string() - ); - } -} diff --git a/crates/wasi-nn/examples/wasi-nn-rust-bindings/src/generated.rs b/crates/wasi-nn/examples/wasi-nn-rust-bindings/src/generated.rs deleted file mode 100644 index 2e74c045a981..000000000000 --- a/crates/wasi-nn/examples/wasi-nn-rust-bindings/src/generated.rs +++ /dev/null @@ -1,200 +0,0 @@ -// This file is automatically generated, DO NOT EDIT -// -// To regenerate this file run the `crates/witx-bindgen` command - -use core::mem::MaybeUninit; - -pub use crate::error::Error; -pub type Result = core::result::Result; -pub type BufferSize = u32; -pub type NnErrno = u16; -/// No error occurred. -pub const NN_ERRNO_SUCCESS: NnErrno = 0; -/// Caller module passed an invalid argument. -pub const NN_ERRNO_INVALID_ARGUMENT: NnErrno = 1; -/// Caller module is missing a memory export. -pub const NN_ERRNO_MISSING_MEMORY: NnErrno = 2; -/// Device or resource busy. -pub const NN_ERRNO_BUSY: NnErrno = 3; -pub type TensorDimensions<'a> = &'a [u32]; -pub type TensorType = u8; -pub const TENSOR_TYPE_F16: TensorType = 0; -pub const TENSOR_TYPE_F32: TensorType = 1; -pub const TENSOR_TYPE_U8: TensorType = 2; -pub const TENSOR_TYPE_I32: TensorType = 3; -pub type TensorData<'a> = &'a [u8]; -#[repr(C)] -#[derive(Copy, Clone, Debug)] -pub struct Tensor<'a> { - /// Describe the size of the tensor (e.g. 2x2x2x2 -> [2, 2, 2, 2]). To represent a tensor containing a single value, - /// use `[1]` for the tensor dimensions. - pub dimensions: TensorDimensions<'a>, - pub r#type: TensorType, - /// Contains the tensor data. - pub data: TensorData<'a>, -} -pub type GraphBuilder<'a> = &'a [u8]; -pub type GraphBuilderArray<'a> = &'a [GraphBuilder<'a>]; -pub type Graph = u32; -pub type GraphEncoding = u8; -/// TODO document buffer order -pub const GRAPH_ENCODING_OPENVINO: GraphEncoding = 0; -pub type ExecutionTarget = u8; -pub const EXECUTION_TARGET_CPU: ExecutionTarget = 0; -pub const EXECUTION_TARGET_GPU: ExecutionTarget = 1; -pub const EXECUTION_TARGET_TPU: ExecutionTarget = 2; -pub type GraphExecutionContext = u32; -/// Load an opaque sequence of bytes to use for inference. -/// -/// This allows runtime implementations to support multiple graph encoding formats. For unsupported graph encodings, -/// return `errno::inval`. -/// -/// ## Parameters -/// -/// * `builder` - The bytes necessary to build the graph. -/// * `encoding` - The encoding of the graph. -/// * `target` - Where to execute the graph. -pub unsafe fn load( - builder: GraphBuilderArray, - encoding: GraphEncoding, - target: ExecutionTarget, -) -> Result { - let mut graph = MaybeUninit::uninit(); - let rc = wasi_ephemeral_nn::load( - builder.as_ptr(), - builder.len(), - encoding, - target, - graph.as_mut_ptr(), - ); - if let Some(err) = Error::from_raw_error(rc) { - Err(err) - } else { - Ok(graph.assume_init()) - } -} - -/// TODO Functions like `describe_graph_inputs` and `describe_graph_outputs` (returning -/// an array of `$tensor_description`s) might be useful for introspecting the graph but are not yet included here. -/// Create an execution instance of a loaded graph. -/// TODO this may need to accept flags that might affect the compilation or execution of the graph. -pub unsafe fn init_execution_context(graph: Graph) -> Result { - let mut context = MaybeUninit::uninit(); - let rc = wasi_ephemeral_nn::init_execution_context(graph, context.as_mut_ptr()); - if let Some(err) = Error::from_raw_error(rc) { - Err(err) - } else { - Ok(context.assume_init()) - } -} - -/// Define the inputs to use for inference. -/// -/// This should return an $nn_errno (TODO define) if the input tensor does not match the expected dimensions and type. -/// -/// ## Parameters -/// -/// * `index` - The index of the input to change. -/// * `tensor` - The tensor to set as the input. -pub unsafe fn set_input(context: GraphExecutionContext, index: u32, tensor: Tensor) -> Result<()> { - let rc = wasi_ephemeral_nn::set_input(context, index, &tensor as *const _ as *mut _); - if let Some(err) = Error::from_raw_error(rc) { - Err(err) - } else { - Ok(()) - } -} - -/// Extract the outputs after inference. -/// -/// This should return an $nn_errno (TODO define) if the inference has not yet run. -/// -/// ## Parameters -/// -/// * `index` - The index of the output to retrieve. -/// * `out_buffer` - An out parameter to which to copy the tensor data. The caller is responsible for allocating enough memory for -/// the tensor data or an error will be returned. Currently there is no dynamic way to extract the additional -/// tensor metadata (i.e. dimension, element type) but this should be added at some point. -/// -/// ## Return -/// -/// * `bytes_written` - The number of bytes of tensor data written to the `$out_buffer`. -pub unsafe fn get_output( - context: GraphExecutionContext, - index: u32, - out_buffer: *mut u8, - out_buffer_max_size: BufferSize, -) -> Result { - let mut bytes_written = MaybeUninit::uninit(); - let rc = wasi_ephemeral_nn::get_output( - context, - index, - out_buffer, - out_buffer_max_size, - bytes_written.as_mut_ptr(), - ); - if let Some(err) = Error::from_raw_error(rc) { - Err(err) - } else { - Ok(bytes_written.assume_init()) - } -} - -/// Compute the inference on the given inputs (see `set_input`). -/// -/// This should return an $nn_errno (TODO define) if the inputs are not all defined. -pub unsafe fn compute(context: GraphExecutionContext) -> Result<()> { - let rc = wasi_ephemeral_nn::compute(context); - if let Some(err) = Error::from_raw_error(rc) { - Err(err) - } else { - Ok(()) - } -} - -#[allow(improper_ctypes)] -pub mod wasi_ephemeral_nn { - use super::*; - #[link(wasm_import_module = "wasi_ephemeral_nn")] - extern "C" { - /// Load an opaque sequence of bytes to use for inference. - /// - /// This allows runtime implementations to support multiple graph encoding formats. For unsupported graph encodings, - /// return `errno::inval`. - pub fn load( - builder_ptr: *const GraphBuilder, - builder_len: usize, - encoding: GraphEncoding, - target: ExecutionTarget, - graph: *mut Graph, - ) -> NnErrno; - /// TODO Functions like `describe_graph_inputs` and `describe_graph_outputs` (returning - /// an array of `$tensor_description`s) might be useful for introspecting the graph but are not yet included here. - /// Create an execution instance of a loaded graph. - /// TODO this may need to accept flags that might affect the compilation or execution of the graph. - pub fn init_execution_context(graph: Graph, context: *mut GraphExecutionContext) - -> NnErrno; - /// Define the inputs to use for inference. - /// - /// This should return an $nn_errno (TODO define) if the input tensor does not match the expected dimensions and type. - pub fn set_input( - context: GraphExecutionContext, - index: u32, - tensor: *mut Tensor, - ) -> NnErrno; - /// Extract the outputs after inference. - /// - /// This should return an $nn_errno (TODO define) if the inference has not yet run. - pub fn get_output( - context: GraphExecutionContext, - index: u32, - out_buffer: *mut u8, - out_buffer_max_size: BufferSize, - bytes_written: *mut BufferSize, - ) -> NnErrno; - /// Compute the inference on the given inputs (see `set_input`). - /// - /// This should return an $nn_errno (TODO define) if the inputs are not all defined. - pub fn compute(context: GraphExecutionContext) -> NnErrno; - } -} diff --git a/crates/wasi-nn/examples/wasi-nn-rust-bindings/src/lib.rs b/crates/wasi-nn/examples/wasi-nn-rust-bindings/src/lib.rs deleted file mode 100644 index 86fdcd009145..000000000000 --- a/crates/wasi-nn/examples/wasi-nn-rust-bindings/src/lib.rs +++ /dev/null @@ -1,3 +0,0 @@ -mod error; -mod generated; -pub use generated::*;