separate uniforms from the pipeline

This commit is contained in:
numzero 2026-10-19 02:28:00 +03:00
parent ec22c4a6e4
commit 972aee716a
2 changed files with 65 additions and 34 deletions

View File

@ -2,6 +2,8 @@ use std::error::Error;
use glam::{Mat4, UVec2, Vec3, Vec4, vec3, vec4}; use glam::{Mat4, UVec2, Vec3, Vec4, vec3, vec4};
use crate::render::mesh::GpuParams;
mod bevel_gear; mod bevel_gear;
mod camera; mod camera;
mod crown_gear; mod crown_gear;
@ -56,10 +58,15 @@ pub struct Core {
device: wgpu::Device, device: wgpu::Device,
queue: wgpu::Queue, queue: wgpu::Queue,
surface: wgpu::Surface<'static>, surface: wgpu::Surface<'static>,
depth: wgpu::Texture,
mesh_pipeline: render::mesh::Pipeline, mesh_pipeline: render::mesh::Pipeline,
mesh_gray: render::mesh::GpuMeshIndexed,
depth: wgpu::Texture, mesh_gear: render::mesh::GpuMeshIndexed,
mesh_cutter: render::mesh::GpuMeshIndexed,
params_gear: render::mesh::GpuParams,
params_cutter: render::mesh::GpuParams,
} }
fn srgb_to_linear(color: Vec3) -> Vec3 { fn srgb_to_linear(color: Vec3) -> Vec3 {
@ -131,7 +138,11 @@ impl Core {
.to_standard_mesh() .to_standard_mesh()
.into_indexed(); .into_indexed();
let mesh_gray = render::mesh::GpuMeshIndexed::new(&device, &bevel_gear_mesh); let mesh_cutter = render::mesh::GpuMeshIndexed::new(&device, &crown_gear_mesh);
let mesh_gear = render::mesh::GpuMeshIndexed::new(&device, &bevel_gear_mesh);
let params_gear = GpuParams::new(&device, &mesh_pipeline);
let params_cutter = GpuParams::new(&device, &mesh_pipeline);
Self::configure_surface(&surface, &device, pixel_size); Self::configure_surface(&surface, &device, pixel_size);
@ -139,9 +150,12 @@ impl Core {
device, device,
queue, queue,
surface, surface,
mesh_pipeline,
mesh_gray,
depth, depth,
mesh_pipeline,
mesh_gear,
mesh_cutter,
params_gear,
params_cutter,
} }
} }
@ -162,16 +176,26 @@ impl Core {
.clamp_z_min(0.01 * args.cam_view_y) .clamp_z_min(0.01 * args.cam_view_y)
.to_mat4(); .to_mat4();
let view = Mat4::from_mat3(camera::rotation(-args.cam_yaw, -args.cam_pitch)); let view = Mat4::from_mat3(camera::rotation(-args.cam_yaw, -args.cam_pitch));
self.mesh_pipeline.set_params( let light = vec3(0.7, 0.5, 1.0).normalize();
self.params_gear.set(
&self.queue, &self.queue,
render::mesh::Params { render::mesh::Params {
mvp: proj * view, mvp: proj * view,
light: vec3(0.7, 0.5, 1.0).normalize(), light,
_zero: 0., _zero: 0.,
color: vec4(0.5, 0.5, 0.5, 1.0), color: srgba_to_linear(vec4(0.2, 0.8, 0.1, 1.0)),
},
);
self.params_cutter.set(
&self.queue,
render::mesh::Params {
mvp: proj * view,
light,
_zero: 0.,
color: srgba_to_linear(vec4(0.8, 0.2, 0.1, 1.0)),
}, },
); );
self.queue.submit([]); // flush buffer updates
let view = output.create_view(&wgpu::TextureViewDescriptor::default()); let view = output.create_view(&wgpu::TextureViewDescriptor::default());
let depth_view = self let depth_view = self
@ -200,7 +224,10 @@ impl Core {
}), }),
..Default::default() ..Default::default()
}); });
self.mesh_gray.render(&self.mesh_pipeline, &mut pass); self.mesh_cutter
.render(&mut pass, &self.mesh_pipeline, &self.params_cutter);
self.mesh_gear
.render(&mut pass, &self.mesh_pipeline, &self.params_gear);
drop(pass); drop(pass);
self.queue.submit(std::iter::once(encoder.finish())); self.queue.submit(std::iter::once(encoder.finish()));
} }

View File

