Do not try to add transfer src/dst for all buffers

It seems that adding transfer src/dst usages to uniform buffers will
make Chrome less stable. Remove them and rely on memory snapshot to
snapshot buffer contents.

Bug: 342414479
Test: GfxstreamEnd2EndVkSnapshotPipelineTest
Change-Id: Ie9572a7e8f015378f89f106ec628647836513d8e
diff --git a/common/end2end/GfxstreamEnd2EndVkSnapshotBufferTests.cpp b/common/end2end/GfxstreamEnd2EndVkSnapshotBufferTests.cpp
index dbc043a..cc177f7 100644
--- a/common/end2end/GfxstreamEnd2EndVkSnapshotBufferTests.cpp
+++ b/common/end2end/GfxstreamEnd2EndVkSnapshotBufferTests.cpp
@@ -31,7 +31,7 @@
 
 class GfxstreamEnd2EndVkSnapshotBufferTest : public GfxstreamEnd2EndTest {};
 
-TEST_P(GfxstreamEnd2EndVkSnapshotBufferTest, BufferContent) {
+TEST_P(GfxstreamEnd2EndVkSnapshotBufferTest, DeviceLocalBufferContent) {
     static constexpr vkhpp::DeviceSize kSize = 256;
 
     std::vector<uint8_t> srcBufferContent(kSize);
@@ -86,7 +86,9 @@
     // Vertex buffer
     const vkhpp::BufferCreateInfo vertexBufferCreateInfo = {
         .size = static_cast<VkDeviceSize>(kSize),
-        .usage = vkhpp::BufferUsageFlagBits::eVertexBuffer,
+        .usage = vkhpp::BufferUsageFlagBits::eVertexBuffer |
+                 vkhpp::BufferUsageFlagBits::eTransferSrc |
+                 vkhpp::BufferUsageFlagBits::eTransferDst,
         .sharingMode = vkhpp::SharingMode::eExclusive,
     };
     auto vertexBuffer = device->createBufferUnique(vertexBufferCreateInfo).value;
@@ -95,9 +97,9 @@
     vkhpp::MemoryRequirements vertexBufferMemoryRequirements{};
     device->getBufferMemoryRequirements(*vertexBuffer, &vertexBufferMemoryRequirements);
 
-    const auto vertexBufferMemoryType = utils::getMemoryType(
-        physicalDevice, vertexBufferMemoryRequirements,
-        vkhpp::MemoryPropertyFlagBits::eHostVisible | vkhpp::MemoryPropertyFlagBits::eHostCoherent);
+    const auto vertexBufferMemoryType =
+        utils::getMemoryType(physicalDevice, vertexBufferMemoryRequirements,
+                             vkhpp::MemoryPropertyFlagBits::eDeviceLocal);
 
     // Vertex memory
     const vkhpp::MemoryAllocateInfo vertexBufferMemoryAllocateInfo = {
@@ -214,6 +216,69 @@
     device->unmapMemory(*readbackBufferMemory);
 }
 
+TEST_P(GfxstreamEnd2EndVkSnapshotBufferTest, HostVisibleBufferContent) {
+    static constexpr vkhpp::DeviceSize kSize = 256;
+
+    std::vector<uint8_t> srcBufferContent(kSize);
+    for (size_t i = 0; i < kSize; i++) {
+        srcBufferContent[i] = static_cast<uint8_t>(i & 0xff);
+    }
+    auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
+        VK_ASSERT(SetUpTypicalVkTestEnvironment());
+
+    // Vertex buffer
+    const vkhpp::BufferCreateInfo uniformBufferCreateInfo = {
+        .size = static_cast<VkDeviceSize>(kSize),
+        .usage = vkhpp::BufferUsageFlagBits::eUniformBuffer,
+        .sharingMode = vkhpp::SharingMode::eExclusive,
+    };
+    auto uniformBuffer = device->createBufferUnique(uniformBufferCreateInfo).value;
+    ASSERT_THAT(uniformBuffer, IsValidHandle());
+
+    vkhpp::MemoryRequirements uniformBufferMemoryRequirements{};
+    device->getBufferMemoryRequirements(*uniformBuffer, &uniformBufferMemoryRequirements);
+
+    const auto uniformBufferMemoryType = utils::getMemoryType(
+        physicalDevice, uniformBufferMemoryRequirements,
+        vkhpp::MemoryPropertyFlagBits::eHostVisible | vkhpp::MemoryPropertyFlagBits::eHostCoherent);
+
+    // Vertex memory
+    const vkhpp::MemoryAllocateInfo uniformBufferMemoryAllocateInfo = {
+        .allocationSize = uniformBufferMemoryRequirements.size,
+        .memoryTypeIndex = uniformBufferMemoryType,
+    };
+    auto uniformBufferMemory = device->allocateMemoryUnique(uniformBufferMemoryAllocateInfo).value;
+    ASSERT_THAT(uniformBufferMemory, IsValidHandle());
+    ASSERT_THAT(device->bindBufferMemory(*uniformBuffer, *uniformBufferMemory, 0), IsVkSuccess());
+
+    // Fill memory content
+    void* mapped = nullptr;
+    auto mapResult =
+        device->mapMemory(*uniformBufferMemory, 0, VK_WHOLE_SIZE, vkhpp::MemoryMapFlags{}, &mapped);
+    ASSERT_THAT(mapResult, IsVkSuccess());
+    ASSERT_THAT(mapped, NotNull());
+
+    auto* bytes = reinterpret_cast<uint8_t*>(mapped);
+    std::memcpy(bytes, srcBufferContent.data(), kSize);
+
+    device->unmapMemory(*uniformBufferMemory);
+
+    // We need to unmap before snapshot due to limitations of the testing framework.
+    SnapshotSaveAndLoad();
+
+    // Verify content
+    mapResult =
+        device->mapMemory(*uniformBufferMemory, 0, VK_WHOLE_SIZE, vkhpp::MemoryMapFlags{}, &mapped);
+    ASSERT_THAT(mapResult, IsVkSuccess());
+    ASSERT_THAT(mapped, NotNull());
+    bytes = reinterpret_cast<uint8_t*>(mapped);
+
+    for (uint32_t i = 0; i < kSize; ++i) {
+        ASSERT_THAT(bytes[i], Eq(srcBufferContent[i]));
+    }
+    device->unmapMemory(*uniformBufferMemory);
+}
+
 INSTANTIATE_TEST_CASE_P(GfxstreamEnd2EndTests, GfxstreamEnd2EndVkSnapshotBufferTest,
                         ::testing::ValuesIn({
                             TestParams{
diff --git a/host/vulkan/VkDecoderGlobalState.cpp b/host/vulkan/VkDecoderGlobalState.cpp
index 5298e60..6d90792 100644
--- a/host/vulkan/VkDecoderGlobalState.cpp
+++ b/host/vulkan/VkDecoderGlobalState.cpp
@@ -1906,8 +1906,19 @@
         VkBufferCreateInfo localCreateInfo;
         if (snapshotsEnabled()) {
             localCreateInfo = *pCreateInfo;
-            localCreateInfo.usage |=
-                VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+            // Add transfer src bit for potential device local memories.
+            //
+            // There are 3 ways to populate buffer content:
+            //   a) use host coherent memory and memory mapping;
+            //   b) use transfer_dst and vkcmdcopy* (for device local memories);
+            //   c) use storage and compute shaders.
+            //
+            // (a) is covered by memory snapshot. (b) requires an extra vkCmdCopyBuffer
+            // command on snapshot, thuse we need to add transfer_src for (b) so that
+            // they could be loaded back on snapshot save. (c) is still future work.
+            if (localCreateInfo.usage & VK_BUFFER_USAGE_TRANSFER_DST_BIT) {
+                localCreateInfo.usage |= VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
+            }
             pCreateInfo = &localCreateInfo;
         }
 
@@ -1917,6 +1928,7 @@
             std::lock_guard<std::recursive_mutex> lock(mLock);
             auto& bufInfo = mBufferInfo[*pBuffer];
             bufInfo.device = device;
+            bufInfo.usage = pCreateInfo->usage;
             bufInfo.size = pCreateInfo->size;
             *pBuffer = new_boxed_non_dispatchable_VkBuffer(*pBuffer);
         }
diff --git a/host/vulkan/VkDecoderInternalStructs.h b/host/vulkan/VkDecoderInternalStructs.h
index eab6656..dc352de 100644
--- a/host/vulkan/VkDecoderInternalStructs.h
+++ b/host/vulkan/VkDecoderInternalStructs.h
@@ -228,6 +228,7 @@
 
 struct BufferInfo {
     VkDevice device;
+    VkBufferUsageFlags usage;
     VkDeviceMemory memory = 0;
     VkDeviceSize memoryOffset = 0;
     VkDeviceSize size;
diff --git a/host/vulkan/VkDecoderSnapshotUtils.cpp b/host/vulkan/VkDecoderSnapshotUtils.cpp
index d8510ed..2359fe8 100644
--- a/host/vulkan/VkDecoderSnapshotUtils.cpp
+++ b/host/vulkan/VkDecoderSnapshotUtils.cpp
@@ -475,6 +475,11 @@
 
 void saveBufferContent(android::base::Stream* stream, StateBlock* stateBlock, VkBuffer buffer,
                        const BufferInfo* bufferInfo) {
+    VkBufferUsageFlags requiredUsages =
+        VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+    if ((bufferInfo->usage & requiredUsages) != requiredUsages) {
+        return;
+    }
     VulkanDispatch* dispatch = stateBlock->deviceDispatch;
     VkCommandBufferAllocateInfo allocInfo{
         .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
@@ -573,6 +578,11 @@
 
 void loadBufferContent(android::base::Stream* stream, StateBlock* stateBlock, VkBuffer buffer,
                        const BufferInfo* bufferInfo) {
+    VkBufferUsageFlags requiredUsages =
+        VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+    if ((bufferInfo->usage & requiredUsages) != requiredUsages) {
+        return;
+    }
     VulkanDispatch* dispatch = stateBlock->deviceDispatch;
     VkCommandBufferAllocateInfo allocInfo{
         .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,