Merge "Log snapshot related error messages only when enabled" into main
diff --git a/codegen/vulkan/vulkan-docs-next/xml/vk.xml b/codegen/vulkan/vulkan-docs-next/xml/vk.xml
index 20f350e..f02aac0 100644
--- a/codegen/vulkan/vulkan-docs-next/xml/vk.xml
+++ b/codegen/vulkan/vulkan-docs-next/xml/vk.xml
@@ -13824,11 +13824,12 @@
             <param optional="true" len="pInternalRepresentationCount"><type>VkPipelineExecutableInternalRepresentationKHR</type>* <name>pInternalRepresentations</name></param>
         </command>
         <command queues="graphics" renderpass="both" cmdbufferlevel="primary,secondary" tasks="state">
-            <proto><type>void</type> <name>vkCmdSetLineStippleEXT</name></proto>
+            <proto><type>void</type> <name>vkCmdSetLineStippleKHR</name></proto>
             <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
             <param><type>uint32_t</type> <name>lineStippleFactor</name></param>
             <param><type>uint16_t</type> <name>lineStipplePattern</name></param>
         </command>
+        <command name="vkCmdSetLineStippleEXT" alias="vkCmdSetLineStippleKHR"/>
         <command successcodes="VK_SUCCESS,VK_INCOMPLETE" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
             <proto><type>VkResult</type> <name>vkGetFaultData</name></proto>
             <param><type>VkDevice</type> <name>device</name></param>
@@ -22561,13 +22562,12 @@
                 <enum value="&quot;VK_GOOGLE_extension_455&quot;"       name="VK_GOOGLE_EXTENSION_455_EXTENSION_NAME"/>
             </require>
         </extension>
-        <extension name="VK_EXT_extended_dynamic_state3" number="456" type="device" depends="VK_KHR_get_physical_device_properties2" author="NV" contact="Piers Daniell @pdaniell-nv" supported="vulkan">
+        <extension name="VK_EXT_extended_dynamic_state3" number="456" type="device" depends="VK_KHR_get_physical_device_properties2,VK_VERSION_1_1" author="NV" contact="Piers Daniell @pdaniell-nv" supported="vulkan" ratified="vulkan">
             <require>
                 <enum value="2"                                              name="VK_EXT_EXTENDED_DYNAMIC_STATE_3_SPEC_VERSION"/>
                 <enum value="&quot;VK_EXT_extended_dynamic_state3&quot;"     name="VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME"/>
                 <enum offset="0" extends="VkStructureType"                   name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_FEATURES_EXT"/>
                 <enum offset="1" extends="VkStructureType"                   name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_PROPERTIES_EXT"/>
-                <enum offset="2" extends="VkDynamicState"                    name="VK_DYNAMIC_STATE_TESSELLATION_DOMAIN_ORIGIN_EXT"/>
                 <enum offset="3" extends="VkDynamicState"                    name="VK_DYNAMIC_STATE_DEPTH_CLAMP_ENABLE_EXT"/>
                 <enum offset="4" extends="VkDynamicState"                    name="VK_DYNAMIC_STATE_POLYGON_MODE_EXT"/>
                 <enum offset="5" extends="VkDynamicState"                    name="VK_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT"/>
@@ -22578,21 +22578,10 @@
                 <enum offset="10" extends="VkDynamicState"                   name="VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT"/>
                 <enum offset="11" extends="VkDynamicState"                   name="VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT"/>
                 <enum offset="12" extends="VkDynamicState"                   name="VK_DYNAMIC_STATE_COLOR_WRITE_MASK_EXT"/>
-                <enum offset="13" extends="VkDynamicState"                   name="VK_DYNAMIC_STATE_RASTERIZATION_STREAM_EXT"/>
-                <enum offset="14" extends="VkDynamicState"                   name="VK_DYNAMIC_STATE_CONSERVATIVE_RASTERIZATION_MODE_EXT"/>
-                <enum offset="15" extends="VkDynamicState"                   name="VK_DYNAMIC_STATE_EXTRA_PRIMITIVE_OVERESTIMATION_SIZE_EXT"/>
-                <enum offset="16" extends="VkDynamicState"                   name="VK_DYNAMIC_STATE_DEPTH_CLIP_ENABLE_EXT"/>
-                <enum offset="17" extends="VkDynamicState"                   name="VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_ENABLE_EXT"/>
-                <enum offset="18" extends="VkDynamicState"                   name="VK_DYNAMIC_STATE_COLOR_BLEND_ADVANCED_EXT"/>
-                <enum offset="19" extends="VkDynamicState"                   name="VK_DYNAMIC_STATE_PROVOKING_VERTEX_MODE_EXT"/>
-                <enum offset="20" extends="VkDynamicState"                   name="VK_DYNAMIC_STATE_LINE_RASTERIZATION_MODE_EXT"/>
-                <enum offset="21" extends="VkDynamicState"                   name="VK_DYNAMIC_STATE_LINE_STIPPLE_ENABLE_EXT"/>
-                <enum offset="22" extends="VkDynamicState"                   name="VK_DYNAMIC_STATE_DEPTH_CLIP_NEGATIVE_ONE_TO_ONE_EXT"/>
                 <type name="VkPhysicalDeviceExtendedDynamicState3FeaturesEXT"/>
                 <type name="VkPhysicalDeviceExtendedDynamicState3PropertiesEXT"/>
                 <type name="VkColorBlendEquationEXT"/>
                 <type name="VkColorBlendAdvancedEXT"/>
