[WebGPU] Convert GPUComputePipeline LOG statements to generate GPUErrors
https://bugs.webkit.org/show_bug.cgi?id=199773

Reviewed by Myles C. Maxfield.

Source/WebCore:

Generate a GPUError if GPUComputePipeline creation fails.
Rework the WHLSL test harness to take advantage of this.

Test: webgpu/compute-pipeline-errors.html

* Modules/webgpu/WebGPUComputePipelineDescriptor.cpp:
(WebCore::WebGPUComputePipelineDescriptor::tryCreateGPUComputePipelineDescriptor const):
* Modules/webgpu/WebGPUComputePipelineDescriptor.h:
* Modules/webgpu/WebGPUDevice.cpp:
(WebCore::WebGPUDevice::createComputePipeline const):
* platform/graphics/gpu/GPUBuffer.h:
* platform/graphics/gpu/GPUComputePipeline.h:
        Now inherits from GPUObjectBase, though this isn't super useful yet
        since GPUComputePipeline itself does not expose any operations that can error.
* platform/graphics/gpu/GPUDevice.cpp:
(WebCore::GPUDevice::tryCreateComputePipeline const):
* platform/graphics/gpu/GPUDevice.h:
* platform/graphics/gpu/cocoa/GPUBufferMetal.mm:
(WebCore::GPUBuffer::validateBufferUsage):
* platform/graphics/gpu/cocoa/GPUComputePipelineMetal.mm:
(WebCore::trySetMetalFunctions):
(WebCore::trySetFunctions):
(WebCore::convertComputePipelineDescriptor):
(WebCore::tryCreateMTLComputePipelineState):
(WebCore::GPUComputePipeline::tryCreate):
(WebCore::GPUComputePipeline::GPUComputePipeline):

LayoutTests:

Add a test to ensure GPUComputePipeline errors generate correctly.
Rework checkFail in the WHLSL test harness to check for GPUError.

* webgpu/compute-pipeline-errors-expected.txt: Added.
* webgpu/compute-pipeline-errors.html: Added.
* webgpu/error-scopes-test.html:
* webgpu/js/webgpu-functions.js:
(runTestsWithDevice): Runs tests in an object all with the same device.
* webgpu/js/whlsl-test-harness.js: Add shader compilation error checking.
(Harness.prototype.async.callTypedFunction):
(Harness.prototype.async.checkCompileFail):
(Harness.prototype.async._callFunction):
(Harness):
(async.checkFail):
(Harness.prototype._callFunction): Deleted.
* webgpu/whlsl-recursive-structs-expected.txt: Remove a WHLSL compiler buggy test.
* webgpu/whlsl-recursive-structs.html:
* webgpu/whlsl-test-harness-test-expected.txt:
* webgpu/whlsl-test-harness-test.html:


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@247500 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 024f569..0260047 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,42 @@
+2019-07-16  Justin Fan  <justin_fan@apple.com>
+
+        [WebGPU] Convert GPUComputePipeline LOG statements to generate GPUErrors
+        https://bugs.webkit.org/show_bug.cgi?id=199773
+
+        Reviewed by Myles C. Maxfield.
+
+        Add a test to ensure GPUComputePipeline errors generate correctly.
+        Rework checkFail in the WHLSL test harness to check for GPUError.
+
+        * webgpu/compute-pipeline-errors-expected.txt: Added.
+        * webgpu/compute-pipeline-errors.html: Added.
+        * webgpu/error-scopes-test.html:
+        * webgpu/js/webgpu-functions.js:
+        (runTestsWithDevice): Runs tests in an object all with the same device.
+        * webgpu/js/whlsl-test-harness.js: Add shader compilation error checking.
+        (Harness.prototype.async.callTypedFunction):
+        (Harness.prototype.async.checkCompileFail):
+        (Harness.prototype.async._callFunction):
+        (Harness):
+        (async.checkFail):
+        (Harness.prototype._callFunction): Deleted.
+        * webgpu/whlsl-recursive-structs-expected.txt: Remove a WHLSL compiler buggy test.
+        * webgpu/whlsl-recursive-structs.html:
+        * webgpu/whlsl-test-harness-test-expected.txt:
+        * webgpu/whlsl-test-harness-test.html:
+
+2019-07-10  Justin Fan  <justin_fan@apple.com>
+
+        [WebGPU] Implement GPUError and error scopes
+        https://bugs.webkit.org/show_bug.cgi?id=199655
+
+        Reviewed by Myles C. Maxfield.
+
+        Add a test to cover the cases outlined in the WebGPU error handling design doc.
+
+        * webgpu/error-scopes-test-expected.txt: Added.
+        * webgpu/error-scopes-test.html: Added.
+
 2019-07-16  Commit Queue  <commit-queue@webkit.org>
 
         Unreviewed, rolling out r247493.
diff --git a/LayoutTests/webgpu/compute-pipeline-errors-expected.txt b/LayoutTests/webgpu/compute-pipeline-errors-expected.txt
new file mode 100644
index 0000000..35fdf2b
--- /dev/null
+++ b/LayoutTests/webgpu/compute-pipeline-errors-expected.txt
@@ -0,0 +1,6 @@
+
+PASS Compute compilation failed due to incorrect entry point string. 
+PASS Compute pipeline creation succeeded. 
+PASS MSL pipeline creation failed due to invalid GPUShaderModule. 
+PASS MSL pipeline creation failed due to incorrect entry point string. 
+
diff --git a/LayoutTests/webgpu/compute-pipeline-errors.html b/LayoutTests/webgpu/compute-pipeline-errors.html
new file mode 100644
index 0000000..f8bbfe0
--- /dev/null
+++ b/LayoutTests/webgpu/compute-pipeline-errors.html
@@ -0,0 +1,85 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Test Error Scopes.</title>
+<body>
+<script src="js/webgpu-functions.js"></script>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+<script>
+let tests = {};
+let goodModule;
+
+tests["Compute compilation failed due to incorrect entry point string."] = async device => {
+    const goodWHLSL = `
+[numthreads(1, 1, 1)]
+compute void _compute_main() { }
+`;
+    goodModule = device.createShaderModule({ code: goodWHLSL, isWHLSL: true });
+
+    device.pushErrorScope("validation");
+
+    device.createComputePipeline({
+        computeStage: {
+            module: goodModule,
+            entryPoint: "compute_main"
+        }
+    });
+
+    return popValidationError(device);
+};
+
+tests["Compute pipeline creation succeeded."] = async device => {
+    device.pushErrorScope("validation");
+
+    device.createComputePipeline({
+        computeStage: {
+            module: goodModule,
+            entryPoint: "_compute_main"
+        }
+    });
+
+    return popNullError(device);
+};
+
+tests["MSL pipeline creation failed due to invalid GPUShaderModule."] = async device => {
+    const badMSL = `This code should not compile.`;
+
+    device.pushErrorScope("none");
+
+    const badMSLModule = device.createShaderModule({ code: badMSL });
+
+    await device.popErrorScope();
+
+    device.pushErrorScope("validation");
+
+    device.createComputePipeline({
+        computeStage: {
+            module: badMSLModule,
+            entryPoint: "_compute_main"
+        }
+    });
+
+    return popValidationError(device);
+};
+
+tests["MSL pipeline creation failed due to incorrect entry point string."] = async device => {
+    const goodMSL = `
+kernel void _compute_main() { }
+`;
+    const mslModule = device.createShaderModule({ code: goodMSL });
+
+    device.pushErrorScope("validation");
+
+    device.createComputePipeline({
+        computeStage: {
+            module: mslModule,
+            entryPoint: "_compute_mai"
+        }
+    });
+
+    return popValidationError(device);
+};
+
+runTestsWithDevice(tests);
+</script>
+</body>
\ No newline at end of file
diff --git a/LayoutTests/webgpu/error-scopes-test-expected.txt b/LayoutTests/webgpu/error-scopes-test-expected.txt
new file mode 100644
index 0000000..4eba67f
--- /dev/null
+++ b/LayoutTests/webgpu/error-scopes-test-expected.txt
@@ -0,0 +1,10 @@
+
+PASS Capture a single GPUValidation error. 
+PASS Capture a single GPUOutOfMemory error. 
+PASS Ignore errors past the first. 
+PASS Captured errors match error scope filter. 
+PASS Reject popErrorScope if no scope exists. 
+PASS Filter 'none' should capture but not report errors. 
+PASS Push and pop many error scopes with no rejections. 
+PASS Catch many errors in nested scopes. 
+
diff --git a/LayoutTests/webgpu/error-scopes-test.html b/LayoutTests/webgpu/error-scopes-test.html
new file mode 100644
index 0000000..856afa8
--- /dev/null
+++ b/LayoutTests/webgpu/error-scopes-test.html
@@ -0,0 +1,100 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Test Error Scopes.</title>
+<body>
+<script src="js/webgpu-functions.js"></script>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+<script>
+let tests = {};
+
+tests["Capture a single GPUValidation error."] = async device => {
+    device.pushErrorScope("validation");
+    causeValidationError(device);
+    return popValidationError(device);
+};
+
+tests["Capture a single GPUOutOfMemory error."] = async device => {
+    device.pushErrorScope("out-of-memory");
+    causeMemoryError(device);
+    return popMemoryError(device);
+};
+
+tests["Ignore errors past the first."] = async device => {
+    device.pushErrorScope("validation");
+    device.pushErrorScope("validation");
+    causeValidationError(device);
+    causeValidationError(device);
+    
+    const error = await device.popErrorScope();
+    assertValidationError(error);
+
+    return popNullError(device);
+};
+
+tests["Captured errors match error scope filter."] = async device => {
+    device.pushErrorScope("validation");
+    device.pushErrorScope("out-of-memory");
+    causeValidationError(device);
+
+    const shouldBeNull = await device.popErrorScope();
+    assertNull(shouldBeNull);
+
+    return popValidationError(device);
+};
+
+tests["Reject popErrorScope if no scope exists."] = async device => {
+    const promise = device.popErrorScope().then(() => assert_unreached(), async e => {
+        assert_false(e === undefined);
+        // Pop the extra 'none' scope.
+        await popNullError(device);
+    });
+    // 'promise' should still reject if a scope is pushed here.
+    device.pushErrorScope("none");
+    return promise;
+};
+
+tests["Filter 'none' should capture but not report errors."] = async device => {
+    device.pushErrorScope("out-of-memory");
+    device.pushErrorScope("none");
+    causeMemoryError(device);
+
+    const shouldBeNull = await device.popErrorScope();
+    assertNull(shouldBeNull);
+
+    return popNullError(device);
+};
+
+tests["Push and pop many error scopes with no rejections."] = async device => {
+    const numIterations = 128;
+    for (let i = 0; i < numIterations; ++i)
+        device.pushErrorScope("out-of-memory");
+    
+    for (let i = 0; i < numIterations - 1; ++i)
+        await popNullError(device);
+
+    return popNullError(device);
+};
+
+tests["Catch many errors in nested scopes."] = async device => {
+    const numIterations = 128;
+    for (let i = 0; i < numIterations; ++i) {
+        device.pushErrorScope("validation");
+        causeValidationError(device);
+    }
+
+    for (let i = 0; i < numIterations - 1; ++i)
+        await popValidationError(device);
+
+    return popValidationError(device);
+};
+
+runTestsWithDevice(tests);
+
+/* Helper Functions */
+
+const causeValidationError = device => device.createBuffer({ size: 4, usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.MAP_WRITE });
+const causeMemoryError = device => device.createBuffer({ size: 99999999999, usage: GPUBufferUsage.NONE });
+
+</script>
+</body>
\ No newline at end of file
diff --git a/LayoutTests/webgpu/js/webgpu-functions.js b/LayoutTests/webgpu/js/webgpu-functions.js
index 646e801..8a1aef5 100644
--- a/LayoutTests/webgpu/js/webgpu-functions.js
+++ b/LayoutTests/webgpu/js/webgpu-functions.js
@@ -149,3 +149,43 @@
     writeArray.set(new Uint8Array(data), offset);
     buffer.unmap();
 }
