feat: Tracy profiler 接入(CPU 帧时间线)

- vendored tracy 子模块;TRACY_ENABLE 全局生效,宏关闭时零开销
- 插桩:Application::Run FrameMark(帧边界)、Renderer::Render、
  SceneRenderer::BuildFrame(ZoneScopedN)+ GPUDriven Collect
  (ZoneNamedN——同作用域第二个 zone 不能用 ZoneScopedN,变量名
  固定会重声明)、Scene::UpdateTransforms
- 覆盖 CPU 侧关键路径:帧时间线 / 场景收集 / transform 重算 / 录制提交
- 用法:游戏运行时打开 Tracy GUI(release 下载)即自动连接(8086 端口)
This commit is contained in:
2026-09-23 16:10:46 +08:00
parent 7d137fa9b1
commit b6982d426f
9 changed files with 48 additions and 24 deletions
+3
View File
@@ -20,3 +20,6 @@
[submodule "Lib/VulkanMemoryAllocator"] [submodule "Lib/VulkanMemoryAllocator"]
path = Lib/VulkanMemoryAllocator path = Lib/VulkanMemoryAllocator
url = https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git url = https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git
[submodule "Lib/tracy"]
path = Lib/tracy
url = https://github.com/wolfpld/tracy.git
+1 -1
View File
@@ -48,7 +48,7 @@ protected:
// 模型资产(AssetManager 负责加载/缓存/生命周期,返回句柄) // 模型资产(AssetManager 负责加载/缓存/生命周期,返回句柄)
// SunTemple:FBX + DDS 压缩贴图(DdsLoader 验证场景) // SunTemple:FBX + DDS 压缩贴图(DdsLoader 验证场景)
const auto model = GetAssets().LoadModel("assets/models/backpack/backpack.obj"); const auto model = GetAssets().LoadModel("assets/models/viking_room/viking_room.obj");
const auto temple = GetAssets().LoadModel("assets/models/SunTemple/SunTemple.fbx"); const auto temple = GetAssets().LoadModel("assets/models/SunTemple/SunTemple.fbx");
m_Spinners.push_back(scene.CreateEntity("backpack")); m_Spinners.push_back(scene.CreateEntity("backpack"));
+9
View File
@@ -35,4 +35,13 @@ target_link_libraries(Engine PUBLIC
assimp::assimp assimp::assimp
) )
# Tracy(CPU/GPU 帧分析):宏关闭时全部退化空操作,零开销
set(TRACY_DIR ${CMAKE_SOURCE_DIR}/Lib/tracy)
target_include_directories(Engine PUBLIC ${TRACY_DIR}/public)
target_sources(Engine PRIVATE ${TRACY_DIR}/public/TracyClient.cpp)
target_compile_definitions(Engine PUBLIC TRACY_ENABLE)
find_package(Threads REQUIRED)
target_link_libraries(Engine PUBLIC Threads::Threads)
target_compile_definitions(Engine PRIVATE VULKAN_HPP_DISPATCH_LOADER_DYNAMIC=1) target_compile_definitions(Engine PRIVATE VULKAN_HPP_DISPATCH_LOADER_DYNAMIC=1)
+20 -23
View File
@@ -41,42 +41,39 @@ namespace Engine::ECS {
// 层级(父子变换)留给后续的层级同步系统。 // 层级(父子变换)留给后续的层级同步系统。
struct TransformComponent { struct TransformComponent {
// ---- 读取 ---- // ---- 读取 ----
const glm::vec3& GetPosition() const { return m_position; } const glm::vec3& GetPosition() const { return m_Position; }
const glm::vec3& GetRotation() const { return m_rotation; } // 欧拉角(度) const glm::vec3& GetRotation() const { return m_Rotation; } // 欧拉角(度)
const glm::vec3& GetScale() const { return m_scale; } const glm::vec3& GetScale() const { return m_Scale; }
const glm::mat4& World() const { return m_world; } // 要求已由 UpdateTransforms 计算 const glm::mat4& World() const { return m_World; } // 要求已由 UpdateTransforms 计算
// ---- 写入(标脏,脏实体由 UpdateTransforms 重算)---- // ---- 写入(标脏,脏实体由 UpdateTransforms 重算)----
TransformComponent& SetPosition(const glm::vec3& p) { if (m_position != p) { m_position = p; m_dirty = true; } return *this; } TransformComponent& SetPosition(const glm::vec3& p) { if (m_Position != p) { m_Position = p; m_Dirty = true; } return *this; }
TransformComponent& SetRotation(const glm::vec3& r) { if (m_rotation != r) { m_rotation = r; m_dirty = true; } return *this; } TransformComponent& SetRotation(const glm::vec3& r) { if (m_Rotation != r) { m_Rotation = r; m_Dirty = true; } return *this; }
TransformComponent& SetScale(const glm::vec3& s) { if (m_scale != s) { m_scale = s; m_dirty = true; } return *this; } TransformComponent& SetScale(const glm::vec3& s) { if (m_Scale != s) { m_Scale = s; m_Dirty = true; } return *this; }
// 便捷:原地修改单个欧拉角分量(度) bool IsDirty() const { return m_Dirty; }
TransformComponent& AddRotationY(f32 degY) { m_rotation.y += degY; m_dirty = true; return *this; }
bool IsDirty() const { return m_dirty; }
// SRT 分量 → world 矩阵(T * R * S),清除脏标记。 // SRT 分量 → world 矩阵(T * R * S),清除脏标记。
// 由 Scene::UpdateTransforms 调用(或层级系统),勿手动 // 由 Scene::UpdateTransforms 调用(或层级系统),勿手动
TransformComponent& Compose() TransformComponent& Compose()
{ {
const glm::mat4 t = glm::translate(glm::mat4(1.0f), m_position); const glm::mat4 t = glm::translate(glm::mat4(1.0f), m_Position);
const glm::mat4 r = const glm::mat4 r =
glm::rotate(glm::mat4(1.0f), glm::radians(m_rotation.y), glm::vec3(0, 1, 0)) * glm::rotate(glm::mat4(1.0f), glm::radians(m_Rotation.y), glm::vec3(0, 1, 0)) *
glm::rotate(glm::mat4(1.0f), glm::radians(m_rotation.x), glm::vec3(1, 0, 0)) * glm::rotate(glm::mat4(1.0f), glm::radians(m_Rotation.x), glm::vec3(1, 0, 0)) *
glm::rotate(glm::mat4(1.0f), glm::radians(m_rotation.z), glm::vec3(0, 0, 1)); glm::rotate(glm::mat4(1.0f), glm::radians(m_Rotation.z), glm::vec3(0, 0, 1));
const glm::mat4 s = glm::scale(glm::mat4(1.0f), m_scale); const glm::mat4 s = glm::scale(glm::mat4(1.0f), m_Scale);
m_world = t * r * s; m_World = t * r * s;
m_dirty = false; m_Dirty = false;
return *this; return *this;
} }
private: private:
glm::vec3 m_position{0.0f}; glm::vec3 m_Position{0.0f};
glm::vec3 m_rotation{0.0f}; glm::vec3 m_Rotation{0.0f};
glm::vec3 m_scale{1.0f}; glm::vec3 m_Scale{1.0f};
glm::mat4 m_world{1.0f}; glm::mat4 m_World{1.0f};
bool m_dirty = true; // 出生即脏:首次 UpdateTransforms 计算 world bool m_Dirty = true; // 出生即脏:首次 UpdateTransforms 计算 world
}; };
// 网格渲染体:引用共享的 Model 资产。 // 网格渲染体:引用共享的 Model 资产。
+3
View File
@@ -13,6 +13,8 @@
#include <imgui.h> #include <imgui.h>
#include <tracy/Tracy.hpp>
#include <algorithm> #include <algorithm>
#include <thread> #include <thread>
@@ -133,6 +135,7 @@ namespace Engine {
} }
} }
++m_FrameCount; ++m_FrameCount;
FrameMark; // Tracy:帧边界(一帧的时间线切分)
} }
OnShutdown(); OnShutdown();
+3
View File
@@ -6,6 +6,8 @@
#include <Engine/ECS/EntityHandle.h> #include <Engine/ECS/EntityHandle.h>
#include <Engine/Core/Log.h> #include <Engine/Core/Log.h>
#include <tracy/Tracy.hpp>
namespace Engine::ECS { namespace Engine::ECS {
EntityHandle Scene::CreateEntity(std::string name) EntityHandle Scene::CreateEntity(std::string name)
@@ -55,6 +57,7 @@ namespace Engine::ECS {
void Scene::UpdateTransforms() void Scene::UpdateTransforms()
{ {
ZoneScoped;
// 只重算脏的:UE transform-update 阶段模式。 // 只重算脏的:UE transform-update 阶段模式。
// 静止实体(绝大多数)零成本;层级传播在此扩展 // 静止实体(绝大多数)零成本;层级传播在此扩展
m_Registry.view<TransformComponent>().each([](TransformComponent& t) { m_Registry.view<TransformComponent>().each([](TransformComponent& t) {
+3
View File
@@ -33,6 +33,8 @@
#include <Engine/ECS/Scene.h> #include <Engine/ECS/Scene.h>
#include <Engine/Assets/AssetManager.h> #include <Engine/Assets/AssetManager.h>
#include <tracy/Tracy.hpp>
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <array> #include <array>
@@ -307,6 +309,7 @@ namespace Engine
void Renderer::Render(ECS::Scene& scene, Assets::AssetManager& assets) void Renderer::Render(ECS::Scene& scene, Assets::AssetManager& assets)
{ {
ZoneScoped; // CPU 侧:UBO/SSBO 上传 + 录制 + 提交(GPU 耗时见 RG timestamp)
if (m_Window.WasResized()) { if (m_Window.WasResized()) {
m_Window.ResetResizedFlag(); m_Window.ResetResizedFlag();
HandleResize(); HandleResize();
+5
View File
@@ -15,6 +15,8 @@
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/matrix_transform.hpp>
#include <tracy/Tracy.hpp>
#include <chrono> #include <chrono>
#include <limits> #include <limits>
@@ -129,6 +131,7 @@ namespace Engine
bool SceneRenderer::BuildFrame(ECS::Scene& scene, Assets::AssetManager& assets, bool SceneRenderer::BuildFrame(ECS::Scene& scene, Assets::AssetManager& assets,
vk::Extent2D targetExtent) vk::Extent2D targetExtent)
{ {
ZoneScopedN("BuildFrame");
const auto collectStart = std::chrono::steady_clock::now(); const auto collectStart = std::chrono::steady_clock::now();
// ---- 0. TAA 时域状态先行(velocity = 上一帧姿态与相机)---- // ---- 0. TAA 时域状态先行(velocity = 上一帧姿态与相机)----
@@ -188,6 +191,8 @@ namespace Engine
ubo.cameraPos = glm::vec4(camTransform->GetPosition(), 1.0f); ubo.cameraPos = glm::vec4(camTransform->GetPosition(), 1.0f);
// ---- 3. GPUDriven:单趟收集 + 多视图剔除 ---- // ---- 3. GPUDriven:单趟收集 + 多视图剔除 ----
// 同作用域第二个 zone:ZoneScopedN 变量名固定会重声明,用 ZoneNamedN
ZoneNamedN( ___tracy_collect, "GPUDriven Collect", true );
// 每个实例的包围球对 4 个视锥分别测试: // 每个实例的包围球对 4 个视锥分别测试:
// 相机视锥 → 主视图(Forward 画) // 相机视锥 → 主视图(Forward 画)
// 各级联光视锥 → 各自的阴影 batch(Shadow 按 region 各画各的) // 各级联光视锥 → 各自的阴影 batch(Shadow 按 region 各画各的)
Submodule
+1
Submodule Lib/tracy added at 81c5005509