-                <command name="vkCmdSetTessellationDomainOriginEXT"/>
                 <command name="vkCmdSetDepthClampEnableEXT"/>
                 <command name="vkCmdSetPolygonModeEXT"/>
                 <command name="vkCmdSetRasterizationSamplesEXT"/>
@@ -22603,15 +22592,45 @@
                 <command name="vkCmdSetColorBlendEnableEXT"/>
                 <command name="vkCmdSetColorBlendEquationEXT"/>
                 <command name="vkCmdSetColorWriteMaskEXT"/>
+            </require>
+            <require depends="VK_KHR_maintenance2,VK_VERSION_1_1">
+                <enum offset="2" extends="VkDynamicState"                    name="VK_DYNAMIC_STATE_TESSELLATION_DOMAIN_ORIGIN_EXT"/>
+                <command name="vkCmdSetTessellationDomainOriginEXT"/>
+            </require>
+            <require depends="VK_EXT_transform_feedback">
+                <enum offset="13" extends="VkDynamicState"                   name="VK_DYNAMIC_STATE_RASTERIZATION_STREAM_EXT"/>
                 <command name="vkCmdSetRasterizationStreamEXT"/>
+            </require>
+            <require depends="VK_EXT_conservative_rasterization">
+                <enum offset="14" extends="VkDynamicState"                   name="VK_DYNAMIC_STATE_CONSERVATIVE_RASTERIZATION_MODE_EXT"/>
+                <enum offset="15" extends="VkDynamicState"                   name="VK_DYNAMIC_STATE_EXTRA_PRIMITIVE_OVERESTIMATION_SIZE_EXT"/>
                 <command name="vkCmdSetConservativeRasterizationModeEXT"/>
                 <command name="vkCmdSetExtraPrimitiveOverestimationSizeEXT"/>
+            </require>
+            <require depends="VK_EXT_depth_clip_enable">
+                <enum offset="16" extends="VkDynamicState"                   name="VK_DYNAMIC_STATE_DEPTH_CLIP_ENABLE_EXT"/>
                 <command name="vkCmdSetDepthClipEnableEXT"/>
+            </require>
+            <require depends="VK_EXT_sample_locations">
+                <enum offset="17" extends="VkDynamicState"                   name="VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_ENABLE_EXT"/>
                 <command name="vkCmdSetSampleLocationsEnableEXT"/>
+            </require>
+            <require depends="VK_EXT_blend_operation_advanced">
+                <enum offset="18" extends="VkDynamicState"                   name="VK_DYNAMIC_STATE_COLOR_BLEND_ADVANCED_EXT"/>
                 <command name="vkCmdSetColorBlendAdvancedEXT"/>
+            </require>
+            <require depends="VK_EXT_provoking_vertex">
+                <enum offset="19" extends="VkDynamicState"                   name="VK_DYNAMIC_STATE_PROVOKING_VERTEX_MODE_EXT"/>
                 <command name="vkCmdSetProvokingVertexModeEXT"/>
+            </require>
+            <require depends="VK_EXT_line_rasterization">
+                <enum offset="20" extends="VkDynamicState"                   name="VK_DYNAMIC_STATE_LINE_RASTERIZATION_MODE_EXT"/>
+                <enum offset="21" extends="VkDynamicState"                   name="VK_DYNAMIC_STATE_LINE_STIPPLE_ENABLE_EXT"/>
                 <command name="vkCmdSetLineRasterizationModeEXT"/>
                 <command name="vkCmdSetLineStippleEnableEXT"/>
+            </require>
+            <require depends="VK_EXT_depth_clip_control">
+                <enum offset="22" extends="VkDynamicState"                   name="VK_DYNAMIC_STATE_DEPTH_CLIP_NEGATIVE_ONE_TO_ONE_EXT"/>
                 <command name="vkCmdSetDepthClipNegativeOneToOneEXT"/>
             </require>
             <require depends="VK_NV_clip_space_w_scaling">
@@ -23035,7 +23054,7 @@
                 <type name="VkPhysicalDeviceRayTracingPositionFetchFeaturesKHR"/>
             </require>
         </extension>
