Added Vulkan support

This commit is contained in:
Rua
2018-07-12 14:52:11 +02:00
parent 4bb6b9abcf
commit 443d116f49
4 changed files with 676 additions and 15 deletions
+49
View File
@@ -459,6 +459,55 @@ fn main() {
This method is useful when you don't care about sdl2's render capabilities, but you do care about
its audio, controller and other neat features that sdl2 has.
# Vulkan
To use Vulkan, you need a Vulkan library for Rust. This example uses the [Vulkano][vulkano]
library. Other libraries may use different data types for raw Vulkan object handles. The
procedure to interface SDL2's Vulkan functions with these will be different for each one.
```rust
extern crate sdl2;
extern crate vulkano;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use std::ffi::CString;
use vulkano::VulkanObject;
use vulkano::instance::{Instance, RawInstanceExtensions};
use vulkano::swapchain::Surface;
fn main() {
let sdl_context = sdl2::init().unwrap();
let video_subsystem = sdl_context.video().unwrap();
let window = video_subsystem.window("Window", 800, 600)
.vulkan()
.build()
.unwrap();
let instance_extensions = window.vulkan_instance_extensions().unwrap();
let raw_instance_extensions = RawInstanceExtensions::new(instance_extensions.iter().map(|&v| CString::new(v).unwrap()));
let instance = Instance::new(None, raw_instance_extensions, None).unwrap();
let surface_handle = window.vulkan_create_surface(instance.internal_object()).unwrap();
let surface = unsafe { Surface::from_raw_surface(instance, surface_handle, window.context()) };
let mut event_pump = sdl_context.event_pump().unwrap();
'running: loop {
for event in event_pump.poll_iter() {
match event {
Event::Quit {..} | Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
break 'running
},
_ => {}
}
}
::std::thread::sleep(::std::time::Duration::new(0, 1_000_000_000u32 / 60));
}
}
```
# When things go wrong
Rust, and Rust-SDL2, are both still heavily in development, and you may run
into teething issues when using this. Before panicking, check that you're using
+535 -14
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -1,2 +1,3 @@
#include <SDL.h>
#include <SDL_syswm.h>
#include <SDL_vulkan.h>
+91 -1
View File
@@ -1,4 +1,4 @@
use libc::{c_int, c_float, uint32_t, c_char};
use libc::{c_int, c_uint, c_float, uint32_t, c_char};
use std::ffi::{CStr, CString, NulError};
use std::{mem, ptr, fmt};
use std::rc::Rc;
@@ -19,6 +19,9 @@ use get_error;
use sys;
type VkInstance = usize;
type VkSurfaceKHR = u64;
pub struct WindowSurfaceRef<'a>(&'a mut SurfaceRef, &'a Window);
impl<'a> Deref for WindowSurfaceRef<'a> {
@@ -807,6 +810,61 @@ impl VideoSubsystem {
mem::transmute(interval)
}
}
/// Loads the default Vulkan library.
///
/// This should be done after initializing the video driver, but before creating any Vulkan windows.
/// If no Vulkan library is loaded, the default library will be loaded upon creation of the first Vulkan window.
///
/// If a different library is already loaded, this function will return an error.
pub fn vulkan_load_library_default(&self) -> Result<(), String> {
unsafe {
if sys::SDL_Vulkan_LoadLibrary(ptr::null()) == 0 {
Ok(())
} else {
Err(get_error())
}
}
}
/// Loads the Vulkan library using a platform-dependent Vulkan library name (usually a file path).
///
/// This should be done after initializing the video driver, but before creating any Vulkan windows.
/// If no Vulkan library is loaded, the default library will be loaded upon creation of the first Vulkan window.
///
/// If a different library is already loaded, this function will return an error.
pub fn vulkan_load_library<P: AsRef<::std::path::Path>>(&self, path: P) -> Result<(), String> {
unsafe {
// TODO: use OsStr::to_cstring() once it's stable
let path = CString::new(path.as_ref().to_str().unwrap()).unwrap();
if sys::SDL_Vulkan_LoadLibrary(path.as_ptr() as *const c_char) == 0 {
Ok(())
} else {
Err(get_error())
}
}
}
/// Unloads the current Vulkan library.
///
/// To completely unload the library, this should be called for every successful load of the
/// Vulkan library.
pub fn vulkan_unload_library(&self) {
unsafe { sys::SDL_Vulkan_UnloadLibrary(); }
}
/// Gets the pointer to the
/// [`vkGetInstanceProcAddr`](https://www.khronos.org/registry/vulkan/specs/1.1-extensions/man/html/vkGetInstanceProcAddr.html)
/// Vulkan function. This function can be called to retrieve the address of other Vulkan
/// functions.
pub fn vulkan_get_proc_address_function(&self) -> Result<*const (), String> {
let result = unsafe { sys::SDL_Vulkan_GetVkGetInstanceProcAddr() as *const () };
if result.is_null() {
Err(get_error())
} else {
Ok(result)
}
}
}
#[derive(Debug)]
@@ -1070,6 +1128,31 @@ impl Window {
unsafe { sys::SDL_GL_SwapWindow(self.context.raw) }
}
/// Get the names of the Vulkan instance extensions needed to create a surface with `vulkan_create_surface`.
pub fn vulkan_instance_extensions(&self) -> Result<Vec<&'static str>, String> {
let mut count: c_uint = 0;
if unsafe { sys::SDL_Vulkan_GetInstanceExtensions(self.context.raw, &mut count, ptr::null_mut()) } == sys::SDL_bool::SDL_FALSE {
return Err(get_error());
}
let mut names: Vec<*const c_char> = vec![ptr::null(); count as usize];
if unsafe { sys::SDL_Vulkan_GetInstanceExtensions(self.context.raw, &mut count, names.as_mut_ptr()) } == sys::SDL_bool::SDL_FALSE {
return Err(get_error());
}
Ok(names.iter().map(|&val| unsafe { CStr::from_ptr(val) }.to_str().unwrap()).collect())
}
/// Create a Vulkan rendering surface for a window.
///
/// The `VkInstance` must be created using a prior call to the `vkCreateInstance` function in the Vulkan library.
pub fn vulkan_create_surface(&self, instance: VkInstance) -> Result<VkSurfaceKHR, String> {
let mut surface: sys::VkSurfaceKHR = ptr::null_mut();
if unsafe { sys::SDL_Vulkan_CreateSurface(self.context.raw, instance as *mut _, &mut surface) } == sys::SDL_bool::SDL_FALSE {
Err(get_error())
} else {
Ok(surface as VkSurfaceKHR)
}
}
pub fn display_index(&self) -> Result<i32, String> {
let result = unsafe { sys::SDL_GetWindowDisplayIndex(self.context.raw) };
if result < 0 {
@@ -1205,6 +1288,13 @@ impl Window {
(w as u32, h as u32)
}
pub fn vulkan_drawable_size(&self) -> (u32, u32) {
let mut w: c_int = 0;
let mut h: c_int = 0;
unsafe { sys::SDL_Vulkan_GetDrawableSize(self.context.raw, &mut w, &mut h) };
(w as u32, h as u32)
}
pub fn set_minimum_size(&mut self, width: u32, height: u32)
-> Result<(), IntegerOrSdlError> {
let w = try!(validate_int(width, "width"));