1.1 搞了半天了Vulkan的影儿都没看见,老板,能不能把主菜端上来?

好吧,我们在上小节里创建了需要承载vulkan的窗口(注意不是Vulkan实例正在运行的窗口),现在可以实现一下vulkan的实例了.

工作流程

上面这个流程图呢简单的介绍了一下大概我们Vulkan是怎么搞工作的,那么我们的实例在哪里呢?

你看到Vulkan App 右边第一个加载没有? 这就是我们实例所在的位置,实例负责加载(初始化)一个Vulkan加载器,然后加载器会加载一些其他的层和驱动之类的东西,在下一节我们会讲到验证层,也就是一个最常用的层.

现在我们开始实际写代码,我们在app目录下创建一个vki.rs

use super::super::platforms::required_extension::*;//这个马上写
use ash::version::EntryV1_0;
use ash::version::InstanceV1_0;
use ash::vk;
use ash::vk_make_version;
use std::ffi::CString;
use std::ptr;
pub const WINDOW_TITLE: &'static str = "When Vulkan meets Rust";
//vulkan的版本需要使用一个宏来构造,其实是u32类型的,这里大家可以根据自己vulkan的版本来进行配置
pub const APPLICATION_VERSION: u32 = vk_make_version!(1, 0, 0);
pub const ENGINE_VERSION: u32 = vk_make_version!(1, 0, 0);
pub const API_VERSION: u32 = vk_make_version!(1, 0, 92);

pub struct VKI {
    pub instance: ash::Instance, //Vulkan实例
}

现在我们实现一下new方法

impl VKI {
    pub fn new() -> VKI {
        let entry = ash::Entry::new().unwrap(); //入口

        let app_name = CString::new(WINDOW_TITLE).unwrap(); //vulkan内部描述应用的名称
        let engine_name = CString::new("Vulkan Engine").unwrap();
        let app_info = vk::ApplicationInfo {
            s_type: vk::StructureType::APPLICATION_INFO,//结构类型
            p_next: ptr::null(),//一会儿再讲
            p_application_name: app_name.as_ptr(),//app名称
            application_version: APPLICATION_VERSION,//app版本
            p_engine_name: engine_name.as_ptr(),//引擎名称
            engine_version: ENGINE_VERSION,//引擎版本
            api_version: API_VERSION, //api版本
        }; //应用信息

        let extension_names = required_extension_names();//这个马上写

        let create_info = vk::InstanceCreateInfo {
            s_type: vk::StructureType::INSTANCE_CREATE_INFO,
            p_next: ptr::null(),
            flags: vk::InstanceCreateFlags::empty(),//一会儿再讲
            p_application_info: &app_info,//刚刚我们创建的描述信息
            pp_enabled_layer_names: ptr::null(),//一会儿讲,暂时用不到
            enabled_layer_count: 0,//同上
            pp_enabled_extension_names: extension_names.as_ptr(),//启用的扩展
            enabled_extension_count: extension_names.len() as u32,//扩展表列长度
        };

        let instance: ash::Instance = unsafe { //unsafe因为vulkan是C语言写的
            entry
                .create_instance(&create_info, None)
                .expect("Vulkan实例创建失败 原因:")
        };

        VKI { instance: instance }
    }
}

因为vulkan是C语言写的(为了追求最强性能),所以他的内存管理完全是手动的.

而Rust没怎么用过free()函数是因为Rust采用了RAII,当对象从作用空间里消失的时候会自动调用drop函数

一般情况下drop函数都是Rust替我们写好的,不过这次不一样,我们需要手动去释放vulkan创建出来的一堆东西,所以我们需要手动写drop函数 还是那个文件

impl Drop for VKI {
    fn drop(&mut self) {
        unsafe {//因为涉及到了裸指针操作
            self.instance.destroy_instance(None);
        }
    }
}




因为vulkan每个平台上用的渲染方法都不太一样 所以我们要实现一个非常平台相关的一堆函数

src下创建platforms文件夹,自行配置lib.rs

platforms下创建required_extension.rs自行写mod.rs

#[cfg(target_os = "windows")] //对于windows平台用的是win32的surface
use ash::extensions::khr::Win32Surface;
#[cfg(all(unix, not(target_os = "android"), not(target_os = "macos")))] 
//对于不是安卓,苹果的unix(linux BSD HPUnix之类的)用的Xlib
use ash::extensions::khr::XlibSurface;

use ash::extensions::khr::Surface;
use ash::extensions::ext::DebugReport;

// *const i8 是指针类型,这个也是因为vulkan是C写的所以我们需要传递裸指针
#[cfg(all(windows))]
pub fn required_extension_names() -> Vec<*const i8> {
    vec![
        Surface::name().as_ptr(),
        Win32Surface::name().as_ptr(),
        DebugReport::name().as_ptr(),
    ]
}

#[cfg(all(unix, not(target_os = "android"), not(target_os = "macos")))]
pub fn required_extension_names() -> Vec<*const i8> {
    vec![
        Surface::name().as_ptr(),
        XlibSurface::name().as_ptr(),
        DebugReport::name().as_ptr(),
    ]
}

现在呢,我们写好了一切创建一个vulkan实例用的东西了,我们只需要把我们的VKI加入到App里就好了,还是app.rs

pub struct App {
    pub window: winit::Window,
    pub vki: VKI, //新增
}

impl App {
    pub fn new(events_loop: &EventsLoop) -> App {
        let window = window_create(WINDOW_TITLE.to_string(), 800, 600, events_loop);
        return App {
            window: window,
            vki: VKI::new(),//新增
        };
    }
}

一切准备就绪,可以cargo run跑跑看看了

补充: 如果终端显示 error: process didn't exit successfully: target\debug\vk_00.exe (exit code: 0xc0000005, STATUS_ACCESS_VIOLATION)或类似问题,请不要急,在1.2会解决这个问题的

results matching ""

    No results matching ""