+
+/*** Functions below this line require WPT testharness.js and testharnessreport.js. ***/
+
+function runTestsWithDevice(tests) {
+    window.addEventListener("load", async () => {
+        try {
+            var device = await getBasicDevice();
+        } catch (e) { /* WebGPU is not supported. */ }
+    
+        for (let name in tests)
+            devicePromiseTest(device, tests[name], name);
+    });
+}
+
+function devicePromiseTest(device, func, name) {
+    promise_test(async () => {
+        if (device === undefined)
+            return Promise.resolve();
+        return func(device);
+    }, name);
+};
+
+// Asserting errors.
+
+const popValidationError = device => device.popErrorScope().then(error => assertValidationError(error));
+const popMemoryError = device => device.popErrorScope().then(error => assertMemoryError(error));
+const popNullError = device => device.popErrorScope().then(error => assertNull(error));
+const assertNull = error => {
+    let assertionMsg = "No error expected!";
+    if (error && error.message)
+        assertionMsg += " Got: " + error.message;
+    assert_true(error === null, assertionMsg);
+};
+const assertValidationError = error => {
+    let assertionMsg = "Expected validation error: ";
+    if (error && error.message)
+        assertionMsg += error.message;
+    assert_true(error instanceof GPUValidationError, assertionMsg);
+};
+const assertMemoryError = error => assert_true(error instanceof GPUOutOfMemoryError, "Expected out-of-memory error!");
diff --git a/LayoutTests/webgpu/js/whlsl-test-harness.js b/LayoutTests/webgpu/js/whlsl-test-harness.js
index cce9f9f..8e61067 100644
--- a/LayoutTests/webgpu/js/whlsl-test-harness.js
+++ b/LayoutTests/webgpu/js/whlsl-test-harness.js
@@ -253,7 +253,7 @@
 `;
         }
         const code = this._shaderHeader + functions + entryPointCode;
-        this._callFunction(code, argsLayouts, argsResourceBindings);
+        await this._callFunction(code, argsLayouts, argsResourceBindings);
     
         try {
             var result = await this._resultBuffer.mapReadAsync();
@@ -303,6 +303,43 @@
         this._callFunction(code, argsLayouts, argsResourceBindings);
     }
 
+    /**
+     * Assert that malformed shader code does not compile.
+     * @param {String} source - Custom code to be tested.
+     */
+    async checkCompileFail(source)
+    {
+        if (this._device === undefined)
+            return;
+        
+        let entryPointCode;
+        if (this.isWHLSL) {
+            entryPointCode = `
+[numthreads(1, 1, 1)]
+compute void _compute_main() { }`;
+        } else {
+            entryPointCode = `
+kernel void _compute_main() { }`;
+        }
+
+        const code = this._shaderHeader + source + entryPointCode;
+
+        this._device.pushErrorScope("validation");
+        
+        const shaders = this._device.createShaderModule({ code: code, isWHLSL: this._isWHLSL });
+    
+        this._device.createComputePipeline({
+            computeStage: {
+                module: shaders,
+                entryPoint: "_compute_main"
+            }
+        });
+
+        const error = await this._device.popErrorScope();
+        if (!error)
+            throw new Error("Compiler error: shader code did not fail to compile!");
+    }
+
     get device() { return this._device; }
 
     _clearResults()
@@ -359,10 +396,8 @@
         return [argsLayouts, argsResourceBindings, argsDeclarations, functionCallArgs];
     }
 
-    _callFunction(code, argsLayouts, argsResourceBindings)
+    async _callFunction(code, argsLayouts, argsResourceBindings)
     {
-        const shaders = this._device.createShaderModule({ code: code, isWHLSL: this._isWHLSL });
-
         const bindGroupLayout = this._device.createBindGroupLayout({
             bindings: argsLayouts
         });
@@ -374,7 +409,10 @@
             bindings: argsResourceBindings
         });
 
-        // FIXME: Compile errors should be caught and reported here.
+        this._device.pushErrorScope("validation");
+
+        const shaders = this._device.createShaderModule({ code: code, isWHLSL: this._isWHLSL });
+    
         const pipeline = this._device.createComputePipeline({
             layout: pipelineLayout,
             computeStage: {
@@ -391,6 +429,10 @@
         passEncoder.endPass();
         
         this._device.getQueue().submit([commandEncoder.finish()]);
+
+        const error = await this._device.popErrorScope();
+        if (error)
+            throw new Error(error.message);
     }
 }
 
@@ -509,61 +551,9 @@
     return (await harness.callTypedFunction(Types.FLOAT4X4, functions, name, args)).subarray(0, 16);
 }
 
-async function checkFail(source) {
-    // FIXME: Make this handle errors with proper messages once we implement the API for that.
-    const name = "____test_name____";
-    const program = `
-        ${source}
-
-        [numthreads(1, 1, 1)]
-        compute void ${name}(device int[] buffer : register(u0), float3 threadID : SV_DispatchThreadID) {
-            buffer[0] = 1;
-        }
-    `;
-    const device = await getBasicDevice();
-    const shaderModule = device.createShaderModule({code: program, isWHLSL: true});
-    const computeStage = {module: shaderModule, entryPoint: name};
-
-    const bindGroupLayoutDescriptor = {bindings: [{binding: 0, visibility: 7, type: "storage-buffer"}]};
-    const bindGroupLayout = device.createBindGroupLayout(bindGroupLayoutDescriptor);
-    const pipelineLayoutDescriptor = {bindGroupLayouts: [bindGroupLayout]};
-    const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor);
-
-    const computePipelineDescriptor = {computeStage, layout: pipelineLayout};
-    const computePipeline = device.createComputePipeline(computePipelineDescriptor);
-
-    const size = Int32Array.BYTES_PER_ELEMENT * 1;
-
-    const bufferDescriptor = {size, usage: GPUBufferUsage.MAP_WRITE | GPUBufferUsage.TRANSFER_SRC};
-    const buffer = device.createBuffer(bufferDescriptor);
-    const bufferArrayBuffer = await buffer.mapWriteAsync();
-    const bufferInt32Array = new Int32Array(bufferArrayBuffer);
-    bufferInt32Array[0] = 0;
-    buffer.unmap();
-
-    const resultsBufferDescriptor = {size, usage: GPUBufferUsage.STORAGE | GPUBufferUsage.TRANSFER_DST | GPUBufferUsage.MAP_READ};
-    const resultsBuffer = device.createBuffer(resultsBufferDescriptor);
-
-    const bufferBinding = {buffer: resultsBuffer, size};
-    const bindGroupBinding = {binding: 0, resource: bufferBinding};
-    const bindGroupDescriptor = {layout: bindGroupLayout, bindings: [bindGroupBinding]};
-    const bindGroup = device.createBindGroup(bindGroupDescriptor);
-
-    const commandEncoder = device.createCommandEncoder(); // {}
-    commandEncoder.copyBufferToBuffer(buffer, 0, resultsBuffer, 0, size);
-    const computePassEncoder = commandEncoder.beginComputePass();
-    computePassEncoder.setPipeline(computePipeline);
-    computePassEncoder.setBindGroup(0, bindGroup);
-    computePassEncoder.dispatch(1, 1, 1);
-    computePassEncoder.endPass();
-    const commandBuffer = commandEncoder.finish();
-    device.getQueue().submit([commandBuffer]);
-
-    const resultsArrayBuffer = await resultsBuffer.mapReadAsync();
-    let resultsInt32Array = new Int32Array(resultsArrayBuffer);
-    if (resultsInt32Array[0] !== 0)
-        throw new Error("program did not fail to compile");
-    resultsBuffer.unmap();
+async function checkFail(source) 
+{
+    return (await harness.checkCompileFail(source));
 }
 
 /**
diff --git a/LayoutTests/webgpu/whlsl-recursive-structs-expected.txt b/LayoutTests/webgpu/whlsl-recursive-structs-expected.txt
index deb5348..b57d319 100644
--- a/LayoutTests/webgpu/whlsl-recursive-structs-expected.txt
+++ b/LayoutTests/webgpu/whlsl-recursive-structs-expected.txt
@@ -1,4 +1,3 @@
 
 PASS mutuallyRecursiveStruct 
-PASS mutuallyRecursiveStructWithPointersBroken 
 
diff --git a/LayoutTests/webgpu/whlsl-recursive-structs.html b/LayoutTests/webgpu/whlsl-recursive-structs.html
index 82f08d4..36edc0b 100644
--- a/LayoutTests/webgpu/whlsl-recursive-structs.html
+++ b/LayoutTests/webgpu/whlsl-recursive-structs.html
@@ -24,28 +24,29 @@
         
 }
 
-whlslTests.mutuallyRecursiveStructWithPointersBroken = async () =>
-{
-    let program = `
-        struct Foo {
-            thread Bar* bar;
-            int foo;
-        }
-        struct Bar {
-            thread Foo* foo;
-            int bar;
-        }
-        int foo()
-        {
-            Foo foo;
-            Bar bar;
-            foo.foo = 564;
-            bar.bar = 53;
-            return foo.bar->bar - bar.foo->foo;
-        }
-    `;
-    assert_equals(await callIntFunction(program, "foo", []), 0);
-}
+// FIXME https://bugs.webkit.org/show_bug.cgi?id=199766: This should compile.
+// whlslTests.mutuallyRecursiveStructWithPointersBroken = async () =>
+// {
+//     let program = `
+//         struct Foo {
+//             thread Bar* bar;
+//             int foo;
+//         }
+//         struct Bar {
+//             thread Foo* foo;
+//             int bar;
+//         }
+//         int foo()
+//         {
+//             Foo foo;
+//             Bar bar;
+//             foo.foo = 564;
+//             bar.bar = 53;
+//             return foo.bar->bar - bar.foo->foo;
+//         }
+//     `;
+//     assert_equals(await callIntFunction(program, "foo", []), 0);
+// }
 
 runTests(whlslTests);
 </script>
diff --git a/LayoutTests/webgpu/whlsl-test-harness-test-expected.txt b/LayoutTests/webgpu/whlsl-test-harness-test-expected.txt
index a07577d..7abb71a 100644
--- a/LayoutTests/webgpu/whlsl-test-harness-test-expected.txt
+++ b/LayoutTests/webgpu/whlsl-test-harness-test-expected.txt
@@ -30,4 +30,6 @@
 PASS Return an expected float4x4 value. 
 PASS Return an expected float4x4 value. 
 PASS Return an expected float4x4 value. 
+PASS Code should not compile, and no error is reported. 
+PASS Successfully compiling code in checkFail is an error. 
 
diff --git a/LayoutTests/webgpu/whlsl-test-harness-test.html b/LayoutTests/webgpu/whlsl-test-harness-test.html
index 4529146..363a0a1 100644
--- a/LayoutTests/webgpu/whlsl-test-harness-test.html
+++ b/LayoutTests/webgpu/whlsl-test-harness-test.html
@@ -177,6 +177,18 @@
     checkArrays("float4x4", "return in0[0];", [[float4x4expected]], float4x4expected);
 };
 
