diff options
Diffstat (limited to 'dom/webgpu/mochitest')
18 files changed, 823 insertions, 0 deletions
diff --git a/dom/webgpu/mochitest/mochitest-no-pref.ini b/dom/webgpu/mochitest/mochitest-no-pref.ini new file mode 100644 index 0000000000..d4d111e6ee --- /dev/null +++ b/dom/webgpu/mochitest/mochitest-no-pref.ini @@ -0,0 +1,10 @@ +[DEFAULT] +subsuite = webgpu +run-if = release_or_beta + +# Even if the pref were enabled, WebGPU is only available in secure contexts. +# +# See spec WebIDL, like this: https://www.w3.org/TR/webgpu/#navigatorgpu +scheme = https + +[test_disabled.html] diff --git a/dom/webgpu/mochitest/mochitest.ini b/dom/webgpu/mochitest/mochitest.ini new file mode 100644 index 0000000000..96b2c55ee8 --- /dev/null +++ b/dom/webgpu/mochitest/mochitest.ini @@ -0,0 +1,42 @@ +[DEFAULT] +subsuite = webgpu +run-if = !release_or_beta +prefs = + dom.webgpu.enabled=true + gfx.offscreencanvas.enabled=true +support-files = + worker_wrapper.js + test_basic_canvas.worker.js + test_submit_render_empty.worker.js + +# WebGPU is only available in secure contexts. +# +# See spec WebIDL, like this: https://www.w3.org/TR/webgpu/#navigatorgpu +scheme = https + +[test_basic_canvas.worker.html] +skip-if = true # Bug 1818379 - no webgpu in worker scopes, see bug 1808820 +fail-if = (os == 'linux' && os_version == '18.04') || (os == 'win' && os_version == '6.1') || (os == 'mac') +[test_buffer_mapping.html] +fail-if = (os == 'linux' && os_version == '18.04') || (os == 'win' && os_version == '6.1') || (os == 'mac') +[test_command_buffer_creation.html] +fail-if = (os == 'linux' && os_version == '18.04') || (os == 'win' && os_version == '6.1') || (os == 'mac') +[test_device_creation.html] +fail-if = (os == 'linux' && os_version == '18.04') || (os == 'win' && os_version == '6.1') || (os == 'mac') +[test_enabled.html] +[test_error_scope.html] +fail-if = (os == 'linux' && os_version == '18.04') || (os == 'win' && os_version == '6.1') || (os == 'mac') +[test_insecure_context.html] +# This test checks that WebGPU is not available in insecure contexts. +scheme = http +[test_queue_copyExternalImageToTexture.html] +fail-if = (os == 'linux' && os_version == '18.04') || (os == 'win' && os_version == '6.1') || (os == 'mac') +[test_queue_write.html] +fail-if = (os == 'linux' && os_version == '18.04') || (os == 'win' && os_version == '6.1') || (os == 'mac') +[test_submit_compute_empty.html] +fail-if = (os == 'linux' && os_version == '18.04') || (os == 'win' && os_version == '6.1') || (os == 'mac') +[test_submit_render_empty.html] +fail-if = (os == 'linux' && os_version == '18.04') || (os == 'win' && os_version == '6.1') || (os == 'mac') +[test_submit_render_empty.worker.html] +skip-if = true # Bug 1818379 - no webgpu in worker scopes, see bug 1808820 +fail-if = (os == 'linux' && os_version == '18.04') || (os == 'win' && os_version == '6.1') || (os == 'mac') diff --git a/dom/webgpu/mochitest/test_basic_canvas.worker.html b/dom/webgpu/mochitest/test_basic_canvas.worker.html new file mode 100644 index 0000000000..a23ee9fc70 --- /dev/null +++ b/dom/webgpu/mochitest/test_basic_canvas.worker.html @@ -0,0 +1,18 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8" /> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <script src="worker_wrapper.js"></script> + <link rel="stylesheet" href="/tests/SimpleTest/test.css" /> + </head> + <body> + <canvas id="canvas"></canvas> + <script> + const canvas = document.getElementById("canvas"); + const offscreen = canvas.transferControlToOffscreen(); + + runWorkerTest("test_basic_canvas.worker.js", { offscreen }, [offscreen]); + </script> + </body> +</html> diff --git a/dom/webgpu/mochitest/test_basic_canvas.worker.js b/dom/webgpu/mochitest/test_basic_canvas.worker.js new file mode 100644 index 0000000000..5bd0434602 --- /dev/null +++ b/dom/webgpu/mochitest/test_basic_canvas.worker.js @@ -0,0 +1,32 @@ +self.addEventListener("message", async function (event) { + try { + const offscreen = event.data.offscreen; + const context = offscreen.getContext("webgpu"); + + const adapter = await navigator.gpu.requestAdapter(); + const device = await adapter.requestDevice(); + const swapChainFormat = context.getPreferredFormat(adapter); + + context.configure({ + device, + format: swapChainFormat, + size: { width: 100, height: 100, depth: 1 }, + }); + + const texture = context.getCurrentTexture(); + + self.postMessage([ + { + value: texture !== undefined, + message: "texture !== undefined", + }, + ]); + } catch (e) { + self.postMessage([ + { + value: false, + message: "Unhandled exception " + e, + }, + ]); + } +}); diff --git a/dom/webgpu/mochitest/test_buffer_mapping.html b/dom/webgpu/mochitest/test_buffer_mapping.html new file mode 100644 index 0000000000..01dfbf893e --- /dev/null +++ b/dom/webgpu/mochitest/test_buffer_mapping.html @@ -0,0 +1,73 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8" /> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" href="/tests/SimpleTest/test.css" /> + </head> + <body> + <script> + ok( + SpecialPowers.getBoolPref("dom.webgpu.enabled"), + "Pref should be enabled." + ); + + async function testBody() { + const adapter = await navigator.gpu.requestAdapter(); + const device = await adapter.requestDevice(); + + const bufferRead = device.createBuffer({ + size: 4, + usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST, + }); + const bufferWrite = device.createBuffer({ + size: 4, + usage: GPUBufferUsage.COPY_SRC, + mappedAtCreation: true, + }); + new Float32Array(bufferWrite.getMappedRange()).set([1.0]); + bufferWrite.unmap(); + + const encoder = device.createCommandEncoder(); + encoder.copyBufferToBuffer(bufferWrite, 0, bufferRead, 0, 4); + device.queue.submit([encoder.finish()]); + + await bufferRead.mapAsync(GPUMapMode.READ); + + try { + bufferRead.getMappedRange(0, 5); + ok(false, "mapped with size outside buffer should throw"); + } catch (e) { + ok( + true, + "mapped with size outside buffer should throw OperationError" + ); + } + + try { + bufferRead.getMappedRange(4, 1); + ok(false, "mapped with offset outside buffer should throw"); + } catch (e) { + ok( + true, + "mapped with offset outside buffer should throw OperationError" + ); + } + + const data = bufferRead.getMappedRange(); + is(data.byteLength, 4, "array should be 4 bytes long"); + + const value = new Float32Array(data)[0]; + ok(value == 1.0, "value == 1.0"); + + bufferRead.unmap(); + is(data.byteLength, 0, "array should be detached after explicit unmap"); + } + + SimpleTest.waitForExplicitFinish(); + testBody() + .catch(e => ok(false, "Unhandled exception " + e)) + .finally(() => SimpleTest.finish()); + </script> + </body> +</html> diff --git a/dom/webgpu/mochitest/test_command_buffer_creation.html b/dom/webgpu/mochitest/test_command_buffer_creation.html new file mode 100644 index 0000000000..a92c038afd --- /dev/null +++ b/dom/webgpu/mochitest/test_command_buffer_creation.html @@ -0,0 +1,29 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8" /> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" href="/tests/SimpleTest/test.css" /> + </head> + <body> + <script> + ok( + SpecialPowers.getBoolPref("dom.webgpu.enabled"), + "Pref should be enabled." + ); + + const func = async function () { + const adapter = await navigator.gpu.requestAdapter(); + const device = await adapter.requestDevice(); + const encoder = device.createCommandEncoder(); + const command_buffer = encoder.finish(); + ok(command_buffer !== undefined, "command_buffer !== undefined"); + }; + + SimpleTest.waitForExplicitFinish(); + func() + .catch(e => ok(false, "Unhandled exception " + e)) + .finally(() => SimpleTest.finish()); + </script> + </body> +</html> diff --git a/dom/webgpu/mochitest/test_device_creation.html b/dom/webgpu/mochitest/test_device_creation.html new file mode 100644 index 0000000000..678359c323 --- /dev/null +++ b/dom/webgpu/mochitest/test_device_creation.html @@ -0,0 +1,29 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8" /> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" href="/tests/SimpleTest/test.css" /> + </head> + <body> + <script> + ok( + SpecialPowers.getBoolPref("dom.webgpu.enabled"), + "Pref should be enabled." + ); + + const func = async function () { + const adapter = await navigator.gpu.requestAdapter(); + const limits = adapter.limits; + const features = adapter.features; + const device = await adapter.requestDevice(); + ok(device !== undefined, "device !== undefined"); + }; + + SimpleTest.waitForExplicitFinish(); + func() + .catch(e => ok(false, "Unhandled exception " + e)) + .finally(() => SimpleTest.finish()); + </script> + </body> +</html> diff --git a/dom/webgpu/mochitest/test_disabled.html b/dom/webgpu/mochitest/test_disabled.html new file mode 100644 index 0000000000..12eb01e465 --- /dev/null +++ b/dom/webgpu/mochitest/test_disabled.html @@ -0,0 +1,17 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8" /> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" href="/tests/SimpleTest/test.css" /> + </head> + <body> + <script> + ok( + !SpecialPowers.getBoolPref("dom.webgpu.enabled"), + "Pref should be disabled." + ); + ok(navigator.gpu === undefined, "navigator.gpu === undefined"); + </script> + </body> +</html> diff --git a/dom/webgpu/mochitest/test_enabled.html b/dom/webgpu/mochitest/test_enabled.html new file mode 100644 index 0000000000..318788bf1e --- /dev/null +++ b/dom/webgpu/mochitest/test_enabled.html @@ -0,0 +1,17 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8" /> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" href="/tests/SimpleTest/test.css" /> + </head> + <body> + <script> + ok( + SpecialPowers.getBoolPref("dom.webgpu.enabled"), + "Pref should be enabled." + ); + ok(navigator.gpu !== undefined, "navigator.gpu !== undefined"); + </script> + </body> +</html> diff --git a/dom/webgpu/mochitest/test_error_scope.html b/dom/webgpu/mochitest/test_error_scope.html new file mode 100644 index 0000000000..2bed5b937b --- /dev/null +++ b/dom/webgpu/mochitest/test_error_scope.html @@ -0,0 +1,39 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8" /> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" href="/tests/SimpleTest/test.css" /> + </head> + <body> + <script> + ok( + SpecialPowers.getBoolPref("dom.webgpu.enabled"), + "Pref should be enabled." + ); + + const func = async function () { + const adapter = await navigator.gpu.requestAdapter(); + const device = await adapter.requestDevice(); + + device.pushErrorScope("validation"); + const buffer = device.createBuffer({ size: 0, usage: 0 }); + const error = await device.popErrorScope(); + + isnot(error, null); + + try { + await device.popErrorScope(); + ok(false, "Should have thrown"); + } catch (ex) { + ok(ex.name == "OperationError", "Should throw an OperationError"); + } + }; + + SimpleTest.waitForExplicitFinish(); + func() + .catch(e => ok(false, "Unhandled exception " + e)) + .finally(() => SimpleTest.finish()); + </script> + </body> +</html> diff --git a/dom/webgpu/mochitest/test_insecure_context.html b/dom/webgpu/mochitest/test_insecure_context.html new file mode 100644 index 0000000000..dcc4a313b9 --- /dev/null +++ b/dom/webgpu/mochitest/test_insecure_context.html @@ -0,0 +1,22 @@ +<!-- This is somewhat redundant with + dom/tests/mochitest/general/test_interfaces.js, but I think it's good to + have something here as well. --> + +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8" /> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" href="/tests/SimpleTest/test.css" /> + </head> + <body> + <script> + ok( + SpecialPowers.getBoolPref("dom.webgpu.enabled"), + "Pref should be enabled." + ); + ok(!isSecureContext, "test should not run in a secure context"); + ok(navigator.gpu === undefined, "navigator.gpu === undefined"); + </script> + </body> +</html> diff --git a/dom/webgpu/mochitest/test_queue_copyExternalImageToTexture.html b/dom/webgpu/mochitest/test_queue_copyExternalImageToTexture.html new file mode 100644 index 0000000000..279b4a52b4 --- /dev/null +++ b/dom/webgpu/mochitest/test_queue_copyExternalImageToTexture.html @@ -0,0 +1,261 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8" /> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" href="/tests/SimpleTest/test.css" /> + </head> + + <body> + <script type="text/javascript"> + "use strict"; + + ok( + SpecialPowers.getBoolPref("dom.webgpu.enabled"), + "WebGPU pref should be enabled." + ); + ok( + SpecialPowers.getBoolPref("gfx.offscreencanvas.enabled"), + "OffscreenCanvas pref should be enabled." + ); + + SimpleTest.waitForExplicitFinish(); + + function requestAnimationFramePromise() { + return new Promise(requestAnimationFrame); + } + + function createSourceCanvasWebgl() { + const offscreenCanvas = new OffscreenCanvas(200, 200); + const gl = offscreenCanvas.getContext("webgl"); + + const COLOR_VALUE = 127.0 / 255.0; + const ALPHA_VALUE = 127.0 / 255.0; + + gl.enable(gl.SCISSOR_TEST); + + gl.scissor(0, 0, 100, 100); + gl.clearColor(COLOR_VALUE, 0.0, 0.0, ALPHA_VALUE); + gl.clear(gl.COLOR_BUFFER_BIT); + + gl.scissor(100, 0, 100, 100); + gl.clearColor(0.0, COLOR_VALUE, 0.0, ALPHA_VALUE); + gl.clear(gl.COLOR_BUFFER_BIT); + + gl.scissor(0, 100, 100, 100); + gl.clearColor(0.0, 0.0, COLOR_VALUE, ALPHA_VALUE); + gl.clear(gl.COLOR_BUFFER_BIT); + + gl.scissor(100, 100, 100, 100); + gl.clearColor(0.0, 0.0, 0.0, ALPHA_VALUE); + gl.clear(gl.COLOR_BUFFER_BIT); + + return { + source: offscreenCanvas, + origin: { x: 0, y: 0 }, + flipY: true, + }; + } + + function createSourceCanvas2d() { + const offscreenCanvas = new OffscreenCanvas(200, 200); + const context = offscreenCanvas.getContext("2d"); + + context.fillStyle = "rgba(255,0,0,0.498)"; + context.fillRect(0, 0, 100, 100); + + context.fillStyle = "rgba(0,255,0,0.498)"; + context.fillRect(100, 0, 100, 100); + + context.fillStyle = "rgba(0,0,255,0.498)"; + context.fillRect(0, 100, 100, 100); + + context.fillStyle = "rgba(0,0,0,0.498)"; + context.fillRect(100, 100, 100, 100); + + return { + source: offscreenCanvas, + origin: { x: 0, y: 0 }, + flipY: false, + }; + } + + function createSourceImageBitmap() { + const sourceCanvas = createSourceCanvas2d(); + return { + source: sourceCanvas.source.transferToImageBitmap(), + origin: { x: 0, y: 0 }, + flipY: false, + }; + } + + async function mapDestTexture( + device, + source, + destFormat, + premultiply, + copySize + ) { + const bytesPerRow = 256 * 4; // 256 aligned for 200 pixels + const texture = device.createTexture({ + format: destFormat, + size: copySize, + usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST, + }); + + device.queue.copyExternalImageToTexture( + source, + { texture, premultipliedAlpha: premultiply }, + copySize + ); + + const buffer = device.createBuffer({ + size: 1024 * 200, + usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST, + }); + + const encoder = device.createCommandEncoder(); + encoder.copyTextureToBuffer( + { texture }, + { buffer, bytesPerRow }, + copySize + ); + device.queue.submit([encoder.finish()]); + + await buffer.mapAsync(GPUMapMode.READ); + return buffer; + } + + async function verifyBuffer( + test, + device, + source, + format, + premultiply, + copyDim, + topLeftPixelData + ) { + try { + const buffer = await mapDestTexture( + device, + source, + format, + premultiply, + copyDim + ); + const arrayBuffer = buffer.getMappedRange(); + const view = new Uint8Array(arrayBuffer); + for (let i = 0; i < topLeftPixelData.length; ++i) { + is( + view[i], + topLeftPixelData[i], + test + + " " + + format + + " (" + + source.origin.x + + "," + + source.origin.y + + ") channel " + + i + ); + } + } catch (e) { + ok(false, "WebGPU exception: " + e); + } + } + + async function verifySourceCanvas(test, device, source) { + await verifyBuffer( + test, + device, + source, + "rgba8unorm", + /* premultiply */ true, + { width: 200, height: 200 }, + [127, 0, 0, 127] + ); + await verifyBuffer( + test, + device, + source, + "bgra8unorm", + /* premultiply */ true, + { width: 200, height: 200 }, + [0, 0, 127, 127] + ); + await verifyBuffer( + test, + device, + source, + "rgba8unorm", + /* premultiply */ false, + { width: 200, height: 200 }, + [255, 0, 0, 127] + ); + await verifyBuffer( + test, + device, + source, + "bgra8unorm", + /* premultiply */ false, + { width: 200, height: 200 }, + [0, 0, 255, 127] + ); + + // The copy is flipped but the origin is relative to the original source data, + // so we need to invert for WebGL. + const topRightPixelData = + test === "webgl" ? [0, 0, 0, 127] : [0, 127, 0, 127]; + const topRightOrigin = { origin: { x: 100, y: 0 } }; + await verifyBuffer( + test, + device, + { ...source, ...topRightOrigin }, + "bgra8unorm", + /* premultiply */ true, + { width: 100, height: 100 }, + topRightPixelData + ); + + const bottomLeftPixelData = + test === "webgl" ? [0, 0, 127, 127] : [127, 0, 0, 127]; + const bottomLeftOrigin = { origin: { x: 0, y: 100 } }; + await verifyBuffer( + test, + device, + { ...source, ...bottomLeftOrigin }, + "bgra8unorm", + /* premultiply */ true, + { width: 100, height: 100 }, + bottomLeftPixelData + ); + } + + async function writeDestCanvas(source2d, sourceWebgl, sourceImageBitmap) { + const adapter = await navigator.gpu.requestAdapter(); + const device = await adapter.requestDevice(); + await verifySourceCanvas("2d", device, source2d); + await verifySourceCanvas("imageBitmap", device, sourceImageBitmap); + await verifySourceCanvas("webgl", device, sourceWebgl); + } + + async function runTest() { + try { + const source2d = createSourceCanvas2d(); + const sourceWebgl = createSourceCanvasWebgl(); + const sourceImageBitmap = createSourceImageBitmap(); + await requestAnimationFramePromise(); + await requestAnimationFramePromise(); + await writeDestCanvas(source2d, sourceWebgl, sourceImageBitmap); + } catch (e) { + ok(false, "Uncaught exception: " + e); + } finally { + SimpleTest.finish(); + } + } + + runTest(); + </script> + </body> +</html> diff --git a/dom/webgpu/mochitest/test_queue_write.html b/dom/webgpu/mochitest/test_queue_write.html new file mode 100644 index 0000000000..585c1617cd --- /dev/null +++ b/dom/webgpu/mochitest/test_queue_write.html @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8" /> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" href="/tests/SimpleTest/test.css" /> + </head> + <body> + <script> + ok( + SpecialPowers.getBoolPref("dom.webgpu.enabled"), + "Pref should be enabled." + ); + + const func = async function () { + const adapter = await navigator.gpu.requestAdapter(); + const device = await adapter.requestDevice(); + const buffer = device.createBuffer({ + size: 16, + usage: + GPUBufferUsage.COPY_DST | + GPUBufferUsage.COPY_SRC | + GPUBufferUsage.VERTEX, + }); + const arrayBuf = new ArrayBuffer(16); + new Int32Array(arrayBuf).fill(5); + device.queue.writeBuffer(buffer, 0, arrayBuf, 0); + const texture = device.createTexture({ + size: [2, 2, 1], + dimension: "2d", + format: "rgba8unorm", + usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC, + }); + device.queue.writeTexture( + { texture }, + arrayBuf, + { bytesPerRow: 8 }, + [2, 2, 1] + ); + // this isn't a process check, we need to read back the contents and verify the writes happened + ok(device !== undefined, ""); + }; + + SimpleTest.waitForExplicitFinish(); + func() + .catch(e => ok(false, "Unhandled exception " + e)) + .finally(() => SimpleTest.finish()); + </script> + </body> +</html> diff --git a/dom/webgpu/mochitest/test_submit_compute_empty.html b/dom/webgpu/mochitest/test_submit_compute_empty.html new file mode 100644 index 0000000000..82cb9473c5 --- /dev/null +++ b/dom/webgpu/mochitest/test_submit_compute_empty.html @@ -0,0 +1,32 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8" /> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" href="/tests/SimpleTest/test.css" /> + </head> + <body> + <script> + ok( + SpecialPowers.getBoolPref("dom.webgpu.enabled"), + "Pref should be enabled." + ); + + const func = async function () { + const adapter = await navigator.gpu.requestAdapter(); + const device = await adapter.requestDevice(); + const encoder = device.createCommandEncoder(); + const pass = encoder.beginComputePass(); + pass.end(); + const command_buffer = encoder.finish(); + device.queue.submit([command_buffer]); + ok(command_buffer !== undefined, "command_buffer !== undefined"); + }; + + SimpleTest.waitForExplicitFinish(); + func() + .catch(e => ok(false, "Unhandled exception " + e)) + .finally(() => SimpleTest.finish()); + </script> + </body> +</html> diff --git a/dom/webgpu/mochitest/test_submit_render_empty.html b/dom/webgpu/mochitest/test_submit_render_empty.html new file mode 100644 index 0000000000..bac0d1ede7 --- /dev/null +++ b/dom/webgpu/mochitest/test_submit_render_empty.html @@ -0,0 +1,57 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8" /> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" href="/tests/SimpleTest/test.css" /> + </head> + <body> + <script> + ok( + SpecialPowers.getBoolPref("dom.webgpu.enabled"), + "Pref should be enabled." + ); + + const func = async function () { + const adapter = await navigator.gpu.requestAdapter(); + const device = await adapter.requestDevice(); + + const swapChainFormat = "rgba8unorm"; + const bundleEncoder = device.createRenderBundleEncoder({ + colorFormats: [swapChainFormat], + }); + const bundle = bundleEncoder.finish({}); + + const texture = device.createTexture({ + size: { width: 100, height: 100, depth: 1 }, + format: swapChainFormat, + usage: GPUTextureUsage.RENDER_ATTACHMENT, + }); + const view = texture.createView(); + + const encoder = device.createCommandEncoder(); + const pass = encoder.beginRenderPass({ + colorAttachments: [ + { + view, + clearValue: { r: 0, g: 0, b: 0, a: 0 }, + loadOp: "clear", + storeOp: "store", + }, + ], + }); + pass.executeBundles([bundle]); + pass.end(); + const command_buffer = encoder.finish(); + + device.queue.submit([command_buffer]); + ok(command_buffer !== undefined, "command_buffer !== undefined"); + }; + + SimpleTest.waitForExplicitFinish(); + func() + .catch(e => ok(false, "Unhandled exception " + e)) + .finally(() => SimpleTest.finish()); + </script> + </body> +</html> diff --git a/dom/webgpu/mochitest/test_submit_render_empty.worker.html b/dom/webgpu/mochitest/test_submit_render_empty.worker.html new file mode 100644 index 0000000000..8db3168be0 --- /dev/null +++ b/dom/webgpu/mochitest/test_submit_render_empty.worker.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8" /> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <script src="worker_wrapper.js"></script> + <link rel="stylesheet" href="/tests/SimpleTest/test.css" /> + </head> + <body> + <script> + runWorkerTest("test_submit_render_empty.worker.js", {}, []); + </script> + </body> +</html> diff --git a/dom/webgpu/mochitest/test_submit_render_empty.worker.js b/dom/webgpu/mochitest/test_submit_render_empty.worker.js new file mode 100644 index 0000000000..6183983ff4 --- /dev/null +++ b/dom/webgpu/mochitest/test_submit_render_empty.worker.js @@ -0,0 +1,48 @@ +self.addEventListener("message", async function (event) { + try { + const adapter = await navigator.gpu.requestAdapter(); + const device = await adapter.requestDevice(); + + const swapChainFormat = "rgba8unorm"; + const bundleEncoder = device.createRenderBundleEncoder({ + colorFormats: [swapChainFormat], + }); + const bundle = bundleEncoder.finish({}); + + const texture = device.createTexture({ + size: { width: 100, height: 100, depth: 1 }, + format: swapChainFormat, + usage: GPUTextureUsage.RENDER_ATTACHMENT, + }); + const view = texture.createView(); + + const encoder = device.createCommandEncoder(); + const pass = encoder.beginRenderPass({ + colorAttachments: [ + { + view, + loadValue: { r: 0, g: 0, b: 0, a: 0 }, + storeOp: "store", + }, + ], + }); + pass.executeBundles([bundle]); + pass.end(); + const command_buffer = encoder.finish(); + + device.queue.submit([command_buffer]); + self.postMessage([ + { + value: command_buffer !== undefined, + message: "command_buffer !== undefined", + }, + ]); + } catch (e) { + self.postMessage([ + { + value: false, + message: "Unhandled exception " + e, + }, + ]); + } +}); diff --git a/dom/webgpu/mochitest/worker_wrapper.js b/dom/webgpu/mochitest/worker_wrapper.js new file mode 100644 index 0000000000..6f6de9002d --- /dev/null +++ b/dom/webgpu/mochitest/worker_wrapper.js @@ -0,0 +1,33 @@ +ok( + SpecialPowers.getBoolPref("dom.webgpu.enabled"), + "WebGPU pref should be enabled." +); +ok( + SpecialPowers.getBoolPref("gfx.offscreencanvas.enabled"), + "OffscreenCanvas pref should be enabled." +); +SimpleTest.waitForExplicitFinish(); + +const workerWrapperFunc = async function (worker_path, data, transfer) { + const worker = new Worker(worker_path); + + const results = new Promise((resolve, reject) => { + worker.addEventListener("message", event => { + resolve(event.data); + }); + }); + + worker.postMessage(data, transfer); + for (const result of await results) { + ok(result.value, result.message); + } +}; + +async function runWorkerTest(worker_path, data, transfer) { + try { + await workerWrapperFunc(worker_path, data, transfer); + } catch (e) { + ok(false, "Unhandled exception " + e); + } + SimpleTest.finish(); +} |