dawn::native::vulkan: Extract UniqueVkhandle out of QueueVk.

This unique_ptr equivalent for Vulkan handles will be useful in future
CLs.

Bug: 42241496
Change-Id: Iabbc5a8f45376434c3273ae8fe16474b6705cc12
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/207236
Reviewed-by: Geoff Lang <geofflang@google.com>
Reviewed-by: Loko Kung <lokokung@google.com>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Auto-Submit: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/dawn/native/BUILD.gn b/src/dawn/native/BUILD.gn
index 1582e70..004b8c3 100644
--- a/src/dawn/native/BUILD.gn
+++ b/src/dawn/native/BUILD.gn
@@ -830,6 +830,7 @@
       "vulkan/SwapChainVk.h",
       "vulkan/TextureVk.cpp",
       "vulkan/TextureVk.h",
+      "vulkan/UniqueVkHandle.h",
       "vulkan/UtilsVulkan.cpp",
       "vulkan/UtilsVulkan.h",
       "vulkan/VulkanError.cpp",
diff --git a/src/dawn/native/CMakeLists.txt b/src/dawn/native/CMakeLists.txt
index 6fec2bd..051ca77 100644
--- a/src/dawn/native/CMakeLists.txt
+++ b/src/dawn/native/CMakeLists.txt
@@ -684,6 +684,7 @@
         "vulkan/SharedTextureMemoryVk.h"
         "vulkan/SwapChainVk.h"
         "vulkan/TextureVk.h"
+        "vulkan/UniqueVkHandle.h"
         "vulkan/UtilsVulkan.h"
         "vulkan/VulkanError.h"
         "vulkan/VulkanExtensions.h"
diff --git a/src/dawn/native/vulkan/QueueVk.cpp b/src/dawn/native/vulkan/QueueVk.cpp
index 298a9d9..97b22fa 100644
--- a/src/dawn/native/vulkan/QueueVk.cpp
+++ b/src/dawn/native/vulkan/QueueVk.cpp
@@ -41,6 +41,7 @@
 #include "dawn/native/vulkan/FencedDeleter.h"
 #include "dawn/native/vulkan/SharedFenceVk.h"
 #include "dawn/native/vulkan/TextureVk.h"
+#include "dawn/native/vulkan/UniqueVkHandle.h"
 #include "dawn/native/vulkan/UtilsVulkan.h"
 #include "dawn/native/vulkan/VulkanError.h"
 #include "dawn/platform/DawnPlatform.h"
@@ -51,27 +52,6 @@
 
 namespace {
 
-// Destroy the semaphore when out of scope.
-class ScopedSignalSemaphore : public NonCopyable {
-  public:
-    ScopedSignalSemaphore(Device* device, VkSemaphore semaphore)
-        : mDevice(device), mSemaphore(semaphore) {}
-    ScopedSignalSemaphore(ScopedSignalSemaphore&& other)
-        : mDevice(other.mDevice), mSemaphore(std::exchange(other.mSemaphore, VK_NULL_HANDLE)) {}
-    ~ScopedSignalSemaphore() {
-        if (mSemaphore != VK_NULL_HANDLE) {
-            mDevice->GetFencedDeleter()->DeleteWhenUnused(mSemaphore);
-        }
-    }
-
-    VkSemaphore Get() { return mSemaphore; }
-    VkSemaphore* InitializeInto() { return &mSemaphore; }
-
-  private:
-    raw_ptr<Device> mDevice = nullptr;
-    VkSemaphore mSemaphore = VK_NULL_HANDLE;
-};
-
 // Destroys command pool/buffer.
 // TODO(dawn:1601) Revisit this and potentially bake into pool/buffer objects instead.
 void DestroyCommandPoolAndBuffer(const VulkanFunctions& fn,
@@ -350,14 +330,15 @@
         Buffer::TransitionMappableBuffersEagerly(
             device->fn, &mRecordingContext, mRecordingContext.mappableBuffersForEagerTransition);
     }
-    std::vector<ScopedSignalSemaphore> externalTextureSemaphores;
+
+    // Create an external semaphore for each external textures used in the pending submit.
+    std::vector<UniqueVkHandle<VkSemaphore>> externalTextureSemaphores(
+        mRecordingContext.externalTexturesForEagerTransition.size());
     for (size_t i = 0; i < mRecordingContext.externalTexturesForEagerTransition.size(); ++i) {
-        // Create an external semaphore for each external textures that have been used in the
-        // pending submit.
-        auto& externalTextureSemaphore =
-            externalTextureSemaphores.emplace_back(device, VK_NULL_HANDLE);
-        DAWN_TRY_ASSIGN(*externalTextureSemaphore.InitializeInto(),
+        VkSemaphore semaphore;
+        DAWN_TRY_ASSIGN(semaphore,
                         device->GetExternalSemaphoreService()->CreateExportableSemaphore());
+        externalTextureSemaphores[i] = {device, semaphore};
     }
 
     // Transition eagerly all used external textures for export.
diff --git a/src/dawn/native/vulkan/UniqueVkHandle.h b/src/dawn/native/vulkan/UniqueVkHandle.h
new file mode 100644
index 0000000..795ed21
--- /dev/null
+++ b/src/dawn/native/vulkan/UniqueVkHandle.h
@@ -0,0 +1,83 @@
+// Copyright 2024 The Dawn & Tint Authors
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its
+//    contributors may be used to endorse or promote products derived from
+//    this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef SRC_DAWN_NATIVE_VULKAN_UNIQUEVKHANDLE_H_
+#define SRC_DAWN_NATIVE_VULKAN_UNIQUEVKHANDLE_H_
+
+#include <utility>
+
+#include "dawn/common/NonCopyable.h"
+#include "dawn/native/vulkan/DeviceVk.h"
+#include "dawn/native/vulkan/FencedDeleter.h"
+
+namespace dawn::native::vulkan {
+
+// unique_ptr<> like RAII helper for Vulkan objects.
+template <typename Handle>
+class UniqueVkHandle : public NonCopyable {
+  public:
+    UniqueVkHandle() : mDevice(nullptr), mHandle(VK_NULL_HANDLE) {}
+    UniqueVkHandle(Device* device, Handle handle) : mDevice(device), mHandle(handle) {}
+    ~UniqueVkHandle() {
+        if (mHandle != VK_NULL_HANDLE) {
+            mDevice->GetFencedDeleter()->DeleteWhenUnused(mHandle);
+        }
+    }
+
+    UniqueVkHandle(UniqueVkHandle<Handle>&& other)
+        : mDevice(std::move(other.mDevice)), mHandle(other.mHandle) {
+        other.mHandle = VK_NULL_HANDLE;
+    }
+    UniqueVkHandle<Handle>& operator=(UniqueVkHandle<Handle>&& other) {
+        if (&other != this) {
+            if (mHandle != VK_NULL_HANDLE) {
+                mDevice->GetFencedDeleter()->DeleteWhenUnused(mHandle);
+            }
+            mDevice = std::move(other.mDevice);
+            mHandle = other.mHandle;
+            other.mHandle = VK_NULL_HANDLE;
+        }
+
+        return *this;
+    }
+
+    Handle Get() const { return mHandle; }
+    Handle Acquire() {
+        Handle handle = mHandle;
+        mDevice = nullptr;
+        mHandle = VK_NULL_HANDLE;
+        return handle;
+    }
+
+  private:
+    Ref<Device> mDevice;
+    Handle mHandle = VK_NULL_HANDLE;
+};
+
+}  // namespace dawn::native::vulkan
+
+#endif  // SRC_DAWN_NATIVE_VULKAN_UNIQUEVKHANDLE_H_