diff --git a/test/integration/scratch-tests.js b/test/integration/scratch-tests.js
index dbc3d2ea..d2c7f8fd 100644
--- a/test/integration/scratch-tests.js
+++ b/test/integration/scratch-tests.js
@@ -5,51 +5,12 @@ const path = require('path');
 const fs = require('fs');
 const chromeless = new Chromeless();
 
+const allGpuModes = ['ForceCPU', 'ForceGPU', 'Automatic'];
+
 const indexHTML = path.resolve(__dirname, 'index.html');
 const testDir = (...args) => path.resolve(__dirname, 'scratch-tests', ...args);
 
-const testFile = file => test(file, async t => {
-    // start each test by going to the index.html, and loading the scratch file
-    const says = await chromeless.goto(`file://${indexHTML}`)
-        .setFileInput('#file', testDir(file))
-        // the index.html handler for file input will add a #loaded element when it
-        // finishes.
-        .wait('#loaded')
-        .evaluate(() => {
-            // This function is run INSIDE the integration chrome browser via some
-            // injection and .toString() magic.  We can return some "simple data"
-            // back across as a promise, so we will just log all the says that happen
-            // for parsing after.
-
-            // this becomes the `says` in the outer scope
-            const messages = [];
-            const TIMEOUT = 5000;
-
-            vm.runtime.on('SAY', (_, __, message) => {
-                messages.push(message);
-            });
-
-            vm.greenFlag();
-            const startTime = Date.now();
-
-            return Promise.resolve()
-                .then(async () => {
-                    // waiting for all threads to complete, then we return
-                    while (vm.runtime.threads.some(thread => vm.runtime.isActiveThread(thread))) {
-                        if ((Date.now() - startTime) >= TIMEOUT) {
-                            // if we push the message after end, the failure from tap is not very useful:
-                            // "not ok test after end() was called"
-                            messages.unshift(`fail Threads still running after ${TIMEOUT}ms`);
-                            break;
-                        }
-
-                        await new Promise(resolve => setTimeout(resolve, 50));
-                    }
-
-                    return messages;
-                });
-        });
-
+const checkOneGpuMode = (t, says) => {
     // Map string messages to tap reporting methods. This will be used
     // with events from scratch's runtime emitted on block instructions.
     let didPlan = false;
@@ -99,7 +60,57 @@ const testFile = file => test(file, async t => {
         t.fail('did not say "end"');
         t.end();
     }
-});
+};
+
+const testFile = async file => {
+    // start each test by going to the index.html, and loading the scratch file
+    const says = await chromeless.goto(`file://${indexHTML}`)
+        .setFileInput('#file', testDir(file))
+        // the index.html handler for file input will add a #loaded element when it
+        // finishes.
+        .wait('#loaded')
+        .evaluate(async useGpuModes => {
+            // This function is run INSIDE the integration chrome browser via some
+            // injection and .toString() magic.  We can return some "simple data"
+            // back across as a promise, so we will just log all the says that happen
+            // for parsing after.
+
+            // this becomes the `says` in the outer scope
+            const allMessages = {};
+            const TIMEOUT = 5000;
+
+            vm.runtime.on('SAY', (_, __, message) => {
+                const messages = allMessages[vm.renderer._useGpuMode];
+                messages.push(message);
+            });
+
+            for (const useGpuMode of useGpuModes) {
+                const messages = allMessages[useGpuMode] = [];
+
+                vm.renderer.setUseGpuMode(useGpuMode);
+                vm.greenFlag();
+                const startTime = Date.now();
+
+                // wait for all threads to complete before moving on to the next mode
+                while (vm.runtime.threads.some(thread => vm.runtime.isActiveThread(thread))) {
+                    if ((Date.now() - startTime) >= TIMEOUT) {
+                        // if we push the message after end, the failure from tap is not very useful:
+                        // "not ok test after end() was called"
+                        messages.unshift(`fail Threads still running after ${TIMEOUT}ms`);
+                        break;
+                    }
+
+                    await new Promise(resolve => setTimeout(resolve, 50));
+                }
+            }
+
+            return allMessages;
+        }, allGpuModes);
+
+    for (const gpuMode of allGpuModes) {
+        test(`File: ${file}, GPU Mode: ${gpuMode}`, t => checkOneGpuMode(t, says[gpuMode]));
+    }
+};
 
 const testBubbles = () => test('bubble snapshot', async t => {
     const bubbleSvg = await chromeless.goto(`file://${indexHTML}`)