首页 > 解决方案 > 为什么启用 VK_KHR_SURFACE 会导致 CreateInstance 失败?

问题描述

取消注释第 96 行:

 // extension_names.push(String::from(VK_KHR_SURFACE)); // uncomment to see error

将导致CreateInstance第 121 行失败。

我正在关注一个Vulkan 教程,其中提到扩展是通过定义VK_USE_PLATFORM_WIN32_KHR. 好吧,我正在使用vk-sys(我应该使用其他 Rust Vulkan 绑定吗?),这是Vulkano使用的板条箱。我搜索了 Vulkano 的存储库,没有提到VK_USE_PLATFORM_WIN32_KHR. 它也不在vk-sys docs中。

有没有办法VK_USE_PLATFORM_WIN32_KHR在 Rust 中定义或者不需要?或者还有什么我需要做的吗?

extern crate shared_library;
extern crate vk_sys as vk;

use std::mem;
use std::os::raw::c_char;
use std::os::raw::c_void;
use std::ptr;
use std::path::Path;

const VK_KHR_SURFACE: &'static str = "VK_KHR_surface\0"; // base surface that all platforms need
const VK_KHR_WIN32_SURFACE: &'static str = "VK_KHR_win32_surface\0";

// https://github.com/vulkano-rs/vulkano/blob/f4f91f7ee1aace3062571bc1f678b702fbd020cd/vulkano/src/instance/loader.rs#L36
pub unsafe trait Loader {
    fn get_instance_proc_addr(
        &self,
        instance: vk::Instance,
        name: *const c_char,
    ) -> extern "system" fn() -> ();
}

// https://github.com/vulkano-rs/vulkano/blob/f4f91f7ee1aace3062571bc1f678b702fbd020cd/vulkano/src/instance/loader.rs#L56
pub struct DynamicLibraryLoader {
    vk_lib: shared_library::dynamic_library::DynamicLibrary,
    get_proc_addr: extern "system" fn(instance: vk::Instance, pName: *const c_char)
        -> extern "system" fn() -> (),
}

// removed error checking
// https://github.com/vulkano-rs/vulkano/blob/71d90e562a63f2a9aee40abaa3b59949e909015d/vulkano/src/instance/loader.rs#L63
impl DynamicLibraryLoader {
    pub unsafe fn new<P>(path: P) -> DynamicLibraryLoader
    where
        P: AsRef<Path>,
    {
        let vk_lib =
            shared_library::dynamic_library::DynamicLibrary::open(Some(path.as_ref())).unwrap();
        let get_proc_addr = {
            let ptr: *mut c_void = vk_lib.symbol("vkGetInstanceProcAddr").unwrap();
            mem::transmute(ptr)
        };

        DynamicLibraryLoader {
            vk_lib,
            get_proc_addr,
        }
    }
}

// https://github.com/vulkano-rs/vulkano/blob/f4f91f7ee1aace3062571bc1f678b702fbd020cd/vulkano/src/instance/loader.rs#L94
unsafe impl Loader for DynamicLibraryLoader {
    #[inline]
    fn get_instance_proc_addr(
        &self,
        instance: vk::Instance,
        name: *const c_char,
    ) -> extern "system" fn() -> () {
        (self.get_proc_addr)(instance, name)
    }
}

// For Windows. For other OS, see:
// https://github.com/vulkano-rs/vulkano/blob/71d90e562a63f2a9aee40abaa3b59949e909015d/vulkano/src/instance/loader.rs#L171
fn get_path() -> &'static Path {
    Path::new("vulkan-1.dll")
}

