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

11
CLI.md
View file

@ -9,6 +9,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
@ -53,6 +54,11 @@ Options:
[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.
@ -137,6 +143,11 @@ Options:
[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),
}) })
}) })