Split NXT helpers from example/Utils into src/utils

This will make it possible to use them in the test suites
diff --git a/examples/Animometer.cpp b/examples/Animometer.cpp
index 0ea4457..601994d 100644
--- a/examples/Animometer.cpp
+++ b/examples/Animometer.cpp
@@ -14,6 +14,8 @@
 
 #include "Utils.h"
 
+#include "utils/NXTHelpers.h"
+
 #include <cstdlib>
 #include <cstdio>
 #include <vector>
@@ -45,7 +47,7 @@
 
     queue = device.CreateQueueBuilder().GetResult();
 
-    nxt::ShaderModule vsModule = CreateShaderModule(device, nxt::ShaderStage::Vertex, R"(
+    nxt::ShaderModule vsModule = utils::CreateShaderModule(device, nxt::ShaderStage::Vertex, R"(
         #version 450
 
         layout(push_constant) uniform ConstantsBlock {
@@ -93,7 +95,7 @@
         })"
     );
 
-    nxt::ShaderModule fsModule = CreateShaderModule(device, nxt::ShaderStage::Fragment, R"(
+    nxt::ShaderModule fsModule = utils::CreateShaderModule(device, nxt::ShaderStage::Fragment, R"(
         #version 450
         out vec4 fragColor;
         layout(location = 0) in vec4 v_color;
@@ -102,7 +104,7 @@
         })"
     );
 
-    CreateDefaultRenderPass(device, &renderpass, &framebuffer);
+    utils::CreateDefaultRenderPass(device, &renderpass, &framebuffer);
     pipeline = device.CreatePipelineBuilder()
         .SetSubpass(renderpass, 0)
         .SetStage(nxt::ShaderStage::Vertex, vsModule, "main")
diff --git a/examples/CHelloTriangle.cpp b/examples/CHelloTriangle.cpp
index 479fe91..1a2dfe6 100644
--- a/examples/CHelloTriangle.cpp
+++ b/examples/CHelloTriangle.cpp
@@ -14,6 +14,8 @@
 
 #include "Utils.h"
 
+#include "utils/NXTHelpers.h"
+
 nxtDevice device;
 nxtQueue queue;
 nxtPipeline pipeline;
@@ -35,7 +37,7 @@
         "void main() {\n"
         "   gl_Position = vec4(pos[gl_VertexIndex], 0.0, 1.0);\n"
         "}\n";
-    nxtShaderModule vsModule = CreateShaderModule(nxt::Device(device), nxt::ShaderStage::Vertex, vs).Release();
+    nxtShaderModule vsModule = utils::CreateShaderModule(nxt::Device(device), nxt::ShaderStage::Vertex, vs).Release();
 
     const char* fs =
         "#version 450\n"
@@ -43,7 +45,7 @@
         "void main() {\n"
         "   fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
         "}\n";
-    nxtShaderModule fsModule = CreateShaderModule(device, nxt::ShaderStage::Fragment, fs).Release();
+    nxtShaderModule fsModule = utils::CreateShaderModule(device, nxt::ShaderStage::Fragment, fs).Release();
 
     {
         nxtRenderPassBuilder builder = nxtDeviceCreateRenderPassBuilder(device);
diff --git a/examples/ComputeBoids.cpp b/examples/ComputeBoids.cpp
index a31cb95..61e3733 100644
--- a/examples/ComputeBoids.cpp
+++ b/examples/ComputeBoids.cpp
@@ -14,6 +14,8 @@
 
 #include "Utils.h"
 
+#include "utils/NXTHelpers.h"
+
 #include <array>
 #include <cstring>
 #include <random>
@@ -62,10 +64,10 @@
         {0.01, -0.02},
         {0.00, 0.02},
     };
-    modelBuffer = CreateFrozenBufferFromData(device, model, sizeof(model), nxt::BufferUsageBit::Vertex);
+    modelBuffer = utils::CreateFrozenBufferFromData(device, model, sizeof(model), nxt::BufferUsageBit::Vertex);
 
     SimParams params = { 0.04, 0.1, 0.025, 0.025, 0.02, 0.05, 0.005, kNumParticles };
