Skip to main content

bevy_render/
lib.rs

1//! # Useful Environment Variables
2//!
3//! Both `bevy_render` and `wgpu` have a number of environment variable options for changing the runtime behavior
4//! of both crates. Many of these may be useful in development or release environments.
5//!
6//! - `WGPU_DEBUG=1` enables debug labels, which can be useful in release builds.
7//! - `WGPU_VALIDATION=0` disables validation layers. This can help with particularly spammy errors.
8//! - `WGPU_FORCE_FALLBACK_ADAPTER=1` attempts to force software rendering. This typically matches what is used in CI.
9//! - `WGPU_ADAPTER_NAME` allows selecting a specific adapter by name.
10//! - `WGPU_SETTINGS_PRIO=webgl2` uses webgl2 limits.
11//! - `WGPU_SETTINGS_PRIO=webgpu` uses webgpu limits.
12//! - `VERBOSE_SHADER_ERROR=1` prints more detailed information about WGSL compilation errors, such as shader defs and shader entrypoint.
13
14#![expect(missing_docs, reason = "Not all docs are written yet, see #3492.")]
15#![expect(unsafe_code, reason = "Unsafe code is used to improve performance.")]
16#![cfg_attr(
17    any(docsrs, docsrs_dep),
18    expect(
19        internal_features,
20        reason = "rustdoc_internals is needed for fake_variadic"
21    )
22)]
23#![cfg_attr(any(docsrs, docsrs_dep), feature(rustdoc_internals))]
24#![cfg_attr(docsrs, feature(doc_cfg))]
25#![doc(
26    html_logo_url = "https://bevy.org/assets/icon.png",
27    html_favicon_url = "https://bevy.org/assets/icon.png"
28)]
29
30#[cfg(target_pointer_width = "16")]
31compile_error!("bevy_render cannot compile for a 16-bit platform.");
32
33extern crate alloc;
34extern crate core;
35
36// Required to make proc macros work in bevy itself.
37extern crate self as bevy_render;
38
39pub mod batching;
40pub mod camera;
41pub mod diagnostic;
42pub mod erased_render_asset;
43pub mod error_handler;
44pub mod extract_component;
45pub mod extract_instances;
46mod extract_param;
47pub mod extract_plugin;
48pub mod extract_resource;
49pub mod globals;
50pub mod gpu_component_array_buffer;
51pub mod gpu_readback;
52pub mod mesh;
53pub mod occlusion_culling;
54#[cfg(not(target_arch = "wasm32"))]
55pub mod pipelined_rendering;
56pub mod render_asset;
57pub mod render_phase;
58pub mod render_resource;
59pub mod renderer;
60pub mod settings;
61pub mod slab_allocator;
62pub mod storage;
63pub mod sync_component;
64pub mod sync_world;
65#[cfg(test)]
66pub(crate) mod test_utils;
67pub mod texture;
68pub mod uniform;
69pub mod view;
70
71/// The render prelude.
72///
73/// This includes the most common types in this crate, re-exported for your convenience.
74pub mod prelude {
75    #[doc(hidden)]
76    pub use crate::{
77        camera::NormalizedRenderTargetExt as _, renderer::RenderGraph, texture::ManualTextureViews,
78        view::Msaa, ExtractSchedule,
79    };
80}
81
82pub use extract_param::Extract;
83pub use extract_plugin::{ExtractSchedule, MainWorld};
84
85use crate::{
86    camera::CameraPlugin,
87    error_handler::{RenderErrorHandler, RenderState},
88    extract_plugin::ExtractPlugin,
89    gpu_readback::GpuReadbackPlugin,
90    mesh::{MeshRenderAssetPlugin, RenderMesh},
91    render_asset::prepare_assets,
92    render_resource::{PipelineCache, SparseBufferPlugin},
93    renderer::{render_system, RenderAdapterInfo, RenderGraph},
94    settings::{RenderCreation, WgpuLimits},
95    storage::StoragePlugin,
96    texture::TexturePlugin,
97    view::{ViewPlugin, WindowRenderPlugin},
98};
99use alloc::sync::Arc;
100use batching::gpu_preprocessing::BatchingPlugin;
101use bevy_app::{App, AppLabel, First, Plugin, SubApp};
102use bevy_asset::{AssetApp, AssetServer};
103use bevy_derive::Deref;
104use bevy_ecs::{
105    prelude::*,
106    schedule::{InternedScheduleLabel, ScheduleLabel},
107};
108use bevy_platform::time::Instant;
109use bevy_shader::{load_shader_library, Shader, ShaderLoader};
110use bevy_time::TimeSender;
111use bevy_window::{PrimaryWindow, RawHandleWrapperHolder};
112use bitflags::bitflags;
113use globals::GlobalsPlugin;
114use occlusion_culling::OcclusionCullingPlugin;
115use render_asset::{
116    extract_render_asset_bytes_per_frame, reset_render_asset_bytes_per_frame,
117    RenderAssetBytesPerFrame, RenderAssetBytesPerFrameLimiter,
118};
119use settings::RenderResources;
120use std::sync::{Mutex, OnceLock};
121
122/// Contains the default Bevy rendering backend based on wgpu.
123///
124/// Rendering is done in a [`SubApp`], which exchanges data with the main app
125/// between main schedule iterations.
126///
127/// Rendering can be executed between iterations of the main schedule,
128/// or it can be executed in parallel with main schedule when
129/// [`PipelinedRenderingPlugin`](pipelined_rendering::PipelinedRenderingPlugin) is enabled.
130#[derive(#[automatically_derived]
impl ::core::default::Default for RenderPlugin {
    #[inline]
    fn default() -> RenderPlugin {
        RenderPlugin {
            render_creation: ::core::default::Default::default(),
            synchronous_pipeline_compilation: ::core::default::Default::default(),
            debug_flags: ::core::default::Default::default(),
        }
    }
}Default)]
131pub struct RenderPlugin {
132    pub render_creation: RenderCreation,
133    /// If `true`, disables asynchronous pipeline compilation.
134    /// This has no effect on macOS, Wasm, iOS, or without the `multi_threaded` feature.
135    pub synchronous_pipeline_compilation: bool,
136    /// Debugging flags that can optionally be set when constructing the renderer.
137    pub debug_flags: RenderDebugFlags,
138}
139
140bitflags! {
141    /// Debugging flags that can optionally be set when constructing the renderer.
142    #[derive(#[automatically_derived]
impl ::core::clone::Clone for RenderDebugFlags {
    #[inline]
    fn clone(&self) -> RenderDebugFlags {
        let _:
                ::core::clone::AssertParamIsClone<<RenderDebugFlags 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(u8);
        #[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<u8>;
                *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<u8>;
            }
        }
        #[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 RenderDebugFlags {
            #[doc =
            r" If true, this sets the `COPY_SRC` flag on indirect draw parameters"]
            #[doc = r" so that they can be read back to CPU."]
            #[doc = r""]
            #[doc =
            r" This is a debugging feature that may reduce performance. It"]
            #[doc = r" primarily exists for the `occlusion_culling` example."]
            pub const ALLOW_COPIES_FROM_INDIRECT_PARAMETERS: Self =
                Self::from_bits_retain(1);
        }
        impl ::bitflags::Flags for RenderDebugFlags {
            const FLAGS: &'static [::bitflags::Flag<RenderDebugFlags>] =
                {
                    mod __bitflags_flag_names {
                        use super::*;
                        pub(super) const ALLOW_COPIES_FROM_INDIRECT_PARAMETERS:
                            &'static str =
                            "ALLOW_COPIES_FROM_INDIRECT_PARAMETERS";
                    }
                    &[{
                                    ::bitflags::Flag::new(__bitflags_flag_names::ALLOW_COPIES_FROM_INDIRECT_PARAMETERS,
                                        RenderDebugFlags::ALLOW_COPIES_FROM_INDIRECT_PARAMETERS)
                                }]
                };
            type Bits = u8;
            fn bits(&self) -> u8 { RenderDebugFlags::bits(self) }
            fn from_bits_retain(bits: u8) -> RenderDebugFlags {
                RenderDebugFlags::from_bits_retain(bits)
            }
            fn all_named() -> RenderDebugFlags {
                const ALL_NAMED: u8 =
                    {
                        let mut truncated = <u8 as ::bitflags::Bits>::EMPTY;
                        let mut i = 0;
                        {
                            {
                                let flag =
                                    &<RenderDebugFlags as ::bitflags::Flags>::FLAGS[i];
                                if flag.is_named() {
                                    truncated = truncated | flag.value().bits();
                                }
                                i += 1;
                            }
                        };
                        let _ = i;
                        truncated
                    };
                RenderDebugFlags::from_bits_retain(ALL_NAMED)
            }
        }
        impl ::bitflags::__private::PublicFlags for RenderDebugFlags {
            type Primitive = u8;
            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}",
                            <u8 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(&RenderDebugFlags(*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::<RenderDebugFlags>(s).map(|flags|
                        flags.0)
            }
        }
        impl ::bitflags::__private::core::convert::AsRef<u8> for
            InternalBitFlags {
            fn as_ref(&self) -> &u8 { &self.0 }
        }
        impl ::bitflags::__private::core::convert::From<u8> for
            InternalBitFlags {
            fn from(bits: u8) -> Self { Self::from_bits_retain(bits) }
        }
        impl InternalBitFlags {
            /// Get a flags value with all bits unset.
            #[inline]
            pub const fn empty() -> Self {
                Self(<u8 as ::bitflags::Bits>::EMPTY)
            }
            /// Get a flags value with all known bits set.
            #[inline]
            pub const fn all() -> Self {
                const ALL: InternalBitFlags =
                    {
                        let mut truncated = <u8 as ::bitflags::Bits>::EMPTY;
                        let mut _i = 0;
                        {
                            {
                                truncated |=
                                    <RenderDebugFlags as
                                                    ::bitflags::Flags>::FLAGS[_i].value().bits();
                                _i += 1;
                            }
                        };
                        InternalBitFlags(truncated)
                    };
                ALL
            }
            /// Get the underlying bits value.
            ///
            /// The returned value is exactly the bits set in this flags value.
            #[inline]
            pub const fn bits(&self) -> u8 { 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: u8)
                -> ::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: u8) -> Self {
                Self(bits & Self::all().0)
            }
            /// Convert from a bits value exactly.
            #[inline]
            pub const fn from_bits_retain(bits: u8) -> 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 ALLOW_COPIES_FROM_INDIRECT_PARAMETERS:
                        &'static str =
                        "ALLOW_COPIES_FROM_INDIRECT_PARAMETERS";
                }
                {
                    {
                        if name ==
                                __bitflags_flag_names::ALLOW_COPIES_FROM_INDIRECT_PARAMETERS
                            {
                            return ::bitflags::__private::core::option::Option::Some(Self(RenderDebugFlags::ALLOW_COPIES_FROM_INDIRECT_PARAMETERS.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 == <u8 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 != <u8 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<RenderDebugFlags> {
                ::bitflags::iter::Iter::__private_const_new(<RenderDebugFlags
                        as ::bitflags::Flags>::FLAGS,
                    RenderDebugFlags::from_bits_retain(self.bits()),
                    RenderDebugFlags::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<RenderDebugFlags> {
                ::bitflags::iter::IterNames::__private_const_new(<RenderDebugFlags
                        as ::bitflags::Flags>::FLAGS,
                    RenderDebugFlags::from_bits_retain(self.bits()),
                    RenderDebugFlags::from_bits_retain(self.bits()))
            }
        }
        impl ::bitflags::__private::core::iter::IntoIterator for
            InternalBitFlags {
            type Item = RenderDebugFlags;
            type IntoIter = ::bitflags::iter::Iter<RenderDebugFlags>;
            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 u8 { &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(&RenderDebugFlags::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: RenderDebugFlags =
                    ::bitflags::serde::deserialize(deserializer)?;
                ::bitflags::__private::core::result::Result::Ok(flags.0)
            }
        }
        impl RenderDebugFlags {
            /// 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) -> u8 { 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: u8)
                -> ::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: u8) -> Self {
                Self(InternalBitFlags::from_bits_truncate(bits))
            }
            /// Convert from a bits value exactly.
            #[inline]
            pub const fn from_bits_retain(bits: u8) -> 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 RenderDebugFlags {
            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 RenderDebugFlags {
            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 RenderDebugFlags {
            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 RenderDebugFlags {
            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 RenderDebugFlags {
            type Output = Self;
            /// The bitwise or (`|`) of the bits in `self` and `other`.
            #[inline]
            fn bitor(self, other: RenderDebugFlags) -> Self {
                self.union(other)
            }
        }
        impl ::bitflags::__private::core::ops::BitOrAssign for
            RenderDebugFlags {
            /// 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 RenderDebugFlags {
            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
            RenderDebugFlags {
            /// 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 RenderDebugFlags {
            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
            RenderDebugFlags {
            /// 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 RenderDebugFlags {
            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 RenderDebugFlags
            {
            /// 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 RenderDebugFlags {
            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<RenderDebugFlags> for
            RenderDebugFlags {
            /// 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<RenderDebugFlags>
            for RenderDebugFlags {
            /// 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 RenderDebugFlags {
            /// 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<RenderDebugFlags> {
                ::bitflags::iter::Iter::__private_const_new(<RenderDebugFlags
                        as ::bitflags::Flags>::FLAGS,
                    RenderDebugFlags::from_bits_retain(self.bits()),
                    RenderDebugFlags::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<RenderDebugFlags> {
                ::bitflags::iter::IterNames::__private_const_new(<RenderDebugFlags
                        as ::bitflags::Flags>::FLAGS,
                    RenderDebugFlags::from_bits_retain(self.bits()),
                    RenderDebugFlags::from_bits_retain(self.bits()))
            }
        }
        impl ::bitflags::__private::core::iter::IntoIterator for
            RenderDebugFlags {
            type Item = RenderDebugFlags;
            type IntoIter = ::bitflags::iter::Iter<RenderDebugFlags>;
            fn into_iter(self) -> Self::IntoIter { self.iter() }
        }
    };Clone, #[automatically_derived]
impl ::core::marker::Copy for RenderDebugFlags { }Copy, #[automatically_derived]
impl ::core::cmp::PartialEq for RenderDebugFlags {
    #[inline]
    fn eq(&self, other: &RenderDebugFlags) -> bool { self.0 == other.0 }
}PartialEq, #[automatically_derived]
impl ::core::default::Default for RenderDebugFlags {
    #[inline]
    fn default() -> RenderDebugFlags {
        RenderDebugFlags(::core::default::Default::default())
    }
}Default, #[automatically_derived]
impl ::core::fmt::Debug for RenderDebugFlags {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_tuple_field1_finish(f,
            "RenderDebugFlags", &&self.0)
    }
}Debug)]
143    pub struct RenderDebugFlags: u8 {
144        /// If true, this sets the `COPY_SRC` flag on indirect draw parameters
145        /// so that they can be read back to CPU.
146        ///
147        /// This is a debugging feature that may reduce performance. It
148        /// primarily exists for the `occlusion_culling` example.
149        const ALLOW_COPIES_FROM_INDIRECT_PARAMETERS = 1;
150    }
151}
152
153/// The systems sets of the default [`App`] rendering schedule.
154///
155/// These can be useful for ordering, but you almost never want to add your systems to these sets.
156#[derive(#[automatically_derived]
impl ::core::fmt::Debug for RenderSystems {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        static __NAMES: &str =
            "ExtractCommandsPrepareAssetsPrepareMeshesCreateViewsSpecializePrepareViewsQueueQueueMeshesQueueSweepPhaseSortPreparePrepareResourcesPrepareResourcesBatchPhasesPrepareResourcesWritePhaseBuffersPrepareResourcesCollectPhaseBuffersPrepareResourcesFlushPrepareBindGroupsRenderCleanupPostCleanup";
        static __OFFSET: [usize; 21] =
            [0usize, 15usize, 28usize, 41usize, 52usize, 62usize, 74usize,
                    79usize, 90usize, 100usize, 109usize, 116usize, 132usize,
                    159usize, 192usize, 227usize, 248usize, 265usize, 271usize,
                    278usize, 289usize];
        let __d = ::core::intrinsics::discriminant_value(self) as usize;
        ::core::fmt::Formatter::debug_c_like_enum_write_str(f, __NAMES,
            &__OFFSET, __d)
    }
}Debug, #[automatically_derived]
impl ::core::hash::Hash for RenderSystems {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state)
    }
}Hash, #[automatically_derived]
impl ::core::cmp::PartialEq for RenderSystems {
    #[inline]
    fn eq(&self, other: &RenderSystems) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for RenderSystems {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {}
}Eq, #[automatically_derived]
impl ::core::clone::Clone for RenderSystems {
    #[inline]
    fn clone(&self) -> RenderSystems {
        match self {
            RenderSystems::ExtractCommands => RenderSystems::ExtractCommands,
            RenderSystems::PrepareAssets => RenderSystems::PrepareAssets,
            RenderSystems::PrepareMeshes => RenderSystems::PrepareMeshes,
            RenderSystems::CreateViews => RenderSystems::CreateViews,
            RenderSystems::Specialize => RenderSystems::Specialize,
            RenderSystems::PrepareViews => RenderSystems::PrepareViews,
            RenderSystems::Queue => RenderSystems::Queue,
            RenderSystems::QueueMeshes => RenderSystems::QueueMeshes,
            RenderSystems::QueueSweep => RenderSystems::QueueSweep,
            RenderSystems::PhaseSort => RenderSystems::PhaseSort,
            RenderSystems::Prepare => RenderSystems::Prepare,
            RenderSystems::PrepareResources =>
                RenderSystems::PrepareResources,
            RenderSystems::PrepareResourcesBatchPhases =>
                RenderSystems::PrepareResourcesBatchPhases,
            RenderSystems::PrepareResourcesWritePhaseBuffers =>
                RenderSystems::PrepareResourcesWritePhaseBuffers,
            RenderSystems::PrepareResourcesCollectPhaseBuffers =>
                RenderSystems::PrepareResourcesCollectPhaseBuffers,
            RenderSystems::PrepareResourcesFlush =>
                RenderSystems::PrepareResourcesFlush,
            RenderSystems::PrepareBindGroups =>
                RenderSystems::PrepareBindGroups,
            RenderSystems::Render => RenderSystems::Render,
            RenderSystems::Cleanup => RenderSystems::Cleanup,
            RenderSystems::PostCleanup => RenderSystems::PostCleanup,
        }
    }
}Clone, const _: () =
    {
        extern crate alloc;
        impl bevy_ecs::schedule::SystemSet for RenderSystems 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)]
157pub enum RenderSystems {
158    /// This is used for applying the commands from the [`ExtractSchedule`]
159    ExtractCommands,
160    /// Prepare assets that have been created/modified/removed this frame.
161    PrepareAssets,
162    /// Prepares extracted meshes.
163    PrepareMeshes,
164    /// Create any additional views such as those used for shadow mapping.
165    CreateViews,
166    /// Specialize material meshes and shadow views.
167    Specialize,
168    /// Prepare any additional views such as those used for shadow mapping.
169    PrepareViews,
170    /// Queue drawable entities as phase items in render phases ready for
171    /// sorting (if necessary)
172    Queue,
173    /// A sub-set within [`Queue`](RenderSystems::Queue) where mesh entity queue systems are executed. Ensures `prepare_assets::<RenderMesh>` is completed.
174    QueueMeshes,
175    /// A sub-set within [`Queue`](RenderSystems::Queue) where meshes that have
176    /// become invisible or changed phases are removed from the bins.
177    QueueSweep,
178    // TODO: This could probably be moved in favor of a system ordering
179    // abstraction in `Render` or `Queue`
180    /// Sort the [`SortedRenderPhase`](render_phase::SortedRenderPhase)s and
181    /// [`BinKey`](render_phase::BinnedPhaseItem::BinKey)s here.
182    PhaseSort,
183    /// Prepare render resources from extracted data for the GPU based on their sorted order.
184    /// Create [`BindGroups`](render_resource::BindGroup) that depend on those data.
185    Prepare,
186    /// A sub-set within [`Prepare`](RenderSystems::Prepare) for initializing buffers, textures and uniforms for use in bind groups.
187    PrepareResources,
188    /// A sub-set within [`Prepare`](RenderSystems::Prepare) that creates batches for render phases.
189    PrepareResourcesBatchPhases,
190    /// A sub-set within [`Prepare`](RenderSystems::Prepare) that writes batches
191    /// for render phases to the GPU.
192    PrepareResourcesWritePhaseBuffers,
193    /// A sub-set within [`Prepare`](RenderSystems::Prepare) to collect phase buffers after
194    /// [`PrepareResourcesBatchPhases`](RenderSystems::PrepareResourcesBatchPhases) has run.
195    PrepareResourcesCollectPhaseBuffers,
196    /// Flush buffers after [`PrepareResources`](RenderSystems::PrepareResources), but before [`PrepareBindGroups`](RenderSystems::PrepareBindGroups).
197    PrepareResourcesFlush,
198    /// A sub-set within [`Prepare`](RenderSystems::Prepare) for constructing bind groups, or other data that relies on render resources prepared in [`PrepareResources`](RenderSystems::PrepareResources).
199    PrepareBindGroups,
200    /// Actual rendering happens here.
201    /// In most cases, only the render backend should insert resources here.
202    Render,
203    /// Cleanup render resources here.
204    Cleanup,
205    /// Final cleanup occurs: any entities with
206    /// [`TemporaryRenderEntity`](sync_world::TemporaryRenderEntity) will be despawned.
207    ///
208    /// Runs after [`Cleanup`](RenderSystems::Cleanup).
209    PostCleanup,
210}
211
212/// The startup schedule of the [`RenderApp`].
213/// This can potentially run multiple times, and not on a fresh render world.
214/// Every time a new [`RenderDevice`](renderer::RenderDevice) is acquired,
215/// this schedule runs to initialize any gpu resources needed for rendering on it.
216#[derive(const _: () =
    {
        extern crate alloc;
        impl bevy_ecs::schedule::ScheduleLabel for RenderStartup 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::ScheduleLabel> {
                alloc::boxed::Box::new(::core::clone::Clone::clone(self))
            }
        }
    };ScheduleLabel, #[automatically_derived]
impl ::core::fmt::Debug for RenderStartup {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f, "RenderStartup")
    }
}Debug, #[automatically_derived]
impl ::core::hash::Hash for RenderStartup {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {}
}Hash, #[automatically_derived]
impl ::core::cmp::PartialEq for RenderStartup {
    #[inline]
    fn eq(&self, other: &RenderStartup) -> bool { true }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for RenderStartup {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {}
}Eq, #[automatically_derived]
impl ::core::clone::Clone for RenderStartup {
    #[inline]
    fn clone(&self) -> RenderStartup { RenderStartup }
}Clone, #[automatically_derived]
impl ::core::default::Default for RenderStartup {
    #[inline]
    fn default() -> RenderStartup { RenderStartup {} }
}Default)]
217pub struct RenderStartup;
218
219/// Constructs a `T` resource with `from_world` and inserts it.
220pub fn init_gpu_resource<R: Resource + FromWorld>(world: &mut World) {
221    let res = R::from_world(world);
222    world.insert_resource(res);
223}
224
225/// Convenience methods for render-recovery-aware resource initialization.
226pub trait GpuResourceAppExt {
227    /// Causes the provided GPU resource to be re-initialized during [`RenderStartup`].
228    ///
229    /// This is useful when recovering from lost render devices.
230    ///
231    /// Shorthand for:
232    /// ```ignore
233    /// app.add_systems(RenderStartup, init_gpu_resource::<R>.ambiguous_with_all());
234    /// ```
235    fn init_gpu_resource<R: Resource + FromWorld>(&mut self) -> &mut Self;
236}
237
238impl GpuResourceAppExt for SubApp {
239    fn init_gpu_resource<R: Resource + FromWorld>(&mut self) -> &mut Self {
240        self.add_systems(RenderStartup, init_gpu_resource::<R>.ambiguous_with_all())
241    }
242}
243
244/// The render recovery schedule. This schedule runs the [`RenderScheduleOrder`] schedules if
245/// we are in [`RenderState::Ready`], and is otherwise hidden from users.
246#[derive(const _: () =
    {
        extern crate alloc;
        impl bevy_ecs::schedule::ScheduleLabel for RenderRecovery 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::ScheduleLabel> {
                alloc::boxed::Box::new(::core::clone::Clone::clone(self))
            }
        }
    };ScheduleLabel, #[automatically_derived]
impl ::core::fmt::Debug for RenderRecovery {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f, "RenderRecovery")
    }
}Debug, #[automatically_derived]
impl ::core::hash::Hash for RenderRecovery {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {}
}Hash, #[automatically_derived]
impl ::core::cmp::PartialEq for RenderRecovery {
    #[inline]
    fn eq(&self, other: &RenderRecovery) -> bool { true }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for RenderRecovery {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {}
}Eq, #[automatically_derived]
impl ::core::clone::Clone for RenderRecovery {
    #[inline]
    fn clone(&self) -> RenderRecovery { RenderRecovery }
}Clone)]
247struct RenderRecovery;
248
249/// Defines the schedules to be run for the rendering, including their order.
250///
251/// This is the same approach as [`MainScheduleOrder`](`bevy_app::MainScheduleOrder`).
252#[derive(impl bevy_ecs::resource::Resource for RenderScheduleOrder where
    Self: ::core::marker::Send + ::core::marker::Sync + 'static {}Resource, #[automatically_derived]
impl ::core::fmt::Debug for RenderScheduleOrder {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field1_finish(f,
            "RenderScheduleOrder", "labels", &&self.labels)
    }
}Debug)]
253pub struct RenderScheduleOrder {
254    /// The labels to run for the rendering schedule (in the order they will be run).
255    pub labels: Vec<InternedScheduleLabel>,
256}
257
258impl Default for RenderScheduleOrder {
259    fn default() -> Self {
260        Self {
261            labels: ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [First.intern(), Render.intern()]))vec![First.intern(), Render.intern()],
262        }
263    }
264}
265
266impl RenderScheduleOrder {
267    /// Adds the given `schedule` after the `after` schedule
268    pub fn insert_after(&mut self, after: impl ScheduleLabel, schedule: impl ScheduleLabel) {
269        let index = self
270            .labels
271            .iter()
272            .position(|current| (**current).eq(&after))
273            .unwrap_or_else(|| {
    ::core::panicking::panic_fmt(format_args!("Expected {0:?} to exist",
            after));
}panic!("Expected {after:?} to exist"));
274        self.labels.insert(index + 1, schedule.intern());
275    }
276
277    /// Adds the given `schedule` before the `before` schedule
278    pub fn insert_before(&mut self, before: impl ScheduleLabel, schedule: impl ScheduleLabel) {
279        let index = self
280            .labels
281            .iter()
282            .position(|current| (**current).eq(&before))
283            .unwrap_or_else(|| {
    ::core::panicking::panic_fmt(format_args!("Expected {0:?} to exist",
            before));
}panic!("Expected {before:?} to exist"));
284        self.labels.insert(index, schedule.intern());
285    }
286}
287
288/// The main render schedule.
289#[derive(const _: () =
    {
        extern crate alloc;
        impl bevy_ecs::schedule::ScheduleLabel for Render 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::ScheduleLabel> {
                alloc::boxed::Box::new(::core::clone::Clone::clone(self))
            }
        }
    };ScheduleLabel, #[automatically_derived]
