From b20ab9893e833703d40cefbfd52beab7da5878a1 Mon Sep 17 00:00:00 2001 From: Xu Xing Date: Mon, 6 Feb 2023 16:20:57 +0800 Subject: [PATCH 1/4] SharedArrayBuffer is not GPU data Bug: https://github.com/tensorflow/tfjs/issues/7343 --- tfjs-core/src/ops/tensor_ops_util.ts | 6 ++---- tfjs-core/src/tensor_util_env.ts | 22 +++++++++++++--------- tfjs-core/src/types.ts | 23 +++++++++++++++++++++++ 3 files changed, 38 insertions(+), 13 deletions(-) diff --git a/tfjs-core/src/ops/tensor_ops_util.ts b/tfjs-core/src/ops/tensor_ops_util.ts index 197ccf1e30d..d3113cfd8b6 100644 --- a/tfjs-core/src/ops/tensor_ops_util.ts +++ b/tfjs-core/src/ops/tensor_ops_util.ts @@ -17,7 +17,7 @@ import {ENGINE} from '../engine'; import {Tensor} from '../tensor'; -import {TensorLike, TypedArray, WebGLData, WebGPUData} from '../types'; +import {getGPUDataType, GPUDataType, TensorLike, TypedArray, WebGLData, WebGPUData} from '../types'; import {DataType} from '../types'; import {assert, assertNonNegativeIntegerDimensions, flatten, inferDtype, isTypedArray, sizeFromShape, toTypedArray} from '../util'; @@ -33,9 +33,7 @@ export function makeTensor( `Please use tf.complex(real, imag).`); } - if (typeof values === 'object' && - ('texture' in values || - ('buffer' in values && !(values.buffer instanceof ArrayBuffer)))) { + if (getGPUDataType(values) !== GPUDataType.Unknown) { if (dtype !== 'float32' && dtype !== 'int32') { throw new Error( `Creating tensor from GPU data only supports ` + diff --git a/tfjs-core/src/tensor_util_env.ts b/tfjs-core/src/tensor_util_env.ts index e7be4297429..0792952be49 100644 --- a/tfjs-core/src/tensor_util_env.ts +++ b/tfjs-core/src/tensor_util_env.ts @@ -18,7 +18,7 @@ import {ENGINE} from './engine'; import {env} from './environment'; import {Tensor} from './tensor'; -import {DataType, TensorLike, WebGLData, WebGPUData} from './types'; +import {DataType, getGPUDataType, GPUDataType, TensorLike, WebGLData, WebGPUData} from './types'; import {assert, flatten, inferDtype, isTypedArray, toTypedArray} from './util'; import {bytesPerElement} from './util_base'; @@ -29,14 +29,18 @@ export function inferShape( if (isTypedArray(val)) { return dtype === 'string' ? [] : [val.length]; } - const isObject = typeof val === 'object'; - if (isObject) { - if ('texture' in val) { - const usedChannels = val.channels || 'RGBA'; - return [val.height, val.width * usedChannels.length]; - } else if ('buffer' in val && !(val.buffer instanceof ArrayBuffer)) { - return [val.buffer.size / (dtype == null ? 4 : bytesPerElement(dtype))]; - } + + const gpuDataType = getGPUDataType(val); + if (gpuDataType === GPUDataType.WebGL) { + const usedChannels = (val as WebGLData).channels || 'RGBA'; + return [ + (val as WebGLData).height, (val as WebGLData).width * usedChannels.length + ]; + } else if (gpuDataType === GPUDataType.WebGPU) { + return [ + (val as WebGPUData).buffer.size / + (dtype == null ? 4 : bytesPerElement(dtype)) + ]; } if (!Array.isArray(val)) { return []; // Scalar. diff --git a/tfjs-core/src/types.ts b/tfjs-core/src/types.ts index 2d3fe88ddad..433f19891b5 100644 --- a/tfjs-core/src/types.ts +++ b/tfjs-core/src/types.ts @@ -196,3 +196,26 @@ export interface WebGPUData { buffer: GPUBuffer; zeroCopy?: boolean; } + +export enum GPUDataType { + Unknown = 0, + WebGL = 1, + WebGPU = 2, +} + +export function getGPUDataType(values: TensorLike|WebGLData| + WebGPUData): GPUDataType { + if (typeof values !== 'object') { + // Unknown data type. + return GPUDataType.Unknown; + } + if ('texture' in values && values.texture instanceof WebGLTexture) { + return GPUDataType.WebGL; + } else if ( + 'buffer' in values && typeof GPUBuffer !== 'undefined' && + values.buffer instanceof GPUBuffer) { + return GPUDataType.WebGPU; + } else { + return GPUDataType.Unknown; + } +} From f633034985e1631fbe9024fe8599e71682507aa3 Mon Sep 17 00:00:00 2001 From: Xu Xing Date: Thu, 9 Feb 2023 14:44:20 +0800 Subject: [PATCH 2/4] Apply suggestions from code review Co-authored-by: Matthew Soulanille --- tfjs-core/src/ops/tensor_ops_util.ts | 4 ++-- tfjs-core/src/tensor_util_env.ts | 17 +++++--------- tfjs-core/src/types.ts | 33 ++++++++++------------------ 3 files changed, 20 insertions(+), 34 deletions(-) diff --git a/tfjs-core/src/ops/tensor_ops_util.ts b/tfjs-core/src/ops/tensor_ops_util.ts index d3113cfd8b6..15b725103ad 100644 --- a/tfjs-core/src/ops/tensor_ops_util.ts +++ b/tfjs-core/src/ops/tensor_ops_util.ts @@ -17,7 +17,7 @@ import {ENGINE} from '../engine'; import {Tensor} from '../tensor'; -import {getGPUDataType, GPUDataType, TensorLike, TypedArray, WebGLData, WebGPUData} from '../types'; +import {isWebGLData, isWebGPUData, TensorLike, TypedArray, WebGLData, WebGPUData} from '../types'; import {DataType} from '../types'; import {assert, assertNonNegativeIntegerDimensions, flatten, inferDtype, isTypedArray, sizeFromShape, toTypedArray} from '../util'; @@ -33,7 +33,7 @@ export function makeTensor( `Please use tf.complex(real, imag).`); } - if (getGPUDataType(values) !== GPUDataType.Unknown) { + if (isWebGPUData(values) || isWebGLData(values)) { if (dtype !== 'float32' && dtype !== 'int32') { throw new Error( `Creating tensor from GPU data only supports ` + diff --git a/tfjs-core/src/tensor_util_env.ts b/tfjs-core/src/tensor_util_env.ts index 0792952be49..7ff3552ad44 100644 --- a/tfjs-core/src/tensor_util_env.ts +++ b/tfjs-core/src/tensor_util_env.ts @@ -18,7 +18,7 @@ import {ENGINE} from './engine'; import {env} from './environment'; import {Tensor} from './tensor'; -import {DataType, getGPUDataType, GPUDataType, TensorLike, WebGLData, WebGPUData} from './types'; +import {DataType, isWebGLData, isWebGPUData, TensorLike, WebGLData, WebGPUData} from './types'; import {assert, flatten, inferDtype, isTypedArray, toTypedArray} from './util'; import {bytesPerElement} from './util_base'; @@ -31,16 +31,11 @@ export function inferShape( } const gpuDataType = getGPUDataType(val); - if (gpuDataType === GPUDataType.WebGL) { - const usedChannels = (val as WebGLData).channels || 'RGBA'; - return [ - (val as WebGLData).height, (val as WebGLData).width * usedChannels.length - ]; - } else if (gpuDataType === GPUDataType.WebGPU) { - return [ - (val as WebGPUData).buffer.size / - (dtype == null ? 4 : bytesPerElement(dtype)) - ]; + if (isWebGLData(val)) { + const usedChannels = val.channels || 'RGBA'; + return [val.height, val.width * usedChannels.length]; + } else if (isWebGPUData(val)) { + return [val.buffer.size / (dtype == null ? 4 : bytesPerElement(dtype))]; } if (!Array.isArray(val)) { return []; // Scalar. diff --git a/tfjs-core/src/types.ts b/tfjs-core/src/types.ts index 433f19891b5..0feeab5d7ff 100644 --- a/tfjs-core/src/types.ts +++ b/tfjs-core/src/types.ts @@ -197,25 +197,16 @@ export interface WebGPUData { zeroCopy?: boolean; } -export enum GPUDataType { - Unknown = 0, - WebGL = 1, - WebGPU = 2, -} - -export function getGPUDataType(values: TensorLike|WebGLData| - WebGPUData): GPUDataType { - if (typeof values !== 'object') { - // Unknown data type. - return GPUDataType.Unknown; - } - if ('texture' in values && values.texture instanceof WebGLTexture) { - return GPUDataType.WebGL; - } else if ( - 'buffer' in values && typeof GPUBuffer !== 'undefined' && - values.buffer instanceof GPUBuffer) { - return GPUDataType.WebGPU; - } else { - return GPUDataType.Unknown; - } +export function isWebGLData(values: unknown): values is WebGLData { + return values != null + && typeof values === 'object' + && 'texture' in values + && values.texture instanceof WebGLTexture; +} +export function isWebGPUData(values: unknown): values is WebGPUData { + return typeof GPUBuffer !== 'undefined' + && values != null + && typeof values === 'object' + && 'buffer' in values + && values.buffer instanceof GPUBuffer; } From 3fa513cf8fd51365d88b33c71b0637a0a5b27c39 Mon Sep 17 00:00:00 2001 From: Xu Xing Date: Thu, 9 Feb 2023 14:46:36 +0800 Subject: [PATCH 3/4] Update tensor_util_env.ts --- tfjs-core/src/tensor_util_env.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/tfjs-core/src/tensor_util_env.ts b/tfjs-core/src/tensor_util_env.ts index 7ff3552ad44..da71b094592 100644 --- a/tfjs-core/src/tensor_util_env.ts +++ b/tfjs-core/src/tensor_util_env.ts @@ -30,7 +30,6 @@ export function inferShape( return dtype === 'string' ? [] : [val.length]; } - const gpuDataType = getGPUDataType(val); if (isWebGLData(val)) { const usedChannels = val.channels || 'RGBA'; return [val.height, val.width * usedChannels.length]; From 96d72a370a0b1e9b44f48ba29c4b2270c6ce41e5 Mon Sep 17 00:00:00 2001 From: Xu Xing Date: Thu, 9 Feb 2023 15:09:05 +0800 Subject: [PATCH 4/4] Fix lint --- tfjs-core/src/ops/tensor_ops_util.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tfjs-core/src/ops/tensor_ops_util.ts b/tfjs-core/src/ops/tensor_ops_util.ts index 15b725103ad..c38783e254c 100644 --- a/tfjs-core/src/ops/tensor_ops_util.ts +++ b/tfjs-core/src/ops/tensor_ops_util.ts @@ -40,7 +40,7 @@ export function makeTensor( `'float32'|'int32' dtype, while the dtype is ${dtype}.`); } return ENGINE.backend.createTensorFromGPUData( - values as WebGLData | WebGPUData, shape || inferredShape, dtype); + values, shape || inferredShape, dtype); } if (!isTypedArray(values) && !Array.isArray(values) &&