capi: make _opt* structs more forwards compatible

yay another abi break 🙃
hopefully for the last time
This commit is contained in:
chyyran 2023-02-09 23:36:09 -05:00
parent 121209da10
commit 2b250db353
17 changed files with 338 additions and 82 deletions

View file

@ -62,21 +62,11 @@ cargo post build --release --package librashader-capi
This will output a `librashader.dll` or `librashader.so` in the target folder.
### C ABI Compatibility
The recommended way of integrating `librashader` is by the `librashader_ld` single header library, ABI stability
As the recommended way of integrating `librashader` is by the `librashader_ld` single header library, ABI stability
is important to ensure that updates to librashader do not break existing consumers.
Pre-1.0, nothing is guaranteed to be stable, but the following APIs are unlikely to change their ABI unless otherwise indicated.
* `libra_preset_*`
* `libra_error_*`
The following APIs, mostly runtime, are more likely to change their ABI before a 1.0 release as I experiment with what
works best.
* `libra_gl_*`
* `libra_vk_*`
* `libra_d3d11_*`
* `libra_d3d12_*`
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/)
@ -109,6 +99,7 @@ Please report an issue if you run into a shader that works in RetroArch, but not
* For performance reasons, mipmaps are never generated for the input texture. In theory, this means that
presets with `mipmap_input0 = "true"` will not get a mipmapped input. In practice, no known shader presets set
`mipmap_input0 = "true"`.
### Runtime specific differences
* OpenGL
* Copying of in-flight framebuffer contents to history is done via `glBlitFramebuffer` rather than drawing a quad into an intermediate FBO.

View file

