[Impeller] remove Buffer type and associated abstractions. (#49702)

Now that the HostBuffer isn't implementing Buffer, there is really no reason to have a Buffer/DeviceBuffer split. make BufferViews use a DeviceBuffer, and remove the data ptr from buffer views (as we can always reach into the device buffer).

Makes some other cleanups too, since we always use a std::shared_ptr<DeviceBuffer>, then we can eliminated the shared_from_this call for AsBufferView by making this a static method.
diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter
index 8b069e9..65cf1c2 100644
--- a/ci/licenses_golden/licenses_flutter
+++ b/ci/licenses_golden/licenses_flutter
@@ -5050,8 +5050,6 @@
 ORIGIN: ../../../flutter/impeller/compiler/utilities.h + ../../../flutter/LICENSE
 ORIGIN: ../../../flutter/impeller/core/allocator.cc + ../../../flutter/LICENSE
 ORIGIN: ../../../flutter/impeller/core/allocator.h + ../../../flutter/LICENSE
-ORIGIN: ../../../flutter/impeller/core/buffer.cc + ../../../flutter/LICENSE
-ORIGIN: ../../../flutter/impeller/core/buffer.h + ../../../flutter/LICENSE
 ORIGIN: ../../../flutter/impeller/core/buffer_view.cc + ../../../flutter/LICENSE
 ORIGIN: ../../../flutter/impeller/core/buffer_view.h + ../../../flutter/LICENSE
 ORIGIN: ../../../flutter/impeller/core/capture.cc + ../../../flutter/LICENSE
@@ -7877,8 +7875,6 @@
 FILE: ../../../flutter/impeller/compiler/utilities.h
 FILE: ../../../flutter/impeller/core/allocator.cc
 FILE: ../../../flutter/impeller/core/allocator.h
-FILE: ../../../flutter/impeller/core/buffer.cc
-FILE: ../../../flutter/impeller/core/buffer.h
 FILE: ../../../flutter/impeller/core/buffer_view.cc
 FILE: ../../../flutter/impeller/core/buffer_view.h
 FILE: ../../../flutter/impeller/core/capture.cc
diff --git a/impeller/base/backend_cast.h b/impeller/base/backend_cast.h
index 71e2331..a67e4e3 100644
--- a/impeller/base/backend_cast.h
+++ b/impeller/base/backend_cast.h
@@ -5,8 +5,6 @@
 #ifndef FLUTTER_IMPELLER_BASE_BACKEND_CAST_H_
 #define FLUTTER_IMPELLER_BASE_BACKEND_CAST_H_
 
-#include "flutter/fml/macros.h"
-
 namespace impeller {
 
 template <class Sub, class Base>
diff --git a/impeller/core/BUILD.gn b/impeller/core/BUILD.gn
index 36c7ddb..2f15c1b 100644
--- a/impeller/core/BUILD.gn
+++ b/impeller/core/BUILD.gn
@@ -8,8 +8,6 @@
   sources = [
     "allocator.cc",
     "allocator.h",
-    "buffer.cc",
-    "buffer.h",
     "buffer_view.cc",
     "buffer_view.h",
     "capture.cc",
diff --git a/impeller/core/buffer.cc b/impeller/core/buffer.cc
deleted file mode 100644
index b645939..0000000
--- a/impeller/core/buffer.cc
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright 2013 The Flutter Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "impeller/core/buffer.h"
-
-namespace impeller {
-
-Buffer::~Buffer() = default;
-
-}  // namespace impeller
diff --git a/impeller/core/buffer.h b/impeller/core/buffer.h
deleted file mode 100644
index df58b56..0000000
--- a/impeller/core/buffer.h
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2013 The Flutter Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef FLUTTER_IMPELLER_CORE_BUFFER_H_
-#define FLUTTER_IMPELLER_CORE_BUFFER_H_
-
-#include <memory>
-
-namespace impeller {
-
-class DeviceBuffer;
-class Allocator;
-
-class Buffer {
- public:
-  virtual ~Buffer();
-
-  virtual std::shared_ptr<const DeviceBuffer> GetDeviceBuffer() const = 0;
-};
-
-}  // namespace impeller
-
-#endif  // FLUTTER_IMPELLER_CORE_BUFFER_H_
diff --git a/impeller/core/buffer_view.h b/impeller/core/buffer_view.h
index 551bb0b..e319f44 100644
--- a/impeller/core/buffer_view.h
+++ b/impeller/core/buffer_view.h
@@ -5,14 +5,15 @@
 #ifndef FLUTTER_IMPELLER_CORE_BUFFER_VIEW_H_
 #define FLUTTER_IMPELLER_CORE_BUFFER_VIEW_H_
 
-#include "impeller/core/buffer.h"
+#include <memory>
 #include "impeller/core/range.h"
 
 namespace impeller {
 
+class DeviceBuffer;
+
 struct BufferView {
-  std::shared_ptr<const Buffer> buffer;
-  uint8_t* contents;
+  std::shared_ptr<const DeviceBuffer> buffer;
   Range range;
 
   constexpr explicit operator bool() const { return static_cast<bool>(buffer); }
diff --git a/impeller/core/device_buffer.cc b/impeller/core/device_buffer.cc
index 5c6ecf4..d7262e7 100644
--- a/impeller/core/device_buffer.cc
+++ b/impeller/core/device_buffer.cc
@@ -10,18 +10,13 @@
 
 DeviceBuffer::~DeviceBuffer() = default;
 
-// |Buffer|
-std::shared_ptr<const DeviceBuffer> DeviceBuffer::GetDeviceBuffer() const {
-  return shared_from_this();
-}
-
 void DeviceBuffer::Flush(std::optional<Range> range) const {}
 
-BufferView DeviceBuffer::AsBufferView() const {
+// static
+BufferView DeviceBuffer::AsBufferView(std::shared_ptr<DeviceBuffer> buffer) {
   BufferView view;
-  view.buffer = shared_from_this();
-  view.contents = OnGetContents();
-  view.range = {0u, desc_.size};
+  view.buffer = std::move(buffer);
+  view.range = {0u, view.buffer->desc_.size};
   return view;
 }
 
diff --git a/impeller/core/device_buffer.h b/impeller/core/device_buffer.h
index 7f0cb99..619069d 100644
--- a/impeller/core/device_buffer.h
+++ b/impeller/core/device_buffer.h
@@ -9,7 +9,6 @@
 #include <string>
 
 #include "impeller/core/allocator.h"
-#include "impeller/core/buffer.h"
 #include "impeller/core/buffer_view.h"
 #include "impeller/core/device_buffer_descriptor.h"
 #include "impeller/core/range.h"
@@ -17,8 +16,7 @@
 
 namespace impeller {
 
-class DeviceBuffer : public Buffer,
-                     public std::enable_shared_from_this<DeviceBuffer> {
+class DeviceBuffer {
  public:
   virtual ~DeviceBuffer();
 
@@ -30,16 +28,14 @@
 
   virtual bool SetLabel(const std::string& label, Range range) = 0;
 
-  BufferView AsBufferView() const;
+  /// @brief Create a buffer view of this entire buffer.
+  static BufferView AsBufferView(std::shared_ptr<DeviceBuffer> buffer);
 
   virtual std::shared_ptr<Texture> AsTexture(
       Allocator& allocator,
       const TextureDescriptor& descriptor,
       uint16_t row_bytes) const;
 
-  // |Buffer|
-  std::shared_ptr<const DeviceBuffer> GetDeviceBuffer() const;
-
   const DeviceBufferDescriptor& GetDeviceBufferDescriptor() const;
 
   virtual uint8_t* OnGetContents() const = 0;
diff --git a/impeller/core/host_buffer.cc b/impeller/core/host_buffer.cc
index 1abc892..0752818 100644
--- a/impeller/core/host_buffer.cc
+++ b/impeller/core/host_buffer.cc
@@ -41,29 +41,29 @@
 BufferView HostBuffer::Emplace(const void* buffer,
                                size_t length,
                                size_t align) {
-  auto [data, range, device_buffer] = EmplaceInternal(buffer, length, align);
+  auto [range, device_buffer] = EmplaceInternal(buffer, length, align);
   if (!device_buffer) {
     return {};
   }
-  return BufferView{std::move(device_buffer), data, range};
+  return BufferView{std::move(device_buffer), range};
 }
 
 BufferView HostBuffer::Emplace(const void* buffer, size_t length) {
-  auto [data, range, device_buffer] = EmplaceInternal(buffer, length);
+  auto [range, device_buffer] = EmplaceInternal(buffer, length);
   if (!device_buffer) {
     return {};
   }
-  return BufferView{std::move(device_buffer), data, range};
+  return BufferView{std::move(device_buffer), range};
 }
 
 BufferView HostBuffer::Emplace(size_t length,
                                size_t align,
                                const EmplaceProc& cb) {
-  auto [data, range, device_buffer] = EmplaceInternal(length, align, cb);
+  auto [range, device_buffer] = EmplaceInternal(length, align, cb);
   if (!device_buffer) {
     return {};
   }
-  return BufferView{std::move(device_buffer), data, range};
+  return BufferView{std::move(device_buffer), range};
 }
 
 HostBuffer::TestStateQuery HostBuffer::GetStateForTest() {
@@ -74,10 +74,9 @@
   };
 }
 
-void HostBuffer::MaybeCreateNewBuffer(size_t required_size) {
+void HostBuffer::MaybeCreateNewBuffer() {
   current_buffer_++;
   if (current_buffer_ >= device_buffers_[frame_index_].size()) {
-    FML_DCHECK(required_size <= kAllocatorBlockSize);
     DeviceBufferDescriptor desc;
     desc.size = kAllocatorBlockSize;
     desc.storage_mode = StorageMode::kHostVisible;
@@ -86,10 +85,10 @@
   offset_ = 0;
 }
 
-std::tuple<uint8_t*, Range, std::shared_ptr<DeviceBuffer>>
-HostBuffer::EmplaceInternal(size_t length,
-                            size_t align,
-                            const EmplaceProc& cb) {
+std::tuple<Range, std::shared_ptr<DeviceBuffer>> HostBuffer::EmplaceInternal(
+    size_t length,
+    size_t align,
+    const EmplaceProc& cb) {
   if (!cb) {
     return {};
   }
@@ -108,28 +107,27 @@
       cb(device_buffer->OnGetContents());
       device_buffer->Flush(Range{0, length});
     }
-    return std::make_tuple(device_buffer->OnGetContents(), Range{0, length},
-                           device_buffer);
+    return std::make_tuple(Range{0, length}, device_buffer);
   }
 
   auto old_length = GetLength();
   if (old_length + length > kAllocatorBlockSize) {
-    MaybeCreateNewBuffer(length);
+    MaybeCreateNewBuffer();
   }
   old_length = GetLength();
 
   auto current_buffer = GetCurrentBuffer();
-  cb(current_buffer->OnGetContents() + old_length);
+  auto contents = current_buffer->OnGetContents();
+  cb(contents + old_length);
   current_buffer->Flush(Range{old_length, length});
 
   offset_ += length;
-  auto contents = current_buffer->OnGetContents();
-  return std::make_tuple(contents, Range{old_length, length},
-                         std::move(current_buffer));
+  return std::make_tuple(Range{old_length, length}, std::move(current_buffer));
 }
 
-std::tuple<uint8_t*, Range, std::shared_ptr<DeviceBuffer>>
-HostBuffer::EmplaceInternal(const void* buffer, size_t length) {
+std::tuple<Range, std::shared_ptr<DeviceBuffer>> HostBuffer::EmplaceInternal(
+    const void* buffer,
+    size_t length) {
   // If the requested allocation is bigger than the block size, create a one-off
   // device buffer and write to that.
   if (length > kAllocatorBlockSize) {
@@ -146,38 +144,37 @@
         return {};
       }
     }
-    return std::make_tuple(device_buffer->OnGetContents(), Range{0, length},
-                           device_buffer);
+    return std::make_tuple(Range{0, length}, device_buffer);
   }
 
   auto old_length = GetLength();
   if (old_length + length > kAllocatorBlockSize) {
-    MaybeCreateNewBuffer(length);
+    MaybeCreateNewBuffer();
   }
   old_length = GetLength();
 
   auto current_buffer = GetCurrentBuffer();
+  auto contents = current_buffer->OnGetContents();
   if (buffer) {
-    ::memmove(current_buffer->OnGetContents() + old_length, buffer, length);
+    ::memmove(contents + old_length, buffer, length);
     current_buffer->Flush(Range{old_length, length});
   }
   offset_ += length;
-  auto contents = current_buffer->OnGetContents();
-  return std::make_tuple(contents, Range{old_length, length},
-                         std::move(current_buffer));
+  return std::make_tuple(Range{old_length, length}, std::move(current_buffer));
 }
 
-std::tuple<uint8_t*, Range, std::shared_ptr<DeviceBuffer>>
+std::tuple<Range, std::shared_ptr<DeviceBuffer>>
 HostBuffer::EmplaceInternal(const void* buffer, size_t length, size_t align) {
   if (align == 0 || (GetLength() % align) == 0) {
     return EmplaceInternal(buffer, length);
   }
 
   {
-    auto [buffer, range, device_buffer] =
-        EmplaceInternal(nullptr, align - (GetLength() % align));
-    if (!buffer) {
-      return {};
+    auto padding = align - (GetLength() % align);
+    if (offset_ + padding < kAllocatorBlockSize) {
+      offset_ += padding;
+    } else {
+      MaybeCreateNewBuffer();
     }
   }
 
diff --git a/impeller/core/host_buffer.h b/impeller/core/host_buffer.h
index 16c1180..4ed78d0 100644
--- a/impeller/core/host_buffer.h
+++ b/impeller/core/host_buffer.h
@@ -12,7 +12,7 @@
 #include <string>
 #include <type_traits>
 
-#include "impeller/core/buffer.h"
+#include "impeller/core/allocator.h"
 #include "impeller/core/buffer_view.h"
 #include "impeller/core/platform.h"
 
@@ -134,18 +134,18 @@
   TestStateQuery GetStateForTest();
 
  private:
-  [[nodiscard]] std::tuple<uint8_t*, Range, std::shared_ptr<DeviceBuffer>>
+  [[nodiscard]] std::tuple<Range, std::shared_ptr<DeviceBuffer>>
   EmplaceInternal(const void* buffer, size_t length);
 
-  std::tuple<uint8_t*, Range, std::shared_ptr<DeviceBuffer>>
+  std::tuple<Range, std::shared_ptr<DeviceBuffer>>
   EmplaceInternal(size_t length, size_t align, const EmplaceProc& cb);
 
-  std::tuple<uint8_t*, Range, std::shared_ptr<DeviceBuffer>>
+  std::tuple<Range, std::shared_ptr<DeviceBuffer>>
   EmplaceInternal(const void* buffer, size_t length, size_t align);
 
   size_t GetLength() const { return offset_; }
 
-  void MaybeCreateNewBuffer(size_t required_size);
+  void MaybeCreateNewBuffer();
 
   std::shared_ptr<DeviceBuffer>& GetCurrentBuffer() {
     return device_buffers_[frame_index_][current_buffer_];
diff --git a/impeller/entity/contents/test/contents_test_helpers.h b/impeller/entity/contents/test/contents_test_helpers.h
index 3e0a6d5..e5f33b1 100644
--- a/impeller/entity/contents/test/contents_test_helpers.h
+++ b/impeller/entity/contents/test/contents_test_helpers.h
@@ -21,8 +21,8 @@
     return nullptr;
   }
 
-  auto data =
-      (resource->view.resource.contents + resource->view.resource.range.offset);
+  auto data = (resource->view.resource.buffer->OnGetContents() +
+               resource->view.resource.range.offset);
   return reinterpret_cast<typename T::VertInfo*>(data);
 }
 
@@ -39,8 +39,8 @@
     return nullptr;
   }
 
-  auto data =
-      (resource->view.resource.contents + resource->view.resource.range.offset);
+  auto data = (resource->view.resource.buffer->OnGetContents() +
+               resource->view.resource.range.offset);
   return reinterpret_cast<typename T::FragInfo*>(data);
 }
 
diff --git a/impeller/entity/geometry/point_field_geometry.cc b/impeller/entity/geometry/point_field_geometry.cc
index 2b7a1af..27369da 100644
--- a/impeller/entity/geometry/point_field_geometry.cc
+++ b/impeller/entity/geometry/point_field_geometry.cc
@@ -162,10 +162,8 @@
   buffer_desc.size = total * sizeof(Point);
   buffer_desc.storage_mode = StorageMode::kDevicePrivate;
 
-  auto geometry_buffer = renderer.GetContext()
-                             ->GetResourceAllocator()
-                             ->CreateBuffer(buffer_desc)
-                             ->AsBufferView();
+  auto geometry_buffer = DeviceBuffer::AsBufferView(
+      renderer.GetContext()->GetResourceAllocator()->CreateBuffer(buffer_desc));
 
   BufferView output;
   {
@@ -197,10 +195,9 @@
     buffer_desc.size = total * sizeof(Vector4);
     buffer_desc.storage_mode = StorageMode::kDevicePrivate;
 
-    auto geometry_uv_buffer = renderer.GetContext()
-                                  ->GetResourceAllocator()
-                                  ->CreateBuffer(buffer_desc)
-                                  ->AsBufferView();
+    auto geometry_uv_buffer = DeviceBuffer::AsBufferView(
+        renderer.GetContext()->GetResourceAllocator()->CreateBuffer(
+            buffer_desc));
 
     using UV = UvComputeShader;
 
diff --git a/impeller/playground/playground.cc b/impeller/playground/playground.cc
index 1c6dbfa..c4f4f13 100644
--- a/impeller/playground/playground.cc
+++ b/impeller/playground/playground.cc
@@ -422,7 +422,7 @@
       return nullptr;
     }
     blit_pass->SetLabel("Mipmap Blit Pass");
-    blit_pass->AddCopy(buffer->AsBufferView(), dest_texture);
+    blit_pass->AddCopy(DeviceBuffer::AsBufferView(buffer), dest_texture);
     if (enable_mipmapping) {
       blit_pass->GenerateMipmap(dest_texture);
     }
diff --git a/impeller/renderer/backend/gles/buffer_bindings_gles.cc b/impeller/renderer/backend/gles/buffer_bindings_gles.cc
index 168053e..4be33ce 100644
--- a/impeller/renderer/backend/gles/buffer_bindings_gles.cc
+++ b/impeller/renderer/backend/gles/buffer_bindings_gles.cc
@@ -232,7 +232,7 @@
                                            Allocator& transients_allocator,
                                            const BufferResource& buffer) {
   const auto* metadata = buffer.GetMetadata();
-  auto device_buffer = buffer.resource.buffer->GetDeviceBuffer();
+  auto device_buffer = buffer.resource.buffer;
   if (!device_buffer) {
     VALIDATION_LOG << "Device buffer not found.";
     return false;
diff --git a/impeller/renderer/backend/gles/render_pass_gles.cc b/impeller/renderer/backend/gles/render_pass_gles.cc
index c13dbb1..20b6fd4 100644
--- a/impeller/renderer/backend/gles/render_pass_gles.cc
+++ b/impeller/renderer/backend/gles/render_pass_gles.cc
@@ -386,7 +386,7 @@
       return false;
     }
 
-    auto vertex_buffer = vertex_buffer_view.buffer->GetDeviceBuffer();
+    auto vertex_buffer = vertex_buffer_view.buffer;
 
     if (!vertex_buffer) {
       return false;
@@ -445,7 +445,7 @@
     } else {
       // Bind the index buffer if necessary.
       auto index_buffer_view = command.vertex_buffer.index_buffer;
-      auto index_buffer = index_buffer_view.buffer->GetDeviceBuffer();
+      auto index_buffer = index_buffer_view.buffer;
       const auto& index_buffer_gles = DeviceBufferGLES::Cast(*index_buffer);
       if (!index_buffer_gles.BindAndUploadDataIfNecessary(
               DeviceBufferGLES::BindingType::kElementArrayBuffer)) {
diff --git a/impeller/renderer/backend/metal/allocator_mtl.mm b/impeller/renderer/backend/metal/allocator_mtl.mm
index 1505766..dfae250 100644
--- a/impeller/renderer/backend/metal/allocator_mtl.mm
+++ b/impeller/renderer/backend/metal/allocator_mtl.mm
@@ -7,7 +7,6 @@
 #include "flutter/fml/build_config.h"
 #include "flutter/fml/logging.h"
 #include "impeller/base/validation.h"
-#include "impeller/core/buffer.h"
 #include "impeller/renderer/backend/metal/device_buffer_mtl.h"
 #include "impeller/renderer/backend/metal/formats_mtl.h"
 #include "impeller/renderer/backend/metal/texture_mtl.h"
diff --git a/impeller/renderer/backend/metal/compute_pass_mtl.mm b/impeller/renderer/backend/metal/compute_pass_mtl.mm
index 3f3f7c3..5abab34 100644
--- a/impeller/renderer/backend/metal/compute_pass_mtl.mm
+++ b/impeller/renderer/backend/metal/compute_pass_mtl.mm
@@ -171,7 +171,7 @@
     return false;
   }
 
-  auto device_buffer = view.buffer->GetDeviceBuffer();
+  auto device_buffer = view.buffer;
   if (!device_buffer) {
     return false;
   }
diff --git a/impeller/renderer/backend/metal/device_buffer_mtl.h b/impeller/renderer/backend/metal/device_buffer_mtl.h
index 936bc44..63b5b6d 100644
--- a/impeller/renderer/backend/metal/device_buffer_mtl.h
+++ b/impeller/renderer/backend/metal/device_buffer_mtl.h
@@ -13,8 +13,9 @@
 
 namespace impeller {
 
-class DeviceBufferMTL final : public DeviceBuffer,
-                              public BackendCast<DeviceBufferMTL, Buffer> {
+class DeviceBufferMTL final
+    : public DeviceBuffer,
+      public BackendCast<DeviceBufferMTL, DeviceBuffer> {
  public:
   DeviceBufferMTL();
 
diff --git a/impeller/renderer/backend/metal/render_pass_mtl.mm b/impeller/renderer/backend/metal/render_pass_mtl.mm
index 8b22881..83918f7 100644
--- a/impeller/renderer/backend/metal/render_pass_mtl.mm
+++ b/impeller/renderer/backend/metal/render_pass_mtl.mm
@@ -364,7 +364,7 @@
     return false;
   }
 
-  auto device_buffer = view.buffer->GetDeviceBuffer();
+  auto device_buffer = view.buffer;
   if (!device_buffer) {
     return false;
   }
@@ -508,12 +508,7 @@
     if (!index_buffer) {
       return false;
     }
-    auto device_buffer = index_buffer->GetDeviceBuffer();
-    if (!device_buffer) {
-      return false;
-    }
-    auto mtl_index_buffer =
-        DeviceBufferMTL::Cast(*device_buffer).GetMTLBuffer();
+    auto mtl_index_buffer = DeviceBufferMTL::Cast(*index_buffer).GetMTLBuffer();
     if (!mtl_index_buffer) {
       return false;
     }
diff --git a/impeller/renderer/backend/vulkan/binding_helpers_vk.cc b/impeller/renderer/backend/vulkan/binding_helpers_vk.cc
index 19fe535..cb399d9 100644
--- a/impeller/renderer/backend/vulkan/binding_helpers_vk.cc
+++ b/impeller/renderer/backend/vulkan/binding_helpers_vk.cc
@@ -70,7 +70,7 @@
   for (const BufferAndUniformSlot& data : bindings.buffers) {
     const auto& buffer_view = data.view.resource.buffer;
 
-    auto device_buffer = buffer_view->GetDeviceBuffer();
+    auto device_buffer = buffer_view;
     if (!device_buffer) {
       VALIDATION_LOG << "Failed to get device buffer for vertex binding";
       return false;
diff --git a/impeller/renderer/backend/vulkan/blit_command_vk_unittests.cc b/impeller/renderer/backend/vulkan/blit_command_vk_unittests.cc
index 260c9e4..db4fbdf 100644
--- a/impeller/renderer/backend/vulkan/blit_command_vk_unittests.cc
+++ b/impeller/renderer/backend/vulkan/blit_command_vk_unittests.cc
@@ -54,11 +54,10 @@
       .format = PixelFormat::kR8G8B8A8UNormInt,
       .size = ISize(100, 100),
   });
-  cmd.source = context->GetResourceAllocator()
-                   ->CreateBuffer({
-                       .size = 1,
-                   })
-                   ->AsBufferView();
+  cmd.source =
+      DeviceBuffer::AsBufferView(context->GetResourceAllocator()->CreateBuffer({
+          .size = 1,
+      }));
   bool result = cmd.Encode(*encoder.get());
   EXPECT_TRUE(result);
   EXPECT_TRUE(encoder->IsTracking(cmd.source.buffer));
diff --git a/impeller/renderer/backend/vulkan/command_encoder_vk.cc b/impeller/renderer/backend/vulkan/command_encoder_vk.cc
index 31ab804..4cd2284 100644
--- a/impeller/renderer/backend/vulkan/command_encoder_vk.cc
+++ b/impeller/renderer/backend/vulkan/command_encoder_vk.cc
@@ -48,14 +48,14 @@
     tracked_objects_.insert(std::move(object));
   }
 
-  void Track(std::shared_ptr<const Buffer> buffer) {
+  void Track(std::shared_ptr<const DeviceBuffer> buffer) {
     if (!buffer) {
       return;
     }
     tracked_buffers_.insert(std::move(buffer));
   }
 
-  bool IsTracking(const std::shared_ptr<const Buffer>& buffer) const {
+  bool IsTracking(const std::shared_ptr<const DeviceBuffer>& buffer) const {
     if (!buffer) {
       return false;
     }
@@ -88,7 +88,7 @@
   std::shared_ptr<CommandPoolVK> pool_;
   vk::UniqueCommandBuffer buffer_;
   std::set<std::shared_ptr<SharedObjectVK>> tracked_objects_;
-  std::set<std::shared_ptr<const Buffer>> tracked_buffers_;
+  std::set<std::shared_ptr<const DeviceBuffer>> tracked_buffers_;
   std::set<std::shared_ptr<const TextureSourceVK>> tracked_textures_;
   std::unique_ptr<GPUProbe> probe_;
   bool is_valid_ = false;
@@ -250,7 +250,7 @@
   return true;
 }
 
-bool CommandEncoderVK::Track(std::shared_ptr<const Buffer> buffer) {
+bool CommandEncoderVK::Track(std::shared_ptr<const DeviceBuffer> buffer) {
   if (!IsValid()) {
     return false;
   }
@@ -259,7 +259,7 @@
 }
 
 bool CommandEncoderVK::IsTracking(
-    const std::shared_ptr<const Buffer>& buffer) const {
+    const std::shared_ptr<const DeviceBuffer>& buffer) const {
   if (!IsValid()) {
     return false;
   }
diff --git a/impeller/renderer/backend/vulkan/command_encoder_vk.h b/impeller/renderer/backend/vulkan/command_encoder_vk.h
index 4c682e8..3622447 100644
--- a/impeller/renderer/backend/vulkan/command_encoder_vk.h
+++ b/impeller/renderer/backend/vulkan/command_encoder_vk.h
@@ -64,9 +64,9 @@
 
   bool Track(std::shared_ptr<SharedObjectVK> object);
 
-  bool Track(std::shared_ptr<const Buffer> buffer);
+  bool Track(std::shared_ptr<const DeviceBuffer> buffer);
 
-  bool IsTracking(const std::shared_ptr<const Buffer>& texture) const;
+  bool IsTracking(const std::shared_ptr<const DeviceBuffer>& texture) const;
 
   bool Track(const std::shared_ptr<const Texture>& texture);
 
diff --git a/impeller/renderer/backend/vulkan/device_buffer_vk.h b/impeller/renderer/backend/vulkan/device_buffer_vk.h
index 33182c5..e5603c9 100644
--- a/impeller/renderer/backend/vulkan/device_buffer_vk.h
+++ b/impeller/renderer/backend/vulkan/device_buffer_vk.h
@@ -15,7 +15,7 @@
 namespace impeller {
 
 class DeviceBufferVK final : public DeviceBuffer,
-                             public BackendCast<DeviceBufferVK, Buffer> {
+                             public BackendCast<DeviceBufferVK, DeviceBuffer> {
  public:
   DeviceBufferVK(DeviceBufferDescriptor desc,
                  std::weak_ptr<Context> context,
diff --git a/impeller/renderer/backend/vulkan/render_pass_vk.cc b/impeller/renderer/backend/vulkan/render_pass_vk.cc
index 67066c0..4225436 100644
--- a/impeller/renderer/backend/vulkan/render_pass_vk.cc
+++ b/impeller/renderer/backend/vulkan/render_pass_vk.cc
@@ -410,7 +410,7 @@
   }
 
   auto& allocator = *context.GetResourceAllocator();
-  auto vertex_buffer = vertex_buffer_view.buffer->GetDeviceBuffer();
+  auto vertex_buffer = vertex_buffer_view.buffer;
 
   if (!vertex_buffer) {
     VALIDATION_LOG << "Failed to acquire device buffer"
@@ -435,7 +435,7 @@
       return false;
     }
 
-    auto index_buffer = index_buffer_view.buffer->GetDeviceBuffer();
+    auto index_buffer = index_buffer_view.buffer;
     if (!index_buffer) {
       VALIDATION_LOG << "Failed to acquire device buffer"
                      << " for index buffer view";
diff --git a/impeller/renderer/compute_subgroup_unittests.cc b/impeller/renderer/compute_subgroup_unittests.cc
index e93bec3..49bc9ea 100644
--- a/impeller/renderer/compute_subgroup_unittests.cc
+++ b/impeller/renderer/compute_subgroup_unittests.cc
@@ -71,10 +71,9 @@
                                                            "VertexCount");
 
   auto callback = [&](RenderPass& pass) -> bool {
-    ::memset(vertex_buffer_count->AsBufferView().contents, 0,
+    ::memset(vertex_buffer_count->OnGetContents(), 0,
              sizeof(SS::VertexBufferCount));
-    ::memset(vertex_buffer->AsBufferView().contents, 0,
-             sizeof(SS::VertexBuffer<2048>));
+    ::memset(vertex_buffer->OnGetContents(), 0, sizeof(SS::VertexBuffer<2048>));
     const auto* main_viewport = ImGui::GetMainViewport();
     ImGui::SetNextWindowPos(
         ImVec2(main_viewport->WorkPos.x + 650, main_viewport->WorkPos.y + 20));
@@ -93,18 +92,18 @@
       auto status =
           ComputeTessellator{}
               .SetStrokeWidth(stroke_width)
-              .Tessellate(
-                  path, *host_buffer, context, vertex_buffer->AsBufferView(),
-                  vertex_buffer_count->AsBufferView(),
-                  [vertex_buffer_count, &vertex_count,
-                   &promise](CommandBuffer::Status status) {
-                    vertex_count =
-                        reinterpret_cast<SS::VertexBufferCount*>(
-                            vertex_buffer_count->AsBufferView().contents)
-                            ->count;
-                    promise.set_value(status ==
-                                      CommandBuffer::Status::kCompleted);
-                  });
+              .Tessellate(path, *host_buffer, context,
+                          DeviceBuffer::AsBufferView(vertex_buffer),
+                          DeviceBuffer::AsBufferView(vertex_buffer_count),
+                          [vertex_buffer_count, &vertex_count,
+                           &promise](CommandBuffer::Status status) {
+                            vertex_count =
+                                reinterpret_cast<SS::VertexBufferCount*>(
+                                    vertex_buffer_count->OnGetContents())
+                                    ->count;
+                            promise.set_value(
+                                status == CommandBuffer::Status::kCompleted);
+                          });
       switch (status) {
         case ComputeTessellator::Status::kCommandInvalid:
           ImGui::Text("Failed to submit compute job (invalid command)");
@@ -152,11 +151,11 @@
     cmd.pipeline = renderer.GetSolidFillPipeline(options);
 
     auto count = reinterpret_cast<SS::VertexBufferCount*>(
-                     vertex_buffer_count->AsBufferView().contents)
+                     vertex_buffer_count->OnGetContents())
                      ->count;
 
     cmd.BindVertices(
-        VertexBuffer{.vertex_buffer = vertex_buffer->AsBufferView(),
+        VertexBuffer{.vertex_buffer = DeviceBuffer::AsBufferView(vertex_buffer),
                      .vertex_count = count,
                      .index_type = IndexType::kNone});
 
@@ -313,10 +312,9 @@
           .TakePath();
 
   auto callback = [&](RenderPass& pass) -> bool {
-    ::memset(vertex_buffer_count->AsBufferView().contents, 0,
+    ::memset(vertex_buffer_count->OnGetContents(), 0,
              sizeof(SS::VertexBufferCount));
-    ::memset(vertex_buffer->AsBufferView().contents, 0,
-             sizeof(SS::VertexBuffer<2048>));
+    ::memset(vertex_buffer->OnGetContents(), 0, sizeof(SS::VertexBuffer<2048>));
 
     ContentContext renderer(context, nullptr);
     if (!renderer.IsValid()) {
@@ -327,10 +325,11 @@
         .SetStrokeWidth(stroke_width)
         .Tessellate(
             complex_path, renderer.GetTransientsBuffer(), context,
-            vertex_buffer->AsBufferView(), vertex_buffer_count->AsBufferView(),
+            DeviceBuffer::AsBufferView(vertex_buffer),
+            DeviceBuffer::AsBufferView(vertex_buffer_count),
             [vertex_buffer_count, &vertex_count](CommandBuffer::Status status) {
               vertex_count = reinterpret_cast<SS::VertexBufferCount*>(
-                                 vertex_buffer_count->AsBufferView().contents)
+                                 vertex_buffer_count->OnGetContents())
                                  ->count;
             });
 
@@ -354,11 +353,11 @@
     cmd.pipeline = renderer.GetSolidFillPipeline(options);
 
     auto count = reinterpret_cast<SS::VertexBufferCount*>(
-                     vertex_buffer_count->AsBufferView().contents)
+                     vertex_buffer_count->OnGetContents())
                      ->count;
 
     cmd.BindVertices(
-        VertexBuffer{.vertex_buffer = vertex_buffer->AsBufferView(),
+        VertexBuffer{.vertex_buffer = DeviceBuffer::AsBufferView(vertex_buffer),
                      .vertex_count = count,
                      .index_type = IndexType::kNone});
 
@@ -402,8 +401,8 @@
 
   auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
   auto status = tessellator.Tessellate(
-      path, *host_buffer, context, vertex_buffer->AsBufferView(),
-      vertex_buffer_count->AsBufferView(),
+      path, *host_buffer, context, DeviceBuffer::AsBufferView(vertex_buffer),
+      DeviceBuffer::AsBufferView(vertex_buffer_count),
       [&latch](CommandBuffer::Status status) {
         EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
         latch.Signal();
@@ -437,11 +436,11 @@
     cmd.pipeline = renderer.GetSolidFillPipeline(options);
 
     auto count = reinterpret_cast<SS::VertexBufferCount*>(
-                     vertex_buffer_count->AsBufferView().contents)
+                     vertex_buffer_count->OnGetContents())
                      ->count;
 
     cmd.BindVertices(
-        VertexBuffer{.vertex_buffer = vertex_buffer->AsBufferView(),
+        VertexBuffer{.vertex_buffer = DeviceBuffer::AsBufferView(vertex_buffer),
                      .vertex_count = count,
                      .index_type = IndexType::kNone});
 
@@ -468,11 +467,11 @@
   latch.Wait();
 
   auto vertex_count = reinterpret_cast<SS::VertexBufferCount*>(
-                          vertex_buffer_count->AsBufferView().contents)
+                          vertex_buffer_count->OnGetContents())
                           ->count;
   EXPECT_EQ(vertex_count, golden_cubic_and_quad_points.size());
-  auto vertex_buffer_data = reinterpret_cast<SS::VertexBuffer<2048>*>(
-      vertex_buffer->AsBufferView().contents);
+  auto vertex_buffer_data =
+      reinterpret_cast<SS::VertexBuffer<2048>*>(vertex_buffer->OnGetContents());
   for (size_t i = 0; i < vertex_count; i++) {
     EXPECT_LT(std::abs(golden_cubic_and_quad_points[i].x -
                        vertex_buffer_data->position[i].x),
diff --git a/impeller/renderer/compute_tessellator.cc b/impeller/renderer/compute_tessellator.cc
index 1c6a22f2..ebcf76d 100644
--- a/impeller/renderer/compute_tessellator.cc
+++ b/impeller/renderer/compute_tessellator.cc
@@ -133,7 +133,7 @@
     PS::BindQuads(cmd, host_buffer.EmplaceStorageBuffer(quads));
     PS::BindLines(cmd, host_buffer.EmplaceStorageBuffer(lines));
     PS::BindComponents(cmd, host_buffer.EmplaceStorageBuffer(components));
-    PS::BindPolyline(cmd, polyline_buffer->AsBufferView());
+    PS::BindPolyline(cmd, DeviceBuffer::AsBufferView(polyline_buffer));
 
     if (!pass->AddCommand(std::move(cmd))) {
       return Status::kCommandInvalid;
@@ -164,7 +164,7 @@
     };
     SS::BindConfig(cmd, host_buffer.EmplaceUniform(config));
 
-    SS::BindPolyline(cmd, polyline_buffer->AsBufferView());
+    SS::BindPolyline(cmd, DeviceBuffer::AsBufferView(polyline_buffer));
     SS::BindVertexBufferCount(cmd, std::move(vertex_buffer_count));
     SS::BindVertexBuffer(cmd, std::move(vertex_buffer));
 
diff --git a/impeller/renderer/compute_unittests.cc b/impeller/renderer/compute_unittests.cc
index 03eb268..ce416c6 100644
--- a/impeller/renderer/compute_unittests.cc
+++ b/impeller/renderer/compute_unittests.cc
@@ -79,33 +79,33 @@
   CS::BindInfo(cmd, host_buffer->EmplaceUniform(info));
   CS::BindInput0(cmd, host_buffer->EmplaceStorageBuffer(input_0));
   CS::BindInput1(cmd, host_buffer->EmplaceStorageBuffer(input_1));
-  CS::BindOutput(cmd, output_buffer->AsBufferView());
+  CS::BindOutput(cmd, DeviceBuffer::AsBufferView(output_buffer));
 
   ASSERT_TRUE(pass->AddCommand(std::move(cmd)));
   ASSERT_TRUE(pass->EncodeCommands());
 
   fml::AutoResetWaitableEvent latch;
-  ASSERT_TRUE(
-      cmd_buffer->SubmitCommands([&latch, output_buffer, &input_0,
-                                  &input_1](CommandBuffer::Status status) {
-        EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
+  ASSERT_TRUE(cmd_buffer->SubmitCommands([&latch, output_buffer, &input_0,
+                                          &input_1](
+                                             CommandBuffer::Status status) {
+    EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
 
-        auto view = output_buffer->AsBufferView();
-        EXPECT_EQ(view.range.length, sizeof(CS::Output<kCount>));
+    auto view = DeviceBuffer::AsBufferView(output_buffer);
+    EXPECT_EQ(view.range.length, sizeof(CS::Output<kCount>));
 
-        CS::Output<kCount>* output =
-            reinterpret_cast<CS::Output<kCount>*>(view.contents);
-        EXPECT_TRUE(output);
-        for (size_t i = 0; i < kCount; i++) {
-          Vector4 vector = output->elements[i];
-          Vector4 computed = input_0.elements[i] * input_1.elements[i];
-          EXPECT_EQ(vector, Vector4(computed.x + 2 + input_1.some_struct.i,
-                                    computed.y + 3 + input_1.some_struct.vf.x,
-                                    computed.z + 5 + input_1.some_struct.vf.y,
-                                    computed.w));
-        }
-        latch.Signal();
-      }));
+    CS::Output<kCount>* output =
+        reinterpret_cast<CS::Output<kCount>*>(output_buffer->OnGetContents());
+    EXPECT_TRUE(output);
+    for (size_t i = 0; i < kCount; i++) {
+      Vector4 vector = output->elements[i];
+      Vector4 computed = input_0.elements[i] * input_1.elements[i];
+      EXPECT_EQ(vector,
+                Vector4(computed.x + 2 + input_1.some_struct.i,
+                        computed.y + 3 + input_1.some_struct.vf.x,
+                        computed.z + 5 + input_1.some_struct.vf.y, computed.w));
+    }
+    latch.Signal();
+  }));
 
   latch.Wait();
 }
@@ -147,30 +147,30 @@
       context, "Output Buffer");
 
   CS::BindInputData(cmd, host_buffer->EmplaceStorageBuffer(input_data));
-  CS::BindOutputData(cmd, output_buffer->AsBufferView());
+  CS::BindOutputData(cmd, DeviceBuffer::AsBufferView(output_buffer));
 
   ASSERT_TRUE(pass->AddCommand(std::move(cmd)));
   ASSERT_TRUE(pass->EncodeCommands());
 
   fml::AutoResetWaitableEvent latch;
-  ASSERT_TRUE(cmd_buffer->SubmitCommands(
-      [&latch, output_buffer](CommandBuffer::Status status) {
-        EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
+  ASSERT_TRUE(cmd_buffer->SubmitCommands([&latch, output_buffer](
+                                             CommandBuffer::Status status) {
+    EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
 
-        auto view = output_buffer->AsBufferView();
-        EXPECT_EQ(view.range.length, sizeof(CS::OutputData<kCount>));
+    auto view = DeviceBuffer::AsBufferView(output_buffer);
+    EXPECT_EQ(view.range.length, sizeof(CS::OutputData<kCount>));
 
-        CS::OutputData<kCount>* output =
-            reinterpret_cast<CS::OutputData<kCount>*>(view.contents);
-        EXPECT_TRUE(output);
+    CS::OutputData<kCount>* output = reinterpret_cast<CS::OutputData<kCount>*>(
+        output_buffer->OnGetContents());
+    EXPECT_TRUE(output);
 
-        constexpr uint32_t expected[kCount] = {1, 3, 6, 10, 15};
-        for (size_t i = 0; i < kCount; i++) {
-          auto computed_sum = output->data[i];
-          EXPECT_EQ(computed_sum, expected[i]);
-        }
-        latch.Signal();
-      }));
+    constexpr uint32_t expected[kCount] = {1, 3, 6, 10, 15};
+    for (size_t i = 0; i < kCount; i++) {
+      auto computed_sum = output->data[i];
+      EXPECT_EQ(computed_sum, expected[i]);
+    }
+    latch.Signal();
+  }));
 
   latch.Wait();
 }
@@ -204,25 +204,25 @@
   auto output_buffer = CreateHostVisibleDeviceBuffer<CS::OutputData<kCount>>(
       context, "Output Buffer");
 
-  CS::BindOutputData(cmd, output_buffer->AsBufferView());
+  CS::BindOutputData(cmd, DeviceBuffer::AsBufferView(output_buffer));
 
   ASSERT_TRUE(pass->AddCommand(std::move(cmd)));
   ASSERT_TRUE(pass->EncodeCommands());
 
   fml::AutoResetWaitableEvent latch;
-  ASSERT_TRUE(cmd_buffer->SubmitCommands(
-      [&latch, output_buffer](CommandBuffer::Status status) {
-        EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
+  ASSERT_TRUE(cmd_buffer->SubmitCommands([&latch, output_buffer](
+                                             CommandBuffer::Status status) {
+    EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
 
-        auto view = output_buffer->AsBufferView();
-        EXPECT_EQ(view.range.length, sizeof(CS::OutputData<kCount>));
+    auto view = DeviceBuffer::AsBufferView(output_buffer);
+    EXPECT_EQ(view.range.length, sizeof(CS::OutputData<kCount>));
 
-        CS::OutputData<kCount>* output =
-            reinterpret_cast<CS::OutputData<kCount>*>(view.contents);
-        EXPECT_TRUE(output);
-        EXPECT_EQ(output->data[kCount - 1], kCount - 1);
-        latch.Signal();
-      }));
+    CS::OutputData<kCount>* output = reinterpret_cast<CS::OutputData<kCount>*>(
+        output_buffer->OnGetContents());
+    EXPECT_TRUE(output);
+    EXPECT_EQ(output->data[kCount - 1], kCount - 1);
+    latch.Signal();
+  }));
 
   latch.Wait();
 }
@@ -263,7 +263,7 @@
         context, "Output Buffer");
 
     CS::BindInputData(cmd, host_buffer->EmplaceStorageBuffer(input_data));
-    CS::BindOutputData(cmd, output_buffer->AsBufferView());
+    CS::BindOutputData(cmd, DeviceBuffer::AsBufferView(output_buffer));
 
     pass->AddCommand(std::move(cmd));
     pass->EncodeCommands();
@@ -330,7 +330,7 @@
     cmd.pipeline = compute_pipeline_1;
 
     CS1::BindInput(cmd, host_buffer->EmplaceStorageBuffer(input_1));
-    CS1::BindOutput(cmd, output_buffer_1->AsBufferView());
+    CS1::BindOutput(cmd, DeviceBuffer::AsBufferView(output_buffer_1));
 
     ASSERT_TRUE(pass->AddCommand(std::move(cmd)));
   }
@@ -339,8 +339,8 @@
     ComputeCommand cmd;
     cmd.pipeline = compute_pipeline_2;
 
-    CS1::BindInput(cmd, output_buffer_1->AsBufferView());
-    CS2::BindOutput(cmd, output_buffer_2->AsBufferView());
+    CS1::BindInput(cmd, DeviceBuffer::AsBufferView(output_buffer_1));
+    CS2::BindOutput(cmd, DeviceBuffer::AsBufferView(output_buffer_2));
     ASSERT_TRUE(pass->AddCommand(std::move(cmd)));
   }
 
@@ -353,14 +353,14 @@
     EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
 
     CS1::Output<kCount2>* output_1 = reinterpret_cast<CS1::Output<kCount2>*>(
-        output_buffer_1->AsBufferView().contents);
+        output_buffer_1->OnGetContents());
     EXPECT_TRUE(output_1);
     EXPECT_EQ(output_1->count, 10u);
     EXPECT_THAT(output_1->elements,
                 ::testing::ElementsAre(0, 0, 2, 3, 4, 6, 6, 9, 8, 12));
 
     CS2::Output<kCount2>* output_2 = reinterpret_cast<CS2::Output<kCount2>*>(
-        output_buffer_2->AsBufferView().contents);
+        output_buffer_2->OnGetContents());
     EXPECT_TRUE(output_2);
     EXPECT_EQ(output_2->count, 10u);
     EXPECT_THAT(output_2->elements,
@@ -417,33 +417,33 @@
   CS::BindInfo(cmd, host_buffer->EmplaceUniform(info));
   CS::BindInput0(cmd, host_buffer->EmplaceStorageBuffer(input_0));
   CS::BindInput1(cmd, host_buffer->EmplaceStorageBuffer(input_1));
-  CS::BindOutput(cmd, output_buffer->AsBufferView());
+  CS::BindOutput(cmd, DeviceBuffer::AsBufferView(output_buffer));
 
   ASSERT_TRUE(pass->AddCommand(std::move(cmd)));
   ASSERT_TRUE(pass->EncodeCommands());
 
   fml::AutoResetWaitableEvent latch;
-  ASSERT_TRUE(
-      cmd_buffer->SubmitCommands([&latch, output_buffer, &input_0,
-                                  &input_1](CommandBuffer::Status status) {
-        EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
+  ASSERT_TRUE(cmd_buffer->SubmitCommands([&latch, output_buffer, &input_0,
+                                          &input_1](
+                                             CommandBuffer::Status status) {
+    EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
 
-        auto view = output_buffer->AsBufferView();
-        EXPECT_EQ(view.range.length, sizeof(CS::Output<kCount>));
+    auto view = DeviceBuffer::AsBufferView(output_buffer);
+    EXPECT_EQ(view.range.length, sizeof(CS::Output<kCount>));
 
-        CS::Output<kCount>* output =
-            reinterpret_cast<CS::Output<kCount>*>(view.contents);
-        EXPECT_TRUE(output);
-        for (size_t i = 0; i < kCount; i++) {
-          Vector4 vector = output->elements[i];
-          Vector4 computed = input_0.elements[i] * input_1.elements[i];
-          EXPECT_EQ(vector, Vector4(computed.x + 2 + input_1.some_struct.i,
-                                    computed.y + 3 + input_1.some_struct.vf.x,
-                                    computed.z + 5 + input_1.some_struct.vf.y,
-                                    computed.w));
-        }
-        latch.Signal();
-      }));
+    CS::Output<kCount>* output =
+        reinterpret_cast<CS::Output<kCount>*>(output_buffer->OnGetContents());
+    EXPECT_TRUE(output);
+    for (size_t i = 0; i < kCount; i++) {
+      Vector4 vector = output->elements[i];
+      Vector4 computed = input_0.elements[i] * input_1.elements[i];
+      EXPECT_EQ(vector,
+                Vector4(computed.x + 2 + input_1.some_struct.i,
+                        computed.y + 3 + input_1.some_struct.vf.x,
+                        computed.z + 5 + input_1.some_struct.vf.y, computed.w));
+    }
+    latch.Signal();
+  }));
 
   latch.Wait();
 }
@@ -496,7 +496,7 @@
   CS::BindInfo(cmd, host_buffer->EmplaceUniform(info));
   CS::BindInput0(cmd, host_buffer->EmplaceStorageBuffer(input_0));
   CS::BindInput1(cmd, host_buffer->EmplaceStorageBuffer(input_1));
-  CS::BindOutput(cmd, output_buffer->AsBufferView());
+  CS::BindOutput(cmd, DeviceBuffer::AsBufferView(output_buffer));
 
   ASSERT_TRUE(pass->AddCommand(std::move(cmd)));
   ASSERT_FALSE(pass->EncodeCommands());
diff --git a/impeller/renderer/renderer_unittests.cc b/impeller/renderer/renderer_unittests.cc
index dcc4035..60514ce 100644
--- a/impeller/renderer/renderer_unittests.cc
+++ b/impeller/renderer/renderer_unittests.cc
@@ -688,10 +688,10 @@
         FS::BindFragInfo(cmd, host_buffer->EmplaceUniform(frag_info));
 
         auto sampler = context->GetSamplerLibrary()->GetSampler({});
-        auto buffer_view = device_buffer->AsBufferView();
+        auto buffer_view = DeviceBuffer::AsBufferView(device_buffer);
         auto texture =
             context->GetResourceAllocator()->CreateTexture(texture_desc);
-        if (!texture->SetContents(buffer_view.contents,
+        if (!texture->SetContents(device_buffer->OnGetContents(),
                                   buffer_view.range.length)) {
           VALIDATION_LOG << "Could not upload texture to device memory";
           return false;
diff --git a/impeller/renderer/vertex_buffer_builder.h b/impeller/renderer/vertex_buffer_builder.h
index 78a780b..98ca510 100644
--- a/impeller/renderer/vertex_buffer_builder.h
+++ b/impeller/renderer/vertex_buffer_builder.h
@@ -127,7 +127,7 @@
     if (!label_.empty()) {
       buffer->SetLabel(SPrintF("%s Vertices", label_.c_str()));
     }
-    return buffer->AsBufferView();
+    return DeviceBuffer::AsBufferView(buffer);
   }
 
   std::vector<IndexType> CreateIndexBuffer() const { return indices_; }
@@ -156,7 +156,7 @@
     if (!label_.empty()) {
       buffer->SetLabel(SPrintF("%s Indices", label_.c_str()));
     }
-    return buffer->AsBufferView();
+    return DeviceBuffer::AsBufferView(buffer);
   }
 };
 
diff --git a/lib/ui/painting/image_decoder_impeller.cc b/lib/ui/painting/image_decoder_impeller.cc
index 0238044..e577b7a 100644
--- a/lib/ui/painting/image_decoder_impeller.cc
+++ b/lib/ui/painting/image_decoder_impeller.cc
@@ -333,7 +333,8 @@
     return std::make_pair(nullptr, decode_error);
   }
   blit_pass->SetLabel("Mipmap Blit Pass");
-  blit_pass->AddCopy(buffer->AsBufferView(), dest_texture);
+  blit_pass->AddCopy(impeller::DeviceBuffer::AsBufferView(buffer),
+                     dest_texture);
   if (texture_descriptor.size.MipCount() > 1) {
     blit_pass->GenerateMipmap(dest_texture);
   }
diff --git a/lib/ui/painting/image_encoding_impeller.cc b/lib/ui/painting/image_encoding_impeller.cc
index 0801f79..a0b61da 100644
--- a/lib/ui/painting/image_encoding_impeller.cc
+++ b/lib/ui/painting/image_encoding_impeller.cc
@@ -34,7 +34,7 @@
     const std::shared_ptr<impeller::DeviceBuffer>& buffer,
     SkColorType color_type,
     SkISize dimensions) {
-  auto buffer_view = buffer->AsBufferView();
+  auto buffer_view = impeller::DeviceBuffer::AsBufferView(buffer);
 
   SkImageInfo image_info = SkImageInfo::Make(dimensions, color_type,
                                              SkAlphaType::kPremul_SkAlphaType);
@@ -47,7 +47,7 @@
     delete buffer;
   };
   auto bytes_per_pixel = image_info.bytesPerPixel();
-  bitmap.installPixels(image_info, buffer_view.contents,
+  bitmap.installPixels(image_info, buffer->OnGetContents(),
                        dimensions.width() * bytes_per_pixel, func,
                        new std::shared_ptr<impeller::DeviceBuffer>(buffer));
   bitmap.setImmutable();