-        <extension name="VK_EXT_shader_object" number="483" depends="(VK_KHR_get_physical_device_properties2,VK_VERSION_1_1)+(VK_KHR_dynamic_rendering,VK_VERSION_1_3)" type="device" author="EXT" contact="Daniel Story @daniel-story" supported="vulkan" ratified="vulkan">
+        <extension name="VK_EXT_shader_object" number="483" depends="((VK_KHR_get_physical_device_properties2,VK_VERSION_1_1)+VK_KHR_dynamic_rendering),VK_VERSION_1_3" type="device" author="EXT" contact="Daniel Story @daniel-story" supported="vulkan" ratified="vulkan">
             <require>
                 <enum value="1"                                            name="VK_EXT_SHADER_OBJECT_SPEC_VERSION"/>
                 <enum value="&quot;VK_EXT_shader_object&quot;"             name="VK_EXT_SHADER_OBJECT_EXTENSION_NAME"/>
@@ -23046,7 +23065,8 @@
                 <enum extnumber="353" offset="2" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VERTEX_INPUT_ATTRIBUTE_DESCRIPTION_2_EXT"/>
                 <enum extends="VkStructureType"                            name="VK_STRUCTURE_TYPE_SHADER_REQUIRED_SUBGROUP_SIZE_CREATE_INFO_EXT" alias="VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO"/>
                 <enum offset="0" extends="VkObjectType"                    name="VK_OBJECT_TYPE_SHADER_EXT"/>
-                <enum offset="0" extends="VkResult"                        name="VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT"/>
+                <enum offset="0" extends="VkResult"                        name="VK_INCOMPATIBLE_SHADER_BINARY_EXT"/>
+                <enum            extends="VkResult"                        name="VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT" alias="VK_INCOMPATIBLE_SHADER_BINARY_EXT" deprecated="aliased"/>
                 <type name="VkShaderEXT"/>
                 <type name="VkShaderCreateFlagBitsEXT"/>
                 <type name="VkShaderCreateFlagsEXT"/>
@@ -23092,15 +23112,32 @@
                 <command name="vkCmdSetColorBlendEnableEXT"/>
                 <command name="vkCmdSetColorBlendEquationEXT"/>
                 <command name="vkCmdSetColorWriteMaskEXT"/>
+                <feature name="shaderObject" struct="VkPhysicalDeviceShaderObjectFeaturesEXT"/>
+            </require>
+            <require depends="VK_EXT_transform_feedback">
                 <command name="vkCmdSetRasterizationStreamEXT"/>
+            </require>
+            <require depends="VK_EXT_conservative_rasterization">
                 <command name="vkCmdSetConservativeRasterizationModeEXT"/>
                 <command name="vkCmdSetExtraPrimitiveOverestimationSizeEXT"/>
+            </require>
+            <require depends="VK_EXT_depth_clip_enable">
                 <command name="vkCmdSetDepthClipEnableEXT"/>
+            </require>
+            <require depends="VK_EXT_sample_locations">
                 <command name="vkCmdSetSampleLocationsEnableEXT"/>
+            </require>
+            <require depends="VK_EXT_blend_operation_advanced">
                 <command name="vkCmdSetColorBlendAdvancedEXT"/>
+            </require>
+            <require depends="VK_EXT_provoking_vertex">
                 <command name="vkCmdSetProvokingVertexModeEXT"/>
+            </require>
+            <require depends="VK_EXT_line_rasterization">
                 <command name="vkCmdSetLineRasterizationModeEXT"/>
                 <command name="vkCmdSetLineStippleEnableEXT"/>
+            </require>
+            <require depends="VK_EXT_depth_clip_control">
                 <command name="vkCmdSetDepthClipNegativeOneToOneEXT"/>
             </require>
             <require depends="VK_EXT_subgroup_size_control,VK_VERSION_1_3">
diff --git a/common/end2end/GfxstreamEnd2EndVkSnapshotPipelineTests.cpp b/common/end2end/GfxstreamEnd2EndVkSnapshotPipelineTests.cpp
index c277447..ebc8305 100644
--- a/common/end2end/GfxstreamEnd2EndVkSnapshotPipelineTests.cpp
+++ b/common/end2end/GfxstreamEnd2EndVkSnapshotPipelineTests.cpp
@@ -1259,11 +1259,6 @@
                                 .with_vk = true,
                                 .with_features = {"VulkanSnapshots", "VulkanBatchedDescriptorSetUpdate"},
                             },
-                            TestParams{
-                                .with_gl = false,
-                                .with_vk = true,
-                                .with_features = {"VulkanSnapshots"},
-                            },
                         }),
                         &GetTestName);
 
diff --git a/host/VirtioGpuFrontend.cpp b/host/VirtioGpuFrontend.cpp
index f240f03..fb0d3ff 100644
--- a/host/VirtioGpuFrontend.cpp
+++ b/host/VirtioGpuFrontend.cpp
@@ -697,6 +697,9 @@
                     vk_emu->representativeColorBufferMemoryTypeInfo->guestMemoryTypeIndex;
             }
 
