Vulkan Fragment Renderer
Real-time GLSL shader viewer with hot reload, stereo XR rendering, and depth-buffer compositing.
Implementation AI-generated. I designed the architecture, chose the approach, and directed the engineering decisions; the code itself was generated rather than hand-written. Noted here so the nature of the work is clear up front.

- Shader reload
- Runtime, no restart
- XR
- Per-eye frustums
A Vulkan port of shader-viewer-4, replacing OpenGL and adding HMD support and a descriptor set architecture built for extension.
The original is the useful comparison: I wrote that one myself, in OpenGL, by hand. This port covers the same ground in Vulkan with the implementation AI-generated, which means the decisions below — the descriptor set split, submitting depth to the XR runtime, the two-phase initialization — are the part that carried over.
Rendering
VMA handles memory, the swapchain is sRGB, and synchronization uses per-swapchain-image semaphores with deferred destruction of GPU resources still in flight.
Fragment shaders write gl_FragDepth through the projection matrix, which means
shader output composites correctly against rasterized geometry. In XR mode that depth
is submitted to the runtime so reprojection — ASW/SpaceWarp — has something to work
with, rather than warping a flat image.
XR
Stereo rendering with per-eye asymmetric frustums and 6DoF head tracking, plus a desktop mirror. Initialization runs in two phases so that Vulkan can satisfy the instance and device extensions OpenXR requires, and the whole path falls back cleanly to desktop-only when no headset is present.
Interaction
Runtime GLSL compilation through shaderc with hot reload — edit a shader, press R,
see it. The camera is quaternion-based to avoid gimbal lock, with velocity physics,
friction, and movement scaled by pivot distance so navigation stays usable at every
zoom level.
Descriptor set 0 carries view, projection, resolution, and time for every shader; set 1 carries precomputed inverse matrices for ray marching. Push constants are reserved for per-object model matrices.