export const description = ` Destroying a texture more than once is allowed. `; import { makeTestGroup } from '../../../../common/framework/test_group.js'; import { kTextureAspects } from '../../../capability_info.js'; import { isDepthTextureFormat, isStencilTextureFormat } from '../../../format_info.js'; import { AllFeaturesMaxLimitsGPUTest } from '../../../gpu_test.js'; import * as vtu from '../validation_test_utils.js'; export const g = makeTestGroup(AllFeaturesMaxLimitsGPUTest); g.test('base') .desc(`Test that it is valid to destroy a texture.`) .fn(t => { const texture = vtu.getSampledTexture(t); texture.destroy(); }); g.test('twice') .desc(`Test that it is valid to destroy a destroyed texture.`) .fn(t => { const texture = vtu.getSampledTexture(t); texture.destroy(); texture.destroy(); }); g.test('invalid_texture') .desc('Test that invalid textures may be destroyed without generating validation errors.') .fn(async t => { t.device.pushErrorScope('validation'); const invalidTexture = t.createTextureTracked({ size: [t.device.limits.maxTextureDimension2D + 1, 1, 1], format: 'rgba8unorm', usage: GPUTextureUsage.TEXTURE_BINDING, }); // Expect error because it's invalid. const error = await t.device.popErrorScope(); t.expect(!!error); // This line should not generate an error invalidTexture.destroy(); }); const kColorTextureFormat: GPUTextureFormat = 'rgba8unorm'; g.test('submit_a_destroyed_texture_as_attachment') .desc( ` Test that it is invalid to submit with a texture as {color, depth, stencil, depth-stencil} attachment that was destroyed {before, after} encoding finishes. ` ) .params(u => u // .combine('depthStencilTextureAspect', kTextureAspects) .combine('colorTextureState', [ 'valid', 'destroyedBeforeEncode', 'destroyedAfterEncode', ] as const) .combine('depthStencilTextureState', [ 'valid', 'destroyedBeforeEncode', 'destroyedAfterEncode', ] as const) ) .fn(t => { const { colorTextureState, depthStencilTextureAspect, depthStencilTextureState } = t.params; const isSubmitSuccess = colorTextureState === 'valid' && depthStencilTextureState === 'valid'; const depthStencilTextureFormat: GPUTextureFormat = depthStencilTextureAspect === 'all' ? 'depth24plus-stencil8' : depthStencilTextureAspect === 'depth-only' ? 'depth32float' : 'stencil8'; const colorTextureDesc: GPUTextureDescriptor = { size: { width: 16, height: 16, depthOrArrayLayers: 1 }, format: kColorTextureFormat, usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT, }; const depthStencilTextureDesc: GPUTextureDescriptor = { size: { width: 16, height: 16, depthOrArrayLayers: 1 }, format: depthStencilTextureFormat, usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT, }; const colorTexture = t.createTextureTracked(colorTextureDesc); const depthStencilTexture = t.createTextureTracked(depthStencilTextureDesc); if (colorTextureState === 'destroyedBeforeEncode') { colorTexture.destroy(); } if (depthStencilTextureState === 'destroyedBeforeEncode') { depthStencilTexture.destroy(); } const commandEncoder = t.device.createCommandEncoder(); const depthStencilAttachment: GPURenderPassDepthStencilAttachment = { view: depthStencilTexture.createView({ aspect: depthStencilTextureAspect }), }; if (isDepthTextureFormat(depthStencilTextureFormat)) { depthStencilAttachment.depthClearValue = 0; depthStencilAttachment.depthLoadOp = 'clear'; depthStencilAttachment.depthStoreOp = 'discard'; } if (isStencilTextureFormat(depthStencilTextureFormat)) { depthStencilAttachment.stencilClearValue = 0; depthStencilAttachment.stencilLoadOp = 'clear'; depthStencilAttachment.stencilStoreOp = 'discard'; } const renderPass = commandEncoder.beginRenderPass({ colorAttachments: [ { view: colorTexture.createView(), clearValue: [0, 0, 0, 0], loadOp: 'clear', storeOp: 'store', }, ], depthStencilAttachment, }); renderPass.end(); const cmd = commandEncoder.finish(); if (colorTextureState === 'destroyedAfterEncode') { colorTexture.destroy(); } if (depthStencilTextureState === 'destroyedAfterEncode') { depthStencilTexture.destroy(); } t.expectValidationError(() => t.queue.submit([cmd]), !isSubmitSuccess); });