1use bevy_math::Mat4;
4use bevy_mesh::morph::MAX_MORPH_WEIGHTS;
5use bevy_render::{
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(
129 binding: u32,
130 texture: &TextureView,
131 ) -> BindGroupEntry<'_> {
132 BindGroupEntry {
133 binding,
134 resource: BindingResource::TextureView(texture),
135 }
136 }
137 pub(super) fn lightmaps_sampler(binding: u32, sampler: &Sampler) -> BindGroupEntry<'_> {
138 BindGroupEntry {
139 binding,
140 resource: BindingResource::Sampler(sampler),
141 }
142 }
143 pub(super) fn lightmaps_texture_view_array<'a>(
144 binding: u32,
145 textures: &'a [&'a WgpuTextureView],
146 ) -> BindGroupEntry<'a> {
147 BindGroupEntry {
148 binding,
149 resource: BindingResource::TextureViewArray(textures),
150 }
151 }
152 pub(super) fn lightmaps_sampler_array<'a>(
153 binding: u32,
154 samplers: &'a [&'a WgpuSampler],
155 ) -> BindGroupEntry<'a> {
156 BindGroupEntry {
157 binding,
158 resource: BindingResource::SamplerArray(samplers),
159 }
160 }
161}
162
163#[derive(Clone)]
165pub struct MeshLayouts {
166 pub model_only: BindGroupLayout,
168
169 pub lightmapped: BindGroupLayout,
171
172 pub skinned: BindGroupLayout,
174
175 pub skinned_motion: BindGroupLayout,
178
179 pub morphed: BindGroupLayout,
183
184 pub morphed_motion: BindGroupLayout,
187
188 pub morphed_skinned: BindGroupLayout,
193
194 pub morphed_skinned_motion: BindGroupLayout,
198}
199
200impl MeshLayouts {
201 pub fn new(render_device: &RenderDevice, render_adapter: &RenderAdapter) -> Self {
205 MeshLayouts {
206 model_only: Self::model_only_layout(render_device),
207 lightmapped: Self::lightmapped_layout(render_device, render_adapter),
208 skinned: Self::skinned_layout(render_device),
209 skinned_motion: Self::skinned_motion_layout(render_device),
210 morphed: Self::morphed_layout(render_device),
211 morphed_motion: Self::morphed_motion_layout(render_device),
212 morphed_skinned: Self::morphed_skinned_layout(render_device),
213 morphed_skinned_motion: Self::morphed_skinned_motion_layout(render_device),
214 }
215 }
216
217 fn model_only_layout(render_device: &RenderDevice) -> BindGroupLayout {
220 render_device.create_bind_group_layout(
221 "mesh_layout",
222 &BindGroupLayoutEntries::single(
223 ShaderStages::empty(),
224 layout_entry::model(render_device),
225 ),
226 )
227 }
228
229 fn skinned_layout(render_device: &RenderDevice) -> BindGroupLayout {
231 render_device.create_bind_group_layout(
232 "skinned_mesh_layout",
233 &BindGroupLayoutEntries::with_indices(
234 ShaderStages::VERTEX,
235 (
236 (0, layout_entry::model(render_device)),
237 (1, layout_entry::skinning(render_device)),
239 ),
240 ),
241 )
242 }
243
244 fn skinned_motion_layout(render_device: &RenderDevice) -> BindGroupLayout {
247 render_device.create_bind_group_layout(
248 "skinned_motion_mesh_layout",
249 &BindGroupLayoutEntries::with_indices(
250 ShaderStages::VERTEX,
251 (
252 (0, layout_entry::model(render_device)),
253 (1, layout_entry::skinning(render_device)),
255 (6, layout_entry::skinning(render_device)),
257 ),
258 ),
259 )
260 }
261
262 fn morphed_layout(render_device: &RenderDevice) -> BindGroupLayout {
264 render_device.create_bind_group_layout(
265 "morphed_mesh_layout",
266 &BindGroupLayoutEntries::with_indices(
267 ShaderStages::VERTEX,
268 (
269 (0, layout_entry::model(render_device)),
270 (2, layout_entry::weights()),
272 (3, layout_entry::targets()),
273 ),
274 ),
275 )
276 }
277
278 fn morphed_motion_layout(render_device: &RenderDevice) -> BindGroupLayout {
281 render_device.create_bind_group_layout(
282 "morphed_mesh_layout",
283 &BindGroupLayoutEntries::with_indices(
284 ShaderStages::VERTEX,
285 (
286 (0, layout_entry::model(render_device)),
287 (2, layout_entry::weights()),
289 (3, layout_entry::targets()),
290 (7, layout_entry::weights()),
292 ),
293 ),
294 )
295 }
296
297 fn morphed_skinned_layout(render_device: &RenderDevice) -> BindGroupLayout {
300 render_device.create_bind_group_layout(
301 "morphed_skinned_mesh_layout",
302 &BindGroupLayoutEntries::with_indices(
303 ShaderStages::VERTEX,
304 (
305 (0, layout_entry::model(render_device)),
306 (1, layout_entry::skinning(render_device)),
308 (2, layout_entry::weights()),
310 (3, layout_entry::targets()),
311 ),
312 ),
313 )
314 }
315
316 fn morphed_skinned_motion_layout(render_device: &RenderDevice) -> BindGroupLayout {
319 render_device.create_bind_group_layout(
320 "morphed_skinned_motion_mesh_layout",
321 &BindGroupLayoutEntries::with_indices(
322 ShaderStages::VERTEX,
323 (
324 (0, layout_entry::model(render_device)),
325 (1, layout_entry::skinning(render_device)),
327 (2, layout_entry::weights()),
329 (3, layout_entry::targets()),
330 (6, layout_entry::skinning(render_device)),
332 (7, layout_entry::weights()),
334 ),
335 ),
336 )
337 }
338
339 fn lightmapped_layout(
340 render_device: &RenderDevice,
341 render_adapter: &RenderAdapter,
342 ) -> BindGroupLayout {
343 if binding_arrays_are_usable(render_device, render_adapter) {
344 render_device.create_bind_group_layout(
345 "lightmapped_mesh_layout",
346 &BindGroupLayoutEntries::with_indices(
347 ShaderStages::VERTEX,
348 (
349 (0, layout_entry::model(render_device)),
350 (4, layout_entry::lightmaps_texture_view_array()),
351 (5, layout_entry::lightmaps_sampler_array()),
352 ),
353 ),
354 )
355 } else {
356 render_device.create_bind_group_layout(
357 "lightmapped_mesh_layout",
358 &BindGroupLayoutEntries::with_indices(
359 ShaderStages::VERTEX,
360 (
361 (0, layout_entry::model(render_device)),
362 (4, layout_entry::lightmaps_texture_view()),
363 (5, layout_entry::lightmaps_sampler()),
364 ),
365 ),
366 )
367 }
368 }
369
370 pub fn model_only(&self, render_device: &RenderDevice, model: &BindingResource) -> BindGroup {
373 render_device.create_bind_group(
374 "model_only_mesh_bind_group",
375 &self.model_only,
376 &[entry::model(0, model.clone())],
377 )
378 }
379
380 pub fn lightmapped(
381 &self,
382 render_device: &RenderDevice,
383 model: &BindingResource,
384 lightmap_slab: &LightmapSlab,
385 bindless_lightmaps: bool,
386 ) -> BindGroup {
387 if bindless_lightmaps {
388 let (texture_views, samplers) = lightmap_slab.build_binding_arrays();
389 render_device.create_bind_group(
390 "lightmapped_mesh_bind_group",
391 &self.lightmapped,
392 &[
393 entry::model(0, model.clone()),
394 entry::lightmaps_texture_view_array(4, &texture_views),
395 entry::lightmaps_sampler_array(5, &samplers),
396 ],
397 )
398 } else {
399 let (texture_view, sampler) = lightmap_slab.bindings_for_first_lightmap();
400 render_device.create_bind_group(
401 "lightmapped_mesh_bind_group",
402 &self.lightmapped,
403 &[
404 entry::model(0, model.clone()),
405 entry::lightmaps_texture_view(4, texture_view),
406 entry::lightmaps_sampler(5, sampler),
407 ],
408 )
409 }
410 }
411
412 pub fn skinned(
414 &self,
415 render_device: &RenderDevice,
416 model: &BindingResource,
417 current_skin: &Buffer,
418 ) -> BindGroup {
419 render_device.create_bind_group(
420 "skinned_mesh_bind_group",
421 &self.skinned,
422 &[
423 entry::model(0, model.clone()),
424 entry::skinning(render_device, 1, current_skin),
425 ],
426 )
427 }
428
429 pub fn skinned_motion(
437 &self,
438 render_device: &RenderDevice,
439 model: &BindingResource,
440 current_skin: &Buffer,
441 prev_skin: &Buffer,
442 ) -> BindGroup {
443 render_device.create_bind_group(
444 "skinned_motion_mesh_bind_group",
445 &self.skinned_motion,
446 &[
447 entry::model(0, model.clone()),
448 entry::skinning(render_device, 1, current_skin),
449 entry::skinning(render_device, 6, prev_skin),
450 ],
451 )
452 }
453
454 pub fn morphed(
456 &self,
457 render_device: &RenderDevice,
458 model: &BindingResource,
459 current_weights: &Buffer,
460 targets: &TextureView,
461 ) -> BindGroup {
462 render_device.create_bind_group(
463 "morphed_mesh_bind_group",
464 &self.morphed,
465 &[
466 entry::model(0, model.clone()),
467 entry::weights(2, current_weights),
468 entry::targets(3, targets),
469 ],
470 )
471 }
472
473 pub fn morphed_motion(
481 &self,
482 render_device: &RenderDevice,
483 model: &BindingResource,
484 current_weights: &Buffer,
485 targets: &TextureView,
486 prev_weights: &Buffer,
487 ) -> BindGroup {
488 render_device.create_bind_group(
489 "morphed_motion_mesh_bind_group",
490 &self.morphed_motion,
491 &[
492 entry::model(0, model.clone()),
493 entry::weights(2, current_weights),
494 entry::targets(3, targets),
495 entry::weights(7, prev_weights),
496 ],
497 )
498 }
499
500 pub fn morphed_skinned(
502 &self,
503 render_device: &RenderDevice,
504 model: &BindingResource,
505 current_skin: &Buffer,
506 current_weights: &Buffer,
507 targets: &TextureView,
508 ) -> BindGroup {
509 render_device.create_bind_group(
510 "morphed_skinned_mesh_bind_group",
511 &self.morphed_skinned,
512 &[
513 entry::model(0, model.clone()),
514 entry::skinning(render_device, 1, current_skin),
515 entry::weights(2, current_weights),
516 entry::targets(3, targets),
517 ],
518 )
519 }
520
521 pub fn morphed_skinned_motion(
529 &self,
530 render_device: &RenderDevice,
531 model: &BindingResource,
532 current_skin: &Buffer,
533 current_weights: &Buffer,
534 targets: &TextureView,
535 prev_skin: &Buffer,
536 prev_weights: &Buffer,
537 ) -> BindGroup {
538 render_device.create_bind_group(
539 "morphed_skinned_motion_mesh_bind_group",
540 &self.morphed_skinned_motion,
541 &[
542 entry::model(0, model.clone()),
543 entry::skinning(render_device, 1, current_skin),
544 entry::weights(2, current_weights),
545 entry::targets(3, targets),
546 entry::skinning(render_device, 6, prev_skin),
547 entry::weights(7, prev_weights),
548 ],
549 )
550 }
551}