Structs & Data Layout
3D Vertex
Total stride: 44 bytes. Used for all 3D geometry (loaded meshes + procedural primitives).
UI Vertex
Total stride: 32 bytes. Used for debug overlay text and background quads.
GlyphInfo
Stores baked glyph metrics from stb_truetype. Array of 95 entries (ASCII 32-126).
Push Constants
3D Push Constants
Sent per-entity via vkCmdPushConstants to the vertex shader.
UI Push Constants
Sent once per UI draw to convert pixel coords to NDC.
Uniform Buffer Objects
View/Projection UBO (set 0, binding 0)
Updated per frame. Projection Y-axis is flipped for Vulkan (proj[1][1] *= -1).
Light UBO (set 0, binding 1)
alignas annotations are critical for std140/std430 layout compatibility.
Material Data
Each material owns its GPU texture resources and a descriptor set bound to pipeline set 1.
Mesh Data
Entity Data
The same EntityData struct is used for both regular entities (entities_) and debug wireframe entities (debugEntities_). Each has its own free-slot list for ID reuse.
Queue Family Indices
Combined Buffer Strategy
All mesh vertices are concatenated into a single allVertices_ vector and all indices into allIndices_. Each MeshData stores its vertexOffset and indexOffset into these combined arrays. At draw time, vkCmdDrawIndexed uses these offsets:
This means a single vertex buffer bind + single index buffer bind serves all entities. New meshes are appended and buffersNeedRebuild_ is set to true, triggering rebuildGeometryBuffers() on the next frame (staging buffer -> device-local copy).
Adding a new vertex attribute: Add the field to Vertex in renderer.h, add a new VkVertexInputAttributeDescription in getAttributeDescriptions(), update the array size, and update shader.vert to declare the new input/output.
Changing UBO layout: Modify the struct in renderer.h, ensure alignas matches std140 rules, update the corresponding GLSL uniform block, and verify sizeof() matches between C++ and shader.