@ -26,6 +26,10 @@ pub struct Params {
pub color: Vec4, pub color: Vec4,
} }
pub struct Pipeline {
pipeline: wgpu::RenderPipeline,
}
pub struct GpuMesh { pub struct GpuMesh {
vertices: wgpu::Buffer, vertices: wgpu::Buffer,
vertex_count: u32, vertex_count: u32,
@ -37,6 +41,11 @@ pub struct GpuMeshIndexed {
index_count: u32, index_count: u32,
} }
pub struct GpuParams {
params: wgpu::Buffer,
bindings: wgpu::BindGroup,
}
impl GpuMesh { impl GpuMesh {
pub fn new(device: &wgpu::Device, data: &CpuMesh) -> Self { pub fn new(device: &wgpu::Device, data: &CpuMesh) -> Self {
let vertices = cast_slice::<_, Vertex>(&data.faces); let vertices = cast_slice::<_, Vertex>(&data.faces);
@ -84,21 +93,8 @@ impl GpuMeshIndexed {
} }
} }
pub struct Pipeline {
params: wgpu::Buffer,
bindings: wgpu::BindGroup,
pipeline: wgpu::RenderPipeline,
}
impl Pipeline { impl Pipeline {
pub fn new(device: &wgpu::Device) -> Self { pub fn new(device: &wgpu::Device) -> Self {
let params = device.create_buffer(&wgpu::BufferDescriptor {
label: None,
size: size_of::<Params>() as u64,
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
mapped_at_creation: false,
});
let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor { let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
label: None, label: None,
source: wgpu::ShaderSource::Wgsl(SHADER.into()), source: wgpu::ShaderSource::Wgsl(SHADER.into()),
@ -157,39 +153,47 @@ impl Pipeline {
multiview: None, multiview: None,
cache: None, cache: None,
}); });
Self { pipeline }
}
}
impl GpuParams {
pub fn new(device: &wgpu::Device, pipeline: &Pipeline) -> Self {
let params = device.create_buffer(&wgpu::BufferDescriptor {
label: None,
size: size_of::<Params>() as u64,
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
mapped_at_creation: false,
});
let bindings = device.create_bind_group(&wgpu::BindGroupDescriptor { let bindings = device.create_bind_group(&wgpu::BindGroupDescriptor {
label: None, label: None,
layout: &pipeline.get_bind_group_layout(0), layout: &pipeline.pipeline.get_bind_group_layout(0),
entries: &[wgpu::BindGroupEntry { entries: &[wgpu::BindGroupEntry {
binding: 0, binding: 0,
resource: params.as_entire_binding(), resource: params.as_entire_binding(),
}], }],
}); });
Self { Self { params, bindings }
params,
bindings,
pipeline,
}
} }
pub fn set_params(&self, queue: &wgpu::Queue, params: Params) { pub fn set(&self, queue: &wgpu::Queue, params: Params) {
queue.write_buffer(&self.params, 0, bytes_of(&params)); queue.write_buffer(&self.params, 0, bytes_of(&params));
} }
} }
impl GpuMesh { impl GpuMesh {
pub fn render(&self, pipeline: &Pipeline, pass: &mut wgpu::RenderPass) { pub fn render(&self, pass: &mut wgpu::RenderPass, pipeline: &Pipeline, params: &GpuParams) {
pass.set_pipeline(&pipeline.pipeline); pass.set_pipeline(&pipeline.pipeline);
pass.set_bind_group(0, &pipeline.bindings, &[]); pass.set_bind_group(0, &params.bindings, &[]);
pass.set_vertex_buffer(0, self.vertices.slice(..)); pass.set_vertex_buffer(0, self.vertices.slice(..));
pass.draw(0..self.vertex_count, 0..1); pass.draw(0..self.vertex_count, 0..1);
} }
} }
impl GpuMeshIndexed { impl GpuMeshIndexed {
pub fn render(&self, pipeline: &Pipeline, pass: &mut wgpu::RenderPass) { pub fn render(&self, pass: &mut wgpu::RenderPass, pipeline: &Pipeline, params: &GpuParams) {
pass.set_pipeline(&pipeline.pipeline); pass.set_pipeline(&pipeline.pipeline);
pass.set_bind_group(0, &pipeline.bindings, &[]); pass.set_bind_group(0, &params.bindings, &[]);
pass.set_vertex_buffer(0, self.vertices.slice(..)); pass.set_vertex_buffer(0, self.vertices.slice(..));
pass.set_index_buffer(self.indices.slice(..), wgpu::IndexFormat::Uint16); pass.set_index_buffer(self.indices.slice(..), wgpu::IndexFormat::Uint16);
pass.draw_indexed(0..self.index_count, 0, 0..1); pass.draw_indexed(0..self.index_count, 0, 0..1);