diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/3d/object.h | 3 | ||||
| -rw-r--r-- | src/3d/renderer.h | 6 | ||||
| -rw-r--r-- | src/3d/scene_loader.cc | 36 | ||||
| -rw-r--r-- | src/audio/audio.cc | 12 | ||||
| -rw-r--r-- | src/gpu/demo_effects.h | 31 | ||||
| -rw-r--r-- | src/gpu/effects/chroma_aberration_effect.cc | 48 | ||||
| -rw-r--r-- | src/gpu/effects/flash_effect.cc | 4 | ||||
| -rw-r--r-- | src/gpu/effects/flash_effect.h | 19 | ||||
| -rw-r--r-- | src/gpu/effects/shaders.cc | 3 | ||||
| -rw-r--r-- | src/gpu/uniform_helper.h | 7 | ||||
| -rw-r--r-- | src/test_demo.cc | 14 | ||||
| -rw-r--r-- | src/tests/test_effect_base.cc | 6 | ||||
| -rw-r--r-- | src/tests/test_jittered_audio.cc | 11 | ||||
| -rw-r--r-- | src/tests/test_variable_tempo.cc | 21 | ||||
| -rw-r--r-- | src/util/asset_manager.cc | 34 | ||||
| -rw-r--r-- | src/util/check_return.h | 17 |
16 files changed, 164 insertions, 108 deletions
diff --git a/src/3d/object.h b/src/3d/object.h index dfd31ce..a8eb98c 100644 --- a/src/3d/object.h +++ b/src/3d/object.h @@ -43,7 +43,8 @@ class Object3D { AssetId mesh_asset_id; vec3 local_extent; // Half-extents for AABB (used by meshes for shadows) void* user_data; // For tool-specific data, not for general use - std::shared_ptr<void> shared_user_data; // For tool-specific data managed with shared ownership + std::shared_ptr<void> + shared_user_data; // For tool-specific data managed with shared ownership Object3D(ObjectType t = ObjectType::CUBE) : position(0, 0, 0), rotation(0, 0, 0, 1), scale(1, 1, 1), type(t), diff --git a/src/3d/renderer.h b/src/3d/renderer.h index 94a194d..bf3b497 100644 --- a/src/3d/renderer.h +++ b/src/3d/renderer.h @@ -30,11 +30,11 @@ struct ObjectData { mat4 model; mat4 inv_model; vec4 color; - // params.x = object type (as float), params.y = plane_distance (if applicable) - vec4 params; + // params.x = object type (as float), params.y = plane_distance (if + // applicable) + vec4 params; }; - class Renderer3D { public: void init(WGPUDevice device, WGPUQueue queue, WGPUTextureFormat format); diff --git a/src/3d/scene_loader.cc b/src/3d/scene_loader.cc index 936d8a2..286edca 100644 --- a/src/3d/scene_loader.cc +++ b/src/3d/scene_loader.cc @@ -1,13 +1,13 @@ #include "3d/scene_loader.h" #include "generated/assets.h" +#include "plane_data.h" #include "util/asset_manager.h" #include "util/mini_math.h" #include <cstdio> #include <cstring> -#include <vector> #include <memory> // For std::shared_ptr #include <new> // For std::nothrow -#include "plane_data.h" +#include <vector> bool SceneLoader::LoadScene(Scene& scene, const uint8_t* data, size_t size) { if (!data || size < 16) { // Header size check @@ -77,18 +77,23 @@ bool SceneLoader::LoadScene(Scene& scene, const uint8_t* data, size_t size) { vec3 scale(sx, sy, sz); // Color components (cr, cg, cb, ca) - float cr = *reinterpret_cast<const float*>(data + offset); offset += 4; - float cg = *reinterpret_cast<const float*>(data + offset); offset += 4; - float cb = *reinterpret_cast<const float*>(data + offset); offset += 4; + float cr = *reinterpret_cast<const float*>(data + offset); + offset += 4; + float cg = *reinterpret_cast<const float*>(data + offset); + offset += 4; + float cb = *reinterpret_cast<const float*>(data + offset); + offset += 4; // Read ca, advance offset AFTER reading ca, then construct color - float ca = *reinterpret_cast<const float*>(data + offset); offset += 4; // Offset is now after ca + float ca = *reinterpret_cast<const float*>(data + offset); + offset += 4; // Offset is now after ca vec4 color(cr, cg, cb, ca); // Plane Distance (if type == PLANE) float plane_distance = 0.0f; if (type == ObjectType::PLANE) { // Check bounds before reading plane_distance - if (offset + 4 > size) return false; + if (offset + 4 > size) + return false; plane_distance = *reinterpret_cast<const float*>(data + offset); offset += 4; // Advance offset after reading plane_distance } @@ -96,7 +101,8 @@ bool SceneLoader::LoadScene(Scene& scene, const uint8_t* data, size_t size) { // Mesh Asset Name Length // The offset is now correctly positioned for name_len, // either after ca (if not PLANE) or after plane_distance (if PLANE). - if (offset + 4 > size) return false; + if (offset + 4 > size) + return false; uint32_t name_len = *reinterpret_cast<const uint32_t*>(data + offset); offset += 4; @@ -145,12 +151,14 @@ bool SceneLoader::LoadScene(Scene& scene, const uint8_t* data, size_t size) { // Store plane distance in shared_user_data if it's a plane if (type == ObjectType::PLANE) { - // Allocate PlaneData on the heap and manage with shared_ptr - // Use std::make_shared for exception safety and efficiency - obj.shared_user_data = std::make_shared<PlaneData>(); - // Assign the plane distance - // Safely cast void* to PlaneData* using static_cast on the shared_ptr's get() - static_cast<PlaneData*>(obj.shared_user_data.get())->distance = plane_distance; + // Allocate PlaneData on the heap and manage with shared_ptr + // Use std::make_shared for exception safety and efficiency + obj.shared_user_data = std::make_shared<PlaneData>(); + // Assign the plane distance + // Safely cast void* to PlaneData* using static_cast on the shared_ptr's + // get() + static_cast<PlaneData*>(obj.shared_user_data.get())->distance = + plane_distance; } // Add to scene diff --git a/src/audio/audio.cc b/src/audio/audio.cc index d3880f0..2f485a6 100644 --- a/src/audio/audio.cc +++ b/src/audio/audio.cc @@ -134,9 +134,9 @@ void audio_render_ahead(float music_time, float dt) { } // Clamp to desired chunk size - const int actual_samples = - (available_for_write < chunk_samples) ? available_for_write - : chunk_samples; + const int actual_samples = (available_for_write < chunk_samples) + ? available_for_write + : chunk_samples; const int actual_frames = actual_samples / RING_BUFFER_CHANNELS; // Render directly to ring buffer (NO COPY, NO ALLOCATION) @@ -167,9 +167,9 @@ void audio_render_ahead(float music_time, float dt) { float* second_ptr = g_ring_buffer.get_write_region(&second_avail); if (second_avail > 0) { const int remaining_samples = chunk_samples - actual_samples; - const int second_samples = - (second_avail < remaining_samples) ? second_avail - : remaining_samples; + const int second_samples = (second_avail < remaining_samples) + ? second_avail + : remaining_samples; const int second_frames = second_samples / RING_BUFFER_CHANNELS; synth_render(second_ptr, second_frames); diff --git a/src/gpu/demo_effects.h b/src/gpu/demo_effects.h index d9487fa..36be118 100644 --- a/src/gpu/demo_effects.h +++ b/src/gpu/demo_effects.h @@ -6,11 +6,12 @@ #include "3d/renderer.h" #include "3d/scene.h" #include "effect.h" -#include "gpu/effects/flash_effect.h" // FlashEffect with params support +#include "gpu/effects/flash_effect.h" // FlashEffect with params support #include "gpu/effects/post_process_helper.h" #include "gpu/effects/shaders.h" #include "gpu/gpu.h" #include "gpu/texture_manager.h" +#include "gpu/uniform_helper.h" #include <memory> static const int NUM_PARTICLES = 10000; @@ -100,12 +101,40 @@ class DistortEffect : public PostProcessEffect { void update_bind_group(WGPUTextureView input_view) override; }; +// Parameters for ChromaAberrationEffect (set at construction time) +struct ChromaAberrationParams { + float offset_scale = 0.02f; // Default: 2% screen offset + float angle = 0.0f; // Default: horizontal (0 radians) +}; + +// Uniform data sent to GPU shader +struct ChromaUniforms { + float time; // offset 0 + float beat; // offset 4 + float intensity; // offset 8 + float aspect_ratio; // offset 12 + float width; // offset 16 + float height; // offset 20 + float offset_scale; // offset 24 + float angle; // offset 28 +}; +static_assert(sizeof(ChromaUniforms) == 32, + "ChromaUniforms must be 32 bytes for WGSL alignment"); + class ChromaAberrationEffect : public PostProcessEffect { public: + // Backward compatibility constructor (uses default params) ChromaAberrationEffect(const GpuContext& ctx); + // New parameterized constructor + ChromaAberrationEffect(const GpuContext& ctx, + const ChromaAberrationParams& params); void render(WGPURenderPassEncoder pass, float time, float beat, float intensity, float aspect_ratio) override; void update_bind_group(WGPUTextureView input_view) override; + + private: + ChromaAberrationParams params_; + UniformBuffer<ChromaUniforms> uniforms_; }; class Hybrid3DEffect : public Effect { diff --git a/src/gpu/effects/chroma_aberration_effect.cc b/src/gpu/effects/chroma_aberration_effect.cc index dc28ee5..3e953e3 100644 --- a/src/gpu/effects/chroma_aberration_effect.cc +++ b/src/gpu/effects/chroma_aberration_effect.cc @@ -1,26 +1,46 @@ // This file is part of the 64k demo project. -// It implements the ChromaAberrationEffect. +// It implements the ChromaAberrationEffect with parameterization. #include "gpu/demo_effects.h" +#include "gpu/effects/post_process_helper.h" #include "gpu/gpu.h" // --- ChromaAberrationEffect --- + +// Backward compatibility constructor (delegates to parameterized constructor) ChromaAberrationEffect::ChromaAberrationEffect(const GpuContext& ctx) - : PostProcessEffect(ctx) { - uniforms_ = - gpu_create_buffer(ctx_.device, sizeof(float) * 6, - WGPUBufferUsage_Uniform | WGPUBufferUsage_CopyDst); + : ChromaAberrationEffect(ctx, ChromaAberrationParams{}) { +} + +// Parameterized constructor +ChromaAberrationEffect::ChromaAberrationEffect( + const GpuContext& ctx, const ChromaAberrationParams& params) + : PostProcessEffect(ctx), params_(params) { pipeline_ = create_post_process_pipeline(ctx_.device, ctx_.format, chroma_aberration_shader_wgsl); + uniforms_.init(ctx_.device); } -void ChromaAberrationEffect::render(WGPURenderPassEncoder pass, float t, - float b, float i, float a) { - struct { - float t, b, i, a, w, h; - } u = {t, b, i, a, (float)width_, (float)height_}; - wgpuQueueWriteBuffer(ctx_.queue, uniforms_.buffer, 0, &u, sizeof(u)); - PostProcessEffect::render(pass, t, b, i, a); + +void ChromaAberrationEffect::render(WGPURenderPassEncoder pass, float time, + float beat, float intensity, + float aspect_ratio) { + // Update uniforms with current state and parameters + const ChromaUniforms u = {.time = time, + .beat = beat, + .intensity = intensity, + .aspect_ratio = aspect_ratio, + .width = (float)width_, + .height = (float)height_, + .offset_scale = params_.offset_scale, + .angle = params_.angle}; + uniforms_.update(ctx_.queue, u); + + wgpuRenderPassEncoderSetPipeline(pass, pipeline_); + wgpuRenderPassEncoderSetBindGroup(pass, 0, bind_group_, 0, nullptr); + wgpuRenderPassEncoderDraw(pass, 3, 1, 0, 0); } -void ChromaAberrationEffect::update_bind_group(WGPUTextureView v) { - pp_update_bind_group(ctx_.device, pipeline_, &bind_group_, v, uniforms_); + +void ChromaAberrationEffect::update_bind_group(WGPUTextureView input_view) { + pp_update_bind_group(ctx_.device, pipeline_, &bind_group_, input_view, + uniforms_.get()); } diff --git a/src/gpu/effects/flash_effect.cc b/src/gpu/effects/flash_effect.cc index 1bb4d93..fdd1e1c 100644 --- a/src/gpu/effects/flash_effect.cc +++ b/src/gpu/effects/flash_effect.cc @@ -85,8 +85,8 @@ void FlashEffect::render(WGPURenderPassEncoder pass, float time, float beat, const FlashUniforms u = { .flash_intensity = flash_intensity_, .intensity = intensity, - ._pad1 = {0.0f, 0.0f}, // Padding for vec3 alignment - .color = {r, g, b}, // Time-dependent, computed every frame + ._pad1 = {0.0f, 0.0f}, // Padding for vec3 alignment + .color = {r, g, b}, // Time-dependent, computed every frame ._pad2 = 0.0f}; uniforms_.update(ctx_.queue, u); diff --git a/src/gpu/effects/flash_effect.h b/src/gpu/effects/flash_effect.h index 373b48b..71815d5 100644 --- a/src/gpu/effects/flash_effect.h +++ b/src/gpu/effects/flash_effect.h @@ -9,22 +9,23 @@ // Parameters for FlashEffect (set at construction time) struct FlashEffectParams { - float color[3] = {1.0f, 1.0f, 1.0f}; // Default: white - float decay_rate = 0.98f; // Default: fast decay - float trigger_threshold = 0.7f; // Default: trigger on strong beats + float color[3] = {1.0f, 1.0f, 1.0f}; // Default: white + float decay_rate = 0.98f; // Default: fast decay + float trigger_threshold = 0.7f; // Default: trigger on strong beats }; // Uniform data sent to GPU shader // IMPORTANT: Must match WGSL struct layout with proper alignment // vec3<f32> in WGSL has 16-byte alignment, not 12-byte! struct FlashUniforms { - float flash_intensity; // offset 0 - float intensity; // offset 4 - float _pad1[2]; // offset 8-15 (padding for vec3 alignment) - float color[3]; // offset 16-27 (vec3 aligned to 16 bytes) - float _pad2; // offset 28-31 + float flash_intensity; // offset 0 + float intensity; // offset 4 + float _pad1[2]; // offset 8-15 (padding for vec3 alignment) + float color[3]; // offset 16-27 (vec3 aligned to 16 bytes) + float _pad2; // offset 28-31 }; -static_assert(sizeof(FlashUniforms) == 32, "FlashUniforms must be 32 bytes for WGSL alignment"); +static_assert(sizeof(FlashUniforms) == 32, + "FlashUniforms must be 32 bytes for WGSL alignment"); class FlashEffect : public PostProcessEffect { public: diff --git a/src/gpu/effects/shaders.cc b/src/gpu/effects/shaders.cc index 51e6e41..380b5b4 100644 --- a/src/gpu/effects/shaders.cc +++ b/src/gpu/effects/shaders.cc @@ -33,7 +33,8 @@ void InitShaderComposer() { register_if_exists("common_uniforms", AssetId::ASSET_SHADER_COMMON_UNIFORMS); register_if_exists("math/sdf_shapes", AssetId::ASSET_SHADER_MATH_SDF_SHAPES); register_if_exists("math/sdf_utils", AssetId::ASSET_SHADER_MATH_SDF_UTILS); - register_if_exists("math/common_utils", AssetId::ASSET_SHADER_MATH_COMMON_UTILS); + register_if_exists("math/common_utils", + AssetId::ASSET_SHADER_MATH_COMMON_UTILS); register_if_exists("render/shadows", AssetId::ASSET_SHADER_RENDER_SHADOWS); register_if_exists("render/scene_query_bvh", AssetId::ASSET_SHADER_RENDER_SCENE_QUERY_BVH); diff --git a/src/gpu/uniform_helper.h b/src/gpu/uniform_helper.h index afc4a4b..151153f 100644 --- a/src/gpu/uniform_helper.h +++ b/src/gpu/uniform_helper.h @@ -12,15 +12,14 @@ // UniformBuffer<MyUniforms> uniforms_; // uniforms_.init(device); // uniforms_.update(queue, my_data); -template <typename T> -class UniformBuffer { +template <typename T> class UniformBuffer { public: UniformBuffer() = default; // Initialize the uniform buffer with the device void init(WGPUDevice device) { - buffer_ = gpu_create_buffer(device, sizeof(T), - WGPUBufferUsage_Uniform | WGPUBufferUsage_CopyDst); + buffer_ = gpu_create_buffer( + device, sizeof(T), WGPUBufferUsage_Uniform | WGPUBufferUsage_CopyDst); } // Update the uniform buffer with new data diff --git a/src/test_demo.cc b/src/test_demo.cc index 91c5427..4ec8d70 100644 --- a/src/test_demo.cc +++ b/src/test_demo.cc @@ -3,12 +3,12 @@ #include "audio/audio.h" #include "audio/audio_engine.h" -#include "util/check_return.h" #include "audio/synth.h" #include "generated/assets.h" // Note: uses main demo asset bundle #include "gpu/demo_effects.h" #include "gpu/gpu.h" #include "platform/platform.h" +#include "util/check_return.h" #include <cmath> #include <cstdio> #include <cstdlib> @@ -183,18 +183,18 @@ int main(int argc, char** argv) { } } else if (strcmp(argv[i], "--log-peaks") == 0) { CHECK_RETURN_BEGIN(i + 1 >= argc, 1) - print_usage(argv[0]); - ERROR_MSG("--log-peaks requires a filename argument\n"); - return 1; + print_usage(argv[0]); + ERROR_MSG("--log-peaks requires a filename argument\n"); + return 1; CHECK_RETURN_END log_peaks_file = argv[++i]; } else if (strcmp(argv[i], "--log-peaks-fine") == 0) { log_peaks_fine = true; } else { CHECK_RETURN_BEGIN(true, 1) - print_usage(argv[0]); - ERROR_MSG("Unknown option '%s'\n", argv[i]); - return 1; + print_usage(argv[0]); + ERROR_MSG("Unknown option '%s'\n", argv[i]); + return 1; CHECK_RETURN_END } } diff --git a/src/tests/test_effect_base.cc b/src/tests/test_effect_base.cc index 2534b36..e280e05 100644 --- a/src/tests/test_effect_base.cc +++ b/src/tests/test_effect_base.cc @@ -60,10 +60,12 @@ static void test_offscreen_render_target() { // Note: Buffer mapping may fail on some systems (WebGPU driver issue) // Don't fail the test if readback returns empty buffer if (pixels.empty()) { - fprintf(stdout, " ⚠ Pixel readback skipped (buffer mapping unavailable)\n"); + fprintf(stdout, + " ⚠ Pixel readback skipped (buffer mapping unavailable)\n"); } else { assert(pixels.size() == 256 * 256 * 4 && "Pixel buffer size should match"); - fprintf(stdout, " ✓ Pixel readback succeeded (%zu bytes)\n", pixels.size()); + fprintf(stdout, " ✓ Pixel readback succeeded (%zu bytes)\n", + pixels.size()); } } diff --git a/src/tests/test_jittered_audio.cc b/src/tests/test_jittered_audio.cc index c1376db..d8260ec 100644 --- a/src/tests/test_jittered_audio.cc +++ b/src/tests/test_jittered_audio.cc @@ -64,8 +64,8 @@ void test_jittered_audio_basic() { // Should have consumed some audio (exact amount depends on timing/jitter) // With minimal sleeps and 0.1s sim time, expect 50-1000 frames - assert(frames_consumed > 50); // At least some audio consumed - assert(frames_consumed < 2000); // Not excessive + assert(frames_consumed > 50); // At least some audio consumed + assert(frames_consumed < 2000); // Not excessive // Underruns are acceptable in this test, but shouldn't be excessive assert(underruns < 5); // Less than 5 underruns in 0.1 seconds @@ -133,10 +133,11 @@ void test_jittered_audio_with_acceleration() { // Should have consumed some audio (exact amount depends on timing/jitter) // With minimal sleeps and 0.6s sim time, expect more than basic test - assert(frames_consumed > 200); // At least some audio consumed - assert(frames_consumed < 5000); // Not excessive + assert(frames_consumed > 200); // At least some audio consumed + assert(frames_consumed < 5000); // Not excessive - // During acceleration with jitter, some underruns are expected but not excessive + // During acceleration with jitter, some underruns are expected but not + // excessive assert(underruns < 10); // Less than 10 underruns in 0.6 seconds printf(" ✓ Jittered audio with acceleration PASSED\n"); diff --git a/src/tests/test_variable_tempo.cc b/src/tests/test_variable_tempo.cc index cd83a06..bbc9ebf 100644 --- a/src/tests/test_variable_tempo.cc +++ b/src/tests/test_variable_tempo.cc @@ -32,8 +32,8 @@ static void simulate_tempo(AudioEngine& engine, float& music_time, // Helper: Simulate tempo with variable scaling function static void simulate_tempo_fn(AudioEngine& engine, float& music_time, - float& physical_time, float duration, float dt, - float (*tempo_fn)(float)) { + float& physical_time, float duration, float dt, + float (*tempo_fn)(float)) { const int steps = (int)(duration / dt); for (int i = 0; i < steps; ++i) { physical_time += dt; @@ -96,9 +96,7 @@ void test_2x_speedup_reset_trick() { // Phase 1: Accelerate from 1.0x to 2.0x over 5 seconds printf(" Phase 1: Accelerating 1.0x → 2.0x\n"); - auto accel_fn = [](float t) { - return fminf(1.0f + (t / 5.0f), 2.0f); - }; + auto accel_fn = [](float t) { return fminf(1.0f + (t / 5.0f), 2.0f); }; simulate_tempo_fn(engine, music_time, physical_time, 5.0f, dt, accel_fn); const float tempo_scale = accel_fn(physical_time); @@ -133,9 +131,7 @@ void test_2x_slowdown_reset_trick() { // Phase 1: Decelerate from 1.0x to 0.5x over 5 seconds printf(" Phase 1: Decelerating 1.0x → 0.5x\n"); - auto decel_fn = [](float t) { - return fmaxf(1.0f - (t / 10.0f), 0.5f); - }; + auto decel_fn = [](float t) { return fmaxf(1.0f - (t / 10.0f), 0.5f); }; simulate_tempo_fn(engine, music_time, physical_time, 5.0f, dt, decel_fn); const float tempo_scale = decel_fn(physical_time); @@ -209,8 +205,9 @@ void test_continuous_acceleration() { auto accel_fn = [min_tempo, max_tempo](float t) { const float progress = t / 10.0f; - return fmaxf(min_tempo, fminf(max_tempo, - min_tempo + progress * (max_tempo - min_tempo))); + return fmaxf( + min_tempo, + fminf(max_tempo, min_tempo + progress * (max_tempo - min_tempo))); }; const int steps = (int)(10.0f / dt); @@ -252,9 +249,7 @@ void test_oscillating_tempo() { printf(" Oscillating tempo: 0.8x ↔ 1.2x\n"); - auto oscil_fn = [](float t) { - return 1.0f + 0.2f * sinf(t * 2.0f); - }; + auto oscil_fn = [](float t) { return 1.0f + 0.2f * sinf(t * 2.0f); }; const int steps = 100; for (int i = 0; i < steps; ++i) { diff --git a/src/util/asset_manager.cc b/src/util/asset_manager.cc index 2a41876..a0e2a97 100644 --- a/src/util/asset_manager.cc +++ b/src/util/asset_manager.cc @@ -86,11 +86,11 @@ const uint8_t* GetAsset(AssetId asset_id, size_t* out_size) { } CHECK_RETURN_BEGIN(proc_gen_func_ptr == nullptr, nullptr) - if (out_size) - *out_size = 0; - ERROR_MSG("Unknown procedural function at runtime: %s", - source_record.proc_func_name_str); - return nullptr; + if (out_size) + *out_size = 0; + ERROR_MSG("Unknown procedural function at runtime: %s", + source_record.proc_func_name_str); + return nullptr; CHECK_RETURN_END // For this demo, assuming procedural textures are RGBA8 256x256 (for @@ -101,10 +101,10 @@ const uint8_t* GetAsset(AssetId asset_id, size_t* out_size) { size_t data_size = header_size + (size_t)width * height * 4; // RGBA8 uint8_t* generated_data = new (std::nothrow) uint8_t[data_size]; CHECK_RETURN_BEGIN(!generated_data, nullptr) - if (out_size) - *out_size = 0; - ERROR_MSG("Failed to allocate memory for procedural asset"); - return nullptr; + if (out_size) + *out_size = 0; + ERROR_MSG("Failed to allocate memory for procedural asset"); + return nullptr; CHECK_RETURN_END // Write header @@ -114,15 +114,15 @@ const uint8_t* GetAsset(AssetId asset_id, size_t* out_size) { // Generate data after header CHECK_RETURN_BEGIN(!proc_gen_func_ptr(generated_data + header_size, width, - height, source_record.proc_params, - source_record.num_proc_params), + height, source_record.proc_params, + source_record.num_proc_params), nullptr) - delete[] generated_data; - if (out_size) - *out_size = 0; - ERROR_MSG("Procedural generation failed for asset: %s", - source_record.proc_func_name_str); - return nullptr; + delete[] generated_data; + if (out_size) + *out_size = 0; + ERROR_MSG("Procedural generation failed for asset: %s", + source_record.proc_func_name_str); + return nullptr; CHECK_RETURN_END cached_record.data = generated_data; diff --git a/src/util/check_return.h b/src/util/check_return.h index cd2c293..89ed4bc 100644 --- a/src/util/check_return.h +++ b/src/util/check_return.h @@ -45,17 +45,14 @@ // CHECK_RETURN_END // // Allows cleanup code before return. -#define CHECK_RETURN_BEGIN(cond, retval) \ - if (cond) { - +#define CHECK_RETURN_BEGIN(cond, retval) if (cond) { #define ERROR_MSG(...) \ do { \ fprintf(stderr, "Error: " __VA_ARGS__); \ fprintf(stderr, " [%s:%d]\n", __FILE__, __LINE__); \ } while (0) -#define CHECK_RETURN_END \ - } +#define CHECK_RETURN_END } // Warning message (non-fatal, execution continues) // Usage: WARN_IF(count == 0, "No items found"); @@ -84,7 +81,6 @@ // Block-based check - cleanup code preserved, messages stripped #define CHECK_RETURN_BEGIN(cond, retval) if (cond) { - #define ERROR_MSG(...) ((void)0) #define CHECK_RETURN_END } @@ -103,7 +99,8 @@ // CHECK_RETURN_IF: // - Simple error checks with no cleanup needed (90% of cases) // - Input validation: CHECK_RETURN_IF(argc < 2, 1, "Too few arguments") -// - Null checks: CHECK_RETURN_IF(ptr == nullptr, nullptr, "Not found: %s", name) +// - Null checks: CHECK_RETURN_IF(ptr == nullptr, nullptr, "Not found: %s", +// name) // - Range checks: CHECK_RETURN_IF(x < 0 || x > max, -1, "Out of range") // // CHECK_RETURN_BEGIN/END: @@ -141,13 +138,15 @@ // - Programming errors (assertion failures, invariant violations) // - Corrupted state that cannot be recovered // - Internal consistency checks -// - Example: FATAL_CHECK(idx >= size, "Index out of bounds: %d >= %d", idx, size) +// - Example: FATAL_CHECK(idx >= size, "Index out of bounds: %d >= %d", idx, +// size) // // Use CHECK_RETURN for: // - Recoverable errors (invalid input, missing files) // - Runtime configuration issues // - API parameter validation -// - Example: CHECK_RETURN_IF(file == nullptr, false, "File not found: %s", path) +// - Example: CHECK_RETURN_IF(file == nullptr, false, "File not found: %s", +// path) // // Key difference: // - FATAL_XXX: abort() - program terminates |
