Merge "Add tests (initially disabled) testing sync obj usage in ANI" into main

GitOrigin-RevId: d181c34dad474f23fa744353997020c7109f70c5
Change-Id: I846051b5579c4fdf3a59cff603baf6851b4a50c0
diff --git a/common/end2end/GfxstreamEnd2EndTests.h b/common/end2end/GfxstreamEnd2EndTests.h
index 783bc3c..37051f2 100644
--- a/common/end2end/GfxstreamEnd2EndTests.h
+++ b/common/end2end/GfxstreamEnd2EndTests.h
@@ -150,13 +150,22 @@
     std::move(vkhpp_result_value.value);                                      \
   })
 
-#define VK_TRY(x)                                                             \
-  ({                                                                          \
-    auto vkhpp_result = (x);                                                  \
-    if (vkhpp_result != vkhpp::Result::eSuccess) {                            \
-        return vkhpp_result;                                                  \
-    }                                                                         \
-  })
+#define VK_TRY(x)                                                                   \
+    ({                                                                              \
+        auto vk_try_android_base_expected = (x);                                    \
+        if (!vk_try_android_base_expected.ok()) {                                   \
+            return android::base::unexpected(vk_try_android_base_expected.error()); \
+        }                                                                           \
+        std::move(vk_try_android_base_expected.value());                            \
+    })
+
+#define VK_TRY_RESULT(x)                               \
+    ({                                                 \
+        auto vkhpp_result = (x);                       \
+        if (vkhpp_result != vkhpp::Result::eSuccess) { \
+            return vkhpp_result;                       \
+        }                                              \
+    })
 
 #define VK_TRY_RV(x)                                                          \
   ({                                                                          \
diff --git a/common/end2end/GfxstreamEnd2EndVkTests.cpp b/common/end2end/GfxstreamEnd2EndVkTests.cpp
index 2400994..87529ea 100644
--- a/common/end2end/GfxstreamEnd2EndVkTests.cpp
+++ b/common/end2end/GfxstreamEnd2EndVkTests.cpp
@@ -37,7 +37,88 @@
     return static_cast<uint64_t>(std::chrono::duration_cast<std::chrono::nanoseconds>(duration).count());
 }
 
-class GfxstreamEnd2EndVkTest : public GfxstreamEnd2EndTest {};
+class GfxstreamEnd2EndVkTest : public GfxstreamEnd2EndTest {
+   protected:
+    // Gfxstream uses a vkQueueSubmit() to signal the VkFence and VkSemaphore used
+    // in vkAcquireImageANDROID() calls. The guest is not aware of this and may try
+    // to vkDestroyFence() and vkDestroySemaphore() (because the VkImage, VkFence,
+    // and VkSemaphore may have been unused from the guest point of view) while the
+    // host's command buffer is running. Gfxstream needs to ensure that it performs
+    // the necessary tracking to not delete the VkFence and VkSemaphore while they
+    // are in use on the host.
+    void DoAcquireImageAndroidWithSync(bool withFence, bool withSemaphore) {
+        auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
+            VK_ASSERT(SetUpTypicalVkTestEnvironment());
+
+        const uint32_t width = 32;
+        const uint32_t height = 32;
+        auto ahb = GL_ASSERT(ScopedAHardwareBuffer::Allocate(*mGralloc, width, height,
+                                                             GFXSTREAM_AHB_FORMAT_R8G8B8A8_UNORM));
+
+        const VkNativeBufferANDROID imageNativeBufferInfo = {
+            .sType = VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID,
+            .handle = mGralloc->getNativeHandle(ahb),
+        };
+
+        auto vkAcquireImageANDROID =
+            PFN_vkAcquireImageANDROID(device->getProcAddr("vkAcquireImageANDROID"));
+        ASSERT_THAT(vkAcquireImageANDROID, NotNull());
+
+        const vkhpp::ImageCreateInfo imageCreateInfo = {
+            .pNext = &imageNativeBufferInfo,
+            .imageType = vkhpp::ImageType::e2D,
+            .extent.width = width,
+            .extent.height = height,
+            .extent.depth = 1,
+            .mipLevels = 1,
+            .arrayLayers = 1,
+            .format = vkhpp::Format::eR8G8B8A8Unorm,
+            .tiling = vkhpp::ImageTiling::eOptimal,
+            .initialLayout = vkhpp::ImageLayout::eUndefined,
+            .usage = vkhpp::ImageUsageFlagBits::eSampled | vkhpp::ImageUsageFlagBits::eTransferDst |
+                     vkhpp::ImageUsageFlagBits::eTransferSrc,
+            .sharingMode = vkhpp::SharingMode::eExclusive,
+            .samples = vkhpp::SampleCountFlagBits::e1,
+        };
+        auto image = device->createImageUnique(imageCreateInfo).value;
+
+        vkhpp::MemoryRequirements imageMemoryRequirements{};
+        device->getImageMemoryRequirements(*image, &imageMemoryRequirements);
+
+        const uint32_t imageMemoryIndex = GetMemoryType(
+            physicalDevice, imageMemoryRequirements, vkhpp::MemoryPropertyFlagBits::eDeviceLocal);
+        ASSERT_THAT(imageMemoryIndex, Not(Eq(-1)));
+
+        const vkhpp::MemoryAllocateInfo imageMemoryAllocateInfo = {
+            .allocationSize = imageMemoryRequirements.size,
+            .memoryTypeIndex = imageMemoryIndex,
+        };
+
+        auto imageMemory = device->allocateMemoryUnique(imageMemoryAllocateInfo).value;
+        ASSERT_THAT(imageMemory, IsValidHandle());
+        ASSERT_THAT(device->bindImageMemory(*image, *imageMemory, 0), IsVkSuccess());
+
+        vkhpp::UniqueFence fence;
+        if (withFence) {
+            fence = device->createFenceUnique(vkhpp::FenceCreateInfo()).value;
+        }
+
+        vkhpp::UniqueSemaphore semaphore;
+        if (withSemaphore) {
+            semaphore = device->createSemaphoreUnique(vkhpp::SemaphoreCreateInfo()).value;
+        }
+
+        auto result = vkAcquireImageANDROID(*device, *image, -1, *semaphore, *fence);
+        ASSERT_THAT(result, Eq(VK_SUCCESS));
+
+        if (withFence) {
+            fence.reset();
+        }
+        if (withSemaphore) {
+            semaphore.reset();
+        }
+    }
+};
 
 TEST_P(GfxstreamEnd2EndVkTest, Basic) {
     auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
@@ -626,6 +707,18 @@
     }
 }
 
+TEST_P(GfxstreamEnd2EndVkTest, DISABLED_AcquireImageAndroidWithFence) {
+    DoAcquireImageAndroidWithSync(/*withFence=*/true, /*withSemaphore=*/false);
+}
+
+TEST_P(GfxstreamEnd2EndVkTest, DISABLED_AcquireImageAndroidWithSemaphore) {
+    DoAcquireImageAndroidWithSync(/*withFence=*/false, /*withSemaphore=*/true);
+}
+
+TEST_P(GfxstreamEnd2EndVkTest, DISABLED_AcquireImageAndroidWithFenceAndSemaphore) {
+    DoAcquireImageAndroidWithSync(/*withFence=*/true, /*withSemaphore=*/true);
+}
+
 std::vector<TestParams> GenerateTestCases() {
     std::vector<TestParams> cases = {TestParams{
                                          .with_gl = false,