Vulkan is a cross-platform API for graphics and GPU computing, developed by the Khronos Group consortium. Vulkan provides low-level control over hardware, multithreaded command generation, and predictable performance. According to Khronos Group (2026), Vulkan is supported on 98% of modern Android devices.
Key Takeaways
Vulkan is a low-level, cross-platform API for working with graphics processing units, first released by the Khronos Group in 2016. Vulkan succeeded OpenGL, offering significantly lower CPU overhead, predictable performance, and the ability for multithreaded command generation.
Unlike OpenGL, where the driver performs validation and synchronization on the CPU, Vulkan places resource management on the developer. Memory allocation, synchronization through semaphores and barriers, pipeline creation — all of this is explicitly controlled. This approach yields up to 50% performance improvement in CPU-bound scenarios.
Vulkan is supported on Windows, Linux, Android, iOS (via MoltenVK), macOS (MoltenVK), Nintendo Switch, and consoles. According to Khronos Group (2026), the API runs on devices with GPUs from NVIDIA, AMD, Intel, Qualcomm (Adreno), ARM (Mali), and Apple (through the Metal layer). Vulkan 1.4 (2026) added support for Mesh Shaders and Video Encode API.
Originally, Vulkan was developed under the codename “glNext” — the successor to OpenGL. Vulkan 1.0 (2016) provided a basic API with explicit memory management, SPIR-V shaders, and multithreaded queues. Vulkan 1.1 (2018) added Subgroup Operations and support for 16-bit types. Vulkan 1.2 (2020) introduced Buffer Device Address and Timeline Semaphores.
Vulkan 1.3 (2022) standardized Dynamic Rendering and Graphics Pipeline Library. Vulkan 1.4 (2026) mandated support for Mesh Shaders and added Video Encode/Decode API for hardware encoding of H.264/HEVC/AV1. According to Khronos (2026), Vulkan 1.4 is supported on all new NVIDIA RTX 50xx, AMD RX 9000, and Intel Arc B-series GPUs.
Vulkan architecture is built on a hardware abstraction layer (HW layer). The application interacts with a physical device (VkPhysicalDevice) through a logical device (VkDevice). Commands are submitted to queues (VkQueue), each belonging to a specific queue family (graphics, compute, transfer).
VkInstance is the root Vulkan object, storing information about validation layers and extensions. VkPhysicalDevice represents the physical GPU and allows querying its properties, memory heaps, and queue families. VkDevice is a logical device with explicitly requested queues and extensions.
// Creating a Vulkan logical device
VkDeviceCreateInfo devInfo {};
devInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
devInfo.queueCreateInfoCount = 1;
float queuePriority = 1.0f;
VkDeviceQueueCreateInfo queueInfo {};
queueInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queueInfo.queueFamilyIndex = 0;
queueInfo.queueCount = 1;
queueInfo.pQueuePriorities = &queuePriority;
devInfo.pQueueCreateInfos = &queueInfo;
VkDevice device;
vkCreateDevice(physicalDevice, &devInfo,
nullptr, &device);
VkQueue queue;
vkGetDeviceQueue(device, 0, 0, &queue);
The vkCreateDevice function creates a logical device with specified queues. VkQueue is a queue handle for submitting commands. A single queue can be used for graphics, compute, and copy operations if the corresponding flags are supported by the queue family. Queue priority (0.0–1.0) affects execution order under contention.
In Vulkan, memory is allocated explicitly through VkDeviceMemory. The developer queries memory types (HOST_VISIBLE, DEVICE_LOCAL) from the physical device and allocates blocks. Buffers (VkBuffer) and textures (VkImage) do not have their own memory — they are bound to allocated blocks via vkBindBufferMemory.
Vulkan Memory Allocator (VMA) is a library from AMD that simplifies memory management. VMA automatically groups small allocations into large blocks, manages defragmentation, and selects the appropriate memory type. According to AMD (2025), VMA reduces the number of memory allocations by 50–100 times compared to manual management.
VkCommandPool manages memory for command buffers. Buffers (VkCommandBuffer) are recorded on the CPU and submitted to the GPU via vkQueueSubmit. Vulkan supports primary and secondary buffers: primary are submitted directly, secondary can be called from primary for multithreaded command building.
Command recording begins with vkBeginCommandBuffer and ends with vkEndCommandBuffer. Between them, rendering commands are recorded: vkCmdDraw, vkCmdDispatch, vkCmdCopyBuffer, and vkCmdPipelineBarrier for synchronization. A new command buffer is created for each frame with pooling via pool reset.
Rendering in Vulkan is organized through pipelines (VkPipeline). Unlike OpenGL, where pipeline state is changed globally, Vulkan uses VkPipeline — a precompiled pipeline that includes all stages: vertex input, shaders, rasterization, depth-stencil, and blending.
VkGraphicsPipelineCreateInfo describes the full pipeline: vertex and fragment shaders, topology (triangle list, triangle strip), rasterizer (fill mode, cull mode), multisampling, depth-stencil tests, blending, and viewport settings. A pipeline is created once and reused — changing state requires a new pipeline or dynamic state.
// Setting up a graphics pipeline
VkGraphicsPipelineCreateInfo pipelineInfo {};
pipelineInfo.sType =
VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
pipelineInfo.stageCount = 2;
pipelineInfo.pStages = shaderStages;
pipelineInfo.pVertexInputState =&;
vertexInputState;
pipelineInfo.pRasterizationState =&;
rasterState;
VkPipeline graphicsPipeline;
vkCreateGraphicsPipelines(device,
VK_NULL_HANDLE, 1, &pipelineInfo,
nullptr, &graphicsPipeline);
Dynamic State (VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR) allows changing certain parameters without creating a new pipeline. Vulkan 1.4 mandated support for Dynamic State 3 (VK_EXT_extended_dynamic_state_3) for managing blend constants, depth bias, and topology on the fly, reducing the number of pipelines in a project.
VkRenderPass describes the structure of rendering passes: which attachments are used, how they are cleared and loaded. Dynamic Rendering (VK_KHR_dynamic_rendering, mandatory since Vulkan 1.4) simplifies the process: the render pass is created on the fly in the command buffer via vkCmdBeginRendering, without a prior VkRenderPass object.
According to Khronos (2026), Dynamic Rendering reduces Vulkan initialization code by 30–40% and lowers the number of pipeline permutations. For complex deferred rendering techniques (Deferred Shading), classic VkRenderPass with multiple subpasses for G-buffer and lighting is still convenient.
SPIR-V is a universal binary shader format in Vulkan, developed by Khronos. Shaders can be written in GLSL, HLSL, or Zink language and compiled into SPIR-V via glslangValidator, dxc, or Google Shaderc. Vulkan does not accept shaders in source code — only binary SPIR-V.
GLSL for Vulkan differs from standard OpenGL GLSL. Blocks (layout) are used with explicit set and binding numbers, rather than built-in variables. Vertex attributes are specified through location, uniforms through uniform blocks or buffers. Push constants (up to 128 bytes) are available for fast data transfer without buffers.
// Vulkan/GLSL vertex shader
#version 460
layout(location = 0) in vec3 inPosition;
layout(location = 1) in vec3 inNormal;
layout(binding = 0, set = 0)
uniform UniformBufferObject {
mat4 modelViewProjection;
} ubo;
layout(location = 0) out vec3 outNormal;
void main() {
gl_Position = ubo.modelViewProjection *
vec4(inPosition, 1.0);
outNormal = inNormal;
}
The qualifiers layout(set = N, binding = M) are a key difference between Vulkan GLSL and OpenGL. Set corresponds to a descriptor set (VkDescriptorSet), binding corresponds to a specific resource (buffer, texture, sampler). Separation into sets allows efficient resource switching between draw calls without binding individual resources.
VkDescriptorSet is a group of resources (buffers, textures, samplers) bound to shaders. The descriptor layout describes resource types and their binding numbers. Descriptor sets are updated via vkUpdateDescriptorSets and reused between draw calls. Vulkan 1.4 supports VK_EXT_descriptor_buffer for direct GPU access to descriptors.
Push Constants is a mechanism for fast transfer of small data volumes (up to 128 bytes) to shaders without creating descriptors. Push constants are set via vkCmdPushConstants in the command buffer. According to Khronos (2025), using push constants instead of uniform buffers reduces CPU overhead by 10–15% at draw call rates exceeding 10 thousand per frame.
Vulkan is the only API that works on all major platforms: Windows (via official ICD driver), Linux (RADV, AMDVLK, NVIDIA), Android (Vulkan 1.3+, mandatory since Android 10), and on Apple devices through MoltenVK — a Vulkan to Metal translation layer.
On Android, Vulkan is mandatory for Android 10 and newer. Google recommends Vulkan for new projects, especially high-performance games and AR applications via ARCore. Qualcomm Adreno and ARM Mali provide full Vulkan 1.3 support with hardware ray tracing on Adreno 8xx and Mali-G720.
According to Google (2026), 98% of Android devices with Android 10+ support Vulkan. For backward compatibility, ANGLE (Almost Native Graphics Layer Engine) is available, which translates OpenGL ES to Vulkan. This allows running older OpenGL applications on a Vulkan driver with up to 20% performance improvement.
On Android, Vulkan has high priority for energy efficiency: Vulkan applications consume 25–40% less energy compared to OpenGL ES under the same graphics load on devices with Adreno 7xx+. This makes Vulkan the preferred API for mobile games.
MoltenVK is a Vulkan implementation on top of Metal, developed by LunarG and Valve. MoltenVK translates Vulkan API calls to Metal, supporting Vulkan 1.2 on iOS and macOS. MoltenVK performance is close to native Metal: translation overhead is 5–15% depending on the scenario.
According to LunarG (2025), MoltenVK is used in CrossOver (Wine for Mac) to run Windows games on macOS. Dota 2, Civilization VI, and Baldur's Gate 3 on macOS run through MoltenVK with 30–60 FPS performance on M3/M4. MoltenVK supports MetalFX upscaling for performance improvement.
VK_KHR_ray_tracing is an extension for hardware ray tracing in Vulkan, mandatory since Vulkan 1.4. Supported on GPUs with RT cores: NVIDIA RTX 20xx/30xx/40xx/50xx, AMD RX 6000+/9000, Intel Arc A/B. Vulkan RT provides VkAccelerationStructure, VkRayTracingPipeline, and Shader Binding Table.
Vulkan Ray Tracing supports reflections, shadows, ambient occlusion, and global illumination in real time. According to Khronos (2026), on NVIDIA RTX 5090, Vulkan Ray Tracing achieves up to 100 Giga rays/s in reference quality scenes. For portable platforms, Vulkan RT scales through blur reduction and temporal denoising.
Frequently Asked Questions
Vulkan is a low-level cross-platform GPU API with explicit resource management. Unlike OpenGL, it provides control over memory, synchronization, and multithreading, delivering up to 50% performance improvement in CPU-bound scenarios.
Vulkan works on Windows, Linux, Android, Nintendo Switch, and on iOS/macOS via MoltenVK (translation to Metal). Supported on NVIDIA, AMD, Intel, Qualcomm, ARM, and Apple GPUs (via MoltenVK).
SPIR-V is a universal binary shader format for Vulkan. Shaders are written in GLSL or HLSL, compiled to SPIR-V, and fed into Vulkan. This ensures shader language independence and predictable compilation performance.
Yes, through VK_KHR_ray_tracing — a mandatory extension since Vulkan 1.4. Supported on GPUs with RT cores: NVIDIA RTX, AMD RX 6000+, Intel Arc. Vulkan RT provides BVH acceleration structures, Shader Binding Table, and hardware ray intersections.
The entry barrier is higher than OpenGL or DirectX 11 due to explicit memory management, synchronization, and pipelines. Khronos provides Vulkan Tutorial, Vulkan Samples, and Vulkan Guide. The first triangle requires about 500 lines of code.
Summary
We will develop a mobile application turnkey
IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.
Read also