blob: 23e2b4ff6618d7e778a4d81d8cc7f35ea1f748d3 [file] [log] [blame]
/**
* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
**/ export const description = `
API validation tests for dynamic state commands (setViewport/ScissorRect/BlendColor...).
TODO: ensure existing tests cover these notes. Note many of these may be operation tests instead.
> - setViewport
> - {x, y} = {0, invalid values if any}
> - {width, height, minDepth, maxDepth} = {
> - least possible value that's valid
> - greatest possible negative value that's invalid
> - greatest possible positive value that's valid
> - least possible positive value that's invalid if any
> - }
> - minDepth {<, =, >} maxDepth
> - setScissorRect
> - {width, height} = 0
> - {x+width, y+height} = attachment size + 1
> - setBlendColor
> - color {slightly, very} out of range
> - used with a simple pipeline that {does, doesn't} use it
> - setStencilReference
> - {0, max}
> - used with a simple pipeline that {does, doesn't} use it
`;
import { params } from '../../../../../../common/framework/params_builder.js';
import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
import { ValidationTest } from '../../../validation_test.js';
class F extends ValidationTest {
testViewportCall(success, v, attachmentSize = { width: 1, height: 1, depth: 1 }) {
const attachment = this.device.createTexture({
format: 'rgba8unorm',
size: attachmentSize,
usage: GPUTextureUsage.OUTPUT_ATTACHMENT,
});
const encoder = this.device.createCommandEncoder();
const pass = encoder.beginRenderPass({
colorAttachments: [
{
attachment: attachment.createView(),
loadValue: 'load',
},
],
});
pass.setViewport(v.x, v.y, v.w, v.h, v.minDepth, v.maxDepth);
pass.endPass();
this.expectValidationError(() => {
encoder.finish();
}, !success);
}
testScissorCall(success, s, attachmentSize = { width: 1, height: 1, depth: 1 }) {
const attachment = this.device.createTexture({
format: 'rgba8unorm',
size: attachmentSize,
usage: GPUTextureUsage.OUTPUT_ATTACHMENT,
});
const encoder = this.device.createCommandEncoder();
const pass = encoder.beginRenderPass({
colorAttachments: [
{
attachment: attachment.createView(),
loadValue: 'load',
},
],
});
if (success === 'type-error') {
this.shouldThrow('TypeError', () => {
pass.setScissorRect(s.x, s.y, s.w, s.h);
});
} else {
pass.setScissorRect(s.x, s.y, s.w, s.h);
pass.endPass();
this.expectValidationError(() => {
encoder.finish();
}, !success);
}
}
createDummyRenderPassEncoder() {
const attachment = this.device.createTexture({
format: 'rgba8unorm',
size: [1, 1, 1],
usage: GPUTextureUsage.OUTPUT_ATTACHMENT,
});
const encoder = this.device.createCommandEncoder();
const pass = encoder.beginRenderPass({
colorAttachments: [
{
attachment: attachment.createView(),
loadValue: 'load',
},
],
});
return { encoder, pass };
}
}
export const g = makeTestGroup(F);
g.test('setViewport,x_y_width_height_nonnegative')
.desc('Test that the parameters of setViewport to define the box must be non-negative.')
.params([
// Control case: everything to 0 is ok, covers the empty viewport case.
{ x: 0, y: 0, w: 0, h: 0 },
// Test -1
{ x: -1, y: 0, w: 0, h: 0 },
{ x: 0, y: -1, w: 0, h: 0 },
{ x: 0, y: 0, w: -1, h: 0 },
{ x: 0, y: 0, w: 0, h: -1 },
// TODO Test -0 (it should be valid) but can't be tested because the harness complains about duplicate parameters.
// TODO Test the first value smaller than -0
])
.fn(t => {
const { x, y, w, h } = t.params;
const success = x >= 0 && y >= 0 && w >= 0 && h >= 0;
t.testViewportCall(success, { x, y, w, h, minDepth: 0, maxDepth: 1 });
});
g.test('setViewport,xy_rect_contained_in_attachment')
.desc(
'Test that the rectangle defined by x, y, width, height must be contained in the attachments'
)
.params(
params()
.combine([
{ attachmentWidth: 3, attachmentHeight: 5 },
{ attachmentWidth: 5, attachmentHeight: 3 },
{ attachmentWidth: 1024, attachmentHeight: 1 },
{ attachmentWidth: 1, attachmentHeight: 1024 },
])
.combine([
// Control case: a full viewport is valid.
{ dx: 0, dy: 0, dw: 0, dh: 0 },
// Other valid cases with a partial viewport.
{ dx: 1, dy: 0, dw: -1, dh: 0 },
{ dx: 0, dy: 1, dw: 0, dh: -1 },
{ dx: 0, dy: 0, dw: -1, dh: 0 },
{ dx: 0, dy: 0, dw: 0, dh: -1 },
// Test with a small value that causes the viewport to go outside the attachment.
{ dx: 1, dy: 0, dw: 0, dh: 0 },
{ dx: 0, dy: 1, dw: 0, dh: 0 },
{ dx: 0, dy: 0, dw: 1, dh: 0 },
{ dx: 0, dy: 0, dw: 0, dh: 1 },
])
)
.fn(t => {
const { attachmentWidth, attachmentHeight, dx, dy, dw, dh } = t.params;
const x = dx;
const y = dy;
const w = attachmentWidth + dw;
const h = attachmentWidth + dh;
const success = x + w <= attachmentWidth && y + h <= attachmentHeight;
t.testViewportCall(
success,
{ x, y, w, h, minDepth: 0, maxDepth: 1 },
{ width: attachmentWidth, height: attachmentHeight, depth: 1 }
);
});
g.test('setViewport,depth_rangeAndOrder')
.desc('Test that 0 <= minDepth <= maxDepth <= 1')
.params([
// Success cases
{ minDepth: 0, maxDepth: 1 },
{ minDepth: -0, maxDepth: -0 },
{ minDepth: 1, maxDepth: 1 },
{ minDepth: 0.3, maxDepth: 0.7 },
{ minDepth: 0.7, maxDepth: 0.7 },
{ minDepth: 0.3, maxDepth: 0.3 },
// Invalid cases
{ minDepth: -0.1, maxDepth: 1 },
{ minDepth: 0, maxDepth: 1.1 },
{ minDepth: 0.5, maxDepth: 0.49999 },
])
.fn(t => {
const { minDepth, maxDepth } = t.params;
const success =
0 <= minDepth && minDepth <= 1 && 0 <= maxDepth && maxDepth <= 1 && minDepth <= maxDepth;
t.testViewportCall(success, { x: 0, y: 0, w: 1, h: 1, minDepth, maxDepth });
});
g.test('setScissorRect,x_y_width_height_nonnegative')
.desc(
'Test that the parameters of setScissorRect to define the box must be non-negative or a TypeError is thrown.'
)
.params([
// Control case: everything to 0 is ok, covers the empty scissor case.
{ x: 0, y: 0, w: 0, h: 0 },
// Test -1
{ x: -1, y: 0, w: 0, h: 0 },
{ x: 0, y: -1, w: 0, h: 0 },
{ x: 0, y: 0, w: -1, h: 0 },
{ x: 0, y: 0, w: 0, h: -1 },
// TODO Test -0 (it should be valid) but can't be tested because the harness complains about duplicate parameters.
// TODO Test the first value smaller than -0
])
.fn(t => {
const { x, y, w, h } = t.params;
const success = x >= 0 && y >= 0 && w >= 0 && h >= 0;
t.testScissorCall(success ? true : 'type-error', { x, y, w, h });
});
g.test('setScissorRect,xy_rect_contained_in_attachment')
.desc(
'Test that the rectangle defined by x, y, width, height must be contained in the attachments'
)
.params(
params()
.combine([
{ attachmentWidth: 3, attachmentHeight: 5 },
{ attachmentWidth: 5, attachmentHeight: 3 },
{ attachmentWidth: 1024, attachmentHeight: 1 },
{ attachmentWidth: 1, attachmentHeight: 1024 },
])
.combine([
// Control case: a full scissor is valid.
{ dx: 0, dy: 0, dw: 0, dh: 0 },
// Other valid cases with a partial scissor.
{ dx: 1, dy: 0, dw: -1, dh: 0 },
{ dx: 0, dy: 1, dw: 0, dh: -1 },
{ dx: 0, dy: 0, dw: -1, dh: 0 },
{ dx: 0, dy: 0, dw: 0, dh: -1 },
// Test with a small value that causes the scissor to go outside the attachment.
{ dx: 1, dy: 0, dw: 0, dh: 0 },
{ dx: 0, dy: 1, dw: 0, dh: 0 },
{ dx: 0, dy: 0, dw: 1, dh: 0 },
{ dx: 0, dy: 0, dw: 0, dh: 1 },
])
)
.fn(t => {
const { attachmentWidth, attachmentHeight, dx, dy, dw, dh } = t.params;
const x = dx;
const y = dy;
const w = attachmentWidth + dw;
const h = attachmentWidth + dh;
const success = x + w <= attachmentWidth && y + h <= attachmentHeight;
t.testScissorCall(
success,
{ x, y, w, h },
{ width: attachmentWidth, height: attachmentHeight, depth: 1 }
);
});
g.test('setBlendColor')
.desc('Test that almost any color value is valid for setBlendColor')
.params([
{ r: 1.0, g: 1.0, b: 1.0, a: 1.0 },
{ r: -1.0, g: -1.0, b: -1.0, a: -1.0 },
{ r: Number.MAX_SAFE_INTEGER, g: Number.MIN_SAFE_INTEGER, b: -0, a: 100000 },
])
.fn(t => {
const { r, g, b, a } = t.params;
const encoders = t.createDummyRenderPassEncoder();
encoders.pass.setBlendColor({ r, g, b, a });
encoders.pass.endPass();
encoders.encoder.finish();
});
g.test('setStencilReference')
.desc('Test that almost any stencil reference value is valid for setStencilReference')
.params([
{ value: 1 }, //
{ value: 0 },
{ value: 1000 },
{ value: 0xffffffff },
])
.fn(t => {
const { value } = t.params;
const encoders = t.createDummyRenderPassEncoder();
encoders.pass.setStencilReference(value);
encoders.pass.endPass();
encoders.encoder.finish();
});