Split Mapped usage in MapWrite and MapRead

Also make use of CreateFrozenBufferFromData where possible in the
example to make the renaming easier.
diff --git a/examples/ComputeBoids.cpp b/examples/ComputeBoids.cpp
index c37d0f6..d73eb5d 100644
--- a/examples/ComputeBoids.cpp
+++ b/examples/ComputeBoids.cpp
@@ -62,24 +62,10 @@
         {0.01, -0.02},
         {0.00, 0.02},
     };
-    modelBuffer = device.CreateBufferBuilder()
-        .SetAllowedUsage(nxt::BufferUsageBit::Mapped | nxt::BufferUsageBit::Vertex)
-        .SetInitialUsage(nxt::BufferUsageBit::Mapped)
-        .SetSize(sizeof(model))
-        .GetResult();
-    modelBuffer.SetSubData(0, sizeof(model) / sizeof(uint32_t),
-            reinterpret_cast<uint32_t*>(model));
-    modelBuffer.FreezeUsage(nxt::BufferUsageBit::Vertex);
+    modelBuffer = 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 = device.CreateBufferBuilder()
-        .SetAllowedUsage(nxt::BufferUsageBit::Mapped | nxt::BufferUsageBit::Uniform)
-        .SetInitialUsage(nxt::BufferUsageBit::Mapped)
-        .SetSize(sizeof(SimParams))
-        .GetResult();
-    updateParams.SetSubData(0, sizeof(SimParams) / sizeof(uint32_t),
-            reinterpret_cast<uint32_t*>(&params));
-    updateParams.FreezeUsage(nxt::BufferUsageBit::Uniform);
+    updateParams = CreateFrozenBufferFromData(device, &params, sizeof(params), nxt::BufferUsageBit::Uniform);
 
     std::vector<Particle> initialParticles(kNumParticles);
     {
@@ -94,8 +80,8 @@
 
     for (int i = 0; i < 2; i++) {
         particleBuffers[i] = device.CreateBufferBuilder()
-            .SetAllowedUsage(nxt::BufferUsageBit::Mapped | nxt::BufferUsageBit::Vertex | nxt::BufferUsageBit::Storage)
-            .SetInitialUsage(nxt::BufferUsageBit::Mapped)
+            .SetAllowedUsage(nxt::BufferUsageBit::MapWrite | nxt::BufferUsageBit::Vertex | nxt::BufferUsageBit::Storage)
+            .SetInitialUsage(nxt::BufferUsageBit::MapWrite)
             .SetSize(sizeof(Particle) * kNumParticles)
             .GetResult();
 
diff --git a/examples/HelloCompute.cpp b/examples/HelloCompute.cpp
index f0b9024..6d64e1a 100644
--- a/examples/HelloCompute.cpp
+++ b/examples/HelloCompute.cpp
@@ -34,8 +34,8 @@
     struct {uint32_t a; float b;} s;
     memset(&s, sizeof(s), 0);
     buffer = device.CreateBufferBuilder()
-        .SetAllowedUsage(nxt::BufferUsageBit::Mapped | nxt::BufferUsageBit::Uniform | nxt::BufferUsageBit::Storage)
-        .SetInitialUsage(nxt::BufferUsageBit::Mapped)
+        .SetAllowedUsage(nxt::BufferUsageBit::MapWrite | nxt::BufferUsageBit::Uniform | nxt::BufferUsageBit::Storage)
+        .SetInitialUsage(nxt::BufferUsageBit::MapWrite)
         .SetSize(sizeof(s))
         .GetResult();
     buffer.SetSubData(0, sizeof(s) / sizeof(uint32_t), reinterpret_cast<uint32_t*>(&s));
diff --git a/examples/HelloDepthStencil.cpp b/examples/HelloDepthStencil.cpp
index 6e70a15..287880f 100644
--- a/examples/HelloDepthStencil.cpp
+++ b/examples/HelloDepthStencil.cpp
@@ -165,8 +165,8 @@
         .GetResult();
 
     cameraBuffer = device.CreateBufferBuilder()
-        .SetAllowedUsage(nxt::BufferUsageBit::Mapped | nxt::BufferUsageBit::Uniform)
-        .SetInitialUsage(nxt::BufferUsageBit::Mapped)
+        .SetAllowedUsage(nxt::BufferUsageBit::MapWrite | nxt::BufferUsageBit::Uniform)
+        .SetInitialUsage(nxt::BufferUsageBit::MapWrite)
         .SetSize(sizeof(CameraData))
         .GetResult();
 
@@ -265,7 +265,7 @@
         glm::vec3(0.0f, 1.0f, 0.0f)
     );
 
-    cameraBuffer.TransitionUsage(nxt::BufferUsageBit::Mapped);
+    cameraBuffer.TransitionUsage(nxt::BufferUsageBit::MapWrite);
     cameraBuffer.SetSubData(0, sizeof(CameraData) / sizeof(uint32_t), reinterpret_cast<uint32_t*>(&cameraData));
 
     nxt::CommandBuffer commands = device.CreateCommandBufferBuilder()
diff --git a/examples/HelloIndices.cpp b/examples/HelloIndices.cpp
index f67cf80..c20269f 100644
--- a/examples/HelloIndices.cpp
+++ b/examples/HelloIndices.cpp
@@ -30,27 +30,14 @@
     static const uint32_t indexData[3] = {
         0, 1, 2,
     };
-    indexBuffer = device.CreateBufferBuilder()
-        .SetAllowedUsage(nxt::BufferUsageBit::Mapped | nxt::BufferUsageBit::Index)
-        .SetInitialUsage(nxt::BufferUsageBit::Mapped)
-        .SetSize(sizeof(indexData))
-        .GetResult();
-    indexBuffer.SetSubData(0, sizeof(indexData) / sizeof(uint32_t), indexData);
-    indexBuffer.FreezeUsage(nxt::BufferUsageBit::Index);
+    indexBuffer = 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 = device.CreateBufferBuilder()
-        .SetAllowedUsage(nxt::BufferUsageBit::Mapped | nxt::BufferUsageBit::Vertex)
-        .SetInitialUsage(nxt::BufferUsageBit::Mapped)
-        .SetSize(sizeof(vertexData))
-        .GetResult();
-    vertexBuffer.SetSubData(0, sizeof(vertexData) / sizeof(uint32_t),
-            reinterpret_cast<const uint32_t*>(vertexData));
-    vertexBuffer.FreezeUsage(nxt::BufferUsageBit::Vertex);
+    vertexBuffer = CreateFrozenBufferFromData(device, vertexData, sizeof(vertexData), nxt::BufferUsageBit::Vertex);
 }
 
 void init() {
diff --git a/examples/HelloInstancing.cpp b/examples/HelloInstancing.cpp
index 2cb291f..04971a8 100644
--- a/examples/HelloInstancing.cpp
+++ b/examples/HelloInstancing.cpp
@@ -32,14 +32,7 @@
         -0.1f, -0.1f, 0.0f, 1.0f,
         0.1f, -0.1f, 0.0f, 1.0f,
     };
