cvkg_render_gpu/passes/
geometry.rs1use crate::kvasir::node::{ExecutionContext, KvasirNode};
2use crate::kvasir::nodes::{PassId, RES_SCENE};
3use crate::kvasir::resource::ResourceId;
4
5pub struct GeometryNode {
6 pub inputs: Vec<ResourceId>,
7 pub outputs: Vec<ResourceId>,
8}
9
10impl GeometryNode {
11 pub fn new() -> Self {
12 Self {
13 inputs: vec![],
14 outputs: vec![RES_SCENE],
15 }
16 }
17}
18
19impl KvasirNode for GeometryNode {
20 fn label(&self) -> &'static str {
21 "Geometry"
22 }
23
24 fn inputs(&self) -> &[ResourceId] {
25 &self.inputs
26 }
27
28 fn outputs(&self) -> &[ResourceId] {
29 &self.outputs
30 }
31
32 fn pass_id(&self) -> PassId {
33 PassId::Geometry
34 }
35
36 fn execute(&self, ctx: &mut ExecutionContext) {
37 let scale = ctx.renderer.current_scale_factor();
38 let rt_w = ctx.renderer.current_width() as i32;
39 let rt_h = ctx.renderer.current_height() as i32;
40
41 let scene_view = match ctx.registry.get_texture_view(RES_SCENE) {
42 Some(v) => v,
43 None => {
44 log::error!("Missing texture view for {}", stringify!(RES_SCENE));
45 return;
46 }
47 };
48 let msaa_view = match ctx
49 .registry
50 .get_texture_view(crate::kvasir::nodes::RES_SCENE_MSAA)
51 {
52 Some(v) => v,
53 None => {
54 log::error!(
55 "Missing texture view for {}",
56 stringify!(crate::kvasir::nodes::RES_SCENE_MSAA)
57 );
58 return;
59 }
60 };
61 let depth_view = ctx.depth_view;
62
63 let bg = ctx.renderer.default_background_color;
64 let mut p = ctx.encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
65 label: Some("Surtr P1 Opaque Background"),
66 color_attachments: &[Some(wgpu::RenderPassColorAttachment {
67 view: &msaa_view,
68 resolve_target: Some(&scene_view),
69 ops: wgpu::Operations {
70 load: wgpu::LoadOp::Clear(wgpu::Color {
71 r: bg[0] as f64,
72 g: bg[1] as f64,
73 b: bg[2] as f64,
74 a: bg[3] as f64,
75 }),
76 store: wgpu::StoreOp::Store,
77 },
78 depth_slice: None,
79 })],
80 depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment {
81 view: depth_view,
82 depth_ops: Some(wgpu::Operations {
83 load: wgpu::LoadOp::Clear(1.0),
84 store: wgpu::StoreOp::Store,
85 }),
86 stencil_ops: None,
87 }),
88 timestamp_writes: ctx.renderer.skuld_queries.as_ref().map(|q| {
89 wgpu::RenderPassTimestampWrites {
90 query_set: q,
91 beginning_of_pass_write_index: Some(0),
92 end_of_pass_write_index: None,
93 }
94 }),
95 occlusion_query_set: None,
96 multiview_mask: None,
97 });
98
99 if ctx.renderer.current_scene.scene_type == cvkg_core::SCENE_AURORA {
100 p.set_pipeline(&ctx.renderer.background_pipeline);
101 p.set_bind_group(0, &ctx.renderer.dummy_texture_bind_group, &[]);
102 p.set_bind_group(1, &ctx.renderer.dummy_env_bind_group, &[]);
103 p.set_bind_group(2, &ctx.renderer.berserker_bind_group, &[]);
104 p.draw(0..3, 0..1);
105 }
106
107 if !ctx.renderer.draw_calls.is_empty() {
108 log::trace!(
109 "[Kvasir] GeometryNode: draw_calls={}",
110 ctx.renderer.draw_calls.len()
111 );
112 for (i, call) in ctx.renderer.draw_calls.iter().enumerate() {
113 log::trace!(
114 "[Kvasir] call[{}]: material={:?}, target_id={:?}, index_start={}, index_count={}",
115 i,
116 call.material,
117 call.target_id,
118 call.index_start,
119 call.index_count
120 );
121 }
122 p.set_vertex_buffer(0, ctx.renderer.geometry_buffers.vertex_buffer.slice(..));
123 p.set_vertex_buffer(1, ctx.renderer.geometry_buffers.instance_buffer.slice(..));
124 p.set_index_buffer(
125 ctx.renderer.geometry_buffers.index_buffer.slice(..),
126 wgpu::IndexFormat::Uint32,
127 );
128 p.set_bind_group(1, &ctx.renderer.dummy_env_bind_group, &[]);
129 p.set_bind_group(2, &ctx.renderer.berserker_bind_group, &[]);
130
131 let mut opaque_calls_count = 0;
139 for call in ctx.renderer.draw_calls.iter().filter(|c| {
140 matches!(c.material, cvkg_core::DrawMaterial::Opaque) && c.target_id.is_none()
141 }) {
142 opaque_calls_count += 1;
143 p.set_pipeline(&ctx.renderer.opaque_pipeline);
144
145 if let Some(rect) = call.scissor_rect
149 && rt_w > 0
150 && rt_h > 0
151 {
152 let x1 = (rect.x * scale).round() as i32;
153 let y1 = (rect.y * scale).round() as i32;
154 let x2 = ((rect.x + rect.width) * scale).round() as i32;
155 let y2 = ((rect.y + rect.height) * scale).round() as i32;
156 let w = (x2 - x1).clamp(0, rt_w);
157 let h = (y2 - y1).clamp(0, rt_h);
158 if w > 0 && h > 0 {
159 p.set_scissor_rect(x1 as u32, y1 as u32, w as u32, h as u32);
160 } else {
161 p.set_scissor_rect(0, 0, 0, 0);
167 }
168 } else {
169 p.set_scissor_rect(0, 0, rt_w as u32, rt_h as u32);
170 }
171
172 let bg = if let Some(id) = call.texture_id {
173 if id == 0 {
174 &ctx.renderer.mega_heim_bind_group
175 } else {
176 ctx.renderer
177 .texture_bind_groups
178 .get(id as usize)
179 .unwrap_or(&ctx.renderer.dummy_texture_bind_group)
180 }
181 } else {
182 &ctx.renderer.dummy_texture_bind_group
183 };
184 p.set_bind_group(0, bg, &[]);
185 p.draw_indexed(
186 call.index_start..call.index_start + call.index_count,
187 0,
188 call.instance_start..call.instance_start + call.instance_count,
189 );
190 }
191 log::trace!(
192 "[Kvasir] GeometryNode: opaque_calls drawn={}",
193 opaque_calls_count
194 );
195 }
196 }
197}