Categories
Tags
3d ABI Actions algorithms alignment analyze APIT Arc Architecture arm array ascii ash assembly asynchronous attribute base64 bithacks Blogging box c c23 cdylib CHAR_BIT clamp clang clang-format client clippy cmake compiler Computer concat concurrency const_fn constexpr contravariant cos covariant cpp cpu crate CS Customization cybersecurity DataStructure db debugging Demo deserialization discrete dll doc DP drawio dtruss dylib Dynamic emulator example Example FFI ffmpeg flamegraph flat_map fold format FP fsanitize Functional FunctionalProgramming functions futures Fuwari game GATs gcc gccrs generics gitignore glibc GUI hacking hashmap haskell heap hyperfine Imperative inference intel interop invariant iterator join justfile kernel LaTeX leak LFU limits linux lto MachineLearning macOS map Markdown math ML mmap mod mp3 nc nextest OnceLock optimization OS ownership panic parallels perf physics pin postgresql procedure product profiling pub radare2 rayon release reverse RPIT rust sanitizer Science science serialization server shift SIMD sin size SmallProjects so socket std strace String StringView strip strlen struct sum super surrealdb SWAR swisstable synchronous syscall tan test thread time toml tracing traits trap triangulation type uint32_t UnsafeRust utf16 utf8 vector Video vulkan wsl x86_64 xilem zig
683 words
3 minutes
ash_vulkan_basic001
link
ash test
use ash::Entry;
fn main() {
let entry = unsafe { Entry::load().unwrap() };
let extensions = unsafe { entry.enumerate_instance_extension_properties(None).unwrap() };
for extension in extensions {
let name = unsafe { std::ffi::CStr::from_ptr(extension.extension_name.as_ptr()) };
println!("{}", name.to_string_lossy());
}
}- result
$ cargo r
VK_KHR_device_group_creation
VK_KHR_external_fence_capabilities
VK_KHR_external_memory_capabilities
VK_KHR_external_semaphore_capabilities
VK_KHR_get_physical_device_properties2
VK_KHR_get_surface_capabilities2
VK_KHR_surface
VK_KHR_surface_maintenance1
VK_KHR_surface_protected_capabilities
VK_EXT_debug_report
VK_EXT_debug_utils
VK_EXT_headless_surface
VK_EXT_layer_settings
VK_EXT_metal_surface
VK_EXT_surface_maintenance1
VK_EXT_swapchain_colorspace
VK_MVK_macos_surface
VK_KHR_portability_enumeration
VK_LUNARG_direct_driver_loadinghello ash
use ash::{Entry, vk};
use std::ffi::{CStr, CString};
fn main() -> Result<(), Box<dyn std::error::Error>> {
// ------------------------------------------------------------
// 1. Load the Vulkan loader
// ------------------------------------------------------------
let entry = unsafe { Entry::load()? };
// ------------------------------------------------------------
// 2. Enumerate available instance layers
// ------------------------------------------------------------
let available_layers = unsafe { entry.enumerate_instance_layer_properties()? };
let has_validation = available_layers.iter().any(|layer| {
let name = unsafe { CStr::from_ptr(layer.layer_name.as_ptr()) };
name == c"VK_LAYER_KHRONOS_validation"
});
println!("Validation layer available: {has_validation}");
// ------------------------------------------------------------
// 3. Enumerate available instance extensions
// ------------------------------------------------------------
let available_extensions = unsafe { entry.enumerate_instance_extension_properties(None)? };
let has_extension = |wanted: &CStr| {
available_extensions.iter().any(|extension| {
let name = unsafe { CStr::from_ptr(extension.extension_name.as_ptr()) };
name == wanted
})
};
let has_debug_utils = has_extension(c"VK_EXT_debug_utils");
let has_portability_enumeration = has_extension(c"VK_KHR_portability_enumeration");
let has_get_physical_device_properties2 =
has_extension(c"VK_KHR_get_physical_device_properties2");
println!("VK_EXT_debug_utils: {}", has_debug_utils);
println!(
"VK_KHR_portability_enumeration: {}",
has_portability_enumeration
);
println!(
"VK_KHR_get_physical_device_properties2: {}",
has_get_physical_device_properties2
);
// ------------------------------------------------------------
// 4. Application information
// ------------------------------------------------------------
let app_name = CString::new("Ash Practice")?;
let engine_name = CString::new("No Engine")?;
let app_info = vk::ApplicationInfo::default()
.application_name(&app_name)
.application_version(0)
.engine_name(&engine_name)
.engine_version(0)
.api_version(vk::API_VERSION_1_0);
// ------------------------------------------------------------
// 5. Instance extensions
// ------------------------------------------------------------
let mut extension_names = Vec::new();
// Debug utilities are optional.
if has_validation && has_debug_utils {
extension_names.push(c"VK_EXT_debug_utils".as_ptr());
}
// ------------------------------------------------------------
// macOS / MoltenVK
//
// VK_KHR_portability_enumeration tells the loader that
// we explicitly want to enumerate portability drivers such
// as MoltenVK.
//
// With Vulkan 1.0, LunarG also recommends:
//
// VK_KHR_get_physical_device_properties2
// ------------------------------------------------------------
let use_portability = has_portability_enumeration;
if use_portability {
extension_names.push(c"VK_KHR_portability_enumeration".as_ptr());
if has_get_physical_device_properties2 {
extension_names.push(c"VK_KHR_get_physical_device_properties2".as_ptr());
}
}
// ------------------------------------------------------------
// 6. Instance creation flags
// ------------------------------------------------------------
let mut instance_flags = vk::InstanceCreateFlags::empty();
if use_portability {
instance_flags |= vk::InstanceCreateFlags::ENUMERATE_PORTABILITY_KHR;
println!("Enabling Vulkan portability enumeration");
}
// ------------------------------------------------------------
// 7. Validation layer
// ------------------------------------------------------------
let validation_layer_name = c"VK_LAYER_KHRONOS_validation";
let layer_names = if has_validation {
println!("Enabling validation layers");
vec![validation_layer_name.as_ptr()]
} else {
println!("Validation layers not found, continuing without them");
Vec::new()
};
// ------------------------------------------------------------
// 8. Create Vulkan instance
// ------------------------------------------------------------
let create_info = vk::InstanceCreateInfo::default()
.flags(instance_flags)
.application_info(&app_info)
.enabled_extension_names(&extension_names)
.enabled_layer_names(&layer_names);
let instance = unsafe { entry.create_instance(&create_info, None)? };
println!("Instance created!");
// ------------------------------------------------------------
// 9. Enumerate physical devices
// ------------------------------------------------------------
let pdevices = unsafe { instance.enumerate_physical_devices()? };
println!("Found {} physical device(s)", pdevices.len());
if pdevices.is_empty() {
return Err("No Vulkan physical device found".into());
}
// ------------------------------------------------------------
// 10. Find a graphics queue
// ------------------------------------------------------------
let (pdevice, queue_family_index) = pdevices
.iter()
.find_map(|pdevice| {
let queue_families =
unsafe { instance.get_physical_device_queue_family_properties(*pdevice) };
queue_families.iter().enumerate().find_map(|(index, info)| {
if info.queue_flags.contains(vk::QueueFlags::GRAPHICS) {
Some((*pdevice, index as u32))
} else {
None
}
})
})
.ok_or("No graphics queue family found")?;
// ------------------------------------------------------------
// 11. GPU information
// ------------------------------------------------------------
let props = unsafe { instance.get_physical_device_properties(pdevice) };
let device_name = unsafe { CStr::from_ptr(props.device_name.as_ptr()) };
println!("----------------------------------------");
println!("Selected GPU: {}", device_name.to_string_lossy());
println!(
"Vulkan API: {}.{}.{}",
vk::api_version_major(props.api_version),
vk::api_version_minor(props.api_version),
vk::api_version_patch(props.api_version),
);
println!("Driver version: {}", props.driver_version);
println!("Graphics queue family: {}", queue_family_index);
println!("----------------------------------------");
// ------------------------------------------------------------
// 12. Create logical device
// ------------------------------------------------------------
let queue_priority = [1.0_f32];
let queue_info = vk::DeviceQueueCreateInfo::default()
.queue_family_index(queue_family_index)
.queue_priorities(&queue_priority);
let queue_infos = std::slice::from_ref(&queue_info);
let device_create_info = vk::DeviceCreateInfo::default().queue_create_infos(queue_infos);
let device = unsafe { instance.create_device(pdevice, &device_create_info, None)? };
// ------------------------------------------------------------
// 13. Get graphics queue
// ------------------------------------------------------------
let graphics_queue = unsafe { device.get_device_queue(queue_family_index, 0) };
println!("Logical device created!");
println!("Graphics queue created!");
println!("Vulkan initialization successful!");
// Prevent the queue from being considered unused.
let _ = graphics_queue;
// ------------------------------------------------------------
// 14. Cleanup
// ------------------------------------------------------------
unsafe {
device.destroy_device(None);
instance.destroy_instance(None);
}
Ok(())
}- result
Validation layer available: true
VK_EXT_debug_utils: true
VK_KHR_portability_enumeration: true
VK_KHR_get_physical_device_properties2: true
Enabling Vulkan portability enumeration
Enabling validation layers
Instance created!
Found 1 physical device(s)
----------------------------------------
Selected GPU: Apple M4 Max
Vulkan API: 1.0.357
Driver version: 10402
Graphics queue family: 0
----------------------------------------
Validation Error: [ VUID-VkDeviceCreateInfo-pProperties-04451 ] | MessageID = 0x3a3b6ca0
vkCreateDevice(): VK_KHR_portability_subset must be enabled because physical device VkPhysicalDevice 0x7baf4a9320 supports it.
The Vulkan spec states: If the VK_KHR_portability_subset extension is included in pProperties of vkEnumerateDeviceExtensionProperties, ppEnabledExtensionNames must include "VK_KHR_portability_subset" (https://vulkan.lunarg.com/doc/view/1.4.357.1/mac/antora/spec/latest/chapters/devsandqueues.html#VUID-VkDeviceCreateInfo-pProperties-04451)
Objects: 1
[0] VkPhysicalDevice 0x7baf4a9320
Logical device created!
Graphics queue created!
Vulkan initialization successful!ash_vulkan_basic001
https://younghakim7.github.io/blog/posts/ash_vulkan_basic001/