revert: feat: lsd
Some checks reported errors
continuous-integration/drone/push Build was killed

It was a horrible idea...
This commit is contained in:
light7734 2025-11-30 09:46:48 +03:30
parent 61a79d1c8d
commit 2b81b4376c
Signed by: light7734
GPG key ID: 8C30176798F1A6BA
48 changed files with 763 additions and 888 deletions

View file

@ -1,35 +1,12 @@
add_module( add_module(
NAME NAME logger INTERFACES logger.cppm TESTS logger.test.cpp
lsd
INTERFACES
lsd.cppm
ref.cppm
vec.cppm
arr.cppm
str.cppm
set.cppm
span.cppm
hash.cppm
utils.cppm
scope.cppm
chrono.cppm
thread.cppm
bitwise.cppm
concepts.cppm
algorithm.cppm
filesystem.cppm
primitives.cppm
exceptions.cppm
src_location.cppm
math/algebra.cppm
math/trig.cppm
math/vec2.cppm
math/vec3.cppm
math/vec4.cppm
math/mat4.cppm
) )
add_module(NAME bitwise INTERFACES operations.cppm)
add_module(NAME logger INTERFACES logger.cppm DEPENDENCIES lsd) add_module(NAME env INTERFACES constants.cppm)
add_module(
NAME memory INTERFACES null_on_move.cppm reference.cppm scope.cppm
)
add_module(NAME time INTERFACES timer.cppm)
add_module( add_module(
NAME NAME
@ -41,12 +18,8 @@ add_module(
SOURCES SOURCES
entrypoint.cpp entrypoint.cpp
DEPENDENCIES DEPENDENCIES
lsd
logger logger
) )
add_module(NAME env INTERFACES constants.cppm DEPENDENCIES lsd)
# add_module(NAME memory INTERFACES reference.cppm scope.cppm)
add_module(NAME time INTERFACES timer.cppm DEPENDENCIES lsd)
add_module( add_module(
NAME NAME
@ -54,10 +27,23 @@ add_module(
ROOT_DIR ROOT_DIR
${CMAKE_CURRENT_SOURCE_DIR}/debug ${CMAKE_CURRENT_SOURCE_DIR}/debug
INTERFACES INTERFACES
instrumentor.cppm
assertions.cppm assertions.cppm
DEPENDENCIES DEPENDENCIES
logger logger
lsd )
add_module(
NAME
math
INTERFACES
algebra.cppm
mat4.cppm
trig.cppm
vec2.cppm
vec3.cppm
vec4.cppm
components.cppm
) )
add_module( add_module(
@ -79,7 +65,6 @@ add_module(
INTERFACES INTERFACES
bakers.cppm bakers.cppm
DEPENDENCIES DEPENDENCIES
lsd
assets assets
logger logger
lt_debug lt_debug
@ -88,15 +73,7 @@ add_module(
# add_executable(asset_baker entrypoint.cpp) target_link_libraries(asset_baker # add_executable(asset_baker entrypoint.cpp) target_link_libraries(asset_baker
# PRIVATE libasset_baker) # PRIVATE libasset_baker)
add_module( add_module(NAME camera INTERFACES components.cppm DEPENDENCIES math)
NAME
camera
INTERFACES
components.cppm
DEPENDENCIES
math
lsd
)
add_module( add_module(
NAME NAME
@ -104,9 +81,10 @@ add_module(
INTERFACES INTERFACES
application.cppm application.cppm
system.cppm system.cppm
DEPENDENCIES
memory
PRIVATE_DEPENDENCIES PRIVATE_DEPENDENCIES
lt_debug lt_debug
lsd
) )
add_module( add_module(
@ -119,11 +97,9 @@ add_module(
DEPENDENCIES DEPENDENCIES
logger logger
lt_debug lt_debug
lsd memory
) )
return()
if(WIN32) if(WIN32)
add_module( add_module(
NAME NAME
@ -230,8 +206,6 @@ add_module(
mirror mirror
ROOT_DIR ROOT_DIR
${CMAKE_CURRENT_SOURCE_DIR}/mirror ${CMAKE_CURRENT_SOURCE_DIR}/mirror
ENTRYPOINT
entrypoint.cpp
INTERFACES INTERFACES
system.cppm system.cppm
DEPENDENCIES DEPENDENCIES
@ -242,6 +216,23 @@ add_module(
surface surface
renderer renderer
camera camera
TESTS # TESTS
system.test.cpp # system.test.cpp
) )
add_executable(exectest ${CMAKE_CURRENT_SOURCE_DIR}/mirror/entrypoint.cpp
)
target_link_libraries(exectest PRIVATE
mirror
app
time
input
surface
renderer
camera
)
# add_executable_module(mirror entrypoint/mirror.cpp)
# target_link_libraries(mirror PRIVATE libmirror input)

View file

@ -1,6 +1,8 @@
export module app; export module app;
import app.system; import app.system;
import lsd; import memory.reference;
import memory.scope;
import std;
namespace lt::app { namespace lt::app {
@ -23,19 +25,19 @@ public:
void game_loop(); void game_loop();
void register_system(lsd::ref<app::ISystem> system); void register_system(memory::Ref<app::ISystem> system);
void unregister_system(lsd::ref<app::ISystem> system); void unregister_system(memory::Ref<app::ISystem> system);
protected: protected:
Application() = default; Application() = default;
private: private:
lsd::vec<lsd::ref<app::ISystem>> m_systems; std::vector<memory::Ref<app::ISystem>> m_systems;
lsd::vec<lsd::ref<app::ISystem>> m_systems_to_be_unregistered; std::vector<memory::Ref<app::ISystem>> m_systems_to_be_unregistered;
lsd::vec<lsd::ref<app::ISystem>> m_systems_to_be_registered; std::vector<memory::Ref<app::ISystem>> m_systems_to_be_registered;
}; };
} // namespace lt::app } // namespace lt::app
@ -50,11 +52,11 @@ void Application::game_loop()
for (auto &system : m_systems) for (auto &system : m_systems)
{ {
const auto &last_tick = system->get_last_tick_result(); const auto &last_tick = system->get_last_tick_result();
const auto now = lsd::chrono::steady_clock::now(); const auto now = std::chrono::steady_clock::now();
system->tick(TickInfo { system->tick(TickInfo {
.delta_time = now - last_tick.end_time, .delta_time = now - last_tick.end_time,
.budget = lsd::chrono::milliseconds { 10 }, .budget = std::chrono::milliseconds { 10 },
.start_time = now, .start_time = now,
}); });
} }
@ -67,7 +69,7 @@ void Application::game_loop()
for (auto &system : m_systems_to_be_unregistered) for (auto &system : m_systems_to_be_unregistered)
{ {
m_systems.erase( m_systems.erase(
lsd::remove(m_systems.begin(), m_systems.end(), system), std::remove(m_systems.begin(), m_systems.end(), system),
m_systems.end() m_systems.end()
); );
} }
@ -79,14 +81,14 @@ void Application::game_loop()
} }
} }
void Application::register_system(lsd::ref<app::ISystem> system) void Application::register_system(memory::Ref<app::ISystem> system)
{ {
m_systems.emplace_back(lsd::move(system)); m_systems.emplace_back(std::move(system));
} }
void Application::unregister_system(lsd::ref<app::ISystem> system) void Application::unregister_system(memory::Ref<app::ISystem> system)
{ {
m_systems_to_be_unregistered.emplace_back(lsd::move(system)); m_systems_to_be_unregistered.emplace_back(std::move(system));
} }
} // namespace lt::app } // namespace lt::app

View file

@ -1,6 +1,6 @@
export module app.system; export module app.system;
import logger; import logger;
import lsd; import std;
namespace lt::app { namespace lt::app {
@ -9,9 +9,9 @@ namespace lt::app {
*/ */
export struct TickInfo export struct TickInfo
{ {
using Timepoint_T = lsd::chrono::time_point<lsd::chrono::steady_clock>; using Timepoint_T = std::chrono::time_point<std::chrono::steady_clock>;
using Duration_T = lsd::chrono::duration<f64>; using Duration_T = std::chrono::duration<double>;
/** Duration since previous tick's end_time to current tick's start_time. */ /** Duration since previous tick's end_time to current tick's start_time. */
Duration_T delta_time {}; Duration_T delta_time {};
@ -32,9 +32,9 @@ export struct TickInfo
/** Information about how a system's tick performed */ /** Information about how a system's tick performed */
export struct TickResult export struct TickResult
{ {
using Timepoint_T = lsd::chrono::time_point<lsd::chrono::steady_clock>; using Timepoint_T = std::chrono::time_point<std::chrono::steady_clock>;
using Duration_T = lsd::chrono::duration<f64>; using Duration_T = std::chrono::duration<double>;
/** The info supplied to the system for ticking. */ /** The info supplied to the system for ticking. */
TickInfo info; TickInfo info;
@ -48,7 +48,7 @@ export struct TickResult
export struct SystemDiagnosis export struct SystemDiagnosis
{ {
enum class Severity : u8 enum class Severity : std::uint8_t
{ {
verbose, verbose,
info, info,
@ -57,9 +57,9 @@ export struct SystemDiagnosis
fatal, fatal,
}; };
lsd::str message; std::string message;
lsd::str code; std::string code;
Severity severity; Severity severity;
}; };
@ -69,9 +69,9 @@ export class SystemStats
public: public:
void push_diagnosis(SystemDiagnosis &&diagnosis) void push_diagnosis(SystemDiagnosis &&diagnosis)
{ {
auto &diag = m_diagnosis.emplace_back(lsd::move(diagnosis)); auto &diag = m_diagnosis.emplace_back(std::move(diagnosis));
log::info("message: {}", lsd::str { diag.message }); log::info("message: {}", std::string { diag.message });
} }
[[nodiscard]] auto empty_diagnosis() const -> bool [[nodiscard]] auto empty_diagnosis() const -> bool
@ -80,7 +80,7 @@ public:
} }
private: private:
lsd::vec<SystemDiagnosis> m_diagnosis; std::vector<SystemDiagnosis> m_diagnosis;
}; };
export class ISystem export class ISystem

View file

@ -1,33 +1,32 @@
export module bakers; export module bakers;
import debug.assertions; import debug.assertions;
import assets.metadata; import assets.metadata;
import assets.shader; import assets.shader;
import logger; import logger;
import lsd; import std;
namespace lt {
export void bake_shader( export void bake_shader(
const lsd::file::path &in_path, const std::filesystem::path &in_path,
const lsd::file::path &out_path, const std::filesystem::path &out_path,
assets::ShaderAsset::Type type lt::assets::ShaderAsset::Type type
) )
{ {
using assets::ShaderAsset; using lt::assets::ShaderAsset;
using enum assets::ShaderAsset::Type; using enum lt::assets::ShaderAsset::Type;
auto glsl_path = lsd::str { in_path.string() }; auto glsl_path = std::string { in_path.string() };
auto spv_path = lsd::format("{}.spv", glsl_path); auto spv_path = std::format("{}.spv", glsl_path);
log::trace( lt::log::trace(
"Compiling {} shader {} -> {}", "Compiling {} shader {} -> {}",
type == vertex ? "vertex" : "fragment", type == vertex ? "vertex" : "fragment",
lsd::str { glsl_path }, std::string { glsl_path },
lsd::str { spv_path } std::string { spv_path }
); );
// Don't bother linking to shaderc, just invoke the command with a system call. // Don't bother linking to shaderc, just invoke the command with a system call.
// NOLINTNEXTLINE(concurrency-mt-unsafe) // NOLINTNEXTLINE(concurrency-mt-unsafe)
lsd::system(lsd::format( std::system(std::format(
"glslc --target-env=vulkan1.4 -std=450core -fshader-stage={} {} -o {}", "glslc --target-env=vulkan1.4 -std=450core -fshader-stage={} {} -o {}",
type == vertex ? "vert" : "frag", type == vertex ? "vert" : "frag",
glsl_path, glsl_path,
@ -35,35 +34,33 @@ export void bake_shader(
) )
.c_str()); .c_str());
auto stream = lsd::file::in_stream(spv_path, lsd::file::ios_binary); auto stream = std::ifstream(spv_path, std::ios::binary);
debug::ensure( lt::debug::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",
spv_path spv_path
); );
stream.seekg(0, lsd::file::ios_end); stream.seekg(0, std::ios::end);
const auto size = stream.tellg(); const auto size = stream.tellg();
auto bytes = lsd::vec<byte>(size); auto bytes = std::vector<std::byte>(size);
stream.seekg(0, lsd::file::ios_beg); stream.seekg(0, std::ios::beg);
stream.read((char *)bytes.data(), size); // NOLINT stream.read((char *)bytes.data(), size); // NOLINT
log::debug("BYTES: {}", bytes.size()); lt::log::debug("BYTES: {}", bytes.size());
stream.close(); stream.close();
lsd::file::remove(spv_path); std::filesystem::remove(spv_path);
ShaderAsset::pack( ShaderAsset::pack(
out_path, out_path,
assets::AssetMetadata { lt::assets::AssetMetadata {
.version = assets::current_version, .version = lt::assets::current_version,
.type = ShaderAsset::asset_type_identifier, .type = ShaderAsset::asset_type_identifier,
}, },
ShaderAsset::Metadata { ShaderAsset::Metadata {
.type = type, .type = type,
}, },
lsd::move(bytes) std::move(bytes)
); );
} }
} // namespace lt

View file

@ -2,7 +2,7 @@ export module assets.shader;
import assets.metadata; import assets.metadata;
import debug.assertions; import debug.assertions;
import lsd; import std;
export namespace lt::assets { export namespace lt::assets {
@ -16,7 +16,7 @@ public:
code, code,
}; };
enum class Type : u8 enum class Type : std::uint8_t
{ {
vertex, vertex,
fragment, fragment,
@ -30,15 +30,15 @@ public:
}; };
static void pack( static void pack(
const lsd::file::path &destination, const std::filesystem::path &destination,
AssetMetadata asset_metadata, AssetMetadata asset_metadata,
Metadata metadata, Metadata metadata,
Blob code_blob Blob code_blob
); );
ShaderAsset(const lsd::file::path &path); ShaderAsset(const std::filesystem::path &path);
void unpack_to(BlobTag tag, lsd::span<byte> destination) const; void unpack_to(BlobTag tag, std::span<std::byte> destination) const;
[[nodiscard]] auto unpack(BlobTag tag) const -> Blob; [[nodiscard]] auto unpack(BlobTag tag) const -> Blob;
@ -57,7 +57,7 @@ public:
debug::ensure( debug::ensure(
tag == BlobTag::code, tag == BlobTag::code,
"Invalid blob tag for shader asset: {}", "Invalid blob tag for shader asset: {}",
lsd::to_underlying(tag) std::to_underlying(tag)
); );
return m_code_blob_metadata; return m_code_blob_metadata;
@ -88,15 +88,15 @@ constexpr auto total_metadata_size = //
+ sizeof(BlobMetadata::compressed_size) // + sizeof(BlobMetadata::compressed_size) //
+ sizeof(BlobMetadata::uncompressed_size); + sizeof(BlobMetadata::uncompressed_size);
ShaderAsset::ShaderAsset(const lsd::file::path &path): m_stream(path) ShaderAsset::ShaderAsset(const std::filesystem::path &path): m_stream(path)
{ {
debug::ensure(m_stream.is_open(), "Failed to open shader asset at: {}", path.string()); debug::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(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<std::size_t>(m_stream.tellg());
debug::ensure( debug::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: {} < {}",
@ -132,14 +132,14 @@ ShaderAsset::ShaderAsset(const lsd::file::path &path): m_stream(path)
); );
debug::ensure( debug::ensure(
lsd::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(),
lsd::to_underlying(m_metadata.type) std::to_underlying(m_metadata.type)
); );
debug::ensure( debug::ensure(
m_code_blob_metadata.tag == lsd::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
@ -156,7 +156,7 @@ ShaderAsset::ShaderAsset(const lsd::file::path &path): m_stream(path)
} }
/* static */ void ShaderAsset::pack( /* static */ void ShaderAsset::pack(
const lsd::file::path &destination, const std::filesystem::path &destination,
AssetMetadata asset_metadata, AssetMetadata asset_metadata,
Metadata metadata, Metadata metadata,
Blob code_blob Blob code_blob
@ -168,7 +168,7 @@ ShaderAsset::ShaderAsset(const lsd::file::path &path): m_stream(path)
}; };
const auto code_blob_metadata = BlobMetadata { const auto code_blob_metadata = BlobMetadata {
.tag = lsd::to_underlying(BlobTag::code), .tag = std::to_underlying(BlobTag::code),
.offset = total_metadata_size, .offset = total_metadata_size,
.compression_type = CompressionType::none, .compression_type = CompressionType::none,
.compressed_size = code_blob.size(), .compressed_size = code_blob.size(),
@ -177,7 +177,7 @@ ShaderAsset::ShaderAsset(const lsd::file::path &path): m_stream(path)
debug::ensure(stream.is_open(), "Failed to pack shader asset to {}", destination.string()); debug::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(bit_cast<char *>(&field), sizeof(field)); stream.write(std::bit_cast<char *>(&field), sizeof(field));
}; };
write(asset_metadata.type); write(asset_metadata.type);
write(asset_metadata.version); write(asset_metadata.version);
@ -187,31 +187,31 @@ ShaderAsset::ShaderAsset(const lsd::file::path &path): m_stream(path)
write(code_blob_metadata.compression_type); write(code_blob_metadata.compression_type);
write(code_blob_metadata.compressed_size); write(code_blob_metadata.compressed_size);
write(code_blob_metadata.uncompressed_size); write(code_blob_metadata.uncompressed_size);
stream.write(bit_cast<char *>(code_blob.data()), static_cast<stream_size>(code_blob.size())); stream.write(std::bit_cast<char *>(code_blob.data()), static_cast<long long>(code_blob.size()));
} }
void ShaderAsset::unpack_to(BlobTag tag, lsd::span<byte> destination) const void ShaderAsset::unpack_to(BlobTag tag, std::span<std::byte> destination) const
{ {
debug::ensure( debug::ensure(
tag == BlobTag::code, tag == BlobTag::code,
"Invalid blob tag for shader asset: {}", "Invalid blob tag for shader asset: {}",
lsd::to_underlying(tag) std::to_underlying(tag)
); );
debug::ensure( debug::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: {}",
lsd::to_underlying(tag), std::to_underlying(tag),
bit_cast<size_t>(destination.data()), std::bit_cast<std::size_t>(destination.data()),
destination.size(), destination.size(),
m_code_blob_metadata.uncompressed_size m_code_blob_metadata.uncompressed_size
); );
m_stream.seekg(static_cast<stream_size>(m_code_blob_metadata.offset)); m_stream.seekg(static_cast<long long>(m_code_blob_metadata.offset));
m_stream.read( m_stream.read(
bit_cast<char *>(destination.data()), std::bit_cast<char *>(destination.data()),
static_cast<stream_size>(m_code_blob_metadata.uncompressed_size) static_cast<long long>(m_code_blob_metadata.uncompressed_size)
); );
} }
@ -220,7 +220,7 @@ void ShaderAsset::unpack_to(BlobTag tag, lsd::span<byte> destination) const
debug::ensure( debug::ensure(
tag == BlobTag::code, tag == BlobTag::code,
"Invalid blob tag for shader asset: {}", "Invalid blob tag for shader asset: {}",
lsd::to_underlying(tag) std::to_underlying(tag)
); );
auto blob = Blob(m_code_blob_metadata.uncompressed_size); auto blob = Blob(m_code_blob_metadata.uncompressed_size);

View file

@ -0,0 +1,12 @@
export module bitwise;
import std;
namespace lt::bitwise {
/* bit-wise */
export constexpr auto bit(std::uint32_t x) -> std::uint32_t
{
return 1u << x;
}
} // namespace lt::bitwise

View file

@ -1,19 +1,19 @@
export module camera.components; export module camera.components;
import lsd; import math.vec4;
export namespace lt::camera::components { namespace lt::camera::components {
struct PerspectiveCamera export struct PerspectiveCamera
{ {
f32 vertical_fov {}; float vertical_fov {};
f32 near_plane {}; float near_plane {};
f32 far_plane {}; float far_plane {};
f32 aspect_ratio {}; float aspect_ratio {};
lsd::vec4 background_color; math::vec4 background_color;
bool is_primary {}; bool is_primary {};
}; };

View file

@ -1,36 +1,43 @@
export module debug.assertions; export module debug.assertions;
import lsd; import std;
export namespace lt::debug { namespace lt::debug {
template<typename Expression_T, typename... Args_T> ///////////////////////////////////////
// ----------* INTERFACE *--------- //
/////////////////////////////////////
export template<typename Expression_T, typename... Args_T>
struct ensure struct ensure
{ {
ensure( ensure(
const Expression_T &expression, const Expression_T &expression,
lsd::format_str<Args_T...> fmt, std::format_string<Args_T...> fmt,
Args_T &&...args, Args_T &&...args,
const lsd::src_location &location = lsd::src_location::current() const std::source_location &location = std::source_location::current()
); );
}; };
template<typename Expression_T, typename... Args_T> export template<typename Expression_T, typename... Args_T>
ensure(Expression_T, lsd::format_str<Args_T...>, Args_T &&...) -> ensure<Expression_T, 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> template<typename Expression_T, typename... Args_T>
ensure<Expression_T, Args_T...>::ensure( ensure<Expression_T, Args_T...>::ensure(
const Expression_T &expression, const Expression_T &expression,
lsd::format_str<Args_T...> fmt, std::format_string<Args_T...> fmt,
Args_T &&...args, Args_T &&...args,
const lsd::src_location &location const std::source_location &location
) )
{ {
if (!static_cast<bool>(expression)) if (!static_cast<bool>(expression))
{ {
throw lsd::runtime_error { lsd::format( throw std::runtime_error { std::format(
"exception: {}\nlocation: {}:{}", "exception: {}\nlocation: {}:{}",
lsd::format(fmt, lsd::forward<Args_T>(args)...), std::format(fmt, std::forward<Args_T>(args)...),
location.file_name(), location.file_name(),
location.line() location.line()
) }; ) };

View file

@ -0,0 +1,146 @@
export module debug.instrumentor;
import std;
import logger;
namespace lt::debug {
struct ScopeProfileResult
{
std::string name;
long long start, duration;
std::uint32_t threadID;
};
class Instrumentor
{
public:
static auto instance() -> Instrumentor &
{
static auto instance = Instrumentor {};
return instance;
}
static void begin_session(const std::string &outputPath)
{
instance().begin_session_impl(outputPath);
}
static void end_session()
{
instance().end_session_impl();
}
static void submit_scope_profile(const ScopeProfileResult &profileResult)
{
instance().submit_scope_profile_impl(profileResult);
}
private:
std::ofstream m_output_file_stream;
unsigned int m_current_session_count { 0u };
Instrumentor() = default;
void begin_session_impl(const std::string &outputPath);
void end_session_impl();
void submit_scope_profile_impl(const ScopeProfileResult &profileResult);
};
class InstrumentorTimer
{
public:
InstrumentorTimer(const std::string &scopeName);
~InstrumentorTimer();
private:
ScopeProfileResult m_result;
std::chrono::time_point<std::chrono::steady_clock> m_start;
};
} // namespace lt::debug
/* scope */
#define lt_profile_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_profile_scope_no_redifinition2(name, line) InstrumentorTimer timer##line(name)
/* function */
#define LT_PROFILE_FUNCTION lt_profile_scope(__FUNCSIG__)
/* session */
#define lt_profile_begin_session(outputPath) ::lt::Instrumentor::begin_session(outputPath)
#define lt_profile_end_session() ::lt::Instrumentor::end_session()
module :private;
namespace lt::debug {
void Instrumentor::begin_session_impl(const std::string &outputPath)
{
std::filesystem::create_directory(outputPath.substr(0, outputPath.find_last_of('/') + 1));
m_output_file_stream.open(outputPath);
m_output_file_stream << "{\"traceEvents\":[";
}
void Instrumentor::end_session_impl()
{
if (m_current_session_count == 0u)
{
log::warn("0 profiling for the ended session");
}
m_current_session_count = 0u;
m_output_file_stream << "]}";
m_output_file_stream.flush();
m_output_file_stream.close();
}
void Instrumentor::submit_scope_profile_impl(const ScopeProfileResult &profileResult)
{
if (m_current_session_count++ == 0u)
{
m_output_file_stream << "{";
}
else
{
m_output_file_stream << ",{";
}
m_output_file_stream << R"("name":")" << profileResult.name << "\",";
m_output_file_stream << R"("cat": "scope",)";
m_output_file_stream << R"("ph": "X",)";
m_output_file_stream << "\"ts\":" << profileResult.start << ",";
m_output_file_stream << "\"dur\":" << profileResult.duration << ",";
m_output_file_stream << "\"pid\":0,";
m_output_file_stream << "\"tid\":" << profileResult.threadID << "";
m_output_file_stream << "}";
}
InstrumentorTimer::InstrumentorTimer(const std::string &scopeName)
: m_result({ .name = scopeName, .start = 0, .duration = 0, .threadID = 0 })
, m_start(std::chrono::steady_clock::now())
{
}
InstrumentorTimer::~InstrumentorTimer()
{
auto end = std::chrono::steady_clock::now();
m_result.start = std::chrono::time_point_cast<std::chrono::microseconds>(m_start)
.time_since_epoch()
.count();
m_result.duration = std::chrono::time_point_cast<std::chrono::microseconds>(end)
.time_since_epoch()
.count()
- m_result.start;
Instrumentor::submit_scope_profile(m_result);
}
} // namespace lt::debug

View file

@ -1,13 +1,13 @@
export module ecs.sparse_set; export module ecs.sparse_set;
import debug.assertions; import debug.assertions;
import lsd; import std;
export namespace lt::ecs { namespace lt::ecs {
/** /**
* @ref https://programmingpraxis.com/2012/03/09/sparse-sets/ * @ref https://programmingpraxis.com/2012/03/09/sparse-sets/
*/ */
template<typename Identifier_T = u32> export template<typename Identifier_T = std::uint32_t>
class TypeErasedSparseSet class TypeErasedSparseSet
{ {
public: public:
@ -26,17 +26,17 @@ public:
virtual void remove(Identifier_T identifier) = 0; virtual void remove(Identifier_T identifier) = 0;
}; };
template<typename Value_T, typename Identifier_T = u32> export template<typename Value_T, typename Identifier_T = std::uint32_t>
class SparseSet: public TypeErasedSparseSet<Identifier_T> class SparseSet: public TypeErasedSparseSet<Identifier_T>
{ {
public: public:
using Dense_T = std::pair<Identifier_T, Value_T>; using Dense_T = std::pair<Identifier_T, Value_T>;
static constexpr auto max_capacity = size_t { 1'000'000 }; static constexpr auto max_capacity = std::size_t { 1'000'000 };
static constexpr auto null_identifier = lsd::numeric_limits<Identifier_T>().max(); static constexpr auto null_identifier = std::numeric_limits<Identifier_T>().max();
explicit SparseSet(size_t initial_capacity = 1) explicit SparseSet(std::size_t initial_capacity = 1)
{ {
debug::ensure( debug::ensure(
initial_capacity <= max_capacity, initial_capacity <= max_capacity,
@ -53,7 +53,10 @@ public:
{ {
if (m_sparse.size() < identifier + 1) if (m_sparse.size() < identifier + 1)
{ {
auto new_capacity = std::max(static_cast<size_t>(identifier + 1), m_sparse.size() * 2); auto new_capacity = std::max(
static_cast<std::size_t>(identifier + 1),
m_sparse.size() * 2
);
new_capacity = std::min(new_capacity, max_capacity); new_capacity = std::min(new_capacity, max_capacity);
// log::debug("Increasing sparse vector size:", m_dead_count); // log::debug("Increasing sparse vector size:", m_dead_count);
@ -119,12 +122,12 @@ public:
&& m_dense[m_sparse[identifier]].first == identifier; && m_dense[m_sparse[identifier]].first == identifier;
} }
auto begin() -> lsd::vector<Dense_T>::iterator auto begin() -> std::vector<Dense_T>::iterator
{ {
return m_dense.begin(); return m_dense.begin();
} }
auto end() -> lsd::vector<Dense_T>::iterator auto end() -> std::vector<Dense_T>::iterator
{ {
return m_dense.end(); return m_dense.end();
} }
@ -143,15 +146,15 @@ public:
[[nodiscard]] auto &&operator[](this auto &&self, Identifier_T identifier) [[nodiscard]] auto &&operator[](this auto &&self, Identifier_T identifier)
{ {
using Self_T = decltype(self); using Self_T = decltype(self);
return lsd::forward<Self_T>(self).m_dense[lsd::forward<Self_T>(self).m_sparse[identifier]]; return std::forward<Self_T>(self).m_dense[std::forward<Self_T>(self).m_sparse[identifier]];
} }
[[nodiscard]] auto get_size() const noexcept -> size_t [[nodiscard]] auto get_size() const noexcept -> std::size_t
{ {
return m_alive_count; return m_alive_count;
} }
[[nodiscard]] auto get_capacity() const noexcept -> size_t [[nodiscard]] auto get_capacity() const noexcept -> std::size_t
{ {
return m_sparse.capacity(); return m_sparse.capacity();
} }
@ -162,13 +165,13 @@ public:
} }
private: private:
lsd::vector<Dense_T> m_dense; std::vector<Dense_T> m_dense;
lsd::vector<Identifier_T> m_sparse; std::vector<Identifier_T> m_sparse;
size_t m_alive_count {}; std::size_t m_alive_count {};
size_t m_dead_count {}; std::size_t m_dead_count {};
}; };
} // namespace lt::ecs } // namespace lt::ecs

View file

@ -1,9 +1,10 @@
export module env; export module env;
import lsd;
export namespace lt { import std;
enum class Platform : u8 namespace lt {
enum class Platform : std::uint8_t
{ {
/** The GNU/Linux platform. /** The GNU/Linux platform.
* Tested on the following distros: arch-x86_64 * Tested on the following distros: arch-x86_64
@ -25,7 +26,7 @@ enum class Platform : u8
}; };
/** The compiler that was used for compiling the project. */ /** The compiler that was used for compiling the project. */
enum class Compiler : u8 enum class Compiler : std::uint8_t
{ {
clang, clang,
gcc, gcc,
@ -35,25 +36,19 @@ enum class Compiler : u8
namespace constants { namespace constants {
#define lt_windows_only(x)
#define lt_linux_only(x)
#define lt_mac_only(x)
#if defined(LIGHT_PLATFORM_WINDOWS) #if defined(LIGHT_PLATFORM_WINDOWS)
// NOLINTNEXTLINE #define lt_win(x)
#define lt_windows_only(x) x
constexpr auto platform = Platform::windows; constexpr auto platform = Platform::windows;
constexpr auto platform_name = "windows"; constexpr auto platform_name = "windows";
#undef LIGHT_PLATFORM_WINDOWS
#elif defined(LIGHT_PLATFORM_LINUX) #elif defined(LIGHT_PLATFORM_LINUX)
// NOLINTNEXTLINE
#define lt_linux_only(x) x
constexpr auto platform = Platform::gnu_linux; constexpr auto platform = Platform::gnu_linux;
constexpr auto platform_name = "gnu_linux"; constexpr auto platform_name = "gnu_linux";
#elif defined(LIGHT_PLATFORM_MAC) #elif defined(LIGHT_PLATFORM_MAC)
// NOLINTNEXTLINE #define lt_mac(x) x
#define lt_mac_only(x) x
constexpr auto platform = Platform::mac; constexpr auto platform = Platform::mac;
constexpr auto platform_name = "mac"; constexpr auto platform_name = "mac";

View file

@ -1,49 +1,50 @@
export module logger; export module logger;
import lsd;
import std;
namespace lt::log { namespace lt::log {
auto thread_hash_id() noexcept -> u64
{
return static_cast<u64>(lsd::hash<lsd::thread_id> {}(lsd::this_thread_id()));
}
} // namespace lt::log
export namespace lt::log {
/** Severity of a log message. */ /** Severity of a log message. */
enum class Level : u8 enum class Level : std::uint8_t
{ {
/** Lowest and most vebose log level, for tracing execution paths and events */ /** Lowest and most vebose log level, for tracing execution paths and events */
trace = 0u, trace = 0,
/** Vebose log level, for enabling temporarily to debug */ /** Vebose log level, for enabling temporarily to debug */
debug = 1u, debug = 1,
/** General information */ /** General information */
info = 2u, info = 2,
/** Things we should to be aware of and edge cases */ /** Things we should to be aware of and edge cases */
warn = 3u, warn = 3,
/** Defects, bugs and undesired behaviour */ /** Defects, bugs and undesired behaviour */
error = 4u, error = 4,
/** Unrecoverable errors */ /** Unrecoverable errors */
critical = 5u, critical = 5,
/** No logging */ /** No logging */
off = 6u, off = 6,
}; };
namespace details {
inline auto thread_hash_id() noexcept -> std::uint64_t
{
return static_cast<std::uint64_t>(std::hash<std::thread::id> {}(std::this_thread::get_id()));
}
} // namespace details
template<typename... Args> template<typename... Args>
struct [[maybe_unused]] print struct [[maybe_unused]] print
{ {
[[maybe_unused]] print( [[maybe_unused]] print(
Level level, Level level,
const lsd::src_location &location, const std::source_location &location,
lsd::format_str<Args...> format, std::format_string<Args...> format,
Args &&...arguments Args &&...arguments
) noexcept ) noexcept
{ {
@ -62,118 +63,118 @@ struct [[maybe_unused]] print
} }
// clang-format on // clang-format on
lsd::unreachable(); std::unreachable();
}; };
const auto path = lsd::file::path { location.file_name() }; const auto path = std::filesystem::path { location.file_name() };
lsd::println( std::println(
"{} {} ==> {}", "{} {} ==> {}",
to_string(level, location), to_string(level, location),
lsd::format("{}:{}", path.filename().string(), location.line()), std::format("{}:{}", path.filename().string(), location.line()),
lsd::format(format, lsd::forward<Args>(arguments)...) std::format(format, std::forward<Args>(arguments)...)
); );
} }
}; };
template<typename... Args> template<typename... Args>
print(Level, const lsd::src_location &, lsd::format_str<Args...>, Args &&...) noexcept print(Level, const std::source_location &, std::format_string<Args...>, Args &&...) noexcept
-> print<Args...>; -> print<Args...>;
template<typename... Args> export template<typename... Args>
struct [[maybe_unused]] trace struct [[maybe_unused]] trace
{ {
[[maybe_unused]] trace( [[maybe_unused]] trace(
lsd::format_str<Args...> format, std::format_string<Args...> format,
Args &&...arguments, Args &&...arguments,
const lsd::src_location &location = lsd::src_location::current() const std::source_location &location = std::source_location::current()
) noexcept ) noexcept
{ {
print(Level::trace, location, format, lsd::forward<Args>(arguments)...); print(Level::trace, location, format, std::forward<Args>(arguments)...);
} }
}; };
template<typename... Args> export template<typename... Args>
trace(lsd::format_str<Args...>, Args &&...) noexcept -> trace<Args...>; trace(std::format_string<Args...>, Args &&...) noexcept -> trace<Args...>;
template<typename... Args> export template<typename... Args>
struct [[maybe_unused]] debug struct [[maybe_unused]] debug
{ {
[[maybe_unused]] debug( [[maybe_unused]] debug(
lsd::format_str<Args...> format, std::format_string<Args...> format,
Args &&...arguments, Args &&...arguments,
const lsd::src_location &location = lsd::src_location::current() const std::source_location &location = std::source_location::current()
) noexcept ) noexcept
{ {
print(Level::debug, location, format, lsd::forward<Args>(arguments)...); print(Level::debug, location, format, std::forward<Args>(arguments)...);
} }
}; };
template<typename... Args> export template<typename... Args>
debug(lsd::format_str<Args...>, Args &&...) noexcept -> debug<Args...>; debug(std::format_string<Args...>, Args &&...) noexcept -> debug<Args...>;
template<typename... Args> export template<typename... Args>
struct [[maybe_unused]] info struct [[maybe_unused]] info
{ {
[[maybe_unused]] info( [[maybe_unused]] info(
lsd::format_str<Args...> format, std::format_string<Args...> format,
Args &&...arguments, Args &&...arguments,
const lsd::src_location &location = lsd::src_location::current() const std::source_location &location = std::source_location::current()
) noexcept ) noexcept
{ {
print(Level::info, location, format, lsd::forward<Args>(arguments)...); print(Level::info, location, format, std::forward<Args>(arguments)...);
} }
}; };
template<typename... Args> export template<typename... Args>
info(lsd::format_str<Args...>, Args &&...) noexcept -> info<Args...>; info(std::format_string<Args...>, Args &&...) noexcept -> info<Args...>;
template<typename... Args> export template<typename... Args>
struct [[maybe_unused]] warn struct [[maybe_unused]] warn
{ {
[[maybe_unused]] warn( [[maybe_unused]] warn(
lsd::format_str<Args...> format, std::format_string<Args...> format,
Args &&...arguments, Args &&...arguments,
const lsd::src_location &location = lsd::src_location::current() const std::source_location &location = std::source_location::current()
) noexcept ) noexcept
{ {
print(Level::warn, location, format, lsd::forward<Args>(arguments)...); print(Level::warn, location, format, std::forward<Args>(arguments)...);
} }
}; };
template<typename... Args> export template<typename... Args>
warn(lsd::format_str<Args...>, Args &&...) noexcept -> warn<Args...>; warn(std::format_string<Args...>, Args &&...) noexcept -> warn<Args...>;
template<typename... Args> export template<typename... Args>
struct [[maybe_unused]] error struct [[maybe_unused]] error
{ {
[[maybe_unused]] error( [[maybe_unused]] error(
lsd::format_str<Args...> format, std::format_string<Args...> format,
Args &&...arguments, Args &&...arguments,
const lsd::src_location &location = lsd::src_location::current() const std::source_location &location = std::source_location::current()
) noexcept ) noexcept
{ {
print(Level::error, location, format, lsd::forward<Args>(arguments)...); print(Level::error, location, format, std::forward<Args>(arguments)...);
} }
}; };
template<typename... Args> export template<typename... Args>
error(lsd::format_str<Args...>, Args &&...) noexcept -> error<Args...>; error(std::format_string<Args...>, Args &&...) noexcept -> error<Args...>;
template<typename... Args> export template<typename... Args>
struct [[maybe_unused]] critical struct [[maybe_unused]] critical
{ {
[[maybe_unused]] critical( [[maybe_unused]] critical(
lsd::format_str<Args...> format, std::format_string<Args...> format,
Args &&...arguments, Args &&...arguments,
const lsd::src_location &location = lsd::src_location::current() const std::source_location &location = std::source_location::current()
) noexcept ) noexcept
{ {
print(Level::critical, location, format, lsd::forward<Args>(arguments)...); print(Level::critical, location, format, std::forward<Args>(arguments)...);
} }
}; };
template<typename... Args> export template<typename... Args>
critical(lsd::format_str<Args...>, Args &&...) noexcept -> critical<Args...>; critical(std::format_string<Args...>, Args &&...) noexcept -> critical<Args...>;
} // namespace lt::log } // namespace lt::log

View file

@ -1,9 +0,0 @@
export module lsd.algorithm;
import std;
export namespace lt::lsd {
using ::std::remove;
using ::std::remove_if;
} // namespace lt::lsd

View file

@ -1,10 +0,0 @@
export module lsd.arr;
import lsd.primitives;
import std;
export namespace lt::lsd {
template<typename T, size_t size>
using arr = std::array<T, size>;
}

View file

@ -1,11 +0,0 @@
export module lsd.bitwise;
export namespace lt::lsd {
/* bit-wise */
constexpr auto bit(auto x)
{
return 1u << x;
}
} // namespace lt::lsd

View file

@ -1,13 +0,0 @@
export module lsd.chrono;
import std;
export namespace lt::lsd::chrono {
using std::chrono::duration;
using std::chrono::steady_clock;
using std::chrono::time_point;
using std::chrono::time_point_cast;
using std::chrono::milliseconds;
} // namespace lt::lsd::chrono

View file

@ -1,9 +0,0 @@
export module lsd.concepts;
import std;
export namespace lt::lsd {
using std::invocable;
}

View file

@ -1,10 +0,0 @@
export module lsd.exceptions;
import std;
export namespace lt::lsd {
using std::exception;
using std::runtime_error;
} // namespace lt::lsd

View file

@ -1,16 +0,0 @@
export module lsd.filesystem;
import std;
export namespace lt::lsd::file {
using path = ::std::filesystem::path;
using ::std::filesystem::remove;
using in_stream = ::std::ifstream;
using out_stream = ::std::ofstream;
constexpr auto ios_binary = std::ios::binary;
constexpr auto ios_end = std::ios::end;
constexpr auto ios_beg = std::ios::beg;
} // namespace lt::lsd::file

View file

@ -1,8 +0,0 @@
export module lsd.hash;
import std;
export namespace lt::lsd {
template<typename T>
using hash = std::hash<T>;
}

View file

@ -1,12 +0,0 @@
export module lsd.literals;
import lsd.str;
import std;
export namespace lt {
constexpr str_view operator""sv(const char *str, unsigned long len) noexcept
{
return str_view { str, len };
}
} // namespace lt

View file

@ -1,27 +0,0 @@
export module lsd;
export import lsd.set;
export import lsd.vec;
export import lsd.arr;
export import lsd.str;
export import lsd.hash;
export import lsd.span;
export import lsd.utils;
export import lsd.thread;
export import lsd.chrono;
export import lsd.ref_ptr;
export import lsd.bitwise;
export import lsd.concepts;
export import lsd.scope_ptr;
export import lsd.exceptions;
export import lsd.primitives;
export import lsd.filesystem;
export import lsd.src_location;
export import lsd.math.vec2;
export import lsd.math.vec3;
export import lsd.math.vec4;
export import lsd.math.mat4;
export import lsd.math.algebra;
export import lsd.math.trig;
export import lsd.algorithm;

View file

@ -1,9 +0,0 @@
export module lsd.bitwise;
import std;
export namespace lt::lsd {
template<typename T>
using set = std::set<T>;
}

View file

@ -1,104 +0,0 @@
export module lsd.math.vec4;
import lsd.math.vec2;
import lsd.math.vec3;
import lsd.primitives;
import lsd.arr;
import lsd.str;
export namespace lt::lsd {
template<typename T>
struct vec4_impl
{
constexpr vec4_impl() = default;
constexpr explicit vec4_impl(T scalar): x(scalar), y(scalar), z(scalar), w(scalar)
{
}
constexpr vec4_impl(T x, T y, T z, T w): x(x), y(y), z(z), w(w)
{
}
[[nodiscard]] auto operator==(const vec4_impl<T> &other) const -> bool
{
return x == other.x && y == other.y && z == other.z && w == other.w;
}
[[nodiscard]] auto operator!=(const vec4_impl<T> &other) const -> bool
{
return !(*this == other);
}
[[nodiscard]] constexpr auto operator-(const vec4_impl<T> &other) const -> vec4_impl
{
return {
x - other.x,
y - other.y,
z - other.z,
w - other.w,
};
}
[[nodiscard]] constexpr auto operator[](size_t idx) -> T &
{
return values[idx];
}
[[nodiscard]] constexpr auto operator[](size_t idx) const -> const T &
{
return values[idx];
}
// NOLINTNEXTLINE
union
{
struct
{
T x;
T y;
T z;
T w;
};
struct
{
T r;
T g;
T b;
T a;
};
struct
{
lsd::arr<T, 4uz> values;
};
};
};
using vec4 = vec4_impl<f32>;
using ivec4 = vec4_impl<i32>;
using uvec4 = vec4_impl<u32>;
} // namespace lt::lsd
export template<typename T>
struct lt::lsd::formatter<lt::lsd::vec4_impl<T>>
{
constexpr auto parse(lt::lsd::format_parse_context &context)
{
return context.begin();
}
auto format(const lt::lsd::vec4_impl<T> &val, lt::lsd::format_context &context) const
{
return lt::lsd::format_to(context.out(), "{}, {}, {}, {}", val.x, val.y, val.z, val.w);
}
};

View file

@ -1,8 +0,0 @@
export module lsd.numeric_limits;
import std;
export namespace lt::lsd {
using ::std::numeric_limits;
}

View file

@ -1,34 +0,0 @@
export module lsd.primitives;
import std;
/** THIS IS AND SHALL BE THE ONLY NAMESPACE FROM LT
THAT HAS NO SUB-NAMESPACE IDENTIFIER. */
export namespace lt {
using byte = ::std::byte;
using u8 = ::std::uint8_t;
using u16 = ::std::uint16_t;
using u32 = ::std::uint32_t;
using u64 = ::std::uint64_t;
using i8 = ::std::int8_t;
using i16 = ::std::int16_t;
using i32 = ::std::int32_t;
using i64 = ::std::int64_t;
using f32 = float;
using f64 = double;
using size_t = ::std::size_t;
using stream_size = ::std::streamsize;
// The fact that bit_cast is a part of the standard library,
// rather than a builtin like static_cast is language quirk.
//
// From the end-user's perspective, it would be convenient
// for the bit_cast to be a language keyword.
using ::std::bit_cast;
} // namespace lt

View file

@ -1,9 +0,0 @@
export module lsd.set;
import std;
namespace lt::lsd {
template<typename T>
using set = std::set<T>;
}

View file

@ -1,6 +0,0 @@
export module lsd.span;
import std;
export namespace lt::lsd {
using ::std::span;
}

View file

@ -1,8 +0,0 @@
export module lsd.src_location;
import std;
export namespace lt::lsd {
using src_location = std::source_location;
}

View file

@ -1,20 +0,0 @@
export module lsd.str;
import std;
export namespace lt::lsd {
using c_str = const char *;
using str = std::string;
using str_view = std::string_view;
template<typename... T>
using format_str = std::format_string<T...>;
using std::format_context;
using std::format_parse_context;
using std::format_to;
using std::formatter;
} // namespace lt::lsd

View file

@ -1,13 +0,0 @@
export module lsd.thread;
import std;
export namespace lt::lsd {
using thread_id = std::thread::id;
[[nodiscard]] auto this_thread_id() -> thread_id
{
return std::this_thread::get_id();
}
} // namespace lt::sd

View file

@ -1,30 +0,0 @@
export module lsd.utils;
import std;
export namespace lt::lsd {
[[noreturn]] void unreachable() noexcept
{
#if defined(__clang__) || defined(__GNUC__)
__builtin_unreachable();
#elif defined(_MSC_VER)
std::terminate();
__assume(0);
#else
std::terminate();
#endif
}
// NOLINTBEGIN
using ::std::bit_cast;
using ::std::declval;
using ::std::format;
using ::std::forward;
using ::std::move;
using ::std::println;
using ::std::system;
using ::std::to_underlying;
// NOLINTEND
} // namespace lt::lsd

View file

@ -1,9 +0,0 @@
export module lsd.vec;
import std;
export namespace lt::lsd {
template<typename T>
using vec = std::vector<T>;
}

View file

@ -1,8 +1,8 @@
export module lsd.math.algebra; export module math.algebra;
import lsd.math.mat4; import math.mat4;
import lsd.math.trig; import std;
export namespace lt::lsd { export namespace lt::math {
/** /**
* let... * let...
@ -37,19 +37,19 @@ export namespace lt::lsd {
template<typename T> template<typename T>
constexpr auto perspective(T field_of_view, T aspect_ratio, T z_near, T z_far) constexpr auto perspective(T field_of_view, T aspect_ratio, T z_near, T z_far)
{ {
const T half_fov_tan = tan(field_of_view / static_cast<T>(2u)); const T half_fov_tan = std::tan(field_of_view / static_cast<T>(2));
auto result = mat4_impl<T>::identity(); auto result = mat4_impl<T>::identity();
result[0][0] = T { 1u } / (aspect_ratio * half_fov_tan); result[0][0] = T { 1 } / (aspect_ratio * half_fov_tan);
// //
result[1][1] = T { 1u } / (half_fov_tan); result[1][1] = T { 1 } / (half_fov_tan);
// //
// result[2][2] = -(z_far + z_near) / (z_far - z_near); // result[2][2] = -(z_far + z_near) / (z_far - z_near);
// //
result[2][2] = z_far / (z_far - z_near); result[2][2] = z_far / (z_far - z_near);
// //
result[2][3] = -T { 1u }; result[2][3] = -T { 1 };
// //
// result[3][2] = -(T { 2 } * z_far * z_near) / (z_far - z_near); // result[3][2] = -(T { 2 } * z_far * z_near) / (z_far - z_near);
result[3][2] = -(z_far * z_near) / (z_far - z_near); result[3][2] = -(z_far * z_near) / (z_far - z_near);
@ -57,4 +57,4 @@ constexpr auto perspective(T field_of_view, T aspect_ratio, T z_near, T z_far)
return result; return result;
} }
} // namespace lt::lsd } // namespace lt::math

View file

@ -1,27 +1,24 @@
export module lsd.math.mat4; export module math.mat4;
import lsd.math.vec2; import math.vec3;
import lsd.math.vec3; import math.vec4;
import lsd.math.vec4; import std;
import lsd.primitives;
import lsd.arr;
import lsd.str;
export namespace lt::lsd { namespace lt::math {
template<typename T> export template<typename T = float>
struct mat4_impl struct mat4_impl
{ {
using Column_T = vec4_impl<T>; using Column_T = vec4_impl<T>;
constexpr mat4_impl() = default;
constexpr explicit mat4_impl(T scalar = 0) constexpr explicit mat4_impl(T scalar = 0)
: values({ : values(
{
Column_T { scalar }, Column_T { scalar },
Column_T { scalar }, Column_T { scalar },
Column_T { scalar }, Column_T { scalar },
Column_T { scalar }, Column_T { scalar },
}) }
)
{ {
} }
@ -57,12 +54,12 @@ struct mat4_impl
}; };
} }
[[nodiscard]] constexpr auto operator[](size_t idx) -> Column_T & [[nodiscard]] constexpr auto operator[](std::size_t idx) -> Column_T &
{ {
return values[idx]; return values[idx];
} }
[[nodiscard]] constexpr auto operator[](size_t idx) const -> const Column_T & [[nodiscard]] constexpr auto operator[](std::size_t idx) const -> const Column_T &
{ {
return values[idx]; return values[idx];
} }
@ -77,37 +74,37 @@ struct mat4_impl
return vec4_impl<T> {}; return vec4_impl<T> {};
} }
lsd::arr<Column_T, 4uz> values; // NOLINT std::array<Column_T, 4> values; // NOLINT
}; };
template<typename T> export template<typename T>
[[nodiscard]] auto translate(const vec3_impl<T> &value) -> mat4_impl<T> [[nodiscard]] auto translate(const vec3_impl<T> &value) -> mat4_impl<T>
{ {
return mat4_impl<T> {}; return mat4_impl<T> {};
} }
template<typename T> export template<typename T>
[[nodiscard]] auto rotate(f32 value, const vec3_impl<T> &xyz) -> mat4_impl<T> [[nodiscard]] auto rotate(float value, const vec3_impl<T> &xyz) -> mat4_impl<T>
{ {
return mat4_impl<T> {}; return mat4_impl<T> {};
} }
template<typename T> export template<typename T>
[[nodiscard]] auto scale(const vec3_impl<T> &value) -> mat4_impl<T> [[nodiscard]] auto scale(const vec3_impl<T> &value) -> mat4_impl<T>
{ {
return mat4_impl<T> {}; return mat4_impl<T> {};
} }
template<typename T> export template<typename T>
[[nodiscard]] auto inverse(const mat4_impl<T> &value) -> mat4_impl<T> [[nodiscard]] auto inverse(const mat4_impl<T> &value) -> mat4_impl<T>
{ {
return mat4_impl<T> {}; return mat4_impl<T> {};
} }
using mat4 = mat4_impl<f32>; export using mat4 = mat4_impl<float>;
using imat4 = mat4_impl<i32>; export using imat4 = mat4_impl<std::int32_t>;
using umat4 = mat4_impl<u32>; export using umat4 = mat4_impl<std::uint32_t>;
} // namespace lt::lsd } // namespace lt::math

View file

@ -1,11 +1,6 @@
export module lsd.math.trig; export module math.trig;
import std;
export namespace lt::lsd { export namespace lt::math {
using ::std::cos;
using ::std::sin;
using ::std::tan;
[[nodiscard]] constexpr auto radians(float degrees) -> float [[nodiscard]] constexpr auto radians(float degrees) -> float
{ {
@ -28,4 +23,4 @@ using ::std::tan;
} }
} // namespace lt::lsd } // namespace lt::math

View file

@ -1,14 +1,15 @@
export module lsd.math.vec2; export module math.vec2;
import lsd.primitives;
import lsd.str;
export namespace lt::lsd { import std;
template<typename T> namespace lt::math {
export template<typename T = float>
struct vec2_impl struct vec2_impl
{ {
constexpr vec2_impl() = default; constexpr vec2_impl(): x(), y()
{
}
constexpr explicit vec2_impl(T scalar): x(scalar), y(scalar) constexpr explicit vec2_impl(T scalar): x(scalar), y(scalar)
{ {
@ -44,7 +45,7 @@ struct vec2_impl
}; };
} }
[[nodiscard]] auto operator*(f32 scalar) const -> vec2_impl [[nodiscard]] auto operator*(float scalar) const -> vec2_impl
{ {
return { return {
x * scalar, x * scalar,
@ -58,26 +59,24 @@ struct vec2_impl
}; };
using vec2 = vec2_impl<f32>; export using vec2 = vec2_impl<float>;
using dvec2 = vec2_impl<f64>; export using ivec2 = vec2_impl<std::int32_t>;
using ivec2 = vec2_impl<i32>; export using uvec2 = vec2_impl<std::uint32_t>;
using uvec2 = vec2_impl<u32>; } // namespace lt::math
} // namespace lt::lsd
export template<typename T> export template<typename T>
struct lt::lsd::formatter<lt::lsd::vec2_impl<T>> struct std::formatter<lt::math::vec2_impl<T>>
{ {
constexpr auto parse(lt::lsd::format_parse_context &context) constexpr auto parse(std::format_parse_context &context)
{ {
return context.begin(); return context.begin();
} }
auto format(const lt::lsd::vec2_impl<T> &val, lt::lsd::format_context &context) const auto format(const lt::math::vec2_impl<T> &val, std::format_context &context) const
{ {
return lt::lsd::format_to(context.out(), "{}, {}", val.x, val.y); return std::format_to(context.out(), "{}, {}", val.x, val.y);
} }
}; };

View file

@ -1,16 +1,16 @@
export module lsd.math.vec3; export module math.vec3;
import lsd.math.vec2; import math.vec2;
import lsd.primitives; import std;
import lsd.str;
export namespace lt::lsd { namespace lt::math {
template<typename T> export template<typename T = float>
struct vec3_impl struct vec3_impl
{ {
constexpr vec3_impl() = default; constexpr vec3_impl(): x(), y(), z()
{
}
constexpr explicit vec3_impl(T scalar): x(scalar), y(scalar), z(scalar) constexpr explicit vec3_impl(T scalar): x(scalar), y(scalar), z(scalar)
{ {
@ -48,11 +48,11 @@ struct vec3_impl
}; };
} }
// friend auto operator<<(std::ostream &stream, vec3_impl<T> value) -> std::ostream & friend auto operator<<(std::ostream &stream, vec3_impl<T> value) -> std::ostream &
// { {
// stream << value.x << ", " << value.y << ", " << value.z; stream << value.x << ", " << value.y << ", " << value.z;
// return stream; return stream;
// } }
T x; // NOLINT T x; // NOLINT
@ -61,26 +61,24 @@ struct vec3_impl
T z; // NOLINT T z; // NOLINT
}; };
using vec3 = vec3_impl<f32>; export using vec3 = vec3_impl<float>;
using dvec3 = vec3_impl<f32>; export using ivec3 = vec3_impl<std::int32_t>;
using ivec3 = vec3_impl<i32>; export using uvec3 = vec3_impl<std::uint32_t>;
using uvec3 = vec3_impl<u32>; } // namespace lt::math
} // namespace lt::lsd
template<typename T> template<typename T>
struct lt::lsd::formatter<lt::lsd::vec3_impl<T>> struct std::formatter<lt::math::vec3_impl<T>>
{ {
constexpr auto parse(lt::lsd::format_parse_context &context) constexpr auto parse(std::format_parse_context &context)
{ {
return context.begin(); return context.begin();
} }
auto format(const lt::lsd::vec3_impl<T> &val, lt::lsd::format_context &context) const auto format(const lt::math::vec3_impl<T> &val, std::format_context &context) const
{ {
return lt::lsd::format_to(context.out(), "{}, {}, {}", val.x, val.y, val.z); return std::format_to(context.out(), "{}, {}, {}", val.x, val.y, val.z);
} }
}; };

109
modules/math/vec4.cppm Normal file
View file

@ -0,0 +1,109 @@
export module math.vec4;
import math.vec2;
import math.vec3;
import std;
namespace lt::math {
export template<typename T = float>
struct vec4_impl
{
constexpr vec4_impl(): x(), y(), z(), w()
{
}
constexpr explicit vec4_impl(T scalar): x(scalar), y(scalar), z(scalar), w(scalar)
{
}
constexpr vec4_impl(T x, T y, T z, T w): x(x), y(y), z(z), w(w)
{
}
[[nodiscard]] auto operator==(const vec4_impl<T> &other) const -> bool
{
return x == other.x && y == other.y && z == other.z && w == other.w;
}
[[nodiscard]] auto operator!=(const vec4_impl<T> &other) const -> bool
{
return !(*this == other);
}
[[nodiscard]] constexpr auto operator-(const vec4_impl<T> &other) const -> vec4_impl
{
return {
x - other.x,
y - other.y,
z - other.z,
w - other.w,
};
}
[[nodiscard]] constexpr auto operator[](std::size_t idx) -> T &
{
return values[idx];
}
[[nodiscard]] constexpr auto operator[](std::size_t idx) const -> const T &
{
return values[idx];
}
friend auto operator<<(std::ostream &stream, vec4_impl<T> value) -> std::ostream &
{
stream << value.x << ", " << value.y << ", " << value.z << ", " << value.w;
return stream;
}
// NOLINTNEXTLINE
union
{
struct
{
T x;
T y;
T z;
T w;
};
struct
{
T r;
T g;
T b;
T a;
};
struct
{
std::array<T, 4> values;
};
};
};
export using vec4 = vec4_impl<float>;
export using ivec4 = vec4_impl<std::int32_t>;
export using uvec4 = vec4_impl<std::uint32_t>;
} // namespace lt::math
export template<typename T>
struct std::formatter<lt::math::vec4_impl<T>>
{
constexpr auto parse(std::format_parse_context &context)
{
return context.begin();
}
auto format(const lt::math::vec4_impl<T> &val, std::format_context &context) const
{
return std::format_to(context.out(), "{}, {}, {}, {}", val.x, val.y, val.z, val.w);
}
};

View file

@ -0,0 +1,101 @@
export module memory.null_on_move;
import std;
namespace lt::memory {
/** 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
* Vulkan handles. But may serve other purposes, hence why I kept the implementation generic.
*/
export template<typename Underlying_T, Underlying_T null_value = nullptr>
class NullOnMove
{
public:
NullOnMove() = default;
NullOnMove(Underlying_T value): m_value(value)
{
}
~NullOnMove() = default;
NullOnMove(const NullOnMove &) = delete;
auto operator=(const NullOnMove &) -> NullOnMove & = delete;
NullOnMove(NullOnMove &&other) noexcept
{
*this = std::move(other);
}
auto operator=(NullOnMove &&other) noexcept -> NullOnMove &
{
if (this == std::addressof(other))
{
return *this;
}
m_value = other.m_value;
other.m_value = null_value;
return *this;
}
auto operator->() -> Underlying_T
{
return m_value;
}
// NOLINTNEXTLINE
auto operator->() const -> const Underlying_T
{
return m_value;
}
auto operator&() const -> const Underlying_T *
{
return &m_value;
}
auto operator&() -> Underlying_T *
{
return &m_value;
}
operator bool() const
{
return m_value != null_value;
}
operator Underlying_T() const
{
return m_value;
}
operator Underlying_T()
{
return m_value;
}
operator std::uint64_t() const
{
return (std::uint64_t)m_value;
}
[[nodiscard]] auto get() -> Underlying_T &
{
return m_value;
}
[[nodiscard]] auto get() const -> const Underlying_T &
{
return m_value;
}
private:
Underlying_T m_value;
};
} // namespace lt::memory

View file

@ -1,32 +1,32 @@
export module lsd.ref_ptr; export module memory.reference;
import std; import std;
export namespace lt::lsd { namespace lt::memory {
/** Wrapper around std::shared_ptr. /** Wrapper around std::shared_ptr.
* *
* @note Currently just an alias, might turn into an implementation later. * @note Currently just an alias, might turn into an implementation later.
* @ref https://en.cppreference.com/w/cpp/memory/shared_ptr.html * @ref https://en.cppreference.com/w/cpp/memory/shared_ptr.html
*/ */
template<typename T> export template<typename T>
using ref = std::shared_ptr<T>; using Ref = std::shared_ptr<T>;
/** Allocates memory for an `Underlying_T` and directly constructs it there. /** Allocates memory for an `Underlying_T` and directly constructs it there.
* *
* @return A Ref<Underlying_T> to the constructed object. * @return A Ref<Underlying_T> to the constructed object.
*/ */
template<typename Underlying_T, typename... Args> export template<typename Underlying_T, typename... Args>
constexpr auto create_ref(Args &&...args) -> ref<Underlying_T> constexpr Ref<Underlying_T> create_ref(Args &&...args)
{ {
return std::make_shared<Underlying_T>(std::forward<Args>(args)...); return std::make_shared<Underlying_T>(std::forward<Args>(args)...);
} }
/** Converts c-style pointer of type `Underlying_T` to a `Ref<Underlying_T>`. */ /** Converts c-style pointer of type `Underlying_T` to a `Ref<Underlying_T>`. */
template<typename Underlying_T> export template<typename Underlying_T>
constexpr auto make_ref(Underlying_T *raw_pointer) -> ref<Underlying_T> constexpr Ref<Underlying_T> make_ref(Underlying_T *raw_pointer)
{ {
return ref<Underlying_T>(raw_pointer); return Ref<Underlying_T>(raw_pointer);
} }
} // namespace lt::lsd } // namespace lt::memory

View file

@ -1,31 +1,32 @@
export module lsd.scope_ptr; export module memory.scope;
import std; import std;
export namespace lt::lsd { namespace lt::memory {
/** Wrapper around std::unique_ptr. /** @brief Wrapper around std::unique_ptr.
* *
* @note Currently just an alias, might turn into an implementation later. * @note Currently just an alias, might turn into an implementation later.
* @ref https://en.cppreference.com/w/cpp/memory/unique_ptr.html * @ref https://en.cppreference.com/w/cpp/memory/unique_ptr.html
*/ */
template<typename t> export template<typename t>
using scope = std::unique_ptr<t>; using Scope = std::unique_ptr<t>;
/** Allocates memory for an `Underlying_T` and directly constructs it there. /** Allocates memory for an `Underlying_T` and directly constructs it there.
* *
* @return A Scope<Underlying_T> to the constructed object. * @return A Scope<Underlying_T> to the constructed object.
*/ */
template<typename Underlying_T, typename... Args> export template<typename Underlying_T, typename... Args>
constexpr auto create_scope(Args &&...args) -> scope<Underlying_T> constexpr Scope<Underlying_T> create_scope(Args &&...args)
{ {
return std::make_unique<Underlying_T>(std::forward<Args>(args)...); return std::make_unique<Underlying_T>(std::forward<Args>(args)...);
} }
/** Converts c-style pointer of type `Underlying_T` to a `Scope<Underlying_T>`. */ /** Converts c-style pointer of type `Underlying_T` to a `Scope<Underlying_T>`. */
template<typename Underlying_T> export template<typename Underlying_T>
constexpr auto make_scope(Underlying_T *raw_pointer) -> scope<Underlying_T> constexpr Scope<Underlying_T> make_scope(Underlying_T *raw_pointer)
{ {
return scope<Underlying_T>(raw_pointer); return Scope<Underlying_T>(raw_pointer);
} }
} // namespace lt::lsd } // namespace lt::memory

View file

@ -50,96 +50,6 @@ struct overloads: Ts...
using Ts::operator()...; using Ts::operator()...;
}; };
template<typename Underlying_T, Underlying_T null_value = nullptr>
class NullOnMove
{
public:
NullOnMove() = default;
NullOnMove(Underlying_T value): m_value(value)
{
}
~NullOnMove() = default;
NullOnMove(const NullOnMove &) = delete;
auto operator=(const NullOnMove &) -> NullOnMove & = delete;
NullOnMove(NullOnMove &&other) noexcept
{
*this = std::move(other);
}
auto operator=(NullOnMove &&other) noexcept -> NullOnMove &
{
if (this == std::addressof(other))
{
return *this;
}
m_value = other.m_value;
other.m_value = null_value;
return *this;
}
auto operator->() -> Underlying_T
{
return m_value;
}
// NOLINTNEXTLINE
auto operator->() const -> const Underlying_T
{
return m_value;
}
auto operator&() const -> const Underlying_T *
{
return &m_value;
}
auto operator&() -> Underlying_T *
{
return &m_value;
}
operator bool() const
{
return m_value != null_value;
}
operator Underlying_T() const
{
return m_value;
}
operator Underlying_T()
{
return m_value;
}
operator std::uint64_t() const
{
return (std::uint64_t)m_value;
}
[[nodiscard]] auto get() -> Underlying_T &
{
return m_value;
}
[[nodiscard]] auto get() const -> const Underlying_T &
{
return m_value;
}
private:
Underlying_T m_value;
};
export namespace lt::renderer::vk { export namespace lt::renderer::vk {
using Bool32 = VkBool32; using Bool32 = VkBool32;
@ -840,7 +750,7 @@ private:
return m_instance; return m_instance;
} }
NullOnMove<VkInstance> m_instance {}; memory::NullOnMove<VkInstance> m_instance {};
}; };
class Surface class Surface
@ -932,7 +842,7 @@ private:
return m_surface.get(); return m_surface.get();
} }
NullOnMove<VkSurfaceKHR> m_surface {}; memory::NullOnMove<VkSurfaceKHR> m_surface {};
VkInstance m_instance {}; VkInstance m_instance {};
}; };
@ -1419,7 +1329,7 @@ private:
return m_device.get(); return m_device.get();
} }
NullOnMove<VkDevice> m_device {}; memory::NullOnMove<VkDevice> m_device {};
}; };
class Semaphore class Semaphore
@ -1456,7 +1366,7 @@ private:
return &m_semaphore; return &m_semaphore;
} }
NullOnMove<VkDevice> m_device; memory::NullOnMove<VkDevice> m_device;
VkSemaphore m_semaphore; VkSemaphore m_semaphore;
}; };
@ -1507,7 +1417,7 @@ private:
return &m_fence; return &m_fence;
} }
NullOnMove<VkDevice> m_device; memory::NullOnMove<VkDevice> m_device;
VkFence m_fence; VkFence m_fence;
}; };
@ -1586,7 +1496,7 @@ private:
return m_buffer; return m_buffer;
} }
NullOnMove<VkDevice> m_device {}; memory::NullOnMove<VkDevice> m_device {};
VkBuffer m_buffer {}; VkBuffer m_buffer {};
}; };
@ -1841,7 +1751,7 @@ private:
return m_shader_module; return m_shader_module;
} }
NullOnMove<VkDevice> m_device {}; memory::NullOnMove<VkDevice> m_device {};
VkShaderModule m_shader_module {}; VkShaderModule m_shader_module {};
}; };
@ -1944,7 +1854,7 @@ public:
} }
private: private:
NullOnMove<VkDevice> m_device; memory::NullOnMove<VkDevice> m_device;
VkDescriptorSetLayout m_layout; VkDescriptorSetLayout m_layout;
}; };
@ -2074,7 +1984,7 @@ public:
~Pipeline(); ~Pipeline();
private: private:
NullOnMove<VkDevice> m_device {}; memory::NullOnMove<VkDevice> m_device {};
VkPipeline m_pipeline {}; VkPipeline m_pipeline {};
}; };
@ -2126,7 +2036,7 @@ private:
return m_layout; return m_layout;
} }
NullOnMove<VkDevice> m_device {}; memory::NullOnMove<VkDevice> m_device {};
VkPipelineLayout m_layout {}; VkPipelineLayout m_layout {};
}; };
@ -2522,7 +2432,7 @@ private:
return m_queue; return m_queue;
} }
NullOnMove<VkDevice> m_device; memory::NullOnMove<VkDevice> m_device;
VkQueue m_queue; VkQueue m_queue;
}; };
@ -2576,7 +2486,7 @@ private:
return m_memory; return m_memory;
} }
NullOnMove<VkDevice> m_device {}; memory::NullOnMove<VkDevice> m_device {};
VkDeviceMemory m_memory {}; VkDeviceMemory m_memory {};
}; };
@ -2630,7 +2540,7 @@ public:
auto operator=(const Messenger &) -> Messenger & = delete; auto operator=(const Messenger &) -> Messenger & = delete;
private: private:
NullOnMove<VkInstance> m_instance {}; memory::NullOnMove<VkInstance> m_instance {};
VkDebugUtilsMessengerEXT m_messenger {}; VkDebugUtilsMessengerEXT m_messenger {};
}; };