@ -138,15 +138,21 @@ typedef struct libra_preset_param_list_t {
typedef const void *(*libra_gl_loader_t)(const char*);
#endif
typedef size_t LIBRASHADER_API_VERSION;
#if defined(LIBRA_RUNTIME_OPENGL)
/// Options for filter chain creation.
typedef struct filter_chain_gl_opt_t {
/// The librashader API version.
LIBRASHADER_API_VERSION version;
/// The GLSL version. Should be at least `330`.
uint16_t gl_version;
uint16_t glsl_version;
/// Whether or not to use the Direct State Access APIs. Only available on OpenGL 4.5+.
bool use_dsa;
/// Whether or not to explicitly disable mipmap generation regardless of shader preset settings.
bool force_no_mipmaps;
} filter_chain_gl_opt_t;
#endif
#if defined(LIBRA_RUNTIME_OPENGL)
/// A handle to a OpenGL filter chain.
@ -191,14 +197,18 @@ typedef struct libra_output_framebuffer_gl_t {
} libra_output_framebuffer_gl_t;
#endif
#if defined(LIBRA_RUNTIME_OPENGL)
/// Options for each OpenGL shader frame.
typedef struct frame_gl_opt_t {
/// The librashader API version.
LIBRASHADER_API_VERSION version;
/// Whether or not to clear the history buffers.
bool clear_history;
/// The direction of rendering.
/// -1 indicates that the frames are played in reverse order.
int32_t frame_direction;
} frame_gl_opt_t;
#endif
#if defined(LIBRA_RUNTIME_VULKAN)
/// Handles required to instantiate vulkan
@ -217,8 +227,11 @@ typedef struct libra_device_vk_t {
} libra_device_vk_t;
#endif
#if defined(LIBRA_RUNTIME_VULKAN)
/// Options for filter chain creation.
typedef struct filter_chain_vk_opt_t {
/// The librashader API version.
size_t version;
/// The number of frames in flight to keep. If zero, defaults to three.
uint32_t frames_in_flight;
/// Whether or not to explicitly disable mipmap generation regardless of shader preset settings.
@ -227,6 +240,7 @@ typedef struct filter_chain_vk_opt_t {
/// because render-pass mode will create new framebuffers per pass.
bool use_render_pass;
} filter_chain_vk_opt_t;
#endif
#if defined(LIBRA_RUNTIME_VULKAN)
/// A handle to a Vulkan filter chain.
@ -257,17 +271,24 @@ typedef struct libra_output_image_vk_t {
} libra_output_image_vk_t;
#endif
/// Options for each Vulkan shader frame.
#if defined(LIBRA_RUNTIME_VULKAN)
/// Options for each OpenGL shader frame.
typedef struct frame_vk_opt_t {
/// The librashader API version.
size_t version;
/// Whether or not to clear the history buffers.
bool clear_history;
/// The direction of rendering.
/// -1 indicates that the frames are played in reverse order.
int32_t frame_direction;
} frame_vk_opt_t;
#endif
/// Options for Direct3D11 filter chain creation.
#if defined(LIBRA_RUNTIME_D3D11)
/// Options for Direct3D 11 filter chain creation.
typedef struct filter_chain_d3d11_opt_t {
/// The librashader API version.
LIBRASHADER_API_VERSION version;
/// Use a deferred context to record shader rendering state.
///
/// The deferred context will be executed on the immediate context
@ -277,6 +298,7 @@ typedef struct filter_chain_d3d11_opt_t {
/// generation regardless of shader preset settings.
bool force_no_mipmaps;
} filter_chain_d3d11_opt_t;
#endif
#if defined(LIBRA_RUNTIME_D3D11)
/// A handle to a Direct3D 11 filter chain.
@ -295,17 +317,24 @@ typedef struct libra_source_image_d3d11_t {
} libra_source_image_d3d11_t;
#endif
/// Options for each Direct3D11 shader frame.
#if defined(LIBRA_RUNTIME_D3D11)
/// Options for each Direct3D 11 shader frame.
typedef struct frame_d3d11_opt_t {
/// The librashader API version.
LIBRASHADER_API_VERSION version;
/// Whether or not to clear the history buffers.
bool clear_history;
/// The direction of rendering.
/// -1 indicates that the frames are played in reverse order.
int32_t frame_direction;
} frame_d3d11_opt_t;
#endif
#if defined(LIBRA_RUNTIME_D3D12)
/// Options for Direct3D11 filter chain creation.
typedef struct filter_chain_d3d12_opt_t {
/// The librashader API version.
LIBRASHADER_API_VERSION version;
/// Force the HLSL shader pipeline. This may reduce shader compatibility.
bool force_hlsl_pipeline;
/// Whether or not to explicitly disable mipmap
@ -313,6 +342,7 @@ typedef struct filter_chain_d3d12_opt_t {
/// of shader preset settings.
bool force_no_mipmaps;
} filter_chain_d3d12_opt_t;
#endif
#if defined(LIBRA_RUNTIME_D3D12)
/// A handle to a Direct3D 12 filter chain.
@ -345,14 +375,18 @@ typedef struct libra_output_image_d3d12_t {
} libra_output_image_d3d12_t;
#endif
/// Options for each Direct3D11 shader frame.
#if defined(LIBRA_RUNTIME_D3D12)
/// Options for each Direct3D 12 shader frame.
typedef struct frame_d3d12_opt_t {
/// The librashader API version.
LIBRASHADER_API_VERSION version;
/// Whether or not to clear the history buffers.
bool clear_history;
/// The direction of rendering.
/// -1 indicates that the frames are played in reverse order.
int32_t frame_direction;
} frame_d3d12_opt_t;
#endif
/// Function pointer definition for
///libra_preset_create
@ -583,7 +617,7 @@ typedef libra_error_t (*PFN_libra_d3d11_filter_chain_free)(libra_d3d11_filter_ch
/// Function pointer definition for
///libra_d3d12_filter_chain_create
typedef libra_error_t (*PFN_libra_d3d12_filter_chain_create)(libra_shader_preset_t *preset,
const struct filter_chain_d3d12_opt_t *options,
const struct filter_chain_d3d12_opt_t *opt,
const ID3D12Device * device,
libra_d3d12_filter_chain_t *out);
#endif
@ -598,7 +632,7 @@ typedef libra_error_t (*PFN_libra_d3d12_filter_chain_frame)(libra_d3d12_filter_c
struct libra_viewport_t viewport,
struct libra_output_image_d3d12_t out,
const float *mvp,
const struct frame_d3d12_opt_t *opt);
const struct frame_d3d12_opt_t *options);
#endif
#if defined(LIBRA_RUNTIME_D3D12)
@ -637,6 +671,10 @@ typedef libra_error_t (*PFN_libra_d3d12_filter_chain_get_active_pass_count)(libr
typedef libra_error_t (*PFN_libra_d3d12_filter_chain_free)(libra_d3d12_filter_chain_t *chain);
#endif
/// The current version of the librashader API/ABI.
/// Pass this into `version` for config structs.
#define LIBRASHADER_CURRENT_VERSION 0
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
@ -1049,7 +1087,7 @@ libra_error_t libra_d3d11_filter_chain_free(libra_d3d11_filter_chain_t *chain);
/// - `device` must not be null.
/// - `out` must be aligned, but may be null, invalid, or uninitialized.
libra_error_t libra_d3d12_filter_chain_create(libra_shader_preset_t *preset,
const struct filter_chain_d3d12_opt_t *options,
const struct filter_chain_d3d12_opt_t *opt,
const ID3D12Device * device,
libra_d3d12_filter_chain_t *out);
#endif
@ -1075,7 +1113,7 @@ libra_error_t libra_d3d12_filter_chain_frame(libra_d3d12_filter_chain_t *chain,
struct libra_viewport_t viewport,
struct libra_output_image_d3d12_t out,
const float *mvp,
const struct frame_d3d12_opt_t *opt);
const struct frame_d3d12_opt_t *options);
#endif
#if defined(LIBRA_RUNTIME_D3D12)

View file

@ -144,17 +144,9 @@ include = [
"LibrashaderError" = "_libra_error"
"ShaderPreset" = "_shader_preset"
"FilterChainGL" = "_filter_chain_gl"
"FilterChainOptionsGL" = "filter_chain_gl_opt_t"
"FrameOptionsGL" = "frame_gl_opt_t"
"FilterChainVulkan" = "_filter_chain_vk"
"FilterChainOptionsVulkan" = "filter_chain_vk_opt_t"
"FrameOptionsVulkan" = "frame_vk_opt_t"
"FilterChainD3D11" = "_filter_chain_d3d11"
"FilterChainOptionsD3D11" = "filter_chain_d3d11_opt_t"
"FrameOptionsD3D11" = "frame_d3d11_opt_t"
"FilterChainD3D12" = "_filter_chain_d3d12"
"FilterChainOptionsD3D12" = "filter_chain_d3d12_opt_t"
"FrameOptionsD3D12" = "frame_d3d12_opt_t"
# vulkan renames
"PhysicalDevice" = "VkPhysicalDevice"

View file

@ -1,6 +1,7 @@
//! Binding types for the librashader C API.
use crate::error::LibrashaderError;
use librashader::presets::ShaderPreset;
use std::mem::MaybeUninit;
use std::ptr::NonNull;
/// A handle to a shader preset object.
@ -44,3 +45,45 @@ pub struct libra_viewport_t {
/// The height of the viewport framebuffer.
pub height: u32,
}
pub(crate) trait FromUninit<T>
where
Self: Sized,
{
fn from_uninit(value: MaybeUninit<Self>) -> T;
}
macro_rules! config_set_field {
($options:ident.$field:ident <- $ptr:ident) => {
$options.$field = unsafe { ::std::ptr::addr_of!((*$ptr).$field).read() };
};
}
macro_rules! config_version_set {
($version:literal => [$($field:ident),+ $(,)?] ($options:ident <- $ptr:ident)) => {
let version = unsafe { ::std::ptr::addr_of!((*$ptr).version).read() };
#[allow(unused_comparisons)]
if version >= $version {
$($crate::ctypes::config_set_field!($options.$field <- $ptr);)+
}
}
}
macro_rules! config_struct {
(impl $rust:ty => $capi:ty {$($version:literal => [$($field:ident),+ $(,)?]);+ $(;)?}) => {
impl $crate::ctypes::FromUninit<$rust> for $capi {
fn from_uninit(value: ::std::mem::MaybeUninit<Self>) -> $rust {
let ptr = value.as_ptr();
let mut options = <$rust>::default();
$(
$crate::ctypes::config_version_set!($version => [$($field),+] (options <- ptr));
)+
options
}
}
}
}
pub(crate) use config_set_field;
pub(crate) use config_struct;
pub(crate) use config_version_set;

View file

@ -58,7 +58,7 @@ macro_rules! ffi_body {
}
macro_rules! extern_fn {
($(#[$($attrss:tt)*])* fn $func_name:ident ($($arg_name:ident : $arg_ty:ty),*) $body:block) => {
($(#[$($attrss:tt)*])* fn $func_name:ident ($($arg_name:ident : $arg_ty:ty),* $(,)?) $body:block) => {
::paste::paste! {
/// Function pointer definition for
#[doc = ::std::stringify!($func_name)]
@ -72,11 +72,11 @@ macro_rules! extern_fn {
}
};
($(#[$($attrss:tt)*])* raw fn $func_name:ident ($($arg_name:ident : $arg_ty:ty),*) $body:block) => {
($(#[$($attrss:tt)*])* raw fn $func_name:ident ($($arg_name:ident : $arg_ty:ty),* $(,)?) $body:block) => {
::paste::paste! {
/// Function pointer definition for
#[doc = ::std::stringify!($func_name)]
pub type [<PFN_ $func_name>] = unsafe extern "C" fn($($arg_name: $arg_ty,)*) -> $crate::ctypes::libra_error_t;
pub type [<PFN_ $func_name>] = unsafe extern "C" fn($($arg_name: $arg_ty,)* ) -> $crate::ctypes::libra_error_t;
}
#[no_mangle]
@ -86,7 +86,7 @@ macro_rules! extern_fn {
}
};
($(#[$($attrss:tt)*])* fn $func_name:ident ($($arg_name:ident : $arg_ty:ty),*) |$($ref_capture:ident),*|; mut |$($mut_capture:ident),*| $body:block) => {
($(#[$($attrss:tt)*])* fn $func_name:ident ($($arg_name:ident : $arg_ty:ty),* $(,)?) |$($ref_capture:ident),*|; mut |$($mut_capture:ident),*| $body:block) => {
::paste::paste! {
/// Function pointer definition for
#[doc = ::std::stringify!($func_name)]
@ -100,7 +100,7 @@ macro_rules! extern_fn {
}
};
($(#[$($attrss:tt)*])* fn $func_name:ident ($($arg_name:ident : $arg_ty:ty),*) mut |$($mut_capture:ident),*| $body:block) => {
($(#[$($attrss:tt)*])* fn $func_name:ident ($($arg_name:ident : $arg_ty:ty),* $(,)?) mut |$($mut_capture:ident),*| $body:block) => {
::paste::paste! {
/// Function pointer definition for
#[doc = ::std::stringify!($func_name)]
@ -113,7 +113,7 @@ macro_rules! extern_fn {
$crate::ffi::ffi_body!(mut |$($mut_capture),*| $body)
}
};
($(#[$($attrss:tt)*])* fn $func_name:ident ($($arg_name:ident : $arg_ty:ty),*) |$($ref_capture:ident),*| $body:block) => {
($(#[$($attrss:tt)*])* fn $func_name:ident ($($arg_name:ident : $arg_ty:ty),* $(,)?) |$($ref_capture:ident),*| $body:block) => {
::paste::paste! {
/// Function pointer definition for
#[doc = ::std::stringify!($func_name)]

View file

@ -67,3 +67,9 @@ pub mod presets;
pub mod reflect;
pub mod runtime;
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;

View file

@ -1,4 +1,6 @@
use crate::ctypes::{libra_d3d11_filter_chain_t, libra_shader_preset_t, libra_viewport_t};
use crate::ctypes::{
config_struct, libra_d3d11_filter_chain_t, libra_shader_preset_t, libra_viewport_t, FromUninit,
};
use crate::error::{assert_non_null, assert_some_ptr, LibrashaderError};
use crate::ffi::extern_fn;
use librashader::runtime::d3d11::{D3D11InputView, D3D11OutputView};
@ -15,6 +17,7 @@ pub use librashader::runtime::d3d11::capi::options::FilterChainOptionsD3D11;
pub use librashader::runtime::d3d11::capi::options::FrameOptionsD3D11;
use librashader::runtime::{FilterChainParameters, Size, Viewport};
use crate::LIBRASHADER_API_VERSION;
/// Direct3D 11 parameters for the source image.
#[repr(C)]
@ -40,6 +43,48 @@ impl TryFrom<libra_source_image_d3d11_t> for D3D11InputView {
}
}
/// Options for Direct3D 11 filter chain creation.
#[repr(C)]
#[derive(Default, Debug, Clone)]
pub struct filter_chain_d3d11_opt_t {
/// The librashader API version.
pub version: LIBRASHADER_API_VERSION,
/// Use a deferred context to record shader rendering state.
///
/// The deferred context will be executed on the immediate context
/// with `RenderContextState = true`.
pub use_deferred_context: bool,
/// Whether or not to explicitly disable mipmap
/// generation regardless of shader preset settings.
pub force_no_mipmaps: bool,
}
config_struct! {
impl FilterChainOptionsD3D11 => filter_chain_d3d11_opt_t {
0 => [use_deferred_context, force_no_mipmaps];
}
}
/// Options for each Direct3D 11 shader frame.
#[repr(C)]
#[derive(Default, Debug, Clone)]
pub struct frame_d3d11_opt_t {
/// The librashader API version.
pub version: LIBRASHADER_API_VERSION,
/// Whether or not to clear the history buffers.
pub clear_history: bool,
/// The direction of rendering.
/// -1 indicates that the frames are played in reverse order.
pub frame_direction: i32,
}
config_struct! {
impl FrameOptionsD3D11 => frame_d3d11_opt_t {
0 => [clear_history, frame_direction];
}
}
extern_fn! {
/// Create the filter chain given the shader preset.
///
@ -53,7 +98,7 @@ extern_fn! {
/// - `out` must be aligned, but may be null, invalid, or uninitialized.
fn libra_d3d11_filter_chain_create(
preset: *mut libra_shader_preset_t,
options: *const FilterChainOptionsD3D11,
options: *const MaybeUninit<filter_chain_d3d11_opt_t>,
device: ManuallyDrop<ID3D11Device>,
out: *mut MaybeUninit<libra_d3d11_filter_chain_t>
) {
@ -67,13 +112,14 @@ extern_fn! {
let options = if options.is_null() {
None
} else {
Some(unsafe { &*options })
Some(unsafe { options.read() })
};
let options = options.map(FromUninit::from_uninit);
let chain = librashader::runtime::d3d11::capi::FilterChainD3D11::load_from_preset(
&device,
*preset,
options,
options.as_ref(),
)?;
unsafe {
@ -103,7 +149,7 @@ extern_fn! {
viewport: libra_viewport_t,
out: ManuallyDrop<ID3D11RenderTargetView>,
mvp: *const f32,
opt: *const FrameOptionsD3D11
opt: *const MaybeUninit<frame_d3d11_opt_t>
) mut |chain| {
assert_some_ptr!(mut chain);
@ -129,6 +175,8 @@ extern_fn! {
mvp,
};
let opt = opt.map(FromUninit::from_uninit);
let image = image.try_into()?;
chain.frame(image, &viewport, frame_count, opt.as_ref())?;
}

View file

@ -1,4 +1,6 @@
use crate::ctypes::{libra_d3d12_filter_chain_t, libra_shader_preset_t, libra_viewport_t};
use crate::ctypes::{
config_struct, libra_d3d12_filter_chain_t, libra_shader_preset_t, libra_viewport_t, FromUninit,
};
use crate::error::{assert_non_null, assert_some_ptr, LibrashaderError};
use crate::ffi::extern_fn;
use std::ffi::c_char;
@ -16,6 +18,7 @@ pub use librashader::runtime::d3d12::capi::options::FrameOptionsD3D12;
use librashader::runtime::d3d12::{D3D12InputImage, D3D12OutputView};
use librashader::runtime::{FilterChainParameters, Size, Viewport};
use crate::LIBRASHADER_API_VERSION;
/// Direct3D 12 parameters for the source image.
#[repr(C)]
@ -41,6 +44,47 @@ pub struct libra_output_image_d3d12_t {
pub format: DXGI_FORMAT,
}
/// Options for each Direct3D 12 shader frame.
#[repr(C)]
#[derive(Default, Debug, Clone)]
pub struct frame_d3d12_opt_t {
/// The librashader API version.
pub version: LIBRASHADER_API_VERSION,
/// Whether or not to clear the history buffers.
pub clear_history: bool,
/// The direction of rendering.
/// -1 indicates that the frames are played in reverse order.
pub frame_direction: i32,
}
config_struct! {
impl FrameOptionsD3D12 => frame_d3d12_opt_t {
0 => [clear_history, frame_direction];
}
}
/// Options for Direct3D11 filter chain creation.
#[repr(C)]
#[derive(Default, Debug, Clone)]
pub struct filter_chain_d3d12_opt_t {
/// The librashader API version.
pub version: LIBRASHADER_API_VERSION,
/// Force the HLSL shader pipeline. This may reduce shader compatibility.
pub force_hlsl_pipeline: bool,
/// Whether or not to explicitly disable mipmap
/// generation for intermediate passes regardless
/// of shader preset settings.
pub force_no_mipmaps: bool,
}
config_struct! {
impl FilterChainOptionsD3D12 => filter_chain_d3d12_opt_t {
0 => [force_hlsl_pipeline, force_no_mipmaps];
}
}
impl TryFrom<libra_source_image_d3d12_t> for D3D12InputImage {
type Error = LibrashaderError;
@ -69,7 +113,7 @@ extern_fn! {
/// - `out` must be aligned, but may be null, invalid, or uninitialized.
fn libra_d3d12_filter_chain_create(
preset: *mut libra_shader_preset_t,
options: *const FilterChainOptionsD3D12,
opt: *const MaybeUninit<filter_chain_d3d12_opt_t>,
device: ManuallyDrop<ID3D12Device>,
out: *mut MaybeUninit<libra_d3d12_filter_chain_t>
) {
@ -80,16 +124,17 @@ extern_fn! {
Box::from_raw(preset.unwrap().as_ptr())
};
let options = if options.is_null() {
let opt = if opt.is_null() {
None
} else {
Some(unsafe { &*options })
Some(unsafe { opt.read() })
};
let opt = opt.map(FromUninit::from_uninit);
let chain = librashader::runtime::d3d12::capi::FilterChainD3D12::load_from_preset(
&device,
*preset,
options,
opt.as_ref(),
)?;
unsafe {
@ -122,7 +167,7 @@ extern_fn! {
viewport: libra_viewport_t,
out: libra_output_image_d3d12_t,
mvp: *const f32,
opt: *const FrameOptionsD3D12
options: *const MaybeUninit<frame_d3d12_opt_t>
) mut |chain| {
assert_some_ptr!(mut chain);
@ -132,12 +177,13 @@ extern_fn! {
Some(<&[f32; 16]>::try_from(unsafe { slice::from_raw_parts(mvp, 16) }).unwrap())
};
let opt = if opt.is_null() {
let options = if options.is_null() {
None
} else {
Some(unsafe { opt.read() })
Some(unsafe { options.read() })
};
let options = options.map(FromUninit::from_uninit);
let viewport = Viewport {
x: viewport.x,
y: viewport.y,
@ -146,7 +192,7 @@ extern_fn! {
};
let image = image.try_into()?;
chain.frame(&command_list, image, &viewport, frame_count, opt.as_ref())?;
chain.frame(&command_list, image, &viewport, frame_count, options.as_ref())?;
}
}

View file

@ -1,4 +1,6 @@
use crate::ctypes::{libra_gl_filter_chain_t, libra_shader_preset_t, libra_viewport_t};
use crate::ctypes::{
config_struct, libra_gl_filter_chain_t, libra_shader_preset_t, libra_viewport_t, FromUninit,
};
use crate::error::{assert_non_null, assert_some_ptr, LibrashaderError};
use crate::ffi::extern_fn;
use librashader::runtime::gl::{Framebuffer, GLImage};
@ -12,6 +14,7 @@ pub use librashader::runtime::gl::capi::options::FilterChainOptionsGL;
pub use librashader::runtime::gl::capi::options::FrameOptionsGL;
use librashader::runtime::FilterChainParameters;
use librashader::runtime::{Size, Viewport};
use crate::LIBRASHADER_API_VERSION;
/// 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;
@ -51,6 +54,45 @@ impl From<libra_source_image_gl_t> for GLImage {
}
}
/// Options for each OpenGL shader frame.
#[repr(C)]
#[derive(Default, Debug, Clone)]
pub struct frame_gl_opt_t {
/// The librashader API version.
pub version: LIBRASHADER_API_VERSION,
/// Whether or not to clear the history buffers.
pub clear_history: bool,
/// The direction of rendering.
/// -1 indicates that the frames are played in reverse order.
pub frame_direction: i32,
}
config_struct! {
impl FrameOptionsGL => frame_gl_opt_t {
0 => [clear_history, frame_direction];
}
}
/// Options for filter chain creation.
#[repr(C)]
#[derive(Default, Debug, Clone)]
pub struct filter_chain_gl_opt_t {
/// The librashader API version.
pub version: LIBRASHADER_API_VERSION,
/// The GLSL version. Should be at least `330`.
pub glsl_version: u16,
/// Whether or not to use the Direct State Access APIs. Only available on OpenGL 4.5+.
pub use_dsa: bool,
/// Whether or not to explicitly disable mipmap generation regardless of shader preset settings.
pub force_no_mipmaps: bool,
}
config_struct! {
impl FilterChainOptionsGL => filter_chain_gl_opt_t {
0 => [glsl_version, use_dsa, force_no_mipmaps];
}
}
extern_fn! {
/// Initialize the OpenGL Context for librashader.
///
@ -84,7 +126,7 @@ extern_fn! {
/// - `out` must be aligned, but may be null, invalid, or uninitialized.
fn libra_gl_filter_chain_create(
preset: *mut libra_shader_preset_t,
options: *const FilterChainOptionsGL,
options: *const MaybeUninit<filter_chain_gl_opt_t>,
out: *mut MaybeUninit<libra_gl_filter_chain_t>
) {
assert_non_null!(preset);
@ -97,10 +139,11 @@ extern_fn! {
let options = if options.is_null() {
None
} else {
Some(unsafe { &*options })
Some(unsafe { options.read() })
};
let chain = librashader::runtime::gl::capi::FilterChainGL::load_from_preset(*preset, options)?;
let options = options.map(FromUninit::from_uninit);
let chain = librashader::runtime::gl::capi::FilterChainGL::load_from_preset(*preset, options.as_ref())?;
unsafe {
out.write(MaybeUninit::new(NonNull::new(Box::into_raw(Box::new(
@ -127,7 +170,7 @@ extern_fn! {
viewport: libra_viewport_t,
out: libra_output_framebuffer_gl_t,
mvp: *const f32,
opt: *const FrameOptionsGL
opt: *const MaybeUninit<frame_gl_opt_t>,
) mut |chain| {
assert_some_ptr!(mut chain);
let image: GLImage = image.into();
@ -141,6 +184,8 @@ extern_fn! {
} else {
Some(unsafe { opt.read() })
};
let opt = opt.map(FromUninit::from_uninit);
let framebuffer = Framebuffer::new_from_raw(out.texture, out.handle, out.format, Size::new(viewport.width, viewport.height), 1);
let viewport = Viewport {
x: viewport.x,

View file

@ -1,4 +1,6 @@
use crate::ctypes::{libra_shader_preset_t, libra_viewport_t, libra_vk_filter_chain_t};
use crate::ctypes::{
config_struct, libra_shader_preset_t, libra_viewport_t, libra_vk_filter_chain_t, FromUninit,
};
use crate::error::{assert_non_null, assert_some_ptr, LibrashaderError};
use crate::ffi::extern_fn;
use librashader::runtime::vk::{VulkanImage, VulkanInstance};
@ -80,6 +82,46 @@ impl From<libra_device_vk_t> for VulkanInstance {
}
}
/// Options for each OpenGL shader frame.
#[repr(C)]
#[derive(Default, Debug, Clone)]
pub struct frame_vk_opt_t {
/// The librashader API version.
pub version: usize,
/// Whether or not to clear the history buffers.
pub clear_history: bool,
/// The direction of rendering.
/// -1 indicates that the frames are played in reverse order.
pub frame_direction: i32,
}
config_struct! {
impl FrameOptionsVulkan => frame_vk_opt_t {
0 => [clear_history, frame_direction];
}
}
/// Options for filter chain creation.
#[repr(C)]
#[derive(Default, Debug, Clone)]
pub struct filter_chain_vk_opt_t {
/// The librashader API version.
pub version: usize,
/// The number of frames in flight to keep. If zero, defaults to three.
pub frames_in_flight: u32,
/// Whether or not to explicitly disable mipmap generation regardless of shader preset settings.
pub force_no_mipmaps: bool,
/// Use explicit render pass objects It is recommended if possible to use dynamic rendering,
/// because render-pass mode will create new framebuffers per pass.
pub use_render_pass: bool,
}
config_struct! {
impl FilterChainOptionsVulkan => filter_chain_vk_opt_t {
0 => [frames_in_flight, force_no_mipmaps, use_render_pass];
}
}
extern_fn! {
/// Create the filter chain given the shader preset.
///
@ -96,7 +138,7 @@ extern_fn! {
fn libra_vk_filter_chain_create(
vulkan: libra_device_vk_t,
preset: *mut libra_shader_preset_t,
options: *const FilterChainOptionsVulkan,
options: *const MaybeUninit<filter_chain_vk_opt_t>,
out: *mut MaybeUninit<libra_vk_filter_chain_t>
) {
assert_non_null!(preset);
@ -109,12 +151,13 @@ extern_fn! {
let options = if options.is_null() {
None
} else {
Some(unsafe { &*options })
Some(unsafe { options.read() })
};
let vulkan: VulkanInstance = vulkan.into();
let options = options.map(FromUninit::from_uninit);
let chain = librashader::runtime::vk::capi::FilterChainVulkan::load_from_preset(vulkan, *preset, options)?;
let chain = librashader::runtime::vk::capi::FilterChainVulkan::load_from_preset(vulkan, *preset, options.as_ref())?;
unsafe {
out.write(MaybeUninit::new(NonNull::new(Box::into_raw(Box::new(
@ -147,7 +190,7 @@ extern_fn! {
viewport: libra_viewport_t,
out: libra_output_image_vk_t,
mvp: *const f32,
opt: *const FrameOptionsVulkan
opt: *const MaybeUninit<frame_vk_opt_t>
) mut |chain| {
assert_some_ptr!(mut chain);
let image: VulkanImage = image.into();
@ -166,6 +209,7 @@ extern_fn! {
} else {
Some(unsafe { opt.read() })
};
let opt = opt.map(FromUninit::from_uninit);
let viewport = Viewport {
x: viewport.x,
y: viewport.y,

View file

@ -1,8 +1,8 @@
//! Direct3D11 shader runtime options.
//! Direct3D 11 shader runtime options.
/// Options for each Direct3D11 shader frame.
/// Options for each Direct3D 11 shader frame.
#[repr(C)]
#[derive(Debug, Clone)]
#[derive(Default, Debug, Clone)]
pub struct FrameOptionsD3D11 {
/// Whether or not to clear the history buffers.
pub clear_history: bool,
@ -11,9 +11,9 @@ pub struct FrameOptionsD3D11 {
pub frame_direction: i32,
}
/// Options for Direct3D11 filter chain creation.
/// Options for Direct3D 11 filter chain creation.
#[repr(C)]
#[derive(Debug, Clone)]
#[derive(Default, Debug, Clone)]
pub struct FilterChainOptionsD3D11 {
/// Use a deferred context to record shader rendering state.
///

View file

@ -1,8 +1,8 @@
//! Direct3D12 shader runtime options.
//! Direct3D 12 shader runtime options.
/// Options for each Direct3D11 shader frame.
/// Options for each Direct3D12 shader frame.
#[repr(C)]
#[derive(Debug, Clone)]
#[derive(Default, Debug, Clone)]
pub struct FrameOptionsD3D12 {
/// Whether or not to clear the history buffers.
pub clear_history: bool,
@ -11,9 +11,9 @@ pub struct FrameOptionsD3D12 {
pub frame_direction: i32,
}
/// Options for Direct3D11 filter chain creation.
/// Options for Direct3D 12 filter chain creation.
#[repr(C)]
#[derive(Debug, Clone)]
#[derive(Default, Debug, Clone)]
pub struct FilterChainOptionsD3D12 {
/// Force the HLSL shader pipeline. This may reduce shader compatibility.
pub force_hlsl_pipeline: bool,

View file

@ -107,7 +107,7 @@ impl<T: GLInterface> FilterChainImpl<T> {
FilterChainError,
>(preset.shaders, &preset.textures)?;
let version = options.map_or_else(gl_get_version, |o| gl_u16_to_version(o.gl_version));
let version = options.map_or_else(gl_get_version, |o| gl_u16_to_version(o.glsl_version));
// initialize passes
let filters = Self::init_passes(version, passes, &semantics)?;

View file

@ -37,7 +37,7 @@ mod tests {
let mut filter = FilterChainGL::load_from_path(
"../test/slang-shaders/bezel/Mega_Bezel/Presets/MBZ__0__SMOOTH-ADV.slangp",
Some(&FilterChainOptionsGL {
gl_version: 0,
glsl_version: 0,
use_dsa: false,
force_no_mipmaps: false,
}),
@ -54,7 +54,7 @@ mod tests {
// "../test/slang-shaders/vhs/VHSPro.slangp",
"../test/slang-shaders/crt/crt-royale.slangp",
Some(&FilterChainOptionsGL {
gl_version: 0,
glsl_version: 0,
use_dsa: true,
force_no_mipmaps: false,
}),

View file

@ -2,7 +2,7 @@
/// Options for each OpenGL shader frame.
#[repr(C)]
#[derive(Debug, Clone)]
#[derive(Default, Debug, Clone)]
pub struct FrameOptionsGL {
/// Whether or not to clear the history buffers.
pub clear_history: bool,
@ -13,10 +13,10 @@ pub struct FrameOptionsGL {
/// Options for filter chain creation.
#[repr(C)]
#[derive(Debug, Clone)]
#[derive(Default, Debug, Clone)]
pub struct FilterChainOptionsGL {
/// The GLSL version. Should be at least `330`.
pub gl_version: u16,
pub glsl_version: u16,
/// Whether or not to use the Direct State Access APIs. Only available on OpenGL 4.5+.
pub use_dsa: bool,
/// Whether or not to explicitly disable mipmap generation regardless of shader preset settings.

View file

@ -2,7 +2,7 @@
/// Options for each Vulkan shader frame.
#[repr(C)]
#[derive(Debug, Clone)]
#[derive(Default, Debug, Clone)]
pub struct FrameOptionsVulkan {
/// Whether or not to clear the history buffers.
pub clear_history: bool,
@ -13,7 +13,7 @@ pub struct FrameOptionsVulkan {
/// Options for filter chain creation.
#[repr(C)]
#[derive(Debug, Clone)]
#[derive(Default, Debug, Clone)]
pub struct FilterChainOptionsVulkan {
/// The number of frames in flight to keep. If zero, defaults to three.
pub frames_in_flight: u32,

View file

@ -66,12 +66,12 @@ int main(int, char**)
auto libra = librashader_load_instance();
libra_shader_preset_t preset;
auto error = libra.preset_create(
"../../../../../../slang-shaders/crt/crt-royale.slangp", &preset);
"../../../../../../slang-shaders/bezel/Mega_Bezel/Presets/MBZ__0__SMOOTH-ADV-GLASS.slangp", &preset);
libra_d3d11_filter_chain_t filter_chain;
filter_chain_d3d11_opt_t opt = {
.use_deferred_context = true,
.force_no_mipmaps = false,
.force_no_mipmaps = true,
};
libra.d3d11_filter_chain_create(&preset, &opt, g_pd3dDevice, &filter_chain);
@ -181,8 +181,11 @@ int main(int, char**)
framebufferTextureDesc.Width,
framebufferTextureDesc.Height,
};
frame_d3d11_opt_t frame_opt = {.clear_history = false,
.frame_direction = -1};
frame_d3d11_opt_t frame_opt = {
.version = 0,
.clear_history = false,
.frame_direction = -1
};
libra.d3d11_filter_chain_frame(&filter_chain, frameCount, input, vp,
g_mainRenderTargetView, NULL, &frame_opt);