| // META: timeout=long |
| // META: title=validation tests for WebNN API MLContext::destroy() |
| // META: global=window,worker |
| // META: variant=?cpu |
| // META: variant=?gpu |
| // META: variant=?npu |
| |
| 'use strict'; |
| |
| let context; |
| |
| promise_setup(async () => { |
| assert_implements(navigator.ml, 'WebNN is not supported'); |
| const contextOptions = {deviceType: location.search.substring(1)}; |
| try { |
| context = await navigator.ml.createContext(contextOptions); |
| } catch (e) { |
| throw new AssertionError( |
| `Unable to create context for ${variant} variant. ${e}`); |
| } |
| }, {explicit_timeout: true}); |
| |
| promise_test(async t => { |
| const builder = new MLGraphBuilder(context); |
| const operandType = {dataType: 'float32', shape: [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}); |
| |
| graph.destroy(); |
| graph.destroy(); |
| }, 'Graph can be destroyed twice.'); |
| |
| promise_test(async t => { |
| const builder = new MLGraphBuilder(context); |
| const operandType = {dataType: 'float32', shape: [1]}; |
| const lhsOperand = builder.input('lhs', operandType); |
| const rhsOperand = builder.input('rhs', operandType); |
| const graph = |
| await builder.build({'output': builder.mul(lhsOperand, rhsOperand)}); |
| |
| const lhsTensor = await context.createTensor(operandType); |
| const rhsTensor = await context.createTensor(operandType); |
| const dispatchOutputs = {'output': await context.createTensor(operandType)}; |
| |
| graph.destroy(); |
| assert_throws_dom('InvalidStateError', () => { |
| context.dispatch( |
| graph, { |
| 'lhs': lhsTensor, |
| 'rhs': rhsTensor, |
| }, |
| dispatchOutputs); |
| }); |
| }, 'Destroyed graph can not dispatch.'); |
| |
| promise_test(async t => { |
| const builder = new MLGraphBuilder(context); |
| const operandType = {dataType: 'float32', shape: [1]}; |
| const lhsOperand = builder.input('lhs', operandType); |
| const rhsOperand = builder.input('rhs', operandType); |
| const graph = |
| await builder.build({'output': builder.mul(lhsOperand, rhsOperand)}); |
| |
| const lhsTensor = await context.createTensor({ |
| dataType: 'float32', |
| shape: [1], |
| writable: true, |
| }); |
| const rhsTensor = await context.createTensor({ |
| dataType: 'float32', |
| shape: [1], |
| writable: true, |
| }); |
| const outputTensor = await context.createTensor({ |
| dataType: 'float32', |
| shape: [1], |
| readable: true, |
| }); |
| // Initialize inputs |
| const inputData = new Float32Array(1).fill(2.0); |
| context.writeTensor(lhsTensor, inputData); |
| context.writeTensor(rhsTensor, inputData); |
| context.dispatch( |
| graph, { |
| 'lhs': lhsTensor, |
| 'rhs': rhsTensor, |
| }, |
| {'output': outputTensor}); |
| |
| graph.destroy(); |
| const outputData = await context.readTensor(outputTensor); |
| assert_array_equals( |
| new Float32Array(outputData), [4], |
| 'Read tensor data equals expected data.'); |
| }, 'Destroying graph after dispatch() and before readTensor() is OK.'); |