1use std::ops::Deref;
2
3use bevy_ecs::prelude::*;
4
5use crate::{
6 ResolutionInfo, WgpuContext,
7 primitives::{
8 mesh_items::MeshItemsBuffer,
9 viewport::{ViewportBindGroup, ViewportGpuPacket},
10 },
11 resource::{GpuResource, OUTPUT_TEXTURE_FORMAT, PipelinesPool},
12 schedule::{FrameTarget, RenderContext, RenderProfiler},
13};
14
15#[allow(clippy::too_many_arguments)]
16pub(crate) fn depth(
17 mut render: RenderContext,
18 ctx: Res<WgpuContext>,
19 pipelines: Res<PipelinesPool>,
20 resolution: Res<ResolutionInfo>,
21 target: Res<FrameTarget>,
22 viewport: Res<ViewportGpuPacket>,
23 merged: Res<MeshItemsBuffer>,
24 profiler: Res<RenderProfiler>,
25) {
26 if merged.item_count() == 0 {
27 return;
28 }
29 let mut pass = render
30 .encoder()
31 .begin_render_pass(&wgpu::RenderPassDescriptor {
32 label: Some("Merged MeshItem Depth Render Pass"),
33 color_attachments: &[],
34 depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment {
35 view: &target.depth_stencil_view,
36 depth_ops: Some(wgpu::Operations {
37 load: wgpu::LoadOp::Load,
38 store: wgpu::StoreOp::Store,
39 }),
40 stencil_ops: None,
41 }),
42 timestamp_writes: None,
43 occlusion_query_set: None,
44 multiview_mask: None,
45 });
46 profiler.scope_pass("mesh::depth", &mut pass, |pass| {
47 pass.set_pipeline(&pipelines.get_or_init::<MeshItemDepthPipeline>(&ctx));
48 pass.set_bind_group(0, &resolution.bind_group, &[]);
49 pass.set_bind_group(1, &viewport.uniforms_bind_group.bind_group, &[]);
50 pass.set_bind_group(2, merged.render_bind_group.as_ref().unwrap(), &[]);
51 pass.set_vertex_buffer(0, merged.vertices_buffer.buffer.slice(..));
52 pass.set_vertex_buffer(1, merged.mesh_ids_buffer.buffer.slice(..));
53 pass.set_vertex_buffer(2, merged.vertex_colors_buffer.buffer.slice(..));
54 pass.set_vertex_buffer(3, merged.vertex_normals_buffer.buffer.slice(..));
55 pass.set_index_buffer(
56 merged.indices_buffer.buffer.slice(..),
57 wgpu::IndexFormat::Uint32,
58 );
59 pass.draw_indexed(0..merged.total_indices(), 0, 0..1);
60 });
61}
62
63#[allow(clippy::too_many_arguments)]
64pub(crate) fn color(
65 mut render: RenderContext,
66 ctx: Res<WgpuContext>,
67 pipelines: Res<PipelinesPool>,
68 resolution: Res<ResolutionInfo>,
69 target: Res<FrameTarget>,
70 viewport: Res<ViewportGpuPacket>,
71 merged: Res<MeshItemsBuffer>,
72 profiler: Res<RenderProfiler>,
73) {
74 if merged.item_count() == 0 {
75 return;
76 }
77 let mut pass = render
78 .encoder()
79 .begin_render_pass(&wgpu::RenderPassDescriptor {
80 label: Some("Merged MeshItem Color Render Pass"),
81 color_attachments: &[Some(wgpu::RenderPassColorAttachment {
82 view: &target.render_view,
83 resolve_target: None,
84 depth_slice: None,
85 ops: wgpu::Operations {
86 load: wgpu::LoadOp::Load,
87 store: wgpu::StoreOp::Store,
88 },
89 })],
90 depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment {
91 view: &target.depth_stencil_view,
92 depth_ops: Some(wgpu::Operations {
93 load: wgpu::LoadOp::Load,
94 store: wgpu::StoreOp::Store,
95 }),
96 stencil_ops: None,
97 }),
98 timestamp_writes: None,
99 occlusion_query_set: None,
100 multiview_mask: None,
101 });
102 profiler.scope_pass("mesh::color", &mut pass, |pass| {
103 pass.set_pipeline(&pipelines.get_or_init::<MeshItemColorPipeline>(&ctx));
104 pass.set_bind_group(0, &resolution.bind_group, &[]);
105 pass.set_bind_group(1, &viewport.uniforms_bind_group.bind_group, &[]);
106 pass.set_bind_group(2, merged.render_bind_group.as_ref().unwrap(), &[]);
107 pass.set_vertex_buffer(0, merged.vertices_buffer.buffer.slice(..));
108 pass.set_vertex_buffer(1, merged.mesh_ids_buffer.buffer.slice(..));
109 pass.set_vertex_buffer(2, merged.vertex_colors_buffer.buffer.slice(..));
110 pass.set_vertex_buffer(3, merged.vertex_normals_buffer.buffer.slice(..));
111 pass.set_index_buffer(
112 merged.indices_buffer.buffer.slice(..),
113 wgpu::IndexFormat::Uint32,
114 );
115 pass.draw_indexed(0..merged.total_indices(), 0, 0..1);
116 });
117}
118
119pub struct MeshItemColorPipeline {
120 pipeline: wgpu::RenderPipeline,
121}
122
123impl Deref for MeshItemColorPipeline {
124 type Target = wgpu::RenderPipeline;
125 fn deref(&self) -> &Self::Target {
126 &self.pipeline
127 }
128}
129
130impl GpuResource for MeshItemColorPipeline {
131 fn new(ctx: &WgpuContext) -> Self {
132 let module = &ctx
133 .device
134 .create_shader_module(wgpu::include_wgsl!("./shaders/mesh_item.wgsl"));
135 let layout = ctx
136 .device
137 .create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
138 label: Some("MeshItem Color Pipeline Layout"),
139 bind_group_layouts: &[
140 Some(&ResolutionInfo::create_bind_group_layout(ctx)),
141 Some(&ViewportBindGroup::bind_group_layout(ctx)),
142 Some(&MeshItemsBuffer::render_bind_group_layout(ctx)),
143 ],
144 immediate_size: 0,
145 });
146 let vertex_buffer_layouts = MeshItemsBuffer::vertex_buffer_layouts().map(Some);
147 let pipeline = ctx
148 .device
149 .create_render_pipeline(&wgpu::RenderPipelineDescriptor {
150 label: Some("MeshItem Color Pipeline"),
151 layout: Some(&layout),
152 vertex: wgpu::VertexState {
153 module,
154 entry_point: Some("vs_main"),
155 buffers: &vertex_buffer_layouts,
156 compilation_options: wgpu::PipelineCompilationOptions::default(),
157 },
158 fragment: Some(wgpu::FragmentState {
159 module,
160 entry_point: Some("fs_color"),
161 compilation_options: wgpu::PipelineCompilationOptions::default(),
162 targets: &[Some(wgpu::ColorTargetState {
163 format: OUTPUT_TEXTURE_FORMAT,
164 blend: Some(wgpu::BlendState::ALPHA_BLENDING),
165 write_mask: wgpu::ColorWrites::ALL,
166 })],
167 }),
168 primitive: wgpu::PrimitiveState {
169 topology: wgpu::PrimitiveTopology::TriangleList,
170 ..Default::default()
171 },
172 depth_stencil: Some(wgpu::DepthStencilState {
173 format: wgpu::TextureFormat::Depth32Float,
174 depth_write_enabled: Some(false),
175 depth_compare: Some(wgpu::CompareFunction::LessEqual),
176 stencil: wgpu::StencilState::default(),
177 bias: wgpu::DepthBiasState::default(),
178 }),
179 multisample: wgpu::MultisampleState {
180 count: 1,
181 mask: !0,
182 alpha_to_coverage_enabled: false,
183 },
184 multiview_mask: None,
185 cache: None,
186 });
187 Self { pipeline }
188 }
189}
190
191pub struct MeshItemDepthPipeline {
192 pipeline: wgpu::RenderPipeline,
193}
194
195impl Deref for MeshItemDepthPipeline {
196 type Target = wgpu::RenderPipeline;
197 fn deref(&self) -> &Self::Target {
198 &self.pipeline
199 }
200}
201
202impl GpuResource for MeshItemDepthPipeline {
203 fn new(ctx: &WgpuContext) -> Self {
204 let module = &ctx
205 .device
206 .create_shader_module(wgpu::include_wgsl!("./shaders/mesh_item.wgsl"));
207 let layout = ctx
208 .device
209 .create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
210 label: Some("MeshItem Depth Pipeline Layout"),
211 bind_group_layouts: &[
212 Some(&ResolutionInfo::create_bind_group_layout(ctx)),
213 Some(&ViewportBindGroup::bind_group_layout(ctx)),
214 Some(&MeshItemsBuffer::render_bind_group_layout(ctx)),
215 ],
216 immediate_size: 0,
217 });
218 let vertex_buffer_layouts = MeshItemsBuffer::vertex_buffer_layouts().map(Some);
219 let pipeline = ctx
220 .device
221 .create_render_pipeline(&wgpu::RenderPipelineDescriptor {
222 label: Some("MeshItem Depth Pipeline"),
223 layout: Some(&layout),
224 vertex: wgpu::VertexState {
225 module,
226 entry_point: Some("vs_main"),
227 buffers: &vertex_buffer_layouts,
228 compilation_options: wgpu::PipelineCompilationOptions::default(),
229 },
230 fragment: Some(wgpu::FragmentState {
231 module,
232 entry_point: Some("fs_depth"),
233 compilation_options: wgpu::PipelineCompilationOptions::default(),
234 targets: &[],
235 }),
236 primitive: wgpu::PrimitiveState {
237 topology: wgpu::PrimitiveTopology::TriangleList,
238 ..Default::default()
239 },
240 depth_stencil: Some(wgpu::DepthStencilState {
241 format: wgpu::TextureFormat::Depth32Float,
242 depth_write_enabled: Some(true),
243 depth_compare: Some(wgpu::CompareFunction::Less),
244 stencil: wgpu::StencilState::default(),
245 bias: wgpu::DepthBiasState::default(),
246 }),
247 multisample: wgpu::MultisampleState {
248 count: 1,
249 mask: !0,
250 alpha_to_coverage_enabled: false,
251 },
252 multiview_mask: None,
253 cache: None,
254 });
255 Self { pipeline }
256 }
257}