mirror of
https://github.com/encounter/rust-sdl2.git
synced 2026-07-10 21:18:41 -07:00
Added Vulkan support
This commit is contained in:
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -1,2 +1,3 @@
|
||||
#include <SDL.h>
|
||||
#include <SDL_syswm.h>
|
||||
#include <SDL_vulkan.h>
|
||||
|
||||
+91
-1
@@ -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"));
|
||||
|
||||
Reference in New Issue
Block a user