1use crate::contact_shadows::ViewContactShadowsUniformOffset;
2use crate::{
3 material_bind_groups::MaterialBindGroupSlot, resources::write_atmosphere_buffer,
4 skin::skin_uniforms_from_world,
5};
6use alloc::sync::Arc;
7use bevy_asset::uuid::Uuid;
8use bevy_asset::{embedded_asset, load_embedded_asset, AssetId, AssetIndex, AssetServer};
9use bevy_camera::visibility::NoCpuCulling;
10use bevy_camera::{
11 primitives::Aabb,
12 visibility::{NoFrustumCulling, RenderLayers, ViewVisibility, VisibilityRange},
13 Camera, Projection,
14};
15use bevy_core_pipeline::{
16 core_3d::{AlphaMask3d, Opaque3d, Transparent3d, CORE_3D_DEPTH_FORMAT},
17 deferred::{AlphaMask3dDeferred, Opaque3dDeferred},
18 oit::prepare_oit_buffers,
19 prepass::MotionVectorPrepass,
20};
21use bevy_derive::{Deref, DerefMut};
22use bevy_diagnostic::FrameCount;
23use bevy_ecs::entity::EntityHash;
24use bevy_ecs::{
25 entity::EntityHashSet,
26 prelude::*,
27 query::{QueryData, ROQueryItem},
28 relationship::RelationshipSourceCollection,
29 system::{lifetimeless::*, SystemParamItem},
30};
31use bevy_image::{ImageSampler, TextureFormatPixelInfo};
32use bevy_light::{
33 EnvironmentMapLight, IrradianceVolume, NotShadowCaster, NotShadowReceiver,
34 ShadowFilteringMethod, TransmittedShadowReceiver,
35};
36use bevy_math::{Affine3, Affine3Ext, Rect, UVec2, Vec3, Vec4};
37use bevy_mesh::{
38 skinning::SkinnedMesh, BaseMeshPipelineKey, Mesh, Mesh3d, MeshTag, MeshVertexBufferLayoutRef,
39 VertexAttributeDescriptor,
40};
41use bevy_platform::collections::{hash_map::Entry, HashMap};
42use bevy_render::batching::gpu_preprocessing::PreviousInstanceInputUniformBuffer;
43use bevy_render::impl_atomic_pod;
44use bevy_render::mesh::allocator::{MeshSlabId, MeshSlabs};
45use bevy_render::mesh::morph::{
46 MorphTargetImage, MorphTargetsResource, RenderMorphTargetAllocator,
47};
48use bevy_render::{
49 batching::{
50 gpu_preprocessing::{
51 self, GpuPreprocessingSupport, IndirectBatchSet, IndirectParametersBuffers,
52 IndirectParametersCpuMetadata, IndirectParametersIndexed, IndirectParametersNonIndexed,
53 InstanceInputUniformBuffer, UntypedPhaseIndirectParametersBuffers,
54 },
55 no_gpu_preprocessing, GetBatchData, GetFullBatchData, NoAutomaticBatching,
56 },
57 mesh::{allocator::MeshAllocator, RenderMesh, RenderMeshBufferInfo},
58 render_asset::RenderAssets,
59 render_phase::{
60 BinnedRenderPhasePlugin, InputUniformIndex, PhaseItem, PhaseItemExtraIndex, RenderCommand,
61 RenderCommandResult, SortedRenderPhasePlugin, TrackedRenderPass,
62 },
63 render_resource::*,
64 renderer::{RenderAdapter, RenderDevice, RenderQueue},
65 sync_world::MainEntityHashSet,
66 texture::{DefaultImageSampler, GpuImage},
67 view::{self, NoIndirectDrawing, RenderVisibilityRanges, RetainedViewEntity},
68 Extract,
69};
70use bevy_shader::{load_shader_library, Shader, ShaderDefVal, ShaderSettings};
71use bevy_transform::components::GlobalTransform;
72use bevy_utils::{default, Parallel, TypeIdMap};
73use core::any::TypeId;
74use core::iter;
75use core::mem::{offset_of, size_of};
76use core::sync::atomic::{AtomicU64, Ordering};
77use indexmap::IndexSet;
78use material_bind_groups::MaterialBindingId;
79use static_assertions::const_assert_eq;
80use std::sync::mpsc;
81#[cfg(feature = "trace")]
82use tracing::info_span;
83use tracing::{error, warn};
84
85use self::irradiance_volume::IRRADIANCE_VOLUMES_ARE_USABLE;
86use crate::{
87 render::{
88 morph::{
89 extract_morphs, no_automatic_morph_batching, write_morph_buffers, MorphIndices,
90 MorphUniforms,
91 },
92 skin::no_automatic_skin_batching,
93 },
94 *,
95};
96use bevy_core_pipeline::oit::OrderIndependentTransparencySettings;
97use bevy_core_pipeline::prepass::{DeferredPrepass, DepthPrepass, NormalPrepass};
98use bevy_core_pipeline::tonemapping::{DebandDither, Tonemapping};
99use bevy_render::camera::{DirtySpecializations, ExtractedCamera, TemporalJitter};
100use bevy_render::prelude::Msaa;
101use bevy_render::sync_world::{MainEntity, MainEntityHashMap};
102use bevy_render::view::{
103 texture_format_from_code, texture_format_to_code, ExtractedView,
104 RenderShadowMapVisibleEntities, RenderVisibleEntities,
105};
106use bevy_render::RenderSystems::PrepareAssets;
107use bevy_tasks::ComputeTaskPool;
108
109use bytemuck::{Pod, Zeroable};
110use nonmax::{NonMaxU16, NonMaxU32};
111
112pub struct MeshRenderPlugin {
114 pub use_gpu_instance_buffer_builder: bool,
119 pub debug_flags: RenderDebugFlags,
121}
122
123impl MeshRenderPlugin {
124 pub fn new(debug_flags: RenderDebugFlags) -> MeshRenderPlugin {
126 MeshRenderPlugin {
127 use_gpu_instance_buffer_builder: false,
128 debug_flags,
129 }
130 }
131}
132
133#[cfg(debug_assertions)]
142pub const MESH_PIPELINE_VIEW_LAYOUT_SAFE_MAX_TEXTURES: usize = 10;
143
144#[derive(#[automatically_derived]
impl ::core::fmt::Debug for MeshPipelineSystems {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f, "MeshPipelineSystems")
}
}Debug, #[automatically_derived]
impl ::core::hash::Hash for MeshPipelineSystems {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {}
}Hash, #[automatically_derived]
impl ::core::cmp::PartialEq for MeshPipelineSystems {
#[inline]
fn eq(&self, other: &MeshPipelineSystems) -> bool { true }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for MeshPipelineSystems {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {}
}Eq, #[automatically_derived]
impl ::core::clone::Clone for MeshPipelineSystems {
#[inline]
fn clone(&self) -> MeshPipelineSystems { MeshPipelineSystems }
}Clone, const _: () =
{
extern crate alloc;
impl bevy_ecs::schedule::SystemSet for MeshPipelineSystems where
Self: 'static + ::core::marker::Send + ::core::marker::Sync +
::core::clone::Clone + ::core::cmp::Eq + ::core::fmt::Debug +
::core::hash::Hash {
fn dyn_clone(&self)
-> alloc::boxed::Box<dyn bevy_ecs::schedule::SystemSet> {
alloc::boxed::Box::new(::core::clone::Clone::clone(self))
}
}
};SystemSet)]
145pub struct MeshPipelineSystems;
146
147impl Plugin for MeshRenderPlugin {
148 fn build(&self, app: &mut App) {
149 {
{
let mut embedded =
app.world_mut().resource_mut::<::bevy_asset::io::embedded::EmbeddedAssetRegistry>();
let path =
{
let crate_name =
"bevy_pbr::render::mesh".split(':').next().unwrap();
::bevy_asset::io::embedded::_embedded_asset_path(crate_name,
"src".as_ref(), "src/render/mesh.rs".as_ref(),
"forward_io.wgsl".as_ref())
};
let watched_path =
::bevy_asset::io::embedded::watched_path("src/render/mesh.rs",
"forward_io.wgsl");
embedded.insert_asset(watched_path, &path,
b"#define_import_path bevy_pbr::forward_io\n\nstruct Vertex {\n @builtin(instance_index) instance_index: u32,\n#ifdef VERTEX_POSITIONS\n @location(0) position: vec3<f32>,\n#endif\n#ifdef VERTEX_NORMALS\n @location(1) normal: vec3<f32>,\n#endif\n#ifdef VERTEX_UVS_A\n @location(2) uv: vec2<f32>,\n#endif\n#ifdef VERTEX_UVS_B\n @location(3) uv_b: vec2<f32>,\n#endif\n#ifdef VERTEX_TANGENTS\n @location(4) tangent: vec4<f32>,\n#endif\n#ifdef VERTEX_COLORS\n @location(5) color: vec4<f32>,\n#endif\n#ifdef SKINNED\n @location(6) joint_indices: vec4<u32>,\n @location(7) joint_weights: vec4<f32>,\n#endif\n#ifdef MORPH_TARGETS\n @builtin(vertex_index) index: u32,\n#endif\n};\n\nstruct VertexOutput {\n // This is `clip position` when the struct is used as a vertex stage output\n // and `frag coord` when used as a fragment stage input\n @builtin(position) position: vec4<f32>,\n @location(0) world_position: vec4<f32>,\n @location(1) world_normal: vec3<f32>,\n#ifdef VERTEX_UVS_A\n @location(2) uv: vec2<f32>,\n#endif\n#ifdef VERTEX_UVS_B\n @location(3) uv_b: vec2<f32>,\n#endif\n#ifdef VERTEX_TANGENTS\n @location(4) world_tangent: vec4<f32>,\n#endif\n#ifdef VERTEX_COLORS\n @location(5) color: vec4<f32>,\n#endif\n#ifdef VERTEX_OUTPUT_INSTANCE_INDEX\n @location(6) @interpolate(flat) instance_index: u32,\n#endif\n#ifdef VISIBILITY_RANGE_DITHER\n @location(7) @interpolate(flat) visibility_range_dither: i32,\n#endif\n}\n\nstruct FragmentOutput {\n @location(0) color: vec4<f32>,\n}\n");
}
};
let handle:
::bevy_shader::_macro::bevy_asset::prelude::Handle<::bevy_shader::prelude::Shader> =
{
let (path, asset_server) =
{
let path =
{
{
let crate_name =
"bevy_pbr::render::mesh".split(':').next().unwrap();
::bevy_asset::io::embedded::_embedded_asset_path(crate_name,
"src".as_ref(), "src/render/mesh.rs".as_ref(),
"forward_io.wgsl".as_ref())
}
};
let path =
::bevy_asset::AssetPath::from_path_buf(path).with_source("embedded");
let asset_server =
::bevy_asset::io::embedded::GetAssetServer::get_asset_server(app);
(path, asset_server)
};
asset_server.load(path)
};
core::mem::forget(handle);load_shader_library!(app, "forward_io.wgsl");
150 {
{
let mut embedded =
app.world_mut().resource_mut::<::bevy_asset::io::embedded::EmbeddedAssetRegistry>();
let path =
{
let crate_name =
"bevy_pbr::render::mesh".split(':').next().unwrap();
::bevy_asset::io::embedded::_embedded_asset_path(crate_name,
"src".as_ref(), "src/render/mesh.rs".as_ref(),
"mesh_view_types.wgsl".as_ref())
};
let watched_path =
::bevy_asset::io::embedded::watched_path("src/render/mesh.rs",
"mesh_view_types.wgsl");
embedded.insert_asset(watched_path, &path,
b"#define_import_path bevy_pbr::mesh_view_types\n\nstruct ClusteredLight {\n // For point lights: the lower-right 2x2 values of the projection matrix [2][2] [2][3] [3][2] [3][3]\n // For spot lights: the direction (x,z), spot_scale and spot_offset\n light_custom_data: vec4<f32>,\n color_inverse_square_range: vec4<f32>,\n position_radius: vec4<f32>,\n // \'flags\' is a bit field indicating various options. u32 is 32 bits so we have up to 32 options.\n flags: u32,\n shadow_depth_bias: f32,\n shadow_normal_bias: f32,\n spot_light_tan_angle: f32,\n soft_shadow_size: f32,\n shadow_map_near_z: f32,\n decal_index: u32,\n range: f32,\n};\n\nconst POINT_LIGHT_FLAGS_SHADOWS_ENABLED_BIT: u32 = 1u << 0u;\nconst POINT_LIGHT_FLAGS_SPOT_LIGHT_Y_NEGATIVE: u32 = 1u << 1u;\nconst POINT_LIGHT_FLAGS_VOLUMETRIC_BIT: u32 = 1u << 2u;\nconst POINT_LIGHT_FLAGS_AFFECTS_LIGHTMAPPED_MESH_DIFFUSE_BIT: u32 = 1u << 3u;\nconst POINT_LIGHT_FLAGS_CONTACT_SHADOWS_ENABLED_BIT: u32 = 1u << 4u;\nconst POINT_LIGHT_FLAGS_SPOT_LIGHT_BIT: u32 = 1u << 5u;\n\nstruct DirectionalCascade {\n clip_from_world: mat4x4<f32>,\n texel_size: f32,\n far_bound: f32,\n}\n\nstruct DirectionalLight {\n cascades: array<DirectionalCascade, #{MAX_CASCADES_PER_LIGHT}>,\n color: vec4<f32>,\n direction_to_light: vec3<f32>,\n // \'flags\' is a bit field indicating various options. u32 is 32 bits so we have up to 32 options.\n flags: u32,\n soft_shadow_size: f32,\n shadow_depth_bias: f32,\n shadow_normal_bias: f32,\n num_cascades: u32,\n cascades_overlap_proportion: f32,\n depth_texture_base_index: u32,\n decal_index: u32,\n sun_disk_angular_size: f32,\n sun_disk_intensity: f32,\n};\n\nconst DIRECTIONAL_LIGHT_FLAGS_SHADOWS_ENABLED_BIT: u32 = 1u << 0u;\nconst DIRECTIONAL_LIGHT_FLAGS_VOLUMETRIC_BIT: u32 = 1u << 1u;\nconst DIRECTIONAL_LIGHT_FLAGS_AFFECTS_LIGHTMAPPED_MESH_DIFFUSE_BIT: u32 = 1u << 2u;\nconst DIRECTIONAL_LIGHT_FLAGS_CONTACT_SHADOWS_ENABLED_BIT: u32 = 1u << 3u;\n\nstruct RectLight {\n color: vec4<f32>,\n position: vec3<f32>,\n width: f32,\n right: vec3<f32>,\n height: f32,\n up: vec3<f32>,\n range: f32,\n};\n\nstruct Lights {\n // NOTE: this array size must be kept in sync with the constants defined in bevy_pbr/src/render/light.rs\n directional_lights: array<DirectionalLight, #{MAX_DIRECTIONAL_LIGHTS}u>,\n ambient_color: vec4<f32>,\n // x/y/z dimensions and n_clusters in w\n cluster_dimensions: vec4<u32>,\n // xy are vec2<f32>(cluster_dimensions.xy) / vec2<f32>(view.width, view.height)\n //\n // For perspective projections:\n // z is (cluster_dimensions.z - 1) / log(far / near)\n // w is (cluster_dimensions.z - 1) * log(near) / log(far / near)\n //\n // For orthographic projections:\n // NOTE: near and far are +ve but -z is infront of the camera\n // z is -near\n // w is cluster_dimensions.z / (-far - -near)\n cluster_factors: vec4<f32>,\n n_directional_lights: u32,\n spot_light_shadowmap_offset: i32,\n ambient_light_affects_lightmapped_meshes: u32,\n n_rect_lights: u32,\n rect_lights: array<RectLight, #{MAX_RECT_LIGHTS}u>,\n};\n\nstruct Fog {\n base_color: vec4<f32>,\n directional_light_color: vec4<f32>,\n // `be` and `bi` are allocated differently depending on the fog mode\n //\n // For Linear Fog:\n // be.x = start, be.y = end\n // For Exponential and ExponentialSquared Fog:\n // be.x = density\n // For Atmospheric Fog:\n // be = per-channel extinction density\n // bi = per-channel inscattering density\n be: vec3<f32>,\n directional_light_exponent: f32,\n bi: vec3<f32>,\n mode: u32,\n}\n\n// Important: These must be kept in sync with `fog.rs`\nconst FOG_MODE_OFF: u32 = 0u;\nconst FOG_MODE_LINEAR: u32 = 1u;\nconst FOG_MODE_EXPONENTIAL: u32 = 2u;\nconst FOG_MODE_EXPONENTIAL_SQUARED: u32 = 3u;\nconst FOG_MODE_ATMOSPHERIC: u32 = 4u;\n\n#if AVAILABLE_STORAGE_BUFFER_BINDINGS >= 3\nstruct ClusteredLights {\n data: array<ClusteredLight>,\n};\nstruct ClusterableObjectIndexLists {\n data: array<u32>,\n};\nstruct ClusterOffsetsAndCounts {\n data: array<array<vec4<u32>, 2>>,\n};\n#else\nstruct ClusteredLights {\n data: array<ClusteredLight, 204u>,\n};\nstruct ClusterableObjectIndexLists {\n // each u32 contains 4 u8 indices into the ClusterableObjects array\n data: array<vec4<u32>, 1024u>,\n};\nstruct ClusterOffsetsAndCounts {\n // each u32 contains a 24-bit index into ClusterableObjectIndexLists in the high 24 bits\n // and an 8-bit count of the number of lights in the low 8 bits\n data: array<vec4<u32>, 1024u>,\n};\n#endif\n\n// Whether this light probe contributes diffuse light to lightmapped meshes.\nconst LIGHT_PROBE_FLAG_AFFECTS_LIGHTMAPPED_MESH_DIFFUSE: u32 = 1;\n// Whether this light probe has parallax correction enabled.\nconst LIGHT_PROBE_FLAG_PARALLAX_CORRECT: u32 = 2;\n\nstruct LightProbe {\n // This is stored as the transpose in order to save space in this structure.\n // It\'ll be transposed in the `environment_map_light` function.\n light_from_world_transposed: mat3x4<f32>,\n // The falloff region, specified as a fraction of the light probe\'s\n // bounding box.\n falloff: vec3<f32>,\n bounding_sphere_radius: f32,\n // The boundaries of the simulated space used for parallax correction,\n // specified as *half* extents in light probe space.\n parallax_correction_bounds: vec3<f32>,\n intensity: f32,\n world_position: vec3<f32>,\n cubemap_index: i32,\n // Various flags that apply to this light probe.\n flags: u32,\n};\n\nstruct LightProbes {\n // This must match `MAX_VIEW_LIGHT_PROBES` on the Rust side.\n reflection_probes: array<LightProbe, 8u>,\n irradiance_volumes: array<LightProbe, 8u>,\n reflection_probe_count: i32,\n irradiance_volume_count: i32,\n // The index of the view environment map cubemap binding, or -1 if there\'s\n // no such cubemap.\n view_cubemap_index: i32,\n // The smallest valid mipmap level for the specular environment cubemap\n // associated with the view.\n smallest_specular_mip_level_for_view: u32,\n view_rotation: vec4<f32>,\n // The intensity of the environment map associated with the view.\n intensity_for_view: f32,\n // Whether the environment map attached to the view affects the diffuse\n // lighting for lightmapped meshes.\n view_environment_map_affects_lightmapped_mesh_diffuse: u32,\n};\n\n// Settings for screen space reflections.\n//\n// For more information on these settings, see the documentation for\n// `bevy_pbr::ssr::ScreenSpaceReflections`.\nstruct ScreenSpaceReflectionsSettings {\n min_perceptual_roughness: f32,\n min_perceptual_roughness_fully_active: f32,\n max_perceptual_roughness_starts_to_fade: f32,\n max_perceptual_roughness: f32,\n edge_fadeout_fully_active: f32,\n edge_fadeout_no_longer_active: f32,\n thickness: f32,\n linear_steps: u32,\n linear_march_exponent: f32,\n bisection_steps: u32,\n use_secant: u32,\n};\n\n// See the `ContactShadows` rust struct.\nstruct ContactShadowsSettings {\n linear_steps: u32,\n thickness: f32,\n length: f32,\n#ifdef SIXTEEN_BYTE_ALIGNMENT\n _padding: f32,\n#endif\n};\n\nstruct EnvironmentMapUniform {\n // Transformation matrix for the environment cubemaps in world space.\n transform: mat4x4<f32>,\n};\n\n// Shader version of the order independent transparency settings component.\nstruct OrderIndependentTransparencySettings {\n sorted_fragment_max_count: u32,\n fragments_per_pixel_average: f32,\n alpha_threshold: f32,\n};\n\nstruct OitFragmentNode {\n color: u32,\n depth_alpha: u32,\n next: u32,\n};\n\nstruct ClusteredDecal {\n local_from_world: mat4x4<f32>,\n base_color_texture_index: i32,\n normal_map_texture_index: i32,\n metallic_roughness_texture_index: i32,\n emissive_texture_index: i32,\n world_position: vec3<f32>,\n bounding_sphere_radius: f32,\n tag: u32,\n pad_a: u32,\n pad_b: u32,\n pad_c: u32,\n}\n\nstruct ClusteredDecals {\n decals: array<ClusteredDecal>,\n}\n");
}
};
let handle:
::bevy_shader::_macro::bevy_asset::prelude::Handle<::bevy_shader::prelude::Shader> =
{
let (path, asset_server) =
{
let path =
{
{
let crate_name =
"bevy_pbr::render::mesh".split(':').next().unwrap();
::bevy_asset::io::embedded::_embedded_asset_path(crate_name,
"src".as_ref(), "src/render/mesh.rs".as_ref(),
"mesh_view_types.wgsl".as_ref())
}
};
let path =
::bevy_asset::AssetPath::from_path_buf(path).with_source("embedded");
let asset_server =
::bevy_asset::io::embedded::GetAssetServer::get_asset_server(app);
(path, asset_server)
};
asset_server.load_builder().with_settings(|settings|
*settings =
ShaderSettings {
shader_defs: ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[ShaderDefVal::UInt("MAX_DIRECTIONAL_LIGHTS".into(),
MAX_DIRECTIONAL_LIGHTS as u32),
ShaderDefVal::UInt("MAX_CASCADES_PER_LIGHT".into(),
MAX_CASCADES_PER_LIGHT as u32),
ShaderDefVal::UInt("MAX_RECT_LIGHTS".into(),
MAX_RECT_LIGHTS as u32)])),
}).load(path)
};
core::mem::forget(handle);load_shader_library!(app, "mesh_view_types.wgsl", |settings| *settings =
151 ShaderSettings {
152 shader_defs: vec![
153 ShaderDefVal::UInt(
154 "MAX_DIRECTIONAL_LIGHTS".into(),
155 MAX_DIRECTIONAL_LIGHTS as u32
156 ),
157 ShaderDefVal::UInt(
158 "MAX_CASCADES_PER_LIGHT".into(),
159 MAX_CASCADES_PER_LIGHT as u32,
160 ),
161 ShaderDefVal::UInt("MAX_RECT_LIGHTS".into(), MAX_RECT_LIGHTS as u32,),
162 ]
163 });
164 {
{
let mut embedded =
app.world_mut().resource_mut::<::bevy_asset::io::embedded::EmbeddedAssetRegistry>();
let path =
{
let crate_name =
"bevy_pbr::render::mesh".split(':').next().unwrap();
::bevy_asset::io::embedded::_embedded_asset_path(crate_name,
"src".as_ref(), "src/render/mesh.rs".as_ref(),
"mesh_view_bindings.wgsl".as_ref())
};
let watched_path =
::bevy_asset::io::embedded::watched_path("src/render/mesh.rs",
"mesh_view_bindings.wgsl");
embedded.insert_asset(watched_path, &path,
b"#define_import_path bevy_pbr::mesh_view_bindings\n\n#import bevy_pbr::mesh_view_types as types\n#import bevy_pbr::atmosphere::types as atmosphere_types\n#import bevy_render::{\n view::View,\n globals::Globals,\n}\n\n@group(0) @binding(0) var<uniform> view: View;\n@group(0) @binding(1) var<uniform> lights: types::Lights;\n#ifdef NO_CUBE_ARRAY_TEXTURES_SUPPORT\n@group(0) @binding(2) var point_shadow_textures: texture_depth_cube;\n#else\n@group(0) @binding(2) var point_shadow_textures: texture_depth_cube_array;\n#endif\n@group(0) @binding(3) var point_shadow_textures_comparison_sampler: sampler_comparison;\n#ifdef PCSS_SAMPLERS_AVAILABLE\n@group(0) @binding(4) var point_shadow_textures_linear_sampler: sampler;\n#endif // PCSS_SAMPLERS_AVAILABLE\n#ifdef NO_ARRAY_TEXTURES_SUPPORT\n@group(0) @binding(5) var directional_shadow_textures: texture_depth_2d;\n#else\n@group(0) @binding(5) var directional_shadow_textures: texture_depth_2d_array;\n#endif\n@group(0) @binding(6) var directional_shadow_textures_comparison_sampler: sampler_comparison;\n#ifdef PCSS_SAMPLERS_AVAILABLE\n@group(0) @binding(7) var directional_shadow_textures_linear_sampler: sampler;\n#endif // PCSS_SAMPLERS_AVAILABLE\n\n#if AVAILABLE_STORAGE_BUFFER_BINDINGS >= 3\n@group(0) @binding(8) var<storage> clustered_lights: types::ClusteredLights;\n@group(0) @binding(9) var<storage> clusterable_object_index_lists: types::ClusterableObjectIndexLists;\n@group(0) @binding(10) var<storage> cluster_offsets_and_counts: types::ClusterOffsetsAndCounts;\n#else\n@group(0) @binding(8) var<uniform> clustered_lights: types::ClusteredLights;\n@group(0) @binding(9) var<uniform> clusterable_object_index_lists: types::ClusterableObjectIndexLists;\n@group(0) @binding(10) var<uniform> cluster_offsets_and_counts: types::ClusterOffsetsAndCounts;\n#endif\n\n@group(0) @binding(11) var<uniform> globals: Globals;\n@group(0) @binding(12) var<uniform> light_probes: types::LightProbes;\n\n#ifdef DISTANCE_FOG\n@group(0) @binding(13) var<uniform> fog: types::Fog;\n#endif\n\nconst VISIBILITY_RANGE_UNIFORM_BUFFER_SIZE: u32 = 64u;\n#if AVAILABLE_STORAGE_BUFFER_BINDINGS >= 6\n@group(0) @binding(14) var<storage> visibility_ranges: array<vec4<f32>>;\n#else\n@group(0) @binding(14) var<uniform> visibility_ranges: array<vec4<f32>, VISIBILITY_RANGE_UNIFORM_BUFFER_SIZE>;\n#endif\n\n#ifdef SCREEN_SPACE_REFLECTIONS\n@group(0) @binding(15) var<uniform> ssr_settings: types::ScreenSpaceReflectionsSettings;\n#endif\n\n#ifdef CONTACT_SHADOWS\n@group(0) @binding(16) var<uniform> contact_shadows_settings: types::ContactShadowsSettings;\n#endif\n\n#ifdef SCREEN_SPACE_AMBIENT_OCCLUSION\n@group(0) @binding(17) var screen_space_ambient_occlusion_texture: texture_2d<f32>;\n#endif\n\n#ifdef TONEMAP_IN_SHADER\n// NB: If you change these, make sure to update `tonemapping_shared.wgsl` too.\n@group(0) @binding(18) var dt_lut_texture: texture_3d<f32>;\n@group(0) @binding(19) var dt_lut_sampler: sampler;\n#endif\n\n#ifdef MULTISAMPLED\n#ifdef DEPTH_PREPASS\n@group(0) @binding(20) var depth_prepass_texture: texture_depth_multisampled_2d;\n#endif // DEPTH_PREPASS\n#ifdef NORMAL_PREPASS\n@group(0) @binding(21) var normal_prepass_texture: texture_multisampled_2d<f32>;\n#endif // NORMAL_PREPASS\n#ifdef MOTION_VECTOR_PREPASS\n@group(0) @binding(22) var motion_vector_prepass_texture: texture_multisampled_2d<f32>;\n#endif // MOTION_VECTOR_PREPASS\n\n#else // MULTISAMPLED\n\n#ifdef DEPTH_PREPASS\n@group(0) @binding(20) var depth_prepass_texture: texture_depth_2d;\n#endif // DEPTH_PREPASS\n#ifdef NORMAL_PREPASS\n@group(0) @binding(21) var normal_prepass_texture: texture_2d<f32>;\n#endif // NORMAL_PREPASS\n#ifdef MOTION_VECTOR_PREPASS\n@group(0) @binding(22) var motion_vector_prepass_texture: texture_2d<f32>;\n#endif // MOTION_VECTOR_PREPASS\n\n#endif // MULTISAMPLED\n\n#ifdef DEFERRED_PREPASS\n@group(0) @binding(23) var deferred_prepass_texture: texture_2d<u32>;\n#endif // DEFERRED_PREPASS\n\n@group(0) @binding(24) var view_transmission_texture: texture_2d<f32>;\n@group(0) @binding(25) var view_transmission_sampler: sampler;\n\n#ifdef OIT_ENABLED\n@group(0) @binding(26) var<uniform> oit_settings: types::OrderIndependentTransparencySettings;\n@group(0) @binding(27) var<uniform> oit_nodes_capacity: u32;\n@group(0) @binding(28) var<storage, read_write> oit_nodes: array<types::OitFragmentNode>;\n@group(0) @binding(29) var<storage, read_write> oit_heads: array<atomic<u32>>;\n@group(0) @binding(30) var<storage, read_write> oit_atomic_counter: atomic<u32>;\n#endif // OIT_ENABLED\n\n#ifdef ATMOSPHERE\n@group(0) @binding(31) var atmosphere_transmittance_texture: texture_2d<f32>;\n@group(0) @binding(32) var atmosphere_transmittance_sampler: sampler;\n@group(0) @binding(33) var<storage> atmosphere: atmosphere_types::Atmosphere;\n#endif // ATMOSPHERE\n\n#ifdef BLUE_NOISE_TEXTURE\n@group(0) @binding(34) var blue_noise_texture: texture_2d_array<f32>;\n#endif // BLUE_NOISE_TEXTURE\n\n#ifdef AREA_LIGHT_LUTS\n@group(0) @binding(35) var area_light_luts: texture_2d_array<f32>;\n@group(0) @binding(36) var area_light_luts_sampler: sampler;\n#endif\n\n#ifdef DFG_LUT\n@group(0) @binding(37) var dfg_lut: texture_2d<f32>;\n@group(0) @binding(38) var dfg_lut_sampler: sampler;\n#endif // DFG_LUT\n\n#ifdef ENVIRONMENT_MAP\n#ifdef MULTIPLE_LIGHT_PROBES_IN_ARRAY\n@group(1) @binding(0) var diffuse_environment_maps: binding_array<texture_cube<f32>, 8u>;\n@group(1) @binding(1) var specular_environment_maps: binding_array<texture_cube<f32>, 8u>;\n#else\n@group(1) @binding(0) var diffuse_environment_map: texture_cube<f32>;\n@group(1) @binding(1) var specular_environment_map: texture_cube<f32>;\n#endif\n@group(1) @binding(2) var environment_map_sampler: sampler;\n#endif\n\n#ifdef IRRADIANCE_VOLUME\n#ifdef IRRADIANCE_VOLUMES_ARE_USABLE\n#ifdef MULTIPLE_LIGHT_PROBES_IN_ARRAY\n@group(1) @binding(3) var irradiance_volumes: binding_array<texture_3d<f32>, 8u>;\n#else\n@group(1) @binding(3) var irradiance_volume: texture_3d<f32>;\n#endif\n@group(1) @binding(4) var irradiance_volume_sampler: sampler;\n#endif\n#endif\n\n#ifdef CLUSTERED_DECALS_ARE_USABLE\n@group(1) @binding(5) var<storage> clustered_decals: types::ClusteredDecals;\n@group(1) @binding(6) var clustered_decal_textures: binding_array<texture_2d<f32>, 8u>;\n@group(1) @binding(7) var clustered_decal_sampler: sampler;\n#endif // CLUSTERED_DECALS_ARE_USABLE\n");
}
};
let handle:
::bevy_shader::_macro::bevy_asset::prelude::Handle<::bevy_shader::prelude::Shader> =
{
let (path, asset_server) =
{
let path =
{
{
let crate_name =
"bevy_pbr::render::mesh".split(':').next().unwrap();
::bevy_asset::io::embedded::_embedded_asset_path(crate_name,
"src".as_ref(), "src/render/mesh.rs".as_ref(),
"mesh_view_bindings.wgsl".as_ref())
}
};
let path =
::bevy_asset::AssetPath::from_path_buf(path).with_source("embedded");
let asset_server =
::bevy_asset::io::embedded::GetAssetServer::get_asset_server(app);
(path, asset_server)
};
asset_server.load(path)
};
core::mem::forget(handle);load_shader_library!(app, "mesh_view_bindings.wgsl");
165 {
{
let mut embedded =
app.world_mut().resource_mut::<::bevy_asset::io::embedded::EmbeddedAssetRegistry>();
let path =
{
let crate_name =
"bevy_pbr::render::mesh".split(':').next().unwrap();
::bevy_asset::io::embedded::_embedded_asset_path(crate_name,
"src".as_ref(), "src/render/mesh.rs".as_ref(),
"mesh_types.wgsl".as_ref())
};
let watched_path =
::bevy_asset::io::embedded::watched_path("src/render/mesh.rs",
"mesh_types.wgsl");
embedded.insert_asset(watched_path, &path,
b"#define_import_path bevy_pbr::mesh_types\n\nstruct Mesh {\n // Affine 4x3 matrices transposed to 3x4\n // Use bevy_render::maths::affine3_to_square to unpack\n world_from_local: mat3x4<f32>,\n previous_world_from_local: mat3x4<f32>,\n // 3x3 matrix packed in mat2x4 and f32 as:\n // [0].xyz, [1].x,\n // [1].yz, [2].xy\n // [2].z\n // Use bevy_pbr::mesh_functions::mat2x4_f32_to_mat3x3_unpack to unpack\n local_from_world_transpose_a: mat2x4<f32>,\n local_from_world_transpose_b: f32,\n // \'flags\' is a bit field indicating various options. u32 is 32 bits so we have up to 32 options.\n flags: u32,\n lightmap_uv_rect: vec2<u32>,\n // The index of the mesh\'s first vertex in the vertex buffer.\n first_vertex_index: u32,\n current_skin_index: u32,\n // Low 16 bits: index of the material inside the bind group data.\n // High 16 bits: index of the lightmap in the binding array.\n material_and_lightmap_bind_group_slot: u32,\n // User supplied index to identify the mesh instance\n tag: u32,\n morph_descriptor_index: u32,\n};\n\n#ifdef SKINNED\nstruct SkinnedMesh {\n data: array<mat4x4<f32>, 256u>,\n};\n#endif\n\n#ifdef MORPH_TARGETS\n\nstruct MorphWeights {\n weights: array<vec4<f32>, 64u>, // 64 = 256 / 4 (256 = MAX_MORPH_WEIGHTS)\n};\n\n// Describes a single mesh instance that uses morph targets.\nstruct MorphDescriptor {\n // The index of the first morph target weight in the `morph_weights` array.\n current_weights_offset: u32,\n // The index of the first morph target weight in the `prev_morph_weights`\n // array.\n prev_weights_offset: u32,\n // The index of the first morph target for this mesh in the\n // `MorphAttributes` array.\n targets_offset: u32,\n // The number of vertices in the mesh.\n vertex_count: u32,\n // The number of morph targets this mesh has.\n weight_count: u32,\n};\n\n// Morph displacement for a single vertex.\nstruct MorphAttributes {\n // The position delta.\n position: vec3<f32>,\n // Padding, to ensure that each `vec3<f32>` is aligned to 16 bytes.\n pad_a: f32,\n // The normal delta.\n normal: vec3<f32>,\n // Padding, to ensure that each `vec3<f32>` is aligned to 16 bytes.\n pad_b: f32,\n // The tangent delta.\n tangent: vec3<f32>,\n // Padding, to ensure that each `vec3<f32>` is aligned to 16 bytes.\n pad_c: f32,\n};\n\n#endif // MORPH_TARGETS\n\n// [2^0, 2^16)\nconst MESH_FLAGS_VISIBILITY_RANGE_INDEX_BITS: u32 = (1u << 16u) - 1u;\nconst MESH_FLAGS_AABB_BASED_VISIBILITY_RANGE_BIT: u32 = 1u << 27u;\nconst MESH_FLAGS_NO_FRUSTUM_CULLING_BIT: u32 = 1u << 28u;\nconst MESH_FLAGS_SHADOW_RECEIVER_BIT: u32 = 1u << 29u;\nconst MESH_FLAGS_TRANSMITTED_SHADOW_RECEIVER_BIT: u32 = 1u << 30u;\n// if the flag is set, the sign is positive, else it is negative\nconst MESH_FLAGS_SIGN_DETERMINANT_MODEL_3X3_BIT: u32 = 1u << 31u;\n");
}
};
let handle:
::bevy_shader::_macro::bevy_asset::prelude::Handle<::bevy_shader::prelude::Shader> =
{
let (path, asset_server) =
{
let path =
{
{
let crate_name =
"bevy_pbr::render::mesh".split(':').next().unwrap();
::bevy_asset::io::embedded::_embedded_asset_path(crate_name,
"src".as_ref(), "src/render/mesh.rs".as_ref(),
"mesh_types.wgsl".as_ref())
}
};
let path =
::bevy_asset::AssetPath::from_path_buf(path).with_source("embedded");
let asset_server =
::bevy_asset::io::embedded::GetAssetServer::get_asset_server(app);
(path, asset_server)
};
asset_server.load(path)
};
core::mem::forget(handle);load_shader_library!(app, "mesh_types.wgsl");
166 {
{
let mut embedded =
app.world_mut().resource_mut::<::bevy_asset::io::embedded::EmbeddedAssetRegistry>();
let path =
{
let crate_name =
"bevy_pbr::render::mesh".split(':').next().unwrap();
::bevy_asset::io::embedded::_embedded_asset_path(crate_name,
"src".as_ref(), "src/render/mesh.rs".as_ref(),
"mesh_functions.wgsl".as_ref())
};
let watched_path =
::bevy_asset::io::embedded::watched_path("src/render/mesh.rs",
"mesh_functions.wgsl");
embedded.insert_asset(watched_path, &path,
b"#define_import_path bevy_pbr::mesh_functions\n\n#import bevy_pbr::{\n mesh_view_bindings::{\n view,\n visibility_ranges,\n VISIBILITY_RANGE_UNIFORM_BUFFER_SIZE\n },\n mesh_bindings::mesh,\n mesh_types::MESH_FLAGS_SIGN_DETERMINANT_MODEL_3X3_BIT,\n view_transformations::position_world_to_clip,\n}\n#import bevy_render::maths::{affine3_to_square, mat2x4_f32_to_mat3x3_unpack}\n\n#ifndef MESHLET_MESH_MATERIAL_PASS\n\nfn get_world_from_local(instance_index: u32) -> mat4x4<f32> {\n return affine3_to_square(mesh[instance_index].world_from_local);\n}\n\nfn get_previous_world_from_local(instance_index: u32) -> mat4x4<f32> {\n return affine3_to_square(mesh[instance_index].previous_world_from_local);\n}\n\nfn get_local_from_world(instance_index: u32) -> mat4x4<f32> {\n // the model matrix is translation * rotation * scale\n // the inverse is then scale^-1 * rotation ^-1 * translation^-1 \n // the 3x3 matrix only contains the information for the rotation and scale\n let inverse_model_3x3 = transpose(mat2x4_f32_to_mat3x3_unpack(\n mesh[instance_index].local_from_world_transpose_a,\n mesh[instance_index].local_from_world_transpose_b,\n ));\n // construct scale^-1 * rotation^-1 from the 3x3\n let inverse_model_4x4_no_trans = mat4x4<f32>(\n vec4(inverse_model_3x3[0], 0.0),\n vec4(inverse_model_3x3[1], 0.0),\n vec4(inverse_model_3x3[2], 0.0),\n vec4(0.0,0.0,0.0,1.0)\n );\n // we can get translation^-1 by negating the translation of the model\n let model = get_world_from_local(instance_index);\n let inverse_model_4x4_only_trans = mat4x4<f32>(\n vec4(1.0,0.0,0.0,0.0),\n vec4(0.0,1.0,0.0,0.0),\n vec4(0.0,0.0,1.0,0.0),\n vec4(-model[3].xyz, 1.0)\n );\n\n return inverse_model_4x4_no_trans * inverse_model_4x4_only_trans;\n}\n\n#endif // MESHLET_MESH_MATERIAL_PASS\n\nfn mesh_position_local_to_world(world_from_local: mat4x4<f32>, vertex_position: vec4<f32>) -> vec4<f32> {\n return world_from_local * vertex_position;\n}\n\n// NOTE: The intermediate world_position assignment is important\n// for precision purposes when using the \'equals\' depth comparison\n// function.\nfn mesh_position_local_to_clip(world_from_local: mat4x4<f32>, vertex_position: vec4<f32>) -> vec4<f32> {\n let world_position = mesh_position_local_to_world(world_from_local, vertex_position);\n return position_world_to_clip(world_position.xyz);\n}\n\n#ifndef MESHLET_MESH_MATERIAL_PASS\n\nfn mesh_normal_local_to_world(vertex_normal: vec3<f32>, instance_index: u32) -> vec3<f32> {\n // NOTE: The mikktspace method of normal mapping requires that the world normal is\n // re-normalized in the vertex shader to match the way mikktspace bakes vertex tangents\n // and normal maps so that the exact inverse process is applied when shading. Blender, Unity,\n // Unreal Engine, Godot, and more all use the mikktspace method.\n // We only skip normalization for invalid normals so that they don\'t become NaN.\n // Do not change this code unless you really know what you are doing.\n // http://www.mikktspace.com/\n if any(vertex_normal != vec3<f32>(0.0)) {\n return normalize(\n mat2x4_f32_to_mat3x3_unpack(\n mesh[instance_index].local_from_world_transpose_a,\n mesh[instance_index].local_from_world_transpose_b,\n ) * vertex_normal\n );\n } else {\n return vertex_normal;\n }\n}\n\n#endif // MESHLET_MESH_MATERIAL_PASS\n\n// Calculates the sign of the determinant of the 3x3 model matrix based on a\n// mesh flag\nfn sign_determinant_model_3x3m(mesh_flags: u32) -> f32 {\n // bool(u32) is false if 0u else true\n // f32(bool) is 1.0 if true else 0.0\n // * 2.0 - 1.0 remaps 0.0 or 1.0 to -1.0 or 1.0 respectively\n return f32(bool(mesh_flags & MESH_FLAGS_SIGN_DETERMINANT_MODEL_3X3_BIT)) * 2.0 - 1.0;\n}\n\n#ifndef MESHLET_MESH_MATERIAL_PASS\n\nfn mesh_tangent_local_to_world(world_from_local: mat4x4<f32>, vertex_tangent: vec4<f32>, instance_index: u32) -> vec4<f32> {\n // NOTE: The mikktspace method of normal mapping requires that the world tangent is\n // re-normalized in the vertex shader to match the way mikktspace bakes vertex tangents\n // and normal maps so that the exact inverse process is applied when shading. Blender, Unity,\n // Unreal Engine, Godot, and more all use the mikktspace method.\n // We only skip normalization for invalid tangents so that they don\'t become NaN.\n // Do not change this code unless you really know what you are doing.\n // http://www.mikktspace.com/\n if any(vertex_tangent != vec4<f32>(0.0)) {\n return vec4<f32>(\n normalize(\n mat3x3<f32>(\n world_from_local[0].xyz,\n world_from_local[1].xyz,\n world_from_local[2].xyz,\n ) * vertex_tangent.xyz\n ),\n // NOTE: Multiplying by the sign of the determinant of the 3x3 model matrix accounts for\n // situations such as negative scaling.\n vertex_tangent.w * sign_determinant_model_3x3m(mesh[instance_index].flags)\n );\n } else {\n return vertex_tangent;\n }\n}\n\n#endif // MESHLET_MESH_MATERIAL_PASS\n\n// Returns an appropriate dither level for the current mesh instance.\n//\n// This looks up the LOD range in the `visibility_ranges` table and compares the\n// camera distance to determine the dithering level.\n#ifdef VISIBILITY_RANGE_DITHER\nfn get_visibility_range_dither_level(instance_index: u32, world_position: vec4<f32>) -> i32 {\n#if AVAILABLE_STORAGE_BUFFER_BINDINGS >= 6\n // If we\'re using a storage buffer, then the length is variable.\n let visibility_buffer_array_len = arrayLength(&visibility_ranges);\n#else // AVAILABLE_STORAGE_BUFFER_BINDINGS >= 6\n // If we\'re using a uniform buffer, then the length is constant\n let visibility_buffer_array_len = VISIBILITY_RANGE_UNIFORM_BUFFER_SIZE;\n#endif // AVAILABLE_STORAGE_BUFFER_BINDINGS >= 6\n\n let visibility_buffer_index = mesh[instance_index].flags & 0xffffu;\n if (visibility_buffer_index > visibility_buffer_array_len) {\n return -16;\n }\n\n let lod_range = visibility_ranges[visibility_buffer_index];\n let camera_distance = length(view.lod_view_world_position.xyz - world_position.xyz);\n\n // This encodes the following mapping:\n //\n // `lod_range.` x y z w camera distance\n // \xe2\x86\x90\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xbc\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xbc\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xbc\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xbc\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x86\x92\n // Dither Level -16 -16 0 0 16 16 Dither Level\n let offset = select(-16, 0, camera_distance >= lod_range.z);\n let bounds = select(lod_range.xy, lod_range.zw, camera_distance >= lod_range.z);\n let level = i32(round((camera_distance - bounds.x) / (bounds.y - bounds.x) * 16.0));\n return offset + clamp(level, 0, 16);\n}\n#endif\n\n\n#ifndef MESHLET_MESH_MATERIAL_PASS\nfn get_tag(instance_index: u32) -> u32 {\n return mesh[instance_index].tag;\n}\n#endif\n");
}
};
let handle:
::bevy_shader::_macro::bevy_asset::prelude::Handle<::bevy_shader::prelude::Shader> =
{
let (path, asset_server) =
{
let path =
{
{
let crate_name =
"bevy_pbr::render::mesh".split(':').next().unwrap();
::bevy_asset::io::embedded::_embedded_asset_path(crate_name,
"src".as_ref(), "src/render/mesh.rs".as_ref(),
"mesh_functions.wgsl".as_ref())
}
};
let path =
::bevy_asset::AssetPath::from_path_buf(path).with_source("embedded");
let asset_server =
::bevy_asset::io::embedded::GetAssetServer::get_asset_server(app);
(path, asset_server)
};
asset_server.load(path)
};
core::mem::forget(handle);load_shader_library!(app, "mesh_functions.wgsl");
167 {
{
let mut embedded =
app.world_mut().resource_mut::<::bevy_asset::io::embedded::EmbeddedAssetRegistry>();
let path =
{
let crate_name =
"bevy_pbr::render::mesh".split(':').next().unwrap();
::bevy_asset::io::embedded::_embedded_asset_path(crate_name,
"src".as_ref(), "src/render/mesh.rs".as_ref(),
"skinning.wgsl".as_ref())
};
let watched_path =
::bevy_asset::io::embedded::watched_path("src/render/mesh.rs",
"skinning.wgsl");
embedded.insert_asset(watched_path, &path,
b"#define_import_path bevy_pbr::skinning\n\n#import bevy_pbr::mesh_types::SkinnedMesh\n#import bevy_pbr::mesh_bindings::mesh\n\n#ifdef SKINNED\n\n#ifdef SKINS_USE_UNIFORM_BUFFERS\n@group(2) @binding(1) var<uniform> joint_matrices: SkinnedMesh;\n#else // SKINS_USE_UNIFORM_BUFFERS\n@group(2) @binding(1) var<storage> joint_matrices: array<mat4x4<f32>>;\n#endif // SKINS_USE_UNIFORM_BUFFERS\n\n// An array of matrices specifying the joint positions from the previous frame.\n//\n// This is used for motion vector computation.\n//\n// If this is the first frame, or we\'re otherwise prevented from using data from\n// the previous frame, this is simply the same as `joint_matrices` above.\n#ifdef SKINS_USE_UNIFORM_BUFFERS\n@group(2) @binding(6) var<uniform> prev_joint_matrices: SkinnedMesh;\n#else // SKINS_USE_UNIFORM_BUFFERS\n@group(2) @binding(6) var<storage> prev_joint_matrices: array<mat4x4<f32>>;\n#endif // SKINS_USE_UNIFORM_BUFFERS\n\nfn skin_model(\n indexes: vec4<u32>,\n weights: vec4<f32>,\n instance_index: u32,\n) -> mat4x4<f32> {\n#ifdef SKINS_USE_UNIFORM_BUFFERS\n return weights.x * joint_matrices.data[indexes.x]\n + weights.y * joint_matrices.data[indexes.y]\n + weights.z * joint_matrices.data[indexes.z]\n + weights.w * joint_matrices.data[indexes.w];\n#else // SKINS_USE_UNIFORM_BUFFERS\n var skin_index = mesh[instance_index].current_skin_index;\n return weights.x * joint_matrices[skin_index + indexes.x]\n + weights.y * joint_matrices[skin_index + indexes.y]\n + weights.z * joint_matrices[skin_index + indexes.z]\n + weights.w * joint_matrices[skin_index + indexes.w];\n#endif // SKINS_USE_UNIFORM_BUFFERS\n}\n\n// Returns the skinned position of a vertex with the given weights from the\n// previous frame.\n//\n// This is used for motion vector computation.\nfn skin_prev_model(\n indexes: vec4<u32>,\n weights: vec4<f32>,\n instance_index: u32,\n) -> mat4x4<f32> {\n#ifdef SKINS_USE_UNIFORM_BUFFERS\n return weights.x * prev_joint_matrices.data[indexes.x]\n + weights.y * prev_joint_matrices.data[indexes.y]\n + weights.z * prev_joint_matrices.data[indexes.z]\n + weights.w * prev_joint_matrices.data[indexes.w];\n#else // SKINS_USE_UNIFORM_BUFFERS\n let skin_index = mesh[instance_index].current_skin_index;\n return weights.x * prev_joint_matrices[skin_index + indexes.x]\n + weights.y * prev_joint_matrices[skin_index + indexes.y]\n + weights.z * prev_joint_matrices[skin_index + indexes.z]\n + weights.w * prev_joint_matrices[skin_index + indexes.w];\n#endif // SKINS_USE_UNIFORM_BUFFERS\n}\n\nfn inverse_transpose_3x3m(in: mat3x3<f32>) -> mat3x3<f32> {\n let x = cross(in[1], in[2]);\n let y = cross(in[2], in[0]);\n let z = cross(in[0], in[1]);\n let det = dot(in[2], z);\n return mat3x3<f32>(\n x / det,\n y / det,\n z / det\n );\n}\n\nfn skin_normals(\n world_from_local: mat4x4<f32>,\n normal: vec3<f32>,\n) -> vec3<f32> {\n return normalize(\n inverse_transpose_3x3m(\n mat3x3<f32>(\n world_from_local[0].xyz,\n world_from_local[1].xyz,\n world_from_local[2].xyz\n )\n ) * normal\n );\n}\n\n#endif\n");
}
};
let handle:
::bevy_shader::_macro::bevy_asset::prelude::Handle<::bevy_shader::prelude::Shader> =
{
let (path, asset_server) =
{
let path =
{
{
let crate_name =
"bevy_pbr::render::mesh".split(':').next().unwrap();
::bevy_asset::io::embedded::_embedded_asset_path(crate_name,
"src".as_ref(), "src/render/mesh.rs".as_ref(),
"skinning.wgsl".as_ref())
}
};
let path =
::bevy_asset::AssetPath::from_path_buf(path).with_source("embedded");
let asset_server =
::bevy_asset::io::embedded::GetAssetServer::get_asset_server(app);
(path, asset_server)
};
asset_server.load(path)
};
core::mem::forget(handle);load_shader_library!(app, "skinning.wgsl");
168 {
{
let mut embedded =
app.world_mut().resource_mut::<::bevy_asset::io::embedded::EmbeddedAssetRegistry>();
let path =
{
let crate_name =
"bevy_pbr::render::mesh".split(':').next().unwrap();
::bevy_asset::io::embedded::_embedded_asset_path(crate_name,
"src".as_ref(), "src/render/mesh.rs".as_ref(),
"morph.wgsl".as_ref())
};
let watched_path =
::bevy_asset::io::embedded::watched_path("src/render/mesh.rs",
"morph.wgsl");
embedded.insert_asset(watched_path, &path,
b"#define_import_path bevy_pbr::morph\n\n#ifdef MORPH_TARGETS\n\n#import bevy_pbr::mesh_types::{MorphAttributes, MorphDescriptor, MorphWeights}\n#import bevy_pbr::mesh_bindings::mesh\n\n#ifdef SKINS_USE_UNIFORM_BUFFERS\n\n@group(2) @binding(2) var<uniform> morph_weights: MorphWeights;\n@group(2) @binding(3) var morph_targets: texture_3d<f32>;\n@group(2) @binding(7) var<uniform> prev_morph_weights: MorphWeights;\n\n#else // SKINS_USE_UNIFORM_BUFFERS\n\n@group(2) @binding(2) var<storage> morph_weights: array<f32>;\n@group(2) @binding(3) var<storage> morph_targets: array<MorphAttributes>;\n@group(2) @binding(7) var<storage> prev_morph_weights: array<f32>;\n@group(2) @binding(8) var<storage> morph_descriptors: array<MorphDescriptor>;\n\n#endif // SKINS_USE_UNIFORM_BUFFERS\n\n// NOTE: Those are the \"hardcoded\" values found in `MorphAttributes` struct\n// in crates/bevy_render/src/mesh/morph/visitors.rs\n// In an ideal world, the offsets are established dynamically and passed as #defines\n// to the shader, but it\'s out of scope for the initial implementation of morph targets.\nconst position_offset: u32 = 0u;\nconst normal_offset: u32 = 3u;\nconst tangent_offset: u32 = 6u;\nconst total_component_count: u32 = 9u;\n\nfn layer_count(instance_index: u32) -> u32 {\n#ifdef SKINS_USE_UNIFORM_BUFFERS\n let dimensions = textureDimensions(morph_targets);\n return u32(dimensions.z);\n#else // SKINS_USE_UNIFORM_BUFFERS\n let morph_descriptor_index = mesh[instance_index].morph_descriptor_index;\n return morph_descriptors[morph_descriptor_index].weight_count;\n#endif // SKINS_USE_UNIFORM_BUFFERS\n}\n\n#ifdef SKINS_USE_UNIFORM_BUFFERS\nfn component_texture_coord(vertex_index: u32, component_offset: u32) -> vec2<u32> {\n let width = u32(textureDimensions(morph_targets).x);\n let component_index = total_component_count * vertex_index + component_offset;\n return vec2<u32>(component_index % width, component_index / width);\n}\n#endif // SKINS_USE_UNIFORM_BUFFERS\n\nfn weight_at(weight_index: u32, instance_index: u32) -> f32 {\n#ifdef SKINS_USE_UNIFORM_BUFFERS\n let i = weight_index;\n return morph_weights.weights[i / 4u][i % 4u];\n#else // SKINS_USE_UNIFORM_BUFFERS\n let morph_descriptor_index = mesh[instance_index].morph_descriptor_index;\n let weights_offset = morph_descriptors[morph_descriptor_index].current_weights_offset;\n return morph_weights[weights_offset + weight_index];\n#endif // SKINS_USE_UNIFORM_BUFFERS\n}\n\nfn prev_weight_at(weight_index: u32, instance_index: u32) -> f32 {\n#ifdef SKINS_USE_UNIFORM_BUFFERS\n let i = weight_index;\n return prev_morph_weights.weights[i / 4u][i % 4u];\n#else // SKINS_USE_UNIFORM_BUFFERS\n let morph_descriptor_index = mesh[instance_index].morph_descriptor_index;\n let weights_offset = morph_descriptors[morph_descriptor_index].prev_weights_offset;\n return prev_morph_weights[weights_offset + weight_index];\n#endif // SKINS_USE_UNIFORM_BUFFERS\n}\n\n#ifdef SKINS_USE_UNIFORM_BUFFERS\n\nfn morph_pixel(vertex: u32, component: u32, weight: u32) -> f32 {\n let coord = component_texture_coord(vertex, component);\n // Due to https://gpuweb.github.io/gpuweb/wgsl/#texel-formats\n // While the texture stores a f32, the textureLoad returns a vec4<>, where\n // only the first component is set.\n return textureLoad(morph_targets, vec3(coord, weight), 0).r;\n}\n\nfn morph(vertex_index: u32, component_offset: u32, weight_index: u32) -> vec3<f32> {\n return vec3<f32>(\n morph_pixel(vertex_index, component_offset, weight_index),\n morph_pixel(vertex_index, component_offset + 1u, weight_index),\n morph_pixel(vertex_index, component_offset + 2u, weight_index),\n );\n}\n\nfn morph_position(vertex_index: u32, weight_index: u32, instance_index: u32) -> vec3<f32> {\n return morph(vertex_index, position_offset, weight_index);\n}\n\nfn morph_normal(vertex_index: u32, weight_index: u32, instance_index: u32) -> vec3<f32> {\n return morph(vertex_index, normal_offset, weight_index);\n}\n\nfn morph_tangent(vertex_index: u32, weight_index: u32, instance_index: u32) -> vec3<f32> {\n return morph(vertex_index, tangent_offset, weight_index);\n}\n\n#else // SKINS_USE_UNIFORM_BUFFERS\n\nfn get_morph_target(vertex_index: u32, weight_index: u32, instance_index: u32) -> MorphAttributes {\n let morph_descriptor_index = mesh[instance_index].morph_descriptor_index;\n let targets_offset = morph_descriptors[morph_descriptor_index].targets_offset;\n let vertex_count = morph_descriptors[morph_descriptor_index].vertex_count;\n return morph_targets[targets_offset + weight_index * vertex_count + vertex_index];\n}\n\nfn morph_position(vertex_index: u32, weight_index: u32, instance_index: u32) -> vec3<f32> {\n return get_morph_target(vertex_index, weight_index, instance_index).position;\n}\n\nfn morph_normal(vertex_index: u32, weight_index: u32, instance_index: u32) -> vec3<f32> {\n return get_morph_target(vertex_index, weight_index, instance_index).normal;\n}\n\nfn morph_tangent(vertex_index: u32, weight_index: u32, instance_index: u32) -> vec3<f32> {\n return get_morph_target(vertex_index, weight_index, instance_index).tangent;\n}\n\n#endif // SKINS_USE_UNIFORM_BUFFERS\n\n#endif // MORPH_TARGETS\n");
}
};
let handle:
::bevy_shader::_macro::bevy_asset::prelude::Handle<::bevy_shader::prelude::Shader> =
{
let (path, asset_server) =
{
let path =
{
{
let crate_name =
"bevy_pbr::render::mesh".split(':').next().unwrap();
::bevy_asset::io::embedded::_embedded_asset_path(crate_name,
"src".as_ref(), "src/render/mesh.rs".as_ref(),
"morph.wgsl".as_ref())
}
};
let path =
::bevy_asset::AssetPath::from_path_buf(path).with_source("embedded");
let asset_server =
::bevy_asset::io::embedded::GetAssetServer::get_asset_server(app);
(path, asset_server)
};
asset_server.load(path)
};
core::mem::forget(handle);load_shader_library!(app, "morph.wgsl");
169 {
{
let mut embedded =
app.world_mut().resource_mut::<::bevy_asset::io::embedded::EmbeddedAssetRegistry>();
let path =
{
let crate_name =
"bevy_pbr::render::mesh".split(':').next().unwrap();
::bevy_asset::io::embedded::_embedded_asset_path(crate_name,
"src".as_ref(), "src/render/mesh.rs".as_ref(),
"occlusion_culling.wgsl".as_ref())
};
let watched_path =
::bevy_asset::io::embedded::watched_path("src/render/mesh.rs",
"occlusion_culling.wgsl");
embedded.insert_asset(watched_path, &path,
b"// Occlusion culling utility functions.\n\n#define_import_path bevy_pbr::occlusion_culling\n\nfn get_aabb_size_in_pixels(aabb: vec4<f32>, depth_pyramid: texture_2d<f32>) -> vec2<f32> {\n let depth_pyramid_size_mip_0 = vec2<f32>(textureDimensions(depth_pyramid, 0));\n let aabb_width_pixels = (aabb.z - aabb.x) * depth_pyramid_size_mip_0.x;\n let aabb_height_pixels = (aabb.w - aabb.y) * depth_pyramid_size_mip_0.y;\n return vec2(aabb_width_pixels, aabb_height_pixels);\n}\n\nfn get_occluder_depth(\n aabb: vec4<f32>,\n aabb_pixel_size: vec2<f32>,\n depth_pyramid: texture_2d<f32>\n) -> f32 {\n let aabb_width_pixels = aabb_pixel_size.x;\n let aabb_height_pixels = aabb_pixel_size.y;\n\n let depth_pyramid_size_mip_0 = vec2<f32>(textureDimensions(depth_pyramid, 0));\n let depth_level = max(0, i32(ceil(log2(max(aabb_width_pixels, aabb_height_pixels))))); // TODO: Naga doesn\'t like this being a u32\n let depth_pyramid_size = vec2<f32>(textureDimensions(depth_pyramid, depth_level));\n let aabb_top_left = vec2<u32>(aabb.xy * depth_pyramid_size);\n\n let depth_quad_a = textureLoad(depth_pyramid, aabb_top_left, depth_level).x;\n let depth_quad_b = textureLoad(depth_pyramid, aabb_top_left + vec2(1u, 0u), depth_level).x;\n let depth_quad_c = textureLoad(depth_pyramid, aabb_top_left + vec2(0u, 1u), depth_level).x;\n let depth_quad_d = textureLoad(depth_pyramid, aabb_top_left + vec2(1u, 1u), depth_level).x;\n return min(min(depth_quad_a, depth_quad_b), min(depth_quad_c, depth_quad_d));\n}\n");
}
};
let handle:
::bevy_shader::_macro::bevy_asset::prelude::Handle<::bevy_shader::prelude::Shader> =
{
let (path, asset_server) =
{
let path =
{
{
let crate_name =
"bevy_pbr::render::mesh".split(':').next().unwrap();
::bevy_asset::io::embedded::_embedded_asset_path(crate_name,
"src".as_ref(), "src/render/mesh.rs".as_ref(),
"occlusion_culling.wgsl".as_ref())
}
};
let path =
::bevy_asset::AssetPath::from_path_buf(path).with_source("embedded");
let asset_server =
::bevy_asset::io::embedded::GetAssetServer::get_asset_server(app);
(path, asset_server)
};
asset_server.load(path)
};
core::mem::forget(handle);load_shader_library!(app, "occlusion_culling.wgsl");
170
171 {
{
let mut embedded =
app.world_mut().resource_mut::<::bevy_asset::io::embedded::EmbeddedAssetRegistry>();
let path =
{
let crate_name =
"bevy_pbr::render::mesh".split(':').next().unwrap();
::bevy_asset::io::embedded::_embedded_asset_path(crate_name,
"src".as_ref(), "src/render/mesh.rs".as_ref(),
"mesh.wgsl".as_ref())
};
let watched_path =
::bevy_asset::io::embedded::watched_path("src/render/mesh.rs",
"mesh.wgsl");
embedded.insert_asset(watched_path, &path,
b"#import bevy_pbr::{\n mesh_bindings::mesh,\n mesh_functions,\n skinning,\n morph::{morph_position, morph_normal, morph_tangent},\n forward_io::{Vertex, VertexOutput},\n view_transformations::position_world_to_clip,\n}\n\n#ifdef MORPH_TARGETS\n// The instance_index parameter must match vertex_in.instance_index. This is a work around for a wgpu dx12 bug.\n// See https://github.com/gfx-rs/naga/issues/2416\nfn morph_vertex(vertex_in: Vertex, instance_index: u32) -> Vertex {\n var vertex = vertex_in;\n let first_vertex = mesh[instance_index].first_vertex_index;\n let vertex_index = vertex.index - first_vertex;\n\n let weight_count = bevy_pbr::morph::layer_count(instance_index);\n for (var i: u32 = 0u; i < weight_count; i ++) {\n let weight = bevy_pbr::morph::weight_at(i, instance_index);\n if weight == 0.0 {\n continue;\n }\n vertex.position += weight * morph_position(vertex_index, i, instance_index);\n#ifdef VERTEX_NORMALS\n vertex.normal += weight * morph_normal(vertex_index, i, instance_index);\n#endif\n#ifdef VERTEX_TANGENTS\n vertex.tangent += vec4(weight * morph_tangent(vertex_index, i, instance_index), 0.0);\n#endif\n }\n return vertex;\n}\n#endif\n\n@vertex\nfn vertex(vertex_no_morph: Vertex) -> VertexOutput {\n var out: VertexOutput;\n\n#ifdef MORPH_TARGETS\n var vertex = morph_vertex(vertex_no_morph, vertex_no_morph.instance_index);\n#else\n var vertex = vertex_no_morph;\n#endif\n\n let mesh_world_from_local = mesh_functions::get_world_from_local(vertex_no_morph.instance_index);\n\n#ifdef SKINNED\n // Use vertex_no_morph.instance_index instead of vertex.instance_index to work around a wgpu dx12 bug.\n // See https://github.com/gfx-rs/naga/issues/2416 .\n var world_from_local = skinning::skin_model(\n vertex.joint_indices,\n vertex.joint_weights,\n vertex_no_morph.instance_index\n );\n#else\n var world_from_local = mesh_world_from_local;\n#endif\n\n#ifdef VERTEX_NORMALS\n#ifdef SKINNED\n out.world_normal = skinning::skin_normals(world_from_local, vertex.normal);\n#else\n out.world_normal = mesh_functions::mesh_normal_local_to_world(\n vertex.normal,\n // Use vertex_no_morph.instance_index instead of vertex.instance_index to work around a wgpu dx12 bug.\n // See https://github.com/gfx-rs/naga/issues/2416\n vertex_no_morph.instance_index\n );\n#endif\n#endif\n\n#ifdef VERTEX_POSITIONS\n out.world_position = mesh_functions::mesh_position_local_to_world(world_from_local, vec4<f32>(vertex.position, 1.0));\n out.position = position_world_to_clip(out.world_position.xyz);\n#endif\n\n#ifdef VERTEX_UVS_A\n out.uv = vertex.uv;\n#endif\n#ifdef VERTEX_UVS_B\n out.uv_b = vertex.uv_b;\n#endif\n\n#ifdef VERTEX_TANGENTS\n out.world_tangent = mesh_functions::mesh_tangent_local_to_world(\n world_from_local,\n vertex.tangent,\n // Use vertex_no_morph.instance_index instead of vertex.instance_index to work around a wgpu dx12 bug.\n // See https://github.com/gfx-rs/naga/issues/2416\n vertex_no_morph.instance_index\n );\n#endif\n\n#ifdef VERTEX_COLORS\n out.color = vertex.color;\n#endif\n\n#ifdef VERTEX_OUTPUT_INSTANCE_INDEX\n // Use vertex_no_morph.instance_index instead of vertex.instance_index to work around a wgpu dx12 bug.\n // See https://github.com/gfx-rs/naga/issues/2416\n out.instance_index = vertex_no_morph.instance_index;\n#endif\n\n#ifdef VISIBILITY_RANGE_DITHER\n out.visibility_range_dither = mesh_functions::get_visibility_range_dither_level(\n vertex_no_morph.instance_index, mesh_world_from_local[3]);\n#endif\n\n return out;\n}\n\n@fragment\nfn fragment(\n mesh: VertexOutput,\n) -> @location(0) vec4<f32> {\n#ifdef VERTEX_COLORS\n return mesh.color;\n#else\n return vec4<f32>(1.0, 0.0, 1.0, 1.0);\n#endif\n}\n");
}
};embedded_asset!(app, "mesh.wgsl");
172
173 if app.get_sub_app(RenderApp).is_none() {
174 return;
175 }
176
177 app.add_systems(
178 PostUpdate,
179 (no_automatic_skin_batching, no_automatic_morph_batching),
180 )
181 .add_plugins((
182 BinnedRenderPhasePlugin::<Opaque3d, MeshPipeline>::new(self.debug_flags),
183 BinnedRenderPhasePlugin::<AlphaMask3d, MeshPipeline>::new(self.debug_flags),
184 BinnedRenderPhasePlugin::<Shadow, MeshPipeline>::new(self.debug_flags),
185 BinnedRenderPhasePlugin::<Opaque3dDeferred, MeshPipeline>::new(self.debug_flags),
186 BinnedRenderPhasePlugin::<AlphaMask3dDeferred, MeshPipeline>::new(self.debug_flags),
187 SortedRenderPhasePlugin::<Transmissive3d, MeshPipeline>::new(self.debug_flags),
188 SortedRenderPhasePlugin::<Transparent3d, MeshPipeline>::new(self.debug_flags),
189 ));
190
191 if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
192 render_app
193 .init_gpu_resource::<MeshCullingDataBuffer>()
194 .init_resource::<RenderMaterialInstances>()
195 .configure_sets(
196 ExtractSchedule,
197 MeshExtractionSystems.after(view::extract_visibility_ranges),
198 )
199 .add_systems(
200 ExtractSchedule,
201 (
202 extract_skins,
203 extract_morphs,
204 gpu_preprocessing::clear_batched_gpu_instance_buffers::<MeshPipeline>
205 .before(MeshExtractionSystems),
206 ),
207 )
208 .add_systems(
209 Render,
210 (
211 set_mesh_motion_vector_flags.in_set(RenderSystems::PrepareMeshes),
212 prepare_skins.in_set(RenderSystems::PrepareResources),
213 write_morph_buffers.in_set(RenderSystems::PrepareResourcesFlush),
214 prepare_mesh_bind_groups.in_set(RenderSystems::PrepareBindGroups),
215 prepare_mesh_view_bind_groups
216 .in_set(RenderSystems::PrepareBindGroups)
217 .after(prepare_oit_buffers)
218 .after(write_atmosphere_buffer),
219 no_gpu_preprocessing::clear_batched_cpu_instance_buffers::<MeshPipeline>
220 .in_set(RenderSystems::Cleanup)
221 .after(RenderSystems::Render),
222 prepare_morph_descriptors.in_set(RenderSystems::PrepareMeshes),
223 ),
224 );
225 }
226 }
227
228 fn finish(&self, app: &mut App) {
229 let mut mesh_bindings_shader_defs = Vec::with_capacity(1);
230
231 if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
232 render_app
233 .init_gpu_resource::<MorphIndices>()
234 .init_gpu_resource::<MorphUniforms>()
235 .init_gpu_resource::<ViewKeyCache>()
236 .init_resource::<GpuPreprocessingSupport>()
237 .init_resource::<RenderGpuCulledEntities>()
238 .add_systems(RenderStartup, skin_uniforms_from_world)
239 .add_systems(
240 Render,
241 check_views_need_specialization.in_set(PrepareAssets),
242 );
243
244 let gpu_preprocessing_support =
245 render_app.world().resource::<GpuPreprocessingSupport>();
246 let use_gpu_instance_buffer_builder =
247 self.use_gpu_instance_buffer_builder && gpu_preprocessing_support.is_available();
248
249 let render_mesh_instances = RenderMeshInstances::new(use_gpu_instance_buffer_builder);
250 render_app
251 .allow_ambiguous_resource::<no_gpu_preprocessing::BatchedInstanceBuffer::<MeshUniform>>()
252 .allow_ambiguous_resource::<gpu_preprocessing::BatchedInstanceBuffers<MeshUniform, MeshInputUniform>>()
253 .insert_resource(render_mesh_instances);
254
255 if use_gpu_instance_buffer_builder {
256 render_app
257 .init_gpu_resource::<gpu_preprocessing::BatchedInstanceBuffers<
258 MeshUniform,
259 MeshInputUniform
260 >>()
261 .init_gpu_resource::<RenderMeshInstanceGpuQueues>()
262 .init_resource::<MeshesToReextractNextFrame>()
263 .add_systems(
264 RenderStartup,
265 mark_all_meshes_for_reextraction,
266 )
267 .add_systems(
268 ExtractSchedule,
269 extract_meshes_for_gpu_building.in_set(MeshExtractionSystems),
270 )
271 .add_systems(
272 Render,
273 (
274 gpu_preprocessing::write_batched_instance_buffers::<MeshPipeline>
275 .in_set(RenderSystems::PrepareResourcesFlush)
276 .after(write_mesh_culling_data_buffer),
277 gpu_preprocessing::delete_old_work_item_buffers::<MeshPipeline>
278 .in_set(RenderSystems::PrepareResources),
279 collect_meshes_for_gpu_building
280 .in_set(RenderSystems::PrepareMeshes)
281 .before(set_mesh_motion_vector_flags)
285 .after(prepare_morph_descriptors),
290 collect_gpu_culled_meshes.in_set(RenderSystems::PrepareMeshes)
291 .after(collect_meshes_for_gpu_building)
292 .before(set_mesh_motion_vector_flags),
293 ),
294 );
295 } else {
296 render_app
297 .init_gpu_resource::<no_gpu_preprocessing::BatchedInstanceBuffer<MeshUniform>>()
298 .add_systems(
299 ExtractSchedule,
300 extract_meshes_for_cpu_building.in_set(MeshExtractionSystems),
301 )
302 .add_systems(
303 Render,
304 no_gpu_preprocessing::write_batched_instance_buffer::<MeshPipeline>
305 .in_set(RenderSystems::PrepareResourcesFlush),
306 );
307 };
308
309 let render_device = render_app.world().resource::<RenderDevice>();
310 if let Some(per_object_buffer_batch_size) =
311 GpuArrayBuffer::<MeshUniform>::batch_size(&render_device.limits())
312 {
313 mesh_bindings_shader_defs.push(ShaderDefVal::UInt(
314 "PER_OBJECT_BUFFER_BATCH_SIZE".into(),
315 per_object_buffer_batch_size,
316 ));
317 }
318
319 render_app.add_systems(
320 RenderStartup,
321 (init_mesh_pipeline_view_layouts, init_mesh_pipeline)
322 .chain()
323 .in_set(MeshPipelineSystems),
324 );
325 }
326
327 {
{
let mut embedded =
app.world_mut().resource_mut::<::bevy_asset::io::embedded::EmbeddedAssetRegistry>();
let path =
{
let crate_name =
"bevy_pbr::render::mesh".split(':').next().unwrap();
::bevy_asset::io::embedded::_embedded_asset_path(crate_name,
"src".as_ref(), "src/render/mesh.rs".as_ref(),
"mesh_bindings.wgsl".as_ref())
};
let watched_path =
::bevy_asset::io::embedded::watched_path("src/render/mesh.rs",
"mesh_bindings.wgsl");
embedded.insert_asset(watched_path, &path,
b"#define_import_path bevy_pbr::mesh_bindings\n\n#import bevy_pbr::mesh_types::Mesh\n\n#ifndef MESHLET_MESH_MATERIAL_PASS\n#ifdef PER_OBJECT_BUFFER_BATCH_SIZE\n@group(2) @binding(0) var<uniform> mesh: array<Mesh, #{PER_OBJECT_BUFFER_BATCH_SIZE}u>;\n#else\n@group(2) @binding(0) var<storage> mesh: array<Mesh>;\n#endif // PER_OBJECT_BUFFER_BATCH_SIZE\n#endif // MESHLET_MESH_MATERIAL_PASS\n");
}
};
let handle:
::bevy_shader::_macro::bevy_asset::prelude::Handle<::bevy_shader::prelude::Shader> =
{
let (path, asset_server) =
{
let path =
{
{
let crate_name =
"bevy_pbr::render::mesh".split(':').next().unwrap();
::bevy_asset::io::embedded::_embedded_asset_path(crate_name,
"src".as_ref(), "src/render/mesh.rs".as_ref(),
"mesh_bindings.wgsl".as_ref())
}
};
let path =
::bevy_asset::AssetPath::from_path_buf(path).with_source("embedded");
let asset_server =
::bevy_asset::io::embedded::GetAssetServer::get_asset_server(app);
(path, asset_server)
};
asset_server.load_builder().with_settings(move |settings|
*settings =
ShaderSettings {
shader_defs: mesh_bindings_shader_defs.clone(),
}).load(path)
};
core::mem::forget(handle);load_shader_library!(app, "mesh_bindings.wgsl", move |settings| *settings =
330 ShaderSettings {
331 shader_defs: mesh_bindings_shader_defs.clone(),
332 });
333 }
334}
335
336fn mark_all_meshes_for_reextraction(
338 mut render_mesh_instances: ResMut<RenderMeshInstances>,
339 mut meshes_to_reextract: ResMut<MeshesToReextractNextFrame>,
340) {
341 match *render_mesh_instances {
342 RenderMeshInstances::CpuBuilding(ref mut cpu) => {
343 meshes_to_reextract.extend(cpu.keys());
344 cpu.clear();
345 }
346 RenderMeshInstances::GpuBuilding(ref mut gpu) => {
347 meshes_to_reextract.extend(gpu.keys());
348 gpu.clear();
349 }
350 }
351}
352
353#[derive(impl bevy_ecs::resource::Resource for ViewKeyCache where
Self: ::core::marker::Send + ::core::marker::Sync + 'static {}Resource, impl ::core::ops::Deref for ViewKeyCache {
type Target = HashMap<RetainedViewEntity, MeshPipelineKey>;
fn deref(&self) -> &Self::Target { &self.0 }
}Deref, impl ::core::ops::DerefMut for ViewKeyCache {
fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 }
}DerefMut, #[automatically_derived]
impl ::core::default::Default for ViewKeyCache {
#[inline]
fn default() -> ViewKeyCache {
ViewKeyCache(::core::default::Default::default())
}
}Default, #[automatically_derived]
impl ::core::fmt::Debug for ViewKeyCache {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_tuple_field1_finish(f, "ViewKeyCache",
&&self.0)
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for ViewKeyCache {
#[inline]
fn clone(&self) -> ViewKeyCache {
ViewKeyCache(::core::clone::Clone::clone(&self.0))
}
}Clone)]
356pub struct ViewKeyCache(HashMap<RetainedViewEntity, MeshPipelineKey>);
357
358pub fn check_views_need_specialization(
359 mut view_key_cache: ResMut<ViewKeyCache>,
360 mut dirty_specializations: ResMut<DirtySpecializations>,
361 mut views: Query<(
362 &ExtractedView,
363 Option<&ExtractedCamera>,
364 &Msaa,
365 (Option<&Tonemapping>, Option<&DebandDither>),
366 Option<&ShadowFilteringMethod>,
367 Has<ScreenSpaceAmbientOcclusion>,
368 (
369 Has<NormalPrepass>,
370 Has<DepthPrepass>,
371 Has<MotionVectorPrepass>,
372 Has<DeferredPrepass>,
373 ),
374 Option<&ScreenSpaceTransmission>,
375 Has<TemporalJitter>,
376 Option<&Projection>,
377 Has<DistanceFog>,
378 (
379 Has<RenderViewLightProbes<EnvironmentMapLight>>,
380 Has<RenderViewLightProbes<IrradianceVolume>>,
381 ),
382 (
383 Has<OrderIndependentTransparencySettings>,
384 Has<ExtractedAtmosphere>,
385 Has<ScreenSpaceReflectionsUniform>,
386 Has<ViewContactShadowsUniformOffset>,
387 ),
388 )>,
389) {
390 for (
391 view,
392 camera,
393 msaa,
394 (tonemapping, dither),
395 shadow_filter_method,
396 ssao,
397 (normal_prepass, depth_prepass, motion_vector_prepass, deferred_prepass),
398 transmission,
399 temporal_jitter,
400 projection,
401 distance_fog,
402 (has_environment_maps, has_irradiance_volumes),
403 (has_oit, has_atmosphere, has_ssr, has_contact_shadows),
404 ) in views.iter_mut()
405 {
406 let mut view_key = MeshPipelineKey::from_msaa_samples(msaa.samples())
407 | MeshPipelineKey::from_target_format(view.target_format);
408
409 if normal_prepass {
410 view_key |= MeshPipelineKey::NORMAL_PREPASS;
411 }
412
413 if depth_prepass {
414 view_key |= MeshPipelineKey::DEPTH_PREPASS;
415 }
416
417 if motion_vector_prepass {
418 view_key |= MeshPipelineKey::MOTION_VECTOR_PREPASS;
419 }
420
421 if deferred_prepass {
422 view_key |= MeshPipelineKey::DEFERRED_PREPASS;
423 }
424
425 if temporal_jitter {
426 view_key |= MeshPipelineKey::TEMPORAL_JITTER;
427 }
428
429 if has_environment_maps {
430 view_key |= MeshPipelineKey::ENVIRONMENT_MAP;
431 }
432
433 if has_irradiance_volumes {
434 view_key |= MeshPipelineKey::IRRADIANCE_VOLUME;
435 }
436
437 if has_ssr {
438 view_key |= MeshPipelineKey::SCREEN_SPACE_REFLECTIONS;
439 }
440
441 if has_oit {
442 view_key |= MeshPipelineKey::OIT_ENABLED;
443 }
444
445 if has_atmosphere {
446 view_key |= MeshPipelineKey::ATMOSPHERE;
447 }
448
449 if has_contact_shadows {
450 view_key |= MeshPipelineKey::CONTACT_SHADOWS;
451 }
452
453 if view.invert_culling {
454 view_key |= MeshPipelineKey::INVERT_CULLING;
455 }
456
457 if let Some(projection) = projection {
458 view_key |= match projection {
459 Projection::Perspective(_) => MeshPipelineKey::VIEW_PROJECTION_PERSPECTIVE,
460 Projection::Orthographic(_) => MeshPipelineKey::VIEW_PROJECTION_ORTHOGRAPHIC,
461 Projection::Custom(_) => MeshPipelineKey::VIEW_PROJECTION_NONSTANDARD,
462 };
463 }
464
465 match shadow_filter_method.unwrap_or(&ShadowFilteringMethod::default()) {
466 ShadowFilteringMethod::Hardware2x2 => {
467 view_key |= MeshPipelineKey::SHADOW_FILTER_METHOD_HARDWARE_2X2;
468 }
469 ShadowFilteringMethod::Gaussian => {
470 view_key |= MeshPipelineKey::SHADOW_FILTER_METHOD_GAUSSIAN;
471 }
472 ShadowFilteringMethod::Temporal => {
473 view_key |= MeshPipelineKey::SHADOW_FILTER_METHOD_TEMPORAL;
474 }
475 }
476
477 if !camera.is_some_and(|camera| camera.hdr) {
478 if let Some(tonemapping) = tonemapping {
479 view_key |= MeshPipelineKey::TONEMAP_IN_SHADER;
480 view_key |= tonemapping_pipeline_key(*tonemapping);
481 }
482 if let Some(DebandDither::Enabled) = dither {
483 view_key |= MeshPipelineKey::DEBAND_DITHER;
484 }
485 }
486 if ssao {
487 view_key |= MeshPipelineKey::SCREEN_SPACE_AMBIENT_OCCLUSION;
488 }
489 if distance_fog {
490 view_key |= MeshPipelineKey::DISTANCE_FOG;
491 }
492 if let Some(transmission) = transmission {
493 view_key |= transmission.quality.pipeline_key();
494 }
495 if !view_key_cache
496 .get_mut(&view.retained_view_entity)
497 .is_some_and(|current_key| *current_key == view_key)
498 {
499 view_key_cache.insert(view.retained_view_entity, view_key);
500 dirty_specializations
501 .views
502 .insert(view.retained_view_entity);
503 }
504 }
505}
506
507#[derive(impl bevy_ecs::component::Component for MeshTransforms where
Self: ::core::marker::Send + ::core::marker::Sync + 'static {
const STORAGE_TYPE: bevy_ecs::component::StorageType =
bevy_ecs::component::StorageType::Table;
type Mutability = bevy_ecs::component::Mutable;
fn register_required_components(_requiree:
bevy_ecs::component::ComponentId,
required_components:
&mut bevy_ecs::component::RequiredComponentsRegistrator) {}
fn clone_behavior() -> bevy_ecs::component::ComponentCloneBehavior {
use bevy_ecs::component::{
DefaultCloneBehaviorBase, DefaultCloneBehaviorViaClone,
};
(&&&bevy_ecs::component::DefaultCloneBehaviorSpecialization::<Self>::default()).default_clone_behavior()
}
fn relationship_accessor()
->
::core::option::Option<bevy_ecs::relationship::ComponentRelationshipAccessor<Self>> {
::core::option::Option::None
}
}Component)]
508pub struct MeshTransforms {
509 pub world_from_local: Affine3,
510 pub previous_world_from_local: Affine3,
511 pub flags: u32,
512}
513
514#[derive(impl bevy_render::render_resource::encase::private::ShaderSize for MeshUniform
where
[Vec4; 3]: bevy_render::render_resource::encase::private::ShaderSize,
[Vec4; 3]: bevy_render::render_resource::encase::private::ShaderSize,
[Vec4; 2]: bevy_render::render_resource::encase::private::ShaderSize,
f32: bevy_render::render_resource::encase::private::ShaderSize,
u32: bevy_render::render_resource::encase::private::ShaderSize,
UVec2: bevy_render::render_resource::encase::private::ShaderSize,
u32: bevy_render::render_resource::encase::private::ShaderSize,
u32: bevy_render::render_resource::encase::private::ShaderSize,
u32: bevy_render::render_resource::encase::private::ShaderSize,
u32: bevy_render::render_resource::encase::private::ShaderSize,
u32: bevy_render::render_resource::encase::private::ShaderSize {}ShaderType, #[automatically_derived]
impl ::core::clone::Clone for MeshUniform {
#[inline]
fn clone(&self) -> MeshUniform {
MeshUniform {
world_from_local: ::core::clone::Clone::clone(&self.world_from_local),
previous_world_from_local: ::core::clone::Clone::clone(&self.previous_world_from_local),
local_from_world_transpose_a: ::core::clone::Clone::clone(&self.local_from_world_transpose_a),
local_from_world_transpose_b: ::core::clone::Clone::clone(&self.local_from_world_transpose_b),
flags: ::core::clone::Clone::clone(&self.flags),
lightmap_uv_rect: ::core::clone::Clone::clone(&self.lightmap_uv_rect),
first_vertex_index: ::core::clone::Clone::clone(&self.first_vertex_index),
current_skin_index: ::core::clone::Clone::clone(&self.current_skin_index),
material_and_lightmap_bind_group_slot: ::core::clone::Clone::clone(&self.material_and_lightmap_bind_group_slot),
tag: ::core::clone::Clone::clone(&self.tag),
morph_descriptor_index: ::core::clone::Clone::clone(&self.morph_descriptor_index),
}
}
}Clone)]
515pub struct MeshUniform {
516 pub world_from_local: [Vec4; 3],
518 pub previous_world_from_local: [Vec4; 3],
519 pub local_from_world_transpose_a: [Vec4; 2],
524 pub local_from_world_transpose_b: f32,
525 pub flags: u32,
526 pub lightmap_uv_rect: UVec2,
536 pub first_vertex_index: u32,
542 pub current_skin_index: u32,
544 pub material_and_lightmap_bind_group_slot: u32,
549 pub tag: u32,
551 pub morph_descriptor_index: u32,
556}
557
558#[derive(impl bevy_render::render_resource::encase::private::ShaderSize for
MeshInputUniform where
[Vec4; 3]: bevy_render::render_resource::encase::private::ShaderSize,
UVec2: bevy_render::render_resource::encase::private::ShaderSize,
u32: bevy_render::render_resource::encase::private::ShaderSize,
u32: bevy_render::render_resource::encase::private::ShaderSize,
u32: bevy_render::render_resource::encase::private::ShaderSize,
u32: bevy_render::render_resource::encase::private::ShaderSize,
u32: bevy_render::render_resource::encase::private::ShaderSize,
u32: bevy_render::render_resource::encase::private::ShaderSize,
u32: bevy_render::render_resource::encase::private::ShaderSize,
u32: bevy_render::render_resource::encase::private::ShaderSize,
u32: bevy_render::render_resource::encase::private::ShaderSize,
u32: bevy_render::render_resource::encase::private::ShaderSize {}ShaderType, unsafe impl ::bytemuck::Pod for MeshInputUniform {}Pod, unsafe impl ::bytemuck::Zeroable for MeshInputUniform {}Zeroable, #[automatically_derived]
impl ::core::clone::Clone for MeshInputUniform {
#[inline]
fn clone(&self) -> MeshInputUniform {
let _: ::core::clone::AssertParamIsClone<[Vec4; 3]>;
let _: ::core::clone::AssertParamIsClone<UVec2>;
let _: ::core::clone::AssertParamIsClone<u32>;
*self
}
}Clone, #[automatically_derived]
impl ::core::marker::Copy for MeshInputUniform { }Copy, #[automatically_derived]
impl ::core::default::Default for MeshInputUniform {
#[inline]
fn default() -> MeshInputUniform {
MeshInputUniform {
world_from_local: ::core::default::Default::default(),
lightmap_uv_rect: ::core::default::Default::default(),
flags: ::core::default::Default::default(),
previous_input_index: ::core::default::Default::default(),
first_vertex_index: ::core::default::Default::default(),
first_index_index: ::core::default::Default::default(),
index_count: ::core::default::Default::default(),
current_skin_index: ::core::default::Default::default(),
material_and_lightmap_bind_group_slot: ::core::default::Default::default(),
timestamp: ::core::default::Default::default(),
tag: ::core::default::Default::default(),
morph_descriptor_index: ::core::default::Default::default(),
}
}
}Default, #[automatically_derived]
impl ::core::fmt::Debug for MeshInputUniform {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
let names: &'static _ =
&["world_from_local", "lightmap_uv_rect", "flags",
"previous_input_index", "first_vertex_index",
"first_index_index", "index_count", "current_skin_index",
"material_and_lightmap_bind_group_slot", "timestamp", "tag",
"morph_descriptor_index"];
let values: &[&dyn ::core::fmt::Debug] =
&[&self.world_from_local, &self.lightmap_uv_rect, &self.flags,
&self.previous_input_index, &self.first_vertex_index,
&self.first_index_index, &self.index_count,
&self.current_skin_index,
&self.material_and_lightmap_bind_group_slot,
&self.timestamp, &self.tag, &&self.morph_descriptor_index];
::core::fmt::Formatter::debug_struct_fields_finish(f,
"MeshInputUniform", names, values)
}
}Debug)]
563#[repr(C)]
564pub struct MeshInputUniform {
565 pub world_from_local: [Vec4; 3],
567 pub lightmap_uv_rect: UVec2,
579 pub flags: u32,
581 pub previous_input_index: u32,
586 pub first_vertex_index: u32,
592 pub first_index_index: u32,
600 pub index_count: u32,
603 pub current_skin_index: u32,
605 pub material_and_lightmap_bind_group_slot: u32,
610 pub timestamp: u32,
618 pub tag: u32,
620 pub morph_descriptor_index: u32,
625}
626
627#[repr(transparent)]
pub struct MeshInputUniformBlob(pub [::core::sync::atomic::AtomicU32; ::core::mem::size_of::<MeshInputUniform>()
/ 4]);
#[automatically_derived]
impl ::core::default::Default for MeshInputUniformBlob {
#[inline]
fn default() -> MeshInputUniformBlob {
MeshInputUniformBlob(::core::default::Default::default())
}
}
impl ::core::ops::Deref for MeshInputUniformBlob {
type Target =
[::core::sync::atomic::AtomicU32; ::core::mem::size_of::<MeshInputUniform>()
/ 4];
fn deref(&self) -> &Self::Target { &self.0 }
}
impl ::core::ops::DerefMut for MeshInputUniformBlob {
fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 }
}
impl ::bevy_render::render_resource::AtomicPod for MeshInputUniform {
type Blob = MeshInputUniformBlob;
fn read_from_blob(blob: &Self::Blob) -> Self {
const _ASSERT_POD_TYPE_SIZE: () =
if !(::core::mem::size_of::<MeshInputUniform>() % 4 == 0) {
::core::panicking::panic("assertion failed: ::core::mem::size_of::<MeshInputUniform>() % 4 == 0")
};
let nonatomic_data:
[u32; ::core::mem::size_of::<MeshInputUniform>() / 4] =
::core::array::from_fn(|i|
{
blob.0[i].load(::bevy_platform::sync::atomic::Ordering::Relaxed)
});
::bytemuck::must_cast(nonatomic_data)
}
fn write_to_blob(&self, blob: &Self::Blob) {
let src: [u32; ::core::mem::size_of::<MeshInputUniform>() / 4] =
::bytemuck::must_cast(*self);
for (dest, src) in blob.0.iter().zip(src.iter()) {
dest.store(*src,
::bevy_platform::sync::atomic::Ordering::Relaxed);
}
}
}
unsafe impl ::bevy_render::render_resource::AtomicPodBlob for
MeshInputUniformBlob {}
impl<'a> ::core::convert::From<&'a MeshInputUniform> for MeshInputUniformBlob
{
fn from(pod: &'a MeshInputUniform) -> Self {
let blob = Self::default();
pod.write_to_blob(&blob);
blob
}
}
impl MeshInputUniformBlob {}impl_atomic_pod!(MeshInputUniform, MeshInputUniformBlob);
628
629#[derive(impl bevy_render::render_resource::encase::private::ShaderSize for
MeshCullingData where
Vec4: bevy_render::render_resource::encase::private::ShaderSize,
Vec4: bevy_render::render_resource::encase::private::ShaderSize {}ShaderType, unsafe impl ::bytemuck::Pod for MeshCullingData {}Pod, unsafe impl ::bytemuck::Zeroable for MeshCullingData {}Zeroable, #[automatically_derived]
impl ::core::clone::Clone for MeshCullingData {
#[inline]
fn clone(&self) -> MeshCullingData {
let _: ::core::clone::AssertParamIsClone<Vec4>;
*self
}
}Clone, #[automatically_derived]
impl ::core::marker::Copy for MeshCullingData { }Copy, #[automatically_derived]
impl ::core::default::Default for MeshCullingData {
#[inline]
fn default() -> MeshCullingData {
MeshCullingData {
aabb_center: ::core::default::Default::default(),
aabb_half_extents: ::core::default::Default::default(),
}
}
}Default)]
633#[repr(C)]
634pub struct MeshCullingData {
635 pub aabb_center: Vec4,
638 pub aabb_half_extents: Vec4,
641}
642
643#[derive(impl bevy_ecs::resource::Resource for MeshCullingDataBuffer where
Self: ::core::marker::Send + ::core::marker::Sync + 'static {}Resource, impl ::core::ops::Deref for MeshCullingDataBuffer {
type Target = AtomicSparseBufferVec<MeshCullingData>;
fn deref(&self) -> &Self::Target { &self.0 }
}Deref, impl ::core::ops::DerefMut for MeshCullingDataBuffer {
fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 }
}DerefMut)]
650pub struct MeshCullingDataBuffer(AtomicSparseBufferVec<MeshCullingData>);
651
652#[repr(transparent)]
pub struct MeshCullingDataBlob(pub [::core::sync::atomic::AtomicU32; ::core::mem::size_of::<MeshCullingData>()
/ 4]);
#[automatically_derived]
impl ::core::default::Default for MeshCullingDataBlob {
#[inline]
fn default() -> MeshCullingDataBlob {
MeshCullingDataBlob(::core::default::Default::default())
}
}
impl ::core::ops::Deref for MeshCullingDataBlob {
type Target =
[::core::sync::atomic::AtomicU32; ::core::mem::size_of::<MeshCullingData>()
/ 4];
fn deref(&self) -> &Self::Target { &self.0 }
}
impl ::core::ops::DerefMut for MeshCullingDataBlob {
fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 }
}
impl ::bevy_render::render_resource::AtomicPod for MeshCullingData {
type Blob = MeshCullingDataBlob;
fn read_from_blob(blob: &Self::Blob) -> Self {
const _ASSERT_POD_TYPE_SIZE: () =
if !(::core::mem::size_of::<MeshCullingData>() % 4 == 0) {
::core::panicking::panic("assertion failed: ::core::mem::size_of::<MeshCullingData>() % 4 == 0")
};
let nonatomic_data:
[u32; ::core::mem::size_of::<MeshCullingData>() / 4] =
::core::array::from_fn(|i|
{
blob.0[i].load(::bevy_platform::sync::atomic::Ordering::Relaxed)
});
::bytemuck::must_cast(nonatomic_data)
}
fn write_to_blob(&self, blob: &Self::Blob) {
let src: [u32; ::core::mem::size_of::<MeshCullingData>() / 4] =
::bytemuck::must_cast(*self);
for (dest, src) in blob.0.iter().zip(src.iter()) {
dest.store(*src,
::bevy_platform::sync::atomic::Ordering::Relaxed);
}
}
}
unsafe impl ::bevy_render::render_resource::AtomicPodBlob for
MeshCullingDataBlob {}
impl<'a> ::core::convert::From<&'a MeshCullingData> for MeshCullingDataBlob {
fn from(pod: &'a MeshCullingData) -> Self {
let blob = Self::default();
pod.write_to_blob(&blob);
blob
}
}
impl MeshCullingDataBlob {}impl_atomic_pod!(MeshCullingData, MeshCullingDataBlob);
653
654impl MeshUniform {
655 pub fn new(
656 mesh_transforms: &MeshTransforms,
657 first_vertex_index: u32,
658 material_bind_group_slot: MaterialBindGroupSlot,
659 maybe_lightmap: Option<(LightmapSlotIndex, Rect)>,
660 current_skin_index: Option<u32>,
661 morph_descriptor_index: Option<MorphDescriptorIndex>,
662 tag: Option<u32>,
663 ) -> Self {
664 let (local_from_world_transpose_a, local_from_world_transpose_b) =
665 mesh_transforms.world_from_local.inverse_transpose_3x3();
666 let lightmap_bind_group_slot = match maybe_lightmap {
667 None => u16::MAX,
668 Some((slot_index, _)) => slot_index.into(),
669 };
670
671 let material_slot = u32::from(material_bind_group_slot);
672 if true {
if !(material_slot <= 0xFFFF) {
{
::core::panicking::panic_fmt(format_args!("Material bind group slot {0} overflowed",
material_slot));
}
};
};debug_assert!(
673 material_slot <= 0xFFFF,
674 "Material bind group slot {material_slot} overflowed"
675 );
676 let material_and_lightmap_bind_group_slot =
677 material_slot | ((lightmap_bind_group_slot as u32) << 16);
678
679 Self {
680 world_from_local: mesh_transforms.world_from_local.to_transpose(),
681 previous_world_from_local: mesh_transforms.previous_world_from_local.to_transpose(),
682 lightmap_uv_rect: pack_lightmap_uv_rect(maybe_lightmap.map(|(_, uv_rect)| uv_rect)),
683 local_from_world_transpose_a,
684 local_from_world_transpose_b,
685 flags: mesh_transforms.flags,
686 first_vertex_index,
687 current_skin_index: current_skin_index.unwrap_or(u32::MAX),
688 material_and_lightmap_bind_group_slot,
689 tag: tag.unwrap_or(0),
690 morph_descriptor_index: match morph_descriptor_index {
691 Some(morph_descriptor_index) => morph_descriptor_index.0,
692 None => u32::MAX,
693 },
694 }
695 }
696}
697
698#[doc = r" Various flags and tightly-packed values on a mesh."]
#[doc = r""]
#[doc =
r" Flags grow from the top bit down; other values grow from the bottom bit"]
#[doc = r" up."]
#[repr(transparent)]
pub struct MeshFlags(<MeshFlags as
::bitflags::__private::PublicFlags>::Internal);
#[allow(dead_code, deprecated, unused_doc_comments, unused_attributes,
unused_mut, unused_imports, non_upper_case_globals, clippy :: min_ident_chars,
clippy :: assign_op_pattern, clippy :: indexing_slicing, clippy ::
same_name_method, clippy :: iter_without_into_iter,)]
const _: () =
{
#[repr(transparent)]
pub struct InternalBitFlags(u32);
#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for InternalBitFlags { }
#[automatically_derived]
impl ::core::clone::Clone for InternalBitFlags {
#[inline]
fn clone(&self) -> InternalBitFlags {
let _: ::core::clone::AssertParamIsClone<u32>;
*self
}
}
#[automatically_derived]
impl ::core::marker::Copy for InternalBitFlags { }
#[automatically_derived]
impl ::core::marker::StructuralPartialEq for InternalBitFlags { }
#[automatically_derived]
impl ::core::cmp::PartialEq for InternalBitFlags {
#[inline]
fn eq(&self, other: &InternalBitFlags) -> bool {
self.0 == other.0
}
}
#[automatically_derived]
impl ::core::cmp::Eq for InternalBitFlags {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<u32>;
}
}
#[automatically_derived]
impl ::core::cmp::PartialOrd for InternalBitFlags {
#[inline]
fn partial_cmp(&self, other: &InternalBitFlags)
-> ::core::option::Option<::core::cmp::Ordering> {
::core::option::Option::Some(::core::cmp::Ord::cmp(self,
other))
}
}
#[automatically_derived]
impl ::core::cmp::Ord for InternalBitFlags {
#[inline]
fn cmp(&self, other: &InternalBitFlags) -> ::core::cmp::Ordering {
::core::cmp::Ord::cmp(&self.0, &other.0)
}
}
#[automatically_derived]
impl ::core::hash::Hash for InternalBitFlags {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.0, state)
}
}
impl MeshFlags {
#[doc = r" Bitmask for the 16-bit index into the LOD array."]
#[doc = r""]
#[doc = r" This will be `u16::MAX` if this mesh has no LOD."]
pub const LOD_INDEX_MASK: Self =
Self::from_bits_retain((1 << 16) - 1);
#[doc =
r" Whether visibility ranges use the center of the AABB to compute"]
#[doc = r" distance from the camera."]
#[doc = r""]
#[doc =
r" If false, this uses distance from the world-space translation of the"]
#[doc = r" mesh instead."]
pub const AABB_BASED_VISIBILITY_RANGE: Self =
Self::from_bits_retain(1 << 27);
#[doc = r" Disables frustum culling for this mesh."]
#[doc = r""]
#[doc = r" This corresponds to the"]
#[doc =
r" [`bevy_render::view::visibility::NoFrustumCulling`] component."]
pub const NO_FRUSTUM_CULLING: Self =
Self::from_bits_retain(1 << 28);
pub const SHADOW_RECEIVER: Self = Self::from_bits_retain(1 << 29);
pub const TRANSMITTED_SHADOW_RECEIVER: Self =
Self::from_bits_retain(1 << 30);
pub const SIGN_DETERMINANT_MODEL_3X3: Self =
Self::from_bits_retain(1 << 31);
pub const NONE: Self = Self::from_bits_retain(0);
pub const UNINITIALIZED: Self =
Self::from_bits_retain(0xFFFFFFFF);
}
impl ::bitflags::Flags for MeshFlags {
const FLAGS: &'static [::bitflags::Flag<MeshFlags>] =
{
mod __bitflags_flag_names {
use super::*;
pub(super) const LOD_INDEX_MASK: &'static str =
"LOD_INDEX_MASK";
pub(super) const AABB_BASED_VISIBILITY_RANGE: &'static str =
"AABB_BASED_VISIBILITY_RANGE";
pub(super) const NO_FRUSTUM_CULLING: &'static str =
"NO_FRUSTUM_CULLING";
pub(super) const SHADOW_RECEIVER: &'static str =
"SHADOW_RECEIVER";
pub(super) const TRANSMITTED_SHADOW_RECEIVER: &'static str =
"TRANSMITTED_SHADOW_RECEIVER";
pub(super) const SIGN_DETERMINANT_MODEL_3X3: &'static str =
"SIGN_DETERMINANT_MODEL_3X3";
pub(super) const NONE: &'static str = "NONE";
pub(super) const UNINITIALIZED: &'static str =
"UNINITIALIZED";
}
&[{
::bitflags::Flag::new(__bitflags_flag_names::LOD_INDEX_MASK,
MeshFlags::LOD_INDEX_MASK)
},
{
::bitflags::Flag::new(__bitflags_flag_names::AABB_BASED_VISIBILITY_RANGE,
MeshFlags::AABB_BASED_VISIBILITY_RANGE)
},
{
::bitflags::Flag::new(__bitflags_flag_names::NO_FRUSTUM_CULLING,
MeshFlags::NO_FRUSTUM_CULLING)
},
{
::bitflags::Flag::new(__bitflags_flag_names::SHADOW_RECEIVER,
MeshFlags::SHADOW_RECEIVER)
},
{
::bitflags::Flag::new(__bitflags_flag_names::TRANSMITTED_SHADOW_RECEIVER,
MeshFlags::TRANSMITTED_SHADOW_RECEIVER)
},
{
::bitflags::Flag::new(__bitflags_flag_names::SIGN_DETERMINANT_MODEL_3X3,
MeshFlags::SIGN_DETERMINANT_MODEL_3X3)
},
{
::bitflags::Flag::new(__bitflags_flag_names::NONE,
MeshFlags::NONE)
},
{
::bitflags::Flag::new(__bitflags_flag_names::UNINITIALIZED,
MeshFlags::UNINITIALIZED)
}]
};
type Bits = u32;
fn bits(&self) -> u32 { MeshFlags::bits(self) }
fn from_bits_retain(bits: u32) -> MeshFlags {
MeshFlags::from_bits_retain(bits)
}
fn all_named() -> MeshFlags {
const ALL_NAMED: u32 =
{
let mut truncated = <u32 as ::bitflags::Bits>::EMPTY;
let mut i = 0;
{
{
let flag = &<MeshFlags as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag = &<MeshFlags as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag = &<MeshFlags as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag = &<MeshFlags as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag = &<MeshFlags as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag = &<MeshFlags as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag = &<MeshFlags as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag = &<MeshFlags as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
let _ = i;
truncated
};
MeshFlags::from_bits_retain(ALL_NAMED)
}
}
impl ::bitflags::__private::PublicFlags for MeshFlags {
type Primitive = u32;
type Internal = InternalBitFlags;
}
impl ::bitflags::__private::core::default::Default for
InternalBitFlags {
#[inline]
fn default() -> Self { InternalBitFlags::empty() }
}
impl ::bitflags::__private::core::fmt::Debug for InternalBitFlags {
fn fmt(&self,
f: &mut ::bitflags::__private::core::fmt::Formatter<'_>)
-> ::bitflags::__private::core::fmt::Result {
if self.is_empty() {
f.write_fmt(format_args!("{0:#x}",
<u32 as ::bitflags::Bits>::EMPTY))
} else {
::bitflags::__private::core::fmt::Display::fmt(self, f)
}
}
}
impl ::bitflags::__private::core::fmt::Display for InternalBitFlags {
fn fmt(&self,
f: &mut ::bitflags::__private::core::fmt::Formatter<'_>)
-> ::bitflags::__private::core::fmt::Result {
::bitflags::parser::to_writer(&MeshFlags(*self), f)
}
}
impl ::bitflags::__private::core::str::FromStr for InternalBitFlags {
type Err = ::bitflags::parser::ParseError;
fn from_str(s: &str)
->
::bitflags::__private::core::result::Result<Self,
Self::Err> {
::bitflags::parser::from_str::<MeshFlags>(s).map(|flags|
flags.0)
}
}
impl ::bitflags::__private::core::convert::AsRef<u32> for
InternalBitFlags {
fn as_ref(&self) -> &u32 { &self.0 }
}
impl ::bitflags::__private::core::convert::From<u32> for
InternalBitFlags {
fn from(bits: u32) -> Self { Self::from_bits_retain(bits) }
}
impl InternalBitFlags {
#[inline]
pub const fn empty() -> Self {
Self(<u32 as ::bitflags::Bits>::EMPTY)
}
#[inline]
pub const fn all() -> Self {
let mut truncated = <u32 as ::bitflags::Bits>::EMPTY;
let mut i = 0;
{
{
let flag =
<MeshFlags as ::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshFlags as ::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshFlags as ::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshFlags as ::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshFlags as ::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshFlags as ::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshFlags as ::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshFlags as ::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
let _ = i;
Self(truncated)
}
#[inline]
pub const fn bits(&self) -> u32 { self.0 }
#[inline]
pub const fn from_bits(bits: u32)
-> ::bitflags::__private::core::option::Option<Self> {
let truncated = Self::from_bits_truncate(bits).0;
if truncated == bits {
::bitflags::__private::core::option::Option::Some(Self(bits))
} else { ::bitflags::__private::core::option::Option::None }
}
#[inline]
pub const fn from_bits_truncate(bits: u32) -> Self {
Self(bits & Self::all().0)
}
#[inline]
pub const fn from_bits_retain(bits: u32) -> Self { Self(bits) }
#[inline]
pub fn from_name(name: &str)
-> ::bitflags::__private::core::option::Option<Self> {
mod __bitflags_flag_names {
use super::*;
pub(super) const LOD_INDEX_MASK: &'static str =
"LOD_INDEX_MASK";
pub(super) const AABB_BASED_VISIBILITY_RANGE: &'static str =
"AABB_BASED_VISIBILITY_RANGE";
pub(super) const NO_FRUSTUM_CULLING: &'static str =
"NO_FRUSTUM_CULLING";
pub(super) const SHADOW_RECEIVER: &'static str =
"SHADOW_RECEIVER";
pub(super) const TRANSMITTED_SHADOW_RECEIVER: &'static str =
"TRANSMITTED_SHADOW_RECEIVER";
pub(super) const SIGN_DETERMINANT_MODEL_3X3: &'static str =
"SIGN_DETERMINANT_MODEL_3X3";
pub(super) const NONE: &'static str = "NONE";
pub(super) const UNINITIALIZED: &'static str =
"UNINITIALIZED";
}
{
{
if name == __bitflags_flag_names::LOD_INDEX_MASK {
return ::bitflags::__private::core::option::Option::Some(Self(MeshFlags::LOD_INDEX_MASK.bits()));
}
};
};
{
{
if name ==
__bitflags_flag_names::AABB_BASED_VISIBILITY_RANGE {
return ::bitflags::__private::core::option::Option::Some(Self(MeshFlags::AABB_BASED_VISIBILITY_RANGE.bits()));
}
};
};
{
{
if name == __bitflags_flag_names::NO_FRUSTUM_CULLING {
return ::bitflags::__private::core::option::Option::Some(Self(MeshFlags::NO_FRUSTUM_CULLING.bits()));
}
};
};
{
{
if name == __bitflags_flag_names::SHADOW_RECEIVER {
return ::bitflags::__private::core::option::Option::Some(Self(MeshFlags::SHADOW_RECEIVER.bits()));
}
};
};
{
{
if name ==
__bitflags_flag_names::TRANSMITTED_SHADOW_RECEIVER {
return ::bitflags::__private::core::option::Option::Some(Self(MeshFlags::TRANSMITTED_SHADOW_RECEIVER.bits()));
}
};
};
{
{
if name == __bitflags_flag_names::SIGN_DETERMINANT_MODEL_3X3
{
return ::bitflags::__private::core::option::Option::Some(Self(MeshFlags::SIGN_DETERMINANT_MODEL_3X3.bits()));
}
};
};
{
{
if name == __bitflags_flag_names::NONE {
return ::bitflags::__private::core::option::Option::Some(Self(MeshFlags::NONE.bits()));
}
};
};
{
{
if name == __bitflags_flag_names::UNINITIALIZED {
return ::bitflags::__private::core::option::Option::Some(Self(MeshFlags::UNINITIALIZED.bits()));
}
};
};
let _ = name;
::bitflags::__private::core::option::Option::None
}
#[inline]
pub const fn is_empty(&self) -> bool {
self.0 == <u32 as ::bitflags::Bits>::EMPTY
}
#[inline]
pub const fn is_all(&self) -> bool {
Self::all().0 | self.0 == self.0
}
#[inline]
pub const fn intersects(&self, other: Self) -> bool {
self.0 & other.0 != <u32 as ::bitflags::Bits>::EMPTY
}
#[inline]
pub const fn contains(&self, other: Self) -> bool {
self.0 & other.0 == other.0
}
#[inline]
pub fn insert(&mut self, other: Self) {
*self = Self(self.0).union(other);
}
#[inline]
pub fn remove(&mut self, other: Self) {
*self = Self(self.0).difference(other);
}
#[inline]
pub fn toggle(&mut self, other: Self) {
*self = Self(self.0).symmetric_difference(other);
}
#[inline]
pub fn set(&mut self, other: Self, value: bool) {
if value { self.insert(other); } else { self.remove(other); }
}
#[inline]
#[must_use]
pub const fn intersection(self, other: Self) -> Self {
Self(self.0 & other.0)
}
#[inline]
#[must_use]
pub const fn union(self, other: Self) -> Self {
Self(self.0 | other.0)
}
#[inline]
#[must_use]
pub const fn difference(self, other: Self) -> Self {
Self(self.0 & !other.0)
}
#[inline]
#[must_use]
pub const fn symmetric_difference(self, other: Self) -> Self {
Self(self.0 ^ other.0)
}
#[inline]
#[must_use]
pub const fn complement(self) -> Self {
Self::from_bits_truncate(!self.0)
}
}
impl ::bitflags::__private::core::fmt::Binary for InternalBitFlags {
fn fmt(&self, f: &mut ::bitflags::__private::core::fmt::Formatter)
-> ::bitflags::__private::core::fmt::Result {
let inner = self.0;
::bitflags::__private::core::fmt::Binary::fmt(&inner, f)
}
}
impl ::bitflags::__private::core::fmt::Octal for InternalBitFlags {
fn fmt(&self, f: &mut ::bitflags::__private::core::fmt::Formatter)
-> ::bitflags::__private::core::fmt::Result {
let inner = self.0;
::bitflags::__private::core::fmt::Octal::fmt(&inner, f)
}
}
impl ::bitflags::__private::core::fmt::LowerHex for InternalBitFlags {
fn fmt(&self, f: &mut ::bitflags::__private::core::fmt::Formatter)
-> ::bitflags::__private::core::fmt::Result {
let inner = self.0;
::bitflags::__private::core::fmt::LowerHex::fmt(&inner, f)
}
}
impl ::bitflags::__private::core::fmt::UpperHex for InternalBitFlags {
fn fmt(&self, f: &mut ::bitflags::__private::core::fmt::Formatter)
-> ::bitflags::__private::core::fmt::Result {
let inner = self.0;
::bitflags::__private::core::fmt::UpperHex::fmt(&inner, f)
}
}
impl ::bitflags::__private::core::ops::BitOr for InternalBitFlags {
type Output = Self;
#[inline]
fn bitor(self, other: InternalBitFlags) -> Self {
self.union(other)
}
}
impl ::bitflags::__private::core::ops::BitOrAssign for
InternalBitFlags {
#[inline]
fn bitor_assign(&mut self, other: Self) { self.insert(other); }
}
impl ::bitflags::__private::core::ops::BitXor for InternalBitFlags {
type Output = Self;
#[inline]
fn bitxor(self, other: Self) -> Self {
self.symmetric_difference(other)
}
}
impl ::bitflags::__private::core::ops::BitXorAssign for
InternalBitFlags {
#[inline]
fn bitxor_assign(&mut self, other: Self) { self.toggle(other); }
}
impl ::bitflags::__private::core::ops::BitAnd for InternalBitFlags {
type Output = Self;
#[inline]
fn bitand(self, other: Self) -> Self { self.intersection(other) }
}
impl ::bitflags::__private::core::ops::BitAndAssign for
InternalBitFlags {
#[inline]
fn bitand_assign(&mut self, other: Self) {
*self =
Self::from_bits_retain(self.bits()).intersection(other);
}
}
impl ::bitflags::__private::core::ops::Sub for InternalBitFlags {
type Output = Self;
#[inline]
fn sub(self, other: Self) -> Self { self.difference(other) }
}
impl ::bitflags::__private::core::ops::SubAssign for InternalBitFlags
{
#[inline]
fn sub_assign(&mut self, other: Self) { self.remove(other); }
}
impl ::bitflags::__private::core::ops::Not for InternalBitFlags {
type Output = Self;
#[inline]
fn not(self) -> Self { self.complement() }
}
impl ::bitflags::__private::core::iter::Extend<InternalBitFlags> for
InternalBitFlags {
fn extend<T: ::bitflags::__private::core::iter::IntoIterator<Item
= Self>>(&mut self, iterator: T) {
for item in iterator { self.insert(item) }
}
}
impl ::bitflags::__private::core::iter::FromIterator<InternalBitFlags>
for InternalBitFlags {
fn from_iter<T: ::bitflags::__private::core::iter::IntoIterator<Item
= Self>>(iterator: T) -> Self {
use ::bitflags::__private::core::iter::Extend;
let mut result = Self::empty();
result.extend(iterator);
result
}
}
impl InternalBitFlags {
#[inline]
pub const fn iter(&self) -> ::bitflags::iter::Iter<MeshFlags> {
::bitflags::iter::Iter::__private_const_new(<MeshFlags as
::bitflags::Flags>::FLAGS,
MeshFlags::from_bits_retain(self.bits()),
MeshFlags::from_bits_retain(self.bits()))
}
#[inline]
pub const fn iter_names(&self)
-> ::bitflags::iter::IterNames<MeshFlags> {
::bitflags::iter::IterNames::__private_const_new(<MeshFlags as
::bitflags::Flags>::FLAGS,
MeshFlags::from_bits_retain(self.bits()),
MeshFlags::from_bits_retain(self.bits()))
}
}
impl ::bitflags::__private::core::iter::IntoIterator for
InternalBitFlags {
type Item = MeshFlags;
type IntoIter = ::bitflags::iter::Iter<MeshFlags>;
fn into_iter(self) -> Self::IntoIter { self.iter() }
}
impl InternalBitFlags {
#[inline]
pub fn bits_mut(&mut self) -> &mut u32 { &mut self.0 }
}
impl ::bitflags::__private::serde::Serialize for InternalBitFlags {
fn serialize<S: ::bitflags::__private::serde::Serializer>(&self,
serializer: S)
->
::bitflags::__private::core::result::Result<S::Ok,
S::Error> {
::bitflags::serde::serialize(&MeshFlags::from_bits_retain(self.bits()),
serializer)
}
}
impl<'de> ::bitflags::__private::serde::Deserialize<'de> for
InternalBitFlags {
fn deserialize<D: ::bitflags::__private::serde::Deserializer<'de>>(deserializer:
D)
->
::bitflags::__private::core::result::Result<Self,
D::Error> {
let flags: MeshFlags =
::bitflags::serde::deserialize(deserializer)?;
::bitflags::__private::core::result::Result::Ok(flags.0)
}
}
unsafe impl ::bitflags::__private::bytemuck::Pod for InternalBitFlags
where u32: ::bitflags::__private::bytemuck::Pod {}
unsafe impl ::bitflags::__private::bytemuck::Zeroable for
InternalBitFlags where
u32: ::bitflags::__private::bytemuck::Zeroable {}
impl MeshFlags {
#[inline]
pub const fn empty() -> Self { Self(InternalBitFlags::empty()) }
#[inline]
pub const fn all() -> Self { Self(InternalBitFlags::all()) }
#[inline]
pub const fn bits(&self) -> u32 { self.0.bits() }
#[inline]
pub const fn from_bits(bits: u32)
-> ::bitflags::__private::core::option::Option<Self> {
match InternalBitFlags::from_bits(bits) {
::bitflags::__private::core::option::Option::Some(bits) =>
::bitflags::__private::core::option::Option::Some(Self(bits)),
::bitflags::__private::core::option::Option::None =>
::bitflags::__private::core::option::Option::None,
}
}
#[inline]
pub const fn from_bits_truncate(bits: u32) -> Self {
Self(InternalBitFlags::from_bits_truncate(bits))
}
#[inline]
pub const fn from_bits_retain(bits: u32) -> Self {
Self(InternalBitFlags::from_bits_retain(bits))
}
#[inline]
pub fn from_name(name: &str)
-> ::bitflags::__private::core::option::Option<Self> {
match InternalBitFlags::from_name(name) {
::bitflags::__private::core::option::Option::Some(bits) =>
::bitflags::__private::core::option::Option::Some(Self(bits)),
::bitflags::__private::core::option::Option::None =>
::bitflags::__private::core::option::Option::None,
}
}
#[inline]
pub const fn is_empty(&self) -> bool { self.0.is_empty() }
#[inline]
pub const fn is_all(&self) -> bool { self.0.is_all() }
#[inline]
pub const fn intersects(&self, other: Self) -> bool {
self.0.intersects(other.0)
}
#[inline]
pub const fn contains(&self, other: Self) -> bool {
self.0.contains(other.0)
}
#[inline]
pub fn insert(&mut self, other: Self) { self.0.insert(other.0) }
#[inline]
pub fn remove(&mut self, other: Self) { self.0.remove(other.0) }
#[inline]
pub fn toggle(&mut self, other: Self) { self.0.toggle(other.0) }
#[inline]
pub fn set(&mut self, other: Self, value: bool) {
self.0.set(other.0, value)
}
#[inline]
#[must_use]
pub const fn intersection(self, other: Self) -> Self {
Self(self.0.intersection(other.0))
}
#[inline]
#[must_use]
pub const fn union(self, other: Self) -> Self {
Self(self.0.union(other.0))
}
#[inline]
#[must_use]
pub const fn difference(self, other: Self) -> Self {
Self(self.0.difference(other.0))
}
#[inline]
#[must_use]
pub const fn symmetric_difference(self, other: Self) -> Self {
Self(self.0.symmetric_difference(other.0))
}
#[inline]
#[must_use]
pub const fn complement(self) -> Self {
Self(self.0.complement())
}
}
impl ::bitflags::__private::core::fmt::Binary for MeshFlags {
fn fmt(&self, f: &mut ::bitflags::__private::core::fmt::Formatter)
-> ::bitflags::__private::core::fmt::Result {
let inner = self.0;
::bitflags::__private::core::fmt::Binary::fmt(&inner, f)
}
}
impl ::bitflags::__private::core::fmt::Octal for MeshFlags {
fn fmt(&self, f: &mut ::bitflags::__private::core::fmt::Formatter)
-> ::bitflags::__private::core::fmt::Result {
let inner = self.0;
::bitflags::__private::core::fmt::Octal::fmt(&inner, f)
}
}
impl ::bitflags::__private::core::fmt::LowerHex for MeshFlags {
fn fmt(&self, f: &mut ::bitflags::__private::core::fmt::Formatter)
-> ::bitflags::__private::core::fmt::Result {
let inner = self.0;
::bitflags::__private::core::fmt::LowerHex::fmt(&inner, f)
}
}
impl ::bitflags::__private::core::fmt::UpperHex for MeshFlags {
fn fmt(&self, f: &mut ::bitflags::__private::core::fmt::Formatter)
-> ::bitflags::__private::core::fmt::Result {
let inner = self.0;
::bitflags::__private::core::fmt::UpperHex::fmt(&inner, f)
}
}
impl ::bitflags::__private::core::ops::BitOr for MeshFlags {
type Output = Self;
#[inline]
fn bitor(self, other: MeshFlags) -> Self { self.union(other) }
}
impl ::bitflags::__private::core::ops::BitOrAssign for MeshFlags {
#[inline]
fn bitor_assign(&mut self, other: Self) { self.insert(other); }
}
impl ::bitflags::__private::core::ops::BitXor for MeshFlags {
type Output = Self;
#[inline]
fn bitxor(self, other: Self) -> Self {
self.symmetric_difference(other)
}
}
impl ::bitflags::__private::core::ops::BitXorAssign for MeshFlags {
#[inline]
fn bitxor_assign(&mut self, other: Self) { self.toggle(other); }
}
impl ::bitflags::__private::core::ops::BitAnd for MeshFlags {
type Output = Self;
#[inline]
fn bitand(self, other: Self) -> Self { self.intersection(other) }
}
impl ::bitflags::__private::core::ops::BitAndAssign for MeshFlags {
#[inline]
fn bitand_assign(&mut self, other: Self) {
*self =
Self::from_bits_retain(self.bits()).intersection(other);
}
}
impl ::bitflags::__private::core::ops::Sub for MeshFlags {
type Output = Self;
#[inline]
fn sub(self, other: Self) -> Self { self.difference(other) }
}
impl ::bitflags::__private::core::ops::SubAssign for MeshFlags {
#[inline]
fn sub_assign(&mut self, other: Self) { self.remove(other); }
}
impl ::bitflags::__private::core::ops::Not for MeshFlags {
type Output = Self;
#[inline]
fn not(self) -> Self { self.complement() }
}
impl ::bitflags::__private::core::iter::Extend<MeshFlags> for
MeshFlags {
fn extend<T: ::bitflags::__private::core::iter::IntoIterator<Item
= Self>>(&mut self, iterator: T) {
for item in iterator { self.insert(item) }
}
}
impl ::bitflags::__private::core::iter::FromIterator<MeshFlags> for
MeshFlags {
fn from_iter<T: ::bitflags::__private::core::iter::IntoIterator<Item
= Self>>(iterator: T) -> Self {
use ::bitflags::__private::core::iter::Extend;
let mut result = Self::empty();
result.extend(iterator);
result
}
}
impl MeshFlags {
#[inline]
pub const fn iter(&self) -> ::bitflags::iter::Iter<MeshFlags> {
::bitflags::iter::Iter::__private_const_new(<MeshFlags as
::bitflags::Flags>::FLAGS,
MeshFlags::from_bits_retain(self.bits()),
MeshFlags::from_bits_retain(self.bits()))
}
#[inline]
pub const fn iter_names(&self)
-> ::bitflags::iter::IterNames<MeshFlags> {
::bitflags::iter::IterNames::__private_const_new(<MeshFlags as
::bitflags::Flags>::FLAGS,
MeshFlags::from_bits_retain(self.bits()),
MeshFlags::from_bits_retain(self.bits()))
}
}
impl ::bitflags::__private::core::iter::IntoIterator for MeshFlags {
type Item = MeshFlags;
type IntoIter = ::bitflags::iter::Iter<MeshFlags>;
fn into_iter(self) -> Self::IntoIter { self.iter() }
}
};bitflags::bitflags! {
700 #[repr(transparent)]
705 pub struct MeshFlags: u32 {
706 const LOD_INDEX_MASK = (1 << 16) - 1;
710 const AABB_BASED_VISIBILITY_RANGE = 1 << 27;
716 const NO_FRUSTUM_CULLING = 1 << 28;
721 const SHADOW_RECEIVER = 1 << 29;
722 const TRANSMITTED_SHADOW_RECEIVER = 1 << 30;
723 const SIGN_DETERMINANT_MODEL_3X3 = 1 << 31;
726 const NONE = 0;
727 const UNINITIALIZED = 0xFFFFFFFF;
728 }
729}
730
731impl MeshFlags {
732 fn from_components(
733 transform: &GlobalTransform,
734 lod_index: Option<NonMaxU16>,
735 visibility_range: Option<&VisibilityRange>,
736 no_frustum_culling: bool,
737 not_shadow_receiver: bool,
738 transmitted_receiver: bool,
739 ) -> MeshFlags {
740 let mut mesh_flags = if not_shadow_receiver {
741 MeshFlags::empty()
742 } else {
743 MeshFlags::SHADOW_RECEIVER
744 };
745 if visibility_range.is_some_and(|visibility_range| visibility_range.use_aabb) {
746 mesh_flags |= MeshFlags::AABB_BASED_VISIBILITY_RANGE;
747 }
748 if no_frustum_culling {
749 mesh_flags |= MeshFlags::NO_FRUSTUM_CULLING;
750 }
751 if transmitted_receiver {
752 mesh_flags |= MeshFlags::TRANSMITTED_SHADOW_RECEIVER;
753 }
754 if transform.affine().matrix3.determinant().is_sign_positive() {
755 mesh_flags |= MeshFlags::SIGN_DETERMINANT_MODEL_3X3;
756 }
757
758 let lod_index_bits = match lod_index {
759 None => u16::MAX,
760 Some(lod_index) => u16::from(lod_index),
761 };
762 mesh_flags |=
763 MeshFlags::from_bits_retain((lod_index_bits as u32) << MeshFlags::LOD_INDEX_SHIFT);
764
765 mesh_flags
766 }
767
768 pub const LOD_INDEX_SHIFT: u32 = 0;
770}
771
772bitflags::bitflags! {
773 #[derive(#[automatically_derived]
impl ::core::clone::Clone for RenderMeshInstanceFlags {
#[inline]
fn clone(&self) -> RenderMeshInstanceFlags {
let _:
::core::clone::AssertParamIsClone<<RenderMeshInstanceFlags as
::bitflags::__private::PublicFlags>::Internal>;
*self
}
}
#[allow(dead_code, deprecated, unused_doc_comments, unused_attributes,
unused_mut, unused_imports, non_upper_case_globals, clippy :: min_ident_chars,
clippy :: assign_op_pattern, clippy :: indexing_slicing, clippy ::
same_name_method, clippy :: iter_without_into_iter,)]
const _: () =
{
#[repr(transparent)]
pub struct InternalBitFlags(u32);
#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for InternalBitFlags { }
#[automatically_derived]
impl ::core::clone::Clone for InternalBitFlags {
#[inline]
fn clone(&self) -> InternalBitFlags {
let _: ::core::clone::AssertParamIsClone<u32>;
*self
}
}
#[automatically_derived]
impl ::core::marker::Copy for InternalBitFlags { }
#[automatically_derived]
impl ::core::marker::StructuralPartialEq for InternalBitFlags { }
#[automatically_derived]
impl ::core::cmp::PartialEq for InternalBitFlags {
#[inline]
fn eq(&self, other: &InternalBitFlags) -> bool {
self.0 == other.0
}
}
#[automatically_derived]
impl ::core::cmp::Eq for InternalBitFlags {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<u32>;
}
}
#[automatically_derived]
impl ::core::cmp::PartialOrd for InternalBitFlags {
#[inline]
fn partial_cmp(&self, other: &InternalBitFlags)
-> ::core::option::Option<::core::cmp::Ordering> {
::core::option::Option::Some(::core::cmp::Ord::cmp(self,
other))
}
}
#[automatically_derived]
impl ::core::cmp::Ord for InternalBitFlags {
#[inline]
fn cmp(&self, other: &InternalBitFlags) -> ::core::cmp::Ordering {
::core::cmp::Ord::cmp(&self.0, &other.0)
}
}
#[automatically_derived]
impl ::core::hash::Hash for InternalBitFlags {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.0, state)
}
}
impl RenderMeshInstanceFlags {
#[doc = r" The mesh casts shadows."]
pub const SHADOW_CASTER: Self = Self::from_bits_retain(1 << 0);
#[doc = r" The mesh can participate in automatic batching."]
pub const AUTOMATIC_BATCHING: Self =
Self::from_bits_retain(1 << 1);
#[doc =
r" The mesh had a transform last frame and so is eligible for motion"]
#[doc = r" vector computation."]
pub const HAS_PREVIOUS_TRANSFORM: Self =
Self::from_bits_retain(1 << 2);
#[doc =
r" The mesh had a skin last frame and so that skin should be taken into"]
#[doc = r" account for motion vector computation."]
pub const HAS_PREVIOUS_SKIN: Self =
Self::from_bits_retain(1 << 3);
#[doc =
r" The mesh had morph targets last frame and so they should be taken"]
#[doc = r" into account for motion vector computation."]
pub const HAS_PREVIOUS_MORPH: Self =
Self::from_bits_retain(1 << 4);
#[doc =
r" CPU culling has been disabled because the `NoCpuCulling` component"]
#[doc = r" is present on the mesh instance."]
pub const NO_CPU_CULLING: Self = Self::from_bits_retain(1 << 5);
}
impl ::bitflags::Flags for RenderMeshInstanceFlags {
const FLAGS: &'static [::bitflags::Flag<RenderMeshInstanceFlags>]
=
{
mod __bitflags_flag_names {
use super::*;
pub(super) const SHADOW_CASTER: &'static str =
"SHADOW_CASTER";
pub(super) const AUTOMATIC_BATCHING: &'static str =
"AUTOMATIC_BATCHING";
pub(super) const HAS_PREVIOUS_TRANSFORM: &'static str =
"HAS_PREVIOUS_TRANSFORM";
pub(super) const HAS_PREVIOUS_SKIN: &'static str =
"HAS_PREVIOUS_SKIN";
pub(super) const HAS_PREVIOUS_MORPH: &'static str =
"HAS_PREVIOUS_MORPH";
pub(super) const NO_CPU_CULLING: &'static str =
"NO_CPU_CULLING";
}
&[{
::bitflags::Flag::new(__bitflags_flag_names::SHADOW_CASTER,
RenderMeshInstanceFlags::SHADOW_CASTER)
},
{
::bitflags::Flag::new(__bitflags_flag_names::AUTOMATIC_BATCHING,
RenderMeshInstanceFlags::AUTOMATIC_BATCHING)
},
{
::bitflags::Flag::new(__bitflags_flag_names::HAS_PREVIOUS_TRANSFORM,
RenderMeshInstanceFlags::HAS_PREVIOUS_TRANSFORM)
},
{
::bitflags::Flag::new(__bitflags_flag_names::HAS_PREVIOUS_SKIN,
RenderMeshInstanceFlags::HAS_PREVIOUS_SKIN)
},
{
::bitflags::Flag::new(__bitflags_flag_names::HAS_PREVIOUS_MORPH,
RenderMeshInstanceFlags::HAS_PREVIOUS_MORPH)
},
{
::bitflags::Flag::new(__bitflags_flag_names::NO_CPU_CULLING,
RenderMeshInstanceFlags::NO_CPU_CULLING)
}]
};
type Bits = u32;
fn bits(&self) -> u32 { RenderMeshInstanceFlags::bits(self) }
fn from_bits_retain(bits: u32) -> RenderMeshInstanceFlags {
RenderMeshInstanceFlags::from_bits_retain(bits)
}
fn all_named() -> RenderMeshInstanceFlags {
const ALL_NAMED: u32 =
{
let mut truncated = <u32 as ::bitflags::Bits>::EMPTY;
let mut i = 0;
{
{
let flag =
&<RenderMeshInstanceFlags as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<RenderMeshInstanceFlags as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<RenderMeshInstanceFlags as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<RenderMeshInstanceFlags as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<RenderMeshInstanceFlags as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<RenderMeshInstanceFlags as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
let _ = i;
truncated
};
RenderMeshInstanceFlags::from_bits_retain(ALL_NAMED)
}
}
impl ::bitflags::__private::PublicFlags for RenderMeshInstanceFlags {
type Primitive = u32;
type Internal = InternalBitFlags;
}
impl ::bitflags::__private::core::default::Default for
InternalBitFlags {
#[inline]
fn default() -> Self { InternalBitFlags::empty() }
}
impl ::bitflags::__private::core::fmt::Debug for InternalBitFlags {
fn fmt(&self,
f: &mut ::bitflags::__private::core::fmt::Formatter<'_>)
-> ::bitflags::__private::core::fmt::Result {
if self.is_empty() {
f.write_fmt(format_args!("{0:#x}",
<u32 as ::bitflags::Bits>::EMPTY))
} else {
::bitflags::__private::core::fmt::Display::fmt(self, f)
}
}
}
impl ::bitflags::__private::core::fmt::Display for InternalBitFlags {
fn fmt(&self,
f: &mut ::bitflags::__private::core::fmt::Formatter<'_>)
-> ::bitflags::__private::core::fmt::Result {
::bitflags::parser::to_writer(&RenderMeshInstanceFlags(*self),
f)
}
}
impl ::bitflags::__private::core::str::FromStr for InternalBitFlags {
type Err = ::bitflags::parser::ParseError;
fn from_str(s: &str)
->
::bitflags::__private::core::result::Result<Self,
Self::Err> {
::bitflags::parser::from_str::<RenderMeshInstanceFlags>(s).map(|flags|
flags.0)
}
}
impl ::bitflags::__private::core::convert::AsRef<u32> for
InternalBitFlags {
fn as_ref(&self) -> &u32 { &self.0 }
}
impl ::bitflags::__private::core::convert::From<u32> for
InternalBitFlags {
fn from(bits: u32) -> Self { Self::from_bits_retain(bits) }
}
impl InternalBitFlags {
#[inline]
pub const fn empty() -> Self {
Self(<u32 as ::bitflags::Bits>::EMPTY)
}
#[inline]
pub const fn all() -> Self {
let mut truncated = <u32 as ::bitflags::Bits>::EMPTY;
let mut i = 0;
{
{
let flag =
<RenderMeshInstanceFlags as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<RenderMeshInstanceFlags as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<RenderMeshInstanceFlags as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<RenderMeshInstanceFlags as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<RenderMeshInstanceFlags as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<RenderMeshInstanceFlags as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
let _ = i;
Self(truncated)
}
#[inline]
pub const fn bits(&self) -> u32 { self.0 }
#[inline]
pub const fn from_bits(bits: u32)
-> ::bitflags::__private::core::option::Option<Self> {
let truncated = Self::from_bits_truncate(bits).0;
if truncated == bits {
::bitflags::__private::core::option::Option::Some(Self(bits))
} else { ::bitflags::__private::core::option::Option::None }
}
#[inline]
pub const fn from_bits_truncate(bits: u32) -> Self {
Self(bits & Self::all().0)
}
#[inline]
pub const fn from_bits_retain(bits: u32) -> Self { Self(bits) }
#[inline]
pub fn from_name(name: &str)
-> ::bitflags::__private::core::option::Option<Self> {
mod __bitflags_flag_names {
use super::*;
pub(super) const SHADOW_CASTER: &'static str =
"SHADOW_CASTER";
pub(super) const AUTOMATIC_BATCHING: &'static str =
"AUTOMATIC_BATCHING";
pub(super) const HAS_PREVIOUS_TRANSFORM: &'static str =
"HAS_PREVIOUS_TRANSFORM";
pub(super) const HAS_PREVIOUS_SKIN: &'static str =
"HAS_PREVIOUS_SKIN";
pub(super) const HAS_PREVIOUS_MORPH: &'static str =
"HAS_PREVIOUS_MORPH";
pub(super) const NO_CPU_CULLING: &'static str =
"NO_CPU_CULLING";
}
{
{
if name == __bitflags_flag_names::SHADOW_CASTER {
return ::bitflags::__private::core::option::Option::Some(Self(RenderMeshInstanceFlags::SHADOW_CASTER.bits()));
}
};
};
{
{
if name == __bitflags_flag_names::AUTOMATIC_BATCHING {
return ::bitflags::__private::core::option::Option::Some(Self(RenderMeshInstanceFlags::AUTOMATIC_BATCHING.bits()));
}
};
};
{
{
if name == __bitflags_flag_names::HAS_PREVIOUS_TRANSFORM {
return ::bitflags::__private::core::option::Option::Some(Self(RenderMeshInstanceFlags::HAS_PREVIOUS_TRANSFORM.bits()));
}
};
};
{
{
if name == __bitflags_flag_names::HAS_PREVIOUS_SKIN {
return ::bitflags::__private::core::option::Option::Some(Self(RenderMeshInstanceFlags::HAS_PREVIOUS_SKIN.bits()));
}
};
};
{
{
if name == __bitflags_flag_names::HAS_PREVIOUS_MORPH {
return ::bitflags::__private::core::option::Option::Some(Self(RenderMeshInstanceFlags::HAS_PREVIOUS_MORPH.bits()));
}
};
};
{
{
if name == __bitflags_flag_names::NO_CPU_CULLING {
return ::bitflags::__private::core::option::Option::Some(Self(RenderMeshInstanceFlags::NO_CPU_CULLING.bits()));
}
};
};
let _ = name;
::bitflags::__private::core::option::Option::None
}
#[inline]
pub const fn is_empty(&self) -> bool {
self.0 == <u32 as ::bitflags::Bits>::EMPTY
}
#[inline]
pub const fn is_all(&self) -> bool {
Self::all().0 | self.0 == self.0
}
#[inline]
pub const fn intersects(&self, other: Self) -> bool {
self.0 & other.0 != <u32 as ::bitflags::Bits>::EMPTY
}
#[inline]
pub const fn contains(&self, other: Self) -> bool {
self.0 & other.0 == other.0
}
#[inline]
pub fn insert(&mut self, other: Self) {
*self = Self(self.0).union(other);
}
#[inline]
pub fn remove(&mut self, other: Self) {
*self = Self(self.0).difference(other);
}
#[inline]
pub fn toggle(&mut self, other: Self) {
*self = Self(self.0).symmetric_difference(other);
}
#[inline]
pub fn set(&mut self, other: Self, value: bool) {
if value { self.insert(other); } else { self.remove(other); }
}
#[inline]
#[must_use]
pub const fn intersection(self, other: Self) -> Self {
Self(self.0 & other.0)
}
#[inline]
#[must_use]
pub const fn union(self, other: Self) -> Self {
Self(self.0 | other.0)
}
#[inline]
#[must_use]
pub const fn difference(self, other: Self) -> Self {
Self(self.0 & !other.0)
}
#[inline]
#[must_use]
pub const fn symmetric_difference(self, other: Self) -> Self {
Self(self.0 ^ other.0)
}
#[inline]
#[must_use]
pub const fn complement(self) -> Self {
Self::from_bits_truncate(!self.0)
}
}
impl ::bitflags::__private::core::fmt::Binary for InternalBitFlags {
fn fmt(&self, f: &mut ::bitflags::__private::core::fmt::Formatter)
-> ::bitflags::__private::core::fmt::Result {
let inner = self.0;
::bitflags::__private::core::fmt::Binary::fmt(&inner, f)
}
}
impl ::bitflags::__private::core::fmt::Octal for InternalBitFlags {
fn fmt(&self, f: &mut ::bitflags::__private::core::fmt::Formatter)
-> ::bitflags::__private::core::fmt::Result {
let inner = self.0;
::bitflags::__private::core::fmt::Octal::fmt(&inner, f)
}
}
impl ::bitflags::__private::core::fmt::LowerHex for InternalBitFlags {
fn fmt(&self, f: &mut ::bitflags::__private::core::fmt::Formatter)
-> ::bitflags::__private::core::fmt::Result {
let inner = self.0;
::bitflags::__private::core::fmt::LowerHex::fmt(&inner, f)
}
}
impl ::bitflags::__private::core::fmt::UpperHex for InternalBitFlags {
fn fmt(&self, f: &mut ::bitflags::__private::core::fmt::Formatter)
-> ::bitflags::__private::core::fmt::Result {
let inner = self.0;
::bitflags::__private::core::fmt::UpperHex::fmt(&inner, f)
}
}
impl ::bitflags::__private::core::ops::BitOr for InternalBitFlags {
type Output = Self;
#[inline]
fn bitor(self, other: InternalBitFlags) -> Self {
self.union(other)
}
}
impl ::bitflags::__private::core::ops::BitOrAssign for
InternalBitFlags {
#[inline]
fn bitor_assign(&mut self, other: Self) { self.insert(other); }
}
impl ::bitflags::__private::core::ops::BitXor for InternalBitFlags {
type Output = Self;
#[inline]
fn bitxor(self, other: Self) -> Self {
self.symmetric_difference(other)
}
}
impl ::bitflags::__private::core::ops::BitXorAssign for
InternalBitFlags {
#[inline]
fn bitxor_assign(&mut self, other: Self) { self.toggle(other); }
}
impl ::bitflags::__private::core::ops::BitAnd for InternalBitFlags {
type Output = Self;
#[inline]
fn bitand(self, other: Self) -> Self { self.intersection(other) }
}
impl ::bitflags::__private::core::ops::BitAndAssign for
InternalBitFlags {
#[inline]
fn bitand_assign(&mut self, other: Self) {
*self =
Self::from_bits_retain(self.bits()).intersection(other);
}
}
impl ::bitflags::__private::core::ops::Sub for InternalBitFlags {
type Output = Self;
#[inline]
fn sub(self, other: Self) -> Self { self.difference(other) }
}
impl ::bitflags::__private::core::ops::SubAssign for InternalBitFlags
{
#[inline]
fn sub_assign(&mut self, other: Self) { self.remove(other); }
}
impl ::bitflags::__private::core::ops::Not for InternalBitFlags {
type Output = Self;
#[inline]
fn not(self) -> Self { self.complement() }
}
impl ::bitflags::__private::core::iter::Extend<InternalBitFlags> for
InternalBitFlags {
fn extend<T: ::bitflags::__private::core::iter::IntoIterator<Item
= Self>>(&mut self, iterator: T) {
for item in iterator { self.insert(item) }
}
}
impl ::bitflags::__private::core::iter::FromIterator<InternalBitFlags>
for InternalBitFlags {
fn from_iter<T: ::bitflags::__private::core::iter::IntoIterator<Item
= Self>>(iterator: T) -> Self {
use ::bitflags::__private::core::iter::Extend;
let mut result = Self::empty();
result.extend(iterator);
result
}
}
impl InternalBitFlags {
#[inline]
pub const fn iter(&self)
-> ::bitflags::iter::Iter<RenderMeshInstanceFlags> {
::bitflags::iter::Iter::__private_const_new(<RenderMeshInstanceFlags
as ::bitflags::Flags>::FLAGS,
RenderMeshInstanceFlags::from_bits_retain(self.bits()),
RenderMeshInstanceFlags::from_bits_retain(self.bits()))
}
#[inline]
pub const fn iter_names(&self)
-> ::bitflags::iter::IterNames<RenderMeshInstanceFlags> {
::bitflags::iter::IterNames::__private_const_new(<RenderMeshInstanceFlags
as ::bitflags::Flags>::FLAGS,
RenderMeshInstanceFlags::from_bits_retain(self.bits()),
RenderMeshInstanceFlags::from_bits_retain(self.bits()))
}
}
impl ::bitflags::__private::core::iter::IntoIterator for
InternalBitFlags {
type Item = RenderMeshInstanceFlags;
type IntoIter = ::bitflags::iter::Iter<RenderMeshInstanceFlags>;
fn into_iter(self) -> Self::IntoIter { self.iter() }
}
impl InternalBitFlags {
#[inline]
pub fn bits_mut(&mut self) -> &mut u32 { &mut self.0 }
}
impl ::bitflags::__private::serde::Serialize for InternalBitFlags {
fn serialize<S: ::bitflags::__private::serde::Serializer>(&self,
serializer: S)
->
::bitflags::__private::core::result::Result<S::Ok,
S::Error> {
::bitflags::serde::serialize(&RenderMeshInstanceFlags::from_bits_retain(self.bits()),
serializer)
}
}
impl<'de> ::bitflags::__private::serde::Deserialize<'de> for
InternalBitFlags {
fn deserialize<D: ::bitflags::__private::serde::Deserializer<'de>>(deserializer:
D)
->
::bitflags::__private::core::result::Result<Self,
D::Error> {
let flags: RenderMeshInstanceFlags =
::bitflags::serde::deserialize(deserializer)?;
::bitflags::__private::core::result::Result::Ok(flags.0)
}
}
unsafe impl ::bitflags::__private::bytemuck::Pod for InternalBitFlags
where u32: ::bitflags::__private::bytemuck::Pod {}
unsafe impl ::bitflags::__private::bytemuck::Zeroable for
InternalBitFlags where
u32: ::bitflags::__private::bytemuck::Zeroable {}
impl RenderMeshInstanceFlags {
#[inline]
pub const fn empty() -> Self { Self(InternalBitFlags::empty()) }
#[inline]
pub const fn all() -> Self { Self(InternalBitFlags::all()) }
#[inline]
pub const fn bits(&self) -> u32 { self.0.bits() }
#[inline]
pub const fn from_bits(bits: u32)
-> ::bitflags::__private::core::option::Option<Self> {
match InternalBitFlags::from_bits(bits) {
::bitflags::__private::core::option::Option::Some(bits) =>
::bitflags::__private::core::option::Option::Some(Self(bits)),
::bitflags::__private::core::option::Option::None =>
::bitflags::__private::core::option::Option::None,
}
}
#[inline]
pub const fn from_bits_truncate(bits: u32) -> Self {
Self(InternalBitFlags::from_bits_truncate(bits))
}
#[inline]
pub const fn from_bits_retain(bits: u32) -> Self {
Self(InternalBitFlags::from_bits_retain(bits))
}
#[inline]
pub fn from_name(name: &str)
-> ::bitflags::__private::core::option::Option<Self> {
match InternalBitFlags::from_name(name) {
::bitflags::__private::core::option::Option::Some(bits) =>
::bitflags::__private::core::option::Option::Some(Self(bits)),
::bitflags::__private::core::option::Option::None =>
::bitflags::__private::core::option::Option::None,
}
}
#[inline]
pub const fn is_empty(&self) -> bool { self.0.is_empty() }
#[inline]
pub const fn is_all(&self) -> bool { self.0.is_all() }
#[inline]
pub const fn intersects(&self, other: Self) -> bool {
self.0.intersects(other.0)
}
#[inline]
pub const fn contains(&self, other: Self) -> bool {
self.0.contains(other.0)
}
#[inline]
pub fn insert(&mut self, other: Self) { self.0.insert(other.0) }
#[inline]
pub fn remove(&mut self, other: Self) { self.0.remove(other.0) }
#[inline]
pub fn toggle(&mut self, other: Self) { self.0.toggle(other.0) }
#[inline]
pub fn set(&mut self, other: Self, value: bool) {
self.0.set(other.0, value)
}
#[inline]
#[must_use]
pub const fn intersection(self, other: Self) -> Self {
Self(self.0.intersection(other.0))
}
#[inline]
#[must_use]
pub const fn union(self, other: Self) -> Self {
Self(self.0.union(other.0))
}
#[inline]
#[must_use]
pub const fn difference(self, other: Self) -> Self {
Self(self.0.difference(other.0))
}
#[inline]
#[must_use]
pub const fn symmetric_difference(self, other: Self) -> Self {
Self(self.0.symmetric_difference(other.0))
}
#[inline]
#[must_use]
pub const fn complement(self) -> Self {
Self(self.0.complement())
}
}
impl ::bitflags::__private::core::fmt::Binary for
RenderMeshInstanceFlags {
fn fmt(&self, f: &mut ::bitflags::__private::core::fmt::Formatter)
-> ::bitflags::__private::core::fmt::Result {
let inner = self.0;
::bitflags::__private::core::fmt::Binary::fmt(&inner, f)
}
}
impl ::bitflags::__private::core::fmt::Octal for
RenderMeshInstanceFlags {
fn fmt(&self, f: &mut ::bitflags::__private::core::fmt::Formatter)
-> ::bitflags::__private::core::fmt::Result {
let inner = self.0;
::bitflags::__private::core::fmt::Octal::fmt(&inner, f)
}
}
impl ::bitflags::__private::core::fmt::LowerHex for
RenderMeshInstanceFlags {
fn fmt(&self, f: &mut ::bitflags::__private::core::fmt::Formatter)
-> ::bitflags::__private::core::fmt::Result {
let inner = self.0;
::bitflags::__private::core::fmt::LowerHex::fmt(&inner, f)
}
}
impl ::bitflags::__private::core::fmt::UpperHex for
RenderMeshInstanceFlags {
fn fmt(&self, f: &mut ::bitflags::__private::core::fmt::Formatter)
-> ::bitflags::__private::core::fmt::Result {
let inner = self.0;
::bitflags::__private::core::fmt::UpperHex::fmt(&inner, f)
}
}
impl ::bitflags::__private::core::ops::BitOr for
RenderMeshInstanceFlags {
type Output = Self;
#[inline]
fn bitor(self, other: RenderMeshInstanceFlags) -> Self {
self.union(other)
}
}
impl ::bitflags::__private::core::ops::BitOrAssign for
RenderMeshInstanceFlags {
#[inline]
fn bitor_assign(&mut self, other: Self) { self.insert(other); }
}
impl ::bitflags::__private::core::ops::BitXor for
RenderMeshInstanceFlags {
type Output = Self;
#[inline]
fn bitxor(self, other: Self) -> Self {
self.symmetric_difference(other)
}
}
impl ::bitflags::__private::core::ops::BitXorAssign for
RenderMeshInstanceFlags {
#[inline]
fn bitxor_assign(&mut self, other: Self) { self.toggle(other); }
}
impl ::bitflags::__private::core::ops::BitAnd for
RenderMeshInstanceFlags {
type Output = Self;
#[inline]
fn bitand(self, other: Self) -> Self { self.intersection(other) }
}
impl ::bitflags::__private::core::ops::BitAndAssign for
RenderMeshInstanceFlags {
#[inline]
fn bitand_assign(&mut self, other: Self) {
*self =
Self::from_bits_retain(self.bits()).intersection(other);
}
}
impl ::bitflags::__private::core::ops::Sub for RenderMeshInstanceFlags
{
type Output = Self;
#[inline]
fn sub(self, other: Self) -> Self { self.difference(other) }
}
impl ::bitflags::__private::core::ops::SubAssign for
RenderMeshInstanceFlags {
#[inline]
fn sub_assign(&mut self, other: Self) { self.remove(other); }
}
impl ::bitflags::__private::core::ops::Not for RenderMeshInstanceFlags
{
type Output = Self;
#[inline]
fn not(self) -> Self { self.complement() }
}
impl ::bitflags::__private::core::iter::Extend<RenderMeshInstanceFlags>
for RenderMeshInstanceFlags {
fn extend<T: ::bitflags::__private::core::iter::IntoIterator<Item
= Self>>(&mut self, iterator: T) {
for item in iterator { self.insert(item) }
}
}
impl ::bitflags::__private::core::iter::FromIterator<RenderMeshInstanceFlags>
for RenderMeshInstanceFlags {
fn from_iter<T: ::bitflags::__private::core::iter::IntoIterator<Item
= Self>>(iterator: T) -> Self {
use ::bitflags::__private::core::iter::Extend;
let mut result = Self::empty();
result.extend(iterator);
result
}
}
impl RenderMeshInstanceFlags {
#[inline]
pub const fn iter(&self)
-> ::bitflags::iter::Iter<RenderMeshInstanceFlags> {
::bitflags::iter::Iter::__private_const_new(<RenderMeshInstanceFlags
as ::bitflags::Flags>::FLAGS,
RenderMeshInstanceFlags::from_bits_retain(self.bits()),
RenderMeshInstanceFlags::from_bits_retain(self.bits()))
}
#[inline]
pub const fn iter_names(&self)
-> ::bitflags::iter::IterNames<RenderMeshInstanceFlags> {
::bitflags::iter::IterNames::__private_const_new(<RenderMeshInstanceFlags
as ::bitflags::Flags>::FLAGS,
RenderMeshInstanceFlags::from_bits_retain(self.bits()),
RenderMeshInstanceFlags::from_bits_retain(self.bits()))
}
}
impl ::bitflags::__private::core::iter::IntoIterator for
RenderMeshInstanceFlags {
type Item = RenderMeshInstanceFlags;
type IntoIter = ::bitflags::iter::Iter<RenderMeshInstanceFlags>;
fn into_iter(self) -> Self::IntoIter { self.iter() }
}
};Clone, #[automatically_derived]
impl ::core::marker::Copy for RenderMeshInstanceFlags { }Copy, #[automatically_derived]
impl ::core::default::Default for RenderMeshInstanceFlags {
#[inline]
fn default() -> RenderMeshInstanceFlags {
RenderMeshInstanceFlags(::core::default::Default::default())
}
}Default, unsafe impl ::bytemuck::Pod for RenderMeshInstanceFlags {}Pod, unsafe impl ::bytemuck::Zeroable for RenderMeshInstanceFlags {}Zeroable)]
775 #[repr(C)]
776 pub struct RenderMeshInstanceFlags: u32 {
777 const SHADOW_CASTER = 1 << 0;
779 const AUTOMATIC_BATCHING = 1 << 1;
781 const HAS_PREVIOUS_TRANSFORM = 1 << 2;
784 const HAS_PREVIOUS_SKIN = 1 << 3;
787 const HAS_PREVIOUS_MORPH = 1 << 4;
790 const NO_CPU_CULLING = 1 << 5;
793 }
794}
795
796#[derive(impl ::core::ops::Deref for RenderMeshInstanceCpu {
type Target = RenderMeshInstanceSharedFlatBlob;
fn deref(&self) -> &Self::Target { &self.shared }
}Deref, impl ::core::ops::DerefMut for RenderMeshInstanceCpu {
fn deref_mut(&mut self) -> &mut Self::Target { &mut self.shared }
}DerefMut)]
799pub struct RenderMeshInstanceCpu {
800 #[deref]
803 pub shared: RenderMeshInstanceSharedFlatBlob,
804 pub transforms: MeshTransforms,
808 pub render_layers: Option<RenderLayers>,
810}
811
812#[derive(impl ::core::ops::Deref for RenderMeshInstanceGpu {
type Target = RenderMeshInstanceSharedFlatBlob;
fn deref(&self) -> &Self::Target { &self.shared }
}Deref)]
815pub struct RenderMeshInstanceGpu {
816 #[deref]
819 pub shared: RenderMeshInstanceSharedFlatBlob,
820 pub gpu_specific: RenderMeshInstanceGpuFlatBlob,
823 pub render_layers: Option<RenderLayers>,
827}
828
829#[derive(#[automatically_derived]
impl ::core::clone::Clone for RenderMeshInstanceSharedFlat {
#[inline]
fn clone(&self) -> RenderMeshInstanceSharedFlat {
let _: ::core::clone::AssertParamIsClone<MeshAssetIdFlat>;
let _: ::core::clone::AssertParamIsClone<MaterialBindingId>;
let _: ::core::clone::AssertParamIsClone<LightmapSlabIndexFlat>;
let _: ::core::clone::AssertParamIsClone<u32>;
let _: ::core::clone::AssertParamIsClone<RenderMeshInstanceFlags>;
*self
}
}Clone, #[automatically_derived]
impl ::core::marker::Copy for RenderMeshInstanceSharedFlat { }Copy, #[automatically_derived]
impl ::core::default::Default for RenderMeshInstanceSharedFlat {
#[inline]
fn default() -> RenderMeshInstanceSharedFlat {
RenderMeshInstanceSharedFlat {
asset_id: ::core::default::Default::default(),
material_bindings_index: ::core::default::Default::default(),
lightmap_slab_index: ::core::default::Default::default(),
tag: ::core::default::Default::default(),
current_uniform_index: ::core::default::Default::default(),
flags: ::core::default::Default::default(),
}
}
}Default, unsafe impl ::bytemuck::Pod for RenderMeshInstanceSharedFlat {}Pod, unsafe impl ::bytemuck::Zeroable for RenderMeshInstanceSharedFlat {}Zeroable)]
837#[repr(C)]
838pub struct RenderMeshInstanceSharedFlat {
839 asset_id: MeshAssetIdFlat,
840 material_bindings_index: MaterialBindingId,
841 lightmap_slab_index: LightmapSlabIndexFlat,
842 tag: u32,
843 current_uniform_index: u32,
844 flags: RenderMeshInstanceFlags,
845}
846
847#[repr(transparent)]
pub struct RenderMeshInstanceSharedFlatBlob(pub [::core::sync::atomic::AtomicU32; ::core::mem::size_of::<RenderMeshInstanceSharedFlat>()
/ 4]);
#[automatically_derived]
impl ::core::default::Default for RenderMeshInstanceSharedFlatBlob {
#[inline]
fn default() -> RenderMeshInstanceSharedFlatBlob {
RenderMeshInstanceSharedFlatBlob(::core::default::Default::default())
}
}
impl ::core::ops::Deref for RenderMeshInstanceSharedFlatBlob {
type Target =
[::core::sync::atomic::AtomicU32; ::core::mem::size_of::<RenderMeshInstanceSharedFlat>()
/ 4];
fn deref(&self) -> &Self::Target { &self.0 }
}
impl ::core::ops::DerefMut for RenderMeshInstanceSharedFlatBlob {
fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 }
}
impl ::bevy_render::render_resource::AtomicPod for
RenderMeshInstanceSharedFlat {
type Blob = RenderMeshInstanceSharedFlatBlob;
fn read_from_blob(blob: &Self::Blob) -> Self {
const _ASSERT_POD_TYPE_SIZE: () =
if !(::core::mem::size_of::<RenderMeshInstanceSharedFlat>() % 4 ==
0) {
::core::panicking::panic("assertion failed: ::core::mem::size_of::<RenderMeshInstanceSharedFlat>() % 4 == 0")
};
let nonatomic_data:
[u32; ::core::mem::size_of::<RenderMeshInstanceSharedFlat>() /
4] =
::core::array::from_fn(|i|
{
blob.0[i].load(::bevy_platform::sync::atomic::Ordering::Relaxed)
});
::bytemuck::must_cast(nonatomic_data)
}
fn write_to_blob(&self, blob: &Self::Blob) {
let src:
[u32; ::core::mem::size_of::<RenderMeshInstanceSharedFlat>() /
4] = ::bytemuck::must_cast(*self);
for (dest, src) in blob.0.iter().zip(src.iter()) {
dest.store(*src,
::bevy_platform::sync::atomic::Ordering::Relaxed);
}
}
}
unsafe impl ::bevy_render::render_resource::AtomicPodBlob for
RenderMeshInstanceSharedFlatBlob {}
impl<'a> ::core::convert::From<&'a RenderMeshInstanceSharedFlat> for
RenderMeshInstanceSharedFlatBlob {
fn from(pod: &'a RenderMeshInstanceSharedFlat) -> Self {
let blob = Self::default();
pod.write_to_blob(&blob);
blob
}
}
impl RenderMeshInstanceSharedFlatBlob {
pub fn mesh_asset_id_flat(&self) -> MeshAssetIdFlat {
const _ASSERT_FIELD_SIZE: () =
if !(::core::mem::size_of::<MeshAssetIdFlat>() % 4 == 0) {
::core::panicking::panic("assertion failed: ::core::mem::size_of::<MeshAssetIdFlat>() % 4 == 0")
};
let words: [u32; ::core::mem::size_of::<MeshAssetIdFlat>() / 4] =
::core::array::from_fn(|i|
{
self.0[const {
builtin # offset_of(RenderMeshInstanceSharedFlat, asset_id)
} / 4 +
i].load(::bevy_platform::sync::atomic::Ordering::Relaxed)
});
*::bytemuck::must_cast_ref(&words)
}
pub fn set_mesh_asset_id_flat(&self, value: MeshAssetIdFlat) {
let words: [u32; ::core::mem::size_of::<MeshAssetIdFlat>() / 4] =
::bytemuck::must_cast(value);
for i in 0..(::core::mem::size_of::<MeshAssetIdFlat>() / 4) {
self.0[const {
builtin # offset_of(RenderMeshInstanceSharedFlat, asset_id)
} / 4 +
i].store(words[i],
::bevy_platform::sync::atomic::Ordering::Relaxed);
}
}
pub fn material_bindings_index(&self) -> MaterialBindingId {
const _ASSERT_FIELD_SIZE: () =
if !(::core::mem::size_of::<MaterialBindingId>() % 4 == 0) {
::core::panicking::panic("assertion failed: ::core::mem::size_of::<MaterialBindingId>() % 4 == 0")
};
let words: [u32; ::core::mem::size_of::<MaterialBindingId>() / 4] =
::core::array::from_fn(|i|
{
self.0[const {
builtin # offset_of(RenderMeshInstanceSharedFlat,
material_bindings_index)
} / 4 +
i].load(::bevy_platform::sync::atomic::Ordering::Relaxed)
});
*::bytemuck::must_cast_ref(&words)
}
pub fn set_material_bindings_index(&self, value: MaterialBindingId) {
let words: [u32; ::core::mem::size_of::<MaterialBindingId>() / 4] =
::bytemuck::must_cast(value);
for i in 0..(::core::mem::size_of::<MaterialBindingId>() / 4) {
self.0[const {
builtin # offset_of(RenderMeshInstanceSharedFlat,
material_bindings_index)
} / 4 +
i].store(words[i],
::bevy_platform::sync::atomic::Ordering::Relaxed);
}
}
pub fn lightmap_slab_index_flat(&self) -> LightmapSlabIndexFlat {
const _ASSERT_FIELD_SIZE: () =
if !(::core::mem::size_of::<LightmapSlabIndexFlat>() % 4 == 0) {
::core::panicking::panic("assertion failed: ::core::mem::size_of::<LightmapSlabIndexFlat>() % 4 == 0")
};
let words:
[u32; ::core::mem::size_of::<LightmapSlabIndexFlat>() / 4] =
::core::array::from_fn(|i|
{
self.0[const {
builtin # offset_of(RenderMeshInstanceSharedFlat,
lightmap_slab_index)
} / 4 +
i].load(::bevy_platform::sync::atomic::Ordering::Relaxed)
});
*::bytemuck::must_cast_ref(&words)
}
pub fn set_lightmap_slab_index_flat(&self, value: LightmapSlabIndexFlat) {
let words:
[u32; ::core::mem::size_of::<LightmapSlabIndexFlat>() / 4] =
::bytemuck::must_cast(value);
for i in 0..(::core::mem::size_of::<LightmapSlabIndexFlat>() / 4) {
self.0[const {
builtin # offset_of(RenderMeshInstanceSharedFlat,
lightmap_slab_index)
} / 4 +
i].store(words[i],
::bevy_platform::sync::atomic::Ordering::Relaxed);
}
}
pub fn tag(&self) -> u32 {
const _ASSERT_FIELD_SIZE: () =
if !(::core::mem::size_of::<u32>() % 4 == 0) {
::core::panicking::panic("assertion failed: ::core::mem::size_of::<u32>() % 4 == 0")
};
let words: [u32; ::core::mem::size_of::<u32>() / 4] =
::core::array::from_fn(|i|
{
self.0[const {
builtin # offset_of(RenderMeshInstanceSharedFlat, tag)
} / 4 +
i].load(::bevy_platform::sync::atomic::Ordering::Relaxed)
});
*::bytemuck::must_cast_ref(&words)
}
pub fn set_tag(&self, value: u32) {
let words: [u32; ::core::mem::size_of::<u32>() / 4] =
::bytemuck::must_cast(value);
for i in 0..(::core::mem::size_of::<u32>() / 4) {
self.0[const {
builtin # offset_of(RenderMeshInstanceSharedFlat, tag)
} / 4 +
i].store(words[i],
::bevy_platform::sync::atomic::Ordering::Relaxed);
}
}
pub fn flags(&self) -> RenderMeshInstanceFlags {
const _ASSERT_FIELD_SIZE: () =
if !(::core::mem::size_of::<RenderMeshInstanceFlags>() % 4 == 0) {
::core::panicking::panic("assertion failed: ::core::mem::size_of::<RenderMeshInstanceFlags>() % 4 == 0")
};
let words:
[u32; ::core::mem::size_of::<RenderMeshInstanceFlags>() / 4] =
::core::array::from_fn(|i|
{
self.0[const {
builtin # offset_of(RenderMeshInstanceSharedFlat, flags)
} / 4 +
i].load(::bevy_platform::sync::atomic::Ordering::Relaxed)
});
*::bytemuck::must_cast_ref(&words)
}
pub fn set_flags(&self, value: RenderMeshInstanceFlags) {
let words:
[u32; ::core::mem::size_of::<RenderMeshInstanceFlags>() / 4] =
::bytemuck::must_cast(value);
for i in 0..(::core::mem::size_of::<RenderMeshInstanceFlags>() / 4) {
self.0[const {
builtin # offset_of(RenderMeshInstanceSharedFlat, flags)
} / 4 +
i].store(words[i],
::bevy_platform::sync::atomic::Ordering::Relaxed);
}
}
}impl_atomic_pod!(
848 RenderMeshInstanceSharedFlat,
849 RenderMeshInstanceSharedFlatBlob,
850 field(asset_id: MeshAssetIdFlat, mesh_asset_id_flat, set_mesh_asset_id_flat),
851 field(
852 material_bindings_index: MaterialBindingId,
853 material_bindings_index,
854 set_material_bindings_index
855 ),
856 field(
857 lightmap_slab_index: LightmapSlabIndexFlat,
858 lightmap_slab_index_flat,
859 set_lightmap_slab_index_flat
860 ),
861 field(tag: u32, tag, set_tag),
862 field(flags: RenderMeshInstanceFlags, flags, set_flags),
863);
864
865impl RenderMeshInstanceSharedFlatBlob {
866 pub fn mesh_asset_id(&self) -> AssetId<Mesh> {
867 self.mesh_asset_id_flat().into()
868 }
869
870 pub fn set_mesh_asset_id(&self, asset_id: AssetId<Mesh>) {
871 self.set_mesh_asset_id_flat(asset_id.into());
872 }
873
874 pub fn lightmap_slab_index(&self) -> Option<LightmapSlabIndex> {
875 self.lightmap_slab_index_flat().into()
876 }
877
878 pub fn set_lightmap_slab_index(&self, lightmap_slab_index: Option<LightmapSlabIndex>) {
879 self.set_lightmap_slab_index_flat(lightmap_slab_index.into());
880 }
881
882 #[inline]
885 pub fn should_batch(&self) -> bool {
886 self.flags()
887 .contains(RenderMeshInstanceFlags::AUTOMATIC_BATCHING)
888 }
889}
890
891#[derive(#[automatically_derived]
impl ::core::clone::Clone for RenderMeshInstanceGpuFlat {
#[inline]
fn clone(&self) -> RenderMeshInstanceGpuFlat {
let _: ::core::clone::AssertParamIsClone<u32>;
*self
}
}Clone, #[automatically_derived]
impl ::core::marker::Copy for RenderMeshInstanceGpuFlat { }Copy, #[automatically_derived]
impl ::core::default::Default for RenderMeshInstanceGpuFlat {
#[inline]
fn default() -> RenderMeshInstanceGpuFlat {
RenderMeshInstanceGpuFlat {
current_uniform_index: ::core::default::Default::default(),
}
}
}Default, unsafe impl ::bytemuck::Pod for RenderMeshInstanceGpuFlat {}Pod, unsafe impl ::bytemuck::Zeroable for RenderMeshInstanceGpuFlat {}Zeroable)]
896#[repr(C)]
897pub struct RenderMeshInstanceGpuFlat {
898 current_uniform_index: u32,
899}
900
901#[repr(transparent)]
pub struct RenderMeshInstanceGpuFlatBlob(pub [::core::sync::atomic::AtomicU32; ::core::mem::size_of::<RenderMeshInstanceGpuFlat>()
/ 4]);
#[automatically_derived]
impl ::core::default::Default for RenderMeshInstanceGpuFlatBlob {
#[inline]
fn default() -> RenderMeshInstanceGpuFlatBlob {
RenderMeshInstanceGpuFlatBlob(::core::default::Default::default())
}
}
impl ::core::ops::Deref for RenderMeshInstanceGpuFlatBlob {
type Target =
[::core::sync::atomic::AtomicU32; ::core::mem::size_of::<RenderMeshInstanceGpuFlat>()
/ 4];
fn deref(&self) -> &Self::Target { &self.0 }
}
impl ::core::ops::DerefMut for RenderMeshInstanceGpuFlatBlob {
fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 }
}
impl ::bevy_render::render_resource::AtomicPod for RenderMeshInstanceGpuFlat {
type Blob = RenderMeshInstanceGpuFlatBlob;
fn read_from_blob(blob: &Self::Blob) -> Self {
const _ASSERT_POD_TYPE_SIZE: () =
if !(::core::mem::size_of::<RenderMeshInstanceGpuFlat>() % 4 == 0)
{
::core::panicking::panic("assertion failed: ::core::mem::size_of::<RenderMeshInstanceGpuFlat>() % 4 == 0")
};
let nonatomic_data:
[u32; ::core::mem::size_of::<RenderMeshInstanceGpuFlat>() /
4] =
::core::array::from_fn(|i|
{
blob.0[i].load(::bevy_platform::sync::atomic::Ordering::Relaxed)
});
::bytemuck::must_cast(nonatomic_data)
}
fn write_to_blob(&self, blob: &Self::Blob) {
let src:
[u32; ::core::mem::size_of::<RenderMeshInstanceGpuFlat>() /
4] = ::bytemuck::must_cast(*self);
for (dest, src) in blob.0.iter().zip(src.iter()) {
dest.store(*src,
::bevy_platform::sync::atomic::Ordering::Relaxed);
}
}
}
unsafe impl ::bevy_render::render_resource::AtomicPodBlob for
RenderMeshInstanceGpuFlatBlob {}
impl<'a> ::core::convert::From<&'a RenderMeshInstanceGpuFlat> for
RenderMeshInstanceGpuFlatBlob {
fn from(pod: &'a RenderMeshInstanceGpuFlat) -> Self {
let blob = Self::default();
pod.write_to_blob(&blob);
blob
}
}
impl RenderMeshInstanceGpuFlatBlob {
pub fn current_uniform_index(&self) -> u32 {
const _ASSERT_FIELD_SIZE: () =
if !(::core::mem::size_of::<u32>() % 4 == 0) {
::core::panicking::panic("assertion failed: ::core::mem::size_of::<u32>() % 4 == 0")
};
let words: [u32; ::core::mem::size_of::<u32>() / 4] =
::core::array::from_fn(|i|
{
self.0[const {
builtin # offset_of(RenderMeshInstanceGpuFlat,
current_uniform_index)
} / 4 +
i].load(::bevy_platform::sync::atomic::Ordering::Relaxed)
});
*::bytemuck::must_cast_ref(&words)
}
pub fn set_current_uniform_index(&self, value: u32) {
let words: [u32; ::core::mem::size_of::<u32>() / 4] =
::bytemuck::must_cast(value);
for i in 0..(::core::mem::size_of::<u32>() / 4) {
self.0[const {
builtin # offset_of(RenderMeshInstanceGpuFlat,
current_uniform_index)
} / 4 +
i].store(words[i],
::bevy_platform::sync::atomic::Ordering::Relaxed);
}
}
}impl_atomic_pod!(
902 RenderMeshInstanceGpuFlat,
903 RenderMeshInstanceGpuFlatBlob,
904 field(current_uniform_index: u32, current_uniform_index, set_current_uniform_index),
905);
906
907#[derive(#[automatically_derived]
impl ::core::clone::Clone for MeshAssetIdFlat {
#[inline]
fn clone(&self) -> MeshAssetIdFlat {
let _: ::core::clone::AssertParamIsClone<u32>;
let _: ::core::clone::AssertParamIsClone<[u32; 4]>;
*self
}
}Clone, #[automatically_derived]
impl ::core::marker::Copy for MeshAssetIdFlat { }Copy, #[automatically_derived]
impl ::core::default::Default for MeshAssetIdFlat {
#[inline]
fn default() -> MeshAssetIdFlat {
MeshAssetIdFlat {
mode: ::core::default::Default::default(),
words: ::core::default::Default::default(),
}
}
}Default, unsafe impl ::bytemuck::Pod for MeshAssetIdFlat {}Pod, unsafe impl ::bytemuck::Zeroable for MeshAssetIdFlat {}Zeroable)]
908#[repr(C)]
909struct MeshAssetIdFlat {
910 mode: u32,
911 words: [u32; 4],
912}
913
914#[derive(#[automatically_derived]
impl ::core::clone::Clone for LightmapSlabIndexFlat {
#[inline]
fn clone(&self) -> LightmapSlabIndexFlat {
let _: ::core::clone::AssertParamIsClone<u32>;
*self
}
}Clone, #[automatically_derived]
impl ::core::marker::Copy for LightmapSlabIndexFlat { }Copy, #[automatically_derived]
impl ::core::default::Default for LightmapSlabIndexFlat {
#[inline]
fn default() -> LightmapSlabIndexFlat {
LightmapSlabIndexFlat(::core::default::Default::default())
}
}Default, unsafe impl ::bytemuck::Pod for LightmapSlabIndexFlat {}Pod, unsafe impl ::bytemuck::Zeroable for LightmapSlabIndexFlat {}Zeroable)]
915#[repr(C)]
916struct LightmapSlabIndexFlat(u32);
917
918const MESH_ASSET_ID_FLAT_MODE_INDEX: u32 = 0;
919const MESH_ASSET_ID_FLAT_MODE_UUID: u32 = 1;
920
921impl From<AssetId<Mesh>> for MeshAssetIdFlat {
922 #[inline]
923 fn from(value: AssetId<Mesh>) -> Self {
924 match value {
925 AssetId::Index { index, .. } => {
926 let bits = index.to_bits();
927 MeshAssetIdFlat {
928 mode: MESH_ASSET_ID_FLAT_MODE_INDEX,
929 words: [(bits & 0xffff_ffff) as u32, (bits >> 32) as u32, 0, 0],
930 }
931 }
932 AssetId::Uuid { uuid } => {
933 let (hi, lo) = uuid.as_u64_pair();
934 MeshAssetIdFlat {
935 mode: MESH_ASSET_ID_FLAT_MODE_UUID,
936 words: [
937 (lo & 0xffff_ffff) as u32,
938 (lo >> 32) as u32,
939 (hi & 0xffff_ffff) as u32,
940 (hi >> 32) as u32,
941 ],
942 }
943 }
944 }
945 }
946}
947
948impl From<MeshAssetIdFlat> for AssetId<Mesh> {
949 #[inline]
950 fn from(value: MeshAssetIdFlat) -> AssetId<Mesh> {
951 if value.mode == MESH_ASSET_ID_FLAT_MODE_INDEX {
952 AssetId::from(AssetIndex::from_bits(
953 (value.words[0] as u64) | ((value.words[1] as u64) << 32),
954 ))
955 } else {
956 let lo = (value.words[0] as u64) | ((value.words[1] as u64) << 32);
957 let hi = (value.words[2] as u64) | ((value.words[3] as u64) << 32);
958 AssetId::Uuid {
959 uuid: Uuid::from_u64_pair(hi, lo),
960 }
961 }
962 }
963}
964
965impl From<Option<LightmapSlabIndex>> for LightmapSlabIndexFlat {
966 #[inline]
967 fn from(value: Option<LightmapSlabIndex>) -> Self {
968 match value {
969 Some(slab_index) => LightmapSlabIndexFlat((*slab_index).into()),
970 None => LightmapSlabIndexFlat(!0),
971 }
972 }
973}
974
975impl From<LightmapSlabIndexFlat> for Option<LightmapSlabIndex> {
976 #[inline]
977 fn from(value: LightmapSlabIndexFlat) -> Self {
978 NonMaxU32::new(value.0).map(LightmapSlabIndex)
979 }
980}
981
982pub struct RenderMeshInstanceShared {
985 pub mesh_asset_id: AssetId<Mesh>,
987 pub material_bindings_index: MaterialBindingId,
989 pub lightmap_slab_index: Option<LightmapSlabIndex>,
992 pub center: Vec3,
998 pub tag: u32,
1000 pub flags: RenderMeshInstanceFlags,
1002}
1003
1004pub struct RenderMeshInstanceGpuBuilder {
1010 pub shared: RenderMeshInstanceSharedFlat,
1012 pub world_from_local: Affine3,
1014 pub lightmap_uv_rect: UVec2,
1026 pub previous_input_index: Option<NonMaxU32>,
1028 pub render_layers: Option<RenderLayers>,
1030 pub mesh_flags: MeshFlags,
1032}
1033
1034#[derive(#[automatically_derived]
impl ::core::default::Default for RenderMeshInstanceGpuQueue {
#[inline]
fn default() -> RenderMeshInstanceGpuQueue { Self::None }
}Default)]
1040pub enum RenderMeshInstanceGpuQueue {
1041 #[default]
1046 None,
1047 CpuCulling {
1051 changed: Vec<(MainEntity, RenderMeshInstanceGpuBuilder)>,
1055 removed: Vec<MainEntity>,
1057 },
1058 GpuCulling {
1062 changed_cpu_culling: Vec<(MainEntity, RenderMeshInstanceGpuBuilder, MeshCullingData)>,
1068 changed_gpu_culling: Vec<(MainEntity, RenderMeshInstanceGpuBuilder, MeshCullingData)>,
1074 removed: Vec<MainEntity>,
1076 },
1077}
1078
1079#[derive(impl bevy_ecs::resource::Resource for RenderMeshInstanceGpuQueues where
Self: ::core::marker::Send + ::core::marker::Sync + 'static {}Resource, #[automatically_derived]
impl ::core::default::Default for RenderMeshInstanceGpuQueues {
#[inline]
fn default() -> RenderMeshInstanceGpuQueues {
RenderMeshInstanceGpuQueues(::core::default::Default::default())
}
}Default, impl ::core::ops::Deref for RenderMeshInstanceGpuQueues {
type Target = Parallel<RenderMeshInstanceGpuQueue>;
fn deref(&self) -> &Self::Target { &self.0 }
}Deref, impl ::core::ops::DerefMut for RenderMeshInstanceGpuQueues {
fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 }
}DerefMut)]
1085pub struct RenderMeshInstanceGpuQueues(Parallel<RenderMeshInstanceGpuQueue>);
1086
1087#[derive(impl bevy_ecs::resource::Resource for MeshesToReextractNextFrame where
Self: ::core::marker::Send + ::core::marker::Sync + 'static {}Resource, #[automatically_derived]
impl ::core::default::Default for MeshesToReextractNextFrame {
#[inline]
fn default() -> MeshesToReextractNextFrame {
MeshesToReextractNextFrame(::core::default::Default::default())
}
}Default, impl ::core::ops::Deref for MeshesToReextractNextFrame {
type Target = MainEntityHashSet;
fn deref(&self) -> &Self::Target { &self.0 }
}Deref, impl ::core::ops::DerefMut for MeshesToReextractNextFrame {
fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 }
}DerefMut)]
1092pub struct MeshesToReextractNextFrame(MainEntityHashSet);
1093
1094impl RenderMeshInstanceSharedFlat {
1095 fn for_gpu_building(
1098 previous_transform: Option<&PreviousGlobalTransform>,
1099 mesh: &Mesh3d,
1100 tag: Option<&MeshTag>,
1101 not_shadow_caster: bool,
1102 no_automatic_batching: bool,
1103 no_cpu_culling: bool,
1104 ) -> Self {
1105 Self::new(
1106 previous_transform,
1107 mesh,
1108 tag,
1109 default(),
1110 not_shadow_caster,
1111 no_automatic_batching,
1112 no_cpu_culling,
1113 )
1114 }
1115
1116 fn for_cpu_building(
1118 previous_transform: Option<&PreviousGlobalTransform>,
1119 mesh: &Mesh3d,
1120 tag: Option<&MeshTag>,
1121 material_bindings_index: MaterialBindingId,
1122 not_shadow_caster: bool,
1123 no_automatic_batching: bool,
1124 ) -> Self {
1125 Self::new(
1126 previous_transform,
1127 mesh,
1128 tag,
1129 material_bindings_index,
1130 not_shadow_caster,
1131 no_automatic_batching,
1132 false,
1133 )
1134 }
1135
1136 fn new(
1137 previous_transform: Option<&PreviousGlobalTransform>,
1138 mesh: &Mesh3d,
1139 tag: Option<&MeshTag>,
1140 material_bindings_index: MaterialBindingId,
1141 not_shadow_caster: bool,
1142 no_automatic_batching: bool,
1143 no_cpu_culling: bool,
1144 ) -> Self {
1145 let mut mesh_instance_flags = RenderMeshInstanceFlags::empty();
1146 mesh_instance_flags.set(RenderMeshInstanceFlags::SHADOW_CASTER, !not_shadow_caster);
1147 mesh_instance_flags.set(
1148 RenderMeshInstanceFlags::AUTOMATIC_BATCHING,
1149 !no_automatic_batching,
1150 );
1151 mesh_instance_flags.set(
1152 RenderMeshInstanceFlags::HAS_PREVIOUS_TRANSFORM,
1153 previous_transform.is_some(),
1154 );
1155 mesh_instance_flags.set(RenderMeshInstanceFlags::NO_CPU_CULLING, no_cpu_culling);
1156
1157 RenderMeshInstanceSharedFlat {
1158 asset_id: mesh.id().into(),
1159 material_bindings_index,
1160 tag: tag.map_or(0, |i| **i),
1161 flags: mesh_instance_flags,
1162 lightmap_slab_index: LightmapSlabIndexFlat::default(),
1164 current_uniform_index: 0,
1166 }
1167 }
1168}
1169
1170#[derive(impl bevy_ecs::resource::Resource for RenderMeshInstances where
Self: ::core::marker::Send + ::core::marker::Sync + 'static {}Resource)]
1176pub enum RenderMeshInstances {
1177 CpuBuilding(RenderMeshInstancesCpu),
1179 GpuBuilding(RenderMeshInstancesGpu),
1181}
1182
1183#[derive(#[automatically_derived]
impl ::core::default::Default for RenderMeshInstancesCpu {
#[inline]
fn default() -> RenderMeshInstancesCpu {
RenderMeshInstancesCpu(::core::default::Default::default())
}
}Default, impl ::core::ops::Deref for RenderMeshInstancesCpu {
type Target = MainEntityHashMap<RenderMeshInstanceCpu>;
fn deref(&self) -> &Self::Target { &self.0 }
}Deref, impl ::core::ops::DerefMut for RenderMeshInstancesCpu {
fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 }
}DerefMut)]
1186pub struct RenderMeshInstancesCpu(MainEntityHashMap<RenderMeshInstanceCpu>);
1187
1188#[derive(#[automatically_derived]
impl ::core::default::Default for RenderMeshInstancesGpu {
#[inline]
fn default() -> RenderMeshInstancesGpu {
RenderMeshInstancesGpu(::core::default::Default::default())
}
}Default, impl ::core::ops::Deref for RenderMeshInstancesGpu {
type Target = MainEntityHashMap<RenderMeshInstanceGpu>;
fn deref(&self) -> &Self::Target { &self.0 }
}Deref, impl ::core::ops::DerefMut for RenderMeshInstancesGpu {
fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 }
}DerefMut)]
1191pub struct RenderMeshInstancesGpu(MainEntityHashMap<RenderMeshInstanceGpu>);
1192
1193impl RenderMeshInstances {
1194 fn new(use_gpu_instance_buffer_builder: bool) -> RenderMeshInstances {
1196 if use_gpu_instance_buffer_builder {
1197 RenderMeshInstances::GpuBuilding(RenderMeshInstancesGpu::default())
1198 } else {
1199 RenderMeshInstances::CpuBuilding(RenderMeshInstancesCpu::default())
1200 }
1201 }
1202
1203 pub fn mesh_asset_id(&self, entity: MainEntity) -> Option<AssetId<Mesh>> {
1205 match *self {
1206 RenderMeshInstances::CpuBuilding(ref instances) => instances.mesh_asset_id(entity),
1207 RenderMeshInstances::GpuBuilding(ref instances) => instances.mesh_asset_id(entity),
1208 }
1209 }
1210
1211 pub fn render_mesh_queue_data(&self, entity: MainEntity) -> Option<RenderMeshQueueData<'_>> {
1214 match *self {
1215 RenderMeshInstances::CpuBuilding(ref instances) => {
1216 instances.render_mesh_queue_data(entity)
1217 }
1218 RenderMeshInstances::GpuBuilding(ref instances) => {
1219 instances.render_mesh_queue_data(entity)
1220 }
1221 }
1222 }
1223
1224 fn insert_mesh_instance_flags(&mut self, entity: MainEntity, flags: RenderMeshInstanceFlags) {
1227 match *self {
1228 RenderMeshInstances::CpuBuilding(ref mut instances) => {
1229 instances.insert_mesh_instance_flags(entity, flags);
1230 }
1231 RenderMeshInstances::GpuBuilding(ref mut instances) => {
1232 instances.insert_mesh_instance_flags(entity, flags);
1233 }
1234 }
1235 }
1236}
1237
1238impl RenderMeshInstancesCpu {
1239 fn mesh_asset_id(&self, entity: MainEntity) -> Option<AssetId<Mesh>> {
1240 self.get(&entity)
1241 .map(|render_mesh_instance| render_mesh_instance.mesh_asset_id())
1242 }
1243
1244 fn render_mesh_queue_data(&self, entity: MainEntity) -> Option<RenderMeshQueueData<'_>> {
1245 self.get(&entity)
1246 .map(|render_mesh_instance| RenderMeshQueueData {
1247 shared: &render_mesh_instance.shared,
1248 render_layers: render_mesh_instance.render_layers.clone(),
1249 current_uniform_index: InputUniformIndex::default(),
1250 })
1251 }
1252
1253 fn insert_mesh_instance_flags(&mut self, entity: MainEntity, flags: RenderMeshInstanceFlags) {
1256 if let Some(instance) = self.get_mut(&entity) {
1257 instance.set_flags(instance.flags() | flags);
1258 }
1259 }
1260}
1261
1262impl RenderMeshInstancesGpu {
1263 fn mesh_asset_id(&self, entity: MainEntity) -> Option<AssetId<Mesh>> {
1264 self.get(&entity)
1265 .map(|render_mesh_instance| render_mesh_instance.mesh_asset_id())
1266 }
1267
1268 fn render_mesh_queue_data(&self, entity: MainEntity) -> Option<RenderMeshQueueData<'_>> {
1269 self.get(&entity)
1270 .map(|render_mesh_instance| RenderMeshQueueData {
1271 shared: &render_mesh_instance.shared,
1272 render_layers: render_mesh_instance.render_layers.clone(),
1273 current_uniform_index: InputUniformIndex(
1274 render_mesh_instance.gpu_specific.current_uniform_index(),
1275 ),
1276 })
1277 }
1278
1279 fn insert_mesh_instance_flags(&mut self, entity: MainEntity, flags: RenderMeshInstanceFlags) {
1282 if let Some(instance) = self.get_mut(&entity) {
1283 instance.set_flags(instance.flags() | flags);
1284 }
1285 }
1286}
1287
1288impl RenderMeshInstanceGpuQueue {
1289 fn init(&mut self, any_gpu_culling: bool) {
1295 match (any_gpu_culling, &mut *self) {
1296 (
1297 true,
1298 RenderMeshInstanceGpuQueue::GpuCulling {
1299 changed_cpu_culling,
1300 changed_gpu_culling,
1301 removed,
1302 },
1303 ) => {
1304 changed_cpu_culling.clear();
1305 changed_gpu_culling.clear();
1306 removed.clear();
1307 }
1308 (true, _) => {
1309 *self = RenderMeshInstanceGpuQueue::GpuCulling {
1310 changed_cpu_culling: ::alloc::vec::Vec::new()vec![],
1311 changed_gpu_culling: ::alloc::vec::Vec::new()vec![],
1312 removed: ::alloc::vec::Vec::new()vec![],
1313 }
1314 }
1315 (false, RenderMeshInstanceGpuQueue::CpuCulling { changed, removed }) => {
1316 changed.clear();
1317 removed.clear();
1318 }
1319 (false, _) => {
1320 *self = RenderMeshInstanceGpuQueue::CpuCulling {
1321 changed: ::alloc::vec::Vec::new()vec![],
1322 removed: ::alloc::vec::Vec::new()vec![],
1323 }
1324 }
1325 }
1326 }
1327
1328 fn push(
1330 &mut self,
1331 entity: MainEntity,
1332 instance_builder: RenderMeshInstanceGpuBuilder,
1333 culling_data_builder: Option<MeshCullingData>,
1334 no_cpu_culling: bool,
1335 ) {
1336 match (&mut *self, culling_data_builder, no_cpu_culling) {
1337 (
1338 &mut RenderMeshInstanceGpuQueue::CpuCulling {
1339 changed: ref mut queue,
1340 ..
1341 },
1342 None,
1343 _,
1344 ) => {
1345 queue.push((entity, instance_builder));
1346 }
1347
1348 (
1349 &mut RenderMeshInstanceGpuQueue::GpuCulling {
1350 changed_cpu_culling: ref mut queue,
1351 ..
1352 },
1353 Some(culling_data_builder),
1354 false,
1355 )
1356 | (
1357 &mut RenderMeshInstanceGpuQueue::GpuCulling {
1358 changed_gpu_culling: ref mut queue,
1359 ..
1360 },
1361 Some(culling_data_builder),
1362 true,
1363 ) => {
1364 queue.push((entity, instance_builder, culling_data_builder));
1365 }
1366
1367 (_, None, _) => {
1368 *self = RenderMeshInstanceGpuQueue::CpuCulling {
1369 changed: ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[(entity, instance_builder)]))vec![(entity, instance_builder)],
1370 removed: ::alloc::vec::Vec::new()vec![],
1371 };
1372 }
1373
1374 (_, Some(culling_data_builder), false) => {
1375 *self = RenderMeshInstanceGpuQueue::GpuCulling {
1376 changed_cpu_culling: ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[(entity, instance_builder, culling_data_builder)]))vec![(entity, instance_builder, culling_data_builder)],
1377 changed_gpu_culling: ::alloc::vec::Vec::new()vec![],
1378 removed: ::alloc::vec::Vec::new()vec![],
1379 };
1380 }
1381 (_, Some(culling_data_builder), true) => {
1382 *self = RenderMeshInstanceGpuQueue::GpuCulling {
1383 changed_cpu_culling: ::alloc::vec::Vec::new()vec![],
1384 changed_gpu_culling: ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[(entity, instance_builder, culling_data_builder)]))vec![(entity, instance_builder, culling_data_builder)],
1385 removed: ::alloc::vec::Vec::new()vec![],
1386 };
1387 }
1388 }
1389 }
1390
1391 fn remove(&mut self, entity: MainEntity, gpu_culling: bool) {
1395 match (&mut *self, gpu_culling) {
1396 (RenderMeshInstanceGpuQueue::None, false) => {
1397 *self = RenderMeshInstanceGpuQueue::CpuCulling {
1398 changed: ::alloc::vec::Vec::new()vec![],
1399 removed: ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[entity]))vec![entity],
1400 }
1401 }
1402 (RenderMeshInstanceGpuQueue::None, true) => {
1403 *self = RenderMeshInstanceGpuQueue::GpuCulling {
1404 changed_cpu_culling: ::alloc::vec::Vec::new()vec![],
1405 changed_gpu_culling: ::alloc::vec::Vec::new()vec![],
1406 removed: ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[entity]))vec![entity],
1407 }
1408 }
1409 (RenderMeshInstanceGpuQueue::CpuCulling { removed, .. }, _)
1410 | (RenderMeshInstanceGpuQueue::GpuCulling { removed, .. }, _) => {
1411 removed.push(entity);
1412 }
1413 }
1414 }
1415}
1416
1417impl RenderMeshInstanceGpuBuilder {
1418 fn prepare(
1422 mut self,
1423 entity: MainEntity,
1424 mesh_allocator: &MeshAllocator,
1425 mesh_material_ids: &RenderMaterialInstances,
1426 render_material_bindings: &RenderMaterialBindings,
1427 render_lightmaps: &RenderLightmaps,
1428 skin_uniforms: &SkinUniforms,
1429 morph_indices: &MorphIndices,
1430 timestamp: FrameCount,
1431 ) -> Option<RenderMeshInstanceGpuPrepared> {
1432 let mesh_material = mesh_material_ids.mesh_material(entity);
1438 let mesh_material_binding_id = if mesh_material != DUMMY_MESH_MATERIAL.untyped() {
1439 render_material_bindings.get(&mesh_material).copied()?
1440 } else {
1441 MaterialBindingId::default()
1443 };
1444 self.shared.material_bindings_index = mesh_material_binding_id;
1445
1446 let (first_vertex_index, vertex_count) =
1447 match mesh_allocator.mesh_vertex_slice(&self.shared.asset_id.into()) {
1448 Some(mesh_vertex_slice) => (
1449 mesh_vertex_slice.range.start,
1450 mesh_vertex_slice.range.end - mesh_vertex_slice.range.start,
1451 ),
1452 None => (0, 0),
1453 };
1454 let (mesh_is_indexed, first_index_index, index_count) =
1455 match mesh_allocator.mesh_index_slice(&self.shared.asset_id.into()) {
1456 Some(mesh_index_slice) => (
1457 true,
1458 mesh_index_slice.range.start,
1459 mesh_index_slice.range.end - mesh_index_slice.range.start,
1460 ),
1461 None => (false, 0, 0),
1462 };
1463 let current_skin_index = match skin_uniforms.skin_byte_offset(entity) {
1464 Some(skin_index) => skin_index.index(),
1465 None => u32::MAX,
1466 };
1467
1468 let lightmap_slot = match render_lightmaps.render_lightmaps.get(&entity) {
1469 Some(render_lightmap) => u16::from(*render_lightmap.slot_index),
1470 None => u16::MAX,
1471 };
1472 let lightmap_slab_index = render_lightmaps
1473 .render_lightmaps
1474 .get(&entity)
1475 .map(|lightmap| lightmap.slab_index);
1476 self.shared.lightmap_slab_index = lightmap_slab_index.into();
1477
1478 let morph_descriptor_index = match morph_indices.morph_descriptor_index(entity) {
1479 Some(morph_descriptor_index) => *morph_descriptor_index,
1480 None => u32::MAX,
1481 };
1482
1483 let material_slot = u32::from(self.shared.material_bindings_index.slot);
1485 if true {
if !(material_slot <= 0xFFFF) {
{
::core::panicking::panic_fmt(format_args!("Material bind group slot {0} overflowed",
material_slot));
}
};
};debug_assert!(
1486 material_slot <= 0xFFFF,
1487 "Material bind group slot {material_slot} overflowed"
1488 );
1489 let material_and_lightmap_bind_group_slot = material_slot | ((lightmap_slot as u32) << 16);
1490
1491 let mesh_input_uniform = MeshInputUniform {
1492 world_from_local: self.world_from_local.to_transpose(),
1493 lightmap_uv_rect: self.lightmap_uv_rect,
1494 flags: self.mesh_flags.bits(),
1495 previous_input_index: u32::MAX,
1496 timestamp: timestamp.0,
1497 first_vertex_index,
1498 first_index_index,
1499 index_count: if mesh_is_indexed {
1500 index_count
1501 } else {
1502 vertex_count
1503 },
1504 current_skin_index,
1505 material_and_lightmap_bind_group_slot,
1506 tag: self.shared.tag,
1507 morph_descriptor_index,
1508 };
1509
1510 Some(RenderMeshInstanceGpuPrepared {
1511 shared: self.shared,
1512 mesh_input_uniform,
1513 render_layers: self.render_layers,
1514 })
1515 }
1516}
1517
1518pub struct RenderMeshInstanceGpuPrepared {
1520 shared: RenderMeshInstanceSharedFlat,
1522 mesh_input_uniform: MeshInputUniform,
1524 render_layers: Option<RenderLayers>,
1526}
1527
1528impl RenderMeshInstanceGpuPrepared {
1529 fn update(
1532 mut self,
1533 entity: MainEntity,
1534 render_mesh_instances: &mut MainEntityHashMap<RenderMeshInstanceGpu>,
1535 current_input_buffer: &mut InstanceInputUniformBuffer<MeshInputUniform>,
1536 previous_input_buffer: &PreviousInstanceInputUniformBuffer<MeshInputUniform>,
1537 ) -> u32 {
1538 let current_uniform_index;
1540 match render_mesh_instances.entry(entity) {
1541 Entry::Occupied(mut occupied_entry) => {
1542 current_uniform_index = occupied_entry
1546 .get_mut()
1547 .gpu_specific
1548 .current_uniform_index();
1549
1550 let previous_mesh_input_uniform =
1553 current_input_buffer.get_unchecked(current_uniform_index);
1554 let previous_input_index = previous_input_buffer.push(previous_mesh_input_uniform);
1555 self.mesh_input_uniform.previous_input_index = previous_input_index;
1556
1557 current_input_buffer.set(current_uniform_index, self.mesh_input_uniform);
1559
1560 let existing_instance = occupied_entry.get_mut();
1562 self.shared.write_to_blob(&existing_instance.shared);
1563 existing_instance
1564 .gpu_specific
1565 .set_current_uniform_index(current_uniform_index);
1566 existing_instance.render_layers = self.render_layers.clone();
1567 }
1568
1569 Entry::Vacant(vacant_entry) => {
1570 current_uniform_index = current_input_buffer.add(self.mesh_input_uniform);
1572
1573 let new_instance = vacant_entry.insert(RenderMeshInstanceGpu {
1574 shared: RenderMeshInstanceSharedFlatBlob::default(),
1575 gpu_specific: RenderMeshInstanceGpuFlatBlob::default(),
1576 render_layers: self.render_layers.clone(),
1577 });
1578 self.shared.write_to_blob(&new_instance.shared);
1579 RenderMeshInstanceGpuFlat {
1580 current_uniform_index,
1581 }
1582 .write_to_blob(&new_instance.gpu_specific);
1583 }
1584 }
1585
1586 current_uniform_index
1587 }
1588}
1589
1590fn remove_mesh_input_uniform(
1593 entity: MainEntity,
1594 render_mesh_instances: &mut MainEntityHashMap<RenderMeshInstanceGpu>,
1595 current_input_buffer: &mut InstanceInputUniformBuffer<MeshInputUniform>,
1596) -> Option<u32> {
1597 let removed_render_mesh_instance = render_mesh_instances.remove(&entity)?;
1599
1600 let removed_uniform_index = removed_render_mesh_instance
1601 .gpu_specific
1602 .current_uniform_index();
1603 current_input_buffer.remove(removed_uniform_index);
1604 Some(removed_uniform_index)
1605}
1606
1607impl MeshCullingData {
1608 fn new(aabb: Option<&Aabb>) -> Self {
1613 match aabb {
1614 Some(aabb) => MeshCullingData {
1615 aabb_center: aabb.center.extend(0.0),
1616 aabb_half_extents: aabb.half_extents.extend(0.0),
1617 },
1618 None => MeshCullingData {
1619 aabb_center: Vec3::ZERO.extend(0.0),
1620 aabb_half_extents: Vec3::INFINITY.extend(0.0),
1621 },
1622 }
1623 }
1624
1625 fn update(
1628 &self,
1629 mesh_culling_data_buffer: &mut MeshCullingDataBuffer,
1630 instance_data_index: u32,
1631 ) {
1632 while mesh_culling_data_buffer.len() < instance_data_index + 1 {
1633 mesh_culling_data_buffer.push(MeshCullingData::default());
1634 }
1635 mesh_culling_data_buffer.set(instance_data_index, *self);
1636 }
1637}
1638
1639impl Default for MeshCullingDataBuffer {
1640 #[inline]
1641 fn default() -> Self {
1642 Self(AtomicSparseBufferVec::new(
1643 BufferUsages::STORAGE,
1644 8,
1645 Arc::from("mesh culling data buffer"),
1646 ))
1647 }
1648}
1649
1650#[derive(impl<'a> ::core::ops::Deref for RenderMeshQueueData<'a> {
type Target = &'a RenderMeshInstanceSharedFlatBlob;
fn deref(&self) -> &Self::Target { &self.shared }
}Deref)]
1653pub struct RenderMeshQueueData<'a> {
1654 #[deref]
1656 pub shared: &'a RenderMeshInstanceSharedFlatBlob,
1657 pub render_layers: Option<RenderLayers>,
1659 pub current_uniform_index: InputUniformIndex,
1662}
1663
1664#[derive(const _: () =
{
extern crate alloc;
impl bevy_ecs::schedule::SystemSet for MeshExtractionSystems where
Self: 'static + ::core::marker::Send + ::core::marker::Sync +
::core::clone::Clone + ::core::cmp::Eq + ::core::fmt::Debug +
::core::hash::Hash {
fn dyn_clone(&self)
-> alloc::boxed::Box<dyn bevy_ecs::schedule::SystemSet> {
alloc::boxed::Box::new(::core::clone::Clone::clone(self))
}
}
};SystemSet, #[automatically_derived]
impl ::core::clone::Clone for MeshExtractionSystems {
#[inline]
fn clone(&self) -> MeshExtractionSystems { MeshExtractionSystems }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for MeshExtractionSystems {
#[inline]
fn eq(&self, other: &MeshExtractionSystems) -> bool { true }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for MeshExtractionSystems {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {}
}Eq, #[automatically_derived]
impl ::core::fmt::Debug for MeshExtractionSystems {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f, "MeshExtractionSystems")
}
}Debug, #[automatically_derived]
impl ::core::hash::Hash for MeshExtractionSystems {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {}
}Hash)]
1667pub struct MeshExtractionSystems;
1668
1669#[derive(impl bevy_ecs::resource::Resource for RenderGpuCulledEntities where
Self: ::core::marker::Send + ::core::marker::Sync + 'static {}Resource, #[automatically_derived]
impl ::core::default::Default for RenderGpuCulledEntities {
#[inline]
fn default() -> RenderGpuCulledEntities {
RenderGpuCulledEntities {
entities: ::core::default::Default::default(),
added: ::core::default::Default::default(),
removed: ::core::default::Default::default(),
changed_layers: ::core::default::Default::default(),
}
}
}Default)]
1676pub struct RenderGpuCulledEntities {
1677 pub entities: MainEntityHashMap<RenderLayers>,
1680
1681 pub added: Vec<MainEntity>,
1691
1692 pub removed: Vec<MainEntity>,
1701
1702 pub changed_layers: Vec<MainEntity>,
1705}
1706
1707impl RenderGpuCulledEntities {
1708 pub fn prepare_for_new_frame(&mut self) {
1712 self.added.clear();
1713 self.removed.clear();
1714 self.changed_layers.clear();
1715 }
1716
1717 pub fn update(
1723 &mut self,
1724 new_entity: MainEntity,
1725 render_layers: RenderLayers,
1726 no_cpu_culling: bool,
1727 ) {
1728 match self.entities.entry(new_entity) {
1729 Entry::Occupied(mut occupied_entry) => {
1730 if no_cpu_culling {
1731 occupied_entry.insert(render_layers);
1732 } else {
1733 occupied_entry.remove();
1734 self.removed.push(new_entity);
1735 }
1736 }
1737 Entry::Vacant(vacant_entry) => {
1738 if no_cpu_culling {
1739 vacant_entry.insert(render_layers);
1740 self.added.push(new_entity);
1741 }
1742 }
1743 }
1744 }
1745
1746 pub fn remove(&mut self, old_entity: MainEntity) {
1748 self.removed.push(old_entity);
1749 self.entities.remove(&old_entity);
1750 }
1751}
1752
1753pub fn extract_meshes_for_cpu_building(
1759 mut render_mesh_instances: ResMut<RenderMeshInstances>,
1760 mesh_material_ids: Res<RenderMaterialInstances>,
1761 render_material_bindings: Res<RenderMaterialBindings>,
1762 render_visibility_ranges: Res<RenderVisibilityRanges>,
1763 mut render_mesh_instance_queues: Local<Parallel<Vec<(Entity, RenderMeshInstanceCpu)>>>,
1764 meshes_query: Extract<
1765 Query<(
1766 Entity,
1767 &ViewVisibility,
1768 &GlobalTransform,
1769 Option<&PreviousGlobalTransform>,
1770 &Mesh3d,
1771 Option<&MeshTag>,
1772 Has<NoFrustumCulling>,
1773 Has<NotShadowReceiver>,
1774 Has<TransmittedShadowReceiver>,
1775 Has<NotShadowCaster>,
1776 Has<NoAutomaticBatching>,
1777 Option<&VisibilityRange>,
1778 Option<&RenderLayers>,
1779 )>,
1780 >,
1781) {
1782 meshes_query.par_iter().for_each_init(
1783 || render_mesh_instance_queues.borrow_local_mut(),
1784 |queue,
1785 (
1786 entity,
1787 view_visibility,
1788 transform,
1789 previous_transform,
1790 mesh,
1791 tag,
1792 no_frustum_culling,
1793 not_shadow_receiver,
1794 transmitted_receiver,
1795 not_shadow_caster,
1796 no_automatic_batching,
1797 visibility_range,
1798 render_layers,
1799 )| {
1800 if !view_visibility.get() {
1801 return;
1802 }
1803
1804 let mut lod_index = None;
1805 if visibility_range.is_some() {
1806 lod_index = render_visibility_ranges.lod_index_for_entity(entity.into());
1807 }
1808
1809 let mesh_flags = MeshFlags::from_components(
1810 transform,
1811 lod_index,
1812 visibility_range,
1813 no_frustum_culling,
1814 not_shadow_receiver,
1815 transmitted_receiver,
1816 );
1817
1818 let mesh_material = mesh_material_ids.mesh_material(MainEntity::from(entity));
1819
1820 let material_bindings_index = render_material_bindings
1821 .get(&mesh_material)
1822 .copied()
1823 .unwrap_or_default();
1824
1825 let shared = RenderMeshInstanceSharedFlat::for_cpu_building(
1826 previous_transform,
1827 mesh,
1828 tag,
1829 material_bindings_index,
1830 not_shadow_caster,
1831 no_automatic_batching,
1832 );
1833
1834 let world_from_local = transform.affine();
1835 let previous_world_from_local = previous_transform
1836 .map(|previous_transform| previous_transform.0)
1837 .unwrap_or(world_from_local);
1838
1839 queue.push((
1840 entity,
1841 RenderMeshInstanceCpu {
1842 transforms: MeshTransforms {
1843 world_from_local: world_from_local.into(),
1844 previous_world_from_local: previous_world_from_local.into(),
1845 flags: mesh_flags.bits(),
1846 },
1847 shared: (&shared).into(),
1848 render_layers: render_layers.cloned(),
1849 },
1850 ));
1851 },
1852 );
1853
1854 let RenderMeshInstances::CpuBuilding(ref mut render_mesh_instances) = *render_mesh_instances
1856 else {
1857 {
::core::panicking::panic_fmt(format_args!("`extract_meshes_for_cpu_building` should only be called if we\'re using CPU `MeshUniform` building"));
};panic!(
1858 "`extract_meshes_for_cpu_building` should only be called if we're using CPU \
1859 `MeshUniform` building"
1860 );
1861 };
1862
1863 render_mesh_instances.clear();
1864 for queue in render_mesh_instance_queues.iter_mut() {
1865 for (entity, render_mesh_instance) in queue.drain(..) {
1866 render_mesh_instances.insert(entity.into(), render_mesh_instance);
1867 }
1868 }
1869}
1870
1871type GpuMeshExtractionQuery = (
1873 Entity,
1874 Read<ViewVisibility>,
1875 Read<GlobalTransform>,
1876 Option<Read<PreviousGlobalTransform>>,
1877 Option<Read<Lightmap>>,
1878 Option<Read<Aabb>>,
1879 Read<Mesh3d>,
1880 Option<Read<MeshTag>>,
1881 (
1882 Has<NoFrustumCulling>,
1883 Has<NotShadowReceiver>,
1884 Has<TransmittedShadowReceiver>,
1885 Has<NotShadowCaster>,
1886 Has<NoAutomaticBatching>,
1887 Has<NoCpuCulling>,
1888 ),
1889 Option<Read<VisibilityRange>>,
1890 Option<Read<RenderLayers>>,
1891);
1892
1893pub fn extract_meshes_for_gpu_building(
1902 mut render_mesh_instances: ResMut<RenderMeshInstances>,
1903 render_visibility_ranges: Res<RenderVisibilityRanges>,
1904 mut render_mesh_instance_queues: ResMut<RenderMeshInstanceGpuQueues>,
1905 changed_meshes_query: Extract<
1906 Query<
1907 GpuMeshExtractionQuery,
1908 Or<(
1909 Changed<ViewVisibility>,
1910 Changed<GlobalTransform>,
1911 Changed<PreviousGlobalTransform>,
1912 Changed<Lightmap>,
1913 Changed<Aabb>,
1914 Changed<Mesh3d>,
1915 Changed<MeshTag>,
1916 Or<(
1917 Changed<NoFrustumCulling>,
1918 Changed<NotShadowReceiver>,
1919 Changed<TransmittedShadowReceiver>,
1920 Changed<NotShadowCaster>,
1921 Changed<NoAutomaticBatching>,
1922 Changed<NoCpuCulling>,
1923 )>,
1924 Changed<VisibilityRange>,
1925 Changed<SkinnedMesh>,
1926 )>,
1927 >,
1928 >,
1929 (
1930 mut removed_previous_global_transform_query,
1931 mut removed_lightmap_query,
1932 mut removed_aabb_query,
1933 mut removed_mesh_tag_query,
1934 mut removed_no_frustum_culling_query,
1935 mut removed_not_shadow_receiver_query,
1936 mut removed_transmitted_receiver_query,
1937 mut removed_not_shadow_caster_query,
1938 mut removed_no_automatic_batching_query,
1939 mut removed_no_cpu_culling_query,
1940 mut removed_visibility_range_query,
1941 mut removed_skinned_mesh_query,
1942 ): (
1943 Extract<RemovedComponents<PreviousGlobalTransform>>,
1944 Extract<RemovedComponents<Lightmap>>,
1945 Extract<RemovedComponents<Aabb>>,
1946 Extract<RemovedComponents<MeshTag>>,
1947 Extract<RemovedComponents<NoFrustumCulling>>,
1948 Extract<RemovedComponents<NotShadowReceiver>>,
1949 Extract<RemovedComponents<TransmittedShadowReceiver>>,
1950 Extract<RemovedComponents<NotShadowCaster>>,
1951 Extract<RemovedComponents<NoAutomaticBatching>>,
1952 Extract<RemovedComponents<NoCpuCulling>>,
1953 Extract<RemovedComponents<VisibilityRange>>,
1954 Extract<RemovedComponents<SkinnedMesh>>,
1955 ),
1956 all_meshes_query: Extract<Query<GpuMeshExtractionQuery>>,
1957 mut removed_meshes_query: Extract<RemovedComponents<Mesh3d>>,
1958 gpu_culling_query: Extract<Query<(), (With<Camera>, Without<NoIndirectDrawing>)>>,
1959 meshes_to_reextract_next_frame: ResMut<MeshesToReextractNextFrame>,
1960 mut reextract_entities: Local<EntityHashSet>,
1961 mut potential_reextraction_set: Local<IndexSet<Entity, EntityHash>>,
1962 mut potential_reextraction_bitfield: Local<Vec<AtomicU64>>,
1963) {
1964 reextract_entities.clear();
1965
1966 let any_gpu_culling = !gpu_culling_query.is_empty();
1968 for render_mesh_instance_queue in render_mesh_instance_queues.iter_mut() {
1969 render_mesh_instance_queue.init(any_gpu_culling);
1970 }
1971
1972 potential_reextraction_set.clear();
1979 potential_reextraction_set.extend(
1980 meshes_to_reextract_next_frame
1981 .iter()
1982 .map(|&e| *e)
1983 .chain(removed_previous_global_transform_query.read())
1984 .chain(removed_lightmap_query.read())
1985 .chain(removed_aabb_query.read())
1986 .chain(removed_mesh_tag_query.read())
1987 .chain(removed_no_frustum_culling_query.read())
1988 .chain(removed_not_shadow_receiver_query.read())
1989 .chain(removed_transmitted_receiver_query.read())
1990 .chain(removed_not_shadow_caster_query.read())
1991 .chain(removed_no_automatic_batching_query.read())
1992 .chain(removed_no_cpu_culling_query.read())
1993 .chain(removed_visibility_range_query.read())
1994 .chain(removed_skinned_mesh_query.read()),
1995 );
1996
1997 potential_reextraction_bitfield.clear();
2004 potential_reextraction_bitfield.extend(
2005 iter::repeat_with(|| AtomicU64::new(0)).take(potential_reextraction_set.len().div_ceil(64)),
2006 );
2007
2008 let RenderMeshInstances::GpuBuilding(ref mut render_mesh_instances) = *render_mesh_instances
2011 else {
2012 {
::core::panicking::panic_fmt(format_args!("`extract_meshes_for_gpu_building` should only be called if we\'re using GPU `MeshUniform` building"));
};panic!(
2013 "`extract_meshes_for_gpu_building` should only be called if we're \
2014 using GPU `MeshUniform` building"
2015 );
2016 };
2017
2018 changed_meshes_query.par_iter().for_each_init(
2021 || render_mesh_instance_queues.borrow_local_mut(),
2022 |queue, query_row| {
2023 extract_mesh_for_gpu_building(
2024 query_row,
2025 &render_visibility_ranges,
2026 render_mesh_instances,
2027 queue,
2028 any_gpu_culling,
2029 );
2030
2031 if let Some(bit_index) = potential_reextraction_set.get_index_of(&query_row.0) {
2034 potential_reextraction_bitfield[bit_index / 64]
2035 .fetch_or(1 << (bit_index % 64), Ordering::Relaxed);
2036 }
2037 },
2038 );
2039
2040 for bit in AtomicU64ZeroBitIter::new(&potential_reextraction_bitfield) {
2049 if let Some(entity) = potential_reextraction_set.get_index(bit as usize) {
2050 reextract_entities.insert(*entity);
2051 }
2052 }
2053
2054 let mut queue = render_mesh_instance_queues.borrow_local_mut();
2056 for entity in &reextract_entities {
2057 if let Ok(query_row) = all_meshes_query.get(*entity) {
2058 extract_mesh_for_gpu_building(
2059 query_row,
2060 &render_visibility_ranges,
2061 render_mesh_instances,
2062 &mut queue,
2063 any_gpu_culling,
2064 );
2065 }
2066 }
2067
2068 for entity in removed_meshes_query.read() {
2070 let entity = MainEntity::from(entity);
2074 if !changed_meshes_query.contains(*entity)
2075 && !meshes_to_reextract_next_frame.contains(&entity)
2076 {
2077 queue.remove(entity, any_gpu_culling);
2078 }
2079 }
2080}
2081
2082fn extract_mesh_for_gpu_building(
2085 (
2086 entity,
2087 view_visibility,
2088 transform,
2089 previous_transform,
2090 lightmap,
2091 aabb,
2092 mesh,
2093 tag,
2094 (
2095 no_frustum_culling,
2096 not_shadow_receiver,
2097 transmitted_receiver,
2098 not_shadow_caster,
2099 no_automatic_batching,
2100 no_cpu_culling,
2101 ),
2102 visibility_range,
2103 render_layers,
2104 ): <GpuMeshExtractionQuery as QueryData>::Item<'_, '_>,
2105 render_visibility_ranges: &RenderVisibilityRanges,
2106 render_mesh_instances: &RenderMeshInstancesGpu,
2107 queue: &mut RenderMeshInstanceGpuQueue,
2108 any_gpu_culling: bool,
2109) {
2110 if !view_visibility.get() {
2112 queue.remove(entity.into(), any_gpu_culling);
2113 return;
2114 }
2115
2116 let mut lod_index = None;
2118 if visibility_range.is_some() {
2119 lod_index = render_visibility_ranges.lod_index_for_entity(entity.into());
2120 }
2121
2122 let mesh_flags = MeshFlags::from_components(
2124 transform,
2125 lod_index,
2126 visibility_range,
2127 no_frustum_culling,
2128 not_shadow_receiver,
2129 transmitted_receiver,
2130 );
2131
2132 let shared = RenderMeshInstanceSharedFlat::for_gpu_building(
2134 previous_transform,
2135 mesh,
2136 tag,
2137 not_shadow_caster,
2138 no_automatic_batching,
2139 no_cpu_culling,
2140 );
2141
2142 let lightmap_uv_rect = pack_lightmap_uv_rect(lightmap.map(|lightmap| lightmap.uv_rect));
2144
2145 let gpu_mesh_culling_data = any_gpu_culling.then(|| MeshCullingData::new(aabb));
2147
2148 let previous_input_index = if shared
2151 .flags
2152 .contains(RenderMeshInstanceFlags::HAS_PREVIOUS_TRANSFORM)
2153 {
2154 render_mesh_instances
2155 .get(&MainEntity::from(entity))
2156 .and_then(|render_mesh_instance| {
2157 NonMaxU32::new(render_mesh_instance.gpu_specific.current_uniform_index())
2158 })
2159 } else {
2160 None
2161 };
2162
2163 let gpu_mesh_instance_builder = RenderMeshInstanceGpuBuilder {
2166 shared,
2167 world_from_local: (transform.affine()).into(),
2168 lightmap_uv_rect,
2169 mesh_flags,
2170 previous_input_index,
2171 render_layers: render_layers.cloned(),
2172 };
2173
2174 queue.push(
2176 entity.into(),
2177 gpu_mesh_instance_builder,
2178 gpu_mesh_culling_data,
2179 no_cpu_culling,
2180 );
2181}
2182
2183struct AtomicU64ZeroBitIter<'a> {
2185 bits: &'a [AtomicU64],
2187 current_word: u64,
2191 next_index: usize,
2193}
2194
2195impl<'a> AtomicU64ZeroBitIter<'a> {
2196 fn new(bits: &'a [AtomicU64]) -> AtomicU64ZeroBitIter<'a> {
2199 AtomicU64ZeroBitIter {
2200 bits,
2201 current_word: !0,
2202 next_index: 0,
2203 }
2204 }
2205}
2206
2207impl<'a> Iterator for AtomicU64ZeroBitIter<'a> {
2208 type Item = u32;
2209
2210 fn next(&mut self) -> Option<Self::Item> {
2211 while self.current_word == !0 {
2213 self.current_word = self.bits.get(self.next_index)?.load(Ordering::Relaxed);
2214 self.next_index += 1;
2215 }
2216
2217 let bit_index = self.current_word.trailing_ones();
2219 self.current_word |= 1 << bit_index;
2220 let word_index = ((self.next_index - 1) * 64) as u32;
2221 Some(word_index + bit_index)
2222 }
2223}
2224
2225pub fn collect_gpu_culled_meshes(
2232 mut cameras: Query<(Option<&RenderLayers>, &mut RenderVisibleEntities), With<ExtractedView>>,
2233 mut lights: Query<(Option<&RenderLayers>, &mut RenderShadowMapVisibleEntities)>,
2234 mut render_gpu_culled_entities: ResMut<RenderGpuCulledEntities>,
2235) {
2236 for (maybe_render_layers, mut render_visible_entities) in &mut cameras {
2238 collect_gpu_culled_meshes_for_subview(
2239 maybe_render_layers,
2240 &mut render_visible_entities,
2241 &mut render_gpu_culled_entities,
2242 );
2243 }
2244
2245 for (maybe_render_layers, mut render_shadow_map_visible_entities) in &mut lights {
2247 for render_visible_entities in render_shadow_map_visible_entities.subviews.values_mut() {
2248 collect_gpu_culled_meshes_for_subview(
2249 maybe_render_layers,
2250 render_visible_entities,
2251 &mut render_gpu_culled_entities,
2252 );
2253 }
2254 }
2255}
2256
2257fn collect_gpu_culled_meshes_for_subview(
2264 maybe_view_render_layers: Option<&RenderLayers>,
2265 render_visible_entities: &mut RenderVisibleEntities,
2266 render_mesh_instance_gpu_queues: &mut RenderGpuCulledEntities,
2267) {
2268 let render_view_visible_mesh_entities = render_visible_entities
2270 .classes
2271 .entry(TypeId::of::<Mesh3d>())
2272 .or_default();
2273
2274 for main_entity in &render_mesh_instance_gpu_queues.removed {
2276 if render_view_visible_mesh_entities
2277 .entities_gpu_culling
2278 .remove(main_entity)
2279 .is_some()
2280 {
2281 render_view_visible_mesh_entities
2282 .removed_entities
2283 .push((Entity::PLACEHOLDER, *main_entity));
2284 }
2285 }
2286
2287 let mut any_added = false;
2289 for main_entity in &render_mesh_instance_gpu_queues.added {
2290 let maybe_entity_render_layers = render_mesh_instance_gpu_queues.entities.get(main_entity);
2292 if let (Some(view_render_layers), Some(entity_render_layers)) =
2293 (maybe_view_render_layers, maybe_entity_render_layers)
2294 && !view_render_layers.intersects(entity_render_layers)
2295 {
2296 continue;
2297 }
2298
2299 render_view_visible_mesh_entities
2302 .entities_gpu_culling
2303 .insert(*main_entity, Entity::PLACEHOLDER);
2304 render_view_visible_mesh_entities.add_entity((Entity::PLACEHOLDER, *main_entity));
2305 any_added = true;
2306 }
2307
2308 for main_entity in &render_mesh_instance_gpu_queues.changed_layers {
2310 let Some(new_render_layers) = render_mesh_instance_gpu_queues.entities.get(main_entity)
2311 else {
2312 continue;
2313 };
2314
2315 let entity_was_visible = render_view_visible_mesh_entities
2317 .entities_gpu_culling
2318 .contains_key(main_entity);
2319 let entity_is_visible = maybe_view_render_layers
2320 .is_none_or(|render_layers| render_layers.intersects(new_render_layers));
2321 match (entity_was_visible, entity_is_visible) {
2322 (false, false) | (true, true) => {
2323 }
2325 (false, true) => {
2326 render_view_visible_mesh_entities
2328 .entities_gpu_culling
2329 .insert(*main_entity, Entity::PLACEHOLDER);
2330 render_view_visible_mesh_entities.add_entity((Entity::PLACEHOLDER, *main_entity));
2331 any_added = true;
2332 }
2333 (true, false) => {
2334 render_view_visible_mesh_entities
2336 .entities_gpu_culling
2337 .remove(main_entity);
2338 render_view_visible_mesh_entities
2339 .removed_entities
2340 .push((Entity::PLACEHOLDER, *main_entity));
2341 }
2342 }
2343 }
2344
2345 if any_added {
2348 render_view_visible_mesh_entities.sort_added_entities();
2349 }
2350}
2351
2352pub fn set_mesh_motion_vector_flags(
2367 mut render_mesh_instances: ResMut<RenderMeshInstances>,
2368 skin_uniforms: Res<SkinUniforms>,
2369 morph_indices: Res<MorphIndices>,
2370) {
2371 for &entity in skin_uniforms.all_skins() {
2374 render_mesh_instances
2375 .insert_mesh_instance_flags(entity, RenderMeshInstanceFlags::HAS_PREVIOUS_SKIN);
2376 }
2377
2378 match *morph_indices {
2381 MorphIndices::Uniform { ref prev, .. } => {
2382 for &entity in prev.keys() {
2383 render_mesh_instances.insert_mesh_instance_flags(
2384 entity,
2385 RenderMeshInstanceFlags::HAS_PREVIOUS_MORPH,
2386 );
2387 }
2388 }
2389 MorphIndices::Storage {
2390 morph_weights_info: ref morph_target_info,
2391 ..
2392 } => {
2393 for (entity, morph_target_info) in morph_target_info {
2394 if morph_target_info.prev_weight_offset.is_some() {
2395 render_mesh_instances.insert_mesh_instance_flags(
2396 *entity,
2397 RenderMeshInstanceFlags::HAS_PREVIOUS_MORPH,
2398 );
2399 }
2400 }
2401 }
2402 }
2403}
2404
2405pub fn collect_meshes_for_gpu_building(
2408 render_mesh_instances: ResMut<RenderMeshInstances>,
2409 batched_instance_buffers: ResMut<
2410 gpu_preprocessing::BatchedInstanceBuffers<MeshUniform, MeshInputUniform>,
2411 >,
2412 mut mesh_culling_data_buffer: ResMut<MeshCullingDataBuffer>,
2413 mut render_mesh_instance_queues: ResMut<RenderMeshInstanceGpuQueues>,
2414 mut render_gpu_culled_entities: ResMut<RenderGpuCulledEntities>,
2415 mesh_allocator: Res<MeshAllocator>,
2416 mesh_material_ids: Res<RenderMaterialInstances>,
2417 render_material_bindings: Res<RenderMaterialBindings>,
2418 render_lightmaps: Res<RenderLightmaps>,
2419 skin_uniforms: Res<SkinUniforms>,
2420 morph_indices: Res<MorphIndices>,
2421 frame_count: Res<FrameCount>,
2422 mut meshes_to_reextract_next_frame: ResMut<MeshesToReextractNextFrame>,
2423) {
2424 let RenderMeshInstances::GpuBuilding(render_mesh_instances) =
2425 render_mesh_instances.into_inner()
2426 else {
2427 return;
2428 };
2429
2430 meshes_to_reextract_next_frame.clear();
2432
2433 let gpu_preprocessing::BatchedInstanceBuffers {
2435 current_input_buffer,
2436 previous_input_buffer,
2437 ..
2438 } = batched_instance_buffers.into_inner();
2439
2440 if !current_input_buffer.is_empty() {
2442 mesh_culling_data_buffer.grow(current_input_buffer.len() as u32);
2443 }
2444
2445 previous_input_buffer.reserve(current_input_buffer.len() as u32);
2447
2448 render_gpu_culled_entities.prepare_for_new_frame();
2451
2452 let (prepared_tx, prepared_rx) = mpsc::channel();
2454 let (reextract_tx, reextract_rx) = mpsc::channel();
2455 let (removed_tx, removed_rx) = mpsc::channel();
2456
2457 {
2458 let mesh_allocator = &mesh_allocator;
2460 let mesh_material_ids = &mesh_material_ids;
2461 let render_material_bindings = &render_material_bindings;
2462 let render_lightmaps = &render_lightmaps;
2463 let skin_uniforms = &skin_uniforms;
2464 let frame_count = *frame_count;
2465 let render_mesh_instances = &*render_mesh_instances;
2466 let current_input_buffer = &*current_input_buffer;
2467 let previous_input_buffer = &*previous_input_buffer;
2468 let mesh_culling_data_buffer = &*mesh_culling_data_buffer;
2469 let morph_indices = &*morph_indices;
2470
2471 ComputeTaskPool::get().scope(|scope| {
2473 for queue in render_mesh_instance_queues.iter_mut() {
2476 match *queue {
2477 RenderMeshInstanceGpuQueue::None => {
2478 }
2480
2481 RenderMeshInstanceGpuQueue::CpuCulling {
2482 ref mut changed,
2483 ref mut removed,
2484 } => {
2485 let prepared_tx = prepared_tx.clone();
2486 let reextract_tx = reextract_tx.clone();
2487 let removed_tx = removed_tx.clone();
2488 scope.spawn(async move {
2489 #[cfg(feature = "trace")]
2490 let _span = {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("prepared_mesh_producer",
"bevy_pbr::render::mesh", ::tracing::Level::INFO,
::tracing_core::__macro_support::Option::Some("src/render/mesh.rs"),
::tracing_core::__macro_support::Option::Some(2490u32),
::tracing_core::__macro_support::Option::Some("bevy_pbr::render::mesh"),
::tracing_core::field::FieldSet::new(&[],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::INFO <= ::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::INFO <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() } &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta, &{ meta.fields().value_set_all(&[]) })
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
}info_span!("prepared_mesh_producer").entered();
2491 changed
2492 .drain(..)
2493 .for_each(|(entity, mesh_instance_builder)| {
2494 match mesh_instance_builder.prepare(
2495 entity,
2496 mesh_allocator,
2497 mesh_material_ids,
2498 render_material_bindings,
2499 render_lightmaps,
2500 skin_uniforms,
2501 morph_indices,
2502 frame_count,
2503 ) {
2504 Some(prepared) => {
2505 prepared_tx.send((entity, prepared, None)).ok();
2506 }
2507 None => {
2508 reextract_tx.send(entity).ok();
2509 }
2510 }
2511 });
2512
2513 for entity in removed.drain(..) {
2514 removed_tx.send(entity).unwrap();
2515 }
2516 });
2517 }
2518
2519 RenderMeshInstanceGpuQueue::GpuCulling {
2520 ref mut changed_cpu_culling,
2521 ref mut changed_gpu_culling,
2522 ref mut removed,
2523 } => {
2524 let prepared_tx = prepared_tx.clone();
2525 let reextract_tx = reextract_tx.clone();
2526 let removed_tx = removed_tx.clone();
2527 scope.spawn(async move {
2528 #[cfg(feature = "trace")]
2529 let _span = {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("prepared_mesh_producer",
"bevy_pbr::render::mesh", ::tracing::Level::INFO,
::tracing_core::__macro_support::Option::Some("src/render/mesh.rs"),
::tracing_core::__macro_support::Option::Some(2529u32),
::tracing_core::__macro_support::Option::Some("bevy_pbr::render::mesh"),
::tracing_core::field::FieldSet::new(&[],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::INFO <= ::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::INFO <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() } &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta, &{ meta.fields().value_set_all(&[]) })
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
}info_span!("prepared_mesh_producer").entered();
2530 for (entity, mesh_instance_builder, mesh_culling_builder) in
2531 changed_cpu_culling
2532 .drain(..)
2533 .chain(changed_gpu_culling.drain(..))
2534 {
2535 let Some(mut prepared) = mesh_instance_builder.prepare(
2536 entity,
2537 mesh_allocator,
2538 mesh_material_ids,
2539 render_material_bindings,
2540 render_lightmaps,
2541 skin_uniforms,
2542 morph_indices,
2543 frame_count,
2544 ) else {
2545 reextract_tx.send(entity).ok();
2546 continue;
2547 };
2548
2549 let Some(render_mesh_instance) = render_mesh_instances.get(&entity)
2550 else {
2551 let _ = prepared_tx.send((
2555 entity,
2556 prepared,
2557 Some(mesh_culling_builder),
2558 ));
2559 continue;
2560 };
2561
2562 if prepared.render_layers != render_mesh_instance.render_layers
2563 || prepared
2564 .shared
2565 .flags
2566 .contains(RenderMeshInstanceFlags::NO_CPU_CULLING)
2567 != render_mesh_instance
2568 .shared
2569 .flags()
2570 .contains(RenderMeshInstanceFlags::NO_CPU_CULLING)
2571 {
2572 let _ = prepared_tx.send((
2577 entity,
2578 prepared,
2579 Some(mesh_culling_builder),
2580 ));
2581 continue;
2582 }
2583
2584 prepared.shared.write_to_blob(&render_mesh_instance.shared);
2589
2590 let current_uniform_index =
2591 render_mesh_instance.gpu_specific.current_uniform_index();
2592
2593 let previous_mesh_input_uniform =
2594 current_input_buffer.get_unchecked(current_uniform_index);
2595 let previous_input_index =
2596 previous_input_buffer.push(previous_mesh_input_uniform);
2597 prepared.mesh_input_uniform.previous_input_index =
2598 previous_input_index;
2599
2600 current_input_buffer
2601 .set(current_uniform_index, prepared.mesh_input_uniform);
2602 mesh_culling_data_buffer
2603 .set(current_uniform_index, mesh_culling_builder);
2604 }
2605
2606 for entity in removed.drain(..) {
2607 removed_tx.send(entity).unwrap();
2608 }
2609 });
2610 }
2611 }
2612 }
2613
2614 drop(prepared_tx);
2618 drop(reextract_tx);
2619 drop(removed_tx);
2620 });
2621 }
2622
2623 while let Ok(batch) = prepared_rx.recv() {
2624 let (entity, prepared, mesh_culling_builder) = batch;
2625 let instance_data_index = prepared.update(
2626 entity,
2627 &mut *render_mesh_instances,
2628 current_input_buffer,
2629 previous_input_buffer,
2630 );
2631 if let Some(mesh_culling_data) = mesh_culling_builder {
2632 mesh_culling_data.update(&mut mesh_culling_data_buffer, instance_data_index);
2633 }
2634 let (render_layers, no_cpu_culling) = match render_mesh_instances.get(&entity) {
2637 None => (RenderLayers::default(), false),
2638 Some(render_mesh_instance) => (
2639 render_mesh_instance
2640 .render_layers
2641 .clone()
2642 .unwrap_or_default(),
2643 render_mesh_instance
2644 .shared
2645 .flags()
2646 .contains(RenderMeshInstanceFlags::NO_CPU_CULLING),
2647 ),
2648 };
2649 render_gpu_culled_entities.update(entity, render_layers, no_cpu_culling);
2650 }
2651 while let Ok(batch) = removed_rx.recv() {
2652 let entity = batch;
2653 remove_mesh_input_uniform(entity, &mut *render_mesh_instances, current_input_buffer);
2654 render_gpu_culled_entities.remove(entity);
2655 }
2656 while let Ok(batch) = reextract_rx.recv() {
2657 let entity = batch;
2658 meshes_to_reextract_next_frame.insert(entity);
2659 }
2660 previous_input_buffer.ensure_nonempty();
2662}
2663
2664#[derive(impl bevy_ecs::resource::Resource for MeshPipeline where
Self: ::core::marker::Send + ::core::marker::Sync + 'static {}Resource, #[automatically_derived]
impl ::core::clone::Clone for MeshPipeline {
#[inline]
fn clone(&self) -> MeshPipeline {
MeshPipeline {
view_layouts: ::core::clone::Clone::clone(&self.view_layouts),
clustered_forward_buffer_binding_type: ::core::clone::Clone::clone(&self.clustered_forward_buffer_binding_type),
mesh_layouts: ::core::clone::Clone::clone(&self.mesh_layouts),
shader: ::core::clone::Clone::clone(&self.shader),
per_object_buffer_batch_size: ::core::clone::Clone::clone(&self.per_object_buffer_batch_size),
binding_arrays_are_usable: ::core::clone::Clone::clone(&self.binding_arrays_are_usable),
clustered_decals_are_usable: ::core::clone::Clone::clone(&self.clustered_decals_are_usable),
skins_use_uniform_buffers: ::core::clone::Clone::clone(&self.skins_use_uniform_buffers),
}
}
}Clone)]
2666pub struct MeshPipeline {
2667 pub view_layouts: MeshPipelineViewLayouts,
2669 pub clustered_forward_buffer_binding_type: BufferBindingType,
2670 pub mesh_layouts: MeshLayouts,
2671 pub shader: Handle<Shader>,
2673 pub per_object_buffer_batch_size: Option<u32>,
2685
2686 pub binding_arrays_are_usable: bool,
2691
2692 pub clustered_decals_are_usable: bool,
2694
2695 pub skins_use_uniform_buffers: bool,
2698}
2699
2700fn init_mesh_pipeline(
2701 mut commands: Commands,
2702 render_device: Res<RenderDevice>,
2703 render_adapter: Res<RenderAdapter>,
2704 view_layouts: Res<MeshPipelineViewLayouts>,
2705 asset_server: Res<AssetServer>,
2706) {
2707 let shader = {
let (path, asset_server) =
{
let path =
{
{
let crate_name =
"bevy_pbr::render::mesh".split(':').next().unwrap();
::bevy_asset::io::embedded::_embedded_asset_path(crate_name,
"src".as_ref(), "src/render/mesh.rs".as_ref(),
"mesh.wgsl".as_ref())
}
};
let path =
::bevy_asset::AssetPath::from_path_buf(path).with_source("embedded");
let asset_server =
::bevy_asset::io::embedded::GetAssetServer::get_asset_server(asset_server.as_ref());
(path, asset_server)
};
asset_server.load(path)
}load_embedded_asset!(asset_server.as_ref(), "mesh.wgsl");
2708
2709 let clustered_forward_buffer_binding_type =
2710 render_device.get_supported_read_only_binding_type(CLUSTERED_FORWARD_STORAGE_BUFFER_COUNT);
2711
2712 let res = MeshPipeline {
2713 view_layouts: view_layouts.clone(),
2714 clustered_forward_buffer_binding_type,
2715 mesh_layouts: MeshLayouts::new(&render_device, &render_adapter),
2716 shader,
2717 per_object_buffer_batch_size: GpuArrayBuffer::<MeshUniform>::batch_size(
2718 &render_device.limits(),
2719 ),
2720 binding_arrays_are_usable: binding_arrays_are_usable(&render_device, &render_adapter),
2721 clustered_decals_are_usable: decal::clustered::clustered_decals_are_usable(
2722 &render_device,
2723 &render_adapter,
2724 ),
2725 skins_use_uniform_buffers: skins_use_uniform_buffers(&render_device.limits()),
2726 };
2727
2728 commands.insert_resource(res);
2729}
2730
2731impl MeshPipeline {
2732 pub fn get_view_layout(&self, layout_key: MeshPipelineViewLayoutKey) -> MeshPipelineViewLayout {
2733 self.view_layouts.get_view_layout(layout_key)
2734 }
2735}
2736
2737pub fn build_dummy_white_gpu_image(
2739 render_device: Res<RenderDevice>,
2740 default_sampler: Res<DefaultImageSampler>,
2741 render_queue: Res<RenderQueue>,
2742) -> GpuImage {
2743 let image = Image::default();
2744 let texture = render_device.create_texture(&image.texture_descriptor);
2745 let sampler = match image.sampler {
2746 ImageSampler::Default => (**default_sampler).clone(),
2747 ImageSampler::Descriptor(ref descriptor) => {
2748 render_device.create_sampler(&descriptor.as_wgpu())
2749 }
2750 };
2751
2752 if let Ok(format_size) = image.texture_descriptor.format.pixel_size() {
2753 render_queue.write_texture(
2754 texture.as_image_copy(),
2755 image.data.as_ref().expect("Image was created without data"),
2756 TexelCopyBufferLayout {
2757 offset: 0,
2758 bytes_per_row: Some(image.width() * format_size as u32),
2759 rows_per_image: None,
2760 },
2761 image.texture_descriptor.size,
2762 );
2763 }
2764
2765 let texture_view = texture.create_view(&TextureViewDescriptor::default());
2766 GpuImage {
2767 texture,
2768 texture_view,
2769 sampler,
2770 texture_descriptor: image.texture_descriptor,
2771 texture_view_descriptor: image.texture_view_descriptor,
2772 had_data: true,
2773 }
2774}
2775
2776pub fn get_image_texture<'a>(
2777 dummy_white_gpu_image: &'a GpuImage,
2778 gpu_images: &'a RenderAssets<GpuImage>,
2779 handle_option: &Option<Handle<Image>>,
2780) -> Option<(&'a TextureView, &'a Sampler)> {
2781 if let Some(handle) = handle_option {
2782 let gpu_image = gpu_images.get(handle)?;
2783 Some((&gpu_image.texture_view, &gpu_image.sampler))
2784 } else {
2785 Some((
2786 &dummy_white_gpu_image.texture_view,
2787 &dummy_white_gpu_image.sampler,
2788 ))
2789 }
2790}
2791
2792#[derive(#[automatically_derived]
impl ::core::clone::Clone for MeshBatchSetCompareData {
#[inline]
fn clone(&self) -> MeshBatchSetCompareData {
let _: ::core::clone::AssertParamIsClone<MaterialBindGroupIndex>;
let _: ::core::clone::AssertParamIsClone<MeshSlabs>;
let _: ::core::clone::AssertParamIsClone<Option<NonMaxU32>>;
*self
}
}Clone, #[automatically_derived]
impl ::core::marker::Copy for MeshBatchSetCompareData { }Copy, #[automatically_derived]
impl ::core::cmp::PartialEq for MeshBatchSetCompareData {
#[inline]
fn eq(&self, other: &MeshBatchSetCompareData) -> bool {
self.material_bind_group_index == other.material_bind_group_index &&
self.mesh_slabs == other.mesh_slabs &&
self.lightmap_slab == other.lightmap_slab
}
}PartialEq)]
2794pub struct MeshBatchSetCompareData {
2795 material_bind_group_index: MaterialBindGroupIndex,
2797 mesh_slabs: MeshSlabs,
2799 lightmap_slab: Option<NonMaxU32>,
2801}
2802
2803impl GetBatchData for MeshPipeline {
2804 type Param = (
2805 SRes<RenderMeshInstances>,
2806 SRes<RenderLightmaps>,
2807 SRes<RenderAssets<RenderMesh>>,
2808 SRes<MeshAllocator>,
2809 SRes<SkinUniforms>,
2810 SRes<MorphIndices>,
2811 );
2812 type BatchSetCompareData = MeshBatchSetCompareData;
2813 type BatchCompareData = AssetId<Mesh>;
2814
2815 type BufferData = MeshUniform;
2816
2817 fn get_batch_data(
2818 (mesh_instances, lightmaps, _, mesh_allocator, skin_uniforms, morph_indices): &SystemParamItem<
2819 Self::Param,
2820 >,
2821 (_entity, main_entity): (Entity, MainEntity),
2822 ) -> Option<(
2823 Self::BufferData,
2824 Option<(Self::BatchSetCompareData, Self::BatchCompareData)>,
2825 )> {
2826 let RenderMeshInstances::CpuBuilding(ref mesh_instances) = **mesh_instances else {
2827 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event src/render/mesh.rs:2827",
"bevy_pbr::render::mesh", ::tracing::Level::ERROR,
::tracing_core::__macro_support::Option::Some("src/render/mesh.rs"),
::tracing_core::__macro_support::Option::Some(2827u32),
::tracing_core::__macro_support::Option::Some("bevy_pbr::render::mesh"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::ERROR <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::ERROR <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("`get_batch_data` should never be called in GPU mesh uniform building mode")
as &dyn ::tracing::field::Value))])
});
} else { ; }
};error!(
2828 "`get_batch_data` should never be called in GPU mesh uniform \
2829 building mode"
2830 );
2831 return None;
2832 };
2833 let mesh_instance = mesh_instances.get(&main_entity)?;
2834 let first_vertex_index =
2835 match mesh_allocator.mesh_vertex_slice(&mesh_instance.mesh_asset_id()) {
2836 Some(mesh_vertex_slice) => mesh_vertex_slice.range.start,
2837 None => 0,
2838 };
2839 let mesh_slabs = mesh_allocator.mesh_slabs(&mesh_instance.mesh_asset_id())?;
2840 let maybe_lightmap = lightmaps.render_lightmaps.get(&main_entity);
2841
2842 let current_skin_index = skin_uniforms.skin_index(main_entity);
2843 let morph_descriptor_index = morph_indices.morph_descriptor_index(main_entity);
2844 let material_bind_group_index = mesh_instance.material_bindings_index();
2845
2846 Some((
2847 MeshUniform::new(
2848 &mesh_instance.transforms,
2849 first_vertex_index,
2850 material_bind_group_index.slot,
2851 maybe_lightmap.map(|lightmap| (lightmap.slot_index, lightmap.uv_rect)),
2852 current_skin_index,
2853 morph_descriptor_index,
2854 Some(mesh_instance.tag()),
2855 ),
2856 mesh_instance.should_batch().then_some((
2857 MeshBatchSetCompareData {
2858 material_bind_group_index: material_bind_group_index.group,
2859 mesh_slabs,
2860 lightmap_slab: maybe_lightmap.map(|lightmap| lightmap.slab_index.0),
2861 },
2862 mesh_instance.mesh_asset_id(),
2863 )),
2864 ))
2865 }
2866}
2867
2868impl GetFullBatchData for MeshPipeline {
2869 type BufferInputData = MeshInputUniform;
2870
2871 fn get_index_and_compare_data(
2872 (mesh_instances, lightmaps, _, mesh_allocator, _, _): &SystemParamItem<Self::Param>,
2873 main_entity: MainEntity,
2874 ) -> Option<(
2875 NonMaxU32,
2876 Option<(Self::BatchSetCompareData, Self::BatchCompareData)>,
2877 )> {
2878 let RenderMeshInstances::GpuBuilding(ref mesh_instances) = **mesh_instances else {
2880 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event src/render/mesh.rs:2880",
"bevy_pbr::render::mesh", ::tracing::Level::ERROR,
::tracing_core::__macro_support::Option::Some("src/render/mesh.rs"),
::tracing_core::__macro_support::Option::Some(2880u32),
::tracing_core::__macro_support::Option::Some("bevy_pbr::render::mesh"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::ERROR <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::ERROR <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("`get_index_and_compare_data` should never be called in CPU mesh uniform building mode")
as &dyn ::tracing::field::Value))])
});
} else { ; }
};error!(
2881 "`get_index_and_compare_data` should never be called in CPU mesh uniform building \
2882 mode"
2883 );
2884 return None;
2885 };
2886
2887 let mesh_instance = mesh_instances.get(&main_entity)?;
2888 let mesh_slabs = mesh_allocator.mesh_slabs(&mesh_instance.mesh_asset_id())?;
2889 let maybe_lightmap = lightmaps.render_lightmaps.get(&main_entity);
2890 let material_bind_group_index = mesh_instance.material_bindings_index();
2891
2892 Some((
2893 NonMaxU32::new(mesh_instance.gpu_specific.current_uniform_index())?,
2894 mesh_instance.should_batch().then_some((
2895 MeshBatchSetCompareData {
2896 material_bind_group_index: material_bind_group_index.group,
2897 mesh_slabs,
2898 lightmap_slab: maybe_lightmap.map(|lightmap| lightmap.slab_index.0),
2899 },
2900 mesh_instance.mesh_asset_id(),
2901 )),
2902 ))
2903 }
2904
2905 fn get_binned_batch_data(
2906 (mesh_instances, lightmaps, _, mesh_allocator, skin_uniforms, morph_indices): &SystemParamItem<
2907 Self::Param,
2908 >,
2909 main_entity: MainEntity,
2910 ) -> Option<Self::BufferData> {
2911 let RenderMeshInstances::CpuBuilding(ref mesh_instances) = **mesh_instances else {
2912 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event src/render/mesh.rs:2912",
"bevy_pbr::render::mesh", ::tracing::Level::ERROR,
::tracing_core::__macro_support::Option::Some("src/render/mesh.rs"),
::tracing_core::__macro_support::Option::Some(2912u32),
::tracing_core::__macro_support::Option::Some("bevy_pbr::render::mesh"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::ERROR <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::ERROR <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("`get_binned_batch_data` should never be called in GPU mesh uniform building mode")
as &dyn ::tracing::field::Value))])
});
} else { ; }
};error!(
2913 "`get_binned_batch_data` should never be called in GPU mesh uniform building mode"
2914 );
2915 return None;
2916 };
2917 let mesh_instance = mesh_instances.get(&main_entity)?;
2918 let first_vertex_index =
2919 match mesh_allocator.mesh_vertex_slice(&mesh_instance.mesh_asset_id()) {
2920 Some(mesh_vertex_slice) => mesh_vertex_slice.range.start,
2921 None => 0,
2922 };
2923 let maybe_lightmap = lightmaps.render_lightmaps.get(&main_entity);
2924
2925 let current_skin_index = skin_uniforms.skin_index(main_entity);
2926 let morph_descriptor_index = morph_indices.morph_descriptor_index(main_entity);
2927
2928 Some(MeshUniform::new(
2929 &mesh_instance.transforms,
2930 first_vertex_index,
2931 mesh_instance.material_bindings_index().slot,
2932 maybe_lightmap.map(|lightmap| (lightmap.slot_index, lightmap.uv_rect)),
2933 current_skin_index,
2934 morph_descriptor_index,
2935 Some(mesh_instance.tag()),
2936 ))
2937 }
2938
2939 fn get_binned_index(
2940 (mesh_instances, _, _, _, _, _): &SystemParamItem<Self::Param>,
2941 main_entity: MainEntity,
2942 ) -> Option<NonMaxU32> {
2943 let RenderMeshInstances::GpuBuilding(ref mesh_instances) = **mesh_instances else {
2945 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event src/render/mesh.rs:2945",
"bevy_pbr::render::mesh", ::tracing::Level::ERROR,
::tracing_core::__macro_support::Option::Some("src/render/mesh.rs"),
::tracing_core::__macro_support::Option::Some(2945u32),
::tracing_core::__macro_support::Option::Some("bevy_pbr::render::mesh"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::ERROR <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::ERROR <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("`get_binned_index` should never be called in CPU mesh uniform building mode")
as &dyn ::tracing::field::Value))])
});
} else { ; }
};error!(
2946 "`get_binned_index` should never be called in CPU mesh uniform \
2947 building mode"
2948 );
2949 return None;
2950 };
2951
2952 mesh_instances
2953 .get(&main_entity)
2954 .and_then(|entity| NonMaxU32::new(entity.gpu_specific.current_uniform_index()))
2955 }
2956
2957 fn write_batch_indirect_parameters_metadata(
2958 indexed: bool,
2959 base_output_index: u32,
2960 batch_set_index: Option<NonMaxU32>,
2961 phase_indirect_parameters_buffers: &mut UntypedPhaseIndirectParametersBuffers,
2962 indirect_parameters_offset: u32,
2963 ) {
2964 let indirect_parameters = IndirectParametersCpuMetadata {
2965 base_output_index,
2966 batch_set_index: match batch_set_index {
2967 Some(batch_set_index) => u32::from(batch_set_index),
2968 None => !0,
2969 },
2970 };
2971
2972 if indexed {
2973 phase_indirect_parameters_buffers
2974 .indexed
2975 .set(indirect_parameters_offset, indirect_parameters);
2976 } else {
2977 phase_indirect_parameters_buffers
2978 .non_indexed
2979 .set(indirect_parameters_offset, indirect_parameters);
2980 }
2981 }
2982}
2983
2984#[repr(transparent)]
pub struct MeshPipelineKey(<MeshPipelineKey as
::bitflags::__private::PublicFlags>::Internal);
#[automatically_derived]
impl ::core::default::Default for MeshPipelineKey {
#[inline]
fn default() -> MeshPipelineKey {
MeshPipelineKey(::core::default::Default::default())
}
}
#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for MeshPipelineKey { }
#[automatically_derived]
impl ::core::clone::Clone for MeshPipelineKey {
#[inline]
fn clone(&self) -> MeshPipelineKey {
let _:
::core::clone::AssertParamIsClone<<MeshPipelineKey as
::bitflags::__private::PublicFlags>::Internal>;
*self
}
}
#[automatically_derived]
impl ::core::marker::Copy for MeshPipelineKey { }
#[automatically_derived]
impl ::core::fmt::Debug for MeshPipelineKey {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"MeshPipelineKey", &&self.0)
}
}
#[automatically_derived]
impl ::core::marker::StructuralPartialEq for MeshPipelineKey { }
#[automatically_derived]
impl ::core::cmp::PartialEq for MeshPipelineKey {
#[inline]
fn eq(&self, other: &MeshPipelineKey) -> bool { self.0 == other.0 }
}
#[automatically_derived]
impl ::core::cmp::Eq for MeshPipelineKey {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _:
::core::cmp::AssertParamIsEq<<MeshPipelineKey as
::bitflags::__private::PublicFlags>::Internal>;
}
}
#[automatically_derived]
impl ::core::hash::Hash for MeshPipelineKey {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.0, state)
}
}
#[allow(dead_code, deprecated, unused_doc_comments, unused_attributes,
unused_mut, unused_imports, non_upper_case_globals, clippy :: min_ident_chars,
clippy :: assign_op_pattern, clippy :: indexing_slicing, clippy ::
same_name_method, clippy :: iter_without_into_iter,)]
const _: () =
{
#[repr(transparent)]
pub struct InternalBitFlags(u64);
#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for InternalBitFlags { }
#[automatically_derived]
impl ::core::clone::Clone for InternalBitFlags {
#[inline]
fn clone(&self) -> InternalBitFlags {
let _: ::core::clone::AssertParamIsClone<u64>;
*self
}
}
#[automatically_derived]
impl ::core::marker::Copy for InternalBitFlags { }
#[automatically_derived]
impl ::core::marker::StructuralPartialEq for InternalBitFlags { }
#[automatically_derived]
impl ::core::cmp::PartialEq for InternalBitFlags {
#[inline]
fn eq(&self, other: &InternalBitFlags) -> bool {
self.0 == other.0
}
}
#[automatically_derived]
impl ::core::cmp::Eq for InternalBitFlags {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<u64>;
}
}
#[automatically_derived]
impl ::core::cmp::PartialOrd for InternalBitFlags {
#[inline]
fn partial_cmp(&self, other: &InternalBitFlags)
-> ::core::option::Option<::core::cmp::Ordering> {
::core::option::Option::Some(::core::cmp::Ord::cmp(self,
other))
}
}
#[automatically_derived]
impl ::core::cmp::Ord for InternalBitFlags {
#[inline]
fn cmp(&self, other: &InternalBitFlags) -> ::core::cmp::Ordering {
::core::cmp::Ord::cmp(&self.0, &other.0)
}
}
#[automatically_derived]
impl ::core::hash::Hash for InternalBitFlags {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.0, state)
}
}
impl MeshPipelineKey {
pub const NONE: Self = Self::from_bits_retain(0);
pub const MORPH_TARGETS: Self =
Self::from_bits_retain(BaseMeshPipelineKey::MORPH_TARGETS.bits());
pub const TONEMAP_IN_SHADER: Self =
Self::from_bits_retain(1 << 0);
pub const DEBAND_DITHER: Self = Self::from_bits_retain(1 << 1);
pub const DEPTH_PREPASS: Self = Self::from_bits_retain(1 << 2);
pub const NORMAL_PREPASS: Self = Self::from_bits_retain(1 << 3);
pub const DEFERRED_PREPASS: Self = Self::from_bits_retain(1 << 4);
pub const MOTION_VECTOR_PREPASS: Self =
Self::from_bits_retain(1 << 5);
pub const MAY_DISCARD: Self = Self::from_bits_retain(1 << 6);
pub const ENVIRONMENT_MAP: Self = Self::from_bits_retain(1 << 7);
pub const SCREEN_SPACE_AMBIENT_OCCLUSION: Self =
Self::from_bits_retain(1 << 8);
pub const UNCLIPPED_DEPTH_ORTHO: Self =
Self::from_bits_retain(1 << 9);
pub const TEMPORAL_JITTER: Self = Self::from_bits_retain(1 << 10);
pub const READS_VIEW_TRANSMISSION_TEXTURE: Self =
Self::from_bits_retain(1 << 11);
pub const LIGHTMAPPED: Self = Self::from_bits_retain(1 << 12);
pub const LIGHTMAP_BICUBIC_SAMPLING: Self =
Self::from_bits_retain(1 << 13);
pub const IRRADIANCE_VOLUME: Self =
Self::from_bits_retain(1 << 14);
pub const VISIBILITY_RANGE_DITHER: Self =
Self::from_bits_retain(1 << 15);
pub const SCREEN_SPACE_REFLECTIONS: Self =
Self::from_bits_retain(1 << 16);
pub const HAS_PREVIOUS_SKIN: Self =
Self::from_bits_retain(1 << 17);
pub const HAS_PREVIOUS_MORPH: Self =
Self::from_bits_retain(1 << 18);
pub const OIT_ENABLED: Self = Self::from_bits_retain(1 << 19);
pub const DISTANCE_FOG: Self = Self::from_bits_retain(1 << 20);
pub const ATMOSPHERE: Self = Self::from_bits_retain(1 << 21);
pub const INVERT_CULLING: Self = Self::from_bits_retain(1 << 22);
pub const PREPASS_READS_MATERIAL: Self =
Self::from_bits_retain(1 << 23);
pub const CONTACT_SHADOWS: Self = Self::from_bits_retain(1 << 24);
pub const LAST_FLAG: Self =
Self::from_bits_retain(Self::CONTACT_SHADOWS.bits());
pub const ALL_PREPASS_BITS: Self =
Self::from_bits_retain(Self::DEPTH_PREPASS.bits() |
Self::NORMAL_PREPASS.bits() | Self::DEFERRED_PREPASS.bits()
| Self::MOTION_VECTOR_PREPASS.bits() |
Self::MAY_DISCARD.bits() |
Self::PREPASS_READS_MATERIAL.bits());
pub const MSAA_RESERVED_BITS: Self =
Self::from_bits_retain(Self::MSAA_MASK_BITS <<
Self::MSAA_SHIFT_BITS);
pub const BLEND_RESERVED_BITS: Self =
Self::from_bits_retain(Self::BLEND_MASK_BITS <<
Self::BLEND_SHIFT_BITS);
pub const BLEND_OPAQUE: Self =
Self::from_bits_retain(0 << Self::BLEND_SHIFT_BITS);
pub const BLEND_PREMULTIPLIED_ALPHA: Self =
Self::from_bits_retain(1 << Self::BLEND_SHIFT_BITS);
pub const BLEND_MULTIPLY: Self =
Self::from_bits_retain(2 << Self::BLEND_SHIFT_BITS);
pub const BLEND_ALPHA: Self =
Self::from_bits_retain(3 << Self::BLEND_SHIFT_BITS);
pub const BLEND_ALPHA_TO_COVERAGE: Self =
Self::from_bits_retain(4 << Self::BLEND_SHIFT_BITS);
pub const TONEMAP_METHOD_RESERVED_BITS: Self =
Self::from_bits_retain(Self::TONEMAP_METHOD_MASK_BITS <<
Self::TONEMAP_METHOD_SHIFT_BITS);
pub const TONEMAP_METHOD_NONE: Self =
Self::from_bits_retain(0 << Self::TONEMAP_METHOD_SHIFT_BITS);
pub const TONEMAP_METHOD_REINHARD: Self =
Self::from_bits_retain(1 << Self::TONEMAP_METHOD_SHIFT_BITS);
pub const TONEMAP_METHOD_REINHARD_LUMINANCE: Self =
Self::from_bits_retain(2 << Self::TONEMAP_METHOD_SHIFT_BITS);
pub const TONEMAP_METHOD_ACES_FITTED: Self =
Self::from_bits_retain(3 << Self::TONEMAP_METHOD_SHIFT_BITS);
pub const TONEMAP_METHOD_AGX: Self =
Self::from_bits_retain(4 << Self::TONEMAP_METHOD_SHIFT_BITS);
pub const TONEMAP_METHOD_SOMEWHAT_BORING_DISPLAY_TRANSFORM: Self =
Self::from_bits_retain(5 << Self::TONEMAP_METHOD_SHIFT_BITS);
pub const TONEMAP_METHOD_TONY_MC_MAPFACE: Self =
Self::from_bits_retain(6 << Self::TONEMAP_METHOD_SHIFT_BITS);
pub const TONEMAP_METHOD_BLENDER_FILMIC: Self =
Self::from_bits_retain(7 << Self::TONEMAP_METHOD_SHIFT_BITS);
pub const TONEMAP_METHOD_PBR_NEUTRAL: Self =
Self::from_bits_retain(8 << Self::TONEMAP_METHOD_SHIFT_BITS);
pub const SHADOW_FILTER_METHOD_RESERVED_BITS: Self =
Self::from_bits_retain(Self::SHADOW_FILTER_METHOD_MASK_BITS <<
Self::SHADOW_FILTER_METHOD_SHIFT_BITS);
pub const SHADOW_FILTER_METHOD_HARDWARE_2X2: Self =
Self::from_bits_retain(0 <<
Self::SHADOW_FILTER_METHOD_SHIFT_BITS);
pub const SHADOW_FILTER_METHOD_GAUSSIAN: Self =
Self::from_bits_retain(1 <<
Self::SHADOW_FILTER_METHOD_SHIFT_BITS);
pub const SHADOW_FILTER_METHOD_TEMPORAL: Self =
Self::from_bits_retain(2 <<
Self::SHADOW_FILTER_METHOD_SHIFT_BITS);
pub const VIEW_PROJECTION_RESERVED_BITS: Self =
Self::from_bits_retain(Self::VIEW_PROJECTION_MASK_BITS <<
Self::VIEW_PROJECTION_SHIFT_BITS);
pub const VIEW_PROJECTION_NONSTANDARD: Self =
Self::from_bits_retain(0 << Self::VIEW_PROJECTION_SHIFT_BITS);
pub const VIEW_PROJECTION_PERSPECTIVE: Self =
Self::from_bits_retain(1 << Self::VIEW_PROJECTION_SHIFT_BITS);
pub const VIEW_PROJECTION_ORTHOGRAPHIC: Self =
Self::from_bits_retain(2 << Self::VIEW_PROJECTION_SHIFT_BITS);
pub const VIEW_PROJECTION_RESERVED: Self =
Self::from_bits_retain(3 << Self::VIEW_PROJECTION_SHIFT_BITS);
pub const SCREEN_SPACE_SPECULAR_TRANSMISSION_RESERVED_BITS: Self =
Self::from_bits_retain(Self::SCREEN_SPACE_SPECULAR_TRANSMISSION_MASK_BITS
<< Self::SCREEN_SPACE_SPECULAR_TRANSMISSION_SHIFT_BITS);
pub const SCREEN_SPACE_SPECULAR_TRANSMISSION_LOW: Self =
Self::from_bits_retain(0 <<
Self::SCREEN_SPACE_SPECULAR_TRANSMISSION_SHIFT_BITS);
pub const SCREEN_SPACE_SPECULAR_TRANSMISSION_MEDIUM: Self =
Self::from_bits_retain(1 <<
Self::SCREEN_SPACE_SPECULAR_TRANSMISSION_SHIFT_BITS);
pub const SCREEN_SPACE_SPECULAR_TRANSMISSION_HIGH: Self =
Self::from_bits_retain(2 <<
Self::SCREEN_SPACE_SPECULAR_TRANSMISSION_SHIFT_BITS);
pub const SCREEN_SPACE_SPECULAR_TRANSMISSION_ULTRA: Self =
Self::from_bits_retain(3 <<
Self::SCREEN_SPACE_SPECULAR_TRANSMISSION_SHIFT_BITS);
pub const COLOR_TARGET_FORMAT_RESERVED_BITS: Self =
Self::from_bits_retain(Self::COLOR_TARGET_FORMAT_MASK_BITS <<
Self::COLOR_TARGET_FORMAT_SHIFT_BITS);
pub const ALL_RESERVED_BITS: Self =
Self::from_bits_retain(Self::BLEND_RESERVED_BITS.bits() |
Self::MSAA_RESERVED_BITS.bits() |
Self::TONEMAP_METHOD_RESERVED_BITS.bits() |
Self::SHADOW_FILTER_METHOD_RESERVED_BITS.bits() |
Self::VIEW_PROJECTION_RESERVED_BITS.bits() |
Self::SCREEN_SPACE_SPECULAR_TRANSMISSION_RESERVED_BITS.bits()
| Self::COLOR_TARGET_FORMAT_RESERVED_BITS.bits());
}
impl ::bitflags::Flags for MeshPipelineKey {
const FLAGS: &'static [::bitflags::Flag<MeshPipelineKey>] =
{
mod __bitflags_flag_names {
use super::*;
pub(super) const NONE: &'static str = "NONE";
pub(super) const MORPH_TARGETS: &'static str =
"MORPH_TARGETS";
pub(super) const TONEMAP_IN_SHADER: &'static str =
"TONEMAP_IN_SHADER";
pub(super) const DEBAND_DITHER: &'static str =
"DEBAND_DITHER";
pub(super) const DEPTH_PREPASS: &'static str =
"DEPTH_PREPASS";
pub(super) const NORMAL_PREPASS: &'static str =
"NORMAL_PREPASS";
pub(super) const DEFERRED_PREPASS: &'static str =
"DEFERRED_PREPASS";
pub(super) const MOTION_VECTOR_PREPASS: &'static str =
"MOTION_VECTOR_PREPASS";
pub(super) const MAY_DISCARD: &'static str = "MAY_DISCARD";
pub(super) const ENVIRONMENT_MAP: &'static str =
"ENVIRONMENT_MAP";
pub(super) const SCREEN_SPACE_AMBIENT_OCCLUSION:
&'static str =
"SCREEN_SPACE_AMBIENT_OCCLUSION";
pub(super) const UNCLIPPED_DEPTH_ORTHO: &'static str =
"UNCLIPPED_DEPTH_ORTHO";
pub(super) const TEMPORAL_JITTER: &'static str =
"TEMPORAL_JITTER";
pub(super) const READS_VIEW_TRANSMISSION_TEXTURE:
&'static str =
"READS_VIEW_TRANSMISSION_TEXTURE";
pub(super) const LIGHTMAPPED: &'static str = "LIGHTMAPPED";
pub(super) const LIGHTMAP_BICUBIC_SAMPLING: &'static str =
"LIGHTMAP_BICUBIC_SAMPLING";
pub(super) const IRRADIANCE_VOLUME: &'static str =
"IRRADIANCE_VOLUME";
pub(super) const VISIBILITY_RANGE_DITHER: &'static str =
"VISIBILITY_RANGE_DITHER";
pub(super) const SCREEN_SPACE_REFLECTIONS: &'static str =
"SCREEN_SPACE_REFLECTIONS";
pub(super) const HAS_PREVIOUS_SKIN: &'static str =
"HAS_PREVIOUS_SKIN";
pub(super) const HAS_PREVIOUS_MORPH: &'static str =
"HAS_PREVIOUS_MORPH";
pub(super) const OIT_ENABLED: &'static str = "OIT_ENABLED";
pub(super) const DISTANCE_FOG: &'static str =
"DISTANCE_FOG";
pub(super) const ATMOSPHERE: &'static str = "ATMOSPHERE";
pub(super) const INVERT_CULLING: &'static str =
"INVERT_CULLING";
pub(super) const PREPASS_READS_MATERIAL: &'static str =
"PREPASS_READS_MATERIAL";
pub(super) const CONTACT_SHADOWS: &'static str =
"CONTACT_SHADOWS";
pub(super) const LAST_FLAG: &'static str = "LAST_FLAG";
pub(super) const ALL_PREPASS_BITS: &'static str =
"ALL_PREPASS_BITS";
pub(super) const MSAA_RESERVED_BITS: &'static str =
"MSAA_RESERVED_BITS";
pub(super) const BLEND_RESERVED_BITS: &'static str =
"BLEND_RESERVED_BITS";
pub(super) const BLEND_OPAQUE: &'static str =
"BLEND_OPAQUE";
pub(super) const BLEND_PREMULTIPLIED_ALPHA: &'static str =
"BLEND_PREMULTIPLIED_ALPHA";
pub(super) const BLEND_MULTIPLY: &'static str =
"BLEND_MULTIPLY";
pub(super) const BLEND_ALPHA: &'static str = "BLEND_ALPHA";
pub(super) const BLEND_ALPHA_TO_COVERAGE: &'static str =
"BLEND_ALPHA_TO_COVERAGE";
pub(super) const TONEMAP_METHOD_RESERVED_BITS: &'static str
=
"TONEMAP_METHOD_RESERVED_BITS";
pub(super) const TONEMAP_METHOD_NONE: &'static str =
"TONEMAP_METHOD_NONE";
pub(super) const TONEMAP_METHOD_REINHARD: &'static str =
"TONEMAP_METHOD_REINHARD";
pub(super) const TONEMAP_METHOD_REINHARD_LUMINANCE:
&'static str =
"TONEMAP_METHOD_REINHARD_LUMINANCE";
pub(super) const TONEMAP_METHOD_ACES_FITTED: &'static str =
"TONEMAP_METHOD_ACES_FITTED";
pub(super) const TONEMAP_METHOD_AGX: &'static str =
"TONEMAP_METHOD_AGX";
pub(super) const
TONEMAP_METHOD_SOMEWHAT_BORING_DISPLAY_TRANSFORM:
&'static str =
"TONEMAP_METHOD_SOMEWHAT_BORING_DISPLAY_TRANSFORM";
pub(super) const TONEMAP_METHOD_TONY_MC_MAPFACE:
&'static str =
"TONEMAP_METHOD_TONY_MC_MAPFACE";
pub(super) const TONEMAP_METHOD_BLENDER_FILMIC: &'static str
=
"TONEMAP_METHOD_BLENDER_FILMIC";
pub(super) const TONEMAP_METHOD_PBR_NEUTRAL: &'static str =
"TONEMAP_METHOD_PBR_NEUTRAL";
pub(super) const SHADOW_FILTER_METHOD_RESERVED_BITS:
&'static str =
"SHADOW_FILTER_METHOD_RESERVED_BITS";
pub(super) const SHADOW_FILTER_METHOD_HARDWARE_2X2:
&'static str =
"SHADOW_FILTER_METHOD_HARDWARE_2X2";
pub(super) const SHADOW_FILTER_METHOD_GAUSSIAN: &'static str
=
"SHADOW_FILTER_METHOD_GAUSSIAN";
pub(super) const SHADOW_FILTER_METHOD_TEMPORAL: &'static str
=
"SHADOW_FILTER_METHOD_TEMPORAL";
pub(super) const VIEW_PROJECTION_RESERVED_BITS: &'static str
=
"VIEW_PROJECTION_RESERVED_BITS";
pub(super) const VIEW_PROJECTION_NONSTANDARD: &'static str =
"VIEW_PROJECTION_NONSTANDARD";
pub(super) const VIEW_PROJECTION_PERSPECTIVE: &'static str =
"VIEW_PROJECTION_PERSPECTIVE";
pub(super) const VIEW_PROJECTION_ORTHOGRAPHIC: &'static str
=
"VIEW_PROJECTION_ORTHOGRAPHIC";
pub(super) const VIEW_PROJECTION_RESERVED: &'static str =
"VIEW_PROJECTION_RESERVED";
pub(super) const
SCREEN_SPACE_SPECULAR_TRANSMISSION_RESERVED_BITS:
&'static str =
"SCREEN_SPACE_SPECULAR_TRANSMISSION_RESERVED_BITS";
pub(super) const SCREEN_SPACE_SPECULAR_TRANSMISSION_LOW:
&'static str =
"SCREEN_SPACE_SPECULAR_TRANSMISSION_LOW";
pub(super) const SCREEN_SPACE_SPECULAR_TRANSMISSION_MEDIUM:
&'static str =
"SCREEN_SPACE_SPECULAR_TRANSMISSION_MEDIUM";
pub(super) const SCREEN_SPACE_SPECULAR_TRANSMISSION_HIGH:
&'static str =
"SCREEN_SPACE_SPECULAR_TRANSMISSION_HIGH";
pub(super) const SCREEN_SPACE_SPECULAR_TRANSMISSION_ULTRA:
&'static str =
"SCREEN_SPACE_SPECULAR_TRANSMISSION_ULTRA";
pub(super) const COLOR_TARGET_FORMAT_RESERVED_BITS:
&'static str =
"COLOR_TARGET_FORMAT_RESERVED_BITS";
pub(super) const ALL_RESERVED_BITS: &'static str =
"ALL_RESERVED_BITS";
}
&[{
::bitflags::Flag::new(__bitflags_flag_names::NONE,
MeshPipelineKey::NONE)
},
{
::bitflags::Flag::new(__bitflags_flag_names::MORPH_TARGETS,
MeshPipelineKey::MORPH_TARGETS)
},
{
::bitflags::Flag::new(__bitflags_flag_names::TONEMAP_IN_SHADER,
MeshPipelineKey::TONEMAP_IN_SHADER)
},
{
::bitflags::Flag::new(__bitflags_flag_names::DEBAND_DITHER,
MeshPipelineKey::DEBAND_DITHER)
},
{
::bitflags::Flag::new(__bitflags_flag_names::DEPTH_PREPASS,
MeshPipelineKey::DEPTH_PREPASS)
},
{
::bitflags::Flag::new(__bitflags_flag_names::NORMAL_PREPASS,
MeshPipelineKey::NORMAL_PREPASS)
},
{
::bitflags::Flag::new(__bitflags_flag_names::DEFERRED_PREPASS,
MeshPipelineKey::DEFERRED_PREPASS)
},
{
::bitflags::Flag::new(__bitflags_flag_names::MOTION_VECTOR_PREPASS,
MeshPipelineKey::MOTION_VECTOR_PREPASS)
},
{
::bitflags::Flag::new(__bitflags_flag_names::MAY_DISCARD,
MeshPipelineKey::MAY_DISCARD)
},
{
::bitflags::Flag::new(__bitflags_flag_names::ENVIRONMENT_MAP,
MeshPipelineKey::ENVIRONMENT_MAP)
},
{
::bitflags::Flag::new(__bitflags_flag_names::SCREEN_SPACE_AMBIENT_OCCLUSION,
MeshPipelineKey::SCREEN_SPACE_AMBIENT_OCCLUSION)
},
{
::bitflags::Flag::new(__bitflags_flag_names::UNCLIPPED_DEPTH_ORTHO,
MeshPipelineKey::UNCLIPPED_DEPTH_ORTHO)
},
{
::bitflags::Flag::new(__bitflags_flag_names::TEMPORAL_JITTER,
MeshPipelineKey::TEMPORAL_JITTER)
},
{
::bitflags::Flag::new(__bitflags_flag_names::READS_VIEW_TRANSMISSION_TEXTURE,
MeshPipelineKey::READS_VIEW_TRANSMISSION_TEXTURE)
},
{
::bitflags::Flag::new(__bitflags_flag_names::LIGHTMAPPED,
MeshPipelineKey::LIGHTMAPPED)
},
{
::bitflags::Flag::new(__bitflags_flag_names::LIGHTMAP_BICUBIC_SAMPLING,
MeshPipelineKey::LIGHTMAP_BICUBIC_SAMPLING)
},
{
::bitflags::Flag::new(__bitflags_flag_names::IRRADIANCE_VOLUME,
MeshPipelineKey::IRRADIANCE_VOLUME)
},
{
::bitflags::Flag::new(__bitflags_flag_names::VISIBILITY_RANGE_DITHER,
MeshPipelineKey::VISIBILITY_RANGE_DITHER)
},
{
::bitflags::Flag::new(__bitflags_flag_names::SCREEN_SPACE_REFLECTIONS,
MeshPipelineKey::SCREEN_SPACE_REFLECTIONS)
},
{
::bitflags::Flag::new(__bitflags_flag_names::HAS_PREVIOUS_SKIN,
MeshPipelineKey::HAS_PREVIOUS_SKIN)
},
{
::bitflags::Flag::new(__bitflags_flag_names::HAS_PREVIOUS_MORPH,
MeshPipelineKey::HAS_PREVIOUS_MORPH)
},
{
::bitflags::Flag::new(__bitflags_flag_names::OIT_ENABLED,
MeshPipelineKey::OIT_ENABLED)
},
{
::bitflags::Flag::new(__bitflags_flag_names::DISTANCE_FOG,
MeshPipelineKey::DISTANCE_FOG)
},
{
::bitflags::Flag::new(__bitflags_flag_names::ATMOSPHERE,
MeshPipelineKey::ATMOSPHERE)
},
{
::bitflags::Flag::new(__bitflags_flag_names::INVERT_CULLING,
MeshPipelineKey::INVERT_CULLING)
},
{
::bitflags::Flag::new(__bitflags_flag_names::PREPASS_READS_MATERIAL,
MeshPipelineKey::PREPASS_READS_MATERIAL)
},
{
::bitflags::Flag::new(__bitflags_flag_names::CONTACT_SHADOWS,
MeshPipelineKey::CONTACT_SHADOWS)
},
{
::bitflags::Flag::new(__bitflags_flag_names::LAST_FLAG,
MeshPipelineKey::LAST_FLAG)
},
{
::bitflags::Flag::new(__bitflags_flag_names::ALL_PREPASS_BITS,
MeshPipelineKey::ALL_PREPASS_BITS)
},
{
::bitflags::Flag::new(__bitflags_flag_names::MSAA_RESERVED_BITS,
MeshPipelineKey::MSAA_RESERVED_BITS)
},
{
::bitflags::Flag::new(__bitflags_flag_names::BLEND_RESERVED_BITS,
MeshPipelineKey::BLEND_RESERVED_BITS)
},
{
::bitflags::Flag::new(__bitflags_flag_names::BLEND_OPAQUE,
MeshPipelineKey::BLEND_OPAQUE)
},
{
::bitflags::Flag::new(__bitflags_flag_names::BLEND_PREMULTIPLIED_ALPHA,
MeshPipelineKey::BLEND_PREMULTIPLIED_ALPHA)
},
{
::bitflags::Flag::new(__bitflags_flag_names::BLEND_MULTIPLY,
MeshPipelineKey::BLEND_MULTIPLY)
},
{
::bitflags::Flag::new(__bitflags_flag_names::BLEND_ALPHA,
MeshPipelineKey::BLEND_ALPHA)
},
{
::bitflags::Flag::new(__bitflags_flag_names::BLEND_ALPHA_TO_COVERAGE,
MeshPipelineKey::BLEND_ALPHA_TO_COVERAGE)
},
{
::bitflags::Flag::new(__bitflags_flag_names::TONEMAP_METHOD_RESERVED_BITS,
MeshPipelineKey::TONEMAP_METHOD_RESERVED_BITS)
},
{
::bitflags::Flag::new(__bitflags_flag_names::TONEMAP_METHOD_NONE,
MeshPipelineKey::TONEMAP_METHOD_NONE)
},
{
::bitflags::Flag::new(__bitflags_flag_names::TONEMAP_METHOD_REINHARD,
MeshPipelineKey::TONEMAP_METHOD_REINHARD)
},
{
::bitflags::Flag::new(__bitflags_flag_names::TONEMAP_METHOD_REINHARD_LUMINANCE,
MeshPipelineKey::TONEMAP_METHOD_REINHARD_LUMINANCE)
},
{
::bitflags::Flag::new(__bitflags_flag_names::TONEMAP_METHOD_ACES_FITTED,
MeshPipelineKey::TONEMAP_METHOD_ACES_FITTED)
},
{
::bitflags::Flag::new(__bitflags_flag_names::TONEMAP_METHOD_AGX,
MeshPipelineKey::TONEMAP_METHOD_AGX)
},
{
::bitflags::Flag::new(__bitflags_flag_names::TONEMAP_METHOD_SOMEWHAT_BORING_DISPLAY_TRANSFORM,
MeshPipelineKey::TONEMAP_METHOD_SOMEWHAT_BORING_DISPLAY_TRANSFORM)
},
{
::bitflags::Flag::new(__bitflags_flag_names::TONEMAP_METHOD_TONY_MC_MAPFACE,
MeshPipelineKey::TONEMAP_METHOD_TONY_MC_MAPFACE)
},
{
::bitflags::Flag::new(__bitflags_flag_names::TONEMAP_METHOD_BLENDER_FILMIC,
MeshPipelineKey::TONEMAP_METHOD_BLENDER_FILMIC)
},
{
::bitflags::Flag::new(__bitflags_flag_names::TONEMAP_METHOD_PBR_NEUTRAL,
MeshPipelineKey::TONEMAP_METHOD_PBR_NEUTRAL)
},
{
::bitflags::Flag::new(__bitflags_flag_names::SHADOW_FILTER_METHOD_RESERVED_BITS,
MeshPipelineKey::SHADOW_FILTER_METHOD_RESERVED_BITS)
},
{
::bitflags::Flag::new(__bitflags_flag_names::SHADOW_FILTER_METHOD_HARDWARE_2X2,
MeshPipelineKey::SHADOW_FILTER_METHOD_HARDWARE_2X2)
},
{
::bitflags::Flag::new(__bitflags_flag_names::SHADOW_FILTER_METHOD_GAUSSIAN,
MeshPipelineKey::SHADOW_FILTER_METHOD_GAUSSIAN)
},
{
::bitflags::Flag::new(__bitflags_flag_names::SHADOW_FILTER_METHOD_TEMPORAL,
MeshPipelineKey::SHADOW_FILTER_METHOD_TEMPORAL)
},
{
::bitflags::Flag::new(__bitflags_flag_names::VIEW_PROJECTION_RESERVED_BITS,
MeshPipelineKey::VIEW_PROJECTION_RESERVED_BITS)
},
{
::bitflags::Flag::new(__bitflags_flag_names::VIEW_PROJECTION_NONSTANDARD,
MeshPipelineKey::VIEW_PROJECTION_NONSTANDARD)
},
{
::bitflags::Flag::new(__bitflags_flag_names::VIEW_PROJECTION_PERSPECTIVE,
MeshPipelineKey::VIEW_PROJECTION_PERSPECTIVE)
},
{
::bitflags::Flag::new(__bitflags_flag_names::VIEW_PROJECTION_ORTHOGRAPHIC,
MeshPipelineKey::VIEW_PROJECTION_ORTHOGRAPHIC)
},
{
::bitflags::Flag::new(__bitflags_flag_names::VIEW_PROJECTION_RESERVED,
MeshPipelineKey::VIEW_PROJECTION_RESERVED)
},
{
::bitflags::Flag::new(__bitflags_flag_names::SCREEN_SPACE_SPECULAR_TRANSMISSION_RESERVED_BITS,
MeshPipelineKey::SCREEN_SPACE_SPECULAR_TRANSMISSION_RESERVED_BITS)
},
{
::bitflags::Flag::new(__bitflags_flag_names::SCREEN_SPACE_SPECULAR_TRANSMISSION_LOW,
MeshPipelineKey::SCREEN_SPACE_SPECULAR_TRANSMISSION_LOW)
},
{
::bitflags::Flag::new(__bitflags_flag_names::SCREEN_SPACE_SPECULAR_TRANSMISSION_MEDIUM,
MeshPipelineKey::SCREEN_SPACE_SPECULAR_TRANSMISSION_MEDIUM)
},
{
::bitflags::Flag::new(__bitflags_flag_names::SCREEN_SPACE_SPECULAR_TRANSMISSION_HIGH,
MeshPipelineKey::SCREEN_SPACE_SPECULAR_TRANSMISSION_HIGH)
},
{
::bitflags::Flag::new(__bitflags_flag_names::SCREEN_SPACE_SPECULAR_TRANSMISSION_ULTRA,
MeshPipelineKey::SCREEN_SPACE_SPECULAR_TRANSMISSION_ULTRA)
},
{
::bitflags::Flag::new(__bitflags_flag_names::COLOR_TARGET_FORMAT_RESERVED_BITS,
MeshPipelineKey::COLOR_TARGET_FORMAT_RESERVED_BITS)
},
{
::bitflags::Flag::new(__bitflags_flag_names::ALL_RESERVED_BITS,
MeshPipelineKey::ALL_RESERVED_BITS)
}]
};
type Bits = u64;
fn bits(&self) -> u64 { MeshPipelineKey::bits(self) }
fn from_bits_retain(bits: u64) -> MeshPipelineKey {
MeshPipelineKey::from_bits_retain(bits)
}
fn all_named() -> MeshPipelineKey {
const ALL_NAMED: u64 =
{
let mut truncated = <u64 as ::bitflags::Bits>::EMPTY;
let mut i = 0;
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
{
{
let flag =
&<MeshPipelineKey as ::bitflags::Flags>::FLAGS[i];
if flag.is_named() {
truncated = truncated | flag.value().bits();
}
i += 1;
}
};
let _ = i;
truncated
};
MeshPipelineKey::from_bits_retain(ALL_NAMED)
}
}
impl ::bitflags::__private::PublicFlags for MeshPipelineKey {
type Primitive = u64;
type Internal = InternalBitFlags;
}
impl ::bitflags::__private::core::default::Default for
InternalBitFlags {
#[inline]
fn default() -> Self { InternalBitFlags::empty() }
}
impl ::bitflags::__private::core::fmt::Debug for InternalBitFlags {
fn fmt(&self,
f: &mut ::bitflags::__private::core::fmt::Formatter<'_>)
-> ::bitflags::__private::core::fmt::Result {
if self.is_empty() {
f.write_fmt(format_args!("{0:#x}",
<u64 as ::bitflags::Bits>::EMPTY))
} else {
::bitflags::__private::core::fmt::Display::fmt(self, f)
}
}
}
impl ::bitflags::__private::core::fmt::Display for InternalBitFlags {
fn fmt(&self,
f: &mut ::bitflags::__private::core::fmt::Formatter<'_>)
-> ::bitflags::__private::core::fmt::Result {
::bitflags::parser::to_writer(&MeshPipelineKey(*self), f)
}
}
impl ::bitflags::__private::core::str::FromStr for InternalBitFlags {
type Err = ::bitflags::parser::ParseError;
fn from_str(s: &str)
->
::bitflags::__private::core::result::Result<Self,
Self::Err> {
::bitflags::parser::from_str::<MeshPipelineKey>(s).map(|flags|
flags.0)
}
}
impl ::bitflags::__private::core::convert::AsRef<u64> for
InternalBitFlags {
fn as_ref(&self) -> &u64 { &self.0 }
}
impl ::bitflags::__private::core::convert::From<u64> for
InternalBitFlags {
fn from(bits: u64) -> Self { Self::from_bits_retain(bits) }
}
impl InternalBitFlags {
#[inline]
pub const fn empty() -> Self {
Self(<u64 as ::bitflags::Bits>::EMPTY)
}
#[inline]
pub const fn all() -> Self {
let mut truncated = <u64 as ::bitflags::Bits>::EMPTY;
let mut i = 0;
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<MeshPipelineKey as
::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
let _ = i;
Self(truncated)
}
#[inline]
pub const fn bits(&self) -> u64 { self.0 }
#[inline]
pub const fn from_bits(bits: u64)
-> ::bitflags::__private::core::option::Option<Self> {
let truncated = Self::from_bits_truncate(bits).0;
if truncated == bits {
::bitflags::__private::core::option::Option::Some(Self(bits))
} else { ::bitflags::__private::core::option::Option::None }
}
#[inline]
pub const fn from_bits_truncate(bits: u64) -> Self {
Self(bits & Self::all().0)
}
#[inline]
pub const fn from_bits_retain(bits: u64) -> Self { Self(bits) }
#[inline]
pub fn from_name(name: &str)
-> ::bitflags::__private::core::option::Option<Self> {
mod __bitflags_flag_names {
use super::*;
pub(super) const NONE: &'static str = "NONE";
pub(super) const MORPH_TARGETS: &'static str =
"MORPH_TARGETS";
pub(super) const TONEMAP_IN_SHADER: &'static str =
"TONEMAP_IN_SHADER";
pub(super) const DEBAND_DITHER: &'static str =
"DEBAND_DITHER";
pub(super) const DEPTH_PREPASS: &'static str =
"DEPTH_PREPASS";
pub(super) const NORMAL_PREPASS: &'static str =
"NORMAL_PREPASS";
pub(super) const DEFERRED_PREPASS: &'static str =
"DEFERRED_PREPASS";
pub(super) const MOTION_VECTOR_PREPASS: &'static str =
"MOTION_VECTOR_PREPASS";
pub(super) const MAY_DISCARD: &'static str = "MAY_DISCARD";
pub(super) const ENVIRONMENT_MAP: &'static str =
"ENVIRONMENT_MAP";
pub(super) const SCREEN_SPACE_AMBIENT_OCCLUSION:
&'static str =
"SCREEN_SPACE_AMBIENT_OCCLUSION";
pub(super) const UNCLIPPED_DEPTH_ORTHO: &'static str =
"UNCLIPPED_DEPTH_ORTHO";
pub(super) const TEMPORAL_JITTER: &'static str =
"TEMPORAL_JITTER";
pub(super) const READS_VIEW_TRANSMISSION_TEXTURE:
&'static str =
"READS_VIEW_TRANSMISSION_TEXTURE";
pub(super) const LIGHTMAPPED: &'static str = "LIGHTMAPPED";
pub(super) const LIGHTMAP_BICUBIC_SAMPLING: &'static str =
"LIGHTMAP_BICUBIC_SAMPLING";
pub(super) const IRRADIANCE_VOLUME: &'static str =
"IRRADIANCE_VOLUME";
pub(super) const VISIBILITY_RANGE_DITHER: &'static str =
"VISIBILITY_RANGE_DITHER";
pub(super) const SCREEN_SPACE_REFLECTIONS: &'static str =
"SCREEN_SPACE_REFLECTIONS";
pub(super) const HAS_PREVIOUS_SKIN: &'static str =
"HAS_PREVIOUS_SKIN";
pub(super) const HAS_PREVIOUS_MORPH: &'static str =
"HAS_PREVIOUS_MORPH";
pub(super) const OIT_ENABLED: &'static str = "OIT_ENABLED";
pub(super) const DISTANCE_FOG: &'static str =
"DISTANCE_FOG";
pub(super) const ATMOSPHERE: &'static str = "ATMOSPHERE";
pub(super) const INVERT_CULLING: &'static str =
"INVERT_CULLING";
pub(super) const PREPASS_READS_MATERIAL: &'static str =
"PREPASS_READS_MATERIAL";
pub(super) const CONTACT_SHADOWS: &'static str =
"CONTACT_SHADOWS";
pub(super) const LAST_FLAG: &'static str = "LAST_FLAG";
pub(super) const ALL_PREPASS_BITS: &'static str =
"ALL_PREPASS_BITS";
pub(super) const MSAA_RESERVED_BITS: &'static str =
"MSAA_RESERVED_BITS";
pub(super) const BLEND_RESERVED_BITS: &'static str =
"BLEND_RESERVED_BITS";
pub(super) const BLEND_OPAQUE: &'static str =
"BLEND_OPAQUE";
pub(super) const BLEND_PREMULTIPLIED_ALPHA: &'static str =
"BLEND_PREMULTIPLIED_ALPHA";
pub(super) const BLEND_MULTIPLY: &'static str =
"BLEND_MULTIPLY";
pub(super) const BLEND_ALPHA: &'static str = "BLEND_ALPHA";
pub(super) const BLEND_ALPHA_TO_COVERAGE: &'static str =
"BLEND_ALPHA_TO_COVERAGE";
pub(super) const TONEMAP_METHOD_RESERVED_BITS: &'static str
=
"TONEMAP_METHOD_RESERVED_BITS";
pub(super) const TONEMAP_METHOD_NONE: &'static str =
"TONEMAP_METHOD_NONE";
pub(super) const TONEMAP_METHOD_REINHARD: &'static str =
"TONEMAP_METHOD_REINHARD";
pub(super) const TONEMAP_METHOD_REINHARD_LUMINANCE:
&'static str =
"TONEMAP_METHOD_REINHARD_LUMINANCE";
pub(super) const TONEMAP_METHOD_ACES_FITTED: &'static str =
"TONEMAP_METHOD_ACES_FITTED";
pub(super) const TONEMAP_METHOD_AGX: &'static str =
"TONEMAP_METHOD_AGX";
pub(super) const
TONEMAP_METHOD_SOMEWHAT_BORING_DISPLAY_TRANSFORM:
&'static str =
"TONEMAP_METHOD_SOMEWHAT_BORING_DISPLAY_TRANSFORM";
pub(super) const TONEMAP_METHOD_TONY_MC_MAPFACE:
&'static str =
"TONEMAP_METHOD_TONY_MC_MAPFACE";
pub(super) const TONEMAP_METHOD_BLENDER_FILMIC: &'static str
=
"TONEMAP_METHOD_BLENDER_FILMIC";
pub(super) const TONEMAP_METHOD_PBR_NEUTRAL: &'static str =
"TONEMAP_METHOD_PBR_NEUTRAL";
pub(super) const SHADOW_FILTER_METHOD_RESERVED_BITS:
&'static str =
"SHADOW_FILTER_METHOD_RESERVED_BITS";
pub(super) const SHADOW_FILTER_METHOD_HARDWARE_2X2:
&'static str =
"SHADOW_FILTER_METHOD_HARDWARE_2X2";
pub(super) const SHADOW_FILTER_METHOD_GAUSSIAN: &'static str
=
"SHADOW_FILTER_METHOD_GAUSSIAN";
pub(super) const SHADOW_FILTER_METHOD_TEMPORAL: &'static str
=
"SHADOW_FILTER_METHOD_TEMPORAL";
pub(super) const VIEW_PROJECTION_RESERVED_BITS: &'static str
=
"VIEW_PROJECTION_RESERVED_BITS";
pub(super) const VIEW_PROJECTION_NONSTANDARD: &'static str =
"VIEW_PROJECTION_NONSTANDARD";
pub(super) const VIEW_PROJECTION_PERSPECTIVE: &'static str =
"VIEW_PROJECTION_PERSPECTIVE";
pub(super) const VIEW_PROJECTION_ORTHOGRAPHIC: &'static str
=
"VIEW_PROJECTION_ORTHOGRAPHIC";
pub(super) const VIEW_PROJECTION_RESERVED: &'static str =
"VIEW_PROJECTION_RESERVED";
pub(super) const
SCREEN_SPACE_SPECULAR_TRANSMISSION_RESERVED_BITS:
&'static str =
"SCREEN_SPACE_SPECULAR_TRANSMISSION_RESERVED_BITS";
pub(super) const SCREEN_SPACE_SPECULAR_TRANSMISSION_LOW:
&'static str =
"SCREEN_SPACE_SPECULAR_TRANSMISSION_LOW";
pub(super) const SCREEN_SPACE_SPECULAR_TRANSMISSION_MEDIUM:
&'static str =
"SCREEN_SPACE_SPECULAR_TRANSMISSION_MEDIUM";
pub(super) const SCREEN_SPACE_SPECULAR_TRANSMISSION_HIGH:
&'static str =
"SCREEN_SPACE_SPECULAR_TRANSMISSION_HIGH";
pub(super) const SCREEN_SPACE_SPECULAR_TRANSMISSION_ULTRA:
&'static str =
"SCREEN_SPACE_SPECULAR_TRANSMISSION_ULTRA";
pub(super) const COLOR_TARGET_FORMAT_RESERVED_BITS:
&'static str =
"COLOR_TARGET_FORMAT_RESERVED_BITS";
pub(super) const ALL_RESERVED_BITS: &'static str =
"ALL_RESERVED_BITS";
}
{
{
if name == __bitflags_flag_names::NONE {
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::NONE.bits()));
}
};
};
{
{
if name == __bitflags_flag_names::MORPH_TARGETS {
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::MORPH_TARGETS.bits()));
}
};
};
{
{
if name == __bitflags_flag_names::TONEMAP_IN_SHADER {
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::TONEMAP_IN_SHADER.bits()));
}
};
};
{
{
if name == __bitflags_flag_names::DEBAND_DITHER {
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::DEBAND_DITHER.bits()));
}
};
};
{
{
if name == __bitflags_flag_names::DEPTH_PREPASS {
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::DEPTH_PREPASS.bits()));
}
};
};
{
{
if name == __bitflags_flag_names::NORMAL_PREPASS {
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::NORMAL_PREPASS.bits()));
}
};
};
{
{
if name == __bitflags_flag_names::DEFERRED_PREPASS {
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::DEFERRED_PREPASS.bits()));
}
};
};
{
{
if name == __bitflags_flag_names::MOTION_VECTOR_PREPASS {
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::MOTION_VECTOR_PREPASS.bits()));
}
};
};
{
{
if name == __bitflags_flag_names::MAY_DISCARD {
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::MAY_DISCARD.bits()));
}
};
};
{
{
if name == __bitflags_flag_names::ENVIRONMENT_MAP {
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::ENVIRONMENT_MAP.bits()));
}
};
};
{
{
if name ==
__bitflags_flag_names::SCREEN_SPACE_AMBIENT_OCCLUSION {
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::SCREEN_SPACE_AMBIENT_OCCLUSION.bits()));
}
};
};
{
{
if name == __bitflags_flag_names::UNCLIPPED_DEPTH_ORTHO {
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::UNCLIPPED_DEPTH_ORTHO.bits()));
}
};
};
{
{
if name == __bitflags_flag_names::TEMPORAL_JITTER {
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::TEMPORAL_JITTER.bits()));
}
};
};
{
{
if name ==
__bitflags_flag_names::READS_VIEW_TRANSMISSION_TEXTURE {
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::READS_VIEW_TRANSMISSION_TEXTURE.bits()));
}
};
};
{
{
if name == __bitflags_flag_names::LIGHTMAPPED {
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::LIGHTMAPPED.bits()));
}
};
};
{
{
if name == __bitflags_flag_names::LIGHTMAP_BICUBIC_SAMPLING
{
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::LIGHTMAP_BICUBIC_SAMPLING.bits()));
}
};
};
{
{
if name == __bitflags_flag_names::IRRADIANCE_VOLUME {
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::IRRADIANCE_VOLUME.bits()));
}
};
};
{
{
if name == __bitflags_flag_names::VISIBILITY_RANGE_DITHER {
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::VISIBILITY_RANGE_DITHER.bits()));
}
};
};
{
{
if name == __bitflags_flag_names::SCREEN_SPACE_REFLECTIONS {
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::SCREEN_SPACE_REFLECTIONS.bits()));
}
};
};
{
{
if name == __bitflags_flag_names::HAS_PREVIOUS_SKIN {
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::HAS_PREVIOUS_SKIN.bits()));
}
};
};
{
{
if name == __bitflags_flag_names::HAS_PREVIOUS_MORPH {
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::HAS_PREVIOUS_MORPH.bits()));
}
};
};
{
{
if name == __bitflags_flag_names::OIT_ENABLED {
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::OIT_ENABLED.bits()));
}
};
};
{
{
if name == __bitflags_flag_names::DISTANCE_FOG {
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::DISTANCE_FOG.bits()));
}
};
};
{
{
if name == __bitflags_flag_names::ATMOSPHERE {
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::ATMOSPHERE.bits()));
}
};
};
{
{
if name == __bitflags_flag_names::INVERT_CULLING {
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::INVERT_CULLING.bits()));
}
};
};
{
{
if name == __bitflags_flag_names::PREPASS_READS_MATERIAL {
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::PREPASS_READS_MATERIAL.bits()));
}
};
};
{
{
if name == __bitflags_flag_names::CONTACT_SHADOWS {
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::CONTACT_SHADOWS.bits()));
}
};
};
{
{
if name == __bitflags_flag_names::LAST_FLAG {
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::LAST_FLAG.bits()));
}
};
};
{
{
if name == __bitflags_flag_names::ALL_PREPASS_BITS {
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::ALL_PREPASS_BITS.bits()));
}
};
};
{
{
if name == __bitflags_flag_names::MSAA_RESERVED_BITS {
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::MSAA_RESERVED_BITS.bits()));
}
};
};
{
{
if name == __bitflags_flag_names::BLEND_RESERVED_BITS {
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::BLEND_RESERVED_BITS.bits()));
}
};
};
{
{
if name == __bitflags_flag_names::BLEND_OPAQUE {
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::BLEND_OPAQUE.bits()));
}
};
};
{
{
if name == __bitflags_flag_names::BLEND_PREMULTIPLIED_ALPHA
{
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::BLEND_PREMULTIPLIED_ALPHA.bits()));
}
};
};
{
{
if name == __bitflags_flag_names::BLEND_MULTIPLY {
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::BLEND_MULTIPLY.bits()));
}
};
};
{
{
if name == __bitflags_flag_names::BLEND_ALPHA {
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::BLEND_ALPHA.bits()));
}
};
};
{
{
if name == __bitflags_flag_names::BLEND_ALPHA_TO_COVERAGE {
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::BLEND_ALPHA_TO_COVERAGE.bits()));
}
};
};
{
{
if name ==
__bitflags_flag_names::TONEMAP_METHOD_RESERVED_BITS {
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::TONEMAP_METHOD_RESERVED_BITS.bits()));
}
};
};
{
{
if name == __bitflags_flag_names::TONEMAP_METHOD_NONE {
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::TONEMAP_METHOD_NONE.bits()));
}
};
};
{
{
if name == __bitflags_flag_names::TONEMAP_METHOD_REINHARD {
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::TONEMAP_METHOD_REINHARD.bits()));
}
};
};
{
{
if name ==
__bitflags_flag_names::TONEMAP_METHOD_REINHARD_LUMINANCE {
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::TONEMAP_METHOD_REINHARD_LUMINANCE.bits()));
}
};
};
{
{
if name == __bitflags_flag_names::TONEMAP_METHOD_ACES_FITTED
{
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::TONEMAP_METHOD_ACES_FITTED.bits()));
}
};
};
{
{
if name == __bitflags_flag_names::TONEMAP_METHOD_AGX {
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::TONEMAP_METHOD_AGX.bits()));
}
};
};
{
{
if name ==
__bitflags_flag_names::TONEMAP_METHOD_SOMEWHAT_BORING_DISPLAY_TRANSFORM
{
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::TONEMAP_METHOD_SOMEWHAT_BORING_DISPLAY_TRANSFORM.bits()));
}
};
};
{
{
if name ==
__bitflags_flag_names::TONEMAP_METHOD_TONY_MC_MAPFACE {
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::TONEMAP_METHOD_TONY_MC_MAPFACE.bits()));
}
};
};
{
{
if name ==
__bitflags_flag_names::TONEMAP_METHOD_BLENDER_FILMIC {
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::TONEMAP_METHOD_BLENDER_FILMIC.bits()));
}
};
};
{
{
if name == __bitflags_flag_names::TONEMAP_METHOD_PBR_NEUTRAL
{
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::TONEMAP_METHOD_PBR_NEUTRAL.bits()));
}
};
};
{
{
if name ==
__bitflags_flag_names::SHADOW_FILTER_METHOD_RESERVED_BITS {
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::SHADOW_FILTER_METHOD_RESERVED_BITS.bits()));
}
};
};
{
{
if name ==
__bitflags_flag_names::SHADOW_FILTER_METHOD_HARDWARE_2X2 {
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::SHADOW_FILTER_METHOD_HARDWARE_2X2.bits()));
}
};
};
{
{
if name ==
__bitflags_flag_names::SHADOW_FILTER_METHOD_GAUSSIAN {
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::SHADOW_FILTER_METHOD_GAUSSIAN.bits()));
}
};
};
{
{
if name ==
__bitflags_flag_names::SHADOW_FILTER_METHOD_TEMPORAL {
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::SHADOW_FILTER_METHOD_TEMPORAL.bits()));
}
};
};
{
{
if name ==
__bitflags_flag_names::VIEW_PROJECTION_RESERVED_BITS {
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::VIEW_PROJECTION_RESERVED_BITS.bits()));
}
};
};
{
{
if name ==
__bitflags_flag_names::VIEW_PROJECTION_NONSTANDARD {
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::VIEW_PROJECTION_NONSTANDARD.bits()));
}
};
};
{
{
if name ==
__bitflags_flag_names::VIEW_PROJECTION_PERSPECTIVE {
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::VIEW_PROJECTION_PERSPECTIVE.bits()));
}
};
};
{
{
if name ==
__bitflags_flag_names::VIEW_PROJECTION_ORTHOGRAPHIC {
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::VIEW_PROJECTION_ORTHOGRAPHIC.bits()));
}
};
};
{
{
if name == __bitflags_flag_names::VIEW_PROJECTION_RESERVED {
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::VIEW_PROJECTION_RESERVED.bits()));
}
};
};
{
{
if name ==
__bitflags_flag_names::SCREEN_SPACE_SPECULAR_TRANSMISSION_RESERVED_BITS
{
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::SCREEN_SPACE_SPECULAR_TRANSMISSION_RESERVED_BITS.bits()));
}
};
};
{
{
if name ==
__bitflags_flag_names::SCREEN_SPACE_SPECULAR_TRANSMISSION_LOW
{
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::SCREEN_SPACE_SPECULAR_TRANSMISSION_LOW.bits()));
}
};
};
{
{
if name ==
__bitflags_flag_names::SCREEN_SPACE_SPECULAR_TRANSMISSION_MEDIUM
{
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::SCREEN_SPACE_SPECULAR_TRANSMISSION_MEDIUM.bits()));
}
};
};
{
{
if name ==
__bitflags_flag_names::SCREEN_SPACE_SPECULAR_TRANSMISSION_HIGH
{
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::SCREEN_SPACE_SPECULAR_TRANSMISSION_HIGH.bits()));
}
};
};
{
{
if name ==
__bitflags_flag_names::SCREEN_SPACE_SPECULAR_TRANSMISSION_ULTRA
{
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::SCREEN_SPACE_SPECULAR_TRANSMISSION_ULTRA.bits()));
}
};
};
{
{
if name ==
__bitflags_flag_names::COLOR_TARGET_FORMAT_RESERVED_BITS {
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::COLOR_TARGET_FORMAT_RESERVED_BITS.bits()));
}
};
};
{
{
if name == __bitflags_flag_names::ALL_RESERVED_BITS {
return ::bitflags::__private::core::option::Option::Some(Self(MeshPipelineKey::ALL_RESERVED_BITS.bits()));
}
};
};
let _ = name;
::bitflags::__private::core::option::Option::None
}
#[inline]
pub const fn is_empty(&self) -> bool {
self.0 == <u64 as ::bitflags::Bits>::EMPTY
}
#[inline]
pub const fn is_all(&self) -> bool {
Self::all().0 | self.0 == self.0
}
#[inline]
pub const fn intersects(&self, other: Self) -> bool {
self.0 & other.0 != <u64 as ::bitflags::Bits>::EMPTY
}
#[inline]
pub const fn contains(&self, other: Self) -> bool {
self.0 & other.0 == other.0
}
#[inline]
pub fn insert(&mut self, other: Self) {
*self = Self(self.0).union(other);
}
#[inline]
pub fn remove(&mut self, other: Self) {
*self = Self(self.0).difference(other);
}
#[inline]
pub fn toggle(&mut self, other: Self) {
*self = Self(self.0).symmetric_difference(other);
}
#[inline]
pub fn set(&mut self, other: Self, value: bool) {
if value { self.insert(other); } else { self.remove(other); }
}
#[inline]
#[must_use]
pub const fn intersection(self, other: Self) -> Self {
Self(self.0 & other.0)
}
#[inline]
#[must_use]
pub const fn union(self, other: Self) -> Self {
Self(self.0 | other.0)
}
#[inline]
#[must_use]
pub const fn difference(self, other: Self) -> Self {
Self(self.0 & !other.0)
}
#[inline]
#[must_use]
pub const fn symmetric_difference(self, other: Self) -> Self {
Self(self.0 ^ other.0)
}
#[inline]
#[must_use]
pub const fn complement(self) -> Self {
Self::from_bits_truncate(!self.0)
}
}
impl ::bitflags::__private::core::fmt::Binary for InternalBitFlags {
fn fmt(&self, f: &mut ::bitflags::__private::core::fmt::Formatter)
-> ::bitflags::__private::core::fmt::Result {
let inner = self.0;
::bitflags::__private::core::fmt::Binary::fmt(&inner, f)
}
}
impl ::bitflags::__private::core::fmt::Octal for InternalBitFlags {
fn fmt(&self, f: &mut ::bitflags::__private::core::fmt::Formatter)
-> ::bitflags::__private::core::fmt::Result {
let inner = self.0;
::bitflags::__private::core::fmt::Octal::fmt(&inner, f)
}
}
impl ::bitflags::__private::core::fmt::LowerHex for InternalBitFlags {
fn fmt(&self, f: &mut ::bitflags::__private::core::fmt::Formatter)
-> ::bitflags::__private::core::fmt::Result {
let inner = self.0;
::bitflags::__private::core::fmt::LowerHex::fmt(&inner, f)
}
}
impl ::bitflags::__private::core::fmt::UpperHex for InternalBitFlags {
fn fmt(&self, f: &mut ::bitflags::__private::core::fmt::Formatter)
-> ::bitflags::__private::core::fmt::Result {
let inner = self.0;
::bitflags::__private::core::fmt::UpperHex::fmt(&inner, f)
}
}
impl ::bitflags::__private::core::ops::BitOr for InternalBitFlags {
type Output = Self;
#[inline]
fn bitor(self, other: InternalBitFlags) -> Self {
self.union(other)
}
}
impl ::bitflags::__private::core::ops::BitOrAssign for
InternalBitFlags {
#[inline]
fn bitor_assign(&mut self, other: Self) { self.insert(other); }
}
impl ::bitflags::__private::core::ops::BitXor for InternalBitFlags {
type Output = Self;
#[inline]
fn bitxor(self, other: Self) -> Self {
self.symmetric_difference(other)
}
}
impl ::bitflags::__private::core::ops::BitXorAssign for
InternalBitFlags {
#[inline]
fn bitxor_assign(&mut self, other: Self) { self.toggle(other); }
}
impl ::bitflags::__private::core::ops::BitAnd for InternalBitFlags {
type Output = Self;
#[inline]
fn bitand(self, other: Self) -> Self { self.intersection(other) }
}
impl ::bitflags::__private::core::ops::BitAndAssign for
InternalBitFlags {
#[inline]
fn bitand_assign(&mut self, other: Self) {
*self =
Self::from_bits_retain(self.bits()).intersection(other);
}
}
impl ::bitflags::__private::core::ops::Sub for InternalBitFlags {
type Output = Self;
#[inline]
fn sub(self, other: Self) -> Self { self.difference(other) }
}
impl ::bitflags::__private::core::ops::SubAssign for InternalBitFlags
{
#[inline]
fn sub_assign(&mut self, other: Self) { self.remove(other); }
}
impl ::bitflags::__private::core::ops::Not for InternalBitFlags {
type Output = Self;
#[inline]
fn not(self) -> Self { self.complement() }
}
impl ::bitflags::__private::core::iter::Extend<InternalBitFlags> for
InternalBitFlags {
fn extend<T: ::bitflags::__private::core::iter::IntoIterator<Item
= Self>>(&mut self, iterator: T) {
for item in iterator { self.insert(item) }
}
}
impl ::bitflags::__private::core::iter::FromIterator<InternalBitFlags>
for InternalBitFlags {
fn from_iter<T: ::bitflags::__private::core::iter::IntoIterator<Item
= Self>>(iterator: T) -> Self {
use ::bitflags::__private::core::iter::Extend;
let mut result = Self::empty();
result.extend(iterator);
result
}
}
impl InternalBitFlags {
#[inline]
pub const fn iter(&self)
-> ::bitflags::iter::Iter<MeshPipelineKey> {
::bitflags::iter::Iter::__private_const_new(<MeshPipelineKey
as ::bitflags::Flags>::FLAGS,
MeshPipelineKey::from_bits_retain(self.bits()),
MeshPipelineKey::from_bits_retain(self.bits()))
}
#[inline]
pub const fn iter_names(&self)
-> ::bitflags::iter::IterNames<MeshPipelineKey> {
::bitflags::iter::IterNames::__private_const_new(<MeshPipelineKey
as ::bitflags::Flags>::FLAGS,
MeshPipelineKey::from_bits_retain(self.bits()),
MeshPipelineKey::from_bits_retain(self.bits()))
}
}
impl ::bitflags::__private::core::iter::IntoIterator for
InternalBitFlags {
type Item = MeshPipelineKey;
type IntoIter = ::bitflags::iter::Iter<MeshPipelineKey>;
fn into_iter(self) -> Self::IntoIter { self.iter() }
}
impl InternalBitFlags {
#[inline]
pub fn bits_mut(&mut self) -> &mut u64 { &mut self.0 }
}
impl ::bitflags::__private::serde::Serialize for InternalBitFlags {
fn serialize<S: ::bitflags::__private::serde::Serializer>(&self,
serializer: S)
->
::bitflags::__private::core::result::Result<S::Ok,
S::Error> {
::bitflags::serde::serialize(&MeshPipelineKey::from_bits_retain(self.bits()),
serializer)
}
}
impl<'de> ::bitflags::__private::serde::Deserialize<'de> for
InternalBitFlags {
fn deserialize<D: ::bitflags::__private::serde::Deserializer<'de>>(deserializer:
D)
->
::bitflags::__private::core::result::Result<Self,
D::Error> {
let flags: MeshPipelineKey =
::bitflags::serde::deserialize(deserializer)?;
::bitflags::__private::core::result::Result::Ok(flags.0)
}
}
unsafe impl ::bitflags::__private::bytemuck::Pod for InternalBitFlags
where u64: ::bitflags::__private::bytemuck::Pod {}
unsafe impl ::bitflags::__private::bytemuck::Zeroable for
InternalBitFlags where
u64: ::bitflags::__private::bytemuck::Zeroable {}
impl MeshPipelineKey {
#[inline]
pub const fn empty() -> Self { Self(InternalBitFlags::empty()) }
#[inline]
pub const fn all() -> Self { Self(InternalBitFlags::all()) }
#[inline]
pub const fn bits(&self) -> u64 { self.0.bits() }
#[inline]
pub const fn from_bits(bits: u64)
-> ::bitflags::__private::core::option::Option<Self> {
match InternalBitFlags::from_bits(bits) {
::bitflags::__private::core::option::Option::Some(bits) =>
::bitflags::__private::core::option::Option::Some(Self(bits)),
::bitflags::__private::core::option::Option::None =>
::bitflags::__private::core::option::Option::None,
}
}
#[inline]
pub const fn from_bits_truncate(bits: u64) -> Self {
Self(InternalBitFlags::from_bits_truncate(bits))
}
#[inline]
pub const fn from_bits_retain(bits: u64) -> Self {
Self(InternalBitFlags::from_bits_retain(bits))
}
#[inline]
pub fn from_name(name: &str)
-> ::bitflags::__private::core::option::Option<Self> {
match InternalBitFlags::from_name(name) {
::bitflags::__private::core::option::Option::Some(bits) =>
::bitflags::__private::core::option::Option::Some(Self(bits)),
::bitflags::__private::core::option::Option::None =>
::bitflags::__private::core::option::Option::None,
}
}
#[inline]
pub const fn is_empty(&self) -> bool { self.0.is_empty() }
#[inline]
pub const fn is_all(&self) -> bool { self.0.is_all() }
#[inline]
pub const fn intersects(&self, other: Self) -> bool {
self.0.intersects(other.0)
}
#[inline]
pub const fn contains(&self, other: Self) -> bool {
self.0.contains(other.0)
}
#[inline]
pub fn insert(&mut self, other: Self) { self.0.insert(other.0) }
#[inline]
pub fn remove(&mut self, other: Self) { self.0.remove(other.0) }
#[inline]
pub fn toggle(&mut self, other: Self) { self.0.toggle(other.0) }
#[inline]
pub fn set(&mut self, other: Self, value: bool) {
self.0.set(other.0, value)
}
#[inline]
#[must_use]
pub const fn intersection(self, other: Self) -> Self {
Self(self.0.intersection(other.0))
}
#[inline]
#[must_use]
pub const fn union(self, other: Self) -> Self {
Self(self.0.union(other.0))
}
#[inline]
#[must_use]
pub const fn difference(self, other: Self) -> Self {
Self(self.0.difference(other.0))
}
#[inline]
#[must_use]
pub const fn symmetric_difference(self, other: Self) -> Self {
Self(self.0.symmetric_difference(other.0))
}
#[inline]
#[must_use]
pub const fn complement(self) -> Self {
Self(self.0.complement())
}
}
impl ::bitflags::__private::core::fmt::Binary for MeshPipelineKey {
fn fmt(&self, f: &mut ::bitflags::__private::core::fmt::Formatter)
-> ::bitflags::__private::core::fmt::Result {
let inner = self.0;
::bitflags::__private::core::fmt::Binary::fmt(&inner, f)
}
}
impl ::bitflags::__private::core::fmt::Octal for MeshPipelineKey {
fn fmt(&self, f: &mut ::bitflags::__private::core::fmt::Formatter)
-> ::bitflags::__private::core::fmt::Result {
let inner = self.0;
::bitflags::__private::core::fmt::Octal::fmt(&inner, f)
}
}
impl ::bitflags::__private::core::fmt::LowerHex for MeshPipelineKey {
fn fmt(&self, f: &mut ::bitflags::__private::core::fmt::Formatter)
-> ::bitflags::__private::core::fmt::Result {
let inner = self.0;
::bitflags::__private::core::fmt::LowerHex::fmt(&inner, f)
}
}
impl ::bitflags::__private::core::fmt::UpperHex for MeshPipelineKey {
fn fmt(&self, f: &mut ::bitflags::__private::core::fmt::Formatter)
-> ::bitflags::__private::core::fmt::Result {
let inner = self.0;
::bitflags::__private::core::fmt::UpperHex::fmt(&inner, f)
}
}
impl ::bitflags::__private::core::ops::BitOr for MeshPipelineKey {
type Output = Self;
#[inline]
fn bitor(self, other: MeshPipelineKey) -> Self {
self.union(other)
}
}
impl ::bitflags::__private::core::ops::BitOrAssign for MeshPipelineKey
{
#[inline]
fn bitor_assign(&mut self, other: Self) { self.insert(other); }
}
impl ::bitflags::__private::core::ops::BitXor for MeshPipelineKey {
type Output = Self;
#[inline]
fn bitxor(self, other: Self) -> Self {
self.symmetric_difference(other)
}
}
impl ::bitflags::__private::core::ops::BitXorAssign for
MeshPipelineKey {
#[inline]
fn bitxor_assign(&mut self, other: Self) { self.toggle(other); }
}
impl ::bitflags::__private::core::ops::BitAnd for MeshPipelineKey {
type Output = Self;
#[inline]
fn bitand(self, other: Self) -> Self { self.intersection(other) }
}
impl ::bitflags::__private::core::ops::BitAndAssign for
MeshPipelineKey {
#[inline]
fn bitand_assign(&mut self, other: Self) {
*self =
Self::from_bits_retain(self.bits()).intersection(other);
}
}
impl ::bitflags::__private::core::ops::Sub for MeshPipelineKey {
type Output = Self;
#[inline]
fn sub(self, other: Self) -> Self { self.difference(other) }
}
impl ::bitflags::__private::core::ops::SubAssign for MeshPipelineKey {
#[inline]
fn sub_assign(&mut self, other: Self) { self.remove(other); }
}
impl ::bitflags::__private::core::ops::Not for MeshPipelineKey {
type Output = Self;
#[inline]
fn not(self) -> Self { self.complement() }
}
impl ::bitflags::__private::core::iter::Extend<MeshPipelineKey> for
MeshPipelineKey {
fn extend<T: ::bitflags::__private::core::iter::IntoIterator<Item
= Self>>(&mut self, iterator: T) {
for item in iterator { self.insert(item) }
}
}
impl ::bitflags::__private::core::iter::FromIterator<MeshPipelineKey>
for MeshPipelineKey {
fn from_iter<T: ::bitflags::__private::core::iter::IntoIterator<Item
= Self>>(iterator: T) -> Self {
use ::bitflags::__private::core::iter::Extend;
let mut result = Self::empty();
result.extend(iterator);
result
}
}
impl MeshPipelineKey {
#[inline]
pub const fn iter(&self)
-> ::bitflags::iter::Iter<MeshPipelineKey> {
::bitflags::iter::Iter::__private_const_new(<MeshPipelineKey
as ::bitflags::Flags>::FLAGS,
MeshPipelineKey::from_bits_retain(self.bits()),
MeshPipelineKey::from_bits_retain(self.bits()))
}
#[inline]
pub const fn iter_names(&self)
-> ::bitflags::iter::IterNames<MeshPipelineKey> {
::bitflags::iter::IterNames::__private_const_new(<MeshPipelineKey
as ::bitflags::Flags>::FLAGS,
MeshPipelineKey::from_bits_retain(self.bits()),
MeshPipelineKey::from_bits_retain(self.bits()))
}
}
impl ::bitflags::__private::core::iter::IntoIterator for
MeshPipelineKey {
type Item = MeshPipelineKey;
type IntoIter = ::bitflags::iter::Iter<MeshPipelineKey>;
fn into_iter(self) -> Self::IntoIter { self.iter() }
}
};bitflags::bitflags! {
2985 #[derive(Default, Clone, Copy, Debug, PartialEq, Eq, Hash)]
2986 #[repr(transparent)]
2987 pub struct MeshPipelineKey: u64 {
2990 const NONE = 0;
2992
2993 const MORPH_TARGETS = BaseMeshPipelineKey::MORPH_TARGETS.bits();
2995
2996 const TONEMAP_IN_SHADER = 1 << 0;
2998 const DEBAND_DITHER = 1 << 1;
2999 const DEPTH_PREPASS = 1 << 2;
3000 const NORMAL_PREPASS = 1 << 3;
3001 const DEFERRED_PREPASS = 1 << 4;
3002 const MOTION_VECTOR_PREPASS = 1 << 5;
3003 const MAY_DISCARD = 1 << 6; const ENVIRONMENT_MAP = 1 << 7;
3006 const SCREEN_SPACE_AMBIENT_OCCLUSION = 1 << 8;
3007 const UNCLIPPED_DEPTH_ORTHO = 1 << 9; const TEMPORAL_JITTER = 1 << 10;
3011 const READS_VIEW_TRANSMISSION_TEXTURE = 1 << 11;
3012 const LIGHTMAPPED = 1 << 12;
3013 const LIGHTMAP_BICUBIC_SAMPLING = 1 << 13;
3014 const IRRADIANCE_VOLUME = 1 << 14;
3015 const VISIBILITY_RANGE_DITHER = 1 << 15;
3016 const SCREEN_SPACE_REFLECTIONS = 1 << 16;
3017 const HAS_PREVIOUS_SKIN = 1 << 17;
3018 const HAS_PREVIOUS_MORPH = 1 << 18;
3019 const OIT_ENABLED = 1 << 19;
3020 const DISTANCE_FOG = 1 << 20;
3021 const ATMOSPHERE = 1 << 21;
3022 const INVERT_CULLING = 1 << 22;
3023 const PREPASS_READS_MATERIAL = 1 << 23;
3024 const CONTACT_SHADOWS = 1 << 24;
3025 const LAST_FLAG = Self::CONTACT_SHADOWS.bits();
3026
3027 const ALL_PREPASS_BITS = Self::DEPTH_PREPASS.bits()
3028 | Self::NORMAL_PREPASS.bits()
3029 | Self::DEFERRED_PREPASS.bits()
3030 | Self::MOTION_VECTOR_PREPASS.bits()
3031 | Self::MAY_DISCARD.bits()
3032 | Self::PREPASS_READS_MATERIAL.bits();
3033
3034 const MSAA_RESERVED_BITS = Self::MSAA_MASK_BITS << Self::MSAA_SHIFT_BITS;
3036 const BLEND_RESERVED_BITS = Self::BLEND_MASK_BITS << Self::BLEND_SHIFT_BITS; const BLEND_OPAQUE = 0 << Self::BLEND_SHIFT_BITS; const BLEND_PREMULTIPLIED_ALPHA = 1 << Self::BLEND_SHIFT_BITS; const BLEND_MULTIPLY = 2 << Self::BLEND_SHIFT_BITS; const BLEND_ALPHA = 3 << Self::BLEND_SHIFT_BITS; const BLEND_ALPHA_TO_COVERAGE = 4 << Self::BLEND_SHIFT_BITS; const TONEMAP_METHOD_RESERVED_BITS = Self::TONEMAP_METHOD_MASK_BITS << Self::TONEMAP_METHOD_SHIFT_BITS;
3043 const TONEMAP_METHOD_NONE = 0 << Self::TONEMAP_METHOD_SHIFT_BITS;
3044 const TONEMAP_METHOD_REINHARD = 1 << Self::TONEMAP_METHOD_SHIFT_BITS;
3045 const TONEMAP_METHOD_REINHARD_LUMINANCE = 2 << Self::TONEMAP_METHOD_SHIFT_BITS;
3046 const TONEMAP_METHOD_ACES_FITTED = 3 << Self::TONEMAP_METHOD_SHIFT_BITS;
3047 const TONEMAP_METHOD_AGX = 4 << Self::TONEMAP_METHOD_SHIFT_BITS;
3048 const TONEMAP_METHOD_SOMEWHAT_BORING_DISPLAY_TRANSFORM = 5 << Self::TONEMAP_METHOD_SHIFT_BITS;
3049 const TONEMAP_METHOD_TONY_MC_MAPFACE = 6 << Self::TONEMAP_METHOD_SHIFT_BITS;
3050 const TONEMAP_METHOD_BLENDER_FILMIC = 7 << Self::TONEMAP_METHOD_SHIFT_BITS;
3051 const TONEMAP_METHOD_PBR_NEUTRAL = 8 << Self::TONEMAP_METHOD_SHIFT_BITS;
3052 const SHADOW_FILTER_METHOD_RESERVED_BITS = Self::SHADOW_FILTER_METHOD_MASK_BITS << Self::SHADOW_FILTER_METHOD_SHIFT_BITS;
3053 const SHADOW_FILTER_METHOD_HARDWARE_2X2 = 0 << Self::SHADOW_FILTER_METHOD_SHIFT_BITS;
3054 const SHADOW_FILTER_METHOD_GAUSSIAN = 1 << Self::SHADOW_FILTER_METHOD_SHIFT_BITS;
3055 const SHADOW_FILTER_METHOD_TEMPORAL = 2 << Self::SHADOW_FILTER_METHOD_SHIFT_BITS;
3056 const VIEW_PROJECTION_RESERVED_BITS = Self::VIEW_PROJECTION_MASK_BITS << Self::VIEW_PROJECTION_SHIFT_BITS;
3057 const VIEW_PROJECTION_NONSTANDARD = 0 << Self::VIEW_PROJECTION_SHIFT_BITS;
3058 const VIEW_PROJECTION_PERSPECTIVE = 1 << Self::VIEW_PROJECTION_SHIFT_BITS;
3059 const VIEW_PROJECTION_ORTHOGRAPHIC = 2 << Self::VIEW_PROJECTION_SHIFT_BITS;
3060 const VIEW_PROJECTION_RESERVED = 3 << Self::VIEW_PROJECTION_SHIFT_BITS;
3061 const SCREEN_SPACE_SPECULAR_TRANSMISSION_RESERVED_BITS = Self::SCREEN_SPACE_SPECULAR_TRANSMISSION_MASK_BITS << Self::SCREEN_SPACE_SPECULAR_TRANSMISSION_SHIFT_BITS;
3062 const SCREEN_SPACE_SPECULAR_TRANSMISSION_LOW = 0 << Self::SCREEN_SPACE_SPECULAR_TRANSMISSION_SHIFT_BITS;
3063 const SCREEN_SPACE_SPECULAR_TRANSMISSION_MEDIUM = 1 << Self::SCREEN_SPACE_SPECULAR_TRANSMISSION_SHIFT_BITS;
3064 const SCREEN_SPACE_SPECULAR_TRANSMISSION_HIGH = 2 << Self::SCREEN_SPACE_SPECULAR_TRANSMISSION_SHIFT_BITS;
3065 const SCREEN_SPACE_SPECULAR_TRANSMISSION_ULTRA = 3 << Self::SCREEN_SPACE_SPECULAR_TRANSMISSION_SHIFT_BITS;
3066 const COLOR_TARGET_FORMAT_RESERVED_BITS = Self::COLOR_TARGET_FORMAT_MASK_BITS
3067 << Self::COLOR_TARGET_FORMAT_SHIFT_BITS;
3068 const ALL_RESERVED_BITS =
3069 Self::BLEND_RESERVED_BITS.bits() |
3070 Self::MSAA_RESERVED_BITS.bits() |
3071 Self::TONEMAP_METHOD_RESERVED_BITS.bits() |
3072 Self::SHADOW_FILTER_METHOD_RESERVED_BITS.bits() |
3073 Self::VIEW_PROJECTION_RESERVED_BITS.bits() |
3074 Self::SCREEN_SPACE_SPECULAR_TRANSMISSION_RESERVED_BITS.bits() |
3075 Self::COLOR_TARGET_FORMAT_RESERVED_BITS.bits();
3076 }
3077}
3078
3079impl MeshPipelineKey {
3080 const MSAA_MASK_BITS: u64 = 0b111;
3081 const MSAA_SHIFT_BITS: u64 = Self::LAST_FLAG.bits().trailing_zeros() as u64 + 1;
3082
3083 const BLEND_MASK_BITS: u64 = 0b111;
3084 const BLEND_SHIFT_BITS: u64 = Self::MSAA_MASK_BITS.count_ones() as u64 + Self::MSAA_SHIFT_BITS;
3085
3086 const TONEMAP_METHOD_MASK_BITS: u64 = 0b1111;
3087 const TONEMAP_METHOD_SHIFT_BITS: u64 =
3088 Self::BLEND_MASK_BITS.count_ones() as u64 + Self::BLEND_SHIFT_BITS;
3089
3090 const SHADOW_FILTER_METHOD_MASK_BITS: u64 = 0b11;
3091 const SHADOW_FILTER_METHOD_SHIFT_BITS: u64 =
3092 Self::TONEMAP_METHOD_MASK_BITS.count_ones() as u64 + Self::TONEMAP_METHOD_SHIFT_BITS;
3093
3094 const VIEW_PROJECTION_MASK_BITS: u64 = 0b11;
3095 const VIEW_PROJECTION_SHIFT_BITS: u64 = Self::SHADOW_FILTER_METHOD_MASK_BITS.count_ones()
3096 as u64
3097 + Self::SHADOW_FILTER_METHOD_SHIFT_BITS;
3098
3099 const SCREEN_SPACE_SPECULAR_TRANSMISSION_MASK_BITS: u64 = 0b11;
3100 const SCREEN_SPACE_SPECULAR_TRANSMISSION_SHIFT_BITS: u64 =
3101 Self::VIEW_PROJECTION_MASK_BITS.count_ones() as u64 + Self::VIEW_PROJECTION_SHIFT_BITS;
3102
3103 const COLOR_TARGET_FORMAT_MASK_BITS: u64 = view::COLOR_TARGET_FORMAT_MASK_BITS as u64;
3104 const COLOR_TARGET_FORMAT_SHIFT_BITS: u64 = Self::SCREEN_SPACE_SPECULAR_TRANSMISSION_MASK_BITS
3105 .count_ones() as u64
3106 + Self::SCREEN_SPACE_SPECULAR_TRANSMISSION_SHIFT_BITS;
3107
3108 pub fn from_msaa_samples(msaa_samples: u32) -> Self {
3109 let msaa_bits =
3110 (msaa_samples.trailing_zeros() as u64 & Self::MSAA_MASK_BITS) << Self::MSAA_SHIFT_BITS;
3111 Self::from_bits_retain(msaa_bits)
3112 }
3113
3114 #[inline]
3116 pub fn from_target_format(format: TextureFormat) -> Self {
3117 let code = texture_format_to_code(format)
3118 .expect("Texture format is not supported by the pipeline") as u64;
3119 Self::from_bits_retain(
3120 (code & Self::COLOR_TARGET_FORMAT_MASK_BITS) << Self::COLOR_TARGET_FORMAT_SHIFT_BITS,
3121 )
3122 }
3123
3124 #[inline]
3126 pub fn target_format(&self) -> TextureFormat {
3127 let code = ((self.bits() >> Self::COLOR_TARGET_FORMAT_SHIFT_BITS)
3128 & Self::COLOR_TARGET_FORMAT_MASK_BITS) as u8;
3129 texture_format_from_code(code)
3130 .expect("Unknown bits in `COLOR_TARGET_FORMAT_MASK_BITS` of the pipeline key")
3131 }
3132
3133 pub fn msaa_samples(&self) -> u32 {
3134 1 << ((self.bits() >> Self::MSAA_SHIFT_BITS) & Self::MSAA_MASK_BITS)
3135 }
3136
3137 pub fn from_primitive_topology_and_strip_index(
3141 primitive_topology: PrimitiveTopology,
3142 strip_index_format: Option<IndexFormat>,
3143 ) -> Self {
3144 let index_bits = if primitive_topology.is_strip() {
3145 match strip_index_format {
3146 None => BaseMeshPipelineKey::STRIP_INDEX_FORMAT_NONE,
3147 Some(indices) => match indices {
3148 IndexFormat::Uint16 => BaseMeshPipelineKey::STRIP_INDEX_FORMAT_U16,
3149 IndexFormat::Uint32 => BaseMeshPipelineKey::STRIP_INDEX_FORMAT_U32,
3150 },
3151 }
3152 } else {
3153 BaseMeshPipelineKey::STRIP_INDEX_FORMAT_NONE
3154 }
3155 .bits();
3156 let primitive_topology_bits = ((primitive_topology as u64)
3157 & BaseMeshPipelineKey::PRIMITIVE_TOPOLOGY_MASK_BITS)
3158 << BaseMeshPipelineKey::PRIMITIVE_TOPOLOGY_SHIFT_BITS;
3159 Self::from_bits_retain(primitive_topology_bits | index_bits)
3160 }
3161
3162 pub fn primitive_topology(&self) -> PrimitiveTopology {
3163 let primitive_topology_bits = (self.bits()
3164 >> BaseMeshPipelineKey::PRIMITIVE_TOPOLOGY_SHIFT_BITS)
3165 & BaseMeshPipelineKey::PRIMITIVE_TOPOLOGY_MASK_BITS;
3166 match primitive_topology_bits {
3167 x if x == PrimitiveTopology::PointList as u64 => PrimitiveTopology::PointList,
3168 x if x == PrimitiveTopology::LineList as u64 => PrimitiveTopology::LineList,
3169 x if x == PrimitiveTopology::LineStrip as u64 => PrimitiveTopology::LineStrip,
3170 x if x == PrimitiveTopology::TriangleList as u64 => PrimitiveTopology::TriangleList,
3171 x if x == PrimitiveTopology::TriangleStrip as u64 => PrimitiveTopology::TriangleStrip,
3172 _ => PrimitiveTopology::default(),
3173 }
3174 }
3175
3176 pub fn strip_index_format(&self) -> Option<IndexFormat> {
3177 let index_bits = self.bits() & BaseMeshPipelineKey::STRIP_INDEX_FORMAT_RESERVED_BITS.bits();
3178 match index_bits {
3179 x if x == BaseMeshPipelineKey::STRIP_INDEX_FORMAT_U16.bits() => {
3180 Some(IndexFormat::Uint16)
3181 }
3182 x if x == BaseMeshPipelineKey::STRIP_INDEX_FORMAT_U32.bits() => {
3183 Some(IndexFormat::Uint32)
3184 }
3185 x if x == BaseMeshPipelineKey::STRIP_INDEX_FORMAT_NONE.bits() => None,
3186 _ => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
3187 }
3188 }
3189}
3190
3191impl From<u64> for MeshPipelineKey {
3192 fn from(value: u64) -> Self {
3193 MeshPipelineKey::from_bits_retain(value)
3194 }
3195}
3196
3197impl From<MeshPipelineKey> for u64 {
3198 fn from(value: MeshPipelineKey) -> Self {
3199 value.bits()
3200 }
3201}
3202
3203#[allow(unknown_lints, eq_op)]
const _:
[(); 0 -
!{
const ASSERT: bool =
(((MeshPipelineKey::LAST_FLAG.bits() << 1) - 1) |
MeshPipelineKey::ALL_RESERVED_BITS.bits()) &
BaseMeshPipelineKey::all().bits() == 0;
ASSERT
} as usize] =
[];const_assert_eq!(
3205 (((MeshPipelineKey::LAST_FLAG.bits() << 1) - 1) | MeshPipelineKey::ALL_RESERVED_BITS.bits())
3206 & BaseMeshPipelineKey::all().bits(),
3207 0
3208);
3209
3210#[allow(unknown_lints, eq_op)]
const _:
[(); 0 -
!{
const ASSERT: bool =
BaseMeshPipelineKey::all().bits() &
MeshPipelineKey::all().bits() ==
MeshPipelineKey::MORPH_TARGETS.bits();
ASSERT
} as usize] =
[];const_assert_eq!(
3213 BaseMeshPipelineKey::all().bits() & MeshPipelineKey::all().bits(),
3214 MeshPipelineKey::MORPH_TARGETS.bits()
3215);
3216
3217fn is_skinned(layout: &MeshVertexBufferLayoutRef) -> bool {
3218 layout.0.contains(Mesh::ATTRIBUTE_JOINT_INDEX)
3219 && layout.0.contains(Mesh::ATTRIBUTE_JOINT_WEIGHT)
3220}
3221pub fn setup_morph_and_skinning_defs(
3222 mesh_layouts: &MeshLayouts,
3223 layout: &MeshVertexBufferLayoutRef,
3224 offset: u32,
3225 key: &MeshPipelineKey,
3226 shader_defs: &mut Vec<ShaderDefVal>,
3227 vertex_attributes: &mut Vec<VertexAttributeDescriptor>,
3228 skins_use_uniform_buffers: bool,
3229) -> BindGroupLayoutDescriptor {
3230 let is_morphed = key.intersects(MeshPipelineKey::MORPH_TARGETS);
3231 let is_lightmapped = key.intersects(MeshPipelineKey::LIGHTMAPPED);
3232 let motion_vector_prepass = key.intersects(MeshPipelineKey::MOTION_VECTOR_PREPASS);
3233
3234 if skins_use_uniform_buffers {
3235 shader_defs.push("SKINS_USE_UNIFORM_BUFFERS".into());
3236 }
3237
3238 let mut add_skin_data = || {
3239 shader_defs.push("SKINNED".into());
3240 vertex_attributes.push(Mesh::ATTRIBUTE_JOINT_INDEX.at_shader_location(offset));
3241 vertex_attributes.push(Mesh::ATTRIBUTE_JOINT_WEIGHT.at_shader_location(offset + 1));
3242 };
3243
3244 match (
3245 is_skinned(layout),
3246 is_morphed,
3247 is_lightmapped,
3248 motion_vector_prepass,
3249 ) {
3250 (true, false, _, true) => {
3251 add_skin_data();
3252 mesh_layouts.skinned_motion.clone()
3253 }
3254 (true, false, _, false) => {
3255 add_skin_data();
3256 mesh_layouts.skinned.clone()
3257 }
3258 (true, true, _, true) => {
3259 add_skin_data();
3260 shader_defs.push("MORPH_TARGETS".into());
3261 mesh_layouts.morphed_skinned_motion.clone()
3262 }
3263 (true, true, _, false) => {
3264 add_skin_data();
3265 shader_defs.push("MORPH_TARGETS".into());
3266 mesh_layouts.morphed_skinned.clone()
3267 }
3268 (false, true, _, true) => {
3269 shader_defs.push("MORPH_TARGETS".into());
3270 mesh_layouts.morphed_motion.clone()
3271 }
3272 (false, true, _, false) => {
3273 shader_defs.push("MORPH_TARGETS".into());
3274 mesh_layouts.morphed.clone()
3275 }
3276 (false, false, true, _) => mesh_layouts.lightmapped.clone(),
3277 (false, false, false, _) => mesh_layouts.model_only.clone(),
3278 }
3279}
3280
3281impl SpecializedMeshPipeline for MeshPipeline {
3282 type Key = MeshPipelineKey;
3283
3284 fn specialize(
3285 &self,
3286 key: Self::Key,
3287 layout: &MeshVertexBufferLayoutRef,
3288 ) -> Result<RenderPipelineDescriptor, SpecializedMeshPipelineError> {
3289 let mut shader_defs = Vec::new();
3290 let mut vertex_attributes = Vec::new();
3291
3292 shader_defs.push("MESH_PIPELINE".into());
3294
3295 shader_defs.push("VERTEX_OUTPUT_INSTANCE_INDEX".into());
3296
3297 if layout.0.contains(Mesh::ATTRIBUTE_POSITION) {
3298 shader_defs.push("VERTEX_POSITIONS".into());
3299 vertex_attributes.push(Mesh::ATTRIBUTE_POSITION.at_shader_location(0));
3300 }
3301
3302 if layout.0.contains(Mesh::ATTRIBUTE_NORMAL) {
3303 shader_defs.push("VERTEX_NORMALS".into());
3304 vertex_attributes.push(Mesh::ATTRIBUTE_NORMAL.at_shader_location(1));
3305 }
3306
3307 if layout.0.contains(Mesh::ATTRIBUTE_UV_0) {
3308 shader_defs.push("VERTEX_UVS".into());
3309 shader_defs.push("VERTEX_UVS_A".into());
3310 vertex_attributes.push(Mesh::ATTRIBUTE_UV_0.at_shader_location(2));
3311 }
3312
3313 if layout.0.contains(Mesh::ATTRIBUTE_UV_1) {
3314 shader_defs.push("VERTEX_UVS".into());
3315 shader_defs.push("VERTEX_UVS_B".into());
3316 vertex_attributes.push(Mesh::ATTRIBUTE_UV_1.at_shader_location(3));
3317 }
3318
3319 if layout.0.contains(Mesh::ATTRIBUTE_TANGENT) {
3320 shader_defs.push("VERTEX_TANGENTS".into());
3321 vertex_attributes.push(Mesh::ATTRIBUTE_TANGENT.at_shader_location(4));
3322 }
3323
3324 if layout.0.contains(Mesh::ATTRIBUTE_COLOR) {
3325 shader_defs.push("VERTEX_COLORS".into());
3326 vertex_attributes.push(Mesh::ATTRIBUTE_COLOR.at_shader_location(5));
3327 }
3328
3329 if truecfg!(feature = "pbr_transmission_textures") {
3330 shader_defs.push("PBR_TRANSMISSION_TEXTURES_SUPPORTED".into());
3331 }
3332 if truecfg!(feature = "pbr_multi_layer_material_textures") {
3333 shader_defs.push("PBR_MULTI_LAYER_MATERIAL_TEXTURES_SUPPORTED".into());
3334 }
3335 if truecfg!(feature = "pbr_anisotropy_texture") {
3336 shader_defs.push("PBR_ANISOTROPY_TEXTURE_SUPPORTED".into());
3337 }
3338 if truecfg!(feature = "pbr_specular_textures") {
3339 shader_defs.push("PBR_SPECULAR_TEXTURES_SUPPORTED".into());
3340 }
3341 if truecfg!(feature = "bluenoise_texture") {
3342 shader_defs.push("BLUE_NOISE_TEXTURE".into());
3343 }
3344 if truecfg!(feature = "dfg_lut") {
3345 shader_defs.push("DFG_LUT".into());
3346 }
3347 if truecfg!(feature = "area_light_luts") {
3348 shader_defs.push("AREA_LIGHT_LUTS".into());
3349 }
3350
3351 let bind_group_layout = self.get_view_layout(key.into());
3352 let mut bind_group_layout = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[bind_group_layout.main_layout.clone(),
bind_group_layout.binding_array_layout.clone()]))vec![
3353 bind_group_layout.main_layout.clone(),
3354 bind_group_layout.binding_array_layout.clone(),
3355 ];
3356
3357 if key.msaa_samples() > 1 {
3358 shader_defs.push("MULTISAMPLED".into());
3359 };
3360
3361 bind_group_layout.push(setup_morph_and_skinning_defs(
3362 &self.mesh_layouts,
3363 layout,
3364 6,
3365 &key,
3366 &mut shader_defs,
3367 &mut vertex_attributes,
3368 self.skins_use_uniform_buffers,
3369 ));
3370
3371 if key.contains(MeshPipelineKey::SCREEN_SPACE_AMBIENT_OCCLUSION) {
3372 shader_defs.push("SCREEN_SPACE_AMBIENT_OCCLUSION".into());
3373 }
3374
3375 if key.contains(MeshPipelineKey::CONTACT_SHADOWS) {
3376 shader_defs.push("CONTACT_SHADOWS".into());
3377 }
3378
3379 let vertex_buffer_layout = layout.0.get_layout(&vertex_attributes)?;
3380
3381 let (label, blend, depth_write_enabled);
3382 let pass = key.intersection(MeshPipelineKey::BLEND_RESERVED_BITS);
3383 let (mut is_opaque, mut alpha_to_coverage_enabled) = (false, false);
3384 if key.contains(MeshPipelineKey::OIT_ENABLED) && pass == MeshPipelineKey::BLEND_ALPHA {
3385 label = "oit_mesh_pipeline".into();
3386 blend = None;
3388 shader_defs.push("OIT_ENABLED".into());
3389 depth_write_enabled = false;
3392 } else if pass == MeshPipelineKey::BLEND_ALPHA {
3393 label = "alpha_blend_mesh_pipeline".into();
3394 blend = Some(BlendState::ALPHA_BLENDING);
3395 depth_write_enabled = false;
3398 } else if pass == MeshPipelineKey::BLEND_PREMULTIPLIED_ALPHA {
3399 label = "premultiplied_alpha_mesh_pipeline".into();
3400 blend = Some(BlendState::PREMULTIPLIED_ALPHA_BLENDING);
3401 shader_defs.push("PREMULTIPLY_ALPHA".into());
3402 shader_defs.push("BLEND_PREMULTIPLIED_ALPHA".into());
3403 depth_write_enabled = false;
3406 } else if pass == MeshPipelineKey::BLEND_MULTIPLY {
3407 label = "multiply_mesh_pipeline".into();
3408 blend = Some(BlendState {
3409 color: BlendComponent {
3410 src_factor: BlendFactor::Dst,
3411 dst_factor: BlendFactor::OneMinusSrcAlpha,
3412 operation: BlendOperation::Add,
3413 },
3414 alpha: BlendComponent::OVER,
3415 });
3416 shader_defs.push("PREMULTIPLY_ALPHA".into());
3417 shader_defs.push("BLEND_MULTIPLY".into());
3418 depth_write_enabled = false;
3421 } else if pass == MeshPipelineKey::BLEND_ALPHA_TO_COVERAGE {
3422 label = "alpha_to_coverage_mesh_pipeline".into();
3423 blend = None;
3425 depth_write_enabled = true;
3429 is_opaque = !key.contains(MeshPipelineKey::READS_VIEW_TRANSMISSION_TEXTURE);
3430 alpha_to_coverage_enabled = true;
3431 shader_defs.push("ALPHA_TO_COVERAGE".into());
3432 } else {
3433 label = "opaque_mesh_pipeline".into();
3434 blend = None;
3436 depth_write_enabled = true;
3440 is_opaque = !key.contains(MeshPipelineKey::READS_VIEW_TRANSMISSION_TEXTURE);
3441 }
3442
3443 if key.contains(MeshPipelineKey::NORMAL_PREPASS) {
3444 shader_defs.push("NORMAL_PREPASS".into());
3445 }
3446
3447 if key.contains(MeshPipelineKey::DEPTH_PREPASS) {
3448 shader_defs.push("DEPTH_PREPASS".into());
3449 }
3450
3451 if key.contains(MeshPipelineKey::MOTION_VECTOR_PREPASS) {
3452 shader_defs.push("MOTION_VECTOR_PREPASS".into());
3453 }
3454
3455 if key.contains(MeshPipelineKey::HAS_PREVIOUS_SKIN) {
3456 shader_defs.push("HAS_PREVIOUS_SKIN".into());
3457 }
3458
3459 if key.contains(MeshPipelineKey::HAS_PREVIOUS_MORPH) {
3460 shader_defs.push("HAS_PREVIOUS_MORPH".into());
3461 }
3462
3463 if key.contains(MeshPipelineKey::DEFERRED_PREPASS) {
3464 shader_defs.push("DEFERRED_PREPASS".into());
3465 }
3466
3467 if key.contains(MeshPipelineKey::NORMAL_PREPASS) && key.msaa_samples() == 1 && is_opaque {
3468 shader_defs.push("LOAD_PREPASS_NORMALS".into());
3469 }
3470
3471 let view_projection = key.intersection(MeshPipelineKey::VIEW_PROJECTION_RESERVED_BITS);
3472 if view_projection == MeshPipelineKey::VIEW_PROJECTION_NONSTANDARD {
3473 shader_defs.push("VIEW_PROJECTION_NONSTANDARD".into());
3474 } else if view_projection == MeshPipelineKey::VIEW_PROJECTION_PERSPECTIVE {
3475 shader_defs.push("VIEW_PROJECTION_PERSPECTIVE".into());
3476 } else if view_projection == MeshPipelineKey::VIEW_PROJECTION_ORTHOGRAPHIC {
3477 shader_defs.push("VIEW_PROJECTION_ORTHOGRAPHIC".into());
3478 }
3479
3480 #[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
3481 shader_defs.push("WEBGL2".into());
3482
3483 #[cfg(feature = "experimental_pbr_pcss")]
3484 shader_defs.push("PCSS_SAMPLERS_AVAILABLE".into());
3485
3486 if key.contains(MeshPipelineKey::TONEMAP_IN_SHADER) {
3487 shader_defs.push("TONEMAP_IN_SHADER".into());
3488 shader_defs.push(ShaderDefVal::UInt(
3489 "TONEMAPPING_LUT_TEXTURE_BINDING_INDEX".into(),
3490 TONEMAPPING_LUT_TEXTURE_BINDING_INDEX,
3491 ));
3492 shader_defs.push(ShaderDefVal::UInt(
3493 "TONEMAPPING_LUT_SAMPLER_BINDING_INDEX".into(),
3494 TONEMAPPING_LUT_SAMPLER_BINDING_INDEX,
3495 ));
3496
3497 let method = key.intersection(MeshPipelineKey::TONEMAP_METHOD_RESERVED_BITS);
3498
3499 if method == MeshPipelineKey::TONEMAP_METHOD_NONE {
3500 shader_defs.push("TONEMAP_METHOD_NONE".into());
3501 } else if method == MeshPipelineKey::TONEMAP_METHOD_REINHARD {
3502 shader_defs.push("TONEMAP_METHOD_REINHARD".into());
3503 } else if method == MeshPipelineKey::TONEMAP_METHOD_REINHARD_LUMINANCE {
3504 shader_defs.push("TONEMAP_METHOD_REINHARD_LUMINANCE".into());
3505 } else if method == MeshPipelineKey::TONEMAP_METHOD_ACES_FITTED {
3506 shader_defs.push("TONEMAP_METHOD_ACES_FITTED".into());
3507 } else if method == MeshPipelineKey::TONEMAP_METHOD_AGX {
3508 shader_defs.push("TONEMAP_METHOD_AGX".into());
3509 } else if method == MeshPipelineKey::TONEMAP_METHOD_SOMEWHAT_BORING_DISPLAY_TRANSFORM {
3510 shader_defs.push("TONEMAP_METHOD_SOMEWHAT_BORING_DISPLAY_TRANSFORM".into());
3511 } else if method == MeshPipelineKey::TONEMAP_METHOD_BLENDER_FILMIC {
3512 shader_defs.push("TONEMAP_METHOD_BLENDER_FILMIC".into());
3513 } else if method == MeshPipelineKey::TONEMAP_METHOD_TONY_MC_MAPFACE {
3514 shader_defs.push("TONEMAP_METHOD_TONY_MC_MAPFACE".into());
3515 } else if method == MeshPipelineKey::TONEMAP_METHOD_PBR_NEUTRAL {
3516 shader_defs.push("TONEMAP_METHOD_PBR_NEUTRAL".into());
3517 }
3518
3519 if key.contains(MeshPipelineKey::DEBAND_DITHER) {
3521 shader_defs.push("DEBAND_DITHER".into());
3522 }
3523 }
3524
3525 if key.contains(MeshPipelineKey::MAY_DISCARD) {
3526 shader_defs.push("MAY_DISCARD".into());
3527 }
3528
3529 if key.contains(MeshPipelineKey::ENVIRONMENT_MAP) {
3530 shader_defs.push("ENVIRONMENT_MAP".into());
3531 }
3532
3533 if key.contains(MeshPipelineKey::IRRADIANCE_VOLUME) && IRRADIANCE_VOLUMES_ARE_USABLE {
3534 shader_defs.push("IRRADIANCE_VOLUME".into());
3535 }
3536
3537 if key.contains(MeshPipelineKey::LIGHTMAPPED) {
3538 shader_defs.push("LIGHTMAP".into());
3539 }
3540 if key.contains(MeshPipelineKey::LIGHTMAP_BICUBIC_SAMPLING) {
3541 shader_defs.push("LIGHTMAP_BICUBIC_SAMPLING".into());
3542 }
3543
3544 if key.contains(MeshPipelineKey::TEMPORAL_JITTER) {
3545 shader_defs.push("TEMPORAL_JITTER".into());
3546 }
3547
3548 let shadow_filter_method =
3549 key.intersection(MeshPipelineKey::SHADOW_FILTER_METHOD_RESERVED_BITS);
3550 if shadow_filter_method == MeshPipelineKey::SHADOW_FILTER_METHOD_HARDWARE_2X2 {
3551 shader_defs.push("SHADOW_FILTER_METHOD_HARDWARE_2X2".into());
3552 } else if shadow_filter_method == MeshPipelineKey::SHADOW_FILTER_METHOD_GAUSSIAN {
3553 shader_defs.push("SHADOW_FILTER_METHOD_GAUSSIAN".into());
3554 } else if shadow_filter_method == MeshPipelineKey::SHADOW_FILTER_METHOD_TEMPORAL {
3555 shader_defs.push("SHADOW_FILTER_METHOD_TEMPORAL".into());
3556 }
3557
3558 let blur_quality =
3559 key.intersection(MeshPipelineKey::SCREEN_SPACE_SPECULAR_TRANSMISSION_RESERVED_BITS);
3560
3561 shader_defs.push(ShaderDefVal::Int(
3562 "SCREEN_SPACE_SPECULAR_TRANSMISSION_BLUR_TAPS".into(),
3563 match blur_quality {
3564 MeshPipelineKey::SCREEN_SPACE_SPECULAR_TRANSMISSION_LOW => 4,
3565 MeshPipelineKey::SCREEN_SPACE_SPECULAR_TRANSMISSION_MEDIUM => 8,
3566 MeshPipelineKey::SCREEN_SPACE_SPECULAR_TRANSMISSION_HIGH => 16,
3567 MeshPipelineKey::SCREEN_SPACE_SPECULAR_TRANSMISSION_ULTRA => 32,
3568 _ => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(), },
3570 ));
3571
3572 if key.contains(MeshPipelineKey::VISIBILITY_RANGE_DITHER) {
3573 shader_defs.push("VISIBILITY_RANGE_DITHER".into());
3574 }
3575
3576 if key.contains(MeshPipelineKey::DISTANCE_FOG) {
3577 shader_defs.push("DISTANCE_FOG".into());
3578 }
3579
3580 if key.contains(MeshPipelineKey::ATMOSPHERE) {
3581 shader_defs.push("ATMOSPHERE".into());
3582 }
3583
3584 if self.binding_arrays_are_usable {
3585 shader_defs.push("MULTIPLE_LIGHT_PROBES_IN_ARRAY".into());
3586 shader_defs.push("MULTIPLE_LIGHTMAPS_IN_ARRAY".into());
3587 }
3588
3589 if IRRADIANCE_VOLUMES_ARE_USABLE {
3590 shader_defs.push("IRRADIANCE_VOLUMES_ARE_USABLE".into());
3591 }
3592
3593 if self.clustered_decals_are_usable {
3594 shader_defs.push("CLUSTERED_DECALS_ARE_USABLE".into());
3595 if truecfg!(feature = "pbr_light_textures") {
3596 shader_defs.push("LIGHT_TEXTURES".into());
3597 }
3598 }
3599
3600 let format = key.target_format();
3601
3602 if let Some(per_object_buffer_batch_size) = self.per_object_buffer_batch_size {
3606 shader_defs.push(ShaderDefVal::UInt(
3607 "PER_OBJECT_BUFFER_BATCH_SIZE".into(),
3608 per_object_buffer_batch_size,
3609 ));
3610 }
3611
3612 Ok(RenderPipelineDescriptor {
3613 vertex: VertexState {
3614 shader: self.shader.clone(),
3615 shader_defs: shader_defs.clone(),
3616 buffers: ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[vertex_buffer_layout]))vec![vertex_buffer_layout],
3617 ..default()
3618 },
3619 fragment: Some(FragmentState {
3620 shader: self.shader.clone(),
3621 shader_defs,
3622 targets: ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[Some(ColorTargetState {
format,
blend,
write_mask: ColorWrites::ALL,
})]))vec![Some(ColorTargetState {
3623 format,
3624 blend,
3625 write_mask: ColorWrites::ALL,
3626 })],
3627 ..default()
3628 }),
3629 layout: bind_group_layout,
3630 primitive: PrimitiveState {
3631 cull_mode: Some(Face::Back),
3632 unclipped_depth: false,
3633 topology: key.primitive_topology(),
3634 strip_index_format: key.strip_index_format(),
3635 ..default()
3636 },
3637 depth_stencil: Some(DepthStencilState {
3638 format: CORE_3D_DEPTH_FORMAT,
3639 depth_write_enabled: Some(depth_write_enabled),
3640 depth_compare: Some(CompareFunction::GreaterEqual),
3641 stencil: StencilState {
3642 front: StencilFaceState::IGNORE,
3643 back: StencilFaceState::IGNORE,
3644 read_mask: 0,
3645 write_mask: 0,
3646 },
3647 bias: DepthBiasState {
3648 constant: 0,
3649 slope_scale: 0.0,
3650 clamp: 0.0,
3651 },
3652 }),
3653 multisample: MultisampleState {
3654 count: key.msaa_samples(),
3655 mask: !0,
3656 alpha_to_coverage_enabled,
3657 },
3658 label: Some(label),
3659 ..default()
3660 })
3661 }
3662}
3663
3664pub struct MeshPhaseBindGroups {
3669 model_only: Option<BindGroup>,
3670 skinned: Option<MeshBindGroupPair>,
3671 morph_targets: MeshMorphTargetBindGroups,
3673 lightmaps: HashMap<LightmapSlabIndex, BindGroup>,
3674}
3675
3676pub enum MeshMorphTargetBindGroups {
3682 Uniform(HashMap<AssetId<Mesh>, MeshBindGroupPair>),
3688
3689 Storage(HashMap<MeshSlabId, MeshMorphTargetStorageBindGroups>),
3692}
3693
3694pub struct MeshMorphTargetStorageBindGroups {
3700 skinned: Option<MeshBindGroupPair>,
3702 unskinned: Option<MeshBindGroupPair>,
3704}
3705
3706impl MeshMorphTargetBindGroups {
3707 fn clear(&mut self) {
3709 match *self {
3710 MeshMorphTargetBindGroups::Uniform(ref mut mesh_to_bind_group_pair) => {
3711 mesh_to_bind_group_pair.clear();
3712 }
3713 MeshMorphTargetBindGroups::Storage(ref mut slab_id_to_bind_groups) => {
3714 slab_id_to_bind_groups.clear();
3715 }
3716 }
3717 }
3718}
3719
3720pub struct MeshBindGroupPair {
3721 motion_vectors: BindGroup,
3722 no_motion_vectors: BindGroup,
3723}
3724
3725#[derive(impl bevy_ecs::resource::Resource for MeshBindGroups where
Self: ::core::marker::Send + ::core::marker::Sync + 'static {}Resource)]
3727pub enum MeshBindGroups {
3728 CpuPreprocessing(MeshPhaseBindGroups),
3731 GpuPreprocessing(TypeIdMap<MeshPhaseBindGroups>),
3734}
3735
3736impl MeshPhaseBindGroups {
3737 pub fn new(render_device: &RenderDevice) -> MeshPhaseBindGroups {
3742 MeshPhaseBindGroups {
3743 model_only: None,
3744 skinned: None,
3745 morph_targets: if skins_use_uniform_buffers(&render_device.limits()) {
3746 MeshMorphTargetBindGroups::Uniform(HashMap::default())
3747 } else {
3748 MeshMorphTargetBindGroups::Storage(HashMap::default())
3749 },
3750 lightmaps: HashMap::default(),
3751 }
3752 }
3753
3754 pub fn reset(&mut self) {
3755 self.model_only = None;
3756 self.skinned = None;
3757 self.morph_targets.clear();
3758 self.lightmaps.clear();
3759 }
3760
3761 pub fn get(
3763 &self,
3764 lightmap: Option<LightmapSlabIndex>,
3765 is_skinned: bool,
3766 morph: MeshMorphBindGroupKey,
3767 motion_vectors: bool,
3768 ) -> Option<&BindGroup> {
3769 match (is_skinned, morph, lightmap) {
3770 (_, MeshMorphBindGroupKey::Uniform(asset_id), _) => match self.morph_targets {
3771 MeshMorphTargetBindGroups::Uniform(ref morph_targets) => morph_targets
3772 .get(&asset_id)
3773 .map(|bind_group_pair| bind_group_pair.get(motion_vectors)),
3774 MeshMorphTargetBindGroups::Storage(..) => {
3775 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event src/render/mesh.rs:3775",
"bevy_pbr::render::mesh", ::tracing::Level::ERROR,
::tracing_core::__macro_support::Option::Some("src/render/mesh.rs"),
::tracing_core::__macro_support::Option::Some(3775u32),
::tracing_core::__macro_support::Option::Some("bevy_pbr::render::mesh"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::ERROR <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::ERROR <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("Tried to look up a mesh morph target bind group using a mesh ID, but we\'re using storage buffers. Look it up using the slab ID instead.")
as &dyn ::tracing::field::Value))])
});
} else { ; }
};error!(
3776 "Tried to look up a mesh morph target bind group using a mesh ID, but \
3777 we're using storage buffers. Look it up using the slab ID instead."
3778 );
3779 None
3780 }
3781 },
3782 (_, MeshMorphBindGroupKey::Storage(slab_id), _) => match &self.morph_targets {
3783 MeshMorphTargetBindGroups::Uniform(..) => {
3784 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event src/render/mesh.rs:3784",
"bevy_pbr::render::mesh", ::tracing::Level::ERROR,
::tracing_core::__macro_support::Option::Some("src/render/mesh.rs"),
::tracing_core::__macro_support::Option::Some(3784u32),
::tracing_core::__macro_support::Option::Some("bevy_pbr::render::mesh"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::ERROR <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::ERROR <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("Tried to look up a mesh morph target bind group using a slab ID, but we\'re using uniform buffers. Look it up using the mesh ID instead.")
as &dyn ::tracing::field::Value))])
});
} else { ; }
};error!(
3785 "Tried to look up a mesh morph target bind group using a slab ID, but \
3786 we're using uniform buffers. Look it up using the mesh ID instead."
3787 );
3788 None
3789 }
3790 MeshMorphTargetBindGroups::Storage(slab_to_bind_group) => {
3791 let slab_bind_group = slab_to_bind_group.get(&slab_id)?;
3792 if is_skinned {
3793 slab_bind_group
3794 .skinned
3795 .as_ref()
3796 .map(|bind_group_pair| bind_group_pair.get(motion_vectors))
3797 } else {
3798 slab_bind_group
3799 .unskinned
3800 .as_ref()
3801 .map(|bind_group_pair| bind_group_pair.get(motion_vectors))
3802 }
3803 }
3804 },
3805 (true, MeshMorphBindGroupKey::NoMorphTargets, _) => self
3806 .skinned
3807 .as_ref()
3808 .map(|bind_group_pair| bind_group_pair.get(motion_vectors)),
3809 (false, MeshMorphBindGroupKey::NoMorphTargets, Some(lightmap_slab)) => {
3810 self.lightmaps.get(&lightmap_slab)
3811 }
3812 (false, MeshMorphBindGroupKey::NoMorphTargets, None) => self.model_only.as_ref(),
3813 }
3814 }
3815}
3816
3817impl MeshBindGroupPair {
3818 fn get(&self, motion_vectors: bool) -> &BindGroup {
3819 if motion_vectors {
3820 &self.motion_vectors
3821 } else {
3822 &self.no_motion_vectors
3823 }
3824 }
3825}
3826
3827#[derive(#[automatically_derived]
impl ::core::clone::Clone for MeshMorphBindGroupKey {
#[inline]
fn clone(&self) -> MeshMorphBindGroupKey {
let _: ::core::clone::AssertParamIsClone<AssetId<Mesh>>;
let _: ::core::clone::AssertParamIsClone<MeshSlabId>;
*self
}
}Clone, #[automatically_derived]
impl ::core::marker::Copy for MeshMorphBindGroupKey { }Copy)]
3830pub enum MeshMorphBindGroupKey {
3831 NoMorphTargets,
3833 Uniform(AssetId<Mesh>),
3838 Storage(MeshSlabId),
3844}
3845
3846pub fn prepare_mesh_bind_groups(
3848 mut commands: Commands,
3849 meshes: Res<RenderAssets<RenderMesh>>,
3850 mesh_pipeline: Res<MeshPipeline>,
3851 render_device: Res<RenderDevice>,
3852 pipeline_cache: Res<PipelineCache>,
3853 cpu_batched_instance_buffer: Option<
3854 Res<no_gpu_preprocessing::BatchedInstanceBuffer<MeshUniform>>,
3855 >,
3856 gpu_batched_instance_buffers: Option<
3857 Res<gpu_preprocessing::BatchedInstanceBuffers<MeshUniform, MeshInputUniform>>,
3858 >,
3859 skins_uniform: Res<SkinUniforms>,
3860 weights_uniform: Res<MorphUniforms>,
3861 mesh_allocator: Res<MeshAllocator>,
3862 render_morph_target_allocator: Res<RenderMorphTargetAllocator>,
3863 mut render_lightmaps: ResMut<RenderLightmaps>,
3864) {
3865 if let Some(cpu_batched_instance_buffer) = cpu_batched_instance_buffer
3867 && let Some(instance_data_binding) = cpu_batched_instance_buffer
3868 .into_inner()
3869 .instance_data_binding()
3870 {
3871 let cpu_preprocessing_mesh_bind_groups = prepare_mesh_bind_groups_for_phase(
3873 instance_data_binding,
3874 &meshes,
3875 &mesh_pipeline,
3876 &render_device,
3877 &pipeline_cache,
3878 &skins_uniform,
3879 &weights_uniform,
3880 &mesh_allocator,
3881 &render_morph_target_allocator,
3882 &mut render_lightmaps,
3883 );
3884
3885 commands.insert_resource(MeshBindGroups::CpuPreprocessing(
3886 cpu_preprocessing_mesh_bind_groups,
3887 ));
3888 return;
3889 }
3890
3891 if let Some(gpu_batched_instance_buffers) = gpu_batched_instance_buffers {
3893 let mut gpu_preprocessing_mesh_bind_groups = TypeIdMap::default();
3894
3895 for (phase_type_id, batched_phase_instance_buffers) in
3897 &gpu_batched_instance_buffers.phase_instance_buffers
3898 {
3899 let Some(instance_data_binding) =
3900 batched_phase_instance_buffers.instance_data_binding()
3901 else {
3902 continue;
3903 };
3904
3905 let mesh_phase_bind_groups = prepare_mesh_bind_groups_for_phase(
3906 instance_data_binding,
3907 &meshes,
3908 &mesh_pipeline,
3909 &render_device,
3910 &pipeline_cache,
3911 &skins_uniform,
3912 &weights_uniform,
3913 &mesh_allocator,
3914 &render_morph_target_allocator,
3915 &mut render_lightmaps,
3916 );
3917
3918 gpu_preprocessing_mesh_bind_groups.insert(*phase_type_id, mesh_phase_bind_groups);
3919 }
3920
3921 commands.insert_resource(MeshBindGroups::GpuPreprocessing(
3922 gpu_preprocessing_mesh_bind_groups,
3923 ));
3924 }
3925}
3926
3927fn prepare_mesh_bind_groups_for_phase(
3929 model: BindingResource,
3930 meshes: &RenderAssets<RenderMesh>,
3931 mesh_pipeline: &MeshPipeline,
3932 render_device: &RenderDevice,
3933 pipeline_cache: &PipelineCache,
3934 skins_uniform: &SkinUniforms,
3935 weights_uniform: &MorphUniforms,
3936 mesh_allocator: &MeshAllocator,
3937 render_morph_target_allocator: &RenderMorphTargetAllocator,
3938 render_lightmaps: &mut RenderLightmaps,
3939) -> MeshPhaseBindGroups {
3940 let layouts = &mesh_pipeline.mesh_layouts;
3941
3942 let mut groups = MeshPhaseBindGroups {
3944 model_only: Some(layouts.model_only(render_device, pipeline_cache, &model)),
3945 ..MeshPhaseBindGroups::new(render_device)
3946 };
3947
3948 let (skin, prev_skin) = (&skins_uniform.current_buffer, &skins_uniform.prev_buffer);
3951 groups.skinned = Some(MeshBindGroupPair {
3952 motion_vectors: layouts.skinned_motion(
3953 render_device,
3954 pipeline_cache,
3955 &model,
3956 skin,
3957 prev_skin,
3958 ),
3959 no_motion_vectors: layouts.skinned(render_device, pipeline_cache, &model, skin),
3960 });
3961
3962 if weights_uniform.current_buffer.buffer().is_some() {
3965 match (render_morph_target_allocator, &mut groups.morph_targets) {
3966 (
3967 RenderMorphTargetAllocator::Image { mesh_id_to_image },
3968 &mut MeshMorphTargetBindGroups::Uniform(ref mut morph_targets),
3969 ) => {
3970 prepare_mesh_morph_target_bind_groups_for_phase_using_uniforms(
3971 &model,
3972 meshes,
3973 layouts,
3974 render_device,
3975 pipeline_cache,
3976 skins_uniform,
3977 weights_uniform,
3978 mesh_id_to_image,
3979 morph_targets,
3980 );
3981 }
3982
3983 (
3984 &RenderMorphTargetAllocator::Storage,
3985 &mut MeshMorphTargetBindGroups::Storage(ref mut morph_target_storage_bind_groups),
3986 ) => {
3987 prepare_mesh_morph_target_bind_groups_for_phase_using_storage(
3988 &model,
3989 layouts,
3990 render_device,
3991 pipeline_cache,
3992 skins_uniform,
3993 weights_uniform,
3994 mesh_allocator,
3995 morph_target_storage_bind_groups,
3996 );
3997 }
3998
3999 _ => {
4000 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event src/render/mesh.rs:4000",
"bevy_pbr::render::mesh", ::tracing::Level::ERROR,
::tracing_core::__macro_support::Option::Some("src/render/mesh.rs"),
::tracing_core::__macro_support::Option::Some(4000u32),
::tracing_core::__macro_support::Option::Some("bevy_pbr::render::mesh"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::ERROR <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::ERROR <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("Mismatched render morph target allocator and mesh morph target bind groups")
as &dyn ::tracing::field::Value))])
});
} else { ; }
};error!(
4001 "Mismatched render morph target allocator and mesh morph target bind groups"
4002 );
4003 }
4004 }
4005 }
4006
4007 let bindless_supported = render_lightmaps.bindless_supported;
4009 for (lightmap_slab_id, lightmap_slab) in render_lightmaps.slabs.iter_mut().enumerate() {
4010 groups.lightmaps.insert(
4011 LightmapSlabIndex(NonMaxU32::new(lightmap_slab_id as u32).unwrap()),
4012 layouts.lightmapped(
4013 render_device,
4014 pipeline_cache,
4015 &model,
4016 lightmap_slab,
4017 bindless_supported,
4018 ),
4019 );
4020 }
4021
4022 groups
4023}
4024
4025fn prepare_mesh_morph_target_bind_groups_for_phase_using_uniforms(
4030 model: &BindingResource,
4031 meshes: &RenderAssets<RenderMesh>,
4032 layouts: &MeshLayouts,
4033 render_device: &RenderDevice,
4034 pipeline_cache: &PipelineCache,
4035 skins_uniform: &SkinUniforms,
4036 weights_uniform: &MorphUniforms,
4037 mesh_id_to_image: &HashMap<AssetId<Mesh>, MorphTargetImage>,
4038 morph_targets: &mut HashMap<AssetId<Mesh>, MeshBindGroupPair>,
4039) {
4040 let (skin, prev_skin) = (&skins_uniform.current_buffer, &skins_uniform.prev_buffer);
4041 let weights = weights_uniform
4042 .current_buffer
4043 .buffer()
4044 .expect("Should have a weights buffer by now");
4045 let prev_weights = weights_uniform.prev_buffer.buffer().unwrap_or(weights);
4046 let maybe_morph_descriptors = weights_uniform
4047 .descriptors_buffer
4048 .as_ref()
4049 .and_then(|descriptors_buffer| descriptors_buffer.buffer());
4050
4051 for (id, gpu_mesh) in meshes.iter() {
4052 if !gpu_mesh.has_morph_targets() {
4053 continue;
4054 }
4055 let Some(morph_targets_image) = mesh_id_to_image.get(&id) else {
4056 continue;
4057 };
4058 let targets = MorphTargetsResource::Texture(&morph_targets_image.texture_view);
4059 let bind_group_pair = if is_skinned(&gpu_mesh.layout) {
4060 MeshBindGroupPair {
4061 motion_vectors: layouts.morphed_skinned_motion(
4062 render_device,
4063 pipeline_cache,
4064 model,
4065 skin,
4066 weights,
4067 targets,
4068 prev_skin,
4069 prev_weights,
4070 maybe_morph_descriptors,
4071 ),
4072 no_motion_vectors: layouts.morphed_skinned(
4073 render_device,
4074 pipeline_cache,
4075 model,
4076 skin,
4077 weights,
4078 targets,
4079 maybe_morph_descriptors,
4080 ),
4081 }
4082 } else {
4083 MeshBindGroupPair {
4084 motion_vectors: layouts.morphed_motion(
4085 render_device,
4086 pipeline_cache,
4087 model,
4088 weights,
4089 prev_weights,
4090 targets,
4091 maybe_morph_descriptors,
4092 ),
4093 no_motion_vectors: layouts.morphed(
4094 render_device,
4095 pipeline_cache,
4096 model,
4097 weights,
4098 targets,
4099 maybe_morph_descriptors,
4100 ),
4101 }
4102 };
4103 morph_targets.insert(id, bind_group_pair);
4104 }
4105}
4106
4107fn prepare_mesh_morph_target_bind_groups_for_phase_using_storage(
4111 model: &BindingResource,
4112 layouts: &MeshLayouts,
4113 render_device: &RenderDevice,
4114 pipeline_cache: &PipelineCache,
4115 skins_uniform: &SkinUniforms,
4116 weights_uniform: &MorphUniforms,
4117 mesh_allocator: &MeshAllocator,
4118 morph_target_storage_bind_groups: &mut HashMap<MeshSlabId, MeshMorphTargetStorageBindGroups>,
4119) {
4120 let (skin, prev_skin) = (&skins_uniform.current_buffer, &skins_uniform.prev_buffer);
4121 let weights = weights_uniform
4122 .current_buffer
4123 .buffer()
4124 .expect("Should have a weights buffer by now");
4125 let prev_weights = weights_uniform.prev_buffer.buffer().unwrap_or(weights);
4126 let maybe_morph_descriptors = weights_uniform
4127 .descriptors_buffer
4128 .as_ref()
4129 .and_then(|descriptors_buffer| descriptors_buffer.buffer());
4130
4131 for morph_target_slab_id in mesh_allocator.morph_target_slabs() {
4132 let Some(buffer) = mesh_allocator.buffer_for_slab(morph_target_slab_id) else {
4133 continue;
4134 };
4135 let targets = MorphTargetsResource::Storage(buffer);
4136 morph_target_storage_bind_groups.insert(
4137 morph_target_slab_id,
4138 MeshMorphTargetStorageBindGroups {
4139 skinned: Some(MeshBindGroupPair {
4140 motion_vectors: layouts.morphed_skinned_motion(
4141 render_device,
4142 pipeline_cache,
4143 model,
4144 skin,
4145 weights,
4146 targets,
4147 prev_skin,
4148 prev_weights,
4149 maybe_morph_descriptors,
4150 ),
4151 no_motion_vectors: layouts.morphed_skinned(
4152 render_device,
4153 pipeline_cache,
4154 model,
4155 skin,
4156 weights,
4157 targets,
4158 maybe_morph_descriptors,
4159 ),
4160 }),
4161 unskinned: Some(MeshBindGroupPair {
4162 motion_vectors: layouts.morphed_motion(
4163 render_device,
4164 pipeline_cache,
4165 model,
4166 weights,
4167 prev_weights,
4168 targets,
4169 maybe_morph_descriptors,
4170 ),
4171 no_motion_vectors: layouts.morphed(
4172 render_device,
4173 pipeline_cache,
4174 model,
4175 weights,
4176 targets,
4177 maybe_morph_descriptors,
4178 ),
4179 }),
4180 },
4181 );
4182 }
4183}
4184
4185pub struct SetMeshViewBindGroup<const I: usize>;
4186impl<P: PhaseItem, const I: usize> RenderCommand<P> for SetMeshViewBindGroup<I> {
4187 type Param = ();
4188 type ViewQuery = (Read<MeshViewBindGroup>,);
4189 type ItemQuery = ();
4190
4191 #[inline]
4192 fn render<'w>(
4193 _item: &P,
4194 (mesh_view_bind_group,): ROQueryItem<'w, '_, Self::ViewQuery>,
4195 _entity: Option<()>,
4196 _: SystemParamItem<'w, '_, Self::Param>,
4197 pass: &mut TrackedRenderPass<'w>,
4198 ) -> RenderCommandResult {
4199 pass.set_bind_group(
4200 I,
4201 &mesh_view_bind_group.main,
4202 &mesh_view_bind_group.main_offsets,
4203 );
4204
4205 RenderCommandResult::Success
4206 }
4207}
4208
4209pub struct SetMeshViewBindingArrayBindGroup<const I: usize>;
4210impl<P: PhaseItem, const I: usize> RenderCommand<P> for SetMeshViewBindingArrayBindGroup<I> {
4211 type Param = ();
4212 type ViewQuery = (Read<MeshViewBindGroup>,);
4213 type ItemQuery = ();
4214
4215 #[inline]
4216 fn render<'w>(
4217 _item: &P,
4218 (mesh_view_bind_group,): ROQueryItem<'w, '_, Self::ViewQuery>,
4219 _entity: Option<()>,
4220 _: SystemParamItem<'w, '_, Self::Param>,
4221 pass: &mut TrackedRenderPass<'w>,
4222 ) -> RenderCommandResult {
4223 pass.set_bind_group(I, &mesh_view_bind_group.binding_array, &[]);
4224
4225 RenderCommandResult::Success
4226 }
4227}
4228
4229pub struct SetMeshViewEmptyBindGroup<const I: usize>;
4230impl<P: PhaseItem, const I: usize> RenderCommand<P> for SetMeshViewEmptyBindGroup<I> {
4231 type Param = ();
4232 type ViewQuery = (Read<MeshViewBindGroup>,);
4233 type ItemQuery = ();
4234
4235 #[inline]
4236 fn render<'w>(
4237 _item: &P,
4238 (mesh_view_bind_group,): ROQueryItem<'w, '_, Self::ViewQuery>,
4239 _entity: Option<()>,
4240 _: SystemParamItem<'w, '_, Self::Param>,
4241 pass: &mut TrackedRenderPass<'w>,
4242 ) -> RenderCommandResult {
4243 pass.set_bind_group(I, &mesh_view_bind_group.empty, &[]);
4244
4245 RenderCommandResult::Success
4246 }
4247}
4248
4249pub struct SetMeshBindGroup<const I: usize>;
4250impl<P: PhaseItem, const I: usize> RenderCommand<P> for SetMeshBindGroup<I> {
4251 type Param = (
4252 SRes<RenderDevice>,
4253 SRes<MeshBindGroups>,
4254 SRes<RenderMeshInstances>,
4255 SRes<SkinUniforms>,
4256 SRes<MorphIndices>,
4257 SRes<MeshAllocator>,
4258 SRes<RenderLightmaps>,
4259 );
4260 type ViewQuery = Has<MotionVectorPrepass>;
4261 type ItemQuery = ();
4262
4263 #[inline]
4264 fn render<'w>(
4265 item: &P,
4266 has_motion_vector_prepass: bool,
4267 _item_query: Option<()>,
4268 (
4269 render_device,
4270 bind_groups,
4271 mesh_instances,
4272 skin_uniforms,
4273 morph_indices,
4274 mesh_allocator,
4275 lightmaps,
4276 ): SystemParamItem<'w, '_, Self::Param>,
4277 pass: &mut TrackedRenderPass<'w>,
4278 ) -> RenderCommandResult {
4279 let bind_groups = bind_groups.into_inner();
4280 let mesh_instances = mesh_instances.into_inner();
4281 let skin_uniforms = skin_uniforms.into_inner();
4282 let morph_indices = morph_indices.into_inner();
4283
4284 let entity = &item.main_entity();
4285
4286 let Some(mesh_asset_id) = mesh_instances.mesh_asset_id(*entity) else {
4287 return RenderCommandResult::Success;
4288 };
4289
4290 let skins_use_uniform_buffers = skins_use_uniform_buffers(&render_device.limits());
4291
4292 let current_skin_byte_offset = skin_uniforms.skin_byte_offset(*entity);
4293
4294 let (current_morph_index, prev_morph_index, morph_bind_group_key);
4300 match *morph_indices {
4301 MorphIndices::Uniform {
4302 ref current,
4303 ref prev,
4304 } => {
4305 current_morph_index = current.get(entity);
4306 prev_morph_index = prev.get(entity);
4307 morph_bind_group_key = if current_morph_index.is_some() {
4308 MeshMorphBindGroupKey::Uniform(mesh_asset_id)
4309 } else {
4310 MeshMorphBindGroupKey::NoMorphTargets
4311 };
4312 }
4313 MorphIndices::Storage { .. } => {
4314 current_morph_index = None;
4315 prev_morph_index = None;
4316 morph_bind_group_key = match mesh_allocator
4317 .mesh_slabs(&mesh_asset_id)
4318 .and_then(|mesh_slabs| mesh_slabs.morph_target_slab_id)
4319 {
4320 Some(morph_target_slab_id) => {
4321 MeshMorphBindGroupKey::Storage(morph_target_slab_id)
4322 }
4323 None => MeshMorphBindGroupKey::NoMorphTargets,
4324 };
4325 }
4326 };
4327
4328 let is_skinned = current_skin_byte_offset.is_some();
4329
4330 let lightmap_slab_index = lightmaps
4331 .render_lightmaps
4332 .get(entity)
4333 .map(|render_lightmap| render_lightmap.slab_index);
4334
4335 let Some(mesh_phase_bind_groups) = (match *bind_groups {
4336 MeshBindGroups::CpuPreprocessing(ref mesh_phase_bind_groups) => {
4337 Some(mesh_phase_bind_groups)
4338 }
4339 MeshBindGroups::GpuPreprocessing(ref mesh_phase_bind_groups) => {
4340 mesh_phase_bind_groups.get(&TypeId::of::<P>())
4341 }
4342 }) else {
4343 return RenderCommandResult::Success;
4346 };
4347
4348 let Some(bind_group) = mesh_phase_bind_groups.get(
4349 lightmap_slab_index,
4350 is_skinned,
4351 morph_bind_group_key,
4352 has_motion_vector_prepass,
4353 ) else {
4354 return RenderCommandResult::Failure(
4355 "The MeshBindGroups resource wasn't set in the render phase. \
4356 It should be set by the prepare_mesh_bind_group system.\n\
4357 This is a bevy bug! Please open an issue.",
4358 );
4359 };
4360
4361 let mut dynamic_offsets: [u32; 5] = Default::default();
4362 let mut offset_count = 0;
4363 if let PhaseItemExtraIndex::DynamicOffset(dynamic_offset) = item.extra_index() {
4364 dynamic_offsets[offset_count] = dynamic_offset;
4365 offset_count += 1;
4366 }
4367 if skins_use_uniform_buffers {
4368 if let Some(current_skin_index) = current_skin_byte_offset {
4369 dynamic_offsets[offset_count] = current_skin_index.byte_offset;
4370 offset_count += 1;
4371 }
4372 if let Some(current_morph_index) = current_morph_index {
4373 dynamic_offsets[offset_count] = current_morph_index.index;
4374 offset_count += 1;
4375 }
4376 }
4377
4378 if skins_use_uniform_buffers && has_motion_vector_prepass {
4380 if let Some(current_skin_byte_offset) = current_skin_byte_offset {
4382 dynamic_offsets[offset_count] = current_skin_byte_offset.byte_offset;
4383 offset_count += 1;
4384 }
4385
4386 if current_morph_index.is_some() {
4389 match prev_morph_index {
4390 Some(prev_morph_index) => {
4391 dynamic_offsets[offset_count] = prev_morph_index.index;
4392 }
4393 None => dynamic_offsets[offset_count] = 0,
4394 }
4395 offset_count += 1;
4396 }
4397 }
4398
4399 pass.set_bind_group(I, bind_group, &dynamic_offsets[0..offset_count]);
4400
4401 RenderCommandResult::Success
4402 }
4403}
4404
4405pub struct DrawMesh;
4406impl<P: PhaseItem> RenderCommand<P> for DrawMesh {
4407 type Param = (
4408 SRes<RenderAssets<RenderMesh>>,
4409 SRes<RenderMeshInstances>,
4410 SRes<IndirectParametersBuffers>,
4411 SRes<PipelineCache>,
4412 SRes<MeshAllocator>,
4413 Option<SRes<PreprocessPipelines>>,
4414 SRes<GpuPreprocessingSupport>,
4415 );
4416 type ViewQuery = Has<PreprocessBindGroups>;
4417 type ItemQuery = ();
4418 #[inline]
4419 fn render<'w>(
4420 item: &P,
4421 has_preprocess_bind_group: ROQueryItem<Self::ViewQuery>,
4422 _item_query: Option<()>,
4423 (
4424 meshes,
4425 mesh_instances,
4426 indirect_parameters_buffer,
4427 pipeline_cache,
4428 mesh_allocator,
4429 preprocess_pipelines,
4430 preprocessing_support,
4431 ): SystemParamItem<'w, '_, Self::Param>,
4432 pass: &mut TrackedRenderPass<'w>,
4433 ) -> RenderCommandResult {
4434 if let Some(preprocess_pipelines) = preprocess_pipelines
4438 && (!has_preprocess_bind_group
4439 || !preprocess_pipelines
4440 .pipelines_are_loaded(&pipeline_cache, &preprocessing_support))
4441 {
4442 return RenderCommandResult::Skip;
4443 }
4444
4445 let meshes = meshes.into_inner();
4446 let mesh_instances = mesh_instances.into_inner();
4447 let indirect_parameters_buffer = indirect_parameters_buffer.into_inner();
4448 let mesh_allocator = mesh_allocator.into_inner();
4449
4450 let Some(mesh_asset_id) = mesh_instances.mesh_asset_id(item.main_entity()) else {
4451 return RenderCommandResult::Skip;
4452 };
4453 let Some(gpu_mesh) = meshes.get(mesh_asset_id) else {
4454 return RenderCommandResult::Skip;
4455 };
4456 let Some(vertex_buffer_slice) = mesh_allocator.mesh_vertex_slice(&mesh_asset_id) else {
4457 return RenderCommandResult::Skip;
4458 };
4459
4460 pass.set_vertex_buffer(0, vertex_buffer_slice.buffer.slice(..));
4461
4462 let batch_range = item.batch_range();
4463
4464 match &gpu_mesh.buffer_info {
4468 RenderMeshBufferInfo::Indexed {
4469 index_format,
4470 count,
4471 } => {
4472 let Some(index_buffer_slice) = mesh_allocator.mesh_index_slice(&mesh_asset_id)
4473 else {
4474 return RenderCommandResult::Skip;
4475 };
4476
4477 pass.set_index_buffer(index_buffer_slice.buffer.slice(..), *index_format);
4478
4479 match item.extra_index() {
4480 PhaseItemExtraIndex::None | PhaseItemExtraIndex::DynamicOffset(_) => {
4481 pass.draw_indexed(
4482 index_buffer_slice.range.start
4483 ..(index_buffer_slice.range.start + *count),
4484 vertex_buffer_slice.range.start as i32,
4485 batch_range.clone(),
4486 );
4487 }
4488 PhaseItemExtraIndex::IndirectParametersIndex {
4489 range: indirect_parameters_range,
4490 batch_set_index,
4491 } => {
4492 let Some(phase_indirect_parameters_buffers) =
4496 indirect_parameters_buffer.get(&TypeId::of::<P>())
4497 else {
4498 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event src/render/mesh.rs:4498",
"bevy_pbr::render::mesh", ::tracing::Level::WARN,
::tracing_core::__macro_support::Option::Some("src/render/mesh.rs"),
::tracing_core::__macro_support::Option::Some(4498u32),
::tracing_core::__macro_support::Option::Some("bevy_pbr::render::mesh"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::WARN <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::WARN <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("Not rendering mesh because indexed indirect parameters buffer wasn\'t present for this phase")
as &dyn ::tracing::field::Value))])
});
} else { ; }
};warn!(
4499 "Not rendering mesh because indexed indirect parameters buffer \
4500 wasn't present for this phase",
4501 );
4502 return RenderCommandResult::Skip;
4503 };
4504 let (Some(indirect_parameters_buffer), Some(batch_sets_buffer)) = (
4505 phase_indirect_parameters_buffers.indexed.data_buffer(),
4506 phase_indirect_parameters_buffers
4507 .indexed
4508 .batch_sets_buffer(),
4509 ) else {
4510 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event src/render/mesh.rs:4510",
"bevy_pbr::render::mesh", ::tracing::Level::WARN,
::tracing_core::__macro_support::Option::Some("src/render/mesh.rs"),
::tracing_core::__macro_support::Option::Some(4510u32),
::tracing_core::__macro_support::Option::Some("bevy_pbr::render::mesh"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::WARN <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::WARN <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("Not rendering mesh because indexed indirect parameters buffer wasn\'t present")
as &dyn ::tracing::field::Value))])
});
} else { ; }
};warn!(
4511 "Not rendering mesh because indexed indirect parameters buffer \
4512 wasn't present",
4513 );
4514 return RenderCommandResult::Skip;
4515 };
4516
4517 let indirect_parameters_offset = indirect_parameters_range.start as u64
4520 * size_of::<IndirectParametersIndexed>() as u64;
4521 let indirect_parameters_count =
4522 indirect_parameters_range.end - indirect_parameters_range.start;
4523
4524 match batch_set_index {
4529 Some(batch_set_index) => {
4530 let count_offset = u32::from(batch_set_index)
4531 * (size_of::<IndirectBatchSet>() as u32);
4532 pass.multi_draw_indexed_indirect_count(
4533 indirect_parameters_buffer,
4534 indirect_parameters_offset,
4535 batch_sets_buffer,
4536 count_offset as u64,
4537 indirect_parameters_count,
4538 );
4539 }
4540 None => {
4541 pass.multi_draw_indexed_indirect(
4542 indirect_parameters_buffer,
4543 indirect_parameters_offset,
4544 indirect_parameters_count,
4545 );
4546 }
4547 }
4548 }
4549 }
4550 }
4551
4552 RenderMeshBufferInfo::NonIndexed => match item.extra_index() {
4553 PhaseItemExtraIndex::None | PhaseItemExtraIndex::DynamicOffset(_) => {
4554 pass.draw(vertex_buffer_slice.range, batch_range.clone());
4555 }
4556 PhaseItemExtraIndex::IndirectParametersIndex {
4557 range: indirect_parameters_range,
4558 batch_set_index,
4559 } => {
4560 let Some(phase_indirect_parameters_buffers) =
4564 indirect_parameters_buffer.get(&TypeId::of::<P>())
4565 else {
4566 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event src/render/mesh.rs:4566",
"bevy_pbr::render::mesh", ::tracing::Level::WARN,
::tracing_core::__macro_support::Option::Some("src/render/mesh.rs"),
::tracing_core::__macro_support::Option::Some(4566u32),
::tracing_core::__macro_support::Option::Some("bevy_pbr::render::mesh"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::WARN <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::WARN <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("Not rendering mesh because non-indexed indirect parameters buffer wasn\'t present for this phase")
as &dyn ::tracing::field::Value))])
});
} else { ; }
};warn!(
4567 "Not rendering mesh because non-indexed indirect parameters buffer \
4568 wasn't present for this phase",
4569 );
4570 return RenderCommandResult::Skip;
4571 };
4572 let (Some(indirect_parameters_buffer), Some(batch_sets_buffer)) = (
4573 phase_indirect_parameters_buffers.non_indexed.data_buffer(),
4574 phase_indirect_parameters_buffers
4575 .non_indexed
4576 .batch_sets_buffer(),
4577 ) else {
4578 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event src/render/mesh.rs:4578",
"bevy_pbr::render::mesh", ::tracing::Level::WARN,
::tracing_core::__macro_support::Option::Some("src/render/mesh.rs"),
::tracing_core::__macro_support::Option::Some(4578u32),
::tracing_core::__macro_support::Option::Some("bevy_pbr::render::mesh"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::WARN <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::WARN <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("Not rendering mesh because non-indexed indirect parameters buffer wasn\'t present")
as &dyn ::tracing::field::Value))])
});
} else { ; }
};warn!(
4579 "Not rendering mesh because non-indexed indirect parameters buffer \
4580 wasn't present"
4581 );
4582 return RenderCommandResult::Skip;
4583 };
4584
4585 let indirect_parameters_offset = indirect_parameters_range.start as u64
4588 * size_of::<IndirectParametersNonIndexed>() as u64;
4589 let indirect_parameters_count =
4590 indirect_parameters_range.end - indirect_parameters_range.start;
4591
4592 match batch_set_index {
4597 Some(batch_set_index) => {
4598 let count_offset =
4599 u32::from(batch_set_index) * (size_of::<IndirectBatchSet>() as u32);
4600 pass.multi_draw_indirect_count(
4601 indirect_parameters_buffer,
4602 indirect_parameters_offset,
4603 batch_sets_buffer,
4604 count_offset as u64,
4605 indirect_parameters_count,
4606 );
4607 }
4608 None => {
4609 pass.multi_draw_indirect(
4610 indirect_parameters_buffer,
4611 indirect_parameters_offset,
4612 indirect_parameters_count,
4613 );
4614 }
4615 }
4616 }
4617 },
4618 }
4619 RenderCommandResult::Success
4620 }
4621}
4622
4623#[cfg(test)]
4624mod tests {
4625 use core::sync::atomic::{AtomicU64, Ordering};
4626
4627 use super::{AtomicU64ZeroBitIter, MeshPipelineKey};
4628
4629 #[test]
4630 fn mesh_key_msaa_samples() {
4631 for i in [1, 2, 4, 8, 16, 32, 64, 128] {
4632 assert_eq!(MeshPipelineKey::from_msaa_samples(i).msaa_samples(), i);
4633 }
4634 }
4635
4636 #[test]
4638 fn atomic_u64_zero_bit_iter() {
4639 static TEST_DATA_0: [AtomicU64; 1] = [AtomicU64::new(0x7b52f5ca63498b6a)];
4643 static TEST_DATA_1: [AtomicU64; 2] = [
4644 AtomicU64::new(0x5705b33451b95827),
4645 AtomicU64::new(0x1939ee614074abad),
4646 ];
4647 static TEST_DATA_2: [AtomicU64; 3] = [
4648 AtomicU64::new(0xf33c508d14d145c),
4649 AtomicU64::new(0x2a4749823594ea),
4650 AtomicU64::new(0x5e68df04196a3818),
4651 ];
4652 static TEST_DATA_3: [AtomicU64; 6] = [
4653 AtomicU64::new(0x2336dbda2bd74d09),
4654 AtomicU64::new(0x10b7da1dacf22d33),
4655 AtomicU64::new(0x6eaaf908d957923a),
4656 AtomicU64::new(0x7ec7ffb64cb9c4a6),
4657 AtomicU64::new(0x6dd027da8ad22fa0),
4658 AtomicU64::new(0x13278c5caa74f73d),
4659 ];
4660 static TEST_DATA_4: [AtomicU64; 4] = [
4661 AtomicU64::new(0x32c66f0334bb09e9),
4662 AtomicU64::new(0x60815770d307bdcd),
4663 AtomicU64::new(0x6270a1e972fb8469),
4664 AtomicU64::new(0x610e995c042d6df4),
4665 ];
4666 static TEST_DATA_5: [AtomicU64; 3] = [
4667 AtomicU64::new(0x7fe756fc690097eb),
4668 AtomicU64::new(0x15d87ce6679b1bd8),
4669 AtomicU64::new(0x1985ea515135b255),
4670 ];
4671 static TEST_DATA_6: [AtomicU64; 4] = [
4672 AtomicU64::new(0x1afb9d361c135827),
4673 AtomicU64::new(0x4a79ad582628a854),
4674 AtomicU64::new(0x57a802160315c974),
4675 AtomicU64::new(0x1c0aef068db1f6fb),
4676 ];
4677 static TEST_DATA_7: [AtomicU64; 3] = [
4678 AtomicU64::new(0x53d10eb77230c696),
4679 AtomicU64::new(0x2ca2d709994855fb),
4680 AtomicU64::new(0x26536a13f647f2f7),
4681 ];
4682 static TEST_DATA_8: [AtomicU64; 2] = [
4683 AtomicU64::new(0x6ed95eb903155e00),
4684 AtomicU64::new(0x5e5d58eec92cba0),
4685 ];
4686 static TEST_DATA_9: [AtomicU64; 1] = [AtomicU64::new(0x2caa4b77512b1664)];
4687
4688 let test_data = [
4689 &TEST_DATA_0[..],
4690 &TEST_DATA_1[..],
4691 &TEST_DATA_2[..],
4692 &TEST_DATA_3[..],
4693 &TEST_DATA_4[..],
4694 &TEST_DATA_5[..],
4695 &TEST_DATA_6[..],
4696 &TEST_DATA_7[..],
4697 &TEST_DATA_8[..],
4698 &TEST_DATA_9[..],
4699 ];
4700
4701 for bits in &test_data {
4702 let mut reference_zero_positions = vec![];
4704 for (word_index, word) in (*bits).iter().enumerate() {
4705 let word = word.load(Ordering::Relaxed);
4706 for bit_index in 0..64 {
4707 if ((word >> bit_index) & 1) == 0 {
4708 reference_zero_positions.push((word_index * 64 + bit_index) as u32);
4709 }
4710 }
4711 }
4712
4713 let test_zero_positions: Vec<_> = AtomicU64ZeroBitIter::new(bits).collect();
4715
4716 assert_eq!(test_zero_positions, reference_zero_positions);
4718 }
4719 }
4720}