Bump to 0.8.0, close Target 12, and record what is still missing
Collision changed the collide slot's signature and grew four public structs, so this is an ABI break and the soname moves to libakgl.so.0.8. The manual's counts move with it: 195 functions across 23 headers, 183 of which return an error context. Target 12 -- "collision for 256 actors under 2 ms without the caller writing a broad phase" -- is met. A new benchmark times the whole step with a world attached, which is the number the target is actually about rather than a narrowphase call in isolation: 15.4 us at 64 actors, and 54.1 us at 256 in a purpose-built -DAKGL_MAX_HEAP_ACTOR=256 configuration. Over that 4x range the step grew 3.5x while the all-pairs control grew 15.6x, which is the n-squared the index exists to avoid. Plan item 7 is rewritten to record what shipped and why both partitioners exist; the Construct and Phaser citations stay. Three new TODO entries. Actor rotation, scoped to the five places it touches and the one place it does not -- collision_support is written so rotating `dir` in and the answer back is the whole narrowphase change, and rotational *response* is explicitly a different piece of work. The swept narrowphase FLAG_BULLET reserves, with the tunnelling arithmetic written out so a game can check its own numbers against 1280 px/s. And the ccd arena being single-threaded and sized by measurement at 7,264 bytes per GJK/EPA box pair. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KzBDV2fqgnUAcqCKqKvc71
This commit is contained in:
61
tests/perf.c
61
tests/perf.c
@@ -643,6 +643,66 @@ static akerr_ErrorContext *bench_physics_simulate(void)
|
||||
SUCCEED_RETURN(errctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Time a whole physics step with collision attached, over a full pool.
|
||||
*
|
||||
* **This is the number Target 12 is about**: collision for a full actor pool
|
||||
* without the caller writing a broad phase. It is the whole step -- the proxy
|
||||
* sync pass, the movement logic, gravity, drag, the sub-stepped move, and
|
||||
* akgl_collision_resolve per actor per sub-step -- against the same pool the
|
||||
* row above measures without a world, so the two subtract.
|
||||
*
|
||||
* The actors are spread on a 24-pixel lattice with 16-pixel boxes, so neighbours
|
||||
* are close enough to share grid cells and be tested against each other and far
|
||||
* enough apart that most of those tests answer "no". A population that all
|
||||
* overlaps measures the resolver; this measures a frame.
|
||||
*/
|
||||
static akerr_ErrorContext *bench_physics_collision(void)
|
||||
{
|
||||
PREPARE_ERROR(errctx);
|
||||
akerr_ErrorContext *inner = NULL;
|
||||
akgl_Character *basechar = NULL;
|
||||
akgl_CollisionWorld world;
|
||||
akgl_PhysicsBackend backend;
|
||||
SDL_FRect body = { .x = -8.0, .y = -8.0, .w = 16.0, .h = 16.0 };
|
||||
char label[64];
|
||||
int count = bench_iterations(2000);
|
||||
int i = 0;
|
||||
int rep = 0;
|
||||
|
||||
PASS(errctx, akgl_heap_init());
|
||||
PASS(errctx, akgl_registry_init());
|
||||
PASS(errctx, akgl_registry_init_properties());
|
||||
PASS(errctx, bench_make_character(&basechar, "benchcollisionchar", 0));
|
||||
|
||||
memset(&backend, 0x00, sizeof(akgl_PhysicsBackend));
|
||||
PASS(errctx, akgl_physics_init_arcade(&backend));
|
||||
backend.gravity_y = 9.8;
|
||||
backend.drag_x = 0.1;
|
||||
backend.drag_y = 0.1;
|
||||
|
||||
PASS(errctx, bench_fill_actor_pool(basechar, BENCH_ACTOR_COUNT));
|
||||
for ( i = 0; i < BENCH_ACTOR_COUNT; i++ ) {
|
||||
PASS(errctx, akgl_collision_shape_box(&akgl_heap_actors[i].shape, &body, 0.0));
|
||||
akgl_heap_actors[i].shape_override = true;
|
||||
akgl_heap_actors[i].shape.collidemask |= AKGL_COLLISION_LAYER_ACTOR;
|
||||
akgl_heap_actors[i].x = (float32_t)((i % 20) * 24);
|
||||
akgl_heap_actors[i].y = (float32_t)((i / 20) * 24);
|
||||
}
|
||||
PASS(errctx, akgl_collision_world_init(&world, "grid", 16.0, 16.0));
|
||||
backend.collision = &world;
|
||||
|
||||
snprintf((char *)&label, sizeof(label),
|
||||
"physics_simulate + collision, %d live actors", BENCH_ACTOR_COUNT);
|
||||
for ( rep = 0; rep < AKGL_BENCH_REPETITIONS; rep++ ) {
|
||||
bench_start((char *)&label, "frame", 2000000.0);
|
||||
BENCH_LOOP(inner, i, count, backend.simulate(&backend, NULL));
|
||||
bench_stop(count);
|
||||
PASS(errctx, inner);
|
||||
}
|
||||
SUCCEED_RETURN(errctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Time the logic half of a frame: update every actor, then simulate.
|
||||
*
|
||||
@@ -1044,6 +1104,7 @@ int main(void)
|
||||
CATCH(errctx, bench_character_sprite_get());
|
||||
CATCH(errctx, bench_actor_update());
|
||||
CATCH(errctx, bench_physics_simulate());
|
||||
CATCH(errctx, bench_physics_collision());
|
||||
CATCH(errctx, bench_logic_frame());
|
||||
CATCH(errctx, bench_geometry());
|
||||
CATCH(errctx, bench_collision());
|
||||
|
||||
Reference in New Issue
Block a user