| export const description = ` |
| Tests that TypedArrays created when mapping a GPUBuffer are detached when the |
| buffer is unmapped or destroyed. |
| `; |
| |
| import { makeTestGroup } from '../../../../common/framework/test_group.js'; |
| import { getGPU } from '../../../../common/util/navigator_gpu.js'; |
| import { assert } from '../../../../common/util/util.js'; |
| import { GPUConst } from '../../../constants.js'; |
| import { AllFeaturesMaxLimitsGPUTest } from '../../../gpu_test.js'; |
| |
| export const g = makeTestGroup(AllFeaturesMaxLimitsGPUTest); |
| |
| g.test('while_mapped') |
| .desc( |
| ` |
| Test that a mapped buffers are able to properly detach. |
| - Tests {mappable, unmappable mapAtCreation, mappable mapAtCreation} |
| - Tests while {mapped, mapped at creation, mapped at creation then unmapped and mapped again} |
| - When {unmap, destroy, unmap && destroy, device.destroy} is called` |
| ) |
| .paramsSubcasesOnly(u => |
| u |
| .combine('mappedAtCreation', [false, true]) |
| .combineWithParams([ |
| { usage: GPUConst.BufferUsage.COPY_SRC }, |
| { usage: GPUConst.BufferUsage.MAP_WRITE | GPUConst.BufferUsage.COPY_SRC }, |
| { usage: GPUConst.BufferUsage.COPY_DST | GPUConst.BufferUsage.MAP_READ }, |
| { |
| usage: GPUConst.BufferUsage.MAP_WRITE | GPUConst.BufferUsage.COPY_SRC, |
| mapMode: GPUConst.MapMode.WRITE, |
| }, |
| { |
| usage: GPUConst.BufferUsage.COPY_DST | GPUConst.BufferUsage.MAP_READ, |
| mapMode: GPUConst.MapMode.READ, |
| }, |
| ]) |
| .combineWithParams([ |
| { unmap: true, destroy: false }, |
| { unmap: false, destroy: true }, |
| { unmap: true, destroy: true }, |
| { unmap: false, destroy: false, deviceDestroy: true }, |
| ]) |
| .unless(p => p.mappedAtCreation === false && p.mapMode === undefined) |
| ) |
| .fn(async t => { |
| const { usage, mapMode, mappedAtCreation, unmap, destroy, deviceDestroy } = t.params; |
| |
| let device: GPUDevice = t.device; |
| if (deviceDestroy) { |
| const adapter = await getGPU(t.rec).requestAdapter(); |
| assert(adapter !== null); |
| device = await t.requestDeviceTracked(adapter); |
| } |
| const buffer = t.trackForCleanup( |
| device.createBuffer({ |
| size: 4, |
| usage, |
| mappedAtCreation, |
| }) |
| ); |
| |
| if (mapMode !== undefined) { |
| if (mappedAtCreation) { |
| buffer.unmap(); |
| } |
| await buffer.mapAsync(mapMode); |
| } |
| |
| const arrayBuffer = buffer.getMappedRange(); |
| const view = new Uint8Array(arrayBuffer); |
| t.expect(arrayBuffer.byteLength === 4); |
| t.expect(view.length === 4); |
| |
| if (unmap) buffer.unmap(); |
| if (destroy) buffer.destroy(); |
| if (deviceDestroy) device.destroy(); |
| |
| t.expect(arrayBuffer.byteLength === 0, 'ArrayBuffer should be detached'); |
| t.expect(view.byteLength === 0, 'ArrayBufferView should be detached'); |
| }); |