Skip to main content

bevy_pbr/render/
mesh.rs

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
112/// Provides support for rendering 3D meshes.
113pub struct MeshRenderPlugin {
114    /// Whether we're building [`MeshUniform`]s on GPU.
115    ///
116    /// This requires compute shader support and so will be forcibly disabled if
117    /// the platform doesn't support those.
118    pub use_gpu_instance_buffer_builder: bool,
119    /// Debugging flags that can optionally be set when constructing the renderer.
120    pub debug_flags: RenderDebugFlags,
121}
122
123impl MeshRenderPlugin {
124    /// Creates a new [`MeshRenderPlugin`] with the given debug flags.
125    pub fn new(debug_flags: RenderDebugFlags) -> MeshRenderPlugin {
126        MeshRenderPlugin {
127            use_gpu_instance_buffer_builder: false,
128            debug_flags,
129        }
130    }
131}
132
133/// How many textures are allowed in the view bind group layout (`@group(0)`) before
134/// broader compatibility with WebGL and WebGPU is at risk, due to the minimum guaranteed
135/// values for `MAX_TEXTURE_IMAGE_UNITS` (in WebGL) and `maxSampledTexturesPerShaderStage` (in WebGPU),
136/// currently both at 16.
137///
138/// We use 10 here because it still leaves us, in a worst case scenario, with 6 textures for the other bind groups.
139///
140/// See: <https://gpuweb.github.io/gpuweb/#limits>
141#[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                                // This must be before
282                                // `set_mesh_motion_vector_flags` so it doesn't
283                                // overwrite those flags.
284                                .before(set_mesh_motion_vector_flags)
285                                // This must be after
286                                // `prepare_morph_descriptors` because it needs
287                                // the indices of the morph descriptors in the
288                                // buffer.
289                                .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        // Load the mesh_bindings shader module here as it depends on runtime information about
328        // whether storage buffers are supported, or the maximum uniform buffer binding size.
329        {
    {
        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
336/// Drains all entities from [`RenderMeshInstances`] into [`MeshesToReextractNextFrame`].
337fn 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/// This resource caches [`MeshPipelineKey`]s for each view with pre-enabled features needed to properly
354/// setup the [`MeshViewBindGroup`] layout in specialized [`MeshPipeline`]s.
355#[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    // Affine 4x3 matrices transposed to 3x4
517    pub world_from_local: [Vec4; 3],
518    pub previous_world_from_local: [Vec4; 3],
519    // 3x3 matrix packed in mat2x4 and f32 as:
520    //   [0].xyz, [1].x,
521    //   [1].yz, [2].xy
522    //   [2].z
523    pub local_from_world_transpose_a: [Vec4; 2],
524    pub local_from_world_transpose_b: f32,
525    pub flags: u32,
526    // Four 16-bit unsigned normalized UV values packed into a `UVec2`:
527    //
528    //                         <--- MSB                   LSB --->
529    //                         +---- min v ----+ +---- min u ----+
530    //     lightmap_uv_rect.x: vvvvvvvv vvvvvvvv uuuuuuuu uuuuuuuu,
531    //                         +---- max v ----+ +---- max u ----+
532    //     lightmap_uv_rect.y: VVVVVVVV VVVVVVVV UUUUUUUU UUUUUUUU,
533    //
534    // (MSB: most significant bit; LSB: least significant bit.)
535    pub lightmap_uv_rect: UVec2,
536    /// The index of this mesh's first vertex in the vertex buffer.
537    ///
538    /// Multiple meshes can be packed into a single vertex buffer (see
539    /// [`MeshAllocator`]). This value stores the offset of the first vertex in
540    /// this mesh in that buffer.
541    pub first_vertex_index: u32,
542    /// The current skin index, or `u32::MAX` if there's no skin.
543    pub current_skin_index: u32,
544    /// The material and lightmap indices, packed into 32 bits.
545    ///
546    /// Low 16 bits: index of the material inside the bind group data.
547    /// High 16 bits: index of the lightmap in the binding array.
548    pub material_and_lightmap_bind_group_slot: u32,
549    /// User supplied tag to identify this mesh instance.
550    pub tag: u32,
551    /// The index of the morph descriptor for this mesh instance in the
552    /// `morph_descriptors` table.
553    ///
554    /// If the mesh has no morph targets, this is `u32::MAX`.
555    pub morph_descriptor_index: u32,
556}
557
558/// Information that has to be transferred from CPU to GPU in order to produce
559/// the full [`MeshUniform`].
560///
561/// This is essentially a subset of the fields in [`MeshUniform`] above.
562#[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    /// Affine 4x3 matrix transposed to 3x4.
566    pub world_from_local: [Vec4; 3],
567    /// Four 16-bit unsigned normalized UV values packed into a `UVec2`:
568    ///
569    /// ```text
570    ///                         <--- MSB                   LSB --->
571    ///                         +---- min v ----+ +---- min u ----+
572    ///     lightmap_uv_rect.x: vvvvvvvv vvvvvvvv uuuuuuuu uuuuuuuu,
573    ///                         +---- max v ----+ +---- max u ----+
574    ///     lightmap_uv_rect.y: VVVVVVVV VVVVVVVV UUUUUUUU UUUUUUUU,
575    ///
576    /// (MSB: most significant bit; LSB: least significant bit.)
577    /// ```
578    pub lightmap_uv_rect: UVec2,
579    /// Various [`MeshFlags`].
580    pub flags: u32,
581    /// The index of this mesh's [`MeshInputUniform`] in the previous frame's
582    /// buffer, if applicable.
583    ///
584    /// This is used for TAA. If not present, this will be `u32::MAX`.
585    pub previous_input_index: u32,
586    /// The index of this mesh's first vertex in the vertex buffer.
587    ///
588    /// Multiple meshes can be packed into a single vertex buffer (see
589    /// [`MeshAllocator`]). This value stores the offset of the first vertex in
590    /// this mesh in that buffer.
591    pub first_vertex_index: u32,
592    /// The index of this mesh's first index in the index buffer, if any.
593    ///
594    /// Multiple meshes can be packed into a single index buffer (see
595    /// [`MeshAllocator`]). This value stores the offset of the first index in
596    /// this mesh in that buffer.
597    ///
598    /// If this mesh isn't indexed, this value is ignored.
599    pub first_index_index: u32,
600    /// For an indexed mesh, the number of indices that make it up; for a
601    /// non-indexed mesh, the number of vertices in it.
602    pub index_count: u32,
603    /// The current skin index, or `u32::MAX` if there's no skin.
604    pub current_skin_index: u32,
605    /// The material and lightmap indices, packed into 32 bits.
606    ///
607    /// Low 16 bits: index of the material inside the bind group data.
608    /// High 16 bits: index of the lightmap in the binding array.
609    pub material_and_lightmap_bind_group_slot: u32,
610    /// The number of the frame on which this [`MeshInputUniform`] was built.
611    ///
612    /// This is used to validate the previous transform and skin. If this
613    /// [`MeshInputUniform`] wasn't updated on this frame, then we know that
614    /// neither this mesh's transform nor that of its joints have been updated
615    /// on this frame, and therefore the transforms of both this mesh and its
616    /// joints must be identical to those for the previous frame.
617    pub timestamp: u32,
618    /// User supplied tag to identify this mesh instance.
619    pub tag: u32,
620    /// The index of the morph descriptor for this mesh instance in the
621    /// `morph_descriptors` table.
622    ///
623    /// If the mesh has no morph targets, this is `u32::MAX`.
624    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/// Information about each mesh instance needed to cull it on GPU.
630///
631/// This consists of its axis-aligned bounding box (AABB).
632#[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    /// The 3D center of the AABB in model space, padded with an extra unused
636    /// float value.
637    pub aabb_center: Vec4,
638    /// The 3D extents of the AABB in model space, divided by two, padded with
639    /// an extra unused float value.
640    pub aabb_half_extents: Vec4,
641}
642
643/// A GPU buffer that holds the information needed to cull meshes on GPU.
644///
645/// At the moment, this simply holds each mesh's AABB.
646///
647/// To avoid wasting CPU time in the CPU culling case, this buffer will be empty
648/// if GPU culling isn't in use.
649#[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// NOTE: These must match the bit flags in bevy_pbr/src/render/mesh_types.wgsl!
699#[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 {
            /// Get a flags value with all bits unset.
            #[inline]
            pub const fn empty() -> Self {
                Self(<u32 as ::bitflags::Bits>::EMPTY)
            }
            /// Get a flags value with all known bits set.
            #[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)
            }
            /// Get the underlying bits value.
            ///
            /// The returned value is exactly the bits set in this flags value.
            #[inline]
            pub const fn bits(&self) -> u32 { self.0 }
            /// Convert from a bits value.
            ///
            /// This method will return `None` if any unknown bits are set.
            #[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 }
            }
            /// Convert from a bits value, unsetting any unknown bits.
            #[inline]
            pub const fn from_bits_truncate(bits: u32) -> Self {
                Self(bits & Self::all().0)
            }
            /// Convert from a bits value exactly.
            #[inline]
            pub const fn from_bits_retain(bits: u32) -> Self { Self(bits) }
            /// Get a flags value with the bits of a flag with the given name set.
            ///
            /// This method will return `None` if `name` is empty or doesn't
            /// correspond to any named flag.
            #[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
            }
            /// Whether all bits in `self` are unset.
            #[inline]
            pub const fn is_empty(&self) -> bool {
                self.0 == <u32 as ::bitflags::Bits>::EMPTY
            }
            /// Whether all known bits in this flags value are set.
            #[inline]
            pub const fn is_all(&self) -> bool {
                Self::all().0 | self.0 == self.0
            }
            /// Whether any set bits in `other` are also set in `self`.
            #[inline]
            pub const fn intersects(&self, other: Self) -> bool {
                self.0 & other.0 != <u32 as ::bitflags::Bits>::EMPTY
            }
            /// Whether all set bits in `other` are also set in `self`.
            #[inline]
            pub const fn contains(&self, other: Self) -> bool {
                self.0 & other.0 == other.0
            }
            /// The bitwise or (`|`) of the bits in `self` and `other`.
            #[inline]
            pub fn insert(&mut self, other: Self) {
                *self = Self(self.0).union(other);
            }
            /// The intersection of `self` with the complement of `other` (`&!`).
            ///
            /// This method is not equivalent to `self & !other` when `other` has unknown bits set.
            /// `remove` won't truncate `other`, but the `!` operator will.
            #[inline]
            pub fn remove(&mut self, other: Self) {
                *self = Self(self.0).difference(other);
            }
            /// The bitwise exclusive-or (`^`) of the bits in `self` and `other`.
            #[inline]
            pub fn toggle(&mut self, other: Self) {
                *self = Self(self.0).symmetric_difference(other);
            }
            /// Call `insert` when `value` is `true` or `remove` when `value` is `false`.
            #[inline]
            pub fn set(&mut self, other: Self, value: bool) {
                if value { self.insert(other); } else { self.remove(other); }
            }
            /// The bitwise and (`&`) of the bits in `self` and `other`.
            #[inline]
            #[must_use]
            pub const fn intersection(self, other: Self) -> Self {
                Self(self.0 & other.0)
            }
            /// The bitwise or (`|`) of the bits in `self` and `other`.
            #[inline]
            #[must_use]
            pub const fn union(self, other: Self) -> Self {
                Self(self.0 | other.0)
            }
            /// The intersection of `self` with the complement of `other` (`&!`).
            ///
            /// This method is not equivalent to `self & !other` when `other` has unknown bits set.
            /// `difference` won't truncate `other`, but the `!` operator will.
            #[inline]
            #[must_use]
            pub const fn difference(self, other: Self) -> Self {
                Self(self.0 & !other.0)
            }
            /// The bitwise exclusive-or (`^`) of the bits in `self` and `other`.
            #[inline]
            #[must_use]
            pub const fn symmetric_difference(self, other: Self) -> Self {
                Self(self.0 ^ other.0)
            }
            /// The bitwise negation (`!`) of the bits in `self`, truncating the result.
            #[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;
            /// The bitwise or (`|`) of the bits in `self` and `other`.
            #[inline]
            fn bitor(self, other: InternalBitFlags) -> Self {
                self.union(other)
            }
        }
        impl ::bitflags::__private::core::ops::BitOrAssign for
            InternalBitFlags {
            /// The bitwise or (`|`) of the bits in `self` and `other`.
            #[inline]
            fn bitor_assign(&mut self, other: Self) { self.insert(other); }
        }
        impl ::bitflags::__private::core::ops::BitXor for InternalBitFlags {
            type Output = Self;
            /// The bitwise exclusive-or (`^`) of the bits in `self` and `other`.
            #[inline]
            fn bitxor(self, other: Self) -> Self {
                self.symmetric_difference(other)
            }
        }
        impl ::bitflags::__private::core::ops::BitXorAssign for
            InternalBitFlags {
            /// The bitwise exclusive-or (`^`) of the bits in `self` and `other`.
            #[inline]
            fn bitxor_assign(&mut self, other: Self) { self.toggle(other); }
        }
        impl ::bitflags::__private::core::ops::BitAnd for InternalBitFlags {
            type Output = Self;
            /// The bitwise and (`&`) of the bits in `self` and `other`.
            #[inline]
            fn bitand(self, other: Self) -> Self { self.intersection(other) }
        }
        impl ::bitflags::__private::core::ops::BitAndAssign for
            InternalBitFlags {
            /// The bitwise and (`&`) of the bits in `self` and `other`.
            #[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;
            /// The intersection of `self` with the complement of `other` (`&!`).
            ///
            /// This method is not equivalent to `self & !other` when `other` has unknown bits set.
            /// `difference` won't truncate `other`, but the `!` operator will.
            #[inline]
            fn sub(self, other: Self) -> Self { self.difference(other) }
        }
        impl ::bitflags::__private::core::ops::SubAssign for InternalBitFlags
            {
            /// The intersection of `self` with the complement of `other` (`&!`).
            ///
            /// This method is not equivalent to `self & !other` when `other` has unknown bits set.
            /// `difference` won't truncate `other`, but the `!` operator will.
            #[inline]
            fn sub_assign(&mut self, other: Self) { self.remove(other); }
        }
        impl ::bitflags::__private::core::ops::Not for InternalBitFlags {
            type Output = Self;
            /// The bitwise negation (`!`) of the bits in `self`, truncating the result.
            #[inline]
            fn not(self) -> Self { self.complement() }
        }
        impl ::bitflags::__private::core::iter::Extend<InternalBitFlags> for
            InternalBitFlags {
            /// The bitwise or (`|`) of the bits in each flags value.
            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 {
            /// The bitwise or (`|`) of the bits in each flags value.
            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 {
            /// Yield a set of contained flags values.
            ///
            /// Each yielded flags value will correspond to a defined named flag. Any unknown bits
            /// will be yielded together as a final flags value.
            #[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()))
            }
            /// Yield a set of contained named flags values.
            ///
            /// This method is like [`iter`](#method.iter), except only yields bits in contained named flags.
            /// Any unknown bits, or bits not corresponding to a contained flag will not be yielded.
            #[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 {
            /// Returns a mutable reference to the raw value of the flags currently stored.
            #[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 {
            /// Get a flags value with all bits unset.
            #[inline]
            pub const fn empty() -> Self { Self(InternalBitFlags::empty()) }
            /// Get a flags value with all known bits set.
            #[inline]
            pub const fn all() -> Self { Self(InternalBitFlags::all()) }
            /// Get the underlying bits value.
            ///
            /// The returned value is exactly the bits set in this flags value.
            #[inline]
            pub const fn bits(&self) -> u32 { self.0.bits() }
            /// Convert from a bits value.
            ///
            /// This method will return `None` if any unknown bits are set.
            #[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,
                }
            }
            /// Convert from a bits value, unsetting any unknown bits.
            #[inline]
            pub const fn from_bits_truncate(bits: u32) -> Self {
                Self(InternalBitFlags::from_bits_truncate(bits))
            }
            /// Convert from a bits value exactly.
            #[inline]
            pub const fn from_bits_retain(bits: u32) -> Self {
                Self(InternalBitFlags::from_bits_retain(bits))
            }
            /// Get a flags value with the bits of a flag with the given name set.
            ///
            /// This method will return `None` if `name` is empty or doesn't
            /// correspond to any named flag.
            #[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,
                }
            }
            /// Whether all bits in `self` are unset.
            #[inline]
            pub const fn is_empty(&self) -> bool { self.0.is_empty() }
            /// Whether all known bits in this flags value are set.
            #[inline]
            pub const fn is_all(&self) -> bool { self.0.is_all() }
            /// Whether any set bits in `other` are also set in `self`.
            #[inline]
            pub const fn intersects(&self, other: Self) -> bool {
                self.0.intersects(other.0)
            }
            /// Whether all set bits in `other` are also set in `self`.
            #[inline]
            pub const fn contains(&self, other: Self) -> bool {
                self.0.contains(other.0)
            }
            /// The bitwise or (`|`) of the bits in `self` and `other`.
            #[inline]
            pub fn insert(&mut self, other: Self) { self.0.insert(other.0) }
            /// The intersection of `self` with the complement of `other` (`&!`).
            ///
            /// This method is not equivalent to `self & !other` when `other` has unknown bits set.
            /// `remove` won't truncate `other`, but the `!` operator will.
            #[inline]
            pub fn remove(&mut self, other: Self) { self.0.remove(other.0) }
            /// The bitwise exclusive-or (`^`) of the bits in `self` and `other`.
            #[inline]
            pub fn toggle(&mut self, other: Self) { self.0.toggle(other.0) }
            /// Call `insert` when `value` is `true` or `remove` when `value` is `false`.
            #[inline]
            pub fn set(&mut self, other: Self, value: bool) {
                self.0.set(other.0, value)
            }
            /// The bitwise and (`&`) of the bits in `self` and `other`.
            #[inline]
            #[must_use]
            pub const fn intersection(self, other: Self) -> Self {
                Self(self.0.intersection(other.0))
            }
            /// The bitwise or (`|`) of the bits in `self` and `other`.
            #[inline]
            #[must_use]
            pub const fn union(self, other: Self) -> Self {
                Self(self.0.union(other.0))
            }
            /// The intersection of `self` with the complement of `other` (`&!`).
            ///
            /// This method is not equivalent to `self & !other` when `other` has unknown bits set.
            /// `difference` won't truncate `other`, but the `!` operator will.
            #[inline]
            #[must_use]
            pub const fn difference(self, other: Self) -> Self {
                Self(self.0.difference(other.0))
            }
            /// The bitwise exclusive-or (`^`) of the bits in `self` and `other`.
            #[inline]
            #[must_use]
            pub const fn symmetric_difference(self, other: Self) -> Self {
                Self(self.0.symmetric_difference(other.0))
            }
            /// The bitwise negation (`!`) of the bits in `self`, truncating the result.
            #[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;
            /// The bitwise or (`|`) of the bits in `self` and `other`.
            #[inline]
            fn bitor(self, other: MeshFlags) -> Self { self.union(other) }
        }
        impl ::bitflags::__private::core::ops::BitOrAssign for MeshFlags {
            /// The bitwise or (`|`) of the bits in `self` and `other`.
            #[inline]
            fn bitor_assign(&mut self, other: Self) { self.insert(other); }
        }
        impl ::bitflags::__private::core::ops::BitXor for MeshFlags {
            type Output = Self;
            /// The bitwise exclusive-or (`^`) of the bits in `self` and `other`.
            #[inline]
            fn bitxor(self, other: Self) -> Self {
                self.symmetric_difference(other)
            }
        }
        impl ::bitflags::__private::core::ops::BitXorAssign for MeshFlags {
            /// The bitwise exclusive-or (`^`) of the bits in `self` and `other`.
            #[inline]
            fn bitxor_assign(&mut self, other: Self) { self.toggle(other); }
        }
        impl ::bitflags::__private::core::ops::BitAnd for MeshFlags {
            type Output = Self;
            /// The bitwise and (`&`) of the bits in `self` and `other`.
            #[inline]
            fn bitand(self, other: Self) -> Self { self.intersection(other) }
        }
        impl ::bitflags::__private::core::ops::BitAndAssign for MeshFlags {
            /// The bitwise and (`&`) of the bits in `self` and `other`.
            #[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;
            /// The intersection of `self` with the complement of `other` (`&!`).
            ///
            /// This method is not equivalent to `self & !other` when `other` has unknown bits set.
            /// `difference` won't truncate `other`, but the `!` operator will.
            #[inline]
            fn sub(self, other: Self) -> Self { self.difference(other) }
        }
        impl ::bitflags::__private::core::ops::SubAssign for MeshFlags {
            /// The intersection of `self` with the complement of `other` (`&!`).
            ///
            /// This method is not equivalent to `self & !other` when `other` has unknown bits set.
            /// `difference` won't truncate `other`, but the `!` operator will.
            #[inline]
            fn sub_assign(&mut self, other: Self) { self.remove(other); }
        }
        impl ::bitflags::__private::core::ops::Not for MeshFlags {
            type Output = Self;
            /// The bitwise negation (`!`) of the bits in `self`, truncating the result.
            #[inline]
            fn not(self) -> Self { self.complement() }
        }
        impl ::bitflags::__private::core::iter::Extend<MeshFlags> for
            MeshFlags {
            /// The bitwise or (`|`) of the bits in each flags value.
            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 {
            /// The bitwise or (`|`) of the bits in each flags value.
            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 {
            /// Yield a set of contained flags values.
            ///
            /// Each yielded flags value will correspond to a defined named flag. Any unknown bits
            /// will be yielded together as a final flags value.
            #[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()))
            }
            /// Yield a set of contained named flags values.
            ///
            /// This method is like [`iter`](#method.iter), except only yields bits in contained named flags.
            /// Any unknown bits, or bits not corresponding to a contained flag will not be yielded.
            #[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    /// Various flags and tightly-packed values on a mesh.
701    ///
702    /// Flags grow from the top bit down; other values grow from the bottom bit
703    /// up.
704    #[repr(transparent)]
705    pub struct MeshFlags: u32 {
706        /// Bitmask for the 16-bit index into the LOD array.
707        ///
708        /// This will be `u16::MAX` if this mesh has no LOD.
709        const LOD_INDEX_MASK              = (1 << 16) - 1;
710        /// Whether visibility ranges use the center of the AABB to compute
711        /// distance from the camera.
712        ///
713        /// If false, this uses distance from the world-space translation of the
714        /// mesh instead.
715        const AABB_BASED_VISIBILITY_RANGE = 1 << 27;
716        /// Disables frustum culling for this mesh.
717        ///
718        /// This corresponds to the
719        /// [`bevy_render::view::visibility::NoFrustumCulling`] component.
720        const NO_FRUSTUM_CULLING          = 1 << 28;
721        const SHADOW_RECEIVER             = 1 << 29;
722        const TRANSMITTED_SHADOW_RECEIVER = 1 << 30;
723        // Indicates the sign of the determinant of the 3x3 model matrix. If the sign is positive,
724        // then the flag should be set, else it should not be set.
725        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    /// The first bit of the LOD index.
769    pub const LOD_INDEX_SHIFT: u32 = 0;
770}
771
772bitflags::bitflags! {
773    /// Various useful flags for [`RenderMeshInstance`]s.
774    #[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 {
            /// Get a flags value with all bits unset.
            #[inline]
            pub const fn empty() -> Self {
                Self(<u32 as ::bitflags::Bits>::EMPTY)
            }
            /// Get a flags value with all known bits set.
            #[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)
            }
            /// Get the underlying bits value.
            ///
            /// The returned value is exactly the bits set in this flags value.
            #[inline]
            pub const fn bits(&self) -> u32 { self.0 }
            /// Convert from a bits value.
            ///
            /// This method will return `None` if any unknown bits are set.
            #[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 }
            }
            /// Convert from a bits value, unsetting any unknown bits.
            #[inline]
            pub const fn from_bits_truncate(bits: u32) -> Self {
                Self(bits & Self::all().0)
            }
            /// Convert from a bits value exactly.
            #[inline]
            pub const fn from_bits_retain(bits: u32) -> Self { Self(bits) }
            /// Get a flags value with the bits of a flag with the given name set.
            ///
            /// This method will return `None` if `name` is empty or doesn't
            /// correspond to any named flag.
            #[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
            }
            /// Whether all bits in `self` are unset.
            #[inline]
            pub const fn is_empty(&self) -> bool {
                self.0 == <u32 as ::bitflags::Bits>::EMPTY
            }
            /// Whether all known bits in this flags value are set.
            #[inline]
            pub const fn is_all(&self) -> bool {
                Self::all().0 | self.0 == self.0
            }
            /// Whether any set bits in `other` are also set in `self`.
            #[inline]
            pub const fn intersects(&self, other: Self) -> bool {
                self.0 & other.0 != <u32 as ::bitflags::Bits>::EMPTY
            }
            /// Whether all set bits in `other` are also set in `self`.
            #[inline]
            pub const fn contains(&self, other: Self) -> bool {
                self.0 & other.0 == other.0
            }
            /// The bitwise or (`|`) of the bits in `self` and `other`.
            #[inline]
            pub fn insert(&mut self, other: Self) {
                *self = Self(self.0).union(other);
            }
            /// The intersection of `self` with the complement of `other` (`&!`).
            ///
            /// This method is not equivalent to `self & !other` when `other` has unknown bits set.
            /// `remove` won't truncate `other`, but the `!` operator will.
            #[inline]
            pub fn remove(&mut self, other: Self) {
                *self = Self(self.0).difference(other);
            }
            /// The bitwise exclusive-or (`^`) of the bits in `self` and `other`.
            #[inline]
            pub fn toggle(&mut self, other: Self) {
                *self = Self(self.0).symmetric_difference(other);
            }
            /// Call `insert` when `value` is `true` or `remove` when `value` is `false`.
            #[inline]
            pub fn set(&mut self, other: Self, value: bool) {
                if value { self.insert(other); } else { self.remove(other); }
            }
            /// The bitwise and (`&`) of the bits in `self` and `other`.
            #[inline]
            #[must_use]
            pub const fn intersection(self, other: Self) -> Self {
                Self(self.0 & other.0)
            }
            /// The bitwise or (`|`) of the bits in `self` and `other`.
            #[inline]
            #[must_use]
            pub const fn union(self, other: Self) -> Self {
                Self(self.0 | other.0)
            }
            /// The intersection of `self` with the complement of `other` (`&!`).
            ///
            /// This method is not equivalent to `self & !other` when `other` has unknown bits set.
            /// `difference` won't truncate `other`, but the `!` operator will.
            #[inline]
            #[must_use]
            pub const fn difference(self, other: Self) -> Self {
                Self(self.0 & !other.0)
            }
            /// The bitwise exclusive-or (`^`) of the bits in `self` and `other`.
            #[inline]
            #[must_use]
            pub const fn symmetric_difference(self, other: Self) -> Self {
                Self(self.0 ^ other.0)
            }
            /// The bitwise negation (`!`) of the bits in `self`, truncating the result.
            #[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;
            /// The bitwise or (`|`) of the bits in `self` and `other`.
            #[inline]
            fn bitor(self, other: InternalBitFlags) -> Self {
                self.union(other)
            }
        }
        impl ::bitflags::__private::core::ops::BitOrAssign for
            InternalBitFlags {
            /// The bitwise or (`|`) of the bits in `self` and `other`.
            #[inline]
            fn bitor_assign(&mut self, other: Self) { self.insert(other); }
        }
        impl ::bitflags::__private::core::ops::BitXor for InternalBitFlags {
            type Output = Self;
            /// The bitwise exclusive-or (`^`) of the bits in `self` and `other`.
            #[inline]
            fn bitxor(self, other: Self) -> Self {
                self.symmetric_difference(other)
            }
        }
        impl ::bitflags::__private::core::ops::BitXorAssign for
            InternalBitFlags {
            /// The bitwise exclusive-or (`^`) of the bits in `self` and `other`.
            #[inline]
            fn bitxor_assign(&mut self, other: Self) { self.toggle(other); }
        }
        impl ::bitflags::__private::core::ops::BitAnd for InternalBitFlags {
            type Output = Self;
            /// The bitwise and (`&`) of the bits in `self` and `other`.
            #[inline]
            fn bitand(self, other: Self) -> Self { self.intersection(other) }
        }
        impl ::bitflags::__private::core::ops::BitAndAssign for
            InternalBitFlags {
            /// The bitwise and (`&`) of the bits in `self` and `other`.
            #[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;
            /// The intersection of `self` with the complement of `other` (`&!`).
            ///
            /// This method is not equivalent to `self & !other` when `other` has unknown bits set.
            /// `difference` won't truncate `other`, but the `!` operator will.
            #[inline]
            fn sub(self, other: Self) -> Self { self.difference(other) }
        }
        impl ::bitflags::__private::core::ops::SubAssign for InternalBitFlags
            {
            /// The intersection of `self` with the complement of `other` (`&!`).
            ///
            /// This method is not equivalent to `self & !other` when `other` has unknown bits set.
            /// `difference` won't truncate `other`, but the `!` operator will.
            #[inline]
            fn sub_assign(&mut self, other: Self) { self.remove(other); }
        }
        impl ::bitflags::__private::core::ops::Not for InternalBitFlags {
            type Output = Self;
            /// The bitwise negation (`!`) of the bits in `self`, truncating the result.
            #[inline]
            fn not(self) -> Self { self.complement() }
        }
        impl ::bitflags::__private::core::iter::Extend<InternalBitFlags> for
            InternalBitFlags {
            /// The bitwise or (`|`) of the bits in each flags value.
            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 {
            /// The bitwise or (`|`) of the bits in each flags value.
            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 {
            /// Yield a set of contained flags values.
            ///
            /// Each yielded flags value will correspond to a defined named flag. Any unknown bits
            /// will be yielded together as a final flags value.
            #[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()))
            }
            /// Yield a set of contained named flags values.
            ///
            /// This method is like [`iter`](#method.iter), except only yields bits in contained named flags.
            /// Any unknown bits, or bits not corresponding to a contained flag will not be yielded.
            #[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 {
            /// Returns a mutable reference to the raw value of the flags currently stored.
            #[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 {
            /// Get a flags value with all bits unset.
            #[inline]
            pub const fn empty() -> Self { Self(InternalBitFlags::empty()) }
            /// Get a flags value with all known bits set.
            #[inline]
            pub const fn all() -> Self { Self(InternalBitFlags::all()) }
            /// Get the underlying bits value.
            ///
            /// The returned value is exactly the bits set in this flags value.
            #[inline]
            pub const fn bits(&self) -> u32 { self.0.bits() }
            /// Convert from a bits value.
            ///
            /// This method will return `None` if any unknown bits are set.
            #[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,
                }
            }
            /// Convert from a bits value, unsetting any unknown bits.
            #[inline]
            pub const fn from_bits_truncate(bits: u32) -> Self {
                Self(InternalBitFlags::from_bits_truncate(bits))
            }
            /// Convert from a bits value exactly.
            #[inline]
            pub const fn from_bits_retain(bits: u32) -> Self {
                Self(InternalBitFlags::from_bits_retain(bits))
            }
            /// Get a flags value with the bits of a flag with the given name set.
            ///
            /// This method will return `None` if `name` is empty or doesn't
            /// correspond to any named flag.
            #[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,
                }
            }
            /// Whether all bits in `self` are unset.
            #[inline]
            pub const fn is_empty(&self) -> bool { self.0.is_empty() }
            /// Whether all known bits in this flags value are set.
            #[inline]
            pub const fn is_all(&self) -> bool { self.0.is_all() }
            /// Whether any set bits in `other` are also set in `self`.
            #[inline]
            pub const fn intersects(&self, other: Self) -> bool {
                self.0.intersects(other.0)
            }
            /// Whether all set bits in `other` are also set in `self`.
            #[inline]
            pub const fn contains(&self, other: Self) -> bool {
                self.0.contains(other.0)
            }
            /// The bitwise or (`|`) of the bits in `self` and `other`.
            #[inline]
            pub fn insert(&mut self, other: Self) { self.0.insert(other.0) }
            /// The intersection of `self` with the complement of `other` (`&!`).
            ///
            /// This method is not equivalent to `self & !other` when `other` has unknown bits set.
            /// `remove` won't truncate `other`, but the `!` operator will.
            #[inline]
            pub fn remove(&mut self, other: Self) { self.0.remove(other.0) }
            /// The bitwise exclusive-or (`^`) of the bits in `self` and `other`.
            #[inline]
            pub fn toggle(&mut self, other: Self) { self.0.toggle(other.0) }
            /// Call `insert` when `value` is `true` or `remove` when `value` is `false`.
            #[inline]
            pub fn set(&mut self, other: Self, value: bool) {
                self.0.set(other.0, value)
            }
            /// The bitwise and (`&`) of the bits in `self` and `other`.
            #[inline]
            #[must_use]
            pub const fn intersection(self, other: Self) -> Self {
                Self(self.0.intersection(other.0))
            }
            /// The bitwise or (`|`) of the bits in `self` and `other`.
            #[inline]
            #[must_use]
            pub const fn union(self, other: Self) -> Self {
                Self(self.0.union(other.0))
            }
            /// The intersection of `self` with the complement of `other` (`&!`).
            ///
            /// This method is not equivalent to `self & !other` when `other` has unknown bits set.
            /// `difference` won't truncate `other`, but the `!` operator will.
            #[inline]
            #[must_use]
            pub const fn difference(self, other: Self) -> Self {
                Self(self.0.difference(other.0))
            }
            /// The bitwise exclusive-or (`^`) of the bits in `self` and `other`.
            #[inline]
            #[must_use]
            pub const fn symmetric_difference(self, other: Self) -> Self {
                Self(self.0.symmetric_difference(other.0))
            }
            /// The bitwise negation (`!`) of the bits in `self`, truncating the result.
            #[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;
            /// The bitwise or (`|`) of the bits in `self` and `other`.
            #[inline]
            fn bitor(self, other: RenderMeshInstanceFlags) -> Self {
                self.union(other)
            }
        }
        impl ::bitflags::__private::core::ops::BitOrAssign for
            RenderMeshInstanceFlags {
            /// The bitwise or (`|`) of the bits in `self` and `other`.
            #[inline]
            fn bitor_assign(&mut self, other: Self) { self.insert(other); }
        }
        impl ::bitflags::__private::core::ops::BitXor for
            RenderMeshInstanceFlags {
            type Output = Self;
            /// The bitwise exclusive-or (`^`) of the bits in `self` and `other`.
            #[inline]
            fn bitxor(self, other: Self) -> Self {
                self.symmetric_difference(other)
            }
        }
        impl ::bitflags::__private::core::ops::BitXorAssign for
            RenderMeshInstanceFlags {
            /// The bitwise exclusive-or (`^`) of the bits in `self` and `other`.
            #[inline]
            fn bitxor_assign(&mut self, other: Self) { self.toggle(other); }
        }
        impl ::bitflags::__private::core::ops::BitAnd for
            RenderMeshInstanceFlags {
            type Output = Self;
            /// The bitwise and (`&`) of the bits in `self` and `other`.
            #[inline]
            fn bitand(self, other: Self) -> Self { self.intersection(other) }
        }
        impl ::bitflags::__private::core::ops::BitAndAssign for
            RenderMeshInstanceFlags {
            /// The bitwise and (`&`) of the bits in `self` and `other`.
            #[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;
            /// The intersection of `self` with the complement of `other` (`&!`).
            ///
            /// This method is not equivalent to `self & !other` when `other` has unknown bits set.
            /// `difference` won't truncate `other`, but the `!` operator will.
            #[inline]
            fn sub(self, other: Self) -> Self { self.difference(other) }
        }
        impl ::bitflags::__private::core::ops::SubAssign for
            RenderMeshInstanceFlags {
            /// The intersection of `self` with the complement of `other` (`&!`).
            ///
            /// This method is not equivalent to `self & !other` when `other` has unknown bits set.
            /// `difference` won't truncate `other`, but the `!` operator will.
            #[inline]
            fn sub_assign(&mut self, other: Self) { self.remove(other); }
        }
        impl ::bitflags::__private::core::ops::Not for RenderMeshInstanceFlags
            {
            type Output = Self;
            /// The bitwise negation (`!`) of the bits in `self`, truncating the result.
            #[inline]
            fn not(self) -> Self { self.complement() }
        }
        impl ::bitflags::__private::core::iter::Extend<RenderMeshInstanceFlags>
            for RenderMeshInstanceFlags {
            /// The bitwise or (`|`) of the bits in each flags value.
            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 {
            /// The bitwise or (`|`) of the bits in each flags value.
            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 {
            /// Yield a set of contained flags values.
            ///
            /// Each yielded flags value will correspond to a defined named flag. Any unknown bits
            /// will be yielded together as a final flags value.
            #[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()))
            }
            /// Yield a set of contained named flags values.
            ///
            /// This method is like [`iter`](#method.iter), except only yields bits in contained named flags.
            /// Any unknown bits, or bits not corresponding to a contained flag will not be yielded.
            #[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        /// The mesh casts shadows.
778        const SHADOW_CASTER           = 1 << 0;
779        /// The mesh can participate in automatic batching.
780        const AUTOMATIC_BATCHING      = 1 << 1;
781        /// The mesh had a transform last frame and so is eligible for motion
782        /// vector computation.
783        const HAS_PREVIOUS_TRANSFORM  = 1 << 2;
784        /// The mesh had a skin last frame and so that skin should be taken into
785        /// account for motion vector computation.
786        const HAS_PREVIOUS_SKIN       = 1 << 3;
787        /// The mesh had morph targets last frame and so they should be taken
788        /// into account for motion vector computation.
789        const HAS_PREVIOUS_MORPH      = 1 << 4;
790        /// CPU culling has been disabled because the `NoCpuCulling` component
791        /// is present on the mesh instance.
792        const NO_CPU_CULLING          = 1 << 5;
793    }
794}
795
796/// CPU data that the render world keeps for each entity, when *not* using GPU
797/// mesh uniform building.
798#[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    /// Data shared between both the CPU mesh uniform building and the GPU mesh
801    /// uniform building paths.
802    #[deref]
803    pub shared: RenderMeshInstanceSharedFlatBlob,
804    /// The transform of the mesh.
805    ///
806    /// This will be written into the [`MeshUniform`] at the appropriate time.
807    pub transforms: MeshTransforms,
808    /// The set of render layers that this mesh belongs to.
809    pub render_layers: Option<RenderLayers>,
810}
811
812/// CPU data that the render world needs to keep for each entity that contains a
813/// mesh when using GPU mesh uniform building.
814#[derive(impl ::core::ops::Deref for RenderMeshInstanceGpu {
    type Target = RenderMeshInstanceSharedFlatBlob;
    fn deref(&self) -> &Self::Target { &self.shared }
}Deref)]
815pub struct RenderMeshInstanceGpu {
816    /// Thread-safe shared between both the CPU mesh uniform building and the
817    /// GPU mesh uniform building paths.
818    #[deref]
819    pub shared: RenderMeshInstanceSharedFlatBlob,
820    /// Thread-safe per-mesh-instance data that's specific to the GPU mesh
821    /// uniform building path.
822    pub gpu_specific: RenderMeshInstanceGpuFlatBlob,
823    /// The render layers that this mesh instance belongs to.
824    ///
825    /// This contains a [`smallvec::SmallVec`], so it isn't thread-safe.
826    pub render_layers: Option<RenderLayers>,
827}
828
829/// The thread-safe POD that's stored for each mesh, common to both the CPU and
830/// GPU preprocessing paths.
831///
832/// Fields here are formatted in such a way as to implement [`bytemuck::Pod`]:
833/// i.e. with no vectors and no enums. A corresponding
834/// [`RenderMeshInstanceSharedFlatBlob`] is provided, for in-place update in
835/// shared memory.
836#[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    /// Returns true if this entity is eligible to participate in automatic
883    /// batching.
884    #[inline]
885    pub fn should_batch(&self) -> bool {
886        self.flags()
887            .contains(RenderMeshInstanceFlags::AUTOMATIC_BATCHING)
888    }
889}
890
891/// Data in [`RenderMeshInstanceGpu`] that's both specific to the GPU
892/// preprocessing path and POD.
893///
894/// This includes all the data except the `render_layers` list, which isn't POD.
895#[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
982/// CPU data that the render world needs to keep about each entity that contains
983/// a mesh.
984pub struct RenderMeshInstanceShared {
985    /// The [`AssetId`] of the mesh.
986    pub mesh_asset_id: AssetId<Mesh>,
987    /// A slot for the material bind group index.
988    pub material_bindings_index: MaterialBindingId,
989    /// Index of the slab that the lightmap resides in, if a lightmap is
990    /// present.
991    pub lightmap_slab_index: Option<LightmapSlabIndex>,
992    /// A representative position of the mesh instance in local space,
993    /// derived from its axis-aligned bounding box.
994    ///
995    /// This value is typically used as a spatial proxy for operations such as
996    /// view-dependent sorting (e.g., transparent object ordering).
997    pub center: Vec3,
998    /// User supplied tag to identify this mesh instance.
999    pub tag: u32,
1000    /// Various flags.
1001    pub flags: RenderMeshInstanceFlags,
1002}
1003
1004/// Information that is gathered during the parallel portion of mesh extraction
1005/// when GPU mesh uniform building is enabled.
1006///
1007/// From this, the [`MeshInputUniform`] and [`RenderMeshInstanceGpu`] are
1008/// prepared.
1009pub struct RenderMeshInstanceGpuBuilder {
1010    /// Data that will be placed on the [`RenderMeshInstanceGpu`].
1011    pub shared: RenderMeshInstanceSharedFlat,
1012    /// The current transform.
1013    pub world_from_local: Affine3,
1014    /// Four 16-bit unsigned normalized UV values packed into a [`UVec2`]:
1015    ///
1016    /// ```text
1017    ///                         <--- MSB                   LSB --->
1018    ///                         +---- min v ----+ +---- min u ----+
1019    ///     lightmap_uv_rect.x: vvvvvvvv vvvvvvvv uuuuuuuu uuuuuuuu,
1020    ///                         +---- max v ----+ +---- max u ----+
1021    ///     lightmap_uv_rect.y: VVVVVVVV VVVVVVVV UUUUUUUU UUUUUUUU,
1022    ///
1023    /// (MSB: most significant bit; LSB: least significant bit.)
1024    /// ```
1025    pub lightmap_uv_rect: UVec2,
1026    /// The index of the previous mesh input.
1027    pub previous_input_index: Option<NonMaxU32>,
1028    /// The render layers that this mesh instance belongs to.
1029    pub render_layers: Option<RenderLayers>,
1030    /// Various flags.
1031    pub mesh_flags: MeshFlags,
1032}
1033
1034/// The per-thread queues used during [`extract_meshes_for_gpu_building`].
1035///
1036/// There are two varieties of these: one for when culling happens on CPU and
1037/// one for when culling happens on GPU. Having the two varieties avoids wasting
1038/// space if GPU culling is disabled.
1039#[derive(#[automatically_derived]
impl ::core::default::Default for RenderMeshInstanceGpuQueue {
    #[inline]
    fn default() -> RenderMeshInstanceGpuQueue { Self::None }
}Default)]
1040pub enum RenderMeshInstanceGpuQueue {
1041    /// The default value.
1042    ///
1043    /// This becomes [`RenderMeshInstanceGpuQueue::CpuCulling`] or
1044    /// [`RenderMeshInstanceGpuQueue::GpuCulling`] once extraction starts.
1045    #[default]
1046    None,
1047    /// The version of [`RenderMeshInstanceGpuQueue`] that omits the
1048    /// [`MeshCullingData`], so that we don't waste space when GPU
1049    /// culling is disabled.
1050    CpuCulling {
1051        /// Stores GPU data for each entity that became visible or changed in
1052        /// such a way that necessitates updating the [`MeshInputUniform`] (e.g.
1053        /// changed transform).
1054        changed: Vec<(MainEntity, RenderMeshInstanceGpuBuilder)>,
1055        /// Stores the IDs of entities that became invisible this frame.
1056        removed: Vec<MainEntity>,
1057    },
1058    /// The version of [`RenderMeshInstanceGpuQueue`] that contains the
1059    /// [`MeshCullingData`], used when any view has GPU culling
1060    /// enabled.
1061    GpuCulling {
1062        /// Stores GPU data for each mesh entity that became visible or changed
1063        /// in such a way as to necessitate updating the [`MeshInputUniform`]
1064        /// (e.g. changed transform).
1065        ///
1066        /// This only stores information for meshes *without* [`NoCpuCulling`].
1067        changed_cpu_culling: Vec<(MainEntity, RenderMeshInstanceGpuBuilder, MeshCullingData)>,
1068        /// Stores GPU data for each mesh entity that changed in such a way as
1069        /// to necessitate updating the [`MeshInputUniform`] (e.g. changed
1070        /// transform).
1071        ///
1072        /// This only stores information for meshes *with* [`NoCpuCulling`].
1073        changed_gpu_culling: Vec<(MainEntity, RenderMeshInstanceGpuBuilder, MeshCullingData)>,
1074        /// Stores the IDs of entities that became invisible this frame.
1075        removed: Vec<MainEntity>,
1076    },
1077}
1078
1079/// The per-thread queues containing mesh instances, populated during the
1080/// extract phase.
1081///
1082/// These are filled in [`extract_meshes_for_gpu_building`] and consumed in
1083/// [`collect_meshes_for_gpu_building`].
1084#[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/// Holds a list of meshes that couldn't be extracted this frame because their
1088/// materials weren't prepared yet.
1089///
1090/// On subsequent frames, we try to reextract those meshes.
1091#[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    /// A gpu builder will provide the mesh instance id
1096    /// during [`RenderMeshInstanceGpuPrepared::update`].
1097    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    /// The cpu builder does not have an equivalent [`RenderMeshInstanceGpuBuilder`].
1117    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            // Filled in later.
1163            lightmap_slab_index: LightmapSlabIndexFlat::default(),
1164            // Filled in later.
1165            current_uniform_index: 0,
1166        }
1167    }
1168}
1169
1170/// Information that the render world keeps about each entity that contains a
1171/// mesh.
1172///
1173/// The set of information needed is different depending on whether CPU or GPU
1174/// [`MeshUniform`] building is in use.
1175#[derive(impl bevy_ecs::resource::Resource for RenderMeshInstances where
    Self: ::core::marker::Send + ::core::marker::Sync + 'static {}Resource)]
