I am new to graphics programming and I'm trying to create an efficient 2D tilemap renderer (using rust and wgpu (webgpu)).
My current implementation
My current implementation consists of:
- A Rust-Vec (contains all tiles needed for rendering in a normal buffer)
- A Vertex Buffer (contains 4 Vertices, describing a quad)
- An Index Buffer (contains Indices to define the said quad)
- An Instance Buffer (basically contains ALL the tile data (currently only world positions (2 u32 Integers))
- A Uniform Buffer (contains current camera position (x, y, zoom))
The 1. buffer (Rust-Vec) is updated and copied to the Instance Buffer every new frame (both buffers are fully replaced every frame). In order to improve performance a bit, the world is split up into chunks. Although that does not affect the rendering process after the needed tiles are loaded into the 1. buffer.
The instance data (tile coordinates) is translated to the relative normal positions in the vertex shader.
My project currently does not support textures etc.
Problem
When zooming out far enough, but not unreasonably far, the frame time starts to increase immensely. Looking at a flamegraph I have found the part of code that takes the longest is updating the 1. Vector and copying it to the instance buffer. Sadly I have not come up with a more efficient solution to rendering large amounts of 2D tiles.
Question
What concepts and ideas can I make use of to increase the performance of my project? Is my current solution inherently flawed, or is it somewhat acceptable?