stardance has been extended another month! the new deadline is october 31 :)

You are browsing as a guest. Sign up (or log in) to start making projects!

Light

@Light

Joined June 4th, 2026

  • 36Devlogs
  • 1Projects
  • 1Ships
  • 19Votes
I'm a 15 years old guy from Italy. I'm curious about how low-level systems work, and this summer I took the opportunity to explore them with Vulkan and C++ with my project called Eve.
Ship Pending review

Eve is a graphics engine written entirely in Vulkan, with the primary goal of learning Vulkan and C++ while simplifying their usage. Originally conceived as a simple, lightweight wrapper around Vulkan, Eve now includes:

A Render Graph designed from scratch that leverages technologies such as memory aliasing (where multiple resources share the same memory space) and resource pooling (reusing resources across frames). It performs the core function of a Render Graph: by simply knowing how resources are utilized, it automatically issues the necessary synchronization barriers to the GPU. Developing the Render Graph was a grueling process, but it proved worthwhile in terms of both performance and the educational value of the experience.

An ECS (Entity Component System) also designed from scratch, following the model of Unity’s DOTS ECS. Instead of scattering resources across VRAM—which slows down access due to constant memory jumps—game objects are organized into Archetypes. Components are distributed in contiguous memory batches, thereby minimizing cache misses.

A rendering system that automates the insertion of transforms into buffers; these are subsequently processed into matrices via a compute shader and sent to the rendering shaders. It also features a material system that analyzes shader composition, looking for a struct named “Properties” that allows fields to be assigned by name from the C++ side.

Support for the Slang shading language with a bindless system. Eve provides a file named Eve.slangh that simplifies and automates the retrieval of textures, buffers, and samplers from descriptors. Compute shader support is also included.

An integrated, easy-to-use Input system inspired by Unity’s Input System, along with a lightweight UI wrapper that makes using Dear ImGui simpler and more intuitive.

Eve also includes a demo featuring a gravitational simulation of thousands of entities orbiting a black hole, allowing various parameters to be adjusted in real-time.

  • 36 devlogs
  • 294h
Try project → See source code →
Open comments for this post

8h 50m 46s logged

DEVLOG 36 - Black Hole!

Hi Stardance!
 
Intro
I’ve been working really hard lately, and I think I’ve reached a milestone with Eve that I honestly never expected to hit. The project is finally complete; now I just need to click that nice button to ship it. I’ve spent this time working on the README, improving the documentation, fixing bugs, and building a demo using Eve.
 
Eve Demo
The demo is a gravity simulation featuring hundreds of thousands of entities orbiting a black hole. You can tweak various parameters—such as time, the black hole’s gravitational pull, lighting, colors, meshes, and much more. If you’d like to test it out, you can find it in the GitHub releases; there’s a ready-to-use .exe, or the source code if you’re on Linux—or if you simply want to understand how Eve works or make some modifications yourself.
 
Problems Encountered
While building the demo, I ran into—and have since resolved—some very frustrating bugs, such as memory corruption in the ECS caused by the continuous creation and destruction of entities and their components. I also added UI text support and implemented the ability to register “stages” belonging to classes or structs that can be called by the engine.

0
0
17
Open comments for this post

8h 5m 57s logged

DEVLOG 35 - Documentation

Hi Stardance!
 

Intro
I’ve finally finished writing the documentation for Eve—a rather tedious and repetitive process, but a necessary one.
 
How The Docs Is Structured:
Every part of the engine is documented; inside the docs folder, you’ll find instructions on how to launch the engine, along with subfolders for each component—graphics, input, window management, and so on.
 
Next Last Steps:
I still need to create the README and tidy up a few things in the project, as well as write instructions on how to configure Eve for use on one’s own PC… But after a whole summer, I’m finally close to shipping!

0
0
18
Open comments for this post

2h 48m 52s logged

DEVLOG 34 - Icon, Windows & More

Hi Stardance!
 
Intro
The release is getting close, so I’m tidying up a few final details; I’ve finally turned my attention to a slightly more relaxed and lighthearted part of the project.
 
Engine Settings
I added a method to start the engine that accepts configuration settings for how the app runs. You can also choose whether or not to enable VSync at runtime.
 
