// ------------------------------------------------------------------------------------------------ int main(int argc, char* argv[]) { memset(&g_settings, 0, sizeof(vktrace_settings)); vktrace_LogSetCallback(loggingCallback); vktrace_LogSetLevel(VKTRACE_LOG_ERROR); // setup defaults memset(&g_default_settings, 0, sizeof(vktrace_settings)); g_default_settings.output_trace = vktrace_allocate_and_copy("vktrace_out.vktrace"); g_default_settings.verbosity = "errors"; g_default_settings.screenshotList = NULL; if (vktrace_SettingGroup_init(&g_settingGroup, NULL, argc, argv, &g_settings.arguments) != 0) { // invalid cmd-line parameters vktrace_SettingGroup_delete(&g_settingGroup); vktrace_free(g_default_settings.output_trace); return -1; } else { // Validate vktrace inputs BOOL validArgs = TRUE; if (g_settings.output_trace == NULL || strlen (g_settings.output_trace) == 0) { validArgs = FALSE; } else { size_t len = strlen(g_settings.output_trace); if (strncmp(&g_settings.output_trace[len-8], ".vktrace", 8) != 0) { // output trace filename does not end in .vktrace vktrace_LogError("Output trace file specified with -o parameter must have a '.vktrace' extension."); validArgs = FALSE; } } if (strcmp(g_settings.verbosity, "quiet") == 0) vktrace_LogSetLevel(VKTRACE_LOG_NONE); else if (strcmp(g_settings.verbosity, "errors") == 0) vktrace_LogSetLevel(VKTRACE_LOG_ERROR); else if (strcmp(g_settings.verbosity, "warnings") == 0) vktrace_LogSetLevel(VKTRACE_LOG_WARNING); else if (strcmp(g_settings.verbosity, "full") == 0) vktrace_LogSetLevel(VKTRACE_LOG_VERBOSE); #if _DEBUG else if (strcmp(g_settings.verbosity, "debug") == 0) vktrace_LogSetLevel(VKTRACE_LOG_DEBUG); #endif else { vktrace_LogSetLevel(VKTRACE_LOG_ERROR); validArgs = FALSE; } vktrace_set_global_var("_VK_TRACE_VERBOSITY", g_settings.verbosity); if (validArgs == FALSE) { vktrace_SettingGroup_print(&g_settingGroup); return -1; } if (g_settings.program == NULL || strlen(g_settings.program) == 0) { vktrace_LogWarning("No program (-p) parameter found: Will run vktrace as server."); printf("Running vktrace as server...\n"); fflush(stdout); g_settings.arguments = NULL; } else { if (g_settings.working_dir == NULL || strlen(g_settings.working_dir) == 0) { CHAR* buf = VKTRACE_NEW_ARRAY(CHAR, 4096); vktrace_LogVerbose("No working directory (-w) parameter found: Assuming executable's path as working directory."); vktrace_platform_full_path(g_settings.program, 4096, buf); g_settings.working_dir = vktrace_platform_extract_path(buf); VKTRACE_DELETE(buf); } vktrace_LogVerbose("Running vktrace as parent process will spawn child process: %s", g_settings.program); if (g_settings.arguments != NULL && strlen(g_settings.arguments) > 0) { vktrace_LogVerbose("Args to be passed to child process: '%s'", g_settings.arguments); } } } if (g_settings.screenshotList) { // Export list to screenshot layer vktrace_set_global_var("_VK_SCREENSHOT", g_settings.screenshotList); } else { vktrace_set_global_var("_VK_SCREENSHOT",""); } unsigned int serverIndex = 0; do { // Create and start the process or run in server mode BOOL procStarted = TRUE; vktrace_process_info procInfo; memset(&procInfo, 0, sizeof(vktrace_process_info)); if (g_settings.program != NULL) { procInfo.exeName = vktrace_allocate_and_copy(g_settings.program); procInfo.processArgs = vktrace_allocate_and_copy(g_settings.arguments); procInfo.fullProcessCmdLine = vktrace_copy_and_append(g_settings.program, " ", g_settings.arguments); procInfo.workingDirectory = vktrace_allocate_and_copy(g_settings.working_dir); procInfo.traceFilename = vktrace_allocate_and_copy(g_settings.output_trace); } else { const char *pExtension = strrchr(g_settings.output_trace, '.'); char *basename = vktrace_allocate_and_copy_n(g_settings.output_trace, (int) ((pExtension == NULL) ? strlen(g_settings.output_trace) : pExtension - g_settings.output_trace)); char num[16]; #ifdef PLATFORM_LINUX snprintf(num, 16, "%u", serverIndex); #elif defined(WIN32) _snprintf_s(num, 16, _TRUNCATE, "%u", serverIndex); #endif procInfo.traceFilename = vktrace_copy_and_append(basename, num, pExtension); } procInfo.parentThreadId = vktrace_platform_get_thread_id(); // setup tracer, only Vulkan tracer suppported PrepareTracers(&procInfo.pCaptureThreads); if (g_settings.program != NULL) { char *instEnv = vktrace_get_global_var("VK_INSTANCE_LAYERS"); // Add ScreenShot layer if enabled if (g_settings.screenshotList && (!instEnv || !strstr(instEnv, "VK_LAYER_LUNARG_screenshot"))) { if (!instEnv || strlen(instEnv) == 0) vktrace_set_global_var("VK_INSTANCE_LAYERS", "VK_LAYER_LUNARG_screenshot"); else { char *newEnv = vktrace_copy_and_append(instEnv, VKTRACE_LIST_SEPARATOR, "VK_LAYER_LUNARG_screenshot"); vktrace_set_global_var("VK_INSTANCE_LAYERS", newEnv); } instEnv = vktrace_get_global_var("VK_INSTANCE_LAYERS"); } char *devEnv = vktrace_get_global_var("VK_DEVICE_LAYERS"); if (g_settings.screenshotList && (!devEnv || !strstr(devEnv, "VK_LAYER_LUNARG_screenshot"))) { if (!devEnv || strlen(devEnv) == 0) vktrace_set_global_var("VK_DEVICE_LAYERS", "VK_LAYER_LUNARG_screenshot"); else { char *newEnv = vktrace_copy_and_append(devEnv, VKTRACE_LIST_SEPARATOR, "VK_LAYER_LUNARG_screenshot"); vktrace_set_global_var("VK_DEVICE_LAYERS", newEnv); } devEnv = vktrace_get_global_var("VK_DEVICE_LAYERS"); } // Add vktrace_layer enable env var if needed if (!instEnv || strlen(instEnv) == 0) { vktrace_set_global_var("VK_INSTANCE_LAYERS", "VK_LAYER_LUNARG_vktrace"); } else if (instEnv != strstr(instEnv, "VK_LAYER_LUNARG_vktrace")) { char *newEnv = vktrace_copy_and_append("VK_LAYER_LUNARG_vktrace", VKTRACE_LIST_SEPARATOR, instEnv); vktrace_set_global_var("VK_INSTANCE_LAYERS", newEnv); } if (!devEnv || strlen(devEnv) == 0) { vktrace_set_global_var("VK_DEVICE_LAYERS", "VK_LAYER_LUNARG_vktrace"); } else if (devEnv != strstr(devEnv, "VK_LAYER_LUNARG_vktrace")) { char *newEnv = vktrace_copy_and_append("VK_LAYER_LUNARG_vktrace", VKTRACE_LIST_SEPARATOR, devEnv); vktrace_set_global_var("VK_DEVICE_LAYERS", newEnv); } // call CreateProcess to launch the application procStarted = vktrace_process_spawn(&procInfo); } if (procStarted == FALSE) { vktrace_LogError("Failed to setup remote process."); } else { if (InjectTracersIntoProcess(&procInfo) == FALSE) { vktrace_LogError("Failed to setup tracer communication threads."); return -1; } // create watchdog thread to monitor existence of remote process if (g_settings.program != NULL) procInfo.watchdogThread = vktrace_platform_create_thread(Process_RunWatchdogThread, &procInfo); #if defined(PLATFORM_LINUX) // Sync wait for local threads and remote process to complete. vktrace_platform_sync_wait_for_thread(&(procInfo.pCaptureThreads[0].recordingThread)); if (g_settings.program != NULL) vktrace_platform_sync_wait_for_thread(&procInfo.watchdogThread); #else vktrace_platform_resume_thread(&procInfo.hThread); // Now into the main message loop, listen for hotkeys to send over. MessageLoop(); #endif } vktrace_process_info_delete(&procInfo); serverIndex++; } while (g_settings.program == NULL); vktrace_SettingGroup_delete(&g_settingGroup); vktrace_free(g_default_settings.output_trace); return 0; }
VkResult vkDisplay::init_vk(unsigned int gpu_idx) { #if 0 VkApplicationInfo appInfo = {}; appInfo.pApplicationName = APP_NAME; appInfo.pEngineName = ""; appInfo.apiVersion = VK_API_VERSION; VkResult res = vkInitAndEnumerateGpus(&appInfo, NULL, VK_MAX_PHYSICAL_GPUS, &m_gpuCount, m_gpus); if ( res == VK_SUCCESS ) { // retrieve the GPU information for all GPUs for( uint32_t gpu = 0; gpu < m_gpuCount; gpu++) { size_t gpuInfoSize = sizeof(m_gpuProps[0]); // get the GPU physical properties: res = vkGetGpuInfo( m_gpus[gpu], VK_INFO_TYPE_PHYSICAL_GPU_PROPERTIES, &gpuInfoSize, &m_gpuProps[gpu]); if (res != VK_SUCCESS) vktrace_LogWarning("Failed to retrieve properties for gpu[%d] result %d", gpu, res); } res = VK_SUCCESS; } else if ((gpu_idx + 1) > m_gpuCount) { vktrace_LogError("vkInitAndEnumerate number of gpus does not include requested index: num %d, requested %d", m_gpuCount, gpu_idx); return -1; } else { vktrace_LogError("vkInitAndEnumerate failed"); return res; } // TODO add multi-gpu support always use gpu[gpu_idx] for now // get all extensions supported by this device gpu[gpu_idx] // first check if extensions are available and save a list of them bool foundWSIExt = false; for( int ext = 0; ext < sizeof( extensions ) / sizeof( extensions[0] ); ext++) { res = vkGetExtensionSupport( m_gpus[gpu_idx], extensions[ext] ); if (res == VK_SUCCESS) { m_extensions.push_back((char *) extensions[ext]); if (!strcmp(extensions[ext], "VK_WSI_WINDOWS")) foundWSIExt = true; } } if (!foundWSIExt) { vktrace_LogError("VK_WSI_WINDOWS extension not supported by gpu[%d]", gpu_idx); return VK_ERROR_INCOMPATIBLE_DEVICE; } // TODO generalize this: use one universal queue for now VkDeviceQueueCreateInfo dqci = {}; dqci.queueCount = 1; dqci.queueType = VK_QUEUE_UNIVERSAL; std::vector<float> queue_priorities (dqci.queueCount, 0.0); dqci.pQueuePriorities = queue_priorities.data(); // create the device enabling validation level 4 const char * const * extensionNames = &m_extensions[0]; VkDeviceCreateInfo info = {}; info.queueCreateInfoCount = 1; info.pQueueCreateInfos = &dqci; info.enabledExtensionCount = static_cast <uint32_t> (m_extensions.size()); info.ppEnabledExtensionNames = extensionNames; info.flags = VK_DEVICE_CREATE_VALIDATION; info.maxValidationLevel = VK_VALIDATION_LEVEL_4; bool32_t vkTrue = VK_TRUE; res = vkDbgSetGlobalOption( VK_DBG_OPTION_BREAK_ON_ERROR, sizeof( vkTrue ), &vkTrue ); if (res != VK_SUCCESS) vktrace_LogWarning("Could not set debug option break on error"); res = vkCreateDevice( m_gpus[0], &info, &m_dev[gpu_idx]); return res; #else return VK_ERROR_INITIALIZATION_FAILED; #endif }
int main_loop(Sequencer &seq, vktrace_trace_packet_replay_library *replayerArray[], vkreplayer_settings settings) { int err = 0; vktrace_trace_packet_header *packet; unsigned int res; vktrace_trace_packet_replay_library *replayer = NULL; vktrace_trace_packet_message* msgPacket; struct seqBookmark startingPacket; bool trace_running = true; int prevFrameNumber = -1; // record the location of looping start packet seq.record_bookmark(); seq.get_bookmark(startingPacket); while (settings.numLoops > 0) { while ((packet = seq.get_next_packet()) != NULL && trace_running) { switch (packet->packet_id) { case VKTRACE_TPI_MESSAGE: msgPacket = vktrace_interpret_body_as_trace_packet_message(packet); vktrace_LogAlways("Packet %lu: Traced Message (%s): %s", packet->global_packet_index, vktrace_LogLevelToShortString(msgPacket->type), msgPacket->message); break; case VKTRACE_TPI_MARKER_CHECKPOINT: break; case VKTRACE_TPI_MARKER_API_BOUNDARY: break; case VKTRACE_TPI_MARKER_API_GROUP_BEGIN: break; case VKTRACE_TPI_MARKER_API_GROUP_END: break; case VKTRACE_TPI_MARKER_TERMINATE_PROCESS: break; //TODO processing code for all the above cases default: { if (packet->tracer_id >= VKTRACE_MAX_TRACER_ID_ARRAY_SIZE || packet->tracer_id == VKTRACE_TID_RESERVED) { vktrace_LogError("Tracer_id from packet num packet %d invalid.", packet->packet_id); continue; } replayer = replayerArray[packet->tracer_id]; if (replayer == NULL) { vktrace_LogWarning("Tracer_id %d has no valid replayer.", packet->tracer_id); continue; } if (packet->packet_id >= VKTRACE_TPI_BEGIN_API_HERE) { // replay the API packet res = replayer->Replay(replayer->Interpret(packet)); if (res != VKTRACE_REPLAY_SUCCESS) { vktrace_LogError("Failed to replay packet_id %d.",packet->packet_id); return -1; } // frame control logic int frameNumber = replayer->GetFrameNumber(); if (prevFrameNumber != frameNumber) { prevFrameNumber = frameNumber; if (frameNumber == settings.loopStartFrame) { // record the location of looping start packet seq.record_bookmark(); seq.get_bookmark(startingPacket); } if (frameNumber == settings.loopEndFrame) { trace_running = false; } } } else { vktrace_LogError("Bad packet type id=%d, index=%d.", packet->packet_id, packet->global_packet_index); return -1; } } } } settings.numLoops--; seq.set_bookmark(startingPacket); trace_running = true; if (replayer != NULL) { replayer->ResetFrameNumber(); } } return err; }