Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions compositor_render/src/transformations/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ impl LayoutNode {
let params: Vec<LayoutNodeParams> = layouts
.iter()
.map(|layout| {
let layout_resolution = [layout.width, layout.height];
let (is_texture, background_color, input_resolution) = match layout.content {
RenderLayoutContent::ChildNode { index, .. } => (
1,
Expand All @@ -137,6 +138,7 @@ impl LayoutNode {
.vertices_transformation_matrix(&output_resolution),
transform_texture_coords_matrix: layout
.texture_coords_transformation_matrix(&input_resolution),
layout_resolution,
}
})
.collect();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ struct Layout {
texture_coord_transformation: mat4x4<f32>,
color: vec4<f32>, // used only when is_texture == 0
is_texture: u32, // 0 -> color, 1 -> texture
layout_resolution: vec2<f32>,
}

@group(0) @binding(0) var texture: texture_2d<f32>;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
struct VertexInput {
@location(0) position: vec3<f32>,
@location(1) tex_coords: vec2<f32>,
}

struct VertexOutput {
@builtin(position) position: vec4<f32>,
@location(0) tex_coords: vec2<f32>,
}


struct Layout {
vertices_transformation: mat4x4<f32>,
texture_coord_transformation: mat4x4<f32>,
color: vec4<f32>, // used only when is_texture == 0
is_texture: u32, // 0 -> color, 1 -> texture
layout_resolution: vec2<f32>,
}

@group(0) @binding(0) var texture: texture_2d<f32>;
@group(1) @binding(0) var<uniform> layouts: array<Layout, 128>;
@group(2) @binding(0) var sampler_: sampler;

var<push_constant> layout_id: u32;

@vertex
fn vs_main(input: VertexInput) -> VertexOutput {
var output: VertexOutput;

let vertices_transformation_matrix: mat4x4<f32> = layouts[layout_id].vertices_transformation;
let texture_coord_transformation_matrix: mat4x4<f32> = layouts[layout_id].texture_coord_transformation;

output.position = vec4(input.position, 1.0) * vertices_transformation_matrix;
output.tex_coords = (vec4(input.tex_coords, 0.0, 1.0) * texture_coord_transformation_matrix).xy;

return output;
}

const PI: f32 = 3.1415926535897932384626433832795;
// Lanczos parameter a
const A: f32 = 3.0;


// Lanczos Sinc Function
fn sinc(x: f32) -> f32 {
if x == 0.0 {
return 1.0;
}
let x_pi = PI * x;
return (sin(x_pi) / x_pi);
}

// Lanczos Weight Function
fn lanczos(x: f32) -> f32 {
if abs(x) < A {
return sinc(x) * sinc(x / A);
} else {
return 0.0;
}
}


@fragment
fn fs_main(input: VertexOutput) -> @location(0) vec4<f32> {
let current_layout = layouts[layout_id];
let dim = textureDimensions(texture);

let input_resolution: vec2<f32> = vec2<f32>(f32(dim.x), f32(dim.y));
let scaling_factor: vec2<f32> = current_layout.layout_resolution / input_resolution;

let half_pixel_size: vec2<f32> = vec2<f32>(0.5) / input_resolution;

var color: vec4<f32> = vec4<f32>(0.0, 0.0, 0.0, 0.0);
var normalization: f32 = 0.0;


for (var i: f32 = -A; i <= A; i += 1.0) {
for (var j: f32 = -A; j <= A; j += 1.0) {
// Position on input texture in pixels
let x = input.tex_coords * input_resolution;
// Sample position in pixels
let sample_pixel_x = floor(input.tex_coords.x * input_resolution.x) + i;
let sample_pixel_y = floor(input.tex_coords.y * input_resolution.y) + j;

// Sample position in texture coordinates
let sample_coord_x = clamp((sample_pixel_x / input_resolution.x) + half_pixel_size.x, 0.0, 1.0);
let sample_coord_y = clamp((sample_pixel_y / input_resolution.y) + half_pixel_size.y, 0.0, 1.0);
let sample_coords = vec2<f32>(sample_coord_x, sample_coord_y);

// Distance of sampled output pixel from sampled position
let dx = sample_pixel_x - x.x;
let dy = sample_pixel_y - x.y;

let sample_color: vec4<f32> = textureSample(texture, sampler_, sample_coords);
// Lanczos weight normalizing sampled values
let weight: f32 = lanczos(dx) * lanczos(dy);
color += sample_color * weight;
normalization += weight;
}
}

// sampling can't be conditional, so in case of plane_id == -1
// sample textures[0], but ignore the result.
if (current_layout.is_texture == 0u) {
return current_layout.color;
}
// clamp transparent, when crop > input texture
let is_inside: f32 = round(f32(input.tex_coords.x < 1.0 && input.tex_coords.x > 0.0 && input.tex_coords.y > 0.0 && input.tex_coords.y < 1.0));

return is_inside * color / normalization;
}
17 changes: 11 additions & 6 deletions compositor_render/src/transformations/layout/params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ use crate::{scene::RGBAColor, wgpu::WgpuCtx};
pub(super) struct LayoutNodeParams {
pub(super) transform_vertices_matrix: Mat4,
pub(super) transform_texture_coords_matrix: Mat4,
pub(super) is_texture: u32,
pub(super) background_color: RGBAColor,
pub(super) is_texture: u32,
pub(super) layout_resolution: [f32; 2],
}

pub(super) struct ParamsBuffer {
Expand Down Expand Up @@ -70,21 +71,24 @@ impl ParamsBuffer {
params
.iter()
.map(LayoutNodeParams::shader_buffer_content)
.collect::<Vec<[u8; 160]>>()
.collect::<Vec<[u8; LAYOUT_STRUCT_SIZE]>>()
.concat()
.into()
}
}

const LAYOUT_STRUCT_SIZE: usize = 160;

impl LayoutNodeParams {
fn shader_buffer_content(&self) -> [u8; 160] {
fn shader_buffer_content(&self) -> [u8; LAYOUT_STRUCT_SIZE] {
let Self {
transform_vertices_matrix,
transform_texture_coords_matrix,
is_texture,
background_color,
is_texture,
layout_resolution,
} = self;
let mut result = [0; 160];
let mut result = [0; LAYOUT_STRUCT_SIZE];
fn from_u8_color(value: u8) -> [u8; 4] {
(value as f32 / 255.0).to_ne_bytes()
}
Expand All @@ -93,14 +97,15 @@ impl LayoutNodeParams {
result[64..128].copy_from_slice(bytemuck::bytes_of(
&transform_texture_coords_matrix.transpose(),
));
// 12 bytes padding
result[128..132].copy_from_slice(&from_u8_color(background_color.0));
result[132..136].copy_from_slice(&from_u8_color(background_color.1));
result[136..140].copy_from_slice(&from_u8_color(background_color.2));
result[140..144].copy_from_slice(&from_u8_color(background_color.3));

result[144..148].copy_from_slice(&is_texture.to_ne_bytes());
// 12 bytes padding
result[152..156].copy_from_slice(&layout_resolution[0].to_ne_bytes());
result[156..160].copy_from_slice(&layout_resolution[1].to_ne_bytes());

result
}
Expand Down
10 changes: 5 additions & 5 deletions compositor_render/src/transformations/layout/shader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ impl LayoutShader {

let shader_module = wgpu_ctx
.device
.create_shader_module(wgpu::include_wgsl!("./apply_layouts.wgsl"));
.create_shader_module(wgpu::include_wgsl!("./apply_layouts_lanczos.wgsl"));
let result = Self::new_pipeline(wgpu_ctx, shader_module)?;

scope.pop(&wgpu_ctx.device)?;
Expand Down Expand Up @@ -93,18 +93,18 @@ impl LayoutShader {
occlusion_query_set: None,
});

for (layout_id, texture_bg) in input_texture_bgs.iter().enumerate() {
render_pass.set_pipeline(&self.pipeline);
render_pass.set_pipeline(&self.pipeline);
render_pass.set_bind_group(1, params, &[]);
render_pass.set_bind_group(2, &self.sampler.bind_group, &[]);

for (layout_id, texture_bg) in input_texture_bgs.iter().enumerate() {
render_pass.set_push_constants(
ShaderStages::VERTEX_FRAGMENT,
0,
&(layout_id as u32).to_le_bytes(),
);

render_pass.set_bind_group(0, texture_bg, &[]);
render_pass.set_bind_group(1, params, &[]);
render_pass.set_bind_group(2, &self.sampler.bind_group, &[]);

wgpu_ctx.plane.draw(&mut render_pass);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,14 @@ fn fs_main(input: VertexOutput) -> @location(0) vec4<f32> {
// - adding eps to avoid numerical errors when converting f32 -> u32
var x_pos = u32((input.tex_coords.x * f32(dimensions.x) - half_pixel_width + eps) * 2.0);
// x_pos/2 is calculated before conversion to float to make sure that reminder is lost for odd column.
var tex_coords = vec2((f32(x_pos/2) / f32(dimensions.x)) + half_pixel_width, input.tex_coords.y);
var tex_coords = vec2((f32( x_pos / 2u) / f32(dimensions.x)) + half_pixel_width, input.tex_coords.y);

var uyvy = textureSample(texture, sampler_, tex_coords);

var u = uyvy.x;
var v = uyvy.z;
var y = uyvy.y;
if (x_pos % 2 != 0) {
if (x_pos % 2u != 0u) {
y = uyvy.w;
}

Expand Down
9 changes: 7 additions & 2 deletions integration_tests/examples/test_pattern.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,13 @@ fn start_example_client_code() -> Result<()> {
"shader_id": "example_shader",
"children": [
{
"type": "input_stream",
"input_id": "input_1",
"type": "rescaler",
"width": 1760,
"height": 990,
"child": {
"type": "input_stream",
"input_id": "input_1"
},
}
],
"resolution": { "width": VIDEO_RESOLUTION.width, "height": VIDEO_RESOLUTION.height },
Expand Down