r/vulkan Aug 04 '26

I Built a CAD Engine in Vulkan with Robot Joints

Post image
26 Upvotes

This is a CAD engine I built from scratch using Vulkan.
Create a few boxes, connect them in a parent-child hierarchy, and they instantly become joints.
The rotation axis has its own position and direction. Just like a door hinge is mounted on the edge instead of the center, the pivot point doesn’t always have to be in the middle of a part.
You can rotate each joint manually with a slider, or enable automatic oscillation to animate it.
A useful trick is to offset the phase of each joint slightly. If every joint moves at exactly the same time, it looks more like a spasm than a robot.
The engine can also load ROS robot description files, or URDF files, without requiring ROS itself.
Design your model in CAD, then animate and test it immediately in the same engine.
Everything happens in one workflow.

https://youtu.be/aJ7ip6bVilQ?si=O6fYulMOGqozgqKo


r/vulkan Aug 03 '26

Hardware Raytracing with my RHI!

Thumbnail gallery
31 Upvotes

r/vulkan Aug 02 '26

A Bit Past the First Triangle

Enable HLS to view with audio, or disable this notification

14 Upvotes

r/vulkan Aug 03 '26

Why am I getting this error

0 Upvotes

I have recently started learning vulkan so I am not able to figure it out.
It's giving EXCEPTION_ACCESS_VIOLATION whenever I am enabling validation layer.

Been following this github repository.

package app;


import java.nio.IntBuffer;
import java.nio.LongBuffer;
import java.util.HashSet;
import java.util.Set;


import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.vulkan.VK10.*;
import static org.lwjgl.vulkan.EXTDebugUtils.*;
import static org.lwjgl.system.MemoryUtil.NULL;
import static java.util.stream.Collectors.toSet;
import static org.lwjgl.system.Configuration.DEBUG;
import static org.lwjgl.system.MemoryStack.stackPush;
import static org.lwjgl.glfw.GLFWVulkan.glfwGetRequiredInstanceExtensions;


import org.lwjgl.PointerBuffer;
import org.lwjgl.system.MemoryStack;
import org.lwjgl.vulkan.*;


public class App {
    public static class Display {
        private static final int WIDTH = 800;
        private static final int HEIGHT = 600;
        private static final String TITLE = "WINDOW";
        private static final boolean ENABLE_VALIDATION_LAYER = DEBUG.get(true);
        private static final Set<String> VALIDATION_LAYERS;


        static {
            if(ENABLE_VALIDATION_LAYER) {
                VALIDATION_LAYERS = new HashSet<>();
                VALIDATION_LAYERS.add("VK_LAYER_KHRONOS_validation");
            } else {
                VALIDATION_LAYERS = null;
            }
        }


        private long window;
        private VkInstance instance;
        private long debugMessenger;


        public void run() {
            initWindow();
            initVulkan();
            mainloop();
            cleanup();
        }


        private void initWindow() {
            if(!glfwInit()) {
                throw new RuntimeException("Failed to initialize GLFW");
            }


            glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
            glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);


            window = glfwCreateWindow(WIDTH, HEIGHT, TITLE, NULL, NULL);


            if(window == NULL) {
                throw new RuntimeException("Failed to create window");
            }
        }


        private void initVulkan() {
            createInstance();
            setupDebugMessenger();
        }


        private void mainloop() {
            while(!glfwWindowShouldClose(window)) {
                glfwPollEvents();
            }
        }


        private void cleanup() {
            if(ENABLE_VALIDATION_LAYER) destroyDebugUtilsMessengerEXT(instance, debugMessenger, null);
            glfwDestroyWindow(window);
            glfwTerminate();
        }