Window Class
I added a window management class that allows for various operations, such as toggling fullscreen mode and manually changing the resolution, position, title, etc. I also included a method to set the window icon using a PNG image.
 
Eve’s Icon
I also spent some time on Canva trying to create an icon—a logo—for Eve. After several attempts, I settled on the one in the attachment.

0
0
25
Open comments for this post

4h 2m 21s logged

DEVLOG 33 - Meshes & Fixes

Hi Stardance!
 
Intro
We’re getting closer to the release build of Eve! I have to say that with this devlog, the engine is practically finished and ready for shipping; I just need to tweak a few final details and we’re all set…
 
Meshes:
In this devlog, I worked on the mesh system—fleshing it out and making it functional—and added standard meshes to Eve: a cube, a UV sphere, an icosphere, a plane, and a quad.
 
Some Bugs Fixed
While implementing this, the program kept crashing for no apparent reason; after two hours of debugging, I found the error in the Render Graph—caused by the order of Eve’s internal passes—which is now fixed.
 
Internal Shaders Organization
I also embedded the engine’s internal shaders directly into the executable, so there’s no need to remember to include them alongside the executable when creating an app.
 
The video shows the same UI as the previous devlog—featuring controls for color, rotation, cube position, and direct light direction—but this time, you can change the meshes of the “thousand-odd” cubes at runtime using the standard Eve meshes listed above, via a simple UI dropdown menu.

0
0
13
Open comments for this post

7h 53m 10s logged

DEVLOG 32 - UI Support

Hi Stardance,
 
Intro
I’ve been working on the UI lately, as I wanted to give the user a way to interact with the engine beyond just mouse and keyboard input.
 
The UI in Eve
I opted for Dear ImGui and created a lightweight wrapper that allows it to run within Eve. I stripped away some of the boilerplate code associated with the standard Begin and End calls, making it slightly simpler and safer to use than raw ImGui. I also added support for dockable windows.
 
The video shows a scene with 1,000 cubes; thanks to the UI, you can modify their color, position, and rotation. You can also change the direction of the direct light. The code required by this UI is just five lines.

0
0
7
Open comments for this post

17m 51s logged

DEVLOG 31 - It’s not my fault!

Hi Stardance!
 
Unlike the other devlogs, this one is very quick and simple.
 
A Little Recap
In devlog 29, I encountered some issues with RenderDoc, even though the app kept running fine and caused no problems outside of RenderDoc itself.
 
What I Did
After doing some online research, I discovered that RenderDoc has issues with AMD drivers, which can cause the app to crash. So, I decided to try AMD’s Radeon Developer Tools (a profiler similar to RenderDoc, designed specifically for AMD GPUs). No errors were reported and everything works perfectly, so the problem most likely lies in how AMD drivers interface with RenderDoc.

0
0
34
Open comments for this post

5h 38m 38s logged

DEVLOG 30 - Compute Shaders

Hi Stardance!
 
Intro
I’ve finally implemented compute shaders—as the title suggests—alongside conducting some tests and reorganizing the project.
 
Compute Shader Support
I’ve added support for compute shaders, meaning they can now be used just like any other type of pass, whether graphics or transfer.
 
Optimizations
I’ve also utilized compute shaders internally within the engine to speed up matrix calculations; here are the results:
With 100,000 entities using instanced rendering, I’m getting 800 FPS, up from the previous 250.
With 1,000,000 entities using instanced rendering, I’m getting around 90 FPS, up from the previous 30.
With 100,000 entities using independent draw calls, I’m getting around 90 FPS, up from the previous 30.
I’d say the results speak for themselves, and I’m quite happy with these optimizations. As mentioned in the previous devlog, testing was performed on my PC, which is equipped with a Ryzen 5 5600X and an RX 6600.
 
Swapchain & CMake
I also made slight modifications to the swapchain recreation code to make it faster and reduce stuttering.
Finally, I tidied up the CMakeLists file to make it more organized and prepare for the release.
 
The video shows a scene with 1M entities rendered in real-time using instanced draw call at 90 FPS

0
0
13
Open comments for this post

8h 4m 40s logged

DEVLOG 29 - 1M Entities!

Hi Stardance!
 
Intro
Since the last day, I’ve been working alone and have run into several issues… Most of them have been resolved.
 
Some Tests
So I started running some tests to check the speed of my new rendering system, and with 100,000 entities drawn to the screen with a single draw call, I was getting 30 FPS. After parallelizing the code a bit and reducing the copies, the results are now better:
100,000 entities with single draw calls get 50-60 FPS.
100,000 entities with a single instanced draw call get 230-250 FPS.
1,000,000 entities with a single instanced draw call get 30 FPS.
 
What Need To Be Optimized
Actually, I could optimize even more and double these FPS, but the current problem is that I’m calculating the matrices on the CPU side, so I’m doing a lot of calculations that currently take up a good portion of the necessary CPU time, about 50%. The idea would be to move all the work to the GPU in the future with compute shaders, thus significantly reducing the CPU load. I’ll see if I can do this… Maybe in a while, when I add full support for compute shaders. (I have a Ryzen 5 5600 X and an RX 6600)
 
Rendering System Time:
Not counting the matrices, the rendering cycle along with the Render Graph takes about 2-2.5 ms, almost all of which is spent on the Render Graph. I have also fixed some problems with Swapchain Recreation when the window is minimized.
 
Problems With RenderDoc
Five of these eight hours have been pure frustration, as I don’t understand why, but the app crashes on RenderDoc. Normally, on my PC it starts and works, but on RenderDoc it crashes… I’ve tried every way to understand the problem, but unfortunately I haven’t been able to. I’ll also test on other PCs to better understand the problem. Unfortunately, I don’t have time on my side, so I’ve had to put the issue aside for now…

0
0
9
Open comments for this post

10h 13m 34s logged

DEVLOG 28 - New Render System

Hi Stardance!
 
Intro
I think this devlog is consistent with the next one I’m working on, since the work I’ve done in the last few hours isn’t quite finished, as there are still some bugs to resolve…
 
Why a new render system?
So far, I’ve been working on improving Eve’s rendering system. Instead of having to manually create buffers and the like, Eve has a completely automated system similar to the one used by Unity. For example, when you try to draw an object, you need things like object transformation matrices. If you then need more data, the limited size of push constants is no longer enough.
 
Per Instance Params
Eve, therefore, with its new rendering system, revolutionizes the way we write code, reduces bugs, and simplifies it. For each draw call sent to the GPU, the engine sends a buffer called InstanceParams to the GPU, which contains, for each drawing instance, its model matrix and its inverse. These matrices can then be retrieved using simple, custom functions ready for use in the shader.
 
Per Render View Data
For camera data, the process is similar. For each RenderView object, Eve allocates these objects on the GPU in a contiguous buffer from which the view, perspective, VP, and other matrices can be accessed.
 
Custom Draw Info Data
If you want to send custom data to the shader, each drawing function offers a pointer called DrawInfo that allows you to send data to the shader, which can then be accessed. If set to null, the shader will not send anything.
 
GLM & A Flycam
I also created a flycam and deprecated the Eve math package to use the glm one. Honestly, I want to focus on Eve and not the math, which is why I chose this option.
 
Next Step:
I still have some bugs to fix regarding making more than one draw call, but I’m working on it.

0
0
57
Open comments for this post

7h 29m 35s logged

DEVLOG 27 - Material System

Intro
After some code rewrites, such as the separation between shaders and materials, the materials system now works. It’s very similar to how it works in Unity. I’ve figured out how to set things like material properties (floats, integers, vectors, etc.) directly from C++ using their names, without manually binding code.
 
How Vulkan Handle All Of This?
In Vulkan, you can’t set a shader parameter directly with a name. You need to create a buffer on the GPU, specifically a UBO, typically used for materials, bind it using a descriptor, and then bind it on the CPU. All of this is hidden by Eve, making the code easier and faster to write.
 
What It Does?
Basically, once the shader is compiled, it’s analyzed and checked for a struct called Properties. If it exists, this struct will be used for the material properties. Each field within it will be settable directly from the CPU using its name. Eve, now knowing the size of the struct and the field offsets, creates a buffer for the materials (actually, one for each frame in flight) and uses it to write everything a material might need, thus allowing for very simple parameter setting.
 
How To Use It:
The material provides an ID via the GetPropertyUBOId function, which must always be retrieved at each frame since it is not the same from frame to frame. This ID can be sent to the shader via push constant, which then allows access to the material’s property UBO, which contains all the values ​​set on the CPU side.
 
A simple cube rotating on itself using the new Material System and simple direct lighting

0
0
14
Open comments for this post

4h 53m 55s logged

DEVLOG 26 - Input System

 
Hi Stardance!
 
The New Input System
Since I couldn’t interact much with the graphics engine at the moment, I chose to create an Input System that currently only supports keyboard and mouse. It has methods like IsKeyDown(...), GetMouseState(...), IsMouseUp(...), and similar ones. It’s quite simple, but it allows you to interact with the world, for example by creating a camera or a moving player.
 
The Cube
For fun and to test a bit, I tried creating a scene with a slightly rotated cube with direct light, obviously using my Render Graph, which allows you to do all this in about 150 lines of code (CPU side) instead of having to manually write barriers, configure passes, and many other repetitive tasks.
 
I’m still using glm for matrix math, but I’m trying to reach a more stable level with the Eve package.

0
0
14
Open comments for this post

7h 10m 25s logged

DEVLOG 25 - Eve is “Multi PC”

 
Hi everyone!
What’s changed since last time?

 
More Device Supported
As promised, Eve now uses Vulkan 1.2, so it can be used on multiple devices. Obviously, the device requires that, in addition to supporting Vulkan 1.2, it also supports some extensions that became core in Vulkan 1.3.
 
Tests On Other PCs
I then tried running the app on the only PC I had at home, but it crashed. I then tried updating the graphics driver, but that didn’t help; unfortunately, that PC is too old. I then asked a friend of mine to test the app. After fixing some issues, it started, but it would crash instantly. After hours of debugging, I found the problem: the problem was in resource allocation within the Render Graph, which only occurred with integrated GPUs (my heap selection algorithm for integrated GPUs was wrong). It’s now fixed. I also added my checks for failed Vulkan or VMA calls in places where they were missing, so now everything should work properly.
 
Math Packet In Eve
I also added a small mathematical component to Eve, including Vector2,3,4; Vector2Int,3Int,4Int; Quaternion; and Matrix4x4. I must say that quaternions were difficult to understand at first, but once you understand how they work, it’s very easy to visualize them in your head.
 
 
The first attachment shows Eve running on the PC of this friend of mine, whom I thank so much for his help, and the second image shows Eve running on my PC.

0
0
12
Open comments for this post

4h 35m 39s logged

DEVLOG 24 - Error Manager, Copies & More

 
Intro
Hi Stardance!
Lately, I’ve been focusing mainly on improving error handling returned by Vulkan and fixing some code here and there.
 
New Error Manager System
I’ve created a system responsible for error handling so that when an error occurs, such as a failure to allocate memory due to fragmentation or any other critical error, the app places a text file with information about the error in a folder called logs (created on the fly if it doesn’t exist). Immediately afterward, an error message is displayed on the screen explaining what happened. When the user presses the OK button, the app closes in the pop-up by calling std::abort();.
 
Some Test On Other PCs
I tried running Eve outside of my PC on two other PCs, but since they’re a bit older, they don’t have support for Vulkan 1.4, so the app can’t be started.
 
Swapchain Improvements
The code for creating the swapchain has been improved somewhat, making it more secure and robust.
 
New Copy Support
I’ve added support for buffer and texture copy operations between resources that aren’t the same type (one transient and one persistent).
 
Next Step:
I want to make Eve a little more portable, so in the next few hours I’ll try using Vulkan 1.2, trying not to mess with the code. If necessary, I might resort to using Vulkan 1.3; I’ll see…

0
0
15
Open comments for this post

3h 56m 7s logged

DEVLOG 23 - Instanced Draw & Some Fixes

 
Intro
Devlog time!!
In the last devlog, I had some issues with instanced drawing and reading a position buffer.
 
What Was The Problem?
I worked hard, but I managed to figure out where the problem was and fix it. (The problem was due to a for loop responsible for creating the address buffers. I was saving pointers outside the for loop with structs allocated inside the for loop; therefore, the pointers were pointing to corrupted memory or nothing.)
 
Render Graph Fixes
I fixed several things in the Render Graph that could cause future problems. I added small guards within the Render Graph so that if the user does something wrong, the application doesn’t crash unexpectedly. For example, previously, if the user set a texture to display that they’d never used (never involved in a transfer operation, never used as a graphic attachment), the program would crash. With these simple guards, everything is solved.
 
