cli(render): allow specifying output dimensions

This commit is contained in:
chyyran 2024-10-04 02:41:36 -04:00 committed by Ronny Chan
parent 4abd48eb24
commit 95a489ee12
12 changed files with 191 additions and 58 deletions

13
CLI.md
View file

@ -9,11 +9,12 @@ Commands:
render Render a shader preset against an image render Render a shader preset against an image
compare Compare two runtimes and get a similarity score between the two runtimes rendering the same frame compare Compare two runtimes and get a similarity score between the two runtimes rendering the same frame
parse Parse a preset and get a JSON representation of the data parse Parse a preset and get a JSON representation of the data
pack Create a serialized preset pack from a shader preset
preprocess Get the raw GLSL output of a preprocessed shader preprocess Get the raw GLSL output of a preprocessed shader
transpile Transpile a shader in a given preset to the given format transpile Transpile a shader in a given preset to the given format
reflect Reflect the shader relative to a preset, giving information about semantics used in a slang shader reflect Reflect the shader relative to a preset, giving information about semantics used in a slang shader
help Print this message or the help of the given subcommand(s) help Print this message or the help of the given subcommand(s)
Options: Options:
-h, --help Print help -h, --help Print help
-V, --version Print version -V, --version Print version
@ -52,6 +53,11 @@ Options:
The renderer will run up to the number of frames specified here to ensure feedback and history. The renderer will run up to the number of frames specified here to ensure feedback and history.
[default: 0] [default: 0]
-d, --dimensions <DIMENSIONS>
The dimensions of the image.
This is given in either explicit dimensions `WIDTHxHEIGHT`, or a percentage of the input image in `SCALE%`.
--params <PARAMS>... --params <PARAMS>...
Parameters to pass to the shader preset, comma separated with equals signs. Parameters to pass to the shader preset, comma separated with equals signs.
@ -136,6 +142,11 @@ Options:
The renderer will run up to the number of frames specified here to ensure feedback and history. The renderer will run up to the number of frames specified here to ensure feedback and history.
[default: 0] [default: 0]
-d, --dimensions <DIMENSIONS>
The dimensions of the image.
This is given in either explicit dimensions `WIDTHxHEIGHT`, or a percentage of the input image in `SCALE%`.
--params <PARAMS>... --params <PARAMS>...
Parameters to pass to the shader preset, comma separated with equals signs. Parameters to pass to the shader preset, comma separated with equals signs.

View file

@ -111,6 +111,7 @@ Commands:
render Render a shader preset against an image render Render a shader preset against an image
compare Compare two runtimes and get a similarity score between the two runtimes rendering the same frame compare Compare two runtimes and get a similarity score between the two runtimes rendering the same frame
parse Parse a preset and get a JSON representation of the data parse Parse a preset and get a JSON representation of the data
pack Create a serialized preset pack from a shader preset
preprocess Get the raw GLSL output of a preprocessed shader preprocess Get the raw GLSL output of a preprocessed shader
transpile Transpile a shader in a given preset to the given format transpile Transpile a shader in a given preset to the given format
reflect Reflect the shader relative to a preset, giving information about semantics used in a slang shader reflect Reflect the shader relative to a preset, giving information about semantics used in a slang shader

View file

@ -49,7 +49,7 @@ pub enum LIBRA_PRESET_CTX_RUNTIME {
/// Metal /// Metal
Metal, Metal,
/// Direct3D 9 /// Direct3D 9
D3D9_HLSL D3D9_HLSL,
} }
impl From<LIBRA_PRESET_CTX_RUNTIME> for VideoDriver { impl From<LIBRA_PRESET_CTX_RUNTIME> for VideoDriver {
@ -61,7 +61,7 @@ impl From<LIBRA_PRESET_CTX_RUNTIME> for VideoDriver {
LIBRA_PRESET_CTX_RUNTIME::D3D11 => VideoDriver::Direct3D11, LIBRA_PRESET_CTX_RUNTIME::D3D11 => VideoDriver::Direct3D11,
LIBRA_PRESET_CTX_RUNTIME::D3D12 => VideoDriver::Direct3D12, LIBRA_PRESET_CTX_RUNTIME::D3D12 => VideoDriver::Direct3D12,
LIBRA_PRESET_CTX_RUNTIME::Metal => VideoDriver::Metal, LIBRA_PRESET_CTX_RUNTIME::Metal => VideoDriver::Metal,
LIBRA_PRESET_CTX_RUNTIME::D3D9_HLSL => VideoDriver::Direct3D9Hlsl LIBRA_PRESET_CTX_RUNTIME::D3D9_HLSL => VideoDriver::Direct3D9Hlsl,
} }
} }
} }

View file

@ -7,6 +7,7 @@ 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::runtime::Size;
use librashader::{FastHashMap, ShortString}; use librashader::{FastHashMap, ShortString};
use librashader_runtime::parameters::RuntimeParameters; use librashader_runtime::parameters::RuntimeParameters;
use librashader_test::render::{CommonFrameOptions, RenderTest}; use librashader_test::render::{CommonFrameOptions, RenderTest};
@ -43,6 +44,12 @@ struct RenderArgs {
/// to ensure feedback and history. /// to ensure feedback and history.
#[arg(short, long, default_value_t = 0)] #[arg(short, long, default_value_t = 0)]
frame: usize, frame: usize,
/// The dimensions of the image.
///
/// This is given in either explicit dimensions `WIDTHxHEIGHT`, or a
/// percentage of the input image in `SCALE%`.
#[arg(short, long)]
dimensions: Option<String>,
/// Parameters to pass to the shader preset, comma separated with equals signs. /// Parameters to pass to the shader preset, comma separated with equals signs.
/// ///
/// For example, crt_gamma=2.5,halation_weight=0.001 /// For example, crt_gamma=2.5,halation_weight=0.001
@ -313,6 +320,7 @@ pub fn main() -> Result<(), anyhow::Error> {
let PresetArgs { preset, wildcards } = preset; let PresetArgs { preset, wildcards } = preset;
let RenderArgs { let RenderArgs {
frame, frame,
dimensions,
params, params,
passes_enabled, passes_enabled,
image, image,
@ -320,13 +328,14 @@ pub fn main() -> Result<(), anyhow::Error> {
} = render; } = render;
let test: &mut dyn RenderTest = get_runtime!(runtime, image); let test: &mut dyn RenderTest = get_runtime!(runtime, image);
let dimensions = parse_dimension(dimensions, test.image_size())?;
let preset = get_shader_preset(preset, wildcards)?; let preset = get_shader_preset(preset, wildcards)?;
let params = parse_params(params)?; let params = parse_params(params)?;
let image = test.render_with_preset_and_params( let image = test.render_with_preset_and_params(
preset, preset,
frame, frame,
Some(dimensions),
Some(&|rp| set_params(rp, &params, passes_enabled)), Some(&|rp| set_params(rp, &params, passes_enabled)),
options.map(CommonFrameOptions::from), options.map(CommonFrameOptions::from),
)?; )?;
@ -348,6 +357,7 @@ pub fn main() -> Result<(), anyhow::Error> {
let PresetArgs { preset, wildcards } = preset; let PresetArgs { preset, wildcards } = preset;
let RenderArgs { let RenderArgs {
frame, frame,
dimensions,
params, params,
passes_enabled, passes_enabled,
image, image,
@ -357,12 +367,14 @@ 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 dimensions = parse_dimension(dimensions, left.image_size())?;
let params = parse_params(params)?; let params = parse_params(params)?;
let left_preset = get_shader_preset(preset.clone(), wildcards.clone())?; let left_preset = get_shader_preset(preset.clone(), wildcards.clone())?;
let left_image = left.render_with_preset_and_params( let left_image = left.render_with_preset_and_params(
left_preset, left_preset,
frame, frame,
Some(dimensions),
Some(&|rp| set_params(rp, &params, passes_enabled)), Some(&|rp| set_params(rp, &params, passes_enabled)),
None, None,
)?; )?;
@ -371,6 +383,7 @@ pub fn main() -> Result<(), anyhow::Error> {
let right_image = right.render_with_preset_and_params( let right_image = right.render_with_preset_and_params(
right_preset, right_preset,
frame, frame,
Some(dimensions),
Some(&|rp| set_params(rp, &params, passes_enabled)), Some(&|rp| set_params(rp, &params, passes_enabled)),
options.map(CommonFrameOptions::from), options.map(CommonFrameOptions::from),
)?; )?;
@ -742,3 +755,47 @@ fn parse_msl_version(version_str: &str) -> anyhow::Result<MslVersion> {
_ => return Err(anyhow!("Unknown MSL version")), _ => return Err(anyhow!("Unknown MSL version")),
}) })
} }
fn parse_dimension(dimstr: Option<String>, image_dim: Size<u32>) -> anyhow::Result<Size<u32>> {
let Some(dimstr) = dimstr else {
return Ok(image_dim);
};
if dimstr.contains("x") {
if let Some((Ok(width), Ok(height))) = dimstr
.split_once("x")
.map(|(width, height)| (width.parse::<u32>(), height.parse::<u32>()))
{
if width < 1 || height < 1 {
return Err(anyhow!("Dimensions must be larger than 1x1"));
}
if width > 16384 || height > 16384 {
return Err(anyhow!("Dimensions must not be larger than 16384x16384"));
}
return Ok(Size::new(width, height));
}
}
if dimstr.ends_with("%") && dimstr.len() > 1 {
if let Ok(percent) = dimstr.trim_end_matches("%").parse::<u32>() {
let percent = percent as f32 / 100f32;
let width = (image_dim.width as f32 * percent) as u32;
let height = (image_dim.height as f32 * percent) as u32;
if width < 1 || height < 1 {
return Err(anyhow!("Dimensions must be larger than 1x1"));
}
if width > 16384 || height > 16384 {
return Err(anyhow!("Dimensions must not be larger than 16384x16384"));
}
return Ok(Size { width, height });
}
}
Err(anyhow!(
"Invalid dimension syntax, must either in form WIDTHxHEIGHT or SCALE%"
))
}

View file

@ -4,6 +4,8 @@ use image::RgbaImage;
use librashader::runtime::d3d11::*; use librashader::runtime::d3d11::*;
use librashader::runtime::{FilterChainParameters, RuntimeParameters}; use librashader::runtime::{FilterChainParameters, RuntimeParameters};
use librashader::runtime::{Size, Viewport}; use librashader::runtime::{Size, Viewport};
use std::io::{Cursor, Write};
use std::ops::DerefMut;
use std::path::Path; use std::path::Path;
impl RenderTest for Direct3D11 { impl RenderTest for Direct3D11 {
@ -14,14 +16,20 @@ impl RenderTest for Direct3D11 {
Direct3D11::new(path) Direct3D11::new(path)
} }
fn image_size(&self) -> Size<u32> {
self.image_bytes.size
}
fn render_with_preset_and_params( fn render_with_preset_and_params(
&mut self, &mut self,
preset: ShaderPreset, preset: ShaderPreset,
frame_count: usize, frame_count: usize,
output_size: Option<Size<u32>>,
param_setter: Option<&dyn Fn(&RuntimeParameters)>, param_setter: Option<&dyn Fn(&RuntimeParameters)>,
frame_options: Option<CommonFrameOptions>, frame_options: Option<CommonFrameOptions>,
) -> anyhow::Result<image::RgbaImage> { ) -> anyhow::Result<image::RgbaImage> {
let (renderbuffer, rtv) = self.create_renderbuffer(self.image_bytes.size)?; let output_size = output_size.unwrap_or(self.image_bytes.size);
let (renderbuffer, rtv) = self.create_renderbuffer(output_size)?;
unsafe { unsafe {
let mut filter_chain = FilterChain::load_from_preset( let mut filter_chain = FilterChain::load_from_preset(
@ -50,10 +58,10 @@ impl RenderTest for Direct3D11 {
} }
let mut renderbuffer_desc = Default::default(); let mut renderbuffer_desc = Default::default();
self.immediate_context.Flush();
renderbuffer.GetDesc(&mut renderbuffer_desc); renderbuffer.GetDesc(&mut renderbuffer_desc);
self.immediate_context.Flush(); eprintln!("{:?}", renderbuffer_desc);
let mut staging = None; let mut staging = None;
self.device.CreateTexture2D( self.device.CreateTexture2D(
&D3D11_TEXTURE2D_DESC { &D3D11_TEXTURE2D_DESC {
@ -72,6 +80,8 @@ impl RenderTest for Direct3D11 {
self.immediate_context.CopyResource(&staging, &renderbuffer); self.immediate_context.CopyResource(&staging, &renderbuffer);
let mut pixels: Vec<u8> = Vec::new();
let mut map_info = Default::default(); let mut map_info = Default::default();
self.immediate_context self.immediate_context
.Map(&staging, 0, D3D11_MAP_READ, 0, Some(&mut map_info))?; .Map(&staging, 0, D3D11_MAP_READ, 0, Some(&mut map_info))?;
@ -80,13 +90,18 @@ impl RenderTest for Direct3D11 {
map_info.pData as *const u8, map_info.pData as *const u8,
(renderbuffer_desc.Height * map_info.RowPitch) as usize, (renderbuffer_desc.Height * map_info.RowPitch) as usize,
); );
pixels.resize(
(renderbuffer_desc.Height * renderbuffer_desc.Width * 4) as usize,
0,
);
let image = RgbaImage::from_raw( let mut cursor = Cursor::new(pixels.deref_mut());
renderbuffer_desc.Width, for chunk in slice.chunks(map_info.RowPitch as usize) {
renderbuffer_desc.Height, cursor.write_all(&chunk[..(renderbuffer_desc.Width * 4) as usize])?
Vec::from(slice), }
)
.ok_or(anyhow!("Unable to create image from data"))?; let image = RgbaImage::from_raw(output_size.width, output_size.height, pixels)
.ok_or(anyhow!("Unable to create image from data"))?;
self.immediate_context.Unmap(&staging, 0); self.immediate_context.Unmap(&staging, 0);
Ok(image) Ok(image)

View file

@ -8,8 +8,8 @@ use d3d12_descriptor_heap::{D3D12DescriptorHeap, D3D12DescriptorHeapSlot};
use image::RgbaImage; use image::RgbaImage;
use librashader::presets::ShaderPreset; use librashader::presets::ShaderPreset;
use librashader::runtime::d3d12::{D3D12OutputView, FilterChain, FilterChainOptions, FrameOptions}; use librashader::runtime::d3d12::{D3D12OutputView, FilterChain, FilterChainOptions, FrameOptions};
use librashader::runtime::Viewport;
use librashader::runtime::{FilterChainParameters, RuntimeParameters}; use librashader::runtime::{FilterChainParameters, RuntimeParameters};
use librashader::runtime::{Size, Viewport};
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,10 +58,14 @@ impl RenderTest for Direct3D12 {
Direct3D12::new(path) Direct3D12::new(path)
} }
fn image_size(&self) -> Size<u32> {
self.image.size
}
fn render_with_preset_and_params( fn render_with_preset_and_params(
&mut self, &mut self,
preset: ShaderPreset, preset: ShaderPreset,
frame_count: usize, frame_count: usize,
output_size: Option<Size<u32>>,
param_setter: Option<&dyn Fn(&RuntimeParameters)>, param_setter: Option<&dyn Fn(&RuntimeParameters)>,
frame_options: Option<CommonFrameOptions>, frame_options: Option<CommonFrameOptions>,
) -> anyhow::Result<image::RgbaImage> { ) -> anyhow::Result<image::RgbaImage> {
@ -92,12 +96,13 @@ impl RenderTest for Direct3D12 {
setter(filter_chain.parameters()); setter(filter_chain.parameters());
} }
let output_size = output_size.unwrap_or(self.image.size);
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,
Alignment: 0, Alignment: 0,
Width: self.image.size.width as u64, Width: output_size.width as u64,
Height: self.image.size.height, Height: output_size.height,
DepthOrArraySize: 1, DepthOrArraySize: 1,
MipLevels: 1, MipLevels: 1,
Format: DXGI_FORMAT_B8G8R8A8_UNORM, Format: DXGI_FORMAT_B8G8R8A8_UNORM,
@ -135,7 +140,7 @@ impl RenderTest for Direct3D12 {
let viewport = Viewport::new_render_target_sized_origin( let viewport = Viewport::new_render_target_sized_origin(
D3D12OutputView::new_from_raw( D3D12OutputView::new_from_raw(
*descriptor.as_ref(), *descriptor.as_ref(),
self.image.size, output_size,
DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM,
), ),
None, None,
@ -165,11 +170,11 @@ impl RenderTest for Direct3D12 {
CloseHandle(fence_event)?; CloseHandle(fence_event)?;
}; };
let mut buffer = vec![0u8; self.image.bytes.len()]; let mut buffer = vec![0u8; (output_size.height * output_size.width) as usize * 4];
output_texture.ReadFromSubresource( output_texture.ReadFromSubresource(
buffer.as_mut_ptr().cast(), buffer.as_mut_ptr().cast(),
4 * self.image.size.width, 4 * output_size.width,
0, 0,
0, 0,
None, None,
@ -177,12 +182,9 @@ impl RenderTest for Direct3D12 {
BGRA8::convert(&mut buffer); BGRA8::convert(&mut buffer);
let image = RgbaImage::from_raw( let image =
self.image.size.width, RgbaImage::from_raw(output_size.width, output_size.height, Vec::from(buffer))
self.image.size.height, .ok_or(anyhow!("Unable to create image from data"))?;
Vec::from(buffer),
)
.ok_or(anyhow!("Unable to create image from data"))?;
Ok(image) Ok(image)
} }

View file

@ -3,8 +3,8 @@ use anyhow::anyhow;
use image::RgbaImage; use image::RgbaImage;
use librashader::presets::ShaderPreset; use librashader::presets::ShaderPreset;
use librashader::runtime::d3d9::{FilterChain, FilterChainOptions, FrameOptions}; use librashader::runtime::d3d9::{FilterChain, FilterChainOptions, FrameOptions};
use librashader::runtime::Viewport;
use librashader::runtime::{FilterChainParameters, RuntimeParameters}; use librashader::runtime::{FilterChainParameters, RuntimeParameters};
use librashader::runtime::{Size, Viewport};
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};
@ -31,10 +31,15 @@ impl RenderTest for Direct3D9 {
Direct3D9::new(path) Direct3D9::new(path)
} }
fn image_size(&self) -> Size<u32> {
self.image.size
}
fn render_with_preset_and_params( fn render_with_preset_and_params(
&mut self, &mut self,
preset: ShaderPreset, preset: ShaderPreset,
frame_count: usize, frame_count: usize,
output_size: Option<Size<u32>>,
param_setter: Option<&dyn Fn(&RuntimeParameters)>, param_setter: Option<&dyn Fn(&RuntimeParameters)>,
frame_options: Option<CommonFrameOptions>, frame_options: Option<CommonFrameOptions>,
) -> anyhow::Result<image::RgbaImage> { ) -> anyhow::Result<image::RgbaImage> {
@ -54,9 +59,10 @@ impl RenderTest for Direct3D9 {
let mut render_texture = None; let mut render_texture = None;
let output_size = output_size.unwrap_or(self.image.size);
self.device.CreateTexture( self.device.CreateTexture(
self.image.size.width, output_size.width,
self.image.size.height, output_size.height,
1, 1,
D3DUSAGE_RENDERTARGET as u32, D3DUSAGE_RENDERTARGET as u32,
D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8,
@ -71,8 +77,8 @@ impl RenderTest for Direct3D9 {
let mut copy_texture = None; let mut copy_texture = None;
self.device.CreateOffscreenPlainSurface( self.device.CreateOffscreenPlainSurface(
self.image.size.width, output_size.width,
self.image.size.height, output_size.height,
D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8,
D3DPOOL_SYSTEMMEM, D3DPOOL_SYSTEMMEM,
&mut copy_texture, &mut copy_texture,
@ -112,7 +118,7 @@ impl RenderTest for Direct3D9 {
BGRA8::convert(&mut buffer); BGRA8::convert(&mut buffer);
let image = RgbaImage::from_raw(self.image.size.width, self.image.size.height, buffer) let image = RgbaImage::from_raw(output_size.width, output_size.height, buffer)
.ok_or(anyhow!("Unable to create image from data"))?; .ok_or(anyhow!("Unable to create image from data"))?;
Ok(image) Ok(image)

View file

@ -7,8 +7,8 @@ use glow::{HasContext, PixelPackData, PixelUnpackData};
use image::RgbaImage; use image::RgbaImage;
use librashader::presets::ShaderPreset; use librashader::presets::ShaderPreset;
use librashader::runtime::gl::{FilterChain, FilterChainOptions, FrameOptions, GLImage}; use librashader::runtime::gl::{FilterChain, FilterChainOptions, FrameOptions, GLImage};
use librashader::runtime::Viewport;
use librashader::runtime::{FilterChainParameters, RuntimeParameters}; use librashader::runtime::{FilterChainParameters, RuntimeParameters};
use librashader::runtime::{Size, Viewport};
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;
@ -30,10 +30,15 @@ impl RenderTest for OpenGl3 {
OpenGl3::new(path) OpenGl3::new(path)
} }
fn image_size(&self) -> Size<u32> {
self.0.image_bytes.size
}
fn render_with_preset_and_params( fn render_with_preset_and_params(
&mut self, &mut self,
preset: ShaderPreset, preset: ShaderPreset,
frame_count: usize, frame_count: usize,
output_size: Option<Size<u32>>,
param_setter: Option<&dyn Fn(&RuntimeParameters)>, param_setter: Option<&dyn Fn(&RuntimeParameters)>,
frame_options: Option<CommonFrameOptions>, frame_options: Option<CommonFrameOptions>,
) -> anyhow::Result<image::RgbaImage> { ) -> anyhow::Result<image::RgbaImage> {
@ -57,6 +62,7 @@ impl RenderTest for OpenGl3 {
Ok(self.0.render( Ok(self.0.render(
&mut filter_chain, &mut filter_chain,
frame_count, frame_count,
output_size,
frame_options frame_options
.map(|options| FrameOptions { .map(|options| FrameOptions {
clear_history: options.clear_history, clear_history: options.clear_history,
@ -78,10 +84,15 @@ impl RenderTest for OpenGl4 {
OpenGl4::new(path) OpenGl4::new(path)
} }
fn image_size(&self) -> Size<u32> {
self.0.image_bytes.size
}
fn render_with_preset_and_params( fn render_with_preset_and_params(
&mut self, &mut self,
preset: ShaderPreset, preset: ShaderPreset,
frame_count: usize, frame_count: usize,
output_size: Option<Size<u32>>,
param_setter: Option<&dyn Fn(&RuntimeParameters)>, param_setter: Option<&dyn Fn(&RuntimeParameters)>,
frame_options: Option<CommonFrameOptions>, frame_options: Option<CommonFrameOptions>,
) -> anyhow::Result<image::RgbaImage> { ) -> anyhow::Result<image::RgbaImage> {
@ -105,6 +116,7 @@ impl RenderTest for OpenGl4 {
Ok(self.0.render( Ok(self.0.render(
&mut filter_chain, &mut filter_chain,
frame_count, frame_count,
output_size,
frame_options frame_options
.map(|options| FrameOptions { .map(|options| FrameOptions {
clear_history: options.clear_history, clear_history: options.clear_history,
@ -189,8 +201,11 @@ impl OpenGl {
&self, &self,
chain: &mut FilterChain, chain: &mut FilterChain,
frame_count: usize, frame_count: usize,
output_size: Option<Size<u32>>,
options: Option<&FrameOptions>, options: Option<&FrameOptions>,
) -> Result<RgbaImage, anyhow::Error> { ) -> Result<RgbaImage, anyhow::Error> {
let output_size = output_size.unwrap_or(self.image_bytes.size);
let render_texture = unsafe { let render_texture = unsafe {
let tex = self let tex = self
.context .context
@ -202,8 +217,8 @@ impl OpenGl {
glow::TEXTURE_2D, glow::TEXTURE_2D,
1, 1,
glow::RGBA8, glow::RGBA8,
self.image_bytes.size.width as i32, output_size.width as i32,
self.image_bytes.size.height as i32, output_size.height as i32,
); );
self.context.gl.bind_texture(glow::TEXTURE_2D, None); self.context.gl.bind_texture(glow::TEXTURE_2D, None);
tex tex
@ -212,7 +227,7 @@ impl OpenGl {
let output = GLImage { let output = GLImage {
handle: Some(render_texture), handle: Some(render_texture),
format: glow::RGBA8, format: glow::RGBA8,
size: self.image_bytes.size, size: output_size,
}; };
let viewport = Viewport::new_render_target_sized_origin(&output, None)?; let viewport = Viewport::new_render_target_sized_origin(&output, None)?;
@ -222,8 +237,7 @@ impl OpenGl {
} }
} }
// should be the same size as the input image let mut data = vec![0u8; output_size.width as usize * output_size.height as usize * 4];
let mut data = vec![0u8; self.image_bytes.bytes.len()];
unsafe { unsafe {
self.context self.context
@ -237,11 +251,9 @@ impl OpenGl {
PixelPackData::Slice(&mut data), PixelPackData::Slice(&mut data),
) )
} }
Ok(RgbaImage::from_raw( Ok(
self.image_bytes.size.width, RgbaImage::from_raw(output_size.width, output_size.height, data)
self.image_bytes.size.height, .ok_or(anyhow!("failed to create image from slice"))?,
data,
) )
.ok_or(anyhow!("failed to create image from slice"))?)
} }
} }

View file

@ -20,6 +20,7 @@ pub mod wgpu;
pub mod mtl; pub mod mtl;
use librashader::presets::ShaderPreset; use librashader::presets::ShaderPreset;
use librashader::runtime::Size;
use librashader_runtime::impl_default_frame_options; use librashader_runtime::impl_default_frame_options;
use librashader_runtime::parameters::RuntimeParameters; use librashader_runtime::parameters::RuntimeParameters;
use std::path::Path; use std::path::Path;
@ -31,6 +32,9 @@ pub trait RenderTest {
where where
Self: Sized; Self: Sized;
/// Get the size of the image loaded.
fn image_size(&self) -> Size<u32>;
/// Render a shader onto an image buffer, applying the provided shader. /// Render a shader onto an image buffer, applying the provided shader.
/// ///
/// The test should render in linear colour space for proper comparison against /// The test should render in linear colour space for proper comparison against
@ -39,9 +43,14 @@ 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,
output_size: Option<Size<u32>>,
) -> anyhow::Result<image::RgbaImage> {
let preset = ShaderPreset::try_parse(path)?; let preset = ShaderPreset::try_parse(path)?;
self.render_with_preset(preset, frame_count) self.render_with_preset(preset, frame_count, output_size)
} }
/// Render a shader onto an image buffer, applying the provided shader. /// Render a shader onto an image buffer, applying the provided shader.
@ -56,8 +65,9 @@ pub trait RenderTest {
&mut self, &mut self,
preset: ShaderPreset, preset: ShaderPreset,
frame_count: usize, frame_count: usize,
output_size: Option<Size<u32>>,
) -> anyhow::Result<image::RgbaImage> { ) -> anyhow::Result<image::RgbaImage> {
self.render_with_preset_and_params(preset, frame_count, None, None) self.render_with_preset_and_params(preset, frame_count, output_size, None, None)
} }
/// Render a shader onto an image buffer, applying the provided shader. /// Render a shader onto an image buffer, applying the provided shader.
@ -72,6 +82,7 @@ pub trait RenderTest {
&mut self, &mut self,
preset: ShaderPreset, preset: ShaderPreset,
frame_count: usize, frame_count: usize,
output_size: Option<Size<u32>>,
param_setter: Option<&dyn Fn(&RuntimeParameters)>, param_setter: Option<&dyn Fn(&RuntimeParameters)>,
frame_options: Option<CommonFrameOptions>, frame_options: Option<CommonFrameOptions>,
) -> anyhow::Result<image::RgbaImage>; ) -> anyhow::Result<image::RgbaImage>;

View file

@ -3,8 +3,8 @@ use anyhow::anyhow;
use image::RgbaImage; use image::RgbaImage;
use librashader::presets::ShaderPreset; use librashader::presets::ShaderPreset;
use librashader::runtime::mtl::{FilterChain, FilterChainOptions, FrameOptions}; use librashader::runtime::mtl::{FilterChain, FilterChainOptions, FrameOptions};
use librashader::runtime::Viewport;
use librashader::runtime::{FilterChainParameters, RuntimeParameters}; use librashader::runtime::{FilterChainParameters, RuntimeParameters};
use librashader::runtime::{Size, Viewport};
use librashader_runtime::image::{Image, PixelFormat, UVDirection, BGRA8}; use librashader_runtime::image::{Image, PixelFormat, UVDirection, BGRA8};
use objc2::ffi::NSUInteger; use objc2::ffi::NSUInteger;
use objc2::rc::Retained; use objc2::rc::Retained;
@ -31,10 +31,15 @@ impl RenderTest for Metal {
Metal::new(path) Metal::new(path)
} }
fn image_size(&self) -> Size<u32> {
self.image_bytes.size
}
fn render_with_preset_and_params( fn render_with_preset_and_params(
&mut self, &mut self,
preset: ShaderPreset, preset: ShaderPreset,
frame_count: usize, frame_count: usize,
output_size: Option<Size<u32>>,
param_setter: Option<&dyn Fn(&RuntimeParameters)>, param_setter: Option<&dyn Fn(&RuntimeParameters)>,
frame_options: Option<CommonFrameOptions>, frame_options: Option<CommonFrameOptions>,
) -> anyhow::Result<image::RgbaImage> { ) -> anyhow::Result<image::RgbaImage> {
@ -59,12 +64,14 @@ impl RenderTest for Metal {
setter(filter_chain.parameters()); setter(filter_chain.parameters());
} }
let output_size = output_size.unwrap_or(self.image_bytes.size);
let render_texture = unsafe { let render_texture = unsafe {
let texture_descriptor = let texture_descriptor =
MTLTextureDescriptor::texture2DDescriptorWithPixelFormat_width_height_mipmapped( MTLTextureDescriptor::texture2DDescriptorWithPixelFormat_width_height_mipmapped(
MTLPixelFormat::BGRA8Unorm, MTLPixelFormat::BGRA8Unorm,
self.image_bytes.size.width as NSUInteger, output_size.width as NSUInteger,
self.image_bytes.size.height as NSUInteger, output_size.height as NSUInteger,
false, false,
); );
@ -113,18 +120,19 @@ impl RenderTest for Metal {
let region = MTLRegion { let region = MTLRegion {
origin: MTLOrigin { x: 0, y: 0, z: 0 }, origin: MTLOrigin { x: 0, y: 0, z: 0 },
size: MTLSize { size: MTLSize {
width: self.image_bytes.size.width as usize, width: output_size.width as usize,
height: self.image_bytes.size.height as usize, height: output_size.height as usize,
depth: 1, depth: 1,
}, },
}; };
unsafe { unsafe {
// should be the same size // should be the same size
let mut buffer = vec![0u8; self.image_bytes.bytes.len()]; let mut buffer =
vec![0u8; output_size.width as usize * output_size.height as usize * 4];
render_texture.getBytes_bytesPerRow_fromRegion_mipmapLevel( render_texture.getBytes_bytesPerRow_fromRegion_mipmapLevel(
NonNull::new(buffer.as_mut_ptr().cast()).unwrap(), NonNull::new(buffer.as_mut_ptr().cast()).unwrap(),
4 * self.image_bytes.size.width as usize, 4 * output_size.width as usize,
region, region,
0, 0,
); );

View file

@ -7,8 +7,8 @@ use gpu_allocator::MemoryLocation;
use image::RgbaImage; use image::RgbaImage;
use librashader::presets::ShaderPreset; use librashader::presets::ShaderPreset;
use librashader::runtime::vk::{FilterChain, FilterChainOptions, FrameOptions, VulkanImage}; use librashader::runtime::vk::{FilterChain, FilterChainOptions, FrameOptions, VulkanImage};
use librashader::runtime::Viewport;
use librashader::runtime::{FilterChainParameters, RuntimeParameters}; use librashader::runtime::{FilterChainParameters, RuntimeParameters};
use librashader::runtime::{Size, Viewport};
use librashader_runtime::image::{Image, UVDirection, BGRA8}; use librashader_runtime::image::{Image, UVDirection, BGRA8};
use std::path::Path; use std::path::Path;
@ -32,10 +32,15 @@ impl RenderTest for Vulkan {
Vulkan::new(path) Vulkan::new(path)
} }
fn image_size(&self) -> Size<u32> {
self.image_bytes.size
}
fn render_with_preset_and_params( fn render_with_preset_and_params(
&mut self, &mut self,
preset: ShaderPreset, preset: ShaderPreset,
frame_count: usize, frame_count: usize,
output_size: Option<Size<u32>>,
param_setter: Option<&dyn Fn(&RuntimeParameters)>, param_setter: Option<&dyn Fn(&RuntimeParameters)>,
frame_options: Option<CommonFrameOptions>, frame_options: Option<CommonFrameOptions>,
) -> anyhow::Result<image::RgbaImage> { ) -> anyhow::Result<image::RgbaImage> {
@ -58,7 +63,7 @@ impl RenderTest for Vulkan {
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)
.extent(self.image_bytes.size.into()) .extent(output_size.map_or(self.image_bytes.size.into(), |size| size.into()))
.mip_levels(1) .mip_levels(1)
.array_layers(1) .array_layers(1)
.samples(vk::SampleCountFlags::TYPE_1) .samples(vk::SampleCountFlags::TYPE_1)

View file

@ -2,7 +2,7 @@ use crate::render::{CommonFrameOptions, RenderTest};
use anyhow::anyhow; use anyhow::anyhow;
use image::RgbaImage; use image::RgbaImage;
use librashader::runtime::wgpu::*; use librashader::runtime::wgpu::*;
use librashader::runtime::Viewport; use librashader::runtime::{Size, Viewport};
use librashader_runtime::image::{Image, UVDirection}; use librashader_runtime::image::{Image, UVDirection};
use std::io::{Cursor, Write}; use std::io::{Cursor, Write};
use std::ops::DerefMut; use std::ops::DerefMut;
@ -23,7 +23,7 @@ pub struct Wgpu {
_adapter: Adapter, _adapter: Adapter,
device: Arc<Device>, device: Arc<Device>,
queue: Arc<Queue>, queue: Arc<Queue>,
_image: Image, image: Image,
texture: Arc<Texture>, texture: Arc<Texture>,
} }
@ -56,10 +56,15 @@ impl RenderTest for Wgpu {
Wgpu::new(path) Wgpu::new(path)
} }
fn image_size(&self) -> Size<u32> {
self.image.size
}
fn render_with_preset_and_params( fn render_with_preset_and_params(
&mut self, &mut self,
preset: ShaderPreset, preset: ShaderPreset,
frame_count: usize, frame_count: usize,
output_size: Option<Size<u32>>,
param_setter: Option<&dyn Fn(&RuntimeParameters)>, param_setter: Option<&dyn Fn(&RuntimeParameters)>,
frame_options: Option<CommonFrameOptions>, frame_options: Option<CommonFrameOptions>,
) -> anyhow::Result<image::RgbaImage> { ) -> anyhow::Result<image::RgbaImage> {
@ -82,7 +87,7 @@ impl RenderTest for Wgpu {
let output_tex = self.device.create_texture(&TextureDescriptor { let output_tex = self.device.create_texture(&TextureDescriptor {
label: None, label: None,
size: self.texture.size(), size: output_size.map_or(self.texture.size(), |size| size.into()),
mip_level_count: 1, mip_level_count: 1,
sample_count: 1, sample_count: 1,
dimension: TextureDimension::D2, dimension: TextureDimension::D2,
@ -219,7 +224,7 @@ impl Wgpu {
_adapter: adapter, _adapter: adapter,
device: Arc::new(device), device: Arc::new(device),
queue: Arc::new(queue), queue: Arc::new(queue),
_image: image, image: image,
texture: Arc::new(texture), texture: Arc::new(texture),
}) })
}) })