diff --git a/src/bin/minitracer/main.rs b/src/bin/minitracer/main.rs index 885a9cf..4ae1d0e 100644 --- a/src/bin/minitracer/main.rs +++ b/src/bin/minitracer/main.rs @@ -92,15 +92,6 @@ fn main() { frame += 1; let spheres: Vec<_> = sphere_params.iter().map(|p| p.to_sphere(time)).collect(); let data = TracerData::new(&device, &tracer, &spheres); - tracer.set_params( - &queue, - trace::Params { - max_reflections: 3, - min_strength: 0.1, - sphere_count: N_SPHERES, - seed: frame, - }, - ); let output = surface.get_current_texture().unwrap(); let view = output.texture.create_view(&wgpu::TextureViewDescriptor::default()); @@ -136,7 +127,17 @@ fn main() { occlusion_query_set: None, timestamp_writes: None, }); - tracer.render(&mut render_pass, &data, &tracer_env); + tracer.render( + &mut render_pass, + &data, + &tracer_env, + trace::Params { + max_reflections: 3, + min_strength: 0.1, + sphere_count: N_SPHERES, + seed: frame, + }, + ); } { let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { @@ -183,8 +184,11 @@ async fn init_gpu(wnd: &Window) -> Result<(wgpu::Device, wgpu::Queue, wgpu::Surf .request_device( &wgpu::DeviceDescriptor { label: None, - required_features: wgpu::Features::empty(), - required_limits: wgpu::Limits::default(), + required_features: wgpu::Features::PUSH_CONSTANTS, + required_limits: wgpu::Limits { + max_push_constant_size: 32, + ..Default::default() + }, memory_hints: Default::default(), }, None, diff --git a/src/bin/minitracer/trace.rs b/src/bin/minitracer/trace.rs index cc32337..d9f98ee 100644 --- a/src/bin/minitracer/trace.rs +++ b/src/bin/minitracer/trace.rs @@ -43,7 +43,6 @@ struct SphereData { pub struct Tracer { view_buf: wgpu::Buffer, - params_buf: wgpu::Buffer, pipeline: wgpu::RenderPipeline, } @@ -65,19 +64,55 @@ impl Tracer { usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST, mapped_at_creation: false, }); - let params_buf = device.create_buffer(&wgpu::BufferDescriptor { - label: None, - size: mem::size_of::() as u64, - usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, - mapped_at_creation: false, - }); let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor { label: None, source: wgpu::ShaderSource::Wgsl(SHADER.into()), }); + let spheres_bgl = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: None, + entries: &[wgpu::BindGroupLayoutEntry { + binding: 1, + visibility: wgpu::ShaderStages::FRAGMENT, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Storage { read_only: true }, + has_dynamic_offset: false, + min_binding_size: None, + }, + count: None, + }], + }); + let envmap_bgl = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: None, + entries: &[ + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStages::FRAGMENT, + ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering), + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 1, + visibility: wgpu::ShaderStages::FRAGMENT, + ty: wgpu::BindingType::Texture { + sample_type: wgpu::TextureSampleType::Float { filterable: true }, + view_dimension: wgpu::TextureViewDimension::Cube, + multisampled: false, + }, + count: None, + }, + ], + }); + let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: None, + bind_group_layouts: &[&spheres_bgl, &envmap_bgl], + push_constant_ranges: &[wgpu::PushConstantRange { + stages: wgpu::ShaderStages::FRAGMENT, + range: 0..16, + }], + }); let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { label: None, - layout: None, + layout: Some(&pipeline_layout), vertex: wgpu::VertexState { module: &shader, entry_point: None, @@ -120,30 +155,34 @@ impl Tracer { compilation_options: wgpu::PipelineCompilationOptions::default(), targets: &[Some(wgpu::ColorTargetState { format, - blend: Some(wgpu::BlendState::REPLACE), + blend: Some(wgpu::BlendState { + color: wgpu::BlendComponent { + src_factor: wgpu::BlendFactor::One, + dst_factor: wgpu::BlendFactor::One, + operation: wgpu::BlendOperation::Add, + }, + alpha: wgpu::BlendComponent { + src_factor: wgpu::BlendFactor::One, + dst_factor: wgpu::BlendFactor::One, + operation: wgpu::BlendOperation::Add, + }, + }), write_mask: wgpu::ColorWrites::ALL, })], }), multiview: None, cache: None, }); - Self { - view_buf, - params_buf, - pipeline, - } - } - - pub fn set_params(&mut self, queue: &wgpu::Queue, params: Params) { - queue.write_buffer(&self.params_buf, 0, bytes_of(¶ms)); + Self { view_buf, pipeline } } pub fn set_view(&mut self, queue: &wgpu::Queue, vertices: &[Vertex; 4]) { queue.write_buffer(&self.view_buf, 0, bytes_of(vertices)); } - pub fn render(&self, pass: &mut wgpu::RenderPass, data: &TracerData, env: &TracerEnv) { + pub fn render(&self, pass: &mut wgpu::RenderPass, data: &TracerData, env: &TracerEnv, params: Params) { pass.set_pipeline(&self.pipeline); + pass.set_push_constants(wgpu::ShaderStages::FRAGMENT, 0, bytes_of(¶ms)); pass.set_vertex_buffer(0, self.view_buf.slice(..)); pass.set_bind_group(0, &data.bindings, &[]); pass.set_bind_group(1, &env.bindings, &[]); @@ -172,16 +211,10 @@ impl TracerData { let bindings = device.create_bind_group(&wgpu::BindGroupDescriptor { label: None, layout: &tracer.pipeline.get_bind_group_layout(0), - entries: &[ - wgpu::BindGroupEntry { - binding: 0, - resource: tracer.params_buf.as_entire_binding(), - }, - wgpu::BindGroupEntry { - binding: 1, - resource: spheres_buf.as_entire_binding(), - }, - ], + entries: &[wgpu::BindGroupEntry { + binding: 1, + resource: spheres_buf.as_entire_binding(), + }], }); Self { bindings } } diff --git a/src/bin/minitracer/trace.wgsl b/src/bin/minitracer/trace.wgsl index e1cffc4..9ee1b35 100644 --- a/src/bin/minitracer/trace.wgsl +++ b/src/bin/minitracer/trace.wgsl @@ -25,7 +25,7 @@ struct Varying { @builtin(position) screen: vec4f, } -@group(0) @binding(0) var params: Params; +var params: Params; @group(0) @binding(1) var spheres: array; @group(1) @binding(0) var env_sampler: sampler; @group(1) @binding(1) var env_texture: texture_cube;