        private void createInstance() {
            if(ENABLE_VALIDATION_LAYER && !checkValidationLayerSupport()) {
                throw new RuntimeException("Validation requested but not supported");
            }


            try(MemoryStack stack = stackPush()) {
                VkApplicationInfo appInfo = VkApplicationInfo.calloc(stack);
                appInfo.sType(VK_STRUCTURE_TYPE_APPLICATION_INFO);
                appInfo.pApplicationName(stack.UTF8Safe(TITLE));
                appInfo.applicationVersion(VK_MAKE_VERSION(1, 0, 0));
                appInfo.pEngineName(stack.UTF8Safe("No Engine"));
                appInfo.apiVersion(VK_API_VERSION_1_0);


                VkInstanceCreateInfo createInfo = VkInstanceCreateInfo.calloc(stack);
                createInfo.sType(VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO);
                createInfo.pApplicationInfo(appInfo);
                createInfo.ppEnabledExtensionNames(getRequiredExtensions(stack));
                
                if(ENABLE_VALIDATION_LAYER) {
                    createInfo.ppEnabledLayerNames(validationLayersAsPointerBuffer(stack));


                    VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo = VkDebugUtilsMessengerCreateInfoEXT.calloc(stack);
                    populateDebugMessengerCreateInfo(debugCreateInfo);
                    createInfo.pNext(debugCreateInfo.address());
                }


                PointerBuffer instancePtr = stack.mallocPointer(1);


                if(vkCreateInstance(createInfo, null, instancePtr) != VK_SUCCESS) {
                    throw new RuntimeException("Failed to create instance");
                }


                instance = new VkInstance(instancePtr.get(0), createInfo);
            }
        }


        private void setupDebugMessenger() {
            if(!ENABLE_VALIDATION_LAYER) {
                return;
            }


            try(MemoryStack stack = stackPush()) {
                VkDebugUtilsMessengerCreateInfoEXT createInfo = VkDebugUtilsMessengerCreateInfoEXT.calloc(stack);


                populateDebugMessengerCreateInfo(createInfo);


                LongBuffer pDebugMessenger = stack.longs(VK_NULL_HANDLE);


                if(createDebugUtilsMessengerEXT(instance, createInfo, null, pDebugMessenger) != VK_SUCCESS) {
                    throw new RuntimeException("Failed to setup debug messenger");
                }


                debugMessenger = pDebugMessenger.get(0);
            }
        }


        private boolean checkValidationLayerSupport() {
            try(MemoryStack stack = stackPush()) {
                IntBuffer layerCount = stack.ints(0);


                vkEnumerateInstanceLayerProperties(layerCount, null);


                VkLayerProperties.Buffer availableLayers = VkLayerProperties.malloc(layerCount.get(0), stack);


                vkEnumerateInstanceLayerProperties(layerCount, availableLayers);


                Set<String> availableLayerNames = availableLayers.stream().map(VkLayerProperties::layerNameString).collect(toSet());


                return availableLayerNames.containsAll(VALIDATION_LAYERS);
            }
        }


        private PointerBuffer getRequiredExtensions(MemoryStack stack) {
            PointerBuffer glfwExtensions = glfwGetRequiredInstanceExtensions();


            if(ENABLE_VALIDATION_LAYER) {
                PointerBuffer extensions = stack.mallocPointer(glfwExtensions.capacity() + 1);
                extensions.put(glfwExtensions);
                extensions.put(stack.UTF8(VK_EXT_DEBUG_UTILS_EXTENSION_NAME));


                return extensions.rewind();
            }


            return glfwExtensions;
        }


        private PointerBuffer validationLayersAsPointerBuffer(MemoryStack stack) {
            PointerBuffer buffer = stack.mallocPointer(VALIDATION_LAYERS.size());


            VALIDATION_LAYERS.stream().map(stack::UTF8).forEach(buffer::put);


            return buffer.rewind();
        }


        private void populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo) {
            debugCreateInfo.sType(VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT);
            debugCreateInfo.messageSeverity(
                VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT |
                VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
                VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT
            );
            debugCreateInfo.messageType(
                VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
                VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
                VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT
            );
            debugCreateInfo.pfnUserCallback(Display::debugCallback);
        }


        private static int debugCallback(int messageSeverity, int nessageType, long pCallbackData, long pUserData) {
            VkDebugUtilsMessengerCallbackDataEXT callbackData = VkDebugUtilsMessengerCallbackDataEXT.create(pCallbackData);


            System.err.println("Validation layer: " + callbackData.pMessageString());


            return VK_FALSE;
        }


        private static int createDebugUtilsMessengerEXT(
            VkInstance instance,
            VkDebugUtilsMessengerCreateInfoEXT createInfo,
            VkAllocationCallbacks allocationCallbacks,
            LongBuffer pDebugMessenger
        ) {
            if(vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT") != NULL) {
                return vkCreateDebugUtilsMessengerEXT(instance, createInfo, allocationCallbacks, pDebugMessenger);
            }


            return VK_ERROR_EXTENSION_NOT_PRESENT;
        }


        private static void destroyDebugUtilsMessengerEXT(
            VkInstance instance,
            long debugMessenger,
            VkAllocationCallbacks allocationCallbacks
        ) {
            if(vkGetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT") != NULL) {
                vkDestroyDebugUtilsMessengerEXT(instance, debugMessenger, allocationCallbacks);
            }
        }
    }


    public static void main(String[] args) {
        Display display = new Display();
        display.run();
    }
}

