A custom rendering engine built in C++ using Vulkan as Graphics API, designed and focused on modern GPU-driven rendering techniques.
Architecture
- MgxEngine
- Creates GLFW window
- Updates input
- Invokes Tick callback
- Calls render
- MgxRenderer
- Creates Vulkan instance
- Creates swapchain
- Creates and submits command buffers
- Declare render passes
- Presents to swapchain
- MgxRenderGraph
- Manages passes
- Manages resource transitions
- Records command buffer
- Draw
- Dispatch
- Copy/Fill
- Bind
- PushConstants
- MgxDescriptorManager
- Creates descriptor pools
- Creates descriptor layouts
- Allocates descriptor sets
- Writes descriptor sets
- Binds descriptor sets
- MgxScene
- Manages entities
- Manages systems (particles, boids)
- Uploads changed data to staging buffers
- Sort batches for optimized drawing
- MgxInput
- Key values
- Axis values
- Bind actions
- MgxMath
- Unity-like design (Vector4, Quaternion, Matrix4x4, etc)
- Matrix multiplications optimized with SSE
- SimplexNoise
Frame Lifecycle
- Poll windows events
- Process GLFW window events.
- MgxInput => Record pressed keys and mouse scroll value.
- Update input
- MgxInput => Update axis values and call input events.
- Tick
- Invoke Tick callback.
- The app updates the scene (spawn entities, update camera, etc).
- Acquire swapchain image
- Acquire next swapchain image to draw on it (currently using double buffering with Mailbox/FIFO present modes).
- Compile RenderGraph
- Check resource usage on each pass and subpasses.
- Create image and buffer memory barriers to sync read/write accesses to these resources.
- Determines when color and depth attachments need to be cleared.
- Execute RenderGraph
- Records CommandBuffer.
- Insert memory barriers generated by compilation.
- Executes each pass (check Pipeline section).
- Submit CommandBuffer
- Submit recorded command buffer to queue.
- Present
- Present to current swapchain image.
Pipeline
- Initialize Buffers => Initialize buffers to zero.
- Bake Skybox => Sample HDR skybox texture and creates skybox cubemap.
- Bake Irradiance => Samples skybox cubemap and generates irradiance cubemap.
- Bake Prefiltered => Samples skybox cubemap and generates prefiltered cubemap (one mip per roughness level).
- Bake BRDF LUT => Compute BRDF LUT texture to be used in PBR shader.
- Copy Buffers => Copy data changes from staging buffers to GPU local buffers.
- Reset Counters => Reset instance count on each draw command in DrawCommandBuffer.
- Spawn => Spawn new instances by writing Instance Buffer (only particles for now).
- Kinematics => Transform (move, rotate, scale) instances accordingly (kinematic, particles and boids).
- Frustum Culling => Test camera frustum against instance bounds (static instances only) and writes instance count per batch.
- Prefix Scan => Using instance count calculates first instance (offset) on each batch.
- Compaction => Writes visible instances buffer.
- Depth Only => Renders depth using indirect drawing.
- Hi-Z Copy => Copy depth attachment to Hi-Z texture.
- Hi-Z Downsample => Down sample Hi-Z texture from high to low mip levels.
- Reset Counters => Reset instance count on each draw command in DrawCommandBuffer.
- Frustum Culling => Test camera frustum against instance bounds and writes instance count per batch.
- Occlusion Culling => Test object depth against Hi-Z texture sampled depth to cull occluded instances.
- Prefix Scan => Using instance count calculates first instance (offset) on each batch.
- Compaction => Writes visible instances buffer.
- Shadow => Renders depth from light perspective using indirect drawing (not used for now).
- Forward => Renders visible instances using indirect drawing and material batching.
- Skybox => Renders skybox behind.
- Bloom Bright => Extracts brightness from rendered image and writes to bloom texture.
- Bloom Downsample => Downsamples the bloom texture from high to low mip levels.
- Bloom Upsample => Upsamples the bloom texture from low to high mip levels.
- Post Process => Applies bloom and tone mapping to rendered image.
Demo: Kinematics + Particles
6,000 spheres leaving a trace of particles (around 60,000 particles in total).
Demo: Flocking
10,000 paper planes flocking
RenderDoc Frame Captures
Instance and Boid Buffers
Instance count after culling
Indirect drawing color output
Indirect drawing depth output
Bloom texture
