Merge "Reduce guest logspam" into main
diff --git a/codegen/vulkan/vulkan-docs-next/scripts/cereal/api_log_decoder.py b/codegen/vulkan/vulkan-docs-next/scripts/cereal/api_log_decoder.py
index cd66055..811cbbd 100644
--- a/codegen/vulkan/vulkan-docs-next/scripts/cereal/api_log_decoder.py
+++ b/codegen/vulkan/vulkan-docs-next/scripts/cereal/api_log_decoder.py
@@ -77,6 +77,7 @@
         "vkGetPhysicalDeviceFormatProperties",
         "vkGetPhysicalDeviceProperties2KHR",
         "vkGetPipelineCacheData",
+        "vkGetSemaphoreGOOGLE",
         "vkGetSwapchainGrallocUsageANDROID",
         "vkQueueCommitDescriptorSetUpdatesGOOGLE",
         "vkQueueFlushCommandsGOOGLE",
diff --git a/codegen/vulkan/vulkan-docs-next/scripts/cereal/common/codegen.py b/codegen/vulkan/vulkan-docs-next/scripts/cereal/common/codegen.py
index 1f217e3..0ebb535 100644
--- a/codegen/vulkan/vulkan-docs-next/scripts/cereal/common/codegen.py
+++ b/codegen/vulkan/vulkan-docs-next/scripts/cereal/common/codegen.py
@@ -22,6 +22,7 @@
 import sys
 import shutil
 import subprocess
+import re
 
 # Class capturing a single file
 
@@ -166,6 +167,25 @@
         self._headerFileModule.end()
         self._implFileModule.end()
 
+        # Removes empty ifdef blocks with a regex query over the file
+        # which are mainly introduced by extensions with no functions or variables
+        def remove_empty_ifdefs(filename: Path):
+            """Removes empty #ifdef blocks from a C++ file."""
+
+            # Load file contents
+            with open(filename, 'r') as file:
+                content = file.read()
+
+            # Regular Expression Pattern
+            pattern = r"#ifdef\s+(\w+)\s*(?://.*)?\s*\n\s*#endif\s*(?://.*)?\s*"
+
+            # Replace Empty Blocks
+            modified_content = re.sub(pattern, "", content)
+
+            # Save file back
+            with open(filename, 'w') as file:
+                file.write(modified_content)
+
         clang_format_command = shutil.which('clang-format')
         assert (clang_format_command is not None)
 
@@ -174,10 +194,14 @@
                     "--style=file", str(filename.resolve())]) == 0)
 
         if not self._headerFileModule.suppress:
-            formatFile(Path(self._headerFileModule.file.name))
+            filename = Path(self._headerFileModule.file.name)
+            remove_empty_ifdefs(filename)
+            formatFile(filename)
 
         if not self._implFileModule.suppress:
-            formatFile(Path(self._implFileModule.file.name))
+            filename = Path(self._implFileModule.file.name)
+            remove_empty_ifdefs(filename)
+            formatFile(filename)
 
 
 class PyScript(SingleFileModule):
diff --git a/codegen/vulkan/vulkan-docs-next/scripts/cereal/decoder.py b/codegen/vulkan/vulkan-docs-next/scripts/cereal/decoder.py
index ee69028..640ac78 100644
--- a/codegen/vulkan/vulkan-docs-next/scripts/cereal/decoder.py
+++ b/codegen/vulkan/vulkan-docs-next/scripts/cereal/decoder.py
@@ -742,6 +742,7 @@
     "vkMapMemoryIntoAddressSpaceGOOGLE" : emit_global_state_wrapped_decoding,
     "vkGetMemoryHostAddressInfoGOOGLE" : emit_global_state_wrapped_decoding,
     "vkGetBlobGOOGLE" : emit_global_state_wrapped_decoding,
+    "vkGetSemaphoreGOOGLE" : emit_global_state_wrapped_decoding,
 
     # Descriptor update templates
     "vkCreateDescriptorUpdateTemplate" : emit_global_state_wrapped_decoding,
@@ -788,6 +789,10 @@
     "vkCmdCopyBufferToImage2KHR" : emit_global_state_wrapped_decoding_with_context,
     "vkCmdCopyImage2KHR" : emit_global_state_wrapped_decoding,
     "vkCmdCopyImageToBuffer2KHR" : emit_global_state_wrapped_decoding,
+
+    # VK_KHR_device_group_creation / VK_VERSION_1_1
+    "vkEnumeratePhysicalDeviceGroups" : emit_global_state_wrapped_decoding,
+    "vkEnumeratePhysicalDeviceGroupsKHR" : emit_global_state_wrapped_decoding,
 }
 
 class VulkanDecoder(VulkanWrapperGenerator):
diff --git a/codegen/vulkan/vulkan-docs-next/scripts/cereal/extensionstructs.py b/codegen/vulkan/vulkan-docs-next/scripts/cereal/extensionstructs.py
index f6e30a9..6811515 100644
--- a/codegen/vulkan/vulkan-docs-next/scripts/cereal/extensionstructs.py
+++ b/codegen/vulkan/vulkan-docs-next/scripts/cereal/extensionstructs.py
@@ -110,7 +110,7 @@
             # emitForEachStructExtension and not accessible here. Consequently,
             # this is a copy-paste from there and must be updated accordingly.
             # NOTE: No need for %% if no substitution is made.
-            cgen.stmt("fprintf(stderr, \"Unhandled Vulkan structure type %d, aborting.\\n\", structType)")
+            cgen.stmt("fprintf(stderr, \"Unhandled Vulkan structure type %s [%d], aborting.\\n\", string_VkStructureType(VkStructureType(structType)), structType)")
             cgen.stmt("GFXSTREAM_ABORT(::emugl::FatalError(::emugl::ABORT_REASON_OTHER))")
             cgen.stmt("return (%s)0" % self.extensionStructSizeRetType.typeName)
 
diff --git a/codegen/vulkan/vulkan-docs-next/scripts/cereal/functable.py b/codegen/vulkan/vulkan-docs-next/scripts/cereal/functable.py
index 20906fe..ab04624 100644
--- a/codegen/vulkan/vulkan-docs-next/scripts/cereal/functable.py
+++ b/codegen/vulkan/vulkan-docs-next/scripts/cereal/functable.py
@@ -122,6 +122,8 @@
     "vkResetCommandPool",
     "vkFreeCommandBuffers",
     "vkResetCommandPool",
+    # Transform feedback
+    "vkCmdBeginTransformFeedbackEXT",
     # Special cases to handle struct translations in the pNext chain
     # TODO: Make a codegen module (use deepcopy as reference) to make this more robust
     "vkAllocateMemory",
@@ -392,8 +394,7 @@
                         cgen.stmt("%s = %s.size()" % (countParamName, nestedOutName))
                     else:
                         # Standard translation
-                        cgen.stmt("%s.reserve(%s)" % (nestedOutName, countParamName))
-                        cgen.stmt("memset(&%s[0], 0, sizeof(%s) * %s)" % (nestedOutName, member.typeName, countParamName))
+                        cgen.stmt("%s.resize(%s)" % (nestedOutName, countParamName))
                         if not nextLoopVar:
                             nextLoopVar = getNextLoopVar()
                         internalArray = genInternalArray(member, countParamName, nestedOutName, inArrayName, nextLoopVar)
@@ -517,7 +518,7 @@
                 cgen.stmt("return %s" % api.getRetVarExpr())
 
         def genGfxstreamEntry(declareResources=True):
-            cgen.stmt("AEMU_SCOPED_TRACE(\"%s\")" % api.name)
+            cgen.stmt("MESA_TRACE_SCOPE(\"%s\")" % api.name)
             # declare returnVar
             retTypeName = api.getRetTypeExpr()
             retVar = api.getRetVarExpr()
diff --git a/codegen/vulkan/vulkan-docs-next/scripts/cereal/marshalingdefs.py b/codegen/vulkan/vulkan-docs-next/scripts/cereal/marshalingdefs.py
index a78de96..01d4bc7 100644
--- a/codegen/vulkan/vulkan-docs-next/scripts/cereal/marshalingdefs.py
+++ b/codegen/vulkan/vulkan-docs-next/scripts/cereal/marshalingdefs.py
@@ -348,6 +348,7 @@
     "vkGetLinearImageLayoutGOOGLE": 20333,
     "vkQueueFlushCommandsGOOGLE": 20340,
     "vkGetBlobGOOGLE": 20341,
+    "vkGetSemaphoreGOOGLE": 20342,
 }
 
 CUSTOM_MARSHAL_TYPES = {
diff --git a/codegen/vulkan/vulkan-docs-next/scripts/cereal/reservedmarshaling.py b/codegen/vulkan/vulkan-docs-next/scripts/cereal/reservedmarshaling.py
index 3b54a41..9a75198 100644
--- a/codegen/vulkan/vulkan-docs-next/scripts/cereal/reservedmarshaling.py
+++ b/codegen/vulkan/vulkan-docs-next/scripts/cereal/reservedmarshaling.py
@@ -223,7 +223,7 @@
                     self.cgen.beginIf(lenAccessGuard)
                 self.cgen.beginFor("uint32_t k = 0", "k < %s" % lenAccess, "++k")
                 self.cgen.stmt("uint64_t tmpval; memcpy(&tmpval, %s_ptr + k * 8, sizeof(uint64_t))" % handle64Var)
-                self.cgen.stmt("*((%s%s) + k) = (%s)%s((%s)tmpval)" % (
+                self.cgen.stmt("*((%s%s) + k) = tmpval ? (%s)%s((%s)tmpval) : VK_NULL_HANDLE" % (
                     self.makeCastExpr(vulkanType.getForNonConstAccess()), access,
                     vulkanType.typeName, mapFunc, vulkanType.typeName))
                 if lenAccessGuard is not None:
diff --git a/codegen/vulkan/vulkan-docs-next/scripts/cerealgenerator.py b/codegen/vulkan/vulkan-docs-next/scripts/cerealgenerator.py
index be52de3..af73410 100644
--- a/codegen/vulkan/vulkan-docs-next/scripts/cerealgenerator.py
+++ b/codegen/vulkan/vulkan-docs-next/scripts/cerealgenerator.py
@@ -123,6 +123,9 @@
     "VK_EXT_metal_objects",
     "VK_KHR_external_semaphore_win32",
     "VK_KHR_external_memory_win32",
+    "VK_NV_device_diagnostic_checkpoints",
+    "VK_KHR_ray_tracing_pipeline",
+    "VK_KHR_pipeline_library",
     # Android
     "VK_ANDROID_native_buffer",
     "VK_ANDROID_external_memory_android_hardware_buffer",
@@ -169,8 +172,18 @@
     "VK_KHR_android_surface": ["func_table"],
     "VK_EXT_swapchain_maintenance1" : HOST_MODULES,
     "VK_KHR_swapchain" : HOST_MODULES,
+    "VK_NV_device_diagnostic_checkpoints": ["goldfish_vk_dispatch"],
+    "VK_KHR_ray_tracing_pipeline": HOST_MODULES,
+    "VK_KHR_pipeline_library": HOST_MODULES,
 }
 
+# These modules will be used when the feature is not supported.
+# This is necessary to cover all extensions where needed.
+UNSUPPORTED_FEATURE_MODULES = {
+    "goldfish_vk_extension_structs",
+}
+
+
 REQUIRED_TYPES = {
     "int",
     "uint16_t",
@@ -447,6 +460,7 @@
 {self.hostCommonExtraVulkanHeaders}
 #include "goldfish_vk_private_defs.h"
 #include "host-common/GfxstreamFatalError.h"
+#include "vulkan/vk_enum_string_helper.h"
 """
 
         extensionStructsIncludeGuest = """
@@ -788,10 +802,14 @@
             if self.featureName == supportedFeature:
                 self.featureSupported = True
 
-        if self.featureSupported == False:
+        if self.featureSupported == False and UNSUPPORTED_FEATURE_MODULES:
+            self.featureSupported = True
+            self.supportedModules = UNSUPPORTED_FEATURE_MODULES
+        elif self.featureSupported == False:
             return
+        else:
+            self.supportedModules = SUPPORTED_MODULES.get(self.featureName)
 
-        self.supportedModules = SUPPORTED_MODULES.get(self.featureName)
         self.typeInfo.onBeginFeature(self.featureName, self.featureType)
 
         self.forEachModule(
diff --git a/codegen/vulkan/vulkan-docs-next/xml/vk_gfxstream.xml b/codegen/vulkan/vulkan-docs-next/xml/vk_gfxstream.xml
index a42bcde..54eeae2 100644
--- a/codegen/vulkan/vulkan-docs-next/xml/vk_gfxstream.xml
+++ b/codegen/vulkan/vulkan-docs-next/xml/vk_gfxstream.xml
@@ -246,6 +246,12 @@
             <param><type>VkDeviceSize</type> <name>dataOffset</name></param>
             <param><type>VkDeviceSize</type> <name>dataSize</name></param>
         </command>
+        <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY">
+            <proto><type>VkResult</type> <name>vkGetSemaphoreGOOGLE</name></proto>
+            <param><type>VkDevice</type> <name>device</name></param>
+            <param><type>VkSemaphore</type> <name>semaphore</name></param>
+	    <param><type>uint64_t</type> <name>syncId</name></param>
+        </command>
     </commands>
     <extensions comment="Vulkan extension interface definitions">
         <extension name="VK_ANDROID_native_buffer" supported="vulkan"/>
@@ -284,7 +290,8 @@
                 <command name="vkGetBlobGOOGLE"/>
                 <command name="vkUpdateDescriptorSetWithTemplateSized2GOOGLE"/>
                 <command name="vkQueueSubmitAsync2GOOGLE"/>
+                <command name="vkGetSemaphoreGOOGLE"/>
             </require>
         </extension>
     </extensions>
-</registry>
\ No newline at end of file
+</registry>
diff --git a/common/end2end/Android.bp b/common/end2end/Android.bp
index c0d9a65..de6086e 100644
--- a/common/end2end/Android.bp
+++ b/common/end2end/Android.bp
@@ -38,7 +38,6 @@
     shared_libs: [
         "libandroidemu",
         "libOpenglSystemCommonWithHost",
-        "libbase",
         "liblog",
         "libgfxstream_platform_rutabaga_server",
     ],
@@ -57,6 +56,9 @@
         "-Wno-unused-parameter",
         "-Wno-extern-c-compat",
     ],
+    local_include_dirs: [
+        ".",
+    ],
     test_options: {
         // Disabled by default as requires host OpenGL and Vulkan.
         unit_test: false,
diff --git a/common/end2end/GfxstreamEnd2EndCompositionTests.cpp b/common/end2end/GfxstreamEnd2EndCompositionTests.cpp
index 2f54f70..db9811139 100644
--- a/common/end2end/GfxstreamEnd2EndCompositionTests.cpp
+++ b/common/end2end/GfxstreamEnd2EndCompositionTests.cpp
@@ -27,10 +27,10 @@
 TEST_P(GfxstreamEnd2EndCompositionTest, BasicComposition) {
     ScopedRenderControlDevice rcDevice(*mRc);
 
-    auto layer1Ahb = GL_ASSERT(CreateAHBFromImage("256x256_android.png"));
-    auto layer2Ahb = GL_ASSERT(CreateAHBFromImage("256x256_android_with_transparency.png"));
-    auto resultAhb =
-        GL_ASSERT(ScopedAHardwareBuffer::Allocate(*mGralloc, 256, 256, GFXSTREAM_AHB_FORMAT_R8G8B8A8_UNORM));
+    auto layer1Ahb = GFXSTREAM_ASSERT(CreateAHBFromImage("256x256_android.png"));
+    auto layer2Ahb = GFXSTREAM_ASSERT(CreateAHBFromImage("256x256_android_with_transparency.png"));
+    auto resultAhb = GFXSTREAM_ASSERT(
+        ScopedAHardwareBuffer::Allocate(*mGralloc, 256, 256, GFXSTREAM_AHB_FORMAT_R8G8B8A8_UNORM));
 
     const RenderControlComposition composition = {
         .displayId = 0,
@@ -97,15 +97,15 @@
 
     ASSERT_THAT(mRc->rcCompose(rcDevice, &composition, 2, compositionLayers), Eq(0));
 
-    GL_ASSERT(CompareAHBWithGolden(resultAhb, "256x256_golden_basic_composition.png"));
+    GFXSTREAM_ASSERT(CompareAHBWithGolden(resultAhb, "256x256_golden_basic_composition.png"));
 }
 
 TEST_P(GfxstreamEnd2EndCompositionTest, BasicCompositionBGRA) {
     ScopedRenderControlDevice rcDevice(*mRc);
 
-    auto layer1Ahb = GL_ASSERT(CreateAHBFromImage("256x256_android.png"));
-    auto layer2Ahb = GL_ASSERT(CreateAHBFromImage("256x256_android_with_transparency.png"));
-    auto resultAhb = GL_ASSERT(
+    auto layer1Ahb = GFXSTREAM_ASSERT(CreateAHBFromImage("256x256_android.png"));
+    auto layer2Ahb = GFXSTREAM_ASSERT(CreateAHBFromImage("256x256_android_with_transparency.png"));
+    auto resultAhb = GFXSTREAM_ASSERT(
         ScopedAHardwareBuffer::Allocate(*mGralloc, 256, 256, GFXSTREAM_AHB_FORMAT_B8G8R8A8_UNORM));
 
     const RenderControlComposition composition = {
@@ -173,7 +173,7 @@
 
     ASSERT_THAT(mRc->rcCompose(rcDevice, &composition, 2, compositionLayers), Eq(0));
 
-    GL_ASSERT(CompareAHBWithGolden(resultAhb, "256x256_golden_basic_composition.png"));
+    GFXSTREAM_ASSERT(CompareAHBWithGolden(resultAhb, "256x256_golden_basic_composition.png"));
 }
 
 INSTANTIATE_TEST_CASE_P(GfxstreamEnd2EndTests, GfxstreamEnd2EndCompositionTest,
diff --git a/common/end2end/GfxstreamEnd2EndGlTests.cpp b/common/end2end/GfxstreamEnd2EndGlTests.cpp
index 0779000..d3be079 100644
--- a/common/end2end/GfxstreamEnd2EndGlTests.cpp
+++ b/common/end2end/GfxstreamEnd2EndGlTests.cpp
@@ -28,47 +28,6 @@
 using testing::Le;
 using testing::Not;
 
-struct PixelR8G8B8A8 {
-    PixelR8G8B8A8() = default;
-
-    PixelR8G8B8A8(uint8_t rr, uint8_t gg, uint8_t bb, uint8_t aa) : r(rr), g(gg), b(bb), a(aa) {}
-
-    PixelR8G8B8A8(int xx, int yy, uint8_t rr, uint8_t gg, uint8_t bb, uint8_t aa)
-        : x(xx), y(yy), r(rr), g(gg), b(bb), a(aa) {}
-
-    std::optional<int> x;
-    std::optional<int> y;
-
-    uint8_t r = 0;
-    uint8_t g = 0;
-    uint8_t b = 0;
-    uint8_t a = 0;
-
-    std::string ToString() const {
-        std::string ret = std::string("Pixel");
-        if (x) {
-            ret += std::string(" x:") + std::to_string(*x);
-        }
-        if (y) {
-            ret += std::string(" y:") + std::to_string(*y);
-        }
-        ret += std::string(" {");
-        ret += std::string(" r:") + std::to_string(static_cast<int>(r));
-        ret += std::string(" g:") + std::to_string(static_cast<int>(g));
-        ret += std::string(" b:") + std::to_string(static_cast<int>(b));
-        ret += std::string(" a:") + std::to_string(static_cast<int>(a));
-        ret += std::string(" }");
-        return ret;
-    }
-
-    bool operator==(const PixelR8G8B8A8& rhs) const {
-        const auto& lhs = *this;
-        return std::tie(lhs.r, lhs.g, lhs.b, lhs.a) == std::tie(rhs.r, rhs.g, rhs.b, rhs.a);
-    }
-
-    friend void PrintTo(const PixelR8G8B8A8& pixel, std::ostream* os) { *os << pixel.ToString(); }
-};
-
 MATCHER_P(IsOkWith, expected, std::string(" equals ") + expected.ToString()) {
     const auto& actual = arg;
 
@@ -133,16 +92,16 @@
 
 class GfxstreamEnd2EndGlTest : public GfxstreamEnd2EndTest {
    protected:
-    GlExpected<PixelR8G8B8A8> GetPixelAt(GLint x, GLint y) {
+    Result<PixelR8G8B8A8> GetPixelAt(GLint x, GLint y) {
         if (!mGl) {
-            return android::base::unexpected("GL not available, running with `with_gl = false`?");
+            return gfxstream::unexpected("GL not available, running with `with_gl = false`?");
         }
 
         GLubyte rgba[4] = {0, 0, 0, 0};
         mGl->glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, rgba);
 
         if (GLenum error = mGl->glGetError(); error != GL_NO_ERROR) {
-            return android::base::unexpected("Failed to glReadPixels() with error " +
+            return gfxstream::unexpected("Failed to glReadPixels() with error " +
                                              std::to_string(error));
         }
 
@@ -449,7 +408,7 @@
 }
     )";
 
-    ScopedGlProgram program = GL_ASSERT(SetUpProgram(vertSource, fragSource));
+    ScopedGlProgram program = GFXSTREAM_ASSERT(SetUpProgram(vertSource, fragSource));
 
     GLint transformUniformLocation = mGl->glGetUniformLocation(program, "transform");
     mGl->glEnableVertexAttribArray(0);
@@ -502,25 +461,13 @@
     mGl->glUseProgram(0);
 }
 
-TEST_P(GfxstreamEnd2EndGlTest, DISABLED_ProgramBinaryWithAHB) {
+TEST_P(GfxstreamEnd2EndGlTest, ProgramBinaryWithAHB) {
     const uint32_t width = 2;
     const uint32_t height = 2;
-    auto ahb =
-        GL_ASSERT(ScopedAHardwareBuffer::Allocate(*mGralloc, width, height, GFXSTREAM_AHB_FORMAT_R8G8B8A8_UNORM));
+    auto ahb = GFXSTREAM_ASSERT(ScopedAHardwareBuffer::Allocate(
+        *mGralloc, width, height, GFXSTREAM_AHB_FORMAT_R8G8B8A8_UNORM));
 
-    {
-        uint8_t* mapped = GL_ASSERT(ahb.Lock());
-        uint32_t pos = 0;
-        for (uint32_t h = 0; h < height; h++) {
-            for (uint32_t w = 0; w < width; w++) {
-                mapped[pos++] = 0;
-                mapped[pos++] = 0;
-                mapped[pos++] = 128;
-                mapped[pos++] = 255;
-            }
-        }
-        ahb.Unlock();
-    }
+    GFXSTREAM_ASSERT(FillAhb(ahb, PixelR8G8B8A8(0, 0, 128, 255)));
 
     const EGLint ahbImageAttribs[] = {
         // clang-format off
@@ -571,7 +518,7 @@
                 oColor = texture(uTexture, vTex) * uMultiplier;
             })";
 
-        ScopedGlProgram program = GL_ASSERT(SetUpProgram(vertSource, fragSource));
+        ScopedGlProgram program = GFXSTREAM_ASSERT(SetUpProgram(vertSource, fragSource));
 
         GLint programBinaryLength = 0;
         mGl->glGetProgramiv(program, GL_PROGRAM_BINARY_LENGTH, &programBinaryLength);
@@ -586,7 +533,8 @@
         ASSERT_THAT(programBinaryLength, Eq(readProgramBinaryLength));
     }
 
-    ScopedGlProgram program = GL_ASSERT(SetUpProgram(programBinaryFormat, programBinaryData));
+    ScopedGlProgram program =
+        GFXSTREAM_ASSERT(SetUpProgram(programBinaryFormat, programBinaryData));
     ASSERT_THAT(program, Not(Eq(0)));
 
     GLint textureUniformLoc = mGl->glGetUniformLocation(program, "uTexture");
@@ -659,7 +607,7 @@
     mGl->glBindFramebuffer(GL_FRAMEBUFFER, 0);
 }
 
-TEST_P(GfxstreamEnd2EndGlTest, DISABLED_ProgramBinaryWithTexture) {
+TEST_P(GfxstreamEnd2EndGlTest, ProgramBinaryWithTexture) {
     const GLsizei kTextureWidth = 2;
     const GLsizei kTextureHeight = 2;
     const GLubyte kTextureData[16] = {
@@ -709,7 +657,7 @@
                 oColor = texture(uTexture, vTex) * uMultiplier;
             })";
 
-        ScopedGlProgram program = GL_ASSERT(SetUpProgram(vertSource, fragSource));
+        ScopedGlProgram program = GFXSTREAM_ASSERT(SetUpProgram(vertSource, fragSource));
 
         GLint programBinaryLength = 0;
         mGl->glGetProgramiv(program, GL_PROGRAM_BINARY_LENGTH, &programBinaryLength);
@@ -724,7 +672,8 @@
         ASSERT_THAT(programBinaryLength, Eq(readProgramBinaryLength));
     }
 
-    ScopedGlProgram program = GL_ASSERT(SetUpProgram(programBinaryFormat, programBinaryData));
+    ScopedGlProgram program =
+        GFXSTREAM_ASSERT(SetUpProgram(programBinaryFormat, programBinaryData));
     ASSERT_THAT(program, Not(Eq(0)));
 
     GLint textureUniformLoc = mGl->glGetUniformLocation(program, "uTexture");
@@ -797,39 +746,20 @@
     mGl->glBindFramebuffer(GL_FRAMEBUFFER, 0);
 }
 
-constexpr std::vector<uint8_t> Fill(uint32_t w, uint32_t h, const PixelR8G8B8A8& pixel) {
-    std::vector<uint8_t> ret;
-    ret.reserve(w * h * 4);
-    for (uint32_t y = 0; y < h; y++) {
-        for (uint32_t x = 0; x < w; x++) {
-            ret.push_back(pixel.r);
-            ret.push_back(pixel.g);
-            ret.push_back(pixel.b);
-            ret.push_back(pixel.a);
-        }
-    }
-    return ret;
-}
-
 TEST_P(GfxstreamEnd2EndGlTest, AhbTextureUploadAndReadback) {
     const uint32_t width = 2;
     const uint32_t height = 2;
 
     const auto lockPixel = PixelR8G8B8A8(11, 22, 33, 44);
-    const auto lockPixels = Fill(width, height, lockPixel);
 
     const auto uploadPixel = PixelR8G8B8A8(55, 66, 77, 88);
     const auto uploadPixels = Fill(width, height, uploadPixel);
 
-    auto ahb = GL_ASSERT(ScopedAHardwareBuffer::Allocate(*mGralloc, width, height,
-                                                         GFXSTREAM_AHB_FORMAT_R8G8B8A8_UNORM));
+    auto ahb = GFXSTREAM_ASSERT(ScopedAHardwareBuffer::Allocate(
+        *mGralloc, width, height, GFXSTREAM_AHB_FORMAT_R8G8B8A8_UNORM));
 
     // Initialize AHB with `lockPixel`
-    {
-        uint8_t* mapped = GL_ASSERT(ahb.Lock());
-        std::memcpy(mapped, lockPixels.data(), lockPixels.size());
-        ahb.Unlock();
-    }
+    GFXSTREAM_ASSERT(FillAhb(ahb, lockPixel));
 
     // Update AHB with `uploadPixel` via texture upload:
     {
@@ -927,20 +857,15 @@
     ASSERT_THAT(mGl->glGetError(), Eq(GL_NO_ERROR));
 
     const auto lockPixel = PixelR8G8B8A8(11, 22, 33, 44);
-    const auto lockPixels = Fill(width, height, lockPixel);
 
     const auto uploadPixel = PixelR8G8B8A8(55, 66, 77, 88);
     const auto uploadPixels = Fill(width, height, uploadPixel);
 
-    auto ahb = GL_ASSERT(ScopedAHardwareBuffer::Allocate(*mGralloc, width, height,
-                                                         GFXSTREAM_AHB_FORMAT_R8G8B8A8_UNORM));
+    auto ahb = GFXSTREAM_ASSERT(ScopedAHardwareBuffer::Allocate(
+        *mGralloc, width, height, GFXSTREAM_AHB_FORMAT_R8G8B8A8_UNORM));
 
     // Initialize AHB with `lockPixel`
-    {
-        uint8_t* mapped = GL_ASSERT(ahb.Lock());
-        std::memcpy(mapped, lockPixels.data(), lockPixels.size());
-        ahb.Unlock();
-    }
+    GFXSTREAM_ASSERT(FillAhb(ahb, lockPixel));
 
     // Update AHB with `uploadPixel` via texture upload:
     {
@@ -1009,7 +934,7 @@
             })";
 
         ScopedGlProgram program =
-            GL_ASSERT(SetUpProgram(blitTextureVertSource, blitTextureFragSource));
+            GFXSTREAM_ASSERT(SetUpProgram(blitTextureVertSource, blitTextureFragSource));
 
         GLint textureUniformLoc = mGl->glGetUniformLocation(program, "uTexture");
         ASSERT_THAT(mGl->glGetError(), Eq(GL_NO_ERROR));
@@ -1088,13 +1013,12 @@
     const uint32_t height = 2;
 
     const auto lockPixel = PixelR8G8B8A8(11, 22, 33, 44);
-    const auto lockPixels = Fill(width, height, lockPixel);
 
     const auto uploadPixel = PixelR8G8B8A8(55, 66, 77, 88);
     const auto uploadPixels = Fill(width, height, uploadPixel);
 
-    auto ahb = GL_ASSERT(ScopedAHardwareBuffer::Allocate(*mGralloc, width, height,
-                                                         GFXSTREAM_AHB_FORMAT_R8G8B8A8_UNORM));
+    auto ahb = GFXSTREAM_ASSERT(ScopedAHardwareBuffer::Allocate(
+        *mGralloc, width, height, GFXSTREAM_AHB_FORMAT_R8G8B8A8_UNORM));
 
     const EGLint ahbImageAttribs[] = {
         // clang-format off
@@ -1170,7 +1094,7 @@
                     void main() {
                         oColor = texture(uTexture, vTex);
                     })";
-            ScopedGlProgram program = GL_ASSERT(SetUpProgram(vertSource, fragSource));
+            ScopedGlProgram program = GFXSTREAM_ASSERT(SetUpProgram(vertSource, fragSource));
             ASSERT_THAT(program, Not(Eq(0)));
 
             GLint textureUniformLoc = mGl->glGetUniformLocation(program, "uTexture");
@@ -1283,11 +1207,7 @@
     uploadThreadInitialized.wait();
 
     // "MainThread" updates the AHB with `lockPixel` via Gralloc->Lock():
-    {
-        uint8_t* mapped = GL_ASSERT(ahb.Lock());
-        std::memcpy(mapped, lockPixels.data(), lockPixels.size());
-        ahb.Unlock();
-    }
+    GFXSTREAM_ASSERT(FillAhb(ahb, lockPixel));
 
     // "UploadThread" updates the AHB with `uploadPixel` via GL texture upload:
     uploadThreadStartUpload.count_down();
@@ -1345,13 +1265,12 @@
     ASSERT_THAT(mGl->glGetError(), Eq(GL_NO_ERROR));
 
     const auto lockPixel = PixelR8G8B8A8(11, 22, 33, 44);
-    const auto lockPixels = Fill(width, height, lockPixel);
 
     const auto uploadPixel = PixelR8G8B8A8(55, 66, 77, 88);
     const auto uploadPixels = Fill(width, height, uploadPixel);
 
-    auto ahb = GL_ASSERT(ScopedAHardwareBuffer::Allocate(*mGralloc, width, height,
-                                                         GFXSTREAM_AHB_FORMAT_R8G8B8A8_UNORM));
+    auto ahb = GFXSTREAM_ASSERT(ScopedAHardwareBuffer::Allocate(
+        *mGralloc, width, height, GFXSTREAM_AHB_FORMAT_R8G8B8A8_UNORM));
 
     const EGLint ahbImageAttribs[] = {
         // clang-format off
@@ -1361,11 +1280,7 @@
     };
 
     // Initialize AHB with `lockPixel`
-    {
-        uint8_t* mapped = GL_ASSERT(ahb.Lock());
-        std::memcpy(mapped, lockPixels.data(), lockPixels.size());
-        ahb.Unlock();
-    }
+    GFXSTREAM_ASSERT(FillAhb(ahb, lockPixel));
 
     // Update AHB with `uploadPixel` via texture upload:
     {
@@ -1421,7 +1336,7 @@
             })";
 
         ScopedGlProgram program =
-            GL_ASSERT(SetUpProgram(blitTextureVertSource, blitTextureFragSource));
+            GFXSTREAM_ASSERT(SetUpProgram(blitTextureVertSource, blitTextureFragSource));
 
         GLint textureUniformLoc = mGl->glGetUniformLocation(program, "uTexture");
         ASSERT_THAT(mGl->glGetError(), Eq(GL_NO_ERROR));
@@ -1513,10 +1428,9 @@
     ASSERT_THAT(mGl->glGetError(), Eq(GL_NO_ERROR));
 
     const auto lockPixel = PixelR8G8B8A8(11, 22, 33, 44);
-    const auto lockPixels = Fill(width, height, lockPixel);
 
-    auto ahb = GL_ASSERT(ScopedAHardwareBuffer::Allocate(*mGralloc, width, height,
-                                                         GFXSTREAM_AHB_FORMAT_R8G8B8A8_UNORM));
+    auto ahb = GFXSTREAM_ASSERT(ScopedAHardwareBuffer::Allocate(
+        *mGralloc, width, height, GFXSTREAM_AHB_FORMAT_R8G8B8A8_UNORM));
 
     const EGLint ahbImageAttribs[] = {
         // clang-format off
@@ -1526,11 +1440,7 @@
     };
 
     // Initialize AHB with `lockPixel`
-    {
-        uint8_t* mapped = GL_ASSERT(ahb.Lock());
-        std::memcpy(mapped, lockPixels.data(), lockPixels.size());
-        ahb.Unlock();
-    }
+    GFXSTREAM_ASSERT(FillAhb(ahb, lockPixel));
 
     // Blit from AHB to an additional framebuffer and readback:
     {
@@ -1564,7 +1474,7 @@
             })";
 
         ScopedGlProgram program =
-            GL_ASSERT(SetUpProgram(blitTextureVertSource, blitTextureFragSource));
+            GFXSTREAM_ASSERT(SetUpProgram(blitTextureVertSource, blitTextureFragSource));
 
         GLint textureUniformLoc = mGl->glGetUniformLocation(program, "uTexture");
         ASSERT_THAT(mGl->glGetError(), Eq(GL_NO_ERROR));
@@ -1633,7 +1543,11 @@
     }
 }
 
-TEST_P(GfxstreamEnd2EndGlTest, DISABLED_AhbExternalOesTextureBlitProgramBinary) {
+TEST_P(GfxstreamEnd2EndGlTest, AhbExternalOesTextureBlitProgramBinary) {
+    if (GetParam().with_features.count("GlProgramBinaryLinkStatus") == 0) {
+        GTEST_SKIP() << "Skipping test, GlProgramBinaryLinkStatus not enabled.";
+    }
+
     const uint32_t width = 2;
     const uint32_t height = 2;
 
@@ -1653,10 +1567,9 @@
     ASSERT_THAT(mGl->glGetError(), Eq(GL_NO_ERROR));
 
     const auto lockPixel = PixelR8G8B8A8(11, 22, 33, 44);
-    const auto lockPixels = Fill(width, height, lockPixel);
 
-    auto ahb = GL_ASSERT(ScopedAHardwareBuffer::Allocate(*mGralloc, width, height,
-                                                         GFXSTREAM_AHB_FORMAT_R8G8B8A8_UNORM));
+    auto ahb = GFXSTREAM_ASSERT(ScopedAHardwareBuffer::Allocate(
+        *mGralloc, width, height, GFXSTREAM_AHB_FORMAT_R8G8B8A8_UNORM));
 
     const EGLint ahbImageAttribs[] = {
         // clang-format off
@@ -1666,11 +1579,7 @@
     };
 
     // Initialize AHB with `lockPixel`
-    {
-        uint8_t* mapped = GL_ASSERT(ahb.Lock());
-        std::memcpy(mapped, lockPixels.data(), lockPixels.size());
-        ahb.Unlock();
-    }
+    GFXSTREAM_ASSERT(FillAhb(ahb, lockPixel));
 
     // Setup blit program:
     GLenum programBinaryFormat = GL_NONE;
@@ -1697,7 +1606,7 @@
                 oColor = texture(uTexture, vTex);
             })";
 
-        ScopedGlProgram program = GL_ASSERT(SetUpProgram(vertSource, fragSource));
+        ScopedGlProgram program = GFXSTREAM_ASSERT(SetUpProgram(vertSource, fragSource));
 
         GLint programBinaryLength = 0;
         mGl->glGetProgramiv(program, GL_PROGRAM_BINARY_LENGTH, &programBinaryLength);
@@ -1709,12 +1618,13 @@
         mGl->glGetProgramBinary(program, programBinaryLength, &readProgramBinaryLength,
                                 &programBinaryFormat, programBinaryData.data());
         ASSERT_THAT(mGl->glGetError(), Eq(GL_NO_ERROR));
-        ASSERT_THAT(programBinaryLength, Eq(readProgramBinaryLength));
+        ASSERT_THAT(readProgramBinaryLength, Eq(programBinaryLength));
     }
 
     // Blit from AHB to an additional framebuffer and readback:
     {
-        ScopedGlProgram program = GL_ASSERT(SetUpProgram(programBinaryFormat, programBinaryData));
+        ScopedGlProgram program =
+            GFXSTREAM_ASSERT(SetUpProgram(programBinaryFormat, programBinaryData));
         ASSERT_THAT(program, Not(Eq(0)));
 
         GLint textureUniformLoc = mGl->glGetUniformLocation(program, "uTexture");
@@ -1789,10 +1699,12 @@
                             TestParams{
                                 .with_gl = true,
                                 .with_vk = false,
+                                .with_features = {"GlProgramBinaryLinkStatus"},
                             },
                             TestParams{
                                 .with_gl = true,
                                 .with_vk = true,
+                                .with_features = {"GlProgramBinaryLinkStatus"},
                             },
                         }),
                         &GetTestName);
diff --git a/common/end2end/GfxstreamEnd2EndTests.cpp b/common/end2end/GfxstreamEnd2EndTests.cpp
index 660cbf8..fd3212f 100644
--- a/common/end2end/GfxstreamEnd2EndTests.cpp
+++ b/common/end2end/GfxstreamEnd2EndTests.cpp
@@ -50,6 +50,21 @@
 
 }  // namespace
 
+Image ImageFromColor(uint32_t w, uint32_t h, const PixelR8G8B8A8& pixel) {
+    uint32_t rgba = 0;
+    uint8_t* rgbaParts = reinterpret_cast<uint8_t*>(&rgba);
+    rgbaParts[0] = pixel.r;
+    rgbaParts[1] = pixel.g;
+    rgbaParts[2] = pixel.b;
+    rgbaParts[3] = pixel.a;
+
+    Image ret;
+    ret.width = w;
+    ret.height = h;
+    ret.pixels.resize(w * h, rgba);
+    return ret;
+}
+
 std::string GfxstreamTransportToEnvVar(GfxstreamTransport transport) {
     switch (transport) {
         case GfxstreamTransport::kVirtioGpuAsg: {
@@ -357,11 +372,11 @@
     ASSERT_THAT(mGl->eglDestroySurface(display, surface), IsTrue());
 }
 
-GlExpected<ScopedGlShader> ScopedGlShader::MakeShader(GlDispatch& dispatch, GLenum type,
-                                                      const std::string& source) {
+Result<ScopedGlShader> ScopedGlShader::MakeShader(GlDispatch& dispatch, GLenum type,
+                                                  const std::string& source) {
     GLuint shader = dispatch.glCreateShader(type);
     if (!shader) {
-        return android::base::unexpected("Failed to create shader.");
+        return gfxstream::unexpected("Failed to create shader.");
     }
 
     const GLchar* sourceTyped = (const GLchar*)source.c_str();
@@ -386,18 +401,19 @@
         ALOGE("Shader compilation failed with: \"%s\"", errorString.c_str());
 
         dispatch.glDeleteShader(shader);
-        return android::base::unexpected(errorString);
+        return gfxstream::unexpected(errorString);
     }
 
     return ScopedGlShader(dispatch, shader);
 }
 
-GlExpected<ScopedGlProgram> ScopedGlProgram::MakeProgram(GlDispatch& dispatch,
-                                                         const std::string& vertSource,
-                                                         const std::string& fragSource) {
-    auto vertShader = GL_EXPECT(ScopedGlShader::MakeShader(dispatch, GL_VERTEX_SHADER, vertSource));
+Result<ScopedGlProgram> ScopedGlProgram::MakeProgram(GlDispatch& dispatch,
+                                                     const std::string& vertSource,
+                                                     const std::string& fragSource) {
+    auto vertShader =
+        GFXSTREAM_EXPECT(ScopedGlShader::MakeShader(dispatch, GL_VERTEX_SHADER, vertSource));
     auto fragShader =
-        GL_EXPECT(ScopedGlShader::MakeShader(dispatch, GL_FRAGMENT_SHADER, fragSource));
+        GFXSTREAM_EXPECT(ScopedGlShader::MakeShader(dispatch, GL_FRAGMENT_SHADER, fragSource));
 
     GLuint program = dispatch.glCreateProgram();
     dispatch.glAttachShader(program, vertShader);
@@ -420,13 +436,13 @@
         ALOGE("Program link failed with: \"%s\"", errorString.c_str());
 
         dispatch.glDeleteProgram(program);
-        return android::base::unexpected(errorString);
+        return gfxstream::unexpected(errorString);
     }
 
     return ScopedGlProgram(dispatch, program);
 }
 
-GlExpected<ScopedGlProgram> ScopedGlProgram::MakeProgram(
+Result<ScopedGlProgram> ScopedGlProgram::MakeProgram(
     GlDispatch& dispatch, GLenum programBinaryFormat,
     const std::vector<uint8_t>& programBinaryData) {
     GLuint program = dispatch.glCreateProgram();
@@ -449,19 +465,18 @@
         ALOGE("Program link failed with: \"%s\"", errorString.c_str());
 
         dispatch.glDeleteProgram(program);
-        return android::base::unexpected(errorString);
+        return gfxstream::unexpected(errorString);
     }
 
     return ScopedGlProgram(dispatch, program);
 }
 
-GlExpected<ScopedAHardwareBuffer> ScopedAHardwareBuffer::Allocate(Gralloc& gralloc, uint32_t width,
-                                                                  uint32_t height,
-                                                                  uint32_t format) {
+Result<ScopedAHardwareBuffer> ScopedAHardwareBuffer::Allocate(Gralloc& gralloc, uint32_t width,
+                                                              uint32_t height, uint32_t format) {
     AHardwareBuffer* ahb = nullptr;
     int status = gralloc.allocate(width, height, format, -1, &ahb);
     if (status != 0) {
-        return android::base::unexpected(std::string("Failed to allocate AHB with width:") +
+        return gfxstream::unexpected(std::string("Failed to allocate AHB with width:") +
                                          std::to_string(width) + std::string(" height:") +
                                          std::to_string(height) + std::string(" format:") +
                                          std::to_string(format));
@@ -470,34 +485,33 @@
     return ScopedAHardwareBuffer(gralloc, ahb);
 }
 
-GlExpected<ScopedGlShader> GfxstreamEnd2EndTest::SetUpShader(GLenum type,
-                                                             const std::string& source) {
+Result<ScopedGlShader> GfxstreamEnd2EndTest::SetUpShader(GLenum type, const std::string& source) {
     if (!mGl) {
-        return android::base::unexpected("Gl not enabled for this test.");
+        return gfxstream::unexpected("Gl not enabled for this test.");
     }
 
     return ScopedGlShader::MakeShader(*mGl, type, source);
 }
 
-GlExpected<ScopedGlProgram> GfxstreamEnd2EndTest::SetUpProgram(const std::string& vertSource,
-                                                               const std::string& fragSource) {
+Result<ScopedGlProgram> GfxstreamEnd2EndTest::SetUpProgram(const std::string& vertSource,
+                                                           const std::string& fragSource) {
     if (!mGl) {
-        return android::base::unexpected("Gl not enabled for this test.");
+        return gfxstream::unexpected("Gl not enabled for this test.");
     }
 
     return ScopedGlProgram::MakeProgram(*mGl, vertSource, fragSource);
 }
 
-GlExpected<ScopedGlProgram> GfxstreamEnd2EndTest::SetUpProgram(
+Result<ScopedGlProgram> GfxstreamEnd2EndTest::SetUpProgram(
     GLenum programBinaryFormat, const std::vector<uint8_t>& programBinaryData) {
     if (!mGl) {
-        return android::base::unexpected("Gl not enabled for this test.");
+        return gfxstream::unexpected("Gl not enabled for this test.");
     }
 
     return ScopedGlProgram::MakeProgram(*mGl, programBinaryFormat, programBinaryData);
 }
 
-VkExpected<GfxstreamEnd2EndTest::TypicalVkTestEnvironment>
+Result<GfxstreamEnd2EndTest::TypicalVkTestEnvironment>
 GfxstreamEnd2EndTest::SetUpTypicalVkTestEnvironment(const TypicalVkTestEnvironmentOptions& opts) {
     const auto availableInstanceLayers = vkhpp::enumerateInstanceLayerProperties().value;
     ALOGV("Available instance layers:");
@@ -529,11 +543,11 @@
         .ppEnabledExtensionNames = requestedInstanceExtensions.data(),
     };
 
-    auto instance = VK_EXPECT_RV(vkhpp::createInstanceUnique(instanceCreateInfo));
+    auto instance = GFXSTREAM_EXPECT_VKHPP_RV(vkhpp::createInstanceUnique(instanceCreateInfo));
 
     VULKAN_HPP_DEFAULT_DISPATCHER.init(*instance);
 
-    auto physicalDevices = VK_EXPECT_RV(instance->enumeratePhysicalDevices());
+    auto physicalDevices = GFXSTREAM_EXPECT_VKHPP_RV(instance->enumeratePhysicalDevices());
     ALOGV("Available physical devices:");
     for (const auto& physicalDevice : physicalDevices) {
         const auto physicalDeviceProps = physicalDevice.getProperties();
@@ -541,8 +555,8 @@
     }
 
     if (physicalDevices.empty()) {
-        ALOGE("No physical devices available?");
-        return android::base::unexpected(vkhpp::Result::eErrorUnknown);
+        return gfxstream::unexpected(
+            "Failed to set up typical VK env: no physical devices available.");
     }
 
     auto physicalDevice = std::move(physicalDevices[0]);
@@ -551,7 +565,8 @@
         ALOGV("Selected physical device: %s", physicalDeviceProps.deviceName.data());
     }
     {
-        const auto exts = VK_EXPECT_RV(physicalDevice.enumerateDeviceExtensionProperties());
+        const auto exts =
+            GFXSTREAM_EXPECT_VKHPP_RV(physicalDevice.enumerateDeviceExtensionProperties());
         ALOGV("Available physical device extensions:");
         for (const auto& ext : exts) {
             ALOGV(" - %s", ext.extensionName.data());
@@ -570,8 +585,7 @@
         }
     }
     if (graphicsQueueFamilyIndex == -1) {
-        ALOGE("Failed to find graphics queue.");
-        return android::base::unexpected(vkhpp::Result::eErrorUnknown);
+        return gfxstream::unexpected("Failed to set up typical VK env: no graphics queue.");
     }
 
     const float queuePriority = 1.0f;
@@ -598,7 +612,7 @@
         .enabledExtensionCount = static_cast<uint32_t>(deviceExtensions.size()),
         .ppEnabledExtensionNames = deviceExtensions.data(),
     };
-    auto device = VK_EXPECT_RV(physicalDevice.createDeviceUnique(deviceCreateInfo));
+    auto device = GFXSTREAM_EXPECT_VKHPP_RV(physicalDevice.createDeviceUnique(deviceCreateInfo));
 
     auto queue = device->getQueue(graphicsQueueFamilyIndex, 0);
 
@@ -620,13 +634,13 @@
     emulation->SnapshotRestore(directory);
 }
 
-GlExpected<Image> GfxstreamEnd2EndTest::LoadImage(const std::string& basename) {
+Result<Image> GfxstreamEnd2EndTest::LoadImage(const std::string& basename) {
     const std::string filepath = GetTestDataPath(basename);
     if (!std::filesystem::exists(filepath)) {
-        return android::base::unexpected("File " + filepath + " does not exist.");
+        return gfxstream::unexpected("File " + filepath + " does not exist.");
     }
     if (!std::filesystem::is_regular_file(filepath)) {
-        return android::base::unexpected("File " + filepath + " is not a regular file.");
+        return gfxstream::unexpected("File " + filepath + " is not a regular file.");
     }
 
     Image image;
@@ -635,32 +649,32 @@
     uint32_t sourceHeight = 0;
     std::vector<uint32_t> sourcePixels;
     if (!LoadRGBAFromPng(filepath, &image.width, &image.height, &image.pixels)) {
-        return android::base::unexpected("Failed to load " + filepath + " as RGBA PNG.");
+        return gfxstream::unexpected("Failed to load " + filepath + " as RGBA PNG.");
     }
 
     return image;
 }
 
-GlExpected<Image> GfxstreamEnd2EndTest::AsImage(ScopedAHardwareBuffer& ahb) {
+Result<Image> GfxstreamEnd2EndTest::AsImage(ScopedAHardwareBuffer& ahb) {
     Image actual;
     actual.width = ahb.GetWidth();
     if (actual.width == 0) {
-        return android::base::unexpected("Failed to query AHB width.");
+        return gfxstream::unexpected("Failed to query AHB width.");
     }
     actual.height = ahb.GetHeight();
     if (actual.height == 0) {
-        return android::base::unexpected("Failed to query AHB height.");
+        return gfxstream::unexpected("Failed to query AHB height.");
     }
     actual.pixels.resize(actual.width * actual.height);
 
     const uint32_t ahbFormat = ahb.GetAHBFormat();
     if (ahbFormat != GFXSTREAM_AHB_FORMAT_R8G8B8A8_UNORM &&
         ahbFormat != GFXSTREAM_AHB_FORMAT_B8G8R8A8_UNORM) {
-        return android::base::unexpected("Unhandled AHB format " + std::to_string(ahbFormat));
+        return gfxstream::unexpected("Unhandled AHB format " + std::to_string(ahbFormat));
     }
 
     {
-        uint8_t* ahbPixels = GL_EXPECT(ahb.Lock());
+        uint8_t* ahbPixels = GFXSTREAM_EXPECT(ahb.Lock());
         std::memcpy(actual.pixels.data(), ahbPixels, actual.pixels.size() * sizeof(uint32_t));
         ahb.Unlock();
     }
@@ -675,15 +689,73 @@
     return actual;
 }
 
-GlExpected<ScopedAHardwareBuffer> GfxstreamEnd2EndTest::CreateAHBFromImage(
-    const std::string& basename) {
-    auto image = GL_EXPECT(LoadImage(basename));
+Result<Ok> GfxstreamEnd2EndTest::FillAhb(ScopedAHardwareBuffer& ahb, PixelR8G8B8A8 color) {
+    const uint32_t drmFormat = ahb.GetDrmFormat();
 
-    auto ahb = GL_EXPECT(
-        ScopedAHardwareBuffer::Allocate(*mGralloc, image.width, image.height, GFXSTREAM_AHB_FORMAT_R8G8B8A8_UNORM));
+    const uint32_t ahbWidth = ahb.GetWidth();
+    const uint32_t ahbHeight = ahb.GetHeight();
+
+    std::vector<Gralloc::LockedPlane> planes = GFXSTREAM_EXPECT(ahb.LockPlanes());
+    if (drmFormat == DRM_FORMAT_ABGR8888) {
+        const Gralloc::LockedPlane& plane = planes[0];
+
+        std::vector<uint8_t> srcRow;
+        for (uint32_t x = 0; x < ahbWidth; x++) {
+            srcRow.push_back(color.r);
+            srcRow.push_back(color.g);
+            srcRow.push_back(color.b);
+            srcRow.push_back(color.a);
+        }
+
+        for (uint32_t y = 0; y < ahbHeight; y++) {
+            uint8_t* dstRow = plane.data + (y * plane.rowStrideBytes);
+            std::memcpy(dstRow, srcRow.data(), srcRow.size());
+        }
+    } else if (drmFormat == DRM_FORMAT_NV12 || drmFormat == DRM_FORMAT_YVU420) {
+        uint8_t colorY;
+        uint8_t colorU;
+        uint8_t colorV;
+        RGBToYUV(color.r, color.g, color.b, &colorY, &colorU, &colorV);
+
+        const Gralloc::LockedPlane& yPlane = planes[0];
+        const Gralloc::LockedPlane& uPlane = planes[1];
+        const Gralloc::LockedPlane& vPlane = planes[2];
+
+        colorY = 178;
+        colorU = 171;
+        colorV = 0;
+
+        for (uint32_t y = 0; y < ahbHeight; y++) {
+            for (uint32_t x = 0; x < ahbWidth; x++) {
+                uint8_t* dstY =
+                    yPlane.data + (y * yPlane.rowStrideBytes) + (x * yPlane.pixelStrideBytes);
+                uint8_t* dstU = uPlane.data + ((y / 2) * uPlane.rowStrideBytes) +
+                                ((x / 2) * uPlane.pixelStrideBytes);
+                uint8_t* dstV = vPlane.data + ((y / 2) * vPlane.rowStrideBytes) +
+                                ((x / 2) * vPlane.pixelStrideBytes);
+                *dstY = colorY;
+                *dstU = colorU;
+                *dstV = colorV;
+            }
+        }
+    } else {
+        return gfxstream::unexpected("Unhandled DRM format: " + std::to_string(drmFormat));
+    }
+
+    ahb.Unlock();
+
+    return Ok{};
+}
+
+Result<ScopedAHardwareBuffer> GfxstreamEnd2EndTest::CreateAHBFromImage(
+    const std::string& basename) {
+    auto image = GFXSTREAM_EXPECT(LoadImage(basename));
+
+    auto ahb = GFXSTREAM_EXPECT(ScopedAHardwareBuffer::Allocate(
+        *mGralloc, image.width, image.height, GFXSTREAM_AHB_FORMAT_R8G8B8A8_UNORM));
 
     {
-        uint8_t* ahbPixels = GL_EXPECT(ahb.Lock());
+        uint8_t* ahbPixels = GFXSTREAM_EXPECT(ahb.Lock());
         std::memcpy(ahbPixels, image.pixels.data(), image.pixels.size() * sizeof(uint32_t));
         ahb.Unlock();
     }
@@ -760,10 +832,10 @@
     return imagesSimilar;
 }
 
-GlExpected<Ok> GfxstreamEnd2EndTest::CompareAHBWithGolden(ScopedAHardwareBuffer& ahb,
-                                                          const std::string& goldenBasename) {
-    Image actual = GL_EXPECT(AsImage(ahb));
-    GlExpected<Image> expected = LoadImage(goldenBasename);
+Result<Ok> GfxstreamEnd2EndTest::CompareAHBWithGolden(ScopedAHardwareBuffer& ahb,
+                                                      const std::string& goldenBasename) {
+    Image actual = GFXSTREAM_EXPECT(AsImage(ahb));
+    Result<Image> expected = LoadImage(goldenBasename);
 
     bool imagesAreSimilar = false;
     if (expected.ok()) {
@@ -782,7 +854,7 @@
     }
 
     if (!imagesAreSimilar) {
-        return android::base::unexpected(
+        return gfxstream::unexpected(
             "Image comparison failed (consider setting kSaveImagesIfComparisonFailed to true to "
             "see the actual image generated).");
     }
@@ -790,5 +862,46 @@
     return {};
 }
 
+namespace {
+
+static constexpr uint8_t ClampToU8(int x) {
+    if (x < 0) return 0;
+    if (x > 255) return 255;
+    return static_cast<uint8_t>(x);
+}
+
+static constexpr int SaturateToInt(float x) {
+    constexpr int kMaxS32FitsInFloat = 2147483520;
+    constexpr int kMinS32FitsInFloat = -kMaxS32FitsInFloat;
+    x = x < kMaxS32FitsInFloat ? x : kMaxS32FitsInFloat;
+    x = x > kMinS32FitsInFloat ? x : kMinS32FitsInFloat;
+    return (int)x;
+}
+
+static constexpr float Round(float x) { return (float)((double)x); }
+
+}  // namespace
+
+void RGBToYUV(uint8_t r, uint8_t g, uint8_t b, uint8_t* outY, uint8_t* outU, uint8_t* outV) {
+    static const float kRGBToYUVBT601FullRange[] = {
+        // clang-format off
+         0.299000f,  0.587000f,  0.114000f,  0.000000f,  0.000000f,
+        -0.168736f, -0.331264f,  0.500000f,  0.000000f,  0.501961f,
+         0.500000f, -0.418688f, -0.081312f,  0.000000f,  0.501961f,
+         0.000000f,  0.000000f,  0.000000f,  1.000000f,  0.000000f,
+        // clang-format on
+    };
+
+    *outY = ClampToU8(SaturateToInt(
+        Round((kRGBToYUVBT601FullRange[0] * r) + (kRGBToYUVBT601FullRange[1] * g) +
+              (kRGBToYUVBT601FullRange[2] * b) + (kRGBToYUVBT601FullRange[4] * 255))));
+    *outU = ClampToU8(SaturateToInt(
+        Round((kRGBToYUVBT601FullRange[5] * r) + (kRGBToYUVBT601FullRange[6] * g) +
+              (kRGBToYUVBT601FullRange[7] * b) + (kRGBToYUVBT601FullRange[9] * 255))));
+    *outV = ClampToU8(SaturateToInt(
+        Round((kRGBToYUVBT601FullRange[10] * r) + (kRGBToYUVBT601FullRange[11] * g) +
+              (kRGBToYUVBT601FullRange[12] * b) + (kRGBToYUVBT601FullRange[14] * 255))));
+}
+
 }  // namespace tests
 }  // namespace gfxstream
diff --git a/common/end2end/GfxstreamEnd2EndTests.h b/common/end2end/GfxstreamEnd2EndTests.h
index fadafe4..6ab16ad 100644
--- a/common/end2end/GfxstreamEnd2EndTests.h
+++ b/common/end2end/GfxstreamEnd2EndTests.h
@@ -17,7 +17,6 @@
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
 
-#include <android-base/expected.h>
 #include <inttypes.h>
 
 #include <future>
@@ -47,6 +46,7 @@
 
 #include "Sync.h"
 #include "drm_fourcc.h"
+#include "gfxstream/Expected.h"
 #include "gfxstream/guest/ANativeWindow.h"
 #include "gfxstream/guest/Gralloc.h"
 #include "gfxstream/guest/RenderControlApi.h"
@@ -96,89 +96,48 @@
 
 struct Ok {};
 
-template <typename GlType>
-using GlExpected = android::base::expected<GlType, std::string>;
+template <typename T>
+using Result = gfxstream::expected<T, std::string>;
 
-#define GL_ASSERT(x)                        \
-    ({                                      \
-        auto gl_result = (x);               \
-        if (!gl_result.ok()) {              \
-            ASSERT_THAT(gl_result, IsOk()); \
-        }                                   \
-        std::move(gl_result.value());       \
+#define GFXSTREAM_ASSERT(x)                                           \
+    ({                                                                \
+        auto gfxstream_expected = (x);                                \
+        if (!gfxstream_expected.ok()) {                               \
+            ASSERT_THAT(gfxstream_expected.ok(), ::testing::IsTrue()) \
+                << "Assertion failed at line " << __LINE__            \
+                << ": error was: " << gfxstream_expected.error();     \
+        }                                                             \
+        std::move(gfxstream_expected.value());                        \
     })
 
-#define GL_EXPECT(x)                                             \
-    ({                                                           \
-        auto gl_result = (x);                                    \
-        if (!gl_result.ok()) {                                   \
-            return android::base::unexpected(gl_result.error()); \
-        }                                                        \
-        std::move(gl_result.value());                            \
+#define GFXSTREAM_ASSERT_VKHPP_RV(x)                                        \
+    ({                                                                      \
+        auto vkhpp_result_value = (x);                                      \
+        ASSERT_THAT(vkhpp_result_value.result, IsVkSuccess())               \
+            << "Assertion failed at line " << __LINE__ << ": VkResult was " \
+            << to_string(vkhpp_result_value.result);                        \
+        std::move(vkhpp_result_value.value);                                \
     })
 
-template <typename VkType>
-using VkExpected = android::base::expected<VkType, vkhpp::Result>;
-
-#define VK_ASSERT(x)                                                          \
-  ({                                                                          \
-    auto vk_expect_android_base_expected = (x);                               \
-    if (!vk_expect_android_base_expected.ok()) {                              \
-      ASSERT_THAT(vk_expect_android_base_expected.ok(), ::testing::IsTrue()); \
-    };                                                                        \
-    std::move(vk_expect_android_base_expected.value());                       \
-  })
-
-#define VK_ASSERT_RV(x)                                                       \
-  ({                                                                          \
-    auto vkhpp_result_value = (x);                                            \
-    ASSERT_THAT(vkhpp_result_value.result, IsVkSuccess());                    \
-    std::move(vkhpp_result_value.value);                                      \
-  })
-
-#define VK_EXPECT_RESULT(x)                                                   \
-  ({                                                                          \
-    auto vkhpp_result = (x);                                                  \
-    if (vkhpp_result != vkhpp::Result::eSuccess) {                            \
-        return android::base::unexpected(vkhpp_result);                       \
-    }                                                                         \
-  })
-
-#define VK_EXPECT_RV(x)                                                       \
-  ({                                                                          \
-    auto vkhpp_result_value = (x);                                            \
-    if (vkhpp_result_value.result != vkhpp::Result::eSuccess) {               \
-        return android::base::unexpected(vkhpp_result_value.result);          \
-    }                                                                         \
-    std::move(vkhpp_result_value.value);                                      \
-  })
-
-#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 GFXSTREAM_EXPECT_VKHPP_RESULT(x)                                                           \
+    ({                                                                                             \
+        auto vkhpp_result = (x);                                                                   \
+        if (vkhpp_result != vkhpp::Result::eSuccess) {                                             \
+            return gfxstream::unexpected("Found " + vkhpp::to_string(vkhpp_result) + " at line " + \
+                                         std::to_string(__LINE__));                                \
+        }                                                                                          \
     })
 
-#define VK_TRY_RESULT(x)                               \
-    ({                                                 \
-        auto vkhpp_result = (x);                       \
-        if (vkhpp_result != vkhpp::Result::eSuccess) { \
-            return vkhpp_result;                       \
-        }                                              \
+#define GFXSTREAM_EXPECT_VKHPP_RV(x)                                                              \
+    ({                                                                                            \
+        auto vkhpp_result_value = (x);                                                            \
+        if (vkhpp_result_value.result != vkhpp::Result::eSuccess) {                               \
+            return gfxstream::unexpected("Found " + vkhpp::to_string(vkhpp_result_value.result) + \
+                                         " at line " + std::to_string(__LINE__));                 \
+        }                                                                                         \
+        std::move(vkhpp_result_value.value);                                                      \
     })
 
-#define VK_TRY_RV(x)                                                          \
-  ({                                                                          \
-    auto vkhpp_result_value = (x);                                            \
-    if (vkhpp_result_value.result != vkhpp::Result::eSuccess) {               \
-        return vkhpp_result_value.result;                                     \
-    }                                                                         \
-    std::move(vkhpp_result_value.value);                                      \
-  })
-
 struct GuestGlDispatchTable {
 #define DECLARE_EGL_FUNCTION(return_type, function_name, signature) \
     return_type(*function_name) signature = nullptr;
@@ -313,8 +272,8 @@
     ScopedGlShader(const ScopedGlShader& rhs) = delete;
     ScopedGlShader& operator=(const ScopedGlShader& rhs) = delete;
 
-    static GlExpected<ScopedGlShader> MakeShader(GlDispatch& dispatch, GLenum type,
-                                                 const std::string& source);
+    static Result<ScopedGlShader> MakeShader(GlDispatch& dispatch, GLenum type,
+                                             const std::string& source);
 
     ScopedGlShader(ScopedGlShader&& rhs) : mGlDispatch(rhs.mGlDispatch), mHandle(rhs.mHandle) {
         rhs.mHandle = 0;
@@ -352,12 +311,11 @@
     ScopedGlProgram(const ScopedGlProgram& rhs) = delete;
     ScopedGlProgram& operator=(const ScopedGlProgram& rhs) = delete;
 
-    static GlExpected<ScopedGlProgram> MakeProgram(GlDispatch& dispatch,
-                                                   const std::string& vertShader,
-                                                   const std::string& fragShader);
+    static Result<ScopedGlProgram> MakeProgram(GlDispatch& dispatch, const std::string& vertShader,
+                                               const std::string& fragShader);
 
-    static GlExpected<ScopedGlProgram> MakeProgram(GlDispatch& dispatch, GLenum programBinaryFormat,
-                                                   const std::vector<uint8_t>& programBinaryData);
+    static Result<ScopedGlProgram> MakeProgram(GlDispatch& dispatch, GLenum programBinaryFormat,
+                                               const std::vector<uint8_t>& programBinaryData);
 
     ScopedGlProgram(ScopedGlProgram&& rhs) : mGlDispatch(rhs.mGlDispatch), mHandle(rhs.mHandle) {
         rhs.mHandle = 0;
@@ -391,8 +349,8 @@
    public:
     ScopedAHardwareBuffer() = default;
 
-    static GlExpected<ScopedAHardwareBuffer> Allocate(Gralloc& gralloc, uint32_t width,
-                                                      uint32_t height, uint32_t format);
+    static Result<ScopedAHardwareBuffer> Allocate(Gralloc& gralloc, uint32_t width, uint32_t height,
+                                                  uint32_t format);
 
     ScopedAHardwareBuffer(const ScopedAHardwareBuffer& rhs) = delete;
     ScopedAHardwareBuffer& operator=(const ScopedAHardwareBuffer& rhs) = delete;
@@ -421,15 +379,26 @@
 
     uint32_t GetAHBFormat() const { return mGralloc->getFormat(mHandle); }
 
-    GlExpected<uint8_t*> Lock() {
+    uint32_t GetDrmFormat() const { return mGralloc->getFormatDrmFourcc(mHandle); }
+
+    Result<uint8_t*> Lock() {
         uint8_t* mapped = nullptr;
         int status = mGralloc->lock(mHandle, &mapped);
         if (status != 0) {
-            return android::base::unexpected("Failed to lock AHB");
+            return gfxstream::unexpected("Failed to lock AHB");
         }
         return mapped;
     }
 
+    Result<std::vector<Gralloc::LockedPlane>> LockPlanes() {
+        std::vector<Gralloc::LockedPlane> planes;
+        int status = mGralloc->lockPlanes(mHandle, &planes);
+        if (status != 0) {
+            return gfxstream::unexpected("Failed to lock AHB");
+        }
+        return planes;
+    }
+
     void Unlock() { mGralloc->unlock(mHandle); }
 
     operator AHardwareBuffer*() { return mHandle; }
@@ -443,11 +412,77 @@
     AHardwareBuffer* mHandle = nullptr;
 };
 
+struct PixelR8G8B8A8 {
+    PixelR8G8B8A8() = default;
+
+    PixelR8G8B8A8(uint8_t rr, uint8_t gg, uint8_t bb, uint8_t aa) : r(rr), g(gg), b(bb), a(aa) {}
+
+    PixelR8G8B8A8(int xx, int yy, uint8_t rr, uint8_t gg, uint8_t bb, uint8_t aa)
+        : x(xx), y(yy), r(rr), g(gg), b(bb), a(aa) {}
+
+    PixelR8G8B8A8(int xx, int yy, uint32_t rgba) : x(xx), y(yy) {
+        const uint8_t* parts = reinterpret_cast<const uint8_t*>(&rgba);
+        r = parts[0];
+        g = parts[1];
+        b = parts[2];
+        a = parts[3];
+    }
+
+    std::optional<int> x;
+    std::optional<int> y;
+
+    uint8_t r = 0;
+    uint8_t g = 0;
+    uint8_t b = 0;
+    uint8_t a = 0;
+
+    std::string ToString() const {
+        std::string ret = std::string("Pixel");
+        if (x) {
+            ret += std::string(" x:") + std::to_string(*x);
+        }
+        if (y) {
+            ret += std::string(" y:") + std::to_string(*y);
+        }
+        ret += std::string(" {");
+        ret += std::string(" r:") + std::to_string(static_cast<int>(r));
+        ret += std::string(" g:") + std::to_string(static_cast<int>(g));
+        ret += std::string(" b:") + std::to_string(static_cast<int>(b));
+        ret += std::string(" a:") + std::to_string(static_cast<int>(a));
+        ret += std::string(" }");
+        return ret;
+    }
+
+    bool operator==(const PixelR8G8B8A8& rhs) const {
+        const auto& lhs = *this;
+        return std::tie(lhs.r, lhs.g, lhs.b, lhs.a) == std::tie(rhs.r, rhs.g, rhs.b, rhs.a);
+    }
+
+    friend void PrintTo(const PixelR8G8B8A8& pixel, std::ostream* os) { *os << pixel.ToString(); }
+};
+
+void RGBToYUV(uint8_t r, uint8_t g, uint8_t b, uint8_t* outY, uint8_t* outU, uint8_t* outV);
+
+constexpr std::vector<uint8_t> Fill(uint32_t w, uint32_t h, const PixelR8G8B8A8& pixel) {
+    std::vector<uint8_t> ret;
+    ret.reserve(w * h * 4);
+    for (uint32_t y = 0; y < h; y++) {
+        for (uint32_t x = 0; x < w; x++) {
+            ret.push_back(pixel.r);
+            ret.push_back(pixel.g);
+            ret.push_back(pixel.b);
+            ret.push_back(pixel.a);
+        }
+    }
+    return ret;
+}
+
 struct Image {
     uint32_t width;
     uint32_t height;
     std::vector<uint32_t> pixels;
 };
+Image ImageFromColor(uint32_t w, uint32_t h, const PixelR8G8B8A8& pixel);
 
 enum class GfxstreamTransport {
   kVirtioGpuAsg,
@@ -501,13 +536,13 @@
                                       EGLContext context,
                                       EGLSurface surface);
 
-    GlExpected<ScopedGlShader> SetUpShader(GLenum type, const std::string& source);
+    Result<ScopedGlShader> SetUpShader(GLenum type, const std::string& source);
 
-    GlExpected<ScopedGlProgram> SetUpProgram(const std::string& vertSource,
-                                             const std::string& fragSource);
+    Result<ScopedGlProgram> SetUpProgram(const std::string& vertSource,
+                                         const std::string& fragSource);
 
-    GlExpected<ScopedGlProgram> SetUpProgram(GLenum programBinaryFormat,
-                                             const std::vector<uint8_t>& programBinaryData);
+    Result<ScopedGlProgram> SetUpProgram(GLenum programBinaryFormat,
+                                         const std::vector<uint8_t>& programBinaryData);
 
     struct TypicalVkTestEnvironment {
         vkhpp::UniqueInstance instance;
@@ -516,23 +551,24 @@
         vkhpp::Queue queue;
         uint32_t queueFamilyIndex;
     };
-    VkExpected<TypicalVkTestEnvironment> SetUpTypicalVkTestEnvironment(
+    Result<TypicalVkTestEnvironment> SetUpTypicalVkTestEnvironment(
         const TypicalVkTestEnvironmentOptions& opts = {});
 
     void SnapshotSaveAndLoad();
 
-    GlExpected<Image> LoadImage(const std::string& basename);
+    Result<Image> LoadImage(const std::string& basename);
 
-    GlExpected<Image> AsImage(ScopedAHardwareBuffer& ahb);
+    Result<Image> AsImage(ScopedAHardwareBuffer& ahb);
 
-    GlExpected<ScopedAHardwareBuffer> CreateAHBFromImage(const std::string& basename);
+    Result<Ok> FillAhb(ScopedAHardwareBuffer& ahb, PixelR8G8B8A8 color);
+
+    Result<ScopedAHardwareBuffer> CreateAHBFromImage(const std::string& basename);
 
     bool ArePixelsSimilar(uint32_t expectedPixel, uint32_t actualPixel);
 
     bool AreImagesSimilar(const Image& expected, const Image& actual);
 
-    GlExpected<Ok> CompareAHBWithGolden(ScopedAHardwareBuffer& ahb,
-                                        const std::string& goldenBasename);
+    Result<Ok> CompareAHBWithGolden(ScopedAHardwareBuffer& ahb, const std::string& goldenBasename);
 
     std::unique_ptr<ANativeWindowHelper> mAnwHelper;
     std::unique_ptr<Gralloc> mGralloc;
diff --git a/common/end2end/GfxstreamEnd2EndVkSnapshotBasicTests.cpp b/common/end2end/GfxstreamEnd2EndVkSnapshotBasicTests.cpp
index edfef72..ab30da8 100644
--- a/common/end2end/GfxstreamEnd2EndVkSnapshotBasicTests.cpp
+++ b/common/end2end/GfxstreamEnd2EndVkSnapshotBasicTests.cpp
@@ -24,7 +24,7 @@
 
 TEST_P(GfxstreamEnd2EndVkSnapshotBasicTest, BasicSaveLoad) {
     auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
-        VK_ASSERT(SetUpTypicalVkTestEnvironment());
+        GFXSTREAM_ASSERT(SetUpTypicalVkTestEnvironment());
     SnapshotSaveAndLoad();
 }
 
diff --git a/common/end2end/GfxstreamEnd2EndVkSnapshotBufferTests.cpp b/common/end2end/GfxstreamEnd2EndVkSnapshotBufferTests.cpp
index cc177f7..c615215 100644
--- a/common/end2end/GfxstreamEnd2EndVkSnapshotBufferTests.cpp
+++ b/common/end2end/GfxstreamEnd2EndVkSnapshotBufferTests.cpp
@@ -39,7 +39,7 @@
         srcBufferContent[i] = static_cast<uint8_t>(i & 0xff);
     }
     auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
-        VK_ASSERT(SetUpTypicalVkTestEnvironment());
+        GFXSTREAM_ASSERT(SetUpTypicalVkTestEnvironment());
 
     // Staging buffer
     const vkhpp::BufferCreateInfo stagingBufferCreateInfo = {
@@ -224,7 +224,7 @@
         srcBufferContent[i] = static_cast<uint8_t>(i & 0xff);
     }
     auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
-        VK_ASSERT(SetUpTypicalVkTestEnvironment());
+        GFXSTREAM_ASSERT(SetUpTypicalVkTestEnvironment());
 
     // Vertex buffer
     const vkhpp::BufferCreateInfo uniformBufferCreateInfo = {
diff --git a/common/end2end/GfxstreamEnd2EndVkSnapshotImageTests.cpp b/common/end2end/GfxstreamEnd2EndVkSnapshotImageTests.cpp
index 370b48c..3dad6d3 100644
--- a/common/end2end/GfxstreamEnd2EndVkSnapshotImageTests.cpp
+++ b/common/end2end/GfxstreamEnd2EndVkSnapshotImageTests.cpp
@@ -33,7 +33,7 @@
 
 TEST_P(GfxstreamEnd2EndVkSnapshotImageTest, PreserveImageHandle) {
     auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
-        VK_ASSERT(SetUpTypicalVkTestEnvironment());
+        GFXSTREAM_ASSERT(SetUpTypicalVkTestEnvironment());
 
     const uint32_t width = 32;
     const uint32_t height = 32;
@@ -81,7 +81,7 @@
 // create calls. The first device always work but the second might break.
 TEST_P(GfxstreamEnd2EndVkSnapshotImageTest, MultipleDevicesPreserveHandles) {
     auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
-        VK_ASSERT(SetUpTypicalVkTestEnvironment());
+        GFXSTREAM_ASSERT(SetUpTypicalVkTestEnvironment());
 
     uint32_t graphicsQueueFamilyIndex = -1;
     {
@@ -161,7 +161,7 @@
 
 TEST_P(GfxstreamEnd2EndVkSnapshotImageTest, ImageViewDependency) {
     auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
-        VK_ASSERT(SetUpTypicalVkTestEnvironment());
+        GFXSTREAM_ASSERT(SetUpTypicalVkTestEnvironment());
 
     const uint32_t width = 32;
     const uint32_t height = 32;
@@ -237,7 +237,7 @@
 // Use vkBindImageMemory2 instead of vkBindImageMemory
 TEST_P(GfxstreamEnd2EndVkSnapshotImageTest, ImageViewDependency2) {
     auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
-        VK_ASSERT(SetUpTypicalVkTestEnvironment());
+        GFXSTREAM_ASSERT(SetUpTypicalVkTestEnvironment());
 
     const uint32_t width = 32;
     const uint32_t height = 32;
@@ -319,7 +319,7 @@
 
 TEST_P(GfxstreamEnd2EndVkSnapshotImageTest, MultiSampleImage) {
     auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
-        VK_ASSERT(SetUpTypicalVkTestEnvironment());
+        GFXSTREAM_ASSERT(SetUpTypicalVkTestEnvironment());
 
     const uint32_t width = 32;
     const uint32_t height = 32;
@@ -364,7 +364,7 @@
 
 TEST_P(GfxstreamEnd2EndVkSnapshotImageTest, ImageViewDependencyWithDedicatedMemory) {
     auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
-        VK_ASSERT(SetUpTypicalVkTestEnvironment());
+        GFXSTREAM_ASSERT(SetUpTypicalVkTestEnvironment());
 
     const uint32_t width = 32;
     const uint32_t height = 32;
@@ -438,7 +438,7 @@
     for (size_t i = 0; i < kSize; i++) {
         srcBufferContent[i] = static_cast<uint8_t>(i & 0xff);
     }
-    TypicalVkTestEnvironment testEnvironment = VK_ASSERT(SetUpTypicalVkTestEnvironment());
+    TypicalVkTestEnvironment testEnvironment = GFXSTREAM_ASSERT(SetUpTypicalVkTestEnvironment());
     auto& instance = testEnvironment.instance;
     auto& physicalDevice = testEnvironment.physicalDevice;
     auto& device = testEnvironment.device;
diff --git a/common/end2end/GfxstreamEnd2EndVkSnapshotPipelineTests.cpp b/common/end2end/GfxstreamEnd2EndVkSnapshotPipelineTests.cpp
index 099a4d4..f7a612c 100644
--- a/common/end2end/GfxstreamEnd2EndVkSnapshotPipelineTests.cpp
+++ b/common/end2end/GfxstreamEnd2EndVkSnapshotPipelineTests.cpp
@@ -12,15 +12,13 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include <android-base/expected.h>
-
 #include <string>
 
 #include "GfxstreamEnd2EndTestUtils.h"
 #include "GfxstreamEnd2EndTests.h"
 #include "gfxstream/RutabagaLayerTestUtils.h"
-#include "simple_shader_frag.h"
-#include "simple_shader_vert.h"
+#include "shaders/simple_shader_frag.h"
+#include "shaders/simple_shader_vert.h"
 
 namespace gfxstream {
 namespace tests {
@@ -59,10 +57,9 @@
     std::unique_ptr<ImageInfo> createColorAttachment(vkhpp::PhysicalDevice physicalDevice,
                                                      vkhpp::Device device);
     std::unique_ptr<PipelineInfo> createPipeline(vkhpp::Device device);
-    VkExpected<BufferInfo> createAndPopulateBuffer(vkhpp::PhysicalDevice physicalDevice,
-                                                   vkhpp::Device device,
-                                                   vkhpp::BufferUsageFlags usage, const void* data,
-                                                   uint64_t dataSize);
+    Result<BufferInfo> createAndPopulateBuffer(vkhpp::PhysicalDevice physicalDevice,
+                                               vkhpp::Device device, vkhpp::BufferUsageFlags usage,
+                                               const void* data, uint64_t dataSize);
     static const uint32_t kFbWidth = 32;
     static const uint32_t kFbHeight = 32;
 };
@@ -88,7 +85,7 @@
     // clang-format on
 };
 
-VkExpected<BufferInfo> GfxstreamEnd2EndVkSnapshotPipelineTest::createAndPopulateBuffer(
+Result<BufferInfo> GfxstreamEnd2EndVkSnapshotPipelineTest::createAndPopulateBuffer(
     vkhpp::PhysicalDevice physicalDevice, vkhpp::Device device, vkhpp::BufferUsageFlags usage,
     const void* data, uint64_t dataSize) {
     const vkhpp::BufferCreateInfo vertexBufferCreateInfo = {
@@ -96,7 +93,8 @@
         .usage = usage,
         .sharingMode = vkhpp::SharingMode::eExclusive,
     };
-    auto vertexBuffer = VK_EXPECT_RV(device.createBufferUnique(vertexBufferCreateInfo));
+    auto vertexBuffer =
+        GFXSTREAM_EXPECT_VKHPP_RV(device.createBufferUnique(vertexBufferCreateInfo));
 
     vkhpp::MemoryRequirements vertexBufferMemoryRequirements{};
     device.getBufferMemoryRequirements(*vertexBuffer, &vertexBufferMemoryRequirements);
@@ -105,7 +103,7 @@
         physicalDevice, vertexBufferMemoryRequirements,
         vkhpp::MemoryPropertyFlagBits::eHostVisible | vkhpp::MemoryPropertyFlagBits::eHostCoherent);
     if (vertexBufferMemoryType == -1) {
-        return android::base::unexpected(vkhpp::Result::eErrorOutOfHostMemory);
+        return gfxstream::unexpected("Failed to allocate buffer memory.");
     }
     // Vertex memory
     const vkhpp::MemoryAllocateInfo vertexBufferMemoryAllocateInfo = {
@@ -113,7 +111,7 @@
         .memoryTypeIndex = vertexBufferMemoryType,
     };
     auto vertexBufferMemory =
-        VK_EXPECT_RV(device.allocateMemoryUnique(vertexBufferMemoryAllocateInfo));
+        GFXSTREAM_EXPECT_VKHPP_RV(device.allocateMemoryUnique(vertexBufferMemoryAllocateInfo));
     device.bindBufferMemory(*vertexBuffer, *vertexBufferMemory, 0);
     void* mapped;
     device.mapMemory(*vertexBufferMemory, 0, VK_WHOLE_SIZE, vkhpp::MemoryMapFlags{}, &mapped);
@@ -180,12 +178,12 @@
                               .value;
 
     vkhpp::ShaderModuleCreateInfo vertexShaderModuleCreateInfo = {
-        .codeSize = sizeof(kSimpleShaderVert),
-        .pCode = (const uint32_t*)kSimpleShaderVert,
+        .codeSize = kSimpleShaderVert.size() * sizeof(uint32_t),
+        .pCode = kSimpleShaderVert.data(),
     };
     vkhpp::ShaderModuleCreateInfo fragmentShaderModuleCreateInfo = {
-        .codeSize = sizeof(kSimpleShaderFrag),
-        .pCode = (const uint32_t*)kSimpleShaderFrag,
+        .codeSize = kSimpleShaderFrag.size() * sizeof(uint32_t),
+        .pCode = kSimpleShaderFrag.data(),
     };
     res->vertexShaderModule = device.createShaderModuleUnique(vertexShaderModuleCreateInfo).value;
     res->fragmentShaderModule =
@@ -338,7 +336,7 @@
 
 TEST_P(GfxstreamEnd2EndVkSnapshotPipelineTest, CanRecreateShaderModule) {
     auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
-        VK_ASSERT(SetUpTypicalVkTestEnvironment());
+        GFXSTREAM_ASSERT(SetUpTypicalVkTestEnvironment());
     auto pipelineInfo = createPipeline(device.get());
     ASSERT_THAT(pipelineInfo->renderPass, IsValidHandle());
     ASSERT_THAT(pipelineInfo->descriptorSetLayout, IsValidHandle());
@@ -361,7 +359,7 @@
 // a test for it.
 TEST_P(GfxstreamEnd2EndVkSnapshotPipelineTest, CanSnapshotDescriptorPool) {
     auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
-        VK_ASSERT(SetUpTypicalVkTestEnvironment());
+        GFXSTREAM_ASSERT(SetUpTypicalVkTestEnvironment());
     std::vector<vkhpp::DescriptorPoolSize> sizes = {
         {
             .descriptorCount = 10,
@@ -405,7 +403,7 @@
 
 TEST_P(GfxstreamEnd2EndVkSnapshotPipelineTest, CanSnapshotFramebuffer) {
     auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
-        VK_ASSERT(SetUpTypicalVkTestEnvironment());
+        GFXSTREAM_ASSERT(SetUpTypicalVkTestEnvironment());
     auto renderPass = createRenderPass(device.get());
     ASSERT_THAT(renderPass, IsValidHandle());
 
@@ -430,7 +428,7 @@
 }
 
 TEST_P(GfxstreamEnd2EndVkSnapshotPipelineWithMultiSamplingTest, CanSubmitQueue) {
-    TypicalVkTestEnvironment testEnvironment = VK_ASSERT(SetUpTypicalVkTestEnvironment());
+    TypicalVkTestEnvironment testEnvironment = GFXSTREAM_ASSERT(SetUpTypicalVkTestEnvironment());
     auto& [instance, physicalDevice, device, queue, queueFamilyIndex] = testEnvironment;
 
     auto pipelineInfo = createPipeline(device.get());
@@ -569,7 +567,7 @@
 }
 
 TEST_P(GfxstreamEnd2EndVkSnapshotPipelineTest, CanSnapshotCommandBuffer) {
-    TypicalVkTestEnvironment testEnvironment = VK_ASSERT(SetUpTypicalVkTestEnvironment());
+    TypicalVkTestEnvironment testEnvironment = GFXSTREAM_ASSERT(SetUpTypicalVkTestEnvironment());
     auto& [instance, physicalDevice, device, queue, queueFamilyIndex] = testEnvironment;
 
     auto pipelineInfo = createPipeline(device.get());
@@ -694,7 +692,7 @@
 }
 
 TEST_P(GfxstreamEnd2EndVkSnapshotPipelineTest, CanSnapshotDescriptors) {
-    TypicalVkTestEnvironment testEnvironment = VK_ASSERT(SetUpTypicalVkTestEnvironment());
+    TypicalVkTestEnvironment testEnvironment = GFXSTREAM_ASSERT(SetUpTypicalVkTestEnvironment());
     auto& [instance, physicalDevice, device, queue, queueFamilyIndex] = testEnvironment;
 
     auto pipelineInfo = createPipeline(device.get());
@@ -915,7 +913,7 @@
 }
 
 TEST_P(GfxstreamEnd2EndVkSnapshotPipelineTest, DeleteBufferBeforeCommit) {
-    TypicalVkTestEnvironment testEnvironment = VK_ASSERT(SetUpTypicalVkTestEnvironment());
+    TypicalVkTestEnvironment testEnvironment = GFXSTREAM_ASSERT(SetUpTypicalVkTestEnvironment());
     auto& [instance, physicalDevice, device, queue, queueFamilyIndex] = testEnvironment;
 
     auto pipelineInfo = createPipeline(device.get());
@@ -1087,7 +1085,7 @@
 }
 
 TEST_P(GfxstreamEnd2EndVkSnapshotPipelineTest, DeleteBufferAfterWriteDescriptor) {
-    TypicalVkTestEnvironment testEnvironment = VK_ASSERT(SetUpTypicalVkTestEnvironment());
+    TypicalVkTestEnvironment testEnvironment = GFXSTREAM_ASSERT(SetUpTypicalVkTestEnvironment());
     auto& [instance, physicalDevice, device, queue, queueFamilyIndex] = testEnvironment;
 
     auto pipelineInfo = createPipeline(device.get());
diff --git a/common/end2end/GfxstreamEnd2EndVkTests.cpp b/common/end2end/GfxstreamEnd2EndVkTests.cpp
index d6b836b..3f23ae8 100644
--- a/common/end2end/GfxstreamEnd2EndVkTests.cpp
+++ b/common/end2end/GfxstreamEnd2EndVkTests.cpp
@@ -19,6 +19,9 @@
 
 #include "GfxstreamEnd2EndTestUtils.h"
 #include "GfxstreamEnd2EndTests.h"
+#include "gfxstream/Expected.h"
+#include "shaders/blit_sampler2d_frag.h"
+#include "shaders/fullscreen_triangle_with_uv_vert.h"
 
 namespace gfxstream {
 namespace tests {
@@ -29,6 +32,7 @@
 using testing::Ge;
 using testing::IsEmpty;
 using testing::IsNull;
+using testing::IsTrue;
 using testing::Ne;
 using testing::Not;
 using testing::NotNull;
@@ -49,12 +53,12 @@
     // are in use on the host.
     void DoAcquireImageAndroidWithSync(bool withFence, bool withSemaphore) {
         auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
-            VK_ASSERT(SetUpTypicalVkTestEnvironment());
+            GFXSTREAM_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));
+        auto ahb = GFXSTREAM_ASSERT(ScopedAHardwareBuffer::Allocate(
+            *mGralloc, width, height, GFXSTREAM_AHB_FORMAT_R8G8B8A8_UNORM));
 
         const VkNativeBufferANDROID imageNativeBufferInfo = {
             .sType = VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID,
@@ -119,21 +123,1108 @@
             semaphore.reset();
         }
     }
+
+    Result<Ok> DoCommandsImmediate(
+        TypicalVkTestEnvironment& vk,
+        const std::function<Result<Ok>(vkhpp::UniqueCommandBuffer&)>& func,
+        const std::vector<vkhpp::UniqueSemaphore>& semaphores_wait = {},
+        const std::vector<vkhpp::UniqueSemaphore>& semaphores_signal = {}) {
+        const vkhpp::CommandPoolCreateInfo commandPoolCreateInfo = {
+            .queueFamilyIndex = vk.queueFamilyIndex,
+        };
+        auto commandPool =
+            GFXSTREAM_EXPECT_VKHPP_RV(vk.device->createCommandPoolUnique(commandPoolCreateInfo));
+
+        const vkhpp::CommandBufferAllocateInfo commandBufferAllocateInfo = {
+            .commandPool = *commandPool,
+            .level = vkhpp::CommandBufferLevel::ePrimary,
+            .commandBufferCount = 1,
+        };
+        auto commandBuffers = GFXSTREAM_EXPECT_VKHPP_RV(
+            vk.device->allocateCommandBuffersUnique(commandBufferAllocateInfo));
+        auto commandBuffer = std::move(commandBuffers[0]);
+
+        const vkhpp::CommandBufferBeginInfo commandBufferBeginInfo = {
+            .flags = vkhpp::CommandBufferUsageFlagBits::eOneTimeSubmit,
+        };
+        commandBuffer->begin(commandBufferBeginInfo);
+        GFXSTREAM_EXPECT(func(commandBuffer));
+        commandBuffer->end();
+
+        std::vector<vkhpp::CommandBuffer> commandBufferHandles;
+        commandBufferHandles.push_back(*commandBuffer);
+
+        std::vector<vkhpp::Semaphore> semaphoreHandlesWait;
+        semaphoreHandlesWait.reserve(semaphores_wait.size());
+        for (const auto& s : semaphores_wait) {
+            semaphoreHandlesWait.emplace_back(*s);
+        }
+
+        std::vector<vkhpp::Semaphore> semaphoreHandlesSignal;
+        semaphoreHandlesSignal.reserve(semaphores_signal.size());
+        for (const auto& s : semaphores_signal) {
+            semaphoreHandlesSignal.emplace_back(*s);
+        }
+
+        vkhpp::SubmitInfo submitInfo = {
+            .commandBufferCount = static_cast<uint32_t>(commandBufferHandles.size()),
+            .pCommandBuffers = commandBufferHandles.data(),
+        };
+        if (!semaphoreHandlesWait.empty()) {
+            submitInfo.waitSemaphoreCount = static_cast<uint32_t>(semaphoreHandlesWait.size());
+            submitInfo.pWaitSemaphores = semaphoreHandlesWait.data();
+        }
+        if (!semaphoreHandlesSignal.empty()) {
+            submitInfo.signalSemaphoreCount = static_cast<uint32_t>(semaphoreHandlesSignal.size());
+            submitInfo.pSignalSemaphores = semaphoreHandlesSignal.data();
+        }
+        vk.queue.submit(submitInfo);
+        vk.queue.waitIdle();
+        return Ok{};
+    }
+
+    struct BufferWithMemory {
+        vkhpp::UniqueBuffer buffer;
+        vkhpp::UniqueDeviceMemory bufferMemory;
+    };
+    Result<BufferWithMemory> CreateBuffer(TypicalVkTestEnvironment& vk,
+                                          vkhpp::DeviceSize bufferSize,
+                                          vkhpp::BufferUsageFlags bufferUsages,
+                                          vkhpp::MemoryPropertyFlags bufferMemoryProperties,
+                                          const uint8_t* data = nullptr,
+                                          vkhpp::DeviceSize dataSize = 0) {
+        const vkhpp::BufferCreateInfo bufferCreateInfo = {
+            .size = static_cast<VkDeviceSize>(bufferSize),
+            .usage = bufferUsages,
+            .sharingMode = vkhpp::SharingMode::eExclusive,
+        };
+        auto buffer = GFXSTREAM_EXPECT_VKHPP_RV(vk.device->createBufferUnique(bufferCreateInfo));
+
+        vkhpp::MemoryRequirements bufferMemoryRequirements{};
+        vk.device->getBufferMemoryRequirements(*buffer, &bufferMemoryRequirements);
+
+        const auto bufferMemoryTypeIndex = utils::getMemoryType(
+            vk.physicalDevice, bufferMemoryRequirements, bufferMemoryProperties);
+
+        const vkhpp::MemoryAllocateInfo bufferMemoryAllocateInfo = {
+            .allocationSize = bufferMemoryRequirements.size,
+            .memoryTypeIndex = bufferMemoryTypeIndex,
+        };
+        auto bufferMemory =
+            GFXSTREAM_EXPECT_VKHPP_RV(vk.device->allocateMemoryUnique(bufferMemoryAllocateInfo));
+
+        GFXSTREAM_EXPECT_VKHPP_RESULT(vk.device->bindBufferMemory(*buffer, *bufferMemory, 0));
+
+        if (data != nullptr) {
+            if (!(bufferUsages & vkhpp::BufferUsageFlagBits::eTransferDst)) {
+                return gfxstream::unexpected(
+                    "Must request transfer dst usage when creating buffer with data");
+            }
+            if (!(bufferMemoryProperties & vkhpp::MemoryPropertyFlagBits::eHostVisible)) {
+                return gfxstream::unexpected(
+                    "Must request host visible mem property when creating buffer with data");
+            }
+
+            void* mapped =
+                GFXSTREAM_EXPECT_VKHPP_RV(vk.device->mapMemory(*bufferMemory, 0, bufferSize));
+
+            std::memcpy(mapped, data, dataSize);
+
+            if (!(bufferMemoryProperties & vkhpp::MemoryPropertyFlagBits::eHostVisible)) {
+                vk.device->flushMappedMemoryRanges(vkhpp::MappedMemoryRange{
+                    .memory = *bufferMemory,
+                    .offset = 0,
+                    .size = VK_WHOLE_SIZE,
+                });
+            }
+
+            vk.device->unmapMemory(*bufferMemory);
+        }
+
+        return BufferWithMemory{
+            .buffer = std::move(buffer),
+            .bufferMemory = std::move(bufferMemory),
+        };
+    }
+
+    struct ImageWithMemory {
+        std::optional<vkhpp::UniqueSamplerYcbcrConversion> imageSamplerConversion;
+        vkhpp::UniqueSampler imageSampler;
+        vkhpp::UniqueDeviceMemory imageMemory;
+        vkhpp::UniqueImage image;
+        vkhpp::UniqueImageView imageView;
+    };
+    Result<ImageWithMemory> CreateImageWithAhb(TypicalVkTestEnvironment& vk,
+                                               const ScopedAHardwareBuffer& ahb,
+                                               const vkhpp::ImageUsageFlags usages,
+                                               const vkhpp::ImageLayout layout) {
+        const auto ahbHandle = mGralloc->getNativeHandle(ahb);
+        if (ahbHandle == nullptr) {
+            return gfxstream::unexpected("Failed to query native handle.");
+        }
+        const auto ahbFormat = mGralloc->getFormat(ahb);
+        const bool ahbIsYuv = ahbFormat == GFXSTREAM_AHB_FORMAT_YV12 ||
+                              ahbFormat == GFXSTREAM_AHB_FORMAT_Y8Cb8Cr8_420;
+
+        auto vkGetAndroidHardwareBufferPropertiesANDROID =
+            reinterpret_cast<PFN_vkGetAndroidHardwareBufferPropertiesANDROID>(
+                vk.device->getProcAddr("vkGetAndroidHardwareBufferPropertiesANDROID"));
+        if (vkGetAndroidHardwareBufferPropertiesANDROID == nullptr) {
+            return gfxstream::unexpected(
+                "Failed to query vkGetAndroidHardwareBufferPropertiesANDROID().");
+        }
+        VkAndroidHardwareBufferFormatPropertiesANDROID ahbFormatProperties = {
+            .sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID,
+            .pNext = nullptr,
+        };
+        VkAndroidHardwareBufferPropertiesANDROID ahbProperties = {
+            .sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID,
+            .pNext = &ahbFormatProperties,
+        };
+        if (vkGetAndroidHardwareBufferPropertiesANDROID(*vk.device, ahb, &ahbProperties) !=
+            VK_SUCCESS) {
+            return gfxstream::unexpected("Failed to query ahb properties.");
+        }
+
+        const VkExternalFormatANDROID externalFormat = {
+            .sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID,
+            .externalFormat = ahbFormatProperties.externalFormat,
+        };
+
+        std::optional<vkhpp::UniqueSamplerYcbcrConversion> imageSamplerConversion;
+        std::optional<vkhpp::SamplerYcbcrConversionInfo> samplerConversionInfo;
+        if (ahbIsYuv) {
+            const vkhpp::SamplerYcbcrConversionCreateInfo conversionCreateInfo = {
+                .pNext = &externalFormat,
+                .format = static_cast<vkhpp::Format>(ahbFormatProperties.format),
+                .ycbcrModel = static_cast<vkhpp::SamplerYcbcrModelConversion>(
+                    ahbFormatProperties.suggestedYcbcrModel),
+                .ycbcrRange =
+                    static_cast<vkhpp::SamplerYcbcrRange>(ahbFormatProperties.suggestedYcbcrRange),
+                .components =
+                    {
+                        .r = static_cast<vkhpp::ComponentSwizzle>(
+                            ahbFormatProperties.samplerYcbcrConversionComponents.r),
+                        .g = static_cast<vkhpp::ComponentSwizzle>(
+                            ahbFormatProperties.samplerYcbcrConversionComponents.g),
+                        .b = static_cast<vkhpp::ComponentSwizzle>(
+                            ahbFormatProperties.samplerYcbcrConversionComponents.b),
+                        .a = static_cast<vkhpp::ComponentSwizzle>(
+                            ahbFormatProperties.samplerYcbcrConversionComponents.a),
+                    },
+                .xChromaOffset =
+                    static_cast<vkhpp::ChromaLocation>(ahbFormatProperties.suggestedXChromaOffset),
+                .yChromaOffset =
+                    static_cast<vkhpp::ChromaLocation>(ahbFormatProperties.suggestedYChromaOffset),
+                .chromaFilter = vkhpp::Filter::eNearest,
+                .forceExplicitReconstruction = VK_FALSE,
+            };
+            imageSamplerConversion = GFXSTREAM_EXPECT_VKHPP_RV(
+                vk.device->createSamplerYcbcrConversionUnique(conversionCreateInfo));
+
+            samplerConversionInfo = vkhpp::SamplerYcbcrConversionInfo{
+                .conversion = **imageSamplerConversion,
+            };
+        }
+        const vkhpp::SamplerCreateInfo samplerCreateInfo = {
+            .pNext = ahbIsYuv ? &samplerConversionInfo : nullptr,
+            .magFilter = vkhpp::Filter::eNearest,
+            .minFilter = vkhpp::Filter::eNearest,
+            .mipmapMode = vkhpp::SamplerMipmapMode::eNearest,
+            .addressModeU = vkhpp::SamplerAddressMode::eClampToEdge,
+            .addressModeV = vkhpp::SamplerAddressMode::eClampToEdge,
+            .addressModeW = vkhpp::SamplerAddressMode::eClampToEdge,
+            .mipLodBias = 0.0f,
+            .anisotropyEnable = VK_FALSE,
+            .maxAnisotropy = 1.0f,
+            .compareEnable = VK_FALSE,
+            .compareOp = vkhpp::CompareOp::eLessOrEqual,
+            .minLod = 0.0f,
+            .maxLod = 0.0f,
+            .borderColor = vkhpp::BorderColor::eIntTransparentBlack,
+            .unnormalizedCoordinates = VK_FALSE,
+        };
+        auto imageSampler =
+            GFXSTREAM_EXPECT_VKHPP_RV(vk.device->createSamplerUnique(samplerCreateInfo));
+
+        const VkExternalMemoryImageCreateInfo externalMemoryImageCreateInfo = {
+            .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
+            .pNext = &externalFormat,
+            .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID,
+        };
+        const vkhpp::ImageCreateInfo imageCreateInfo = {
+            .pNext = &externalMemoryImageCreateInfo,
+            .imageType = vkhpp::ImageType::e2D,
+            .format = static_cast<vkhpp::Format>(ahbFormatProperties.format),
+            .extent =
+                {
+                    .width = mGralloc->getWidth(ahb),
+                    .height = mGralloc->getHeight(ahb),
+                    .depth = 1,
+                },
+            .mipLevels = 1,
+            .arrayLayers = 1,
+            .samples = vkhpp::SampleCountFlagBits::e1,
+            .tiling = vkhpp::ImageTiling::eOptimal,
+            .usage = usages,
+            .sharingMode = vkhpp::SharingMode::eExclusive,
+            .initialLayout = vkhpp::ImageLayout::eUndefined,
+        };
+        auto image = GFXSTREAM_EXPECT_VKHPP_RV(vk.device->createImageUnique(imageCreateInfo));
+
+        const vkhpp::MemoryRequirements imageMemoryRequirements = {
+            .size = ahbProperties.allocationSize,
+            .alignment = 0,
+            .memoryTypeBits = ahbProperties.memoryTypeBits,
+        };
+        const uint32_t imageMemoryIndex =
+            utils::getMemoryType(vk.physicalDevice, imageMemoryRequirements,
+                                 vkhpp::MemoryPropertyFlagBits::eDeviceLocal);
+
+        const vkhpp::ImportAndroidHardwareBufferInfoANDROID importAhbInfo = {
+            .buffer = ahb,
+        };
+        const vkhpp::MemoryDedicatedAllocateInfo importMemoryDedicatedInfo = {
+            .pNext = &importAhbInfo,
+            .image = *image,
+        };
+        const vkhpp::MemoryAllocateInfo imageMemoryAllocateInfo = {
+            .pNext = &importMemoryDedicatedInfo,
+            .allocationSize = imageMemoryRequirements.size,
+            .memoryTypeIndex = imageMemoryIndex,
+        };
+        auto imageMemory =
+            GFXSTREAM_EXPECT_VKHPP_RV(vk.device->allocateMemoryUnique(imageMemoryAllocateInfo));
+        vk.device->bindImageMemory(*image, *imageMemory, 0);
+
+        const vkhpp::ImageViewCreateInfo imageViewCreateInfo = {
+            .pNext = &samplerConversionInfo,
+            .image = *image,
+            .viewType = vkhpp::ImageViewType::e2D,
+            .format = static_cast<vkhpp::Format>(ahbFormatProperties.format),
+            .components =
+                {
+                    .r = vkhpp::ComponentSwizzle::eIdentity,
+                    .g = vkhpp::ComponentSwizzle::eIdentity,
+                    .b = vkhpp::ComponentSwizzle::eIdentity,
+                    .a = vkhpp::ComponentSwizzle::eIdentity,
+                },
+            .subresourceRange =
+                {
+                    .aspectMask = vkhpp::ImageAspectFlagBits::eColor,
+                    .baseMipLevel = 0,
+                    .levelCount = 1,
+                    .baseArrayLayer = 0,
+                    .layerCount = 1,
+                },
+        };
+        auto imageView =
+            GFXSTREAM_EXPECT_VKHPP_RV(vk.device->createImageViewUnique(imageViewCreateInfo));
+
+        GFXSTREAM_EXPECT(DoCommandsImmediate(vk, [&](vkhpp::UniqueCommandBuffer& cmd) {
+            const std::vector<vkhpp::ImageMemoryBarrier> imageMemoryBarriers = {
+                vkhpp::ImageMemoryBarrier{
+                    .srcAccessMask = {},
+                    .dstAccessMask = vkhpp::AccessFlagBits::eTransferWrite,
+                    .oldLayout = vkhpp::ImageLayout::eUndefined,
+                    .newLayout = layout,
+                    .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+                    .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+                    .image = *image,
+                    .subresourceRange =
+                        {
+                            .aspectMask = vkhpp::ImageAspectFlagBits::eColor,
+                            .baseMipLevel = 0,
+                            .levelCount = 1,
+                            .baseArrayLayer = 0,
+                            .layerCount = 1,
+                        },
+
+                },
+            };
+            cmd->pipelineBarrier(
+                /*srcStageMask=*/vkhpp::PipelineStageFlagBits::eAllCommands,
+                /*dstStageMask=*/vkhpp::PipelineStageFlagBits::eAllCommands,
+                /*dependencyFlags=*/{},
+                /*memoryBarriers=*/{},
+                /*bufferMemoryBarriers=*/{},
+                /*imageMemoryBarriers=*/imageMemoryBarriers);
+            return Ok{};
+        }));
+
+        return ImageWithMemory{
+            .imageSamplerConversion = std::move(imageSamplerConversion),
+            .imageSampler = std::move(imageSampler),
+            .imageMemory = std::move(imageMemory),
+            .image = std::move(image),
+            .imageView = std::move(imageView),
+        };
+    }
+
+    Result<ImageWithMemory> CreateImage(TypicalVkTestEnvironment& vk, uint32_t width,
+                                        uint32_t height, vkhpp::Format format,
+                                        vkhpp::ImageUsageFlags usages,
+                                        vkhpp::MemoryPropertyFlags memoryProperties,
+                                        vkhpp::ImageLayout returnedLayout) {
+        const vkhpp::ImageCreateInfo imageCreateInfo = {
+            .imageType = vkhpp::ImageType::e2D,
+            .format = format,
+            .extent =
+                {
+                    .width = width,
+                    .height = height,
+                    .depth = 1,
+                },
+            .mipLevels = 1,
+            .arrayLayers = 1,
+            .samples = vkhpp::SampleCountFlagBits::e1,
+            .tiling = vkhpp::ImageTiling::eOptimal,
+            .usage = usages,
+            .sharingMode = vkhpp::SharingMode::eExclusive,
+            .initialLayout = vkhpp::ImageLayout::eUndefined,
+        };
+        auto image = GFXSTREAM_EXPECT_VKHPP_RV(vk.device->createImageUnique(imageCreateInfo));
+
+        const auto memoryRequirements = vk.device->getImageMemoryRequirements(*image);
+        const uint32_t memoryIndex =
+            utils::getMemoryType(vk.physicalDevice, memoryRequirements, memoryProperties);
+
+        const vkhpp::MemoryAllocateInfo imageMemoryAllocateInfo = {
+            .allocationSize = memoryRequirements.size,
+            .memoryTypeIndex = memoryIndex,
+        };
+        auto imageMemory =
+            GFXSTREAM_EXPECT_VKHPP_RV(vk.device->allocateMemoryUnique(imageMemoryAllocateInfo));
+
+        vk.device->bindImageMemory(*image, *imageMemory, 0);
+
+        const vkhpp::ImageViewCreateInfo imageViewCreateInfo = {
+            .image = *image,
+            .viewType = vkhpp::ImageViewType::e2D,
+            .format = format,
+            .components =
+                {
+                    .r = vkhpp::ComponentSwizzle::eIdentity,
+                    .g = vkhpp::ComponentSwizzle::eIdentity,
+                    .b = vkhpp::ComponentSwizzle::eIdentity,
+                    .a = vkhpp::ComponentSwizzle::eIdentity,
+                },
+            .subresourceRange =
+                {
+                    .aspectMask = vkhpp::ImageAspectFlagBits::eColor,
+                    .baseMipLevel = 0,
+                    .levelCount = 1,
+                    .baseArrayLayer = 0,
+                    .layerCount = 1,
+                },
+        };
+        auto imageView =
+            GFXSTREAM_EXPECT_VKHPP_RV(vk.device->createImageViewUnique(imageViewCreateInfo));
+
+        GFXSTREAM_EXPECT(DoCommandsImmediate(vk, [&](vkhpp::UniqueCommandBuffer& cmd) {
+            const std::vector<vkhpp::ImageMemoryBarrier> imageMemoryBarriers = {
+                vkhpp::ImageMemoryBarrier{
+                    .srcAccessMask = {},
+                    .dstAccessMask = vkhpp::AccessFlagBits::eTransferWrite,
+                    .oldLayout = vkhpp::ImageLayout::eUndefined,
+                    .newLayout = returnedLayout,
+                    .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+                    .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+                    .image = *image,
+                    .subresourceRange =
+                        {
+                            .aspectMask = vkhpp::ImageAspectFlagBits::eColor,
+                            .baseMipLevel = 0,
+                            .levelCount = 1,
+                            .baseArrayLayer = 0,
+                            .layerCount = 1,
+                        },
+                },
+            };
+            cmd->pipelineBarrier(
+                /*srcStageMask=*/vkhpp::PipelineStageFlagBits::eAllCommands,
+                /*dstStageMask=*/vkhpp::PipelineStageFlagBits::eAllCommands,
+                /*dependencyFlags=*/{},
+                /*memoryBarriers=*/{},
+                /*bufferMemoryBarriers=*/{},
+                /*imageMemoryBarriers=*/imageMemoryBarriers);
+
+            return Ok{};
+        }));
+
+        return ImageWithMemory{
+            .image = std::move(image),
+            .imageMemory = std::move(imageMemory),
+            .imageView = std::move(imageView),
+        };
+    }
+
+    struct FramebufferWithAttachments {
+        std::optional<ImageWithMemory> colorAttachment;
+        std::optional<ImageWithMemory> depthAttachment;
+        vkhpp::UniqueRenderPass renderpass;
+        vkhpp::UniqueFramebuffer framebuffer;
+    };
+    Result<FramebufferWithAttachments> CreateFramebuffer(
+        TypicalVkTestEnvironment& vk, uint32_t width, uint32_t height,
+        vkhpp::Format colorAttachmentFormat = vkhpp::Format::eUndefined,
+        vkhpp::Format depthAttachmentFormat = vkhpp::Format::eUndefined) {
+        std::optional<ImageWithMemory> colorAttachment;
+        if (colorAttachmentFormat != vkhpp::Format::eUndefined) {
+            colorAttachment =
+                GFXSTREAM_EXPECT(CreateImage(vk, width, height, colorAttachmentFormat,
+                                             vkhpp::ImageUsageFlagBits::eColorAttachment |
+                                                 vkhpp::ImageUsageFlagBits::eTransferSrc,
+                                             vkhpp::MemoryPropertyFlagBits::eDeviceLocal,
+                                             vkhpp::ImageLayout::eColorAttachmentOptimal));
+        }
+
+        std::optional<ImageWithMemory> depthAttachment;
+        if (depthAttachmentFormat != vkhpp::Format::eUndefined) {
+            depthAttachment =
+                GFXSTREAM_EXPECT(CreateImage(vk, width, height, depthAttachmentFormat,
+                                             vkhpp::ImageUsageFlagBits::eDepthStencilAttachment |
+                                                 vkhpp::ImageUsageFlagBits::eTransferSrc,
+                                             vkhpp::MemoryPropertyFlagBits::eDeviceLocal,
+                                             vkhpp::ImageLayout::eDepthStencilAttachmentOptimal));
+        }
+
+        std::vector<vkhpp::AttachmentDescription> attachments;
+
+        std::optional<vkhpp::AttachmentReference> colorAttachmentReference;
+        if (colorAttachmentFormat != vkhpp::Format::eUndefined) {
+            attachments.push_back(vkhpp::AttachmentDescription{
+                .format = colorAttachmentFormat,
+                .samples = vkhpp::SampleCountFlagBits::e1,
+                .loadOp = vkhpp::AttachmentLoadOp::eClear,
+                .storeOp = vkhpp::AttachmentStoreOp::eStore,
+                .stencilLoadOp = vkhpp::AttachmentLoadOp::eClear,
+                .stencilStoreOp = vkhpp::AttachmentStoreOp::eStore,
+                .initialLayout = vkhpp::ImageLayout::eColorAttachmentOptimal,
+                .finalLayout = vkhpp::ImageLayout::eColorAttachmentOptimal,
+            });
+
+            colorAttachmentReference = vkhpp::AttachmentReference{
+                .attachment = static_cast<uint32_t>(attachments.size() - 1),
+                .layout = vkhpp::ImageLayout::eColorAttachmentOptimal,
+            };
+        }
+
+        std::optional<vkhpp::AttachmentReference> depthAttachmentReference;
+        if (depthAttachmentFormat != vkhpp::Format::eUndefined) {
+            attachments.push_back(vkhpp::AttachmentDescription{
+                .format = depthAttachmentFormat,
+                .samples = vkhpp::SampleCountFlagBits::e1,
+                .loadOp = vkhpp::AttachmentLoadOp::eClear,
+                .storeOp = vkhpp::AttachmentStoreOp::eStore,
+                .stencilLoadOp = vkhpp::AttachmentLoadOp::eClear,
+                .stencilStoreOp = vkhpp::AttachmentStoreOp::eStore,
+                .initialLayout = vkhpp::ImageLayout::eColorAttachmentOptimal,
+                .finalLayout = vkhpp::ImageLayout::eColorAttachmentOptimal,
+            });
+
+            depthAttachmentReference = vkhpp::AttachmentReference{
+                .attachment = static_cast<uint32_t>(attachments.size() - 1),
+                .layout = vkhpp::ImageLayout::eDepthStencilAttachmentOptimal,
+            };
+        }
+
+        vkhpp::SubpassDependency dependency = {
+            .srcSubpass = 0,
+            .dstSubpass = 0,
+            .srcStageMask = {},
+            .dstStageMask = vkhpp::PipelineStageFlagBits::eFragmentShader,
+            .srcAccessMask = {},
+            .dstAccessMask = vkhpp::AccessFlagBits::eInputAttachmentRead,
+            .dependencyFlags = vkhpp::DependencyFlagBits::eByRegion,
+        };
+        if (colorAttachmentFormat != vkhpp::Format::eUndefined) {
+            dependency.srcStageMask |= vkhpp::PipelineStageFlagBits::eColorAttachmentOutput;
+            dependency.dstStageMask |= vkhpp::PipelineStageFlagBits::eColorAttachmentOutput;
+            dependency.srcAccessMask |= vkhpp::AccessFlagBits::eColorAttachmentWrite;
+        }
+        if (depthAttachmentFormat != vkhpp::Format::eUndefined) {
+            dependency.srcStageMask |= vkhpp::PipelineStageFlagBits::eColorAttachmentOutput;
+            dependency.dstStageMask |= vkhpp::PipelineStageFlagBits::eColorAttachmentOutput;
+            dependency.srcAccessMask |= vkhpp::AccessFlagBits::eColorAttachmentWrite;
+        }
+
+        vkhpp::SubpassDescription subpass = {
+            .pipelineBindPoint = vkhpp::PipelineBindPoint::eGraphics,
+            .inputAttachmentCount = 0,
+            .pInputAttachments = nullptr,
+            .colorAttachmentCount = 0,
+            .pColorAttachments = nullptr,
+            .pResolveAttachments = nullptr,
+            .pDepthStencilAttachment = nullptr,
+            .pPreserveAttachments = nullptr,
+        };
+        if (colorAttachmentFormat != vkhpp::Format::eUndefined) {
+            subpass.colorAttachmentCount = 1;
+            subpass.pColorAttachments = &*colorAttachmentReference;
+        }
+        if (depthAttachmentFormat != vkhpp::Format::eUndefined) {
+            subpass.pDepthStencilAttachment = &*depthAttachmentReference;
+        }
+
+        const vkhpp::RenderPassCreateInfo renderpassCreateInfo = {
+            .attachmentCount = static_cast<uint32_t>(attachments.size()),
+            .pAttachments = attachments.data(),
+            .subpassCount = 1,
+            .pSubpasses = &subpass,
+            .dependencyCount = 1,
+            .pDependencies = &dependency,
+        };
+        auto renderpass =
+            GFXSTREAM_EXPECT_VKHPP_RV(vk.device->createRenderPassUnique(renderpassCreateInfo));
+
+        std::vector<vkhpp::ImageView> framebufferAttachments;
+        if (colorAttachment) {
+            framebufferAttachments.push_back(*colorAttachment->imageView);
+        }
+        if (depthAttachment) {
+            framebufferAttachments.push_back(*depthAttachment->imageView);
+        }
+        const vkhpp::FramebufferCreateInfo framebufferCreateInfo = {
+            .renderPass = *renderpass,
+            .attachmentCount = static_cast<uint32_t>(framebufferAttachments.size()),
+            .pAttachments = framebufferAttachments.data(),
+            .width = width,
+            .height = height,
+            .layers = 1,
+        };
+        auto framebuffer =
+            GFXSTREAM_EXPECT_VKHPP_RV(vk.device->createFramebufferUnique(framebufferCreateInfo));
+
+        return FramebufferWithAttachments{
+            .colorAttachment = std::move(colorAttachment),
+            .depthAttachment = std::move(depthAttachment),
+            .renderpass = std::move(renderpass),
+            .framebuffer = std::move(framebuffer),
+        };
+    }
+
+    struct DescriptorContents {
+        uint32_t binding = 0;
+        struct Image {
+            vkhpp::ImageView imageView;
+            vkhpp::ImageLayout imageLayout;
+            vkhpp::Sampler imageSampler;
+        };
+        std::optional<Image> image;
+    };
+    struct DescriptorSetBundle {
+        vkhpp::UniqueDescriptorPool pool;
+        vkhpp::UniqueDescriptorSetLayout layout;
+        vkhpp::UniqueDescriptorSet ds;
+    };
+    Result<DescriptorSetBundle> CreateDescriptorSet(
+        TypicalVkTestEnvironment& vk,
+        const std::vector<vkhpp::DescriptorSetLayoutBinding>& bindings,
+        const std::vector<DescriptorContents> contents) {
+        std::unordered_map<vkhpp::DescriptorType, uint32_t> descriptorTypeToSizes;
+        for (const auto& binding : bindings) {
+            descriptorTypeToSizes[binding.descriptorType] += binding.descriptorCount;
+        }
+        std::vector<vkhpp::DescriptorPoolSize> descriptorPoolSizes;
+        for (const auto& [descriptorType, descriptorCount] : descriptorTypeToSizes) {
+            descriptorPoolSizes.push_back(vkhpp::DescriptorPoolSize{
+                .type = descriptorType,
+                .descriptorCount = descriptorCount,
+            });
+        }
+        const vkhpp::DescriptorPoolCreateInfo descriptorPoolCreateInfo = {
+            .flags = vkhpp::DescriptorPoolCreateFlagBits::eFreeDescriptorSet,
+            .maxSets = 1,
+            .poolSizeCount = static_cast<uint32_t>(descriptorPoolSizes.size()),
+            .pPoolSizes = descriptorPoolSizes.data(),
+        };
+        auto descriptorSetPool = GFXSTREAM_EXPECT_VKHPP_RV(
+            vk.device->createDescriptorPoolUnique(descriptorPoolCreateInfo));
+
+        const vkhpp::DescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = {
+            .bindingCount = static_cast<uint32_t>(bindings.size()),
+            .pBindings = bindings.data(),
+        };
+        auto descriptorSetLayout = GFXSTREAM_EXPECT_VKHPP_RV(
+            vk.device->createDescriptorSetLayoutUnique(descriptorSetLayoutCreateInfo));
+
+        const vkhpp::DescriptorSetLayout descriptorSetLayoutHandle = *descriptorSetLayout;
+        const vkhpp::DescriptorSetAllocateInfo descriptorSetAllocateInfo = {
+            .descriptorPool = *descriptorSetPool,
+            .descriptorSetCount = 1,
+            .pSetLayouts = &descriptorSetLayoutHandle,
+        };
+        auto descriptorSets = GFXSTREAM_EXPECT_VKHPP_RV(
+            vk.device->allocateDescriptorSetsUnique(descriptorSetAllocateInfo));
+        auto descriptorSet(std::move(descriptorSets[0]));
+
+        std::vector<std::unique_ptr<vkhpp::DescriptorImageInfo>> descriptorImageInfos;
+        std::vector<vkhpp::WriteDescriptorSet> descriptorSetWrites;
+        for (const auto& content : contents) {
+            if (content.image) {
+                descriptorImageInfos.emplace_back(new vkhpp::DescriptorImageInfo{
+                    .sampler = content.image->imageSampler,
+                    .imageView = content.image->imageView,
+                    .imageLayout = content.image->imageLayout,
+                });
+                descriptorSetWrites.emplace_back(vkhpp::WriteDescriptorSet{
+                    .dstSet = *descriptorSet,
+                    .dstBinding = content.binding,
+                    .dstArrayElement = 0,
+                    .descriptorCount = 1,
+                    .descriptorType = vkhpp::DescriptorType::eCombinedImageSampler,
+                    .pImageInfo = descriptorImageInfos.back().get(),
+                });
+            } else {
+                return gfxstream::unexpected("Unhandled descriptor type");
+                ;
+            }
+        }
+        vk.device->updateDescriptorSets(descriptorSetWrites, {});
+
+        return DescriptorSetBundle{
+            .pool = std::move(descriptorSetPool),
+            .layout = std::move(descriptorSetLayout),
+            .ds = std::move(descriptorSet),
+        };
+    }
+
+    struct PipelineParams {
+        std::vector<uint32_t> vert;
+        std::vector<uint32_t> frag;
+        std::vector<DescriptorSetBundle*> descriptorSets;
+        const FramebufferWithAttachments* framebuffer = nullptr;
+    };
+    struct PipelineBundle {
+        vkhpp::UniqueShaderModule vert;
+        vkhpp::UniqueShaderModule frag;
+        vkhpp::UniquePipelineLayout pipelineLayout;
+        vkhpp::UniquePipeline pipeline;
+    };
+    Result<PipelineBundle> CreatePipeline(TypicalVkTestEnvironment& vk,
+                                          const PipelineParams& params) {
+        const vkhpp::ShaderModuleCreateInfo vertShaderCreateInfo = {
+            .codeSize = params.vert.size() * sizeof(uint32_t),
+            .pCode = params.vert.data(),
+        };
+        auto vertShaderModule =
+            GFXSTREAM_EXPECT_VKHPP_RV(vk.device->createShaderModuleUnique(vertShaderCreateInfo));
+
+        const vkhpp::ShaderModuleCreateInfo fragShaderCreateInfo = {
+            .codeSize = params.frag.size() * sizeof(uint32_t),
+            .pCode = params.frag.data(),
+        };
+        auto fragShaderModule =
+            GFXSTREAM_EXPECT_VKHPP_RV(vk.device->createShaderModuleUnique(fragShaderCreateInfo));
+
+        const std::vector<vkhpp::PipelineShaderStageCreateInfo> pipelineStages = {
+            vkhpp::PipelineShaderStageCreateInfo{
+                .stage = vkhpp::ShaderStageFlagBits::eVertex,
+                .module = *vertShaderModule,
+                .pName = "main",
+            },
+            vkhpp::PipelineShaderStageCreateInfo{
+                .stage = vkhpp::ShaderStageFlagBits::eFragment,
+                .module = *fragShaderModule,
+                .pName = "main",
+            },
+        };
+
+        std::vector<vkhpp::DescriptorSetLayout> descriptorSetLayoutHandles;
+        for (const auto* descriptorSet : params.descriptorSets) {
+            descriptorSetLayoutHandles.push_back(*descriptorSet->layout);
+        }
+        const vkhpp::PipelineLayoutCreateInfo pipelineLayoutCreateInfo = {
+            .setLayoutCount = static_cast<uint32_t>(descriptorSetLayoutHandles.size()),
+            .pSetLayouts = descriptorSetLayoutHandles.data(),
+        };
+        auto pipelineLayout = GFXSTREAM_EXPECT_VKHPP_RV(
+            vk.device->createPipelineLayoutUnique(pipelineLayoutCreateInfo));
+
+        const vkhpp::PipelineVertexInputStateCreateInfo pipelineVertexInputStateCreateInfo = {};
+        const vkhpp::PipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateCreateInfo = {
+            .topology = vkhpp::PrimitiveTopology::eTriangleList,
+        };
+        const vkhpp::PipelineViewportStateCreateInfo pipelineViewportStateCreateInfo = {
+            .viewportCount = 1,
+            .pViewports = nullptr,
+            .scissorCount = 1,
+            .pScissors = nullptr,
+        };
+        const vkhpp::PipelineRasterizationStateCreateInfo pipelineRasterStateCreateInfo = {
+            .depthClampEnable = VK_FALSE,
+            .rasterizerDiscardEnable = VK_FALSE,
+            .polygonMode = vkhpp::PolygonMode::eFill,
+            .cullMode = {},
+            .frontFace = vkhpp::FrontFace::eCounterClockwise,
+            .depthBiasEnable = VK_FALSE,
+            .depthBiasConstantFactor = 0.0f,
+            .depthBiasClamp = 0.0f,
+            .depthBiasSlopeFactor = 0.0f,
+            .lineWidth = 1.0f,
+        };
+        const vkhpp::SampleMask pipelineSampleMask = 65535;
+        const vkhpp::PipelineMultisampleStateCreateInfo pipelineMultisampleStateCreateInfo = {
+            .rasterizationSamples = vkhpp::SampleCountFlagBits::e1,
+            .sampleShadingEnable = VK_FALSE,
+            .minSampleShading = 1.0f,
+            .pSampleMask = &pipelineSampleMask,
+            .alphaToCoverageEnable = VK_FALSE,
+            .alphaToOneEnable = VK_FALSE,
+        };
+        const vkhpp::PipelineDepthStencilStateCreateInfo pipelineDepthStencilStateCreateInfo = {
+            .depthTestEnable = VK_FALSE,
+            .depthWriteEnable = VK_FALSE,
+            .depthCompareOp = vkhpp::CompareOp::eLess,
+            .depthBoundsTestEnable = VK_FALSE,
+            .stencilTestEnable = VK_FALSE,
+            .front =
+                {
+                    .failOp = vkhpp::StencilOp::eKeep,
+                    .passOp = vkhpp::StencilOp::eKeep,
+                    .depthFailOp = vkhpp::StencilOp::eKeep,
+                    .compareOp = vkhpp::CompareOp::eAlways,
+                    .compareMask = 0,
+                    .writeMask = 0,
+                    .reference = 0,
+                },
+            .back =
+                {
+                    .failOp = vkhpp::StencilOp::eKeep,
+                    .passOp = vkhpp::StencilOp::eKeep,
+                    .depthFailOp = vkhpp::StencilOp::eKeep,
+                    .compareOp = vkhpp::CompareOp::eAlways,
+                    .compareMask = 0,
+                    .writeMask = 0,
+                    .reference = 0,
+                },
+            .minDepthBounds = 0.0f,
+            .maxDepthBounds = 0.0f,
+        };
+        const std::vector<vkhpp::PipelineColorBlendAttachmentState> pipelineColorBlendAttachments =
+            {
+                vkhpp::PipelineColorBlendAttachmentState{
+                    .blendEnable = VK_FALSE,
+                    .srcColorBlendFactor = vkhpp::BlendFactor::eOne,
+                    .dstColorBlendFactor = vkhpp::BlendFactor::eOneMinusSrcAlpha,
+                    .colorBlendOp = vkhpp::BlendOp::eAdd,
+                    .srcAlphaBlendFactor = vkhpp::BlendFactor::eOne,
+                    .dstAlphaBlendFactor = vkhpp::BlendFactor::eOneMinusSrcAlpha,
+                    .alphaBlendOp = vkhpp::BlendOp::eAdd,
+                    .colorWriteMask =
+                        vkhpp::ColorComponentFlagBits::eR | vkhpp::ColorComponentFlagBits::eG |
+                        vkhpp::ColorComponentFlagBits::eB | vkhpp::ColorComponentFlagBits::eA,
+                },
+            };
+        const vkhpp::PipelineColorBlendStateCreateInfo pipelineColorBlendStateCreateInfo = {
+            .logicOpEnable = VK_FALSE,
+            .logicOp = vkhpp::LogicOp::eCopy,
+            .attachmentCount = static_cast<uint32_t>(pipelineColorBlendAttachments.size()),
+            .pAttachments = pipelineColorBlendAttachments.data(),
+            .blendConstants = {{
+                0.0f,
+                0.0f,
+                0.0f,
+                0.0f,
+            }},
+        };
+        const std::vector<vkhpp::DynamicState> pipelineDynamicStates = {
+            vkhpp::DynamicState::eViewport,
+            vkhpp::DynamicState::eScissor,
+        };
+        const vkhpp::PipelineDynamicStateCreateInfo pipelineDynamicStateCreateInfo = {
+            .dynamicStateCount = static_cast<uint32_t>(pipelineDynamicStates.size()),
+            .pDynamicStates = pipelineDynamicStates.data(),
+        };
+        const vkhpp::GraphicsPipelineCreateInfo pipelineCreateInfo = {
+            .stageCount = static_cast<uint32_t>(pipelineStages.size()),
+            .pStages = pipelineStages.data(),
+            .pVertexInputState = &pipelineVertexInputStateCreateInfo,
+            .pInputAssemblyState = &pipelineInputAssemblyStateCreateInfo,
+            .pTessellationState = nullptr,
+            .pViewportState = &pipelineViewportStateCreateInfo,
+            .pRasterizationState = &pipelineRasterStateCreateInfo,
+            .pMultisampleState = &pipelineMultisampleStateCreateInfo,
+            .pDepthStencilState = &pipelineDepthStencilStateCreateInfo,
+            .pColorBlendState = &pipelineColorBlendStateCreateInfo,
+            .pDynamicState = &pipelineDynamicStateCreateInfo,
+            .layout = *pipelineLayout,
+            .renderPass = *params.framebuffer->renderpass,
+            .subpass = 0,
+            .basePipelineHandle = VK_NULL_HANDLE,
+            .basePipelineIndex = 0,
+        };
+        auto pipeline = GFXSTREAM_EXPECT_VKHPP_RV(
+            vk.device->createGraphicsPipelineUnique({}, pipelineCreateInfo));
+
+        return PipelineBundle{
+            .vert = std::move(vertShaderModule),
+            .frag = std::move(fragShaderModule),
+            .pipelineLayout = std::move(pipelineLayout),
+            .pipeline = std::move(pipeline),
+        };
+    }
+
+    Result<Image> DownloadImage(TypicalVkTestEnvironment& vk, uint32_t width, uint32_t height,
+                                const vkhpp::UniqueImage& image, vkhpp::ImageLayout currentLayout,
+                                vkhpp::ImageLayout returnedLayout) {
+        static constexpr const VkDeviceSize kStagingBufferSize = 32 * 1024 * 1024;
+        auto stagingBuffer = GFXSTREAM_EXPECT(CreateBuffer(
+            vk, kStagingBufferSize,
+            vkhpp::BufferUsageFlagBits::eTransferDst | vkhpp::BufferUsageFlagBits::eTransferSrc,
+            vkhpp::MemoryPropertyFlagBits::eHostVisible |
+                vkhpp::MemoryPropertyFlagBits::eHostCoherent));
+
+        GFXSTREAM_EXPECT(DoCommandsImmediate(vk, [&](vkhpp::UniqueCommandBuffer& cmd) {
+            if (currentLayout != vkhpp::ImageLayout::eTransferSrcOptimal) {
+                const std::vector<vkhpp::ImageMemoryBarrier> imageMemoryBarriers = {
+                    vkhpp::ImageMemoryBarrier{
+                        .srcAccessMask = vkhpp::AccessFlagBits::eMemoryRead |
+                                         vkhpp::AccessFlagBits::eMemoryWrite,
+                        .dstAccessMask = vkhpp::AccessFlagBits::eTransferRead,
+                        .oldLayout = currentLayout,
+                        .newLayout = vkhpp::ImageLayout::eTransferSrcOptimal,
+                        .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+                        .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+                        .image = *image,
+                        .subresourceRange =
+                            {
+                                .aspectMask = vkhpp::ImageAspectFlagBits::eColor,
+                                .baseMipLevel = 0,
+                                .levelCount = 1,
+                                .baseArrayLayer = 0,
+                                .layerCount = 1,
+                            },
+                    },
+                };
+                cmd->pipelineBarrier(
+                    /*srcStageMask=*/vkhpp::PipelineStageFlagBits::eAllCommands,
+                    /*dstStageMask=*/vkhpp::PipelineStageFlagBits::eAllCommands,
+                    /*dependencyFlags=*/{},
+                    /*memoryBarriers=*/{},
+                    /*bufferMemoryBarriers=*/{},
+                    /*imageMemoryBarriers=*/imageMemoryBarriers);
+            }
+
+            const std::vector<vkhpp::BufferImageCopy> regions = {
+                vkhpp::BufferImageCopy{
+                    .bufferOffset = 0,
+                    .bufferRowLength = 0,
+                    .bufferImageHeight = 0,
+                    .imageSubresource =
+                        {
+                            .aspectMask = vkhpp::ImageAspectFlagBits::eColor,
+                            .mipLevel = 0,
+                            .baseArrayLayer = 0,
+                            .layerCount = 1,
+                        },
+                    .imageOffset =
+                        {
+                            .x = 0,
+                            .y = 0,
+                            .z = 0,
+                        },
+                    .imageExtent =
+                        {
+                            .width = width,
+                            .height = height,
+                            .depth = 1,
+                        },
+                },
+            };
+            cmd->copyImageToBuffer(*image, vkhpp::ImageLayout::eTransferSrcOptimal,
+                                   *stagingBuffer.buffer, regions);
+
+            if (returnedLayout != vkhpp::ImageLayout::eTransferSrcOptimal) {
+                const std::vector<vkhpp::ImageMemoryBarrier> imageMemoryBarriers = {
+                    vkhpp::ImageMemoryBarrier{
+                        .srcAccessMask = vkhpp::AccessFlagBits::eTransferRead,
+                        .dstAccessMask = vkhpp::AccessFlagBits::eMemoryRead |
+                                         vkhpp::AccessFlagBits::eMemoryWrite,
+                        .oldLayout = vkhpp::ImageLayout::eTransferSrcOptimal,
+                        .newLayout = returnedLayout,
+                        .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+                        .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+                        .image = *image,
+                        .subresourceRange =
+                            {
+                                .aspectMask = vkhpp::ImageAspectFlagBits::eColor,
+                                .baseMipLevel = 0,
+                                .levelCount = 1,
+                                .baseArrayLayer = 0,
+                                .layerCount = 1,
+                            },
+                    },
+                };
+                cmd->pipelineBarrier(
+                    /*srcStageMask=*/vkhpp::PipelineStageFlagBits::eAllCommands,
+                    /*dstStageMask=*/vkhpp::PipelineStageFlagBits::eAllCommands,
+                    /*dependencyFlags=*/{},
+                    /*memoryBarriers=*/{},
+                    /*bufferMemoryBarriers=*/{},
+                    /*imageMemoryBarriers=*/imageMemoryBarriers);
+            }
+            return Ok{};
+        }));
+
+        std::vector<uint32_t> outPixels;
+        outPixels.resize(width * height);
+
+        auto* mapped = GFXSTREAM_EXPECT_VKHPP_RV(
+            vk.device->mapMemory(*stagingBuffer.bufferMemory, 0, VK_WHOLE_SIZE));
+        std::memcpy(outPixels.data(), mapped, sizeof(uint32_t) * outPixels.size());
+        vk.device->unmapMemory(*stagingBuffer.bufferMemory);
+
+        return Image{
+            .width = width,
+            .height = height,
+            .pixels = outPixels,
+        };
+    }
+
+    void DoFillAndRenderFromAhb(uint32_t ahbFormat) {
+        const uint32_t width = 1920;
+        const uint32_t height = 1080;
+        const auto goldenPixel = PixelR8G8B8A8(0, 255, 255, 255);
+
+        auto ahb =
+            GFXSTREAM_ASSERT(ScopedAHardwareBuffer::Allocate(*mGralloc, width, height, ahbFormat));
+
+        GFXSTREAM_ASSERT(FillAhb(ahb, goldenPixel));
+
+        const vkhpp::PhysicalDeviceVulkan11Features deviceFeatures = {
+            .samplerYcbcrConversion = VK_TRUE,
+        };
+        auto vk = GFXSTREAM_ASSERT(SetUpTypicalVkTestEnvironment({
+            .deviceExtensions = {{VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME}},
+            .deviceCreateInfoPNext = &deviceFeatures,
+        }));
+
+        auto ahbImage =
+            GFXSTREAM_ASSERT(CreateImageWithAhb(vk, ahb, vkhpp::ImageUsageFlagBits::eSampled,
+                                                vkhpp::ImageLayout::eShaderReadOnlyOptimal));
+
+        auto framebuffer = GFXSTREAM_ASSERT(CreateFramebuffer(
+            vk, width, height, /*colorAttachmentFormat=*/vkhpp::Format::eR8G8B8A8Unorm));
+
+        const vkhpp::Sampler ahbSamplerHandle = *ahbImage.imageSampler;
+        auto descriptorSet0 = GFXSTREAM_ASSERT(
+            CreateDescriptorSet(vk,
+                                /*bindings=*/
+                                {{
+                                    .binding = 0,
+                                    .descriptorType = vkhpp::DescriptorType::eCombinedImageSampler,
+                                    .descriptorCount = 1,
+                                    .stageFlags = vkhpp::ShaderStageFlagBits::eFragment,
+                                    .pImmutableSamplers = &ahbSamplerHandle,
+                                }},
+                                /*writes=*/
+                                {{
+                                    .binding = 0,
+                                    .image = {{
+                                        .imageView = *ahbImage.imageView,
+                                        .imageLayout = vkhpp::ImageLayout::eShaderReadOnlyOptimal,
+                                        .imageSampler = *ahbImage.imageSampler,
+                                    }},
+                                }}));
+
+        auto pipeline =
+            GFXSTREAM_ASSERT(CreatePipeline(vk, {
+                                                    .vert = kFullscreenTriangleWithUVVert,
+                                                    .frag = kBlitSampler2dFrag,
+                                                    .descriptorSets = {&descriptorSet0},
+                                                    .framebuffer = &framebuffer,
+                                                }));
+
+        GFXSTREAM_ASSERT(DoCommandsImmediate(vk, [&](vkhpp::UniqueCommandBuffer& cmd) {
+            const std::vector<vkhpp::ClearValue> renderPassBeginClearValues = {
+                vkhpp::ClearValue{
+                    .color =
+                        {
+                            .float32 = {{
+                                1.0f,
+                                0.0f,
+                                0.0f,
+                                1.0f,
+                            }},
+                        },
+                },
+            };
+            const vkhpp::RenderPassBeginInfo renderPassBeginInfo = {
+                .renderPass = *framebuffer.renderpass,
+                .framebuffer = *framebuffer.framebuffer,
+                .renderArea =
+                    {
+                        .offset =
+                            {
+                                .x = 0,
+                                .y = 0,
+                            },
+                        .extent =
+                            {
+                                .width = width,
+                                .height = height,
+                            },
+                    },
+                .clearValueCount = static_cast<uint32_t>(renderPassBeginClearValues.size()),
+                .pClearValues = renderPassBeginClearValues.data(),
+            };
+            cmd->beginRenderPass(renderPassBeginInfo, vkhpp::SubpassContents::eInline);
+            cmd->bindPipeline(vkhpp::PipelineBindPoint::eGraphics, *pipeline.pipeline);
+            cmd->bindDescriptorSets(vkhpp::PipelineBindPoint::eGraphics, *pipeline.pipelineLayout,
+                                    /*firstSet=*/0, {*descriptorSet0.ds},
+                                    /*dynamicOffsets=*/{});
+            const vkhpp::Viewport viewport = {
+                .x = 0.0f,
+                .y = 0.0f,
+                .width = static_cast<float>(width),
+                .height = static_cast<float>(height),
+                .minDepth = 0.0f,
+                .maxDepth = 1.0f,
+            };
+            cmd->setViewport(0, {viewport});
+            const vkhpp::Rect2D scissor = {
+                .offset =
+                    {
+                        .x = 0,
+                        .y = 0,
+                    },
+                .extent =
+                    {
+                        .width = width,
+                        .height = height,
+                    },
+            };
+            cmd->setScissor(0, {scissor});
+            cmd->draw(3, 1, 0, 0);
+            cmd->endRenderPass();
+            return Ok{};
+        }));
+
+        const auto actualImage = GFXSTREAM_ASSERT(
+            DownloadImage(vk, width, height, framebuffer.colorAttachment->image,
+                          /*currentLayout=*/vkhpp::ImageLayout::eColorAttachmentOptimal,
+                          /*returnedLayout=*/vkhpp::ImageLayout::eColorAttachmentOptimal));
+
+        const auto expectedImage = ImageFromColor(width, height, goldenPixel);
+        EXPECT_THAT(AreImagesSimilar(expectedImage, actualImage), IsTrue());
+    }
 };
 
 TEST_P(GfxstreamEnd2EndVkTest, Basic) {
     auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
-        VK_ASSERT(SetUpTypicalVkTestEnvironment());
+        GFXSTREAM_ASSERT(SetUpTypicalVkTestEnvironment());
 }
 
 TEST_P(GfxstreamEnd2EndVkTest, ImportAHB) {
     auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
-        VK_ASSERT(SetUpTypicalVkTestEnvironment());
+        GFXSTREAM_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));
+    auto ahb = GFXSTREAM_ASSERT(ScopedAHardwareBuffer::Allocate(
+        *mGralloc, width, height, GFXSTREAM_AHB_FORMAT_R8G8B8A8_UNORM));
 
     const VkNativeBufferANDROID imageNativeBufferInfo = {
         .sType = VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID,
@@ -252,12 +1343,12 @@
 
 TEST_P(GfxstreamEnd2EndVkTest, DeferredImportAHB) {
     auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
-        VK_ASSERT(SetUpTypicalVkTestEnvironment());
+        GFXSTREAM_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));
+    auto ahb = GFXSTREAM_ASSERT(ScopedAHardwareBuffer::Allocate(
+        *mGralloc, width, height, GFXSTREAM_AHB_FORMAT_R8G8B8A8_UNORM));
 
     auto vkQueueSignalReleaseImageANDROID = PFN_vkQueueSignalReleaseImageANDROID(
         device->getProcAddr("vkQueueSignalReleaseImageANDROID"));
@@ -317,11 +1408,11 @@
     }
 
     auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
-        VK_ASSERT(SetUpTypicalVkTestEnvironment());
+        GFXSTREAM_ASSERT(SetUpTypicalVkTestEnvironment());
 
     const uint32_t width = 32;
     const uint32_t height = 1;
-    auto ahb = GL_ASSERT(
+    auto ahb = GFXSTREAM_ASSERT(
         ScopedAHardwareBuffer::Allocate(*mGralloc, width, height, GFXSTREAM_AHB_FORMAT_BLOB));
 
     const vkhpp::ExternalMemoryBufferCreateInfo externalMemoryBufferCreateInfo = {
@@ -389,7 +1480,7 @@
     static constexpr const vkhpp::DeviceSize kSize = 16 * 1024;
 
     auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
-        VK_ASSERT(SetUpTypicalVkTestEnvironment());
+        GFXSTREAM_ASSERT(SetUpTypicalVkTestEnvironment());
 
     uint32_t hostMemoryTypeIndex = -1;
     const auto memoryProperties = physicalDevice.getMemoryProperties();
@@ -435,7 +1526,7 @@
 
 TEST_P(GfxstreamEnd2EndVkTest, GetPhysicalDeviceProperties2) {
     auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
-        VK_ASSERT(SetUpTypicalVkTestEnvironment());
+        GFXSTREAM_ASSERT(SetUpTypicalVkTestEnvironment());
 
     auto props1 = physicalDevice.getProperties();
     auto props2 = physicalDevice.getProperties2();
@@ -446,7 +1537,7 @@
 
 TEST_P(GfxstreamEnd2EndVkTest, GetPhysicalDeviceFeatures2KHR) {
     auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
-        VK_ASSERT(SetUpTypicalVkTestEnvironment());
+        GFXSTREAM_ASSERT(SetUpTypicalVkTestEnvironment());
 
     auto features1 = physicalDevice.getFeatures();
     auto features2 = physicalDevice.getFeatures2();
@@ -455,7 +1546,7 @@
 
 TEST_P(GfxstreamEnd2EndVkTest, GetPhysicalDeviceImageFormatProperties2KHR) {
     auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
-        VK_ASSERT(SetUpTypicalVkTestEnvironment());
+        GFXSTREAM_ASSERT(SetUpTypicalVkTestEnvironment());
 
     const vkhpp::PhysicalDeviceImageFormatInfo2 imageFormatInfo = {
         .format = vkhpp::Format::eR8G8B8A8Unorm,
@@ -463,7 +1554,8 @@
         .tiling = vkhpp::ImageTiling::eOptimal,
         .usage = vkhpp::ImageUsageFlagBits::eSampled,
     };
-    const auto properties = VK_ASSERT_RV(physicalDevice.getImageFormatProperties2(imageFormatInfo));
+    const auto properties =
+        GFXSTREAM_ASSERT_VKHPP_RV(physicalDevice.getImageFormatProperties2(imageFormatInfo));
     EXPECT_THAT(properties.imageFormatProperties.maxExtent.width, Ge(1));
     EXPECT_THAT(properties.imageFormatProperties.maxExtent.height, Ge(1));
     EXPECT_THAT(properties.imageFormatProperties.maxExtent.depth, Ge(1));
@@ -486,10 +1578,10 @@
     std::vector<vkhpp::UniqueDescriptorSet> descriptorSets;
 };
 
-vkhpp::Result ReallocateDescriptorBundleSets(vkhpp::Device device, uint32_t count, DescriptorBundle* bundle) {
+Result<Ok> ReallocateDescriptorBundleSets(vkhpp::Device device, uint32_t count,
+                                          DescriptorBundle* bundle) {
     if (!bundle->descriptorSetLayout) {
-        ALOGE("Invalid descriptor set layout.");
-        return vkhpp::Result::eErrorUnknown;
+        return gfxstream::unexpected("Invalid descriptor set layout");
     }
 
     const std::vector<vkhpp::DescriptorSetLayout> descriptorSetLayouts(count, *bundle->descriptorSetLayout);
@@ -498,12 +1590,13 @@
         .descriptorSetCount = count,
         .pSetLayouts = descriptorSetLayouts.data(),
     };
-    auto descriptorSets = VK_TRY_RV(device.allocateDescriptorSetsUnique(descriptorSetAllocateInfo));
+    auto descriptorSets =
+        GFXSTREAM_EXPECT_VKHPP_RV(device.allocateDescriptorSetsUnique(descriptorSetAllocateInfo));
     bundle->descriptorSets = std::move(descriptorSets);
-    return vkhpp::Result::eSuccess;
+    return Ok{};
 }
 
-VkExpected<DescriptorBundle> AllocateDescriptorBundle(vkhpp::Device device, uint32_t count) {
+Result<DescriptorBundle> AllocateDescriptorBundle(vkhpp::Device device, uint32_t count) {
     const vkhpp::DescriptorPoolSize descriptorPoolSize = {
         .type = vkhpp::DescriptorType::eUniformBuffer,
         .descriptorCount = 1 * count,
@@ -514,7 +1607,8 @@
         .poolSizeCount = 1,
         .pPoolSizes = &descriptorPoolSize,
     };
-    auto descriptorPool = VK_EXPECT_RV(device.createDescriptorPoolUnique(descriptorPoolCreateInfo));
+    auto descriptorPool =
+        GFXSTREAM_EXPECT_VKHPP_RV(device.createDescriptorPoolUnique(descriptorPoolCreateInfo));
 
     const vkhpp::DescriptorSetLayoutBinding descriptorSetBinding = {
         .binding = 0,
@@ -526,13 +1620,14 @@
         .bindingCount = 1,
         .pBindings = &descriptorSetBinding,
     };
-    auto descriptorSetLayout = VK_EXPECT_RV(device.createDescriptorSetLayoutUnique(descriptorSetLayoutInfo));
+    auto descriptorSetLayout =
+        GFXSTREAM_EXPECT_VKHPP_RV(device.createDescriptorSetLayoutUnique(descriptorSetLayoutInfo));
 
     DescriptorBundle bundle = {
         .descriptorPool = std::move(descriptorPool),
         .descriptorSetLayout = std::move(descriptorSetLayout),
     };
-    VK_EXPECT_RESULT(ReallocateDescriptorBundleSets(device, count, &bundle));
+    GFXSTREAM_EXPECT(ReallocateDescriptorBundleSets(device, count, &bundle));
     return std::move(bundle);
 }
 
@@ -549,9 +1644,9 @@
     constexpr const uint32_t kNumSets = 4;
 
     auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
-        VK_ASSERT(SetUpTypicalVkTestEnvironment());
+        GFXSTREAM_ASSERT(SetUpTypicalVkTestEnvironment());
 
-    auto bundle = VK_ASSERT(AllocateDescriptorBundle(*device, kNumSets));
+    auto bundle = GFXSTREAM_ASSERT(AllocateDescriptorBundle(*device, kNumSets));
 
     auto descriptorSetHandles = AsHandles(bundle.descriptorSets);
     EXPECT_THAT(device->freeDescriptorSets(*bundle.descriptorPool, kNumSets, descriptorSetHandles.data()), IsVkSuccess());
@@ -560,7 +1655,7 @@
     EXPECT_THAT(device->freeDescriptorSets(*bundle.descriptorPool, kNumSets, descriptorSetHandles.data()), IsVkSuccess());
 
     // Alloc/free again should also work
-    ASSERT_THAT(ReallocateDescriptorBundleSets(*device, kNumSets, &bundle), IsVkSuccess());
+    GFXSTREAM_ASSERT(ReallocateDescriptorBundleSets(*device, kNumSets, &bundle));
 
     descriptorSetHandles = AsHandles(bundle.descriptorSets);
     EXPECT_THAT(device->freeDescriptorSets(*bundle.descriptorPool, kNumSets, descriptorSetHandles.data()), IsVkSuccess());
@@ -570,9 +1665,9 @@
     constexpr const uint32_t kNumSets = 4;
 
     auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
-        VK_ASSERT(SetUpTypicalVkTestEnvironment());
+        GFXSTREAM_ASSERT(SetUpTypicalVkTestEnvironment());
 
-    auto bundle = VK_ASSERT(AllocateDescriptorBundle(*device, kNumSets));
+    auto bundle = GFXSTREAM_ASSERT(AllocateDescriptorBundle(*device, kNumSets));
 
     device->resetDescriptorPool(*bundle.descriptorPool);
 
@@ -581,7 +1676,7 @@
     EXPECT_THAT(device->freeDescriptorSets(*bundle.descriptorPool, kNumSets, descriptorSetHandles.data()), IsVkSuccess());
 
     // Alloc/reset/free again should also work
-    ASSERT_THAT(ReallocateDescriptorBundleSets(*device, kNumSets, &bundle), IsVkSuccess());
+    GFXSTREAM_ASSERT(ReallocateDescriptorBundleSets(*device, kNumSets, &bundle));
 
     device->resetDescriptorPool(*bundle.descriptorPool);
 
@@ -593,9 +1688,9 @@
     constexpr const uint32_t kNumSets = 4;
 
     auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
-        VK_ASSERT(SetUpTypicalVkTestEnvironment());
+        GFXSTREAM_ASSERT(SetUpTypicalVkTestEnvironment());
 
-    auto bundle = VK_ASSERT(AllocateDescriptorBundle(*device, kNumSets));
+    auto bundle = GFXSTREAM_ASSERT(AllocateDescriptorBundle(*device, kNumSets));
 
     device->destroyDescriptorPool(*bundle.descriptorPool);
 
@@ -608,7 +1703,7 @@
     constexpr const int kNumIterations = 20;
     for (int i = 0; i < kNumIterations; i++) {
         auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
-                VK_ASSERT(SetUpTypicalVkTestEnvironment());
+            GFXSTREAM_ASSERT(SetUpTypicalVkTestEnvironment());
 
         const vkhpp::BufferCreateInfo bufferCreateInfo = {
             .size = 1024,
@@ -706,6 +1801,30 @@
     }
 }
 
+TEST_P(GfxstreamEnd2EndVkTest, DeviceCreateWithDeviceGroup) {
+    auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
+        GFXSTREAM_ASSERT(SetUpTypicalVkTestEnvironment());
+
+    const vkhpp::DeviceGroupDeviceCreateInfo deviceGroupDeviceCreateInfo = {
+        .physicalDeviceCount = 1,
+        .pPhysicalDevices = &physicalDevice,
+    };
+
+    const float queuePriority = 1.0f;
+    const vkhpp::DeviceQueueCreateInfo deviceQueueCreateInfo = {
+        .queueFamilyIndex = 0,
+        .queueCount = 1,
+        .pQueuePriorities = &queuePriority,
+    };
+    const vkhpp::DeviceCreateInfo deviceCreateInfo = {
+        .pNext = &deviceGroupDeviceCreateInfo,
+        .pQueueCreateInfos = &deviceQueueCreateInfo,
+        .queueCreateInfoCount = 1,
+    };
+    auto device2 = GFXSTREAM_ASSERT_VKHPP_RV(physicalDevice.createDeviceUnique(deviceCreateInfo));
+    ASSERT_THAT(device2, IsValidHandle());
+}
+
 TEST_P(GfxstreamEnd2EndVkTest, AcquireImageAndroidWithFence) {
     DoAcquireImageAndroidWithSync(/*withFence=*/true, /*withSemaphore=*/false);
 }
@@ -730,7 +1849,7 @@
     };
 
     auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
-        VK_ASSERT(SetUpTypicalVkTestEnvironment({
+        GFXSTREAM_ASSERT(SetUpTypicalVkTestEnvironment({
             .deviceExtensions = {{
                 VK_EXT_DEVICE_MEMORY_REPORT_EXTENSION_NAME,
             }},
@@ -747,13 +1866,13 @@
 
 TEST_P(GfxstreamEnd2EndVkTest, DescriptorUpdateTemplateWithWrapping) {
     auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
-        VK_ASSERT(SetUpTypicalVkTestEnvironment());
+        GFXSTREAM_ASSERT(SetUpTypicalVkTestEnvironment());
 
     const vkhpp::BufferCreateInfo bufferCreateInfo = {
         .size = 1024,
         .usage = vkhpp::BufferUsageFlagBits::eUniformBuffer,
     };
-    auto buffer = VK_ASSERT_RV(device->createBufferUnique(bufferCreateInfo));
+    auto buffer = GFXSTREAM_ASSERT_VKHPP_RV(device->createBufferUnique(bufferCreateInfo));
 
     const std::vector<VkDescriptorBufferInfo> descriptorInfo = {
         VkDescriptorBufferInfo{
@@ -791,7 +1910,7 @@
         .pPoolSizes = descriptorPoolSizes.data(),
     };
     auto descriptorPool =
-        VK_ASSERT_RV(device->createDescriptorPoolUnique(descriptorPoolCreateInfo));
+        GFXSTREAM_ASSERT_VKHPP_RV(device->createDescriptorPoolUnique(descriptorPoolCreateInfo));
 
     const std::vector<vkhpp::DescriptorSetLayoutBinding> descriptorSetBindings = {
         {
@@ -824,7 +1943,7 @@
         .pBindings = descriptorSetBindings.data(),
     };
     auto descriptorSetLayout =
-        VK_ASSERT_RV(device->createDescriptorSetLayoutUnique(descriptorSetLayoutInfo));
+        GFXSTREAM_ASSERT_VKHPP_RV(device->createDescriptorSetLayoutUnique(descriptorSetLayoutInfo));
 
     const std::vector<vkhpp::DescriptorSetLayout> descriptorSetLayouts = {*descriptorSetLayout};
     const vkhpp::DescriptorSetAllocateInfo descriptorSetAllocateInfo = {
@@ -833,7 +1952,7 @@
         .pSetLayouts = descriptorSetLayouts.data(),
     };
     auto descriptorSets =
-        VK_ASSERT_RV(device->allocateDescriptorSetsUnique(descriptorSetAllocateInfo));
+        GFXSTREAM_ASSERT_VKHPP_RV(device->allocateDescriptorSetsUnique(descriptorSetAllocateInfo));
     auto descriptorSet = std::move(descriptorSets[0]);
 
     const vkhpp::PipelineLayoutCreateInfo pipelineLayoutCreateInfo = {
@@ -841,7 +1960,7 @@
         .pSetLayouts = descriptorSetLayouts.data(),
     };
     auto pipelineLayout =
-        VK_ASSERT_RV(device->createPipelineLayoutUnique(pipelineLayoutCreateInfo));
+        GFXSTREAM_ASSERT_VKHPP_RV(device->createPipelineLayoutUnique(pipelineLayoutCreateInfo));
 
     const std::vector<vkhpp::DescriptorUpdateTemplateEntry> descriptorUpdateEntries = {
         {
@@ -861,7 +1980,7 @@
         .pipelineLayout = *pipelineLayout,
         .set = 0,
     };
-    auto descriptorUpdateTemplate = VK_ASSERT_RV(
+    auto descriptorUpdateTemplate = GFXSTREAM_ASSERT_VKHPP_RV(
         device->createDescriptorUpdateTemplateUnique(descriptorUpdateTemplateCreateInfo));
 
     device->updateDescriptorSetWithTemplate(*descriptorSet, *descriptorUpdateTemplate,
@@ -870,7 +1989,7 @@
 
 TEST_P(GfxstreamEnd2EndVkTest, MultiThreadedVkMapMemory) {
     auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
-        VK_ASSERT(SetUpTypicalVkTestEnvironment());
+        GFXSTREAM_ASSERT(SetUpTypicalVkTestEnvironment());
 
     static constexpr const vkhpp::DeviceSize kSize = 1024;
     const vkhpp::BufferCreateInfo bufferCreateInfo = {
@@ -935,7 +2054,7 @@
 
 TEST_P(GfxstreamEnd2EndVkTest, MultiThreadedResetCommandBuffer) {
     auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
-        VK_ASSERT(SetUpTypicalVkTestEnvironment());
+        GFXSTREAM_ASSERT(SetUpTypicalVkTestEnvironment());
 
     static constexpr const vkhpp::DeviceSize kSize = 1024;
     const vkhpp::BufferCreateInfo bufferCreateInfo = {
@@ -1008,6 +2127,18 @@
     }
 }
 
+TEST_P(GfxstreamEnd2EndVkTest, ImportAndBlitFromR8G8B8A8Ahb) {
+    DoFillAndRenderFromAhb(GFXSTREAM_AHB_FORMAT_R8G8B8A8_UNORM);
+}
+
+TEST_P(GfxstreamEnd2EndVkTest, ImportAndBlitFromYCbCr888420Ahb) {
+    DoFillAndRenderFromAhb(GFXSTREAM_AHB_FORMAT_Y8Cb8Cr8_420);
+}
+
+TEST_P(GfxstreamEnd2EndVkTest, ImportAndBlitFromYv12Ahb) {
+    DoFillAndRenderFromAhb(GFXSTREAM_AHB_FORMAT_YV12);
+}
+
 std::vector<TestParams> GenerateTestCases() {
     std::vector<TestParams> cases = {TestParams{
                                          .with_gl = false,
diff --git a/common/end2end/shaders/blit_sampler2d.frag b/common/end2end/shaders/blit_sampler2d.frag
new file mode 100644
index 0000000..1c629eb
--- /dev/null
+++ b/common/end2end/shaders/blit_sampler2d.frag
@@ -0,0 +1,11 @@
+#version 460
+
+layout(set = 0, binding = 0) uniform sampler2D uTexture;
+
+layout(location = 0) noperspective in vec2 iUV;
+
+layout(location = 0) out vec4 oColor;
+
+void main() {
+    oColor = texture(uTexture, iUV);
+}
\ No newline at end of file
diff --git a/common/end2end/shaders/blit_sampler2d_frag.h b/common/end2end/shaders/blit_sampler2d_frag.h
new file mode 100644
index 0000000..22d1955
--- /dev/null
+++ b/common/end2end/shaders/blit_sampler2d_frag.h
@@ -0,0 +1,60 @@
+// Copyright (C) 2024 The Android Open Source Project
+// Copyright (C) 2024 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Please do not modify directly.
+
+// Autogenerated module common/end2end/shaders/blit_sampler2d_frag.h generated by:
+//   python3 scripts/glsl-shader-to-spv.py common/end2end/shaders/blit_sampler2d.frag
+//   common/end2end/shaders/blit_sampler2d_frag.h kBlitSampler2dFrag
+
+#include <stdint.h>
+
+#include <vector>
+
+// From common/end2end/shaders/blit_sampler2d.frag:
+
+// #version 460
+//
+// layout(set = 0, binding = 0) uniform sampler2D uTexture;
+//
+// layout(location = 0) noperspective in vec2 iUV;
+//
+// layout(location = 0) out vec4 oColor;
+//
+// void main() {
+//     oColor = texture(uTexture, iUV);
+// }
+
+const std::vector<uint32_t> kBlitSampler2dFrag = {
+    0x07230203, 0x00010000, 0x000d000b, 0x00000014, 0x00000000, 0x00020011, 0x00000001, 0x0006000b,
+    0x00000001, 0x4c534c47, 0x6474732e, 0x3035342e, 0x00000000, 0x0003000e, 0x00000000, 0x00000001,
+    0x0007000f, 0x00000004, 0x00000004, 0x6e69616d, 0x00000000, 0x00000009, 0x00000011, 0x00030010,
+    0x00000004, 0x00000007, 0x00030003, 0x00000002, 0x000001cc, 0x000a0004, 0x475f4c47, 0x4c474f4f,
+    0x70635f45, 0x74735f70, 0x5f656c79, 0x656e696c, 0x7269645f, 0x69746365, 0x00006576, 0x00080004,
+    0x475f4c47, 0x4c474f4f, 0x6e695f45, 0x64756c63, 0x69645f65, 0x74636572, 0x00657669, 0x00040005,
+    0x00000004, 0x6e69616d, 0x00000000, 0x00040005, 0x00000009, 0x6c6f436f, 0x0000726f, 0x00050005,
+    0x0000000d, 0x78655475, 0x65727574, 0x00000000, 0x00030005, 0x00000011, 0x00565569, 0x00040047,
+    0x00000009, 0x0000001e, 0x00000000, 0x00040047, 0x0000000d, 0x00000022, 0x00000000, 0x00040047,
+    0x0000000d, 0x00000021, 0x00000000, 0x00030047, 0x00000011, 0x0000000d, 0x00040047, 0x00000011,
+    0x0000001e, 0x00000000, 0x00020013, 0x00000002, 0x00030021, 0x00000003, 0x00000002, 0x00030016,
+    0x00000006, 0x00000020, 0x00040017, 0x00000007, 0x00000006, 0x00000004, 0x00040020, 0x00000008,
+    0x00000003, 0x00000007, 0x0004003b, 0x00000008, 0x00000009, 0x00000003, 0x00090019, 0x0000000a,
+    0x00000006, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x0003001b,
+    0x0000000b, 0x0000000a, 0x00040020, 0x0000000c, 0x00000000, 0x0000000b, 0x0004003b, 0x0000000c,
+    0x0000000d, 0x00000000, 0x00040017, 0x0000000f, 0x00000006, 0x00000002, 0x00040020, 0x00000010,
+    0x00000001, 0x0000000f, 0x0004003b, 0x00000010, 0x00000011, 0x00000001, 0x00050036, 0x00000002,
+    0x00000004, 0x00000000, 0x00000003, 0x000200f8, 0x00000005, 0x0004003d, 0x0000000b, 0x0000000e,
+    0x0000000d, 0x0004003d, 0x0000000f, 0x00000012, 0x00000011, 0x00050057, 0x00000007, 0x00000013,
+    0x0000000e, 0x00000012, 0x0003003e, 0x00000009, 0x00000013, 0x000100fd, 0x00010038};
\ No newline at end of file
diff --git a/common/end2end/shaders/fullscreen_triangle_with_uv.vert b/common/end2end/shaders/fullscreen_triangle_with_uv.vert
new file mode 100644
index 0000000..a7f0cfe
--- /dev/null
+++ b/common/end2end/shaders/fullscreen_triangle_with_uv.vert
@@ -0,0 +1,20 @@
+#version 460
+
+vec2 kPositions[3] = vec2[](
+    vec2(-1.0, -1.0),
+    vec2( 3.0, -1.0),
+    vec2(-1.0,  3.0)
+);
+
+vec2 kUVs[3] = vec2[](
+    vec2(0.0, 0.0),
+    vec2(2.0, 0.0),
+    vec2(0.0, 2.0)
+);
+
+layout (location = 0) out vec2 oUV;
+
+void main() {
+    gl_Position = vec4(kPositions[gl_VertexIndex], 0.0, 1.0);
+    oUV = kUVs[gl_VertexIndex];
+}
\ No newline at end of file
diff --git a/common/end2end/shaders/fullscreen_triangle_with_uv_vert.h b/common/end2end/shaders/fullscreen_triangle_with_uv_vert.h
new file mode 100644
index 0000000..3e54f0f
--- /dev/null
+++ b/common/end2end/shaders/fullscreen_triangle_with_uv_vert.h
@@ -0,0 +1,94 @@
+// Copyright (C) 2024 The Android Open Source Project
+// Copyright (C) 2024 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Please do not modify directly.
+
+// Autogenerated module common/end2end/shaders/fullscreen_triangle_with_uv_vert.h generated by:
+//   python3 scripts/glsl-shader-to-spv.py common/end2end/shaders/fullscreen_triangle_with_uv.vert
+//   common/end2end/shaders/fullscreen_triangle_with_uv_vert.h kFullscreenTriangleWithUVVert
+
+#include <stdint.h>
+
+#include <vector>
+
+// From common/end2end/shaders/fullscreen_triangle_with_uv.vert:
+
+// #version 460
+//
+// vec2 kPositions[3] = vec2[](
+//     vec2(-1.0, -1.0),
+//     vec2( 3.0, -1.0),
+//     vec2(-1.0,  3.0)
+// );
+//
+// vec2 kUVs[3] = vec2[](
+//     vec2(0.0, 0.0),
+//     vec2(2.0, 0.0),
+//     vec2(0.0, 2.0)
+// );
+//
+// layout (location = 0) out vec2 oUV;
+//
+// void main() {
+//     gl_Position = vec4(kPositions[gl_VertexIndex], 0.0, 1.0);
+//     oUV = kUVs[gl_VertexIndex];
+// }
+
+const std::vector<uint32_t> kFullscreenTriangleWithUVVert = {
+    0x07230203, 0x00010000, 0x000d000b, 0x00000033, 0x00000000, 0x00020011, 0x00000001, 0x0006000b,
+    0x00000001, 0x4c534c47, 0x6474732e, 0x3035342e, 0x00000000, 0x0003000e, 0x00000000, 0x00000001,
+    0x0008000f, 0x00000000, 0x00000004, 0x6e69616d, 0x00000000, 0x0000001f, 0x00000023, 0x0000002f,
+    0x00030003, 0x00000002, 0x000001cc, 0x000a0004, 0x475f4c47, 0x4c474f4f, 0x70635f45, 0x74735f70,
+    0x5f656c79, 0x656e696c, 0x7269645f, 0x69746365, 0x00006576, 0x00080004, 0x475f4c47, 0x4c474f4f,
+    0x6e695f45, 0x64756c63, 0x69645f65, 0x74636572, 0x00657669, 0x00040005, 0x00000004, 0x6e69616d,
+    0x00000000, 0x00050005, 0x0000000c, 0x736f506b, 0x6f697469, 0x0000736e, 0x00040005, 0x00000013,
+    0x7356556b, 0x00000000, 0x00060005, 0x0000001d, 0x505f6c67, 0x65567265, 0x78657472, 0x00000000,
+    0x00060006, 0x0000001d, 0x00000000, 0x505f6c67, 0x7469736f, 0x006e6f69, 0x00070006, 0x0000001d,
+    0x00000001, 0x505f6c67, 0x746e696f, 0x657a6953, 0x00000000, 0x00070006, 0x0000001d, 0x00000002,
+    0x435f6c67, 0x4470696c, 0x61747369, 0x0065636e, 0x00070006, 0x0000001d, 0x00000003, 0x435f6c67,
+    0x446c6c75, 0x61747369, 0x0065636e, 0x00030005, 0x0000001f, 0x00000000, 0x00060005, 0x00000023,
+    0x565f6c67, 0x65747265, 0x646e4978, 0x00007865, 0x00030005, 0x0000002f, 0x0056556f, 0x00050048,
+    0x0000001d, 0x00000000, 0x0000000b, 0x00000000, 0x00050048, 0x0000001d, 0x00000001, 0x0000000b,
+    0x00000001, 0x00050048, 0x0000001d, 0x00000002, 0x0000000b, 0x00000003, 0x00050048, 0x0000001d,
+    0x00000003, 0x0000000b, 0x00000004, 0x00030047, 0x0000001d, 0x00000002, 0x00040047, 0x00000023,
+    0x0000000b, 0x0000002a, 0x00040047, 0x0000002f, 0x0000001e, 0x00000000, 0x00020013, 0x00000002,
+    0x00030021, 0x00000003, 0x00000002, 0x00030016, 0x00000006, 0x00000020, 0x00040017, 0x00000007,
+    0x00000006, 0x00000002, 0x00040015, 0x00000008, 0x00000020, 0x00000000, 0x0004002b, 0x00000008,
+    0x00000009, 0x00000003, 0x0004001c, 0x0000000a, 0x00000007, 0x00000009, 0x00040020, 0x0000000b,
+    0x00000006, 0x0000000a, 0x0004003b, 0x0000000b, 0x0000000c, 0x00000006, 0x0004002b, 0x00000006,
+    0x0000000d, 0xbf800000, 0x0005002c, 0x00000007, 0x0000000e, 0x0000000d, 0x0000000d, 0x0004002b,
+    0x00000006, 0x0000000f, 0x40400000, 0x0005002c, 0x00000007, 0x00000010, 0x0000000f, 0x0000000d,
+    0x0005002c, 0x00000007, 0x00000011, 0x0000000d, 0x0000000f, 0x0006002c, 0x0000000a, 0x00000012,
+    0x0000000e, 0x00000010, 0x00000011, 0x0004003b, 0x0000000b, 0x00000013, 0x00000006, 0x0004002b,
+    0x00000006, 0x00000014, 0x00000000, 0x0005002c, 0x00000007, 0x00000015, 0x00000014, 0x00000014,
+    0x0004002b, 0x00000006, 0x00000016, 0x40000000, 0x0005002c, 0x00000007, 0x00000017, 0x00000016,
+    0x00000014, 0x0005002c, 0x00000007, 0x00000018, 0x00000014, 0x00000016, 0x0006002c, 0x0000000a,
+    0x00000019, 0x00000015, 0x00000017, 0x00000018, 0x00040017, 0x0000001a, 0x00000006, 0x00000004,
+    0x0004002b, 0x00000008, 0x0000001b, 0x00000001, 0x0004001c, 0x0000001c, 0x00000006, 0x0000001b,
+    0x0006001e, 0x0000001d, 0x0000001a, 0x00000006, 0x0000001c, 0x0000001c, 0x00040020, 0x0000001e,
+    0x00000003, 0x0000001d, 0x0004003b, 0x0000001e, 0x0000001f, 0x00000003, 0x00040015, 0x00000020,
+    0x00000020, 0x00000001, 0x0004002b, 0x00000020, 0x00000021, 0x00000000, 0x00040020, 0x00000022,
+    0x00000001, 0x00000020, 0x0004003b, 0x00000022, 0x00000023, 0x00000001, 0x00040020, 0x00000025,
+    0x00000006, 0x00000007, 0x0004002b, 0x00000006, 0x00000028, 0x3f800000, 0x00040020, 0x0000002c,
+    0x00000003, 0x0000001a, 0x00040020, 0x0000002e, 0x00000003, 0x00000007, 0x0004003b, 0x0000002e,
+    0x0000002f, 0x00000003, 0x00050036, 0x00000002, 0x00000004, 0x00000000, 0x00000003, 0x000200f8,
+    0x00000005, 0x0003003e, 0x0000000c, 0x00000012, 0x0003003e, 0x00000013, 0x00000019, 0x0004003d,
+    0x00000020, 0x00000024, 0x00000023, 0x00050041, 0x00000025, 0x00000026, 0x0000000c, 0x00000024,
+    0x0004003d, 0x00000007, 0x00000027, 0x00000026, 0x00050051, 0x00000006, 0x00000029, 0x00000027,
+    0x00000000, 0x00050051, 0x00000006, 0x0000002a, 0x00000027, 0x00000001, 0x00070050, 0x0000001a,
+    0x0000002b, 0x00000029, 0x0000002a, 0x00000014, 0x00000028, 0x00050041, 0x0000002c, 0x0000002d,
+    0x0000001f, 0x00000021, 0x0003003e, 0x0000002d, 0x0000002b, 0x0004003d, 0x00000020, 0x00000030,
+    0x00000023, 0x00050041, 0x00000025, 0x00000031, 0x00000013, 0x00000030, 0x0004003d, 0x00000007,
+    0x00000032, 0x00000031, 0x0003003e, 0x0000002f, 0x00000032, 0x000100fd, 0x00010038};
\ No newline at end of file
diff --git a/common/end2end/simple_shader.frag b/common/end2end/shaders/simple_shader.frag
similarity index 100%
rename from common/end2end/simple_shader.frag
rename to common/end2end/shaders/simple_shader.frag
diff --git a/common/end2end/simple_shader.vert b/common/end2end/shaders/simple_shader.vert
similarity index 100%
rename from common/end2end/simple_shader.vert
rename to common/end2end/shaders/simple_shader.vert
diff --git a/common/end2end/simple_shader_frag.h b/common/end2end/shaders/simple_shader_frag.h
similarity index 69%
rename from common/end2end/simple_shader_frag.h
rename to common/end2end/shaders/simple_shader_frag.h
index 974d127..281362c 100644
--- a/common/end2end/simple_shader_frag.h
+++ b/common/end2end/shaders/simple_shader_frag.h
@@ -13,13 +13,48 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// Autogenerated module common/end2end/simple_shader_frag.h
-// generated by python3 scripts/glsl-shader-to-spv-c-array.py common/end2end/simple_shader.frag
-// common/end2end/simple_shader_frag.h kSimpleShaderFrag Please do not modify directly.
+// Please do not modify directly.
+
+// Autogenerated module common/end2end/shaders/simple_shader_frag.h generated by:
+//   python3 scripts/glsl-shader-to-spv.py common/end2end/shaders/simple_shader.frag
+//   common/end2end/shaders/simple_shader_frag.h kSimpleShaderFrag
 
 #include <stdint.h>
 
-const uint32_t kSimpleShaderFrag[] = {
+#include <vector>
+
+// From common/end2end/shaders/simple_shader.frag:
+
+// // Copyright (C) 2024 The Android Open Source Project
+// //
+// // Licensed under the Apache License, Version 2.0 (the "License");
+// // you may not use this file except in compliance with the License.
+// // You may obtain a copy of the License at
+// //
+// // http://www.apache.org/licenses/LICENSE-2.0
+// //
+// // Unless required by applicable law or agreed to in writing, software
+// // distributed under the License is distributed on an "AS IS" BASIS,
+// // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// // See the License for the specific language governing permissions and
+// // limitations under the License.
+//
+// #version 450
+//
+// layout (binding = 0) uniform UniformBuffer {
+//   vec4 color1;
+// };
+//
+// layout (location = 0) in vec4 color;
+//
+// layout (location = 0) out vec4 outColor;
+//
+// void main()
+// {
+//   outColor = color + color1;
+// }
+
+const std::vector<uint32_t> kSimpleShaderFrag = {
     0x07230203, 0x00010000, 0x000d000b, 0x00000016, 0x00000000, 0x00020011, 0x00000001, 0x0006000b,
     0x00000001, 0x4c534c47, 0x6474732e, 0x3035342e, 0x00000000, 0x0003000e, 0x00000000, 0x00000001,
     0x0007000f, 0x00000004, 0x00000004, 0x6e69616d, 0x00000000, 0x00000009, 0x0000000b, 0x00030010,
diff --git a/common/end2end/simple_shader_vert.h b/common/end2end/shaders/simple_shader_vert.h
similarity index 73%
rename from common/end2end/simple_shader_vert.h
rename to common/end2end/shaders/simple_shader_vert.h
index 49a78fd..94c49af 100644
--- a/common/end2end/simple_shader_vert.h
+++ b/common/end2end/shaders/simple_shader_vert.h
@@ -13,13 +13,46 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// Autogenerated module common/end2end/simple_shader_vert.h
-// generated by python3 scripts/glsl-shader-to-spv-c-array.py common/end2end/simple_shader.vert
-// common/end2end/simple_shader_vert.h kSimpleShaderVert Please do not modify directly.
+// Please do not modify directly.
+
+// Autogenerated module common/end2end/shaders/simple_shader_vert.h generated by:
+//   python3 scripts/glsl-shader-to-spv.py common/end2end/shaders/simple_shader.vert
+//   common/end2end/shaders/simple_shader_vert.h kSimpleShaderVert
 
 #include <stdint.h>
 
-const uint32_t kSimpleShaderVert[] = {
+#include <vector>
+
+// From common/end2end/shaders/simple_shader.vert:
+
+// // Copyright (C) 2024 The Android Open Source Project
+// //
+// // Licensed under the Apache License, Version 2.0 (the "License");
+// // you may not use this file except in compliance with the License.
+// // You may obtain a copy of the License at
+// //
+// // http://www.apache.org/licenses/LICENSE-2.0
+// //
+// // Unless required by applicable law or agreed to in writing, software
+// // distributed under the License is distributed on an "AS IS" BASIS,
+// // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// // See the License for the specific language governing permissions and
+// // limitations under the License.
+//
+// #version 450
+//
+// layout (location = 0) in vec4 pos;
+// layout (location = 1) in vec4 inColor;
+//
+// layout (location = 0) out vec4 outColor;
+//
+// void main()
+// {
+//   outColor = inColor;
+//   gl_Position = pos;
+// }
+
+const std::vector<uint32_t> kSimpleShaderVert = {
     0x07230203, 0x00010000, 0x000d000b, 0x00000018, 0x00000000, 0x00020011, 0x00000001, 0x0006000b,
     0x00000001, 0x4c534c47, 0x6474732e, 0x3035342e, 0x00000000, 0x0003000e, 0x00000000, 0x00000001,
     0x0009000f, 0x00000000, 0x00000004, 0x6e69616d, 0x00000000, 0x00000009, 0x0000000b, 0x00000012,
diff --git a/common/utils/include/gfxstream/Expected.h b/common/utils/include/gfxstream/Expected.h
new file mode 100644
index 0000000..529cd7e
--- /dev/null
+++ b/common/utils/include/gfxstream/Expected.h
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <functional>
+#include <type_traits>
+#include <variant>
+
+namespace gfxstream {
+
+template <typename E>
+class unexpected;
+
+template<class E>
+unexpected(E) -> unexpected<E>;
+
+#define ENABLE_IF(...) typename std::enable_if<__VA_ARGS__>::type* = nullptr
+
+template <typename T, typename E>
+class expected {
+  public:
+    constexpr expected() = default;
+    constexpr expected(const expected& rhs) = default;
+    constexpr expected(expected&& rhs) = default;
+
+    template <typename CopyT = T, ENABLE_IF(!std::is_void<CopyT>::value)>
+    constexpr expected(T&& v)
+        : mVariant(std::in_place_index<0>, std::forward<T>(v)) {}
+
+    template<class... Args, ENABLE_IF(std::is_constructible<T, Args&&...>::value)>
+    constexpr expected(std::in_place_t, Args&&... args)
+        : mVariant(std::in_place_index<0>, std::forward<Args>(args)...) {}
+
+    constexpr expected(const unexpected<E>& u)
+        : mVariant(std::in_place_index<1>, u.value()) {}
+
+    template<class OtherE = E, ENABLE_IF(std::is_constructible<E, const OtherE&>::value)>
+    constexpr expected(const unexpected<OtherE>& e)
+        : mVariant(std::in_place_index<1>, e.value()) {}
+
+    constexpr const T* operator->() const { return std::addressof(value()); }
+    constexpr T* operator->() { return std::addressof(value()); }
+    constexpr const T& operator*() const& { return value(); }
+    constexpr T& operator*() & { return value(); }
+    constexpr const T&& operator*() const&& { return std::move(std::get<T>(mVariant)); }
+    constexpr T&& operator*() && { return std::move(std::get<T>(mVariant)); }
+
+    constexpr bool has_value() const { return mVariant.index() == 0; }
+    constexpr bool ok() const { return has_value(); }
+
+    template <typename T2 = T, ENABLE_IF(!std::is_void<T>::value)>
+    constexpr const T& value() const& { return std::get<T>(mVariant); }
+    template <typename T2 = T, ENABLE_IF(!std::is_void<T>::value)>
+    constexpr T& value() & { return std::get<T>(mVariant); }
+
+    constexpr const T&& value() const&& { return std::move(std::get<T>(mVariant)); }
+    constexpr T&& value() && { return std::move(std::get<T>(mVariant)); }
+
+    constexpr const E& error() const& { return std::get<E>(mVariant); }
+    constexpr E& error() & { return std::get<E>(mVariant); }
+    constexpr const E&& error() const&& { return std::move(std::get<E>(mVariant)); }
+    constexpr E&& error() && { return std::move(std::get<E>(mVariant)); }
+
+    template <typename F,
+              typename NewE = std::remove_cv_t<std::invoke_result_t<F, E>>>
+    constexpr expected<T, NewE> transform_error(F&& function) {
+        if (ok()) {
+            if constexpr (std::is_void_v<T>) {
+                return expected<T, NewE>();
+            } else {
+                return expected<T, NewE>(std::in_place, std::move(value()));
+            }
+        } else {
+            return unexpected(std::invoke(std::forward<F>(function), error()));
+        }
+    }
+
+  private:
+    std::variant<T, E> mVariant;
+};
+
+template <typename E>
+class unexpected {
+  public:
+    constexpr unexpected(const unexpected&) = default;
+
+    template <typename T>
+    constexpr explicit unexpected(T&& e)
+        : mError(std::forward<T>(e)) {}
+
+    template<class... Args, ENABLE_IF(std::is_constructible<E, Args&&...>::value)>
+    constexpr explicit unexpected(std::in_place_t, Args&&... args)
+        : mError(std::forward<Args>(args)...) {}
+
+    constexpr const E& value() const& noexcept { return mError; }
+    constexpr E& value() & noexcept { return mError; }
+    constexpr const E&& value() const&& noexcept { return std::move(mError); }
+    constexpr E&& value() && noexcept { return std::move(mError); }
+
+  private:
+    E mError;
+};
+
+#define GFXSTREAM_EXPECT(x)                                       \
+    ({                                                            \
+        auto local_expected = (x);                                \
+        if (!local_expected.ok()) {                               \
+            return gfxstream::unexpected(local_expected.error()); \
+        };                                                        \
+        std::move(local_expected.value());                        \
+     })
+
+class Ok {};
+
+}  // namespace gfxstream
\ No newline at end of file
diff --git a/guest/BUILD.gn b/guest/BUILD.gn
index 9b5b697..33e5f65 100644
--- a/guest/BUILD.gn
+++ b/guest/BUILD.gn
@@ -31,6 +31,7 @@
 
   include_dirs = [
     "../common/opengl/include",
+    "../common/vulkan/include",
     "android-emu",
     "GoldfishAddressSpace/include",
     "iostream/include",
diff --git a/guest/GLESv2_enc/Android.bp b/guest/GLESv2_enc/Android.bp
index f72c41f..0ea4aeb 100644
--- a/guest/GLESv2_enc/Android.bp
+++ b/guest/GLESv2_enc/Android.bp
@@ -19,6 +19,20 @@
     default_applicable_licenses: ["hardware_google_gfxstream_license"],
 }
 
+cc_library {
+    name: "libgfxstream_gles2_encoder_program_binary_proto",
+    host_supported: true,
+    vendor: true,
+    proto: {
+        canonical_path_from_root: false,
+        export_proto_headers: true,
+        type: "lite",
+    },
+    srcs: [
+        "ProgramBinary.proto",
+    ],
+}
+
 cc_library_shared {
     name: "libGLESv2_enc",
     host_supported: true,
@@ -38,6 +52,13 @@
     export_shared_lib_headers: [
         "libOpenglCodecCommon",
     ],
+    static_libs: [
+        "libgfxstream_gles2_encoder_program_binary_proto",
+        "libprotobuf-cpp-lite",
+    ],
+    export_static_lib_headers: [
+        "libgfxstream_gles2_encoder_program_binary_proto",
+    ],
     cflags: [
         "-DGL_GLEXT_PROTOTYPES",
         "-DLOG_TAG=\"emuglGLESv2_enc\"",
diff --git a/guest/GLESv2_enc/GL2Encoder.cpp b/guest/GLESv2_enc/GL2Encoder.cpp
old mode 100755
new mode 100644
index c9fcc64..33f018c
--- a/guest/GLESv2_enc/GL2Encoder.cpp
+++ b/guest/GLESv2_enc/GL2Encoder.cpp
@@ -39,8 +39,10 @@
 using gfxstream::guest::GLClientState;
 using gfxstream::guest::GLSharedGroupPtr;
 using gfxstream::guest::IOStream;
+using gfxstream::guest::ProgramData;
 using gfxstream::guest::ShaderData;
 using gfxstream::guest::ShaderProgramData;
+using gfxstream::guest::gles2::ProgramBinaryInfo;
 
 #ifndef MIN
 #define MIN(a, b) ((a) < (b) ? (a) : (b))
@@ -1939,21 +1941,11 @@
     ctx->glFinishRoundTrip(self);
 }
 
-void GL2Encoder::s_glLinkProgram(void* self, GLuint program) {
-    GL2Encoder* ctx = (GL2Encoder*)self;
-    bool isProgram = ctx->m_shared->isProgram(program);
-    SET_ERROR_IF(!isProgram && !ctx->m_shared->isShader(program), GL_INVALID_VALUE);
-    SET_ERROR_IF(!isProgram, GL_INVALID_OPERATION);
-
-    if (program == ctx->m_state->currentProgram() ||
-        (!ctx->m_state->currentProgram() && (program == ctx->m_state->currentShaderProgram()))) {
-        SET_ERROR_IF(ctx->m_state->getTransformFeedbackActive(), GL_INVALID_OPERATION);
-    }
-
-    ctx->m_glLinkProgram_enc(self, program);
+void GL2Encoder::updateProgramInfoAfterLink(GLuint program) {
+    GL2Encoder* ctx = this;
 
     GLint linkStatus = 0;
-    ctx->m_glGetProgramiv_enc(self, program, GL_LINK_STATUS, &linkStatus);
+    ctx->m_glGetProgramiv_enc(ctx, program, GL_LINK_STATUS, &linkStatus);
     ctx->m_shared->setProgramLinkStatus(program, linkStatus);
     if (!linkStatus) {
         return;
@@ -1962,15 +1954,15 @@
     // get number of active uniforms and attributes in the program
     GLint numUniforms=0;
     GLint numAttributes=0;
-    ctx->m_glGetProgramiv_enc(self, program, GL_ACTIVE_UNIFORMS, &numUniforms);
-    ctx->m_glGetProgramiv_enc(self, program, GL_ACTIVE_ATTRIBUTES, &numAttributes);
+    ctx->m_glGetProgramiv_enc(ctx, program, GL_ACTIVE_UNIFORMS, &numUniforms);
+    ctx->m_glGetProgramiv_enc(ctx, program, GL_ACTIVE_ATTRIBUTES, &numAttributes);
     ctx->m_shared->initProgramData(program,numUniforms,numAttributes);
 
     //get the length of the longest uniform name
     GLint maxLength=0;
     GLint maxAttribLength=0;
-    ctx->m_glGetProgramiv_enc(self, program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength);
-    ctx->m_glGetProgramiv_enc(self, program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxAttribLength);
+    ctx->m_glGetProgramiv_enc(ctx, program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength);
+    ctx->m_glGetProgramiv_enc(ctx, program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxAttribLength);
 
     GLint size;
     GLenum type;
@@ -1980,14 +1972,14 @@
     //for each active uniform, get its size and starting location.
     for (GLint i=0 ; i<numUniforms ; ++i)
     {
-        ctx->m_glGetActiveUniform_enc(self, program, i, maxLength, NULL, &size, &type, name);
-        location = ctx->m_glGetUniformLocation_enc(self, program, name);
+        ctx->m_glGetActiveUniform_enc(ctx, program, i, maxLength, NULL, &size, &type, name);
+        location = ctx->m_glGetUniformLocation_enc(ctx, program, name);
         ctx->m_shared->setProgramIndexInfo(program, i, location, size, type, name);
     }
 
     for (GLint i = 0; i < numAttributes; ++i) {
-        ctx->m_glGetActiveAttrib_enc(self, program, i, maxAttribLength, NULL, &size, &type, name);
-        location = ctx->m_glGetAttribLocation_enc(self, program, name);
+        ctx->m_glGetActiveAttrib_enc(ctx, program, i, maxAttribLength, NULL, &size, &type, name);
+        location = ctx->m_glGetAttribLocation_enc(ctx, program, name);
         ctx->m_shared->setProgramAttribInfo(program, i, location, size, type, name);
     }
 
@@ -2004,6 +1996,22 @@
     delete[] name;
 }
 
+void GL2Encoder::s_glLinkProgram(void* self, GLuint program) {
+    GL2Encoder* ctx = (GL2Encoder*)self;
+    bool isProgram = ctx->m_shared->isProgram(program);
+    SET_ERROR_IF(!isProgram && !ctx->m_shared->isShader(program), GL_INVALID_VALUE);
+    SET_ERROR_IF(!isProgram, GL_INVALID_OPERATION);
+
+    if (program == ctx->m_state->currentProgram() ||
+        (!ctx->m_state->currentProgram() && (program == ctx->m_state->currentShaderProgram()))) {
+        SET_ERROR_IF(ctx->m_state->getTransformFeedbackActive(), GL_INVALID_OPERATION);
+    }
+
+    ctx->m_glLinkProgram_enc(self, program);
+
+    ctx->updateProgramInfoAfterLink(program);
+}
+
 #define VALIDATE_PROGRAM_NAME(program) \
     bool isShaderOrProgramObject = \
         ctx->m_shared->isShaderOrProgramObject(program); \
@@ -4955,20 +4963,129 @@
     return retval;
 }
 
+std::optional<ProgramBinaryInfo> GL2Encoder::getProgramBinary(GLuint program) {
+    GL2Encoder* ctx = this;
+
+    VALIDATE_PROGRAM_NAME_RET(program, std::nullopt);
+
+    GLint linkStatus = 0;
+    ctx->m_glGetProgramiv_enc(ctx, program, GL_LINK_STATUS, &linkStatus);
+    if (!linkStatus) return std::nullopt;
+
+    ProgramBinaryInfo info;
+
+    {
+        auto* guestProgramInfo = info.mutable_guest_program_info();
+
+        // External sampler uniforms can not be reconstructed from the host program info
+        // because the host only sees the modified shader where each `samplerExternalOES`
+        // was rewritten to `sampler2D`.
+        std::vector<GLuint> externalSamplerUnifomIndices;
+        if (!ctx->m_shared->getExternalSamplerUniformIndices(program,
+                                                             &externalSamplerUnifomIndices)) {
+            return std::nullopt;
+        }
+        for (GLuint index : externalSamplerUnifomIndices) {
+            guestProgramInfo->add_external_sampler_uniform_indices(index);
+        }
+    }
+
+    {
+        auto* hostProgramInfo = info.mutable_host_program_info();
+
+        GLint hostProgramBinaryLength = 0;
+        ctx->m_glGetProgramiv_enc(ctx, program, GL_PROGRAM_BINARY_LENGTH, &hostProgramBinaryLength);
+
+        std::string hostProgramBinary;
+        hostProgramBinary.resize(hostProgramBinaryLength, 'x');
+
+        GLenum hostProgramBinaryFormat = 0;
+        ctx->m_glGetProgramBinary_enc(ctx, program, hostProgramBinary.size(), nullptr,
+                                      &hostProgramBinaryFormat, hostProgramBinary.data());
+
+        hostProgramInfo->set_binary_format(static_cast<uint64_t>(hostProgramBinaryFormat));
+        hostProgramInfo->set_binary(hostProgramBinary);
+    }
+
+    return info;
+}
+
+void GL2Encoder::getProgramBinaryLength(GLuint program, GLint* outLength) {
+    GL2Encoder* ctx = (GL2Encoder*)this;
+
+    VALIDATE_PROGRAM_NAME(program);
+
+    auto programBinaryInfoOpt = ctx->getProgramBinary(program);
+    SET_ERROR_IF(!programBinaryInfoOpt.has_value(), GL_INVALID_OPERATION);
+    auto& programBinaryInfo = *programBinaryInfoOpt;
+
+    std::string programBinaryInfoBytes;
+    SET_ERROR_IF(!programBinaryInfo.SerializeToString(&programBinaryInfoBytes),
+                 GL_INVALID_OPERATION);
+
+    *outLength = static_cast<GLint>(programBinaryInfoBytes.size());
+}
+
+#define GL_PROGRAM_BINARY_FORMAT_GFXSTREAM_PROGRAM_BINARY_INFO_V1 0x0001
+
 void GL2Encoder::s_glGetProgramBinary(void* self, GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, void* binary) {
     GL2Encoder *ctx = (GL2Encoder *)self;
 
     VALIDATE_PROGRAM_NAME(program);
 
-    GLint linkStatus = 0;
-    ctx->m_glGetProgramiv_enc(self, program, GL_LINK_STATUS, &linkStatus);
-    GLint properLength = 0;
-    ctx->m_glGetProgramiv_enc(self, program, GL_PROGRAM_BINARY_LENGTH, &properLength);
+    auto programBinaryInfoOpt = ctx->getProgramBinary(program);
+    SET_ERROR_IF(!programBinaryInfoOpt.has_value(), GL_INVALID_OPERATION);
+    auto& programBinaryInfo = *programBinaryInfoOpt;
 
-    SET_ERROR_IF(!linkStatus, GL_INVALID_OPERATION);
-    SET_ERROR_IF(bufSize < properLength, GL_INVALID_OPERATION);
+    std::string programBinaryInfoBytes;
+    SET_ERROR_IF(!programBinaryInfo.SerializeToString(&programBinaryInfoBytes),
+                 GL_INVALID_OPERATION);
 
-    ctx->m_glGetProgramBinary_enc(ctx, program, bufSize, length, binaryFormat, binary);
+    SET_ERROR_IF(bufSize < programBinaryInfoBytes.size(), GL_INVALID_OPERATION);
+
+    if (length) {
+        *length = static_cast<GLsizei>(programBinaryInfoBytes.size());
+    }
+    *binaryFormat = GL_PROGRAM_BINARY_FORMAT_GFXSTREAM_PROGRAM_BINARY_INFO_V1;
+    std::memcpy(binary, programBinaryInfoBytes.data(), programBinaryInfoBytes.size());
+}
+
+void GL2Encoder::s_glProgramBinary(void* self, GLuint program, GLenum binaryFormat,
+                                   const void* binary, GLsizei length) {
+    GL2Encoder* ctx = (GL2Encoder*)self;
+
+    VALIDATE_PROGRAM_NAME(program);
+
+    SET_ERROR_IF(binaryFormat != GL_PROGRAM_BINARY_FORMAT_GFXSTREAM_PROGRAM_BINARY_INFO_V1,
+                 GL_INVALID_ENUM);
+
+    std::string programBinaryInfoBytes(reinterpret_cast<const char*>(binary), length);
+
+    ProgramBinaryInfo programBinaryInfo;
+    if (!programBinaryInfo.ParseFromString(programBinaryInfoBytes)) {
+        ctx->m_shared->setProgramLinkStatus(program, GL_FALSE);
+        return;
+    }
+
+    {
+        const auto& hostProgramInfo = programBinaryInfo.host_program_info();
+
+        const auto hostProgramBinaryFormat = static_cast<GLenum>(hostProgramInfo.binary_format());
+        const auto& hostProgramBinary = hostProgramInfo.binary();
+        ctx->m_glProgramBinary_enc(self, program, hostProgramBinaryFormat,
+                                   hostProgramBinary.c_str(), hostProgramBinary.size());
+
+        ctx->updateProgramInfoAfterLink(program);
+    }
+
+    {
+        const auto& guestProgramInfo = programBinaryInfo.guest_program_info();
+
+        for (uint64_t index : guestProgramInfo.external_sampler_uniform_indices()) {
+            ctx->m_shared->setProgramIndexFlag(program, index,
+                                               ProgramData::INDEX_FLAG_SAMPLER_EXTERNAL);
+        }
+    }
 }
 
 void GL2Encoder::s_glReadPixels(void* self, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels) {
@@ -6345,16 +6462,6 @@
     ctx->m_glValidateProgram_enc(self, program);
 }
 
-void GL2Encoder::s_glProgramBinary(void *self , GLuint program, GLenum binaryFormat, const void* binary, GLsizei length) {
-    GL2Encoder *ctx = (GL2Encoder*)self;
-
-    VALIDATE_PROGRAM_NAME(program);
-
-    SET_ERROR_IF(~0 == binaryFormat, GL_INVALID_ENUM);
-
-    ctx->m_glProgramBinary_enc(self, program, binaryFormat, binary, length);
-}
-
 void GL2Encoder::s_glGetSamplerParameterfv(void *self, GLuint sampler, GLenum pname, GLfloat* params) {
     GL2Encoder *ctx = (GL2Encoder*)self;
 
@@ -6690,6 +6797,11 @@
     GL2Encoder* ctx = (GL2Encoder*)self;
     SET_ERROR_IF(!GLESv2Validation::allowedGetProgram(ctx->majorVersion(), ctx->minorVersion(), pname), GL_INVALID_ENUM);
     VALIDATE_PROGRAM_NAME(program);
+
+    if (pname == GL_PROGRAM_BINARY_LENGTH) {
+        return ctx->getProgramBinaryLength(program, params);
+    }
+
     ctx->m_glGetProgramiv_enc(ctx, program, pname, params);
 }
 
diff --git a/guest/GLESv2_enc/GL2Encoder.h b/guest/GLESv2_enc/GL2Encoder.h
index b7d79f0..f6aa37a 100644
--- a/guest/GLESv2_enc/GL2Encoder.h
+++ b/guest/GLESv2_enc/GL2Encoder.h
@@ -16,13 +16,15 @@
 #ifndef _GL2_ENCODER_H_
 #define _GL2_ENCODER_H_
 
-#include "gl2_enc.h"
-#include "gfxstream/guest/GLClientState.h"
-#include "gfxstream/guest/GLSharedGroup.h"
-
+#include <optional>
 #include <string>
 #include <vector>
 
+#include "ProgramBinary.pb.h"
+#include "gfxstream/guest/GLClientState.h"
+#include "gfxstream/guest/GLSharedGroup.h"
+#include "gl2_enc.h"
+
 struct Extensions
 {
     Extensions() = default;
@@ -117,7 +119,10 @@
     bool isBufferMapped(GLuint buffer) const;
     bool isBufferTargetMapped(GLenum target) const;
 
-private:
+    std::optional<gfxstream::guest::gles2::ProgramBinaryInfo> getProgramBinary(GLuint program);
+    void getProgramBinaryLength(GLuint program, GLint* outLength);
+
+   private:
 
     int m_currMajorVersion;
     int m_currMinorVersion;
@@ -190,6 +195,8 @@
     void updateHostTexture2DBindingsFromProgramData(GLuint program);
     bool texture2DNeedsOverride(GLenum target) const;
 
+    void updateProgramInfoAfterLink(GLuint program);
+
     // Utility classes for safe queries that
     // need access to private class members
     class ErrorUpdater;
diff --git a/guest/GLESv2_enc/ProgramBinary.proto b/guest/GLESv2_enc/ProgramBinary.proto
new file mode 100644
index 0000000..a9a6636
--- /dev/null
+++ b/guest/GLESv2_enc/ProgramBinary.proto
@@ -0,0 +1,42 @@
+// Copyright (C) 2024 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+syntax = "proto3";
+
+package gfxstream.guest.gles2;
+
+// Gfxstream's custom format for `glGetProgramBinary()` and `glProgramBinary()`.
+message ProgramBinaryInfo {
+    // Info about the program that can not be queried or recreated from the host
+    // program and must be saved in order to recreate the original guest program
+    // state.
+    message GuestProgramInfo {
+        // The uniform indices that were originally `samplerExternalOes`. These
+        // need to be explicitly saved because they are rewritten to `sampler2D`
+        // before being sent to the host.
+        repeated uint64 external_sampler_uniform_indices = 1;
+    }
+
+    GuestProgramInfo guest_program_info = 1;
+
+    message HostProgramInfo {
+        // The GLenum returned in glGetProgramBinary()'s `binaryFormat` parameter.
+        uint64 binary_format = 1;
+
+        // The bytes returned in glGetProgramBinary()'s `binary` parameter.
+        bytes binary = 2;
+    }
+
+    HostProgramInfo host_program_info = 2;
+}
diff --git a/guest/OpenglCodecCommon/GLSharedGroup.cpp b/guest/OpenglCodecCommon/GLSharedGroup.cpp
old mode 100755
new mode 100644
index da3de64..78aa187
--- a/guest/OpenglCodecCommon/GLSharedGroup.cpp
+++ b/guest/OpenglCodecCommon/GLSharedGroup.cpp
@@ -138,6 +138,14 @@
     return false;
 }
 
+void ProgramData::getExternalSamplerUniformIndices(std::vector<GLuint>* outIndices) {
+    for (GLuint i = 0; i < m_numIndexes; ++i) {
+        if (m_Indexes[i].flags & INDEX_FLAG_SAMPLER_EXTERNAL) {
+            outIndices->push_back(i);
+        }
+    }
+}
+
 GLint ProgramData::getNextSamplerUniform(
     GLint index, GLint* val, GLenum* target) {
 
@@ -559,6 +567,15 @@
     }
 }
 
+void GLSharedGroup::setProgramIndexFlag(GLuint program, GLuint index, GLuint flags) {
+    AutoLock<Lock> _lock(m_lock);
+
+    ProgramData* pData = findObjectOrDefault(m_programs, program);
+    if (pData) {
+        pData->setIndexFlags(index, flags);
+    }
+}
+
 void GLSharedGroup::setProgramAttribInfo(
     GLuint program, GLuint index, GLint attribLoc,
     GLint size, GLenum type, __attribute__((unused)) const char* name) {
@@ -672,6 +689,19 @@
     return pData->isValidUniformLocation(location);
 }
 
+bool GLSharedGroup::getExternalSamplerUniformIndices(GLuint program,
+                                                     std::vector<GLuint>* outIndices) {
+    AutoLock<Lock> _lock(m_lock);
+
+    ProgramData* pData = findObjectOrDefault(m_programs, program);
+
+    if (!pData) return false;
+
+    pData->getExternalSamplerUniformIndices(outIndices);
+
+    return true;
+}
+
 bool GLSharedGroup::isShader(GLuint shader) {
 
     AutoLock<Lock> _lock(m_lock);
diff --git a/guest/OpenglCodecCommon/include/gfxstream/guest/GLSharedGroup.h b/guest/OpenglCodecCommon/include/gfxstream/guest/GLSharedGroup.h
old mode 100755
new mode 100644
index 86c4d62..9fc4065
--- a/guest/OpenglCodecCommon/include/gfxstream/guest/GLSharedGroup.h
+++ b/guest/OpenglCodecCommon/include/gfxstream/guest/GLSharedGroup.h
@@ -113,6 +113,7 @@
     GLuint getIndexForLocation(GLint location);
     GLenum getTypeForLocation(GLint location);
     bool isValidUniformLocation(GLint location);
+    void getExternalSamplerUniformIndices(std::vector<GLuint>* outIndices);
 
     GLint getNextSamplerUniform(GLint index, GLint* val, GLenum* target);
     bool setSamplerUniform(GLint appLoc, GLint val, GLenum* target);
@@ -210,7 +211,7 @@
 
     bool    isProgram(GLuint program);
     bool    isProgramInitialized(GLuint program);
-    void    addProgramData(GLuint program); 
+    void    addProgramData(GLuint program);
     void    initProgramData(GLuint program, GLuint numIndexes, GLuint numAttributes);
     void    refProgramData(GLuint program);
     void    onUseProgram(GLuint previous, GLuint next);
@@ -220,11 +221,13 @@
     void    deleteProgramData(GLuint program);
     void    deleteProgramDataLocked(GLuint program);
     void    setProgramIndexInfo(GLuint program, GLuint index, GLint base, GLint size, GLenum type, const char* name);
+    void    setProgramIndexFlag(GLuint program, GLuint index, GLuint flags);
     void    setProgramAttribInfo(GLuint program, GLuint index, GLint attribLoc, GLint size, GLenum type, const char* name);
     GLenum  getProgramUniformType(GLuint program, GLint location);
     GLint   getNextSamplerUniform(GLuint program, GLint index, GLint* val, GLenum* target);
     bool    setSamplerUniform(GLuint program, GLint appLoc, GLint val, GLenum* target);
     bool    isProgramUniformLocationValid(GLuint program, GLint location);
+    bool    getExternalSamplerUniformIndices(GLuint program, std::vector<GLuint>* outIndices);
 
     bool    isShader(GLuint shader);
     bool    addShaderData(GLuint shader, GLenum shaderType);
diff --git a/guest/OpenglSystemCommon/HostConnection.cpp b/guest/OpenglSystemCommon/HostConnection.cpp
index b56d913..2e3390d 100644
--- a/guest/OpenglSystemCommon/HostConnection.cpp
+++ b/guest/OpenglSystemCommon/HostConnection.cpp
@@ -25,8 +25,6 @@
 #endif
 #include "renderControl_types.h"
 
-#include "aemu/base/Process.h"
-
 #define DEBUG_HOSTCONNECTION 0
 
 #if DEBUG_HOSTCONNECTION
diff --git a/guest/OpenglSystemCommon/VirtioGpuPipeStream.cpp b/guest/OpenglSystemCommon/VirtioGpuPipeStream.cpp
index ce3495c..d628156 100644
--- a/guest/OpenglSystemCommon/VirtioGpuPipeStream.cpp
+++ b/guest/OpenglSystemCommon/VirtioGpuPipeStream.cpp
@@ -68,9 +68,11 @@
             return -1;
         }
 
-        m_resource =
-            m_device->createResource(kTransferBufferSize, 1, kTransferBufferSize,
-                                     VIRGL_FORMAT_R8_UNORM, PIPE_BUFFER, VIRGL_BIND_CUSTOM);
+        m_resource = m_device->createResource(/*width=*/kTransferBufferSize,
+                                              /*height=*/1,
+                                              /*stride=*/kTransferBufferSize,
+                                              /*size=*/kTransferBufferSize, VIRGL_FORMAT_R8_UNORM,
+                                              PIPE_BUFFER, VIRGL_BIND_CUSTOM);
         if (!m_resource) {
             ALOGE("Failed to create VirtioGpuPipeStream resource.");
             return -1;
diff --git a/guest/android-emu/aemu/base/Optional.h b/guest/android-emu/aemu/base/Optional.h
index b76f5a1..a8df357 100644
--- a/guest/android-emu/aemu/base/Optional.h
+++ b/guest/android-emu/aemu/base/Optional.h
@@ -20,6 +20,7 @@
 
 #include <cassert>
 #include <initializer_list>
+#include <new>
 #include <type_traits>
 #include <utility>
 
diff --git a/guest/android-emu/aemu/base/threads/AndroidWorkPool.cpp b/guest/android-emu/aemu/base/threads/AndroidWorkPool.cpp
index dafb6ea..0eba3d1 100644
--- a/guest/android-emu/aemu/base/threads/AndroidWorkPool.cpp
+++ b/guest/android-emu/aemu/base/threads/AndroidWorkPool.cpp
@@ -33,6 +33,9 @@
 namespace gfxstream {
 namespace guest {
 
+static constexpr const uint64_t kMicrosecondsPerSecond = 1000000;
+static constexpr const uint64_t kNanosecondsPerMicrosecond = 1000;
+
 class WaitGroup { // intrusive refcounted
 public:
 
@@ -104,24 +107,23 @@
         struct timespec deadlineNs;
         gettimeofday(&deadlineUs, 0);
 
-        auto prevDeadlineUs = deadlineUs.tv_usec;
+        deadlineUs.tv_sec += (relative / kMicrosecondsPerSecond);
+        deadlineUs.tv_usec += (relative % kMicrosecondsPerSecond);
 
-        deadlineUs.tv_usec += relative;
-
-        // Wrap around
-        if (prevDeadlineUs > deadlineUs.tv_usec) {
-            ++deadlineUs.tv_sec;
+        if (deadlineUs.tv_usec > kMicrosecondsPerSecond) {
+            deadlineUs.tv_sec += (deadlineUs.tv_usec / kMicrosecondsPerSecond);
+            deadlineUs.tv_usec = (deadlineUs.tv_usec % kMicrosecondsPerSecond);
         }
 
         deadlineNs.tv_sec = deadlineUs.tv_sec;
-        deadlineNs.tv_nsec = deadlineUs.tv_usec * 1000LL;
+        deadlineNs.tv_nsec = deadlineUs.tv_usec * kNanosecondsPerMicrosecond;
         return deadlineNs;
     }
 
     uint64_t currTimeUs() {
         struct timeval tv;
         gettimeofday(&tv, 0);
-        return (uint64_t)(tv.tv_sec * 1000000LL + tv.tv_usec);
+        return (uint64_t)(tv.tv_sec * kMicrosecondsPerSecond + tv.tv_usec);
     }
 
     bool conditionalTimeoutLocked(std::function<bool()> conditionFunc, WorkPool::TimeoutUs timeout) {
diff --git a/guest/android/GrallocEmulated.cpp b/guest/android/GrallocEmulated.cpp
index f96b717..34945a5 100644
--- a/guest/android/GrallocEmulated.cpp
+++ b/guest/android/GrallocEmulated.cpp
@@ -17,6 +17,7 @@
 #include <cutils/log.h>
 
 #include <optional>
+#include <unordered_map>
 
 #include "drm_fourcc.h"
 
@@ -28,6 +29,18 @@
 
 #define DRM_FORMAT_R8_BLOB fourcc_code('9', '9', '9', '9')
 
+template <typename T, typename N>
+T DivideRoundUp(T n, N divisor) {
+    const T div = static_cast<T>(divisor);
+    const T q = n / div;
+    return n % div == 0 ? q : q + 1;
+}
+
+template <typename T, typename N>
+T Align(T number, N n) {
+    return DivideRoundUp(number, n) * n;
+}
+
 std::optional<uint32_t> GlFormatToDrmFormat(uint32_t glFormat) {
     switch (glFormat) {
         case kGlRGB:
@@ -71,68 +84,204 @@
             return DRM_FORMAT_ABGR16161616F;
         case GFXSTREAM_AHB_FORMAT_R10G10B10A2_UNORM:
             return DRM_FORMAT_ABGR2101010;
+        case GFXSTREAM_AHB_FORMAT_Y8Cb8Cr8_420:
+            return DRM_FORMAT_NV12;
     }
     return std::nullopt;
 }
 
-std::optional<uint32_t> DrmToAhbFormat(uint32_t drmFormat) {
-    switch (drmFormat) {
-        case DRM_FORMAT_ABGR8888:
-            return GFXSTREAM_AHB_FORMAT_R8G8B8A8_UNORM;
-        case DRM_FORMAT_XBGR8888:
-            return GFXSTREAM_AHB_FORMAT_R8G8B8X8_UNORM;
-        case DRM_FORMAT_ARGB8888:
-            return GFXSTREAM_AHB_FORMAT_B8G8R8A8_UNORM;
-        case DRM_FORMAT_BGR888:
-            return GFXSTREAM_AHB_FORMAT_R8G8B8_UNORM;
-        case DRM_FORMAT_RGB565:
-            return GFXSTREAM_AHB_FORMAT_R5G6B5_UNORM;
-        case DRM_FORMAT_R8_BLOB:
-            return GFXSTREAM_AHB_FORMAT_BLOB;
-        case DRM_FORMAT_R8:
-            return GFXSTREAM_AHB_FORMAT_R8_UNORM;
-        case DRM_FORMAT_YVU420:
-            return GFXSTREAM_AHB_FORMAT_YV12;
-        case DRM_FORMAT_ABGR16161616F:
-            return GFXSTREAM_AHB_FORMAT_R16G16B16A16_FLOAT;
-        case DRM_FORMAT_ABGR2101010:
-            return GFXSTREAM_AHB_FORMAT_R10G10B10A2_UNORM;
-    }
-    return std::nullopt;
-}
-
-std::optional<uint32_t> DrmToBpp(uint32_t drmFormat) {
-    switch (drmFormat) {
-        case DRM_FORMAT_ABGR8888:
-        case DRM_FORMAT_ARGB8888:
-        case DRM_FORMAT_XBGR8888:
-            return 4;
-        case DRM_FORMAT_BGR888:
-            return 3;
-        case DRM_FORMAT_RGB565:
-            return 2;
-        case DRM_FORMAT_R8_BLOB:
-        case DRM_FORMAT_R8:
-            return 1;
-    }
-    return std::nullopt;
-}
-
-std::optional<uint32_t> DrmToVirglFormat(uint32_t drmFormat) {
-    switch (drmFormat) {
-        case DRM_FORMAT_ABGR8888:
-            return VIRGL_FORMAT_R8G8B8A8_UNORM;
-        case DRM_FORMAT_ARGB8888:
-            return VIRGL_FORMAT_B8G8R8A8_UNORM;
-        case DRM_FORMAT_BGR888:
-            return VIRGL_FORMAT_R8G8B8_UNORM;
-        case DRM_FORMAT_BGR565:
-            return VIRGL_FORMAT_B5G6R5_UNORM;
-        case DRM_FORMAT_R8:
-        case DRM_FORMAT_R8_BLOB:
-            return VIRGL_FORMAT_R8_UNORM;
-    }
-    return std::nullopt;
+struct DrmFormatPlaneInfo {
+    uint32_t horizontalSubsampling;
+    uint32_t verticalSubsampling;
+    uint32_t bytesPerPixel;
+};
+struct DrmFormatInfo {
+    uint32_t androidFormat;
+    uint32_t virglFormat;
+    bool isYuv;
+    uint32_t horizontalAlignmentPixels;
+    uint32_t verticalAlignmentPixels;
+    std::vector<DrmFormatPlaneInfo> planes;
+};
+const std::unordered_map<uint32_t, DrmFormatInfo>& GetDrmFormatInfoMap() {
+    static const auto* kFormatInfoMap = new std::unordered_map<uint32_t, DrmFormatInfo>({
+        {DRM_FORMAT_ABGR8888,
+         {
+             .androidFormat = GFXSTREAM_AHB_FORMAT_R8G8B8A8_UNORM,
+             .virglFormat = VIRGL_FORMAT_R8G8B8A8_UNORM,
+             .isYuv = false,
+             .horizontalAlignmentPixels = 1,
+             .verticalAlignmentPixels = 1,
+             .planes =
+                 {
+                     {
+                         .horizontalSubsampling = 1,
+                         .verticalSubsampling = 1,
+                         .bytesPerPixel = 4,
+                     },
+                 },
+         }},
+        {DRM_FORMAT_ARGB8888,
+         {
+             .androidFormat = GFXSTREAM_AHB_FORMAT_B8G8R8A8_UNORM,
+             .virglFormat = VIRGL_FORMAT_B8G8R8A8_UNORM,
+             .isYuv = false,
+             .horizontalAlignmentPixels = 1,
+             .verticalAlignmentPixels = 1,
+             .planes =
+                 {
+                     {
+                         .horizontalSubsampling = 1,
+                         .verticalSubsampling = 1,
+                         .bytesPerPixel = 4,
+                     },
+                 },
+         }},
+        {DRM_FORMAT_BGR888,
+         {
+             .androidFormat = GFXSTREAM_AHB_FORMAT_R8G8B8_UNORM,
+             .virglFormat = VIRGL_FORMAT_R8G8B8_UNORM,
+             .isYuv = false,
+             .horizontalAlignmentPixels = 1,
+             .verticalAlignmentPixels = 1,
+             .planes =
+                 {
+                     {
+                         .horizontalSubsampling = 1,
+                         .verticalSubsampling = 1,
+                         .bytesPerPixel = 3,
+                     },
+                 },
+         }},
+        {DRM_FORMAT_BGR565,
+         {
+             .androidFormat = GFXSTREAM_AHB_FORMAT_R5G6B5_UNORM,
+             .virglFormat = VIRGL_FORMAT_B5G6R5_UNORM,
+             .isYuv = false,
+             .horizontalAlignmentPixels = 1,
+             .verticalAlignmentPixels = 1,
+             .planes =
+                 {
+                     {
+                         .horizontalSubsampling = 1,
+                         .verticalSubsampling = 1,
+                         .bytesPerPixel = 2,
+                     },
+                 },
+         }},
+        {DRM_FORMAT_R8,
+         {
+             .androidFormat = GFXSTREAM_AHB_FORMAT_R8_UNORM,
+             .virglFormat = VIRGL_FORMAT_R8_UNORM,
+             .isYuv = false,
+             .horizontalAlignmentPixels = 1,
+             .verticalAlignmentPixels = 1,
+             .planes =
+                 {
+                     {
+                         .horizontalSubsampling = 1,
+                         .verticalSubsampling = 1,
+                         .bytesPerPixel = 1,
+                     },
+                 },
+         }},
+        {DRM_FORMAT_R8_BLOB,
+         {
+             .androidFormat = GFXSTREAM_AHB_FORMAT_BLOB,
+             .virglFormat = VIRGL_FORMAT_R8_UNORM,
+             .isYuv = false,
+             .horizontalAlignmentPixels = 1,
+             .verticalAlignmentPixels = 1,
+             .planes =
+                 {
+                     {
+                         .horizontalSubsampling = 1,
+                         .verticalSubsampling = 1,
+                         .bytesPerPixel = 1,
+                     },
+                 },
+         }},
+        {DRM_FORMAT_ABGR16161616F,
+         {
+             .androidFormat = GFXSTREAM_AHB_FORMAT_R16G16B16A16_FLOAT,
+             .virglFormat = VIRGL_FORMAT_R16G16B16A16_FLOAT,
+             .isYuv = false,
+             .horizontalAlignmentPixels = 1,
+             .verticalAlignmentPixels = 1,
+             .planes =
+                 {
+                     {
+                         .horizontalSubsampling = 1,
+                         .verticalSubsampling = 1,
+                         .bytesPerPixel = 8,
+                     },
+                 },
+         }},
+        {DRM_FORMAT_ABGR2101010,
+         {
+             .androidFormat = GFXSTREAM_AHB_FORMAT_R10G10B10A2_UNORM,
+             .virglFormat = VIRGL_FORMAT_R10G10B10A2_UNORM,
+             .isYuv = false,
+             .horizontalAlignmentPixels = 1,
+             .verticalAlignmentPixels = 1,
+             .planes =
+                 {
+                     {
+                         .horizontalSubsampling = 1,
+                         .verticalSubsampling = 1,
+                         .bytesPerPixel = 4,
+                     },
+                 },
+         }},
+        {DRM_FORMAT_NV12,
+         {
+             .androidFormat = GFXSTREAM_AHB_FORMAT_Y8Cb8Cr8_420,
+             .virglFormat = VIRGL_FORMAT_NV12,
+             .isYuv = true,
+             .horizontalAlignmentPixels = 2,
+             .verticalAlignmentPixels = 1,
+             .planes =
+                 {
+                     {
+                         .horizontalSubsampling = 1,
+                         .verticalSubsampling = 1,
+                         .bytesPerPixel = 1,
+                     },
+                     {
+                         .horizontalSubsampling = 2,
+                         .verticalSubsampling = 2,
+                         .bytesPerPixel = 2,
+                     },
+                 },
+         }},
+        {DRM_FORMAT_YVU420,
+         {
+             .androidFormat = GFXSTREAM_AHB_FORMAT_YV12,
+             .virglFormat = VIRGL_FORMAT_YV12,
+             .isYuv = true,
+             .horizontalAlignmentPixels = 32,
+             .verticalAlignmentPixels = 1,
+             .planes =
+                 {
+                     {
+                         .horizontalSubsampling = 1,
+                         .verticalSubsampling = 1,
+                         .bytesPerPixel = 1,
+                     },
+                     {
+                         .horizontalSubsampling = 2,
+                         .verticalSubsampling = 2,
+                         .bytesPerPixel = 1,
+                     },
+                     {
+                         .horizontalSubsampling = 2,
+                         .verticalSubsampling = 2,
+                         .bytesPerPixel = 1,
+                     },
+                 },
+         }},
+    });
+    return *kFormatInfoMap;
 }
 
 }  // namespace
@@ -150,12 +299,14 @@
 uint32_t EmulatedAHardwareBuffer::getHeight() const { return mHeight; }
 
 int EmulatedAHardwareBuffer::getAndroidFormat() const {
-    auto ahbFormat = DrmToAhbFormat(mDrmFormat);
-    if (!ahbFormat) {
+    const auto& formatInfosMap = GetDrmFormatInfoMap();
+    auto formatInfoIt = formatInfosMap.find(mDrmFormat);
+    if (formatInfoIt == formatInfosMap.end()) {
         ALOGE("Unhandled DRM format:%u", mDrmFormat);
         return -1;
     }
-    return *ahbFormat;
+    const auto& formatInfo = formatInfoIt->second;
+    return formatInfo.androidFormat;
 }
 
 uint32_t EmulatedAHardwareBuffer::getDrmFormat() const { return mDrmFormat; }
@@ -197,6 +348,54 @@
     return 0;
 }
 
+int EmulatedAHardwareBuffer::lockPlanes(std::vector<Gralloc::LockedPlane>* ahbPlanes) {
+    uint8_t* data = 0;
+    int ret = lock(&data);
+    if (ret) {
+        return ret;
+    }
+
+    const auto& formatInfosMap = GetDrmFormatInfoMap();
+    auto formatInfoIt = formatInfosMap.find(mDrmFormat);
+    if (formatInfoIt == formatInfosMap.end()) {
+        ALOGE("Failed to lock: failed to find format info for drm format:%u", mDrmFormat);
+        return -1;
+    }
+    const auto& formatInfo = formatInfoIt->second;
+
+    const uint32_t alignedWidth = Align(mWidth, formatInfo.horizontalAlignmentPixels);
+    const uint32_t alignedHeight = Align(mHeight, formatInfo.verticalAlignmentPixels);
+    uint32_t cumulativeSize = 0;
+    for (const DrmFormatPlaneInfo& planeInfo : formatInfo.planes) {
+        const uint32_t planeWidth = DivideRoundUp(alignedWidth, planeInfo.horizontalSubsampling);
+        const uint32_t planeHeight = DivideRoundUp(alignedHeight, planeInfo.verticalSubsampling);
+        const uint32_t planeBpp = planeInfo.bytesPerPixel;
+        const uint32_t planeStrideBytes = planeWidth * planeBpp;
+        const uint32_t planeSizeBytes = planeHeight * planeStrideBytes;
+        ahbPlanes->emplace_back(Gralloc::LockedPlane{
+            .data = data + cumulativeSize,
+            .pixelStrideBytes = planeBpp,
+            .rowStrideBytes = planeStrideBytes,
+        });
+        cumulativeSize += planeSizeBytes;
+    }
+
+    if (mDrmFormat == DRM_FORMAT_NV12) {
+        const auto& uPlane = (*ahbPlanes)[1];
+        auto vPlane = uPlane;
+        vPlane.data += 1;
+
+        ahbPlanes->push_back(vPlane);
+    } else if (mDrmFormat == DRM_FORMAT_YVU420) {
+        // Note: lockPlanes() always returns Y, then U, then V but YV12 is Y, then V, then U.
+        auto& plane1 = (*ahbPlanes)[1];
+        auto& plane2 = (*ahbPlanes)[2];
+        std::swap(plane1, plane2);
+    }
+
+    return 0;
+}
+
 int EmulatedAHardwareBuffer::unlock() {
     if (!mMapped) {
         ALOGE("Failed to unlock EmulatedAHardwareBuffer: never locked?");
@@ -214,9 +413,13 @@
     auto drmFormat = GlFormatToDrmFormat(glFormat);
     if (!drmFormat) {
         ALOGE("Unhandled format");
+        return -1;
     }
 
     auto ahb = allocate(width, height, *drmFormat);
+    if (ahb == nullptr) {
+        return -1;
+    }
 
     EmulatedAHardwareBuffer* rahb = reinterpret_cast<EmulatedAHardwareBuffer*>(ahb);
 
@@ -252,24 +455,36 @@
         return nullptr;
     }
 
-    auto virglFormat = DrmToVirglFormat(drmFormat);
-    if (!virglFormat) {
-        ALOGE("Failed to allocate: Unhandled DRM format:%u to Virgl format conversion.", drmFormat);
+    const auto& formatInfosMap = GetDrmFormatInfoMap();
+    auto formatInfoIt = formatInfosMap.find(drmFormat);
+    if (formatInfoIt == formatInfosMap.end()) {
+        ALOGE("Failed to allocate: failed to find format info for drm format:%u", drmFormat);
         return nullptr;
     }
+    const auto& formatInfo = formatInfoIt->second;
 
-    auto bpp = DrmToBpp(drmFormat);
-    if (!virglFormat) {
-        ALOGE("Failed to allocate: Unhandled DRM format:%u to bpp conversion.", drmFormat);
-        return nullptr;
+    const uint32_t alignedWidth = Align(width, formatInfo.horizontalAlignmentPixels);
+    const uint32_t alignedHeight = Align(height, formatInfo.verticalAlignmentPixels);
+    uint32_t stride = 0;
+    uint32_t size = 0;
+    for (uint32_t i = 0; i < formatInfo.planes.size(); i++) {
+        const DrmFormatPlaneInfo& planeInfo = formatInfo.planes[i];
+        const uint32_t planeWidth = DivideRoundUp(alignedWidth, planeInfo.horizontalSubsampling);
+        const uint32_t planeHeight = DivideRoundUp(alignedHeight, planeInfo.verticalSubsampling);
+        const uint32_t planeBpp = planeInfo.bytesPerPixel;
+        const uint32_t planeStrideBytes = planeWidth * planeBpp;
+        const uint32_t planeSizeBytes = planeHeight * planeStrideBytes;
+        size += planeSizeBytes;
+        if (i == 0) stride = planeStrideBytes;
     }
 
-    const uint32_t bind =
-        (drmFormat == DRM_FORMAT_R8_BLOB) ? VIRGL_BIND_LINEAR : VIRGL_BIND_RENDER_TARGET;
-    const uint32_t stride = width * (*bpp);
+    const uint32_t bind = (drmFormat == DRM_FORMAT_R8_BLOB || drmFormat == DRM_FORMAT_NV12 ||
+                           drmFormat == DRM_FORMAT_YVU420)
+                              ? VIRGL_BIND_LINEAR
+                              : VIRGL_BIND_RENDER_TARGET;
 
-    auto resource =
-        device->createResource(width, height, stride, *virglFormat, PIPE_TEXTURE_2D, bind);
+    auto resource = device->createResource(width, height, stride, size, formatInfo.virglFormat,
+                                           PIPE_TEXTURE_2D, bind);
     if (!resource) {
         ALOGE("Failed to allocate: failed to create virtio resource.");
         return nullptr;
@@ -296,6 +511,11 @@
     return rahb->lock(ptr);
 }
 
+int EmulatedGralloc::lockPlanes(AHardwareBuffer* ahb, std::vector<LockedPlane>* ahbPlanes) {
+    auto* rahb = reinterpret_cast<EmulatedAHardwareBuffer*>(ahb);
+    return rahb->lockPlanes(ahbPlanes);
+}
+
 int EmulatedGralloc::unlock(AHardwareBuffer* ahb) {
     auto* rahb = reinterpret_cast<EmulatedAHardwareBuffer*>(ahb);
     return rahb->unlock();
diff --git a/guest/android/GrallocEmulated.h b/guest/android/GrallocEmulated.h
index 1412ca3..c5d8985 100644
--- a/guest/android/GrallocEmulated.h
+++ b/guest/android/GrallocEmulated.h
@@ -51,6 +51,7 @@
     void release();
 
     int lock(uint8_t** ptr);
+    int lockPlanes(std::vector<Gralloc::LockedPlane>* ahbPlanes);
     int unlock();
 
    private:
@@ -77,6 +78,7 @@
     void release(AHardwareBuffer* ahb) override;
 
     int lock(AHardwareBuffer* ahb, uint8_t** ptr) override;
+    int lockPlanes(AHardwareBuffer* ahb, std::vector<LockedPlane>* ahbPlanes) override;
     int unlock(AHardwareBuffer* ahb) override;
 
     uint32_t getHostHandle(const native_handle_t* handle) override;
diff --git a/guest/android/GrallocGoldfish.cpp b/guest/android/GrallocGoldfish.cpp
index 113cb6d..6962ab4 100644
--- a/guest/android/GrallocGoldfish.cpp
+++ b/guest/android/GrallocGoldfish.cpp
@@ -48,6 +48,10 @@
                                 reinterpret_cast<void**>(ptr));
 }
 
+int GoldfishGralloc::lockPlanes(AHardwareBuffer* ahb, std::vector<LockedPlane>* ahbPlanes) {
+    return -1;
+}
+
 int GoldfishGralloc::unlock(AHardwareBuffer* ahb) { return AHardwareBuffer_unlock(ahb, nullptr); }
 
 uint32_t GoldfishGralloc::getHostHandle(native_handle_t const* handle) {
diff --git a/guest/android/GrallocGoldfish.h b/guest/android/GrallocGoldfish.h
index 183c110..2c83afc 100644
--- a/guest/android/GrallocGoldfish.h
+++ b/guest/android/GrallocGoldfish.h
@@ -29,6 +29,7 @@
     void release(AHardwareBuffer* ahb) override;
 
     int lock(AHardwareBuffer* ahb, uint8_t** ptr) override;
+    int lockPlanes(AHardwareBuffer* ahb, std::vector<LockedPlane>* ahbPlanes) override;
     int unlock(AHardwareBuffer* ahb) override;
 
     uint32_t getHostHandle(native_handle_t const* handle) override;
diff --git a/guest/android/GrallocMinigbm.cpp b/guest/android/GrallocMinigbm.cpp
index 8d97be6..be62a2b 100644
--- a/guest/android/GrallocMinigbm.cpp
+++ b/guest/android/GrallocMinigbm.cpp
@@ -181,12 +181,17 @@
                                 reinterpret_cast<void**>(ptr));
 }
 
+int MinigbmGralloc::lockPlanes(AHardwareBuffer* ahb, std::vector<LockedPlane>* ahbPlanes) {
+    ALOGE("%s: unimplemented", __func__);
+    return -1;
+}
+
 int MinigbmGralloc::unlock(AHardwareBuffer* ahb) { return AHardwareBuffer_unlock(ahb, nullptr); }
 
 uint32_t MinigbmGralloc::getHostHandle(const native_handle_t* handle) {
     struct drm_virtgpu_resource_info info;
     if (!getVirtioGpuResourceInfo(m_fd, handle, &info)) {
-        ALOGE("%s: failed to get resource info\n", __func__);
+        ALOGE("%s: failed to get resource info", __func__);
         return 0;
     }
 
diff --git a/guest/android/GrallocMinigbm.h b/guest/android/GrallocMinigbm.h
index 8a70bca..2542d0d 100644
--- a/guest/android/GrallocMinigbm.h
+++ b/guest/android/GrallocMinigbm.h
@@ -29,6 +29,7 @@
     void release(AHardwareBuffer* ahb) override;
 
     int lock(AHardwareBuffer* ahb, uint8_t** ptr) override;
+    int lockPlanes(AHardwareBuffer* ahb, std::vector<LockedPlane>* ahbPlanes) override;
     int unlock(AHardwareBuffer* ahb) override;
 
     uint32_t getHostHandle(native_handle_t const* handle) override;
diff --git a/guest/android/include/gfxstream/guest/Gralloc.h b/guest/android/include/gfxstream/guest/Gralloc.h
index 7d037cb..577c22e 100644
--- a/guest/android/include/gfxstream/guest/Gralloc.h
+++ b/guest/android/include/gfxstream/guest/Gralloc.h
@@ -20,6 +20,8 @@
 #include <stddef.h>
 #include <stdint.h>
 
+#include <vector>
+
 typedef struct AHardwareBuffer AHardwareBuffer;
 
 namespace gfxstream {
@@ -67,6 +69,13 @@
                          AHardwareBuffer** outputAhb) = 0;
 
     virtual int lock(AHardwareBuffer* ahb, uint8_t** ptr) = 0;
+    struct LockedPlane {
+        uint8_t* data = nullptr;
+        uint32_t pixelStrideBytes = 0;
+        uint32_t rowStrideBytes = 0;
+    };
+    // If AHB is a YUV format, always returns Y, then U, then V.
+    virtual int lockPlanes(AHardwareBuffer* ahb, std::vector<LockedPlane>* ahbPlanes) = 0;
     virtual int unlock(AHardwareBuffer* ahb) = 0;
 
     virtual const native_handle_t* getNativeHandle(const AHardwareBuffer* ahb) = 0;
diff --git a/guest/mesa/meson.build b/guest/mesa/meson.build
index dfa1054..a68e18d 100644
--- a/guest/mesa/meson.build
+++ b/guest/mesa/meson.build
@@ -868,9 +868,12 @@
 has_mako = run_command(
   prog_python, '-c',
   '''
-from distutils.version import StrictVersion
+try:
+  from packaging.version import Version
+except:
+  from distutils.version import StrictVersion as Version
 import mako
-assert StrictVersion(mako.__version__) >= StrictVersion("0.8.0")
+assert Version(mako.__version__) >= Version("0.8.0")
   ''', check: false)
 if has_mako.returncode() != 0
   error('Python (3.x) mako module >= 0.8.0 required to build mesa.')
diff --git a/guest/mesa/src/vulkan/wsi/wsi_common_drm.c b/guest/mesa/src/vulkan/wsi/wsi_common_drm.c
index b53d485..f04a791 100644
--- a/guest/mesa/src/vulkan/wsi/wsi_common_drm.c
+++ b/guest/mesa/src/vulkan/wsi/wsi_common_drm.c
@@ -323,7 +323,8 @@
    if (result != VK_SUCCESS)
       return result;
 
-   if (num_modifier_lists == 0) {
+   /* HACK: This should be fixed as part of (b:326956485) */
+   if (true) {
       /* If we don't have modifiers, fall back to the legacy "scanout" flag */
       info->wsi.scanout = true;
    } else {
diff --git a/guest/platform/fuchsia/FuchsiaVirtGpu.h b/guest/platform/fuchsia/FuchsiaVirtGpu.h
index 48e6dfa..edd86c3 100644
--- a/guest/platform/fuchsia/FuchsiaVirtGpu.h
+++ b/guest/platform/fuchsia/FuchsiaVirtGpu.h
@@ -57,7 +57,8 @@
 
     VirtGpuResourcePtr createBlob(const struct VirtGpuCreateBlob& blobCreate) override;
     VirtGpuResourcePtr createResource(uint32_t width, uint32_t height, uint32_t stride,
-                                      uint32_t format, uint32_t target, uint32_t bind) override;
+                                      uint32_t size, uint32_t virglFormat, uint32_t target,
+                                      uint32_t bind) override;
     VirtGpuResourcePtr importBlob(const struct VirtGpuExternalHandle& handle) override;
 
     int execBuffer(struct VirtGpuExecBuffer& execbuffer, const VirtGpuResource* blob) override;
diff --git a/guest/platform/fuchsia/FuchsiaVirtGpuDevice.cpp b/guest/platform/fuchsia/FuchsiaVirtGpuDevice.cpp
index 3d8c081..7868ec6 100644
--- a/guest/platform/fuchsia/FuchsiaVirtGpuDevice.cpp
+++ b/guest/platform/fuchsia/FuchsiaVirtGpuDevice.cpp
@@ -75,8 +75,9 @@
 }
 
 VirtGpuResourcePtr FuchsiaVirtGpuDevice::createResource(uint32_t width, uint32_t height,
-                                                        uint32_t stride, uint32_t virglFormat,
-                                                        uint32_t target, uint32_t bind) {
+                                                        uint32_t stride, uint32_t size,
+                                                        uint32_t virglFormat, uint32_t target,
+                                                        uint32_t bind) {
     ALOGE("%s: unimplemented", __func__);
     return nullptr;
 }
diff --git a/guest/platform/include/VirtGpu.h b/guest/platform/include/VirtGpu.h
index c0bfa3b..b9afbdf 100644
--- a/guest/platform/include/VirtGpu.h
+++ b/guest/platform/include/VirtGpu.h
@@ -22,11 +22,18 @@
 #include "virtgpu_gfxstream_protocol.h"
 
 // See virgl_hw.h and p_defines.h
-#define VIRGL_FORMAT_R8_UNORM 64
 #define VIRGL_FORMAT_B8G8R8A8_UNORM 1
 #define VIRGL_FORMAT_B5G6R5_UNORM 7
+#define VIRGL_FORMAT_R10G10B10A2_UNORM 8
+#define VIRGL_FORMAT_R8_UNORM 64
 #define VIRGL_FORMAT_R8G8B8_UNORM 66
 #define VIRGL_FORMAT_R8G8B8A8_UNORM 67
+#define VIRGL_FORMAT_R16G16B16A16_FLOAT 94
+#define VIRGL_FORMAT_YV12 163
+#define VIRGL_FORMAT_YV16 164
+#define VIRGL_FORMAT_IYUV 165
+#define VIRGL_FORMAT_NV12 166
+#define VIRGL_FORMAT_NV21 167
 
 #define VIRGL_BIND_RENDER_TARGET (1 << 1)
 #define VIRGL_BIND_CUSTOM (1 << 17)
@@ -44,14 +51,18 @@
     kParamContextInit = 5,
     kParamSupportedCapsetIds = 6,
     kParamExplicitDebugName = 7,
-    kParamCreateGuestHandle = 8,
-    kParamMax = 9,
+    // Experimental, not in upstream Linux
+    kParamFencePassing = 8,
+    kParamCreateGuestHandle = 9,
+    kParamMax = 10,
 };
 
 enum VirtGpuExecBufferFlags : uint32_t {
     kFenceIn = 0x0001,
     kFenceOut = 0x0002,
     kRingIdx = 0x0004,
+    kShareableIn = 0x0008,
+    kShareableOut = 0x0010,
 };
 
 enum VirtGpuCapset {
@@ -182,7 +193,7 @@
 
     virtual VirtGpuResourcePtr createBlob(const struct VirtGpuCreateBlob& blobCreate) = 0;
     virtual VirtGpuResourcePtr createResource(uint32_t width, uint32_t height, uint32_t stride,
-                                              uint32_t virglFormat, uint32_t target,
+                                              uint32_t size, uint32_t virglFormat, uint32_t target,
                                               uint32_t bind) = 0;
     virtual VirtGpuResourcePtr importBlob(const struct VirtGpuExternalHandle& handle) = 0;
 
diff --git a/guest/platform/include/virtgpu_drm.h b/guest/platform/include/virtgpu_drm.h
index 965b675..2d5ca8f 100644
--- a/guest/platform/include/virtgpu_drm.h
+++ b/guest/platform/include/virtgpu_drm.h
@@ -83,7 +83,6 @@
 #define VIRTGPU_PARAM_CONTEXT_INIT 6 /* DRM_VIRTGPU_CONTEXT_INIT */
 #define VIRTGPU_PARAM_SUPPORTED_CAPSET_IDs 7 /* Bitmask of supported capability set ids */
 #define VIRTGPU_PARAM_EXPLICIT_DEBUG_NAME 8 /* Ability to set debug name from userspace */
-#define VIRTGPU_PARAM_CREATE_GUEST_HANDLE 9  /* Host OS handle can be created from guest memory. */
 
 struct drm_virtgpu_getparam {
 	__u64 param;
diff --git a/guest/platform/include/virtgpu_gfxstream_protocol.h b/guest/platform/include/virtgpu_gfxstream_protocol.h
index 2edc2f3..c618ddc 100644
--- a/guest/platform/include/virtgpu_gfxstream_protocol.h
+++ b/guest/platform/include/virtgpu_gfxstream_protocol.h
@@ -42,6 +42,7 @@
 #define GFXSTREAM_CREATE_IMPORT_SYNC_VK         0xa001
 #define GFXSTREAM_CREATE_QSRI_EXPORT_VK         0xa002
 #define GFXSTREAM_RESOURCE_CREATE_3D            0xa003
+#define GFXSTREAM_ACQUIRE_SYNC                  0xa004
 
 // clang-format off
 // A placeholder command to ensure virtio-gpu completes
@@ -104,6 +105,12 @@
     uint64_t blobId;
 };
 
+struct gfxstreamAcquireSync {
+    struct gfxstreamHeader hdr;
+    uint32_t padding;
+    uint64_t syncId;
+};
+
 struct vulkanCapset {
     uint32_t protocolVersion;
 
@@ -116,7 +123,8 @@
     uint32_t blobAlignment;
     uint32_t noRenderControlEnc;
     uint32_t alwaysBlob;
-    uint32_t padding[13];
+    uint32_t externalSync;
+    uint32_t padding[12];
 };
 
 struct magmaCapset {
diff --git a/guest/platform/kumquat/VirtGpuKumquat.h b/guest/platform/kumquat/VirtGpuKumquat.h
index 624dece..d940ffd 100644
--- a/guest/platform/kumquat/VirtGpuKumquat.h
+++ b/guest/platform/kumquat/VirtGpuKumquat.h
@@ -40,7 +40,6 @@
     // Not owned.  Really should use a ScopedFD for this, but doesn't matter since we have a
     // singleton deviceimplemenentation anyways.
     struct virtgpu_kumquat* mVirtGpu = nullptr;
-    ;
 
     uint32_t mBlobHandle;
     uint32_t mResourceHandle;
@@ -49,13 +48,15 @@
 
 class VirtGpuKumquatResourceMapping : public VirtGpuResourceMapping {
    public:
-    VirtGpuKumquatResourceMapping(VirtGpuResourcePtr blob, uint8_t* ptr, uint64_t size);
+    VirtGpuKumquatResourceMapping(VirtGpuResourcePtr blob, struct virtgpu_kumquat* virtGpu,
+                                  uint8_t* ptr, uint64_t size);
     ~VirtGpuKumquatResourceMapping(void);
 
     uint8_t* asRawPtr(void) override;
 
    private:
     VirtGpuResourcePtr mBlob;
+    struct virtgpu_kumquat* mVirtGpu = nullptr;
     uint8_t* mPtr;
     uint64_t mSize;
 };
@@ -70,14 +71,14 @@
     virtual struct VirtGpuCaps getCaps(void);
 
     VirtGpuResourcePtr createBlob(const struct VirtGpuCreateBlob& blobCreate) override;
-    VirtGpuResourcePtr createResource(uint32_t width, uint32_t height, uint32_t virglFormat,
-                                      uint32_t target, uint32_t bind, uint32_t bpp) override;
+    VirtGpuResourcePtr createResource(uint32_t width, uint32_t height, uint32_t stride,
+                                      uint32_t size, uint32_t virglFormat, uint32_t target,
+                                      uint32_t bind) override;
 
     virtual VirtGpuResourcePtr importBlob(const struct VirtGpuExternalHandle& handle);
     virtual int execBuffer(struct VirtGpuExecBuffer& execbuffer, const VirtGpuResource* blob);
 
    private:
     struct virtgpu_kumquat* mVirtGpu = nullptr;
-    ;
     struct VirtGpuCaps mCaps;
 };
diff --git a/guest/platform/kumquat/VirtGpuKumquatBlob.cpp b/guest/platform/kumquat/VirtGpuKumquatBlob.cpp
index 1a9c99e..cd0e3e0 100644
--- a/guest/platform/kumquat/VirtGpuKumquatBlob.cpp
+++ b/guest/platform/kumquat/VirtGpuKumquatBlob.cpp
@@ -57,8 +57,8 @@
         return nullptr;
     }
 
-    return std::make_shared<VirtGpuKumquatResourceMapping>(shared_from_this(), (uint8_t*)map.ptr,
-                                                           mSize);
+    return std::make_shared<VirtGpuKumquatResourceMapping>(shared_from_this(), mVirtGpu,
+                                                           (uint8_t*)map.ptr, mSize);
 }
 
 int VirtGpuKumquatResource::exportBlob(struct VirtGpuExternalHandle& handle) {
diff --git a/guest/platform/kumquat/VirtGpuKumquatBlobMapping.cpp b/guest/platform/kumquat/VirtGpuKumquatBlobMapping.cpp
index e4869db..c932e93 100644
--- a/guest/platform/kumquat/VirtGpuKumquatBlobMapping.cpp
+++ b/guest/platform/kumquat/VirtGpuKumquatBlobMapping.cpp
@@ -15,11 +15,18 @@
  */
 
 #include "VirtGpuKumquat.h"
+#include "cutils/log.h"
 
-VirtGpuKumquatResourceMapping::VirtGpuKumquatResourceMapping(VirtGpuResourcePtr blob, uint8_t* ptr,
-                                                             uint64_t size)
-    : mBlob(blob), mPtr(ptr), mSize(size) {}
+VirtGpuKumquatResourceMapping::VirtGpuKumquatResourceMapping(VirtGpuResourcePtr blob,
+                                                             struct virtgpu_kumquat* virtGpu,
+                                                             uint8_t* ptr, uint64_t size)
+    : mBlob(blob), mVirtGpu(virtGpu), mPtr(ptr), mSize(size) {}
 
-VirtGpuKumquatResourceMapping::~VirtGpuKumquatResourceMapping(void) { return; }
+VirtGpuKumquatResourceMapping::~VirtGpuKumquatResourceMapping(void) {
+    int32_t ret = virtgpu_kumquat_resource_unmap(mVirtGpu, mBlob->getBlobHandle());
+    if (ret) {
+        ALOGE("failed to unmap buffer");
+    }
+}
 
 uint8_t* VirtGpuKumquatResourceMapping::asRawPtr(void) { return mPtr; }
diff --git a/guest/platform/kumquat/VirtGpuKumquatDevice.cpp b/guest/platform/kumquat/VirtGpuKumquatDevice.cpp
index 7de219f..6101cc1 100644
--- a/guest/platform/kumquat/VirtGpuKumquatDevice.cpp
+++ b/guest/platform/kumquat/VirtGpuKumquatDevice.cpp
@@ -44,6 +44,7 @@
         PARAM(VIRTGPU_KUMQUAT_PARAM_CONTEXT_INIT),
         PARAM(VIRTGPU_KUMQUAT_PARAM_SUPPORTED_CAPSET_IDs),
         PARAM(VIRTGPU_KUMQUAT_PARAM_EXPLICIT_DEBUG_NAME),
+        PARAM(VIRTGPU_KUMQUAT_PARAM_FENCE_PASSING),
         PARAM(VIRTGPU_KUMQUAT_PARAM_CREATE_GUEST_HANDLE),
     };
 
@@ -68,7 +69,6 @@
     for (uint32_t i = 0; i < kParamMax; i++) {
         struct drm_kumquat_getparam get_param = {0};
         get_param.param = params[i].param;
-        get_param.value = (uint64_t)(uintptr_t)&params[i].value;
 
         ret = virtgpu_kumquat_get_param(mVirtGpu, &get_param);
         if (ret) {
@@ -76,7 +76,7 @@
             continue;
         }
 
-        mCaps.params[i] = params[i].value;
+        mCaps.params[i] = get_param.value;
     }
 
     get_caps.cap_set_id = static_cast<uint32_t>(capset);
@@ -145,8 +145,9 @@
 int64_t VirtGpuKumquatDevice::getDeviceHandle(void) { return -1; }
 
 VirtGpuResourcePtr VirtGpuKumquatDevice::createResource(uint32_t width, uint32_t height,
+                                                        uint32_t stride, uint32_t size,
                                                         uint32_t virglFormat, uint32_t target,
-                                                        uint32_t bind, uint32_t bpp) {
+                                                        uint32_t bind) {
     struct drm_kumquat_resource_create_3d create = {
         .target = target,
         .format = virglFormat,
@@ -157,8 +158,8 @@
         .array_size = 1U,
         .last_level = 0,
         .nr_samples = 0,
-        .size = width * height * bpp,
-        .stride = width * bpp,
+        .size = size,
+        .stride = stride,
     };
 
     int ret = virtgpu_kumquat_resource_create_3d(mVirtGpu, &create);
@@ -207,7 +208,6 @@
 
     return std::make_shared<VirtGpuKumquatResource>(
         mVirtGpu, resource_import.bo_handle, resource_import.res_handle, resource_import.size);
-    return nullptr;
 }
 
 int VirtGpuKumquatDevice::execBuffer(struct VirtGpuExecBuffer& execbuffer,
diff --git a/guest/platform/linux/LinuxVirtGpu.h b/guest/platform/linux/LinuxVirtGpu.h
index 28357f0..c1442a8 100644
--- a/guest/platform/linux/LinuxVirtGpu.h
+++ b/guest/platform/linux/LinuxVirtGpu.h
@@ -69,7 +69,7 @@
 
     VirtGpuResourcePtr createBlob(const struct VirtGpuCreateBlob& blobCreate) override;
     VirtGpuResourcePtr createResource(uint32_t width, uint32_t height, uint32_t stride,
-                                      uint32_t virglFormat, uint32_t target,
+                                      uint32_t size, uint32_t virglFormat, uint32_t target,
                                       uint32_t bind) override;
 
     virtual VirtGpuResourcePtr importBlob(const struct VirtGpuExternalHandle& handle);
diff --git a/guest/platform/linux/LinuxVirtGpuDevice.cpp b/guest/platform/linux/LinuxVirtGpuDevice.cpp
index 5078a11..af7b05b 100644
--- a/guest/platform/linux/LinuxVirtGpuDevice.cpp
+++ b/guest/platform/linux/LinuxVirtGpuDevice.cpp
@@ -31,6 +31,9 @@
 #include "virtgpu_drm.h"
 #include "virtgpu_gfxstream_protocol.h"
 
+#define VIRTGPU_PARAM_CREATE_FENCE_PASSING 9  /* Fence passing */
+#define VIRTGPU_PARAM_CREATE_GUEST_HANDLE 10  /* Host OS handle can be created from guest memory. */
+
 #define PARAM(x) \
     (struct VirtGpuParam) { x, #x, 0 }
 
@@ -42,6 +45,7 @@
         PARAM(VIRTGPU_PARAM_RESOURCE_BLOB),        PARAM(VIRTGPU_PARAM_HOST_VISIBLE),
         PARAM(VIRTGPU_PARAM_CROSS_DEVICE),         PARAM(VIRTGPU_PARAM_CONTEXT_INIT),
         PARAM(VIRTGPU_PARAM_SUPPORTED_CAPSET_IDs), PARAM(VIRTGPU_PARAM_EXPLICIT_DEBUG_NAME),
+        PARAM(VIRTGPU_PARAM_CREATE_FENCE_PASSING),
         PARAM(VIRTGPU_PARAM_CREATE_GUEST_HANDLE),
     };
 
@@ -150,8 +154,9 @@
 int64_t LinuxVirtGpuDevice::getDeviceHandle(void) { return mDeviceHandle; }
 
 VirtGpuResourcePtr LinuxVirtGpuDevice::createResource(uint32_t width, uint32_t height,
-                                                      uint32_t stride, uint32_t virglFormat,
-                                                      uint32_t target, uint32_t bind) {
+                                                      uint32_t stride, uint32_t size,
+                                                      uint32_t virglFormat, uint32_t target,
+                                                      uint32_t bind) {
     drm_virtgpu_resource_create create = {
         .target = target,
         .format = virglFormat,
@@ -162,7 +167,7 @@
         .array_size = 1U,
         .last_level = 0,
         .nr_samples = 0,
-        .size = stride * height,
+        .size = size,
         .stride = stride,
     };
 
diff --git a/guest/platform/rutabaga/RutabagaVirtGpu.h b/guest/platform/rutabaga/RutabagaVirtGpu.h
index d2cce9d..e56369b 100644
--- a/guest/platform/rutabaga/RutabagaVirtGpu.h
+++ b/guest/platform/rutabaga/RutabagaVirtGpu.h
@@ -90,7 +90,8 @@
    VirtGpuResourcePtr createBlob(const struct VirtGpuCreateBlob& blobCreate) override;
 
    VirtGpuResourcePtr createResource(uint32_t width, uint32_t height, uint32_t stride,
-                                     uint32_t virglFormat, uint32_t target, uint32_t bind) override;
+                                     uint32_t size, uint32_t virglFormat, uint32_t target,
+                                     uint32_t bind) override;
 
    VirtGpuResourcePtr importBlob(const struct VirtGpuExternalHandle& handle) override;
 
diff --git a/guest/platform/rutabaga/RutabagaVirtGpuDevice.cpp b/guest/platform/rutabaga/RutabagaVirtGpuDevice.cpp
index 8794122..4ae1636 100644
--- a/guest/platform/rutabaga/RutabagaVirtGpuDevice.cpp
+++ b/guest/platform/rutabaga/RutabagaVirtGpuDevice.cpp
@@ -105,10 +105,9 @@
 }
 
 VirtGpuResourcePtr RutabagaVirtGpuDevice::createResource(uint32_t width, uint32_t height,
-                                                         uint32_t stride, uint32_t virglFormat,
-                                                         uint32_t target, uint32_t bind) {
-    uint32_t size = stride * height;
-
+                                                         uint32_t /*stride*/, uint32_t size,
+                                                         uint32_t virglFormat, uint32_t target,
+                                                         uint32_t bind) {
     const auto resourceIdOpt =
         mEmulation->CreateVirglBlob(mContextId, width, height, virglFormat, target, bind, size);
     if (!resourceIdOpt) {
diff --git a/guest/platform/stub/StubVirtGpu.h b/guest/platform/stub/StubVirtGpu.h
index e1b098e..c8f8178 100644
--- a/guest/platform/stub/StubVirtGpu.h
+++ b/guest/platform/stub/StubVirtGpu.h
@@ -69,7 +69,8 @@
 
     VirtGpuResourcePtr createBlob(const struct VirtGpuCreateBlob& blobCreate) override;
     VirtGpuResourcePtr createResource(uint32_t width, uint32_t height, uint32_t stride,
-                                      uint32_t virglFormat, uint32_t target, uint32_t bind);
+                                      uint32_t size, uint32_t virglFormat, uint32_t target,
+                                      uint32_t bind);
     VirtGpuResourcePtr importBlob(const struct VirtGpuExternalHandle& handle) override;
 
     int execBuffer(struct VirtGpuExecBuffer& execbuffer, const VirtGpuResource* blob) override;
diff --git a/guest/platform/stub/StubVirtGpuDevice.cpp b/guest/platform/stub/StubVirtGpuDevice.cpp
index 7a08b52..f642b25 100644
--- a/guest/platform/stub/StubVirtGpuDevice.cpp
+++ b/guest/platform/stub/StubVirtGpuDevice.cpp
@@ -27,11 +27,13 @@
 }
 
 VirtGpuResourcePtr StubVirtGpuDevice::createResource(uint32_t width, uint32_t height,
-                                                     uint32_t stride, uint32_t virglFormat,
-                                                     uint32_t target, uint32_t bind) {
+                                                     uint32_t stride, uint32_t size,
+                                                     uint32_t virglFormat, uint32_t target,
+                                                     uint32_t bind) {
     (void)width;
     (void)height;
     (void)stride;
+    (void)size;
     (void)virglFormat;
     (void)target;
     (void)bind;
diff --git a/guest/vulkan/gfxstream_vk_cmd.cpp b/guest/vulkan/gfxstream_vk_cmd.cpp
index b3d6fce..2039e08 100644
--- a/guest/vulkan/gfxstream_vk_cmd.cpp
+++ b/guest/vulkan/gfxstream_vk_cmd.cpp
@@ -15,11 +15,12 @@
 #include "ResourceTracker.h"
 #include "VkEncoder.h"
 #include "gfxstream_vk_private.h"
+#include "util/perf/cpu_trace.h"
 
 VkResult gfxstream_vk_CreateCommandPool(VkDevice device, const VkCommandPoolCreateInfo* pCreateInfo,
                                         const VkAllocationCallbacks* pAllocator,
                                         VkCommandPool* pCommandPool) {
-    AEMU_SCOPED_TRACE("vkCreateCommandPool");
+    MESA_TRACE_SCOPE("vkCreateCommandPool");
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     VkResult result = (VkResult)0;
     struct gfxstream_vk_command_pool* gfxstream_pCommandPool =
@@ -43,7 +44,7 @@
 
 void gfxstream_vk_DestroyCommandPool(VkDevice device, VkCommandPool commandPool,
                                      const VkAllocationCallbacks* pAllocator) {
-    AEMU_SCOPED_TRACE("vkDestroyCommandPool");
+    MESA_TRACE_SCOPE("vkDestroyCommandPool");
     if (VK_NULL_HANDLE == commandPool) {
         return;
     }
@@ -61,7 +62,7 @@
 
 VkResult gfxstream_vk_ResetCommandPool(VkDevice device, VkCommandPool commandPool,
                                        VkCommandPoolResetFlags flags) {
-    AEMU_SCOPED_TRACE("vkResetCommandPool");
+    MESA_TRACE_SCOPE("vkResetCommandPool");
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     VK_FROM_HANDLE(gfxstream_vk_command_pool, gfxstream_commandPool, commandPool);
     VkResult vkResetCommandPool_VkResult_return = (VkResult)0;
@@ -121,7 +122,7 @@
 VkResult gfxstream_vk_AllocateCommandBuffers(VkDevice device,
                                              const VkCommandBufferAllocateInfo* pAllocateInfo,
                                              VkCommandBuffer* pCommandBuffers) {
-    AEMU_SCOPED_TRACE("vkAllocateCommandBuffers");
+    MESA_TRACE_SCOPE("vkAllocateCommandBuffers");
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     VK_FROM_HANDLE(gfxstream_vk_command_pool, gfxstream_commandPool, pAllocateInfo->commandPool);
     VkResult result = (VkResult)0;
@@ -165,7 +166,7 @@
 void gfxstream_vk_FreeCommandBuffers(VkDevice device, VkCommandPool commandPool,
                                      uint32_t commandBufferCount,
                                      const VkCommandBuffer* pCommandBuffers) {
-    AEMU_SCOPED_TRACE("vkFreeCommandBuffers");
+    MESA_TRACE_SCOPE("vkFreeCommandBuffers");
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     VK_FROM_HANDLE(gfxstream_vk_command_pool, gfxstream_commandPool, commandPool);
     {
@@ -186,3 +187,25 @@
         vk_command_buffer_destroyOp(&gfxstream_commandBuffer->vk);
     }
 }
+
+void gfxstream_vk_CmdBeginTransformFeedbackEXT(VkCommandBuffer commandBuffer,
+                                               uint32_t firstCounterBuffer,
+                                               uint32_t counterBufferCount,
+                                               const VkBuffer* pCounterBuffers,
+                                               const VkDeviceSize* pCounterBufferOffsets) {
+    MESA_TRACE_SCOPE("vkCmdBeginTransformFeedbackEXT");
+    VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
+    auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
+        gfxstream_commandBuffer->internal_object);
+    std::vector<VkBuffer> internal_pCounterBuffers(counterBufferCount);
+    for (uint32_t i = 0; i < counterBufferCount; ++i) {
+        if (pCounterBuffers && pCounterBuffers[i]) {
+            VK_FROM_HANDLE(gfxstream_vk_buffer, gfxstream_pCounterBuffers, pCounterBuffers[i]);
+            internal_pCounterBuffers[i] = gfxstream_pCounterBuffers->internal_object;
+        }
+    }
+    vkEnc->vkCmdBeginTransformFeedbackEXT(gfxstream_commandBuffer->internal_object,
+                                          firstCounterBuffer, counterBufferCount,
+                                          pCounterBuffers ? internal_pCounterBuffers.data() : NULL,
+                                          pCounterBufferOffsets, true /* do lock */);
+}
diff --git a/guest/vulkan/gfxstream_vk_device.cpp b/guest/vulkan/gfxstream_vk_device.cpp
index 2ccf87e..4c022e8 100644
--- a/guest/vulkan/gfxstream_vk_device.cpp
+++ b/guest/vulkan/gfxstream_vk_device.cpp
@@ -22,6 +22,7 @@
 #include "VkEncoder.h"
 #include "gfxstream_vk_entrypoints.h"
 #include "gfxstream_vk_private.h"
+#include "util/perf/cpu_trace.h"
 #include "vk_alloc.h"
 #include "vk_device.h"
 #include "vk_instance.h"
@@ -302,7 +303,7 @@
 VkResult gfxstream_vk_CreateInstance(const VkInstanceCreateInfo* pCreateInfo,
                                      const VkAllocationCallbacks* pAllocator,
                                      VkInstance* pInstance) {
-    AEMU_SCOPED_TRACE("vkCreateInstance");
+    MESA_TRACE_SCOPE("vkCreateInstance");
 
     struct gfxstream_vk_instance* instance;
 
@@ -366,7 +367,7 @@
 }
 
 void gfxstream_vk_DestroyInstance(VkInstance _instance, const VkAllocationCallbacks* pAllocator) {
-    AEMU_SCOPED_TRACE("vkDestroyInstance");
+    MESA_TRACE_SCOPE("vkDestroyInstance");
     if (VK_NULL_HANDLE == _instance) return;
 
     VK_FROM_HANDLE(gfxstream_vk_instance, instance, _instance);
@@ -388,7 +389,7 @@
 VkResult gfxstream_vk_EnumerateInstanceExtensionProperties(const char* pLayerName,
                                                            uint32_t* pPropertyCount,
                                                            VkExtensionProperties* pProperties) {
-    AEMU_SCOPED_TRACE("vkvkEnumerateInstanceExtensionProperties");
+    MESA_TRACE_SCOPE("vkvkEnumerateInstanceExtensionProperties");
     (void)pLayerName;
 
     return vk_enumerate_instance_extension_properties(get_instance_extensions(), pPropertyCount,
@@ -399,7 +400,7 @@
                                                          const char* pLayerName,
                                                          uint32_t* pPropertyCount,
                                                          VkExtensionProperties* pProperties) {
-    AEMU_SCOPED_TRACE("vkEnumerateDeviceExtensionProperties");
+    MESA_TRACE_SCOPE("vkEnumerateDeviceExtensionProperties");
     (void)pLayerName;
     VK_FROM_HANDLE(vk_physical_device, pdevice, physicalDevice);
 
@@ -419,7 +420,7 @@
 VkResult gfxstream_vk_CreateDevice(VkPhysicalDevice physicalDevice,
                                    const VkDeviceCreateInfo* pCreateInfo,
                                    const VkAllocationCallbacks* pAllocator, VkDevice* pDevice) {
-    AEMU_SCOPED_TRACE("vkCreateDevice");
+    MESA_TRACE_SCOPE("vkCreateDevice");
     VK_FROM_HANDLE(gfxstream_vk_physical_device, gfxstream_physicalDevice, physicalDevice);
     VkResult result = (VkResult)0;
 
@@ -516,7 +517,7 @@
 }
 
 void gfxstream_vk_DestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator) {
-    AEMU_SCOPED_TRACE("vkDestroyDevice");
+    MESA_TRACE_SCOPE("vkDestroyDevice");
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     if (VK_NULL_HANDLE == device) return;
 
@@ -534,7 +535,7 @@
 
 void gfxstream_vk_GetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex,
                                  VkQueue* pQueue) {
-    AEMU_SCOPED_TRACE("vkGetDeviceQueue");
+    MESA_TRACE_SCOPE("vkGetDeviceQueue");
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     struct gfxstream_vk_queue* gfxstream_queue = (struct gfxstream_vk_queue*)vk_zalloc(
         &gfxstream_device->vk.alloc, sizeof(struct gfxstream_vk_queue), 8,
@@ -566,7 +567,7 @@
 
 void gfxstream_vk_GetDeviceQueue2(VkDevice device, const VkDeviceQueueInfo2* pQueueInfo,
                                   VkQueue* pQueue) {
-    AEMU_SCOPED_TRACE("vkGetDeviceQueue2");
+    MESA_TRACE_SCOPE("vkGetDeviceQueue2");
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     struct gfxstream_vk_queue* gfxstream_queue = (struct gfxstream_vk_queue*)vk_zalloc(
         &gfxstream_device->vk.alloc, sizeof(struct gfxstream_vk_queue), 8,
@@ -637,7 +638,7 @@
 }
 
 PFN_vkVoidFunction gfxstream_vk_GetDeviceProcAddr(VkDevice _device, const char* pName) {
-    AEMU_SCOPED_TRACE("vkGetDeviceProcAddr");
+    MESA_TRACE_SCOPE("vkGetDeviceProcAddr");
     VK_FROM_HANDLE(gfxstream_vk_device, device, _device);
     return vk_device_get_proc_addr(&device->vk, pName);
 }
@@ -645,7 +646,7 @@
 VkResult gfxstream_vk_AllocateMemory(VkDevice device, const VkMemoryAllocateInfo* pAllocateInfo,
                                      const VkAllocationCallbacks* pAllocator,
                                      VkDeviceMemory* pMemory) {
-    AEMU_SCOPED_TRACE("vkAllocateMemory");
+    MESA_TRACE_SCOPE("vkAllocateMemory");
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     VkResult vkAllocateMemory_VkResult_return = (VkResult)0;
     /* VkMemoryDedicatedAllocateInfo */
@@ -670,7 +671,7 @@
 
 VkResult gfxstream_vk_EnumerateInstanceLayerProperties(uint32_t* pPropertyCount,
                                                        VkLayerProperties* pProperties) {
-    AEMU_SCOPED_TRACE("vkEnumerateInstanceLayerProperties");
+    MESA_TRACE_SCOPE("vkEnumerateInstanceLayerProperties");
     auto result = SetupInstanceForProcess();
     if (VK_SUCCESS != result) {
         return vk_error(NULL, result);
@@ -687,7 +688,7 @@
 }
 
 VkResult gfxstream_vk_EnumerateInstanceVersion(uint32_t* pApiVersion) {
-    AEMU_SCOPED_TRACE("vkEnumerateInstanceVersion");
+    MESA_TRACE_SCOPE("vkEnumerateInstanceVersion");
     auto result = SetupInstanceForProcess();
     if (VK_SUCCESS != result) {
         return vk_error(NULL, result);
@@ -714,7 +715,7 @@
         outDescriptorSet = srcDescriptorSet;
 
         bufferInfos.push_back(std::vector<VkDescriptorBufferInfo>());
-        bufferInfos[i].reserve(descriptorCount);
+        bufferInfos[i].resize(descriptorCount);
         memset(&bufferInfos[i][0], 0, sizeof(VkDescriptorBufferInfo) * descriptorCount);
         for (uint32_t j = 0; j < descriptorCount; ++j) {
             const auto* srcBufferInfo = srcDescriptorSet.pBufferInfo;
@@ -737,7 +738,7 @@
                                        const VkWriteDescriptorSet* pDescriptorWrites,
                                        uint32_t descriptorCopyCount,
                                        const VkCopyDescriptorSet* pDescriptorCopies) {
-    AEMU_SCOPED_TRACE("vkUpdateDescriptorSets");
+    MESA_TRACE_SCOPE("vkUpdateDescriptorSets");
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
diff --git a/guest/vulkan/gfxstream_vk_fuchsia.cpp b/guest/vulkan/gfxstream_vk_fuchsia.cpp
index 4b1b324..edc75ac 100644
--- a/guest/vulkan/gfxstream_vk_fuchsia.cpp
+++ b/guest/vulkan/gfxstream_vk_fuchsia.cpp
@@ -3,6 +3,7 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
+#include <cutils/log.h>
 #include <fidl/fuchsia.logger/cpp/wire.h>
 #include <lib/syslog/structured_backend/cpp/fuchsia_syslog.h>
 #include <lib/zx/channel.h>
diff --git a/guest/vulkan_enc/ResourceTracker.cpp b/guest/vulkan_enc/ResourceTracker.cpp
index b663921..fe19b25 100644
--- a/guest/vulkan_enc/ResourceTracker.cpp
+++ b/guest/vulkan_enc/ResourceTracker.cpp
@@ -30,6 +30,7 @@
 #include "virtgpu_gfxstream_protocol.h"
 #include "vulkan/vk_enum_string_helper.h"
 #include "vulkan/vulkan_core.h"
+
 #ifdef VK_USE_PLATFORM_ANDROID_KHR
 #include "vk_format_info.h"
 #endif
@@ -129,7 +130,7 @@
 ResourceTracker::ThreadingCallbacks ResourceTracker::threadingCallbacks;
 
 struct StagingInfo {
-    Lock mLock;
+    std::mutex mLock;
     std::vector<CommandBufferStagingStream*> streams;
     std::vector<VkEncoder*> encoders;
     /// \brief sets alloc and free callbacks for memory allocation for CommandBufferStagingStream(s)
@@ -152,14 +153,14 @@
     }
 
     void pushStaging(CommandBufferStagingStream* stream, VkEncoder* encoder) {
-        AutoLock<Lock> lock(mLock);
+        std::lock_guard<std::mutex> lock(mLock);
         stream->reset();
         streams.push_back(stream);
         encoders.push_back(encoder);
     }
 
     void popStaging(CommandBufferStagingStream** streamOut, VkEncoder** encoderOut) {
-        AutoLock<Lock> lock(mLock);
+        std::lock_guard<std::mutex> lock(mLock);
         CommandBufferStagingStream* stream;
         VkEncoder* encoder;
         if (streams.empty()) {
@@ -191,16 +192,16 @@
     std::unordered_set<VkDescriptorSet> sets;
 };
 
-#define HANDLE_REGISTER_IMPL_IMPL(type)               \
-    void ResourceTracker::register_##type(type obj) { \
-        AutoLock<RecursiveLock> lock(mLock);          \
-        info_##type[obj] = type##_Info();             \
+#define HANDLE_REGISTER_IMPL_IMPL(type)                    \
+    void ResourceTracker::register_##type(type obj) {      \
+        std::lock_guard<std::recursive_mutex> lock(mLock); \
+        info_##type[obj] = type##_Info();                  \
     }
 
-#define HANDLE_UNREGISTER_IMPL_IMPL(type)               \
-    void ResourceTracker::unregister_##type(type obj) { \
-        AutoLock<RecursiveLock> lock(mLock);            \
-        info_##type.erase(obj);                         \
+#define HANDLE_UNREGISTER_IMPL_IMPL(type)                  \
+    void ResourceTracker::unregister_##type(type obj) {    \
+        std::lock_guard<std::recursive_mutex> lock(mLock); \
+        info_##type.erase(obj);                            \
     }
 
 GOLDFISH_VK_LIST_HANDLE_TYPES(HANDLE_REGISTER_IMPL_IMPL)
@@ -753,6 +754,24 @@
     return nullptr;
 }
 
+VkResult acquireSync(uint64_t syncId, int64_t& osHandle) {
+    struct VirtGpuExecBuffer exec = {};
+    struct gfxstreamAcquireSync acquireSync = {};
+    VirtGpuDevice* instance = VirtGpuDevice::getInstance();
+
+    acquireSync.hdr.opCode = GFXSTREAM_ACQUIRE_SYNC;
+    acquireSync.syncId = syncId;
+
+    exec.command = static_cast<void*>(&acquireSync);
+    exec.command_size = sizeof(acquireSync);
+    exec.flags = kFenceOut | kRingIdx | kShareableOut;
+
+    if (instance->execBuffer(exec, nullptr)) return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+    osHandle = exec.handle.osHandle;
+    return VK_SUCCESS;
+}
+
 VkResult createFence(VkDevice device, uint64_t hostFenceHandle, int64_t& osHandle) {
     struct VirtGpuExecBuffer exec = {};
     struct gfxstreamCreateExportSyncVK exportSync = {};
@@ -1000,23 +1019,21 @@
 }
 
 void ResourceTracker::unregister_VkInstance(VkInstance instance) {
-    AutoLock<RecursiveLock> lock(mLock);
+    std::lock_guard<std::recursive_mutex> lock(mLock);
 
     auto it = info_VkInstance.find(instance);
     if (it == info_VkInstance.end()) return;
     auto info = it->second;
     info_VkInstance.erase(instance);
-    lock.unlock();
 }
 
 void ResourceTracker::unregister_VkDevice(VkDevice device) {
-    AutoLock<RecursiveLock> lock(mLock);
+    std::lock_guard<std::recursive_mutex> lock(mLock);
 
     auto it = info_VkDevice.find(device);
     if (it == info_VkDevice.end()) return;
     auto info = it->second;
     info_VkDevice.erase(device);
-    lock.unlock();
 }
 
 void ResourceTracker::unregister_VkCommandPool(VkCommandPool pool) {
@@ -1024,14 +1041,14 @@
 
     clearCommandPool(pool);
 
-    AutoLock<RecursiveLock> lock(mLock);
+    std::lock_guard<std::recursive_mutex> lock(mLock);
     info_VkCommandPool.erase(pool);
 }
 
 void ResourceTracker::unregister_VkSampler(VkSampler sampler) {
     if (!sampler) return;
 
-    AutoLock<RecursiveLock> lock(mLock);
+    std::lock_guard<std::recursive_mutex> lock(mLock);
     info_VkSampler.erase(sampler);
 }
 
@@ -1057,7 +1074,7 @@
         delete pendingSets;
     }
 
-    AutoLock<RecursiveLock> lock(mLock);
+    std::lock_guard<std::recursive_mutex> lock(mLock);
     info_VkCommandBuffer.erase(commandBuffer);
 }
 
@@ -1068,12 +1085,12 @@
         q->lastUsedEncoder->decRef();
     }
 
-    AutoLock<RecursiveLock> lock(mLock);
+    std::lock_guard<std::recursive_mutex> lock(mLock);
     info_VkQueue.erase(queue);
 }
 
 void ResourceTracker::unregister_VkDeviceMemory(VkDeviceMemory mem) {
-    AutoLock<RecursiveLock> lock(mLock);
+    std::lock_guard<std::recursive_mutex> lock(mLock);
 
     auto it = info_VkDeviceMemory.find(mem);
     if (it == info_VkDeviceMemory.end()) return;
@@ -1096,7 +1113,7 @@
 }
 
 void ResourceTracker::unregister_VkImage(VkImage img) {
-    AutoLock<RecursiveLock> lock(mLock);
+    std::lock_guard<std::recursive_mutex> lock(mLock);
 
     auto it = info_VkImage.find(img);
     if (it == info_VkImage.end()) return;
@@ -1107,7 +1124,7 @@
 }
 
 void ResourceTracker::unregister_VkBuffer(VkBuffer buf) {
-    AutoLock<RecursiveLock> lock(mLock);
+    std::lock_guard<std::recursive_mutex> lock(mLock);
 
     auto it = info_VkBuffer.find(buf);
     if (it == info_VkBuffer.end()) return;
@@ -1116,7 +1133,7 @@
 }
 
 void ResourceTracker::unregister_VkSemaphore(VkSemaphore sem) {
-    AutoLock<RecursiveLock> lock(mLock);
+    std::lock_guard<std::recursive_mutex> lock(mLock);
 
     auto it = info_VkSemaphore.find(sem);
     if (it == info_VkSemaphore.end()) return;
@@ -1139,7 +1156,7 @@
 }
 
 void ResourceTracker::unregister_VkDescriptorUpdateTemplate(VkDescriptorUpdateTemplate templ) {
-    AutoLock<RecursiveLock> lock(mLock);
+    std::lock_guard<std::recursive_mutex> lock(mLock);
     auto it = info_VkDescriptorUpdateTemplate.find(templ);
     if (it == info_VkDescriptorUpdateTemplate.end()) return;
 
@@ -1161,7 +1178,7 @@
 }
 
 void ResourceTracker::unregister_VkFence(VkFence fence) {
-    AutoLock<RecursiveLock> lock(mLock);
+    std::lock_guard<std::recursive_mutex> lock(mLock);
     auto it = info_VkFence.find(fence);
     if (it == info_VkFence.end()) return;
 
@@ -1181,7 +1198,7 @@
 
 #ifdef VK_USE_PLATFORM_FUCHSIA
 void ResourceTracker::unregister_VkBufferCollectionFUCHSIA(VkBufferCollectionFUCHSIA collection) {
-    AutoLock<RecursiveLock> lock(mLock);
+    std::lock_guard<std::recursive_mutex> lock(mLock);
     info_VkBufferCollectionFUCHSIA.erase(collection);
 }
 #endif
@@ -1195,14 +1212,14 @@
 void ResourceTracker::unregister_VkDescriptorSet(VkDescriptorSet set) {
     if (!set) return;
 
-    AutoLock<RecursiveLock> lock(mLock);
+    std::lock_guard<std::recursive_mutex> lock(mLock);
     unregister_VkDescriptorSet_locked(set);
 }
 
 void ResourceTracker::unregister_VkDescriptorSetLayout(VkDescriptorSetLayout setLayout) {
     if (!setLayout) return;
 
-    AutoLock<RecursiveLock> lock(mLock);
+    std::lock_guard<std::recursive_mutex> lock(mLock);
     delete as_goldfish_VkDescriptorSetLayout(setLayout)->layoutInfo;
     info_VkDescriptorSetLayout.erase(setLayout);
 }
@@ -1239,7 +1256,7 @@
 void ResourceTracker::unregister_VkDescriptorPool(VkDescriptorPool pool) {
     if (!pool) return;
 
-    AutoLock<RecursiveLock> lock(mLock);
+    std::lock_guard<std::recursive_mutex> lock(mLock);
 
     struct goldfish_VkDescriptorPool* dp = as_goldfish_VkDescriptorPool(pool);
     delete dp->allocInfo;
@@ -1283,7 +1300,7 @@
 void ResourceTracker::setInstanceInfo(VkInstance instance, uint32_t enabledExtensionCount,
                                       const char* const* ppEnabledExtensionNames,
                                       uint32_t apiVersion) {
-    AutoLock<RecursiveLock> lock(mLock);
+    std::lock_guard<std::recursive_mutex> lock(mLock);
     auto& info = info_VkInstance[instance];
     info.highestApiVersion = apiVersion;
 
@@ -1299,7 +1316,7 @@
                                     VkPhysicalDeviceMemoryProperties memProps,
                                     uint32_t enabledExtensionCount,
                                     const char* const* ppEnabledExtensionNames, const void* pNext) {
-    AutoLock<RecursiveLock> lock(mLock);
+    std::lock_guard<std::recursive_mutex> lock(mLock);
     auto& info = info_VkDevice[device];
     info.physdev = physdev;
     info.props = props;
@@ -1335,7 +1352,7 @@
                                           uint32_t memoryTypeIndex, AHardwareBuffer* ahw,
                                           bool imported, zx_handle_t vmoHandle,
                                           VirtGpuResourcePtr blobPtr) {
-    AutoLock<RecursiveLock> lock(mLock);
+    std::lock_guard<std::recursive_mutex> lock(mLock);
     auto& info = info_VkDeviceMemory[memory];
 
     info.device = device;
@@ -1352,7 +1369,7 @@
 
 void ResourceTracker::setImageInfo(VkImage image, VkDevice device,
                                    const VkImageCreateInfo* pCreateInfo) {
-    AutoLock<RecursiveLock> lock(mLock);
+    std::lock_guard<std::recursive_mutex> lock(mLock);
     auto& info = info_VkImage[image];
 
     info.device = device;
@@ -1360,7 +1377,7 @@
 }
 
 uint8_t* ResourceTracker::getMappedPointer(VkDeviceMemory memory) {
-    AutoLock<RecursiveLock> lock(mLock);
+    std::lock_guard<std::recursive_mutex> lock(mLock);
     const auto it = info_VkDeviceMemory.find(memory);
     if (it == info_VkDeviceMemory.end()) return nullptr;
 
@@ -1369,7 +1386,7 @@
 }
 
 VkDeviceSize ResourceTracker::getMappedSize(VkDeviceMemory memory) {
-    AutoLock<RecursiveLock> lock(mLock);
+    std::lock_guard<std::recursive_mutex> lock(mLock);
     const auto it = info_VkDeviceMemory.find(memory);
     if (it == info_VkDeviceMemory.end()) return 0;
 
@@ -1377,8 +1394,8 @@
     return info.allocationSize;
 }
 
-bool ResourceTracker::isValidMemoryRange(const VkMappedMemoryRange& range) const {
-    AutoLock<RecursiveLock> lock(mLock);
+bool ResourceTracker::isValidMemoryRange(const VkMappedMemoryRange& range) {
+    std::lock_guard<std::recursive_mutex> lock(mLock);
     const auto it = info_VkDeviceMemory.find(range.memory);
     if (it == info_VkDeviceMemory.end()) return false;
     const auto& info = it->second;
@@ -1552,7 +1569,7 @@
     (void)typeBitsCount;
 
     if (memory) {
-        AutoLock<RecursiveLock> lock(mLock);
+        std::lock_guard<std::recursive_mutex> lock(mLock);
 
         for (uint32_t i = 0; i < memoryCount; ++i) {
             VkDeviceMemory mem = memory[i];
@@ -1954,7 +1971,7 @@
 
     if (!pPhysicalDeviceCount) return VK_ERROR_INITIALIZATION_FAILED;
 
-    AutoLock<RecursiveLock> lock(mLock);
+    std::unique_lock<std::recursive_mutex> lock(mLock);
 
     // When this function is called, we actually need to do two things:
     // - Get full information about physical devices from the host,
@@ -2104,13 +2121,13 @@
 
 void ResourceTracker::on_vkGetDeviceQueue(void*, VkDevice device, uint32_t, uint32_t,
                                           VkQueue* pQueue) {
-    AutoLock<RecursiveLock> lock(mLock);
+    std::lock_guard<std::recursive_mutex> lock(mLock);
     info_VkQueue[*pQueue].device = device;
 }
 
 void ResourceTracker::on_vkGetDeviceQueue2(void*, VkDevice device, const VkDeviceQueueInfo2*,
                                            VkQueue* pQueue) {
-    AutoLock<RecursiveLock> lock(mLock);
+    std::lock_guard<std::recursive_mutex> lock(mLock);
     info_VkQueue[*pQueue].device = device;
 }
 
@@ -2153,7 +2170,7 @@
 void ResourceTracker::on_vkDestroyDevice_pre(void* context, VkDevice device,
                                              const VkAllocationCallbacks*) {
     (void)context;
-    AutoLock<RecursiveLock> lock(mLock);
+    std::lock_guard<std::recursive_mutex> lock(mLock);
 
     auto it = info_VkDevice.find(device);
     if (it == info_VkDevice.end()) return;
@@ -2198,7 +2215,7 @@
     if (!pInfo) return VK_ERROR_INITIALIZATION_FAILED;
     if (!pInfo->memory) return VK_ERROR_INITIALIZATION_FAILED;
 
-    AutoLock<RecursiveLock> lock(mLock);
+    std::lock_guard<std::recursive_mutex> lock(mLock);
 
     auto deviceIt = info_VkDevice.find(device);
 
@@ -2232,7 +2249,7 @@
     if (!pInfo) return VK_ERROR_INITIALIZATION_FAILED;
     if (!pInfo->memory) return VK_ERROR_INITIALIZATION_FAILED;
 
-    AutoLock<RecursiveLock> lock(mLock);
+    std::lock_guard<std::recursive_mutex> lock(mLock);
 
     auto deviceIt = info_VkDevice.find(device);
 
@@ -2275,7 +2292,7 @@
         return VK_ERROR_INVALID_EXTERNAL_HANDLE;
     }
 
-    AutoLock<RecursiveLock> lock(mLock);
+    std::lock_guard<std::recursive_mutex> lock(mLock);
 
     auto deviceIt = info_VkDevice.find(device);
 
@@ -2349,7 +2366,7 @@
     if (!pInfo) return VK_ERROR_INITIALIZATION_FAILED;
     if (!pInfo->semaphore) return VK_ERROR_INITIALIZATION_FAILED;
 
-    AutoLock<RecursiveLock> lock(mLock);
+    std::lock_guard<std::recursive_mutex> lock(mLock);
 
     auto deviceIt = info_VkDevice.find(device);
 
@@ -2386,7 +2403,7 @@
     if (!pInfo) return VK_ERROR_INITIALIZATION_FAILED;
     if (!pInfo->semaphore) return VK_ERROR_INITIALIZATION_FAILED;
 
-    AutoLock<RecursiveLock> lock(mLock);
+    std::lock_guard<std::recursive_mutex> lock(mLock);
 
     auto deviceIt = info_VkDevice.find(device);
 
@@ -2498,7 +2515,7 @@
 
     VkPhysicalDevice physicalDevice;
     {
-        AutoLock<RecursiveLock> lock(mLock);
+        std::lock_guard<std::recursive_mutex> lock(mLock);
         auto deviceIt = info_VkDevice.find(device);
         if (deviceIt == info_VkDevice.end()) {
             return {VK_ERROR_INITIALIZATION_FAILED};
@@ -2611,13 +2628,14 @@
 
     // copy constraints to info_VkBufferCollectionFUCHSIA if
     // |collection| is a valid VkBufferCollectionFUCHSIA handle.
-    AutoLock<RecursiveLock> lock(mLock);
+    std::lock_guard<std::recursive_mutex> lock(mLock);
     VkBufferCollectionFUCHSIA buffer_collection =
         reinterpret_cast<VkBufferCollectionFUCHSIA>(pCollection);
     if (info_VkBufferCollectionFUCHSIA.find(buffer_collection) !=
         info_VkBufferCollectionFUCHSIA.end()) {
         info_VkBufferCollectionFUCHSIA[buffer_collection].constraints =
-            gfxstream::guest::makeOptional(std::move(setConstraintsResult.constraints));
+            std::make_optional<fuchsia_sysmem::wire::BufferCollectionConstraints>(
+                std::move(setConstraintsResult.constraints));
         info_VkBufferCollectionFUCHSIA[buffer_collection].createInfoIndex =
             std::move(setConstraintsResult.createInfoIndex);
     }
@@ -2636,13 +2654,14 @@
 
     // copy constraints to info_VkBufferCollectionFUCHSIA if
     // |collection| is a valid VkBufferCollectionFUCHSIA handle.
-    AutoLock<RecursiveLock> lock(mLock);
+    std::lock_guard<std::recursive_mutex> lock(mLock);
     VkBufferCollectionFUCHSIA buffer_collection =
         reinterpret_cast<VkBufferCollectionFUCHSIA>(pCollection);
     if (info_VkBufferCollectionFUCHSIA.find(buffer_collection) !=
         info_VkBufferCollectionFUCHSIA.end()) {
         info_VkBufferCollectionFUCHSIA[buffer_collection].constraints =
-            gfxstream::guest::makeOptional(setConstraintsResult.constraints);
+            std::make_optional<fuchsia_sysmem::wire::BufferCollectionConstraints>(
+                setConstraintsResult.constraints);
     }
 
     return VK_SUCCESS;
@@ -2669,7 +2688,7 @@
 VkResult ResourceTracker::getBufferCollectionImageCreateInfoIndexLocked(
     VkBufferCollectionFUCHSIA collection, fuchsia_sysmem::wire::BufferCollectionInfo2& info,
     uint32_t* outCreateInfoIndex) {
-    if (!info_VkBufferCollectionFUCHSIA[collection].constraints.hasValue()) {
+    if (!info_VkBufferCollectionFUCHSIA[collection].constraints.has_value()) {
         mesa_loge("%s: constraints not set", __func__);
         return VK_ERROR_OUT_OF_DEVICE_MEMORY;
     }
@@ -2757,7 +2776,7 @@
     // memoryTypeBits
     // ====================================================================
     {
-        AutoLock<RecursiveLock> lock(mLock);
+        std::lock_guard<std::recursive_mutex> lock(mLock);
         auto deviceIt = info_VkDevice.find(device);
         if (deviceIt == info_VkDevice.end()) {
             return VK_ERROR_INITIALIZATION_FAILED;
@@ -2782,14 +2801,14 @@
 
     auto storeProperties = [this, collection, pProperties]() -> VkResult {
         // store properties to storage
-        AutoLock<RecursiveLock> lock(mLock);
+        std::lock_guard<std::recursive_mutex> lock(mLock);
         if (info_VkBufferCollectionFUCHSIA.find(collection) ==
             info_VkBufferCollectionFUCHSIA.end()) {
             return VK_ERROR_OUT_OF_DEVICE_MEMORY;
         }
 
         info_VkBufferCollectionFUCHSIA[collection].properties =
-            gfxstream::guest::makeOptional(*pProperties);
+            std::make_optional<VkBufferCollectionPropertiesFUCHSIA>(*pProperties);
 
         // We only do a shallow copy so we should remove all pNext pointers.
         info_VkBufferCollectionFUCHSIA[collection].properties->pNext = nullptr;
@@ -2826,7 +2845,7 @@
     // createInfoIndex
     // ====================================================================
     {
-        AutoLock<RecursiveLock> lock(mLock);
+        std::lock_guard<std::recursive_mutex> lock(mLock);
         auto getIndexResult = getBufferCollectionImageCreateInfoIndexLocked(
             collection, info, &pProperties->createInfoIndex);
         if (getIndexResult != VK_SUCCESS) {
@@ -2838,7 +2857,7 @@
     // ====================================================================
     VkPhysicalDevice physicalDevice;
     {
-        AutoLock<RecursiveLock> lock(mLock);
+        std::lock_guard<std::recursive_mutex> lock(mLock);
         auto deviceIt = info_VkDevice.find(device);
         if (deviceIt == info_VkDevice.end()) {
             return VK_ERROR_INITIALIZATION_FAILED;
@@ -2895,6 +2914,9 @@
         case VK_FORMAT_B8G8R8A8_USCALED:
             virglFormat = VIRGL_FORMAT_B8G8R8A8_UNORM;
             break;
+        case VK_FORMAT_A2R10G10B10_UNORM_PACK32:
+            virglFormat = VIRGL_FORMAT_R10G10B10A2_UNORM;
+            break;
         default:
             break;
     }
@@ -2920,7 +2942,7 @@
             return coherentMemory;
         }
         {
-            AutoLock<RecursiveLock> lock(mLock);
+            std::lock_guard<std::recursive_mutex> lock(mLock);
             auto it = info_VkDeviceMemory.find(mem);
             if (it == info_VkDeviceMemory.end()) {
                 mesa_loge("Failed to create coherent memory: failed to find device memory.");
@@ -2949,7 +2971,7 @@
                 return coherentMemory;
             }
             {
-                AutoLock<RecursiveLock> lock(mLock);
+                std::lock_guard<std::recursive_mutex> lock(mLock);
                 VirtGpuDevice* instance = VirtGpuDevice::getInstance((enum VirtGpuCapset)3);
                 createBlob.blobMem = kBlobMemHost3d;
                 createBlob.flags = kBlobFlagMappable;
@@ -3027,13 +3049,13 @@
     // Support device address capture/replay allocations
     if (deviceAddressMemoryAllocation) {
         if (allocFlagsInfoPtr) {
-            mesa_logi("%s: has alloc flags\n", __func__);
+            mesa_logd("%s: has alloc flags\n", __func__);
             allocFlagsInfo = *allocFlagsInfoPtr;
             vk_append_struct(&structChainIter, &allocFlagsInfo);
         }
 
         if (opaqueCaptureAddressAllocInfoPtr) {
-            mesa_logi("%s: has opaque capture address\n", __func__);
+            mesa_logd("%s: has opaque capture address\n", __func__);
             opaqueCaptureAddressAllocInfo = *opaqueCaptureAddressAllocInfoPtr;
             vk_append_struct(&structChainIter, &opaqueCaptureAddressAllocInfo);
         }
@@ -3045,7 +3067,7 @@
         VirtGpuDevice* instance = VirtGpuDevice::getInstance();
         struct gfxstreamPlaceholderCommandVk placeholderCmd = {};
 
-        createBlobInfo.blobId = ++mBlobId;
+        createBlobInfo.blobId = ++mAtomicId;
         createBlobInfo.blobMem = kBlobMemGuest;
         createBlobInfo.blobFlags = kBlobFlagCreateGuestHandle;
         vk_append_struct(&structChainIter, &createBlobInfo);
@@ -3073,7 +3095,7 @@
 
         guestBlob->wait();
     } else if (mCaps.vulkanCapset.deferredMapping) {
-        createBlobInfo.blobId = ++mBlobId;
+        createBlobInfo.blobId = ++mAtomicId;
         createBlobInfo.blobMem = kBlobMemHost3d;
         vk_append_struct(&structChainIter, &createBlobInfo);
     }
@@ -3116,7 +3138,7 @@
     {
         // createCoherentMemory inside need to access info_VkDeviceMemory
         // information. set it before use.
-        AutoLock<RecursiveLock> lock(mLock);
+        std::lock_guard<std::recursive_mutex> lock(mLock);
         info_VkDeviceMemory[mem] = info;
     }
 
@@ -3127,7 +3149,7 @@
 
     auto coherentMemory = createCoherentMemory(device, mem, hostAllocationInfo, enc, host_res);
     if (coherentMemory) {
-        AutoLock<RecursiveLock> lock(mLock);
+        std::lock_guard<std::recursive_mutex> lock(mLock);
         coherentMemory->subAllocate(pAllocateInfo->allocationSize, &ptr, offset);
         info.allocationSize = pAllocateInfo->allocationSize;
         info.coherentMemoryOffset = offset;
@@ -3137,7 +3159,7 @@
         *pMemory = mem;
     } else {
         enc->vkFreeMemory(device, mem, nullptr, true);
-        AutoLock<RecursiveLock> lock(mLock);
+        std::lock_guard<std::recursive_mutex> lock(mLock);
         info_VkDeviceMemory.erase(mem);
     }
     return host_res;
@@ -3165,7 +3187,7 @@
     uint8_t* ptr = nullptr;
     uint64_t offset = 0;
     {
-        AutoLock<RecursiveLock> lock(mLock);
+        std::lock_guard<std::recursive_mutex> lock(mLock);
         for (const auto& [memory, info] : info_VkDeviceMemory) {
             if (info.device != device) continue;
 
@@ -3252,13 +3274,13 @@
         vk_find_struct<VkMemoryOpaqueCaptureAddressAllocateInfo>(pAllocateInfo);
 
     if (allocFlagsInfoPtr) {
-        mesa_logi("%s: has alloc flags\n", __func__);
+        mesa_logd("%s: has alloc flags\n", __func__);
         allocFlagsInfo = *allocFlagsInfoPtr;
         vk_append_struct(&structChainIter, &allocFlagsInfo);
     }
 
     if (opaqueCaptureAddressAllocInfoPtr) {
-        mesa_logi("%s: has opaque capture address\n", __func__);
+        mesa_logd("%s: has opaque capture address\n", __func__);
         opaqueCaptureAddressAllocInfo = *opaqueCaptureAddressAllocInfoPtr;
         vk_append_struct(&structChainIter, &opaqueCaptureAddressAllocInfo);
     }
@@ -3398,7 +3420,7 @@
         VkDeviceSize allocationInfoAllocSize = finalAllocInfo.allocationSize;
 
         if (hasDedicatedImage) {
-            AutoLock<RecursiveLock> lock(mLock);
+            std::lock_guard<std::recursive_mutex> lock(mLock);
 
             auto it = info_VkImage.find(dedicatedAllocInfoPtr->image);
             if (it == info_VkImage.end())
@@ -3414,7 +3436,7 @@
         }
 
         if (hasDedicatedBuffer) {
-            AutoLock<RecursiveLock> lock(mLock);
+            std::lock_guard<std::recursive_mutex> lock(mLock);
 
             auto it = info_VkBuffer.find(dedicatedAllocInfoPtr->buffer);
             if (it == info_VkBuffer.end())
@@ -3474,7 +3496,7 @@
         fuchsia_sysmem::wire::BufferCollectionInfo2& info = result->buffer_collection_info;
         uint32_t index = importBufferCollectionInfoPtr->index;
         if (info.buffer_count < index) {
-            mesa_loge("Invalid buffer index: %d %d", index);
+            mesa_loge("Invalid buffer index: %d", index);
             _RETURN_FAILURE_WITH_DEVICE_MEMORY_REPORT(VK_ERROR_INITIALIZATION_FAILED);
         }
         vmo_handle = info.buffers[index].vmo.release();
@@ -3518,7 +3540,7 @@
         const VkBufferConstraintsInfoFUCHSIA* pBufferConstraintsInfo = nullptr;
 
         if (hasDedicatedImage) {
-            AutoLock<RecursiveLock> lock(mLock);
+            std::lock_guard<std::recursive_mutex> lock(mLock);
 
             auto it = info_VkImage.find(dedicatedAllocInfoPtr->image);
             if (it == info_VkImage.end()) return VK_ERROR_INITIALIZATION_FAILED;
@@ -3528,7 +3550,7 @@
         }
 
         if (hasDedicatedBuffer) {
-            AutoLock<RecursiveLock> lock(mLock);
+            std::lock_guard<std::recursive_mutex> lock(mLock);
 
             auto it = info_VkBuffer.find(dedicatedAllocInfoPtr->buffer);
             if (it == info_VkBuffer.end()) return VK_ERROR_INITIALIZATION_FAILED;
@@ -3769,7 +3791,7 @@
             VkImageCreateInfo imageCreateInfo;
             bool isDmaBufImage = false;
             {
-                AutoLock<RecursiveLock> lock(mLock);
+                std::lock_guard<std::recursive_mutex> lock(mLock);
 
                 auto it = info_VkImage.find(dedicatedAllocInfoPtr->image);
                 if (it == info_VkImage.end()) return VK_ERROR_INITIALIZATION_FAILED;
@@ -3819,7 +3841,7 @@
                     create3d.format = virglFormat;
                     create3d.width = imageCreateInfo.extent.width;
                     create3d.height = imageCreateInfo.extent.height;
-                    create3d.blobId = ++mBlobId;
+                    create3d.blobId = ++mAtomicId;
 
                     createBlob.blobCmd = reinterpret_cast<uint8_t*>(&create3d);
                     createBlob.blobCmdSize = sizeof(create3d);
@@ -3848,12 +3870,14 @@
                 } else {
                     bufferBlob = instance->createResource(
                         imageCreateInfo.extent.width, imageCreateInfo.extent.height,
-                        subResourceLayout.rowPitch, virglFormat, target, bind);
+                        subResourceLayout.rowPitch,
+                        subResourceLayout.rowPitch * imageCreateInfo.extent.height, virglFormat,
+                        target, bind);
                     if (!bufferBlob) {
                         mesa_loge("Failed to create colorBuffer resource for Image memory");
                         return VK_ERROR_OUT_OF_DEVICE_MEMORY;
                     }
-                    if (!bufferBlob->wait()) {
+                    if (bufferBlob->wait()) {
                         mesa_loge("Failed to wait for colorBuffer resource for Image memory");
                         return VK_ERROR_OUT_OF_DEVICE_MEMORY;
                     }
@@ -3883,7 +3907,7 @@
                 create3d.format = virglFormat;
                 create3d.width = width;
                 create3d.height = height;
-                create3d.blobId = ++mBlobId;
+                create3d.blobId = ++mAtomicId;
 
                 createBlob.blobCmd = reinterpret_cast<uint8_t*>(&create3d);
                 createBlob.blobCmdSize = sizeof(create3d);
@@ -3907,13 +3931,13 @@
 
                 bufferBlob->wait();
             } else {
-                bufferBlob =
-                    instance->createResource(width, height, width, virglFormat, target, bind);
+                bufferBlob = instance->createResource(width, height, width, width * height,
+                                                      virglFormat, target, bind);
                 if (!bufferBlob) {
                     mesa_loge("Failed to create colorBuffer resource for Image memory");
                     return VK_ERROR_OUT_OF_DEVICE_MEMORY;
                 }
-                if (!bufferBlob->wait()) {
+                if (bufferBlob->wait()) {
                     mesa_loge("Failed to wait for colorBuffer resource for Image memory");
                     return VK_ERROR_OUT_OF_DEVICE_MEMORY;
                 }
@@ -4006,7 +4030,7 @@
 
 void ResourceTracker::on_vkFreeMemory(void* context, VkDevice device, VkDeviceMemory memory,
                                       const VkAllocationCallbacks* pAllocateInfo) {
-    AutoLock<RecursiveLock> lock(mLock);
+    std::unique_lock<std::recursive_mutex> lock(mLock);
 
     auto it = info_VkDeviceMemory.find(memory);
     if (it == info_VkDeviceMemory.end()) return;
@@ -4029,7 +4053,7 @@
         zx_status_t status = zx_vmar_unmap(
             zx_vmar_root_self(), reinterpret_cast<zx_paddr_t>(info.ptr), info.allocationSize);
         if (status != ZX_OK) {
-            mesa_loge("%s: Cannot unmap ptr: status %d", status);
+            mesa_loge("%s: Cannot unmap ptr: status %d", __func__, status);
         }
         info.ptr = nullptr;
     }
@@ -4059,7 +4083,7 @@
         return host_result;
     }
 
-    AutoLock<RecursiveLock> lock(mLock);
+    std::unique_lock<std::recursive_mutex> lock(mLock);
 
     auto deviceMemoryInfoIt = info_VkDeviceMemory.find(memory);
     if (deviceMemoryInfoIt == info_VkDeviceMemory.end()) {
@@ -4132,7 +4156,7 @@
 
 void ResourceTracker::transformImageMemoryRequirements2ForGuest(VkImage image,
                                                                 VkMemoryRequirements2* reqs2) {
-    AutoLock<RecursiveLock> lock(mLock);
+    std::lock_guard<std::recursive_mutex> lock(mLock);
 
     auto it = info_VkImage.find(image);
     if (it == info_VkImage.end()) return;
@@ -4156,7 +4180,7 @@
 
 void ResourceTracker::transformBufferMemoryRequirements2ForGuest(VkBuffer buffer,
                                                                  VkMemoryRequirements2* reqs2) {
-    AutoLock<RecursiveLock> lock(mLock);
+    std::lock_guard<std::recursive_mutex> lock(mLock);
 
     auto it = info_VkBuffer.find(buffer);
     if (it == info_VkBuffer.end()) return;
@@ -4364,7 +4388,7 @@
 
     if (res != VK_SUCCESS) return res;
 
-    AutoLock<RecursiveLock> lock(mLock);
+    std::lock_guard<std::recursive_mutex> lock(mLock);
 
     auto it = info_VkImage.find(*pImage);
     if (it == info_VkImage.end()) return VK_ERROR_INITIALIZATION_FAILED;
@@ -4633,12 +4657,12 @@
 #if defined(VK_USE_PLATFORM_ANDROID_KHR) || defined(__linux__)
     if (exportSyncFd) {
         if (!mFeatureInfo->hasVirtioGpuNativeSync) {
-            mesa_logi("%s: ensure sync device\n", __func__);
+            mesa_logd("%s: ensure sync device\n", __func__);
             ensureSyncDeviceFd();
         }
 
-        mesa_logi("%s: getting fence info\n", __func__);
-        AutoLock<RecursiveLock> lock(mLock);
+        mesa_logd("%s: getting fence info\n", __func__);
+        std::lock_guard<std::recursive_mutex> lock(mLock);
         auto it = info_VkFence.find(*pFence);
 
         if (it == info_VkFence.end()) return VK_ERROR_INITIALIZATION_FAILED;
@@ -4647,7 +4671,7 @@
 
         info.external = true;
         info.exportFenceCreateInfo = *exportFenceInfoPtr;
-        mesa_logi("%s: info set (fence still -1). fence: %p\n", __func__, (void*)(*pFence));
+        mesa_logd("%s: info set (fence still -1). fence: %p\n", __func__, (void*)(*pFence));
         // syncFd is still -1 because we expect user to explicitly
         // export it via vkGetFenceFdKHR
     }
@@ -4674,7 +4698,7 @@
     // Permanence: temporary
     // on fence reset, close the fence fd
     // and act like we need to GetFenceFdKHR/ImportFenceFdKHR again
-    AutoLock<RecursiveLock> lock(mLock);
+    std::lock_guard<std::recursive_mutex> lock(mLock);
     for (uint32_t i = 0; i < fenceCount; ++i) {
         VkFence fence = pFences[i];
         auto it = info_VkFence.find(fence);
@@ -4683,7 +4707,7 @@
 
 #if GFXSTREAM_ENABLE_GUEST_GOLDFISH
         if (info.syncFd >= 0) {
-            mesa_logi("%s: resetting fence. make fd -1\n", __func__);
+            mesa_logd("%s: resetting fence. make fd -1\n", __func__);
             goldfish_sync_signal(info.syncFd);
             auto* syncHelper =
                 ResourceTracker::threadingCallbacks.hostConnectionGetFunc()->syncHelper();
@@ -4716,14 +4740,14 @@
     bool syncFdImport = pImportFenceFdInfo->handleType & VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT;
 
     if (!syncFdImport) {
-        mesa_logi("%s: VK_ERROR_OUT_OF_HOST_MEMORY: no sync fd import\n", __func__);
+        mesa_loge("%s: VK_ERROR_OUT_OF_HOST_MEMORY: no sync fd import\n", __func__);
         return VK_ERROR_OUT_OF_HOST_MEMORY;
     }
 
-    AutoLock<RecursiveLock> lock(mLock);
+    std::lock_guard<std::recursive_mutex> lock(mLock);
     auto it = info_VkFence.find(pImportFenceFdInfo->fence);
     if (it == info_VkFence.end()) {
-        mesa_logi("%s: VK_ERROR_OUT_OF_HOST_MEMORY: no fence info\n", __func__);
+        mesa_loge("%s: VK_ERROR_OUT_OF_HOST_MEMORY: no fence info\n", __func__);
         return VK_ERROR_OUT_OF_HOST_MEMORY;
     }
 
@@ -4732,17 +4756,17 @@
     auto* syncHelper = ResourceTracker::threadingCallbacks.hostConnectionGetFunc()->syncHelper();
 #if GFXSTREAM_ENABLE_GUEST_GOLDFISH
     if (info.syncFd >= 0) {
-        mesa_logi("%s: previous sync fd exists, close it\n", __func__);
+        mesa_logd("%s: previous sync fd exists, close it\n", __func__);
         goldfish_sync_signal(info.syncFd);
         syncHelper->close(info.syncFd);
     }
 #endif
 
     if (pImportFenceFdInfo->fd < 0) {
-        mesa_logi("%s: import -1, set to -1 and exit\n", __func__);
+        mesa_logd("%s: import -1, set to -1 and exit\n", __func__);
         info.syncFd = -1;
     } else {
-        mesa_logi("%s: import actual fd, dup and close()\n", __func__);
+        mesa_logd("%s: import actual fd, dup and close()\n", __func__);
         info.syncFd = syncHelper->dup(pImportFenceFdInfo->fd);
         syncHelper->close(pImportFenceFdInfo->fd);
     }
@@ -4764,7 +4788,7 @@
     bool hasFence = pGetFdInfo->fence != VK_NULL_HANDLE;
 
     if (!hasFence) {
-        mesa_logi("%s: VK_ERROR_OUT_OF_HOST_MEMORY: no fence\n", __func__);
+        mesa_loge("%s: VK_ERROR_OUT_OF_HOST_MEMORY: no fence\n", __func__);
         return VK_ERROR_OUT_OF_HOST_MEMORY;
     }
 
@@ -4772,7 +4796,7 @@
     bool syncFdExport = pGetFdInfo->handleType & VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT;
 
     if (!syncFdExport) {
-        mesa_logi("%s: VK_ERROR_OUT_OF_HOST_MEMORY: no sync fd fence\n", __func__);
+        mesa_loge("%s: VK_ERROR_OUT_OF_HOST_MEMORY: no sync fd fence\n", __func__);
         return VK_ERROR_OUT_OF_HOST_MEMORY;
     }
 
@@ -4780,7 +4804,7 @@
         enc->vkGetFenceStatus(device, pGetFdInfo->fence, true /* do lock */);
 
     if (VK_ERROR_DEVICE_LOST == currentFenceStatus) {  // Other error
-        mesa_logi("%s: VK_ERROR_DEVICE_LOST: Other error\n", __func__);
+        mesa_loge("%s: VK_ERROR_DEVICE_LOST: Other error\n", __func__);
         *pFd = -1;
         return VK_ERROR_DEVICE_LOST;
     }
@@ -4790,11 +4814,11 @@
         // fence, because ANGLE will use the returned fd directly to
         // implement eglDupNativeFenceFDANDROID, where -1 is only returned
         // when error occurs.
-        AutoLock<RecursiveLock> lock(mLock);
+        std::lock_guard<std::recursive_mutex> lock(mLock);
 
         auto it = info_VkFence.find(pGetFdInfo->fence);
         if (it == info_VkFence.end()) {
-            mesa_logi("%s: VK_ERROR_OUT_OF_HOST_MEMORY: no fence info\n", __func__);
+            mesa_loge("%s: VK_ERROR_OUT_OF_HOST_MEMORY: no fence info\n", __func__);
             return VK_ERROR_OUT_OF_HOST_MEMORY;
         }
 
@@ -4804,7 +4828,7 @@
                                                VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT);
 
         if (!syncFdCreated) {
-            mesa_logi("%s: VK_ERROR_OUT_OF_HOST_MEMORY: no sync fd created\n", __func__);
+            mesa_loge("%s: VK_ERROR_OUT_OF_HOST_MEMORY: no sync fd created\n", __func__);
             return VK_ERROR_OUT_OF_HOST_MEMORY;
         }
 
@@ -4828,7 +4852,7 @@
 
         // relinquish ownership
         info.syncFd = -1;
-        mesa_logi("%s: got fd: %d\n", __func__, *pFd);
+        mesa_logd("%s: got fd: %d\n", __func__, *pFd);
         return VK_SUCCESS;
     }
     return VK_ERROR_DEVICE_LOST;
@@ -4847,7 +4871,7 @@
     std::vector<int> fencesExternalWaitFds;
     std::vector<VkFence> fencesNonExternal;
 
-    AutoLock<RecursiveLock> lock(mLock);
+    std::unique_lock<std::recursive_mutex> lock(mLock);
 
     for (uint32_t i = 0; i < fenceCount; ++i) {
         auto it = info_VkFence.find(pFences[i]);
@@ -4872,15 +4896,15 @@
         // schedule a wait group with waitAny/waitAll
         std::vector<WorkPool::Task> tasks;
 
-        mesa_logi("%s: scheduling ext waits\n", __func__);
+        mesa_logd("%s: scheduling ext waits\n", __func__);
 
         for (auto fd : fencesExternalWaitFds) {
-            mesa_logi("%s: wait on %d\n", __func__, fd);
+            mesa_logd("%s: wait on %d\n", __func__, fd);
             tasks.push_back([fd] {
                 auto* syncHelper =
                     ResourceTracker::threadingCallbacks.hostConnectionGetFunc()->syncHelper();
                 syncHelper->wait(fd, 3000);
-                mesa_logi("done waiting on fd %d\n", fd);
+                mesa_logd("done waiting on fd %d\n", fd);
             });
         }
 
@@ -4889,7 +4913,7 @@
                 [this, fencesNonExternal /* copy of vector */, device, waitAll, timeout] {
                     auto hostConn = ResourceTracker::threadingCallbacks.hostConnectionGetFunc();
                     auto vkEncoder = ResourceTracker::threadingCallbacks.vkEncoderGetFunc(hostConn);
-                    mesa_logi("%s: vkWaitForFences to host\n", __func__);
+                    mesa_logd("%s: vkWaitForFences to host\n", __func__);
                     vkEncoder->vkWaitForFences(device, fencesNonExternal.size(),
                                                fencesNonExternal.data(), waitAll, timeout,
                                                true /* do lock */);
@@ -4907,10 +4931,10 @@
         }
 
         if (waitRes) {
-            mesa_logi("%s: VK_SUCCESS\n", __func__);
+            mesa_logd("%s: VK_SUCCESS\n", __func__);
             return VK_SUCCESS;
         } else {
-            mesa_logi("%s: VK_TIMEOUT\n", __func__);
+            mesa_loge("%s: VK_TIMEOUT\n", __func__);
             return VK_TIMEOUT;
         }
     }
@@ -5036,7 +5060,7 @@
     // (people expect VK_SUCCESS to always be returned by vkFreeDescriptorSets)
     std::vector<VkDescriptorSet> toActuallyFree;
     {
-        AutoLock<RecursiveLock> lock(mLock);
+        std::lock_guard<std::recursive_mutex> lock(mLock);
 
         // Pool was destroyed
         if (info_VkDescriptorPool.find(descriptorPool) == info_VkDescriptorPool.end()) {
@@ -5055,7 +5079,7 @@
 
             for (uint32_t i = 0; i < descriptorSetCount; ++i) {
                 if (allocedSets.end() == allocedSets.find(pDescriptorSets[i])) {
-                    mesa_logi(
+                    mesa_loge(
                         "%s: Warning: descriptor set %p not found in pool. Was this "
                         "double-freed?\n",
                         __func__, (void*)pDescriptorSets[i]);
@@ -5156,7 +5180,7 @@
 
     {
         // Validate and filter samplers
-        AutoLock<RecursiveLock> lock(mLock);
+        std::lock_guard<std::recursive_mutex> lock(mLock);
         size_t imageInfoIndex = 0;
         for (uint32_t i = 0; i < descriptorWriteCount; ++i) {
             if (!isDescriptorTypeImageInfo(transformedWrites[i].descriptorType)) continue;
@@ -5200,8 +5224,8 @@
 #ifdef VK_USE_PLATFORM_ANDROID_KHR
     auto* syncHelper = ResourceTracker::threadingCallbacks.hostConnectionGetFunc()->syncHelper();
     {
-        AutoLock<RecursiveLock> lock(mLock);  // do not guard encoder may cause
-                                              // deadlock b/243339973
+        std::lock_guard<std::recursive_mutex> lock(mLock);  // do not guard encoder may cause
+                                                            // deadlock b/243339973
 
         // Wait for any pending QSRIs to prevent a race between the Gfxstream host
         // potentially processing the below `vkDestroyImage()` from the VK encoder
@@ -5238,7 +5262,7 @@
 
 void ResourceTracker::on_vkGetImageMemoryRequirements(void* context, VkDevice device, VkImage image,
                                                       VkMemoryRequirements* pMemoryRequirements) {
-    AutoLock<RecursiveLock> lock(mLock);
+    std::unique_lock<std::recursive_mutex> lock(mLock);
 
     auto it = info_VkImage.find(image);
     if (it == info_VkImage.end()) return;
@@ -5377,7 +5401,7 @@
     }
 
 #ifdef VK_USE_PLATFORM_FUCHSIA
-    Optional<zx::vmo> vmo;
+    std::optional<zx::vmo> vmo;
     bool isSysmemBackedMemory = false;
 
     if (extBufCiPtr &&
@@ -5398,7 +5422,7 @@
         if (result.ok() && result->status == ZX_OK) {
             auto& info = result->buffer_collection_info;
             if (index < info.buffer_count) {
-                vmo = gfxstream::guest::makeOptional(std::move(info.buffers[index].vmo));
+                vmo = std::make_optional<zx::vmo>(std::move(info.buffers[index].vmo));
             }
         } else {
             mesa_loge("WaitForBuffersAllocated failed: %d %d", result.status(),
@@ -5447,7 +5471,7 @@
     }
 #endif
 
-    AutoLock<RecursiveLock> lock(mLock);
+    std::lock_guard<std::recursive_mutex> lock(mLock);
 
     auto it = info_VkBuffer.find(*pBuffer);
     if (it == info_VkBuffer.end()) return VK_ERROR_INITIALIZATION_FAILED;
@@ -5485,7 +5509,7 @@
 void ResourceTracker::on_vkGetBufferMemoryRequirements(void* context, VkDevice device,
                                                        VkBuffer buffer,
                                                        VkMemoryRequirements* pMemoryRequirements) {
-    AutoLock<RecursiveLock> lock(mLock);
+    std::unique_lock<std::recursive_mutex> lock(mLock);
 
     auto it = info_VkBuffer.find(buffer);
     if (it == info_VkBuffer.end()) return;
@@ -5595,7 +5619,7 @@
     }
 #endif
 
-    AutoLock<RecursiveLock> lock(mLock);
+    std::lock_guard<std::recursive_mutex> lock(mLock);
 
     auto it = info_VkSemaphore.find(*pSemaphore);
     if (it == info_VkSemaphore.end()) return VK_ERROR_INITIALIZATION_FAILED;
@@ -5610,7 +5634,8 @@
 
 #if defined(VK_USE_PLATFORM_ANDROID_KHR) || defined(__linux__)
     if (exportSyncFd) {
-        if (mFeatureInfo->hasVirtioGpuNativeSync) {
+        if (mFeatureInfo->hasVirtioGpuNativeSync &&
+            !(mCaps.params[kParamFencePassing] && mCaps.vulkanCapset.externalSync)) {
             VkResult result;
             int64_t osHandle;
             uint64_t hostFenceHandle = get_host_u64_VkSemaphore(*pSemaphore);
@@ -5658,15 +5683,39 @@
     bool getSyncFd = pGetFdInfo->handleType & VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
 
     if (getSyncFd) {
-        AutoLock<RecursiveLock> lock(mLock);
-        auto it = info_VkSemaphore.find(pGetFdInfo->semaphore);
-        if (it == info_VkSemaphore.end()) return VK_ERROR_OUT_OF_HOST_MEMORY;
-        auto& semInfo = it->second;
-        // syncFd is supposed to have value.
-        auto* syncHelper =
-            ResourceTracker::threadingCallbacks.hostConnectionGetFunc()->syncHelper();
-        *pFd = syncHelper->dup(semInfo.syncFd.value_or(-1));
-        return VK_SUCCESS;
+        if (mCaps.params[kParamFencePassing] && mCaps.vulkanCapset.externalSync) {
+            uint64_t syncId = ++mAtomicId;
+            int64_t osHandle = -1;
+
+            VkResult result = enc->vkGetSemaphoreGOOGLE(device, pGetFdInfo->semaphore, syncId,
+                                                        true /* do lock */);
+            if (result != VK_SUCCESS) {
+                ALOGE("unable to get the semaphore");
+                return result;
+            }
+
+            result = acquireSync(syncId, osHandle);
+            if (result != VK_SUCCESS) {
+                ALOGE("unable to create host sync object");
+                return result;
+            }
+
+            *pFd = (int)osHandle;
+            return VK_SUCCESS;
+        } else {
+            // Doesn't this assume that sync file descriptor generated via the non-fence
+            // passing path during "on_vkCreateSemaphore" is the same one that would be
+            // generated via guest's "okGetSemaphoreFdKHR" call?
+            std::lock_guard<std::recursive_mutex> lock(mLock);
+            auto it = info_VkSemaphore.find(pGetFdInfo->semaphore);
+            if (it == info_VkSemaphore.end()) return VK_ERROR_OUT_OF_HOST_MEMORY;
+            auto& semInfo = it->second;
+            // syncFd is supposed to have value.
+            auto* syncHelper =
+                ResourceTracker::threadingCallbacks.hostConnectionGetFunc()->syncHelper();
+            *pFd = syncHelper->dup(semInfo.syncFd.value_or(-1));
+            return VK_SUCCESS;
+        }
     } else {
         // opaque fd
         int hostFd = 0;
@@ -5701,7 +5750,7 @@
     if (pImportSemaphoreFdInfo->handleType & VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT) {
         VkImportSemaphoreFdInfoKHR tmpInfo = *pImportSemaphoreFdInfo;
 
-        AutoLock<RecursiveLock> lock(mLock);
+        std::lock_guard<std::recursive_mutex> lock(mLock);
 
         auto semaphoreIt = info_VkSemaphore.find(pImportSemaphoreFdInfo->semaphore);
         auto& info = semaphoreIt->second;
@@ -5746,7 +5795,7 @@
         return VK_ERROR_INVALID_EXTERNAL_HANDLE;
     }
     // Sanity-check device
-    AutoLock<RecursiveLock> lock(mLock);
+    std::lock_guard<std::recursive_mutex> lock(mLock);
     auto deviceIt = info_VkDevice.find(device);
     if (deviceIt == info_VkDevice.end()) {
         return VK_ERROR_OUT_OF_HOST_MEMORY;
@@ -5785,7 +5834,7 @@
         return VK_ERROR_OUT_OF_HOST_MEMORY;
     }
     // Sanity-check device
-    AutoLock<RecursiveLock> lock(mLock);
+    std::lock_guard<std::recursive_mutex> lock(mLock);
     auto deviceIt = info_VkDevice.find(device);
     if (deviceIt == info_VkDevice.end()) {
         return VK_ERROR_OUT_OF_HOST_MEMORY;
@@ -5936,7 +5985,36 @@
 VkResult ResourceTracker::on_vkQueueSubmit(void* context, VkResult input_result, VkQueue queue,
                                            uint32_t submitCount, const VkSubmitInfo* pSubmits,
                                            VkFence fence) {
-    AEMU_SCOPED_TRACE("on_vkQueueSubmit");
+    MESA_TRACE_SCOPE("on_vkQueueSubmit");
+
+    /* From the Vulkan 1.3.204 spec:
+     *
+     *    VUID-VkSubmitInfo-pNext-03240
+     *
+     *    "If the pNext chain of this structure includes a VkTimelineSemaphoreSubmitInfo structure
+     *    and any element of pSignalSemaphores was created with a VkSemaphoreType of
+     *    VK_SEMAPHORE_TYPE_TIMELINE, then its signalSemaphoreValueCount member must equal
+     *    signalSemaphoreCount"
+     *
+     * Internally, Mesa WSI creates placeholder semaphores/fences (see transformVkSemaphore functions
+     * in in gfxstream_vk_private.cpp).  We don't want to forward that to the host, since there is
+     * no host side Vulkan object associated with the placeholder sync objects.
+     *
+     * The way to test this behavior is Zink + glxgears, on Linux hosts.  It should fail without
+     * this check.
+     */
+    for (uint32_t i = 0; i < submitCount; i++) {
+        VkTimelineSemaphoreSubmitInfo* tssi = const_cast<VkTimelineSemaphoreSubmitInfo*>(
+            vk_find_struct<VkTimelineSemaphoreSubmitInfo>(&pSubmits[i]));
+
+        if (tssi) {
+            uint32_t count = getSignalSemaphoreCount(pSubmits[i]);
+            if (count != tssi->signalSemaphoreValueCount) {
+                tssi->signalSemaphoreValueCount = count;
+            }
+        }
+    }
+
     return on_vkQueueSubmitTemplate<VkSubmitInfo>(context, input_result, queue, submitCount,
                                                   pSubmits, fence);
 }
@@ -5944,7 +6022,7 @@
 VkResult ResourceTracker::on_vkQueueSubmit2(void* context, VkResult input_result, VkQueue queue,
                                             uint32_t submitCount, const VkSubmitInfo2* pSubmits,
                                             VkFence fence) {
-    AEMU_SCOPED_TRACE("on_vkQueueSubmit2");
+    MESA_TRACE_SCOPE("on_vkQueueSubmit2");
     return on_vkQueueSubmitTemplate<VkSubmitInfo2>(context, input_result, queue, submitCount,
                                                    pSubmits, fence);
 }
@@ -5984,7 +6062,7 @@
 
     VkEncoder* enc = (VkEncoder*)context;
 
-    AutoLock<RecursiveLock> lock(mLock);
+    std::unique_lock<std::recursive_mutex> lock(mLock);
 
     for (uint32_t i = 0; i < submitCount; ++i) {
         for (uint32_t j = 0; j < getWaitSemaphoreCount(pSubmits[i]); ++j) {
@@ -6104,7 +6182,7 @@
             auto vkEncoder = ResourceTracker::threadingCallbacks.vkEncoderGetFunc(hostConn);
             auto waitIdleRes = vkEncoder->vkQueueWaitIdle(queue, true /* do lock */);
 #ifdef VK_USE_PLATFORM_FUCHSIA
-            AEMU_SCOPED_TRACE("on_vkQueueSubmit::SignalSemaphores");
+            MESA_TRACE_SCOPE("on_vkQueueSubmit::SignalSemaphores");
             (void)externalFenceFdToSignal;
             for (auto& [event, koid] : post_wait_events) {
 #ifndef FUCHSIA_NO_TRACE
@@ -6122,7 +6200,8 @@
             }
 
             if (externalFenceFdToSignal >= 0) {
-                mesa_logi("%s: external fence real signal: %d\n", __func__, externalFenceFdToSignal);
+                mesa_logd("%s: external fence real signal: %d\n", __func__,
+                          externalFenceFdToSignal);
                 goldfish_sync_signal(externalFenceFdToSignal);
             }
 #endif
@@ -6137,18 +6216,18 @@
 VkResult ResourceTracker::on_vkQueueWaitIdle(void* context, VkResult, VkQueue queue) {
     VkEncoder* enc = (VkEncoder*)context;
 
-    AutoLock<RecursiveLock> lock(mLock);
+    std::unique_lock<std::recursive_mutex> lock(mLock);
     std::vector<WorkPool::WaitGroupHandle> toWait = mQueueSensitiveWorkPoolItems[queue];
     mQueueSensitiveWorkPoolItems[queue].clear();
     lock.unlock();
 
     if (toWait.empty()) {
-        mesa_logi("%s: No queue-specific work pool items\n", __func__);
+        mesa_logd("%s: No queue-specific work pool items\n", __func__);
         return enc->vkQueueWaitIdle(queue, true /* do lock */);
     }
 
     for (auto handle : toWait) {
-        mesa_logi("%s: waiting on work group item: %llu\n", __func__, (unsigned long long)handle);
+        mesa_logd("%s: waiting on work group item: %llu\n", __func__, (unsigned long long)handle);
         mWorkPool.waitAll(handle);
     }
 
@@ -6208,7 +6287,7 @@
 #ifdef VK_USE_PLATFORM_ANDROID_KHR
     (void)fd_out;
     if (fd != -1) {
-        AEMU_SCOPED_TRACE("waitNativeFenceInAcquire");
+        MESA_TRACE_SCOPE("waitNativeFenceInAcquire");
         // Implicit Synchronization
         auto* syncHelper =
             ResourceTracker::threadingCallbacks.hostConnectionGetFunc()->syncHelper();
@@ -6273,7 +6352,7 @@
 VkResult ResourceTracker::on_vkMapMemoryIntoAddressSpaceGOOGLE_pre(void*, VkResult, VkDevice,
                                                                    VkDeviceMemory memory,
                                                                    uint64_t* pAddress) {
-    AutoLock<RecursiveLock> lock(mLock);
+    std::lock_guard<std::recursive_mutex> lock(mLock);
 
     auto it = info_VkDeviceMemory.find(memory);
     if (it == info_VkDeviceMemory.end()) {
@@ -6312,7 +6391,7 @@
 VkResult ResourceTracker::initDescriptorUpdateTemplateBuffers(
     const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo,
     VkDescriptorUpdateTemplate descriptorUpdateTemplate) {
-    AutoLock<RecursiveLock> lock(mLock);
+    std::lock_guard<std::recursive_mutex> lock(mLock);
 
     auto it = info_VkDescriptorUpdateTemplate.find(descriptorUpdateTemplate);
     if (it == info_VkDescriptorUpdateTemplate.end()) {
@@ -6443,7 +6522,7 @@
     if (!userBuffer) return;
 
     // TODO: Make this thread safe
-    AutoLock<RecursiveLock> lock(mLock);
+    std::unique_lock<std::recursive_mutex> lock(mLock);
 
     auto it = info_VkDescriptorUpdateTemplate.find(descriptorUpdateTemplate);
     if (it == info_VkDescriptorUpdateTemplate.end()) {
@@ -6817,18 +6896,18 @@
 
 void ResourceTracker::registerEncoderCleanupCallback(const VkEncoder* encoder, void* object,
                                                      CleanupCallback callback) {
-    AutoLock<RecursiveLock> lock(mLock);
+    std::lock_guard<std::recursive_mutex> lock(mLock);
     auto& callbacks = mEncoderCleanupCallbacks[encoder];
     callbacks[object] = callback;
 }
 
 void ResourceTracker::unregisterEncoderCleanupCallback(const VkEncoder* encoder, void* object) {
-    AutoLock<RecursiveLock> lock(mLock);
+    std::lock_guard<std::recursive_mutex> lock(mLock);
     mEncoderCleanupCallbacks[encoder].erase(object);
 }
 
 void ResourceTracker::onEncoderDeleted(const VkEncoder* encoder) {
-    AutoLock<RecursiveLock> lock(mLock);
+    std::unique_lock<std::recursive_mutex> lock(mLock);
     if (mEncoderCleanupCallbacks.find(encoder) == mEncoderCleanupCallbacks.end()) return;
 
     std::unordered_map<void*, CleanupCallback> callbackCopies = mEncoderCleanupCallbacks[encoder];
@@ -6865,7 +6944,7 @@
             // VkDeviceMemory filled in by getCoherentMemory()
             // scope of mLock
             {
-                AutoLock<RecursiveLock> lock(mLock);
+                std::lock_guard<std::recursive_mutex> lock(mLock);
                 const auto it = info_VkDeviceMemory.find(vkDeviceMem);
                 if (it == info_VkDeviceMemory.end()) {
                     mesa_loge("Coherent memory allocated %u not found", result);
@@ -6887,7 +6966,7 @@
             // for suballocations, deviceMemory is a alias VkDeviceMemory hand;
             // freeCoherentMemoryLocked maps the alias to the backing VkDeviceMemory
             VkDeviceMemory deviceMemory = memory.deviceMemory;
-            AutoLock<RecursiveLock> lock(mLock);
+            std::unique_lock<std::recursive_mutex> lock(mLock);
             auto it = info_VkDeviceMemory.find(deviceMemory);
             if (it == info_VkDeviceMemory.end()) {
                 mesa_loge("Device memory to free not found");
@@ -6981,7 +7060,7 @@
 
 #if defined(VK_USE_PLATFORM_ANDROID_KHR)
     if (pCreateInfo->format == VK_FORMAT_UNDEFINED) {
-        AutoLock<RecursiveLock> lock(mLock);
+        std::lock_guard<std::recursive_mutex> lock(mLock);
 
         auto it = info_VkImage.find(pCreateInfo->image);
         if (it != info_VkImage.end() && it->second.hasExternalFormat) {
@@ -7113,8 +7192,8 @@
 
 #if defined(VK_USE_PLATFORM_ANDROID_KHR)
 VkResult ResourceTracker::exportSyncFdForQSRILocked(VkImage image, int* fd) {
-    mesa_logi("%s: call for image %p hos timage handle 0x%llx\n", __func__, (void*)image,
-          (unsigned long long)get_host_u64_VkImage(image));
+    mesa_logd("%s: call for image %p hos timage handle 0x%llx\n", __func__, (void*)image,
+              (unsigned long long)get_host_u64_VkImage(image));
 
     if (mFeatureInfo->hasVirtioGpuNativeSync) {
         struct VirtGpuExecBuffer exec = {};
@@ -7142,7 +7221,7 @@
 #endif
     }
 
-    mesa_logi("%s: got fd: %d\n", __func__, *fd);
+    mesa_logd("%s: got fd: %d\n", __func__, *fd);
     auto imageInfoIt = info_VkImage.find(image);
     if (imageInfoIt != info_VkImage.end()) {
         auto& imageInfo = imageInfoIt->second;
@@ -7195,7 +7274,7 @@
     }
 
     {
-        AutoLock<RecursiveLock> lock(mLock);
+        std::lock_guard<std::recursive_mutex> lock(mLock);
         auto it = info_VkImage.find(image);
         if (it == info_VkImage.end()) {
             if (pNativeFenceFd) *pNativeFenceFd = -1;
@@ -7206,7 +7285,7 @@
     enc->vkQueueSignalReleaseImageANDROIDAsyncGOOGLE(queue, waitSemaphoreCount, pWaitSemaphores,
                                                      image, true /* lock */);
 
-    AutoLock<RecursiveLock> lock(mLock);
+    std::lock_guard<std::recursive_mutex> lock(mLock);
     VkResult result;
     if (pNativeFenceFd) {
         result = exportSyncFdForQSRILocked(image, pNativeFenceFd);
@@ -7297,8 +7376,8 @@
                                           true /* do lock */);
 }
 
-uint32_t ResourceTracker::getApiVersionFromInstance(VkInstance instance) const {
-    AutoLock<RecursiveLock> lock(mLock);
+uint32_t ResourceTracker::getApiVersionFromInstance(VkInstance instance) {
+    std::lock_guard<std::recursive_mutex> lock(mLock);
     uint32_t api = kDefaultApiVersion;
 
     auto it = info_VkInstance.find(instance);
@@ -7309,8 +7388,8 @@
     return api;
 }
 
-uint32_t ResourceTracker::getApiVersionFromDevice(VkDevice device) const {
-    AutoLock<RecursiveLock> lock(mLock);
+uint32_t ResourceTracker::getApiVersionFromDevice(VkDevice device) {
+    std::lock_guard<std::recursive_mutex> lock(mLock);
 
     uint32_t api = kDefaultApiVersion;
 
@@ -7322,8 +7401,8 @@
     return api;
 }
 
-bool ResourceTracker::hasInstanceExtension(VkInstance instance, const std::string& name) const {
-    AutoLock<RecursiveLock> lock(mLock);
+bool ResourceTracker::hasInstanceExtension(VkInstance instance, const std::string& name) {
+    std::lock_guard<std::recursive_mutex> lock(mLock);
 
     auto it = info_VkInstance.find(instance);
     if (it == info_VkInstance.end()) return false;
@@ -7331,8 +7410,8 @@
     return it->second.enabledExtensions.find(name) != it->second.enabledExtensions.end();
 }
 
-bool ResourceTracker::hasDeviceExtension(VkDevice device, const std::string& name) const {
-    AutoLock<RecursiveLock> lock(mLock);
+bool ResourceTracker::hasDeviceExtension(VkDevice device, const std::string& name) {
+    std::lock_guard<std::recursive_mutex> lock(mLock);
 
     auto it = info_VkDevice.find(device);
     if (it == info_VkDevice.end()) return false;
@@ -7448,7 +7527,7 @@
     void* context, VkDevice device, VkPhysicalDevice physicalDevice) {
     if (!mCachedPhysicalDeviceMemoryProps) {
         if (physicalDevice == VK_NULL_HANDLE) {
-            AutoLock<RecursiveLock> lock(mLock);
+            std::lock_guard<std::recursive_mutex> lock(mLock);
 
             auto deviceInfoIt = info_VkDevice.find(device);
             if (deviceInfoIt == info_VkDevice.end()) {
diff --git a/guest/vulkan_enc/ResourceTracker.h b/guest/vulkan_enc/ResourceTracker.h
index 005887b..fc4d9b0 100644
--- a/guest/vulkan_enc/ResourceTracker.h
+++ b/guest/vulkan_enc/ResourceTracker.h
@@ -19,6 +19,7 @@
 #include <atomic>
 #include <functional>
 #include <memory>
+#include <mutex>
 #include <optional>
 #include <set>
 #include <unordered_map>
@@ -28,16 +29,10 @@
 #include "VirtGpu.h"
 #include "VulkanHandleMapping.h"
 #include "VulkanHandles.h"
-#include "aemu/base/Optional.h"
-#include "aemu/base/Tracing.h"
-#include "aemu/base/synchronization/AndroidLock.h"
 #include "aemu/base/threads/AndroidWorkPool.h"
 #include "goldfish_vk_transform_guest.h"
+#include "util/perf/cpu_trace.h"
 
-using gfxstream::guest::AutoLock;
-using gfxstream::guest::Lock;
-using gfxstream::guest::Optional;
-using gfxstream::guest::RecursiveLock;
 using gfxstream::guest::WorkPool;
 
 /// Use installed headers or locally defined Fuchsia-specific bits
@@ -533,7 +528,7 @@
     uint8_t* getMappedPointer(VkDeviceMemory memory);
     VkDeviceSize getMappedSize(VkDeviceMemory memory);
     VkDeviceSize getNonCoherentExtendedSize(VkDevice device, VkDeviceSize basicSize) const;
-    bool isValidMemoryRange(const VkMappedMemoryRange& range) const;
+    bool isValidMemoryRange(const VkMappedMemoryRange& range);
 
     void setupFeatures(const EmulatorFeatureInfo* features);
     void setupCaps(uint32_t& noRenderControlEnc);
@@ -542,10 +537,10 @@
     bool hostSupportsVulkan() const;
     bool usingDirectMapping() const;
     uint32_t getStreamFeatures() const;
-    uint32_t getApiVersionFromInstance(VkInstance instance) const;
-    uint32_t getApiVersionFromDevice(VkDevice device) const;
-    bool hasInstanceExtension(VkInstance instance, const std::string& name) const;
-    bool hasDeviceExtension(VkDevice instance, const std::string& name) const;
+    uint32_t getApiVersionFromInstance(VkInstance instance);
+    uint32_t getApiVersionFromDevice(VkDevice device);
+    bool hasInstanceExtension(VkInstance instance, const std::string& name);
+    bool hasDeviceExtension(VkDevice instance, const std::string& name);
     VkDevice getDevice(VkCommandBuffer commandBuffer) const;
     void addToCommandPool(VkCommandPool commandPool, uint32_t commandBufferCount,
                           VkCommandBuffer* pCommandBuffers);
@@ -861,8 +856,8 @@
 
     struct VkBufferCollectionFUCHSIA_Info {
 #ifdef VK_USE_PLATFORM_FUCHSIA
-        gfxstream::guest::Optional<fuchsia_sysmem::wire::BufferCollectionConstraints> constraints;
-        gfxstream::guest::Optional<VkBufferCollectionPropertiesFUCHSIA> properties;
+        std::optional<fuchsia_sysmem::wire::BufferCollectionConstraints> constraints;
+        std::optional<VkBufferCollectionPropertiesFUCHSIA> properties;
 
         // the index of corresponding createInfo for each image format
         // constraints in |constraints|.
@@ -879,7 +874,7 @@
     void transformImageMemoryRequirementsForGuestLocked(VkImage image, VkMemoryRequirements* reqs);
     CoherentMemoryPtr freeCoherentMemoryLocked(VkDeviceMemory memory, VkDeviceMemory_Info& info);
 
-    mutable RecursiveLock mLock;
+    std::recursive_mutex mLock;
 
     std::optional<const VkPhysicalDeviceMemoryProperties> mCachedPhysicalDeviceMemoryProps;
     std::unique_ptr<EmulatorFeatureInfo> mFeatureInfo;
@@ -892,7 +887,7 @@
     std::vector<VkExtensionProperties> mHostDeviceExtensions;
 
     // 32 bits only for now, upper bits may be used later.
-    std::atomic<uint32_t> mBlobId = 0;
+    std::atomic<uint32_t> mAtomicId = 0;
 #if defined(VK_USE_PLATFORM_ANDROID_KHR) || defined(__linux__)
     int mSyncDeviceFd = -1;
 #endif
diff --git a/guest/vulkan_enc/VkEncoder.cpp b/guest/vulkan_enc/VkEncoder.cpp
index 5cd3218..0e41d65 100644
--- a/guest/vulkan_enc/VkEncoder.cpp
+++ b/guest/vulkan_enc/VkEncoder.cpp
@@ -24732,16 +24732,6 @@
 }
 
 #endif
-#ifdef VK_KHR_surface
-#endif
-#ifdef VK_KHR_swapchain
-#endif
-#ifdef VK_KHR_xcb_surface
-#endif
-#ifdef VK_KHR_android_surface
-#endif
-#ifdef VK_KHR_win32_surface
-#endif
 #ifdef VK_KHR_dynamic_rendering
 void VkEncoder::vkCmdBeginRenderingKHR(VkCommandBuffer commandBuffer,
                                        const VkRenderingInfo* pRenderingInfo, uint32_t doLock) {
@@ -25982,12 +25972,6 @@
 }
 
 #endif
-#ifdef VK_KHR_external_memory
-#endif
-#ifdef VK_KHR_external_memory_win32
-#endif
-#ifdef VK_KHR_external_memory_fd
-#endif
 #ifdef VK_KHR_external_semaphore_capabilities
 void VkEncoder::vkGetPhysicalDeviceExternalSemaphorePropertiesKHR(
     VkPhysicalDevice physicalDevice,
@@ -26116,10 +26100,6 @@
 }
 
 #endif
-#ifdef VK_KHR_external_semaphore
-#endif
-#ifdef VK_KHR_external_semaphore_win32
-#endif
 #ifdef VK_KHR_external_semaphore_fd
 VkResult VkEncoder::vkImportSemaphoreFdKHR(VkDevice device,
                                            const VkImportSemaphoreFdInfoKHR* pImportSemaphoreFdInfo,
@@ -26331,10 +26311,6 @@
 }
 
 #endif
-#ifdef VK_KHR_shader_float16_int8
-#endif
-#ifdef VK_KHR_incremental_present
-#endif
 #ifdef VK_KHR_descriptor_update_template
 VkResult VkEncoder::vkCreateDescriptorUpdateTemplateKHR(
     VkDevice device, const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo,
@@ -26736,8 +26712,6 @@
 }
 
 #endif
-#ifdef VK_KHR_imageless_framebuffer
-#endif
 #ifdef VK_KHR_create_renderpass2
 VkResult VkEncoder::vkCreateRenderPass2KHR(VkDevice device,
                                            const VkRenderPassCreateInfo2* pCreateInfo,
@@ -27321,8 +27295,6 @@
 }
 
 #endif
-#ifdef VK_KHR_external_fence
-#endif
 #ifdef VK_KHR_external_fence_fd
 VkResult VkEncoder::vkImportFenceFdKHR(VkDevice device,
                                        const VkImportFenceFdInfoKHR* pImportFenceFdInfo,
@@ -27528,12 +27500,6 @@
 }
 
 #endif
-#ifdef VK_KHR_maintenance2
-#endif
-#ifdef VK_KHR_dedicated_allocation
-#endif
-#ifdef VK_KHR_storage_buffer_storage_class
-#endif
 #ifdef VK_KHR_get_memory_requirements2
 void VkEncoder::vkGetImageMemoryRequirements2KHR(VkDevice device,
                                                  const VkImageMemoryRequirementsInfo2* pInfo,
@@ -27945,8 +27911,6 @@
 }
 
 #endif
-#ifdef VK_KHR_image_format_list
-#endif
 #ifdef VK_KHR_sampler_ycbcr_conversion
 VkResult VkEncoder::vkCreateSamplerYcbcrConversionKHR(
     VkDevice device, const VkSamplerYcbcrConversionCreateInfo* pCreateInfo,
@@ -28570,12 +28534,6 @@
 }
 
 #endif
-#ifdef VK_KHR_shader_subgroup_extended_types
-#endif
-#ifdef VK_KHR_vulkan_memory_model
-#endif
-#ifdef VK_KHR_shader_terminate_invocation
-#endif
 #ifdef VK_KHR_buffer_device_address
 VkDeviceAddress VkEncoder::vkGetBufferDeviceAddressKHR(VkDevice device,
                                                        const VkBufferDeviceAddressInfo* pInfo,
@@ -29427,10 +29385,6 @@
 }
 
 #endif
-#ifdef VK_KHR_shader_integer_dot_product
-#endif
-#ifdef VK_KHR_shader_non_semantic_info
-#endif
 #ifdef VK_KHR_synchronization2
 void VkEncoder::vkCmdSetEvent2KHR(VkCommandBuffer commandBuffer, VkEvent event,
                                   const VkDependencyInfo* pDependencyInfo, uint32_t doLock) {
@@ -30299,8 +30253,6 @@
 }
 
 #endif
-#ifdef VK_KHR_zero_initialize_workgroup_memory
-#endif
 #ifdef VK_KHR_copy_commands2
 void VkEncoder::vkCmdCopyBuffer2KHR(VkCommandBuffer commandBuffer,
                                     const VkCopyBufferInfo2* pCopyBufferInfo, uint32_t doLock) {
@@ -30862,8 +30814,6 @@
 }
 
 #endif
-#ifdef VK_KHR_format_feature_flags2
-#endif
 #ifdef VK_KHR_maintenance4
 void VkEncoder::vkGetDeviceBufferMemoryRequirementsKHR(
     VkDevice device, const VkDeviceBufferMemoryRequirements* pInfo,
@@ -32181,8 +32131,6 @@
 }
 
 #endif
-#ifdef VK_EXT_debug_report
-#endif
 #ifdef VK_EXT_transform_feedback
 void VkEncoder::vkCmdBindTransformFeedbackBuffersEXT(VkCommandBuffer commandBuffer,
                                                      uint32_t firstBinding, uint32_t bindingCount,
@@ -32894,38 +32842,6 @@
 }
 
 #endif
-#ifdef VK_AMD_gpu_shader_half_float
-#endif
-#ifdef VK_EXT_texture_compression_astc_hdr
-#endif
-#ifdef VK_EXT_depth_clip_enable
-#endif
-#ifdef VK_EXT_swapchain_colorspace
-#endif
-#ifdef VK_EXT_queue_family_foreign
-#endif
-#ifdef VK_EXT_debug_utils
-#endif
-#ifdef VK_ANDROID_external_memory_android_hardware_buffer
-#endif
-#ifdef VK_EXT_inline_uniform_block
-#endif
-#ifdef VK_EXT_shader_stencil_export
-#endif
-#ifdef VK_EXT_vertex_attribute_divisor
-#endif
-#ifdef VK_EXT_pipeline_creation_feedback
-#endif
-#ifdef VK_NV_shader_subgroup_partitioned
-#endif
-#ifdef VK_EXT_metal_surface
-#endif
-#ifdef VK_EXT_fragment_density_map
-#endif
-#ifdef VK_EXT_scalar_block_layout
-#endif
-#ifdef VK_EXT_subgroup_size_control
-#endif
 #ifdef VK_EXT_tooling_info
 VkResult VkEncoder::vkGetPhysicalDeviceToolPropertiesEXT(
     VkPhysicalDevice physicalDevice, uint32_t* pToolCount,
@@ -33086,10 +33002,6 @@
 }
 
 #endif
-#ifdef VK_EXT_validation_features
-#endif
-#ifdef VK_EXT_provoking_vertex
-#endif
 #ifdef VK_EXT_line_rasterization
 void VkEncoder::vkCmdSetLineStippleEXT(VkCommandBuffer commandBuffer, uint32_t lineStippleFactor,
                                        uint16_t lineStipplePattern, uint32_t doLock) {
@@ -33179,8 +33091,6 @@
 }
 
 #endif
-#ifdef VK_EXT_index_type_uint8
-#endif
 #ifdef VK_EXT_extended_dynamic_state
 void VkEncoder::vkCmdSetCullModeEXT(VkCommandBuffer commandBuffer, VkCullModeFlags cullMode,
                                     uint32_t doLock) {
@@ -34852,18 +34762,6 @@
 }
 
 #endif
-#ifdef VK_EXT_swapchain_maintenance1
-#endif
-#ifdef VK_EXT_shader_demote_to_helper_invocation
-#endif
-#ifdef VK_EXT_texel_buffer_alignment
-#endif
-#ifdef VK_EXT_device_memory_report
-#endif
-#ifdef VK_EXT_robustness2
-#endif
-#ifdef VK_EXT_custom_border_color
-#endif
 #ifdef VK_EXT_private_data
 VkResult VkEncoder::vkCreatePrivateDataSlotEXT(VkDevice device,
                                                const VkPrivateDataSlotCreateInfo* pCreateInfo,
@@ -35333,22 +35231,6 @@
 }
 
 #endif
-#ifdef VK_EXT_pipeline_creation_cache_control
-#endif
-#ifdef VK_EXT_metal_objects
-#endif
-#ifdef VK_EXT_graphics_pipeline_library
-#endif
-#ifdef VK_EXT_ycbcr_2plane_444_formats
-#endif
-#ifdef VK_EXT_image_robustness
-#endif
-#ifdef VK_EXT_image_compression_control
-#endif
-#ifdef VK_EXT_4444_formats
-#endif
-#ifdef VK_EXT_primitive_topology_list_restart
-#endif
 #ifdef VK_EXT_extended_dynamic_state2
 void VkEncoder::vkCmdSetPatchControlPointsEXT(VkCommandBuffer commandBuffer,
                                               uint32_t patchControlPoints, uint32_t doLock) {
@@ -38926,13 +38808,103 @@
     if (!queueSubmitWithCommandsEnabled && doLock) this->unlock();
 }
 
-#endif
-#ifdef VK_EXT_load_store_op_none
-#endif
-#ifdef VK_EXT_image_compression_control_swapchain
-#endif
-#ifdef VK_QNX_external_memory_screen_buffer
-#endif
+VkResult VkEncoder::vkGetSemaphoreGOOGLE(VkDevice device, VkSemaphore semaphore, uint64_t syncId,
+                                         uint32_t doLock) {
+    std::optional<uint32_t> healthMonitorAnnotation_seqno = std::nullopt;
+    std::optional<uint32_t> healthMonitorAnnotation_packetSize = std::nullopt;
+    std::vector<uint8_t> healthMonitorAnnotation_packetContents;
 
+    auto watchdog =
+        WATCHDOG_BUILDER(mHealthMonitor, "vkGetSemaphoreGOOGLE in VkEncoder")
+            .setOnHangCallback([&]() {
+                auto annotations = std::make_unique<EventHangMetadata::HangAnnotations>();
+                if (healthMonitorAnnotation_seqno) {
+                    annotations->insert(
+                        {{"seqno", std::to_string(healthMonitorAnnotation_seqno.value())}});
+                }
+                if (healthMonitorAnnotation_packetSize) {
+                    annotations->insert(
+                        {{"packetSize",
+                          std::to_string(healthMonitorAnnotation_packetSize.value())}});
+                }
+                if (!healthMonitorAnnotation_packetContents.empty()) {
+                    annotations->insert(
+                        {{"packetContents",
+                          getPacketContents(&healthMonitorAnnotation_packetContents[0],
+                                            healthMonitorAnnotation_packetContents.size())}});
+                }
+                return std::move(annotations);
+            })
+            .build();
+
+    ENCODER_DEBUG_LOG("vkGetSemaphoreGOOGLE(device:%p, semaphore:%p, syncId:%ld)", device,
+                      semaphore, syncId);
+    (void)doLock;
+    bool queueSubmitWithCommandsEnabled =
+        sFeatureBits & VULKAN_STREAM_FEATURE_QUEUE_SUBMIT_WITH_COMMANDS_BIT;
+    if (!queueSubmitWithCommandsEnabled && doLock) this->lock();
+    auto stream = mImpl->stream();
+    auto pool = mImpl->pool();
+    VkDevice local_device;
+    VkSemaphore local_semaphore;
+    uint64_t local_syncId;
+    local_device = device;
+    local_semaphore = semaphore;
+    local_syncId = syncId;
+    size_t count = 0;
+    size_t* countPtr = &count;
+    {
+        uint64_t cgen_var_0;
+        *countPtr += 1 * 8;
+        uint64_t cgen_var_1;
+        *countPtr += 1 * 8;
+        *countPtr += sizeof(uint64_t);
+    }
+    uint32_t packetSize_vkGetSemaphoreGOOGLE =
+        4 + 4 + (queueSubmitWithCommandsEnabled ? 4 : 0) + count;
+    healthMonitorAnnotation_packetSize = std::make_optional(packetSize_vkGetSemaphoreGOOGLE);
+    uint8_t* streamPtr = stream->reserve(packetSize_vkGetSemaphoreGOOGLE);
+    uint8_t* packetBeginPtr = streamPtr;
+    uint8_t** streamPtrPtr = &streamPtr;
+    uint32_t opcode_vkGetSemaphoreGOOGLE = OP_vkGetSemaphoreGOOGLE;
+    uint32_t seqno;
+    if (queueSubmitWithCommandsEnabled) seqno = ResourceTracker::nextSeqno();
+    healthMonitorAnnotation_seqno = std::make_optional(seqno);
+    memcpy(streamPtr, &opcode_vkGetSemaphoreGOOGLE, sizeof(uint32_t));
+    streamPtr += sizeof(uint32_t);
+    memcpy(streamPtr, &packetSize_vkGetSemaphoreGOOGLE, sizeof(uint32_t));
+    streamPtr += sizeof(uint32_t);
+    if (queueSubmitWithCommandsEnabled) {
+        memcpy(streamPtr, &seqno, sizeof(uint32_t));
+        streamPtr += sizeof(uint32_t);
+    }
+    uint64_t cgen_var_0;
+    *&cgen_var_0 = get_host_u64_VkDevice((*&local_device));
+    memcpy(*streamPtrPtr, (uint64_t*)&cgen_var_0, 1 * 8);
+    *streamPtrPtr += 1 * 8;
+    uint64_t cgen_var_1;
+    *&cgen_var_1 = get_host_u64_VkSemaphore((*&local_semaphore));
+    memcpy(*streamPtrPtr, (uint64_t*)&cgen_var_1, 1 * 8);
+    *streamPtrPtr += 1 * 8;
+    memcpy(*streamPtrPtr, (uint64_t*)&local_syncId, sizeof(uint64_t));
+    *streamPtrPtr += sizeof(uint64_t);
+    if (watchdog) {
+        size_t watchdogBufSize = std::min<size_t>(
+            static_cast<size_t>(packetSize_vkGetSemaphoreGOOGLE), kWatchdogBufferMax);
+        healthMonitorAnnotation_packetContents.resize(watchdogBufSize);
+        memcpy(&healthMonitorAnnotation_packetContents[0], packetBeginPtr, watchdogBufSize);
+    }
+    VkResult vkGetSemaphoreGOOGLE_VkResult_return = (VkResult)0;
+    stream->read(&vkGetSemaphoreGOOGLE_VkResult_return, sizeof(VkResult));
+    ++encodeCount;
+    if (0 == encodeCount % POOL_CLEAR_INTERVAL) {
+        pool->freeAll();
+        stream->clearPool();
+    }
+    if (!queueSubmitWithCommandsEnabled && doLock) this->unlock();
+    return vkGetSemaphoreGOOGLE_VkResult_return;
+}
+
+#endif
 }  // namespace vk
 }  // namespace gfxstream
diff --git a/guest/vulkan_enc/VkEncoder.h b/guest/vulkan_enc/VkEncoder.h
index 6c12269..89728e3 100644
--- a/guest/vulkan_enc/VkEncoder.h
+++ b/guest/vulkan_enc/VkEncoder.h
@@ -617,16 +617,6 @@
         uint32_t* pSparseMemoryRequirementCount,
         VkSparseImageMemoryRequirements2* pSparseMemoryRequirements, uint32_t doLock);
 #endif
-#ifdef VK_KHR_surface
-#endif
-#ifdef VK_KHR_swapchain
-#endif
-#ifdef VK_KHR_xcb_surface
-#endif
-#ifdef VK_KHR_android_surface
-#endif
-#ifdef VK_KHR_win32_surface
-#endif
 #ifdef VK_KHR_dynamic_rendering
     void vkCmdBeginRenderingKHR(VkCommandBuffer commandBuffer,
                                 const VkRenderingInfo* pRenderingInfo, uint32_t doLock);
@@ -664,22 +654,12 @@
         const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo,
         VkExternalBufferProperties* pExternalBufferProperties, uint32_t doLock);
 #endif
-#ifdef VK_KHR_external_memory
-#endif
-#ifdef VK_KHR_external_memory_win32
-#endif
-#ifdef VK_KHR_external_memory_fd
-#endif
 #ifdef VK_KHR_external_semaphore_capabilities
     void vkGetPhysicalDeviceExternalSemaphorePropertiesKHR(
         VkPhysicalDevice physicalDevice,
         const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo,
         VkExternalSemaphoreProperties* pExternalSemaphoreProperties, uint32_t doLock);
 #endif
-#ifdef VK_KHR_external_semaphore
-#endif
-#ifdef VK_KHR_external_semaphore_win32
-#endif
 #ifdef VK_KHR_external_semaphore_fd
     VkResult vkImportSemaphoreFdKHR(VkDevice device,
                                     const VkImportSemaphoreFdInfoKHR* pImportSemaphoreFdInfo,
@@ -687,10 +667,6 @@
     VkResult vkGetSemaphoreFdKHR(VkDevice device, const VkSemaphoreGetFdInfoKHR* pGetFdInfo,
                                  int* pFd, uint32_t doLock);
 #endif
-#ifdef VK_KHR_shader_float16_int8
-#endif
-#ifdef VK_KHR_incremental_present
-#endif
 #ifdef VK_KHR_descriptor_update_template
     VkResult vkCreateDescriptorUpdateTemplateKHR(
         VkDevice device, const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo,
@@ -704,8 +680,6 @@
                                               VkDescriptorUpdateTemplate descriptorUpdateTemplate,
                                               const void* pData, uint32_t doLock);
 #endif
-#ifdef VK_KHR_imageless_framebuffer
-#endif
 #ifdef VK_KHR_create_renderpass2
     VkResult vkCreateRenderPass2KHR(VkDevice device, const VkRenderPassCreateInfo2* pCreateInfo,
                                     const VkAllocationCallbacks* pAllocator,
@@ -725,20 +699,12 @@
         const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo,
         VkExternalFenceProperties* pExternalFenceProperties, uint32_t doLock);
 #endif
-#ifdef VK_KHR_external_fence
-#endif
 #ifdef VK_KHR_external_fence_fd
     VkResult vkImportFenceFdKHR(VkDevice device, const VkImportFenceFdInfoKHR* pImportFenceFdInfo,
                                 uint32_t doLock);
     VkResult vkGetFenceFdKHR(VkDevice device, const VkFenceGetFdInfoKHR* pGetFdInfo, int* pFd,
                              uint32_t doLock);
 #endif
-#ifdef VK_KHR_maintenance2
-#endif
-#ifdef VK_KHR_dedicated_allocation
-#endif
-#ifdef VK_KHR_storage_buffer_storage_class
-#endif
 #ifdef VK_KHR_get_memory_requirements2
     void vkGetImageMemoryRequirements2KHR(VkDevice device,
                                           const VkImageMemoryRequirementsInfo2* pInfo,
@@ -753,8 +719,6 @@
         uint32_t* pSparseMemoryRequirementCount,
         VkSparseImageMemoryRequirements2* pSparseMemoryRequirements, uint32_t doLock);
 #endif
-#ifdef VK_KHR_image_format_list
-#endif
 #ifdef VK_KHR_sampler_ycbcr_conversion
     VkResult vkCreateSamplerYcbcrConversionKHR(
         VkDevice device, const VkSamplerYcbcrConversionCreateInfo* pCreateInfo,
@@ -777,12 +741,6 @@
                                             VkDescriptorSetLayoutSupport* pSupport,
                                             uint32_t doLock);
 #endif
-#ifdef VK_KHR_shader_subgroup_extended_types
-#endif
-#ifdef VK_KHR_vulkan_memory_model
-#endif
-#ifdef VK_KHR_shader_terminate_invocation
-#endif
 #ifdef VK_KHR_buffer_device_address
     VkDeviceAddress vkGetBufferDeviceAddressKHR(VkDevice device,
                                                 const VkBufferDeviceAddressInfo* pInfo,
@@ -807,10 +765,6 @@
         uint32_t* pInternalRepresentationCount,
         VkPipelineExecutableInternalRepresentationKHR* pInternalRepresentations, uint32_t doLock);
 #endif
-#ifdef VK_KHR_shader_integer_dot_product
-#endif
-#ifdef VK_KHR_shader_non_semantic_info
-#endif
 #ifdef VK_KHR_synchronization2
     void vkCmdSetEvent2KHR(VkCommandBuffer commandBuffer, VkEvent event,
                            const VkDependencyInfo* pDependencyInfo, uint32_t doLock);
@@ -831,8 +785,6 @@
     void vkGetQueueCheckpointData2NV(VkQueue queue, uint32_t* pCheckpointDataCount,
                                      VkCheckpointData2NV* pCheckpointData, uint32_t doLock);
 #endif
-#ifdef VK_KHR_zero_initialize_workgroup_memory
-#endif
 #ifdef VK_KHR_copy_commands2
     void vkCmdCopyBuffer2KHR(VkCommandBuffer commandBuffer,
                              const VkCopyBufferInfo2* pCopyBufferInfo, uint32_t doLock);
@@ -849,8 +801,6 @@
     void vkCmdResolveImage2KHR(VkCommandBuffer commandBuffer,
                                const VkResolveImageInfo2* pResolveImageInfo, uint32_t doLock);
 #endif
-#ifdef VK_KHR_format_feature_flags2
-#endif
 #ifdef VK_KHR_maintenance4
     void vkGetDeviceBufferMemoryRequirementsKHR(VkDevice device,
                                                 const VkDeviceBufferMemoryRequirements* pInfo,
@@ -893,8 +843,6 @@
         VkSwapchainImageUsageFlagsANDROID swapchainImageUsage, uint64_t* grallocConsumerUsage,
         uint64_t* grallocProducerUsage, uint32_t doLock);
 #endif
-#ifdef VK_EXT_debug_report
-#endif
 #ifdef VK_EXT_transform_feedback
     void vkCmdBindTransformFeedbackBuffersEXT(VkCommandBuffer commandBuffer, uint32_t firstBinding,
                                               uint32_t bindingCount, const VkBuffer* pBuffers,
@@ -917,54 +865,16 @@
                                        VkDeviceSize counterBufferOffset, uint32_t counterOffset,
                                        uint32_t vertexStride, uint32_t doLock);
 #endif
-#ifdef VK_AMD_gpu_shader_half_float
-#endif
-#ifdef VK_EXT_texture_compression_astc_hdr
-#endif
-#ifdef VK_EXT_depth_clip_enable
-#endif
-#ifdef VK_EXT_swapchain_colorspace
-#endif
-#ifdef VK_EXT_queue_family_foreign
-#endif
-#ifdef VK_EXT_debug_utils
-#endif
-#ifdef VK_ANDROID_external_memory_android_hardware_buffer
-#endif
-#ifdef VK_EXT_inline_uniform_block
-#endif
-#ifdef VK_EXT_shader_stencil_export
-#endif
-#ifdef VK_EXT_vertex_attribute_divisor
-#endif
-#ifdef VK_EXT_pipeline_creation_feedback
-#endif
-#ifdef VK_NV_shader_subgroup_partitioned
-#endif
-#ifdef VK_EXT_metal_surface
-#endif
-#ifdef VK_EXT_fragment_density_map
-#endif
-#ifdef VK_EXT_scalar_block_layout
-#endif
-#ifdef VK_EXT_subgroup_size_control
-#endif
 #ifdef VK_EXT_tooling_info
     VkResult vkGetPhysicalDeviceToolPropertiesEXT(VkPhysicalDevice physicalDevice,
                                                   uint32_t* pToolCount,
                                                   VkPhysicalDeviceToolProperties* pToolProperties,
                                                   uint32_t doLock);
 #endif
-#ifdef VK_EXT_validation_features
-#endif
-#ifdef VK_EXT_provoking_vertex
-#endif
 #ifdef VK_EXT_line_rasterization
     void vkCmdSetLineStippleEXT(VkCommandBuffer commandBuffer, uint32_t lineStippleFactor,
                                 uint16_t lineStipplePattern, uint32_t doLock);
 #endif
-#ifdef VK_EXT_index_type_uint8
-#endif
 #ifdef VK_EXT_extended_dynamic_state
     void vkCmdSetCullModeEXT(VkCommandBuffer commandBuffer, VkCullModeFlags cullMode,
                              uint32_t doLock);
@@ -1011,18 +921,6 @@
                                          const VkImageSubresource2KHR* pSubresource,
                                          VkSubresourceLayout2KHR* pLayout, uint32_t doLock);
 #endif
-#ifdef VK_EXT_swapchain_maintenance1
-#endif
-#ifdef VK_EXT_shader_demote_to_helper_invocation
-#endif
-#ifdef VK_EXT_texel_buffer_alignment
-#endif
-#ifdef VK_EXT_device_memory_report
-#endif
-#ifdef VK_EXT_robustness2
-#endif
-#ifdef VK_EXT_custom_border_color
-#endif
 #ifdef VK_EXT_private_data
     VkResult vkCreatePrivateDataSlotEXT(VkDevice device,
                                         const VkPrivateDataSlotCreateInfo* pCreateInfo,
@@ -1035,22 +933,6 @@
     void vkGetPrivateDataEXT(VkDevice device, VkObjectType objectType, uint64_t objectHandle,
                              VkPrivateDataSlot privateDataSlot, uint64_t* pData, uint32_t doLock);
 #endif
-#ifdef VK_EXT_pipeline_creation_cache_control
-#endif
-#ifdef VK_EXT_metal_objects
-#endif
-#ifdef VK_EXT_graphics_pipeline_library
-#endif
-#ifdef VK_EXT_ycbcr_2plane_444_formats
-#endif
-#ifdef VK_EXT_image_robustness
-#endif
-#ifdef VK_EXT_image_compression_control
-#endif
-#ifdef VK_EXT_4444_formats
-#endif
-#ifdef VK_EXT_primitive_topology_list_restart
-#endif
 #ifdef VK_EXT_extended_dynamic_state2
     void vkCmdSetPatchControlPointsEXT(VkCommandBuffer commandBuffer, uint32_t patchControlPoints,
                                        uint32_t doLock);
@@ -1144,14 +1026,9 @@
         const uint8_t* pInlineUniformBlockData, uint32_t doLock);
     void vkQueueSubmitAsync2GOOGLE(VkQueue queue, uint32_t submitCount,
                                    const VkSubmitInfo2* pSubmits, VkFence fence, uint32_t doLock);
+    VkResult vkGetSemaphoreGOOGLE(VkDevice device, VkSemaphore semaphore, uint64_t syncId,
+                                  uint32_t doLock);
 #endif
-#ifdef VK_EXT_load_store_op_none
-#endif
-#ifdef VK_EXT_image_compression_control_swapchain
-#endif
-#ifdef VK_QNX_external_memory_screen_buffer
-#endif
-
    private:
     class Impl;
     std::unique_ptr<Impl> mImpl;
diff --git a/guest/vulkan_enc/VulkanStreamGuest.cpp b/guest/vulkan_enc/VulkanStreamGuest.cpp
index 1a88d55..422d54f 100644
--- a/guest/vulkan_enc/VulkanStreamGuest.cpp
+++ b/guest/vulkan_enc/VulkanStreamGuest.cpp
@@ -14,6 +14,7 @@
 #include "VulkanStreamGuest.h"
 
 #include "util/log.h"
+#include "util/perf/cpu_trace.h"
 
 namespace gfxstream {
 namespace vk {
@@ -128,7 +129,7 @@
 VulkanHandleMapping* VulkanStreamGuest::handleMapping() const { return mCurrentHandleMapping; }
 
 void VulkanStreamGuest::flush() {
-    AEMU_SCOPED_TRACE("VulkanStreamGuest device write");
+    MESA_TRACE_SCOPE("VulkanStreamGuest device write");
     mStream->flush();
 }
 
diff --git a/guest/vulkan_enc/VulkanStreamGuest.h b/guest/vulkan_enc/VulkanStreamGuest.h
index 37436bc..3190a2a 100644
--- a/guest/vulkan_enc/VulkanStreamGuest.h
+++ b/guest/vulkan_enc/VulkanStreamGuest.h
@@ -21,7 +21,6 @@
 #include "ResourceTracker.h"
 #include "VulkanHandleMapping.h"
 #include "aemu/base/BumpPool.h"
-#include "aemu/base/Tracing.h"
 #include "aemu/base/files/Stream.h"
 #include "aemu/base/files/StreamSerializing.h"
 #include "gfxstream/guest/IOStream.h"
diff --git a/guest/vulkan_enc/func_table.cpp b/guest/vulkan_enc/func_table.cpp
index 562eb40..c7f0004 100644
--- a/guest/vulkan_enc/func_table.cpp
+++ b/guest/vulkan_enc/func_table.cpp
@@ -52,7 +52,7 @@
 #ifdef VK_VERSION_1_0
 void gfxstream_vk_GetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice,
                                             VkPhysicalDeviceFeatures* pFeatures) {
-    AEMU_SCOPED_TRACE("vkGetPhysicalDeviceFeatures");
+    MESA_TRACE_SCOPE("vkGetPhysicalDeviceFeatures");
     VK_FROM_HANDLE(gfxstream_vk_physical_device, gfxstream_physicalDevice, physicalDevice);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -63,7 +63,7 @@
 void gfxstream_vk_GetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice,
                                                     VkFormat format,
                                                     VkFormatProperties* pFormatProperties) {
-    AEMU_SCOPED_TRACE("vkGetPhysicalDeviceFormatProperties");
+    MESA_TRACE_SCOPE("vkGetPhysicalDeviceFormatProperties");
     VK_FROM_HANDLE(gfxstream_vk_physical_device, gfxstream_physicalDevice, physicalDevice);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -75,7 +75,7 @@
     VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling,
     VkImageUsageFlags usage, VkImageCreateFlags flags,
     VkImageFormatProperties* pImageFormatProperties) {
-    AEMU_SCOPED_TRACE("vkGetPhysicalDeviceImageFormatProperties");
+    MESA_TRACE_SCOPE("vkGetPhysicalDeviceImageFormatProperties");
     VkResult vkGetPhysicalDeviceImageFormatProperties_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_physical_device, gfxstream_physicalDevice, physicalDevice);
     {
@@ -89,7 +89,7 @@
 }
 void gfxstream_vk_GetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice,
                                               VkPhysicalDeviceProperties* pProperties) {
-    AEMU_SCOPED_TRACE("vkGetPhysicalDeviceProperties");
+    MESA_TRACE_SCOPE("vkGetPhysicalDeviceProperties");
     VK_FROM_HANDLE(gfxstream_vk_physical_device, gfxstream_physicalDevice, physicalDevice);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -100,7 +100,7 @@
 void gfxstream_vk_GetPhysicalDeviceQueueFamilyProperties(
     VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount,
     VkQueueFamilyProperties* pQueueFamilyProperties) {
-    AEMU_SCOPED_TRACE("vkGetPhysicalDeviceQueueFamilyProperties");
+    MESA_TRACE_SCOPE("vkGetPhysicalDeviceQueueFamilyProperties");
     VK_FROM_HANDLE(gfxstream_vk_physical_device, gfxstream_physicalDevice, physicalDevice);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -111,7 +111,7 @@
 }
 void gfxstream_vk_GetPhysicalDeviceMemoryProperties(
     VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties* pMemoryProperties) {
-    AEMU_SCOPED_TRACE("vkGetPhysicalDeviceMemoryProperties");
+    MESA_TRACE_SCOPE("vkGetPhysicalDeviceMemoryProperties");
     VK_FROM_HANDLE(gfxstream_vk_physical_device, gfxstream_physicalDevice, physicalDevice);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -122,7 +122,7 @@
 VkResult gfxstream_vk_EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice,
                                                      uint32_t* pPropertyCount,
                                                      VkLayerProperties* pProperties) {
-    AEMU_SCOPED_TRACE("vkEnumerateDeviceLayerProperties");
+    MESA_TRACE_SCOPE("vkEnumerateDeviceLayerProperties");
     VkResult vkEnumerateDeviceLayerProperties_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_physical_device, gfxstream_physicalDevice, physicalDevice);
     {
@@ -135,7 +135,7 @@
 }
 VkResult gfxstream_vk_QueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo* pSubmits,
                                   VkFence fence) {
-    AEMU_SCOPED_TRACE("vkQueueSubmit");
+    MESA_TRACE_SCOPE("vkQueueSubmit");
     VkResult vkQueueSubmit_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_queue, gfxstream_queue, queue);
     VK_FROM_HANDLE(gfxstream_vk_fence, gfxstream_fence, fence);
@@ -157,10 +157,8 @@
                 internal_VkSubmitInfo_pWaitSemaphores[i].size();
             /* VkSubmitInfo::pCommandBuffers */
             internal_VkSubmitInfo_pCommandBuffers.push_back(std::vector<VkCommandBuffer>());
-            internal_VkSubmitInfo_pCommandBuffers[i].reserve(
+            internal_VkSubmitInfo_pCommandBuffers[i].resize(
                 internal_pSubmits[i].commandBufferCount);
-            memset(&internal_VkSubmitInfo_pCommandBuffers[i][0], 0,
-                   sizeof(VkCommandBuffer) * internal_pSubmits[i].commandBufferCount);
             for (uint32_t j = 0; j < internal_pSubmits[i].commandBufferCount; ++j) {
                 VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_pCommandBuffers,
                                internal_pSubmits[i].pCommandBuffers[j]);
@@ -186,7 +184,7 @@
     return vkQueueSubmit_VkResult_return;
 }
 VkResult gfxstream_vk_QueueWaitIdle(VkQueue queue) {
-    AEMU_SCOPED_TRACE("vkQueueWaitIdle");
+    MESA_TRACE_SCOPE("vkQueueWaitIdle");
     VkResult vkQueueWaitIdle_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_queue, gfxstream_queue, queue);
     {
@@ -199,7 +197,7 @@
     return vkQueueWaitIdle_VkResult_return;
 }
 VkResult gfxstream_vk_DeviceWaitIdle(VkDevice device) {
-    AEMU_SCOPED_TRACE("vkDeviceWaitIdle");
+    MESA_TRACE_SCOPE("vkDeviceWaitIdle");
     VkResult vkDeviceWaitIdle_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -211,7 +209,7 @@
 }
 void gfxstream_vk_FreeMemory(VkDevice device, VkDeviceMemory memory,
                              const VkAllocationCallbacks* pAllocator) {
-    AEMU_SCOPED_TRACE("vkFreeMemory");
+    MESA_TRACE_SCOPE("vkFreeMemory");
     if (VK_NULL_HANDLE == memory) {
         return;
     }
@@ -224,7 +222,7 @@
 }
 VkResult gfxstream_vk_MapMemory(VkDevice device, VkDeviceMemory memory, VkDeviceSize offset,
                                 VkDeviceSize size, VkMemoryMapFlags flags, void** ppData) {
-    AEMU_SCOPED_TRACE("vkMapMemory");
+    MESA_TRACE_SCOPE("vkMapMemory");
     VkResult vkMapMemory_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -236,7 +234,7 @@
     return vkMapMemory_VkResult_return;
 }
 void gfxstream_vk_UnmapMemory(VkDevice device, VkDeviceMemory memory) {
-    AEMU_SCOPED_TRACE("vkUnmapMemory");
+    MESA_TRACE_SCOPE("vkUnmapMemory");
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -245,7 +243,7 @@
 }
 VkResult gfxstream_vk_FlushMappedMemoryRanges(VkDevice device, uint32_t memoryRangeCount,
                                               const VkMappedMemoryRange* pMemoryRanges) {
-    AEMU_SCOPED_TRACE("vkFlushMappedMemoryRanges");
+    MESA_TRACE_SCOPE("vkFlushMappedMemoryRanges");
     VkResult vkFlushMappedMemoryRanges_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -257,7 +255,7 @@
 }
 VkResult gfxstream_vk_InvalidateMappedMemoryRanges(VkDevice device, uint32_t memoryRangeCount,
                                                    const VkMappedMemoryRange* pMemoryRanges) {
-    AEMU_SCOPED_TRACE("vkInvalidateMappedMemoryRanges");
+    MESA_TRACE_SCOPE("vkInvalidateMappedMemoryRanges");
     VkResult vkInvalidateMappedMemoryRanges_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -269,7 +267,7 @@
 }
 void gfxstream_vk_GetDeviceMemoryCommitment(VkDevice device, VkDeviceMemory memory,
                                             VkDeviceSize* pCommittedMemoryInBytes) {
-    AEMU_SCOPED_TRACE("vkGetDeviceMemoryCommitment");
+    MESA_TRACE_SCOPE("vkGetDeviceMemoryCommitment");
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -279,7 +277,7 @@
 }
 VkResult gfxstream_vk_BindBufferMemory(VkDevice device, VkBuffer buffer, VkDeviceMemory memory,
                                        VkDeviceSize memoryOffset) {
-    AEMU_SCOPED_TRACE("vkBindBufferMemory");
+    MESA_TRACE_SCOPE("vkBindBufferMemory");
     VkResult vkBindBufferMemory_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     VK_FROM_HANDLE(gfxstream_vk_buffer, gfxstream_buffer, buffer);
@@ -294,7 +292,7 @@
 }
 VkResult gfxstream_vk_BindImageMemory(VkDevice device, VkImage image, VkDeviceMemory memory,
                                       VkDeviceSize memoryOffset) {
-    AEMU_SCOPED_TRACE("vkBindImageMemory");
+    MESA_TRACE_SCOPE("vkBindImageMemory");
     VkResult vkBindImageMemory_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -307,7 +305,7 @@
 }
 void gfxstream_vk_GetBufferMemoryRequirements(VkDevice device, VkBuffer buffer,
                                               VkMemoryRequirements* pMemoryRequirements) {
-    AEMU_SCOPED_TRACE("vkGetBufferMemoryRequirements");
+    MESA_TRACE_SCOPE("vkGetBufferMemoryRequirements");
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     VK_FROM_HANDLE(gfxstream_vk_buffer, gfxstream_buffer, buffer);
     {
@@ -320,7 +318,7 @@
 }
 void gfxstream_vk_GetImageMemoryRequirements(VkDevice device, VkImage image,
                                              VkMemoryRequirements* pMemoryRequirements) {
-    AEMU_SCOPED_TRACE("vkGetImageMemoryRequirements");
+    MESA_TRACE_SCOPE("vkGetImageMemoryRequirements");
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -332,7 +330,7 @@
 void gfxstream_vk_GetImageSparseMemoryRequirements(
     VkDevice device, VkImage image, uint32_t* pSparseMemoryRequirementCount,
     VkSparseImageMemoryRequirements* pSparseMemoryRequirements) {
-    AEMU_SCOPED_TRACE("vkGetImageSparseMemoryRequirements");
+    MESA_TRACE_SCOPE("vkGetImageSparseMemoryRequirements");
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -345,7 +343,7 @@
     VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type,
     VkSampleCountFlagBits samples, VkImageUsageFlags usage, VkImageTiling tiling,
     uint32_t* pPropertyCount, VkSparseImageFormatProperties* pProperties) {
-    AEMU_SCOPED_TRACE("vkGetPhysicalDeviceSparseImageFormatProperties");
+    MESA_TRACE_SCOPE("vkGetPhysicalDeviceSparseImageFormatProperties");
     VK_FROM_HANDLE(gfxstream_vk_physical_device, gfxstream_physicalDevice, physicalDevice);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -356,7 +354,7 @@
 }
 VkResult gfxstream_vk_QueueBindSparse(VkQueue queue, uint32_t bindInfoCount,
                                       const VkBindSparseInfo* pBindInfo, VkFence fence) {
-    AEMU_SCOPED_TRACE("vkQueueBindSparse");
+    MESA_TRACE_SCOPE("vkQueueBindSparse");
     VkResult vkQueueBindSparse_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_queue, gfxstream_queue, queue);
     VK_FROM_HANDLE(gfxstream_vk_fence, gfxstream_fence, fence);
@@ -381,10 +379,7 @@
             /* VkBindSparseInfo::pBufferBinds */
             internal_VkBindSparseInfo_pBufferBinds.push_back(
                 std::vector<VkSparseBufferMemoryBindInfo>());
-            internal_VkBindSparseInfo_pBufferBinds[i].reserve(
-                internal_pBindInfo[i].bufferBindCount);
-            memset(&internal_VkBindSparseInfo_pBufferBinds[i][0], 0,
-                   sizeof(VkSparseBufferMemoryBindInfo) * internal_pBindInfo[i].bufferBindCount);
+            internal_VkBindSparseInfo_pBufferBinds[i].resize(internal_pBindInfo[i].bufferBindCount);
             for (uint32_t j = 0; j < internal_pBindInfo[i].bufferBindCount; ++j) {
                 internal_VkBindSparseInfo_pBufferBinds[i][j] =
                     internal_pBindInfo[i].pBufferBinds[j];
@@ -414,7 +409,7 @@
 }
 VkResult gfxstream_vk_CreateFence(VkDevice device, const VkFenceCreateInfo* pCreateInfo,
                                   const VkAllocationCallbacks* pAllocator, VkFence* pFence) {
-    AEMU_SCOPED_TRACE("vkCreateFence");
+    MESA_TRACE_SCOPE("vkCreateFence");
     VkResult vkCreateFence_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     struct gfxstream_vk_fence* gfxstream_pFence = (gfxstream_vk_fence*)vk_object_zalloc(
@@ -432,7 +427,7 @@
 }
 void gfxstream_vk_DestroyFence(VkDevice device, VkFence fence,
                                const VkAllocationCallbacks* pAllocator) {
-    AEMU_SCOPED_TRACE("vkDestroyFence");
+    MESA_TRACE_SCOPE("vkDestroyFence");
     if (VK_NULL_HANDLE == fence) {
         return;
     }
@@ -447,7 +442,7 @@
     vk_object_free(&gfxstream_device->vk, pAllocator, (void*)gfxstream_fence);
 }
 VkResult gfxstream_vk_ResetFences(VkDevice device, uint32_t fenceCount, const VkFence* pFences) {
-    AEMU_SCOPED_TRACE("vkResetFences");
+    MESA_TRACE_SCOPE("vkResetFences");
     VkResult vkResetFences_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -464,7 +459,7 @@
     return vkResetFences_VkResult_return;
 }
 VkResult gfxstream_vk_GetFenceStatus(VkDevice device, VkFence fence) {
-    AEMU_SCOPED_TRACE("vkGetFenceStatus");
+    MESA_TRACE_SCOPE("vkGetFenceStatus");
     VkResult vkGetFenceStatus_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     VK_FROM_HANDLE(gfxstream_vk_fence, gfxstream_fence, fence);
@@ -478,7 +473,7 @@
 }
 VkResult gfxstream_vk_WaitForFences(VkDevice device, uint32_t fenceCount, const VkFence* pFences,
                                     VkBool32 waitAll, uint64_t timeout) {
-    AEMU_SCOPED_TRACE("vkWaitForFences");
+    MESA_TRACE_SCOPE("vkWaitForFences");
     VkResult vkWaitForFences_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -497,7 +492,7 @@
 VkResult gfxstream_vk_CreateSemaphore(VkDevice device, const VkSemaphoreCreateInfo* pCreateInfo,
                                       const VkAllocationCallbacks* pAllocator,
                                       VkSemaphore* pSemaphore) {
-    AEMU_SCOPED_TRACE("vkCreateSemaphore");
+    MESA_TRACE_SCOPE("vkCreateSemaphore");
     VkResult vkCreateSemaphore_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     struct gfxstream_vk_semaphore* gfxstream_pSemaphore = (gfxstream_vk_semaphore*)vk_object_zalloc(
@@ -517,7 +512,7 @@
 }
 void gfxstream_vk_DestroySemaphore(VkDevice device, VkSemaphore semaphore,
                                    const VkAllocationCallbacks* pAllocator) {
-    AEMU_SCOPED_TRACE("vkDestroySemaphore");
+    MESA_TRACE_SCOPE("vkDestroySemaphore");
     if (VK_NULL_HANDLE == semaphore) {
         return;
     }
@@ -535,7 +530,7 @@
 }
 VkResult gfxstream_vk_CreateEvent(VkDevice device, const VkEventCreateInfo* pCreateInfo,
                                   const VkAllocationCallbacks* pAllocator, VkEvent* pEvent) {
-    AEMU_SCOPED_TRACE("vkCreateEvent");
+    MESA_TRACE_SCOPE("vkCreateEvent");
     VkResult vkCreateEvent_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -547,7 +542,7 @@
 }
 void gfxstream_vk_DestroyEvent(VkDevice device, VkEvent event,
                                const VkAllocationCallbacks* pAllocator) {
-    AEMU_SCOPED_TRACE("vkDestroyEvent");
+    MESA_TRACE_SCOPE("vkDestroyEvent");
     if (VK_NULL_HANDLE == event) {
         return;
     }
@@ -559,7 +554,7 @@
     }
 }
 VkResult gfxstream_vk_GetEventStatus(VkDevice device, VkEvent event) {
-    AEMU_SCOPED_TRACE("vkGetEventStatus");
+    MESA_TRACE_SCOPE("vkGetEventStatus");
     VkResult vkGetEventStatus_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -570,7 +565,7 @@
     return vkGetEventStatus_VkResult_return;
 }
 VkResult gfxstream_vk_SetEvent(VkDevice device, VkEvent event) {
-    AEMU_SCOPED_TRACE("vkSetEvent");
+    MESA_TRACE_SCOPE("vkSetEvent");
     VkResult vkSetEvent_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -581,7 +576,7 @@
     return vkSetEvent_VkResult_return;
 }
 VkResult gfxstream_vk_ResetEvent(VkDevice device, VkEvent event) {
-    AEMU_SCOPED_TRACE("vkResetEvent");
+    MESA_TRACE_SCOPE("vkResetEvent");
     VkResult vkResetEvent_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -594,7 +589,7 @@
 VkResult gfxstream_vk_CreateQueryPool(VkDevice device, const VkQueryPoolCreateInfo* pCreateInfo,
                                       const VkAllocationCallbacks* pAllocator,
                                       VkQueryPool* pQueryPool) {
-    AEMU_SCOPED_TRACE("vkCreateQueryPool");
+    MESA_TRACE_SCOPE("vkCreateQueryPool");
     VkResult vkCreateQueryPool_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -607,7 +602,7 @@
 }
 void gfxstream_vk_DestroyQueryPool(VkDevice device, VkQueryPool queryPool,
                                    const VkAllocationCallbacks* pAllocator) {
-    AEMU_SCOPED_TRACE("vkDestroyQueryPool");
+    MESA_TRACE_SCOPE("vkDestroyQueryPool");
     if (VK_NULL_HANDLE == queryPool) {
         return;
     }
@@ -622,7 +617,7 @@
                                           uint32_t firstQuery, uint32_t queryCount, size_t dataSize,
                                           void* pData, VkDeviceSize stride,
                                           VkQueryResultFlags flags) {
-    AEMU_SCOPED_TRACE("vkGetQueryPoolResults");
+    MESA_TRACE_SCOPE("vkGetQueryPoolResults");
     VkResult vkGetQueryPoolResults_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -635,7 +630,7 @@
 }
 VkResult gfxstream_vk_CreateBuffer(VkDevice device, const VkBufferCreateInfo* pCreateInfo,
                                    const VkAllocationCallbacks* pAllocator, VkBuffer* pBuffer) {
-    AEMU_SCOPED_TRACE("vkCreateBuffer");
+    MESA_TRACE_SCOPE("vkCreateBuffer");
     VkResult vkCreateBuffer_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     struct gfxstream_vk_buffer* gfxstream_pBuffer = (gfxstream_vk_buffer*)vk_object_zalloc(
@@ -653,7 +648,7 @@
 }
 void gfxstream_vk_DestroyBuffer(VkDevice device, VkBuffer buffer,
                                 const VkAllocationCallbacks* pAllocator) {
-    AEMU_SCOPED_TRACE("vkDestroyBuffer");
+    MESA_TRACE_SCOPE("vkDestroyBuffer");
     if (VK_NULL_HANDLE == buffer) {
         return;
     }
@@ -671,7 +666,7 @@
 VkResult gfxstream_vk_CreateBufferView(VkDevice device, const VkBufferViewCreateInfo* pCreateInfo,
                                        const VkAllocationCallbacks* pAllocator,
                                        VkBufferView* pView) {
-    AEMU_SCOPED_TRACE("vkCreateBufferView");
+    MESA_TRACE_SCOPE("vkCreateBufferView");
     VkResult vkCreateBufferView_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -691,7 +686,7 @@
 }
 void gfxstream_vk_DestroyBufferView(VkDevice device, VkBufferView bufferView,
                                     const VkAllocationCallbacks* pAllocator) {
-    AEMU_SCOPED_TRACE("vkDestroyBufferView");
+    MESA_TRACE_SCOPE("vkDestroyBufferView");
     if (VK_NULL_HANDLE == bufferView) {
         return;
     }
@@ -704,7 +699,7 @@
 }
 VkResult gfxstream_vk_CreateImage(VkDevice device, const VkImageCreateInfo* pCreateInfo,
                                   const VkAllocationCallbacks* pAllocator, VkImage* pImage) {
-    AEMU_SCOPED_TRACE("vkCreateImage");
+    MESA_TRACE_SCOPE("vkCreateImage");
     VkResult vkCreateImage_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -717,7 +712,7 @@
 }
 void gfxstream_vk_DestroyImage(VkDevice device, VkImage image,
                                const VkAllocationCallbacks* pAllocator) {
-    AEMU_SCOPED_TRACE("vkDestroyImage");
+    MESA_TRACE_SCOPE("vkDestroyImage");
     if (VK_NULL_HANDLE == image) {
         return;
     }
@@ -731,7 +726,7 @@
 void gfxstream_vk_GetImageSubresourceLayout(VkDevice device, VkImage image,
                                             const VkImageSubresource* pSubresource,
                                             VkSubresourceLayout* pLayout) {
-    AEMU_SCOPED_TRACE("vkGetImageSubresourceLayout");
+    MESA_TRACE_SCOPE("vkGetImageSubresourceLayout");
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -742,7 +737,7 @@
 }
 VkResult gfxstream_vk_CreateImageView(VkDevice device, const VkImageViewCreateInfo* pCreateInfo,
                                       const VkAllocationCallbacks* pAllocator, VkImageView* pView) {
-    AEMU_SCOPED_TRACE("vkCreateImageView");
+    MESA_TRACE_SCOPE("vkCreateImageView");
     VkResult vkCreateImageView_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -755,7 +750,7 @@
 }
 void gfxstream_vk_DestroyImageView(VkDevice device, VkImageView imageView,
                                    const VkAllocationCallbacks* pAllocator) {
-    AEMU_SCOPED_TRACE("vkDestroyImageView");
+    MESA_TRACE_SCOPE("vkDestroyImageView");
     if (VK_NULL_HANDLE == imageView) {
         return;
     }
@@ -770,7 +765,7 @@
                                          const VkShaderModuleCreateInfo* pCreateInfo,
                                          const VkAllocationCallbacks* pAllocator,
                                          VkShaderModule* pShaderModule) {
-    AEMU_SCOPED_TRACE("vkCreateShaderModule");
+    MESA_TRACE_SCOPE("vkCreateShaderModule");
     VkResult vkCreateShaderModule_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -783,7 +778,7 @@
 }
 void gfxstream_vk_DestroyShaderModule(VkDevice device, VkShaderModule shaderModule,
                                       const VkAllocationCallbacks* pAllocator) {
-    AEMU_SCOPED_TRACE("vkDestroyShaderModule");
+    MESA_TRACE_SCOPE("vkDestroyShaderModule");
     if (VK_NULL_HANDLE == shaderModule) {
         return;
     }
@@ -798,7 +793,7 @@
                                           const VkPipelineCacheCreateInfo* pCreateInfo,
                                           const VkAllocationCallbacks* pAllocator,
                                           VkPipelineCache* pPipelineCache) {
-    AEMU_SCOPED_TRACE("vkCreatePipelineCache");
+    MESA_TRACE_SCOPE("vkCreatePipelineCache");
     VkResult vkCreatePipelineCache_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -811,7 +806,7 @@
 }
 void gfxstream_vk_DestroyPipelineCache(VkDevice device, VkPipelineCache pipelineCache,
                                        const VkAllocationCallbacks* pAllocator) {
-    AEMU_SCOPED_TRACE("vkDestroyPipelineCache");
+    MESA_TRACE_SCOPE("vkDestroyPipelineCache");
     if (VK_NULL_HANDLE == pipelineCache) {
         return;
     }
@@ -824,7 +819,7 @@
 }
 VkResult gfxstream_vk_GetPipelineCacheData(VkDevice device, VkPipelineCache pipelineCache,
                                            size_t* pDataSize, void* pData) {
-    AEMU_SCOPED_TRACE("vkGetPipelineCacheData");
+    MESA_TRACE_SCOPE("vkGetPipelineCacheData");
     VkResult vkGetPipelineCacheData_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -837,7 +832,7 @@
 VkResult gfxstream_vk_MergePipelineCaches(VkDevice device, VkPipelineCache dstCache,
                                           uint32_t srcCacheCount,
                                           const VkPipelineCache* pSrcCaches) {
-    AEMU_SCOPED_TRACE("vkMergePipelineCaches");
+    MESA_TRACE_SCOPE("vkMergePipelineCaches");
     VkResult vkMergePipelineCaches_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -853,7 +848,7 @@
                                               const VkGraphicsPipelineCreateInfo* pCreateInfos,
                                               const VkAllocationCallbacks* pAllocator,
                                               VkPipeline* pPipelines) {
-    AEMU_SCOPED_TRACE("vkCreateGraphicsPipelines");
+    MESA_TRACE_SCOPE("vkCreateGraphicsPipelines");
     VkResult vkCreateGraphicsPipelines_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -870,7 +865,7 @@
                                              const VkComputePipelineCreateInfo* pCreateInfos,
                                              const VkAllocationCallbacks* pAllocator,
                                              VkPipeline* pPipelines) {
-    AEMU_SCOPED_TRACE("vkCreateComputePipelines");
+    MESA_TRACE_SCOPE("vkCreateComputePipelines");
     VkResult vkCreateComputePipelines_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -883,7 +878,7 @@
 }
 void gfxstream_vk_DestroyPipeline(VkDevice device, VkPipeline pipeline,
                                   const VkAllocationCallbacks* pAllocator) {
-    AEMU_SCOPED_TRACE("vkDestroyPipeline");
+    MESA_TRACE_SCOPE("vkDestroyPipeline");
     if (VK_NULL_HANDLE == pipeline) {
         return;
     }
@@ -898,7 +893,7 @@
                                            const VkPipelineLayoutCreateInfo* pCreateInfo,
                                            const VkAllocationCallbacks* pAllocator,
                                            VkPipelineLayout* pPipelineLayout) {
-    AEMU_SCOPED_TRACE("vkCreatePipelineLayout");
+    MESA_TRACE_SCOPE("vkCreatePipelineLayout");
     VkResult vkCreatePipelineLayout_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -911,7 +906,7 @@
 }
 void gfxstream_vk_DestroyPipelineLayout(VkDevice device, VkPipelineLayout pipelineLayout,
                                         const VkAllocationCallbacks* pAllocator) {
-    AEMU_SCOPED_TRACE("vkDestroyPipelineLayout");
+    MESA_TRACE_SCOPE("vkDestroyPipelineLayout");
     if (VK_NULL_HANDLE == pipelineLayout) {
         return;
     }
@@ -924,7 +919,7 @@
 }
 VkResult gfxstream_vk_CreateSampler(VkDevice device, const VkSamplerCreateInfo* pCreateInfo,
                                     const VkAllocationCallbacks* pAllocator, VkSampler* pSampler) {
-    AEMU_SCOPED_TRACE("vkCreateSampler");
+    MESA_TRACE_SCOPE("vkCreateSampler");
     VkResult vkCreateSampler_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -938,7 +933,7 @@
 }
 void gfxstream_vk_DestroySampler(VkDevice device, VkSampler sampler,
                                  const VkAllocationCallbacks* pAllocator) {
-    AEMU_SCOPED_TRACE("vkDestroySampler");
+    MESA_TRACE_SCOPE("vkDestroySampler");
     if (VK_NULL_HANDLE == sampler) {
         return;
     }
@@ -953,7 +948,7 @@
                                                 const VkDescriptorSetLayoutCreateInfo* pCreateInfo,
                                                 const VkAllocationCallbacks* pAllocator,
                                                 VkDescriptorSetLayout* pSetLayout) {
-    AEMU_SCOPED_TRACE("vkCreateDescriptorSetLayout");
+    MESA_TRACE_SCOPE("vkCreateDescriptorSetLayout");
     VkResult vkCreateDescriptorSetLayout_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -968,7 +963,7 @@
 void gfxstream_vk_DestroyDescriptorSetLayout(VkDevice device,
                                              VkDescriptorSetLayout descriptorSetLayout,
                                              const VkAllocationCallbacks* pAllocator) {
-    AEMU_SCOPED_TRACE("vkDestroyDescriptorSetLayout");
+    MESA_TRACE_SCOPE("vkDestroyDescriptorSetLayout");
     if (VK_NULL_HANDLE == descriptorSetLayout) {
         return;
     }
@@ -984,7 +979,7 @@
                                            const VkDescriptorPoolCreateInfo* pCreateInfo,
                                            const VkAllocationCallbacks* pAllocator,
                                            VkDescriptorPool* pDescriptorPool) {
-    AEMU_SCOPED_TRACE("vkCreateDescriptorPool");
+    MESA_TRACE_SCOPE("vkCreateDescriptorPool");
     VkResult vkCreateDescriptorPool_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -998,7 +993,7 @@
 }
 void gfxstream_vk_DestroyDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool,
                                         const VkAllocationCallbacks* pAllocator) {
-    AEMU_SCOPED_TRACE("vkDestroyDescriptorPool");
+    MESA_TRACE_SCOPE("vkDestroyDescriptorPool");
     if (VK_NULL_HANDLE == descriptorPool) {
         return;
     }
@@ -1012,7 +1007,7 @@
 }
 VkResult gfxstream_vk_ResetDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool,
                                           VkDescriptorPoolResetFlags flags) {
-    AEMU_SCOPED_TRACE("vkResetDescriptorPool");
+    MESA_TRACE_SCOPE("vkResetDescriptorPool");
     VkResult vkResetDescriptorPool_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -1026,7 +1021,7 @@
 VkResult gfxstream_vk_AllocateDescriptorSets(VkDevice device,
                                              const VkDescriptorSetAllocateInfo* pAllocateInfo,
                                              VkDescriptorSet* pDescriptorSets) {
-    AEMU_SCOPED_TRACE("vkAllocateDescriptorSets");
+    MESA_TRACE_SCOPE("vkAllocateDescriptorSets");
     VkResult vkAllocateDescriptorSets_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -1040,7 +1035,7 @@
 VkResult gfxstream_vk_FreeDescriptorSets(VkDevice device, VkDescriptorPool descriptorPool,
                                          uint32_t descriptorSetCount,
                                          const VkDescriptorSet* pDescriptorSets) {
-    AEMU_SCOPED_TRACE("vkFreeDescriptorSets");
+    MESA_TRACE_SCOPE("vkFreeDescriptorSets");
     VkResult vkFreeDescriptorSets_VkResult_return = (VkResult)0;
     if (VK_NULL_HANDLE == pDescriptorSets) {
         return vkFreeDescriptorSets_VkResult_return;
@@ -1058,7 +1053,7 @@
 VkResult gfxstream_vk_CreateFramebuffer(VkDevice device, const VkFramebufferCreateInfo* pCreateInfo,
                                         const VkAllocationCallbacks* pAllocator,
                                         VkFramebuffer* pFramebuffer) {
-    AEMU_SCOPED_TRACE("vkCreateFramebuffer");
+    MESA_TRACE_SCOPE("vkCreateFramebuffer");
     VkResult vkCreateFramebuffer_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -1071,7 +1066,7 @@
 }
 void gfxstream_vk_DestroyFramebuffer(VkDevice device, VkFramebuffer framebuffer,
                                      const VkAllocationCallbacks* pAllocator) {
-    AEMU_SCOPED_TRACE("vkDestroyFramebuffer");
+    MESA_TRACE_SCOPE("vkDestroyFramebuffer");
     if (VK_NULL_HANDLE == framebuffer) {
         return;
     }
@@ -1085,7 +1080,7 @@
 VkResult gfxstream_vk_CreateRenderPass(VkDevice device, const VkRenderPassCreateInfo* pCreateInfo,
                                        const VkAllocationCallbacks* pAllocator,
                                        VkRenderPass* pRenderPass) {
-    AEMU_SCOPED_TRACE("vkCreateRenderPass");
+    MESA_TRACE_SCOPE("vkCreateRenderPass");
     VkResult vkCreateRenderPass_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -1098,7 +1093,7 @@
 }
 void gfxstream_vk_DestroyRenderPass(VkDevice device, VkRenderPass renderPass,
                                     const VkAllocationCallbacks* pAllocator) {
-    AEMU_SCOPED_TRACE("vkDestroyRenderPass");
+    MESA_TRACE_SCOPE("vkDestroyRenderPass");
     if (VK_NULL_HANDLE == renderPass) {
         return;
     }
@@ -1111,7 +1106,7 @@
 }
 void gfxstream_vk_GetRenderAreaGranularity(VkDevice device, VkRenderPass renderPass,
                                            VkExtent2D* pGranularity) {
-    AEMU_SCOPED_TRACE("vkGetRenderAreaGranularity");
+    MESA_TRACE_SCOPE("vkGetRenderAreaGranularity");
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -1121,7 +1116,7 @@
 }
 VkResult gfxstream_vk_BeginCommandBuffer(VkCommandBuffer commandBuffer,
                                          const VkCommandBufferBeginInfo* pBeginInfo) {
-    AEMU_SCOPED_TRACE("vkBeginCommandBuffer");
+    MESA_TRACE_SCOPE("vkBeginCommandBuffer");
     VkResult vkBeginCommandBuffer_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
@@ -1134,7 +1129,7 @@
     return vkBeginCommandBuffer_VkResult_return;
 }
 VkResult gfxstream_vk_EndCommandBuffer(VkCommandBuffer commandBuffer) {
-    AEMU_SCOPED_TRACE("vkEndCommandBuffer");
+    MESA_TRACE_SCOPE("vkEndCommandBuffer");
     VkResult vkEndCommandBuffer_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
@@ -1148,7 +1143,7 @@
 }
 VkResult gfxstream_vk_ResetCommandBuffer(VkCommandBuffer commandBuffer,
                                          VkCommandBufferResetFlags flags) {
-    AEMU_SCOPED_TRACE("vkResetCommandBuffer");
+    MESA_TRACE_SCOPE("vkResetCommandBuffer");
     VkResult vkResetCommandBuffer_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
@@ -1162,7 +1157,7 @@
 }
 void gfxstream_vk_CmdBindPipeline(VkCommandBuffer commandBuffer,
                                   VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline) {
-    AEMU_SCOPED_TRACE("vkCmdBindPipeline");
+    MESA_TRACE_SCOPE("vkCmdBindPipeline");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -1173,7 +1168,7 @@
 }
 void gfxstream_vk_CmdSetViewport(VkCommandBuffer commandBuffer, uint32_t firstViewport,
                                  uint32_t viewportCount, const VkViewport* pViewports) {
-    AEMU_SCOPED_TRACE("vkCmdSetViewport");
+    MESA_TRACE_SCOPE("vkCmdSetViewport");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -1184,7 +1179,7 @@
 }
 void gfxstream_vk_CmdSetScissor(VkCommandBuffer commandBuffer, uint32_t firstScissor,
                                 uint32_t scissorCount, const VkRect2D* pScissors) {
-    AEMU_SCOPED_TRACE("vkCmdSetScissor");
+    MESA_TRACE_SCOPE("vkCmdSetScissor");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -1194,7 +1189,7 @@
     }
 }
 void gfxstream_vk_CmdSetLineWidth(VkCommandBuffer commandBuffer, float lineWidth) {
-    AEMU_SCOPED_TRACE("vkCmdSetLineWidth");
+    MESA_TRACE_SCOPE("vkCmdSetLineWidth");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -1205,7 +1200,7 @@
 }
 void gfxstream_vk_CmdSetDepthBias(VkCommandBuffer commandBuffer, float depthBiasConstantFactor,
                                   float depthBiasClamp, float depthBiasSlopeFactor) {
-    AEMU_SCOPED_TRACE("vkCmdSetDepthBias");
+    MESA_TRACE_SCOPE("vkCmdSetDepthBias");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -1216,7 +1211,7 @@
 }
 void gfxstream_vk_CmdSetBlendConstants(VkCommandBuffer commandBuffer,
                                        const float blendConstants[4]) {
-    AEMU_SCOPED_TRACE("vkCmdSetBlendConstants");
+    MESA_TRACE_SCOPE("vkCmdSetBlendConstants");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -1227,7 +1222,7 @@
 }
 void gfxstream_vk_CmdSetDepthBounds(VkCommandBuffer commandBuffer, float minDepthBounds,
                                     float maxDepthBounds) {
-    AEMU_SCOPED_TRACE("vkCmdSetDepthBounds");
+    MESA_TRACE_SCOPE("vkCmdSetDepthBounds");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -1238,7 +1233,7 @@
 }
 void gfxstream_vk_CmdSetStencilCompareMask(VkCommandBuffer commandBuffer,
                                            VkStencilFaceFlags faceMask, uint32_t compareMask) {
-    AEMU_SCOPED_TRACE("vkCmdSetStencilCompareMask");
+    MESA_TRACE_SCOPE("vkCmdSetStencilCompareMask");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -1249,7 +1244,7 @@
 }
 void gfxstream_vk_CmdSetStencilWriteMask(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask,
                                          uint32_t writeMask) {
-    AEMU_SCOPED_TRACE("vkCmdSetStencilWriteMask");
+    MESA_TRACE_SCOPE("vkCmdSetStencilWriteMask");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -1260,7 +1255,7 @@
 }
 void gfxstream_vk_CmdSetStencilReference(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask,
                                          uint32_t reference) {
-    AEMU_SCOPED_TRACE("vkCmdSetStencilReference");
+    MESA_TRACE_SCOPE("vkCmdSetStencilReference");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -1273,7 +1268,7 @@
     VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout,
     uint32_t firstSet, uint32_t descriptorSetCount, const VkDescriptorSet* pDescriptorSets,
     uint32_t dynamicOffsetCount, const uint32_t* pDynamicOffsets) {
-    AEMU_SCOPED_TRACE("vkCmdBindDescriptorSets");
+    MESA_TRACE_SCOPE("vkCmdBindDescriptorSets");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -1286,7 +1281,7 @@
 }
 void gfxstream_vk_CmdBindIndexBuffer(VkCommandBuffer commandBuffer, VkBuffer buffer,
                                      VkDeviceSize offset, VkIndexType indexType) {
-    AEMU_SCOPED_TRACE("vkCmdBindIndexBuffer");
+    MESA_TRACE_SCOPE("vkCmdBindIndexBuffer");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     VK_FROM_HANDLE(gfxstream_vk_buffer, gfxstream_buffer, buffer);
     {
@@ -1300,7 +1295,7 @@
 void gfxstream_vk_CmdBindVertexBuffers(VkCommandBuffer commandBuffer, uint32_t firstBinding,
                                        uint32_t bindingCount, const VkBuffer* pBuffers,
                                        const VkDeviceSize* pOffsets) {
-    AEMU_SCOPED_TRACE("vkCmdBindVertexBuffers");
+    MESA_TRACE_SCOPE("vkCmdBindVertexBuffers");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -1319,7 +1314,7 @@
 }
 void gfxstream_vk_CmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCount,
                           uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance) {
-    AEMU_SCOPED_TRACE("vkCmdDraw");
+    MESA_TRACE_SCOPE("vkCmdDraw");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -1331,7 +1326,7 @@
 void gfxstream_vk_CmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_t indexCount,
                                  uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset,
                                  uint32_t firstInstance) {
-    AEMU_SCOPED_TRACE("vkCmdDrawIndexed");
+    MESA_TRACE_SCOPE("vkCmdDrawIndexed");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -1342,7 +1337,7 @@
 }
 void gfxstream_vk_CmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer,
                                   VkDeviceSize offset, uint32_t drawCount, uint32_t stride) {
-    AEMU_SCOPED_TRACE("vkCmdDrawIndirect");
+    MESA_TRACE_SCOPE("vkCmdDrawIndirect");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     VK_FROM_HANDLE(gfxstream_vk_buffer, gfxstream_buffer, buffer);
     {
@@ -1355,7 +1350,7 @@
 }
 void gfxstream_vk_CmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer,
                                          VkDeviceSize offset, uint32_t drawCount, uint32_t stride) {
-    AEMU_SCOPED_TRACE("vkCmdDrawIndexedIndirect");
+    MESA_TRACE_SCOPE("vkCmdDrawIndexedIndirect");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     VK_FROM_HANDLE(gfxstream_vk_buffer, gfxstream_buffer, buffer);
     {
@@ -1368,7 +1363,7 @@
 }
 void gfxstream_vk_CmdDispatch(VkCommandBuffer commandBuffer, uint32_t groupCountX,
                               uint32_t groupCountY, uint32_t groupCountZ) {
-    AEMU_SCOPED_TRACE("vkCmdDispatch");
+    MESA_TRACE_SCOPE("vkCmdDispatch");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -1379,7 +1374,7 @@
 }
 void gfxstream_vk_CmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer,
                                       VkDeviceSize offset) {
-    AEMU_SCOPED_TRACE("vkCmdDispatchIndirect");
+    MESA_TRACE_SCOPE("vkCmdDispatchIndirect");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     VK_FROM_HANDLE(gfxstream_vk_buffer, gfxstream_buffer, buffer);
     {
@@ -1392,7 +1387,7 @@
 void gfxstream_vk_CmdCopyBuffer(VkCommandBuffer commandBuffer, VkBuffer srcBuffer,
                                 VkBuffer dstBuffer, uint32_t regionCount,
                                 const VkBufferCopy* pRegions) {
-    AEMU_SCOPED_TRACE("vkCmdCopyBuffer");
+    MESA_TRACE_SCOPE("vkCmdCopyBuffer");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     VK_FROM_HANDLE(gfxstream_vk_buffer, gfxstream_srcBuffer, srcBuffer);
     VK_FROM_HANDLE(gfxstream_vk_buffer, gfxstream_dstBuffer, dstBuffer);
@@ -1408,7 +1403,7 @@
                                VkImageLayout srcImageLayout, VkImage dstImage,
                                VkImageLayout dstImageLayout, uint32_t regionCount,
                                const VkImageCopy* pRegions) {
-    AEMU_SCOPED_TRACE("vkCmdCopyImage");
+    MESA_TRACE_SCOPE("vkCmdCopyImage");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -1421,7 +1416,7 @@
                                VkImageLayout srcImageLayout, VkImage dstImage,
                                VkImageLayout dstImageLayout, uint32_t regionCount,
                                const VkImageBlit* pRegions, VkFilter filter) {
-    AEMU_SCOPED_TRACE("vkCmdBlitImage");
+    MESA_TRACE_SCOPE("vkCmdBlitImage");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -1434,7 +1429,7 @@
 void gfxstream_vk_CmdCopyBufferToImage(VkCommandBuffer commandBuffer, VkBuffer srcBuffer,
                                        VkImage dstImage, VkImageLayout dstImageLayout,
                                        uint32_t regionCount, const VkBufferImageCopy* pRegions) {
-    AEMU_SCOPED_TRACE("vkCmdCopyBufferToImage");
+    MESA_TRACE_SCOPE("vkCmdCopyBufferToImage");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     VK_FROM_HANDLE(gfxstream_vk_buffer, gfxstream_srcBuffer, srcBuffer);
     {
@@ -1448,7 +1443,7 @@
 void gfxstream_vk_CmdCopyImageToBuffer(VkCommandBuffer commandBuffer, VkImage srcImage,
                                        VkImageLayout srcImageLayout, VkBuffer dstBuffer,
                                        uint32_t regionCount, const VkBufferImageCopy* pRegions) {
-    AEMU_SCOPED_TRACE("vkCmdCopyImageToBuffer");
+    MESA_TRACE_SCOPE("vkCmdCopyImageToBuffer");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     VK_FROM_HANDLE(gfxstream_vk_buffer, gfxstream_dstBuffer, dstBuffer);
     {
@@ -1462,7 +1457,7 @@
 void gfxstream_vk_CmdUpdateBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer,
                                   VkDeviceSize dstOffset, VkDeviceSize dataSize,
                                   const void* pData) {
-    AEMU_SCOPED_TRACE("vkCmdUpdateBuffer");
+    MESA_TRACE_SCOPE("vkCmdUpdateBuffer");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     VK_FROM_HANDLE(gfxstream_vk_buffer, gfxstream_dstBuffer, dstBuffer);
     {
@@ -1475,7 +1470,7 @@
 }
 void gfxstream_vk_CmdFillBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer,
                                 VkDeviceSize dstOffset, VkDeviceSize size, uint32_t data) {
-    AEMU_SCOPED_TRACE("vkCmdFillBuffer");
+    MESA_TRACE_SCOPE("vkCmdFillBuffer");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     VK_FROM_HANDLE(gfxstream_vk_buffer, gfxstream_dstBuffer, dstBuffer);
     {
@@ -1489,7 +1484,7 @@
 void gfxstream_vk_CmdClearColorImage(VkCommandBuffer commandBuffer, VkImage image,
                                      VkImageLayout imageLayout, const VkClearColorValue* pColor,
                                      uint32_t rangeCount, const VkImageSubresourceRange* pRanges) {
-    AEMU_SCOPED_TRACE("vkCmdClearColorImage");
+    MESA_TRACE_SCOPE("vkCmdClearColorImage");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -1503,7 +1498,7 @@
                                             const VkClearDepthStencilValue* pDepthStencil,
                                             uint32_t rangeCount,
                                             const VkImageSubresourceRange* pRanges) {
-    AEMU_SCOPED_TRACE("vkCmdClearDepthStencilImage");
+    MESA_TRACE_SCOPE("vkCmdClearDepthStencilImage");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -1516,7 +1511,7 @@
 void gfxstream_vk_CmdClearAttachments(VkCommandBuffer commandBuffer, uint32_t attachmentCount,
                                       const VkClearAttachment* pAttachments, uint32_t rectCount,
                                       const VkClearRect* pRects) {
-    AEMU_SCOPED_TRACE("vkCmdClearAttachments");
+    MESA_TRACE_SCOPE("vkCmdClearAttachments");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -1529,7 +1524,7 @@
                                   VkImageLayout srcImageLayout, VkImage dstImage,
                                   VkImageLayout dstImageLayout, uint32_t regionCount,
                                   const VkImageResolve* pRegions) {
-    AEMU_SCOPED_TRACE("vkCmdResolveImage");
+    MESA_TRACE_SCOPE("vkCmdResolveImage");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -1541,7 +1536,7 @@
 }
 void gfxstream_vk_CmdSetEvent(VkCommandBuffer commandBuffer, VkEvent event,
                               VkPipelineStageFlags stageMask) {
-    AEMU_SCOPED_TRACE("vkCmdSetEvent");
+    MESA_TRACE_SCOPE("vkCmdSetEvent");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -1552,7 +1547,7 @@
 }
 void gfxstream_vk_CmdResetEvent(VkCommandBuffer commandBuffer, VkEvent event,
                                 VkPipelineStageFlags stageMask) {
-    AEMU_SCOPED_TRACE("vkCmdResetEvent");
+    MESA_TRACE_SCOPE("vkCmdResetEvent");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -1569,7 +1564,7 @@
                                 const VkBufferMemoryBarrier* pBufferMemoryBarriers,
                                 uint32_t imageMemoryBarrierCount,
                                 const VkImageMemoryBarrier* pImageMemoryBarriers) {
-    AEMU_SCOPED_TRACE("vkCmdWaitEvents");
+    MESA_TRACE_SCOPE("vkCmdWaitEvents");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -1594,7 +1589,7 @@
     uint32_t memoryBarrierCount, const VkMemoryBarrier* pMemoryBarriers,
     uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier* pBufferMemoryBarriers,
     uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier* pImageMemoryBarriers) {
-    AEMU_SCOPED_TRACE("vkCmdPipelineBarrier");
+    MESA_TRACE_SCOPE("vkCmdPipelineBarrier");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -1616,7 +1611,7 @@
 }
 void gfxstream_vk_CmdBeginQuery(VkCommandBuffer commandBuffer, VkQueryPool queryPool,
                                 uint32_t query, VkQueryControlFlags flags) {
-    AEMU_SCOPED_TRACE("vkCmdBeginQuery");
+    MESA_TRACE_SCOPE("vkCmdBeginQuery");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -1627,7 +1622,7 @@
 }
 void gfxstream_vk_CmdEndQuery(VkCommandBuffer commandBuffer, VkQueryPool queryPool,
                               uint32_t query) {
-    AEMU_SCOPED_TRACE("vkCmdEndQuery");
+    MESA_TRACE_SCOPE("vkCmdEndQuery");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -1638,7 +1633,7 @@
 }
 void gfxstream_vk_CmdResetQueryPool(VkCommandBuffer commandBuffer, VkQueryPool queryPool,
                                     uint32_t firstQuery, uint32_t queryCount) {
-    AEMU_SCOPED_TRACE("vkCmdResetQueryPool");
+    MESA_TRACE_SCOPE("vkCmdResetQueryPool");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -1650,7 +1645,7 @@
 void gfxstream_vk_CmdWriteTimestamp(VkCommandBuffer commandBuffer,
                                     VkPipelineStageFlagBits pipelineStage, VkQueryPool queryPool,
                                     uint32_t query) {
-    AEMU_SCOPED_TRACE("vkCmdWriteTimestamp");
+    MESA_TRACE_SCOPE("vkCmdWriteTimestamp");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -1663,7 +1658,7 @@
                                           uint32_t firstQuery, uint32_t queryCount,
                                           VkBuffer dstBuffer, VkDeviceSize dstOffset,
                                           VkDeviceSize stride, VkQueryResultFlags flags) {
-    AEMU_SCOPED_TRACE("vkCmdCopyQueryPoolResults");
+    MESA_TRACE_SCOPE("vkCmdCopyQueryPoolResults");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     VK_FROM_HANDLE(gfxstream_vk_buffer, gfxstream_dstBuffer, dstBuffer);
     {
@@ -1677,7 +1672,7 @@
 void gfxstream_vk_CmdPushConstants(VkCommandBuffer commandBuffer, VkPipelineLayout layout,
                                    VkShaderStageFlags stageFlags, uint32_t offset, uint32_t size,
                                    const void* pValues) {
-    AEMU_SCOPED_TRACE("vkCmdPushConstants");
+    MESA_TRACE_SCOPE("vkCmdPushConstants");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -1689,7 +1684,7 @@
 void gfxstream_vk_CmdBeginRenderPass(VkCommandBuffer commandBuffer,
                                      const VkRenderPassBeginInfo* pRenderPassBegin,
                                      VkSubpassContents contents) {
-    AEMU_SCOPED_TRACE("vkCmdBeginRenderPass");
+    MESA_TRACE_SCOPE("vkCmdBeginRenderPass");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -1699,7 +1694,7 @@
     }
 }
 void gfxstream_vk_CmdNextSubpass(VkCommandBuffer commandBuffer, VkSubpassContents contents) {
-    AEMU_SCOPED_TRACE("vkCmdNextSubpass");
+    MESA_TRACE_SCOPE("vkCmdNextSubpass");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -1709,7 +1704,7 @@
     }
 }
 void gfxstream_vk_CmdEndRenderPass(VkCommandBuffer commandBuffer) {
-    AEMU_SCOPED_TRACE("vkCmdEndRenderPass");
+    MESA_TRACE_SCOPE("vkCmdEndRenderPass");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -1719,7 +1714,7 @@
 }
 void gfxstream_vk_CmdExecuteCommands(VkCommandBuffer commandBuffer, uint32_t commandBufferCount,
                                      const VkCommandBuffer* pCommandBuffers) {
-    AEMU_SCOPED_TRACE("vkCmdExecuteCommands");
+    MESA_TRACE_SCOPE("vkCmdExecuteCommands");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -1739,7 +1734,7 @@
 #ifdef VK_VERSION_1_1
 VkResult gfxstream_vk_BindBufferMemory2(VkDevice device, uint32_t bindInfoCount,
                                         const VkBindBufferMemoryInfo* pBindInfos) {
-    AEMU_SCOPED_TRACE("vkBindBufferMemory2");
+    MESA_TRACE_SCOPE("vkBindBufferMemory2");
     VkResult vkBindBufferMemory2_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -1760,7 +1755,7 @@
 }
 VkResult gfxstream_vk_BindImageMemory2(VkDevice device, uint32_t bindInfoCount,
                                        const VkBindImageMemoryInfo* pBindInfos) {
-    AEMU_SCOPED_TRACE("vkBindImageMemory2");
+    MESA_TRACE_SCOPE("vkBindImageMemory2");
     VkResult vkBindImageMemory2_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -1775,7 +1770,7 @@
                                                    uint32_t localDeviceIndex,
                                                    uint32_t remoteDeviceIndex,
                                                    VkPeerMemoryFeatureFlags* pPeerMemoryFeatures) {
-    AEMU_SCOPED_TRACE("vkGetDeviceGroupPeerMemoryFeatures");
+    MESA_TRACE_SCOPE("vkGetDeviceGroupPeerMemoryFeatures");
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -1785,7 +1780,7 @@
     }
 }
 void gfxstream_vk_CmdSetDeviceMask(VkCommandBuffer commandBuffer, uint32_t deviceMask) {
-    AEMU_SCOPED_TRACE("vkCmdSetDeviceMask");
+    MESA_TRACE_SCOPE("vkCmdSetDeviceMask");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -1797,7 +1792,7 @@
 void gfxstream_vk_CmdDispatchBase(VkCommandBuffer commandBuffer, uint32_t baseGroupX,
                                   uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX,
                                   uint32_t groupCountY, uint32_t groupCountZ) {
-    AEMU_SCOPED_TRACE("vkCmdDispatchBase");
+    MESA_TRACE_SCOPE("vkCmdDispatchBase");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -1810,7 +1805,7 @@
 void gfxstream_vk_GetImageMemoryRequirements2(VkDevice device,
                                               const VkImageMemoryRequirementsInfo2* pInfo,
                                               VkMemoryRequirements2* pMemoryRequirements) {
-    AEMU_SCOPED_TRACE("vkGetImageMemoryRequirements2");
+    MESA_TRACE_SCOPE("vkGetImageMemoryRequirements2");
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -1822,7 +1817,7 @@
 void gfxstream_vk_GetBufferMemoryRequirements2(VkDevice device,
                                                const VkBufferMemoryRequirementsInfo2* pInfo,
                                                VkMemoryRequirements2* pMemoryRequirements) {
-    AEMU_SCOPED_TRACE("vkGetBufferMemoryRequirements2");
+    MESA_TRACE_SCOPE("vkGetBufferMemoryRequirements2");
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -1842,7 +1837,7 @@
     VkDevice device, const VkImageSparseMemoryRequirementsInfo2* pInfo,
     uint32_t* pSparseMemoryRequirementCount,
     VkSparseImageMemoryRequirements2* pSparseMemoryRequirements) {
-    AEMU_SCOPED_TRACE("vkGetImageSparseMemoryRequirements2");
+    MESA_TRACE_SCOPE("vkGetImageSparseMemoryRequirements2");
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -1853,7 +1848,7 @@
 }
 void gfxstream_vk_GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice,
                                              VkPhysicalDeviceFeatures2* pFeatures) {
-    AEMU_SCOPED_TRACE("vkGetPhysicalDeviceFeatures2");
+    MESA_TRACE_SCOPE("vkGetPhysicalDeviceFeatures2");
     VK_FROM_HANDLE(gfxstream_vk_physical_device, gfxstream_physicalDevice, physicalDevice);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -1863,7 +1858,7 @@
 }
 void gfxstream_vk_GetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice,
                                                VkPhysicalDeviceProperties2* pProperties) {
-    AEMU_SCOPED_TRACE("vkGetPhysicalDeviceProperties2");
+    MESA_TRACE_SCOPE("vkGetPhysicalDeviceProperties2");
     VK_FROM_HANDLE(gfxstream_vk_physical_device, gfxstream_physicalDevice, physicalDevice);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -1874,7 +1869,7 @@
 void gfxstream_vk_GetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice,
                                                      VkFormat format,
                                                      VkFormatProperties2* pFormatProperties) {
-    AEMU_SCOPED_TRACE("vkGetPhysicalDeviceFormatProperties2");
+    MESA_TRACE_SCOPE("vkGetPhysicalDeviceFormatProperties2");
     VK_FROM_HANDLE(gfxstream_vk_physical_device, gfxstream_physicalDevice, physicalDevice);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -1885,7 +1880,7 @@
 VkResult gfxstream_vk_GetPhysicalDeviceImageFormatProperties2(
     VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo,
     VkImageFormatProperties2* pImageFormatProperties) {
-    AEMU_SCOPED_TRACE("vkGetPhysicalDeviceImageFormatProperties2");
+    MESA_TRACE_SCOPE("vkGetPhysicalDeviceImageFormatProperties2");
     VkResult vkGetPhysicalDeviceImageFormatProperties2_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_physical_device, gfxstream_physicalDevice, physicalDevice);
     {
@@ -1901,7 +1896,7 @@
 void gfxstream_vk_GetPhysicalDeviceQueueFamilyProperties2(
     VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount,
     VkQueueFamilyProperties2* pQueueFamilyProperties) {
-    AEMU_SCOPED_TRACE("vkGetPhysicalDeviceQueueFamilyProperties2");
+    MESA_TRACE_SCOPE("vkGetPhysicalDeviceQueueFamilyProperties2");
     VK_FROM_HANDLE(gfxstream_vk_physical_device, gfxstream_physicalDevice, physicalDevice);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -1912,7 +1907,7 @@
 }
 void gfxstream_vk_GetPhysicalDeviceMemoryProperties2(
     VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2* pMemoryProperties) {
-    AEMU_SCOPED_TRACE("vkGetPhysicalDeviceMemoryProperties2");
+    MESA_TRACE_SCOPE("vkGetPhysicalDeviceMemoryProperties2");
     VK_FROM_HANDLE(gfxstream_vk_physical_device, gfxstream_physicalDevice, physicalDevice);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -1923,7 +1918,7 @@
 void gfxstream_vk_GetPhysicalDeviceSparseImageFormatProperties2(
     VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo,
     uint32_t* pPropertyCount, VkSparseImageFormatProperties2* pProperties) {
-    AEMU_SCOPED_TRACE("vkGetPhysicalDeviceSparseImageFormatProperties2");
+    MESA_TRACE_SCOPE("vkGetPhysicalDeviceSparseImageFormatProperties2");
     VK_FROM_HANDLE(gfxstream_vk_physical_device, gfxstream_physicalDevice, physicalDevice);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -1934,7 +1929,7 @@
 }
 void gfxstream_vk_TrimCommandPool(VkDevice device, VkCommandPool commandPool,
                                   VkCommandPoolTrimFlags flags) {
-    AEMU_SCOPED_TRACE("vkTrimCommandPool");
+    MESA_TRACE_SCOPE("vkTrimCommandPool");
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     VK_FROM_HANDLE(gfxstream_vk_command_pool, gfxstream_commandPool, commandPool);
     {
@@ -1946,7 +1941,7 @@
 VkResult gfxstream_vk_CreateSamplerYcbcrConversion(
     VkDevice device, const VkSamplerYcbcrConversionCreateInfo* pCreateInfo,
     const VkAllocationCallbacks* pAllocator, VkSamplerYcbcrConversion* pYcbcrConversion) {
-    AEMU_SCOPED_TRACE("vkCreateSamplerYcbcrConversion");
+    MESA_TRACE_SCOPE("vkCreateSamplerYcbcrConversion");
     VkResult vkCreateSamplerYcbcrConversion_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -1962,7 +1957,7 @@
 void gfxstream_vk_DestroySamplerYcbcrConversion(VkDevice device,
                                                 VkSamplerYcbcrConversion ycbcrConversion,
                                                 const VkAllocationCallbacks* pAllocator) {
-    AEMU_SCOPED_TRACE("vkDestroySamplerYcbcrConversion");
+    MESA_TRACE_SCOPE("vkDestroySamplerYcbcrConversion");
     if (VK_NULL_HANDLE == ycbcrConversion) {
         return;
     }
@@ -1978,7 +1973,7 @@
     VkDevice device, const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo,
     const VkAllocationCallbacks* pAllocator,
     VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate) {
-    AEMU_SCOPED_TRACE("vkCreateDescriptorUpdateTemplate");
+    MESA_TRACE_SCOPE("vkCreateDescriptorUpdateTemplate");
     VkResult vkCreateDescriptorUpdateTemplate_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -1992,7 +1987,7 @@
 void gfxstream_vk_DestroyDescriptorUpdateTemplate(
     VkDevice device, VkDescriptorUpdateTemplate descriptorUpdateTemplate,
     const VkAllocationCallbacks* pAllocator) {
-    AEMU_SCOPED_TRACE("vkDestroyDescriptorUpdateTemplate");
+    MESA_TRACE_SCOPE("vkDestroyDescriptorUpdateTemplate");
     if (VK_NULL_HANDLE == descriptorUpdateTemplate) {
         return;
     }
@@ -2007,7 +2002,7 @@
 void gfxstream_vk_UpdateDescriptorSetWithTemplate(
     VkDevice device, VkDescriptorSet descriptorSet,
     VkDescriptorUpdateTemplate descriptorUpdateTemplate, const void* pData) {
-    AEMU_SCOPED_TRACE("vkUpdateDescriptorSetWithTemplate");
+    MESA_TRACE_SCOPE("vkUpdateDescriptorSetWithTemplate");
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -2020,7 +2015,7 @@
 void gfxstream_vk_GetPhysicalDeviceExternalBufferProperties(
     VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo,
     VkExternalBufferProperties* pExternalBufferProperties) {
-    AEMU_SCOPED_TRACE("vkGetPhysicalDeviceExternalBufferProperties");
+    MESA_TRACE_SCOPE("vkGetPhysicalDeviceExternalBufferProperties");
     VK_FROM_HANDLE(gfxstream_vk_physical_device, gfxstream_physicalDevice, physicalDevice);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -2033,7 +2028,7 @@
 void gfxstream_vk_GetPhysicalDeviceExternalFenceProperties(
     VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo,
     VkExternalFenceProperties* pExternalFenceProperties) {
-    AEMU_SCOPED_TRACE("vkGetPhysicalDeviceExternalFenceProperties");
+    MESA_TRACE_SCOPE("vkGetPhysicalDeviceExternalFenceProperties");
     VK_FROM_HANDLE(gfxstream_vk_physical_device, gfxstream_physicalDevice, physicalDevice);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -2047,7 +2042,7 @@
     VkPhysicalDevice physicalDevice,
     const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo,
     VkExternalSemaphoreProperties* pExternalSemaphoreProperties) {
-    AEMU_SCOPED_TRACE("vkGetPhysicalDeviceExternalSemaphoreProperties");
+    MESA_TRACE_SCOPE("vkGetPhysicalDeviceExternalSemaphoreProperties");
     VK_FROM_HANDLE(gfxstream_vk_physical_device, gfxstream_physicalDevice, physicalDevice);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -2059,7 +2054,7 @@
 void gfxstream_vk_GetDescriptorSetLayoutSupport(VkDevice device,
                                                 const VkDescriptorSetLayoutCreateInfo* pCreateInfo,
                                                 VkDescriptorSetLayoutSupport* pSupport) {
-    AEMU_SCOPED_TRACE("vkGetDescriptorSetLayoutSupport");
+    MESA_TRACE_SCOPE("vkGetDescriptorSetLayoutSupport");
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -2073,7 +2068,7 @@
                                        VkDeviceSize offset, VkBuffer countBuffer,
                                        VkDeviceSize countBufferOffset, uint32_t maxDrawCount,
                                        uint32_t stride) {
-    AEMU_SCOPED_TRACE("vkCmdDrawIndirectCount");
+    MESA_TRACE_SCOPE("vkCmdDrawIndirectCount");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     VK_FROM_HANDLE(gfxstream_vk_buffer, gfxstream_buffer, buffer);
     VK_FROM_HANDLE(gfxstream_vk_buffer, gfxstream_countBuffer, countBuffer);
@@ -2090,7 +2085,7 @@
                                               VkDeviceSize offset, VkBuffer countBuffer,
                                               VkDeviceSize countBufferOffset, uint32_t maxDrawCount,
                                               uint32_t stride) {
-    AEMU_SCOPED_TRACE("vkCmdDrawIndexedIndirectCount");
+    MESA_TRACE_SCOPE("vkCmdDrawIndexedIndirectCount");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     VK_FROM_HANDLE(gfxstream_vk_buffer, gfxstream_buffer, buffer);
     VK_FROM_HANDLE(gfxstream_vk_buffer, gfxstream_countBuffer, countBuffer);
@@ -2106,7 +2101,7 @@
 VkResult gfxstream_vk_CreateRenderPass2(VkDevice device, const VkRenderPassCreateInfo2* pCreateInfo,
                                         const VkAllocationCallbacks* pAllocator,
                                         VkRenderPass* pRenderPass) {
-    AEMU_SCOPED_TRACE("vkCreateRenderPass2");
+    MESA_TRACE_SCOPE("vkCreateRenderPass2");
     VkResult vkCreateRenderPass2_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -2120,7 +2115,7 @@
 void gfxstream_vk_CmdBeginRenderPass2(VkCommandBuffer commandBuffer,
                                       const VkRenderPassBeginInfo* pRenderPassBegin,
                                       const VkSubpassBeginInfo* pSubpassBeginInfo) {
-    AEMU_SCOPED_TRACE("vkCmdBeginRenderPass2");
+    MESA_TRACE_SCOPE("vkCmdBeginRenderPass2");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -2132,7 +2127,7 @@
 void gfxstream_vk_CmdNextSubpass2(VkCommandBuffer commandBuffer,
                                   const VkSubpassBeginInfo* pSubpassBeginInfo,
                                   const VkSubpassEndInfo* pSubpassEndInfo) {
-    AEMU_SCOPED_TRACE("vkCmdNextSubpass2");
+    MESA_TRACE_SCOPE("vkCmdNextSubpass2");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -2143,7 +2138,7 @@
 }
 void gfxstream_vk_CmdEndRenderPass2(VkCommandBuffer commandBuffer,
                                     const VkSubpassEndInfo* pSubpassEndInfo) {
-    AEMU_SCOPED_TRACE("vkCmdEndRenderPass2");
+    MESA_TRACE_SCOPE("vkCmdEndRenderPass2");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -2154,7 +2149,7 @@
 }
 void gfxstream_vk_ResetQueryPool(VkDevice device, VkQueryPool queryPool, uint32_t firstQuery,
                                  uint32_t queryCount) {
-    AEMU_SCOPED_TRACE("vkResetQueryPool");
+    MESA_TRACE_SCOPE("vkResetQueryPool");
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -2164,7 +2159,7 @@
 }
 VkResult gfxstream_vk_GetSemaphoreCounterValue(VkDevice device, VkSemaphore semaphore,
                                                uint64_t* pValue) {
-    AEMU_SCOPED_TRACE("vkGetSemaphoreCounterValue");
+    MESA_TRACE_SCOPE("vkGetSemaphoreCounterValue");
     VkResult vkGetSemaphoreCounterValue_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     VK_FROM_HANDLE(gfxstream_vk_semaphore, gfxstream_semaphore, semaphore);
@@ -2178,7 +2173,7 @@
 }
 VkResult gfxstream_vk_WaitSemaphores(VkDevice device, const VkSemaphoreWaitInfo* pWaitInfo,
                                      uint64_t timeout) {
-    AEMU_SCOPED_TRACE("vkWaitSemaphores");
+    MESA_TRACE_SCOPE("vkWaitSemaphores");
     VkResult vkWaitSemaphores_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -2202,7 +2197,7 @@
     return vkWaitSemaphores_VkResult_return;
 }
 VkResult gfxstream_vk_SignalSemaphore(VkDevice device, const VkSemaphoreSignalInfo* pSignalInfo) {
-    AEMU_SCOPED_TRACE("vkSignalSemaphore");
+    MESA_TRACE_SCOPE("vkSignalSemaphore");
     VkResult vkSignalSemaphore_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -2222,7 +2217,7 @@
 }
 VkDeviceAddress gfxstream_vk_GetBufferDeviceAddress(VkDevice device,
                                                     const VkBufferDeviceAddressInfo* pInfo) {
-    AEMU_SCOPED_TRACE("vkGetBufferDeviceAddress");
+    MESA_TRACE_SCOPE("vkGetBufferDeviceAddress");
     VkDeviceAddress vkGetBufferDeviceAddress_VkDeviceAddress_return = (VkDeviceAddress)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -2241,7 +2236,7 @@
 }
 uint64_t gfxstream_vk_GetBufferOpaqueCaptureAddress(VkDevice device,
                                                     const VkBufferDeviceAddressInfo* pInfo) {
-    AEMU_SCOPED_TRACE("vkGetBufferOpaqueCaptureAddress");
+    MESA_TRACE_SCOPE("vkGetBufferOpaqueCaptureAddress");
     uint64_t vkGetBufferOpaqueCaptureAddress_uint64_t_return = (uint64_t)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -2260,7 +2255,7 @@
 }
 uint64_t gfxstream_vk_GetDeviceMemoryOpaqueCaptureAddress(
     VkDevice device, const VkDeviceMemoryOpaqueCaptureAddressInfo* pInfo) {
-    AEMU_SCOPED_TRACE("vkGetDeviceMemoryOpaqueCaptureAddress");
+    MESA_TRACE_SCOPE("vkGetDeviceMemoryOpaqueCaptureAddress");
     uint64_t vkGetDeviceMemoryOpaqueCaptureAddress_uint64_t_return = (uint64_t)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -2276,7 +2271,7 @@
 VkResult gfxstream_vk_GetPhysicalDeviceToolProperties(
     VkPhysicalDevice physicalDevice, uint32_t* pToolCount,
     VkPhysicalDeviceToolProperties* pToolProperties) {
-    AEMU_SCOPED_TRACE("vkGetPhysicalDeviceToolProperties");
+    MESA_TRACE_SCOPE("vkGetPhysicalDeviceToolProperties");
     VkResult vkGetPhysicalDeviceToolProperties_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_physical_device, gfxstream_physicalDevice, physicalDevice);
     {
@@ -2292,7 +2287,7 @@
                                             const VkPrivateDataSlotCreateInfo* pCreateInfo,
                                             const VkAllocationCallbacks* pAllocator,
                                             VkPrivateDataSlot* pPrivateDataSlot) {
-    AEMU_SCOPED_TRACE("vkCreatePrivateDataSlot");
+    MESA_TRACE_SCOPE("vkCreatePrivateDataSlot");
     VkResult vkCreatePrivateDataSlot_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -2305,7 +2300,7 @@
 }
 void gfxstream_vk_DestroyPrivateDataSlot(VkDevice device, VkPrivateDataSlot privateDataSlot,
                                          const VkAllocationCallbacks* pAllocator) {
-    AEMU_SCOPED_TRACE("vkDestroyPrivateDataSlot");
+    MESA_TRACE_SCOPE("vkDestroyPrivateDataSlot");
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -2316,7 +2311,7 @@
 VkResult gfxstream_vk_SetPrivateData(VkDevice device, VkObjectType objectType,
                                      uint64_t objectHandle, VkPrivateDataSlot privateDataSlot,
                                      uint64_t data) {
-    AEMU_SCOPED_TRACE("vkSetPrivateData");
+    MESA_TRACE_SCOPE("vkSetPrivateData");
     VkResult vkSetPrivateData_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -2329,7 +2324,7 @@
 }
 void gfxstream_vk_GetPrivateData(VkDevice device, VkObjectType objectType, uint64_t objectHandle,
                                  VkPrivateDataSlot privateDataSlot, uint64_t* pData) {
-    AEMU_SCOPED_TRACE("vkGetPrivateData");
+    MESA_TRACE_SCOPE("vkGetPrivateData");
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -2339,7 +2334,7 @@
 }
 void gfxstream_vk_CmdSetEvent2(VkCommandBuffer commandBuffer, VkEvent event,
                                const VkDependencyInfo* pDependencyInfo) {
-    AEMU_SCOPED_TRACE("vkCmdSetEvent2");
+    MESA_TRACE_SCOPE("vkCmdSetEvent2");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -2352,11 +2347,8 @@
             /* VkDependencyInfo::pBufferMemoryBarriers */
             internal_VkDependencyInfo_pBufferMemoryBarriers.push_back(
                 std::vector<VkBufferMemoryBarrier2>());
-            internal_VkDependencyInfo_pBufferMemoryBarriers[i].reserve(
+            internal_VkDependencyInfo_pBufferMemoryBarriers[i].resize(
                 internal_pDependencyInfo[i].bufferMemoryBarrierCount);
-            memset(&internal_VkDependencyInfo_pBufferMemoryBarriers[i][0], 0,
-                   sizeof(VkBufferMemoryBarrier2) *
-                       internal_pDependencyInfo[i].bufferMemoryBarrierCount);
             for (uint32_t j = 0; j < internal_pDependencyInfo[i].bufferMemoryBarrierCount; ++j) {
                 internal_VkDependencyInfo_pBufferMemoryBarriers[i][j] =
                     internal_pDependencyInfo[i].pBufferMemoryBarriers[j];
@@ -2375,7 +2367,7 @@
 }
 void gfxstream_vk_CmdResetEvent2(VkCommandBuffer commandBuffer, VkEvent event,
                                  VkPipelineStageFlags2 stageMask) {
-    AEMU_SCOPED_TRACE("vkCmdResetEvent2");
+    MESA_TRACE_SCOPE("vkCmdResetEvent2");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -2386,7 +2378,7 @@
 }
 void gfxstream_vk_CmdWaitEvents2(VkCommandBuffer commandBuffer, uint32_t eventCount,
                                  const VkEvent* pEvents, const VkDependencyInfo* pDependencyInfos) {
-    AEMU_SCOPED_TRACE("vkCmdWaitEvents2");
+    MESA_TRACE_SCOPE("vkCmdWaitEvents2");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -2399,11 +2391,8 @@
             /* VkDependencyInfo::pBufferMemoryBarriers */
             internal_VkDependencyInfo_pBufferMemoryBarriers.push_back(
                 std::vector<VkBufferMemoryBarrier2>());
-            internal_VkDependencyInfo_pBufferMemoryBarriers[i].reserve(
+            internal_VkDependencyInfo_pBufferMemoryBarriers[i].resize(
                 internal_pDependencyInfos[i].bufferMemoryBarrierCount);
-            memset(&internal_VkDependencyInfo_pBufferMemoryBarriers[i][0], 0,
-                   sizeof(VkBufferMemoryBarrier2) *
-                       internal_pDependencyInfos[i].bufferMemoryBarrierCount);
             for (uint32_t j = 0; j < internal_pDependencyInfos[i].bufferMemoryBarrierCount; ++j) {
                 internal_VkDependencyInfo_pBufferMemoryBarriers[i][j] =
                     internal_pDependencyInfos[i].pBufferMemoryBarriers[j];
@@ -2422,7 +2411,7 @@
 }
 void gfxstream_vk_CmdPipelineBarrier2(VkCommandBuffer commandBuffer,
                                       const VkDependencyInfo* pDependencyInfo) {
-    AEMU_SCOPED_TRACE("vkCmdPipelineBarrier2");
+    MESA_TRACE_SCOPE("vkCmdPipelineBarrier2");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -2435,11 +2424,8 @@
             /* VkDependencyInfo::pBufferMemoryBarriers */
             internal_VkDependencyInfo_pBufferMemoryBarriers.push_back(
                 std::vector<VkBufferMemoryBarrier2>());
-            internal_VkDependencyInfo_pBufferMemoryBarriers[i].reserve(
+            internal_VkDependencyInfo_pBufferMemoryBarriers[i].resize(
                 internal_pDependencyInfo[i].bufferMemoryBarrierCount);
-            memset(&internal_VkDependencyInfo_pBufferMemoryBarriers[i][0], 0,
-                   sizeof(VkBufferMemoryBarrier2) *
-                       internal_pDependencyInfo[i].bufferMemoryBarrierCount);
             for (uint32_t j = 0; j < internal_pDependencyInfo[i].bufferMemoryBarrierCount; ++j) {
                 internal_VkDependencyInfo_pBufferMemoryBarriers[i][j] =
                     internal_pDependencyInfo[i].pBufferMemoryBarriers[j];
@@ -2458,7 +2444,7 @@
 }
 void gfxstream_vk_CmdWriteTimestamp2(VkCommandBuffer commandBuffer, VkPipelineStageFlags2 stage,
                                      VkQueryPool queryPool, uint32_t query) {
-    AEMU_SCOPED_TRACE("vkCmdWriteTimestamp2");
+    MESA_TRACE_SCOPE("vkCmdWriteTimestamp2");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -2469,7 +2455,7 @@
 }
 VkResult gfxstream_vk_QueueSubmit2(VkQueue queue, uint32_t submitCount,
                                    const VkSubmitInfo2* pSubmits, VkFence fence) {
-    AEMU_SCOPED_TRACE("vkQueueSubmit2");
+    MESA_TRACE_SCOPE("vkQueueSubmit2");
     VkResult vkQueueSubmit2_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_queue, gfxstream_queue, queue);
     VK_FROM_HANDLE(gfxstream_vk_fence, gfxstream_fence, fence);
@@ -2497,10 +2483,8 @@
             /* VkSubmitInfo2::pCommandBufferInfos */
             internal_VkSubmitInfo2_pCommandBufferInfos.push_back(
                 std::vector<VkCommandBufferSubmitInfo>());
-            internal_VkSubmitInfo2_pCommandBufferInfos[i].reserve(
+            internal_VkSubmitInfo2_pCommandBufferInfos[i].resize(
                 internal_pSubmits[i].commandBufferInfoCount);
-            memset(&internal_VkSubmitInfo2_pCommandBufferInfos[i][0], 0,
-                   sizeof(VkCommandBufferSubmitInfo) * internal_pSubmits[i].commandBufferInfoCount);
             for (uint32_t j = 0; j < internal_pSubmits[i].commandBufferInfoCount; ++j) {
                 internal_VkSubmitInfo2_pCommandBufferInfos[i][j] =
                     internal_pSubmits[i].pCommandBufferInfos[j];
@@ -2533,7 +2517,7 @@
 }
 void gfxstream_vk_CmdCopyBuffer2(VkCommandBuffer commandBuffer,
                                  const VkCopyBufferInfo2* pCopyBufferInfo) {
-    AEMU_SCOPED_TRACE("vkCmdCopyBuffer2");
+    MESA_TRACE_SCOPE("vkCmdCopyBuffer2");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -2556,7 +2540,7 @@
 }
 void gfxstream_vk_CmdCopyImage2(VkCommandBuffer commandBuffer,
                                 const VkCopyImageInfo2* pCopyImageInfo) {
-    AEMU_SCOPED_TRACE("vkCmdCopyImage2");
+    MESA_TRACE_SCOPE("vkCmdCopyImage2");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -2567,7 +2551,7 @@
 }
 void gfxstream_vk_CmdCopyBufferToImage2(VkCommandBuffer commandBuffer,
                                         const VkCopyBufferToImageInfo2* pCopyBufferToImageInfo) {
-    AEMU_SCOPED_TRACE("vkCmdCopyBufferToImage2");
+    MESA_TRACE_SCOPE("vkCmdCopyBufferToImage2");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -2586,7 +2570,7 @@
 }
 void gfxstream_vk_CmdCopyImageToBuffer2(VkCommandBuffer commandBuffer,
                                         const VkCopyImageToBufferInfo2* pCopyImageToBufferInfo) {
-    AEMU_SCOPED_TRACE("vkCmdCopyImageToBuffer2");
+    MESA_TRACE_SCOPE("vkCmdCopyImageToBuffer2");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -2605,7 +2589,7 @@
 }
 void gfxstream_vk_CmdBlitImage2(VkCommandBuffer commandBuffer,
                                 const VkBlitImageInfo2* pBlitImageInfo) {
-    AEMU_SCOPED_TRACE("vkCmdBlitImage2");
+    MESA_TRACE_SCOPE("vkCmdBlitImage2");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -2616,7 +2600,7 @@
 }
 void gfxstream_vk_CmdResolveImage2(VkCommandBuffer commandBuffer,
                                    const VkResolveImageInfo2* pResolveImageInfo) {
-    AEMU_SCOPED_TRACE("vkCmdResolveImage2");
+    MESA_TRACE_SCOPE("vkCmdResolveImage2");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -2627,7 +2611,7 @@
 }
 void gfxstream_vk_CmdBeginRendering(VkCommandBuffer commandBuffer,
                                     const VkRenderingInfo* pRenderingInfo) {
-    AEMU_SCOPED_TRACE("vkCmdBeginRendering");
+    MESA_TRACE_SCOPE("vkCmdBeginRendering");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -2637,7 +2621,7 @@
     }
 }
 void gfxstream_vk_CmdEndRendering(VkCommandBuffer commandBuffer) {
-    AEMU_SCOPED_TRACE("vkCmdEndRendering");
+    MESA_TRACE_SCOPE("vkCmdEndRendering");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -2646,7 +2630,7 @@
     }
 }
 void gfxstream_vk_CmdSetCullMode(VkCommandBuffer commandBuffer, VkCullModeFlags cullMode) {
-    AEMU_SCOPED_TRACE("vkCmdSetCullMode");
+    MESA_TRACE_SCOPE("vkCmdSetCullMode");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -2656,7 +2640,7 @@
     }
 }
 void gfxstream_vk_CmdSetFrontFace(VkCommandBuffer commandBuffer, VkFrontFace frontFace) {
-    AEMU_SCOPED_TRACE("vkCmdSetFrontFace");
+    MESA_TRACE_SCOPE("vkCmdSetFrontFace");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -2667,7 +2651,7 @@
 }
 void gfxstream_vk_CmdSetPrimitiveTopology(VkCommandBuffer commandBuffer,
                                           VkPrimitiveTopology primitiveTopology) {
-    AEMU_SCOPED_TRACE("vkCmdSetPrimitiveTopology");
+    MESA_TRACE_SCOPE("vkCmdSetPrimitiveTopology");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -2678,7 +2662,7 @@
 }
 void gfxstream_vk_CmdSetViewportWithCount(VkCommandBuffer commandBuffer, uint32_t viewportCount,
                                           const VkViewport* pViewports) {
-    AEMU_SCOPED_TRACE("vkCmdSetViewportWithCount");
+    MESA_TRACE_SCOPE("vkCmdSetViewportWithCount");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -2689,7 +2673,7 @@
 }
 void gfxstream_vk_CmdSetScissorWithCount(VkCommandBuffer commandBuffer, uint32_t scissorCount,
                                          const VkRect2D* pScissors) {
-    AEMU_SCOPED_TRACE("vkCmdSetScissorWithCount");
+    MESA_TRACE_SCOPE("vkCmdSetScissorWithCount");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -2702,7 +2686,7 @@
                                         uint32_t bindingCount, const VkBuffer* pBuffers,
                                         const VkDeviceSize* pOffsets, const VkDeviceSize* pSizes,
                                         const VkDeviceSize* pStrides) {
-    AEMU_SCOPED_TRACE("vkCmdBindVertexBuffers2");
+    MESA_TRACE_SCOPE("vkCmdBindVertexBuffers2");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -2720,7 +2704,7 @@
     }
 }
 void gfxstream_vk_CmdSetDepthTestEnable(VkCommandBuffer commandBuffer, VkBool32 depthTestEnable) {
-    AEMU_SCOPED_TRACE("vkCmdSetDepthTestEnable");
+    MESA_TRACE_SCOPE("vkCmdSetDepthTestEnable");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -2730,7 +2714,7 @@
     }
 }
 void gfxstream_vk_CmdSetDepthWriteEnable(VkCommandBuffer commandBuffer, VkBool32 depthWriteEnable) {
-    AEMU_SCOPED_TRACE("vkCmdSetDepthWriteEnable");
+    MESA_TRACE_SCOPE("vkCmdSetDepthWriteEnable");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -2740,7 +2724,7 @@
     }
 }
 void gfxstream_vk_CmdSetDepthCompareOp(VkCommandBuffer commandBuffer, VkCompareOp depthCompareOp) {
-    AEMU_SCOPED_TRACE("vkCmdSetDepthCompareOp");
+    MESA_TRACE_SCOPE("vkCmdSetDepthCompareOp");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -2751,7 +2735,7 @@
 }
 void gfxstream_vk_CmdSetDepthBoundsTestEnable(VkCommandBuffer commandBuffer,
                                               VkBool32 depthBoundsTestEnable) {
-    AEMU_SCOPED_TRACE("vkCmdSetDepthBoundsTestEnable");
+    MESA_TRACE_SCOPE("vkCmdSetDepthBoundsTestEnable");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -2762,7 +2746,7 @@
 }
 void gfxstream_vk_CmdSetStencilTestEnable(VkCommandBuffer commandBuffer,
                                           VkBool32 stencilTestEnable) {
-    AEMU_SCOPED_TRACE("vkCmdSetStencilTestEnable");
+    MESA_TRACE_SCOPE("vkCmdSetStencilTestEnable");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -2774,7 +2758,7 @@
 void gfxstream_vk_CmdSetStencilOp(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask,
                                   VkStencilOp failOp, VkStencilOp passOp, VkStencilOp depthFailOp,
                                   VkCompareOp compareOp) {
-    AEMU_SCOPED_TRACE("vkCmdSetStencilOp");
+    MESA_TRACE_SCOPE("vkCmdSetStencilOp");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -2785,7 +2769,7 @@
 }
 void gfxstream_vk_CmdSetRasterizerDiscardEnable(VkCommandBuffer commandBuffer,
                                                 VkBool32 rasterizerDiscardEnable) {
-    AEMU_SCOPED_TRACE("vkCmdSetRasterizerDiscardEnable");
+    MESA_TRACE_SCOPE("vkCmdSetRasterizerDiscardEnable");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -2795,7 +2779,7 @@
     }
 }
 void gfxstream_vk_CmdSetDepthBiasEnable(VkCommandBuffer commandBuffer, VkBool32 depthBiasEnable) {
-    AEMU_SCOPED_TRACE("vkCmdSetDepthBiasEnable");
+    MESA_TRACE_SCOPE("vkCmdSetDepthBiasEnable");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -2806,7 +2790,7 @@
 }
 void gfxstream_vk_CmdSetPrimitiveRestartEnable(VkCommandBuffer commandBuffer,
                                                VkBool32 primitiveRestartEnable) {
-    AEMU_SCOPED_TRACE("vkCmdSetPrimitiveRestartEnable");
+    MESA_TRACE_SCOPE("vkCmdSetPrimitiveRestartEnable");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -2818,7 +2802,7 @@
 void gfxstream_vk_GetDeviceBufferMemoryRequirements(VkDevice device,
                                                     const VkDeviceBufferMemoryRequirements* pInfo,
                                                     VkMemoryRequirements2* pMemoryRequirements) {
-    AEMU_SCOPED_TRACE("vkGetDeviceBufferMemoryRequirements");
+    MESA_TRACE_SCOPE("vkGetDeviceBufferMemoryRequirements");
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -2829,7 +2813,7 @@
 void gfxstream_vk_GetDeviceImageMemoryRequirements(VkDevice device,
                                                    const VkDeviceImageMemoryRequirements* pInfo,
                                                    VkMemoryRequirements2* pMemoryRequirements) {
-    AEMU_SCOPED_TRACE("vkGetDeviceImageMemoryRequirements");
+    MESA_TRACE_SCOPE("vkGetDeviceImageMemoryRequirements");
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -2841,7 +2825,7 @@
     VkDevice device, const VkDeviceImageMemoryRequirements* pInfo,
     uint32_t* pSparseMemoryRequirementCount,
     VkSparseImageMemoryRequirements2* pSparseMemoryRequirements) {
-    AEMU_SCOPED_TRACE("vkGetDeviceImageSparseMemoryRequirements");
+    MESA_TRACE_SCOPE("vkGetDeviceImageSparseMemoryRequirements");
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -2851,18 +2835,12 @@
     }
 }
 #endif
-#ifdef VK_KHR_surface
-#endif
-#ifdef VK_KHR_swapchain
-#endif
-#ifdef VK_KHR_xcb_surface
-#endif
 #ifdef VK_KHR_android_surface
 VkResult gfxstream_vk_CreateAndroidSurfaceKHR(VkInstance instance,
                                               const VkAndroidSurfaceCreateInfoKHR* pCreateInfo,
                                               const VkAllocationCallbacks* pAllocator,
                                               VkSurfaceKHR* pSurface) {
-    AEMU_SCOPED_TRACE("vkCreateAndroidSurfaceKHR");
+    MESA_TRACE_SCOPE("vkCreateAndroidSurfaceKHR");
     VkResult vkCreateAndroidSurfaceKHR_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_instance, gfxstream_instance, instance);
     {
@@ -2874,12 +2852,10 @@
     return vkCreateAndroidSurfaceKHR_VkResult_return;
 }
 #endif
-#ifdef VK_KHR_win32_surface
-#endif
 #ifdef VK_KHR_dynamic_rendering
 void gfxstream_vk_CmdBeginRenderingKHR(VkCommandBuffer commandBuffer,
                                        const VkRenderingInfo* pRenderingInfo) {
-    AEMU_SCOPED_TRACE("vkCmdBeginRenderingKHR");
+    MESA_TRACE_SCOPE("vkCmdBeginRenderingKHR");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -2889,7 +2865,7 @@
     }
 }
 void gfxstream_vk_CmdEndRenderingKHR(VkCommandBuffer commandBuffer) {
-    AEMU_SCOPED_TRACE("vkCmdEndRenderingKHR");
+    MESA_TRACE_SCOPE("vkCmdEndRenderingKHR");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -2901,7 +2877,7 @@
 #ifdef VK_KHR_get_physical_device_properties2
 void gfxstream_vk_GetPhysicalDeviceFeatures2KHR(VkPhysicalDevice physicalDevice,
                                                 VkPhysicalDeviceFeatures2* pFeatures) {
-    AEMU_SCOPED_TRACE("vkGetPhysicalDeviceFeatures2KHR");
+    MESA_TRACE_SCOPE("vkGetPhysicalDeviceFeatures2KHR");
     VK_FROM_HANDLE(gfxstream_vk_physical_device, gfxstream_physicalDevice, physicalDevice);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -2911,7 +2887,7 @@
 }
 void gfxstream_vk_GetPhysicalDeviceProperties2KHR(VkPhysicalDevice physicalDevice,
                                                   VkPhysicalDeviceProperties2* pProperties) {
-    AEMU_SCOPED_TRACE("vkGetPhysicalDeviceProperties2KHR");
+    MESA_TRACE_SCOPE("vkGetPhysicalDeviceProperties2KHR");
     VK_FROM_HANDLE(gfxstream_vk_physical_device, gfxstream_physicalDevice, physicalDevice);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -2922,7 +2898,7 @@
 void gfxstream_vk_GetPhysicalDeviceFormatProperties2KHR(VkPhysicalDevice physicalDevice,
                                                         VkFormat format,
                                                         VkFormatProperties2* pFormatProperties) {
-    AEMU_SCOPED_TRACE("vkGetPhysicalDeviceFormatProperties2KHR");
+    MESA_TRACE_SCOPE("vkGetPhysicalDeviceFormatProperties2KHR");
     VK_FROM_HANDLE(gfxstream_vk_physical_device, gfxstream_physicalDevice, physicalDevice);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -2934,7 +2910,7 @@
 VkResult gfxstream_vk_GetPhysicalDeviceImageFormatProperties2KHR(
     VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo,
     VkImageFormatProperties2* pImageFormatProperties) {
-    AEMU_SCOPED_TRACE("vkGetPhysicalDeviceImageFormatProperties2KHR");
+    MESA_TRACE_SCOPE("vkGetPhysicalDeviceImageFormatProperties2KHR");
     VkResult vkGetPhysicalDeviceImageFormatProperties2KHR_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_physical_device, gfxstream_physicalDevice, physicalDevice);
     {
@@ -2950,7 +2926,7 @@
 void gfxstream_vk_GetPhysicalDeviceQueueFamilyProperties2KHR(
     VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount,
     VkQueueFamilyProperties2* pQueueFamilyProperties) {
-    AEMU_SCOPED_TRACE("vkGetPhysicalDeviceQueueFamilyProperties2KHR");
+    MESA_TRACE_SCOPE("vkGetPhysicalDeviceQueueFamilyProperties2KHR");
     VK_FROM_HANDLE(gfxstream_vk_physical_device, gfxstream_physicalDevice, physicalDevice);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -2961,7 +2937,7 @@
 }
 void gfxstream_vk_GetPhysicalDeviceMemoryProperties2KHR(
     VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2* pMemoryProperties) {
-    AEMU_SCOPED_TRACE("vkGetPhysicalDeviceMemoryProperties2KHR");
+    MESA_TRACE_SCOPE("vkGetPhysicalDeviceMemoryProperties2KHR");
     VK_FROM_HANDLE(gfxstream_vk_physical_device, gfxstream_physicalDevice, physicalDevice);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -2972,7 +2948,7 @@
 void gfxstream_vk_GetPhysicalDeviceSparseImageFormatProperties2KHR(
     VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo,
     uint32_t* pPropertyCount, VkSparseImageFormatProperties2* pProperties) {
-    AEMU_SCOPED_TRACE("vkGetPhysicalDeviceSparseImageFormatProperties2KHR");
+    MESA_TRACE_SCOPE("vkGetPhysicalDeviceSparseImageFormatProperties2KHR");
     VK_FROM_HANDLE(gfxstream_vk_physical_device, gfxstream_physicalDevice, physicalDevice);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -2985,7 +2961,7 @@
 #ifdef VK_KHR_maintenance1
 void gfxstream_vk_TrimCommandPoolKHR(VkDevice device, VkCommandPool commandPool,
                                      VkCommandPoolTrimFlags flags) {
-    AEMU_SCOPED_TRACE("vkTrimCommandPoolKHR");
+    MESA_TRACE_SCOPE("vkTrimCommandPoolKHR");
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     VK_FROM_HANDLE(gfxstream_vk_command_pool, gfxstream_commandPool, commandPool);
     {
@@ -3000,7 +2976,7 @@
 void gfxstream_vk_GetPhysicalDeviceExternalBufferPropertiesKHR(
     VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo,
     VkExternalBufferProperties* pExternalBufferProperties) {
-    AEMU_SCOPED_TRACE("vkGetPhysicalDeviceExternalBufferPropertiesKHR");
+    MESA_TRACE_SCOPE("vkGetPhysicalDeviceExternalBufferPropertiesKHR");
     VK_FROM_HANDLE(gfxstream_vk_physical_device, gfxstream_physicalDevice, physicalDevice);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -3011,14 +2987,10 @@
     }
 }
 #endif
-#ifdef VK_KHR_external_memory
-#endif
-#ifdef VK_KHR_external_memory_win32
-#endif
 #ifdef VK_KHR_external_memory_fd
 VkResult gfxstream_vk_GetMemoryFdKHR(VkDevice device, const VkMemoryGetFdInfoKHR* pGetFdInfo,
                                      int* pFd) {
-    AEMU_SCOPED_TRACE("vkGetMemoryFdKHR");
+    MESA_TRACE_SCOPE("vkGetMemoryFdKHR");
     VkResult vkGetMemoryFdKHR_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -3033,7 +3005,7 @@
                                                VkExternalMemoryHandleTypeFlagBits handleType,
                                                int fd,
                                                VkMemoryFdPropertiesKHR* pMemoryFdProperties) {
-    AEMU_SCOPED_TRACE("vkGetMemoryFdPropertiesKHR");
+    MESA_TRACE_SCOPE("vkGetMemoryFdPropertiesKHR");
     VkResult vkGetMemoryFdPropertiesKHR_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -3051,7 +3023,7 @@
     VkPhysicalDevice physicalDevice,
     const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo,
     VkExternalSemaphoreProperties* pExternalSemaphoreProperties) {
-    AEMU_SCOPED_TRACE("vkGetPhysicalDeviceExternalSemaphorePropertiesKHR");
+    MESA_TRACE_SCOPE("vkGetPhysicalDeviceExternalSemaphorePropertiesKHR");
     VK_FROM_HANDLE(gfxstream_vk_physical_device, gfxstream_physicalDevice, physicalDevice);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -3061,14 +3033,10 @@
     }
 }
 #endif
-#ifdef VK_KHR_external_semaphore
-#endif
-#ifdef VK_KHR_external_semaphore_win32
-#endif
 #ifdef VK_KHR_external_semaphore_fd
 VkResult gfxstream_vk_ImportSemaphoreFdKHR(
     VkDevice device, const VkImportSemaphoreFdInfoKHR* pImportSemaphoreFdInfo) {
-    AEMU_SCOPED_TRACE("vkImportSemaphoreFdKHR");
+    MESA_TRACE_SCOPE("vkImportSemaphoreFdKHR");
     VkResult vkImportSemaphoreFdKHR_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -3090,7 +3058,7 @@
 }
 VkResult gfxstream_vk_GetSemaphoreFdKHR(VkDevice device, const VkSemaphoreGetFdInfoKHR* pGetFdInfo,
                                         int* pFd) {
-    AEMU_SCOPED_TRACE("vkGetSemaphoreFdKHR");
+    MESA_TRACE_SCOPE("vkGetSemaphoreFdKHR");
     VkResult vkGetSemaphoreFdKHR_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -3110,16 +3078,12 @@
     return vkGetSemaphoreFdKHR_VkResult_return;
 }
 #endif
-#ifdef VK_KHR_shader_float16_int8
-#endif
-#ifdef VK_KHR_incremental_present
-#endif
 #ifdef VK_KHR_descriptor_update_template
 VkResult gfxstream_vk_CreateDescriptorUpdateTemplateKHR(
     VkDevice device, const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo,
     const VkAllocationCallbacks* pAllocator,
     VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate) {
-    AEMU_SCOPED_TRACE("vkCreateDescriptorUpdateTemplateKHR");
+    MESA_TRACE_SCOPE("vkCreateDescriptorUpdateTemplateKHR");
     VkResult vkCreateDescriptorUpdateTemplateKHR_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -3134,7 +3098,7 @@
 void gfxstream_vk_DestroyDescriptorUpdateTemplateKHR(
     VkDevice device, VkDescriptorUpdateTemplate descriptorUpdateTemplate,
     const VkAllocationCallbacks* pAllocator) {
-    AEMU_SCOPED_TRACE("vkDestroyDescriptorUpdateTemplateKHR");
+    MESA_TRACE_SCOPE("vkDestroyDescriptorUpdateTemplateKHR");
     if (VK_NULL_HANDLE == descriptorUpdateTemplate) {
         return;
     }
@@ -3149,7 +3113,7 @@
 void gfxstream_vk_UpdateDescriptorSetWithTemplateKHR(
     VkDevice device, VkDescriptorSet descriptorSet,
     VkDescriptorUpdateTemplate descriptorUpdateTemplate, const void* pData) {
-    AEMU_SCOPED_TRACE("vkUpdateDescriptorSetWithTemplateKHR");
+    MESA_TRACE_SCOPE("vkUpdateDescriptorSetWithTemplateKHR");
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -3160,14 +3124,12 @@
     }
 }
 #endif
-#ifdef VK_KHR_imageless_framebuffer
-#endif
 #ifdef VK_KHR_create_renderpass2
 VkResult gfxstream_vk_CreateRenderPass2KHR(VkDevice device,
                                            const VkRenderPassCreateInfo2* pCreateInfo,
                                            const VkAllocationCallbacks* pAllocator,
                                            VkRenderPass* pRenderPass) {
-    AEMU_SCOPED_TRACE("vkCreateRenderPass2KHR");
+    MESA_TRACE_SCOPE("vkCreateRenderPass2KHR");
     VkResult vkCreateRenderPass2KHR_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -3181,7 +3143,7 @@
 void gfxstream_vk_CmdBeginRenderPass2KHR(VkCommandBuffer commandBuffer,
                                          const VkRenderPassBeginInfo* pRenderPassBegin,
                                          const VkSubpassBeginInfo* pSubpassBeginInfo) {
-    AEMU_SCOPED_TRACE("vkCmdBeginRenderPass2KHR");
+    MESA_TRACE_SCOPE("vkCmdBeginRenderPass2KHR");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -3193,7 +3155,7 @@
 void gfxstream_vk_CmdNextSubpass2KHR(VkCommandBuffer commandBuffer,
                                      const VkSubpassBeginInfo* pSubpassBeginInfo,
                                      const VkSubpassEndInfo* pSubpassEndInfo) {
-    AEMU_SCOPED_TRACE("vkCmdNextSubpass2KHR");
+    MESA_TRACE_SCOPE("vkCmdNextSubpass2KHR");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -3204,7 +3166,7 @@
 }
 void gfxstream_vk_CmdEndRenderPass2KHR(VkCommandBuffer commandBuffer,
                                        const VkSubpassEndInfo* pSubpassEndInfo) {
-    AEMU_SCOPED_TRACE("vkCmdEndRenderPass2KHR");
+    MESA_TRACE_SCOPE("vkCmdEndRenderPass2KHR");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -3218,7 +3180,7 @@
 void gfxstream_vk_GetPhysicalDeviceExternalFencePropertiesKHR(
     VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo,
     VkExternalFenceProperties* pExternalFenceProperties) {
-    AEMU_SCOPED_TRACE("vkGetPhysicalDeviceExternalFencePropertiesKHR");
+    MESA_TRACE_SCOPE("vkGetPhysicalDeviceExternalFencePropertiesKHR");
     VK_FROM_HANDLE(gfxstream_vk_physical_device, gfxstream_physicalDevice, physicalDevice);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -3229,12 +3191,10 @@
     }
 }
 #endif
-#ifdef VK_KHR_external_fence
-#endif
 #ifdef VK_KHR_external_fence_fd
 VkResult gfxstream_vk_ImportFenceFdKHR(VkDevice device,
                                        const VkImportFenceFdInfoKHR* pImportFenceFdInfo) {
-    AEMU_SCOPED_TRACE("vkImportFenceFdKHR");
+    MESA_TRACE_SCOPE("vkImportFenceFdKHR");
     VkResult vkImportFenceFdKHR_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -3256,7 +3216,7 @@
 }
 VkResult gfxstream_vk_GetFenceFdKHR(VkDevice device, const VkFenceGetFdInfoKHR* pGetFdInfo,
                                     int* pFd) {
-    AEMU_SCOPED_TRACE("vkGetFenceFdKHR");
+    MESA_TRACE_SCOPE("vkGetFenceFdKHR");
     VkResult vkGetFenceFdKHR_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -3275,17 +3235,11 @@
     return vkGetFenceFdKHR_VkResult_return;
 }
 #endif
-#ifdef VK_KHR_maintenance2
-#endif
-#ifdef VK_KHR_dedicated_allocation
-#endif
-#ifdef VK_KHR_storage_buffer_storage_class
-#endif
 #ifdef VK_KHR_get_memory_requirements2
 void gfxstream_vk_GetImageMemoryRequirements2KHR(VkDevice device,
                                                  const VkImageMemoryRequirementsInfo2* pInfo,
                                                  VkMemoryRequirements2* pMemoryRequirements) {
-    AEMU_SCOPED_TRACE("vkGetImageMemoryRequirements2KHR");
+    MESA_TRACE_SCOPE("vkGetImageMemoryRequirements2KHR");
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -3297,7 +3251,7 @@
 void gfxstream_vk_GetBufferMemoryRequirements2KHR(VkDevice device,
                                                   const VkBufferMemoryRequirementsInfo2* pInfo,
                                                   VkMemoryRequirements2* pMemoryRequirements) {
-    AEMU_SCOPED_TRACE("vkGetBufferMemoryRequirements2KHR");
+    MESA_TRACE_SCOPE("vkGetBufferMemoryRequirements2KHR");
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -3317,7 +3271,7 @@
     VkDevice device, const VkImageSparseMemoryRequirementsInfo2* pInfo,
     uint32_t* pSparseMemoryRequirementCount,
     VkSparseImageMemoryRequirements2* pSparseMemoryRequirements) {
-    AEMU_SCOPED_TRACE("vkGetImageSparseMemoryRequirements2KHR");
+    MESA_TRACE_SCOPE("vkGetImageSparseMemoryRequirements2KHR");
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -3327,13 +3281,11 @@
     }
 }
 #endif
-#ifdef VK_KHR_image_format_list
-#endif
 #ifdef VK_KHR_sampler_ycbcr_conversion
 VkResult gfxstream_vk_CreateSamplerYcbcrConversionKHR(
     VkDevice device, const VkSamplerYcbcrConversionCreateInfo* pCreateInfo,
     const VkAllocationCallbacks* pAllocator, VkSamplerYcbcrConversion* pYcbcrConversion) {
-    AEMU_SCOPED_TRACE("vkCreateSamplerYcbcrConversionKHR");
+    MESA_TRACE_SCOPE("vkCreateSamplerYcbcrConversionKHR");
     VkResult vkCreateSamplerYcbcrConversionKHR_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -3349,7 +3301,7 @@
 void gfxstream_vk_DestroySamplerYcbcrConversionKHR(VkDevice device,
                                                    VkSamplerYcbcrConversion ycbcrConversion,
                                                    const VkAllocationCallbacks* pAllocator) {
-    AEMU_SCOPED_TRACE("vkDestroySamplerYcbcrConversionKHR");
+    MESA_TRACE_SCOPE("vkDestroySamplerYcbcrConversionKHR");
     if (VK_NULL_HANDLE == ycbcrConversion) {
         return;
     }
@@ -3365,7 +3317,7 @@
 #ifdef VK_KHR_bind_memory2
 VkResult gfxstream_vk_BindBufferMemory2KHR(VkDevice device, uint32_t bindInfoCount,
                                            const VkBindBufferMemoryInfo* pBindInfos) {
-    AEMU_SCOPED_TRACE("vkBindBufferMemory2KHR");
+    MESA_TRACE_SCOPE("vkBindBufferMemory2KHR");
     VkResult vkBindBufferMemory2KHR_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -3386,7 +3338,7 @@
 }
 VkResult gfxstream_vk_BindImageMemory2KHR(VkDevice device, uint32_t bindInfoCount,
                                           const VkBindImageMemoryInfo* pBindInfos) {
-    AEMU_SCOPED_TRACE("vkBindImageMemory2KHR");
+    MESA_TRACE_SCOPE("vkBindImageMemory2KHR");
     VkResult vkBindImageMemory2KHR_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -3402,7 +3354,7 @@
 void gfxstream_vk_GetDescriptorSetLayoutSupportKHR(
     VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo,
     VkDescriptorSetLayoutSupport* pSupport) {
-    AEMU_SCOPED_TRACE("vkGetDescriptorSetLayoutSupportKHR");
+    MESA_TRACE_SCOPE("vkGetDescriptorSetLayoutSupportKHR");
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -3411,16 +3363,10 @@
     }
 }
 #endif
-#ifdef VK_KHR_shader_subgroup_extended_types
-#endif
-#ifdef VK_KHR_vulkan_memory_model
-#endif
-#ifdef VK_KHR_shader_terminate_invocation
-#endif
 #ifdef VK_KHR_buffer_device_address
 VkDeviceAddress gfxstream_vk_GetBufferDeviceAddressKHR(VkDevice device,
                                                        const VkBufferDeviceAddressInfo* pInfo) {
-    AEMU_SCOPED_TRACE("vkGetBufferDeviceAddressKHR");
+    MESA_TRACE_SCOPE("vkGetBufferDeviceAddressKHR");
     VkDeviceAddress vkGetBufferDeviceAddressKHR_VkDeviceAddress_return = (VkDeviceAddress)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -3439,7 +3385,7 @@
 }
 uint64_t gfxstream_vk_GetBufferOpaqueCaptureAddressKHR(VkDevice device,
                                                        const VkBufferDeviceAddressInfo* pInfo) {
-    AEMU_SCOPED_TRACE("vkGetBufferOpaqueCaptureAddressKHR");
+    MESA_TRACE_SCOPE("vkGetBufferOpaqueCaptureAddressKHR");
     uint64_t vkGetBufferOpaqueCaptureAddressKHR_uint64_t_return = (uint64_t)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -3459,7 +3405,7 @@
 }
 uint64_t gfxstream_vk_GetDeviceMemoryOpaqueCaptureAddressKHR(
     VkDevice device, const VkDeviceMemoryOpaqueCaptureAddressInfo* pInfo) {
-    AEMU_SCOPED_TRACE("vkGetDeviceMemoryOpaqueCaptureAddressKHR");
+    MESA_TRACE_SCOPE("vkGetDeviceMemoryOpaqueCaptureAddressKHR");
     uint64_t vkGetDeviceMemoryOpaqueCaptureAddressKHR_uint64_t_return = (uint64_t)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -3475,7 +3421,7 @@
 VkResult gfxstream_vk_GetPipelineExecutablePropertiesKHR(
     VkDevice device, const VkPipelineInfoKHR* pPipelineInfo, uint32_t* pExecutableCount,
     VkPipelineExecutablePropertiesKHR* pProperties) {
-    AEMU_SCOPED_TRACE("vkGetPipelineExecutablePropertiesKHR");
+    MESA_TRACE_SCOPE("vkGetPipelineExecutablePropertiesKHR");
     VkResult vkGetPipelineExecutablePropertiesKHR_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -3490,7 +3436,7 @@
 VkResult gfxstream_vk_GetPipelineExecutableStatisticsKHR(
     VkDevice device, const VkPipelineExecutableInfoKHR* pExecutableInfo, uint32_t* pStatisticCount,
     VkPipelineExecutableStatisticKHR* pStatistics) {
-    AEMU_SCOPED_TRACE("vkGetPipelineExecutableStatisticsKHR");
+    MESA_TRACE_SCOPE("vkGetPipelineExecutableStatisticsKHR");
     VkResult vkGetPipelineExecutableStatisticsKHR_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -3506,7 +3452,7 @@
     VkDevice device, const VkPipelineExecutableInfoKHR* pExecutableInfo,
     uint32_t* pInternalRepresentationCount,
     VkPipelineExecutableInternalRepresentationKHR* pInternalRepresentations) {
-    AEMU_SCOPED_TRACE("vkGetPipelineExecutableInternalRepresentationsKHR");
+    MESA_TRACE_SCOPE("vkGetPipelineExecutableInternalRepresentationsKHR");
     VkResult vkGetPipelineExecutableInternalRepresentationsKHR_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -3519,14 +3465,10 @@
     return vkGetPipelineExecutableInternalRepresentationsKHR_VkResult_return;
 }
 #endif
-#ifdef VK_KHR_shader_integer_dot_product
-#endif
-#ifdef VK_KHR_shader_non_semantic_info
-#endif
 #ifdef VK_KHR_synchronization2
 void gfxstream_vk_CmdSetEvent2KHR(VkCommandBuffer commandBuffer, VkEvent event,
                                   const VkDependencyInfo* pDependencyInfo) {
-    AEMU_SCOPED_TRACE("vkCmdSetEvent2KHR");
+    MESA_TRACE_SCOPE("vkCmdSetEvent2KHR");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -3539,11 +3481,8 @@
             /* VkDependencyInfo::pBufferMemoryBarriers */
             internal_VkDependencyInfo_pBufferMemoryBarriers.push_back(
                 std::vector<VkBufferMemoryBarrier2>());
-            internal_VkDependencyInfo_pBufferMemoryBarriers[i].reserve(
+            internal_VkDependencyInfo_pBufferMemoryBarriers[i].resize(
                 internal_pDependencyInfo[i].bufferMemoryBarrierCount);
-            memset(&internal_VkDependencyInfo_pBufferMemoryBarriers[i][0], 0,
-                   sizeof(VkBufferMemoryBarrier2) *
-                       internal_pDependencyInfo[i].bufferMemoryBarrierCount);
             for (uint32_t j = 0; j < internal_pDependencyInfo[i].bufferMemoryBarrierCount; ++j) {
                 internal_VkDependencyInfo_pBufferMemoryBarriers[i][j] =
                     internal_pDependencyInfo[i].pBufferMemoryBarriers[j];
@@ -3562,7 +3501,7 @@
 }
 void gfxstream_vk_CmdResetEvent2KHR(VkCommandBuffer commandBuffer, VkEvent event,
                                     VkPipelineStageFlags2 stageMask) {
-    AEMU_SCOPED_TRACE("vkCmdResetEvent2KHR");
+    MESA_TRACE_SCOPE("vkCmdResetEvent2KHR");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -3574,7 +3513,7 @@
 void gfxstream_vk_CmdWaitEvents2KHR(VkCommandBuffer commandBuffer, uint32_t eventCount,
                                     const VkEvent* pEvents,
                                     const VkDependencyInfo* pDependencyInfos) {
-    AEMU_SCOPED_TRACE("vkCmdWaitEvents2KHR");
+    MESA_TRACE_SCOPE("vkCmdWaitEvents2KHR");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -3587,11 +3526,8 @@
             /* VkDependencyInfo::pBufferMemoryBarriers */
             internal_VkDependencyInfo_pBufferMemoryBarriers.push_back(
                 std::vector<VkBufferMemoryBarrier2>());
-            internal_VkDependencyInfo_pBufferMemoryBarriers[i].reserve(
+            internal_VkDependencyInfo_pBufferMemoryBarriers[i].resize(
                 internal_pDependencyInfos[i].bufferMemoryBarrierCount);
-            memset(&internal_VkDependencyInfo_pBufferMemoryBarriers[i][0], 0,
-                   sizeof(VkBufferMemoryBarrier2) *
-                       internal_pDependencyInfos[i].bufferMemoryBarrierCount);
             for (uint32_t j = 0; j < internal_pDependencyInfos[i].bufferMemoryBarrierCount; ++j) {
                 internal_VkDependencyInfo_pBufferMemoryBarriers[i][j] =
                     internal_pDependencyInfos[i].pBufferMemoryBarriers[j];
@@ -3610,7 +3546,7 @@
 }
 void gfxstream_vk_CmdPipelineBarrier2KHR(VkCommandBuffer commandBuffer,
                                          const VkDependencyInfo* pDependencyInfo) {
-    AEMU_SCOPED_TRACE("vkCmdPipelineBarrier2KHR");
+    MESA_TRACE_SCOPE("vkCmdPipelineBarrier2KHR");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -3623,11 +3559,8 @@
             /* VkDependencyInfo::pBufferMemoryBarriers */
             internal_VkDependencyInfo_pBufferMemoryBarriers.push_back(
                 std::vector<VkBufferMemoryBarrier2>());
-            internal_VkDependencyInfo_pBufferMemoryBarriers[i].reserve(
+            internal_VkDependencyInfo_pBufferMemoryBarriers[i].resize(
                 internal_pDependencyInfo[i].bufferMemoryBarrierCount);
-            memset(&internal_VkDependencyInfo_pBufferMemoryBarriers[i][0], 0,
-                   sizeof(VkBufferMemoryBarrier2) *
-                       internal_pDependencyInfo[i].bufferMemoryBarrierCount);
             for (uint32_t j = 0; j < internal_pDependencyInfo[i].bufferMemoryBarrierCount; ++j) {
                 internal_VkDependencyInfo_pBufferMemoryBarriers[i][j] =
                     internal_pDependencyInfo[i].pBufferMemoryBarriers[j];
@@ -3646,7 +3579,7 @@
 }
 void gfxstream_vk_CmdWriteTimestamp2KHR(VkCommandBuffer commandBuffer, VkPipelineStageFlags2 stage,
                                         VkQueryPool queryPool, uint32_t query) {
-    AEMU_SCOPED_TRACE("vkCmdWriteTimestamp2KHR");
+    MESA_TRACE_SCOPE("vkCmdWriteTimestamp2KHR");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -3657,7 +3590,7 @@
 }
 VkResult gfxstream_vk_QueueSubmit2KHR(VkQueue queue, uint32_t submitCount,
                                       const VkSubmitInfo2* pSubmits, VkFence fence) {
-    AEMU_SCOPED_TRACE("vkQueueSubmit2KHR");
+    MESA_TRACE_SCOPE("vkQueueSubmit2KHR");
     VkResult vkQueueSubmit2KHR_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_queue, gfxstream_queue, queue);
     VK_FROM_HANDLE(gfxstream_vk_fence, gfxstream_fence, fence);
@@ -3685,10 +3618,8 @@
             /* VkSubmitInfo2::pCommandBufferInfos */
             internal_VkSubmitInfo2_pCommandBufferInfos.push_back(
                 std::vector<VkCommandBufferSubmitInfo>());
-            internal_VkSubmitInfo2_pCommandBufferInfos[i].reserve(
+            internal_VkSubmitInfo2_pCommandBufferInfos[i].resize(
                 internal_pSubmits[i].commandBufferInfoCount);
-            memset(&internal_VkSubmitInfo2_pCommandBufferInfos[i][0], 0,
-                   sizeof(VkCommandBufferSubmitInfo) * internal_pSubmits[i].commandBufferInfoCount);
             for (uint32_t j = 0; j < internal_pSubmits[i].commandBufferInfoCount; ++j) {
                 internal_VkSubmitInfo2_pCommandBufferInfos[i][j] =
                     internal_pSubmits[i].pCommandBufferInfos[j];
@@ -3721,7 +3652,7 @@
 void gfxstream_vk_CmdWriteBufferMarker2AMD(VkCommandBuffer commandBuffer,
                                            VkPipelineStageFlags2 stage, VkBuffer dstBuffer,
                                            VkDeviceSize dstOffset, uint32_t marker) {
-    AEMU_SCOPED_TRACE("vkCmdWriteBufferMarker2AMD");
+    MESA_TRACE_SCOPE("vkCmdWriteBufferMarker2AMD");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     VK_FROM_HANDLE(gfxstream_vk_buffer, gfxstream_dstBuffer, dstBuffer);
     {
@@ -3734,7 +3665,7 @@
 }
 void gfxstream_vk_GetQueueCheckpointData2NV(VkQueue queue, uint32_t* pCheckpointDataCount,
                                             VkCheckpointData2NV* pCheckpointData) {
-    AEMU_SCOPED_TRACE("vkGetQueueCheckpointData2NV");
+    MESA_TRACE_SCOPE("vkGetQueueCheckpointData2NV");
     VK_FROM_HANDLE(gfxstream_vk_queue, gfxstream_queue, queue);
     {
         auto vkEnc =
@@ -3744,12 +3675,10 @@
     }
 }
 #endif
-#ifdef VK_KHR_zero_initialize_workgroup_memory
-#endif
 #ifdef VK_KHR_copy_commands2
 void gfxstream_vk_CmdCopyBuffer2KHR(VkCommandBuffer commandBuffer,
                                     const VkCopyBufferInfo2* pCopyBufferInfo) {
-    AEMU_SCOPED_TRACE("vkCmdCopyBuffer2KHR");
+    MESA_TRACE_SCOPE("vkCmdCopyBuffer2KHR");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -3772,7 +3701,7 @@
 }
 void gfxstream_vk_CmdCopyImage2KHR(VkCommandBuffer commandBuffer,
                                    const VkCopyImageInfo2* pCopyImageInfo) {
-    AEMU_SCOPED_TRACE("vkCmdCopyImage2KHR");
+    MESA_TRACE_SCOPE("vkCmdCopyImage2KHR");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -3783,7 +3712,7 @@
 }
 void gfxstream_vk_CmdCopyBufferToImage2KHR(VkCommandBuffer commandBuffer,
                                            const VkCopyBufferToImageInfo2* pCopyBufferToImageInfo) {
-    AEMU_SCOPED_TRACE("vkCmdCopyBufferToImage2KHR");
+    MESA_TRACE_SCOPE("vkCmdCopyBufferToImage2KHR");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -3803,7 +3732,7 @@
 }
 void gfxstream_vk_CmdCopyImageToBuffer2KHR(VkCommandBuffer commandBuffer,
                                            const VkCopyImageToBufferInfo2* pCopyImageToBufferInfo) {
-    AEMU_SCOPED_TRACE("vkCmdCopyImageToBuffer2KHR");
+    MESA_TRACE_SCOPE("vkCmdCopyImageToBuffer2KHR");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -3823,7 +3752,7 @@
 }
 void gfxstream_vk_CmdBlitImage2KHR(VkCommandBuffer commandBuffer,
                                    const VkBlitImageInfo2* pBlitImageInfo) {
-    AEMU_SCOPED_TRACE("vkCmdBlitImage2KHR");
+    MESA_TRACE_SCOPE("vkCmdBlitImage2KHR");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -3834,7 +3763,7 @@
 }
 void gfxstream_vk_CmdResolveImage2KHR(VkCommandBuffer commandBuffer,
                                       const VkResolveImageInfo2* pResolveImageInfo) {
-    AEMU_SCOPED_TRACE("vkCmdResolveImage2KHR");
+    MESA_TRACE_SCOPE("vkCmdResolveImage2KHR");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -3844,13 +3773,11 @@
     }
 }
 #endif
-#ifdef VK_KHR_format_feature_flags2
-#endif
 #ifdef VK_KHR_maintenance4
 void gfxstream_vk_GetDeviceBufferMemoryRequirementsKHR(
     VkDevice device, const VkDeviceBufferMemoryRequirements* pInfo,
     VkMemoryRequirements2* pMemoryRequirements) {
-    AEMU_SCOPED_TRACE("vkGetDeviceBufferMemoryRequirementsKHR");
+    MESA_TRACE_SCOPE("vkGetDeviceBufferMemoryRequirementsKHR");
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -3861,7 +3788,7 @@
 void gfxstream_vk_GetDeviceImageMemoryRequirementsKHR(VkDevice device,
                                                       const VkDeviceImageMemoryRequirements* pInfo,
                                                       VkMemoryRequirements2* pMemoryRequirements) {
-    AEMU_SCOPED_TRACE("vkGetDeviceImageMemoryRequirementsKHR");
+    MESA_TRACE_SCOPE("vkGetDeviceImageMemoryRequirementsKHR");
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -3873,7 +3800,7 @@
     VkDevice device, const VkDeviceImageMemoryRequirements* pInfo,
     uint32_t* pSparseMemoryRequirementCount,
     VkSparseImageMemoryRequirements2* pSparseMemoryRequirements) {
-    AEMU_SCOPED_TRACE("vkGetDeviceImageSparseMemoryRequirementsKHR");
+    MESA_TRACE_SCOPE("vkGetDeviceImageSparseMemoryRequirementsKHR");
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -3887,7 +3814,7 @@
 void gfxstream_vk_CmdBindIndexBuffer2KHR(VkCommandBuffer commandBuffer, VkBuffer buffer,
                                          VkDeviceSize offset, VkDeviceSize size,
                                          VkIndexType indexType) {
-    AEMU_SCOPED_TRACE("vkCmdBindIndexBuffer2KHR");
+    MESA_TRACE_SCOPE("vkCmdBindIndexBuffer2KHR");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     VK_FROM_HANDLE(gfxstream_vk_buffer, gfxstream_buffer, buffer);
     {
@@ -3901,7 +3828,7 @@
 void gfxstream_vk_GetRenderingAreaGranularityKHR(VkDevice device,
                                                  const VkRenderingAreaInfoKHR* pRenderingAreaInfo,
                                                  VkExtent2D* pGranularity) {
-    AEMU_SCOPED_TRACE("vkGetRenderingAreaGranularityKHR");
+    MESA_TRACE_SCOPE("vkGetRenderingAreaGranularityKHR");
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -3913,7 +3840,7 @@
 void gfxstream_vk_GetDeviceImageSubresourceLayoutKHR(VkDevice device,
                                                      const VkDeviceImageSubresourceInfoKHR* pInfo,
                                                      VkSubresourceLayout2KHR* pLayout) {
-    AEMU_SCOPED_TRACE("vkGetDeviceImageSubresourceLayoutKHR");
+    MESA_TRACE_SCOPE("vkGetDeviceImageSubresourceLayoutKHR");
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -3924,7 +3851,7 @@
 void gfxstream_vk_GetImageSubresourceLayout2KHR(VkDevice device, VkImage image,
                                                 const VkImageSubresource2KHR* pSubresource,
                                                 VkSubresourceLayout2KHR* pLayout) {
-    AEMU_SCOPED_TRACE("vkGetImageSubresourceLayout2KHR");
+    MESA_TRACE_SCOPE("vkGetImageSubresourceLayout2KHR");
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -3937,7 +3864,7 @@
 VkResult gfxstream_vk_GetSwapchainGrallocUsageANDROID(VkDevice device, VkFormat format,
                                                       VkImageUsageFlags imageUsage,
                                                       int* grallocUsage) {
-    AEMU_SCOPED_TRACE("vkGetSwapchainGrallocUsageANDROID");
+    MESA_TRACE_SCOPE("vkGetSwapchainGrallocUsageANDROID");
     VkResult vkGetSwapchainGrallocUsageANDROID_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -3950,7 +3877,7 @@
 }
 VkResult gfxstream_vk_AcquireImageANDROID(VkDevice device, VkImage image, int nativeFenceFd,
                                           VkSemaphore semaphore, VkFence fence) {
-    AEMU_SCOPED_TRACE("vkAcquireImageANDROID");
+    MESA_TRACE_SCOPE("vkAcquireImageANDROID");
     VkResult vkAcquireImageANDROID_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     VK_FROM_HANDLE(gfxstream_vk_semaphore, gfxstream_semaphore, semaphore);
@@ -3968,7 +3895,7 @@
 VkResult gfxstream_vk_QueueSignalReleaseImageANDROID(VkQueue queue, uint32_t waitSemaphoreCount,
                                                      const VkSemaphore* pWaitSemaphores,
                                                      VkImage image, int* pNativeFenceFd) {
-    AEMU_SCOPED_TRACE("vkQueueSignalReleaseImageANDROID");
+    MESA_TRACE_SCOPE("vkQueueSignalReleaseImageANDROID");
     VkResult vkQueueSignalReleaseImageANDROID_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_queue, gfxstream_queue, queue);
     {
@@ -3990,7 +3917,7 @@
     VkDevice device, VkFormat format, VkImageUsageFlags imageUsage,
     VkSwapchainImageUsageFlagsANDROID swapchainImageUsage, uint64_t* grallocConsumerUsage,
     uint64_t* grallocProducerUsage) {
-    AEMU_SCOPED_TRACE("vkGetSwapchainGrallocUsage2ANDROID");
+    MESA_TRACE_SCOPE("vkGetSwapchainGrallocUsage2ANDROID");
     VkResult vkGetSwapchainGrallocUsage2ANDROID_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -4003,15 +3930,13 @@
     return vkGetSwapchainGrallocUsage2ANDROID_VkResult_return;
 }
 #endif
-#ifdef VK_EXT_debug_report
-#endif
 #ifdef VK_EXT_transform_feedback
 void gfxstream_vk_CmdBindTransformFeedbackBuffersEXT(VkCommandBuffer commandBuffer,
                                                      uint32_t firstBinding, uint32_t bindingCount,
                                                      const VkBuffer* pBuffers,
                                                      const VkDeviceSize* pOffsets,
                                                      const VkDeviceSize* pSizes) {
-    AEMU_SCOPED_TRACE("vkCmdBindTransformFeedbackBuffersEXT");
+    MESA_TRACE_SCOPE("vkCmdBindTransformFeedbackBuffersEXT");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -4026,34 +3951,12 @@
             internal_pBuffers.data(), pOffsets, pSizes, true /* do lock */);
     }
 }
-void gfxstream_vk_CmdBeginTransformFeedbackEXT(VkCommandBuffer commandBuffer,
-                                               uint32_t firstCounterBuffer,
-                                               uint32_t counterBufferCount,
-                                               const VkBuffer* pCounterBuffers,
-                                               const VkDeviceSize* pCounterBufferOffsets) {
-    AEMU_SCOPED_TRACE("vkCmdBeginTransformFeedbackEXT");
-    VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
-    {
-        auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
-            gfxstream_commandBuffer->internal_object);
-        std::vector<VkBuffer> internal_pCounterBuffers(counterBufferCount);
-        for (uint32_t i = 0; i < counterBufferCount; ++i) {
-            if (pCounterBuffers) {
-                VK_FROM_HANDLE(gfxstream_vk_buffer, gfxstream_pCounterBuffers, pCounterBuffers[i]);
-                internal_pCounterBuffers[i] = gfxstream_pCounterBuffers->internal_object;
-            }
-        }
-        vkEnc->vkCmdBeginTransformFeedbackEXT(
-            gfxstream_commandBuffer->internal_object, firstCounterBuffer, counterBufferCount,
-            internal_pCounterBuffers.data(), pCounterBufferOffsets, true /* do lock */);
-    }
-}
 void gfxstream_vk_CmdEndTransformFeedbackEXT(VkCommandBuffer commandBuffer,
                                              uint32_t firstCounterBuffer,
                                              uint32_t counterBufferCount,
                                              const VkBuffer* pCounterBuffers,
                                              const VkDeviceSize* pCounterBufferOffsets) {
-    AEMU_SCOPED_TRACE("vkCmdEndTransformFeedbackEXT");
+    MESA_TRACE_SCOPE("vkCmdEndTransformFeedbackEXT");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -4073,7 +3976,7 @@
 void gfxstream_vk_CmdBeginQueryIndexedEXT(VkCommandBuffer commandBuffer, VkQueryPool queryPool,
                                           uint32_t query, VkQueryControlFlags flags,
                                           uint32_t index) {
-    AEMU_SCOPED_TRACE("vkCmdBeginQueryIndexedEXT");
+    MESA_TRACE_SCOPE("vkCmdBeginQueryIndexedEXT");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -4084,7 +3987,7 @@
 }
 void gfxstream_vk_CmdEndQueryIndexedEXT(VkCommandBuffer commandBuffer, VkQueryPool queryPool,
                                         uint32_t query, uint32_t index) {
-    AEMU_SCOPED_TRACE("vkCmdEndQueryIndexedEXT");
+    MESA_TRACE_SCOPE("vkCmdEndQueryIndexedEXT");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -4097,7 +4000,7 @@
                                               uint32_t firstInstance, VkBuffer counterBuffer,
                                               VkDeviceSize counterBufferOffset,
                                               uint32_t counterOffset, uint32_t vertexStride) {
-    AEMU_SCOPED_TRACE("vkCmdDrawIndirectByteCountEXT");
+    MESA_TRACE_SCOPE("vkCmdDrawIndirectByteCountEXT");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     VK_FROM_HANDLE(gfxstream_vk_buffer, gfxstream_counterBuffer, counterBuffer);
     {
@@ -4110,23 +4013,11 @@
     }
 }
 #endif
-#ifdef VK_AMD_gpu_shader_half_float
-#endif
-#ifdef VK_EXT_texture_compression_astc_hdr
-#endif
-#ifdef VK_EXT_depth_clip_enable
-#endif
-#ifdef VK_EXT_swapchain_colorspace
-#endif
-#ifdef VK_EXT_queue_family_foreign
-#endif
-#ifdef VK_EXT_debug_utils
-#endif
 #ifdef VK_ANDROID_external_memory_android_hardware_buffer
 VkResult gfxstream_vk_GetAndroidHardwareBufferPropertiesANDROID(
     VkDevice device, const AHardwareBuffer* buffer,
     VkAndroidHardwareBufferPropertiesANDROID* pProperties) {
-    AEMU_SCOPED_TRACE("vkGetAndroidHardwareBufferPropertiesANDROID");
+    MESA_TRACE_SCOPE("vkGetAndroidHardwareBufferPropertiesANDROID");
     VkResult vkGetAndroidHardwareBufferPropertiesANDROID_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -4141,7 +4032,7 @@
 VkResult gfxstream_vk_GetMemoryAndroidHardwareBufferANDROID(
     VkDevice device, const VkMemoryGetAndroidHardwareBufferInfoANDROID* pInfo,
     AHardwareBuffer** pBuffer) {
-    AEMU_SCOPED_TRACE("vkGetMemoryAndroidHardwareBufferANDROID");
+    MESA_TRACE_SCOPE("vkGetMemoryAndroidHardwareBufferANDROID");
     VkResult vkGetMemoryAndroidHardwareBufferANDROID_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -4154,29 +4045,11 @@
     return vkGetMemoryAndroidHardwareBufferANDROID_VkResult_return;
 }
 #endif
-#ifdef VK_EXT_inline_uniform_block
-#endif
-#ifdef VK_EXT_shader_stencil_export
-#endif
-#ifdef VK_EXT_vertex_attribute_divisor
-#endif
-#ifdef VK_EXT_pipeline_creation_feedback
-#endif
-#ifdef VK_NV_shader_subgroup_partitioned
-#endif
-#ifdef VK_EXT_metal_surface
-#endif
-#ifdef VK_EXT_fragment_density_map
-#endif
-#ifdef VK_EXT_scalar_block_layout
-#endif
-#ifdef VK_EXT_subgroup_size_control
-#endif
 #ifdef VK_EXT_tooling_info
 VkResult gfxstream_vk_GetPhysicalDeviceToolPropertiesEXT(
     VkPhysicalDevice physicalDevice, uint32_t* pToolCount,
     VkPhysicalDeviceToolProperties* pToolProperties) {
-    AEMU_SCOPED_TRACE("vkGetPhysicalDeviceToolPropertiesEXT");
+    MESA_TRACE_SCOPE("vkGetPhysicalDeviceToolPropertiesEXT");
     VkResult vkGetPhysicalDeviceToolPropertiesEXT_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_physical_device, gfxstream_physicalDevice, physicalDevice);
     {
@@ -4189,14 +4062,10 @@
     return vkGetPhysicalDeviceToolPropertiesEXT_VkResult_return;
 }
 #endif
-#ifdef VK_EXT_validation_features
-#endif
-#ifdef VK_EXT_provoking_vertex
-#endif
 #ifdef VK_EXT_line_rasterization
 void gfxstream_vk_CmdSetLineStippleEXT(VkCommandBuffer commandBuffer, uint32_t lineStippleFactor,
                                        uint16_t lineStipplePattern) {
-    AEMU_SCOPED_TRACE("vkCmdSetLineStippleEXT");
+    MESA_TRACE_SCOPE("vkCmdSetLineStippleEXT");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -4206,11 +4075,9 @@
     }
 }
 #endif
-#ifdef VK_EXT_index_type_uint8
-#endif
 #ifdef VK_EXT_extended_dynamic_state
 void gfxstream_vk_CmdSetCullModeEXT(VkCommandBuffer commandBuffer, VkCullModeFlags cullMode) {
-    AEMU_SCOPED_TRACE("vkCmdSetCullModeEXT");
+    MESA_TRACE_SCOPE("vkCmdSetCullModeEXT");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -4220,7 +4087,7 @@
     }
 }
 void gfxstream_vk_CmdSetFrontFaceEXT(VkCommandBuffer commandBuffer, VkFrontFace frontFace) {
-    AEMU_SCOPED_TRACE("vkCmdSetFrontFaceEXT");
+    MESA_TRACE_SCOPE("vkCmdSetFrontFaceEXT");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -4231,7 +4098,7 @@
 }
 void gfxstream_vk_CmdSetPrimitiveTopologyEXT(VkCommandBuffer commandBuffer,
                                              VkPrimitiveTopology primitiveTopology) {
-    AEMU_SCOPED_TRACE("vkCmdSetPrimitiveTopologyEXT");
+    MESA_TRACE_SCOPE("vkCmdSetPrimitiveTopologyEXT");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -4242,7 +4109,7 @@
 }
 void gfxstream_vk_CmdSetViewportWithCountEXT(VkCommandBuffer commandBuffer, uint32_t viewportCount,
                                              const VkViewport* pViewports) {
-    AEMU_SCOPED_TRACE("vkCmdSetViewportWithCountEXT");
+    MESA_TRACE_SCOPE("vkCmdSetViewportWithCountEXT");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -4253,7 +4120,7 @@
 }
 void gfxstream_vk_CmdSetScissorWithCountEXT(VkCommandBuffer commandBuffer, uint32_t scissorCount,
                                             const VkRect2D* pScissors) {
-    AEMU_SCOPED_TRACE("vkCmdSetScissorWithCountEXT");
+    MESA_TRACE_SCOPE("vkCmdSetScissorWithCountEXT");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -4266,7 +4133,7 @@
                                            uint32_t bindingCount, const VkBuffer* pBuffers,
                                            const VkDeviceSize* pOffsets, const VkDeviceSize* pSizes,
                                            const VkDeviceSize* pStrides) {
-    AEMU_SCOPED_TRACE("vkCmdBindVertexBuffers2EXT");
+    MESA_TRACE_SCOPE("vkCmdBindVertexBuffers2EXT");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -4285,7 +4152,7 @@
 }
 void gfxstream_vk_CmdSetDepthTestEnableEXT(VkCommandBuffer commandBuffer,
                                            VkBool32 depthTestEnable) {
-    AEMU_SCOPED_TRACE("vkCmdSetDepthTestEnableEXT");
+    MESA_TRACE_SCOPE("vkCmdSetDepthTestEnableEXT");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -4296,7 +4163,7 @@
 }
 void gfxstream_vk_CmdSetDepthWriteEnableEXT(VkCommandBuffer commandBuffer,
                                             VkBool32 depthWriteEnable) {
-    AEMU_SCOPED_TRACE("vkCmdSetDepthWriteEnableEXT");
+    MESA_TRACE_SCOPE("vkCmdSetDepthWriteEnableEXT");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -4307,7 +4174,7 @@
 }
 void gfxstream_vk_CmdSetDepthCompareOpEXT(VkCommandBuffer commandBuffer,
                                           VkCompareOp depthCompareOp) {
-    AEMU_SCOPED_TRACE("vkCmdSetDepthCompareOpEXT");
+    MESA_TRACE_SCOPE("vkCmdSetDepthCompareOpEXT");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -4318,7 +4185,7 @@
 }
 void gfxstream_vk_CmdSetDepthBoundsTestEnableEXT(VkCommandBuffer commandBuffer,
                                                  VkBool32 depthBoundsTestEnable) {
-    AEMU_SCOPED_TRACE("vkCmdSetDepthBoundsTestEnableEXT");
+    MESA_TRACE_SCOPE("vkCmdSetDepthBoundsTestEnableEXT");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -4329,7 +4196,7 @@
 }
 void gfxstream_vk_CmdSetStencilTestEnableEXT(VkCommandBuffer commandBuffer,
                                              VkBool32 stencilTestEnable) {
-    AEMU_SCOPED_TRACE("vkCmdSetStencilTestEnableEXT");
+    MESA_TRACE_SCOPE("vkCmdSetStencilTestEnableEXT");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -4341,7 +4208,7 @@
 void gfxstream_vk_CmdSetStencilOpEXT(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask,
                                      VkStencilOp failOp, VkStencilOp passOp,
                                      VkStencilOp depthFailOp, VkCompareOp compareOp) {
-    AEMU_SCOPED_TRACE("vkCmdSetStencilOpEXT");
+    MESA_TRACE_SCOPE("vkCmdSetStencilOpEXT");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -4354,7 +4221,7 @@
 #ifdef VK_EXT_host_image_copy
 VkResult gfxstream_vk_CopyMemoryToImageEXT(
     VkDevice device, const VkCopyMemoryToImageInfoEXT* pCopyMemoryToImageInfo) {
-    AEMU_SCOPED_TRACE("vkCopyMemoryToImageEXT");
+    MESA_TRACE_SCOPE("vkCopyMemoryToImageEXT");
     VkResult vkCopyMemoryToImageEXT_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -4366,7 +4233,7 @@
 }
 VkResult gfxstream_vk_CopyImageToMemoryEXT(
     VkDevice device, const VkCopyImageToMemoryInfoEXT* pCopyImageToMemoryInfo) {
-    AEMU_SCOPED_TRACE("vkCopyImageToMemoryEXT");
+    MESA_TRACE_SCOPE("vkCopyImageToMemoryEXT");
     VkResult vkCopyImageToMemoryEXT_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -4378,7 +4245,7 @@
 }
 VkResult gfxstream_vk_CopyImageToImageEXT(VkDevice device,
                                           const VkCopyImageToImageInfoEXT* pCopyImageToImageInfo) {
-    AEMU_SCOPED_TRACE("vkCopyImageToImageEXT");
+    MESA_TRACE_SCOPE("vkCopyImageToImageEXT");
     VkResult vkCopyImageToImageEXT_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -4391,7 +4258,7 @@
 VkResult gfxstream_vk_TransitionImageLayoutEXT(
     VkDevice device, uint32_t transitionCount,
     const VkHostImageLayoutTransitionInfoEXT* pTransitions) {
-    AEMU_SCOPED_TRACE("vkTransitionImageLayoutEXT");
+    MESA_TRACE_SCOPE("vkTransitionImageLayoutEXT");
     VkResult vkTransitionImageLayoutEXT_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -4404,7 +4271,7 @@
 void gfxstream_vk_GetImageSubresourceLayout2EXT(VkDevice device, VkImage image,
                                                 const VkImageSubresource2KHR* pSubresource,
                                                 VkSubresourceLayout2KHR* pLayout) {
-    AEMU_SCOPED_TRACE("vkGetImageSubresourceLayout2EXT");
+    MESA_TRACE_SCOPE("vkGetImageSubresourceLayout2EXT");
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -4413,24 +4280,12 @@
     }
 }
 #endif
-#ifdef VK_EXT_swapchain_maintenance1
-#endif
-#ifdef VK_EXT_shader_demote_to_helper_invocation
-#endif
-#ifdef VK_EXT_texel_buffer_alignment
-#endif
-#ifdef VK_EXT_device_memory_report
-#endif
-#ifdef VK_EXT_robustness2
-#endif
-#ifdef VK_EXT_custom_border_color
-#endif
 #ifdef VK_EXT_private_data
 VkResult gfxstream_vk_CreatePrivateDataSlotEXT(VkDevice device,
                                                const VkPrivateDataSlotCreateInfo* pCreateInfo,
                                                const VkAllocationCallbacks* pAllocator,
                                                VkPrivateDataSlot* pPrivateDataSlot) {
-    AEMU_SCOPED_TRACE("vkCreatePrivateDataSlotEXT");
+    MESA_TRACE_SCOPE("vkCreatePrivateDataSlotEXT");
     VkResult vkCreatePrivateDataSlotEXT_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -4443,7 +4298,7 @@
 }
 void gfxstream_vk_DestroyPrivateDataSlotEXT(VkDevice device, VkPrivateDataSlot privateDataSlot,
                                             const VkAllocationCallbacks* pAllocator) {
-    AEMU_SCOPED_TRACE("vkDestroyPrivateDataSlotEXT");
+    MESA_TRACE_SCOPE("vkDestroyPrivateDataSlotEXT");
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -4454,7 +4309,7 @@
 VkResult gfxstream_vk_SetPrivateDataEXT(VkDevice device, VkObjectType objectType,
                                         uint64_t objectHandle, VkPrivateDataSlot privateDataSlot,
                                         uint64_t data) {
-    AEMU_SCOPED_TRACE("vkSetPrivateDataEXT");
+    MESA_TRACE_SCOPE("vkSetPrivateDataEXT");
     VkResult vkSetPrivateDataEXT_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -4467,7 +4322,7 @@
 }
 void gfxstream_vk_GetPrivateDataEXT(VkDevice device, VkObjectType objectType, uint64_t objectHandle,
                                     VkPrivateDataSlot privateDataSlot, uint64_t* pData) {
-    AEMU_SCOPED_TRACE("vkGetPrivateDataEXT");
+    MESA_TRACE_SCOPE("vkGetPrivateDataEXT");
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -4476,26 +4331,10 @@
     }
 }
 #endif
-#ifdef VK_EXT_pipeline_creation_cache_control
-#endif
-#ifdef VK_EXT_metal_objects
-#endif
-#ifdef VK_EXT_graphics_pipeline_library
-#endif
-#ifdef VK_EXT_ycbcr_2plane_444_formats
-#endif
-#ifdef VK_EXT_image_robustness
-#endif
-#ifdef VK_EXT_image_compression_control
-#endif
-#ifdef VK_EXT_4444_formats
-#endif
-#ifdef VK_EXT_primitive_topology_list_restart
-#endif
 #ifdef VK_EXT_extended_dynamic_state2
 void gfxstream_vk_CmdSetPatchControlPointsEXT(VkCommandBuffer commandBuffer,
                                               uint32_t patchControlPoints) {
-    AEMU_SCOPED_TRACE("vkCmdSetPatchControlPointsEXT");
+    MESA_TRACE_SCOPE("vkCmdSetPatchControlPointsEXT");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -4506,7 +4345,7 @@
 }
 void gfxstream_vk_CmdSetRasterizerDiscardEnableEXT(VkCommandBuffer commandBuffer,
                                                    VkBool32 rasterizerDiscardEnable) {
-    AEMU_SCOPED_TRACE("vkCmdSetRasterizerDiscardEnableEXT");
+    MESA_TRACE_SCOPE("vkCmdSetRasterizerDiscardEnableEXT");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -4517,7 +4356,7 @@
 }
 void gfxstream_vk_CmdSetDepthBiasEnableEXT(VkCommandBuffer commandBuffer,
                                            VkBool32 depthBiasEnable) {
-    AEMU_SCOPED_TRACE("vkCmdSetDepthBiasEnableEXT");
+    MESA_TRACE_SCOPE("vkCmdSetDepthBiasEnableEXT");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -4527,7 +4366,7 @@
     }
 }
 void gfxstream_vk_CmdSetLogicOpEXT(VkCommandBuffer commandBuffer, VkLogicOp logicOp) {
-    AEMU_SCOPED_TRACE("vkCmdSetLogicOpEXT");
+    MESA_TRACE_SCOPE("vkCmdSetLogicOpEXT");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -4538,7 +4377,7 @@
 }
 void gfxstream_vk_CmdSetPrimitiveRestartEnableEXT(VkCommandBuffer commandBuffer,
                                                   VkBool32 primitiveRestartEnable) {
-    AEMU_SCOPED_TRACE("vkCmdSetPrimitiveRestartEnableEXT");
+    MESA_TRACE_SCOPE("vkCmdSetPrimitiveRestartEnableEXT");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -4551,7 +4390,7 @@
 #ifdef VK_EXT_color_write_enable
 void gfxstream_vk_CmdSetColorWriteEnableEXT(VkCommandBuffer commandBuffer, uint32_t attachmentCount,
                                             const VkBool32* pColorWriteEnables) {
-    AEMU_SCOPED_TRACE("vkCmdSetColorWriteEnableEXT");
+    MESA_TRACE_SCOPE("vkCmdSetColorWriteEnableEXT");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -4564,7 +4403,7 @@
 #ifdef VK_GOOGLE_gfxstream
 VkResult gfxstream_vk_MapMemoryIntoAddressSpaceGOOGLE(VkDevice device, VkDeviceMemory memory,
                                                       uint64_t* pAddress) {
-    AEMU_SCOPED_TRACE("vkMapMemoryIntoAddressSpaceGOOGLE");
+    MESA_TRACE_SCOPE("vkMapMemoryIntoAddressSpaceGOOGLE");
     VkResult vkMapMemoryIntoAddressSpaceGOOGLE_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -4582,7 +4421,7 @@
     const uint32_t* pBufferInfoEntryIndices, const uint32_t* pBufferViewEntryIndices,
     const VkDescriptorImageInfo* pImageInfos, const VkDescriptorBufferInfo* pBufferInfos,
     const VkBufferView* pBufferViews) {
-    AEMU_SCOPED_TRACE("vkUpdateDescriptorSetWithTemplateSizedGOOGLE");
+    MESA_TRACE_SCOPE("vkUpdateDescriptorSetWithTemplateSizedGOOGLE");
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -4607,7 +4446,7 @@
 }
 void gfxstream_vk_BeginCommandBufferAsyncGOOGLE(VkCommandBuffer commandBuffer,
                                                 const VkCommandBufferBeginInfo* pBeginInfo) {
-    AEMU_SCOPED_TRACE("vkBeginCommandBufferAsyncGOOGLE");
+    MESA_TRACE_SCOPE("vkBeginCommandBufferAsyncGOOGLE");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -4617,7 +4456,7 @@
     }
 }
 void gfxstream_vk_EndCommandBufferAsyncGOOGLE(VkCommandBuffer commandBuffer) {
-    AEMU_SCOPED_TRACE("vkEndCommandBufferAsyncGOOGLE");
+    MESA_TRACE_SCOPE("vkEndCommandBufferAsyncGOOGLE");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -4628,7 +4467,7 @@
 }
 void gfxstream_vk_ResetCommandBufferAsyncGOOGLE(VkCommandBuffer commandBuffer,
                                                 VkCommandBufferResetFlags flags) {
-    AEMU_SCOPED_TRACE("vkResetCommandBufferAsyncGOOGLE");
+    MESA_TRACE_SCOPE("vkResetCommandBufferAsyncGOOGLE");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -4639,7 +4478,7 @@
 }
 void gfxstream_vk_CommandBufferHostSyncGOOGLE(VkCommandBuffer commandBuffer, uint32_t needHostSync,
                                               uint32_t sequenceNumber) {
-    AEMU_SCOPED_TRACE("vkCommandBufferHostSyncGOOGLE");
+    MESA_TRACE_SCOPE("vkCommandBufferHostSyncGOOGLE");
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
@@ -4653,7 +4492,7 @@
                                                         const VkAllocationCallbacks* pAllocator,
                                                         VkImage* pImage,
                                                         VkMemoryRequirements* pMemoryRequirements) {
-    AEMU_SCOPED_TRACE("vkCreateImageWithRequirementsGOOGLE");
+    MESA_TRACE_SCOPE("vkCreateImageWithRequirementsGOOGLE");
     VkResult vkCreateImageWithRequirementsGOOGLE_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -4668,7 +4507,7 @@
 VkResult gfxstream_vk_CreateBufferWithRequirementsGOOGLE(
     VkDevice device, const VkBufferCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator,
     VkBuffer* pBuffer, VkMemoryRequirements* pMemoryRequirements) {
-    AEMU_SCOPED_TRACE("vkCreateBufferWithRequirementsGOOGLE");
+    MESA_TRACE_SCOPE("vkCreateBufferWithRequirementsGOOGLE");
     VkResult vkCreateBufferWithRequirementsGOOGLE_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     struct gfxstream_vk_buffer* gfxstream_pBuffer = (gfxstream_vk_buffer*)vk_object_zalloc(
@@ -4688,7 +4527,7 @@
 VkResult gfxstream_vk_GetMemoryHostAddressInfoGOOGLE(VkDevice device, VkDeviceMemory memory,
                                                      uint64_t* pAddress, uint64_t* pSize,
                                                      uint64_t* pHostmemId) {
-    AEMU_SCOPED_TRACE("vkGetMemoryHostAddressInfoGOOGLE");
+    MESA_TRACE_SCOPE("vkGetMemoryHostAddressInfoGOOGLE");
     VkResult vkGetMemoryHostAddressInfoGOOGLE_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -4701,7 +4540,7 @@
 }
 VkResult gfxstream_vk_FreeMemorySyncGOOGLE(VkDevice device, VkDeviceMemory memory,
                                            const VkAllocationCallbacks* pAllocator) {
-    AEMU_SCOPED_TRACE("vkFreeMemorySyncGOOGLE");
+    MESA_TRACE_SCOPE("vkFreeMemorySyncGOOGLE");
     VkResult vkFreeMemorySyncGOOGLE_VkResult_return = (VkResult)0;
     if (VK_NULL_HANDLE == memory) {
         return vkFreeMemorySyncGOOGLE_VkResult_return;
@@ -4716,7 +4555,7 @@
 }
 void gfxstream_vk_QueueHostSyncGOOGLE(VkQueue queue, uint32_t needHostSync,
                                       uint32_t sequenceNumber) {
-    AEMU_SCOPED_TRACE("vkQueueHostSyncGOOGLE");
+    MESA_TRACE_SCOPE("vkQueueHostSyncGOOGLE");
     VK_FROM_HANDLE(gfxstream_vk_queue, gfxstream_queue, queue);
     {
         auto vkEnc =
@@ -4727,7 +4566,7 @@
 }
 void gfxstream_vk_QueueSubmitAsyncGOOGLE(VkQueue queue, uint32_t submitCount,
                                          const VkSubmitInfo* pSubmits, VkFence fence) {
-    AEMU_SCOPED_TRACE("vkQueueSubmitAsyncGOOGLE");
+    MESA_TRACE_SCOPE("vkQueueSubmitAsyncGOOGLE");
     VK_FROM_HANDLE(gfxstream_vk_queue, gfxstream_queue, queue);
     VK_FROM_HANDLE(gfxstream_vk_fence, gfxstream_fence, fence);
     {
@@ -4748,10 +4587,8 @@
                 internal_VkSubmitInfo_pWaitSemaphores[i].size();
             /* VkSubmitInfo::pCommandBuffers */
             internal_VkSubmitInfo_pCommandBuffers.push_back(std::vector<VkCommandBuffer>());
-            internal_VkSubmitInfo_pCommandBuffers[i].reserve(
+            internal_VkSubmitInfo_pCommandBuffers[i].resize(
                 internal_pSubmits[i].commandBufferCount);
-            memset(&internal_VkSubmitInfo_pCommandBuffers[i][0], 0,
-                   sizeof(VkCommandBuffer) * internal_pSubmits[i].commandBufferCount);
             for (uint32_t j = 0; j < internal_pSubmits[i].commandBufferCount; ++j) {
                 VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_pCommandBuffers,
                                internal_pSubmits[i].pCommandBuffers[j]);
@@ -4775,7 +4612,7 @@
     }
 }
 void gfxstream_vk_QueueWaitIdleAsyncGOOGLE(VkQueue queue) {
-    AEMU_SCOPED_TRACE("vkQueueWaitIdleAsyncGOOGLE");
+    MESA_TRACE_SCOPE("vkQueueWaitIdleAsyncGOOGLE");
     VK_FROM_HANDLE(gfxstream_vk_queue, gfxstream_queue, queue);
     {
         auto vkEnc =
@@ -4785,7 +4622,7 @@
 }
 void gfxstream_vk_QueueBindSparseAsyncGOOGLE(VkQueue queue, uint32_t bindInfoCount,
                                              const VkBindSparseInfo* pBindInfo, VkFence fence) {
-    AEMU_SCOPED_TRACE("vkQueueBindSparseAsyncGOOGLE");
+    MESA_TRACE_SCOPE("vkQueueBindSparseAsyncGOOGLE");
     VK_FROM_HANDLE(gfxstream_vk_queue, gfxstream_queue, queue);
     VK_FROM_HANDLE(gfxstream_vk_fence, gfxstream_fence, fence);
     {
@@ -4809,10 +4646,7 @@
             /* VkBindSparseInfo::pBufferBinds */
             internal_VkBindSparseInfo_pBufferBinds.push_back(
                 std::vector<VkSparseBufferMemoryBindInfo>());
-            internal_VkBindSparseInfo_pBufferBinds[i].reserve(
-                internal_pBindInfo[i].bufferBindCount);
-            memset(&internal_VkBindSparseInfo_pBufferBinds[i][0], 0,
-                   sizeof(VkSparseBufferMemoryBindInfo) * internal_pBindInfo[i].bufferBindCount);
+            internal_VkBindSparseInfo_pBufferBinds[i].resize(internal_pBindInfo[i].bufferBindCount);
             for (uint32_t j = 0; j < internal_pBindInfo[i].bufferBindCount; ++j) {
                 internal_VkBindSparseInfo_pBufferBinds[i][j] =
                     internal_pBindInfo[i].pBufferBinds[j];
@@ -4842,7 +4676,7 @@
 void gfxstream_vk_GetLinearImageLayoutGOOGLE(VkDevice device, VkFormat format,
                                              VkDeviceSize* pOffset,
                                              VkDeviceSize* pRowPitchAlignment) {
-    AEMU_SCOPED_TRACE("vkGetLinearImageLayoutGOOGLE");
+    MESA_TRACE_SCOPE("vkGetLinearImageLayoutGOOGLE");
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -4853,7 +4687,7 @@
 void gfxstream_vk_GetLinearImageLayout2GOOGLE(VkDevice device, const VkImageCreateInfo* pCreateInfo,
                                               VkDeviceSize* pOffset,
                                               VkDeviceSize* pRowPitchAlignment) {
-    AEMU_SCOPED_TRACE("vkGetLinearImageLayout2GOOGLE");
+    MESA_TRACE_SCOPE("vkGetLinearImageLayout2GOOGLE");
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -4863,7 +4697,7 @@
 }
 void gfxstream_vk_QueueFlushCommandsGOOGLE(VkQueue queue, VkCommandBuffer commandBuffer,
                                            VkDeviceSize dataSize, const void* pData) {
-    AEMU_SCOPED_TRACE("vkQueueFlushCommandsGOOGLE");
+    MESA_TRACE_SCOPE("vkQueueFlushCommandsGOOGLE");
     VK_FROM_HANDLE(gfxstream_vk_queue, gfxstream_queue, queue);
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
@@ -4881,7 +4715,7 @@
     const uint32_t* pDescriptorSetPendingAllocation,
     const uint32_t* pDescriptorWriteStartingIndices, uint32_t pendingDescriptorWriteCount,
     const VkWriteDescriptorSet* pPendingDescriptorWrites) {
-    AEMU_SCOPED_TRACE("vkQueueCommitDescriptorSetUpdatesGOOGLE");
+    MESA_TRACE_SCOPE("vkQueueCommitDescriptorSetUpdatesGOOGLE");
     VK_FROM_HANDLE(gfxstream_vk_queue, gfxstream_queue, queue);
     {
         auto vkEnc =
@@ -4894,11 +4728,8 @@
             /* VkWriteDescriptorSet::pBufferInfo */
             internal_VkWriteDescriptorSet_pBufferInfo.push_back(
                 std::vector<VkDescriptorBufferInfo>());
-            internal_VkWriteDescriptorSet_pBufferInfo[i].reserve(
+            internal_VkWriteDescriptorSet_pBufferInfo[i].resize(
                 internal_pPendingDescriptorWrites[i].descriptorCount);
-            memset(&internal_VkWriteDescriptorSet_pBufferInfo[i][0], 0,
-                   sizeof(VkDescriptorBufferInfo) *
-                       internal_pPendingDescriptorWrites[i].descriptorCount);
             for (uint32_t j = 0; j < internal_pPendingDescriptorWrites[i].descriptorCount; ++j) {
                 if (internal_pPendingDescriptorWrites[i].pBufferInfo) {
                     internal_VkWriteDescriptorSet_pBufferInfo[i][j] =
@@ -4925,7 +4756,7 @@
 }
 void gfxstream_vk_CollectDescriptorPoolIdsGOOGLE(VkDevice device, VkDescriptorPool descriptorPool,
                                                  uint32_t* pPoolIdCount, uint64_t* pPoolIds) {
-    AEMU_SCOPED_TRACE("vkCollectDescriptorPoolIdsGOOGLE");
+    MESA_TRACE_SCOPE("vkCollectDescriptorPoolIdsGOOGLE");
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -4937,7 +4768,7 @@
                                                             uint32_t waitSemaphoreCount,
                                                             const VkSemaphore* pWaitSemaphores,
                                                             VkImage image) {
-    AEMU_SCOPED_TRACE("vkQueueSignalReleaseImageANDROIDAsyncGOOGLE");
+    MESA_TRACE_SCOPE("vkQueueSignalReleaseImageANDROIDAsyncGOOGLE");
     VK_FROM_HANDLE(gfxstream_vk_queue, gfxstream_queue, queue);
     {
         auto vkEnc =
@@ -4956,7 +4787,7 @@
                                                         VkDeviceMemory deviceMemory,
                                                         VkDeviceSize dataOffset,
                                                         VkDeviceSize dataSize) {
-    AEMU_SCOPED_TRACE("vkQueueFlushCommandsFromAuxMemoryGOOGLE");
+    MESA_TRACE_SCOPE("vkQueueFlushCommandsFromAuxMemoryGOOGLE");
     VK_FROM_HANDLE(gfxstream_vk_queue, gfxstream_queue, queue);
     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
     {
@@ -4968,7 +4799,7 @@
     }
 }
 VkResult gfxstream_vk_GetBlobGOOGLE(VkDevice device, VkDeviceMemory memory) {
-    AEMU_SCOPED_TRACE("vkGetBlobGOOGLE");
+    MESA_TRACE_SCOPE("vkGetBlobGOOGLE");
     VkResult vkGetBlobGOOGLE_VkResult_return = (VkResult)0;
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
@@ -4986,7 +4817,7 @@
     const uint32_t* pBufferViewEntryIndices, const VkDescriptorImageInfo* pImageInfos,
     const VkDescriptorBufferInfo* pBufferInfos, const VkBufferView* pBufferViews,
     const uint8_t* pInlineUniformBlockData) {
-    AEMU_SCOPED_TRACE("vkUpdateDescriptorSetWithTemplateSized2GOOGLE");
+    MESA_TRACE_SCOPE("vkUpdateDescriptorSetWithTemplateSized2GOOGLE");
     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
     {
         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
@@ -5012,7 +4843,7 @@
 }
 void gfxstream_vk_QueueSubmitAsync2GOOGLE(VkQueue queue, uint32_t submitCount,
                                           const VkSubmitInfo2* pSubmits, VkFence fence) {
-    AEMU_SCOPED_TRACE("vkQueueSubmitAsync2GOOGLE");
+    MESA_TRACE_SCOPE("vkQueueSubmitAsync2GOOGLE");
     VK_FROM_HANDLE(gfxstream_vk_queue, gfxstream_queue, queue);
     VK_FROM_HANDLE(gfxstream_vk_fence, gfxstream_fence, fence);
     {
@@ -5039,10 +4870,8 @@
             /* VkSubmitInfo2::pCommandBufferInfos */
             internal_VkSubmitInfo2_pCommandBufferInfos.push_back(
                 std::vector<VkCommandBufferSubmitInfo>());
-            internal_VkSubmitInfo2_pCommandBufferInfos[i].reserve(
+            internal_VkSubmitInfo2_pCommandBufferInfos[i].resize(
                 internal_pSubmits[i].commandBufferInfoCount);
-            memset(&internal_VkSubmitInfo2_pCommandBufferInfos[i][0], 0,
-                   sizeof(VkCommandBufferSubmitInfo) * internal_pSubmits[i].commandBufferInfoCount);
             for (uint32_t j = 0; j < internal_pSubmits[i].commandBufferInfoCount; ++j) {
                 internal_VkSubmitInfo2_pCommandBufferInfos[i][j] =
                     internal_pSubmits[i].pCommandBufferInfos[j];
@@ -5071,10 +4900,17 @@
             true /* do lock */);
     }
 }
-#endif
-#ifdef VK_EXT_load_store_op_none
-#endif
-#ifdef VK_EXT_image_compression_control_swapchain
-#endif
-#ifdef VK_QNX_external_memory_screen_buffer
+VkResult gfxstream_vk_GetSemaphoreGOOGLE(VkDevice device, VkSemaphore semaphore, uint64_t syncId) {
+    MESA_TRACE_SCOPE("vkGetSemaphoreGOOGLE");
+    VkResult vkGetSemaphoreGOOGLE_VkResult_return = (VkResult)0;
+    VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
+    VK_FROM_HANDLE(gfxstream_vk_semaphore, gfxstream_semaphore, semaphore);
+    {
+        auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
+        vkGetSemaphoreGOOGLE_VkResult_return = vkEnc->vkGetSemaphoreGOOGLE(
+            gfxstream_device->internal_object, gfxstream_semaphore->internal_object, syncId,
+            true /* do lock */);
+    }
+    return vkGetSemaphoreGOOGLE_VkResult_return;
+}
 #endif
diff --git a/guest/vulkan_enc/goldfish_vk_counting_guest.cpp b/guest/vulkan_enc/goldfish_vk_counting_guest.cpp
index 8091de6..c5d56fc 100644
--- a/guest/vulkan_enc/goldfish_vk_counting_guest.cpp
+++ b/guest/vulkan_enc/goldfish_vk_counting_guest.cpp
@@ -32,6 +32,7 @@
 
 #include "goldfish_vk_counting_guest.h"
 
+#include <cstdlib>
 #include <cstring>
 
 #include "goldfish_vk_extension_structs_guest.h"
@@ -5708,16 +5709,6 @@
 }
 
 #endif
-#ifdef VK_KHR_surface
-#endif
-#ifdef VK_KHR_swapchain
-#endif
-#ifdef VK_KHR_xcb_surface
-#endif
-#ifdef VK_KHR_android_surface
-#endif
-#ifdef VK_KHR_win32_surface
-#endif
 #ifdef VK_KHR_dynamic_rendering
 void count_VkRenderingFragmentShadingRateAttachmentInfoKHR(
     uint32_t featureBits, VkStructureType rootType,
@@ -5795,24 +5786,6 @@
 }
 
 #endif
-#ifdef VK_KHR_get_physical_device_properties2
-#endif
-#ifdef VK_KHR_maintenance1
-#endif
-#ifdef VK_KHR_external_memory_capabilities
-#endif
-#ifdef VK_KHR_external_memory
-#endif
-#ifdef VK_KHR_external_memory_win32
-#endif
-#ifdef VK_KHR_external_memory_fd
-#endif
-#ifdef VK_KHR_external_semaphore_capabilities
-#endif
-#ifdef VK_KHR_external_semaphore
-#endif
-#ifdef VK_KHR_external_semaphore_win32
-#endif
 #ifdef VK_KHR_external_semaphore_fd
 void count_VkImportSemaphoreFdInfoKHR(uint32_t featureBits, VkStructureType rootType,
                                       const VkImportSemaphoreFdInfoKHR* toCount, size_t* count) {
@@ -5849,8 +5822,6 @@
 }
 
 #endif
-#ifdef VK_KHR_shader_float16_int8
-#endif
 #ifdef VK_KHR_incremental_present
 void count_VkRectLayerKHR(uint32_t featureBits, VkStructureType rootType,
                           const VkRectLayerKHR* toCount, size_t* count) {
@@ -5907,16 +5878,6 @@
 }
 
 #endif
-#ifdef VK_KHR_descriptor_update_template
-#endif
-#ifdef VK_KHR_imageless_framebuffer
-#endif
-#ifdef VK_KHR_create_renderpass2
-#endif
-#ifdef VK_KHR_external_fence_capabilities
-#endif
-#ifdef VK_KHR_external_fence
-#endif
 #ifdef VK_KHR_external_fence_fd
 void count_VkImportFenceFdInfoKHR(uint32_t featureBits, VkStructureType rootType,
                                   const VkImportFenceFdInfoKHR* toCount, size_t* count) {
@@ -5953,30 +5914,6 @@
 }
 
 #endif
-#ifdef VK_KHR_maintenance2
-#endif
-#ifdef VK_KHR_dedicated_allocation
-#endif
-#ifdef VK_KHR_storage_buffer_storage_class
-#endif
-#ifdef VK_KHR_get_memory_requirements2
-#endif
-#ifdef VK_KHR_image_format_list
-#endif
-#ifdef VK_KHR_sampler_ycbcr_conversion
-#endif
-#ifdef VK_KHR_bind_memory2
-#endif
-#ifdef VK_KHR_maintenance3
-#endif
-#ifdef VK_KHR_shader_subgroup_extended_types
-#endif
-#ifdef VK_KHR_vulkan_memory_model
-#endif
-#ifdef VK_KHR_shader_terminate_invocation
-#endif
-#ifdef VK_KHR_buffer_device_address
-#endif
 #ifdef VK_KHR_pipeline_executable_properties
 void count_VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR(
     uint32_t featureBits, VkStructureType rootType,
@@ -6097,10 +6034,6 @@
 }
 
 #endif
-#ifdef VK_KHR_shader_integer_dot_product
-#endif
-#ifdef VK_KHR_shader_non_semantic_info
-#endif
 #ifdef VK_KHR_synchronization2
 void count_VkQueueFamilyCheckpointProperties2NV(uint32_t featureBits, VkStructureType rootType,
                                                 const VkQueueFamilyCheckpointProperties2NV* toCount,
@@ -6137,14 +6070,6 @@
 }
 
 #endif
-#ifdef VK_KHR_zero_initialize_workgroup_memory
-#endif
-#ifdef VK_KHR_copy_commands2
-#endif
-#ifdef VK_KHR_format_feature_flags2
-#endif
-#ifdef VK_KHR_maintenance4
-#endif
 #ifdef VK_KHR_maintenance5
 void count_VkPhysicalDeviceMaintenance5FeaturesKHR(
     uint32_t featureBits, VkStructureType rootType,
@@ -6349,8 +6274,6 @@
 }
 
 #endif
-#ifdef VK_EXT_debug_report
-#endif
 #ifdef VK_EXT_transform_feedback
 void count_VkPhysicalDeviceTransformFeedbackFeaturesEXT(
     uint32_t featureBits, VkStructureType rootType,
@@ -6409,10 +6332,6 @@
 }
 
 #endif
-#ifdef VK_AMD_gpu_shader_half_float
-#endif
-#ifdef VK_EXT_texture_compression_astc_hdr
-#endif
 #ifdef VK_EXT_depth_clip_enable
 void count_VkPhysicalDeviceDepthClipEnableFeaturesEXT(
     uint32_t featureBits, VkStructureType rootType,
@@ -6446,18 +6365,6 @@
 }
 
 #endif
-#ifdef VK_EXT_swapchain_colorspace
-#endif
-#ifdef VK_EXT_queue_family_foreign
-#endif
-#ifdef VK_EXT_debug_utils
-#endif
-#ifdef VK_ANDROID_external_memory_android_hardware_buffer
-#endif
-#ifdef VK_EXT_inline_uniform_block
-#endif
-#ifdef VK_EXT_shader_stencil_export
-#endif
 #ifdef VK_EXT_vertex_attribute_divisor
 void count_VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT(
     uint32_t featureBits, VkStructureType rootType,
@@ -6526,12 +6433,6 @@
 }
 
 #endif
-#ifdef VK_EXT_pipeline_creation_feedback
-#endif
-#ifdef VK_NV_shader_subgroup_partitioned
-#endif
-#ifdef VK_EXT_metal_surface
-#endif
 #ifdef VK_EXT_fragment_density_map
 void count_VkPhysicalDeviceFragmentDensityMapFeaturesEXT(
     uint32_t featureBits, VkStructureType rootType,
@@ -6587,14 +6488,6 @@
 }
 
 #endif
-#ifdef VK_EXT_scalar_block_layout
-#endif
-#ifdef VK_EXT_subgroup_size_control
-#endif
-#ifdef VK_EXT_tooling_info
-#endif
-#ifdef VK_EXT_validation_features
-#endif
 #ifdef VK_EXT_provoking_vertex
 void count_VkPhysicalDeviceProvokingVertexFeaturesEXT(
     uint32_t featureBits, VkStructureType rootType,
@@ -6950,10 +6843,6 @@
 }
 
 #endif
-#ifdef VK_EXT_swapchain_maintenance1
-#endif
-#ifdef VK_EXT_shader_demote_to_helper_invocation
-#endif
 #ifdef VK_EXT_texel_buffer_alignment
 void count_VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT(
     uint32_t featureBits, VkStructureType rootType,
@@ -7111,12 +7000,6 @@
 }
 
 #endif
-#ifdef VK_EXT_private_data
-#endif
-#ifdef VK_EXT_pipeline_creation_cache_control
-#endif
-#ifdef VK_EXT_metal_objects
-#endif
 #ifdef VK_EXT_graphics_pipeline_library
 void count_VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT(
     uint32_t featureBits, VkStructureType rootType,
@@ -7182,8 +7065,6 @@
 }
 
 #endif
-#ifdef VK_EXT_image_robustness
-#endif
 #ifdef VK_EXT_image_compression_control
 void count_VkPhysicalDeviceImageCompressionControlFeaturesEXT(
     uint32_t featureBits, VkStructureType rootType,
@@ -7377,8 +7258,6 @@
 }
 
 #endif
-#ifdef VK_EXT_load_store_op_none
-#endif
 #ifdef VK_EXT_image_compression_control_swapchain
 void count_VkPhysicalDeviceImageCompressionControlSwapchainFeaturesEXT(
     uint32_t featureBits, VkStructureType rootType,
@@ -7396,8 +7275,6 @@
 }
 
 #endif
-#ifdef VK_QNX_external_memory_screen_buffer
-#endif
 void count_extension_struct(uint32_t featureBits, VkStructureType rootType,
                             const void* structExtension, size_t* count) {
     VkInstanceCreateInfo* structAccess = (VkInstanceCreateInfo*)(structExtension);
diff --git a/guest/vulkan_enc/goldfish_vk_counting_guest.h b/guest/vulkan_enc/goldfish_vk_counting_guest.h
index 3288d09..2573d47 100644
--- a/guest/vulkan_enc/goldfish_vk_counting_guest.h
+++ b/guest/vulkan_enc/goldfish_vk_counting_guest.h
@@ -1033,16 +1033,6 @@
                                            size_t* count);
 
 #endif
-#ifdef VK_KHR_surface
-#endif
-#ifdef VK_KHR_swapchain
-#endif
-#ifdef VK_KHR_xcb_surface
-#endif
-#ifdef VK_KHR_android_surface
-#endif
-#ifdef VK_KHR_win32_surface
-#endif
 #ifdef VK_KHR_dynamic_rendering
 DEFINE_ALIAS_FUNCTION(count_VkRenderingInfo, count_VkRenderingInfoKHR)
 
@@ -1098,8 +1088,6 @@
                       count_VkPhysicalDeviceSparseImageFormatInfo2KHR)
 
 #endif
-#ifdef VK_KHR_maintenance1
-#endif
 #ifdef VK_KHR_external_memory_capabilities
 DEFINE_ALIAS_FUNCTION(count_VkExternalMemoryProperties, count_VkExternalMemoryPropertiesKHR)
 
@@ -1127,10 +1115,6 @@
 DEFINE_ALIAS_FUNCTION(count_VkExportMemoryAllocateInfo, count_VkExportMemoryAllocateInfoKHR)
 
 #endif
-#ifdef VK_KHR_external_memory_win32
-#endif
-#ifdef VK_KHR_external_memory_fd
-#endif
 #ifdef VK_KHR_external_semaphore_capabilities
 DEFINE_ALIAS_FUNCTION(count_VkPhysicalDeviceExternalSemaphoreInfo,
                       count_VkPhysicalDeviceExternalSemaphoreInfoKHR)
@@ -1142,8 +1126,6 @@
 DEFINE_ALIAS_FUNCTION(count_VkExportSemaphoreCreateInfo, count_VkExportSemaphoreCreateInfoKHR)
 
 #endif
-#ifdef VK_KHR_external_semaphore_win32
-#endif
 #ifdef VK_KHR_external_semaphore_fd
 void count_VkImportSemaphoreFdInfoKHR(uint32_t featureBits, VkStructureType rootType,
                                       const VkImportSemaphoreFdInfoKHR* toCount, size_t* count);
@@ -1250,8 +1232,6 @@
 DEFINE_ALIAS_FUNCTION(count_VkMemoryDedicatedAllocateInfo, count_VkMemoryDedicatedAllocateInfoKHR)
 
 #endif
-#ifdef VK_KHR_storage_buffer_storage_class
-#endif
 #ifdef VK_KHR_get_memory_requirements2
 DEFINE_ALIAS_FUNCTION(count_VkBufferMemoryRequirementsInfo2,
                       count_VkBufferMemoryRequirementsInfo2KHR)
@@ -1369,8 +1349,6 @@
                       count_VkPhysicalDeviceShaderIntegerDotProductPropertiesKHR)
 
 #endif
-#ifdef VK_KHR_shader_non_semantic_info
-#endif
 #ifdef VK_KHR_synchronization2
 DEFINE_ALIAS_FUNCTION(count_VkMemoryBarrier2, count_VkMemoryBarrier2KHR)
 
@@ -1491,8 +1469,6 @@
     const VkPhysicalDevicePresentationPropertiesANDROID* toCount, size_t* count);
 
 #endif
-#ifdef VK_EXT_debug_report
-#endif
 #ifdef VK_EXT_transform_feedback
 void count_VkPhysicalDeviceTransformFeedbackFeaturesEXT(
     uint32_t featureBits, VkStructureType rootType,
@@ -1507,8 +1483,6 @@
     const VkPipelineRasterizationStateStreamCreateInfoEXT* toCount, size_t* count);
 
 #endif
-#ifdef VK_AMD_gpu_shader_half_float
-#endif
 #ifdef VK_EXT_texture_compression_astc_hdr
 DEFINE_ALIAS_FUNCTION(count_VkPhysicalDeviceTextureCompressionASTCHDRFeatures,
                       count_VkPhysicalDeviceTextureCompressionASTCHDRFeaturesEXT)
@@ -1524,14 +1498,6 @@
     const VkPipelineRasterizationDepthClipStateCreateInfoEXT* toCount, size_t* count);
 
 #endif
-#ifdef VK_EXT_swapchain_colorspace
-#endif
-#ifdef VK_EXT_queue_family_foreign
-#endif
-#ifdef VK_EXT_debug_utils
-#endif
-#ifdef VK_ANDROID_external_memory_android_hardware_buffer
-#endif
 #ifdef VK_EXT_inline_uniform_block
 DEFINE_ALIAS_FUNCTION(count_VkPhysicalDeviceInlineUniformBlockFeatures,
                       count_VkPhysicalDeviceInlineUniformBlockFeaturesEXT)
@@ -1546,8 +1512,6 @@
                       count_VkDescriptorPoolInlineUniformBlockCreateInfoEXT)
 
 #endif
-#ifdef VK_EXT_shader_stencil_export
-#endif
 #ifdef VK_EXT_vertex_attribute_divisor
 void count_VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT(
     uint32_t featureBits, VkStructureType rootType,
@@ -1573,10 +1537,6 @@
 DEFINE_ALIAS_FUNCTION(count_VkPipelineCreationFeedback, count_VkPipelineCreationFeedbackEXT)
 
 #endif
-#ifdef VK_NV_shader_subgroup_partitioned
-#endif
-#ifdef VK_EXT_metal_surface
-#endif
 #ifdef VK_EXT_fragment_density_map
 void count_VkPhysicalDeviceFragmentDensityMapFeaturesEXT(
     uint32_t featureBits, VkStructureType rootType,
@@ -1611,8 +1571,6 @@
 DEFINE_ALIAS_FUNCTION(count_VkPhysicalDeviceToolProperties, count_VkPhysicalDeviceToolPropertiesEXT)
 
 #endif
-#ifdef VK_EXT_validation_features
-#endif
 #ifdef VK_EXT_provoking_vertex
 void count_VkPhysicalDeviceProvokingVertexFeaturesEXT(
     uint32_t featureBits, VkStructureType rootType,
@@ -1694,8 +1652,6 @@
 DEFINE_ALIAS_FUNCTION(count_VkImageSubresource2KHR, count_VkImageSubresource2EXT)
 
 #endif
-#ifdef VK_EXT_swapchain_maintenance1
-#endif
 #ifdef VK_EXT_shader_demote_to_helper_invocation
 DEFINE_ALIAS_FUNCTION(count_VkPhysicalDeviceShaderDemoteToHelperInvocationFeatures,
                       count_VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT)
@@ -1762,8 +1718,6 @@
                       count_VkPhysicalDevicePipelineCreationCacheControlFeaturesEXT)
 
 #endif
-#ifdef VK_EXT_metal_objects
-#endif
 #ifdef VK_EXT_graphics_pipeline_library
 void count_VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT(
     uint32_t featureBits, VkStructureType rootType,
@@ -1841,16 +1795,11 @@
                               const VkCreateBlobGOOGLE* toCount, size_t* count);
 
 #endif
-#ifdef VK_EXT_load_store_op_none
-#endif
 #ifdef VK_EXT_image_compression_control_swapchain
 void count_VkPhysicalDeviceImageCompressionControlSwapchainFeaturesEXT(
     uint32_t featureBits, VkStructureType rootType,
     const VkPhysicalDeviceImageCompressionControlSwapchainFeaturesEXT* toCount, size_t* count);
 
 #endif
-#ifdef VK_QNX_external_memory_screen_buffer
-#endif
-
 }  // namespace vk
 }  // namespace gfxstream
diff --git a/guest/vulkan_enc/goldfish_vk_deepcopy_guest.cpp b/guest/vulkan_enc/goldfish_vk_deepcopy_guest.cpp
index 415e9e2..2cdab19 100644
--- a/guest/vulkan_enc/goldfish_vk_deepcopy_guest.cpp
+++ b/guest/vulkan_enc/goldfish_vk_deepcopy_guest.cpp
@@ -6503,16 +6503,6 @@
 }
 
 #endif
-#ifdef VK_KHR_surface
-#endif
-#ifdef VK_KHR_swapchain
-#endif
-#ifdef VK_KHR_xcb_surface
-#endif
-#ifdef VK_KHR_android_surface
-#endif
-#ifdef VK_KHR_win32_surface
-#endif
 #ifdef VK_KHR_dynamic_rendering
 void deepcopy_VkRenderingFragmentShadingRateAttachmentInfoKHR(
     Allocator* alloc, VkStructureType rootType,
@@ -6613,24 +6603,6 @@
 }
 
 #endif
-#ifdef VK_KHR_get_physical_device_properties2
-#endif
-#ifdef VK_KHR_maintenance1
-#endif
-#ifdef VK_KHR_external_memory_capabilities
-#endif
-#ifdef VK_KHR_external_memory
-#endif
-#ifdef VK_KHR_external_memory_win32
-#endif
-#ifdef VK_KHR_external_memory_fd
-#endif
-#ifdef VK_KHR_external_semaphore_capabilities
-#endif
-#ifdef VK_KHR_external_semaphore
-#endif
-#ifdef VK_KHR_external_semaphore_win32
-#endif
 #ifdef VK_KHR_external_semaphore_fd
 void deepcopy_VkImportSemaphoreFdInfoKHR(Allocator* alloc, VkStructureType rootType,
                                          const VkImportSemaphoreFdInfoKHR* from,
@@ -6677,8 +6649,6 @@
 }
 
 #endif
-#ifdef VK_KHR_shader_float16_int8
-#endif
 #ifdef VK_KHR_incremental_present
 void deepcopy_VkRectLayerKHR(Allocator* alloc, VkStructureType rootType, const VkRectLayerKHR* from,
                              VkRectLayerKHR* to) {
@@ -6742,16 +6712,6 @@
 }
 
 #endif
-#ifdef VK_KHR_descriptor_update_template
-#endif
-#ifdef VK_KHR_imageless_framebuffer
-#endif
-#ifdef VK_KHR_create_renderpass2
-#endif
-#ifdef VK_KHR_external_fence_capabilities
-#endif
-#ifdef VK_KHR_external_fence
-#endif
 #ifdef VK_KHR_external_fence_fd
 void deepcopy_VkImportFenceFdInfoKHR(Allocator* alloc, VkStructureType rootType,
                                      const VkImportFenceFdInfoKHR* from,
@@ -6797,30 +6757,6 @@
 }
 
 #endif
-#ifdef VK_KHR_maintenance2
-#endif
-#ifdef VK_KHR_dedicated_allocation
-#endif
-#ifdef VK_KHR_storage_buffer_storage_class
-#endif
-#ifdef VK_KHR_get_memory_requirements2
-#endif
-#ifdef VK_KHR_image_format_list
-#endif
-#ifdef VK_KHR_sampler_ycbcr_conversion
-#endif
-#ifdef VK_KHR_bind_memory2
-#endif
-#ifdef VK_KHR_maintenance3
-#endif
-#ifdef VK_KHR_shader_subgroup_extended_types
-#endif
-#ifdef VK_KHR_vulkan_memory_model
-#endif
-#ifdef VK_KHR_shader_terminate_invocation
-#endif
-#ifdef VK_KHR_buffer_device_address
-#endif
 #ifdef VK_KHR_pipeline_executable_properties
 void deepcopy_VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR(
     Allocator* alloc, VkStructureType rootType,
@@ -6976,10 +6912,6 @@
 }
 
 #endif
-#ifdef VK_KHR_shader_integer_dot_product
-#endif
-#ifdef VK_KHR_shader_non_semantic_info
-#endif
 #ifdef VK_KHR_synchronization2
 void deepcopy_VkQueueFamilyCheckpointProperties2NV(Allocator* alloc, VkStructureType rootType,
                                                    const VkQueueFamilyCheckpointProperties2NV* from,
@@ -7029,14 +6961,6 @@
 }
 
 #endif
-#ifdef VK_KHR_zero_initialize_workgroup_memory
-#endif
-#ifdef VK_KHR_copy_commands2
-#endif
-#ifdef VK_KHR_format_feature_flags2
-#endif
-#ifdef VK_KHR_maintenance4
-#endif
 #ifdef VK_KHR_maintenance5
 void deepcopy_VkPhysicalDeviceMaintenance5FeaturesKHR(
     Allocator* alloc, VkStructureType rootType, const VkPhysicalDeviceMaintenance5FeaturesKHR* from,
@@ -7320,8 +7244,6 @@
 }
 
 #endif
-#ifdef VK_EXT_debug_report
-#endif
 #ifdef VK_EXT_transform_feedback
 void deepcopy_VkPhysicalDeviceTransformFeedbackFeaturesEXT(
     Allocator* alloc, VkStructureType rootType,
@@ -7393,10 +7315,6 @@
 }
 
 #endif
-#ifdef VK_AMD_gpu_shader_half_float
-#endif
-#ifdef VK_EXT_texture_compression_astc_hdr
-#endif
 #ifdef VK_EXT_depth_clip_enable
 void deepcopy_VkPhysicalDeviceDepthClipEnableFeaturesEXT(
     Allocator* alloc, VkStructureType rootType,
@@ -7445,18 +7363,6 @@
 }
 
 #endif
-#ifdef VK_EXT_swapchain_colorspace
-#endif
-#ifdef VK_EXT_queue_family_foreign
-#endif
-#ifdef VK_EXT_debug_utils
-#endif
-#ifdef VK_ANDROID_external_memory_android_hardware_buffer
-#endif
-#ifdef VK_EXT_inline_uniform_block
-#endif
-#ifdef VK_EXT_shader_stencil_export
-#endif
 #ifdef VK_EXT_vertex_attribute_divisor
 void deepcopy_VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT(
     Allocator* alloc, VkStructureType rootType,
@@ -7551,12 +7457,6 @@
 }
 
 #endif
-#ifdef VK_EXT_pipeline_creation_feedback
-#endif
-#ifdef VK_NV_shader_subgroup_partitioned
-#endif
-#ifdef VK_EXT_metal_surface
-#endif
 #ifdef VK_EXT_fragment_density_map
 void deepcopy_VkPhysicalDeviceFragmentDensityMapFeaturesEXT(
     Allocator* alloc, VkStructureType rootType,
@@ -7634,14 +7534,6 @@
 }
 
 #endif
-#ifdef VK_EXT_scalar_block_layout
-#endif
-#ifdef VK_EXT_subgroup_size_control
-#endif
-#ifdef VK_EXT_tooling_info
-#endif
-#ifdef VK_EXT_validation_features
-#endif
 #ifdef VK_EXT_provoking_vertex
 void deepcopy_VkPhysicalDeviceProvokingVertexFeaturesEXT(
     Allocator* alloc, VkStructureType rootType,
@@ -8125,10 +8017,6 @@
 }
 
 #endif
-#ifdef VK_EXT_swapchain_maintenance1
-#endif
-#ifdef VK_EXT_shader_demote_to_helper_invocation
-#endif
 #ifdef VK_EXT_texel_buffer_alignment
 void deepcopy_VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT(
     Allocator* alloc, VkStructureType rootType,
@@ -8346,12 +8234,6 @@
 }
 
 #endif
-#ifdef VK_EXT_private_data
-#endif
-#ifdef VK_EXT_pipeline_creation_cache_control
-#endif
-#ifdef VK_EXT_metal_objects
-#endif
 #ifdef VK_EXT_graphics_pipeline_library
 void deepcopy_VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT(
     Allocator* alloc, VkStructureType rootType,
@@ -8447,8 +8329,6 @@
 }
 
 #endif
-#ifdef VK_EXT_image_robustness
-#endif
 #ifdef VK_EXT_image_compression_control
 void deepcopy_VkPhysicalDeviceImageCompressionControlFeaturesEXT(
     Allocator* alloc, VkStructureType rootType,
@@ -8716,8 +8596,6 @@
 }
 
 #endif
-#ifdef VK_EXT_load_store_op_none
-#endif
 #ifdef VK_EXT_image_compression_control_swapchain
 void deepcopy_VkPhysicalDeviceImageCompressionControlSwapchainFeaturesEXT(
     Allocator* alloc, VkStructureType rootType,
@@ -8743,8 +8621,6 @@
 }
 
 #endif
-#ifdef VK_QNX_external_memory_screen_buffer
-#endif
 void deepcopy_extension_struct(Allocator* alloc, VkStructureType rootType,
                                const void* structExtension, void* structExtension_out) {
     if (!structExtension) {
diff --git a/guest/vulkan_enc/goldfish_vk_deepcopy_guest.h b/guest/vulkan_enc/goldfish_vk_deepcopy_guest.h
index 9a49782..98f1696 100644
--- a/guest/vulkan_enc/goldfish_vk_deepcopy_guest.h
+++ b/guest/vulkan_enc/goldfish_vk_deepcopy_guest.h
@@ -1147,16 +1147,6 @@
                                               VkDeviceImageMemoryRequirements* to);
 
 #endif
-#ifdef VK_KHR_surface
-#endif
-#ifdef VK_KHR_swapchain
-#endif
-#ifdef VK_KHR_xcb_surface
-#endif
-#ifdef VK_KHR_android_surface
-#endif
-#ifdef VK_KHR_win32_surface
-#endif
 #ifdef VK_KHR_dynamic_rendering
 DEFINE_ALIAS_FUNCTION(deepcopy_VkRenderingInfo, deepcopy_VkRenderingInfoKHR)
 
@@ -1217,8 +1207,6 @@
                       deepcopy_VkPhysicalDeviceSparseImageFormatInfo2KHR)
 
 #endif
-#ifdef VK_KHR_maintenance1
-#endif
 #ifdef VK_KHR_external_memory_capabilities
 DEFINE_ALIAS_FUNCTION(deepcopy_VkExternalMemoryProperties, deepcopy_VkExternalMemoryPropertiesKHR)
 
@@ -1247,10 +1235,6 @@
 DEFINE_ALIAS_FUNCTION(deepcopy_VkExportMemoryAllocateInfo, deepcopy_VkExportMemoryAllocateInfoKHR)
 
 #endif
-#ifdef VK_KHR_external_memory_win32
-#endif
-#ifdef VK_KHR_external_memory_fd
-#endif
 #ifdef VK_KHR_external_semaphore_capabilities
 DEFINE_ALIAS_FUNCTION(deepcopy_VkPhysicalDeviceExternalSemaphoreInfo,
                       deepcopy_VkPhysicalDeviceExternalSemaphoreInfoKHR)
@@ -1263,8 +1247,6 @@
 DEFINE_ALIAS_FUNCTION(deepcopy_VkExportSemaphoreCreateInfo, deepcopy_VkExportSemaphoreCreateInfoKHR)
 
 #endif
-#ifdef VK_KHR_external_semaphore_win32
-#endif
 #ifdef VK_KHR_external_semaphore_fd
 void deepcopy_VkImportSemaphoreFdInfoKHR(Allocator* alloc, VkStructureType rootType,
                                          const VkImportSemaphoreFdInfoKHR* from,
@@ -1376,8 +1358,6 @@
                       deepcopy_VkMemoryDedicatedAllocateInfoKHR)
 
 #endif
-#ifdef VK_KHR_storage_buffer_storage_class
-#endif
 #ifdef VK_KHR_get_memory_requirements2
 DEFINE_ALIAS_FUNCTION(deepcopy_VkBufferMemoryRequirementsInfo2,
                       deepcopy_VkBufferMemoryRequirementsInfo2KHR)
@@ -1501,8 +1481,6 @@
                       deepcopy_VkPhysicalDeviceShaderIntegerDotProductPropertiesKHR)
 
 #endif
-#ifdef VK_KHR_shader_non_semantic_info
-#endif
 #ifdef VK_KHR_synchronization2
 DEFINE_ALIAS_FUNCTION(deepcopy_VkMemoryBarrier2, deepcopy_VkMemoryBarrier2KHR)
 
@@ -1629,8 +1607,6 @@
     VkPhysicalDevicePresentationPropertiesANDROID* to);
 
 #endif
-#ifdef VK_EXT_debug_report
-#endif
 #ifdef VK_EXT_transform_feedback
 void deepcopy_VkPhysicalDeviceTransformFeedbackFeaturesEXT(
     Allocator* alloc, VkStructureType rootType,
@@ -1648,8 +1624,6 @@
     VkPipelineRasterizationStateStreamCreateInfoEXT* to);
 
 #endif
-#ifdef VK_AMD_gpu_shader_half_float
-#endif
 #ifdef VK_EXT_texture_compression_astc_hdr
 DEFINE_ALIAS_FUNCTION(deepcopy_VkPhysicalDeviceTextureCompressionASTCHDRFeatures,
                       deepcopy_VkPhysicalDeviceTextureCompressionASTCHDRFeaturesEXT)
@@ -1667,14 +1641,6 @@
     VkPipelineRasterizationDepthClipStateCreateInfoEXT* to);
 
 #endif
-#ifdef VK_EXT_swapchain_colorspace
-#endif
-#ifdef VK_EXT_queue_family_foreign
-#endif
-#ifdef VK_EXT_debug_utils
-#endif
-#ifdef VK_ANDROID_external_memory_android_hardware_buffer
-#endif
 #ifdef VK_EXT_inline_uniform_block
 DEFINE_ALIAS_FUNCTION(deepcopy_VkPhysicalDeviceInlineUniformBlockFeatures,
                       deepcopy_VkPhysicalDeviceInlineUniformBlockFeaturesEXT)
@@ -1689,8 +1655,6 @@
                       deepcopy_VkDescriptorPoolInlineUniformBlockCreateInfoEXT)
 
 #endif
-#ifdef VK_EXT_shader_stencil_export
-#endif
 #ifdef VK_EXT_vertex_attribute_divisor
 void deepcopy_VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT(
     Allocator* alloc, VkStructureType rootType,
@@ -1720,10 +1684,6 @@
 DEFINE_ALIAS_FUNCTION(deepcopy_VkPipelineCreationFeedback, deepcopy_VkPipelineCreationFeedbackEXT)
 
 #endif
-#ifdef VK_NV_shader_subgroup_partitioned
-#endif
-#ifdef VK_EXT_metal_surface
-#endif
 #ifdef VK_EXT_fragment_density_map
 void deepcopy_VkPhysicalDeviceFragmentDensityMapFeaturesEXT(
     Allocator* alloc, VkStructureType rootType,
@@ -1762,8 +1722,6 @@
                       deepcopy_VkPhysicalDeviceToolPropertiesEXT)
 
 #endif
-#ifdef VK_EXT_validation_features
-#endif
 #ifdef VK_EXT_provoking_vertex
 void deepcopy_VkPhysicalDeviceProvokingVertexFeaturesEXT(
     Allocator* alloc, VkStructureType rootType,
@@ -1861,8 +1819,6 @@
 DEFINE_ALIAS_FUNCTION(deepcopy_VkImageSubresource2KHR, deepcopy_VkImageSubresource2EXT)
 
 #endif
-#ifdef VK_EXT_swapchain_maintenance1
-#endif
 #ifdef VK_EXT_shader_demote_to_helper_invocation
 DEFINE_ALIAS_FUNCTION(deepcopy_VkPhysicalDeviceShaderDemoteToHelperInvocationFeatures,
                       deepcopy_VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT)
@@ -1935,8 +1891,6 @@
                       deepcopy_VkPhysicalDevicePipelineCreationCacheControlFeaturesEXT)
 
 #endif
-#ifdef VK_EXT_metal_objects
-#endif
 #ifdef VK_EXT_graphics_pipeline_library
 void deepcopy_VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT(
     Allocator* alloc, VkStructureType rootType,
@@ -2023,8 +1977,6 @@
                                  const VkCreateBlobGOOGLE* from, VkCreateBlobGOOGLE* to);
 
 #endif
-#ifdef VK_EXT_load_store_op_none
-#endif
 #ifdef VK_EXT_image_compression_control_swapchain
 void deepcopy_VkPhysicalDeviceImageCompressionControlSwapchainFeaturesEXT(
     Allocator* alloc, VkStructureType rootType,
@@ -2032,8 +1984,5 @@
     VkPhysicalDeviceImageCompressionControlSwapchainFeaturesEXT* to);
 
 #endif
-#ifdef VK_QNX_external_memory_screen_buffer
-#endif
-
 }  // namespace vk
 }  // namespace gfxstream
diff --git a/guest/vulkan_enc/goldfish_vk_extension_structs_guest.cpp b/guest/vulkan_enc/goldfish_vk_extension_structs_guest.cpp
index 8f4e423..27a7c47 100644
--- a/guest/vulkan_enc/goldfish_vk_extension_structs_guest.cpp
+++ b/guest/vulkan_enc/goldfish_vk_extension_structs_guest.cpp
@@ -34,198 +34,6 @@
 namespace gfxstream {
 namespace vk {
 
-#ifdef VK_VERSION_1_0
-#endif
-#ifdef VK_VERSION_1_1
-#endif
-#ifdef VK_VERSION_1_2
-#endif
-#ifdef VK_VERSION_1_3
-#endif
-#ifdef VK_KHR_surface
-#endif
-#ifdef VK_KHR_swapchain
-#endif
-#ifdef VK_KHR_xcb_surface
-#endif
-#ifdef VK_KHR_android_surface
-#endif
-#ifdef VK_KHR_win32_surface
-#endif
-#ifdef VK_KHR_dynamic_rendering
-#endif
-#ifdef VK_KHR_get_physical_device_properties2
-#endif
-#ifdef VK_KHR_maintenance1
-#endif
-#ifdef VK_KHR_external_memory_capabilities
-#endif
-#ifdef VK_KHR_external_memory
-#endif
-#ifdef VK_KHR_external_memory_win32
-#endif
-#ifdef VK_KHR_external_memory_fd
-#endif
-#ifdef VK_KHR_external_semaphore_capabilities
-#endif
-#ifdef VK_KHR_external_semaphore
-#endif
-#ifdef VK_KHR_external_semaphore_win32
-#endif
-#ifdef VK_KHR_external_semaphore_fd
-#endif
-#ifdef VK_KHR_shader_float16_int8
-#endif
-#ifdef VK_KHR_incremental_present
-#endif
-#ifdef VK_KHR_descriptor_update_template
-#endif
-#ifdef VK_KHR_imageless_framebuffer
-#endif
-#ifdef VK_KHR_create_renderpass2
-#endif
-#ifdef VK_KHR_external_fence_capabilities
-#endif
-#ifdef VK_KHR_external_fence
-#endif
-#ifdef VK_KHR_external_fence_fd
-#endif
-#ifdef VK_KHR_maintenance2
-#endif
-#ifdef VK_KHR_dedicated_allocation
-#endif
-#ifdef VK_KHR_storage_buffer_storage_class
-#endif
-#ifdef VK_KHR_get_memory_requirements2
-#endif
-#ifdef VK_KHR_image_format_list
-#endif
-#ifdef VK_KHR_sampler_ycbcr_conversion
-#endif
-#ifdef VK_KHR_bind_memory2
-#endif
-#ifdef VK_KHR_maintenance3
-#endif
-#ifdef VK_KHR_shader_subgroup_extended_types
-#endif
-#ifdef VK_KHR_vulkan_memory_model
-#endif
-#ifdef VK_KHR_shader_terminate_invocation
-#endif
-#ifdef VK_KHR_buffer_device_address
-#endif
-#ifdef VK_KHR_pipeline_executable_properties
-#endif
-#ifdef VK_KHR_shader_integer_dot_product
-#endif
-#ifdef VK_KHR_shader_non_semantic_info
-#endif
-#ifdef VK_KHR_synchronization2
-#endif
-#ifdef VK_KHR_zero_initialize_workgroup_memory
-#endif
-#ifdef VK_KHR_copy_commands2
-#endif
-#ifdef VK_KHR_format_feature_flags2
-#endif
-#ifdef VK_KHR_maintenance4
-#endif
-#ifdef VK_KHR_maintenance5
-#endif
-#ifdef VK_ANDROID_native_buffer
-#endif
-#ifdef VK_EXT_debug_report
-#endif
-#ifdef VK_EXT_transform_feedback
-#endif
-#ifdef VK_AMD_gpu_shader_half_float
-#endif
-#ifdef VK_EXT_texture_compression_astc_hdr
-#endif
-#ifdef VK_EXT_depth_clip_enable
-#endif
-#ifdef VK_EXT_swapchain_colorspace
-#endif
-#ifdef VK_EXT_queue_family_foreign
-#endif
-#ifdef VK_EXT_debug_utils
-#endif
-#ifdef VK_ANDROID_external_memory_android_hardware_buffer
-#endif
-#ifdef VK_EXT_inline_uniform_block
-#endif
-#ifdef VK_EXT_shader_stencil_export
-#endif
-#ifdef VK_EXT_vertex_attribute_divisor
-#endif
-#ifdef VK_EXT_pipeline_creation_feedback
-#endif
-#ifdef VK_NV_shader_subgroup_partitioned
-#endif
-#ifdef VK_EXT_metal_surface
-#endif
-#ifdef VK_EXT_fragment_density_map
-#endif
-#ifdef VK_EXT_scalar_block_layout
-#endif
-#ifdef VK_EXT_subgroup_size_control
-#endif
-#ifdef VK_EXT_tooling_info
-#endif
-#ifdef VK_EXT_validation_features
-#endif
-#ifdef VK_EXT_provoking_vertex
-#endif
-#ifdef VK_EXT_line_rasterization
-#endif
-#ifdef VK_EXT_index_type_uint8
-#endif
-#ifdef VK_EXT_extended_dynamic_state
-#endif
-#ifdef VK_EXT_host_image_copy
-#endif
-#ifdef VK_EXT_swapchain_maintenance1
-#endif
-#ifdef VK_EXT_shader_demote_to_helper_invocation
-#endif
-#ifdef VK_EXT_texel_buffer_alignment
-#endif
-#ifdef VK_EXT_device_memory_report
-#endif
-#ifdef VK_EXT_robustness2
-#endif
-#ifdef VK_EXT_custom_border_color
-#endif
-#ifdef VK_EXT_private_data
-#endif
-#ifdef VK_EXT_pipeline_creation_cache_control
-#endif
-#ifdef VK_EXT_metal_objects
-#endif
-#ifdef VK_EXT_graphics_pipeline_library
-#endif
-#ifdef VK_EXT_ycbcr_2plane_444_formats
-#endif
-#ifdef VK_EXT_image_robustness
-#endif
-#ifdef VK_EXT_image_compression_control
-#endif
-#ifdef VK_EXT_4444_formats
-#endif
-#ifdef VK_EXT_primitive_topology_list_restart
-#endif
-#ifdef VK_EXT_extended_dynamic_state2
-#endif
-#ifdef VK_EXT_color_write_enable
-#endif
-#ifdef VK_GOOGLE_gfxstream
-#endif
-#ifdef VK_EXT_load_store_op_none
-#endif
-#ifdef VK_EXT_image_compression_control_swapchain
-#endif
-#ifdef VK_QNX_external_memory_screen_buffer
-#endif
 uint32_t goldfish_vk_struct_type(const void* structExtension) {
     const uint32_t asStructType = *(reinterpret_cast<const uint32_t*>(structExtension));
     return asStructType;
diff --git a/guest/vulkan_enc/goldfish_vk_extension_structs_guest.h b/guest/vulkan_enc/goldfish_vk_extension_structs_guest.h
index 30d250f..47447cb 100644
--- a/guest/vulkan_enc/goldfish_vk_extension_structs_guest.h
+++ b/guest/vulkan_enc/goldfish_vk_extension_structs_guest.h
@@ -54,198 +54,5 @@
                                                               VkStructureType rootType,
                                                               const void* structExtension);
 
-#ifdef VK_VERSION_1_0
-#endif
-#ifdef VK_VERSION_1_1
-#endif
-#ifdef VK_VERSION_1_2
-#endif
-#ifdef VK_VERSION_1_3
-#endif
-#ifdef VK_KHR_surface
-#endif
-#ifdef VK_KHR_swapchain
-#endif
-#ifdef VK_KHR_xcb_surface
-#endif
-#ifdef VK_KHR_android_surface
-#endif
-#ifdef VK_KHR_win32_surface
-#endif
-#ifdef VK_KHR_dynamic_rendering
-#endif
-#ifdef VK_KHR_get_physical_device_properties2
-#endif
-#ifdef VK_KHR_maintenance1
-#endif
-#ifdef VK_KHR_external_memory_capabilities
-#endif
-#ifdef VK_KHR_external_memory
-#endif
-#ifdef VK_KHR_external_memory_win32
-#endif
-#ifdef VK_KHR_external_memory_fd
-#endif
-#ifdef VK_KHR_external_semaphore_capabilities
-#endif
-#ifdef VK_KHR_external_semaphore
-#endif
-#ifdef VK_KHR_external_semaphore_win32
-#endif
-#ifdef VK_KHR_external_semaphore_fd
-#endif
-#ifdef VK_KHR_shader_float16_int8
-#endif
-#ifdef VK_KHR_incremental_present
-#endif
-#ifdef VK_KHR_descriptor_update_template
-#endif
-#ifdef VK_KHR_imageless_framebuffer
-#endif
-#ifdef VK_KHR_create_renderpass2
-#endif
-#ifdef VK_KHR_external_fence_capabilities
-#endif
-#ifdef VK_KHR_external_fence
-#endif
-#ifdef VK_KHR_external_fence_fd
-#endif
-#ifdef VK_KHR_maintenance2
-#endif
-#ifdef VK_KHR_dedicated_allocation
-#endif
-#ifdef VK_KHR_storage_buffer_storage_class
-#endif
-#ifdef VK_KHR_get_memory_requirements2
-#endif
-#ifdef VK_KHR_image_format_list
-#endif
-#ifdef VK_KHR_sampler_ycbcr_conversion
-#endif
-#ifdef VK_KHR_bind_memory2
-#endif
-#ifdef VK_KHR_maintenance3
-#endif
-#ifdef VK_KHR_shader_subgroup_extended_types
-#endif
-#ifdef VK_KHR_vulkan_memory_model
-#endif
-#ifdef VK_KHR_shader_terminate_invocation
-#endif
-#ifdef VK_KHR_buffer_device_address
-#endif
-#ifdef VK_KHR_pipeline_executable_properties
-#endif
-#ifdef VK_KHR_shader_integer_dot_product
-#endif
-#ifdef VK_KHR_shader_non_semantic_info
-#endif
-#ifdef VK_KHR_synchronization2
-#endif
-#ifdef VK_KHR_zero_initialize_workgroup_memory
-#endif
-#ifdef VK_KHR_copy_commands2
-#endif
-#ifdef VK_KHR_format_feature_flags2
-#endif
-#ifdef VK_KHR_maintenance4
-#endif
-#ifdef VK_KHR_maintenance5
-#endif
-#ifdef VK_ANDROID_native_buffer
-#endif
-#ifdef VK_EXT_debug_report
-#endif
-#ifdef VK_EXT_transform_feedback
-#endif
-#ifdef VK_AMD_gpu_shader_half_float
-#endif
-#ifdef VK_EXT_texture_compression_astc_hdr
-#endif
-#ifdef VK_EXT_depth_clip_enable
-#endif
-#ifdef VK_EXT_swapchain_colorspace
-#endif
-#ifdef VK_EXT_queue_family_foreign
-#endif
-#ifdef VK_EXT_debug_utils
-#endif
-#ifdef VK_ANDROID_external_memory_android_hardware_buffer
-#endif
-#ifdef VK_EXT_inline_uniform_block
-#endif
-#ifdef VK_EXT_shader_stencil_export
-#endif
-#ifdef VK_EXT_vertex_attribute_divisor
-#endif
-#ifdef VK_EXT_pipeline_creation_feedback
-#endif
-#ifdef VK_NV_shader_subgroup_partitioned
-#endif
-#ifdef VK_EXT_metal_surface
-#endif
-#ifdef VK_EXT_fragment_density_map
-#endif
-#ifdef VK_EXT_scalar_block_layout
-#endif
-#ifdef VK_EXT_subgroup_size_control
-#endif
-#ifdef VK_EXT_tooling_info
-#endif
-#ifdef VK_EXT_validation_features
-#endif
-#ifdef VK_EXT_provoking_vertex
-#endif
-#ifdef VK_EXT_line_rasterization
-#endif
-#ifdef VK_EXT_index_type_uint8
-#endif
-#ifdef VK_EXT_extended_dynamic_state
-#endif
-#ifdef VK_EXT_host_image_copy
-#endif
-#ifdef VK_EXT_swapchain_maintenance1
-#endif
-#ifdef VK_EXT_shader_demote_to_helper_invocation
-#endif
-#ifdef VK_EXT_texel_buffer_alignment
-#endif
-#ifdef VK_EXT_device_memory_report
-#endif
-#ifdef VK_EXT_robustness2
-#endif
-#ifdef VK_EXT_custom_border_color
-#endif
-#ifdef VK_EXT_private_data
-#endif
-#ifdef VK_EXT_pipeline_creation_cache_control
-#endif
-#ifdef VK_EXT_metal_objects
-#endif
-#ifdef VK_EXT_graphics_pipeline_library
-#endif
-#ifdef VK_EXT_ycbcr_2plane_444_formats
-#endif
-#ifdef VK_EXT_image_robustness
-#endif
-#ifdef VK_EXT_image_compression_control
-#endif
-#ifdef VK_EXT_4444_formats
-#endif
-#ifdef VK_EXT_primitive_topology_list_restart
-#endif
-#ifdef VK_EXT_extended_dynamic_state2
-#endif
-#ifdef VK_EXT_color_write_enable
-#endif
-#ifdef VK_GOOGLE_gfxstream
-#endif
-#ifdef VK_EXT_load_store_op_none
-#endif
-#ifdef VK_EXT_image_compression_control_swapchain
-#endif
-#ifdef VK_QNX_external_memory_screen_buffer
-#endif
-
 }  // namespace vk
 }  // namespace gfxstream
diff --git a/guest/vulkan_enc/goldfish_vk_marshaling_guest.cpp b/guest/vulkan_enc/goldfish_vk_marshaling_guest.cpp
index 46dc549..43f1037 100644
--- a/guest/vulkan_enc/goldfish_vk_marshaling_guest.cpp
+++ b/guest/vulkan_enc/goldfish_vk_marshaling_guest.cpp
@@ -10807,16 +10807,6 @@
 }
 
 #endif
-#ifdef VK_KHR_surface
-#endif
-#ifdef VK_KHR_swapchain
-#endif
-#ifdef VK_KHR_xcb_surface
-#endif
-#ifdef VK_KHR_android_surface
-#endif
-#ifdef VK_KHR_win32_surface
-#endif
 #ifdef VK_KHR_dynamic_rendering
 void marshal_VkRenderingFragmentShadingRateAttachmentInfoKHR(
     VulkanStreamGuest* vkStream, VkStructureType rootType,
@@ -10958,24 +10948,6 @@
 }
 
 #endif
-#ifdef VK_KHR_get_physical_device_properties2
-#endif
-#ifdef VK_KHR_maintenance1
-#endif
-#ifdef VK_KHR_external_memory_capabilities
-#endif
-#ifdef VK_KHR_external_memory
-#endif
-#ifdef VK_KHR_external_memory_win32
-#endif
-#ifdef VK_KHR_external_memory_fd
-#endif
-#ifdef VK_KHR_external_semaphore_capabilities
-#endif
-#ifdef VK_KHR_external_semaphore
-#endif
-#ifdef VK_KHR_external_semaphore_win32
-#endif
 #ifdef VK_KHR_external_semaphore_fd
 void marshal_VkImportSemaphoreFdInfoKHR(VulkanStreamGuest* vkStream, VkStructureType rootType,
                                         const VkImportSemaphoreFdInfoKHR* forMarshaling) {
@@ -11047,8 +11019,6 @@
 }
 
 #endif
-#ifdef VK_KHR_shader_float16_int8
-#endif
 #ifdef VK_KHR_incremental_present
 void marshal_VkRectLayerKHR(VulkanStreamGuest* vkStream, VkStructureType rootType,
                             const VkRectLayerKHR* forMarshaling) {
@@ -11153,16 +11123,6 @@
 }
 
 #endif
-#ifdef VK_KHR_descriptor_update_template
-#endif
-#ifdef VK_KHR_imageless_framebuffer
-#endif
-#ifdef VK_KHR_create_renderpass2
-#endif
-#ifdef VK_KHR_external_fence_capabilities
-#endif
-#ifdef VK_KHR_external_fence
-#endif
 #ifdef VK_KHR_external_fence_fd
 void marshal_VkImportFenceFdInfoKHR(VulkanStreamGuest* vkStream, VkStructureType rootType,
                                     const VkImportFenceFdInfoKHR* forMarshaling) {
@@ -11231,30 +11191,6 @@
 }
 
 #endif
-#ifdef VK_KHR_maintenance2
-#endif
-#ifdef VK_KHR_dedicated_allocation
-#endif
-#ifdef VK_KHR_storage_buffer_storage_class
-#endif
-#ifdef VK_KHR_get_memory_requirements2
-#endif
-#ifdef VK_KHR_image_format_list
-#endif
-#ifdef VK_KHR_sampler_ycbcr_conversion
-#endif
-#ifdef VK_KHR_bind_memory2
-#endif
-#ifdef VK_KHR_maintenance3
-#endif
-#ifdef VK_KHR_shader_subgroup_extended_types
-#endif
-#ifdef VK_KHR_vulkan_memory_model
-#endif
-#ifdef VK_KHR_shader_terminate_invocation
-#endif
-#ifdef VK_KHR_buffer_device_address
-#endif
 #ifdef VK_KHR_pipeline_executable_properties
 void marshal_VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR(
     VulkanStreamGuest* vkStream, VkStructureType rootType,
@@ -11461,10 +11397,6 @@
 }
 
 #endif
-#ifdef VK_KHR_shader_integer_dot_product
-#endif
-#ifdef VK_KHR_shader_non_semantic_info
-#endif
 #ifdef VK_KHR_synchronization2
 void marshal_VkQueueFamilyCheckpointProperties2NV(
     VulkanStreamGuest* vkStream, VkStructureType rootType,
@@ -11532,14 +11464,6 @@
 }
 
 #endif
-#ifdef VK_KHR_zero_initialize_workgroup_memory
-#endif
-#ifdef VK_KHR_copy_commands2
-#endif
-#ifdef VK_KHR_format_feature_flags2
-#endif
-#ifdef VK_KHR_maintenance4
-#endif
 #ifdef VK_KHR_maintenance5
 void marshal_VkPhysicalDeviceMaintenance5FeaturesKHR(
     VulkanStreamGuest* vkStream, VkStructureType rootType,
@@ -11894,8 +11818,6 @@
 }
 
 #endif
-#ifdef VK_EXT_debug_report
-#endif
 #ifdef VK_EXT_transform_feedback
 void marshal_VkPhysicalDeviceTransformFeedbackFeaturesEXT(
     VulkanStreamGuest* vkStream, VkStructureType rootType,
@@ -12006,10 +11928,6 @@
 }
 
 #endif
-#ifdef VK_AMD_gpu_shader_half_float
-#endif
-#ifdef VK_EXT_texture_compression_astc_hdr
-#endif
 #ifdef VK_EXT_depth_clip_enable
 void marshal_VkPhysicalDeviceDepthClipEnableFeaturesEXT(
     VulkanStreamGuest* vkStream, VkStructureType rootType,
@@ -12064,18 +11982,6 @@
 }
 
 #endif
-#ifdef VK_EXT_swapchain_colorspace
-#endif
-#ifdef VK_EXT_queue_family_foreign
-#endif
-#ifdef VK_EXT_debug_utils
-#endif
-#ifdef VK_ANDROID_external_memory_android_hardware_buffer
-#endif
-#ifdef VK_EXT_inline_uniform_block
-#endif
-#ifdef VK_EXT_shader_stencil_export
-#endif
 #ifdef VK_EXT_vertex_attribute_divisor
 void marshal_VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT(
     VulkanStreamGuest* vkStream, VkStructureType rootType,
@@ -12190,12 +12096,6 @@
 }
 
 #endif
-#ifdef VK_EXT_pipeline_creation_feedback
-#endif
-#ifdef VK_NV_shader_subgroup_partitioned
-#endif
-#ifdef VK_EXT_metal_surface
-#endif
 #ifdef VK_EXT_fragment_density_map
 void marshal_VkPhysicalDeviceFragmentDensityMapFeaturesEXT(
     VulkanStreamGuest* vkStream, VkStructureType rootType,
@@ -12290,14 +12190,6 @@
 }
 
 #endif
-#ifdef VK_EXT_scalar_block_layout
-#endif
-#ifdef VK_EXT_subgroup_size_control
-#endif
-#ifdef VK_EXT_tooling_info
-#endif
-#ifdef VK_EXT_validation_features
-#endif
 #ifdef VK_EXT_provoking_vertex
 void marshal_VkPhysicalDeviceProvokingVertexFeaturesEXT(
     VulkanStreamGuest* vkStream, VkStructureType rootType,
@@ -12926,10 +12818,6 @@
 }
 
 #endif
-#ifdef VK_EXT_swapchain_maintenance1
-#endif
-#ifdef VK_EXT_shader_demote_to_helper_invocation
-#endif
 #ifdef VK_EXT_texel_buffer_alignment
 void marshal_VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT(
     VulkanStreamGuest* vkStream, VkStructureType rootType,
@@ -13193,12 +13081,6 @@
 }
 
 #endif
-#ifdef VK_EXT_private_data
-#endif
-#ifdef VK_EXT_pipeline_creation_cache_control
-#endif
-#ifdef VK_EXT_metal_objects
-#endif
 #ifdef VK_EXT_graphics_pipeline_library
 void marshal_VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT(
     VulkanStreamGuest* vkStream, VkStructureType rootType,
@@ -13309,8 +13191,6 @@
 }
 
 #endif
-#ifdef VK_EXT_image_robustness
-#endif
 #ifdef VK_EXT_image_compression_control
 void marshal_VkPhysicalDeviceImageCompressionControlFeaturesEXT(
     VulkanStreamGuest* vkStream, VkStructureType rootType,
@@ -13633,8 +13513,6 @@
 }
 
 #endif
-#ifdef VK_EXT_load_store_op_none
-#endif
 #ifdef VK_EXT_image_compression_control_swapchain
 void marshal_VkPhysicalDeviceImageCompressionControlSwapchainFeaturesEXT(
     VulkanStreamGuest* vkStream, VkStructureType rootType,
@@ -13661,8 +13539,6 @@
 }
 
 #endif
-#ifdef VK_QNX_external_memory_screen_buffer
-#endif
 void marshal_extension_struct(VulkanStreamGuest* vkStream, VkStructureType rootType,
                               const void* structExtension) {
     VkInstanceCreateInfo* structAccess = (VkInstanceCreateInfo*)(structExtension);
@@ -16785,6 +16661,9 @@
         case OP_vkGetBlobGOOGLE: {
             return "OP_vkGetBlobGOOGLE";
         }
+        case OP_vkGetSemaphoreGOOGLE: {
+            return "OP_vkGetSemaphoreGOOGLE";
+        }
 #endif
 #ifdef VK_KHR_dynamic_rendering
         case OP_vkCmdEndRenderingKHR: {
diff --git a/guest/vulkan_enc/goldfish_vk_marshaling_guest.h b/guest/vulkan_enc/goldfish_vk_marshaling_guest.h
index 5d26900..c48c4c6 100644
--- a/guest/vulkan_enc/goldfish_vk_marshaling_guest.h
+++ b/guest/vulkan_enc/goldfish_vk_marshaling_guest.h
@@ -2203,16 +2203,6 @@
 #define OP_vkGetDeviceImageMemoryRequirements 282480635
 #define OP_vkGetDeviceImageSparseMemoryRequirements 233707261
 #endif
-#ifdef VK_KHR_surface
-#endif
-#ifdef VK_KHR_swapchain
-#endif
-#ifdef VK_KHR_xcb_surface
-#endif
-#ifdef VK_KHR_android_surface
-#endif
-#ifdef VK_KHR_win32_surface
-#endif
 #ifdef VK_KHR_dynamic_rendering
 DEFINE_ALIAS_FUNCTION(marshal_VkRenderingInfo, marshal_VkRenderingInfoKHR)
 
@@ -2387,10 +2377,6 @@
 DEFINE_ALIAS_FUNCTION(unmarshal_VkExportMemoryAllocateInfo, unmarshal_VkExportMemoryAllocateInfoKHR)
 
 #endif
-#ifdef VK_KHR_external_memory_win32
-#endif
-#ifdef VK_KHR_external_memory_fd
-#endif
 #ifdef VK_KHR_external_semaphore_capabilities
 DEFINE_ALIAS_FUNCTION(marshal_VkPhysicalDeviceExternalSemaphoreInfo,
                       marshal_VkPhysicalDeviceExternalSemaphoreInfoKHR)
@@ -2413,8 +2399,6 @@
                       unmarshal_VkExportSemaphoreCreateInfoKHR)
 
 #endif
-#ifdef VK_KHR_external_semaphore_win32
-#endif
 #ifdef VK_KHR_external_semaphore_fd
 void marshal_VkImportSemaphoreFdInfoKHR(VulkanStreamGuest* vkStream, VkStructureType rootType,
                                         const VkImportSemaphoreFdInfoKHR* forMarshaling);
@@ -2621,8 +2605,6 @@
                       unmarshal_VkMemoryDedicatedAllocateInfoKHR)
 
 #endif
-#ifdef VK_KHR_storage_buffer_storage_class
-#endif
 #ifdef VK_KHR_get_memory_requirements2
 DEFINE_ALIAS_FUNCTION(marshal_VkBufferMemoryRequirementsInfo2,
                       marshal_VkBufferMemoryRequirementsInfo2KHR)
@@ -2854,8 +2836,6 @@
                       unmarshal_VkPhysicalDeviceShaderIntegerDotProductPropertiesKHR)
 
 #endif
-#ifdef VK_KHR_shader_non_semantic_info
-#endif
 #ifdef VK_KHR_synchronization2
 DEFINE_ALIAS_FUNCTION(marshal_VkMemoryBarrier2, marshal_VkMemoryBarrier2KHR)
 
@@ -3106,8 +3086,6 @@
 #define OP_vkQueueSignalReleaseImageANDROID 20253
 #define OP_vkGetSwapchainGrallocUsage2ANDROID 287960452
 #endif
-#ifdef VK_EXT_debug_report
-#endif
 #ifdef VK_EXT_transform_feedback
 void marshal_VkPhysicalDeviceTransformFeedbackFeaturesEXT(
     VulkanStreamGuest* vkStream, VkStructureType rootType,
@@ -3140,8 +3118,6 @@
 #define OP_vkCmdEndQueryIndexedEXT 279821337
 #define OP_vkCmdDrawIndirectByteCountEXT 285235943
 #endif
-#ifdef VK_AMD_gpu_shader_half_float
-#endif
 #ifdef VK_EXT_texture_compression_astc_hdr
 DEFINE_ALIAS_FUNCTION(marshal_VkPhysicalDeviceTextureCompressionASTCHDRFeatures,
                       marshal_VkPhysicalDeviceTextureCompressionASTCHDRFeaturesEXT)
@@ -3168,14 +3144,6 @@
     VkPipelineRasterizationDepthClipStateCreateInfoEXT* forUnmarshaling);
 
 #endif
-#ifdef VK_EXT_swapchain_colorspace
-#endif
-#ifdef VK_EXT_queue_family_foreign
-#endif
-#ifdef VK_EXT_debug_utils
-#endif
-#ifdef VK_ANDROID_external_memory_android_hardware_buffer
-#endif
 #ifdef VK_EXT_inline_uniform_block
 DEFINE_ALIAS_FUNCTION(marshal_VkPhysicalDeviceInlineUniformBlockFeatures,
                       marshal_VkPhysicalDeviceInlineUniformBlockFeaturesEXT)
@@ -3202,8 +3170,6 @@
                       unmarshal_VkDescriptorPoolInlineUniformBlockCreateInfoEXT)
 
 #endif
-#ifdef VK_EXT_shader_stencil_export
-#endif
 #ifdef VK_EXT_vertex_attribute_divisor
 void marshal_VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT(
     VulkanStreamGuest* vkStream, VkStructureType rootType,
@@ -3250,10 +3216,6 @@
 DEFINE_ALIAS_FUNCTION(unmarshal_VkPipelineCreationFeedback, unmarshal_VkPipelineCreationFeedbackEXT)
 
 #endif
-#ifdef VK_NV_shader_subgroup_partitioned
-#endif
-#ifdef VK_EXT_metal_surface
-#endif
 #ifdef VK_EXT_fragment_density_map
 void marshal_VkPhysicalDeviceFragmentDensityMapFeaturesEXT(
     VulkanStreamGuest* vkStream, VkStructureType rootType,
@@ -3317,8 +3279,6 @@
 
 #define OP_vkGetPhysicalDeviceToolPropertiesEXT 282247593
 #endif
-#ifdef VK_EXT_validation_features
-#endif
 #ifdef VK_EXT_provoking_vertex
 void marshal_VkPhysicalDeviceProvokingVertexFeaturesEXT(
     VulkanStreamGuest* vkStream, VkStructureType rootType,
@@ -3487,8 +3447,6 @@
 #define OP_vkTransitionImageLayoutEXT 242817558
 #define OP_vkGetImageSubresourceLayout2EXT 296152177
 #endif
-#ifdef VK_EXT_swapchain_maintenance1
-#endif
 #ifdef VK_EXT_shader_demote_to_helper_invocation
 DEFINE_ALIAS_FUNCTION(marshal_VkPhysicalDeviceShaderDemoteToHelperInvocationFeatures,
                       marshal_VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT)
@@ -3614,8 +3572,6 @@
                       unmarshal_VkPhysicalDevicePipelineCreationCacheControlFeaturesEXT)
 
 #endif
-#ifdef VK_EXT_metal_objects
-#endif
 #ifdef VK_EXT_graphics_pipeline_library
 void marshal_VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT(
     VulkanStreamGuest* vkStream, VkStructureType rootType,
@@ -3780,8 +3736,7 @@
 #define OP_vkGetBlobGOOGLE 20341
 #define OP_vkUpdateDescriptorSetWithTemplateSized2GOOGLE 244782974
 #define OP_vkQueueSubmitAsync2GOOGLE 292092830
-#endif
-#ifdef VK_EXT_load_store_op_none
+#define OP_vkGetSemaphoreGOOGLE 20342
 #endif
 #ifdef VK_EXT_image_compression_control_swapchain
 void marshal_VkPhysicalDeviceImageCompressionControlSwapchainFeaturesEXT(
@@ -3793,8 +3748,6 @@
     VkPhysicalDeviceImageCompressionControlSwapchainFeaturesEXT* forUnmarshaling);
 
 #endif
-#ifdef VK_QNX_external_memory_screen_buffer
-#endif
 const char* api_opcode_to_string(const uint32_t opcode);
 
 #define OP_vkFirst_old 20000
diff --git a/guest/vulkan_enc/goldfish_vk_reserved_marshaling_guest.cpp b/guest/vulkan_enc/goldfish_vk_reserved_marshaling_guest.cpp
index 0f702ca..db59101 100644
--- a/guest/vulkan_enc/goldfish_vk_reserved_marshaling_guest.cpp
+++ b/guest/vulkan_enc/goldfish_vk_reserved_marshaling_guest.cpp
@@ -7291,16 +7291,6 @@
 }
 
 #endif
-#ifdef VK_KHR_surface
-#endif
-#ifdef VK_KHR_swapchain
-#endif
-#ifdef VK_KHR_xcb_surface
-#endif
-#ifdef VK_KHR_android_surface
-#endif
-#ifdef VK_KHR_win32_surface
-#endif
 #ifdef VK_KHR_dynamic_rendering
 void reservedmarshal_VkRenderingFragmentShadingRateAttachmentInfoKHR(
     VulkanStreamGuest* vkStream, VkStructureType rootType,
@@ -7388,24 +7378,6 @@
 }
 
 #endif
-#ifdef VK_KHR_get_physical_device_properties2
-#endif
-#ifdef VK_KHR_maintenance1
-#endif
-#ifdef VK_KHR_external_memory_capabilities
-#endif
-#ifdef VK_KHR_external_memory
-#endif
-#ifdef VK_KHR_external_memory_win32
-#endif
-#ifdef VK_KHR_external_memory_fd
-#endif
-#ifdef VK_KHR_external_semaphore_capabilities
-#endif
-#ifdef VK_KHR_external_semaphore
-#endif
-#ifdef VK_KHR_external_semaphore_win32
-#endif
 #ifdef VK_KHR_external_semaphore_fd
 void reservedmarshal_VkImportSemaphoreFdInfoKHR(VulkanStreamGuest* vkStream,
                                                 VkStructureType rootType,
@@ -7453,8 +7425,6 @@
 }
 
 #endif
-#ifdef VK_KHR_shader_float16_int8
-#endif
 #ifdef VK_KHR_incremental_present
 void reservedmarshal_VkRectLayerKHR(VulkanStreamGuest* vkStream, VkStructureType rootType,
                                     const VkRectLayerKHR* forMarshaling, uint8_t** ptr) {
@@ -7511,16 +7481,6 @@
 }
 
 #endif
-#ifdef VK_KHR_descriptor_update_template
-#endif
-#ifdef VK_KHR_imageless_framebuffer
-#endif
-#ifdef VK_KHR_create_renderpass2
-#endif
-#ifdef VK_KHR_external_fence_capabilities
-#endif
-#ifdef VK_KHR_external_fence
-#endif
 #ifdef VK_KHR_external_fence_fd
 void reservedmarshal_VkImportFenceFdInfoKHR(VulkanStreamGuest* vkStream, VkStructureType rootType,
                                             const VkImportFenceFdInfoKHR* forMarshaling,
@@ -7566,30 +7526,6 @@
 }
 
 #endif
-#ifdef VK_KHR_maintenance2
-#endif
-#ifdef VK_KHR_dedicated_allocation
-#endif
-#ifdef VK_KHR_storage_buffer_storage_class
-#endif
-#ifdef VK_KHR_get_memory_requirements2
-#endif
-#ifdef VK_KHR_image_format_list
-#endif
-#ifdef VK_KHR_sampler_ycbcr_conversion
-#endif
-#ifdef VK_KHR_bind_memory2
-#endif
-#ifdef VK_KHR_maintenance3
-#endif
-#ifdef VK_KHR_shader_subgroup_extended_types
-#endif
-#ifdef VK_KHR_vulkan_memory_model
-#endif
-#ifdef VK_KHR_shader_terminate_invocation
-#endif
-#ifdef VK_KHR_buffer_device_address
-#endif
 #ifdef VK_KHR_pipeline_executable_properties
 void reservedmarshal_VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR(
     VulkanStreamGuest* vkStream, VkStructureType rootType,
@@ -7727,10 +7663,6 @@
 }
 
 #endif
-#ifdef VK_KHR_shader_integer_dot_product
-#endif
-#ifdef VK_KHR_shader_non_semantic_info
-#endif
 #ifdef VK_KHR_synchronization2
 void reservedmarshal_VkQueueFamilyCheckpointProperties2NV(
     VulkanStreamGuest* vkStream, VkStructureType rootType,
@@ -7772,14 +7704,6 @@
 }
 
 #endif
-#ifdef VK_KHR_zero_initialize_workgroup_memory
-#endif
-#ifdef VK_KHR_copy_commands2
-#endif
-#ifdef VK_KHR_format_feature_flags2
-#endif
-#ifdef VK_KHR_maintenance4
-#endif
 #ifdef VK_KHR_maintenance5
 void reservedmarshal_VkPhysicalDeviceMaintenance5FeaturesKHR(
     VulkanStreamGuest* vkStream, VkStructureType rootType,
@@ -8009,8 +7933,6 @@
 }
 
 #endif
-#ifdef VK_EXT_debug_report
-#endif
 #ifdef VK_EXT_transform_feedback
 void reservedmarshal_VkPhysicalDeviceTransformFeedbackFeaturesEXT(
     VulkanStreamGuest* vkStream, VkStructureType rootType,
@@ -8084,10 +8006,6 @@
 }
 
 #endif
-#ifdef VK_AMD_gpu_shader_half_float
-#endif
-#ifdef VK_EXT_texture_compression_astc_hdr
-#endif
 #ifdef VK_EXT_depth_clip_enable
 void reservedmarshal_VkPhysicalDeviceDepthClipEnableFeaturesEXT(
     VulkanStreamGuest* vkStream, VkStructureType rootType,
@@ -8123,18 +8041,6 @@
 }
 
 #endif
-#ifdef VK_EXT_swapchain_colorspace
-#endif
-#ifdef VK_EXT_queue_family_foreign
-#endif
-#ifdef VK_EXT_debug_utils
-#endif
-#ifdef VK_ANDROID_external_memory_android_hardware_buffer
-#endif
-#ifdef VK_EXT_inline_uniform_block
-#endif
-#ifdef VK_EXT_shader_stencil_export
-#endif
 #ifdef VK_EXT_vertex_attribute_divisor
 void reservedmarshal_VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT(
     VulkanStreamGuest* vkStream, VkStructureType rootType,
@@ -8204,12 +8110,6 @@
 }
 
 #endif
-#ifdef VK_EXT_pipeline_creation_feedback
-#endif
-#ifdef VK_NV_shader_subgroup_partitioned
-#endif
-#ifdef VK_EXT_metal_surface
-#endif
 #ifdef VK_EXT_fragment_density_map
 void reservedmarshal_VkPhysicalDeviceFragmentDensityMapFeaturesEXT(
     VulkanStreamGuest* vkStream, VkStructureType rootType,
@@ -8267,14 +8167,6 @@
 }
 
 #endif
-#ifdef VK_EXT_scalar_block_layout
-#endif
-#ifdef VK_EXT_subgroup_size_control
-#endif
-#ifdef VK_EXT_tooling_info
-#endif
-#ifdef VK_EXT_validation_features
-#endif
 #ifdef VK_EXT_provoking_vertex
 void reservedmarshal_VkPhysicalDeviceProvokingVertexFeaturesEXT(
     VulkanStreamGuest* vkStream, VkStructureType rootType,
@@ -8676,10 +8568,6 @@
 }
 
 #endif
-#ifdef VK_EXT_swapchain_maintenance1
-#endif
-#ifdef VK_EXT_shader_demote_to_helper_invocation
-#endif
 #ifdef VK_EXT_texel_buffer_alignment
 void reservedmarshal_VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT(
     VulkanStreamGuest* vkStream, VkStructureType rootType,
@@ -8856,12 +8744,6 @@
 }
 
 #endif
-#ifdef VK_EXT_private_data
-#endif
-#ifdef VK_EXT_pipeline_creation_cache_control
-#endif
-#ifdef VK_EXT_metal_objects
-#endif
 #ifdef VK_EXT_graphics_pipeline_library
 void reservedmarshal_VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT(
     VulkanStreamGuest* vkStream, VkStructureType rootType,
@@ -8931,8 +8813,6 @@
 }
 
 #endif
-#ifdef VK_EXT_image_robustness
-#endif
 #ifdef VK_EXT_image_compression_control
 void reservedmarshal_VkPhysicalDeviceImageCompressionControlFeaturesEXT(
     VulkanStreamGuest* vkStream, VkStructureType rootType,
@@ -9147,8 +9027,6 @@
 }
 
 #endif
-#ifdef VK_EXT_load_store_op_none
-#endif
 #ifdef VK_EXT_image_compression_control_swapchain
 void reservedmarshal_VkPhysicalDeviceImageCompressionControlSwapchainFeaturesEXT(
     VulkanStreamGuest* vkStream, VkStructureType rootType,
@@ -9167,8 +9045,6 @@
 }
 
 #endif
-#ifdef VK_QNX_external_memory_screen_buffer
-#endif
 void reservedmarshal_extension_struct(VulkanStreamGuest* vkStream, VkStructureType rootType,
                                       const void* structExtension, uint8_t** ptr) {
     VkInstanceCreateInfo* structAccess = (VkInstanceCreateInfo*)(structExtension);
diff --git a/guest/vulkan_enc/goldfish_vk_reserved_marshaling_guest.h b/guest/vulkan_enc/goldfish_vk_reserved_marshaling_guest.h
index 4022f15..092c55a 100644
--- a/guest/vulkan_enc/goldfish_vk_reserved_marshaling_guest.h
+++ b/guest/vulkan_enc/goldfish_vk_reserved_marshaling_guest.h
@@ -1156,16 +1156,6 @@
     const VkDeviceImageMemoryRequirements* forMarshaling, uint8_t** ptr);
 
 #endif
-#ifdef VK_KHR_surface
-#endif
-#ifdef VK_KHR_swapchain
-#endif
-#ifdef VK_KHR_xcb_surface
-#endif
-#ifdef VK_KHR_android_surface
-#endif
-#ifdef VK_KHR_win32_surface
-#endif
 #ifdef VK_KHR_dynamic_rendering
 DEFINE_ALIAS_FUNCTION(reservedmarshal_VkRenderingInfo, reservedmarshal_VkRenderingInfoKHR)
 
@@ -1229,8 +1219,6 @@
                       reservedmarshal_VkPhysicalDeviceSparseImageFormatInfo2KHR)
 
 #endif
-#ifdef VK_KHR_maintenance1
-#endif
 #ifdef VK_KHR_external_memory_capabilities
 DEFINE_ALIAS_FUNCTION(reservedmarshal_VkExternalMemoryProperties,
                       reservedmarshal_VkExternalMemoryPropertiesKHR)
@@ -1262,10 +1250,6 @@
                       reservedmarshal_VkExportMemoryAllocateInfoKHR)
 
 #endif
-#ifdef VK_KHR_external_memory_win32
-#endif
-#ifdef VK_KHR_external_memory_fd
-#endif
 #ifdef VK_KHR_external_semaphore_capabilities
 DEFINE_ALIAS_FUNCTION(reservedmarshal_VkPhysicalDeviceExternalSemaphoreInfo,
                       reservedmarshal_VkPhysicalDeviceExternalSemaphoreInfoKHR)
@@ -1279,8 +1263,6 @@
                       reservedmarshal_VkExportSemaphoreCreateInfoKHR)
 
 #endif
-#ifdef VK_KHR_external_semaphore_win32
-#endif
 #ifdef VK_KHR_external_semaphore_fd
 void reservedmarshal_VkImportSemaphoreFdInfoKHR(VulkanStreamGuest* vkStream,
                                                 VkStructureType rootType,
@@ -1400,8 +1382,6 @@
                       reservedmarshal_VkMemoryDedicatedAllocateInfoKHR)
 
 #endif
-#ifdef VK_KHR_storage_buffer_storage_class
-#endif
 #ifdef VK_KHR_get_memory_requirements2
 DEFINE_ALIAS_FUNCTION(reservedmarshal_VkBufferMemoryRequirementsInfo2,
                       reservedmarshal_VkBufferMemoryRequirementsInfo2KHR)
@@ -1530,8 +1510,6 @@
                       reservedmarshal_VkPhysicalDeviceShaderIntegerDotProductPropertiesKHR)
 
 #endif
-#ifdef VK_KHR_shader_non_semantic_info
-#endif
 #ifdef VK_KHR_synchronization2
 DEFINE_ALIAS_FUNCTION(reservedmarshal_VkMemoryBarrier2, reservedmarshal_VkMemoryBarrier2KHR)
 
@@ -1664,8 +1642,6 @@
     const VkPhysicalDevicePresentationPropertiesANDROID* forMarshaling, uint8_t** ptr);
 
 #endif
-#ifdef VK_EXT_debug_report
-#endif
 #ifdef VK_EXT_transform_feedback
 void reservedmarshal_VkPhysicalDeviceTransformFeedbackFeaturesEXT(
     VulkanStreamGuest* vkStream, VkStructureType rootType,
@@ -1680,8 +1656,6 @@
     const VkPipelineRasterizationStateStreamCreateInfoEXT* forMarshaling, uint8_t** ptr);
 
 #endif
-#ifdef VK_AMD_gpu_shader_half_float
-#endif
 #ifdef VK_EXT_texture_compression_astc_hdr
 DEFINE_ALIAS_FUNCTION(reservedmarshal_VkPhysicalDeviceTextureCompressionASTCHDRFeatures,
                       reservedmarshal_VkPhysicalDeviceTextureCompressionASTCHDRFeaturesEXT)
@@ -1697,14 +1671,6 @@
     const VkPipelineRasterizationDepthClipStateCreateInfoEXT* forMarshaling, uint8_t** ptr);
 
 #endif
-#ifdef VK_EXT_swapchain_colorspace
-#endif
-#ifdef VK_EXT_queue_family_foreign
-#endif
-#ifdef VK_EXT_debug_utils
-#endif
-#ifdef VK_ANDROID_external_memory_android_hardware_buffer
-#endif
 #ifdef VK_EXT_inline_uniform_block
 DEFINE_ALIAS_FUNCTION(reservedmarshal_VkPhysicalDeviceInlineUniformBlockFeatures,
                       reservedmarshal_VkPhysicalDeviceInlineUniformBlockFeaturesEXT)
@@ -1719,8 +1685,6 @@
                       reservedmarshal_VkDescriptorPoolInlineUniformBlockCreateInfoEXT)
 
 #endif
-#ifdef VK_EXT_shader_stencil_export
-#endif
 #ifdef VK_EXT_vertex_attribute_divisor
 void reservedmarshal_VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT(
     VulkanStreamGuest* vkStream, VkStructureType rootType,
@@ -1747,10 +1711,6 @@
                       reservedmarshal_VkPipelineCreationFeedbackEXT)
 
 #endif
-#ifdef VK_NV_shader_subgroup_partitioned
-#endif
-#ifdef VK_EXT_metal_surface
-#endif
 #ifdef VK_EXT_fragment_density_map
 void reservedmarshal_VkPhysicalDeviceFragmentDensityMapFeaturesEXT(
     VulkanStreamGuest* vkStream, VkStructureType rootType,
@@ -1786,8 +1746,6 @@
                       reservedmarshal_VkPhysicalDeviceToolPropertiesEXT)
 
 #endif
-#ifdef VK_EXT_validation_features
-#endif
 #ifdef VK_EXT_provoking_vertex
 void reservedmarshal_VkPhysicalDeviceProvokingVertexFeaturesEXT(
     VulkanStreamGuest* vkStream, VkStructureType rootType,
@@ -1879,8 +1837,6 @@
                       reservedmarshal_VkImageSubresource2EXT)
 
 #endif
-#ifdef VK_EXT_swapchain_maintenance1
-#endif
 #ifdef VK_EXT_shader_demote_to_helper_invocation
 DEFINE_ALIAS_FUNCTION(reservedmarshal_VkPhysicalDeviceShaderDemoteToHelperInvocationFeatures,
                       reservedmarshal_VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT)
@@ -1949,8 +1905,6 @@
                       reservedmarshal_VkPhysicalDevicePipelineCreationCacheControlFeaturesEXT)
 
 #endif
-#ifdef VK_EXT_metal_objects
-#endif
 #ifdef VK_EXT_graphics_pipeline_library
 void reservedmarshal_VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT(
     VulkanStreamGuest* vkStream, VkStructureType rootType,
@@ -2032,8 +1986,6 @@
                                         const VkCreateBlobGOOGLE* forMarshaling, uint8_t** ptr);
 
 #endif
-#ifdef VK_EXT_load_store_op_none
-#endif
 #ifdef VK_EXT_image_compression_control_swapchain
 void reservedmarshal_VkPhysicalDeviceImageCompressionControlSwapchainFeaturesEXT(
     VulkanStreamGuest* vkStream, VkStructureType rootType,
@@ -2041,8 +1993,5 @@
     uint8_t** ptr);
 
 #endif
-#ifdef VK_QNX_external_memory_screen_buffer
-#endif
-
 }  // namespace vk
 }  // namespace gfxstream
diff --git a/guest/vulkan_enc/goldfish_vk_transform_guest.cpp b/guest/vulkan_enc/goldfish_vk_transform_guest.cpp
index 9ff5199..7ef53d1 100644
--- a/guest/vulkan_enc/goldfish_vk_transform_guest.cpp
+++ b/guest/vulkan_enc/goldfish_vk_transform_guest.cpp
@@ -6086,16 +6086,6 @@
 }
 
 #endif
-#ifdef VK_KHR_surface
-#endif
-#ifdef VK_KHR_swapchain
-#endif
-#ifdef VK_KHR_xcb_surface
-#endif
-#ifdef VK_KHR_android_surface
-#endif
-#ifdef VK_KHR_win32_surface
-#endif
 #ifdef VK_KHR_dynamic_rendering
 void transform_tohost_VkRenderingFragmentShadingRateAttachmentInfoKHR(
     ResourceTracker* resourceTracker,
@@ -6176,24 +6166,6 @@
 }
 
 #endif
-#ifdef VK_KHR_get_physical_device_properties2
-#endif
-#ifdef VK_KHR_maintenance1
-#endif
-#ifdef VK_KHR_external_memory_capabilities
-#endif
-#ifdef VK_KHR_external_memory
-#endif
-#ifdef VK_KHR_external_memory_win32
-#endif
-#ifdef VK_KHR_external_memory_fd
-#endif
-#ifdef VK_KHR_external_semaphore_capabilities
-#endif
-#ifdef VK_KHR_external_semaphore
-#endif
-#ifdef VK_KHR_external_semaphore_win32
-#endif
 #ifdef VK_KHR_external_semaphore_fd
 void transform_tohost_VkImportSemaphoreFdInfoKHR(ResourceTracker* resourceTracker,
                                                  VkImportSemaphoreFdInfoKHR* toTransform) {
@@ -6232,8 +6204,6 @@
 }
 
 #endif
-#ifdef VK_KHR_shader_float16_int8
-#endif
 #ifdef VK_KHR_incremental_present
 void transform_tohost_VkRectLayerKHR(ResourceTracker* resourceTracker,
                                      VkRectLayerKHR* toTransform) {
@@ -6314,16 +6284,6 @@
 }
 
 #endif
-#ifdef VK_KHR_descriptor_update_template
-#endif
-#ifdef VK_KHR_imageless_framebuffer
-#endif
-#ifdef VK_KHR_create_renderpass2
-#endif
-#ifdef VK_KHR_external_fence_capabilities
-#endif
-#ifdef VK_KHR_external_fence
-#endif
 #ifdef VK_KHR_external_fence_fd
 void transform_tohost_VkImportFenceFdInfoKHR(ResourceTracker* resourceTracker,
                                              VkImportFenceFdInfoKHR* toTransform) {
@@ -6362,30 +6322,6 @@
 }
 
 #endif
-#ifdef VK_KHR_maintenance2
-#endif
-#ifdef VK_KHR_dedicated_allocation
-#endif
-#ifdef VK_KHR_storage_buffer_storage_class
-#endif
-#ifdef VK_KHR_get_memory_requirements2
-#endif
-#ifdef VK_KHR_image_format_list
-#endif
-#ifdef VK_KHR_sampler_ycbcr_conversion
-#endif
-#ifdef VK_KHR_bind_memory2
-#endif
-#ifdef VK_KHR_maintenance3
-#endif
-#ifdef VK_KHR_shader_subgroup_extended_types
-#endif
-#ifdef VK_KHR_vulkan_memory_model
-#endif
-#ifdef VK_KHR_shader_terminate_invocation
-#endif
-#ifdef VK_KHR_buffer_device_address
-#endif
 #ifdef VK_KHR_pipeline_executable_properties
 void transform_tohost_VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR(
     ResourceTracker* resourceTracker,
@@ -6514,10 +6450,6 @@
 }
 
 #endif
-#ifdef VK_KHR_shader_integer_dot_product
-#endif
-#ifdef VK_KHR_shader_non_semantic_info
-#endif
 #ifdef VK_KHR_synchronization2
 void transform_tohost_VkQueueFamilyCheckpointProperties2NV(
     ResourceTracker* resourceTracker, VkQueueFamilyCheckpointProperties2NV* toTransform) {
@@ -6556,14 +6488,6 @@
 }
 
 #endif
-#ifdef VK_KHR_zero_initialize_workgroup_memory
-#endif
-#ifdef VK_KHR_copy_commands2
-#endif
-#ifdef VK_KHR_format_feature_flags2
-#endif
-#ifdef VK_KHR_maintenance4
-#endif
 #ifdef VK_KHR_maintenance5
 void transform_tohost_VkPhysicalDeviceMaintenance5FeaturesKHR(
     ResourceTracker* resourceTracker, VkPhysicalDeviceMaintenance5FeaturesKHR* toTransform) {
@@ -6808,8 +6732,6 @@
 }
 
 #endif
-#ifdef VK_EXT_debug_report
-#endif
 #ifdef VK_EXT_transform_feedback
 void transform_tohost_VkPhysicalDeviceTransformFeedbackFeaturesEXT(
     ResourceTracker* resourceTracker, VkPhysicalDeviceTransformFeedbackFeaturesEXT* toTransform) {
@@ -6868,10 +6790,6 @@
 }
 
 #endif
-#ifdef VK_AMD_gpu_shader_half_float
-#endif
-#ifdef VK_EXT_texture_compression_astc_hdr
-#endif
 #ifdef VK_EXT_depth_clip_enable
 void transform_tohost_VkPhysicalDeviceDepthClipEnableFeaturesEXT(
     ResourceTracker* resourceTracker, VkPhysicalDeviceDepthClipEnableFeaturesEXT* toTransform) {
@@ -6912,18 +6830,6 @@
 }
 
 #endif
-#ifdef VK_EXT_swapchain_colorspace
-#endif
-#ifdef VK_EXT_queue_family_foreign
-#endif
-#ifdef VK_EXT_debug_utils
-#endif
-#ifdef VK_ANDROID_external_memory_android_hardware_buffer
-#endif
-#ifdef VK_EXT_inline_uniform_block
-#endif
-#ifdef VK_EXT_shader_stencil_export
-#endif
 #ifdef VK_EXT_vertex_attribute_divisor
 void transform_tohost_VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT(
     ResourceTracker* resourceTracker,
@@ -7018,12 +6924,6 @@
 }
 
 #endif
-#ifdef VK_EXT_pipeline_creation_feedback
-#endif
-#ifdef VK_NV_shader_subgroup_partitioned
-#endif
-#ifdef VK_EXT_metal_surface
-#endif
 #ifdef VK_EXT_fragment_density_map
 void transform_tohost_VkPhysicalDeviceFragmentDensityMapFeaturesEXT(
     ResourceTracker* resourceTracker, VkPhysicalDeviceFragmentDensityMapFeaturesEXT* toTransform) {
@@ -7094,14 +6994,6 @@
 }
 
 #endif
-#ifdef VK_EXT_scalar_block_layout
-#endif
-#ifdef VK_EXT_subgroup_size_control
-#endif
-#ifdef VK_EXT_tooling_info
-#endif
-#ifdef VK_EXT_validation_features
-#endif
 #ifdef VK_EXT_provoking_vertex
 void transform_tohost_VkPhysicalDeviceProvokingVertexFeaturesEXT(
     ResourceTracker* resourceTracker, VkPhysicalDeviceProvokingVertexFeaturesEXT* toTransform) {
@@ -7508,10 +7400,6 @@
 }
 
 #endif
-#ifdef VK_EXT_swapchain_maintenance1
-#endif
-#ifdef VK_EXT_shader_demote_to_helper_invocation
-#endif
 #ifdef VK_EXT_texel_buffer_alignment
 void transform_tohost_VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT(
     ResourceTracker* resourceTracker,
@@ -7688,12 +7576,6 @@
 }
 
 #endif
-#ifdef VK_EXT_private_data
-#endif
-#ifdef VK_EXT_pipeline_creation_cache_control
-#endif
-#ifdef VK_EXT_metal_objects
-#endif
 #ifdef VK_EXT_graphics_pipeline_library
 void transform_tohost_VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT(
     ResourceTracker* resourceTracker,
@@ -7776,8 +7658,6 @@
 }
 
 #endif
-#ifdef VK_EXT_image_robustness
-#endif
 #ifdef VK_EXT_image_compression_control
 void transform_tohost_VkPhysicalDeviceImageCompressionControlFeaturesEXT(
     ResourceTracker* resourceTracker,
@@ -7994,8 +7874,6 @@
 }
 
 #endif
-#ifdef VK_EXT_load_store_op_none
-#endif
 #ifdef VK_EXT_image_compression_control_swapchain
 void transform_tohost_VkPhysicalDeviceImageCompressionControlSwapchainFeaturesEXT(
     ResourceTracker* resourceTracker,
@@ -8018,8 +7896,6 @@
 }
 
 #endif
-#ifdef VK_QNX_external_memory_screen_buffer
-#endif
 void transform_tohost_extension_struct(ResourceTracker* resourceTracker,
                                        void* structExtension_out) {
     if (!structExtension_out) {
diff --git a/guest/vulkan_enc/goldfish_vk_transform_guest.h b/guest/vulkan_enc/goldfish_vk_transform_guest.h
index ce60f0d..0616180 100644
--- a/guest/vulkan_enc/goldfish_vk_transform_guest.h
+++ b/guest/vulkan_enc/goldfish_vk_transform_guest.h
@@ -1759,16 +1759,6 @@
     ResourceTracker* resourceTracker, VkDeviceImageMemoryRequirements* toTransform);
 
 #endif
-#ifdef VK_KHR_surface
-#endif
-#ifdef VK_KHR_swapchain
-#endif
-#ifdef VK_KHR_xcb_surface
-#endif
-#ifdef VK_KHR_android_surface
-#endif
-#ifdef VK_KHR_win32_surface
-#endif
 #ifdef VK_KHR_dynamic_rendering
 DEFINE_ALIAS_FUNCTION(transform_tohost_VkRenderingInfo, transform_tohost_VkRenderingInfoKHR)
 
@@ -1884,8 +1874,6 @@
                       transform_fromhost_VkPhysicalDeviceSparseImageFormatInfo2KHR)
 
 #endif
-#ifdef VK_KHR_maintenance1
-#endif
 #ifdef VK_KHR_external_memory_capabilities
 DEFINE_ALIAS_FUNCTION(transform_tohost_VkExternalMemoryProperties,
                       transform_tohost_VkExternalMemoryPropertiesKHR)
@@ -1944,10 +1932,6 @@
                       transform_fromhost_VkExportMemoryAllocateInfoKHR)
 
 #endif
-#ifdef VK_KHR_external_memory_win32
-#endif
-#ifdef VK_KHR_external_memory_fd
-#endif
 #ifdef VK_KHR_external_semaphore_capabilities
 DEFINE_ALIAS_FUNCTION(transform_tohost_VkPhysicalDeviceExternalSemaphoreInfo,
                       transform_tohost_VkPhysicalDeviceExternalSemaphoreInfoKHR)
@@ -1970,8 +1954,6 @@
                       transform_fromhost_VkExportSemaphoreCreateInfoKHR)
 
 #endif
-#ifdef VK_KHR_external_semaphore_win32
-#endif
 #ifdef VK_KHR_external_semaphore_fd
 void transform_tohost_VkImportSemaphoreFdInfoKHR(ResourceTracker* resourceTracker,
                                                  VkImportSemaphoreFdInfoKHR* toTransform);
@@ -2182,8 +2164,6 @@
                       transform_fromhost_VkMemoryDedicatedAllocateInfoKHR)
 
 #endif
-#ifdef VK_KHR_storage_buffer_storage_class
-#endif
 #ifdef VK_KHR_get_memory_requirements2
 DEFINE_ALIAS_FUNCTION(transform_tohost_VkBufferMemoryRequirementsInfo2,
                       transform_tohost_VkBufferMemoryRequirementsInfo2KHR)
@@ -2406,8 +2386,6 @@
                       transform_fromhost_VkPhysicalDeviceShaderIntegerDotProductPropertiesKHR)
 
 #endif
-#ifdef VK_KHR_shader_non_semantic_info
-#endif
 #ifdef VK_KHR_synchronization2
 DEFINE_ALIAS_FUNCTION(transform_tohost_VkMemoryBarrier2, transform_tohost_VkMemoryBarrier2KHR)
 
@@ -2633,8 +2611,6 @@
     ResourceTracker* resourceTracker, VkPhysicalDevicePresentationPropertiesANDROID* toTransform);
 
 #endif
-#ifdef VK_EXT_debug_report
-#endif
 #ifdef VK_EXT_transform_feedback
 void transform_tohost_VkPhysicalDeviceTransformFeedbackFeaturesEXT(
     ResourceTracker* resourceTracker, VkPhysicalDeviceTransformFeedbackFeaturesEXT* toTransform);
@@ -2655,8 +2631,6 @@
     ResourceTracker* resourceTracker, VkPipelineRasterizationStateStreamCreateInfoEXT* toTransform);
 
 #endif
-#ifdef VK_AMD_gpu_shader_half_float
-#endif
 #ifdef VK_EXT_texture_compression_astc_hdr
 DEFINE_ALIAS_FUNCTION(transform_tohost_VkPhysicalDeviceTextureCompressionASTCHDRFeatures,
                       transform_tohost_VkPhysicalDeviceTextureCompressionASTCHDRFeaturesEXT)
@@ -2681,14 +2655,6 @@
     VkPipelineRasterizationDepthClipStateCreateInfoEXT* toTransform);
 
 #endif
-#ifdef VK_EXT_swapchain_colorspace
-#endif
-#ifdef VK_EXT_queue_family_foreign
-#endif
-#ifdef VK_EXT_debug_utils
-#endif
-#ifdef VK_ANDROID_external_memory_android_hardware_buffer
-#endif
 #ifdef VK_EXT_inline_uniform_block
 DEFINE_ALIAS_FUNCTION(transform_tohost_VkPhysicalDeviceInlineUniformBlockFeatures,
                       transform_tohost_VkPhysicalDeviceInlineUniformBlockFeaturesEXT)
@@ -2715,8 +2681,6 @@
                       transform_fromhost_VkDescriptorPoolInlineUniformBlockCreateInfoEXT)
 
 #endif
-#ifdef VK_EXT_shader_stencil_export
-#endif
 #ifdef VK_EXT_vertex_attribute_divisor
 void transform_tohost_VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT(
     ResourceTracker* resourceTracker,
@@ -2761,10 +2725,6 @@
                       transform_fromhost_VkPipelineCreationFeedbackEXT)
 
 #endif
-#ifdef VK_NV_shader_subgroup_partitioned
-#endif
-#ifdef VK_EXT_metal_surface
-#endif
 #ifdef VK_EXT_fragment_density_map
 void transform_tohost_VkPhysicalDeviceFragmentDensityMapFeaturesEXT(
     ResourceTracker* resourceTracker, VkPhysicalDeviceFragmentDensityMapFeaturesEXT* toTransform);
@@ -2821,8 +2781,6 @@
                       transform_fromhost_VkPhysicalDeviceToolPropertiesEXT)
 
 #endif
-#ifdef VK_EXT_validation_features
-#endif
 #ifdef VK_EXT_provoking_vertex
 void transform_tohost_VkPhysicalDeviceProvokingVertexFeaturesEXT(
     ResourceTracker* resourceTracker, VkPhysicalDeviceProvokingVertexFeaturesEXT* toTransform);
@@ -2955,8 +2913,6 @@
                       transform_fromhost_VkImageSubresource2EXT)
 
 #endif
-#ifdef VK_EXT_swapchain_maintenance1
-#endif
 #ifdef VK_EXT_shader_demote_to_helper_invocation
 DEFINE_ALIAS_FUNCTION(transform_tohost_VkPhysicalDeviceShaderDemoteToHelperInvocationFeatures,
                       transform_tohost_VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT)
@@ -3061,8 +3017,6 @@
                       transform_fromhost_VkPhysicalDevicePipelineCreationCacheControlFeaturesEXT)
 
 #endif
-#ifdef VK_EXT_metal_objects
-#endif
 #ifdef VK_EXT_graphics_pipeline_library
 void transform_tohost_VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT(
     ResourceTracker* resourceTracker,
@@ -3189,8 +3143,6 @@
                                            VkCreateBlobGOOGLE* toTransform);
 
 #endif
-#ifdef VK_EXT_load_store_op_none
-#endif
 #ifdef VK_EXT_image_compression_control_swapchain
 void transform_tohost_VkPhysicalDeviceImageCompressionControlSwapchainFeaturesEXT(
     ResourceTracker* resourceTracker,
@@ -3201,8 +3153,5 @@
     VkPhysicalDeviceImageCompressionControlSwapchainFeaturesEXT* toTransform);
 
 #endif
-#ifdef VK_QNX_external_memory_screen_buffer
-#endif
-
 }  // namespace vk
 }  // namespace gfxstream
diff --git a/guest/vulkan_enc/vkQueueFlushCommandsGOOGLE_encode_impl.cpp.inl b/guest/vulkan_enc/vkQueueFlushCommandsGOOGLE_encode_impl.cpp.inl
index 3b4cf32..8e27e9c 100644
--- a/guest/vulkan_enc/vkQueueFlushCommandsGOOGLE_encode_impl.cpp.inl
+++ b/guest/vulkan_enc/vkQueueFlushCommandsGOOGLE_encode_impl.cpp.inl
@@ -55,7 +55,7 @@
     memcpy(&healthMonitorAnnotation_packetContents[0], packetBeginPtr, watchdogBufSize);
 }
 
-AEMU_SCOPED_TRACE("vkQueueFlush large xfer");
+MESA_TRACE_SCOPE("vkQueueFlush large xfer");
 stream->flush();
 stream->writeLarge(local_pData, dataSize);
 
diff --git a/guest/vulkan_enc/vk_struct_id.h b/guest/vulkan_enc/vk_struct_id.h
index 5d43282..e7a6e60 100644
--- a/guest/vulkan_enc/vk_struct_id.h
+++ b/guest/vulkan_enc/vk_struct_id.h
@@ -129,6 +129,9 @@
 REGISTER_VK_STRUCT_ID(VkPhysicalDeviceGroupProperties,
                       VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES);
 REGISTER_VK_STRUCT_ID(VkPhysicalDeviceSwapchainMaintenance1FeaturesEXT, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SWAPCHAIN_MAINTENANCE_1_FEATURES_EXT);
+REGISTER_VK_STRUCT_ID(VkSubmitInfo, VK_STRUCTURE_TYPE_SUBMIT_INFO);
+REGISTER_VK_STRUCT_ID(VkTimelineSemaphoreSubmitInfo,
+                      VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO);
 #if defined(LINUX_GUEST_BUILD)
 REGISTER_VK_STRUCT_ID(wsi_image_create_info, VK_STRUCTURE_TYPE_WSI_IMAGE_CREATE_INFO_MESA);
 #endif
diff --git a/guest/vulkan_enc/vk_util.h b/guest/vulkan_enc/vk_util.h
index 61ce359..4639064 100644
--- a/guest/vulkan_enc/vk_util.h
+++ b/guest/vulkan_enc/vk_util.h
@@ -204,10 +204,6 @@
                                                   vk_get_vk_struct_id<T>::id));
 }
 
-uint32_t vk_get_driver_version(void);
-
-uint32_t vk_get_version_override(void);
-
 #define VK_EXT_OFFSET (1000000000UL)
 #define VK_ENUM_EXTENSION(__enum) \
     ((__enum) >= VK_EXT_OFFSET ? ((((__enum)-VK_EXT_OFFSET) / 1000UL) + 1) : 0)
@@ -242,18 +238,6 @@
     *i = vk_make_chain_iterator(vk_struct);
 }
 
-bool vk_descriptor_type_has_image_view(VkDescriptorType type) {
-    switch (type) {
-        case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
-        case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
-        case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
-        case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
-            return true;
-        default:
-            return false;
-    }
-}
-
 bool vk_descriptor_type_has_descriptor_buffer(VkDescriptorType type) {
     switch (type) {
         case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
@@ -266,16 +250,6 @@
     }
 }
 
-bool vk_descriptor_type_has_texel_buffer(VkDescriptorType type) {
-    switch (type) {
-        case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
-        case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
-            return true;
-        default:
-            return false;
-    }
-}
-
 }  // namespace
 
 #endif /* VK_UTIL_H */
diff --git a/guest/vulkan_enc/vulkan_gfxstream.h b/guest/vulkan_enc/vulkan_gfxstream.h
index a2c288c..a7ac22b 100644
--- a/guest/vulkan_enc/vulkan_gfxstream.h
+++ b/guest/vulkan_enc/vulkan_gfxstream.h
@@ -69,6 +69,7 @@
 typedef VkResult (VKAPI_PTR *PFN_vkGetBlobGOOGLE)(VkDevice device, VkDeviceMemory memory);
 typedef void (VKAPI_PTR *PFN_vkUpdateDescriptorSetWithTemplateSized2GOOGLE)(VkDevice device, VkDescriptorSet descriptorSet, VkDescriptorUpdateTemplate descriptorUpdateTemplate, uint32_t imageInfoCount, uint32_t bufferInfoCount, uint32_t bufferViewCount, uint32_t inlineUniformBlockCount, const uint32_t* pImageInfoEntryIndices, const uint32_t* pBufferInfoEntryIndices, const uint32_t* pBufferViewEntryIndices, const VkDescriptorImageInfo* pImageInfos, const VkDescriptorBufferInfo* pBufferInfos, const VkBufferView* pBufferViews, const uint8_t* pInlineUniformBlockData);
 typedef void (VKAPI_PTR *PFN_vkQueueSubmitAsync2GOOGLE)(VkQueue queue, uint32_t submitCount, const VkSubmitInfo2* pSubmits, VkFence fence);
+typedef VkResult (VKAPI_PTR *PFN_vkGetSemaphoreGOOGLE)(VkDevice device, VkSemaphore semaphore, uint64_t syncId);
 
 #ifndef VK_NO_PROTOTYPES
 VKAPI_ATTR VkResult VKAPI_CALL vkMapMemoryIntoAddressSpaceGOOGLE(
@@ -227,6 +228,11 @@
     uint32_t                                    submitCount,
     const VkSubmitInfo2*                        pSubmits,
     VkFence                                     fence);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetSemaphoreGOOGLE(
+    VkDevice                                    device,
+    VkSemaphore                                 semaphore,
+    uint64_t                                    syncId);
 #endif
 
 #ifdef __cplusplus
diff --git a/host/Android.bp b/host/Android.bp
index 6c7f6fb..3ab8b29 100644
--- a/host/Android.bp
+++ b/host/Android.bp
@@ -86,7 +86,7 @@
     ],
     srcs: [
         "Buffer.cpp",
-        "BlobManager.cpp",
+        "ExternalObjectManager.cpp",
         "ChannelStream.cpp",
         "ColorBuffer.cpp",
         "DisplaySurface.cpp",
diff --git a/host/BUILD.bazel b/host/BUILD.bazel
index 242b3e4..df5dde8 100644
--- a/host/BUILD.bazel
+++ b/host/BUILD.bazel
@@ -67,12 +67,12 @@
 cc_library(
     name = "gfxstream_backend_static",
     srcs = [
-        "BlobManager.cpp",
         "Buffer.cpp",
         "ChannelStream.cpp",
         "ColorBuffer.cpp",
         "DisplaySurface.cpp",
         "DisplaySurfaceUser.cpp",
+        "ExternalObjectManager.cpp",
         "FrameBuffer.cpp",
         "GfxStreamAgents.cpp",
         "Hwc2.cpp",
diff --git a/host/BlobManager.cpp b/host/BlobManager.cpp
deleted file mode 100644
index 938f275..0000000
--- a/host/BlobManager.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright 2019 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-#include "BlobManager.h"
-
-#include <utility>
-
-using android::base::ManagedDescriptor;
-
-namespace gfxstream {
-
-static BlobManager* sMapping() {
-    static BlobManager* s = new BlobManager;
-    return s;
-}
-
-// static
-BlobManager* BlobManager::get() { return sMapping(); }
-
-void BlobManager::addMapping(uint32_t ctxId, uint64_t blobId, void* addr, uint32_t caching) {
-    struct HostMemInfo info = {
-        .addr = addr,
-        .caching = caching,
-    };
-
-    auto key = std::make_pair(ctxId, blobId);
-    std::lock_guard<std::mutex> lock(mLock);
-    mHostMemInfos.insert(std::make_pair(key, info));
-}
-
-std::optional<HostMemInfo> BlobManager::removeMapping(uint32_t ctxId, uint64_t blobId) {
-    auto key = std::make_pair(ctxId, blobId);
-    std::lock_guard<std::mutex> lock(mLock);
-    auto found = mHostMemInfos.find(key);
-    if (found != mHostMemInfos.end()) {
-        std::optional<HostMemInfo> ret = found->second;
-        mHostMemInfos.erase(found);
-        return ret;
-    }
-
-    return std::nullopt;
-}
-
-void BlobManager::addDescriptorInfo(uint32_t ctxId, uint64_t blobId, ManagedDescriptor descriptor,
-                                    uint32_t handleType, uint32_t caching,
-                                    std::optional<VulkanInfo> vulkanInfoOpt) {
-    struct ManagedDescriptorInfo info = {
-        .descriptor = std::move(descriptor),
-        .handleType = handleType,
-        .caching = caching,
-        .vulkanInfoOpt = vulkanInfoOpt,
-    };
-
-    auto key = std::make_pair(ctxId, blobId);
-    std::lock_guard<std::mutex> lock(mLock);
-    mDescriptorInfos.insert(std::make_pair(key, std::move(info)));
-}
-
-std::optional<ManagedDescriptorInfo> BlobManager::removeDescriptorInfo(uint32_t ctxId,
-                                                                       uint64_t blobId) {
-    auto key = std::make_pair(ctxId, blobId);
-    std::lock_guard<std::mutex> lock(mLock);
-    auto found = mDescriptorInfos.find(key);
-    if (found != mDescriptorInfos.end()) {
-        std::optional<ManagedDescriptorInfo> ret = std::move(found->second);
-        mDescriptorInfos.erase(found);
-        return ret;
-    }
-
-    return std::nullopt;
-}
-
-}  // namespace gfxstream
diff --git a/host/Buffer.cpp b/host/Buffer.cpp
index 84459db..b37c729 100644
--- a/host/Buffer.cpp
+++ b/host/Buffer.cpp
@@ -138,7 +138,7 @@
     return false;
 }
 
-std::optional<ManagedDescriptorInfo> Buffer::exportBlob() {
+std::optional<BlobDescriptorInfo> Buffer::exportBlob() {
     if (!mBufferVk) {
         return std::nullopt;
     }
diff --git a/host/Buffer.h b/host/Buffer.h
index cf2b15e..8944768 100644
--- a/host/Buffer.h
+++ b/host/Buffer.h
@@ -16,7 +16,7 @@
 
 #include <memory>
 
-#include "BlobManager.h"
+#include "ExternalObjectManager.h"
 #include "Handle.h"
 #include "aemu/base/files/Stream.h"
 #include "snapshot/LazySnapshotObj.h"
@@ -58,7 +58,7 @@
 
     void readToBytes(uint64_t offset, uint64_t size, void* outBytes);
     bool updateFromBytes(uint64_t offset, uint64_t size, const void* bytes);
-    std::optional<ManagedDescriptorInfo> exportBlob();
+    std::optional<BlobDescriptorInfo> exportBlob();
 
    private:
     Buffer(HandleType handle, uint64_t size);
diff --git a/host/CMakeLists.txt b/host/CMakeLists.txt
index ffbaf7b..327d15c 100644
--- a/host/CMakeLists.txt
+++ b/host/CMakeLists.txt
@@ -24,7 +24,7 @@
 # Stream server core
 set(stream-server-core-sources
     Buffer.cpp
-    BlobManager.cpp
+    ExternalObjectManager.cpp
     ColorBuffer.cpp
     GfxStreamAgents.cpp
     VirtioGpuTimelines.cpp
diff --git a/host/ColorBuffer.cpp b/host/ColorBuffer.cpp
index 159f8e2..92414e7 100644
--- a/host/ColorBuffer.cpp
+++ b/host/ColorBuffer.cpp
@@ -455,7 +455,7 @@
     return mColorBufferVk->waitSync();
 }
 
-std::optional<ManagedDescriptorInfo> ColorBuffer::exportBlob() {
+std::optional<BlobDescriptorInfo> ColorBuffer::exportBlob() {
     if (!mColorBufferVk) {
         return std::nullopt;
     }
diff --git a/host/ColorBuffer.h b/host/ColorBuffer.h
index ba6a9ad..ab99dfa 100644
--- a/host/ColorBuffer.h
+++ b/host/ColorBuffer.h
@@ -16,8 +16,8 @@
 
 #include <memory>
 
-#include "BlobManager.h"
 #include "BorrowedImage.h"
+#include "ExternalObjectManager.h"
 #include "FrameworkFormats.h"
 #include "Handle.h"
 #include "Hwc2.h"
@@ -95,7 +95,7 @@
     bool importNativeResource(void* nativeResource, uint32_t type, bool preserveContent);
 
     int waitSync();
-    std::optional<ManagedDescriptorInfo> exportBlob();
+    std::optional<BlobDescriptorInfo> exportBlob();
 
 #if GFXSTREAM_ENABLE_HOST_GLES
     GLuint glOpGetTexture();
diff --git a/host/ExternalObjectManager.cpp b/host/ExternalObjectManager.cpp
new file mode 100644
index 0000000..94f858f
--- /dev/null
+++ b/host/ExternalObjectManager.cpp
@@ -0,0 +1,112 @@
+// Copyright 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#include "ExternalObjectManager.h"
+
+#include <utility>
+
+using android::base::ManagedDescriptor;
+
+namespace gfxstream {
+
+static ExternalObjectManager* sMapping() {
+    static ExternalObjectManager* s = new ExternalObjectManager;
+    return s;
+}
+
+// static
+ExternalObjectManager* ExternalObjectManager::get() { return sMapping(); }
+
+void ExternalObjectManager::addMapping(uint32_t ctxId, uint64_t blobId, void* addr,
+                                       uint32_t caching) {
+    struct HostMemInfo info = {
+        .addr = addr,
+        .caching = caching,
+    };
+
+    auto key = std::make_pair(ctxId, blobId);
+    std::lock_guard<std::mutex> lock(mLock);
+    mHostMemInfos.insert(std::make_pair(key, info));
+}
+
+std::optional<HostMemInfo> ExternalObjectManager::removeMapping(uint32_t ctxId, uint64_t blobId) {
+    auto key = std::make_pair(ctxId, blobId);
+    std::lock_guard<std::mutex> lock(mLock);
+    auto found = mHostMemInfos.find(key);
+    if (found != mHostMemInfos.end()) {
+        std::optional<HostMemInfo> ret = found->second;
+        mHostMemInfos.erase(found);
+        return ret;
+    }
+
+    return std::nullopt;
+}
+
+void ExternalObjectManager::addBlobDescriptorInfo(uint32_t ctxId, uint64_t blobId,
+                                                  ManagedDescriptor descriptor, uint32_t handleType,
+                                                  uint32_t caching,
+                                                  std::optional<VulkanInfo> vulkanInfoOpt) {
+    struct BlobDescriptorInfo info = {
+        .descriptor = std::move(descriptor),
+        .handleType = handleType,
+        .caching = caching,
+        .vulkanInfoOpt = vulkanInfoOpt,
+    };
+
+    auto key = std::make_pair(ctxId, blobId);
+    std::lock_guard<std::mutex> lock(mLock);
+    mBlobDescriptorInfos.insert(std::make_pair(key, std::move(info)));
+}
+
+std::optional<BlobDescriptorInfo> ExternalObjectManager::removeBlobDescriptorInfo(uint32_t ctxId,
+                                                                                  uint64_t blobId) {
+    auto key = std::make_pair(ctxId, blobId);
+    std::lock_guard<std::mutex> lock(mLock);
+    auto found = mBlobDescriptorInfos.find(key);
+    if (found != mBlobDescriptorInfos.end()) {
+        std::optional<BlobDescriptorInfo> ret = std::move(found->second);
+        mBlobDescriptorInfos.erase(found);
+        return ret;
+    }
+
+    return std::nullopt;
+}
+
+void ExternalObjectManager::addSyncDescriptorInfo(uint32_t ctxId, uint64_t syncId,
+                                                  ManagedDescriptor descriptor,
+                                                  uint32_t handleType) {
+    struct SyncDescriptorInfo info = {
+        .descriptor = std::move(descriptor),
+        .handleType = handleType,
+    };
+
+    auto key = std::make_pair(ctxId, syncId);
+    std::lock_guard<std::mutex> lock(mLock);
+    mSyncDescriptorInfos.insert(std::make_pair(key, std::move(info)));
+}
+
+std::optional<SyncDescriptorInfo> ExternalObjectManager::removeSyncDescriptorInfo(uint32_t ctxId,
+                                                                                  uint64_t syncId) {
+    auto key = std::make_pair(ctxId, syncId);
+    std::lock_guard<std::mutex> lock(mLock);
+    auto found = mSyncDescriptorInfos.find(key);
+    if (found != mSyncDescriptorInfos.end()) {
+        std::optional<SyncDescriptorInfo> ret = std::move(found->second);
+        mSyncDescriptorInfos.erase(found);
+        return ret;
+    }
+
+    return std::nullopt;
+}
+
+}  // namespace gfxstream
diff --git a/host/BlobManager.h b/host/ExternalObjectManager.h
similarity index 75%
rename from host/BlobManager.h
rename to host/ExternalObjectManager.h
index b23987c..4c901ad 100644
--- a/host/BlobManager.h
+++ b/host/ExternalObjectManager.h
@@ -68,26 +68,35 @@
     uint8_t driverUUID[16];
 };
 
-struct ManagedDescriptorInfo {
+struct BlobDescriptorInfo {
     ManagedDescriptor descriptor;
     uint32_t handleType;
     uint32_t caching;
     std::optional<VulkanInfo> vulkanInfoOpt;
 };
 
-class BlobManager {
-   public:
-    BlobManager() = default;
+struct SyncDescriptorInfo {
+    ManagedDescriptor descriptor;
+    uint32_t handleType;
+};
 
-    static BlobManager* get();
+class ExternalObjectManager {
+   public:
+    ExternalObjectManager() = default;
+
+    static ExternalObjectManager* get();
 
     void addMapping(uint32_t ctx_id, uint64_t blobId, void* addr, uint32_t caching);
     std::optional<HostMemInfo> removeMapping(uint32_t ctx_id, uint64_t blobId);
 
-    void addDescriptorInfo(uint32_t ctx_id, uint64_t blobId, ManagedDescriptor descriptor,
-                           uint32_t handleType, uint32_t caching,
-                           std::optional<VulkanInfo> vulkanInfoOpt);
-    std::optional<ManagedDescriptorInfo> removeDescriptorInfo(uint32_t ctx_id, uint64_t blobId);
+    void addBlobDescriptorInfo(uint32_t ctx_id, uint64_t blobId, ManagedDescriptor descriptor,
+                               uint32_t handleType, uint32_t caching,
+                               std::optional<VulkanInfo> vulkanInfoOpt);
+    std::optional<BlobDescriptorInfo> removeBlobDescriptorInfo(uint32_t ctx_id, uint64_t blobId);
+
+    void addSyncDescriptorInfo(uint32_t ctx_id, uint64_t syncId, ManagedDescriptor descriptor,
+                               uint32_t handleType);
+    std::optional<SyncDescriptorInfo> removeSyncDescriptorInfo(uint32_t ctx_id, uint64_t syncId);
 
    private:
     // Only for pairs of std::hash-able types for simplicity.
@@ -106,9 +115,11 @@
 
     std::mutex mLock;
     std::unordered_map<std::pair<uint32_t, uint64_t>, HostMemInfo, pair_hash> mHostMemInfos;
-    std::unordered_map<std::pair<uint32_t, uint64_t>, ManagedDescriptorInfo, pair_hash>
-        mDescriptorInfos;
-    DISALLOW_COPY_ASSIGN_AND_MOVE(BlobManager);
+    std::unordered_map<std::pair<uint32_t, uint64_t>, BlobDescriptorInfo, pair_hash>
+        mBlobDescriptorInfos;
+    std::unordered_map<std::pair<uint32_t, uint64_t>, SyncDescriptorInfo, pair_hash>
+        mSyncDescriptorInfos;
+    DISALLOW_COPY_ASSIGN_AND_MOVE(ExternalObjectManager);
 };
 
 }  // namespace gfxstream
diff --git a/host/FrameBuffer.cpp b/host/FrameBuffer.cpp
index cd02bab..daba974 100644
--- a/host/FrameBuffer.cpp
+++ b/host/FrameBuffer.cpp
@@ -2849,6 +2849,13 @@
     return colorBufferPtr->borrowForDisplay(api);
 }
 
+void FrameBuffer::logVulkanDeviceLost() {
+    if (!m_emulationVk) {
+        GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "Device lost without VkEmulation?";
+    }
+    vk::onVkDeviceLost();
+}
+
 void FrameBuffer::logVulkanOutOfMemory(VkResult result, const char* function, int line,
                                        std::optional<uint64_t> allocationSize) {
     m_logger->logMetricEvent(MetricEventVulkanOutOfMemory{
@@ -2980,7 +2987,7 @@
     return colorBuffer->waitSync();
 }
 
-std::optional<ManagedDescriptorInfo> FrameBuffer::exportColorBuffer(HandleType colorBufferHandle) {
+std::optional<BlobDescriptorInfo> FrameBuffer::exportColorBuffer(HandleType colorBufferHandle) {
     AutoLock mutex(m_lock);
 
     ColorBufferPtr colorBuffer = findColorBuffer(colorBufferHandle);
@@ -2991,7 +2998,7 @@
     return colorBuffer->exportBlob();
 }
 
-std::optional<ManagedDescriptorInfo> FrameBuffer::exportBuffer(HandleType bufferHandle) {
+std::optional<BlobDescriptorInfo> FrameBuffer::exportBuffer(HandleType bufferHandle) {
     AutoLock mutex(m_lock);
 
     BufferPtr buffer = findBuffer(bufferHandle);
diff --git a/host/FrameBuffer.h b/host/FrameBuffer.h
index 52104df..c00ee27 100644
--- a/host/FrameBuffer.h
+++ b/host/FrameBuffer.h
@@ -26,12 +26,12 @@
 #include <unordered_map>
 #include <unordered_set>
 
-#include "BlobManager.h"
 #include "Buffer.h"
 #include "ColorBuffer.h"
 #include "Compositor.h"
 #include "Display.h"
 #include "DisplaySurface.h"
+#include "ExternalObjectManager.h"
 #include "Hwc2.h"
 #include "PostCommands.h"
 #include "PostWorker.h"
@@ -482,6 +482,7 @@
         return *m_logger;
     }
 
+    void logVulkanDeviceLost();
     void logVulkanOutOfMemory(VkResult result, const char* function, int line,
                               std::optional<uint64_t> allocationSize = std::nullopt);
 
@@ -499,8 +500,8 @@
     bool invalidateColorBufferForVk(HandleType colorBufferHandle);
 
     int waitSyncColorBuffer(HandleType colorBufferHandle);
-    std::optional<ManagedDescriptorInfo> exportColorBuffer(HandleType colorBufferHandle);
-    std::optional<ManagedDescriptorInfo> exportBuffer(HandleType bufferHandle);
+    std::optional<BlobDescriptorInfo> exportColorBuffer(HandleType colorBufferHandle);
+    std::optional<BlobDescriptorInfo> exportBuffer(HandleType bufferHandle);
 
 #if GFXSTREAM_ENABLE_HOST_GLES
     // Retrieves the color buffer handle associated with |p_surface|.
diff --git a/host/features/include/gfxstream/host/Features.h b/host/features/include/gfxstream/host/Features.h
index c17fac4..38e034c 100644
--- a/host/features/include/gfxstream/host/Features.h
+++ b/host/features/include/gfxstream/host/Features.h
@@ -67,6 +67,12 @@
         "memory and will be exportable via file descriptors.",
         &map,
     };
+    FeatureInfo VulkanExternalSync = {
+        "VulkanExternalSync",
+        "If enabled, Vulkan fences/semaphores will be allocated with external "
+        "create info and will be exportable via fence handles.",
+        &map,
+    };
     FeatureInfo SystemBlob = {
         "SystemBlob",
         "If enabled, virtio gpu blob resources will be allocated with shmem and "
@@ -96,6 +102,31 @@
         "Default description: consider contributing a description if you see this!",
         &map,
     };
+    FeatureInfo GlProgramBinaryLinkStatus = {
+        "GlProgramBinaryLinkStatus",
+        "If enabled, the host will track and report the correct link status of programs "
+        "created with glProgramBinary(). If not enabled, the host will effectively "
+        "return false for all glGetProgramiv(... GL_LINK_STATUS ...) calls."
+        ""
+        "Prior to aosp/3151743, the host GLES translator was not tracking the link "
+        "status of programs created by glProgramBinary() and would always return "
+        "false for glGetProgramiv(... GL_LINK_STATUS ...) calls."
+        ""
+        "Also, prior to aosp/3151743, the guest GL encoder was losing information about "
+        "`samplerExternalOES` between glGetProgramBinary() and glProgramBinary() calls "
+        "which would cause incorrect handling of sampling from a binding with "
+        "GL_TEXTURE_EXTERNAL_OES."
+        ""
+        "Guest applications seem to typically fallback to fully recreating programs "
+        "with shaders (glCreateShader() + glShaderSource() + glAttachShader()) when "
+        "linking fails with glProgramBinary(). This lead to backwards compatibility "
+        "problems when an old guest (which does not have the above guest GL encoder "
+        "fix) runs with a newer host (which does have the above host GLES translator "
+        "fix) as the fallback path would be disabled but the guest would have "
+        "incorrect GL_TEXTURE_EXTERNAL_OES handling. As such, the corrected host "
+        "behavior is hidden behind this feature.",
+        &map,
+    };
     FeatureInfo GlPipeChecksum = {
         "GlPipeChecksum",
         "If enabled, the guest and host will use checksums to ensure consistency "
@@ -268,6 +299,13 @@
         "labels on Vulkan resources and operation",
         &map,
     };
+    FeatureInfo VulkanCommandBufferCheckpoints = {
+        "VulkanCommandBufferCheckpoints",
+        "If enabled, the host will enable the VK_NV_device_diagnostic_checkpoints extension "
+        "when available, track command buffers with markers, and report unfinished command "
+        "buffers on device lost. (TODO: VK_AMD_buffer_marker)",
+        &map,
+    };
 };
 
 #define GFXSTREAM_SET_FEATURE_ON_CONDITION(set, feature, condition) \
diff --git a/host/gl/EmulationGl.cpp b/host/gl/EmulationGl.cpp
index 51192b2..a07a500 100644
--- a/host/gl/EmulationGl.cpp
+++ b/host/gl/EmulationGl.cpp
@@ -251,6 +251,12 @@
             emulationGl->mFeatures.NativeTextureDecompression.enabled);
     }
 
+    if (s_egl.eglSetProgramBinaryLinkStatusEnabledANDROID) {
+        s_egl.eglSetProgramBinaryLinkStatusEnabledANDROID(
+            emulationGl->mEglDisplay,
+            emulationGl->mFeatures.GlProgramBinaryLinkStatus.enabled);
+    }
+
     s_egl.eglBindAPI(EGL_OPENGL_ES_API);
 
 #ifdef ENABLE_GL_LOG
diff --git a/host/gl/OpenGLESDispatch/render_egl_extensions.entries b/host/gl/OpenGLESDispatch/render_egl_extensions.entries
index d9d46d0..1725b2a 100644
--- a/host/gl/OpenGLESDispatch/render_egl_extensions.entries
+++ b/host/gl/OpenGLESDispatch/render_egl_extensions.entries
@@ -28,3 +28,4 @@
 EGLImage eglImportImageANDROID(EGLDisplay display, EGLImage image);
 EGLint eglDebugMessageControlKHR(EGLDEBUGPROCKHR callback, const EGLAttrib * attrib_list);
 EGLBoolean eglSetNativeTextureDecompressionEnabledANDROID(EGLDisplay display, EGLBoolean enabled);
+EGLBoolean eglSetProgramBinaryLinkStatusEnabledANDROID(EGLDisplay display, EGLboolean enabled);
diff --git a/host/gl/gl-host-common/opengl/NativeGpuInfo_windows.cpp b/host/gl/gl-host-common/opengl/NativeGpuInfo_windows.cpp
old mode 100755
new mode 100644
diff --git a/host/gl/glestranslator/EGL/EglDisplay.cpp b/host/gl/glestranslator/EGL/EglDisplay.cpp
index f601315..ecdb7ed 100644
--- a/host/gl/glestranslator/EGL/EglDisplay.cpp
+++ b/host/gl/glestranslator/EGL/EglDisplay.cpp
@@ -709,4 +709,12 @@
 
 void EglDisplay::setNativeTextureDecompressionEnabled(bool enabled) {
     m_nativeTextureDecompressionEnabled = enabled;
-}
\ No newline at end of file
+}
+
+bool EglDisplay::programBinaryLinkStatusEnabled() const {
+    return m_programBinaryLinkStatusEnabled;
+}
+
+void EglDisplay::setProgramBinaryLinkStatusEnabled(bool enabled) {
+    m_programBinaryLinkStatusEnabled = enabled;
+}
diff --git a/host/gl/glestranslator/EGL/EglDisplay.h b/host/gl/glestranslator/EGL/EglDisplay.h
index d26ec9a..cc2a96d 100644
--- a/host/gl/glestranslator/EGL/EglDisplay.h
+++ b/host/gl/glestranslator/EGL/EglDisplay.h
@@ -152,6 +152,9 @@
     bool nativeTextureDecompressionEnabled() const;
     void setNativeTextureDecompressionEnabled(bool enabled);
 
+    bool programBinaryLinkStatusEnabled() const;
+    void setProgramBinaryLinkStatusEnabled(bool enabled);
+
 private:
     static void addConfig(void* opaque, const EglOS::ConfigInfo* configInfo);
 
@@ -175,6 +178,7 @@
     mutable std::shared_ptr<EglOS::Context> m_globalSharedContext;
     ConfigSet               m_uniqueConfigs;
     bool                    m_nativeTextureDecompressionEnabled = false;
+    bool                    m_programBinaryLinkStatusEnabled = false;
 };
 
 #endif
diff --git a/host/gl/glestranslator/EGL/EglImp.cpp b/host/gl/glestranslator/EGL/EglImp.cpp
index 3095f47..e3891da 100644
--- a/host/gl/glestranslator/EGL/EglImp.cpp
+++ b/host/gl/glestranslator/EGL/EglImp.cpp
@@ -131,6 +131,7 @@
 EGLAPI EGLBoolean EGLAPIENTRY eglQueryVulkanInteropSupportANDROID(void);
 EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttribKHR(EGLDisplay display, EGLSyncKHR sync, EGLint attribute, EGLint *value);
 EGLAPI EGLBoolean EGLAPIENTRY eglSetNativeTextureDecompressionEnabledANDROID(EGLDisplay display, EGLBoolean enabled);
+EGLAPI EGLBoolean EGLAPIENTRY eglSetProgramBinaryLinkStatusEnabledANDROID(EGLDisplay display, EGLBoolean enabled);
 
 EGLAPI EGLBoolean EGLAPIENTRY eglSaveConfig(EGLDisplay display, EGLConfig config, EGLStreamKHR stream);
 EGLAPI EGLConfig EGLAPIENTRY eglLoadConfig(EGLDisplay display, EGLStreamKHR stream);
@@ -194,6 +195,8 @@
                 (__eglMustCastToProperFunctionPointerType)eglGetSyncAttribKHR },
         {"eglSetNativeTextureDecompressionEnabledANDROID",
                 (__eglMustCastToProperFunctionPointerType)eglSetNativeTextureDecompressionEnabledANDROID },
+        {"eglSetProgramBinaryLinkStatusEnabledANDROID",
+                (__eglMustCastToProperFunctionPointerType)eglSetProgramBinaryLinkStatusEnabledANDROID },
 };
 
 static const int s_eglExtensionsSize =
@@ -1180,7 +1183,8 @@
             thread->updateInfo(newCtx,dpy,newCtx->getGlesContext(),newCtx->getShareGroup(),dpy->getManager(newCtx->version()));
             newCtx->setSurfaces(newReadSrfc,newDrawSrfc);
             g_eglInfo->getIface(newCtx->version())->initContext(newCtx->getGlesContext(), newCtx->getShareGroup(),
-                                                                dpy->nativeTextureDecompressionEnabled());
+                                                                dpy->nativeTextureDecompressionEnabled(),
+                                                                dpy->programBinaryLinkStatusEnabled());
             g_eglInfo->sweepDestroySurfaces();
         }
 
@@ -1665,6 +1669,13 @@
     return EGL_TRUE;
 }
 
+EGLAPI EGLBoolean EGLAPIENTRY eglSetProgramBinaryLinkStatusEnabledANDROID(EGLDisplay display, EGLBoolean enabled) {
+    MEM_TRACE("EMUGL");
+    VALIDATE_DISPLAY_RETURN(display, EGL_FALSE);
+    dpy->setProgramBinaryLinkStatusEnabled(enabled == EGL_TRUE);
+    return EGL_TRUE;
+}
+
 /*********************************************************************************/
 
 EGLAPI EGLBoolean EGLAPIENTRY eglPreSaveContext(EGLDisplay display, EGLContext contex, EGLStreamKHR stream) {
diff --git a/host/gl/glestranslator/EGL/EglOsApi_wgl.cpp b/host/gl/glestranslator/EGL/EglOsApi_wgl.cpp
old mode 100755
new mode 100644
diff --git a/host/gl/glestranslator/GLES_CM/GLEScmContext.cpp b/host/gl/glestranslator/GLES_CM/GLEScmContext.cpp
index 4e39f98..d21997d 100644
--- a/host/gl/glestranslator/GLES_CM/GLEScmContext.cpp
+++ b/host/gl/glestranslator/GLES_CM/GLEScmContext.cpp
@@ -39,10 +39,10 @@
     s_maxGlesVersion = version;
 }
 
-void GLEScmContext::init(bool nativeTextureDecompressionEnabled) {
+void GLEScmContext::init(bool nativeTextureDecompressionEnabled, bool programBinaryLinkStatusEnabled) {
     android::base::AutoLock mutex(s_lock);
     if(!m_initialized) {
-        GLEScontext::init(nativeTextureDecompressionEnabled);
+        GLEScontext::init(nativeTextureDecompressionEnabled, programBinaryLinkStatusEnabled);
 
         addVertexArrayObject(0);
         setVertexArrayObject(0);
diff --git a/host/gl/glestranslator/GLES_CM/GLEScmContext.h b/host/gl/glestranslator/GLES_CM/GLEScmContext.h
index f7227a9..b5fcf2b 100644
--- a/host/gl/glestranslator/GLES_CM/GLEScmContext.h
+++ b/host/gl/glestranslator/GLES_CM/GLEScmContext.h
@@ -37,7 +37,7 @@
 class GLEScmContext: public GLEScontext
 {
 public:
-    virtual void init(bool nativeTextureDecompressionEnabled) override;
+    virtual void init(bool nativeTextureDecompressionEnabled, bool programBinaryLinkStatusEnabled) override;
     virtual const GLSupport* getCaps() const override { return &(GLEScontext::s_glSupportGles1); }
     static void initGlobal(EGLiface* eglIface);
     GLEScmContext(int maj, int min, GlobalNameSpace* globalNameSpace,
diff --git a/host/gl/glestranslator/GLES_CM/GLEScmImp.cpp b/host/gl/glestranslator/GLES_CM/GLEScmImp.cpp
index a1f5a20..4342efb 100644
--- a/host/gl/glestranslator/GLES_CM/GLEScmImp.cpp
+++ b/host/gl/glestranslator/GLES_CM/GLEScmImp.cpp
@@ -64,7 +64,7 @@
 
 //decleration
 static void initGLESx(bool isGles2Gles);
-static void initContext(GLEScontext* ctx, ShareGroupPtr grp, bool nativeTextureDecompressionEnabled);
+static void initContext(GLEScontext* ctx, ShareGroupPtr grp, bool nativeTextureDecompressionEnabled, bool programBinaryLinkStatusEnabled);
 static void setMaxGlesVersion(GLESVersion version);
 static void deleteGLESContext(GLEScontext* ctx);
 static void setShareGroup(GLEScontext* ctx,ShareGroupPtr grp);
@@ -203,7 +203,7 @@
     return;
 }
 
-static void initContext(GLEScontext* ctx, ShareGroupPtr grp, bool nativeTextureDecompressionEnabled) {
+static void initContext(GLEScontext* ctx, ShareGroupPtr grp, bool nativeTextureDecompressionEnabled, bool programBinaryLinkStatusEnabled) {
     setCoreProfile(ctx->isCoreProfile());
     GLEScmContext::initGlobal(s_eglIface);
 
@@ -220,7 +220,7 @@
         ctx->setShareGroup(grp);
     }
     if (!ctx->isInitialized()) {
-        ctx->init(nativeTextureDecompressionEnabled);
+        ctx->init(nativeTextureDecompressionEnabled, programBinaryLinkStatusEnabled);
         translator::gles1::glBindTexture(GL_TEXTURE_2D,0);
         translator::gles1::glBindTexture(GL_TEXTURE_CUBE_MAP_OES,0);
     }
diff --git a/host/gl/glestranslator/GLES_V2/GLESv2Context.cpp b/host/gl/glestranslator/GLES_V2/GLESv2Context.cpp
index 5a4e597..efababc 100644
--- a/host/gl/glestranslator/GLES_V2/GLESv2Context.cpp
+++ b/host/gl/glestranslator/GLES_V2/GLESv2Context.cpp
@@ -64,10 +64,10 @@
     GLEScontext::initGlobal(iface);
 }
 
-void GLESv2Context::init(bool nativeTextureDecompressionEnabled) {
+void GLESv2Context::init(bool nativeTextureDecompressionEnabled, bool programBinaryLinkStatusEnabled) {
     android::base::AutoLock mutex(s_lock);
     if(!m_initialized) {
-        GLEScontext::init(nativeTextureDecompressionEnabled);
+        GLEScontext::init(nativeTextureDecompressionEnabled, programBinaryLinkStatusEnabled);
         addVertexArrayObject(0);
         setVertexArrayObject(0);
         setAttribute0value(0.0, 0.0, 0.0, 1.0);
diff --git a/host/gl/glestranslator/GLES_V2/GLESv2Context.h b/host/gl/glestranslator/GLES_V2/GLESv2Context.h
index 683fba5..d8f57cc 100644
--- a/host/gl/glestranslator/GLES_V2/GLESv2Context.h
+++ b/host/gl/glestranslator/GLES_V2/GLESv2Context.h
@@ -33,7 +33,8 @@
 
 class GLESv2Context : public GLEScontext{
 public:
-    virtual void init(bool nativeTextureDecompressionEnabled) override;
+    virtual void init(bool nativeTextureDecompressionEnabled,
+                      bool programBinaryLinkStatusEnabled) override;
     virtual const GLSupport* getCaps() const override {
         if (m_glesMajorVersion == 3 && m_glesMinorVersion == 1) {
             return &s_glSupportGles31;
diff --git a/host/gl/glestranslator/GLES_V2/GLESv2Imp.cpp b/host/gl/glestranslator/GLES_V2/GLESv2Imp.cpp
index f85edd1..0dee561 100644
--- a/host/gl/glestranslator/GLES_V2/GLESv2Imp.cpp
+++ b/host/gl/glestranslator/GLES_V2/GLESv2Imp.cpp
@@ -75,7 +75,7 @@
 
 //decleration
 static void initGLESx(bool isGles2Gles);
-static void initContext(GLEScontext* ctx, ShareGroupPtr grp, bool nativeTextureDecompressionEnabled);
+static void initContext(GLEScontext* ctx, ShareGroupPtr grp, bool nativeTextureDecompressionEnabled, bool programBinaryLinkStatusEnabled);
 static void setMaxGlesVersion(GLESVersion version);
 static void deleteGLESContext(GLEScontext* ctx);
 static void setShareGroup(GLEScontext* ctx,ShareGroupPtr grp);
@@ -241,7 +241,7 @@
     GLESv2Context::setMaxGlesVersion(version);
 }
 
-static void initContext(GLEScontext* ctx, ShareGroupPtr grp, bool nativeTextureDecompressionEnabled) {
+static void initContext(GLEScontext* ctx, ShareGroupPtr grp, bool nativeTextureDecompressionEnabled, bool programBinaryLinkStatusEnabled) {
     setCoreProfile(ctx->isCoreProfile());
     GLESv2Context::initGlobal(s_eglIface);
 
@@ -249,7 +249,7 @@
         ctx->setShareGroup(grp);
     }
     if (!ctx->isInitialized()) {
-        ctx->init(nativeTextureDecompressionEnabled);
+        ctx->init(nativeTextureDecompressionEnabled, programBinaryLinkStatusEnabled);
         translator::gles2::glBindTexture(GL_TEXTURE_2D,0);
         translator::gles2::glBindTexture(GL_TEXTURE_CUBE_MAP,0);
     }
diff --git a/host/gl/glestranslator/GLES_V2/GLESv30Imp.cpp b/host/gl/glestranslator/GLES_V2/GLESv30Imp.cpp
index 3752642..60183b2 100644
--- a/host/gl/glestranslator/GLES_V2/GLESv30Imp.cpp
+++ b/host/gl/glestranslator/GLES_V2/GLESv30Imp.cpp
@@ -983,7 +983,38 @@
     GET_CTX_V2();
     if (ctx->shareGroup().get()) {
         const GLuint globalProgramName = ctx->shareGroup()->getGlobalName(NamedObjectType::SHADER_OR_PROGRAM, program);
+        SET_ERROR_IF(globalProgramName == 0, GL_INVALID_VALUE);
+
+        auto objData =
+            ctx->shareGroup()->getObjectData(NamedObjectType::SHADER_OR_PROGRAM, program);
+        SET_ERROR_IF(!objData, GL_INVALID_OPERATION);
+        SET_ERROR_IF(objData->getDataType() != PROGRAM_DATA, GL_INVALID_OPERATION);
+
+        ProgramData* programData = (ProgramData*)objData;
+
         ctx->dispatcher().glProgramBinary(globalProgramName, binaryFormat, binary, length);
+
+        if (ctx->programBinaryLinkStatusEnabled()) {
+            GLint linkStatus = GL_FALSE;
+            ctx->dispatcher().glGetProgramiv(globalProgramName, GL_LINK_STATUS, &linkStatus);
+
+            programData->setHostLinkStatus(linkStatus);
+            programData->setLinkStatus(linkStatus);
+
+            GLsizei infoLogLength = 0;
+            ctx->dispatcher().glGetProgramiv(globalProgramName, GL_INFO_LOG_LENGTH, &infoLogLength);
+
+            if (infoLogLength > 0) {
+                std::vector<GLchar> infoLog(infoLogLength);
+                ctx->dispatcher().glGetProgramInfoLog(globalProgramName, infoLogLength, &infoLogLength,
+                                                    infoLog.data());
+
+                if (infoLogLength) {
+                    infoLog.resize(infoLogLength);
+                    programData->setInfoLog(infoLog.data());
+                }
+            }
+        }
     }
 }
 
diff --git a/host/gl/glestranslator/GLcommon/GLEScontext.cpp b/host/gl/glestranslator/GLcommon/GLEScontext.cpp
index 70e9905..4678cee 100644
--- a/host/gl/glestranslator/GLcommon/GLEScontext.cpp
+++ b/host/gl/glestranslator/GLcommon/GLEScontext.cpp
@@ -401,9 +401,10 @@
     s_lock.unlock();
 }
 
-void GLEScontext::init(bool nativeTextureDecompressionEnabled) {
+void GLEScontext::init(bool nativeTextureDecompressionEnabled, bool programBinaryLinkStatusEnabled) {
     if (!m_initialized) {
         m_nativeTextureDecompressionEnabled = nativeTextureDecompressionEnabled;
+        m_programBinaryLinkStatusEnabled = programBinaryLinkStatusEnabled;
         initExtensionString();
 
         m_maxTexUnits = getMaxCombinedTexUnits();
diff --git a/host/gl/glestranslator/GLcommon/TextureData.cpp b/host/gl/glestranslator/GLcommon/TextureData.cpp
old mode 100755
new mode 100644
diff --git a/host/gl/glestranslator/include/GLcommon/GLEScontext.h b/host/gl/glestranslator/include/GLcommon/GLEScontext.h
index de18de8..44b87df 100644
--- a/host/gl/glestranslator/include/GLcommon/GLEScontext.h
+++ b/host/gl/glestranslator/include/GLcommon/GLEScontext.h
@@ -248,7 +248,7 @@
     GLEScontext();
     GLEScontext(GlobalNameSpace* globalNameSpace, android::base::Stream* stream,
             GlLibrary* glLib);
-    virtual void init(bool nativeTextureDecompressionEnabled);
+    virtual void init(bool nativeTextureDecompressionEnabled, bool programBinaryLinkStatusEnabled);
     static void initGlobal(EGLiface* eglIface);
     GLenum getGLerror();
     void setGLerror(GLenum err);
@@ -509,6 +509,8 @@
                                             GLint internalFormat, GLenum format, GLenum type);
     void blitFromReadBufferToEGLImage(EGLImage image, GLint internalFormat, int width, int height);
 
+    bool programBinaryLinkStatusEnabled() const { return m_programBinaryLinkStatusEnabled; }
+
 protected:
     void initDefaultFboImpl(
         GLint width, GLint height,
@@ -674,6 +676,7 @@
     GLuint m_useProgram = 0;
 
     bool m_nativeTextureDecompressionEnabled = false;
+    bool m_programBinaryLinkStatusEnabled = false;
 
 private:
 
diff --git a/host/gl/glestranslator/include/GLcommon/TranslatorIfaces.h b/host/gl/glestranslator/include/GLcommon/TranslatorIfaces.h
index 37d9f35..dc56ea1 100644
--- a/host/gl/glestranslator/include/GLcommon/TranslatorIfaces.h
+++ b/host/gl/glestranslator/include/GLcommon/TranslatorIfaces.h
@@ -95,7 +95,7 @@
 typedef struct {
     void (*initGLESx)(bool isGles2Gles);
     GLEScontext*                                    (*createGLESContext)(int majorVersion, int minorVersion, GlobalNameSpace* globalNameSpace, android::base::Stream* stream);
-    void                                            (*initContext)(GLEScontext*, ShareGroupPtr, bool);
+    void                                            (*initContext)(GLEScontext*, ShareGroupPtr, bool, bool);
     void                                            (*setMaxGlesVersion)(GLESVersion);
     void                                            (*deleteGLESContext)(GLEScontext*);
     void                                            (*flush)();
diff --git a/host/include/gfxstream/virtio-gpu-gfxstream-renderer.h b/host/include/gfxstream/virtio-gpu-gfxstream-renderer.h
index 9a97be8..ce43ca1 100644
--- a/host/include/gfxstream/virtio-gpu-gfxstream-renderer.h
+++ b/host/include/gfxstream/virtio-gpu-gfxstream-renderer.h
@@ -255,6 +255,8 @@
     STREAM_RENDERER_FLAGS_USE_EXTERNAL_BLOB = 1 << 6,
     STREAM_RENDERER_FLAGS_USE_SYSTEM_BLOB = 1 << 7,
     STREAM_RENDERER_FLAGS_VULKAN_NATIVE_SWAPCHAIN_BIT = 1 << 8,
+    // Unstable: do not use until a release greater than 0.1.2
+    STREAM_RENDERER_FLAGS_VULKAN_EXTERNAL_SYNC = 1 << 31,
 };
 
 #endif
diff --git a/host/magma/DrmBuffer.cpp b/host/magma/DrmBuffer.cpp
index 84aa2f9..067b816 100644
--- a/host/magma/DrmBuffer.cpp
+++ b/host/magma/DrmBuffer.cpp
@@ -19,7 +19,7 @@
 #include <sys/mman.h>
 
 #include "host-common/logging.h"
-#include "host/BlobManager.h"
+#include "host/ExternalObjectManager.h"
 
 namespace gfxstream {
 namespace magma {
@@ -43,7 +43,7 @@
         return;
     }
     if (mHva) {
-        BlobManager::get()->removeMapping(mContextId, mId);
+        ExternalObjectManager::get()->removeMapping(mContextId, mId);
     }
     drm_gem_close params{.handle = mGemHandle};
     int result = mDevice.ioctl(DRM_IOCTL_GEM_CLOSE, &params);
@@ -95,7 +95,7 @@
     mId = mIdNext.fetch_add(1);
 
     // Add the mapping entry.
-    BlobManager::get()->addMapping(mContextId, mId, mHva, MAP_CACHE_CACHED);
+    ExternalObjectManager::get()->addMapping(mContextId, mId, mHva, MAP_CACHE_CACHED);
 
     INFO("Mapped DrmBuffer size %" PRIu64 " gem %" PRIu32 " to addr %p mid %" PRIu64, mSize,
          mGemHandle, mHva, mId);
diff --git a/host/meson.build b/host/meson.build
index 5444eeb..18dfea9 100644
--- a/host/meson.build
+++ b/host/meson.build
@@ -6,6 +6,7 @@
 #===============#
 gfxstream_host_args = [
   '-D_FILE_OFFSET_BITS=64',
+  '-DGFXSTREAM_ENABLE_GUEST_VIRTIO_RESOURCE_TILING_CONTROL=1',
   '-Wno-unused-parameter',
   '-Wno-unused-function',
   '-Wno-unused-variable',
@@ -76,6 +77,8 @@
   aemu_snapshot_dep = dependency('aemu_snapshot')
   dl_dep = dependency('dl')
   thread_dep = dependency('threads')
+  gfxstream_host_args += '-DGFXSTREAM_UNSTABLE_VULKAN_EXTERNAL_SYNC=1'
+  gfxstream_host_args += '-DGFXSTREAM_UNSTABLE_VULKAN_DMABUF_WINSYS=1'
 endif
 
 if log_level == 'error'
@@ -161,7 +164,7 @@
 
 files_lib_gfxstream_backend = files(
   'Buffer.cpp',
-  'BlobManager.cpp',
+  'ExternalObjectManager.cpp',
   'ChannelStream.cpp',
   'ColorBuffer.cpp',
   'DisplaySurface.cpp',
diff --git a/host/virtgpu_gfxstream_protocol.h b/host/virtgpu_gfxstream_protocol.h
index 19827ea..5a3aefa 100644
--- a/host/virtgpu_gfxstream_protocol.h
+++ b/host/virtgpu_gfxstream_protocol.h
@@ -44,6 +44,7 @@
 #define GFXSTREAM_CREATE_IMPORT_SYNC_VK         0xa001
 #define GFXSTREAM_CREATE_QSRI_EXPORT_VK         0xa002
 #define GFXSTREAM_RESOURCE_CREATE_3D            0xa003
+#define GFXSTREAM_ACQUIRE_SYNC                  0xa004
 
 // clang-format off
 // A placeholder command to ensure virtio-gpu completes
@@ -106,6 +107,12 @@
     uint64_t blobId;
 };
 
+struct gfxstreamAcquireSync {
+    struct gfxstreamHeader hdr;
+    uint32_t padding;
+    uint64_t syncId;
+};
+
 struct vulkanCapset {
     uint32_t protocolVersion;
 
@@ -118,7 +125,8 @@
     uint32_t blobAlignment;
     uint32_t noRenderControlEnc;
     uint32_t alwaysBlob;
-    uint32_t padding[13];
+    uint32_t externalSync;
+    uint32_t padding[12];
 };
 
 struct magmaCapset {
diff --git a/host/virtio-gpu-gfxstream-renderer.cpp b/host/virtio-gpu-gfxstream-renderer.cpp
index 89ad5cc..cf5fae7 100644
--- a/host/virtio-gpu-gfxstream-renderer.cpp
+++ b/host/virtio-gpu-gfxstream-renderer.cpp
@@ -20,7 +20,7 @@
 #include <unordered_map>
 #include <variant>
 
-#include "BlobManager.h"
+#include "ExternalObjectManager.h"
 #include "FrameBuffer.h"
 #include "GfxStreamAgents.h"
 #include "VirtioGpuTimelines.h"
@@ -220,8 +220,9 @@
 using android::base::SharedMemory;
 
 using emugl::FatalError;
-using gfxstream::BlobManager;
-using gfxstream::ManagedDescriptorInfo;
+using gfxstream::BlobDescriptorInfo;
+using gfxstream::ExternalObjectManager;
+using gfxstream::SyncDescriptorInfo;
 
 using VirtioGpuResId = uint32_t;
 
@@ -243,6 +244,7 @@
     bool hasAddressSpaceHandle;
     std::unordered_map<VirtioGpuResId, uint32_t> addressSpaceHandles;
     std::unordered_map<uint32_t, struct stream_renderer_resource_create_args> blobMap;
+    std::shared_ptr<gfxstream::SyncDescriptorInfo> latestFence;
 };
 
 enum class ResType {
@@ -315,7 +317,7 @@
     ResType type;
     std::shared_ptr<RingBlob> ringBlob;
     bool externalAddr = false;
-    std::shared_ptr<ManagedDescriptorInfo> descriptorInfo = nullptr;
+    std::shared_ptr<BlobDescriptorInfo> descriptorInfo = nullptr;
 };
 
 static inline uint32_t align_up(uint32_t n, uint32_t a) { return ((n + a - 1) / a) * a; }
@@ -1058,6 +1060,33 @@
                 ctxEntry.blobMap[create3d.blobId] = rc3d;
                 break;
             }
+            case GFXSTREAM_ACQUIRE_SYNC: {
+                DECODE(acquireSync, gfxstream::gfxstreamAcquireSync, buffer);
+
+                auto ctxIt = mContexts.find(cmd->ctx_id);
+                if (ctxIt == mContexts.end()) {
+                    stream_renderer_error("ctx id %u is not found", cmd->ctx_id);
+                    return -EINVAL;
+                }
+
+                auto& ctxEntry = ctxIt->second;
+                if (ctxEntry.latestFence) {
+                    stream_renderer_error("expected latest fence to empty");
+                    return -EINVAL;
+                }
+
+                auto syncDescriptorInfoOpt = ExternalObjectManager::get()->removeSyncDescriptorInfo(
+                    cmd->ctx_id, acquireSync.syncId);
+                if (syncDescriptorInfoOpt) {
+                    ctxEntry.latestFence = std::make_shared<gfxstream::SyncDescriptorInfo>(
+                        std::move(*syncDescriptorInfoOpt));
+                } else {
+                    stream_renderer_error("failed to get sync descriptor info");
+                    return -EINVAL;
+                }
+
+                break;
+            }
             case GFXSTREAM_PLACEHOLDER_COMMAND_VK: {
                 // Do nothing, this is a placeholder command
                 break;
@@ -1108,6 +1137,25 @@
         return 0;
     }
 
+    int acquireContextFence(uint32_t ctx_id, uint64_t fenceId) {
+        auto ctxIt = mContexts.find(ctx_id);
+        if (ctxIt == mContexts.end()) {
+            stream_renderer_error("ctx id %u is not found", ctx_id);
+            return -EINVAL;
+        }
+
+        auto& ctxEntry = ctxIt->second;
+        if (ctxEntry.latestFence) {
+            mSyncMap[fenceId] = ctxEntry.latestFence;
+            ctxEntry.latestFence = nullptr;
+        } else {
+            stream_renderer_error("Failed to acquire sync descriptor");
+            return -EINVAL;
+        }
+
+        return 0;
+    }
+
     void poll() { mVirtioGpuTimelines->poll(); }
 
     enum pipe_texture_target {
@@ -1185,7 +1233,13 @@
 
         const uint32_t glformat = virgl_format_to_gl(args->format);
         const uint32_t fwkformat = virgl_format_to_fwk_format(args->format);
-        const bool linear = !!(args->bind & VIRGL_BIND_LINEAR);
+
+        const bool linear =
+#ifdef GFXSTREAM_ENABLE_GUEST_VIRTIO_RESOURCE_TILING_CONTROL
+            !!(args->bind & VIRGL_BIND_LINEAR);
+#else
+            false;
+#endif
         gfxstream::FrameBuffer::getFB()->createColorBufferWithHandle(
             args->width, args->height, glformat, (gfxstream::FrameworkFormat)fwkformat,
             args->handle, linear);
@@ -1582,9 +1636,13 @@
                     capset->deferredMapping = 1;
                 }
 
-#if SUPPORT_DMABUF
+#if GFXSTREAM_UNSTABLE_VULKAN_DMABUF_WINSYS
                 capset->alwaysBlob = 1;
 #endif
+
+#if GFXSTREAM_UNSTABLE_VULKAN_EXTERNAL_SYNC
+                capset->externalSync = 1;
+#endif
                 break;
             }
             case VIRTGPU_CAPSET_GFXSTREAM_MAGMA: {
@@ -1763,7 +1821,7 @@
 
         PipeResEntry e;
         struct stream_renderer_resource_create_args args = {0};
-        std::optional<ManagedDescriptorInfo> descriptorInfoOpt = std::nullopt;
+        std::optional<BlobDescriptorInfo> descriptorInfoOpt = std::nullopt;
         e.args = args;
         e.hostPipe = 0;
 
@@ -1815,9 +1873,9 @@
                 (create_blob->blob_flags & STREAM_BLOB_FLAG_CREATE_GUEST_HANDLE)) {
 #if defined(__linux__) || defined(__QNX__)
                 ManagedDescriptor managedHandle(handle->os_handle);
-                BlobManager::get()->addDescriptorInfo(ctx_id, create_blob->blob_id,
-                                                      std::move(managedHandle), handle->handle_type,
-                                                      0, std::nullopt);
+                ExternalObjectManager::get()->addBlobDescriptorInfo(
+                    ctx_id, create_blob->blob_id, std::move(managedHandle), handle->handle_type, 0,
+                    std::nullopt);
 
                 e.caching = STREAM_RENDERER_MAP_CACHE_CACHED;
 #else
@@ -1825,13 +1883,13 @@
 #endif
             } else {
                 if (!descriptorInfoOpt) {
-                    descriptorInfoOpt =
-                        BlobManager::get()->removeDescriptorInfo(ctx_id, create_blob->blob_id);
+                    descriptorInfoOpt = ExternalObjectManager::get()->removeBlobDescriptorInfo(
+                        ctx_id, create_blob->blob_id);
                 }
 
                 if (descriptorInfoOpt) {
                     e.descriptorInfo =
-                        std::make_shared<ManagedDescriptorInfo>(std::move(*descriptorInfoOpt));
+                        std::make_shared<BlobDescriptorInfo>(std::move(*descriptorInfoOpt));
                 } else {
                     return -EINVAL;
                 }
@@ -1839,7 +1897,8 @@
                 e.caching = e.descriptorInfo->caching;
             }
         } else {
-            auto entryOpt = BlobManager::get()->removeMapping(ctx_id, create_blob->blob_id);
+            auto entryOpt =
+                ExternalObjectManager::get()->removeMapping(ctx_id, create_blob->blob_id);
             if (entryOpt) {
                 e.hva = entryOpt->addr;
                 e.caching = entryOpt->caching;
@@ -1969,22 +2028,12 @@
         }
 
         if (entry.descriptorInfo) {
-            bool shareable = entry.blobFlags &
-                             (STREAM_BLOB_FLAG_USE_SHAREABLE | STREAM_BLOB_FLAG_USE_CROSS_DEVICE);
-
-            DescriptorType rawDescriptor;
-            if (shareable) {
-                // TODO: Add ManagedDescriptor::{clone, dup} method and use it;
-                // This should have no affect since gfxstream allocates mappable-only buffers
-                // currently
+	    DescriptorType rawDescriptor;
+            auto rawDescriptorOpt = entry.descriptorInfo->descriptor.release();
+            if (rawDescriptorOpt)
+                rawDescriptor = *rawDescriptorOpt;
+            else
                 return -EINVAL;
-            } else {
-                auto rawDescriptorOpt = entry.descriptorInfo->descriptor.release();
-                if (rawDescriptorOpt)
-                    rawDescriptor = *rawDescriptorOpt;
-                else
-                    return -EINVAL;
-            }
 
             handle->handle_type = entry.descriptorInfo->handleType;
 
@@ -2000,6 +2049,31 @@
         return -EINVAL;
     }
 
+    int exportFence(uint64_t fenceId, struct stream_renderer_handle* handle) {
+        auto it = mSyncMap.find(fenceId);
+        if (it == mSyncMap.end()) {
+            return -EINVAL;
+        }
+
+        auto& entry = it->second;
+        DescriptorType rawDescriptor;
+        auto rawDescriptorOpt = entry->descriptor.release();
+        if (rawDescriptorOpt)
+            rawDescriptor = *rawDescriptorOpt;
+        else
+            return -EINVAL;
+
+        handle->handle_type = entry->handleType;
+
+#ifdef _WIN32
+        handle->os_handle = static_cast<int64_t>(reinterpret_cast<intptr_t>(rawDescriptor));
+#else
+        handle->os_handle = static_cast<int64_t>(rawDescriptor);
+#endif
+
+        return 0;
+    }
+
     int vulkanInfo(uint32_t res_handle, struct stream_renderer_vulkan_info* vulkan_info) {
         auto it = mResources.find(res_handle);
         if (it == mResources.end()) return -EINVAL;
@@ -2103,6 +2177,7 @@
     std::unordered_map<VirtioGpuResId, PipeResEntry> mResources;
     std::unordered_map<VirtioGpuCtxId, std::vector<VirtioGpuResId>> mContextResources;
     std::unordered_map<VirtioGpuResId, std::vector<VirtioGpuCtxId>> mResourceContexts;
+    std::unordered_map<uint64_t, std::shared_ptr<SyncDescriptorInfo>> mSyncMap;
 
     // When we wait for gpu or wait for gpu vulkan, the next (and subsequent)
     // fences created for that context should not be signaled immediately.
@@ -2213,6 +2288,13 @@
 }
 
 VG_EXPORT int stream_renderer_create_fence(const struct stream_renderer_fence* fence) {
+    if (fence->flags & STREAM_RENDERER_FLAG_FENCE_SHAREABLE) {
+        int ret = sRenderer()->acquireContextFence(fence->ctx_id, fence->fence_id);
+        if (ret) {
+            return ret;
+        }
+    }
+
     if (fence->flags & STREAM_RENDERER_FLAG_FENCE_RING_IDX) {
         sRenderer()->createFence(fence->fence_id, VirtioGpuRingContextSpecific{
                                                       .mCtxId = fence->ctx_id,
@@ -2225,6 +2307,11 @@
     return 0;
 }
 
+VG_EXPORT int stream_renderer_export_fence(uint64_t fence_id,
+                                           struct stream_renderer_handle* handle) {
+    return sRenderer()->exportFence(fence_id, handle);
+}
+
 VG_EXPORT int stream_renderer_platform_import_resource(int res_handle, int res_info,
                                                        void* resource) {
     return sRenderer()->platformImportResource(res_handle, res_info, resource);
@@ -2511,6 +2598,8 @@
     GFXSTREAM_SET_FEATURE_ON_CONDITION(
         &features, ExternalBlob,
         renderer_flags & STREAM_RENDERER_FLAGS_USE_EXTERNAL_BLOB);
+    GFXSTREAM_SET_FEATURE_ON_CONDITION(&features, VulkanExternalSync,
+                                       renderer_flags & STREAM_RENDERER_FLAGS_VULKAN_EXTERNAL_SYNC);
     GFXSTREAM_SET_FEATURE_ON_CONDITION(
         &features, GlAsyncSwap, false);
     GFXSTREAM_SET_FEATURE_ON_CONDITION(
@@ -2788,6 +2877,10 @@
         return -EINVAL;
     }
 
+#if GFXSTREAM_UNSTABLE_VULKAN_EXTERNAL_SYNC
+    renderer_flags |= STREAM_RENDERER_FLAGS_VULKAN_EXTERNAL_SYNC;
+#endif
+
     gfxstream::host::FeatureSet features;
     int ret = parseGfxstreamFeatures(renderer_flags, renderer_features_str, features);
     if (ret) {
@@ -2805,6 +2898,15 @@
     gfxstream::vk::vk_util::setVkCheckCallbacks(
         std::make_unique<gfxstream::vk::vk_util::VkCheckCallbacks>(
             gfxstream::vk::vk_util::VkCheckCallbacks{
+                .onVkErrorDeviceLost =
+                    []() {
+                        auto fb = gfxstream::FrameBuffer::getFB();
+                        if (!fb) {
+                            ERR("FrameBuffer not yet initialized. Dropping device lost event");
+                            return;
+                        }
+                        fb->logVulkanDeviceLost();
+                    },
                 .onVkErrorOutOfMemory =
                     [](VkResult result, const char* function, int line) {
                         auto fb = gfxstream::FrameBuffer::getFB();
diff --git a/host/vulkan/Android.bp b/host/vulkan/Android.bp
index f51c207..6b809ae 100644
--- a/host/vulkan/Android.bp
+++ b/host/vulkan/Android.bp
@@ -45,6 +45,7 @@
         "ColorBufferVk.cpp",
         "CompositorVk.cpp",
         "DebugUtilsHelper.cpp",
+        "DeviceLostHelper.cpp",
         "DeviceOpTracker.cpp",
         "DisplaySurfaceVk.cpp",
         "DisplayVk.cpp",
diff --git a/host/vulkan/BUILD.bazel b/host/vulkan/BUILD.bazel
index 2ef519d..3b2d174 100644
--- a/host/vulkan/BUILD.bazel
+++ b/host/vulkan/BUILD.bazel
@@ -6,6 +6,7 @@
         "ColorBufferVk.cpp",
         "CompositorVk.cpp",
         "DebugUtilsHelper.cpp",
+        "DeviceLostHelper.cpp",
         "DeviceOpTracker.cpp",
         "DisplaySurfaceVk.cpp",
         "DisplayVk.cpp",
diff --git a/host/vulkan/BufferVk.cpp b/host/vulkan/BufferVk.cpp
index a8ec4f3..234a629 100644
--- a/host/vulkan/BufferVk.cpp
+++ b/host/vulkan/BufferVk.cpp
@@ -45,12 +45,12 @@
     return updateBufferFromBytes(mHandle, offset, size, bytes);
 }
 
-std::optional<ManagedDescriptorInfo> BufferVk::exportBlob() {
+std::optional<BlobDescriptorInfo> BufferVk::exportBlob() {
     uint32_t streamHandleType = 0;
     auto vkHandle = getBufferExtMemoryHandle(mHandle, &streamHandleType);
     if (vkHandle != VK_EXT_MEMORY_HANDLE_INVALID) {
         ManagedDescriptor descriptor(dupExternalMemory(vkHandle));
-        return ManagedDescriptorInfo{
+        return BlobDescriptorInfo{
             .descriptor = std::move(descriptor),
             .handleType = streamHandleType,
             .caching = 0,
diff --git a/host/vulkan/BufferVk.h b/host/vulkan/BufferVk.h
index 1df6b55..231179b 100644
--- a/host/vulkan/BufferVk.h
+++ b/host/vulkan/BufferVk.h
@@ -15,7 +15,7 @@
 #include <memory>
 #include <vector>
 
-#include "BlobManager.h"
+#include "ExternalObjectManager.h"
 
 namespace gfxstream {
 namespace vk {
@@ -30,7 +30,7 @@
 
     bool updateFromBytes(uint64_t offset, uint64_t size, const void* bytes);
 
-    std::optional<ManagedDescriptorInfo> exportBlob();
+    std::optional<BlobDescriptorInfo> exportBlob();
 
    private:
     BufferVk(uint32_t handle);
diff --git a/host/vulkan/CMakeLists.txt b/host/vulkan/CMakeLists.txt
index 779aa42..7da5d9e 100644
--- a/host/vulkan/CMakeLists.txt
+++ b/host/vulkan/CMakeLists.txt
@@ -11,6 +11,7 @@
             BufferVk.cpp
             ColorBufferVk.cpp
             CompositorVk.cpp
+            DeviceLostHelper.cpp
             DeviceOpTracker.cpp
             DisplayVk.cpp
             DisplaySurfaceVk.cpp
diff --git a/host/vulkan/ColorBufferVk.cpp b/host/vulkan/ColorBufferVk.cpp
index cd82b15..d432fd2 100644
--- a/host/vulkan/ColorBufferVk.cpp
+++ b/host/vulkan/ColorBufferVk.cpp
@@ -80,10 +80,10 @@
 
 int ColorBufferVk::waitSync() { return waitSyncVkColorBuffer(mHandle); }
 
-std::optional<ManagedDescriptorInfo> ColorBufferVk::exportBlob() {
+std::optional<BlobDescriptorInfo> ColorBufferVk::exportBlob() {
     auto info = exportColorBufferMemory(mHandle);
     if (info) {
-        return ManagedDescriptorInfo{
+        return BlobDescriptorInfo{
             .descriptor = std::move((*info).descriptor),
             .handleType = (*info).streamHandleType,
             .caching = 0,
diff --git a/host/vulkan/ColorBufferVk.h b/host/vulkan/ColorBufferVk.h
index e7187b9..fec9284 100644
--- a/host/vulkan/ColorBufferVk.h
+++ b/host/vulkan/ColorBufferVk.h
@@ -17,7 +17,7 @@
 #include <memory>
 #include <vector>
 
-#include "BlobManager.h"
+#include "ExternalObjectManager.h"
 #include "FrameworkFormats.h"
 #include "aemu/base/files/Stream.h"
 
@@ -44,7 +44,7 @@
     void onSave(android::base::Stream* stream);
 
     int waitSync();
-    std::optional<ManagedDescriptorInfo> exportBlob();
+    std::optional<BlobDescriptorInfo> exportBlob();
 
    private:
     ColorBufferVk(uint32_t handle);
diff --git a/host/vulkan/DeviceLostHelper.cpp b/host/vulkan/DeviceLostHelper.cpp
new file mode 100644
index 0000000..ed6f989
--- /dev/null
+++ b/host/vulkan/DeviceLostHelper.cpp
@@ -0,0 +1,160 @@
+// Copyright 2024 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either expresso or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "DeviceLostHelper.h"
+
+#include "host-common/logging.h"
+
+namespace gfxstream {
+namespace vk {
+
+void DeviceLostHelper::enableWithNvidiaDeviceDiagnosticCheckpoints() { mEnabled = true; }
+
+const void* DeviceLostHelper::createMarkerForCommandBuffer(const VkCommandBuffer& commandBuffer,
+                                                           MarkerType type) {
+    std::lock_guard<std::mutex> lock(mMarkersMutex);
+
+    auto it = mMarkers.insert(CheckpointMarker{commandBuffer, type});
+
+    // References and pointers to data stored in the container are only
+    // invalidated by erasing that element, even when the corresponding
+    // iterator is invalidated.
+    return reinterpret_cast<const void*>(&(*it.first));
+}
+
+void DeviceLostHelper::removeMarkersForCommandBuffer(const VkCommandBuffer& commandBuffer) {
+    std::lock_guard<std::mutex> lock(mMarkersMutex);
+    mMarkers.erase(CheckpointMarker{
+        .commandBuffer = commandBuffer,
+        .type = MarkerType::kBegin,
+    });
+    mMarkers.erase(CheckpointMarker{
+        .commandBuffer = commandBuffer,
+        .type = MarkerType::kEnd,
+    });
+}
+
+void DeviceLostHelper::addNeededDeviceExtensions(std::vector<const char*>* deviceExtensions) {
+    if (mEnabled) {
+        deviceExtensions->push_back(VK_NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_EXTENSION_NAME);
+    }
+}
+
+void DeviceLostHelper::onBeginCommandBuffer(const VkCommandBuffer& commandBuffer,
+                                            const VulkanDispatch* vk) {
+    if (!mEnabled) {
+        return;
+    }
+
+    const void* marker = createMarkerForCommandBuffer(commandBuffer, MarkerType::kBegin);
+    vk->vkCmdSetCheckpointNV(commandBuffer, marker);
+}
+
+void DeviceLostHelper::onEndCommandBuffer(const VkCommandBuffer& commandBuffer,
+                                          const VulkanDispatch* vk) {
+    if (!mEnabled) {
+        return;
+    }
+
+    const void* marker = createMarkerForCommandBuffer(commandBuffer, MarkerType::kEnd);
+    vk->vkCmdSetCheckpointNV(commandBuffer, marker);
+}
+
+void DeviceLostHelper::onResetCommandBuffer(const VkCommandBuffer& commandBuffer) {
+    if (!mEnabled) {
+        return;
+    }
+
+    removeMarkersForCommandBuffer(commandBuffer);
+}
+
+void DeviceLostHelper::onFreeCommandBuffer(const VkCommandBuffer& commandBuffer) {
+    if (!mEnabled) {
+        return;
+    }
+
+    removeMarkersForCommandBuffer(commandBuffer);
+}
+
+void DeviceLostHelper::onDeviceLost(const std::vector<DeviceWithQueues>& devicesWithQueues) {
+    if (!mEnabled) {
+        return;
+    }
+
+    ERR("DeviceLostHelper starting lost device checks...");
+
+    for (const DeviceWithQueues& deviceWithQueues : devicesWithQueues) {
+        const auto& device = deviceWithQueues.device;
+        const auto* deviceDispatch = deviceWithQueues.deviceDispatch;
+        if (deviceDispatch->vkDeviceWaitIdle(device) != VK_ERROR_DEVICE_LOST) {
+            continue;
+        }
+        ERR("VkDevice:%p was lost, checking for unfinished VkCommandBuffers...", device);
+
+        struct CommandBufferOnQueue {
+            VkCommandBuffer commandBuffer = VK_NULL_HANDLE;
+            VkQueue queue = VK_NULL_HANDLE;
+        };
+        std::vector<CommandBufferOnQueue> unfinishedCommandBuffers;
+
+        for (const VkQueue& queue : deviceWithQueues.queues) {
+            std::vector<VkCheckpointDataNV> checkpointDatas;
+
+            uint32_t checkpointDataCount = 0;
+            deviceDispatch->vkGetQueueCheckpointDataNV(queue, &checkpointDataCount, nullptr);
+            if (checkpointDataCount == 0) continue;
+
+            checkpointDatas.resize(
+                static_cast<size_t>(checkpointDataCount),
+                VkCheckpointDataNV{
+                    .sType = VK_STRUCTURE_TYPE_CHECKPOINT_DATA_NV,
+                });
+            deviceDispatch->vkGetQueueCheckpointDataNV(queue, &checkpointDataCount,
+                                                       checkpointDatas.data());
+
+            std::unordered_set<VkCommandBuffer> unfinishedCommandBuffersForQueue;
+            for (const VkCheckpointDataNV& checkpointData : checkpointDatas) {
+                const auto& marker =
+                    *reinterpret_cast<const CheckpointMarker*>(checkpointData.pCheckpointMarker);
+                if (marker.type == MarkerType::kBegin) {
+                    unfinishedCommandBuffersForQueue.insert(marker.commandBuffer);
+                } else {
+                    unfinishedCommandBuffersForQueue.erase(marker.commandBuffer);
+                }
+            }
+
+            for (const VkCommandBuffer commandBuffer : unfinishedCommandBuffersForQueue) {
+                unfinishedCommandBuffers.push_back(CommandBufferOnQueue{
+                    .commandBuffer = commandBuffer,
+                    .queue = queue,
+                });
+            }
+        }
+
+        if (unfinishedCommandBuffers.empty()) {
+            ERR("VkDevice:%p has no outstanding VkCommandBuffers.", device);
+        } else {
+            ERR("VkDevice:%p has outstanding VkCommandBuffers:", device);
+            for (const CommandBufferOnQueue& unfinished : unfinishedCommandBuffers) {
+                ERR("   - VkCommandBuffer:%p on VkQueue:%p", unfinished.commandBuffer,
+                    unfinished.queue);
+            }
+        }
+    }
+
+    ERR("DeviceLostHelper finished lost device checks.");
+}
+
+}  // namespace vk
+}  // namespace gfxstream
\ No newline at end of file
diff --git a/host/vulkan/DeviceLostHelper.h b/host/vulkan/DeviceLostHelper.h
new file mode 100644
index 0000000..5b07eb2
--- /dev/null
+++ b/host/vulkan/DeviceLostHelper.h
@@ -0,0 +1,89 @@
+// Copyright 2024 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either expresso or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma once
+
+#include <vulkan/vulkan.h>
+
+#include <memory>
+#include <mutex>
+#include <vector>
+#include <unordered_set>
+
+#include "vulkan/cereal/common/goldfish_vk_dispatch.h"
+
+namespace gfxstream {
+namespace vk {
+
+// TODO: Support VK_AMD_buffer_marker.
+class DeviceLostHelper {
+   public:
+    DeviceLostHelper() : mEnabled(false) {};
+
+    DeviceLostHelper(const DeviceLostHelper&) = delete;
+    DeviceLostHelper& operator=(const DeviceLostHelper&) = delete;
+
+    DeviceLostHelper(DeviceLostHelper&&) = delete;
+    DeviceLostHelper& operator=(const DeviceLostHelper&&) = delete;
+
+    void enableWithNvidiaDeviceDiagnosticCheckpoints();
+
+    void addNeededDeviceExtensions(std::vector<const char*>* deviceExtensions);
+
+    void onBeginCommandBuffer(const VkCommandBuffer& commandBuffer, const VulkanDispatch* vk);
+    void onEndCommandBuffer(const VkCommandBuffer& commandBuffer, const VulkanDispatch* vk);
+
+    void onResetCommandBuffer(const VkCommandBuffer& commandBuffer);
+    void onFreeCommandBuffer(const VkCommandBuffer& commandBuffer);
+
+    struct DeviceWithQueues {
+        VkDevice device;
+        const VulkanDispatch* deviceDispatch;
+        std::vector<VkQueue> queues;
+    };
+    void onDeviceLost(const std::vector<DeviceWithQueues>& devicesWithQueues);
+
+   private:
+    enum class MarkerType { kBegin, kEnd };
+
+    struct CheckpointMarker {
+        VkCommandBuffer commandBuffer;
+        MarkerType type;
+    };
+
+    struct CheckpointMarkerEq {
+        bool operator()(const CheckpointMarker& lhs, const CheckpointMarker& rhs) const {
+            return lhs.commandBuffer == rhs.commandBuffer && lhs.type == rhs.type;
+        }
+    };
+
+    struct CheckpointMarkerHash {
+        size_t operator()(const CheckpointMarker& marker) const {
+            std::size_t h1 = (std::size_t)(marker.commandBuffer);
+            std::size_t h2 = (std::size_t)(marker.type);
+            return h1 ^ (h2 << 1);
+        }
+    };
+
+    const void* createMarkerForCommandBuffer(const VkCommandBuffer& commandBuffer, MarkerType type);
+    void removeMarkersForCommandBuffer(const VkCommandBuffer& commandBuffer);
+
+    bool mEnabled = false;
+
+    std::mutex mMarkersMutex;
+    std::unordered_set<CheckpointMarker, CheckpointMarkerHash, CheckpointMarkerEq> mMarkers;
+};
+
+}  // namespace vk
+}  // namespace gfxstream
diff --git a/host/vulkan/VkCommonOperations.cpp b/host/vulkan/VkCommonOperations.cpp
index 05851be..21b1ff7 100644
--- a/host/vulkan/VkCommonOperations.cpp
+++ b/host/vulkan/VkCommonOperations.cpp
@@ -25,7 +25,7 @@
 #include <sstream>
 #include <unordered_set>
 
-#include "BlobManager.h"
+#include "ExternalObjectManager.h"
 #include "VkDecoderGlobalState.h"
 #include "VkEmulatedPhysicalDeviceMemory.h"
 #include "VkFormatUtils.h"
@@ -574,6 +574,10 @@
         VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME,
     };
 
+    std::vector<const char*> externalFenceInstanceExtNames = {
+        VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME,
+    };
+
     std::vector<const char*> surfaceInstanceExtNames = {
         VK_KHR_SURFACE_EXTENSION_NAME,
     };
@@ -599,6 +603,8 @@
         extensionsSupported(instanceExts, externalMemoryInstanceExtNames);
     bool externalSemaphoreCapabilitiesSupported =
         extensionsSupported(instanceExts, externalSemaphoreInstanceExtNames);
+    bool externalFenceCapabilitiesSupported =
+        extensionsSupported(instanceExts, externalFenceInstanceExtNames);
     bool surfaceSupported = extensionsSupported(instanceExts, surfaceInstanceExtNames);
 #if defined(__APPLE__)
     const std::string vulkanIcd = android::base::getEnvironmentVariable("ANDROID_EMU_VK_ICD");
@@ -735,6 +741,7 @@
     sVkEmulation->instanceSupportsExternalMemoryCapabilities = externalMemoryCapabilitiesSupported;
     sVkEmulation->instanceSupportsExternalSemaphoreCapabilities =
         externalSemaphoreCapabilitiesSupported;
+    sVkEmulation->instanceSupportsExternalFenceCapabilities = externalFenceCapabilitiesSupported;
     sVkEmulation->instanceSupportsSurface = surfaceSupported;
 #if defined(__APPLE__)
     sVkEmulation->instanceSupportsMoltenVK = moltenVKSupported;
@@ -814,8 +821,6 @@
             deviceInfos[i].supportsExternalMemoryExport = false;
 #endif
 
-            deviceInfos[i].supportsDmaBuf =
-                extensionsSupported(deviceExts, {VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME});
             deviceInfos[i].supportsIdProperties =
                 sVkEmulation->getPhysicalDeviceProperties2Func != nullptr;
             deviceInfos[i].supportsDriverProperties =
@@ -877,17 +882,28 @@
             deviceInfos[i].driverVersion = driverVersion;
         }
 
+        bool dmaBufBlockList = deviceInfos[i].driverVendor == "NVIDIA (Vendor 0x10de)";
+        deviceInfos[i].supportsDmaBuf =
+            extensionsSupported(deviceExts, {VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME}) &&
+            !dmaBufBlockList;
+
         deviceInfos[i].hasSamplerYcbcrConversionExtension =
             extensionsSupported(deviceExts, {VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME});
+
+        deviceInfos[i].hasNvidiaDeviceDiagnosticCheckpointsExtension =
+            extensionsSupported(deviceExts, {VK_NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_EXTENSION_NAME});
+
         if (sVkEmulation->getPhysicalDeviceFeatures2Func) {
             VkPhysicalDeviceFeatures2 features2 = {
                 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
             };
             auto features2Chain = vk_make_chain_iterator(&features2);
+
             VkPhysicalDeviceSamplerYcbcrConversionFeatures samplerYcbcrConversionFeatures = {
                 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES,
             };
             vk_append_struct(&features2Chain, &samplerYcbcrConversionFeatures);
+
 #if defined(__QNX__)
             VkPhysicalDeviceExternalMemoryScreenBufferFeaturesQNX extMemScreenBufferFeatures = {
                 .sType =
@@ -895,10 +911,23 @@
             };
             vk_append_struct(&features2Chain, &extMemScreenBufferFeatures);
 #endif
+
+            VkPhysicalDeviceDiagnosticsConfigFeaturesNV deviceDiagnosticsConfigFeatures = {
+                .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DIAGNOSTICS_CONFIG_FEATURES_NV,
+                .diagnosticsConfig = VK_FALSE,
+            };
+            if (deviceInfos[i].hasNvidiaDeviceDiagnosticCheckpointsExtension) {
+                vk_append_struct(&features2Chain, &deviceDiagnosticsConfigFeatures);
+            }
+
             sVkEmulation->getPhysicalDeviceFeatures2Func(physdevs[i], &features2);
 
             deviceInfos[i].supportsSamplerYcbcrConversion =
                 samplerYcbcrConversionFeatures.samplerYcbcrConversion == VK_TRUE;
+
+            deviceInfos[i].supportsNvidiaDeviceDiagnosticCheckpoints =
+                deviceDiagnosticsConfigFeatures.diagnosticsConfig == VK_TRUE;
+
 #if defined(__QNX__)
             deviceInfos[i].supportsExternalMemoryImport =
                 extMemScreenBufferFeatures.screenBufferImport == VK_TRUE;
@@ -1119,6 +1148,7 @@
                 });
         vk_append_struct(&deviceCiChain, samplerYcbcrConversionFeatures.get());
     }
+
 #if defined(__QNX__)
     std::unique_ptr<VkPhysicalDeviceExternalMemoryScreenBufferFeaturesQNX>
         extMemScreenBufferFeaturesQNX = nullptr;
@@ -1134,6 +1164,25 @@
     }
 #endif
 
+    const bool commandBufferCheckpointsSupported =
+        sVkEmulation->deviceInfo.supportsNvidiaDeviceDiagnosticCheckpoints;
+    const bool commandBufferCheckpointsRequested =
+        sVkEmulation->features.VulkanCommandBufferCheckpoints.enabled;
+    const bool commandBufferCheckpointsSupportedAndRequested =
+        commandBufferCheckpointsSupported && commandBufferCheckpointsRequested;
+    VkPhysicalDeviceDiagnosticsConfigFeaturesNV deviceDiagnosticsConfigFeatures = {
+        .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DIAGNOSTICS_CONFIG_FEATURES_NV,
+        .diagnosticsConfig = VK_TRUE,
+    };
+    if (commandBufferCheckpointsSupportedAndRequested) {
+        INFO("Enabling command buffer checkpoints with VK_NV_device_diagnostic_checkpoints.");
+        vk_append_struct(&deviceCiChain, &deviceDiagnosticsConfigFeatures);
+    } else if (commandBufferCheckpointsRequested) {
+        WARN(
+            "VulkanCommandBufferCheckpoints was requested but the "
+            "VK_NV_device_diagnostic_checkpoints extension is not supported.");
+    }
+
     ivk->vkCreateDevice(sVkEmulation->physdev, &dCi, nullptr, &sVkEmulation->device);
 
     if (res != VK_SUCCESS) {
@@ -1327,8 +1376,8 @@
                                              string_VkResult(stagingBufferBindRes));
     }
 
-    sVkEmulation->debugUtilsAvailableAndRequested = debugUtilsAvailableAndRequested;
-    if (sVkEmulation->debugUtilsAvailableAndRequested) {
+    if (debugUtilsAvailableAndRequested) {
+        sVkEmulation->debugUtilsAvailableAndRequested = true;
         sVkEmulation->debugUtilsHelper =
             DebugUtilsHelper::withUtilsEnabled(sVkEmulation->device, sVkEmulation->ivk);
 
@@ -1340,6 +1389,11 @@
                                                      "AEMU_CommandBuffer");
     }
 
+    if (commandBufferCheckpointsSupportedAndRequested) {
+        sVkEmulation->commandBufferCheckpointsSupportedAndRequested = true;
+        sVkEmulation->deviceLostHelper.enableWithNvidiaDeviceDiagnosticCheckpoints();
+    }
+
     VERBOSE("Vulkan global emulation state successfully initialized.");
     sVkEmulation->live = true;
 
@@ -1452,6 +1506,8 @@
     sVkEmulation = nullptr;
 }
 
+void onVkDeviceLost() { VkDecoderGlobalState::get()->on_DeviceLost(); }
+
 std::unique_ptr<gfxstream::DisplaySurface> createDisplaySurface(FBNativeWindowType window,
                                                                 uint32_t width, uint32_t height) {
     if (!sVkEmulation || !sVkEmulation->live) {
@@ -2434,8 +2490,7 @@
     AutoLock lock(sVkEmulationLock);
 
     const auto& deviceInfo = sVkEmulation->deviceInfo;
-    if ((!(deviceInfo.supportsExternalMemoryExport || !deviceInfo.supportsExternalMemoryImport)) ||
-        (!deviceInfo.glInteropSupported)) {
+    if (!deviceInfo.supportsExternalMemoryExport && deviceInfo.supportsExternalMemoryImport) {
         return std::nullopt;
     }
 
@@ -2444,6 +2499,11 @@
         return std::nullopt;
     }
 
+    if ((info->vulkanMode != VkEmulation::VulkanMode::VulkanOnly) &&
+        !deviceInfo.glInteropSupported) {
+        return std::nullopt;
+    }
+
     if (info->frameworkFormat != FRAMEWORK_FORMAT_GL_COMPATIBLE) {
         return std::nullopt;
     }
diff --git a/host/vulkan/VkCommonOperations.h b/host/vulkan/VkCommonOperations.h
index cb53bf2..43ebc91 100644
--- a/host/vulkan/VkCommonOperations.h
+++ b/host/vulkan/VkCommonOperations.h
@@ -26,6 +26,7 @@
 #include "BorrowedImageVk.h"
 #include "CompositorVk.h"
 #include "DebugUtilsHelper.h"
+#include "DeviceLostHelper.h"
 #include "DeviceOpTracker.h"
 #include "DisplayVk.h"
 #include "FrameworkFormats.h"
@@ -144,6 +145,7 @@
 
     bool instanceSupportsExternalMemoryCapabilities = false;
     bool instanceSupportsExternalSemaphoreCapabilities = false;
+    bool instanceSupportsExternalFenceCapabilities = false;
     bool instanceSupportsSurface = false;
     PFN_vkGetPhysicalDeviceImageFormatProperties2KHR getImageFormatProperties2Func = nullptr;
     PFN_vkGetPhysicalDeviceProperties2KHR getPhysicalDeviceProperties2Func = nullptr;
@@ -158,6 +160,9 @@
     bool debugUtilsAvailableAndRequested = false;
     DebugUtilsHelper debugUtilsHelper = DebugUtilsHelper::withUtilsDisabled();
 
+    bool commandBufferCheckpointsSupportedAndRequested = false;
+    DeviceLostHelper deviceLostHelper{};
+
     // Queue, command pool, and command buffer
     // for running commands to sync stuff system-wide.
     // TODO(b/197362803): Encapsulate host side VkQueue and the lock.
@@ -204,6 +209,8 @@
         bool hasSamplerYcbcrConversionExtension = false;
         bool supportsSamplerYcbcrConversion = false;
         bool glInteropSupported = false;
+        bool hasNvidiaDeviceDiagnosticCheckpointsExtension = false;
+        bool supportsNvidiaDeviceDiagnosticCheckpoints = false;
 
         std::vector<VkExtensionProperties> extensions;
 
@@ -453,6 +460,8 @@
 VkEmulation* getGlobalVkEmulation();
 void teardownGlobalVkEmulation();
 
+void onVkDeviceLost();
+
 std::unique_ptr<gfxstream::DisplaySurface> createDisplaySurface(FBNativeWindowType window,
                                                                 uint32_t width, uint32_t height);
 
diff --git a/host/vulkan/VkDecoder.cpp b/host/vulkan/VkDecoder.cpp
index 2d0a40e..5942c91 100644
--- a/host/vulkan/VkDecoder.cpp
+++ b/host/vulkan/VkDecoder.cpp
@@ -370,7 +370,9 @@
                                 uint64_t tmpval;
                                 memcpy(&tmpval, cgen_var_2_0_ptr + k * 8, sizeof(uint64_t));
                                 *(((VkPhysicalDevice*)pPhysicalDevices) + k) =
-                                    (VkPhysicalDevice)(VkPhysicalDevice)((VkPhysicalDevice)tmpval);
+                                    tmpval ? (VkPhysicalDevice)(VkPhysicalDevice)((
+                                                 VkPhysicalDevice)tmpval)
+                                           : VK_NULL_HANDLE;
                             }
                         }
                     }
@@ -2743,7 +2745,8 @@
                     for (uint32_t k = 0; k < ((fenceCount)); ++k) {
                         uint64_t tmpval;
                         memcpy(&tmpval, cgen_var_1_ptr + k * 8, sizeof(uint64_t));
-                        *(((VkFence*)pFences) + k) = (VkFence)unbox_VkFence((VkFence)tmpval);
+                        *(((VkFence*)pFences) + k) =
+                            tmpval ? (VkFence)unbox_VkFence((VkFence)tmpval) : VK_NULL_HANDLE;
                     }
                 }
                 if (m_logCalls) {
@@ -2840,7 +2843,8 @@
                     for (uint32_t k = 0; k < ((fenceCount)); ++k) {
                         uint64_t tmpval;
                         memcpy(&tmpval, cgen_var_1_ptr + k * 8, sizeof(uint64_t));
-                        *(((VkFence*)pFences) + k) = (VkFence)unbox_VkFence((VkFence)tmpval);
+                        *(((VkFence*)pFences) + k) =
+                            tmpval ? (VkFence)unbox_VkFence((VkFence)tmpval) : VK_NULL_HANDLE;
                     }
                 }
                 memcpy((VkBool32*)&waitAll, *readStreamPtrPtr, sizeof(VkBool32));
@@ -4479,7 +4483,8 @@
                         uint64_t tmpval;
                         memcpy(&tmpval, cgen_var_2_ptr + k * 8, sizeof(uint64_t));
                         *(((VkPipelineCache*)pSrcCaches) + k) =
-                            (VkPipelineCache)unbox_VkPipelineCache((VkPipelineCache)tmpval);
+                            tmpval ? (VkPipelineCache)unbox_VkPipelineCache((VkPipelineCache)tmpval)
+                                   : VK_NULL_HANDLE;
                     }
                 }
                 if (m_logCalls) {
@@ -4561,7 +4566,7 @@
                         uint64_t tmpval;
                         memcpy(&tmpval, cgen_var_3_ptr + k * 8, sizeof(uint64_t));
                         *(((VkPipeline*)pPipelines) + k) =
-                            (VkPipeline)(VkPipeline)((VkPipeline)tmpval);
+                            tmpval ? (VkPipeline)(VkPipeline)((VkPipeline)tmpval) : VK_NULL_HANDLE;
                     }
                 }
                 if (pCreateInfos) {
@@ -4672,7 +4677,7 @@
                         uint64_t tmpval;
                         memcpy(&tmpval, cgen_var_3_ptr + k * 8, sizeof(uint64_t));
                         *(((VkPipeline*)pPipelines) + k) =
-                            (VkPipeline)(VkPipeline)((VkPipeline)tmpval);
+                            tmpval ? (VkPipeline)(VkPipeline)((VkPipeline)tmpval) : VK_NULL_HANDLE;
                     }
                 }
                 if (pCreateInfos) {
@@ -5429,7 +5434,8 @@
                         uint64_t tmpval;
                         memcpy(&tmpval, cgen_var_1_ptr + k * 8, sizeof(uint64_t));
                         *(((VkDescriptorSet*)pDescriptorSets) + k) =
-                            (VkDescriptorSet)(VkDescriptorSet)((VkDescriptorSet)tmpval);
+                            tmpval ? (VkDescriptorSet)(VkDescriptorSet)((VkDescriptorSet)tmpval)
+                                   : VK_NULL_HANDLE;
                     }
                 }
                 if (pAllocateInfo) {
@@ -5518,7 +5524,8 @@
                             uint64_t tmpval;
                             memcpy(&tmpval, cgen_var_2_0_ptr + k * 8, sizeof(uint64_t));
                             *(((VkDescriptorSet*)pDescriptorSets) + k) =
-                                (VkDescriptorSet)(VkDescriptorSet)((VkDescriptorSet)tmpval);
+                                tmpval ? (VkDescriptorSet)(VkDescriptorSet)((VkDescriptorSet)tmpval)
+                                       : VK_NULL_HANDLE;
                         }
                     }
                 }
@@ -6164,7 +6171,8 @@
                         uint64_t tmpval;
                         memcpy(&tmpval, cgen_var_1_ptr + k * 8, sizeof(uint64_t));
                         *(((VkCommandBuffer*)pCommandBuffers) + k) =
-                            (VkCommandBuffer)(VkCommandBuffer)((VkCommandBuffer)tmpval);
+                            tmpval ? (VkCommandBuffer)(VkCommandBuffer)((VkCommandBuffer)tmpval)
+                                   : VK_NULL_HANDLE;
                     }
                 }
                 if (pAllocateInfo) {
@@ -6249,7 +6257,8 @@
                             uint64_t tmpval;
                             memcpy(&tmpval, cgen_var_2_0_ptr + k * 8, sizeof(uint64_t));
                             *(((VkCommandBuffer*)pCommandBuffers) + k) =
-                                (VkCommandBuffer)(VkCommandBuffer)((VkCommandBuffer)tmpval);
+                                tmpval ? (VkCommandBuffer)(VkCommandBuffer)((VkCommandBuffer)tmpval)
+                                       : VK_NULL_HANDLE;
                         }
                     }
                 }
@@ -6869,7 +6878,8 @@
                         uint64_t tmpval;
                         memcpy(&tmpval, cgen_var_2_ptr + k * 8, sizeof(uint64_t));
                         *(((VkDescriptorSet*)pDescriptorSets) + k) =
-                            (VkDescriptorSet)unbox_VkDescriptorSet((VkDescriptorSet)tmpval);
+                            tmpval ? (VkDescriptorSet)unbox_VkDescriptorSet((VkDescriptorSet)tmpval)
+                                   : VK_NULL_HANDLE;
                     }
                 }
                 memcpy((uint32_t*)&dynamicOffsetCount, *readStreamPtrPtr, sizeof(uint32_t));
@@ -6981,7 +6991,8 @@
                     for (uint32_t k = 0; k < ((bindingCount)); ++k) {
                         uint64_t tmpval;
                         memcpy(&tmpval, cgen_var_1_ptr + k * 8, sizeof(uint64_t));
-                        *(((VkBuffer*)pBuffers) + k) = (VkBuffer)unbox_VkBuffer((VkBuffer)tmpval);
+                        *(((VkBuffer*)pBuffers) + k) =
+                            tmpval ? (VkBuffer)unbox_VkBuffer((VkBuffer)tmpval) : VK_NULL_HANDLE;
                     }
                 }
                 vkReadStream->alloc((void**)&pOffsets,
@@ -8119,7 +8130,8 @@
                     for (uint32_t k = 0; k < ((eventCount)); ++k) {
                         uint64_t tmpval;
                         memcpy(&tmpval, cgen_var_1_ptr + k * 8, sizeof(uint64_t));
-                        *(((VkEvent*)pEvents) + k) = (VkEvent)unbox_VkEvent((VkEvent)tmpval);
+                        *(((VkEvent*)pEvents) + k) =
+                            tmpval ? (VkEvent)unbox_VkEvent((VkEvent)tmpval) : VK_NULL_HANDLE;
                     }
                 }
                 memcpy((VkPipelineStageFlags*)&srcStageMask, *readStreamPtrPtr,
@@ -8754,7 +8766,8 @@
                         uint64_t tmpval;
                         memcpy(&tmpval, cgen_var_1_ptr + k * 8, sizeof(uint64_t));
                         *(((VkCommandBuffer*)pCommandBuffers) + k) =
-                            (VkCommandBuffer)unbox_VkCommandBuffer((VkCommandBuffer)tmpval);
+                            tmpval ? (VkCommandBuffer)unbox_VkCommandBuffer((VkCommandBuffer)tmpval)
+                                   : VK_NULL_HANDLE;
                     }
                 }
                 if (m_logCalls) {
@@ -9076,14 +9089,11 @@
                 VkInstance instance;
                 uint32_t* pPhysicalDeviceGroupCount;
                 VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties;
-                // Begin non wrapped dispatchable handle unboxing for instance;
+                // Begin global wrapped dispatchable handle unboxing for instance;
                 uint64_t cgen_var_0;
                 memcpy((uint64_t*)&cgen_var_0, *readStreamPtrPtr, 1 * 8);
                 *readStreamPtrPtr += 1 * 8;
                 *(VkInstance*)&instance = (VkInstance)(VkInstance)((VkInstance)(*&cgen_var_0));
-                auto unboxed_instance = unbox_VkInstance(instance);
-                auto vk = dispatch_VkInstance(instance);
-                // End manual dispatchable handle unboxing for instance;
                 // Begin manual dispatchable handle unboxing for pPhysicalDeviceGroupCount;
                 vkReadStream->unsetHandleMapping();
                 // WARNING PTR CHECK
@@ -9134,8 +9144,9 @@
                 }
                 VkResult vkEnumeratePhysicalDeviceGroups_VkResult_return = (VkResult)0;
                 vkEnumeratePhysicalDeviceGroups_VkResult_return =
-                    vk->vkEnumeratePhysicalDeviceGroups(unboxed_instance, pPhysicalDeviceGroupCount,
-                                                        pPhysicalDeviceGroupProperties);
+                    m_state->on_vkEnumeratePhysicalDeviceGroups(&m_pool, instance,
+                                                                pPhysicalDeviceGroupCount,
+                                                                pPhysicalDeviceGroupProperties);
                 if ((vkEnumeratePhysicalDeviceGroups_VkResult_return) == VK_ERROR_DEVICE_LOST)
                     m_state->on_DeviceLost();
                 m_state->on_CheckOutOfMemory(vkEnumeratePhysicalDeviceGroups_VkResult_return,
@@ -11774,7 +11785,8 @@
                     for (uint32_t k = 0; k < ((eventCount)); ++k) {
                         uint64_t tmpval;
                         memcpy(&tmpval, cgen_var_1_ptr + k * 8, sizeof(uint64_t));
-                        *(((VkEvent*)pEvents) + k) = (VkEvent)unbox_VkEvent((VkEvent)tmpval);
+                        *(((VkEvent*)pEvents) + k) =
+                            tmpval ? (VkEvent)unbox_VkEvent((VkEvent)tmpval) : VK_NULL_HANDLE;
                     }
                 }
                 vkReadStream->alloc((void**)&pDependencyInfos,
@@ -12503,7 +12515,8 @@
                             uint64_t tmpval;
                             memcpy(&tmpval, cgen_var_1_0_ptr + k * 8, sizeof(uint64_t));
                             *(((VkBuffer*)pBuffers) + k) =
-                                (VkBuffer)unbox_VkBuffer((VkBuffer)tmpval);
+                                tmpval ? (VkBuffer)unbox_VkBuffer((VkBuffer)tmpval)
+                                       : VK_NULL_HANDLE;
                         }
                     }
                 }
@@ -13146,8 +13159,6 @@
                 break;
             }
 #endif
-#ifdef VK_KHR_surface
-#endif
 #ifdef VK_KHR_swapchain
             case OP_vkCreateSwapchainKHR: {
                 android::base::beginTrace("vkCreateSwapchainKHR decode");
@@ -13339,7 +13350,7 @@
                                 uint64_t tmpval;
                                 memcpy(&tmpval, cgen_var_3_0_ptr + k * 8, sizeof(uint64_t));
                                 *(((VkImage*)pSwapchainImages) + k) =
-                                    (VkImage)(VkImage)((VkImage)tmpval);
+                                    tmpval ? (VkImage)(VkImage)((VkImage)tmpval) : VK_NULL_HANDLE;
                             }
                         }
                     }
@@ -13820,12 +13831,6 @@
                 break;
             }
 #endif
-#ifdef VK_KHR_xcb_surface
-#endif
-#ifdef VK_KHR_android_surface
-#endif
-#ifdef VK_KHR_win32_surface
-#endif
 #ifdef VK_KHR_dynamic_rendering
             case OP_vkCmdBeginRenderingKHR: {
                 android::base::beginTrace("vkCmdBeginRenderingKHR decode");
@@ -14514,12 +14519,6 @@
                 break;
             }
 #endif
-#ifdef VK_KHR_external_memory
-#endif
-#ifdef VK_KHR_external_memory_win32
-#endif
-#ifdef VK_KHR_external_memory_fd
-#endif
 #ifdef VK_KHR_external_semaphore_capabilities
             case OP_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR: {
                 android::base::beginTrace(
@@ -14589,10 +14588,6 @@
                 break;
             }
 #endif
-#ifdef VK_KHR_external_semaphore
-#endif
-#ifdef VK_KHR_external_semaphore_win32
-#endif
 #ifdef VK_KHR_external_semaphore_fd
             case OP_vkImportSemaphoreFdKHR: {
                 android::base::beginTrace("vkImportSemaphoreFdKHR decode");
@@ -14694,10 +14689,6 @@
                 break;
             }
 #endif
-#ifdef VK_KHR_shader_float16_int8
-#endif
-#ifdef VK_KHR_incremental_present
-#endif
 #ifdef VK_KHR_descriptor_update_template
             case OP_vkCreateDescriptorUpdateTemplateKHR: {
                 android::base::beginTrace("vkCreateDescriptorUpdateTemplateKHR decode");
@@ -14911,8 +14902,6 @@
                 break;
             }
 #endif
-#ifdef VK_KHR_imageless_framebuffer
-#endif
 #ifdef VK_KHR_create_renderpass2
             case OP_vkCreateRenderPass2KHR: {
                 android::base::beginTrace("vkCreateRenderPass2KHR decode");
@@ -15210,8 +15199,6 @@
                 break;
             }
 #endif
-#ifdef VK_KHR_external_fence
-#endif
 #ifdef VK_KHR_external_fence_fd
             case OP_vkImportFenceFdKHR: {
                 android::base::beginTrace("vkImportFenceFdKHR decode");
@@ -15317,12 +15304,6 @@
                 break;
             }
 #endif
-#ifdef VK_KHR_maintenance2
-#endif
-#ifdef VK_KHR_dedicated_allocation
-#endif
-#ifdef VK_KHR_storage_buffer_storage_class
-#endif
 #ifdef VK_KHR_get_memory_requirements2
             case OP_vkGetImageMemoryRequirements2KHR: {
                 android::base::beginTrace("vkGetImageMemoryRequirements2KHR decode");
@@ -15562,8 +15543,6 @@
                 break;
             }
 #endif
-#ifdef VK_KHR_image_format_list
-#endif
 #ifdef VK_KHR_sampler_ycbcr_conversion
             case OP_vkCreateSamplerYcbcrConversionKHR: {
                 android::base::beginTrace("vkCreateSamplerYcbcrConversionKHR decode");
@@ -15888,12 +15867,6 @@
                 break;
             }
 #endif
-#ifdef VK_KHR_shader_subgroup_extended_types
-#endif
-#ifdef VK_KHR_vulkan_memory_model
-#endif
-#ifdef VK_KHR_shader_terminate_invocation
-#endif
 #ifdef VK_KHR_buffer_device_address
             case OP_vkGetBufferDeviceAddressKHR: {
                 android::base::beginTrace("vkGetBufferDeviceAddressKHR decode");
@@ -16409,10 +16382,6 @@
                 break;
             }
 #endif
-#ifdef VK_KHR_shader_integer_dot_product
-#endif
-#ifdef VK_KHR_shader_non_semantic_info
-#endif
 #ifdef VK_KHR_synchronization2
             case OP_vkCmdSetEvent2KHR: {
                 android::base::beginTrace("vkCmdSetEvent2KHR decode");
@@ -16527,7 +16496,8 @@
                     for (uint32_t k = 0; k < ((eventCount)); ++k) {
                         uint64_t tmpval;
                         memcpy(&tmpval, cgen_var_1_ptr + k * 8, sizeof(uint64_t));
-                        *(((VkEvent*)pEvents) + k) = (VkEvent)unbox_VkEvent((VkEvent)tmpval);
+                        *(((VkEvent*)pEvents) + k) =
+                            tmpval ? (VkEvent)unbox_VkEvent((VkEvent)tmpval) : VK_NULL_HANDLE;
                     }
                 }
                 vkReadStream->alloc((void**)&pDependencyInfos,
@@ -16869,8 +16839,6 @@
                 break;
             }
 #endif
-#ifdef VK_KHR_zero_initialize_workgroup_memory
-#endif
 #ifdef VK_KHR_copy_commands2
             case OP_vkCmdCopyBuffer2KHR: {
                 android::base::beginTrace("vkCmdCopyBuffer2KHR decode");
@@ -17114,8 +17082,6 @@
                 break;
             }
 #endif
-#ifdef VK_KHR_format_feature_flags2
-#endif
 #ifdef VK_KHR_maintenance4
             case OP_vkGetDeviceBufferMemoryRequirementsKHR: {
                 android::base::beginTrace("vkGetDeviceBufferMemoryRequirementsKHR decode");
@@ -17744,7 +17710,8 @@
                             uint64_t tmpval;
                             memcpy(&tmpval, cgen_var_1_0_ptr + k * 8, sizeof(uint64_t));
                             *(((VkSemaphore*)pWaitSemaphores) + k) =
-                                (VkSemaphore)unbox_VkSemaphore((VkSemaphore)tmpval);
+                                tmpval ? (VkSemaphore)unbox_VkSemaphore((VkSemaphore)tmpval)
+                                       : VK_NULL_HANDLE;
                         }
                     }
                 }
@@ -18108,7 +18075,8 @@
                     for (uint32_t k = 0; k < ((bindingCount)); ++k) {
                         uint64_t tmpval;
                         memcpy(&tmpval, cgen_var_1_ptr + k * 8, sizeof(uint64_t));
-                        *(((VkBuffer*)pBuffers) + k) = (VkBuffer)unbox_VkBuffer((VkBuffer)tmpval);
+                        *(((VkBuffer*)pBuffers) + k) =
+                            tmpval ? (VkBuffer)unbox_VkBuffer((VkBuffer)tmpval) : VK_NULL_HANDLE;
                     }
                 }
                 vkReadStream->alloc((void**)&pOffsets,
@@ -18187,7 +18155,8 @@
                             uint64_t tmpval;
                             memcpy(&tmpval, cgen_var_1_0_ptr + k * 8, sizeof(uint64_t));
                             *(((VkBuffer*)pCounterBuffers) + k) =
-                                (VkBuffer)unbox_VkBuffer((VkBuffer)tmpval);
+                                tmpval ? (VkBuffer)unbox_VkBuffer((VkBuffer)tmpval)
+                                       : VK_NULL_HANDLE;
                         }
                     }
                 }
@@ -18265,7 +18234,8 @@
                             uint64_t tmpval;
                             memcpy(&tmpval, cgen_var_1_0_ptr + k * 8, sizeof(uint64_t));
                             *(((VkBuffer*)pCounterBuffers) + k) =
-                                (VkBuffer)unbox_VkBuffer((VkBuffer)tmpval);
+                                tmpval ? (VkBuffer)unbox_VkBuffer((VkBuffer)tmpval)
+                                       : VK_NULL_HANDLE;
                         }
                     }
                 }
@@ -18472,16 +18442,6 @@
                 break;
             }
 #endif
-#ifdef VK_AMD_gpu_shader_half_float
-#endif
-#ifdef VK_EXT_texture_compression_astc_hdr
-#endif
-#ifdef VK_EXT_depth_clip_enable
-#endif
-#ifdef VK_EXT_swapchain_colorspace
-#endif
-#ifdef VK_EXT_queue_family_foreign
-#endif
 #ifdef VK_EXT_debug_utils
             case OP_vkSetDebugUtilsObjectNameEXT: {
                 android::base::beginTrace("vkSetDebugUtilsObjectNameEXT decode");
@@ -19010,26 +18970,6 @@
                 break;
             }
 #endif
-#ifdef VK_ANDROID_external_memory_android_hardware_buffer
-#endif
-#ifdef VK_EXT_inline_uniform_block
-#endif
-#ifdef VK_EXT_shader_stencil_export
-#endif
-#ifdef VK_EXT_vertex_attribute_divisor
-#endif
-#ifdef VK_EXT_pipeline_creation_feedback
-#endif
-#ifdef VK_NV_shader_subgroup_partitioned
-#endif
-#ifdef VK_EXT_metal_surface
-#endif
-#ifdef VK_EXT_fragment_density_map
-#endif
-#ifdef VK_EXT_scalar_block_layout
-#endif
-#ifdef VK_EXT_subgroup_size_control
-#endif
 #ifdef VK_EXT_tooling_info
             case OP_vkGetPhysicalDeviceToolPropertiesEXT: {
                 android::base::beginTrace("vkGetPhysicalDeviceToolPropertiesEXT decode");
@@ -19141,10 +19081,6 @@
                 break;
             }
 #endif
-#ifdef VK_EXT_validation_features
-#endif
-#ifdef VK_EXT_provoking_vertex
-#endif
 #ifdef VK_EXT_line_rasterization
             case OP_vkCmdSetLineStippleEXT: {
                 android::base::beginTrace("vkCmdSetLineStippleEXT decode");
@@ -19189,8 +19125,6 @@
                 break;
             }
 #endif
-#ifdef VK_EXT_index_type_uint8
-#endif
 #ifdef VK_EXT_extended_dynamic_state
             case OP_vkCmdSetCullModeEXT: {
                 android::base::beginTrace("vkCmdSetCullModeEXT decode");
@@ -19432,7 +19366,8 @@
                             uint64_t tmpval;
                             memcpy(&tmpval, cgen_var_1_0_ptr + k * 8, sizeof(uint64_t));
                             *(((VkBuffer*)pBuffers) + k) =
-                                (VkBuffer)unbox_VkBuffer((VkBuffer)tmpval);
+                                tmpval ? (VkBuffer)unbox_VkBuffer((VkBuffer)tmpval)
+                                       : VK_NULL_HANDLE;
                         }
                     }
                 }
@@ -20054,16 +19989,6 @@
                 break;
             }
 #endif
-#ifdef VK_EXT_shader_demote_to_helper_invocation
-#endif
-#ifdef VK_EXT_texel_buffer_alignment
-#endif
-#ifdef VK_EXT_device_memory_report
-#endif
-#ifdef VK_EXT_robustness2
-#endif
-#ifdef VK_EXT_custom_border_color
-#endif
 #ifdef VK_EXT_private_data
             case OP_vkCreatePrivateDataSlotEXT: {
                 android::base::beginTrace("vkCreatePrivateDataSlotEXT decode");
@@ -20305,22 +20230,6 @@
                 break;
             }
 #endif
-#ifdef VK_EXT_pipeline_creation_cache_control
-#endif
-#ifdef VK_EXT_metal_objects
-#endif
-#ifdef VK_EXT_graphics_pipeline_library
-#endif
-#ifdef VK_EXT_ycbcr_2plane_444_formats
-#endif
-#ifdef VK_EXT_image_robustness
-#endif
-#ifdef VK_EXT_image_compression_control
-#endif
-#ifdef VK_EXT_4444_formats
-#endif
-#ifdef VK_EXT_primitive_topology_list_restart
-#endif
 #ifdef VK_EXT_extended_dynamic_state2
             case OP_vkCmdSetPatchControlPointsEXT: {
                 android::base::beginTrace("vkCmdSetPatchControlPointsEXT decode");
@@ -20729,7 +20638,8 @@
                             uint64_t tmpval;
                             memcpy(&tmpval, cgen_var_8_0_ptr + k * 8, sizeof(uint64_t));
                             *(((VkBufferView*)pBufferViews) + k) =
-                                (VkBufferView)unbox_VkBufferView((VkBufferView)tmpval);
+                                tmpval ? (VkBufferView)unbox_VkBufferView((VkBufferView)tmpval)
+                                       : VK_NULL_HANDLE;
                         }
                     }
                 }
@@ -21639,7 +21549,9 @@
                         uint64_t tmpval;
                         memcpy(&tmpval, cgen_var_1_ptr + k * 8, sizeof(uint64_t));
                         *(((VkDescriptorPool*)pDescriptorPools) + k) =
-                            (VkDescriptorPool)unbox_VkDescriptorPool((VkDescriptorPool)tmpval);
+                            tmpval
+                                ? (VkDescriptorPool)unbox_VkDescriptorPool((VkDescriptorPool)tmpval)
+                                : VK_NULL_HANDLE;
                     }
                 }
                 memcpy((uint32_t*)&descriptorSetCount, *readStreamPtrPtr, sizeof(uint32_t));
@@ -21653,8 +21565,9 @@
                         uint64_t tmpval;
                         memcpy(&tmpval, cgen_var_2_ptr + k * 8, sizeof(uint64_t));
                         *(((VkDescriptorSetLayout*)pSetLayouts) + k) =
-                            (VkDescriptorSetLayout)unbox_VkDescriptorSetLayout(
-                                (VkDescriptorSetLayout)tmpval);
+                            tmpval ? (VkDescriptorSetLayout)unbox_VkDescriptorSetLayout(
+                                         (VkDescriptorSetLayout)tmpval)
+                                   : VK_NULL_HANDLE;
                     }
                 }
                 vkReadStream->alloc((void**)&pDescriptorSetPoolIds,
@@ -21825,7 +21738,8 @@
                             uint64_t tmpval;
                             memcpy(&tmpval, cgen_var_1_0_ptr + k * 8, sizeof(uint64_t));
                             *(((VkSemaphore*)pWaitSemaphores) + k) =
-                                (VkSemaphore)unbox_VkSemaphore((VkSemaphore)tmpval);
+                                tmpval ? (VkSemaphore)unbox_VkSemaphore((VkSemaphore)tmpval)
+                                       : VK_NULL_HANDLE;
                         }
                     }
                 }
@@ -22064,7 +21978,8 @@
                             uint64_t tmpval;
                             memcpy(&tmpval, cgen_var_8_0_ptr + k * 8, sizeof(uint64_t));
                             *(((VkBufferView*)pBufferViews) + k) =
-                                (VkBufferView)unbox_VkBufferView((VkBufferView)tmpval);
+                                tmpval ? (VkBufferView)unbox_VkBufferView((VkBufferView)tmpval)
+                                       : VK_NULL_HANDLE;
                         }
                     }
                 }
@@ -22183,12 +22098,511 @@
                 android::base::endTrace();
                 break;
             }
+            case OP_vkGetSemaphoreGOOGLE: {
+                android::base::beginTrace("vkGetSemaphoreGOOGLE decode");
+                VkDevice device;
+                VkSemaphore semaphore;
+                uint64_t syncId;
+                // Begin global wrapped dispatchable handle unboxing for device;
+                uint64_t cgen_var_0;
+                memcpy((uint64_t*)&cgen_var_0, *readStreamPtrPtr, 1 * 8);
+                *readStreamPtrPtr += 1 * 8;
+                *(VkDevice*)&device = (VkDevice)(VkDevice)((VkDevice)(*&cgen_var_0));
+                uint64_t cgen_var_1;
+                memcpy((uint64_t*)&cgen_var_1, *readStreamPtrPtr, 1 * 8);
+                *readStreamPtrPtr += 1 * 8;
+                *(VkSemaphore*)&semaphore =
+                    (VkSemaphore)unbox_VkSemaphore((VkSemaphore)(*&cgen_var_1));
+                memcpy((uint64_t*)&syncId, *readStreamPtrPtr, sizeof(uint64_t));
+                *readStreamPtrPtr += sizeof(uint64_t);
+                if (m_logCalls) {
+                    fprintf(stderr, "stream %p: call vkGetSemaphoreGOOGLE 0x%llx 0x%llx 0x%llx \n",
+                            ioStream, (unsigned long long)device, (unsigned long long)semaphore,
+                            (unsigned long long)syncId);
+                }
+                VkResult vkGetSemaphoreGOOGLE_VkResult_return = (VkResult)0;
+                vkGetSemaphoreGOOGLE_VkResult_return =
+                    m_state->on_vkGetSemaphoreGOOGLE(&m_pool, device, semaphore, syncId);
+                if ((vkGetSemaphoreGOOGLE_VkResult_return) == VK_ERROR_DEVICE_LOST)
+                    m_state->on_DeviceLost();
+                m_state->on_CheckOutOfMemory(vkGetSemaphoreGOOGLE_VkResult_return, opcode, context);
+                vkStream->unsetHandleMapping();
+                vkStream->write(&vkGetSemaphoreGOOGLE_VkResult_return, sizeof(VkResult));
+                vkStream->commitWrite();
+                vkReadStream->setReadPos((uintptr_t)(*readStreamPtrPtr) -
+                                         (uintptr_t)snapshotTraceBegin);
+                size_t snapshotTraceBytes = vkReadStream->endTrace();
+                if (m_state->snapshotsEnabled()) {
+                    m_state->snapshot()->vkGetSemaphoreGOOGLE(
+                        snapshotTraceBegin, snapshotTraceBytes, &m_pool,
+                        vkGetSemaphoreGOOGLE_VkResult_return, device, semaphore, syncId);
+                }
+                vkReadStream->clearPool();
+                if (m_queueSubmitWithCommandsEnabled)
+                    seqnoPtr->fetch_add(1, std::memory_order_seq_cst);
+                android::base::endTrace();
+                break;
+            }
 #endif
-#ifdef VK_EXT_load_store_op_none
-#endif
-#ifdef VK_EXT_image_compression_control_swapchain
-#endif
-#ifdef VK_QNX_external_memory_screen_buffer
+#ifdef VK_KHR_ray_tracing_pipeline
+            case OP_vkCmdTraceRaysKHR: {
+                android::base::beginTrace("vkCmdTraceRaysKHR decode");
+                VkCommandBuffer commandBuffer;
+                const VkStridedDeviceAddressRegionKHR* pRaygenShaderBindingTable;
+                const VkStridedDeviceAddressRegionKHR* pMissShaderBindingTable;
+                const VkStridedDeviceAddressRegionKHR* pHitShaderBindingTable;
+                const VkStridedDeviceAddressRegionKHR* pCallableShaderBindingTable;
+                uint32_t width;
+                uint32_t height;
+                uint32_t depth;
+                // Begin non wrapped dispatchable handle unboxing for commandBuffer;
+                uint64_t cgen_var_0;
+                memcpy((uint64_t*)&cgen_var_0, *readStreamPtrPtr, 1 * 8);
+                *readStreamPtrPtr += 1 * 8;
+                *(VkCommandBuffer*)&commandBuffer =
+                    (VkCommandBuffer)(VkCommandBuffer)((VkCommandBuffer)(*&cgen_var_0));
+                auto unboxed_commandBuffer = unbox_VkCommandBuffer(commandBuffer);
+                auto vk = dispatch_VkCommandBuffer(commandBuffer);
+                // End manual dispatchable handle unboxing for commandBuffer;
+                vkReadStream->alloc((void**)&pRaygenShaderBindingTable,
+                                    sizeof(const VkStridedDeviceAddressRegionKHR));
+                reservedunmarshal_VkStridedDeviceAddressRegionKHR(
+                    vkReadStream, VK_STRUCTURE_TYPE_MAX_ENUM,
+                    (VkStridedDeviceAddressRegionKHR*)(pRaygenShaderBindingTable),
+                    readStreamPtrPtr);
+                vkReadStream->alloc((void**)&pMissShaderBindingTable,
+                                    sizeof(const VkStridedDeviceAddressRegionKHR));
+                reservedunmarshal_VkStridedDeviceAddressRegionKHR(
+                    vkReadStream, VK_STRUCTURE_TYPE_MAX_ENUM,
+                    (VkStridedDeviceAddressRegionKHR*)(pMissShaderBindingTable), readStreamPtrPtr);
+                vkReadStream->alloc((void**)&pHitShaderBindingTable,
+                                    sizeof(const VkStridedDeviceAddressRegionKHR));
+                reservedunmarshal_VkStridedDeviceAddressRegionKHR(
+                    vkReadStream, VK_STRUCTURE_TYPE_MAX_ENUM,
+                    (VkStridedDeviceAddressRegionKHR*)(pHitShaderBindingTable), readStreamPtrPtr);
+                vkReadStream->alloc((void**)&pCallableShaderBindingTable,
+                                    sizeof(const VkStridedDeviceAddressRegionKHR));
+                reservedunmarshal_VkStridedDeviceAddressRegionKHR(
+                    vkReadStream, VK_STRUCTURE_TYPE_MAX_ENUM,
+                    (VkStridedDeviceAddressRegionKHR*)(pCallableShaderBindingTable),
+                    readStreamPtrPtr);
+                memcpy((uint32_t*)&width, *readStreamPtrPtr, sizeof(uint32_t));
+                *readStreamPtrPtr += sizeof(uint32_t);
+                memcpy((uint32_t*)&height, *readStreamPtrPtr, sizeof(uint32_t));
+                *readStreamPtrPtr += sizeof(uint32_t);
+                memcpy((uint32_t*)&depth, *readStreamPtrPtr, sizeof(uint32_t));
+                *readStreamPtrPtr += sizeof(uint32_t);
+                if (pRaygenShaderBindingTable) {
+                    transform_tohost_VkStridedDeviceAddressRegionKHR(
+                        m_state, (VkStridedDeviceAddressRegionKHR*)(pRaygenShaderBindingTable));
+                }
+                if (pMissShaderBindingTable) {
+                    transform_tohost_VkStridedDeviceAddressRegionKHR(
+                        m_state, (VkStridedDeviceAddressRegionKHR*)(pMissShaderBindingTable));
+                }
+                if (pHitShaderBindingTable) {
+                    transform_tohost_VkStridedDeviceAddressRegionKHR(
+                        m_state, (VkStridedDeviceAddressRegionKHR*)(pHitShaderBindingTable));
+                }
+                if (pCallableShaderBindingTable) {
+                    transform_tohost_VkStridedDeviceAddressRegionKHR(
+                        m_state, (VkStridedDeviceAddressRegionKHR*)(pCallableShaderBindingTable));
+                }
+                if (m_logCalls) {
+                    fprintf(stderr,
+                            "stream %p: call vkCmdTraceRaysKHR 0x%llx 0x%llx 0x%llx 0x%llx 0x%llx "
+                            "0x%llx 0x%llx 0x%llx \n",
+                            ioStream, (unsigned long long)commandBuffer,
+                            (unsigned long long)pRaygenShaderBindingTable,
+                            (unsigned long long)pMissShaderBindingTable,
+                            (unsigned long long)pHitShaderBindingTable,
+                            (unsigned long long)pCallableShaderBindingTable,
+                            (unsigned long long)width, (unsigned long long)height,
+                            (unsigned long long)depth);
+                }
+                vk->vkCmdTraceRaysKHR(unboxed_commandBuffer, pRaygenShaderBindingTable,
+                                      pMissShaderBindingTable, pHitShaderBindingTable,
+                                      pCallableShaderBindingTable, width, height, depth);
+                vkStream->unsetHandleMapping();
+                vkReadStream->setReadPos((uintptr_t)(*readStreamPtrPtr) -
+                                         (uintptr_t)snapshotTraceBegin);
+                size_t snapshotTraceBytes = vkReadStream->endTrace();
+                if (m_state->snapshotsEnabled()) {
+                    m_state->snapshot()->vkCmdTraceRaysKHR(
+                        snapshotTraceBegin, snapshotTraceBytes, &m_pool, commandBuffer,
+                        pRaygenShaderBindingTable, pMissShaderBindingTable, pHitShaderBindingTable,
+                        pCallableShaderBindingTable, width, height, depth);
+                }
+                vkReadStream->clearPool();
+                if (m_queueSubmitWithCommandsEnabled)
+                    seqnoPtr->fetch_add(1, std::memory_order_seq_cst);
+                android::base::endTrace();
+                break;
+            }
+            case OP_vkCreateRayTracingPipelinesKHR: {
+                android::base::beginTrace("vkCreateRayTracingPipelinesKHR decode");
+                VkDevice device;
+                VkDeferredOperationKHR deferredOperation;
+                VkPipelineCache pipelineCache;
+                uint32_t createInfoCount;
+                const VkRayTracingPipelineCreateInfoKHR* pCreateInfos;
+                const VkAllocationCallbacks* pAllocator;
+                VkPipeline* pPipelines;
+                // Begin non wrapped dispatchable handle unboxing for device;
+                uint64_t cgen_var_0;
+                memcpy((uint64_t*)&cgen_var_0, *readStreamPtrPtr, 1 * 8);
+                *readStreamPtrPtr += 1 * 8;
+                *(VkDevice*)&device = (VkDevice)(VkDevice)((VkDevice)(*&cgen_var_0));
+                auto unboxed_device = unbox_VkDevice(device);
+                auto vk = dispatch_VkDevice(device);
+                // End manual dispatchable handle unboxing for device;
+                memcpy((VkDeferredOperationKHR*)&deferredOperation, (*readStreamPtrPtr), 8);
+                android::base::Stream::fromBe64((uint8_t*)&deferredOperation);
+                *readStreamPtrPtr += 8;
+                uint64_t cgen_var_2;
+                memcpy((uint64_t*)&cgen_var_2, *readStreamPtrPtr, 1 * 8);
+                *readStreamPtrPtr += 1 * 8;
+                *(VkPipelineCache*)&pipelineCache =
+                    (VkPipelineCache)unbox_VkPipelineCache((VkPipelineCache)(*&cgen_var_2));
+                memcpy((uint32_t*)&createInfoCount, *readStreamPtrPtr, sizeof(uint32_t));
+                *readStreamPtrPtr += sizeof(uint32_t);
+                vkReadStream->alloc(
+                    (void**)&pCreateInfos,
+                    ((createInfoCount)) * sizeof(const VkRayTracingPipelineCreateInfoKHR));
+                for (uint32_t i = 0; i < (uint32_t)((createInfoCount)); ++i) {
+                    reservedunmarshal_VkRayTracingPipelineCreateInfoKHR(
+                        vkReadStream, VK_STRUCTURE_TYPE_MAX_ENUM,
+                        (VkRayTracingPipelineCreateInfoKHR*)(pCreateInfos + i), readStreamPtrPtr);
+                }
+                // WARNING PTR CHECK
+                memcpy((VkAllocationCallbacks**)&pAllocator, (*readStreamPtrPtr), 8);
+                android::base::Stream::fromBe64((uint8_t*)&pAllocator);
+                *readStreamPtrPtr += 8;
+                if (pAllocator) {
+                    vkReadStream->alloc((void**)&pAllocator, sizeof(const VkAllocationCallbacks));
+                    reservedunmarshal_VkAllocationCallbacks(
+                        vkReadStream, VK_STRUCTURE_TYPE_MAX_ENUM,
+                        (VkAllocationCallbacks*)(pAllocator), readStreamPtrPtr);
+                }
+                // Begin manual dispatchable handle unboxing for pPipelines;
+                vkReadStream->unsetHandleMapping();
+                vkReadStream->alloc((void**)&pPipelines, ((createInfoCount)) * sizeof(VkPipeline));
+                if (((createInfoCount))) {
+                    uint8_t* cgen_var_4_ptr = (uint8_t*)(*readStreamPtrPtr);
+                    *readStreamPtrPtr += 8 * ((createInfoCount));
+                    for (uint32_t k = 0; k < ((createInfoCount)); ++k) {
+                        uint64_t tmpval;
+                        memcpy(&tmpval, cgen_var_4_ptr + k * 8, sizeof(uint64_t));
+                        *(((VkPipeline*)pPipelines) + k) =
+                            tmpval ? (VkPipeline)(VkPipeline)((VkPipeline)tmpval) : VK_NULL_HANDLE;
+                    }
+                }
+                if (pCreateInfos) {
+                    for (uint32_t i = 0; i < (uint32_t)((createInfoCount)); ++i) {
+                        transform_tohost_VkRayTracingPipelineCreateInfoKHR(
+                            m_state, (VkRayTracingPipelineCreateInfoKHR*)(pCreateInfos + i));
+                    }
+                }
+                if (pAllocator) {
+                    transform_tohost_VkAllocationCallbacks(m_state,
+                                                           (VkAllocationCallbacks*)(pAllocator));
+                }
+                if (m_logCalls) {
+                    fprintf(stderr,
+                            "stream %p: call vkCreateRayTracingPipelinesKHR 0x%llx 0x%llx 0x%llx "
+                            "0x%llx 0x%llx 0x%llx 0x%llx \n",
+                            ioStream, (unsigned long long)device,
+                            (unsigned long long)deferredOperation,
+                            (unsigned long long)pipelineCache, (unsigned long long)createInfoCount,
+                            (unsigned long long)pCreateInfos, (unsigned long long)pAllocator,
+                            (unsigned long long)pPipelines);
+                }
+                VkResult vkCreateRayTracingPipelinesKHR_VkResult_return = (VkResult)0;
+                vkCreateRayTracingPipelinesKHR_VkResult_return = vk->vkCreateRayTracingPipelinesKHR(
+                    unboxed_device, deferredOperation, pipelineCache, createInfoCount, pCreateInfos,
+                    pAllocator, pPipelines);
+                if ((vkCreateRayTracingPipelinesKHR_VkResult_return) == VK_ERROR_DEVICE_LOST)
+                    m_state->on_DeviceLost();
+                m_state->on_CheckOutOfMemory(vkCreateRayTracingPipelinesKHR_VkResult_return, opcode,
+                                             context);
+                vkStream->unsetHandleMapping();
+                if (((createInfoCount))) {
+                    uint64_t* cgen_var_5;
+                    vkStream->alloc((void**)&cgen_var_5, ((createInfoCount)) * 8);
+                    vkStream->handleMapping()->mapHandles_VkPipeline_u64(pPipelines, cgen_var_5,
+                                                                         ((createInfoCount)));
+                    vkStream->write((uint64_t*)cgen_var_5, ((createInfoCount)) * 8);
+                }
+                vkStream->write(&vkCreateRayTracingPipelinesKHR_VkResult_return, sizeof(VkResult));
+                vkStream->commitWrite();
+                vkReadStream->setReadPos((uintptr_t)(*readStreamPtrPtr) -
+                                         (uintptr_t)snapshotTraceBegin);
+                size_t snapshotTraceBytes = vkReadStream->endTrace();
+                if (m_state->snapshotsEnabled()) {
+                    m_state->snapshot()->vkCreateRayTracingPipelinesKHR(
+                        snapshotTraceBegin, snapshotTraceBytes, &m_pool,
+                        vkCreateRayTracingPipelinesKHR_VkResult_return, device, deferredOperation,
+                        pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
+                }
+                vkReadStream->clearPool();
+                if (m_queueSubmitWithCommandsEnabled)
+                    seqnoPtr->fetch_add(1, std::memory_order_seq_cst);
+                android::base::endTrace();
+                break;
+            }
+            case OP_vkGetRayTracingCaptureReplayShaderGroupHandlesKHR: {
+                android::base::beginTrace(
+                    "vkGetRayTracingCaptureReplayShaderGroupHandlesKHR decode");
+                VkDevice device;
+                VkPipeline pipeline;
+                uint32_t firstGroup;
+                uint32_t groupCount;
+                size_t dataSize;
+                void* pData;
+                // Begin non wrapped dispatchable handle unboxing for device;
+                uint64_t cgen_var_0;
+                memcpy((uint64_t*)&cgen_var_0, *readStreamPtrPtr, 1 * 8);
+                *readStreamPtrPtr += 1 * 8;
+                *(VkDevice*)&device = (VkDevice)(VkDevice)((VkDevice)(*&cgen_var_0));
+                auto unboxed_device = unbox_VkDevice(device);
+                auto vk = dispatch_VkDevice(device);
+                // End manual dispatchable handle unboxing for device;
+                uint64_t cgen_var_1;
+                memcpy((uint64_t*)&cgen_var_1, *readStreamPtrPtr, 1 * 8);
+                *readStreamPtrPtr += 1 * 8;
+                *(VkPipeline*)&pipeline = (VkPipeline)unbox_VkPipeline((VkPipeline)(*&cgen_var_1));
+                memcpy((uint32_t*)&firstGroup, *readStreamPtrPtr, sizeof(uint32_t));
+                *readStreamPtrPtr += sizeof(uint32_t);
+                memcpy((uint32_t*)&groupCount, *readStreamPtrPtr, sizeof(uint32_t));
+                *readStreamPtrPtr += sizeof(uint32_t);
+                memcpy((size_t*)&dataSize, (*readStreamPtrPtr), 8);
+                android::base::Stream::fromBe64((uint8_t*)&dataSize);
+                *readStreamPtrPtr += 8;
+                // Begin manual dispatchable handle unboxing for pData;
+                vkReadStream->unsetHandleMapping();
+                vkReadStream->alloc((void**)&pData, ((dataSize)) * sizeof(uint8_t));
+                memcpy((void*)pData, *readStreamPtrPtr, ((dataSize)) * sizeof(uint8_t));
+                *readStreamPtrPtr += ((dataSize)) * sizeof(uint8_t);
+                if (m_logCalls) {
+                    fprintf(stderr,
+                            "stream %p: call vkGetRayTracingCaptureReplayShaderGroupHandlesKHR "
+                            "0x%llx 0x%llx 0x%llx 0x%llx 0x%llx 0x%llx \n",
+                            ioStream, (unsigned long long)device, (unsigned long long)pipeline,
+                            (unsigned long long)firstGroup, (unsigned long long)groupCount,
+                            (unsigned long long)dataSize, (unsigned long long)pData);
+                }
+                VkResult vkGetRayTracingCaptureReplayShaderGroupHandlesKHR_VkResult_return =
+                    (VkResult)0;
+                vkGetRayTracingCaptureReplayShaderGroupHandlesKHR_VkResult_return =
+                    vk->vkGetRayTracingCaptureReplayShaderGroupHandlesKHR(
+                        unboxed_device, pipeline, firstGroup, groupCount, dataSize, pData);
+                if ((vkGetRayTracingCaptureReplayShaderGroupHandlesKHR_VkResult_return) ==
+                    VK_ERROR_DEVICE_LOST)
+                    m_state->on_DeviceLost();
+                m_state->on_CheckOutOfMemory(
+                    vkGetRayTracingCaptureReplayShaderGroupHandlesKHR_VkResult_return, opcode,
+                    context);
+                vkStream->unsetHandleMapping();
+                vkStream->write((void*)pData, ((dataSize)) * sizeof(uint8_t));
+                vkStream->write(&vkGetRayTracingCaptureReplayShaderGroupHandlesKHR_VkResult_return,
+                                sizeof(VkResult));
+                vkStream->commitWrite();
+                vkReadStream->setReadPos((uintptr_t)(*readStreamPtrPtr) -
+                                         (uintptr_t)snapshotTraceBegin);
+                size_t snapshotTraceBytes = vkReadStream->endTrace();
+                if (m_state->snapshotsEnabled()) {
+                    m_state->snapshot()->vkGetRayTracingCaptureReplayShaderGroupHandlesKHR(
+                        snapshotTraceBegin, snapshotTraceBytes, &m_pool,
+                        vkGetRayTracingCaptureReplayShaderGroupHandlesKHR_VkResult_return, device,
+                        pipeline, firstGroup, groupCount, dataSize, pData);
+                }
+                vkReadStream->clearPool();
+                if (m_queueSubmitWithCommandsEnabled)
+                    seqnoPtr->fetch_add(1, std::memory_order_seq_cst);
+                android::base::endTrace();
+                break;
+            }
+            case OP_vkCmdTraceRaysIndirectKHR: {
+                android::base::beginTrace("vkCmdTraceRaysIndirectKHR decode");
+                VkCommandBuffer commandBuffer;
+                const VkStridedDeviceAddressRegionKHR* pRaygenShaderBindingTable;
+                const VkStridedDeviceAddressRegionKHR* pMissShaderBindingTable;
+                const VkStridedDeviceAddressRegionKHR* pHitShaderBindingTable;
+                const VkStridedDeviceAddressRegionKHR* pCallableShaderBindingTable;
+                VkDeviceAddress indirectDeviceAddress;
+                // Begin non wrapped dispatchable handle unboxing for commandBuffer;
+                uint64_t cgen_var_0;
+                memcpy((uint64_t*)&cgen_var_0, *readStreamPtrPtr, 1 * 8);
+                *readStreamPtrPtr += 1 * 8;
+                *(VkCommandBuffer*)&commandBuffer =
+                    (VkCommandBuffer)(VkCommandBuffer)((VkCommandBuffer)(*&cgen_var_0));
+                auto unboxed_commandBuffer = unbox_VkCommandBuffer(commandBuffer);
+                auto vk = dispatch_VkCommandBuffer(commandBuffer);
+                // End manual dispatchable handle unboxing for commandBuffer;
+                vkReadStream->alloc((void**)&pRaygenShaderBindingTable,
+                                    sizeof(const VkStridedDeviceAddressRegionKHR));
+                reservedunmarshal_VkStridedDeviceAddressRegionKHR(
+                    vkReadStream, VK_STRUCTURE_TYPE_MAX_ENUM,
+                    (VkStridedDeviceAddressRegionKHR*)(pRaygenShaderBindingTable),
+                    readStreamPtrPtr);
+                vkReadStream->alloc((void**)&pMissShaderBindingTable,
+                                    sizeof(const VkStridedDeviceAddressRegionKHR));
+                reservedunmarshal_VkStridedDeviceAddressRegionKHR(
+                    vkReadStream, VK_STRUCTURE_TYPE_MAX_ENUM,
+                    (VkStridedDeviceAddressRegionKHR*)(pMissShaderBindingTable), readStreamPtrPtr);
+                vkReadStream->alloc((void**)&pHitShaderBindingTable,
+                                    sizeof(const VkStridedDeviceAddressRegionKHR));
+                reservedunmarshal_VkStridedDeviceAddressRegionKHR(
+                    vkReadStream, VK_STRUCTURE_TYPE_MAX_ENUM,
+                    (VkStridedDeviceAddressRegionKHR*)(pHitShaderBindingTable), readStreamPtrPtr);
+                vkReadStream->alloc((void**)&pCallableShaderBindingTable,
+                                    sizeof(const VkStridedDeviceAddressRegionKHR));
+                reservedunmarshal_VkStridedDeviceAddressRegionKHR(
+                    vkReadStream, VK_STRUCTURE_TYPE_MAX_ENUM,
+                    (VkStridedDeviceAddressRegionKHR*)(pCallableShaderBindingTable),
+                    readStreamPtrPtr);
+                memcpy((VkDeviceAddress*)&indirectDeviceAddress, *readStreamPtrPtr,
+                       sizeof(VkDeviceAddress));
+                *readStreamPtrPtr += sizeof(VkDeviceAddress);
+                if (pRaygenShaderBindingTable) {
+                    transform_tohost_VkStridedDeviceAddressRegionKHR(
+                        m_state, (VkStridedDeviceAddressRegionKHR*)(pRaygenShaderBindingTable));
+                }
+                if (pMissShaderBindingTable) {
+                    transform_tohost_VkStridedDeviceAddressRegionKHR(
+                        m_state, (VkStridedDeviceAddressRegionKHR*)(pMissShaderBindingTable));
+                }
+                if (pHitShaderBindingTable) {
+                    transform_tohost_VkStridedDeviceAddressRegionKHR(
+                        m_state, (VkStridedDeviceAddressRegionKHR*)(pHitShaderBindingTable));
+                }
+                if (pCallableShaderBindingTable) {
+                    transform_tohost_VkStridedDeviceAddressRegionKHR(
+                        m_state, (VkStridedDeviceAddressRegionKHR*)(pCallableShaderBindingTable));
+                }
+                if (m_logCalls) {
+                    fprintf(stderr,
+                            "stream %p: call vkCmdTraceRaysIndirectKHR 0x%llx 0x%llx 0x%llx 0x%llx "
+                            "0x%llx 0x%llx \n",
+                            ioStream, (unsigned long long)commandBuffer,
+                            (unsigned long long)pRaygenShaderBindingTable,
+                            (unsigned long long)pMissShaderBindingTable,
+                            (unsigned long long)pHitShaderBindingTable,
+                            (unsigned long long)pCallableShaderBindingTable,
+                            (unsigned long long)indirectDeviceAddress);
+                }
+                vk->vkCmdTraceRaysIndirectKHR(unboxed_commandBuffer, pRaygenShaderBindingTable,
+                                              pMissShaderBindingTable, pHitShaderBindingTable,
+                                              pCallableShaderBindingTable, indirectDeviceAddress);
+                vkStream->unsetHandleMapping();
+                vkReadStream->setReadPos((uintptr_t)(*readStreamPtrPtr) -
+                                         (uintptr_t)snapshotTraceBegin);
+                size_t snapshotTraceBytes = vkReadStream->endTrace();
+                if (m_state->snapshotsEnabled()) {
+                    m_state->snapshot()->vkCmdTraceRaysIndirectKHR(
+                        snapshotTraceBegin, snapshotTraceBytes, &m_pool, commandBuffer,
+                        pRaygenShaderBindingTable, pMissShaderBindingTable, pHitShaderBindingTable,
+                        pCallableShaderBindingTable, indirectDeviceAddress);
+                }
+                vkReadStream->clearPool();
+                if (m_queueSubmitWithCommandsEnabled)
+                    seqnoPtr->fetch_add(1, std::memory_order_seq_cst);
+                android::base::endTrace();
+                break;
+            }
+            case OP_vkGetRayTracingShaderGroupStackSizeKHR: {
+                android::base::beginTrace("vkGetRayTracingShaderGroupStackSizeKHR decode");
+                VkDevice device;
+                VkPipeline pipeline;
+                uint32_t group;
+                VkShaderGroupShaderKHR groupShader;
+                // Begin non wrapped dispatchable handle unboxing for device;
+                uint64_t cgen_var_0;
+                memcpy((uint64_t*)&cgen_var_0, *readStreamPtrPtr, 1 * 8);
+                *readStreamPtrPtr += 1 * 8;
+                *(VkDevice*)&device = (VkDevice)(VkDevice)((VkDevice)(*&cgen_var_0));
+                auto unboxed_device = unbox_VkDevice(device);
+                auto vk = dispatch_VkDevice(device);
+                // End manual dispatchable handle unboxing for device;
+                uint64_t cgen_var_1;
+                memcpy((uint64_t*)&cgen_var_1, *readStreamPtrPtr, 1 * 8);
+                *readStreamPtrPtr += 1 * 8;
+                *(VkPipeline*)&pipeline = (VkPipeline)unbox_VkPipeline((VkPipeline)(*&cgen_var_1));
+                memcpy((uint32_t*)&group, *readStreamPtrPtr, sizeof(uint32_t));
+                *readStreamPtrPtr += sizeof(uint32_t);
+                memcpy((VkShaderGroupShaderKHR*)&groupShader, *readStreamPtrPtr,
+                       sizeof(VkShaderGroupShaderKHR));
+                *readStreamPtrPtr += sizeof(VkShaderGroupShaderKHR);
+                if (m_logCalls) {
+                    fprintf(stderr,
+                            "stream %p: call vkGetRayTracingShaderGroupStackSizeKHR 0x%llx 0x%llx "
+                            "0x%llx 0x%llx \n",
+                            ioStream, (unsigned long long)device, (unsigned long long)pipeline,
+                            (unsigned long long)group, (unsigned long long)groupShader);
+                }
+                VkDeviceSize vkGetRayTracingShaderGroupStackSizeKHR_VkDeviceSize_return =
+                    (VkDeviceSize)0;
+                vkGetRayTracingShaderGroupStackSizeKHR_VkDeviceSize_return =
+                    vk->vkGetRayTracingShaderGroupStackSizeKHR(unboxed_device, pipeline, group,
+                                                               groupShader);
+                vkStream->unsetHandleMapping();
+                vkStream->write(&vkGetRayTracingShaderGroupStackSizeKHR_VkDeviceSize_return,
+                                sizeof(VkDeviceSize));
+                vkStream->commitWrite();
+                vkReadStream->setReadPos((uintptr_t)(*readStreamPtrPtr) -
+                                         (uintptr_t)snapshotTraceBegin);
+                size_t snapshotTraceBytes = vkReadStream->endTrace();
+                if (m_state->snapshotsEnabled()) {
+                    m_state->snapshot()->vkGetRayTracingShaderGroupStackSizeKHR(
+                        snapshotTraceBegin, snapshotTraceBytes, &m_pool,
+                        vkGetRayTracingShaderGroupStackSizeKHR_VkDeviceSize_return, device,
+                        pipeline, group, groupShader);
+                }
+                vkReadStream->clearPool();
+                if (m_queueSubmitWithCommandsEnabled)
+                    seqnoPtr->fetch_add(1, std::memory_order_seq_cst);
+                android::base::endTrace();
+                break;
+            }
+            case OP_vkCmdSetRayTracingPipelineStackSizeKHR: {
+                android::base::beginTrace("vkCmdSetRayTracingPipelineStackSizeKHR decode");
+                VkCommandBuffer commandBuffer;
+                uint32_t pipelineStackSize;
+                // Begin non wrapped dispatchable handle unboxing for commandBuffer;
+                uint64_t cgen_var_0;
+                memcpy((uint64_t*)&cgen_var_0, *readStreamPtrPtr, 1 * 8);
+                *readStreamPtrPtr += 1 * 8;
+                *(VkCommandBuffer*)&commandBuffer =
+                    (VkCommandBuffer)(VkCommandBuffer)((VkCommandBuffer)(*&cgen_var_0));
+                auto unboxed_commandBuffer = unbox_VkCommandBuffer(commandBuffer);
+                auto vk = dispatch_VkCommandBuffer(commandBuffer);
+                // End manual dispatchable handle unboxing for commandBuffer;
+                memcpy((uint32_t*)&pipelineStackSize, *readStreamPtrPtr, sizeof(uint32_t));
+                *readStreamPtrPtr += sizeof(uint32_t);
+                if (m_logCalls) {
+                    fprintf(
+                        stderr,
+                        "stream %p: call vkCmdSetRayTracingPipelineStackSizeKHR 0x%llx 0x%llx \n",
+                        ioStream, (unsigned long long)commandBuffer,
+                        (unsigned long long)pipelineStackSize);
+                }
+                vk->vkCmdSetRayTracingPipelineStackSizeKHR(unboxed_commandBuffer,
+                                                           pipelineStackSize);
+                vkStream->unsetHandleMapping();
+                vkReadStream->setReadPos((uintptr_t)(*readStreamPtrPtr) -
+                                         (uintptr_t)snapshotTraceBegin);
+                size_t snapshotTraceBytes = vkReadStream->endTrace();
+                if (m_state->snapshotsEnabled()) {
+                    m_state->snapshot()->vkCmdSetRayTracingPipelineStackSizeKHR(
+                        snapshotTraceBegin, snapshotTraceBytes, &m_pool, commandBuffer,
+                        pipelineStackSize);
+                }
+                vkReadStream->clearPool();
+                if (m_queueSubmitWithCommandsEnabled)
+                    seqnoPtr->fetch_add(1, std::memory_order_seq_cst);
+                android::base::endTrace();
+                break;
+            }
 #endif
             default: {
                 m_pool.freeAll();
diff --git a/host/vulkan/VkDecoder.h b/host/vulkan/VkDecoder.h
index f4cfa65..602fe10 100644
--- a/host/vulkan/VkDecoder.h
+++ b/host/vulkan/VkDecoder.h
@@ -67,196 +67,3 @@
 
 }  // namespace vk
 }  // namespace gfxstream
-
-#ifdef VK_VERSION_1_0
-#endif
-#ifdef VK_VERSION_1_1
-#endif
-#ifdef VK_VERSION_1_2
-#endif
-#ifdef VK_VERSION_1_3
-#endif
-#ifdef VK_KHR_surface
-#endif
-#ifdef VK_KHR_swapchain
-#endif
-#ifdef VK_KHR_xcb_surface
-#endif
-#ifdef VK_KHR_android_surface
-#endif
-#ifdef VK_KHR_win32_surface
-#endif
-#ifdef VK_KHR_dynamic_rendering
-#endif
-#ifdef VK_KHR_get_physical_device_properties2
-#endif
-#ifdef VK_KHR_maintenance1
-#endif
-#ifdef VK_KHR_external_memory_capabilities
-#endif
-#ifdef VK_KHR_external_memory
-#endif
-#ifdef VK_KHR_external_memory_win32
-#endif
-#ifdef VK_KHR_external_memory_fd
-#endif
-#ifdef VK_KHR_external_semaphore_capabilities
-#endif
-#ifdef VK_KHR_external_semaphore
-#endif
-#ifdef VK_KHR_external_semaphore_win32
-#endif
-#ifdef VK_KHR_external_semaphore_fd
-#endif
-#ifdef VK_KHR_shader_float16_int8
-#endif
-#ifdef VK_KHR_incremental_present
-#endif
-#ifdef VK_KHR_descriptor_update_template
-#endif
-#ifdef VK_KHR_imageless_framebuffer
-#endif
-#ifdef VK_KHR_create_renderpass2
-#endif
-#ifdef VK_KHR_external_fence_capabilities
-#endif
-#ifdef VK_KHR_external_fence
-#endif
-#ifdef VK_KHR_external_fence_fd
-#endif
-#ifdef VK_KHR_maintenance2
-#endif
-#ifdef VK_KHR_dedicated_allocation
-#endif
-#ifdef VK_KHR_storage_buffer_storage_class
-#endif
-#ifdef VK_KHR_get_memory_requirements2
-#endif
-#ifdef VK_KHR_image_format_list
-#endif
-#ifdef VK_KHR_sampler_ycbcr_conversion
-#endif
-#ifdef VK_KHR_bind_memory2
-#endif
-#ifdef VK_KHR_maintenance3
-#endif
-#ifdef VK_KHR_shader_subgroup_extended_types
-#endif
-#ifdef VK_KHR_vulkan_memory_model
-#endif
-#ifdef VK_KHR_shader_terminate_invocation
-#endif
-#ifdef VK_KHR_buffer_device_address
-#endif
-#ifdef VK_KHR_pipeline_executable_properties
-#endif
-#ifdef VK_KHR_shader_integer_dot_product
-#endif
-#ifdef VK_KHR_shader_non_semantic_info
-#endif
-#ifdef VK_KHR_synchronization2
-#endif
-#ifdef VK_KHR_zero_initialize_workgroup_memory
-#endif
-#ifdef VK_KHR_copy_commands2
-#endif
-#ifdef VK_KHR_format_feature_flags2
-#endif
-#ifdef VK_KHR_maintenance4
-#endif
-#ifdef VK_KHR_maintenance5
-#endif
-#ifdef VK_ANDROID_native_buffer
-#endif
-#ifdef VK_EXT_debug_report
-#endif
-#ifdef VK_EXT_transform_feedback
-#endif
-#ifdef VK_AMD_gpu_shader_half_float
-#endif
-#ifdef VK_EXT_texture_compression_astc_hdr
-#endif
-#ifdef VK_EXT_depth_clip_enable
-#endif
-#ifdef VK_EXT_swapchain_colorspace
-#endif
-#ifdef VK_EXT_queue_family_foreign
-#endif
-#ifdef VK_EXT_debug_utils
-#endif
-#ifdef VK_ANDROID_external_memory_android_hardware_buffer
-#endif
-#ifdef VK_EXT_inline_uniform_block
-#endif
-#ifdef VK_EXT_shader_stencil_export
-#endif
-#ifdef VK_EXT_vertex_attribute_divisor
-#endif
-#ifdef VK_EXT_pipeline_creation_feedback
-#endif
-#ifdef VK_NV_shader_subgroup_partitioned
-#endif
-#ifdef VK_EXT_metal_surface
-#endif
-#ifdef VK_EXT_fragment_density_map
-#endif
-#ifdef VK_EXT_scalar_block_layout
-#endif
-#ifdef VK_EXT_subgroup_size_control
-#endif
-#ifdef VK_EXT_tooling_info
-#endif
-#ifdef VK_EXT_validation_features
-#endif
-#ifdef VK_EXT_provoking_vertex
-#endif
-#ifdef VK_EXT_line_rasterization
-#endif
-#ifdef VK_EXT_index_type_uint8
-#endif
-#ifdef VK_EXT_extended_dynamic_state
-#endif
-#ifdef VK_EXT_host_image_copy
-#endif
-#ifdef VK_EXT_swapchain_maintenance1
-#endif
-#ifdef VK_EXT_shader_demote_to_helper_invocation
-#endif
-#ifdef VK_EXT_texel_buffer_alignment
-#endif
-#ifdef VK_EXT_device_memory_report
-#endif
-#ifdef VK_EXT_robustness2
-#endif
-#ifdef VK_EXT_custom_border_color
-#endif
-#ifdef VK_EXT_private_data
-#endif
-#ifdef VK_EXT_pipeline_creation_cache_control
-#endif
-#ifdef VK_EXT_metal_objects
-#endif
-#ifdef VK_EXT_graphics_pipeline_library
-#endif
-#ifdef VK_EXT_ycbcr_2plane_444_formats
-#endif
-#ifdef VK_EXT_image_robustness
-#endif
-#ifdef VK_EXT_image_compression_control
-#endif
-#ifdef VK_EXT_4444_formats
-#endif
-#ifdef VK_EXT_primitive_topology_list_restart
-#endif
-#ifdef VK_EXT_extended_dynamic_state2
-#endif
-#ifdef VK_EXT_color_write_enable
-#endif
-#ifdef VK_GOOGLE_gfxstream
-#endif
-#ifdef VK_EXT_load_store_op_none
-#endif
-#ifdef VK_EXT_image_compression_control_swapchain
-#endif
-#ifdef VK_QNX_external_memory_screen_buffer
-#endif
diff --git a/host/vulkan/VkDecoderGlobalState.cpp b/host/vulkan/VkDecoderGlobalState.cpp
index 40c2918..93e5e8f 100644
--- a/host/vulkan/VkDecoderGlobalState.cpp
+++ b/host/vulkan/VkDecoderGlobalState.cpp
@@ -21,7 +21,7 @@
 #include <unordered_map>
 #include <vector>
 
-#include "BlobManager.h"
+#include "ExternalObjectManager.h"
 #include "FrameBuffer.h"
 #include "RenderThreadInfoVk.h"
 #include "VkAndroidNativeBuffer.h"
@@ -93,11 +93,10 @@
 using android::base::Optional;
 using android::base::SharedMemory;
 using android::base::StaticLock;
-using android::emulation::ManagedDescriptorInfo;
 using emugl::ABORT_REASON_OTHER;
 using emugl::FatalError;
 using emugl::GfxApiLogger;
-using gfxstream::BlobManager;
+using gfxstream::ExternalObjectManager;
 using gfxstream::VulkanInfo;
 
 // TODO(b/261477138): Move to a shared aemu definition
@@ -1097,29 +1096,30 @@
         fb->unregisterProcessCleanupCallback(instance);
     }
 
-    VkResult on_vkEnumeratePhysicalDevices(android::base::BumpPool* pool, VkInstance boxed_instance,
-                                           uint32_t* physicalDeviceCount,
-                                           VkPhysicalDevice* physicalDevices) {
-        auto instance = unbox_VkInstance(boxed_instance);
-        auto vk = dispatch_VkInstance(boxed_instance);
-
-        uint32_t physicalDevicesSize = 0;
-        if (physicalDeviceCount) {
-            physicalDevicesSize = *physicalDeviceCount;
-        }
-
-        uint32_t actualPhysicalDeviceCount;
-        auto res = vk->vkEnumeratePhysicalDevices(instance, &actualPhysicalDeviceCount, nullptr);
+    VkResult GetPhysicalDevices(VkInstance instance, VulkanDispatch* vk,
+                                std::vector<VkPhysicalDevice>& outPhysicalDevices) {
+        uint32_t physicalDevicesCount = 0;
+        auto res = vk->vkEnumeratePhysicalDevices(instance, &physicalDevicesCount, nullptr);
         if (res != VK_SUCCESS) {
             return res;
         }
-        std::vector<VkPhysicalDevice> validPhysicalDevices(actualPhysicalDeviceCount);
-        res = vk->vkEnumeratePhysicalDevices(instance, &actualPhysicalDeviceCount,
-                                             validPhysicalDevices.data());
-        if (res != VK_SUCCESS) return res;
 
-        std::lock_guard<std::recursive_mutex> lock(mLock);
+        outPhysicalDevices.resize(physicalDevicesCount);
 
+        res = vk->vkEnumeratePhysicalDevices(instance, &physicalDevicesCount,
+                                             outPhysicalDevices.data());
+        if (res != VK_SUCCESS) {
+            outPhysicalDevices.clear();
+            return res;
+        }
+
+        outPhysicalDevices.resize(physicalDevicesCount);
+
+        return VK_SUCCESS;
+    }
+
+    void FilterPhysicalDevicesLocked(VkInstance instance, VulkanDispatch* vk,
+                                     std::vector<VkPhysicalDevice>& toFilterPhysicalDevices) {
         if (m_emu->instanceSupportsExternalMemoryCapabilities) {
             PFN_vkGetPhysicalDeviceProperties2KHR getPhysdevProps2Func =
                 vk_util::getVkInstanceProcAddrWithFallback<
@@ -1131,8 +1131,9 @@
                     instance);
 
             if (getPhysdevProps2Func) {
-                validPhysicalDevices.erase(
-                    std::remove_if(validPhysicalDevices.begin(), validPhysicalDevices.end(),
+                // Remove those devices whose UUIDs don't match the one in VkCommonOperations.
+                toFilterPhysicalDevices.erase(
+                    std::remove_if(toFilterPhysicalDevices.begin(), toFilterPhysicalDevices.end(),
                                    [getPhysdevProps2Func, this](VkPhysicalDevice physicalDevice) {
                                        // We can get the device UUID.
                                        VkPhysicalDeviceIDPropertiesKHR idProps = {
@@ -1145,54 +1146,65 @@
                                        };
                                        getPhysdevProps2Func(physicalDevice, &propsWithId);
 
-                                       // Remove those devices whose UUIDs don't match the one
-                                       // in VkCommonOperations.
                                        return memcmp(m_emu->deviceInfo.idProps.deviceUUID,
                                                      idProps.deviceUUID, VK_UUID_SIZE) != 0;
                                    }),
-                    validPhysicalDevices.end());
+                    toFilterPhysicalDevices.end());
             } else {
-                fprintf(stderr,
-                        "%s: warning: failed to "
-                        "vkGetPhysicalDeviceProperties2KHR\n",
-                        __func__);
+                ERR("Failed to vkGetPhysicalDeviceProperties2KHR().");
             }
         } else {
             // If we don't support ID properties then just advertise only the
             // first physical device.
-            fprintf(stderr,
-                    "%s: device id properties not supported, using first "
-                    "physical device\n",
-                    __func__);
+            WARN("Device ID not available, returning first physical device.");
         }
-        if (!validPhysicalDevices.empty()) {
-            validPhysicalDevices.erase(std::next(validPhysicalDevices.begin()),
-                                       validPhysicalDevices.end());
+        if (!toFilterPhysicalDevices.empty()) {
+            toFilterPhysicalDevices.erase(std::next(toFilterPhysicalDevices.begin()),
+                                          toFilterPhysicalDevices.end());
+        }
+    }
+
+    VkResult on_vkEnumeratePhysicalDevices(android::base::BumpPool* pool, VkInstance boxed_instance,
+                                           uint32_t* pPhysicalDeviceCount,
+                                           VkPhysicalDevice* pPhysicalDevices) {
+        auto instance = unbox_VkInstance(boxed_instance);
+        auto vk = dispatch_VkInstance(boxed_instance);
+
+        std::vector<VkPhysicalDevice> physicalDevices;
+        auto res = GetPhysicalDevices(instance, vk, physicalDevices);
+        if (res != VK_SUCCESS) {
+            return res;
         }
 
-        if (physicalDeviceCount) {
-            *physicalDeviceCount = validPhysicalDevices.size();
+        std::lock_guard<std::recursive_mutex> lock(mLock);
+
+        FilterPhysicalDevicesLocked(instance, vk, physicalDevices);
+
+        const uint32_t requestedCount = pPhysicalDeviceCount ? *pPhysicalDeviceCount : 0;
+        const uint32_t availableCount = static_cast<uint32_t>(physicalDevices.size());
+
+        if (pPhysicalDeviceCount) {
+            *pPhysicalDeviceCount = availableCount;
         }
 
-        if (physicalDeviceCount && physicalDevices) {
+        if (pPhysicalDeviceCount && pPhysicalDevices) {
             // Box them up
-            for (uint32_t i = 0; i < std::min(*physicalDeviceCount, physicalDevicesSize); ++i) {
-                mPhysicalDeviceToInstance[validPhysicalDevices[i]] = instance;
+            for (uint32_t i = 0; i < std::min(requestedCount, availableCount); ++i) {
+                mPhysicalDeviceToInstance[physicalDevices[i]] = instance;
 
-                auto& physdevInfo = mPhysdevInfo[validPhysicalDevices[i]];
+                auto& physdevInfo = mPhysdevInfo[physicalDevices[i]];
                 physdevInfo.instance = instance;
-                physdevInfo.boxed = new_boxed_VkPhysicalDevice(validPhysicalDevices[i], vk,
+                physdevInfo.boxed = new_boxed_VkPhysicalDevice(physicalDevices[i], vk,
                                                                false /* does not own dispatch */);
 
-                vk->vkGetPhysicalDeviceProperties(validPhysicalDevices[i], &physdevInfo.props);
+                vk->vkGetPhysicalDeviceProperties(physicalDevices[i], &physdevInfo.props);
 
                 if (physdevInfo.props.apiVersion > kMaxSafeVersion) {
                     physdevInfo.props.apiVersion = kMaxSafeVersion;
                 }
 
                 VkPhysicalDeviceMemoryProperties hostMemoryProperties;
-                vk->vkGetPhysicalDeviceMemoryProperties(validPhysicalDevices[i],
-                                                        &hostMemoryProperties);
+                vk->vkGetPhysicalDeviceMemoryProperties(physicalDevices[i], &hostMemoryProperties);
 
                 physdevInfo.memoryPropertiesHelper =
                     std::make_unique<EmulatedPhysicalDeviceMemoryProperties>(
@@ -1202,18 +1214,18 @@
 
                 uint32_t queueFamilyPropCount = 0;
 
-                vk->vkGetPhysicalDeviceQueueFamilyProperties(validPhysicalDevices[i],
+                vk->vkGetPhysicalDeviceQueueFamilyProperties(physicalDevices[i],
                                                              &queueFamilyPropCount, nullptr);
 
                 physdevInfo.queueFamilyProperties.resize((size_t)queueFamilyPropCount);
 
                 vk->vkGetPhysicalDeviceQueueFamilyProperties(
-                    validPhysicalDevices[i], &queueFamilyPropCount,
+                    physicalDevices[i], &queueFamilyPropCount,
                     physdevInfo.queueFamilyProperties.data());
 
-                physicalDevices[i] = (VkPhysicalDevice)physdevInfo.boxed;
+                pPhysicalDevices[i] = (VkPhysicalDevice)physdevInfo.boxed;
             }
-            if (physicalDevicesSize < *physicalDeviceCount) {
+            if (requestedCount < availableCount) {
                 res = VK_INCOMPLETE;
             }
         }
@@ -1644,10 +1656,13 @@
         auto physicalDevice = unbox_VkPhysicalDevice(boxed_physicalDevice);
         auto vk = dispatch_VkPhysicalDevice(boxed_physicalDevice);
 
-        const std::vector<const char*> finalExts =
+        std::vector<const char*> updatedDeviceExtensions =
             filteredDeviceExtensionNames(vk, physicalDevice, pCreateInfo->enabledExtensionCount,
                                          pCreateInfo->ppEnabledExtensionNames);
 
+        m_emu->deviceLostHelper.addNeededDeviceExtensions(&updatedDeviceExtensions);
+        uint32_t supportedFenceHandleTypes = 0;
+        uint32_t supportedBinarySemaphoreHandleTypes = 0;
         // Run the underlying API call, filtering extensions.
         VkDeviceCreateInfo createInfoFiltered = *pCreateInfo;
         // According to the spec, it seems that the application can use compressed texture formats
@@ -1757,8 +1772,11 @@
         // Filter device memory report as callbacks can not be passed between guest and host.
         vk_struct_chain_filter<VkDeviceDeviceMemoryReportCreateInfoEXT>(&createInfoFiltered);
 
-        createInfoFiltered.enabledExtensionCount = (uint32_t)finalExts.size();
-        createInfoFiltered.ppEnabledExtensionNames = finalExts.data();
+        // Filter device groups as they are effectively disabled.
+        vk_struct_chain_filter<VkDeviceGroupDeviceCreateInfo>(&createInfoFiltered);
+
+        createInfoFiltered.enabledExtensionCount = (uint32_t)updatedDeviceExtensions.size();
+        createInfoFiltered.ppEnabledExtensionNames = updatedDeviceExtensions.data();
 
         // bug: 155795731
         bool swiftshader =
@@ -1800,6 +1818,13 @@
             AstcCpuDecompressor::get().available();
         deviceInfo.decompPipelines =
             std::make_unique<GpuDecompressionPipelineManager>(m_vk, *pDevice);
+        getSupportedFenceHandleTypes(vk, physicalDevice, &supportedFenceHandleTypes);
+        getSupportedSemaphoreHandleTypes(vk, physicalDevice, &supportedBinarySemaphoreHandleTypes);
+
+        deviceInfo.externalFenceInfo.supportedFenceHandleTypes =
+            static_cast<VkExternalFenceHandleTypeFlagBits>(supportedFenceHandleTypes);
+        deviceInfo.externalFenceInfo.supportedBinarySemaphoreHandleTypes =
+            static_cast<VkExternalSemaphoreHandleTypeFlagBits>(supportedBinarySemaphoreHandleTypes);
 
         INFO("Created VkDevice:%p for application:%s engine:%s ASTC emulation:%s CPU decoding:%s.",
              *pDevice, instanceInfo.applicationName.c_str(), instanceInfo.engineName.c_str(),
@@ -2530,6 +2555,45 @@
         destroySamplerLocked(device, deviceDispatch, sampler, pAllocator);
     }
 
+    VkResult exportSemaphore(
+        VulkanDispatch* vk, VkDevice device, VkSemaphore semaphore, VK_EXT_SYNC_HANDLE* outHandle,
+        std::optional<VkExternalSemaphoreHandleTypeFlagBits> handleType = std::nullopt) {
+#if defined(_WIN32)
+        VkSemaphoreGetWin32HandleInfoKHR getWin32 = {
+            VK_STRUCTURE_TYPE_SEMAPHORE_GET_WIN32_HANDLE_INFO_KHR,
+            0,
+            semaphore,
+            VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT,
+        };
+
+        return vk->vkGetSemaphoreWin32HandleKHR(device, &getWin32, outHandle);
+#elif defined(__linux__)
+        VkExternalSemaphoreHandleTypeFlagBits handleTypeBits =
+            VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT;
+        if (handleType) {
+            handleTypeBits = *handleType;
+        }
+
+        VkSemaphoreGetFdInfoKHR getFd = {
+            VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR,
+            0,
+            semaphore,
+            handleTypeBits,
+        };
+
+        if (!hasDeviceExtension(device, VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME)) {
+            // Note: VK_KHR_external_semaphore_fd might be advertised in the guest,
+            // because SYNC_FD handling is performed guest-side only. But still need
+            // need to error out here when handling a non-sync, opaque FD.
+            return VK_ERROR_OUT_OF_HOST_MEMORY;
+        }
+
+        return vk->vkGetSemaphoreFdKHR(device, &getFd, outHandle);
+#else
+        return VK_ERROR_OUT_OF_HOST_MEMORY;
+#endif
+    }
+
     VkResult on_vkCreateSemaphore(android::base::BumpPool* pool, VkDevice boxed_device,
                                   const VkSemaphoreCreateInfo* pCreateInfo,
                                   const VkAllocationCallbacks* pAllocator,
@@ -2540,29 +2604,61 @@
         VkSemaphoreCreateInfo localCreateInfo = vk_make_orphan_copy(*pCreateInfo);
         vk_struct_chain_iterator structChainIter = vk_make_chain_iterator(&localCreateInfo);
 
+        bool timelineSemaphore = false;
+
         VkSemaphoreTypeCreateInfoKHR localSemaphoreTypeCreateInfo;
         if (const VkSemaphoreTypeCreateInfoKHR* semaphoreTypeCiPtr =
                 vk_find_struct<VkSemaphoreTypeCreateInfoKHR>(pCreateInfo);
             semaphoreTypeCiPtr) {
             localSemaphoreTypeCreateInfo = vk_make_orphan_copy(*semaphoreTypeCiPtr);
             vk_append_struct(&structChainIter, &localSemaphoreTypeCreateInfo);
+
+            if (localSemaphoreTypeCreateInfo.semaphoreType == VK_SEMAPHORE_TYPE_TIMELINE) {
+                timelineSemaphore = true;
+            }
         }
 
-        const VkExportSemaphoreCreateInfoKHR* exportCiPtr =
-            vk_find_struct<VkExportSemaphoreCreateInfoKHR>(pCreateInfo);
-        VkExportSemaphoreCreateInfoKHR localSemaphoreCreateInfo;
+        VkExportSemaphoreCreateInfoKHR localExportSemaphoreCi = {};
 
-        if (exportCiPtr) {
-            localSemaphoreCreateInfo = vk_make_orphan_copy(*exportCiPtr);
+        /* Timeline semaphores are exportable:
+         *
+         * "Timeline semaphore specific external sharing capabilities can be queried using
+         *  vkGetPhysicalDeviceExternalSemaphoreProperties by chaining the new
+         *  VkSemaphoreTypeCreateInfoKHR structure to its pExternalSemaphoreInfo structure.
+         *  This allows having a different set of external semaphore handle types supported
+         *  for timeline semaphores vs. binary semaphores."
+         *
+         *  We just don't support this here since neither Android or Zink use this feature
+         *  with timeline semaphores yet.
+         */
+        if (m_emu->features.VulkanExternalSync.enabled && !timelineSemaphore) {
+            localExportSemaphoreCi.sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO;
+            localExportSemaphoreCi.pNext = nullptr;
 
-#ifdef _WIN32
-            if (localSemaphoreCreateInfo.handleTypes) {
-                localSemaphoreCreateInfo.handleTypes =
-                    VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR;
+            {
+                std::lock_guard<std::recursive_mutex> lock(mLock);
+                auto* deviceInfo = android::base::find(mDeviceInfo, device);
+
+                if (!deviceInfo) {
+                    return VK_ERROR_DEVICE_LOST;
+                }
+
+                if (deviceInfo->externalFenceInfo.supportedBinarySemaphoreHandleTypes &
+                    VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT) {
+                    localExportSemaphoreCi.handleTypes =
+                        VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT;
+                } else if (deviceInfo->externalFenceInfo.supportedBinarySemaphoreHandleTypes &
+                           VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT) {
+                    localExportSemaphoreCi.handleTypes =
+                        VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
+                } else if (deviceInfo->externalFenceInfo.supportedBinarySemaphoreHandleTypes &
+                           VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT) {
+                    localExportSemaphoreCi.handleTypes =
+                        VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT;
+                }
             }
-#endif
 
-            vk_append_struct(&structChainIter, &localSemaphoreCreateInfo);
+            vk_append_struct(&structChainIter, &localExportSemaphoreCi);
         }
 
         VkResult res = vk->vkCreateSemaphore(device, &localCreateInfo, pAllocator, pSemaphore);
@@ -2744,42 +2840,71 @@
                                     const VkSemaphoreGetFdInfoKHR* pGetFdInfo, int* pFd) {
         auto device = unbox_VkDevice(boxed_device);
         auto vk = dispatch_VkDevice(boxed_device);
-#ifdef _WIN32
-        VkSemaphoreGetWin32HandleInfoKHR getWin32 = {
-            VK_STRUCTURE_TYPE_SEMAPHORE_GET_WIN32_HANDLE_INFO_KHR,
-            0,
-            pGetFdInfo->semaphore,
-            VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT,
-        };
         VK_EXT_SYNC_HANDLE handle;
-        VkResult result = vk->vkGetSemaphoreWin32HandleKHR(device, &getWin32, &handle);
+
+        VkResult result = exportSemaphore(vk, device, pGetFdInfo->semaphore, &handle);
         if (result != VK_SUCCESS) {
             return result;
         }
+
         std::lock_guard<std::recursive_mutex> lock(mLock);
         mSemaphoreInfo[pGetFdInfo->semaphore].externalHandle = handle;
+#ifdef _WIN32
         int nextId = genSemaphoreId();
         mExternalSemaphoresById[nextId] = pGetFdInfo->semaphore;
         *pFd = nextId;
 #else
-        if (!hasDeviceExtension(device, VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME)) {
-            // Note: VK_KHR_external_semaphore_fd might be advertised in the guest,
-            // because SYNC_FD handling is performed guest-side only. But still need
-            // need to error out here when handling a non-sync, opaque FD.
-            return VK_ERROR_OUT_OF_HOST_MEMORY;
+        // No next id; its already an fd
+        mSemaphoreInfo[pGetFdInfo->semaphore].externalHandle = handle;
+#endif
+        return result;
+    }
+
+    VkResult on_vkGetSemaphoreGOOGLE(android::base::BumpPool* pool, VkDevice boxed_device,
+                                     VkSemaphore semaphore, uint64_t syncId) {
+        VK_EXT_SYNC_HANDLE handle;
+        uint32_t streamHandleType = 0;
+        auto* tInfo = RenderThreadInfoVk::get();
+        auto vk = dispatch_VkDevice(boxed_device);
+        auto device = unbox_VkDevice(boxed_device);
+        VkExternalSemaphoreHandleTypeFlagBits flagBits =
+            static_cast<VkExternalSemaphoreHandleTypeFlagBits>(0);
+
+        if (!m_emu->features.VulkanExternalSync.enabled) {
+            return VK_ERROR_FEATURE_NOT_PRESENT;
         }
 
-        VkResult result = vk->vkGetSemaphoreFdKHR(device, pGetFdInfo, pFd);
+        {
+            std::lock_guard<std::recursive_mutex> lock(mLock);
+            auto* deviceInfo = android::base::find(mDeviceInfo, device);
+
+            if (!deviceInfo) {
+                return VK_ERROR_DEVICE_LOST;
+            }
+
+            if (deviceInfo->externalFenceInfo.supportedBinarySemaphoreHandleTypes &
+                VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT) {
+                flagBits = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT;
+            } else if (deviceInfo->externalFenceInfo.supportedBinarySemaphoreHandleTypes &
+                       VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT) {
+                flagBits = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
+            } else if (deviceInfo->externalFenceInfo.supportedBinarySemaphoreHandleTypes &
+                       VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT) {
+                flagBits = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT;
+            }
+        }
+
+        VkResult result =
+            exportSemaphore(vk, device, semaphore, &handle,
+                            std::make_optional<VkExternalSemaphoreHandleTypeFlagBits>(flagBits));
         if (result != VK_SUCCESS) {
             return result;
         }
 
-        std::lock_guard<std::recursive_mutex> lock(mLock);
-
-        mSemaphoreInfo[pGetFdInfo->semaphore].externalHandle = *pFd;
-        // No next id; its already an fd
-#endif
-        return result;
+        ManagedDescriptor descriptor(handle);
+        ExternalObjectManager::get()->addSyncDescriptorInfo(
+            tInfo->ctx_id, syncId, std::move(descriptor), streamHandleType);
+        return VK_SUCCESS;
     }
 
     void destroySemaphoreLocked(VkDevice device, VulkanDispatch* deviceDispatch,
@@ -4400,74 +4525,83 @@
                                               &localAllocInfo.allocationSize,
                                               &localAllocInfo.memoryTypeIndex,
                                               &colorBufferMemoryUsesDedicatedAlloc, &mappedPtr)) {
-                GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
-                    << "Failed to get allocation info for ColorBuffer:"
-                    << importCbInfoPtr->colorBuffer;
-            }
-
-            shouldUseDedicatedAllocInfo &= colorBufferMemoryUsesDedicatedAlloc;
-
-            if (!m_emu->features.GuestVulkanOnly.enabled) {
-                auto fb = FrameBuffer::getFB();
-                if (fb) {
-                    fb->invalidateColorBufferForVk(importCbInfoPtr->colorBuffer);
+                if (mSnapshotState != SnapshotState::Loading) {
+                    GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+                        << "Failed to get allocation info for ColorBuffer:"
+                        << importCbInfoPtr->colorBuffer;
                 }
-            }
+                // During snapshot load there could be invalidated references to
+                // color buffers.
+                // Here we just create a placeholder for it, as it is not suppoed
+                // to be used.
+                importCbInfoPtr = nullptr;
+            } else {
+                shouldUseDedicatedAllocInfo &= colorBufferMemoryUsesDedicatedAlloc;
+
+                if (!m_emu->features.GuestVulkanOnly.enabled) {
+                    auto fb = FrameBuffer::getFB();
+                    if (fb) {
+                        fb->invalidateColorBufferForVk(importCbInfoPtr->colorBuffer);
+                    }
+                }
 
 #if defined(__APPLE__)
-            // Use metal object extension on MoltenVK mode for color buffer import,
-            // non-moltenVK path on MacOS will use FD handles
-            if (m_emu->instanceSupportsMoltenVK) {
-                // TODO(b/333460957): This is a temporary fix to get MoltenVK image memory binding
-                // checks working as expected  based on dedicated memory checks. It's not a valid usage
-                // of Vulkan as the device of the image is different than what's being used here
-                localDedicatedAllocInfo = {
-                    .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
-                    .pNext = nullptr,
-                    .image = getColorBufferVkImage(importCbInfoPtr->colorBuffer),
-                    .buffer = VK_NULL_HANDLE,
-                };
-                shouldUseDedicatedAllocInfo = true;
+                // Use metal object extension on MoltenVK mode for color buffer import,
+                // non-moltenVK path on MacOS will use FD handles
+                if (m_emu->instanceSupportsMoltenVK) {
+                    // TODO(b/333460957): This is a temporary fix to get MoltenVK image memory
+                    // binding checks working as expected  based on dedicated memory checks. It's
+                    // not a valid usage of Vulkan as the device of the image is different than
+                    // what's being used here
+                    localDedicatedAllocInfo = {
+                        .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
+                        .pNext = nullptr,
+                        .image = getColorBufferVkImage(importCbInfoPtr->colorBuffer),
+                        .buffer = VK_NULL_HANDLE,
+                    };
+                    shouldUseDedicatedAllocInfo = true;
 
-                MTLBufferRef cbExtMemoryHandle =
-                    getColorBufferMetalMemoryHandle(importCbInfoPtr->colorBuffer);
+                    MTLBufferRef cbExtMemoryHandle =
+                        getColorBufferMetalMemoryHandle(importCbInfoPtr->colorBuffer);
 
-                if (cbExtMemoryHandle == nullptr) {
-                    fprintf(stderr,
-                            "%s: VK_ERROR_OUT_OF_DEVICE_MEMORY: "
-                            "colorBuffer 0x%x does not have Vulkan external memory backing\n",
-                            __func__, importCbInfoPtr->colorBuffer);
-                    return VK_ERROR_OUT_OF_DEVICE_MEMORY;
-                }
+                    if (cbExtMemoryHandle == nullptr) {
+                        fprintf(stderr,
+                                "%s: VK_ERROR_OUT_OF_DEVICE_MEMORY: "
+                                "colorBuffer 0x%x does not have Vulkan external memory backing\n",
+                                __func__, importCbInfoPtr->colorBuffer);
+                        return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+                    }
 
-                importInfoMetalBuffer.mtlBuffer = cbExtMemoryHandle;
-                vk_append_struct(&structChainIter, &importInfoMetalBuffer);
-            } else
+                    importInfoMetalBuffer.mtlBuffer = cbExtMemoryHandle;
+                    vk_append_struct(&structChainIter, &importInfoMetalBuffer);
+                } else
 #endif
-            if (m_emu->deviceInfo.supportsExternalMemoryImport) {
-                VK_EXT_MEMORY_HANDLE cbExtMemoryHandle =
-                    getColorBufferExtMemoryHandle(importCbInfoPtr->colorBuffer);
+                if (m_emu->deviceInfo.supportsExternalMemoryImport) {
+                    VK_EXT_MEMORY_HANDLE cbExtMemoryHandle =
+                        getColorBufferExtMemoryHandle(importCbInfoPtr->colorBuffer);
 
-                if (cbExtMemoryHandle == VK_EXT_MEMORY_HANDLE_INVALID) {
-                    fprintf(stderr,
-                            "%s: VK_ERROR_OUT_OF_DEVICE_MEMORY: "
-                            "colorBuffer 0x%x does not have Vulkan external memory backing\n",
-                            __func__, importCbInfoPtr->colorBuffer);
-                    return VK_ERROR_OUT_OF_DEVICE_MEMORY;
-                }
+                    if (cbExtMemoryHandle == VK_EXT_MEMORY_HANDLE_INVALID) {
+                        fprintf(stderr,
+                                "%s: VK_ERROR_OUT_OF_DEVICE_MEMORY: "
+                                "colorBuffer 0x%x does not have Vulkan external memory backing\n",
+                                __func__, importCbInfoPtr->colorBuffer);
+                        return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+                    }
 
 #if defined(__QNX__)
-                importInfo.buffer = cbExtMemoryHandle;
+                    importInfo.buffer = cbExtMemoryHandle;
 #else
-                externalMemoryHandle = ManagedDescriptor(dupExternalMemory(cbExtMemoryHandle));
+                    externalMemoryHandle = ManagedDescriptor(dupExternalMemory(cbExtMemoryHandle));
 
 #ifdef _WIN32
-                importInfo.handle = externalMemoryHandle.get().value_or(static_cast<HANDLE>(NULL));
+                    importInfo.handle =
+                        externalMemoryHandle.get().value_or(static_cast<HANDLE>(NULL));
 #else
-                importInfo.fd = externalMemoryHandle.get().value_or(-1);
+                    importInfo.fd = externalMemoryHandle.get().value_or(-1);
 #endif
 #endif
-                vk_append_struct(&structChainIter, &importInfo);
+                    vk_append_struct(&structChainIter, &importInfo);
+                }
             }
         }
 
@@ -4573,7 +4707,8 @@
 #endif
 
 #ifdef __linux__
-        if (hasDeviceExtension(device, VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME)) {
+        if (m_emu->deviceInfo.supportsDmaBuf &&
+            hasDeviceExtension(device, VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME)) {
             exportAllocate.handleTypes |= VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
         }
 #endif
@@ -4600,8 +4735,8 @@
             uint32_t ctx_id = mSnapshotState == SnapshotState::Loading
                                   ? kTemporaryContextIdForSnapshotLoading
                                   : tInfo->ctx_id;
-            auto descriptorInfoOpt =
-                BlobManager::get()->removeDescriptorInfo(ctx_id, createBlobInfoPtr->blobId);
+            auto descriptorInfoOpt = ExternalObjectManager::get()->removeBlobDescriptorInfo(
+                ctx_id, createBlobInfoPtr->blobId);
             if (descriptorInfoOpt) {
                 auto rawDescriptorOpt = (*descriptorInfoOpt).descriptor.release();
                 if (rawDescriptorOpt) {
@@ -4619,7 +4754,8 @@
 #endif
 
 #ifdef __linux__
-            if (hasDeviceExtension(device, VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME)) {
+            if (m_emu->deviceInfo.supportsDmaBuf &&
+                hasDeviceExtension(device, VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME)) {
                 importInfo.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
             }
 #endif
@@ -5094,9 +5230,9 @@
             // We transfer ownership of the shared memory handle to the descriptor info.
             // The memory itself is destroyed only when all processes unmap / release their
             // handles.
-            BlobManager::get()->addDescriptorInfo(ctx_id, hostBlobId,
-                                                  info->sharedMemory->releaseHandle(), handleType,
-                                                  info->caching, std::nullopt);
+            ExternalObjectManager::get()->addBlobDescriptorInfo(
+                ctx_id, hostBlobId, info->sharedMemory->releaseHandle(), handleType, info->caching,
+                std::nullopt);
         } else if (m_emu->features.ExternalBlob.enabled) {
             VkResult result;
             auto device = unbox_VkDevice(boxed_device);
@@ -5122,7 +5258,8 @@
 #endif
 
 #ifdef __linux__
-            if (hasDeviceExtension(device, VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME)) {
+            if (m_emu->deviceInfo.supportsDmaBuf &&
+                hasDeviceExtension(device, VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME)) {
                 getFd.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
                 handleType = STREAM_MEM_HANDLE_TYPE_DMABUF;
             }
@@ -5159,9 +5296,9 @@
 #endif
 
             ManagedDescriptor managedHandle(handle);
-            BlobManager::get()->addDescriptorInfo(ctx_id, hostBlobId, std::move(managedHandle),
-                                                  handleType, info->caching,
-                                                  std::optional<VulkanInfo>(vulkanInfo));
+            ExternalObjectManager::get()->addBlobDescriptorInfo(
+                ctx_id, hostBlobId, std::move(managedHandle), handleType, info->caching,
+                std::optional<VulkanInfo>(vulkanInfo));
         } else if (!info->needUnmap) {
             auto device = unbox_VkDevice(boxed_device);
             auto vk = dispatch_VkDevice(boxed_device);
@@ -5188,8 +5325,8 @@
                     "using this blob may be corrupted/offset.",
                     kPageSizeforBlob, hva, alignedHva);
             }
-            BlobManager::get()->addMapping(ctx_id, hostBlobId, (void*)(uintptr_t)alignedHva,
-                                           info->caching);
+            ExternalObjectManager::get()->addMapping(ctx_id, hostBlobId,
+                                                     (void*)(uintptr_t)alignedHva, info->caching);
             info->virtioGpuMapped = true;
             info->hostmemId = hostBlobId;
         }
@@ -5439,6 +5576,8 @@
                 usedFence = builder.CreateFenceForOp();
             }
             queueCompletedWaitable = builder.OnQueueSubmittedWithFence(usedFence);
+
+            deviceInfo->deviceOpTracker->PollAndProcessGarbage();
         }
 
         {
@@ -5466,6 +5605,7 @@
         auto result = dispatchVkQueueSubmit(vk, queue, submitCount, pSubmits, usedFence);
 
         if (result != VK_SUCCESS) {
+            WARN("dispatchVkQueueSubmit failed: %s [%d]", string_VkResult(result), result);
             return result;
         }
         {
@@ -5560,6 +5700,8 @@
         auto commandBuffer = unbox_VkCommandBuffer(boxed_commandBuffer);
         auto vk = dispatch_VkCommandBuffer(boxed_commandBuffer);
 
+        m_emu->deviceLostHelper.onResetCommandBuffer(commandBuffer);
+
         VkResult result = vk->vkResetCommandBuffer(commandBuffer, flags);
         if (VK_SUCCESS == result) {
             std::lock_guard<std::recursive_mutex> lock(mLock);
@@ -5576,7 +5718,13 @@
         auto vk = dispatch_VkDevice(boxed_device);
 
         if (!device) return;
+
+        for (uint32_t i = 0; i < commandBufferCount; i++) {
+            m_emu->deviceLostHelper.onFreeCommandBuffer(pCommandBuffers[i]);
+        }
+
         vk->vkFreeCommandBuffers(device, commandPool, commandBufferCount, pCommandBuffers);
+
         std::lock_guard<std::recursive_mutex> lock(mLock);
         for (uint32_t i = 0; i < commandBufferCount; i++) {
             const auto& cmdBufferInfoIt = mCmdBufferInfo.find(pCommandBuffers[i]);
@@ -5883,6 +6031,8 @@
             return result;
         }
 
+        m_emu->deviceLostHelper.onBeginCommandBuffer(commandBuffer, vk);
+
         std::lock_guard<std::recursive_mutex> lock(mLock);
 
         auto* commandBufferInfo = android::base::find(mCmdBufferInfo, commandBuffer);
@@ -5910,6 +6060,8 @@
         auto commandBuffer = unbox_VkCommandBuffer(boxed_commandBuffer);
         auto vk = dispatch_VkCommandBuffer(boxed_commandBuffer);
 
+        m_emu->deviceLostHelper.onEndCommandBuffer(commandBuffer, vk);
+
         std::lock_guard<std::recursive_mutex> lock(mLock);
 
         auto* commandBufferInfo = android::base::find(mCmdBufferInfo, commandBuffer);
@@ -6563,9 +6715,70 @@
         return;
     }
 
-    void on_DeviceLost() { GFXSTREAM_ABORT(FatalError(VK_ERROR_DEVICE_LOST)); }
+    VkResult on_vkEnumeratePhysicalDeviceGroups(
+        android::base::BumpPool* pool, VkInstance boxed_instance,
+        uint32_t* pPhysicalDeviceGroupCount,
+        VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties) {
+        auto instance = unbox_VkInstance(boxed_instance);
+        auto vk = dispatch_VkInstance(boxed_instance);
 
-    void DeviceLostHandler() {}
+        std::vector<VkPhysicalDevice> physicalDevices;
+        auto res = GetPhysicalDevices(instance, vk, physicalDevices);
+        if (res != VK_SUCCESS) {
+            return res;
+        }
+
+        {
+            std::lock_guard<std::recursive_mutex> lock(mLock);
+            FilterPhysicalDevicesLocked(instance, vk, physicalDevices);
+        }
+
+        const uint32_t requestedCount = pPhysicalDeviceGroupCount ? *pPhysicalDeviceGroupCount : 0;
+        const uint32_t availableCount = static_cast<uint32_t>(physicalDevices.size());
+
+        if (pPhysicalDeviceGroupCount) {
+            *pPhysicalDeviceGroupCount = availableCount;
+        }
+        if (pPhysicalDeviceGroupCount && pPhysicalDeviceGroupProperties) {
+            for (uint32_t i = 0; i < std::min(requestedCount, availableCount); ++i) {
+                pPhysicalDeviceGroupProperties[i] = VkPhysicalDeviceGroupProperties{
+                    .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES,
+                    .pNext = nullptr,
+                    .physicalDeviceCount = 1,
+                    .physicalDevices =
+                        {
+                            unboxed_to_boxed_VkPhysicalDevice(physicalDevices[i]),
+                        },
+                    .subsetAllocation = VK_FALSE,
+                };
+            }
+            if (requestedCount < availableCount) {
+                return VK_INCOMPLETE;
+            }
+        }
+
+        return VK_SUCCESS;
+    }
+
+    void on_DeviceLost() {
+        {
+            std::lock_guard<std::recursive_mutex> lock(mLock);
+
+            std::vector<DeviceLostHelper::DeviceWithQueues> devicesToQueues;
+            for (const auto& [device, deviceInfo] : mDeviceInfo) {
+                auto& deviceToQueues = devicesToQueues.emplace_back();
+                deviceToQueues.device = device;
+                deviceToQueues.deviceDispatch = dispatch_VkDevice(deviceInfo.boxed);
+                for (const auto& [queueIndex, queues] : deviceInfo.queues) {
+                    deviceToQueues.queues.insert(deviceToQueues.queues.end(), queues.begin(),
+                                                 queues.end());
+                }
+            }
+            m_emu->deviceLostHelper.onDeviceLost(devicesToQueues);
+        }
+
+        GFXSTREAM_ABORT(FatalError(VK_ERROR_DEVICE_LOST));
+    }
 
     void on_CheckOutOfMemory(VkResult result, uint32_t opCode, const VkDecoderContext& context,
                              std::optional<uint64_t> allocationSize = std::nullopt) {
@@ -7020,6 +7233,7 @@
         return (type)sBoxedHandleManager.getBoxedFromUnboxedLocked((uint64_t)(uintptr_t)unboxed); \
     }                                                                                             \
     type unbox_##type(type boxed) {                                                               \
+        AutoLock lock(sBoxedHandleManager.lock);                                                  \
         auto elt = sBoxedHandleManager.get((uint64_t)(uintptr_t)boxed);                           \
         if (!elt) {                                                                               \
             if constexpr (!std::is_same_v<type, VkFence>) {                                       \
@@ -7150,7 +7364,8 @@
 #ifdef __linux__
         // A dma-buf is a Linux kernel construct, commonly used with open-source DRM drivers.
         // See https://docs.kernel.org/driver-api/dma-buf.html for details.
-        if (hasDeviceExtension(properties, VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME)) {
+        if (m_emu->deviceInfo.supportsDmaBuf &&
+            hasDeviceExtension(properties, VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME)) {
             res.push_back(VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME);
         }
 #endif
@@ -7175,6 +7390,10 @@
             res.push_back(VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME);
         }
 
+        if (m_emu->instanceSupportsExternalFenceCapabilities) {
+            res.push_back(VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME);
+        }
+
         if (m_emu->debugUtilsAvailableAndRequested) {
             res.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
         }
@@ -7283,6 +7502,80 @@
         return !feature.textureCompressionASTC_LDR;
     }
 
+    void getSupportedFenceHandleTypes(VulkanDispatch* vk, VkPhysicalDevice physicalDevice,
+                                      uint32_t* supportedFenceHandleTypes) {
+        if (!m_emu->instanceSupportsExternalFenceCapabilities) {
+            return;
+        }
+
+        VkExternalFenceHandleTypeFlagBits handleTypes[] = {
+            VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR,
+            VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT,
+            VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT,
+        };
+
+        for (auto handleType : handleTypes) {
+            VkExternalFenceProperties externalFenceProps;
+            externalFenceProps.sType = VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES;
+            externalFenceProps.pNext = nullptr;
+
+            VkPhysicalDeviceExternalFenceInfo externalFenceInfo = {
+                VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO, nullptr, handleType};
+
+            vk->vkGetPhysicalDeviceExternalFenceProperties(physicalDevice, &externalFenceInfo,
+                                                           &externalFenceProps);
+
+            if ((externalFenceProps.externalFenceFeatures &
+                 (VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT)) == 0) {
+                continue;
+            }
+
+            if ((externalFenceProps.externalFenceFeatures &
+                 (VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT)) == 0) {
+                continue;
+            }
+
+            *supportedFenceHandleTypes |= handleType;
+        }
+    }
+
+    void getSupportedSemaphoreHandleTypes(VulkanDispatch* vk, VkPhysicalDevice physicalDevice,
+                                          uint32_t* supportedBinarySemaphoreHandleTypes) {
+        if (!m_emu->instanceSupportsExternalSemaphoreCapabilities) {
+            return;
+        }
+
+        VkExternalSemaphoreHandleTypeFlagBits handleTypes[] = {
+            VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR,
+            VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT,
+            VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
+        };
+
+        for (auto handleType : handleTypes) {
+            VkExternalSemaphoreProperties externalSemaphoreProps;
+            externalSemaphoreProps.sType = VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES;
+            externalSemaphoreProps.pNext = nullptr;
+
+            VkPhysicalDeviceExternalSemaphoreInfo externalSemaphoreInfo = {
+                VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO, nullptr, handleType};
+
+            vk->vkGetPhysicalDeviceExternalSemaphoreProperties(
+                physicalDevice, &externalSemaphoreInfo, &externalSemaphoreProps);
+
+            if ((externalSemaphoreProps.externalSemaphoreFeatures &
+                 (VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT)) == 0) {
+                continue;
+            }
+
+            if ((externalSemaphoreProps.externalSemaphoreFeatures &
+                 (VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT)) == 0) {
+                continue;
+            }
+
+            *supportedBinarySemaphoreHandleTypes |= handleType;
+        }
+    }
+
     bool supportsSwapchainMaintenance1(VkPhysicalDevice physicalDevice, VulkanDispatch* vk) {
         bool hasGetPhysicalDeviceFeatures2 = false;
         bool hasGetPhysicalDeviceFeatures2KHR = false;
@@ -8311,6 +8604,12 @@
     return mImpl->on_vkGetSemaphoreFdKHR(pool, device, pGetFdInfo, pFd);
 }
 
+VkResult VkDecoderGlobalState::on_vkGetSemaphoreGOOGLE(android::base::BumpPool* pool,
+                                                       VkDevice device, VkSemaphore semaphore,
+                                                       uint64_t syncId) {
+    return mImpl->on_vkGetSemaphoreGOOGLE(pool, device, semaphore, syncId);
+}
+
 void VkDecoderGlobalState::on_vkDestroySemaphore(android::base::BumpPool* pool, VkDevice device,
                                                  VkSemaphore semaphore,
                                                  const VkAllocationCallbacks* pAllocator) {
@@ -9067,9 +9366,21 @@
     mImpl->on_vkDestroySamplerYcbcrConversion(pool, device, ycbcrConversion, pAllocator);
 }
 
-void VkDecoderGlobalState::on_DeviceLost() { mImpl->on_DeviceLost(); }
+VkResult VkDecoderGlobalState::on_vkEnumeratePhysicalDeviceGroups(
+    android::base::BumpPool* pool, VkInstance instance, uint32_t* pPhysicalDeviceGroupCount,
+    VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties) {
+    return mImpl->on_vkEnumeratePhysicalDeviceGroups(pool, instance, pPhysicalDeviceGroupCount,
+                                                     pPhysicalDeviceGroupProperties);
+}
 
-void VkDecoderGlobalState::DeviceLostHandler() { mImpl->DeviceLostHandler(); }
+VkResult VkDecoderGlobalState::on_vkEnumeratePhysicalDeviceGroupsKHR(
+    android::base::BumpPool* pool, VkInstance instance, uint32_t* pPhysicalDeviceGroupCount,
+    VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties) {
+    return mImpl->on_vkEnumeratePhysicalDeviceGroups(pool, instance, pPhysicalDeviceGroupCount,
+                                                     pPhysicalDeviceGroupProperties);
+}
+
+void VkDecoderGlobalState::on_DeviceLost() { mImpl->on_DeviceLost(); }
 
 void VkDecoderGlobalState::on_CheckOutOfMemory(VkResult result, uint32_t opCode,
                                                const VkDecoderContext& context,
diff --git a/host/vulkan/VkDecoderGlobalState.h b/host/vulkan/VkDecoderGlobalState.h
index 705c077..dcb24c5 100644
--- a/host/vulkan/VkDecoderGlobalState.h
+++ b/host/vulkan/VkDecoderGlobalState.h
@@ -512,6 +512,8 @@
                                        const VkImportSemaphoreFdInfoKHR* pImportSemaphoreFdInfo);
     VkResult on_vkGetSemaphoreFdKHR(android::base::BumpPool* pool, VkDevice boxed_device,
                                     const VkSemaphoreGetFdInfoKHR* pGetFdInfo, int* pFd);
+    VkResult on_vkGetSemaphoreGOOGLE(android::base::BumpPool* pool, VkDevice boxed_device,
+                                     VkSemaphore semaphore, uint64_t syncId);
     void on_vkDestroySemaphore(android::base::BumpPool* pool, VkDevice boxed_device,
                                VkSemaphore semaphore, const VkAllocationCallbacks* pAllocator);
 
@@ -703,9 +705,14 @@
                                                VkSamplerYcbcrConversion ycbcrConversion,
                                                const VkAllocationCallbacks* pAllocator);
 
-    void on_DeviceLost();
+    VkResult on_vkEnumeratePhysicalDeviceGroups(
+        android::base::BumpPool* pool, VkInstance instance, uint32_t* pPhysicalDeviceGroupCount,
+        VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties);
+    VkResult on_vkEnumeratePhysicalDeviceGroupsKHR(
+        android::base::BumpPool* pool, VkInstance instance, uint32_t* pPhysicalDeviceGroupCount,
+        VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties);
 
-    void DeviceLostHandler();
+    void on_DeviceLost();
 
     void on_CheckOutOfMemory(VkResult result, uint32_t opCode, const VkDecoderContext& context,
                              std::optional<uint64_t> allocationSize = std::nullopt);
diff --git a/host/vulkan/VkDecoderInternalStructs.h b/host/vulkan/VkDecoderInternalStructs.h
index fc0d514..f8acb70 100644
--- a/host/vulkan/VkDecoderInternalStructs.h
+++ b/host/vulkan/VkDecoderInternalStructs.h
@@ -187,12 +187,19 @@
     VkPhysicalDevice boxed = nullptr;
 };
 
+struct ExternalFenceInfo {
+    VkExternalSemaphoreHandleTypeFlagBits supportedBinarySemaphoreHandleTypes;
+    VkExternalFenceHandleTypeFlagBits supportedFenceHandleTypes;
+};
+
 struct DeviceInfo {
     std::unordered_map<uint32_t, std::vector<VkQueue>> queues;
     std::vector<std::string> enabledExtensionNames;
     bool emulateTextureEtc2 = false;
     bool emulateTextureAstc = false;
     bool useAstcCpuDecompression = false;
+
+    ExternalFenceInfo externalFenceInfo;
     VkPhysicalDevice physicalDevice;
     VkDevice boxed = nullptr;
     DebugUtilsHelper debugUtilsHelper = DebugUtilsHelper::withUtilsDisabled();
diff --git a/host/vulkan/VkDecoderSnapshot.cpp b/host/vulkan/VkDecoderSnapshot.cpp
index 370c9a9..25a024a 100644
--- a/host/vulkan/VkDecoderSnapshot.cpp
+++ b/host/vulkan/VkDecoderSnapshot.cpp
@@ -2382,8 +2382,6 @@
         uint32_t* pSparseMemoryRequirementCount,
         VkSparseImageMemoryRequirements2* pSparseMemoryRequirements) {}
 #endif
-#ifdef VK_KHR_surface
-#endif
 #ifdef VK_KHR_swapchain
     void vkCreateSwapchainKHR(const uint8_t* snapshotTraceBegin, size_t snapshotTraceBytes,
                               android::base::BumpPool* pool, VkResult input_result, VkDevice device,
@@ -2440,12 +2438,6 @@
                                 VkDevice device, const VkAcquireNextImageInfoKHR* pAcquireInfo,
                                 uint32_t* pImageIndex) {}
 #endif
-#ifdef VK_KHR_xcb_surface
-#endif
-#ifdef VK_KHR_android_surface
-#endif
-#ifdef VK_KHR_win32_surface
-#endif
 #ifdef VK_KHR_dynamic_rendering
     void vkCmdBeginRenderingKHR(const uint8_t* snapshotTraceBegin, size_t snapshotTraceBytes,
                                 android::base::BumpPool* pool, VkCommandBuffer commandBuffer,
@@ -2518,12 +2510,6 @@
         const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo,
         VkExternalBufferProperties* pExternalBufferProperties) {}
 #endif
-#ifdef VK_KHR_external_memory
-#endif
-#ifdef VK_KHR_external_memory_win32
-#endif
-#ifdef VK_KHR_external_memory_fd
-#endif
 #ifdef VK_KHR_external_semaphore_capabilities
     void vkGetPhysicalDeviceExternalSemaphorePropertiesKHR(
         const uint8_t* snapshotTraceBegin, size_t snapshotTraceBytes, android::base::BumpPool* pool,
@@ -2531,10 +2517,6 @@
         const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo,
         VkExternalSemaphoreProperties* pExternalSemaphoreProperties) {}
 #endif
-#ifdef VK_KHR_external_semaphore
-#endif
-#ifdef VK_KHR_external_semaphore_win32
-#endif
 #ifdef VK_KHR_external_semaphore_fd
     void vkImportSemaphoreFdKHR(const uint8_t* snapshotTraceBegin, size_t snapshotTraceBytes,
                                 android::base::BumpPool* pool, VkResult input_result,
@@ -2544,10 +2526,6 @@
                              android::base::BumpPool* pool, VkResult input_result, VkDevice device,
                              const VkSemaphoreGetFdInfoKHR* pGetFdInfo, int* pFd) {}
 #endif
-#ifdef VK_KHR_shader_float16_int8
-#endif
-#ifdef VK_KHR_incremental_present
-#endif
 #ifdef VK_KHR_descriptor_update_template
     void vkCreateDescriptorUpdateTemplateKHR(
         const uint8_t* snapshotTraceBegin, size_t snapshotTraceBytes, android::base::BumpPool* pool,
@@ -2586,8 +2564,6 @@
                                               VkDescriptorUpdateTemplate descriptorUpdateTemplate,
                                               const void* pData) {}
 #endif
-#ifdef VK_KHR_imageless_framebuffer
-#endif
 #ifdef VK_KHR_create_renderpass2
     void vkCreateRenderPass2KHR(const uint8_t* snapshotTraceBegin, size_t snapshotTraceBytes,
                                 android::base::BumpPool* pool, VkResult input_result,
@@ -2660,8 +2636,6 @@
         const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo,
         VkExternalFenceProperties* pExternalFenceProperties) {}
 #endif
-#ifdef VK_KHR_external_fence
-#endif
 #ifdef VK_KHR_external_fence_fd
     void vkImportFenceFdKHR(const uint8_t* snapshotTraceBegin, size_t snapshotTraceBytes,
                             android::base::BumpPool* pool, VkResult input_result, VkDevice device,
@@ -2670,12 +2644,6 @@
                          android::base::BumpPool* pool, VkResult input_result, VkDevice device,
                          const VkFenceGetFdInfoKHR* pGetFdInfo, int* pFd) {}
 #endif
-#ifdef VK_KHR_maintenance2
-#endif
-#ifdef VK_KHR_dedicated_allocation
-#endif
-#ifdef VK_KHR_storage_buffer_storage_class
-#endif
 #ifdef VK_KHR_get_memory_requirements2
     void vkGetImageMemoryRequirements2KHR(const uint8_t* snapshotTraceBegin,
                                           size_t snapshotTraceBytes, android::base::BumpPool* pool,
@@ -2693,8 +2661,6 @@
         uint32_t* pSparseMemoryRequirementCount,
         VkSparseImageMemoryRequirements2* pSparseMemoryRequirements) {}
 #endif
-#ifdef VK_KHR_image_format_list
-#endif
 #ifdef VK_KHR_sampler_ycbcr_conversion
     void vkCreateSamplerYcbcrConversionKHR(const uint8_t* snapshotTraceBegin,
                                            size_t snapshotTraceBytes, android::base::BumpPool* pool,
@@ -2766,12 +2732,6 @@
                                             const VkDescriptorSetLayoutCreateInfo* pCreateInfo,
                                             VkDescriptorSetLayoutSupport* pSupport) {}
 #endif
-#ifdef VK_KHR_shader_subgroup_extended_types
-#endif
-#ifdef VK_KHR_vulkan_memory_model
-#endif
-#ifdef VK_KHR_shader_terminate_invocation
-#endif
 #ifdef VK_KHR_buffer_device_address
     void vkGetBufferDeviceAddressKHR(const uint8_t* snapshotTraceBegin, size_t snapshotTraceBytes,
                                      android::base::BumpPool* pool, VkDeviceAddress input_result,
@@ -2801,10 +2761,6 @@
         uint32_t* pInternalRepresentationCount,
         VkPipelineExecutableInternalRepresentationKHR* pInternalRepresentations) {}
 #endif
-#ifdef VK_KHR_shader_integer_dot_product
-#endif
-#ifdef VK_KHR_shader_non_semantic_info
-#endif
 #ifdef VK_KHR_synchronization2
     void vkCmdSetEvent2KHR(const uint8_t* snapshotTraceBegin, size_t snapshotTraceBytes,
                            android::base::BumpPool* pool, VkCommandBuffer commandBuffer,
@@ -2901,8 +2857,6 @@
                                      uint32_t* pCheckpointDataCount,
                                      VkCheckpointData2NV* pCheckpointData) {}
 #endif
-#ifdef VK_KHR_zero_initialize_workgroup_memory
-#endif
 #ifdef VK_KHR_copy_commands2
     void vkCmdCopyBuffer2KHR(const uint8_t* snapshotTraceBegin, size_t snapshotTraceBytes,
                              android::base::BumpPool* pool, VkCommandBuffer commandBuffer,
@@ -2989,8 +2943,6 @@
         }
     }
 #endif
-#ifdef VK_KHR_format_feature_flags2
-#endif
 #ifdef VK_KHR_maintenance4
     void vkGetDeviceBufferMemoryRequirementsKHR(const uint8_t* snapshotTraceBegin,
                                                 size_t snapshotTraceBytes,
@@ -3189,16 +3141,6 @@
         }
     }
 #endif
-#ifdef VK_AMD_gpu_shader_half_float
-#endif
-#ifdef VK_EXT_texture_compression_astc_hdr
-#endif
-#ifdef VK_EXT_depth_clip_enable
-#endif
-#ifdef VK_EXT_swapchain_colorspace
-#endif
-#ifdef VK_EXT_queue_family_foreign
-#endif
 #ifdef VK_EXT_debug_utils
     void vkSetDebugUtilsObjectNameEXT(const uint8_t* snapshotTraceBegin, size_t snapshotTraceBytes,
                                       android::base::BumpPool* pool, VkResult input_result,
@@ -3289,26 +3231,6 @@
                                       VkDebugUtilsMessageTypeFlagsEXT messageTypes,
                                       const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData) {}
 #endif
-#ifdef VK_ANDROID_external_memory_android_hardware_buffer
-#endif
-#ifdef VK_EXT_inline_uniform_block
-#endif
-#ifdef VK_EXT_shader_stencil_export
-#endif
-#ifdef VK_EXT_vertex_attribute_divisor
-#endif
-#ifdef VK_EXT_pipeline_creation_feedback
-#endif
-#ifdef VK_NV_shader_subgroup_partitioned
-#endif
-#ifdef VK_EXT_metal_surface
-#endif
-#ifdef VK_EXT_fragment_density_map
-#endif
-#ifdef VK_EXT_scalar_block_layout
-#endif
-#ifdef VK_EXT_subgroup_size_control
-#endif
 #ifdef VK_EXT_tooling_info
     void vkGetPhysicalDeviceToolPropertiesEXT(const uint8_t* snapshotTraceBegin,
                                               size_t snapshotTraceBytes,
@@ -3316,10 +3238,6 @@
                                               VkPhysicalDevice physicalDevice, uint32_t* pToolCount,
                                               VkPhysicalDeviceToolProperties* pToolProperties) {}
 #endif
-#ifdef VK_EXT_validation_features
-#endif
-#ifdef VK_EXT_provoking_vertex
-#endif
 #ifdef VK_EXT_line_rasterization
     void vkCmdSetLineStippleEXT(const uint8_t* snapshotTraceBegin, size_t snapshotTraceBytes,
                                 android::base::BumpPool* pool, VkCommandBuffer commandBuffer,
@@ -3336,8 +3254,6 @@
         }
     }
 #endif
-#ifdef VK_EXT_index_type_uint8
-#endif
 #ifdef VK_EXT_extended_dynamic_state
     void vkCmdSetCullModeEXT(const uint8_t* snapshotTraceBegin, size_t snapshotTraceBytes,
                              android::base::BumpPool* pool, VkCommandBuffer commandBuffer,
@@ -3541,16 +3457,6 @@
                                      VkDevice device,
                                      const VkReleaseSwapchainImagesInfoEXT* pReleaseInfo) {}
 #endif
-#ifdef VK_EXT_shader_demote_to_helper_invocation
-#endif
-#ifdef VK_EXT_texel_buffer_alignment
-#endif
-#ifdef VK_EXT_device_memory_report
-#endif
-#ifdef VK_EXT_robustness2
-#endif
-#ifdef VK_EXT_custom_border_color
-#endif
 #ifdef VK_EXT_private_data
     void vkCreatePrivateDataSlotEXT(const uint8_t* snapshotTraceBegin, size_t snapshotTraceBytes,
                                     android::base::BumpPool* pool, VkResult input_result,
@@ -3570,22 +3476,6 @@
                              VkObjectType objectType, uint64_t objectHandle,
                              VkPrivateDataSlot privateDataSlot, uint64_t* pData) {}
 #endif
-#ifdef VK_EXT_pipeline_creation_cache_control
-#endif
-#ifdef VK_EXT_metal_objects
-#endif
-#ifdef VK_EXT_graphics_pipeline_library
-#endif
-#ifdef VK_EXT_ycbcr_2plane_444_formats
-#endif
-#ifdef VK_EXT_image_robustness
-#endif
-#ifdef VK_EXT_image_compression_control
-#endif
-#ifdef VK_EXT_4444_formats
-#endif
-#ifdef VK_EXT_primitive_topology_list_restart
-#endif
 #ifdef VK_EXT_extended_dynamic_state2
     void vkCmdSetPatchControlPointsEXT(const uint8_t* snapshotTraceBegin, size_t snapshotTraceBytes,
                                        android::base::BumpPool* pool, VkCommandBuffer commandBuffer,
@@ -3844,14 +3734,83 @@
                                    android::base::BumpPool* pool, VkQueue queue,
                                    uint32_t submitCount, const VkSubmitInfo2* pSubmits,
                                    VkFence fence) {}
+    void vkGetSemaphoreGOOGLE(const uint8_t* snapshotTraceBegin, size_t snapshotTraceBytes,
+                              android::base::BumpPool* pool, VkResult input_result, VkDevice device,
+                              VkSemaphore semaphore, uint64_t syncId) {}
 #endif
-#ifdef VK_EXT_load_store_op_none
+#ifdef VK_KHR_ray_tracing_pipeline
+    void vkCmdTraceRaysKHR(const uint8_t* snapshotTraceBegin, size_t snapshotTraceBytes,
+                           android::base::BumpPool* pool, VkCommandBuffer commandBuffer,
+                           const VkStridedDeviceAddressRegionKHR* pRaygenShaderBindingTable,
+                           const VkStridedDeviceAddressRegionKHR* pMissShaderBindingTable,
+                           const VkStridedDeviceAddressRegionKHR* pHitShaderBindingTable,
+                           const VkStridedDeviceAddressRegionKHR* pCallableShaderBindingTable,
+                           uint32_t width, uint32_t height, uint32_t depth) {
+        android::base::AutoLock lock(mLock);
+        // commandBuffer modify
+        auto apiHandle = mReconstruction.createApiInfo();
+        auto apiInfo = mReconstruction.getApiInfo(apiHandle);
+        mReconstruction.setApiTrace(apiInfo, OP_vkCmdTraceRaysKHR, snapshotTraceBegin,
+                                    snapshotTraceBytes);
+        for (uint32_t i = 0; i < 1; ++i) {
+            VkCommandBuffer boxed = unboxed_to_boxed_VkCommandBuffer((&commandBuffer)[i]);
+            mReconstruction.forEachHandleAddModifyApi((const uint64_t*)(&boxed), 1, apiHandle);
+        }
+    }
+    void vkCreateRayTracingPipelinesKHR(const uint8_t* snapshotTraceBegin,
+                                        size_t snapshotTraceBytes, android::base::BumpPool* pool,
+                                        VkResult input_result, VkDevice device,
+                                        VkDeferredOperationKHR deferredOperation,
+                                        VkPipelineCache pipelineCache, uint32_t createInfoCount,
+                                        const VkRayTracingPipelineCreateInfoKHR* pCreateInfos,
+                                        const VkAllocationCallbacks* pAllocator,
+                                        VkPipeline* pPipelines) {}
+    void vkGetRayTracingCaptureReplayShaderGroupHandlesKHR(
+        const uint8_t* snapshotTraceBegin, size_t snapshotTraceBytes, android::base::BumpPool* pool,
+        VkResult input_result, VkDevice device, VkPipeline pipeline, uint32_t firstGroup,
+        uint32_t groupCount, size_t dataSize, void* pData) {}
+    void vkCmdTraceRaysIndirectKHR(
+        const uint8_t* snapshotTraceBegin, size_t snapshotTraceBytes, android::base::BumpPool* pool,
+        VkCommandBuffer commandBuffer,
+        const VkStridedDeviceAddressRegionKHR* pRaygenShaderBindingTable,
+        const VkStridedDeviceAddressRegionKHR* pMissShaderBindingTable,
+        const VkStridedDeviceAddressRegionKHR* pHitShaderBindingTable,
+        const VkStridedDeviceAddressRegionKHR* pCallableShaderBindingTable,
+        VkDeviceAddress indirectDeviceAddress) {
+        android::base::AutoLock lock(mLock);
+        // commandBuffer modify
+        auto apiHandle = mReconstruction.createApiInfo();
+        auto apiInfo = mReconstruction.getApiInfo(apiHandle);
+        mReconstruction.setApiTrace(apiInfo, OP_vkCmdTraceRaysIndirectKHR, snapshotTraceBegin,
+                                    snapshotTraceBytes);
+        for (uint32_t i = 0; i < 1; ++i) {
+            VkCommandBuffer boxed = unboxed_to_boxed_VkCommandBuffer((&commandBuffer)[i]);
+            mReconstruction.forEachHandleAddModifyApi((const uint64_t*)(&boxed), 1, apiHandle);
+        }
+    }
+    void vkGetRayTracingShaderGroupStackSizeKHR(const uint8_t* snapshotTraceBegin,
+                                                size_t snapshotTraceBytes,
+                                                android::base::BumpPool* pool,
+                                                VkDeviceSize input_result, VkDevice device,
+                                                VkPipeline pipeline, uint32_t group,
+                                                VkShaderGroupShaderKHR groupShader) {}
+    void vkCmdSetRayTracingPipelineStackSizeKHR(const uint8_t* snapshotTraceBegin,
+                                                size_t snapshotTraceBytes,
+                                                android::base::BumpPool* pool,
+                                                VkCommandBuffer commandBuffer,
+                                                uint32_t pipelineStackSize) {
+        android::base::AutoLock lock(mLock);
+        // commandBuffer modify
+        auto apiHandle = mReconstruction.createApiInfo();
+        auto apiInfo = mReconstruction.getApiInfo(apiHandle);
+        mReconstruction.setApiTrace(apiInfo, OP_vkCmdSetRayTracingPipelineStackSizeKHR,
+                                    snapshotTraceBegin, snapshotTraceBytes);
+        for (uint32_t i = 0; i < 1; ++i) {
+            VkCommandBuffer boxed = unboxed_to_boxed_VkCommandBuffer((&commandBuffer)[i]);
+            mReconstruction.forEachHandleAddModifyApi((const uint64_t*)(&boxed), 1, apiHandle);
+        }
+    }
 #endif
-#ifdef VK_EXT_image_compression_control_swapchain
-#endif
-#ifdef VK_QNX_external_memory_screen_buffer
-#endif
-
    private:
     android::base::Lock mLock;
     VkReconstruction mReconstruction;
@@ -7366,3 +7325,83 @@
                                      submitCount, pSubmits, fence);
 }
 #endif
+#ifdef VK_GOOGLE_gfxstream
+void VkDecoderSnapshot::vkGetSemaphoreGOOGLE(const uint8_t* snapshotTraceBegin,
+                                             size_t snapshotTraceBytes,
+                                             android::base::BumpPool* pool, VkResult input_result,
+                                             VkDevice device, VkSemaphore semaphore,
+                                             uint64_t syncId) {
+    mImpl->vkGetSemaphoreGOOGLE(snapshotTraceBegin, snapshotTraceBytes, pool, input_result, device,
+                                semaphore, syncId);
+}
+#endif
+#ifdef VK_KHR_ray_tracing_pipeline
+void VkDecoderSnapshot::vkCmdTraceRaysKHR(
+    const uint8_t* snapshotTraceBegin, size_t snapshotTraceBytes, android::base::BumpPool* pool,
+    VkCommandBuffer commandBuffer, const VkStridedDeviceAddressRegionKHR* pRaygenShaderBindingTable,
+    const VkStridedDeviceAddressRegionKHR* pMissShaderBindingTable,
+    const VkStridedDeviceAddressRegionKHR* pHitShaderBindingTable,
+    const VkStridedDeviceAddressRegionKHR* pCallableShaderBindingTable, uint32_t width,
+    uint32_t height, uint32_t depth) {
+    mImpl->vkCmdTraceRaysKHR(snapshotTraceBegin, snapshotTraceBytes, pool, commandBuffer,
+                             pRaygenShaderBindingTable, pMissShaderBindingTable,
+                             pHitShaderBindingTable, pCallableShaderBindingTable, width, height,
+                             depth);
+}
+#endif
+#ifdef VK_KHR_ray_tracing_pipeline
+void VkDecoderSnapshot::vkCreateRayTracingPipelinesKHR(
+    const uint8_t* snapshotTraceBegin, size_t snapshotTraceBytes, android::base::BumpPool* pool,
+    VkResult input_result, VkDevice device, VkDeferredOperationKHR deferredOperation,
+    VkPipelineCache pipelineCache, uint32_t createInfoCount,
+    const VkRayTracingPipelineCreateInfoKHR* pCreateInfos, const VkAllocationCallbacks* pAllocator,
+    VkPipeline* pPipelines) {
+    mImpl->vkCreateRayTracingPipelinesKHR(snapshotTraceBegin, snapshotTraceBytes, pool,
+                                          input_result, device, deferredOperation, pipelineCache,
+                                          createInfoCount, pCreateInfos, pAllocator, pPipelines);
+}
+#endif
+#ifdef VK_KHR_ray_tracing_pipeline
+void VkDecoderSnapshot::vkGetRayTracingCaptureReplayShaderGroupHandlesKHR(
+    const uint8_t* snapshotTraceBegin, size_t snapshotTraceBytes, android::base::BumpPool* pool,
+    VkResult input_result, VkDevice device, VkPipeline pipeline, uint32_t firstGroup,
+    uint32_t groupCount, size_t dataSize, void* pData) {
+    mImpl->vkGetRayTracingCaptureReplayShaderGroupHandlesKHR(
+        snapshotTraceBegin, snapshotTraceBytes, pool, input_result, device, pipeline, firstGroup,
+        groupCount, dataSize, pData);
+}
+#endif
+#ifdef VK_KHR_ray_tracing_pipeline
+void VkDecoderSnapshot::vkCmdTraceRaysIndirectKHR(
+    const uint8_t* snapshotTraceBegin, size_t snapshotTraceBytes, android::base::BumpPool* pool,
+    VkCommandBuffer commandBuffer, const VkStridedDeviceAddressRegionKHR* pRaygenShaderBindingTable,
+    const VkStridedDeviceAddressRegionKHR* pMissShaderBindingTable,
+    const VkStridedDeviceAddressRegionKHR* pHitShaderBindingTable,
+    const VkStridedDeviceAddressRegionKHR* pCallableShaderBindingTable,
+    VkDeviceAddress indirectDeviceAddress) {
+    mImpl->vkCmdTraceRaysIndirectKHR(snapshotTraceBegin, snapshotTraceBytes, pool, commandBuffer,
+                                     pRaygenShaderBindingTable, pMissShaderBindingTable,
+                                     pHitShaderBindingTable, pCallableShaderBindingTable,
+                                     indirectDeviceAddress);
+}
+#endif
+#ifdef VK_KHR_ray_tracing_pipeline
+void VkDecoderSnapshot::vkGetRayTracingShaderGroupStackSizeKHR(
+    const uint8_t* snapshotTraceBegin, size_t snapshotTraceBytes, android::base::BumpPool* pool,
+    VkDeviceSize input_result, VkDevice device, VkPipeline pipeline, uint32_t group,
+    VkShaderGroupShaderKHR groupShader) {
+    mImpl->vkGetRayTracingShaderGroupStackSizeKHR(snapshotTraceBegin, snapshotTraceBytes, pool,
+                                                  input_result, device, pipeline, group,
+                                                  groupShader);
+}
+#endif
+#ifdef VK_KHR_ray_tracing_pipeline
+void VkDecoderSnapshot::vkCmdSetRayTracingPipelineStackSizeKHR(const uint8_t* snapshotTraceBegin,
+                                                               size_t snapshotTraceBytes,
+                                                               android::base::BumpPool* pool,
+                                                               VkCommandBuffer commandBuffer,
+                                                               uint32_t pipelineStackSize) {
+    mImpl->vkCmdSetRayTracingPipelineStackSizeKHR(snapshotTraceBegin, snapshotTraceBytes, pool,
+                                                  commandBuffer, pipelineStackSize);
+}
+#endif
diff --git a/host/vulkan/VkDecoderSnapshot.h b/host/vulkan/VkDecoderSnapshot.h
index 4812b60..466adc6 100644
--- a/host/vulkan/VkDecoderSnapshot.h
+++ b/host/vulkan/VkDecoderSnapshot.h
@@ -895,8 +895,6 @@
         uint32_t* pSparseMemoryRequirementCount,
         VkSparseImageMemoryRequirements2* pSparseMemoryRequirements);
 #endif
-#ifdef VK_KHR_surface
-#endif
 #ifdef VK_KHR_swapchain
     void vkCreateSwapchainKHR(const uint8_t* snapshotTraceBegin, size_t snapshotTraceBytes,
                               android::base::BumpPool* pool, VkResult input_result, VkDevice device,
@@ -935,12 +933,6 @@
                                 VkDevice device, const VkAcquireNextImageInfoKHR* pAcquireInfo,
                                 uint32_t* pImageIndex);
 #endif
-#ifdef VK_KHR_xcb_surface
-#endif
-#ifdef VK_KHR_android_surface
-#endif
-#ifdef VK_KHR_win32_surface
-#endif
 #ifdef VK_KHR_dynamic_rendering
     void vkCmdBeginRenderingKHR(const uint8_t* snapshotTraceBegin, size_t snapshotTraceBytes,
                                 android::base::BumpPool* pool, VkCommandBuffer commandBuffer,
@@ -991,12 +983,6 @@
         const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo,
         VkExternalBufferProperties* pExternalBufferProperties);
 #endif
-#ifdef VK_KHR_external_memory
-#endif
-#ifdef VK_KHR_external_memory_win32
-#endif
-#ifdef VK_KHR_external_memory_fd
-#endif
 #ifdef VK_KHR_external_semaphore_capabilities
     void vkGetPhysicalDeviceExternalSemaphorePropertiesKHR(
         const uint8_t* snapshotTraceBegin, size_t snapshotTraceBytes, android::base::BumpPool* pool,
@@ -1004,10 +990,6 @@
         const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo,
         VkExternalSemaphoreProperties* pExternalSemaphoreProperties);
 #endif
-#ifdef VK_KHR_external_semaphore
-#endif
-#ifdef VK_KHR_external_semaphore_win32
-#endif
 #ifdef VK_KHR_external_semaphore_fd
     void vkImportSemaphoreFdKHR(const uint8_t* snapshotTraceBegin, size_t snapshotTraceBytes,
                                 android::base::BumpPool* pool, VkResult input_result,
@@ -1017,10 +999,6 @@
                              android::base::BumpPool* pool, VkResult input_result, VkDevice device,
                              const VkSemaphoreGetFdInfoKHR* pGetFdInfo, int* pFd);
 #endif
-#ifdef VK_KHR_shader_float16_int8
-#endif
-#ifdef VK_KHR_incremental_present
-#endif
 #ifdef VK_KHR_descriptor_update_template
     void vkCreateDescriptorUpdateTemplateKHR(
         const uint8_t* snapshotTraceBegin, size_t snapshotTraceBytes, android::base::BumpPool* pool,
@@ -1040,8 +1018,6 @@
                                               VkDescriptorUpdateTemplate descriptorUpdateTemplate,
                                               const void* pData);
 #endif
-#ifdef VK_KHR_imageless_framebuffer
-#endif
 #ifdef VK_KHR_create_renderpass2
     void vkCreateRenderPass2KHR(const uint8_t* snapshotTraceBegin, size_t snapshotTraceBytes,
                                 android::base::BumpPool* pool, VkResult input_result,
@@ -1066,8 +1042,6 @@
         const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo,
         VkExternalFenceProperties* pExternalFenceProperties);
 #endif
-#ifdef VK_KHR_external_fence
-#endif
 #ifdef VK_KHR_external_fence_fd
     void vkImportFenceFdKHR(const uint8_t* snapshotTraceBegin, size_t snapshotTraceBytes,
                             android::base::BumpPool* pool, VkResult input_result, VkDevice device,
@@ -1076,12 +1050,6 @@
                          android::base::BumpPool* pool, VkResult input_result, VkDevice device,
                          const VkFenceGetFdInfoKHR* pGetFdInfo, int* pFd);
 #endif
-#ifdef VK_KHR_maintenance2
-#endif
-#ifdef VK_KHR_dedicated_allocation
-#endif
-#ifdef VK_KHR_storage_buffer_storage_class
-#endif
 #ifdef VK_KHR_get_memory_requirements2
     void vkGetImageMemoryRequirements2KHR(const uint8_t* snapshotTraceBegin,
                                           size_t snapshotTraceBytes, android::base::BumpPool* pool,
@@ -1099,8 +1067,6 @@
         uint32_t* pSparseMemoryRequirementCount,
         VkSparseImageMemoryRequirements2* pSparseMemoryRequirements);
 #endif
-#ifdef VK_KHR_image_format_list
-#endif
 #ifdef VK_KHR_sampler_ycbcr_conversion
     void vkCreateSamplerYcbcrConversionKHR(const uint8_t* snapshotTraceBegin,
                                            size_t snapshotTraceBytes, android::base::BumpPool* pool,
@@ -1131,12 +1097,6 @@
                                             const VkDescriptorSetLayoutCreateInfo* pCreateInfo,
                                             VkDescriptorSetLayoutSupport* pSupport);
 #endif
-#ifdef VK_KHR_shader_subgroup_extended_types
-#endif
-#ifdef VK_KHR_vulkan_memory_model
-#endif
-#ifdef VK_KHR_shader_terminate_invocation
-#endif
 #ifdef VK_KHR_buffer_device_address
     void vkGetBufferDeviceAddressKHR(const uint8_t* snapshotTraceBegin, size_t snapshotTraceBytes,
                                      android::base::BumpPool* pool, VkDeviceAddress input_result,
@@ -1166,10 +1126,6 @@
         uint32_t* pInternalRepresentationCount,
         VkPipelineExecutableInternalRepresentationKHR* pInternalRepresentations);
 #endif
-#ifdef VK_KHR_shader_integer_dot_product
-#endif
-#ifdef VK_KHR_shader_non_semantic_info
-#endif
 #ifdef VK_KHR_synchronization2
     void vkCmdSetEvent2KHR(const uint8_t* snapshotTraceBegin, size_t snapshotTraceBytes,
                            android::base::BumpPool* pool, VkCommandBuffer commandBuffer,
@@ -1200,8 +1156,6 @@
                                      uint32_t* pCheckpointDataCount,
                                      VkCheckpointData2NV* pCheckpointData);
 #endif
-#ifdef VK_KHR_zero_initialize_workgroup_memory
-#endif
 #ifdef VK_KHR_copy_commands2
     void vkCmdCopyBuffer2KHR(const uint8_t* snapshotTraceBegin, size_t snapshotTraceBytes,
                              android::base::BumpPool* pool, VkCommandBuffer commandBuffer,
@@ -1222,8 +1176,6 @@
                                android::base::BumpPool* pool, VkCommandBuffer commandBuffer,
                                const VkResolveImageInfo2* pResolveImageInfo);
 #endif
-#ifdef VK_KHR_format_feature_flags2
-#endif
 #ifdef VK_KHR_maintenance4
     void vkGetDeviceBufferMemoryRequirementsKHR(const uint8_t* snapshotTraceBegin,
                                                 size_t snapshotTraceBytes,
@@ -1329,16 +1281,6 @@
                                        VkBuffer counterBuffer, VkDeviceSize counterBufferOffset,
                                        uint32_t counterOffset, uint32_t vertexStride);
 #endif
-#ifdef VK_AMD_gpu_shader_half_float
-#endif
-#ifdef VK_EXT_texture_compression_astc_hdr
-#endif
-#ifdef VK_EXT_depth_clip_enable
-#endif
-#ifdef VK_EXT_swapchain_colorspace
-#endif
-#ifdef VK_EXT_queue_family_foreign
-#endif
 #ifdef VK_EXT_debug_utils
     void vkSetDebugUtilsObjectNameEXT(const uint8_t* snapshotTraceBegin, size_t snapshotTraceBytes,
                                       android::base::BumpPool* pool, VkResult input_result,
@@ -1379,26 +1321,6 @@
                                       VkDebugUtilsMessageTypeFlagsEXT messageTypes,
                                       const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData);
 #endif
-#ifdef VK_ANDROID_external_memory_android_hardware_buffer
-#endif
-#ifdef VK_EXT_inline_uniform_block
-#endif
-#ifdef VK_EXT_shader_stencil_export
-#endif
-#ifdef VK_EXT_vertex_attribute_divisor
-#endif
-#ifdef VK_EXT_pipeline_creation_feedback
-#endif
-#ifdef VK_NV_shader_subgroup_partitioned
-#endif
-#ifdef VK_EXT_metal_surface
-#endif
-#ifdef VK_EXT_fragment_density_map
-#endif
-#ifdef VK_EXT_scalar_block_layout
-#endif
-#ifdef VK_EXT_subgroup_size_control
-#endif
 #ifdef VK_EXT_tooling_info
     void vkGetPhysicalDeviceToolPropertiesEXT(const uint8_t* snapshotTraceBegin,
                                               size_t snapshotTraceBytes,
@@ -1406,17 +1328,11 @@
                                               VkPhysicalDevice physicalDevice, uint32_t* pToolCount,
                                               VkPhysicalDeviceToolProperties* pToolProperties);
 #endif
-#ifdef VK_EXT_validation_features
-#endif
-#ifdef VK_EXT_provoking_vertex
-#endif
 #ifdef VK_EXT_line_rasterization
     void vkCmdSetLineStippleEXT(const uint8_t* snapshotTraceBegin, size_t snapshotTraceBytes,
                                 android::base::BumpPool* pool, VkCommandBuffer commandBuffer,
                                 uint32_t lineStippleFactor, uint16_t lineStipplePattern);
 #endif
-#ifdef VK_EXT_index_type_uint8
-#endif
 #ifdef VK_EXT_extended_dynamic_state
     void vkCmdSetCullModeEXT(const uint8_t* snapshotTraceBegin, size_t snapshotTraceBytes,
                              android::base::BumpPool* pool, VkCommandBuffer commandBuffer,
@@ -1488,16 +1404,6 @@
                                      VkDevice device,
                                      const VkReleaseSwapchainImagesInfoEXT* pReleaseInfo);
 #endif
-#ifdef VK_EXT_shader_demote_to_helper_invocation
-#endif
-#ifdef VK_EXT_texel_buffer_alignment
-#endif
-#ifdef VK_EXT_device_memory_report
-#endif
-#ifdef VK_EXT_robustness2
-#endif
-#ifdef VK_EXT_custom_border_color
-#endif
 #ifdef VK_EXT_private_data
     void vkCreatePrivateDataSlotEXT(const uint8_t* snapshotTraceBegin, size_t snapshotTraceBytes,
                                     android::base::BumpPool* pool, VkResult input_result,
@@ -1517,22 +1423,6 @@
                              VkObjectType objectType, uint64_t objectHandle,
                              VkPrivateDataSlot privateDataSlot, uint64_t* pData);
 #endif
-#ifdef VK_EXT_pipeline_creation_cache_control
-#endif
-#ifdef VK_EXT_metal_objects
-#endif
-#ifdef VK_EXT_graphics_pipeline_library
-#endif
-#ifdef VK_EXT_ycbcr_2plane_444_formats
-#endif
-#ifdef VK_EXT_image_robustness
-#endif
-#ifdef VK_EXT_image_compression_control
-#endif
-#ifdef VK_EXT_4444_formats
-#endif
-#ifdef VK_EXT_primitive_topology_list_restart
-#endif
 #ifdef VK_EXT_extended_dynamic_state2
     void vkCmdSetPatchControlPointsEXT(const uint8_t* snapshotTraceBegin, size_t snapshotTraceBytes,
                                        android::base::BumpPool* pool, VkCommandBuffer commandBuffer,
@@ -1671,14 +1561,50 @@
                                    android::base::BumpPool* pool, VkQueue queue,
                                    uint32_t submitCount, const VkSubmitInfo2* pSubmits,
                                    VkFence fence);
+    void vkGetSemaphoreGOOGLE(const uint8_t* snapshotTraceBegin, size_t snapshotTraceBytes,
+                              android::base::BumpPool* pool, VkResult input_result, VkDevice device,
+                              VkSemaphore semaphore, uint64_t syncId);
 #endif
-#ifdef VK_EXT_load_store_op_none
+#ifdef VK_KHR_ray_tracing_pipeline
+    void vkCmdTraceRaysKHR(const uint8_t* snapshotTraceBegin, size_t snapshotTraceBytes,
+                           android::base::BumpPool* pool, VkCommandBuffer commandBuffer,
+                           const VkStridedDeviceAddressRegionKHR* pRaygenShaderBindingTable,
+                           const VkStridedDeviceAddressRegionKHR* pMissShaderBindingTable,
+                           const VkStridedDeviceAddressRegionKHR* pHitShaderBindingTable,
+                           const VkStridedDeviceAddressRegionKHR* pCallableShaderBindingTable,
+                           uint32_t width, uint32_t height, uint32_t depth);
+    void vkCreateRayTracingPipelinesKHR(const uint8_t* snapshotTraceBegin,
+                                        size_t snapshotTraceBytes, android::base::BumpPool* pool,
+                                        VkResult input_result, VkDevice device,
+                                        VkDeferredOperationKHR deferredOperation,
+                                        VkPipelineCache pipelineCache, uint32_t createInfoCount,
+                                        const VkRayTracingPipelineCreateInfoKHR* pCreateInfos,
+                                        const VkAllocationCallbacks* pAllocator,
+                                        VkPipeline* pPipelines);
+    void vkGetRayTracingCaptureReplayShaderGroupHandlesKHR(
+        const uint8_t* snapshotTraceBegin, size_t snapshotTraceBytes, android::base::BumpPool* pool,
+        VkResult input_result, VkDevice device, VkPipeline pipeline, uint32_t firstGroup,
+        uint32_t groupCount, size_t dataSize, void* pData);
+    void vkCmdTraceRaysIndirectKHR(
+        const uint8_t* snapshotTraceBegin, size_t snapshotTraceBytes, android::base::BumpPool* pool,
+        VkCommandBuffer commandBuffer,
+        const VkStridedDeviceAddressRegionKHR* pRaygenShaderBindingTable,
+        const VkStridedDeviceAddressRegionKHR* pMissShaderBindingTable,
+        const VkStridedDeviceAddressRegionKHR* pHitShaderBindingTable,
+        const VkStridedDeviceAddressRegionKHR* pCallableShaderBindingTable,
+        VkDeviceAddress indirectDeviceAddress);
+    void vkGetRayTracingShaderGroupStackSizeKHR(const uint8_t* snapshotTraceBegin,
+                                                size_t snapshotTraceBytes,
+                                                android::base::BumpPool* pool,
+                                                VkDeviceSize input_result, VkDevice device,
+                                                VkPipeline pipeline, uint32_t group,
+                                                VkShaderGroupShaderKHR groupShader);
+    void vkCmdSetRayTracingPipelineStackSizeKHR(const uint8_t* snapshotTraceBegin,
+                                                size_t snapshotTraceBytes,
+                                                android::base::BumpPool* pool,
+                                                VkCommandBuffer commandBuffer,
+                                                uint32_t pipelineStackSize);
 #endif
-#ifdef VK_EXT_image_compression_control_swapchain
-#endif
-#ifdef VK_QNX_external_memory_screen_buffer
-#endif
-
    private:
     class Impl;
     std::unique_ptr<Impl> mImpl;
diff --git a/host/vulkan/VkSubDecoder.cpp b/host/vulkan/VkSubDecoder.cpp
index 0377e1e..233ea7a 100644
--- a/host/vulkan/VkSubDecoder.cpp
+++ b/host/vulkan/VkSubDecoder.cpp
@@ -304,7 +304,8 @@
                         uint64_t tmpval;
                         memcpy(&tmpval, cgen_var_1_ptr + k * 8, sizeof(uint64_t));
                         *(((VkDescriptorSet*)pDescriptorSets) + k) =
-                            (VkDescriptorSet)unbox_VkDescriptorSet((VkDescriptorSet)tmpval);
+                            tmpval ? (VkDescriptorSet)unbox_VkDescriptorSet((VkDescriptorSet)tmpval)
+                                   : VK_NULL_HANDLE;
                     }
                 }
                 memcpy((uint32_t*)&dynamicOffsetCount, *readStreamPtrPtr, sizeof(uint32_t));
@@ -366,7 +367,8 @@
                     for (uint32_t k = 0; k < ((bindingCount)); ++k) {
                         uint64_t tmpval;
                         memcpy(&tmpval, cgen_var_0_ptr + k * 8, sizeof(uint64_t));
-                        *(((VkBuffer*)pBuffers) + k) = (VkBuffer)unbox_VkBuffer((VkBuffer)tmpval);
+                        *(((VkBuffer*)pBuffers) + k) =
+                            tmpval ? (VkBuffer)unbox_VkBuffer((VkBuffer)tmpval) : VK_NULL_HANDLE;
                     }
                 }
                 if (((bindingCount)) <= MAX_STACK_ITEMS) {
@@ -1001,7 +1003,8 @@
                     for (uint32_t k = 0; k < ((eventCount)); ++k) {
                         uint64_t tmpval;
                         memcpy(&tmpval, cgen_var_0_ptr + k * 8, sizeof(uint64_t));
-                        *(((VkEvent*)pEvents) + k) = (VkEvent)unbox_VkEvent((VkEvent)tmpval);
+                        *(((VkEvent*)pEvents) + k) =
+                            tmpval ? (VkEvent)unbox_VkEvent((VkEvent)tmpval) : VK_NULL_HANDLE;
                     }
                 }
                 memcpy((VkPipelineStageFlags*)&srcStageMask, *readStreamPtrPtr,
@@ -1359,7 +1362,8 @@
                         uint64_t tmpval;
                         memcpy(&tmpval, cgen_var_0_ptr + k * 8, sizeof(uint64_t));
                         *(((VkCommandBuffer*)pCommandBuffers) + k) =
-                            (VkCommandBuffer)unbox_VkCommandBuffer((VkCommandBuffer)tmpval);
+                            tmpval ? (VkCommandBuffer)unbox_VkCommandBuffer((VkCommandBuffer)tmpval)
+                                   : VK_NULL_HANDLE;
                     }
                 }
                 this->on_vkCmdExecuteCommands(pool, (VkCommandBuffer)(boxed_dispatchHandle),
@@ -1592,7 +1596,8 @@
                     for (uint32_t k = 0; k < ((eventCount)); ++k) {
                         uint64_t tmpval;
                         memcpy(&tmpval, cgen_var_0_ptr + k * 8, sizeof(uint64_t));
-                        *(((VkEvent*)pEvents) + k) = (VkEvent)unbox_VkEvent((VkEvent)tmpval);
+                        *(((VkEvent*)pEvents) + k) =
+                            tmpval ? (VkEvent)unbox_VkEvent((VkEvent)tmpval) : VK_NULL_HANDLE;
                     }
                 }
                 if (((eventCount)) <= MAX_STACK_ITEMS) {
@@ -1890,7 +1895,8 @@
                             uint64_t tmpval;
                             memcpy(&tmpval, cgen_var_0_0_ptr + k * 8, sizeof(uint64_t));
                             *(((VkBuffer*)pBuffers) + k) =
-                                (VkBuffer)unbox_VkBuffer((VkBuffer)tmpval);
+                                tmpval ? (VkBuffer)unbox_VkBuffer((VkBuffer)tmpval)
+                                       : VK_NULL_HANDLE;
                         }
                     }
                 }
@@ -2037,16 +2043,6 @@
                 break;
             }
 #endif
-#ifdef VK_KHR_surface
-#endif
-#ifdef VK_KHR_swapchain
-#endif
-#ifdef VK_KHR_xcb_surface
-#endif
-#ifdef VK_KHR_android_surface
-#endif
-#ifdef VK_KHR_win32_surface
-#endif
 #ifdef VK_KHR_dynamic_rendering
             case OP_vkCmdBeginRenderingKHR: {
                 android::base::beginTrace("vkCmdBeginRenderingKHR subdecode");
@@ -2071,34 +2067,6 @@
                 break;
             }
 #endif
-#ifdef VK_KHR_get_physical_device_properties2
-#endif
-#ifdef VK_KHR_maintenance1
-#endif
-#ifdef VK_KHR_external_memory_capabilities
-#endif
-#ifdef VK_KHR_external_memory
-#endif
-#ifdef VK_KHR_external_memory_win32
-#endif
-#ifdef VK_KHR_external_memory_fd
-#endif
-#ifdef VK_KHR_external_semaphore_capabilities
-#endif
-#ifdef VK_KHR_external_semaphore
-#endif
-#ifdef VK_KHR_external_semaphore_win32
-#endif
-#ifdef VK_KHR_external_semaphore_fd
-#endif
-#ifdef VK_KHR_shader_float16_int8
-#endif
-#ifdef VK_KHR_incremental_present
-#endif
-#ifdef VK_KHR_descriptor_update_template
-#endif
-#ifdef VK_KHR_imageless_framebuffer
-#endif
 #ifdef VK_KHR_create_renderpass2
             case OP_vkCmdBeginRenderPass2KHR: {
                 android::base::beginTrace("vkCmdBeginRenderPass2KHR subdecode");
@@ -2171,42 +2139,6 @@
                 break;
             }
 #endif
-#ifdef VK_KHR_external_fence_capabilities
-#endif
-#ifdef VK_KHR_external_fence
-#endif
-#ifdef VK_KHR_external_fence_fd
-#endif
-#ifdef VK_KHR_maintenance2
-#endif
-#ifdef VK_KHR_dedicated_allocation
-#endif
-#ifdef VK_KHR_storage_buffer_storage_class
-#endif
-#ifdef VK_KHR_get_memory_requirements2
-#endif
-#ifdef VK_KHR_image_format_list
-#endif
-#ifdef VK_KHR_sampler_ycbcr_conversion
-#endif
-#ifdef VK_KHR_bind_memory2
-#endif
-#ifdef VK_KHR_maintenance3
-#endif
-#ifdef VK_KHR_shader_subgroup_extended_types
-#endif
-#ifdef VK_KHR_vulkan_memory_model
-#endif
-#ifdef VK_KHR_shader_terminate_invocation
-#endif
-#ifdef VK_KHR_buffer_device_address
-#endif
-#ifdef VK_KHR_pipeline_executable_properties
-#endif
-#ifdef VK_KHR_shader_integer_dot_product
-#endif
-#ifdef VK_KHR_shader_non_semantic_info
-#endif
 #ifdef VK_KHR_synchronization2
             case OP_vkCmdSetEvent2KHR: {
                 android::base::beginTrace("vkCmdSetEvent2KHR subdecode");
@@ -2264,7 +2196,8 @@
                     for (uint32_t k = 0; k < ((eventCount)); ++k) {
                         uint64_t tmpval;
                         memcpy(&tmpval, cgen_var_0_ptr + k * 8, sizeof(uint64_t));
-                        *(((VkEvent*)pEvents) + k) = (VkEvent)unbox_VkEvent((VkEvent)tmpval);
+                        *(((VkEvent*)pEvents) + k) =
+                            tmpval ? (VkEvent)unbox_VkEvent((VkEvent)tmpval) : VK_NULL_HANDLE;
                     }
                 }
                 if (((eventCount)) <= MAX_STACK_ITEMS) {
@@ -2348,8 +2281,6 @@
                 break;
             }
 #endif
-#ifdef VK_KHR_zero_initialize_workgroup_memory
-#endif
 #ifdef VK_KHR_copy_commands2
             case OP_vkCmdCopyBuffer2KHR: {
                 android::base::beginTrace("vkCmdCopyBuffer2KHR subdecode");
@@ -2451,10 +2382,6 @@
                 break;
             }
 #endif
-#ifdef VK_KHR_format_feature_flags2
-#endif
-#ifdef VK_KHR_maintenance4
-#endif
 #ifdef VK_KHR_maintenance5
             case OP_vkCmdBindIndexBuffer2KHR: {
                 android::base::beginTrace("vkCmdBindIndexBuffer2KHR subdecode");
@@ -2478,10 +2405,6 @@
                 break;
             }
 #endif
-#ifdef VK_ANDROID_native_buffer
-#endif
-#ifdef VK_EXT_debug_report
-#endif
 #ifdef VK_EXT_transform_feedback
             case OP_vkCmdBindTransformFeedbackBuffersEXT: {
                 android::base::beginTrace("vkCmdBindTransformFeedbackBuffersEXT subdecode");
@@ -2508,7 +2431,8 @@
                     for (uint32_t k = 0; k < ((bindingCount)); ++k) {
                         uint64_t tmpval;
                         memcpy(&tmpval, cgen_var_0_ptr + k * 8, sizeof(uint64_t));
-                        *(((VkBuffer*)pBuffers) + k) = (VkBuffer)unbox_VkBuffer((VkBuffer)tmpval);
+                        *(((VkBuffer*)pBuffers) + k) =
+                            tmpval ? (VkBuffer)unbox_VkBuffer((VkBuffer)tmpval) : VK_NULL_HANDLE;
                     }
                 }
                 if (((bindingCount)) <= MAX_STACK_ITEMS) {
@@ -2571,7 +2495,8 @@
                             uint64_t tmpval;
                             memcpy(&tmpval, cgen_var_0_0_ptr + k * 8, sizeof(uint64_t));
                             *(((VkBuffer*)pCounterBuffers) + k) =
-                                (VkBuffer)unbox_VkBuffer((VkBuffer)tmpval);
+                                tmpval ? (VkBuffer)unbox_VkBuffer((VkBuffer)tmpval)
+                                       : VK_NULL_HANDLE;
                         }
                     }
                 }
@@ -2626,7 +2551,8 @@
                             uint64_t tmpval;
                             memcpy(&tmpval, cgen_var_0_0_ptr + k * 8, sizeof(uint64_t));
                             *(((VkBuffer*)pCounterBuffers) + k) =
-                                (VkBuffer)unbox_VkBuffer((VkBuffer)tmpval);
+                                tmpval ? (VkBuffer)unbox_VkBuffer((VkBuffer)tmpval)
+                                       : VK_NULL_HANDLE;
                         }
                     }
                 }
@@ -2723,16 +2649,6 @@
                 break;
             }
 #endif
-#ifdef VK_AMD_gpu_shader_half_float
-#endif
-#ifdef VK_EXT_texture_compression_astc_hdr
-#endif
-#ifdef VK_EXT_depth_clip_enable
-#endif
-#ifdef VK_EXT_swapchain_colorspace
-#endif
-#ifdef VK_EXT_queue_family_foreign
-#endif
 #ifdef VK_EXT_debug_utils
             case OP_vkCmdBeginDebugUtilsLabelEXT: {
                 android::base::beginTrace("vkCmdBeginDebugUtilsLabelEXT subdecode");
@@ -2773,32 +2689,6 @@
                 break;
             }
 #endif
-#ifdef VK_ANDROID_external_memory_android_hardware_buffer
-#endif
-#ifdef VK_EXT_inline_uniform_block
-#endif
-#ifdef VK_EXT_shader_stencil_export
-#endif
-#ifdef VK_EXT_vertex_attribute_divisor
-#endif
-#ifdef VK_EXT_pipeline_creation_feedback
-#endif
-#ifdef VK_NV_shader_subgroup_partitioned
-#endif
-#ifdef VK_EXT_metal_surface
-#endif
-#ifdef VK_EXT_fragment_density_map
-#endif
-#ifdef VK_EXT_scalar_block_layout
-#endif
-#ifdef VK_EXT_subgroup_size_control
-#endif
-#ifdef VK_EXT_tooling_info
-#endif
-#ifdef VK_EXT_validation_features
-#endif
-#ifdef VK_EXT_provoking_vertex
-#endif
 #ifdef VK_EXT_line_rasterization
             case OP_vkCmdSetLineStippleEXT: {
                 android::base::beginTrace("vkCmdSetLineStippleEXT subdecode");
@@ -2814,8 +2704,6 @@
                 break;
             }
 #endif
-#ifdef VK_EXT_index_type_uint8
-#endif
 #ifdef VK_EXT_extended_dynamic_state
             case OP_vkCmdSetCullModeEXT: {
                 android::base::beginTrace("vkCmdSetCullModeEXT subdecode");
@@ -2934,7 +2822,8 @@
                             uint64_t tmpval;
                             memcpy(&tmpval, cgen_var_0_0_ptr + k * 8, sizeof(uint64_t));
                             *(((VkBuffer*)pBuffers) + k) =
-                                (VkBuffer)unbox_VkBuffer((VkBuffer)tmpval);
+                                tmpval ? (VkBuffer)unbox_VkBuffer((VkBuffer)tmpval)
+                                       : VK_NULL_HANDLE;
                         }
                     }
                 }
@@ -3053,38 +2942,6 @@
                 break;
             }
 #endif
-#ifdef VK_EXT_host_image_copy
-#endif
-#ifdef VK_EXT_swapchain_maintenance1
-#endif
-#ifdef VK_EXT_shader_demote_to_helper_invocation
-#endif
-#ifdef VK_EXT_texel_buffer_alignment
-#endif
-#ifdef VK_EXT_device_memory_report
-#endif
-#ifdef VK_EXT_robustness2
-#endif
-#ifdef VK_EXT_custom_border_color
-#endif
-#ifdef VK_EXT_private_data
-#endif
-#ifdef VK_EXT_pipeline_creation_cache_control
-#endif
-#ifdef VK_EXT_metal_objects
-#endif
-#ifdef VK_EXT_graphics_pipeline_library
-#endif
-#ifdef VK_EXT_ycbcr_2plane_444_formats
-#endif
-#ifdef VK_EXT_image_robustness
-#endif
-#ifdef VK_EXT_image_compression_control
-#endif
-#ifdef VK_EXT_4444_formats
-#endif
-#ifdef VK_EXT_primitive_topology_list_restart
-#endif
 #ifdef VK_EXT_extended_dynamic_state2
             case OP_vkCmdSetPatchControlPointsEXT: {
                 android::base::beginTrace("vkCmdSetPatchControlPointsEXT subdecode");
@@ -3208,11 +3065,141 @@
                 break;
             }
 #endif
-#ifdef VK_EXT_load_store_op_none
-#endif
-#ifdef VK_EXT_image_compression_control_swapchain
-#endif
-#ifdef VK_QNX_external_memory_screen_buffer
+#ifdef VK_KHR_ray_tracing_pipeline
+            case OP_vkCmdTraceRaysKHR: {
+                android::base::beginTrace("vkCmdTraceRaysKHR subdecode");
+                const VkStridedDeviceAddressRegionKHR* pRaygenShaderBindingTable;
+                VkStridedDeviceAddressRegionKHR stack_pRaygenShaderBindingTable[1];
+                const VkStridedDeviceAddressRegionKHR* pMissShaderBindingTable;
+                VkStridedDeviceAddressRegionKHR stack_pMissShaderBindingTable[1];
+                const VkStridedDeviceAddressRegionKHR* pHitShaderBindingTable;
+                VkStridedDeviceAddressRegionKHR stack_pHitShaderBindingTable[1];
+                const VkStridedDeviceAddressRegionKHR* pCallableShaderBindingTable;
+                VkStridedDeviceAddressRegionKHR stack_pCallableShaderBindingTable[1];
+                uint32_t width;
+                uint32_t height;
+                uint32_t depth;
+                pRaygenShaderBindingTable =
+                    (VkStridedDeviceAddressRegionKHR*)stack_pRaygenShaderBindingTable;
+                reservedunmarshal_VkStridedDeviceAddressRegionKHR(
+                    readStream, VK_STRUCTURE_TYPE_MAX_ENUM,
+                    (VkStridedDeviceAddressRegionKHR*)(pRaygenShaderBindingTable),
+                    readStreamPtrPtr);
+                pMissShaderBindingTable =
+                    (VkStridedDeviceAddressRegionKHR*)stack_pMissShaderBindingTable;
+                reservedunmarshal_VkStridedDeviceAddressRegionKHR(
+                    readStream, VK_STRUCTURE_TYPE_MAX_ENUM,
+                    (VkStridedDeviceAddressRegionKHR*)(pMissShaderBindingTable), readStreamPtrPtr);
+                pHitShaderBindingTable =
+                    (VkStridedDeviceAddressRegionKHR*)stack_pHitShaderBindingTable;
+                reservedunmarshal_VkStridedDeviceAddressRegionKHR(
+                    readStream, VK_STRUCTURE_TYPE_MAX_ENUM,
+                    (VkStridedDeviceAddressRegionKHR*)(pHitShaderBindingTable), readStreamPtrPtr);
+                pCallableShaderBindingTable =
+                    (VkStridedDeviceAddressRegionKHR*)stack_pCallableShaderBindingTable;
+                reservedunmarshal_VkStridedDeviceAddressRegionKHR(
+                    readStream, VK_STRUCTURE_TYPE_MAX_ENUM,
+                    (VkStridedDeviceAddressRegionKHR*)(pCallableShaderBindingTable),
+                    readStreamPtrPtr);
+                memcpy((uint32_t*)&width, *readStreamPtrPtr, sizeof(uint32_t));
+                *readStreamPtrPtr += sizeof(uint32_t);
+                memcpy((uint32_t*)&height, *readStreamPtrPtr, sizeof(uint32_t));
+                *readStreamPtrPtr += sizeof(uint32_t);
+                memcpy((uint32_t*)&depth, *readStreamPtrPtr, sizeof(uint32_t));
+                *readStreamPtrPtr += sizeof(uint32_t);
+                if (pRaygenShaderBindingTable) {
+                    transform_tohost_VkStridedDeviceAddressRegionKHR(
+                        globalstate, (VkStridedDeviceAddressRegionKHR*)(pRaygenShaderBindingTable));
+                }
+                if (pMissShaderBindingTable) {
+                    transform_tohost_VkStridedDeviceAddressRegionKHR(
+                        globalstate, (VkStridedDeviceAddressRegionKHR*)(pMissShaderBindingTable));
+                }
+                if (pHitShaderBindingTable) {
+                    transform_tohost_VkStridedDeviceAddressRegionKHR(
+                        globalstate, (VkStridedDeviceAddressRegionKHR*)(pHitShaderBindingTable));
+                }
+                if (pCallableShaderBindingTable) {
+                    transform_tohost_VkStridedDeviceAddressRegionKHR(
+                        globalstate,
+                        (VkStridedDeviceAddressRegionKHR*)(pCallableShaderBindingTable));
+                }
+                vk->vkCmdTraceRaysKHR((VkCommandBuffer)dispatchHandle, pRaygenShaderBindingTable,
+                                      pMissShaderBindingTable, pHitShaderBindingTable,
+                                      pCallableShaderBindingTable, width, height, depth);
+                android::base::endTrace();
+                break;
+            }
+            case OP_vkCmdTraceRaysIndirectKHR: {
+                android::base::beginTrace("vkCmdTraceRaysIndirectKHR subdecode");
+                const VkStridedDeviceAddressRegionKHR* pRaygenShaderBindingTable;
+                VkStridedDeviceAddressRegionKHR stack_pRaygenShaderBindingTable[1];
+                const VkStridedDeviceAddressRegionKHR* pMissShaderBindingTable;
+                VkStridedDeviceAddressRegionKHR stack_pMissShaderBindingTable[1];
+                const VkStridedDeviceAddressRegionKHR* pHitShaderBindingTable;
+                VkStridedDeviceAddressRegionKHR stack_pHitShaderBindingTable[1];
+                const VkStridedDeviceAddressRegionKHR* pCallableShaderBindingTable;
+                VkStridedDeviceAddressRegionKHR stack_pCallableShaderBindingTable[1];
+                VkDeviceAddress indirectDeviceAddress;
+                pRaygenShaderBindingTable =
+                    (VkStridedDeviceAddressRegionKHR*)stack_pRaygenShaderBindingTable;
+                reservedunmarshal_VkStridedDeviceAddressRegionKHR(
+                    readStream, VK_STRUCTURE_TYPE_MAX_ENUM,
+                    (VkStridedDeviceAddressRegionKHR*)(pRaygenShaderBindingTable),
+                    readStreamPtrPtr);
+                pMissShaderBindingTable =
+                    (VkStridedDeviceAddressRegionKHR*)stack_pMissShaderBindingTable;
+                reservedunmarshal_VkStridedDeviceAddressRegionKHR(
+                    readStream, VK_STRUCTURE_TYPE_MAX_ENUM,
+                    (VkStridedDeviceAddressRegionKHR*)(pMissShaderBindingTable), readStreamPtrPtr);
+                pHitShaderBindingTable =
+                    (VkStridedDeviceAddressRegionKHR*)stack_pHitShaderBindingTable;
+                reservedunmarshal_VkStridedDeviceAddressRegionKHR(
+                    readStream, VK_STRUCTURE_TYPE_MAX_ENUM,
+                    (VkStridedDeviceAddressRegionKHR*)(pHitShaderBindingTable), readStreamPtrPtr);
+                pCallableShaderBindingTable =
+                    (VkStridedDeviceAddressRegionKHR*)stack_pCallableShaderBindingTable;
+                reservedunmarshal_VkStridedDeviceAddressRegionKHR(
+                    readStream, VK_STRUCTURE_TYPE_MAX_ENUM,
+                    (VkStridedDeviceAddressRegionKHR*)(pCallableShaderBindingTable),
+                    readStreamPtrPtr);
+                memcpy((VkDeviceAddress*)&indirectDeviceAddress, *readStreamPtrPtr,
+                       sizeof(VkDeviceAddress));
+                *readStreamPtrPtr += sizeof(VkDeviceAddress);
+                if (pRaygenShaderBindingTable) {
+                    transform_tohost_VkStridedDeviceAddressRegionKHR(
+                        globalstate, (VkStridedDeviceAddressRegionKHR*)(pRaygenShaderBindingTable));
+                }
+                if (pMissShaderBindingTable) {
+                    transform_tohost_VkStridedDeviceAddressRegionKHR(
+                        globalstate, (VkStridedDeviceAddressRegionKHR*)(pMissShaderBindingTable));
+                }
+                if (pHitShaderBindingTable) {
+                    transform_tohost_VkStridedDeviceAddressRegionKHR(
+                        globalstate, (VkStridedDeviceAddressRegionKHR*)(pHitShaderBindingTable));
+                }
+                if (pCallableShaderBindingTable) {
+                    transform_tohost_VkStridedDeviceAddressRegionKHR(
+                        globalstate,
+                        (VkStridedDeviceAddressRegionKHR*)(pCallableShaderBindingTable));
+                }
+                vk->vkCmdTraceRaysIndirectKHR((VkCommandBuffer)dispatchHandle,
+                                              pRaygenShaderBindingTable, pMissShaderBindingTable,
+                                              pHitShaderBindingTable, pCallableShaderBindingTable,
+                                              indirectDeviceAddress);
+                android::base::endTrace();
+                break;
+            }
+            case OP_vkCmdSetRayTracingPipelineStackSizeKHR: {
+                android::base::beginTrace("vkCmdSetRayTracingPipelineStackSizeKHR subdecode");
+                uint32_t pipelineStackSize;
+                memcpy((uint32_t*)&pipelineStackSize, *readStreamPtrPtr, sizeof(uint32_t));
+                *readStreamPtrPtr += sizeof(uint32_t);
+                vk->vkCmdSetRayTracingPipelineStackSizeKHR((VkCommandBuffer)dispatchHandle,
+                                                           pipelineStackSize);
+                android::base::endTrace();
+                break;
+            }
 #endif
             default: {
                 GFXSTREAM_ABORT(::emugl::FatalError(::emugl::ABORT_REASON_OTHER))
diff --git a/host/vulkan/VulkanDispatch.cpp b/host/vulkan/VulkanDispatch.cpp
index 8494528..ea51459 100644
--- a/host/vulkan/VulkanDispatch.cpp
+++ b/host/vulkan/VulkanDispatch.cpp
@@ -24,6 +24,10 @@
 using android::base::Lock;
 using android::base::pj;
 
+#ifndef VERBOSE
+#define VERBOSE INFO
+#endif
+
 namespace gfxstream {
 namespace vk {
 
@@ -100,6 +104,14 @@
         //  submitted to a queue will give the same result as if they had been run in
         //  submission order.
         android::base::setEnvironmentVariable("MVK_CONFIG_VK_SEMAPHORE_SUPPORT_STYLE", "0");
+
+        // TODO(b/351765838): VVL won't work with MoltenVK due to the current
+        //  way of external memory handling, add it into disable list to
+        //  avoid users enabling it implicitly (i.e. via vkconfig).
+        //  It can be enabled with VK_LOADER_LAYERS_ALLOW=VK_LAYER_KHRONOS_validation
+        INFO("Vulkan Validation Layers won't be enabled with MoltenVK");
+        android::base::setEnvironmentVariable("VK_LOADER_LAYERS_DISABLE",
+                                              "VK_LAYER_KHRONOS_validation");
 #else
         // By default, on other platforms, just use whatever the system
         // is packing.
@@ -115,17 +127,18 @@
 
     bool addLibrary(const std::string& path) {
         if (size() >= mSizeLimit) {
-            fprintf(stderr, "cannot add library %s: full\n", path.c_str());
+            WARN("Cannot add library %s due to size limit(%d)", path.c_str(), mSizeLimit);
             return false;
         }
 
         auto library = android::base::SharedLibrary::open(path.c_str());
         if (library) {
             mLibs.push_back(library);
-            fprintf(stderr, "added library %s\n", path.c_str());
+            INFO("Added library: %s", path.c_str());
             return true;
         } else {
-            fprintf(stderr, "cannot add library %s: failed\n", path.c_str());
+            // This is expected when searching for a valid library path
+            VERBOSE("Library cannot be added: %s", path.c_str());
             return false;
         }
     }
@@ -271,7 +284,11 @@
 
     void* dlopen() {
         if (mVulkanLibs.size() == 0) {
-            mVulkanLibs.addFirstAvailableLibrary(getPossibleLoaderPaths());
+            const std::vector<std::string> possiblePaths = getPossibleLoaderPaths();
+            if (!mVulkanLibs.addFirstAvailableLibrary(possiblePaths)) {
+                ERR("Cannot add any library for Vulkan loader from the list of %d items",
+                    possiblePaths.size());
+            }
         }
         return static_cast<void*>(&mVulkanLibs);
     }
diff --git a/host/vulkan/cereal/common/goldfish_vk_deepcopy.cpp b/host/vulkan/cereal/common/goldfish_vk_deepcopy.cpp
index a2db21d..6cf3ab5 100644
--- a/host/vulkan/cereal/common/goldfish_vk_deepcopy.cpp
+++ b/host/vulkan/cereal/common/goldfish_vk_deepcopy.cpp
@@ -6503,8 +6503,6 @@
 }
 
 #endif
-#ifdef VK_KHR_surface
-#endif
 #ifdef VK_KHR_swapchain
 void deepcopy_VkSwapchainCreateInfoKHR(Allocator* alloc, VkStructureType rootType,
                                        const VkSwapchainCreateInfoKHR* from,
@@ -6714,12 +6712,6 @@
 }
 
 #endif
-#ifdef VK_KHR_xcb_surface
-#endif
-#ifdef VK_KHR_android_surface
-#endif
-#ifdef VK_KHR_win32_surface
-#endif
 #ifdef VK_KHR_dynamic_rendering
 void deepcopy_VkRenderingFragmentShadingRateAttachmentInfoKHR(
     Allocator* alloc, VkStructureType rootType,
@@ -6820,24 +6812,6 @@
 }
 
 #endif
-#ifdef VK_KHR_get_physical_device_properties2
-#endif
-#ifdef VK_KHR_maintenance1
-#endif
-#ifdef VK_KHR_external_memory_capabilities
-#endif
-#ifdef VK_KHR_external_memory
-#endif
-#ifdef VK_KHR_external_memory_win32
-#endif
-#ifdef VK_KHR_external_memory_fd
-#endif
-#ifdef VK_KHR_external_semaphore_capabilities
-#endif
-#ifdef VK_KHR_external_semaphore
-#endif
-#ifdef VK_KHR_external_semaphore_win32
-#endif
 #ifdef VK_KHR_external_semaphore_fd
 void deepcopy_VkImportSemaphoreFdInfoKHR(Allocator* alloc, VkStructureType rootType,
                                          const VkImportSemaphoreFdInfoKHR* from,
@@ -6884,8 +6858,6 @@
 }
 
 #endif
-#ifdef VK_KHR_shader_float16_int8
-#endif
 #ifdef VK_KHR_incremental_present
 void deepcopy_VkRectLayerKHR(Allocator* alloc, VkStructureType rootType, const VkRectLayerKHR* from,
                              VkRectLayerKHR* to) {
@@ -6949,16 +6921,6 @@
 }
 
 #endif
-#ifdef VK_KHR_descriptor_update_template
-#endif
-#ifdef VK_KHR_imageless_framebuffer
-#endif
-#ifdef VK_KHR_create_renderpass2
-#endif
-#ifdef VK_KHR_external_fence_capabilities
-#endif
-#ifdef VK_KHR_external_fence
-#endif
 #ifdef VK_KHR_external_fence_fd
 void deepcopy_VkImportFenceFdInfoKHR(Allocator* alloc, VkStructureType rootType,
                                      const VkImportFenceFdInfoKHR* from,
@@ -7004,30 +6966,6 @@
 }
 
 #endif
-#ifdef VK_KHR_maintenance2
-#endif
-#ifdef VK_KHR_dedicated_allocation
-#endif
-#ifdef VK_KHR_storage_buffer_storage_class
-#endif
-#ifdef VK_KHR_get_memory_requirements2
-#endif
-#ifdef VK_KHR_image_format_list
-#endif
-#ifdef VK_KHR_sampler_ycbcr_conversion
-#endif
-#ifdef VK_KHR_bind_memory2
-#endif
-#ifdef VK_KHR_maintenance3
-#endif
-#ifdef VK_KHR_shader_subgroup_extended_types
-#endif
-#ifdef VK_KHR_vulkan_memory_model
-#endif
-#ifdef VK_KHR_shader_terminate_invocation
-#endif
-#ifdef VK_KHR_buffer_device_address
-#endif
 #ifdef VK_KHR_pipeline_executable_properties
 void deepcopy_VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR(
     Allocator* alloc, VkStructureType rootType,
@@ -7183,9 +7121,34 @@
 }
 
 #endif
-#ifdef VK_KHR_shader_integer_dot_product
-#endif
-#ifdef VK_KHR_shader_non_semantic_info
+#ifdef VK_KHR_pipeline_library
+void deepcopy_VkPipelineLibraryCreateInfoKHR(Allocator* alloc, VkStructureType rootType,
+                                             const VkPipelineLibraryCreateInfoKHR* from,
+                                             VkPipelineLibraryCreateInfoKHR* to) {
+    (void)alloc;
+    (void)rootType;
+    *to = *from;
+    if (rootType == VK_STRUCTURE_TYPE_MAX_ENUM) {
+        rootType = from->sType;
+    }
+    const void* from_pNext = from;
+    size_t pNext_size = 0u;
+    while (!pNext_size && from_pNext) {
+        from_pNext = static_cast<const vk_struct_common*>(from_pNext)->pNext;
+        pNext_size = goldfish_vk_extension_struct_size(rootType, from_pNext);
+    }
+    to->pNext = nullptr;
+    if (pNext_size) {
+        to->pNext = (void*)alloc->alloc(pNext_size);
+        deepcopy_extension_struct(alloc, rootType, from_pNext, (void*)(to->pNext));
+    }
+    to->pLibraries = nullptr;
+    if (from->pLibraries) {
+        to->pLibraries = (VkPipeline*)alloc->dupArray(
+            from->pLibraries, from->libraryCount * sizeof(const VkPipeline));
+    }
+}
+
 #endif
 #ifdef VK_KHR_synchronization2
 void deepcopy_VkQueueFamilyCheckpointProperties2NV(Allocator* alloc, VkStructureType rootType,
@@ -7236,14 +7199,6 @@
 }
 
 #endif
-#ifdef VK_KHR_zero_initialize_workgroup_memory
-#endif
-#ifdef VK_KHR_copy_commands2
-#endif
-#ifdef VK_KHR_format_feature_flags2
-#endif
-#ifdef VK_KHR_maintenance4
-#endif
 #ifdef VK_KHR_maintenance5
 void deepcopy_VkPhysicalDeviceMaintenance5FeaturesKHR(
     Allocator* alloc, VkStructureType rootType, const VkPhysicalDeviceMaintenance5FeaturesKHR* from,
@@ -7626,10 +7581,6 @@
 }
 
 #endif
-#ifdef VK_AMD_gpu_shader_half_float
-#endif
-#ifdef VK_EXT_texture_compression_astc_hdr
-#endif
 #ifdef VK_EXT_depth_clip_enable
 void deepcopy_VkPhysicalDeviceDepthClipEnableFeaturesEXT(
     Allocator* alloc, VkStructureType rootType,
@@ -7678,10 +7629,6 @@
 }
 
 #endif
-#ifdef VK_EXT_swapchain_colorspace
-#endif
-#ifdef VK_EXT_queue_family_foreign
-#endif
 #ifdef VK_EXT_debug_utils
 void deepcopy_VkDebugUtilsLabelEXT(Allocator* alloc, VkStructureType rootType,
                                    const VkDebugUtilsLabelEXT* from, VkDebugUtilsLabelEXT* to) {
@@ -7855,12 +7802,6 @@
 }
 
 #endif
-#ifdef VK_ANDROID_external_memory_android_hardware_buffer
-#endif
-#ifdef VK_EXT_inline_uniform_block
-#endif
-#ifdef VK_EXT_shader_stencil_export
-#endif
 #ifdef VK_EXT_vertex_attribute_divisor
 void deepcopy_VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT(
     Allocator* alloc, VkStructureType rootType,
@@ -7955,12 +7896,6 @@
 }
 
 #endif
-#ifdef VK_EXT_pipeline_creation_feedback
-#endif
-#ifdef VK_NV_shader_subgroup_partitioned
-#endif
-#ifdef VK_EXT_metal_surface
-#endif
 #ifdef VK_EXT_fragment_density_map
 void deepcopy_VkPhysicalDeviceFragmentDensityMapFeaturesEXT(
     Allocator* alloc, VkStructureType rootType,
@@ -8038,12 +7973,6 @@
 }
 
 #endif
-#ifdef VK_EXT_scalar_block_layout
-#endif
-#ifdef VK_EXT_subgroup_size_control
-#endif
-#ifdef VK_EXT_tooling_info
-#endif
 #ifdef VK_EXT_validation_features
 void deepcopy_VkValidationFeaturesEXT(Allocator* alloc, VkStructureType rootType,
                                       const VkValidationFeaturesEXT* from,
@@ -8718,8 +8647,6 @@
 }
 
 #endif
-#ifdef VK_EXT_shader_demote_to_helper_invocation
-#endif
 #ifdef VK_EXT_texel_buffer_alignment
 void deepcopy_VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT(
     Allocator* alloc, VkStructureType rootType,
@@ -8937,12 +8864,6 @@
 }
 
 #endif
-#ifdef VK_EXT_private_data
-#endif
-#ifdef VK_EXT_pipeline_creation_cache_control
-#endif
-#ifdef VK_EXT_metal_objects
-#endif
 #ifdef VK_EXT_graphics_pipeline_library
 void deepcopy_VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT(
     Allocator* alloc, VkStructureType rootType,
@@ -9038,8 +8959,6 @@
 }
 
 #endif
-#ifdef VK_EXT_image_robustness
-#endif
 #ifdef VK_EXT_image_compression_control
 void deepcopy_VkPhysicalDeviceImageCompressionControlFeaturesEXT(
     Allocator* alloc, VkStructureType rootType,
@@ -9307,8 +9226,6 @@
 }
 
 #endif
-#ifdef VK_EXT_load_store_op_none
-#endif
 #ifdef VK_EXT_image_compression_control_swapchain
 void deepcopy_VkPhysicalDeviceImageCompressionControlSwapchainFeaturesEXT(
     Allocator* alloc, VkStructureType rootType,
@@ -9334,7 +9251,191 @@
 }
 
 #endif
-#ifdef VK_QNX_external_memory_screen_buffer
+#ifdef VK_KHR_ray_tracing_pipeline
+void deepcopy_VkRayTracingShaderGroupCreateInfoKHR(Allocator* alloc, VkStructureType rootType,
+                                                   const VkRayTracingShaderGroupCreateInfoKHR* from,
+                                                   VkRayTracingShaderGroupCreateInfoKHR* to) {
+    (void)alloc;
+    (void)rootType;
+    *to = *from;
+    if (rootType == VK_STRUCTURE_TYPE_MAX_ENUM) {
+        rootType = from->sType;
+    }
+    const void* from_pNext = from;
+    size_t pNext_size = 0u;
+    while (!pNext_size && from_pNext) {
+        from_pNext = static_cast<const vk_struct_common*>(from_pNext)->pNext;
+        pNext_size = goldfish_vk_extension_struct_size(rootType, from_pNext);
+    }
+    to->pNext = nullptr;
+    if (pNext_size) {
+        to->pNext = (void*)alloc->alloc(pNext_size);
+        deepcopy_extension_struct(alloc, rootType, from_pNext, (void*)(to->pNext));
+    }
+    to->pShaderGroupCaptureReplayHandle = nullptr;
+    if (from->pShaderGroupCaptureReplayHandle) {
+        to->pShaderGroupCaptureReplayHandle =
+            (void*)alloc->dupArray(from->pShaderGroupCaptureReplayHandle, sizeof(const uint8_t));
+    }
+}
+
+void deepcopy_VkRayTracingPipelineInterfaceCreateInfoKHR(
+    Allocator* alloc, VkStructureType rootType,
+    const VkRayTracingPipelineInterfaceCreateInfoKHR* from,
+    VkRayTracingPipelineInterfaceCreateInfoKHR* to) {
+    (void)alloc;
+    (void)rootType;
+    *to = *from;
+    if (rootType == VK_STRUCTURE_TYPE_MAX_ENUM) {
+        rootType = from->sType;
+    }
+    const void* from_pNext = from;
+    size_t pNext_size = 0u;
+    while (!pNext_size && from_pNext) {
+        from_pNext = static_cast<const vk_struct_common*>(from_pNext)->pNext;
+        pNext_size = goldfish_vk_extension_struct_size(rootType, from_pNext);
+    }
+    to->pNext = nullptr;
+    if (pNext_size) {
+        to->pNext = (void*)alloc->alloc(pNext_size);
+        deepcopy_extension_struct(alloc, rootType, from_pNext, (void*)(to->pNext));
+    }
+}
+
+void deepcopy_VkRayTracingPipelineCreateInfoKHR(Allocator* alloc, VkStructureType rootType,
+                                                const VkRayTracingPipelineCreateInfoKHR* from,
+                                                VkRayTracingPipelineCreateInfoKHR* to) {
+    (void)alloc;
+    (void)rootType;
+    *to = *from;
+    if (rootType == VK_STRUCTURE_TYPE_MAX_ENUM) {
+        rootType = from->sType;
+    }
+    const void* from_pNext = from;
+    size_t pNext_size = 0u;
+    while (!pNext_size && from_pNext) {
+        from_pNext = static_cast<const vk_struct_common*>(from_pNext)->pNext;
+        pNext_size = goldfish_vk_extension_struct_size(rootType, from_pNext);
+    }
+    to->pNext = nullptr;
+    if (pNext_size) {
+        to->pNext = (void*)alloc->alloc(pNext_size);
+        deepcopy_extension_struct(alloc, rootType, from_pNext, (void*)(to->pNext));
+    }
+    if (from) {
+        to->pStages = nullptr;
+        if (from->pStages) {
+            to->pStages = (VkPipelineShaderStageCreateInfo*)alloc->alloc(
+                from->stageCount * sizeof(const VkPipelineShaderStageCreateInfo));
+            to->stageCount = from->stageCount;
+            for (uint32_t i = 0; i < (uint32_t)from->stageCount; ++i) {
+                deepcopy_VkPipelineShaderStageCreateInfo(
+                    alloc, rootType, from->pStages + i,
+                    (VkPipelineShaderStageCreateInfo*)(to->pStages + i));
+            }
+        }
+    }
+    if (from) {
+        to->pGroups = nullptr;
+        if (from->pGroups) {
+            to->pGroups = (VkRayTracingShaderGroupCreateInfoKHR*)alloc->alloc(
+                from->groupCount * sizeof(const VkRayTracingShaderGroupCreateInfoKHR));
+            to->groupCount = from->groupCount;
+            for (uint32_t i = 0; i < (uint32_t)from->groupCount; ++i) {
+                deepcopy_VkRayTracingShaderGroupCreateInfoKHR(
+                    alloc, rootType, from->pGroups + i,
+                    (VkRayTracingShaderGroupCreateInfoKHR*)(to->pGroups + i));
+            }
+        }
+    }
+    to->pLibraryInfo = nullptr;
+    if (from->pLibraryInfo) {
+        to->pLibraryInfo = (VkPipelineLibraryCreateInfoKHR*)alloc->alloc(
+            sizeof(const VkPipelineLibraryCreateInfoKHR));
+        deepcopy_VkPipelineLibraryCreateInfoKHR(
+            alloc, rootType, from->pLibraryInfo,
+            (VkPipelineLibraryCreateInfoKHR*)(to->pLibraryInfo));
+    }
+    to->pLibraryInterface = nullptr;
+    if (from->pLibraryInterface) {
+        to->pLibraryInterface = (VkRayTracingPipelineInterfaceCreateInfoKHR*)alloc->alloc(
+            sizeof(const VkRayTracingPipelineInterfaceCreateInfoKHR));
+        deepcopy_VkRayTracingPipelineInterfaceCreateInfoKHR(
+            alloc, rootType, from->pLibraryInterface,
+            (VkRayTracingPipelineInterfaceCreateInfoKHR*)(to->pLibraryInterface));
+    }
+    to->pDynamicState = nullptr;
+    if (from->pDynamicState) {
+        to->pDynamicState = (VkPipelineDynamicStateCreateInfo*)alloc->alloc(
+            sizeof(const VkPipelineDynamicStateCreateInfo));
+        deepcopy_VkPipelineDynamicStateCreateInfo(
+            alloc, rootType, from->pDynamicState,
+            (VkPipelineDynamicStateCreateInfo*)(to->pDynamicState));
+    }
+}
+
+void deepcopy_VkPhysicalDeviceRayTracingPipelineFeaturesKHR(
+    Allocator* alloc, VkStructureType rootType,
+    const VkPhysicalDeviceRayTracingPipelineFeaturesKHR* from,
+    VkPhysicalDeviceRayTracingPipelineFeaturesKHR* to) {
+    (void)alloc;
+    (void)rootType;
+    *to = *from;
+    if (rootType == VK_STRUCTURE_TYPE_MAX_ENUM) {
+        rootType = from->sType;
+    }
+    const void* from_pNext = from;
+    size_t pNext_size = 0u;
+    while (!pNext_size && from_pNext) {
+        from_pNext = static_cast<const vk_struct_common*>(from_pNext)->pNext;
+        pNext_size = goldfish_vk_extension_struct_size(rootType, from_pNext);
+    }
+    to->pNext = nullptr;
+    if (pNext_size) {
+        to->pNext = (void*)alloc->alloc(pNext_size);
+        deepcopy_extension_struct(alloc, rootType, from_pNext, (void*)(to->pNext));
+    }
+}
+
+void deepcopy_VkPhysicalDeviceRayTracingPipelinePropertiesKHR(
+    Allocator* alloc, VkStructureType rootType,
+    const VkPhysicalDeviceRayTracingPipelinePropertiesKHR* from,
+    VkPhysicalDeviceRayTracingPipelinePropertiesKHR* to) {
+    (void)alloc;
+    (void)rootType;
+    *to = *from;
+    if (rootType == VK_STRUCTURE_TYPE_MAX_ENUM) {
+        rootType = from->sType;
+    }
+    const void* from_pNext = from;
+    size_t pNext_size = 0u;
+    while (!pNext_size && from_pNext) {
+        from_pNext = static_cast<const vk_struct_common*>(from_pNext)->pNext;
+        pNext_size = goldfish_vk_extension_struct_size(rootType, from_pNext);
+    }
+    to->pNext = nullptr;
+    if (pNext_size) {
+        to->pNext = (void*)alloc->alloc(pNext_size);
+        deepcopy_extension_struct(alloc, rootType, from_pNext, (void*)(to->pNext));
+    }
+}
+
+void deepcopy_VkStridedDeviceAddressRegionKHR(Allocator* alloc, VkStructureType rootType,
+                                              const VkStridedDeviceAddressRegionKHR* from,
+                                              VkStridedDeviceAddressRegionKHR* to) {
+    (void)alloc;
+    (void)rootType;
+    *to = *from;
+}
+
+void deepcopy_VkTraceRaysIndirectCommandKHR(Allocator* alloc, VkStructureType rootType,
+                                            const VkTraceRaysIndirectCommandKHR* from,
+                                            VkTraceRaysIndirectCommandKHR* to) {
+    (void)alloc;
+    (void)rootType;
+    *to = *from;
+}
+
 #endif
 void deepcopy_extension_struct(Allocator* alloc, VkStructureType rootType,
                                const void* structExtension, void* structExtension_out) {
@@ -10239,6 +10340,15 @@
             break;
         }
 #endif
+#ifdef VK_KHR_pipeline_library
+        case VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR: {
+            deepcopy_VkPipelineLibraryCreateInfoKHR(
+                alloc, rootType,
+                reinterpret_cast<const VkPipelineLibraryCreateInfoKHR*>(structExtension),
+                reinterpret_cast<VkPipelineLibraryCreateInfoKHR*>(structExtension_out));
+            break;
+        }
+#endif
 #ifdef VK_KHR_synchronization2
         case VK_STRUCTURE_TYPE_QUEUE_FAMILY_CHECKPOINT_PROPERTIES_2_NV: {
             deepcopy_VkQueueFamilyCheckpointProperties2NV(
@@ -10870,6 +10980,26 @@
             break;
         }
 #endif
+#ifdef VK_KHR_ray_tracing_pipeline
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR: {
+            deepcopy_VkPhysicalDeviceRayTracingPipelineFeaturesKHR(
+                alloc, rootType,
+                reinterpret_cast<const VkPhysicalDeviceRayTracingPipelineFeaturesKHR*>(
+                    structExtension),
+                reinterpret_cast<VkPhysicalDeviceRayTracingPipelineFeaturesKHR*>(
+                    structExtension_out));
+            break;
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR: {
+            deepcopy_VkPhysicalDeviceRayTracingPipelinePropertiesKHR(
+                alloc, rootType,
+                reinterpret_cast<const VkPhysicalDeviceRayTracingPipelinePropertiesKHR*>(
+                    structExtension),
+                reinterpret_cast<VkPhysicalDeviceRayTracingPipelinePropertiesKHR*>(
+                    structExtension_out));
+            break;
+        }
+#endif
         default: {
             return;
         }
diff --git a/host/vulkan/cereal/common/goldfish_vk_deepcopy.h b/host/vulkan/cereal/common/goldfish_vk_deepcopy.h
index 240822f..2312fec 100644
--- a/host/vulkan/cereal/common/goldfish_vk_deepcopy.h
+++ b/host/vulkan/cereal/common/goldfish_vk_deepcopy.h
@@ -1140,8 +1140,6 @@
                                               VkDeviceImageMemoryRequirements* to);
 
 #endif
-#ifdef VK_KHR_surface
-#endif
 #ifdef VK_KHR_swapchain
 void deepcopy_VkSwapchainCreateInfoKHR(Allocator* alloc, VkStructureType rootType,
                                        const VkSwapchainCreateInfoKHR* from,
@@ -1175,12 +1173,6 @@
                                                   VkDeviceGroupSwapchainCreateInfoKHR* to);
 
 #endif
-#ifdef VK_KHR_xcb_surface
-#endif
-#ifdef VK_KHR_android_surface
-#endif
-#ifdef VK_KHR_win32_surface
-#endif
 #ifdef VK_KHR_dynamic_rendering
 DEFINE_ALIAS_FUNCTION(deepcopy_VkRenderingInfo, deepcopy_VkRenderingInfoKHR)
 
@@ -1241,8 +1233,6 @@
                       deepcopy_VkPhysicalDeviceSparseImageFormatInfo2KHR)
 
 #endif
-#ifdef VK_KHR_maintenance1
-#endif
 #ifdef VK_KHR_external_memory_capabilities
 DEFINE_ALIAS_FUNCTION(deepcopy_VkExternalMemoryProperties, deepcopy_VkExternalMemoryPropertiesKHR)
 
@@ -1271,10 +1261,6 @@
 DEFINE_ALIAS_FUNCTION(deepcopy_VkExportMemoryAllocateInfo, deepcopy_VkExportMemoryAllocateInfoKHR)
 
 #endif
-#ifdef VK_KHR_external_memory_win32
-#endif
-#ifdef VK_KHR_external_memory_fd
-#endif
 #ifdef VK_KHR_external_semaphore_capabilities
 DEFINE_ALIAS_FUNCTION(deepcopy_VkPhysicalDeviceExternalSemaphoreInfo,
                       deepcopy_VkPhysicalDeviceExternalSemaphoreInfoKHR)
@@ -1287,8 +1273,6 @@
 DEFINE_ALIAS_FUNCTION(deepcopy_VkExportSemaphoreCreateInfo, deepcopy_VkExportSemaphoreCreateInfoKHR)
 
 #endif
-#ifdef VK_KHR_external_semaphore_win32
-#endif
 #ifdef VK_KHR_external_semaphore_fd
 void deepcopy_VkImportSemaphoreFdInfoKHR(Allocator* alloc, VkStructureType rootType,
                                          const VkImportSemaphoreFdInfoKHR* from,
@@ -1400,8 +1384,6 @@
                       deepcopy_VkMemoryDedicatedAllocateInfoKHR)
 
 #endif
-#ifdef VK_KHR_storage_buffer_storage_class
-#endif
 #ifdef VK_KHR_get_memory_requirements2
 DEFINE_ALIAS_FUNCTION(deepcopy_VkBufferMemoryRequirementsInfo2,
                       deepcopy_VkBufferMemoryRequirementsInfo2KHR)
@@ -1525,7 +1507,11 @@
                       deepcopy_VkPhysicalDeviceShaderIntegerDotProductPropertiesKHR)
 
 #endif
-#ifdef VK_KHR_shader_non_semantic_info
+#ifdef VK_KHR_pipeline_library
+void deepcopy_VkPipelineLibraryCreateInfoKHR(Allocator* alloc, VkStructureType rootType,
+                                             const VkPipelineLibraryCreateInfoKHR* from,
+                                             VkPipelineLibraryCreateInfoKHR* to);
+
 #endif
 #ifdef VK_KHR_synchronization2
 DEFINE_ALIAS_FUNCTION(deepcopy_VkMemoryBarrier2, deepcopy_VkMemoryBarrier2KHR)
@@ -1676,8 +1662,6 @@
     VkPipelineRasterizationStateStreamCreateInfoEXT* to);
 
 #endif
-#ifdef VK_AMD_gpu_shader_half_float
-#endif
 #ifdef VK_EXT_texture_compression_astc_hdr
 DEFINE_ALIAS_FUNCTION(deepcopy_VkPhysicalDeviceTextureCompressionASTCHDRFeatures,
                       deepcopy_VkPhysicalDeviceTextureCompressionASTCHDRFeaturesEXT)
@@ -1695,10 +1679,6 @@
     VkPipelineRasterizationDepthClipStateCreateInfoEXT* to);
 
 #endif
-#ifdef VK_EXT_swapchain_colorspace
-#endif
-#ifdef VK_EXT_queue_family_foreign
-#endif
 #ifdef VK_EXT_debug_utils
 void deepcopy_VkDebugUtilsLabelEXT(Allocator* alloc, VkStructureType rootType,
                                    const VkDebugUtilsLabelEXT* from, VkDebugUtilsLabelEXT* to);
@@ -1720,8 +1700,6 @@
                                            VkDebugUtilsObjectTagInfoEXT* to);
 
 #endif
-#ifdef VK_ANDROID_external_memory_android_hardware_buffer
-#endif
 #ifdef VK_EXT_inline_uniform_block
 DEFINE_ALIAS_FUNCTION(deepcopy_VkPhysicalDeviceInlineUniformBlockFeatures,
                       deepcopy_VkPhysicalDeviceInlineUniformBlockFeaturesEXT)
@@ -1736,8 +1714,6 @@
                       deepcopy_VkDescriptorPoolInlineUniformBlockCreateInfoEXT)
 
 #endif
-#ifdef VK_EXT_shader_stencil_export
-#endif
 #ifdef VK_EXT_vertex_attribute_divisor
 void deepcopy_VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT(
     Allocator* alloc, VkStructureType rootType,
@@ -1767,10 +1743,6 @@
 DEFINE_ALIAS_FUNCTION(deepcopy_VkPipelineCreationFeedback, deepcopy_VkPipelineCreationFeedbackEXT)
 
 #endif
-#ifdef VK_NV_shader_subgroup_partitioned
-#endif
-#ifdef VK_EXT_metal_surface
-#endif
 #ifdef VK_EXT_fragment_density_map
 void deepcopy_VkPhysicalDeviceFragmentDensityMapFeaturesEXT(
     Allocator* alloc, VkStructureType rootType,
@@ -2011,8 +1983,6 @@
                       deepcopy_VkPhysicalDevicePipelineCreationCacheControlFeaturesEXT)
 
 #endif
-#ifdef VK_EXT_metal_objects
-#endif
 #ifdef VK_EXT_graphics_pipeline_library
 void deepcopy_VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT(
     Allocator* alloc, VkStructureType rootType,
@@ -2099,8 +2069,6 @@
                                  const VkCreateBlobGOOGLE* from, VkCreateBlobGOOGLE* to);
 
 #endif
-#ifdef VK_EXT_load_store_op_none
-#endif
 #ifdef VK_EXT_image_compression_control_swapchain
 void deepcopy_VkPhysicalDeviceImageCompressionControlSwapchainFeaturesEXT(
     Allocator* alloc, VkStructureType rootType,
@@ -2108,8 +2076,38 @@
     VkPhysicalDeviceImageCompressionControlSwapchainFeaturesEXT* to);
 
 #endif
-#ifdef VK_QNX_external_memory_screen_buffer
-#endif
+#ifdef VK_KHR_ray_tracing_pipeline
+void deepcopy_VkRayTracingShaderGroupCreateInfoKHR(Allocator* alloc, VkStructureType rootType,
+                                                   const VkRayTracingShaderGroupCreateInfoKHR* from,
+                                                   VkRayTracingShaderGroupCreateInfoKHR* to);
 
+void deepcopy_VkRayTracingPipelineInterfaceCreateInfoKHR(
+    Allocator* alloc, VkStructureType rootType,
+    const VkRayTracingPipelineInterfaceCreateInfoKHR* from,
+    VkRayTracingPipelineInterfaceCreateInfoKHR* to);
+
+void deepcopy_VkRayTracingPipelineCreateInfoKHR(Allocator* alloc, VkStructureType rootType,
+                                                const VkRayTracingPipelineCreateInfoKHR* from,
+                                                VkRayTracingPipelineCreateInfoKHR* to);
+
+void deepcopy_VkPhysicalDeviceRayTracingPipelineFeaturesKHR(
+    Allocator* alloc, VkStructureType rootType,
+    const VkPhysicalDeviceRayTracingPipelineFeaturesKHR* from,
+    VkPhysicalDeviceRayTracingPipelineFeaturesKHR* to);
+
+void deepcopy_VkPhysicalDeviceRayTracingPipelinePropertiesKHR(
+    Allocator* alloc, VkStructureType rootType,
+    const VkPhysicalDeviceRayTracingPipelinePropertiesKHR* from,
+    VkPhysicalDeviceRayTracingPipelinePropertiesKHR* to);
+
+void deepcopy_VkStridedDeviceAddressRegionKHR(Allocator* alloc, VkStructureType rootType,
+                                              const VkStridedDeviceAddressRegionKHR* from,
+                                              VkStridedDeviceAddressRegionKHR* to);
+
+void deepcopy_VkTraceRaysIndirectCommandKHR(Allocator* alloc, VkStructureType rootType,
+                                            const VkTraceRaysIndirectCommandKHR* from,
+                                            VkTraceRaysIndirectCommandKHR* to);
+
+#endif
 }  // namespace vk
 }  // namespace gfxstream
diff --git a/host/vulkan/cereal/common/goldfish_vk_dispatch.cpp b/host/vulkan/cereal/common/goldfish_vk_dispatch.cpp
index 1e50c5b..4b8d4a3 100644
--- a/host/vulkan/cereal/common/goldfish_vk_dispatch.cpp
+++ b/host/vulkan/cereal/common/goldfish_vk_dispatch.cpp
@@ -39,199 +39,6 @@
 namespace gfxstream {
 namespace vk {
 
-#ifdef VK_VERSION_1_0
-#endif
-#ifdef VK_VERSION_1_1
-#endif
-#ifdef VK_VERSION_1_2
-#endif
-#ifdef VK_VERSION_1_3
-#endif
-#ifdef VK_KHR_surface
-#endif
-#ifdef VK_KHR_swapchain
-#endif
-#ifdef VK_KHR_xcb_surface
-#endif
-#ifdef VK_KHR_android_surface
-#endif
-#ifdef VK_KHR_win32_surface
-#endif
-#ifdef VK_KHR_dynamic_rendering
-#endif
-#ifdef VK_KHR_get_physical_device_properties2
-#endif
-#ifdef VK_KHR_maintenance1
-#endif
-#ifdef VK_KHR_external_memory_capabilities
-#endif
-#ifdef VK_KHR_external_memory
-#endif
-#ifdef VK_KHR_external_memory_win32
-#endif
-#ifdef VK_KHR_external_memory_fd
-#endif
-#ifdef VK_KHR_external_semaphore_capabilities
-#endif
-#ifdef VK_KHR_external_semaphore
-#endif
-#ifdef VK_KHR_external_semaphore_win32
-#endif
-#ifdef VK_KHR_external_semaphore_fd
-#endif
-#ifdef VK_KHR_shader_float16_int8
-#endif
-#ifdef VK_KHR_incremental_present
-#endif
-#ifdef VK_KHR_descriptor_update_template
-#endif
-#ifdef VK_KHR_imageless_framebuffer
-#endif
-#ifdef VK_KHR_create_renderpass2
-#endif
-#ifdef VK_KHR_external_fence_capabilities
-#endif
-#ifdef VK_KHR_external_fence
-#endif
-#ifdef VK_KHR_external_fence_fd
-#endif
-#ifdef VK_KHR_maintenance2
-#endif
-#ifdef VK_KHR_dedicated_allocation
-#endif
-#ifdef VK_KHR_storage_buffer_storage_class
-#endif
-#ifdef VK_KHR_get_memory_requirements2
-#endif
-#ifdef VK_KHR_image_format_list
-#endif
-#ifdef VK_KHR_sampler_ycbcr_conversion
-#endif
-#ifdef VK_KHR_bind_memory2
-#endif
-#ifdef VK_KHR_maintenance3
-#endif
-#ifdef VK_KHR_shader_subgroup_extended_types
-#endif
-#ifdef VK_KHR_vulkan_memory_model
-#endif
-#ifdef VK_KHR_shader_terminate_invocation
-#endif
-#ifdef VK_KHR_buffer_device_address
-#endif
-#ifdef VK_KHR_pipeline_executable_properties
-#endif
-#ifdef VK_KHR_shader_integer_dot_product
-#endif
-#ifdef VK_KHR_shader_non_semantic_info
-#endif
-#ifdef VK_KHR_synchronization2
-#endif
-#ifdef VK_KHR_zero_initialize_workgroup_memory
-#endif
-#ifdef VK_KHR_copy_commands2
-#endif
-#ifdef VK_KHR_format_feature_flags2
-#endif
-#ifdef VK_KHR_maintenance4
-#endif
-#ifdef VK_KHR_maintenance5
-#endif
-#ifdef VK_ANDROID_native_buffer
-#endif
-#ifdef VK_EXT_debug_report
-#endif
-#ifdef VK_EXT_transform_feedback
-#endif
-#ifdef VK_AMD_gpu_shader_half_float
-#endif
-#ifdef VK_EXT_texture_compression_astc_hdr
-#endif
-#ifdef VK_EXT_depth_clip_enable
-#endif
-#ifdef VK_EXT_swapchain_colorspace
-#endif
-#ifdef VK_EXT_queue_family_foreign
-#endif
-#ifdef VK_EXT_debug_utils
-#endif
-#ifdef VK_ANDROID_external_memory_android_hardware_buffer
-#endif
-#ifdef VK_EXT_inline_uniform_block
-#endif
-#ifdef VK_EXT_shader_stencil_export
-#endif
-#ifdef VK_EXT_vertex_attribute_divisor
-#endif
-#ifdef VK_EXT_pipeline_creation_feedback
-#endif
-#ifdef VK_NV_shader_subgroup_partitioned
-#endif
-#ifdef VK_EXT_metal_surface
-#endif
-#ifdef VK_EXT_fragment_density_map
-#endif
-#ifdef VK_EXT_scalar_block_layout
-#endif
-#ifdef VK_EXT_subgroup_size_control
-#endif
-#ifdef VK_EXT_tooling_info
-#endif
-#ifdef VK_EXT_validation_features
-#endif
-#ifdef VK_EXT_provoking_vertex
-#endif
-#ifdef VK_EXT_line_rasterization
-#endif
-#ifdef VK_EXT_index_type_uint8
-#endif
-#ifdef VK_EXT_extended_dynamic_state
-#endif
-#ifdef VK_EXT_host_image_copy
-#endif
-#ifdef VK_EXT_swapchain_maintenance1
-#endif
-#ifdef VK_EXT_shader_demote_to_helper_invocation
-#endif
-#ifdef VK_EXT_texel_buffer_alignment
-#endif
-#ifdef VK_EXT_device_memory_report
-#endif
-#ifdef VK_EXT_robustness2
-#endif
-#ifdef VK_EXT_custom_border_color
-#endif
-#ifdef VK_EXT_private_data
-#endif
-#ifdef VK_EXT_pipeline_creation_cache_control
-#endif
-#ifdef VK_EXT_metal_objects
-#endif
-#ifdef VK_EXT_graphics_pipeline_library
-#endif
-#ifdef VK_EXT_ycbcr_2plane_444_formats
-#endif
-#ifdef VK_EXT_image_robustness
-#endif
-#ifdef VK_EXT_image_compression_control
-#endif
-#ifdef VK_EXT_4444_formats
-#endif
-#ifdef VK_EXT_primitive_topology_list_restart
-#endif
-#ifdef VK_EXT_extended_dynamic_state2
-#endif
-#ifdef VK_EXT_color_write_enable
-#endif
-#ifdef VK_GOOGLE_gfxstream
-#endif
-#ifdef VK_EXT_load_store_op_none
-#endif
-#ifdef VK_EXT_image_compression_control_swapchain
-#endif
-#ifdef VK_QNX_external_memory_screen_buffer
-#endif
-
 void init_vulkan_dispatch_from_system_loader(DlOpenFunc dlOpenFunc, DlSymFunc dlSymFunc,
                                              VulkanDispatch* out) {
     memset(out, 0x0, sizeof(VulkanDispatch));
@@ -852,6 +659,11 @@
     out->vkCmdInsertDebugUtilsLabelEXT =
         (PFN_vkCmdInsertDebugUtilsLabelEXT)dlSymFunc(lib, "vkCmdInsertDebugUtilsLabelEXT");
 #endif
+#ifdef VK_NV_device_diagnostic_checkpoints
+    out->vkCmdSetCheckpointNV = (PFN_vkCmdSetCheckpointNV)dlSymFunc(lib, "vkCmdSetCheckpointNV");
+    out->vkGetQueueCheckpointDataNV =
+        (PFN_vkGetQueueCheckpointDataNV)dlSymFunc(lib, "vkGetQueueCheckpointDataNV");
+#endif
 #ifdef VK_EXT_tooling_info
     out->vkGetPhysicalDeviceToolPropertiesEXT = (PFN_vkGetPhysicalDeviceToolPropertiesEXT)dlSymFunc(
         lib, "vkGetPhysicalDeviceToolPropertiesEXT");
@@ -977,11 +789,28 @@
             lib, "vkUpdateDescriptorSetWithTemplateSized2GOOGLE");
     out->vkQueueSubmitAsync2GOOGLE =
         (PFN_vkQueueSubmitAsync2GOOGLE)dlSymFunc(lib, "vkQueueSubmitAsync2GOOGLE");
+    out->vkGetSemaphoreGOOGLE = (PFN_vkGetSemaphoreGOOGLE)dlSymFunc(lib, "vkGetSemaphoreGOOGLE");
 #endif
 #ifdef VK_QNX_external_memory_screen_buffer
     out->vkGetScreenBufferPropertiesQNX =
         (PFN_vkGetScreenBufferPropertiesQNX)dlSymFunc(lib, "vkGetScreenBufferPropertiesQNX");
 #endif
+#ifdef VK_KHR_ray_tracing_pipeline
+    out->vkCmdTraceRaysKHR = (PFN_vkCmdTraceRaysKHR)dlSymFunc(lib, "vkCmdTraceRaysKHR");
+    out->vkCreateRayTracingPipelinesKHR =
+        (PFN_vkCreateRayTracingPipelinesKHR)dlSymFunc(lib, "vkCreateRayTracingPipelinesKHR");
+    out->vkGetRayTracingCaptureReplayShaderGroupHandlesKHR =
+        (PFN_vkGetRayTracingCaptureReplayShaderGroupHandlesKHR)dlSymFunc(
+            lib, "vkGetRayTracingCaptureReplayShaderGroupHandlesKHR");
+    out->vkCmdTraceRaysIndirectKHR =
+        (PFN_vkCmdTraceRaysIndirectKHR)dlSymFunc(lib, "vkCmdTraceRaysIndirectKHR");
+    out->vkGetRayTracingShaderGroupStackSizeKHR =
+        (PFN_vkGetRayTracingShaderGroupStackSizeKHR)dlSymFunc(
+            lib, "vkGetRayTracingShaderGroupStackSizeKHR");
+    out->vkCmdSetRayTracingPipelineStackSizeKHR =
+        (PFN_vkCmdSetRayTracingPipelineStackSizeKHR)dlSymFunc(
+            lib, "vkCmdSetRayTracingPipelineStackSizeKHR");
+#endif
 }
 
 void init_vulkan_dispatch_from_instance(VulkanDispatch* vk, VkInstance instance,
@@ -1789,6 +1618,12 @@
         (PFN_vkCmdInsertDebugUtilsLabelEXT)vk->vkGetInstanceProcAddr(
             instance, "vkCmdInsertDebugUtilsLabelEXT");
 #endif
+#ifdef VK_NV_device_diagnostic_checkpoints
+    out->vkCmdSetCheckpointNV =
+        (PFN_vkCmdSetCheckpointNV)vk->vkGetInstanceProcAddr(instance, "vkCmdSetCheckpointNV");
+    out->vkGetQueueCheckpointDataNV = (PFN_vkGetQueueCheckpointDataNV)vk->vkGetInstanceProcAddr(
+        instance, "vkGetQueueCheckpointDataNV");
+#endif
 #ifdef VK_EXT_tooling_info
     out->vkGetPhysicalDeviceToolPropertiesEXT =
         (PFN_vkGetPhysicalDeviceToolPropertiesEXT)vk->vkGetInstanceProcAddr(
@@ -1939,12 +1774,32 @@
             instance, "vkUpdateDescriptorSetWithTemplateSized2GOOGLE");
     out->vkQueueSubmitAsync2GOOGLE = (PFN_vkQueueSubmitAsync2GOOGLE)vk->vkGetInstanceProcAddr(
         instance, "vkQueueSubmitAsync2GOOGLE");
+    out->vkGetSemaphoreGOOGLE =
+        (PFN_vkGetSemaphoreGOOGLE)vk->vkGetInstanceProcAddr(instance, "vkGetSemaphoreGOOGLE");
 #endif
 #ifdef VK_QNX_external_memory_screen_buffer
     out->vkGetScreenBufferPropertiesQNX =
         (PFN_vkGetScreenBufferPropertiesQNX)vk->vkGetInstanceProcAddr(
             instance, "vkGetScreenBufferPropertiesQNX");
 #endif
+#ifdef VK_KHR_ray_tracing_pipeline
+    out->vkCmdTraceRaysKHR =
+        (PFN_vkCmdTraceRaysKHR)vk->vkGetInstanceProcAddr(instance, "vkCmdTraceRaysKHR");
+    out->vkCreateRayTracingPipelinesKHR =
+        (PFN_vkCreateRayTracingPipelinesKHR)vk->vkGetInstanceProcAddr(
+            instance, "vkCreateRayTracingPipelinesKHR");
+    out->vkGetRayTracingCaptureReplayShaderGroupHandlesKHR =
+        (PFN_vkGetRayTracingCaptureReplayShaderGroupHandlesKHR)vk->vkGetInstanceProcAddr(
+            instance, "vkGetRayTracingCaptureReplayShaderGroupHandlesKHR");
+    out->vkCmdTraceRaysIndirectKHR = (PFN_vkCmdTraceRaysIndirectKHR)vk->vkGetInstanceProcAddr(
+        instance, "vkCmdTraceRaysIndirectKHR");
+    out->vkGetRayTracingShaderGroupStackSizeKHR =
+        (PFN_vkGetRayTracingShaderGroupStackSizeKHR)vk->vkGetInstanceProcAddr(
+            instance, "vkGetRayTracingShaderGroupStackSizeKHR");
+    out->vkCmdSetRayTracingPipelineStackSizeKHR =
+        (PFN_vkCmdSetRayTracingPipelineStackSizeKHR)vk->vkGetInstanceProcAddr(
+            instance, "vkCmdSetRayTracingPipelineStackSizeKHR");
+#endif
 }
 
 void init_vulkan_dispatch_from_device(VulkanDispatch* vk, VkDevice device, VulkanDispatch* out) {
@@ -2730,6 +2585,12 @@
     out->vkCmdInsertDebugUtilsLabelEXT = (PFN_vkCmdInsertDebugUtilsLabelEXT)vk->vkGetDeviceProcAddr(
         device, "vkCmdInsertDebugUtilsLabelEXT");
 #endif
+#ifdef VK_NV_device_diagnostic_checkpoints
+    out->vkCmdSetCheckpointNV =
+        (PFN_vkCmdSetCheckpointNV)vk->vkGetDeviceProcAddr(device, "vkCmdSetCheckpointNV");
+    out->vkGetQueueCheckpointDataNV = (PFN_vkGetQueueCheckpointDataNV)vk->vkGetDeviceProcAddr(
+        device, "vkGetQueueCheckpointDataNV");
+#endif
 #ifdef VK_EXT_tooling_info
     out->vkGetPhysicalDeviceToolPropertiesEXT =
         (PFN_vkGetPhysicalDeviceToolPropertiesEXT)vk->vkGetDeviceProcAddr(
@@ -2875,12 +2736,32 @@
             device, "vkUpdateDescriptorSetWithTemplateSized2GOOGLE");
     out->vkQueueSubmitAsync2GOOGLE =
         (PFN_vkQueueSubmitAsync2GOOGLE)vk->vkGetDeviceProcAddr(device, "vkQueueSubmitAsync2GOOGLE");
+    out->vkGetSemaphoreGOOGLE =
+        (PFN_vkGetSemaphoreGOOGLE)vk->vkGetDeviceProcAddr(device, "vkGetSemaphoreGOOGLE");
 #endif
 #ifdef VK_QNX_external_memory_screen_buffer
     out->vkGetScreenBufferPropertiesQNX =
         (PFN_vkGetScreenBufferPropertiesQNX)vk->vkGetDeviceProcAddr(
             device, "vkGetScreenBufferPropertiesQNX");
 #endif
+#ifdef VK_KHR_ray_tracing_pipeline
+    out->vkCmdTraceRaysKHR =
+        (PFN_vkCmdTraceRaysKHR)vk->vkGetDeviceProcAddr(device, "vkCmdTraceRaysKHR");
+    out->vkCreateRayTracingPipelinesKHR =
+        (PFN_vkCreateRayTracingPipelinesKHR)vk->vkGetDeviceProcAddr(
+            device, "vkCreateRayTracingPipelinesKHR");
+    out->vkGetRayTracingCaptureReplayShaderGroupHandlesKHR =
+        (PFN_vkGetRayTracingCaptureReplayShaderGroupHandlesKHR)vk->vkGetDeviceProcAddr(
+            device, "vkGetRayTracingCaptureReplayShaderGroupHandlesKHR");
+    out->vkCmdTraceRaysIndirectKHR =
+        (PFN_vkCmdTraceRaysIndirectKHR)vk->vkGetDeviceProcAddr(device, "vkCmdTraceRaysIndirectKHR");
+    out->vkGetRayTracingShaderGroupStackSizeKHR =
+        (PFN_vkGetRayTracingShaderGroupStackSizeKHR)vk->vkGetDeviceProcAddr(
+            device, "vkGetRayTracingShaderGroupStackSizeKHR");
+    out->vkCmdSetRayTracingPipelineStackSizeKHR =
+        (PFN_vkCmdSetRayTracingPipelineStackSizeKHR)vk->vkGetDeviceProcAddr(
+            device, "vkCmdSetRayTracingPipelineStackSizeKHR");
+#endif
 }
 
 bool vulkan_dispatch_check_instance_VK_VERSION_1_0(const VulkanDispatch* vk)
diff --git a/host/vulkan/cereal/common/goldfish_vk_dispatch.h b/host/vulkan/cereal/common/goldfish_vk_dispatch.h
index 06700b2..3723f23 100644
--- a/host/vulkan/cereal/common/goldfish_vk_dispatch.h
+++ b/host/vulkan/cereal/common/goldfish_vk_dispatch.h
@@ -314,8 +314,6 @@
     PFN_vkCreateXcbSurfaceKHR vkCreateXcbSurfaceKHR;
     PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR vkGetPhysicalDeviceXcbPresentationSupportKHR;
 #endif
-#ifdef VK_KHR_android_surface
-#endif
 #ifdef VK_KHR_win32_surface
     PFN_vkCreateWin32SurfaceKHR vkCreateWin32SurfaceKHR;
     PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR
@@ -342,8 +340,6 @@
     PFN_vkGetPhysicalDeviceExternalBufferPropertiesKHR
         vkGetPhysicalDeviceExternalBufferPropertiesKHR;
 #endif
-#ifdef VK_KHR_external_memory
-#endif
 #ifdef VK_KHR_external_memory_win32
     PFN_vkGetMemoryWin32HandleKHR vkGetMemoryWin32HandleKHR;
     PFN_vkGetMemoryWin32HandlePropertiesKHR vkGetMemoryWin32HandlePropertiesKHR;
@@ -356,8 +352,6 @@
     PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR
         vkGetPhysicalDeviceExternalSemaphorePropertiesKHR;
 #endif
-#ifdef VK_KHR_external_semaphore
-#endif
 #ifdef VK_KHR_external_semaphore_win32
     PFN_vkImportSemaphoreWin32HandleKHR vkImportSemaphoreWin32HandleKHR;
     PFN_vkGetSemaphoreWin32HandleKHR vkGetSemaphoreWin32HandleKHR;
@@ -366,17 +360,11 @@
     PFN_vkImportSemaphoreFdKHR vkImportSemaphoreFdKHR;
     PFN_vkGetSemaphoreFdKHR vkGetSemaphoreFdKHR;
 #endif
-#ifdef VK_KHR_shader_float16_int8
-#endif
-#ifdef VK_KHR_incremental_present
-#endif
 #ifdef VK_KHR_descriptor_update_template
     PFN_vkCreateDescriptorUpdateTemplateKHR vkCreateDescriptorUpdateTemplateKHR;
     PFN_vkDestroyDescriptorUpdateTemplateKHR vkDestroyDescriptorUpdateTemplateKHR;
     PFN_vkUpdateDescriptorSetWithTemplateKHR vkUpdateDescriptorSetWithTemplateKHR;
 #endif
-#ifdef VK_KHR_imageless_framebuffer
-#endif
 #ifdef VK_KHR_create_renderpass2
     PFN_vkCreateRenderPass2KHR vkCreateRenderPass2KHR;
     PFN_vkCmdBeginRenderPass2KHR vkCmdBeginRenderPass2KHR;
@@ -386,25 +374,15 @@
 #ifdef VK_KHR_external_fence_capabilities
     PFN_vkGetPhysicalDeviceExternalFencePropertiesKHR vkGetPhysicalDeviceExternalFencePropertiesKHR;
 #endif
-#ifdef VK_KHR_external_fence
-#endif
 #ifdef VK_KHR_external_fence_fd
     PFN_vkImportFenceFdKHR vkImportFenceFdKHR;
     PFN_vkGetFenceFdKHR vkGetFenceFdKHR;
 #endif
-#ifdef VK_KHR_maintenance2
-#endif
-#ifdef VK_KHR_dedicated_allocation
-#endif
-#ifdef VK_KHR_storage_buffer_storage_class
-#endif
 #ifdef VK_KHR_get_memory_requirements2
     PFN_vkGetImageMemoryRequirements2KHR vkGetImageMemoryRequirements2KHR;
     PFN_vkGetBufferMemoryRequirements2KHR vkGetBufferMemoryRequirements2KHR;
     PFN_vkGetImageSparseMemoryRequirements2KHR vkGetImageSparseMemoryRequirements2KHR;
 #endif
-#ifdef VK_KHR_image_format_list
-#endif
 #ifdef VK_KHR_sampler_ycbcr_conversion
     PFN_vkCreateSamplerYcbcrConversionKHR vkCreateSamplerYcbcrConversionKHR;
     PFN_vkDestroySamplerYcbcrConversionKHR vkDestroySamplerYcbcrConversionKHR;
@@ -416,12 +394,6 @@
 #ifdef VK_KHR_maintenance3
     PFN_vkGetDescriptorSetLayoutSupportKHR vkGetDescriptorSetLayoutSupportKHR;
 #endif
-#ifdef VK_KHR_shader_subgroup_extended_types
-#endif
-#ifdef VK_KHR_vulkan_memory_model
-#endif
-#ifdef VK_KHR_shader_terminate_invocation
-#endif
 #ifdef VK_KHR_buffer_device_address
     PFN_vkGetBufferDeviceAddressKHR vkGetBufferDeviceAddressKHR;
     PFN_vkGetBufferOpaqueCaptureAddressKHR vkGetBufferOpaqueCaptureAddressKHR;
@@ -433,10 +405,6 @@
     PFN_vkGetPipelineExecutableInternalRepresentationsKHR
         vkGetPipelineExecutableInternalRepresentationsKHR;
 #endif
-#ifdef VK_KHR_shader_integer_dot_product
-#endif
-#ifdef VK_KHR_shader_non_semantic_info
-#endif
 #ifdef VK_KHR_synchronization2
     PFN_vkCmdSetEvent2KHR vkCmdSetEvent2KHR;
     PFN_vkCmdResetEvent2KHR vkCmdResetEvent2KHR;
@@ -447,8 +415,6 @@
     PFN_vkCmdWriteBufferMarker2AMD vkCmdWriteBufferMarker2AMD;
     PFN_vkGetQueueCheckpointData2NV vkGetQueueCheckpointData2NV;
 #endif
-#ifdef VK_KHR_zero_initialize_workgroup_memory
-#endif
 #ifdef VK_KHR_copy_commands2
     PFN_vkCmdCopyBuffer2KHR vkCmdCopyBuffer2KHR;
     PFN_vkCmdCopyImage2KHR vkCmdCopyImage2KHR;
@@ -457,8 +423,6 @@
     PFN_vkCmdBlitImage2KHR vkCmdBlitImage2KHR;
     PFN_vkCmdResolveImage2KHR vkCmdResolveImage2KHR;
 #endif
-#ifdef VK_KHR_format_feature_flags2
-#endif
 #ifdef VK_KHR_maintenance4
     PFN_vkGetDeviceBufferMemoryRequirementsKHR vkGetDeviceBufferMemoryRequirementsKHR;
     PFN_vkGetDeviceImageMemoryRequirementsKHR vkGetDeviceImageMemoryRequirementsKHR;
@@ -489,16 +453,6 @@
     PFN_vkCmdEndQueryIndexedEXT vkCmdEndQueryIndexedEXT;
     PFN_vkCmdDrawIndirectByteCountEXT vkCmdDrawIndirectByteCountEXT;
 #endif
-#ifdef VK_AMD_gpu_shader_half_float
-#endif
-#ifdef VK_EXT_texture_compression_astc_hdr
-#endif
-#ifdef VK_EXT_depth_clip_enable
-#endif
-#ifdef VK_EXT_swapchain_colorspace
-#endif
-#ifdef VK_EXT_queue_family_foreign
-#endif
 #ifdef VK_EXT_debug_utils
     PFN_vkSetDebugUtilsObjectNameEXT vkSetDebugUtilsObjectNameEXT;
     PFN_vkSetDebugUtilsObjectTagEXT vkSetDebugUtilsObjectTagEXT;
@@ -512,39 +466,19 @@
     PFN_vkDestroyDebugUtilsMessengerEXT vkDestroyDebugUtilsMessengerEXT;
     PFN_vkSubmitDebugUtilsMessageEXT vkSubmitDebugUtilsMessageEXT;
 #endif
-#ifdef VK_ANDROID_external_memory_android_hardware_buffer
-#endif
-#ifdef VK_EXT_inline_uniform_block
-#endif
-#ifdef VK_EXT_shader_stencil_export
-#endif
-#ifdef VK_EXT_vertex_attribute_divisor
-#endif
-#ifdef VK_EXT_pipeline_creation_feedback
-#endif
-#ifdef VK_NV_shader_subgroup_partitioned
+#ifdef VK_NV_device_diagnostic_checkpoints
+    PFN_vkCmdSetCheckpointNV vkCmdSetCheckpointNV;
+    PFN_vkGetQueueCheckpointDataNV vkGetQueueCheckpointDataNV;
 #endif
 #ifdef VK_EXT_metal_surface
     PFN_vkCreateMetalSurfaceEXT vkCreateMetalSurfaceEXT;
 #endif
-#ifdef VK_EXT_fragment_density_map
-#endif
-#ifdef VK_EXT_scalar_block_layout
-#endif
-#ifdef VK_EXT_subgroup_size_control
-#endif
 #ifdef VK_EXT_tooling_info
     PFN_vkGetPhysicalDeviceToolPropertiesEXT vkGetPhysicalDeviceToolPropertiesEXT;
 #endif
-#ifdef VK_EXT_validation_features
-#endif
-#ifdef VK_EXT_provoking_vertex
-#endif
 #ifdef VK_EXT_line_rasterization
     PFN_vkCmdSetLineStippleEXT vkCmdSetLineStippleEXT;
 #endif
-#ifdef VK_EXT_index_type_uint8
-#endif
 #ifdef VK_EXT_extended_dynamic_state
     PFN_vkCmdSetCullModeEXT vkCmdSetCullModeEXT;
     PFN_vkCmdSetFrontFaceEXT vkCmdSetFrontFaceEXT;
@@ -569,39 +503,15 @@
 #ifdef VK_EXT_swapchain_maintenance1
     PFN_vkReleaseSwapchainImagesEXT vkReleaseSwapchainImagesEXT;
 #endif
-#ifdef VK_EXT_shader_demote_to_helper_invocation
-#endif
-#ifdef VK_EXT_texel_buffer_alignment
-#endif
-#ifdef VK_EXT_device_memory_report
-#endif
-#ifdef VK_EXT_robustness2
-#endif
-#ifdef VK_EXT_custom_border_color
-#endif
 #ifdef VK_EXT_private_data
     PFN_vkCreatePrivateDataSlotEXT vkCreatePrivateDataSlotEXT;
     PFN_vkDestroyPrivateDataSlotEXT vkDestroyPrivateDataSlotEXT;
     PFN_vkSetPrivateDataEXT vkSetPrivateDataEXT;
     PFN_vkGetPrivateDataEXT vkGetPrivateDataEXT;
 #endif
-#ifdef VK_EXT_pipeline_creation_cache_control
-#endif
 #ifdef VK_EXT_metal_objects
     PFN_vkExportMetalObjectsEXT vkExportMetalObjectsEXT;
 #endif
-#ifdef VK_EXT_graphics_pipeline_library
-#endif
-#ifdef VK_EXT_ycbcr_2plane_444_formats
-#endif
-#ifdef VK_EXT_image_robustness
-#endif
-#ifdef VK_EXT_image_compression_control
-#endif
-#ifdef VK_EXT_4444_formats
-#endif
-#ifdef VK_EXT_primitive_topology_list_restart
-#endif
 #ifdef VK_EXT_extended_dynamic_state2
     PFN_vkCmdSetPatchControlPointsEXT vkCmdSetPatchControlPointsEXT;
     PFN_vkCmdSetRasterizerDiscardEnableEXT vkCmdSetRasterizerDiscardEnableEXT;
@@ -637,14 +547,20 @@
     PFN_vkGetBlobGOOGLE vkGetBlobGOOGLE;
     PFN_vkUpdateDescriptorSetWithTemplateSized2GOOGLE vkUpdateDescriptorSetWithTemplateSized2GOOGLE;
     PFN_vkQueueSubmitAsync2GOOGLE vkQueueSubmitAsync2GOOGLE;
-#endif
-#ifdef VK_EXT_load_store_op_none
-#endif
-#ifdef VK_EXT_image_compression_control_swapchain
+    PFN_vkGetSemaphoreGOOGLE vkGetSemaphoreGOOGLE;
 #endif
 #ifdef VK_QNX_external_memory_screen_buffer
     PFN_vkGetScreenBufferPropertiesQNX vkGetScreenBufferPropertiesQNX;
 #endif
+#ifdef VK_KHR_ray_tracing_pipeline
+    PFN_vkCmdTraceRaysKHR vkCmdTraceRaysKHR;
+    PFN_vkCreateRayTracingPipelinesKHR vkCreateRayTracingPipelinesKHR;
+    PFN_vkGetRayTracingCaptureReplayShaderGroupHandlesKHR
+        vkGetRayTracingCaptureReplayShaderGroupHandlesKHR;
+    PFN_vkCmdTraceRaysIndirectKHR vkCmdTraceRaysIndirectKHR;
+    PFN_vkGetRayTracingShaderGroupStackSizeKHR vkGetRayTracingShaderGroupStackSizeKHR;
+    PFN_vkCmdSetRayTracingPipelineStackSizeKHR vkCmdSetRayTracingPipelineStackSizeKHR;
+#endif
 };
 
 }  // namespace vk
diff --git a/host/vulkan/cereal/common/goldfish_vk_extension_structs.cpp b/host/vulkan/cereal/common/goldfish_vk_extension_structs.cpp
index 4661eff..61c2754 100644
--- a/host/vulkan/cereal/common/goldfish_vk_extension_structs.cpp
+++ b/host/vulkan/cereal/common/goldfish_vk_extension_structs.cpp
@@ -34,198 +34,6 @@
 namespace gfxstream {
 namespace vk {
 
-#ifdef VK_VERSION_1_0
-#endif
-#ifdef VK_VERSION_1_1
-#endif
-#ifdef VK_VERSION_1_2
-#endif
-#ifdef VK_VERSION_1_3
-#endif
-#ifdef VK_KHR_surface
-#endif
-#ifdef VK_KHR_swapchain
-#endif
-#ifdef VK_KHR_xcb_surface
-#endif
-#ifdef VK_KHR_android_surface
-#endif
-#ifdef VK_KHR_win32_surface
-#endif
-#ifdef VK_KHR_dynamic_rendering
-#endif
-#ifdef VK_KHR_get_physical_device_properties2
-#endif
-#ifdef VK_KHR_maintenance1
-#endif
-#ifdef VK_KHR_external_memory_capabilities
-#endif
-#ifdef VK_KHR_external_memory
-#endif
-#ifdef VK_KHR_external_memory_win32
-#endif
-#ifdef VK_KHR_external_memory_fd
-#endif
-#ifdef VK_KHR_external_semaphore_capabilities
-#endif
-#ifdef VK_KHR_external_semaphore
-#endif
-#ifdef VK_KHR_external_semaphore_win32
-#endif
-#ifdef VK_KHR_external_semaphore_fd
-#endif
-#ifdef VK_KHR_shader_float16_int8
-#endif
-#ifdef VK_KHR_incremental_present
-#endif
-#ifdef VK_KHR_descriptor_update_template
-#endif
-#ifdef VK_KHR_imageless_framebuffer
-#endif
-#ifdef VK_KHR_create_renderpass2
-#endif
-#ifdef VK_KHR_external_fence_capabilities
-#endif
-#ifdef VK_KHR_external_fence
-#endif
-#ifdef VK_KHR_external_fence_fd
-#endif
-#ifdef VK_KHR_maintenance2
-#endif
-#ifdef VK_KHR_dedicated_allocation
-#endif
-#ifdef VK_KHR_storage_buffer_storage_class
-#endif
-#ifdef VK_KHR_get_memory_requirements2
-#endif
-#ifdef VK_KHR_image_format_list
-#endif
-#ifdef VK_KHR_sampler_ycbcr_conversion
-#endif
-#ifdef VK_KHR_bind_memory2
-#endif
-#ifdef VK_KHR_maintenance3
-#endif
-#ifdef VK_KHR_shader_subgroup_extended_types
-#endif
-#ifdef VK_KHR_vulkan_memory_model
-#endif
-#ifdef VK_KHR_shader_terminate_invocation
-#endif
-#ifdef VK_KHR_buffer_device_address
-#endif
-#ifdef VK_KHR_pipeline_executable_properties
-#endif
-#ifdef VK_KHR_shader_integer_dot_product
-#endif
-#ifdef VK_KHR_shader_non_semantic_info
-#endif
-#ifdef VK_KHR_synchronization2
-#endif
-#ifdef VK_KHR_zero_initialize_workgroup_memory
-#endif
-#ifdef VK_KHR_copy_commands2
-#endif
-#ifdef VK_KHR_format_feature_flags2
-#endif
-#ifdef VK_KHR_maintenance4
-#endif
-#ifdef VK_KHR_maintenance5
-#endif
-#ifdef VK_ANDROID_native_buffer
-#endif
-#ifdef VK_EXT_debug_report
-#endif
-#ifdef VK_EXT_transform_feedback
-#endif
-#ifdef VK_AMD_gpu_shader_half_float
-#endif
-#ifdef VK_EXT_texture_compression_astc_hdr
-#endif
-#ifdef VK_EXT_depth_clip_enable
-#endif
-#ifdef VK_EXT_swapchain_colorspace
-#endif
-#ifdef VK_EXT_queue_family_foreign
-#endif
-#ifdef VK_EXT_debug_utils
-#endif
-#ifdef VK_ANDROID_external_memory_android_hardware_buffer
-#endif
-#ifdef VK_EXT_inline_uniform_block
-#endif
-#ifdef VK_EXT_shader_stencil_export
-#endif
-#ifdef VK_EXT_vertex_attribute_divisor
-#endif
-#ifdef VK_EXT_pipeline_creation_feedback
-#endif
-#ifdef VK_NV_shader_subgroup_partitioned
-#endif
-#ifdef VK_EXT_metal_surface
-#endif
-#ifdef VK_EXT_fragment_density_map
-#endif
-#ifdef VK_EXT_scalar_block_layout
-#endif
-#ifdef VK_EXT_subgroup_size_control
-#endif
-#ifdef VK_EXT_tooling_info
-#endif
-#ifdef VK_EXT_validation_features
-#endif
-#ifdef VK_EXT_provoking_vertex
-#endif
-#ifdef VK_EXT_line_rasterization
-#endif
-#ifdef VK_EXT_index_type_uint8
-#endif
-#ifdef VK_EXT_extended_dynamic_state
-#endif
-#ifdef VK_EXT_host_image_copy
-#endif
-#ifdef VK_EXT_swapchain_maintenance1
-#endif
-#ifdef VK_EXT_shader_demote_to_helper_invocation
-#endif
-#ifdef VK_EXT_texel_buffer_alignment
-#endif
-#ifdef VK_EXT_device_memory_report
-#endif
-#ifdef VK_EXT_robustness2
-#endif
-#ifdef VK_EXT_custom_border_color
-#endif
-#ifdef VK_EXT_private_data
-#endif
-#ifdef VK_EXT_pipeline_creation_cache_control
-#endif
-#ifdef VK_EXT_metal_objects
-#endif
-#ifdef VK_EXT_graphics_pipeline_library
-#endif
-#ifdef VK_EXT_ycbcr_2plane_444_formats
-#endif
-#ifdef VK_EXT_image_robustness
-#endif
-#ifdef VK_EXT_image_compression_control
-#endif
-#ifdef VK_EXT_4444_formats
-#endif
-#ifdef VK_EXT_primitive_topology_list_restart
-#endif
-#ifdef VK_EXT_extended_dynamic_state2
-#endif
-#ifdef VK_EXT_color_write_enable
-#endif
-#ifdef VK_GOOGLE_gfxstream
-#endif
-#ifdef VK_EXT_load_store_op_none
-#endif
-#ifdef VK_EXT_image_compression_control_swapchain
-#endif
-#ifdef VK_QNX_external_memory_screen_buffer
-#endif
 uint32_t goldfish_vk_struct_type(const void* structExtension) {
     const uint32_t asStructType = *(reinterpret_cast<const uint32_t*>(structExtension));
     return asStructType;
@@ -580,6 +388,53 @@
             return sizeof(VkDeviceGroupSwapchainCreateInfoKHR);
         }
 #endif
+#ifdef VK_KHR_display_swapchain
+        case VK_STRUCTURE_TYPE_DISPLAY_PRESENT_INFO_KHR: {
+            return sizeof(VkDisplayPresentInfoKHR);
+        }
+#endif
+#ifdef VK_KHR_video_queue
+        case VK_STRUCTURE_TYPE_QUEUE_FAMILY_QUERY_RESULT_STATUS_PROPERTIES_KHR: {
+            return sizeof(VkQueueFamilyQueryResultStatusPropertiesKHR);
+        }
+        case VK_STRUCTURE_TYPE_QUEUE_FAMILY_VIDEO_PROPERTIES_KHR: {
+            return sizeof(VkQueueFamilyVideoPropertiesKHR);
+        }
+        case VK_STRUCTURE_TYPE_VIDEO_PROFILE_INFO_KHR: {
+            return sizeof(VkVideoProfileInfoKHR);
+        }
+        case VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR: {
+            return sizeof(VkVideoProfileListInfoKHR);
+        }
+#endif
+#ifdef VK_KHR_video_decode_queue
+        case VK_STRUCTURE_TYPE_VIDEO_DECODE_CAPABILITIES_KHR: {
+            return sizeof(VkVideoDecodeCapabilitiesKHR);
+        }
+        case VK_STRUCTURE_TYPE_VIDEO_DECODE_USAGE_INFO_KHR: {
+            return sizeof(VkVideoDecodeUsageInfoKHR);
+        }
+#endif
+#ifdef VK_KHR_video_decode_h264
+        case VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PROFILE_INFO_KHR: {
+            return sizeof(VkVideoDecodeH264ProfileInfoKHR);
+        }
+        case VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_CAPABILITIES_KHR: {
+            return sizeof(VkVideoDecodeH264CapabilitiesKHR);
+        }
+        case VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_ADD_INFO_KHR: {
+            return sizeof(VkVideoDecodeH264SessionParametersAddInfoKHR);
+        }
+        case VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_CREATE_INFO_KHR: {
+            return sizeof(VkVideoDecodeH264SessionParametersCreateInfoKHR);
+        }
+        case VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PICTURE_INFO_KHR: {
+            return sizeof(VkVideoDecodeH264PictureInfoKHR);
+        }
+        case VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_DPB_SLOT_INFO_KHR: {
+            return sizeof(VkVideoDecodeH264DpbSlotInfoKHR);
+        }
+#endif
 #ifdef VK_KHR_dynamic_rendering
         case VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR: {
             return sizeof(VkRenderingFragmentShadingRateAttachmentInfoKHR);
@@ -594,21 +449,190 @@
             return sizeof(VkMultiviewPerViewAttributesInfoNVX);
         }
 #endif
+#ifdef VK_KHR_win32_keyed_mutex
+        case VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_KHR: {
+            return sizeof(VkWin32KeyedMutexAcquireReleaseInfoKHR);
+        }
+#endif
+#ifdef VK_KHR_push_descriptor
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR: {
+            return sizeof(VkPhysicalDevicePushDescriptorPropertiesKHR);
+        }
+#endif
 #ifdef VK_KHR_incremental_present
         case VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR: {
             return sizeof(VkPresentRegionsKHR);
         }
 #endif
+#ifdef VK_KHR_shared_presentable_image
+        case VK_STRUCTURE_TYPE_SHARED_PRESENT_SURFACE_CAPABILITIES_KHR: {
+            return sizeof(VkSharedPresentSurfaceCapabilitiesKHR);
+        }
+#endif
+#ifdef VK_KHR_external_fence_win32
+        case VK_STRUCTURE_TYPE_EXPORT_FENCE_WIN32_HANDLE_INFO_KHR: {
+            return sizeof(VkExportFenceWin32HandleInfoKHR);
+        }
+#endif
+#ifdef VK_KHR_performance_query
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_FEATURES_KHR: {
+            return sizeof(VkPhysicalDevicePerformanceQueryFeaturesKHR);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_PROPERTIES_KHR: {
+            return sizeof(VkPhysicalDevicePerformanceQueryPropertiesKHR);
+        }
+        case VK_STRUCTURE_TYPE_QUERY_POOL_PERFORMANCE_CREATE_INFO_KHR: {
+            return sizeof(VkQueryPoolPerformanceCreateInfoKHR);
+        }
+        case VK_STRUCTURE_TYPE_PERFORMANCE_QUERY_SUBMIT_INFO_KHR: {
+            return sizeof(VkPerformanceQuerySubmitInfoKHR);
+        }
+#endif
+#ifdef VK_KHR_portability_subset
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_FEATURES_KHR: {
+            return sizeof(VkPhysicalDevicePortabilitySubsetFeaturesKHR);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_PROPERTIES_KHR: {
+            return sizeof(VkPhysicalDevicePortabilitySubsetPropertiesKHR);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#endif
+#ifdef VK_KHR_shader_clock
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CLOCK_FEATURES_KHR: {
+            return sizeof(VkPhysicalDeviceShaderClockFeaturesKHR);
+        }
+#endif
+#ifdef VK_KHR_video_decode_h265
+        case VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PROFILE_INFO_KHR: {
+            return sizeof(VkVideoDecodeH265ProfileInfoKHR);
+        }
+        case VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_CAPABILITIES_KHR: {
+            return sizeof(VkVideoDecodeH265CapabilitiesKHR);
+        }
+        case VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_ADD_INFO_KHR: {
+            return sizeof(VkVideoDecodeH265SessionParametersAddInfoKHR);
+        }
+        case VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_CREATE_INFO_KHR: {
+            return sizeof(VkVideoDecodeH265SessionParametersCreateInfoKHR);
+        }
+        case VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PICTURE_INFO_KHR: {
+            return sizeof(VkVideoDecodeH265PictureInfoKHR);
+        }
+        case VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_DPB_SLOT_INFO_KHR: {
+            return sizeof(VkVideoDecodeH265DpbSlotInfoKHR);
+        }
+#endif
+#ifdef VK_KHR_global_priority
+        case VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_KHR: {
+            return sizeof(VkDeviceQueueGlobalPriorityCreateInfoKHR);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GLOBAL_PRIORITY_QUERY_FEATURES_KHR: {
+            return sizeof(VkPhysicalDeviceGlobalPriorityQueryFeaturesKHR);
+        }
+        case VK_STRUCTURE_TYPE_QUEUE_FAMILY_GLOBAL_PRIORITY_PROPERTIES_KHR: {
+            return sizeof(VkQueueFamilyGlobalPriorityPropertiesKHR);
+        }
+#endif
+#ifdef VK_KHR_fragment_shading_rate
+        case VK_STRUCTURE_TYPE_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR: {
+            return sizeof(VkFragmentShadingRateAttachmentInfoKHR);
+        }
+        case VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_STATE_CREATE_INFO_KHR: {
+            return sizeof(VkPipelineFragmentShadingRateStateCreateInfoKHR);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR: {
+            return sizeof(VkPhysicalDeviceFragmentShadingRateFeaturesKHR);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_PROPERTIES_KHR: {
+            return sizeof(VkPhysicalDeviceFragmentShadingRatePropertiesKHR);
+        }
+#endif
+#ifdef VK_KHR_surface_protected_capabilities
+        case VK_STRUCTURE_TYPE_SURFACE_PROTECTED_CAPABILITIES_KHR: {
+            return sizeof(VkSurfaceProtectedCapabilitiesKHR);
+        }
+#endif
+#ifdef VK_KHR_present_wait
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_WAIT_FEATURES_KHR: {
+            return sizeof(VkPhysicalDevicePresentWaitFeaturesKHR);
+        }
+#endif
 #ifdef VK_KHR_pipeline_executable_properties
         case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_EXECUTABLE_PROPERTIES_FEATURES_KHR: {
             return sizeof(VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR);
         }
 #endif
+#ifdef VK_KHR_pipeline_library
+        case VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR: {
+            return sizeof(VkPipelineLibraryCreateInfoKHR);
+        }
+#endif
+#ifdef VK_KHR_present_id
+        case VK_STRUCTURE_TYPE_PRESENT_ID_KHR: {
+            return sizeof(VkPresentIdKHR);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_ID_FEATURES_KHR: {
+            return sizeof(VkPhysicalDevicePresentIdFeaturesKHR);
+        }
+#endif
+#ifdef VK_KHR_video_encode_queue
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_CAPABILITIES_KHR: {
+            return sizeof(VkVideoEncodeCapabilitiesKHR);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_QUERY_POOL_VIDEO_ENCODE_FEEDBACK_CREATE_INFO_KHR: {
+            return sizeof(VkQueryPoolVideoEncodeFeedbackCreateInfoKHR);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_USAGE_INFO_KHR: {
+            return sizeof(VkVideoEncodeUsageInfoKHR);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_RATE_CONTROL_INFO_KHR: {
+            return sizeof(VkVideoEncodeRateControlInfoKHR);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_QUALITY_LEVEL_INFO_KHR: {
+            return sizeof(VkVideoEncodeQualityLevelInfoKHR);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#endif
 #ifdef VK_KHR_synchronization2
         case VK_STRUCTURE_TYPE_QUEUE_FAMILY_CHECKPOINT_PROPERTIES_2_NV: {
             return sizeof(VkQueueFamilyCheckpointProperties2NV);
         }
 #endif
+#ifdef VK_KHR_fragment_shader_barycentric
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_FEATURES_KHR: {
+            return sizeof(VkPhysicalDeviceFragmentShaderBarycentricFeaturesKHR);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_PROPERTIES_KHR: {
+            return sizeof(VkPhysicalDeviceFragmentShaderBarycentricPropertiesKHR);
+        }
+#endif
+#ifdef VK_KHR_shader_subgroup_uniform_control_flow
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_UNIFORM_CONTROL_FLOW_FEATURES_KHR: {
+            return sizeof(VkPhysicalDeviceShaderSubgroupUniformControlFlowFeaturesKHR);
+        }
+#endif
+#ifdef VK_KHR_workgroup_memory_explicit_layout
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_FEATURES_KHR: {
+            return sizeof(VkPhysicalDeviceWorkgroupMemoryExplicitLayoutFeaturesKHR);
+        }
+#endif
+#ifdef VK_KHR_ray_tracing_maintenance1
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_MAINTENANCE_1_FEATURES_KHR: {
+            return sizeof(VkPhysicalDeviceRayTracingMaintenance1FeaturesKHR);
+        }
+#endif
 #ifdef VK_KHR_maintenance5
         case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_5_FEATURES_KHR: {
             return sizeof(VkPhysicalDeviceMaintenance5FeaturesKHR);
@@ -623,6 +647,19 @@
             return sizeof(VkBufferUsageFlags2CreateInfoKHR);
         }
 #endif
+#ifdef VK_KHR_ray_tracing_position_fetch
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_POSITION_FETCH_FEATURES_KHR: {
+            return sizeof(VkPhysicalDeviceRayTracingPositionFetchFeaturesKHR);
+        }
+#endif
+#ifdef VK_KHR_cooperative_matrix
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_FEATURES_KHR: {
+            return sizeof(VkPhysicalDeviceCooperativeMatrixFeaturesKHR);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_PROPERTIES_KHR: {
+            return sizeof(VkPhysicalDeviceCooperativeMatrixPropertiesKHR);
+        }
+#endif
 #ifdef VK_ANDROID_native_buffer
         case VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID: {
             return sizeof(VkNativeBufferANDROID);
@@ -633,6 +670,22 @@
             return sizeof(VkDebugReportCallbackCreateInfoEXT);
         }
 #endif
+#ifdef VK_AMD_rasterization_order
+        case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_RASTERIZATION_ORDER_AMD: {
+            return sizeof(VkPipelineRasterizationStateRasterizationOrderAMD);
+        }
+#endif
+#ifdef VK_NV_dedicated_allocation
+        case VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_IMAGE_CREATE_INFO_NV: {
+            return sizeof(VkDedicatedAllocationImageCreateInfoNV);
+        }
+        case VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_BUFFER_CREATE_INFO_NV: {
+            return sizeof(VkDedicatedAllocationBufferCreateInfoNV);
+        }
+        case VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV: {
+            return sizeof(VkDedicatedAllocationMemoryAllocateInfoNV);
+        }
+#endif
 #ifdef VK_EXT_transform_feedback
         case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT: {
             return sizeof(VkPhysicalDeviceTransformFeedbackFeaturesEXT);
@@ -644,6 +697,244 @@
             return sizeof(VkPipelineRasterizationStateStreamCreateInfoEXT);
         }
 #endif
+#ifdef VK_EXT_video_encode_h264
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_CAPABILITIES_EXT: {
+            return sizeof(VkVideoEncodeH264CapabilitiesEXT);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_QUALITY_LEVEL_PROPERTIES_EXT: {
+            return sizeof(VkVideoEncodeH264QualityLevelPropertiesEXT);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_CREATE_INFO_EXT: {
+            return sizeof(VkVideoEncodeH264SessionCreateInfoEXT);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_PARAMETERS_ADD_INFO_EXT: {
+            return sizeof(VkVideoEncodeH264SessionParametersAddInfoEXT);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_PARAMETERS_CREATE_INFO_EXT: {
+            return sizeof(VkVideoEncodeH264SessionParametersCreateInfoEXT);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_PARAMETERS_GET_INFO_EXT: {
+            return sizeof(VkVideoEncodeH264SessionParametersGetInfoEXT);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_PARAMETERS_FEEDBACK_INFO_EXT: {
+            return sizeof(VkVideoEncodeH264SessionParametersFeedbackInfoEXT);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_PICTURE_INFO_EXT: {
+            return sizeof(VkVideoEncodeH264PictureInfoEXT);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_DPB_SLOT_INFO_EXT: {
+            return sizeof(VkVideoEncodeH264DpbSlotInfoEXT);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_PROFILE_INFO_EXT: {
+            return sizeof(VkVideoEncodeH264ProfileInfoEXT);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_RATE_CONTROL_INFO_EXT: {
+            return sizeof(VkVideoEncodeH264RateControlInfoEXT);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_RATE_CONTROL_LAYER_INFO_EXT: {
+            return sizeof(VkVideoEncodeH264RateControlLayerInfoEXT);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_GOP_REMAINING_FRAME_INFO_EXT: {
+            return sizeof(VkVideoEncodeH264GopRemainingFrameInfoEXT);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#endif
+#ifdef VK_EXT_video_encode_h265
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_CAPABILITIES_EXT: {
+            return sizeof(VkVideoEncodeH265CapabilitiesEXT);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_CREATE_INFO_EXT: {
+            return sizeof(VkVideoEncodeH265SessionCreateInfoEXT);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_QUALITY_LEVEL_PROPERTIES_EXT: {
+            return sizeof(VkVideoEncodeH265QualityLevelPropertiesEXT);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_PARAMETERS_ADD_INFO_EXT: {
+            return sizeof(VkVideoEncodeH265SessionParametersAddInfoEXT);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_PARAMETERS_CREATE_INFO_EXT: {
+            return sizeof(VkVideoEncodeH265SessionParametersCreateInfoEXT);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_PARAMETERS_GET_INFO_EXT: {
+            return sizeof(VkVideoEncodeH265SessionParametersGetInfoEXT);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_PARAMETERS_FEEDBACK_INFO_EXT: {
+            return sizeof(VkVideoEncodeH265SessionParametersFeedbackInfoEXT);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_PICTURE_INFO_EXT: {
+            return sizeof(VkVideoEncodeH265PictureInfoEXT);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_DPB_SLOT_INFO_EXT: {
+            return sizeof(VkVideoEncodeH265DpbSlotInfoEXT);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_PROFILE_INFO_EXT: {
+            return sizeof(VkVideoEncodeH265ProfileInfoEXT);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_RATE_CONTROL_INFO_EXT: {
+            return sizeof(VkVideoEncodeH265RateControlInfoEXT);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_RATE_CONTROL_LAYER_INFO_EXT: {
+            return sizeof(VkVideoEncodeH265RateControlLayerInfoEXT);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_GOP_REMAINING_FRAME_INFO_EXT: {
+            return sizeof(VkVideoEncodeH265GopRemainingFrameInfoEXT);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#endif
+#ifdef VK_AMD_texture_gather_bias_lod
+        case VK_STRUCTURE_TYPE_TEXTURE_LOD_GATHER_FORMAT_PROPERTIES_AMD: {
+            return sizeof(VkTextureLODGatherFormatPropertiesAMD);
+        }
+#endif
+#ifdef VK_NV_corner_sampled_image
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CORNER_SAMPLED_IMAGE_FEATURES_NV: {
+            return sizeof(VkPhysicalDeviceCornerSampledImageFeaturesNV);
+        }
+#endif
+#ifdef VK_NV_external_memory
+        case VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_NV: {
+            return sizeof(VkExternalMemoryImageCreateInfoNV);
+        }
+        case VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_NV: {
+            return sizeof(VkExportMemoryAllocateInfoNV);
+        }
+#endif
+#ifdef VK_NV_external_memory_win32
+        case VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_NV: {
+            return sizeof(VkImportMemoryWin32HandleInfoNV);
+        }
+        case VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_NV: {
+            return sizeof(VkExportMemoryWin32HandleInfoNV);
+        }
+#endif
+#ifdef VK_NV_win32_keyed_mutex
+        case VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_NV: {
+            return sizeof(VkWin32KeyedMutexAcquireReleaseInfoNV);
+        }
+#endif
+#ifdef VK_EXT_validation_flags
+        case VK_STRUCTURE_TYPE_VALIDATION_FLAGS_EXT: {
+            return sizeof(VkValidationFlagsEXT);
+        }
+#endif
+#ifdef VK_EXT_astc_decode_mode
+        case VK_STRUCTURE_TYPE_IMAGE_VIEW_ASTC_DECODE_MODE_EXT: {
+            return sizeof(VkImageViewASTCDecodeModeEXT);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ASTC_DECODE_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceASTCDecodeFeaturesEXT);
+        }
+#endif
+#ifdef VK_EXT_pipeline_robustness
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_ROBUSTNESS_FEATURES_EXT: {
+            return sizeof(VkPhysicalDevicePipelineRobustnessFeaturesEXT);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_ROBUSTNESS_PROPERTIES_EXT: {
+            return sizeof(VkPhysicalDevicePipelineRobustnessPropertiesEXT);
+        }
+        case VK_STRUCTURE_TYPE_PIPELINE_ROBUSTNESS_CREATE_INFO_EXT: {
+            return sizeof(VkPipelineRobustnessCreateInfoEXT);
+        }
+#endif
+#ifdef VK_EXT_conditional_rendering
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONDITIONAL_RENDERING_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceConditionalRenderingFeaturesEXT);
+        }
+        case VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_CONDITIONAL_RENDERING_INFO_EXT: {
+            return sizeof(VkCommandBufferInheritanceConditionalRenderingInfoEXT);
+        }
+#endif
+#ifdef VK_NV_clip_space_w_scaling
+        case VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_W_SCALING_STATE_CREATE_INFO_NV: {
+            return sizeof(VkPipelineViewportWScalingStateCreateInfoNV);
+        }
+#endif
+#ifdef VK_EXT_display_control
+        case VK_STRUCTURE_TYPE_SWAPCHAIN_COUNTER_CREATE_INFO_EXT: {
+            return sizeof(VkSwapchainCounterCreateInfoEXT);
+        }
+#endif
+#ifdef VK_GOOGLE_display_timing
+        case VK_STRUCTURE_TYPE_PRESENT_TIMES_INFO_GOOGLE: {
+            return sizeof(VkPresentTimesInfoGOOGLE);
+        }
+#endif
+#ifdef VK_NVX_multiview_per_view_attributes
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_ATTRIBUTES_PROPERTIES_NVX: {
+            return sizeof(VkPhysicalDeviceMultiviewPerViewAttributesPropertiesNVX);
+        }
+#endif
+#ifdef VK_NV_viewport_swizzle
+        case VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SWIZZLE_STATE_CREATE_INFO_NV: {
+            return sizeof(VkPipelineViewportSwizzleStateCreateInfoNV);
+        }
+#endif
+#ifdef VK_EXT_discard_rectangles
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DISCARD_RECTANGLE_PROPERTIES_EXT: {
+            return sizeof(VkPhysicalDeviceDiscardRectanglePropertiesEXT);
+        }
+        case VK_STRUCTURE_TYPE_PIPELINE_DISCARD_RECTANGLE_STATE_CREATE_INFO_EXT: {
+            return sizeof(VkPipelineDiscardRectangleStateCreateInfoEXT);
+        }
+#endif
+#ifdef VK_EXT_conservative_rasterization
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONSERVATIVE_RASTERIZATION_PROPERTIES_EXT: {
+            return sizeof(VkPhysicalDeviceConservativeRasterizationPropertiesEXT);
+        }
+        case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_CONSERVATIVE_STATE_CREATE_INFO_EXT: {
+            return sizeof(VkPipelineRasterizationConservativeStateCreateInfoEXT);
+        }
+#endif
 #ifdef VK_EXT_depth_clip_enable
         case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_ENABLE_FEATURES_EXT: {
             return sizeof(VkPhysicalDeviceDepthClipEnableFeaturesEXT);
@@ -660,6 +951,149 @@
             return sizeof(VkDebugUtilsMessengerCreateInfoEXT);
         }
 #endif
+#ifdef VK_AMDX_shader_enqueue
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ENQUEUE_FEATURES_AMDX: {
+            return sizeof(VkPhysicalDeviceShaderEnqueueFeaturesAMDX);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ENQUEUE_PROPERTIES_AMDX: {
+            return sizeof(VkPhysicalDeviceShaderEnqueuePropertiesAMDX);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_NODE_CREATE_INFO_AMDX: {
+            return sizeof(VkPipelineShaderStageNodeCreateInfoAMDX);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#endif
+#ifdef VK_EXT_sample_locations
+        case VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT: {
+            return sizeof(VkSampleLocationsInfoEXT);
+        }
+        case VK_STRUCTURE_TYPE_RENDER_PASS_SAMPLE_LOCATIONS_BEGIN_INFO_EXT: {
+            return sizeof(VkRenderPassSampleLocationsBeginInfoEXT);
+        }
+        case VK_STRUCTURE_TYPE_PIPELINE_SAMPLE_LOCATIONS_STATE_CREATE_INFO_EXT: {
+            return sizeof(VkPipelineSampleLocationsStateCreateInfoEXT);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLE_LOCATIONS_PROPERTIES_EXT: {
+            return sizeof(VkPhysicalDeviceSampleLocationsPropertiesEXT);
+        }
+#endif
+#ifdef VK_EXT_blend_operation_advanced
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_PROPERTIES_EXT: {
+            return sizeof(VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT);
+        }
+        case VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_ADVANCED_STATE_CREATE_INFO_EXT: {
+            return sizeof(VkPipelineColorBlendAdvancedStateCreateInfoEXT);
+        }
+#endif
+#ifdef VK_NV_fragment_coverage_to_color
+        case VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_TO_COLOR_STATE_CREATE_INFO_NV: {
+            return sizeof(VkPipelineCoverageToColorStateCreateInfoNV);
+        }
+#endif
+#ifdef VK_NV_framebuffer_mixed_samples
+        case VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_MODULATION_STATE_CREATE_INFO_NV: {
+            return sizeof(VkPipelineCoverageModulationStateCreateInfoNV);
+        }
+#endif
+#ifdef VK_NV_shader_sm_builtins
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SM_BUILTINS_PROPERTIES_NV: {
+            return sizeof(VkPhysicalDeviceShaderSMBuiltinsPropertiesNV);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SM_BUILTINS_FEATURES_NV: {
+            return sizeof(VkPhysicalDeviceShaderSMBuiltinsFeaturesNV);
+        }
+#endif
+#ifdef VK_EXT_image_drm_format_modifier
+        case VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT: {
+            return sizeof(VkDrmFormatModifierPropertiesListEXT);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT: {
+            return sizeof(VkPhysicalDeviceImageDrmFormatModifierInfoEXT);
+        }
+        case VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT: {
+            return sizeof(VkImageDrmFormatModifierListCreateInfoEXT);
+        }
+        case VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT: {
+            return sizeof(VkImageDrmFormatModifierExplicitCreateInfoEXT);
+        }
+        case VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_2_EXT: {
+            return sizeof(VkDrmFormatModifierPropertiesList2EXT);
+        }
+#endif
+#ifdef VK_EXT_validation_cache
+        case VK_STRUCTURE_TYPE_SHADER_MODULE_VALIDATION_CACHE_CREATE_INFO_EXT: {
+            return sizeof(VkShaderModuleValidationCacheCreateInfoEXT);
+        }
+#endif
+#ifdef VK_NV_shading_rate_image
+        case VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SHADING_RATE_IMAGE_STATE_CREATE_INFO_NV: {
+            return sizeof(VkPipelineViewportShadingRateImageStateCreateInfoNV);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_FEATURES_NV: {
+            return sizeof(VkPhysicalDeviceShadingRateImageFeaturesNV);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_PROPERTIES_NV: {
+            return sizeof(VkPhysicalDeviceShadingRateImagePropertiesNV);
+        }
+        case VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_COARSE_SAMPLE_ORDER_STATE_CREATE_INFO_NV: {
+            return sizeof(VkPipelineViewportCoarseSampleOrderStateCreateInfoNV);
+        }
+#endif
+#ifdef VK_NV_ray_tracing
+        case VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_NV: {
+            return sizeof(VkWriteDescriptorSetAccelerationStructureNV);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_NV: {
+            return sizeof(VkPhysicalDeviceRayTracingPropertiesNV);
+        }
+#endif
+#ifdef VK_NV_representative_fragment_test
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_REPRESENTATIVE_FRAGMENT_TEST_FEATURES_NV: {
+            return sizeof(VkPhysicalDeviceRepresentativeFragmentTestFeaturesNV);
+        }
+        case VK_STRUCTURE_TYPE_PIPELINE_REPRESENTATIVE_FRAGMENT_TEST_STATE_CREATE_INFO_NV: {
+            return sizeof(VkPipelineRepresentativeFragmentTestStateCreateInfoNV);
+        }
+#endif
+#ifdef VK_EXT_filter_cubic
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_IMAGE_FORMAT_INFO_EXT: {
+            return sizeof(VkPhysicalDeviceImageViewImageFormatInfoEXT);
+        }
+        case VK_STRUCTURE_TYPE_FILTER_CUBIC_IMAGE_VIEW_IMAGE_FORMAT_PROPERTIES_EXT: {
+            return sizeof(VkFilterCubicImageViewImageFormatPropertiesEXT);
+        }
+#endif
+#ifdef VK_EXT_external_memory_host
+        case VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT: {
+            return sizeof(VkImportMemoryHostPointerInfoEXT);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT: {
+            return sizeof(VkPhysicalDeviceExternalMemoryHostPropertiesEXT);
+        }
+#endif
+#ifdef VK_AMD_pipeline_compiler_control
+        case VK_STRUCTURE_TYPE_PIPELINE_COMPILER_CONTROL_CREATE_INFO_AMD: {
+            return sizeof(VkPipelineCompilerControlCreateInfoAMD);
+        }
+#endif
+#ifdef VK_AMD_shader_core_properties
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_AMD: {
+            return sizeof(VkPhysicalDeviceShaderCorePropertiesAMD);
+        }
+#endif
+#ifdef VK_AMD_memory_overallocation_behavior
+        case VK_STRUCTURE_TYPE_DEVICE_MEMORY_OVERALLOCATION_CREATE_INFO_AMD: {
+            return sizeof(VkDeviceMemoryOverallocationCreateInfoAMD);
+        }
+#endif
 #ifdef VK_EXT_vertex_attribute_divisor
         case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT: {
             return sizeof(VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT);
@@ -671,6 +1105,60 @@
             return sizeof(VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT);
         }
 #endif
+#ifdef VK_GGP_frame_token
+        case VK_STRUCTURE_TYPE_PRESENT_FRAME_TOKEN_GGP: {
+            return sizeof(VkPresentFrameTokenGGP);
+        }
+#endif
+#ifdef VK_NV_compute_shader_derivatives
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COMPUTE_SHADER_DERIVATIVES_FEATURES_NV: {
+            return sizeof(VkPhysicalDeviceComputeShaderDerivativesFeaturesNV);
+        }
+#endif
+#ifdef VK_NV_mesh_shader
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_NV: {
+            return sizeof(VkPhysicalDeviceMeshShaderFeaturesNV);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_PROPERTIES_NV: {
+            return sizeof(VkPhysicalDeviceMeshShaderPropertiesNV);
+        }
+#endif
+#ifdef VK_NV_shader_image_footprint
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_IMAGE_FOOTPRINT_FEATURES_NV: {
+            return sizeof(VkPhysicalDeviceShaderImageFootprintFeaturesNV);
+        }
+#endif
+#ifdef VK_NV_scissor_exclusive
+        case VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_EXCLUSIVE_SCISSOR_STATE_CREATE_INFO_NV: {
+            return sizeof(VkPipelineViewportExclusiveScissorStateCreateInfoNV);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXCLUSIVE_SCISSOR_FEATURES_NV: {
+            return sizeof(VkPhysicalDeviceExclusiveScissorFeaturesNV);
+        }
+#endif
+#ifdef VK_INTEL_shader_integer_functions2
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_FUNCTIONS_2_FEATURES_INTEL: {
+            return sizeof(VkPhysicalDeviceShaderIntegerFunctions2FeaturesINTEL);
+        }
+#endif
+#ifdef VK_INTEL_performance_query
+        case VK_STRUCTURE_TYPE_QUERY_POOL_PERFORMANCE_QUERY_CREATE_INFO_INTEL: {
+            return sizeof(VkQueryPoolPerformanceQueryCreateInfoINTEL);
+        }
+#endif
+#ifdef VK_EXT_pci_bus_info
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PCI_BUS_INFO_PROPERTIES_EXT: {
+            return sizeof(VkPhysicalDevicePCIBusInfoPropertiesEXT);
+        }
+#endif
+#ifdef VK_AMD_display_native_hdr
+        case VK_STRUCTURE_TYPE_DISPLAY_NATIVE_HDR_SURFACE_CAPABILITIES_AMD: {
+            return sizeof(VkDisplayNativeHdrSurfaceCapabilitiesAMD);
+        }
+        case VK_STRUCTURE_TYPE_SWAPCHAIN_DISPLAY_NATIVE_HDR_CREATE_INFO_AMD: {
+            return sizeof(VkSwapchainDisplayNativeHdrCreateInfoAMD);
+        }
+#endif
 #ifdef VK_EXT_fragment_density_map
         case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_FEATURES_EXT: {
             switch (rootType) {
@@ -729,11 +1217,78 @@
             }
         }
 #endif
+#ifdef VK_AMD_shader_core_properties2
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_2_AMD: {
+            return sizeof(VkPhysicalDeviceShaderCoreProperties2AMD);
+        }
+#endif
+#ifdef VK_AMD_device_coherent_memory
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COHERENT_MEMORY_FEATURES_AMD: {
+            return sizeof(VkPhysicalDeviceCoherentMemoryFeaturesAMD);
+        }
+#endif
+#ifdef VK_EXT_shader_image_atomic_int64
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_IMAGE_ATOMIC_INT64_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceShaderImageAtomicInt64FeaturesEXT);
+        }
+#endif
+#ifdef VK_EXT_memory_budget
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT: {
+            return sizeof(VkPhysicalDeviceMemoryBudgetPropertiesEXT);
+        }
+#endif
+#ifdef VK_EXT_memory_priority
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PRIORITY_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceMemoryPriorityFeaturesEXT);
+        }
+        case VK_STRUCTURE_TYPE_MEMORY_PRIORITY_ALLOCATE_INFO_EXT: {
+            return sizeof(VkMemoryPriorityAllocateInfoEXT);
+        }
+#endif
+#ifdef VK_NV_dedicated_allocation_image_aliasing
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEDICATED_ALLOCATION_IMAGE_ALIASING_FEATURES_NV: {
+            return sizeof(VkPhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV);
+        }
+#endif
+#ifdef VK_EXT_buffer_device_address
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceBufferDeviceAddressFeaturesEXT);
+        }
+        case VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_CREATE_INFO_EXT: {
+            return sizeof(VkBufferDeviceAddressCreateInfoEXT);
+        }
+#endif
 #ifdef VK_EXT_validation_features
         case VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT: {
             return sizeof(VkValidationFeaturesEXT);
         }
 #endif
+#ifdef VK_NV_cooperative_matrix
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_FEATURES_NV: {
+            return sizeof(VkPhysicalDeviceCooperativeMatrixFeaturesNV);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_PROPERTIES_NV: {
+            return sizeof(VkPhysicalDeviceCooperativeMatrixPropertiesNV);
+        }
+#endif
+#ifdef VK_NV_coverage_reduction_mode
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COVERAGE_REDUCTION_MODE_FEATURES_NV: {
+            return sizeof(VkPhysicalDeviceCoverageReductionModeFeaturesNV);
+        }
+        case VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_REDUCTION_STATE_CREATE_INFO_NV: {
+            return sizeof(VkPipelineCoverageReductionStateCreateInfoNV);
+        }
+#endif
+#ifdef VK_EXT_fragment_shader_interlock
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_INTERLOCK_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT);
+        }
+#endif
+#ifdef VK_EXT_ycbcr_image_arrays
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_YCBCR_IMAGE_ARRAYS_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceYcbcrImageArraysFeaturesEXT);
+        }
+#endif
 #ifdef VK_EXT_provoking_vertex
         case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_FEATURES_EXT: {
             return sizeof(VkPhysicalDeviceProvokingVertexFeaturesEXT);
@@ -745,6 +1300,17 @@
             return sizeof(VkPipelineRasterizationProvokingVertexStateCreateInfoEXT);
         }
 #endif
+#ifdef VK_EXT_full_screen_exclusive
+        case VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_INFO_EXT: {
+            return sizeof(VkSurfaceFullScreenExclusiveInfoEXT);
+        }
+        case VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_FULL_SCREEN_EXCLUSIVE_EXT: {
+            return sizeof(VkSurfaceCapabilitiesFullScreenExclusiveEXT);
+        }
+        case VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_WIN32_INFO_EXT: {
+            return sizeof(VkSurfaceFullScreenExclusiveWin32InfoEXT);
+        }
+#endif
 #ifdef VK_EXT_line_rasterization
         case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT: {
             return sizeof(VkPhysicalDeviceLineRasterizationFeaturesEXT);
@@ -756,6 +1322,11 @@
             return sizeof(VkPipelineRasterizationLineStateCreateInfoEXT);
         }
 #endif
+#ifdef VK_EXT_shader_atomic_float
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceShaderAtomicFloatFeaturesEXT);
+        }
+#endif
 #ifdef VK_EXT_index_type_uint8
         case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES_EXT: {
             return sizeof(VkPhysicalDeviceIndexTypeUint8FeaturesEXT);
@@ -780,6 +1351,22 @@
             return sizeof(VkHostImageCopyDevicePerformanceQueryEXT);
         }
 #endif
+#ifdef VK_EXT_shader_atomic_float2
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_2_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceShaderAtomicFloat2FeaturesEXT);
+        }
+#endif
+#ifdef VK_EXT_surface_maintenance1
+        case VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_EXT: {
+            return sizeof(VkSurfacePresentModeEXT);
+        }
+        case VK_STRUCTURE_TYPE_SURFACE_PRESENT_SCALING_CAPABILITIES_EXT: {
+            return sizeof(VkSurfacePresentScalingCapabilitiesEXT);
+        }
+        case VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_COMPATIBILITY_EXT: {
+            return sizeof(VkSurfacePresentModeCompatibilityEXT);
+        }
+#endif
 #ifdef VK_EXT_swapchain_maintenance1
         case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SWAPCHAIN_MAINTENANCE_1_FEATURES_EXT: {
             return sizeof(VkPhysicalDeviceSwapchainMaintenance1FeaturesEXT);
@@ -797,11 +1384,46 @@
             return sizeof(VkSwapchainPresentScalingCreateInfoEXT);
         }
 #endif
+#ifdef VK_NV_device_generated_commands
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_PROPERTIES_NV: {
+            return sizeof(VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_FEATURES_NV: {
+            return sizeof(VkPhysicalDeviceDeviceGeneratedCommandsFeaturesNV);
+        }
+        case VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_SHADER_GROUPS_CREATE_INFO_NV: {
+            return sizeof(VkGraphicsPipelineShaderGroupsCreateInfoNV);
+        }
+#endif
+#ifdef VK_NV_inherited_viewport_scissor
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INHERITED_VIEWPORT_SCISSOR_FEATURES_NV: {
+            return sizeof(VkPhysicalDeviceInheritedViewportScissorFeaturesNV);
+        }
+        case VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_VIEWPORT_SCISSOR_INFO_NV: {
+            return sizeof(VkCommandBufferInheritanceViewportScissorInfoNV);
+        }
+#endif
 #ifdef VK_EXT_texel_buffer_alignment
         case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_FEATURES_EXT: {
             return sizeof(VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT);
         }
 #endif
+#ifdef VK_QCOM_render_pass_transform
+        case VK_STRUCTURE_TYPE_RENDER_PASS_TRANSFORM_BEGIN_INFO_QCOM: {
+            return sizeof(VkRenderPassTransformBeginInfoQCOM);
+        }
+        case VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDER_PASS_TRANSFORM_INFO_QCOM: {
+            return sizeof(VkCommandBufferInheritanceRenderPassTransformInfoQCOM);
+        }
+#endif
+#ifdef VK_EXT_depth_bias_control
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_BIAS_CONTROL_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceDepthBiasControlFeaturesEXT);
+        }
+        case VK_STRUCTURE_TYPE_DEPTH_BIAS_REPRESENTATION_INFO_EXT: {
+            return sizeof(VkDepthBiasRepresentationInfoEXT);
+        }
+#endif
 #ifdef VK_EXT_device_memory_report
         case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_MEMORY_REPORT_FEATURES_EXT: {
             return sizeof(VkPhysicalDeviceDeviceMemoryReportFeaturesEXT);
@@ -829,6 +1451,55 @@
             return sizeof(VkPhysicalDeviceCustomBorderColorFeaturesEXT);
         }
 #endif
+#ifdef VK_NV_present_barrier
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_BARRIER_FEATURES_NV: {
+            return sizeof(VkPhysicalDevicePresentBarrierFeaturesNV);
+        }
+        case VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_PRESENT_BARRIER_NV: {
+            return sizeof(VkSurfaceCapabilitiesPresentBarrierNV);
+        }
+        case VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_BARRIER_CREATE_INFO_NV: {
+            return sizeof(VkSwapchainPresentBarrierCreateInfoNV);
+        }
+#endif
+#ifdef VK_NV_device_diagnostics_config
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DIAGNOSTICS_CONFIG_FEATURES_NV: {
+            return sizeof(VkPhysicalDeviceDiagnosticsConfigFeaturesNV);
+        }
+        case VK_STRUCTURE_TYPE_DEVICE_DIAGNOSTICS_CONFIG_CREATE_INFO_NV: {
+            return sizeof(VkDeviceDiagnosticsConfigCreateInfoNV);
+        }
+#endif
+#ifdef VK_NV_cuda_kernel_launch
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUDA_KERNEL_LAUNCH_FEATURES_NV: {
+            return sizeof(VkPhysicalDeviceCudaKernelLaunchFeaturesNV);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUDA_KERNEL_LAUNCH_PROPERTIES_NV: {
+            return sizeof(VkPhysicalDeviceCudaKernelLaunchPropertiesNV);
+        }
+#endif
+#ifdef VK_NV_low_latency
+        case VK_STRUCTURE_TYPE_QUERY_LOW_LATENCY_SUPPORT_NV: {
+            return sizeof(VkQueryLowLatencySupportNV);
+        }
+#endif
+#ifdef VK_EXT_descriptor_buffer
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_PROPERTIES_EXT: {
+            return sizeof(VkPhysicalDeviceDescriptorBufferPropertiesEXT);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_DENSITY_MAP_PROPERTIES_EXT: {
+            return sizeof(VkPhysicalDeviceDescriptorBufferDensityMapPropertiesEXT);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceDescriptorBufferFeaturesEXT);
+        }
+        case VK_STRUCTURE_TYPE_DESCRIPTOR_BUFFER_BINDING_PUSH_DESCRIPTOR_BUFFER_HANDLE_EXT: {
+            return sizeof(VkDescriptorBufferBindingPushDescriptorBufferHandleEXT);
+        }
+        case VK_STRUCTURE_TYPE_OPAQUE_CAPTURE_DESCRIPTOR_DATA_CREATE_INFO_EXT: {
+            return sizeof(VkOpaqueCaptureDescriptorDataCreateInfoEXT);
+        }
+#endif
 #ifdef VK_EXT_graphics_pipeline_library
         case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GRAPHICS_PIPELINE_LIBRARY_FEATURES_EXT: {
             return sizeof(VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT);
@@ -840,11 +1511,51 @@
             return sizeof(VkGraphicsPipelineLibraryCreateInfoEXT);
         }
 #endif
+#ifdef VK_AMD_shader_early_and_late_fragment_tests
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_EARLY_AND_LATE_FRAGMENT_TESTS_FEATURES_AMD: {
+            return sizeof(VkPhysicalDeviceShaderEarlyAndLateFragmentTestsFeaturesAMD);
+        }
+#endif
+#ifdef VK_NV_fragment_shading_rate_enums
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_ENUMS_FEATURES_NV: {
+            return sizeof(VkPhysicalDeviceFragmentShadingRateEnumsFeaturesNV);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_ENUMS_PROPERTIES_NV: {
+            return sizeof(VkPhysicalDeviceFragmentShadingRateEnumsPropertiesNV);
+        }
+        case VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_ENUM_STATE_CREATE_INFO_NV: {
+            return sizeof(VkPipelineFragmentShadingRateEnumStateCreateInfoNV);
+        }
+#endif
+#ifdef VK_NV_ray_tracing_motion_blur
+        case VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_MOTION_TRIANGLES_DATA_NV: {
+            return sizeof(VkAccelerationStructureGeometryMotionTrianglesDataNV);
+        }
+        case VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MOTION_INFO_NV: {
+            return sizeof(VkAccelerationStructureMotionInfoNV);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_MOTION_BLUR_FEATURES_NV: {
+            return sizeof(VkPhysicalDeviceRayTracingMotionBlurFeaturesNV);
+        }
+#endif
 #ifdef VK_EXT_ycbcr_2plane_444_formats
         case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_YCBCR_2_PLANE_444_FORMATS_FEATURES_EXT: {
             return sizeof(VkPhysicalDeviceYcbcr2Plane444FormatsFeaturesEXT);
         }
 #endif
+#ifdef VK_EXT_fragment_density_map2
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_2_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceFragmentDensityMap2FeaturesEXT);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_2_PROPERTIES_EXT: {
+            return sizeof(VkPhysicalDeviceFragmentDensityMap2PropertiesEXT);
+        }
+#endif
+#ifdef VK_QCOM_rotated_copy_commands
+        case VK_STRUCTURE_TYPE_COPY_COMMAND_TRANSFORM_INFO_QCOM: {
+            return sizeof(VkCopyCommandTransformInfoQCOM);
+        }
+#endif
 #ifdef VK_EXT_image_compression_control
         case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_COMPRESSION_CONTROL_FEATURES_EXT: {
             return sizeof(VkPhysicalDeviceImageCompressionControlFeaturesEXT);
@@ -856,16 +1567,131 @@
             return sizeof(VkImageCompressionPropertiesEXT);
         }
 #endif
+#ifdef VK_EXT_attachment_feedback_loop_layout
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ATTACHMENT_FEEDBACK_LOOP_LAYOUT_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceAttachmentFeedbackLoopLayoutFeaturesEXT);
+        }
+#endif
 #ifdef VK_EXT_4444_formats
         case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_4444_FORMATS_FEATURES_EXT: {
             return sizeof(VkPhysicalDevice4444FormatsFeaturesEXT);
         }
 #endif
+#ifdef VK_EXT_device_fault
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FAULT_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceFaultFeaturesEXT);
+        }
+#endif
+#ifdef VK_ARM_rasterization_order_attachment_access
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceRasterizationOrderAttachmentAccessFeaturesEXT);
+        }
+#endif
+#ifdef VK_EXT_rgba10x6_formats
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RGBA10X6_FORMATS_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceRGBA10X6FormatsFeaturesEXT);
+        }
+#endif
+#ifdef VK_VALVE_mutable_descriptor_type
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MUTABLE_DESCRIPTOR_TYPE_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceMutableDescriptorTypeFeaturesEXT);
+        }
+        case VK_STRUCTURE_TYPE_MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_EXT: {
+            return sizeof(VkMutableDescriptorTypeCreateInfoEXT);
+        }
+#endif
+#ifdef VK_EXT_vertex_input_dynamic_state
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_INPUT_DYNAMIC_STATE_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceVertexInputDynamicStateFeaturesEXT);
+        }
+#endif
+#ifdef VK_EXT_physical_device_drm
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRM_PROPERTIES_EXT: {
+            return sizeof(VkPhysicalDeviceDrmPropertiesEXT);
+        }
+#endif
+#ifdef VK_EXT_device_address_binding_report
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ADDRESS_BINDING_REPORT_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceAddressBindingReportFeaturesEXT);
+        }
+        case VK_STRUCTURE_TYPE_DEVICE_ADDRESS_BINDING_CALLBACK_DATA_EXT: {
+            return sizeof(VkDeviceAddressBindingCallbackDataEXT);
+        }
+#endif
+#ifdef VK_EXT_depth_clip_control
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_CONTROL_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceDepthClipControlFeaturesEXT);
+        }
+        case VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_DEPTH_CLIP_CONTROL_CREATE_INFO_EXT: {
+            return sizeof(VkPipelineViewportDepthClipControlCreateInfoEXT);
+        }
+#endif
 #ifdef VK_EXT_primitive_topology_list_restart
         case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIMITIVE_TOPOLOGY_LIST_RESTART_FEATURES_EXT: {
             return sizeof(VkPhysicalDevicePrimitiveTopologyListRestartFeaturesEXT);
         }
 #endif
+#ifdef VK_FUCHSIA_external_memory
+        case VK_STRUCTURE_TYPE_IMPORT_MEMORY_ZIRCON_HANDLE_INFO_FUCHSIA: {
+            return sizeof(VkImportMemoryZirconHandleInfoFUCHSIA);
+        }
+#endif
+#ifdef VK_FUCHSIA_buffer_collection
+        case VK_STRUCTURE_TYPE_IMPORT_MEMORY_BUFFER_COLLECTION_FUCHSIA: {
+            return sizeof(VkImportMemoryBufferCollectionFUCHSIA);
+        }
+        case VK_STRUCTURE_TYPE_BUFFER_COLLECTION_IMAGE_CREATE_INFO_FUCHSIA: {
+            return sizeof(VkBufferCollectionImageCreateInfoFUCHSIA);
+        }
+        case VK_STRUCTURE_TYPE_BUFFER_COLLECTION_BUFFER_CREATE_INFO_FUCHSIA: {
+            return sizeof(VkBufferCollectionBufferCreateInfoFUCHSIA);
+        }
+#endif
+#ifdef VK_HUAWEI_subpass_shading
+        case VK_STRUCTURE_TYPE_SUBPASS_SHADING_PIPELINE_CREATE_INFO_HUAWEI: {
+            return sizeof(VkSubpassShadingPipelineCreateInfoHUAWEI);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBPASS_SHADING_FEATURES_HUAWEI: {
+            return sizeof(VkPhysicalDeviceSubpassShadingFeaturesHUAWEI);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBPASS_SHADING_PROPERTIES_HUAWEI: {
+            return sizeof(VkPhysicalDeviceSubpassShadingPropertiesHUAWEI);
+        }
+#endif
+#ifdef VK_HUAWEI_invocation_mask
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INVOCATION_MASK_FEATURES_HUAWEI: {
+            return sizeof(VkPhysicalDeviceInvocationMaskFeaturesHUAWEI);
+        }
+#endif
+#ifdef VK_NV_external_memory_rdma
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_RDMA_FEATURES_NV: {
+            return sizeof(VkPhysicalDeviceExternalMemoryRDMAFeaturesNV);
+        }
+#endif
+#ifdef VK_EXT_pipeline_properties
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_PROPERTIES_FEATURES_EXT: {
+            return sizeof(VkPhysicalDevicePipelinePropertiesFeaturesEXT);
+        }
+#endif
+#ifdef VK_EXT_frame_boundary
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAME_BOUNDARY_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceFrameBoundaryFeaturesEXT);
+        }
+        case VK_STRUCTURE_TYPE_FRAME_BOUNDARY_EXT: {
+            return sizeof(VkFrameBoundaryEXT);
+        }
+#endif
+#ifdef VK_EXT_multisampled_render_to_single_sampled
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceMultisampledRenderToSingleSampledFeaturesEXT);
+        }
+        case VK_STRUCTURE_TYPE_SUBPASS_RESOLVE_PERFORMANCE_QUERY_EXT: {
+            return sizeof(VkSubpassResolvePerformanceQueryEXT);
+        }
+        case VK_STRUCTURE_TYPE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_INFO_EXT: {
+            return sizeof(VkMultisampledRenderToSingleSampledInfoEXT);
+        }
+#endif
 #ifdef VK_EXT_extended_dynamic_state2
         case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_2_FEATURES_EXT: {
             return sizeof(VkPhysicalDeviceExtendedDynamicState2FeaturesEXT);
@@ -879,6 +1705,11 @@
             return sizeof(VkPipelineColorWriteCreateInfoEXT);
         }
 #endif
+#ifdef VK_EXT_primitives_generated_query
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIMITIVES_GENERATED_QUERY_FEATURES_EXT: {
+            return sizeof(VkPhysicalDevicePrimitivesGeneratedQueryFeaturesEXT);
+        }
+#endif
 #ifdef VK_GOOGLE_gfxstream
         case VK_STRUCTURE_TYPE_IMPORT_COLOR_BUFFER_GOOGLE: {
             return sizeof(VkImportColorBufferGOOGLE);
@@ -890,13 +1721,426 @@
             return sizeof(VkCreateBlobGOOGLE);
         }
 #endif
+#ifdef VK_EXT_image_view_min_lod
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_MIN_LOD_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceImageViewMinLodFeaturesEXT);
+        }
+        case VK_STRUCTURE_TYPE_IMAGE_VIEW_MIN_LOD_CREATE_INFO_EXT: {
+            return sizeof(VkImageViewMinLodCreateInfoEXT);
+        }
+#endif
+#ifdef VK_EXT_multi_draw
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTI_DRAW_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceMultiDrawFeaturesEXT);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTI_DRAW_PROPERTIES_EXT: {
+            return sizeof(VkPhysicalDeviceMultiDrawPropertiesEXT);
+        }
+#endif
+#ifdef VK_EXT_image_2d_view_of_3d
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_2D_VIEW_OF_3D_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceImage2DViewOf3DFeaturesEXT);
+        }
+#endif
+#ifdef VK_EXT_shader_tile_image
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_TILE_IMAGE_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceShaderTileImageFeaturesEXT);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_TILE_IMAGE_PROPERTIES_EXT: {
+            return sizeof(VkPhysicalDeviceShaderTileImagePropertiesEXT);
+        }
+#endif
+#ifdef VK_EXT_opacity_micromap
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_OPACITY_MICROMAP_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceOpacityMicromapFeaturesEXT);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_OPACITY_MICROMAP_PROPERTIES_EXT: {
+            return sizeof(VkPhysicalDeviceOpacityMicromapPropertiesEXT);
+        }
+        case VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_TRIANGLES_OPACITY_MICROMAP_EXT: {
+            return sizeof(VkAccelerationStructureTrianglesOpacityMicromapEXT);
+        }
+#endif
+#ifdef VK_NV_displacement_micromap
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DISPLACEMENT_MICROMAP_FEATURES_NV: {
+            return sizeof(VkPhysicalDeviceDisplacementMicromapFeaturesNV);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DISPLACEMENT_MICROMAP_PROPERTIES_NV: {
+            return sizeof(VkPhysicalDeviceDisplacementMicromapPropertiesNV);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_TRIANGLES_DISPLACEMENT_MICROMAP_NV: {
+            return sizeof(VkAccelerationStructureTrianglesDisplacementMicromapNV);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#endif
+#ifdef VK_HUAWEI_cluster_culling_shader
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CLUSTER_CULLING_SHADER_FEATURES_HUAWEI: {
+            return sizeof(VkPhysicalDeviceClusterCullingShaderFeaturesHUAWEI);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CLUSTER_CULLING_SHADER_PROPERTIES_HUAWEI: {
+            return sizeof(VkPhysicalDeviceClusterCullingShaderPropertiesHUAWEI);
+        }
+#endif
+#ifdef VK_EXT_border_color_swizzle
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BORDER_COLOR_SWIZZLE_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceBorderColorSwizzleFeaturesEXT);
+        }
+        case VK_STRUCTURE_TYPE_SAMPLER_BORDER_COLOR_COMPONENT_MAPPING_CREATE_INFO_EXT: {
+            return sizeof(VkSamplerBorderColorComponentMappingCreateInfoEXT);
+        }
+#endif
+#ifdef VK_EXT_pageable_device_local_memory
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PAGEABLE_DEVICE_LOCAL_MEMORY_FEATURES_EXT: {
+            return sizeof(VkPhysicalDevicePageableDeviceLocalMemoryFeaturesEXT);
+        }
+#endif
+#ifdef VK_ARM_shader_core_properties
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_ARM: {
+            return sizeof(VkPhysicalDeviceShaderCorePropertiesARM);
+        }
+#endif
+#ifdef VK_ARM_scheduling_controls
+        case VK_STRUCTURE_TYPE_DEVICE_QUEUE_SHADER_CORE_CONTROL_CREATE_INFO_ARM: {
+            return sizeof(VkDeviceQueueShaderCoreControlCreateInfoARM);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCHEDULING_CONTROLS_FEATURES_ARM: {
+            return sizeof(VkPhysicalDeviceSchedulingControlsFeaturesARM);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCHEDULING_CONTROLS_PROPERTIES_ARM: {
+            return sizeof(VkPhysicalDeviceSchedulingControlsPropertiesARM);
+        }
+#endif
+#ifdef VK_EXT_image_sliced_view_of_3d
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_SLICED_VIEW_OF_3D_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceImageSlicedViewOf3DFeaturesEXT);
+        }
+        case VK_STRUCTURE_TYPE_IMAGE_VIEW_SLICED_CREATE_INFO_EXT: {
+            return sizeof(VkImageViewSlicedCreateInfoEXT);
+        }
+#endif
+#ifdef VK_VALVE_descriptor_set_host_mapping
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_SET_HOST_MAPPING_FEATURES_VALVE: {
+            return sizeof(VkPhysicalDeviceDescriptorSetHostMappingFeaturesVALVE);
+        }
+#endif
+#ifdef VK_EXT_depth_clamp_zero_one
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLAMP_ZERO_ONE_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceDepthClampZeroOneFeaturesEXT);
+        }
+#endif
+#ifdef VK_EXT_non_seamless_cube_map
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_NON_SEAMLESS_CUBE_MAP_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceNonSeamlessCubeMapFeaturesEXT);
+        }
+#endif
+#ifdef VK_QCOM_fragment_density_map_offset
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_OFFSET_FEATURES_QCOM: {
+            return sizeof(VkPhysicalDeviceFragmentDensityMapOffsetFeaturesQCOM);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_OFFSET_PROPERTIES_QCOM: {
+            return sizeof(VkPhysicalDeviceFragmentDensityMapOffsetPropertiesQCOM);
+        }
+        case VK_STRUCTURE_TYPE_SUBPASS_FRAGMENT_DENSITY_MAP_OFFSET_END_INFO_QCOM: {
+            return sizeof(VkSubpassFragmentDensityMapOffsetEndInfoQCOM);
+        }
+#endif
+#ifdef VK_NV_copy_memory_indirect
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COPY_MEMORY_INDIRECT_FEATURES_NV: {
+            return sizeof(VkPhysicalDeviceCopyMemoryIndirectFeaturesNV);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COPY_MEMORY_INDIRECT_PROPERTIES_NV: {
+            return sizeof(VkPhysicalDeviceCopyMemoryIndirectPropertiesNV);
+        }
+#endif
+#ifdef VK_NV_memory_decompression
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_DECOMPRESSION_FEATURES_NV: {
+            return sizeof(VkPhysicalDeviceMemoryDecompressionFeaturesNV);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_DECOMPRESSION_PROPERTIES_NV: {
+            return sizeof(VkPhysicalDeviceMemoryDecompressionPropertiesNV);
+        }
+#endif
+#ifdef VK_NV_device_generated_commands_compute
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_COMPUTE_FEATURES_NV: {
+            return sizeof(VkPhysicalDeviceDeviceGeneratedCommandsComputeFeaturesNV);
+        }
+#endif
+#ifdef VK_NV_linear_color_attachment
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINEAR_COLOR_ATTACHMENT_FEATURES_NV: {
+            return sizeof(VkPhysicalDeviceLinearColorAttachmentFeaturesNV);
+        }
+#endif
 #ifdef VK_EXT_image_compression_control_swapchain
         case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN_FEATURES_EXT: {
             return sizeof(VkPhysicalDeviceImageCompressionControlSwapchainFeaturesEXT);
         }
 #endif
+#ifdef VK_QCOM_image_processing
+        case VK_STRUCTURE_TYPE_IMAGE_VIEW_SAMPLE_WEIGHT_CREATE_INFO_QCOM: {
+            return sizeof(VkImageViewSampleWeightCreateInfoQCOM);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_PROCESSING_FEATURES_QCOM: {
+            return sizeof(VkPhysicalDeviceImageProcessingFeaturesQCOM);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_PROCESSING_PROPERTIES_QCOM: {
+            return sizeof(VkPhysicalDeviceImageProcessingPropertiesQCOM);
+        }
+#endif
+#ifdef VK_EXT_nested_command_buffer
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_NESTED_COMMAND_BUFFER_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceNestedCommandBufferFeaturesEXT);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_NESTED_COMMAND_BUFFER_PROPERTIES_EXT: {
+            return sizeof(VkPhysicalDeviceNestedCommandBufferPropertiesEXT);
+        }
+#endif
+#ifdef VK_EXT_external_memory_acquire_unmodified
+        case VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_ACQUIRE_UNMODIFIED_EXT: {
+            return sizeof(VkExternalMemoryAcquireUnmodifiedEXT);
+        }
+#endif
+#ifdef VK_EXT_extended_dynamic_state3
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceExtendedDynamicState3FeaturesEXT);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_PROPERTIES_EXT: {
+            return sizeof(VkPhysicalDeviceExtendedDynamicState3PropertiesEXT);
+        }
+#endif
+#ifdef VK_EXT_subpass_merge_feedback
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBPASS_MERGE_FEEDBACK_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceSubpassMergeFeedbackFeaturesEXT);
+        }
+        case VK_STRUCTURE_TYPE_RENDER_PASS_CREATION_CONTROL_EXT: {
+            return sizeof(VkRenderPassCreationControlEXT);
+        }
+        case VK_STRUCTURE_TYPE_RENDER_PASS_CREATION_FEEDBACK_CREATE_INFO_EXT: {
+            return sizeof(VkRenderPassCreationFeedbackCreateInfoEXT);
+        }
+        case VK_STRUCTURE_TYPE_RENDER_PASS_SUBPASS_FEEDBACK_CREATE_INFO_EXT: {
+            return sizeof(VkRenderPassSubpassFeedbackCreateInfoEXT);
+        }
+#endif
+#ifdef VK_LUNARG_direct_driver_loading
+        case VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_LIST_LUNARG: {
+            return sizeof(VkDirectDriverLoadingListLUNARG);
+        }
+#endif
+#ifdef VK_EXT_shader_module_identifier
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_MODULE_IDENTIFIER_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceShaderModuleIdentifierFeaturesEXT);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_MODULE_IDENTIFIER_PROPERTIES_EXT: {
+            return sizeof(VkPhysicalDeviceShaderModuleIdentifierPropertiesEXT);
+        }
+        case VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_MODULE_IDENTIFIER_CREATE_INFO_EXT: {
+            return sizeof(VkPipelineShaderStageModuleIdentifierCreateInfoEXT);
+        }
+#endif
+#ifdef VK_NV_optical_flow
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_OPTICAL_FLOW_FEATURES_NV: {
+            return sizeof(VkPhysicalDeviceOpticalFlowFeaturesNV);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_OPTICAL_FLOW_PROPERTIES_NV: {
+            return sizeof(VkPhysicalDeviceOpticalFlowPropertiesNV);
+        }
+        case VK_STRUCTURE_TYPE_OPTICAL_FLOW_IMAGE_FORMAT_INFO_NV: {
+            return sizeof(VkOpticalFlowImageFormatInfoNV);
+        }
+        case VK_STRUCTURE_TYPE_OPTICAL_FLOW_SESSION_CREATE_PRIVATE_DATA_INFO_NV: {
+            return sizeof(VkOpticalFlowSessionCreatePrivateDataInfoNV);
+        }
+#endif
+#ifdef VK_EXT_legacy_dithering
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LEGACY_DITHERING_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceLegacyDitheringFeaturesEXT);
+        }
+#endif
+#ifdef VK_EXT_pipeline_protected_access
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_PROTECTED_ACCESS_FEATURES_EXT: {
+            return sizeof(VkPhysicalDevicePipelineProtectedAccessFeaturesEXT);
+        }
+#endif
+#ifdef VK_ANDROID_external_format_resolve
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FORMAT_RESOLVE_FEATURES_ANDROID: {
+            return sizeof(VkPhysicalDeviceExternalFormatResolveFeaturesANDROID);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FORMAT_RESOLVE_PROPERTIES_ANDROID: {
+            return sizeof(VkPhysicalDeviceExternalFormatResolvePropertiesANDROID);
+        }
+        case VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_RESOLVE_PROPERTIES_ANDROID: {
+            return sizeof(VkAndroidHardwareBufferFormatResolvePropertiesANDROID);
+        }
+#endif
+#ifdef VK_EXT_shader_object
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_OBJECT_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceShaderObjectFeaturesEXT);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_OBJECT_PROPERTIES_EXT: {
+            return sizeof(VkPhysicalDeviceShaderObjectPropertiesEXT);
+        }
+#endif
+#ifdef VK_QCOM_tile_properties
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TILE_PROPERTIES_FEATURES_QCOM: {
+            return sizeof(VkPhysicalDeviceTilePropertiesFeaturesQCOM);
+        }
+#endif
+#ifdef VK_SEC_amigo_profiling
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_AMIGO_PROFILING_FEATURES_SEC: {
+            return sizeof(VkPhysicalDeviceAmigoProfilingFeaturesSEC);
+        }
+        case VK_STRUCTURE_TYPE_AMIGO_PROFILING_SUBMIT_INFO_SEC: {
+            return sizeof(VkAmigoProfilingSubmitInfoSEC);
+        }
+#endif
+#ifdef VK_QCOM_multiview_per_view_viewports
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_VIEWPORTS_FEATURES_QCOM: {
+            return sizeof(VkPhysicalDeviceMultiviewPerViewViewportsFeaturesQCOM);
+        }
+#endif
+#ifdef VK_NV_ray_tracing_invocation_reorder
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_INVOCATION_REORDER_PROPERTIES_NV: {
+            return sizeof(VkPhysicalDeviceRayTracingInvocationReorderPropertiesNV);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_INVOCATION_REORDER_FEATURES_NV: {
+            return sizeof(VkPhysicalDeviceRayTracingInvocationReorderFeaturesNV);
+        }
+#endif
+#ifdef VK_NV_extended_sparse_address_space
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_SPARSE_ADDRESS_SPACE_FEATURES_NV: {
+            return sizeof(VkPhysicalDeviceExtendedSparseAddressSpaceFeaturesNV);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_SPARSE_ADDRESS_SPACE_PROPERTIES_NV: {
+            return sizeof(VkPhysicalDeviceExtendedSparseAddressSpacePropertiesNV);
+        }
+#endif
+#ifdef VK_ARM_shader_core_builtins
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_BUILTINS_FEATURES_ARM: {
+            return sizeof(VkPhysicalDeviceShaderCoreBuiltinsFeaturesARM);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_BUILTINS_PROPERTIES_ARM: {
+            return sizeof(VkPhysicalDeviceShaderCoreBuiltinsPropertiesARM);
+        }
+#endif
+#ifdef VK_EXT_pipeline_library_group_handles
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_LIBRARY_GROUP_HANDLES_FEATURES_EXT: {
+            return sizeof(VkPhysicalDevicePipelineLibraryGroupHandlesFeaturesEXT);
+        }
+#endif
+#ifdef VK_EXT_dynamic_rendering_unused_attachments
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_UNUSED_ATTACHMENTS_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceDynamicRenderingUnusedAttachmentsFeaturesEXT);
+        }
+#endif
+#ifdef VK_NV_low_latency2
+        case VK_STRUCTURE_TYPE_LATENCY_SUBMISSION_PRESENT_ID_NV: {
+            return sizeof(VkLatencySubmissionPresentIdNV);
+        }
+        case VK_STRUCTURE_TYPE_SWAPCHAIN_LATENCY_CREATE_INFO_NV: {
+            return sizeof(VkSwapchainLatencyCreateInfoNV);
+        }
+        case VK_STRUCTURE_TYPE_LATENCY_SURFACE_CAPABILITIES_NV: {
+            return sizeof(VkLatencySurfaceCapabilitiesNV);
+        }
+#endif
+#ifdef VK_QCOM_multiview_per_view_render_areas
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_RENDER_AREAS_FEATURES_QCOM: {
+            return sizeof(VkPhysicalDeviceMultiviewPerViewRenderAreasFeaturesQCOM);
+        }
+        case VK_STRUCTURE_TYPE_MULTIVIEW_PER_VIEW_RENDER_AREAS_RENDER_PASS_BEGIN_INFO_QCOM: {
+            return sizeof(VkMultiviewPerViewRenderAreasRenderPassBeginInfoQCOM);
+        }
+#endif
+#ifdef VK_QCOM_image_processing2
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_PROCESSING_2_FEATURES_QCOM: {
+            return sizeof(VkPhysicalDeviceImageProcessing2FeaturesQCOM);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_PROCESSING_2_PROPERTIES_QCOM: {
+            return sizeof(VkPhysicalDeviceImageProcessing2PropertiesQCOM);
+        }
+        case VK_STRUCTURE_TYPE_SAMPLER_BLOCK_MATCH_WINDOW_CREATE_INFO_QCOM: {
+            return sizeof(VkSamplerBlockMatchWindowCreateInfoQCOM);
+        }
+#endif
+#ifdef VK_QCOM_filter_cubic_weights
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUBIC_WEIGHTS_FEATURES_QCOM: {
+            return sizeof(VkPhysicalDeviceCubicWeightsFeaturesQCOM);
+        }
+        case VK_STRUCTURE_TYPE_SAMPLER_CUBIC_WEIGHTS_CREATE_INFO_QCOM: {
+            return sizeof(VkSamplerCubicWeightsCreateInfoQCOM);
+        }
+        case VK_STRUCTURE_TYPE_BLIT_IMAGE_CUBIC_WEIGHTS_INFO_QCOM: {
+            return sizeof(VkBlitImageCubicWeightsInfoQCOM);
+        }
+#endif
+#ifdef VK_QCOM_ycbcr_degamma
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_YCBCR_DEGAMMA_FEATURES_QCOM: {
+            return sizeof(VkPhysicalDeviceYcbcrDegammaFeaturesQCOM);
+        }
+        case VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_YCBCR_DEGAMMA_CREATE_INFO_QCOM: {
+            return sizeof(VkSamplerYcbcrConversionYcbcrDegammaCreateInfoQCOM);
+        }
+#endif
+#ifdef VK_QCOM_filter_cubic_clamp
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUBIC_CLAMP_FEATURES_QCOM: {
+            return sizeof(VkPhysicalDeviceCubicClampFeaturesQCOM);
+        }
+#endif
+#ifdef VK_EXT_attachment_feedback_loop_dynamic_state
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ATTACHMENT_FEEDBACK_LOOP_DYNAMIC_STATE_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesEXT);
+        }
+#endif
+#ifdef VK_MSFT_layered_driver
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LAYERED_DRIVER_PROPERTIES_MSFT: {
+            return sizeof(VkPhysicalDeviceLayeredDriverPropertiesMSFT);
+        }
+#endif
+#ifdef VK_NV_descriptor_pool_overallocation
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_POOL_OVERALLOCATION_FEATURES_NV: {
+            return sizeof(VkPhysicalDeviceDescriptorPoolOverallocationFeaturesNV);
+        }
+#endif
+#ifdef VK_KHR_acceleration_structure
+        case VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR: {
+            return sizeof(VkWriteDescriptorSetAccelerationStructureKHR);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR: {
+            return sizeof(VkPhysicalDeviceAccelerationStructureFeaturesKHR);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_PROPERTIES_KHR: {
+            return sizeof(VkPhysicalDeviceAccelerationStructurePropertiesKHR);
+        }
+#endif
+#ifdef VK_KHR_ray_tracing_pipeline
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR: {
+            return sizeof(VkPhysicalDeviceRayTracingPipelineFeaturesKHR);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR: {
+            return sizeof(VkPhysicalDeviceRayTracingPipelinePropertiesKHR);
+        }
+#endif
+#ifdef VK_KHR_ray_query
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_QUERY_FEATURES_KHR: {
+            return sizeof(VkPhysicalDeviceRayQueryFeaturesKHR);
+        }
+#endif
+#ifdef VK_EXT_mesh_shader
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceMeshShaderFeaturesEXT);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_PROPERTIES_EXT: {
+            return sizeof(VkPhysicalDeviceMeshShaderPropertiesEXT);
+        }
+#endif
         default: {
-            fprintf(stderr, "Unhandled Vulkan structure type %d, aborting.\n", structType);
+            fprintf(stderr, "Unhandled Vulkan structure type %s [%d], aborting.\n",
+                    string_VkStructureType(VkStructureType(structType)), structType);
             GFXSTREAM_ABORT(::emugl::FatalError(::emugl::ABORT_REASON_OTHER));
             return (size_t)0;
         }
@@ -1258,6 +2502,53 @@
             return sizeof(VkDeviceGroupSwapchainCreateInfoKHR);
         }
 #endif
+#ifdef VK_KHR_display_swapchain
+        case VK_STRUCTURE_TYPE_DISPLAY_PRESENT_INFO_KHR: {
+            return sizeof(VkDisplayPresentInfoKHR);
+        }
+#endif
+#ifdef VK_KHR_video_queue
+        case VK_STRUCTURE_TYPE_QUEUE_FAMILY_QUERY_RESULT_STATUS_PROPERTIES_KHR: {
+            return sizeof(VkQueueFamilyQueryResultStatusPropertiesKHR);
+        }
+        case VK_STRUCTURE_TYPE_QUEUE_FAMILY_VIDEO_PROPERTIES_KHR: {
+            return sizeof(VkQueueFamilyVideoPropertiesKHR);
+        }
+        case VK_STRUCTURE_TYPE_VIDEO_PROFILE_INFO_KHR: {
+            return sizeof(VkVideoProfileInfoKHR);
+        }
+        case VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR: {
+            return sizeof(VkVideoProfileListInfoKHR);
+        }
+#endif
+#ifdef VK_KHR_video_decode_queue
+        case VK_STRUCTURE_TYPE_VIDEO_DECODE_CAPABILITIES_KHR: {
+            return sizeof(VkVideoDecodeCapabilitiesKHR);
+        }
+        case VK_STRUCTURE_TYPE_VIDEO_DECODE_USAGE_INFO_KHR: {
+            return sizeof(VkVideoDecodeUsageInfoKHR);
+        }
+#endif
+#ifdef VK_KHR_video_decode_h264
+        case VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PROFILE_INFO_KHR: {
+            return sizeof(VkVideoDecodeH264ProfileInfoKHR);
+        }
+        case VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_CAPABILITIES_KHR: {
+            return sizeof(VkVideoDecodeH264CapabilitiesKHR);
+        }
+        case VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_ADD_INFO_KHR: {
+            return sizeof(VkVideoDecodeH264SessionParametersAddInfoKHR);
+        }
+        case VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_CREATE_INFO_KHR: {
+            return sizeof(VkVideoDecodeH264SessionParametersCreateInfoKHR);
+        }
+        case VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PICTURE_INFO_KHR: {
+            return sizeof(VkVideoDecodeH264PictureInfoKHR);
+        }
+        case VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_DPB_SLOT_INFO_KHR: {
+            return sizeof(VkVideoDecodeH264DpbSlotInfoKHR);
+        }
+#endif
 #ifdef VK_KHR_dynamic_rendering
         case VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR: {
             return sizeof(VkRenderingFragmentShadingRateAttachmentInfoKHR);
@@ -1272,21 +2563,190 @@
             return sizeof(VkMultiviewPerViewAttributesInfoNVX);
         }
 #endif
+#ifdef VK_KHR_win32_keyed_mutex
+        case VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_KHR: {
+            return sizeof(VkWin32KeyedMutexAcquireReleaseInfoKHR);
+        }
+#endif
+#ifdef VK_KHR_push_descriptor
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR: {
+            return sizeof(VkPhysicalDevicePushDescriptorPropertiesKHR);
+        }
+#endif
 #ifdef VK_KHR_incremental_present
         case VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR: {
             return sizeof(VkPresentRegionsKHR);
         }
 #endif
+#ifdef VK_KHR_shared_presentable_image
+        case VK_STRUCTURE_TYPE_SHARED_PRESENT_SURFACE_CAPABILITIES_KHR: {
+            return sizeof(VkSharedPresentSurfaceCapabilitiesKHR);
+        }
+#endif
+#ifdef VK_KHR_external_fence_win32
+        case VK_STRUCTURE_TYPE_EXPORT_FENCE_WIN32_HANDLE_INFO_KHR: {
+            return sizeof(VkExportFenceWin32HandleInfoKHR);
+        }
+#endif
+#ifdef VK_KHR_performance_query
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_FEATURES_KHR: {
+            return sizeof(VkPhysicalDevicePerformanceQueryFeaturesKHR);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_PROPERTIES_KHR: {
+            return sizeof(VkPhysicalDevicePerformanceQueryPropertiesKHR);
+        }
+        case VK_STRUCTURE_TYPE_QUERY_POOL_PERFORMANCE_CREATE_INFO_KHR: {
+            return sizeof(VkQueryPoolPerformanceCreateInfoKHR);
+        }
+        case VK_STRUCTURE_TYPE_PERFORMANCE_QUERY_SUBMIT_INFO_KHR: {
+            return sizeof(VkPerformanceQuerySubmitInfoKHR);
+        }
+#endif
+#ifdef VK_KHR_portability_subset
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_FEATURES_KHR: {
+            return sizeof(VkPhysicalDevicePortabilitySubsetFeaturesKHR);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_PROPERTIES_KHR: {
+            return sizeof(VkPhysicalDevicePortabilitySubsetPropertiesKHR);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#endif
+#ifdef VK_KHR_shader_clock
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CLOCK_FEATURES_KHR: {
+            return sizeof(VkPhysicalDeviceShaderClockFeaturesKHR);
+        }
+#endif
+#ifdef VK_KHR_video_decode_h265
+        case VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PROFILE_INFO_KHR: {
+            return sizeof(VkVideoDecodeH265ProfileInfoKHR);
+        }
+        case VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_CAPABILITIES_KHR: {
+            return sizeof(VkVideoDecodeH265CapabilitiesKHR);
+        }
+        case VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_ADD_INFO_KHR: {
+            return sizeof(VkVideoDecodeH265SessionParametersAddInfoKHR);
+        }
+        case VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_CREATE_INFO_KHR: {
+            return sizeof(VkVideoDecodeH265SessionParametersCreateInfoKHR);
+        }
+        case VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PICTURE_INFO_KHR: {
+            return sizeof(VkVideoDecodeH265PictureInfoKHR);
+        }
+        case VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_DPB_SLOT_INFO_KHR: {
+            return sizeof(VkVideoDecodeH265DpbSlotInfoKHR);
+        }
+#endif
+#ifdef VK_KHR_global_priority
+        case VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_KHR: {
+            return sizeof(VkDeviceQueueGlobalPriorityCreateInfoKHR);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GLOBAL_PRIORITY_QUERY_FEATURES_KHR: {
+            return sizeof(VkPhysicalDeviceGlobalPriorityQueryFeaturesKHR);
+        }
+        case VK_STRUCTURE_TYPE_QUEUE_FAMILY_GLOBAL_PRIORITY_PROPERTIES_KHR: {
+            return sizeof(VkQueueFamilyGlobalPriorityPropertiesKHR);
+        }
+#endif
+#ifdef VK_KHR_fragment_shading_rate
+        case VK_STRUCTURE_TYPE_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR: {
+            return sizeof(VkFragmentShadingRateAttachmentInfoKHR);
+        }
+        case VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_STATE_CREATE_INFO_KHR: {
+            return sizeof(VkPipelineFragmentShadingRateStateCreateInfoKHR);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR: {
+            return sizeof(VkPhysicalDeviceFragmentShadingRateFeaturesKHR);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_PROPERTIES_KHR: {
+            return sizeof(VkPhysicalDeviceFragmentShadingRatePropertiesKHR);
+        }
+#endif
+#ifdef VK_KHR_surface_protected_capabilities
+        case VK_STRUCTURE_TYPE_SURFACE_PROTECTED_CAPABILITIES_KHR: {
+            return sizeof(VkSurfaceProtectedCapabilitiesKHR);
+        }
+#endif
+#ifdef VK_KHR_present_wait
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_WAIT_FEATURES_KHR: {
+            return sizeof(VkPhysicalDevicePresentWaitFeaturesKHR);
+        }
+#endif
 #ifdef VK_KHR_pipeline_executable_properties
         case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_EXECUTABLE_PROPERTIES_FEATURES_KHR: {
             return sizeof(VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR);
         }
 #endif
+#ifdef VK_KHR_pipeline_library
+        case VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR: {
+            return sizeof(VkPipelineLibraryCreateInfoKHR);
+        }
+#endif
+#ifdef VK_KHR_present_id
+        case VK_STRUCTURE_TYPE_PRESENT_ID_KHR: {
+            return sizeof(VkPresentIdKHR);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_ID_FEATURES_KHR: {
+            return sizeof(VkPhysicalDevicePresentIdFeaturesKHR);
+        }
+#endif
+#ifdef VK_KHR_video_encode_queue
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_CAPABILITIES_KHR: {
+            return sizeof(VkVideoEncodeCapabilitiesKHR);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_QUERY_POOL_VIDEO_ENCODE_FEEDBACK_CREATE_INFO_KHR: {
+            return sizeof(VkQueryPoolVideoEncodeFeedbackCreateInfoKHR);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_USAGE_INFO_KHR: {
+            return sizeof(VkVideoEncodeUsageInfoKHR);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_RATE_CONTROL_INFO_KHR: {
+            return sizeof(VkVideoEncodeRateControlInfoKHR);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_QUALITY_LEVEL_INFO_KHR: {
+            return sizeof(VkVideoEncodeQualityLevelInfoKHR);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#endif
 #ifdef VK_KHR_synchronization2
         case VK_STRUCTURE_TYPE_QUEUE_FAMILY_CHECKPOINT_PROPERTIES_2_NV: {
             return sizeof(VkQueueFamilyCheckpointProperties2NV);
         }
 #endif
+#ifdef VK_KHR_fragment_shader_barycentric
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_FEATURES_KHR: {
+            return sizeof(VkPhysicalDeviceFragmentShaderBarycentricFeaturesKHR);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_PROPERTIES_KHR: {
+            return sizeof(VkPhysicalDeviceFragmentShaderBarycentricPropertiesKHR);
+        }
+#endif
+#ifdef VK_KHR_shader_subgroup_uniform_control_flow
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_UNIFORM_CONTROL_FLOW_FEATURES_KHR: {
+            return sizeof(VkPhysicalDeviceShaderSubgroupUniformControlFlowFeaturesKHR);
+        }
+#endif
+#ifdef VK_KHR_workgroup_memory_explicit_layout
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_FEATURES_KHR: {
+            return sizeof(VkPhysicalDeviceWorkgroupMemoryExplicitLayoutFeaturesKHR);
+        }
+#endif
+#ifdef VK_KHR_ray_tracing_maintenance1
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_MAINTENANCE_1_FEATURES_KHR: {
+            return sizeof(VkPhysicalDeviceRayTracingMaintenance1FeaturesKHR);
+        }
+#endif
 #ifdef VK_KHR_maintenance5
         case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_5_FEATURES_KHR: {
             return sizeof(VkPhysicalDeviceMaintenance5FeaturesKHR);
@@ -1301,6 +2761,19 @@
             return sizeof(VkBufferUsageFlags2CreateInfoKHR);
         }
 #endif
+#ifdef VK_KHR_ray_tracing_position_fetch
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_POSITION_FETCH_FEATURES_KHR: {
+            return sizeof(VkPhysicalDeviceRayTracingPositionFetchFeaturesKHR);
+        }
+#endif
+#ifdef VK_KHR_cooperative_matrix
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_FEATURES_KHR: {
+            return sizeof(VkPhysicalDeviceCooperativeMatrixFeaturesKHR);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_PROPERTIES_KHR: {
+            return sizeof(VkPhysicalDeviceCooperativeMatrixPropertiesKHR);
+        }
+#endif
 #ifdef VK_ANDROID_native_buffer
         case VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID: {
             return sizeof(VkNativeBufferANDROID);
@@ -1311,6 +2784,22 @@
             return sizeof(VkDebugReportCallbackCreateInfoEXT);
         }
 #endif
+#ifdef VK_AMD_rasterization_order
+        case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_RASTERIZATION_ORDER_AMD: {
+            return sizeof(VkPipelineRasterizationStateRasterizationOrderAMD);
+        }
+#endif
+#ifdef VK_NV_dedicated_allocation
+        case VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_IMAGE_CREATE_INFO_NV: {
+            return sizeof(VkDedicatedAllocationImageCreateInfoNV);
+        }
+        case VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_BUFFER_CREATE_INFO_NV: {
+            return sizeof(VkDedicatedAllocationBufferCreateInfoNV);
+        }
+        case VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV: {
+            return sizeof(VkDedicatedAllocationMemoryAllocateInfoNV);
+        }
+#endif
 #ifdef VK_EXT_transform_feedback
         case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT: {
             return sizeof(VkPhysicalDeviceTransformFeedbackFeaturesEXT);
@@ -1322,6 +2811,244 @@
             return sizeof(VkPipelineRasterizationStateStreamCreateInfoEXT);
         }
 #endif
+#ifdef VK_EXT_video_encode_h264
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_CAPABILITIES_EXT: {
+            return sizeof(VkVideoEncodeH264CapabilitiesEXT);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_QUALITY_LEVEL_PROPERTIES_EXT: {
+            return sizeof(VkVideoEncodeH264QualityLevelPropertiesEXT);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_CREATE_INFO_EXT: {
+            return sizeof(VkVideoEncodeH264SessionCreateInfoEXT);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_PARAMETERS_ADD_INFO_EXT: {
+            return sizeof(VkVideoEncodeH264SessionParametersAddInfoEXT);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_PARAMETERS_CREATE_INFO_EXT: {
+            return sizeof(VkVideoEncodeH264SessionParametersCreateInfoEXT);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_PARAMETERS_GET_INFO_EXT: {
+            return sizeof(VkVideoEncodeH264SessionParametersGetInfoEXT);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_PARAMETERS_FEEDBACK_INFO_EXT: {
+            return sizeof(VkVideoEncodeH264SessionParametersFeedbackInfoEXT);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_PICTURE_INFO_EXT: {
+            return sizeof(VkVideoEncodeH264PictureInfoEXT);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_DPB_SLOT_INFO_EXT: {
+            return sizeof(VkVideoEncodeH264DpbSlotInfoEXT);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_PROFILE_INFO_EXT: {
+            return sizeof(VkVideoEncodeH264ProfileInfoEXT);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_RATE_CONTROL_INFO_EXT: {
+            return sizeof(VkVideoEncodeH264RateControlInfoEXT);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_RATE_CONTROL_LAYER_INFO_EXT: {
+            return sizeof(VkVideoEncodeH264RateControlLayerInfoEXT);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_GOP_REMAINING_FRAME_INFO_EXT: {
+            return sizeof(VkVideoEncodeH264GopRemainingFrameInfoEXT);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#endif
+#ifdef VK_EXT_video_encode_h265
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_CAPABILITIES_EXT: {
+            return sizeof(VkVideoEncodeH265CapabilitiesEXT);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_CREATE_INFO_EXT: {
+            return sizeof(VkVideoEncodeH265SessionCreateInfoEXT);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_QUALITY_LEVEL_PROPERTIES_EXT: {
+            return sizeof(VkVideoEncodeH265QualityLevelPropertiesEXT);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_PARAMETERS_ADD_INFO_EXT: {
+            return sizeof(VkVideoEncodeH265SessionParametersAddInfoEXT);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_PARAMETERS_CREATE_INFO_EXT: {
+            return sizeof(VkVideoEncodeH265SessionParametersCreateInfoEXT);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_PARAMETERS_GET_INFO_EXT: {
+            return sizeof(VkVideoEncodeH265SessionParametersGetInfoEXT);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_PARAMETERS_FEEDBACK_INFO_EXT: {
+            return sizeof(VkVideoEncodeH265SessionParametersFeedbackInfoEXT);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_PICTURE_INFO_EXT: {
+            return sizeof(VkVideoEncodeH265PictureInfoEXT);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_DPB_SLOT_INFO_EXT: {
+            return sizeof(VkVideoEncodeH265DpbSlotInfoEXT);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_PROFILE_INFO_EXT: {
+            return sizeof(VkVideoEncodeH265ProfileInfoEXT);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_RATE_CONTROL_INFO_EXT: {
+            return sizeof(VkVideoEncodeH265RateControlInfoEXT);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_RATE_CONTROL_LAYER_INFO_EXT: {
+            return sizeof(VkVideoEncodeH265RateControlLayerInfoEXT);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_GOP_REMAINING_FRAME_INFO_EXT: {
+            return sizeof(VkVideoEncodeH265GopRemainingFrameInfoEXT);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#endif
+#ifdef VK_AMD_texture_gather_bias_lod
+        case VK_STRUCTURE_TYPE_TEXTURE_LOD_GATHER_FORMAT_PROPERTIES_AMD: {
+            return sizeof(VkTextureLODGatherFormatPropertiesAMD);
+        }
+#endif
+#ifdef VK_NV_corner_sampled_image
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CORNER_SAMPLED_IMAGE_FEATURES_NV: {
+            return sizeof(VkPhysicalDeviceCornerSampledImageFeaturesNV);
+        }
+#endif
+#ifdef VK_NV_external_memory
+        case VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_NV: {
+            return sizeof(VkExternalMemoryImageCreateInfoNV);
+        }
+        case VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_NV: {
+            return sizeof(VkExportMemoryAllocateInfoNV);
+        }
+#endif
+#ifdef VK_NV_external_memory_win32
+        case VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_NV: {
+            return sizeof(VkImportMemoryWin32HandleInfoNV);
+        }
+        case VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_NV: {
+            return sizeof(VkExportMemoryWin32HandleInfoNV);
+        }
+#endif
+#ifdef VK_NV_win32_keyed_mutex
+        case VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_NV: {
+            return sizeof(VkWin32KeyedMutexAcquireReleaseInfoNV);
+        }
+#endif
+#ifdef VK_EXT_validation_flags
+        case VK_STRUCTURE_TYPE_VALIDATION_FLAGS_EXT: {
+            return sizeof(VkValidationFlagsEXT);
+        }
+#endif
+#ifdef VK_EXT_astc_decode_mode
+        case VK_STRUCTURE_TYPE_IMAGE_VIEW_ASTC_DECODE_MODE_EXT: {
+            return sizeof(VkImageViewASTCDecodeModeEXT);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ASTC_DECODE_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceASTCDecodeFeaturesEXT);
+        }
+#endif
+#ifdef VK_EXT_pipeline_robustness
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_ROBUSTNESS_FEATURES_EXT: {
+            return sizeof(VkPhysicalDevicePipelineRobustnessFeaturesEXT);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_ROBUSTNESS_PROPERTIES_EXT: {
+            return sizeof(VkPhysicalDevicePipelineRobustnessPropertiesEXT);
+        }
+        case VK_STRUCTURE_TYPE_PIPELINE_ROBUSTNESS_CREATE_INFO_EXT: {
+            return sizeof(VkPipelineRobustnessCreateInfoEXT);
+        }
+#endif
+#ifdef VK_EXT_conditional_rendering
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONDITIONAL_RENDERING_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceConditionalRenderingFeaturesEXT);
+        }
+        case VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_CONDITIONAL_RENDERING_INFO_EXT: {
+            return sizeof(VkCommandBufferInheritanceConditionalRenderingInfoEXT);
+        }
+#endif
+#ifdef VK_NV_clip_space_w_scaling
+        case VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_W_SCALING_STATE_CREATE_INFO_NV: {
+            return sizeof(VkPipelineViewportWScalingStateCreateInfoNV);
+        }
+#endif
+#ifdef VK_EXT_display_control
+        case VK_STRUCTURE_TYPE_SWAPCHAIN_COUNTER_CREATE_INFO_EXT: {
+            return sizeof(VkSwapchainCounterCreateInfoEXT);
+        }
+#endif
+#ifdef VK_GOOGLE_display_timing
+        case VK_STRUCTURE_TYPE_PRESENT_TIMES_INFO_GOOGLE: {
+            return sizeof(VkPresentTimesInfoGOOGLE);
+        }
+#endif
+#ifdef VK_NVX_multiview_per_view_attributes
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_ATTRIBUTES_PROPERTIES_NVX: {
+            return sizeof(VkPhysicalDeviceMultiviewPerViewAttributesPropertiesNVX);
+        }
+#endif
+#ifdef VK_NV_viewport_swizzle
+        case VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SWIZZLE_STATE_CREATE_INFO_NV: {
+            return sizeof(VkPipelineViewportSwizzleStateCreateInfoNV);
+        }
+#endif
+#ifdef VK_EXT_discard_rectangles
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DISCARD_RECTANGLE_PROPERTIES_EXT: {
+            return sizeof(VkPhysicalDeviceDiscardRectanglePropertiesEXT);
+        }
+        case VK_STRUCTURE_TYPE_PIPELINE_DISCARD_RECTANGLE_STATE_CREATE_INFO_EXT: {
+            return sizeof(VkPipelineDiscardRectangleStateCreateInfoEXT);
+        }
+#endif
+#ifdef VK_EXT_conservative_rasterization
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONSERVATIVE_RASTERIZATION_PROPERTIES_EXT: {
+            return sizeof(VkPhysicalDeviceConservativeRasterizationPropertiesEXT);
+        }
+        case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_CONSERVATIVE_STATE_CREATE_INFO_EXT: {
+            return sizeof(VkPipelineRasterizationConservativeStateCreateInfoEXT);
+        }
+#endif
 #ifdef VK_EXT_depth_clip_enable
         case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_ENABLE_FEATURES_EXT: {
             return sizeof(VkPhysicalDeviceDepthClipEnableFeaturesEXT);
@@ -1338,6 +3065,149 @@
             return sizeof(VkDebugUtilsMessengerCreateInfoEXT);
         }
 #endif
+#ifdef VK_AMDX_shader_enqueue
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ENQUEUE_FEATURES_AMDX: {
+            return sizeof(VkPhysicalDeviceShaderEnqueueFeaturesAMDX);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ENQUEUE_PROPERTIES_AMDX: {
+            return sizeof(VkPhysicalDeviceShaderEnqueuePropertiesAMDX);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_NODE_CREATE_INFO_AMDX: {
+            return sizeof(VkPipelineShaderStageNodeCreateInfoAMDX);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#endif
+#ifdef VK_EXT_sample_locations
+        case VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT: {
+            return sizeof(VkSampleLocationsInfoEXT);
+        }
+        case VK_STRUCTURE_TYPE_RENDER_PASS_SAMPLE_LOCATIONS_BEGIN_INFO_EXT: {
+            return sizeof(VkRenderPassSampleLocationsBeginInfoEXT);
+        }
+        case VK_STRUCTURE_TYPE_PIPELINE_SAMPLE_LOCATIONS_STATE_CREATE_INFO_EXT: {
+            return sizeof(VkPipelineSampleLocationsStateCreateInfoEXT);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLE_LOCATIONS_PROPERTIES_EXT: {
+            return sizeof(VkPhysicalDeviceSampleLocationsPropertiesEXT);
+        }
+#endif
+#ifdef VK_EXT_blend_operation_advanced
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_PROPERTIES_EXT: {
+            return sizeof(VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT);
+        }
+        case VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_ADVANCED_STATE_CREATE_INFO_EXT: {
+            return sizeof(VkPipelineColorBlendAdvancedStateCreateInfoEXT);
+        }
+#endif
+#ifdef VK_NV_fragment_coverage_to_color
+        case VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_TO_COLOR_STATE_CREATE_INFO_NV: {
+            return sizeof(VkPipelineCoverageToColorStateCreateInfoNV);
+        }
+#endif
+#ifdef VK_NV_framebuffer_mixed_samples
+        case VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_MODULATION_STATE_CREATE_INFO_NV: {
+            return sizeof(VkPipelineCoverageModulationStateCreateInfoNV);
+        }
+#endif
+#ifdef VK_NV_shader_sm_builtins
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SM_BUILTINS_PROPERTIES_NV: {
+            return sizeof(VkPhysicalDeviceShaderSMBuiltinsPropertiesNV);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SM_BUILTINS_FEATURES_NV: {
+            return sizeof(VkPhysicalDeviceShaderSMBuiltinsFeaturesNV);
+        }
+#endif
+#ifdef VK_EXT_image_drm_format_modifier
+        case VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT: {
+            return sizeof(VkDrmFormatModifierPropertiesListEXT);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT: {
+            return sizeof(VkPhysicalDeviceImageDrmFormatModifierInfoEXT);
+        }
+        case VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT: {
+            return sizeof(VkImageDrmFormatModifierListCreateInfoEXT);
+        }
+        case VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT: {
+            return sizeof(VkImageDrmFormatModifierExplicitCreateInfoEXT);
+        }
+        case VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_2_EXT: {
+            return sizeof(VkDrmFormatModifierPropertiesList2EXT);
+        }
+#endif
+#ifdef VK_EXT_validation_cache
+        case VK_STRUCTURE_TYPE_SHADER_MODULE_VALIDATION_CACHE_CREATE_INFO_EXT: {
+            return sizeof(VkShaderModuleValidationCacheCreateInfoEXT);
+        }
+#endif
+#ifdef VK_NV_shading_rate_image
+        case VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SHADING_RATE_IMAGE_STATE_CREATE_INFO_NV: {
+            return sizeof(VkPipelineViewportShadingRateImageStateCreateInfoNV);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_FEATURES_NV: {
+            return sizeof(VkPhysicalDeviceShadingRateImageFeaturesNV);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_PROPERTIES_NV: {
+            return sizeof(VkPhysicalDeviceShadingRateImagePropertiesNV);
+        }
+        case VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_COARSE_SAMPLE_ORDER_STATE_CREATE_INFO_NV: {
+            return sizeof(VkPipelineViewportCoarseSampleOrderStateCreateInfoNV);
+        }
+#endif
+#ifdef VK_NV_ray_tracing
+        case VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_NV: {
+            return sizeof(VkWriteDescriptorSetAccelerationStructureNV);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_NV: {
+            return sizeof(VkPhysicalDeviceRayTracingPropertiesNV);
+        }
+#endif
+#ifdef VK_NV_representative_fragment_test
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_REPRESENTATIVE_FRAGMENT_TEST_FEATURES_NV: {
+            return sizeof(VkPhysicalDeviceRepresentativeFragmentTestFeaturesNV);
+        }
+        case VK_STRUCTURE_TYPE_PIPELINE_REPRESENTATIVE_FRAGMENT_TEST_STATE_CREATE_INFO_NV: {
+            return sizeof(VkPipelineRepresentativeFragmentTestStateCreateInfoNV);
+        }
+#endif
+#ifdef VK_EXT_filter_cubic
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_IMAGE_FORMAT_INFO_EXT: {
+            return sizeof(VkPhysicalDeviceImageViewImageFormatInfoEXT);
+        }
+        case VK_STRUCTURE_TYPE_FILTER_CUBIC_IMAGE_VIEW_IMAGE_FORMAT_PROPERTIES_EXT: {
+            return sizeof(VkFilterCubicImageViewImageFormatPropertiesEXT);
+        }
+#endif
+#ifdef VK_EXT_external_memory_host
+        case VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT: {
+            return sizeof(VkImportMemoryHostPointerInfoEXT);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT: {
+            return sizeof(VkPhysicalDeviceExternalMemoryHostPropertiesEXT);
+        }
+#endif
+#ifdef VK_AMD_pipeline_compiler_control
+        case VK_STRUCTURE_TYPE_PIPELINE_COMPILER_CONTROL_CREATE_INFO_AMD: {
+            return sizeof(VkPipelineCompilerControlCreateInfoAMD);
+        }
+#endif
+#ifdef VK_AMD_shader_core_properties
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_AMD: {
+            return sizeof(VkPhysicalDeviceShaderCorePropertiesAMD);
+        }
+#endif
+#ifdef VK_AMD_memory_overallocation_behavior
+        case VK_STRUCTURE_TYPE_DEVICE_MEMORY_OVERALLOCATION_CREATE_INFO_AMD: {
+            return sizeof(VkDeviceMemoryOverallocationCreateInfoAMD);
+        }
+#endif
 #ifdef VK_EXT_vertex_attribute_divisor
         case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT: {
             return sizeof(VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT);
@@ -1349,6 +3219,60 @@
             return sizeof(VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT);
         }
 #endif
+#ifdef VK_GGP_frame_token
+        case VK_STRUCTURE_TYPE_PRESENT_FRAME_TOKEN_GGP: {
+            return sizeof(VkPresentFrameTokenGGP);
+        }
+#endif
+#ifdef VK_NV_compute_shader_derivatives
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COMPUTE_SHADER_DERIVATIVES_FEATURES_NV: {
+            return sizeof(VkPhysicalDeviceComputeShaderDerivativesFeaturesNV);
+        }
+#endif
+#ifdef VK_NV_mesh_shader
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_NV: {
+            return sizeof(VkPhysicalDeviceMeshShaderFeaturesNV);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_PROPERTIES_NV: {
+            return sizeof(VkPhysicalDeviceMeshShaderPropertiesNV);
+        }
+#endif
+#ifdef VK_NV_shader_image_footprint
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_IMAGE_FOOTPRINT_FEATURES_NV: {
+            return sizeof(VkPhysicalDeviceShaderImageFootprintFeaturesNV);
+        }
+#endif
+#ifdef VK_NV_scissor_exclusive
+        case VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_EXCLUSIVE_SCISSOR_STATE_CREATE_INFO_NV: {
+            return sizeof(VkPipelineViewportExclusiveScissorStateCreateInfoNV);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXCLUSIVE_SCISSOR_FEATURES_NV: {
+            return sizeof(VkPhysicalDeviceExclusiveScissorFeaturesNV);
+        }
+#endif
+#ifdef VK_INTEL_shader_integer_functions2
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_FUNCTIONS_2_FEATURES_INTEL: {
+            return sizeof(VkPhysicalDeviceShaderIntegerFunctions2FeaturesINTEL);
+        }
+#endif
+#ifdef VK_INTEL_performance_query
+        case VK_STRUCTURE_TYPE_QUERY_POOL_PERFORMANCE_QUERY_CREATE_INFO_INTEL: {
+            return sizeof(VkQueryPoolPerformanceQueryCreateInfoINTEL);
+        }
+#endif
+#ifdef VK_EXT_pci_bus_info
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PCI_BUS_INFO_PROPERTIES_EXT: {
+            return sizeof(VkPhysicalDevicePCIBusInfoPropertiesEXT);
+        }
+#endif
+#ifdef VK_AMD_display_native_hdr
+        case VK_STRUCTURE_TYPE_DISPLAY_NATIVE_HDR_SURFACE_CAPABILITIES_AMD: {
+            return sizeof(VkDisplayNativeHdrSurfaceCapabilitiesAMD);
+        }
+        case VK_STRUCTURE_TYPE_SWAPCHAIN_DISPLAY_NATIVE_HDR_CREATE_INFO_AMD: {
+            return sizeof(VkSwapchainDisplayNativeHdrCreateInfoAMD);
+        }
+#endif
 #ifdef VK_EXT_fragment_density_map
         case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_FEATURES_EXT: {
             switch (rootType) {
@@ -1407,11 +3331,78 @@
             }
         }
 #endif
+#ifdef VK_AMD_shader_core_properties2
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_2_AMD: {
+            return sizeof(VkPhysicalDeviceShaderCoreProperties2AMD);
+        }
+#endif
+#ifdef VK_AMD_device_coherent_memory
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COHERENT_MEMORY_FEATURES_AMD: {
+            return sizeof(VkPhysicalDeviceCoherentMemoryFeaturesAMD);
+        }
+#endif
+#ifdef VK_EXT_shader_image_atomic_int64
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_IMAGE_ATOMIC_INT64_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceShaderImageAtomicInt64FeaturesEXT);
+        }
+#endif
+#ifdef VK_EXT_memory_budget
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT: {
+            return sizeof(VkPhysicalDeviceMemoryBudgetPropertiesEXT);
+        }
+#endif
+#ifdef VK_EXT_memory_priority
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PRIORITY_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceMemoryPriorityFeaturesEXT);
+        }
+        case VK_STRUCTURE_TYPE_MEMORY_PRIORITY_ALLOCATE_INFO_EXT: {
+            return sizeof(VkMemoryPriorityAllocateInfoEXT);
+        }
+#endif
+#ifdef VK_NV_dedicated_allocation_image_aliasing
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEDICATED_ALLOCATION_IMAGE_ALIASING_FEATURES_NV: {
+            return sizeof(VkPhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV);
+        }
+#endif
+#ifdef VK_EXT_buffer_device_address
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceBufferDeviceAddressFeaturesEXT);
+        }
+        case VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_CREATE_INFO_EXT: {
+            return sizeof(VkBufferDeviceAddressCreateInfoEXT);
+        }
+#endif
 #ifdef VK_EXT_validation_features
         case VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT: {
             return sizeof(VkValidationFeaturesEXT);
         }
 #endif
+#ifdef VK_NV_cooperative_matrix
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_FEATURES_NV: {
+            return sizeof(VkPhysicalDeviceCooperativeMatrixFeaturesNV);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_PROPERTIES_NV: {
+            return sizeof(VkPhysicalDeviceCooperativeMatrixPropertiesNV);
+        }
+#endif
+#ifdef VK_NV_coverage_reduction_mode
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COVERAGE_REDUCTION_MODE_FEATURES_NV: {
+            return sizeof(VkPhysicalDeviceCoverageReductionModeFeaturesNV);
+        }
+        case VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_REDUCTION_STATE_CREATE_INFO_NV: {
+            return sizeof(VkPipelineCoverageReductionStateCreateInfoNV);
+        }
+#endif
+#ifdef VK_EXT_fragment_shader_interlock
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_INTERLOCK_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT);
+        }
+#endif
+#ifdef VK_EXT_ycbcr_image_arrays
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_YCBCR_IMAGE_ARRAYS_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceYcbcrImageArraysFeaturesEXT);
+        }
+#endif
 #ifdef VK_EXT_provoking_vertex
         case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_FEATURES_EXT: {
             return sizeof(VkPhysicalDeviceProvokingVertexFeaturesEXT);
@@ -1423,6 +3414,17 @@
             return sizeof(VkPipelineRasterizationProvokingVertexStateCreateInfoEXT);
         }
 #endif
+#ifdef VK_EXT_full_screen_exclusive
+        case VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_INFO_EXT: {
+            return sizeof(VkSurfaceFullScreenExclusiveInfoEXT);
+        }
+        case VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_FULL_SCREEN_EXCLUSIVE_EXT: {
+            return sizeof(VkSurfaceCapabilitiesFullScreenExclusiveEXT);
+        }
+        case VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_WIN32_INFO_EXT: {
+            return sizeof(VkSurfaceFullScreenExclusiveWin32InfoEXT);
+        }
+#endif
 #ifdef VK_EXT_line_rasterization
         case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT: {
             return sizeof(VkPhysicalDeviceLineRasterizationFeaturesEXT);
@@ -1434,6 +3436,11 @@
             return sizeof(VkPipelineRasterizationLineStateCreateInfoEXT);
         }
 #endif
+#ifdef VK_EXT_shader_atomic_float
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceShaderAtomicFloatFeaturesEXT);
+        }
+#endif
 #ifdef VK_EXT_index_type_uint8
         case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES_EXT: {
             return sizeof(VkPhysicalDeviceIndexTypeUint8FeaturesEXT);
@@ -1458,6 +3465,22 @@
             return sizeof(VkHostImageCopyDevicePerformanceQueryEXT);
         }
 #endif
+#ifdef VK_EXT_shader_atomic_float2
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_2_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceShaderAtomicFloat2FeaturesEXT);
+        }
+#endif
+#ifdef VK_EXT_surface_maintenance1
+        case VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_EXT: {
+            return sizeof(VkSurfacePresentModeEXT);
+        }
+        case VK_STRUCTURE_TYPE_SURFACE_PRESENT_SCALING_CAPABILITIES_EXT: {
+            return sizeof(VkSurfacePresentScalingCapabilitiesEXT);
+        }
+        case VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_COMPATIBILITY_EXT: {
+            return sizeof(VkSurfacePresentModeCompatibilityEXT);
+        }
+#endif
 #ifdef VK_EXT_swapchain_maintenance1
         case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SWAPCHAIN_MAINTENANCE_1_FEATURES_EXT: {
             return sizeof(VkPhysicalDeviceSwapchainMaintenance1FeaturesEXT);
@@ -1475,11 +3498,46 @@
             return sizeof(VkSwapchainPresentScalingCreateInfoEXT);
         }
 #endif
+#ifdef VK_NV_device_generated_commands
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_PROPERTIES_NV: {
+            return sizeof(VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_FEATURES_NV: {
+            return sizeof(VkPhysicalDeviceDeviceGeneratedCommandsFeaturesNV);
+        }
+        case VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_SHADER_GROUPS_CREATE_INFO_NV: {
+            return sizeof(VkGraphicsPipelineShaderGroupsCreateInfoNV);
+        }
+#endif
+#ifdef VK_NV_inherited_viewport_scissor
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INHERITED_VIEWPORT_SCISSOR_FEATURES_NV: {
+            return sizeof(VkPhysicalDeviceInheritedViewportScissorFeaturesNV);
+        }
+        case VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_VIEWPORT_SCISSOR_INFO_NV: {
+            return sizeof(VkCommandBufferInheritanceViewportScissorInfoNV);
+        }
+#endif
 #ifdef VK_EXT_texel_buffer_alignment
         case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_FEATURES_EXT: {
             return sizeof(VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT);
         }
 #endif
+#ifdef VK_QCOM_render_pass_transform
+        case VK_STRUCTURE_TYPE_RENDER_PASS_TRANSFORM_BEGIN_INFO_QCOM: {
+            return sizeof(VkRenderPassTransformBeginInfoQCOM);
+        }
+        case VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDER_PASS_TRANSFORM_INFO_QCOM: {
+            return sizeof(VkCommandBufferInheritanceRenderPassTransformInfoQCOM);
+        }
+#endif
+#ifdef VK_EXT_depth_bias_control
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_BIAS_CONTROL_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceDepthBiasControlFeaturesEXT);
+        }
+        case VK_STRUCTURE_TYPE_DEPTH_BIAS_REPRESENTATION_INFO_EXT: {
+            return sizeof(VkDepthBiasRepresentationInfoEXT);
+        }
+#endif
 #ifdef VK_EXT_device_memory_report
         case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_MEMORY_REPORT_FEATURES_EXT: {
             return sizeof(VkPhysicalDeviceDeviceMemoryReportFeaturesEXT);
@@ -1507,6 +3565,55 @@
             return sizeof(VkPhysicalDeviceCustomBorderColorFeaturesEXT);
         }
 #endif
+#ifdef VK_NV_present_barrier
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_BARRIER_FEATURES_NV: {
+            return sizeof(VkPhysicalDevicePresentBarrierFeaturesNV);
+        }
+        case VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_PRESENT_BARRIER_NV: {
+            return sizeof(VkSurfaceCapabilitiesPresentBarrierNV);
+        }
+        case VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_BARRIER_CREATE_INFO_NV: {
+            return sizeof(VkSwapchainPresentBarrierCreateInfoNV);
+        }
+#endif
+#ifdef VK_NV_device_diagnostics_config
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DIAGNOSTICS_CONFIG_FEATURES_NV: {
+            return sizeof(VkPhysicalDeviceDiagnosticsConfigFeaturesNV);
+        }
+        case VK_STRUCTURE_TYPE_DEVICE_DIAGNOSTICS_CONFIG_CREATE_INFO_NV: {
+            return sizeof(VkDeviceDiagnosticsConfigCreateInfoNV);
+        }
+#endif
+#ifdef VK_NV_cuda_kernel_launch
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUDA_KERNEL_LAUNCH_FEATURES_NV: {
+            return sizeof(VkPhysicalDeviceCudaKernelLaunchFeaturesNV);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUDA_KERNEL_LAUNCH_PROPERTIES_NV: {
+            return sizeof(VkPhysicalDeviceCudaKernelLaunchPropertiesNV);
+        }
+#endif
+#ifdef VK_NV_low_latency
+        case VK_STRUCTURE_TYPE_QUERY_LOW_LATENCY_SUPPORT_NV: {
+            return sizeof(VkQueryLowLatencySupportNV);
+        }
+#endif
+#ifdef VK_EXT_descriptor_buffer
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_PROPERTIES_EXT: {
+            return sizeof(VkPhysicalDeviceDescriptorBufferPropertiesEXT);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_DENSITY_MAP_PROPERTIES_EXT: {
+            return sizeof(VkPhysicalDeviceDescriptorBufferDensityMapPropertiesEXT);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceDescriptorBufferFeaturesEXT);
+        }
+        case VK_STRUCTURE_TYPE_DESCRIPTOR_BUFFER_BINDING_PUSH_DESCRIPTOR_BUFFER_HANDLE_EXT: {
+            return sizeof(VkDescriptorBufferBindingPushDescriptorBufferHandleEXT);
+        }
+        case VK_STRUCTURE_TYPE_OPAQUE_CAPTURE_DESCRIPTOR_DATA_CREATE_INFO_EXT: {
+            return sizeof(VkOpaqueCaptureDescriptorDataCreateInfoEXT);
+        }
+#endif
 #ifdef VK_EXT_graphics_pipeline_library
         case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GRAPHICS_PIPELINE_LIBRARY_FEATURES_EXT: {
             return sizeof(VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT);
@@ -1518,11 +3625,51 @@
             return sizeof(VkGraphicsPipelineLibraryCreateInfoEXT);
         }
 #endif
+#ifdef VK_AMD_shader_early_and_late_fragment_tests
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_EARLY_AND_LATE_FRAGMENT_TESTS_FEATURES_AMD: {
+            return sizeof(VkPhysicalDeviceShaderEarlyAndLateFragmentTestsFeaturesAMD);
+        }
+#endif
+#ifdef VK_NV_fragment_shading_rate_enums
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_ENUMS_FEATURES_NV: {
+            return sizeof(VkPhysicalDeviceFragmentShadingRateEnumsFeaturesNV);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_ENUMS_PROPERTIES_NV: {
+            return sizeof(VkPhysicalDeviceFragmentShadingRateEnumsPropertiesNV);
+        }
+        case VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_ENUM_STATE_CREATE_INFO_NV: {
+            return sizeof(VkPipelineFragmentShadingRateEnumStateCreateInfoNV);
+        }
+#endif
+#ifdef VK_NV_ray_tracing_motion_blur
+        case VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_MOTION_TRIANGLES_DATA_NV: {
+            return sizeof(VkAccelerationStructureGeometryMotionTrianglesDataNV);
+        }
+        case VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MOTION_INFO_NV: {
+            return sizeof(VkAccelerationStructureMotionInfoNV);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_MOTION_BLUR_FEATURES_NV: {
+            return sizeof(VkPhysicalDeviceRayTracingMotionBlurFeaturesNV);
+        }
+#endif
 #ifdef VK_EXT_ycbcr_2plane_444_formats
         case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_YCBCR_2_PLANE_444_FORMATS_FEATURES_EXT: {
             return sizeof(VkPhysicalDeviceYcbcr2Plane444FormatsFeaturesEXT);
         }
 #endif
+#ifdef VK_EXT_fragment_density_map2
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_2_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceFragmentDensityMap2FeaturesEXT);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_2_PROPERTIES_EXT: {
+            return sizeof(VkPhysicalDeviceFragmentDensityMap2PropertiesEXT);
+        }
+#endif
+#ifdef VK_QCOM_rotated_copy_commands
+        case VK_STRUCTURE_TYPE_COPY_COMMAND_TRANSFORM_INFO_QCOM: {
+            return sizeof(VkCopyCommandTransformInfoQCOM);
+        }
+#endif
 #ifdef VK_EXT_image_compression_control
         case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_COMPRESSION_CONTROL_FEATURES_EXT: {
             return sizeof(VkPhysicalDeviceImageCompressionControlFeaturesEXT);
@@ -1534,16 +3681,131 @@
             return sizeof(VkImageCompressionPropertiesEXT);
         }
 #endif
+#ifdef VK_EXT_attachment_feedback_loop_layout
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ATTACHMENT_FEEDBACK_LOOP_LAYOUT_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceAttachmentFeedbackLoopLayoutFeaturesEXT);
+        }
+#endif
 #ifdef VK_EXT_4444_formats
         case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_4444_FORMATS_FEATURES_EXT: {
             return sizeof(VkPhysicalDevice4444FormatsFeaturesEXT);
         }
 #endif
+#ifdef VK_EXT_device_fault
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FAULT_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceFaultFeaturesEXT);
+        }
+#endif
+#ifdef VK_ARM_rasterization_order_attachment_access
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceRasterizationOrderAttachmentAccessFeaturesEXT);
+        }
+#endif
+#ifdef VK_EXT_rgba10x6_formats
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RGBA10X6_FORMATS_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceRGBA10X6FormatsFeaturesEXT);
+        }
+#endif
+#ifdef VK_VALVE_mutable_descriptor_type
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MUTABLE_DESCRIPTOR_TYPE_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceMutableDescriptorTypeFeaturesEXT);
+        }
+        case VK_STRUCTURE_TYPE_MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_EXT: {
+            return sizeof(VkMutableDescriptorTypeCreateInfoEXT);
+        }
+#endif
+#ifdef VK_EXT_vertex_input_dynamic_state
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_INPUT_DYNAMIC_STATE_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceVertexInputDynamicStateFeaturesEXT);
+        }
+#endif
+#ifdef VK_EXT_physical_device_drm
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRM_PROPERTIES_EXT: {
+            return sizeof(VkPhysicalDeviceDrmPropertiesEXT);
+        }
+#endif
+#ifdef VK_EXT_device_address_binding_report
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ADDRESS_BINDING_REPORT_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceAddressBindingReportFeaturesEXT);
+        }
+        case VK_STRUCTURE_TYPE_DEVICE_ADDRESS_BINDING_CALLBACK_DATA_EXT: {
+            return sizeof(VkDeviceAddressBindingCallbackDataEXT);
+        }
+#endif
+#ifdef VK_EXT_depth_clip_control
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_CONTROL_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceDepthClipControlFeaturesEXT);
+        }
+        case VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_DEPTH_CLIP_CONTROL_CREATE_INFO_EXT: {
+            return sizeof(VkPipelineViewportDepthClipControlCreateInfoEXT);
+        }
+#endif
 #ifdef VK_EXT_primitive_topology_list_restart
         case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIMITIVE_TOPOLOGY_LIST_RESTART_FEATURES_EXT: {
             return sizeof(VkPhysicalDevicePrimitiveTopologyListRestartFeaturesEXT);
         }
 #endif
+#ifdef VK_FUCHSIA_external_memory
+        case VK_STRUCTURE_TYPE_IMPORT_MEMORY_ZIRCON_HANDLE_INFO_FUCHSIA: {
+            return sizeof(VkImportMemoryZirconHandleInfoFUCHSIA);
+        }
+#endif
+#ifdef VK_FUCHSIA_buffer_collection
+        case VK_STRUCTURE_TYPE_IMPORT_MEMORY_BUFFER_COLLECTION_FUCHSIA: {
+            return sizeof(VkImportMemoryBufferCollectionFUCHSIA);
+        }
+        case VK_STRUCTURE_TYPE_BUFFER_COLLECTION_IMAGE_CREATE_INFO_FUCHSIA: {
+            return sizeof(VkBufferCollectionImageCreateInfoFUCHSIA);
+        }
+        case VK_STRUCTURE_TYPE_BUFFER_COLLECTION_BUFFER_CREATE_INFO_FUCHSIA: {
+            return sizeof(VkBufferCollectionBufferCreateInfoFUCHSIA);
+        }
+#endif
+#ifdef VK_HUAWEI_subpass_shading
+        case VK_STRUCTURE_TYPE_SUBPASS_SHADING_PIPELINE_CREATE_INFO_HUAWEI: {
+            return sizeof(VkSubpassShadingPipelineCreateInfoHUAWEI);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBPASS_SHADING_FEATURES_HUAWEI: {
+            return sizeof(VkPhysicalDeviceSubpassShadingFeaturesHUAWEI);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBPASS_SHADING_PROPERTIES_HUAWEI: {
+            return sizeof(VkPhysicalDeviceSubpassShadingPropertiesHUAWEI);
+        }
+#endif
+#ifdef VK_HUAWEI_invocation_mask
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INVOCATION_MASK_FEATURES_HUAWEI: {
+            return sizeof(VkPhysicalDeviceInvocationMaskFeaturesHUAWEI);
+        }
+#endif
+#ifdef VK_NV_external_memory_rdma
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_RDMA_FEATURES_NV: {
+            return sizeof(VkPhysicalDeviceExternalMemoryRDMAFeaturesNV);
+        }
+#endif
+#ifdef VK_EXT_pipeline_properties
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_PROPERTIES_FEATURES_EXT: {
+            return sizeof(VkPhysicalDevicePipelinePropertiesFeaturesEXT);
+        }
+#endif
+#ifdef VK_EXT_frame_boundary
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAME_BOUNDARY_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceFrameBoundaryFeaturesEXT);
+        }
+        case VK_STRUCTURE_TYPE_FRAME_BOUNDARY_EXT: {
+            return sizeof(VkFrameBoundaryEXT);
+        }
+#endif
+#ifdef VK_EXT_multisampled_render_to_single_sampled
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceMultisampledRenderToSingleSampledFeaturesEXT);
+        }
+        case VK_STRUCTURE_TYPE_SUBPASS_RESOLVE_PERFORMANCE_QUERY_EXT: {
+            return sizeof(VkSubpassResolvePerformanceQueryEXT);
+        }
+        case VK_STRUCTURE_TYPE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_INFO_EXT: {
+            return sizeof(VkMultisampledRenderToSingleSampledInfoEXT);
+        }
+#endif
 #ifdef VK_EXT_extended_dynamic_state2
         case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_2_FEATURES_EXT: {
             return sizeof(VkPhysicalDeviceExtendedDynamicState2FeaturesEXT);
@@ -1557,6 +3819,11 @@
             return sizeof(VkPipelineColorWriteCreateInfoEXT);
         }
 #endif
+#ifdef VK_EXT_primitives_generated_query
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIMITIVES_GENERATED_QUERY_FEATURES_EXT: {
+            return sizeof(VkPhysicalDevicePrimitivesGeneratedQueryFeaturesEXT);
+        }
+#endif
 #ifdef VK_GOOGLE_gfxstream
         case VK_STRUCTURE_TYPE_IMPORT_COLOR_BUFFER_GOOGLE: {
             return sizeof(VkImportColorBufferGOOGLE);
@@ -1568,13 +3835,426 @@
             return sizeof(VkCreateBlobGOOGLE);
         }
 #endif
+#ifdef VK_EXT_image_view_min_lod
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_MIN_LOD_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceImageViewMinLodFeaturesEXT);
+        }
+        case VK_STRUCTURE_TYPE_IMAGE_VIEW_MIN_LOD_CREATE_INFO_EXT: {
+            return sizeof(VkImageViewMinLodCreateInfoEXT);
+        }
+#endif
+#ifdef VK_EXT_multi_draw
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTI_DRAW_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceMultiDrawFeaturesEXT);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTI_DRAW_PROPERTIES_EXT: {
+            return sizeof(VkPhysicalDeviceMultiDrawPropertiesEXT);
+        }
+#endif
+#ifdef VK_EXT_image_2d_view_of_3d
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_2D_VIEW_OF_3D_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceImage2DViewOf3DFeaturesEXT);
+        }
+#endif
+#ifdef VK_EXT_shader_tile_image
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_TILE_IMAGE_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceShaderTileImageFeaturesEXT);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_TILE_IMAGE_PROPERTIES_EXT: {
+            return sizeof(VkPhysicalDeviceShaderTileImagePropertiesEXT);
+        }
+#endif
+#ifdef VK_EXT_opacity_micromap
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_OPACITY_MICROMAP_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceOpacityMicromapFeaturesEXT);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_OPACITY_MICROMAP_PROPERTIES_EXT: {
+            return sizeof(VkPhysicalDeviceOpacityMicromapPropertiesEXT);
+        }
+        case VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_TRIANGLES_OPACITY_MICROMAP_EXT: {
+            return sizeof(VkAccelerationStructureTrianglesOpacityMicromapEXT);
+        }
+#endif
+#ifdef VK_NV_displacement_micromap
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DISPLACEMENT_MICROMAP_FEATURES_NV: {
+            return sizeof(VkPhysicalDeviceDisplacementMicromapFeaturesNV);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DISPLACEMENT_MICROMAP_PROPERTIES_NV: {
+            return sizeof(VkPhysicalDeviceDisplacementMicromapPropertiesNV);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+        case VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_TRIANGLES_DISPLACEMENT_MICROMAP_NV: {
+            return sizeof(VkAccelerationStructureTrianglesDisplacementMicromapNV);
+        }
+#endif  // VK_ENABLE_BETA_EXTENSIONS
+#endif
+#ifdef VK_HUAWEI_cluster_culling_shader
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CLUSTER_CULLING_SHADER_FEATURES_HUAWEI: {
+            return sizeof(VkPhysicalDeviceClusterCullingShaderFeaturesHUAWEI);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CLUSTER_CULLING_SHADER_PROPERTIES_HUAWEI: {
+            return sizeof(VkPhysicalDeviceClusterCullingShaderPropertiesHUAWEI);
+        }
+#endif
+#ifdef VK_EXT_border_color_swizzle
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BORDER_COLOR_SWIZZLE_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceBorderColorSwizzleFeaturesEXT);
+        }
+        case VK_STRUCTURE_TYPE_SAMPLER_BORDER_COLOR_COMPONENT_MAPPING_CREATE_INFO_EXT: {
+            return sizeof(VkSamplerBorderColorComponentMappingCreateInfoEXT);
+        }
+#endif
+#ifdef VK_EXT_pageable_device_local_memory
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PAGEABLE_DEVICE_LOCAL_MEMORY_FEATURES_EXT: {
+            return sizeof(VkPhysicalDevicePageableDeviceLocalMemoryFeaturesEXT);
+        }
+#endif
+#ifdef VK_ARM_shader_core_properties
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_ARM: {
+            return sizeof(VkPhysicalDeviceShaderCorePropertiesARM);
+        }
+#endif
+#ifdef VK_ARM_scheduling_controls
+        case VK_STRUCTURE_TYPE_DEVICE_QUEUE_SHADER_CORE_CONTROL_CREATE_INFO_ARM: {
+            return sizeof(VkDeviceQueueShaderCoreControlCreateInfoARM);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCHEDULING_CONTROLS_FEATURES_ARM: {
+            return sizeof(VkPhysicalDeviceSchedulingControlsFeaturesARM);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCHEDULING_CONTROLS_PROPERTIES_ARM: {
+            return sizeof(VkPhysicalDeviceSchedulingControlsPropertiesARM);
+        }
+#endif
+#ifdef VK_EXT_image_sliced_view_of_3d
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_SLICED_VIEW_OF_3D_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceImageSlicedViewOf3DFeaturesEXT);
+        }
+        case VK_STRUCTURE_TYPE_IMAGE_VIEW_SLICED_CREATE_INFO_EXT: {
+            return sizeof(VkImageViewSlicedCreateInfoEXT);
+        }
+#endif
+#ifdef VK_VALVE_descriptor_set_host_mapping
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_SET_HOST_MAPPING_FEATURES_VALVE: {
+            return sizeof(VkPhysicalDeviceDescriptorSetHostMappingFeaturesVALVE);
+        }
+#endif
+#ifdef VK_EXT_depth_clamp_zero_one
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLAMP_ZERO_ONE_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceDepthClampZeroOneFeaturesEXT);
+        }
+#endif
+#ifdef VK_EXT_non_seamless_cube_map
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_NON_SEAMLESS_CUBE_MAP_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceNonSeamlessCubeMapFeaturesEXT);
+        }
+#endif
+#ifdef VK_QCOM_fragment_density_map_offset
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_OFFSET_FEATURES_QCOM: {
+            return sizeof(VkPhysicalDeviceFragmentDensityMapOffsetFeaturesQCOM);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_OFFSET_PROPERTIES_QCOM: {
+            return sizeof(VkPhysicalDeviceFragmentDensityMapOffsetPropertiesQCOM);
+        }
+        case VK_STRUCTURE_TYPE_SUBPASS_FRAGMENT_DENSITY_MAP_OFFSET_END_INFO_QCOM: {
+            return sizeof(VkSubpassFragmentDensityMapOffsetEndInfoQCOM);
+        }
+#endif
+#ifdef VK_NV_copy_memory_indirect
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COPY_MEMORY_INDIRECT_FEATURES_NV: {
+            return sizeof(VkPhysicalDeviceCopyMemoryIndirectFeaturesNV);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COPY_MEMORY_INDIRECT_PROPERTIES_NV: {
+            return sizeof(VkPhysicalDeviceCopyMemoryIndirectPropertiesNV);
+        }
+#endif
+#ifdef VK_NV_memory_decompression
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_DECOMPRESSION_FEATURES_NV: {
+            return sizeof(VkPhysicalDeviceMemoryDecompressionFeaturesNV);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_DECOMPRESSION_PROPERTIES_NV: {
+            return sizeof(VkPhysicalDeviceMemoryDecompressionPropertiesNV);
+        }
+#endif
+#ifdef VK_NV_device_generated_commands_compute
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_COMPUTE_FEATURES_NV: {
+            return sizeof(VkPhysicalDeviceDeviceGeneratedCommandsComputeFeaturesNV);
+        }
+#endif
+#ifdef VK_NV_linear_color_attachment
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINEAR_COLOR_ATTACHMENT_FEATURES_NV: {
+            return sizeof(VkPhysicalDeviceLinearColorAttachmentFeaturesNV);
+        }
+#endif
 #ifdef VK_EXT_image_compression_control_swapchain
         case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN_FEATURES_EXT: {
             return sizeof(VkPhysicalDeviceImageCompressionControlSwapchainFeaturesEXT);
         }
 #endif
+#ifdef VK_QCOM_image_processing
+        case VK_STRUCTURE_TYPE_IMAGE_VIEW_SAMPLE_WEIGHT_CREATE_INFO_QCOM: {
+            return sizeof(VkImageViewSampleWeightCreateInfoQCOM);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_PROCESSING_FEATURES_QCOM: {
+            return sizeof(VkPhysicalDeviceImageProcessingFeaturesQCOM);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_PROCESSING_PROPERTIES_QCOM: {
+            return sizeof(VkPhysicalDeviceImageProcessingPropertiesQCOM);
+        }
+#endif
+#ifdef VK_EXT_nested_command_buffer
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_NESTED_COMMAND_BUFFER_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceNestedCommandBufferFeaturesEXT);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_NESTED_COMMAND_BUFFER_PROPERTIES_EXT: {
+            return sizeof(VkPhysicalDeviceNestedCommandBufferPropertiesEXT);
+        }
+#endif
+#ifdef VK_EXT_external_memory_acquire_unmodified
+        case VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_ACQUIRE_UNMODIFIED_EXT: {
+            return sizeof(VkExternalMemoryAcquireUnmodifiedEXT);
+        }
+#endif
+#ifdef VK_EXT_extended_dynamic_state3
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceExtendedDynamicState3FeaturesEXT);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_PROPERTIES_EXT: {
+            return sizeof(VkPhysicalDeviceExtendedDynamicState3PropertiesEXT);
+        }
+#endif
+#ifdef VK_EXT_subpass_merge_feedback
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBPASS_MERGE_FEEDBACK_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceSubpassMergeFeedbackFeaturesEXT);
+        }
+        case VK_STRUCTURE_TYPE_RENDER_PASS_CREATION_CONTROL_EXT: {
+            return sizeof(VkRenderPassCreationControlEXT);
+        }
+        case VK_STRUCTURE_TYPE_RENDER_PASS_CREATION_FEEDBACK_CREATE_INFO_EXT: {
+            return sizeof(VkRenderPassCreationFeedbackCreateInfoEXT);
+        }
+        case VK_STRUCTURE_TYPE_RENDER_PASS_SUBPASS_FEEDBACK_CREATE_INFO_EXT: {
+            return sizeof(VkRenderPassSubpassFeedbackCreateInfoEXT);
+        }
+#endif
+#ifdef VK_LUNARG_direct_driver_loading
+        case VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_LIST_LUNARG: {
+            return sizeof(VkDirectDriverLoadingListLUNARG);
+        }
+#endif
+#ifdef VK_EXT_shader_module_identifier
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_MODULE_IDENTIFIER_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceShaderModuleIdentifierFeaturesEXT);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_MODULE_IDENTIFIER_PROPERTIES_EXT: {
+            return sizeof(VkPhysicalDeviceShaderModuleIdentifierPropertiesEXT);
+        }
+        case VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_MODULE_IDENTIFIER_CREATE_INFO_EXT: {
+            return sizeof(VkPipelineShaderStageModuleIdentifierCreateInfoEXT);
+        }
+#endif
+#ifdef VK_NV_optical_flow
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_OPTICAL_FLOW_FEATURES_NV: {
+            return sizeof(VkPhysicalDeviceOpticalFlowFeaturesNV);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_OPTICAL_FLOW_PROPERTIES_NV: {
+            return sizeof(VkPhysicalDeviceOpticalFlowPropertiesNV);
+        }
+        case VK_STRUCTURE_TYPE_OPTICAL_FLOW_IMAGE_FORMAT_INFO_NV: {
+            return sizeof(VkOpticalFlowImageFormatInfoNV);
+        }
+        case VK_STRUCTURE_TYPE_OPTICAL_FLOW_SESSION_CREATE_PRIVATE_DATA_INFO_NV: {
+            return sizeof(VkOpticalFlowSessionCreatePrivateDataInfoNV);
+        }
+#endif
+#ifdef VK_EXT_legacy_dithering
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LEGACY_DITHERING_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceLegacyDitheringFeaturesEXT);
+        }
+#endif
+#ifdef VK_EXT_pipeline_protected_access
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_PROTECTED_ACCESS_FEATURES_EXT: {
+            return sizeof(VkPhysicalDevicePipelineProtectedAccessFeaturesEXT);
+        }
+#endif
+#ifdef VK_ANDROID_external_format_resolve
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FORMAT_RESOLVE_FEATURES_ANDROID: {
+            return sizeof(VkPhysicalDeviceExternalFormatResolveFeaturesANDROID);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FORMAT_RESOLVE_PROPERTIES_ANDROID: {
+            return sizeof(VkPhysicalDeviceExternalFormatResolvePropertiesANDROID);
+        }
+        case VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_RESOLVE_PROPERTIES_ANDROID: {
+            return sizeof(VkAndroidHardwareBufferFormatResolvePropertiesANDROID);
+        }
+#endif
+#ifdef VK_EXT_shader_object
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_OBJECT_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceShaderObjectFeaturesEXT);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_OBJECT_PROPERTIES_EXT: {
+            return sizeof(VkPhysicalDeviceShaderObjectPropertiesEXT);
+        }
+#endif
+#ifdef VK_QCOM_tile_properties
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TILE_PROPERTIES_FEATURES_QCOM: {
+            return sizeof(VkPhysicalDeviceTilePropertiesFeaturesQCOM);
+        }
+#endif
+#ifdef VK_SEC_amigo_profiling
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_AMIGO_PROFILING_FEATURES_SEC: {
+            return sizeof(VkPhysicalDeviceAmigoProfilingFeaturesSEC);
+        }
+        case VK_STRUCTURE_TYPE_AMIGO_PROFILING_SUBMIT_INFO_SEC: {
+            return sizeof(VkAmigoProfilingSubmitInfoSEC);
+        }
+#endif
+#ifdef VK_QCOM_multiview_per_view_viewports
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_VIEWPORTS_FEATURES_QCOM: {
+            return sizeof(VkPhysicalDeviceMultiviewPerViewViewportsFeaturesQCOM);
+        }
+#endif
+#ifdef VK_NV_ray_tracing_invocation_reorder
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_INVOCATION_REORDER_PROPERTIES_NV: {
+            return sizeof(VkPhysicalDeviceRayTracingInvocationReorderPropertiesNV);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_INVOCATION_REORDER_FEATURES_NV: {
+            return sizeof(VkPhysicalDeviceRayTracingInvocationReorderFeaturesNV);
+        }
+#endif
+#ifdef VK_NV_extended_sparse_address_space
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_SPARSE_ADDRESS_SPACE_FEATURES_NV: {
+            return sizeof(VkPhysicalDeviceExtendedSparseAddressSpaceFeaturesNV);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_SPARSE_ADDRESS_SPACE_PROPERTIES_NV: {
+            return sizeof(VkPhysicalDeviceExtendedSparseAddressSpacePropertiesNV);
+        }
+#endif
+#ifdef VK_ARM_shader_core_builtins
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_BUILTINS_FEATURES_ARM: {
+            return sizeof(VkPhysicalDeviceShaderCoreBuiltinsFeaturesARM);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_BUILTINS_PROPERTIES_ARM: {
+            return sizeof(VkPhysicalDeviceShaderCoreBuiltinsPropertiesARM);
+        }
+#endif
+#ifdef VK_EXT_pipeline_library_group_handles
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_LIBRARY_GROUP_HANDLES_FEATURES_EXT: {
+            return sizeof(VkPhysicalDevicePipelineLibraryGroupHandlesFeaturesEXT);
+        }
+#endif
+#ifdef VK_EXT_dynamic_rendering_unused_attachments
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_UNUSED_ATTACHMENTS_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceDynamicRenderingUnusedAttachmentsFeaturesEXT);
+        }
+#endif
+#ifdef VK_NV_low_latency2
+        case VK_STRUCTURE_TYPE_LATENCY_SUBMISSION_PRESENT_ID_NV: {
+            return sizeof(VkLatencySubmissionPresentIdNV);
+        }
+        case VK_STRUCTURE_TYPE_SWAPCHAIN_LATENCY_CREATE_INFO_NV: {
+            return sizeof(VkSwapchainLatencyCreateInfoNV);
+        }
+        case VK_STRUCTURE_TYPE_LATENCY_SURFACE_CAPABILITIES_NV: {
+            return sizeof(VkLatencySurfaceCapabilitiesNV);
+        }
+#endif
+#ifdef VK_QCOM_multiview_per_view_render_areas
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_RENDER_AREAS_FEATURES_QCOM: {
+            return sizeof(VkPhysicalDeviceMultiviewPerViewRenderAreasFeaturesQCOM);
+        }
+        case VK_STRUCTURE_TYPE_MULTIVIEW_PER_VIEW_RENDER_AREAS_RENDER_PASS_BEGIN_INFO_QCOM: {
+            return sizeof(VkMultiviewPerViewRenderAreasRenderPassBeginInfoQCOM);
+        }
+#endif
+#ifdef VK_QCOM_image_processing2
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_PROCESSING_2_FEATURES_QCOM: {
+            return sizeof(VkPhysicalDeviceImageProcessing2FeaturesQCOM);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_PROCESSING_2_PROPERTIES_QCOM: {
+            return sizeof(VkPhysicalDeviceImageProcessing2PropertiesQCOM);
+        }
+        case VK_STRUCTURE_TYPE_SAMPLER_BLOCK_MATCH_WINDOW_CREATE_INFO_QCOM: {
+            return sizeof(VkSamplerBlockMatchWindowCreateInfoQCOM);
+        }
+#endif
+#ifdef VK_QCOM_filter_cubic_weights
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUBIC_WEIGHTS_FEATURES_QCOM: {
+            return sizeof(VkPhysicalDeviceCubicWeightsFeaturesQCOM);
+        }
+        case VK_STRUCTURE_TYPE_SAMPLER_CUBIC_WEIGHTS_CREATE_INFO_QCOM: {
+            return sizeof(VkSamplerCubicWeightsCreateInfoQCOM);
+        }
+        case VK_STRUCTURE_TYPE_BLIT_IMAGE_CUBIC_WEIGHTS_INFO_QCOM: {
+            return sizeof(VkBlitImageCubicWeightsInfoQCOM);
+        }
+#endif
+#ifdef VK_QCOM_ycbcr_degamma
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_YCBCR_DEGAMMA_FEATURES_QCOM: {
+            return sizeof(VkPhysicalDeviceYcbcrDegammaFeaturesQCOM);
+        }
+        case VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_YCBCR_DEGAMMA_CREATE_INFO_QCOM: {
+            return sizeof(VkSamplerYcbcrConversionYcbcrDegammaCreateInfoQCOM);
+        }
+#endif
+#ifdef VK_QCOM_filter_cubic_clamp
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUBIC_CLAMP_FEATURES_QCOM: {
+            return sizeof(VkPhysicalDeviceCubicClampFeaturesQCOM);
+        }
+#endif
+#ifdef VK_EXT_attachment_feedback_loop_dynamic_state
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ATTACHMENT_FEEDBACK_LOOP_DYNAMIC_STATE_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesEXT);
+        }
+#endif
+#ifdef VK_MSFT_layered_driver
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LAYERED_DRIVER_PROPERTIES_MSFT: {
+            return sizeof(VkPhysicalDeviceLayeredDriverPropertiesMSFT);
+        }
+#endif
+#ifdef VK_NV_descriptor_pool_overallocation
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_POOL_OVERALLOCATION_FEATURES_NV: {
+            return sizeof(VkPhysicalDeviceDescriptorPoolOverallocationFeaturesNV);
+        }
+#endif
+#ifdef VK_KHR_acceleration_structure
+        case VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR: {
+            return sizeof(VkWriteDescriptorSetAccelerationStructureKHR);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR: {
+            return sizeof(VkPhysicalDeviceAccelerationStructureFeaturesKHR);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_PROPERTIES_KHR: {
+            return sizeof(VkPhysicalDeviceAccelerationStructurePropertiesKHR);
+        }
+#endif
+#ifdef VK_KHR_ray_tracing_pipeline
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR: {
+            return sizeof(VkPhysicalDeviceRayTracingPipelineFeaturesKHR);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR: {
+            return sizeof(VkPhysicalDeviceRayTracingPipelinePropertiesKHR);
+        }
+#endif
+#ifdef VK_KHR_ray_query
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_QUERY_FEATURES_KHR: {
+            return sizeof(VkPhysicalDeviceRayQueryFeaturesKHR);
+        }
+#endif
+#ifdef VK_EXT_mesh_shader
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_EXT: {
+            return sizeof(VkPhysicalDeviceMeshShaderFeaturesEXT);
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_PROPERTIES_EXT: {
+            return sizeof(VkPhysicalDeviceMeshShaderPropertiesEXT);
+        }
+#endif
         default: {
-            fprintf(stderr, "Unhandled Vulkan structure type %d, aborting.\n", structType);
+            fprintf(stderr, "Unhandled Vulkan structure type %s [%d], aborting.\n",
+                    string_VkStructureType(VkStructureType(structType)), structType);
             GFXSTREAM_ABORT(::emugl::FatalError(::emugl::ABORT_REASON_OTHER));
             return (size_t)0;
         }
diff --git a/host/vulkan/cereal/common/goldfish_vk_extension_structs.h b/host/vulkan/cereal/common/goldfish_vk_extension_structs.h
index a7feb37..ff3121b 100644
--- a/host/vulkan/cereal/common/goldfish_vk_extension_structs.h
+++ b/host/vulkan/cereal/common/goldfish_vk_extension_structs.h
@@ -35,6 +35,7 @@
 #include "goldfish_vk_private_defs.h"
 #include "host-common/GfxstreamFatalError.h"
 #include "vk_android_native_buffer_gfxstream.h"
+#include "vulkan/vk_enum_string_helper.h"
 #include "vulkan_gfxstream.h"
 
 namespace gfxstream {
@@ -48,198 +49,5 @@
                                                               VkStructureType rootType,
                                                               const void* structExtension);
 
-#ifdef VK_VERSION_1_0
-#endif
-#ifdef VK_VERSION_1_1
-#endif
-#ifdef VK_VERSION_1_2
-#endif
-#ifdef VK_VERSION_1_3
-#endif
-#ifdef VK_KHR_surface
-#endif
-#ifdef VK_KHR_swapchain
-#endif
-#ifdef VK_KHR_xcb_surface
-#endif
-#ifdef VK_KHR_android_surface
-#endif
-#ifdef VK_KHR_win32_surface
-#endif
-#ifdef VK_KHR_dynamic_rendering
-#endif
-#ifdef VK_KHR_get_physical_device_properties2
-#endif
-#ifdef VK_KHR_maintenance1
-#endif
-#ifdef VK_KHR_external_memory_capabilities
-#endif
-#ifdef VK_KHR_external_memory
-#endif
-#ifdef VK_KHR_external_memory_win32
-#endif
-#ifdef VK_KHR_external_memory_fd
-#endif
-#ifdef VK_KHR_external_semaphore_capabilities
-#endif
-#ifdef VK_KHR_external_semaphore
-#endif
-#ifdef VK_KHR_external_semaphore_win32
-#endif
-#ifdef VK_KHR_external_semaphore_fd
-#endif
-#ifdef VK_KHR_shader_float16_int8
-#endif
-#ifdef VK_KHR_incremental_present
-#endif
-#ifdef VK_KHR_descriptor_update_template
-#endif
-#ifdef VK_KHR_imageless_framebuffer
-#endif
-#ifdef VK_KHR_create_renderpass2
-#endif
-#ifdef VK_KHR_external_fence_capabilities
-#endif
-#ifdef VK_KHR_external_fence
-#endif
-#ifdef VK_KHR_external_fence_fd
-#endif
-#ifdef VK_KHR_maintenance2
-#endif
-#ifdef VK_KHR_dedicated_allocation
-#endif
-#ifdef VK_KHR_storage_buffer_storage_class
-#endif
-#ifdef VK_KHR_get_memory_requirements2
-#endif
-#ifdef VK_KHR_image_format_list
-#endif
-#ifdef VK_KHR_sampler_ycbcr_conversion
-#endif
-#ifdef VK_KHR_bind_memory2
-#endif
-#ifdef VK_KHR_maintenance3
-#endif
-#ifdef VK_KHR_shader_subgroup_extended_types
-#endif
-#ifdef VK_KHR_vulkan_memory_model
-#endif
-#ifdef VK_KHR_shader_terminate_invocation
-#endif
-#ifdef VK_KHR_buffer_device_address
-#endif
-#ifdef VK_KHR_pipeline_executable_properties
-#endif
-#ifdef VK_KHR_shader_integer_dot_product
-#endif
-#ifdef VK_KHR_shader_non_semantic_info
-#endif
-#ifdef VK_KHR_synchronization2
-#endif
-#ifdef VK_KHR_zero_initialize_workgroup_memory
-#endif
-#ifdef VK_KHR_copy_commands2
-#endif
-#ifdef VK_KHR_format_feature_flags2
-#endif
-#ifdef VK_KHR_maintenance4
-#endif
-#ifdef VK_KHR_maintenance5
-#endif
-#ifdef VK_ANDROID_native_buffer
-#endif
-#ifdef VK_EXT_debug_report
-#endif
-#ifdef VK_EXT_transform_feedback
-#endif
-#ifdef VK_AMD_gpu_shader_half_float
-#endif
-#ifdef VK_EXT_texture_compression_astc_hdr
-#endif
-#ifdef VK_EXT_depth_clip_enable
-#endif
-#ifdef VK_EXT_swapchain_colorspace
-#endif
-#ifdef VK_EXT_queue_family_foreign
-#endif
-#ifdef VK_EXT_debug_utils
-#endif
-#ifdef VK_ANDROID_external_memory_android_hardware_buffer
-#endif
-#ifdef VK_EXT_inline_uniform_block
-#endif
-#ifdef VK_EXT_shader_stencil_export
-#endif
-#ifdef VK_EXT_vertex_attribute_divisor
-#endif
-#ifdef VK_EXT_pipeline_creation_feedback
-#endif
-#ifdef VK_NV_shader_subgroup_partitioned
-#endif
-#ifdef VK_EXT_metal_surface
-#endif
-#ifdef VK_EXT_fragment_density_map
-#endif
-#ifdef VK_EXT_scalar_block_layout
-#endif
-#ifdef VK_EXT_subgroup_size_control
-#endif
-#ifdef VK_EXT_tooling_info
-#endif
-#ifdef VK_EXT_validation_features
-#endif
-#ifdef VK_EXT_provoking_vertex
-#endif
-#ifdef VK_EXT_line_rasterization
-#endif
-#ifdef VK_EXT_index_type_uint8
-#endif
-#ifdef VK_EXT_extended_dynamic_state
-#endif
-#ifdef VK_EXT_host_image_copy
-#endif
-#ifdef VK_EXT_swapchain_maintenance1
-#endif
-#ifdef VK_EXT_shader_demote_to_helper_invocation
-#endif
-#ifdef VK_EXT_texel_buffer_alignment
-#endif
-#ifdef VK_EXT_device_memory_report
-#endif
-#ifdef VK_EXT_robustness2
-#endif
-#ifdef VK_EXT_custom_border_color
-#endif
-#ifdef VK_EXT_private_data
-#endif
-#ifdef VK_EXT_pipeline_creation_cache_control
-#endif
-#ifdef VK_EXT_metal_objects
-#endif
-#ifdef VK_EXT_graphics_pipeline_library
-#endif
-#ifdef VK_EXT_ycbcr_2plane_444_formats
-#endif
-#ifdef VK_EXT_image_robustness
-#endif
-#ifdef VK_EXT_image_compression_control
-#endif
-#ifdef VK_EXT_4444_formats
-#endif
-#ifdef VK_EXT_primitive_topology_list_restart
-#endif
-#ifdef VK_EXT_extended_dynamic_state2
-#endif
-#ifdef VK_EXT_color_write_enable
-#endif
-#ifdef VK_GOOGLE_gfxstream
-#endif
-#ifdef VK_EXT_load_store_op_none
-#endif
-#ifdef VK_EXT_image_compression_control_swapchain
-#endif
-#ifdef VK_QNX_external_memory_screen_buffer
-#endif
-
 }  // namespace vk
 }  // namespace gfxstream
diff --git a/host/vulkan/cereal/common/goldfish_vk_marshaling.cpp b/host/vulkan/cereal/common/goldfish_vk_marshaling.cpp
index f981ca7..0cfedea 100644
--- a/host/vulkan/cereal/common/goldfish_vk_marshaling.cpp
+++ b/host/vulkan/cereal/common/goldfish_vk_marshaling.cpp
@@ -13430,8 +13430,6 @@
 }
 
 #endif
-#ifdef VK_KHR_surface
-#endif
 #ifdef VK_KHR_swapchain
 void marshal_VkSwapchainCreateInfoKHR(VulkanStream* vkStream, VkStructureType rootType,
                                       const VkSwapchainCreateInfoKHR* forMarshaling) {
@@ -13886,12 +13884,6 @@
 }
 
 #endif
-#ifdef VK_KHR_xcb_surface
-#endif
-#ifdef VK_KHR_android_surface
-#endif
-#ifdef VK_KHR_win32_surface
-#endif
 #ifdef VK_KHR_dynamic_rendering
 void marshal_VkRenderingFragmentShadingRateAttachmentInfoKHR(
     VulkanStream* vkStream, VkStructureType rootType,
@@ -14079,24 +14071,6 @@
 }
 
 #endif
-#ifdef VK_KHR_get_physical_device_properties2
-#endif
-#ifdef VK_KHR_maintenance1
-#endif
-#ifdef VK_KHR_external_memory_capabilities
-#endif
-#ifdef VK_KHR_external_memory
-#endif
-#ifdef VK_KHR_external_memory_win32
-#endif
-#ifdef VK_KHR_external_memory_fd
-#endif
-#ifdef VK_KHR_external_semaphore_capabilities
-#endif
-#ifdef VK_KHR_external_semaphore
-#endif
-#ifdef VK_KHR_external_semaphore_win32
-#endif
 #ifdef VK_KHR_external_semaphore_fd
 void marshal_VkImportSemaphoreFdInfoKHR(VulkanStream* vkStream, VkStructureType rootType,
                                         const VkImportSemaphoreFdInfoKHR* forMarshaling) {
@@ -14192,8 +14166,6 @@
 }
 
 #endif
-#ifdef VK_KHR_shader_float16_int8
-#endif
 #ifdef VK_KHR_incremental_present
 void marshal_VkRectLayerKHR(VulkanStream* vkStream, VkStructureType rootType,
                             const VkRectLayerKHR* forMarshaling) {
@@ -14304,16 +14276,6 @@
 }
 
 #endif
-#ifdef VK_KHR_descriptor_update_template
-#endif
-#ifdef VK_KHR_imageless_framebuffer
-#endif
-#ifdef VK_KHR_create_renderpass2
-#endif
-#ifdef VK_KHR_external_fence_capabilities
-#endif
-#ifdef VK_KHR_external_fence
-#endif
 #ifdef VK_KHR_external_fence_fd
 void marshal_VkImportFenceFdInfoKHR(VulkanStream* vkStream, VkStructureType rootType,
                                     const VkImportFenceFdInfoKHR* forMarshaling) {
@@ -14406,30 +14368,6 @@
 }
 
 #endif
-#ifdef VK_KHR_maintenance2
-#endif
-#ifdef VK_KHR_dedicated_allocation
-#endif
-#ifdef VK_KHR_storage_buffer_storage_class
-#endif
-#ifdef VK_KHR_get_memory_requirements2
-#endif
-#ifdef VK_KHR_image_format_list
-#endif
-#ifdef VK_KHR_sampler_ycbcr_conversion
-#endif
-#ifdef VK_KHR_bind_memory2
-#endif
-#ifdef VK_KHR_maintenance3
-#endif
-#ifdef VK_KHR_shader_subgroup_extended_types
-#endif
-#ifdef VK_KHR_vulkan_memory_model
-#endif
-#ifdef VK_KHR_shader_terminate_invocation
-#endif
-#ifdef VK_KHR_buffer_device_address
-#endif
 #ifdef VK_KHR_pipeline_executable_properties
 void marshal_VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR(
     VulkanStream* vkStream, VkStructureType rootType,
@@ -14705,9 +14643,57 @@
 }
 
 #endif
-#ifdef VK_KHR_shader_integer_dot_product
-#endif
-#ifdef VK_KHR_shader_non_semantic_info
+#ifdef VK_KHR_pipeline_library
+void marshal_VkPipelineLibraryCreateInfoKHR(VulkanStream* vkStream, VkStructureType rootType,
+                                            const VkPipelineLibraryCreateInfoKHR* forMarshaling) {
+    (void)rootType;
+    vkStream->write((VkStructureType*)&forMarshaling->sType, sizeof(VkStructureType));
+    if (rootType == VK_STRUCTURE_TYPE_MAX_ENUM) {
+        rootType = forMarshaling->sType;
+    }
+    marshal_extension_struct(vkStream, rootType, forMarshaling->pNext);
+    vkStream->write((uint32_t*)&forMarshaling->libraryCount, sizeof(uint32_t));
+    if (forMarshaling->libraryCount) {
+        uint64_t* cgen_var_0;
+        vkStream->alloc((void**)&cgen_var_0, forMarshaling->libraryCount * 8);
+        vkStream->handleMapping()->mapHandles_VkPipeline_u64(forMarshaling->pLibraries, cgen_var_0,
+                                                             forMarshaling->libraryCount);
+        vkStream->write((uint64_t*)cgen_var_0, forMarshaling->libraryCount * 8);
+    }
+}
+
+void unmarshal_VkPipelineLibraryCreateInfoKHR(VulkanStream* vkStream, VkStructureType rootType,
+                                              VkPipelineLibraryCreateInfoKHR* forUnmarshaling) {
+    (void)rootType;
+    vkStream->read((VkStructureType*)&forUnmarshaling->sType, sizeof(VkStructureType));
+    if (rootType == VK_STRUCTURE_TYPE_MAX_ENUM) {
+        rootType = forUnmarshaling->sType;
+    }
+    size_t pNext_size;
+    pNext_size = vkStream->getBe32();
+    forUnmarshaling->pNext = nullptr;
+    if (pNext_size) {
+        vkStream->alloc((void**)&forUnmarshaling->pNext, sizeof(VkStructureType));
+        vkStream->read((void*)forUnmarshaling->pNext, sizeof(VkStructureType));
+        VkStructureType extType = *(VkStructureType*)(forUnmarshaling->pNext);
+        vkStream->alloc((void**)&forUnmarshaling->pNext,
+                        goldfish_vk_extension_struct_size_with_stream_features(
+                            vkStream->getFeatureBits(), rootType, forUnmarshaling->pNext));
+        *(VkStructureType*)forUnmarshaling->pNext = extType;
+        unmarshal_extension_struct(vkStream, rootType, (void*)(forUnmarshaling->pNext));
+    }
+    vkStream->read((uint32_t*)&forUnmarshaling->libraryCount, sizeof(uint32_t));
+    vkStream->alloc((void**)&forUnmarshaling->pLibraries,
+                    forUnmarshaling->libraryCount * sizeof(const VkPipeline));
+    if (forUnmarshaling->libraryCount) {
+        uint64_t* cgen_var_0;
+        vkStream->alloc((void**)&cgen_var_0, forUnmarshaling->libraryCount * 8);
+        vkStream->read((uint64_t*)cgen_var_0, forUnmarshaling->libraryCount * 8);
+        vkStream->handleMapping()->mapHandles_u64_VkPipeline(
+            cgen_var_0, (VkPipeline*)forUnmarshaling->pLibraries, forUnmarshaling->libraryCount);
+    }
+}
+
 #endif
 #ifdef VK_KHR_synchronization2
 void marshal_VkQueueFamilyCheckpointProperties2NV(
@@ -14795,14 +14781,6 @@
 }
 
 #endif
-#ifdef VK_KHR_zero_initialize_workgroup_memory
-#endif
-#ifdef VK_KHR_copy_commands2
-#endif
-#ifdef VK_KHR_format_feature_flags2
-#endif
-#ifdef VK_KHR_maintenance4
-#endif
 #ifdef VK_KHR_maintenance5
 void marshal_VkPhysicalDeviceMaintenance5FeaturesKHR(
     VulkanStream* vkStream, VkStructureType rootType,
@@ -15481,10 +15459,6 @@
 }
 
 #endif
-#ifdef VK_AMD_gpu_shader_half_float
-#endif
-#ifdef VK_EXT_texture_compression_astc_hdr
-#endif
 #ifdef VK_EXT_depth_clip_enable
 void marshal_VkPhysicalDeviceDepthClipEnableFeaturesEXT(
     VulkanStream* vkStream, VkStructureType rootType,
@@ -15563,10 +15537,6 @@
 }
 
 #endif
-#ifdef VK_EXT_swapchain_colorspace
-#endif
-#ifdef VK_EXT_queue_family_foreign
-#endif
 #ifdef VK_EXT_debug_utils
 void marshal_VkDebugUtilsLabelEXT(VulkanStream* vkStream, VkStructureType rootType,
                                   const VkDebugUtilsLabelEXT* forMarshaling) {
@@ -15879,12 +15849,6 @@
 }
 
 #endif
-#ifdef VK_ANDROID_external_memory_android_hardware_buffer
-#endif
-#ifdef VK_EXT_inline_uniform_block
-#endif
-#ifdef VK_EXT_shader_stencil_export
-#endif
 #ifdef VK_EXT_vertex_attribute_divisor
 void marshal_VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT(
     VulkanStream* vkStream, VkStructureType rootType,
@@ -16038,12 +16002,6 @@
 }
 
 #endif
-#ifdef VK_EXT_pipeline_creation_feedback
-#endif
-#ifdef VK_NV_shader_subgroup_partitioned
-#endif
-#ifdef VK_EXT_metal_surface
-#endif
 #ifdef VK_EXT_fragment_density_map
 void marshal_VkPhysicalDeviceFragmentDensityMapFeaturesEXT(
     VulkanStream* vkStream, VkStructureType rootType,
@@ -16174,12 +16132,6 @@
 }
 
 #endif
-#ifdef VK_EXT_scalar_block_layout
-#endif
-#ifdef VK_EXT_subgroup_size_control
-#endif
-#ifdef VK_EXT_tooling_info
-#endif
 #ifdef VK_EXT_validation_features
 void marshal_VkValidationFeaturesEXT(VulkanStream* vkStream, VkStructureType rootType,
                                      const VkValidationFeaturesEXT* forMarshaling) {
@@ -17345,8 +17297,6 @@
 }
 
 #endif
-#ifdef VK_EXT_shader_demote_to_helper_invocation
-#endif
 #ifdef VK_EXT_texel_buffer_alignment
 void marshal_VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT(
     VulkanStream* vkStream, VkStructureType rootType,
@@ -17719,12 +17669,6 @@
 }
 
 #endif
-#ifdef VK_EXT_private_data
-#endif
-#ifdef VK_EXT_pipeline_creation_cache_control
-#endif
-#ifdef VK_EXT_metal_objects
-#endif
 #ifdef VK_EXT_graphics_pipeline_library
 void marshal_VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT(
     VulkanStream* vkStream, VkStructureType rootType,
@@ -17883,8 +17827,6 @@
 }
 
 #endif
-#ifdef VK_EXT_image_robustness
-#endif
 #ifdef VK_EXT_image_compression_control
 void marshal_VkPhysicalDeviceImageCompressionControlFeaturesEXT(
     VulkanStream* vkStream, VkStructureType rootType,
@@ -18338,8 +18280,6 @@
 }
 
 #endif
-#ifdef VK_EXT_load_store_op_none
-#endif
 #ifdef VK_EXT_image_compression_control_swapchain
 void marshal_VkPhysicalDeviceImageCompressionControlSwapchainFeaturesEXT(
     VulkanStream* vkStream, VkStructureType rootType,
@@ -18378,7 +18318,388 @@
 }
 
 #endif
-#ifdef VK_QNX_external_memory_screen_buffer
+#ifdef VK_KHR_ray_tracing_pipeline
+void marshal_VkRayTracingShaderGroupCreateInfoKHR(
+    VulkanStream* vkStream, VkStructureType rootType,
+    const VkRayTracingShaderGroupCreateInfoKHR* forMarshaling) {
+    (void)rootType;
+    vkStream->write((VkStructureType*)&forMarshaling->sType, sizeof(VkStructureType));
+    if (rootType == VK_STRUCTURE_TYPE_MAX_ENUM) {
+        rootType = forMarshaling->sType;
+    }
+    marshal_extension_struct(vkStream, rootType, forMarshaling->pNext);
+    vkStream->write((VkRayTracingShaderGroupTypeKHR*)&forMarshaling->type,
+                    sizeof(VkRayTracingShaderGroupTypeKHR));
+    vkStream->write((uint32_t*)&forMarshaling->generalShader, sizeof(uint32_t));
+    vkStream->write((uint32_t*)&forMarshaling->closestHitShader, sizeof(uint32_t));
+    vkStream->write((uint32_t*)&forMarshaling->anyHitShader, sizeof(uint32_t));
+    vkStream->write((uint32_t*)&forMarshaling->intersectionShader, sizeof(uint32_t));
+    // WARNING PTR CHECK
+    uint64_t cgen_var_0 = (uint64_t)(uintptr_t)forMarshaling->pShaderGroupCaptureReplayHandle;
+    vkStream->putBe64(cgen_var_0);
+    if (forMarshaling->pShaderGroupCaptureReplayHandle) {
+        vkStream->write((const void*)forMarshaling->pShaderGroupCaptureReplayHandle,
+                        sizeof(const uint8_t));
+    }
+}
+
+void unmarshal_VkRayTracingShaderGroupCreateInfoKHR(
+    VulkanStream* vkStream, VkStructureType rootType,
+    VkRayTracingShaderGroupCreateInfoKHR* forUnmarshaling) {
+    (void)rootType;
+    vkStream->read((VkStructureType*)&forUnmarshaling->sType, sizeof(VkStructureType));
+    if (rootType == VK_STRUCTURE_TYPE_MAX_ENUM) {
+        rootType = forUnmarshaling->sType;
+    }
+    size_t pNext_size;
+    pNext_size = vkStream->getBe32();
+    forUnmarshaling->pNext = nullptr;
+    if (pNext_size) {
+        vkStream->alloc((void**)&forUnmarshaling->pNext, sizeof(VkStructureType));
+        vkStream->read((void*)forUnmarshaling->pNext, sizeof(VkStructureType));
+        VkStructureType extType = *(VkStructureType*)(forUnmarshaling->pNext);
+        vkStream->alloc((void**)&forUnmarshaling->pNext,
+                        goldfish_vk_extension_struct_size_with_stream_features(
+                            vkStream->getFeatureBits(), rootType, forUnmarshaling->pNext));
+        *(VkStructureType*)forUnmarshaling->pNext = extType;
+        unmarshal_extension_struct(vkStream, rootType, (void*)(forUnmarshaling->pNext));
+    }
+    vkStream->read((VkRayTracingShaderGroupTypeKHR*)&forUnmarshaling->type,
+                   sizeof(VkRayTracingShaderGroupTypeKHR));
+    vkStream->read((uint32_t*)&forUnmarshaling->generalShader, sizeof(uint32_t));
+    vkStream->read((uint32_t*)&forUnmarshaling->closestHitShader, sizeof(uint32_t));
+    vkStream->read((uint32_t*)&forUnmarshaling->anyHitShader, sizeof(uint32_t));
+    vkStream->read((uint32_t*)&forUnmarshaling->intersectionShader, sizeof(uint32_t));
+    // WARNING PTR CHECK
+    forUnmarshaling->pShaderGroupCaptureReplayHandle = (const void*)(uintptr_t)vkStream->getBe64();
+    if (forUnmarshaling->pShaderGroupCaptureReplayHandle) {
+        vkStream->alloc((void**)&forUnmarshaling->pShaderGroupCaptureReplayHandle,
+                        sizeof(const uint8_t));
+        vkStream->read((void*)forUnmarshaling->pShaderGroupCaptureReplayHandle,
+                       sizeof(const uint8_t));
+    }
+}
+
+void marshal_VkRayTracingPipelineInterfaceCreateInfoKHR(
+    VulkanStream* vkStream, VkStructureType rootType,
+    const VkRayTracingPipelineInterfaceCreateInfoKHR* forMarshaling) {
+    (void)rootType;
+    vkStream->write((VkStructureType*)&forMarshaling->sType, sizeof(VkStructureType));
+    if (rootType == VK_STRUCTURE_TYPE_MAX_ENUM) {
+        rootType = forMarshaling->sType;
+    }
+    marshal_extension_struct(vkStream, rootType, forMarshaling->pNext);
+    vkStream->write((uint32_t*)&forMarshaling->maxPipelineRayPayloadSize, sizeof(uint32_t));
+    vkStream->write((uint32_t*)&forMarshaling->maxPipelineRayHitAttributeSize, sizeof(uint32_t));
+}
+
+void unmarshal_VkRayTracingPipelineInterfaceCreateInfoKHR(
+    VulkanStream* vkStream, VkStructureType rootType,
+    VkRayTracingPipelineInterfaceCreateInfoKHR* forUnmarshaling) {
+    (void)rootType;
+    vkStream->read((VkStructureType*)&forUnmarshaling->sType, sizeof(VkStructureType));
+    if (rootType == VK_STRUCTURE_TYPE_MAX_ENUM) {
+        rootType = forUnmarshaling->sType;
+    }
+    size_t pNext_size;
+    pNext_size = vkStream->getBe32();
+    forUnmarshaling->pNext = nullptr;
+    if (pNext_size) {
+        vkStream->alloc((void**)&forUnmarshaling->pNext, sizeof(VkStructureType));
+        vkStream->read((void*)forUnmarshaling->pNext, sizeof(VkStructureType));
+        VkStructureType extType = *(VkStructureType*)(forUnmarshaling->pNext);
+        vkStream->alloc((void**)&forUnmarshaling->pNext,
+                        goldfish_vk_extension_struct_size_with_stream_features(
+                            vkStream->getFeatureBits(), rootType, forUnmarshaling->pNext));
+        *(VkStructureType*)forUnmarshaling->pNext = extType;
+        unmarshal_extension_struct(vkStream, rootType, (void*)(forUnmarshaling->pNext));
+    }
+    vkStream->read((uint32_t*)&forUnmarshaling->maxPipelineRayPayloadSize, sizeof(uint32_t));
+    vkStream->read((uint32_t*)&forUnmarshaling->maxPipelineRayHitAttributeSize, sizeof(uint32_t));
+}
+
+void marshal_VkRayTracingPipelineCreateInfoKHR(
+    VulkanStream* vkStream, VkStructureType rootType,
+    const VkRayTracingPipelineCreateInfoKHR* forMarshaling) {
+    (void)rootType;
+    vkStream->write((VkStructureType*)&forMarshaling->sType, sizeof(VkStructureType));
+    if (rootType == VK_STRUCTURE_TYPE_MAX_ENUM) {
+        rootType = forMarshaling->sType;
+    }
+    marshal_extension_struct(vkStream, rootType, forMarshaling->pNext);
+    vkStream->write((VkPipelineCreateFlags*)&forMarshaling->flags, sizeof(VkPipelineCreateFlags));
+    vkStream->write((uint32_t*)&forMarshaling->stageCount, sizeof(uint32_t));
+    if (forMarshaling) {
+        for (uint32_t i = 0; i < (uint32_t)forMarshaling->stageCount; ++i) {
+            marshal_VkPipelineShaderStageCreateInfo(
+                vkStream, rootType,
+                (const VkPipelineShaderStageCreateInfo*)(forMarshaling->pStages + i));
+        }
+    }
+    vkStream->write((uint32_t*)&forMarshaling->groupCount, sizeof(uint32_t));
+    if (forMarshaling) {
+        for (uint32_t i = 0; i < (uint32_t)forMarshaling->groupCount; ++i) {
+            marshal_VkRayTracingShaderGroupCreateInfoKHR(
+                vkStream, rootType,
+                (const VkRayTracingShaderGroupCreateInfoKHR*)(forMarshaling->pGroups + i));
+        }
+    }
+    vkStream->write((uint32_t*)&forMarshaling->maxPipelineRayRecursionDepth, sizeof(uint32_t));
+    // WARNING PTR CHECK
+    uint64_t cgen_var_0 = (uint64_t)(uintptr_t)forMarshaling->pLibraryInfo;
+    vkStream->putBe64(cgen_var_0);
+    if (forMarshaling->pLibraryInfo) {
+        marshal_VkPipelineLibraryCreateInfoKHR(
+            vkStream, rootType,
+            (const VkPipelineLibraryCreateInfoKHR*)(forMarshaling->pLibraryInfo));
+    }
+    // WARNING PTR CHECK
+    uint64_t cgen_var_1 = (uint64_t)(uintptr_t)forMarshaling->pLibraryInterface;
+    vkStream->putBe64(cgen_var_1);
+    if (forMarshaling->pLibraryInterface) {
+        marshal_VkRayTracingPipelineInterfaceCreateInfoKHR(
+            vkStream, rootType,
+            (const VkRayTracingPipelineInterfaceCreateInfoKHR*)(forMarshaling->pLibraryInterface));
+    }
+    // WARNING PTR CHECK
+    uint64_t cgen_var_2 = (uint64_t)(uintptr_t)forMarshaling->pDynamicState;
+    vkStream->putBe64(cgen_var_2);
+    if (forMarshaling->pDynamicState) {
+        marshal_VkPipelineDynamicStateCreateInfo(
+            vkStream, rootType,
+            (const VkPipelineDynamicStateCreateInfo*)(forMarshaling->pDynamicState));
+    }
+    uint64_t cgen_var_3;
+    vkStream->handleMapping()->mapHandles_VkPipelineLayout_u64(&forMarshaling->layout, &cgen_var_3,
+                                                               1);
+    vkStream->write((uint64_t*)&cgen_var_3, 1 * 8);
+    uint64_t cgen_var_4;
+    vkStream->handleMapping()->mapHandles_VkPipeline_u64(&forMarshaling->basePipelineHandle,
+                                                         &cgen_var_4, 1);
+    vkStream->write((uint64_t*)&cgen_var_4, 1 * 8);
+    vkStream->write((int32_t*)&forMarshaling->basePipelineIndex, sizeof(int32_t));
+}
+
+void unmarshal_VkRayTracingPipelineCreateInfoKHR(
+    VulkanStream* vkStream, VkStructureType rootType,
+    VkRayTracingPipelineCreateInfoKHR* forUnmarshaling) {
+    (void)rootType;
+    vkStream->read((VkStructureType*)&forUnmarshaling->sType, sizeof(VkStructureType));
+    if (rootType == VK_STRUCTURE_TYPE_MAX_ENUM) {
+        rootType = forUnmarshaling->sType;
+    }
+    size_t pNext_size;
+    pNext_size = vkStream->getBe32();
+    forUnmarshaling->pNext = nullptr;
+    if (pNext_size) {
+        vkStream->alloc((void**)&forUnmarshaling->pNext, sizeof(VkStructureType));
+        vkStream->read((void*)forUnmarshaling->pNext, sizeof(VkStructureType));
+        VkStructureType extType = *(VkStructureType*)(forUnmarshaling->pNext);
+        vkStream->alloc((void**)&forUnmarshaling->pNext,
+                        goldfish_vk_extension_struct_size_with_stream_features(
+                            vkStream->getFeatureBits(), rootType, forUnmarshaling->pNext));
+        *(VkStructureType*)forUnmarshaling->pNext = extType;
+        unmarshal_extension_struct(vkStream, rootType, (void*)(forUnmarshaling->pNext));
+    }
+    vkStream->read((VkPipelineCreateFlags*)&forUnmarshaling->flags, sizeof(VkPipelineCreateFlags));
+    vkStream->read((uint32_t*)&forUnmarshaling->stageCount, sizeof(uint32_t));
+    vkStream->alloc((void**)&forUnmarshaling->pStages,
+                    forUnmarshaling->stageCount * sizeof(const VkPipelineShaderStageCreateInfo));
+    if (forUnmarshaling) {
+        for (uint32_t i = 0; i < (uint32_t)forUnmarshaling->stageCount; ++i) {
+            unmarshal_VkPipelineShaderStageCreateInfo(
+                vkStream, rootType,
+                (VkPipelineShaderStageCreateInfo*)(forUnmarshaling->pStages + i));
+        }
+    }
+    vkStream->read((uint32_t*)&forUnmarshaling->groupCount, sizeof(uint32_t));
+    vkStream->alloc(
+        (void**)&forUnmarshaling->pGroups,
+        forUnmarshaling->groupCount * sizeof(const VkRayTracingShaderGroupCreateInfoKHR));
+    if (forUnmarshaling) {
+        for (uint32_t i = 0; i < (uint32_t)forUnmarshaling->groupCount; ++i) {
+            unmarshal_VkRayTracingShaderGroupCreateInfoKHR(
+                vkStream, rootType,
+                (VkRayTracingShaderGroupCreateInfoKHR*)(forUnmarshaling->pGroups + i));
+        }
+    }
+    vkStream->read((uint32_t*)&forUnmarshaling->maxPipelineRayRecursionDepth, sizeof(uint32_t));
+    // WARNING PTR CHECK
+    forUnmarshaling->pLibraryInfo =
+        (const VkPipelineLibraryCreateInfoKHR*)(uintptr_t)vkStream->getBe64();
+    if (forUnmarshaling->pLibraryInfo) {
+        vkStream->alloc((void**)&forUnmarshaling->pLibraryInfo,
+                        sizeof(const VkPipelineLibraryCreateInfoKHR));
+        unmarshal_VkPipelineLibraryCreateInfoKHR(
+            vkStream, rootType, (VkPipelineLibraryCreateInfoKHR*)(forUnmarshaling->pLibraryInfo));
+    }
+    // WARNING PTR CHECK
+    forUnmarshaling->pLibraryInterface =
+        (const VkRayTracingPipelineInterfaceCreateInfoKHR*)(uintptr_t)vkStream->getBe64();
+    if (forUnmarshaling->pLibraryInterface) {
+        vkStream->alloc((void**)&forUnmarshaling->pLibraryInterface,
+                        sizeof(const VkRayTracingPipelineInterfaceCreateInfoKHR));
+        unmarshal_VkRayTracingPipelineInterfaceCreateInfoKHR(
+            vkStream, rootType,
+            (VkRayTracingPipelineInterfaceCreateInfoKHR*)(forUnmarshaling->pLibraryInterface));
+    }
+    // WARNING PTR CHECK
+    forUnmarshaling->pDynamicState =
+        (const VkPipelineDynamicStateCreateInfo*)(uintptr_t)vkStream->getBe64();
+    if (forUnmarshaling->pDynamicState) {
+        vkStream->alloc((void**)&forUnmarshaling->pDynamicState,
+                        sizeof(const VkPipelineDynamicStateCreateInfo));
+        unmarshal_VkPipelineDynamicStateCreateInfo(
+            vkStream, rootType,
+            (VkPipelineDynamicStateCreateInfo*)(forUnmarshaling->pDynamicState));
+    }
+    uint64_t cgen_var_3;
+    vkStream->read((uint64_t*)&cgen_var_3, 1 * 8);
+    vkStream->handleMapping()->mapHandles_u64_VkPipelineLayout(
+        &cgen_var_3, (VkPipelineLayout*)&forUnmarshaling->layout, 1);
+    uint64_t cgen_var_4;
+    vkStream->read((uint64_t*)&cgen_var_4, 1 * 8);
+    vkStream->handleMapping()->mapHandles_u64_VkPipeline(
+        &cgen_var_4, (VkPipeline*)&forUnmarshaling->basePipelineHandle, 1);
+    vkStream->read((int32_t*)&forUnmarshaling->basePipelineIndex, sizeof(int32_t));
+}
+
+void marshal_VkPhysicalDeviceRayTracingPipelineFeaturesKHR(
+    VulkanStream* vkStream, VkStructureType rootType,
+    const VkPhysicalDeviceRayTracingPipelineFeaturesKHR* forMarshaling) {
+    (void)rootType;
+    vkStream->write((VkStructureType*)&forMarshaling->sType, sizeof(VkStructureType));
+    if (rootType == VK_STRUCTURE_TYPE_MAX_ENUM) {
+        rootType = forMarshaling->sType;
+    }
+    marshal_extension_struct(vkStream, rootType, forMarshaling->pNext);
+    vkStream->write((VkBool32*)&forMarshaling->rayTracingPipeline, sizeof(VkBool32));
+    vkStream->write((VkBool32*)&forMarshaling->rayTracingPipelineShaderGroupHandleCaptureReplay,
+                    sizeof(VkBool32));
+    vkStream->write(
+        (VkBool32*)&forMarshaling->rayTracingPipelineShaderGroupHandleCaptureReplayMixed,
+        sizeof(VkBool32));
+    vkStream->write((VkBool32*)&forMarshaling->rayTracingPipelineTraceRaysIndirect,
+                    sizeof(VkBool32));
+    vkStream->write((VkBool32*)&forMarshaling->rayTraversalPrimitiveCulling, sizeof(VkBool32));
+}
+
+void unmarshal_VkPhysicalDeviceRayTracingPipelineFeaturesKHR(
+    VulkanStream* vkStream, VkStructureType rootType,
+    VkPhysicalDeviceRayTracingPipelineFeaturesKHR* forUnmarshaling) {
+    (void)rootType;
+    vkStream->read((VkStructureType*)&forUnmarshaling->sType, sizeof(VkStructureType));
+    if (rootType == VK_STRUCTURE_TYPE_MAX_ENUM) {
+        rootType = forUnmarshaling->sType;
+    }
+    size_t pNext_size;
+    pNext_size = vkStream->getBe32();
+    forUnmarshaling->pNext = nullptr;
+    if (pNext_size) {
+        vkStream->alloc((void**)&forUnmarshaling->pNext, sizeof(VkStructureType));
+        vkStream->read((void*)forUnmarshaling->pNext, sizeof(VkStructureType));
+        VkStructureType extType = *(VkStructureType*)(forUnmarshaling->pNext);
+        vkStream->alloc((void**)&forUnmarshaling->pNext,
+                        goldfish_vk_extension_struct_size_with_stream_features(
+                            vkStream->getFeatureBits(), rootType, forUnmarshaling->pNext));
+        *(VkStructureType*)forUnmarshaling->pNext = extType;
+        unmarshal_extension_struct(vkStream, rootType, (void*)(forUnmarshaling->pNext));
+    }
+    vkStream->read((VkBool32*)&forUnmarshaling->rayTracingPipeline, sizeof(VkBool32));
+    vkStream->read((VkBool32*)&forUnmarshaling->rayTracingPipelineShaderGroupHandleCaptureReplay,
+                   sizeof(VkBool32));
+    vkStream->read(
+        (VkBool32*)&forUnmarshaling->rayTracingPipelineShaderGroupHandleCaptureReplayMixed,
+        sizeof(VkBool32));
+    vkStream->read((VkBool32*)&forUnmarshaling->rayTracingPipelineTraceRaysIndirect,
+                   sizeof(VkBool32));
+    vkStream->read((VkBool32*)&forUnmarshaling->rayTraversalPrimitiveCulling, sizeof(VkBool32));
+}
+
+void marshal_VkPhysicalDeviceRayTracingPipelinePropertiesKHR(
+    VulkanStream* vkStream, VkStructureType rootType,
+    const VkPhysicalDeviceRayTracingPipelinePropertiesKHR* forMarshaling) {
+    (void)rootType;
+    vkStream->write((VkStructureType*)&forMarshaling->sType, sizeof(VkStructureType));
+    if (rootType == VK_STRUCTURE_TYPE_MAX_ENUM) {
+        rootType = forMarshaling->sType;
+    }
+    marshal_extension_struct(vkStream, rootType, forMarshaling->pNext);
+    vkStream->write((uint32_t*)&forMarshaling->shaderGroupHandleSize, sizeof(uint32_t));
+    vkStream->write((uint32_t*)&forMarshaling->maxRayRecursionDepth, sizeof(uint32_t));
+    vkStream->write((uint32_t*)&forMarshaling->maxShaderGroupStride, sizeof(uint32_t));
+    vkStream->write((uint32_t*)&forMarshaling->shaderGroupBaseAlignment, sizeof(uint32_t));
+    vkStream->write((uint32_t*)&forMarshaling->shaderGroupHandleCaptureReplaySize,
+                    sizeof(uint32_t));
+    vkStream->write((uint32_t*)&forMarshaling->maxRayDispatchInvocationCount, sizeof(uint32_t));
+    vkStream->write((uint32_t*)&forMarshaling->shaderGroupHandleAlignment, sizeof(uint32_t));
+    vkStream->write((uint32_t*)&forMarshaling->maxRayHitAttributeSize, sizeof(uint32_t));
+}
+
+void unmarshal_VkPhysicalDeviceRayTracingPipelinePropertiesKHR(
+    VulkanStream* vkStream, VkStructureType rootType,
+    VkPhysicalDeviceRayTracingPipelinePropertiesKHR* forUnmarshaling) {
+    (void)rootType;
+    vkStream->read((VkStructureType*)&forUnmarshaling->sType, sizeof(VkStructureType));
+    if (rootType == VK_STRUCTURE_TYPE_MAX_ENUM) {
+        rootType = forUnmarshaling->sType;
+    }
+    size_t pNext_size;
+    pNext_size = vkStream->getBe32();
+    forUnmarshaling->pNext = nullptr;
+    if (pNext_size) {
+        vkStream->alloc((void**)&forUnmarshaling->pNext, sizeof(VkStructureType));
+        vkStream->read((void*)forUnmarshaling->pNext, sizeof(VkStructureType));
+        VkStructureType extType = *(VkStructureType*)(forUnmarshaling->pNext);
+        vkStream->alloc((void**)&forUnmarshaling->pNext,
+                        goldfish_vk_extension_struct_size_with_stream_features(
+                            vkStream->getFeatureBits(), rootType, forUnmarshaling->pNext));
+        *(VkStructureType*)forUnmarshaling->pNext = extType;
+        unmarshal_extension_struct(vkStream, rootType, (void*)(forUnmarshaling->pNext));
+    }
+    vkStream->read((uint32_t*)&forUnmarshaling->shaderGroupHandleSize, sizeof(uint32_t));
+    vkStream->read((uint32_t*)&forUnmarshaling->maxRayRecursionDepth, sizeof(uint32_t));
+    vkStream->read((uint32_t*)&forUnmarshaling->maxShaderGroupStride, sizeof(uint32_t));
+    vkStream->read((uint32_t*)&forUnmarshaling->shaderGroupBaseAlignment, sizeof(uint32_t));
+    vkStream->read((uint32_t*)&forUnmarshaling->shaderGroupHandleCaptureReplaySize,
+                   sizeof(uint32_t));
+    vkStream->read((uint32_t*)&forUnmarshaling->maxRayDispatchInvocationCount, sizeof(uint32_t));
+    vkStream->read((uint32_t*)&forUnmarshaling->shaderGroupHandleAlignment, sizeof(uint32_t));
+    vkStream->read((uint32_t*)&forUnmarshaling->maxRayHitAttributeSize, sizeof(uint32_t));
+}
+
+void marshal_VkStridedDeviceAddressRegionKHR(VulkanStream* vkStream, VkStructureType rootType,
+                                             const VkStridedDeviceAddressRegionKHR* forMarshaling) {
+    (void)rootType;
+    vkStream->write((VkDeviceAddress*)&forMarshaling->deviceAddress, sizeof(VkDeviceAddress));
+    vkStream->write((VkDeviceSize*)&forMarshaling->stride, sizeof(VkDeviceSize));
+    vkStream->write((VkDeviceSize*)&forMarshaling->size, sizeof(VkDeviceSize));
+}
+
+void unmarshal_VkStridedDeviceAddressRegionKHR(VulkanStream* vkStream, VkStructureType rootType,
+                                               VkStridedDeviceAddressRegionKHR* forUnmarshaling) {
+    (void)rootType;
+    vkStream->read((VkDeviceAddress*)&forUnmarshaling->deviceAddress, sizeof(VkDeviceAddress));
+    vkStream->read((VkDeviceSize*)&forUnmarshaling->stride, sizeof(VkDeviceSize));
+    vkStream->read((VkDeviceSize*)&forUnmarshaling->size, sizeof(VkDeviceSize));
+}
+
+void marshal_VkTraceRaysIndirectCommandKHR(VulkanStream* vkStream, VkStructureType rootType,
+                                           const VkTraceRaysIndirectCommandKHR* forMarshaling) {
+    (void)rootType;
+    vkStream->write((uint32_t*)&forMarshaling->width, sizeof(uint32_t));
+    vkStream->write((uint32_t*)&forMarshaling->height, sizeof(uint32_t));
+    vkStream->write((uint32_t*)&forMarshaling->depth, sizeof(uint32_t));
+}
+
+void unmarshal_VkTraceRaysIndirectCommandKHR(VulkanStream* vkStream, VkStructureType rootType,
+                                             VkTraceRaysIndirectCommandKHR* forUnmarshaling) {
+    (void)rootType;
+    vkStream->read((uint32_t*)&forUnmarshaling->width, sizeof(uint32_t));
+    vkStream->read((uint32_t*)&forUnmarshaling->height, sizeof(uint32_t));
+    vkStream->read((uint32_t*)&forUnmarshaling->depth, sizeof(uint32_t));
+}
+
 #endif
 void marshal_extension_struct(VulkanStream* vkStream, VkStructureType rootType,
                               const void* structExtension) {
@@ -19159,6 +19480,14 @@
             break;
         }
 #endif
+#ifdef VK_KHR_pipeline_library
+        case VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR: {
+            marshal_VkPipelineLibraryCreateInfoKHR(
+                vkStream, rootType,
+                reinterpret_cast<const VkPipelineLibraryCreateInfoKHR*>(structExtension));
+            break;
+        }
+#endif
 #ifdef VK_KHR_synchronization2
         case VK_STRUCTURE_TYPE_QUEUE_FAMILY_CHECKPOINT_PROPERTIES_2_NV: {
             marshal_VkQueueFamilyCheckpointProperties2NV(
@@ -19690,6 +20019,22 @@
             break;
         }
 #endif
+#ifdef VK_KHR_ray_tracing_pipeline
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR: {
+            marshal_VkPhysicalDeviceRayTracingPipelineFeaturesKHR(
+                vkStream, rootType,
+                reinterpret_cast<const VkPhysicalDeviceRayTracingPipelineFeaturesKHR*>(
+                    structExtension));
+            break;
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR: {
+            marshal_VkPhysicalDeviceRayTracingPipelinePropertiesKHR(
+                vkStream, rootType,
+                reinterpret_cast<const VkPhysicalDeviceRayTracingPipelinePropertiesKHR*>(
+                    structExtension));
+            break;
+        }
+#endif
         default: {
             // fatal; the switch is only taken if the extension struct is known
             abort();
@@ -20465,6 +20810,14 @@
             break;
         }
 #endif
+#ifdef VK_KHR_pipeline_library
+        case VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR: {
+            unmarshal_VkPipelineLibraryCreateInfoKHR(
+                vkStream, rootType,
+                reinterpret_cast<VkPipelineLibraryCreateInfoKHR*>(structExtension_out));
+            break;
+        }
+#endif
 #ifdef VK_KHR_synchronization2
         case VK_STRUCTURE_TYPE_QUEUE_FAMILY_CHECKPOINT_PROPERTIES_2_NV: {
             unmarshal_VkQueueFamilyCheckpointProperties2NV(
@@ -20989,6 +21342,22 @@
             break;
         }
 #endif
+#ifdef VK_KHR_ray_tracing_pipeline
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR: {
+            unmarshal_VkPhysicalDeviceRayTracingPipelineFeaturesKHR(
+                vkStream, rootType,
+                reinterpret_cast<VkPhysicalDeviceRayTracingPipelineFeaturesKHR*>(
+                    structExtension_out));
+            break;
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR: {
+            unmarshal_VkPhysicalDeviceRayTracingPipelinePropertiesKHR(
+                vkStream, rootType,
+                reinterpret_cast<VkPhysicalDeviceRayTracingPipelinePropertiesKHR*>(
+                    structExtension_out));
+            break;
+        }
+#endif
         default: {
             // fatal; the switch is only taken if the extension struct is known
             abort();
@@ -21751,6 +22120,9 @@
         case OP_vkGetBlobGOOGLE: {
             return "OP_vkGetBlobGOOGLE";
         }
+        case OP_vkGetSemaphoreGOOGLE: {
+            return "OP_vkGetSemaphoreGOOGLE";
+        }
 #endif
 #ifdef VK_KHR_dynamic_rendering
         case OP_vkCmdEndRenderingKHR: {
@@ -21787,6 +22159,11 @@
             return "OP_vkCopyImageToMemoryEXT";
         }
 #endif
+#ifdef VK_KHR_ray_tracing_pipeline
+        case OP_vkGetRayTracingShaderGroupStackSizeKHR: {
+            return "OP_vkGetRayTracingShaderGroupStackSizeKHR";
+        }
+#endif
 #ifdef VK_EXT_extended_dynamic_state2
         case OP_vkCmdSetPatchControlPointsEXT: {
             return "OP_vkCmdSetPatchControlPointsEXT";
@@ -21802,6 +22179,11 @@
             return "OP_vkCmdSetDepthTestEnable";
         }
 #endif
+#ifdef VK_KHR_ray_tracing_pipeline
+        case OP_vkCmdTraceRaysIndirectKHR: {
+            return "OP_vkCmdTraceRaysIndirectKHR";
+        }
+#endif
 #ifdef VK_EXT_extended_dynamic_state
         case OP_vkCmdSetFrontFaceEXT: {
             return "OP_vkCmdSetFrontFaceEXT";
@@ -21812,6 +22194,11 @@
             return "OP_vkCollectDescriptorPoolIdsGOOGLE";
         }
 #endif
+#ifdef VK_KHR_ray_tracing_pipeline
+        case OP_vkCmdTraceRaysKHR: {
+            return "OP_vkCmdTraceRaysKHR";
+        }
+#endif
 #ifdef VK_VERSION_1_3
         case OP_vkCmdCopyImageToBuffer2: {
             return "OP_vkCmdCopyImageToBuffer2";
@@ -21847,6 +22234,13 @@
         case OP_vkCmdEndRenderPass2: {
             return "OP_vkCmdEndRenderPass2";
         }
+#endif
+#ifdef VK_KHR_ray_tracing_pipeline
+        case OP_vkGetRayTracingCaptureReplayShaderGroupHandlesKHR: {
+            return "OP_vkGetRayTracingCaptureReplayShaderGroupHandlesKHR";
+        }
+#endif
+#ifdef VK_VERSION_1_2
         case OP_vkGetBufferDeviceAddress: {
             return "OP_vkGetBufferDeviceAddress";
         }
@@ -22024,6 +22418,11 @@
             return "OP_vkCmdCopyImage2";
         }
 #endif
+#ifdef VK_KHR_ray_tracing_pipeline
+        case OP_vkCreateRayTracingPipelinesKHR: {
+            return "OP_vkCreateRayTracingPipelinesKHR";
+        }
+#endif
 #ifdef VK_EXT_extended_dynamic_state
         case OP_vkCmdSetDepthCompareOpEXT: {
             return "OP_vkCmdSetDepthCompareOpEXT";
@@ -22082,6 +22481,11 @@
             return "OP_vkCmdBlitImage2KHR";
         }
 #endif
+#ifdef VK_KHR_ray_tracing_pipeline
+        case OP_vkCmdSetRayTracingPipelineStackSizeKHR: {
+            return "OP_vkCmdSetRayTracingPipelineStackSizeKHR";
+        }
+#endif
 #ifdef VK_VERSION_1_2
         case OP_vkGetDeviceMemoryOpaqueCaptureAddress: {
             return "OP_vkGetDeviceMemoryOpaqueCaptureAddress";
diff --git a/host/vulkan/cereal/common/goldfish_vk_marshaling.h b/host/vulkan/cereal/common/goldfish_vk_marshaling.h
index 0a77003..ada18ae 100644
--- a/host/vulkan/cereal/common/goldfish_vk_marshaling.h
+++ b/host/vulkan/cereal/common/goldfish_vk_marshaling.h
@@ -2166,8 +2166,6 @@
 #define OP_vkGetDeviceImageMemoryRequirements 282480635
 #define OP_vkGetDeviceImageSparseMemoryRequirements 233707261
 #endif
-#ifdef VK_KHR_surface
-#endif
 #ifdef VK_KHR_swapchain
 void marshal_VkSwapchainCreateInfoKHR(VulkanStream* vkStream, VkStructureType rootType,
                                       const VkSwapchainCreateInfoKHR* forMarshaling);
@@ -2233,12 +2231,6 @@
 #define OP_vkGetPhysicalDevicePresentRectanglesKHR 20177
 #define OP_vkAcquireNextImage2KHR 20178
 #endif
-#ifdef VK_KHR_xcb_surface
-#endif
-#ifdef VK_KHR_android_surface
-#endif
-#ifdef VK_KHR_win32_surface
-#endif
 #ifdef VK_KHR_dynamic_rendering
 DEFINE_ALIAS_FUNCTION(marshal_VkRenderingInfo, marshal_VkRenderingInfoKHR)
 
@@ -2413,10 +2405,6 @@
 DEFINE_ALIAS_FUNCTION(unmarshal_VkExportMemoryAllocateInfo, unmarshal_VkExportMemoryAllocateInfoKHR)
 
 #endif
-#ifdef VK_KHR_external_memory_win32
-#endif
-#ifdef VK_KHR_external_memory_fd
-#endif
 #ifdef VK_KHR_external_semaphore_capabilities
 DEFINE_ALIAS_FUNCTION(marshal_VkPhysicalDeviceExternalSemaphoreInfo,
                       marshal_VkPhysicalDeviceExternalSemaphoreInfoKHR)
@@ -2439,8 +2427,6 @@
                       unmarshal_VkExportSemaphoreCreateInfoKHR)
 
 #endif
-#ifdef VK_KHR_external_semaphore_win32
-#endif
 #ifdef VK_KHR_external_semaphore_fd
 void marshal_VkImportSemaphoreFdInfoKHR(VulkanStream* vkStream, VkStructureType rootType,
                                         const VkImportSemaphoreFdInfoKHR* forMarshaling);
@@ -2647,8 +2633,6 @@
                       unmarshal_VkMemoryDedicatedAllocateInfoKHR)
 
 #endif
-#ifdef VK_KHR_storage_buffer_storage_class
-#endif
 #ifdef VK_KHR_get_memory_requirements2
 DEFINE_ALIAS_FUNCTION(marshal_VkBufferMemoryRequirementsInfo2,
                       marshal_VkBufferMemoryRequirementsInfo2KHR)
@@ -2879,7 +2863,13 @@
                       unmarshal_VkPhysicalDeviceShaderIntegerDotProductPropertiesKHR)
 
 #endif
-#ifdef VK_KHR_shader_non_semantic_info
+#ifdef VK_KHR_pipeline_library
+void marshal_VkPipelineLibraryCreateInfoKHR(VulkanStream* vkStream, VkStructureType rootType,
+                                            const VkPipelineLibraryCreateInfoKHR* forMarshaling);
+
+void unmarshal_VkPipelineLibraryCreateInfoKHR(VulkanStream* vkStream, VkStructureType rootType,
+                                              VkPipelineLibraryCreateInfoKHR* forUnmarshaling);
+
 #endif
 #ifdef VK_KHR_synchronization2
 DEFINE_ALIAS_FUNCTION(marshal_VkMemoryBarrier2, marshal_VkMemoryBarrier2KHR)
@@ -3174,8 +3164,6 @@
 #define OP_vkCmdEndQueryIndexedEXT 279821337
 #define OP_vkCmdDrawIndirectByteCountEXT 285235943
 #endif
-#ifdef VK_AMD_gpu_shader_half_float
-#endif
 #ifdef VK_EXT_texture_compression_astc_hdr
 DEFINE_ALIAS_FUNCTION(marshal_VkPhysicalDeviceTextureCompressionASTCHDRFeatures,
                       marshal_VkPhysicalDeviceTextureCompressionASTCHDRFeaturesEXT)
@@ -3202,10 +3190,6 @@
     VkPipelineRasterizationDepthClipStateCreateInfoEXT* forUnmarshaling);
 
 #endif
-#ifdef VK_EXT_swapchain_colorspace
-#endif
-#ifdef VK_EXT_queue_family_foreign
-#endif
 #ifdef VK_EXT_debug_utils
 void marshal_VkDebugUtilsLabelEXT(VulkanStream* vkStream, VkStructureType rootType,
                                   const VkDebugUtilsLabelEXT* forMarshaling);
@@ -3253,8 +3237,6 @@
 #define OP_vkDestroyDebugUtilsMessengerEXT 20303
 #define OP_vkSubmitDebugUtilsMessageEXT 20304
 #endif
-#ifdef VK_ANDROID_external_memory_android_hardware_buffer
-#endif
 #ifdef VK_EXT_inline_uniform_block
 DEFINE_ALIAS_FUNCTION(marshal_VkPhysicalDeviceInlineUniformBlockFeatures,
                       marshal_VkPhysicalDeviceInlineUniformBlockFeaturesEXT)
@@ -3281,8 +3263,6 @@
                       unmarshal_VkDescriptorPoolInlineUniformBlockCreateInfoEXT)
 
 #endif
-#ifdef VK_EXT_shader_stencil_export
-#endif
 #ifdef VK_EXT_vertex_attribute_divisor
 void marshal_VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT(
     VulkanStream* vkStream, VkStructureType rootType,
@@ -3329,10 +3309,6 @@
 DEFINE_ALIAS_FUNCTION(unmarshal_VkPipelineCreationFeedback, unmarshal_VkPipelineCreationFeedbackEXT)
 
 #endif
-#ifdef VK_NV_shader_subgroup_partitioned
-#endif
-#ifdef VK_EXT_metal_surface
-#endif
 #ifdef VK_EXT_fragment_density_map
 void marshal_VkPhysicalDeviceFragmentDensityMapFeaturesEXT(
     VulkanStream* vkStream, VkStructureType rootType,
@@ -3742,8 +3718,6 @@
                       unmarshal_VkPhysicalDevicePipelineCreationCacheControlFeaturesEXT)
 
 #endif
-#ifdef VK_EXT_metal_objects
-#endif
 #ifdef VK_EXT_graphics_pipeline_library
 void marshal_VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT(
     VulkanStream* vkStream, VkStructureType rootType,
@@ -3907,8 +3881,7 @@
 #define OP_vkGetBlobGOOGLE 20341
 #define OP_vkUpdateDescriptorSetWithTemplateSized2GOOGLE 244782974
 #define OP_vkQueueSubmitAsync2GOOGLE 292092830
-#endif
-#ifdef VK_EXT_load_store_op_none
+#define OP_vkGetSemaphoreGOOGLE 20342
 #endif
 #ifdef VK_EXT_image_compression_control_swapchain
 void marshal_VkPhysicalDeviceImageCompressionControlSwapchainFeaturesEXT(
@@ -3920,7 +3893,65 @@
     VkPhysicalDeviceImageCompressionControlSwapchainFeaturesEXT* forUnmarshaling);
 
 #endif
-#ifdef VK_QNX_external_memory_screen_buffer
+#ifdef VK_KHR_ray_tracing_pipeline
+void marshal_VkRayTracingShaderGroupCreateInfoKHR(
+    VulkanStream* vkStream, VkStructureType rootType,
+    const VkRayTracingShaderGroupCreateInfoKHR* forMarshaling);
+
+void unmarshal_VkRayTracingShaderGroupCreateInfoKHR(
+    VulkanStream* vkStream, VkStructureType rootType,
+    VkRayTracingShaderGroupCreateInfoKHR* forUnmarshaling);
+
+void marshal_VkRayTracingPipelineInterfaceCreateInfoKHR(
+    VulkanStream* vkStream, VkStructureType rootType,
+    const VkRayTracingPipelineInterfaceCreateInfoKHR* forMarshaling);
+
+void unmarshal_VkRayTracingPipelineInterfaceCreateInfoKHR(
+    VulkanStream* vkStream, VkStructureType rootType,
+    VkRayTracingPipelineInterfaceCreateInfoKHR* forUnmarshaling);
+
+void marshal_VkRayTracingPipelineCreateInfoKHR(
+    VulkanStream* vkStream, VkStructureType rootType,
+    const VkRayTracingPipelineCreateInfoKHR* forMarshaling);
+
+void unmarshal_VkRayTracingPipelineCreateInfoKHR(
+    VulkanStream* vkStream, VkStructureType rootType,
+    VkRayTracingPipelineCreateInfoKHR* forUnmarshaling);
+
+void marshal_VkPhysicalDeviceRayTracingPipelineFeaturesKHR(
+    VulkanStream* vkStream, VkStructureType rootType,
+    const VkPhysicalDeviceRayTracingPipelineFeaturesKHR* forMarshaling);
+
+void unmarshal_VkPhysicalDeviceRayTracingPipelineFeaturesKHR(
+    VulkanStream* vkStream, VkStructureType rootType,
+    VkPhysicalDeviceRayTracingPipelineFeaturesKHR* forUnmarshaling);
+
+void marshal_VkPhysicalDeviceRayTracingPipelinePropertiesKHR(
+    VulkanStream* vkStream, VkStructureType rootType,
+    const VkPhysicalDeviceRayTracingPipelinePropertiesKHR* forMarshaling);
+
+void unmarshal_VkPhysicalDeviceRayTracingPipelinePropertiesKHR(
+    VulkanStream* vkStream, VkStructureType rootType,
+    VkPhysicalDeviceRayTracingPipelinePropertiesKHR* forUnmarshaling);
+
+void marshal_VkStridedDeviceAddressRegionKHR(VulkanStream* vkStream, VkStructureType rootType,
+                                             const VkStridedDeviceAddressRegionKHR* forMarshaling);
+
+void unmarshal_VkStridedDeviceAddressRegionKHR(VulkanStream* vkStream, VkStructureType rootType,
+                                               VkStridedDeviceAddressRegionKHR* forUnmarshaling);
+
+void marshal_VkTraceRaysIndirectCommandKHR(VulkanStream* vkStream, VkStructureType rootType,
+                                           const VkTraceRaysIndirectCommandKHR* forMarshaling);
+
+void unmarshal_VkTraceRaysIndirectCommandKHR(VulkanStream* vkStream, VkStructureType rootType,
+                                             VkTraceRaysIndirectCommandKHR* forUnmarshaling);
+
+#define OP_vkCmdTraceRaysKHR 213680716
+#define OP_vkCreateRayTracingPipelinesKHR 247628685
+#define OP_vkGetRayTracingCaptureReplayShaderGroupHandlesKHR 221334934
+#define OP_vkCmdTraceRaysIndirectKHR 211788517
+#define OP_vkGetRayTracingShaderGroupStackSizeKHR 205271933
+#define OP_vkCmdSetRayTracingPipelineStackSizeKHR 260219604
 #endif
 const char* api_opcode_to_string(const uint32_t opcode);
 
diff --git a/host/vulkan/cereal/common/goldfish_vk_reserved_marshaling.cpp b/host/vulkan/cereal/common/goldfish_vk_reserved_marshaling.cpp
index 10cc791..9dba0a7 100644
--- a/host/vulkan/cereal/common/goldfish_vk_reserved_marshaling.cpp
+++ b/host/vulkan/cereal/common/goldfish_vk_reserved_marshaling.cpp
@@ -1093,7 +1093,7 @@
                 uint64_t tmpval;
                 memcpy(&tmpval, cgen_var_0_ptr + k * 8, sizeof(uint64_t));
                 *(((VkSemaphore*)forUnmarshaling->pWaitSemaphores) + k) =
-                    (VkSemaphore)unbox_VkSemaphore((VkSemaphore)tmpval);
+                    tmpval ? (VkSemaphore)unbox_VkSemaphore((VkSemaphore)tmpval) : VK_NULL_HANDLE;
             }
         }
     }
@@ -1114,7 +1114,8 @@
                 uint64_t tmpval;
                 memcpy(&tmpval, cgen_var_1_ptr + k * 8, sizeof(uint64_t));
                 *(((VkCommandBuffer*)forUnmarshaling->pCommandBuffers) + k) =
-                    (VkCommandBuffer)unbox_VkCommandBuffer((VkCommandBuffer)tmpval);
+                    tmpval ? (VkCommandBuffer)unbox_VkCommandBuffer((VkCommandBuffer)tmpval)
+                           : VK_NULL_HANDLE;
             }
         }
     }
@@ -1130,7 +1131,7 @@
                 uint64_t tmpval;
                 memcpy(&tmpval, cgen_var_2_ptr + k * 8, sizeof(uint64_t));
                 *(((VkSemaphore*)forUnmarshaling->pSignalSemaphores) + k) =
-                    (VkSemaphore)unbox_VkSemaphore((VkSemaphore)tmpval);
+                    tmpval ? (VkSemaphore)unbox_VkSemaphore((VkSemaphore)tmpval) : VK_NULL_HANDLE;
             }
         }
     }
@@ -1346,7 +1347,7 @@
                 uint64_t tmpval;
                 memcpy(&tmpval, cgen_var_0_ptr + k * 8, sizeof(uint64_t));
                 *(((VkSemaphore*)forUnmarshaling->pWaitSemaphores) + k) =
-                    (VkSemaphore)unbox_VkSemaphore((VkSemaphore)tmpval);
+                    tmpval ? (VkSemaphore)unbox_VkSemaphore((VkSemaphore)tmpval) : VK_NULL_HANDLE;
             }
         }
     }
@@ -1390,7 +1391,7 @@
                 uint64_t tmpval;
                 memcpy(&tmpval, cgen_var_1_ptr + k * 8, sizeof(uint64_t));
                 *(((VkSemaphore*)forUnmarshaling->pSignalSemaphores) + k) =
-                    (VkSemaphore)unbox_VkSemaphore((VkSemaphore)tmpval);
+                    tmpval ? (VkSemaphore)unbox_VkSemaphore((VkSemaphore)tmpval) : VK_NULL_HANDLE;
             }
         }
     }
@@ -2701,8 +2702,9 @@
                 uint64_t tmpval;
                 memcpy(&tmpval, cgen_var_0_ptr + k * 8, sizeof(uint64_t));
                 *(((VkDescriptorSetLayout*)forUnmarshaling->pSetLayouts) + k) =
-                    (VkDescriptorSetLayout)unbox_VkDescriptorSetLayout(
-                        (VkDescriptorSetLayout)tmpval);
+                    tmpval ? (VkDescriptorSetLayout)unbox_VkDescriptorSetLayout(
+                                 (VkDescriptorSetLayout)tmpval)
+                           : VK_NULL_HANDLE;
             }
         }
     }
@@ -2943,8 +2945,9 @@
                 uint64_t tmpval;
                 memcpy(&tmpval, cgen_var_1_ptr + k * 8, sizeof(uint64_t));
                 *(((VkDescriptorSetLayout*)forUnmarshaling->pSetLayouts) + k) =
-                    (VkDescriptorSetLayout)unbox_VkDescriptorSetLayout(
-                        (VkDescriptorSetLayout)tmpval);
+                    tmpval ? (VkDescriptorSetLayout)unbox_VkDescriptorSetLayout(
+                                 (VkDescriptorSetLayout)tmpval)
+                           : VK_NULL_HANDLE;
             }
         }
     }
@@ -2977,7 +2980,7 @@
                     uint64_t tmpval;
                     memcpy(&tmpval, cgen_var_0_0_ptr + k * 8, sizeof(uint64_t));
                     *(((VkSampler*)forUnmarshaling->pImmutableSamplers) + k) =
-                        (VkSampler)unbox_VkSampler((VkSampler)tmpval);
+                        tmpval ? (VkSampler)unbox_VkSampler((VkSampler)tmpval) : VK_NULL_HANDLE;
                 }
             }
         }
@@ -3122,7 +3125,8 @@
                         uint64_t tmpval;
                         memcpy(&tmpval, cgen_var_3_0_ptr + k * 8, sizeof(uint64_t));
                         *(((VkBufferView*)forUnmarshaling->pTexelBufferView) + k) =
-                            (VkBufferView)unbox_VkBufferView((VkBufferView)tmpval);
+                            tmpval ? (VkBufferView)unbox_VkBufferView((VkBufferView)tmpval)
+                                   : VK_NULL_HANDLE;
                     }
                 }
             }
@@ -3213,7 +3217,8 @@
                     uint64_t tmpval;
                     memcpy(&tmpval, cgen_var_0_0_ptr + k * 8, sizeof(uint64_t));
                     *(((VkImageView*)forUnmarshaling->pAttachments) + k) =
-                        (VkImageView)unbox_VkImageView((VkImageView)tmpval);
+                        tmpval ? (VkImageView)unbox_VkImageView((VkImageView)tmpval)
+                               : VK_NULL_HANDLE;
                 }
             }
         }
@@ -4232,7 +4237,8 @@
                 uint64_t tmpval;
                 memcpy(&tmpval, cgen_var_0_ptr + k * 8, sizeof(uint64_t));
                 *(((VkPhysicalDevice*)forUnmarshaling->pPhysicalDevices) + k) =
-                    (VkPhysicalDevice)unbox_VkPhysicalDevice((VkPhysicalDevice)tmpval);
+                    tmpval ? (VkPhysicalDevice)unbox_VkPhysicalDevice((VkPhysicalDevice)tmpval)
+                           : VK_NULL_HANDLE;
             }
         }
     }
@@ -7537,7 +7543,7 @@
                 uint64_t tmpval;
                 memcpy(&tmpval, cgen_var_0_ptr + k * 8, sizeof(uint64_t));
                 *(((VkImageView*)forUnmarshaling->pAttachments) + k) =
-                    (VkImageView)unbox_VkImageView((VkImageView)tmpval);
+                    tmpval ? (VkImageView)unbox_VkImageView((VkImageView)tmpval) : VK_NULL_HANDLE;
             }
         }
     }
@@ -7901,7 +7907,7 @@
                 uint64_t tmpval;
                 memcpy(&tmpval, cgen_var_0_ptr + k * 8, sizeof(uint64_t));
                 *(((VkSemaphore*)forUnmarshaling->pSemaphores) + k) =
-                    (VkSemaphore)unbox_VkSemaphore((VkSemaphore)tmpval);
+                    tmpval ? (VkSemaphore)unbox_VkSemaphore((VkSemaphore)tmpval) : VK_NULL_HANDLE;
             }
         }
     }
@@ -10310,8 +10316,6 @@
 }
 
 #endif
-#ifdef VK_KHR_surface
-#endif
 #ifdef VK_KHR_swapchain
 void reservedunmarshal_VkSwapchainCreateInfoKHR(VulkanStream* vkStream, VkStructureType rootType,
                                                 VkSwapchainCreateInfoKHR* forUnmarshaling,
@@ -10426,7 +10430,7 @@
                 uint64_t tmpval;
                 memcpy(&tmpval, cgen_var_0_ptr + k * 8, sizeof(uint64_t));
                 *(((VkSemaphore*)forUnmarshaling->pWaitSemaphores) + k) =
-                    (VkSemaphore)unbox_VkSemaphore((VkSemaphore)tmpval);
+                    tmpval ? (VkSemaphore)unbox_VkSemaphore((VkSemaphore)tmpval) : VK_NULL_HANDLE;
             }
         }
     }
@@ -10442,7 +10446,8 @@
                 uint64_t tmpval;
                 memcpy(&tmpval, cgen_var_1_ptr + k * 8, sizeof(uint64_t));
                 *(((VkSwapchainKHR*)forUnmarshaling->pSwapchains) + k) =
-                    (VkSwapchainKHR)unbox_VkSwapchainKHR((VkSwapchainKHR)tmpval);
+                    tmpval ? (VkSwapchainKHR)unbox_VkSwapchainKHR((VkSwapchainKHR)tmpval)
+                           : VK_NULL_HANDLE;
             }
         }
     }
@@ -10677,12 +10682,6 @@
 }
 
 #endif
-#ifdef VK_KHR_xcb_surface
-#endif
-#ifdef VK_KHR_android_surface
-#endif
-#ifdef VK_KHR_win32_surface
-#endif
 #ifdef VK_KHR_dynamic_rendering
 void reservedunmarshal_VkRenderingFragmentShadingRateAttachmentInfoKHR(
     VulkanStream* vkStream, VkStructureType rootType,
@@ -10830,24 +10829,6 @@
 }
 
 #endif
-#ifdef VK_KHR_get_physical_device_properties2
-#endif
-#ifdef VK_KHR_maintenance1
-#endif
-#ifdef VK_KHR_external_memory_capabilities
-#endif
-#ifdef VK_KHR_external_memory
-#endif
-#ifdef VK_KHR_external_memory_win32
-#endif
-#ifdef VK_KHR_external_memory_fd
-#endif
-#ifdef VK_KHR_external_semaphore_capabilities
-#endif
-#ifdef VK_KHR_external_semaphore
-#endif
-#ifdef VK_KHR_external_semaphore_win32
-#endif
 #ifdef VK_KHR_external_semaphore_fd
 void reservedunmarshal_VkImportSemaphoreFdInfoKHR(VulkanStream* vkStream, VkStructureType rootType,
                                                   VkImportSemaphoreFdInfoKHR* forUnmarshaling,
@@ -10924,8 +10905,6 @@
 }
 
 #endif
-#ifdef VK_KHR_shader_float16_int8
-#endif
 #ifdef VK_KHR_incremental_present
 void reservedunmarshal_VkRectLayerKHR(VulkanStream* vkStream, VkStructureType rootType,
                                       VkRectLayerKHR* forUnmarshaling, uint8_t** ptr) {
@@ -10994,16 +10973,6 @@
 }
 
 #endif
-#ifdef VK_KHR_descriptor_update_template
-#endif
-#ifdef VK_KHR_imageless_framebuffer
-#endif
-#ifdef VK_KHR_create_renderpass2
-#endif
-#ifdef VK_KHR_external_fence_capabilities
-#endif
-#ifdef VK_KHR_external_fence
-#endif
 #ifdef VK_KHR_external_fence_fd
 void reservedunmarshal_VkImportFenceFdInfoKHR(VulkanStream* vkStream, VkStructureType rootType,
                                               VkImportFenceFdInfoKHR* forUnmarshaling,
@@ -11077,30 +11046,6 @@
 }
 
 #endif
-#ifdef VK_KHR_maintenance2
-#endif
-#ifdef VK_KHR_dedicated_allocation
-#endif
-#ifdef VK_KHR_storage_buffer_storage_class
-#endif
-#ifdef VK_KHR_get_memory_requirements2
-#endif
-#ifdef VK_KHR_image_format_list
-#endif
-#ifdef VK_KHR_sampler_ycbcr_conversion
-#endif
-#ifdef VK_KHR_bind_memory2
-#endif
-#ifdef VK_KHR_maintenance3
-#endif
-#ifdef VK_KHR_shader_subgroup_extended_types
-#endif
-#ifdef VK_KHR_vulkan_memory_model
-#endif
-#ifdef VK_KHR_shader_terminate_invocation
-#endif
-#ifdef VK_KHR_buffer_device_address
-#endif
 #ifdef VK_KHR_pipeline_executable_properties
 void reservedunmarshal_VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR(
     VulkanStream* vkStream, VkStructureType rootType,
@@ -11321,9 +11266,50 @@
 }
 
 #endif
-#ifdef VK_KHR_shader_integer_dot_product
-#endif
-#ifdef VK_KHR_shader_non_semantic_info
+#ifdef VK_KHR_pipeline_library
+void reservedunmarshal_VkPipelineLibraryCreateInfoKHR(
+    VulkanStream* vkStream, VkStructureType rootType,
+    VkPipelineLibraryCreateInfoKHR* forUnmarshaling, uint8_t** ptr) {
+    memcpy((VkStructureType*)&forUnmarshaling->sType, *ptr, sizeof(VkStructureType));
+    *ptr += sizeof(VkStructureType);
+    if (rootType == VK_STRUCTURE_TYPE_MAX_ENUM) {
+        rootType = forUnmarshaling->sType;
+    }
+    uint32_t pNext_size;
+    memcpy((uint32_t*)&pNext_size, *ptr, sizeof(uint32_t));
+    android::base::Stream::fromBe32((uint8_t*)&pNext_size);
+    *ptr += sizeof(uint32_t);
+    forUnmarshaling->pNext = nullptr;
+    if (pNext_size) {
+        vkStream->alloc((void**)&forUnmarshaling->pNext, sizeof(VkStructureType));
+        memcpy((void*)forUnmarshaling->pNext, *ptr, sizeof(VkStructureType));
+        *ptr += sizeof(VkStructureType);
+        VkStructureType extType = *(VkStructureType*)(forUnmarshaling->pNext);
+        vkStream->alloc((void**)&forUnmarshaling->pNext,
+                        goldfish_vk_extension_struct_size_with_stream_features(
+                            vkStream->getFeatureBits(), rootType, forUnmarshaling->pNext));
+        *(VkStructureType*)forUnmarshaling->pNext = extType;
+        reservedunmarshal_extension_struct(vkStream, rootType, (void*)(forUnmarshaling->pNext),
+                                           ptr);
+    }
+    memcpy((uint32_t*)&forUnmarshaling->libraryCount, *ptr, sizeof(uint32_t));
+    *ptr += sizeof(uint32_t);
+    vkStream->alloc((void**)&forUnmarshaling->pLibraries,
+                    forUnmarshaling->libraryCount * sizeof(const VkPipeline));
+    if (forUnmarshaling->libraryCount) {
+        uint8_t* cgen_var_0_ptr = (uint8_t*)(*ptr);
+        *ptr += 8 * forUnmarshaling->libraryCount;
+        if (forUnmarshaling) {
+            for (uint32_t k = 0; k < forUnmarshaling->libraryCount; ++k) {
+                uint64_t tmpval;
+                memcpy(&tmpval, cgen_var_0_ptr + k * 8, sizeof(uint64_t));
+                *(((VkPipeline*)forUnmarshaling->pLibraries) + k) =
+                    tmpval ? (VkPipeline)unbox_VkPipeline((VkPipeline)tmpval) : VK_NULL_HANDLE;
+            }
+        }
+    }
+}
+
 #endif
 #ifdef VK_KHR_synchronization2
 void reservedunmarshal_VkQueueFamilyCheckpointProperties2NV(
@@ -11394,14 +11380,6 @@
 }
 
 #endif
-#ifdef VK_KHR_zero_initialize_workgroup_memory
-#endif
-#ifdef VK_KHR_copy_commands2
-#endif
-#ifdef VK_KHR_format_feature_flags2
-#endif
-#ifdef VK_KHR_maintenance4
-#endif
 #ifdef VK_KHR_maintenance5
 void reservedunmarshal_VkPhysicalDeviceMaintenance5FeaturesKHR(
     VulkanStream* vkStream, VkStructureType rootType,
@@ -11944,10 +11922,6 @@
 }
 
 #endif
-#ifdef VK_AMD_gpu_shader_half_float
-#endif
-#ifdef VK_EXT_texture_compression_astc_hdr
-#endif
 #ifdef VK_EXT_depth_clip_enable
 void reservedunmarshal_VkPhysicalDeviceDepthClipEnableFeaturesEXT(
     VulkanStream* vkStream, VkStructureType rootType,
@@ -12011,10 +11985,6 @@
 }
 
 #endif
-#ifdef VK_EXT_swapchain_colorspace
-#endif
-#ifdef VK_EXT_queue_family_foreign
-#endif
 #ifdef VK_EXT_debug_utils
 void reservedunmarshal_VkDebugUtilsLabelEXT(VulkanStream* vkStream, VkStructureType rootType,
                                             VkDebugUtilsLabelEXT* forUnmarshaling, uint8_t** ptr) {
@@ -12247,12 +12217,6 @@
 }
 
 #endif
-#ifdef VK_ANDROID_external_memory_android_hardware_buffer
-#endif
-#ifdef VK_EXT_inline_uniform_block
-#endif
-#ifdef VK_EXT_shader_stencil_export
-#endif
 #ifdef VK_EXT_vertex_attribute_divisor
 void reservedunmarshal_VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT(
     VulkanStream* vkStream, VkStructureType rootType,
@@ -12364,12 +12328,6 @@
 }
 
 #endif
-#ifdef VK_EXT_pipeline_creation_feedback
-#endif
-#ifdef VK_NV_shader_subgroup_partitioned
-#endif
-#ifdef VK_EXT_metal_surface
-#endif
 #ifdef VK_EXT_fragment_density_map
 void reservedunmarshal_VkPhysicalDeviceFragmentDensityMapFeaturesEXT(
     VulkanStream* vkStream, VkStructureType rootType,
@@ -12472,12 +12430,6 @@
 }
 
 #endif
-#ifdef VK_EXT_scalar_block_layout
-#endif
-#ifdef VK_EXT_subgroup_size_control
-#endif
-#ifdef VK_EXT_tooling_info
-#endif
 #ifdef VK_EXT_validation_features
 void reservedunmarshal_VkValidationFeaturesEXT(VulkanStream* vkStream, VkStructureType rootType,
                                                VkValidationFeaturesEXT* forUnmarshaling,
@@ -13262,7 +13214,7 @@
                 uint64_t tmpval;
                 memcpy(&tmpval, cgen_var_0_ptr + k * 8, sizeof(uint64_t));
                 *(((VkFence*)forUnmarshaling->pFences) + k) =
-                    (VkFence)unbox_VkFence((VkFence)tmpval);
+                    tmpval ? (VkFence)unbox_VkFence((VkFence)tmpval) : VK_NULL_HANDLE;
             }
         }
     }
@@ -13413,8 +13365,6 @@
 }
 
 #endif
-#ifdef VK_EXT_shader_demote_to_helper_invocation
-#endif
 #ifdef VK_EXT_texel_buffer_alignment
 void reservedunmarshal_VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT(
     VulkanStream* vkStream, VkStructureType rootType,
@@ -13717,12 +13667,6 @@
 }
 
 #endif
-#ifdef VK_EXT_private_data
-#endif
-#ifdef VK_EXT_pipeline_creation_cache_control
-#endif
-#ifdef VK_EXT_metal_objects
-#endif
 #ifdef VK_EXT_graphics_pipeline_library
 void reservedunmarshal_VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT(
     VulkanStream* vkStream, VkStructureType rootType,
@@ -13847,8 +13791,6 @@
 }
 
 #endif
-#ifdef VK_EXT_image_robustness
-#endif
 #ifdef VK_EXT_image_compression_control
 void reservedunmarshal_VkPhysicalDeviceImageCompressionControlFeaturesEXT(
     VulkanStream* vkStream, VkStructureType rootType,
@@ -14221,8 +14163,6 @@
 }
 
 #endif
-#ifdef VK_EXT_load_store_op_none
-#endif
 #ifdef VK_EXT_image_compression_control_swapchain
 void reservedunmarshal_VkPhysicalDeviceImageCompressionControlSwapchainFeaturesEXT(
     VulkanStream* vkStream, VkStructureType rootType,
@@ -14254,7 +14194,289 @@
 }
 
 #endif
-#ifdef VK_QNX_external_memory_screen_buffer
+#ifdef VK_KHR_ray_tracing_pipeline
+void reservedunmarshal_VkRayTracingShaderGroupCreateInfoKHR(
+    VulkanStream* vkStream, VkStructureType rootType,
+    VkRayTracingShaderGroupCreateInfoKHR* forUnmarshaling, uint8_t** ptr) {
+    memcpy((VkStructureType*)&forUnmarshaling->sType, *ptr, sizeof(VkStructureType));
+    *ptr += sizeof(VkStructureType);
+    if (rootType == VK_STRUCTURE_TYPE_MAX_ENUM) {
+        rootType = forUnmarshaling->sType;
+    }
+    uint32_t pNext_size;
+    memcpy((uint32_t*)&pNext_size, *ptr, sizeof(uint32_t));
+    android::base::Stream::fromBe32((uint8_t*)&pNext_size);
+    *ptr += sizeof(uint32_t);
+    forUnmarshaling->pNext = nullptr;
+    if (pNext_size) {
+        vkStream->alloc((void**)&forUnmarshaling->pNext, sizeof(VkStructureType));
+        memcpy((void*)forUnmarshaling->pNext, *ptr, sizeof(VkStructureType));
+        *ptr += sizeof(VkStructureType);
+        VkStructureType extType = *(VkStructureType*)(forUnmarshaling->pNext);
+        vkStream->alloc((void**)&forUnmarshaling->pNext,
+                        goldfish_vk_extension_struct_size_with_stream_features(
+                            vkStream->getFeatureBits(), rootType, forUnmarshaling->pNext));
+        *(VkStructureType*)forUnmarshaling->pNext = extType;
+        reservedunmarshal_extension_struct(vkStream, rootType, (void*)(forUnmarshaling->pNext),
+                                           ptr);
+    }
+    memcpy((VkRayTracingShaderGroupTypeKHR*)&forUnmarshaling->type, *ptr,
+           sizeof(VkRayTracingShaderGroupTypeKHR));
+    *ptr += sizeof(VkRayTracingShaderGroupTypeKHR);
+    memcpy((uint32_t*)&forUnmarshaling->generalShader, *ptr, sizeof(uint32_t));
+    *ptr += sizeof(uint32_t);
+    memcpy((uint32_t*)&forUnmarshaling->closestHitShader, *ptr, sizeof(uint32_t));
+    *ptr += sizeof(uint32_t);
+    memcpy((uint32_t*)&forUnmarshaling->anyHitShader, *ptr, sizeof(uint32_t));
+    *ptr += sizeof(uint32_t);
+    memcpy((uint32_t*)&forUnmarshaling->intersectionShader, *ptr, sizeof(uint32_t));
+    *ptr += sizeof(uint32_t);
+    // WARNING PTR CHECK
+    memcpy((void**)&forUnmarshaling->pShaderGroupCaptureReplayHandle, (*ptr), 8);
+    android::base::Stream::fromBe64((uint8_t*)&forUnmarshaling->pShaderGroupCaptureReplayHandle);
+    *ptr += 8;
+    if (forUnmarshaling->pShaderGroupCaptureReplayHandle) {
+        vkStream->alloc((void**)&forUnmarshaling->pShaderGroupCaptureReplayHandle,
+                        sizeof(const uint8_t));
+        memcpy((void*)forUnmarshaling->pShaderGroupCaptureReplayHandle, *ptr,
+               sizeof(const uint8_t));
+        *ptr += sizeof(const uint8_t);
+    }
+}
+
+void reservedunmarshal_VkRayTracingPipelineInterfaceCreateInfoKHR(
+    VulkanStream* vkStream, VkStructureType rootType,
+    VkRayTracingPipelineInterfaceCreateInfoKHR* forUnmarshaling, uint8_t** ptr) {
+    memcpy((VkStructureType*)&forUnmarshaling->sType, *ptr, sizeof(VkStructureType));
+    *ptr += sizeof(VkStructureType);
+    if (rootType == VK_STRUCTURE_TYPE_MAX_ENUM) {
+        rootType = forUnmarshaling->sType;
+    }
+    uint32_t pNext_size;
+    memcpy((uint32_t*)&pNext_size, *ptr, sizeof(uint32_t));
+    android::base::Stream::fromBe32((uint8_t*)&pNext_size);
+    *ptr += sizeof(uint32_t);
+    forUnmarshaling->pNext = nullptr;
+    if (pNext_size) {
+        vkStream->alloc((void**)&forUnmarshaling->pNext, sizeof(VkStructureType));
+        memcpy((void*)forUnmarshaling->pNext, *ptr, sizeof(VkStructureType));
+        *ptr += sizeof(VkStructureType);
+        VkStructureType extType = *(VkStructureType*)(forUnmarshaling->pNext);
+        vkStream->alloc((void**)&forUnmarshaling->pNext,
+                        goldfish_vk_extension_struct_size_with_stream_features(
+                            vkStream->getFeatureBits(), rootType, forUnmarshaling->pNext));
+        *(VkStructureType*)forUnmarshaling->pNext = extType;
+        reservedunmarshal_extension_struct(vkStream, rootType, (void*)(forUnmarshaling->pNext),
+                                           ptr);
+    }
+    memcpy((uint32_t*)&forUnmarshaling->maxPipelineRayPayloadSize, *ptr, sizeof(uint32_t));
+    *ptr += sizeof(uint32_t);
+    memcpy((uint32_t*)&forUnmarshaling->maxPipelineRayHitAttributeSize, *ptr, sizeof(uint32_t));
+    *ptr += sizeof(uint32_t);
+}
+
+void reservedunmarshal_VkRayTracingPipelineCreateInfoKHR(
+    VulkanStream* vkStream, VkStructureType rootType,
+    VkRayTracingPipelineCreateInfoKHR* forUnmarshaling, uint8_t** ptr) {
+    memcpy((VkStructureType*)&forUnmarshaling->sType, *ptr, sizeof(VkStructureType));
+    *ptr += sizeof(VkStructureType);
+    if (rootType == VK_STRUCTURE_TYPE_MAX_ENUM) {
+        rootType = forUnmarshaling->sType;
+    }
+    uint32_t pNext_size;
+    memcpy((uint32_t*)&pNext_size, *ptr, sizeof(uint32_t));
+    android::base::Stream::fromBe32((uint8_t*)&pNext_size);
+    *ptr += sizeof(uint32_t);
+    forUnmarshaling->pNext = nullptr;
+    if (pNext_size) {
+        vkStream->alloc((void**)&forUnmarshaling->pNext, sizeof(VkStructureType));
+        memcpy((void*)forUnmarshaling->pNext, *ptr, sizeof(VkStructureType));
+        *ptr += sizeof(VkStructureType);
+        VkStructureType extType = *(VkStructureType*)(forUnmarshaling->pNext);
+        vkStream->alloc((void**)&forUnmarshaling->pNext,
+                        goldfish_vk_extension_struct_size_with_stream_features(
+                            vkStream->getFeatureBits(), rootType, forUnmarshaling->pNext));
+        *(VkStructureType*)forUnmarshaling->pNext = extType;
+        reservedunmarshal_extension_struct(vkStream, rootType, (void*)(forUnmarshaling->pNext),
+                                           ptr);
+    }
+    memcpy((VkPipelineCreateFlags*)&forUnmarshaling->flags, *ptr, sizeof(VkPipelineCreateFlags));
+    *ptr += sizeof(VkPipelineCreateFlags);
+    memcpy((uint32_t*)&forUnmarshaling->stageCount, *ptr, sizeof(uint32_t));
+    *ptr += sizeof(uint32_t);
+    vkStream->alloc((void**)&forUnmarshaling->pStages,
+                    forUnmarshaling->stageCount * sizeof(const VkPipelineShaderStageCreateInfo));
+    for (uint32_t i = 0; i < (uint32_t)forUnmarshaling->stageCount; ++i) {
+        reservedunmarshal_VkPipelineShaderStageCreateInfo(
+            vkStream, rootType, (VkPipelineShaderStageCreateInfo*)(forUnmarshaling->pStages + i),
+            ptr);
+    }
+    memcpy((uint32_t*)&forUnmarshaling->groupCount, *ptr, sizeof(uint32_t));
+    *ptr += sizeof(uint32_t);
+    vkStream->alloc(
+        (void**)&forUnmarshaling->pGroups,
+        forUnmarshaling->groupCount * sizeof(const VkRayTracingShaderGroupCreateInfoKHR));
+    for (uint32_t i = 0; i < (uint32_t)forUnmarshaling->groupCount; ++i) {
+        reservedunmarshal_VkRayTracingShaderGroupCreateInfoKHR(
+            vkStream, rootType,
+            (VkRayTracingShaderGroupCreateInfoKHR*)(forUnmarshaling->pGroups + i), ptr);
+    }
+    memcpy((uint32_t*)&forUnmarshaling->maxPipelineRayRecursionDepth, *ptr, sizeof(uint32_t));
+    *ptr += sizeof(uint32_t);
+    // WARNING PTR CHECK
+    memcpy((VkPipelineLibraryCreateInfoKHR**)&forUnmarshaling->pLibraryInfo, (*ptr), 8);
+    android::base::Stream::fromBe64((uint8_t*)&forUnmarshaling->pLibraryInfo);
+    *ptr += 8;
+    if (forUnmarshaling->pLibraryInfo) {
+        vkStream->alloc((void**)&forUnmarshaling->pLibraryInfo,
+                        sizeof(const VkPipelineLibraryCreateInfoKHR));
+        reservedunmarshal_VkPipelineLibraryCreateInfoKHR(
+            vkStream, rootType, (VkPipelineLibraryCreateInfoKHR*)(forUnmarshaling->pLibraryInfo),
+            ptr);
+    }
+    // WARNING PTR CHECK
+    memcpy((VkRayTracingPipelineInterfaceCreateInfoKHR**)&forUnmarshaling->pLibraryInterface,
+           (*ptr), 8);
+    android::base::Stream::fromBe64((uint8_t*)&forUnmarshaling->pLibraryInterface);
+    *ptr += 8;
+    if (forUnmarshaling->pLibraryInterface) {
+        vkStream->alloc((void**)&forUnmarshaling->pLibraryInterface,
+                        sizeof(const VkRayTracingPipelineInterfaceCreateInfoKHR));
+        reservedunmarshal_VkRayTracingPipelineInterfaceCreateInfoKHR(
+            vkStream, rootType,
+            (VkRayTracingPipelineInterfaceCreateInfoKHR*)(forUnmarshaling->pLibraryInterface), ptr);
+    }
+    // WARNING PTR CHECK
+    memcpy((VkPipelineDynamicStateCreateInfo**)&forUnmarshaling->pDynamicState, (*ptr), 8);
+    android::base::Stream::fromBe64((uint8_t*)&forUnmarshaling->pDynamicState);
+    *ptr += 8;
+    if (forUnmarshaling->pDynamicState) {
+        vkStream->alloc((void**)&forUnmarshaling->pDynamicState,
+                        sizeof(const VkPipelineDynamicStateCreateInfo));
+        reservedunmarshal_VkPipelineDynamicStateCreateInfo(
+            vkStream, rootType, (VkPipelineDynamicStateCreateInfo*)(forUnmarshaling->pDynamicState),
+            ptr);
+    }
+    uint64_t cgen_var_3;
+    memcpy((uint64_t*)&cgen_var_3, *ptr, 1 * 8);
+    *ptr += 1 * 8;
+    *(VkPipelineLayout*)&forUnmarshaling->layout =
+        (VkPipelineLayout)unbox_VkPipelineLayout((VkPipelineLayout)(*&cgen_var_3));
+    uint64_t cgen_var_4;
+    memcpy((uint64_t*)&cgen_var_4, *ptr, 1 * 8);
+    *ptr += 1 * 8;
+    *(VkPipeline*)&forUnmarshaling->basePipelineHandle =
+        (VkPipeline)unbox_VkPipeline((VkPipeline)(*&cgen_var_4));
+    memcpy((int32_t*)&forUnmarshaling->basePipelineIndex, *ptr, sizeof(int32_t));
+    *ptr += sizeof(int32_t);
+}
+
+void reservedunmarshal_VkPhysicalDeviceRayTracingPipelineFeaturesKHR(
+    VulkanStream* vkStream, VkStructureType rootType,
+    VkPhysicalDeviceRayTracingPipelineFeaturesKHR* forUnmarshaling, uint8_t** ptr) {
+    memcpy((VkStructureType*)&forUnmarshaling->sType, *ptr, sizeof(VkStructureType));
+    *ptr += sizeof(VkStructureType);
+    if (rootType == VK_STRUCTURE_TYPE_MAX_ENUM) {
+        rootType = forUnmarshaling->sType;
+    }
+    uint32_t pNext_size;
+    memcpy((uint32_t*)&pNext_size, *ptr, sizeof(uint32_t));
+    android::base::Stream::fromBe32((uint8_t*)&pNext_size);
+    *ptr += sizeof(uint32_t);
+    forUnmarshaling->pNext = nullptr;
+    if (pNext_size) {
+        vkStream->alloc((void**)&forUnmarshaling->pNext, sizeof(VkStructureType));
+        memcpy((void*)forUnmarshaling->pNext, *ptr, sizeof(VkStructureType));
+        *ptr += sizeof(VkStructureType);
+        VkStructureType extType = *(VkStructureType*)(forUnmarshaling->pNext);
+        vkStream->alloc((void**)&forUnmarshaling->pNext,
+                        goldfish_vk_extension_struct_size_with_stream_features(
+                            vkStream->getFeatureBits(), rootType, forUnmarshaling->pNext));
+        *(VkStructureType*)forUnmarshaling->pNext = extType;
+        reservedunmarshal_extension_struct(vkStream, rootType, (void*)(forUnmarshaling->pNext),
+                                           ptr);
+    }
+    memcpy((VkBool32*)&forUnmarshaling->rayTracingPipeline, *ptr, sizeof(VkBool32));
+    *ptr += sizeof(VkBool32);
+    memcpy((VkBool32*)&forUnmarshaling->rayTracingPipelineShaderGroupHandleCaptureReplay, *ptr,
+           sizeof(VkBool32));
+    *ptr += sizeof(VkBool32);
+    memcpy((VkBool32*)&forUnmarshaling->rayTracingPipelineShaderGroupHandleCaptureReplayMixed, *ptr,
+           sizeof(VkBool32));
+    *ptr += sizeof(VkBool32);
+    memcpy((VkBool32*)&forUnmarshaling->rayTracingPipelineTraceRaysIndirect, *ptr,
+           sizeof(VkBool32));
+    *ptr += sizeof(VkBool32);
+    memcpy((VkBool32*)&forUnmarshaling->rayTraversalPrimitiveCulling, *ptr, sizeof(VkBool32));
+    *ptr += sizeof(VkBool32);
+}
+
+void reservedunmarshal_VkPhysicalDeviceRayTracingPipelinePropertiesKHR(
+    VulkanStream* vkStream, VkStructureType rootType,
+    VkPhysicalDeviceRayTracingPipelinePropertiesKHR* forUnmarshaling, uint8_t** ptr) {
+    memcpy((VkStructureType*)&forUnmarshaling->sType, *ptr, sizeof(VkStructureType));
+    *ptr += sizeof(VkStructureType);
+    if (rootType == VK_STRUCTURE_TYPE_MAX_ENUM) {
+        rootType = forUnmarshaling->sType;
+    }
+    uint32_t pNext_size;
+    memcpy((uint32_t*)&pNext_size, *ptr, sizeof(uint32_t));
+    android::base::Stream::fromBe32((uint8_t*)&pNext_size);
+    *ptr += sizeof(uint32_t);
+    forUnmarshaling->pNext = nullptr;
+    if (pNext_size) {
+        vkStream->alloc((void**)&forUnmarshaling->pNext, sizeof(VkStructureType));
+        memcpy((void*)forUnmarshaling->pNext, *ptr, sizeof(VkStructureType));
+        *ptr += sizeof(VkStructureType);
+        VkStructureType extType = *(VkStructureType*)(forUnmarshaling->pNext);
+        vkStream->alloc((void**)&forUnmarshaling->pNext,
+                        goldfish_vk_extension_struct_size_with_stream_features(
+                            vkStream->getFeatureBits(), rootType, forUnmarshaling->pNext));
+        *(VkStructureType*)forUnmarshaling->pNext = extType;
+        reservedunmarshal_extension_struct(vkStream, rootType, (void*)(forUnmarshaling->pNext),
+                                           ptr);
+    }
+    memcpy((uint32_t*)&forUnmarshaling->shaderGroupHandleSize, *ptr, sizeof(uint32_t));
+    *ptr += sizeof(uint32_t);
+    memcpy((uint32_t*)&forUnmarshaling->maxRayRecursionDepth, *ptr, sizeof(uint32_t));
+    *ptr += sizeof(uint32_t);
+    memcpy((uint32_t*)&forUnmarshaling->maxShaderGroupStride, *ptr, sizeof(uint32_t));
+    *ptr += sizeof(uint32_t);
+    memcpy((uint32_t*)&forUnmarshaling->shaderGroupBaseAlignment, *ptr, sizeof(uint32_t));
+    *ptr += sizeof(uint32_t);
+    memcpy((uint32_t*)&forUnmarshaling->shaderGroupHandleCaptureReplaySize, *ptr, sizeof(uint32_t));
+    *ptr += sizeof(uint32_t);
+    memcpy((uint32_t*)&forUnmarshaling->maxRayDispatchInvocationCount, *ptr, sizeof(uint32_t));
+    *ptr += sizeof(uint32_t);
+    memcpy((uint32_t*)&forUnmarshaling->shaderGroupHandleAlignment, *ptr, sizeof(uint32_t));
+    *ptr += sizeof(uint32_t);
+    memcpy((uint32_t*)&forUnmarshaling->maxRayHitAttributeSize, *ptr, sizeof(uint32_t));
+    *ptr += sizeof(uint32_t);
+}
+
+void reservedunmarshal_VkStridedDeviceAddressRegionKHR(
+    VulkanStream* vkStream, VkStructureType rootType,
+    VkStridedDeviceAddressRegionKHR* forUnmarshaling, uint8_t** ptr) {
+    memcpy((VkDeviceAddress*)&forUnmarshaling->deviceAddress, *ptr, sizeof(VkDeviceAddress));
+    *ptr += sizeof(VkDeviceAddress);
+    memcpy((VkDeviceSize*)&forUnmarshaling->stride, *ptr, sizeof(VkDeviceSize));
+    *ptr += sizeof(VkDeviceSize);
+    memcpy((VkDeviceSize*)&forUnmarshaling->size, *ptr, sizeof(VkDeviceSize));
+    *ptr += sizeof(VkDeviceSize);
+}
+
+void reservedunmarshal_VkTraceRaysIndirectCommandKHR(VulkanStream* vkStream,
+                                                     VkStructureType rootType,
+                                                     VkTraceRaysIndirectCommandKHR* forUnmarshaling,
+                                                     uint8_t** ptr) {
+    memcpy((uint32_t*)&forUnmarshaling->width, *ptr, sizeof(uint32_t));
+    *ptr += sizeof(uint32_t);
+    memcpy((uint32_t*)&forUnmarshaling->height, *ptr, sizeof(uint32_t));
+    *ptr += sizeof(uint32_t);
+    memcpy((uint32_t*)&forUnmarshaling->depth, *ptr, sizeof(uint32_t));
+    *ptr += sizeof(uint32_t);
+}
+
 #endif
 void reservedunmarshal_extension_struct(VulkanStream* vkStream, VkStructureType rootType,
                                         void* structExtension_out, uint8_t** ptr) {
@@ -15079,6 +15301,14 @@
             break;
         }
 #endif
+#ifdef VK_KHR_pipeline_library
+        case VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR: {
+            reservedunmarshal_VkPipelineLibraryCreateInfoKHR(
+                vkStream, rootType,
+                reinterpret_cast<VkPipelineLibraryCreateInfoKHR*>(structExtension_out), ptr);
+            break;
+        }
+#endif
 #ifdef VK_KHR_synchronization2
         case VK_STRUCTURE_TYPE_QUEUE_FAMILY_CHECKPOINT_PROPERTIES_2_NV: {
             reservedunmarshal_VkQueueFamilyCheckpointProperties2NV(
@@ -15654,6 +15884,24 @@
             break;
         }
 #endif
+#ifdef VK_KHR_ray_tracing_pipeline
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR: {
+            reservedunmarshal_VkPhysicalDeviceRayTracingPipelineFeaturesKHR(
+                vkStream, rootType,
+                reinterpret_cast<VkPhysicalDeviceRayTracingPipelineFeaturesKHR*>(
+                    structExtension_out),
+                ptr);
+            break;
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR: {
+            reservedunmarshal_VkPhysicalDeviceRayTracingPipelinePropertiesKHR(
+                vkStream, rootType,
+                reinterpret_cast<VkPhysicalDeviceRayTracingPipelinePropertiesKHR*>(
+                    structExtension_out),
+                ptr);
+            break;
+        }
+#endif
         default: {
             // fatal; the switch is only taken if the extension struct is known
             abort();
diff --git a/host/vulkan/cereal/common/goldfish_vk_reserved_marshaling.h b/host/vulkan/cereal/common/goldfish_vk_reserved_marshaling.h
index cec4966..fcb5de3 100644
--- a/host/vulkan/cereal/common/goldfish_vk_reserved_marshaling.h
+++ b/host/vulkan/cereal/common/goldfish_vk_reserved_marshaling.h
@@ -1113,8 +1113,6 @@
     VkDeviceImageMemoryRequirements* forUnmarshaling, uint8_t** ptr);
 
 #endif
-#ifdef VK_KHR_surface
-#endif
 #ifdef VK_KHR_swapchain
 void reservedunmarshal_VkSwapchainCreateInfoKHR(VulkanStream* vkStream, VkStructureType rootType,
                                                 VkSwapchainCreateInfoKHR* forUnmarshaling,
@@ -1149,12 +1147,6 @@
     VkDeviceGroupSwapchainCreateInfoKHR* forUnmarshaling, uint8_t** ptr);
 
 #endif
-#ifdef VK_KHR_xcb_surface
-#endif
-#ifdef VK_KHR_android_surface
-#endif
-#ifdef VK_KHR_win32_surface
-#endif
 #ifdef VK_KHR_dynamic_rendering
 DEFINE_ALIAS_FUNCTION(reservedunmarshal_VkRenderingInfo, reservedunmarshal_VkRenderingInfoKHR)
 
@@ -1219,8 +1211,6 @@
                       reservedunmarshal_VkPhysicalDeviceSparseImageFormatInfo2KHR)
 
 #endif
-#ifdef VK_KHR_maintenance1
-#endif
 #ifdef VK_KHR_external_memory_capabilities
 DEFINE_ALIAS_FUNCTION(reservedunmarshal_VkExternalMemoryProperties,
                       reservedunmarshal_VkExternalMemoryPropertiesKHR)
@@ -1252,10 +1242,6 @@
                       reservedunmarshal_VkExportMemoryAllocateInfoKHR)
 
 #endif
-#ifdef VK_KHR_external_memory_win32
-#endif
-#ifdef VK_KHR_external_memory_fd
-#endif
 #ifdef VK_KHR_external_semaphore_capabilities
 DEFINE_ALIAS_FUNCTION(reservedunmarshal_VkPhysicalDeviceExternalSemaphoreInfo,
                       reservedunmarshal_VkPhysicalDeviceExternalSemaphoreInfoKHR)
@@ -1269,8 +1255,6 @@
                       reservedunmarshal_VkExportSemaphoreCreateInfoKHR)
 
 #endif
-#ifdef VK_KHR_external_semaphore_win32
-#endif
 #ifdef VK_KHR_external_semaphore_fd
 void reservedunmarshal_VkImportSemaphoreFdInfoKHR(VulkanStream* vkStream, VkStructureType rootType,
                                                   VkImportSemaphoreFdInfoKHR* forUnmarshaling,
@@ -1390,8 +1374,6 @@
                       reservedunmarshal_VkMemoryDedicatedAllocateInfoKHR)
 
 #endif
-#ifdef VK_KHR_storage_buffer_storage_class
-#endif
 #ifdef VK_KHR_get_memory_requirements2
 DEFINE_ALIAS_FUNCTION(reservedunmarshal_VkBufferMemoryRequirementsInfo2,
                       reservedunmarshal_VkBufferMemoryRequirementsInfo2KHR)
@@ -1519,7 +1501,11 @@
                       reservedunmarshal_VkPhysicalDeviceShaderIntegerDotProductPropertiesKHR)
 
 #endif
-#ifdef VK_KHR_shader_non_semantic_info
+#ifdef VK_KHR_pipeline_library
+void reservedunmarshal_VkPipelineLibraryCreateInfoKHR(
+    VulkanStream* vkStream, VkStructureType rootType,
+    VkPipelineLibraryCreateInfoKHR* forUnmarshaling, uint8_t** ptr);
+
 #endif
 #ifdef VK_KHR_synchronization2
 DEFINE_ALIAS_FUNCTION(reservedunmarshal_VkMemoryBarrier2, reservedunmarshal_VkMemoryBarrier2KHR)
@@ -1673,8 +1659,6 @@
     VkPipelineRasterizationStateStreamCreateInfoEXT* forUnmarshaling, uint8_t** ptr);
 
 #endif
-#ifdef VK_AMD_gpu_shader_half_float
-#endif
 #ifdef VK_EXT_texture_compression_astc_hdr
 DEFINE_ALIAS_FUNCTION(reservedunmarshal_VkPhysicalDeviceTextureCompressionASTCHDRFeatures,
                       reservedunmarshal_VkPhysicalDeviceTextureCompressionASTCHDRFeaturesEXT)
@@ -1690,10 +1674,6 @@
     VkPipelineRasterizationDepthClipStateCreateInfoEXT* forUnmarshaling, uint8_t** ptr);
 
 #endif
-#ifdef VK_EXT_swapchain_colorspace
-#endif
-#ifdef VK_EXT_queue_family_foreign
-#endif
 #ifdef VK_EXT_debug_utils
 void reservedunmarshal_VkDebugUtilsLabelEXT(VulkanStream* vkStream, VkStructureType rootType,
                                             VkDebugUtilsLabelEXT* forUnmarshaling, uint8_t** ptr);
@@ -1717,8 +1697,6 @@
                                                     uint8_t** ptr);
 
 #endif
-#ifdef VK_ANDROID_external_memory_android_hardware_buffer
-#endif
 #ifdef VK_EXT_inline_uniform_block
 DEFINE_ALIAS_FUNCTION(reservedunmarshal_VkPhysicalDeviceInlineUniformBlockFeatures,
                       reservedunmarshal_VkPhysicalDeviceInlineUniformBlockFeaturesEXT)
@@ -1733,8 +1711,6 @@
                       reservedunmarshal_VkDescriptorPoolInlineUniformBlockCreateInfoEXT)
 
 #endif
-#ifdef VK_EXT_shader_stencil_export
-#endif
 #ifdef VK_EXT_vertex_attribute_divisor
 void reservedunmarshal_VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT(
     VulkanStream* vkStream, VkStructureType rootType,
@@ -1761,10 +1737,6 @@
                       reservedunmarshal_VkPipelineCreationFeedbackEXT)
 
 #endif
-#ifdef VK_NV_shader_subgroup_partitioned
-#endif
-#ifdef VK_EXT_metal_surface
-#endif
 #ifdef VK_EXT_fragment_density_map
 void reservedunmarshal_VkPhysicalDeviceFragmentDensityMapFeaturesEXT(
     VulkanStream* vkStream, VkStructureType rootType,
@@ -1989,8 +1961,6 @@
                       reservedunmarshal_VkPhysicalDevicePipelineCreationCacheControlFeaturesEXT)
 
 #endif
-#ifdef VK_EXT_metal_objects
-#endif
 #ifdef VK_EXT_graphics_pipeline_library
 void reservedunmarshal_VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT(
     VulkanStream* vkStream, VkStructureType rootType,
@@ -2071,16 +2041,42 @@
                                           VkCreateBlobGOOGLE* forUnmarshaling, uint8_t** ptr);
 
 #endif
-#ifdef VK_EXT_load_store_op_none
-#endif
 #ifdef VK_EXT_image_compression_control_swapchain
 void reservedunmarshal_VkPhysicalDeviceImageCompressionControlSwapchainFeaturesEXT(
     VulkanStream* vkStream, VkStructureType rootType,
     VkPhysicalDeviceImageCompressionControlSwapchainFeaturesEXT* forUnmarshaling, uint8_t** ptr);
 
 #endif
-#ifdef VK_QNX_external_memory_screen_buffer
-#endif
+#ifdef VK_KHR_ray_tracing_pipeline
+void reservedunmarshal_VkRayTracingShaderGroupCreateInfoKHR(
+    VulkanStream* vkStream, VkStructureType rootType,
+    VkRayTracingShaderGroupCreateInfoKHR* forUnmarshaling, uint8_t** ptr);
 
+void reservedunmarshal_VkRayTracingPipelineInterfaceCreateInfoKHR(
+    VulkanStream* vkStream, VkStructureType rootType,
+    VkRayTracingPipelineInterfaceCreateInfoKHR* forUnmarshaling, uint8_t** ptr);
+
+void reservedunmarshal_VkRayTracingPipelineCreateInfoKHR(
+    VulkanStream* vkStream, VkStructureType rootType,
+    VkRayTracingPipelineCreateInfoKHR* forUnmarshaling, uint8_t** ptr);
+
+void reservedunmarshal_VkPhysicalDeviceRayTracingPipelineFeaturesKHR(
+    VulkanStream* vkStream, VkStructureType rootType,
+    VkPhysicalDeviceRayTracingPipelineFeaturesKHR* forUnmarshaling, uint8_t** ptr);
+
+void reservedunmarshal_VkPhysicalDeviceRayTracingPipelinePropertiesKHR(
+    VulkanStream* vkStream, VkStructureType rootType,
+    VkPhysicalDeviceRayTracingPipelinePropertiesKHR* forUnmarshaling, uint8_t** ptr);
+
+void reservedunmarshal_VkStridedDeviceAddressRegionKHR(
+    VulkanStream* vkStream, VkStructureType rootType,
+    VkStridedDeviceAddressRegionKHR* forUnmarshaling, uint8_t** ptr);
+
+void reservedunmarshal_VkTraceRaysIndirectCommandKHR(VulkanStream* vkStream,
+                                                     VkStructureType rootType,
+                                                     VkTraceRaysIndirectCommandKHR* forUnmarshaling,
+                                                     uint8_t** ptr);
+
+#endif
 }  // namespace vk
 }  // namespace gfxstream
diff --git a/host/vulkan/cereal/common/goldfish_vk_transform.cpp b/host/vulkan/cereal/common/goldfish_vk_transform.cpp
index 70e4cdf..5aba5d9 100644
--- a/host/vulkan/cereal/common/goldfish_vk_transform.cpp
+++ b/host/vulkan/cereal/common/goldfish_vk_transform.cpp
@@ -6138,8 +6138,6 @@
 }
 
 #endif
-#ifdef VK_KHR_surface
-#endif
 #ifdef VK_KHR_swapchain
 void transform_tohost_VkSwapchainCreateInfoKHR(VkDecoderGlobalState* resourceTracker,
                                                VkSwapchainCreateInfoKHR* toTransform) {
@@ -6288,12 +6286,6 @@
 }
 
 #endif
-#ifdef VK_KHR_xcb_surface
-#endif
-#ifdef VK_KHR_android_surface
-#endif
-#ifdef VK_KHR_win32_surface
-#endif
 #ifdef VK_KHR_dynamic_rendering
 void transform_tohost_VkRenderingFragmentShadingRateAttachmentInfoKHR(
     VkDecoderGlobalState* resourceTracker,
@@ -6376,24 +6368,6 @@
 }
 
 #endif
-#ifdef VK_KHR_get_physical_device_properties2
-#endif
-#ifdef VK_KHR_maintenance1
-#endif
-#ifdef VK_KHR_external_memory_capabilities
-#endif
-#ifdef VK_KHR_external_memory
-#endif
-#ifdef VK_KHR_external_memory_win32
-#endif
-#ifdef VK_KHR_external_memory_fd
-#endif
-#ifdef VK_KHR_external_semaphore_capabilities
-#endif
-#ifdef VK_KHR_external_semaphore
-#endif
-#ifdef VK_KHR_external_semaphore_win32
-#endif
 #ifdef VK_KHR_external_semaphore_fd
 void transform_tohost_VkImportSemaphoreFdInfoKHR(VkDecoderGlobalState* resourceTracker,
                                                  VkImportSemaphoreFdInfoKHR* toTransform) {
@@ -6432,8 +6406,6 @@
 }
 
 #endif
-#ifdef VK_KHR_shader_float16_int8
-#endif
 #ifdef VK_KHR_incremental_present
 void transform_tohost_VkRectLayerKHR(VkDecoderGlobalState* resourceTracker,
                                      VkRectLayerKHR* toTransform) {
@@ -6514,16 +6486,6 @@
 }
 
 #endif
-#ifdef VK_KHR_descriptor_update_template
-#endif
-#ifdef VK_KHR_imageless_framebuffer
-#endif
-#ifdef VK_KHR_create_renderpass2
-#endif
-#ifdef VK_KHR_external_fence_capabilities
-#endif
-#ifdef VK_KHR_external_fence
-#endif
 #ifdef VK_KHR_external_fence_fd
 void transform_tohost_VkImportFenceFdInfoKHR(VkDecoderGlobalState* resourceTracker,
                                              VkImportFenceFdInfoKHR* toTransform) {
@@ -6562,30 +6524,6 @@
 }
 
 #endif
-#ifdef VK_KHR_maintenance2
-#endif
-#ifdef VK_KHR_dedicated_allocation
-#endif
-#ifdef VK_KHR_storage_buffer_storage_class
-#endif
-#ifdef VK_KHR_get_memory_requirements2
-#endif
-#ifdef VK_KHR_image_format_list
-#endif
-#ifdef VK_KHR_sampler_ycbcr_conversion
-#endif
-#ifdef VK_KHR_bind_memory2
-#endif
-#ifdef VK_KHR_maintenance3
-#endif
-#ifdef VK_KHR_shader_subgroup_extended_types
-#endif
-#ifdef VK_KHR_vulkan_memory_model
-#endif
-#ifdef VK_KHR_shader_terminate_invocation
-#endif
-#ifdef VK_KHR_buffer_device_address
-#endif
 #ifdef VK_KHR_pipeline_executable_properties
 void transform_tohost_VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR(
     VkDecoderGlobalState* resourceTracker,
@@ -6716,9 +6654,25 @@
 }
 
 #endif
-#ifdef VK_KHR_shader_integer_dot_product
-#endif
-#ifdef VK_KHR_shader_non_semantic_info
+#ifdef VK_KHR_pipeline_library
+void transform_tohost_VkPipelineLibraryCreateInfoKHR(VkDecoderGlobalState* resourceTracker,
+                                                     VkPipelineLibraryCreateInfoKHR* toTransform) {
+    (void)resourceTracker;
+    (void)toTransform;
+    if (toTransform->pNext) {
+        transform_tohost_extension_struct(resourceTracker, (void*)(toTransform->pNext));
+    }
+}
+
+void transform_fromhost_VkPipelineLibraryCreateInfoKHR(
+    VkDecoderGlobalState* resourceTracker, VkPipelineLibraryCreateInfoKHR* toTransform) {
+    (void)resourceTracker;
+    (void)toTransform;
+    if (toTransform->pNext) {
+        transform_fromhost_extension_struct(resourceTracker, (void*)(toTransform->pNext));
+    }
+}
+
 #endif
 #ifdef VK_KHR_synchronization2
 void transform_tohost_VkQueueFamilyCheckpointProperties2NV(
@@ -6758,14 +6712,6 @@
 }
 
 #endif
-#ifdef VK_KHR_zero_initialize_workgroup_memory
-#endif
-#ifdef VK_KHR_copy_commands2
-#endif
-#ifdef VK_KHR_format_feature_flags2
-#endif
-#ifdef VK_KHR_maintenance4
-#endif
 #ifdef VK_KHR_maintenance5
 void transform_tohost_VkPhysicalDeviceMaintenance5FeaturesKHR(
     VkDecoderGlobalState* resourceTracker, VkPhysicalDeviceMaintenance5FeaturesKHR* toTransform) {
@@ -7094,10 +7040,6 @@
 }
 
 #endif
-#ifdef VK_AMD_gpu_shader_half_float
-#endif
-#ifdef VK_EXT_texture_compression_astc_hdr
-#endif
 #ifdef VK_EXT_depth_clip_enable
 void transform_tohost_VkPhysicalDeviceDepthClipEnableFeaturesEXT(
     VkDecoderGlobalState* resourceTracker,
@@ -7140,10 +7082,6 @@
 }
 
 #endif
-#ifdef VK_EXT_swapchain_colorspace
-#endif
-#ifdef VK_EXT_queue_family_foreign
-#endif
 #ifdef VK_EXT_debug_utils
 void transform_tohost_VkDebugUtilsLabelEXT(VkDecoderGlobalState* resourceTracker,
                                            VkDebugUtilsLabelEXT* toTransform) {
@@ -7284,12 +7222,6 @@
 }
 
 #endif
-#ifdef VK_ANDROID_external_memory_android_hardware_buffer
-#endif
-#ifdef VK_EXT_inline_uniform_block
-#endif
-#ifdef VK_EXT_shader_stencil_export
-#endif
 #ifdef VK_EXT_vertex_attribute_divisor
 void transform_tohost_VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT(
     VkDecoderGlobalState* resourceTracker,
@@ -7386,12 +7318,6 @@
 }
 
 #endif
-#ifdef VK_EXT_pipeline_creation_feedback
-#endif
-#ifdef VK_NV_shader_subgroup_partitioned
-#endif
-#ifdef VK_EXT_metal_surface
-#endif
 #ifdef VK_EXT_fragment_density_map
 void transform_tohost_VkPhysicalDeviceFragmentDensityMapFeaturesEXT(
     VkDecoderGlobalState* resourceTracker,
@@ -7466,12 +7392,6 @@
 }
 
 #endif
-#ifdef VK_EXT_scalar_block_layout
-#endif
-#ifdef VK_EXT_subgroup_size_control
-#endif
-#ifdef VK_EXT_tooling_info
-#endif
 #ifdef VK_EXT_validation_features
 void transform_tohost_VkValidationFeaturesEXT(VkDecoderGlobalState* resourceTracker,
                                               VkValidationFeaturesEXT* toTransform) {
@@ -8022,8 +7942,6 @@
 }
 
 #endif
-#ifdef VK_EXT_shader_demote_to_helper_invocation
-#endif
 #ifdef VK_EXT_texel_buffer_alignment
 void transform_tohost_VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT(
     VkDecoderGlobalState* resourceTracker,
@@ -8206,12 +8124,6 @@
 }
 
 #endif
-#ifdef VK_EXT_private_data
-#endif
-#ifdef VK_EXT_pipeline_creation_cache_control
-#endif
-#ifdef VK_EXT_metal_objects
-#endif
 #ifdef VK_EXT_graphics_pipeline_library
 void transform_tohost_VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT(
     VkDecoderGlobalState* resourceTracker,
@@ -8294,8 +8206,6 @@
 }
 
 #endif
-#ifdef VK_EXT_image_robustness
-#endif
 #ifdef VK_EXT_image_compression_control
 void transform_tohost_VkPhysicalDeviceImageCompressionControlFeaturesEXT(
     VkDecoderGlobalState* resourceTracker,
@@ -8514,8 +8424,6 @@
 }
 
 #endif
-#ifdef VK_EXT_load_store_op_none
-#endif
 #ifdef VK_EXT_image_compression_control_swapchain
 void transform_tohost_VkPhysicalDeviceImageCompressionControlSwapchainFeaturesEXT(
     VkDecoderGlobalState* resourceTracker,
@@ -8538,7 +8446,187 @@
 }
 
 #endif
-#ifdef VK_QNX_external_memory_screen_buffer
+#ifdef VK_KHR_ray_tracing_pipeline
+void transform_tohost_VkRayTracingShaderGroupCreateInfoKHR(
+    VkDecoderGlobalState* resourceTracker, VkRayTracingShaderGroupCreateInfoKHR* toTransform) {
+    (void)resourceTracker;
+    (void)toTransform;
+    if (toTransform->pNext) {
+        transform_tohost_extension_struct(resourceTracker, (void*)(toTransform->pNext));
+    }
+}
+
+void transform_fromhost_VkRayTracingShaderGroupCreateInfoKHR(
+    VkDecoderGlobalState* resourceTracker, VkRayTracingShaderGroupCreateInfoKHR* toTransform) {
+    (void)resourceTracker;
+    (void)toTransform;
+    if (toTransform->pNext) {
+        transform_fromhost_extension_struct(resourceTracker, (void*)(toTransform->pNext));
+    }
+}
+
+void transform_tohost_VkRayTracingPipelineInterfaceCreateInfoKHR(
+    VkDecoderGlobalState* resourceTracker,
+    VkRayTracingPipelineInterfaceCreateInfoKHR* toTransform) {
+    (void)resourceTracker;
+    (void)toTransform;
+    if (toTransform->pNext) {
+        transform_tohost_extension_struct(resourceTracker, (void*)(toTransform->pNext));
+    }
+}
+
+void transform_fromhost_VkRayTracingPipelineInterfaceCreateInfoKHR(
+    VkDecoderGlobalState* resourceTracker,
+    VkRayTracingPipelineInterfaceCreateInfoKHR* toTransform) {
+    (void)resourceTracker;
+    (void)toTransform;
+    if (toTransform->pNext) {
+        transform_fromhost_extension_struct(resourceTracker, (void*)(toTransform->pNext));
+    }
+}
+
+void transform_tohost_VkRayTracingPipelineCreateInfoKHR(
+    VkDecoderGlobalState* resourceTracker, VkRayTracingPipelineCreateInfoKHR* toTransform) {
+    (void)resourceTracker;
+    (void)toTransform;
+    if (toTransform->pNext) {
+        transform_tohost_extension_struct(resourceTracker, (void*)(toTransform->pNext));
+    }
+    if (toTransform) {
+        if (toTransform->pStages) {
+            for (uint32_t i = 0; i < (uint32_t)toTransform->stageCount; ++i) {
+                transform_tohost_VkPipelineShaderStageCreateInfo(
+                    resourceTracker, (VkPipelineShaderStageCreateInfo*)(toTransform->pStages + i));
+            }
+        }
+    }
+    if (toTransform) {
+        if (toTransform->pGroups) {
+            for (uint32_t i = 0; i < (uint32_t)toTransform->groupCount; ++i) {
+                transform_tohost_VkRayTracingShaderGroupCreateInfoKHR(
+                    resourceTracker,
+                    (VkRayTracingShaderGroupCreateInfoKHR*)(toTransform->pGroups + i));
+            }
+        }
+    }
+    if (toTransform->pLibraryInfo) {
+        transform_tohost_VkPipelineLibraryCreateInfoKHR(
+            resourceTracker, (VkPipelineLibraryCreateInfoKHR*)(toTransform->pLibraryInfo));
+    }
+    if (toTransform->pLibraryInterface) {
+        transform_tohost_VkRayTracingPipelineInterfaceCreateInfoKHR(
+            resourceTracker,
+            (VkRayTracingPipelineInterfaceCreateInfoKHR*)(toTransform->pLibraryInterface));
+    }
+    if (toTransform->pDynamicState) {
+        transform_tohost_VkPipelineDynamicStateCreateInfo(
+            resourceTracker, (VkPipelineDynamicStateCreateInfo*)(toTransform->pDynamicState));
+    }
+}
+
+void transform_fromhost_VkRayTracingPipelineCreateInfoKHR(
+    VkDecoderGlobalState* resourceTracker, VkRayTracingPipelineCreateInfoKHR* toTransform) {
+    (void)resourceTracker;
+    (void)toTransform;
+    if (toTransform->pNext) {
+        transform_fromhost_extension_struct(resourceTracker, (void*)(toTransform->pNext));
+    }
+    if (toTransform) {
+        if (toTransform->pStages) {
+            for (uint32_t i = 0; i < (uint32_t)toTransform->stageCount; ++i) {
+                transform_fromhost_VkPipelineShaderStageCreateInfo(
+                    resourceTracker, (VkPipelineShaderStageCreateInfo*)(toTransform->pStages + i));
+            }
+        }
+    }
+    if (toTransform) {
+        if (toTransform->pGroups) {
+            for (uint32_t i = 0; i < (uint32_t)toTransform->groupCount; ++i) {
+                transform_fromhost_VkRayTracingShaderGroupCreateInfoKHR(
+                    resourceTracker,
+                    (VkRayTracingShaderGroupCreateInfoKHR*)(toTransform->pGroups + i));
+            }
+        }
+    }
+    if (toTransform->pLibraryInfo) {
+        transform_fromhost_VkPipelineLibraryCreateInfoKHR(
+            resourceTracker, (VkPipelineLibraryCreateInfoKHR*)(toTransform->pLibraryInfo));
+    }
+    if (toTransform->pLibraryInterface) {
+        transform_fromhost_VkRayTracingPipelineInterfaceCreateInfoKHR(
+            resourceTracker,
+            (VkRayTracingPipelineInterfaceCreateInfoKHR*)(toTransform->pLibraryInterface));
+    }
+    if (toTransform->pDynamicState) {
+        transform_fromhost_VkPipelineDynamicStateCreateInfo(
+            resourceTracker, (VkPipelineDynamicStateCreateInfo*)(toTransform->pDynamicState));
+    }
+}
+
+void transform_tohost_VkPhysicalDeviceRayTracingPipelineFeaturesKHR(
+    VkDecoderGlobalState* resourceTracker,
+    VkPhysicalDeviceRayTracingPipelineFeaturesKHR* toTransform) {
+    (void)resourceTracker;
+    (void)toTransform;
+    if (toTransform->pNext) {
+        transform_tohost_extension_struct(resourceTracker, (void*)(toTransform->pNext));
+    }
+}
+
+void transform_fromhost_VkPhysicalDeviceRayTracingPipelineFeaturesKHR(
+    VkDecoderGlobalState* resourceTracker,
+    VkPhysicalDeviceRayTracingPipelineFeaturesKHR* toTransform) {
+    (void)resourceTracker;
+    (void)toTransform;
+    if (toTransform->pNext) {
+        transform_fromhost_extension_struct(resourceTracker, (void*)(toTransform->pNext));
+    }
+}
+
+void transform_tohost_VkPhysicalDeviceRayTracingPipelinePropertiesKHR(
+    VkDecoderGlobalState* resourceTracker,
+    VkPhysicalDeviceRayTracingPipelinePropertiesKHR* toTransform) {
+    (void)resourceTracker;
+    (void)toTransform;
+    if (toTransform->pNext) {
+        transform_tohost_extension_struct(resourceTracker, (void*)(toTransform->pNext));
+    }
+}
+
+void transform_fromhost_VkPhysicalDeviceRayTracingPipelinePropertiesKHR(
+    VkDecoderGlobalState* resourceTracker,
+    VkPhysicalDeviceRayTracingPipelinePropertiesKHR* toTransform) {
+    (void)resourceTracker;
+    (void)toTransform;
+    if (toTransform->pNext) {
+        transform_fromhost_extension_struct(resourceTracker, (void*)(toTransform->pNext));
+    }
+}
+
+void transform_tohost_VkStridedDeviceAddressRegionKHR(
+    VkDecoderGlobalState* resourceTracker, VkStridedDeviceAddressRegionKHR* toTransform) {
+    (void)resourceTracker;
+    (void)toTransform;
+}
+
+void transform_fromhost_VkStridedDeviceAddressRegionKHR(
+    VkDecoderGlobalState* resourceTracker, VkStridedDeviceAddressRegionKHR* toTransform) {
+    (void)resourceTracker;
+    (void)toTransform;
+}
+
+void transform_tohost_VkTraceRaysIndirectCommandKHR(VkDecoderGlobalState* resourceTracker,
+                                                    VkTraceRaysIndirectCommandKHR* toTransform) {
+    (void)resourceTracker;
+    (void)toTransform;
+}
+
+void transform_fromhost_VkTraceRaysIndirectCommandKHR(VkDecoderGlobalState* resourceTracker,
+                                                      VkTraceRaysIndirectCommandKHR* toTransform) {
+    (void)resourceTracker;
+    (void)toTransform;
+}
+
 #endif
 void transform_tohost_extension_struct(VkDecoderGlobalState* resourceTracker,
                                        void* structExtension_out) {
@@ -9279,6 +9367,14 @@
             break;
         }
 #endif
+#ifdef VK_KHR_pipeline_library
+        case VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR: {
+            transform_tohost_VkPipelineLibraryCreateInfoKHR(
+                resourceTracker,
+                reinterpret_cast<VkPipelineLibraryCreateInfoKHR*>(structExtension_out));
+            break;
+        }
+#endif
 #ifdef VK_KHR_synchronization2
         case VK_STRUCTURE_TYPE_QUEUE_FAMILY_CHECKPOINT_PROPERTIES_2_NV: {
             transform_tohost_VkQueueFamilyCheckpointProperties2NV(
@@ -9716,6 +9812,20 @@
             break;
         }
 #endif
+#ifdef VK_KHR_ray_tracing_pipeline
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR: {
+            transform_tohost_VkPhysicalDeviceRayTracingPipelineFeaturesKHR(
+                resourceTracker, reinterpret_cast<VkPhysicalDeviceRayTracingPipelineFeaturesKHR*>(
+                                     structExtension_out));
+            break;
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR: {
+            transform_tohost_VkPhysicalDeviceRayTracingPipelinePropertiesKHR(
+                resourceTracker, reinterpret_cast<VkPhysicalDeviceRayTracingPipelinePropertiesKHR*>(
+                                     structExtension_out));
+            break;
+        }
+#endif
         default: {
             return;
         }
@@ -10461,6 +10571,14 @@
             break;
         }
 #endif
+#ifdef VK_KHR_pipeline_library
+        case VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR: {
+            transform_fromhost_VkPipelineLibraryCreateInfoKHR(
+                resourceTracker,
+                reinterpret_cast<VkPipelineLibraryCreateInfoKHR*>(structExtension_out));
+            break;
+        }
+#endif
 #ifdef VK_KHR_synchronization2
         case VK_STRUCTURE_TYPE_QUEUE_FAMILY_CHECKPOINT_PROPERTIES_2_NV: {
             transform_fromhost_VkQueueFamilyCheckpointProperties2NV(
@@ -10898,6 +11016,20 @@
             break;
         }
 #endif
+#ifdef VK_KHR_ray_tracing_pipeline
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR: {
+            transform_fromhost_VkPhysicalDeviceRayTracingPipelineFeaturesKHR(
+                resourceTracker, reinterpret_cast<VkPhysicalDeviceRayTracingPipelineFeaturesKHR*>(
+                                     structExtension_out));
+            break;
+        }
+        case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR: {
+            transform_fromhost_VkPhysicalDeviceRayTracingPipelinePropertiesKHR(
+                resourceTracker, reinterpret_cast<VkPhysicalDeviceRayTracingPipelinePropertiesKHR*>(
+                                     structExtension_out));
+            break;
+        }
+#endif
         default: {
             return;
         }
diff --git a/host/vulkan/cereal/common/goldfish_vk_transform.h b/host/vulkan/cereal/common/goldfish_vk_transform.h
index 832a816..45358d5 100644
--- a/host/vulkan/cereal/common/goldfish_vk_transform.h
+++ b/host/vulkan/cereal/common/goldfish_vk_transform.h
@@ -1815,8 +1815,6 @@
     VkDecoderGlobalState* resourceTracker, VkDeviceImageMemoryRequirements* toTransform);
 
 #endif
-#ifdef VK_KHR_surface
-#endif
 #ifdef VK_KHR_swapchain
 void transform_tohost_VkSwapchainCreateInfoKHR(VkDecoderGlobalState* resourceTracker,
                                                VkSwapchainCreateInfoKHR* toTransform);
@@ -1867,12 +1865,6 @@
     VkDecoderGlobalState* resourceTracker, VkDeviceGroupSwapchainCreateInfoKHR* toTransform);
 
 #endif
-#ifdef VK_KHR_xcb_surface
-#endif
-#ifdef VK_KHR_android_surface
-#endif
-#ifdef VK_KHR_win32_surface
-#endif
 #ifdef VK_KHR_dynamic_rendering
 DEFINE_ALIAS_FUNCTION(transform_tohost_VkRenderingInfo, transform_tohost_VkRenderingInfoKHR)
 
@@ -1992,8 +1984,6 @@
                       transform_fromhost_VkPhysicalDeviceSparseImageFormatInfo2KHR)
 
 #endif
-#ifdef VK_KHR_maintenance1
-#endif
 #ifdef VK_KHR_external_memory_capabilities
 DEFINE_ALIAS_FUNCTION(transform_tohost_VkExternalMemoryProperties,
                       transform_tohost_VkExternalMemoryPropertiesKHR)
@@ -2052,10 +2042,6 @@
                       transform_fromhost_VkExportMemoryAllocateInfoKHR)
 
 #endif
-#ifdef VK_KHR_external_memory_win32
-#endif
-#ifdef VK_KHR_external_memory_fd
-#endif
 #ifdef VK_KHR_external_semaphore_capabilities
 DEFINE_ALIAS_FUNCTION(transform_tohost_VkPhysicalDeviceExternalSemaphoreInfo,
                       transform_tohost_VkPhysicalDeviceExternalSemaphoreInfoKHR)
@@ -2078,8 +2064,6 @@
                       transform_fromhost_VkExportSemaphoreCreateInfoKHR)
 
 #endif
-#ifdef VK_KHR_external_semaphore_win32
-#endif
 #ifdef VK_KHR_external_semaphore_fd
 void transform_tohost_VkImportSemaphoreFdInfoKHR(VkDecoderGlobalState* resourceTracker,
                                                  VkImportSemaphoreFdInfoKHR* toTransform);
@@ -2291,8 +2275,6 @@
                       transform_fromhost_VkMemoryDedicatedAllocateInfoKHR)
 
 #endif
-#ifdef VK_KHR_storage_buffer_storage_class
-#endif
 #ifdef VK_KHR_get_memory_requirements2
 DEFINE_ALIAS_FUNCTION(transform_tohost_VkBufferMemoryRequirementsInfo2,
                       transform_tohost_VkBufferMemoryRequirementsInfo2KHR)
@@ -2517,7 +2499,13 @@
                       transform_fromhost_VkPhysicalDeviceShaderIntegerDotProductPropertiesKHR)
 
 #endif
-#ifdef VK_KHR_shader_non_semantic_info
+#ifdef VK_KHR_pipeline_library
+void transform_tohost_VkPipelineLibraryCreateInfoKHR(VkDecoderGlobalState* resourceTracker,
+                                                     VkPipelineLibraryCreateInfoKHR* toTransform);
+
+void transform_fromhost_VkPipelineLibraryCreateInfoKHR(VkDecoderGlobalState* resourceTracker,
+                                                       VkPipelineLibraryCreateInfoKHR* toTransform);
+
 #endif
 #ifdef VK_KHR_synchronization2
 DEFINE_ALIAS_FUNCTION(transform_tohost_VkMemoryBarrier2, transform_tohost_VkMemoryBarrier2KHR)
@@ -2780,8 +2768,6 @@
     VkPipelineRasterizationStateStreamCreateInfoEXT* toTransform);
 
 #endif
-#ifdef VK_AMD_gpu_shader_half_float
-#endif
 #ifdef VK_EXT_texture_compression_astc_hdr
 DEFINE_ALIAS_FUNCTION(transform_tohost_VkPhysicalDeviceTextureCompressionASTCHDRFeatures,
                       transform_tohost_VkPhysicalDeviceTextureCompressionASTCHDRFeaturesEXT)
@@ -2806,10 +2792,6 @@
     VkPipelineRasterizationDepthClipStateCreateInfoEXT* toTransform);
 
 #endif
-#ifdef VK_EXT_swapchain_colorspace
-#endif
-#ifdef VK_EXT_queue_family_foreign
-#endif
 #ifdef VK_EXT_debug_utils
 void transform_tohost_VkDebugUtilsLabelEXT(VkDecoderGlobalState* resourceTracker,
                                            VkDebugUtilsLabelEXT* toTransform);
@@ -2842,8 +2824,6 @@
                                                      VkDebugUtilsObjectTagInfoEXT* toTransform);
 
 #endif
-#ifdef VK_ANDROID_external_memory_android_hardware_buffer
-#endif
 #ifdef VK_EXT_inline_uniform_block
 DEFINE_ALIAS_FUNCTION(transform_tohost_VkPhysicalDeviceInlineUniformBlockFeatures,
                       transform_tohost_VkPhysicalDeviceInlineUniformBlockFeaturesEXT)
@@ -2870,8 +2850,6 @@
                       transform_fromhost_VkDescriptorPoolInlineUniformBlockCreateInfoEXT)
 
 #endif
-#ifdef VK_EXT_shader_stencil_export
-#endif
 #ifdef VK_EXT_vertex_attribute_divisor
 void transform_tohost_VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT(
     VkDecoderGlobalState* resourceTracker,
@@ -2918,10 +2896,6 @@
                       transform_fromhost_VkPipelineCreationFeedbackEXT)
 
 #endif
-#ifdef VK_NV_shader_subgroup_partitioned
-#endif
-#ifdef VK_EXT_metal_surface
-#endif
 #ifdef VK_EXT_fragment_density_map
 void transform_tohost_VkPhysicalDeviceFragmentDensityMapFeaturesEXT(
     VkDecoderGlobalState* resourceTracker,
@@ -3286,8 +3260,6 @@
                       transform_fromhost_VkPhysicalDevicePipelineCreationCacheControlFeaturesEXT)
 
 #endif
-#ifdef VK_EXT_metal_objects
-#endif
 #ifdef VK_EXT_graphics_pipeline_library
 void transform_tohost_VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT(
     VkDecoderGlobalState* resourceTracker,
@@ -3416,8 +3388,6 @@
                                            VkCreateBlobGOOGLE* toTransform);
 
 #endif
-#ifdef VK_EXT_load_store_op_none
-#endif
 #ifdef VK_EXT_image_compression_control_swapchain
 void transform_tohost_VkPhysicalDeviceImageCompressionControlSwapchainFeaturesEXT(
     VkDecoderGlobalState* resourceTracker,
@@ -3428,8 +3398,53 @@
     VkPhysicalDeviceImageCompressionControlSwapchainFeaturesEXT* toTransform);
 
 #endif
-#ifdef VK_QNX_external_memory_screen_buffer
-#endif
+#ifdef VK_KHR_ray_tracing_pipeline
+void transform_tohost_VkRayTracingShaderGroupCreateInfoKHR(
+    VkDecoderGlobalState* resourceTracker, VkRayTracingShaderGroupCreateInfoKHR* toTransform);
 
+void transform_fromhost_VkRayTracingShaderGroupCreateInfoKHR(
+    VkDecoderGlobalState* resourceTracker, VkRayTracingShaderGroupCreateInfoKHR* toTransform);
+
+void transform_tohost_VkRayTracingPipelineInterfaceCreateInfoKHR(
+    VkDecoderGlobalState* resourceTracker, VkRayTracingPipelineInterfaceCreateInfoKHR* toTransform);
+
+void transform_fromhost_VkRayTracingPipelineInterfaceCreateInfoKHR(
+    VkDecoderGlobalState* resourceTracker, VkRayTracingPipelineInterfaceCreateInfoKHR* toTransform);
+
+void transform_tohost_VkRayTracingPipelineCreateInfoKHR(
+    VkDecoderGlobalState* resourceTracker, VkRayTracingPipelineCreateInfoKHR* toTransform);
+
+void transform_fromhost_VkRayTracingPipelineCreateInfoKHR(
+    VkDecoderGlobalState* resourceTracker, VkRayTracingPipelineCreateInfoKHR* toTransform);
+
+void transform_tohost_VkPhysicalDeviceRayTracingPipelineFeaturesKHR(
+    VkDecoderGlobalState* resourceTracker,
+    VkPhysicalDeviceRayTracingPipelineFeaturesKHR* toTransform);
+
+void transform_fromhost_VkPhysicalDeviceRayTracingPipelineFeaturesKHR(
+    VkDecoderGlobalState* resourceTracker,
+    VkPhysicalDeviceRayTracingPipelineFeaturesKHR* toTransform);
+
+void transform_tohost_VkPhysicalDeviceRayTracingPipelinePropertiesKHR(
+    VkDecoderGlobalState* resourceTracker,
+    VkPhysicalDeviceRayTracingPipelinePropertiesKHR* toTransform);
+
+void transform_fromhost_VkPhysicalDeviceRayTracingPipelinePropertiesKHR(
+    VkDecoderGlobalState* resourceTracker,
+    VkPhysicalDeviceRayTracingPipelinePropertiesKHR* toTransform);
+
+void transform_tohost_VkStridedDeviceAddressRegionKHR(VkDecoderGlobalState* resourceTracker,
+                                                      VkStridedDeviceAddressRegionKHR* toTransform);
+
+void transform_fromhost_VkStridedDeviceAddressRegionKHR(
+    VkDecoderGlobalState* resourceTracker, VkStridedDeviceAddressRegionKHR* toTransform);
+
+void transform_tohost_VkTraceRaysIndirectCommandKHR(VkDecoderGlobalState* resourceTracker,
+                                                    VkTraceRaysIndirectCommandKHR* toTransform);
+
+void transform_fromhost_VkTraceRaysIndirectCommandKHR(VkDecoderGlobalState* resourceTracker,
+                                                      VkTraceRaysIndirectCommandKHR* toTransform);
+
+#endif
 }  // namespace vk
 }  // namespace gfxstream
diff --git a/host/vulkan/cereal/common/vk_struct_id.h b/host/vulkan/cereal/common/vk_struct_id.h
index 72d9b9d..c526dc1 100644
--- a/host/vulkan/cereal/common/vk_struct_id.h
+++ b/host/vulkan/cereal/common/vk_struct_id.h
@@ -122,4 +122,9 @@
                       VK_STRUCTURE_TYPE_EXPORT_METAL_OBJECT_CREATE_INFO_EXT);
 #endif
 
+REGISTER_VK_STRUCT_ID(VkPhysicalDeviceDiagnosticsConfigFeaturesNV,
+                      VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DIAGNOSTICS_CONFIG_FEATURES_NV);
+REGISTER_VK_STRUCT_ID(VkDeviceGroupDeviceCreateInfo,
+                      VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO);
+
 #undef REGISTER_VK_STRUCT_ID
diff --git a/host/vulkan/meson.build b/host/vulkan/meson.build
index ae7e03a..ccc03a9 100644
--- a/host/vulkan/meson.build
+++ b/host/vulkan/meson.build
@@ -13,6 +13,7 @@
   'BufferVk.cpp',
   'ColorBufferVk.cpp',
   'CompositorVk.cpp',
+  'DeviceLostHelper.cpp',
   'DeviceOpTracker.cpp',
   'DisplayVk.cpp',
   'DisplaySurfaceVk.cpp',
diff --git a/host/vulkan/vulkan_gfxstream.h b/host/vulkan/vulkan_gfxstream.h
index a2c288c..a7ac22b 100644
--- a/host/vulkan/vulkan_gfxstream.h
+++ b/host/vulkan/vulkan_gfxstream.h
@@ -69,6 +69,7 @@
 typedef VkResult (VKAPI_PTR *PFN_vkGetBlobGOOGLE)(VkDevice device, VkDeviceMemory memory);
 typedef void (VKAPI_PTR *PFN_vkUpdateDescriptorSetWithTemplateSized2GOOGLE)(VkDevice device, VkDescriptorSet descriptorSet, VkDescriptorUpdateTemplate descriptorUpdateTemplate, uint32_t imageInfoCount, uint32_t bufferInfoCount, uint32_t bufferViewCount, uint32_t inlineUniformBlockCount, const uint32_t* pImageInfoEntryIndices, const uint32_t* pBufferInfoEntryIndices, const uint32_t* pBufferViewEntryIndices, const VkDescriptorImageInfo* pImageInfos, const VkDescriptorBufferInfo* pBufferInfos, const VkBufferView* pBufferViews, const uint8_t* pInlineUniformBlockData);
 typedef void (VKAPI_PTR *PFN_vkQueueSubmitAsync2GOOGLE)(VkQueue queue, uint32_t submitCount, const VkSubmitInfo2* pSubmits, VkFence fence);
+typedef VkResult (VKAPI_PTR *PFN_vkGetSemaphoreGOOGLE)(VkDevice device, VkSemaphore semaphore, uint64_t syncId);
 
 #ifndef VK_NO_PROTOTYPES
 VKAPI_ATTR VkResult VKAPI_CALL vkMapMemoryIntoAddressSpaceGOOGLE(
@@ -227,6 +228,11 @@
     uint32_t                                    submitCount,
     const VkSubmitInfo2*                        pSubmits,
     VkFence                                     fence);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetSemaphoreGOOGLE(
+    VkDevice                                    device,
+    VkSemaphore                                 semaphore,
+    uint64_t                                    syncId);
 #endif
 
 #ifdef __cplusplus
diff --git a/include/OpenGLESDispatch/RenderEGL_extensions_functions.h b/include/OpenGLESDispatch/RenderEGL_extensions_functions.h
index 6e64214..81dbd47 100644
--- a/include/OpenGLESDispatch/RenderEGL_extensions_functions.h
+++ b/include/OpenGLESDispatch/RenderEGL_extensions_functions.h
@@ -28,6 +28,7 @@
   X(EGLImage, eglImportImageANDROID, (EGLDisplay display, EGLImage image)) \
   X(EGLint, eglDebugMessageControlKHR, (EGLDEBUGPROCKHR callback, const EGLAttrib * attrib_list)) \
   X(EGLBoolean, eglSetNativeTextureDecompressionEnabledANDROID, (EGLDisplay display, EGLBoolean enabled)) \
+  X(EGLBoolean, eglSetProgramBinaryLinkStatusEnabledANDROID, (EGLDisplay display, EGLBoolean enabled)) \
 
 EGLAPI EGLint EGLAPIENTRY eglGetMaxGLESVersion(EGLDisplay display);
 EGLAPI void EGLAPIENTRY eglBlitFromCurrentReadBufferANDROID(EGLDisplay display, EGLImageKHR image);
diff --git a/include/OpenGLESDispatch/RenderEGL_extensions_static_translator_namespaced_header.h b/include/OpenGLESDispatch/RenderEGL_extensions_static_translator_namespaced_header.h
index cbc84f1..000337c 100644
--- a/include/OpenGLESDispatch/RenderEGL_extensions_static_translator_namespaced_header.h
+++ b/include/OpenGLESDispatch/RenderEGL_extensions_static_translator_namespaced_header.h
@@ -28,5 +28,6 @@
 EGLAPI EGLImage EGLAPIENTRY eglImportImageANDROID(EGLDisplay display, EGLImage image);
 EGLAPI EGLint EGLAPIENTRY eglDebugMessageControlKHR(EGLDEBUGPROCKHR callback, const EGLAttrib * attrib_list);
 EGLAPI EGLBoolean EGLAPIENTRY eglSetNativeTextureDecompressionEnabledANDROID(EGLDisplay display, EGLBoolean enabled);
+EGLAPI EGLBoolean EGLAPIENTRY eglSetProgramBinaryLinkStatusEnabledANDROID(EGLDisplay display, EGLBoolean enabled);
 } // namespace translator
 } // namespace egl
diff --git a/scripts/glsl-shader-to-spv-c-array.py b/scripts/glsl-shader-to-spv.py
similarity index 62%
rename from scripts/glsl-shader-to-spv-c-array.py
rename to scripts/glsl-shader-to-spv.py
index a2ec5dc..05a0c45 100755
--- a/scripts/glsl-shader-to-spv-c-array.py
+++ b/scripts/glsl-shader-to-spv.py
@@ -7,6 +7,9 @@
 from datetime import datetime
 import sys
 
+BYTES_PER_UINT32 = 4
+
+UINT32_PER_LINE = 8
 
 def main():
     parser = argparse.ArgumentParser(
@@ -30,21 +33,26 @@
         print("Can't find source file: " + str(args.source_file))
         return
 
-    with subprocess.Popen([str(glslc_path), str(args.source_file), '-o', '-'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) as proc, open(args.target_file, mode='wt') as target_file:
+    spv_bytes = None
+    with subprocess.Popen([str(glslc_path), str(args.source_file), '-o', '-'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) as proc:
         if proc.wait() != 0:
             print(proc.stderr.read().decode('utf-8'))
-            return
         spv_bytes = proc.stdout.read()
-        spv_bytes = [int.from_bytes(spv_bytes[i:i + 4], byteorder="little")
-                     for i in range(0, len(spv_bytes), 4)]
-        chunk_size = 4
-        spv_bytes_chunks = [spv_bytes[i:i + chunk_size]
-                            for i in range(0, len(spv_bytes), chunk_size)]
-        spv_bytes_in_c_array = ',\n'.join([', '.join(
+    spv_bytes = [int.from_bytes(spv_bytes[i:i + BYTES_PER_UINT32], byteorder="little")
+                 for i in range(0, len(spv_bytes), BYTES_PER_UINT32)]
+    spv_bytes_chunks = [spv_bytes[i:i + UINT32_PER_LINE]
+                        for i in range(0, len(spv_bytes), UINT32_PER_LINE)]
+    spv_bytes_in_vector = ',\n'.join([', '.join(
             [f'{spv_byte:#010x}' for spv_byte in spv_bytes_chunk]) for spv_bytes_chunk in spv_bytes_chunks])
-        spv_bytes_in_c_array = f'const uint32_t {args.export_symbol}[] = ' + \
-            '{\n' + spv_bytes_in_c_array + '\n};'
-        comments = f"""// Copyright (C) {datetime.today().year} The Android Open Source Project
+    spv_bytes_in_vector = f'const std::vector<uint32_t> {args.export_symbol} = ' + \
+            '{\n' + spv_bytes_in_vector + '\n};'
+
+    source_file_lines = None
+    with open(args.source_file, mode='r') as source_file:
+        source_file_lines = source_file.readlines()
+
+    with open(args.target_file, mode='wt') as target_file:
+        header = f"""// Copyright (C) {datetime.today().year} The Android Open Source Project
 // Copyright (C) {datetime.today().year} Google Inc.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
@@ -59,13 +67,25 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// Autogenerated module {args.target_file}
-// generated by {"python3 " + " ".join(sys.argv)}
-// Please do not modify directly.\n\n"""
-        prelude = "#include <stdint.h>\n\n"
-        target_file.write(comments)
-        target_file.write(prelude)
-        target_file.write(spv_bytes_in_c_array)
+// Please do not modify directly.
+
+// Autogenerated module {args.target_file} generated by:
+//   {"python3 " + " ".join(sys.argv)}
+
+#include <stdint.h>
+#include <vector>
+
+// From {args.source_file}:
+
+"""
+        target_file.write(header)
+
+        for source_file_line in source_file_lines:
+            target_file.write("// " + source_file_line)
+
+        target_file.write("\n\n")
+
+        target_file.write(spv_bytes_in_vector)
 
 
 if __name__ == '__main__':
diff --git a/scripts/print_gfx_logs/vulkan_printer.py b/scripts/print_gfx_logs/vulkan_printer.py
index 378a94f..c0b64e8 100644
--- a/scripts/print_gfx_logs/vulkan_printer.py
+++ b/scripts/print_gfx_logs/vulkan_printer.py
@@ -446,6 +446,13 @@
     pData = printer.write_int("pData", 8, indent, optional=True, count=pDataSize, big_endian=False)
     return
 
+def OP_vkGetSemaphoreGOOGLE(printer, indent: int):
+    printer.write_int("seqno: ", 4, indent)
+    device = printer.write_int("device", 8, indent, signed=False, big_endian=False)
+    semaphore = printer.write_int("semaphore", 8, indent, signed=False, big_endian=False)
+    syncId = printer.write_int("syncId", 8, indent, signed=False, big_endian=False)
+    return
+
 def OP_vkGetSwapchainGrallocUsageANDROID(printer, indent: int):
     printer.write_int("seqno: ", 4, indent)
     device = printer.write_int("device", 8, indent, signed=False, big_endian=False)
diff --git a/third-party/CMakeLists.txt b/third-party/CMakeLists.txt
index ac85e9a..f725700 100644
--- a/third-party/CMakeLists.txt
+++ b/third-party/CMakeLists.txt
@@ -198,6 +198,7 @@
         find_package(PkgConfig REQUIRED)
         pkg_search_module(egl REQUIRED IMPORTED_TARGET GLOBAL egl>=1.5)
         add_library(gfxstream_egl_headers ALIAS PkgConfig::egl)
+    endif()
 endif()
 
 if(WITH_BENCHMARK)
@@ -213,6 +214,7 @@
         endif()
     elseif(DEPENDENCY_RESOLUTION STREQUAL "SYSTEM")
         message(FATAL_ERROR "Not implemented")
+    endif()
 endif()
 
 if(NOT TARGET libdrm_headers)
@@ -227,6 +229,7 @@
         find_package(PkgConfig REQUIRED)
         pkg_search_module(drm REQUIRED IMPORTED_TARGET GLOBAL libdrm)
         add_library(libdrm_headers ALIAS PkgConfig::drm)
+    endif()
 endif()
 
 if(NOT TARGET aemu_common)