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. This will output a `librashader.dll` or `librashader.so` in the target folder.
### C ABI Compatibility ### 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. 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. 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.
* `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_*`
Linking against `librashader.h` directly is possible, but is not officially supported. You will need to ensure linkage 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/) 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 * 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 presets with `mipmap_input0 = "true"` will not get a mipmapped input. In practice, no known shader presets set
`mipmap_input0 = "true"`. `mipmap_input0 = "true"`.
### Runtime specific differences ### Runtime specific differences
* OpenGL * OpenGL
* Copying of in-flight framebuffer contents to history is done via `glBlitFramebuffer` rather than drawing a quad into an intermediate FBO. * 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*); typedef const void *(*libra_gl_loader_t)(const char*);
#endif #endif
typedef size_t LIBRASHADER_API_VERSION;
#if defined(LIBRA_RUNTIME_OPENGL)
/// Options for filter chain creation. /// Options for filter chain creation.
typedef struct filter_chain_gl_opt_t { typedef struct filter_chain_gl_opt_t {
/// The librashader API version.
LIBRASHADER_API_VERSION version;
/// The GLSL version. Should be at least `330`. /// 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+. /// Whether or not to use the Direct State Access APIs. Only available on OpenGL 4.5+.
bool use_dsa; bool use_dsa;
/// Whether or not to explicitly disable mipmap generation regardless of shader preset settings. /// Whether or not to explicitly disable mipmap generation regardless of shader preset settings.
bool force_no_mipmaps; bool force_no_mipmaps;
} filter_chain_gl_opt_t; } filter_chain_gl_opt_t;
#endif
#if defined(LIBRA_RUNTIME_OPENGL) #if defined(LIBRA_RUNTIME_OPENGL)
/// A handle to a OpenGL filter chain. /// A handle to a OpenGL filter chain.
@ -191,14 +197,18 @@ typedef struct libra_output_framebuffer_gl_t {
} libra_output_framebuffer_gl_t; } libra_output_framebuffer_gl_t;
#endif #endif
#if defined(LIBRA_RUNTIME_OPENGL)
/// Options for each OpenGL shader frame. /// Options for each OpenGL shader frame.
typedef struct frame_gl_opt_t { typedef struct frame_gl_opt_t {
/// The librashader API version.
LIBRASHADER_API_VERSION version;
/// Whether or not to clear the history buffers. /// Whether or not to clear the history buffers.
bool clear_history; bool clear_history;
/// The direction of rendering. /// The direction of rendering.
/// -1 indicates that the frames are played in reverse order. /// -1 indicates that the frames are played in reverse order.
int32_t frame_direction; int32_t frame_direction;
} frame_gl_opt_t; } frame_gl_opt_t;
#endif
#if defined(LIBRA_RUNTIME_VULKAN) #if defined(LIBRA_RUNTIME_VULKAN)
/// Handles required to instantiate vulkan /// Handles required to instantiate vulkan
@ -217,8 +227,11 @@ typedef struct libra_device_vk_t {
} libra_device_vk_t; } libra_device_vk_t;
#endif #endif
#if defined(LIBRA_RUNTIME_VULKAN)
/// Options for filter chain creation. /// Options for filter chain creation.
typedef struct filter_chain_vk_opt_t { 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. /// The number of frames in flight to keep. If zero, defaults to three.
uint32_t frames_in_flight; uint32_t frames_in_flight;
/// Whether or not to explicitly disable mipmap generation regardless of shader preset settings. /// 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. /// because render-pass mode will create new framebuffers per pass.
bool use_render_pass; bool use_render_pass;
} filter_chain_vk_opt_t; } filter_chain_vk_opt_t;
#endif
#if defined(LIBRA_RUNTIME_VULKAN) #if defined(LIBRA_RUNTIME_VULKAN)
/// A handle to a Vulkan filter chain. /// A handle to a Vulkan filter chain.
@ -257,17 +271,24 @@ typedef struct libra_output_image_vk_t {
} libra_output_image_vk_t; } libra_output_image_vk_t;
#endif #endif
/// Options for each Vulkan shader frame. #if defined(LIBRA_RUNTIME_VULKAN)
/// Options for each OpenGL shader frame.
typedef struct frame_vk_opt_t { typedef struct frame_vk_opt_t {
/// The librashader API version.
size_t version;
/// Whether or not to clear the history buffers. /// Whether or not to clear the history buffers.
bool clear_history; bool clear_history;
/// The direction of rendering. /// The direction of rendering.
/// -1 indicates that the frames are played in reverse order. /// -1 indicates that the frames are played in reverse order.
int32_t frame_direction; int32_t frame_direction;
} frame_vk_opt_t; } 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 { typedef struct filter_chain_d3d11_opt_t {
/// The librashader API version.
LIBRASHADER_API_VERSION version;
/// Use a deferred context to record shader rendering state. /// Use a deferred context to record shader rendering state.
/// ///
/// The deferred context will be executed on the immediate context /// 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. /// generation regardless of shader preset settings.
bool force_no_mipmaps; bool force_no_mipmaps;
} filter_chain_d3d11_opt_t; } filter_chain_d3d11_opt_t;
#endif
#if defined(LIBRA_RUNTIME_D3D11) #if defined(LIBRA_RUNTIME_D3D11)
/// A handle to a Direct3D 11 filter chain. /// A handle to a Direct3D 11 filter chain.
@ -295,17 +317,24 @@ typedef struct libra_source_image_d3d11_t {
} libra_source_image_d3d11_t; } libra_source_image_d3d11_t;
#endif #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 { typedef struct frame_d3d11_opt_t {
/// The librashader API version.
LIBRASHADER_API_VERSION version;
/// Whether or not to clear the history buffers. /// Whether or not to clear the history buffers.
bool clear_history; bool clear_history;
/// The direction of rendering. /// The direction of rendering.
/// -1 indicates that the frames are played in reverse order. /// -1 indicates that the frames are played in reverse order.
int32_t frame_direction; int32_t frame_direction;
} frame_d3d11_opt_t; } frame_d3d11_opt_t;
#endif
#if defined(LIBRA_RUNTIME_D3D12)
/// Options for Direct3D11 filter chain creation. /// Options for Direct3D11 filter chain creation.
typedef struct filter_chain_d3d12_opt_t { 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. /// Force the HLSL shader pipeline. This may reduce shader compatibility.
bool force_hlsl_pipeline; bool force_hlsl_pipeline;
/// Whether or not to explicitly disable mipmap /// Whether or not to explicitly disable mipmap
@ -313,6 +342,7 @@ typedef struct filter_chain_d3d12_opt_t {
/// of shader preset settings. /// of shader preset settings.
bool force_no_mipmaps; bool force_no_mipmaps;
} filter_chain_d3d12_opt_t; } filter_chain_d3d12_opt_t;
#endif
#if defined(LIBRA_RUNTIME_D3D12) #if defined(LIBRA_RUNTIME_D3D12)
/// A handle to a Direct3D 12 filter chain. /// A handle to a Direct3D 12 filter chain.
@ -345,14 +375,18 @@ typedef struct libra_output_image_d3d12_t {
} libra_output_image_d3d12_t; } libra_output_image_d3d12_t;
#endif #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 { typedef struct frame_d3d12_opt_t {
/// The librashader API version.
LIBRASHADER_API_VERSION version;
/// Whether or not to clear the history buffers. /// Whether or not to clear the history buffers.
bool clear_history; bool clear_history;
/// The direction of rendering. /// The direction of rendering.
/// -1 indicates that the frames are played in reverse order. /// -1 indicates that the frames are played in reverse order.
int32_t frame_direction; int32_t frame_direction;
} frame_d3d12_opt_t; } frame_d3d12_opt_t;
#endif
/// Function pointer definition for /// Function pointer definition for
///libra_preset_create ///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 /// Function pointer definition for
///libra_d3d12_filter_chain_create ///libra_d3d12_filter_chain_create
typedef libra_error_t (*PFN_libra_d3d12_filter_chain_create)(libra_shader_preset_t *preset, 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, const ID3D12Device * device,
libra_d3d12_filter_chain_t *out); libra_d3d12_filter_chain_t *out);
#endif #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_viewport_t viewport,
struct libra_output_image_d3d12_t out, struct libra_output_image_d3d12_t out,
const float *mvp, const float *mvp,
const struct frame_d3d12_opt_t *opt); const struct frame_d3d12_opt_t *options);
#endif #endif
#if defined(LIBRA_RUNTIME_D3D12) #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); typedef libra_error_t (*PFN_libra_d3d12_filter_chain_free)(libra_d3d12_filter_chain_t *chain);
#endif #endif
/// The current version of the librashader API/ABI.
/// Pass this into `version` for config structs.
#define LIBRASHADER_CURRENT_VERSION 0
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif // __cplusplus #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. /// - `device` must not be null.
/// - `out` must be aligned, but may be null, invalid, or uninitialized. /// - `out` must be aligned, but may be null, invalid, or uninitialized.
libra_error_t libra_d3d12_filter_chain_create(libra_shader_preset_t *preset, 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, const ID3D12Device * device,
libra_d3d12_filter_chain_t *out); libra_d3d12_filter_chain_t *out);
#endif #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_viewport_t viewport,
struct libra_output_image_d3d12_t out, struct libra_output_image_d3d12_t out,
const float *mvp, const float *mvp,
const struct frame_d3d12_opt_t *opt); const struct frame_d3d12_opt_t *options);
#endif #endif
#if defined(LIBRA_RUNTIME_D3D12) #if defined(LIBRA_RUNTIME_D3D12)

