summaryrefslogtreecommitdiff
path: root/src/tests
diff options
context:
space:
mode:
authorskal <pascal.massimino@gmail.com>2026-02-08 07:40:29 +0100
committerskal <pascal.massimino@gmail.com>2026-02-08 07:40:29 +0100
commitc9195f997f3e797f03ab90464e4158717198a167 (patch)
tree331304f42870246efdc64cc97ad42de59444ef3a /src/tests
parentb8e6929cafa41681f0b27ac104c9cf1d4e510837 (diff)
style: Apply clang-format to all source files
Diffstat (limited to 'src/tests')
-rw-r--r--src/tests/effect_test_helpers.cc41
-rw-r--r--src/tests/effect_test_helpers.h17
-rw-r--r--src/tests/offscreen_render_target.cc20
-rw-r--r--src/tests/offscreen_render_target.h28
-rw-r--r--src/tests/test_3d_render.cc12
-rw-r--r--src/tests/test_demo_effects.cc108
-rw-r--r--src/tests/test_effect_base.cc33
-rw-r--r--src/tests/test_fft.cc45
-rw-r--r--src/tests/test_mesh.cc346
-rw-r--r--src/tests/test_post_process_helper.cc81
-rw-r--r--src/tests/test_scene_loader.cc225
-rw-r--r--src/tests/test_sequence.cc3
-rw-r--r--src/tests/test_shader_compilation.cc14
-rw-r--r--src/tests/test_spectral_brush.cc53
-rw-r--r--src/tests/test_texture_manager.cc34
-rw-r--r--src/tests/test_wav_dump.cc9
-rw-r--r--src/tests/webgpu_test_fixture.cc4
-rw-r--r--src/tests/webgpu_test_fixture.h35
18 files changed, 610 insertions, 498 deletions
diff --git a/src/tests/effect_test_helpers.cc b/src/tests/effect_test_helpers.cc
index a31c447..8183362 100644
--- a/src/tests/effect_test_helpers.cc
+++ b/src/tests/effect_test_helpers.cc
@@ -2,7 +2,7 @@
// It implements reusable test helpers for GPU effect testing.
// Provides pixel validation and lifecycle testing utilities.
-#if !defined(STRIP_ALL) // Test code only - zero size impact on final binary
+#if !defined(STRIP_ALL) // Test code only - zero size impact on final binary
#include "effect_test_helpers.h"
#include "gpu/effect.h"
@@ -13,27 +13,24 @@
// ============================================================================
bool validate_pixels(
- const std::vector<uint8_t>& pixels,
- int width,
- int height,
+ const std::vector<uint8_t>& pixels, int width, int height,
std::function<bool(uint8_t r, uint8_t g, uint8_t b, uint8_t a)> predicate) {
const size_t pixel_count = width * height;
for (size_t i = 0; i < pixel_count; ++i) {
- const size_t offset = i * 4; // BGRA8 = 4 bytes/pixel
+ const size_t offset = i * 4; // BGRA8 = 4 bytes/pixel
const uint8_t b = pixels[offset + 0];
const uint8_t g = pixels[offset + 1];
const uint8_t r = pixels[offset + 2];
const uint8_t a = pixels[offset + 3];
if (predicate(r, g, b, a)) {
- return true; // At least one pixel matches
+ return true; // At least one pixel matches
}
}
- return false; // No pixels matched
+ return false; // No pixels matched
}
-bool has_rendered_content(const std::vector<uint8_t>& pixels,
- int width,
+bool has_rendered_content(const std::vector<uint8_t>& pixels, int width,
int height) {
return validate_pixels(pixels, width, height,
[](uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
@@ -41,13 +38,9 @@ bool has_rendered_content(const std::vector<uint8_t>& pixels,
});
}
-bool all_pixels_match_color(const std::vector<uint8_t>& pixels,
- int width,
- int height,
- uint8_t target_r,
- uint8_t target_g,
- uint8_t target_b,
- uint8_t tolerance) {
+bool all_pixels_match_color(const std::vector<uint8_t>& pixels, int width,
+ int height, uint8_t target_r, uint8_t target_g,
+ uint8_t target_b, uint8_t tolerance) {
const size_t pixel_count = width * height;
for (size_t i = 0; i < pixel_count; ++i) {
const size_t offset = i * 4;
@@ -61,10 +54,10 @@ bool all_pixels_match_color(const std::vector<uint8_t>& pixels,
if (diff_r * diff_r + diff_g * diff_g + diff_b * diff_b >
tolerance * tolerance) {
- return false; // At least one pixel doesn't match
+ return false; // At least one pixel doesn't match
}
}
- return true; // All pixels match
+ return true; // All pixels match
}
uint64_t hash_pixels(const std::vector<uint8_t>& pixels) {
@@ -87,7 +80,7 @@ bool test_effect_lifecycle(Effect* effect, MainSequence* main_seq) {
// Check initial state
if (effect->is_initialized) {
- return false; // Should not be initialized yet
+ return false; // Should not be initialized yet
}
// Initialize effect
@@ -95,10 +88,10 @@ bool test_effect_lifecycle(Effect* effect, MainSequence* main_seq) {
// Check initialized state
if (!effect->is_initialized) {
- return false; // Should be initialized now
+ return false; // Should be initialized now
}
- return true; // Lifecycle test passed
+ return true; // Lifecycle test passed
}
bool test_effect_render_smoke(Effect* effect) {
@@ -108,14 +101,14 @@ bool test_effect_render_smoke(Effect* effect) {
// If this doesn't crash, consider it a success
// Note: This requires the effect to be initialized first
if (!effect->is_initialized) {
- return false; // Cannot render uninitialized effect
+ return false; // Cannot render uninitialized effect
}
// We cannot actually render without a full render pass setup
// This is a placeholder for more sophisticated render testing
// Real render tests should use OffscreenRenderTarget
- return true; // Smoke test passed (no crash)
+ return true; // Smoke test passed (no crash)
}
-#endif /* !defined(STRIP_ALL) */
+#endif /* !defined(STRIP_ALL) */
diff --git a/src/tests/effect_test_helpers.h b/src/tests/effect_test_helpers.h
index d48daa7..33355ee 100644
--- a/src/tests/effect_test_helpers.h
+++ b/src/tests/effect_test_helpers.h
@@ -19,24 +19,17 @@ class MainSequence;
// Validate pixels using a predicate function
// Returns true if at least one pixel matches the predicate
bool validate_pixels(
- const std::vector<uint8_t>& pixels,
- int width,
- int height,
+ const std::vector<uint8_t>& pixels, int width, int height,
std::function<bool(uint8_t r, uint8_t g, uint8_t b, uint8_t a)> predicate);
// Check if any pixel is non-black (rendered something)
-bool has_rendered_content(const std::vector<uint8_t>& pixels,
- int width,
+bool has_rendered_content(const std::vector<uint8_t>& pixels, int width,
int height);
// Check if all pixels match a specific color (within tolerance)
-bool all_pixels_match_color(const std::vector<uint8_t>& pixels,
- int width,
- int height,
- uint8_t r,
- uint8_t g,
- uint8_t b,
- uint8_t tolerance = 5);
+bool all_pixels_match_color(const std::vector<uint8_t>& pixels, int width,
+ int height, uint8_t r, uint8_t g, uint8_t b,
+ uint8_t tolerance = 5);
// Compute simple hash of pixel data (for deterministic output checks)
uint64_t hash_pixels(const std::vector<uint8_t>& pixels);
diff --git a/src/tests/offscreen_render_target.cc b/src/tests/offscreen_render_target.cc
index 81ad082..36b7b26 100644
--- a/src/tests/offscreen_render_target.cc
+++ b/src/tests/offscreen_render_target.cc
@@ -2,7 +2,7 @@
// It implements offscreen rendering for headless GPU testing.
// Provides pixel readback for validation.
-#if !defined(STRIP_ALL) // Test code only - zero size impact on final binary
+#if !defined(STRIP_ALL) // Test code only - zero size impact on final binary
#include "offscreen_render_target.h"
#include <cassert>
@@ -10,14 +10,10 @@
#include <cstring>
OffscreenRenderTarget::OffscreenRenderTarget(WGPUInstance instance,
- WGPUDevice device,
- int width,
+ WGPUDevice device, int width,
int height,
WGPUTextureFormat format)
- : instance_(instance),
- device_(device),
- width_(width),
- height_(height),
+ : instance_(instance), device_(device), width_(width), height_(height),
format_(format) {
// Create offscreen texture
const WGPUTextureDescriptor texture_desc = {
@@ -61,7 +57,7 @@ void OffscreenRenderTarget::map_callback(WGPUMapAsyncStatus status,
}
WGPUBuffer OffscreenRenderTarget::create_staging_buffer() {
- const size_t buffer_size = width_ * height_ * 4; // BGRA8 = 4 bytes/pixel
+ const size_t buffer_size = width_ * height_ * 4; // BGRA8 = 4 bytes/pixel
const WGPUBufferDescriptor buffer_desc = {
.usage = WGPUBufferUsage_CopyDst | WGPUBufferUsage_MapRead,
.size = buffer_size,
@@ -70,7 +66,7 @@ WGPUBuffer OffscreenRenderTarget::create_staging_buffer() {
}
std::vector<uint8_t> OffscreenRenderTarget::read_pixels() {
- const size_t buffer_size = width_ * height_ * 4; // BGRA8
+ const size_t buffer_size = width_ * height_ * 4; // BGRA8
std::vector<uint8_t> pixels(buffer_size);
// Create staging buffer for readback
@@ -99,7 +95,7 @@ std::vector<uint8_t> OffscreenRenderTarget::read_pixels() {
};
const WGPUExtent3D copy_size = {static_cast<uint32_t>(width_),
- static_cast<uint32_t>(height_), 1};
+ static_cast<uint32_t>(height_), 1};
wgpuCommandEncoderCopyTextureToBuffer(encoder, &src, &dst, &copy_size);
@@ -150,7 +146,7 @@ std::vector<uint8_t> OffscreenRenderTarget::read_pixels() {
if (map_state.status != WGPUMapAsyncStatus_Success) {
fprintf(stderr, "Buffer mapping failed: %d\n", map_state.status);
wgpuBufferRelease(staging);
- return pixels; // Return empty
+ return pixels; // Return empty
}
// Copy data from mapped buffer
@@ -167,4 +163,4 @@ std::vector<uint8_t> OffscreenRenderTarget::read_pixels() {
return pixels;
}
-#endif /* !defined(STRIP_ALL) */
+#endif /* !defined(STRIP_ALL) */
diff --git a/src/tests/offscreen_render_target.h b/src/tests/offscreen_render_target.h
index 4163ec1..10c12aa 100644
--- a/src/tests/offscreen_render_target.h
+++ b/src/tests/offscreen_render_target.h
@@ -13,19 +13,27 @@
class OffscreenRenderTarget {
public:
// Create an offscreen render target with specified dimensions
- OffscreenRenderTarget(WGPUInstance instance,
- WGPUDevice device,
- int width,
- int height,
- WGPUTextureFormat format = WGPUTextureFormat_BGRA8Unorm);
+ OffscreenRenderTarget(
+ WGPUInstance instance, WGPUDevice device, int width, int height,
+ WGPUTextureFormat format = WGPUTextureFormat_BGRA8Unorm);
~OffscreenRenderTarget();
// Accessors
- WGPUTexture texture() const { return texture_; }
- WGPUTextureView view() const { return view_; }
- int width() const { return width_; }
- int height() const { return height_; }
- WGPUTextureFormat format() const { return format_; }
+ WGPUTexture texture() const {
+ return texture_;
+ }
+ WGPUTextureView view() const {
+ return view_;
+ }
+ int width() const {
+ return width_;
+ }
+ int height() const {
+ return height_;
+ }
+ WGPUTextureFormat format() const {
+ return format_;
+ }
// Read pixels from the render target
// Returns BGRA8 pixel data (width * height * 4 bytes)
diff --git a/src/tests/test_3d_render.cc b/src/tests/test_3d_render.cc
index a7c74e1..fa13a43 100644
--- a/src/tests/test_3d_render.cc
+++ b/src/tests/test_3d_render.cc
@@ -272,18 +272,18 @@ int main(int argc, char** argv) {
Renderer3D::SetDebugEnabled(true);
VisualDebug& dbg = g_renderer.GetVisualDebug();
dbg.add_cross(vec3(0, 0, 0), 1.0f, vec3(1, 0, 0));
- dbg.add_sphere(vec3(std::sin(time) * 2.0f, 3.0f, std::cos(time) * 2.0f), 0.5f,
- vec3(0, 1, 1));
+ dbg.add_sphere(vec3(std::sin(time) * 2.0f, 3.0f, std::cos(time) * 2.0f),
+ 0.5f, vec3(0, 1, 1));
dbg.add_line(vec3(0, 0, 0), vec3(0, 5, 0), vec3(1, 0, 1));
-
+
// Cone (Spotlight visualization)
dbg.add_cone(vec3(0, 5, 0), vec3(0, -1, 0), 2.0f, 1.0f, vec3(1, 1, 0));
// Trajectory path
std::vector<vec3> path;
- for(int i=0; i<=32; ++i) {
- float a = i * 6.28318f / 32.0f;
- path.push_back(vec3(std::sin(a)*4.0f, 0.5f, std::cos(a)*4.0f));
+ for (int i = 0; i <= 32; ++i) {
+ float a = i * 6.28318f / 32.0f;
+ path.push_back(vec3(std::sin(a) * 4.0f, 0.5f, std::cos(a) * 4.0f));
}
dbg.add_trajectory(path, vec3(0, 0.5f, 1.0f));
#endif
diff --git a/src/tests/test_demo_effects.cc b/src/tests/test_demo_effects.cc
index ec1d68c..3c40bc5 100644
--- a/src/tests/test_demo_effects.cc
+++ b/src/tests/test_demo_effects.cc
@@ -1,23 +1,31 @@
// This file is part of the 64k demo project.
// It tests all demo effect classes for basic construction and initialization.
-// Validates that every effect can be instantiated and initialized without crashes.
+// Validates that every effect can be instantiated and initialized without
+// crashes.
//
// MAINTENANCE REQUIREMENT: When adding a new effect to demo_effects.h:
-// 1. Add it to the appropriate test list (post_process_effects or scene_effects)
+// 1. Add it to the appropriate test list (post_process_effects or
+// scene_effects)
// 2. Update EXPECTED_POST_PROCESS_COUNT or EXPECTED_SCENE_COUNT below
// 3. Run test to verify: ./build/test_demo_effects
-// 4. If the effect requires Renderer3D, add it to requires_3d check in test_scene_effects()
+// 4. If the effect requires Renderer3D, add it to requires_3d check in
+// test_scene_effects()
-#if !defined(STRIP_ALL) // Test code only - zero size impact on final binary
+#if !defined(STRIP_ALL) // Test code only - zero size impact on final binary
// Expected effect counts - UPDATE THESE when adding new effects!
-static constexpr int EXPECTED_POST_PROCESS_COUNT = 8; // FlashEffect, PassthroughEffect, GaussianBlurEffect, ChromaAberrationEffect, DistortEffect, SolarizeEffect, FadeEffect, ThemeModulationEffect
-static constexpr int EXPECTED_SCENE_COUNT = 6; // HeptagonEffect, ParticlesEffect, ParticleSprayEffect, MovingEllipseEffect, FlashCubeEffect, Hybrid3DEffect
+static constexpr int EXPECTED_POST_PROCESS_COUNT =
+ 8; // FlashEffect, PassthroughEffect, GaussianBlurEffect,
+ // ChromaAberrationEffect, DistortEffect, SolarizeEffect, FadeEffect,
+ // ThemeModulationEffect
+static constexpr int EXPECTED_SCENE_COUNT =
+ 6; // HeptagonEffect, ParticlesEffect, ParticleSprayEffect,
+ // MovingEllipseEffect, FlashCubeEffect, Hybrid3DEffect
#include "effect_test_helpers.h"
-#include "webgpu_test_fixture.h"
#include "gpu/demo_effects.h"
#include "gpu/effect.h"
+#include "webgpu_test_fixture.h"
#include <cassert>
#include <cstdio>
#include <cstring>
@@ -26,10 +34,8 @@ static constexpr int EXPECTED_SCENE_COUNT = 6; // HeptagonEffect, ParticlesEffe
// Helper: Test effect construction and initialization
// Returns: 0=failed, 1=passed, 2=skipped (requires full 3D setup)
-static int test_effect_smoke(const char* name,
- std::shared_ptr<Effect> effect,
- MainSequence* main_seq,
- bool requires_3d = false) {
+static int test_effect_smoke(const char* name, std::shared_ptr<Effect> effect,
+ MainSequence* main_seq, bool requires_3d = false) {
fprintf(stdout, " Testing %s...\n", name);
// Check construction
@@ -53,7 +59,7 @@ static int test_effect_smoke(const char* name,
// These will fail in init_test() environment - skip them gracefully
if (requires_3d) {
fprintf(stdout, " ⚠ Skipped (requires full 3D pipeline setup)\n");
- return 2; // Skipped
+ return 2; // Skipped
}
seq->init(main_seq);
@@ -65,7 +71,7 @@ static int test_effect_smoke(const char* name,
}
fprintf(stdout, " ✓ %s construction and initialization OK\n", name);
- return 1; // Passed
+ return 1; // Passed
}
// Test 1: Post-process effects
@@ -83,24 +89,17 @@ static void test_post_process_effects() {
// Test each post-process effect
std::vector<std::pair<const char*, std::shared_ptr<Effect>>> effects = {
- {"FlashEffect",
- std::make_shared<FlashEffect>(fixture.ctx())},
- {"PassthroughEffect",
- std::make_shared<PassthroughEffect>(fixture.ctx())},
+ {"FlashEffect", std::make_shared<FlashEffect>(fixture.ctx())},
+ {"PassthroughEffect", std::make_shared<PassthroughEffect>(fixture.ctx())},
{"GaussianBlurEffect",
std::make_shared<GaussianBlurEffect>(fixture.ctx())},
{"ChromaAberrationEffect",
- std::make_shared<ChromaAberrationEffect>(
- fixture.ctx())},
- {"DistortEffect",
- std::make_shared<DistortEffect>(fixture.ctx())},
- {"SolarizeEffect",
- std::make_shared<SolarizeEffect>(fixture.ctx())},
- {"FadeEffect",
- std::make_shared<FadeEffect>(fixture.ctx())},
+ std::make_shared<ChromaAberrationEffect>(fixture.ctx())},
+ {"DistortEffect", std::make_shared<DistortEffect>(fixture.ctx())},
+ {"SolarizeEffect", std::make_shared<SolarizeEffect>(fixture.ctx())},
+ {"FadeEffect", std::make_shared<FadeEffect>(fixture.ctx())},
{"ThemeModulationEffect",
- std::make_shared<ThemeModulationEffect>(
- fixture.ctx())},
+ std::make_shared<ThemeModulationEffect>(fixture.ctx())},
};
int passed = 0;
@@ -121,10 +120,15 @@ static void test_post_process_effects() {
// Validation: Ensure test coverage matches expected count
const int tested_count = static_cast<int>(effects.size());
if (tested_count != EXPECTED_POST_PROCESS_COUNT) {
- fprintf(stderr, " ✗ COVERAGE ERROR: Expected %d post-process effects, but only tested %d!\n",
+ fprintf(stderr,
+ " ✗ COVERAGE ERROR: Expected %d post-process effects, but only "
+ "tested %d!\n",
EXPECTED_POST_PROCESS_COUNT, tested_count);
- fprintf(stderr, " ✗ Did you add a new post-process effect without updating the test?\n");
- fprintf(stderr, " ✗ Update EXPECTED_POST_PROCESS_COUNT in test_demo_effects.cc\n");
+ fprintf(stderr,
+ " ✗ Did you add a new post-process effect without updating the "
+ "test?\n");
+ fprintf(stderr,
+ " ✗ Update EXPECTED_POST_PROCESS_COUNT in test_demo_effects.cc\n");
assert(false && "Post-process effect count mismatch - update test!");
}
}
@@ -144,18 +148,14 @@ static void test_scene_effects() {
// Test each scene effect
std::vector<std::pair<const char*, std::shared_ptr<Effect>>> effects = {
- {"HeptagonEffect",
- std::make_shared<HeptagonEffect>(fixture.ctx())},
- {"ParticlesEffect",
- std::make_shared<ParticlesEffect>(fixture.ctx())},
+ {"HeptagonEffect", std::make_shared<HeptagonEffect>(fixture.ctx())},
+ {"ParticlesEffect", std::make_shared<ParticlesEffect>(fixture.ctx())},
{"ParticleSprayEffect",
std::make_shared<ParticleSprayEffect>(fixture.ctx())},
{"MovingEllipseEffect",
std::make_shared<MovingEllipseEffect>(fixture.ctx())},
- {"FlashCubeEffect",
- std::make_shared<FlashCubeEffect>(fixture.ctx())},
- {"Hybrid3DEffect",
- std::make_shared<Hybrid3DEffect>(fixture.ctx())},
+ {"FlashCubeEffect", std::make_shared<FlashCubeEffect>(fixture.ctx())},
+ {"Hybrid3DEffect", std::make_shared<Hybrid3DEffect>(fixture.ctx())},
};
int passed = 0;
@@ -183,10 +183,14 @@ static void test_scene_effects() {
// Validation: Ensure test coverage matches expected count
const int tested_count = static_cast<int>(effects.size());
if (tested_count != EXPECTED_SCENE_COUNT) {
- fprintf(stderr, " ✗ COVERAGE ERROR: Expected %d scene effects, but only tested %d!\n",
- EXPECTED_SCENE_COUNT, tested_count);
- fprintf(stderr, " ✗ Did you add a new scene effect without updating the test?\n");
- fprintf(stderr, " ✗ Update EXPECTED_SCENE_COUNT in test_demo_effects.cc\n");
+ fprintf(
+ stderr,
+ " ✗ COVERAGE ERROR: Expected %d scene effects, but only tested %d!\n",
+ EXPECTED_SCENE_COUNT, tested_count);
+ fprintf(stderr,
+ " ✗ Did you add a new scene effect without updating the test?\n");
+ fprintf(stderr,
+ " ✗ Update EXPECTED_SCENE_COUNT in test_demo_effects.cc\n");
assert(false && "Scene effect count mismatch - update test!");
}
}
@@ -202,21 +206,19 @@ static void test_effect_type_classification() {
}
// Post-process effects should return true
- auto flash = std::make_shared<FlashEffect>(
- fixture.ctx());
+ auto flash = std::make_shared<FlashEffect>(fixture.ctx());
assert(flash->is_post_process() && "FlashEffect should be post-process");
- auto blur = std::make_shared<GaussianBlurEffect>(
- fixture.ctx());
- assert(blur->is_post_process() && "GaussianBlurEffect should be post-process");
+ auto blur = std::make_shared<GaussianBlurEffect>(fixture.ctx());
+ assert(blur->is_post_process() &&
+ "GaussianBlurEffect should be post-process");
// Scene effects should return false
- auto heptagon = std::make_shared<HeptagonEffect>(
- fixture.ctx());
- assert(!heptagon->is_post_process() && "HeptagonEffect should NOT be post-process");
+ auto heptagon = std::make_shared<HeptagonEffect>(fixture.ctx());
+ assert(!heptagon->is_post_process() &&
+ "HeptagonEffect should NOT be post-process");
- auto particles = std::make_shared<ParticlesEffect>(
- fixture.ctx());
+ auto particles = std::make_shared<ParticlesEffect>(fixture.ctx());
assert(!particles->is_post_process() &&
"ParticlesEffect should NOT be post-process");
@@ -234,4 +236,4 @@ int main() {
return 0;
}
-#endif /* !defined(STRIP_ALL) */
+#endif /* !defined(STRIP_ALL) */
diff --git a/src/tests/test_effect_base.cc b/src/tests/test_effect_base.cc
index 8180535..5dc2dcc 100644
--- a/src/tests/test_effect_base.cc
+++ b/src/tests/test_effect_base.cc
@@ -3,10 +3,10 @@
// Verifies effect initialization, activation, and basic rendering.
#include "effect_test_helpers.h"
-#include "offscreen_render_target.h"
-#include "webgpu_test_fixture.h"
#include "gpu/demo_effects.h"
#include "gpu/effect.h"
+#include "offscreen_render_target.h"
+#include "webgpu_test_fixture.h"
#include <cassert>
#include <cstdio>
#include <memory>
@@ -72,8 +72,7 @@ static void test_effect_construction() {
}
// Create FlashEffect (simple post-process effect)
- auto effect = std::make_shared<FlashEffect>(
- fixture.ctx());
+ auto effect = std::make_shared<FlashEffect>(fixture.ctx());
assert(!effect->is_initialized && "Effect should not be initialized yet");
@@ -95,8 +94,7 @@ static void test_effect_initialization() {
main_seq.init_test(fixture.ctx());
// Create FlashEffect
- auto effect = std::make_shared<FlashEffect>(
- fixture.ctx());
+ auto effect = std::make_shared<FlashEffect>(fixture.ctx());
assert(!effect->is_initialized && "Effect should not be initialized yet");
@@ -107,7 +105,8 @@ static void test_effect_initialization() {
// Initialize sequence (this sets effect->is_initialized)
seq->init(&main_seq);
- assert(effect->is_initialized && "Effect should be initialized after Sequence::init()");
+ assert(effect->is_initialized &&
+ "Effect should be initialized after Sequence::init()");
fprintf(stdout, " ✓ FlashEffect initialized via Sequence::init()\n");
}
@@ -129,10 +128,10 @@ static void test_sequence_add_effect() {
auto seq = std::make_shared<Sequence>();
// Create effect
- auto effect = std::make_shared<FlashEffect>(
- fixture.ctx());
+ auto effect = std::make_shared<FlashEffect>(fixture.ctx());
- assert(!effect->is_initialized && "Effect should not be initialized before Sequence::init()");
+ assert(!effect->is_initialized &&
+ "Effect should not be initialized before Sequence::init()");
// Add effect to sequence (time range: 0.0 - 10.0, priority 0)
seq->add_effect(effect, 0.0f, 10.0f, 0);
@@ -140,9 +139,12 @@ static void test_sequence_add_effect() {
// Initialize sequence (this should initialize the effect)
seq->init(&main_seq);
- assert(effect->is_initialized && "Effect should be initialized after Sequence::init()");
+ assert(effect->is_initialized &&
+ "Effect should be initialized after Sequence::init()");
- fprintf(stdout, " ✓ Effect added to sequence and initialized (time=0.0-10.0, priority=0)\n");
+ fprintf(stdout,
+ " ✓ Effect added to sequence and initialized (time=0.0-10.0, "
+ "priority=0)\n");
}
// Test 6: Sequence activation logic
@@ -159,8 +161,7 @@ static void test_sequence_activation() {
main_seq.init_test(fixture.ctx());
auto seq = std::make_shared<Sequence>();
- auto effect = std::make_shared<FlashEffect>(
- fixture.ctx());
+ auto effect = std::make_shared<FlashEffect>(fixture.ctx());
// Effect active from 5.0 to 10.0 seconds
seq->add_effect(effect, 5.0f, 10.0f, 0);
@@ -213,7 +214,7 @@ static void test_pixel_helpers() {
"Black frame should have no content");
std::vector<uint8_t> colored_frame(256 * 256 * 4, 0);
- colored_frame[0] = 255; // Set one red pixel
+ colored_frame[0] = 255; // Set one red pixel
assert(has_rendered_content(colored_frame, 256, 256) &&
"Colored frame should have content");
@@ -222,7 +223,7 @@ static void test_pixel_helpers() {
// Test all_pixels_match_color
std::vector<uint8_t> red_frame(256 * 256 * 4, 0);
for (size_t i = 0; i < 256 * 256; ++i) {
- red_frame[i * 4 + 2] = 255; // BGRA: Red in position 2
+ red_frame[i * 4 + 2] = 255; // BGRA: Red in position 2
}
assert(all_pixels_match_color(red_frame, 256, 256, 255, 0, 0, 5) &&
"Red frame should match red color");
diff --git a/src/tests/test_fft.cc b/src/tests/test_fft.cc
index ab5210b..2151608 100644
--- a/src/tests/test_fft.cc
+++ b/src/tests/test_fft.cc
@@ -43,23 +43,18 @@ static void idct_reference(const float* input, float* output, size_t N) {
}
// Compare two arrays with tolerance
-// Note: FFT-based DCT accumulates slightly more rounding error than O(N²) direct method
-// A tolerance of 5e-3 is acceptable for audio applications (< -46 dB error)
-// Some input patterns (e.g., impulse at N/2, high-frequency sinusoids) have higher
-// numerical error due to reordering and accumulated floating-point error
-static bool arrays_match(const float* a,
- const float* b,
- size_t N,
+// Note: FFT-based DCT accumulates slightly more rounding error than O(N²)
+// direct method A tolerance of 5e-3 is acceptable for audio applications (< -46
+// dB error) Some input patterns (e.g., impulse at N/2, high-frequency
+// sinusoids) have higher numerical error due to reordering and accumulated
+// floating-point error
+static bool arrays_match(const float* a, const float* b, size_t N,
float tolerance = 5e-3f) {
for (size_t i = 0; i < N; i++) {
const float diff = fabsf(a[i] - b[i]);
if (diff > tolerance) {
- fprintf(stderr,
- "Mismatch at index %zu: %.6f vs %.6f (diff=%.6e)\n",
- i,
- a[i],
- b[i],
- diff);
+ fprintf(stderr, "Mismatch at index %zu: %.6f vs %.6f (diff=%.6e)\n", i,
+ a[i], b[i], diff);
return false;
}
}
@@ -85,9 +80,10 @@ static void test_dct_correctness() {
assert(arrays_match(output_ref, output_fft, N));
printf(" ✓ Impulse test passed\n");
- // Test case 2: Impulse at middle (SKIPPED - reordering method has issues with this pattern)
- // The reordering FFT method has systematic sign errors for impulses at certain positions
- // This doesn't affect typical audio signals (smooth spectra), only pathological cases
+ // Test case 2: Impulse at middle (SKIPPED - reordering method has issues with
+ // this pattern) The reordering FFT method has systematic sign errors for
+ // impulses at certain positions This doesn't affect typical audio signals
+ // (smooth spectra), only pathological cases
// TODO: Investigate and fix, or switch to a different FFT-DCT algorithm
// memset(input, 0, N * sizeof(float));
// input[N / 2] = 1.0f;
@@ -96,10 +92,12 @@ static void test_dct_correctness() {
// assert(arrays_match(output_ref, output_fft, N));
printf(" ⊘ Middle impulse test skipped (known limitation)\n");
- // Test case 3: Sinusoidal input (SKIPPED - FFT accumulates error for high-frequency components)
- // The reordering method has accumulated floating-point error that grows with frequency index
- // This doesn't affect audio synthesis quality (round-trip is what matters)
- printf(" ⊘ Sinusoidal input test skipped (accumulated floating-point error)\n");
+ // Test case 3: Sinusoidal input (SKIPPED - FFT accumulates error for
+ // high-frequency components) The reordering method has accumulated
+ // floating-point error that grows with frequency index This doesn't affect
+ // audio synthesis quality (round-trip is what matters)
+ printf(
+ " ⊘ Sinusoidal input test skipped (accumulated floating-point error)\n");
// Test case 4: Random-ish input (SKIPPED - same issue as sinusoidal)
printf(" ⊘ Complex input test skipped (accumulated floating-point error)\n");
@@ -136,8 +134,11 @@ static void test_idct_correctness() {
assert(arrays_match(output_ref, output_fft, N));
printf(" ✓ Single bin test passed\n");
- // Test case 3: Mixed frequencies (SKIPPED - accumulated error for complex spectra)
- printf(" ⊘ Mixed frequencies test skipped (accumulated floating-point error)\n");
+ // Test case 3: Mixed frequencies (SKIPPED - accumulated error for complex
+ // spectra)
+ printf(
+ " ⊘ Mixed frequencies test skipped (accumulated floating-point "
+ "error)\n");
printf("Test 2: PASSED ✓\n\n");
}
diff --git a/src/tests/test_mesh.cc b/src/tests/test_mesh.cc
index 992471a..0865f80 100644
--- a/src/tests/test_mesh.cc
+++ b/src/tests/test_mesh.cc
@@ -8,9 +8,8 @@
#include "gpu/effects/shaders.h"
#include "gpu/texture_manager.h"
#include "platform/platform.h"
-#include "util/asset_manager_utils.h"
-#include <webgpu.h>
#include "procedural/generator.h"
+#include "util/asset_manager_utils.h"
#include <algorithm>
#include <cmath>
#include <cstdio>
@@ -18,6 +17,7 @@
#include <fstream>
#include <map>
#include <vector>
+#include <webgpu.h>
// Global State
static Renderer3D g_renderer;
@@ -41,18 +41,20 @@ void on_adapter_request_ended(WGPURequestAdapterStatus status,
if (status == WGPURequestAdapterStatus_Success) {
*(WGPUAdapter*)userdata = adapter;
} else {
- fprintf(stderr, "Failed to request adapter.\n"); // Avoid WGPUStringView::s issues
+ fprintf(stderr,
+ "Failed to request adapter.\n"); // Avoid WGPUStringView::s issues
}
}
-void on_device_request_ended(WGPURequestDeviceStatus status,
- WGPUDevice device, WGPUStringView message,
- void* userdata, void* user2) {
+void on_device_request_ended(WGPURequestDeviceStatus status, WGPUDevice device,
+ WGPUStringView message, void* userdata,
+ void* user2) {
(void)user2;
if (status == WGPURequestDeviceStatus_Success) {
*(WGPUDevice*)userdata = device;
} else {
- fprintf(stderr, "Failed to request device.\n"); // Avoid WGPUStringView::s issues
+ fprintf(stderr,
+ "Failed to request device.\n"); // Avoid WGPUStringView::s issues
}
}
@@ -80,7 +82,7 @@ void init_wgpu(WGPUInstance instance, PlatformState* platform_state) {
adapter_callback_info.userdata1 = &g_adapter; // Corrected to userdata1
wgpuInstanceRequestAdapter(instance, &adapter_opts, adapter_callback_info);
-
+
// Busy-wait for adapter
while (!g_adapter) {
platform_wgpu_wait_any(instance);
@@ -92,7 +94,7 @@ void init_wgpu(WGPUInstance instance, PlatformState* platform_state) {
device_callback_info.mode = WGPUCallbackMode_WaitAnyOnly;
device_callback_info.callback = on_device_request_ended;
device_callback_info.userdata1 = &g_device; // Corrected to userdata1
-
+
wgpuAdapterRequestDevice(g_adapter, &device_desc, device_callback_info);
// Busy-wait for device
@@ -122,144 +124,196 @@ void init_wgpu(WGPUInstance instance, PlatformState* platform_state) {
struct Vec3 {
float x, y, z;
- Vec3 operator+(const Vec3& o) const { return {x + o.x, y + o.y, z + o.z}; }
- Vec3& operator+=(const Vec3& o) { x+=o.x; y+=o.y; z+=o.z; return *this; }
- Vec3 operator-(const Vec3& o) const { return {x - o.x, y - o.y, z - o.z}; }
- Vec3 operator*(float s) const { return {x * s, y * s, z * s}; }
+ Vec3 operator+(const Vec3& o) const {
+ return {x + o.x, y + o.y, z + o.z};
+ }
+ Vec3& operator+=(const Vec3& o) {
+ x += o.x;
+ y += o.y;
+ z += o.z;
+ return *this;
+ }
+ Vec3 operator-(const Vec3& o) const {
+ return {x - o.x, y - o.y, z - o.z};
+ }
+ Vec3 operator*(float s) const {
+ return {x * s, y * s, z * s};
+ }
static Vec3 cross(const Vec3& a, const Vec3& b) {
- return {a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x};
+ return {a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z,
+ a.x * b.y - a.y * b.x};
}
Vec3 normalize() const {
float len = std::sqrt(x * x + y * y + z * z);
- if (len > 1e-6f) return {x / len, y / len, z / len};
+ if (len > 1e-6f)
+ return {x / len, y / len, z / len};
return {0, 0, 0};
}
};
bool load_obj_and_create_buffers(const char* path, Object3D& out_obj) {
- std::ifstream obj_file(path);
- if (!obj_file.is_open()) {
- fprintf(stderr, "Error: Could not open mesh file: %s\n", path);
- return false;
- }
+ std::ifstream obj_file(path);
+ if (!obj_file.is_open()) {
+ fprintf(stderr, "Error: Could not open mesh file: %s\n", path);
+ return false;
+ }
- std::vector<float> v_pos, v_norm, v_uv;
- struct RawFace { int v[3], vt[3], vn[3]; };
- std::vector<RawFace> raw_faces;
- std::vector<MeshVertex> final_vertices;
- std::vector<uint32_t> final_indices;
- std::map<std::string, uint32_t> vertex_map;
+ std::vector<float> v_pos, v_norm, v_uv;
+ struct RawFace {
+ int v[3], vt[3], vn[3];
+ };
+ std::vector<RawFace> raw_faces;
+ std::vector<MeshVertex> final_vertices;
+ std::vector<uint32_t> final_indices;
+ std::map<std::string, uint32_t> vertex_map;
- std::string obj_line;
- while (std::getline(obj_file, obj_line)) {
- if (obj_line.compare(0, 2, "v ") == 0) {
- float x, y, z;
- sscanf(obj_line.c_str(), "v %f %f %f", &x, &y, &z);
- v_pos.insert(v_pos.end(), {x, y, z});
- } else if (obj_line.compare(0, 3, "vn ") == 0) {
- float x, y, z;
- sscanf(obj_line.c_str(), "vn %f %f %f", &x, &y, &z);
- v_norm.insert(v_norm.end(), {x, y, z});
- } else if (obj_line.compare(0, 3, "vt ") == 0) {
- float u, v;
- sscanf(obj_line.c_str(), "vt %f %f", &u, &v);
- v_uv.insert(v_uv.end(), {u, v});
- } else if (obj_line.compare(0, 2, "f ") == 0) {
- char s1[64], s2[64], s3[64];
- if (sscanf(obj_line.c_str(), "f %s %s %s", s1, s2, s3) == 3) {
- std::string parts[3] = {s1, s2, s3};
- RawFace face = {};
- for (int i = 0; i < 3; ++i) {
- // Handle v//vn format
- if (parts[i].find("//") != std::string::npos) {
- sscanf(parts[i].c_str(), "%d//%d", &face.v[i], &face.vn[i]);
- face.vt[i] = 0;
- } else {
- int res = sscanf(parts[i].c_str(), "%d/%d/%d", &face.v[i], &face.vt[i], &face.vn[i]);
- if (res == 2) face.vn[i] = 0;
- else if (res == 1) { face.vt[i] = 0; face.vn[i] = 0; }
- }
- }
- raw_faces.push_back(face);
+ std::string obj_line;
+ while (std::getline(obj_file, obj_line)) {
+ if (obj_line.compare(0, 2, "v ") == 0) {
+ float x, y, z;
+ sscanf(obj_line.c_str(), "v %f %f %f", &x, &y, &z);
+ v_pos.insert(v_pos.end(), {x, y, z});
+ } else if (obj_line.compare(0, 3, "vn ") == 0) {
+ float x, y, z;
+ sscanf(obj_line.c_str(), "vn %f %f %f", &x, &y, &z);
+ v_norm.insert(v_norm.end(), {x, y, z});
+ } else if (obj_line.compare(0, 3, "vt ") == 0) {
+ float u, v;
+ sscanf(obj_line.c_str(), "vt %f %f", &u, &v);
+ v_uv.insert(v_uv.end(), {u, v});
+ } else if (obj_line.compare(0, 2, "f ") == 0) {
+ char s1[64], s2[64], s3[64];
+ if (sscanf(obj_line.c_str(), "f %s %s %s", s1, s2, s3) == 3) {
+ std::string parts[3] = {s1, s2, s3};
+ RawFace face = {};
+ for (int i = 0; i < 3; ++i) {
+ // Handle v//vn format
+ if (parts[i].find("//") != std::string::npos) {
+ sscanf(parts[i].c_str(), "%d//%d", &face.v[i], &face.vn[i]);
+ face.vt[i] = 0;
+ } else {
+ int res = sscanf(parts[i].c_str(), "%d/%d/%d", &face.v[i],
+ &face.vt[i], &face.vn[i]);
+ if (res == 2)
+ face.vn[i] = 0;
+ else if (res == 1) {
+ face.vt[i] = 0;
+ face.vn[i] = 0;
}
+ }
}
+ raw_faces.push_back(face);
+ }
+ }
+ }
+
+ if (v_norm.empty() && !v_pos.empty()) {
+ std::vector<Vec3> temp_normals(v_pos.size() / 3, {0, 0, 0});
+ for (auto& face : raw_faces) {
+ int i0 = face.v[0] - 1, i1 = face.v[1] - 1, i2 = face.v[2] - 1;
+ Vec3 p0 = {v_pos[i0 * 3], v_pos[i0 * 3 + 1], v_pos[i0 * 3 + 2]};
+ Vec3 p1 = {v_pos[i1 * 3], v_pos[i1 * 3 + 1], v_pos[i1 * 3 + 2]};
+ Vec3 p2 = {v_pos[i2 * 3], v_pos[i2 * 3 + 1], v_pos[i2 * 3 + 2]};
+ Vec3 n = Vec3::cross(p1 - p0, p2 - p0).normalize();
+ temp_normals[i0] += n;
+ temp_normals[i1] += n;
+ temp_normals[i2] += n;
+ }
+ for (const auto& n : temp_normals) {
+ Vec3 norm = n.normalize();
+ v_norm.insert(v_norm.end(), {norm.x, norm.y, norm.z});
+ }
+ for (auto& face : raw_faces) {
+ face.vn[0] = face.v[0];
+ face.vn[1] = face.v[1];
+ face.vn[2] = face.v[2];
}
+ }
- if (v_norm.empty() && !v_pos.empty()) {
- std::vector<Vec3> temp_normals(v_pos.size() / 3, {0,0,0});
- for(auto& face : raw_faces) {
- int i0=face.v[0]-1, i1=face.v[1]-1, i2=face.v[2]-1;
- Vec3 p0={v_pos[i0*3],v_pos[i0*3+1],v_pos[i0*3+2]};
- Vec3 p1={v_pos[i1*3],v_pos[i1*3+1],v_pos[i1*3+2]};
- Vec3 p2={v_pos[i2*3],v_pos[i2*3+1],v_pos[i2*3+2]};
- Vec3 n = Vec3::cross(p1-p0, p2-p0).normalize();
- temp_normals[i0] += n; temp_normals[i1] += n; temp_normals[i2] += n;
+ for (const auto& face : raw_faces) {
+ for (int i = 0; i < 3; ++i) {
+ char key_buf[128];
+ snprintf(key_buf, sizeof(key_buf), "%d/%d/%d", face.v[i], face.vt[i],
+ face.vn[i]);
+ std::string key = key_buf;
+ if (vertex_map.find(key) == vertex_map.end()) {
+ vertex_map[key] = (uint32_t)final_vertices.size();
+ MeshVertex v = {};
+ if (face.v[i] > 0) {
+ v.p[0] = v_pos[(face.v[i] - 1) * 3];
+ v.p[1] = v_pos[(face.v[i] - 1) * 3 + 1];
+ v.p[2] = v_pos[(face.v[i] - 1) * 3 + 2];
}
- for(const auto& n : temp_normals) {
- Vec3 norm = n.normalize();
- v_norm.insert(v_norm.end(), {norm.x, norm.y, norm.z});
+ if (face.vn[i] > 0) {
+ v.n[0] = v_norm[(face.vn[i] - 1) * 3];
+ v.n[1] = v_norm[(face.vn[i] - 1) * 3 + 1];
+ v.n[2] = v_norm[(face.vn[i] - 1) * 3 + 2];
}
- for(auto& face : raw_faces) {
- face.vn[0]=face.v[0]; face.vn[1]=face.v[1]; face.vn[2]=face.v[2];
+ if (face.vt[i] > 0) {
+ v.u[0] = v_uv[(face.vt[i] - 1) * 2];
+ v.u[1] = v_uv[(face.vt[i] - 1) * 2 + 1];
}
+ final_vertices.push_back(v);
+ }
+ final_indices.push_back(vertex_map[key]);
}
+ }
- for (const auto& face : raw_faces) {
- for (int i=0; i<3; ++i) {
- char key_buf[128];
- snprintf(key_buf, sizeof(key_buf), "%d/%d/%d", face.v[i], face.vt[i], face.vn[i]);
- std::string key = key_buf;
- if (vertex_map.find(key) == vertex_map.end()) {
- vertex_map[key] = (uint32_t)final_vertices.size();
- MeshVertex v = {};
- if(face.v[i]>0) { v.p[0]=v_pos[(face.v[i]-1)*3]; v.p[1]=v_pos[(face.v[i]-1)*3+1]; v.p[2]=v_pos[(face.v[i]-1)*3+2]; }
- if(face.vn[i]>0) { v.n[0]=v_norm[(face.vn[i]-1)*3]; v.n[1]=v_norm[(face.vn[i]-1)*3+1]; v.n[2]=v_norm[(face.vn[i]-1)*3+2]; }
- if(face.vt[i]>0) { v.u[0]=v_uv[(face.vt[i]-1)*2]; v.u[1]=v_uv[(face.vt[i]-1)*2+1]; }
- final_vertices.push_back(v);
- }
- final_indices.push_back(vertex_map[key]);
- }
- }
+ if (final_vertices.empty())
+ return false;
- if (final_vertices.empty()) return false;
+ // Calculate AABB and center the mesh
+ float min_x = 1e10f, min_y = 1e10f, min_z = 1e10f;
+ float max_x = -1e10f, max_y = -1e10f, max_z = -1e10f;
+ for (const auto& v : final_vertices) {
+ min_x = std::min(min_x, v.p[0]);
+ min_y = std::min(min_y, v.p[1]);
+ min_z = std::min(min_z, v.p[2]);
+ max_x = std::max(max_x, v.p[0]);
+ max_y = std::max(max_y, v.p[1]);
+ max_z = std::max(max_z, v.p[2]);
+ }
+ float cx = (min_x + max_x) * 0.5f;
+ float cy = (min_y + max_y) * 0.5f;
+ float cz = (min_z + max_z) * 0.5f;
+ for (auto& v : final_vertices) {
+ v.p[0] -= cx;
+ v.p[1] -= cy;
+ v.p[2] -= cz;
+ }
+ out_obj.local_extent = vec3((max_x - min_x) * 0.5f, (max_y - min_y) * 0.5f,
+ (max_z - min_z) * 0.5f);
- // Calculate AABB and center the mesh
- float min_x = 1e10f, min_y = 1e10f, min_z = 1e10f;
- float max_x = -1e10f, max_y = -1e10f, max_z = -1e10f;
- for (const auto& v : final_vertices) {
- min_x = std::min(min_x, v.p[0]); min_y = std::min(min_y, v.p[1]); min_z = std::min(min_z, v.p[2]);
- max_x = std::max(max_x, v.p[0]); max_y = std::max(max_y, v.p[1]); max_z = std::max(max_z, v.p[2]);
- }
- float cx = (min_x + max_x) * 0.5f;
- float cy = (min_y + max_y) * 0.5f;
- float cz = (min_z + max_z) * 0.5f;
- for (auto& v : final_vertices) {
- v.p[0] -= cx; v.p[1] -= cy; v.p[2] -= cz;
- }
- out_obj.local_extent = vec3((max_x - min_x) * 0.5f, (max_y - min_y) * 0.5f, (max_z - min_z) * 0.5f);
-
- g_mesh_gpu_data.num_indices = final_indices.size();
- g_mesh_gpu_data.vertex_buffer = gpu_create_buffer(g_device, final_vertices.size() * sizeof(MeshVertex), WGPUBufferUsage_Vertex | WGPUBufferUsage_CopyDst, final_vertices.data()).buffer;
- g_mesh_gpu_data.index_buffer = gpu_create_buffer(g_device, final_indices.size() * sizeof(uint32_t), WGPUBufferUsage_Index | WGPUBufferUsage_CopyDst, final_indices.data()).buffer;
-
- struct MeshData {
- std::vector<MeshVertex> vertices;
- std::vector<uint32_t> indices;
- };
- MeshData* mesh_data = new MeshData();
- mesh_data->vertices = final_vertices;
- mesh_data->indices = final_indices;
+ g_mesh_gpu_data.num_indices = final_indices.size();
+ g_mesh_gpu_data.vertex_buffer =
+ gpu_create_buffer(g_device, final_vertices.size() * sizeof(MeshVertex),
+ WGPUBufferUsage_Vertex | WGPUBufferUsage_CopyDst,
+ final_vertices.data())
+ .buffer;
+ g_mesh_gpu_data.index_buffer =
+ gpu_create_buffer(g_device, final_indices.size() * sizeof(uint32_t),
+ WGPUBufferUsage_Index | WGPUBufferUsage_CopyDst,
+ final_indices.data())
+ .buffer;
- out_obj.type = ObjectType::MESH;
- out_obj.user_data = mesh_data;
+ struct MeshData {
+ std::vector<MeshVertex> vertices;
+ std::vector<uint32_t> indices;
+ };
+ MeshData* mesh_data = new MeshData();
+ mesh_data->vertices = final_vertices;
+ mesh_data->indices = final_indices;
- // This test doesn't use the asset system, so we override the renderer's internal cache lookup
- // by manually setting the buffers on the renderer object. This is a HACK for this specific tool.
- g_renderer.override_mesh_buffers(&g_mesh_gpu_data);
+ out_obj.type = ObjectType::MESH;
+ out_obj.user_data = mesh_data;
- return true;
-}
+ // This test doesn't use the asset system, so we override the renderer's
+ // internal cache lookup by manually setting the buffers on the renderer
+ // object. This is a HACK for this specific tool.
+ g_renderer.override_mesh_buffers(&g_mesh_gpu_data);
+ return true;
+}
int main(int argc, char** argv) {
if (argc < 2) {
@@ -270,7 +324,7 @@ int main(int argc, char** argv) {
bool debug_mode = (argc > 2 && strcmp(argv[2], "--debug") == 0);
printf("Loading mesh: %s\n", obj_path);
-
+
PlatformState platform_state = platform_init(false, 1280, 720);
WGPUInstance instance = wgpuCreateInstance(nullptr);
@@ -287,7 +341,8 @@ int main(int argc, char** argv) {
g_textures.init(g_device, g_queue);
ProceduralTextureDef noise_def;
- noise_def.width=256; noise_def.height=256;
+ noise_def.width = 256;
+ noise_def.height = 256;
noise_def.gen_func = procedural::gen_noise;
noise_def.params = {1234.0f, 16.0f};
g_textures.create_procedural_texture("noise", noise_def);
@@ -302,13 +357,13 @@ int main(int argc, char** argv) {
Object3D mesh_obj;
if (!load_obj_and_create_buffers(obj_path, mesh_obj)) {
- printf("Failed to load or process OBJ file.\n");
- return 1;
+ printf("Failed to load or process OBJ file.\n");
+ return 1;
}
mesh_obj.color = vec4(1.0f, 0.7f, 0.2f, 1.0f);
mesh_obj.position = {0, 1.5, 0}; // Elevate a bit more
g_scene.add_object(mesh_obj);
-
+
g_camera.position = vec3(0, 3, 5);
g_camera.target = vec3(0, 1.5, 0);
@@ -317,31 +372,42 @@ int main(int argc, char** argv) {
float time = (float)platform_state.time;
g_camera.aspect_ratio = platform_state.aspect_ratio;
-
+
g_scene.objects[1].rotation = quat::from_axis({0.5f, 1.0f, 0.0f}, time);
#if !defined(STRIP_ALL)
if (debug_mode) {
- struct MeshData {
- std::vector<MeshVertex> vertices;
- std::vector<uint32_t> indices;
- };
- auto* data = (MeshData*)g_scene.objects[1].user_data;
- VisualDebug& dbg = g_renderer.GetVisualDebug();
- dbg.add_mesh_normals(g_scene.objects[1].get_model_matrix(), (uint32_t)data->vertices.size(), data->vertices.data());
- dbg.add_mesh_wireframe(g_scene.objects[1].get_model_matrix(), (uint32_t)data->vertices.size(), data->vertices.data(), (uint32_t)data->indices.size(), data->indices.data(), vec3(0.0f, 1.0f, 1.0f));
+ struct MeshData {
+ std::vector<MeshVertex> vertices;
+ std::vector<uint32_t> indices;
+ };
+ auto* data = (MeshData*)g_scene.objects[1].user_data;
+ VisualDebug& dbg = g_renderer.GetVisualDebug();
+ dbg.add_mesh_normals(g_scene.objects[1].get_model_matrix(),
+ (uint32_t)data->vertices.size(),
+ data->vertices.data());
+ dbg.add_mesh_wireframe(g_scene.objects[1].get_model_matrix(),
+ (uint32_t)data->vertices.size(),
+ data->vertices.data(),
+ (uint32_t)data->indices.size(),
+ data->indices.data(), vec3(0.0f, 1.0f, 1.0f));
}
#endif /* !defined(STRIP_ALL) */
WGPUSurfaceTexture surface_tex;
wgpuSurfaceGetCurrentTexture(g_surface, &surface_tex);
- if (surface_tex.status == WGPUSurfaceGetCurrentTextureStatus_SuccessOptimal) { // WGPUSurfaceGetCurrentTextureStatus_Success is 0
- WGPUTextureView view = wgpuTextureCreateView(surface_tex.texture, nullptr);
+ if (surface_tex.status ==
+ WGPUSurfaceGetCurrentTextureStatus_SuccessOptimal) { // WGPUSurfaceGetCurrentTextureStatus_Success
+ // is 0
+ WGPUTextureView view =
+ wgpuTextureCreateView(surface_tex.texture, nullptr);
g_renderer.render(g_scene, g_camera, time, view);
wgpuTextureViewRelease(view);
wgpuSurfacePresent(g_surface);
}
- wgpuTextureRelease(surface_tex.texture); // Release here, after present, outside the if block
+ wgpuTextureRelease(
+ surface_tex
+ .texture); // Release here, after present, outside the if block
}
#if !defined(STRIP_ALL)
@@ -349,8 +415,8 @@ int main(int argc, char** argv) {
#endif
struct MeshData {
- std::vector<MeshVertex> vertices;
- std::vector<uint32_t> indices;
+ std::vector<MeshVertex> vertices;
+ std::vector<uint32_t> indices;
};
delete (MeshData*)g_scene.objects[1].user_data;
wgpuBufferRelease(g_mesh_gpu_data.vertex_buffer);
diff --git a/src/tests/test_post_process_helper.cc b/src/tests/test_post_process_helper.cc
index c1c5591..c009bc2 100644
--- a/src/tests/test_post_process_helper.cc
+++ b/src/tests/test_post_process_helper.cc
@@ -2,12 +2,12 @@
// It tests post-processing helper functions (pipeline and bind group creation).
// Validates that helpers can create valid WebGPU resources.
-#if !defined(STRIP_ALL) // Test code only - zero size impact on final binary
+#if !defined(STRIP_ALL) // Test code only - zero size impact on final binary
-#include "webgpu_test_fixture.h"
-#include "offscreen_render_target.h"
#include "gpu/demo_effects.h"
#include "gpu/gpu.h"
+#include "offscreen_render_target.h"
+#include "webgpu_test_fixture.h"
#include <cassert>
#include <cstdio>
@@ -16,16 +16,18 @@ extern WGPURenderPipeline create_post_process_pipeline(WGPUDevice device,
WGPUTextureFormat format,
const char* shader_code);
extern void pp_update_bind_group(WGPUDevice device, WGPURenderPipeline pipeline,
- WGPUBindGroup* bind_group, WGPUTextureView input_view,
+ WGPUBindGroup* bind_group,
+ WGPUTextureView input_view,
GpuBuffer uniforms);
-// Helper: Create a texture suitable for post-processing (both render target and texture binding)
-static WGPUTexture create_post_process_texture(WGPUDevice device, int width, int height,
+// Helper: Create a texture suitable for post-processing (both render target and
+// texture binding)
+static WGPUTexture create_post_process_texture(WGPUDevice device, int width,
+ int height,
WGPUTextureFormat format) {
const WGPUTextureDescriptor texture_desc = {
.usage = WGPUTextureUsage_RenderAttachment |
- WGPUTextureUsage_TextureBinding |
- WGPUTextureUsage_CopySrc,
+ WGPUTextureUsage_TextureBinding | WGPUTextureUsage_CopySrc,
.dimension = WGPUTextureDimension_2D,
.size = {static_cast<uint32_t>(width), static_cast<uint32_t>(height), 1},
.format = format,
@@ -36,7 +38,8 @@ static WGPUTexture create_post_process_texture(WGPUDevice device, int width, int
}
// Helper: Create texture view
-static WGPUTextureView create_texture_view(WGPUTexture texture, WGPUTextureFormat format) {
+static WGPUTextureView create_texture_view(WGPUTexture texture,
+ WGPUTextureFormat format) {
const WGPUTextureViewDescriptor view_desc = {
.format = format,
.dimension = WGPUTextureViewDimension_2D,
@@ -105,24 +108,26 @@ static void test_bind_group_creation() {
assert(pipeline != nullptr && "Pipeline required for bind group test");
// Create input texture with TEXTURE_BINDING usage
- WGPUTexture input_texture = create_post_process_texture(
- fixture.device(), 256, 256, fixture.format());
- WGPUTextureView input_view = create_texture_view(input_texture, fixture.format());
+ WGPUTexture input_texture =
+ create_post_process_texture(fixture.device(), 256, 256, fixture.format());
+ WGPUTextureView input_view =
+ create_texture_view(input_texture, fixture.format());
// Create uniform buffer
const WGPUBufferDescriptor uniform_desc = {
.usage = WGPUBufferUsage_Uniform | WGPUBufferUsage_CopyDst,
- .size = 16, // vec4<f32>
+ .size = 16, // vec4<f32>
};
- WGPUBuffer uniform_buffer = wgpuDeviceCreateBuffer(fixture.device(), &uniform_desc);
+ WGPUBuffer uniform_buffer =
+ wgpuDeviceCreateBuffer(fixture.device(), &uniform_desc);
assert(uniform_buffer != nullptr && "Uniform buffer should be created");
GpuBuffer uniforms = {uniform_buffer, 16};
// Test bind group creation
WGPUBindGroup bind_group = nullptr;
- pp_update_bind_group(fixture.device(), pipeline, &bind_group,
- input_view, uniforms);
+ pp_update_bind_group(fixture.device(), pipeline, &bind_group, input_view,
+ uniforms);
assert(bind_group != nullptr && "Bind group should be created successfully");
fprintf(stdout, " ✓ Bind group created successfully\n");
@@ -149,31 +154,32 @@ static void test_bind_group_update() {
WGPURenderPipeline pipeline = create_post_process_pipeline(
fixture.device(), fixture.format(), test_shader);
- WGPUTexture texture1 = create_post_process_texture(
- fixture.device(), 256, 256, fixture.format());
+ WGPUTexture texture1 =
+ create_post_process_texture(fixture.device(), 256, 256, fixture.format());
WGPUTextureView view1 = create_texture_view(texture1, fixture.format());
- WGPUTexture texture2 = create_post_process_texture(
- fixture.device(), 512, 512, fixture.format());
+ WGPUTexture texture2 =
+ create_post_process_texture(fixture.device(), 512, 512, fixture.format());
WGPUTextureView view2 = create_texture_view(texture2, fixture.format());
const WGPUBufferDescriptor uniform_desc = {
.usage = WGPUBufferUsage_Uniform | WGPUBufferUsage_CopyDst,
.size = 16,
};
- WGPUBuffer uniform_buffer = wgpuDeviceCreateBuffer(fixture.device(), &uniform_desc);
+ WGPUBuffer uniform_buffer =
+ wgpuDeviceCreateBuffer(fixture.device(), &uniform_desc);
GpuBuffer uniforms = {uniform_buffer, 16};
// Create initial bind group
WGPUBindGroup bind_group = nullptr;
- pp_update_bind_group(fixture.device(), pipeline, &bind_group,
- view1, uniforms);
+ pp_update_bind_group(fixture.device(), pipeline, &bind_group, view1,
+ uniforms);
assert(bind_group != nullptr && "Initial bind group should be created");
fprintf(stdout, " ✓ Initial bind group created\n");
// Update bind group (should release old and create new)
- pp_update_bind_group(fixture.device(), pipeline, &bind_group,
- view2, uniforms);
+ pp_update_bind_group(fixture.device(), pipeline, &bind_group, view2,
+ uniforms);
assert(bind_group != nullptr && "Updated bind group should be created");
fprintf(stdout, " ✓ Bind group updated successfully\n");
@@ -204,31 +210,35 @@ static void test_full_setup() {
assert(pipeline != nullptr && "Pipeline creation failed");
// Create input texture (with TEXTURE_BINDING usage)
- WGPUTexture input_texture = create_post_process_texture(
- fixture.device(), 256, 256, fixture.format());
- WGPUTextureView input_view = create_texture_view(input_texture, fixture.format());
+ WGPUTexture input_texture =
+ create_post_process_texture(fixture.device(), 256, 256, fixture.format());
+ WGPUTextureView input_view =
+ create_texture_view(input_texture, fixture.format());
// Create output texture (can use OffscreenRenderTarget for this)
- OffscreenRenderTarget output_target(fixture.instance(), fixture.device(), 256, 256);
+ OffscreenRenderTarget output_target(fixture.instance(), fixture.device(), 256,
+ 256);
const WGPUBufferDescriptor uniform_desc = {
.usage = WGPUBufferUsage_Uniform | WGPUBufferUsage_CopyDst,
.size = 16,
};
- WGPUBuffer uniform_buffer = wgpuDeviceCreateBuffer(fixture.device(), &uniform_desc);
+ WGPUBuffer uniform_buffer =
+ wgpuDeviceCreateBuffer(fixture.device(), &uniform_desc);
GpuBuffer uniforms = {uniform_buffer, 16};
// Create bind group
WGPUBindGroup bind_group = nullptr;
- pp_update_bind_group(fixture.device(), pipeline, &bind_group,
- input_view, uniforms);
+ pp_update_bind_group(fixture.device(), pipeline, &bind_group, input_view,
+ uniforms);
assert(bind_group != nullptr && "Bind group creation failed");
fprintf(stdout, " ✓ Pipeline and bind group ready\n");
// Test render pass setup (smoke test - just verify we can create a pass)
const WGPUCommandEncoderDescriptor enc_desc = {};
- WGPUCommandEncoder encoder = wgpuDeviceCreateCommandEncoder(fixture.device(), &enc_desc);
+ WGPUCommandEncoder encoder =
+ wgpuDeviceCreateCommandEncoder(fixture.device(), &enc_desc);
WGPURenderPassColorAttachment color_attachment = {};
gpu_init_color_attachment(color_attachment, output_target.view());
@@ -237,7 +247,8 @@ static void test_full_setup() {
pass_desc.colorAttachmentCount = 1;
pass_desc.colorAttachments = &color_attachment;
- WGPURenderPassEncoder pass = wgpuCommandEncoderBeginRenderPass(encoder, &pass_desc);
+ WGPURenderPassEncoder pass =
+ wgpuCommandEncoderBeginRenderPass(encoder, &pass_desc);
// Set pipeline and bind group
wgpuRenderPassEncoderSetPipeline(pass, pipeline);
@@ -277,4 +288,4 @@ int main() {
return 0;
}
-#endif /* !defined(STRIP_ALL) */
+#endif /* !defined(STRIP_ALL) */
diff --git a/src/tests/test_scene_loader.cc b/src/tests/test_scene_loader.cc
index e14054b..21bcbaa 100644
--- a/src/tests/test_scene_loader.cc
+++ b/src/tests/test_scene_loader.cc
@@ -1,107 +1,134 @@
#include "3d/scene_loader.h"
-#include "util/mini_math.h"
-#include "util/asset_manager.h"
#include "generated/assets.h"
+#include "util/asset_manager.h"
+#include "util/mini_math.h"
+#include <cassert>
#include <cstdio>
#include <cstring>
#include <vector>
-#include <cassert>
int main() {
- Scene scene;
- std::vector<uint8_t> buffer;
-
- // Header
- const char* magic = "SCN1";
- for(int i=0; i<4; ++i) buffer.push_back(magic[i]);
-
- uint32_t num_obj = 2; // Increased to 2
- uint32_t num_cam = 0;
- uint32_t num_light = 0;
-
- auto push_u32 = [&](uint32_t v) {
- uint8_t* p = (uint8_t*)&v;
- for(int i=0; i<4; ++i) buffer.push_back(p[i]);
- };
- auto push_f = [&](float v) {
- uint8_t* p = (uint8_t*)&v;
- for(int i=0; i<4; ++i) buffer.push_back(p[i]);
- };
-
- push_u32(num_obj);
- push_u32(num_cam);
- push_u32(num_light);
-
- // --- Object 1: Basic Cube ---
- char name1[64] = {0};
- std::strcpy(name1, "TestObject");
- for(int i=0; i<64; ++i) buffer.push_back(name1[i]);
-
- push_u32(0); // CUBE
-
- // Pos
- push_f(1.0f); push_f(2.0f); push_f(3.0f);
- // Rot (0,0,0,1)
- push_f(0.0f); push_f(0.0f); push_f(0.0f); push_f(1.0f);
- // Scale
- push_f(1.0f); push_f(1.0f); push_f(1.0f);
- // Color
- push_f(1.0f); push_f(0.0f); push_f(0.0f); push_f(1.0f);
-
- // Mesh Name length 0
- push_u32(0);
-
- // Physics
- push_f(10.0f); // mass
- push_f(0.8f); // restitution
- push_u32(1); // static
-
- // --- Object 2: Mesh with Asset Ref ---
- char name2[64] = {0};
- std::strcpy(name2, "MeshObject");
- for(int i=0; i<64; ++i) buffer.push_back(name2[i]);
-
- push_u32(6); // MESH
-
- // Pos
- push_f(0.0f); push_f(0.0f); push_f(0.0f);
- // Rot
- push_f(0.0f); push_f(0.0f); push_f(0.0f); push_f(1.0f);
- // Scale
- push_f(1.0f); push_f(1.0f); push_f(1.0f);
- // Color
- push_f(0.0f); push_f(1.0f); push_f(0.0f); push_f(1.0f);
-
- // Mesh Name "MESH_CUBE"
- const char* mesh_name = "MESH_CUBE";
- uint32_t mesh_name_len = std::strlen(mesh_name);
- push_u32(mesh_name_len);
- for(size_t i=0; i<mesh_name_len; ++i) buffer.push_back(mesh_name[i]);
-
- // Physics
- push_f(1.0f);
- push_f(0.5f);
- push_u32(0); // dynamic
-
- // --- Load ---
- if (SceneLoader::LoadScene(scene, buffer.data(), buffer.size())) {
- printf("Scene loaded successfully.\n");
- assert(scene.objects.size() == 2);
-
- // Check Obj 1
- assert(scene.objects[0].type == ObjectType::CUBE);
- assert(scene.objects[0].position.x == 1.0f);
- assert(scene.objects[0].is_static == true);
-
- // Check Obj 2
- assert(scene.objects[1].type == ObjectType::MESH);
- assert(scene.objects[1].mesh_asset_id == AssetId::ASSET_MESH_CUBE);
- printf("Mesh Asset ID resolved to: %d (Expected %d)\n", (int)scene.objects[1].mesh_asset_id, (int)AssetId::ASSET_MESH_CUBE);
-
- } else {
- printf("Scene load failed.\n");
- return 1;
- }
-
- return 0;
+ Scene scene;
+ std::vector<uint8_t> buffer;
+
+ // Header
+ const char* magic = "SCN1";
+ for (int i = 0; i < 4; ++i)
+ buffer.push_back(magic[i]);
+
+ uint32_t num_obj = 2; // Increased to 2
+ uint32_t num_cam = 0;
+ uint32_t num_light = 0;
+
+ auto push_u32 = [&](uint32_t v) {
+ uint8_t* p = (uint8_t*)&v;
+ for (int i = 0; i < 4; ++i)
+ buffer.push_back(p[i]);
+ };
+ auto push_f = [&](float v) {
+ uint8_t* p = (uint8_t*)&v;
+ for (int i = 0; i < 4; ++i)
+ buffer.push_back(p[i]);
+ };
+
+ push_u32(num_obj);
+ push_u32(num_cam);
+ push_u32(num_light);
+
+ // --- Object 1: Basic Cube ---
+ char name1[64] = {0};
+ std::strcpy(name1, "TestObject");
+ for (int i = 0; i < 64; ++i)
+ buffer.push_back(name1[i]);
+
+ push_u32(0); // CUBE
+
+ // Pos
+ push_f(1.0f);
+ push_f(2.0f);
+ push_f(3.0f);
+ // Rot (0,0,0,1)
+ push_f(0.0f);
+ push_f(0.0f);
+ push_f(0.0f);
+ push_f(1.0f);
+ // Scale
+ push_f(1.0f);
+ push_f(1.0f);
+ push_f(1.0f);
+ // Color
+ push_f(1.0f);
+ push_f(0.0f);
+ push_f(0.0f);
+ push_f(1.0f);
+
+ // Mesh Name length 0
+ push_u32(0);
+
+ // Physics
+ push_f(10.0f); // mass
+ push_f(0.8f); // restitution
+ push_u32(1); // static
+
+ // --- Object 2: Mesh with Asset Ref ---
+ char name2[64] = {0};
+ std::strcpy(name2, "MeshObject");
+ for (int i = 0; i < 64; ++i)
+ buffer.push_back(name2[i]);
+
+ push_u32(6); // MESH
+
+ // Pos
+ push_f(0.0f);
+ push_f(0.0f);
+ push_f(0.0f);
+ // Rot
+ push_f(0.0f);
+ push_f(0.0f);
+ push_f(0.0f);
+ push_f(1.0f);
+ // Scale
+ push_f(1.0f);
+ push_f(1.0f);
+ push_f(1.0f);
+ // Color
+ push_f(0.0f);
+ push_f(1.0f);
+ push_f(0.0f);
+ push_f(1.0f);
+
+ // Mesh Name "MESH_CUBE"
+ const char* mesh_name = "MESH_CUBE";
+ uint32_t mesh_name_len = std::strlen(mesh_name);
+ push_u32(mesh_name_len);
+ for (size_t i = 0; i < mesh_name_len; ++i)
+ buffer.push_back(mesh_name[i]);
+
+ // Physics
+ push_f(1.0f);
+ push_f(0.5f);
+ push_u32(0); // dynamic
+
+ // --- Load ---
+ if (SceneLoader::LoadScene(scene, buffer.data(), buffer.size())) {
+ printf("Scene loaded successfully.\n");
+ assert(scene.objects.size() == 2);
+
+ // Check Obj 1
+ assert(scene.objects[0].type == ObjectType::CUBE);
+ assert(scene.objects[0].position.x == 1.0f);
+ assert(scene.objects[0].is_static == true);
+
+ // Check Obj 2
+ assert(scene.objects[1].type == ObjectType::MESH);
+ assert(scene.objects[1].mesh_asset_id == AssetId::ASSET_MESH_CUBE);
+ printf("Mesh Asset ID resolved to: %d (Expected %d)\n",
+ (int)scene.objects[1].mesh_asset_id, (int)AssetId::ASSET_MESH_CUBE);
+
+ } else {
+ printf("Scene load failed.\n");
+ return 1;
+ }
+
+ return 0;
}
diff --git a/src/tests/test_sequence.cc b/src/tests/test_sequence.cc
index e00e606..d79ec1d 100644
--- a/src/tests/test_sequence.cc
+++ b/src/tests/test_sequence.cc
@@ -70,8 +70,7 @@ class DummyPostProcessEffect : public PostProcessEffect {
int render_calls = 0;
int update_bind_group_calls = 0;
- DummyPostProcessEffect(const GpuContext& ctx)
- : PostProcessEffect(ctx) {
+ DummyPostProcessEffect(const GpuContext& ctx) : PostProcessEffect(ctx) {
}
void init(MainSequence* demo) override {
diff --git a/src/tests/test_shader_compilation.cc b/src/tests/test_shader_compilation.cc
index fdd71b8..e2c0adc 100644
--- a/src/tests/test_shader_compilation.cc
+++ b/src/tests/test_shader_compilation.cc
@@ -107,13 +107,12 @@ static bool init_wgpu() {
}
// Test shader compilation
-static bool test_shader_compilation(const char* name,
- const char* shader_code) {
+static bool test_shader_compilation(const char* name, const char* shader_code) {
printf("Testing compilation: %s...\n", name);
if (!g_device) {
printf("SKIPPED: %s (no GPU device)\n", name);
- return true; // Not a failure, just skipped
+ return true; // Not a failure, just skipped
}
#if defined(DEMO_CROSS_COMPILE_WIN32)
@@ -145,7 +144,7 @@ static bool test_shader_compilation(const char* name,
// Test composed shader with different modes
static bool test_composed_shader(const char* base_name, AssetId asset_id,
- bool with_bvh) {
+ bool with_bvh) {
const char* mode_name = with_bvh ? "BVH" : "Linear";
char test_name[128];
snprintf(test_name, sizeof(test_name), "%s (%s mode)", base_name, mode_name);
@@ -173,8 +172,7 @@ int main() {
bool gpu_available = init_wgpu();
if (!gpu_available) {
- printf(
- "Note: GPU not available - running composition-only tests\n\n");
+ printf("Note: GPU not available - running composition-only tests\n\n");
}
// Initialize shader composer
@@ -197,13 +195,13 @@ int main() {
// Test 2: Composed shaders (both BVH and Linear modes)
printf("\n--- Test 2: Composed Shaders (BVH Mode) ---\n");
all_passed &= test_composed_shader("Renderer 3D",
- AssetId::ASSET_SHADER_RENDERER_3D, true);
+ AssetId::ASSET_SHADER_RENDERER_3D, true);
all_passed &=
test_composed_shader("Mesh Render", AssetId::ASSET_SHADER_MESH, true);
printf("\n--- Test 3: Composed Shaders (Linear Mode) ---\n");
all_passed &= test_composed_shader("Renderer 3D",
- AssetId::ASSET_SHADER_RENDERER_3D, false);
+ AssetId::ASSET_SHADER_RENDERER_3D, false);
all_passed &=
test_composed_shader("Mesh Render", AssetId::ASSET_SHADER_MESH, false);
diff --git a/src/tests/test_spectral_brush.cc b/src/tests/test_spectral_brush.cc
index 1431ba7..ae1862a 100644
--- a/src/tests/test_spectral_brush.cc
+++ b/src/tests/test_spectral_brush.cc
@@ -28,11 +28,11 @@ void test_bezier_linear_2points() {
// Midpoint: linear interpolation
const float mid = evaluate_bezier_linear(frames, values, 2, 50.0f);
- assert(float_eq(mid, 100.0f)); // (50 + 150) / 2
+ assert(float_eq(mid, 100.0f)); // (50 + 150) / 2
// Quarter point
const float quarter = evaluate_bezier_linear(frames, values, 2, 25.0f);
- assert(float_eq(quarter, 75.0f)); // 50 + (150 - 50) * 0.25
+ assert(float_eq(quarter, 75.0f)); // 50 + (150 - 50) * 0.25
printf("[PASS] test_bezier_linear_2points\n");
}
@@ -78,8 +78,10 @@ void test_bezier_edge_cases() {
// Out of range: clamp to endpoints
const float frames2[] = {10.0f, 90.0f};
const float values2[] = {100.0f, 200.0f};
- assert(float_eq(evaluate_bezier_linear(frames2, values2, 2, 0.0f), 100.0f)); // Before start
- assert(float_eq(evaluate_bezier_linear(frames2, values2, 2, 100.0f), 200.0f)); // After end
+ assert(float_eq(evaluate_bezier_linear(frames2, values2, 2, 0.0f),
+ 100.0f)); // Before start
+ assert(float_eq(evaluate_bezier_linear(frames2, values2, 2, 100.0f),
+ 200.0f)); // After end
printf("[PASS] test_bezier_edge_cases\n");
}
@@ -98,7 +100,7 @@ void test_profile_gaussian() {
// Far from center: should approach 0
const float far = evaluate_profile(PROFILE_GAUSSIAN, 100.0f, 30.0f, 0.0f);
- assert(far < 0.01f); // Very small
+ assert(far < 0.01f); // Very small
printf("[PASS] test_profile_gaussian\n");
}
@@ -110,12 +112,14 @@ void test_profile_decaying_sinusoid() {
// At center (distance = 0)
// exp(-0 * 0.15) * cos(0 * 0.8) = 1.0 * 1.0 = 1.0
- assert(float_eq(evaluate_profile(PROFILE_DECAYING_SINUSOID, 0.0f, decay, omega), 1.0f));
+ assert(float_eq(
+ evaluate_profile(PROFILE_DECAYING_SINUSOID, 0.0f, decay, omega), 1.0f));
// At distance 10
const float dist = 10.0f;
const float expected = expf(-decay * dist) * cosf(omega * dist);
- const float actual = evaluate_profile(PROFILE_DECAYING_SINUSOID, dist, decay, omega);
+ const float actual =
+ evaluate_profile(PROFILE_DECAYING_SINUSOID, dist, decay, omega);
assert(float_eq(actual, expected));
printf("[PASS] test_profile_decaying_sinusoid\n");
@@ -127,12 +131,15 @@ void test_profile_noise() {
const uint32_t seed = 42;
// Same distance + seed should produce same value
- const float val1 = evaluate_profile(PROFILE_NOISE, 10.0f, amplitude, (float)seed);
- const float val2 = evaluate_profile(PROFILE_NOISE, 10.0f, amplitude, (float)seed);
+ const float val1 =
+ evaluate_profile(PROFILE_NOISE, 10.0f, amplitude, (float)seed);
+ const float val2 =
+ evaluate_profile(PROFILE_NOISE, 10.0f, amplitude, (float)seed);
assert(float_eq(val1, val2));
// Different distance should produce different value (with high probability)
- const float val3 = evaluate_profile(PROFILE_NOISE, 20.0f, amplitude, (float)seed);
+ const float val3 =
+ evaluate_profile(PROFILE_NOISE, 20.0f, amplitude, (float)seed);
assert(!float_eq(val1, val3));
// Should be in range [0, amplitude]
@@ -150,25 +157,25 @@ void test_draw_bezier_curve() {
// Simple curve: constant frequency, linearly decaying amplitude
const float frames[] = {0.0f, 100.0f};
- const float freqs[] = {440.0f, 440.0f}; // A4 note (constant pitch)
- const float amps[] = {1.0f, 0.0f}; // Fade out
+ const float freqs[] = {440.0f, 440.0f}; // A4 note (constant pitch)
+ const float amps[] = {1.0f, 0.0f}; // Fade out
- draw_bezier_curve(spectrogram, dct_size, num_frames, frames, freqs, amps, 2, PROFILE_GAUSSIAN,
- 30.0f);
+ draw_bezier_curve(spectrogram, dct_size, num_frames, frames, freqs, amps, 2,
+ PROFILE_GAUSSIAN, 30.0f);
// Verify: At frame 0, should have peak around 440 Hz bin
// bin = (440 / 16000) * 512 ≈ 14.08
const int expected_bin = 14;
const float val_at_peak = spectrogram[0 * dct_size + expected_bin];
- assert(val_at_peak > 0.5f); // Should be near 1.0 due to Gaussian
+ assert(val_at_peak > 0.5f); // Should be near 1.0 due to Gaussian
// Verify: At frame 99 (end), amplitude should be near 0
const float val_at_end = spectrogram[99 * dct_size + expected_bin];
- assert(val_at_end < 0.1f); // Near zero
+ assert(val_at_end < 0.1f); // Near zero
// Verify: At frame 50 (midpoint), amplitude should be ~0.5
const float val_at_mid = spectrogram[50 * dct_size + expected_bin];
- assert(val_at_mid > 0.3f && val_at_mid < 0.7f); // Around 0.5
+ assert(val_at_mid > 0.3f && val_at_mid < 0.7f); // Around 0.5
printf("[PASS] test_draw_bezier_curve\n");
}
@@ -184,20 +191,20 @@ void test_draw_bezier_curve_add() {
const float frames1[] = {0.0f, 100.0f};
const float freqs1[] = {440.0f, 440.0f};
const float amps1[] = {0.5f, 0.5f};
- draw_bezier_curve(spectrogram, dct_size, num_frames, frames1, freqs1, amps1, 2, PROFILE_GAUSSIAN,
- 30.0f);
+ draw_bezier_curve(spectrogram, dct_size, num_frames, frames1, freqs1, amps1,
+ 2, PROFILE_GAUSSIAN, 30.0f);
- const int bin = 14; // ~440 Hz
+ const int bin = 14; // ~440 Hz
const float val_before_add = spectrogram[0 * dct_size + bin];
// Add second curve (same frequency, same amplitude)
- draw_bezier_curve_add(spectrogram, dct_size, num_frames, frames1, freqs1, amps1, 2,
- PROFILE_GAUSSIAN, 30.0f);
+ draw_bezier_curve_add(spectrogram, dct_size, num_frames, frames1, freqs1,
+ amps1, 2, PROFILE_GAUSSIAN, 30.0f);
const float val_after_add = spectrogram[0 * dct_size + bin];
// Should be approximately doubled
- assert(val_after_add > val_before_add * 1.8f); // Allow small error
+ assert(val_after_add > val_before_add * 1.8f); // Allow small error
printf("[PASS] test_draw_bezier_curve_add\n");
}
diff --git a/src/tests/test_texture_manager.cc b/src/tests/test_texture_manager.cc
index aa994cb..41d6919 100644
--- a/src/tests/test_texture_manager.cc
+++ b/src/tests/test_texture_manager.cc
@@ -2,7 +2,7 @@
// It tests the TextureManager for procedural texture generation and management.
// Tests all public methods with both success and failure cases.
-#if !defined(STRIP_ALL) // Test code only - zero size impact on final binary
+#if !defined(STRIP_ALL) // Test code only - zero size impact on final binary
#include "gpu/texture_manager.h"
#include "procedural/generator.h"
@@ -48,12 +48,12 @@ static void test_create_texture_from_data() {
// Create 4x4 red texture (RGBA8)
const int width = 4;
const int height = 4;
- uint8_t pixels[4 * 4 * 4]; // 4x4 RGBA
+ uint8_t pixels[4 * 4 * 4]; // 4x4 RGBA
for (int i = 0; i < width * height; ++i) {
- pixels[i * 4 + 0] = 255; // R
- pixels[i * 4 + 1] = 0; // G
- pixels[i * 4 + 2] = 0; // B
- pixels[i * 4 + 3] = 255; // A
+ pixels[i * 4 + 0] = 255; // R
+ pixels[i * 4 + 1] = 0; // G
+ pixels[i * 4 + 2] = 0; // B
+ pixels[i * 4 + 3] = 255; // A
}
tm.create_texture("red_texture", width, height, pixels);
@@ -84,7 +84,7 @@ static void test_create_procedural_texture() {
noise_def.width = 64;
noise_def.height = 64;
noise_def.gen_func = procedural::gen_noise;
- noise_def.params = {1234.0f, 1.0f}; // seed, frequency
+ noise_def.params = {1234.0f, 1.0f}; // seed, frequency
tm.create_procedural_texture("noise", noise_def);
@@ -137,18 +137,18 @@ static void test_multiple_textures() {
// Fill green texture
for (int i = 0; i < size * size; ++i) {
- green_pixels[i * 4 + 0] = 0; // R
- green_pixels[i * 4 + 1] = 255; // G
- green_pixels[i * 4 + 2] = 0; // B
- green_pixels[i * 4 + 3] = 255; // A
+ green_pixels[i * 4 + 0] = 0; // R
+ green_pixels[i * 4 + 1] = 255; // G
+ green_pixels[i * 4 + 2] = 0; // B
+ green_pixels[i * 4 + 3] = 255; // A
}
// Fill blue texture
for (int i = 0; i < size * size; ++i) {
- blue_pixels[i * 4 + 0] = 0; // R
- blue_pixels[i * 4 + 1] = 0; // G
- blue_pixels[i * 4 + 2] = 255; // B
- blue_pixels[i * 4 + 3] = 255; // A
+ blue_pixels[i * 4 + 0] = 0; // R
+ blue_pixels[i * 4 + 1] = 0; // G
+ blue_pixels[i * 4 + 2] = 255; // B
+ blue_pixels[i * 4 + 3] = 255; // A
}
tm.create_texture("green", size, size, green_pixels);
@@ -187,7 +187,7 @@ static void test_procedural_generation_failure() {
(void)h;
(void)params;
(void)num_params;
- return false; // Simulate failure
+ return false; // Simulate failure
};
ProceduralTextureDef failing_def;
@@ -258,4 +258,4 @@ int main() {
return 0;
}
-#endif /* !defined(STRIP_ALL) */
+#endif /* !defined(STRIP_ALL) */
diff --git a/src/tests/test_wav_dump.cc b/src/tests/test_wav_dump.cc
index a4afba0..880c8cd 100644
--- a/src/tests/test_wav_dump.cc
+++ b/src/tests/test_wav_dump.cc
@@ -3,8 +3,8 @@
#include "audio/audio.h"
#include "audio/audio_engine.h"
-#include "audio/ring_buffer.h"
#include "audio/backend/wav_dump_backend.h"
+#include "audio/ring_buffer.h"
#include <assert.h>
#include <stdio.h>
#include <string.h>
@@ -211,11 +211,11 @@ void test_clipping_detection() {
// Mix of normal and clipped samples
for (int i = 0; i < num_samples; ++i) {
if (i % 10 == 0) {
- test_samples[i] = 1.5f; // Clipped high
+ test_samples[i] = 1.5f; // Clipped high
} else if (i % 10 == 1) {
test_samples[i] = -1.2f; // Clipped low
} else {
- test_samples[i] = 0.5f; // Normal
+ test_samples[i] = 0.5f; // Normal
}
}
@@ -275,7 +275,8 @@ void test_invalid_file_paths() {
// Test 3: Read-only location (permissions error)
{
WavDumpBackend wav_backend;
- wav_backend.set_output_file("/test.wav"); // Root directory (no write permission)
+ wav_backend.set_output_file(
+ "/test.wav"); // Root directory (no write permission)
wav_backend.init(); // Should print error but not crash
float samples[10] = {0.5f};
diff --git a/src/tests/webgpu_test_fixture.cc b/src/tests/webgpu_test_fixture.cc
index 750dea0..980572a 100644
--- a/src/tests/webgpu_test_fixture.cc
+++ b/src/tests/webgpu_test_fixture.cc
@@ -2,7 +2,7 @@
// It implements shared WebGPU initialization for GPU tests.
// Provides graceful fallback if GPU unavailable.
-#if !defined(STRIP_ALL) // Test code only - zero size impact on final binary
+#if !defined(STRIP_ALL) // Test code only - zero size impact on final binary
#include "webgpu_test_fixture.h"
#include <cstdio>
@@ -142,4 +142,4 @@ void WebGPUTestFixture::shutdown() {
}
}
-#endif /* !defined(STRIP_ALL) */
+#endif /* !defined(STRIP_ALL) */
diff --git a/src/tests/webgpu_test_fixture.h b/src/tests/webgpu_test_fixture.h
index fd08276..e10a2ed 100644
--- a/src/tests/webgpu_test_fixture.h
+++ b/src/tests/webgpu_test_fixture.h
@@ -22,14 +22,26 @@ class WebGPUTestFixture {
void shutdown();
// Accessors
- WGPUInstance instance() const { return instance_; }
- WGPUDevice device() const { return device_; }
- WGPUQueue queue() const { return queue_; }
- WGPUTextureFormat format() const { return WGPUTextureFormat_BGRA8Unorm; }
- GpuContext ctx() const { return {device_, queue_, format()}; }
+ WGPUInstance instance() const {
+ return instance_;
+ }
+ WGPUDevice device() const {
+ return device_;
+ }
+ WGPUQueue queue() const {
+ return queue_;
+ }
+ WGPUTextureFormat format() const {
+ return WGPUTextureFormat_BGRA8Unorm;
+ }
+ GpuContext ctx() const {
+ return {device_, queue_, format()};
+ }
// Check if fixture is ready
- bool is_initialized() const { return device_ != nullptr; }
+ bool is_initialized() const {
+ return device_ != nullptr;
+ }
private:
WGPUInstance instance_ = nullptr;
@@ -45,12 +57,9 @@ class WebGPUTestFixture {
};
static void adapter_callback(WGPURequestAdapterStatus status,
- WGPUAdapter adapter,
- const char* message,
- void* userdata);
+ WGPUAdapter adapter, const char* message,
+ void* userdata);
- static void device_callback(WGPURequestDeviceStatus status,
- WGPUDevice device,
- const char* message,
- void* userdata);
+ static void device_callback(WGPURequestDeviceStatus status, WGPUDevice device,
+ const char* message, void* userdata);
};