From 53aabad8b49d1abd0092472bfa84de5eccb07277 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Thu, 13 Sep 2018 15:19:16 -0400 Subject: [PATCH] First bits of the API with extern C functions --- .gitignore | 4 ++ Cargo.toml | 11 +++++ src/command.rs | 13 ++++++ src/device.rs | 22 ++++++++++ src/handle.rs | 113 ++++++++++++++++++++++++++++++++++++++++++++++++ src/instance.rs | 23 ++++++++++ src/lib.rs | 97 +++++++++++++++++++++++++++++++++++++++++ 7 files changed, 283 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.toml create mode 100644 src/command.rs create mode 100644 src/device.rs create mode 100644 src/handle.rs create mode 100644 src/instance.rs create mode 100644 src/lib.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..a821aa992 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ + +/target +**/*.rs.bk +Cargo.lock diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 000000000..954288242 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "gpu" +version = "0.1.0" +authors = ["Dzmitry Malyshau "] + +[features] +default = ["gfx-backend-vulkan"] + +[dependencies] +gfx-hal = { git = "https://github.com/gfx-rs/gfx" } +gfx-backend-vulkan = { git = "https://github.com/gfx-rs/gfx", optional = true } diff --git a/src/command.rs b/src/command.rs new file mode 100644 index 000000000..e88c9e1cf --- /dev/null +++ b/src/command.rs @@ -0,0 +1,13 @@ +use hal; + +pub struct CommandBuffer { + raw: B::CommandBuffer, +} + +pub struct RenderPass { + raw: B::CommandBuffer, +} + +pub struct ComputePass { + raw: B::CommandBuffer, +} diff --git a/src/device.rs b/src/device.rs new file mode 100644 index 000000000..a27dbf46b --- /dev/null +++ b/src/device.rs @@ -0,0 +1,22 @@ +use hal; + + +pub type BufferUsage = hal::buffer::Usage; + +#[repr(C)] +pub struct BufferDescriptor { + pub size: u64, + pub usage: BufferUsage, +} + +#[repr(C)] +pub struct CommandBufferDescriptor { +} + +pub struct Device { + pub raw: B::Device, +} + +pub struct Buffer { + pub raw: B::Buffer, +} diff --git a/src/handle.rs b/src/handle.rs new file mode 100644 index 000000000..6716ff5a7 --- /dev/null +++ b/src/handle.rs @@ -0,0 +1,113 @@ +use std::{borrow, cmp, fmt, ops, ptr}; +#[cfg(feature = "nightly")] +use std::sync::{Arc, Mutex}; + +#[cfg(feature = "nightly")] +use hal::backend::FastHashMap; + +#[cfg(feature = "nightly")] +lazy_static! { + static ref REGISTRY: Arc>> = Arc::new(Mutex::new(FastHashMap::default())); +} + +#[repr(C)] +pub struct Handle(*mut T); + +#[cfg(feature = "nightly")] +impl Handle<()> { + pub fn report_leaks() { + println!("Leaked handles:"); + let mut map = REGISTRY.lock().unwrap(); + for (_, type_id) in map.drain() { + println!("\t{:?}", type_id); + } + } +} + +impl Handle { + pub fn new(value: T) -> Self { + let ptr = Box::into_raw(Box::new(value)); + #[cfg(feature = "nightly")] + { + use std::intrinsics::type_name; + let name = unsafe { type_name::() }; + REGISTRY.lock().unwrap().insert(ptr as _, name); + } + Handle(ptr) + } + + pub fn null() -> Self { + Handle(ptr::null_mut()) + } + + pub fn unbox(self) -> Option { + if self.0.is_null() { + None + } else { + #[cfg(feature = "nightly")] + { + REGISTRY.lock().unwrap().remove(&(self.0 as _)).unwrap(); + } + Some(*unsafe { Box::from_raw(self.0) }) + } + } + + pub fn as_ref(&self) -> Option<&T> { + unsafe { self.0.as_ref() } + } +} + +impl Handle { + #[cfg(feature = "nightly")] + #[inline] + fn check(&self) { + assert!(REGISTRY.lock().unwrap().contains_key(&(self.0 as _))); + } + #[cfg(not(feature = "nightly"))] + #[inline] + fn check(&self) { + debug_assert!(!self.0.is_null()); + } +} + +impl Clone for Handle { + fn clone(&self) -> Self { + Handle(self.0) + } +} + +impl Copy for Handle {} + +impl ops::Deref for Handle { + type Target = T; + fn deref(&self) -> &T { + self.check(); + unsafe { &*self.0 } + } +} + +impl ops::DerefMut for Handle { + fn deref_mut(&mut self) -> &mut T { + self.check(); + unsafe { &mut *self.0 } + } +} + +impl borrow::Borrow for Handle { + fn borrow(&self) -> &T { + self.check(); + unsafe { &*self.0 } + } +} + +impl cmp::PartialEq for Handle { + fn eq(&self, other: &Self) -> bool { + self.0.eq(&other.0) + } +} + +impl fmt::Debug for Handle { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + write!(formatter, "Handle({:p})", self.0) + } +} diff --git a/src/instance.rs b/src/instance.rs new file mode 100644 index 000000000..a9266011b --- /dev/null +++ b/src/instance.rs @@ -0,0 +1,23 @@ +//use hal; + +#[repr(C)] +pub enum PowerPreference { + Default = 0, + LowPower = 1, + HighPerformance = 2, +} + +#[repr(C)] +pub struct AdapterDescriptor { + pub power_preference: PowerPreference, +} + +#[repr(C)] +pub struct Extensions { + anisotropicFiltering: bool, +} + +#[repr(C)] +pub struct DeviceDescriptor { + pub extension: Extensions, +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 000000000..af237c19b --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,97 @@ +extern crate gfx_hal as hal; +#[cfg(feature = "gfx-backend-vulkan")] +extern crate gfx_backend_vulkan as back; + +mod command; +mod device; +mod handle; +mod instance; + +use back::Backend as B; +use hal::Device; + +use handle::Handle; + + +pub type InstanceHandle = Handle; +pub type AdapterHandle = Handle>; +pub type DeviceHandle = Handle>; +pub type BufferHandle = Handle>; +pub type CommandBufferHandle = Handle>; +pub type RenderPassHandle = Handle>; +pub type ComputePassHandle = Handle>; + +// Instance logic + +pub extern "C" +fn create_instance() -> InstanceHandle { + unimplemented!() +} + +pub extern "C" +fn instance_get_adapter( + instance: InstanceHandle, desc: instance::AdapterDescriptor +) -> AdapterHandle { + unimplemented!() +} + +pub extern "C" +fn adapter_create_device( + adapter: AdapterHandle, desc: instance::DeviceDescriptor +) -> DeviceHandle { + unimplemented!() +} + +// Device logic + +pub extern "C" +fn device_create_buffer( + device: DeviceHandle, desc: device::BufferDescriptor +) -> BufferHandle { + //let unbound = device.raw.create_buffer(desc.size, desc.usage).unwrap(); + //let reqs = device.raw.get_buffer_requirements(&unbound); + unimplemented!() +} + +pub extern "C" +fn device_create_command_buffer( + device: DeviceHandle, desc: device::CommandBufferDescriptor +) -> CommandBufferHandle { + unimplemented!() +} + +// Command Buffer logic + +pub extern "C" +fn command_buffer_begin_render_pass( + command_buffer: CommandBufferHandle +) -> RenderPassHandle { + unimplemented!() +} + +pub extern "C" +fn command_buffer_begin_compute_pass( +) -> ComputePassHandle { + unimplemented!() +} + +// Render Pass logic + +pub extern "C" +fn render_pass_draw( + pass: RenderPassHandle, vertex_count: u32, instance_count: u32, first_vertex: u32, first_instance: u32 +) { + unimplemented!() +} + +pub extern "C" +fn render_pass_draw_indexed( + pass: RenderPassHandle, index_count: u32, instance_count: u32, first_index: u32, vertex_offset: i32, first_instance: u32 +) { + unimplemented!() +} + +pub extern "C" +fn render_pass_end(pass: RenderPassHandle) -> CommandBufferHandle { + unimplemented!() +}