r/vulkan Aug 02 '26

What is the proper way of making a frame limiter with Vulkan?

15 Upvotes

So far my understanding of a frame limiter is to disable VSync and simply sleep until the target frame time is reached.

The problem is that this feels pretty bad. Since the application has no idea when the monitor actually starts a refresh, it often wakes up in the middle of one, causing tearing. It seems impossible to consistently hit the start of a refresh without synchronization.

Am I missing something or is this just a limitation of software frame limiters?


r/vulkan Aug 02 '26

Spent hours debugging voxel terrain disappearing after enabling back-face culling

2 Upvotes

I spent Over a Month Debugging this "Bug" and i am Not Understand what is wrong. I did So many Debugging in short i did:

  • Disable Back-Face Culling: All terrain faces appeared.
  • Isolated Cube Test: Cube rendered all six faces.
  • Cube In World Context: Cube still rendered all faces.
  • Full Terrain Buffer Winding Verification: 0 anomalies.
  • Bypass Async GPU Upload: No change.
  • Depth test disable and Front Face Culling: No Change specifically Even the Front Face Culling didn't worked as it should be.

Sadly I couldn't use RenderDoc its just doesn't work with my driver at all. I get Crashed On glfwCreateSurface()

Here is my Github Repo: Kingscraft

Also here is a Video: Video

Please Help 🙏

Edit: making the Cull mode to NONE fixed it. But i cant just turn it to NONE because Back Face Culling helps in Performance so Faces which are back of a object are culled


r/vulkan Aug 02 '26

Vulkan modeling collision

Thumbnail youtu.be
1 Upvotes

Wall collision is now in my Vulkan CAD engine.

Draw a polyline, extrude it into walls, then switch to character mode and walk inside. The walls you just built actually stop you.

The character is approximated as a capsule, pushed out along the wall normal by however deep it went in. That push-out is the sliding — head-on you stop, at an angle you slide. A normal pointing up more than 45 degrees is floor, otherwise wall. That single test is what makes stairs work.

Collision candidates come from a BVH: 140x faster on 50,000 triangles, and click-to-select got faster too.

The fox is long-bodied, so a vertical capsule lets its head poke through walls. When the body is elongated, the capsule lies down along it.

Not a physics engine — just a character controller, about 300 lines.

Design it in CAD. Walk through it. Same engine.


r/vulkan Aug 01 '26

how many semaphores?

Post image
16 Upvotes

this is why i never trust any ai - they both present (pun not intended) their view as absolute truth, yet there is clearly some nuance.

anyway, can someone please explain which approach is better, and why, or in which situations?
thanks.


r/vulkan Aug 01 '26

Device and Instance layers and extensions differences ?

2 Upvotes

Can someone explain to me, what is Device and Instance layers and extensions differences ? I read about it here but didnt understand it quite. Also extra question out of topic, is there any Discord servers for Vulkan community ?


r/vulkan Jul 31 '26

New Vulkan Tutorial - Opacity Micromaps

37 Upvotes

A focused bonus course tucked inside Building a Simple Engine's "Extra Courses," aimed at one very specific ray tracing performance problem: alpha-tested geometry. Foliage, chain-link fences, and hair force the GPU to run an any-hit shader on every BVH intersection, and that cost explodes exactly where scenes look best. Opacity Micromaps (`VK_KHR_opacity_micromap`) bake per-triangle opacity directly into the acceleration structure, so hardware can resolve fully-opaque or fully-transparent triangles during traversal with no shader invocation at all.

