refactor: split debug module into preliminary and tracer

This commit is contained in:
light7734 2026-01-20 10:43:26 +03:30
parent 20f62433f9
commit f7ada66c5c
26 changed files with 281 additions and 210 deletions

View file

@ -1,6 +1,7 @@
add_module(NAME preliminary INTERFACES module.cppm fundumental_types.cppm) add_module(NAME preliminary INTERFACES module.cppm fundumental_types.cppm assertions.cppm build_constants.cppm)
add_module(NAME logger INTERFACES logger.cppm TESTS logger.test.cpp DEPENDENCIES preliminary) add_module(NAME logger INTERFACES logger.cppm TESTS logger.test.cpp DEPENDENCIES preliminary)
add_module(NAME tracer INTERFACES tracer.cppm DEPENDENCIES preliminary logger)
add_module(NAME bitwise INTERFACES operations.cppm DEPENDENCIES preliminary) add_module(NAME bitwise INTERFACES operations.cppm DEPENDENCIES preliminary)
add_module(NAME env INTERFACES constants.cppm DEPENDENCIES preliminary) add_module(NAME env INTERFACES constants.cppm DEPENDENCIES preliminary)
add_module(NAME memory INTERFACES null_on_move.cppm reference.cppm scope.cppm add_module(NAME memory INTERFACES null_on_move.cppm reference.cppm scope.cppm
@ -26,19 +27,6 @@ add_module(
test.test.cpp test.test.cpp
) )
add_module(
NAME
lt_debug
ROOT_DIR
${CMAKE_CURRENT_SOURCE_DIR}/debug
INTERFACES
instrumentor.cppm
assertions.cppm
DEPENDENCIES
preliminary
logger
)
add_module( add_module(
NAME NAME
math math
@ -52,7 +40,6 @@ add_module(
components.cppm components.cppm
DEPENDENCIES DEPENDENCIES
preliminary preliminary
lt_debug
) )
add_module( add_module(
@ -64,7 +51,6 @@ add_module(
DEPENDENCIES DEPENDENCIES
preliminary preliminary
logger logger
lt_debug
TESTS TESTS
shader.test.cpp shader.test.cpp
) )
@ -82,7 +68,6 @@ add_module(
preliminary preliminary
assets assets
logger logger
lt_debug
) )
# add_executable(asset_baker entrypoint.cpp) target_link_libraries(asset_baker # add_executable(asset_baker entrypoint.cpp) target_link_libraries(asset_baker
@ -100,7 +85,6 @@ add_module(
preliminary preliminary
memory memory
PRIVATE_DEPENDENCIES PRIVATE_DEPENDENCIES
lt_debug
) )
add_module( add_module(
@ -112,7 +96,6 @@ add_module(
entity.cppm entity.cppm
DEPENDENCIES DEPENDENCIES
logger logger
lt_debug
memory memory
TESTS TESTS
registry.test.cpp registry.test.cpp
@ -140,7 +123,6 @@ if(WIN32)
input_codes input_codes
PRIVATE_DEPENDENCIES PRIVATE_DEPENDENCIES
logger logger
lt_debug
time time
TESTS TESTS
system.test.cpp system.test.cpp
@ -167,7 +149,6 @@ elseif(UNIX)
PRIVATE_DEPENDENCIES PRIVATE_DEPENDENCIES
X11 X11
logger logger
lt_debug
time time
TESTS TESTS
system.test.cpp system.test.cpp

View file

@ -1,7 +1,6 @@
export module bakers; export module bakers;
import preliminary; import preliminary;
import debug.assertions;
import assets.metadata; import assets.metadata;
import assets.shader; import assets.shader;
import logger; import logger;
@ -37,7 +36,7 @@ export void bake_shader(
); );
auto stream = std::ifstream(spv_path, std::ios::binary); auto stream = std::ifstream(spv_path, std::ios::binary);
lt::debug::ensure( ensure(
stream.is_open(), stream.is_open(),
"Failed to open compiled {} shader at: {}", "Failed to open compiled {} shader at: {}",
type == vertex ? "vert" : "frag", type == vertex ? "vert" : "frag",

View file

@ -3,7 +3,6 @@ export module assets.shader;
import preliminary; import preliminary;
import assets.metadata; import assets.metadata;
import logger; import logger;
import debug.assertions;
export namespace lt::assets { export namespace lt::assets {
@ -55,7 +54,7 @@ public:
[[nodiscard]] auto get_blob_metadata(BlobTag tag) const -> const BlobMetadata & [[nodiscard]] auto get_blob_metadata(BlobTag tag) const -> const BlobMetadata &
{ {
debug::ensure( ensure(
tag == BlobTag::code, tag == BlobTag::code,
"Invalid blob tag for shader asset: {}", "Invalid blob tag for shader asset: {}",
std::to_underlying(tag) std::to_underlying(tag)
@ -92,14 +91,14 @@ constexpr auto total_metadata_size = //
ShaderAsset::ShaderAsset(const std::filesystem::path &path) ShaderAsset::ShaderAsset(const std::filesystem::path &path)
: m_stream(path, std::ios::beg | std::ios::binary) : m_stream(path, std::ios::beg | std::ios::binary)
{ {
debug::ensure(m_stream.is_open(), "Failed to open shader asset at: {}", path.string()); ensure(m_stream.is_open(), "Failed to open shader asset at: {}", path.string());
const auto read = [this](auto &field) { const auto read = [this](auto &field) {
m_stream.read(std::bit_cast<char *>(&field), sizeof(field)); m_stream.read(std::bit_cast<char *>(&field), sizeof(field));
}; };
m_stream.seekg(0, std::ifstream::end); m_stream.seekg(0, std::ifstream::end);
const auto file_size = static_cast<size_t>(m_stream.tellg()); const auto file_size = static_cast<size_t>(m_stream.tellg());
debug::ensure( ensure(
file_size > total_metadata_size, file_size > total_metadata_size,
"Failed to open shader asset at: {}, file smaller than metadata: {} < {}", "Failed to open shader asset at: {}, file smaller than metadata: {} < {}",
path.string(), path.string(),
@ -118,7 +117,7 @@ ShaderAsset::ShaderAsset(const std::filesystem::path &path)
read(m_code_blob_metadata.compressed_size); read(m_code_blob_metadata.compressed_size);
read(m_code_blob_metadata.uncompressed_size); read(m_code_blob_metadata.uncompressed_size);
debug::ensure( ensure(
m_asset_metadata.type == asset_type_identifier, m_asset_metadata.type == asset_type_identifier,
"Failed to open shader asset at: {}, incorrect asset type: {} != {}", "Failed to open shader asset at: {}, incorrect asset type: {} != {}",
path.string(), path.string(),
@ -126,7 +125,7 @@ ShaderAsset::ShaderAsset(const std::filesystem::path &path)
asset_type_identifier asset_type_identifier
); );
debug::ensure( ensure(
m_asset_metadata.version == current_version, m_asset_metadata.version == current_version,
"Failed to open shader asset at: {}, version mismatch: {} != {}", "Failed to open shader asset at: {}, version mismatch: {} != {}",
path.string(), path.string(),
@ -134,21 +133,21 @@ ShaderAsset::ShaderAsset(const std::filesystem::path &path)
current_version current_version
); );
debug::ensure( ensure(
std::to_underlying(m_metadata.type) <= std::to_underlying(Type::compute), std::to_underlying(m_metadata.type) <= std::to_underlying(Type::compute),
"Failed to open shader asset at: {}, invalid shader type: {}", "Failed to open shader asset at: {}, invalid shader type: {}",
path.string(), path.string(),
std::to_underlying(m_metadata.type) std::to_underlying(m_metadata.type)
); );
debug::ensure( ensure(
m_code_blob_metadata.tag == std::to_underlying(BlobTag::code), m_code_blob_metadata.tag == std::to_underlying(BlobTag::code),
"Failed to open shader asset at: {}, invalid blob tag: {}", "Failed to open shader asset at: {}, invalid blob tag: {}",
path.string(), path.string(),
m_code_blob_metadata.tag m_code_blob_metadata.tag
); );
debug::ensure( ensure(
m_code_blob_metadata.offset + m_code_blob_metadata.compressed_size <= file_size, m_code_blob_metadata.offset + m_code_blob_metadata.compressed_size <= file_size,
"Failed to open shader asset at: {}, file smaller than blob: {} > {} + {}", "Failed to open shader asset at: {}, file smaller than blob: {} > {} + {}",
path.string(), path.string(),
@ -178,7 +177,7 @@ ShaderAsset::ShaderAsset(const std::filesystem::path &path)
.uncompressed_size = code_blob.size(), .uncompressed_size = code_blob.size(),
}; };
debug::ensure(stream.is_open(), "Failed to pack shader asset to {}", destination.string()); ensure(stream.is_open(), "Failed to pack shader asset to {}", destination.string());
const auto write = [&stream](auto &field) { const auto write = [&stream](auto &field) {
stream.write(std::bit_cast<char *>(&field), sizeof(field)); stream.write(std::bit_cast<char *>(&field), sizeof(field));
}; };
@ -195,13 +194,9 @@ ShaderAsset::ShaderAsset(const std::filesystem::path &path)
void ShaderAsset::unpack_to(BlobTag tag, std::span<byte> destination) const void ShaderAsset::unpack_to(BlobTag tag, std::span<byte> destination) const
{ {
debug::ensure( ensure(tag == BlobTag::code, "Invalid blob tag for shader asset: {}", std::to_underlying(tag));
tag == BlobTag::code,
"Invalid blob tag for shader asset: {}",
std::to_underlying(tag)
);
debug::ensure( ensure(
destination.size() >= m_code_blob_metadata.uncompressed_size, destination.size() >= m_code_blob_metadata.uncompressed_size,
"Failed to unpack shader blob {} to destination ({}) of size {} since it's smaller " "Failed to unpack shader blob {} to destination ({}) of size {} since it's smaller "
"than the blobl's uncompressed size: {}", "than the blobl's uncompressed size: {}",
@ -220,11 +215,7 @@ void ShaderAsset::unpack_to(BlobTag tag, std::span<byte> destination) const
[[nodiscard]] auto ShaderAsset::unpack(BlobTag tag) const -> Blob [[nodiscard]] auto ShaderAsset::unpack(BlobTag tag) const -> Blob
{ {
debug::ensure( ensure(tag == BlobTag::code, "Invalid blob tag for shader asset: {}", std::to_underlying(tag));
tag == BlobTag::code,
"Invalid blob tag for shader asset: {}",
std::to_underlying(tag)
);
auto blob = Blob(m_code_blob_metadata.uncompressed_size); auto blob = Blob(m_code_blob_metadata.uncompressed_size);
unpack_to(tag, blob); unpack_to(tag, blob);

View file

@ -1,47 +0,0 @@
export module debug.assertions;
import std;
namespace lt::debug {
///////////////////////////////////////
// ----------* INTERFACE *--------- //
/////////////////////////////////////
export template<typename Expression_T, typename... Args_T>
struct ensure
{
ensure(
const Expression_T &expression,
std::format_string<Args_T...> fmt,
Args_T &&...args,
const std::source_location &location = std::source_location::current()
);
};
export template<typename Expression_T, typename... Args_T>
ensure(Expression_T, std::format_string<Args_T...>, Args_T &&...)
-> ensure<Expression_T, Args_T...>;
///////////////////////////////////////
// * IMPLEMENTATION -- TEMPLATES * //
/////////////////////////////////////
template<typename Expression_T, typename... Args_T>
ensure<Expression_T, Args_T...>::ensure(
const Expression_T &expression,
std::format_string<Args_T...> fmt,
Args_T &&...args,
const std::source_location &location
)
{
if (!static_cast<bool>(expression))
{
throw std::runtime_error { std::format(
"exception: {}\nlocation: {}:{}",
std::format(fmt, std::forward<Args_T>(args)...),
location.file_name(),
location.line()
) };
}
}
} // namespace lt::debug

View file

@ -1,7 +1,6 @@
export module ecs.entity; export module ecs.entity;
import preliminary; import preliminary;
import debug.assertions;
import memory.reference; import memory.reference;
import ecs.registry; import ecs.registry;
@ -15,7 +14,7 @@ public:
: m_registry(std::move(registry)) : m_registry(std::move(registry))
, m_identifier(identifier) , m_identifier(identifier)
{ {
debug::ensure(m_registry, "Failed to create Entity ({}): null registry", m_identifier); ensure(m_registry, "Failed to create Entity ({}): null registry", m_identifier);
} }
template<typename Component_T> template<typename Component_T>

View file

@ -1,7 +1,6 @@
export module ecs.registry; export module ecs.registry;
import preliminary; import preliminary;
import debug.assertions;
import ecs.sparse_set; import ecs.sparse_set;
import memory.scope; import memory.scope;
@ -243,7 +242,7 @@ private:
auto *base_set = m_sparsed_sets[type_id].get(); auto *base_set = m_sparsed_sets[type_id].get();
auto *derived_set = dynamic_cast<SparseSet<T, EntityId> *>(base_set); auto *derived_set = dynamic_cast<SparseSet<T, EntityId> *>(base_set);
debug::ensure(derived_set, "Failed to downcast to derived set"); ensure(derived_set, "Failed to downcast to derived set");
return *derived_set; return *derived_set;
} }

View file

@ -1,7 +1,6 @@
export module ecs.sparse_set; export module ecs.sparse_set;
import preliminary; import preliminary;
import debug.assertions;
export namespace lt::ecs { export namespace lt::ecs {
@ -39,7 +38,7 @@ public:
explicit SparseSet(size_t initial_capacity = 1) explicit SparseSet(size_t initial_capacity = 1)
{ {
debug::ensure( ensure(
initial_capacity <= max_capacity, initial_capacity <= max_capacity,
"Failed to create SparseSet: capacity too large ({} > {})", "Failed to create SparseSet: capacity too large ({} > {})",
initial_capacity, initial_capacity,

View file

@ -2,7 +2,6 @@ export module input.system;
export import :components; export import :components;
import logger; import logger;
import app.system; import app.system;
import debug.assertions;
import ecs.registry; import ecs.registry;
import memory.reference; import memory.reference;
import surface.system; import surface.system;
@ -69,7 +68,7 @@ struct overloads: Ts...
System::System(memory::Ref<ecs::Registry> registry): m_registry(std::move(registry)) System::System(memory::Ref<ecs::Registry> registry): m_registry(std::move(registry))
{ {
debug::ensure(m_registry, "Failed to initialize input system: null registry"); ensure(m_registry, "Failed to initialize input system: null registry");
} }
void System::tick(app::TickInfo tick) void System::tick(app::TickInfo tick)

View file

@ -3,7 +3,6 @@ export module math.vec4;
import preliminary; import preliminary;
import math.vec2; import math.vec2;
import math.vec3; import math.vec3;
import debug.assertions;
namespace lt::math { namespace lt::math {
@ -47,14 +46,14 @@ struct vec4_impl
[[nodiscard]] constexpr auto operator[](u8 idx) -> T & [[nodiscard]] constexpr auto operator[](u8 idx) -> T &
{ {
// TODO(Light): Use contract // TODO(Light): Use contract
debug::ensure(idx <= num_elements, "vec4 out of bound: {}", idx); ensure(idx <= num_elements, "vec4 out of bound: {}", idx);
return ((T *)this)[idx]; return ((T *)this)[idx];
} }
[[nodiscard]] constexpr auto operator[](u8 idx) const -> const T & [[nodiscard]] constexpr auto operator[](u8 idx) const -> const T &
{ {
// TODO(Light): Use contract // TODO(Light): Use contract
debug::ensure(idx < num_elements, "vec4 out of bound: {}", idx); ensure(idx < num_elements, "vec4 out of bound: {}", idx);
return ((T *)this)[idx]; return ((T *)this)[idx];
} }

View file

@ -9,7 +9,7 @@ namespace lt::memory {
/** Holds an `Underlying_T`, assigns it to `null_value` when this object is moved. /** Holds an `Underlying_T`, assigns it to `null_value` when this object is moved.
* *
* @note For avoiding the need to explicitly implement the move constructor for objects that hold * @note For avoiding the need to explicitly implement the move constructor for objects that hold
* Vulkan handles. But may serve other purposes, hence why I kept the implementation generic. * non-raii-handles (eg. Vulkan, Wayland).
*/ */
export template<typename Underlying_T, Underlying_T null_value = nullptr> export template<typename Underlying_T, Underlying_T null_value = nullptr>
class NullOnMove class NullOnMove
@ -81,11 +81,6 @@ public:
return m_value; return m_value;
} }
operator u64() const
{
return (u64)m_value;
}
[[nodiscard]] auto get() -> Underlying_T & [[nodiscard]] auto get() -> Underlying_T &
{ {
return m_value; return m_value;

View file

@ -0,0 +1,85 @@
export module preliminary.assertions;
import preliminary.build_constants;
import std;
///////////////////////////////////////
// ----------* INTERFACE *--------- //
/////////////////////////////////////
/** To be used for ensuring a condition holds true, throws otherwise. */
export template<typename Expression_T, typename... Args_T>
struct ensure
{
ensure(
const Expression_T &expression,
std::format_string<Args_T...> fmt,
Args_T &&...args,
const std::source_location &location = std::source_location::current()
);
};
/** To be used for costly checks that should be stripped in release builds. */
export template<typename Expression_T, typename... Args_T>
struct debug_check
{
debug_check(
const Expression_T &expression,
std::format_string<Args_T...> fmt,
Args_T &&...args,
const std::source_location &location = std::source_location::current()
);
};
export template<typename Expression_T, typename... Args_T>
ensure(Expression_T, std::format_string<Args_T...>, Args_T &&...)
-> ensure<Expression_T, Args_T...>;
export template<typename Expression_T, typename... Args_T>
debug_check(Expression_T, std::format_string<Args_T...>, Args_T &&...)
-> debug_check<Expression_T, Args_T...>;
///////////////////////////////////////
// * IMPLEMENTATION -- TEMPLATES * //
/////////////////////////////////////
template<typename Expression_T, typename... Args_T>
ensure<Expression_T, Args_T...>::ensure(
const Expression_T &expression,
std::format_string<Args_T...> fmt,
Args_T &&...args,
const std::source_location &location
)
{
if (!static_cast<bool>(expression))
{
throw std::runtime_error { std::format(
"exception: {}\nlocation: {}:{}",
std::format(fmt, std::forward<Args_T>(args)...),
location.file_name(),
location.line()
) };
}
}
template<typename Expression_T, typename... Args_T>
debug_check<Expression_T, Args_T...>::debug_check(
const Expression_T &expression,
std::format_string<Args_T...> fmt,
Args_T &&...args,
const std::source_location &location
)
{
if constexpr (build_constants::build_type != build_constants::BuildType::debug)
{
return;
}
if (!static_cast<bool>(expression))
{
throw std::runtime_error { std::format(
"exception: {}\nlocation: {}:{}",
std::format(fmt, std::forward<Args_T>(args)...),
location.file_name(),
location.line()
) };
}
}

View file

@ -0,0 +1,85 @@
export module preliminary.build_constants;
import preliminary.fundumental_types;
import std;
export namespace build_constants {
enum class Platform : u8
{
/** The GNU/Linux platform.
* Tested on the following distros: arch-x86_64
* @note: Named like so because `linux` is a built-in identifier.
* */
gnu_linux,
/**
* The Microsoft Windows(tm) platform.
* Tested on the following architectures: x86_64
*/
windows,
/**
* The apple's macOS platform.
* Currently not supported.
*/
mac,
};
/** The compiler that was used for compiling the project. */
enum class Compiler : u8
{
clang,
gcc,
msvc,
apple_clang,
};
enum class BuildType
{
debug,
release,
distribution
};
#if defined(LIGHT_PLATFORM_WINDOWS)
#define lt_win(x)
constexpr auto platform = Platform::windows;
constexpr auto platform_name = "windows";
constexpr auto platform_identifier = platform_name; // TODO(Light)
#undef LIGHT_PLATFORM_WINDOWS
#elif defined(LIGHT_PLATFORM_LINUX)
constexpr auto platform = Platform::gnu_linux;
constexpr auto platform_name = "gnu_linux";
constexpr auto platform_identifier = platform_name; // TODO(Light)
#elif defined(LIGHT_PLATFORM_MAC)
#define lt_mac(x) x
constexpr auto platform = Platform::mac;
constexpr auto platform_name = "mac";
constexpr auto platform_identifier = platform_name; // TODO(Light)
#else
#error "Unsupported platform: Unknown"
#endif
/** @TODO(Light): Handle other compilers... */
#ifdef __clang__
constexpr auto compiler = Compiler::clang;
constexpr auto compiler_name = "clang";
/** @TODO(Light): insert the full identifier, including version information and such */
constexpr auto compiler_identifier = "clang";
#endif
// @TODO(Light): inject build info through CMake using LIGHT_... constant macros
#if defined(_DEBUG)
constexpr auto build_type = BuildType::debug;
#else
constexpr auto build_type = BuildType::release;
#endif
} // namespace build_constants

View file

@ -1,4 +1,7 @@
export module preliminary; export module preliminary;
export import preliminary.fundumental_types; export import preliminary.fundumental_types;
export import preliminary.assertions;
export import preliminary.build_constants;
// std should always be available... // std should always be available...
export import std; export import std;

View file

@ -11,7 +11,6 @@ export import renderer.vk.gpu;
export import renderer.vk.debugger; export import renderer.vk.debugger;
export import renderer.vk.surface; export import renderer.vk.surface;
export import memory.scope; export import memory.scope;
export import debug.assertions;
export import ecs.entity; export import ecs.entity;
import preliminary; import preliminary;
@ -83,7 +82,7 @@ namespace lt::renderer {
const lt::ecs::Entity &surface_entity const lt::ecs::Entity &surface_entity
) -> memory::Scope<ISurface> ) -> memory::Scope<ISurface>
{ {
debug::ensure(instance, "Failed to create renderer::ISurface: null instance"); ensure(instance, "Failed to create renderer::ISurface: null instance");
switch (target_api) switch (target_api)
{ {
@ -112,8 +111,8 @@ namespace lt::renderer {
[[nodiscard]] auto create_device(Api target_api, IGpu *gpu, ISurface *surface) [[nodiscard]] auto create_device(Api target_api, IGpu *gpu, ISurface *surface)
-> memory::Scope<IDevice> -> memory::Scope<IDevice>
{ {
debug::ensure(gpu, "Failed to create renderer::IDevice: null gpu"); ensure(gpu, "Failed to create renderer::IDevice: null gpu");
debug::ensure(surface, "Failed to create renderer::IDevice: null surface"); ensure(surface, "Failed to create renderer::IDevice: null surface");
switch (target_api) switch (target_api)
{ {
@ -147,9 +146,9 @@ namespace lt::renderer {
const IBuffer::CreateInfo &info const IBuffer::CreateInfo &info
) -> memory::Scope<IBuffer> ) -> memory::Scope<IBuffer>
{ {
debug::ensure(device, "Failed to create renderer::IBuffer: null device"); ensure(device, "Failed to create renderer::IBuffer: null device");
debug::ensure(gpu, "Failed to create renderer::IBuffer: null gpu"); ensure(gpu, "Failed to create renderer::IBuffer: null gpu");
debug::ensure(info.size > 0, "Failed to create renderer::IBuffer: null size"); ensure(info.size > 0, "Failed to create renderer::IBuffer: null size");
switch (target_api) switch (target_api)
{ {
@ -170,7 +169,7 @@ namespace lt::renderer {
const lt::assets::ShaderAsset &fragment_shader const lt::assets::ShaderAsset &fragment_shader
) -> memory::Scope<IPass> ) -> memory::Scope<IPass>
{ {
debug::ensure(device, "Failed to create renderer::IPass: null device"); ensure(device, "Failed to create renderer::IPass: null device");
switch (target_api) switch (target_api)
{ {
@ -192,10 +191,10 @@ namespace lt::renderer {
u32 max_frames_in_flight u32 max_frames_in_flight
) -> memory::Scope<IRenderer> ) -> memory::Scope<IRenderer>
{ {
debug::ensure(gpu, "Failed to create renderer::IRenderer: null gpu"); ensure(gpu, "Failed to create renderer::IRenderer: null gpu");
debug::ensure(device, "Failed to create renderer::IRenderer: null device"); ensure(device, "Failed to create renderer::IRenderer: null device");
debug::ensure(swapchain, "Failed to create renderer::IRenderer: null swapchain"); ensure(swapchain, "Failed to create renderer::IRenderer: null swapchain");
debug::ensure( ensure(
std::clamp( std::clamp(
max_frames_in_flight, max_frames_in_flight,
IRenderer::frames_in_flight_lower_limit, IRenderer::frames_in_flight_lower_limit,
@ -224,17 +223,17 @@ namespace lt::renderer {
[[nodiscard]] auto create_debugger(Api target_api, IInstance *instance, IDebugger::CreateInfo info) [[nodiscard]] auto create_debugger(Api target_api, IInstance *instance, IDebugger::CreateInfo info)
-> memory::Scope<IDebugger> -> memory::Scope<IDebugger>
{ {
debug::ensure( ensure(
info.severities != IDebugger::MessageSeverity::none, info.severities != IDebugger::MessageSeverity::none,
"Failed to create renderer::IDebugger: severities == none" "Failed to create renderer::IDebugger: severities == none"
); );
debug::ensure( ensure(
info.types != IDebugger::MessageType::none, info.types != IDebugger::MessageType::none,
"Failed to create renderer::IDebugger: types == none" "Failed to create renderer::IDebugger: types == none"
); );
debug::ensure(info.callback, "Failed to create vk::Messenger: null callback"); ensure(info.callback, "Failed to create vk::Messenger: null callback");
switch (target_api) switch (target_api)
{ {

View file

@ -2,7 +2,6 @@ export module renderer.system;
import preliminary; import preliminary;
import logger; import logger;
import debug.assertions;
import math.mat4; import math.mat4;
import renderer.factory; import renderer.factory;
import app.system; import app.system;
@ -126,8 +125,8 @@ System::System(CreateInfo info)
, m_instance(get_instance(m_api)) , m_instance(get_instance(m_api))
, m_max_frames_in_flight(info.config.max_frames_in_flight) , m_max_frames_in_flight(info.config.max_frames_in_flight)
{ {
debug::ensure(m_registry, "Failed to initialize renderer::System: null registry"); ensure(m_registry, "Failed to initialize renderer::System: null registry");
debug::ensure( ensure(
std::clamp( std::clamp(
info.config.max_frames_in_flight, info.config.max_frames_in_flight,
frames_in_flight_lower_limit, frames_in_flight_lower_limit,

View file

@ -44,7 +44,6 @@ import preliminary;
import memory.null_on_move; import memory.null_on_move;
import math.vec3; import math.vec3;
import math.vec2; import math.vec2;
import debug.assertions;
import logger; import logger;
template<class... Ts> template<class... Ts>
@ -2930,24 +2929,21 @@ void load_library()
{ {
library = dlopen("libvulkan.so", runtime_loader_flags); library = dlopen("libvulkan.so", runtime_loader_flags);
} }
lt::debug::ensure(library, "Failed to dlopen the libvulkan.so"); ensure(library, "Failed to dlopen the libvulkan.so");
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
api::get_instance_proc_address = reinterpret_cast<PFN_vkGetInstanceProcAddr>( api::get_instance_proc_address = reinterpret_cast<PFN_vkGetInstanceProcAddr>(
dlsym(library, "vkGetInstanceProcAddr") dlsym(library, "vkGetInstanceProcAddr")
); );
lt::debug::ensure( ensure(api::get_instance_proc_address, "Failed to load vulkan function: vkGetInstanceProcAddr");
api::get_instance_proc_address,
"Failed to load vulkan function: vkGetInstanceProcAddr"
);
#elif defined(LIGHT_PLATFORM_WINDOWS) #elif defined(LIGHT_PLATFORM_WINDOWS)
library = LoadLibraryA("vulkan-1.dll"); library = LoadLibraryA("vulkan-1.dll");
lt::debug::ensure(library, "Failed to LoadLibraryA the vulkan-1.dll"); ensure(library, "Failed to LoadLibraryA the vulkan-1.dll");
api::get_instance_proc_address = std::bit_cast<PFN_vkGetInstanceProcAddr>( api::get_instance_proc_address = std::bit_cast<PFN_vkGetInstanceProcAddr>(
GetProcAddress(std::bit_cast<HMODULE>(library), "vkGetInstanceProcAddr") GetProcAddress(std::bit_cast<HMODULE>(library), "vkGetInstanceProcAddr")
); );
lt::debug::ensure( ensure(
api::get_instance_proc_address, api::get_instance_proc_address,
"Failed to get vkGetInstanceProcAddr function pointer from vulkan-1.dll" "Failed to get vkGetInstanceProcAddr function pointer from vulkan-1.dll"
); );
@ -2977,7 +2973,7 @@ void load_global_functions()
{ {
constexpr auto load_fn = []<typename T>(T &pfn, const char *fn_name) { constexpr auto load_fn = []<typename T>(T &pfn, const char *fn_name) {
pfn = std::bit_cast<T>(api::get_instance_proc_address(nullptr, fn_name)); pfn = std::bit_cast<T>(api::get_instance_proc_address(nullptr, fn_name));
lt::debug::ensure(pfn, "Failed to load vulkan global function: {}", fn_name); ensure(pfn, "Failed to load vulkan global function: {}", fn_name);
}; };
load_fn(api::create_instance, "vkCreateInstance"); load_fn(api::create_instance, "vkCreateInstance");
@ -2989,7 +2985,7 @@ void Instance::load_functions()
{ {
const auto load_fn = [this]<typename T>(T &pfn, const char *fn_name) { const auto load_fn = [this]<typename T>(T &pfn, const char *fn_name) {
pfn = std::bit_cast<T>(api::get_instance_proc_address(m_instance, fn_name)); pfn = std::bit_cast<T>(api::get_instance_proc_address(m_instance, fn_name));
lt::debug::ensure(pfn, "Failed to load vulkan instance function: {}", fn_name); ensure(pfn, "Failed to load vulkan instance function: {}", fn_name);
}; };
load_fn(api::destroy_instance, "vkDestroyInstance"); load_fn(api::destroy_instance, "vkDestroyInstance");
@ -3039,7 +3035,7 @@ void Device::load_functions()
{ {
const auto load_fn = [this]<typename T>(T &pfn, const char *fn_name) { const auto load_fn = [this]<typename T>(T &pfn, const char *fn_name) {
pfn = std::bit_cast<T>(api::get_device_proc_address(m_device, fn_name)); pfn = std::bit_cast<T>(api::get_device_proc_address(m_device, fn_name));
lt::debug::ensure(pfn, "Failed to load vulkan device function: {}", fn_name); ensure(pfn, "Failed to load vulkan device function: {}", fn_name);
}; };
load_fn(api::get_device_queue, "vkGetDeviceQueue"); load_fn(api::get_device_queue, "vkGetDeviceQueue");
@ -3149,7 +3145,7 @@ Instance::Instance(CreateInfo info)
values = std::bit_cast<const void *>(&std::get<2>(setting.values)); values = std::bit_cast<const void *>(&std::get<2>(setting.values));
} }
debug::ensure(values, "Failed to get variant from setting.values"); ensure(values, "Failed to get variant from setting.values");
layer_settings.emplace_back( layer_settings.emplace_back(
VkLayerSettingEXT { VkLayerSettingEXT {
@ -3189,7 +3185,7 @@ Instance::Instance(CreateInfo info)
}; };
vkc(api::create_instance(&vk_info, nullptr, &m_instance)); vkc(api::create_instance(&vk_info, nullptr, &m_instance));
debug::ensure(m_instance, "Failed to create vulkan instance"); ensure(m_instance, "Failed to create vulkan instance");
} }
Surface::Surface(const Instance &instance, const CreateInfo &info) Surface::Surface(const Instance &instance, const CreateInfo &info)
@ -3235,7 +3231,7 @@ Surface::~Surface()
{ {
auto count = 0u; auto count = 0u;
vkc(api::enumerate_physical_devices(instance.m_instance, &count, nullptr)); vkc(api::enumerate_physical_devices(instance.m_instance, &count, nullptr));
debug::ensure(count != 0u, "Failed to find any gpus with Vulkan support"); ensure(count != 0u, "Failed to find any gpus with Vulkan support");
auto vk_gpus = std::vector<VkPhysicalDevice>(count); auto vk_gpus = std::vector<VkPhysicalDevice>(count);
vkc(api::enumerate_physical_devices(instance.m_instance, &count, vk_gpus.data())); vkc(api::enumerate_physical_devices(instance.m_instance, &count, vk_gpus.data()));
@ -3926,7 +3922,7 @@ void Device::wait_for_fences(std::span<VkFence> fences) const
{ {
auto count = uint32_t { 0u }; auto count = uint32_t { 0u };
vkc(api::get_swapchain_images_khr(m_device, swapchain, &count, nullptr)); vkc(api::get_swapchain_images_khr(m_device, swapchain, &count, nullptr));
debug::ensure(count != 0u, "Failed to get swapchain images"); ensure(count != 0u, "Failed to get swapchain images");
auto images = std::vector<VkImage>(count); auto images = std::vector<VkImage>(count);
vkc(api::get_swapchain_images_khr(m_device, swapchain, &count, images.data())); vkc(api::get_swapchain_images_khr(m_device, swapchain, &count, images.data()));

View file

@ -5,7 +5,6 @@ import renderer.vk.instance;
import renderer.frontend; import renderer.frontend;
import renderer.vk.api_wrapper; import renderer.vk.api_wrapper;
import memory.null_on_move; import memory.null_on_move;
import debug.assertions;
import logger; import logger;
export namespace lt::renderer::vkb { export namespace lt::renderer::vkb {
@ -156,7 +155,7 @@ void Debugger::native_callback(
{ {
try try
{ {
debug::ensure(user_data, "Null vulkan_user_data received in messenger callback"); ensure(user_data, "Null vulkan_user_data received in messenger callback");
auto *messenger = std::bit_cast<Debugger *>(user_data); auto *messenger = std::bit_cast<Debugger *>(user_data);
messenger->m_user_callback( messenger->m_user_callback(

View file

@ -3,7 +3,6 @@ export module renderer.vk.device;
import preliminary; import preliminary;
import memory.null_on_move; import memory.null_on_move;
import logger; import logger;
import debug.assertions;
import renderer.vk.instance; import renderer.vk.instance;
import renderer.frontend; import renderer.frontend;
import renderer.vk.api_wrapper; import renderer.vk.api_wrapper;
@ -71,7 +70,7 @@ Device::Device(IGpu *gpu, ISurface *surface)
: m_gpu(static_cast<Gpu *>(gpu)) : m_gpu(static_cast<Gpu *>(gpu))
, m_surface(static_cast<Surface *>(surface)) , m_surface(static_cast<Surface *>(surface))
{ {
debug::ensure(m_surface->vk(), "Failed to initialize vk::Device: null vulkan surface"); ensure(m_surface->vk(), "Failed to initialize vk::Device: null vulkan surface");
initialize_queue_indices(); initialize_queue_indices();
initialize_logical_device(); initialize_logical_device();
@ -146,12 +145,12 @@ void Device::initialize_queue_indices()
++idx; ++idx;
} }
debug::ensure( ensure(
m_graphics_queue_family_index != vk::constants::queue_family_ignored, m_graphics_queue_family_index != vk::constants::queue_family_ignored,
"Failed to find graphics queue family" "Failed to find graphics queue family"
); );
debug::ensure( ensure(
m_present_queue_family_index != vk::constants::queue_family_ignored, m_present_queue_family_index != vk::constants::queue_family_ignored,
"Failed to find presentation queue family" "Failed to find presentation queue family"
); );

View file

@ -3,7 +3,6 @@ export module renderer.vk.gpu;
import preliminary; import preliminary;
import renderer.vk.api_wrapper; import renderer.vk.api_wrapper;
import logger; import logger;
import debug.assertions;
import renderer.frontend; import renderer.frontend;
import renderer.vk.instance; import renderer.vk.instance;
import memory.null_on_move; import memory.null_on_move;
@ -66,7 +65,7 @@ Gpu::Gpu(IInstance *instance)
} }
// No suitable GPU is fonud... // No suitable GPU is fonud...
debug::ensure(m_gpu, "Failed to find any suitable Vulkan physical device"); ensure(m_gpu, "Failed to find any suitable Vulkan physical device");
m_memory_properties = m_gpu.get_memory_properties(); m_memory_properties = m_gpu.get_memory_properties();
m_queue_family_properties = m_gpu.get_queue_family_properties(); m_queue_family_properties = m_gpu.get_queue_family_properties();

View file

@ -1,7 +1,6 @@
export module renderer.vk.instance; export module renderer.vk.instance;
import preliminary; import preliminary;
import debug.assertions;
import renderer.frontend; import renderer.frontend;
import renderer.vk.api_wrapper; import renderer.vk.api_wrapper;

View file

@ -3,7 +3,6 @@ export module renderer.vk.renderer;
import preliminary; import preliminary;
import logger; import logger;
import assets.shader; import assets.shader;
import debug.assertions;
import renderer.vk.api_wrapper; import renderer.vk.api_wrapper;
import memory.reference; import memory.reference;
import memory.null_on_move; import memory.null_on_move;
@ -171,7 +170,7 @@ Renderer::Renderer(IGpu *gpu, IDevice *device, ISwapchain *swapchain, u32 max_fr
[[nodiscard]] auto Renderer::frame(u32 frame_idx, std::function<void()> submit_scene) -> Result [[nodiscard]] auto Renderer::frame(u32 frame_idx, std::function<void()> submit_scene) -> Result
{ {
debug::ensure( ensure(
frame_idx < m_max_frames_in_flight, frame_idx < m_max_frames_in_flight,
"Failed to draw: frame_idx >= max_frames_in_flight ({} >= {})", "Failed to draw: frame_idx >= max_frames_in_flight ({} >= {})",
frame_idx, frame_idx,

View file

@ -1,7 +1,6 @@
export module renderer.vk.surface; export module renderer.vk.surface;
import preliminary; import preliminary;
import debug.assertions;
import ecs.entity; import ecs.entity;
import ecs.registry; import ecs.registry;
import memory.null_on_move; import memory.null_on_move;
@ -43,11 +42,11 @@ Surface::Surface(IInstance *instance, const ecs::Entity &surface_entity)
#if defined(LIGHT_PLATFORM_LINUX) #if defined(LIGHT_PLATFORM_LINUX)
debug::ensure( ensure(
component.get_native_data().display, component.get_native_data().display,
"Failed to initialize vk::Surface: null Wayland display" "Failed to initialize vk::Surface: null Wayland display"
); );
debug::ensure( ensure(
component.get_native_data().surface, component.get_native_data().surface,
"Failed to initialize vk::Surface: null Wayland surface" "Failed to initialize vk::Surface: null Wayland surface"
); );
@ -61,7 +60,7 @@ Surface::Surface(IInstance *instance, const ecs::Entity &surface_entity)
); );
#elif defined(LIGHT_PLATFORM_WINDOWS) #elif defined(LIGHT_PLATFORM_WINDOWS)
debug::ensure( ensure(
component.get_native_data().window, component.get_native_data().window,
"Failed to initialize vk::Surface: null win32 window handle" "Failed to initialize vk::Surface: null win32 window handle"
); );

View file

@ -1,3 +1,3 @@
add_executable(sandbox sandbox.cpp) add_executable(sandbox sandbox.cpp)
target_link_libraries(sandbox PRIVATE logger bitwise env memory time test lt_debug math assets app ecs surface renderer input mirror) target_link_libraries(sandbox PRIVATE preliminary logger bitwise env memory time test math assets app ecs surface renderer input mirror)

View file

@ -18,7 +18,7 @@ constexpr auto height = 600u;
constexpr auto vsync = true; constexpr auto vsync = true;
constexpr auto visible = false; constexpr auto visible = false;
auto main() -> int32_t auto main() -> i32
try try
{ {
auto registry = lt::memory::create_ref<lt::ecs::Registry>(); auto registry = lt::memory::create_ref<lt::ecs::Registry>();

View file

@ -12,7 +12,6 @@ export module surface.system;
export import :components; export import :components;
import preliminary; import preliminary;
import debug.assertions;
import app.system; import app.system;
import ecs.registry; import ecs.registry;
import math.vec2; import math.vec2;
@ -23,7 +22,6 @@ import memory.null_on_move;
import logger; import logger;
import preliminary; import preliminary;
import surface.constants; import surface.constants;
import debug.assertions;
import memory.reference; import memory.reference;
import surface.requests; import surface.requests;
import surface.events; import surface.events;
@ -175,7 +173,7 @@ private:
wl_compositor *m_wl_compositor {}; wl_compositor *m_wl_compositor {};
xdg_wm_base *m_shell = {}; xdg_wm_base *m_shell {};
wl_seat *m_wl_seat {}; wl_seat *m_wl_seat {};
@ -440,11 +438,11 @@ System::System(memory::Ref<ecs::Registry> registry)
{ {
// NOLINTNEXTLINE // NOLINTNEXTLINE
m_wl_display = wl_display_connect({}); m_wl_display = wl_display_connect({});
debug::ensure(m_wl_display, "Failed to connect to Wayland display"); ensure(m_wl_display, "Failed to connect to Wayland display");
// NOLINTNEXTLINE // NOLINTNEXTLINE
m_wl_registry = wl_display_get_registry(m_wl_display); m_wl_registry = wl_display_get_registry(m_wl_display);
debug::ensure(m_wl_registry, "Failed to get Wayland display's registry"); ensure(m_wl_registry, "Failed to get Wayland display's registry");
// TODO(Light): "this" could be moved around... replace with a pointer to some heap allocation // TODO(Light): "this" could be moved around... replace with a pointer to some heap allocation
wl_registry_add_listener(m_wl_registry, &m_wl_registry_listener, this); wl_registry_add_listener(m_wl_registry, &m_wl_registry_listener, this);
@ -454,8 +452,8 @@ System::System(memory::Ref<ecs::Registry> registry)
// For reasons beyond my fragile comprehension :( // For reasons beyond my fragile comprehension :(
wl_display_roundtrip(m_wl_display); wl_display_roundtrip(m_wl_display);
debug::ensure(m_wl_compositor, "Failed to bind to the Wayland's compositor global"); ensure(m_wl_compositor, "Failed to bind to the Wayland's compositor global");
debug::ensure(m_shell, "Failed to bind to the Wayland's XDG-shell global"); ensure(m_shell, "Failed to bind to the Wayland's XDG-shell global");
} }
System::~System() System::~System()
@ -488,14 +486,14 @@ void System::create_surface_component(ecs::EntityId entity, SurfaceComponent::Cr
auto *shell_toplevel = (xdg_toplevel *)nullptr; auto *shell_toplevel = (xdg_toplevel *)nullptr;
wayland_surface = wl_compositor_create_surface(m_wl_compositor); wayland_surface = wl_compositor_create_surface(m_wl_compositor);
debug::ensure(wayland_surface, "Failed to create Wayland surface"); ensure(wayland_surface, "Failed to create Wayland surface");
shell_surface = xdg_wm_base_get_xdg_surface(m_shell, wayland_surface); shell_surface = xdg_wm_base_get_xdg_surface(m_shell, wayland_surface);
debug::ensure(shell_surface, "Failed to get XDG-shell surface"); ensure(shell_surface, "Failed to get XDG-shell surface");
xdg_surface_add_listener(shell_surface, &shell_surface_listener, {}); xdg_surface_add_listener(shell_surface, &shell_surface_listener, {});
shell_toplevel = xdg_surface_get_toplevel(shell_surface); shell_toplevel = xdg_surface_get_toplevel(shell_surface);
debug::ensure(shell_toplevel, "Failed to get XDG-shell toplevel"); ensure(shell_toplevel, "Failed to get XDG-shell toplevel");
xdg_toplevel_add_listener(shell_toplevel, &toplevel_listener, {}); xdg_toplevel_add_listener(shell_toplevel, &toplevel_listener, {});
xdg_toplevel_set_title(shell_toplevel, "Wayland Vulkan Example"); xdg_toplevel_set_title(shell_toplevel, "Wayland Vulkan Example");
@ -649,9 +647,9 @@ auto CALLBACK window_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) ->
System::System(memory::Ref<ecs::Registry> registry): m_registry(std::move(registry)) System::System(memory::Ref<ecs::Registry> registry): m_registry(std::move(registry))
{ {
debug::ensure(m_registry, "Failed to initialize surface system: null registry"); ensure(m_registry, "Failed to initialize surface system: null registry");
debug::ensure( ensure(
m_registry->view<SurfaceComponent>().get_size() == 0, m_registry->view<SurfaceComponent>().get_size() == 0,
"Failed to initialize surface system: registry has surface component(s)" "Failed to initialize surface system: registry has surface component(s)"
); );
@ -738,7 +736,7 @@ try
GetModuleHandle(nullptr), GetModuleHandle(nullptr),
nullptr nullptr
); );
debug::ensure(surface.m_native_data.window, "Failed to create Windows surface component"); ensure(surface.m_native_data.window, "Failed to create Windows surface component");
ShowWindow(surface.m_native_data.window, SW_NORMAL); ShowWindow(surface.m_native_data.window, SW_NORMAL);
// SetWindowLongPtrA(surface.m_native_data.window, 0, this); // SetWindowLongPtrA(surface.m_native_data.window, 0, this);
@ -748,10 +746,10 @@ try
// TODO(Light): refactor "environment" into standalone module // TODO(Light): refactor "environment" into standalone module
// NOLINTNEXTLINE(concurrency-mt-unsafe) // NOLINTNEXTLINE(concurrency-mt-unsafe)
// auto *display_env = std::getenv("DISPLAY"); // auto *display_env = std::getenv("DISPLAY");
// debug::ensure(display_env != nullptr, "DISPLAY env var not found!"); // ensure(display_env != nullptr, "DISPLAY env var not found!");
// //
// auto *display = XOpenDisplay(display_env); // auto *display = XOpenDisplay(display_env);
// debug::ensure(display, "Failed to open XDisplay with DISPLAY: {}", display_env); // ensure(display, "Failed to open XDisplay with DISPLAY: {}", display_env);
// //
// auto root_window = XDefaultRootWindow(display); // auto root_window = XDefaultRootWindow(display);
// //
@ -1151,29 +1149,25 @@ void ensure_component_sanity(const SurfaceComponent &component)
{ {
auto [width, height] = component.get_resolution(); auto [width, height] = component.get_resolution();
debug::ensure(width != 0u, "Received bad values for surface component: width({}) == 0", width); ensure(width != 0u, "Received bad values for surface component: width({}) == 0", width);
debug::ensure( ensure(height != 0u, "Received bad values for surface component: height({}) == 0", height);
height != 0u,
"Received bad values for surface component: height({}) == 0",
height
);
debug::ensure( ensure(
width < SurfaceComponent::max_dimension, width < SurfaceComponent::max_dimension,
"Received bad values for surface component: width({}) > max_dimension({})", "Received bad values for surface component: width({}) > max_dimension({})",
width, width,
SurfaceComponent::max_dimension SurfaceComponent::max_dimension
); );
debug::ensure( ensure(
height < SurfaceComponent::max_dimension, height < SurfaceComponent::max_dimension,
"Received bad values for surface component: height({}) > max_dimension({})", "Received bad values for surface component: height({}) > max_dimension({})",
height, height,
SurfaceComponent::max_dimension SurfaceComponent::max_dimension
); );
debug::ensure( ensure(
component.get_title().size() < SurfaceComponent::max_title_length, component.get_title().size() < SurfaceComponent::max_title_length,
"Received bad values for surface component: title.size({}) > max_title_length({})", "Received bad values for surface component: title.size({}) > max_title_length({})",
component.get_title().size(), component.get_title().size(),

View file

@ -1,23 +1,25 @@
// @todo(Light): Implement...
export module debug.instrumentor; export module debug.instrumentor;
import preliminary; import preliminary;
import logger; import logger;
namespace lt::debug { namespace lt::tracer {
struct ScopeProfileResult struct ScopeTraceResult
{ {
std::string name; std::string name;
u64 start, duration; u64 start, duration;
u32 threadID; u32 threadID;
}; };
class Instrumentor class Tracer
{ {
public: public:
static auto instance() -> Instrumentor & static auto instance() -> Tracer &
{ {
static auto instance = Instrumentor {}; static auto instance = Tracer {};
return instance; return instance;
} }
@ -30,7 +32,7 @@ public:
instance().end_session_impl(); instance().end_session_impl();
} }
static void submit_scope_profile(const ScopeProfileResult &profileResult) static void submit_scope_profile(const ScopeTraceResult &profileResult)
{ {
instance().submit_scope_profile_impl(profileResult); instance().submit_scope_profile_impl(profileResult);
} }
@ -40,46 +42,46 @@ private:
unsigned int m_current_session_count { 0u }; unsigned int m_current_session_count { 0u };
Instrumentor() = default; Tracer() = default;
void begin_session_impl(const std::string &outputPath); void begin_session_impl(const std::string &outputPath);
void end_session_impl(); void end_session_impl();
void submit_scope_profile_impl(const ScopeProfileResult &profileResult); void submit_scope_profile_impl(const ScopeTraceResult &profileResult);
}; };
class InstrumentorTimer class TracerTimer
{ {
public: public:
InstrumentorTimer(const std::string &scopeName); TracerTimer(const std::string &scopeName);
~InstrumentorTimer(); ~TracerTimer();
private: private:
ScopeProfileResult m_result; ScopeTraceResult m_result;
std::chrono::time_point<std::chrono::steady_clock> m_start; std::chrono::time_point<std::chrono::steady_clock> m_start;
}; };
} // namespace lt::debug } // namespace lt::tracer
/* scope */ /* scope */
#define lt_profile_scope(name) lt_profile_scope_no_redifinition(name, __LINE__) #define lt_trace_scope(name) lt_profile_scope_no_redifinition(name, __LINE__)
#define lt_profile_scope_no_redifinition(name, line) lt_profile_scope_no_redifinition2(name, line) #define lt_trace_scope_no_redifinition(name, line) lt_profile_scope_no_redifinition2(name, line)
#define lt_profile_scope_no_redifinition2(name, line) InstrumentorTimer timer##line(name) #define lt_trace_scope_no_redifinition2(name, line) InstrumentorTimer timer##line(name)
/* function */ /* function */
#define LT_PROFILE_FUNCTION lt_profile_scope(__FUNCSIG__) #define lt_trace_function lt_profile_scope(__FUNCSIG__)
/* session */ /* session */
#define lt_profile_begin_session(outputPath) ::lt::Instrumentor::begin_session(outputPath) #define lt_trace_begin_session(outputPath) ::lt::Instrumentor::begin_session(outputPath)
#define lt_profile_end_session() ::lt::Instrumentor::end_session() #define lt_trace_end_session() ::lt::Instrumentor::end_session()
module :private; module :private;
namespace lt::debug { namespace lt::tracer {
void Instrumentor::begin_session_impl(const std::string &outputPath) void Tracer::begin_session_impl(const std::string &outputPath)
{ {
std::filesystem::create_directory(outputPath.substr(0, outputPath.find_last_of('/') + 1)); std::filesystem::create_directory(outputPath.substr(0, outputPath.find_last_of('/') + 1));
@ -87,7 +89,7 @@ void Instrumentor::begin_session_impl(const std::string &outputPath)
m_output_file_stream << "{\"traceEvents\":["; m_output_file_stream << "{\"traceEvents\":[";
} }
void Instrumentor::end_session_impl() void Tracer::end_session_impl()
{ {
if (m_current_session_count == 0u) if (m_current_session_count == 0u)
{ {
@ -101,7 +103,7 @@ void Instrumentor::end_session_impl()
m_output_file_stream.close(); m_output_file_stream.close();
} }
void Instrumentor::submit_scope_profile_impl(const ScopeProfileResult &profileResult) void Tracer::submit_scope_profile_impl(const ScopeTraceResult &profileResult)
{ {
if (m_current_session_count++ == 0u) if (m_current_session_count++ == 0u)
{ {
@ -122,13 +124,13 @@ void Instrumentor::submit_scope_profile_impl(const ScopeProfileResult &profileRe
m_output_file_stream << "}"; m_output_file_stream << "}";
} }
InstrumentorTimer::InstrumentorTimer(const std::string &scopeName) TracerTimer::TracerTimer(const std::string &scopeName)
: m_result({ .name = scopeName, .start = 0, .duration = 0, .threadID = 0 }) : m_result({ .name = scopeName, .start = 0, .duration = 0, .threadID = 0 })
, m_start(std::chrono::steady_clock::now()) , m_start(std::chrono::steady_clock::now())
{ {
} }
InstrumentorTimer::~InstrumentorTimer() TracerTimer::~TracerTimer()
{ {
auto end = std::chrono::steady_clock::now(); auto end = std::chrono::steady_clock::now();
@ -141,6 +143,6 @@ InstrumentorTimer::~InstrumentorTimer()
.count() .count()
- m_result.start; - m_result.start;
Instrumentor::submit_scope_profile(m_result); Tracer::submit_scope_profile(m_result);
} }
} // namespace lt::debug } // namespace lt::tracer