capi: expose FilterChainParameters to capi

This commit is contained in:
chyyran 2023-01-14 09:36:26 -05:00
parent ed2681380f
commit 2e2713a21b
9 changed files with 305 additions and 17 deletions

View file

@ -50,16 +50,28 @@ include = [
"PFN_libra_gl_init_context", "PFN_libra_gl_init_context",
"PFN_libra_gl_filter_chain_create", "PFN_libra_gl_filter_chain_create",
"PFN_libra_gl_filter_chain_frame", "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", "PFN_libra_gl_filter_chain_free",
# d3d11 # d3d11
"PFN_libra_d3d11_filter_chain_create", "PFN_libra_d3d11_filter_chain_create",
"PFN_libra_d3d11_filter_chain_frame", "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", "PFN_libra_d3d11_filter_chain_free",
# vulkan # vulkan
"PFN_libra_vk_filter_chain_create", "PFN_libra_vk_filter_chain_create",
"PFN_libra_vk_filter_chain_frame", "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", "PFN_libra_vk_filter_chain_free",
] ]

View file

@ -3,6 +3,7 @@ use std::any::Any;
use std::ffi::{c_char, CString}; use std::ffi::{c_char, CString};
use std::mem::MaybeUninit; use std::mem::MaybeUninit;
use std::ptr::NonNull; use std::ptr::NonNull;
use std::str::Utf8Error;
use thiserror::Error; use thiserror::Error;
/// The error type for librashader. /// The error type for librashader.
@ -13,8 +14,8 @@ pub enum LibrashaderError {
UnknownError(Box<dyn Any + Send + 'static>), UnknownError(Box<dyn Any + Send + 'static>),
#[error("The parameter was null or invalid.")] #[error("The parameter was null or invalid.")]
InvalidParameter(&'static str), InvalidParameter(&'static str),
#[error("The path was invalid.")] #[error("The provided string was not valid UTF8.")]
InvalidPath(#[from] std::str::Utf8Error), InvalidString(#[from] std::str::Utf8Error),
#[error("There was an error parsing the preset.")] #[error("There was an error parsing the preset.")]
PresetError(#[from] librashader::presets::ParsePresetError), PresetError(#[from] librashader::presets::ParsePresetError),
#[error("There was an error preprocessing the shader source.")] #[error("There was an error preprocessing the shader source.")]
@ -23,6 +24,8 @@ pub enum LibrashaderError {
ShaderCompileError(#[from] librashader::reflect::ShaderCompileError), ShaderCompileError(#[from] librashader::reflect::ShaderCompileError),
#[error("There was an error reflecting the shader source.")] #[error("There was an error reflecting the shader source.")]
ShaderReflectError(#[from] librashader::reflect::ShaderReflectError), ShaderReflectError(#[from] librashader::reflect::ShaderReflectError),
#[error("The provided parameter name was invalid.")]
UnknownShaderParameter(*const c_char),
#[cfg(feature = "runtime-opengl")] #[cfg(feature = "runtime-opengl")]
#[error("There was an error in the OpenGL filter chain.")] #[error("There was an error in the OpenGL filter chain.")]
OpenGlFilterError(#[from] librashader::runtime::gl::error::FilterChainError), OpenGlFilterError(#[from] librashader::runtime::gl::error::FilterChainError),
@ -39,10 +42,12 @@ pub enum LibrashaderError {
pub enum LIBRA_ERRNO { pub enum LIBRA_ERRNO {
UNKNOWN_ERROR = 0, UNKNOWN_ERROR = 0,
INVALID_PARAMETER = 1, INVALID_PARAMETER = 1,
INVALID_PATH = 2, INVALID_STRING = 2,
PRESET_ERROR = 3, PRESET_ERROR = 3,
PREPROCESS_ERROR = 4, 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. // Nothing here can use extern_fn because they are lower level than libra_error_t.
@ -165,11 +170,14 @@ impl LibrashaderError {
match self { match self {
LibrashaderError::UnknownError(_) => LIBRA_ERRNO::UNKNOWN_ERROR, LibrashaderError::UnknownError(_) => LIBRA_ERRNO::UNKNOWN_ERROR,
LibrashaderError::InvalidParameter(_) => LIBRA_ERRNO::INVALID_PARAMETER, 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::PresetError(_) => LIBRA_ERRNO::PRESET_ERROR,
LibrashaderError::PreprocessError(_) => LIBRA_ERRNO::PREPROCESS_ERROR, LibrashaderError::PreprocessError(_) => LIBRA_ERRNO::PREPROCESS_ERROR,
LibrashaderError::ShaderCompileError(_) | LibrashaderError::ShaderReflectError(_) => { LibrashaderError::ShaderCompileError(_) | LibrashaderError::ShaderReflectError(_) => {
LIBRA_ERRNO::RUNTIME_ERROR LIBRA_ERRNO::REFLECT_ERROR
},
LibrashaderError::UnknownShaderParameter(_) => {
LIBRA_ERRNO::SHADER_PARAMETER_ERROR
} }
#[cfg(feature = "runtime-opengl")] #[cfg(feature = "runtime-opengl")]
LibrashaderError::OpenGlFilterError(_) => LIBRA_ERRNO::RUNTIME_ERROR, LibrashaderError::OpenGlFilterError(_) => LIBRA_ERRNO::RUNTIME_ERROR,

View file

@ -117,17 +117,19 @@ extern_fn! {
pub type PFN_libra_preset_get_runtime_param_names = unsafe extern "C" fn( pub type PFN_libra_preset_get_runtime_param_names = unsafe extern "C" fn(
preset: *mut libra_shader_preset_t, preset: *mut libra_shader_preset_t,
value: MaybeUninit<*mut *const c_char>, value: MaybeUninit<*mut *const c_char>,
size: *mut MaybeUninit<*const u64>,
) -> libra_error_t; ) -> libra_error_t;
/// Get a list of runtime parameter names. /// Get a list of runtime parameter names.
/// ///
/// The returned value can not currently be freed. /// The caller must provide a sufficiently sized buffer.
/// This function should be considered work in progress. Its use is discouraged. /// ## Safety
/// Removal of this function is exempted from semantic versioning. /// - `preset` must be null or a valid and aligned pointer to a shader preset.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn libra_preset_get_runtime_param_names( pub unsafe extern "C" fn libra_preset_get_runtime_param_names(
preset: *mut libra_shader_preset_t, preset: *mut libra_shader_preset_t,
mut value: MaybeUninit<*mut *const c_char>, mut value: MaybeUninit<*mut *const c_char>,
mut size: *mut MaybeUninit<u64>,
) -> libra_error_t { ) -> libra_error_t {
ffi_body!(|preset| { ffi_body!(|preset| {
assert_some_ptr!(preset); assert_some_ptr!(preset);

View file

@ -1,3 +1,4 @@
use std::ffi::CStr;
use crate::ctypes::{ use crate::ctypes::{
libra_d3d11_filter_chain_t, libra_shader_preset_t, libra_viewport_t, 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 librashader::runtime::d3d11::{D3D11InputView, D3D11OutputView};
use std::mem::MaybeUninit; use std::mem::MaybeUninit;
use std::ptr::NonNull; use std::ptr::NonNull;
use std::ffi::c_char;
use std::slice; use std::slice;
use windows::Win32::Graphics::Direct3D11::{ use windows::Win32::Graphics::Direct3D11::{
ID3D11Device, ID3D11RenderTargetView, ID3D11ShaderResourceView, 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::FilterChainOptionsD3D11;
pub use librashader::runtime::d3d11::capi::options::FrameOptionsD3D11; 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. /// OpenGL parameters for the source image.
#[repr(C)] #[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<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()?;
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<u32>
) mut |chain| {
assert_some_ptr!(mut chain);
unsafe {
let value = chain.get_enabled_pass_count();
out.write(MaybeUninit::new(value as u32))
}
}
}
extern_fn! { extern_fn! {
/// Free a D3D11 filter chain. /// Free a D3D11 filter chain.
/// ///

View file

@ -8,10 +8,12 @@ use std::ffi::{c_char, c_void, CString};
use std::mem::MaybeUninit; use std::mem::MaybeUninit;
use std::ptr::NonNull; use std::ptr::NonNull;
use std::slice; use std::slice;
use std::ffi::CStr;
pub use librashader::runtime::gl::capi::options::FilterChainOptionsGL; pub use librashader::runtime::gl::capi::options::FilterChainOptionsGL;
pub use librashader::runtime::gl::capi::options::FrameOptionsGL; pub use librashader::runtime::gl::capi::options::FrameOptionsGL;
use librashader::runtime::{Size, Viewport}; use librashader::runtime::{Size, Viewport};
use librashader::runtime::FilterChainParameters;
/// A GL function loader that librashader needs to be initialized with. /// 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; 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<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()?;
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<u32>
) mut |chain| {
assert_some_ptr!(mut chain);
unsafe {
let value = chain.get_enabled_pass_count();
out.write(MaybeUninit::new(value as u32))
}
}
}
extern_fn! { extern_fn! {
/// Free a GL filter chain. /// Free a GL filter chain.
/// ///

View file

@ -2,16 +2,18 @@ use std::ffi::{c_char, c_void};
use crate::ctypes::{ use crate::ctypes::{
libra_vk_filter_chain_t, libra_shader_preset_t, libra_viewport_t, 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 crate::ffi::extern_fn;
use librashader::runtime::vk::{VulkanImage, VulkanInstance}; use librashader::runtime::vk::{VulkanImage, VulkanInstance};
use std::mem::MaybeUninit; use std::mem::MaybeUninit;
use std::ptr::NonNull; use std::ptr::NonNull;
use std::slice; use std::slice;
use std::ffi::CStr;
pub use librashader::runtime::vk::capi::options::FilterChainOptionsVulkan; pub use librashader::runtime::vk::capi::options::FilterChainOptionsVulkan;
pub use librashader::runtime::vk::capi::options::FrameOptionsVulkan; pub use librashader::runtime::vk::capi::options::FrameOptionsVulkan;
use librashader::runtime::{Size, Viewport}; use librashader::runtime::{Size, Viewport};
use librashader::runtime::FilterChainParameters;
use ash::vk; use ash::vk;
@ -128,7 +130,7 @@ extern_fn! {
/// function will return an error. /// function will return an error.
/// - `mvp` may be null, or if it is not null, must be an aligned pointer to 16 consecutive `float` /// - `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. /// 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. /// struct.
fn libra_vk_filter_chain_frame( fn libra_vk_filter_chain_frame(
chain: *mut libra_vk_filter_chain_t, chain: *mut libra_vk_filter_chain_t,
@ -163,12 +165,98 @@ extern_fn! {
} }
} }
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<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()?;
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<u32>
) 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. /// The resulting value in `chain` then becomes null.
/// ## Safety /// ## 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( fn libra_vk_filter_chain_free(
chain: *mut libra_vk_filter_chain_t chain: *mut libra_vk_filter_chain_t
) { ) {

View file

@ -470,7 +470,8 @@ impl FilterChainD3D11 {
frame_count: usize, frame_count: usize,
options: Option<&FrameOptionsD3D11>, options: Option<&FrameOptionsD3D11>,
) -> error::Result<()> { ) -> 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 let Some(options) = options {
if options.clear_history { if options.clear_history {
for framebuffer in &mut self.history_framebuffers { for framebuffer in &mut self.history_framebuffers {

View file

@ -424,7 +424,9 @@ impl<T: GLInterface> FilterChainImpl<T> {
options: Option<&FrameOptionsGL>, options: Option<&FrameOptionsGL>,
) -> error::Result<()> { ) -> error::Result<()> {
// limit number of passes to those enabled. // 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 let Some(options) = options {
if options.clear_history { if options.clear_history {
for framebuffer in &self.history_framebuffers { for framebuffer in &self.history_framebuffers {

View file

@ -590,7 +590,8 @@ impl FilterChainVulkan {
intermediates.dispose(); intermediates.dispose();
// limit number of passes to those enabled. // 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 let Some(options) = &options {
if options.clear_history { if options.clear_history {