예제 #1
0
파일: voglsyms.cpp 프로젝트: stahara/vogl
//----------------------------------------------------------------------------------------------------------------------
// init_logfile
//----------------------------------------------------------------------------------------------------------------------
static bool init_logfile()
{
    VOGL_FUNC_TRACER

    dynamic_string log_file(g_command_line_params().get_value_as_string_or_empty("logfile"));
    dynamic_string log_file_append(g_command_line_params().get_value_as_string_or_empty("logfile_append"));
    if (log_file.is_empty() && log_file_append.is_empty())
        return true;

    dynamic_string filename(log_file_append.is_empty() ? log_file : log_file_append);

    // This purposely leaks, don't care
    g_vogl_pLog_stream = vogl_new(cfile_stream);

    if (!g_vogl_pLog_stream->open(filename.get_ptr(), cDataStreamWritable, !log_file_append.is_empty()))
    {
        vogl_error_printf("%s: Failed opening log file \"%s\"\n", VOGL_FUNCTION_NAME, filename.get_ptr());
        return false;
    }
    else
    {
        vogl_message_printf("Opened log file \"%s\"\n", filename.get_ptr());
        console::set_log_stream(g_vogl_pLog_stream);
    }

    return true;
}
예제 #2
0
bool vogleditor_traceReplayer::process_x_events()
{
    while (X11_Pending(m_window.get_display()))
    {
       XEvent newEvent;

       // Watch for new X events
       XNextEvent(m_window.get_display(), &newEvent);

       switch (newEvent.type)
       {
          case MapNotify:
          {
             m_pTraceReplayer->update_window_dimensions();
             break;
          }
          case ConfigureNotify:
          {
             m_pTraceReplayer->update_window_dimensions();
             break;
          }
          case DestroyNotify:
          {
             vogl_message_printf("Exiting\n");
             return false;
             break;
          }
          case ClientMessage:
          {
             if(newEvent.xclient.data.l[0] == (int)m_wmDeleteMessage)
             {
                vogl_message_printf("Exiting\n");
                return false;
             }

             break;
          }
          default: break;
       }
    }

    return true;
}
예제 #3
0
파일: voglbench.cpp 프로젝트: CSRedRat/vogl
//----------------------------------------------------------------------------------------------------------------------
// main
//----------------------------------------------------------------------------------------------------------------------
int main(int argc, char *argv[])
{
#if VOGL_FUNCTION_TRACING
    fflush(stdout);
    fflush(stderr);
    setvbuf(stdout, NULL, _IONBF, 0);
    setvbuf(stderr, NULL, _IONBF, 0);
#endif

    VOGL_FUNC_TRACER

    // Initialize vogl_core.
    vogl_core_init();

    XSetErrorHandler(xerror_handler);

    if (!voglbench_init(argc, argv))
    {
        voglbench_deinit();
        return EXIT_FAILURE;
    }

    if (g_command_line_params().get_count("") < 2)
    {
        vogl_error_printf("No trace file specified!\n");

        tool_print_help();

        voglbench_deinit();
        return EXIT_FAILURE;
    }

    if (g_command_line_params().get_value_as_bool("pause"))
    {
        vogl_message_printf("Press key to continue\n");
        vogl_sleep(1000);
        getchar();
    }

    bool success = tool_replay_mode();

    vogl_printf("%u warning(s), %u error(s)\n",
                    console::get_total_messages(cWarningConsoleMessage),
                    console::get_total_messages(cErrorConsoleMessage));

    voglbench_deinit();

    return success ? EXIT_SUCCESS : EXIT_FAILURE;
}
예제 #4
0
//----------------------------------------------------------------------------------------------------------------------
// init_logfile
//----------------------------------------------------------------------------------------------------------------------
static bool init_logfile()
{
    VOGL_FUNC_TRACER

    dynamic_string backbuffer_hash_file;
    if (g_command_line_params().get_value_as_string(backbuffer_hash_file, "dump_backbuffer_hashes"))
    {
        remove(backbuffer_hash_file.get_ptr());
        vogl_message_printf("Deleted backbuffer hash file \"%s\"\n", backbuffer_hash_file.get_ptr());
    }

    dynamic_string filename(g_command_line_params().get_value_as_string_or_empty("logfile"));
    if (filename.is_empty())
        return true;

    return console::set_log_stream_filename(filename.c_str(), false);
}
예제 #5
0
파일: voglsyms.cpp 프로젝트: stahara/vogl
//----------------------------------------------------------------------------------------------------------------------
// dump_compiler_info
//----------------------------------------------------------------------------------------------------------------------
static bool dump_compiler_info(vogl_trace_file_reader *pTrace_reader, dynamic_string &tracefile_arch)
{
    if (pTrace_reader->get_archive_blob_manager().does_exist(VOGL_TRACE_ARCHIVE_COMPILER_INFO_FILENAME))
    {
        vogl_header1_printf("%s\n", std::string(78, '*').c_str());
        vogl_header1_printf("%s\n", VOGL_TRACE_ARCHIVE_COMPILER_INFO_FILENAME);
        vogl_header1_printf("%s\n", std::string(78, '*').c_str());

        uint8_vec machine_info_data;
        if (pTrace_reader->get_archive_blob_manager().get(VOGL_TRACE_ARCHIVE_COMPILER_INFO_FILENAME, machine_info_data))
        {
            json_document doc;
            json_node *pRoot = doc.get_root();

            if (doc.deserialize((const char *)machine_info_data.get_ptr(), machine_info_data.size()) && pRoot->size())
            {
                for (uint i = 0; i < pRoot->size(); i++)
                {
                    const dynamic_string &sectionKeyStr = pRoot->get_key(i);

                    vogl_message_printf("%s\n", sectionKeyStr.c_str());
                    const vogl::json_value &value = pRoot->get_value(i);
                    const json_node *pNode = value.get_node_ptr();

                    // glinfo, uname, etc.
                    for (uint j = 0; j < pNode->size(); j++)
                    {
                        dynamic_string key = pNode->get_key(j);
                        const vogl::json_value &val = pNode->get_value(j);
                        dynamic_string str = val.as_string();

                        vogl_printf("  %s: %s\n", key.c_str(), str.c_str());

                        if (!key.compare("arch"))
                            tracefile_arch = str;
                    }
                }

                vogl_printf("\n");
                return true;
            }
        }
    }

    return false;
}
예제 #6
0
파일: voglsyms.cpp 프로젝트: stahara/vogl
//----------------------------------------------------------------------------------------------------------------------
// main
//----------------------------------------------------------------------------------------------------------------------
int main(int argc, char *argv[])
{
#if VOGL_FUNCTION_TRACING
    fflush(stdout);
    fflush(stderr);
    setvbuf(stdout, NULL, _IONBF, 0);
    setvbuf(stderr, NULL, _IONBF, 0);
#endif

    VOGL_FUNC_TRACER

    // Initialize vogl_core.
    vogl_core_init();

    if (!voglsyms_init(argc, argv))
    {
        voglsyms_deinit();
        return EXIT_FAILURE;
    }

    if (g_command_line_params().get_count("") < 2)
    {
        vogl_error_printf("No trace file specified!\n");

        tool_print_help();

        voglsyms_deinit();
        return EXIT_FAILURE;
    }

    if (g_command_line_params().get_value_as_bool("pause"))
    {
        vogl_message_printf("Press key to continue\n");
        vogl_sleep(1000);
        getchar();
    }

    bool success = voglsym_main_loop(argv);

    voglsyms_deinit();

    return success ? EXIT_SUCCESS : EXIT_FAILURE;
}
예제 #7
0
// pTrace_archive may be NULL. Takes ownership of pTrace_archive.
// TODO: Get rid of the demarcation packet, etc. Make the initial sequence of packets more explicit.
bool vogl_trace_file_writer::open(const char *pFilename, vogl_archive_blob_manager *pTrace_archive, bool delete_archive, bool write_demarcation_packet, uint pointer_sizes)
{
    VOGL_FUNC_TRACER

    close();

    if (!pFilename)
        return false;

    m_filename = pFilename;
    if (!m_stream.open(pFilename, cDataStreamWritable | cDataStreamSeekable, false))
    {
        vogl_error_printf("%s: Failed opening trace file \"%s\"\n", VOGL_METHOD_NAME, pFilename);
        return false;
    }

    vogl_message_printf("%s: Prepping trace file \"%s\"\n", VOGL_METHOD_NAME, pFilename);

    m_sof_packet.init();
    m_sof_packet.m_pointer_sizes = pointer_sizes;
    m_sof_packet.m_first_packet_offset = sizeof(m_sof_packet);

    md5_hash h(gen_uuid());
    VOGL_ASSUME(sizeof(h) == sizeof(m_sof_packet.m_uuid));
    memcpy(&m_sof_packet.m_uuid, &h, sizeof(h));

    m_sof_packet.finalize();
    VOGL_VERIFY(m_sof_packet.full_validation(sizeof(m_sof_packet)));

    if (m_stream.write(&m_sof_packet, sizeof(m_sof_packet)) != sizeof(m_sof_packet))
    {
        vogl_error_printf("%s: Failed writing to trace file \"%s\"\n", VOGL_METHOD_NAME, pFilename);
        return false;
    }

    if (pTrace_archive)
    {
        m_pTrace_archive.reset(pTrace_archive);
        m_delete_archive = delete_archive;
    }
    else
    {
        m_pTrace_archive.reset(vogl_new(vogl_archive_blob_manager));
        m_delete_archive = true;

        if (!m_pTrace_archive->init_file_temp(cBMFReadWrite, NULL))
        {
            vogl_error_printf("%s: Failed opening temp archive!\n", VOGL_METHOD_NAME);

            m_pTrace_archive.reset();

            return false;
        }
    }

    // TODO: The trace reader records the first offset right after SOF, I would like to do this after the demarcation packet.
    m_frame_file_offsets.reserve(10000);
    m_frame_file_offsets.resize(0);
    m_frame_file_offsets.push_back(m_stream.get_ofs());

    write_ctypes_packet();

    write_entrypoints_packet();

    if (write_demarcation_packet)
    {
        vogl_write_glInternalTraceCommandRAD(m_stream, m_pCTypes, cITCRDemarcation, 0, NULL);
    }

    vogl_message_printf("%s: Finished opening trace file \"%s\"\n", VOGL_METHOD_NAME, pFilename);

    return true;
}
예제 #8
0
bool vogl_trace_file_writer::close()
{
    VOGL_FUNC_TRACER

    vogl_debug_printf("%s\n", VOGL_METHOD_NAME);

    if (!m_stream.is_opened())
        return false;

    vogl_message_printf("%s: Flushing trace file %s (this could take some time), %u total frame file offsets\n", VOGL_METHOD_NAME, m_filename.get_ptr(), m_frame_file_offsets.size());

    bool success = true;

    dynamic_string trace_archive_filename;

    if (!write_eof_packet())
    {
        vogl_error_printf("%s: Failed writing to trace file \"%s\"\n", VOGL_METHOD_NAME, m_filename.get_ptr());
        success = false;
    }
    else if (m_pTrace_archive.get())
    {
        trace_archive_filename = m_pTrace_archive->get_archive_filename();

        if ((!write_frame_file_offsets_to_archive()) || !m_pTrace_archive->deinit())
        {
            vogl_error_printf("%s: Failed closing trace archive \"%s\"!\n", VOGL_FUNCTION_NAME, trace_archive_filename.get_ptr());
            success = false;
        }
        else
        {
            if (!file_utils::get_file_size(trace_archive_filename.get_ptr(), m_sof_packet.m_archive_size))
            {
                vogl_error_printf("%s: Failed determining file size of archive file \"%s\"\n", VOGL_FUNCTION_NAME, trace_archive_filename.get_ptr());
                success = false;
            }
            else if (m_sof_packet.m_archive_size)
            {
                m_sof_packet.m_archive_offset = m_stream.get_size();

                vogl_message_printf("Copying %" PRIu64 " archive bytes into output trace file\n", m_sof_packet.m_archive_size);

                if (!m_stream.write_file_data(trace_archive_filename.get_ptr()))
                {
                    vogl_error_printf("%s: Failed copying source archive \"%s\" into trace file!\n", VOGL_METHOD_NAME, trace_archive_filename.get_ptr());
                    success = false;
                }

                m_sof_packet.m_archive_size = m_stream.get_size() - m_sof_packet.m_archive_offset;
            }
        }

        if (success)
        {
            m_sof_packet.finalize();
            VOGL_VERIFY(m_sof_packet.full_validation(sizeof(m_sof_packet)));

            if (!m_stream.seek(0, false) || (m_stream.write(&m_sof_packet, sizeof(m_sof_packet)) != sizeof(m_sof_packet)))
            {
                vogl_error_printf("%s: Failed writing to trace file \"%s\"\n", VOGL_METHOD_NAME, m_filename.get_ptr());
                success = false;
            }
        }
    }

    close_archive(trace_archive_filename.get_ptr());

    uint64_t total_trace_file_size = m_stream.get_size();

    if (!m_stream.close())
    {
        vogl_error_printf("Failed writing to or closing trace file!\n");
        success = false;
    }

    dynamic_string full_trace_filename(m_filename);
    file_utils::full_path(full_trace_filename);

    if (success)
        vogl_message_printf("%s: Successfully closed trace file %s, total file size: %s\n", VOGL_METHOD_NAME, full_trace_filename.get_ptr(), uint64_to_string_with_commas(total_trace_file_size).get_ptr());
    else
        vogl_error_printf("%s: Failed closing trace file %s! (Trace will probably not be valid.)\n", VOGL_METHOD_NAME, full_trace_filename.get_ptr());

    return success;
}
예제 #9
0
파일: voglsyms.cpp 프로젝트: stahara/vogl
//----------------------------------------------------------------------------------------------------------------------
// dump_machine_info
//----------------------------------------------------------------------------------------------------------------------
static bool dump_machine_info(vogl_trace_file_reader *pTrace_reader, vector<btrace_module_info> &module_infos)
{
    if (pTrace_reader->get_archive_blob_manager().does_exist(VOGL_TRACE_ARCHIVE_MACHINE_INFO_FILENAME))
    {
        vogl_header1_printf("%s\n", std::string(78, '*').c_str());
        vogl_header1_printf("%s\n", VOGL_TRACE_ARCHIVE_MACHINE_INFO_FILENAME);
        vogl_header1_printf("%s\n", std::string(78, '*').c_str());

        uint8_vec machine_info_data;
        if (pTrace_reader->get_archive_blob_manager().get(VOGL_TRACE_ARCHIVE_MACHINE_INFO_FILENAME, machine_info_data))
        {
            json_document doc;
            json_node *pRoot = doc.get_root();

            if (doc.deserialize((const char *)machine_info_data.get_ptr(), machine_info_data.size()) && pRoot->size())
            {
                for (uint i = 0; i < pRoot->size(); i++)
                {
                    const dynamic_string &sectionKeyStr = pRoot->get_key(i);

                    const vogl::json_value &value = pRoot->get_value(i);
                    const json_node *pNode = value.get_node_ptr();

                    bool is_module_list = (sectionKeyStr == "module_list") && value.is_node();

                    if (!is_module_list)
                    {
                        vogl_message_printf("%s\n", sectionKeyStr.c_str());
                    }

                    if (is_module_list)
                    {
                        for (uint j = 0; j < pNode->size(); j++)
                        {
                            dynamic_string key = pNode->get_key(j);
                            const vogl::json_value &val = pNode->get_value(j);

                            // key is filename, addr_base, addr_size, uuid, is_exe
                            if (val.is_array())
                            {
                                uint index = 0;
                                const json_node *pNode2 = val.get_node_ptr();
                                uint size = pNode2->size();

                                btrace_module_info module_info;

                                memset(&module_info, 0, sizeof(module_info));

                                module_info.filename = vogl::vogl_strdup(key.c_str());
                                module_info.base_address = (index < size) ? (uintptr_t)pNode2->get_value(index++).as_uint64() : 0;
                                module_info.address_size = (index < size) ? pNode2->get_value(index++).as_uint32() : 0;
                                const char *uuid_str = (index < size) ? pNode2->get_value(index++).as_string_ptr() : "--";
                                module_info.is_exe = (index < size) ? pNode2->get_value(index++).as_string() == "(exe)" : false;

                                module_info.uuid_len = btrace_uuid_str_to_uuid(module_info.uuid, uuid_str);
                                module_infos.push_back(module_info);
                            }
                        }
                    }
                    else if (value.is_array())
                    {
                        // environ_list, cmdline, etc.
                        for (uint element = 0; element < pNode->size(); element++)
                        {
                            dynamic_string str = pNode->get_value(element).as_string();
                            vogl_printf("  %s\n", str.c_str());
                        }

                        vogl_printf("\n");
                    }
                    else if (value.is_node())
                    {
                        // glinfo, uname, etc.
                        for (uint j = 0; j < pNode->size(); j++)
                        {
                            dynamic_string key = pNode->get_key(j);
                            const vogl::json_value &val = pNode->get_value(j);

                            dynamic_string str = val.as_string();

                            if (val.is_array())
                            {
                                const json_node *pNode2 = val.get_node_ptr();

                                vogl_printf("%s\n", key.c_str());
                                for (uint element = 0; element < pNode2->size(); element++)
                                {
                                    dynamic_string str2 = pNode2->get_value(element).as_string();
                                    vogl_printf("  %s\n", str2.c_str());
                                }
                            }
                            else
                            {
                                vogl_printf("  %s: %s\n", key.c_str(), str.c_str());
                            }
                        }
                        vogl_printf("\n");
                    }
                    else
                    {
                        dynamic_string str = value.as_string();
                        vogl_printf("%s\n", str.c_str());
                    }
                }
            }

            return true;
        }
    }

    return false;
}
예제 #10
0
    //----------------------------------------------------------------------------------------------------------------------
    // tool_replay_mode
    //----------------------------------------------------------------------------------------------------------------------
    static bool tool_replay_mode()
    {
        VOGL_FUNC_TRACER

        dynamic_string trace_filename(g_command_line_params().get_value_as_string_or_empty("", 1));
        if (trace_filename.is_empty())
        {
            vogl_error_printf("No trace file specified!\n");
            return false;
        }

        dynamic_string actual_trace_filename;
        vogl_unique_ptr<vogl_trace_file_reader> pTrace_reader(
            vogl_open_trace_file(
                trace_filename,
                actual_trace_filename,
                g_command_line_params().get_value_as_string_or_empty("loose_file_path").get_ptr()
            )
        );

        if (!pTrace_reader.get())
        {
            vogl_error_printf("File not found, or unable to determine file type of trace file \"%s\"\n", trace_filename.get_ptr());
            return false;
        }

        vogl_printf("Reading trace file %s\n", actual_trace_filename.get_ptr());

        vogl_gl_replayer replayer;
        vogl_replay_window window;

        #if defined(PLATFORM_WINDOWS)
            // We need to get proc addresses for windows late.
            replayer.set_proc_address_helper(vogl_get_proc_address_helper, false);
        #endif

        uint replayer_flags = get_replayer_flags_from_command_line_params();

        // TODO: This will create a window with default attributes, which seems fine for the majority of traces.
        // Unfortunately, some GL call streams *don't* want an alpha channel, or depth, or stencil etc. in the default framebuffer so this may become a problem.
        // Also, this design only supports a single window, which is going to be a problem with multiple window traces.
        if (!window.open(g_command_line_params().get_value_as_int("width", 0, 1024, 1, 65535), g_command_line_params().get_value_as_int("height", 0, 768, 1, 65535), g_command_line_params().get_value_as_int("msaa", 0, 0, 0, 65535)))
        {
            vogl_error_printf("Failed initializing replay window\n");
            return false;
        }

        if (!replayer.init(replayer_flags, &window, pTrace_reader->get_sof_packet(), pTrace_reader->get_multi_blob_manager()))
        {
            vogl_error_printf("Failed initializing GL replayer\n");
            return false;
        }

        // Disable all glGetError() calls in vogl_utils.cpp.
        vogl_disable_gl_get_error();

        // Bool win_mapped = false;

        vogl_gl_state_snapshot *pSnapshot = NULL;
        int64_t snapshot_loop_start_frame = -1;
        int64_t snapshot_loop_end_frame = -1;

        vogl::hash_map<SDL_Keycode> keys_pressed, keys_down;

        int loop_frame = g_command_line_params().get_value_as_int("loop_frame", 0, -1);
        int loop_len = math::maximum<int>(g_command_line_params().get_value_as_int("loop_len", 0, 1), 1);
        int loop_count = math::maximum<int>(g_command_line_params().get_value_as_int("loop_count", 0, cINT32_MAX), 1);
        bool endless_mode = g_command_line_params().get_value_as_bool("endless");

        timer tm;
        tm.start();

        for (;;)
        {
            tmZone(TELEMETRY_LEVEL0, TMZF_NONE, "Main Loop");

            SDL_Event wnd_event;
            
            while (SDL_PollEvent(&wnd_event))
            {
                switch (wnd_event.type)
                {
                    case SDL_KEYDOWN:
                    {
                        keys_down.insert(wnd_event.key.keysym.sym);
                        keys_pressed.insert(wnd_event.key.keysym.sym);
                        break;
                    }

                    case SDL_KEYUP:
                    {
                        keys_down.erase(wnd_event.key.keysym.sym);

                        break;
                    }

                    case SDL_WINDOWEVENT:
                    {
                        switch(wnd_event.window.event)
                        {
                            case SDL_WINDOWEVENT_FOCUS_GAINED:
                            case SDL_WINDOWEVENT_FOCUS_LOST:
                                keys_down.reset();
                                break;

                            case SDL_WINDOWEVENT_CLOSE:
                                vogl_message_printf("Window told to close, exiting.\n");
                                goto normal_exit;
                                break;
                            default:
                                break;
                        };
                        break;
                    }

                    default:
                        // TODO: Handle these somehow?
                        break;
                };
            }

            if (replayer.get_at_frame_boundary())
            {
                if ((!pSnapshot) && (loop_frame != -1) && (static_cast<int64_t>(replayer.get_frame_index()) == loop_frame))
                {
                    vogl_debug_printf("Capturing replayer state at start of frame %u\n", replayer.get_frame_index());

                    pSnapshot = replayer.snapshot_state();

                    if (pSnapshot)
                    {
                        vogl_printf("Snapshot succeeded\n");

                        snapshot_loop_start_frame = pTrace_reader->get_cur_frame();
                        snapshot_loop_end_frame = pTrace_reader->get_cur_frame() + loop_len;

                        vogl_debug_printf("Loop start: %" PRIi64 " Loop end: %" PRIi64 "\n", snapshot_loop_start_frame, snapshot_loop_end_frame);
                    }
                    else
                    {
                        vogl_error_printf("Snapshot failed!\n");
                        loop_frame = -1;
                    }
                }
            }

            vogl_gl_replayer::status_t status = replayer.process_pending_window_resize();
            if (status == vogl_gl_replayer::cStatusOK)
            {
                for (;;)
                {
                    status = replayer.process_pending_packets();

                    if (status == vogl_gl_replayer::cStatusOK)
                    {
                        status = replayer.process_next_packet(*pTrace_reader);
                    }

                    if ((status == vogl_gl_replayer::cStatusNextFrame) ||
                        (status == vogl_gl_replayer::cStatusResizeWindow) ||
                        (status == vogl_gl_replayer::cStatusAtEOF) ||
                        (status == vogl_gl_replayer::cStatusHardFailure))
                    {
                        break;
                    }
                }
            }

            if (status == vogl_gl_replayer::cStatusHardFailure)
                break;

            if (status == vogl_gl_replayer::cStatusAtEOF)
            {
                vogl_message_printf("At trace EOF, frame index %u\n", replayer.get_frame_index());
            }

            if (replayer.get_at_frame_boundary() &&
                pSnapshot && 
                (loop_count > 0) &&
                ((pTrace_reader->get_cur_frame() == snapshot_loop_end_frame) || (status == vogl_gl_replayer::cStatusAtEOF)))
            {
                status = replayer.begin_applying_snapshot(pSnapshot, false);
                if ((status != vogl_gl_replayer::cStatusOK) && (status != vogl_gl_replayer::cStatusResizeWindow))
                    goto error_exit;

                pTrace_reader->seek_to_frame(static_cast<uint>(snapshot_loop_start_frame));

                vogl_debug_printf("Applying snapshot and seeking back to frame %" PRIi64 "\n", snapshot_loop_start_frame);
                loop_count--;
            }
            else
            {
                bool print_progress = (status == vogl_gl_replayer::cStatusAtEOF) ||
                    ((replayer.get_at_frame_boundary()) && ((replayer.get_frame_index() % 100) == 0));
                if (print_progress)
                {
                    if (pTrace_reader->get_type() == cBINARY_TRACE_FILE_READER)
                    {
                        vogl_binary_trace_file_reader &binary_trace_reader = *static_cast<vogl_binary_trace_file_reader *>(pTrace_reader.get());

                        vogl_printf("Replay now at frame index %u, trace file offet %" PRIu64 ", GL call counter %" PRIu64 ", %3.2f%% percent complete\n",
                            replayer.get_frame_index(),
                            binary_trace_reader.get_cur_file_ofs(),
                            replayer.get_last_parsed_call_counter(),
                            binary_trace_reader.get_trace_file_size() ? (binary_trace_reader.get_cur_file_ofs() * 100.0f) / binary_trace_reader.get_trace_file_size() : 0);
                    }
                }

                if (status == vogl_gl_replayer::cStatusAtEOF)
                {
                    if (!endless_mode)
                    {
                        double time_since_start = tm.get_elapsed_secs();

                        vogl_printf("%u total swaps, %.3f secs, %3.3f avg fps\n", replayer.get_total_swaps(), time_since_start, replayer.get_frame_index() / time_since_start);
                        break;
                    }

                    vogl_printf("Resetting state and rewinding back to frame 0\n");

                    replayer.reset_state();

                    if (!pTrace_reader->seek_to_frame(0))
                    {
                        vogl_error_printf("Failed rewinding trace reader!\n");
                        goto error_exit;
                    }
                }
            }

            telemetry_tick();
        }

    normal_exit:
        return true;

    error_exit:
        return false;
    }