+            if (mFeatures.VulkanBatchedDescriptorSetUpdate.enabled) {
+                capset->vulkanBatchedDescriptorSetUpdate=1;
+            }
             capset->noRenderControlEnc = 1;
             capset->blobAlignment = mPageSize;
             if (vk_emu && vk_emu->live) {
diff --git a/host/features/Features.cpp b/host/features/Features.cpp
index 5242113..0e126aa 100644
--- a/host/features/Features.cpp
+++ b/host/features/Features.cpp
@@ -13,7 +13,8 @@
 // limitations under the License.
 
 #include "gfxstream/host/Features.h"
-
+#include <sstream>
+#include <vector>
 namespace gfxstream {
 namespace host {
 
@@ -21,6 +22,23 @@
     *this = rhs;
 }
 
+FeatureResult FeatureDependencyHandler::checkAllDependentFeaturesAreEnabled() {
+    // Only check for direct dependencies. Since we're verifying all enabled features, this should cover the whole span.
+    bool allDependenciesAreEnabled = true;
+    std::stringstream ss;
+    for (auto const&[feature, dependentFeatures] : VK_FEATURE_DEPENDENCY_MAP) {
+        if (feature->enabled && !dependentFeatures.empty()) {
+            for (auto const& dep : dependentFeatures) {
+                if (!dep->enabled) {
+                    ss << "Feature: " << feature->name << " requests missing dependency: " << dep->name << "\n";
+                    allDependenciesAreEnabled = false;
+                }
+            }
+        }
+    }
+    return {allDependenciesAreEnabled, ss.str()};
+};
+
 FeatureSet& FeatureSet::operator=(const FeatureSet& rhs) {
     for (const auto& [featureName, featureInfo] : rhs.map) {
         *map[featureName] = *featureInfo;
diff --git a/host/features/include/gfxstream/host/Features.h b/host/features/include/gfxstream/host/Features.h
index cef9ee7..c88290b 100644
--- a/host/features/include/gfxstream/host/Features.h
+++ b/host/features/include/gfxstream/host/Features.h
@@ -16,6 +16,7 @@
 
 #include <string>
 #include <map>
+#include <vector>
 
 namespace gfxstream {
 namespace host {
@@ -23,6 +24,8 @@
 struct FeatureInfo;
 
 using FeatureMap = std::map<std::string, FeatureInfo*>;
+//type used for returning success or a string with the concatenated errors (missing features)
+using FeatureResult = std::pair<bool, std::string>;
 
 struct FeatureInfo {
     FeatureInfo(const FeatureInfo& rhs) = default;
@@ -313,6 +316,17 @@
         &map,
     };
 };
+struct FeatureDependencyHandler {
+    FeatureDependencyHandler(const FeatureSet& set) : featureSetView(set){}
+    const FeatureSet& featureSetView;
+    const std::map<const FeatureInfo*, std::vector<const FeatureInfo*>> VK_FEATURE_DEPENDENCY_MAP= {
+        // List other dependencies here in the shape of:
+        // {FEATURE_X, {DEPENDENT_FEATURE_A, DEPENDENT_FEATURE_B}}
+        {&featureSetView.VulkanSnapshots, {&featureSetView.VulkanBatchedDescriptorSetUpdate, &featureSetView.Vulkan}},
+    };
+
+    FeatureResult checkAllDependentFeaturesAreEnabled();
+};
 
 #define GFXSTREAM_SET_FEATURE_ON_CONDITION(set, feature, condition) \
     do                                                              \
diff --git a/host/virtgpu_gfxstream_protocol.h b/host/virtgpu_gfxstream_protocol.h
index cb7e592..39a75c7 100644
--- a/host/virtgpu_gfxstream_protocol.h
+++ b/host/virtgpu_gfxstream_protocol.h
@@ -128,6 +128,7 @@
     uint32_t alwaysBlob;
     uint32_t externalSync;
     uint32_t virglSupportedFormats[16];
+    uint32_t vulkanBatchedDescriptorSetUpdate;
 };
 
 struct magmaCapset {
diff --git a/host/virtio-gpu-gfxstream-renderer.cpp b/host/virtio-gpu-gfxstream-renderer.cpp
index 03f0c43..e46a3a9 100644
--- a/host/virtio-gpu-gfxstream-renderer.cpp
+++ b/host/virtio-gpu-gfxstream-renderer.cpp
@@ -764,7 +764,7 @@
         &features, Vulkan,
         renderer_flags & STREAM_RENDERER_FLAGS_USE_VK_BIT);
     GFXSTREAM_SET_FEATURE_ON_CONDITION(
-        &features, VulkanBatchedDescriptorSetUpdate, true);
+        &features, VulkanBatchedDescriptorSetUpdate, features.VulkanBatchedDescriptorSetUpdate.enabled);
     GFXSTREAM_SET_FEATURE_ON_CONDITION(
         &features, VulkanIgnoredHandles, true);
     GFXSTREAM_SET_FEATURE_ON_CONDITION(
diff --git a/host/vulkan/VkDecoder.cpp b/host/vulkan/VkDecoder.cpp
index 90d7ac7..7c112bb 100644
--- a/host/vulkan/VkDecoder.cpp
+++ b/host/vulkan/VkDecoder.cpp
@@ -4621,14 +4621,11 @@
                 const VkComputePipelineCreateInfo* pCreateInfos;
                 const VkAllocationCallbacks* pAllocator;
                 VkPipeline* pPipelines;
-                // Begin non wrapped dispatchable handle unboxing for device;
+                // 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));
-                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;
@@ -4686,17 +4683,16 @@
                             (unsigned long long)pAllocator, (unsigned long long)pPipelines);
                 }
                 VkResult vkCreateComputePipelines_VkResult_return = (VkResult)0;
-                vkCreateComputePipelines_VkResult_return =
-                    vk->vkCreateComputePipelines(unboxed_device, pipelineCache, createInfoCount,
-                                                 pCreateInfos, pAllocator, pPipelines);
+                vkCreateComputePipelines_VkResult_return = m_state->on_vkCreateComputePipelines(
+                    &m_pool, device, pipelineCache, createInfoCount, pCreateInfos, pAllocator,
+                    pPipelines);
                 if ((vkCreateComputePipelines_VkResult_return) == VK_ERROR_DEVICE_LOST)
                     m_state->on_DeviceLost();
                 m_state->on_CheckOutOfMemory(vkCreateComputePipelines_VkResult_return, opcode,
                                              context);
                 vkStream->unsetHandleMapping();
-                // Begin auto non dispatchable handle create for pPipelines;
-                if (vkCreateComputePipelines_VkResult_return == VK_SUCCESS)
-                    vkStream->setHandleMapping(&m_boxedHandleCreateMapping);
+                // Begin manual non dispatchable handle create for pPipelines;
+                vkStream->unsetHandleMapping();
                 if (((createInfoCount))) {
                     uint64_t* cgen_var_4;
                     vkStream->alloc((void**)&cgen_var_4, ((createInfoCount)) * 8);
@@ -4706,7 +4702,7 @@
                                                                      ((createInfoCount)));
                     vkStream->write((VkPipeline*)pPipelines, 8 * ((createInfoCount)));
                 }
-                // Begin auto non dispatchable handle create for pPipelines;
+                // Begin manual non dispatchable handle create for pPipelines;
                 vkStream->setHandleMapping(&m_boxedHandleUnwrapMapping);
                 vkStream->write(&vkCreateComputePipelines_VkResult_return, sizeof(VkResult));
                 vkStream->commitWrite();
@@ -17565,6 +17561,50 @@
                 break;
             }
 #endif
