RE-SkiaVk: Ref-count semaphores to prevent premature deletion

The lower-level parts of SkiaVk occassionally deletes a semaphore
still being used by SkiaVkRenderEngine.  This fixes that by
ref-counting the SkiaVkRenderEngine-created semaphores.

Test: Logcat with a HWASAN build
Bug: 274419744
Bug: 270287296
Change-Id: I05cecff69b4712daa4d7b52eb84c0027491369f5
diff --git a/libs/renderengine/skia/SkiaVkRenderEngine.cpp b/libs/renderengine/skia/SkiaVkRenderEngine.cpp
index 936e316..b99e385 100644
--- a/libs/renderengine/skia/SkiaVkRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaVkRenderEngine.cpp
@@ -52,6 +52,20 @@
     PFN_vkDestroyInstance vkDestroyInstance = nullptr;
 };
 
+// Ref-Count a semaphore
+struct DestroySemaphoreInfo {
+    VkSemaphore mSemaphore;
+    // We need to make sure we don't delete the VkSemaphore until it is done being used by both Skia
+    // (including by the GPU) and inside SkiaVkRenderEngine. So we always start with two refs, one
+    // owned by Skia and one owned by the SkiaVkRenderEngine. The refs are decremented each time
+    // delete_semaphore* is called with this object. Skia will call destroy_semaphore* once it is
+    // done with the semaphore and the GPU has finished work on the semaphore. SkiaVkRenderEngine
+    // calls delete_semaphore* after sending the semaphore to Skia and exporting it if need be.
+    int mRefs = 2;
+
+    DestroySemaphoreInfo(VkSemaphore semaphore) : mSemaphore(semaphore) {}
+};
+
 struct VulkanInterface {
     bool initialized = false;
     VkInstance instance;
@@ -588,14 +602,22 @@
     return true;
 }
 
-static void delete_semaphore(void* _semaphore) {
-    VkSemaphore semaphore = (VkSemaphore)_semaphore;
-    sVulkanInterface.destroySemaphore(semaphore);
+static void delete_semaphore(void* semaphore) {
+    DestroySemaphoreInfo* info = reinterpret_cast<DestroySemaphoreInfo*>(semaphore);
+    --info->mRefs;
+    if (!info->mRefs) {
+        sVulkanInterface.destroySemaphore(info->mSemaphore);
+        delete info;
+    }
 }
 
-static void delete_semaphore_protected(void* _semaphore) {
-    VkSemaphore semaphore = (VkSemaphore)_semaphore;
-    sProtectedContentVulkanInterface.destroySemaphore(semaphore);
+static void delete_semaphore_protected(void* semaphore) {
+    DestroySemaphoreInfo* info = reinterpret_cast<DestroySemaphoreInfo*>(semaphore);
+    --info->mRefs;
+    if (!info->mRefs) {
+        sProtectedContentVulkanInterface.destroySemaphore(info->mSemaphore);
+        delete info;
+    }
 }
 
 static VulkanInterface& getVulkanInterface(bool protectedContext) {
@@ -624,19 +646,30 @@
 }
 
 base::unique_fd SkiaVkRenderEngine::flushAndSubmit(GrDirectContext* grContext) {
-    VkSemaphore signalSemaphore = getVulkanInterface(isProtected()).createExportableSemaphore();
-    GrBackendSemaphore beSignalSemaphore;
-    beSignalSemaphore.initVulkan(signalSemaphore);
+    VulkanInterface& vi = getVulkanInterface(isProtected());
+    VkSemaphore semaphore = vi.createExportableSemaphore();
+
+    GrBackendSemaphore backendSemaphore;
+    backendSemaphore.initVulkan(semaphore);
+
     GrFlushInfo flushInfo;
-    flushInfo.fNumSemaphores = 1;
-    flushInfo.fSignalSemaphores = &beSignalSemaphore;
-    flushInfo.fFinishedProc = isProtected() ? delete_semaphore_protected : delete_semaphore;
-    flushInfo.fFinishedContext = (void*)signalSemaphore;
+    DestroySemaphoreInfo* destroySemaphoreInfo = nullptr;
+    if (semaphore != VK_NULL_HANDLE) {
+        destroySemaphoreInfo = new DestroySemaphoreInfo(semaphore);
+        flushInfo.fNumSemaphores = 1;
+        flushInfo.fSignalSemaphores = &backendSemaphore;
+        flushInfo.fFinishedProc = isProtected() ? delete_semaphore_protected : delete_semaphore;
+        flushInfo.fFinishedContext = destroySemaphoreInfo;
+    }
     GrSemaphoresSubmitted submitted = grContext->flush(flushInfo);
     grContext->submit(false /* no cpu sync */);
     int drawFenceFd = -1;
-    if (GrSemaphoresSubmitted::kYes == submitted) {
-        drawFenceFd = getVulkanInterface(isProtected()).exportSemaphoreSyncFd(signalSemaphore);
+    if (semaphore != VK_NULL_HANDLE) {
+        if (GrSemaphoresSubmitted::kYes == submitted) {
+            drawFenceFd = vi.exportSemaphoreSyncFd(semaphore);
+        }
+        // Now that drawFenceFd has been created, we can delete our reference to this semaphore
+        flushInfo.fFinishedProc(destroySemaphoreInfo);
     }
     base::unique_fd res(drawFenceFd);
     return res;