-    vertexBuffer = device.CreateBufferBuilder()
-        .SetAllowedUsage(nxt::BufferUsageBit::Mapped | nxt::BufferUsageBit::Vertex)
-        .SetInitialUsage(nxt::BufferUsageBit::Mapped)
-        .SetSize(sizeof(vertexData))
-        .GetResult();
-    vertexBuffer.SetSubData(0, sizeof(vertexData) / sizeof(uint32_t),
-            reinterpret_cast<const uint32_t*>(vertexData));
-    vertexBuffer.FreezeUsage(nxt::BufferUsageBit::Vertex);
+    vertexBuffer = CreateFrozenBufferFromData(device, vertexData, sizeof(vertexData), nxt::BufferUsageBit::Vertex);
 
     static const float instanceData[8] = {
         -0.5f, -0.5f,
@@ -47,14 +40,7 @@
         0.5f, -0.5f,
         0.5f, 0.5f,
     };
-    instanceBuffer = device.CreateBufferBuilder()
-        .SetAllowedUsage(nxt::BufferUsageBit::Mapped | nxt::BufferUsageBit::Vertex)
-        .SetInitialUsage(nxt::BufferUsageBit::Mapped)
-        .SetSize(sizeof(instanceData))
-        .GetResult();
-    instanceBuffer.SetSubData(0, sizeof(instanceData) / sizeof(uint32_t),
-            reinterpret_cast<const uint32_t*>(instanceData));
-    instanceBuffer.FreezeUsage(nxt::BufferUsageBit::Vertex);
+    instanceBuffer = CreateFrozenBufferFromData(device, instanceData, sizeof(instanceData), nxt::BufferUsageBit::Vertex);
 }
 
 void init() {
diff --git a/examples/HelloTriangle.cpp b/examples/HelloTriangle.cpp
index cce22b1..75b32c0 100644
--- a/examples/HelloTriangle.cpp
+++ b/examples/HelloTriangle.cpp
@@ -34,27 +34,14 @@
     static const uint32_t indexData[3] = {
         0, 1, 2,
     };
-    indexBuffer = device.CreateBufferBuilder()
-        .SetAllowedUsage(nxt::BufferUsageBit::Mapped | nxt::BufferUsageBit::Index)
-        .SetInitialUsage(nxt::BufferUsageBit::Mapped)
-        .SetSize(sizeof(indexData))
-        .GetResult();
-    indexBuffer.SetSubData(0, sizeof(indexData) / sizeof(uint32_t), indexData);
-    indexBuffer.FreezeUsage(nxt::BufferUsageBit::Index);
+    indexBuffer = 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 = device.CreateBufferBuilder()
-        .SetAllowedUsage(nxt::BufferUsageBit::Mapped | nxt::BufferUsageBit::Vertex)
-        .SetInitialUsage(nxt::BufferUsageBit::Mapped)
-        .SetSize(sizeof(vertexData))
-        .GetResult();
-    vertexBuffer.SetSubData(0, sizeof(vertexData) / sizeof(uint32_t),
-            reinterpret_cast<const uint32_t*>(vertexData));
-    vertexBuffer.FreezeUsage(nxt::BufferUsageBit::Vertex);
+    vertexBuffer = CreateFrozenBufferFromData(device, vertexData, sizeof(vertexData), nxt::BufferUsageBit::Vertex);
 }
 
 void initTextures() {
@@ -76,14 +63,8 @@
         data[i] = i % 253;
     }
 
