capi: make _opt* structs more forwards compatible
yay another abi break 🙃
hopefully for the last time
This commit is contained in:
parent
121209da10
commit
2b250db353
17 changed files with 338 additions and 82 deletions
17
README.md
17
README.md
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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())?;
|
||||
}
|
||||
|
|
|
@ -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())?;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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.
|
||||
///
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)?;
|
||||
|
|
|
@ -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,
|
||||
}),
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue