Skip to content

Vulkan Introduction — Modern Graphics API

DodaTech Updated 2026-06-21 6 min read

In this tutorial, you'll learn about Vulkan Introduction. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.

Vulkan is a low-overhead, cross-platform graphics and compute API that gives developers explicit control over GPU resource management, command submission, and memory allocation for maximum performance.

What You'll Learn & Why It Matters

In this tutorial, you will learn the Vulkan API architecture — how to create a Vulkan instance, select a physical device, set up a logical device and swapchain, create render passes and pipelines, and record command buffers. Vulkan's explicit design lets you achieve near-metal performance.

Real-world use: AAA games, CAD software, and DodaTech's GPU-accelerated antivirus scanning use Vulkan for low-latency graphics and compute workloads.

Prerequisites

  • OpenGL Basics tutorial (previous)
  • C++ knowledge
  • Understanding of the Rendering Pipeline
  • Vulkan SDK installed

Learning Path

flowchart LR
  A[OpenGL Basics] --> B[Vulkan Introduction]
  B --> C[Shader Programming]
  B --> D[Compute Shaders]
  B --> E[GPU Architecture]
  C --> F[Ray Tracing]
  D --> G[Post-Processing]
  B:::current

  classDef current fill:#f90,color:#fff,stroke:#333,stroke-width:2px

Vulkan vs OpenGL

Vulkan is not just a newer OpenGL. It represents a fundamentally different design philosophy:

Aspect OpenGL Vulkan
Driver overhead High Minimal
Error checking Runtime Validation layers
Memory management Automatic Explicit
Multi-threading Limited First-class
Pipeline state Monolithic Programmatic
Shader format GLSL source SPIR-V binary

The cost of this explicit control is more code. Drawing a triangle in OpenGL takes ~200 lines. In Vulkan, it takes ~2000 lines. The benefit is predictable performance and no driver surprises.

Initializing Vulkan

Every Vulkan application starts by creating an instance, which stores application-wide state.

#include <vulkan/vulkan.h>
#include <iostream>

int main()
{
    VkApplicationInfo appInfo{};
    appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
    appInfo.pApplicationName = "Vulkan Triangle";
    appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
    appInfo.pEngineName = "DodaTech Engine";
    appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
    appInfo.apiVersion = VK_API_VERSION_1_3;

    VkInstanceCreateInfo createInfo{};
    createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
    createInfo.pApplicationInfo = &appInfo;

    VkInstance instance;
    VkResult result = vkCreateInstance(&createInfo, nullptr, &instance);
    
    if (result == VK_SUCCESS)
        std::cout << "Vulkan instance created" << std::endl;
    else
        std::cerr << "Failed to create Vulkan instance" << std::endl;

    vkDestroyInstance(instance, nullptr);
    return 0;
}

Required Extensions and Validation Layers

Real applications enable validation layers during development for debugging:

const std::vector<const char*> validationLayers = {
    "VK_LAYER_KHRONOS_validation"
};

VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo{};
debugCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
debugCreateInfo.messageSeverity =
    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 = debugCallback;

Device Selection

Vulkan requires explicit GPU selection. You query available physical devices and pick one that supports your needs.

uint32_t deviceCount = 0;
vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr);
std::vector<VkPhysicalDevice> devices(deviceCount);
vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data());

for (const auto& device : devices)
{
    VkPhysicalDeviceProperties props;
    vkGetPhysicalDeviceProperties(device, &props);
    if (props.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
        std::cout << "Found discrete GPU: " << props.deviceName << std::endl;
}
flowchart TD
  A[Vulkan Instance] --> B[Physical Device Selection]
  B --> C[Logical Device]
  C --> D[Queue Families]
  D --> E[Swapchain]
  E --> F[Render Pass & Pipeline]
  F --> G[Command Buffers]
  G --> H[Submit & Present]

Swapchain and Presentation

The swapchain manages the image queue that will be displayed on screen.

VkSwapchainCreateInfoKHR swapchainInfo{};
swapchainInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
swapchainInfo.surface = surface;
swapchainInfo.minImageCount = 2;  // Double buffering
swapchainInfo.imageFormat = VK_FORMAT_B8G8R8A8_SRGB;
swapchainInfo.imageColorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
swapchainInfo.imageExtent = {800, 600};
swapchainInfo.imageArrayLayers = 1;
swapchainInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;

VkSwapchainKHR swapchain;
vkCreateSwapchainKHR(device, &swapchainInfo, nullptr, &swapchain);

Render Pass and Pipeline

The render pass describes the framebuffer attachments. The pipeline describes the shaders and fixed-function state.

VkPipelineShaderStageCreateInfo vertStage{};
vertStage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
vertStage.stage = VK_SHADER_STAGE_VERTEX_BIT;
vertStage.module = vertModule;
vertStage.pName = "main";

VkPipelineShaderStageCreateInfo fragStage{};
fragStage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
fragStage.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
fragStage.module = fragModule;
fragStage.pName = "main";

Command Buffers

Vulkan requires explicit command recording and submission. You allocate a command buffer, record commands into it, then submit it to a queue.

VkCommandBufferAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
allocInfo.commandPool = commandPool;
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
allocInfo.commandBufferCount = 1;

VkCommandBuffer commandBuffer;
vkAllocateCommandBuffers(device, &allocInfo, &commandBuffer);

VkCommandBufferBeginInfo beginInfo{};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;

vkBeginCommandBuffer(commandBuffer, &beginInfo);
vkCmdDraw(commandBuffer, 3, 1, 0, 0);
vkEndCommandBuffer(commandBuffer);

Fences and Semaphores

Synchronization in Vulkan is explicit. Fences synchronize CPU with GPU. Semaphores synchronize GPU operations.

VkSubmitInfo submitInfo{};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &commandBuffer;

VkFence fence;
VkFenceCreateInfo fenceInfo{};
fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
vkCreateFence(device, &fenceInfo, nullptr, &fence);

vkQueueSubmit(graphicsQueue, 1, &submitInfo, fence);
vkWaitForFences(device, 1, &fence, VK_TRUE, UINT64_MAX);

Common Errors & Mistakes

1. Missing Validation Layers

Mistake: Not enabling validation layers during development, then getting crashes without error messages.

Fix: Always enable VK_LAYER_KHRONOS_validation during development. Install the Vulkan SDK which includes validation layers.

2. Forgetting to Destroy Resources

Mistake: Creating Vulkan objects without destroying them, causing memory leaks.

Fix: Vulkan does not track resources. Destroy everything you create in reverse order of creation using vkDestroy* functions.

3. Incorrect Queue Family Indices

Mistake: Assuming all queue families are the same, causing presentation or compute errors.

Fix: Query vkGetPhysicalDeviceQueueFamilyProperties and check for VK_QUEUE_GRAPHICS_BIT or VK_QUEUE_COMPUTE_BIT flags.

4. Buffer and Image Transitions

Mistake: Reading from an image before a write operation has completed.

Fix: Use pipeline barriers to transition image layouts explicitly. Every image layout change requires a barrier.

Practice Questions

Question 1

What is the main advantage of Vulkan over OpenGL?

Show answer Vulkan offers lower driver overhead, explicit GPU control, better multi-threading support, and predictable performance. The driver does almost nothing behind your back.

Question 2

What is a VkFence used for?

Show answer A fence synchronizes CPU and GPU operations. The CPU can wait on a fence to know when GPU work has completed, preventing the CPU from reading data the GPU is still writing.

Question 3

Why does Vulkan use SPIR-V instead of GLSL?

Show answer SPIR-V is a binary intermediate language that compilers can target from multiple source languages (GLSL, HLSL, Slang). This avoids runtime shader compilation and enables offline optimization.

Question 4

What is the swapchain and why is it needed?

Show answer The swapchain manages the queue of images that get presented to the screen. It handles double or triple buffering and synchronizes rendering with the display refresh rate.

Challenge

Implement a Vulkan application that renders a rotating colored triangle with proper synchronization, validation layers, and clean resource cleanup. Use at least two framebuffers.

FAQ

Do I need a specific GPU for Vulkan?

Vulkan runs on any GPU that supports it, including NVIDIA, AMD, Intel, and Apple Silicon (via MoltenVK). Most GPUs from 2015 onward support Vulkan 1.2 or later.

Is Vulkan harder than OpenGL?

Vulkan requires significantly more boilerplate code. Drawing one triangle in Vulkan is a ~2000-line program. However, the concepts are not harder to understand — there are just more explicit steps.

Can I mix Vulkan with other APIs?

Generally no. Vulkan and OpenGL cannot share resources directly on most platforms. You can use interop extensions like VK_KHR_external_memory_fd for cross-API sharing.

Is Vulkan good for compute workloads?

Yes, Vulkan compute shaders are excellent for GPGPU tasks. Many applications use Vulkan specifically for compute, not graphics, due to its low overhead and explicit control.


Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro.

Author: DodaTech | Last updated: June 21, 2026

DodaTech tutorials are built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro — security tools used by millions worldwide.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro