Vulkan
An explicit, low-level cross-vendor API for graphics and compute. Compute shaders are written in GLSL (or HLSL), compiled ahead of time to SPIR-V, and run on every modern GPU from NVIDIA, AMD, Intel and, via MoltenVK, Apple. Verbose, but it gives you total control and portability, which is why most new engines target it.
KhronosC/C++ · GLSL → SPIR-Vcross-vendoropen standardlow-level
Install
# Install the LunarG Vulkan SDK (glslc, validation layers, headers)
# Linux (Ubuntu):
wget -qO- https://packages.lunarg.com/lunarg-signing-key-pub.asc | sudo tee /etc/apt/trusted.gpg.d/lunarg.asc
sudo wget -qO /etc/apt/sources.list.d/lunarg-vulkan.list https://packages.lunarg.com/vulkan/lunarg-vulkan-jammy.list
sudo apt-get update && sudo apt-get install -y vulkan-sdk
vulkaninfo | head # verify a device is visible
Hello, GPU
double.comp: a Vulkan compute shader (GLSL, compiled to SPIR-V)
// double.comp: GLSL compute shader
#version 450
layout(local_size_x = 64) in;
layout(std430, binding = 0) buffer Data { float v[]; };
void main() {
uint i = gl_GlobalInvocationID.x;
v[i] = v[i] * 2.0;
}
/* Host (C/C++ with the Vulkan API, abbreviated):
vkCreateInstance / pick a VkPhysicalDevice / vkCreateDevice (a compute queue)
load double.spv -> vkCreateShaderModule
VkDescriptorSetLayout (one storage buffer) -> VkPipelineLayout
vkCreateComputePipelines(..., stage = double.spv, "main")
vkCreateBuffer + vkAllocateMemory (HOST_VISIBLE) -> upload the array
vkUpdateDescriptorSets -> bind the buffer at binding 0
vkCmdBindPipeline / vkCmdBindDescriptorSets
vkCmdDispatch(n / 64, 1, 1) -> vkQueueSubmit -> vkQueueWaitIdle
map the memory back: the array is now doubled */
Run it:
glslc double.comp -o double.spv # then dispatch it from the host program above