A Zig library to help with Vulkan initialization inspired by vk-bootstrap
The minimum required version is Vulkan 1.1
This library helps with:
- Instance creation
- Setting up debug environment (validation layers and debug messenger)
- Physical device selection based on a set of criteria
- Enabling physical device extensions
- Device creation
- Swapchain creation
- Getting queues
Add vulkan-zig
as a dependency to your build.zig.zon:
zig fetch --save=vulkan_zig "https://github.com/Snektron/vulkan-zig/archive/<COMMIT_HASH>.tar.gz"
Use the same version as vk-kickstart for the commit hash. See build.zig.zon
Then add vk-kickstart:
zig fetch --save https://github.com/Mikastiv/vk-kickstart/archive/<COMMIT_HASH>.tar.gz
Then update your build file with the following:
// Provide the path to the Vulkan registry (requires version >= 1.3.277)
const xml_path: []const u8 = b.pathFromRoot("vk.xml");
// Add the vulkan-zig module
const vkzig_dep = b.dependency("vulkan_zig", .{
.registry = xml_path,
});
exe.root_module.addImport("vulkan", vkzig_dep.module("vulkan-zig"));
// Add vk-kickstart
const kickstart_dep = b.dependency("vk_kickstart", .{
.registry = xml_path,
// Optional, default is false
.enable_validation = if (optimize == .Debug) true else false,
// Optional, default is false
.verbose = true,
});
exe.root_module.addImport("vk-kickstart", kickstart_dep.module("vk-kickstart"));
You can then import vk-kickstart
as a module and vulkan-zig
const vkk = @import("vk-kickstart");
const vk = @import("vulkan");
See build.zig for an example
For a code example, see main.zig
Using the instance.CreateOptions
struct's fields, you can you can choose how you want the instance to be configured like the required api version.
Note: VK_KHR_surface and the platform specific surface extension are automatically enabled. Only works for Windows, MacOS and Linux (xcb, xlib or wayland) for now
const vk = @import("vulkan-zig");
pub const CreateOptions = struct {
/// Application name.
app_name: [*:0]const u8 = "",
/// Application version.
app_version: u32 = 0,
/// Engine name.
engine_name: [*:0]const u8 = "",
/// Engine version.
engine_version: u32 = 0,
/// Required Vulkan version (minimum 1.1).
required_api_version: u32 = vk.API_VERSION_1_1,
/// Array of required extensions to enable.
/// Note: VK_KHR_surface and the platform specific surface extension are automatically enabled.
required_extensions: []const [*:0]const u8 = &.{},
/// Array of required layers to enable.
required_layers: []const [*:0]const u8 = &.{},
/// pNext chain.
p_next_chain: ?*anyopaque = null,
/// Debug messenger options
debug: DebugMessengerOptions = .{},
};
Pass these options to instance.create()
to create an instance
You can set criterias to select an appropriate physical device for your application using PhysicalDevice.SelectOptions
Note: VK_KHR_subset (if available) and VK_KHR_swapchain are automatically enabled, no need to add them to the list
const vk = @import("vulkan-zig");
pub const SelectOptions = struct {
/// Vulkan render surface.
surface: vk.SurfaceKHR,
/// Name of the device to select.
name: ?[*:0]const u8 = null,
/// Required Vulkan version (minimum 1.1).
required_api_version: u32 = vk.API_VERSION_1_1,
/// Prefered physical device type.
preferred_type: vk.PhysicalDeviceType = .discrete_gpu,
/// Transfer queue preference.
transfer_queue: QueuePreference = .none,
/// Compute queue preference.
compute_queue: QueuePreference = .none,
/// Required local memory size.
required_mem_size: vk.DeviceSize = 0,
/// Required physical device features.
required_features: vk.PhysicalDeviceFeatures = .{},
/// Required physical device feature version 1.1.
required_features_11: vk.PhysicalDeviceVulkan11Features = .{},
/// Required physical device feature version 1.2.
required_features_12: ?vk.PhysicalDeviceVulkan12Features = null,
/// Required physical device feature version 1.3.
required_features_13: ?vk.PhysicalDeviceVulkan13Features = null,
/// Array of required physical device extensions to enable.
/// Note: VK_KHR_swapchain and VK_KHR_subset (if available) are automatically enabled.
required_extensions: []const [*:0]const u8 = &.{},
};
Pass these options to PhysicalDevice.select()
to select a device
For this, you only need to call device.create()
with the previously selected physical device
Finally to create a swapchain, use Swapchain.CreateOptions
const vk = @import("vulkan-zig");
pub const CreateOptions = struct {
/// Graphics queue index
graphics_queue_index: u32,
/// Present queue index
present_queue_index: u32,
/// Desired size (in pixels) of the swapchain image(s).
/// These values will be clamped within the capabilities of the device
desired_extent: vk.Extent2D,
/// Swapchain create flags
create_flags: vk.SwapchainCreateFlagsKHR = .{},
/// Desired minimum number of presentable images that the application needs.
/// If left on default, will try to use the minimum of the device + 1.
/// This value will be clamped between the device's minimum and maximum (if there is a max).
desired_min_image_count: ?u32 = null,
/// Array of desired image formats, in order of priority.
/// Will fallback to the first found if none match
desired_formats: []const vk.SurfaceFormatKHR = &.{
.{ .format = .b8g8r8a8_srgb, .color_space = .srgb_nonlinear_khr },
},
/// Array of desired present modes, in order of priority.
/// Will fallback to fifo_khr is none match
desired_present_modes: []const vk.PresentModeKHR = &.{
.mailbox_khr,
},
/// Desired number of views in a multiview/stereo surface.
/// Will be clamped down if higher than device's max
desired_array_layer_count: u32 = 1,
/// Intended usage of the (acquired) swapchain images
image_usage_flags: vk.ImageUsageFlags = .{ .color_attachment_bit = true },
/// Value describing the transform, relative to the presentation engine’s natural orientation, applied to the image content prior to presentation
pre_transform: ?vk.SurfaceTransformFlagsKHR = null,
/// Value indicating the alpha compositing mode to use when this surface is composited together with other surfaces on certain window systems
composite_alpha: vk.CompositeAlphaFlagsKHR = .{ .opaque_bit_khr = true },
/// Discard rendering operation that are not visible
clipped: vk.Bool32 = vk.TRUE,
/// Existing non-retired swapchain currently associated with surface
old_swapchain: ?vk.SwapchainKHR = null,
/// pNext chain
p_next_chain: ?*anyopaque = null,
};
Pass these options and a the logical device to Swapchain.create()
to create the swapchain
- Headless mode