mirror of
https://github.com/denoland/deno
synced 2024-10-04 07:09:20 +00:00
fix(ext/webgpu): correctly validate GPUExtent3D, GPUOrigin3D, GPUOrigin2D & GPUColor (#23413)
This commit is contained in:
parent
4ab68df33e
commit
a635abbf21
|
@ -1136,10 +1136,11 @@ class GPUDevice extends EventTarget {
|
|||
"Argument 1",
|
||||
);
|
||||
const device = assertDevice(this, prefix, "this");
|
||||
// assign normalized size to descriptor due to createGPUTexture needs it
|
||||
descriptor.size = normalizeGPUExtent3D(descriptor.size);
|
||||
const { rid, err } = op_webgpu_create_texture({
|
||||
deviceRid: device.rid,
|
||||
...descriptor,
|
||||
size: normalizeGPUExtent3D(descriptor.size),
|
||||
});
|
||||
device.pushError(err);
|
||||
|
||||
|
@ -5501,6 +5502,16 @@ webidl.converters["GPUExtent3D"] = (V, opts) => {
|
|||
if (typeof V === "object") {
|
||||
const method = V[SymbolIterator];
|
||||
if (method !== undefined) {
|
||||
// validate length of GPUExtent3D
|
||||
const min = 1;
|
||||
const max = 3;
|
||||
if (V.length < min || V.length > max) {
|
||||
throw webidl.makeException(
|
||||
TypeError,
|
||||
`A sequence of number used as a GPUExtent3D must have between ${min} and ${max} elements.`,
|
||||
opts,
|
||||
);
|
||||
}
|
||||
return webidl.converters["sequence<GPUIntegerCoordinate>"](V, opts);
|
||||
}
|
||||
return webidl.converters["GPUExtent3DDict"](V, opts);
|
||||
|
@ -6836,6 +6847,15 @@ webidl.converters["GPUOrigin3D"] = (V, opts) => {
|
|||
if (typeof V === "object") {
|
||||
const method = V[SymbolIterator];
|
||||
if (method !== undefined) {
|
||||
// validate length of GPUOrigin3D
|
||||
const length = 3;
|
||||
if (V.length > length) {
|
||||
throw webidl.makeException(
|
||||
TypeError,
|
||||
`A sequence of number used as a GPUOrigin3D must have at most ${length} elements.`,
|
||||
opts,
|
||||
);
|
||||
}
|
||||
return webidl.converters["sequence<GPUIntegerCoordinate>"](V, opts);
|
||||
}
|
||||
return webidl.converters["GPUOrigin3DDict"](V, opts);
|
||||
|
@ -6904,6 +6924,15 @@ webidl.converters["GPUOrigin2D"] = (V, opts) => {
|
|||
if (typeof V === "object") {
|
||||
const method = V[SymbolIterator];
|
||||
if (method !== undefined) {
|
||||
// validate length of GPUOrigin2D
|
||||
const length = 2;
|
||||
if (V.length > length) {
|
||||
throw webidl.makeException(
|
||||
TypeError,
|
||||
`A sequence of number used as a GPUOrigin2D must have at most ${length} elements.`,
|
||||
opts,
|
||||
);
|
||||
}
|
||||
return webidl.converters["sequence<GPUIntegerCoordinate>"](V, opts);
|
||||
}
|
||||
return webidl.converters["GPUOrigin2DDict"](V, opts);
|
||||
|
@ -6989,6 +7018,15 @@ webidl.converters["GPUColor"] = (V, opts) => {
|
|||
if (typeof V === "object") {
|
||||
const method = V[SymbolIterator];
|
||||
if (method !== undefined) {
|
||||
// validate length of GPUColor
|
||||
const length = 4;
|
||||
if (V.length !== length) {
|
||||
throw webidl.makeException(
|
||||
TypeError,
|
||||
`A sequence of number used as a GPUColor must have exactly ${length} elements.`,
|
||||
opts,
|
||||
);
|
||||
}
|
||||
return webidl.converters["sequence<double>"](V, opts);
|
||||
}
|
||||
return webidl.converters["GPUColorDict"](V, opts);
|
||||
|
|
|
@ -252,6 +252,268 @@ Deno.test(function getPreferredCanvasFormat() {
|
|||
assert(preferredFormat === "bgra8unorm" || preferredFormat === "rgba8unorm");
|
||||
});
|
||||
|
||||
Deno.test({
|
||||
ignore: isWsl || isLinuxOrMacCI,
|
||||
}, async function validateGPUColor() {
|
||||
const adapter = await navigator.gpu.requestAdapter();
|
||||
assert(adapter);
|
||||
const device = await adapter.requestDevice();
|
||||
assert(device);
|
||||
|
||||
const format = "rgba8unorm-srgb";
|
||||
const encoder = device.createCommandEncoder();
|
||||
const texture = device.createTexture({
|
||||
size: [256, 256],
|
||||
format,
|
||||
usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC,
|
||||
});
|
||||
const view = texture.createView();
|
||||
const storeOp = "store";
|
||||
const loadOp = "clear";
|
||||
|
||||
// values for validating GPUColor
|
||||
const invalidSize = [0, 0, 0];
|
||||
|
||||
const msgIncludes =
|
||||
"A sequence of number used as a GPUColor must have exactly 4 elements.";
|
||||
|
||||
// validate the argument of descriptor.colorAttachments[@@iterator].clearValue property's length of GPUCommandEncoder.beginRenderPass when its a sequence
|
||||
// https://www.w3.org/TR/2024/WD-webgpu-20240409/#dom-gpucommandencoder-beginrenderpass
|
||||
assertThrows(
|
||||
() =>
|
||||
encoder.beginRenderPass({
|
||||
colorAttachments: [
|
||||
{
|
||||
view,
|
||||
storeOp,
|
||||
loadOp,
|
||||
clearValue: invalidSize,
|
||||
},
|
||||
],
|
||||
}),
|
||||
TypeError,
|
||||
msgIncludes,
|
||||
);
|
||||
const renderPass = encoder.beginRenderPass({
|
||||
colorAttachments: [
|
||||
{
|
||||
view,
|
||||
storeOp,
|
||||
loadOp,
|
||||
clearValue: [0, 0, 0, 1],
|
||||
},
|
||||
],
|
||||
});
|
||||
// validate the argument of color length of GPURenderPassEncoder.setBlendConstant when its a sequence
|
||||
// https://www.w3.org/TR/2024/WD-webgpu-20240409/#dom-gpurenderpassencoder-setblendconstant
|
||||
assertThrows(
|
||||
() => renderPass.setBlendConstant(invalidSize),
|
||||
TypeError,
|
||||
msgIncludes,
|
||||
);
|
||||
|
||||
device.destroy();
|
||||
const resources = Object.keys(Deno.resources());
|
||||
Deno.close(Number(resources[resources.length - 1]));
|
||||
});
|
||||
|
||||
Deno.test({
|
||||
ignore: isWsl || isLinuxOrMacCI,
|
||||
}, async function validateGPUExtent3D() {
|
||||
const adapter = await navigator.gpu.requestAdapter();
|
||||
assert(adapter);
|
||||
const device = await adapter.requestDevice();
|
||||
assert(device);
|
||||
|
||||
const format = "rgba8unorm-srgb";
|
||||
const encoder = device.createCommandEncoder();
|
||||
const buffer = device.createBuffer({
|
||||
size: new Uint32Array([1, 4, 3, 295]).byteLength,
|
||||
usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST,
|
||||
});
|
||||
const usage = GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC;
|
||||
const texture = device.createTexture({
|
||||
size: [256, 256],
|
||||
format,
|
||||
usage,
|
||||
});
|
||||
|
||||
// values for validating GPUExtent3D
|
||||
const belowSize: Array<number> = [];
|
||||
const overSize = [256, 256, 1, 1];
|
||||
|
||||
const msgIncludes =
|
||||
"A sequence of number used as a GPUExtent3D must have between 1 and 3 elements.";
|
||||
|
||||
// validate the argument of descriptor.size property's length of GPUDevice.createTexture when its a sequence
|
||||
// https://www.w3.org/TR/2024/WD-webgpu-20240409/#dom-gpudevice-createtexture
|
||||
assertThrows(
|
||||
() => device.createTexture({ size: belowSize, format, usage }),
|
||||
TypeError,
|
||||
msgIncludes,
|
||||
);
|
||||
assertThrows(
|
||||
() => device.createTexture({ size: overSize, format, usage }),
|
||||
TypeError,
|
||||
msgIncludes,
|
||||
);
|
||||
// validate the argument of copySize property's length of GPUCommandEncoder.copyBufferToTexture when its a sequence
|
||||
// https://www.w3.org/TR/2024/WD-webgpu-20240409/#dom-gpucommandencoder-copybuffertotexture
|
||||
assertThrows(
|
||||
() => encoder.copyBufferToTexture({ buffer }, { texture }, belowSize),
|
||||
TypeError,
|
||||
msgIncludes,
|
||||
);
|
||||
assertThrows(
|
||||
() => encoder.copyBufferToTexture({ buffer }, { texture }, overSize),
|
||||
TypeError,
|
||||
msgIncludes,
|
||||
);
|
||||
// validate the argument of copySize property's length of GPUCommandEncoder.copyTextureToBuffer when its a sequence
|
||||
// https://www.w3.org/TR/2024/WD-webgpu-20240409/#dom-gpucommandencoder-copytexturetobuffer
|
||||
assertThrows(
|
||||
() => encoder.copyTextureToBuffer({ texture }, { buffer }, belowSize),
|
||||
TypeError,
|
||||
msgIncludes,
|
||||
);
|
||||
assertThrows(
|
||||
() => encoder.copyTextureToBuffer({ texture }, { buffer }, overSize),
|
||||
TypeError,
|
||||
msgIncludes,
|
||||
);
|
||||
// validate the argument of copySize property's length of GPUCommandEncoder.copyTextureToTexture when its a sequence
|
||||
// https://www.w3.org/TR/2024/WD-webgpu-20240409/#dom-gpucommandencoder-copytexturetotexture
|
||||
assertThrows(
|
||||
() => encoder.copyTextureToTexture({ texture }, { texture }, belowSize),
|
||||
TypeError,
|
||||
msgIncludes,
|
||||
);
|
||||
assertThrows(
|
||||
() => encoder.copyTextureToTexture({ texture }, { texture }, overSize),
|
||||
TypeError,
|
||||
msgIncludes,
|
||||
);
|
||||
const data = new Uint8Array([1 * 255, 1 * 255, 1 * 255, 1 * 255]);
|
||||
// validate the argument of size property's length of GPUQueue.writeTexture when its a sequence
|
||||
// https://www.w3.org/TR/2024/WD-webgpu-20240409/#dom-gpuqueue-writetexture
|
||||
assertThrows(
|
||||
() => device.queue.writeTexture({ texture }, data, {}, belowSize),
|
||||
TypeError,
|
||||
msgIncludes,
|
||||
);
|
||||
assertThrows(
|
||||
() => device.queue.writeTexture({ texture }, data, {}, overSize),
|
||||
TypeError,
|
||||
msgIncludes,
|
||||
);
|
||||
// NOTE: GPUQueue.copyExternalImageToTexture needs to be validated the argument of copySize property's length when its a sequence, but it is not implemented yet
|
||||
|
||||
device.destroy();
|
||||
const resources = Object.keys(Deno.resources());
|
||||
Deno.close(Number(resources[resources.length - 1]));
|
||||
});
|
||||
|
||||
Deno.test({
|
||||
ignore: true,
|
||||
}, async function validateGPUOrigin2D() {
|
||||
// NOTE: GPUQueue.copyExternalImageToTexture needs to be validated the argument of source.origin property's length when its a sequence, but it is not implemented yet
|
||||
});
|
||||
|
||||
Deno.test({
|
||||
ignore: isWsl || isLinuxOrMacCI,
|
||||
}, async function validateGPUOrigin3D() {
|
||||
const adapter = await navigator.gpu.requestAdapter();
|
||||
assert(adapter);
|
||||
const device = await adapter.requestDevice();
|
||||
assert(device);
|
||||
|
||||
const format = "rgba8unorm-srgb";
|
||||
const encoder = device.createCommandEncoder();
|
||||
const buffer = device.createBuffer({
|
||||
size: new Uint32Array([1, 4, 3, 295]).byteLength,
|
||||
usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST,
|
||||
});
|
||||
const usage = GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC;
|
||||
const size = [256, 256, 1];
|
||||
const texture = device.createTexture({
|
||||
size,
|
||||
format,
|
||||
usage,
|
||||
});
|
||||
|
||||
// value for validating GPUOrigin3D
|
||||
const overSize = [256, 256, 1, 1];
|
||||
|
||||
const msgIncludes =
|
||||
"A sequence of number used as a GPUOrigin3D must have at most 3 elements.";
|
||||
|
||||
// validate the argument of destination.origin property's length of GPUCommandEncoder.copyBufferToTexture when its a sequence
|
||||
// https://www.w3.org/TR/2024/WD-webgpu-20240409/#dom-gpucommandencoder-copybuffertotexture
|
||||
assertThrows(
|
||||
() =>
|
||||
encoder.copyBufferToTexture(
|
||||
{ buffer },
|
||||
{ texture, origin: overSize },
|
||||
size,
|
||||
),
|
||||
TypeError,
|
||||
msgIncludes,
|
||||
);
|
||||
// validate the argument of source.origin property's length of GPUCommandEncoder.copyTextureToBuffer when its a sequence
|
||||
// https://www.w3.org/TR/2024/WD-webgpu-20240409/#dom-gpucommandencoder-copytexturetobuffer
|
||||
assertThrows(
|
||||
() =>
|
||||
encoder.copyTextureToBuffer(
|
||||
{ texture, origin: overSize },
|
||||
{ buffer },
|
||||
size,
|
||||
),
|
||||
TypeError,
|
||||
msgIncludes,
|
||||
);
|
||||
// validate the argument of source.origin property's length of GPUCommandEncoder.copyTextureToTexture when its a sequence
|
||||
// https://www.w3.org/TR/2024/WD-webgpu-20240409/#dom-gpucommandencoder-copytexturetotexture
|
||||
assertThrows(
|
||||
() =>
|
||||
encoder.copyTextureToTexture(
|
||||
{ texture, origin: overSize },
|
||||
{ texture },
|
||||
size,
|
||||
),
|
||||
TypeError,
|
||||
msgIncludes,
|
||||
);
|
||||
// validate the argument of destination.origin property's length of GPUCommandEncoder.copyTextureToTexture when its a sequence
|
||||
assertThrows(
|
||||
() =>
|
||||
encoder.copyTextureToTexture(
|
||||
{ texture },
|
||||
{ texture, origin: overSize },
|
||||
size,
|
||||
),
|
||||
TypeError,
|
||||
msgIncludes,
|
||||
);
|
||||
// validate the argument of destination.origin property's length of GPUQueue.writeTexture when its a sequence
|
||||
// https://www.w3.org/TR/2024/WD-webgpu-20240409/#dom-gpuqueue-writetexture
|
||||
assertThrows(
|
||||
() =>
|
||||
device.queue.writeTexture(
|
||||
{ texture, origin: overSize },
|
||||
new Uint8Array([1 * 255, 1 * 255, 1 * 255, 1 * 255]),
|
||||
{},
|
||||
size,
|
||||
),
|
||||
TypeError,
|
||||
msgIncludes,
|
||||
);
|
||||
// NOTE: GPUQueue.copyExternalImageToTexture needs to be validated the argument of destination.origin property's length when its a sequence, but it is not implemented yet
|
||||
|
||||
device.destroy();
|
||||
const resources = Object.keys(Deno.resources());
|
||||
Deno.close(Number(resources[resources.length - 1]));
|
||||
});
|
||||
|
||||
async function checkIsWsl() {
|
||||
return Deno.build.os === "linux" && await hasMicrosoftProcVersion();
|
||||
|
||||
|
|
Loading…
Reference in a new issue