#pragma once #include #include #include #include namespace Slic3r { namespace GUI { // CPU and GPU time spent in the named sections of a frame, shown under the FPS overlay and averaged // by the scene benchmark. A section runs from the previous mark to the one naming it; its GPU time // leaves out any wait for the CPU to send its commands. GPU times are read back a few frames late, // so profiling never waits on the GPU. class FrameProfiler { public: struct Section { const char* name{ nullptr }; double cpu_ms{ 0.0 }; double gpu_ms{ 0.0 }; }; void begin_frame(); void mark(const char* name); void end_frame(); // The sections of the last frame read back, smoothed over the previous ones. const std::vector
& sections() const { return m_sections; } // Averages the sections of the frames begun from now on, until finish_averaging(). void start_averaging(); bool is_averaging() const { return m_averaging; } // With wait, first reads back the averaged frames still on the GPU, with the context current. std::vector
finish_averaging(bool wait); // Frees the queries, with the context current. void reset(); private: static constexpr size_t FRAMES_IN_FLIGHT = 4; static constexpr size_t MAX_SECTIONS = 32; struct Frame { // A begin and an end timestamp per section. std::array queries{}; std::array names{}; std::array cpu_ms{}; size_t count{ 0 }; bool pending{ false }; bool averaged{ false }; }; void collect(bool wait); std::array m_frames; Frame* m_recording{ nullptr }; size_t m_next{ 0 }; std::chrono::steady_clock::time_point m_last_mark; std::vector
m_sections; bool m_averaging{ false }; std::vector
m_sums; size_t m_averaged_frames{ 0 }; }; } // namespace GUI } // namespace Slic3r