(dataId: DataId)
| 318 | } |
| 319 | |
| 320 | override async read(dataId: DataId): Promise<BackendValues> { |
| 321 | if (this.pendingRead.has(dataId)) { |
| 322 | const subscribers = this.pendingRead.get(dataId); |
| 323 | return new Promise<TypedArray>(resolve => subscribers.push(resolve)); |
| 324 | } |
| 325 | const texData = this.texData.get(dataId); |
| 326 | const {values, shape, slice, dtype, complexTensorInfos, isPacked} = texData; |
| 327 | |
| 328 | // The presence of `slice` indicates this tensor is a shallow slice of a |
| 329 | // different tensor, and is using that original tensor's texture. Run |
| 330 | // `clone` in order to copy that texture and read from it. |
| 331 | if (slice != null) { |
| 332 | let program; |
| 333 | if (isPacked) { |
| 334 | program = new UnaryOpPackedProgram(shape, unary_op.CLONE); |
| 335 | } else { |
| 336 | program = new UnaryOpProgram(shape, unary_op.CLONE); |
| 337 | } |
| 338 | const res = |
| 339 | this.runWebGLProgram(program, [{dataId, shape, dtype}], dtype); |
| 340 | const data = this.read(res.dataId); |
| 341 | this.disposeIntermediateTensorInfo(res); |
| 342 | return data; |
| 343 | } |
| 344 | |
| 345 | if (values != null) { |
| 346 | return this.convertAndCacheOnCPU(dataId); |
| 347 | } |
| 348 | |
| 349 | if (env().getBool('DEBUG')) { |
| 350 | // getBool('WEBGL_DOWNLOAD_FLOAT_ENABLED') caused a blocking GPU call. |
| 351 | // For performance reason, only check it for debugging. In production, |
| 352 | // it doesn't handle this use case anyway, so behavior is not changed. |
| 353 | if (!env().getBool('WEBGL_DOWNLOAD_FLOAT_ENABLED') && |
| 354 | env().getNumber('WEBGL_VERSION') === 2) { |
| 355 | throw new Error( |
| 356 | `tensor.data() with WEBGL_DOWNLOAD_FLOAT_ENABLED=false and ` + |
| 357 | `WEBGL_VERSION=2 not yet supported.`); |
| 358 | } |
| 359 | } |
| 360 | |
| 361 | let buffer: WebGLBuffer = null; |
| 362 | let tmpDownloadTarget: TensorInfo; |
| 363 | |
| 364 | if (dtype !== 'complex64' && env().get('WEBGL_BUFFER_SUPPORTED')) { |
| 365 | // Possibly copy the texture into a buffer before inserting a fence. |
| 366 | tmpDownloadTarget = this.decode(dataId); |
| 367 | const tmpData = this.texData.get(tmpDownloadTarget.dataId); |
| 368 | |
| 369 | buffer = this.gpgpu.createBufferFromTexture( |
| 370 | tmpData.texture.texture, ...tex_util.getDenseTexShape(shape)); |
| 371 | } |
| 372 | |
| 373 | this.pendingRead.set(dataId, []); |
| 374 | |
| 375 | if (dtype !== 'complex64') { |
| 376 | // Create a fence and wait for it to resolve. |
| 377 | await this.gpgpu.createAndWaitForFence(); |
nothing calls this directly
no test coverage detected