diff options
Diffstat (limited to 'gfx/wgpu_bindings/src/lib.rs')
-rw-r--r-- | gfx/wgpu_bindings/src/lib.rs | 218 |
1 files changed, 218 insertions, 0 deletions
diff --git a/gfx/wgpu_bindings/src/lib.rs b/gfx/wgpu_bindings/src/lib.rs new file mode 100644 index 0000000000..de34649c95 --- /dev/null +++ b/gfx/wgpu_bindings/src/lib.rs @@ -0,0 +1,218 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use wgc::id; + +pub use wgc::command::{compute_ffi::*, render_ffi::*}; + +pub mod client; +pub mod identity; +pub mod server; + +pub use wgc::device::trace::Command as CommandEncoderAction; + +use std::marker::PhantomData; +use std::{borrow::Cow, mem, slice}; + +use nsstring::nsACString; + +type RawString = *const std::os::raw::c_char; + +//TODO: figure out why 'a and 'b have to be different here +//TODO: remove this +fn cow_label<'a, 'b>(raw: &'a RawString) -> Option<Cow<'b, str>> { + if raw.is_null() { + None + } else { + let cstr = unsafe { std::ffi::CStr::from_ptr(*raw) }; + cstr.to_str().ok().map(Cow::Borrowed) + } +} + +// Hides the repeated boilerplate of turning a `Option<&nsACString>` into a `Option<Cow<str>`. +pub fn wgpu_string(gecko_string: Option<&nsACString>) -> Option<Cow<str>> { + gecko_string.map(|s| s.to_utf8()) +} + +/// An equivalent of `&[T]` for ffi structures and function parameters. +#[repr(C)] +pub struct FfiSlice<'a, T> { + // `data` may be null. + pub data: *const T, + pub length: usize, + pub _marker: PhantomData<&'a T>, +} + +impl<'a, T> FfiSlice<'a, T> { + pub unsafe fn as_slice(&self) -> &'a [T] { + if self.data.is_null() { + // It is invalid to construct a rust slice with a null pointer. + return &[]; + } + + std::slice::from_raw_parts(self.data, self.length) + } +} + +impl<'a, T> Copy for FfiSlice<'a, T> {} +impl<'a, T> Clone for FfiSlice<'a, T> { + fn clone(&self) -> Self { + *self + } +} + +#[repr(C)] +pub struct ByteBuf { + data: *const u8, + len: usize, + capacity: usize, +} + +impl ByteBuf { + fn from_vec(vec: Vec<u8>) -> Self { + if vec.is_empty() { + ByteBuf { + data: std::ptr::null(), + len: 0, + capacity: 0, + } + } else { + let bb = ByteBuf { + data: vec.as_ptr(), + len: vec.len(), + capacity: vec.capacity(), + }; + mem::forget(vec); + bb + } + } + + unsafe fn as_slice(&self) -> &[u8] { + slice::from_raw_parts(self.data, self.len) + } +} + +#[repr(C)] +#[derive(serde::Serialize, serde::Deserialize)] +pub struct AdapterInformation<S> { + id: id::AdapterId, + limits: wgt::Limits, + features: wgt::Features, + name: S, + vendor: u32, + device: u32, + device_type: wgt::DeviceType, + driver: S, + driver_info: S, + backend: wgt::Backend, +} + +#[derive(serde::Serialize, serde::Deserialize)] +struct ImplicitLayout<'a> { + pipeline: id::PipelineLayoutId, + bind_groups: Cow<'a, [id::BindGroupLayoutId]>, +} + +#[derive(serde::Serialize, serde::Deserialize)] +enum DeviceAction<'a> { + CreateTexture(id::TextureId, wgc::resource::TextureDescriptor<'a>), + CreateSampler(id::SamplerId, wgc::resource::SamplerDescriptor<'a>), + CreateBindGroupLayout( + id::BindGroupLayoutId, + wgc::binding_model::BindGroupLayoutDescriptor<'a>, + ), + CreatePipelineLayout( + id::PipelineLayoutId, + wgc::binding_model::PipelineLayoutDescriptor<'a>, + ), + CreateBindGroup(id::BindGroupId, wgc::binding_model::BindGroupDescriptor<'a>), + CreateShaderModule( + id::ShaderModuleId, + wgc::pipeline::ShaderModuleDescriptor<'a>, + Cow<'a, str>, + ), + CreateComputePipeline( + id::ComputePipelineId, + wgc::pipeline::ComputePipelineDescriptor<'a>, + Option<ImplicitLayout<'a>>, + ), + CreateRenderPipeline( + id::RenderPipelineId, + wgc::pipeline::RenderPipelineDescriptor<'a>, + Option<ImplicitLayout<'a>>, + ), + CreateRenderBundle( + id::RenderBundleId, + wgc::command::RenderBundleEncoder, + wgc::command::RenderBundleDescriptor<'a>, + ), + CreateCommandEncoder( + id::CommandEncoderId, + wgt::CommandEncoderDescriptor<wgc::Label<'a>>, + ), + Error(String), +} + +#[derive(serde::Serialize, serde::Deserialize)] +enum QueueWriteAction { + Buffer { + dst: id::BufferId, + offset: wgt::BufferAddress, + }, + Texture { + dst: wgt::ImageCopyTexture<id::TextureId>, + layout: wgt::ImageDataLayout, + size: wgt::Extent3d, + }, +} + +#[derive(serde::Serialize, serde::Deserialize)] +enum TextureAction<'a> { + CreateView(id::TextureViewId, wgc::resource::TextureViewDescriptor<'a>), +} + +#[repr(C)] +#[derive(serde::Serialize, serde::Deserialize)] +enum DropAction { + Adapter(id::AdapterId), + Device(id::DeviceId), + ShaderModule(id::ShaderModuleId), + PipelineLayout(id::PipelineLayoutId), + BindGroupLayout(id::BindGroupLayoutId), + BindGroup(id::BindGroupId), + CommandBuffer(id::CommandBufferId), + RenderBundle(id::RenderBundleId), + RenderPipeline(id::RenderPipelineId), + ComputePipeline(id::ComputePipelineId), + Buffer(id::BufferId), + Texture(id::TextureId), + TextureView(id::TextureViewId), + Sampler(id::SamplerId), +} + +impl DropAction { + // helper function to construct byte bufs + fn to_byte_buf(&self) -> ByteBuf { + let mut data = Vec::new(); + bincode::serialize_into(&mut data, self).unwrap(); + ByteBuf::from_vec(data) + } +} + +#[repr(C)] +pub struct ImageDataLayout<'a> { + pub offset: wgt::BufferAddress, + pub bytes_per_row: Option<&'a u32>, + pub rows_per_image: Option<&'a u32>, +} + +impl<'a> ImageDataLayout<'a> { + fn into_wgt(&self) -> wgt::ImageDataLayout { + wgt::ImageDataLayout { + offset: self.offset, + bytes_per_row: self.bytes_per_row.map(|bpr| *bpr), + rows_per_image: self.rows_per_image.map(|rpi| *rpi), + } + } +} |