예제 #11
0
bool vogleditor_traceReplayer::replay(vogl_trace_file_reader* m_pTraceReader, vogleditor_apiCallTreeItem* pRootItem, vogleditor_gl_state_snapshot** ppNewSnapshot, uint64_t apiCallNumber, bool endlessMode)
{
   // reset to beginnning of trace file.
   m_pTraceReader->seek_to_frame(0);

   int initial_window_width = 1280;
   int initial_window_height = 1024;

   if (!m_window.open(initial_window_width, initial_window_height))
   {
      vogl_error_printf("%s: Failed opening GL replayer window!\n", VOGL_FUNCTION_NAME);
      return false;
   }

   uint replayer_flags = cGLReplayerForceDebugContexts;
   if (!m_pTraceReplayer->init(replayer_flags, &m_window, m_pTraceReader->get_sof_packet(), m_pTraceReader->get_multi_blob_manager()))
   {
      vogl_error_printf("%s: Failed initializing GL replayer\n", VOGL_FUNCTION_NAME);
      m_window.close();
      return false;
   }

   XSelectInput(m_window.get_display(), m_window.get_xwindow(),
                EnterWindowMask | LeaveWindowMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | ExposureMask | FocusChangeMask | KeyPressMask | KeyReleaseMask | PropertyChangeMask | StructureNotifyMask | KeymapStateMask);

   m_wmDeleteMessage = XInternAtom(m_window.get_display(), "WM_DELETE_WINDOW", False);
   XSetWMProtocols(m_window.get_display(), m_window.get_xwindow(), &m_wmDeleteMessage, 1);

   timer tm;
   tm.start();

   bool bStatus = true;

   for ( ; ; )
   {
      if (process_x_events() == false)
      {
          break;
      }

      if (pRootItem->childCount() > 0)
      {
          vogleditor_apiCallTreeItem* pFirstFrame = pRootItem->child(0);

          // if the first snapshot has not been edited, then restore it here, otherwise it will get restored in the recursive call below.
          if (pFirstFrame->has_snapshot() && !pFirstFrame->get_snapshot()->is_edited())
          {
              bStatus = applying_snapshot_and_process_resize(pFirstFrame->get_snapshot()->get_snapshot());
          }

          if (bStatus)
          {
              // replay each API call.
              bStatus = recursive_replay_apicallTreeItem(pRootItem, ppNewSnapshot, apiCallNumber);

              if (bStatus == false)
              {
                 vogl_error_printf("%s: Replay ending abruptly at frame index %u, global api call %" PRIu64 "\n", VOGL_FUNCTION_NAME, m_pTraceReplayer->get_frame_index(), m_pTraceReplayer->get_last_processed_call_counter());
                 break;
              }
              else
              {
                 vogl_message_printf("%s: At trace EOF, frame index %u\n", VOGL_FUNCTION_NAME, m_pTraceReplayer->get_frame_index());
                 if (!endlessMode)
                 {
                     break;
                 }
              }
          }
          else
          {
              break;
          }
      }
   }

   m_pTraceReplayer->deinit();
   m_window.close();
   return bStatus;
}
예제 #12
0
파일: voglbench.cpp 프로젝트: CSRedRat/vogl
//----------------------------------------------------------------------------------------------------------------------
// tool_replay_mode
//----------------------------------------------------------------------------------------------------------------------
static bool tool_replay_mode()
{
    VOGL_FUNC_TRACER

    dynamic_string trace_filename(g_command_line_params().get_value_as_string_or_empty("", 1));
    if (trace_filename.is_empty())
    {
        vogl_error_printf("%s: No trace file specified!\n", VOGL_FUNCTION_INFO_CSTR);
        return false;
    }

    dynamic_string actual_trace_filename;
    vogl_unique_ptr<vogl_trace_file_reader> pTrace_reader(vogl_open_trace_file(
                trace_filename,
                actual_trace_filename,
                g_command_line_params().get_value_as_string_or_empty("loose_file_path").get_ptr()));
    if (!pTrace_reader.get())
    {
        vogl_error_printf("%s: File not found, or unable to determine file type of trace file \"%s\"\n", VOGL_FUNCTION_INFO_CSTR, trace_filename.get_ptr());
        return false;
    }

    vogl_printf("Reading trace file %s\n", actual_trace_filename.get_ptr());

    vogl_gl_replayer replayer;
    vogl_replay_window window;

    uint replayer_flags = get_replayer_flags_from_command_line_params();

    // TODO: This will create a window with default attributes, which seems fine for the majority of traces.
    // Unfortunately, some GL call streams *don't* want an alpha channel, or depth, or stencil etc. in the default framebuffer so this may become a problem.
    // Also, this design only supports a single window, which is going to be a problem with multiple window traces.
    if (!window.open(g_command_line_params().get_value_as_int("width", 0, 1024, 1, 65535), g_command_line_params().get_value_as_int("height", 0, 768, 1, 65535), g_command_line_params().get_value_as_int("msaa", 0, 0, 0, 65535)))
    {
        vogl_error_printf("%s: Failed initializing replay window\n", VOGL_FUNCTION_INFO_CSTR);
        return false;
    }

    if (!replayer.init(replayer_flags, &window, pTrace_reader->get_sof_packet(), pTrace_reader->get_multi_blob_manager()))
    {
        vogl_error_printf("%s: Failed initializing GL replayer\n", VOGL_FUNCTION_INFO_CSTR);
        return false;
    }

    // Disable all glGetError() calls in vogl_utils.cpp.
    vogl_disable_gl_get_error();

    XSelectInput(window.get_display(), window.get_xwindow(),
                 EnterWindowMask | LeaveWindowMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | ExposureMask | FocusChangeMask | KeyPressMask | KeyReleaseMask | PropertyChangeMask | StructureNotifyMask | KeymapStateMask);

    Atom wmDeleteMessage = XInternAtom(window.get_display(), "WM_DELETE_WINDOW", False);
    XSetWMProtocols(window.get_display(), window.get_xwindow(), &wmDeleteMessage, 1);

    // Bool win_mapped = false;

    vogl_gl_state_snapshot *pSnapshot = NULL;
    int64_t snapshot_loop_start_frame = -1;
    int64_t snapshot_loop_end_frame = -1;

    vogl::hash_map<uint64_t> keys_pressed, keys_down;

    int loop_frame = g_command_line_params().get_value_as_int("loop_frame", 0, -1);
    int loop_len = math::maximum<int>(g_command_line_params().get_value_as_int("loop_len", 0, 1), 1);
    int loop_count = math::maximum<int>(g_command_line_params().get_value_as_int("loop_count", 0, cINT32_MAX), 1);
    bool endless_mode = g_command_line_params().get_value_as_bool("endless");

    timer tm;
    tm.start();

    for (;;)
    {
        tmZone(TELEMETRY_LEVEL0, TMZF_NONE, "Main Loop");

        while (X11_Pending(window.get_display()))
        {
            XEvent newEvent;

            // Watch for new X eventsn
            XNextEvent(window.get_display(), &newEvent);

            switch (newEvent.type)
            {
                case KeyPress:
                {
                    KeySym xsym = XLookupKeysym(&newEvent.xkey, 0);

                    //printf("KeyPress 0%04llX %" PRIu64 "\n", (uint64_t)xsym, (uint64_t)xsym);

                    keys_down.insert(xsym);
                    keys_pressed.insert(xsym);

                    break;
                }
                case KeyRelease:
                {
                    KeySym xsym = XLookupKeysym(&newEvent.xkey, 0);

                    //printf("KeyRelease 0x%04llX %" PRIu64 "\n", (uint64_t)xsym, (uint64_t)xsym);

                    keys_down.erase(xsym);

                    break;
                }
                case FocusIn:
                case FocusOut:
                {
                    //printf("FocusIn/FocusOut\n");

                    keys_down.reset();

                    break;
                }
                case MappingNotify:
                {
                    //XRefreshKeyboardMapping(&newEvent);
                    break;
                }
                case UnmapNotify:
                {
                    // printf("UnmapNotify\n");
                    // win_mapped = false;

                    keys_down.reset();

                    break;
                }
                case MapNotify:
                {
                    // printf("MapNotify\n");
                    // win_mapped = true;

                    keys_down.reset();

                    if (!replayer.update_window_dimensions())
                        goto error_exit;

                    break;
                }
                case ConfigureNotify:
                {
                    if (!replayer.update_window_dimensions())
                        goto error_exit;

                    break;
                }
                case DestroyNotify:
                {
                    vogl_message_printf("Exiting\n");
                    goto normal_exit;
                }
                case ClientMessage:
                {
                    if (newEvent.xclient.data.l[0] == (int)wmDeleteMessage)
                    {
                        vogl_message_printf("Exiting\n");
                        goto normal_exit;
                    }

                    break;
                }
                default:
                    break;
            }
        }

        if (replayer.get_at_frame_boundary())
        {
            if ((!pSnapshot) && (loop_frame != -1) && (static_cast<int64_t>(replayer.get_frame_index()) == loop_frame))
            {
                vogl_debug_printf("%s: Capturing replayer state at start of frame %u\n", VOGL_FUNCTION_INFO_CSTR, replayer.get_frame_index());

                pSnapshot = replayer.snapshot_state();

                if (pSnapshot)
                {
                    vogl_printf("Snapshot succeeded\n");

                    snapshot_loop_start_frame = pTrace_reader->get_cur_frame();
                    snapshot_loop_end_frame = pTrace_reader->get_cur_frame() + loop_len;

                    vogl_debug_printf("%s: Loop start: %" PRIi64 " Loop end: %" PRIi64 "\n", VOGL_FUNCTION_INFO_CSTR, snapshot_loop_start_frame, snapshot_loop_end_frame);
                }
                else
                {
                    vogl_error_printf("Snapshot failed!\n");
                    loop_frame = -1;
                }
            }
        }

        vogl_gl_replayer::status_t status = replayer.process_pending_window_resize();
        if (status == vogl_gl_replayer::cStatusOK)
        {
            for (;;)
            {
                status = replayer.process_next_packet(*pTrace_reader);

                if ((status == vogl_gl_replayer::cStatusNextFrame) ||
                    (status == vogl_gl_replayer::cStatusResizeWindow) ||
                    (status == vogl_gl_replayer::cStatusAtEOF) ||
                    (status == vogl_gl_replayer::cStatusHardFailure))
                {
                    break;
                }
            }
        }

        if (status == vogl_gl_replayer::cStatusHardFailure)
            break;

        if (status == vogl_gl_replayer::cStatusAtEOF)
        {
            vogl_message_printf("%s: At trace EOF, frame index %u\n", VOGL_FUNCTION_INFO_CSTR, replayer.get_frame_index());
        }

        if (replayer.get_at_frame_boundary() &&
                pSnapshot && 
                (loop_count > 0) &&
                ((pTrace_reader->get_cur_frame() == snapshot_loop_end_frame) || (status == vogl_gl_replayer::cStatusAtEOF)))
        {
            status = replayer.begin_applying_snapshot(pSnapshot, false);
            if ((status != vogl_gl_replayer::cStatusOK) && (status != vogl_gl_replayer::cStatusResizeWindow))
                goto error_exit;

            pTrace_reader->seek_to_frame(static_cast<uint>(snapshot_loop_start_frame));

            vogl_debug_printf("%s: Applying snapshot and seeking back to frame %" PRIi64 "\n", VOGL_FUNCTION_INFO_CSTR, snapshot_loop_start_frame);
            loop_count--;
        }
        else
        {
            bool print_progress = (status == vogl_gl_replayer::cStatusAtEOF) ||
                    ((replayer.get_at_frame_boundary()) && ((replayer.get_frame_index() % 100) == 0));
            if (print_progress)
            {
                if (pTrace_reader->get_type() == cBINARY_TRACE_FILE_READER)
                {
                    vogl_binary_trace_file_reader &binary_trace_reader = *static_cast<vogl_binary_trace_file_reader *>(pTrace_reader.get());

                    vogl_printf("Replay now at frame index %u, trace file offet %" PRIu64 ", GL call counter %" PRIu64 ", %3.2f%% percent complete\n",
                               replayer.get_frame_index(),
                               binary_trace_reader.get_cur_file_ofs(),
                               replayer.get_last_parsed_call_counter(),
                               binary_trace_reader.get_trace_file_size() ? (binary_trace_reader.get_cur_file_ofs() * 100.0f) / binary_trace_reader.get_trace_file_size() : 0);
                }
            }

            if (status == vogl_gl_replayer::cStatusAtEOF)
            {
                if (!endless_mode)
                {
                    double time_since_start = tm.get_elapsed_secs();

                    vogl_printf("%u total swaps, %.3f secs, %3.3f avg fps\n", replayer.get_total_swaps(), time_since_start, replayer.get_frame_index() / time_since_start);
                    break;
                }

                vogl_printf("Resetting state and rewinding back to frame 0\n");

                replayer.reset_state();

                if (!pTrace_reader->seek_to_frame(0))
                {
                    vogl_error_printf("%s: Failed rewinding trace reader!\n", VOGL_FUNCTION_INFO_CSTR);
                    goto error_exit;
                }
            }
        }

        telemetry_tick();
    }

normal_exit:
    return true;

error_exit:
    return false;
}
예제 #13
0
bool
tool_trace_mode(vogl::vector<command_line_param_desc> *desc)
{
    arguments_t args;

    if (desc)
    {
        desc->append(g_command_line_param_descs_dump, VOGL_ARRAY_SIZE(g_command_line_param_descs_dump));
        desc->append(g_tracer_cmdline_opts, VOGL_ARRAY_SIZE(g_tracer_cmdline_opts));
        return true;
    }

    // Get steam gameid / local application name.
    args.gameid = g_command_line_params().get_value_as_string_or_empty("", 1);

    if (!args.gameid.size())
        errorf(VOGL_FUNCTION_INFO_CSTR, "ERROR: No application or steamid specified.\n");

    // Get logfile and tracefile names.
    args.vogl_tracefile = g_command_line_params().get_value_as_string("vogl_tracefile");
    args.vogl_logfile = g_command_line_params().get_value_as_string("vogl_logfile");

    args.dryrun = g_command_line_params().get_value_as_bool("dry-run");
    args.xterm = g_command_line_params().get_value_as_bool("xterm");

    // Loop through all the arguments looking for "vogl_*".
    for (vogl::command_line_params::param_map_const_iterator param = g_command_line_params().begin();
         param != g_command_line_params().end();
         ++param)
    {
        const dynamic_string &first = param->first;

        // If this is a vogl command and it's not logfile / tracefile, add it to the vogl_cmdline.
        const dynamic_string prefix = param->first.get_clone().left(5);
        if (prefix == "vogl_" && (first != "vogl_logfile" && first != "vogl_tracefile"))
        {
            args.vogl_cmdline += " --" + first;
            for (uint32_t i = 0; i < param->second.m_values.size(); i++)
            {
                args.vogl_cmdline += " " + param->second.m_values[i];
            }
        }
    }

    // Check for -- or --args and add everything after to game_args.
    const dynamic_string& command_line = get_command_line();

    int args_index = command_line.find_left("-- ");
    if (args_index == -1)
        args_index = command_line.find_left("--args ");
    if (args_index != -1)
    {
        args_index = command_line.find_left(' ', args_index);
        if (args_index != -1)
        {
            args.game_args += command_line.get_clone().right(args_index + 1);
        }
    }

    bool is_steam_file = true;
    if (atoi(args.gameid.c_str()) == 0)
    {
        if (access(args.gameid.c_str(), F_OK))
            errorf(VOGL_FUNCTION_INFO_CSTR, "\nCould not find executable '%s'\n", args.gameid.c_str());

        char *filename = realpath(args.gameid.c_str(), NULL);
        if (filename)
        {
            // This is a local executable.
            is_steam_file = false;
            args.gameid = filename;
            free(filename);
        }
    }

    int steam_appid = is_steam_file ? atoi(args.gameid.c_str()) : -1;
    if (!steam_appid)
        errorf(VOGL_FUNCTION_INFO_CSTR, "ERROR: Could not find game number for %s\n", args.gameid.c_str());

    dynamic_string gameid_str;
    if (is_steam_file)
    {
        gameid_str = "appid" + args.gameid;
        vogl_printf("\nGame AppID: %d", steam_appid);

        const char *game_name = get_game_name(steam_appid);
        if (game_name)
        {
            dynamic_string game_name_str(cVarArg, "%s", game_name);
            vogl_printf(" (%s)", game_name_str.c_str());

            // Trim some characters that don't go well with filenames.
            game_name_str.replace(" ", "_");
            game_name_str.replace(":", "");
            game_name_str.replace("'", "");
            game_name_str.replace("!", "");
            game_name_str.replace("?", "");
            gameid_str += "_" + game_name_str;
        }

        vogl_printf("\n");
    }
    else
    {
        gameid_str = basename((char *)args.gameid.c_str());
        vogl_printf("\nGame: %s\n", args.gameid.c_str());
    }

    // If a tracefile / logfile wasn't specified, set em up.
    if (!args.vogl_tracefile.size() || !args.vogl_logfile.size())
    {
        char timestr[200];
        time_t t = time(NULL);

        timestr[0] = 0;
        struct tm *tmp = localtime(&t);
        if (tmp)
        {
            strftime(timestr, sizeof(timestr), "%Y_%m_%d-%H_%M_%S", tmp);
        }

        dynamic_string fname(cVarArg, "%s/vogltrace.%s.%s", P_tmpdir, gameid_str.c_str(), timestr);
        if (!args.vogl_tracefile.size())
            args.vogl_tracefile = fname + ".bin";
        if (!args.vogl_logfile.size())
            args.vogl_logfile = fname + ".log";
    }

    vogl_printf("\n");
    vogl_message_printf("Tracefile: %s\n", args.vogl_tracefile.c_str());
    vogl_message_printf("Logfile: %s", args.vogl_logfile.c_str());
    vogl_printf(" (will have PID appended)\n");

    dynamic_string vogltracepath32 = getfullpath("libvogltrace32.so");
    dynamic_string vogltracepath64 = getfullpath("libvogltrace64.so");

    // set up LD_PRELOAD string
    dynamic_string LD_PRELOAD = "LD_PRELOAD=\"";
    LD_PRELOAD += vogltracepath32 + ":" + vogltracepath64;

    if (is_steam_file || getenv("LD_PRELOAD"))
        LD_PRELOAD += ":$LD_PRELOAD";
    LD_PRELOAD += "\" ";
    vogl_printf("\n%s\n", LD_PRELOAD.c_str());

    // set up VOGL_CMD_LINE string
    dynamic_string VOGL_CMD_LINE = "VOGL_CMD_LINE=\"";
    VOGL_CMD_LINE += "--vogl_tracefile " + args.vogl_tracefile;
    VOGL_CMD_LINE += " --vogl_logfile " + args.vogl_logfile;
    VOGL_CMD_LINE += args.vogl_cmdline;
    VOGL_CMD_LINE += "\"";
    vogl_printf("\n%s\n", VOGL_CMD_LINE.c_str());

    dynamic_string xterm_str;
    if (args.xterm)
    {
        xterm_str = "xterm -geom 120x80+20+20";
        const char *env_user = getenv("USER");

        // If this is mikesart, specify using the Consolas font (which he likes).
        if (env_user && !strcmp(env_user, "mikesart"))
            xterm_str += " -fa Consolas -fs 10";

        // Add the xterm command part.
        xterm_str += " -e ";
    }

    if (is_steam_file)
    {
        // set up xterm string
        dynamic_string steam_cmd_str;

        steam_cmd_str = xterm_str + "%command% " + args.game_args;
        steam_cmd_str.trim();

        // set up steam string
        dynamic_string steam_str = "steam steam://run/" + args.gameid + "//";
        dynamic_string steam_args = VOGL_CMD_LINE + " " + LD_PRELOAD + steam_cmd_str;
        dynamic_string steam_fullcmd = steam_str + url_encode(steam_args.c_str());

        // Spew this whole mess out.
        vogl_printf("\nLaunch string:\n%s\n", (steam_str + steam_args).c_str());
        vogl_printf("\nURL encoded launch string:\n%s\n", steam_fullcmd.c_str());

        // And launch it...
        if (!args.dryrun)
            system(steam_fullcmd.c_str());
    }
    else
    {
        dynamic_string system_cmd;

        system_cmd = VOGL_CMD_LINE + " " + LD_PRELOAD + " " + xterm_str + args.gameid + " " + args.game_args;

        vogl_printf("\nlaunch string:\n%s\n", system_cmd.c_str());

        if (!args.dryrun)
            system(system_cmd.c_str());
    }

    return true;
}