gloss_renderer/forward_renderer/render_passes/
entity_id_pass.rs1use std::collections::HashMap;
2
3use crate::{
4 components::{FacesGPU, ModelMatrix, Name, Renderable, VertsGPU, VisMesh},
5 config::RenderConfig,
6 forward_renderer::{bind_group_collection::BindGroupCollection, locals::LocalEntData},
7 scene::Scene,
8 selector::Selector,
9};
10use easy_wgpu::{
11 bind_group::{BindGroupBuilder, BindGroupWrapper},
12 bind_group_layout::{BindGroupLayoutBuilder, BindGroupLayoutDesc},
13 buffer::Buffer,
14};
15
16use easy_wgpu::{gpu::Gpu, utils::create_empty_group};
17use gloss_hecs::Entity;
18
19use super::{pipeline_runner::PipelineRunner, upload_pass::PerFrameUniforms};
20
21use easy_wgpu::pipeline::RenderPipelineDescBuilder;
22
23use encase;
24
25use gloss_utils::numerical::align;
26
27#[include_wgsl_oil::include_wgsl_oil("../../../shaders/entity_id.wgsl")]
29mod shader_code {}
30
31pub struct EntityIdPass {
33 render_pipeline: wgpu::RenderPipeline,
34 _empty_group: wgpu::BindGroup,
35 locals_uniform: Buffer,
36 locals_bind_groups: LocalsBindGroups,
37}
38
39impl EntityIdPass {
40 pub fn new(gpu: &Gpu) -> Self {
44 const_assert!(std::mem::size_of::<Locals>() % 16 == 0);
46 let render_pipeline = RenderPipelineDescBuilder::new()
58 .label("ent_id_pass")
59 .shader_code(shader_code::SOURCE)
60 .shader_label("ent_id_shader")
61 .add_bind_group_layout_desc(PerFrameUniforms::build_layout_desc())
62 .add_bind_group_layout_desc(LocalsBindGroups::build_layout_desc())
63 .add_vertex_buffer_layout(VertsGPU::vertex_buffer_layout::<0>())
64 .add_render_target(wgpu::ColorTargetState {
65 format: wgpu::TextureFormat::Rgba8Unorm,
66 blend: None,
67 write_mask: wgpu::ColorWrites::ALL,
68 })
69 .depth_state(Some(wgpu::DepthStencilState {
70 format: wgpu::TextureFormat::Depth16Unorm,
71 depth_write_enabled: true,
72 depth_compare: wgpu::CompareFunction::Greater,
73 stencil: wgpu::StencilState::default(),
74 bias: wgpu::DepthBiasState::default(),
75 }))
76 .build_pipeline(gpu.device());
77
78 let empty_group = create_empty_group(gpu.device());
79
80 let size_bytes = 0x10000;
81 let usage = wgpu::BufferUsages::COPY_DST | wgpu::BufferUsages::UNIFORM;
82 let locals_uniform = Buffer::new_empty(gpu.device(), usage, Some("local_buffer"), size_bytes);
83
84 let locals_bind_groups = LocalsBindGroups::new(gpu);
85
86 Self {
87 render_pipeline,
88 _empty_group: empty_group,
89 locals_uniform,
90 locals_bind_groups,
91 }
92 }
93}
94
95impl PipelineRunner for EntityIdPass {
96 type QueryItems<'a> = (&'a VertsGPU, &'a FacesGPU, &'a Name, &'a ModelMatrix, &'a VisMesh);
97 type QueryState<'a> = gloss_hecs::QueryBorrow<'a, gloss_hecs::With<Self::QueryItems<'a>, &'a Renderable>>;
98
99 fn query_state(scene: &Scene) -> Self::QueryState<'_> {
100 scene.world.query::<Self::QueryItems<'_>>().with::<&Renderable>()
101 }
102 fn prepare<'a>(&mut self, gpu: &Gpu, _per_frame_uniforms: &PerFrameUniforms, scene: &'a Scene) -> Self::QueryState<'a> {
103 self.begin_pass();
104 self.update_locals(gpu, scene);
105 Self::query_state(scene)
106 }
107
108 #[allow(clippy::too_many_lines)]
111 fn run<'r>(
112 &'r mut self,
113 render_pass: &mut wgpu::RenderPass<'r>,
114 per_frame_uniforms: &'r PerFrameUniforms,
115 _render_params: &RenderConfig,
116 query_state: &'r mut Self::QueryState<'_>,
117 scene: &Scene,
118 ) {
119 let selector_is_active = scene.has_resource::<Selector>();
121
122 if query_state.iter().count() == 0 || !selector_is_active {
123 return;
124 }
125
126 render_pass.set_pipeline(&self.render_pipeline);
127 render_pass.set_bind_group(0, &per_frame_uniforms.bind_group, &[]);
128
129 for (_id, (verts, faces, name, _model_matrix, _vis_mesh)) in query_state.iter() {
130 let (local_bg, offset) = &self.locals_bind_groups.mesh2local_bind[&name.0.clone()];
131
132 render_pass.set_bind_group(1, local_bg.bg(), &[*offset]);
133 render_pass.set_vertex_buffer(0, verts.buf.slice(..));
134 render_pass.set_index_buffer(faces.buf.slice(..), wgpu::IndexFormat::Uint32);
135 render_pass.draw_indexed(0..faces.nr_triangles * 3, 0, 0..1);
136 }
137 }
138
139 fn begin_pass(&mut self) {}
140
141 fn update_locals(&mut self, gpu: &Gpu, scene: &Scene) {
144 Self::update_locals_inner::<Locals, _>(
145 gpu,
146 scene,
147 &mut self.locals_uniform,
148 &mut self.locals_bind_groups,
149 &mut Self::query_state(scene),
150 );
151 }
152}
153
154#[repr(C)]
156#[derive(Clone, Copy, encase::ShaderType)]
157struct Locals {
158 model_matrix: nalgebra::Matrix4<f32>,
159 entity_id: u32,
160 pad_a: f32,
161 pad_b: f32,
162 pad_c: f32,
163}
164impl LocalEntData for Locals {
165 fn new(entity: Entity, scene: &Scene) -> Self {
166 let model_matrix = scene.get_comp::<&ModelMatrix>(&entity).unwrap().0.to_homogeneous();
167 assert!(entity.id() < 256, "A maximum of 256 entities are allowed!");
168 Locals {
169 model_matrix,
170 entity_id: entity.id(),
171 pad_a: 0.0,
172 pad_b: 0.0,
173 pad_c: 0.0,
174 }
175 }
176}
177
178struct LocalsBindGroups {
179 layout: wgpu::BindGroupLayout,
180 pub mesh2local_bind: HashMap<String, (BindGroupWrapper, u32)>,
181}
182impl BindGroupCollection for LocalsBindGroups {
183 fn new(gpu: &Gpu) -> Self {
184 Self {
185 layout: Self::build_layout_desc().into_bind_group_layout(gpu.device()),
186 mesh2local_bind: HashMap::default(),
187 }
188 }
189
190 fn build_layout_desc() -> BindGroupLayoutDesc {
193 BindGroupLayoutBuilder::new()
194 .label("ent_id_pass_locals_layout")
195 .add_entry_uniform(
197 wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
198 true,
199 wgpu::BufferSize::new(u64::from(align(u32::try_from(std::mem::size_of::<Locals>()).unwrap(), 256))),
200 )
201 .build()
202 }
203
204 fn update_bind_group(&mut self, _entity: Entity, gpu: &Gpu, mesh_name: &str, ubo: &Buffer, offset_in_ubo: u32, _scene: &Scene) {
205 let entries = BindGroupBuilder::new().add_entry_buf_chunk::<Locals>(&ubo.buffer).build_entries();
206
207 self.update_if_stale(mesh_name, entries, offset_in_ubo, gpu);
208 }
209
210 fn get_layout(&self) -> &wgpu::BindGroupLayout {
211 &self.layout
212 }
213 fn get_mut_entity2binds(&mut self) -> &mut HashMap<String, (BindGroupWrapper, u32)> {
214 &mut self.mesh2local_bind
215 }
216}