impl ::core::fmt::Debug for Render {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f, "Render")
    }
}Debug, #[automatically_derived]
impl ::core::hash::Hash for Render {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {}
}Hash, #[automatically_derived]
impl ::core::cmp::PartialEq for Render {
    #[inline]
    fn eq(&self, other: &Render) -> bool { true }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for Render {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {}
}Eq, #[automatically_derived]
impl ::core::clone::Clone for Render {
    #[inline]
    fn clone(&self) -> Render { Render }
}Clone, #[automatically_derived]
impl ::core::default::Default for Render {
    #[inline]
    fn default() -> Render { Render {} }
}Default)]
290pub struct Render;
291
292impl Render {
293    /// Sets up the base structure of the rendering [`Schedule`].
294    ///
295    /// The sets defined in this enum are configured to run in order.
296    pub fn base_schedule() -> Schedule {
297        use RenderSystems::*;
298
299        let mut schedule = Schedule::new(Self);
300
301        schedule.configure_sets(
302            (
303                ExtractCommands,
304                PrepareMeshes,
305                CreateViews,
306                Specialize,
307                PrepareViews,
308                Queue,
309                PhaseSort,
310                Prepare,
311                Render,
312                Cleanup,
313                PostCleanup,
314            )
315                .chain(),
316        );
317        schedule.ignore_ambiguity(Specialize, Specialize);
318
319        schedule.configure_sets((ExtractCommands, PrepareAssets, PrepareMeshes, Prepare).chain());
320        schedule.configure_sets(
321            (QueueMeshes, QueueSweep)
322                .chain()
323                .in_set(Queue)
324                .after(prepare_assets::<RenderMesh>),
325        );
326        schedule.configure_sets(
327            (
328                PrepareResources,
329                PrepareResourcesBatchPhases,
330                PrepareResourcesWritePhaseBuffers,
331                PrepareResourcesCollectPhaseBuffers,
332                PrepareResourcesFlush,
333                PrepareBindGroups,
334            )
335                .chain()
336                .in_set(Prepare),
337        );
338
339        schedule
340    }
341}
342
343#[derive(impl bevy_ecs::resource::Resource for FutureRenderResources where
    Self: ::core::marker::Send + ::core::marker::Sync + 'static {}Resource, #[automatically_derived]