+#ifdef VK_KHR_line_rasterization
+            case OP_vkCmdSetLineStippleKHR: {
+                GFXSTREAM_TRACE_EVENT(GFXSTREAM_TRACE_DECODER_CATEGORY,
+                                      "VkDecoder vkCmdSetLineStippleKHR");
+                VkCommandBuffer commandBuffer;
+                uint32_t lineStippleFactor;
+                uint16_t lineStipplePattern;
+                // 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*)&lineStippleFactor, *readStreamPtrPtr, sizeof(uint32_t));
+                *readStreamPtrPtr += sizeof(uint32_t);
+                memcpy((uint16_t*)&lineStipplePattern, *readStreamPtrPtr, sizeof(uint16_t));
+                *readStreamPtrPtr += sizeof(uint16_t);
+                if (m_logCalls) {
+                    fprintf(stderr,
+                            "stream %p: call vkCmdSetLineStippleKHR 0x%llx 0x%llx 0x%llx \n",
+                            ioStream, (unsigned long long)commandBuffer,
+                            (unsigned long long)lineStippleFactor,
+                            (unsigned long long)lineStipplePattern);
+                }
+                vk->vkCmdSetLineStippleKHR(unboxed_commandBuffer, lineStippleFactor,
+                                           lineStipplePattern);
+                vkStream->unsetHandleMapping();
+                vkReadStream->setReadPos((uintptr_t)(*readStreamPtrPtr) -
+                                         (uintptr_t)snapshotTraceBegin);
+                size_t snapshotTraceBytes = vkReadStream->endTrace();
+                if (m_state->snapshotsEnabled()) {
+                    m_state->snapshot()->vkCmdSetLineStippleKHR(
+                        snapshotTraceBegin, snapshotTraceBytes, &m_pool, commandBuffer,
+                        lineStippleFactor, lineStipplePattern);
+                }
+                vkReadStream->clearPool();
+                if (m_queueSubmitWithCommandsEnabled)
+                    seqnoPtr->fetch_add(1, std::memory_order_seq_cst);
+                break;
+            }
+#endif
 #ifdef VK_ANDROID_native_buffer
             case OP_vkGetSwapchainGrallocUsageANDROID: {
                 GFXSTREAM_TRACE_EVENT(GFXSTREAM_TRACE_DECODER_CATEGORY,
diff --git a/host/vulkan/VkDecoderGlobalState.cpp b/host/vulkan/VkDecoderGlobalState.cpp
index 2beeae2..8b88ed3 100644
--- a/host/vulkan/VkDecoderGlobalState.cpp
+++ b/host/vulkan/VkDecoderGlobalState.cpp
@@ -3884,6 +3884,35 @@
         return result;
     }
 
+    VkResult on_vkCreateComputePipelines(android::base::BumpPool* pool, VkDevice boxed_device,
+                                          VkPipelineCache pipelineCache, uint32_t createInfoCount,
+                                          const VkComputePipelineCreateInfo* pCreateInfos,
+                                          const VkAllocationCallbacks* pAllocator,
+                                          VkPipeline* pPipelines) {
+        auto device = unbox_VkDevice(boxed_device);
+        auto deviceDispatch = dispatch_VkDevice(boxed_device);
+
+        VkResult result = deviceDispatch->vkCreateComputePipelines(
+            device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
+        if (result != VK_SUCCESS && result != VK_PIPELINE_COMPILE_REQUIRED) {
+            return result;
+        }
+
+        std::lock_guard<std::recursive_mutex> lock(mLock);
+
+        for (uint32_t i = 0; i < createInfoCount; i++) {
+            if (!pPipelines[i]) {
+                continue;
+            }
+            auto& pipelineInfo = mPipelineInfo[pPipelines[i]];
+            pipelineInfo.device = device;
+
+            pPipelines[i] = new_boxed_non_dispatchable_VkPipeline(pPipelines[i]);
+        }
+
+        return result;
+    }
+
     void destroyPipelineWithExclusiveInfo(VkDevice device, VulkanDispatch* deviceDispatch,
                                           VkPipeline pipeline, PipelineInfo& pipelineInfo,
                                           const VkAllocationCallbacks* pAllocator) {
@@ -9151,6 +9180,14 @@
                                                pCreateInfos, pAllocator, pPipelines);
 }
 
+VkResult VkDecoderGlobalState::on_vkCreateComputePipelines(
+    android::base::BumpPool* pool, VkDevice boxed_device, VkPipelineCache pipelineCache,
+    uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos,
+    const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines) {
+    return mImpl->on_vkCreateComputePipelines(pool, boxed_device, pipelineCache, createInfoCount,
+                                               pCreateInfos, pAllocator, pPipelines);
+}
+
 void VkDecoderGlobalState::on_vkDestroyPipeline(android::base::BumpPool* pool,
                                                 VkDevice boxed_device, VkPipeline pipeline,
                                                 const VkAllocationCallbacks* pAllocator) {
diff --git a/host/vulkan/VkDecoderGlobalState.h b/host/vulkan/VkDecoderGlobalState.h
index 550dddf..ae09e62 100644
--- a/host/vulkan/VkDecoderGlobalState.h
+++ b/host/vulkan/VkDecoderGlobalState.h
@@ -314,6 +314,12 @@
                                           const VkAllocationCallbacks* pAllocator,
                                           VkPipeline* pPipelines);
 
+    VkResult on_vkCreateComputePipelines(android::base::BumpPool* pool, VkDevice device,
+                                          VkPipelineCache pipelineCache, uint32_t createInfoCount,
+                                          const VkComputePipelineCreateInfo* pCreateInfos,
+                                          const VkAllocationCallbacks* pAllocator,
+                                          VkPipeline* pPipelines);
+
     void on_vkDestroyPipeline(android::base::BumpPool* pool, VkDevice device, VkPipeline pipeline,
                               const VkAllocationCallbacks* pAllocator);
 
diff --git a/host/vulkan/VkDecoderSnapshot.cpp b/host/vulkan/VkDecoderSnapshot.cpp
index 029419c..8b095e6 100644
--- a/host/vulkan/VkDecoderSnapshot.cpp
+++ b/host/vulkan/VkDecoderSnapshot.cpp
@@ -3017,6 +3017,22 @@
                                          const VkImageSubresource2KHR* pSubresource,
                                          VkSubresourceLayout2KHR* pLayout) {}
 #endif