View file

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

View file

@ -1,6 +1,7 @@
//! Binding types for the librashader C API. //! Binding types for the librashader C API.
use crate::error::LibrashaderError; use crate::error::LibrashaderError;
use librashader::presets::ShaderPreset; use librashader::presets::ShaderPreset;
use std::mem::MaybeUninit;
use std::ptr::NonNull; use std::ptr::NonNull;
/// A handle to a shader preset object. /// A handle to a shader preset object.
@ -44,3 +45,45 @@ pub struct libra_viewport_t {
/// The height of the viewport framebuffer. /// The height of the viewport framebuffer.
pub height: u32, 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 { 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! { ::paste::paste! {
/// Function pointer definition for /// Function pointer definition for
#[doc = ::std::stringify!($func_name)] #[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! { ::paste::paste! {
/// Function pointer definition for /// Function pointer definition for
#[doc = ::std::stringify!($func_name)] #[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] #[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! { ::paste::paste! {
/// Function pointer definition for /// Function pointer definition for
#[doc = ::std::stringify!($func_name)] #[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! { ::paste::paste! {
/// Function pointer definition for /// Function pointer definition for
#[doc = ::std::stringify!($func_name)] #[doc = ::std::stringify!($func_name)]
@ -113,7 +113,7 @@ macro_rules! extern_fn {
$crate::ffi::ffi_body!(mut |$($mut_capture),*| $body) $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! { ::paste::paste! {
/// Function pointer definition for /// Function pointer definition for
#[doc = ::std::stringify!($func_name)] #[doc = ::std::stringify!($func_name)]

View file

@ -67,3 +67,9 @@ pub mod presets;
pub mod reflect; pub mod reflect;
pub mod runtime; 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::error::{assert_non_null, assert_some_ptr, LibrashaderError};
use crate::ffi::extern_fn; use crate::ffi::extern_fn;
use librashader::runtime::d3d11::{D3D11InputView, D3D11OutputView}; 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; pub use librashader::runtime::d3d11::capi::options::FrameOptionsD3D11;
use librashader::runtime::{FilterChainParameters, Size, Viewport}; use librashader::runtime::{FilterChainParameters, Size, Viewport};
use crate::LIBRASHADER_API_VERSION;
/// Direct3D 11 parameters for the source image. /// Direct3D 11 parameters for the source image.
#[repr(C)] #[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! { extern_fn! {
/// Create the filter chain given the shader preset. /// 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. /// - `out` must be aligned, but may be null, invalid, or uninitialized.
fn libra_d3d11_filter_chain_create( fn libra_d3d11_filter_chain_create(
preset: *mut libra_shader_preset_t, preset: *mut libra_shader_preset_t,
options: *const FilterChainOptionsD3D11, options: *const MaybeUninit<filter_chain_d3d11_opt_t>,
device: ManuallyDrop<ID3D11Device>, device: ManuallyDrop<ID3D11Device>,
out: *mut MaybeUninit<libra_d3d11_filter_chain_t> out: *mut MaybeUninit<libra_d3d11_filter_chain_t>
) { ) {
@ -67,13 +112,14 @@ extern_fn! {
let options = if options.is_null() { let options = if options.is_null() {
None None
} else { } 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( let chain = librashader::runtime::d3d11::capi::FilterChainD3D11::load_from_preset(
&device, &device,
*preset, *preset,
options, options.as_ref(),
)?; )?;
unsafe { unsafe {
@ -103,7 +149,7 @@ extern_fn! {
viewport: libra_viewport_t, viewport: libra_viewport_t,
out: ManuallyDrop<ID3D11RenderTargetView>, out: ManuallyDrop<ID3D11RenderTargetView>,
mvp: *const f32, mvp: *const f32,
opt: *const FrameOptionsD3D11 opt: *const MaybeUninit<frame_d3d11_opt_t>
) mut |chain| { ) mut |chain| {
assert_some_ptr!(mut chain); assert_some_ptr!(mut chain);
@ -129,6 +175,8 @@ extern_fn! {
mvp, mvp,
}; };
let opt = opt.map(FromUninit::from_uninit);
let image = image.try_into()?; let image = image.try_into()?;
chain.frame(image, &viewport, frame_count, opt.as_ref())?; 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::error::{assert_non_null, assert_some_ptr, LibrashaderError};
use crate::ffi::extern_fn; use crate::ffi::extern_fn;
use std::ffi::c_char; 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::d3d12::{D3D12InputImage, D3D12OutputView};
use librashader::runtime::{FilterChainParameters, Size, Viewport}; use librashader::runtime::{FilterChainParameters, Size, Viewport};
use crate::LIBRASHADER_API_VERSION;
/// Direct3D 12 parameters for the source image. /// Direct3D 12 parameters for the source image.
#[repr(C)] #[repr(C)]
@ -41,6 +44,47 @@ pub struct libra_output_image_d3d12_t {
pub format: DXGI_FORMAT, 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 { impl TryFrom<libra_source_image_d3d12_t> for D3D12InputImage {
type Error = LibrashaderError; type Error = LibrashaderError;
@ -69,7 +113,7 @@ extern_fn! {
/// - `out` must be aligned, but may be null, invalid, or uninitialized. /// - `out` must be aligned, but may be null, invalid, or uninitialized.
fn libra_d3d12_filter_chain_create( fn libra_d3d12_filter_chain_create(
preset: *mut libra_shader_preset_t, preset: *mut libra_shader_preset_t,
options: *const FilterChainOptionsD3D12, opt: *const MaybeUninit<filter_chain_d3d12_opt_t>,
device: ManuallyDrop<ID3D12Device>, device: ManuallyDrop<ID3D12Device>,
out: *mut MaybeUninit<libra_d3d12_filter_chain_t> out: *mut MaybeUninit<libra_d3d12_filter_chain_t>
) { ) {
@ -80,16 +124,17 @@ extern_fn! {
Box::from_raw(preset.unwrap().as_ptr()) Box::from_raw(preset.unwrap().as_ptr())
}; };
let options = if options.is_null() { let opt = if opt.is_null() {
None None
} else { } 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( let chain = librashader::runtime::d3d12::capi::FilterChainD3D12::load_from_preset(
&device, &device,
*preset, *preset,
options, opt.as_ref(),
)?; )?;
unsafe { unsafe {
@ -122,7 +167,7 @@ extern_fn! {
viewport: libra_viewport_t, viewport: libra_viewport_t,
out: libra_output_image_d3d12_t, out: libra_output_image_d3d12_t,
mvp: *const f32, mvp: *const f32,
opt: *const FrameOptionsD3D12 options: *const MaybeUninit<frame_d3d12_opt_t>
) mut |chain| { ) mut |chain| {
assert_some_ptr!(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()) 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 None
} else { } else {
Some(unsafe { opt.read() }) Some(unsafe { options.read() })
}; };
let options = options.map(FromUninit::from_uninit);
let viewport = Viewport { let viewport = Viewport {
x: viewport.x, x: viewport.x,
y: viewport.y, y: viewport.y,
@ -146,7 +192,7 @@ extern_fn! {
}; };
let image = image.try_into()?; 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::error::{assert_non_null, assert_some_ptr, LibrashaderError};
use crate::ffi::extern_fn; use crate::ffi::extern_fn;
use librashader::runtime::gl::{Framebuffer, GLImage}; 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; pub use librashader::runtime::gl::capi::options::FrameOptionsGL;
use librashader::runtime::FilterChainParameters; use librashader::runtime::FilterChainParameters;
use librashader::runtime::{Size, Viewport}; use librashader::runtime::{Size, Viewport};
use crate::LIBRASHADER_API_VERSION;
/// 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;
@ -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! { extern_fn! {
/// Initialize the OpenGL Context for librashader. /// Initialize the OpenGL Context for librashader.
/// ///
@ -84,7 +126,7 @@ extern_fn! {
/// - `out` must be aligned, but may be null, invalid, or uninitialized. /// - `out` must be aligned, but may be null, invalid, or uninitialized.
fn libra_gl_filter_chain_create( fn libra_gl_filter_chain_create(
preset: *mut libra_shader_preset_t, 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> out: *mut MaybeUninit<libra_gl_filter_chain_t>
) { ) {
assert_non_null!(preset); assert_non_null!(preset);
@ -97,10 +139,11 @@ extern_fn! {
let options = if options.is_null() { let options = if options.is_null() {
None None
} else { } 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 { unsafe {
out.write(MaybeUninit::new(NonNull::new(Box::into_raw(Box::new( out.write(MaybeUninit::new(NonNull::new(Box::into_raw(Box::new(
@ -127,7 +170,7 @@ extern_fn! {
viewport: libra_viewport_t, viewport: libra_viewport_t,
out: libra_output_framebuffer_gl_t, out: libra_output_framebuffer_gl_t,
mvp: *const f32, mvp: *const f32,
opt: *const FrameOptionsGL opt: *const MaybeUninit<frame_gl_opt_t>,
) mut |chain| { ) mut |chain| {
assert_some_ptr!(mut chain); assert_some_ptr!(mut chain);
let image: GLImage = image.into(); let image: GLImage = image.into();
@ -141,6 +184,8 @@ extern_fn! {
} else { } else {
Some(unsafe { opt.read() }) 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 framebuffer = Framebuffer::new_from_raw(out.texture, out.handle, out.format, Size::new(viewport.width, viewport.height), 1);
let viewport = Viewport { let viewport = Viewport {
x: viewport.x, 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::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};
@ -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! { extern_fn! {
/// Create the filter chain given the shader preset. /// Create the filter chain given the shader preset.
/// ///
@ -96,7 +138,7 @@ extern_fn! {
fn libra_vk_filter_chain_create( fn libra_vk_filter_chain_create(
vulkan: libra_device_vk_t, vulkan: libra_device_vk_t,
preset: *mut libra_shader_preset_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> out: *mut MaybeUninit<libra_vk_filter_chain_t>
) { ) {
assert_non_null!(preset); assert_non_null!(preset);
@ -109,12 +151,13 @@ extern_fn! {
let options = if options.is_null() { let options = if options.is_null() {
None None
} else { } else {
Some(unsafe { &*options }) Some(unsafe { options.read() })
}; };
let vulkan: VulkanInstance = vulkan.into(); 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 { unsafe {
out.write(MaybeUninit::new(NonNull::new(Box::into_raw(Box::new( out.write(MaybeUninit::new(NonNull::new(Box::into_raw(Box::new(
@ -147,7 +190,7 @@ extern_fn! {
viewport: libra_viewport_t, viewport: libra_viewport_t,
out: libra_output_image_vk_t, out: libra_output_image_vk_t,
mvp: *const f32, mvp: *const f32,
opt: *const FrameOptionsVulkan opt: *const MaybeUninit<frame_vk_opt_t>
) mut |chain| { ) mut |chain| {
assert_some_ptr!(mut chain); assert_some_ptr!(mut chain);
let image: VulkanImage = image.into(); let image: VulkanImage = image.into();
@ -166,6 +209,7 @@ extern_fn! {
} else { } else {
Some(unsafe { opt.read() }) Some(unsafe { opt.read() })
}; };
let opt = opt.map(FromUninit::from_uninit);
let viewport = Viewport { let viewport = Viewport {
x: viewport.x, x: viewport.x,
y: viewport.y, 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)] #[repr(C)]
#[derive(Debug, Clone)] #[derive(Default, Debug, Clone)]
pub struct FrameOptionsD3D11 { pub struct FrameOptionsD3D11 {
/// Whether or not to clear the history buffers. /// Whether or not to clear the history buffers.
pub clear_history: bool, pub clear_history: bool,
@ -11,9 +11,9 @@ pub struct FrameOptionsD3D11 {
pub frame_direction: i32, pub frame_direction: i32,
} }
/// Options for Direct3D11 filter chain creation. /// Options for Direct3D 11 filter chain creation.
#[repr(C)] #[repr(C)]
#[derive(Debug, Clone)] #[derive(Default, Debug, Clone)]
pub struct FilterChainOptionsD3D11 { pub struct FilterChainOptionsD3D11 {
/// Use a deferred context to record shader rendering state. /// 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)] #[repr(C)]
#[derive(Debug, Clone)] #[derive(Default, Debug, Clone)]
pub struct FrameOptionsD3D12 { pub struct FrameOptionsD3D12 {
/// Whether or not to clear the history buffers. /// Whether or not to clear the history buffers.
pub clear_history: bool, pub clear_history: bool,
@ -11,9 +11,9 @@ pub struct FrameOptionsD3D12 {
pub frame_direction: i32, pub frame_direction: i32,
} }
/// Options for Direct3D11 filter chain creation. /// Options for Direct3D 12 filter chain creation.
#[repr(C)] #[repr(C)]
#[derive(Debug, Clone)] #[derive(Default, Debug, Clone)]
pub struct FilterChainOptionsD3D12 { pub struct FilterChainOptionsD3D12 {
/// Force the HLSL shader pipeline. This may reduce shader compatibility. /// Force the HLSL shader pipeline. This may reduce shader compatibility.
pub force_hlsl_pipeline: bool, pub force_hlsl_pipeline: bool,

View file

@ -107,7 +107,7 @@ impl<T: GLInterface> FilterChainImpl<T> {
FilterChainError, FilterChainError,
>(preset.shaders, &preset.textures)?; >(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 // initialize passes
let filters = Self::init_passes(version, passes, &semantics)?; let filters = Self::init_passes(version, passes, &semantics)?;

View file

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

View file

@ -2,7 +2,7 @@
/// Options for each OpenGL shader frame. /// Options for each OpenGL shader frame.
#[repr(C)] #[repr(C)]
#[derive(Debug, Clone)] #[derive(Default, Debug, Clone)]
pub struct FrameOptionsGL { pub struct FrameOptionsGL {
/// Whether or not to clear the history buffers. /// Whether or not to clear the history buffers.
pub clear_history: bool, pub clear_history: bool,
@ -13,10 +13,10 @@ pub struct FrameOptionsGL {
/// Options for filter chain creation. /// Options for filter chain creation.
#[repr(C)] #[repr(C)]
#[derive(Debug, Clone)] #[derive(Default, Debug, Clone)]
pub struct FilterChainOptionsGL { pub struct FilterChainOptionsGL {
/// The GLSL version. Should be at least `330`. /// 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+. /// Whether or not to use the Direct State Access APIs. Only available on OpenGL 4.5+.
pub use_dsa: bool, pub use_dsa: bool,
/// Whether or not to explicitly disable mipmap generation regardless of shader preset settings. /// 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. /// Options for each Vulkan shader frame.
#[repr(C)] #[repr(C)]
#[derive(Debug, Clone)] #[derive(Default, Debug, Clone)]
pub struct FrameOptionsVulkan { pub struct FrameOptionsVulkan {
/// Whether or not to clear the history buffers. /// Whether or not to clear the history buffers.
pub clear_history: bool, pub clear_history: bool,
@ -13,7 +13,7 @@ pub struct FrameOptionsVulkan {
/// Options for filter chain creation. /// Options for filter chain creation.
#[repr(C)] #[repr(C)]
#[derive(Debug, Clone)] #[derive(Default, Debug, Clone)]
pub struct FilterChainOptionsVulkan { pub struct FilterChainOptionsVulkan {
/// The number of frames in flight to keep. If zero, defaults to three. /// The number of frames in flight to keep. If zero, defaults to three.
pub frames_in_flight: u32, pub frames_in_flight: u32,

View file

@ -66,12 +66,12 @@ int main(int, char**)
auto libra = librashader_load_instance(); auto libra = librashader_load_instance();
libra_shader_preset_t preset; libra_shader_preset_t preset;
auto error = libra.preset_create( 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; libra_d3d11_filter_chain_t filter_chain;
filter_chain_d3d11_opt_t opt = { filter_chain_d3d11_opt_t opt = {
.use_deferred_context = true, .use_deferred_context = true,
.force_no_mipmaps = false, .force_no_mipmaps = true,
}; };
libra.d3d11_filter_chain_create(&preset, &opt, g_pd3dDevice, &filter_chain); libra.d3d11_filter_chain_create(&preset, &opt, g_pd3dDevice, &filter_chain);
@ -181,8 +181,11 @@ int main(int, char**)
framebufferTextureDesc.Width, framebufferTextureDesc.Width,
framebufferTextureDesc.Height, framebufferTextureDesc.Height,
}; };
frame_d3d11_opt_t frame_opt = {.clear_history = false, frame_d3d11_opt_t frame_opt = {
.frame_direction = -1}; .version = 0,
.clear_history = false,
.frame_direction = -1
};
libra.d3d11_filter_chain_frame(&filter_chain, frameCount, input, vp, libra.d3d11_filter_chain_frame(&filter_chain, frameCount, input, vp,
g_mainRenderTargetView, NULL, &frame_opt); g_mainRenderTargetView, NULL, &frame_opt);