rt: redesign parameters to be thread-safe across FFI using arcswap and atomicusize
This should allow C FFI consumers to modify frame parameters from a different thread without it being UB.
This commit is contained in:
parent
ae76bf9cc1
commit
c447e40583
26 changed files with 216 additions and 310 deletions
7
Cargo.lock
generated
7
Cargo.lock
generated
|
@ -123,6 +123,12 @@ version = "1.3.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110"
|
||||
|
||||
[[package]]
|
||||
name = "arc-swap"
|
||||
version = "1.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457"
|
||||
|
||||
[[package]]
|
||||
name = "arg_enum_proc_macro"
|
||||
version = "0.3.4"
|
||||
|
@ -1749,6 +1755,7 @@ dependencies = [
|
|||
name = "librashader-runtime"
|
||||
version = "0.3.3"
|
||||
dependencies = [
|
||||
"arc-swap",
|
||||
"array-concat",
|
||||
"bytemuck",
|
||||
"image",
|
||||
|
|
|
@ -260,14 +260,14 @@ extern_fn! {
|
|||
chain: *mut libra_d3d11_filter_chain_t,
|
||||
param_name: *const c_char,
|
||||
value: f32
|
||||
) mut |chain| {
|
||||
assert_some_ptr!(mut chain);
|
||||
) |chain| {
|
||||
assert_some_ptr!(chain);
|
||||
assert_non_null!(param_name);
|
||||
unsafe {
|
||||
let name = CStr::from_ptr(param_name);
|
||||
let name = name.to_str()?;
|
||||
|
||||
if chain.set_parameter(name, value).is_none() {
|
||||
if chain.parameters().set_parameter(name, value).is_none() {
|
||||
return LibrashaderError::UnknownShaderParameter(param_name).export()
|
||||
}
|
||||
}
|
||||
|
@ -282,17 +282,17 @@ extern_fn! {
|
|||
/// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_d3d11_filter_chain_t`.
|
||||
/// - `param_name` must be either null or a null terminated string.
|
||||
fn libra_d3d11_filter_chain_get_param(
|
||||
chain: *mut libra_d3d11_filter_chain_t,
|
||||
chain: *const libra_d3d11_filter_chain_t,
|
||||
param_name: *const c_char,
|
||||
out: *mut MaybeUninit<f32>
|
||||
) mut |chain| {
|
||||
assert_some_ptr!(mut chain);
|
||||
) |chain| {
|
||||
assert_some_ptr!(chain);
|
||||
assert_non_null!(param_name);
|
||||
unsafe {
|
||||
let name = CStr::from_ptr(param_name);
|
||||
let name = name.to_str()?;
|
||||
|
||||
let Some(value) = chain.get_parameter(name) else {
|
||||
let Some(value) = chain.parameters().get_parameter(name) else {
|
||||
return LibrashaderError::UnknownShaderParameter(param_name).export()
|
||||
};
|
||||
|
||||
|
@ -309,9 +309,9 @@ extern_fn! {
|
|||
fn libra_d3d11_filter_chain_set_active_pass_count(
|
||||
chain: *mut libra_d3d11_filter_chain_t,
|
||||
value: u32
|
||||
) mut |chain| {
|
||||
assert_some_ptr!(mut chain);
|
||||
chain.set_enabled_pass_count(value as usize);
|
||||
) |chain| {
|
||||
assert_some_ptr!(chain);
|
||||
chain.parameters().set_passes_enabled(value as usize);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -321,12 +321,12 @@ extern_fn! {
|
|||
/// ## Safety
|
||||
/// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_d3d11_filter_chain_t`.
|
||||
fn libra_d3d11_filter_chain_get_active_pass_count(
|
||||
chain: *mut libra_d3d11_filter_chain_t,
|
||||
chain: *const libra_d3d11_filter_chain_t,
|
||||
out: *mut MaybeUninit<u32>
|
||||
) mut |chain| {
|
||||
assert_some_ptr!(mut chain);
|
||||
) |chain| {
|
||||
assert_some_ptr!(chain);
|
||||
unsafe {
|
||||
let value = chain.get_enabled_pass_count();
|
||||
let value = chain.parameters().passes_enabled();
|
||||
out.write(MaybeUninit::new(value as u32))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -280,14 +280,14 @@ extern_fn! {
|
|||
chain: *mut libra_d3d12_filter_chain_t,
|
||||
param_name: *const c_char,
|
||||
value: f32
|
||||
) mut |chain| {
|
||||
assert_some_ptr!(mut chain);
|
||||
) |chain| {
|
||||
assert_some_ptr!(chain);
|
||||
assert_non_null!(param_name);
|
||||
unsafe {
|
||||
let name = CStr::from_ptr(param_name);
|
||||
let name = name.to_str()?;
|
||||
|
||||
if chain.set_parameter(name, value).is_none() {
|
||||
if chain.parameters().set_parameter(name, value).is_none() {
|
||||
return LibrashaderError::UnknownShaderParameter(param_name).export()
|
||||
}
|
||||
}
|
||||
|
@ -302,17 +302,17 @@ extern_fn! {
|
|||
/// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_d3d12_filter_chain_t`.
|
||||
/// - `param_name` must be either null or a null terminated string.
|
||||
fn libra_d3d12_filter_chain_get_param(
|
||||
chain: *mut libra_d3d12_filter_chain_t,
|
||||
chain: *const libra_d3d12_filter_chain_t,
|
||||
param_name: *const c_char,
|
||||
out: *mut MaybeUninit<f32>
|
||||
) mut |chain| {
|
||||
assert_some_ptr!(mut chain);
|
||||
) |chain| {
|
||||
assert_some_ptr!(chain);
|
||||
assert_non_null!(param_name);
|
||||
unsafe {
|
||||
let name = CStr::from_ptr(param_name);
|
||||
let name = name.to_str()?;
|
||||
|
||||
let Some(value) = chain.get_parameter(name) else {
|
||||
let Some(value) = chain.parameters().get_parameter(name) else {
|
||||
return LibrashaderError::UnknownShaderParameter(param_name).export()
|
||||
};
|
||||
|
||||
|
@ -329,9 +329,9 @@ extern_fn! {
|
|||
fn libra_d3d12_filter_chain_set_active_pass_count(
|
||||
chain: *mut libra_d3d12_filter_chain_t,
|
||||
value: u32
|
||||
) mut |chain| {
|
||||
assert_some_ptr!(mut chain);
|
||||
chain.set_enabled_pass_count(value as usize);
|
||||
) |chain| {
|
||||
assert_some_ptr!(chain);
|
||||
chain.parameters().set_passes_enabled(value as usize);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -341,12 +341,12 @@ extern_fn! {
|
|||
/// ## Safety
|
||||
/// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_d3d12_filter_chain_t`.
|
||||
fn libra_d3d12_filter_chain_get_active_pass_count(
|
||||
chain: *mut libra_d3d12_filter_chain_t,
|
||||
chain: *const libra_d3d12_filter_chain_t,
|
||||
out: *mut MaybeUninit<u32>
|
||||
) mut |chain| {
|
||||
assert_some_ptr!(mut chain);
|
||||
) |chain| {
|
||||
assert_some_ptr!(chain);
|
||||
unsafe {
|
||||
let value = chain.get_enabled_pass_count();
|
||||
let value = chain.parameters().passes_enabled();
|
||||
out.write(MaybeUninit::new(value as u32))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -170,14 +170,14 @@ extern_fn! {
|
|||
chain: *mut libra_d3d9_filter_chain_t,
|
||||
param_name: *const c_char,
|
||||
value: f32
|
||||
) mut |chain| {
|
||||
assert_some_ptr!(mut chain);
|
||||
) |chain| {
|
||||
assert_some_ptr!(chain);
|
||||
assert_non_null!(param_name);
|
||||
unsafe {
|
||||
let name = CStr::from_ptr(param_name);
|
||||
let name = name.to_str()?;
|
||||
|
||||
if chain.set_parameter(name, value).is_none() {
|
||||
if chain.parameters().set_parameter(name, value).is_none() {
|
||||
return LibrashaderError::UnknownShaderParameter(param_name).export()
|
||||
}
|
||||
}
|
||||
|
@ -192,17 +192,17 @@ extern_fn! {
|
|||
/// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_d3d9_filter_chain_t`.
|
||||
/// - `param_name` must be either null or a null terminated string.
|
||||
fn libra_d3d9_filter_chain_get_param(
|
||||
chain: *mut libra_d3d9_filter_chain_t,
|
||||
chain: *const libra_d3d9_filter_chain_t,
|
||||
param_name: *const c_char,
|
||||
out: *mut MaybeUninit<f32>
|
||||
) mut |chain| {
|
||||
assert_some_ptr!(mut chain);
|
||||
) |chain| {
|
||||
assert_some_ptr!(chain);
|
||||
assert_non_null!(param_name);
|
||||
unsafe {
|
||||
let name = CStr::from_ptr(param_name);
|
||||
let name = name.to_str()?;
|
||||
|
||||
let Some(value) = chain.get_parameter(name) else {
|
||||
let Some(value) = chain.parameters().get_parameter(name) else {
|
||||
return LibrashaderError::UnknownShaderParameter(param_name).export()
|
||||
};
|
||||
|
||||
|
@ -219,9 +219,9 @@ extern_fn! {
|
|||
fn libra_d3d9_filter_chain_set_active_pass_count(
|
||||
chain: *mut libra_d3d9_filter_chain_t,
|
||||
value: u32
|
||||
) mut |chain| {
|
||||
assert_some_ptr!(mut chain);
|
||||
chain.set_enabled_pass_count(value as usize);
|
||||
) |chain| {
|
||||
assert_some_ptr!(chain);
|
||||
chain.parameters().set_passes_enabled(value as usize);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -231,12 +231,12 @@ extern_fn! {
|
|||
/// ## Safety
|
||||
/// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_d3d9_filter_chain_t`.
|
||||
fn libra_d3d9_filter_chain_get_active_pass_count(
|
||||
chain: *mut libra_d3d9_filter_chain_t,
|
||||
chain: *const libra_d3d9_filter_chain_t,
|
||||
out: *mut MaybeUninit<u32>
|
||||
) mut |chain| {
|
||||
assert_some_ptr!(mut chain);
|
||||
) |chain| {
|
||||
assert_some_ptr!(chain);
|
||||
unsafe {
|
||||
let value = chain.get_enabled_pass_count();
|
||||
let value = chain.parameters().passes_enabled();
|
||||
out.write(MaybeUninit::new(value as u32))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -227,14 +227,14 @@ extern_fn! {
|
|||
chain: *mut libra_gl_filter_chain_t,
|
||||
param_name: *const c_char,
|
||||
value: f32
|
||||
) mut |chain| {
|
||||
assert_some_ptr!(mut chain);
|
||||
) |chain| {
|
||||
assert_some_ptr!(chain);
|
||||
assert_non_null!(param_name);
|
||||
unsafe {
|
||||
let name = CStr::from_ptr(param_name);
|
||||
let name = name.to_str()?;
|
||||
|
||||
if chain.set_parameter(name, value).is_none() {
|
||||
if chain.parameters().set_parameter(name, value).is_none() {
|
||||
return LibrashaderError::UnknownShaderParameter(param_name).export()
|
||||
}
|
||||
}
|
||||
|
@ -249,17 +249,17 @@ extern_fn! {
|
|||
/// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_gl_filter_chain_t`.
|
||||
/// - `param_name` must be either null or a null terminated string.
|
||||
fn libra_gl_filter_chain_get_param(
|
||||
chain: *mut libra_gl_filter_chain_t,
|
||||
chain: *const libra_gl_filter_chain_t,
|
||||
param_name: *const c_char,
|
||||
out: *mut MaybeUninit<f32>
|
||||
) mut |chain| {
|
||||
assert_some_ptr!(mut chain);
|
||||
) |chain| {
|
||||
assert_some_ptr!(chain);
|
||||
assert_non_null!(param_name);
|
||||
unsafe {
|
||||
let name = CStr::from_ptr(param_name);
|
||||
let name = name.to_str()?;
|
||||
|
||||
let Some(value) = chain.get_parameter(name) else {
|
||||
let Some(value) = chain.parameters().get_parameter(name) else {
|
||||
return LibrashaderError::UnknownShaderParameter(param_name).export()
|
||||
};
|
||||
|
||||
|
@ -276,9 +276,9 @@ extern_fn! {
|
|||
fn libra_gl_filter_chain_set_active_pass_count(
|
||||
chain: *mut libra_gl_filter_chain_t,
|
||||
value: u32
|
||||
) mut |chain| {
|
||||
assert_some_ptr!(mut chain);
|
||||
chain.set_enabled_pass_count(value as usize);
|
||||
) |chain| {
|
||||
assert_some_ptr!(chain);
|
||||
chain.parameters().set_passes_enabled(value as usize);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -292,7 +292,7 @@ extern_fn! {
|
|||
out: *mut MaybeUninit<u32>
|
||||
) mut |chain| {
|
||||
assert_some_ptr!(mut chain);
|
||||
let value = chain.get_enabled_pass_count();
|
||||
let value = chain.parameters().passes_enabled();
|
||||
unsafe {
|
||||
out.write(MaybeUninit::new(value as u32))
|
||||
}
|
||||
|
|
|
@ -229,13 +229,13 @@ extern_fn! {
|
|||
chain: *mut libra_mtl_filter_chain_t,
|
||||
param_name: *const c_char,
|
||||
value: f32
|
||||
) mut |chain| {
|
||||
assert_some_ptr!(mut chain);
|
||||
) |chain| {
|
||||
assert_some_ptr!(chain);
|
||||
unsafe {
|
||||
let name = CStr::from_ptr(param_name);
|
||||
let name = name.to_str()?;
|
||||
|
||||
if chain.set_parameter(name, value).is_none() {
|
||||
if chain.parameters().set_parameter(name, value).is_none() {
|
||||
return LibrashaderError::UnknownShaderParameter(param_name).export()
|
||||
}
|
||||
}
|
||||
|
@ -250,17 +250,17 @@ extern_fn! {
|
|||
/// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_mtl_filter_chain_t`.
|
||||
/// - `param_name` must be either null or a null terminated string.
|
||||
fn libra_mtl_filter_chain_get_param(
|
||||
chain: *mut libra_mtl_filter_chain_t,
|
||||
chain: *const libra_mtl_filter_chain_t,
|
||||
param_name: *const c_char,
|
||||
out: *mut MaybeUninit<f32>
|
||||
) mut |chain| {
|
||||
assert_some_ptr!(mut chain);
|
||||
) |chain| {
|
||||
assert_some_ptr!(chain);
|
||||
|
||||
unsafe {
|
||||
let name = CStr::from_ptr(param_name);
|
||||
let name = name.to_str()?;
|
||||
|
||||
let Some(value) = chain.get_parameter(name) else {
|
||||
let Some(value) = chain.parameters().get_parameter(name) else {
|
||||
return LibrashaderError::UnknownShaderParameter(param_name).export()
|
||||
};
|
||||
|
||||
|
@ -277,9 +277,9 @@ extern_fn! {
|
|||
fn libra_mtl_filter_chain_set_active_pass_count(
|
||||
chain: *mut libra_mtl_filter_chain_t,
|
||||
value: u32
|
||||
) mut |chain| {
|
||||
assert_some_ptr!(mut chain);
|
||||
chain.set_enabled_pass_count(value as usize);
|
||||
) |chain| {
|
||||
assert_some_ptr!(chain);
|
||||
chain.parameters().set_passes_enabled(value as usize);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -289,11 +289,11 @@ extern_fn! {
|
|||
/// ## Safety
|
||||
/// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_mtl_filter_chain_t`.
|
||||
fn libra_mtl_filter_chain_get_active_pass_count(
|
||||
chain: *mut libra_mtl_filter_chain_t,
|
||||
chain: *const libra_mtl_filter_chain_t,
|
||||
out: *mut MaybeUninit<u32>
|
||||
) mut |chain| {
|
||||
assert_some_ptr!(mut chain);
|
||||
let value = chain.get_enabled_pass_count();
|
||||
) |chain| {
|
||||
assert_some_ptr!(chain);
|
||||
let value = chain.parameters().passes_enabled();
|
||||
unsafe {
|
||||
out.write(MaybeUninit::new(value as u32))
|
||||
}
|
||||
|
|
|
@ -306,14 +306,14 @@ extern_fn! {
|
|||
chain: *mut libra_vk_filter_chain_t,
|
||||
param_name: *const c_char,
|
||||
value: f32
|
||||
) mut |chain| {
|
||||
assert_some_ptr!(mut chain);
|
||||
) |chain| {
|
||||
assert_some_ptr!(chain);
|
||||
assert_non_null!(param_name);
|
||||
unsafe {
|
||||
let name = CStr::from_ptr(param_name);
|
||||
let name = name.to_str()?;
|
||||
|
||||
if chain.set_parameter(name, value).is_none() {
|
||||
if chain.parameters().set_parameter(name, value).is_none() {
|
||||
return LibrashaderError::UnknownShaderParameter(param_name).export()
|
||||
}
|
||||
}
|
||||
|
@ -328,17 +328,17 @@ extern_fn! {
|
|||
/// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_vk_filter_chain_t`.
|
||||
/// - `param_name` must be either null or a null terminated string.
|
||||
fn libra_vk_filter_chain_get_param(
|
||||
chain: *mut libra_vk_filter_chain_t,
|
||||
chain: *const libra_vk_filter_chain_t,
|
||||
param_name: *const c_char,
|
||||
out: *mut MaybeUninit<f32>
|
||||
) mut |chain| {
|
||||
assert_some_ptr!(mut chain);
|
||||
) |chain| {
|
||||
assert_some_ptr!(chain);
|
||||
assert_non_null!(param_name);
|
||||
unsafe {
|
||||
let name = CStr::from_ptr(param_name);
|
||||
let name = name.to_str()?;
|
||||
|
||||
let Some(value) = chain.get_parameter(name) else {
|
||||
let Some(value) = chain.parameters().get_parameter(name) else {
|
||||
return LibrashaderError::UnknownShaderParameter(param_name).export()
|
||||
};
|
||||
|
||||
|
@ -355,9 +355,9 @@ extern_fn! {
|
|||
fn libra_vk_filter_chain_set_active_pass_count(
|
||||
chain: *mut libra_vk_filter_chain_t,
|
||||
value: u32
|
||||
) mut |chain| {
|
||||
assert_some_ptr!(mut chain);
|
||||
chain.set_enabled_pass_count(value as usize);
|
||||
) |chain| {
|
||||
assert_some_ptr!(chain);
|
||||
chain.parameters().set_passes_enabled(value as usize);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -367,11 +367,11 @@ extern_fn! {
|
|||
/// ## Safety
|
||||
/// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_vk_filter_chain_t`.
|
||||
fn libra_vk_filter_chain_get_active_pass_count(
|
||||
chain: *mut libra_vk_filter_chain_t,
|
||||
chain: *const libra_vk_filter_chain_t,
|
||||
out: *mut MaybeUninit<u32>
|
||||
) mut |chain| {
|
||||
assert_some_ptr!(mut chain);
|
||||
let value = chain.get_enabled_pass_count();
|
||||
) |chain| {
|
||||
assert_some_ptr!(chain);
|
||||
let value = chain.parameters().passes_enabled();
|
||||
unsafe {
|
||||
out.write(MaybeUninit::new(value as u32))
|
||||
}
|
||||
|
|
|
@ -43,11 +43,6 @@ use windows::Win32::Graphics::Direct3D11::{
|
|||
};
|
||||
use windows::Win32::Graphics::Dxgi::Common::DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
|
||||
pub struct FilterMutable {
|
||||
pub(crate) passes_enabled: usize,
|
||||
pub(crate) parameters: FastHashMap<String, f32>,
|
||||
}
|
||||
|
||||
/// A Direct3D 11 filter chain.
|
||||
pub struct FilterChainD3D11 {
|
||||
pub(crate) common: FilterCommon,
|
||||
|
@ -71,7 +66,7 @@ pub(crate) struct FilterCommon {
|
|||
pub output_textures: Box<[Option<InputTexture>]>,
|
||||
pub feedback_textures: Box<[Option<InputTexture>]>,
|
||||
pub history_textures: Box<[Option<InputTexture>]>,
|
||||
pub config: FilterMutable,
|
||||
pub config: RuntimeParameters,
|
||||
pub disable_mipmaps: bool,
|
||||
pub(crate) draw_quad: DrawQuad,
|
||||
}
|
||||
|
@ -103,6 +98,7 @@ mod compile {
|
|||
}
|
||||
|
||||
use compile::{compile_passes, ShaderPassMeta};
|
||||
use librashader_runtime::parameters::RuntimeParameters;
|
||||
|
||||
impl FilterChainD3D11 {
|
||||
/// Load the shader preset at the given path into a filter chain.
|
||||
|
@ -193,14 +189,7 @@ impl FilterChainD3D11 {
|
|||
_device: device.clone(),
|
||||
immediate_context,
|
||||
},
|
||||
config: FilterMutable {
|
||||
passes_enabled: preset.shader_count as usize,
|
||||
parameters: preset
|
||||
.parameters
|
||||
.into_iter()
|
||||
.map(|param| (param.name, param.value))
|
||||
.collect(),
|
||||
},
|
||||
config: RuntimeParameters::new(preset.shader_count as usize, preset.parameters),
|
||||
disable_mipmaps: options.map_or(false, |o| o.force_no_mipmaps),
|
||||
luts,
|
||||
samplers,
|
||||
|
@ -405,7 +394,7 @@ impl FilterChainD3D11 {
|
|||
frame_count: usize,
|
||||
options: Option<&FrameOptionsD3D11>,
|
||||
) -> error::Result<()> {
|
||||
let max = std::cmp::min(self.passes.len(), self.common.config.passes_enabled);
|
||||
let max = std::cmp::min(self.passes.len(), self.common.config.passes_enabled());
|
||||
|
||||
// Need to clone this because pushing history needs a mutable borrow.
|
||||
let immediate_context = &self.common.d3d11.immediate_context.clone();
|
||||
|
|
|
@ -139,7 +139,7 @@ impl FilterPass {
|
|||
parent.history_textures.iter().map(|o| o.as_ref()),
|
||||
parent.luts.iter().map(|(u, i)| (*u, i.as_ref())),
|
||||
&self.source.parameters,
|
||||
&parent.config.parameters,
|
||||
&parent.config,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -60,11 +60,6 @@ use rayon::prelude::*;
|
|||
|
||||
const MIPMAP_RESERVED_WORKHEAP_DESCRIPTORS: usize = 4096;
|
||||
|
||||
pub struct FilterMutable {
|
||||
pub(crate) passes_enabled: usize,
|
||||
pub(crate) parameters: FastHashMap<String, f32>,
|
||||
}
|
||||
|
||||
/// A Direct3D 12 filter chain.
|
||||
pub struct FilterChainD3D12 {
|
||||
pub(crate) common: FilterCommon,
|
||||
|
@ -92,7 +87,7 @@ pub(crate) struct FilterCommon {
|
|||
pub output_textures: Box<[Option<InputTexture>]>,
|
||||
pub feedback_textures: Box<[Option<InputTexture>]>,
|
||||
pub history_textures: Box<[Option<InputTexture>]>,
|
||||
pub config: FilterMutable,
|
||||
pub config: RuntimeParameters,
|
||||
// pub disable_mipmaps: bool,
|
||||
pub luts: FastHashMap<usize, LutTexture>,
|
||||
pub mipmap_gen: D3D12MipmapGen,
|
||||
|
@ -222,6 +217,7 @@ mod compile {
|
|||
}
|
||||
|
||||
use compile::{compile_passes_dxil, compile_passes_hlsl, DxilShaderPassMeta, HlslShaderPassMeta};
|
||||
use librashader_runtime::parameters::RuntimeParameters;
|
||||
|
||||
impl FilterChainD3D12 {
|
||||
/// Load the shader preset at the given path into a filter chain.
|
||||
|
@ -387,14 +383,7 @@ impl FilterChainD3D12 {
|
|||
mipmap_gen,
|
||||
root_signature,
|
||||
draw_quad,
|
||||
config: FilterMutable {
|
||||
passes_enabled: preset.shader_count as usize,
|
||||
parameters: preset
|
||||
.parameters
|
||||
.into_iter()
|
||||
.map(|param| (param.name, param.value))
|
||||
.collect(),
|
||||
},
|
||||
config: RuntimeParameters::new(preset.shader_count as usize, preset.parameters),
|
||||
history_textures,
|
||||
},
|
||||
staging_heap,
|
||||
|
@ -669,6 +658,13 @@ impl FilterChainD3D12 {
|
|||
) -> error::Result<()> {
|
||||
self.residuals.dispose();
|
||||
|
||||
// limit number of passes to those enabled.
|
||||
let max = std::cmp::min(self.passes.len(), self.common.config.passes_enabled());
|
||||
let passes = &mut self.passes[0..max];
|
||||
if passes.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if let Some(options) = options {
|
||||
if options.clear_history {
|
||||
for framebuffer in &mut self.history_framebuffers {
|
||||
|
@ -677,22 +673,8 @@ impl FilterChainD3D12 {
|
|||
}
|
||||
}
|
||||
|
||||
// limit number of passes to those enabled.
|
||||
let max = std::cmp::min(self.passes.len(), self.common.config.passes_enabled);
|
||||
let passes = &mut self.passes[0..max];
|
||||
|
||||
if passes.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let options = options.unwrap_or(&self.default_options);
|
||||
|
||||
let max = std::cmp::min(self.passes.len(), self.common.config.passes_enabled);
|
||||
let passes = &mut self.passes[0..max];
|
||||
if passes.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let filter = passes[0].config.filter;
|
||||
let wrap_mode = passes[0].config.wrap_mode;
|
||||
|
||||
|
|
|
@ -122,7 +122,7 @@ impl FilterPass {
|
|||
parent.history_textures.iter().map(|o| o.as_ref()),
|
||||
parent.luts.iter().map(|(u, i)| (*u, i.as_ref())),
|
||||
&self.source.parameters,
|
||||
&parent.config.parameters,
|
||||
&parent.config,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -36,11 +36,6 @@ use crate::util::GetSize;
|
|||
|
||||
use windows::Win32::Graphics::Direct3D9::{IDirect3DDevice9, IDirect3DSurface9, IDirect3DTexture9};
|
||||
|
||||
pub struct FilterMutable {
|
||||
pub(crate) passes_enabled: usize,
|
||||
pub(crate) parameters: FastHashMap<String, f32>,
|
||||
}
|
||||
|
||||
pub(crate) struct FilterCommon {
|
||||
pub(crate) d3d9: IDirect3DDevice9,
|
||||
pub(crate) luts: FastHashMap<usize, LutTexture>,
|
||||
|
@ -48,7 +43,7 @@ pub(crate) struct FilterCommon {
|
|||
pub output_textures: Box<[Option<D3D9InputTexture>]>,
|
||||
pub feedback_textures: Box<[Option<D3D9InputTexture>]>,
|
||||
pub history_textures: Box<[Option<D3D9InputTexture>]>,
|
||||
pub config: FilterMutable,
|
||||
pub config: RuntimeParameters,
|
||||
pub disable_mipmaps: bool,
|
||||
pub(crate) draw_quad: DrawQuad,
|
||||
}
|
||||
|
@ -90,6 +85,7 @@ mod compile {
|
|||
}
|
||||
|
||||
use compile::{compile_passes, ShaderPassMeta};
|
||||
use librashader_runtime::parameters::RuntimeParameters;
|
||||
|
||||
impl FilterChainD3D9 {
|
||||
fn init_passes(
|
||||
|
@ -255,14 +251,7 @@ impl FilterChainD3D9 {
|
|||
history_framebuffers,
|
||||
common: FilterCommon {
|
||||
d3d9: device.clone(),
|
||||
config: FilterMutable {
|
||||
passes_enabled: preset.shader_count as usize,
|
||||
parameters: preset
|
||||
.parameters
|
||||
.into_iter()
|
||||
.map(|param| (param.name, param.value))
|
||||
.collect(),
|
||||
},
|
||||
config: RuntimeParameters::new(preset.shader_count as usize, preset.parameters),
|
||||
disable_mipmaps: options.map_or(false, |o| o.force_no_mipmaps),
|
||||
luts,
|
||||
samplers,
|
||||
|
@ -295,7 +284,8 @@ impl FilterChainD3D9 {
|
|||
frame_count: usize,
|
||||
options: Option<&FrameOptionsD3D9>,
|
||||
) -> error::Result<()> {
|
||||
let max = std::cmp::min(self.passes.len(), self.common.config.passes_enabled);
|
||||
let max = std::cmp::min(self.passes.len(), self.common.config.passes_enabled());
|
||||
|
||||
let passes = &mut self.passes[0..max];
|
||||
if let Some(options) = options {
|
||||
if options.clear_history {
|
||||
|
|
|
@ -133,7 +133,7 @@ impl FilterPass {
|
|||
parent.history_textures.iter().map(|o| o.as_ref()),
|
||||
parent.luts.iter().map(|(u, i)| (*u, i.as_ref())),
|
||||
&self.source.parameters,
|
||||
&parent.config.parameters,
|
||||
&parent.config,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ pub(crate) struct FilterChainImpl<T: GLInterface> {
|
|||
|
||||
pub(crate) struct FilterCommon {
|
||||
// semantics: ReflectSemantics,
|
||||
pub config: FilterMutable,
|
||||
pub config: RuntimeParameters,
|
||||
pub luts: FastHashMap<usize, InputTexture>,
|
||||
pub samplers: SamplerSet,
|
||||
pub output_textures: Box<[InputTexture]>,
|
||||
|
@ -52,11 +52,6 @@ pub(crate) struct FilterCommon {
|
|||
pub disable_mipmaps: bool,
|
||||
}
|
||||
|
||||
pub struct FilterMutable {
|
||||
pub(crate) passes_enabled: usize,
|
||||
pub(crate) parameters: FastHashMap<String, f32>,
|
||||
}
|
||||
|
||||
impl<T: GLInterface> FilterChainImpl<T> {
|
||||
fn reflect_uniform_location(pipeline: GLuint, meta: &dyn UniformMeta) -> VariableLocation {
|
||||
let mut location = VariableLocation {
|
||||
|
@ -119,6 +114,7 @@ mod compile {
|
|||
}
|
||||
|
||||
use compile::{compile_passes, ShaderPassMeta};
|
||||
use librashader_runtime::parameters::RuntimeParameters;
|
||||
|
||||
impl<T: GLInterface> FilterChainImpl<T> {
|
||||
/// Load a filter chain from a pre-parsed `ShaderPreset`.
|
||||
|
@ -178,14 +174,7 @@ impl<T: GLInterface> FilterChainImpl<T> {
|
|||
history_framebuffers,
|
||||
draw_quad,
|
||||
common: FilterCommon {
|
||||
config: FilterMutable {
|
||||
passes_enabled: preset.shader_count as usize,
|
||||
parameters: preset
|
||||
.parameters
|
||||
.into_iter()
|
||||
.map(|param| (param.name, param.value))
|
||||
.collect(),
|
||||
},
|
||||
config: RuntimeParameters::new(preset.shader_count as usize, preset.parameters),
|
||||
disable_mipmaps: options.map_or(false, |o| o.force_no_mipmaps),
|
||||
luts,
|
||||
samplers,
|
||||
|
@ -274,7 +263,7 @@ impl<T: GLInterface> FilterChainImpl<T> {
|
|||
options: Option<&FrameOptionsGL>,
|
||||
) -> error::Result<()> {
|
||||
// limit number of passes to those enabled.
|
||||
let max = std::cmp::min(self.passes.len(), self.common.config.passes_enabled);
|
||||
let max = std::cmp::min(self.passes.len(), self.common.config.passes_enabled());
|
||||
let passes = &mut self.passes[0..max];
|
||||
|
||||
if let Some(options) = options {
|
||||
|
|
|
@ -2,7 +2,7 @@ use crate::filter_chain::filter_impl::FilterChainImpl;
|
|||
use crate::filter_chain::inner::FilterChainDispatch;
|
||||
use crate::gl::GLInterface;
|
||||
use crate::FilterChainGL;
|
||||
use librashader_runtime::parameters::FilterChainParameters;
|
||||
use librashader_runtime::parameters::{FilterChainParameters, RuntimeParameters};
|
||||
|
||||
impl AsRef<dyn FilterChainParameters + 'static> for FilterChainDispatch {
|
||||
fn as_ref<'a>(&'a self) -> &'a (dyn FilterChainParameters + 'static) {
|
||||
|
@ -23,60 +23,13 @@ impl AsMut<dyn FilterChainParameters + 'static> for FilterChainDispatch {
|
|||
}
|
||||
|
||||
impl FilterChainParameters for FilterChainGL {
|
||||
fn get_enabled_pass_count(&self) -> usize {
|
||||
self.filter.as_ref().get_enabled_pass_count()
|
||||
}
|
||||
|
||||
fn set_enabled_pass_count(&mut self, count: usize) {
|
||||
self.filter.as_mut().set_enabled_pass_count(count)
|
||||
}
|
||||
|
||||
fn enumerate_parameters(&self) -> ::librashader_common::map::halfbrown::Iter<String, f32> {
|
||||
self.filter.as_ref().enumerate_parameters()
|
||||
}
|
||||
|
||||
fn get_parameter(&self, parameter: &str) -> Option<f32> {
|
||||
self.filter.as_ref().get_parameter(parameter)
|
||||
}
|
||||
|
||||
fn set_parameter(&mut self, parameter: &str, new_value: f32) -> Option<f32> {
|
||||
self.filter.as_mut().set_parameter(parameter, new_value)
|
||||
fn parameters(&self) -> &RuntimeParameters {
|
||||
self.filter.as_ref().parameters()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: GLInterface> FilterChainParameters for FilterChainImpl<T> {
|
||||
fn get_enabled_pass_count(&self) -> usize {
|
||||
self.common.config.passes_enabled
|
||||
}
|
||||
|
||||
fn set_enabled_pass_count(&mut self, count: usize) {
|
||||
self.common.config.passes_enabled = count
|
||||
}
|
||||
|
||||
fn enumerate_parameters(&self) -> ::librashader_common::map::halfbrown::Iter<String, f32> {
|
||||
self.common.config.parameters.iter()
|
||||
}
|
||||
|
||||
fn get_parameter(&self, parameter: &str) -> Option<f32> {
|
||||
self.common
|
||||
.config
|
||||
.parameters
|
||||
.get::<str>(parameter.as_ref())
|
||||
.copied()
|
||||
}
|
||||
|
||||
fn set_parameter(&mut self, parameter: &str, new_value: f32) -> Option<f32> {
|
||||
if let Some(value) = self
|
||||
.common
|
||||
.config
|
||||
.parameters
|
||||
.get_mut::<str>(parameter.as_ref())
|
||||
{
|
||||
let old = *value;
|
||||
*value = new_value;
|
||||
Some(old)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
fn parameters(&self) -> &RuntimeParameters {
|
||||
&self.common.config
|
||||
}
|
||||
}
|
||||
|
|
|
@ -196,7 +196,7 @@ impl<T: GLInterface> FilterPass<T> {
|
|||
parent.history_textures.iter().map(|o| o.bound()),
|
||||
parent.luts.iter().map(|(u, i)| (*u, i)),
|
||||
&self.source.parameters,
|
||||
&parent.config.parameters,
|
||||
&parent.config,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,6 +57,7 @@ mod compile {
|
|||
}
|
||||
|
||||
use compile::{compile_passes, ShaderPassMeta};
|
||||
use librashader_runtime::parameters::RuntimeParameters;
|
||||
|
||||
/// A Metal filter chain.
|
||||
pub struct FilterChainMetal {
|
||||
|
@ -75,18 +76,13 @@ impl Debug for FilterChainMetal {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct FilterMutable {
|
||||
pub passes_enabled: usize,
|
||||
pub(crate) parameters: FastHashMap<String, f32>,
|
||||
}
|
||||
|
||||
pub(crate) struct FilterCommon {
|
||||
pub output_textures: Box<[Option<InputTexture>]>,
|
||||
pub feedback_textures: Box<[Option<InputTexture>]>,
|
||||
pub history_textures: Box<[Option<InputTexture>]>,
|
||||
pub luts: FastHashMap<usize, LutTexture>,
|
||||
pub samplers: SamplerSet,
|
||||
pub config: FilterMutable,
|
||||
pub config: RuntimeParameters,
|
||||
pub internal_frame_count: i32,
|
||||
pub(crate) draw_quad: DrawQuad,
|
||||
device: Id<ProtocolObject<dyn MTLDevice>>,
|
||||
|
@ -301,14 +297,7 @@ impl FilterChainMetal {
|
|||
common: FilterCommon {
|
||||
luts,
|
||||
samplers,
|
||||
config: FilterMutable {
|
||||
passes_enabled: preset.shader_count as usize,
|
||||
parameters: preset
|
||||
.parameters
|
||||
.into_iter()
|
||||
.map(|param| (param.name, param.value))
|
||||
.collect(),
|
||||
},
|
||||
config: RuntimeParameters::new(preset.shader_count as usize, preset.parameters),
|
||||
draw_quad,
|
||||
device,
|
||||
output_textures,
|
||||
|
@ -336,7 +325,7 @@ impl FilterChainMetal {
|
|||
frame_count: usize,
|
||||
options: Option<&FrameOptionsMetal>,
|
||||
) -> error::Result<()> {
|
||||
let max = std::cmp::min(self.passes.len(), self.common.config.passes_enabled);
|
||||
let max = std::cmp::min(self.passes.len(), self.common.config.passes_enabled());
|
||||
let passes = &mut self.passes[0..max];
|
||||
if let Some(options) = &options {
|
||||
let desc = unsafe {
|
||||
|
|
|
@ -163,7 +163,7 @@ impl FilterPass {
|
|||
parent.history_textures.iter().map(|o| o.as_ref()),
|
||||
parent.luts.iter().map(|(u, i)| (*u, i.as_ref())),
|
||||
&self.source.parameters,
|
||||
&parent.config.parameters,
|
||||
&parent.config,
|
||||
);
|
||||
|
||||
// flush to buffers
|
||||
|
|
|
@ -128,11 +128,6 @@ pub struct FilterChainVulkan {
|
|||
default_options: FrameOptionsVulkan,
|
||||
}
|
||||
|
||||
pub struct FilterMutable {
|
||||
pub(crate) passes_enabled: usize,
|
||||
pub(crate) parameters: FastHashMap<String, f32>,
|
||||
}
|
||||
|
||||
pub(crate) struct FilterCommon {
|
||||
pub(crate) luts: FastHashMap<usize, LutTexture>,
|
||||
pub samplers: SamplerSet,
|
||||
|
@ -140,7 +135,7 @@ pub(crate) struct FilterCommon {
|
|||
pub output_textures: Box<[Option<InputImage>]>,
|
||||
pub feedback_textures: Box<[Option<InputImage>]>,
|
||||
pub history_textures: Box<[Option<InputImage>]>,
|
||||
pub config: FilterMutable,
|
||||
pub config: RuntimeParameters,
|
||||
pub device: Arc<ash::Device>,
|
||||
pub(crate) internal_frame_count: usize,
|
||||
}
|
||||
|
@ -236,6 +231,7 @@ mod compile {
|
|||
}
|
||||
|
||||
use compile::{compile_passes, ShaderPassMeta};
|
||||
use librashader_runtime::parameters::RuntimeParameters;
|
||||
|
||||
impl FilterChainVulkan {
|
||||
/// Load the shader preset at the given path into a filter chain.
|
||||
|
@ -386,14 +382,7 @@ impl FilterChainVulkan {
|
|||
common: FilterCommon {
|
||||
luts,
|
||||
samplers,
|
||||
config: FilterMutable {
|
||||
passes_enabled: preset.shader_count as usize,
|
||||
parameters: preset
|
||||
.parameters
|
||||
.into_iter()
|
||||
.map(|param| (param.name, param.value))
|
||||
.collect(),
|
||||
},
|
||||
config: RuntimeParameters::new(preset.shader_count as usize, preset.parameters),
|
||||
draw_quad: DrawQuad::new(&device.device, &device.alloc)?,
|
||||
device: device.device.clone(),
|
||||
output_textures,
|
||||
|
@ -576,7 +565,7 @@ impl FilterChainVulkan {
|
|||
intermediates.dispose();
|
||||
|
||||
// limit number of passes to those enabled.
|
||||
let max = std::cmp::min(self.passes.len(), self.common.config.passes_enabled);
|
||||
let max = std::cmp::min(self.passes.len(), self.common.config.passes_enabled());
|
||||
let passes = &mut self.passes[0..max];
|
||||
|
||||
if let Some(options) = &options {
|
||||
|
|
|
@ -219,7 +219,7 @@ impl FilterPass {
|
|||
parent.history_textures.iter().map(|o| o.as_ref()),
|
||||
parent.luts.iter().map(|(u, i)| (*u, i.as_ref())),
|
||||
&self.source.parameters,
|
||||
&parent.config.parameters,
|
||||
&parent.config,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,6 +56,7 @@ mod compile {
|
|||
}
|
||||
|
||||
use compile::{compile_passes, ShaderPassMeta};
|
||||
use librashader_runtime::parameters::RuntimeParameters;
|
||||
|
||||
/// A wgpu filter chain.
|
||||
pub struct FilterChainWgpu {
|
||||
|
@ -69,19 +70,13 @@ pub struct FilterChainWgpu {
|
|||
default_frame_options: FrameOptionsWgpu,
|
||||
}
|
||||
|
||||
pub struct FilterMutable {
|
||||
pub passes_enabled: usize,
|
||||
pub(crate) parameters: FastHashMap<String, f32>,
|
||||
}
|
||||
|
||||
pub(crate) struct FilterCommon {
|
||||
pub output_textures: Box<[Option<InputImage>]>,
|
||||
pub feedback_textures: Box<[Option<InputImage>]>,
|
||||
pub history_textures: Box<[Option<InputImage>]>,
|
||||
pub luts: FastHashMap<usize, LutTexture>,
|
||||
pub samplers: SamplerSet,
|
||||
pub config: FilterMutable,
|
||||
pub internal_frame_count: i32,
|
||||
pub config: RuntimeParameters,
|
||||
pub(crate) draw_quad: DrawQuad,
|
||||
device: Arc<Device>,
|
||||
pub(crate) queue: Arc<wgpu::Queue>,
|
||||
|
@ -199,21 +194,13 @@ impl FilterChainWgpu {
|
|||
common: FilterCommon {
|
||||
luts,
|
||||
samplers,
|
||||
config: FilterMutable {
|
||||
passes_enabled: preset.shader_count as usize,
|
||||
parameters: preset
|
||||
.parameters
|
||||
.into_iter()
|
||||
.map(|param| (param.name, param.value))
|
||||
.collect(),
|
||||
},
|
||||
config: RuntimeParameters::new(preset.shader_count as usize, preset.parameters),
|
||||
draw_quad,
|
||||
device,
|
||||
queue,
|
||||
output_textures,
|
||||
feedback_textures,
|
||||
history_textures,
|
||||
internal_frame_count: 0,
|
||||
},
|
||||
passes: filters,
|
||||
output_framebuffers,
|
||||
|
@ -377,7 +364,7 @@ impl FilterChainWgpu {
|
|||
frame_count: usize,
|
||||
options: Option<&FrameOptionsWgpu>,
|
||||
) -> error::Result<()> {
|
||||
let max = std::cmp::min(self.passes.len(), self.common.config.passes_enabled);
|
||||
let max = std::cmp::min(self.passes.len(), self.common.config.passes_enabled());
|
||||
let passes = &mut self.passes[0..max];
|
||||
|
||||
if let Some(options) = &options {
|
||||
|
@ -513,7 +500,6 @@ impl FilterChainWgpu {
|
|||
}
|
||||
|
||||
self.push_history(&input, cmd);
|
||||
self.common.internal_frame_count = self.common.internal_frame_count.wrapping_add(1);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -238,7 +238,7 @@ impl FilterPass {
|
|||
parent.history_textures.iter().map(|o| o.as_ref()),
|
||||
parent.luts.iter().map(|(u, i)| (*u, i.as_ref())),
|
||||
&self.source.parameters,
|
||||
&parent.config.parameters,
|
||||
&parent.config,
|
||||
);
|
||||
|
||||
// flush to buffers
|
||||
|
|
|
@ -19,6 +19,7 @@ librashader-reflect = { path = "../librashader-reflect", version = "0.3.3" }
|
|||
bytemuck = { version = "1.12.3", features = ["derive"] }
|
||||
num-traits = "0.2.15"
|
||||
array-concat = "0.5.2"
|
||||
arc-swap = "1.7.1"
|
||||
|
||||
tinymap = "0.4.0"
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use crate::parameters::RuntimeParameters;
|
||||
use crate::uniforms::{BindUniform, NoUniformBinder, UniformStorage};
|
||||
use librashader_common::map::FastHashMap;
|
||||
use librashader_common::Size;
|
||||
|
@ -120,8 +121,9 @@ where
|
|||
original_history: impl Iterator<Item = Option<impl AsRef<Self::InputTexture>>>,
|
||||
lookup_textures: impl Iterator<Item = (usize, impl AsRef<Self::InputTexture>)>,
|
||||
parameter_defaults: &FastHashMap<String, ShaderParameter>,
|
||||
runtime_parameters: &FastHashMap<String, f32>,
|
||||
runtime_parameters: &RuntimeParameters,
|
||||
) {
|
||||
let runtime_parameters = runtime_parameters.parameters.load();
|
||||
// Bind MVP
|
||||
if let Some(offset) = uniform_bindings.get(&UniqueSemantics::MVP.into()) {
|
||||
uniform_storage.bind_mat4(
|
||||
|
|
|
@ -1,64 +1,92 @@
|
|||
use std::ops::Deref;
|
||||
use arc_swap::ArcSwap;
|
||||
use librashader_common::map::FastHashMap;
|
||||
use librashader_presets::ParameterConfig;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Trait for filter chains that allow runtime reflection of shader parameters.
|
||||
pub trait FilterChainParameters {
|
||||
/// Gets the number of shader passes enabled at runtime.
|
||||
fn get_enabled_pass_count(&self) -> usize;
|
||||
/// Get the runtime parameters for this filter chain.
|
||||
fn parameters(&self) -> &RuntimeParameters;
|
||||
}
|
||||
|
||||
/// Sets the number of shader passes enabled at runtime.
|
||||
fn set_enabled_pass_count(&mut self, count: usize);
|
||||
/// Runtime reflection of shader parameters for filter chains.
|
||||
///
|
||||
/// All operations on runtime parameters are atomic and can be done on
|
||||
/// any thread.
|
||||
pub struct RuntimeParameters {
|
||||
passes_enabled: AtomicUsize,
|
||||
pub(crate) parameters: ArcSwap<FastHashMap<String, f32>>,
|
||||
}
|
||||
|
||||
/// Enumerates the active parameters as well as their values in the current filter chain.
|
||||
fn enumerate_parameters<'a>(
|
||||
&'a self,
|
||||
) -> ::librashader_common::map::halfbrown::Iter<String, f32>;
|
||||
impl RuntimeParameters {
|
||||
/// Create a new instance of runtime parameters from a `Vec` of
|
||||
/// shader parameters from a [`ShaderPreset`](librashader_presets::ShaderPreset).
|
||||
pub fn new(passes_enabled: usize, parameters: Vec<ParameterConfig>) -> Self {
|
||||
RuntimeParameters {
|
||||
passes_enabled: AtomicUsize::new(passes_enabled),
|
||||
parameters: ArcSwap::new(Arc::new(
|
||||
parameters
|
||||
.into_iter()
|
||||
.map(|param| (param.name, param.value))
|
||||
.collect(),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the value of the given parameter if present.
|
||||
fn get_parameter(&self, parameter: &str) -> Option<f32>;
|
||||
/// Get the value of a runtime parameter
|
||||
pub fn get_parameter(&self, name: &str) -> Option<f32> {
|
||||
self.parameters.load().get::<str>(name.as_ref()).copied()
|
||||
}
|
||||
|
||||
/// Set the value of the given parameter if present.
|
||||
/// Set a runtime parameter.
|
||||
///
|
||||
/// Returns `None` if the parameter did not exist, or the old value if successful.
|
||||
fn set_parameter(&mut self, parameter: &str, new_value: f32) -> Option<f32>;
|
||||
/// This is a relatively slow operation as it will be synchronized across threads.
|
||||
pub fn set_parameter(&self, name: &str, new_value: f32) -> Option<f32> {
|
||||
let mut updated_map = FastHashMap::clone(&self.parameters.load());
|
||||
|
||||
if let Some(value) = updated_map.get_mut::<str>(name.as_ref()) {
|
||||
let old = *value;
|
||||
*value = new_value;
|
||||
|
||||
self.parameters.store(Arc::new(updated_map));
|
||||
|
||||
Some(old)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Get a reference to the runtime parameters.
|
||||
pub fn parameters(&self) -> Arc<FastHashMap<String, f32>> {
|
||||
self.parameters.load_full()
|
||||
}
|
||||
|
||||
/// Get the number of passes enabled.
|
||||
///
|
||||
/// If set from [`RuntimeParameters::set_passes_enabled`] from a different thread,
|
||||
/// it is not guaranteed to be immediately visible.
|
||||
#[inline(always)]
|
||||
pub fn passes_enabled(&self) -> usize {
|
||||
self.passes_enabled.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
/// Set the number of passes enabled.
|
||||
///
|
||||
/// This is an atomic operation and is thread-safe.
|
||||
#[inline(always)]
|
||||
pub fn set_passes_enabled(&self, count: usize) {
|
||||
self.passes_enabled.store(count, Ordering::Relaxed);
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! impl_filter_chain_parameters {
|
||||
($ty:ty) => {
|
||||
impl ::librashader_runtime::parameters::FilterChainParameters for $ty {
|
||||
fn get_enabled_pass_count(&self) -> usize {
|
||||
self.common.config.passes_enabled
|
||||
}
|
||||
|
||||
fn set_enabled_pass_count(&mut self, count: usize) {
|
||||
self.common.config.passes_enabled = count
|
||||
}
|
||||
|
||||
fn enumerate_parameters<'a>(
|
||||
&'a self,
|
||||
) -> ::librashader_common::map::halfbrown::Iter<String, f32> {
|
||||
self.common.config.parameters.iter()
|
||||
}
|
||||
|
||||
fn get_parameter(&self, parameter: &str) -> Option<f32> {
|
||||
self.common
|
||||
.config
|
||||
.parameters
|
||||
.get::<str>(parameter.as_ref())
|
||||
.copied()
|
||||
}
|
||||
|
||||
fn set_parameter(&mut self, parameter: &str, new_value: f32) -> Option<f32> {
|
||||
if let Some(value) = self
|
||||
.common
|
||||
.config
|
||||
.parameters
|
||||
.get_mut::<str>(parameter.as_ref())
|
||||
{
|
||||
let old = *value;
|
||||
*value = new_value;
|
||||
Some(old)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
fn parameters(&self) -> &::librashader_runtime::parameters::RuntimeParameters {
|
||||
&self.common.config
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -236,6 +236,7 @@ pub mod reflect {
|
|||
pub mod runtime {
|
||||
pub use librashader_common::{Size, Viewport};
|
||||
pub use librashader_runtime::parameters::FilterChainParameters;
|
||||
pub use librashader_runtime::parameters::RuntimeParameters;
|
||||
|
||||
#[cfg(feature = "runtime-gl")]
|
||||
#[doc(cfg(feature = "runtime-gl"))]
|
||||
|
|
Loading…
Add table
Reference in a new issue