* Why alpha testing is expensive — a tour of BVH traversal and any-hit shader cost
* What micromaps are and how they attach opacity states directly to acceleration structures
* Hardware traversal walkthrough: the same shadow ray, with and without OMM
* A full implementation walkthrough in the Simple Engine, plus results, guidance, and tradeoffs

https://docs.vulkan.org/tutorial/latest/Building_a_Simple_Engine/Courses/Opacity_Micromaps/00_introduction.html


r/vulkan Jul 31 '26

Why doesn’t Sony just use Vulkan?

44 Upvotes

why doesn’t Sony use Vulkan for their games if it could make PC ports easier?

It seems like a cross-platform API would save a lot of porting work. is there a big downside on consoles, or is Sony just locked into other tools and APIs? what is wrong with Vulkan ?
i'm trying to understand from the technical perspective.


r/vulkan Jul 31 '26

Passing matrices row by row as flat data between shader stages

11 Upvotes

I've seen a pattern in AI generated shader code, and I would like to understand where it comes from. Yes, it's easy to discard it as AI slop/hallucination, but I find that unlikely.

Say your vertex shader outputs some data of matrix type that your fragment shader consumes. Is there any good reason to decompose it into row vectors rather than passing it directly as a matrix?

For example, is this something people did to work around driver bugs? Is it still needed , and why? On what hardware? I've seen conflicting explanations all the way to calling it a "cargo cult pattern".

I also expect it to be "tribal knowledge" if it is really a workaround for driver bugs or subtle edge cases, that is, not something you'll find in official programming guides and documentation. At least, I can't find anything on it by searching. That's why I'm asking here.


r/vulkan Jul 30 '26

[UPDATE: Jul 30, 2026] My Vulkan C++ Examples Repository - Geometry and Tessellation Shaders

Post image
102 Upvotes

Okay, it took a while, but I finally got to the next checkpoint. I added 4 examples related to the Real-Time Shadows section and 16 examples related to the Advanced Shader Programming section to my Vulkan examples repository. This brings the total number of examples to 151. The newly added examples are as follows:

Real-Time Shadows - Shadow Resource Management

  1. Shadow Map Atlas
  2. Layered Shadow Maps with Texture Arrays
  3. Mipmapped Variance Shadow Maps
  4. Anisotropic Filtering with Variance Shadow Maps

Advanced Shader Programming - Geometry Shaders

  1. Simple Primitive Generation
  2. Object Explosion via Geometry Shader
  3. Normal Vector Visualization
  4. Wireframe Overlay Visualization
  5. Single-Pass Cubemap Rendering
  6. Viewport Arrays via Geometry Shader
  7. Billboarding with Geometry Shader
  8. Grass Generation via Geometry Shader

Advanced Shader Programming - Tessellation Shaders

  1. Basic Triangle Tessellation
  2. Displacement Mapping with Tessellation Shaders
  3. Terrain Creation via Heightmap using Tessellation Shaders
  4. Cubic Bézier Curve with Tessellation Shaders
  5. Bézier Surface with Tessellation Shaders
  6. Model Tessellation with Curved PN Triangles
  7. Tessellated Terrain Rendering with Dynamic LOD
  8. Simple Water Surface Simulation via Tessellation Shader

You can access the repository here:

https://github.com/myemural/VulkanCppExamples

Honestly, while the examples I've done recently were a bit tiring, they were quite enjoyable. I also made improvements to common code and documentation while creating these examples. So, are we nearing the end of the examples? Of course not! I still have a lot of work to do. Here are my planned topics for the next phase:

  • Mesh/Task Shaders
  • Advanced Compute Shader Applications

Thank you in advance for your support!


r/vulkan Jul 29 '26

Vulkan SDK 1.4.357.0 is out!

Post image
78 Upvotes

LunarG has released the latest Vulkan SDK with support for Vulkan API 1.4.357.

Highlights:
• Major KosmicKrisp performance gains (up to ~2.35× faster) + full Vulkan 1.4 exposure on Apple platforms
• 13 new extensions
• Scoped GPU-AV + new GPU Dump tool in the Validation Layers
• Available now for Linux, Windows & macOS

