From 888ed7860ee24e8f8d0f0544b082e40bed3bd87e Mon Sep 17 00:00:00 2001 From: Bryan Bernhart Date: Fri, 8 Mar 2024 10:08:30 -0800 Subject: [PATCH] WebNN: Implement MLBuffer creation/destroy. Introduces MLBuffer to the WebNN service. Since MLBuffer exists in the domain of the context, instead of a graph, a dedicated command recorder was needed to ensure future context operations (ie. readBuffer) get applied prior to graph operations. * Defines handles to identify objects in the ML service. * Defines MLBuffer interfaces. * Implements buffer creation and destruction. https://github.com/webmachinelearning/webnn/issues/482 Bug: 1472888 Change-Id: I852eff452346a968812e9f248fbb0a4cfc917dbc Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5173676 Reviewed-by: ningxin hu Reviewed-by: Reilly Grant Reviewed-by: Alex Gough Reviewed-by: Rafael Cintron Commit-Queue: Bryan Bernhart Cr-Commit-Position: refs/heads/main@{#1270252} --- webnn/conformance_tests/buffer.https.any.js | 12 ++++ .../conformance_tests/gpu/buffer.https.any.js | 12 ++++ webnn/resources/utils.js | 56 +++++++++++++++++++ 3 files changed, 80 insertions(+) create mode 100644 webnn/conformance_tests/buffer.https.any.js create mode 100644 webnn/conformance_tests/gpu/buffer.https.any.js diff --git a/webnn/conformance_tests/buffer.https.any.js b/webnn/conformance_tests/buffer.https.any.js new file mode 100644 index 000000000000000..5b0f46dae021127 --- /dev/null +++ b/webnn/conformance_tests/buffer.https.any.js @@ -0,0 +1,12 @@ +// META: title=test WebNN API buffer operations +// META: global=window,dedicatedworker +// META: script=../resources/utils.js +// META: timeout=long + +'use strict'; + +// https://webmachinelearning.github.io/webnn/#api-mlbuffer + +testCreateWebNNBuffer("create", 4); + +testDestroyWebNNBuffer("destroyTwice"); \ No newline at end of file diff --git a/webnn/conformance_tests/gpu/buffer.https.any.js b/webnn/conformance_tests/gpu/buffer.https.any.js new file mode 100644 index 000000000000000..66bba9ef4afc66c --- /dev/null +++ b/webnn/conformance_tests/gpu/buffer.https.any.js @@ -0,0 +1,12 @@ +// META: title=test WebNN API buffer operations +// META: global=window,dedicatedworker +// META: script=../../resources/utils.js +// META: timeout=long + +'use strict'; + +// https://webmachinelearning.github.io/webnn/#api-mlbuffer + +testCreateWebNNBuffer("create", 4, 'gpu'); + +testDestroyWebNNBuffer("destroyTwice", 'gpu'); \ No newline at end of file diff --git a/webnn/resources/utils.js b/webnn/resources/utils.js index df51321a694ce0f..0a2e0dadda51a1d 100644 --- a/webnn/resources/utils.js +++ b/webnn/resources/utils.js @@ -898,4 +898,60 @@ const toHalf = (value) => { * the exponent, which is OK. */ bits += m & 1; return bits; +}; + + +/** + * WebNN buffer creation. + * @param {MLContext} context - the context used to create the buffer. + * @param {Number} bufferSize - Size of the buffer to create, in bytes. + */ +const createBuffer = (context, bufferSize) => { + let buffer; + try { + buffer = context.createBuffer({size: bufferSize}); + assert_equals(buffer.size, bufferSize); + } catch (e) { + assert_true(e instanceof DOMException); + assert_equals(e.name, "NotSupportedError"); + } + return buffer; +}; + +/** + * WebNN destroy buffer twice test. + * @param {String} testName - The name of the test operation. + * @param {String} deviceType - The execution device type for this test. + */ +const testDestroyWebNNBuffer = (testName, deviceType = 'cpu') => { + let context; + let buffer; + promise_setup(async () => { + context = await navigator.ml.createContext({deviceType}); + buffer = createBuffer(context, 4); + }); + promise_test(async () => { + // MLBuffer is not supported for this deviceType. + if (buffer === undefined) { + return; + } + buffer.destroy(); + buffer.destroy(); + }, `${testName}`); +}; + +/** + * WebNN create buffer test. + * @param {String} testName - The name of the test operation. + * @param {Number} bufferSize - Size of the buffer to create, in bytes. + * @param {String} deviceType - The execution device type for this test. + */ +const testCreateWebNNBuffer = (testName, bufferSize, deviceType = 'cpu') => { + let context; + promise_setup(async () => { + context = await navigator.ml.createContext({deviceType}); + }); + promise_test(async () => { + createBuffer(context, bufferSize); + }, `${testName} / ${bufferSize}`); }; \ No newline at end of file