Compare commits
2 commits
92e0e0fdec
...
0e523e13ba
Author | SHA1 | Date | |
---|---|---|---|
0e523e13ba | |||
9bbc5e156a |
2 changed files with 87 additions and 48 deletions
16
build.rs
16
build.rs
|
@ -7,24 +7,14 @@ fn main() {
|
||||||
|
|
||||||
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
|
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
|
||||||
|
|
||||||
let vk_bindings = bindgen::Builder::default()
|
let glfw_vk_bindings = bindgen::Builder::default()
|
||||||
.header("/usr/include/vulkan/vulkan.h")
|
|
||||||
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
|
|
||||||
.generate()
|
|
||||||
.expect("Unable to generate vulkan bindings");
|
|
||||||
|
|
||||||
vk_bindings
|
|
||||||
.write_to_file(out_path.join("vk_bindings.rs"))
|
|
||||||
.expect("Couldn't write vk bindings!");
|
|
||||||
|
|
||||||
let glfw_bindings = bindgen::Builder::default()
|
|
||||||
.header_contents("glfw_defines", "#define GLFW_INCLUDE_VULKAN")
|
.header_contents("glfw_defines", "#define GLFW_INCLUDE_VULKAN")
|
||||||
.header("/usr/include/GLFW/glfw3.h")
|
.header("/usr/include/GLFW/glfw3.h")
|
||||||
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
|
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
|
||||||
.generate()
|
.generate()
|
||||||
.expect("Unable to generate glfw bindings");
|
.expect("Unable to generate glfw bindings");
|
||||||
|
|
||||||
glfw_bindings
|
glfw_vk_bindings
|
||||||
.write_to_file(out_path.join("glfw_bindings.rs"))
|
.write_to_file(out_path.join("glfw_vk_bindings.rs"))
|
||||||
.expect("Couldn't write glfw bindings!");
|
.expect("Couldn't write glfw bindings!");
|
||||||
}
|
}
|
||||||
|
|
119
src/main.rs
119
src/main.rs
|
@ -1,36 +1,36 @@
|
||||||
mod ffi_vk {
|
mod ffi {
|
||||||
#![allow(non_upper_case_globals)]
|
#![allow(non_upper_case_globals)]
|
||||||
#![allow(non_camel_case_types)]
|
#![allow(non_camel_case_types)]
|
||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
#![allow(unused_imports)]
|
#![allow(unused_imports)]
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
include!(concat!(env!("OUT_DIR"), "/vk_bindings.rs"));
|
include!(concat!(env!("OUT_DIR"), "/glfw_vk_bindings.rs"));
|
||||||
|
|
||||||
pub fn VK_MAKE_VERSION(major: u32, minor: u32, patch: u32) -> u32 {
|
pub fn VK_MAKE_VERSION(major: u32, minor: u32, patch: u32) -> u32 {
|
||||||
(major << 22) | (minor << 12) | patch
|
(major << 22) | (minor << 12) | patch
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn VK_MAKE_API_VERSION(variant: u32, major: u32, minor: u32, patch: u32) -> u32 {
|
pub fn VK_MAKE_API_VERSION(variant: u32, major: u32, minor: u32, patch: u32) -> u32 {
|
||||||
(variant << 29) | (major << 22) | (minor << 12) | patch
|
(variant << 29) | (major << 22) | (minor << 12) | patch
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mod ffi_glfw {
|
use std::ffi::{CStr, CString};
|
||||||
#![allow(non_upper_case_globals)]
|
|
||||||
#![allow(non_camel_case_types)]
|
|
||||||
#![allow(non_snake_case)]
|
|
||||||
#![allow(unused_imports)]
|
|
||||||
#![allow(dead_code)]
|
|
||||||
include!(concat!(env!("OUT_DIR"), "/glfw_bindings.rs"));
|
|
||||||
}
|
|
||||||
|
|
||||||
use std::ffi::CString;
|
|
||||||
|
|
||||||
const WINDOW_WIDTH: i32 = 800;
|
const WINDOW_WIDTH: i32 = 800;
|
||||||
const WINDOW_HEIGHT: i32 = 600;
|
const WINDOW_HEIGHT: i32 = 600;
|
||||||
|
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
const ENABLE_VALIDATION_LAYERS: bool = true;
|
||||||
|
#[cfg(not(debug_assertions))]
|
||||||
|
const ENABLE_VALIDATION_LAYERS: bool = false;
|
||||||
|
|
||||||
|
const VALIDATION_LAYER_STR_0: &str = "VK_LAYER_KHRONOS_validation\x00";
|
||||||
|
const VALIDATION_LAYERS: [&str; 1] = [VALIDATION_LAYER_STR_0];
|
||||||
|
|
||||||
struct VulkanApp {
|
struct VulkanApp {
|
||||||
window: *mut ffi_glfw::GLFWwindow,
|
window: *mut ffi::GLFWwindow,
|
||||||
vk_instance: ffi_vk::VkInstance,
|
vk_instance: ffi::VkInstance,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VulkanApp {
|
impl VulkanApp {
|
||||||
|
@ -44,13 +44,13 @@ impl VulkanApp {
|
||||||
fn init_glfw(&mut self) {
|
fn init_glfw(&mut self) {
|
||||||
let app_title = CString::new("Vulkan").unwrap();
|
let app_title = CString::new("Vulkan").unwrap();
|
||||||
unsafe {
|
unsafe {
|
||||||
ffi_glfw::glfwInit();
|
ffi::glfwInit();
|
||||||
ffi_glfw::glfwWindowHint(
|
ffi::glfwWindowHint(
|
||||||
ffi_glfw::GLFW_CLIENT_API as i32,
|
ffi::GLFW_CLIENT_API as i32,
|
||||||
ffi_glfw::GLFW_NO_API as i32,
|
ffi::GLFW_NO_API as i32,
|
||||||
);
|
);
|
||||||
ffi_glfw::glfwWindowHint(ffi_glfw::GLFW_RESIZABLE as i32, ffi_glfw::GLFW_FALSE as i32);
|
ffi::glfwWindowHint(ffi::GLFW_RESIZABLE as i32, ffi::GLFW_FALSE as i32);
|
||||||
self.window = ffi_glfw::glfwCreateWindow(
|
self.window = ffi::glfwCreateWindow(
|
||||||
WINDOW_WIDTH,
|
WINDOW_WIDTH,
|
||||||
WINDOW_HEIGHT,
|
WINDOW_HEIGHT,
|
||||||
app_title.as_ptr(),
|
app_title.as_ptr(),
|
||||||
|
@ -64,17 +64,22 @@ impl VulkanApp {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init_vulkan(&mut self) {
|
fn init_vulkan(&mut self) {
|
||||||
|
// Check validation layers before creating instance.
|
||||||
|
if ENABLE_VALIDATION_LAYERS && !Self::check_validation_layer_support() {
|
||||||
|
panic!("Validation layers requested, but not available!");
|
||||||
|
}
|
||||||
|
|
||||||
// Create instance.
|
// Create instance.
|
||||||
let app_name = CString::new("Vulkan Triangle").unwrap();
|
let app_name = CString::new("Vulkan Triangle").unwrap();
|
||||||
let engine_name = CString::new("No Engine").unwrap();
|
let engine_name = CString::new("No Engine").unwrap();
|
||||||
let app_info = ffi_vk::VkApplicationInfo {
|
let app_info = ffi::VkApplicationInfo {
|
||||||
sType: ffi_vk::VkStructureType_VK_STRUCTURE_TYPE_APPLICATION_INFO,
|
sType: ffi::VkStructureType_VK_STRUCTURE_TYPE_APPLICATION_INFO,
|
||||||
pNext: std::ptr::null_mut(),
|
pNext: std::ptr::null_mut(),
|
||||||
pApplicationName: app_name.as_ptr(),
|
pApplicationName: app_name.as_ptr(),
|
||||||
applicationVersion: ffi_vk::VK_MAKE_VERSION(1, 0, 0),
|
applicationVersion: ffi::VK_MAKE_VERSION(1, 0, 0),
|
||||||
pEngineName: engine_name.as_ptr(),
|
pEngineName: engine_name.as_ptr(),
|
||||||
engineVersion: ffi_vk::VK_MAKE_VERSION(1, 0, 0),
|
engineVersion: ffi::VK_MAKE_VERSION(1, 0, 0),
|
||||||
apiVersion: ffi_vk::VK_MAKE_API_VERSION(0, 1, 0, 0),
|
apiVersion: ffi::VK_MAKE_API_VERSION(0, 1, 0, 0),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Populate VkInstanceCreateInfo.
|
// Populate VkInstanceCreateInfo.
|
||||||
|
@ -83,12 +88,12 @@ impl VulkanApp {
|
||||||
let mut ext_count: u32 = 0;
|
let mut ext_count: u32 = 0;
|
||||||
let exts: *mut *const std::ffi::c_char;
|
let exts: *mut *const std::ffi::c_char;
|
||||||
unsafe {
|
unsafe {
|
||||||
exts = ffi_glfw::glfwGetRequiredInstanceExtensions(std::ptr::addr_of_mut!(ext_count));
|
exts = ffi::glfwGetRequiredInstanceExtensions(std::ptr::addr_of_mut!(ext_count));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Second populate the struct with necessary info.
|
// Second populate the struct with necessary info.
|
||||||
let create_info = ffi_vk::VkInstanceCreateInfo {
|
let create_info = ffi::VkInstanceCreateInfo {
|
||||||
sType: ffi_vk::VkStructureType_VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
|
sType: ffi::VkStructureType_VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
|
||||||
pNext: std::ptr::null(),
|
pNext: std::ptr::null(),
|
||||||
flags: 0,
|
flags: 0,
|
||||||
pApplicationInfo: std::ptr::addr_of!(app_info),
|
pApplicationInfo: std::ptr::addr_of!(app_info),
|
||||||
|
@ -99,18 +104,62 @@ impl VulkanApp {
|
||||||
};
|
};
|
||||||
|
|
||||||
let vk_result = unsafe {
|
let vk_result = unsafe {
|
||||||
ffi_vk::vkCreateInstance(
|
ffi::vkCreateInstance(
|
||||||
std::ptr::addr_of!(create_info),
|
std::ptr::addr_of!(create_info),
|
||||||
std::ptr::null(),
|
std::ptr::null(),
|
||||||
std::ptr::addr_of_mut!(self.vk_instance),
|
std::ptr::addr_of_mut!(self.vk_instance),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
if vk_result != ffi_vk::VkResult_VK_SUCCESS {
|
if vk_result != ffi::VkResult_VK_SUCCESS {
|
||||||
panic!("ERROR: Failed to create vk instance!");
|
panic!("ERROR: Failed to create vk instance!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn check_validation_layer_support() -> bool {
|
||||||
|
let mut layer_count: u32 = 0;
|
||||||
|
unsafe {
|
||||||
|
ffi::vkEnumerateInstanceLayerProperties(
|
||||||
|
std::ptr::addr_of_mut!(layer_count),
|
||||||
|
std::ptr::null_mut(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut layers: Vec<ffi::VkLayerProperties> = Vec::with_capacity(layer_count as usize);
|
||||||
|
layers.resize(
|
||||||
|
layer_count as usize,
|
||||||
|
ffi::VkLayerProperties {
|
||||||
|
layerName: [0; 256],
|
||||||
|
specVersion: 0,
|
||||||
|
implementationVersion: 0,
|
||||||
|
description: [0; 256],
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
ffi::vkEnumerateInstanceLayerProperties(std::ptr::addr_of_mut!(layer_count), layers.as_mut_ptr());
|
||||||
|
}
|
||||||
|
|
||||||
|
for layer_name in VALIDATION_LAYERS {
|
||||||
|
let mut layer_found = false;
|
||||||
|
let ln_cstr = unsafe { CStr::from_ptr(layer_name.as_ptr() as *const i8) };
|
||||||
|
for layer_prop in &layers {
|
||||||
|
let lp_cstr: &CStr = unsafe { CStr::from_ptr(layer_prop.layerName.as_ptr()) };
|
||||||
|
if ln_cstr == lp_cstr {
|
||||||
|
layer_found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !layer_found {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("Validation layers available");
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
fn main_loop(&mut self) {
|
fn main_loop(&mut self) {
|
||||||
if self.window.is_null() {
|
if self.window.is_null() {
|
||||||
panic!("ERROR: Cannot execute main loop if window is null!");
|
panic!("ERROR: Cannot execute main loop if window is null!");
|
||||||
|
@ -122,10 +171,10 @@ impl VulkanApp {
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
unsafe {
|
unsafe {
|
||||||
if ffi_glfw::glfwWindowShouldClose(self.window) != 0 {
|
if ffi::glfwWindowShouldClose(self.window) != 0 {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ffi_glfw::glfwPollEvents();
|
ffi::glfwPollEvents();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -135,18 +184,18 @@ impl Drop for VulkanApp {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
if !self.vk_instance.is_null() {
|
if !self.vk_instance.is_null() {
|
||||||
unsafe {
|
unsafe {
|
||||||
ffi_vk::vkDestroyInstance(self.vk_instance, std::ptr::null());
|
ffi::vkDestroyInstance(self.vk_instance, std::ptr::null());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !self.window.is_null() {
|
if !self.window.is_null() {
|
||||||
unsafe {
|
unsafe {
|
||||||
ffi_glfw::glfwDestroyWindow(self.window);
|
ffi::glfwDestroyWindow(self.window);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
ffi_glfw::glfwTerminate();
|
ffi::glfwTerminate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue