Adventures in Building a VR Engine - Introduction

February 16, 2019 - 5 minute read -
vr eden engine simulation

After studying, building and playing with a quite a few virtual reality projects and wading through the internals of both the Unity and Unreal engines I have noticed some things about the way we build immersive content that are rather obtuse. The processes, tooling, and even some of the design aspects currently used to build immersive simulations lack support for the challenges encountered developing such a high detail simulated world.

Tools

Building immersive virtual worlds presents some unique technical challenges:

  • Objects must have even the smallest details crafted.
  • Details like accurate collision geometry, mass, and accurate audio response matter.
  • The worlds are much more dynamic requiring extra care in crafting the environment.
  • The size of the worlds needs to be much larger than traditional levels in order to maintain a high level of immersion. Artificial invisible walls are not a good solution.
  • Immersive simulations are by nature highly performance sensitive even in the simplest case.

All this adds up to immersive content production being expensive, labor intensive, and error prone.

A heavier reliance on composable procedural systems is likely the solution to easing development for these types of applications. Edit time procedural systems can automate the common processes of object creation, ease the building of large environments, and potentially reduce the number of assets that need to be manually produced. Runtime generation may play a part later, however real-time generation of content that is both interesting and bug free is a much harder problem.

Computation power is another issue that needs to be solved since an immersive simulation has to simulate far more objects and phenomena to create a convincing facsimile of reality. Current hardware is highly parallel yet few existing public engines take advantage of that parallelism, most only fully utilizing a few of the available cores on a modern CPU leaving much of the resources available unused. The other issue is the tools used in those engines make writing parallel code difficult for those without an intimate knowledge of multithreaded programming.

Designing a new engine architecture that allows for close to linear scalability with available compute power would do much to eliminate the burden of simulating these worlds.

A New Engine

Given the above ideas it’s my opinion that a new type of engine built from the ground up for VR which takes full advantage of modern hardware is the solution. To that end I have embarked on a research project to see how these ideas pan out and just what’s possible if you throw out the old assumptions. That project is named Eden.

Eden’s Core Design Guidelines:

  • Near linear scaling with available processing power.
  • Composable architecture to allow easy modification and experimentation.
  • Maximum automation. If something can be automated, it should be.
  • Massively parallel by design
  • Expressive and concise APIs that enable the developer focus on the problem at hand, not the minutiae of the surrounding environment.

Traditionally a project of this magnitude would imply using C/C++ to build it. However, with how old and error prone those languages are it makes sense to look around and see if there’s any new approaches to the age-old problem. Ideally the language used should take care of the minutia while still allowing low level control where necessary.

Although relatively new and somewhat immature, Rust was chosen as the language for this project. Rust provides quite a few valuable tools for avoiding common issues in a project of this size making it a logical choice.

  • Compile time verified memory safety. Eliminates most memory errors from being a concern (most of the time)
  • A statically verified multithreading model provided by a combination of the borrow rules and the type system.
  • An expressive type system that allows the developer to encode their intent in a compile time verifiable way.
  • A built in and easy to use build system
  • The ability to interoperate with other languages via a C interface

Architecture

Eden’s architecture needs to support a high degree of parallelism without increasing developer overhead. The current plan for achieving this goal is to build the engine and all its systems on something resembling the union of a job system and entity component system. The main concepts of this structure are the entity, storage, and system.

Entities in the framework are merely ids. Logically they are the amalgamation of their components however they are never explicitly stored together. This allows the engine to organize the data in a layout optimal for the hardware.

Storages are simply buffers that hold all the components of a single type in the simulation. Internal sorting and other details are handled by their respective implementations. Depending on the type these storages can be queried and manipulated at runtime by systems.

Systems are singular jobs executed in parallel and have the ability to, at the developer’s discretion, split themselves into more sub jobs that can be distributed further across the hardware. Each system must define its predecessor systems and the storages it reads and writes. On startup up the framework goes through all the registered systems and sets up a series of execution waves that satisfy several constraints:

  • Multiple systems may read from a storage
  • Only one system may write to a storage
  • A wave may not have any data or order dependencies within it
  • Each wave must be executed sequentially and complete before the next wave can be dispatched

Assuming all the above constraints are upheld the entire set of logic can be executed with a high degree of parallelism and no contention or data corruption. Of course, this new architecture means that Eden cannot leverage existing sub engines for audio, physics, and the likes; and thus, requires building variants of those that take advantage of this architecture.

There are quite a few unanswered questions about this type of architecture:

  • Can the sub engines support this type of parallel execution and have performance on par or better than the existing implementations?
  • Does this type of architecture have any serious limitations onthe type of content and logic that it can support?
  • How will this perform with a low number of entities?
  • Which is faster? A strictly linear, or fingerprint-based data layout (more details below)

Note on Fingerprints

An alternative structure for data storage that I have been considering is fingerprints. The idea is similar to the archetypes in unity’s ECS implementation where a fingerprint is a specific subset of components that belong to an entity. Components are then stored in linear buffers adjacent to each other as defined by the fingerprint they belong to. The only disadvantage to this approach is management overhead and it may break down when processing large numbers of entities. This approach needs more testing before committing to it.

There is also a notable lack of public information on the performance characteristics between different methods of organizing an ECS that go beyond trivial toy implementations. I suspect that linear buffers may perform better in the worst case, systems operating on a few types with millions of entries, since they would allow for streaming the data into the caches but this requires real world testing and benchmarks to determine if that hypothesis is correct.

That covers the high-level overview of this research project. In later articles I’ll go into details on the implementation, any benchmarks, and other information gained during the course of this project.