//-----------------------------------------------------------------------------
void vktraceviewer_QTraceFileLoader::loadTraceFile(const QString& filename)
{
    // open trace file and read in header
    memset(&m_traceFileInfo, 0, sizeof(vktraceviewer_trace_file_info));
    m_traceFileInfo.pFile = fopen(filename.toStdString().c_str(), "rb");

    bool bOpened = (m_traceFileInfo.pFile != NULL);
    if (!bOpened)
    {
        emit OutputMessage(VKTRACE_LOG_ERROR, "Unable to open file.");
    }
    else
    {
        m_traceFileInfo.filename = vktrace_allocate_and_copy(filename.toStdString().c_str());
        if (populate_trace_file_info(&m_traceFileInfo) == FALSE)
        {
            emit OutputMessage(VKTRACE_LOG_ERROR, "Unable to populate trace file info from file.");
            bOpened = false;
        }
        else
        {
            // Make sure trace file version is supported
            if (m_traceFileInfo.header.trace_file_version < VKTRACE_TRACE_FILE_VERSION_MINIMUM_COMPATIBLE)
            {
                emit OutputMessage(VKTRACE_LOG_ERROR, QString("Trace file version %1 is older than minimum compatible version (%2).\nYou'll need to make a new trace file, or use an older replayer.").arg(m_traceFileInfo.header.trace_file_version).arg(VKTRACE_TRACE_FILE_VERSION_MINIMUM_COMPATIBLE));
                bOpened = false;
            }

#ifdef USE_STATIC_CONTROLLER_LIBRARY
            m_pController = vtvCreateQController();
            if (bOpened)
#else
            if (!load_controllers(&m_traceFileInfo))
            {
                emit OutputMessage(VKTRACE_LOG_ERROR, "Failed to load necessary debug controllers.");
                bOpened = false;
            }
            else if (bOpened)
#endif
            {
                connect(m_pController, SIGNAL(OutputMessage(VktraceLogLevel, const QString&)), this, SIGNAL(OutputMessage(VktraceLogLevel, const QString&)));
                connect(m_pController, SIGNAL(OutputMessage(VktraceLogLevel, uint64_t, const QString&)), this, SIGNAL(OutputMessage(VktraceLogLevel, uint64_t, const QString&)));

                // interpret the trace file packets
                for (uint64_t i = 0; i < m_traceFileInfo.packetCount; i++)
                {
                    vktraceviewer_trace_file_packet_offsets* pOffsets = &m_traceFileInfo.pPacketOffsets[i];
                    switch (pOffsets->pHeader->packet_id) {
                        case VKTRACE_TPI_MESSAGE:
                            m_traceFileInfo.pPacketOffsets[i].pHeader = vktrace_interpret_body_as_trace_packet_message(pOffsets->pHeader)->pHeader;
                            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:
                        {
                            vktrace_trace_packet_header* pHeader = m_pController->InterpretTracePacket(pOffsets->pHeader);
                            if (pHeader == NULL)
                            {
                                bOpened = false;
                                emit OutputMessage(VKTRACE_LOG_ERROR, QString("Unrecognized packet type: %1").arg(pOffsets->pHeader->packet_id));
                                m_traceFileInfo.pPacketOffsets[i].pHeader = NULL;
                                break;
                            }
                            m_traceFileInfo.pPacketOffsets[i].pHeader = pHeader;
                        }
                    }

                    // break from loop if there is an error
                    if (bOpened == false)
                    {
                        break;
                    }
                }

#ifdef USE_STATIC_CONTROLLER_LIBRARY
            vtvDeleteQController(&m_pController);
#else
            m_controllerFactory.Unload(&m_pController);
#endif
            }
        }

        // TODO: We don't really want to close the trace file yet.
        // I think we want to keep it open so that we can dynamically read from it.
        // BUT we definitely don't want it to get locked open, so we need a smart
        // way to open / close from it when reading.
        fclose(m_traceFileInfo.pFile);
        m_traceFileInfo.pFile = NULL;
    }

    // populate the UI based on trace file info
    emit TraceFileLoaded(bOpened, m_traceFileInfo, m_controllerFilename);

    emit Finished();
}
Пример #2
0
// ------------------------------------------------------------------------------------------------
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;
}
Пример #3
0
void vktraceviewer::onTraceFileLoaded(bool bSuccess, vktraceviewer_trace_file_info fileInfo, const QString& controllerFilename)
{
    QApplication::restoreOverrideCursor();

    if (fileInfo.packetCount == 0)
    {
        LogWarning("The trace file has 0 packets.");
    }
    else if (fileInfo.pPacketOffsets == NULL)
    {
        LogError("No packet offsets read from trace file.");
        bSuccess = false;
    }

    if (!bSuccess)
    {
        LogAlways("...FAILED!");
        QMessageBox::critical(this, tr("Error"), tr("Could not open trace file."));
        close_trace_file();

        if (m_bGeneratingTrace)
        {
            // if the user was generating a trace file, but the trace failed to load,
            // then re-spawn the generate trace dialog.
            prompt_generate_trace();
        }
    }
    else
    {
        m_traceFileInfo = fileInfo;

        setWindowTitle(QString(m_traceFileInfo.filename) + " - " + g_PROJECT_NAME);
        LogAlways("...success!");

        // update settings to reflect the currently open file
        g_settings.trace_file_to_open = vktrace_allocate_and_copy(m_traceFileInfo.filename);
        vktraceviewer_settings_updated();

#ifndef USE_STATIC_CONTROLLER_LIBRARY
        if (!controllerFilename.isEmpty())
        {
            m_pController = m_controllerFactory.Load(controllerFilename.toStdString().c_str());
        }
#else
        m_pController = vtvCreateQController();
#endif

        if (m_pController != NULL)
        {
            connect(m_pController, SIGNAL(OutputMessage(VktraceLogLevel, const QString&)), this, SLOT(OnOutputMessage(VktraceLogLevel, const QString&)));
            connect(m_pController, SIGNAL(OutputMessage(VktraceLogLevel, uint64_t, const QString&)), this, SLOT(OnOutputMessage(VktraceLogLevel, uint64_t, const QString&)));

            // Merge in settings from the controller.
            // This won't replace settings that may have already been loaded from disk.
            vktrace_SettingGroup_merge(m_pController->GetSettings(), &g_pAllSettings, &g_numAllSettings);

            // now update the controller with the loaded settings
            m_pController->UpdateFromSettings(g_pAllSettings, g_numAllSettings);

            //// trace file was loaded, now attempt to open additional session data
            //if (load_or_create_session(filename.c_str(), m_pTraceReader) == false)
            //{
            //    // failing to load session data is not critical, but may result in unexpected behavior at times.
            //    vktraceviewer_output_error("VkTraceViewer was unable to create a session folder to save viewing information. Functionality may be limited.");
            //}

            // Update the UI with the controller
            m_pController->LoadTraceFile(&m_traceFileInfo, this);
        }

        // update toolbar
        ui->searchTextBox->setEnabled(true);
        ui->searchPrevButton->setEnabled(true);
        ui->searchNextButton->setEnabled(true);

        ui->action_Close->setEnabled(true);
        ui->actionExport_API_Calls->setEnabled(true);

        ui->prevDrawcallButton->setEnabled(true);
        ui->nextDrawcallButton->setEnabled(true);

        // reset flag indicating that the ui may have been generating a trace file.
        m_bGeneratingTrace = false;

        GenerateTraceFileStats();
    }