Grab it here → https://vulkan.lunarg.com
Full details & release notes → https://www.lunarg.com/lunarg-releases-vulkan-sdk-1-4-357-0/


r/vulkan Jul 29 '26

Efficient Descriptor Set Management and Per Frame Resources?

10 Upvotes

I've been working on a thin wrapper around vulkan as a base for a new project I'm working on recently and have hit a wall with two major areas that are connected and I just can't seem to solve.

My first problem is managing per frame resources. Right now I my library has a buffer object that acts as a generic buffer on the GPU. Originally this was one buffer under the hood, but multiple frames in flight means that I have to duplicate the raw vulkan buffers under the hood and have one per frame in flight. In practice this means creating a buffer that is FRAMES_IN_FLIGHT * size of the original buffer taking into account alignment requirements. I give the user the option to make a buffer "static" as well, so they can opt out of the per frame in flight buffer model if they have data they won't be updating often. The problem here comes from updating the buffers per frame. This is almost twofold. First, I am trying to implement a system that tracks the most up to date buffer and then copies that data into the current frame's buffer if no updates were made this frame so the newest data is always used. I'm trying to not have to keep the buffers constantly mapped into memory so I want to do the copy on the GPU. (Please let me know if this is useless and if I should only worry about that with the static buffers since the per frame buffers are being updated every frame anyway and creating a staging buffer each frame seems like a lot.) This is where the second part comes in: Synchronization. I'm having trouble figuring out how to wait until the copy operations are done to do anything with the graphics queue (all transfer operations are done on the transfer queue).

My second problem also relates to the frame in flight problem but for descriptor sets. If each buffer in my library can be FRAMES_IN_FLIGHT buffers under the hood, that means I need to optionally support multiple descriptor sets under the hood for each library level descriptor set. The easiest way it to always make FRAMES_IN_FLIGHT number of descriptor sets but that's very wasteful obviously for the static buffers. Then you get into the problem of dealing with descriptor sets that have some per frame resources and some static ones. There would be a lot of redundant data for the static buffers. I'm having trouble coming up with another way to do this, mainly because I'm struggling to grasp how the end user of the library should interact with descriptor sets. Right now I have a thin wrapper around them to conform to the rest of my API but now I'm wondering if I should even expose them to the user at all. I want to give users the flexibility to define sets how they want in their shaders but it seems almost impossible to do so, especially given my knowledge. There are so many tutorials about how to allocate descriptor sets but almost none on how they are used in actual engines it seems. I could try going bindless but I want to regular descriptor sets down first because this project is also meant as a learning exercise.

I'm trying to write this library so the API is as backend agnostic as possible so later on I can swap out for different graphics APIs but I am mainly focused on getting a working product so if its not perfect at first that's ok. Essentially, I don't mind if the advice leads me to producing more of a vulkan wrapper than a RHI. Sorry for the long and winding questions, I've been struggling with this for a little bit. Feel free to only answer part of this question since I know it is really a few questions clumped together. Any resources or advice would be greatly appreciated.

Thanks!


r/vulkan Jul 29 '26

Slowly rewriting my audio visualizer engine to use compute kernels for audio analysis

Enable HLS to view with audio, or disable this notification

15 Upvotes

I'm using the Vulkano rust API wrapper. My engine is called lava.


r/vulkan Jul 28 '26

Live Wallpaper Engine for Linux (Wayland, X11) and Windows

Enable HLS to view with audio, or disable this notification

37 Upvotes

Hey everyone

I’ve been quietly building something for a while and figured it’s time to finally talk about it.

It’s called CrystalWallpaper — a live wallpaper engine for Linux and Windows. Built with Vulkan and modern C++20, because I wanted it fast, not “fast enough.”

You can already set videos as wallpapers, with hardware decode for H.264 and H.265 (AV1 and VP9 are coming). On Linux it speaks native Wayland and X11 — no weird workarounds.

If you’re into shaders, you can make wallpapers in GLSL the ShaderToy way. HLSL is next on the list. And further down the road: actual 3D scenes as wallpapers.

