Skip to content

Commit 179345e

Browse files
committed
add support for uint8
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
1 parent db9d479 commit 179345e

4 files changed

Lines changed: 37 additions & 28 deletions

File tree

Cargo.lock

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

components/script/dom/webnn/mlcontext.rs

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use std::rc::Rc;
88
use dom_struct::dom_struct;
99
use js::jsapi::JSObject;
1010
use js::typedarray::{ArrayBufferU8, Float32, Int8, Int16, Int32, Uint8, Uint16, Uint32};
11+
use rustnn::graph::DataType;
1112
use webnn_traits::{ContextId, GraphId, WebNNMsg};
1213

1314
use crate::dom::bindings::buffer_source::create_buffer_source;
@@ -94,6 +95,15 @@ pub(crate) struct MLContext {
9495
lost: Rc<Promise>,
9596
}
9697

98+
fn operand_data_type_name(data_type: DataType) -> Option<&'static str> {
99+
match data_type {
100+
DataType::Float32 => Some("float32"),
101+
DataType::Int32 => Some("int32"),
102+
DataType::Uint8 => Some("uint8"),
103+
_ => None,
104+
}
105+
}
106+
97107
impl MLContext {
98108
/// <https://webmachinelearning.github.io/webnn/#api-ml-createcontext>
99109
pub(crate) fn new_inherited(
@@ -1024,7 +1034,11 @@ impl MLContextMethods<crate::DomTypeHolder> for MLContext {
10241034
// - ban very large tensors to avoid exhausting the GPU process
10251035
// (the "large inputs" tests use ~137 MB per tensor)
10261036

1027-
let data_types = Some(vec![MLOperandDataType::Float32, MLOperandDataType::Int32]);
1037+
let data_types = Some(vec![
1038+
MLOperandDataType::Float32,
1039+
MLOperandDataType::Int32,
1040+
MLOperandDataType::Uint8,
1041+
]);
10281042
// limit the size to something comfortably smaller than the large-input
10291043
// tests in wpt (/6000×6000 float32 ≈ 144 000 000 bytes).
10301044
// Pick a value comfortably below the ~144 MB used by the
@@ -1314,11 +1328,8 @@ impl MLContextMethods<crate::DomTypeHolder> for MLContext {
13141328
// Compare descriptor: operand descriptor -> tensor descriptor
13151329
if let Some(op) = gi.operands.get(op_id as usize) {
13161330
// Compare data type
1317-
let op_dtype_str = match op.descriptor.data_type {
1318-
rustnn::graph::DataType::Float32 => "float32",
1319-
rustnn::graph::DataType::Int32 => "int32",
1320-
_ => return Err(Error::Type(c"Data type not supported".to_owned())),
1321-
};
1331+
let op_dtype_str = operand_data_type_name(op.descriptor.data_type)
1332+
.ok_or_else(|| Error::Type(c"Data type not supported".to_owned()))?;
13221333
if tensor.data_type() != op_dtype_str {
13231334
return Err(Error::Type(c"input tensor descriptor mismatch".to_owned()));
13241335
}
@@ -1349,11 +1360,8 @@ impl MLContextMethods<crate::DomTypeHolder> for MLContext {
13491360
};
13501361

13511362
if let Some(op) = gi.operands.get(op_id as usize) {
1352-
let op_dtype_str = match op.descriptor.data_type {
1353-
rustnn::graph::DataType::Float32 => "float32",
1354-
rustnn::graph::DataType::Int32 => "int32",
1355-
_ => return Err(Error::Type(c"Data type not supported".to_owned())),
1356-
};
1363+
let op_dtype_str = operand_data_type_name(op.descriptor.data_type)
1364+
.ok_or_else(|| Error::Type(c"Data type not supported".to_owned()))?;
13571365
if tensor.data_type() != op_dtype_str {
13581366
return Err(Error::Type(c"output tensor descriptor mismatch".to_owned()));
13591367
}

components/webnn/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ Design notes
5252
- Implementation note: prefer declaring manager helper types (for example
5353
`Context`) at module scope rather than inside `run_manager()` so types
5454
are discoverable, easier to test, and stable for future backend additions.
55+
- Prefer module-scope helper functions over associated functions when backend
56+
helper logic does not use struct state. Keep `impl` blocks focused on
57+
behavior that depends on `self` or on type-specific construction.
5558
- When dispatching graphs we currently only support the macOS CoreML backend.
5659
Graphs with constant operands must have their bytes recorded (`constant-*`
5760
operations in `GraphInfo`) before conversion; the manager now auto-populates

components/webnn/src/lib.rs

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,17 @@ use rustnn::GraphConverter;
1818
use rustnn::executors::coreml::{CoremlOutput, prepare_compiled_model_with_weights};
1919
use rustnn::graph::{ConstantData, DataType, GraphInfo, Operand, get_static_or_max_size};
2020

21+
fn operand_byte_length(operand: &Operand) -> usize {
22+
operand
23+
.descriptor
24+
.shape
25+
.iter()
26+
.fold(1usize, |acc, d| {
27+
acc.saturating_mul(get_static_or_max_size(d) as usize)
28+
})
29+
.saturating_mul(operand.descriptor.data_type.bytes_per_element())
30+
}
31+
2132
// helper for converting a CoreML output (or lack thereof) into the byte
2233
// buffer we store in the manager's tensor store. Handles all supported
2334
// data types and falls back to a zeroed buffer when the output is missing.
@@ -54,28 +65,15 @@ fn process_coreml_outputs(operand: &Operand, coreml_out: Option<CoremlOutput>) -
5465
}
5566
bytes
5667
},
68+
DataType::Uint8 => coreml_out.data.iter().map(|&v| v as u8).collect(),
5769
_other => {
58-
let byte_length = operand
59-
.descriptor
60-
.shape
61-
.iter()
62-
.fold(1usize, |acc, d| {
63-
acc.saturating_mul(get_static_or_max_size(d) as usize)
64-
})
65-
.saturating_mul(4usize);
70+
let byte_length = operand_byte_length(operand);
6671
vec![0u8; byte_length]
6772
},
6873
}
6974
} else {
7075
// no CoreML output at all -> zero buffer
71-
let byte_length = operand
72-
.descriptor
73-
.shape
74-
.iter()
75-
.fold(1usize, |acc, d| {
76-
acc.saturating_mul(get_static_or_max_size(d) as usize)
77-
})
78-
.saturating_mul(4usize);
76+
let byte_length = operand_byte_length(operand);
7977
vec![0u8; byte_length]
8078
}
8179
}
@@ -927,6 +925,7 @@ fn try_coreml_execute(
927925
iv as f32
928926
})
929927
.collect(),
928+
DataType::Uint8 => buf.iter().map(|&b| b as f32).collect(),
930929
_other => Vec::new(),
931930
};
932931

0 commit comments

Comments
 (0)