Add DebugUtilsHelper to DeviceInfo

... so that VkDecoderGlobalState can inject additional debug
actions into render thread Vulkan command streams.

Bug: b/165022040
Test: cvd start --gpu_mode=gfxstream_guest_angle
Change-Id: I2ec49ed1075da23160e14b3ac04d345578a80cc2
diff --git a/stream-servers/vulkan/VkCommonOperations.cpp b/stream-servers/vulkan/VkCommonOperations.cpp
index ab114e2..4fe147e 100644
--- a/stream-servers/vulkan/VkCommonOperations.cpp
+++ b/stream-servers/vulkan/VkCommonOperations.cpp
@@ -558,6 +558,13 @@
 
     std::unordered_set<const char*> enabledExtensions;
 
+    const bool debugUtilsSupported = extensionsSupported(exts, {VK_EXT_DEBUG_UTILS_EXTENSION_NAME});
+    const bool debugUtilsRequested = false; // TODO: enable via a feature or env var?
+    const bool debugUtilsAvailableAndRequested = debugUtilsSupported && debugUtilsRequested;
+    if (debugUtilsAvailableAndRequested) {
+        enabledExtensions.emplace(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
+    }
+
     if (externalMemoryCapabilitiesSupported) {
         for (auto extension : externalMemoryInstanceExtNames) {
             enabledExtensions.emplace(extension);
@@ -1162,6 +1169,12 @@
                                              string_VkResult(stagingBufferBindRes));
     }
 
+    sVkEmulation->debugUtilsAvailableAndRequested = debugUtilsAvailableAndRequested;
+    if (sVkEmulation->debugUtilsAvailableAndRequested) {
+        sVkEmulation->debugUtilsHelper =
+            DebugUtilsHelper::withUtilsEnabled(sVkEmulation->device, sVkEmulation->ivk);
+    }
+
     // LOG(VERBOSE) << "Vulkan global emulation state successfully initialized.";
     sVkEmulation->live = true;
 
diff --git a/stream-servers/vulkan/VkCommonOperations.h b/stream-servers/vulkan/VkCommonOperations.h
index ce11d89..3c69750 100644
--- a/stream-servers/vulkan/VkCommonOperations.h
+++ b/stream-servers/vulkan/VkCommonOperations.h
@@ -25,6 +25,7 @@
 
 #include "BorrowedImageVk.h"
 #include "CompositorVk.h"
+#include "DebugUtilsHelper.h"
 #include "DisplayVk.h"
 #include "FrameworkFormats.h"
 #include "aemu/base/ManagedDescriptor.hpp"
@@ -132,6 +133,9 @@
     PFN_vkGetMTLTextureMVK getMTLTextureFunc = nullptr;
 #endif
 
+    bool debugUtilsAvailableAndRequested = false;
+    DebugUtilsHelper debugUtilsHelper = DebugUtilsHelper::withUtilsDisabled();
+
     // Queue, command pool, and command buffer
     // for running commands to sync stuff system-wide.
     // TODO(b/197362803): Encapsulate host side VkQueue and the lock.
diff --git a/stream-servers/vulkan/VkDecoderGlobalState.cpp b/stream-servers/vulkan/VkDecoderGlobalState.cpp
index 7179554..3f86182 100644
--- a/stream-servers/vulkan/VkDecoderGlobalState.cpp
+++ b/stream-servers/vulkan/VkDecoderGlobalState.cpp
@@ -1305,9 +1305,14 @@
             fprintf(stderr, "%s: init vulkan dispatch from device\n", __func__);
         }
 
-        init_vulkan_dispatch_from_device(vk, *pDevice, dispatch_VkDevice(boxed));
+        VulkanDispatch* dispatch = dispatch_VkDevice(boxed);
+        init_vulkan_dispatch_from_device(vk, *pDevice, dispatch);
+        if (m_emu->debugUtilsAvailableAndRequested) {
+            deviceInfo.debugUtilsHelper = DebugUtilsHelper::withUtilsEnabled(*pDevice, dispatch);
+        }
+
         deviceInfo.externalFencePool =
-            std::make_unique<ExternalFencePool<VulkanDispatch>>(dispatch_VkDevice(boxed), *pDevice);
+            std::make_unique<ExternalFencePool<VulkanDispatch>>(dispatch, *pDevice);
 
         if (mLogging) {
             fprintf(stderr, "%s: init vulkan dispatch from device (end)\n", __func__);
@@ -5453,6 +5458,10 @@
             res.push_back(VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME);
         }
 
+        if (m_emu->debugUtilsAvailableAndRequested) {
+            res.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
+        }
+
         return res;
     }
 
@@ -5974,6 +5983,7 @@
         bool emulateTextureAstc = false;
         VkPhysicalDevice physicalDevice;
         VkDevice boxed = nullptr;
+        DebugUtilsHelper debugUtilsHelper = DebugUtilsHelper::withUtilsDisabled();
         std::unique_ptr<ExternalFencePool<VulkanDispatch>> externalFencePool = nullptr;
 
         // True if this is a compressed image that needs to be decompressed on the GPU (with our