Skip to content

Commit ec5ad7d

Browse files
committed
Start adding queue validation tests for buffers and textures
1 parent a1efadf commit ec5ad7d

File tree

2 files changed

+305
-0
lines changed

2 files changed

+305
-0
lines changed
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
export const description = `
2+
Tests using a destroyed buffer on a queue.
3+
4+
TODO:
5+
- test renderPass/renderBundle (setVertexBuffer, setIndexBuffer)
6+
- test renderPass (resolveQuerySet)
7+
- test renderPass/computePass (setBindGroup)
8+
`;
9+
10+
import { makeTestGroup } from '../../../../../common/framework/test_group.js';
11+
import { ValidationTest } from '../../validation_test.js';
12+
13+
export const g = makeTestGroup(ValidationTest);
14+
15+
g.test('writeBuffer')
16+
.desc(
17+
`
18+
Tests that using a destroyed buffer in writeBuffer fails.
19+
- x= {destroyed, not destroyed (control case)}
20+
`
21+
)
22+
.paramsSubcasesOnly(u => u.combine('destroyed', [false, true] as const))
23+
.fn(t => {
24+
const { destroyed } = t.params;
25+
const buffer = t.trackForCleanup(
26+
t.device.createBuffer({
27+
size: 4,
28+
usage: GPUBufferUsage.COPY_DST,
29+
})
30+
);
31+
32+
if (destroyed) {
33+
buffer.destroy();
34+
}
35+
36+
t.expectValidationError(() => t.queue.writeBuffer(buffer, 0, new Uint8Array(4)), destroyed);
37+
});
38+
39+
g.test('copyBufferToBuffer')
40+
.desc(
41+
`
42+
Tests that using a destroyed buffer in copyBufferToBuffer fails.
43+
- x= {not destroyed (control case), src destroyed, dst destroyed}
44+
`
45+
)
46+
.paramsSubcasesOnly(u => u.combine('destroyed', ['none', 'src', 'dst', 'both'] as const))
47+
.fn(t => {
48+
const src = t.trackForCleanup(
49+
t.device.createBuffer({ size: 4, usage: GPUBufferUsage.COPY_SRC })
50+
);
51+
const dst = t.trackForCleanup(
52+
t.device.createBuffer({ size: 4, usage: GPUBufferUsage.COPY_DST })
53+
);
54+
55+
const encoder = t.device.createCommandEncoder();
56+
encoder.copyBufferToBuffer(src, 0, dst, 0, dst.size);
57+
const commandBuffer = encoder.finish();
58+
59+
let shouldError = true;
60+
switch (t.params.destroyed) {
61+
case 'none':
62+
shouldError = false;
63+
break;
64+
case 'src':
65+
src.destroy();
66+
break;
67+
case 'dst':
68+
dst.destroy();
69+
break;
70+
case 'both':
71+
src.destroy();
72+
dst.destroy();
73+
break;
74+
}
75+
76+
t.expectValidationError(() => {
77+
t.queue.submit([commandBuffer]);
78+
}, shouldError);
79+
});
80+
81+
g.test('copyBufferToTexture')
82+
.desc(
83+
`
84+
Tests that using a destroyed buffer in copyBufferToTexture fails.
85+
- x= {not destroyed (control case), src destroyed}
86+
`
87+
)
88+
.paramsSubcasesOnly(u => u.combine('destroyed', [false, true] as const))
89+
.fn(t => {
90+
const { destroyed } = t.params;
91+
const buffer = t.trackForCleanup(
92+
t.device.createBuffer({ size: 4, usage: GPUBufferUsage.COPY_SRC })
93+
);
94+
const texture = t.trackForCleanup(
95+
t.device.createTexture({
96+
size: [1, 1, 1],
97+
format: 'rgba8unorm',
98+
usage: GPUTextureUsage.COPY_DST,
99+
})
100+
);
101+
102+
const encoder = t.device.createCommandEncoder();
103+
encoder.copyBufferToTexture({ buffer }, { texture }, [1, 1, 1]);
104+
const commandBuffer = encoder.finish();
105+
106+
if (destroyed) {
107+
buffer.destroy();
108+
}
109+
110+
t.expectValidationError(() => {
111+
t.queue.submit([commandBuffer]);
112+
}, destroyed);
113+
});
114+
115+
g.test('copyTextureToBuffer')
116+
.desc(
117+
`
118+
Tests that using a destroyed buffer in copyTextureToBuffer fails.
119+
- x= {not destroyed (control case), dst destroyed}
120+
`
121+
)
122+
.paramsSubcasesOnly(u => u.combine('destroyed', [false, true] as const))
123+
.fn(t => {
124+
const { destroyed } = t.params;
125+
const texture = t.trackForCleanup(
126+
t.device.createTexture({
127+
size: [1, 1, 1],
128+
format: 'rgba8unorm',
129+
usage: GPUTextureUsage.COPY_SRC,
130+
})
131+
);
132+
const buffer = t.trackForCleanup(
133+
t.device.createBuffer({ size: 4, usage: GPUBufferUsage.COPY_DST })
134+
);
135+
136+
const encoder = t.device.createCommandEncoder();
137+
encoder.copyTextureToBuffer({ texture }, { buffer }, [1, 1, 1]);
138+
const commandBuffer = encoder.finish();
139+
140+
if (destroyed) {
141+
buffer.destroy();
142+
}
143+
144+
t.expectValidationError(() => {
145+
t.queue.submit([commandBuffer]);
146+
}, destroyed);
147+
});
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
export const description = `
2+
Tests using a destroyed texture on a queue.
3+
4+
TODO:
5+
- test renderPass/computePass (setBindGroup)
6+
- test beginRenderPass target
7+
`;
8+
9+
import { makeTestGroup } from '../../../../../common/framework/test_group.js';
10+
import { ValidationTest } from '../../validation_test.js';
11+
12+
export const g = makeTestGroup(ValidationTest);
13+
14+
g.test('writeTexture')
15+
.desc(
16+
`
17+
Tests that using a destroyed texture in writeTexture fails.
18+
- x= {destroyed, not destroyed (control case)}
19+
`
20+
)
21+
.paramsSubcasesOnly(u => u.combine('destroyed', [false, true] as const))
22+
.fn(t => {
23+
const { destroyed } = t.params;
24+
const texture = t.trackForCleanup(
25+
t.device.createTexture({
26+
size: [1, 1, 1],
27+
format: 'rgba8unorm',
28+
usage: GPUTextureUsage.COPY_DST,
29+
})
30+
);
31+
32+
if (destroyed) {
33+
texture.destroy();
34+
}
35+
36+
t.expectValidationError(
37+
() => t.queue.writeTexture({ texture }, new Uint8Array(4), { bytesPerRow: 4 }, [1, 1, 1]),
38+
destroyed
39+
);
40+
});
41+
42+
g.test('copyTextureToTexture')
43+
.desc(
44+
`
45+
Tests that using a destroyed texture in copyTextureToTexture fails.
46+
- x= {not destroyed (control case), src destroyed, dst destroyed}
47+
`
48+
)
49+
.paramsSubcasesOnly(u => u.combine('destroyed', ['none', 'src', 'dst', 'both'] as const))
50+
.fn(t => {
51+
const src = t.trackForCleanup(
52+
t.device.createTexture({
53+
size: [1, 1, 1],
54+
format: 'rgba8unorm',
55+
usage: GPUTextureUsage.COPY_SRC,
56+
})
57+
);
58+
const dst = t.trackForCleanup(
59+
t.device.createTexture({
60+
size: [1, 1, 1],
61+
format: 'rgba8unorm',
62+
usage: GPUTextureUsage.COPY_DST,
63+
})
64+
);
65+
66+
const encoder = t.device.createCommandEncoder();
67+
encoder.copyTextureToTexture({ texture: src }, { texture: dst }, [1, 1, 1]);
68+
const commandBuffer = encoder.finish();
69+
70+
let shouldError = true;
71+
switch (t.params.destroyed) {
72+
case 'none':
73+
shouldError = false;
74+
break;
75+
case 'src':
76+
src.destroy();
77+
break;
78+
case 'dst':
79+
dst.destroy();
80+
break;
81+
case 'both':
82+
src.destroy();
83+
dst.destroy();
84+
break;
85+
}
86+
87+
t.expectValidationError(() => {
88+
t.queue.submit([commandBuffer]);
89+
}, shouldError);
90+
});
91+
92+
g.test('copyBufferToTexture')
93+
.desc(
94+
`
95+
Tests that using a destroyed texture in copyBufferToTexture fails.
96+
- x= {not destroyed (control case), dst destroyed}
97+
`
98+
)
99+
.paramsSubcasesOnly(u => u.combine('destroyed', [false, true] as const))
100+
.fn(t => {
101+
const { destroyed } = t.params;
102+
const buffer = t.trackForCleanup(
103+
t.device.createBuffer({ size: 4, usage: GPUBufferUsage.COPY_SRC })
104+
);
105+
const texture = t.trackForCleanup(
106+
t.device.createTexture({
107+
size: [1, 1, 1],
108+
format: 'rgba8unorm',
109+
usage: GPUTextureUsage.COPY_DST,
110+
})
111+
);
112+
113+
const encoder = t.device.createCommandEncoder();
114+
encoder.copyBufferToTexture({ buffer }, { texture }, [1, 1, 1]);
115+
const commandBuffer = encoder.finish();
116+
117+
if (destroyed) {
118+
texture.destroy();
119+
}
120+
121+
t.expectValidationError(() => {
122+
t.queue.submit([commandBuffer]);
123+
}, destroyed);
124+
});
125+
126+
g.test('copyTextureToBuffer')
127+
.desc(
128+
`
129+
Tests that using a destroyed texture in copyTextureToBuffer fails.
130+
- x= {not destroyed (control case), src destroyed}
131+
`
132+
)
133+
.paramsSubcasesOnly(u => u.combine('destroyed', [false, true] as const))
134+
.fn(t => {
135+
const { destroyed } = t.params;
136+
const texture = t.trackForCleanup(
137+
t.device.createTexture({
138+
size: [1, 1, 1],
139+
format: 'rgba8unorm',
140+
usage: GPUTextureUsage.COPY_SRC,
141+
})
142+
);
143+
const buffer = t.trackForCleanup(
144+
t.device.createBuffer({ size: 4, usage: GPUBufferUsage.COPY_DST })
145+
);
146+
147+
const encoder = t.device.createCommandEncoder();
148+
encoder.copyTextureToBuffer({ texture }, { buffer }, [1, 1, 1]);
149+
const commandBuffer = encoder.finish();
150+
151+
if (destroyed) {
152+
texture.destroy();
153+
}
154+
155+
t.expectValidationError(() => {
156+
t.queue.submit([commandBuffer]);
157+
}, destroyed);
158+
});

0 commit comments

Comments
 (0)