Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions AGENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ xmake r -g test/* # for all groups

To build only a specific target group: `xmake build -g test/math`, `xmake build -g test/gfx`, etc.

### Test Artifacts

Save any test artifacts generated during agent runs under ./temp.

## Architecture Overview

### Module System
Expand Down Expand Up @@ -154,3 +158,4 @@ int main() {
- Vulkan backend works on Windows and Linux (Wayland).
- Runtime is set to `MD`/`MDd` (dynamic CRT) on Windows.
- Source files use UTF-8 encoding (`set_encodings("utf-8")`).

10 changes: 8 additions & 2 deletions hitagi/asset/material_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,17 @@ auto MaterialJSONParser::Parse(const core::Buffer& buffer) -> std::shared_ptr<Ma
desc.pipeline.assembly_state.primitive = json.at("pipeline").value("primitive", gfx::PrimitiveTopology::TriangleList);
if (bool enable_depth_test = json.at("pipeline").value("depth_test", true);
enable_depth_test) {
desc.pipeline.depth_stencil_format = gfx::Format::D32_FLOAT;
desc.pipeline.depth_stencil_state.depth_test_enable = true;
desc.pipeline.depth_stencil_format = gfx::Format::D32_FLOAT;
desc.pipeline.depth_stencil_state.depth_test_enable = true;
desc.pipeline.depth_stencil_state.depth_write_enable = true;
desc.pipeline.rasterization_state =
{
.cull_mode = gfx::CullMode::Back,
};
}
if (json.at("pipeline").value("double_sided", false)) {
desc.pipeline.rasterization_state.cull_mode = gfx::CullMode::None;
}

if (json.contains("parameters")) {
if (!json["parameters"].is_array()) {
Expand Down Expand Up @@ -130,6 +134,8 @@ auto MaterialJSONParser::Parse(const core::Buffer& buffer) -> std::shared_ptr<Ma
else if (type == "texture") {
if (param.contains("default"))
mat_param.value = std::make_shared<Texture>(param["default"]);
else
mat_param.value = std::shared_ptr<Texture>{};
} else {
logger->error("Unkown parameter type: {}", param["type"].get<std::string>());
return nullptr;
Expand Down
6 changes: 5 additions & 1 deletion hitagi/core/file_io_manager.cppm
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
module;

#include <tracy/Tracy.hpp>

export module core:file_io_manager;
import std;
import :runtime_module;
Expand All @@ -24,7 +28,7 @@ private:

using PathHash = std::size_t;

std::mutex m_CacheMutex;
TracyLockableN(std::mutex, m_CacheMutex, "FileIO Cache Mutex");
std::pmr::unordered_map<PathHash, std::filesystem::file_time_type> m_FileStateCache;
std::pmr::unordered_map<PathHash, Buffer> m_FileCache;
Buffer m_EmptyBuffer;
Expand Down
3 changes: 2 additions & 1 deletion hitagi/core/memory_manager.cppm
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
module;
#include <spdlog/logger.h>
#include <tracy/Tracy.hpp>

export module core:memory_manager;
import std;
Expand Down Expand Up @@ -63,7 +64,7 @@ private:
};

struct Pool {
std::mutex mutex{};
TracyLockableN(std::mutex, mutex, "MemoryPool Mutex");
std::list<Page> pages{};
Block* free_list = nullptr;
std::size_t page_size = 8_kB;
Expand Down
7 changes: 6 additions & 1 deletion hitagi/core/thread_manager.cpp
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
module;
#include <spdlog/logger.h>
#include <tracy/Tracy.hpp>

module core;

namespace hitagi::core {

ThreadManager::ThreadManager(std::uint8_t num_threads) : RuntimeModule("ThreadManager"), m_Stop(false) {
m_Logger->trace("create thread pool({})", num_threads);
TracyPlotConfig("Thread Tasks Pending", tracy::PlotFormatType::Number, true, true, 0);

for (std::uint8_t i = 0; i < num_threads; i++) {
m_ThreadPools.emplace_back([this] {
m_ThreadPools.emplace_back([this, i] {
const auto thread_name = std::format("Hitagi/Worker-{}", i);
tracy::SetThreadName(thread_name.c_str());
while (true) {
std::packaged_task<void()> task;
{
Expand All @@ -19,6 +23,7 @@ ThreadManager::ThreadManager(std::uint8_t num_threads) : RuntimeModule("ThreadMa
return;
task = std::move(m_Tasks.front());
m_Tasks.pop();
TracyPlot("Thread Tasks Pending", static_cast<std::int64_t>(m_Tasks.size()));
}
task();
}
Expand Down
11 changes: 11 additions & 0 deletions hitagi/core/thread_manager.cppm
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
module;

#include <tracy/Tracy.hpp>

export module core:thread_manager;
import std;
import :runtime_module;
Expand Down Expand Up @@ -25,6 +29,8 @@ private:
bool m_Stop;
};

auto CreateThreadManager(std::uint8_t num_threads = 8) -> std::unique_ptr<RuntimeModule>;

template <typename Func, typename... Args>
decltype(auto) ThreadManager::RunTask(Func&& func, Args&&... args) {
using return_type = std::invoke_result_t<Func, Args...>;
Expand All @@ -37,10 +43,15 @@ decltype(auto) ThreadManager::RunTask(Func&& func, Args&&... args) {
{
std::unique_lock lock(m_QueueMutex);
m_Tasks.emplace([task] { (*task)(); });
TracyPlot("Thread Tasks Pending", static_cast<std::int64_t>(m_Tasks.size()));
}

m_ConditionForTask.notify_one();
return res;
}

inline auto CreateThreadManager(std::uint8_t num_threads) -> std::unique_ptr<RuntimeModule> {
return std::make_unique<ThreadManager>(num_threads);
}

} // namespace hitagi::core
17 changes: 16 additions & 1 deletion hitagi/ecs/schedule.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module;
#include <taskflow/taskflow.hpp>
#include <spdlog/logger.h>
#include <tracy/Tracy.hpp>

module ecs;
import std;
Expand Down Expand Up @@ -42,7 +43,20 @@ void Schedule::Run(tf::Executor& executor) {
direct_graph[i] = {};

for (const auto& task : m_Tasks) {
tasks.emplace_back(taskflow.emplace([&]() { task->Run(world); }).name(task->name.data()));
tasks.emplace_back(taskflow.emplace([this, &executor, task]() {
thread_local bool tracy_thread_named = false;
if (!tracy_thread_named) {
if (const auto worker_id = executor.this_worker_id(); worker_id >= 0) {
const auto thread_name = std::format("Hitagi/ECS/{}/Worker-{}", world.GetName(), worker_id);
tracy::SetThreadName(thread_name.c_str());
tracy_thread_named = true;
}
}

ZoneScoped;
ZoneName(task->name.data(), task->name.size());
task->Run(world);
}).name(task->name.data()));
}

for (const auto& [component, task_indices] : m_ReadBeforeWriteSet) {
Expand Down Expand Up @@ -97,6 +111,7 @@ void Schedule::Run(tf::Executor& executor) {
return;
}

ZoneScopedN("ECSFrame");
executor.run(taskflow).wait();
}

Expand Down
2 changes: 2 additions & 0 deletions hitagi/ecs/world.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
module;
#include <spdlog/spdlog.h>
#include <tracy/Tracy.hpp>

module ecs;
import std;
Expand All @@ -14,6 +15,7 @@ World::World(std::string_view name)
}

void World::Update() {
ZoneScopedN("ECS::World::Update");
Schedule schedule(*this);
m_SystemManager.Update(schedule);
schedule.Run(m_Executor);
Expand Down
1 change: 1 addition & 0 deletions hitagi/ecs/world.cppm
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public:

void Update();

inline auto GetName() const noexcept -> std::string_view { return m_Name; }
inline auto& GetEntityManager() noexcept { return m_EntityManager; }
inline auto& GetSystemManager() noexcept { return m_SystemManager; }
inline auto& GetEntityManager() const noexcept { return m_EntityManager; }
Expand Down
13 changes: 11 additions & 2 deletions hitagi/engine/engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,15 @@ class OutLogicArea : public RuntimeModule {
};

Engine::Engine(const std::filesystem::path& config_path) : RuntimeModule("Engine") {
tracy::SetThreadName("Hitagi/Main");

auto add_inner_module = [&]<typename T>(std::unique_ptr<T> module) -> T* {
return static_cast<T*>(RuntimeModule::AddSubModule(std::unique_ptr<RuntimeModule>{module.release()}));
};

add_inner_module(std::make_unique<core::MemoryManager>());
add_inner_module(std::make_unique<core::FileIOManager>());
add_inner_module(std::make_unique<core::ThreadManager>());
add_inner_module(core::CreateThreadManager());

// Input
m_App = add_inner_module(Application::CreateApp(config_path)); // input manager is created here
Expand All @@ -56,6 +58,13 @@ void Engine::Tick() {
ZoneScopedN("Engine");
RuntimeModule::Tick();
m_Clock.Tick();

static bool tracy_plot_configured = false;
if (!tracy_plot_configured) {
TracyPlotConfig("CPU Frame Time (ms)", tracy::PlotFormatType::Number, false, true, 0);
tracy_plot_configured = true;
}
TracyPlot("CPU Frame Time (ms)", m_Clock.DeltaTime().count() * 1000.0);
FrameMark;
}

Expand All @@ -74,4 +83,4 @@ auto Engine::AddSubModule(std::unique_ptr<RuntimeModule> module, RuntimeModule*
return OutLogicArea::Get()->AddSubModule(std::move(module), after);
}

} // namespace hitagi
} // namespace hitagi
11 changes: 1 addition & 10 deletions hitagi/gfx/dx12/dx12_bindless.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,6 @@ auto DX12BindlessUtils::CreateBindlessHandle(GPUBuffer& buffer, std::size_t inde
descriptor_increment_size));
}

TracyAllocN((void*)handle.index, 1, "CBV_SRV_UAV_Bindless");
return handle;
}

Expand Down Expand Up @@ -204,7 +203,6 @@ auto DX12BindlessUtils::CreateBindlessHandle(Texture& texture, bool writable) ->
descriptor_increment_size));
}

TracyAllocN((void*)handle.index, 1, "CBV_SRV_UAV_Bindless");
return handle;
}

Expand All @@ -230,7 +228,6 @@ auto DX12BindlessUtils::CreateBindlessHandle(Sampler& sampler) -> BindlessHandle
handle.index,
descriptor_increment_size));

TracyAllocN((void*)handle.index, 1, "Sampler_Bindless");
return handle;
}

Expand All @@ -240,17 +237,11 @@ void DX12BindlessUtils::DiscardBindlessHandle(BindlessHandle handle) {
std::scoped_lock lock{m_Mutex};
auto& pool = handle.type == BindlessHandleType::Sampler ? m_Available_Sampler_BindlessHandlePool : m_Available_CBV_SRV_UAV_BindlessHandlePool;

if (handle.type == BindlessHandleType::Sampler) {
TracyFreeN((void*)handle.index, "Sampler_Bindless");
} else {
TracyFreeN((void*)handle.index, "CBV_SRV_UAV_Bindless");
}

handle.type = BindlessHandleType::Invalid;
handle.writable = 0;
handle.version++;

pool.emplace_back(handle);
}

} // namespace hitagi::gfx
} // namespace hitagi::gfx
5 changes: 3 additions & 2 deletions hitagi/gfx/dx12/dx12_bindless.cppm
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module;

#include <d3d12.h>
#include <tracy/Tracy.hpp>
#include <wrl.h>

export module gfx.dx12:bindless;
Expand Down Expand Up @@ -30,7 +31,7 @@ public:
inline auto GetBindlessRootSignature() const noexcept { return m_RootSignature; }

private:
std::mutex m_Mutex;
TracyLockableN(std::mutex, m_Mutex, "DX12 Bindless Mutex");

ComPtr<ID3D12RootSignature> m_RootSignature;

Expand All @@ -40,4 +41,4 @@ private:
std::pmr::deque<BindlessHandle> m_Available_CBV_SRV_UAV_BindlessHandlePool;
std::pmr::deque<BindlessHandle> m_Available_Sampler_BindlessHandlePool;
};
} // namespace hitagi::gfx
} // namespace hitagi::gfx
Loading
Loading