From 33f771382763871429a5f94bc4bd699a813a0eea Mon Sep 17 00:00:00 2001 From: Antoine Beyeler Date: Mon, 23 Dec 2024 10:44:53 +0100 Subject: [PATCH] Pass vertex data as storage buffer and use it instead of the instance input --- crates/vsvg-viewer/src/engine.rs | 25 ++++----- .../vsvg-viewer/src/painters/basic_painter.rs | 4 +- .../vsvg-viewer/src/painters/line_painter.rs | 53 +++++++++++++++++-- crates/vsvg-viewer/src/painters/mod.rs | 3 +- .../src/painters/page_size_painter.rs | 10 ++-- .../vsvg-viewer/src/painters/point_painter.rs | 4 +- crates/vsvg-viewer/src/shaders/line.wgsl | 31 +++++++---- 7 files changed, 91 insertions(+), 39 deletions(-) diff --git a/crates/vsvg-viewer/src/engine.rs b/crates/vsvg-viewer/src/engine.rs index e376489..ce3426d 100644 --- a/crates/vsvg-viewer/src/engine.rs +++ b/crates/vsvg-viewer/src/engine.rs @@ -154,7 +154,8 @@ impl LayerPainters { if let Some(line_painter_data) = layer_data.line_painter_data() { self.line_painter.draw( render_pass, - &render_objects.camera_bind_group, + render_objects, + //&render_objects.camera_bind_group, line_painter_data, ); } @@ -163,13 +164,13 @@ impl LayerPainters { if let Some(bezier_handles_painter_data) = layer_data.bezier_handles_painter_data() { self.bezier_handles_point_painter.draw( render_pass, - &render_objects.camera_bind_group, + render_objects, &bezier_handles_painter_data.point_painter_data, ); self.bezier_handles_line_painter.draw( render_pass, - &render_objects.camera_bind_group, + render_objects, &bezier_handles_painter_data.line_painter_data, ); } @@ -180,7 +181,7 @@ impl LayerPainters { { self.display_vertices_painter.draw( render_pass, - &render_objects.camera_bind_group, + render_objects, display_vertices_painter_data, ); } @@ -188,11 +189,8 @@ impl LayerPainters { if display_options.show_pen_up { if let Some(pen_up_painter_data) = layer_data.pen_up_painter_data() { - self.pen_up_painter.draw( - render_pass, - &render_objects.camera_bind_group, - pen_up_painter_data, - ); + self.pen_up_painter + .draw(render_pass, render_objects, pen_up_painter_data); } } } @@ -201,7 +199,7 @@ impl LayerPainters { /// wgpu-related objects used by the engine. /// /// They are grouped in a separate structure, so they can be provided to painters during engine -/// initialisation. +/// initialization. pub(crate) struct EngineRenderObjects { pub(crate) device: Arc, pub(crate) camera_buffer: Buffer, @@ -369,11 +367,8 @@ impl Engine { vsvg::trace_function!(); if let Some(page_size_painter_data) = &self.page_size_painter_data { - self.page_size_painter.draw( - render_pass, - &self.render_objects.camera_bind_group, - page_size_painter_data, - ); + self.page_size_painter + .draw(render_pass, &self.render_objects, page_size_painter_data); } let mut viewer_options = self.viewer_options.lock().unwrap(); diff --git a/crates/vsvg-viewer/src/painters/basic_painter.rs b/crates/vsvg-viewer/src/painters/basic_painter.rs index 78f104b..b4bc715 100644 --- a/crates/vsvg-viewer/src/painters/basic_painter.rs +++ b/crates/vsvg-viewer/src/painters/basic_painter.rs @@ -138,7 +138,7 @@ impl Painter for BasicPainter { fn draw( &self, rpass: &mut RenderPass<'static>, - camera_bind_group: &wgpu::BindGroup, + render_objects: &EngineRenderObjects, data: &Self::Data, ) { // `Buffer::slice(..)` panics for empty buffers in wgpu 23+ @@ -147,7 +147,7 @@ impl Painter for BasicPainter { } rpass.set_pipeline(&self.render_pipeline); - rpass.set_bind_group(0, camera_bind_group, &[]); + rpass.set_bind_group(0, &render_objects.camera_bind_group, &[]); rpass.set_vertex_buffer(0, data.vertex_buffer.slice(..)); rpass.draw(0..data.vertex_count, 0..1); } diff --git a/crates/vsvg-viewer/src/painters/line_painter.rs b/crates/vsvg-viewer/src/painters/line_painter.rs index 0c2bbaf..d6a3074 100644 --- a/crates/vsvg-viewer/src/painters/line_painter.rs +++ b/crates/vsvg-viewer/src/painters/line_painter.rs @@ -186,7 +186,7 @@ impl LinePainterData { .create_buffer_init(&wgpu::util::BufferInitDescriptor { label: Some("Point instance buffer"), contents: bytemuck::cast_slice(vertices.as_slice()), - usage: wgpu::BufferUsages::VERTEX, + usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::STORAGE, }); // prepare color buffer @@ -282,6 +282,7 @@ impl LinePainterData { /// /// See module documentation for details. pub(crate) struct LinePainter { + points_bind_group_layout: wgpu::BindGroupLayout, render_pipeline: RenderPipeline, } @@ -320,6 +321,23 @@ impl LinePainter { attributes: &vertex_attrib_color_width, }); + let points_bind_group_layout = + render_objects + .device + .create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + entries: &[wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStages::VERTEX, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Storage { read_only: true }, + has_dynamic_offset: false, + min_binding_size: None, + }, + count: None, + }], + label: Some("point_bind_group_layout"), + }); + let shader = render_objects .device .create_shader_module(include_wgsl!("../shaders/line.wgsl")); @@ -329,7 +347,10 @@ impl LinePainter { .device .create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: None, - bind_group_layouts: &[&render_objects.camera_bind_group_layout], + bind_group_layouts: &[ + &render_objects.camera_bind_group_layout, + &points_bind_group_layout, + ], push_constant_ranges: &[], }); @@ -379,7 +400,12 @@ impl LinePainter { cache: None, }); - Self { render_pipeline } + ///////// + + Self { + points_bind_group_layout, + render_pipeline, + } } } @@ -389,7 +415,7 @@ impl Painter for LinePainter { fn draw( &self, rpass: &mut RenderPass<'static>, - camera_bind_group: &wgpu::BindGroup, + render_objects: &EngineRenderObjects, data: &LinePainterData, ) { // `Buffer::slice(..)` panics for empty buffers in wgpu 23+ @@ -398,7 +424,24 @@ impl Painter for LinePainter { } rpass.set_pipeline(&self.render_pipeline); - rpass.set_bind_group(0, camera_bind_group, &[]); + rpass.set_bind_group(0, &render_objects.camera_bind_group, &[]); + + ////// + //TODO: this could be done once + + let points_bind_group = + render_objects + .device + .create_bind_group(&wgpu::BindGroupDescriptor { + layout: &self.points_bind_group_layout, + entries: &[wgpu::BindGroupEntry { + binding: 0, + resource: data.points_buffer.as_entire_binding(), + }], + label: Some("point_bind_group"), + }); + + rpass.set_bind_group(1, &points_bind_group, &[]); let offset = size_of::() as u64; rpass.set_vertex_buffer(0, data.points_buffer.slice(..)); diff --git a/crates/vsvg-viewer/src/painters/mod.rs b/crates/vsvg-viewer/src/painters/mod.rs index 3a08f9b..4365263 100644 --- a/crates/vsvg-viewer/src/painters/mod.rs +++ b/crates/vsvg-viewer/src/painters/mod.rs @@ -6,6 +6,7 @@ mod point_painter; use vsvg::Point; use wgpu::RenderPass; +use crate::engine::EngineRenderObjects; pub(crate) use basic_painter::{BasicPainter, BasicPainterData}; pub(crate) use line_painter::{LineDisplayOptions, LinePainter, LinePainterData}; pub(crate) use page_size_painter::{PageSizePainter, PageSizePainterData}; @@ -17,7 +18,7 @@ pub(crate) trait Painter { fn draw( &self, rpass: &mut RenderPass<'static>, - camera_bind_group: &wgpu::BindGroup, + render_objects: &EngineRenderObjects, data: &Self::Data, ); } diff --git a/crates/vsvg-viewer/src/painters/page_size_painter.rs b/crates/vsvg-viewer/src/painters/page_size_painter.rs index 7e35a94..758f489 100644 --- a/crates/vsvg-viewer/src/painters/page_size_painter.rs +++ b/crates/vsvg-viewer/src/painters/page_size_painter.rs @@ -4,7 +4,7 @@ use crate::engine::{ }; use crate::painters::{BasicPainter, BasicPainterData, Painter}; use vsvg::PageSize; -use wgpu::{BindGroup, RenderPass}; +use wgpu::RenderPass; pub(crate) struct PageSizePainterData { background: BasicPainterData, @@ -64,14 +64,14 @@ impl Painter for PageSizePainter { fn draw( &self, rpass: &mut RenderPass<'static>, - camera_bind_group: &BindGroup, + render_objects: &EngineRenderObjects, data: &Self::Data, ) { self.background_and_shadow_painter - .draw(rpass, camera_bind_group, &data.shadow); + .draw(rpass, render_objects, &data.shadow); self.background_and_shadow_painter - .draw(rpass, camera_bind_group, &data.background); + .draw(rpass, render_objects, &data.background); self.border_painter - .draw(rpass, camera_bind_group, &data.border); + .draw(rpass, render_objects, &data.border); } } diff --git a/crates/vsvg-viewer/src/painters/point_painter.rs b/crates/vsvg-viewer/src/painters/point_painter.rs index 05424b4..872524f 100644 --- a/crates/vsvg-viewer/src/painters/point_painter.rs +++ b/crates/vsvg-viewer/src/painters/point_painter.rs @@ -140,7 +140,7 @@ impl Painter for PointPainter { fn draw( &self, rpass: &mut RenderPass<'static>, - camera_bind_group: &wgpu::BindGroup, + render_objects: &EngineRenderObjects, data: &Self::Data, ) { // `Buffer::slice(..)` panics for empty buffers in wgpu 23+ @@ -149,7 +149,7 @@ impl Painter for PointPainter { } rpass.set_pipeline(&self.render_pipeline); - rpass.set_bind_group(0, camera_bind_group, &[]); + rpass.set_bind_group(0, &render_objects.camera_bind_group, &[]); rpass.set_vertex_buffer(0, data.instance_buffer.slice(..)); rpass.draw(0..4, 0..data.instance_count); } diff --git a/crates/vsvg-viewer/src/shaders/line.wgsl b/crates/vsvg-viewer/src/shaders/line.wgsl index b54548b..0b85317 100644 --- a/crates/vsvg-viewer/src/shaders/line.wgsl +++ b/crates/vsvg-viewer/src/shaders/line.wgsl @@ -6,6 +6,7 @@ struct CameraUniform { }; @group(0) @binding(0) var camera: CameraUniform; +@group(1) @binding(0) var points: array>; struct InstanceInput { @location(0) p0: vec2, @@ -79,27 +80,39 @@ fn vs_main( let w2 = instance.width/2. + (camera.anti_alias / camera.scale) / 2.; - let d = distance(instance.p1, instance.p2); - let v = normalize(instance.p2 - instance.p1); + +// let p0 = instance.p0; +// let p1 = instance.p1; +// let p2 = instance.p2; +// let p3 = instance.p3; + + let p0 = points[in_instance_index + 0]; + let p1 = points[in_instance_index + 1]; + let p2 = points[in_instance_index + 2]; + let p3 = points[in_instance_index + 3]; + + + let d = distance(p1, p2); + let v = normalize(p2 - p1); let n = vec2(-v.y, v.x); var vertex: vec2; var tex_coords: vec2; switch (in_vertex_index) { case 0u: { - vertex = instance.p1 + w2 * (-v - n); + vertex = p1 + w2 * (-v - n); tex_coords = vec2(-w2, -w2); } case 1u: { - vertex = instance.p1 + w2 * (-v + n); + vertex = p1 + w2 * (-v + n); tex_coords = vec2(-w2, w2); } case 2u: { - vertex = instance.p2 + w2 * (v - n); + vertex = p2 + w2 * (v - n); tex_coords = vec2(d + w2, -w2); } default: { // case 3u - vertex = instance.p2 + w2 * (v + n); + vertex = p2 + w2 * (v + n); tex_coords = vec2(d + w2, w2); } } @@ -117,9 +130,9 @@ fn vs_main( out.distance = d; // compute miter points - let critical_length_mid = length(instance.p2 - instance.p1 + w2 * n); - let m0 = compute_miter(instance.p0, instance.p1, n, critical_length_mid, w2); - let m2 = compute_miter(instance.p2, instance.p3, n, critical_length_mid, w2); + let critical_length_mid = length(p2 - p1 + w2 * n); + let m0 = compute_miter(p0, p1, n, critical_length_mid, w2); + let m2 = compute_miter(p2, p3, n, critical_length_mid, w2); out.color = color; out.width = instance.width;