blob: a3a86c8609c07468df53d2cce40e6d7dcf254347 [file] [edit]
<script src="../../resources/js-test.js"></script>
<script>
jsTestIsAsync = true;
// Only the name of the exception is part of the contract, so the message is left out of the output.
function shouldThrowTypeError(expression)
{
let name = '';
try {
eval(expression);
} catch (e) {
name = e.name;
}
if (name === 'TypeError')
testPassed(expression + ' threw a TypeError.');
else if (name)
testFailed(expression + ' threw a ' + name + ' instead of a TypeError.');
else
testFailed(expression + ' did not throw.');
}
const textureDescriptor = {
size: [1, 1],
format: 'rgba8unorm',
usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.STORAGE_BINDING,
};
onload = async () => {
const adapter = await navigator.gpu.requestAdapter({});
globalThis.featureAdvertised = adapter.features.has('texture-component-swizzle');
shouldBeTrue('featureAdvertised');
globalThis.device = await adapter.requestDevice({});
globalThis.texture = device.createTexture(textureDescriptor);
// Validating the swizzle string happens on the content timeline, so a string that is not
// ^[rgba01]{4}$ throws whether or not the device enabled the feature.
shouldThrowTypeError('texture.createView({ swizzle: "" })');
shouldThrowTypeError('texture.createView({ swizzle: "rgb" })');
shouldThrowTypeError('texture.createView({ swizzle: "rgbaa" })');
shouldThrowTypeError('texture.createView({ swizzle: "rgbx" })');
shouldThrowTypeError('texture.createView({ swizzle: "RGBA" })');
// The identity swizzle needs no feature.
device.pushErrorScope('validation');
texture.createView({ swizzle: 'rgba' });
globalThis.identityError = await device.popErrorScope();
shouldBeNull('identityError');
// Any other one does.
device.pushErrorScope('validation');
texture.createView({ swizzle: 'bgra' });
globalThis.ungatedError = await device.popErrorScope();
shouldBeTrue('ungatedError instanceof GPUValidationError');
// An adapter is consumed by requestDevice(), so the feature-enabled device needs a fresh one.
const swizzleAdapter = await navigator.gpu.requestAdapter({});
globalThis.swizzleDevice = await swizzleAdapter.requestDevice({ requiredFeatures: ['texture-component-swizzle'] });
globalThis.swizzleTexture = swizzleDevice.createTexture(textureDescriptor);
swizzleDevice.pushErrorScope('validation');
globalThis.swizzledView = swizzleTexture.createView({ swizzle: '01ba' });
globalThis.gatedError = await swizzleDevice.popErrorScope();
shouldBeNull('gatedError');
// A swizzle describes how a shader reads a view, so a view with one is not renderable.
swizzleDevice.pushErrorScope('validation');
const commandEncoder = swizzleDevice.createCommandEncoder();
commandEncoder.beginRenderPass({
colorAttachments: [{ view: swizzledView, loadOp: 'clear', storeOp: 'store' }],
}).end();
commandEncoder.finish();
globalThis.attachmentError = await swizzleDevice.popErrorScope();
shouldBeTrue('attachmentError instanceof GPUValidationError');
// Nor may it back a storage binding.
swizzleDevice.pushErrorScope('validation');
swizzleDevice.createBindGroup({
layout: swizzleDevice.createBindGroupLayout({
entries: [
{ binding: 0, visibility: GPUShaderStage.COMPUTE, storageTexture: { access: 'write-only', format: 'rgba8unorm' } },
],
}),
entries: [
{ binding: 0, resource: swizzledView },
],
});
globalThis.storageError = await swizzleDevice.popErrorScope();
shouldBeTrue('storageError instanceof GPUValidationError');
finishJSTest();
};
</script>