How to Vulkan in 2026

repository·main·Indexed 20 days ago

https://github.com/saschawillems/howtovulkan

A minimalist, single-day tutorial designed to teach Vulkan rasterization using modern, widely supported features to reduce API complexity for beginners. The project includes C++ implementation examples, raw markdown documentation, and professional tips based on industry experience. It covers Vulkan 1.3 features such as dynamic rendering, synchronization2, and descriptor indexing, as well as integration with SDL, Volk, and the Vulkan Memory Allocator (VMA).

Tokens
4.6K
Snippets
6
Records
15
Agent score
69%

What's inside howtovulkan

  1. Understand the libKTX licensing model

    main

    The libKTX source is primarily licensed under the Apache License, Version 2.0. However, there are several specific exceptions for included third-party components. When using or distributing derivative works of this project, you must comply with the Apache 2.0 license while also respecting the specific licenses for the following files/modules:

    • etcdec.cxx: Ericsson Software License Agreement (SLA)
    • uthash.h: Revised BSD License
    • other_include/SDL2/*: zlib license
    • other_include/glm: Happy Bunny (Modified MIT) License
    • {VulkanMeshLoader,vulkantextoverlay}.hpp, vulkandebug.*: MIT License

    Note: In the event of a discrepancy between this LICENSE.md file and the individual license files located within the source, the licenses in the individual files shall be deemed correct.

  2. Access the How to Vulkan in 2026 tutorial

    main

    The 'How to Vulkan in 2026' project provides a minimalist, single-day tutorial designed to teach Vulkan rasterization using modern, commonly supported features. It aims to simplify the Vulkan API entry point while providing professional tips and warnings based on long-term industry experience.

    To use this project, you can access the content in three ways:

    • Web Version: The full interactive tutorial is hosted at www.howtovulkan.com.
    • Source Code: C++ implementation examples are located in the /source directory.
    • Tutorial Text: The raw markdown documentation for the tutorial is located in /tutorial/docs/index.md.
  3. Expand $Date$ keywords in KTX source files

    main

    The KTX repository uses $Date$ keywords that are expanded via a smudge & clean filter. If you need proper dates shown in files or are generating documentation/archives, you must install the filter using the following platform-specific commands in the root of your clone.

    Note: The first command adds an include of the repo's .gitconfig to your local .git/config. The subsequent commands force a new checkout of specific files to apply the date smudging. These steps are unnecessary if you only intend to edit the files without caring about the date expansion.

    ### On Unix (Linux, Mac OS X, etc.) or Git Bash/Cygwin:
    ```bash
    ./install-gitconfig.sh
    rm TODO.md include/ktx.h tools/toktx/toktx.cpp
    git checkout TODO.md include/ktx.h tools/toktx/toktx.cpp

    On Windows (Command Prompt):

    install-gitconfig.bat
    del TODO.md include/ktx.h tools/toktx/toktx.cpp
    git checkout TODO.md include/ktx.h tools/toktx/toktx.cpp
  4. Data structures for shader data and textures

    main

    The application uses several structures to manage GPU-related data.

    • ShaderData: Contains uniform data sent to shaders, including projection and view matrices, an array of 3 model matrices, a light position (glm::vec4), and a selected index.
    • ShaderDataBuffer: Manages the lifecycle of a buffer containing ShaderData, including its VmaAllocation, VkBuffer handle, and its VkDeviceAddress for GPU-side pointer access.
    • Texture: Encapsulates a texture resource, including its VmaAllocation, VkImage, VkImageView, and VkSampler.
    • Vertex: Defines the layout for vertex data, consisting of pos (glm::vec3), normal (glm::vec3), and uv (glm::vec2).
  5. Use Descriptor Indexing with Variable Descriptor Counts

    main

    To support a dynamic number of textures in a single descriptor set (e.g., for bindless rendering), use the VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT flag.

    Workflow:

    1. Create a VkDescriptorSetLayout with VkDescriptorSetLayoutBindingFlagsCreateInfo passed via pNext to define the variable count flag.
    2. Create a VkDescriptorPool with enough capacity.
    3. When allocating the descriptor set, use VkDescriptorSetVariableDescriptorCountAllocateInfo (via pNext in VkDescriptorSetAllocateInfo) to specify the actual number of descriptors needed.
    4. Update the set using vkUpdateDescriptorSets.
    // 1. Define binding flags
    VkDescriptorBindingFlags descVariableFlag{ VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT };
    VkDescriptorSetLayoutBindingFlagsCreateInfo descBindingFlags{ 
        .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO, 
        .bindingCount = 1, 
        .pBindingFlags = &descVariableFlag 
    };
    
    // 2. Create Layout
    VkDescriptorSetLayoutCreateInfo descLayoutTexCI{ 
        .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, 
        .pNext = &descBindingFlags, 
        .bindingCount = 1, 
        .pBindings = &descLayoutBindingTex 
    };
    chk(vkCreateDescriptorSetLayout(device, &descLayoutTexCI, nullptr, &descriptorSetLayoutTex));
    
    // 3. Allocate with variable count
    uint32_t variableDescCount{ static_cast<uint32_t>(textures.size()) };
    VkDescriptorSetVariableDescriptorCountAllocateInfo variableDescCountAI{ 
        .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO_EXT, 
        .descriptorSetCount = 1, 
        .pDescriptorCounts = &variableDescCount 
    };
    VkDescriptorSetAllocateInfo texDescSetAlloc{ 
        .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, 
        .pNext = &variableDescCountAI, 
        .descriptorPool = descriptorPool, 
        .descriptorSetCount = 1, 
        .pSetLayouts = &descriptorSetLayoutTex 
    };
    chk(vkAllocateDescriptorSets(device, &texDescSetAlloc, &descriptorSetTex));
  6. Handle Swapchain Resizing

    main

    When the window is resized (detected via SDL_EVENT_WINDOW_RESIZED), you must recreate the swapchain and associated resources to match the new window dimensions:

    1. Wait for the device to be idle: vkDeviceWaitIdle(device).
    2. Create a new swapchain using the oldSwapchain field in VkSwapchainCreateInfoKHR to allow for efficient transition.
    3. Recreate all VkImageView objects for the new swapchain images.
    4. Recreate the depth buffer (image and image view) with the new extent.
    5. Recreate any per-image synchronization primitives (like renderCompleteSemaphores) if the number of swapchain images changed.
    if (updateSwapchain) {
        chk(SDL_GetWindowSize(window, &windowSize.x, &windowSize.y));
        updateSwapchain = false;
        chk(vkDeviceWaitIdle(device));
        
        // Recreate swapchain using oldSwapchain
        swapchainCI.oldSwapchain = swapchain;
        swapchainCI.imageExtent = { .width = static_cast<uint32_t>(windowSize.x), .height = static_cast<uint32_t>(windowSize.y)};
        chk(vkCreateSwapchainKHR(device, &swapchainCI, nullptr, &swapchain));
    
        // ... Recreate Image Views, Depth Image, and Depth Image View ...
    
        vkDestroySwapchainKHR(deviceCI.oldSwapchain, nullptr);
    }
  7. Initialize Vulkan with SDL and Volk

    main

    To set up a Vulkan environment using SDL and Volk (a Vulkan loader), follow these steps:

    1. Initialize SDL video subsystem: SDL_Init(SDL_INIT_VIDEO).
    2. Load the Vulkan library via SDL: SDL_Vulkan_LoadLibrary(NULL).
    3. Initialize Volk: volkInitialize().
    4. Create a VkInstance using vkCreateInstance. Ensure you query instance extensions via SDL_Vulkan_GetInstanceExtensions to support the windowing system.
    5. Load instance-specific function pointers using volkLoadInstance(instance).

    Note: Ensure an assets folder exists in the current working directory before starting.

    // Initialization sequence
    chk(SDL_Init(SDL_INIT_VIDEO));
    chk(SDL_Vulkan_LoadLibrary(NULL));
    volkInitialize();
    
    // Instance creation
    VkApplicationInfo appInfo{ .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, .pApplicationName = "How to Vulkan", .apiVersion = VK_API_VERSION_1_3 };
    uint32_t instanceExtensionsCount{ 0 };
    char const* const* instanceExtensions{ SDL_Vulkan_GetInstanceExtensions(&instanceExtensionsCount) };
    VkInstanceCreateInfo instanceCI{ 
        .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, 
        .pApplicationInfo = &appInfo, 
        .enabledExtensionCount = instanceExtensionsCount, 
        .ppEnabledExtensionNames = instanceExtensions 
    };
    chk(vkCreateInstance(&instanceCI, nullptr, &instance));
    volkLoadInstance(instance);
  8. License terms for uthash.h

    main

    The file uthash.h is provided under a revised BSD license.

    Requirements:

    • Redistributions of source code must retain the original copyright notice (Copyright © 2003-2010, Troy D. Hanson), this list of conditions, and the disclaimer.

    Disclaimer: THE SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR ANY IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.

  9. License terms for KTX application and document icons

    main

    The KTX application and document icons (found in icons/{ios/CommonIcons*,mac,win}/ktx_{app,document}.*) are copyrighted by The Khronos Group, Inc.

    Usage Exception: The ktx_app icon may be distributed in a Derivative Work specifically as the icon for the glloadtests and vkloadtests applications. All other uses require specific prior written permission from The Khronos Group.

  10. License terms for etcdec.cxx (Ericsson Texture Compression)

    main

    The file etcdec.cxx is governed by a specific Software License Agreement (SLA) from Ericsson.

    Key Usage Terms:

    • Permitted Use: You are granted a non-exclusive, non-transferable, limited, free-of-charge, perpetual, and worldwide license to copy, use, distribute, and modify the software for the purpose of developing, manufacturing, selling, using, and distributing products in binary form. These products must use the software for compression and/or decompression according to Khronos standard specifications (OpenGL, OpenGL ES, and WebGL).
    • Source Code Distribution: You may distribute etcdec.cxx in source code form only if it is unmodified and included in software owned by you.
    • Patent Litigation Restriction: If you institute or threaten patent litigation against Ericsson or its affiliates regarding the Khronos framework or related intellectual property, Ericsson has the right to terminate this SLA immediately.
    • Prohibited Use: The software is NOT licensed or intended for mission-critical applications (e.g., nuclear, healthcare, aircraft, or train control systems) where failure could lead to death, personal injury, or severe environmental damage.
  11. License terms for test images (HI logo)

    main

    The HI logo textures (testimages/hi_mark{,_sq}.ktx) are copyrighted by HI Corporation.

    Usage Restrictions:

    • They are provided solely for use in testing the KTX loader.
    • Any other use requires specific prior written permission from HI.
    • The name "HI" may not be used to endorse or promote products derived from this software without specific prior written permission.