impl ::core::default::Default for FutureRenderResources {
    #[inline]
    fn default() -> FutureRenderResources {
        FutureRenderResources(::core::default::Default::default())
    }
}Default, #[automatically_derived]
impl ::core::clone::Clone for FutureRenderResources {
    #[inline]
    fn clone(&self) -> FutureRenderResources {
        FutureRenderResources(::core::clone::Clone::clone(&self.0))
    }
}Clone, impl ::core::ops::Deref for FutureRenderResources {
    type Target = Arc<Mutex<Option<RenderResources>>>;
    fn deref(&self) -> &Self::Target { &self.0 }
}Deref)]
344pub(crate) struct FutureRenderResources(Arc<Mutex<Option<RenderResources>>>);
345
346/// A label for the rendering sub-app.
347#[derive(#[automatically_derived]
impl ::core::fmt::Debug for RenderApp {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f, "RenderApp")
    }
}Debug, #[automatically_derived]
impl ::core::clone::Clone for RenderApp {
    #[inline]
    fn clone(&self) -> RenderApp { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for RenderApp { }Copy, #[automatically_derived]
impl ::core::hash::Hash for RenderApp {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {}
}Hash, #[automatically_derived]
impl ::core::cmp::PartialEq for RenderApp {
    #[inline]
    fn eq(&self, other: &RenderApp) -> bool { true }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for RenderApp {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {}
}Eq, const _: () =
    {
        extern crate alloc;
        impl bevy_app::AppLabel for RenderApp 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_app::AppLabel> {
                alloc::boxed::Box::new(::core::clone::Clone::clone(self))
            }
        }
    };AppLabel)]
