diff --git a/Cargo.lock b/Cargo.lock index 3c0ec58..e8ed0dc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -107,6 +107,12 @@ version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" +[[package]] +name = "bytemuck" +version = "1.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b236fc92302c97ed75b38da1f4917b5cdda4984745740f153a5d3059e48d725e" + [[package]] name = "cfg-if" version = "1.0.0" @@ -1292,6 +1298,7 @@ name = "wgpu-objc2-example" version = "0.1.0" dependencies = [ "block2", + "bytemuck", "core-foundation", "objc2", "objc2-app-kit", diff --git a/Cargo.toml b/Cargo.toml index c10031c..6466d0f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,7 @@ block2 = "0.5.1" objc2 = "0.5.2" objc2-foundation = { version = "0.2.2", features = ["all", "block2"] } objc2-quartz-core = { version = "0.2.2", features = ["all"] } +bytemuck = "1.16.1" [target.'cfg(target_os = "macos")'.dependencies] objc2-app-kit = { version = "0.2.2", features = ["all"] } diff --git a/src/shader.wgsl b/src/shader.wgsl index 3a6f55b..f5c0252 100644 --- a/src/shader.wgsl +++ b/src/shader.wgsl @@ -1,9 +1,16 @@ -// Copied verbatim from `wgpu/examples/src/hello_triangle/shader.wgsl` +// Adapted from `wgpu/examples/src/hello_triangle/shader.wgsl` +@group(0) +@binding(0) +var canvas_width: f32; + @vertex fn vs_main(@builtin(vertex_index) in_vertex_index: u32) -> @builtin(position) vec4 { - let x = f32(i32(in_vertex_index) - 1); - let y = f32(i32(in_vertex_index & 1u) * 2 - 1); - return vec4(x, y, 0.0, 1.0); + var positions = array, 3>( + vec4(1.0 - 200.0 / canvas_width, 1.0, 0.0, 1.0), // Top vertex + vec4(-1.0, -1.0, 0.0, 1.0), // Bottom left vertex + vec4(1.0, -1.0, 0.0, 1.0) // Bottom right vertex + ); + return positions[in_vertex_index]; } @fragment diff --git a/src/wgpu_triangle.rs b/src/wgpu_triangle.rs index cd8815f..a40b520 100644 --- a/src/wgpu_triangle.rs +++ b/src/wgpu_triangle.rs @@ -1,5 +1,6 @@ //! Adapted from `wgpu/examples/src/hello_triangle`. use std::cell::RefCell; +use wgpu::util::DeviceExt; use crate::frame_counter::FrameCounter; @@ -13,6 +14,8 @@ pub struct Triangle<'window> { queue: wgpu::Queue, shader: wgpu::ShaderModule, pipeline_layout: wgpu::PipelineLayout, + bind_group: wgpu::BindGroup, + uniform_buf: wgpu::Buffer, render_pipeline: wgpu::RenderPipeline, config: RefCell, frame_counter: FrameCounter, @@ -58,12 +61,40 @@ impl<'window> Triangle<'window> { source: wgpu::ShaderSource::Wgsl(include_str!("shader.wgsl").into()), }); + let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: None, + entries: &[wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStages::VERTEX, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Uniform, + has_dynamic_offset: false, + min_binding_size: wgpu::BufferSize::new(4), + }, + count: None, + }], + }); let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: None, - bind_group_layouts: &[], + bind_group_layouts: &[&bind_group_layout], push_constant_ranges: &[], }); + let uniform_buf = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some("Uniform Buffer"), + contents: bytemuck::cast_slice(&[width as f32]), + usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, + }); + + let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { + layout: &bind_group_layout, + entries: &[wgpu::BindGroupEntry { + binding: 0, + resource: uniform_buf.as_entire_binding(), + }], + label: None, + }); + let swapchain_capabilities = surface.get_capabilities(&adapter); let swapchain_format = swapchain_capabilities.formats[0]; @@ -106,6 +137,8 @@ impl<'window> Triangle<'window> { queue, shader, pipeline_layout, + uniform_buf, + bind_group, render_pipeline, config: RefCell::new(config), frame_counter: FrameCounter::new(), @@ -113,6 +146,9 @@ impl<'window> Triangle<'window> { } pub fn resize(&self, width: u32, height: u32) { + self.queue + .write_buffer(&self.uniform_buf, 0, bytemuck::cast_slice(&[width as f32])); + let mut config = self.config.borrow_mut(); config.width = width; config.height = height; @@ -146,6 +182,7 @@ impl<'window> Triangle<'window> { occlusion_query_set: None, }); rpass.set_pipeline(&self.render_pipeline); + rpass.set_bind_group(0, &self.bind_group, &[]); rpass.draw(0..3, 0..1); }