// return codes: https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VkResult
fn check_result(msg: &str, result: vk::Result) {
    match result {
        vk::SUCCESS => println!("{}: {}", msg, "SUCCESS"),
        vk::NOT_READY => println!("{}: {}", msg, "NOT_READY"),
        vk::TIMEOUT => println!("{}: {}", msg, "TIMEOUT"),
        vk::EVENT_SET => println!("{}: {}", msg, "EVENT_SET"),
        vk::EVENT_RESET => println!("{}: {}", msg, "EVENT_RESET"),
        vk::INCOMPLETE => println!("{}: {}", msg, "INCOMPLETE"),
        vk::ERROR_OUT_OF_HOST_MEMORY => println!("{}: {}", msg, "ERROR_OUT_OF_HOST_MEMORY"),
        vk::ERROR_OUT_OF_DEVICE_MEMORY => println!("{}: {}", msg, "ERROR_OUT_OF_DEVICE_MEMORY"),
        vk::ERROR_INITIALIZATION_FAILED => println!("{}: {}", msg, "ERROR_INITIALIZATION_FAILED"),
        vk::ERROR_DEVICE_LOST => println!("{}: {}", msg, "ERROR_DEVICE_LOST"),
        vk::ERROR_MEMORY_MAP_FAILED => println!("{}: {}", msg, "ERROR_MEMORY_MAP_FAILED"),
        vk::ERROR_LAYER_NOT_PRESENT => println!("{}: {}", msg, "ERROR_LAYER_NOT_PRESENT"),
        vk::ERROR_EXTENSION_NOT_PRESENT => println!("{}: {}", msg, "ERROR_EXTENSION_NOT_PRESENT"),
        vk::ERROR_FEATURE_NOT_PRESENT => println!("{}: {}", msg, "ERROR_FEATURE_NOT_PRESENT"),
        vk::ERROR_INCOMPATIBLE_DRIVER => println!("{}: {}", msg, "ERROR_INCOMPATIBLE_DRIVER"),
        vk::ERROR_TOO_MANY_OBJECTS => println!("{}: {}", msg, "ERROR_TOO_MANY_OBJECTS"),
        vk::ERROR_FORMAT_NOT_SUPPORTED => println!("{}: {}", msg, "ERROR_FORMAT_NOT_SUPPORTED"),
        // vk::ERROR_FRAGMENTED_POOL => println!("{}: {}", msg, "ERROR_FRAGMENTED_POOL"),
        _ => println!("VK_ERR: {:?}", result),
    };
}

fn main() {
    //********************************************************************************************************** Instance Create Info
    let mut extension_names: Vec<String> = Vec::new();
    // extension_names.push(String::from(VK_KHR_SURFACE)); // uncomment to see error
    extension_names.push(String::from(VK_KHR_WIN32_SURFACE));
    println!("extension_names: {:?}", extension_names);

    let instance_create_info = vk::InstanceCreateInfo {
        sType: vk::STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
        pNext: ptr::null(),
        flags: 0,
        pApplicationInfo: ptr::null(),
        enabledLayerCount: 0,
        ppEnabledLayerNames: ptr::null(),
        enabledExtensionCount: extension_names.len() as u32,
        ppEnabledExtensionNames: extension_names.as_ptr() as *const *const i8,
    };

    //********************************************************************************************************** Instance Creation
    let mut instance: vk::Instance = unsafe {mem::uninitialized()};

    let loader = unsafe { DynamicLibraryLoader::new(get_path()) };

    let entry_points = vk::EntryPoints::load(|name| unsafe {
        mem::transmute(loader.get_instance_proc_addr(instance, name.as_ptr()))
    });

    unsafe {
        check_result("create instance", entry_points.CreateInstance(&instance_create_info, ptr::null(), &mut instance));
    }
}

货物.toml:

[dependencies]
vk-sys = "*"
shared_library = "*"

标签: rustvulkan

解决方案


您尝试&str用于 FFI 的方式不起作用。您必须使用std::ffi::CString. 还要看看你应该如何收集指向CStrings 的指针:

extern crate shared_library;
extern crate vk_sys as vk;

use std::mem;
use std::ffi::CString;
use std::os::raw::c_char;
use std::os::raw::c_void;
use std::ptr;
use std::path::Path;

const VK_KHR_SURFACE: &'static str = "VK_KHR_surface"; // base surface that all platforms need
const VK_KHR_WIN32_SURFACE: &'static str = "VK_KHR_win32_surface";

// https://github.com/vulkano-rs/vulkano/blob/f4f91f7ee1aace3062571bc1f678b702fbd020cd/vulkano/src/instance/loader.rs#L36
pub unsafe trait Loader {
    fn get_instance_proc_addr(
        &self,
        instance: vk::Instance,
        name: *const c_char,
    ) -> extern "system" fn() -> ();
}

// https://github.com/vulkano-rs/vulkano/blob/f4f91f7ee1aace3062571bc1f678b702fbd020cd/vulkano/src/instance/loader.rs#L56
pub struct DynamicLibraryLoader {
    vk_lib: shared_library::dynamic_library::DynamicLibrary,
    get_proc_addr: extern "system" fn(instance: vk::Instance, pName: *const c_char)
        -> extern "system" fn() -> (),
}

// removed error checking
// https://github.com/vulkano-rs/vulkano/blob/71d90e562a63f2a9aee40abaa3b59949e909015d/vulkano/src/instance/loader.rs#L63
impl DynamicLibraryLoader {
    pub unsafe fn new<P>(path: P) -> DynamicLibraryLoader
    where
        P: AsRef<Path>,
    {
        let vk_lib =
            shared_library::dynamic_library::DynamicLibrary::open(Some(path.as_ref())).unwrap();
        let get_proc_addr = {
            let ptr: *mut c_void = vk_lib.symbol("vkGetInstanceProcAddr").unwrap();
            mem::transmute(ptr)
        };

        DynamicLibraryLoader {
            vk_lib,
            get_proc_addr,
        }
    }
}

