diff --git a/garnet/bin/ui/meta/gfx_unittests.cmx b/garnet/bin/ui/meta/gfx_unittests.cmx
index 14675aaafb0cec7a887e68ef49dfb77ea7d4eda5..ce55b9f4c87c914e4cc1819f7b1e2724b3bd5272 100644
--- a/garnet/bin/ui/meta/gfx_unittests.cmx
+++ b/garnet/bin/ui/meta/gfx_unittests.cmx
@@ -2,6 +2,7 @@
     "facets": {
         "fuchsia.test": {
             "injected-services": {
+                "fuchsia.sysmem.Allocator": "fuchsia-pkg://fuchsia.com/sysmem_connector#meta/sysmem_connector.cmx",
                 "fuchsia.vulkan.loader.Loader": "fuchsia-pkg://fuchsia.com/vulkan_loader#meta/vulkan_loader.cmx"
             }
         }
@@ -16,6 +17,7 @@
         "services": [
             "fuchsia.process.Launcher",
             "fuchsia.scheduler.ProfileProvider",
+            "fuchsia.sysmem.Allocator",
             "fuchsia.tracelink.Registry",
             "fuchsia.vulkan.loader.Loader"
         ]
diff --git a/garnet/lib/ui/gfx/resources/buffer.cc b/garnet/lib/ui/gfx/resources/buffer.cc
index 4bd0ef28c88fa2dd27c3e00a7efff7f5cbfbb618..40716c2160fed5d69e1973e9c78b035dc6b481a0 100644
--- a/garnet/lib/ui/gfx/resources/buffer.cc
+++ b/garnet/lib/ui/gfx/resources/buffer.cc
@@ -19,6 +19,8 @@ Buffer::Buffer(Session* session, ResourceId id, escher::GpuMemPtr gpu_mem,
       escher_buffer_(escher::impl::NaiveBuffer::New(
           session->resource_context().escher_resource_recycler,
           std::move(gpu_mem),
+          // TODO(SCN-1369): Clients have no way to know this set of bits, and
+          // yet our code assumes that the imported VMO will bind successfully.
           vk::BufferUsageFlagBits::eTransferSrc |
               vk::BufferUsageFlagBits::eTransferDst |
               vk::BufferUsageFlagBits::eStorageTexelBuffer |
diff --git a/garnet/lib/ui/gfx/tests/session_unittest.cc b/garnet/lib/ui/gfx/tests/session_unittest.cc
index 22b823b52f3806cfa5e7d0812c2f50bc30ec029b..9062db5ef97bff84935b61bc0f1f15fafb152780 100644
--- a/garnet/lib/ui/gfx/tests/session_unittest.cc
+++ b/garnet/lib/ui/gfx/tests/session_unittest.cc
@@ -8,11 +8,9 @@
 #include "garnet/lib/ui/gfx/resources/shapes/circle_shape.h"
 #include "garnet/lib/ui/gfx/tests/session_test.h"
 #include "garnet/lib/ui/gfx/tests/vk_session_test.h"
-#include "public/lib/escher/test/gtest_vulkan.h"
-
-#include "lib/ui/scenic/cpp/commands.h"
-
 #include "gtest/gtest.h"
+#include "lib/ui/scenic/cpp/commands.h"
+#include "public/lib/escher/test/gtest_vulkan.h"
 
 namespace scenic_impl {
 namespace gfx {
@@ -106,23 +104,52 @@ TEST_F(SessionTest, Labeling) {
 using BufferSessionTest = VkSessionTest;
 
 VK_TEST_F(BufferSessionTest, BufferAliasing) {
-  size_t vmo_size = 1024;
-  size_t offset = 512;
-
-  zx::vmo vmo;
-  zx_status_t status = zx::vmo::create(vmo_size, 0u, &vmo);
-  EXPECT_TRUE(status == ZX_OK);
+  const size_t kVmoSize = 1024;
+  const size_t kOffset = 512;
+
+  auto vulkan_queues = CreateVulkanDeviceQueues();
+  auto device = vulkan_queues->vk_device();
+  auto physical_device = vulkan_queues->vk_physical_device();
+
+  // TODO(SCN-1369): Scenic may use a different set of bits when creating a
+  // buffer, resulting in a memory pool mismatch.
+  const vk::BufferUsageFlags kUsageFlags =
+      vk::BufferUsageFlagBits::eTransferSrc |
+      vk::BufferUsageFlagBits::eTransferDst |
+      vk::BufferUsageFlagBits::eStorageTexelBuffer |
+      vk::BufferUsageFlagBits::eStorageBuffer |
+      vk::BufferUsageFlagBits::eIndexBuffer |
+      vk::BufferUsageFlagBits::eVertexBuffer;
+
+  auto memory_requirements =
+      GetBufferRequirements(device, kVmoSize, kUsageFlags);
+  auto memory =
+      AllocateExportableMemory(device, physical_device, memory_requirements,
+                               vk::MemoryPropertyFlagBits::eDeviceLocal |
+                                   vk::MemoryPropertyFlagBits::eHostVisible);
+
+  // If we can't make memory that is both host-visible and device-local, we
+  // can't run this test.
+  if (!memory) {
+    device.freeMemory(memory);
+    FXL_LOG(INFO)
+        << "Could not find UMA compatible memory pool, aborting test.";
+    return;
+  }
+
+  zx::vmo vmo =
+      ExportMemoryAsVmo(device, vulkan_queues->dispatch_loader(), memory);
 
   zx::vmo dup_vmo;
-  status = vmo.duplicate(ZX_RIGHT_SAME_RIGHTS, &dup_vmo);
-  EXPECT_TRUE(status == ZX_OK);
+  zx_status_t status = vmo.duplicate(ZX_RIGHT_SAME_RIGHTS, &dup_vmo);
+  ASSERT_EQ(ZX_OK, status);
 
   EXPECT_TRUE(Apply(
-      scenic::NewCreateMemoryCmd(1, std::move(dup_vmo), vmo_size,
+      scenic::NewCreateMemoryCmd(1, std::move(dup_vmo), kVmoSize,
                                  fuchsia::images::MemoryType::HOST_MEMORY)));
-  EXPECT_TRUE(Apply(scenic::NewCreateBufferCmd(2, 1, 0, vmo_size)));
+  EXPECT_TRUE(Apply(scenic::NewCreateBufferCmd(2, 1, 0, kVmoSize)));
   EXPECT_TRUE(
-      Apply(scenic::NewCreateBufferCmd(3, 1, offset, vmo_size - offset)));
+      Apply(scenic::NewCreateBufferCmd(3, 1, kOffset, kVmoSize - kOffset)));
 
   auto base_buffer = FindResource<Buffer>(2);
   auto offset_buffer = FindResource<Buffer>(3);
@@ -140,11 +167,12 @@ VK_TEST_F(BufferSessionTest, BufferAliasing) {
   uint8_t* raw_memory = static_cast<uint8_t*>(shared_vmo->Map());
   EXPECT_TRUE(raw_memory);
 
-  memset(raw_memory, 0, vmo_size);
-  raw_memory[512] = 1;
+  memset(raw_memory, 0, kVmoSize);
+  raw_memory[kOffset] = 1;
   EXPECT_EQ(base_buffer->escher_buffer()->host_ptr()[0], 0);
-  EXPECT_EQ(base_buffer->escher_buffer()->host_ptr()[512], 1);
+  EXPECT_EQ(base_buffer->escher_buffer()->host_ptr()[kOffset], 1);
   EXPECT_EQ(offset_buffer->escher_buffer()->host_ptr()[0], 1);
+  device.freeMemory(memory);
 }
 
 // TODO:
diff --git a/garnet/lib/ui/gfx/tests/vk_session_test.cc b/garnet/lib/ui/gfx/tests/vk_session_test.cc
index 60be432ba4183174c1ed5935e3d56bbedd42e212..a7ec3efdb5630b78813e21863c349daa453d00f9 100644
--- a/garnet/lib/ui/gfx/tests/vk_session_test.cc
+++ b/garnet/lib/ui/gfx/tests/vk_session_test.cc
@@ -3,30 +3,93 @@
 // found in the LICENSE file.
 
 #include "garnet/lib/ui/gfx/tests/vk_session_test.h"
+
 #include "garnet/lib/ui/gfx/util/vulkan_utils.h"
+#include "garnet/public/lib/escher/impl/vulkan_utils.h"
+
+using namespace escher;
 
 namespace scenic_impl {
 namespace gfx {
 namespace test {
 
-std::unique_ptr<SessionForTest> VkSessionTest::CreateSession() {
-  SessionContext session_context = CreateBarebonesSessionContext();
+VulkanDeviceQueuesPtr VkSessionTest::CreateVulkanDeviceQueues() {
+  VulkanInstance::Params instance_params(
+      {{"VK_LAYER_LUNARG_standard_validation"},
+       {VK_EXT_DEBUG_REPORT_EXTENSION_NAME,
+        VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME},
+       false});
 
-  // Initialize Vulkan.
-  escher::VulkanInstance::Params instance_params(
-      {{}, {VK_EXT_DEBUG_REPORT_EXTENSION_NAME}, false});
+  auto vulkan_instance = VulkanInstance::New(std::move(instance_params));
+  // This extension is necessary to support exporting Vulkan memory to a VMO.
+  return VulkanDeviceQueues::New(
+      vulkan_instance, {{VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME,
+                         VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME,
+                         VK_FUCHSIA_EXTERNAL_MEMORY_EXTENSION_NAME,
+                         VK_FUCHSIA_EXTERNAL_SEMAPHORE_EXTENSION_NAME},
+                        vk::SurfaceKHR()});
+}
+
+vk::DeviceMemory VkSessionTest::AllocateExportableMemory(
+    vk::Device device, vk::PhysicalDevice physical_device,
+    vk::MemoryRequirements requirements, vk::MemoryPropertyFlags flags) {
+  uint32_t memory_type_index = impl::GetMemoryTypeIndex(
+      physical_device, requirements.memoryTypeBits, flags);
+  vk::PhysicalDeviceMemoryProperties memory_types =
+      physical_device.getMemoryProperties();
+  if (memory_type_index == memory_types.memoryTypeCount) {
+    return nullptr;
+  }
 
-  instance_params.layer_names.insert("VK_LAYER_LUNARG_standard_validation");
-  auto vulkan_instance =
-      escher::VulkanInstance::New(std::move(instance_params));
-  auto vulkan_device = escher::VulkanDeviceQueues::New(
-      vulkan_instance,
-      {{VK_FUCHSIA_EXTERNAL_SEMAPHORE_EXTENSION_NAME}, vk::SurfaceKHR()});
+  vk::ExportMemoryAllocateInfoKHR export_info;
+  export_info.handleTypes =
+      vk::ExternalMemoryHandleTypeFlagBits::eTempZirconVmoFUCHSIA;
 
-  escher_ = std::make_unique<escher::Escher>(vulkan_device);
-  release_fence_signaller_ = std::make_unique<escher::ReleaseFenceSignaller>(
+  vk::MemoryAllocateInfo info;
+  info.pNext = &export_info;
+  info.allocationSize = requirements.size;
+  info.memoryTypeIndex = memory_type_index;
+
+  vk::DeviceMemory memory =
+      ESCHER_CHECKED_VK_RESULT(device.allocateMemory(info));
+  return memory;
+}
+
+zx::vmo VkSessionTest::ExportMemoryAsVmo(
+    vk::Device device, vk::DispatchLoaderDynamic dispatch_loader,
+    vk::DeviceMemory memory) {
+  vk::MemoryGetZirconHandleInfoFUCHSIA export_memory_info(
+      memory, vk::ExternalMemoryHandleTypeFlagBits::eTempZirconVmoFUCHSIA);
+  auto result =
+      device.getMemoryZirconHandleFUCHSIA(export_memory_info, dispatch_loader);
+  if (result.result != vk::Result::eSuccess) {
+    FXL_LOG(ERROR) << "Failed to export vk::DeviceMemory as zx::vmo";
+    return zx::vmo();
+  }
+  return zx::vmo(result.value);
+}
+
+vk::MemoryRequirements VkSessionTest::GetBufferRequirements(
+    vk::Device device, vk::DeviceSize size, vk::BufferUsageFlags usage_flags) {
+  // Create a temp buffer to find out memory requirements.
+  vk::BufferCreateInfo buffer_create_info;
+  buffer_create_info.size = size;
+  buffer_create_info.usage = usage_flags;
+  buffer_create_info.sharingMode = vk::SharingMode::eExclusive;
+  auto vk_buffer =
+      escher::ESCHER_CHECKED_VK_RESULT(device.createBuffer(buffer_create_info));
+  auto retval = device.getBufferMemoryRequirements(vk_buffer);
+  device.destroyBuffer(vk_buffer);
+  return retval;
+}
+
+std::unique_ptr<SessionForTest> VkSessionTest::CreateSession() {
+  SessionContext session_context = CreateBarebonesSessionContext();
+  auto vulkan_device = CreateVulkanDeviceQueues();
+  escher_ = std::make_unique<Escher>(vulkan_device);
+  release_fence_signaller_ = std::make_unique<ReleaseFenceSignaller>(
       escher_->command_buffer_sequencer());
-  image_factory_ = std::make_unique<escher::ImageFactoryAdapter>(
+  image_factory_ = std::make_unique<ImageFactoryAdapter>(
       escher_->gpu_allocator(), escher_->resource_recycler());
 
   session_context.vk_device = escher_->vk_device();
diff --git a/garnet/lib/ui/gfx/tests/vk_session_test.h b/garnet/lib/ui/gfx/tests/vk_session_test.h
index 7eb8b7db6cca14c8208757b9659f726d630a3207..b42540cfac2ea21b9f028f55303b1fd5eb9add85 100644
--- a/garnet/lib/ui/gfx/tests/vk_session_test.h
+++ b/garnet/lib/ui/gfx/tests/vk_session_test.h
@@ -13,6 +13,16 @@ namespace test {
 
 class VkSessionTest : public SessionTest {
  public:
+  static escher::VulkanDeviceQueuesPtr CreateVulkanDeviceQueues();
+  static vk::DeviceMemory AllocateExportableMemory(
+      vk::Device device, vk::PhysicalDevice physical_device,
+      vk::MemoryRequirements requirements, vk::MemoryPropertyFlags flags);
+  static zx::vmo ExportMemoryAsVmo(vk::Device device,
+                                   vk::DispatchLoaderDynamic dispatch_loader,
+                                   vk::DeviceMemory memory);
+  static vk::MemoryRequirements GetBufferRequirements(
+      vk::Device device, vk::DeviceSize size, vk::BufferUsageFlags usage_flags);
+
   // |SessionTest|
   std::unique_ptr<SessionForTest> CreateSession() override;
 
diff --git a/garnet/public/lib/escher/test/vk/buffer_unittest.cc b/garnet/public/lib/escher/test/vk/buffer_unittest.cc
index e587b83e656e0495e8cc73d8dea49b599f7b7d70..0a4ed5c525ea4f36de1c8f0c6fdd39764cdef6ce 100644
--- a/garnet/public/lib/escher/test/vk/buffer_unittest.cc
+++ b/garnet/public/lib/escher/test/vk/buffer_unittest.cc
@@ -15,6 +15,8 @@ VK_TEST(BufferTest, CreateWithPreExistingMemory) {
   auto recycler = escher->resource_recycler();
 
   constexpr vk::DeviceSize kDummyBufferSize = 10000;
+  // TODO(SCN-1369): Scenic may use a different set of bits when creating a
+  // buffer, resulting in a memory pool mismatch.
   const auto kBufferUsageFlags = vk::BufferUsageFlagBits::eTransferSrc |
                                  vk::BufferUsageFlagBits::eTransferDst;
   const auto kMemoryPropertyFlags = vk::MemoryPropertyFlagBits::eHostVisible |