glave: Fix replay of CreateInstance
diff --git a/tools/glave/scripts/vk_generate.py b/tools/glave/scripts/vk_generate.py
index 81a3df8..7a5d074 100755
--- a/tools/glave/scripts/vk_generate.py
+++ b/tools/glave/scripts/vk_generate.py
@@ -702,7 +702,6 @@
         pid_enum.append('    glv_finalize_buffer_address(pHeader, (void**)&((*ppStruct)->pEngineName));')
         pid_enum.append('    glv_finalize_buffer_address(pHeader, (void**)&*ppStruct);')
         pid_enum.append('};\n')
-        pid_enum.append('//=============================================================================\n')
         pid_enum.append('static void add_VkInstanceCreateInfo_to_packet(glv_trace_packet_header* pHeader, VkInstanceCreateInfo** ppStruct, VkInstanceCreateInfo *pInStruct)')
         pid_enum.append('{')
         pid_enum.append('    uint32_t i;')
@@ -776,6 +775,46 @@
         pid_enum.append('    }')
         pid_enum.append('    glv_finalize_buffer_address(pHeader, (void**)ppStruct);')
         pid_enum.append('}\n')
+        pid_enum.append('//=============================================================================\n')
+        pid_enum.append('static VkInstanceCreateInfo* interpret_VkInstanceCreateInfo(glv_trace_packet_header*  pHeader, intptr_t ptr_variable)')
+        pid_enum.append('{')
+        pid_enum.append('    VkInstanceCreateInfo* pVkInstanceCreateInfo = (VkInstanceCreateInfo*)glv_trace_packet_interpret_buffer_pointer(pHeader, (intptr_t)ptr_variable);\n')
+        pid_enum.append('    if (pVkInstanceCreateInfo != NULL)')
+        pid_enum.append('    {')
+        pid_enum.append('            uint32_t i;')
+        pid_enum.append('            const char** pNames;')
+        pid_enum.append('            pVkInstanceCreateInfo->pAppInfo = (VkApplicationInfo*)glv_trace_packet_interpret_buffer_pointer(pHeader, (intptr_t)pVkInstanceCreateInfo->pAppInfo);')
+        pid_enum.append('            pVkInstanceCreateInfo->pAllocCb = (VkAllocCallbacks*)glv_trace_packet_interpret_buffer_pointer(pHeader, (intptr_t)pVkInstanceCreateInfo->pAllocCb);')
+        pid_enum.append('            VkApplicationInfo** ppAppInfo = (VkApplicationInfo**) &pVkInstanceCreateInfo->pAppInfo;')
+        pid_enum.append('            (*ppAppInfo)->pAppName = (const char*)glv_trace_packet_interpret_buffer_pointer(pHeader, (intptr_t)pVkInstanceCreateInfo->pAppInfo->pAppName);')
+        pid_enum.append('            (*ppAppInfo)->pEngineName = (const char*)glv_trace_packet_interpret_buffer_pointer(pHeader, (intptr_t)pVkInstanceCreateInfo->pAppInfo->pEngineName);')
+
+        pid_enum.append('        if (pVkInstanceCreateInfo->extensionCount > 0)')
+        pid_enum.append('        {')
+        pid_enum.append('            pVkInstanceCreateInfo->ppEnabledExtensionNames = (const char *const*)glv_trace_packet_interpret_buffer_pointer(pHeader, (intptr_t)pVkInstanceCreateInfo->ppEnabledExtensionNames);')
+        pid_enum.append('            pNames = (const char**)pVkInstanceCreateInfo->ppEnabledExtensionNames;')
+        pid_enum.append('            for (i = 0; i < pVkInstanceCreateInfo->extensionCount; i++)')
+        pid_enum.append('            {')
+        pid_enum.append('                pNames[i] = (const char*)glv_trace_packet_interpret_buffer_pointer(pHeader, (intptr_t)(pVkInstanceCreateInfo->ppEnabledExtensionNames[i]));')
+        pid_enum.append('            }')
+        pid_enum.append('        }')
+        pid_enum.append('        VkLayerCreateInfo *pNext = ( VkLayerCreateInfo *) glv_trace_packet_interpret_buffer_pointer(pHeader, (intptr_t)pVkInstanceCreateInfo->pNext);')
+        pid_enum.append('        while (pNext != NULL)')
+        pid_enum.append('        {')
+        pid_enum.append('            if ((pNext->sType == VK_STRUCTURE_TYPE_LAYER_CREATE_INFO) && pNext->layerCount > 0)')
+        pid_enum.append('            {')
+        pid_enum.append('                pNext->ppActiveLayerNames = (const char**) glv_trace_packet_interpret_buffer_pointer(pHeader, (intptr_t)(pNext->ppActiveLayerNames));')
+        pid_enum.append('                pNames = (const char**)pNext->ppActiveLayerNames;')
+        pid_enum.append('                for (i = 0; i < pNext->layerCount; i++)')
+        pid_enum.append('                {')
+        pid_enum.append('                    pNames[i] = (const char*)glv_trace_packet_interpret_buffer_pointer(pHeader, (intptr_t)(pNext->ppActiveLayerNames[i]));')
+        pid_enum.append('                }')
+        pid_enum.append('            }')
+        pid_enum.append('            pNext = ( VkLayerCreateInfo *) glv_trace_packet_interpret_buffer_pointer(pHeader, (intptr_t)pNext->pNext);')
+        pid_enum.append('        }')
+        pid_enum.append('    }\n')
+        pid_enum.append('    return pVkInstanceCreateInfo;')
+        pid_enum.append('}\n')
         pid_enum.append('static VkDeviceCreateInfo* interpret_VkDeviceCreateInfo(glv_trace_packet_header*  pHeader, intptr_t ptr_variable)')
         pid_enum.append('{')
         pid_enum.append('    VkDeviceCreateInfo* pVkDeviceCreateInfo = (VkDeviceCreateInfo*)glv_trace_packet_interpret_buffer_pointer(pHeader, (intptr_t)ptr_variable);\n')