View file

@ -2,15 +2,14 @@ import logger;
import test.test; import test.test;
import test.registry; import test.registry;
import lsd; import std;
using namespace ::lt;
using namespace ::lt::test; using namespace ::lt::test;
void parse_option(lsd::str_view argument, Registry::Options &options) void parse_option(std::string_view argument, Registry::Options &options)
{ {
constexpr auto case_str = lsd::str_view { "--case=" }; constexpr auto case_str = std::string_view { "--case=" };
constexpr auto suite_str = lsd::str_view { "--suite=" }; constexpr auto suite_str = std::string_view { "--suite=" };
if (argument == "--stop-on-fail") if (argument == "--stop-on-fail")
{ {
@ -27,14 +26,14 @@ void parse_option(lsd::str_view argument, Registry::Options &options)
if (argument.starts_with(suite_str) && argument.length() > suite_str.size()) if (argument.starts_with(suite_str) && argument.length() > suite_str.size())
{ {
options.suite_regex = argument.substr(suite_str.length()); options.suite_regex = argument.substr(suite_str.length());
lsd::println("SUITE REGEX: {}", options.suite_regex); std::println("SUITE REGEX: {}", options.suite_regex);
return; return;
} }
if (argument.starts_with(case_str) && argument.length() > case_str.size()) if (argument.starts_with(case_str) && argument.length() > case_str.size())
{ {
options.case_regex = argument.substr(case_str.length()); options.case_regex = argument.substr(case_str.length());
lsd::println("CASE REGEX: {}", options.case_regex); std::println("CASE REGEX: {}", options.case_regex);
return; return;
} }
@ -43,19 +42,19 @@ void parse_option(lsd::str_view argument, Registry::Options &options)
void print_help() void print_help()
{ {
lsd::println("Options: "); std::println("Options: ");
lsd::println("--stop-on-fail --> Stops executing the remaining tests on first failure"); std::println("--stop-on-fail --> Stops executing the remaining tests on first failure");
lsd::println("--suite --> Regex for running specific suite(s)"); std::println("--suite --> Regex for running specific suite(s)");
lsd::println("--case --> Regex for running specific test(s)"); std::println("--case --> Regex for running specific test(s)");
lsd::println("--mode=stats --> Executes tests with an alternative policy"); std::println("--mode=stats --> Executes tests with an alternative policy");
lsd::println("\t---> stats: Print statistics about the tests without running any"); std::println("\t---> stats: Print statistics about the tests without running any");
lsd::println("--help | -h --> ~You just used it! :D"); std::println("--help | -h --> ~You just used it! :D");
} }
auto main(i32 argc, char **argv) -> i32 auto main(std::int32_t argc, char **argv) -> std::int32_t
try try
{ {
auto raw_arguments = lsd::span<char *>(argv, argc); auto raw_arguments = std::span<char *>(argv, argc);
auto options = Registry::Options {}; auto options = Registry::Options {};
for (auto idx = 0; auto &raw_argument : raw_arguments) for (auto idx = 0; auto &raw_argument : raw_arguments)
@ -66,7 +65,7 @@ try
continue; continue;
} }
auto argument = lsd::str_view(raw_argument); auto argument = std::string_view(raw_argument);
if (argument == "-h" || argument == "--help") if (argument == "-h" || argument == "--help")
{ {
@ -84,9 +83,9 @@ try
} }
} }
return static_cast<i32>(Registry::run_all(options)); return static_cast<std::int32_t>(Registry::run_all(options));
} }
catch (const lsd::exception &exp) catch (const std::exception &exp)
{ {
lt::log::critical("Terminated due to uncaught exception:"); lt::log::critical("Terminated due to uncaught exception:");
lt::log::critical("\twhat: {}", exp.what()); lt::log::critical("\twhat: {}", exp.what());

View file

@ -1,9 +1,8 @@
export module test.test; export module test.test;
import std;
import test.expects; import test.expects;
import test.registry; import test.registry;
import std;
import lsd;
/////////////////////////////////////// ///////////////////////////////////////
// ----------* INTERFACE *--------- // // ----------* INTERFACE *--------- //
@ -13,16 +12,16 @@ namespace lt::test {
class TestCase class TestCase
{ {
public: public:
TestCase(lsd::str_view name); TestCase(std::string_view name);
// NOLINTNEXTLINE(misc-unconventional-assign-operator) // NOLINTNEXTLINE(misc-unconventional-assign-operator)
auto operator=(lsd::invocable auto test) const -> void; auto operator=(std::invocable auto test) const -> void;
private: private:
void run_normal(lsd::invocable auto test) const; void run_normal(std::invocable auto test) const;
private: private:
lsd::str_view m_name; std::string_view m_name;
}; };
struct TestSuite struct TestSuite
@ -39,25 +38,25 @@ struct TestFuzzHarness
export using Case = const TestCase; export using Case = const TestCase;
export using Suite = const TestSuite; export using Suite = const TestSuite;
export using FuzzHarness = const TestFuzzHarness; export using FuzzHarness = const TestFuzzHarness;
export auto operator""_suite(const char *name, size_t size) -> TestSuite; export auto operator""_suite(const char *name, std::size_t size) -> TestSuite;
/////////////////////////////////////// ///////////////////////////////////////
// * IMPLEMENTATION -- TEMPLATES * // // * IMPLEMENTATION -- TEMPLATES * //
///////////////////////////////////// /////////////////////////////////////
// NOLINTNEXTLINE(misc-unconventional-assign-operator) // NOLINTNEXTLINE(misc-unconventional-assign-operator)
auto TestCase::operator=(lsd::invocable auto test) const -> void auto TestCase::operator=(std::invocable auto test) const -> void
{ {
using enum Registry::ExecutionPolicy; using enum Registry::ExecutionPolicy;
switch (Registry::get_options().execution_policy) switch (Registry::get_options().execution_policy)
{ {
case normal: run_normal(lsd::move(test)); break; case normal: run_normal(std::move(test)); break;
case stats: Registry::increment_total_case_count(); break; case stats: Registry::increment_total_case_count(); break;
} }
} }
void TestCase::run_normal(lsd::invocable auto test) const void TestCase::run_normal(std::invocable auto test) const
{ {
Registry::increment_total_case_count(); Registry::increment_total_case_count();
@ -69,16 +68,16 @@ void TestCase::run_normal(lsd::invocable auto test) const
} }
Registry::increment_matched_case_count(); Registry::increment_matched_case_count();
lsd::println("[Running-----------] --> "); std::println("[Running-----------] --> ");
lsd::println("{}", m_name); std::println("{}", m_name);
try try
{ {
test(); test();
} }
catch (const std::exception &exp) catch (const std::exception &exp)
{ {
lsd::println("{}", exp.what()); std::println("{}", exp.what());
lsd::println("[-----------FAIL !!]"); std::println("[-----------FAIL !!]");
Registry::increment_failed_case_count(); Registry::increment_failed_case_count();
if (Registry::should_return_on_failure()) if (Registry::should_return_on_failure())
@ -90,7 +89,7 @@ void TestCase::run_normal(lsd::invocable auto test) const
} }
Registry::increment_passed_case_count(); Registry::increment_passed_case_count();
lsd::println("[--------SUCCESS :D]"); std::println("[--------SUCCESS :D]");
} }
TestSuite::TestSuite(auto body) TestSuite::TestSuite(auto body)
@ -107,7 +106,7 @@ constexpr TestFuzzHarness::TestFuzzHarness(auto body)
#endif #endif
}; };
auto operator""_suite(const char *name, size_t size) -> TestSuite auto operator""_suite(const char *name, std::size_t size) -> TestSuite
{ {
Registry::set_last_suite_name(name); Registry::set_last_suite_name(name);
return {}; return {};
@ -121,7 +120,7 @@ auto operator""_suite(const char *name, size_t size) -> TestSuite
module :private; module :private;
namespace lt::test { namespace lt::test {
TestCase::TestCase(lsd::str_view name): m_name(name) TestCase::TestCase(std::string_view name): m_name(name)
{ {
} }

View file

@ -1,5 +1,5 @@
export module time; export module time;
import lsd; import std;
namespace lt::time { namespace lt::time {
@ -7,11 +7,11 @@ namespace lt::time {
export class Timer export class Timer
{ {
public: public:
using Clock = lsd::chrono::steady_clock; using Clock = std::chrono::steady_clock;
using Duration = lsd::chrono::duration<f64>; using Duration = std::chrono::duration<double>;
using Timepoint = lsd::chrono::time_point<lsd::chrono::steady_clock>; using Timepoint = std::chrono::time_point<std::chrono::steady_clock>;
Timer(Timepoint start = Clock::now()); Timer(Timepoint start = Clock::now());
@ -39,7 +39,7 @@ void Timer::reset(Timepoint start)
[[nodiscard]] auto Timer::elapsed_time() const -> Duration [[nodiscard]] auto Timer::elapsed_time() const -> Duration
{ {
return { lsd::chrono::steady_clock::now() - m_start }; return { std::chrono::steady_clock::now() - m_start };
} }
} // namespace lt::time } // namespace lt::time

View file

@ -19,22 +19,14 @@ function(add_module)
set(module_directory "${ARGS_ROOT_DIR}") set(module_directory "${ARGS_ROOT_DIR}")
endif() endif()
# In this case, the module is an executable, so we prepend "lib" to the # In this case, the module is an executable, so we prepend "lib" to the target name.
# target name. And set the "executable_target" name to ARGS_NAME. # And set the "executable_target" name to ARGS_NAME.
# # The rationale here is to easily be able to write tests for an executable modules's interfaces...
# The rationale here is to easily be able to write tests for an executable # by splitting it into two targets: lib"executable_name" for the interface and "executable_name" for the "int main()" defining file (the entrypoint).
# modules's interfaces... by splitting it into two targets: # the lib"executable_name" should not be disruptive since an executable module's library will not be dependent upon (except by the tests within the same module)
# lib"executable_name" for the interface and "executable_name" for the "int
# main()" defining file (the entrypoint).
# The lib"executable_name" should not be disruptive since an executable
# module's library will not be dependent upon (except by the tests within
# the same module)
if(ARGS_ENTRYPOINT) if(ARGS_ENTRYPOINT)
set(target_library_name "lib_${ARGS_NAME}") set(target_library_name "lib_${ARGS_NAME}")
add_executable( add_executable(${target_executable_name} ${module_directory}/${ARGS_ENTRYPOINT})
${target_executable_name} ${module_directory}/${ARGS_ENTRYPOINT}
)
endif() endif()
add_library(${target_library_name}) add_library(${target_library_name})
@ -61,15 +53,13 @@ function(add_module)
list(APPEND files "${module_directory}/${file}") list(APPEND files "${module_directory}/${file}")
endforeach() endforeach()
target_sources( target_sources(
${target_library_name} PUBLIC FILE_SET public_cxx_modules TYPE ${target_library_name} PUBLIC FILE_SET public_cxx_modules TYPE CXX_MODULES
CXX_MODULES FILES ${files} FILES ${files}
) )
endif() endif()
target_link_libraries(${target_library_name} PUBLIC ${ARGS_DEPENDENCIES}) target_link_libraries(${target_library_name} PUBLIC ${ARGS_DEPENDENCIES})
target_link_libraries( target_link_libraries(${target_library_name} PRIVATE ${ARGS_PRIVATE_DEPENDENCIES})
${target_library_name} PRIVATE ${ARGS_PRIVATE_DEPENDENCIES}
)
if(ARGS_TESTS) if(ARGS_TESTS)
message("ADDING TESTS!!!") message("ADDING TESTS!!!")
@ -88,9 +78,7 @@ function(add_module)
endif() endif()
if(ARGS_ENTRYPOINT) if(ARGS_ENTRYPOINT)
target_link_libraries( target_link_libraries(${target_executable_name} PRIVATE ${target_library_name})
${target_executable_name} PRIVATE ${target_library_name}
)
endif() endif()
endfunction() endfunction()