// https://github.com/vulkano-rs/vulkano/blob/f4f91f7ee1aace3062571bc1f678b702fbd020cd/vulkano/src/instance/loader.rs#L94
unsafe impl Loader for DynamicLibraryLoader {
    #[inline]
    fn get_instance_proc_addr(
        &self,
        instance: vk::Instance,
        name: *const c_char,
    ) -> extern "system" fn() -> () {
        (self.get_proc_addr)(instance, name)
    }
}

// For Windows. For other OS, see:
// https://github.com/vulkano-rs/vulkano/blob/71d90e562a63f2a9aee40abaa3b59949e909015d/vulkano/src/instance/loader.rs#L171
fn get_path() -> &'static Path {
    Path::new("libvulkan.dylib")
}

// return codes: https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VkResult
fn check_result(msg: &str, result: vk::Result) {
    match result {
        vk::SUCCESS => println!("{}: {}", msg, "SUCCESS"),
        vk::NOT_READY => println!("{}: {}", msg, "NOT_READY"),
        vk::TIMEOUT => println!("{}: {}", msg, "TIMEOUT"),
        vk::EVENT_SET => println!("{}: {}", msg, "EVENT_SET"),
        vk::EVENT_RESET => println!("{}: {}", msg, "EVENT_RESET"),
        vk::INCOMPLETE => println!("{}: {}", msg, "INCOMPLETE"),
        vk::ERROR_OUT_OF_HOST_MEMORY => println!("{}: {}", msg, "ERROR_OUT_OF_HOST_MEMORY"),
        vk::ERROR_OUT_OF_DEVICE_MEMORY => println!("{}: {}", msg, "ERROR_OUT_OF_DEVICE_MEMORY"),
        vk::ERROR_INITIALIZATION_FAILED => println!("{}: {}", msg, "ERROR_INITIALIZATION_FAILED"),
        vk::ERROR_DEVICE_LOST => println!("{}: {}", msg, "ERROR_DEVICE_LOST"),
        vk::ERROR_MEMORY_MAP_FAILED => println!("{}: {}", msg, "ERROR_MEMORY_MAP_FAILED"),
        vk::ERROR_LAYER_NOT_PRESENT => println!("{}: {}", msg, "ERROR_LAYER_NOT_PRESENT"),
        vk::ERROR_EXTENSION_NOT_PRESENT => println!("{}: {}", msg, "ERROR_EXTENSION_NOT_PRESENT"),
        vk::ERROR_FEATURE_NOT_PRESENT => println!("{}: {}", msg, "ERROR_FEATURE_NOT_PRESENT"),
        vk::ERROR_INCOMPATIBLE_DRIVER => println!("{}: {}", msg, "ERROR_INCOMPATIBLE_DRIVER"),
        vk::ERROR_TOO_MANY_OBJECTS => println!("{}: {}", msg, "ERROR_TOO_MANY_OBJECTS"),
        vk::ERROR_FORMAT_NOT_SUPPORTED => println!("{}: {}", msg, "ERROR_FORMAT_NOT_SUPPORTED"),
        // vk::ERROR_FRAGMENTED_POOL => println!("{}: {}", msg, "ERROR_FRAGMENTED_POOL"),
        _ => println!("VK_ERR: {:?}", result),
    };
}

fn main() {
    //********************************************************************************************************** Instance Create Info
    let mut extension_names: Vec<CString> = Vec::new();
    extension_names.push(CString::new(VK_KHR_SURFACE).unwrap()); // uncomment to see error
    extension_names.push(CString::new(VK_KHR_WIN32_SURFACE).unwrap());
    println!("extension_names: {:?}", extension_names);

    let extension_names_ffi = extension_names.iter().map(|ext_name| ext_name.as_ptr() as *const i8).collect::<Vec<_>>();

    let instance_create_info = vk::InstanceCreateInfo {
        sType: vk::STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
        pNext: ptr::null(),
        flags: 0,
        pApplicationInfo: ptr::null(),
        enabledLayerCount: 0,
        ppEnabledLayerNames: ptr::null(),
        enabledExtensionCount: extension_names.len() as u32,
        ppEnabledExtensionNames: extension_names_ffi.as_ptr(),
    };

    //********************************************************************************************************** Instance Creation
    let mut instance: vk::Instance = unsafe {mem::uninitialized()};

    let loader = unsafe { DynamicLibraryLoader::new(get_path()) };

    let entry_points = vk::EntryPoints::load(|name| unsafe {
        mem::transmute(loader.get_instance_proc_addr(instance, name.as_ptr()))
    });

    unsafe {
        check_result("create instance", entry_points.CreateInstance(&instance_create_info, ptr::null(), &mut instance));
    }
}

推荐阅读