@@ -835,10 +874,7 @@
     def _generate_interp_funcs(self):
         # Custom txt for given function and parameter.  First check if param is NULL, then insert txt if not
         # TODO : This code is now too large and complex, need to make codegen smarter for pointers embedded in struct params to handle those cases automatically
-        custom_case_dict = { 'CreateInstance' : {'param': 'pAppInfo', 'txt': ['VkApplicationInfo* pInfo = (VkApplicationInfo*)pPacket->pAppInfo;\n',
-                                                       'pInfo->pAppName = (const char*)glv_trace_packet_interpret_buffer_pointer(pHeader, (intptr_t)pPacket->pAppInfo->pAppName);\n',
-                                                       'pInfo->pEngineName = (const char*)glv_trace_packet_interpret_buffer_pointer(pHeader, (intptr_t)pPacket->pAppInfo->pEngineName);']},
-                             'CreateShader' : {'param': 'pCreateInfo', 'txt': ['VkShaderCreateInfo* pInfo = (VkShaderCreateInfo*)pPacket->pCreateInfo;\n',
+        custom_case_dict = { 'CreateShader' : {'param': 'pCreateInfo', 'txt': ['VkShaderCreateInfo* pInfo = (VkShaderCreateInfo*)pPacket->pCreateInfo;\n',
                                                'pInfo->pCode = glv_trace_packet_interpret_buffer_pointer(pHeader, (intptr_t)pPacket->pCreateInfo->pCode);']},
                              'CreateDynamicViewportState' : {'param': 'pCreateInfo', 'txt': ['VkDynamicVpStateCreateInfo* pInfo = (VkDynamicVpStateCreateInfo*)pPacket->pCreateInfo;\n',
                                                                                              'pInfo->pViewports = (VkViewport*) glv_trace_packet_interpret_buffer_pointer(pHeader, (intptr_t)pPacket->pCreateInfo->pViewports);\n',
@@ -1043,6 +1079,8 @@
                     if '*' in p.ty:
                         if 'DeviceCreateInfo' in p.ty:
                             if_body.append('    pPacket->%s = interpret_VkDeviceCreateInfo(pHeader, (intptr_t)pPacket->%s);' % (p.name, p.name))
+                        elif 'InstanceCreateInfo' in p.ty:
+                            if_body.append('    pPacket->%s = interpret_VkInstanceCreateInfo(pHeader, (intptr_t)pPacket->%s);' % (p.name, p.name))
                         else:
                             if_body.append('    pPacket->%s = (%s)glv_trace_packet_interpret_buffer_pointer(pHeader, (intptr_t)pPacket->%s);' % (p.name, p.ty, p.name))
                         # TODO : Generalize this custom code to kill dict data struct above.
@@ -1401,6 +1439,11 @@
             return 'm_objMapper.remap(pPacket->%s)' % (n)
         return 'pPacket->%s' % (n)
 
+    def _gen_replay_create_instance(self):
+        ci_body = []
+        ci_body.append('            returnValue = manually_handle_vkCreateInstance(pPacket);')
+        return "\n".join(ci_body)
+
     def _gen_replay_enum_gpus(self):
         ieg_body = []
         ieg_body.append('            returnValue = manually_handle_vkEnumerateGpus(pPacket);')
@@ -1591,7 +1634,8 @@
     # Generate main replay case statements where actual replay API call is dispatched based on input packet data
     def _generate_replay(self):
         # map protos to custom functions if body is fully custom
-        custom_body_dict = {'EnumerateGpus': self._gen_replay_enum_gpus,
+        custom_body_dict = {'CreateInstance': self._gen_replay_create_instance,
+                            'EnumerateGpus': self._gen_replay_enum_gpus,
                             'GetGpuInfo': self._gen_replay_get_gpu_info,
                             'CreateDevice': self._gen_replay_create_device,
                             'GetExtensionSupport': self._gen_replay_get_extension_support,
@@ -1623,9 +1667,8 @@
                             'CreateDescriptorSetLayout': self._gen_replay_create_descriptor_set_layout,
                             'CmdWaitEvents': self._gen_replay_cmd_wait_events,
                             'CmdPipelineBarrier': self._gen_replay_cmd_pipeline_barrier}
-        # TODO : Need to guard CreateInstance with "if (!m_display->m_initedVK)" check
         # Despite returning a value, don't check these funcs b/c custom code includes check already
-        custom_check_ret_val = ['EnumerateGpus', 'GetGpuInfo', 'CreateDevice', 'GetExtensionSupport', 'QueueSubmit', 'GetObjectInfo',
+        custom_check_ret_val = ['CreateInstance', 'EnumerateGpus', 'GetGpuInfo', 'CreateDevice', 'GetExtensionSupport', 'QueueSubmit', 'GetObjectInfo',
                                 'GetFormatInfo', 'GetImageSubresourceInfo', 'CreateDescriptorSetLayout', 'CreateGraphicsPipeline',
                                 'CreateFramebuffer', 'CreateRenderPass', 'BeginCommandBuffer', 'StorePipeline', 'GetMultiGpuCompatibility',
                                 'DestroyObject', 'WaitForFences', 'FreeMemory', 'MapMemory', 'UnmapMemory',
diff --git a/tools/glave/src/glv_extensions/glvreplay_vk/glvreplay_vk_vkreplay.cpp b/tools/glave/src/glv_extensions/glvreplay_vk/glvreplay_vk_vkreplay.cpp
index c1fce72..d73171b 100644
--- a/tools/glave/src/glv_extensions/glvreplay_vk/glvreplay_vk_vkreplay.cpp
+++ b/tools/glave/src/glv_extensions/glvreplay_vk/glvreplay_vk_vkreplay.cpp
@@ -157,6 +157,59 @@
    return 0;
 }
 
+glv_replay::GLV_REPLAY_RESULT vkReplay::manually_handle_vkCreateInstance(struct_vkCreateInstance* pPacket)
+{
+    VkResult replayResult = VK_ERROR_UNKNOWN;
+    glv_replay::GLV_REPLAY_RESULT returnValue = glv_replay::GLV_REPLAY_SUCCESS;
+    if (!m_display->m_initedVK)
+    {
+        VkInstance inst;
+        if (g_vkReplaySettings.debugLevel > 0)
+        {
+            VkInstanceCreateInfo cInfo, *ci, *pCreateInfoSaved;
+            unsigned int numLayers = 0;
+            char ** layersStr = get_enableLayers_list(&numLayers);
+            apply_layerSettings_overrides();
+            //VkLayerCreateInfo layerInfo;
+            pCreateInfoSaved = (VkInstanceCreateInfo *) pPacket->pCreateInfo;
+            ci = (VkInstanceCreateInfo *) pPacket->pCreateInfo;
+            if (layersStr != NULL && numLayers > 0)
+            {
+                // TODO change this to add the layers into the extension string
+#if 0
+                while (ci->pNext != NULL)
+                    ci = (VkInstanceCreateInfo *) ci->pNext;
+                ci->pNext = &layerInfo;
+                layerInfo.sType = VK_STRUCTURE_TYPE_LAYER_CREATE_INFO;
+                layerInfo.pNext = 0;
+                layerInfo.layerCount = numLayers;
+                layerInfo.ppActiveLayerNames = layersStr;
+#endif
+            }
+            memcpy(&cInfo, pPacket->pCreateInfo, sizeof(VkInstanceCreateInfo));
+            pPacket->pCreateInfo = &cInfo;
+            replayResult = m_vkFuncs.real_vkCreateInstance(pPacket->pCreateInfo, &inst);
+            // restore the packet for next replay
+            ci->pNext = NULL;
+            pPacket->pCreateInfo = pCreateInfoSaved;
+            release_enableLayer_list(layersStr);
+#if !defined(_WIN32)
+            m_pDSDump = (void (*)(char*)) m_vkFuncs.real_vkGetProcAddr(NULL, "drawStateDumpDotFile");
+            m_pCBDump = (void (*)(char*)) m_vkFuncs.real_vkGetProcAddr(NULL, "drawStateDumpCommandBufferDotFile");
+            m_pGlvSnapshotPrint = (GLVSNAPSHOT_PRINT_OBJECTS) m_vkFuncs.real_vkGetProcAddr(NULL, "glvSnapshotPrintObjects");
+#endif
+        }
+        else
+            replayResult = m_vkFuncs.real_vkCreateInstance(pPacket->pCreateInfo, &inst);
+        CHECK_RETURN_VALUE(vkCreateInstance);
+        if (replayResult == VK_SUCCESS)
+        {
+            m_objMapper.add_to_map(pPacket->pInstance, &inst);
+        }
+    }
+    return returnValue;
+}
+
 glv_replay::GLV_REPLAY_RESULT vkReplay::manually_handle_vkCreateDevice(struct_vkCreateDevice* pPacket)
 {
     VkResult replayResult = VK_ERROR_UNKNOWN;
@@ -185,7 +238,6 @@
             }
             memcpy(&cInfo, pPacket->pCreateInfo, sizeof(VkDeviceCreateInfo));
             cInfo.flags = pPacket->pCreateInfo->flags | VK_DEVICE_CREATE_VALIDATION_BIT;
-            cInfo.maxValidationLevel = (VkValidationLevel)((g_vkReplaySettings.debugLevel <= 4) ? (unsigned int) VK_VALIDATION_LEVEL_0 + g_vkReplaySettings.debugLevel : (unsigned int) VK_VALIDATION_LEVEL_0);
             pPacket->pCreateInfo = &cInfo;
             replayResult = m_vkFuncs.real_vkCreateDevice(m_objMapper.remap(pPacket->gpu), pPacket->pCreateInfo, &device);
             // restore the packet for next replay
diff --git a/tools/glave/src/glv_extensions/glvreplay_vk/glvreplay_vk_vkreplay.h b/tools/glave/src/glv_extensions/glvreplay_vk/glvreplay_vk_vkreplay.h
index 934f586..3475fa9 100644
--- a/tools/glave/src/glv_extensions/glvreplay_vk/glvreplay_vk_vkreplay.h
+++ b/tools/glave/src/glv_extensions/glvreplay_vk/glvreplay_vk_vkreplay.h
@@ -1,5 +1,3 @@
-/* THIS FILE IS GENERATED.  DO NOT EDIT. */
-
 /*
  * Vulkan
  *
@@ -90,6 +88,7 @@
     };
     std::vector<struct validationMsg> m_validationMsgs;
     std::vector<int> m_screenshotFrames;
+    glv_replay::GLV_REPLAY_RESULT manually_handle_vkCreateInstance(struct_vkCreateInstance* pPacket);
     glv_replay::GLV_REPLAY_RESULT manually_handle_vkCreateDevice(struct_vkCreateDevice* pPacket);
     glv_replay::GLV_REPLAY_RESULT manually_handle_vkEnumerateGpus(struct_vkEnumerateGpus* pPacket);
     glv_replay::GLV_REPLAY_RESULT manually_handle_vkGetGpuInfo(struct_vkGetGpuInfo* pPacket);