Skip to main content

cvkg_render_gpu/passes/
accessibility.rs

1use crate::color_blindness::ColorBlindUniforms;
2use crate::kvasir::node::{ExecutionContext, KvasirNode};
3use crate::kvasir::nodes::{PassId, RES_SCENE};
4use crate::kvasir::resource::ResourceId;
5
6pub struct AccessibilityNode {
7    pub inputs: Vec<ResourceId>,
8    pub outputs: Vec<ResourceId>,
9}
10
11impl AccessibilityNode {
12    pub fn new() -> Self {
13        Self {
14            // Reads from RES_SCENE (scene texture sampled in the shader).
15            // Writes to the swapchain render target (not a graph resource).
16            inputs: vec![RES_SCENE],
17            outputs: vec![], // render target write is implicit, not a graph edge
18        }
19    }
20}
21
22impl Default for AccessibilityNode {
23    fn default() -> Self {
24        Self::new()
25    }
26}
27
28impl KvasirNode for AccessibilityNode {
29    fn label(&self) -> &'static str {
30        "Accessibility"
31    }
32
33    fn inputs(&self) -> &[ResourceId] {
34        &self.inputs
35    }
36
37    fn outputs(&self) -> &[ResourceId] {
38        &self.outputs
39    }
40
41    fn pass_id(&self) -> PassId {
42        PassId::Accessibility
43    }
44
45    fn execute(&self, ctx: &mut ExecutionContext) {
46        if ctx.renderer.color_blind_mode.is_identity() {
47            return;
48        }
49
50        let uniforms = ColorBlindUniforms::new(
51            ctx.renderer.color_blind_mode,
52            ctx.renderer.color_blind_intensity,
53        );
54        ctx.queue.write_buffer(
55            &ctx.renderer.color_blind_uniform_buffer,
56            0,
57            bytemuck::bytes_of(&uniforms),
58        );
59
60        // Sample from the scene texture, render to the swapchain target.
61        let scene_view = match ctx
62            .registry
63            .get_texture_view(crate::kvasir::nodes::RES_SCENE)
64        {
65            Some(v) => v,
66            None => {
67                log::error!("[Accessibility] Missing scene texture view");
68                return;
69            }
70        };
71        let target_view = ctx.target_view;
72
73        let color_blind_bind_group = ctx.get_or_create_bind_group(
74            (crate::kvasir::nodes::RES_SCENE, 99998, false),
75            &ctx.renderer.color_blind_bind_group_layout,
76            &[
77                wgpu::BindGroupEntry {
78                    binding: 0,
79                    resource: wgpu::BindingResource::TextureView(&scene_view),
80                },
81                wgpu::BindGroupEntry {
82                    binding: 1,
83                    resource: wgpu::BindingResource::Sampler(&ctx.renderer.sampler),
84                },
85                wgpu::BindGroupEntry {
86                    binding: 2,
87                    resource: wgpu::BindingResource::Buffer(wgpu::BufferBinding {
88                        buffer: &ctx.renderer.color_blind_uniform_buffer,
89                        offset: 0,
90                        size: wgpu::BufferSize::new(
91                            std::mem::size_of::<ColorBlindUniforms>() as u64
92                        ),
93                    }),
94                },
95            ],
96            Some("Color Blind Bind Group"),
97        );
98
99        let mut p = ctx.encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
100            label: Some("Surtr Accessibility"),
101            color_attachments: &[Some(wgpu::RenderPassColorAttachment {
102                view: target_view,
103                resolve_target: None,
104                ops: wgpu::Operations {
105                    load: wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT),
106                    store: wgpu::StoreOp::Store,
107                },
108                depth_slice: None,
109            })],
110            depth_stencil_attachment: None,
111            timestamp_writes: None,
112            occlusion_query_set: None,
113            multiview_mask: None,
114        });
115
116        p.set_pipeline(&ctx.renderer.color_blind_pipeline);
117        p.set_bind_group(0, &color_blind_bind_group, &[]);
118        p.draw(0..3, 0..1);
119    }
120}