blob: 1f64e2f8b35698bf372937bda42c8c2360984085 [file] [log] [blame]
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);
});