From 867a1b031250ddb629783d802a67abb7314d9897 Mon Sep 17 00:00:00 2001 From: Egor Orachyov Date: Sat, 12 Oct 2024 14:57:51 +0300 Subject: [PATCH] gh-82: minor polishing --- .gitignore | 1 - .vscode/launch.json | 13 ++ .vscode/settings.json | 114 ++++++++++++ engine/runtime/core/task_manager.cpp | 4 + engine/runtime/core/task_manager.hpp | 1 + engine/runtime/grc/texture_manager.cpp | 34 ++-- engine/runtime/io/async_file_system.cpp | 3 +- engine/runtime/profiler/profiler_capture.cpp | 1 + engine/runtime/profiler/profiler_capture.hpp | 4 + engine/runtime/profiler/profiler_cpu.hpp | 8 + engine/runtime/profiler/profiler_gpu.cpp | 38 +++- engine/runtime/profiler/profiler_gpu.hpp | 15 +- engine/runtime/system/application.cpp | 184 ++----------------- engine/runtime/system/application.hpp | 10 +- engine/runtime/system/engine.cpp | 20 +- engine/runtime/system/game_application.cpp | 172 ++++++++++++++++- engine/runtime/system/game_application.hpp | 9 +- engine/runtime/system/hooks.cpp | 10 +- engine/runtime/system/hooks.hpp | 10 +- engine/runtime/system/plugin.hpp | 3 + engine/runtime/system/plugin_manager.cpp | 8 +- engine/runtime/system/plugin_manager.hpp | 9 +- template/main.cpp | 36 ++-- 23 files changed, 451 insertions(+), 256 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.gitignore b/.gitignore index daf359fe1..82f3f29cc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,5 @@ # IDE files /.idea -/.vscode # python cache files /**/__pycache__ diff --git a/.vscode/launch.json b/.vscode/launch.json index eea226eef..be2a17bfd 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -31,6 +31,19 @@ "cwd": "${workspaceRoot}/build-Release/template", "environment": [], "console": "integratedTerminal" + }, + { + "name": "template-debug (help)", + "type": "cppvsdbg", + "request": "launch", + "program": "${workspaceRoot}/build-Debug/template/template.exe", + "args": [ + "-h" + ], + "stopAtEntry": false, + "cwd": "${workspaceRoot}/build-Debug/template", + "environment": [], + "console": "integratedTerminal" } ] } \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..b8b9ac6c3 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,114 @@ +{ + "cmake.configureOnOpen": true, + "editor.formatOnSave": true, + "editor.formatOnPaste": false, + "files.associations": { + "vector": "cpp", + "cinttypes": "cpp", + "algorithm": "cpp", + "any": "cpp", + "array": "cpp", + "atomic": "cpp", + "bit": "cpp", + "bitset": "cpp", + "cctype": "cpp", + "charconv": "cpp", + "chrono": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "codecvt": "cpp", + "compare": "cpp", + "complex": "cpp", + "concepts": "cpp", + "condition_variable": "cpp", + "csignal": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "deque": "cpp", + "exception": "cpp", + "filesystem": "cpp", + "format": "cpp", + "forward_list": "cpp", + "fstream": "cpp", + "functional": "cpp", + "future": "cpp", + "initializer_list": "cpp", + "iomanip": "cpp", + "ios": "cpp", + "iosfwd": "cpp", + "iostream": "cpp", + "istream": "cpp", + "iterator": "cpp", + "limits": "cpp", + "list": "cpp", + "locale": "cpp", + "map": "cpp", + "memory": "cpp", + "mutex": "cpp", + "new": "cpp", + "numeric": "cpp", + "optional": "cpp", + "ostream": "cpp", + "queue": "cpp", + "random": "cpp", + "ratio": "cpp", + "regex": "cpp", + "set": "cpp", + "shared_mutex": "cpp", + "sstream": "cpp", + "stack": "cpp", + "stdexcept": "cpp", + "stop_token": "cpp", + "streambuf": "cpp", + "string": "cpp", + "system_error": "cpp", + "thread": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "typeinfo": "cpp", + "unordered_map": "cpp", + "unordered_set": "cpp", + "utility": "cpp", + "valarray": "cpp", + "variant": "cpp", + "xfacet": "cpp", + "xhash": "cpp", + "xiosbase": "cpp", + "xlocale": "cpp", + "xlocbuf": "cpp", + "xlocinfo": "cpp", + "xlocmes": "cpp", + "xlocmon": "cpp", + "xlocnum": "cpp", + "xloctime": "cpp", + "xmemory": "cpp", + "xstddef": "cpp", + "xstring": "cpp", + "xtr1common": "cpp", + "xtree": "cpp", + "xutility": "cpp", + "cassert": "cpp", + "debug": "cpp", + "typeindex": "cpp", + "**/*.asset": "yaml", + "**/*.shader": "yaml", + "*.moc": "cpp", + "coroutine": "cpp", + "resumable": "cpp" + }, + "[python]": { + "editor.defaultFormatter": "ms-python.black-formatter" + }, + "python.formatting.provider": "none", + "cmake.generator": "Ninja", + "cmake.buildArgs": [ + "-j 8" + ] +} \ No newline at end of file diff --git a/engine/runtime/core/task_manager.cpp b/engine/runtime/core/task_manager.cpp index 5af3010ec..2b9c3759f 100644 --- a/engine/runtime/core/task_manager.cpp +++ b/engine/runtime/core/task_manager.cpp @@ -80,6 +80,10 @@ namespace wmoge { void TaskManager::shutdown() { WG_PROFILE_CPU_CORE("TaskManager::shutdown"); + if (m_finished.load()) { + return; + } + WG_LOG_INFO("shutdown manager=" << m_worker_prefix << " and join already started tasks"); m_finished.store(true); diff --git a/engine/runtime/core/task_manager.hpp b/engine/runtime/core/task_manager.hpp index 076afd000..8d9a5bf7c 100644 --- a/engine/runtime/core/task_manager.hpp +++ b/engine/runtime/core/task_manager.hpp @@ -31,6 +31,7 @@ #include "core/string_id.hpp" #include "core/synchronization.hpp" +#include #include #include #include diff --git a/engine/runtime/grc/texture_manager.cpp b/engine/runtime/grc/texture_manager.cpp index 66273e161..66c6bd9fc 100644 --- a/engine/runtime/grc/texture_manager.cpp +++ b/engine/runtime/grc/texture_manager.cpp @@ -161,6 +161,7 @@ namespace wmoge { if (!m_need_upload_default) { return; } + m_need_upload_default = false; const std::array tex_colors[int(DefaultTexture::Total)] = { {0xff, 0xff, 0xff, 0xff}, @@ -172,15 +173,18 @@ namespace wmoge { }; auto cmd = m_gfx_driver->acquire_cmd_list(GfxQueueType::Graphics); - - for (int i = 0; i < int(DefaultTexture::Total); i++) { - cmd->barrier_image(m_default_textures[i], GfxTexBarrierType::Undefined, GfxTexBarrierType::CopyDestination); - cmd->update_texture_2d(m_default_textures[i], 0, Rect2i(0, 0, 1, 1), array_view(tex_colors[i].data(), sizeof(std::uint8_t[4]))); - cmd->barrier_image(m_default_textures[i], GfxTexBarrierType::CopyDestination, GfxTexBarrierType::Sampling); + WG_PROFILE_GPU_BEGIN(cmd); + { + WG_PROFILE_GPU_SCOPE(cmd, "TextureManager::upload_default_textures"); + + for (int i = 0; i < int(DefaultTexture::Total); i++) { + cmd->barrier_image(m_default_textures[i], GfxTexBarrierType::Undefined, GfxTexBarrierType::CopyDestination); + cmd->update_texture_2d(m_default_textures[i], 0, Rect2i(0, 0, 1, 1), array_view(tex_colors[i].data(), sizeof(std::uint8_t[4]))); + cmd->barrier_image(m_default_textures[i], GfxTexBarrierType::CopyDestination, GfxTexBarrierType::Sampling); + } } - + WG_PROFILE_GPU_END(cmd); m_gfx_driver->submit_cmd_list(cmd); - m_need_upload_default = false; } void TextureManager::init_textures() { @@ -213,16 +217,18 @@ namespace wmoge { } auto cmd = m_gfx_driver->acquire_cmd_list(GfxQueueType::Graphics); - WG_PROFILE_GPU_BEGIN(cmd.get()); + WG_PROFILE_GPU_BEGIN(cmd); + { + WG_PROFILE_GPU_SCOPE(cmd, "TextureManager::init_textures"); - cmd->barrier_images(for_barrier, GfxTexBarrierType::Undefined, GfxTexBarrierType::CopyDestination); - for (Texture* texture : for_upload) { - texture->upload_gfx_data(cmd); + cmd->barrier_images(for_barrier, GfxTexBarrierType::Undefined, GfxTexBarrierType::CopyDestination); + for (Texture* texture : for_upload) { + texture->upload_gfx_data(cmd); + } + cmd->barrier_images(for_barrier, GfxTexBarrierType::CopyDestination, GfxTexBarrierType::Sampling); } - cmd->barrier_images(for_barrier, GfxTexBarrierType::CopyDestination, GfxTexBarrierType::Sampling); - + WG_PROFILE_GPU_END(cmd); m_gfx_driver->submit_cmd_list(cmd); - WG_PROFILE_GPU_END(cmd.get()); WG_LOG_INFO("uploaded " << for_upload.size() << " textures to gpu"); } diff --git a/engine/runtime/io/async_file_system.cpp b/engine/runtime/io/async_file_system.cpp index e37fc77f8..168e922aa 100644 --- a/engine/runtime/io/async_file_system.cpp +++ b/engine/runtime/io/async_file_system.cpp @@ -38,8 +38,6 @@ namespace wmoge { } AsyncResult IoAsyncFileSystem::read_file(const std::string& filepath, BufferView buffer_view) { - WG_PROFILE_CPU_IO("IoAsyncFileSystem::read_file"); - AsyncOp async_result = make_async_op(); Task task(SID(filepath), [=](TaskContext&) -> int { @@ -49,6 +47,7 @@ namespace wmoge { WG_LOG_ERROR("failed open file " << filepath); return 1; } + WG_PROFILE_CPU_SCOPE_WITH_DESC(io, "IoAsyncFileSystem::read_file", filepath); if (!file->nread(buffer_view.data(), buffer_view.size())) { WG_LOG_ERROR("failed read file " << filepath); return 1; diff --git a/engine/runtime/profiler/profiler_capture.cpp b/engine/runtime/profiler/profiler_capture.cpp index 8ed586ad3..76807903c 100644 --- a/engine/runtime/profiler/profiler_capture.cpp +++ b/engine/runtime/profiler/profiler_capture.cpp @@ -67,6 +67,7 @@ namespace wmoge { m_session_name = session_name; m_session_path = filepath; m_events_cpu.clear(); + m_events_gpu.clear(); m_is_collecting.store(true); } diff --git a/engine/runtime/profiler/profiler_capture.hpp b/engine/runtime/profiler/profiler_capture.hpp index 041cda01d..6daaaa083 100644 --- a/engine/runtime/profiler/profiler_capture.hpp +++ b/engine/runtime/profiler/profiler_capture.hpp @@ -33,6 +33,10 @@ namespace wmoge { + /** + * @class ProfilerCapture + * @brief Allows to caprute cpu and gpu time profiling events and dump to a file + */ class ProfilerCapture { public: ProfilerCapture(class IocContainer* ioc); diff --git a/engine/runtime/profiler/profiler_cpu.hpp b/engine/runtime/profiler/profiler_cpu.hpp index 8cbdb042d..8863deff9 100644 --- a/engine/runtime/profiler/profiler_cpu.hpp +++ b/engine/runtime/profiler/profiler_cpu.hpp @@ -42,6 +42,7 @@ namespace wmoge { + /** @brief Cpu profiling mark */ struct ProfilerCpuMark { std::string name; Strid category; @@ -50,6 +51,7 @@ namespace wmoge { std::size_t line; }; + /** @brief Cpu profiling time event */ struct ProfilerCpuEvent { ProfilerCpuMark* mark = nullptr; std::string data; @@ -58,6 +60,10 @@ namespace wmoge { int thread_id = -1; }; + /** + * @class ProfilerCpu + * @brief Collects cpu time events for application from different threads + */ class ProfilerCpu { public: Signal on_event; @@ -82,6 +88,7 @@ namespace wmoge { static ProfilerCpu* g_profiler_cpu; }; + /** @brief Cpu profiling scope for single event */ struct ProfilerCpuScope { ProfilerCpuScope(ProfilerCpuMark& mark, const std::string& data) { ProfilerCpu::instance()->begin_event(&mark, data); } ~ProfilerCpuScope() { ProfilerCpu::instance()->end_event(); } @@ -126,3 +133,4 @@ namespace wmoge { #define WG_PROFILE_CPU_OPENAL(label) WG_PROFILE_CPU_SCOPE(openal, label) #define WG_PROFILE_CPU_SYSTEM(label) WG_PROFILE_CPU_SCOPE(system, label) #define WG_PROFILE_CPU_PLUGIN(label) WG_PROFILE_CPU_SCOPE(plugin, label) +#define WG_PROFILE_CPU_GPU(label) WG_PROFILE_CPU_SCOPE(gpu, label) diff --git a/engine/runtime/profiler/profiler_gpu.cpp b/engine/runtime/profiler/profiler_gpu.cpp index af7891be1..e56d6ecda 100644 --- a/engine/runtime/profiler/profiler_gpu.cpp +++ b/engine/runtime/profiler/profiler_gpu.cpp @@ -28,15 +28,16 @@ #include "profiler_gpu.hpp" #include "gfx/gfx_driver.hpp" +#include "profiler/profiler_cpu.hpp" #include namespace wmoge { ProfilerGpu::ProfilerGpu() { - m_queue_names.push_back("gfx-graphichs"); - m_queue_names.push_back("gfx-compute"); - m_queue_names.push_back("gfx-copy"); + m_queue_names.push_back("queue-graphichs"); + m_queue_names.push_back("queue-compute"); + m_queue_names.push_back("queue-copy"); } void ProfilerGpu::setup(GfxDriver* driver) { @@ -48,14 +49,18 @@ namespace wmoge { } void ProfilerGpu::calibrate(std::chrono::steady_clock::time_point time) { + WG_PROFILE_CPU_GPU("ProfilerGpu::calibrate"); std::chrono::steady_clock::time_point cpu_now = std::chrono::steady_clock::now(); m_driver->query_callibration(m_gpu_time, m_gpu_freq_ns); m_cpu_time = std::chrono::duration_cast(cpu_now - time).count(); } - void ProfilerGpu::prepare_cmd_list(GfxCmdList* cmd_list) { + void ProfilerGpu::prepare_cmd_list(const GfxCmdListRef& cmd_list) { + WG_PROFILE_CPU_GPU("ProfilerGpu::prepare_cmd_list"); if (!m_is_enabled) { return; } + assert(cmd_list); + if (m_query_pools.empty()) { GfxQueryPoolDesc desc; desc.size = m_events_limit; @@ -66,19 +71,22 @@ namespace wmoge { GfxQueryPoolRef pool = m_query_pools.back(); m_query_pools.pop_back(); - CmdListData& data = m_cmd_lists[cmd_list]; + CmdListData& data = m_cmd_lists[cmd_list.get()]; data.queue_type = cmd_list->get_queue_type(); data.query_pool = pool; cmd_list->reset_pool(data.query_pool, m_events_limit); } - void ProfilerGpu::finish_cmd_list(GfxCmdList* cmd_list) { + void ProfilerGpu::finish_cmd_list(const GfxCmdListRef& cmd_list) { + WG_PROFILE_CPU_GPU("ProfilerGpu::finish_cmd_list"); if (!m_is_enabled) { return; } + assert(cmd_list); + std::size_t idx = m_driver->frame_number() % GfxLimits::FRAMES_IN_FLIGHT; - m_cmd_to_resolve[idx].emplace_back(std::move(m_cmd_lists[cmd_list])); - m_cmd_lists.erase(cmd_list); + m_cmd_to_resolve[idx].emplace_back(std::move(m_cmd_lists[cmd_list.get()])); + m_cmd_lists.erase(cmd_list.get()); } void ProfilerGpu::begin_event(ProfilerGpuMark* mark, const std::string& data, GfxCmdList* cmd_list) { @@ -110,12 +118,14 @@ namespace wmoge { } void ProfilerGpu::resolve() { + WG_PROFILE_CPU_GPU("ProfilerGpu::resolve"); + auto convert_timestamp = [&](std::uint64_t t) { assert(t >= m_gpu_time); return m_cpu_time + ((t - m_gpu_time) * m_gpu_freq_ns) / 1000; }; - std::size_t idx = (m_driver->frame_number() + 1) % GfxLimits::FRAMES_IN_FLIGHT; + const std::size_t idx = (m_driver->frame_number() + 1) % GfxLimits::FRAMES_IN_FLIGHT; for (CmdListData& data : m_cmd_to_resolve[idx]) { std::vector timestamps(data.next_query_idx); @@ -131,6 +141,8 @@ namespace wmoge { on_event.emit(out_event); } + + m_query_pools.emplace_back(std::move(data.query_pool)); } m_cmd_to_resolve[idx].clear(); @@ -140,6 +152,14 @@ namespace wmoge { names = m_queue_names; } + void ProfilerGpu::clear() { + m_query_pools.clear(); + + for (int i = 0; i < GfxLimits::FRAMES_IN_FLIGHT; i++) { + m_cmd_to_resolve[i].clear(); + } + } + ProfilerGpu g_profiler_gpu_default; ProfilerGpu* ProfilerGpu::g_profiler_gpu = &g_profiler_gpu_default; diff --git a/engine/runtime/profiler/profiler_gpu.hpp b/engine/runtime/profiler/profiler_gpu.hpp index 66f731a19..f76b27ef7 100644 --- a/engine/runtime/profiler/profiler_gpu.hpp +++ b/engine/runtime/profiler/profiler_gpu.hpp @@ -44,6 +44,7 @@ namespace wmoge { + /** @brief Gpu profiling mark */ struct ProfilerGpuMark { std::string name; Strid category; @@ -52,6 +53,7 @@ namespace wmoge { std::size_t line; }; + /** @brief Gpu time event */ struct ProfilerGpuEvent { ProfilerGpuMark* mark = nullptr; std::string data; @@ -60,6 +62,10 @@ namespace wmoge { int queue_id = -1; }; + /** + * @class ProfilerGpu + * @brief Collects gpu profiling time events from gfx command lists + */ class ProfilerGpu { public: Signal on_event; @@ -69,12 +75,13 @@ namespace wmoge { void setup(class GfxDriver* driver); void enable(bool enable); void calibrate(std::chrono::steady_clock::time_point time); - void prepare_cmd_list(GfxCmdList* cmd_list); - void finish_cmd_list(GfxCmdList* cmd_list); + void prepare_cmd_list(const GfxCmdListRef& cmd_list); + void finish_cmd_list(const GfxCmdListRef& cmd_list); void begin_event(ProfilerGpuMark* mark, const std::string& data, GfxCmdList* cmd_list); void end_event(GfxCmdList* cmd_list); void resolve(); void get_queue_names(std::vector& names); + void clear(); static ProfilerGpu* instance(); @@ -110,8 +117,10 @@ namespace wmoge { static ProfilerGpu* g_profiler_gpu; }; + /** @brief Gpu profiling scope for single event */ struct ProfilerGpuScope { ProfilerGpuScope(ProfilerGpuMark& mark, const std::string& data, GfxCmdList* cmd_list) : cmd_list(cmd_list) { ProfilerGpu::instance()->begin_event(&mark, data, cmd_list); } + ProfilerGpuScope(ProfilerGpuMark& mark, const std::string& data, const GfxCmdListRef& cmd_list) : ProfilerGpuScope(mark, data, cmd_list.get()) {} ~ProfilerGpuScope() { ProfilerGpu::instance()->end_event(cmd_list); } GfxCmdList* cmd_list; @@ -135,4 +144,4 @@ namespace wmoge { ProfilerGpuScope __wg_auto_scope_gpu(__wg_auto_mark_gpu, desc, cmd_list) #define WG_PROFILE_GPU_SCOPE(cmd_list, name) \ - WG_PROFILE_GPU_SCOPE_WITH_DESC(cmd_list, gfx, name, "") \ No newline at end of file + WG_PROFILE_GPU_SCOPE_WITH_DESC(cmd_list, gpudevice, name, "") \ No newline at end of file diff --git a/engine/runtime/system/application.cpp b/engine/runtime/system/application.cpp index dd2578b75..ef9a79df6 100644 --- a/engine/runtime/system/application.cpp +++ b/engine/runtime/system/application.cpp @@ -27,186 +27,26 @@ #include "application.hpp" -#include "asset/asset_manager.hpp" -#include "audio/openal/al_engine.hpp" -#include "core/callback_queue.hpp" -#include "core/class.hpp" -#include "core/cmd_line.hpp" -#include "core/ioc_container.hpp" -#include "core/log.hpp" -#include "core/task_manager.hpp" -#include "ecs/ecs_registry.hpp" -#include "gfx/vulkan/vk_driver.hpp" -#include "glsl/glsl_shader_compiler.hpp" -#include "grc/pso_cache.hpp" -#include "grc/shader_compiler.hpp" -#include "grc/shader_library.hpp" -#include "grc/shader_manager.hpp" -#include "grc/texture_manager.hpp" -#include "io/async_file_system.hpp" -#include "io/enum.hpp" -#include "mesh/mesh_manager.hpp" -#include "platform/dll_manager.hpp" -#include "platform/file_system.hpp" -#include "platform/glfw/glfw_window_manager.hpp" -#include "platform/input.hpp" -#include "platform/time.hpp" -#include "platform/window_manager.hpp" -#include "profiler/profiler_capture.hpp" #include "profiler/profiler_cpu.hpp" -#include "render/render_engine.hpp" -#include "render/view_manager.hpp" -#include "rtti/type_storage.hpp" -#include "scene/scene_manager.hpp" -#include "system/config.hpp" -#include "system/console.hpp" -#include "system/engine.hpp" -#include "system/plugin_manager.hpp" - -#include "asset/_rtti.hpp" -#include "audio/_rtti.hpp" -#include "glsl/_rtti.hpp" -#include "grc/_rtti.hpp" -#include "material/_rtti.hpp" -#include "mesh/_rtti.hpp" -#include "pfx/_rtti.hpp" -#include "render/_rtti.hpp" -#include "rtti/_rtti.hpp" -#include "scene/_rtti.hpp" -#include "system/_rtti.hpp" namespace wmoge { - static void bind_globals(IocContainer* ioc) { - ioc->bind_by_pointer(Log::instance()); - ioc->bind_by_ioc(); - ioc->bind_by_pointer(RttiTypeStorage::instance()); - ioc->bind_by_ioc(); - ioc->bind(); - ioc->bind