From 2e2713a21b6b28655bc8474dab23e0ef2a13c08f Mon Sep 17 00:00:00 2001 From: chyyran Date: Sat, 14 Jan 2023 09:36:26 -0500 Subject: [PATCH] capi: expose FilterChainParameters to capi --- librashader-capi/cbindgen.toml | 12 +++ librashader-capi/src/error.rs | 20 ++-- librashader-capi/src/presets.rs | 8 +- .../src/runtime/d3d11/filter_chain.rs | 89 ++++++++++++++++- .../src/runtime/gl/filter_chain.rs | 87 +++++++++++++++++ .../src/runtime/vk/filter_chain.rs | 96 ++++++++++++++++++- librashader-runtime-d3d11/src/filter_chain.rs | 3 +- .../src/filter_chain/filter_impl.rs | 4 +- librashader-runtime-vk/src/filter_chain.rs | 3 +- 9 files changed, 305 insertions(+), 17 deletions(-) diff --git a/librashader-capi/cbindgen.toml b/librashader-capi/cbindgen.toml index 8797687..f4db13c 100644 --- a/librashader-capi/cbindgen.toml +++ b/librashader-capi/cbindgen.toml @@ -50,16 +50,28 @@ include = [ "PFN_libra_gl_init_context", "PFN_libra_gl_filter_chain_create", "PFN_libra_gl_filter_chain_frame", + "PFN_libra_gl_filter_chain_set_param", + "PFN_libra_gl_filter_chain_get_param", + "PFN_libra_gl_filter_chain_set_active_pass_count", + "PFN_libra_gl_filter_chain_get_active_pass_count", "PFN_libra_gl_filter_chain_free", # d3d11 "PFN_libra_d3d11_filter_chain_create", "PFN_libra_d3d11_filter_chain_frame", + "PFN_libra_d3d11_filter_chain_set_param", + "PFN_libra_d3d11_filter_chain_get_param", + "PFN_libra_d3d11_filter_chain_set_active_pass_count", + "PFN_libra_d3d11_filter_chain_get_active_pass_count", "PFN_libra_d3d11_filter_chain_free", # vulkan "PFN_libra_vk_filter_chain_create", "PFN_libra_vk_filter_chain_frame", + "PFN_libra_vk_filter_chain_set_param", + "PFN_libra_vk_filter_chain_get_param", + "PFN_libra_vk_filter_chain_set_active_pass_count", + "PFN_libra_vk_filter_chain_get_active_pass_count", "PFN_libra_vk_filter_chain_free", ] diff --git a/librashader-capi/src/error.rs b/librashader-capi/src/error.rs index 6fff6c2..a3ebe8e 100644 --- a/librashader-capi/src/error.rs +++ b/librashader-capi/src/error.rs @@ -3,6 +3,7 @@ use std::any::Any; use std::ffi::{c_char, CString}; use std::mem::MaybeUninit; use std::ptr::NonNull; +use std::str::Utf8Error; use thiserror::Error; /// The error type for librashader. @@ -13,8 +14,8 @@ pub enum LibrashaderError { UnknownError(Box), #[error("The parameter was null or invalid.")] InvalidParameter(&'static str), - #[error("The path was invalid.")] - InvalidPath(#[from] std::str::Utf8Error), + #[error("The provided string was not valid UTF8.")] + InvalidString(#[from] std::str::Utf8Error), #[error("There was an error parsing the preset.")] PresetError(#[from] librashader::presets::ParsePresetError), #[error("There was an error preprocessing the shader source.")] @@ -23,6 +24,8 @@ pub enum LibrashaderError { ShaderCompileError(#[from] librashader::reflect::ShaderCompileError), #[error("There was an error reflecting the shader source.")] ShaderReflectError(#[from] librashader::reflect::ShaderReflectError), + #[error("The provided parameter name was invalid.")] + UnknownShaderParameter(*const c_char), #[cfg(feature = "runtime-opengl")] #[error("There was an error in the OpenGL filter chain.")] OpenGlFilterError(#[from] librashader::runtime::gl::error::FilterChainError), @@ -39,10 +42,12 @@ pub enum LibrashaderError { pub enum LIBRA_ERRNO { UNKNOWN_ERROR = 0, INVALID_PARAMETER = 1, - INVALID_PATH = 2, + INVALID_STRING = 2, PRESET_ERROR = 3, PREPROCESS_ERROR = 4, - RUNTIME_ERROR = 5, + SHADER_PARAMETER_ERROR = 5, + REFLECT_ERROR = 6, + RUNTIME_ERROR = 7, } // Nothing here can use extern_fn because they are lower level than libra_error_t. @@ -165,11 +170,14 @@ impl LibrashaderError { match self { LibrashaderError::UnknownError(_) => LIBRA_ERRNO::UNKNOWN_ERROR, LibrashaderError::InvalidParameter(_) => LIBRA_ERRNO::INVALID_PARAMETER, - LibrashaderError::InvalidPath(_) => LIBRA_ERRNO::INVALID_PATH, + LibrashaderError::InvalidString(_) => LIBRA_ERRNO::INVALID_STRING, LibrashaderError::PresetError(_) => LIBRA_ERRNO::PRESET_ERROR, LibrashaderError::PreprocessError(_) => LIBRA_ERRNO::PREPROCESS_ERROR, LibrashaderError::ShaderCompileError(_) | LibrashaderError::ShaderReflectError(_) => { - LIBRA_ERRNO::RUNTIME_ERROR + LIBRA_ERRNO::REFLECT_ERROR + }, + LibrashaderError::UnknownShaderParameter(_) => { + LIBRA_ERRNO::SHADER_PARAMETER_ERROR } #[cfg(feature = "runtime-opengl")] LibrashaderError::OpenGlFilterError(_) => LIBRA_ERRNO::RUNTIME_ERROR, diff --git a/librashader-capi/src/presets.rs b/librashader-capi/src/presets.rs index dc75db2..5ebc4dd 100644 --- a/librashader-capi/src/presets.rs +++ b/librashader-capi/src/presets.rs @@ -117,17 +117,19 @@ extern_fn! { pub type PFN_libra_preset_get_runtime_param_names = unsafe extern "C" fn( preset: *mut libra_shader_preset_t, value: MaybeUninit<*mut *const c_char>, + size: *mut MaybeUninit<*const u64>, ) -> libra_error_t; /// Get a list of runtime parameter names. /// -/// The returned value can not currently be freed. -/// This function should be considered work in progress. Its use is discouraged. -/// Removal of this function is exempted from semantic versioning. +/// The caller must provide a sufficiently sized buffer. +/// ## Safety +/// - `preset` must be null or a valid and aligned pointer to a shader preset. #[no_mangle] pub unsafe extern "C" fn libra_preset_get_runtime_param_names( preset: *mut libra_shader_preset_t, mut value: MaybeUninit<*mut *const c_char>, + mut size: *mut MaybeUninit, ) -> libra_error_t { ffi_body!(|preset| { assert_some_ptr!(preset); diff --git a/librashader-capi/src/runtime/d3d11/filter_chain.rs b/librashader-capi/src/runtime/d3d11/filter_chain.rs index 8347569..50b9693 100644 --- a/librashader-capi/src/runtime/d3d11/filter_chain.rs +++ b/librashader-capi/src/runtime/d3d11/filter_chain.rs @@ -1,3 +1,4 @@ +use std::ffi::CStr; use crate::ctypes::{ libra_d3d11_filter_chain_t, libra_shader_preset_t, libra_viewport_t, }; @@ -6,6 +7,7 @@ use crate::ffi::extern_fn; use librashader::runtime::d3d11::{D3D11InputView, D3D11OutputView}; use std::mem::MaybeUninit; use std::ptr::NonNull; +use std::ffi::c_char; use std::slice; use windows::Win32::Graphics::Direct3D11::{ ID3D11Device, ID3D11RenderTargetView, ID3D11ShaderResourceView, @@ -14,7 +16,7 @@ use windows::Win32::Graphics::Direct3D11::{ pub use librashader::runtime::d3d11::capi::options::FilterChainOptionsD3D11; pub use librashader::runtime::d3d11::capi::options::FrameOptionsD3D11; -use librashader::runtime::{Size, Viewport}; +use librashader::runtime::{FilterChainParameters, Size, Viewport}; /// OpenGL parameters for the source image. #[repr(C)] @@ -134,6 +136,91 @@ extern_fn! { } } +extern_fn! { + /// Sets a parameter for the filter chain. + /// + /// If the parameter does not exist, returns an error. + /// ## Safety + /// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_d3d11_filter_chain_t`. + /// - `param_name` must be either null or a null terminated string. + fn libra_d3d11_filter_chain_set_param( + chain: *mut libra_d3d11_filter_chain_t, + param_name: *const c_char, + value: f32 + ) mut |chain| { + assert_some_ptr!(mut chain); + assert_non_null!(param_name); + unsafe { + let name = CStr::from_ptr(param_name); + let name = name.to_str()?; + + if let None = chain.set_parameter(name, value) { + return LibrashaderError::UnknownShaderParameter(param_name).export() + } + } + } +} + +extern_fn! { + /// Gets a parameter for the filter chain. + /// + /// If the parameter does not exist, returns an error. + /// ## Safety + /// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_d3d11_filter_chain_t`. + /// - `param_name` must be either null or a null terminated string. + fn libra_d3d11_filter_chain_get_param( + chain: *mut libra_d3d11_filter_chain_t, + param_name: *const c_char, + out: *mut MaybeUninit + ) mut |chain| { + assert_some_ptr!(mut chain); + assert_non_null!(param_name); + unsafe { + let name = CStr::from_ptr(param_name); + let name = name.to_str()?; + + let Some(value) = chain.get_parameter(name) else { + return LibrashaderError::UnknownShaderParameter(param_name).export() + }; + + out.write(MaybeUninit::new(value)); + } + } +} + +extern_fn! { + /// Sets the number of active passes for this chain. + /// + /// ## Safety + /// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_d3d11_filter_chain_t`. + fn libra_d3d11_filter_chain_set_active_pass_count( + chain: *mut libra_d3d11_filter_chain_t, + value: u32 + ) mut |chain| { + assert_some_ptr!(mut chain); + unsafe { + chain.set_enabled_pass_count(value as usize); + } + } +} + +extern_fn! { + /// Gets the number of active passes for this chain. + /// + /// ## Safety + /// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_d3d11_filter_chain_t`. + fn libra_d3d11_filter_chain_get_active_pass_count( + chain: *mut libra_d3d11_filter_chain_t, + out: *mut MaybeUninit + ) mut |chain| { + assert_some_ptr!(mut chain); + unsafe { + let value = chain.get_enabled_pass_count(); + out.write(MaybeUninit::new(value as u32)) + } + } +} + extern_fn! { /// Free a D3D11 filter chain. /// diff --git a/librashader-capi/src/runtime/gl/filter_chain.rs b/librashader-capi/src/runtime/gl/filter_chain.rs index f9b2cf2..3a9a382 100644 --- a/librashader-capi/src/runtime/gl/filter_chain.rs +++ b/librashader-capi/src/runtime/gl/filter_chain.rs @@ -8,10 +8,12 @@ use std::ffi::{c_char, c_void, CString}; use std::mem::MaybeUninit; use std::ptr::NonNull; use std::slice; +use std::ffi::CStr; pub use librashader::runtime::gl::capi::options::FilterChainOptionsGL; pub use librashader::runtime::gl::capi::options::FrameOptionsGL; use librashader::runtime::{Size, Viewport}; +use librashader::runtime::FilterChainParameters; /// A GL function loader that librashader needs to be initialized with. pub type libra_gl_loader_t = unsafe extern "system" fn(*const c_char) -> *const c_void; @@ -149,6 +151,91 @@ extern_fn! { } } +extern_fn! { + /// Sets a parameter for the filter chain. + /// + /// If the parameter does not exist, returns an error. + /// ## Safety + /// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_gl_filter_chain_t`. + /// - `param_name` must be either null or a null terminated string. + fn libra_gl_filter_chain_set_param( + chain: *mut libra_gl_filter_chain_t, + param_name: *const c_char, + value: f32 + ) mut |chain| { + assert_some_ptr!(mut chain); + assert_non_null!(param_name); + unsafe { + let name = CStr::from_ptr(param_name); + let name = name.to_str()?; + + if let None = chain.set_parameter(name, value) { + return LibrashaderError::UnknownShaderParameter(param_name).export() + } + } + } +} + +extern_fn! { + /// Gets a parameter for the filter chain. + /// + /// If the parameter does not exist, returns an error. + /// ## Safety + /// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_gl_filter_chain_t`. + /// - `param_name` must be either null or a null terminated string. + fn libra_gl_filter_chain_get_param( + chain: *mut libra_gl_filter_chain_t, + param_name: *const c_char, + out: *mut MaybeUninit + ) mut |chain| { + assert_some_ptr!(mut chain); + assert_non_null!(param_name); + unsafe { + let name = CStr::from_ptr(param_name); + let name = name.to_str()?; + + let Some(value) = chain.get_parameter(name) else { + return LibrashaderError::UnknownShaderParameter(param_name).export() + }; + + out.write(MaybeUninit::new(value)); + } + } +} + +extern_fn! { + /// Sets the number of active passes for this chain. + /// + /// ## Safety + /// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_gl_filter_chain_t`. + fn libra_gl_filter_chain_set_active_pass_count( + chain: *mut libra_gl_filter_chain_t, + value: u32 + ) mut |chain| { + assert_some_ptr!(mut chain); + unsafe { + chain.set_enabled_pass_count(value as usize); + } + } +} + +extern_fn! { + /// Gets the number of active passes for this chain. + /// + /// ## Safety + /// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_gl_filter_chain_t`. + fn libra_gl_filter_chain_get_active_pass_count( + chain: *mut libra_gl_filter_chain_t, + out: *mut MaybeUninit + ) mut |chain| { + assert_some_ptr!(mut chain); + unsafe { + let value = chain.get_enabled_pass_count(); + out.write(MaybeUninit::new(value as u32)) + } + } +} + extern_fn! { /// Free a GL filter chain. /// diff --git a/librashader-capi/src/runtime/vk/filter_chain.rs b/librashader-capi/src/runtime/vk/filter_chain.rs index 8635e48..5f70446 100644 --- a/librashader-capi/src/runtime/vk/filter_chain.rs +++ b/librashader-capi/src/runtime/vk/filter_chain.rs @@ -2,16 +2,18 @@ use std::ffi::{c_char, c_void}; use crate::ctypes::{ libra_vk_filter_chain_t, libra_shader_preset_t, libra_viewport_t, }; -use crate::error::{assert_non_null, assert_some_ptr}; +use crate::error::{assert_non_null, assert_some_ptr, LibrashaderError}; use crate::ffi::extern_fn; use librashader::runtime::vk::{VulkanImage, VulkanInstance}; use std::mem::MaybeUninit; use std::ptr::NonNull; use std::slice; +use std::ffi::CStr; pub use librashader::runtime::vk::capi::options::FilterChainOptionsVulkan; pub use librashader::runtime::vk::capi::options::FrameOptionsVulkan; use librashader::runtime::{Size, Viewport}; +use librashader::runtime::FilterChainParameters; use ash::vk; @@ -128,7 +130,7 @@ extern_fn! { /// function will return an error. /// - `mvp` may be null, or if it is not null, must be an aligned pointer to 16 consecutive `float` /// 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` + /// - `opt` may be null, or if it is not null, must be an aligned pointer to a valid `frame_vk_opt_t` /// struct. fn libra_vk_filter_chain_frame( chain: *mut libra_vk_filter_chain_t, @@ -163,12 +165,98 @@ extern_fn! { } } + extern_fn! { - /// Free a GL filter chain. + /// Sets a parameter for the filter chain. + /// + /// If the parameter does not exist, returns an error. + /// ## Safety + /// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_vk_filter_chain_t`. + /// - `param_name` must be either null or a null terminated string. + fn libra_vk_filter_chain_set_param( + chain: *mut libra_vk_filter_chain_t, + param_name: *const c_char, + value: f32 + ) mut |chain| { + assert_some_ptr!(mut chain); + assert_non_null!(param_name); + unsafe { + let name = CStr::from_ptr(param_name); + let name = name.to_str()?; + + if let None = chain.set_parameter(name, value) { + return LibrashaderError::UnknownShaderParameter(param_name).export() + } + } + } +} + +extern_fn! { + /// Gets a parameter for the filter chain. + /// + /// If the parameter does not exist, returns an error. + /// ## Safety + /// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_vk_filter_chain_t`. + /// - `param_name` must be either null or a null terminated string. + fn libra_vk_filter_chain_get_param( + chain: *mut libra_vk_filter_chain_t, + param_name: *const c_char, + out: *mut MaybeUninit + ) mut |chain| { + assert_some_ptr!(mut chain); + assert_non_null!(param_name); + unsafe { + let name = CStr::from_ptr(param_name); + let name = name.to_str()?; + + let Some(value) = chain.get_parameter(name) else { + return LibrashaderError::UnknownShaderParameter(param_name).export() + }; + + out.write(MaybeUninit::new(value)); + } + } +} + +extern_fn! { + /// Sets the number of active passes for this chain. + /// + /// ## Safety + /// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_vk_filter_chain_t`. + fn libra_vk_filter_chain_set_active_pass_count( + chain: *mut libra_vk_filter_chain_t, + value: u32 + ) mut |chain| { + assert_some_ptr!(mut chain); + unsafe { + chain.set_enabled_pass_count(value as usize); + } + } +} + +extern_fn! { + /// Gets the number of active passes for this chain. + /// + /// ## Safety + /// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_vk_filter_chain_t`. + fn libra_vk_filter_chain_get_active_pass_count( + chain: *mut libra_vk_filter_chain_t, + out: *mut MaybeUninit + ) mut |chain| { + assert_some_ptr!(mut chain); + unsafe { + let value = chain.get_enabled_pass_count(); + out.write(MaybeUninit::new(value as u32)) + } + } +} + +extern_fn! { + /// Free a Vulkan filter chain. /// /// The resulting value in `chain` then becomes null. /// ## Safety - /// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_gl_filter_chain_t`. + /// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_vk_filter_chain_t`. fn libra_vk_filter_chain_free( chain: *mut libra_vk_filter_chain_t ) { diff --git a/librashader-runtime-d3d11/src/filter_chain.rs b/librashader-runtime-d3d11/src/filter_chain.rs index 255be81..e8cf864 100644 --- a/librashader-runtime-d3d11/src/filter_chain.rs +++ b/librashader-runtime-d3d11/src/filter_chain.rs @@ -470,7 +470,8 @@ impl FilterChainD3D11 { frame_count: usize, options: Option<&FrameOptionsD3D11>, ) -> error::Result<()> { - let passes = &mut self.passes[0..self.common.config.passes_enabled]; + let max = std::cmp::min(self.passes.len(), self.common.config.passes_enabled); + let passes = &mut self.passes[0..max]; if let Some(options) = options { if options.clear_history { for framebuffer in &mut self.history_framebuffers { diff --git a/librashader-runtime-gl/src/filter_chain/filter_impl.rs b/librashader-runtime-gl/src/filter_chain/filter_impl.rs index ae7bd49..64f718a 100644 --- a/librashader-runtime-gl/src/filter_chain/filter_impl.rs +++ b/librashader-runtime-gl/src/filter_chain/filter_impl.rs @@ -424,7 +424,9 @@ impl FilterChainImpl { options: Option<&FrameOptionsGL>, ) -> error::Result<()> { // limit number of passes to those enabled. - let passes = &mut self.passes[0..self.common.config.passes_enabled]; + let max = std::cmp::min(self.passes.len(), self.common.config.passes_enabled); + let passes = &mut self.passes[0..max]; + if let Some(options) = options { if options.clear_history { for framebuffer in &self.history_framebuffers { diff --git a/librashader-runtime-vk/src/filter_chain.rs b/librashader-runtime-vk/src/filter_chain.rs index 34a36bf..22bd3e5 100644 --- a/librashader-runtime-vk/src/filter_chain.rs +++ b/librashader-runtime-vk/src/filter_chain.rs @@ -590,7 +590,8 @@ impl FilterChainVulkan { intermediates.dispose(); // limit number of passes to those enabled. - let passes = &mut self.passes[0..self.common.config.passes_enabled]; + let max = std::cmp::min(self.passes.len(), self.common.config.passes_enabled); + let passes = &mut self.passes[0..max]; if let Some(options) = &options { if options.clear_history {