summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/3d/object.h3
-rw-r--r--src/3d/renderer.h6
-rw-r--r--src/3d/scene_loader.cc36
-rw-r--r--src/audio/audio.cc12
-rw-r--r--src/gpu/demo_effects.h31
-rw-r--r--src/gpu/effects/chroma_aberration_effect.cc48
-rw-r--r--src/gpu/effects/flash_effect.cc4
-rw-r--r--src/gpu/effects/flash_effect.h19
-rw-r--r--src/gpu/effects/shaders.cc3
-rw-r--r--src/gpu/uniform_helper.h7
-rw-r--r--src/test_demo.cc14
-rw-r--r--src/tests/test_effect_base.cc6
-rw-r--r--src/tests/test_jittered_audio.cc11
-rw-r--r--src/tests/test_variable_tempo.cc21
-rw-r--r--src/util/asset_manager.cc34
-rw-r--r--src/util/check_return.h17
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