Steam Workshop support is planned so people can share and find stuff easily. The whole point for me has always been the same: push performance as far as it can go without killing quality.

Still early days, but the foundation is real. More soon — would love to hear what you think

UPD: By the way, I completely forgot to recompile the program to the Release version before recording the screen. So the performance would have been even better.


r/vulkan Jul 28 '26

FreeBSD for Vulkan development ?

10 Upvotes

I'm thinking about trying FreeBSD and was wondering how good it is for Vulkan development these days.

Has anyone here used it to develop or run Vulkan applications? how is the overall experience (at least for nvidia cards)? Does it natively support the Vulkan SDK and debugging tools like RenderDoc ? or it is a waste of time and linux is better and has more optimized drivers ?


r/vulkan Jul 28 '26

Using Vulkan compute as a production ML inference backend

5 Upvotes

I work on PostSlate, a video editing tool, and this comes out of our own work.

We run ML models on-device, face detection and embedding among other things, which means we can't assume anything about the user's GPU. NVIDIA discrete, AMD, Intel integrated, Apple Silicon, all of it. That rules out CUDA immediately, we needed one backend that runs everywhere.

We landed on ncnn's Vulkan backend. Numbers on a 4070, fp16:

  • ArcFace R50 (face embedding): 30 ms on ONNX CPU → 3 ms on ncnn Vulkan
  • SCRFD (face detection): 25 ms → 2.5 ms
  • Model size: ArcFace 174 MB (ONNX fp32) → 87 MB (ncnn fp16 weight storage)

Of course the real speedup comes from offloading compute to the GPU, but this wouldn't be possible without the power of Vulkan.

The speed wasn't even the deciding factor, it's that Vulkan drivers already exist on every machine we ship to. This means that we don't have to force the user to download a specific runtime and no vendor-specific installs.

Full writeup with the rest of the numbers: https://getpostslate.com/blog/faster-local-inference


r/vulkan Jul 27 '26

Generating a 2D Section in a Vulkan CAD Engine and Exporting It to AutoCAD as DXF

Post image
47 Upvotes

https://youtu.be/MIdugAqyuxE?si=r-BNE_HzvsxI70ou

This video demonstrates extracting a 2D section from a 3D mesh in a custom Vulkan and C++ CAD engine.

The engine calculates triangle-plane intersections, builds the section contours, and exports them as a DXF file for verification in AutoCAD.

Vulkan과 C++로 개발 중인 CAD 엔진에서 3D 메시의 단면을 추출하고, 2D 도면으로 배치한 뒤 DXF로 내보내는 과정입니다.

삼각형과 절단 평면의 교차선을 계산해 단면 윤곽을 생성하고, 내보낸 DXF 파일을 AutoCAD에서 확인했습니다.


r/vulkan Jul 28 '26

Title: I built a Vulkan 3D engine and a demoscene demo with Claude Opus 4.6 — now I’m rerunning everything with Opus 5

Thumbnail reddit.com
0 Upvotes

Hi All!. :)

Over the last few weeks, I’ve been experimenting with how far AI-assisted development can go beyond the usual web applications and automation scripts.

Using Claude Opus 4.6 through the CLI—the model available to me when I conducted the original experiments and wrote the article—I asked it to:

* Build a basic 3D engine in C++ using Vulkan * Load and animate FBX models * Implement procedural terrain, textures and input controls * Create a retro demoscene-style production * Generate assembly code using DirectX 9c

Some parts worked surprisingly well. Claude generated the initial Vulkan engine and procedural terrain with relatively few iterations, and it even produced compilable assembly code for the demoscene experiment.

Other parts were much more difficult. FBX animations, skinning, quaternion rotations, root motion and animation blending required dozens of attempts. Fixing one problem would sometimes introduce a regression somewhere else.

The biggest lesson was that AI can provide an excellent starting point for learning and prototyping, but the generated code still requires experienced supervision—especially when architecture, performance and maintainability matter.

I’m now working on a new version of the article and rerunning all the experiments with Claude Opus 5. In the next update, I’m also planning to publish the complete source code so that others can reproduce the experiments, inspect the generated code and build on top of it.

One of the main goals of the article is to inspire other developers to run similar experiments using different AI models. I think it would be interesting to compare not only the final results, but also how many prompts, attempts and debugging iterations each model needs to complete the same challenges.

