diff --git a/Cargo.lock b/Cargo.lock index ed22f39..db525df 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -940,6 +940,7 @@ dependencies = [ "librashader-reflect", "librashader-runtime", "librashader-spirv-cross", + "parking_lot", "rayon", "rustc-hash", "thiserror", diff --git a/README.md b/README.md index e80f9f6..5e3f868 100644 --- a/README.md +++ b/README.md @@ -10,23 +10,21 @@ librashader (*/ˈli:brəʃeɪdɚ/*) is a preprocessor, compiler, and runtime for ![Nightly rust](https://img.shields.io/badge/rust-nightly-orange.svg) ## Supported Render APIs -librashader supports OpenGL 3, OpenGL 4.6, Vulkan, Direct3D 11, and Direct3D 12. Older versions -of Direct3D and OpenGL, as well as Metal, are not supported (but pull-requests are welcome). +librashader supports OpenGL 3, OpenGL 4.6, Vulkan, Direct3D 11, and Direct3D 12. Metal and WebGPU +are not currently supported (but pull-requests are welcome). librashader does not support legacy render +APIs such as older versions of OpenGL, or legacy versions of Direct3D. | **API** | **Status** | **`librashader` feature** | -|-------------|------------|---------------------------| -| OpenGL 3.3+ | ✔ | `gl` | -| OpenGL 4.6 | ✔ | `gl` | -| Vulkan | ✔ | `vk` | -| Direct3D 11 | ✔ | `d3d11` | -| Direct3D 12 | ✔ | `d3d12` | -| OpenGL 2 | ❌ | | -| Direct3D 9 | ❌ | | -| Direct3D 10 | ❌ | | -| Metal | ❌ | | +|-------------|------------|--------------------------| +| OpenGL 3.3+ | ✔ | `gl` | +| OpenGL 4.6 | ✔ | `gl` | +| Vulkan | ✔ | `vk` | +| Direct3D 11 | ✔ | `d3d11` | +| Direct3D 12 | ✔ | `d3d12` | +| Metal | ❌ | | +| WebGPU | ❌ | | - -✔ = Render API is supported — 🚧 = Support is in progress — ❌ Render API is not supported +✔ = Render API is supported — ❌ Render API is not supported ## Usage librashader provides both a Rust API under the `librashader` crate, and a C API. Both APIs are first-class and fully supported. @@ -68,9 +66,9 @@ is important to ensure that updates to librashader do not break existing consume As of `0.1.0-rc.3`, the C ABI should be mostly stable. We reserve the right to make breaking changes before a numbered release without following semantic versioning. -Linking against `librashader.h` directly is possible, but is not officially supported. You will need to ensure linkage -parameters are correct in order to successfully link with `librashader.lib` or `librashader.a`. The [corrosion](https://github.com/corrosion-rs/) -CMake package is highly recommended. +Linking statically against `librashader.h` is possible, but is not officially supported. You will need to ensure +linkage parameters are correct in order to successfully link with `librashader.lib` or `librashader.a`. +The [corrosion](https://github.com/corrosion-rs/) CMake package is highly recommended. ### Examples @@ -153,6 +151,13 @@ static GL_DEFAULT_MVP: &[f32; 16] = &[ ]; ``` +### Thread safety +In general, it is **safe** to create a filter chain instance from a different thread, but drawing filter passes **must be +externally synchronized**. The exceptions to filter chain creation are in OpenGL, where creating the filter chain instance +is safe **if and only if** the thread local OpenGL context is initialized to the same context as the drawing thread, and +in Direct3D 11, where filter chain creation is thread-unsafe if the `ID3D11Device` was created with +`D3D11_CREATE_DEVICE_SINGLETHREADED`. + ### Writing a librashader Runtime If you wish to contribute a runtime implementation not already available, see the [librashader-runtime](https://docs.rs/librashader-runtime/latest/librashader_runtime/) diff --git a/include/librashader.h b/include/librashader.h index 7005e7b..ebb6c87 100644 --- a/include/librashader.h +++ b/include/librashader.h @@ -831,6 +831,10 @@ libra_error_t libra_gl_filter_chain_create(libra_shader_preset_t *preset, /// values for the model view projection matrix. /// - `opt` may be null, or if it is not null, must be an aligned pointer to a valid `frame_gl_opt_t` /// struct. +/// - You must ensure that only one thread has access to `chain` before you call this function. Only one +/// thread at a time may call this function. The thread `libra_gl_filter_chain_frame` is called from +/// must have its thread-local OpenGL context initialized with the same context used to create +/// the filter chain. libra_error_t libra_gl_filter_chain_frame(libra_gl_filter_chain_t *chain, size_t frame_count, struct libra_source_image_gl_t image, @@ -925,6 +929,8 @@ libra_error_t libra_vk_filter_chain_create(struct libra_device_vk_t vulkan, /// values for the model view projection matrix. /// - `opt` may be null, or if it is not null, must be an aligned pointer to a valid `frame_vk_opt_t` /// struct. +/// - You must ensure that only one thread has access to `chain` before you call this function. Only one +/// thread at a time may call this function. libra_error_t libra_vk_filter_chain_frame(libra_vk_filter_chain_t *chain, VkCommandBuffer command_buffer, size_t frame_count, @@ -1015,6 +1021,8 @@ libra_error_t libra_d3d11_filter_chain_create(libra_shader_preset_t *preset, /// struct. /// - `out` must not be null. /// - `image.handle` must not be null. +/// - You must ensure that only one thread has access to `chain` before you call this function. Only one +/// thread at a time may call this function. libra_error_t libra_d3d11_filter_chain_frame(libra_d3d11_filter_chain_t *chain, size_t frame_count, struct libra_source_image_d3d11_t image, @@ -1106,6 +1114,8 @@ libra_error_t libra_d3d12_filter_chain_create(libra_shader_preset_t *preset, /// - `out` must be a descriptor handle to a render target view. /// - `image.resource` must not be null. /// - `command_list` must not be null. +/// - You must ensure that only one thread has access to `chain` before you call this function. Only one +/// thread at a time may call this function. libra_error_t libra_d3d12_filter_chain_frame(libra_d3d12_filter_chain_t *chain, const ID3D12GraphicsCommandList * command_list, size_t frame_count, diff --git a/librashader-capi/src/lib.rs b/librashader-capi/src/lib.rs index a48c7b2..9ec6fcb 100644 --- a/librashader-capi/src/lib.rs +++ b/librashader-capi/src/lib.rs @@ -51,6 +51,18 @@ //! There is a case to be made for skipping error checking for `*_filter_chain_frame` due to performance reasons, //! but only if you are certain that the safety invariants are upheld on each call. Failure to check for errors //! may result in **undefined behaviour** stemming from failure to uphold safety invariants. +//! +//! ## Thread safety +//! +//! In general, it is **safe** to create a filter chain instance from a different thread, but drawing filter passes must be +//! synchronized externally. The exception to filter chain creation are in OpenGL, where creating the filter chain instance +//! is safe **if and only if** the thread local OpenGL context is initialized to the same context as the drawing thread, and +//! in Direct3D 11, where filter chain creation is unsafe if the `ID3D11Device` was created with +//! `D3D11_CREATE_DEVICE_SINGLETHREADED`. +//! +//! You must ensure that only thread has access to a created filter pass **before** you call `*_frame`. `*_frame` may only be +//! called from one thread at a time. + #![allow(non_camel_case_types)] #![feature(try_blocks)] #![feature(pointer_is_aligned)] @@ -73,3 +85,6 @@ pub type LIBRASHADER_API_VERSION = usize; /// The current version of the librashader API/ABI. /// Pass this into `version` for config structs. pub const LIBRASHADER_CURRENT_VERSION: LIBRASHADER_API_VERSION = 0; + +#[allow(dead_code)] +const fn assert_thread_safe() { } diff --git a/librashader-capi/src/presets.rs b/librashader-capi/src/presets.rs index ebd3139..4179741 100644 --- a/librashader-capi/src/presets.rs +++ b/librashader-capi/src/presets.rs @@ -7,6 +7,8 @@ use std::ffi::{c_char, CStr, CString}; use std::mem::MaybeUninit; use std::ptr::NonNull; +const _: () = crate::assert_thread_safe::(); + /// A list of preset parameters. #[repr(C)] pub struct libra_preset_param_list_t { diff --git a/librashader-capi/src/runtime/d3d11/filter_chain.rs b/librashader-capi/src/runtime/d3d11/filter_chain.rs index 288fc24..7729d0e 100644 --- a/librashader-capi/src/runtime/d3d11/filter_chain.rs +++ b/librashader-capi/src/runtime/d3d11/filter_chain.rs @@ -13,8 +13,8 @@ use windows::Win32::Graphics::Direct3D11::{ ID3D11Device, ID3D11RenderTargetView, ID3D11ShaderResourceView, }; -pub use librashader::runtime::d3d11::capi::options::FilterChainOptionsD3D11; -pub use librashader::runtime::d3d11::capi::options::FrameOptionsD3D11; +use librashader::runtime::d3d11::capi::options::FilterChainOptionsD3D11; +use librashader::runtime::d3d11::capi::options::FrameOptionsD3D11; use librashader::runtime::{FilterChainParameters, Size, Viewport}; use crate::LIBRASHADER_API_VERSION; @@ -142,6 +142,8 @@ extern_fn! { /// struct. /// - `out` must not be null. /// - `image.handle` must not be null. + /// - You must ensure that only one thread has access to `chain` before you call this function. Only one + /// thread at a time may call this function. fn libra_d3d11_filter_chain_frame( chain: *mut libra_d3d11_filter_chain_t, frame_count: usize, diff --git a/librashader-capi/src/runtime/d3d11/mod.rs b/librashader-capi/src/runtime/d3d11/mod.rs index 7db6582..5557f2b 100644 --- a/librashader-capi/src/runtime/d3d11/mod.rs +++ b/librashader-capi/src/runtime/d3d11/mod.rs @@ -2,3 +2,4 @@ mod filter_chain; pub use filter_chain::*; +const _: () = crate::assert_thread_safe::(); diff --git a/librashader-capi/src/runtime/d3d12/filter_chain.rs b/librashader-capi/src/runtime/d3d12/filter_chain.rs index 6bef61e..c85ea66 100644 --- a/librashader-capi/src/runtime/d3d12/filter_chain.rs +++ b/librashader-capi/src/runtime/d3d12/filter_chain.rs @@ -13,8 +13,8 @@ use windows::Win32::Graphics::Direct3D12::{ }; use windows::Win32::Graphics::Dxgi::Common::DXGI_FORMAT; -pub use librashader::runtime::d3d12::capi::options::FilterChainOptionsD3D12; -pub use librashader::runtime::d3d12::capi::options::FrameOptionsD3D12; +use librashader::runtime::d3d12::capi::options::FilterChainOptionsD3D12; +use librashader::runtime::d3d12::capi::options::FrameOptionsD3D12; use librashader::runtime::d3d12::{D3D12InputImage, D3D12OutputView}; use librashader::runtime::{FilterChainParameters, Size, Viewport}; @@ -159,6 +159,8 @@ extern_fn! { /// - `out` must be a descriptor handle to a render target view. /// - `image.resource` must not be null. /// - `command_list` must not be null. + /// - You must ensure that only one thread has access to `chain` before you call this function. Only one + /// thread at a time may call this function. fn libra_d3d12_filter_chain_frame( chain: *mut libra_d3d12_filter_chain_t, command_list: ManuallyDrop, diff --git a/librashader-capi/src/runtime/d3d12/mod.rs b/librashader-capi/src/runtime/d3d12/mod.rs index 2201178..3c6ecda 100644 --- a/librashader-capi/src/runtime/d3d12/mod.rs +++ b/librashader-capi/src/runtime/d3d12/mod.rs @@ -2,3 +2,4 @@ mod filter_chain; pub use filter_chain::*; +const _: () = crate::assert_thread_safe::(); diff --git a/librashader-capi/src/runtime/gl/filter_chain.rs b/librashader-capi/src/runtime/gl/filter_chain.rs index cd64a31..cf3728d 100644 --- a/librashader-capi/src/runtime/gl/filter_chain.rs +++ b/librashader-capi/src/runtime/gl/filter_chain.rs @@ -10,8 +10,8 @@ use std::mem::MaybeUninit; use std::ptr::NonNull; use std::slice; -pub use librashader::runtime::gl::capi::options::FilterChainOptionsGL; -pub use librashader::runtime::gl::capi::options::FrameOptionsGL; +use librashader::runtime::gl::capi::options::FilterChainOptionsGL; +use librashader::runtime::gl::capi::options::FrameOptionsGL; use librashader::runtime::FilterChainParameters; use librashader::runtime::{Size, Viewport}; use crate::LIBRASHADER_API_VERSION; @@ -162,6 +162,10 @@ extern_fn! { /// values for the model view projection matrix. /// - `opt` may be null, or if it is not null, must be an aligned pointer to a valid `frame_gl_opt_t` /// struct. + /// - You must ensure that only one thread has access to `chain` before you call this function. Only one + /// thread at a time may call this function. The thread `libra_gl_filter_chain_frame` is called from + /// must have its thread-local OpenGL context initialized with the same context used to create + /// the filter chain. fn libra_gl_filter_chain_frame( chain: *mut libra_gl_filter_chain_t, frame_count: usize, diff --git a/librashader-capi/src/runtime/gl/mod.rs b/librashader-capi/src/runtime/gl/mod.rs index 1699556..f33b437 100644 --- a/librashader-capi/src/runtime/gl/mod.rs +++ b/librashader-capi/src/runtime/gl/mod.rs @@ -2,3 +2,4 @@ mod filter_chain; pub use filter_chain::*; +const _: () = crate::assert_thread_safe::(); diff --git a/librashader-capi/src/runtime/vk/filter_chain.rs b/librashader-capi/src/runtime/vk/filter_chain.rs index 002f8fb..5666b7c 100644 --- a/librashader-capi/src/runtime/vk/filter_chain.rs +++ b/librashader-capi/src/runtime/vk/filter_chain.rs @@ -10,8 +10,8 @@ use std::mem::MaybeUninit; use std::ptr::NonNull; use std::slice; -pub use librashader::runtime::vk::capi::options::FilterChainOptionsVulkan; -pub use librashader::runtime::vk::capi::options::FrameOptionsVulkan; +use librashader::runtime::vk::capi::options::FilterChainOptionsVulkan; +use librashader::runtime::vk::capi::options::FrameOptionsVulkan; use librashader::runtime::FilterChainParameters; use librashader::runtime::{Size, Viewport}; @@ -182,6 +182,8 @@ extern_fn! { /// values for the model view projection matrix. /// - `opt` may be null, or if it is not null, must be an aligned pointer to a valid `frame_vk_opt_t` /// struct. + /// - You must ensure that only one thread has access to `chain` before you call this function. Only one + /// thread at a time may call this function. fn libra_vk_filter_chain_frame( chain: *mut libra_vk_filter_chain_t, command_buffer: vk::CommandBuffer, diff --git a/librashader-capi/src/runtime/vk/mod.rs b/librashader-capi/src/runtime/vk/mod.rs index 1699556..167e387 100644 --- a/librashader-capi/src/runtime/vk/mod.rs +++ b/librashader-capi/src/runtime/vk/mod.rs @@ -2,3 +2,4 @@ mod filter_chain; pub use filter_chain::*; +const _: () = crate::assert_thread_safe::(); diff --git a/librashader-runtime-d3d12/Cargo.toml b/librashader-runtime-d3d12/Cargo.toml index 10a297a..733da98 100644 --- a/librashader-runtime-d3d12/Cargo.toml +++ b/librashader-runtime-d3d12/Cargo.toml @@ -19,6 +19,7 @@ librashader-reflect = { path = "../librashader-reflect", version = "0.1.0-rc.2", librashader-runtime = { path = "../librashader-runtime", version = "0.1.0-rc.2" } thiserror = "1.0.37" spirv_cross = { package = "librashader-spirv-cross", version = "0.23" } +parking_lot = "0.12.1" rustc-hash = "1.1.0" bytemuck = { version = "1.12.3", features = ["derive"] } diff --git a/librashader-runtime-d3d12/src/buffer.rs b/librashader-runtime-d3d12/src/buffer.rs index 6a79028..72e9fe7 100644 --- a/librashader-runtime-d3d12/src/buffer.rs +++ b/librashader-runtime-d3d12/src/buffer.rs @@ -100,8 +100,10 @@ impl D3D12Buffer { /// SAFETY: Creating the pointer should be safe in multithreaded contexts. /// -/// Mutation is guarded by DerefMut +/// Mutation is guarded by DerefMut, so exclusive access is guaranteed. +/// We do not ever leak the pointer to C. unsafe impl Send for RawD3D12Buffer {} +unsafe impl Sync for RawD3D12Buffer {} pub struct RawD3D12Buffer { buffer: ManuallyDrop, ptr: NonNull, diff --git a/librashader-runtime-d3d12/src/descriptor_heap.rs b/librashader-runtime-d3d12/src/descriptor_heap.rs index f9169af..0c62a0c 100644 --- a/librashader-runtime-d3d12/src/descriptor_heap.rs +++ b/librashader-runtime-d3d12/src/descriptor_heap.rs @@ -1,10 +1,10 @@ use crate::error; use bitvec::bitvec; use bitvec::boxed::BitBox; -use std::cell::RefCell; +use parking_lot::RwLock; use std::marker::PhantomData; use std::ops::Deref; -use std::rc::Rc; +use std::sync::Arc; use crate::error::FilterChainError; use windows::Win32::Graphics::Direct3D12::{ @@ -98,12 +98,12 @@ impl const D3D12HeapType for SamplerWorkHeap { } } -pub type D3D12DescriptorHeapSlot = Rc>; +pub type D3D12DescriptorHeapSlot = Arc>; pub struct D3D12DescriptorHeapSlotInner { cpu_handle: D3D12_CPU_DESCRIPTOR_HANDLE, gpu_handle: Option, - heap: Rc>, + heap: Arc>, slot: usize, _pd: PhantomData, } @@ -117,7 +117,7 @@ impl D3D12DescriptorHeapSlotInner { /// unsafe because type must match pub unsafe fn copy_descriptor(&self, source: D3D12_CPU_DESCRIPTOR_HANDLE) { unsafe { - let heap = self.heap.deref().borrow(); + let heap = self.heap.deref().read(); heap.device .CopyDescriptorsSimple(1, self.cpu_handle, source, heap.ty) @@ -142,7 +142,7 @@ impl AsRef impl From<&D3D12DescriptorHeap> for ID3D12DescriptorHeap { fn from(value: &D3D12DescriptorHeap) -> Self { - value.0.borrow().heap.clone() + value.0.read().heap.clone() } } @@ -159,7 +159,7 @@ struct D3D12DescriptorHeapInner { map: BitBox, } -pub struct D3D12DescriptorHeap(Rc>, PhantomData); +pub struct D3D12DescriptorHeap(Arc>, PhantomData); impl D3D12DescriptorHeap { pub fn new(device: &ID3D12Device, size: usize) -> error::Result> { @@ -171,7 +171,7 @@ impl D3D12DescriptorHeap { impl D3D12DescriptorHeap { /// Gets a cloned handle to the inner heap pub fn handle(&self) -> ID3D12DescriptorHeap { - let inner = self.0.borrow(); + let inner = self.0.read(); inner.heap.clone() } @@ -190,7 +190,7 @@ impl D3D12DescriptorHeap { }; Ok(D3D12DescriptorHeap( - Rc::new(RefCell::new(D3D12DescriptorHeapInner { + Arc::new(RwLock::new(D3D12DescriptorHeapInner { device: device.clone(), heap, ty: desc.Type, @@ -224,12 +224,12 @@ impl D3D12DescriptorHeap { ) { // has to be called right after creation. assert_eq!( - Rc::strong_count(&self.0), + Arc::strong_count(&self.0), 1, "D3D12DescriptorHeap::suballocate can only be callled immediately after creation." ); - let inner = Rc::try_unwrap(self.0) + let inner = Arc::try_unwrap(self.0) .expect("[d3d12] undefined behaviour to suballocate a descriptor heap with live descriptors.") .into_inner(); @@ -301,11 +301,11 @@ impl D3D12DescriptorHeap { heaps .into_iter() .map(|inner| { - D3D12DescriptorHeap(Rc::new(RefCell::new(inner)), PhantomData::default()) + D3D12DescriptorHeap(Arc::new(RwLock::new(inner)), PhantomData::default()) }) .collect(), reserved_heap.map(|inner| { - D3D12DescriptorHeap(Rc::new(RefCell::new(inner)), PhantomData::default()) + D3D12DescriptorHeap(Arc::new(RwLock::new(inner)), PhantomData::default()) }), inner.heap, ) @@ -314,7 +314,7 @@ impl D3D12DescriptorHeap { pub fn alloc_slot(&mut self) -> error::Result> { let mut handle = D3D12_CPU_DESCRIPTOR_HANDLE { ptr: 0 }; - let mut inner = self.0.borrow_mut(); + let mut inner = self.0.write(); for i in inner.start..inner.num_descriptors { if !inner.map[i] { inner.map.set(i, true); @@ -327,10 +327,10 @@ impl D3D12DescriptorHeap { ptr: (handle.ptr as u64 - inner.cpu_start.ptr as u64) + gpu_start.ptr, }); - return Ok(Rc::new(D3D12DescriptorHeapSlotInner { + return Ok(Arc::new(D3D12DescriptorHeapSlotInner { cpu_handle: handle, slot: i, - heap: Rc::clone(&self.0), + heap: Arc::clone(&self.0), gpu_handle, _pd: Default::default(), })); @@ -352,7 +352,7 @@ impl D3D12DescriptorHeap { impl Drop for D3D12DescriptorHeapSlotInner { fn drop(&mut self) { - let mut inner = self.heap.borrow_mut(); + let mut inner = self.heap.write(); inner.map.set(self.slot, false); if inner.start > self.slot { inner.start = self.slot diff --git a/librashader-runtime-d3d12/src/filter_chain.rs b/librashader-runtime-d3d12/src/filter_chain.rs index 887e57c..f40c917 100644 --- a/librashader-runtime-d3d12/src/filter_chain.rs +++ b/librashader-runtime-d3d12/src/filter_chain.rs @@ -403,6 +403,8 @@ impl FilterChainD3D12 { let filters: Vec> = passes.into_par_iter() .zip(hlsl_passes) + .zip(work_heaps) + .zip(sampler_work_heaps) .enumerate() .map_init( || { @@ -411,8 +413,8 @@ impl FilterChainD3D12 { let compiler: IDxcCompiler = unsafe { DxcCreateInstance(&CLSID_DxcCompiler)? }; Ok::<_, FilterChainError>((validator, library, compiler)) }, - |dxc, (index, ((config, source, mut dxil), - (_, _, mut hlsl)))| { + |dxc, (index, ((((config, source, mut dxil), + (_, _, mut hlsl)), mut texture_heap), mut sampler_heap))| { let Ok((validator, library, compiler)) = dxc else { return Err(FilterChainError::Direct3DOperationError("Could not initialize DXC for thread")); }; @@ -472,48 +474,55 @@ impl FilterChainD3D12 { let uniform_bindings = reflection.meta.create_binding_map(|param| param.offset()); - Ok((reflection, - uniform_bindings, - uniform_storage, - graphics_pipeline, - config, - source)) - - }).collect(); - - let filters: error::Result> = filters.into_iter().collect(); - let filters = filters?; - - // Need to take care of the heaps in a single thread because [;16] is not sized..? - let filters: Vec> = filters - .into_iter() - .zip(work_heaps) - .zip(sampler_work_heaps) - .map( - |( - ( - (reflection, uniform_bindings, uniform_storage, pipeline, config, source), - mut texture_heap, - ), - mut sampler_heap, - )| { let texture_heap = texture_heap.alloc_range()?; let sampler_heap = sampler_heap.alloc_range()?; + Ok(FilterPass { reflection, uniform_bindings, uniform_storage, - pipeline, + pipeline: graphics_pipeline, config, texture_heap, sampler_heap, source, }) - }, - ) - .collect(); + + }).collect(); + let filters: error::Result> = filters.into_iter().collect(); let filters = filters?; + // + // // Need to take care of the heaps in a single thread because [;16] is not sized..? + // let filters: Vec> = filters + // .into_iter() + // .zip(work_heaps) + // .zip(sampler_work_heaps) + // .map( + // |( + // ( + // (reflection, uniform_bindings, uniform_storage, pipeline, config, source), + // mut texture_heap, + // ), + // mut sampler_heap, + // )| { + // let texture_heap = texture_heap.alloc_range()?; + // let sampler_heap = sampler_heap.alloc_range()?; + // Ok(FilterPass { + // reflection, + // uniform_bindings, + // uniform_storage, + // pipeline, + // config, + // texture_heap, + // sampler_heap, + // source, + // }) + // }, + // ) + // .collect(); + // let filters: error::Result> = filters.into_iter().collect(); + // let filters = filters?; // Panic SAFETY: mipmap_heap is always 1024 descriptors. Ok(( diff --git a/librashader-runtime-gl/src/filter_chain/filter_impl.rs b/librashader-runtime-gl/src/filter_chain/filter_impl.rs index 2e0bb7c..1047af6 100644 --- a/librashader-runtime-gl/src/filter_chain/filter_impl.rs +++ b/librashader-runtime-gl/src/filter_chain/filter_impl.rs @@ -261,7 +261,6 @@ impl FilterChainImpl { filters.push(FilterPass { reflection, - compiled: glsl, program, ubo_location, ubo_ring, diff --git a/librashader-runtime-gl/src/filter_pass.rs b/librashader-runtime-gl/src/filter_pass.rs index 785005d..658f3f5 100644 --- a/librashader-runtime-gl/src/filter_pass.rs +++ b/librashader-runtime-gl/src/filter_pass.rs @@ -1,6 +1,4 @@ use gl::types::{GLint, GLsizei, GLuint}; -use librashader_reflect::back::cross::CrossGlslContext; -use librashader_reflect::back::ShaderCompilerOutput; use librashader_reflect::reflect::ShaderReflection; use librashader_common::{ImageFormat, Size, Viewport}; @@ -33,7 +31,6 @@ impl UniformOffset { pub struct FilterPass { pub reflection: ShaderReflection, - pub compiled: ShaderCompilerOutput, pub program: GLuint, pub ubo_location: UniformLocation, pub ubo_ring: Option, diff --git a/librashader-runtime-vk/src/memory.rs b/librashader-runtime-vk/src/memory.rs index d922461..e97459b 100644 --- a/librashader-runtime-vk/src/memory.rs +++ b/librashader-runtime-vk/src/memory.rs @@ -130,8 +130,10 @@ impl Drop for VulkanBuffer { /// SAFETY: Creating the pointer should be safe in multithreaded contexts. /// -/// Mutation is guarded by DerefMut +/// Mutation is guarded by DerefMut, so exclusive access is guaranteed. +/// We do not ever leak the pointer to C. unsafe impl Send for RawVulkanBuffer {} +unsafe impl Sync for RawVulkanBuffer {} pub struct RawVulkanBuffer { buffer: ManuallyDrop, ptr: NonNull, diff --git a/librashader/src/lib.rs b/librashader/src/lib.rs index 2992035..63d45a1 100644 --- a/librashader/src/lib.rs +++ b/librashader/src/lib.rs @@ -26,16 +26,13 @@ //! //! | **API** | **Status** | **`librashader` feature** | //! |-------------|------------|---------------------------| -//! | OpenGL 3.3+ | ✔ | `gl` | -//! | OpenGL 4.6 | ✔ | `gl` | +//! | OpenGL 3.3+ | ✔ | `gl` | +//! | OpenGL 4.6 | ✔ | `gl` | //! | Vulkan | ✔ | `vk` | -//! | Direct3D 11 | ✔ | `d3d11` | -//! | Direct3D 12 | ✔ | `d3d12` | -//! | OpenGL 2 | ❌ | | -//! | Direct3D 9 | ❌ | | -//! | Direct3D 10 | ❌ | | -//! | Metal | ❌ | | -//! +//! | Direct3D 11 | ✔ | `d3d11` | +//! | Direct3D 12 | ✔ | `d3d12` | +//! | Metal | ❌ | | +//! | WebGPU | ❌ | | //! ## C API //! For documentation on the librashader C API, see [librashader-capi](https://docs.rs/librashader-capi/latest/librashader_capi/), //! or [`librashader.h`](https://github.com/SnowflakePowered/librashader/blob/master/include/librashader.h).