World streaming
I built and maintained a custom streaming solution for static world geometry, there were many iterations of this system, after the introduction of the world partition cell transformer stack this system morphed into a heavily modified version of FastGeo. A cook time tool gathers geometry into cell data. At runtime, the streaming system uses that data to create the corresponding render and physics state in batches. It avoids representing streamed static content as individual Actors, Components or UObjects, reducing object and garbage collection overhead as large numbers of entities move in and out of the world.
Render and physics state creation can run across worker threads, while work per frame is paced according to current streaming conditions. Creation and removal have separate budgets because their costs differ, and those budgets can be adjusted for the target platform. This spreads expensive work across frames, limits hitches, and lets the system respond to differences between hardware and frame rate modes.
As part of the cell streaming transformation pipeline, I also worked on grouping primitives for ray tracing. The transformer batches them for performance, using material frequency to limit the number of unique materials in each group. This helps reduce Lumen scene update cost while keeping capture hitches and peak frame work under control.
I also worked on the surrounding streaming pipeline: cell transformation and cooking, asset and collision behavior, and fixes for issues that appeared only in cooked builds or under particular timing conditions. This required keeping editor data, cooked content, runtime streaming, rendering, physics, and object lifetimes consistent.
Memory optimization
I worked on memory use in both engine and game code, including render resource pools, streaming budgets, object layouts, and platform specific settings. For Xbox Series S, the tighter memory budget required some targeted trade offs across systems such as ray tracing, Lumen, virtual shadow maps, and texture streaming.
While there was indeed some targeted memory savings specifically for these platforms a lot of work resulted in savings across all platforms. Some examples are reducing the size of some heavily instanced objects e.g. ~100MiB was saved by changing an inline allocated TArray in the nanite scene proxy to be dynamic, paying the cost later, this was not a problem for us since the allocation went unused in more than 95% of all such proxies in our case since it was only used under certain conditions. A similar story for the entity representation in our Cell Streaming system which was packed as tightly as possible with the help of memory and packing visualizers.
I changed Nanite and VSM upload buffer sizing strategy so later frames could reuse buffers more effectively. This lowered peak memory use by avoiding repeated allocations of additional buffers that remained alive for several frames, with this peak VRAM usage was reduced by 400MiB during heavy movement.
Other engine side allocation changes avoided repeated GPU Scene buffer reallocations. On the game side, I made smaller per object savings where they applied at scale.
Engine, rendering, and stability
I worked across Unreal Engine and game code to investigate rendering and stability problems, including GPU crashes, validation errors, shader and material issues, memory stomps, races, and other threading hazards. Some fixes involved project configuration. Others required tracing behavior into engine code or adapting an upstream fix to the project fork.
Examples include fixing a GPU crash caused by shader buffer alignment, resolving a data race between asynchronous loading and game thread work, and investigating Nanite GPU crashes associated with corrupted or prematurely freed data. I also worked on rendering issues involving GPU Scene, ray tracing data, hair, water, and console shader compilation.
I did some work on strand based hair rendering across engine and game code. Hair composition needed to coordinate with other rendering passes better, such as SingleLayerWater, I added different composition methods for strand hair that composited better with e.g. SingleLayerWater and reduced issues with translucency and solved some issues with hair and velocity during game pause and slow motion.
I also implemented an interactive ripple system for the ocean surface. It collects dynamic forces from registered skeletal meshes and custom providers, such as vehicles, along with direct impacts, then accumulates them into a force texture built around the view. A cheap simulation then runs at a fixed rate, with substeps if needed. It produces surface displacement and reconstructed normals that are written out for the ocean material to sample.
When an engine fix was applicable beyond the project, it was sent to Epic. Some of these fixes have since been included in later Unreal Engine versions.