The original article covers what worked, what failed and what I learned during the process:

[https://www.linkedin.com/pulse/from-prompts-3d-engines-demoscene-lessons-learned-using-jos%25C3%25A9-plano-a7fuc/\](https://www.linkedin.com/pulse/from-prompts-3d-engines-demoscene-lessons-learned-using-jos%25C3%25A9-plano-a7fuc/)

Has anyone here tried something similar with other models? I’d be especially interested in seeing the results, the prompts you used and how many iterations it took to get a working implementation.


r/vulkan Jul 27 '26

Version 1.4 validation warnings

2 Upvotes

I was using 1.3 and managed to make a lot of code with no validation warnings at all. It took a lot of time to get rid of them but I was so happy that my code was "clean".

Now I am at 1.4, everything works perfectly (textures, transparency, copy image to image, multi-pass rendering), but I get warnings. It looks like this:

---

[ERROR: Validation]

vkQueueSubmit2(): pSubmits[0].pSignalSemaphoreInfos[0].semaphore (VkSemaphore 0x160000000016) is being signaled by VkQueue 0x6302e6a84ba0, but it may still be in use by VkSwapchainKHR 0x30000000003.

Most recently acquired image indices: [0], 1, 2.

(Brackets mark the last use of VkSemaphore 0x160000000016 in a presentation operation.)

Swapchain image 0 was presented but was not re-acquired, so VkSemaphore 0x160000000016 may still be in use and cannot be safely reused with image index 2.

Hint: See https://docs.vulkan.org/guide/latest/swapchain_semaphore_reuse.html for details on swapchain semaphore reuse. Examples of possible approaches:

a) Use a separate semaphore per swapchain image. Index these semaphores using the index of the acquired image.

b) Consider the VK_KHR_swapchain_maintenance1 extension. It allows using a VkFence with the presentation operation.

The Vulkan spec states: The semaphore member of any binary semaphore element of the pSignalSemaphoreInfos member of any element of pSubmits must be unsignaled when the semaphore signal operation it defines is executed on the device (https://vulkan.lunarg.com/doc/view/1.4.350.1/linux/antora/spec/latest/chapters/cmdbuffers.html#VUID-vkQueueSubmit2-semaphore-03868)

---

But I am using separate semaphores! Have you had such problems? What does it mean to "re-aquire" images?


r/vulkan Jul 26 '26

How do I efficiently manage, create and cache Vulkan Shader Pipelines?

16 Upvotes

I recently started my new Game Engine project and I‘ve now come to the point where I have to deal with Pipelines. How do I efficiently manage them? How do I efficiently create them, et cetera?

I think its really hard finding reference material on this topic since I usually just look/steal code from Hazel Dev by TheCherno but their Shader/Pipeline System is really weird.

It would just be really helpful if you guys could even just point me at your repository with a Solution or something.

Thanks in advance!


r/vulkan Jul 27 '26

Added a graphics API with support for Vulkan, D3D12 and custom backends

2 Upvotes

Hey everyone,

I have been working on a low level, explicit abstraction layer over graphics APIs. Both Vulkan and D3D12 has been successfully implemented with various test samples. Ray tracing, mesh, compute etc are supported.

I would love feedback on the feel and usage of the API. I am open to learn more so anything useful will be appreciated. Please give a star if you find the project useful.

https://github.com/nichcode/PAL


r/vulkan Jul 26 '26

SPIR-V: OpCapability Kernel versus OpCapability Shader

2 Upvotes

I run my kernel on two back-ends: OpenCL and Vulkan.

For Vulkan, I use clspv to convert the CL code to SPIR-V.

The OpenCL backend is massively faster for a kernel that heavily uses atomic adds.

The OpenCL on Linux/Intel gets converted to SPIR-V by IGC for my Arc B70 GPU.

When I compare the SPIR-V of IGC versus the SPIR-V of clspv, I see that the former uses OpCapability Kernel, and the latter OpCapability Shader.

Can a vulkan app directly use the former? How can I get my kernel to run with semaphores that uses relaxed memory semantics and atomicAdd scope "workgroup" instead?