-    updateParams = CreateFrozenBufferFromData(device, &params, sizeof(params), nxt::BufferUsageBit::Uniform);
+    updateParams = utils::CreateFrozenBufferFromData(device, &params, sizeof(params), nxt::BufferUsageBit::Uniform);
 
     std::vector<Particle> initialParticles(kNumParticles);
     {
@@ -92,7 +94,7 @@
 }
 
 void initRender() {
-    nxt::ShaderModule vsModule = CreateShaderModule(device, nxt::ShaderStage::Vertex, R"(
+    nxt::ShaderModule vsModule = utils::CreateShaderModule(device, nxt::ShaderStage::Vertex, R"(
         #version 450
         layout(location = 0) in vec2 a_particlePos;
         layout(location = 1) in vec2 a_particleVel;
@@ -105,7 +107,7 @@
         }
     )");
 
-    nxt::ShaderModule fsModule = CreateShaderModule(device, nxt::ShaderStage::Fragment, R"(
+    nxt::ShaderModule fsModule = utils::CreateShaderModule(device, nxt::ShaderStage::Fragment, R"(
         #version 450
         out vec4 fragColor;
         void main() {
@@ -121,7 +123,7 @@
         .SetInput(1, sizeof(glm::vec2), nxt::InputStepMode::Vertex)
         .GetResult();
 
-    CreateDefaultRenderPass(device, &renderpass, &framebuffer);
+    utils::CreateDefaultRenderPass(device, &renderpass, &framebuffer);
     renderPipeline = device.CreatePipelineBuilder()
         .SetSubpass(renderpass, 0)
         .SetStage(nxt::ShaderStage::Vertex, vsModule, "main")
@@ -131,7 +133,7 @@
 }
 
 void initSim() {
-    nxt::ShaderModule module = CreateShaderModule(device, nxt::ShaderStage::Compute, R"(
+    nxt::ShaderModule module = utils::CreateShaderModule(device, nxt::ShaderStage::Compute, R"(
         #version 450
 
         struct Particle {
diff --git a/examples/HelloCompute.cpp b/examples/HelloCompute.cpp
index 440bd4e..11df312 100644
--- a/examples/HelloCompute.cpp
+++ b/examples/HelloCompute.cpp
@@ -14,6 +14,8 @@
 
 #include "Utils.h"
 
+#include "utils/NXTHelpers.h"
+
 #include <string.h>
 
 nxt::Device device;
@@ -45,7 +47,7 @@
         .GetResult();
 
     {
-        nxt::ShaderModule module = CreateShaderModule(device, nxt::ShaderStage::Compute, R"(
+        nxt::ShaderModule module = utils::CreateShaderModule(device, nxt::ShaderStage::Compute, R"(
             #version 450
             layout(set = 0, binding = 0) buffer myBlock {
                 int a;
@@ -78,7 +80,7 @@
     }
 
     {
-        nxt::ShaderModule vsModule = CreateShaderModule(device, nxt::ShaderStage::Vertex, R"(
+        nxt::ShaderModule vsModule = utils::CreateShaderModule(device, nxt::ShaderStage::Vertex, R"(
             #version 450
             const vec2 pos[3] = vec2[3](vec2(0.0f, 0.5f), vec2(-0.5f, -0.5f), vec2(0.5f, -0.5f));
             void main() {
@@ -86,7 +88,7 @@
             })"
         );
 
-        nxt::ShaderModule fsModule = CreateShaderModule(device, nxt::ShaderStage::Fragment, R"(
+        nxt::ShaderModule fsModule = utils::CreateShaderModule(device, nxt::ShaderStage::Fragment, R"(
             #version 450
             layout(set = 0, binding = 0) uniform myBlock {
                 int a;
@@ -106,7 +108,7 @@
             .SetBindGroupLayout(0, bgl)
             .GetResult();
 
-        CreateDefaultRenderPass(device, &renderpass, &framebuffer);
+        utils::CreateDefaultRenderPass(device, &renderpass, &framebuffer);
         renderPipeline = device.CreatePipelineBuilder()
             .SetSubpass(renderpass, 0)
             .SetLayout(pl)
diff --git a/examples/HelloDepthStencil.cpp b/examples/HelloDepthStencil.cpp
index 0d66762..7f83a4c 100644
--- a/examples/HelloDepthStencil.cpp
+++ b/examples/HelloDepthStencil.cpp
@@ -14,6 +14,8 @@
 
 #include "Utils.h"
 
+#include "utils/NXTHelpers.h"
+
 #include <vector>
 #include <glm/glm/glm.hpp>
 #include <glm/glm/gtc/matrix_transform.hpp>
@@ -58,7 +60,7 @@
         20, 21, 22,
         20, 22, 23
     };
-    indexBuffer = CreateFrozenBufferFromData(device, indexData, sizeof(indexData), nxt::BufferUsageBit::Index);
+    indexBuffer = utils::CreateFrozenBufferFromData(device, indexData, sizeof(indexData), nxt::BufferUsageBit::Index);
 
     static const float vertexData[6 * 4 * 6] = {
         -1.0, -1.0,  1.0,    1.0, 0.0, 0.0,
@@ -91,7 +93,7 @@
         -1.0,  1.0,  1.0,    1.0, 1.0, 1.0,
         -1.0,  1.0, -1.0,    1.0, 1.0, 1.0
     };
-    vertexBuffer = CreateFrozenBufferFromData(device, vertexData, sizeof(vertexData), nxt::BufferUsageBit::Vertex);
+    vertexBuffer = utils::CreateFrozenBufferFromData(device, vertexData, sizeof(vertexData), nxt::BufferUsageBit::Vertex);
 
     static const float planeData[6 * 4] = {
         -2.0, -1.0, -2.0,    0.5, 0.5, 0.5,
@@ -99,7 +101,7 @@
         2.0, -1.0,  2.0,    0.5, 0.5, 0.5,
         -2.0, -1.0,  2.0,    0.5, 0.5, 0.5,
     };
-    planeBuffer = CreateFrozenBufferFromData(device, planeData, sizeof(planeData), nxt::BufferUsageBit::Vertex);
+    planeBuffer = utils::CreateFrozenBufferFromData(device, planeData, sizeof(planeData), nxt::BufferUsageBit::Vertex);
 }
 
 struct CameraData {
@@ -114,7 +116,7 @@
 
     initBuffers();
 
-    nxt::ShaderModule vsModule = CreateShaderModule(device, nxt::ShaderStage::Vertex, R"(
+    nxt::ShaderModule vsModule = utils::CreateShaderModule(device, nxt::ShaderStage::Vertex, R"(
         #version 450
         layout(set = 0, binding = 0) uniform cameraData {
             mat4 view;
@@ -132,7 +134,7 @@
         })"
     );
 
-    nxt::ShaderModule fsModule = CreateShaderModule(device, nxt::ShaderStage::Fragment, R"(
+    nxt::ShaderModule fsModule = utils::CreateShaderModule(device, nxt::ShaderStage::Fragment, R"(
         #version 450
         layout(location = 2) in vec3 f_col;
         out vec4 fragColor;
@@ -141,7 +143,7 @@
         })"
     );
 
-    nxt::ShaderModule fsReflectionModule = CreateShaderModule(device, nxt::ShaderStage::Fragment, R"(
+    nxt::ShaderModule fsReflectionModule = utils::CreateShaderModule(device, nxt::ShaderStage::Fragment, R"(
         #version 450
         layout(location = 2) in vec3 f_col;
         out vec4 fragColor;
@@ -171,10 +173,10 @@
         .GetResult();
 
     glm::mat4 transform(1.0);
-    transformBuffer[0] = CreateFrozenBufferFromData(device, &transform, sizeof(glm::mat4), nxt::BufferUsageBit::Uniform);
+    transformBuffer[0] = utils::CreateFrozenBufferFromData(device, &transform, sizeof(glm::mat4), nxt::BufferUsageBit::Uniform);
 
     transform = glm::translate(transform, glm::vec3(0.f, -2.f, 0.f));
-    transformBuffer[1] = CreateFrozenBufferFromData(device, &transform, sizeof(glm::mat4), nxt::BufferUsageBit::Uniform);
+    transformBuffer[1] = utils::CreateFrozenBufferFromData(device, &transform, sizeof(glm::mat4), nxt::BufferUsageBit::Uniform);
 
     nxt::BufferView cameraBufferView = cameraBuffer.CreateBufferViewBuilder()
         .SetExtent(0, sizeof(CameraData))
@@ -203,7 +205,7 @@
         .SetBufferViews(1, 1, &transformBufferView[1])
         .GetResult();
 
-    CreateDefaultRenderPass(device, &renderpass, &framebuffer);
+    utils::CreateDefaultRenderPass(device, &renderpass, &framebuffer);
 
     auto depthStencilState = device.CreateDepthStencilStateBuilder()
         .SetDepthCompareFunction(nxt::CompareFunction::Less)
diff --git a/examples/HelloIndices.cpp b/examples/HelloIndices.cpp
index c20269f..bb127bf 100644
--- a/examples/HelloIndices.cpp
+++ b/examples/HelloIndices.cpp
@@ -14,6 +14,8 @@
 
 #include "Utils.h"
 
+#include "utils/NXTHelpers.h"
+
 #include <vector>
 
 nxt::Device device;
@@ -30,14 +32,14 @@
     static const uint32_t indexData[3] = {
         0, 1, 2,
     };
-    indexBuffer = CreateFrozenBufferFromData(device, indexData, sizeof(indexData), nxt::BufferUsageBit::Index);
+    indexBuffer = utils::CreateFrozenBufferFromData(device, indexData, sizeof(indexData), nxt::BufferUsageBit::Index);
 
     static const float vertexData[12] = {
         0.0f, 0.5f, 0.0f, 1.0f,
         -0.5f, -0.5f, 0.0f, 1.0f,
         0.5f, -0.5f, 0.0f, 1.0f,
     };
-    vertexBuffer = CreateFrozenBufferFromData(device, vertexData, sizeof(vertexData), nxt::BufferUsageBit::Vertex);
+    vertexBuffer = utils::CreateFrozenBufferFromData(device, vertexData, sizeof(vertexData), nxt::BufferUsageBit::Vertex);
 }
 
 void init() {
@@ -47,7 +49,7 @@
 
     initBuffers();
 
-    nxt::ShaderModule vsModule = CreateShaderModule(device, nxt::ShaderStage::Vertex, R"(
+    nxt::ShaderModule vsModule = utils::CreateShaderModule(device, nxt::ShaderStage::Vertex, R"(
         #version 450
         layout(location = 0) in vec4 pos;
         void main() {
@@ -55,7 +57,7 @@
         })"
     );
 
-    nxt::ShaderModule fsModule = CreateShaderModule(device, nxt::ShaderStage::Fragment, R"(
+    nxt::ShaderModule fsModule = utils::CreateShaderModule(device, nxt::ShaderStage::Fragment, R"(
         #version 450
         out vec4 fragColor;
         void main() {
@@ -68,7 +70,7 @@
         .SetInput(0, 4 * sizeof(float), nxt::InputStepMode::Vertex)
         .GetResult();
 
-    CreateDefaultRenderPass(device, &renderpass, &framebuffer);
+    utils::CreateDefaultRenderPass(device, &renderpass, &framebuffer);
     pipeline = device.CreatePipelineBuilder()
         .SetSubpass(renderpass, 0)
         .SetStage(nxt::ShaderStage::Vertex, vsModule, "main")
diff --git a/examples/HelloInstancing.cpp b/examples/HelloInstancing.cpp
index 04971a8..7aa0832 100644
--- a/examples/HelloInstancing.cpp
+++ b/examples/HelloInstancing.cpp
@@ -14,6 +14,8 @@
 
 #include "Utils.h"
 
+#include "utils/NXTHelpers.h"
+
 #include <vector>
 
 nxt::Device device;
@@ -32,7 +34,7 @@
         -0.1f, -0.1f, 0.0f, 1.0f,
         0.1f, -0.1f, 0.0f, 1.0f,
     };
-    vertexBuffer = CreateFrozenBufferFromData(device, vertexData, sizeof(vertexData), nxt::BufferUsageBit::Vertex);
+    vertexBuffer = utils::CreateFrozenBufferFromData(device, vertexData, sizeof(vertexData), nxt::BufferUsageBit::Vertex);
 
     static const float instanceData[8] = {
         -0.5f, -0.5f,
@@ -40,7 +42,7 @@
         0.5f, -0.5f,
         0.5f, 0.5f,
     };
-    instanceBuffer = CreateFrozenBufferFromData(device, instanceData, sizeof(instanceData), nxt::BufferUsageBit::Vertex);
+    instanceBuffer = utils::CreateFrozenBufferFromData(device, instanceData, sizeof(instanceData), nxt::BufferUsageBit::Vertex);
 }
 
 void init() {
@@ -50,7 +52,7 @@
 
     initBuffers();
 
-    nxt::ShaderModule vsModule = CreateShaderModule(device, nxt::ShaderStage::Vertex, R"(
+    nxt::ShaderModule vsModule = utils::CreateShaderModule(device, nxt::ShaderStage::Vertex, R"(
         #version 450
         layout(location = 0) in vec4 pos;
         layout(location = 1) in vec2 instance;
@@ -59,7 +61,7 @@
         })"
     );
 
-    nxt::ShaderModule fsModule = CreateShaderModule(device, nxt::ShaderStage::Fragment, R"(
+    nxt::ShaderModule fsModule = utils::CreateShaderModule(device, nxt::ShaderStage::Fragment, R"(
         #version 450
         out vec4 fragColor;
         void main() {
@@ -74,7 +76,7 @@
         .SetInput(1, 2 * sizeof(float), nxt::InputStepMode::Instance)
         .GetResult();
 
-    CreateDefaultRenderPass(device, &renderpass, &framebuffer);
+    utils::CreateDefaultRenderPass(device, &renderpass, &framebuffer);
     pipeline = device.CreatePipelineBuilder()
         .SetSubpass(renderpass, 0)
         .SetStage(nxt::ShaderStage::Vertex, vsModule, "main")
diff --git a/examples/HelloTriangle.cpp b/examples/HelloTriangle.cpp
index 75b32c0..cfe763e 100644
--- a/examples/HelloTriangle.cpp
+++ b/examples/HelloTriangle.cpp
@@ -14,6 +14,8 @@
 
 #include "Utils.h"
 
+#include "utils/NXTHelpers.h"
+
 #include <vector>
 
 nxt::Device device;
@@ -34,14 +36,14 @@
     static const uint32_t indexData[3] = {
         0, 1, 2,
     };
-    indexBuffer = CreateFrozenBufferFromData(device, indexData, sizeof(indexData), nxt::BufferUsageBit::Index);
+    indexBuffer = utils::CreateFrozenBufferFromData(device, indexData, sizeof(indexData), nxt::BufferUsageBit::Index);
 
     static const float vertexData[12] = {
         0.0f, 0.5f, 0.0f, 1.0f,
         -0.5f, -0.5f, 0.0f, 1.0f,
         0.5f, -0.5f, 0.0f, 1.0f,
     };
-    vertexBuffer = CreateFrozenBufferFromData(device, vertexData, sizeof(vertexData), nxt::BufferUsageBit::Vertex);
+    vertexBuffer = utils::CreateFrozenBufferFromData(device, vertexData, sizeof(vertexData), nxt::BufferUsageBit::Vertex);
 }
 
 void initTextures() {
@@ -64,7 +66,7 @@
     }
 
 
-    nxt::Buffer stagingBuffer = CreateFrozenBufferFromData(device, data.data(), data.size(), nxt::BufferUsageBit::TransferSrc);
+    nxt::Buffer stagingBuffer = utils::CreateFrozenBufferFromData(device, data.data(), data.size(), nxt::BufferUsageBit::TransferSrc);
     nxt::CommandBuffer copy = device.CreateCommandBufferBuilder()
         .TransitionTextureUsage(texture, nxt::TextureUsageBit::TransferDst)
         .CopyBufferToTexture(stagingBuffer, 0, texture, 0, 0, 0, 1024, 1024, 1, 0)
@@ -82,7 +84,7 @@
     initBuffers();
     initTextures();
 
-    nxt::ShaderModule vsModule = CreateShaderModule(device, nxt::ShaderStage::Vertex, R"(
+    nxt::ShaderModule vsModule = utils::CreateShaderModule(device, nxt::ShaderStage::Vertex, R"(
         #version 450
         layout(location = 0) in vec4 pos;
         void main() {
@@ -90,7 +92,7 @@
         })"
     );
 
-    nxt::ShaderModule fsModule = CreateShaderModule(device, nxt::ShaderStage::Fragment, R"(
+    nxt::ShaderModule fsModule = utils::CreateShaderModule(device, nxt::ShaderStage::Fragment, R"(
         #version 450
         layout(set = 0, binding = 0) uniform sampler mySampler;
         layout(set = 0, binding = 1) uniform texture2D myTexture;
@@ -115,7 +117,7 @@
         .SetBindGroupLayout(0, bgl)
         .GetResult();
 
-    CreateDefaultRenderPass(device, &renderpass, &framebuffer);
+    utils::CreateDefaultRenderPass(device, &renderpass, &framebuffer);
     pipeline = device.CreatePipelineBuilder()
         .SetSubpass(renderpass, 0)
         .SetLayout(pl)
diff --git a/examples/HelloUBO.cpp b/examples/HelloUBO.cpp
index 06fdca3..d2fa7f1 100644
--- a/examples/HelloUBO.cpp
+++ b/examples/HelloUBO.cpp
@@ -14,6 +14,8 @@
 
 #include "Utils.h"
 
+#include "utils/NXTHelpers.h"
+
 nxt::Device device;
 nxt::Queue queue;
 nxt::Pipeline pipeline;
@@ -29,7 +31,7 @@
 
     queue = device.CreateQueueBuilder().GetResult();
 
-    nxt::ShaderModule vsModule = CreateShaderModule(device, nxt::ShaderStage::Vertex, R"(
+    nxt::ShaderModule vsModule = utils::CreateShaderModule(device, nxt::ShaderStage::Vertex, R"(
         #version 450
         const vec2 pos[3] = vec2[3](vec2(0.0f, 0.5f), vec2(-0.5f, -0.5f), vec2(0.5f, -0.5f));
         void main() {
@@ -37,7 +39,7 @@
         })"
     );
 
-    nxt::ShaderModule fsModule = CreateShaderModule(device, nxt::ShaderStage::Fragment, R"(
+    nxt::ShaderModule fsModule = utils::CreateShaderModule(device, nxt::ShaderStage::Fragment, R"(
         #version 450
         layout(set = 0, binding = 0) uniform myBlock {
             int a;
@@ -57,7 +59,7 @@
         .SetBindGroupLayout(0, bgl)
         .GetResult();
 
-    CreateDefaultRenderPass(device, &renderpass, &framebuffer);
+    utils::CreateDefaultRenderPass(device, &renderpass, &framebuffer);
     pipeline = device.CreatePipelineBuilder()
         .SetSubpass(renderpass, 0)
         .SetLayout(pl)
diff --git a/examples/HelloVertices.cpp b/examples/HelloVertices.cpp
index 7ca2203..8971d09 100644
--- a/examples/HelloVertices.cpp
+++ b/examples/HelloVertices.cpp
@@ -14,6 +14,8 @@
 
 #include "Utils.h"
 
+#include "utils/NXTHelpers.h"
+
 #include <vector>
 
 nxt::Device device;
@@ -31,7 +33,7 @@
         -0.5f, -0.5f, 0.0f, 1.0f,
         0.5f, -0.5f, 0.0f, 1.0f,
     };
-    vertexBuffer = CreateFrozenBufferFromData(device, vertexData, sizeof(vertexData), nxt::BufferUsageBit::Vertex);
+    vertexBuffer = utils::CreateFrozenBufferFromData(device, vertexData, sizeof(vertexData), nxt::BufferUsageBit::Vertex);
 }
 
 void init() {
@@ -41,7 +43,7 @@
 
     initBuffers();
 
-    nxt::ShaderModule vsModule = CreateShaderModule(device, nxt::ShaderStage::Vertex, R"(
+    nxt::ShaderModule vsModule = utils::CreateShaderModule(device, nxt::ShaderStage::Vertex, R"(
         #version 450
         layout(location = 0) in vec4 pos;
         void main() {
@@ -49,7 +51,7 @@
         })"
     );
 
-    nxt::ShaderModule fsModule = CreateShaderModule(device, nxt::ShaderStage::Fragment, R"(
+    nxt::ShaderModule fsModule = utils::CreateShaderModule(device, nxt::ShaderStage::Fragment, R"(
         #version 450
         layout(location = 0) out vec4 fragColor;
         void main() {
@@ -62,7 +64,7 @@
         .SetInput(0, 4 * sizeof(float), nxt::InputStepMode::Vertex)
         .GetResult();
 
-    CreateDefaultRenderPass(device, &renderpass, &framebuffer);
+    utils::CreateDefaultRenderPass(device, &renderpass, &framebuffer);
     pipeline = device.CreatePipelineBuilder()
         .SetSubpass(renderpass, 0)
         .SetStage(nxt::ShaderStage::Vertex, vsModule, "main")
diff --git a/examples/RenderToTexture.cpp b/examples/RenderToTexture.cpp
index f7ea0a2..91c5e5f 100644
--- a/examples/RenderToTexture.cpp
+++ b/examples/RenderToTexture.cpp
@@ -14,6 +14,8 @@
 
 #include "Utils.h"
 
+#include "utils/NXTHelpers.h"
+
 #include <vector>
 
 nxt::Device device;
@@ -38,7 +40,7 @@
         -0.5f, -0.5f, 0.0f, 1.0f,
         0.5f, -0.5f, 0.0f, 1.0f,
     };
-    vertexBuffer = CreateFrozenBufferFromData(device, vertexData, sizeof(vertexData), nxt::BufferUsageBit::Vertex);
+    vertexBuffer = utils::CreateFrozenBufferFromData(device, vertexData, sizeof(vertexData), nxt::BufferUsageBit::Vertex);
 
     static const float vertexDataQuad[24] = {
         -1.0f, -1.0f, 0.0f, 1.0f,
@@ -48,7 +50,7 @@
         1.0f, -1.0f, 0.0f, 1.0f,
         1.0f, 1.0f, 0.0f, 1.0f,
     };
-    vertexBufferQuad = CreateFrozenBufferFromData(device, vertexDataQuad, sizeof(vertexDataQuad), nxt::BufferUsageBit::Vertex);
+    vertexBufferQuad = utils::CreateFrozenBufferFromData(device, vertexDataQuad, sizeof(vertexDataQuad), nxt::BufferUsageBit::Vertex);
 }
 
 void initTextures() {
@@ -89,7 +91,7 @@
 }
 
 void initPipeline() {
-    nxt::ShaderModule vsModule = CreateShaderModule(device, nxt::ShaderStage::Vertex, R"(
+    nxt::ShaderModule vsModule = utils::CreateShaderModule(device, nxt::ShaderStage::Vertex, R"(
         #version 450
         layout(location = 0) in vec4 pos;
         void main() {
@@ -97,7 +99,7 @@
         })"
     );
 
-    nxt::ShaderModule fsModule = CreateShaderModule(device, nxt::ShaderStage::Fragment, R"(
+    nxt::ShaderModule fsModule = utils::CreateShaderModule(device, nxt::ShaderStage::Fragment, R"(
         #version 450
         layout(location = 0) out vec4 fragColor;
         void main() {
@@ -119,7 +121,7 @@
 }
 
 void initPipelinePost() {
-    nxt::ShaderModule vsModule = CreateShaderModule(device, nxt::ShaderStage::Vertex, R"(
+    nxt::ShaderModule vsModule = utils::CreateShaderModule(device, nxt::ShaderStage::Vertex, R"(
         #version 450
         layout(location = 0) in vec4 pos;
         void main() {
@@ -127,7 +129,7 @@
         })"
     );
 
-    nxt::ShaderModule fsModule = CreateShaderModule(device, nxt::ShaderStage::Fragment, R"(
+    nxt::ShaderModule fsModule = utils::CreateShaderModule(device, nxt::ShaderStage::Fragment, R"(
         #version 450
         layout(set = 0, binding = 0) uniform sampler samp;
         layout(set = 0, binding = 1) uniform texture2D tex;
diff --git a/examples/Utils.cpp b/examples/Utils.cpp
index 7c563c4..e2cba51 100644
--- a/examples/Utils.cpp
+++ b/examples/Utils.cpp
@@ -17,13 +17,10 @@
 
 #include <nxt/nxt.h>
 #include <nxt/nxtcpp.h>
-#include <shaderc/shaderc.hpp>
 #include "GLFW/glfw3.h"
 
 #include <cstring>
 #include <iostream>
-#include <sstream>
-#include <iomanip>
 
 #ifdef _WIN32
     #include <Windows.h>
@@ -113,87 +110,6 @@
     return nxt::Device::Acquire(cDevice);
 }
 
-nxt::ShaderModule CreateShaderModule(const nxt::Device& device, nxt::ShaderStage stage, const char* source) {
-    shaderc::Compiler compiler;
-    shaderc::CompileOptions options;
-
-    shaderc_shader_kind kind;
-    switch (stage) {
-        case nxt::ShaderStage::Vertex:
-            kind = shaderc_glsl_vertex_shader;
-            break;
-        case nxt::ShaderStage::Fragment:
-            kind = shaderc_glsl_fragment_shader;
-            break;
-        case nxt::ShaderStage::Compute:
-            kind = shaderc_glsl_compute_shader;
-            break;
-    }
-
-    auto result = compiler.CompileGlslToSpv(source, strlen(source), kind, "myshader?", options);
-    if (result.GetCompilationStatus() != shaderc_compilation_status_success) {
-        std::cerr << result.GetErrorMessage();
-        return {};
-    }
-
-    size_t size = (result.cend() - result.cbegin());
-
-#ifdef DUMP_SPIRV_ASSEMBLY
-    {
-        auto resultAsm = compiler.CompileGlslToSpvAssembly(source, strlen(source), kind, "myshader?", options);
-        size_t sizeAsm = (resultAsm.cend() - resultAsm.cbegin());
-
-        char* buffer = reinterpret_cast<char*>(malloc(sizeAsm + 1));
-        memcpy(buffer, resultAsm.cbegin(), sizeAsm);
-        buffer[sizeAsm] = '\0';
-        printf("SPIRV ASSEMBLY DUMP START\n%s\nSPIRV ASSEMBLY DUMP END\n", buffer);
-        free(buffer);
-    }
-#endif
-
-#ifdef DUMP_SPIRV_JS_ARRAY
-    printf("SPIRV JS ARRAY DUMP START\n");
-    for (size_t i = 0; i < size; i++) {
-        printf("%#010x", result.cbegin()[i]);
-        if ((i + 1) % 4 == 0) {
-            printf(",\n");
-        } else {
-            printf(", ");
-        }
-    }
-    printf("\n");
-    printf("SPIRV JS ARRAY DUMP END\n");
-#endif
-
-    return device.CreateShaderModuleBuilder()
-        .SetSource(size, result.cbegin())
-        .GetResult();
-}
-
-void CreateDefaultRenderPass(const nxt::Device& device, nxt::RenderPass* renderPass, nxt::Framebuffer* framebuffer) {
-    *renderPass = device.CreateRenderPassBuilder()
-        .SetAttachmentCount(1)
-        .AttachmentSetFormat(0, nxt::TextureFormat::R8G8B8A8Unorm)
-        .SetSubpassCount(1)
-        .SubpassSetColorAttachment(0, 0, 0)
-        .GetResult();
-    *framebuffer = device.CreateFramebufferBuilder()
-        .SetRenderPass(*renderPass)
-        .SetDimensions(640, 480)
-        .GetResult();
-}
-
-nxt::Buffer CreateFrozenBufferFromData(const nxt::Device& device, const void* data, uint32_t size, nxt::BufferUsageBit usage) {
-    nxt::Buffer buffer = device.CreateBufferBuilder()
-        .SetAllowedUsage(nxt::BufferUsageBit::TransferDst | usage)
-        .SetInitialUsage(nxt::BufferUsageBit::TransferDst)
-        .SetSize(size)
-        .GetResult();
-    buffer.SetSubData(0, size / sizeof(uint32_t), reinterpret_cast<const uint32_t*>(data));
-    buffer.FreezeUsage(usage);
-    return buffer;
-}
-
 bool InitUtils(int argc, const char** argv) {
     for (int i = 0; i < argc; i++) {
         if (std::string("-b") == argv[i] || std::string("--backend") == argv[i]) {
diff --git a/examples/Utils.h b/examples/Utils.h
index a279567..e8a2fbc 100644
--- a/examples/Utils.h
+++ b/examples/Utils.h
@@ -23,6 +23,3 @@
 struct GLFWwindow* GetGLFWWindow();
 
 nxt::Device CreateCppNXTDevice();
-nxt::ShaderModule CreateShaderModule(const nxt::Device& device, nxt::ShaderStage stage, const char* source);
-void CreateDefaultRenderPass(const nxt::Device& device, nxt::RenderPass* renderPass, nxt::Framebuffer* framebuffer);
-nxt::Buffer CreateFrozenBufferFromData(const nxt::Device& device, const void* data, uint32_t size, nxt::BufferUsageBit usage);
diff --git a/examples/glTFViewer/glTFViewer.cpp b/examples/glTFViewer/glTFViewer.cpp
index a2a5148..6e233ae 100644
--- a/examples/glTFViewer/glTFViewer.cpp
+++ b/examples/glTFViewer/glTFViewer.cpp
@@ -20,6 +20,8 @@
 
 #include "Utils.h"
 
+#include "utils/NXTHelpers.h"
+
 #include <bitset>
 #define GLM_FORCE_DEPTH_ZERO_TO_ONE
 #include <glm/mat4x4.hpp>
@@ -147,7 +149,7 @@
             uint32_t iBufferViewSize =
                 iBufferView.byteLength ? iBufferView.byteLength :
                 (iBuffer.data.size() - iBufferView.byteOffset);
-            auto oBuffer = CreateFrozenBufferFromData(device, &iBuffer.data.at(iBufferView.byteOffset), iBufferViewSize, usage);
+            auto oBuffer = utils::CreateFrozenBufferFromData(device, &iBuffer.data.at(iBufferView.byteOffset), iBufferViewSize, usage);
             buffers[iBufferViewID] = std::move(oBuffer);
         }
     }
@@ -164,7 +166,7 @@
         const auto& iTechnique = scene.techniques.at(iMaterial.technique);
         const auto& iProgram = scene.programs.at(iTechnique.program);
 
-        auto oVSModule = CreateShaderModule(device, nxt::ShaderStage::Vertex, R"(
+        auto oVSModule = utils::CreateShaderModule(device, nxt::ShaderStage::Vertex, R"(
             #version 450
 
             layout(set = 0, binding = 0) uniform u_transform_block {
@@ -185,7 +187,7 @@
                 gl_Position = u_transform.modelViewProj * a_position;
             })");
 
-        auto oFSModule = CreateShaderModule(device, nxt::ShaderStage::Fragment, R"(
+        auto oFSModule = utils::CreateShaderModule(device, nxt::ShaderStage::Fragment, R"(
             #version 450
 
             layout(set = 0, binding = 1) uniform sampler u_samp;
@@ -373,7 +375,7 @@
                 // TODO: release this texture
 
             uint32_t white = 0xffffffff;
-            nxt::Buffer staging = CreateFrozenBufferFromData(device, &white, sizeof(white), nxt::BufferUsageBit::TransferSrc);
+            nxt::Buffer staging = utils::CreateFrozenBufferFromData(device, &white, sizeof(white), nxt::BufferUsageBit::TransferSrc);
             auto cmdbuf = device.CreateCommandBufferBuilder()
                 .TransitionTextureUsage(oTexture, nxt::TextureUsageBit::TransferDst)
                 .CopyBufferToTexture(staging, 0, oTexture, 0, 0, 0, 1, 1, 1, 0)
@@ -427,7 +429,7 @@
                 fprintf(stderr, "unsupported image.component %d\n", iImage.component);
             }
 
-            nxt::Buffer staging = CreateFrozenBufferFromData(device, data, numPixels * 4, nxt::BufferUsageBit::TransferSrc);
+            nxt::Buffer staging = utils::CreateFrozenBufferFromData(device, data, numPixels * 4, nxt::BufferUsageBit::TransferSrc);
             auto cmdbuf = device.CreateCommandBufferBuilder()
                 .TransitionTextureUsage(oTexture, nxt::TextureUsageBit::TransferDst)
                 .CopyBufferToTexture(staging, 0, oTexture, 0, 0, 0, iImage.width, iImage.height, 1, 0)