cli(render): add ability to specify params and passes enabled
This commit is contained in:
parent
3993f57271
commit
91f8089277
29
CLI.md
29
CLI.md
|
@ -46,6 +46,19 @@ Options:
|
||||||
-p, --preset <PRESET>
|
-p, --preset <PRESET>
|
||||||
The path to the shader preset to load
|
The path to the shader preset to load
|
||||||
|
|
||||||
|
-w, --wildcards <WILDCARDS>...
|
||||||
|
Additional wildcard options, comma separated with equals signs. The PRESET and PRESET_DIR wildcards are always added to the preset parsing context.
|
||||||
|
|
||||||
|
For example, CONTENT-DIR=MyVerticalGames,GAME=mspacman
|
||||||
|
|
||||||
|
--params <PARAMS>...
|
||||||
|
Parameters to pass to the shader preset, comma separated with equals signs.
|
||||||
|
|
||||||
|
For example, crt_gamma=2.5,halation_weight=0.001
|
||||||
|
|
||||||
|
--passes-enabled <PASSES_ENABLED>
|
||||||
|
Set the number of passes enabled for the preset
|
||||||
|
|
||||||
-i, --image <IMAGE>
|
-i, --image <IMAGE>
|
||||||
The path to the input image
|
The path to the input image
|
||||||
|
|
||||||
|
@ -57,10 +70,11 @@ Options:
|
||||||
-r, --runtime <RUNTIME>
|
-r, --runtime <RUNTIME>
|
||||||
The runtime to use to render the shader preset
|
The runtime to use to render the shader preset
|
||||||
|
|
||||||
[possible values: opengl3, opengl4, vulkan, wgpu, d3d9, d3d11, d3d12, metal]
|
[possible values: opengl3, opengl4, vulkan, wgpu, d3d9, d3d11, d3d12]
|
||||||
|
|
||||||
-h, --help
|
-h, --help
|
||||||
Print help (see a summary with '-h')
|
Print help (see a summary with '-h')
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
The `render` command can be used to apply a shader preset to an image. The available runtimes will depend on the platform
|
The `render` command can be used to apply a shader preset to an image. The available runtimes will depend on the platform
|
||||||
|
@ -93,6 +107,19 @@ Options:
|
||||||
-p, --preset <PRESET>
|
-p, --preset <PRESET>
|
||||||
The path to the shader preset to load
|
The path to the shader preset to load
|
||||||
|
|
||||||
|
-w, --wildcards <WILDCARDS>...
|
||||||
|
Additional wildcard options, comma separated with equals signs. The PRESET and PRESET_DIR wildcards are always added to the preset parsing context.
|
||||||
|
|
||||||
|
For example, CONTENT-DIR=MyVerticalGames,GAME=mspacman
|
||||||
|
|
||||||
|
--params <PARAMS>...
|
||||||
|
Parameters to pass to the shader preset, comma separated with equals signs.
|
||||||
|
|
||||||
|
For example, crt_gamma=2.5,halation_weight=0.001
|
||||||
|
|
||||||
|
--passes-enabled <PASSES_ENABLED>
|
||||||
|
Set the number of passes enabled for the preset
|
||||||
|
|
||||||
-i, --image <IMAGE>
|
-i, --image <IMAGE>
|
||||||
The path to the input image
|
The path to the input image
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,8 @@ use librashader::reflect::cross::{GlslVersion, HlslShaderModel, MslVersion, Spir
|
||||||
use librashader::reflect::naga::{Naga, NagaLoweringOptions};
|
use librashader::reflect::naga::{Naga, NagaLoweringOptions};
|
||||||
use librashader::reflect::semantics::ShaderSemantics;
|
use librashader::reflect::semantics::ShaderSemantics;
|
||||||
use librashader::reflect::{CompileShader, FromCompilation, ReflectShader, SpirvCompilation};
|
use librashader::reflect::{CompileShader, FromCompilation, ReflectShader, SpirvCompilation};
|
||||||
|
use librashader::{FastHashMap, ShortString};
|
||||||
|
use librashader_runtime::parameters::RuntimeParameters;
|
||||||
use librashader_test::render::RenderTest;
|
use librashader_test::render::RenderTest;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
|
@ -28,6 +30,21 @@ enum Commands {
|
||||||
/// The path to the shader preset to load.
|
/// The path to the shader preset to load.
|
||||||
#[arg(short, long)]
|
#[arg(short, long)]
|
||||||
preset: PathBuf,
|
preset: PathBuf,
|
||||||
|
/// Additional wildcard options, comma separated with equals signs. The PRESET and PRESET_DIR
|
||||||
|
/// wildcards are always added to the preset parsing context.
|
||||||
|
///
|
||||||
|
/// For example, CONTENT-DIR=MyVerticalGames,GAME=mspacman
|
||||||
|
#[arg(short, long, value_delimiter = ',', num_args = 1..)]
|
||||||
|
wildcards: Option<Vec<String>>,
|
||||||
|
/// Parameters to pass to the shader preset, comma separated with equals signs.
|
||||||
|
///
|
||||||
|
/// For example, crt_gamma=2.5,halation_weight=0.001
|
||||||
|
#[arg(long, value_delimiter = ',', num_args = 1..)]
|
||||||
|
params: Option<Vec<String>>,
|
||||||
|
|
||||||
|
/// Set the number of passes enabled for the preset.
|
||||||
|
#[arg(long)]
|
||||||
|
passes_enabled: Option<usize>,
|
||||||
/// The path to the input image.
|
/// The path to the input image.
|
||||||
#[arg(short, long)]
|
#[arg(short, long)]
|
||||||
image: PathBuf,
|
image: PathBuf,
|
||||||
|
@ -49,6 +66,20 @@ enum Commands {
|
||||||
/// The path to the shader preset to load.
|
/// The path to the shader preset to load.
|
||||||
#[arg(short, long)]
|
#[arg(short, long)]
|
||||||
preset: PathBuf,
|
preset: PathBuf,
|
||||||
|
/// Additional wildcard options, comma separated with equals signs. The PRESET and PRESET_DIR
|
||||||
|
/// wildcards are always added to the preset parsing context.
|
||||||
|
///
|
||||||
|
/// For example, CONTENT-DIR=MyVerticalGames,GAME=mspacman
|
||||||
|
#[arg(short, long, value_delimiter = ',', num_args = 1..)]
|
||||||
|
wildcards: Option<Vec<String>>,
|
||||||
|
/// Parameters to pass to the shader preset, comma separated with equals signs.
|
||||||
|
///
|
||||||
|
/// For example, crt_gamma=2.5,halation_weight=0.001
|
||||||
|
#[arg(long, value_delimiter = ',', num_args = 1..)]
|
||||||
|
params: Option<Vec<String>>,
|
||||||
|
/// Set the number of passes enabled for the preset.
|
||||||
|
#[arg(long)]
|
||||||
|
passes_enabled: Option<usize>,
|
||||||
/// The path to the input image.
|
/// The path to the input image.
|
||||||
#[arg(short, long)]
|
#[arg(short, long)]
|
||||||
image: PathBuf,
|
image: PathBuf,
|
||||||
|
@ -241,12 +272,22 @@ pub fn main() -> Result<(), anyhow::Error> {
|
||||||
Commands::Render {
|
Commands::Render {
|
||||||
frame,
|
frame,
|
||||||
preset,
|
preset,
|
||||||
|
wildcards,
|
||||||
|
params,
|
||||||
|
passes_enabled,
|
||||||
image,
|
image,
|
||||||
out,
|
out,
|
||||||
runtime,
|
runtime,
|
||||||
} => {
|
} => {
|
||||||
let test: &mut dyn RenderTest = get_runtime!(runtime, image);
|
let test: &mut dyn RenderTest = get_runtime!(runtime, image);
|
||||||
let image = test.render(preset.as_path(), frame)?;
|
let preset = get_shader_preset(preset, wildcards)?;
|
||||||
|
let params = parse_params(params)?;
|
||||||
|
|
||||||
|
let image = test.render_with_preset_and_params(
|
||||||
|
preset,
|
||||||
|
frame,
|
||||||
|
Some(&|rp| set_params(rp, ¶ms, passes_enabled)),
|
||||||
|
)?;
|
||||||
|
|
||||||
if out.as_path() == Path::new("-") {
|
if out.as_path() == Path::new("-") {
|
||||||
let out = std::io::stdout();
|
let out = std::io::stdout();
|
||||||
|
@ -258,6 +299,9 @@ pub fn main() -> Result<(), anyhow::Error> {
|
||||||
Commands::Compare {
|
Commands::Compare {
|
||||||
frame,
|
frame,
|
||||||
preset,
|
preset,
|
||||||
|
wildcards,
|
||||||
|
params,
|
||||||
|
passes_enabled,
|
||||||
image,
|
image,
|
||||||
left,
|
left,
|
||||||
right,
|
right,
|
||||||
|
@ -265,9 +309,22 @@ pub fn main() -> Result<(), anyhow::Error> {
|
||||||
} => {
|
} => {
|
||||||
let left: &mut dyn RenderTest = get_runtime!(left, image);
|
let left: &mut dyn RenderTest = get_runtime!(left, image);
|
||||||
let right: &mut dyn RenderTest = get_runtime!(right, image);
|
let right: &mut dyn RenderTest = get_runtime!(right, image);
|
||||||
|
let params = parse_params(params)?;
|
||||||
|
|
||||||
|
let left_preset = get_shader_preset(preset.clone(), wildcards.clone())?;
|
||||||
|
let left_image = left.render_with_preset_and_params(
|
||||||
|
left_preset,
|
||||||
|
frame,
|
||||||
|
Some(&|rp| set_params(rp, ¶ms, passes_enabled)),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let right_preset = get_shader_preset(preset.clone(), wildcards.clone())?;
|
||||||
|
let right_image = right.render_with_preset_and_params(
|
||||||
|
right_preset,
|
||||||
|
frame,
|
||||||
|
Some(&|rp| set_params(rp, ¶ms, passes_enabled)),
|
||||||
|
)?;
|
||||||
|
|
||||||
let left_image = left.render(preset.as_path(), frame)?;
|
|
||||||
let right_image = right.render(preset.as_path(), frame)?;
|
|
||||||
let similarity = image_compare::rgba_hybrid_compare(&left_image, &right_image)?;
|
let similarity = image_compare::rgba_hybrid_compare(&left_image, &right_image)?;
|
||||||
print!("{}", similarity.score);
|
print!("{}", similarity.score);
|
||||||
|
|
||||||
|
@ -312,7 +369,8 @@ pub fn main() -> Result<(), anyhow::Error> {
|
||||||
librashader::reflect::targets::GLSL::from_compilation(compilation)?;
|
librashader::reflect::targets::GLSL::from_compilation(compilation)?;
|
||||||
compilation.validate()?;
|
compilation.validate()?;
|
||||||
|
|
||||||
let version = version.map(|s| parse_glsl_version(&s))
|
let version = version
|
||||||
|
.map(|s| parse_glsl_version(&s))
|
||||||
.unwrap_or(Ok(GlslVersion::Glsl330))?;
|
.unwrap_or(Ok(GlslVersion::Glsl330))?;
|
||||||
|
|
||||||
let output = compilation.compile(version)?;
|
let output = compilation.compile(version)?;
|
||||||
|
@ -326,7 +384,8 @@ pub fn main() -> Result<(), anyhow::Error> {
|
||||||
librashader::reflect::targets::HLSL::from_compilation(compilation)?;
|
librashader::reflect::targets::HLSL::from_compilation(compilation)?;
|
||||||
compilation.validate()?;
|
compilation.validate()?;
|
||||||
|
|
||||||
let shader_model = version.map(|s| parse_hlsl_version(&s))
|
let shader_model = version
|
||||||
|
.map(|s| parse_hlsl_version(&s))
|
||||||
.unwrap_or(Ok(HlslShaderModel::ShaderModel5_0))?;
|
.unwrap_or(Ok(HlslShaderModel::ShaderModel5_0))?;
|
||||||
|
|
||||||
let output = compilation.compile(Some(shader_model))?;
|
let output = compilation.compile(Some(shader_model))?;
|
||||||
|
@ -356,7 +415,8 @@ pub fn main() -> Result<(), anyhow::Error> {
|
||||||
>>::from_compilation(compilation)?;
|
>>::from_compilation(compilation)?;
|
||||||
compilation.validate()?;
|
compilation.validate()?;
|
||||||
|
|
||||||
let version = version.map(|s| parse_msl_version(&s))
|
let version = version
|
||||||
|
.map(|s| parse_msl_version(&s))
|
||||||
.unwrap_or(Ok(MslVersion::new(1, 2, 0)))?;
|
.unwrap_or(Ok(MslVersion::new(1, 2, 0)))?;
|
||||||
|
|
||||||
let output = compilation.compile(Some(version))?;
|
let output = compilation.compile(Some(version))?;
|
||||||
|
@ -459,6 +519,49 @@ fn get_shader_preset(
|
||||||
Ok(preset)
|
Ok(preset)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_params(
|
||||||
|
assignments: Option<Vec<String>>,
|
||||||
|
) -> anyhow::Result<Option<FastHashMap<ShortString, f32>>> {
|
||||||
|
let Some(assignments) = assignments else {
|
||||||
|
return Ok(None);
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut map = FastHashMap::default();
|
||||||
|
for string in assignments {
|
||||||
|
let Some((left, right)) = string.split_once("=") else {
|
||||||
|
return Err(anyhow!("Encountered invalid parameter string {string}"));
|
||||||
|
};
|
||||||
|
|
||||||
|
let value = right
|
||||||
|
.parse::<f32>()
|
||||||
|
.map_err(|_| anyhow!("Encountered invalid parameter value: {right}"))?;
|
||||||
|
|
||||||
|
map.insert(ShortString::from(left), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Some(map))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_params(
|
||||||
|
params: &RuntimeParameters,
|
||||||
|
assignments: &Option<FastHashMap<ShortString, f32>>,
|
||||||
|
passes_enabled: Option<usize>,
|
||||||
|
) {
|
||||||
|
if let Some(passes_enabled) = passes_enabled {
|
||||||
|
params.set_passes_enabled(passes_enabled)
|
||||||
|
};
|
||||||
|
|
||||||
|
let Some(assignments) = assignments else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
params.update_parameters(|params| {
|
||||||
|
for (key, param) in assignments {
|
||||||
|
params.insert(key.clone(), *param);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
fn spirv_to_dis(spirv: Vec<u32>) -> anyhow::Result<String> {
|
fn spirv_to_dis(spirv: Vec<u32>) -> anyhow::Result<String> {
|
||||||
let binary = spq_spvasm::SpirvBinary::from(spirv);
|
let binary = spq_spvasm::SpirvBinary::from(spirv);
|
||||||
spq_spvasm::Disassembler::new()
|
spq_spvasm::Disassembler::new()
|
||||||
|
@ -473,7 +576,7 @@ fn spirv_to_dis(spirv: Vec<u32>) -> anyhow::Result<String> {
|
||||||
fn parse_glsl_version(version_str: &str) -> anyhow::Result<GlslVersion> {
|
fn parse_glsl_version(version_str: &str) -> anyhow::Result<GlslVersion> {
|
||||||
if version_str.contains("es") {
|
if version_str.contains("es") {
|
||||||
let Some(version) = version_str.strip_suffix("es").map(|s| s.trim()) else {
|
let Some(version) = version_str.strip_suffix("es").map(|s| s.trim()) else {
|
||||||
return Err(anyhow!("Unknown GLSL version"))
|
return Err(anyhow!("Unknown GLSL version"));
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(match version {
|
Ok(match version {
|
||||||
|
@ -516,7 +619,9 @@ fn version_to_usize(version_str: &str) -> anyhow::Result<usize> {
|
||||||
version_str
|
version_str
|
||||||
};
|
};
|
||||||
|
|
||||||
let version = version.parse::<usize>().map_err(|_| anyhow!("Invalid version string"))?;
|
let version = version
|
||||||
|
.parse::<usize>()
|
||||||
|
.map_err(|_| anyhow!("Invalid version string"))?;
|
||||||
Ok(version)
|
Ok(version)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ use crate::render::RenderTest;
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use image::RgbaImage;
|
use image::RgbaImage;
|
||||||
use librashader::runtime::d3d11::*;
|
use librashader::runtime::d3d11::*;
|
||||||
|
use librashader::runtime::{FilterChainParameters, RuntimeParameters};
|
||||||
use librashader::runtime::{Size, Viewport};
|
use librashader::runtime::{Size, Viewport};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
|
@ -13,18 +14,28 @@ impl RenderTest for Direct3D11 {
|
||||||
Direct3D11::new(path)
|
Direct3D11::new(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render(&mut self, path: &Path, frame_count: usize) -> anyhow::Result<RgbaImage> {
|
fn render_with_preset_and_params(
|
||||||
|
&mut self,
|
||||||
|
preset: ShaderPreset,
|
||||||
|
frame_count: usize,
|
||||||
|
param_setter: Option<&dyn Fn(&RuntimeParameters)>,
|
||||||
|
) -> anyhow::Result<image::RgbaImage> {
|
||||||
let (renderbuffer, rtv) = self.create_renderbuffer(self.image_bytes.size)?;
|
let (renderbuffer, rtv) = self.create_renderbuffer(self.image_bytes.size)?;
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut filter_chain = FilterChain::load_from_path(
|
let mut filter_chain = FilterChain::load_from_preset(
|
||||||
path,
|
preset,
|
||||||
&self.device,
|
&self.device,
|
||||||
Some(&FilterChainOptions {
|
Some(&FilterChainOptions {
|
||||||
force_no_mipmaps: false,
|
force_no_mipmaps: false,
|
||||||
disable_cache: false,
|
disable_cache: false,
|
||||||
}),
|
}),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
if let Some(setter) = param_setter {
|
||||||
|
setter(filter_chain.parameters());
|
||||||
|
}
|
||||||
|
|
||||||
filter_chain.frame(
|
filter_chain.frame(
|
||||||
None,
|
None,
|
||||||
&self.image_srv,
|
&self.image_srv,
|
||||||
|
@ -78,6 +89,7 @@ impl RenderTest for Direct3D11 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
use librashader::presets::ShaderPreset;
|
||||||
use librashader_runtime::image::{Image, UVDirection};
|
use librashader_runtime::image::{Image, UVDirection};
|
||||||
use windows::{
|
use windows::{
|
||||||
Win32::Foundation::*, Win32::Graphics::Direct3D::*, Win32::Graphics::Direct3D11::*,
|
Win32::Foundation::*, Win32::Graphics::Direct3D::*, Win32::Graphics::Direct3D11::*,
|
||||||
|
|
|
@ -6,10 +6,12 @@ use crate::render::RenderTest;
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use d3d12_descriptor_heap::{D3D12DescriptorHeap, D3D12DescriptorHeapSlot};
|
use d3d12_descriptor_heap::{D3D12DescriptorHeap, D3D12DescriptorHeapSlot};
|
||||||
use image::RgbaImage;
|
use image::RgbaImage;
|
||||||
|
use librashader::presets::ShaderPreset;
|
||||||
use librashader::runtime::d3d12::{
|
use librashader::runtime::d3d12::{
|
||||||
D3D12InputImage, D3D12OutputView, FilterChain, FilterChainOptions,
|
D3D12InputImage, D3D12OutputView, FilterChain, FilterChainOptions,
|
||||||
};
|
};
|
||||||
use librashader::runtime::Viewport;
|
use librashader::runtime::Viewport;
|
||||||
|
use librashader::runtime::{FilterChainParameters, RuntimeParameters};
|
||||||
use librashader_runtime::image::{Image, PixelFormat, UVDirection, BGRA8};
|
use librashader_runtime::image::{Image, PixelFormat, UVDirection, BGRA8};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use windows::core::Interface;
|
use windows::core::Interface;
|
||||||
|
@ -58,7 +60,12 @@ impl RenderTest for Direct3D12 {
|
||||||
Direct3D12::new(path)
|
Direct3D12::new(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render(&mut self, path: &Path, frame_count: usize) -> anyhow::Result<RgbaImage> {
|
fn render_with_preset_and_params(
|
||||||
|
&mut self,
|
||||||
|
preset: ShaderPreset,
|
||||||
|
frame_count: usize,
|
||||||
|
param_setter: Option<&dyn Fn(&RuntimeParameters)>,
|
||||||
|
) -> anyhow::Result<image::RgbaImage> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let descriptor = self.rtv_heap.allocate_descriptor()?;
|
let descriptor = self.rtv_heap.allocate_descriptor()?;
|
||||||
|
|
||||||
|
@ -72,8 +79,8 @@ impl RenderTest for Direct3D12 {
|
||||||
let fence_event = CreateEventA(None, false, false, None)?;
|
let fence_event = CreateEventA(None, false, false, None)?;
|
||||||
let fence: ID3D12Fence = self.device.CreateFence(0, D3D12_FENCE_FLAG_NONE)?;
|
let fence: ID3D12Fence = self.device.CreateFence(0, D3D12_FENCE_FLAG_NONE)?;
|
||||||
|
|
||||||
let mut filter_chain = FilterChain::load_from_path(
|
let mut filter_chain = FilterChain::load_from_preset(
|
||||||
path,
|
preset,
|
||||||
&self.device,
|
&self.device,
|
||||||
Some(&FilterChainOptions {
|
Some(&FilterChainOptions {
|
||||||
force_hlsl_pipeline: false,
|
force_hlsl_pipeline: false,
|
||||||
|
@ -82,6 +89,10 @@ impl RenderTest for Direct3D12 {
|
||||||
}),
|
}),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
if let Some(setter) = param_setter {
|
||||||
|
setter(filter_chain.parameters());
|
||||||
|
}
|
||||||
|
|
||||||
let mut output_texture = None;
|
let mut output_texture = None;
|
||||||
let desc = D3D12_RESOURCE_DESC {
|
let desc = D3D12_RESOURCE_DESC {
|
||||||
Dimension: D3D12_RESOURCE_DIMENSION_TEXTURE2D,
|
Dimension: D3D12_RESOURCE_DIMENSION_TEXTURE2D,
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
use crate::render::RenderTest;
|
use crate::render::RenderTest;
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use image::RgbaImage;
|
use image::RgbaImage;
|
||||||
|
use librashader::presets::ShaderPreset;
|
||||||
use librashader::runtime::d3d9::{FilterChain, FilterChainOptions};
|
use librashader::runtime::d3d9::{FilterChain, FilterChainOptions};
|
||||||
use librashader::runtime::Viewport;
|
use librashader::runtime::Viewport;
|
||||||
|
use librashader::runtime::{FilterChainParameters, RuntimeParameters};
|
||||||
use librashader_runtime::image::{Image, PixelFormat, UVDirection, BGRA8};
|
use librashader_runtime::image::{Image, PixelFormat, UVDirection, BGRA8};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use windows::Win32::Foundation::{HWND, TRUE};
|
use windows::Win32::Foundation::{HWND, TRUE};
|
||||||
|
@ -29,10 +31,15 @@ impl RenderTest for Direct3D9 {
|
||||||
Direct3D9::new(path)
|
Direct3D9::new(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render(&mut self, path: &Path, frame_count: usize) -> anyhow::Result<RgbaImage> {
|
fn render_with_preset_and_params(
|
||||||
|
&mut self,
|
||||||
|
preset: ShaderPreset,
|
||||||
|
frame_count: usize,
|
||||||
|
param_setter: Option<&dyn Fn(&RuntimeParameters)>,
|
||||||
|
) -> anyhow::Result<image::RgbaImage> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut filter_chain = FilterChain::load_from_path(
|
let mut filter_chain = FilterChain::load_from_preset(
|
||||||
path,
|
preset,
|
||||||
&self.device,
|
&self.device,
|
||||||
Some(&FilterChainOptions {
|
Some(&FilterChainOptions {
|
||||||
force_no_mipmaps: false,
|
force_no_mipmaps: false,
|
||||||
|
@ -40,6 +47,10 @@ impl RenderTest for Direct3D9 {
|
||||||
}),
|
}),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
if let Some(setter) = param_setter {
|
||||||
|
setter(filter_chain.parameters());
|
||||||
|
}
|
||||||
|
|
||||||
let mut render_texture = None;
|
let mut render_texture = None;
|
||||||
|
|
||||||
self.device.CreateTexture(
|
self.device.CreateTexture(
|
||||||
|
|
|
@ -5,8 +5,10 @@ use crate::render::RenderTest;
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use glow::{HasContext, PixelPackData, PixelUnpackData};
|
use glow::{HasContext, PixelPackData, PixelUnpackData};
|
||||||
use image::RgbaImage;
|
use image::RgbaImage;
|
||||||
|
use librashader::presets::ShaderPreset;
|
||||||
use librashader::runtime::gl::{FilterChain, FilterChainOptions, GLImage};
|
use librashader::runtime::gl::{FilterChain, FilterChainOptions, GLImage};
|
||||||
use librashader::runtime::Viewport;
|
use librashader::runtime::Viewport;
|
||||||
|
use librashader::runtime::{FilterChainParameters, RuntimeParameters};
|
||||||
use librashader_runtime::image::{Image, UVDirection, RGBA8};
|
use librashader_runtime::image::{Image, UVDirection, RGBA8};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
@ -28,10 +30,15 @@ impl RenderTest for OpenGl3 {
|
||||||
OpenGl3::new(path)
|
OpenGl3::new(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render(&mut self, path: &Path, frame_count: usize) -> anyhow::Result<RgbaImage> {
|
fn render_with_preset_and_params(
|
||||||
|
&mut self,
|
||||||
|
preset: ShaderPreset,
|
||||||
|
frame_count: usize,
|
||||||
|
param_setter: Option<&dyn Fn(&RuntimeParameters)>,
|
||||||
|
) -> anyhow::Result<image::RgbaImage> {
|
||||||
let mut filter_chain = unsafe {
|
let mut filter_chain = unsafe {
|
||||||
FilterChain::load_from_path(
|
FilterChain::load_from_preset(
|
||||||
path,
|
preset,
|
||||||
Arc::clone(&self.0.context.gl),
|
Arc::clone(&self.0.context.gl),
|
||||||
Some(&FilterChainOptions {
|
Some(&FilterChainOptions {
|
||||||
glsl_version: 330,
|
glsl_version: 330,
|
||||||
|
@ -42,6 +49,10 @@ impl RenderTest for OpenGl3 {
|
||||||
)
|
)
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
|
if let Some(setter) = param_setter {
|
||||||
|
setter(filter_chain.parameters());
|
||||||
|
}
|
||||||
|
|
||||||
Ok(self.0.render(&mut filter_chain, frame_count)?)
|
Ok(self.0.render(&mut filter_chain, frame_count)?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,10 +65,15 @@ impl RenderTest for OpenGl4 {
|
||||||
OpenGl4::new(path)
|
OpenGl4::new(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render(&mut self, path: &Path, frame_count: usize) -> anyhow::Result<RgbaImage> {
|
fn render_with_preset_and_params(
|
||||||
|
&mut self,
|
||||||
|
preset: ShaderPreset,
|
||||||
|
frame_count: usize,
|
||||||
|
param_setter: Option<&dyn Fn(&RuntimeParameters)>,
|
||||||
|
) -> anyhow::Result<image::RgbaImage> {
|
||||||
let mut filter_chain = unsafe {
|
let mut filter_chain = unsafe {
|
||||||
FilterChain::load_from_path(
|
FilterChain::load_from_preset(
|
||||||
path,
|
preset,
|
||||||
Arc::clone(&self.0.context.gl),
|
Arc::clone(&self.0.context.gl),
|
||||||
Some(&FilterChainOptions {
|
Some(&FilterChainOptions {
|
||||||
glsl_version: 460,
|
glsl_version: 460,
|
||||||
|
@ -68,6 +84,10 @@ impl RenderTest for OpenGl4 {
|
||||||
)
|
)
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
|
if let Some(setter) = param_setter {
|
||||||
|
setter(filter_chain.parameters());
|
||||||
|
}
|
||||||
|
|
||||||
Ok(self.0.render(&mut filter_chain, frame_count)?)
|
Ok(self.0.render(&mut filter_chain, frame_count)?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,8 @@ pub mod wgpu;
|
||||||
#[cfg(all(target_vendor = "apple", feature = "metal"))]
|
#[cfg(all(target_vendor = "apple", feature = "metal"))]
|
||||||
pub mod mtl;
|
pub mod mtl;
|
||||||
|
|
||||||
|
use librashader::presets::ShaderPreset;
|
||||||
|
use librashader_runtime::parameters::RuntimeParameters;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
/// Test harness to set up a device, render a triangle, and apply a shader
|
/// Test harness to set up a device, render a triangle, and apply a shader
|
||||||
|
@ -36,7 +38,41 @@ pub trait RenderTest {
|
||||||
/// For testing purposes, it is often that a single image will be reused with multiple
|
/// For testing purposes, it is often that a single image will be reused with multiple
|
||||||
/// shader presets, so the actual image that a shader will be applied to
|
/// shader presets, so the actual image that a shader will be applied to
|
||||||
/// will often be part of the test harness object.
|
/// will often be part of the test harness object.
|
||||||
fn render(&mut self, path: &Path, frame_count: usize) -> anyhow::Result<image::RgbaImage>;
|
fn render(&mut self, path: &Path, frame_count: usize) -> anyhow::Result<image::RgbaImage> {
|
||||||
|
let preset = ShaderPreset::try_parse(path)?;
|
||||||
|
self.render_with_preset(preset, frame_count)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Render a shader onto an image buffer, applying the provided shader.
|
||||||
|
///
|
||||||
|
/// The test should render in linear colour space for proper comparison against
|
||||||
|
/// backends.
|
||||||
|
///
|
||||||
|
/// For testing purposes, it is often that a single image will be reused with multiple
|
||||||
|
/// shader presets, so the actual image that a shader will be applied to
|
||||||
|
/// will often be part of the test harness object.
|
||||||
|
fn render_with_preset(
|
||||||
|
&mut self,
|
||||||
|
preset: ShaderPreset,
|
||||||
|
frame_count: usize,
|
||||||
|
) -> anyhow::Result<image::RgbaImage> {
|
||||||
|
self.render_with_preset_and_params(preset, frame_count, None)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Render a shader onto an image buffer, applying the provided shader.
|
||||||
|
///
|
||||||
|
/// The test should render in linear colour space for proper comparison against
|
||||||
|
/// backends.
|
||||||
|
///
|
||||||
|
/// For testing purposes, it is often that a single image will be reused with multiple
|
||||||
|
/// shader presets, so the actual image that a shader will be applied to
|
||||||
|
/// will often be part of the test harness object.
|
||||||
|
fn render_with_preset_and_params(
|
||||||
|
&mut self,
|
||||||
|
preset: ShaderPreset,
|
||||||
|
frame_count: usize,
|
||||||
|
param_setter: Option<&dyn Fn(&RuntimeParameters)>,
|
||||||
|
) -> anyhow::Result<image::RgbaImage>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
use crate::render::RenderTest;
|
use crate::render::RenderTest;
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use image::RgbaImage;
|
use image::RgbaImage;
|
||||||
|
use librashader::presets::ShaderPreset;
|
||||||
use librashader::runtime::mtl::{FilterChain, FilterChainOptions};
|
use librashader::runtime::mtl::{FilterChain, FilterChainOptions};
|
||||||
use librashader::runtime::Viewport;
|
use librashader::runtime::Viewport;
|
||||||
|
use librashader::runtime::{FilterChainParameters, RuntimeParameters};
|
||||||
use librashader_runtime::image::{Image, PixelFormat, UVDirection, BGRA8, RGBA8};
|
use librashader_runtime::image::{Image, PixelFormat, UVDirection, BGRA8, RGBA8};
|
||||||
use objc2::ffi::NSUInteger;
|
use objc2::ffi::NSUInteger;
|
||||||
use objc2::rc::Retained;
|
use objc2::rc::Retained;
|
||||||
|
@ -29,7 +31,12 @@ impl RenderTest for Metal {
|
||||||
Metal::new(path)
|
Metal::new(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render(&mut self, path: &Path, frame_count: usize) -> anyhow::Result<RgbaImage> {
|
fn render_with_preset_and_params(
|
||||||
|
&mut self,
|
||||||
|
preset: ShaderPreset,
|
||||||
|
frame_count: usize,
|
||||||
|
param_setter: Option<&dyn Fn(&RuntimeParameters)>,
|
||||||
|
) -> anyhow::Result<image::RgbaImage> {
|
||||||
let queue = self
|
let queue = self
|
||||||
.device
|
.device
|
||||||
.newCommandQueue()
|
.newCommandQueue()
|
||||||
|
@ -39,14 +46,18 @@ impl RenderTest for Metal {
|
||||||
.commandBuffer()
|
.commandBuffer()
|
||||||
.ok_or_else(|| anyhow!("Unable to create command buffer"))?;
|
.ok_or_else(|| anyhow!("Unable to create command buffer"))?;
|
||||||
|
|
||||||
let mut filter_chain = FilterChain::load_from_path(
|
let mut filter_chain = FilterChain::load_from_preset(
|
||||||
path,
|
preset,
|
||||||
&queue,
|
&queue,
|
||||||
Some(&FilterChainOptions {
|
Some(&FilterChainOptions {
|
||||||
force_no_mipmaps: false,
|
force_no_mipmaps: false,
|
||||||
}),
|
}),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
if let Some(setter) = param_setter {
|
||||||
|
setter(filter_chain.parameters());
|
||||||
|
}
|
||||||
|
|
||||||
let render_texture = unsafe {
|
let render_texture = unsafe {
|
||||||
let texture_descriptor =
|
let texture_descriptor =
|
||||||
MTLTextureDescriptor::texture2DDescriptorWithPixelFormat_width_height_mipmapped(
|
MTLTextureDescriptor::texture2DDescriptorWithPixelFormat_width_height_mipmapped(
|
||||||
|
|
|
@ -5,8 +5,10 @@ use anyhow::anyhow;
|
||||||
use ash::vk;
|
use ash::vk;
|
||||||
use gpu_allocator::MemoryLocation;
|
use gpu_allocator::MemoryLocation;
|
||||||
use image::RgbaImage;
|
use image::RgbaImage;
|
||||||
|
use librashader::presets::ShaderPreset;
|
||||||
use librashader::runtime::vk::{FilterChain, FilterChainOptions, VulkanImage};
|
use librashader::runtime::vk::{FilterChain, FilterChainOptions, VulkanImage};
|
||||||
use librashader::runtime::Viewport;
|
use librashader::runtime::Viewport;
|
||||||
|
use librashader::runtime::{FilterChainParameters, RuntimeParameters};
|
||||||
use librashader_runtime::image::{Image, UVDirection, BGRA8};
|
use librashader_runtime::image::{Image, UVDirection, BGRA8};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
|
@ -30,10 +32,15 @@ impl RenderTest for Vulkan {
|
||||||
Vulkan::new(path)
|
Vulkan::new(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render(&mut self, path: &Path, frame_count: usize) -> anyhow::Result<RgbaImage> {
|
fn render_with_preset_and_params(
|
||||||
|
&mut self,
|
||||||
|
preset: ShaderPreset,
|
||||||
|
frame_count: usize,
|
||||||
|
param_setter: Option<&dyn Fn(&RuntimeParameters)>,
|
||||||
|
) -> anyhow::Result<image::RgbaImage> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut filter_chain = FilterChain::load_from_path(
|
let mut filter_chain = FilterChain::load_from_preset(
|
||||||
path,
|
preset,
|
||||||
&self.vk,
|
&self.vk,
|
||||||
Some(&FilterChainOptions {
|
Some(&FilterChainOptions {
|
||||||
frames_in_flight: 3,
|
frames_in_flight: 3,
|
||||||
|
@ -43,6 +50,10 @@ impl RenderTest for Vulkan {
|
||||||
}),
|
}),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
if let Some(setter) = param_setter {
|
||||||
|
setter(filter_chain.parameters());
|
||||||
|
}
|
||||||
|
|
||||||
let image_info = vk::ImageCreateInfo::default()
|
let image_info = vk::ImageCreateInfo::default()
|
||||||
.image_type(vk::ImageType::TYPE_2D)
|
.image_type(vk::ImageType::TYPE_2D)
|
||||||
.format(vk::Format::B8G8R8A8_UNORM)
|
.format(vk::Format::B8G8R8A8_UNORM)
|
||||||
|
|
|
@ -14,6 +14,8 @@ use wgpu_types::{
|
||||||
ImageDataLayout, Maintain, TextureDescriptor, TextureDimension, TextureFormat, TextureUsages,
|
ImageDataLayout, Maintain, TextureDescriptor, TextureDimension, TextureFormat, TextureUsages,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use librashader::presets::ShaderPreset;
|
||||||
|
use librashader::runtime::{FilterChainParameters, RuntimeParameters};
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
|
|
||||||
pub struct Wgpu {
|
pub struct Wgpu {
|
||||||
|
@ -54,9 +56,14 @@ impl RenderTest for Wgpu {
|
||||||
Wgpu::new(path)
|
Wgpu::new(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render(&mut self, path: &Path, frame_count: usize) -> anyhow::Result<RgbaImage> {
|
fn render_with_preset_and_params(
|
||||||
let mut chain = FilterChain::load_from_path(
|
&mut self,
|
||||||
path,
|
preset: ShaderPreset,
|
||||||
|
frame_count: usize,
|
||||||
|
param_setter: Option<&dyn Fn(&RuntimeParameters)>,
|
||||||
|
) -> anyhow::Result<image::RgbaImage> {
|
||||||
|
let mut chain = FilterChain::load_from_preset(
|
||||||
|
preset,
|
||||||
Arc::clone(&self.device),
|
Arc::clone(&self.device),
|
||||||
Arc::clone(&self.queue),
|
Arc::clone(&self.queue),
|
||||||
Some(&FilterChainOptions {
|
Some(&FilterChainOptions {
|
||||||
|
@ -65,7 +72,9 @@ impl RenderTest for Wgpu {
|
||||||
adapter_info: None,
|
adapter_info: None,
|
||||||
}),
|
}),
|
||||||
)?;
|
)?;
|
||||||
|
if let Some(setter) = param_setter {
|
||||||
|
setter(&chain.parameters());
|
||||||
|
}
|
||||||
let mut cmd = self
|
let mut cmd = self
|
||||||
.device
|
.device
|
||||||
.create_command_encoder(&CommandEncoderDescriptor { label: None });
|
.create_command_encoder(&CommandEncoderDescriptor { label: None });
|
||||||
|
|
|
@ -42,6 +42,7 @@ impl RuntimeParameters {
|
||||||
/// Set a runtime parameter.
|
/// Set a runtime parameter.
|
||||||
///
|
///
|
||||||
/// This is a relatively slow operation as it will be synchronized across threads.
|
/// This is a relatively slow operation as it will be synchronized across threads.
|
||||||
|
/// If updating multiple parameters, see [`RuntimeParameters::update_parameters`].
|
||||||
pub fn set_parameter_value(&self, name: &str, new_value: f32) -> Option<f32> {
|
pub fn set_parameter_value(&self, name: &str, new_value: f32) -> Option<f32> {
|
||||||
let mut updated_map = FastHashMap::clone(&self.parameters.load());
|
let mut updated_map = FastHashMap::clone(&self.parameters.load());
|
||||||
|
|
||||||
|
@ -57,6 +58,13 @@ impl RuntimeParameters {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Update multiple runtime parameters atomically through a function.
|
||||||
|
pub fn update_parameters(&self, updater: impl FnOnce(&mut FastHashMap<ShortString, f32>)) {
|
||||||
|
let mut updated_map = FastHashMap::clone(&self.parameters.load());
|
||||||
|
updater(&mut updated_map);
|
||||||
|
self.parameters.store(Arc::new(updated_map));
|
||||||
|
}
|
||||||
|
|
||||||
/// Get a reference to the runtime parameters.
|
/// Get a reference to the runtime parameters.
|
||||||
pub fn parameters(&self) -> Arc<FastHashMap<ShortString, f32>> {
|
pub fn parameters(&self) -> Arc<FastHashMap<ShortString, f32>> {
|
||||||
self.parameters.load_full()
|
self.parameters.load_full()
|
||||||
|
|
Loading…
Reference in a new issue