-    nxt::Buffer stagingBuffer = device.CreateBufferBuilder()
-        .SetAllowedUsage(nxt::BufferUsageBit::Mapped | nxt::BufferUsageBit::TransferSrc)
-        .SetInitialUsage(nxt::BufferUsageBit::Mapped)
-        .SetSize(data.size())
-        .GetResult();
-    stagingBuffer.SetSubData(0, data.size() / sizeof(uint32_t), reinterpret_cast<uint32_t*>(data.data()));
-    stagingBuffer.FreezeUsage(nxt::BufferUsageBit::TransferSrc);
 
+    nxt::Buffer stagingBuffer = 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)
diff --git a/examples/HelloUBO.cpp b/examples/HelloUBO.cpp
index 364dd33..7ed0672 100644
--- a/examples/HelloUBO.cpp
+++ b/examples/HelloUBO.cpp
@@ -66,8 +66,8 @@
         .GetResult();
 
     buffer = device.CreateBufferBuilder()
-        .SetAllowedUsage(nxt::BufferUsageBit::Mapped | nxt::BufferUsageBit::Uniform)
-        .SetInitialUsage(nxt::BufferUsageBit::Mapped)
+        .SetAllowedUsage(nxt::BufferUsageBit::MapWrite | nxt::BufferUsageBit::Uniform)
+        .SetInitialUsage(nxt::BufferUsageBit::MapWrite)
         .SetSize(sizeof(s))
         .GetResult();
 
@@ -87,7 +87,7 @@
     s.b += 0.02;
     if (s.b >= 1.0f) {s.b = 0.0f;}
 
-    buffer.TransitionUsage(nxt::BufferUsageBit::Mapped);
+    buffer.TransitionUsage(nxt::BufferUsageBit::MapWrite);
     buffer.SetSubData(0, sizeof(s) / sizeof(uint32_t), reinterpret_cast<uint32_t*>(&s));
 
     nxt::CommandBuffer commands = device.CreateCommandBufferBuilder()
diff --git a/examples/HelloVertices.cpp b/examples/HelloVertices.cpp
index 00bac28..7ca2203 100644
--- a/examples/HelloVertices.cpp
+++ b/examples/HelloVertices.cpp
@@ -31,14 +31,7 @@
         -0.5f, -0.5f, 0.0f, 1.0f,
         0.5f, -0.5f, 0.0f, 1.0f,
     };
-    vertexBuffer = device.CreateBufferBuilder()
-        .SetAllowedUsage(nxt::BufferUsageBit::Mapped | nxt::BufferUsageBit::Vertex)
-        .SetInitialUsage(nxt::BufferUsageBit::Mapped)
-        .SetSize(sizeof(vertexData))
-        .GetResult();
-    vertexBuffer.SetSubData(0, sizeof(vertexData) / sizeof(uint32_t),
-            reinterpret_cast<const uint32_t*>(vertexData));
-    vertexBuffer.FreezeUsage(nxt::BufferUsageBit::Vertex);
+    vertexBuffer = CreateFrozenBufferFromData(device, vertexData, sizeof(vertexData), nxt::BufferUsageBit::Vertex);
 }
 
 void init() {
diff --git a/examples/RenderToTexture.cpp b/examples/RenderToTexture.cpp
index d70f7eb..f7ea0a2 100644
--- a/examples/RenderToTexture.cpp
+++ b/examples/RenderToTexture.cpp
@@ -38,14 +38,7 @@
         -0.5f, -0.5f, 0.0f, 1.0f,
         0.5f, -0.5f, 0.0f, 1.0f,
     };
-    vertexBuffer = device.CreateBufferBuilder()
-        .SetAllowedUsage(nxt::BufferUsageBit::Mapped | nxt::BufferUsageBit::Vertex)
-        .SetInitialUsage(nxt::BufferUsageBit::Mapped)
-        .SetSize(sizeof(vertexData))
-        .GetResult();
-    vertexBuffer.SetSubData(0, sizeof(vertexData) / sizeof(uint32_t),
-            reinterpret_cast<const uint32_t*>(vertexData));
-    vertexBuffer.FreezeUsage(nxt::BufferUsageBit::Vertex);
+    vertexBuffer = CreateFrozenBufferFromData(device, vertexData, sizeof(vertexData), nxt::BufferUsageBit::Vertex);
 
     static const float vertexDataQuad[24] = {
         -1.0f, -1.0f, 0.0f, 1.0f,
@@ -55,14 +48,7 @@
         1.0f, -1.0f, 0.0f, 1.0f,
         1.0f, 1.0f, 0.0f, 1.0f,
     };
-    vertexBufferQuad = device.CreateBufferBuilder()
-        .SetAllowedUsage(nxt::BufferUsageBit::Mapped | nxt::BufferUsageBit::Vertex)
-        .SetInitialUsage(nxt::BufferUsageBit::Mapped)
-        .SetSize(sizeof(vertexDataQuad))
-        .GetResult();
-    vertexBufferQuad.SetSubData(0, sizeof(vertexDataQuad) / sizeof(uint32_t),
-            reinterpret_cast<const uint32_t*>(vertexDataQuad));
-    vertexBufferQuad.FreezeUsage(nxt::BufferUsageBit::Vertex);
+    vertexBufferQuad = CreateFrozenBufferFromData(device, vertexDataQuad, sizeof(vertexDataQuad), nxt::BufferUsageBit::Vertex);
 }
 
 void initTextures() {
diff --git a/examples/Utils.cpp b/examples/Utils.cpp
index b72d39e..fc7baa1 100644
--- a/examples/Utils.cpp
+++ b/examples/Utils.cpp
@@ -262,8 +262,8 @@
 
 nxt::Buffer CreateFrozenBufferFromData(const nxt::Device& device, const void* data, uint32_t size, nxt::BufferUsageBit usage) {
     nxt::Buffer buffer = device.CreateBufferBuilder()
-        .SetAllowedUsage(nxt::BufferUsageBit::Mapped | usage)
-        .SetInitialUsage(nxt::BufferUsageBit::Mapped)
+        .SetAllowedUsage(nxt::BufferUsageBit::MapWrite | usage)
+        .SetInitialUsage(nxt::BufferUsageBit::MapWrite)
         .SetSize(size)
         .GetResult();
     buffer.SetSubData(0, size / sizeof(uint32_t), reinterpret_cast<const uint32_t*>(data));
diff --git a/examples/glTFViewer/glTFViewer.cpp b/examples/glTFViewer/glTFViewer.cpp
index 818f467..c6fe580 100644
--- a/examples/glTFViewer/glTFViewer.cpp
+++ b/examples/glTFViewer/glTFViewer.cpp
@@ -147,14 +147,7 @@
             uint32_t iBufferViewSize =
                 iBufferView.byteLength ? iBufferView.byteLength :
                 (iBuffer.data.size() - iBufferView.byteOffset);
-            auto oBuffer = device.CreateBufferBuilder()
-                .SetAllowedUsage(nxt::BufferUsageBit::Mapped | usage)
-                .SetInitialUsage(nxt::BufferUsageBit::Mapped)
-                .SetSize(iBufferViewSize)
-                .GetResult();
-            oBuffer.SetSubData(0, iBufferViewSize / sizeof(uint32_t),
-                    reinterpret_cast<const uint32_t*>(&iBuffer.data.at(iBufferView.byteOffset)));
-            oBuffer.FreezeUsage(usage);
+            auto oBuffer = CreateFrozenBufferFromData(device, &iBuffer.data.at(iBufferView.byteOffset), iBufferViewSize, usage);
             buffers[iBufferViewID] = std::move(oBuffer);
         }
     }
@@ -272,8 +265,8 @@
             .GetResult();
 
         auto uniformBuffer = device.CreateBufferBuilder()
-            .SetAllowedUsage(nxt::BufferUsageBit::Mapped | nxt::BufferUsageBit::Uniform)
-            .SetInitialUsage(nxt::BufferUsageBit::Mapped)
+            .SetAllowedUsage(nxt::BufferUsageBit::MapWrite | nxt::BufferUsageBit::Uniform)
+            .SetInitialUsage(nxt::BufferUsageBit::MapWrite)
             .SetSize(sizeof(u_transform_block))
             .GetResult();
 
@@ -379,16 +372,8 @@
                 .GetResult();
                 // TODO: release this texture
 
-            nxt::Buffer staging = device.CreateBufferBuilder()
-                .SetAllowedUsage(nxt::BufferUsageBit::Mapped | nxt::BufferUsageBit::TransferSrc)
-                .SetInitialUsage(nxt::BufferUsageBit::Mapped)
-                .SetSize(4)
-                .GetResult();
-                // TODO: release this buffer
-
             uint32_t white = 0xffffffff;
-            staging.SetSubData(0, 1, &white);
-            staging.FreezeUsage(nxt::BufferUsageBit::TransferSrc);
+            nxt::Buffer staging = 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)
@@ -442,16 +427,7 @@
                 fprintf(stderr, "unsupported image.component %d\n", iImage.component);
             }
 
-            nxt::Buffer staging = device.CreateBufferBuilder()
-                .SetAllowedUsage(nxt::BufferUsageBit::Mapped | nxt::BufferUsageBit::TransferSrc)
-                .SetInitialUsage(nxt::BufferUsageBit::Mapped)
-                .SetSize(numPixels * 4)
-                .GetResult();
-                // TODO: release this buffer
-
-            staging.SetSubData(0, numPixels,
-                    reinterpret_cast<const uint32_t*>(data));
-            staging.FreezeUsage(nxt::BufferUsageBit::TransferSrc);
+            nxt::Buffer staging = 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)
@@ -513,7 +489,7 @@
                 }
             }
             const MaterialInfo& material = getMaterial(iPrim.material, strides[0], strides[1], strides[2]);
-            material.uniformBuffer.TransitionUsage(nxt::BufferUsageBit::Mapped);
+            material.uniformBuffer.TransitionUsage(nxt::BufferUsageBit::MapWrite);
             material.uniformBuffer.SetSubData(0,
                     sizeof(u_transform_block) / sizeof(uint32_t),
                     reinterpret_cast<const uint32_t*>(&transforms));
diff --git a/next.json b/next.json
index c74d95f..0be3281 100644
--- a/next.json
+++ b/next.json
@@ -177,7 +177,8 @@
         "category": "bitmask",
         "values": [
             {"value": 0, "name": "none"},
-            {"value": 1, "name": "mapped"},
+            {"value": 1, "name": "map read"},
+            {"value": 1, "name": "map write"},
             {"value": 2, "name": "transfer src"},
             {"value": 4, "name": "transfer dst"},
             {"value": 8, "name": "index"},
diff --git a/src/backend/common/Buffer.cpp b/src/backend/common/Buffer.cpp
index 7dcdf65..b1240f2 100644
--- a/src/backend/common/Buffer.cpp
+++ b/src/backend/common/Buffer.cpp
@@ -56,8 +56,8 @@
             return;
         }
 
-        if (!(currentUsage & nxt::BufferUsageBit::Mapped)) {
-            device->HandleError("Buffer needs the mapped usage bit");
+        if (!(currentUsage & nxt::BufferUsageBit::MapWrite)) {
+            device->HandleError("Buffer needs the map write usage bit");
             return;
         }
 
@@ -74,6 +74,7 @@
 
     bool BufferBase::IsUsagePossible(nxt::BufferUsageBit allowedUsage, nxt::BufferUsageBit usage) {
         const nxt::BufferUsageBit allReadBits =
+            nxt::BufferUsageBit::MapRead |
             nxt::BufferUsageBit::TransferSrc |
             nxt::BufferUsageBit::Index |
             nxt::BufferUsageBit::Vertex |