Easier Resource Usage Declaration
I’ve also added the ability to easily declare textures and buffers usage in the Graphics Pass class with dedicated methods like UseBufferReadOnlyVertex(...), UseTextureVertex(...), and others.
 
The image shows a grid of 20x20 quad meshes drawn with a single draw call instead of 400 using instanced draw.

0
0
23
Open comments for this post

10h 30m 42s logged

DEVLOG 22 - ECS Bugs Fixed, Graphics Files Reorganized

Hi Stardance!
 
What I Did
In this dev log, I fixed some of the last bugs the ECS code, so it now works and is very efficient. I ran several tests destroying, creating, and moving entities from one archtype to another, and everything works. I then worked on the project structure of the graphics part by fixing the graphics include files.
 
What Went Wrong
These updates mentioned so far have been successful. Two hours ago, I added a method in the graphics pass responsible for instanced drawing, so I took advantage of the opportunity to create a buffer to read the instance positions to see if it worked. I still don’t know why, but it doesn’t work. The application freezes, and sometimes the driver crashes (it scared me a little… :/ ). The Validation Layers don’t report anything wrong… So I need to figure out what’s wrong and fix it.
 
The image shows some of the methods available after fixing the folders. The methods are in the Graphics class in the include folder.

0
0
13
Open comments for this post

10h 9m 5s logged

DEVLOG 21 - ECS Refactoring

 
Intro
Over the past ten hours, I’ve worked extensively on the ECS, making it more robust, easier to use, more secure, and more efficient. What’s changed:
 

  • New Way To Record Entity Commands
    Entity Command Pools are still used, but they’re managed not by the user but by the Entity Manager. The old CreateCommandPool() method no longer exists. Now, to execute a command on entities, you make a request to the EntityManager, which takes the command and places it in an EntityCommandPool of its choosing. The EntityCommandPool is chosen based on the SystemId provided by the engine with methods like Start, Awake, Update, etc. This reduces complexity and allows for systems that can run natively in parallel on multiple threads.
     
  • Improved Efficiency
    Internally, the Entity Manager has improved the way to compact batches after command execution, making it simpler and faster. Instead, iterating over all batches only iterates on the entities that are no longer valid, and those slots are refilled with the components of the valid entities at the end of the last batches. Batch creation and destruction is handled automatically by the EntityManager.
     
  • New Way To Query Tables
    The way to find tables with certain requirements has improved; the old method required registering a query and then returning a “ticket” used to access the query results. The operation is now simpler and more unified: The EntityManager is asked for all tables that meet the QueryInfo structure requirements, such as the archtype. The EntityManager checks whether the query already exists; if it doesn’t, it calculates it on the fly and returns it.
     
  • Queries Updated Only When Needed
    Queries are updated only when tables are created/destroyed; otherwise, they remain - static and aren’t updated, saving calculations.
     
    The next step will be to verify if everything works, since I haven’t tested anything yet because I’m forced to do this devlog due to the ten-hour time limit. :/
     
     
    Sorry about the picture, it’s the same, I didn’t have time to do anything else
0
0
7
Open comments for this post

5h 48m 46s logged

DEVLOG 20 - A Better Triangle

 
Intro
Hi Stardance!
This triangle was created with Render Graph. The entire process is divided into two steps: the first draws the triangle on a user-selected image, and the second takes that image, samples it, and draws it on the swapchain so the triangle can be seen on screen.
 
Clean and Simple API
The beauty of this is evident in the photo (third attachment). You only need to write a few lines of code to achieve all this compared to the complexity and number of lines of code required by Vulkan. Render Graph thus creates all the resources needed for synchronization, such as barriers, and attempts to alias memory whenever possible. It also leverages Resource Pooling, so images aren’t destroyed and recreated at every frame. Instead, if they have identical requirements, they are reused, avoiding unnecessary Vulkan calls.
 
MSAA Deprecated
MSAA images have been deprecated because, from a desktop computer perspective, they aren’t worth using because they require a lot of computational resources. To achieve anti-aliasing, it’s best to use post-processing passes that use FXAA (Fast Approximate Anti-Aliasing) or TAA(Temporal Anti-Aliasing).
 
There are probably some bugs still present in the Render Graph despite the many already fixed; I’ll work on them.

