1use bevy_math::Mat4;
4use bevy_render::{
5 mesh::morph::MAX_MORPH_WEIGHTS,
6 render_resource::*,
7 renderer::{RenderAdapter, RenderDevice},
8};
9
10use crate::{binding_arrays_are_usable, render::skin::MAX_JOINTS, LightmapSlab};
11
12const MORPH_WEIGHT_SIZE: usize = size_of::<f32>();
13
14pub const MORPH_BUFFER_SIZE: usize = MAX_MORPH_WEIGHTS * MORPH_WEIGHT_SIZE;
20
21const JOINT_SIZE: usize = size_of::<Mat4>();
22pub(crate) const JOINT_BUFFER_SIZE: usize = MAX_JOINTS * JOINT_SIZE;
23
24mod layout_entry {
26 use core::num::NonZeroU32;
27
28 use super::{JOINT_BUFFER_SIZE, MORPH_BUFFER_SIZE};
29 use crate::{render::skin, MeshUniform, LIGHTMAPS_PER_SLAB};
30 use bevy_render::{
31 render_resource::{
32 binding_types::{
33 sampler, storage_buffer_read_only_sized, texture_2d, texture_3d,
34 uniform_buffer_sized,
35 },
36 BindGroupLayoutEntryBuilder, BufferSize, GpuArrayBuffer, SamplerBindingType,
37 ShaderStages, TextureSampleType,
38 },
39 renderer::RenderDevice,
40 };
41
42 pub(super) fn model(render_device: &RenderDevice) -> BindGroupLayoutEntryBuilder {
43 GpuArrayBuffer::<MeshUniform>::binding_layout(render_device)
44 .visibility(ShaderStages::VERTEX_FRAGMENT)
45 }
46 pub(super) fn skinning(render_device: &RenderDevice) -> BindGroupLayoutEntryBuilder {
47 let size = BufferSize::new(JOINT_BUFFER_SIZE as u64);
50 if skin::skins_use_uniform_buffers(render_device) {
51 uniform_buffer_sized(true, size)
52 } else {
53 storage_buffer_read_only_sized(false, size)
54 }
55 }
56 pub(super) fn weights() -> BindGroupLayoutEntryBuilder {
57 uniform_buffer_sized(true, BufferSize::new(MORPH_BUFFER_SIZE as u64))
58 }
59 pub(super) fn targets() -> BindGroupLayoutEntryBuilder {
60 texture_3d(TextureSampleType::Float { filterable: false })
61 }
62 pub(super) fn lightmaps_texture_view() -> BindGroupLayoutEntryBuilder {
63 texture_2d(TextureSampleType::Float { filterable: true }).visibility(ShaderStages::FRAGMENT)
64 }
65 pub(super) fn lightmaps_sampler() -> BindGroupLayoutEntryBuilder {
66 sampler(SamplerBindingType::Filtering).visibility(ShaderStages::FRAGMENT)
67 }
68 pub(super) fn lightmaps_texture_view_array() -> BindGroupLayoutEntryBuilder {
69 texture_2d(TextureSampleType::Float { filterable: true })
70 .visibility(ShaderStages::FRAGMENT)
71 .count(NonZeroU32::new(LIGHTMAPS_PER_SLAB as u32).unwrap())
72 }
73 pub(super) fn lightmaps_sampler_array() -> BindGroupLayoutEntryBuilder {
74 sampler(SamplerBindingType::Filtering)
75 .visibility(ShaderStages::FRAGMENT)
76 .count(NonZeroU32::new(LIGHTMAPS_PER_SLAB as u32).unwrap())
77 }
78}
79
80mod entry {
83 use crate::render::skin;
84
85 use super::{JOINT_BUFFER_SIZE, MORPH_BUFFER_SIZE};
86 use bevy_render::{
87 render_resource::{
88 BindGroupEntry, BindingResource, Buffer, BufferBinding, BufferSize, Sampler,
89 TextureView, WgpuSampler, WgpuTextureView,
90 },
91 renderer::RenderDevice,
92 };
93
94 fn entry(binding: u32, size: Option<u64>, buffer: &Buffer) -> BindGroupEntry {
95 BindGroupEntry {
96 binding,
97 resource: BindingResource::Buffer(BufferBinding {
98 buffer,
99 offset: 0,
100 size: size.map(|size| BufferSize::new(size).unwrap()),
101 }),
102 }
103 }
104 pub(super) fn model(binding: u32, resource: BindingResource) -> BindGroupEntry {
105 BindGroupEntry { binding, resource }
106 }
107 pub(super) fn skinning<'a>(
108 render_device: &RenderDevice,
109 binding: u32,
110 buffer: &'a Buffer,
111 ) -> BindGroupEntry<'a> {
112 let size = if skin::skins_use_uniform_buffers(render_device) {
113 Some(JOINT_BUFFER_SIZE as u64)
114 } else {
115 None
116 };
117 entry(binding, size, buffer)
118 }
119 pub(super) fn weights(binding: u32, buffer: &Buffer) -> BindGroupEntry {
120 entry(binding, Some(MORPH_BUFFER_SIZE as u64), buffer)
121 }
122 pub(super) fn targets(binding: u32, texture: &TextureView) -> BindGroupEntry {
123 BindGroupEntry {
124 binding,
125 resource: BindingResource::TextureView(texture),
126 }
127 }
128 pub(super) fn lightmaps_texture_view(binding: u32, texture: &TextureView) -> BindGroupEntry {
129 BindGroupEntry {
130 binding,
131 resource: BindingResource::TextureView(texture),
132 }
133 }
134 pub(super) fn lightmaps_sampler(binding: u32, sampler: &Sampler) -> BindGroupEntry {
135 BindGroupEntry {
136 binding,
137 resource: BindingResource::Sampler(sampler),
138 }
139 }
140 pub(super) fn lightmaps_texture_view_array<'a>(
141 binding: u32,
142 textures: &'a [&'a WgpuTextureView],
143 ) -> BindGroupEntry<'a> {
144 BindGroupEntry {
145 binding,
146 resource: BindingResource::TextureViewArray(textures),
147 }
148 }
149 pub(super) fn lightmaps_sampler_array<'a>(
150 binding: u32,
151 samplers: &'a [&'a WgpuSampler],
152 ) -> BindGroupEntry<'a> {
153 BindGroupEntry {
154 binding,
155 resource: BindingResource::SamplerArray(samplers),
156 }
157 }
158}
159
160#[derive(Clone)]
162pub struct MeshLayouts {
163 pub model_only: BindGroupLayout,
165
166 pub lightmapped: BindGroupLayout,
168
169 pub skinned: BindGroupLayout,
171
172 pub skinned_motion: BindGroupLayout,
175
176 pub morphed: BindGroupLayout,
180
181 pub morphed_motion: BindGroupLayout,
184
185 pub morphed_skinned: BindGroupLayout,
190
191 pub morphed_skinned_motion: BindGroupLayout,
195}
196
197impl MeshLayouts {
198 pub fn new(render_device: &RenderDevice, render_adapter: &RenderAdapter) -> Self {
202 MeshLayouts {
203 model_only: Self::model_only_layout(render_device),
204 lightmapped: Self::lightmapped_layout(render_device, render_adapter),
205 skinned: Self::skinned_layout(render_device),
206 skinned_motion: Self::skinned_motion_layout(render_device),
207 morphed: Self::morphed_layout(render_device),
208 morphed_motion: Self::morphed_motion_layout(render_device),
209 morphed_skinned: Self::morphed_skinned_layout(render_device),
210 morphed_skinned_motion: Self::morphed_skinned_motion_layout(render_device),
211 }
212 }
213
214 fn model_only_layout(render_device: &RenderDevice) -> BindGroupLayout {
217 render_device.create_bind_group_layout(
218 "mesh_layout",
219 &BindGroupLayoutEntries::single(
220 ShaderStages::empty(),
221 layout_entry::model(render_device),
222 ),
223 )
224 }
225
226 fn skinned_layout(render_device: &RenderDevice) -> BindGroupLayout {
228 render_device.create_bind_group_layout(
229 "skinned_mesh_layout",
230 &BindGroupLayoutEntries::with_indices(
231 ShaderStages::VERTEX,
232 (
233 (0, layout_entry::model(render_device)),
234 (1, layout_entry::skinning(render_device)),
236 ),
237 ),
238 )
239 }
240
241 fn skinned_motion_layout(render_device: &RenderDevice) -> BindGroupLayout {
244 render_device.create_bind_group_layout(
245 "skinned_motion_mesh_layout",
246 &BindGroupLayoutEntries::with_indices(
247 ShaderStages::VERTEX,
248 (
249 (0, layout_entry::model(render_device)),
250 (1, layout_entry::skinning(render_device)),
252 (6, layout_entry::skinning(render_device)),
254 ),
255 ),
256 )
257 }
258
259 fn morphed_layout(render_device: &RenderDevice) -> BindGroupLayout {
261 render_device.create_bind_group_layout(
262 "morphed_mesh_layout",
263 &BindGroupLayoutEntries::with_indices(
264 ShaderStages::VERTEX,
265 (
266 (0, layout_entry::model(render_device)),
267 (2, layout_entry::weights()),
269 (3, layout_entry::targets()),
270 ),
271 ),
272 )
273 }
274
275 fn morphed_motion_layout(render_device: &RenderDevice) -> BindGroupLayout {
278 render_device.create_bind_group_layout(
279 "morphed_mesh_layout",
280 &BindGroupLayoutEntries::with_indices(
281 ShaderStages::VERTEX,
282 (
283 (0, layout_entry::model(render_device)),
284 (2, layout_entry::weights()),
286 (3, layout_entry::targets()),
287 (7, layout_entry::weights()),
289 ),
290 ),
291 )
292 }
293
294 fn morphed_skinned_layout(render_device: &RenderDevice) -> BindGroupLayout {
297 render_device.create_bind_group_layout(
298 "morphed_skinned_mesh_layout",
299 &BindGroupLayoutEntries::with_indices(
300 ShaderStages::VERTEX,
301 (
302 (0, layout_entry::model(render_device)),
303 (1, layout_entry::skinning(render_device)),
305 (2, layout_entry::weights()),
307 (3, layout_entry::targets()),
308 ),
309 ),
310 )
311 }
312
313 fn morphed_skinned_motion_layout(render_device: &RenderDevice) -> BindGroupLayout {
316 render_device.create_bind_group_layout(
317 "morphed_skinned_motion_mesh_layout",
318 &BindGroupLayoutEntries::with_indices(
319 ShaderStages::VERTEX,
320 (
321 (0, layout_entry::model(render_device)),
322 (1, layout_entry::skinning(render_device)),
324 (2, layout_entry::weights()),
326 (3, layout_entry::targets()),
327 (6, layout_entry::skinning(render_device)),
329 (7, layout_entry::weights()),
331 ),
332 ),
333 )
334 }
335
336 fn lightmapped_layout(
337 render_device: &RenderDevice,
338 render_adapter: &RenderAdapter,
339 ) -> BindGroupLayout {
340 if binding_arrays_are_usable(render_device, render_adapter) {
341 render_device.create_bind_group_layout(
342 "lightmapped_mesh_layout",
343 &BindGroupLayoutEntries::with_indices(
344 ShaderStages::VERTEX,
345 (
346 (0, layout_entry::model(render_device)),
347 (4, layout_entry::lightmaps_texture_view_array()),
348 (5, layout_entry::lightmaps_sampler_array()),
349 ),
350 ),
351 )
352 } else {
353 render_device.create_bind_group_layout(
354 "lightmapped_mesh_layout",
355 &BindGroupLayoutEntries::with_indices(
356 ShaderStages::VERTEX,
357 (
358 (0, layout_entry::model(render_device)),
359 (4, layout_entry::lightmaps_texture_view()),
360 (5, layout_entry::lightmaps_sampler()),
361 ),
362 ),
363 )
364 }
365 }
366
367 pub fn model_only(&self, render_device: &RenderDevice, model: &BindingResource) -> BindGroup {
370 render_device.create_bind_group(
371 "model_only_mesh_bind_group",
372 &self.model_only,
373 &[entry::model(0, model.clone())],
374 )
375 }
376
377 pub fn lightmapped(
378 &self,
379 render_device: &RenderDevice,
380 model: &BindingResource,
381 lightmap_slab: &LightmapSlab,
382 bindless_lightmaps: bool,
383 ) -> BindGroup {
384 if bindless_lightmaps {
385 let (texture_views, samplers) = lightmap_slab.build_binding_arrays();
386 render_device.create_bind_group(
387 "lightmapped_mesh_bind_group",
388 &self.lightmapped,
389 &[
390 entry::model(0, model.clone()),
391 entry::lightmaps_texture_view_array(4, &texture_views),
392 entry::lightmaps_sampler_array(5, &samplers),
393 ],
394 )
395 } else {
396 let (texture_view, sampler) = lightmap_slab.bindings_for_first_lightmap();
397 render_device.create_bind_group(
398 "lightmapped_mesh_bind_group",
399 &self.lightmapped,
400 &[
401 entry::model(0, model.clone()),
402 entry::lightmaps_texture_view(4, texture_view),
403 entry::lightmaps_sampler(5, sampler),
404 ],
405 )
406 }
407 }
408
409 pub fn skinned(
411 &self,
412 render_device: &RenderDevice,
413 model: &BindingResource,
414 current_skin: &Buffer,
415 ) -> BindGroup {
416 render_device.create_bind_group(
417 "skinned_mesh_bind_group",
418 &self.skinned,
419 &[
420 entry::model(0, model.clone()),
421 entry::skinning(render_device, 1, current_skin),
422 ],
423 )
424 }
425
426 pub fn skinned_motion(
434 &self,
435 render_device: &RenderDevice,
436 model: &BindingResource,
437 current_skin: &Buffer,
438 prev_skin: &Buffer,
439 ) -> BindGroup {
440 render_device.create_bind_group(
441 "skinned_motion_mesh_bind_group",
442 &self.skinned_motion,
443 &[
444 entry::model(0, model.clone()),
445 entry::skinning(render_device, 1, current_skin),
446 entry::skinning(render_device, 6, prev_skin),
447 ],
448 )
449 }
450
451 pub fn morphed(
453 &self,
454 render_device: &RenderDevice,
455 model: &BindingResource,
456 current_weights: &Buffer,
457 targets: &TextureView,
458 ) -> BindGroup {
459 render_device.create_bind_group(
460 "morphed_mesh_bind_group",
461 &self.morphed,
462 &[
463 entry::model(0, model.clone()),
464 entry::weights(2, current_weights),
465 entry::targets(3, targets),
466 ],
467 )
468 }
469
470 pub fn morphed_motion(
478 &self,
479 render_device: &RenderDevice,
480 model: &BindingResource,
481 current_weights: &Buffer,
482 targets: &TextureView,
483 prev_weights: &Buffer,
484 ) -> BindGroup {
485 render_device.create_bind_group(
486 "morphed_motion_mesh_bind_group",
487 &self.morphed_motion,
488 &[
489 entry::model(0, model.clone()),
490 entry::weights(2, current_weights),
491 entry::targets(3, targets),
492 entry::weights(7, prev_weights),
493 ],
494 )
495 }
496
497 pub fn morphed_skinned(
499 &self,
500 render_device: &RenderDevice,
501 model: &BindingResource,
502 current_skin: &Buffer,
503 current_weights: &Buffer,
504 targets: &TextureView,
505 ) -> BindGroup {
506 render_device.create_bind_group(
507 "morphed_skinned_mesh_bind_group",
508 &self.morphed_skinned,
509 &[
510 entry::model(0, model.clone()),
511 entry::skinning(render_device, 1, current_skin),
512 entry::weights(2, current_weights),
513 entry::targets(3, targets),
514 ],
515 )
516 }
517
518 pub fn morphed_skinned_motion(
526 &self,
527 render_device: &RenderDevice,
528 model: &BindingResource,
529 current_skin: &Buffer,
530 current_weights: &Buffer,
531 targets: &TextureView,
532 prev_skin: &Buffer,
533 prev_weights: &Buffer,
534 ) -> BindGroup {
535 render_device.create_bind_group(
536 "morphed_skinned_motion_mesh_bind_group",
537 &self.morphed_skinned_motion,
538 &[
539 entry::model(0, model.clone()),
540 entry::skinning(render_device, 1, current_skin),
541 entry::weights(2, current_weights),
542 entry::targets(3, targets),
543 entry::skinning(render_device, 6, prev_skin),
544 entry::weights(7, prev_weights),
545 ],
546 )
547 }
548}