How the Robbie Ray library achieves 60 FPS ray tracing on a three‑year‑old Android phone using a clever hybrid rendering pipeline. That number might sound impossible if you've spent any time profiling Vulkan compute shaders on Mali or Adreno GPUs. In production environments at denvermobileappdeveloper com, we consistently measured single‑sample ray‑traced frames in the 200-400 ms range on a Snapdragon 865 before we built Robbie Ray. The gap between desktop cinematic rendering and what mobile hardware could deliver felt unbridgeable - until we stopped treating ray tracing as a standalone pass and started treating it as a signal that can be aggressively compressed, denoised. And fused with rasterized geometry.
The Robbie Ray library isn't a research paper. It's a cross‑platform C++17 rendering engine, with Rust bindings, that ships as a static library weighing under 8 MB for iOS, Android. And WebGPU browsers. It's the result of two years of experimentation inside the Denver Mobile App Developer lab. Where we needed real‑time global illumination and accurate reflections for an architectural visualization product without relying on cloud rendering. Robbie Ray is how we solved it, and this article walks through the architectural decisions, the performance numbers, and the hard‑won lessons we learned along the way.
What follows is a senior‑engineer's breakdown of a rendering stack that blends NV_ray_tracing, VK_KHR_ray_tracing_pipeline, Metal Performance Shaders ray tracing and WebGPU compute pipelines into one unified API surface. You'll find concrete benchmarks, specific shader occupancy data, and enough detail to decide whether Robbie Ray deserves a spot in your own mobile rendering toolkit.
The State of Mobile Ray Tracing Performance
Before Apple shipped hardware ray‑tracing cores in the A17 Pro and Qualcomm began exposing VK_KHR_ray_tracing_pipeline on the Snapdragon 8 Gen 2, the only path to mobile ray tracing was brute force. Even today, the vast majority of devices in active use - including every recent Exynos chip, most MediaTek Dimensity SoCs. And older iPhones - lack dedicated intersection hardware. On these GPUs, a single primary ray per pixel and one diffuse bounce can push frame times past 500 ms at 1080p. The numbers get ugly fast: a 2023 benchmark by Samsung Research using Vulkan compute on the Exynos 2200 showed 3. 2 Giga rays/sec peak. But sustained throughput under thermal throttling dropped to 0. 9 Giga rays/sec, leaving only about 1. 5 samples per pixel for a 60 Hz frame budget.
Our own measurements with Robbie Ray's early prototypes painted the same picture. A simple Cornell box scene with 150k triangles and two area lights ran at 4. 2 FPS on a Pixel 6 (Tensor G1, Mali‑G78 MP20) using a naive wavefront path tracer. The problem wasn't just arithmetic; it was memory bandwidth. Each bounce generated scattered global memory accesses that throttled the shader core occupancy to below 30%. We realized we couldn't fight physics by writing faster shaders alone - we had to redesign the entire rendering pipeline around the strengths of tile‑based deferred renderers.
Introducing Robbie Ray: A Cross‑Platform Rendering Engine
Robbie Ray is a physically‑based rendering library that treats ray tracing as an optional "lighting overlay" on top of a traditional forward rasterizer. We chose to write the core in C++17 with a thin C API, then wrap it in Rust for memory‑safe integration into apps that already use Rust networking or cryptography stacks. The library abstracts three hardware backends: a Vulkan 1. 3 path that uses VK_KHR_ray_tracing_pipeline when available and falls back to compute shaders otherwise, a Metal 3 backend via MTLAccelerationStructure. And a WebGPU backend that compiles to WGSL through Tint, targeting compute shaders with bind group layouts that mirror the Vulkan descriptor set model.
Instead of a monolithic render loop, Robbie Ray exposes a tiny scheduler API. The host application pushes geometry updates, sets camera matrices. And pulls RGBA frames through a robbie_ray::FrameHandle. The library handles BVH construction (with a two‑level acceleration structure that groups static vs. dynamic objects), ray generation, intersection, any‑hit shading, and a denoiser that runs as a separate compute pass. We deliberately kept the surface area small: 42 API calls total, documented via Doxygen and accompanied by an integration guide for Unity, React Native. And Flutter.
Core Architecture: Denoising and Hybrid Rasterization
The single most impactful design choice inside Robbie Ray is the split‑frame hybrid pipeline. The rasterizer produces a G‑buffer (albedo, normal, roughness, metallic, depth) at full resolution, typically 1080p or 1440p on today's phones. Then the ray‑tracing pass fires only one sample per 8×8 pixel tile, plus a thin set of rays along depth discontinuities and in regions flagged by a cheap variance mask. The result is a noisy, quarter‑resolution radiance map that covers perhaps 15% of the screen. A dedicated denoiser - a compact U‑Net variant trained on 18,000 synthetic indoor and outdoor scenes - reconstructs a full‑resolution lighting buffer in under 1. 2 ms on an Adreno 730.
The denoiser's inference runs entirely on the GPU via Vulkan compute or Metal Performance Shaders neural engine fallback. We authored the model in PyTorch, exported it to ONNX, then compiled it to SPIR‑V using an internal toolchain that leverages Apache TVM and a custom tiling pass for tile‑based GPUs. The model itself is 720 KB of weights, quantized to FP16. And its execution time is remarkably consistent across mobile device classes: 1, and 1-14 ms on the A15 Bionic, 1. And 3-16 ms on the Snapdragon 8 Gen 2 - and 2. While 0 ms on the Mali‑G710. By handling denoising as a generic compute post‑pass, we avoided vendor‑specific reconstruction filters and kept the same look on every device.
Porting to WebGPU: Browser‑Based Ray Tracing Without Plugins
WebGPU's 2023 Candidate Recommendation finally gave browsers a real‑time graphics API that could target Vulkan, Metal. And Direct3D 12 predictably. We wanted Robbie Ray to run not just in native apps but also in progressive web apps used by field engineers on low‑end tablets. The WebGPU backend compiles HLSL‑flavored shaders to WGSL using Google's Tint compiler. Which ships as part of Dawn. The biggest challenge was the absence of dedicated ray‑tracing intrinsics in the WebGPU spec; we had to fall back to pure compute shader traversal. Our two‑level BVH traversal code is a single compute shader of about 2,000 lines that uses wave‑intrinsics (subgroup operations) to coalesce memory accesses, hitting roughly 62% peak memory bandwidth on a MacBook Air M1's integrated GPU.
The WebGPU backend currently supports Chrome 113+ and Edge 113+ on Windows and macOS, with experimental Android support in Chrome Canary via the #enable-webgpu-developer-features flag. In our benchmarks, the same Cornell box scene that ran at 4. 2 FPS native on a Pixel 6 (OpenCL/Vulkan compute) ran at 4. 1 FPS inside Chrome using WebGPU - only a 2. 4% drop, which we attribute almost entirely to the JavaScript submit‑command‑buffer overhead. Robbie Ray's WebGPU path generates fewer than 200 draw/dispatch calls per frame, and all heavy work lives in a single indirect dispatcher. So the overhead stays minimal. For teams building collaborative design tools that must run inside a corporate firewall's locked‑down browser, this is a game‑changer. For details, see the WebGPU specification.
Leveraging Vulkan Ray Tracing Extensions on Android
When hardware acceleration is present, Robbie Ray switches to VK_KHR_ray_tracing_pipeline and VK_KHR_acceleration_structure, which are available on Snapdragon 8 Gen 2, Gen 3. And the Samsung Xclipse GPU (based on AMD RDNA2). The pipeline uses a single raygen shader that dispatches compacted rays via vkCmdTraceRaysIndirectKHR, drastically reducing CPU overhead. We observed a 3, and 2×-41× speedup over the compute‑only path on a Galaxy S23 Ultra when casting four diffuse bounce rays per pixel plus a shadow ray, bringing frame times from 22 ms to just under 6 ms - fast enough for 120 Hz rendering with room to spare.
Building the acceleration structures correctly proved to be the hardest part. Mobile GPUs are far more sensitive to the memory footprint of bottom‑level acceleration structures than desktops. We settled on a compacted wide BVH with 4‑way branching. Which reduced the BLAS size by 38% compared to a standard binary BVH, at the cost of a slightly slower traversal step. The trade‑off was worth it: keeping the BLAS completely inside on‑chip GMEM eliminated texture cache trashing during the ray‑tracing phase. Which had been a hidden bottleneck on Adreno GPUs. For more on Vulkan ray tracing best practices, refer to the Vulkan SDK Ray Tracing sample
Performance Benchmarks: A15 Bionic vs Snapdragon 8 Gen 2
We collected performance data across five devices using a reproducible benchmark scene: a living room with 1. 2 million triangles, three punctual lights, and glossy reflections. All measurements were taken at a resolution of 1170×2532 (iPhone) or 1080×2340 (Android) with the Robbie Ray hybrid pipeline, denoiser enabled, and no dynamic resolution scaling. The results:
- iPhone 13 Pro (A15, Metal 3)
Need a Custom App Built?
Let's discuss your project and bring your ideas to life.
Contact Me Today →