cvkg_render_gpu/passes/
ui.rs1use crate::kvasir::node::{ExecutionContext, KvasirNode};
2use crate::kvasir::nodes::{PassId, RES_SCENE};
3use crate::kvasir::resource::ResourceId;
4
5pub struct UINode {
10 pub inputs: Vec<ResourceId>,
11 pub outputs: Vec<ResourceId>,
12}
13
14impl UINode {
15 pub fn new() -> Self {
19 Self {
20 inputs: vec![RES_SCENE],
21 outputs: vec![RES_SCENE],
22 }
23 }
24}
25
26impl KvasirNode for UINode {
27 fn label(&self) -> &'static str {
28 "UI"
29 }
30
31 fn inputs(&self) -> &[ResourceId] {
32 &self.inputs
33 }
34
35 fn outputs(&self) -> &[ResourceId] {
36 &self.outputs
37 }
38
39 fn pass_id(&self) -> PassId {
40 PassId::UI
41 }
42
43 fn execute(&self, ctx: &mut ExecutionContext) {
44 let rt_w = ctx.renderer.current_width() as i32;
45 let rt_h = ctx.renderer.current_height() as i32;
46 let scale = ctx.renderer.current_scale_factor();
47
48 let scene_view = match ctx.registry.get_texture_view(RES_SCENE) {
49 Some(v) => v,
50 None => {
51 log::error!("Missing texture view for {}", stringify!(RES_SCENE));
52 return;
53 }
54 };
55
56 let mut p = ctx.encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
57 label: Some("Surtr P4 UI Layer"),
58 color_attachments: &[Some(wgpu::RenderPassColorAttachment {
59 view: &scene_view,
60 resolve_target: None,
61 ops: wgpu::Operations {
62 load: wgpu::LoadOp::Load,
63 store: wgpu::StoreOp::Store,
64 },
65 depth_slice: None,
66 })],
67 depth_stencil_attachment: None,
68 ..Default::default()
69 });
70
71 p.set_pipeline(&ctx.renderer.ui_pipeline);
72 p.set_vertex_buffer(0, ctx.renderer.geometry_buffers.vertex_buffer.slice(..));
73 p.set_vertex_buffer(1, ctx.renderer.geometry_buffers.instance_buffer.slice(..));
74 p.set_index_buffer(
75 ctx.renderer.geometry_buffers.index_buffer.slice(..),
76 wgpu::IndexFormat::Uint32,
77 );
78 p.set_bind_group(1, &ctx.renderer.dummy_env_bind_group, &[]);
79 p.set_bind_group(2, &ctx.renderer.berserker_bind_group, &[]);
80
81 for call in ctx
82 .renderer
83 .draw_calls
84 .iter()
85 .filter(|c| matches!(c.material, cvkg_core::DrawMaterial::TopUI))
86 {
87 let bg = if let Some(id) = call.texture_id {
88 if id == 0 {
89 &ctx.renderer.mega_heim_bind_group
90 } else {
91 ctx.renderer
92 .texture_bind_groups
93 .get(id as usize)
94 .unwrap_or(&ctx.renderer.dummy_texture_bind_group)
95 }
96 } else {
97 &ctx.renderer.dummy_texture_bind_group
98 };
99
100 p.set_bind_group(0, bg, &[]);
101
102 if let Some(rect) = call.scissor_rect
103 && rt_w > 0
104 && rt_h > 0
105 {
106 let x1 = (rect.x * scale).round() as i32;
107 let y1 = (rect.y * scale).round() as i32;
108 let x2 = ((rect.x + rect.width) * scale).round() as i32;
109 let y2 = ((rect.y + rect.height) * scale).round() as i32;
110 let w = (x2 - x1).clamp(0, rt_w);
111 let h = (y2 - y1).clamp(0, rt_h);
112 if w > 0 && h > 0 {
113 p.set_scissor_rect(x1 as u32, y1 as u32, w as u32, h as u32);
114 } else {
115 p.set_scissor_rect(0, 0, 0, 0);
116 }
117 } else {
118 p.set_scissor_rect(0, 0, rt_w as u32, rt_h as u32);
119 }
120 p.draw_indexed(
121 call.index_start..call.index_start + call.index_count,
122 0,
123 call.instance_start..call.instance_start + call.instance_count,
124 );
125 }
126 }
127}