refactor&feat: 重写日志系统,添加代码追踪信息

master
ternaryop8479 2026-02-14 23:11:26 +08:00
parent 9136627b2a
commit 2284124628
14 changed files with 286 additions and 217 deletions

View File

@ -1,61 +1,74 @@
#ifndef ARE_INCLUDE_UTILS_LOGGER_H #ifndef ARE_INCLUDE_CORE_LOGGER_H
#define ARE_INCLUDE_UTILS_LOGGER_H #define ARE_INCLUDE_CORE_LOGGER_H
#include <string> #include <string>
#include <memory>
namespace are { namespace are {
/// @brief Log level enumeration /**
* @enum LogLevel
* @brief Logging severity levels
*/
enum class LogLevel { enum class LogLevel {
DEBUG, ARE_LOG_TRACE,
INFO, ARE_LOG_DEBUG,
WARNING, ARE_LOG_INFO,
ERROR, ARE_LOG_WARN,
FATAL ARE_LOG_ERROR,
ARE_LOG_CRITICAL
}; };
/// @brief Logger interface for engine logging /**
/// @note This module should be implemented by the user * @class Logger
* @brief Thread-safe logging system
*
* This class provides a simple interface for logging messages with different
* severity levels. It wraps spdlog for actual logging functionality.
*/
class Logger { class Logger {
public: public:
/// @brief Initialize logger /**
/// @param log_file Log file path (empty for console only) * @brief Initialize the logging system
/// @return True if initialization succeeded * @param min_level Minimum log level to display
static bool initialize(const std::string& log_file = ""); */
static void init(LogLevel min_level = LogLevel::ARE_LOG_INFO);
/// @brief Shutdown logger /**
* @brief Shutdown the logging system
*/
static void shutdown(); static void shutdown();
/// @brief Log message /**
/// @param level Log level * @brief Log a message with file/function/line information
/// @param message Message content * @param level Log severity level
static void log(LogLevel level, const std::string& message); * @param file Source file name
* @param func Function name
* @param line Line number
* @param message Log message
*/
static void log(LogLevel level, const char* file, const char* func,
int line, const std::string& message);
/// @brief Log debug message /**
/// @param message Message content * @brief Set minimum log level
static void debug(const std::string& message); * @param level Minimum log level to display
*/
/// @brief Log info message
/// @param message Message content
static void info(const std::string& message);
/// @brief Log warning message
/// @param message Message content
static void warning(const std::string& message);
/// @brief Log error message
/// @param message Message content
static void error(const std::string& message);
/// @brief Log fatal message
/// @param message Message content
static void fatal(const std::string& message);
/// @brief Set minimum log level
/// @param level Minimum level to log
static void set_level(LogLevel level); static void set_level(LogLevel level);
private:
static std::shared_ptr<void> logger_impl_; ///< Internal logger implementation
static bool initialized_; ///< Initialization flag
}; };
} // namespace are } // namespace are
#endif // ARE_INCLUDE_UTILS_LOGGER_H // Logging macros
#define ARE_LOG_TRACE(msg) are::Logger::log(are::LogLevel::ARE_LOG_TRACE, __FILE__, __func__, __LINE__, msg)
#define ARE_LOG_DEBUG(msg) are::Logger::log(are::LogLevel::ARE_LOG_DEBUG, __FILE__, __func__, __LINE__, msg)
#define ARE_LOG_INFO(msg) are::Logger::log(are::LogLevel::ARE_LOG_INFO, __FILE__, __func__, __LINE__, msg)
#define ARE_LOG_WARN(msg) are::Logger::log(are::LogLevel::ARE_LOG_WARN, __FILE__, __func__, __LINE__, msg)
#define ARE_LOG_ERROR(msg) are::Logger::log(are::LogLevel::ARE_LOG_ERROR, __FILE__, __func__, __LINE__, msg)
#define ARE_LOG_CRITICAL(msg) are::Logger::log(are::LogLevel::ARE_LOG_CRITICAL, __FILE__, __func__, __LINE__, msg)
#endif // ARE_INCLUDE_CORE_LOGGER_H

View File

@ -49,7 +49,7 @@ BVH::~BVH() {
bool BVH::build(const std::vector<std::shared_ptr<Mesh>>& meshes) { bool BVH::build(const std::vector<std::shared_ptr<Mesh>>& meshes) {
clear(); clear();
Logger::info("Building BVH..."); ARE_LOG_INFO("Building BVH...");
// Extract all triangles from meshes // Extract all triangles from meshes
for (const auto& mesh : meshes) { for (const auto& mesh : meshes) {
@ -88,7 +88,7 @@ bool BVH::build(const std::vector<std::shared_ptr<Mesh>>& meshes) {
} }
if (triangles_.empty()) { if (triangles_.empty()) {
Logger::warning("No triangles to build BVH"); ARE_LOG_WARN("No triangles to build BVH");
return false; return false;
} }
@ -107,7 +107,7 @@ bool BVH::build(const std::vector<std::shared_ptr<Mesh>>& meshes) {
// Build BVH recursively // Build BVH recursively
build_recursive_(0, 0, static_cast<uint>(triangles_.size())); build_recursive_(0, 0, static_cast<uint>(triangles_.size()));
Logger::info("BVH built: " + std::to_string(nodes_.size()) + " nodes, " + ARE_LOG_INFO("BVH built: " + std::to_string(nodes_.size()) + " nodes, " +
std::to_string(triangles_.size()) + " triangles"); std::to_string(triangles_.size()) + " triangles");
return true; return true;
@ -260,7 +260,7 @@ AABB BVH::calculate_centroid_bounds_(uint first_prim, uint prim_count) {
bool BVH::upload_to_gpu(Buffer& node_buffer, Buffer& triangle_buffer) { bool BVH::upload_to_gpu(Buffer& node_buffer, Buffer& triangle_buffer) {
if (nodes_.empty() || triangles_.empty()) { if (nodes_.empty() || triangles_.empty()) {
Logger::error("Cannot upload empty BVH to GPU"); ARE_LOG_ERROR("Cannot upload empty BVH to GPU");
return false; return false;
} }
@ -307,7 +307,7 @@ bool BVH::upload_to_gpu(Buffer& node_buffer, Buffer& triangle_buffer) {
node_gpu.size() * sizeof(BVHNodeGpu), node_gpu.size() * sizeof(BVHNodeGpu),
node_gpu.data(), node_gpu.data(),
BufferUsage::STATIC_DRAW)) { BufferUsage::STATIC_DRAW)) {
Logger::error("Failed to upload BVH nodes to GPU"); ARE_LOG_ERROR("Failed to upload BVH nodes to GPU");
return false; return false;
} }
@ -315,11 +315,11 @@ bool BVH::upload_to_gpu(Buffer& node_buffer, Buffer& triangle_buffer) {
tri_gpu.size() * sizeof(TriangleGpu), tri_gpu.size() * sizeof(TriangleGpu),
tri_gpu.data(), tri_gpu.data(),
BufferUsage::STATIC_DRAW)) { BufferUsage::STATIC_DRAW)) {
Logger::error("Failed to upload BVH triangles to GPU"); ARE_LOG_ERROR("Failed to upload BVH triangles to GPU");
return false; return false;
} }
Logger::info("BVH uploaded to GPU successfully"); ARE_LOG_INFO("BVH uploaded to GPU successfully");
return true; return true;
} }

View File

@ -20,7 +20,7 @@ bool Denoiser::initialize(const std::shared_ptr<Shader>& shader) {
if (initialized_) return true; if (initialized_) return true;
if (!shader || !shader->is_valid()) { if (!shader || !shader->is_valid()) {
Logger::error("Invalid denoise shader"); ARE_LOG_ERROR("Invalid denoise shader");
return false; return false;
} }
@ -28,7 +28,7 @@ bool Denoiser::initialize(const std::shared_ptr<Shader>& shader) {
create_output_texture_(); create_output_texture_();
initialized_ = true; initialized_ = true;
Logger::info("Denoiser initialized"); ARE_LOG_INFO("Denoiser initialized");
return true; return true;
} }

View File

@ -21,7 +21,7 @@ GBuffer::~GBuffer() {
bool GBuffer::initialize() { bool GBuffer::initialize() {
if (initialized_) { if (initialized_) {
Logger::warning("GBuffer already initialized"); ARE_LOG_WARN("GBuffer already initialized");
return true; return true;
} }
@ -68,7 +68,7 @@ bool GBuffer::initialize() {
glDrawBuffers(GBUFFER_COUNT, draw_buffers); glDrawBuffers(GBUFFER_COUNT, draw_buffers);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
Logger::error("GBuffer framebuffer is not complete"); ARE_LOG_ERROR("GBuffer framebuffer is not complete");
glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0);
return false; return false;
} }
@ -76,7 +76,7 @@ bool GBuffer::initialize() {
glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0);
initialized_ = true; initialized_ = true;
Logger::info("GBuffer initialized successfully"); ARE_LOG_INFO("GBuffer initialized successfully");
return true; return true;
} }
@ -101,7 +101,7 @@ void GBuffer::release() {
} }
initialized_ = false; initialized_ = false;
Logger::info("GBuffer released"); ARE_LOG_INFO("GBuffer released");
} }
TextureHandle GBuffer::create_texture_(uint internal_format, uint format, uint type) { TextureHandle GBuffer::create_texture_(uint internal_format, uint format, uint type) {
@ -118,7 +118,7 @@ TextureHandle GBuffer::create_texture_(uint internal_format, uint format, uint t
void GBuffer::render(const Scene& scene, const Shader& shader) { void GBuffer::render(const Scene& scene, const Shader& shader) {
if (!initialized_) { if (!initialized_) {
Logger::error("GBuffer not initialized"); ARE_LOG_ERROR("GBuffer not initialized");
return; return;
} }
@ -151,7 +151,7 @@ void GBuffer::render(const Scene& scene, const Shader& shader) {
for (const auto& mesh : meshes) { for (const auto& mesh : meshes) {
if (!mesh->is_uploaded()) { if (!mesh->is_uploaded()) {
Logger::warning("Mesh not uploaded to GPU, skipping"); ARE_LOG_WARN("Mesh not uploaded to GPU, skipping");
continue; continue;
} }
@ -216,7 +216,7 @@ void GBuffer::resize(uint width, uint height) {
TextureHandle GBuffer::get_texture(int index) const { TextureHandle GBuffer::get_texture(int index) const {
if (index < 0 || index >= GBUFFER_COUNT) { if (index < 0 || index >= GBUFFER_COUNT) {
Logger::error("Invalid G-Buffer texture index"); ARE_LOG_ERROR("Invalid G-Buffer texture index");
return INVALID_HANDLE; return INVALID_HANDLE;
} }
return textures_[index]; return textures_[index];

View File

@ -39,7 +39,7 @@ RayTracer::~RayTracer() {
bool RayTracer::initialize() { bool RayTracer::initialize() {
if (initialized_) { if (initialized_) {
Logger::warning("RayTracer already initialized"); ARE_LOG_WARN("RayTracer already initialized");
return true; return true;
} }
@ -62,7 +62,7 @@ bool RayTracer::initialize() {
} }
initialized_ = true; initialized_ = true;
Logger::info("RayTracer initialized successfully"); ARE_LOG_INFO("RayTracer initialized successfully");
return true; return true;
} }
@ -92,12 +92,12 @@ void RayTracer::release() {
bvh_built_ = false; bvh_built_ = false;
initialized_ = false; initialized_ = false;
Logger::info("RayTracer released"); ARE_LOG_INFO("RayTracer released");
} }
bool RayTracer::rebuild_bvh(const Scene &scene) { bool RayTracer::rebuild_bvh(const Scene &scene) {
if (!config_.use_bvh_) { if (!config_.use_bvh_) {
Logger::warning("BVH is disabled in configuration"); ARE_LOG_WARN("BVH is disabled in configuration");
return false; return false;
} }
@ -105,32 +105,32 @@ bool RayTracer::rebuild_bvh(const Scene &scene) {
bvh_ = std::make_unique<BVH>(); bvh_ = std::make_unique<BVH>();
} }
Logger::info("Building BVH for ray tracing..."); ARE_LOG_INFO("Building BVH for ray tracing...");
if (!bvh_->build(scene.get_meshes())) { if (!bvh_->build(scene.get_meshes())) {
Logger::error("Failed to build BVH"); ARE_LOG_ERROR("Failed to build BVH");
return false; return false;
} }
if (!bvh_->upload_to_gpu(bvh_node_buffer_, bvh_triangle_buffer_)) { if (!bvh_->upload_to_gpu(bvh_node_buffer_, bvh_triangle_buffer_)) {
Logger::error("Failed to upload BVH to GPU"); ARE_LOG_ERROR("Failed to upload BVH to GPU");
return false; return false;
} }
bvh_built_ = true; bvh_built_ = true;
reset_accumulation(); reset_accumulation();
Logger::info("BVH built and uploaded successfully"); ARE_LOG_INFO("BVH built and uploaded successfully");
return true; return true;
} }
void RayTracer::trace(const Scene &scene, const GBuffer &gbuffer, TextureHandle output_texture) { void RayTracer::trace(const Scene &scene, const GBuffer &gbuffer, TextureHandle output_texture) {
if (!initialized_) { if (!initialized_) {
Logger::error("RayTracer not initialized"); ARE_LOG_ERROR("RayTracer not initialized");
return; return;
} }
if (!compute_shader_->is_valid()) { if (!compute_shader_->is_valid()) {
Logger::error("Ray tracing compute shader not loaded"); ARE_LOG_ERROR("Ray tracing compute shader not loaded");
return; return;
} }
@ -144,7 +144,7 @@ void RayTracer::trace(const Scene &scene, const GBuffer &gbuffer, TextureHandle
// Use compute shader // Use compute shader
if (!compute_shader_ || !compute_shader_->is_valid()) { if (!compute_shader_ || !compute_shader_->is_valid()) {
Logger::error("Ray tracing compute shader not set or invalid"); ARE_LOG_ERROR("Ray tracing compute shader not set or invalid");
return; return;
} }
compute_shader_->use(); compute_shader_->use();
@ -347,7 +347,7 @@ void RayTracer::bind_gbuffer_(const GBuffer &gbuffer) {
void RayTracer::set_compute_shader(const std::shared_ptr<Shader> &shader) { void RayTracer::set_compute_shader(const std::shared_ptr<Shader> &shader) {
compute_shader_ = shader; compute_shader_ = shader;
Logger::info("Compute shader set for RayTracer"); ARE_LOG_INFO("Compute shader set for RayTracer");
} }
} // namespace are } // namespace are

View File

@ -17,23 +17,23 @@ Renderer::~Renderer() {
bool Renderer::initialize() { bool Renderer::initialize() {
if (initialized_) { if (initialized_) {
Logger::warning("Renderer already initialized"); ARE_LOG_WARN("Renderer already initialized");
return true; return true;
} }
Logger::info("Initializing Aurora Rendering Engine..."); ARE_LOG_INFO("Initializing Aurora Rendering Engine...");
// Initialize shader manager // Initialize shader manager
shader_manager_ = std::make_unique<ShaderManager>(); shader_manager_ = std::make_unique<ShaderManager>();
if (!shader_manager_->initialize()) { if (!shader_manager_->initialize()) {
Logger::error("Failed to initialize shader manager"); ARE_LOG_ERROR("Failed to initialize shader manager");
return false; return false;
} }
// Initialize G-Buffer // Initialize G-Buffer
gbuffer_ = std::make_unique<GBuffer>(config_.width_, config_.height_); gbuffer_ = std::make_unique<GBuffer>(config_.width_, config_.height_);
if (!gbuffer_->initialize()) { if (!gbuffer_->initialize()) {
Logger::error("Failed to initialize G-Buffer"); ARE_LOG_ERROR("Failed to initialize G-Buffer");
return false; return false;
} }
@ -48,14 +48,14 @@ bool Renderer::initialize() {
raytracer_ = std::make_unique<RayTracer>(config_.width_, config_.height_, rt_config); raytracer_ = std::make_unique<RayTracer>(config_.width_, config_.height_, rt_config);
if (!raytracer_->initialize()) { if (!raytracer_->initialize()) {
Logger::error("Failed to initialize ray tracer"); ARE_LOG_ERROR("Failed to initialize ray tracer");
return false; return false;
} }
// Pass compute shader to ray tracer // Pass compute shader to ray tracer
const auto& rt_shader = shader_manager_->get_raytracing_shader(); const auto& rt_shader = shader_manager_->get_raytracing_shader();
if (!rt_shader || !rt_shader->is_valid()) { if (!rt_shader || !rt_shader->is_valid()) {
Logger::error("Ray tracing shader is invalid"); ARE_LOG_ERROR("Ray tracing shader is invalid");
return false; return false;
} }
raytracer_->set_compute_shader(rt_shader); raytracer_->set_compute_shader(rt_shader);
@ -63,19 +63,19 @@ bool Renderer::initialize() {
// Initialize screen blit // Initialize screen blit
screen_blit_ = std::make_unique<ScreenBlit>(); screen_blit_ = std::make_unique<ScreenBlit>();
if (!screen_blit_->initialize()) { if (!screen_blit_->initialize()) {
Logger::error("Failed to initialize screen blit"); ARE_LOG_ERROR("Failed to initialize screen blit");
return false; return false;
} }
denoiser_ = std::make_unique<Denoiser>(config_.width_, config_.height_); denoiser_ = std::make_unique<Denoiser>(config_.width_, config_.height_);
const auto& denoise_shader = shader_manager_->get_denoise_shader(); const auto& denoise_shader = shader_manager_->get_denoise_shader();
if (!denoiser_->initialize(denoise_shader)) { if (!denoiser_->initialize(denoise_shader)) {
Logger::error("Failed to initialize denoiser"); ARE_LOG_ERROR("Failed to initialize denoiser");
return false; return false;
} }
initialized_ = true; initialized_ = true;
Logger::info("Aurora Rendering Engine initialized successfully"); ARE_LOG_INFO("Aurora Rendering Engine initialized successfully");
return true; return true;
} }
@ -83,7 +83,7 @@ void Renderer::shutdown() {
if (!initialized_) if (!initialized_)
return; return;
Logger::info("Shutting down Aurora Rendering Engine..."); ARE_LOG_INFO("Shutting down Aurora Rendering Engine...");
if (screen_blit_) { if (screen_blit_) {
screen_blit_->release(); screen_blit_->release();
@ -111,14 +111,14 @@ void Renderer::shutdown() {
} }
initialized_ = false; initialized_ = false;
Logger::info("Aurora Rendering Engine shut down"); ARE_LOG_INFO("Aurora Rendering Engine shut down");
} }
RenderStats Renderer::render(const Scene& scene, TextureHandle output_texture) { RenderStats Renderer::render(const Scene& scene, TextureHandle output_texture) {
RenderStats stats = {}; RenderStats stats = {};
if (!initialized_) { if (!initialized_) {
Logger::error("Renderer not initialized"); ARE_LOG_ERROR("Renderer not initialized");
return stats; return stats;
} }
@ -130,7 +130,7 @@ RenderStats Renderer::render(const Scene& scene, TextureHandle output_texture) {
const auto& gbuffer_shader = shader_manager_->get_gbuffer_shader(); const auto& gbuffer_shader = shader_manager_->get_gbuffer_shader();
if (!gbuffer_shader || !gbuffer_shader->is_valid()) { if (!gbuffer_shader || !gbuffer_shader->is_valid()) {
Logger::error("G-Buffer shader is invalid"); ARE_LOG_ERROR("G-Buffer shader is invalid");
return stats; return stats;
} }
gbuffer_->render(scene, *gbuffer_shader); gbuffer_->render(scene, *gbuffer_shader);
@ -203,7 +203,7 @@ void Renderer::resize(uint width, uint height) {
raytracer_->resize(width, height); raytracer_->resize(width, height);
denoiser_->resize(width, height); denoiser_->resize(width, height);
Logger::info("Renderer resized to " + std::to_string(width) + "x" + std::to_string(height)); ARE_LOG_INFO("Renderer resized to " + std::to_string(width) + "x" + std::to_string(height));
} }
} }

View File

@ -43,13 +43,13 @@ ScreenBlit::~ScreenBlit() {
bool ScreenBlit::initialize() { bool ScreenBlit::initialize() {
if (initialized_) { if (initialized_) {
Logger::warning("ScreenBlit already initialized"); ARE_LOG_WARN("ScreenBlit already initialized");
return true; return true;
} }
// Compile shader // Compile shader
if (!shader_.compile(VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE)) { if (!shader_.compile(VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE)) {
Logger::error("Failed to compile screen blit shader"); ARE_LOG_ERROR("Failed to compile screen blit shader");
return false; return false;
} }
@ -57,7 +57,7 @@ bool ScreenBlit::initialize() {
create_quad_(); create_quad_();
initialized_ = true; initialized_ = true;
Logger::info("ScreenBlit initialized successfully"); ARE_LOG_INFO("ScreenBlit initialized successfully");
return true; return true;
} }
@ -81,7 +81,7 @@ void ScreenBlit::release() {
void ScreenBlit::blit(TextureHandle texture, int x, int y, uint width, uint height) { void ScreenBlit::blit(TextureHandle texture, int x, int y, uint width, uint height) {
if (!initialized_) { if (!initialized_) {
Logger::error("ScreenBlit not initialized"); ARE_LOG_ERROR("ScreenBlit not initialized");
return; return;
} }

View File

@ -13,19 +13,19 @@ ShaderManager::~ShaderManager() {
bool ShaderManager::initialize() { bool ShaderManager::initialize() {
if (initialized_) { if (initialized_) {
Logger::warning("ShaderManager already initialized"); ARE_LOG_WARN("ShaderManager already initialized");
return true; return true;
} }
Logger::info("Loading built-in shaders..."); ARE_LOG_INFO("Loading built-in shaders...");
if (!load_builtin_shaders_()) { if (!load_builtin_shaders_()) {
Logger::error("Failed to load built-in shaders"); ARE_LOG_ERROR("Failed to load built-in shaders");
return false; return false;
} }
initialized_ = true; initialized_ = true;
Logger::info("ShaderManager initialized successfully"); ARE_LOG_INFO("ShaderManager initialized successfully");
return true; return true;
} }
@ -42,7 +42,7 @@ void ShaderManager::release() {
denoise_shader_.reset(); denoise_shader_.reset();
initialized_ = false; initialized_ = false;
Logger::info("ShaderManager released"); ARE_LOG_INFO("ShaderManager released");
} }
std::shared_ptr<Shader> ShaderManager::load_shader(const std::string& name, std::shared_ptr<Shader> ShaderManager::load_shader(const std::string& name,
@ -50,18 +50,18 @@ std::shared_ptr<Shader> ShaderManager::load_shader(const std::string& name,
const std::string& fragment_path) { const std::string& fragment_path) {
auto it = shader_cache_.find(name); auto it = shader_cache_.find(name);
if (it != shader_cache_.end()) { if (it != shader_cache_.end()) {
Logger::info("Shader '" + name + "' loaded from cache"); ARE_LOG_INFO("Shader '" + name + "' loaded from cache");
return it->second; return it->second;
} }
auto shader = std::make_shared<Shader>(); auto shader = std::make_shared<Shader>();
if (!shader->load(vertex_path, fragment_path)) { if (!shader->load(vertex_path, fragment_path)) {
Logger::error("Failed to load shader '" + name + "'"); ARE_LOG_ERROR("Failed to load shader '" + name + "'");
return nullptr; return nullptr;
} }
shader_cache_[name] = shader; shader_cache_[name] = shader;
Logger::info("Shader '" + name + "' loaded successfully"); ARE_LOG_INFO("Shader '" + name + "' loaded successfully");
return shader; return shader;
} }
@ -69,18 +69,18 @@ std::shared_ptr<Shader> ShaderManager::load_compute_shader(const std::string& na
const std::string& compute_path) { const std::string& compute_path) {
auto it = shader_cache_.find(name); auto it = shader_cache_.find(name);
if (it != shader_cache_.end()) { if (it != shader_cache_.end()) {
Logger::info("Compute shader '" + name + "' loaded from cache"); ARE_LOG_INFO("Compute shader '" + name + "' loaded from cache");
return it->second; return it->second;
} }
auto shader = std::make_shared<Shader>(); auto shader = std::make_shared<Shader>();
if (!shader->load_compute(compute_path)) { if (!shader->load_compute(compute_path)) {
Logger::error("Failed to load compute shader '" + name + "'"); ARE_LOG_ERROR("Failed to load compute shader '" + name + "'");
return nullptr; return nullptr;
} }
shader_cache_[name] = shader; shader_cache_[name] = shader;
Logger::info("Compute shader '" + name + "' loaded successfully"); ARE_LOG_INFO("Compute shader '" + name + "' loaded successfully");
return shader; return shader;
} }
@ -88,35 +88,35 @@ std::shared_ptr<Shader> ShaderManager::get_shader(const std::string& name) const
auto it = shader_cache_.find(name); auto it = shader_cache_.find(name);
if (it != shader_cache_.end()) return it->second; if (it != shader_cache_.end()) return it->second;
Logger::warning("Shader '" + name + "' not found in cache"); ARE_LOG_WARN("Shader '" + name + "' not found in cache");
return nullptr; return nullptr;
} }
bool ShaderManager::load_builtin_shaders_() { bool ShaderManager::load_builtin_shaders_() {
gbuffer_shader_ = std::make_shared<Shader>(); gbuffer_shader_ = std::make_shared<Shader>();
if (!gbuffer_shader_->load("shaders/gbuffer.vert", "shaders/gbuffer.frag")) { if (!gbuffer_shader_->load("shaders/gbuffer.vert", "shaders/gbuffer.frag")) {
Logger::error("Failed to load G-Buffer shader"); ARE_LOG_ERROR("Failed to load G-Buffer shader");
return false; return false;
} }
shader_cache_["gbuffer"] = gbuffer_shader_; shader_cache_["gbuffer"] = gbuffer_shader_;
Logger::info("Loading ray tracing compute shader..."); ARE_LOG_INFO("Loading ray tracing compute shader...");
raytracing_shader_ = std::make_shared<Shader>(); raytracing_shader_ = std::make_shared<Shader>();
if (!raytracing_shader_->load_compute("shaders/raytracing.comp")) { if (!raytracing_shader_->load_compute("shaders/raytracing.comp")) {
Logger::error("Failed to load ray tracing shader"); ARE_LOG_ERROR("Failed to load ray tracing shader");
return false; return false;
} }
shader_cache_["raytracing"] = raytracing_shader_; shader_cache_["raytracing"] = raytracing_shader_;
Logger::info("Ray tracing shader loaded successfully"); ARE_LOG_INFO("Ray tracing shader loaded successfully");
Logger::info("Loading denoise compute shader..."); ARE_LOG_INFO("Loading denoise compute shader...");
denoise_shader_ = std::make_shared<Shader>(); denoise_shader_ = std::make_shared<Shader>();
if (!denoise_shader_->load_compute("shaders/denoiser.comp")) { if (!denoise_shader_->load_compute("shaders/denoiser.comp")) {
Logger::error("Failed to load denoise shader"); ARE_LOG_ERROR("Failed to load denoise shader");
return false; return false;
} }
shader_cache_["denoise"] = denoise_shader_; shader_cache_["denoise"] = denoise_shader_;
Logger::info("Denoise shader loaded successfully"); ARE_LOG_INFO("Denoise shader loaded successfully");
return true; return true;
} }

View File

@ -61,7 +61,7 @@ Buffer::~Buffer() {
bool Buffer::create(BufferType type, size_t size, const void* data, BufferUsage usage) { bool Buffer::create(BufferType type, size_t size, const void* data, BufferUsage usage) {
if (handle_ != INVALID_HANDLE) { if (handle_ != INVALID_HANDLE) {
Logger::warning("Buffer already created, releasing old buffer"); ARE_LOG_WARN("Buffer already created, releasing old buffer");
release(); release();
} }
@ -78,18 +78,18 @@ bool Buffer::create(BufferType type, size_t size, const void* data, BufferUsage
glBufferData(gl_type, size, data, gl_usage); glBufferData(gl_type, size, data, gl_usage);
glBindBuffer(gl_type, 0); glBindBuffer(gl_type, 0);
Logger::info("Buffer created successfully"); ARE_LOG_INFO("Buffer created successfully");
return true; return true;
} }
void Buffer::update(size_t offset, size_t size, const void* data) { void Buffer::update(size_t offset, size_t size, const void* data) {
if (handle_ == INVALID_HANDLE) { if (handle_ == INVALID_HANDLE) {
Logger::error("Cannot update invalid buffer"); ARE_LOG_ERROR("Cannot update invalid buffer");
return; return;
} }
if (offset + size > size_) { if (offset + size > size_) {
Logger::error("Buffer update out of bounds"); ARE_LOG_ERROR("Buffer update out of bounds");
return; return;
} }
@ -102,7 +102,7 @@ void Buffer::update(size_t offset, size_t size, const void* data) {
void Buffer::bind() const { void Buffer::bind() const {
if (handle_ == INVALID_HANDLE) { if (handle_ == INVALID_HANDLE) {
Logger::warning("Attempting to bind invalid buffer"); ARE_LOG_WARN("Attempting to bind invalid buffer");
return; return;
} }
@ -112,7 +112,7 @@ void Buffer::bind() const {
void Buffer::bind_base(uint binding_point) const { void Buffer::bind_base(uint binding_point) const {
if (handle_ == INVALID_HANDLE) { if (handle_ == INVALID_HANDLE) {
Logger::warning("Attempting to bind invalid buffer"); ARE_LOG_WARN("Attempting to bind invalid buffer");
return; return;
} }

View File

@ -39,7 +39,7 @@ bool Shader::load(const std::string& vertex_path, const std::string& fragment_pa
std::string fragment_source = read_file_(fragment_path); std::string fragment_source = read_file_(fragment_path);
if (vertex_source.empty() || fragment_source.empty()) { if (vertex_source.empty() || fragment_source.empty()) {
Logger::error("Failed to read shader files"); ARE_LOG_ERROR("Failed to read shader files");
return false; return false;
} }
@ -50,7 +50,7 @@ bool Shader::load_compute(const std::string& compute_path) {
std::string compute_source = read_file_(compute_path); std::string compute_source = read_file_(compute_path);
if (compute_source.empty()) { if (compute_source.empty()) {
Logger::error("Failed to read compute shader file"); ARE_LOG_ERROR("Failed to read compute shader file");
return false; return false;
} }
@ -148,7 +148,7 @@ int Shader::get_uniform_location_(const std::string& name) const { // 改为con
uniform_cache_[name] = location; // mutable允许修改 uniform_cache_[name] = location; // mutable允许修改
if (location == -1) { if (location == -1) {
Logger::warning("Uniform '" + name + "' not found in shader"); ARE_LOG_WARN("Uniform '" + name + "' not found in shader");
} }
return location; return location;
@ -168,7 +168,7 @@ uint Shader::compile_shader_(const std::string& source, uint type) {
std::string type_str = (type == GL_VERTEX_SHADER) ? "VERTEX" : std::string type_str = (type == GL_VERTEX_SHADER) ? "VERTEX" :
(type == GL_FRAGMENT_SHADER) ? "FRAGMENT" : "COMPUTE"; (type == GL_FRAGMENT_SHADER) ? "FRAGMENT" : "COMPUTE";
Logger::error("Shader compilation failed (" + type_str + "): " + std::string(info_log)); ARE_LOG_ERROR("Shader compilation failed (" + type_str + "): " + std::string(info_log));
glDeleteShader(shader); glDeleteShader(shader);
return 0; return 0;
@ -191,7 +191,7 @@ bool Shader::link_program_(const uint* shaders, uint count) {
if (!success) { if (!success) {
char info_log[512]; char info_log[512];
glGetProgramInfoLog(handle_, 512, nullptr, info_log); glGetProgramInfoLog(handle_, 512, nullptr, info_log);
Logger::error("Shader linking failed: " + std::string(info_log)); ARE_LOG_ERROR("Shader linking failed: " + std::string(info_log));
glDeleteProgram(handle_); glDeleteProgram(handle_);
handle_ = INVALID_HANDLE; handle_ = INVALID_HANDLE;
@ -204,7 +204,7 @@ bool Shader::link_program_(const uint* shaders, uint count) {
std::string Shader::read_file_(const std::string& path) { std::string Shader::read_file_(const std::string& path) {
std::ifstream file(path); std::ifstream file(path);
if (!file.is_open()) { if (!file.is_open()) {
Logger::error("Failed to open file: " + path); ARE_LOG_ERROR("Failed to open file: " + path);
return ""; return "";
} }

View File

@ -144,7 +144,7 @@ bool Texture::load_from_file(const std::string& path, bool generate_mipmaps) {
unsigned char* data = stbi_load(path.c_str(), &width, &height, &channels, 0); unsigned char* data = stbi_load(path.c_str(), &width, &height, &channels, 0);
if (!data) { if (!data) {
Logger::error("Failed to load texture: " + path); ARE_LOG_ERROR("Failed to load texture: " + path);
return false; return false;
} }
@ -156,7 +156,7 @@ bool Texture::load_from_file(const std::string& path, bool generate_mipmaps) {
case 3: format = TextureFormat::RGB8; break; case 3: format = TextureFormat::RGB8; break;
case 4: format = TextureFormat::RGBA8; break; case 4: format = TextureFormat::RGBA8; break;
default: default:
Logger::error("Unsupported channel count: " + std::to_string(channels)); ARE_LOG_ERROR("Unsupported channel count: " + std::to_string(channels));
stbi_image_free(data); stbi_image_free(data);
return false; return false;
} }
@ -181,13 +181,13 @@ bool Texture::load_from_file(const std::string& path, bool generate_mipmaps) {
this->generate_mipmaps(); this->generate_mipmaps();
} }
Logger::info("Texture loaded successfully: " + path); ARE_LOG_INFO("Texture loaded successfully: " + path);
return true; return true;
} }
bool Texture::create(uint width, uint height, TextureFormat format) { bool Texture::create(uint width, uint height, TextureFormat format) {
if (handle_ != INVALID_HANDLE) { if (handle_ != INVALID_HANDLE) {
Logger::warning("Texture already created, releasing old texture"); ARE_LOG_WARN("Texture already created, releasing old texture");
release(); release();
} }
@ -217,12 +217,12 @@ bool Texture::create(uint width, uint height, TextureFormat format) {
bool Texture::upload(const void* data, uint width, uint height, TextureFormat format) { bool Texture::upload(const void* data, uint width, uint height, TextureFormat format) {
if (handle_ == INVALID_HANDLE) { if (handle_ == INVALID_HANDLE) {
Logger::error("Cannot upload to invalid texture"); ARE_LOG_ERROR("Cannot upload to invalid texture");
return false; return false;
} }
if (width != width_ || height != height_ || format != format_) { if (width != width_ || height != height_ || format != format_) {
Logger::warning("Upload parameters differ from texture creation, recreating texture"); ARE_LOG_WARN("Upload parameters differ from texture creation, recreating texture");
create(width, height, format); create(width, height, format);
} }
@ -240,7 +240,7 @@ bool Texture::upload(const void* data, uint width, uint height, TextureFormat fo
void Texture::set_filter(TextureFilter min_filter, TextureFilter mag_filter) { void Texture::set_filter(TextureFilter min_filter, TextureFilter mag_filter) {
if (handle_ == INVALID_HANDLE) { if (handle_ == INVALID_HANDLE) {
Logger::error("Cannot set filter on invalid texture"); ARE_LOG_ERROR("Cannot set filter on invalid texture");
return; return;
} }
@ -252,7 +252,7 @@ void Texture::set_filter(TextureFilter min_filter, TextureFilter mag_filter) {
void Texture::set_wrap(TextureWrap wrap_s, TextureWrap wrap_t) { void Texture::set_wrap(TextureWrap wrap_s, TextureWrap wrap_t) {
if (handle_ == INVALID_HANDLE) { if (handle_ == INVALID_HANDLE) {
Logger::error("Cannot set wrap mode on invalid texture"); ARE_LOG_ERROR("Cannot set wrap mode on invalid texture");
return; return;
} }
@ -264,7 +264,7 @@ void Texture::set_wrap(TextureWrap wrap_s, TextureWrap wrap_t) {
void Texture::generate_mipmaps() { void Texture::generate_mipmaps() {
if (handle_ == INVALID_HANDLE) { if (handle_ == INVALID_HANDLE) {
Logger::error("Cannot generate mipmaps for invalid texture"); ARE_LOG_ERROR("Cannot generate mipmaps for invalid texture");
return; return;
} }
@ -277,7 +277,7 @@ void Texture::generate_mipmaps() {
void Texture::bind(uint unit) const { void Texture::bind(uint unit) const {
if (handle_ == INVALID_HANDLE) { if (handle_ == INVALID_HANDLE) {
Logger::warning("Attempting to bind invalid texture"); ARE_LOG_WARN("Attempting to bind invalid texture");
return; return;
} }

View File

@ -37,17 +37,17 @@ void Mesh::set_transform(const Mat4& transform) {
bool Mesh::upload_to_gpu() { bool Mesh::upload_to_gpu() {
if (uploaded_) { if (uploaded_) {
Logger::warning("Mesh already uploaded to GPU"); ARE_LOG_WARN("Mesh already uploaded to GPU");
return true; return true;
} }
if (vertices_.empty()) { if (vertices_.empty()) {
Logger::error("Cannot upload mesh: no vertices"); ARE_LOG_ERROR("Cannot upload mesh: no vertices");
return false; return false;
} }
if (indices_.empty()) { if (indices_.empty()) {
Logger::error("Cannot upload mesh: no indices"); ARE_LOG_ERROR("Cannot upload mesh: no indices");
return false; return false;
} }
@ -91,7 +91,7 @@ bool Mesh::upload_to_gpu() {
glBindVertexArray(0); glBindVertexArray(0);
uploaded_ = true; uploaded_ = true;
Logger::info("Mesh uploaded to GPU successfully"); ARE_LOG_INFO("Mesh uploaded to GPU successfully");
return true; return true;
} }

View File

@ -20,7 +20,7 @@ static std::string trim(const std::string& str) {
bool Config::load(const std::string& path) { bool Config::load(const std::string& path) {
std::ifstream file(path); std::ifstream file(path);
if (!file.is_open()) { if (!file.is_open()) {
Logger::error("Failed to open config file: " + path); ARE_LOG_ERROR("Failed to open config file: " + path);
return false; return false;
} }
@ -58,14 +58,14 @@ bool Config::load(const std::string& path) {
} }
} }
Logger::info("Config loaded: " + path + " (" + std::to_string(g_config_map.size()) + " entries)"); ARE_LOG_INFO("Config loaded: " + path + " (" + std::to_string(g_config_map.size()) + " entries)");
return true; return true;
} }
bool Config::save(const std::string& path) { bool Config::save(const std::string& path) {
std::ofstream file(path); std::ofstream file(path);
if (!file.is_open()) { if (!file.is_open()) {
Logger::error("Failed to open config file for writing: " + path); ARE_LOG_ERROR("Failed to open config file for writing: " + path);
return false; return false;
} }
@ -73,7 +73,7 @@ bool Config::save(const std::string& path) {
file << pair.first << "=" << pair.second << std::endl; file << pair.first << "=" << pair.second << std::endl;
} }
Logger::info("Config saved: " + path); ARE_LOG_INFO("Config saved: " + path);
return true; return true;
} }
@ -91,7 +91,7 @@ int Config::get_int(const std::string& key, int default_value) {
try { try {
return std::stoi(it->second); return std::stoi(it->second);
} catch (...) { } catch (...) {
Logger::warning("Failed to parse int for key: " + key); ARE_LOG_WARN("Failed to parse int for key: " + key);
} }
} }
return default_value; return default_value;
@ -103,7 +103,7 @@ float Config::get_float(const std::string& key, float default_value) {
try { try {
return std::stof(it->second); return std::stof(it->second);
} catch (...) { } catch (...) {
Logger::warning("Failed to parse float for key: " + key); ARE_LOG_WARN("Failed to parse float for key: " + key);
} }
} }
return default_value; return default_value;

View File

@ -1,103 +1,159 @@
#include "utils/logger.h" #include "utils/logger.h"
#include <iostream> #include <spdlog/spdlog.h>
#include <fstream> #include <spdlog/sinks/stdout_color_sinks.h>
#include <ctime> #include <spdlog/sinks/basic_file_sink.h>
#include <iomanip> #include <mutex>
#include <sstream> #include <cstring>
namespace are { namespace are {
// Static members std::shared_ptr<void> Logger::logger_impl_ = nullptr;
static LogLevel g_min_level = LogLevel::DEBUG; bool Logger::initialized_ = false;
static std::ofstream g_log_file;
static bool g_initialized = false;
bool Logger::initialize(const std::string& log_file) { void Logger::init(LogLevel min_level) {
if (g_initialized) { if (initialized_) {
return true; return;
} }
if (!log_file.empty()) { try {
g_log_file.open(log_file, std::ios::out | std::ios::app); // Create console sink with color support
if (!g_log_file.is_open()) { auto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
std::cerr << "Failed to open log file: " << log_file << std::endl; console_sink->set_pattern("[%H:%M:%S.%e] [%^%l%$] %v");
return false;
} // Create logger with console sink
auto logger = std::make_shared<spdlog::logger>("are", console_sink);
// Set log level
switch (min_level) {
case LogLevel::ARE_LOG_TRACE:
logger->set_level(spdlog::level::trace);
break;
case LogLevel::ARE_LOG_DEBUG:
logger->set_level(spdlog::level::debug);
break;
case LogLevel::ARE_LOG_INFO:
logger->set_level(spdlog::level::info);
break;
case LogLevel::ARE_LOG_WARN:
logger->set_level(spdlog::level::warn);
break;
case LogLevel::ARE_LOG_ERROR:
logger->set_level(spdlog::level::err);
break;
case LogLevel::ARE_LOG_CRITICAL:
logger->set_level(spdlog::level::critical);
break;
} }
g_initialized = true; // Flush on error or higher
return true; logger->flush_on(spdlog::level::err);
// Set as default logger
spdlog::set_default_logger(logger);
logger_impl_ = logger;
initialized_ = true;
} catch (const std::exception& e) {
fprintf(stderr, "[ARE] Failed to initialize logger: %s\n", e.what());
}
} }
void Logger::shutdown() { void Logger::shutdown() {
if (g_log_file.is_open()) { if (!initialized_) {
g_log_file.close(); return;
}
try {
spdlog::shutdown();
logger_impl_.reset();
initialized_ = false;
} catch (const std::exception& e) {
fprintf(stderr, "[ARE] Error during logger shutdown: %s\n", e.what());
} }
g_initialized = false;
} }
static std::string get_current_time() { void Logger::log(LogLevel level, const char* file, const char* func,
auto now = std::time(nullptr); int line, const std::string& message) {
auto tm = *std::localtime(&now); if (!initialized_) {
std::ostringstream oss; init();
oss << std::put_time(&tm, "%H:%M:%S"); }
return oss.str();
} // Extract filename from full path
const char* filename = file;
const char* last_slash = nullptr;
for (const char* p = file; *p; ++p) {
if (*p == '/' || *p == '\\') {
last_slash = p;
}
}
if (last_slash) {
filename = last_slash + 1;
}
// Format message with location information
std::string formatted = message + " (" + filename + "-" + func + "():" + std::to_string(line) + ")";
try {
auto logger = std::static_pointer_cast<spdlog::logger>(logger_impl_);
static std::string level_to_string(LogLevel level) {
switch (level) { switch (level) {
case LogLevel::DEBUG: return "DEBUG"; case LogLevel::ARE_LOG_TRACE:
case LogLevel::INFO: return "INFO"; logger->trace(formatted);
case LogLevel::WARNING: return "WARN"; break;
case LogLevel::ERROR: return "ERROR"; case LogLevel::ARE_LOG_DEBUG:
case LogLevel::FATAL: return "FATAL"; logger->debug(formatted);
default: return "UNKNOWN"; break;
case LogLevel::ARE_LOG_INFO:
logger->info(formatted);
break;
case LogLevel::ARE_LOG_WARN:
logger->warn(formatted);
break;
case LogLevel::ARE_LOG_ERROR:
logger->error(formatted);
break;
case LogLevel::ARE_LOG_CRITICAL:
logger->critical(formatted);
break;
} }
} } catch (const std::exception& e) {
fprintf(stderr, "[ARE] Logging error: %s\n", e.what());
void Logger::log(LogLevel level, const std::string& message) {
if (level < g_min_level) return;
std::string time_str = get_current_time();
std::string level_str = level_to_string(level);
std::string formatted = "[" + time_str + "] [" + level_str + "] " + message;
// Console output
if (level >= LogLevel::ERROR) {
std::cerr << formatted << std::endl;
} else {
std::cout << formatted << std::endl;
} }
// File output
if (g_log_file.is_open()) {
g_log_file << formatted << std::endl;
g_log_file.flush();
}
}
void Logger::debug(const std::string& message) {
log(LogLevel::DEBUG, message);
}
void Logger::info(const std::string& message) {
log(LogLevel::INFO, message);
}
void Logger::warning(const std::string& message) {
log(LogLevel::WARNING, message);
}
void Logger::error(const std::string& message) {
log(LogLevel::ERROR, message);
}
void Logger::fatal(const std::string& message) {
log(LogLevel::FATAL, message);
} }
void Logger::set_level(LogLevel level) { void Logger::set_level(LogLevel level) {
g_min_level = level; if (!initialized_) {
return;
}
try {
auto logger = std::static_pointer_cast<spdlog::logger>(logger_impl_);
switch (level) {
case LogLevel::ARE_LOG_TRACE:
logger->set_level(spdlog::level::trace);
break;
case LogLevel::ARE_LOG_DEBUG:
logger->set_level(spdlog::level::debug);
break;
case LogLevel::ARE_LOG_INFO:
logger->set_level(spdlog::level::info);
break;
case LogLevel::ARE_LOG_WARN:
logger->set_level(spdlog::level::warn);
break;
case LogLevel::ARE_LOG_ERROR:
logger->set_level(spdlog::level::err);
break;
case LogLevel::ARE_LOG_CRITICAL:
logger->set_level(spdlog::level::critical);
break;
}
} catch (const std::exception& e) {
fprintf(stderr, "[ARE] Error setting log level: %s\n", e.what());
}
} }
} // namespace are } // namespace are