2
0
35
Open comments for this post

9h 52m 40s logged

DEVLOG 19 - Colors!

 
Hi Stardance!
I’ve made some progress and finally drew something on the screen!
 
Improvements on the Swapchain Pass
I’ve improved the Render Graph a bit by cleaning up old methods and making all the improvements discussed in the last devlog, such as improving the rendering code for the swapchain. Normally, you would set the 2D texture to display on the screen using the RenderGraph::SetPresentTexture(); In reality, this texture isn’t displayed directly on the screen but is first sampled and copied to the swapchain, so the Render Graph adds a hidden pass for this. When this texture hasn’t been assigned to any texture, the swapchain will be colored with the clear value set to black and sent to the screen.
 
Push Constants Supported
I’ve added the ability to use Vulkan Push Constants. Push Constants are data packets that can be sent to the GPU in parallel with the drawing command. Their size is very limited, 128 bytes, but their transfer speed is extremely fast. A hardware limitation is that the offset and size parameters must be multiples of four, so I used a struct called Words32 to dictate the 32-bit size and offset, not the 8-bit one. Furthermore, internally, the engine checks the state of the previous push constant for each push constant update, so as not to make unnecessary updates and to register the push constant command only when necessary, and only partially for the relevant bytes.
 
Shaders Improvements
I improved the shader code a bit by reducing the arguments needed to create a shader, and I also unified the layout; all shaders use the same VkPipelineLayout.
 
The Problem and The Solution
When I was writing the shaders to get these things on screen, I ran into errors telling me I was assigning a buffer descriptor to Descriptor Set 0 with binding 0, even though they’re actually textures. However, in the shader, I wasn’t requesting any of this, since the vertex data was written directly into the shader. After some research, I discovered that Slang shaders were creating bindings for these arrays outside the shader. To fix this, I simply moved the arrays into the vertex shader function, marking them with const.
 
And note that all these images/videos use the swapchain pass, so this was all just a test. Now I’ll have to try declaring a real pass with Render Graph and try to draw something, hoping everything works correctly :/

0
0
8
Open comments for this post

10h 1m 26s logged

DEVLOG 18 - More Refactoring

 
Hi Stardance!
I don’t know what to say about this devlog, since I’ve written a lot of code for my specific implementation… I’ll try to describe what I did without being too boring.
 
Why I refactored again?
As discussed in the previous devlog, I felt the code wasn’t “nice” or at least not very tidy, and honestly, I don’t like that very much, so I rewrote the Render Graph (partially) for the third time. Now, the Render Graph only manages single-frame resources, while all multi-frame resources are managed by a separate class called TransientResourcePool, which is therefore responsible for storing the resources.
 
The Render Graph: A single frame responsibility
The Render Graph is still responsible for memory aliasing and resource pooling, of course, as well as generating barriers and inserting the draw, copy, and, in the future, compute commands. (I still need to improve the code for compiling commands into the Command Buffers a bit.)
 
Improvement in the searching of pooled resources
Now, searching for resources to reuse is even faster, since resources are divided by their composition, for example. For textures, the parameters for this division are height, depth, width, samples, etc. This allows you to immediately find a resource if it’s available.
 
More organization is the TransientResourcePool
The TransientResourcePool is also responsible for permanently destroying unused resources for several frames. I had written the destruction code within the TransientResourcePool, but I thought maybe it wasn’t its responsibility, but rather an existing class called MemoryBin. The MemoryBin class was configured to work only for persistent resources, but now it handles the destruction of persistent and transient resources.
 
What I need to fix:
There’s a small problem in the code: Normally, when you want to destroy a resource, it’s queued and usually assigned a countdown. This countdown is a number that corresponds to the maximum frames in flight and decreases by one every frame. When this number reaches zero, the resource can be destroyed. This works perfectly, but when, for example, the swapchain needs to be recreated because the window size has changed, the GPU needs to be put into idle mode. This means that all in-flight frames have finished, and therefore all resources queued for destruction can and must be destroyed immediately, otherwise they would pile up.
 
Otherwise, I think everything is perfect. I don’t think it will take me long to implement these little tricks, so I assume and hope :/ to start writing the code to display something on the screen soon. I’ll go back to my old, dear little triangle :)

0
0
16
Loading more…

Followers

Loading…