1176pub enum RenderMeshInstances {
1177    /// Information needed when using CPU mesh instance data building.
1178    CpuBuilding(RenderMeshInstancesCpu),
1179    /// Information needed when using GPU mesh instance data building.
1180    GpuBuilding(RenderMeshInstancesGpu),
1181}
1182
1183/// Information that the render world keeps about each entity that contains a
1184/// mesh, when using CPU mesh instance data building.
1185#[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/// Information that the render world keeps about each entity that contains a
1189/// mesh, when using GPU mesh instance data building.
1190#[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    /// Creates a new [`RenderMeshInstances`] instance.
1195    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    /// Returns the ID of the mesh asset attached to the given entity, if any.
1204    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    /// Constructs [`RenderMeshQueueData`] for the given entity, if it has a
1212    /// mesh attached.
1213    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    /// Inserts the given flags into the CPU or GPU render mesh instance data
1225    /// for the given mesh as appropriate.
1226    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    /// Inserts the given flags into the render mesh instance data for the given
1254    /// mesh.
1255    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    /// Inserts the given flags into the render mesh instance data for the given
1280    /// mesh.
1281    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    /// Clears out a [`RenderMeshInstanceGpuQueue`], creating or recreating it
1290    /// as necessary.
1291    ///
1292    /// `any_gpu_culling` should be set to true if any view has GPU culling
1293    /// enabled.
1294    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    /// Adds a new mesh to this queue.
1329    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    /// Adds the given entity to the `removed` list, queuing it for removal.
1392    ///
1393    /// The `gpu_culling` parameter specifies whether GPU culling is enabled.
1394    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    /// Prepares the data needed to update the mesh instance.
1419    ///
1420    /// This is the thread-safe part of the update.
1421    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        // Look up the material index. If we couldn't fetch the material index,
1433        // then the material hasn't been prepared yet, perhaps because it hasn't
1434        // yet loaded. In that case, we return None so that
1435        // `collect_meshes_for_gpu_building` will add the mesh to
1436        // `meshes_to_reextract_next_frame` and bail.
1437        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            // Use a dummy material binding ID.
1442            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        // Create the mesh input uniform.
1484        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
1518/// Data needed to construct the [`RenderMeshInstanceGpu`] for a mesh instance.
1519pub struct RenderMeshInstanceGpuPrepared {
1520    /// Data shared between the CPU and GPU versions of this mesh instance.
1521    shared: RenderMeshInstanceSharedFlat,
1522    /// The data that will be uploaded to the GPU as a [`MeshInputUniform`].
1523    mesh_input_uniform: MeshInputUniform,
1524    /// The render layers that this mesh instance belongs to.
1525    render_layers: Option<RenderLayers>,
1526}
1527
1528impl RenderMeshInstanceGpuPrepared {
1529    /// Flushes this mesh instance to the [`RenderMeshInstanceGpu`] and
1530    /// [`MeshInputUniform`] tables, replacing the existing entry if applicable.
1531    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        // Did the last frame contain this entity as well?
1539        let current_uniform_index;
1540        match render_mesh_instances.entry(entity) {
1541            Entry::Occupied(mut occupied_entry) => {
1542                // Yes, it did. Replace its entry with the new one.
1543
1544                // Reserve a slot.
1545                current_uniform_index = occupied_entry
1546                    .get_mut()
1547                    .gpu_specific
1548                    .current_uniform_index();
1549
1550                // Save the old mesh input uniform. The mesh preprocessing
1551                // shader will need it to compute motion vectors.
1552                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                // Write in the new mesh input uniform.
1558                current_input_buffer.set(current_uniform_index, self.mesh_input_uniform);
1559
1560                // Write the instance.
1561                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                // No, this is a new entity. Push its data on to the buffer.
1571                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
1590/// Removes a [`MeshInputUniform`] corresponding to an entity that became
1591/// invisible from the buffer.
1592fn 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    // Remove the uniform data.
1598    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    /// Returns a new [`MeshCullingData`] initialized with the given AABB.
1609    ///
1610    /// If no AABB is provided, an infinitely-large one is conservatively
1611    /// chosen.
1612    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    /// Flushes this mesh instance culling data to the
1626    /// [`MeshCullingDataBuffer`], replacing the existing entry if applicable.
1627    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/// Data that [`crate::material::queue_material_meshes`] and similar systems
1651/// need in order to place entities that contain meshes in the right batch.
1652#[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    /// General information about the mesh instance.
1655    #[deref]
1656    pub shared: &'a RenderMeshInstanceSharedFlatBlob,
1657    /// The render layers that this mesh instance belongs to.
1658    pub render_layers: Option<RenderLayers>,
1659    /// The index of the [`MeshInputUniform`] in the GPU buffer for this mesh
1660    /// instance.
1661    pub current_uniform_index: InputUniformIndex,
1662}
1663
1664/// A [`SystemSet`] that encompasses both [`extract_meshes_for_cpu_building`]
1665/// and [`extract_meshes_for_gpu_building`].
1666#[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/// A resource, part of the render world, that stores all entities that are
1670/// potentially-visible and have [`NoCpuCulling`] components.
1671///
1672/// Even though this resource exists, individual views still have their own
1673/// lists of all GPU-culled entities, because render layers can alter the set of
1674/// entities visible to each view.
1675#[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    /// A mapping from each potentially-visible entity to the render layers it's
1678    /// part of.
1679    pub entities: MainEntityHashMap<RenderLayers>,
1680
1681    /// A list of all entities with GPU culling (and no CPU culling) that became
1682    /// potentially visible in some view this frame.
1683    ///
1684    /// This also includes entities that changed from CPU culling to GPU
1685    /// culling.
1686    ///
1687    /// Unlike the corresponding field in
1688    /// [`bevy_render::view::visibility::RenderVisibleEntitiesClass`], this list
1689    /// is *not* necessarily sorted.
1690    pub added: Vec<MainEntity>,
1691
1692    /// A list of all entities with GPU culling that were either despawned or
1693    /// otherwise became definitely invisible this frame.
1694    ///
1695    /// This also includes entities that changed from GPU culling to CPU culling.
1696    ///
1697    /// Unlike the corresponding field in
1698    /// [`bevy_render::view::visibility::RenderVisibleEntitiesClass`], this list
1699    /// is *not* necessarily sorted.
1700    pub removed: Vec<MainEntity>,
1701
1702    /// A list of all entities with GPU culling that changed the set of render
1703    /// layers they belong to this frame.
1704    pub changed_layers: Vec<MainEntity>,
1705}
1706
1707impl RenderGpuCulledEntities {
1708    /// Clears out the sets of newly-added entities, newly-removed entities, and
1709    /// entities that newly changed render layers in preparation for a new
1710    /// frame.
1711    pub fn prepare_for_new_frame(&mut self) {
1712        self.added.clear();
1713        self.removed.clear();
1714        self.changed_layers.clear();
1715    }
1716
1717    /// Records that an entity became newly-visible or changed its set of layers
1718    /// this frame.
1719    ///
1720    /// The `render_layers` argument specifies the set of render layers that the
1721    /// entity belongs to.
1722    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    /// Records that an entity became newly-invisible this frame.
1747    pub fn remove(&mut self, old_entity: MainEntity) {
1748        self.removed.push(old_entity);
1749        self.entities.remove(&old_entity);
1750    }
1751}
1752
1753/// Extracts meshes from the main world into the render world, populating the
1754/// [`RenderMeshInstances`].
1755///
1756/// This is the variant of the system that runs when we're *not* using GPU
1757/// [`MeshUniform`] building.
1758pub 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    // Collect the render mesh instances.
1855    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
1871/// All the data that we need from a mesh in the main world.
1872type 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
1893/// Extracts meshes from the main world to thread-local buffers in the render
1894/// world.
1895///
1896/// This is optimized to only look at entities that have changed since the last
1897/// frame.
1898///
1899/// This is the variant of the system that runs when we're using GPU
1900/// [`MeshUniform`] building.
1901pub 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    // Initialize the queues.
1967    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    // Process materials that `collect_meshes_for_gpu_building` marked as
1973    // needing to be reextracted. This will happen when we extracted a mesh on
1974    // some previous frame, but its material hadn't been prepared yet, perhaps
1975    // because the material hadn't yet been loaded. We reextract such materials
1976    // on subsequent frames so that `collect_meshes_for_gpu_building` will check
1977    // to see if their materials have been prepared.
1978    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    // We have to skip the meshes in the potential reextraction set if we
1998    // encounter them during the `changed_meshes_query` below. But, because
1999    // `changed_meshes_query` is currently a full table scan, we don't want to
2000    // have to query it multiple times. So we instead represent the potential
2001    // reextraction set as a bitfield and set the bit corresponding to an entity
2002    // as we encounter that entity below.
2003    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    // Collect render mesh instances. Build up the uniform buffer.
2009
2010    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    // Find all meshes that have changed, and record information needed to
2019    // construct the `MeshInputUniform` for them.
2020    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 this entity was in the potential reextraction set, set the
2032            // appropriate bit.
2033            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    // Add the entities in the potential reextraction set to the
2041    // `reextract_entities` list, unless we saw them in the query above.
2042    //
2043    // Note that this will likely iterate over some spurious zero bits at the
2044    // end, since we rounded the number of elements to potentially reextract up
2045    // to the nearest multiple of 64. But that's OK, because we check to see
2046    // whether the indices exist in the potential reextraction set before adding
2047    // the corresponding entities to the `reextract_entities` list.
2048    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    // Reextract meshes we marked as needing to be reextracted.
2055    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    // Also record info about each mesh that became invisible.
2069    for entity in removed_meshes_query.read() {
2070        // Only queue a mesh for removal if we didn't pick it up above.
2071        // It's possible that a necessary component was removed and re-added in
2072        // the same frame.
2073        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
2082/// Extracts a single mesh from the main world to a thread-local buffer in the
2083/// render world.
2084fn 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 the entity is invisible, remove it.
2111    if !view_visibility.get() {
2112        queue.remove(entity.into(), any_gpu_culling);
2113        return;
2114    }
2115
2116    // If the entity has a visibility range, determine its LOD index.
2117    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    // Calculate the mesh flags.
2123    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    // Calculate shared mesh data.
2133    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    // Calculate the lightmap UV rect, if applicable.
2143    let lightmap_uv_rect = pack_lightmap_uv_rect(lightmap.map(|lightmap| lightmap.uv_rect));
2144
2145    // Calculate data needed to cull the mesh on GPU.
2146    let gpu_mesh_culling_data = any_gpu_culling.then(|| MeshCullingData::new(aabb));
2147
2148    // Determine where the mesh was in the buffer on the previous frame, if
2149    // applicable. This is used for motion vector computation.
2150    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    // Gather up all the data needed to update the GPU buffers in
2164    // `collect_meshes_for_gpu_building`.
2165    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    // Push that data onto the queue.
2175    queue.push(
2176        entity.into(),
2177        gpu_mesh_instance_builder,
2178        gpu_mesh_culling_data,
2179        no_cpu_culling,
2180    );
2181}
2182
2183/// An iterator over the 0 positions in an array of atomic words.
2184struct AtomicU64ZeroBitIter<'a> {
2185    /// The slice of atomic words.
2186    bits: &'a [AtomicU64],
2187    /// The current word.
2188    ///
2189    /// We change bits from 0 to 1 as we encounter them.
2190    current_word: u64,
2191    /// The index of the word after [`Self::current_word`].
2192    next_index: usize,
2193}
2194
2195impl<'a> AtomicU64ZeroBitIter<'a> {
2196    /// Creates a new [`AtomicU64ZeroBitIter`] ready to iterate over the given
2197    /// bits.
2198    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        // Repeatedly load the next word if we're out of zero bits in this one.
2212        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        // Find the next zero bit index.
2218        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
2225/// Transfers entities from [`RenderGpuCulledEntities`] to the
2226/// [`RenderVisibleEntities`] and [`RenderShadowMapVisibleEntities`] components
2227/// on each view.
2228///
2229/// Each view must maintain a separate list of GPU-culled entities because the
2230/// views and entities might belong to different render layers.
2231pub 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    // Collect cameras.
2237    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    // Collect shadow maps.
2246    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
2257/// Transfers entities from [`RenderGpuCulledEntities`] to the
2258/// [`RenderVisibleEntities`] object for each view or subview.
2259///
2260/// This only processes meshes that have [`NoCpuCulling`] components. The
2261/// corresponding function for entities that are culled on CPU is
2262/// `collect_visible_cpu_culled_entities_for_subview`.
2263fn 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    // Only 3D meshes can be culled on GPU at the moment.
2269    let render_view_visible_mesh_entities = render_visible_entities
2270        .classes
2271        .entry(TypeId::of::<Mesh3d>())
2272        .or_default();
2273
2274    // Update the list with entities that were removed.
2275    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    // Update the list with entities that became newly visible.
2288    let mut any_added = false;
2289    for main_entity in &render_mesh_instance_gpu_queues.added {
2290        // Make sure the entity belongs to our set of render layers.
2291        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        // Update the tables. 3D meshes have no render entity, so it's
2300        // appropriate to use `Entity::PLACEHOLDER` here.
2301        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    // Process entities that changed layers.
2309    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        // This is either treated as no change, as an addition, or as a removal.
2316        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                // No change; do nothing.
2324            }
2325            (false, true) => {
2326                // The entity became visible. This is an addition.
2327                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                // The entity became invisible. This is a removal.
2335                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    // Make sure the `added_entities` list is sorted, as the
2346    // `DirtySpecializations` iterator will binary search it.
2347    if any_added {
2348        render_view_visible_mesh_entities.sort_added_entities();
2349    }
2350}
2351
2352/// A system that sets the [`RenderMeshInstanceFlags`] for each mesh based on
2353/// whether the previous frame had skins and/or morph targets.
2354///
2355/// Ordinarily, [`RenderMeshInstanceFlags`] are set during the extraction phase.
2356/// However, we can't do that for the flags related to skins and morph targets
2357/// because the previous frame's skin and morph targets are the responsibility
2358/// of [`extract_skins`] and [`extract_morphs`] respectively. We want to run
2359/// those systems in parallel with mesh extraction for performance, so we need
2360/// to defer setting of these mesh instance flags to after extraction, which
2361/// this system does. An alternative to having skin- and morph-target-related
2362/// data in [`RenderMeshInstanceFlags`] would be to have
2363/// [`crate::material::queue_material_meshes`] check the skin and morph target
2364/// tables for each mesh, but that would be too slow in the hot mesh queuing
2365/// loop.
2366pub 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    // Set `HAS_PREVIOUS_SKIN` if the mesh has skin weights from the previous
2372    // frame.
2373    for &entity in skin_uniforms.all_skins() {
2374        render_mesh_instances
2375            .insert_mesh_instance_flags(entity, RenderMeshInstanceFlags::HAS_PREVIOUS_SKIN);
2376    }
2377
2378    // Set `HAS_PREVIOUS_MORPH` if the mesh has morph targets from the previous
2379    // frame.
2380    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
2405/// Creates the [`RenderMeshInstanceGpu`]s and [`MeshInputUniform`]s when GPU
2406/// preprocessing is in use.
2407pub 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    // We're going to rebuild `meshes_to_reextract_next_frame`.
2431    meshes_to_reextract_next_frame.clear();
2432
2433    // Collect render mesh instances. Build up the uniform buffer.
2434    let gpu_preprocessing::BatchedInstanceBuffers {
2435        current_input_buffer,
2436        previous_input_buffer,
2437        ..
2438    } = batched_instance_buffers.into_inner();
2439
2440    // Make sure the mesh culling data buffer has enough space.
2441    if !current_input_buffer.is_empty() {
2442        mesh_culling_data_buffer.grow(current_input_buffer.len() as u32);
2443    }
2444
2445    // Pre-allocate the previous input buffer for concurrent pushes.
2446    previous_input_buffer.reserve(current_input_buffer.len() as u32);
2447
2448    // We're going to build up the added, removed, and layers-changed lists on
2449    // `RenderGpuCulledEntities`, so clear them out.
2450    render_gpu_culled_entities.prepare_for_new_frame();
2451
2452    // Channels used by parallel workers to send data to the single consumer.
2453    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        // Reference data shared between tasks
2459        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        // Spawn workers on the taskpool to prepare and update meshes in parallel.
2472        ComputeTaskPool::get().scope(|scope| {
2473            // Iterate through each queue, spawning a task for each queue. This loop completes quickly
2474            // as it does very little work, it is just spawning and moving data into tasks in a loop.
2475            for queue in render_mesh_instance_queues.iter_mut() {
2476                match *queue {
2477                    RenderMeshInstanceGpuQueue::None => {
2478                        // This can only happen if the queue is empty.
2479                    }
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                                    // We must take the slow path because we
2552                                    // haven't seen the mesh instance yet. Send
2553                                    // the mesh instance to the collection sink.
2554                                    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                                    // We must take the slow path because the
2573                                    // instance either changed render layers or
2574                                    // CPU/GPU culling mode. Send the mesh
2575                                    // instance to the collection sink.
2576                                    let _ = prepared_tx.send((
2577                                        entity,
2578                                        prepared,
2579                                        Some(mesh_culling_builder),
2580                                    ));
2581                                    continue;
2582                                }
2583
2584                                // If we got here, we can take a fast path and
2585                                // write directly to shared memory, since the
2586                                // only fields that changed are POD fields.
2587
2588                                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 the senders owned by the scope, so the only senders left are those captured by the
2615            // spawned tasks. When the tasks are complete, the channels will close, and the consumer
2616            // will finish. Without this, the scope would deadlock on the blocked consumer.
2617            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        // If the instance is already visible, just update the layers.
2635        // Otherwise, mark it as newly-added.
2636        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    // Buffers can't be empty. Make sure there's something in the previous input buffer.
2661    previous_input_buffer.ensure_nonempty();
2662}
2663
2664/// All data needed to construct a pipeline for rendering 3D meshes.
2665#[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    /// A reference to all the mesh pipeline view layouts.
2668    pub view_layouts: MeshPipelineViewLayouts,
2669    pub clustered_forward_buffer_binding_type: BufferBindingType,
2670    pub mesh_layouts: MeshLayouts,
2671    /// The shader asset handle.
2672    pub shader: Handle<Shader>,
2673    /// `MeshUniform`s are stored in arrays in buffers. If storage buffers are available, they
2674    /// are used and this will be `None`, otherwise uniform buffers will be used with batches
2675    /// of this many `MeshUniform`s, stored at dynamic offsets within the uniform buffer.
2676    /// Use code like this in custom shaders:
2677    /// ```wgsl
2678    /// ##ifdef PER_OBJECT_BUFFER_BATCH_SIZE
2679    /// @group(1) @binding(0) var<uniform> mesh: array<Mesh, #{PER_OBJECT_BUFFER_BATCH_SIZE}u>;
2680    /// ##else
2681    /// @group(1) @binding(0) var<storage> mesh: array<Mesh>;
2682    /// ##endif // PER_OBJECT_BUFFER_BATCH_SIZE
2683    /// ```
2684    pub per_object_buffer_batch_size: Option<u32>,
2685
2686    /// Whether binding arrays (a.k.a. bindless textures) are usable on the
2687    /// current render device.
2688    ///
2689    /// This affects whether reflection probes can be used.
2690    pub binding_arrays_are_usable: bool,
2691
2692    /// Whether clustered decals are usable on the current render device.
2693    pub clustered_decals_are_usable: bool,
2694
2695    /// Whether skins will use uniform buffers on account of storage buffers
2696    /// being unavailable on this platform.
2697    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
2737/// A 1x1x1 'all 1.0' texture to use as a dummy texture in place of optional [`crate::pbr_material::StandardMaterial`] textures
2738pub 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/// Data that must be identical for meshes to be multi-drawn together.
2793#[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    /// The bind group for the material.
2796    material_bind_group_index: MaterialBindGroupIndex,
2797    /// The slabs that the mesh data is stored in.
2798    mesh_slabs: MeshSlabs,
2799    /// The bindless slab that stores the lightmap for this mesh, if applicable.
2800    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        // This should only be called during GPU building.
2879        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        // This should only be called during GPU building.
2944        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 {
            /// Get a flags value with all bits unset.
            #[inline]
            pub const fn empty() -> Self {
                Self(<u64 as ::bitflags::Bits>::EMPTY)
            }
            /// Get a flags value with all known bits set.
            #[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)
            }
            /// Get the underlying bits value.
            ///
            /// The returned value is exactly the bits set in this flags value.
            #[inline]
            pub const fn bits(&self) -> u64 { self.0 }
            /// Convert from a bits value.
            ///
            /// This method will return `None` if any unknown bits are set.
            #[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 }
            }
            /// Convert from a bits value, unsetting any unknown bits.
            #[inline]
            pub const fn from_bits_truncate(bits: u64) -> Self {
                Self(bits & Self::all().0)
            }
            /// Convert from a bits value exactly.
            #[inline]
            pub const fn from_bits_retain(bits: u64) -> Self { Self(bits) }
            /// Get a flags value with the bits of a flag with the given name set.
            ///
            /// This method will return `None` if `name` is empty or doesn't
            /// correspond to any named flag.
            #[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
            }
            /// Whether all bits in `self` are unset.
            #[inline]
            pub const fn is_empty(&self) -> bool {
                self.0 == <u64 as ::bitflags::Bits>::EMPTY
            }
            /// Whether all known bits in this flags value are set.
            #[inline]
            pub const fn is_all(&self) -> bool {
                Self::all().0 | self.0 == self.0
            }
            /// Whether any set bits in `other` are also set in `self`.
            #[inline]
            pub const fn intersects(&self, other: Self) -> bool {
                self.0 & other.0 != <u64 as ::bitflags::Bits>::EMPTY
            }
            /// Whether all set bits in `other` are also set in `self`.
            #[inline]
            pub const fn contains(&self, other: Self) -> bool {
                self.0 & other.0 == other.0
            }
            /// The bitwise or (`|`) of the bits in `self` and `other`.
            #[inline]
            pub fn insert(&mut self, other: Self) {
                *self = Self(self.0).union(other);
            }
            /// The intersection of `self` with the complement of `other` (`&!`).
            ///
            /// This method is not equivalent to `self & !other` when `other` has unknown bits set.
            /// `remove` won't truncate `other`, but the `!` operator will.
            #[inline]
            pub fn remove(&mut self, other: Self) {
                *self = Self(self.0).difference(other);
            }
            /// The bitwise exclusive-or (`^`) of the bits in `self` and `other`.
            #[inline]
            pub fn toggle(&mut self, other: Self) {
                *self = Self(self.0).symmetric_difference(other);
            }
            /// Call `insert` when `value` is `true` or `remove` when `value` is `false`.
            #[inline]
            pub fn set(&mut self, other: Self, value: bool) {
                if value { self.insert(other); } else { self.remove(other); }
            }
            /// The bitwise and (`&`) of the bits in `self` and `other`.
            #[inline]
            #[must_use]
            pub const fn intersection(self, other: Self) -> Self {
                Self(self.0 & other.0)
            }
            /// The bitwise or (`|`) of the bits in `self` and `other`.
            #[inline]
            #[must_use]
            pub const fn union(self, other: Self) -> Self {
                Self(self.0 | other.0)
            }
            /// The intersection of `self` with the complement of `other` (`&!`).
            ///
            /// This method is not equivalent to `self & !other` when `other` has unknown bits set.
            /// `difference` won't truncate `other`, but the `!` operator will.
            #[inline]
            #[must_use]
            pub const fn difference(self, other: Self) -> Self {
                Self(self.0 & !other.0)
            }
            /// The bitwise exclusive-or (`^`) of the bits in `self` and `other`.
            #[inline]
            #[must_use]
            pub const fn symmetric_difference(self, other: Self) -> Self {
                Self(self.0 ^ other.0)
            }
            /// The bitwise negation (`!`) of the bits in `self`, truncating the result.
            #[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;
            /// The bitwise or (`|`) of the bits in `self` and `other`.
            #[inline]
            fn bitor(self, other: InternalBitFlags) -> Self {
                self.union(other)
            }
        }
        impl ::bitflags::__private::core::ops::BitOrAssign for
            InternalBitFlags {
            /// The bitwise or (`|`) of the bits in `self` and `other`.
            #[inline]
            fn bitor_assign(&mut self, other: Self) { self.insert(other); }
        }
        impl ::bitflags::__private::core::ops::BitXor for InternalBitFlags {
            type Output = Self;
            /// The bitwise exclusive-or (`^`) of the bits in `self` and `other`.
            #[inline]
            fn bitxor(self, other: Self) -> Self {
                self.symmetric_difference(other)
            }
        }
        impl ::bitflags::__private::core::ops::BitXorAssign for
            InternalBitFlags {
            /// The bitwise exclusive-or (`^`) of the bits in `self` and `other`.
            #[inline]
            fn bitxor_assign(&mut self, other: Self) { self.toggle(other); }
        }
        impl ::bitflags::__private::core::ops::BitAnd for InternalBitFlags {
            type Output = Self;
            /// The bitwise and (`&`) of the bits in `self` and `other`.
            #[inline]
            fn bitand(self, other: Self) -> Self { self.intersection(other) }
        }
        impl ::bitflags::__private::core::ops::BitAndAssign for
            InternalBitFlags {
            /// The bitwise and (`&`) of the bits in `self` and `other`.
            #[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;
            /// The intersection of `self` with the complement of `other` (`&!`).
            ///
            /// This method is not equivalent to `self & !other` when `other` has unknown bits set.
            /// `difference` won't truncate `other`, but the `!` operator will.
            #[inline]
            fn sub(self, other: Self) -> Self { self.difference(other) }
        }
        impl ::bitflags::__private::core::ops::SubAssign for InternalBitFlags
            {
            /// The intersection of `self` with the complement of `other` (`&!`).
            ///
            /// This method is not equivalent to `self & !other` when `other` has unknown bits set.
            /// `difference` won't truncate `other`, but the `!` operator will.
            #[inline]
            fn sub_assign(&mut self, other: Self) { self.remove(other); }
        }
        impl ::bitflags::__private::core::ops::Not for InternalBitFlags {
            type Output = Self;
            /// The bitwise negation (`!`) of the bits in `self`, truncating the result.
            #[inline]
            fn not(self) -> Self { self.complement() }
        }
        impl ::bitflags::__private::core::iter::Extend<InternalBitFlags> for
            InternalBitFlags {
            /// The bitwise or (`|`) of the bits in each flags value.
            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 {
            /// The bitwise or (`|`) of the bits in each flags value.
            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 {
            /// Yield a set of contained flags values.
            ///
            /// Each yielded flags value will correspond to a defined named flag. Any unknown bits
            /// will be yielded together as a final flags value.
            #[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()))
            }
            /// Yield a set of contained named flags values.
            ///
            /// This method is like [`iter`](#method.iter), except only yields bits in contained named flags.
            /// Any unknown bits, or bits not corresponding to a contained flag will not be yielded.
            #[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 {
            /// Returns a mutable reference to the raw value of the flags currently stored.
            #[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 {
            /// Get a flags value with all bits unset.
            #[inline]
            pub const fn empty() -> Self { Self(InternalBitFlags::empty()) }
            /// Get a flags value with all known bits set.
            #[inline]
            pub const fn all() -> Self { Self(InternalBitFlags::all()) }
            /// Get the underlying bits value.
            ///
            /// The returned value is exactly the bits set in this flags value.
            #[inline]
            pub const fn bits(&self) -> u64 { self.0.bits() }
            /// Convert from a bits value.
            ///
            /// This method will return `None` if any unknown bits are set.
            #[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,
                }
            }
            /// Convert from a bits value, unsetting any unknown bits.
            #[inline]
            pub const fn from_bits_truncate(bits: u64) -> Self {
                Self(InternalBitFlags::from_bits_truncate(bits))
            }
            /// Convert from a bits value exactly.
            #[inline]
            pub const fn from_bits_retain(bits: u64) -> Self {
                Self(InternalBitFlags::from_bits_retain(bits))
            }
            /// Get a flags value with the bits of a flag with the given name set.
            ///
            /// This method will return `None` if `name` is empty or doesn't
            /// correspond to any named flag.
            #[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,
                }
            }
            /// Whether all bits in `self` are unset.
            #[inline]
            pub const fn is_empty(&self) -> bool { self.0.is_empty() }
            /// Whether all known bits in this flags value are set.
            #[inline]
            pub const fn is_all(&self) -> bool { self.0.is_all() }
            /// Whether any set bits in `other` are also set in `self`.
            #[inline]
            pub const fn intersects(&self, other: Self) -> bool {
                self.0.intersects(other.0)
            }
            /// Whether all set bits in `other` are also set in `self`.
            #[inline]
            pub const fn contains(&self, other: Self) -> bool {
                self.0.contains(other.0)
            }
            /// The bitwise or (`|`) of the bits in `self` and `other`.
            #[inline]
            pub fn insert(&mut self, other: Self) { self.0.insert(other.0) }
            /// The intersection of `self` with the complement of `other` (`&!`).
            ///
            /// This method is not equivalent to `self & !other` when `other` has unknown bits set.
            /// `remove` won't truncate `other`, but the `!` operator will.
            #[inline]
            pub fn remove(&mut self, other: Self) { self.0.remove(other.0) }
            /// The bitwise exclusive-or (`^`) of the bits in `self` and `other`.
            #[inline]
            pub fn toggle(&mut self, other: Self) { self.0.toggle(other.0) }
            /// Call `insert` when `value` is `true` or `remove` when `value` is `false`.
            #[inline]
            pub fn set(&mut self, other: Self, value: bool) {
                self.0.set(other.0, value)
            }
            /// The bitwise and (`&`) of the bits in `self` and `other`.
            #[inline]
            #[must_use]
            pub const fn intersection(self, other: Self) -> Self {
                Self(self.0.intersection(other.0))
            }
            /// The bitwise or (`|`) of the bits in `self` and `other`.
            #[inline]
            #[must_use]
            pub const fn union(self, other: Self) -> Self {
                Self(self.0.union(other.0))
            }
            /// The intersection of `self` with the complement of `other` (`&!`).
            ///
            /// This method is not equivalent to `self & !other` when `other` has unknown bits set.
            /// `difference` won't truncate `other`, but the `!` operator will.
            #[inline]
            #[must_use]
            pub const fn difference(self, other: Self) -> Self {
                Self(self.0.difference(other.0))
            }
            /// The bitwise exclusive-or (`^`) of the bits in `self` and `other`.
            #[inline]
            #[must_use]
            pub const fn symmetric_difference(self, other: Self) -> Self {
                Self(self.0.symmetric_difference(other.0))
            }
            /// The bitwise negation (`!`) of the bits in `self`, truncating the result.
            #[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;
            /// The bitwise or (`|`) of the bits in `self` and `other`.
            #[inline]
            fn bitor(self, other: MeshPipelineKey) -> Self {
                self.union(other)
            }
        }
        impl ::bitflags::__private::core::ops::BitOrAssign for MeshPipelineKey
            {
            /// The bitwise or (`|`) of the bits in `self` and `other`.
            #[inline]
            fn bitor_assign(&mut self, other: Self) { self.insert(other); }
        }
        impl ::bitflags::__private::core::ops::BitXor for MeshPipelineKey {
            type Output = Self;
            /// The bitwise exclusive-or (`^`) of the bits in `self` and `other`.
            #[inline]
            fn bitxor(self, other: Self) -> Self {
                self.symmetric_difference(other)
            }
        }
        impl ::bitflags::__private::core::ops::BitXorAssign for
            MeshPipelineKey {
            /// The bitwise exclusive-or (`^`) of the bits in `self` and `other`.
            #[inline]
            fn bitxor_assign(&mut self, other: Self) { self.toggle(other); }
        }
        impl ::bitflags::__private::core::ops::BitAnd for MeshPipelineKey {
            type Output = Self;
            /// The bitwise and (`&`) of the bits in `self` and `other`.
            #[inline]
            fn bitand(self, other: Self) -> Self { self.intersection(other) }
        }
        impl ::bitflags::__private::core::ops::BitAndAssign for
            MeshPipelineKey {
            /// The bitwise and (`&`) of the bits in `self` and `other`.
            #[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;
            /// The intersection of `self` with the complement of `other` (`&!`).
            ///
            /// This method is not equivalent to `self & !other` when `other` has unknown bits set.
            /// `difference` won't truncate `other`, but the `!` operator will.
            #[inline]
            fn sub(self, other: Self) -> Self { self.difference(other) }
        }
        impl ::bitflags::__private::core::ops::SubAssign for MeshPipelineKey {
            /// The intersection of `self` with the complement of `other` (`&!`).
            ///
            /// This method is not equivalent to `self & !other` when `other` has unknown bits set.
            /// `difference` won't truncate `other`, but the `!` operator will.
            #[inline]
            fn sub_assign(&mut self, other: Self) { self.remove(other); }
        }
        impl ::bitflags::__private::core::ops::Not for MeshPipelineKey {
            type Output = Self;
            /// The bitwise negation (`!`) of the bits in `self`, truncating the result.
            #[inline]
            fn not(self) -> Self { self.complement() }
        }
        impl ::bitflags::__private::core::iter::Extend<MeshPipelineKey> for
            MeshPipelineKey {
            /// The bitwise or (`|`) of the bits in each flags value.
            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 {
            /// The bitwise or (`|`) of the bits in each flags value.
            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 {
            /// Yield a set of contained flags values.
            ///
            /// Each yielded flags value will correspond to a defined named flag. Any unknown bits
            /// will be yielded together as a final flags value.
            #[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()))
            }
            /// Yield a set of contained named flags values.
            ///
            /// This method is like [`iter`](#method.iter), except only yields bits in contained named flags.
            /// Any unknown bits, or bits not corresponding to a contained flag will not be yielded.
            #[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    // NOTE: Apparently quadro drivers support up to 64x MSAA.
2988    // MSAA uses the highest 3 bits for the MSAA log2(sample count) to support up to 128x MSAA.
2989    pub struct MeshPipelineKey: u64 {
2990        // Nothing
2991        const NONE                              = 0;
2992
2993        // Inherited bits
2994        const MORPH_TARGETS                     = BaseMeshPipelineKey::MORPH_TARGETS.bits();
2995
2996        // Flag bits
2997        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; // Guards shader codepaths that may discard, allowing early depth tests in most cases
3004                                                            // See: https://www.khronos.org/opengl/wiki/Early_Fragment_Test
3005        const ENVIRONMENT_MAP                   = 1 << 7;
3006        const SCREEN_SPACE_AMBIENT_OCCLUSION    = 1 << 8;
3007        const UNCLIPPED_DEPTH_ORTHO             = 1 << 9; // Disables depth clipping for use with directional light shadow views
3008                                                            // Emulated via fragment shader depth on hardware that doesn't support it natively
3009                                                            // See: https://www.w3.org/TR/webgpu/#depth-clipping and https://therealmjp.github.io/posts/shadow-maps/#disabling-z-clipping
3010        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        // Bitfields
3035        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; // ← Bitmask reserving bits for the blend state
3037        const BLEND_OPAQUE                      = 0 << Self::BLEND_SHIFT_BITS;                     // ← Values are just sequential within the mask
3038        const BLEND_PREMULTIPLIED_ALPHA         = 1 << Self::BLEND_SHIFT_BITS;                     // ← As blend states is on 3 bits, it can range from 0 to 7
3039        const BLEND_MULTIPLY                    = 2 << Self::BLEND_SHIFT_BITS;                     // ← See `BLEND_MASK_BITS` for the number of bits available
3040        const BLEND_ALPHA                       = 3 << Self::BLEND_SHIFT_BITS;                     //
3041        const BLEND_ALPHA_TO_COVERAGE           = 4 << Self::BLEND_SHIFT_BITS;                     // ← We still have room for three more values without adding more bits
3042        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    /// Create a pipeline key from the view's color target format.
3115    #[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    /// Color target format of the main pass for this pipeline key.
3125    #[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    /// Create a [`BaseMeshPipelineKey`] from mesh primitive topology and index format.
3138    ///
3139    /// For non-strip topologies, [`BaseMeshPipelineKey::STRIP_INDEX_FORMAT_NONE`] is set regardless of the `strip_index_format` argument.
3140    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// Ensure that we didn't overflow the number of bits available in `MeshPipelineKey`.
3204#[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// Ensure that the bits of `BaseMeshPipelineKey` don't overlap with the bits of `MeshPipelineKey`
3211// except the inherited bits.
3212#[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        // Let the shader code know that it's running in a mesh pipeline.
3293        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            // TODO tail blending would need alpha blending
3387            blend = None;
3388            shader_defs.push("OIT_ENABLED".into());
3389            // TODO it should be possible to use this to combine MSAA and OIT
3390            // alpha_to_coverage_enabled = true;
3391            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            // For the transparent pass, fragments that are closer will be alpha blended
3396            // but their depth is not written to the depth buffer
3397            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            // For the transparent pass, fragments that are closer will be alpha blended
3404            // but their depth is not written to the depth buffer
3405            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            // For the multiply pass, fragments that are closer will be alpha blended
3419            // but their depth is not written to the depth buffer
3420            depth_write_enabled = false;
3421        } else if pass == MeshPipelineKey::BLEND_ALPHA_TO_COVERAGE {
3422            label = "alpha_to_coverage_mesh_pipeline".into();
3423            // BlendState::REPLACE is not needed here, and None will be potentially much faster in some cases
3424            blend = None;
3425            // For the opaque and alpha mask passes, fragments that are closer will replace
3426            // the current fragment value in the output and the depth is written to the
3427            // depth buffer
3428            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            // BlendState::REPLACE is not needed here, and None will be potentially much faster in some cases
3435            blend = None;
3436            // For the opaque and alpha mask passes, fragments that are closer will replace
3437            // the current fragment value in the output and the depth is written to the
3438            // depth buffer
3439            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            // Debanding is tied to tonemapping in the shader, cannot run without it.
3520            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!(), // Not possible, since the mask is 2 bits, and we've covered all 4 cases
3569            },
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        // This is defined here so that custom shaders that use something other than
3603        // the mesh binding from bevy_pbr::mesh_bindings can easily make use of this
3604        // in their own shaders.
3605        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
3664/// The bind groups for meshes currently loaded.
3665///
3666/// If GPU mesh preprocessing isn't in use, these are global to the scene. If
3667/// GPU mesh preprocessing is in use, these are specific to a single phase.
3668pub struct MeshPhaseBindGroups {
3669    model_only: Option<BindGroup>,
3670    skinned: Option<MeshBindGroupPair>,
3671    /// Bind groups for meshes with morph targets.
3672    morph_targets: MeshMorphTargetBindGroups,
3673    lightmaps: HashMap<LightmapSlabIndex, BindGroup>,
3674}
3675
3676/// Stores bind groups for each mesh with morph targets.
3677///
3678/// If storage buffers aren't available on this platform, we use a single bind
3679/// group per mesh. If they are available, however, we use a single bind group
3680/// per morph target slab ID (managed by the mesh allocator).
3681pub enum MeshMorphTargetBindGroups {
3682    /// Maps a mesh asset ID to the bind group for that mesh.
3683    ///
3684    /// We use morph target images on platforms without storage buffers, and as
3685    /// such platforms don't support bindless textures either, we must use a
3686    /// single bind group per morphable mesh.
3687    Uniform(HashMap<AssetId<Mesh>, MeshBindGroupPair>),
3688
3689    /// Maps a morph target slab ID that the mesh allocator manages to the bind
3690    /// groups for morph displacements in that slab.
3691    Storage(HashMap<MeshSlabId, MeshMorphTargetStorageBindGroups>),
3692}
3693
3694/// The bind groups associated with a single morph displacements slab.
3695///
3696/// Because a single morph displacement slab might contain morph displacements
3697/// for both meshes with skins and meshes without skins, we need two separate
3698/// bind groups here.
3699pub struct MeshMorphTargetStorageBindGroups {
3700    /// The bind group used for meshes with skins.
3701    skinned: Option<MeshBindGroupPair>,
3702    /// The bind group used for meshes without skins.
3703    unskinned: Option<MeshBindGroupPair>,
3704}
3705
3706impl MeshMorphTargetBindGroups {
3707    /// Clears out all morph target bind groups.
3708    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/// All bind groups for meshes currently loaded.
3726#[derive(impl bevy_ecs::resource::Resource for MeshBindGroups where
    Self: ::core::marker::Send + ::core::marker::Sync + 'static {}Resource)]
3727pub enum MeshBindGroups {
3728    /// The bind groups for the meshes for the entire scene, if GPU mesh
3729    /// preprocessing isn't in use.
3730    CpuPreprocessing(MeshPhaseBindGroups),
3731    /// A mapping from the type ID of a phase (e.g. [`Opaque3d`]) to the mesh
3732    /// bind groups for that phase.
3733    GpuPreprocessing(TypeIdMap<MeshPhaseBindGroups>),
3734}
3735
3736impl MeshPhaseBindGroups {
3737    /// Creates a new, blank, set of bind groups for this phase.
3738    ///
3739    /// Bind groups must be added to the resulting [`MeshPhaseBindGroups`]
3740    /// explicitly.
3741    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    /// Get the appropriate `BindGroup` for `RenderMesh` with the given keys.
3762    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/// Data related to morph targets that we need in order to look up the bind
3828/// group for a mesh.
3829#[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    /// The mesh has no morph targets.
3832    NoMorphTargets,
3833    /// The mesh has morph targets, and the current platform doesn't support
3834    /// storage buffers.
3835    ///
3836    /// In this case, there's a single bind group per mesh.
3837    Uniform(AssetId<Mesh>),
3838    /// The mesh has morph targets, and the current platform does support
3839    /// storage buffers.
3840    ///
3841    /// In this case, there's a bind group per morph displacement slab (managed
3842    /// by the mesh allocator).
3843    Storage(MeshSlabId),
3844}
3845
3846/// Creates the per-mesh bind groups for each type of mesh and each phase.
3847pub 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    // CPU mesh preprocessing path.
3866    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        // In this path, we only have a single set of bind groups for all phases.
3872        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    // GPU mesh preprocessing path.
3892    if let Some(gpu_batched_instance_buffers) = gpu_batched_instance_buffers {
3893        let mut gpu_preprocessing_mesh_bind_groups = TypeIdMap::default();
3894
3895        // Loop over each phase.
3896        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
3927/// Creates the per-mesh bind groups for each type of mesh, for a single phase.
3928fn 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    // TODO: Reuse allocations.
3943    let mut groups = MeshPhaseBindGroups {
3944        model_only: Some(layouts.model_only(render_device, pipeline_cache, &model)),
3945        ..MeshPhaseBindGroups::new(render_device)
3946    };
3947
3948    // Create the skinned mesh bind group with the current and previous buffers
3949    // (the latter being for motion vector computation).
3950    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    // Create the morphed bind groups just like we did for the skinned bind
3963    // group.
3964    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    // Create lightmap bindgroups. There will be one bindgroup for each slab.
4008    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
4025/// Creates per-mesh morph target bind groups for a single phase.
4026///
4027/// This function is only used when the platform doesn't support storage
4028/// buffers.
4029fn 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
4107/// Creates per-slab morph target bind groups for a single phase.
4108///
4109/// This function is only used when the platform supports storage buffers.
4110fn 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        // Determine which morph bind group key we need, if any. If the platform
4295        // doesn't support storage buffers, there's a separate bind group per
4296        // mesh. Otherwise, if the platform does support storage buffers,
4297        // there's one bind group per morph target displacement slab (managed by
4298        // the mesh allocator).
4299        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            // This is harmless if e.g. we're rendering the `Shadow` phase and
4344            // there weren't any shadows.
4345            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        // Attach motion vectors if needed.
4379        if skins_use_uniform_buffers && has_motion_vector_prepass {
4380            // Attach the previous skin index for motion vector computation.
4381            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            // Attach the previous morph index for motion vector computation. If
4387            // there isn't one, just use zero as the shader will ignore it.
4388            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 we're using GPU preprocessing, then we're dependent on that
4435        // compute shader having been run, which of course can only happen if
4436        // it's compiled. Otherwise, our mesh instance data won't be present.
4437        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        // Draw either directly or indirectly, as appropriate. If we're in
4465        // indirect mode, we can additionally multi-draw. (We can't multi-draw
4466        // in direct mode because `wgpu` doesn't expose that functionality.)
4467        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                        // Look up the indirect parameters buffer, as well as
4493                        // the buffer we're going to use for
4494                        // `multi_draw_indexed_indirect_count` (if available).
4495                        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                        // Calculate the location of the indirect parameters
4518                        // within the buffer.
4519                        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                        // If we're using `multi_draw_indirect_count`, take the
4525                        // number of batches from the appropriate position in
4526                        // the batch sets buffer. Otherwise, supply the size of
4527                        // the batch set.
4528                        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                    // Look up the indirect parameters buffer, as well as the
4561                    // buffer we're going to use for
4562                    // `multi_draw_indirect_count` (if available).
4563                    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                    // Calculate the location of the indirect parameters within
4586                    // the buffer.
4587                    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                    // If we're using `multi_draw_indirect_count`, take the
4593                    // number of batches from the appropriate position in the
4594                    // batch sets buffer. Otherwise, supply the size of the
4595                    // batch set.
4596                    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    /// Tests that the `AtomicU64ZeroBitIter` works.
4637    #[test]
4638    fn atomic_u64_zero_bit_iter() {
4639        // Randomly-generated test data.
4640        // We use separate constants for this because the Rust compiler
4641        // complains if you make a static array of slices containing atomics.
4642        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            // Compute the zero positions naively.
4703            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            // Compute the zero positions using the iterator.
4714            let test_zero_positions: Vec<_> = AtomicU64ZeroBitIter::new(bits).collect();
4715
4716            // Check for equality.
4717            assert_eq!(test_zero_positions, reference_zero_positions);
4718        }
4719    }
4720}