Skip to content

Commit

Permalink
cli(render): allow specifying output dimensions
Browse files Browse the repository at this point in the history
  • Loading branch information
chyyran committed Oct 6, 2024
1 parent 4abd48e commit 95a489e
Show file tree
Hide file tree
Showing 12 changed files with 191 additions and 58 deletions.
13 changes: 12 additions & 1 deletion CLI.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ Commands:
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
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
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
help Print this message or the help of the given subcommand(s)
Options:
-h, --help Print help
-V, --version Print version
Expand Down Expand Up @@ -52,6 +53,11 @@ Options:
The renderer will run up to the number of frames specified here to ensure feedback and history.
[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>...
Parameters to pass to the shader preset, comma separated with equals signs.
Expand Down Expand Up @@ -136,6 +142,11 @@ Options:
The renderer will run up to the number of frames specified here to ensure feedback and history.
[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>...
Parameters to pass to the shader preset, comma separated with equals signs.
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ Commands:
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
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
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
Expand Down
4 changes: 2 additions & 2 deletions librashader-capi/src/ctypes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ pub enum LIBRA_PRESET_CTX_RUNTIME {
/// Metal
Metal,
/// Direct3D 9
D3D9_HLSL
D3D9_HLSL,
}

impl From<LIBRA_PRESET_CTX_RUNTIME> for VideoDriver {
Expand All @@ -61,7 +61,7 @@ impl From<LIBRA_PRESET_CTX_RUNTIME> for VideoDriver {
LIBRA_PRESET_CTX_RUNTIME::D3D11 => VideoDriver::Direct3D11,
LIBRA_PRESET_CTX_RUNTIME::D3D12 => VideoDriver::Direct3D12,
LIBRA_PRESET_CTX_RUNTIME::Metal => VideoDriver::Metal,
LIBRA_PRESET_CTX_RUNTIME::D3D9_HLSL => VideoDriver::Direct3D9Hlsl
LIBRA_PRESET_CTX_RUNTIME::D3D9_HLSL => VideoDriver::Direct3D9Hlsl,
}
}
}
Expand Down
59 changes: 58 additions & 1 deletion librashader-cli/src/cli/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use librashader::reflect::cross::{GlslVersion, HlslShaderModel, MslVersion, Spir
use librashader::reflect::naga::{Naga, NagaLoweringOptions};
use librashader::reflect::semantics::ShaderSemantics;
use librashader::reflect::{CompileShader, FromCompilation, ReflectShader, SpirvCompilation};
use librashader::runtime::Size;
use librashader::{FastHashMap, ShortString};
use librashader_runtime::parameters::RuntimeParameters;
use librashader_test::render::{CommonFrameOptions, RenderTest};
Expand Down Expand Up @@ -43,6 +44,12 @@ struct RenderArgs {
/// to ensure feedback and history.
#[arg(short, long, default_value_t = 0)]
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.
///
/// For example, crt_gamma=2.5,halation_weight=0.001
Expand Down Expand Up @@ -313,20 +320,22 @@ pub fn main() -> Result<(), anyhow::Error> {
let PresetArgs { preset, wildcards } = preset;
let RenderArgs {
frame,
dimensions,
params,
passes_enabled,
image,
options,
} = render;

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 params = parse_params(params)?;

let image = test.render_with_preset_and_params(
preset,
frame,
Some(dimensions),
Some(&|rp| set_params(rp, &params, passes_enabled)),
options.map(CommonFrameOptions::from),
)?;
Expand All @@ -348,6 +357,7 @@ pub fn main() -> Result<(), anyhow::Error> {
let PresetArgs { preset, wildcards } = preset;
let RenderArgs {
frame,
dimensions,
params,
passes_enabled,
image,
Expand All @@ -357,12 +367,14 @@ pub fn main() -> Result<(), anyhow::Error> {
let left: &mut dyn RenderTest = get_runtime!(left, image);
let right: &mut dyn RenderTest = get_runtime!(right, image);

let dimensions = parse_dimension(dimensions, left.image_size())?;
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(dimensions),
Some(&|rp| set_params(rp, &params, passes_enabled)),
None,
)?;
Expand All @@ -371,6 +383,7 @@ pub fn main() -> Result<(), anyhow::Error> {
let right_image = right.render_with_preset_and_params(
right_preset,
frame,
Some(dimensions),
Some(&|rp| set_params(rp, &params, passes_enabled)),
options.map(CommonFrameOptions::from),
)?;
Expand Down Expand Up @@ -742,3 +755,47 @@ fn parse_msl_version(version_str: &str) -> anyhow::Result<MslVersion> {
_ => 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%"
))
}
33 changes: 24 additions & 9 deletions librashader-cli/src/render/d3d11.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ use image::RgbaImage;
use librashader::runtime::d3d11::*;
use librashader::runtime::{FilterChainParameters, RuntimeParameters};
use librashader::runtime::{Size, Viewport};
use std::io::{Cursor, Write};
use std::ops::DerefMut;
use std::path::Path;

impl RenderTest for Direct3D11 {
Expand All @@ -14,14 +16,20 @@ impl RenderTest for Direct3D11 {
Direct3D11::new(path)
}

fn image_size(&self) -> Size<u32> {
self.image_bytes.size
}

fn render_with_preset_and_params(
&mut self,
preset: ShaderPreset,
frame_count: usize,
output_size: Option<Size<u32>>,
param_setter: Option<&dyn Fn(&RuntimeParameters)>,
frame_options: Option<CommonFrameOptions>,
) -> 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 {
let mut filter_chain = FilterChain::load_from_preset(
Expand Down Expand Up @@ -50,10 +58,10 @@ impl RenderTest for Direct3D11 {
}

let mut renderbuffer_desc = Default::default();
renderbuffer.GetDesc(&mut renderbuffer_desc);

self.immediate_context.Flush();
renderbuffer.GetDesc(&mut renderbuffer_desc);

eprintln!("{:?}", renderbuffer_desc);
let mut staging = None;
self.device.CreateTexture2D(
&D3D11_TEXTURE2D_DESC {
Expand All @@ -72,6 +80,8 @@ impl RenderTest for Direct3D11 {

self.immediate_context.CopyResource(&staging, &renderbuffer);

let mut pixels: Vec<u8> = Vec::new();

let mut map_info = Default::default();
self.immediate_context
.Map(&staging, 0, D3D11_MAP_READ, 0, Some(&mut map_info))?;
Expand All @@ -80,13 +90,18 @@ impl RenderTest for Direct3D11 {
map_info.pData as *const u8,
(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(
renderbuffer_desc.Width,
renderbuffer_desc.Height,
Vec::from(slice),
)
.ok_or(anyhow!("Unable to create image from data"))?;
let mut cursor = Cursor::new(pixels.deref_mut());
for chunk in slice.chunks(map_info.RowPitch as usize) {
cursor.write_all(&chunk[..(renderbuffer_desc.Width * 4) as usize])?
}

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);

Ok(image)
Expand Down
26 changes: 14 additions & 12 deletions librashader-cli/src/render/d3d12/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ use d3d12_descriptor_heap::{D3D12DescriptorHeap, D3D12DescriptorHeapSlot};
use image::RgbaImage;
use librashader::presets::ShaderPreset;
use librashader::runtime::d3d12::{D3D12OutputView, FilterChain, FilterChainOptions, FrameOptions};
use librashader::runtime::Viewport;
use librashader::runtime::{FilterChainParameters, RuntimeParameters};
use librashader::runtime::{Size, Viewport};
use librashader_runtime::image::{Image, PixelFormat, UVDirection, BGRA8};
use std::path::Path;
use windows::core::Interface;
Expand Down Expand Up @@ -58,10 +58,14 @@ impl RenderTest for Direct3D12 {
Direct3D12::new(path)
}

fn image_size(&self) -> Size<u32> {
self.image.size
}
fn render_with_preset_and_params(
&mut self,
preset: ShaderPreset,
frame_count: usize,
output_size: Option<Size<u32>>,
param_setter: Option<&dyn Fn(&RuntimeParameters)>,
frame_options: Option<CommonFrameOptions>,
) -> anyhow::Result<image::RgbaImage> {
Expand Down Expand Up @@ -92,12 +96,13 @@ impl RenderTest for Direct3D12 {
setter(filter_chain.parameters());
}

let output_size = output_size.unwrap_or(self.image.size);
let mut output_texture = None;
let desc = D3D12_RESOURCE_DESC {
Dimension: D3D12_RESOURCE_DIMENSION_TEXTURE2D,
Alignment: 0,
Width: self.image.size.width as u64,
Height: self.image.size.height,
Width: output_size.width as u64,
Height: output_size.height,
DepthOrArraySize: 1,
MipLevels: 1,
Format: DXGI_FORMAT_B8G8R8A8_UNORM,
Expand Down Expand Up @@ -135,7 +140,7 @@ impl RenderTest for Direct3D12 {
let viewport = Viewport::new_render_target_sized_origin(
D3D12OutputView::new_from_raw(
*descriptor.as_ref(),
self.image.size,
output_size,
DXGI_FORMAT_B8G8R8A8_UNORM,
),
None,
Expand Down Expand Up @@ -165,24 +170,21 @@ impl RenderTest for Direct3D12 {
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(
buffer.as_mut_ptr().cast(),
4 * self.image.size.width,
4 * output_size.width,
0,
0,
None,
)?;

BGRA8::convert(&mut buffer);

let image = RgbaImage::from_raw(
self.image.size.width,
self.image.size.height,
Vec::from(buffer),
)
.ok_or(anyhow!("Unable to create image from data"))?;
let image =
RgbaImage::from_raw(output_size.width, output_size.height, Vec::from(buffer))
.ok_or(anyhow!("Unable to create image from data"))?;

Ok(image)
}
Expand Down
Loading

0 comments on commit 95a489e

Please sign in to comment.