diff --git a/blog/2025-03-30-draw-compute-shader/draw-compute/shader/src/lib.rs b/blog/2025-03-30-draw-compute-shader/draw-compute/shader/src/lib.rs index 91c617d..10b25d4 100644 --- a/blog/2025-03-30-draw-compute-shader/draw-compute/shader/src/lib.rs +++ b/blog/2025-03-30-draw-compute-shader/draw-compute/shader/src/lib.rs @@ -6,12 +6,12 @@ use spirv_std::spirv; #[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)] #[repr(C)] pub struct Viewport { - pub image_size: glam::UVec2, - pub viewport_offset: glam::UVec2, - pub viewport_size: glam::UVec2, + pub offset: glam::UVec2, + pub size: glam::UVec2, + pub image: glam::UVec2, } -const BLOCK_SIZE: u32 = 16; +const BLOCK_SIZE: usize = 16; const BLACK: glam::Vec4 = glam::vec4(0.0, 0.0, 0.0, 1.0); const WHITE: glam::Vec4 = glam::vec4(1.0, 1.0, 1.0, 1.0); @@ -24,18 +24,16 @@ pub fn main_cs( #[spirv(uniform, descriptor_set = 0, binding = 0)] viewport: &Viewport, #[spirv(storage_buffer, descriptor_set = 0, binding = 1)] image: &mut [glam::Vec4], ) { - let width = viewport.image_size.x as usize; - let height = viewport.image_size.y as usize; + let width = viewport.image.x as usize; + let height = viewport.image.y as usize; for x in 0..width { + let x_even = x / BLOCK_SIZE % 2 == 0; for y in 0..height { + let y_even = y / BLOCK_SIZE % 2 == 0; + + let color = if x_even == y_even { BLACK } else { WHITE }; let index = image_index(x, y, width); - if x == 0 - || x == width - 1 - || y == 0 - || y == height - 1 - { - image[index] = WHITE; - } + image[index] = color; } } } @@ -58,10 +56,9 @@ pub fn main_fs( ) { let pixel_coordinate = frag_coord.xy().as_usizevec2(); let (pixel_x, pixel_y) = (pixel_coordinate.x, pixel_coordinate.y); - let index = image_index(pixel_x, pixel_y, viewport.viewport_size.x as usize); - *output = if index < image.len() { - image[index] + *output = if pixel_x < viewport.image.x as usize && pixel_y < viewport.image.y as usize { + image[image_index(pixel_x, pixel_y, viewport.image.x as usize)] } else { BLACK }; diff --git a/blog/2025-03-30-draw-compute-shader/draw-compute/src/main.rs b/blog/2025-03-30-draw-compute-shader/draw-compute/src/main.rs index 08b7666..9d32b2b 100644 --- a/blog/2025-03-30-draw-compute-shader/draw-compute/src/main.rs +++ b/blog/2025-03-30-draw-compute-shader/draw-compute/src/main.rs @@ -3,7 +3,6 @@ use eframe::wgpu::{CommandBuffer, CommandEncoder, Device, Queue, RenderPass}; use eframe::Frame; use egui::{Context, Sense}; use egui_wgpu::{CallbackResources, CallbackTrait, ScreenDescriptor}; -use shader::Viewport; struct DrawResources { device: wgpu::Device, @@ -11,7 +10,7 @@ struct DrawResources { bind_group: wgpu::BindGroup, viewport_buffer: wgpu::Buffer, image_buffer: wgpu::Buffer, - image_buffer_size: glam::UVec2, + image_size: glam::UVec2, compute_pipeline: wgpu::ComputePipeline, render_pipeline: wgpu::RenderPipeline, } @@ -150,7 +149,7 @@ impl DrawResources { let bind_group_layout = Self::bind_group_layout(device); let viewport_buffer = Self::viewport_buffer(device); let image_buffer = Self::image_buffer(device, width, height); - let image_buffer_size = glam::uvec2(width as u32, height as u32); + let image_size = glam::uvec2(width as u32, height as u32); let bind_group = Self::bind_group(device, &bind_group_layout, &viewport_buffer, &image_buffer); @@ -165,7 +164,7 @@ impl DrawResources { bind_group, viewport_buffer, image_buffer, - image_buffer_size, + image_size, compute_pipeline, render_pipeline, } @@ -196,35 +195,42 @@ impl CallbackTrait for DrawCallback { egui_encoder: &mut CommandEncoder, callback_resources: &mut CallbackResources, ) -> Vec { - let resources = callback_resources .get_mut::() .expect("missing draw resources"); - let mut viewport = Viewport { - image_size: resources.image_buffer_size, - viewport_offset: glam::uvec2(self.draw_rect.min.x as u32, self.draw_rect.min.y as u32), - viewport_size: glam::uvec2(self.draw_rect.size().x as u32, self.draw_rect.size().y as u32), - }; - - if !self.draw_resize { - queue.write_buffer(&resources.viewport_buffer, 0, bytemuck::cast_slice(&[viewport])); - return vec![]; + if self.draw_resize { + resources.resize( + self.draw_rect.size().x as u64, + self.draw_rect.size().y as u64, + ); } - let draw_size = self.draw_rect.size(); - resources.resize(draw_size.x as u64, draw_size.y as u64); + let mut viewport = shader::Viewport { + image: resources.image_size, + offset: glam::uvec2(self.draw_rect.min.x as u32, self.draw_rect.min.y as u32), + size: glam::uvec2( + self.draw_rect.size().x as u32, + self.draw_rect.size().y as u32, + ), + }; - viewport.image_size = resources.image_buffer_size; - queue.write_buffer(&resources.viewport_buffer, 0, bytemuck::cast_slice(&[viewport])); + queue.write_buffer( + &resources.viewport_buffer, + 0, + bytemuck::cast_slice(&[viewport]), + ); - let mut compute_pass = egui_encoder.begin_compute_pass(&wgpu::ComputePassDescriptor { - label: Some("compute"), - timestamp_writes: None, - }); + if self.draw_resize { + let mut compute_pass = egui_encoder.begin_compute_pass(&wgpu::ComputePassDescriptor { + label: Some("compute"), + timestamp_writes: None, + }); - compute_pass.set_pipeline(&resources.compute_pipeline); - compute_pass.set_bind_group(0, &resources.bind_group, &[]); + compute_pass.set_pipeline(&resources.compute_pipeline); + compute_pass.set_bind_group(0, &resources.bind_group, &[]); + compute_pass.dispatch_workgroups(1, 1, 1); + } vec![] }