+whlslTests.checkFailTests = () => {
+    webGPUPromiseTest(() => {
+        return checkFail(`Doors and corners, kid. That's where they getcha.`);
+    }, "Code should not compile, and no error is reported.");
+
+    webGPUPromiseTest(() => {
+        return checkFail("").catch(e => {
+            assert_true(e instanceof Error, "An expected Error was caught.");
+        });
+    }, "Successfully compiling code in checkFail is an error.")
+};
+
 window.addEventListener("load", () => {
     try {
         for (const name in whlslTests) {
diff --git a/Source/WebCore/CMakeLists.txt b/Source/WebCore/CMakeLists.txt
index 3ce5166..84d84ac 100644
--- a/Source/WebCore/CMakeLists.txt
+++ b/Source/WebCore/CMakeLists.txt
@@ -480,9 +480,11 @@
     Modules/webgpu/GPUColorWriteBits.idl
     Modules/webgpu/GPUCompareFunction.idl
     Modules/webgpu/GPUDepthStencilStateDescriptor.idl
+    Modules/webgpu/GPUErrorFilter.idl
     Modules/webgpu/GPUExtent3D.idl
     Modules/webgpu/GPULoadOp.idl
     Modules/webgpu/GPUOrigin3D.idl
+    Modules/webgpu/GPUOutOfMemoryError.idl
     Modules/webgpu/GPURequestAdapterOptions.idl
     Modules/webgpu/GPUSamplerDescriptor.idl
     Modules/webgpu/GPUShaderStageBit.idl
@@ -490,6 +492,7 @@
     Modules/webgpu/GPUTextureDescriptor.idl
     Modules/webgpu/GPUTextureFormat.idl
     Modules/webgpu/GPUTextureUsage.idl
+    Modules/webgpu/GPUValidationError.idl
     Modules/webgpu/GPUVertexAttributeDescriptor.idl
     Modules/webgpu/GPUVertexBufferDescriptor.idl
     Modules/webgpu/GPUVertexInputDescriptor.idl
@@ -508,6 +511,7 @@
     Modules/webgpu/WebGPUComputePipeline.idl
     Modules/webgpu/WebGPUComputePipelineDescriptor.idl
     Modules/webgpu/WebGPUDevice.idl
+    Modules/webgpu/WebGPUDeviceErrorScopes.idl
     Modules/webgpu/WebGPUPipelineDescriptorBase.idl
     Modules/webgpu/WebGPUPipelineLayout.idl
     Modules/webgpu/WebGPUPipelineLayoutDescriptor.idl
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index dd316b6..c6f7e34 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,142 @@
+2019-07-16  Justin Fan  <justin_fan@apple.com>
+
+        [WebGPU] Convert GPUComputePipeline LOG statements to generate GPUErrors
+        https://bugs.webkit.org/show_bug.cgi?id=199773
+
+        Reviewed by Myles C. Maxfield.
+
+        Generate a GPUError if GPUComputePipeline creation fails.
+        Rework the WHLSL test harness to take advantage of this.
+
+        Test: webgpu/compute-pipeline-errors.html
+
+        * Modules/webgpu/WebGPUComputePipelineDescriptor.cpp:
+        (WebCore::WebGPUComputePipelineDescriptor::tryCreateGPUComputePipelineDescriptor const):
+        * Modules/webgpu/WebGPUComputePipelineDescriptor.h:
+        * Modules/webgpu/WebGPUDevice.cpp:
+        (WebCore::WebGPUDevice::createComputePipeline const):
+        * platform/graphics/gpu/GPUBuffer.h:
+        * platform/graphics/gpu/GPUComputePipeline.h: 
+                Now inherits from GPUObjectBase, though this isn't super useful yet
+                since GPUComputePipeline itself does not expose any operations that can error. 
+        * platform/graphics/gpu/GPUDevice.cpp:
+        (WebCore::GPUDevice::tryCreateComputePipeline const):
+        * platform/graphics/gpu/GPUDevice.h:
+        * platform/graphics/gpu/cocoa/GPUBufferMetal.mm:
+        (WebCore::GPUBuffer::validateBufferUsage):
+        * platform/graphics/gpu/cocoa/GPUComputePipelineMetal.mm:
+        (WebCore::trySetMetalFunctions):
+        (WebCore::trySetFunctions):
+        (WebCore::convertComputePipelineDescriptor):
+        (WebCore::tryCreateMTLComputePipelineState):
+        (WebCore::GPUComputePipeline::tryCreate):
+        (WebCore::GPUComputePipeline::GPUComputePipeline):
+
+2019-07-11  Justin Fan  <justin_fan@apple.com>
+
+        [WebGPU] Move error scopes out of GPUDevice for more portable error generation
+        https://bugs.webkit.org/show_bug.cgi?id=199740
+
+        Reviewed by Myles C. Maxfield.
+
+        Move error generation into a separate RefCounted class to allow GPU objects to generate 
+        errors independent of any GPUDevice.
+        Create GPUObjectBase to delegate error generation and refactor GPUBuffer to inherit from GPUObjectBase.
+
+        No behavior change or new tests. Error scopes covered by error-scopes-test.html.
+
+        * Modules/webgpu/WebGPUDevice.cpp:
+        (WebCore::WebGPUDevice::WebGPUDevice): Now creates a GPUErrorGenerator.
+        (WebCore::WebGPUDevice::createBuffer const): Pass the GPUErrorGenerator to any created GPUBuffer.
+        (WebCore::WebGPUDevice::createBufferMapped const): Ditto.
+        (WebCore::WebGPUDevice::popErrorScope): Shouldn't be const. Can just ask for the GPUError rather than passing a lambda.
+        (WebCore::WebGPUDevice::pushErrorScope const): Deleted.
+        (WebCore::WebGPUDevice::popErrorScope const): Deleted.
+        * Modules/webgpu/WebGPUDevice.h:
+        (WebCore::WebGPUDevice::pushErrorScope):
+        * Sources.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        * platform/graphics/gpu/GPUBuffer.h: Now inherits from GPUObjectBase for error generation ease.
+        * platform/graphics/gpu/GPUDevice.cpp:
+        (WebCore::GPUDevice::tryCreateBuffer): Ensure GPUBuffers reference the GPUErrorGenerator.
+        (WebCore::GPUDevice::pushErrorScope): Deleted. No longer needed here.
+        (WebCore::GPUDevice::popErrorScope): Deleted.
+        (WebCore::GPUDevice::registerError): Deleted.
+        * platform/graphics/gpu/GPUDevice.h: Move error scope logic out.
+        * platform/graphics/gpu/GPUErrorGenerator.cpp: Added.
+        (WebCore::GPUErrorGenerator::pushErrorScope):
+        (WebCore::GPUErrorGenerator::popErrorScope):
+        (WebCore::GPUErrorGenerator::generateError):
+        * platform/graphics/gpu/GPUErrorGenerator.h: Added.
+        (WebCore::GPUErrorGenerator::create):
+        * platform/graphics/gpu/GPUObjectBase.h: Added.
+        (WebCore::GPUObjectBase::generateError):
+        (WebCore::GPUObjectBase::GPUObjectBase):
+        * platform/graphics/gpu/cocoa/GPUBufferMetal.mm: Use the GPUErrorGenerator directly during buffer creation.
+        (WebCore::GPUBuffer::validateBufferUsage):
+        (WebCore::GPUBuffer::tryCreate):
+        (WebCore::GPUBuffer::GPUBuffer):
+        * platform/graphics/gpu/cocoa/GPUQueueMetal.mm:
+        (WebCore::GPUQueue::submit): Prevent possible null dereference.
+
+2019-07-10  Justin Fan  <justin_fan@apple.com>
+
+        [WebGPU] Implement GPUError and error scopes
+        https://bugs.webkit.org/show_bug.cgi?id=199655
+
+        Reviewed by Myles C. Maxfield.
+
+        Add GPUErrorFilter, GPUError, and the ability to push and pop error scopes on a GPUDevice.
+        This will allow us to check for WebGPU errors from JavaScript.
+        Currently, only some GPUBuffer creation errors are reported for testing; more errors will follow in later patches.
+
+        Test: webgpu/error-scopes-test.html
+
+        * Modules/webgpu/GPUErrorFilter.idl: Added.
+        * Modules/webgpu/GPUOutOfMemoryError.idl: Added.
+        * Modules/webgpu/GPUValidationError.idl: Added.
+        * Modules/webgpu/WebGPUDevice.cpp:
+        (WebCore::WebGPUDevice::pushErrorScope):
+        (WebCore::WebGPUDevice::popErrorScope): Resolve the Promise here, since GPUDevice shouldn't worry about DOM layer.
+        * Modules/webgpu/WebGPUDevice.h:
+        * Modules/webgpu/WebGPUDeviceErrorScopes.cpp: Added.
+        (WebCore::WebGPUDeviceErrorScopes::pushErrorScope): Delegates to WebGPUDevice.
+        (WebCore::WebGPUDeviceErrorScopes::popErrorScope): Ditto.
+        * Modules/webgpu/WebGPUDeviceErrorScopes.h: Added.
+        * Modules/webgpu/WebGPUDeviceErrorScopes.idl: Added.
+        * platform/graphics/gpu/GPUBuffer.h:
+        * platform/graphics/gpu/GPUDevice.cpp: The actual error stack lives here.
+        (WebCore::GPUDevice::pushErrorScope):
+        (WebCore::GPUDevice::popErrorScope): Calls a callback with a GPUError, if any.
+        (WebCore::GPUDevice::registerError): Actually creates GPUErrors.
+        * platform/graphics/gpu/GPUDevice.h:
+        * platform/graphics/gpu/GPUError.cpp: Added.
+        (WebCore::createError): Factory function for various error types.
+        * platform/graphics/gpu/GPUError.h: Added.
+        * platform/graphics/gpu/GPUErrorFilter.h: Added.
+        * platform/graphics/gpu/GPUOutOfMemoryError.h: Added.
+        (WebCore::GPUOutOfMemoryError::create):
+        * platform/graphics/gpu/GPUValidationError.cpp: Added.
+        (WebCore::GPUValidationError::create):
+        (WebCore::GPUValidationError::GPUValidationError):
+        * platform/graphics/gpu/GPUValidationError.h: Added.
+        (WebCore::GPUValidationError::message const):
+        * platform/graphics/gpu/cocoa/GPUBufferMetal.mm:
+        (WebCore::GPUBuffer::validateBufferUsage): Create an actual GPUValidationError :)
+        (WebCore::GPUBuffer::tryCreate): Create GPUOutOfMemoryErrors where appropriate.
+
+        Add file/name references:
+        * CMakeLists.txt:
+        * DerivedSources-input.xcfilelist:
+        * DerivedSources-output.xcfilelist:
+        * DerivedSources.make:
+        * Sources.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        * bindings/js/WebCoreBuiltinNames.h:
+
+        Missing includes:
+        * Modules/webgpu/WHLSL/WHLSLCheckTextureReferences.cpp:
+
 2019-07-16  Commit Queue  <commit-queue@webkit.org>
 
         Unreviewed, rolling out r247493.
diff --git a/Source/WebCore/DerivedSources-input.xcfilelist b/Source/WebCore/DerivedSources-input.xcfilelist
index c69d3dd..a681376 100644
--- a/Source/WebCore/DerivedSources-input.xcfilelist
+++ b/Source/WebCore/DerivedSources-input.xcfilelist
@@ -330,10 +330,12 @@
 $(PROJECT_DIR)/Modules/webgpu/GPUColorWriteBits.idl
 $(PROJECT_DIR)/Modules/webgpu/GPUCompareFunction.idl
 $(PROJECT_DIR)/Modules/webgpu/GPUDepthStencilStateDescriptor.idl
+$(PROJECT_DIR)/Modules/webgpu/GPUErrorFilter.idl
 $(PROJECT_DIR)/Modules/webgpu/GPUExtent3D.idl
 $(PROJECT_DIR)/Modules/webgpu/GPUInputStateDescriptor.idl
 $(PROJECT_DIR)/Modules/webgpu/GPULoadOp.idl
 $(PROJECT_DIR)/Modules/webgpu/GPUOrigin3D.idl
+$(PROJECT_DIR)/Modules/webgpu/GPUOutOfMemoryError.idl
 $(PROJECT_DIR)/Modules/webgpu/GPURequestAdapterOptions.idl
 $(PROJECT_DIR)/Modules/webgpu/GPUSamplerDescriptor.idl
 $(PROJECT_DIR)/Modules/webgpu/GPUShaderStageBit.idl
@@ -341,6 +343,7 @@
 $(PROJECT_DIR)/Modules/webgpu/GPUTextureDescriptor.idl
 $(PROJECT_DIR)/Modules/webgpu/GPUTextureFormat.idl
 $(PROJECT_DIR)/Modules/webgpu/GPUTextureUsage.idl
+$(PROJECT_DIR)/Modules/webgpu/GPUValidationError.idl
 $(PROJECT_DIR)/Modules/webgpu/GPUVertexAttributeDescriptor.idl
 $(PROJECT_DIR)/Modules/webgpu/GPUVertexBufferDescriptor.idl
 $(PROJECT_DIR)/Modules/webgpu/GPUVertexInputDescriptor.idl
@@ -361,6 +364,7 @@
 $(PROJECT_DIR)/Modules/webgpu/WebGPUComputePipeline.idl
 $(PROJECT_DIR)/Modules/webgpu/WebGPUComputePipelineDescriptor.idl
 $(PROJECT_DIR)/Modules/webgpu/WebGPUDevice.idl
+$(PROJECT_DIR)/Modules/webgpu/WebGPUDeviceErrorScopes.idl
 $(PROJECT_DIR)/Modules/webgpu/WebGPUPipelineDescriptorBase.idl
 $(PROJECT_DIR)/Modules/webgpu/WebGPUPipelineLayout.idl
 $(PROJECT_DIR)/Modules/webgpu/WebGPUPipelineLayoutDescriptor.idl
diff --git a/Source/WebCore/DerivedSources-output.xcfilelist b/Source/WebCore/DerivedSources-output.xcfilelist
index 37c3c8b..4a26d29 100644
--- a/Source/WebCore/DerivedSources-output.xcfilelist
+++ b/Source/WebCore/DerivedSources-output.xcfilelist
@@ -609,6 +609,8 @@
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSGPUCompareFunction.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSGPUDepthStencilStateDescriptor.cpp
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSGPUDepthStencilStateDescriptor.h
+$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSGPUErrorFilter.cpp
+$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSGPUErrorFilter.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSGPUExtent3D.cpp
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSGPUExtent3D.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSGPUInputStateDescriptor.cpp
@@ -617,6 +619,8 @@
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSGPULoadOp.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSGPUOrigin3D.cpp
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSGPUOrigin3D.h
+$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSGPUOutOfMemoryError.cpp
+$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSGPUOutOfMemoryError.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSGPURequestAdapterOptions.cpp
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSGPURequestAdapterOptions.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSGPUSamplerDescriptor.cpp
@@ -631,6 +635,8 @@
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSGPUTextureFormat.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSGPUTextureUsage.cpp
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSGPUTextureUsage.h
+$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSGPUValidationError.cpp
+$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSGPUValidationError.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSGPUVertexAttributeDescriptor.cpp
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSGPUVertexAttributeDescriptor.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSGPUVertexBufferDescriptor.cpp
@@ -1943,6 +1949,8 @@
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSWebGPUComputePipelineDescriptor.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSWebGPUDevice.cpp
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSWebGPUDevice.h
+$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSWebGPUDeviceErrorScopes.cpp
+$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSWebGPUDeviceErrorScopes.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSWebGPUPipelineDescriptorBase.cpp
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSWebGPUPipelineDescriptorBase.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSWebGPUPipelineLayout.cpp
diff --git a/Source/WebCore/DerivedSources.make b/Source/WebCore/DerivedSources.make
index 7eeb427..c617716 100644
--- a/Source/WebCore/DerivedSources.make
+++ b/Source/WebCore/DerivedSources.make
@@ -386,9 +386,11 @@
     $(WebCore)/Modules/webgpu/GPUBufferUsage.idl \
     $(WebCore)/Modules/webgpu/GPUCompareFunction.idl \
     $(WebCore)/Modules/webgpu/GPUDepthStencilStateDescriptor.idl \
+    $(WebCore)/Modules/webgpu/GPUErrorFilter.idl \
     $(WebCore)/Modules/webgpu/GPUExtent3D.idl \
     $(WebCore)/Modules/webgpu/GPULoadOp.idl \
     $(WebCore)/Modules/webgpu/GPUOrigin3D.idl \
+    $(WebCore)/Modules/webgpu/GPUOutOfMemoryError.idl \
     $(WebCore)/Modules/webgpu/GPURequestAdapterOptions.idl \
     $(WebCore)/Modules/webgpu/GPUSamplerDescriptor.idl \
     $(WebCore)/Modules/webgpu/GPUShaderStageBit.idl \
@@ -396,6 +398,7 @@
     $(WebCore)/Modules/webgpu/GPUTextureDescriptor.idl \
     $(WebCore)/Modules/webgpu/GPUTextureFormat.idl \
     $(WebCore)/Modules/webgpu/GPUTextureUsage.idl \
+    $(WebCore)/Modules/webgpu/GPUValidationError.idl \
     $(WebCore)/Modules/webgpu/GPUVertexAttributeDescriptor.idl \
     $(WebCore)/Modules/webgpu/GPUVertexBufferDescriptor.idl \
 	$(WebCore)/Modules/webgpu/GPUVertexInputDescriptor.idl \
@@ -414,6 +417,7 @@
     $(WebCore)/Modules/webgpu/WebGPUComputePipeline.idl \
     $(WebCore)/Modules/webgpu/WebGPUComputePipelineDescriptor.idl \
     $(WebCore)/Modules/webgpu/WebGPUDevice.idl \
+	$(WebCore)/Modules/webgpu/WebGPUDeviceErrorScopes.idl \
     $(WebCore)/Modules/webgpu/WebGPUQueue.idl \
     $(WebCore)/Modules/webgpu/WebGPUPipelineDescriptorBase.idl \
     $(WebCore)/Modules/webgpu/WebGPUPipelineLayout.idl \
diff --git a/Source/WebCore/Modules/webgpu/GPUErrorFilter.idl b/Source/WebCore/Modules/webgpu/GPUErrorFilter.idl
new file mode 100644
index 0000000..1d6acbb
--- /dev/null
+++ b/Source/WebCore/Modules/webgpu/GPUErrorFilter.idl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// https://gpuweb.github.io/gpuweb
+
+[
+    Conditional=WEBGPU,
+    EnabledAtRuntime=WebGPU
+] enum GPUErrorFilter {
+    "none",
+    "out-of-memory",
+    "validation"
+};
diff --git a/Source/WebCore/Modules/webgpu/GPUOutOfMemoryError.idl b/Source/WebCore/Modules/webgpu/GPUOutOfMemoryError.idl
new file mode 100644
index 0000000..d4d3d00
--- /dev/null
+++ b/Source/WebCore/Modules/webgpu/GPUOutOfMemoryError.idl
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// https://gpuweb.github.io/gpuweb
+
+[
+    Conditional=WEBGPU,
+    Constructor(),
+    EnabledAtRuntime=WebGPU,
+    ImplementationLacksVTable
+] interface GPUOutOfMemoryError {};
diff --git a/Source/WebCore/Modules/webgpu/GPUValidationError.idl b/Source/WebCore/Modules/webgpu/GPUValidationError.idl
new file mode 100644
index 0000000..5e13c18
--- /dev/null
+++ b/Source/WebCore/Modules/webgpu/GPUValidationError.idl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// https://gpuweb.github.io/gpuweb
+
+[
+    Conditional=WEBGPU,
+    Constructor(DOMString message),
+    EnabledAtRuntime=WebGPU,
+    ImplementationLacksVTable
+] interface GPUValidationError {
+    readonly attribute DOMString message;
+};
diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLCheckTextureReferences.cpp b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLCheckTextureReferences.cpp
index c02db89..7386b10 100644
--- a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLCheckTextureReferences.cpp
+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLCheckTextureReferences.cpp
@@ -26,10 +26,15 @@
 #include "config.h"
 #include "WHLSLCheckTextureReferences.h"
 
-#include "WHLSLInferTypes.h"
-
 #if ENABLE(WEBGPU)
 
+#include "WHLSLArrayReferenceType.h"
+#include "WHLSLArrayType.h"
+#include "WHLSLInferTypes.h"
+#include "WHLSLNativeTypeDeclaration.h"
+#include "WHLSLPointerType.h"
+#include "WHLSLVisitor.h"
+
 namespace WebCore {
 
 namespace WHLSL {
diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLRecursionChecker.cpp b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLRecursionChecker.cpp
index 6af88fe..ba497b3 100644
--- a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLRecursionChecker.cpp
+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLRecursionChecker.cpp
@@ -30,6 +30,7 @@
 
 #include "WHLSLCallExpression.h"
 #include "WHLSLFunctionDefinition.h"
+#include "WHLSLProgram.h"
 #include "WHLSLVisitor.h"
 #include <wtf/HashSet.h>
 
diff --git a/Source/WebCore/Modules/webgpu/WebGPUComputePipelineDescriptor.cpp b/Source/WebCore/Modules/webgpu/WebGPUComputePipelineDescriptor.cpp
index de204bb..e1d2acc 100644
--- a/Source/WebCore/Modules/webgpu/WebGPUComputePipelineDescriptor.cpp
+++ b/Source/WebCore/Modules/webgpu/WebGPUComputePipelineDescriptor.cpp
@@ -29,17 +29,17 @@
 #if ENABLE(WEBGPU)
 
 #include "GPUComputePipelineDescriptor.h"
-#include "Logging.h"
+#include "GPUErrorScopes.h"
 
 namespace WebCore {
 
-Optional<GPUComputePipelineDescriptor> WebGPUComputePipelineDescriptor::tryCreateGPUComputePipelineDescriptor() const
+Optional<GPUComputePipelineDescriptor> WebGPUComputePipelineDescriptor::tryCreateGPUComputePipelineDescriptor(GPUErrorScopes& errorScopes) const
 {
     auto pipelineLayout = layout ? makeRefPtr(layout->pipelineLayout()) : nullptr;
 
     auto compute = computeStage.tryCreateGPUPipelineStageDescriptor();
     if (!compute) {
-        LOG(WebGPU, "GPUDevice::createComputePipeline(): Invalid GPUPipelineStageDescriptor!");
+        errorScopes.generateError("GPUDevice::createComputePipeline(): Invalid GPUPipelineStageDescriptor!");
         return WTF::nullopt;
     }
 
diff --git a/Source/WebCore/Modules/webgpu/WebGPUComputePipelineDescriptor.h b/Source/WebCore/Modules/webgpu/WebGPUComputePipelineDescriptor.h
index a453902..5c333ea 100644
--- a/Source/WebCore/Modules/webgpu/WebGPUComputePipelineDescriptor.h
+++ b/Source/WebCore/Modules/webgpu/WebGPUComputePipelineDescriptor.h
@@ -33,10 +33,12 @@
 
 namespace WebCore {
 
+class GPUErrorScopes;
+
 struct GPUComputePipelineDescriptor;
 
 struct WebGPUComputePipelineDescriptor : WebGPUPipelineDescriptorBase {
-    Optional<GPUComputePipelineDescriptor> tryCreateGPUComputePipelineDescriptor() const;
+    Optional<GPUComputePipelineDescriptor> tryCreateGPUComputePipelineDescriptor(GPUErrorScopes&) const;
 
     WebGPUPipelineStageDescriptor computeStage;
 };
diff --git a/Source/WebCore/Modules/webgpu/WebGPUDevice.cpp b/Source/WebCore/Modules/webgpu/WebGPUDevice.cpp
index f059ad8..13a0cf0 100644
--- a/Source/WebCore/Modules/webgpu/WebGPUDevice.cpp
+++ b/Source/WebCore/Modules/webgpu/WebGPUDevice.cpp
@@ -28,6 +28,7 @@
 
 #if ENABLE(WEBGPU)
 
+#include "Exception.h"
 #include "GPUBindGroup.h"
 #include "GPUBindGroupBinding.h"
 #include "GPUBindGroupDescriptor.h"
@@ -42,6 +43,8 @@
 #include "GPUShaderModuleDescriptor.h"
 #include "GPUTextureDescriptor.h"
 #include "JSDOMConvertBufferSource.h"
+#include "JSGPUOutOfMemoryError.h"
+#include "JSGPUValidationError.h"
 #include "JSWebGPUBuffer.h"
 #include "Logging.h"
 #include "WebGPUBindGroup.h"
@@ -63,6 +66,8 @@
 #include "WebGPUShaderModuleDescriptor.h"
 #include "WebGPUSwapChain.h"
 #include "WebGPUTexture.h"
+#include <wtf/Optional.h>
+#include <wtf/text/WTFString.h>
 
 namespace WebCore {
 
@@ -76,12 +81,13 @@
 WebGPUDevice::WebGPUDevice(Ref<const WebGPUAdapter>&& adapter, Ref<GPUDevice>&& device)
     : m_adapter(WTFMove(adapter))
     , m_device(WTFMove(device))
+    , m_errorScopes(GPUErrorScopes::create())
 {
 }
 
 Ref<WebGPUBuffer> WebGPUDevice::createBuffer(const GPUBufferDescriptor& descriptor) const
 {
-    auto buffer = m_device->tryCreateBuffer(descriptor);
+    auto buffer = m_device->tryCreateBuffer(descriptor, GPUBufferMappedOption::NotMapped, m_errorScopes.copyRef());
     return WebGPUBuffer::create(WTFMove(buffer));
 }
 
@@ -89,7 +95,7 @@
 {
     JSC::JSValue wrappedArrayBuffer = JSC::jsNull();
 
-    auto buffer = m_device->tryCreateBuffer(descriptor, true);
+    auto buffer = m_device->tryCreateBuffer(descriptor, GPUBufferMappedOption::IsMapped, m_errorScopes.copyRef());
     if (buffer) {
         auto arrayBuffer = buffer->mapOnCreation();
         wrappedArrayBuffer = toJS(&state, JSC::jsCast<JSDOMGlobalObject*>(state.lexicalGlobalObject()), arrayBuffer);
@@ -158,11 +164,11 @@
 
 Ref<WebGPUComputePipeline> WebGPUDevice::createComputePipeline(const WebGPUComputePipelineDescriptor& descriptor) const
 {
-    auto gpuDescriptor = descriptor.tryCreateGPUComputePipelineDescriptor();
+    auto gpuDescriptor = descriptor.tryCreateGPUComputePipelineDescriptor(m_errorScopes);
     if (!gpuDescriptor)
         return WebGPUComputePipeline::create(nullptr);
 
-    auto pipeline = m_device->tryCreateComputePipeline(*gpuDescriptor);
+    auto pipeline = m_device->tryCreateComputePipeline(*gpuDescriptor, m_errorScopes.copyRef());
     return WebGPUComputePipeline::create(WTFMove(pipeline));
 }
 
@@ -180,6 +186,16 @@
     return makeRef(*m_queue.get());
 }
 
+void WebGPUDevice::popErrorScope(ErrorPromise&& promise)
+{
+    String failMessage;
+    Optional<GPUError> error = m_errorScopes->popErrorScope(failMessage);
+    if (failMessage.isEmpty())
+        promise.resolve(error);
+    else
+        promise.reject(Exception { OperationError, "GPUDevice::popErrorScope(): " + failMessage });
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(WEBGPU)
diff --git a/Source/WebCore/Modules/webgpu/WebGPUDevice.h b/Source/WebCore/Modules/webgpu/WebGPUDevice.h
index 21d371a..f4e43f2 100644
--- a/Source/WebCore/Modules/webgpu/WebGPUDevice.h
+++ b/Source/WebCore/Modules/webgpu/WebGPUDevice.h
@@ -28,6 +28,8 @@
 #if ENABLE(WEBGPU)
 
 #include "GPUDevice.h"
+#include "GPUErrorScopes.h"
+#include "JSDOMPromiseDeferred.h"
 #include "WebGPUAdapter.h"
 #include "WebGPUQueue.h"
 #include "WebGPUSwapChainDescriptor.h"
@@ -43,6 +45,8 @@
 
 namespace WebCore {
 
+class GPUOutOfMemoryError;
+class GPUValidationError;
 class ScriptExecutionContext;
 class WebGPUBindGroup;
 class WebGPUBindGroupLayout;
@@ -66,6 +70,11 @@
 struct WebGPURenderPipelineDescriptor;
 struct WebGPUShaderModuleDescriptor;
 
+enum class GPUErrorFilter;
+
+using ErrorIDLUnion = IDLUnion<IDLInterface<GPUOutOfMemoryError>, IDLInterface<GPUValidationError>>;
+using ErrorPromise = DOMPromiseDeferred<IDLNullable<ErrorIDLUnion>>;
+
 class WebGPUDevice : public RefCounted<WebGPUDevice> {
 public:
     static RefPtr<WebGPUDevice> tryCreate(Ref<const WebGPUAdapter>&&);
@@ -91,12 +100,17 @@
 
     Ref<WebGPUQueue> getQueue() const;
 
+    void pushErrorScope(GPUErrorFilter filter) { m_errorScopes->pushErrorScope(filter); }
+    void popErrorScope(ErrorPromise&&);
+
 private:
     WebGPUDevice(Ref<const WebGPUAdapter>&&, Ref<GPUDevice>&&);
 
     Ref<const WebGPUAdapter> m_adapter;
     Ref<GPUDevice> m_device;
     mutable RefPtr<WebGPUQueue> m_queue;
+
+    Ref<GPUErrorScopes> m_errorScopes;
 };
 
 } // namespace WebCore
diff --git a/Source/WebCore/Modules/webgpu/WebGPUDeviceErrorScopes.cpp b/Source/WebCore/Modules/webgpu/WebGPUDeviceErrorScopes.cpp
new file mode 100644
index 0000000..7931100d
--- /dev/null
+++ b/Source/WebCore/Modules/webgpu/WebGPUDeviceErrorScopes.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "WebGPUDeviceErrorScopes.h"
+
+#if ENABLE(WEBGPU)
+
+#include "GPUErrorFilter.h"
+
+namespace WebCore {
+
+void WebGPUDeviceErrorScopes::pushErrorScope(WebGPUDevice& device, GPUErrorFilter filter)
+{
+    device.pushErrorScope(filter);
+}
+
+void WebGPUDeviceErrorScopes::popErrorScope(WebGPUDevice& device, ErrorPromise&& promise)
+{
+    device.popErrorScope(WTFMove(promise));
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WEBGPU)
diff --git a/Source/WebCore/Modules/webgpu/WebGPUDeviceErrorScopes.h b/Source/WebCore/Modules/webgpu/WebGPUDeviceErrorScopes.h
new file mode 100644
index 0000000..f20f07a
--- /dev/null
+++ b/Source/WebCore/Modules/webgpu/WebGPUDeviceErrorScopes.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(WEBGPU)
+
+#include "WebGPUDevice.h"
+
+namespace WebCore {
+
+enum class GPUErrorFilter;
+
+class WebGPUDeviceErrorScopes {
+public:
+    static void pushErrorScope(WebGPUDevice&, GPUErrorFilter);
+    static void popErrorScope(WebGPUDevice&, ErrorPromise&&);
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(WEBGPU)
diff --git a/Source/WebCore/Modules/webgpu/WebGPUDeviceErrorScopes.idl b/Source/WebCore/Modules/webgpu/WebGPUDeviceErrorScopes.idl
new file mode 100644
index 0000000..ec78527
--- /dev/null
+++ b/Source/WebCore/Modules/webgpu/WebGPUDeviceErrorScopes.idl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// https://gpuweb.github.io/gpuweb
+
+typedef (GPUOutOfMemoryError or GPUValidationError) GPUError;
+
+[
+    Conditional=WEBGPU,
+    EnabledAtRuntime=WebGPU
+] partial interface WebGPUDevice {
+    void pushErrorScope(GPUErrorFilter filter);
+    Promise<GPUError?> popErrorScope();
+};
diff --git a/Source/WebCore/Sources.txt b/Source/WebCore/Sources.txt
index 5d18e14..cc6f2bd 100644
--- a/Source/WebCore/Sources.txt
+++ b/Source/WebCore/Sources.txt
@@ -367,6 +367,7 @@
 Modules/webgpu/WebGPUComputePipeline.cpp
 Modules/webgpu/WebGPUComputePipelineDescriptor.cpp
 Modules/webgpu/WebGPUDevice.cpp
+Modules/webgpu/WebGPUDeviceErrorScopes.cpp
 Modules/webgpu/WebGPUQueue.cpp
 Modules/webgpu/WebGPUPipelineLayout.cpp
 Modules/webgpu/WebGPUPipelineLayoutDescriptor.cpp
@@ -1875,6 +1876,9 @@
 
 platform/graphics/gpu/GPUBuffer.cpp
 platform/graphics/gpu/GPUDevice.cpp
+platform/graphics/gpu/GPUError.cpp
+platform/graphics/gpu/GPUErrorScopes.cpp
+platform/graphics/gpu/GPUValidationError.cpp
 platform/graphics/gpu/GPUPipelineLayout.cpp
 platform/graphics/gpu/GPUProgrammablePassEncoder.cpp
 
@@ -2804,9 +2808,11 @@
 JSGPUBufferUsage.cpp
 JSGPUCompareFunction.cpp
 JSGPUDepthStencilStateDescriptor.cpp
+JSGPUErrorFilter.cpp
 JSGPUExtent3D.cpp
 JSGPULoadOp.cpp
 JSGPUOrigin3D.cpp
+JSGPUOutOfMemoryError.cpp
 JSGPURequestAdapterOptions.cpp
 JSGPUSamplerDescriptor.cpp
 JSGPUShaderStageBit.cpp
@@ -2814,6 +2820,7 @@
 JSGPUTextureDescriptor.cpp
 JSGPUTextureFormat.cpp
 JSGPUTextureUsage.cpp
+JSGPUValidationError.cpp
 JSGPUVertexAttributeDescriptor.cpp
 JSGPUVertexBufferDescriptor.cpp
 JSGPUVertexInputDescriptor.cpp
@@ -3366,6 +3373,7 @@
 JSWebGPUComputePipeline.cpp
 JSWebGPUComputePipelineDescriptor.cpp
 JSWebGPUDevice.cpp
+JSWebGPUDeviceErrorScopes.cpp
 JSWebGPUQueue.cpp
 JSWebGPUPipelineDescriptorBase.cpp
 JSWebGPUPipelineLayout.cpp
diff --git a/Source/WebCore/WebCore.xcodeproj/project.pbxproj b/Source/WebCore/WebCore.xcodeproj/project.pbxproj
index 70ef35a..b453f81 100644
--- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj
+++ b/Source/WebCore/WebCore.xcodeproj/project.pbxproj
@@ -13906,6 +13906,8 @@
 		D03211CE21AC954E00763CF2 /* GPURenderPassEncoder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPURenderPassEncoder.h; sourceTree = "<group>"; };
 		D03211CF21AC954E00763CF2 /* GPUProgrammablePassEncoder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPUProgrammablePassEncoder.h; sourceTree = "<group>"; };
 		D03211D021AC954F00763CF2 /* GPURenderPassDescriptor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPURenderPassDescriptor.h; sourceTree = "<group>"; };
+		D03586B122D7F2EA00DA0284 /* GPUErrorScopes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPUErrorScopes.h; sourceTree = "<group>"; };
+		D03586B222D7F2EA00DA0284 /* GPUErrorScopes.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = GPUErrorScopes.cpp; sourceTree = "<group>"; };
 		D036DD8D208FFC0C00F9F4B2 /* WebGLCompressedTextureASTC.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = WebGLCompressedTextureASTC.idl; sourceTree = "<group>"; };
 		D03C849A21FFC6670002227F /* GPUDepthStencilStateDescriptor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPUDepthStencilStateDescriptor.h; sourceTree = "<group>"; };
 		D03C849C21FFC7FC0002227F /* GPUCompareFunction.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPUCompareFunction.h; sourceTree = "<group>"; };
@@ -13970,6 +13972,20 @@
 		D093D225217951D400329217 /* GPUCanvasContext.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPUCanvasContext.h; sourceTree = "<group>"; };
 		D093D227217951D400329217 /* GPUCanvasContext.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = GPUCanvasContext.idl; sourceTree = "<group>"; };
 		D093D2292179541600329217 /* GPUCanvasContext.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = GPUCanvasContext.cpp; sourceTree = "<group>"; };
+		D09AFAFF22D02E5300C4538C /* WebGPUDeviceErrorScopes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WebGPUDeviceErrorScopes.h; sourceTree = "<group>"; };
+		D09AFB0122D02E5300C4538C /* WebGPUDeviceErrorScopes.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WebGPUDeviceErrorScopes.cpp; sourceTree = "<group>"; };
+		D09AFB0222D0471900C4538C /* GPUErrorFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPUErrorFilter.h; sourceTree = "<group>"; };
+		D09AFB0322D40CC500C4538C /* WebGPUDeviceErrorScopes.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = WebGPUDeviceErrorScopes.idl; sourceTree = "<group>"; };
+		D09AFB0622D417B300C4538C /* GPUErrorFilter.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = GPUErrorFilter.idl; sourceTree = "<group>"; };
+		D09AFB0722D5391B00C4538C /* GPUError.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPUError.h; sourceTree = "<group>"; };
+		D09AFB0822D5542800C4538C /* GPUError.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = GPUError.cpp; sourceTree = "<group>"; };
+		D09AFB0C22D55E9000C4538C /* GPUValidationError.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = GPUValidationError.idl; sourceTree = "<group>"; };
+		D09AFB0D22D55F3B00C4538C /* GPUValidationError.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPUValidationError.h; sourceTree = "<group>"; };
+		D09AFB0E22D55FF500C4538C /* GPUValidationError.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = GPUValidationError.cpp; sourceTree = "<group>"; };
+		D09AFB1722D6694E00C4538C /* GPUOutOfMemoryError.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = GPUOutOfMemoryError.idl; sourceTree = "<group>"; };
+		D09AFB1922D6698A00C4538C /* GPUOutOfMemoryError.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPUOutOfMemoryError.h; sourceTree = "<group>"; };
+		D09AFB2D22D6C01400C4538C /* GPUError.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = GPUError.cpp; sourceTree = "<group>"; };
+		D09AFB3722D7D5C600C4538C /* GPUObjectBase.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPUObjectBase.h; sourceTree = "<group>"; };
 		D0A20D542092A0A600E0C259 /* WebGLCompressedTextureASTC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebGLCompressedTextureASTC.h; sourceTree = "<group>"; };
 		D0A20D562092A0A600E0C259 /* WebGLCompressedTextureASTC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebGLCompressedTextureASTC.cpp; sourceTree = "<group>"; };
 		D0A3A7301405A39800FB8ED3 /* ResourceLoaderOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ResourceLoaderOptions.h; sourceTree = "<group>"; };
@@ -18272,9 +18288,17 @@
 				D03C849A21FFC6670002227F /* GPUDepthStencilStateDescriptor.h */,
 				312FF8BF21A4C2F100EB199D /* GPUDevice.cpp */,
 				312FF8BE21A4C2F100EB199D /* GPUDevice.h */,
+				D09AFB0822D5542800C4538C /* GPUError.cpp */,
+				D09AFB2D22D6C01400C4538C /* GPUError.cpp */,
+				D09AFB0722D5391B00C4538C /* GPUError.h */,
+				D09AFB0222D0471900C4538C /* GPUErrorFilter.h */,
+				D03586B222D7F2EA00DA0284 /* GPUErrorScopes.cpp */,
+				D03586B122D7F2EA00DA0284 /* GPUErrorScopes.h */,
 				D026F47D220A2AC600AC5F49 /* GPUExtent3D.h */,
 				D0F7559F2203BA1400118058 /* GPULimits.h */,
 				D08AA02F220D0BD50058C502 /* GPULoadOp.h */,
+				D09AFB3722D7D5C600C4538C /* GPUObjectBase.h */,
+				D09AFB1922D6698A00C4538C /* GPUOutOfMemoryError.h */,
 				312FF8C421A4C2F400EB199D /* GPUPipelineDescriptorBase.h */,
 				D003288721C9A4E500622AA6 /* GPUPipelineLayout.cpp */,
 				D003288621C9A4E500622AA6 /* GPUPipelineLayout.h */,
@@ -18300,6 +18324,8 @@
 				312FF8C321A4C2F300EB199D /* GPUTextureFormat.h */,
 				D026F485220A477200AC5F49 /* GPUTextureUsage.h */,
 				D06EF552220BA26A0018724E /* GPUUtils.h */,
+				D09AFB0E22D55FF500C4538C /* GPUValidationError.cpp */,
+				D09AFB0D22D55F3B00C4538C /* GPUValidationError.h */,
 				D0D8649B21BA1C2D003C983C /* GPUVertexAttributeDescriptor.h */,
 				D0D8649C21BA1CE8003C983C /* GPUVertexBufferDescriptor.h */,
 				D0D8649921BA1B1F003C983C /* GPUVertexInputDescriptor.h */,
@@ -25889,10 +25915,12 @@
 				D0B56EAE224ECE200061049C /* GPUColorWriteBits.idl */,
 				D03C849E21FFCF000002227F /* GPUCompareFunction.idl */,
 				D03C84A221FFD7230002227F /* GPUDepthStencilStateDescriptor.idl */,
+				D09AFB0622D417B300C4538C /* GPUErrorFilter.idl */,
 				D026F480220A2B7000AC5F49 /* GPUExtent3D.idl */,
 				D08AA02D220D0B9C0058C502 /* GPULoadOp.idl */,
 				D0CCA94922299F97006979B6 /* GPUOrigin3D.h */,
 				D0CCA94A22299F97006979B6 /* GPUOrigin3D.idl */,
+				D09AFB1722D6694E00C4538C /* GPUOutOfMemoryError.idl */,
 				D02C26922181416D00D818E4 /* GPURequestAdapterOptions.idl */,
 				D0ADB26322309D7600A22935 /* GPUSamplerDescriptor.idl */,
 				D0DE8FB8222E09E200882550 /* GPUShaderStageBit.h */,
@@ -25901,6 +25929,7 @@
 				D026F48B220A5B0B00AC5F49 /* GPUTextureDescriptor.idl */,
 				D0EACFAE219E30FD000FA75C /* GPUTextureFormat.idl */,
 				D026F483220A472F00AC5F49 /* GPUTextureUsage.idl */,
+				D09AFB0C22D55E9000C4538C /* GPUValidationError.idl */,
 				D0D8649621BA18F4003C983C /* GPUVertexAttributeDescriptor.idl */,
 				D0D8649821BA19A7003C983C /* GPUVertexBufferDescriptor.idl */,
 				D0D8649421BA173D003C983C /* GPUVertexInputDescriptor.idl */,
@@ -25947,6 +25976,9 @@
 				D00F595321701D8C000D71DB /* WebGPUDevice.cpp */,
 				D00F595221701D8C000D71DB /* WebGPUDevice.h */,
 				D00F595421701D8C000D71DB /* WebGPUDevice.idl */,
+				D09AFB0122D02E5300C4538C /* WebGPUDeviceErrorScopes.cpp */,
+				D09AFAFF22D02E5300C4538C /* WebGPUDeviceErrorScopes.h */,
+				D09AFB0322D40CC500C4538C /* WebGPUDeviceErrorScopes.idl */,
 				D0C419F02183EB31009EC1DE /* WebGPUPipelineDescriptorBase.h */,
 				D0C419F12183EB31009EC1DE /* WebGPUPipelineDescriptorBase.idl */,
 				D05A99E521C9BF2C00032B75 /* WebGPUPipelineLayout.cpp */,
@@ -28352,6 +28384,7 @@
 				A5A7AA43132F0ECC00D3A3C2 /* AutocapitalizeTypes.h in Headers */,
 				7C1843FE1C8B7283002EB973 /* Autofill.h in Headers */,
 				7C1E97281A9F9834007BF0FB /* AutoFillButtonElement.h in Headers */,
+				5CCC270922D5483A00964FA0 /* AutofillElements.h in Headers */,
 				C9D467051E60C465008195FB /* AutoplayEvent.h in Headers */,
 				45830D4E1679B4F800ACF8C3 /* AutoscrollController.h in Headers */,
 				A8CFF04E0A154F09000A4234 /* AutoTableLayout.h in Headers */,
@@ -29996,7 +30029,6 @@
 				7C7761AA1F878AA500F869FD /* JSImageBitmapRenderingContextSettings.h in Headers */,
 				A77979290D6B9E64003851B9 /* JSImageData.h in Headers */,
 				7C193C011F5E11050088F3E6 /* JSImageSmoothingQuality.h in Headers */,
-				5CCC270922D5483A00964FA0 /* AutofillElements.h in Headers */,
 				A86629D309DA2B48009633A6 /* JSInputEvent.h in Headers */,
 				9175CE5E21E281ED00DF2C28 /* JSInspectorAuditAccessibilityObject.h in Headers */,
 				9175CE5C21E281ED00DF2C28 /* JSInspectorAuditDOMObject.h in Headers */,
diff --git a/Source/WebCore/bindings/js/WebCoreBuiltinNames.h b/Source/WebCore/bindings/js/WebCoreBuiltinNames.h
index f5b5322..46f53e1 100644
--- a/Source/WebCore/bindings/js/WebCoreBuiltinNames.h
+++ b/Source/WebCore/bindings/js/WebCoreBuiltinNames.h
@@ -94,6 +94,7 @@
     macro(GPUComputePassEncoder) \
     macro(GPUComputePipeline) \
     macro(GPUDevice) \
+    macro(GPUOutOfMemoryError) \
     macro(GPUPipelineLayout) \
     macro(GPUProgrammablePassEncoder) \
     macro(GPUQueue) \
@@ -106,6 +107,7 @@
     macro(GPUTexture) \
     macro(GPUTextureUsage) \
     macro(GPUTextureView) \
+    macro(GPUValidationError) \
     macro(HTMLAttachmentElement) \
     macro(HTMLAudioElement) \
     macro(HTMLDataListElement) \
diff --git a/Source/WebCore/platform/graphics/gpu/GPUBuffer.h b/Source/WebCore/platform/graphics/gpu/GPUBuffer.h
index 42508bc..5f6f2f0 100644
--- a/Source/WebCore/platform/graphics/gpu/GPUBuffer.h
+++ b/Source/WebCore/platform/graphics/gpu/GPUBuffer.h
@@ -29,6 +29,7 @@
 
 #include "DeferrableTask.h"
 #include "GPUBufferUsage.h"
+#include "GPUObjectBase.h"
 #include <wtf/Function.h>
 #include <wtf/OptionSet.h>
 #include <wtf/Ref.h>
@@ -51,6 +52,8 @@
 
 struct GPUBufferDescriptor;
 
+enum class GPUBufferMappedOption;
+
 #if USE(METAL)
 using PlatformBuffer = MTLBuffer;
 #else
@@ -58,7 +61,7 @@
 #endif
 using PlatformBufferSmartPtr = RetainPtr<PlatformBuffer>;
 
-class GPUBuffer : public RefCounted<GPUBuffer> {
+class GPUBuffer : public GPUObjectBase {
 public:
     enum class State {
         Mapped,
@@ -68,7 +71,7 @@
 
     ~GPUBuffer();
 
-    static RefPtr<GPUBuffer> tryCreate(Ref<GPUDevice>&&, const GPUBufferDescriptor&, bool isMappedOnCreation);
+    static RefPtr<GPUBuffer> tryCreate(Ref<GPUDevice>&&, const GPUBufferDescriptor&, GPUBufferMappedOption, Ref<GPUErrorScopes>&&);
 
     PlatformBuffer *platformBuffer() const { return m_platformBuffer.get(); }
     size_t byteLength() const { return m_byteLength; }
@@ -107,8 +110,8 @@
         PendingMappingCallback(MappingCallback&&);
     };
 
-    GPUBuffer(PlatformBufferSmartPtr&&, Ref<GPUDevice>&&, size_t, OptionSet<GPUBufferUsage::Flags>, bool);
-    static bool validateBufferUsage(const GPUDevice&, OptionSet<GPUBufferUsage::Flags>);
+    GPUBuffer(PlatformBufferSmartPtr&&, Ref<GPUDevice>&&, size_t, OptionSet<GPUBufferUsage::Flags>, GPUBufferMappedOption, Ref<GPUErrorScopes>&&);
+    static bool validateBufferUsage(const GPUDevice&, OptionSet<GPUBufferUsage::Flags>, GPUErrorScopes&);
 
     JSC::ArrayBuffer* stagingBufferForRead();
     JSC::ArrayBuffer* stagingBufferForWrite();
diff --git a/Source/WebCore/platform/graphics/gpu/GPUBufferDescriptor.h b/Source/WebCore/platform/graphics/gpu/GPUBufferDescriptor.h
index ff5c5ab..32072d9 100644
--- a/Source/WebCore/platform/graphics/gpu/GPUBufferDescriptor.h
+++ b/Source/WebCore/platform/graphics/gpu/GPUBufferDescriptor.h
@@ -36,6 +36,11 @@
     GPUBufferUsageFlags usage;
 };
 
+enum class GPUBufferMappedOption {
+    IsMapped,
+    NotMapped
+};
+
 } // namespace WebCore
 
 #endif // ENABLE(WEBGPU)
diff --git a/Source/WebCore/platform/graphics/gpu/GPUComputePipeline.h b/Source/WebCore/platform/graphics/gpu/GPUComputePipeline.h
index 65367c9..46b7adc 100644
--- a/Source/WebCore/platform/graphics/gpu/GPUComputePipeline.h
+++ b/Source/WebCore/platform/graphics/gpu/GPUComputePipeline.h
@@ -27,6 +27,7 @@
 
 #if ENABLE(WEBGPU)
 
+#include "GPUObjectBase.h"
 #include "WHLSLPrepare.h"
 #include <wtf/RefCounted.h>
 #include <wtf/RefPtr.h>
@@ -43,16 +44,16 @@
 using PlatformComputePipeline = MTLComputePipelineState;
 using PlatformComputePipelineSmartPtr = RetainPtr<MTLComputePipelineState>;
 
-class GPUComputePipeline : public RefCounted<GPUComputePipeline> {
+class GPUComputePipeline : public GPUObjectBase {
 public:
-    static RefPtr<GPUComputePipeline> tryCreate(const GPUDevice&, const GPUComputePipelineDescriptor&);
+    static RefPtr<GPUComputePipeline> tryCreate(const GPUDevice&, const GPUComputePipelineDescriptor&, Ref<GPUErrorScopes>&&);
 
     const PlatformComputePipeline* platformComputePipeline() const { return m_platformComputePipeline.get(); }
 
     WHLSL::ComputeDimensions computeDimensions() const { return m_computeDimensions; }
 
 private:
-    GPUComputePipeline(PlatformComputePipelineSmartPtr&&, WHLSL::ComputeDimensions);
+    GPUComputePipeline(PlatformComputePipelineSmartPtr&&, WHLSL::ComputeDimensions, Ref<GPUErrorScopes>&&);
 
     PlatformComputePipelineSmartPtr m_platformComputePipeline;
     WHLSL::ComputeDimensions m_computeDimensions { 0, 0, 0 };
diff --git a/Source/WebCore/platform/graphics/gpu/GPUDevice.cpp b/Source/WebCore/platform/graphics/gpu/GPUDevice.cpp
index a649a60..6dbf284 100644
--- a/Source/WebCore/platform/graphics/gpu/GPUDevice.cpp
+++ b/Source/WebCore/platform/graphics/gpu/GPUDevice.cpp
@@ -35,6 +35,7 @@
 #include "GPUCommandBuffer.h"
 #include "GPUComputePipeline.h"
 #include "GPUComputePipelineDescriptor.h"
+#include "GPUErrorScopes.h"
 #include "GPUPipelineLayout.h"
 #include "GPUPipelineLayoutDescriptor.h"
 #include "GPURenderPipeline.h"
@@ -46,13 +47,14 @@
 #include "GPUSwapChainDescriptor.h"
 #include "GPUTexture.h"
 #include "GPUTextureDescriptor.h"
+#include <algorithm>
 #include <wtf/Optional.h>
 
 namespace WebCore {
 
-RefPtr<GPUBuffer> GPUDevice::tryCreateBuffer(const GPUBufferDescriptor& descriptor, bool isMappedOnCreation)
+RefPtr<GPUBuffer> GPUDevice::tryCreateBuffer(const GPUBufferDescriptor& descriptor, GPUBufferMappedOption isMapped, Ref<GPUErrorScopes>&& errorScopes)
 {
-    return GPUBuffer::tryCreate(makeRef(*this), descriptor, isMappedOnCreation);
+    return GPUBuffer::tryCreate(makeRef(*this), descriptor, isMapped, WTFMove(errorScopes));
 }
 
 RefPtr<GPUTexture> GPUDevice::tryCreateTexture(const GPUTextureDescriptor& descriptor) const
@@ -85,9 +87,9 @@
     return GPURenderPipeline::tryCreate(*this, descriptor);
 }
 
-RefPtr<GPUComputePipeline> GPUDevice::tryCreateComputePipeline(const GPUComputePipelineDescriptor& descriptor) const
+RefPtr<GPUComputePipeline> GPUDevice::tryCreateComputePipeline(const GPUComputePipelineDescriptor& descriptor, Ref<GPUErrorScopes>&& errorScopes) const
 {
-    return GPUComputePipeline::tryCreate(*this, descriptor);
+    return GPUComputePipeline::tryCreate(*this, descriptor, WTFMove(errorScopes));
 }
 
 RefPtr<GPUCommandBuffer> GPUDevice::tryCreateCommandBuffer() const
diff --git a/Source/WebCore/platform/graphics/gpu/GPUDevice.h b/Source/WebCore/platform/graphics/gpu/GPUDevice.h
index a713954..6d19da0 100644
--- a/Source/WebCore/platform/graphics/gpu/GPUDevice.h
+++ b/Source/WebCore/platform/graphics/gpu/GPUDevice.h
@@ -29,6 +29,8 @@
 
 #include "GPUQueue.h"
 #include "GPUSwapChain.h"
+#include <wtf/Function.h>
+#include <wtf/Optional.h>
 #include <wtf/RefCounted.h>
 #include <wtf/RetainPtr.h>
 #include <wtf/WeakPtr.h>
@@ -41,6 +43,7 @@
 class GPUBuffer;
 class GPUCommandBuffer;
 class GPUComputePipeline;
+class GPUErrorScopes;
 class GPUPipelineLayout;
 class GPURenderPipeline;
 class GPUSampler;
@@ -57,7 +60,9 @@
 struct GPUShaderModuleDescriptor;
 struct GPUSwapChainDescriptor;
 struct GPUTextureDescriptor;
-    
+
+enum class GPUBufferMappedOption;
+
 using PlatformDevice = MTLDevice;
 using PlatformDeviceSmartPtr = RetainPtr<MTLDevice>;
 
@@ -65,7 +70,7 @@
 public:
     static RefPtr<GPUDevice> tryCreate(const Optional<GPURequestAdapterOptions>&);
 
-    RefPtr<GPUBuffer> tryCreateBuffer(const GPUBufferDescriptor&, bool isMappedOnCreation = false);
+    RefPtr<GPUBuffer> tryCreateBuffer(const GPUBufferDescriptor&, GPUBufferMappedOption, Ref<GPUErrorScopes>&&);
     RefPtr<GPUTexture> tryCreateTexture(const GPUTextureDescriptor&) const;
     RefPtr<GPUSampler> tryCreateSampler(const GPUSamplerDescriptor&) const;
 
@@ -74,7 +79,7 @@
 
     RefPtr<GPUShaderModule> tryCreateShaderModule(const GPUShaderModuleDescriptor&) const;
     RefPtr<GPURenderPipeline> tryCreateRenderPipeline(const GPURenderPipelineDescriptor&) const;
-    RefPtr<GPUComputePipeline> tryCreateComputePipeline(const GPUComputePipelineDescriptor&) const;
+    RefPtr<GPUComputePipeline> tryCreateComputePipeline(const GPUComputePipelineDescriptor&, Ref<GPUErrorScopes>&&) const;
 
     RefPtr<GPUCommandBuffer> tryCreateCommandBuffer() const;
 
diff --git a/Source/WebCore/platform/graphics/gpu/GPUError.cpp b/Source/WebCore/platform/graphics/gpu/GPUError.cpp
new file mode 100644
index 0000000..e864a3d
--- /dev/null
+++ b/Source/WebCore/platform/graphics/gpu/GPUError.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "GPUError.h"
+
+#if ENABLE(WEBGPU)
+
+#include "GPUErrorFilter.h"
+
+namespace WebCore {
+
+Optional<GPUError> createError(GPUErrorFilter filter, const String& message)
+{
+    switch (filter) {
+    case GPUErrorFilter::OutOfMemory:
+        return GPUError(RefPtr<GPUOutOfMemoryError>(GPUOutOfMemoryError::create()));
+    case GPUErrorFilter::Validation:
+        return GPUError(RefPtr<GPUValidationError>(GPUValidationError::create(message)));
+    default:
+        ASSERT_NOT_REACHED();
+        return WTF::nullopt;
+    }
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WEBGPU)
diff --git a/Source/WebCore/platform/graphics/gpu/GPUError.h b/Source/WebCore/platform/graphics/gpu/GPUError.h
new file mode 100644
index 0000000..e67c35a
--- /dev/null
+++ b/Source/WebCore/platform/graphics/gpu/GPUError.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(WEBGPU)
+
+#include "GPUOutOfMemoryError.h"
+#include "GPUValidationError.h"
+#include <wtf/Optional.h>
+#include <wtf/RefPtr.h>
+#include <wtf/Variant.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+enum class GPUErrorFilter;
+
+using GPUError = Variant<RefPtr<GPUOutOfMemoryError>, RefPtr<GPUValidationError>>;
+
+Optional<GPUError> createError(GPUErrorFilter, const String&);
+
+} // namespace WebCore
+
+#endif
diff --git a/Source/WebCore/platform/graphics/gpu/GPUErrorFilter.h b/Source/WebCore/platform/graphics/gpu/GPUErrorFilter.h
new file mode 100644
index 0000000..d569fef
--- /dev/null
+++ b/Source/WebCore/platform/graphics/gpu/GPUErrorFilter.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(WEBGPU)
+
+namespace WebCore {
+    
+enum class GPUErrorFilter {
+    None,
+    OutOfMemory,
+    Validation,
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(WEBGPU)
diff --git a/Source/WebCore/platform/graphics/gpu/GPUErrorScopes.cpp b/Source/WebCore/platform/graphics/gpu/GPUErrorScopes.cpp
new file mode 100644
index 0000000..fa03d79
--- /dev/null
+++ b/Source/WebCore/platform/graphics/gpu/GPUErrorScopes.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "GPUErrorScopes.h"
+
+#if ENABLE(WEBGPU)
+
+namespace WebCore {
+
+void GPUErrorScopes::pushErrorScope(GPUErrorFilter filter)
+{
+    m_errorScopes.append(ErrorScope { filter, WTF::nullopt });
+}
+
+Optional<GPUError> GPUErrorScopes::popErrorScope(String& failMessage)
+{
+    if (m_errorScopes.isEmpty()) {
+        failMessage = "No error scope exists!";
+        return WTF::nullopt;
+    }
+
+    auto scope = m_errorScopes.takeLast();
+    return scope.filter == GPUErrorFilter::None ? WTF::nullopt : scope.error;
+}
+
+void GPUErrorScopes::generateError(const String& message, GPUErrorFilter filter)
+{
+    auto iterator = std::find_if(m_errorScopes.rbegin(), m_errorScopes.rend(), [filter](const ErrorScope& scope) {
+        return scope.filter == GPUErrorFilter::None || scope.filter == filter;
+    });
+
+    // FIXME: https://webkit.org/b/199676 Uncaptured errors need to be fired as GPUUncapturedErrorEvents.
+    if (iterator == m_errorScopes.rend())
+        return;
+
+    // If the scope has already captured an error, ignore this new one.
+    if (iterator->error)
+        return;
+
+    iterator->error = createError(filter, message);
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WEBGPU)
diff --git a/Source/WebCore/platform/graphics/gpu/GPUErrorScopes.h b/Source/WebCore/platform/graphics/gpu/GPUErrorScopes.h
new file mode 100644
index 0000000..e161f70
--- /dev/null
+++ b/Source/WebCore/platform/graphics/gpu/GPUErrorScopes.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(WEBGPU)
+
+#include "GPUError.h"
+#include "GPUErrorFilter.h"
+#include <wtf/Optional.h>
+#include <wtf/Ref.h>
+#include <wtf/RefCounted.h>
+#include <wtf/Vector.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class GPUErrorScopes : public RefCounted<GPUErrorScopes> {
+public:
+    static Ref<GPUErrorScopes> create() { return adoptRef(*new GPUErrorScopes); }
+
+    void pushErrorScope(GPUErrorFilter);
+    Optional<GPUError> popErrorScope(String& failMessage);
+    void generateError(const String&, GPUErrorFilter = GPUErrorFilter::Validation);
+
+private:
+    struct ErrorScope {
+        const GPUErrorFilter filter;
+        Optional<GPUError> error;
+    };
+
+    GPUErrorScopes() = default;
+
+    Vector<ErrorScope> m_errorScopes;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(WEBGPU)
diff --git a/Source/WebCore/platform/graphics/gpu/GPUObjectBase.h b/Source/WebCore/platform/graphics/gpu/GPUObjectBase.h
new file mode 100644
index 0000000..6653bcf
--- /dev/null
+++ b/Source/WebCore/platform/graphics/gpu/GPUObjectBase.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(WEBGPU)
+
+#include "GPUErrorScopes.h"
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+class GPUObjectBase : public RefCounted<GPUObjectBase> {
+public:
+    void generateError(const String& message, GPUErrorFilter filter = GPUErrorFilter::Validation)
+    {
+        m_errorScopes->generateError(message, filter);
+    }
+
+protected:
+    GPUObjectBase(Ref<GPUErrorScopes>&& reporter)
+        : m_errorScopes(WTFMove(reporter)) { }
+
+private:
+    Ref<GPUErrorScopes> m_errorScopes;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(WEBGPU)
diff --git a/Source/WebCore/platform/graphics/gpu/GPUOutOfMemoryError.h b/Source/WebCore/platform/graphics/gpu/GPUOutOfMemoryError.h
new file mode 100644
index 0000000..9f420e9
--- /dev/null
+++ b/Source/WebCore/platform/graphics/gpu/GPUOutOfMemoryError.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(WEBGPU)
+
+#include <wtf/Ref.h>
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+class GPUOutOfMemoryError : public RefCounted<GPUOutOfMemoryError> {
+public:
+    static Ref<GPUOutOfMemoryError> create() { return adoptRef(*new GPUOutOfMemoryError); }
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(WEBGPU)
diff --git a/Source/WebCore/platform/graphics/gpu/GPUValidationError.cpp b/Source/WebCore/platform/graphics/gpu/GPUValidationError.cpp
new file mode 100644
index 0000000..397e545
--- /dev/null
+++ b/Source/WebCore/platform/graphics/gpu/GPUValidationError.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "GPUValidationError.h"
+
+#if ENABLE(WEBGPU)
+
+namespace WebCore {
+
+Ref<GPUValidationError> GPUValidationError::create(const String& message)
+{
+    return adoptRef(*new GPUValidationError(message));
+}
+
+GPUValidationError::GPUValidationError(const String& message)
+    : m_message(message)
+{
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WEBGPU)
diff --git a/Source/WebCore/platform/graphics/gpu/GPUValidationError.h b/Source/WebCore/platform/graphics/gpu/GPUValidationError.h
new file mode 100644
index 0000000..7225ac2
--- /dev/null
+++ b/Source/WebCore/platform/graphics/gpu/GPUValidationError.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(WEBGPU)
+
+#include <wtf/Ref.h>
+#include <wtf/RefCounted.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class GPUValidationError : public RefCounted<GPUValidationError> {
+public:
+    static Ref<GPUValidationError> create(const String& message);
+
+    String message() const { return m_message; }
+
+private:
+    explicit GPUValidationError(const String& message);
+
+    String m_message;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(WEBGPU)
diff --git a/Source/WebCore/platform/graphics/gpu/cocoa/GPUBufferMetal.mm b/Source/WebCore/platform/graphics/gpu/cocoa/GPUBufferMetal.mm
index 59a07ff..5cbc648 100644
--- a/Source/WebCore/platform/graphics/gpu/cocoa/GPUBufferMetal.mm
+++ b/Source/WebCore/platform/graphics/gpu/cocoa/GPUBufferMetal.mm
@@ -42,7 +42,7 @@
 static constexpr auto readOnlyFlags = OptionSet<GPUBufferUsage::Flags> { GPUBufferUsage::Flags::Index, GPUBufferUsage::Flags::Vertex, GPUBufferUsage::Flags::Uniform, GPUBufferUsage::Flags::TransferSource };
 
 
-bool GPUBuffer::validateBufferUsage(const GPUDevice& device, OptionSet<GPUBufferUsage::Flags> usage)
+bool GPUBuffer::validateBufferUsage(const GPUDevice& device, OptionSet<GPUBufferUsage::Flags> usage, GPUErrorScopes& errorScopes)
 {
     if (!device.platformDevice()) {
         LOG(WebGPU, "GPUBuffer::tryCreate(): Invalid GPUDevice!");
@@ -50,7 +50,7 @@
     }
 
     if (usage.containsAll({ GPUBufferUsage::Flags::MapWrite, GPUBufferUsage::Flags::MapRead })) {
-        LOG(WebGPU, "GPUBuffer::tryCreate(): Buffer cannot have both MAP_READ and MAP_WRITE usage!");
+        errorScopes.generateError("GPUBuffer::tryCreate(): Buffer cannot have both MAP_READ and MAP_WRITE usage!");
         return false;
     }
 
@@ -62,23 +62,23 @@
     return true;
 }
 
-RefPtr<GPUBuffer> GPUBuffer::tryCreate(Ref<GPUDevice>&& device, const GPUBufferDescriptor& descriptor, bool isMappedOnCreation)
+RefPtr<GPUBuffer> GPUBuffer::tryCreate(Ref<GPUDevice>&& device, const GPUBufferDescriptor& descriptor, GPUBufferMappedOption isMapped, Ref<GPUErrorScopes>&& errorScopes)
 {
     // MTLBuffer size (NSUInteger) is 32 bits on some platforms.
     NSUInteger size = 0;
     if (!WTF::convertSafely(descriptor.size, size)) {
-        LOG(WebGPU, "GPUBuffer::tryCreate(): Buffer size is too large!");
+        errorScopes->generateError("", GPUErrorFilter::OutOfMemory);
         return nullptr;
     }
 
     auto usage = OptionSet<GPUBufferUsage::Flags>::fromRaw(descriptor.usage);
-    if (!validateBufferUsage(device.get(), usage))
+    if (!validateBufferUsage(device.get(), usage, errorScopes))
         return nullptr;
 
 #if PLATFORM(MAC)
     // copyBufferToBuffer calls require 4-byte alignment. "Unmapping" a mapped-on-creation GPUBuffer
     // that is otherwise unmappable requires such a copy to upload data.
-    if (isMappedOnCreation
+    if (isMapped == GPUBufferMappedOption::IsMapped
         && !usage.containsAny({ GPUBufferUsage::Flags::MapWrite, GPUBufferUsage::Flags::MapRead })
         && descriptor.size % 4) {
         LOG(WebGPU, "GPUBuffer::tryCreate(): Data must be aligned to a multiple of 4 bytes!");
@@ -102,19 +102,20 @@
     END_BLOCK_OBJC_EXCEPTIONS;
 
     if (!mtlBuffer) {
-        LOG(WebGPU, "GPUBuffer::tryCreate(): Unable to create MTLBuffer!");
+        errorScopes->generateError("", GPUErrorFilter::OutOfMemory);
         return nullptr;
     }
 
-    return adoptRef(*new GPUBuffer(WTFMove(mtlBuffer), WTFMove(device), size, usage, isMappedOnCreation));
+    return adoptRef(*new GPUBuffer(WTFMove(mtlBuffer), WTFMove(device), size, usage, isMapped, WTFMove(errorScopes)));
 }
 
-GPUBuffer::GPUBuffer(RetainPtr<MTLBuffer>&& buffer, Ref<GPUDevice>&& device, size_t size, OptionSet<GPUBufferUsage::Flags> usage, bool isMapped)
-    : m_platformBuffer(WTFMove(buffer))
+GPUBuffer::GPUBuffer(RetainPtr<MTLBuffer>&& buffer, Ref<GPUDevice>&& device, size_t size, OptionSet<GPUBufferUsage::Flags> usage, GPUBufferMappedOption isMapped, Ref<GPUErrorScopes>&& errorScopes)
+    : GPUObjectBase(WTFMove(errorScopes))
+    , m_platformBuffer(WTFMove(buffer))
     , m_device(WTFMove(device))
     , m_byteLength(size)
     , m_usage(usage)
-    , m_isMappedFromCreation(isMapped)
+    , m_isMappedFromCreation(isMapped == GPUBufferMappedOption::IsMapped)
 {
 }
 
diff --git a/Source/WebCore/platform/graphics/gpu/cocoa/GPUComputePipelineMetal.mm b/Source/WebCore/platform/graphics/gpu/cocoa/GPUComputePipelineMetal.mm
index e81f7ca..0884f27 100644
--- a/Source/WebCore/platform/graphics/gpu/cocoa/GPUComputePipelineMetal.mm
+++ b/Source/WebCore/platform/graphics/gpu/cocoa/GPUComputePipelineMetal.mm
@@ -31,45 +31,37 @@
 #import "GPUComputePipelineDescriptor.h"
 #import "GPUDevice.h"
 #import "GPUPipelineMetalConvertLayout.h"
-#import "Logging.h"
 #import "WHLSLPrepare.h"
 #import <Metal/Metal.h>
 #import <wtf/BlockObjCExceptions.h>
+#import <wtf/text/StringConcatenate.h>
 
 namespace WebCore {
 
-static bool trySetMetalFunctions(const char* const functionName, MTLLibrary *computeMetalLibrary, MTLComputePipelineDescriptor *mtlDescriptor, const String& computeEntryPointName)
+static bool trySetMetalFunctions(const char* const functionName, MTLLibrary *computeMetalLibrary, MTLComputePipelineDescriptor *mtlDescriptor, const String& computeEntryPointName, GPUErrorScopes& errorScopes)
 {
-#if LOG_DISABLED
-    UNUSED_PARAM(functionName);
-#endif
-
     BEGIN_BLOCK_OBJC_EXCEPTIONS;
 
     if (!computeMetalLibrary) {
-        LOG(WebGPU, "%s: MTLLibrary for compute stage does not exist!", functionName);
+        errorScopes.generateError(makeString(functionName, ": MTLLibrary for compute stage does not exist!"));
         return false;
     }
 
     auto function = adoptNS([computeMetalLibrary newFunctionWithName:computeEntryPointName]);
     if (!function) {
-        LOG(WebGPU, "%s: Cannot create compute MTLFunction \"%s\"!", functionName, computeEntryPointName.utf8().data());
+        errorScopes.generateError(makeString(functionName, ": Cannot create compute MTLFunction \"", computeEntryPointName, "\"!"));
         return false;
     }
 
     [mtlDescriptor setComputeFunction:function.get()];
-    return true;
 
     END_BLOCK_OBJC_EXCEPTIONS;
 
-    return false;
+    return true;
 }
 
-static Optional<WHLSL::ComputeDimensions> trySetFunctions(const char* const functionName, const GPUPipelineStageDescriptor& computeStage, const GPUDevice& device, MTLComputePipelineDescriptor* mtlDescriptor, Optional<WHLSL::ComputePipelineDescriptor>& whlslDescriptor)
+static Optional<WHLSL::ComputeDimensions> trySetFunctions(const char* const functionName, const GPUPipelineStageDescriptor& computeStage, const GPUDevice& device, MTLComputePipelineDescriptor* mtlDescriptor, Optional<WHLSL::ComputePipelineDescriptor>& whlslDescriptor, GPUErrorScopes& errorScopes)
 {
-#if LOG_DISABLED
-    UNUSED_PARAM(functionName);
-#endif
     RetainPtr<MTLLibrary> computeLibrary;
     String computeEntryPoint;
 
@@ -83,8 +75,11 @@
         whlslDescriptor->entryPointName = computeStage.entryPoint;
 
         auto whlslCompileResult = WHLSL::prepare(whlslSource, *whlslDescriptor);
-        if (!whlslCompileResult)
+        if (!whlslCompileResult) {
+            errorScopes.generateError(makeString(functionName, ": WHLSL compilation failed!"));
             return WTF::nullopt;
+        }
+
         computeDimensions = whlslCompileResult->computeDimensions;
 
         NSError *error = nil;
@@ -105,8 +100,9 @@
         computeEntryPoint = computeStage.entryPoint;
     }
 
-    if (trySetMetalFunctions(functionName, computeLibrary.get(), mtlDescriptor, computeEntryPoint))
+    if (trySetMetalFunctions(functionName, computeLibrary.get(), mtlDescriptor, computeEntryPoint, errorScopes))
         return computeDimensions;
+
     return WTF::nullopt;
 }
 
@@ -114,18 +110,17 @@
     RetainPtr<MTLComputePipelineDescriptor> pipelineDescriptor;
     WHLSL::ComputeDimensions computeDimensions;
 };
-static Optional<ConvertResult> convertComputePipelineDescriptor(const char* const functionName, const GPUComputePipelineDescriptor& descriptor, const GPUDevice& device)
+
+static Optional<ConvertResult> convertComputePipelineDescriptor(const char* const functionName, const GPUComputePipelineDescriptor& descriptor, const GPUDevice& device, GPUErrorScopes& errorScopes)
 {
     RetainPtr<MTLComputePipelineDescriptor> mtlDescriptor;
 
     BEGIN_BLOCK_OBJC_EXCEPTIONS;
-
     mtlDescriptor = adoptNS([MTLComputePipelineDescriptor new]);
-
     END_BLOCK_OBJC_EXCEPTIONS;
 
     if (!mtlDescriptor) {
-        LOG(WebGPU, "%s: Error creating MTLDescriptor!", functionName);
+        errorScopes.generateError(makeString(functionName, ": Error creating MTLDescriptor!"));
         return WTF::nullopt;
     }
 
@@ -141,12 +136,12 @@
         if (auto layout = convertLayout(*descriptor.layout))
             whlslDescriptor->layout = WTFMove(*layout);
         else {
-            LOG(WebGPU, "%s: Error converting GPUPipelineLayout!", functionName);
+            errorScopes.generateError(makeString(functionName, ": Error converting GPUPipelineLayout!"));
             return WTF::nullopt;
         }
     }
 
-    if (auto computeDimensions = trySetFunctions(functionName, computeStage, device, mtlDescriptor.get(), whlslDescriptor))
+    if (auto computeDimensions = trySetFunctions(functionName, computeStage, device, mtlDescriptor.get(), whlslDescriptor, errorScopes))
         return {{ mtlDescriptor, *computeDimensions }};
 
     return WTF::nullopt;
@@ -156,14 +151,15 @@
     RetainPtr<MTLComputePipelineState> pipelineState;
     WHLSL::ComputeDimensions computeDimensions;
 };
-static Optional<CreateResult> tryCreateMTLComputePipelineState(const char* const functionName, const GPUDevice& device, const GPUComputePipelineDescriptor& descriptor)
+
+static Optional<CreateResult> tryCreateMTLComputePipelineState(const char* const functionName, const GPUDevice& device, const GPUComputePipelineDescriptor& descriptor, GPUErrorScopes& errorScopes)
 {
     if (!device.platformDevice()) {
-        LOG(WebGPU, "GPUComputePipeline::tryCreate(): Invalid GPUDevice!");
+        errorScopes.generateError(makeString(functionName, ": Invalid GPUDevice!"));
         return WTF::nullopt;
     }
 
-    auto convertResult = convertComputePipelineDescriptor(functionName, descriptor, device);
+    auto convertResult = convertComputePipelineDescriptor(functionName, descriptor, device, errorScopes);
     if (!convertResult)
         return WTF::nullopt;
     ASSERT(convertResult->pipelineDescriptor);
@@ -176,7 +172,7 @@
     NSError *error = nil;
     pipeline = adoptNS([device.platformDevice() newComputePipelineStateWithDescriptor:mtlDescriptor.get() options:MTLPipelineOptionNone reflection:nil error:&error]);
     if (!pipeline) {
-        LOG(WebGPU, "GPUComputePipeline::tryCreate(): %s!", error ? error.localizedDescription.UTF8String : "Unable to create MTLComputePipelineState!");
+        errorScopes.generateError(makeString(functionName, ": ", (error ? error.localizedDescription.UTF8String : "Unable to create MTLComputePipelineState!")));
         return WTF::nullopt;
     }
 
@@ -185,19 +181,20 @@
     return {{ pipeline, convertResult->computeDimensions }};
 }
 
-RefPtr<GPUComputePipeline> GPUComputePipeline::tryCreate(const GPUDevice& device, const GPUComputePipelineDescriptor& descriptor)
+RefPtr<GPUComputePipeline> GPUComputePipeline::tryCreate(const GPUDevice& device, const GPUComputePipelineDescriptor& descriptor, Ref<GPUErrorScopes>&& errorScopes)
 {
-    const char* const functionName = "GPURenderPipeline::create()";
+    const char* const functionName = "GPUComputePipeline::tryCreate()";
 
-    auto createResult = tryCreateMTLComputePipelineState(functionName, device, descriptor);
+    auto createResult = tryCreateMTLComputePipelineState(functionName, device, descriptor, errorScopes);
     if (!createResult)
         return nullptr;
 
-    return adoptRef(new GPUComputePipeline(WTFMove(createResult->pipelineState), createResult->computeDimensions));
+    return adoptRef(new GPUComputePipeline(WTFMove(createResult->pipelineState), createResult->computeDimensions, WTFMove(errorScopes)));
 }
 
-GPUComputePipeline::GPUComputePipeline(RetainPtr<MTLComputePipelineState>&& pipeline, WHLSL::ComputeDimensions computeDimensions)
-    : m_platformComputePipeline(WTFMove(pipeline))
+GPUComputePipeline::GPUComputePipeline(RetainPtr<MTLComputePipelineState>&& pipeline, WHLSL::ComputeDimensions computeDimensions, Ref<GPUErrorScopes>&& errorScopes)
+    : GPUObjectBase(WTFMove(errorScopes))
+    , m_platformComputePipeline(WTFMove(pipeline))
     , m_computeDimensions(computeDimensions)
 {
 }
diff --git a/Source/WebCore/platform/graphics/gpu/cocoa/GPUQueueMetal.mm b/Source/WebCore/platform/graphics/gpu/cocoa/GPUQueueMetal.mm
index a9ea3cb..174d864 100644
--- a/Source/WebCore/platform/graphics/gpu/cocoa/GPUQueueMetal.mm
+++ b/Source/WebCore/platform/graphics/gpu/cocoa/GPUQueueMetal.mm
@@ -96,7 +96,7 @@
         END_BLOCK_OBJC_EXCEPTIONS;
     }
 
-    if (m_presentTask.hasPendingTask() || !m_device->swapChain())
+    if (m_presentTask.hasPendingTask() || !m_device || !m_device->swapChain())
         return;
 
     // If a GPUSwapChain exists, ensure that a present is scheduled after all command buffers.