Joël van der Werf
All posts

56 issues: what a full engine review found

Before adding features, I reviewed all 6,000 lines of the engine and editor. Six critical bugs, a swapchain split, and RAII for every Vulkan resource.

When I picked Hydro up again in October 2026, I wanted to add a lot quickly: physics, particles, a 3D renderer. Building that on a foundation I hadn't looked at in years felt risky. So before any new features, I reviewed the whole engine and editor: about 6,000 lines. The review found 56 issues.

The six critical ones

  1. Resizing leaked half the renderer. Swapchain recreation rebuilt the render pass, command pool, command buffers, semaphores, fences and sampler without destroying the old ones, then made image views and framebuffers twice. Now only size-dependent objects are rebuilt.
  2. Validation was silently off. GLFW's extension list overwrote the debug-utils extension, so the debug messenger was never created. The layer was also on in Release. Years of "no validation errors" meant nothing.
  3. Images used the wrong flags. A layout constant was passed as usage and aspect flags, and loading an image from a file never actually copied its pixels.
  4. Frames in flight shared data. The 2D renderer used one vertex buffer and one offscreen image across frames in flight with no synchronisation, and uploaded the index buffer at half size.
  5. Scripts kept dangling pointers. Native scripts stored this inside an EnTT pool, which moves its storage, and the address of a stack variable.
  6. A copy-paste bug. PushOverlay called PopOverlay.

Number two is the one I think about most: the tool meant to catch the others was itself broken, and everything looked fine.

Structural fixes

  • The swapchain only presents. Per-frame objects moved to a frame context, the surface to the renderer context, and the frame loop to the renderer.
  • RAII everywhere. Every Vulkan wrapper frees itself in its destructor. Owners hold a Scope (unique ownership), users get references, and no owned GPU object sits behind a shared pointer any more.
  • A deletion queue. Destructors don't free GPU memory immediately: they submit it to a queue that frees it once the frames in flight are done with it. That removed every WaitIdle from hot reload and resizing, so the editor no longer stalls.

Rules that came out of it

The review also produced the house style: everything in namespace Hydro, == false instead of !, braces on every body, resources created from specification structs. They were written into the docs and an architecture skill for AI agents, and later into a linter, so the same bugs can't quietly come back.

The lesson: review before you scale. Every feature built in the weeks after this sits on fixes from this review.

Older: Four years of Hydro: from a Vulkan triangle to an editorNewer: Where runtime state lives: four rules for components in an ECS

Building a game, an engine, or the tools around them?

I'm based in Tokyo and open to conversations about Unity, C++ and engine roles, C# and .NET software roles, and teams that want to put AI agents to work on real codebases.