зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1912155
[wpt PR 47520] - WebNN: Define `MLContext::destroy` interface, a=testonly
Automatic update from web-platform-tests WebNN: Define `MLContext::destroy` interface This CL defines `MLContext::destroy` interface on blink side. It's to destroy the `MLContext` explicitly to let it be lost. `MLContext` retains weak references to all of the `MLBuffer`, `MLGraph` and `MLGraphBuilder` instances, their Mojo pipes will be disconnected and their pending promises will be rejected at the same time as the `MLContext` is destroyed. Any calls rely on the `MLContext` are not allowed and will throw errors. This CL sets disconnection handler for `MLGraphBuilder` to reject pending promise of creating `MLGraph`. This CL removes the unnecessary `MLContext::CreateWebNNBuffer` method, refactors `MLBuffer::ReadBufferImpl` method to create the resolver inside and return the promise, refactors `MLContext::CreateWebNNGraphBuilder` to record the created `MLGraphBuilder` into `MLContext` and return it. Bug: 348904836, 354025380 Change-Id: Ia660fe2f109a089187237da9d6a0285247f19eb9 Cq-Include-Trybots: luci.chromium.try:win11-blink-rel Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5737474 Commit-Queue: Mingming1 Xu <mingming1.xu@intel.com> Reviewed-by: Reilly Grant <reillyg@chromium.org> Reviewed-by: ningxin hu <ningxin.hu@intel.com> Reviewed-by: Rafael Cintron <rafael.cintron@microsoft.com> Cr-Commit-Position: refs/heads/main@{#1338851} -- wpt-commits: 2d8dac31b619e8941e383a5a68d6dfedd65b2d0b wpt-pr: 47520
This commit is contained in:
Родитель
e36b530018
Коммит
48b733f002
|
@ -0,0 +1,150 @@
|
|||
// META: timeout=long
|
||||
// META: title=validation tests for WebNN API MLContext::destroy()
|
||||
// META: global=window,dedicatedworker
|
||||
|
||||
'use strict';
|
||||
|
||||
promise_test(async t => {
|
||||
const context = await navigator.ml.createContext();
|
||||
context.destroy();
|
||||
await context.lost;
|
||||
}, 'Context will be lost by destroyed.');
|
||||
|
||||
promise_test(async t => {
|
||||
const context = await navigator.ml.createContext();
|
||||
context.destroy();
|
||||
context.destroy();
|
||||
await context.lost;
|
||||
}, 'Context can be destroyed twice.');
|
||||
|
||||
promise_test(async t => {
|
||||
const context = await navigator.ml.createContext();
|
||||
const builder = new MLGraphBuilder(context);
|
||||
context.destroy();
|
||||
assert_throws_dom('InvalidStateError', () => {
|
||||
const operandType = {dataType: 'float32', dimensions: [1]};
|
||||
builder.input('input', operandType);
|
||||
});
|
||||
}, 'Destroyed context can not build operator.');
|
||||
|
||||
promise_test(async t => {
|
||||
const context = await navigator.ml.createContext();
|
||||
context.destroy();
|
||||
assert_throws_dom('InvalidStateError', () => {
|
||||
new MLGraphBuilder(context);
|
||||
});
|
||||
}, 'Destroyed context can not create graph builder.');
|
||||
|
||||
promise_test(async t => {
|
||||
const context = await navigator.ml.createContext();
|
||||
const builder = new MLGraphBuilder(context);
|
||||
const operandType = {dataType: 'float32', dimensions: [1]};
|
||||
const input_operand = builder.input('input', operandType);
|
||||
const const_operand = builder.constant(operandType, Float32Array.from([2]));
|
||||
const output_operand = builder.mul(input_operand, const_operand);
|
||||
|
||||
context.destroy();
|
||||
promise_rejects_dom(
|
||||
t, 'InvalidStateError', builder.build({'output': output_operand}));
|
||||
}, 'Destroyed context can not build graph.');
|
||||
|
||||
promise_test(async t => {
|
||||
const context = await navigator.ml.createContext();
|
||||
const builder = new MLGraphBuilder(context);
|
||||
const operandType = {dataType: 'float32', dimensions: [1]};
|
||||
const input_operand = builder.input('input', operandType);
|
||||
const const_operand = builder.constant(operandType, Float32Array.from([2]));
|
||||
const output_operand = builder.mul(input_operand, const_operand);
|
||||
const graph = await builder.build({'output': output_operand});
|
||||
|
||||
context.destroy();
|
||||
let inputs = {'input': Float32Array.from([1])};
|
||||
let outputs = {'output': new Float32Array(1)};
|
||||
promise_rejects_dom(
|
||||
t, 'InvalidStateError', context.compute(graph, inputs, outputs));
|
||||
}, 'Destroyed context can not compute.');
|
||||
|
||||
promise_test(async t => {
|
||||
const context = await navigator.ml.createContext();
|
||||
const builder = new MLGraphBuilder(context);
|
||||
const operandType = {dataType: 'float32', dimensions: [1]};
|
||||
const lhsOperand = builder.input('lhs', operandType);
|
||||
const rhsOperand = builder.input('rhs', operandType);
|
||||
const graph =
|
||||
await builder.build({'output': builder.sub(lhsOperand, rhsOperand)});
|
||||
|
||||
const lhsBuffer = await context.createBuffer(operandType);
|
||||
const rhsBuffer = await context.createBuffer(operandType);
|
||||
|
||||
const dispatchOutputs = {'output': await context.createBuffer(operandType)};
|
||||
context.destroy();
|
||||
assert_throws_dom('InvalidStateError', () => {
|
||||
context.dispatch(
|
||||
graph, {
|
||||
'lhs': lhsBuffer,
|
||||
'rhs': rhsBuffer,
|
||||
},
|
||||
dispatchOutputs);
|
||||
});
|
||||
}, 'Destroyed context can not dispatch.');
|
||||
|
||||
promise_test(async t => {
|
||||
const context = await navigator.ml.createContext();
|
||||
const builder = new MLGraphBuilder(context);
|
||||
const operandType = {dataType: 'float32', dimensions: [1]};
|
||||
const lhsOperand = builder.input('lhs', operandType);
|
||||
const rhsOperand = builder.input('rhs', operandType);
|
||||
const graph =
|
||||
await builder.build({'output': builder.sub(lhsOperand, rhsOperand)});
|
||||
|
||||
const lhsBuffer = await context.createBuffer(operandType);
|
||||
const rhsBuffer = await context.createBuffer(operandType);
|
||||
|
||||
const dispatchOutputs = {'output': await context.createBuffer(operandType)};
|
||||
context.dispatch(
|
||||
graph, {
|
||||
'lhs': lhsBuffer,
|
||||
'rhs': rhsBuffer,
|
||||
},
|
||||
dispatchOutputs);
|
||||
context.destroy();
|
||||
}, 'Executing dispatch() before context destroyed is OK.');
|
||||
|
||||
promise_test(async t => {
|
||||
const context = await navigator.ml.createContext();
|
||||
context.destroy();
|
||||
promise_rejects_dom(
|
||||
t, 'InvalidStateError',
|
||||
context.createBuffer({dataType: 'float32', dimensions: [1]}));
|
||||
}, 'Destroyed context can not create buffer.');
|
||||
|
||||
promise_test(async t => {
|
||||
const context = await navigator.ml.createContext();
|
||||
const buffer =
|
||||
await context.createBuffer({dataType: 'float32', dimensions: [1]});
|
||||
context.destroy();
|
||||
promise_rejects_dom(t, 'InvalidStateError', context.readBuffer(buffer));
|
||||
}, 'Destroyed context can not read buffer.');
|
||||
|
||||
promise_test(async t => {
|
||||
const context = await navigator.ml.createContext();
|
||||
const buffer =
|
||||
await context.createBuffer({dataType: 'float32', dimensions: [1]});
|
||||
let promise = context.readBuffer(buffer);
|
||||
context.destroy();
|
||||
promise_rejects_dom(t, 'InvalidStateError', promise);
|
||||
}, 'Pending promise of readbuffer() will be rejected immediately when context is destroyed.');
|
||||
|
||||
promise_test(async t => {
|
||||
const context = await navigator.ml.createContext();
|
||||
// Destroying another context doesn't impact the first context.
|
||||
const another_context = await navigator.ml.createContext();
|
||||
another_context.destroy();
|
||||
const buffer =
|
||||
await context.createBuffer({dataType: 'float32', dimensions: [1]});
|
||||
let arrayBuffer = new ArrayBuffer(4);
|
||||
context.destroy();
|
||||
assert_throws_dom('InvalidStateError', () => {
|
||||
context.writeBuffer(buffer, new Uint8Array(arrayBuffer));
|
||||
});
|
||||
}, 'Destroyed context can not write buffer.');
|
Загрузка…
Ссылка в новой задаче