348pub struct RenderApp;
349
350impl Plugin for RenderPlugin {
351    /// Initializes the renderer, sets up the [`RenderSystems`] and creates the rendering sub-app.
352    fn build(&self, app: &mut App) {
353        app.init_asset::<Shader>()
354            .init_asset_loader::<ShaderLoader>();
355        {
    {
        let mut embedded =
            app.world_mut().resource_mut::<::bevy_asset::io::embedded::EmbeddedAssetRegistry>();
        let path =
            {
                let crate_name = "bevy_render".split(':').next().unwrap();
                ::bevy_asset::io::embedded::_embedded_asset_path(crate_name,
                    "src".as_ref(), "src/lib.rs".as_ref(),
                    "maths.wgsl".as_ref())
            };
        let watched_path =
            ::bevy_asset::io::embedded::watched_path("src/lib.rs",
                "maths.wgsl");
        embedded.insert_asset(watched_path, &path,
            b"#define_import_path bevy_render::maths\n\nconst PI: f32 = 3.141592653589793;      // \xcf\x80\nconst PI_2: f32 = 6.283185307179586;    // 2\xcf\x80\nconst HALF_PI: f32 = 1.57079632679;     // \xcf\x80/2\nconst FRAC_PI_3: f32 = 1.0471975512;    // \xcf\x80/3\nconst E: f32 = 2.718281828459045;       // exp(1)\n\nfn affine2_to_square(affine: mat3x2<f32>) -> mat3x3<f32> {\n    return mat3x3<f32>(\n        vec3<f32>(affine[0].xy, 0.0),\n        vec3<f32>(affine[1].xy, 0.0),\n        vec3<f32>(affine[2].xy, 1.0),\n    );\n}\n\nfn affine3_to_square(affine: mat3x4<f32>) -> mat4x4<f32> {\n    return transpose(mat4x4<f32>(\n        affine[0],\n        affine[1],\n        affine[2],\n        vec4<f32>(0.0, 0.0, 0.0, 1.0),\n    ));\n}\n\nfn mat2x4_f32_to_mat3x3_unpack(\n    a: mat2x4<f32>,\n    b: f32,\n) -> mat3x3<f32> {\n    return mat3x3<f32>(\n        a[0].xyz,\n        vec3<f32>(a[0].w, a[1].xy),\n        vec3<f32>(a[1].zw, b),\n    );\n}\n\n// Extracts the square portion of an affine matrix: i.e. discards the\n// translation.\nfn affine3_to_mat3x3(affine: mat4x3<f32>) -> mat3x3<f32> {\n    return mat3x3<f32>(affine[0].xyz, affine[1].xyz, affine[2].xyz);\n}\n\n// Returns the inverse of a 3x3 matrix.\nfn inverse_mat3x3(matrix: mat3x3<f32>) -> mat3x3<f32> {\n    let tmp0 = cross(matrix[1], matrix[2]);\n    let tmp1 = cross(matrix[2], matrix[0]);\n    let tmp2 = cross(matrix[0], matrix[1]);\n    let inv_det = 1.0 / dot(matrix[2], tmp2);\n    return transpose(mat3x3<f32>(tmp0 * inv_det, tmp1 * inv_det, tmp2 * inv_det));\n}\n\n// Returns the inverse of an affine matrix.\n//\n// https://en.wikipedia.org/wiki/Affine_transformation#Groups\nfn inverse_affine3(affine: mat4x3<f32>) -> mat4x3<f32> {\n    let matrix3 = affine3_to_mat3x3(affine);\n    let inv_matrix3 = inverse_mat3x3(matrix3);\n    return mat4x3<f32>(inv_matrix3[0], inv_matrix3[1], inv_matrix3[2], -(inv_matrix3 * affine[3]));\n}\n\n// Extracts the upper 3x3 portion of a 4x4 matrix.\nfn mat4x4_to_mat3x3(m: mat4x4<f32>) -> mat3x3<f32> {\n    return mat3x3<f32>(m[0].xyz, m[1].xyz, m[2].xyz);\n}\n\n// Copy the sign bit from B onto A.\n// copysign allows proper handling of negative zero to match the rust implementation of orthonormalize\nfn copysign(a: f32, b: f32) -> f32 {\n    return bitcast<f32>((bitcast<u32>(a) & 0x7FFFFFFF) | (bitcast<u32>(b) & 0x80000000));\n}\n\n// Constructs a right-handed orthonormal basis from a given unit Z vector.\n//\n// NOTE: requires unit-length (normalized) input to function properly.\n//\n// https://jcgt.org/published/0006/01/01/paper.pdf\n// this method of constructing a basis from a vec3 is also used by `glam::Vec3::any_orthonormal_pair`\n// the construction of the orthonormal basis up and right vectors here needs to precisely match the rust\n// implementation in bevy_light/spot_light.rs:spot_light_world_from_view\nfn orthonormalize(z_basis: vec3<f32>) -> mat3x3<f32> {\n    let sign = copysign(1.0, z_basis.z);\n    let a = -1.0 / (sign + z_basis.z);\n    let b = z_basis.x * z_basis.y * a;\n    let x_basis = vec3(1.0 + sign * z_basis.x * z_basis.x * a, sign * b, -sign * z_basis.x);\n    let y_basis = vec3(b, sign + z_basis.y * z_basis.y * a, -z_basis.y);\n    return mat3x3(x_basis, y_basis, z_basis);\n}\n\n// Returns true if any part of a sphere is on the positive side of a plane.\n//\n// `sphere_center.w` should be 1.0.\n//\n// This is used for frustum culling.\nfn sphere_intersects_plane_half_space(\n    plane: vec4<f32>,\n    sphere_center: vec4<f32>,\n    sphere_radius: f32\n) -> bool {\n    return dot(plane, sphere_center) + sphere_radius > 0.0;\n}\n\n// Returns the distances along the ray to its intersections with a sphere\n// centered at the origin.\n//\n// r: distance from the sphere center to the ray origin\n// mu: cosine of the zenith angle\n// sphere_radius: radius of the sphere\n//\n// Returns vec2(t0, t1). If there is no intersection, returns vec2(-1.0).\nfn ray_sphere_intersect(r: f32, mu: f32, sphere_radius: f32) -> vec2<f32> {\n    let discriminant = r * r * (mu * mu - 1.0) + sphere_radius * sphere_radius;\n    \n    // No intersection\n    if discriminant < 0.0 {\n        return vec2(-1.0);\n    }\n    \n    let q = -r * mu;\n    let sqrt_discriminant = sqrt(discriminant);\n    \n    // Return both intersection distances\n    return vec2(\n        q - sqrt_discriminant,\n        q + sqrt_discriminant\n    );\n}\n\n// pow() but safe for NaNs/negatives\nfn powsafe(color: vec3<f32>, power: f32) -> vec3<f32> {\n    return pow(abs(color), vec3(power)) * sign(color);\n}\n\n// https://en.wikipedia.org/wiki/Vector_projection#Vector_projection_2\nfn project_onto(lhs: vec3<f32>, rhs: vec3<f32>) -> vec3<f32> {\n    let other_len_sq_rcp = 1.0 / dot(rhs, rhs);\n    return rhs * dot(lhs, rhs) * other_len_sq_rcp;\n}\n\n// Below are fast approximations of common irrational and trig functions. These\n// are likely most useful when raymarching, for example, where complete numeric\n// accuracy can be sacrificed for greater sample count.\n\n// Slightly less accurate than fast_acos_4, but much simpler.\nfn fast_acos(in_x: f32) -> f32 {\n    let x = abs(in_x);\n    var res = -0.156583 * x + HALF_PI;\n    res *= sqrt(1.0 - x);\n    return select(PI - res, res, in_x >= 0.0);\n}\n\n// 4th order polynomial approximation\n// 4 VGRP, 16 ALU Full Rate\n// 7 * 10^-5 radians precision\n// Reference : Handbook of Mathematical Functions (chapter : Elementary Transcendental Functions), M. Abramowitz and I.A. Stegun, Ed.\nfn fast_acos_4(x: f32) -> f32 {\n    let x1 = abs(x);\n    let x2 = x1 * x1;\n    let x3 = x2 * x1;\n    var s: f32;\n\n    s = -0.2121144 * x1 + 1.5707288;\n    s = 0.0742610 * x2 + s;\n    s = -0.0187293 * x3 + s;\n    s = sqrt(1.0 - x1) * s;\n\n\t// acos function mirroring\n    return select(PI - s, s, x >= 0.0);\n}\n\nfn fast_atan2(y: f32, x: f32) -> f32 {\n    var t0 = max(abs(x), abs(y));\n    var t1 = min(abs(x), abs(y));\n    var t3 = t1 / t0;\n    var t4 = t3 * t3;\n\n    t0 = 0.0872929;\n    t0 = t0 * t4 - 0.301895;\n    t0 = t0 * t4 + 1.0;\n    t3 = t0 * t3;\n\n    t3 = select(t3, (0.5 * PI) - t3, abs(y) > abs(x));\n    t3 = select(t3, PI - t3, x < 0);\n    t3 = select(-t3, t3, y > 0);\n\n    return t3;\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_render".split(':').next().unwrap();
                            ::bevy_asset::io::embedded::_embedded_asset_path(crate_name,
                                "src".as_ref(), "src/lib.rs".as_ref(),
                                "maths.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, "maths.wgsl");
356        {
    {
        let mut embedded =
            app.world_mut().resource_mut::<::bevy_asset::io::embedded::EmbeddedAssetRegistry>();
        let path =
            {
                let crate_name = "bevy_render".split(':').next().unwrap();
                ::bevy_asset::io::embedded::_embedded_asset_path(crate_name,
                    "src".as_ref(), "src/lib.rs".as_ref(),
                    "color_operations.wgsl".as_ref())
            };
        let watched_path =
            ::bevy_asset::io::embedded::watched_path("src/lib.rs",
                "color_operations.wgsl");
        embedded.insert_asset(watched_path, &path,
            b"#define_import_path bevy_render::color_operations\n\n#import bevy_render::maths::{PI_2,PI,FRAC_PI_3}\n\nconst HUE_GUARD: f32 = 0.0001;\n\n// https://en.wikipedia.org/wiki/SRGB\nfn gamma(value: f32) -> f32 {\n    if value <= 0.0 {\n        return value;\n    }\n    if value <= 0.04045 {\n        return value / 12.92; // linear falloff in dark values\n    } else {\n        return pow((value + 0.055) / 1.055, 2.4); // gamma curve in other area\n    }\n}\n\n// https://en.wikipedia.org/wiki/SRGB\nfn inverse_gamma(value: f32) -> f32 {\n    if value <= 0.0 {\n        return value;\n    }\n\n    if value <= 0.0031308 {\n        return value * 12.92; // linear falloff in dark values\n    } else {\n        return 1.055 * pow(value, 1.0 / 2.4) - 0.055; // gamma curve in other area\n    }\n}\n\nfn srgb_to_linear_rgb(color: vec3<f32>) -> vec3<f32> {\n    return vec3(\n        gamma(color.x),\n        gamma(color.y),\n        gamma(color.z)\n    );\n}\n\nfn linear_rgb_to_srgb(color: vec3<f32>) -> vec3<f32> {\n    return vec3(\n        inverse_gamma(color.x),\n        inverse_gamma(color.y),\n        inverse_gamma(color.z)\n    );\n}\n\nfn linear_to_srgb(color: vec3<f32>) -> vec3<f32> {\n    return linear_rgb_to_srgb(color);\n}\n\nfn srgb_to_linear(color: vec3<f32>) -> vec3<f32> {\n    return srgb_to_linear_rgb(color);\n}\n\n// https://bottosson.github.io/posts/oklab/\nfn oklab_to_linear_rgb(c: vec3<f32>) -> vec3<f32> {\n    let l_ = c.x + 0.39633778 * c.y + 0.21580376 * c.z;\n    let m_ = c.x - 0.105561346 * c.y - 0.06385417 * c.z;\n    let s_ = c.x - 0.08948418 * c.y - 1.2914855 * c.z;\n    let l = l_ * l_ * l_;\n    let m = m_ * m_ * m_;\n    let s = s_ * s_ * s_;\n    return vec3(\n        4.0767417 * l - 3.3077116 * m + 0.23096994 * s,\n        -1.268438 * l + 2.6097574 * m - 0.34131938 * s,\n        -0.0041960863 * l - 0.7034186 * m + 1.7076147 * s,\n    );\n}\n\n// https://bottosson.github.io/posts/oklab/ - inverse of oklab_to_linear_rgb\nfn linear_rgb_to_oklab(c: vec3<f32>) -> vec3<f32> {\n    let l_ = pow(c.x * 0.4122214708 + c.y * 0.5363325363 + c.z * 0.0514459929, 1.0 / 3.0);\n    let m_ = pow(c.x * 0.2119034982 + c.y * 0.6806995451 + c.z * 0.1073969566, 1.0 / 3.0);\n    let s_ = pow(c.x * 0.0883024619 + c.y * 0.2817188376 + c.z * 0.6299787005, 1.0 / 3.0);\n    return vec3(\n        0.2104542553 * l_ + 0.7936177850 * m_ - 0.0040720468 * s_,\n        1.9779984951 * l_ - 2.4285922050 * m_ + 0.4505937099 * s_,\n        0.0259040371 * l_ + 0.7827717662 * m_ - 0.8086757660 * s_,\n    );\n}\n\nfn hsl_to_linear_rgb(hsl: vec3<f32>) -> vec3<f32> {\n    let h = hsl.x;\n    let s = hsl.y;\n    let l = hsl.z;\n    let c = (1.0 - abs(2.0 * l - 1.0)) * s;\n    let hp = h * 6.0;\n    let x = c * (1.0 - abs(hp % 2.0 - 1.0));\n    var r: f32 = 0.0;\n    var g: f32 = 0.0;\n    var b: f32 = 0.0;\n    if 0.0 <= hp && hp < 1.0 {\n        r = c; g = x; b = 0.0;\n    } else if 1.0 <= hp && hp < 2.0 {\n        r = x; g = c; b = 0.0;\n    } else if 2.0 <= hp && hp < 3.0 {\n        r = 0.0; g = c; b = x;\n    } else if 3.0 <= hp && hp < 4.0 {\n        r = 0.0; g = x; b = c;\n    } else if 4.0 <= hp && hp < 5.0 {\n        r = x; g = 0.0; b = c;\n    } else if 5.0 <= hp && hp < 6.0 {\n        r = c; g = 0.0; b = x;\n    }\n    let m = l - 0.5 * c;\n    return srgb_to_linear_rgb(vec3(r + m, g + m, b + m));\n}\n\nfn hsv_to_linear_rgb(hsva: vec3<f32>) -> vec3<f32> {\n    let h = hsva.x * 6.0;\n    let s = hsva.y;\n    let v = hsva.z;\n    let c = v * s;\n    let x = c * (1.0 - abs(h % 2.0 - 1.0));\n    let m = v - c;\n    var r: f32 = 0.0;\n    var g: f32 = 0.0;\n    var b: f32 = 0.0;\n    if 0.0 <= h && h < 1.0 {\n        r = c; g = x; b = 0.0;\n    } else if 1.0 <= h && h < 2.0 {\n        r = x; g = c; b = 0.0;\n    } else if 2.0 <= h && h < 3.0 {\n        r = 0.0; g = c; b = x;\n    } else if 3.0 <= h && h < 4.0 {\n        r = 0.0; g = x; b = c;\n    } else if 4.0 <= h && h < 5.0 {\n        r = x; g = 0.0; b = c;\n    } else if 5.0 <= h && h < 6.0 {\n        r = c; g = 0.0; b = x;\n    }\n    return srgb_to_linear_rgb(vec3(r + m, g + m, b + m));\n}\n\nfn oklch_to_linear_rgb(c: vec3<f32>) -> vec3<f32> {\n    let hue = c.z * PI_2;\n    return oklab_to_linear_rgb(vec3(c.x, c.y * cos(hue), c.y * sin(hue)));\n}\n\nfn mix_oklch(a: vec3<f32>, b: vec3<f32>, t: f32) -> vec3<f32> {\n    // If the chroma is close to zero for one of the endpoints, don\'t interpolate \n    // the hue and instead use the hue of the other endpoint. This allows gradients that smoothly \n    // transition from black or white to a target color without passing through unrelated hues.\n    var h = a.z;\n    var g = b.z;\n    if a.y < HUE_GUARD {\n        h = g;\n    } else if b.y < HUE_GUARD {\n        g = h;\n    }\n\n    let hue_diff = g - h;\n    if abs(hue_diff) > 0.5 {\n        if hue_diff > 0.0 {\n            h += (hue_diff - 1.) * t;\n        } else {\n            h += (hue_diff + 1.) * t;\n        }\n    } else {\n        h += hue_diff * t;\n    }\n    return vec3(\n        mix(a.x, b.x, t),\n        mix(a.y, b.y, t),\n        fract(h),\n    );\n}\n\nfn mix_oklch_long(a: vec3<f32>, b: vec3<f32>, t: f32) -> vec3<f32> {\n    var h = a.z;\n    var g = b.z;\n    if a.y < HUE_GUARD {\n        h = g;\n    } else if b.y < HUE_GUARD {\n        g = h;\n    }\n\n    let hue_diff = g - h;\n    if abs(hue_diff) < 0.5 {\n        if hue_diff >= 0.0 {\n            h += (hue_diff - 1.) * t;\n        } else {\n            h += (hue_diff + 1.) * t;\n        }\n    } else {\n        h += hue_diff * t;\n    }\n    return vec3(\n        mix(a.x, b.x, t),\n        mix(a.y, b.y, t),\n        fract(h),\n    );\n}\n\nfn mix_hsl(a: vec3<f32>, b: vec3<f32>, t: f32) -> vec3<f32> {\n    // If the saturation is close to zero for one of the endpoints, don\'t interpolate \n    // the hue and instead use the hue of the other endpoint. This allows gradients that smoothly \n    // transition from black or white to a target color without passing through unrelated hues.\n    var h = a.x; \n    var g = b.x;\n    if a.y < HUE_GUARD {\n        h = g;\n    } else if b.y < HUE_GUARD {\n        g = h;\n    }\n\n    return vec3(\n        fract(h + (fract(g - h + 0.5) - 0.5) * t),\n        mix(a.y, b.y, t),\n        mix(a.z, b.z, t),\n    );\n}\n\nfn mix_hsl_long(a: vec3<f32>, b: vec3<f32>, t: f32) -> vec3<f32> {\n    var h = a.x;\n    var g = b.x;\n    if a.y < HUE_GUARD {\n        h = g;\n    } else if b.y < HUE_GUARD {\n        g = h;\n    }\n\n    let d = fract(g - h + 0.5) - 0.5;\n    return vec3(\n        fract(h + (d + select(1., -1., 0. < d)) * t),\n        mix(a.y, b.y, t),\n        mix(a.z, b.z, t),\n    );\n}\n\nfn mix_hsv(a: vec3<f32>, b: vec3<f32>, t: f32) -> vec3<f32> {\n    // If the saturation is close to zero for one of the endpoints, don\'t interpolate \n    // the hue and instead use the hue of the other endpoint. This allows gradients that smoothly \n    // transition from black or white to a target color without passing through unrelated hues.\n    var h = a.x;\n    var g = b.x;\n    if a.y < HUE_GUARD {\n        h = g;\n    } else if b.y < HUE_GUARD {\n        g = h;\n    }\n\n    let hue_diff = g - h;\n    if abs(hue_diff) > 0.5 {\n        if hue_diff > 0.0 {\n            h += (hue_diff - 1.0) * t;\n        } else {\n            h += (hue_diff + 1.0) * t;\n        }\n    } else {\n        h += hue_diff * t;\n    }\n    return vec3(\n        fract(h),\n        mix(a.y, b.y, t),\n        mix(a.z, b.z, t),\n    );\n}\n\nfn mix_hsv_long(a: vec3<f32>, b: vec3<f32>, t: f32) -> vec3<f32> {\n    var h = a.x;\n    var g = b.x;\n    if a.y < HUE_GUARD {\n        h = g;\n    } else if b.y < HUE_GUARD {\n        g = h;\n    }\n\n    let hue_diff = g - h;\n    if abs(hue_diff) < 0.5 {\n        if hue_diff >= 0.0 {\n            h += (hue_diff - 1.0) * t;\n        } else {\n            h += (hue_diff + 1.0) * t;\n        }\n    } else {\n        h += hue_diff * t;\n    }\n    return vec3(\n        fract(h),\n        mix(a.y, b.y, t),\n        mix(a.z, b.z, t),\n    );\n}\n\n// Converts HSV to RGB.\n//\n// Input: H \xe2\x88\x88 [0, 2\xcf\x80), S \xe2\x88\x88 [0, 1], V \xe2\x88\x88 [0, 1].\n// Output: R \xe2\x88\x88 [0, 1], G \xe2\x88\x88 [0, 1], B \xe2\x88\x88 [0, 1].\n//\n// <https://en.wikipedia.org/wiki/HSL_and_HSV#HSV_to_RGB_alternative>\nfn hsv_to_rgb(hsv: vec3<f32>) -> vec3<f32> {\n    let n = vec3(5.0, 3.0, 1.0);\n    let k = (n + hsv.x / FRAC_PI_3) % 6.0;\n    return hsv.z - hsv.z * hsv.y * max(vec3(0.0), min(k, min(4.0 - k, vec3(1.0))));\n}\n\n// Converts RGB to HSV.\n//\n// Input: R \xe2\x88\x88 [0, 1], G \xe2\x88\x88 [0, 1], B \xe2\x88\x88 [0, 1].\n// Output: H \xe2\x88\x88 [0, 2\xcf\x80), S \xe2\x88\x88 [0, 1], V \xe2\x88\x88 [0, 1].\n//\n// <https://en.wikipedia.org/wiki/HSL_and_HSV#From_RGB>\nfn rgb_to_hsv(rgb: vec3<f32>) -> vec3<f32> {\n    let x_max = max(rgb.r, max(rgb.g, rgb.b));  // i.e. V\n    let x_min = min(rgb.r, min(rgb.g, rgb.b));\n    let c = x_max - x_min;  // chroma\n\n    var swizzle = vec3<f32>(0.0);\n    if (x_max == rgb.r) {\n        swizzle = vec3(rgb.gb, 0.0);\n    } else if (x_max == rgb.g) {\n        swizzle = vec3(rgb.br, 2.0);\n    } else {\n        swizzle = vec3(rgb.rg, 4.0);\n    }\n\n    let h = FRAC_PI_3 * (((swizzle.x - swizzle.y) / c + swizzle.z) % 6.0);\n\n    // Avoid division by zero.\n    var s = 0.0;\n    if (x_max > 0.0) {\n        s = c / x_max;\n    }\n\n    return vec3(h, s, x_max);\n}\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_render".split(':').next().unwrap();
                            ::bevy_asset::io::embedded::_embedded_asset_path(crate_name,
                                "src".as_ref(), "src/lib.rs".as_ref(),
                                "color_operations.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, "color_operations.wgsl");
357        {
    {
        let mut embedded =
            app.world_mut().resource_mut::<::bevy_asset::io::embedded::EmbeddedAssetRegistry>();
        let path =
            {
                let crate_name = "bevy_render".split(':').next().unwrap();
                ::bevy_asset::io::embedded::_embedded_asset_path(crate_name,
                    "src".as_ref(), "src/lib.rs".as_ref(),
                    "bindless.wgsl".as_ref())
            };
        let watched_path =
            ::bevy_asset::io::embedded::watched_path("src/lib.rs",
                "bindless.wgsl");
        embedded.insert_asset(watched_path, &path,
            b"// Defines the common arrays used to access bindless resources.\n//\n// This need to be kept up to date with the `BINDING_NUMBERS` table in\n// `bindless.rs`.\n//\n// You access these by indexing into the bindless index table, and from there\n// indexing into the appropriate binding array. For example, to access the base\n// color texture of a `StandardMaterial` in bindless mode, write\n// `bindless_textures_2d[materials[slot].base_color_texture]`, where\n// `materials` is the bindless index table and `slot` is the index into that\n// table (which can be found in the `Mesh`).\n\n#define_import_path bevy_render::bindless\n\n#ifdef BINDLESS\n\n// Binding 0 is the bindless index table.\n// Filtering samplers.\n@group(#{MATERIAL_BIND_GROUP}) @binding(1) var bindless_samplers_filtering: binding_array<sampler>;\n// Non-filtering samplers (nearest neighbor).\n@group(#{MATERIAL_BIND_GROUP}) @binding(2) var bindless_samplers_non_filtering: binding_array<sampler>;\n// Comparison samplers (typically for shadow mapping).\n@group(#{MATERIAL_BIND_GROUP}) @binding(3) var bindless_samplers_comparison: binding_array<sampler>;\n// 1D textures.\n@group(#{MATERIAL_BIND_GROUP}) @binding(4) var bindless_textures_1d: binding_array<texture_1d<f32>>;\n// 2D textures.\n@group(#{MATERIAL_BIND_GROUP}) @binding(5) var bindless_textures_2d: binding_array<texture_2d<f32>>;\n// 2D array textures.\n@group(#{MATERIAL_BIND_GROUP}) @binding(6) var bindless_textures_2d_array: binding_array<texture_2d_array<f32>>;\n// 3D textures.\n@group(#{MATERIAL_BIND_GROUP}) @binding(7) var bindless_textures_3d: binding_array<texture_3d<f32>>;\n// Cubemap textures.\n@group(#{MATERIAL_BIND_GROUP}) @binding(8) var bindless_textures_cube: binding_array<texture_cube<f32>>;\n// Cubemap array textures.\n@group(#{MATERIAL_BIND_GROUP}) @binding(9) var bindless_textures_cube_array: binding_array<texture_cube_array<f32>>;\n\n#endif  // BINDLESS\n");
    }
};
let handle:
        ::bevy_shader::_macro::bevy_asset::prelude::Handle<::bevy_shader::prelude::Shader> =
    {
        let (path, asset_server) =
            {
                let path =
                    {
                        {
                            let crate_name = "bevy_render".split(':').next().unwrap();
                            ::bevy_asset::io::embedded::_embedded_asset_path(crate_name,
                                "src".as_ref(), "src/lib.rs".as_ref(),
                                "bindless.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, "bindless.wgsl");
358
359        if insert_future_resources(&self.render_creation, app.world_mut()) {
360            // We only create the render world and set up extraction if we
361            // have a rendering backend available.
362            app.add_plugins(ExtractPlugin {
363                pre_extract: error_handler::update_state,
364            });
365        };
366
367        app.add_plugins((
368            WindowRenderPlugin,
369            CameraPlugin,
370            ViewPlugin,
371            MeshRenderAssetPlugin,
372            GlobalsPlugin,
373            TexturePlugin,
374            BatchingPlugin {
375                debug_flags: self.debug_flags,
376            },
377            StoragePlugin,
378            GpuReadbackPlugin::default(),
379            OcclusionCullingPlugin,
380            SparseBufferPlugin,
381            #[cfg(feature = "tracing-tracy")]
382            diagnostic::RenderDiagnosticsPlugin,
383        ));
384
385        let (sender, receiver) = bevy_time::create_time_channels();
386        app.insert_resource(receiver);
387
388        let asset_server = app.world().resource::<AssetServer>().clone();
389        app.init_resource::<RenderAssetBytesPerFrame>()
390            .init_resource::<RenderErrorHandler>();
391        if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
392            render_app.init_resource::<RenderScheduleOrder>();
393            render_app.init_resource::<RenderAssetBytesPerFrameLimiter>();
394            render_app.init_gpu_resource::<renderer::PendingCommandBuffers>();
395            render_app.insert_resource(sender);
396            render_app.insert_resource(asset_server);
397            render_app.insert_resource(RenderState::Initializing);
398            render_app.add_systems(
399                ExtractSchedule,
400                (
401                    extract_render_asset_bytes_per_frame,
402                    PipelineCache::extract_shaders,
403                ),
404            );
405
406            #[cfg(not(feature = "reflect_auto_register"))]
407            render_app.init_resource::<AppTypeRegistry>();
408
409            #[cfg(feature = "reflect_auto_register")]
410            render_app.insert_resource(AppTypeRegistry::new_with_derived_types());
411
412            #[cfg(feature = "reflect_functions")]
413            render_app.init_resource::<AppFunctionRegistry>();
414
415            render_app.add_schedule(RenderGraph::base_schedule());
416
417            render_app.init_schedule(RenderStartup);
418            render_app
419                .get_schedule_mut(RenderStartup)
420                .unwrap()
421                .set_executor(bevy_ecs::schedule::SingleThreadedExecutor::new());
422            render_app.update_schedule = Some(RenderRecovery.intern());
423            render_app.add_systems(
424                RenderRecovery,
425                (run_render_schedule.run_if(renderer_is_ready), send_time).chain(),
426            );
427            render_app.add_systems(
428                Render,
429                (
430                    (PipelineCache::process_pipeline_queue_system, render_system)
431                        .chain()
432                        .in_set(RenderSystems::Render),
433                    reset_render_asset_bytes_per_frame.in_set(RenderSystems::Cleanup),
434                ),
435            );
436        }
437    }
438
439    fn ready(&self, app: &App) -> bool {
440        // This is a little tricky. `FutureRenderResources` is added in `build`, which runs synchronously before `ready`.
441        // It is only added if there is a wgpu backend and thus the renderer can be created.
442        // Hence, if we try and get the resource and it is not present, that means we are ready, because we dont need it.
443        // On the other hand, if the resource is present, then we try and lock on it. The lock can fail, in which case
444        // we currently can assume that means the `FutureRenderResources` is in the act of being populated, because
445        // that is the only other place the lock may be held. If it is being populated, we can assume we're ready. This
446        // happens via the `and_then` falling through to the same `unwrap_or(true)` case as when there's no resource.
447        // If the lock succeeds, we can straightforwardly check if it is populated. If it is not, then we're not ready.
448        app.world()
449            .get_resource::<FutureRenderResources>()
450            .and_then(|frr| frr.try_lock().map(|locked| locked.is_some()).ok())
451            .unwrap_or(true)
452    }
453
454    fn finish(&self, app: &mut App) {
455        if let Some(future_render_resources) =
456            app.world_mut().remove_resource::<FutureRenderResources>()
457        {
458            let bevy_app::SubApps { main, sub_apps } = app.sub_apps_mut();
459            let render = sub_apps.get_mut(&RenderApp.intern()).unwrap();
460            let render_resources = future_render_resources.0.lock().unwrap().take().unwrap();
461
462            render_resources.unpack_into(
463                main.world_mut(),
464                render.world_mut(),
465                self.synchronous_pipeline_compilation,
466            );
467        }
468    }
469}
470
471fn renderer_is_ready(state: Res<RenderState>) -> bool {
472    #[allow(non_exhaustive_omitted_patterns)] match *state {
    RenderState::Ready => true,
    _ => false,
}matches!(*state, RenderState::Ready)
473}
474
475fn run_render_schedule(world: &mut World) {
476    world.resource_scope(|world, order: Mut<RenderScheduleOrder>| {
477        for &label in &order.labels {
478            let _ = world.try_run_schedule(label);
479        }
480    });
481}
482
483fn send_time(time_sender: Res<TimeSender>) {
484    // update the time and send it to the app world regardless of whether we render
485    if let Err(error) = time_sender.0.try_send(Instant::now()) {
486        match error {
487            bevy_time::TrySendError::Full(_) => {
488                {
    ::core::panicking::panic_fmt(format_args!("The TimeSender channel should always be empty during render. You might need to add the bevy::core::time_system to your app."));
};panic!(
489                    "The TimeSender channel should always be empty during render. \
490                            You might need to add the bevy::core::time_system to your app."
491                );
492            }
493            bevy_time::TrySendError::Disconnected(_) => {
494                // ignore disconnected errors, the main world probably just got dropped during shutdown
495            }
496        }
497    }
498}
499
500/// Inserts a [`FutureRenderResources`] created from this [`RenderCreation`].
501///
502/// Returns true if creation was successful, false otherwise.
503fn insert_future_resources(render_creation: &RenderCreation, main_world: &mut World) -> bool {
504    let primary_window = main_world
505        .query_filtered::<&RawHandleWrapperHolder, With<PrimaryWindow>>()
506        .single(main_world)
507        .ok()
508        .cloned();
509
510    #[cfg(feature = "raw_vulkan_init")]
511    let raw_vulkan_init_settings = main_world
512        .get_resource::<renderer::raw_vulkan_init::RawVulkanInitSettings>()
513        .cloned()
514        .unwrap_or_default();
515
516    let future_resources = FutureRenderResources::default();
517    let success = render_creation.create_render(
518        future_resources.clone(),
519        primary_window,
520        #[cfg(feature = "raw_vulkan_init")]
521        raw_vulkan_init_settings,
522    );
523    if success {
524        // Note that `future_resources` is not necessarily populated here yet.
525        main_world.insert_resource(future_resources);
526    }
527    success
528}
529
530/// If the [`RenderAdapterInfo`] is a Qualcomm Adreno, returns its model number.
531///
532/// This lets us work around hardware bugs.
533pub fn get_adreno_model(adapter_info: &RenderAdapterInfo) -> Option<u32> {
534    if !falsecfg!(target_os = "android") {
535        return None;
536    }
537
538    let adreno_model = adapter_info.name.strip_prefix("Adreno (TM) ")?;
539
540    // Take suffixes into account (like Adreno 642L).
541    Some(
542        adreno_model
543            .chars()
544            .map_while(|c| c.to_digit(10))
545            .fold(0, |acc, digit| acc * 10 + digit),
546    )
547}
548
549/// Get the Mali driver version if the adapter is a Mali GPU.
550pub fn get_mali_driver_version(adapter_info: &RenderAdapterInfo) -> Option<u32> {
551    if !falsecfg!(target_os = "android") {
552        return None;
553    }
554
555    if !adapter_info.name.contains("Mali") {
556        return None;
557    }
558    let driver_info = &adapter_info.driver_info;
559    if let Some(start_pos) = driver_info.find("v1.r")
560        && let Some(end_pos) = driver_info[start_pos..].find('p')
561    {
562        let start_idx = start_pos + 4; // Skip "v1.r"
563        let end_idx = start_pos + end_pos;
564
565        return driver_info[start_idx..end_idx].parse::<u32>().ok();
566    }
567
568    None
569}
570
571pub fn get_pixel10_driver_version(adapter_info: &RenderAdapterInfo) -> Option<u32> {
572    if !falsecfg!(target_os = "android") {
573        return None;
574    }
575
576    if adapter_info.name != "PowerVR D-Series DXT-48-1536 MC1" {
577        return None;
578    }
579
580    let (_, driver_version) = adapter_info.driver_info.split_once('@')?;
581    driver_version.parse::<u32>().ok()
582}
583
584/// Returns true if storage buffers are unsupported on this platform or false
585/// if they are supported.
586pub fn storage_buffers_are_unsupported(limits: &WgpuLimits) -> bool {
587    static STORAGE_BUFFERS_UNSUPPORTED: OnceLock<bool> = OnceLock::new();
588    *STORAGE_BUFFERS_UNSUPPORTED.get_or_init(|| limits.max_storage_buffers_per_shader_stage == 0)
589}