+#ifdef VK_KHR_line_rasterization
+    void vkCmdSetLineStippleKHR(const uint8_t* snapshotTraceBegin, size_t snapshotTraceBytes,
+                                android::base::BumpPool* pool, VkCommandBuffer commandBuffer,
+                                uint32_t lineStippleFactor, uint16_t lineStipplePattern) {
+        android::base::AutoLock lock(mLock);
+        // commandBuffer modify
+        auto apiHandle = mReconstruction.createApiInfo();
+        auto apiInfo = mReconstruction.getApiInfo(apiHandle);
+        mReconstruction.setApiTrace(apiInfo, OP_vkCmdSetLineStippleKHR, 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_ANDROID_native_buffer
     void vkGetSwapchainGrallocUsageANDROID(const uint8_t* snapshotTraceBegin,
                                            size_t snapshotTraceBytes, android::base::BumpPool* pool,
@@ -6596,6 +6612,14 @@
                                            image, pSubresource, pLayout);
 }
 #endif
+#ifdef VK_KHR_line_rasterization
+void VkDecoderSnapshot::vkCmdSetLineStippleKHR(
+    const uint8_t* snapshotTraceBegin, size_t snapshotTraceBytes, android::base::BumpPool* pool,
+    VkCommandBuffer commandBuffer, uint32_t lineStippleFactor, uint16_t lineStipplePattern) {
+    mImpl->vkCmdSetLineStippleKHR(snapshotTraceBegin, snapshotTraceBytes, pool, commandBuffer,
+                                  lineStippleFactor, lineStipplePattern);
+}
+#endif
 #ifdef VK_ANDROID_native_buffer
 void VkDecoderSnapshot::vkGetSwapchainGrallocUsageANDROID(
     const uint8_t* snapshotTraceBegin, size_t snapshotTraceBytes, android::base::BumpPool* pool,
diff --git a/host/vulkan/VkDecoderSnapshot.h b/host/vulkan/VkDecoderSnapshot.h
index 4d51354..9ecf635 100644
--- a/host/vulkan/VkDecoderSnapshot.h
+++ b/host/vulkan/VkDecoderSnapshot.h
@@ -1215,6 +1215,11 @@
                                          const VkImageSubresource2KHR* pSubresource,
                                          VkSubresourceLayout2KHR* pLayout);
 #endif
+#ifdef VK_KHR_line_rasterization
+    void vkCmdSetLineStippleKHR(const uint8_t* snapshotTraceBegin, size_t snapshotTraceBytes,
+                                android::base::BumpPool* pool, VkCommandBuffer commandBuffer,
+                                uint32_t lineStippleFactor, uint16_t lineStipplePattern);
+#endif
 #ifdef VK_ANDROID_native_buffer
     void vkGetSwapchainGrallocUsageANDROID(const uint8_t* snapshotTraceBegin,
                                            size_t snapshotTraceBytes, android::base::BumpPool* pool,
diff --git a/host/vulkan/VkSubDecoder.cpp b/host/vulkan/VkSubDecoder.cpp
index a13b4a2..d023253 100644
--- a/host/vulkan/VkSubDecoder.cpp
+++ b/host/vulkan/VkSubDecoder.cpp
@@ -2405,6 +2405,21 @@
                 break;
             }
 #endif
+#ifdef VK_KHR_line_rasterization
+            case OP_vkCmdSetLineStippleKHR: {
+                GFXSTREAM_TRACE_EVENT(GFXSTREAM_TRACE_DECODER_CATEGORY,
+                                      "VkSubDecoder vkCmdSetLineStippleKHR");
+                uint32_t lineStippleFactor;
+                uint16_t lineStipplePattern;
+                memcpy((uint32_t*)&lineStippleFactor, *readStreamPtrPtr, sizeof(uint32_t));
+                *readStreamPtrPtr += sizeof(uint32_t);
+                memcpy((uint16_t*)&lineStipplePattern, *readStreamPtrPtr, sizeof(uint16_t));
+                *readStreamPtrPtr += sizeof(uint16_t);
+                vk->vkCmdSetLineStippleKHR((VkCommandBuffer)dispatchHandle, lineStippleFactor,
+                                           lineStipplePattern);
+                break;
+            }
+#endif
 #ifdef VK_EXT_transform_feedback
             case OP_vkCmdBindTransformFeedbackBuffersEXT: {
                 GFXSTREAM_TRACE_EVENT(GFXSTREAM_TRACE_DECODER_CATEGORY,
diff --git a/host/vulkan/cereal/common/goldfish_vk_dispatch.cpp b/host/vulkan/cereal/common/goldfish_vk_dispatch.cpp
index 6026ef2..3bf5bed 100644
--- a/host/vulkan/cereal/common/goldfish_vk_dispatch.cpp
+++ b/host/vulkan/cereal/common/goldfish_vk_dispatch.cpp
@@ -619,6 +619,10 @@
     out->vkGetImageSubresourceLayout2KHR =
         (PFN_vkGetImageSubresourceLayout2KHR)dlSymFunc(lib, "vkGetImageSubresourceLayout2KHR");
 #endif
+#ifdef VK_KHR_line_rasterization
+    out->vkCmdSetLineStippleKHR =
+        (PFN_vkCmdSetLineStippleKHR)dlSymFunc(lib, "vkCmdSetLineStippleKHR");
+#endif
 #ifdef VK_ANDROID_native_buffer
     out->vkGetSwapchainGrallocUsageANDROID =
         (PFN_vkGetSwapchainGrallocUsageANDROID)dlSymFunc(lib, "vkGetSwapchainGrallocUsageANDROID");
@@ -1583,6 +1587,10 @@
         (PFN_vkGetImageSubresourceLayout2KHR)vk->vkGetInstanceProcAddr(
             instance, "vkGetImageSubresourceLayout2KHR");
 #endif
+#ifdef VK_KHR_line_rasterization
+    out->vkCmdSetLineStippleKHR =
+        (PFN_vkCmdSetLineStippleKHR)vk->vkGetInstanceProcAddr(instance, "vkCmdSetLineStippleKHR");
+#endif
 #ifdef VK_ANDROID_native_buffer
     out->vkGetSwapchainGrallocUsageANDROID =
         (PFN_vkGetSwapchainGrallocUsageANDROID)vk->vkGetInstanceProcAddr(
@@ -2569,6 +2577,10 @@
         (PFN_vkGetImageSubresourceLayout2KHR)vk->vkGetDeviceProcAddr(
             device, "vkGetImageSubresourceLayout2KHR");
 #endif
+#ifdef VK_KHR_line_rasterization
+    out->vkCmdSetLineStippleKHR =
+        (PFN_vkCmdSetLineStippleKHR)vk->vkGetDeviceProcAddr(device, "vkCmdSetLineStippleKHR");
+#endif
 #ifdef VK_ANDROID_native_buffer
     out->vkGetSwapchainGrallocUsageANDROID =
         (PFN_vkGetSwapchainGrallocUsageANDROID)vk->vkGetDeviceProcAddr(
diff --git a/host/vulkan/cereal/common/goldfish_vk_dispatch.h b/host/vulkan/cereal/common/goldfish_vk_dispatch.h
index 2eba683..32c652d 100644
--- a/host/vulkan/cereal/common/goldfish_vk_dispatch.h
+++ b/host/vulkan/cereal/common/goldfish_vk_dispatch.h
@@ -435,6 +435,9 @@
     PFN_vkGetDeviceImageSubresourceLayoutKHR vkGetDeviceImageSubresourceLayoutKHR;
     PFN_vkGetImageSubresourceLayout2KHR vkGetImageSubresourceLayout2KHR;
 #endif
+#ifdef VK_KHR_line_rasterization
+    PFN_vkCmdSetLineStippleKHR vkCmdSetLineStippleKHR;
+#endif
 #ifdef VK_ANDROID_native_buffer
     PFN_vkGetSwapchainGrallocUsageANDROID vkGetSwapchainGrallocUsageANDROID;
     PFN_vkAcquireImageANDROID vkAcquireImageANDROID;
diff --git a/host/vulkan/cereal/common/goldfish_vk_marshaling.cpp b/host/vulkan/cereal/common/goldfish_vk_marshaling.cpp
index 2afdae2..d1474af 100644
--- a/host/vulkan/cereal/common/goldfish_vk_marshaling.cpp
+++ b/host/vulkan/cereal/common/goldfish_vk_marshaling.cpp
@@ -22808,6 +22808,13 @@
         case OP_vkCmdSetDepthBoundsTestEnable: {
             return "OP_vkCmdSetDepthBoundsTestEnable";
         }
+#endif
+#ifdef VK_KHR_line_rasterization
+        case OP_vkCmdSetLineStippleKHR: {
+            return "OP_vkCmdSetLineStippleKHR";
+        }
+#endif
+#ifdef VK_VERSION_1_3
         case OP_vkCmdSetScissorWithCount: {
             return "OP_vkCmdSetScissorWithCount";
         }
diff --git a/host/vulkan/cereal/common/goldfish_vk_marshaling.h b/host/vulkan/cereal/common/goldfish_vk_marshaling.h
index 82b6a7f..35dc63a 100644
--- a/host/vulkan/cereal/common/goldfish_vk_marshaling.h
+++ b/host/vulkan/cereal/common/goldfish_vk_marshaling.h
@@ -3111,6 +3111,7 @@
     VulkanStream* vkStream, VkStructureType rootType,
     VkPipelineRasterizationLineStateCreateInfoKHR* forUnmarshaling);
 
+#define OP_vkCmdSetLineStippleKHR 219923286
 #endif
 #ifdef VK_ANDROID_native_buffer
 void marshal_VkNativeBufferUsage2ANDROID(VulkanStream* vkStream, VkStructureType rootType,
diff --git a/scripts/print_gfx_logs/vulkan_printer.py b/scripts/print_gfx_logs/vulkan_printer.py
index 23528e6..b7a3571 100644
--- a/scripts/print_gfx_logs/vulkan_printer.py
+++ b/scripts/print_gfx_logs/vulkan_printer.py
@@ -1349,7 +1349,6 @@
     1000377000: "VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT",
     1000377003: "VK_DYNAMIC_STATE_LOGIC_OP_EXT",
     1000381000: "VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT",
-    1000455002: "VK_DYNAMIC_STATE_TESSELLATION_DOMAIN_ORIGIN_EXT",
     1000455003: "VK_DYNAMIC_STATE_DEPTH_CLAMP_ENABLE_EXT",
     1000455004: "VK_DYNAMIC_STATE_POLYGON_MODE_EXT",
     1000455005: "VK_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT",
@@ -1360,6 +1359,7 @@
     1000455010: "VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT",
     1000455011: "VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT",
     1000455012: "VK_DYNAMIC_STATE_COLOR_WRITE_MASK_EXT",
+    1000455002: "VK_DYNAMIC_STATE_TESSELLATION_DOMAIN_ORIGIN_EXT",
     1000455013: "VK_DYNAMIC_STATE_RASTERIZATION_STREAM_EXT",
     1000455014: "VK_DYNAMIC_STATE_CONSERVATIVE_RASTERIZATION_MODE_EXT",
     1000455015: "VK_DYNAMIC_STATE_EXTRA_PRIMITIVE_OVERESTIMATION_SIZE_EXT",