diff --git a/crates/bevy_anti_alias/src/contrast_adaptive_sharpening/mod.rs b/crates/bevy_anti_alias/src/contrast_adaptive_sharpening/mod.rs index 43790dc393520..c6f84cba36baf 100644 --- a/crates/bevy_anti_alias/src/contrast_adaptive_sharpening/mod.rs +++ b/crates/bevy_anti_alias/src/contrast_adaptive_sharpening/mod.rs @@ -7,7 +7,6 @@ use bevy_core_pipeline::{ FullscreenShader, }; use bevy_ecs::{prelude::*, query::QueryItem}; -use bevy_image::BevyDefault as _; use bevy_reflect::{std_traits::ReflectDefault, Reflect}; use bevy_render::{ extract_component::{ExtractComponent, ExtractComponentPlugin, UniformComponentPlugin}, @@ -17,7 +16,7 @@ use bevy_render::{ *, }, renderer::RenderDevice, - view::{ExtractedView, ViewTarget}, + view::ExtractedView, Render, RenderApp, RenderStartup, RenderSystems, }; use bevy_shader::Shader; @@ -249,11 +248,7 @@ fn prepare_cas_pipelines( &sharpening_pipeline, CasPipelineKey { denoise: denoise_cas.0, - texture_format: if view.hdr { - ViewTarget::TEXTURE_FORMAT_HDR - } else { - TextureFormat::bevy_default() - }, + texture_format: view.target_format, }, ); diff --git a/crates/bevy_anti_alias/src/fxaa/mod.rs b/crates/bevy_anti_alias/src/fxaa/mod.rs index 075c7a82f610e..9ed2dc279e416 100644 --- a/crates/bevy_anti_alias/src/fxaa/mod.rs +++ b/crates/bevy_anti_alias/src/fxaa/mod.rs @@ -7,7 +7,6 @@ use bevy_core_pipeline::{ FullscreenShader, }; use bevy_ecs::prelude::*; -use bevy_image::BevyDefault as _; use bevy_reflect::{std_traits::ReflectDefault, Reflect}; use bevy_render::{ extract_component::{ExtractComponent, ExtractComponentPlugin}, @@ -17,7 +16,7 @@ use bevy_render::{ *, }, renderer::RenderDevice, - view::{ExtractedView, ViewTarget}, + view::ExtractedView, Render, RenderApp, RenderStartup, RenderSystems, }; use bevy_shader::Shader; @@ -216,11 +215,7 @@ pub fn prepare_fxaa_pipelines( FxaaPipelineKey { edge_threshold: fxaa.edge_threshold, edge_threshold_min: fxaa.edge_threshold_min, - texture_format: if view.hdr { - ViewTarget::TEXTURE_FORMAT_HDR - } else { - TextureFormat::bevy_default() - }, + texture_format: view.target_format, }, ); diff --git a/crates/bevy_anti_alias/src/smaa/mod.rs b/crates/bevy_anti_alias/src/smaa/mod.rs index 9d7d7cd6593c5..363f80dbe5d3c 100644 --- a/crates/bevy_anti_alias/src/smaa/mod.rs +++ b/crates/bevy_anti_alias/src/smaa/mod.rs @@ -48,7 +48,7 @@ use bevy_ecs::{ system::{lifetimeless::Read, Commands, Query, Res, ResMut}, world::World, }; -use bevy_image::{BevyDefault, Image, ToExtents}; +use bevy_image::{Image, ToExtents}; use bevy_math::{vec4, Vec4}; use bevy_reflect::{std_traits::ReflectDefault, Reflect}; use bevy_render::{ @@ -605,11 +605,7 @@ fn prepare_smaa_pipelines( &pipeline_cache, &smaa_pipelines.neighborhood_blending, SmaaNeighborhoodBlendingPipelineKey { - texture_format: if view.hdr { - ViewTarget::TEXTURE_FORMAT_HDR - } else { - TextureFormat::bevy_default() - }, + texture_format: view.target_format, preset: smaa.preset, }, ); diff --git a/crates/bevy_anti_alias/src/taa/mod.rs b/crates/bevy_anti_alias/src/taa/mod.rs index 44aa6624c1111..284c45cf32aba 100644 --- a/crates/bevy_anti_alias/src/taa/mod.rs +++ b/crates/bevy_anti_alias/src/taa/mod.rs @@ -15,7 +15,7 @@ use bevy_ecs::{ system::{Commands, Query, Res, ResMut}, world::World, }; -use bevy_image::{BevyDefault as _, ToExtents}; +use bevy_image::ToExtents; use bevy_math::vec2; use bevy_reflect::{std_traits::ReflectDefault, Reflect}; use bevy_render::{ @@ -295,6 +295,7 @@ fn init_taa_pipeline( #[derive(PartialEq, Eq, Hash, Clone)] struct TaaPipelineKey { hdr: bool, + target_format: TextureFormat, reset: bool, } @@ -304,11 +305,8 @@ impl SpecializedRenderPipeline for TaaPipeline { fn specialize(&self, key: Self::Key) -> RenderPipelineDescriptor { let mut shader_defs = vec![]; - let format = if key.hdr { + if key.hdr { shader_defs.push("TONEMAP".into()); - ViewTarget::TEXTURE_FORMAT_HDR - } else { - TextureFormat::bevy_default() }; if key.reset { @@ -324,12 +322,12 @@ impl SpecializedRenderPipeline for TaaPipeline { shader_defs, targets: vec![ Some(ColorTargetState { - format, + format: key.target_format, blend: None, write_mask: ColorWrites::ALL, }), Some(ColorTargetState { - format, + format: key.target_format, blend: None, write_mask: ColorWrites::ALL, }), @@ -417,11 +415,7 @@ fn prepare_taa_history_textures( mip_level_count: 1, sample_count: 1, dimension: TextureDimension::D2, - format: if view.hdr { - ViewTarget::TEXTURE_FORMAT_HDR - } else { - TextureFormat::bevy_default() - }, + format: view.target_format, usage: TextureUsages::TEXTURE_BINDING | TextureUsages::RENDER_ATTACHMENT, view_formats: &[], }; @@ -462,6 +456,7 @@ fn prepare_taa_pipelines( for (entity, view, taa_settings) in &views { let mut pipeline_key = TaaPipelineKey { hdr: view.hdr, + target_format: view.target_format, reset: taa_settings.reset, }; let pipeline_id = pipelines.specialize(&pipeline_cache, &pipeline, pipeline_key.clone()); diff --git a/crates/bevy_asset/src/io/source.rs b/crates/bevy_asset/src/io/source.rs index 500a1657f353c..8cca30b885345 100644 --- a/crates/bevy_asset/src/io/source.rs +++ b/crates/bevy_asset/src/io/source.rs @@ -12,7 +12,7 @@ use bevy_ecs::resource::Resource; use bevy_platform::collections::HashMap; use core::{fmt::Display, hash::Hash, time::Duration}; use thiserror::Error; -use tracing::{error, warn}; +use tracing::warn; use super::{ErasedAssetReader, ErasedAssetWriter}; diff --git a/crates/bevy_camera/src/camera.rs b/crates/bevy_camera/src/camera.rs index 815c7609460df..d94bc6f21cefb 100644 --- a/crates/bevy_camera/src/camera.rs +++ b/crates/bevy_camera/src/camera.rs @@ -7,7 +7,7 @@ use super::{ use bevy_asset::Handle; use bevy_derive::Deref; use bevy_ecs::{component::Component, entity::Entity, reflect::ReflectComponent}; -use bevy_image::Image; +use bevy_image::{BevyDefault, Image}; use bevy_math::{ops, Dir3, FloatOrd, Mat4, Ray3d, Rect, URect, UVec2, Vec2, Vec3, Vec3A}; use bevy_reflect::prelude::*; use bevy_transform::components::{GlobalTransform, Transform}; @@ -15,7 +15,7 @@ use bevy_window::{NormalizedWindowRef, WindowRef}; use core::ops::Range; use derive_more::derive::From; use thiserror::Error; -use wgpu_types::{BlendState, TextureUsages}; +use wgpu_types::{BlendState, TextureFormat, TextureUsages}; /// Render viewport configuration for the [`Camera`] component. /// @@ -345,6 +345,7 @@ pub enum ViewportConversionError { #[require( Frustum, CameraMainTextureUsages, + CameraMainTextureFormat, VisibleEntities, Transform, Visibility @@ -949,7 +950,6 @@ impl Default for RenderTarget { /// This component lets you control the [`TextureUsages`] field of the main texture generated for the camera #[derive(Component, Clone, Copy, Reflect)] -#[reflect(opaque)] #[reflect(Component, Default, Clone)] pub struct CameraMainTextureUsages(pub TextureUsages); @@ -970,6 +970,25 @@ impl CameraMainTextureUsages { } } +/// This component lets you control the [`TextureFormat`] field of the main texture generated for the camera +/// +/// By default, bevy will use [`TextureFormat::Rgba8UnormSrgb`] for sdr and [`TextureFormat::Rgba16Float`] for hdr. +#[derive(Component, Clone, Copy, Reflect)] +#[reflect(Component, Default, Clone)] +pub struct CameraMainTextureFormat { + pub sdr_format: TextureFormat, + pub hdr_format: TextureFormat, +} + +impl Default for CameraMainTextureFormat { + fn default() -> Self { + Self { + sdr_format: TextureFormat::bevy_default(), + hdr_format: TextureFormat::Rgba16Float, + } + } +} + #[cfg(test)] mod test { use bevy_math::{Vec2, Vec3}; diff --git a/crates/bevy_core_pipeline/src/core_3d/mod.rs b/crates/bevy_core_pipeline/src/core_3d/mod.rs index 0e5a07b870e83..f3cda1982d88a 100644 --- a/crates/bevy_core_pipeline/src/core_3d/mod.rs +++ b/crates/bevy_core_pipeline/src/core_3d/mod.rs @@ -88,7 +88,7 @@ use bevy_app::{App, Plugin, PostUpdate}; use bevy_asset::UntypedAssetId; use bevy_color::LinearRgba; use bevy_ecs::prelude::*; -use bevy_image::{BevyDefault, ToExtents}; +use bevy_image::ToExtents; use bevy_math::FloatOrd; use bevy_platform::collections::{HashMap, HashSet}; use bevy_render::{ @@ -108,7 +108,7 @@ use bevy_render::{ renderer::RenderDevice, sync_world::{MainEntity, RenderEntity}, texture::{ColorAttachment, TextureCache}, - view::{ExtractedView, ViewDepthTexture, ViewTarget}, + view::{ExtractedView, ViewDepthTexture}, Extract, ExtractSchedule, Render, RenderApp, RenderSystems, }; use nonmax::NonMaxU32; @@ -897,12 +897,6 @@ pub fn prepare_core_3d_transmission_textures( .or_insert_with(|| { let usage = TextureUsages::TEXTURE_BINDING | TextureUsages::COPY_DST; - let format = if view.hdr { - ViewTarget::TEXTURE_FORMAT_HDR - } else { - TextureFormat::bevy_default() - }; - let descriptor = TextureDescriptor { label: Some("view_transmission_texture"), // The size of the transmission texture @@ -910,7 +904,7 @@ pub fn prepare_core_3d_transmission_textures( mip_level_count: 1, sample_count: 1, // No need for MSAA, as we'll only copy the main texture here dimension: TextureDimension::D2, - format, + format: view.target_format, usage, view_formats: &[], }; diff --git a/crates/bevy_core_pipeline/src/oit/resolve/mod.rs b/crates/bevy_core_pipeline/src/oit/resolve/mod.rs index d1fd3765a7024..6f8dfd0acea02 100644 --- a/crates/bevy_core_pipeline/src/oit/resolve/mod.rs +++ b/crates/bevy_core_pipeline/src/oit/resolve/mod.rs @@ -7,7 +7,6 @@ use bevy_ecs::{ entity::{EntityHashMap, EntityHashSet}, prelude::*, }; -use bevy_image::BevyDefault as _; use bevy_render::{ render_resource::{ binding_types::{storage_buffer_sized, texture_depth_2d, uniform_buffer}, @@ -16,7 +15,7 @@ use bevy_render::{ FragmentState, PipelineCache, RenderPipelineDescriptor, ShaderStages, TextureFormat, }, renderer::{RenderAdapter, RenderDevice}, - view::{ExtractedView, ViewTarget, ViewUniform, ViewUniforms}, + view::{ExtractedView, ViewUniform, ViewUniforms}, Render, RenderApp, RenderSystems, }; use bevy_shader::ShaderDefVal; @@ -137,7 +136,7 @@ pub struct OitResolvePipelineId(pub CachedRenderPipelineId); /// This key is used to cache the pipeline id and to specialize the render pipeline descriptor. #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub struct OitResolvePipelineKey { - hdr: bool, + target_format: TextureFormat, layer_count: i32, } @@ -163,7 +162,7 @@ pub fn queue_oit_resolve_pipeline( for (e, view, oit_settings) in &views { current_view_entities.insert(e); let key = OitResolvePipelineKey { - hdr: view.hdr, + target_format: view.target_format, layer_count: oit_settings.layer_count, }; @@ -200,12 +199,6 @@ fn specialize_oit_resolve_pipeline( fullscreen_shader: &FullscreenShader, asset_server: &AssetServer, ) -> RenderPipelineDescriptor { - let format = if key.hdr { - ViewTarget::TEXTURE_FORMAT_HDR - } else { - TextureFormat::bevy_default() - }; - RenderPipelineDescriptor { label: Some("oit_resolve_pipeline".into()), layout: vec![ @@ -219,7 +212,7 @@ fn specialize_oit_resolve_pipeline( key.layer_count as u32, )], targets: vec![Some(ColorTargetState { - format, + format: key.target_format, blend: Some(BlendState { color: BlendComponent::OVER, alpha: BlendComponent::OVER, diff --git a/crates/bevy_core_pipeline/src/skybox/mod.rs b/crates/bevy_core_pipeline/src/skybox/mod.rs index aa35210a0eb1f..ff43f3857ab66 100644 --- a/crates/bevy_core_pipeline/src/skybox/mod.rs +++ b/crates/bevy_core_pipeline/src/skybox/mod.rs @@ -9,7 +9,7 @@ use bevy_ecs::{ schedule::IntoScheduleConfigs, system::{Commands, Query, Res, ResMut}, }; -use bevy_image::{BevyDefault, Image}; +use bevy_image::Image; use bevy_math::{Mat4, Quat}; use bevy_reflect::{std_traits::ReflectDefault, Reflect}; use bevy_render::{ @@ -24,7 +24,7 @@ use bevy_render::{ }, renderer::RenderDevice, texture::GpuImage, - view::{ExtractedView, Msaa, ViewTarget, ViewUniform, ViewUniforms}, + view::{ExtractedView, Msaa, ViewUniform, ViewUniforms}, Render, RenderApp, RenderStartup, RenderSystems, }; use bevy_shader::Shader; @@ -185,7 +185,7 @@ fn init_skybox_pipeline( #[derive(PartialEq, Eq, Hash, Clone, Copy)] struct SkyboxPipelineKey { - hdr: bool, + target_format: TextureFormat, samples: u32, depth_format: TextureFormat, } @@ -225,11 +225,7 @@ impl SpecializedRenderPipeline for SkyboxPipeline { fragment: Some(FragmentState { shader: self.shader.clone(), targets: vec![Some(ColorTargetState { - format: if key.hdr { - ViewTarget::TEXTURE_FORMAT_HDR - } else { - TextureFormat::bevy_default() - }, + format: key.target_format, // BlendState::REPLACE is not needed here, and None will be potentially much faster in some cases. blend: None, write_mask: ColorWrites::ALL, @@ -256,7 +252,7 @@ fn prepare_skybox_pipelines( &pipeline_cache, &pipeline, SkyboxPipelineKey { - hdr: view.hdr, + target_format: view.target_format, samples: msaa.samples(), depth_format: CORE_3D_DEPTH_FORMAT, }, diff --git a/crates/bevy_core_pipeline/src/tonemapping/mod.rs b/crates/bevy_core_pipeline/src/tonemapping/mod.rs index 8b1379f6b19b2..e41889843c319 100644 --- a/crates/bevy_core_pipeline/src/tonemapping/mod.rs +++ b/crates/bevy_core_pipeline/src/tonemapping/mod.rs @@ -186,6 +186,7 @@ bitflags! { #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub struct TonemappingPipelineKey { + target_format: TextureFormat, deband_dither: DebandDither, tonemapping: Tonemapping, flags: TonemappingPipelineKeyFlags, @@ -273,7 +274,7 @@ impl SpecializedRenderPipeline for TonemappingPipeline { shader: self.fragment_shader.clone(), shader_defs, targets: vec![Some(ColorTargetState { - format: ViewTarget::TEXTURE_FORMAT_HDR, + format: key.target_format, blend: None, write_mask: ColorWrites::ALL, })], @@ -357,6 +358,7 @@ pub fn prepare_view_tonemapping_pipelines( deband_dither: *dither.unwrap_or(&DebandDither::Disabled), tonemapping: *tonemapping.unwrap_or(&Tonemapping::None), flags, + target_format: view.target_format, }; let pipeline = pipelines.specialize(&pipeline_cache, &upscaling_pipeline, key); diff --git a/crates/bevy_ecs/src/schedule/schedule.rs b/crates/bevy_ecs/src/schedule/schedule.rs index 87a91c86ae568..e3daedae58631 100644 --- a/crates/bevy_ecs/src/schedule/schedule.rs +++ b/crates/bevy_ecs/src/schedule/schedule.rs @@ -17,7 +17,7 @@ use core::{ fmt::{Debug, Write}, }; use fixedbitset::FixedBitSet; -use log::{error, info, warn}; +use log::{info, warn}; use pass::ScheduleBuildPassObj; use thiserror::Error; #[cfg(feature = "trace")] diff --git a/crates/bevy_gizmos/src/pipeline_2d.rs b/crates/bevy_gizmos/src/pipeline_2d.rs index 48cd53c4e1420..9b3defd43a52d 100644 --- a/crates/bevy_gizmos/src/pipeline_2d.rs +++ b/crates/bevy_gizmos/src/pipeline_2d.rs @@ -15,7 +15,6 @@ use bevy_ecs::{ schedule::IntoScheduleConfigs, system::{Commands, Query, Res, ResMut}, }; -use bevy_image::BevyDefault as _; use bevy_math::FloatOrd; use bevy_render::{ render_asset::{prepare_assets, RenderAssets}, @@ -24,7 +23,7 @@ use bevy_render::{ ViewSortedRenderPhases, }, render_resource::*, - view::{ExtractedView, Msaa, ViewTarget}, + view::{ExtractedView, Msaa}, Render, RenderApp, RenderSystems, }; use bevy_render::{sync_world::MainEntity, RenderStartup}; @@ -111,12 +110,6 @@ impl SpecializedRenderPipeline for LineGizmoPipeline { type Key = LineGizmoPipelineKey; fn specialize(&self, key: Self::Key) -> RenderPipelineDescriptor { - let format = if key.mesh_key.contains(Mesh2dPipelineKey::HDR) { - ViewTarget::TEXTURE_FORMAT_HDR - } else { - TextureFormat::bevy_default() - }; - let shader_defs = vec![ #[cfg(feature = "webgl")] "SIXTEEN_BYTE_ALIGNMENT".into(), @@ -145,7 +138,7 @@ impl SpecializedRenderPipeline for LineGizmoPipeline { shader_defs, entry_point: Some(fragment_entry_point.into()), targets: vec![Some(ColorTargetState { - format, + format: key.mesh_key.view_target_format(), blend: Some(BlendState::ALPHA_BLENDING), write_mask: ColorWrites::ALL, })], @@ -195,12 +188,6 @@ impl SpecializedRenderPipeline for LineJointGizmoPipeline { type Key = LineJointGizmoPipelineKey; fn specialize(&self, key: Self::Key) -> RenderPipelineDescriptor { - let format = if key.mesh_key.contains(Mesh2dPipelineKey::HDR) { - ViewTarget::TEXTURE_FORMAT_HDR - } else { - TextureFormat::bevy_default() - }; - let shader_defs = vec![ #[cfg(feature = "webgl")] "SIXTEEN_BYTE_ALIGNMENT".into(), @@ -232,7 +219,7 @@ impl SpecializedRenderPipeline for LineJointGizmoPipeline { shader: self.shader.clone(), shader_defs, targets: vec![Some(ColorTargetState { - format, + format: key.mesh_key.view_target_format(), blend: Some(BlendState::ALPHA_BLENDING), write_mask: ColorWrites::ALL, })], @@ -309,7 +296,7 @@ fn queue_line_gizmos_2d( }; let mesh_key = Mesh2dPipelineKey::from_msaa_samples(msaa.samples()) - | Mesh2dPipelineKey::from_hdr(view.hdr); + | Mesh2dPipelineKey::from_view_target_format(view.target_format); let render_layers = render_layers.unwrap_or_default(); for (entity, main_entity, config) in &line_gizmos { @@ -389,7 +376,7 @@ fn queue_line_joint_gizmos_2d( }; let mesh_key = Mesh2dPipelineKey::from_msaa_samples(msaa.samples()) - | Mesh2dPipelineKey::from_hdr(view.hdr); + | Mesh2dPipelineKey::from_view_target_format(view.target_format); let render_layers = render_layers.unwrap_or_default(); for (entity, main_entity, config) in &line_gizmos { diff --git a/crates/bevy_gizmos/src/pipeline_3d.rs b/crates/bevy_gizmos/src/pipeline_3d.rs index ded286949ac5e..523e1bf64fe9b 100644 --- a/crates/bevy_gizmos/src/pipeline_3d.rs +++ b/crates/bevy_gizmos/src/pipeline_3d.rs @@ -20,7 +20,6 @@ use bevy_ecs::{ schedule::IntoScheduleConfigs, system::{Commands, Query, Res, ResMut}, }; -use bevy_image::BevyDefault as _; use bevy_pbr::{MeshPipeline, MeshPipelineKey, SetMeshViewBindGroup}; use bevy_render::{ render_asset::{prepare_assets, RenderAssets}, @@ -29,7 +28,7 @@ use bevy_render::{ ViewSortedRenderPhases, }, render_resource::*, - view::{ExtractedView, Msaa, ViewTarget}, + view::{ExtractedView, Msaa}, Render, RenderApp, RenderSystems, }; use bevy_render::{sync_world::MainEntity, RenderStartup}; @@ -113,12 +112,6 @@ impl SpecializedRenderPipeline for LineGizmoPipeline { shader_defs.push("PERSPECTIVE".into()); } - let format = if key.view_key.contains(MeshPipelineKey::HDR) { - ViewTarget::TEXTURE_FORMAT_HDR - } else { - TextureFormat::bevy_default() - }; - let view_layout = self .mesh_pipeline .get_view_layout(key.view_key.into()) @@ -143,7 +136,7 @@ impl SpecializedRenderPipeline for LineGizmoPipeline { shader_defs, entry_point: Some(fragment_entry_point.into()), targets: vec![Some(ColorTargetState { - format, + format: key.view_key.view_target_format(), blend: Some(BlendState::ALPHA_BLENDING), write_mask: ColorWrites::ALL, })], @@ -194,12 +187,6 @@ impl SpecializedRenderPipeline for LineJointGizmoPipeline { shader_defs.push("PERSPECTIVE".into()); } - let format = if key.view_key.contains(MeshPipelineKey::HDR) { - ViewTarget::TEXTURE_FORMAT_HDR - } else { - TextureFormat::bevy_default() - }; - let view_layout = self .mesh_pipeline .get_view_layout(key.view_key.into()) @@ -227,7 +214,7 @@ impl SpecializedRenderPipeline for LineJointGizmoPipeline { shader: self.shader.clone(), shader_defs, targets: vec![Some(ColorTargetState { - format, + format: key.view_key.view_target_format(), blend: Some(BlendState::ALPHA_BLENDING), write_mask: ColorWrites::ALL, })], @@ -313,7 +300,7 @@ fn queue_line_gizmos_3d( let render_layers = render_layers.unwrap_or_default(); let mut view_key = MeshPipelineKey::from_msaa_samples(msaa.samples()) - | MeshPipelineKey::from_hdr(view.hdr); + | MeshPipelineKey::from_view_target_format(view.target_format); if normal_prepass { view_key |= MeshPipelineKey::NORMAL_PREPASS; @@ -431,7 +418,7 @@ fn queue_line_joint_gizmos_3d( let render_layers = render_layers.unwrap_or_default(); let mut view_key = MeshPipelineKey::from_msaa_samples(msaa.samples()) - | MeshPipelineKey::from_hdr(view.hdr); + | MeshPipelineKey::from_view_target_format(view.target_format); if normal_prepass { view_key |= MeshPipelineKey::NORMAL_PREPASS; diff --git a/crates/bevy_image/src/dynamic_texture_atlas_builder.rs b/crates/bevy_image/src/dynamic_texture_atlas_builder.rs index 016ae96454666..54a45d10d1834 100644 --- a/crates/bevy_image/src/dynamic_texture_atlas_builder.rs +++ b/crates/bevy_image/src/dynamic_texture_atlas_builder.rs @@ -3,7 +3,6 @@ use bevy_asset::RenderAssetUsages; use bevy_math::{URect, UVec2}; use guillotiere::{size2, Allocation, AtlasAllocator}; use thiserror::Error; -use tracing::error; /// An error produced by [`DynamicTextureAtlasBuilder`] when trying to add a new /// texture to a [`TextureAtlasLayout`]. diff --git a/crates/bevy_pbr/src/deferred/mod.rs b/crates/bevy_pbr/src/deferred/mod.rs index 2eee4303795b3..f75ed8de14735 100644 --- a/crates/bevy_pbr/src/deferred/mod.rs +++ b/crates/bevy_pbr/src/deferred/mod.rs @@ -16,7 +16,6 @@ use bevy_core_pipeline::{ tonemapping::{DebandDither, Tonemapping}, }; use bevy_ecs::{prelude::*, query::QueryItem}; -use bevy_image::BevyDefault as _; use bevy_light::{EnvironmentMapLight, IrradianceVolume, ShadowFilteringMethod}; use bevy_render::RenderStartup; use bevy_render::{ @@ -363,11 +362,7 @@ impl SpecializedRenderPipeline for DeferredLightingLayout { shader: self.deferred_lighting_shader.clone(), shader_defs, targets: vec![Some(ColorTargetState { - format: if key.contains(MeshPipelineKey::HDR) { - ViewTarget::TEXTURE_FORMAT_HDR - } else { - TextureFormat::bevy_default() - }, + format: key.view_target_format(), blend: None, write_mask: ColorWrites::ALL, })], @@ -476,7 +471,7 @@ pub fn prepare_deferred_lighting_pipelines( continue; } - let mut view_key = MeshPipelineKey::from_hdr(view.hdr); + let mut view_key = MeshPipelineKey::from_view_target_format(view.target_format); if normal_prepass { view_key |= MeshPipelineKey::NORMAL_PREPASS; diff --git a/crates/bevy_pbr/src/meshlet/material_pipeline_prepare.rs b/crates/bevy_pbr/src/meshlet/material_pipeline_prepare.rs index e00c41900146d..ae086be0e42e1 100644 --- a/crates/bevy_pbr/src/meshlet/material_pipeline_prepare.rs +++ b/crates/bevy_pbr/src/meshlet/material_pipeline_prepare.rs @@ -74,8 +74,8 @@ pub fn prepare_material_meshlet_meshes_main_opaque_pass( has_irradiance_volumes, ) in &mut views { - let mut view_key = - MeshPipelineKey::from_msaa_samples(1) | MeshPipelineKey::from_hdr(view.hdr); + let mut view_key = MeshPipelineKey::from_msaa_samples(1) + | MeshPipelineKey::from_view_target_format(view.target_format); if normal_prepass { view_key |= MeshPipelineKey::NORMAL_PREPASS; @@ -287,8 +287,8 @@ pub fn prepare_material_meshlet_meshes_prepass( (normal_prepass, motion_vector_prepass, deferred_prepass), ) in &mut views { - let mut view_key = - MeshPipelineKey::from_msaa_samples(1) | MeshPipelineKey::from_hdr(view.hdr); + let mut view_key = MeshPipelineKey::from_msaa_samples(1) + | MeshPipelineKey::from_view_target_format(view.target_format); if normal_prepass.is_some() { view_key |= MeshPipelineKey::NORMAL_PREPASS; diff --git a/crates/bevy_pbr/src/render/light.rs b/crates/bevy_pbr/src/render/light.rs index 8bce0f4556bb6..25ec8d51c8913 100644 --- a/crates/bevy_pbr/src/render/light.rs +++ b/crates/bevy_pbr/src/render/light.rs @@ -19,6 +19,7 @@ use bevy_ecs::{ prelude::*, system::lifetimeless::Read, }; +use bevy_image::BevyDefault; use bevy_light::cascade::Cascade; use bevy_light::cluster::assign::{calculate_cluster_factors, ClusterableObjectType}; use bevy_light::cluster::GlobalVisibleClusterableObjects; @@ -1338,6 +1339,7 @@ pub fn prepare_lights( clip_from_world: None, clip_from_view: cube_face_projection, hdr: false, + target_format: TextureFormat::bevy_default(), color_grading: Default::default(), }, *frustum, @@ -1440,6 +1442,7 @@ pub fn prepare_lights( clip_from_view: spot_projection, clip_from_world: None, hdr: false, + target_format: TextureFormat::bevy_default(), color_grading: Default::default(), }, *spot_light_frustum.unwrap(), @@ -1585,6 +1588,7 @@ pub fn prepare_lights( clip_from_view: cascade.clip_from_cascade, clip_from_world: Some(cascade.clip_from_world), hdr: false, + target_format: TextureFormat::bevy_default(), color_grading: Default::default(), }, frustum, diff --git a/crates/bevy_pbr/src/render/mesh.rs b/crates/bevy_pbr/src/render/mesh.rs index 922294f0657f4..e341688956af3 100644 --- a/crates/bevy_pbr/src/render/mesh.rs +++ b/crates/bevy_pbr/src/render/mesh.rs @@ -18,7 +18,7 @@ use bevy_ecs::{ query::{QueryData, ROQueryItem}, system::{lifetimeless::*, SystemParamItem, SystemState}, }; -use bevy_image::{BevyDefault, ImageSampler, TextureFormatPixelInfo}; +use bevy_image::{ImageSampler, TextureFormatPixelInfo}; use bevy_light::{ EnvironmentMapLight, IrradianceVolume, NotShadowCaster, NotShadowReceiver, ShadowFilteringMethod, TransmittedShadowReceiver, @@ -49,8 +49,7 @@ use bevy_render::{ sync_world::MainEntityHashSet, texture::{DefaultImageSampler, GpuImage}, view::{ - self, NoIndirectDrawing, RenderVisibilityRanges, RetainedViewEntity, ViewTarget, - ViewUniformOffset, + self, NoIndirectDrawing, RenderVisibilityRanges, RetainedViewEntity, ViewUniformOffset, }, Extract, }; @@ -344,7 +343,7 @@ pub fn check_views_need_specialization( ) in views.iter_mut() { let mut view_key = MeshPipelineKey::from_msaa_samples(msaa.samples()) - | MeshPipelineKey::from_hdr(view.hdr); + | MeshPipelineKey::from_view_target_format(view.target_format); if normal_prepass { view_key |= MeshPipelineKey::NORMAL_PREPASS; @@ -2133,6 +2132,19 @@ bitflags::bitflags! { Self::SHADOW_FILTER_METHOD_RESERVED_BITS.bits() | Self::VIEW_PROJECTION_RESERVED_BITS.bits() | Self::SCREEN_SPACE_SPECULAR_TRANSMISSION_RESERVED_BITS.bits(); + + const VIEW_TARGET_FORMAT_RESERVED_BITS = Self::VIEW_TARGET_FORMAT_MASK_BITS << Self::VIEW_TARGET_FORMAT_SHIFT_BITS; + const VIEW_TARGET_FORMAT_R8UNORM = 0 << Self::VIEW_TARGET_FORMAT_SHIFT_BITS; + const VIEW_TARGET_FORMAT_RG8UNORM = 1 << Self::VIEW_TARGET_FORMAT_SHIFT_BITS; + const VIEW_TARGET_FORMAT_RGBA8UNORM = 2 << Self::VIEW_TARGET_FORMAT_SHIFT_BITS; + const VIEW_TARGET_FORMAT_RGBA8UNORMSRGB = 3 << Self::VIEW_TARGET_FORMAT_SHIFT_BITS; + const VIEW_TARGET_FORMAT_BGRA8UNORM = 4 << Self::VIEW_TARGET_FORMAT_SHIFT_BITS; + const VIEW_TARGET_FORMAT_BGRA8UNORMSRGB = 5 << Self::VIEW_TARGET_FORMAT_SHIFT_BITS; + const VIEW_TARGET_FORMAT_R16FLOAT = 6 << Self::VIEW_TARGET_FORMAT_SHIFT_BITS; + const VIEW_TARGET_FORMAT_RG16FLOAT = 7 << Self::VIEW_TARGET_FORMAT_SHIFT_BITS; + const VIEW_TARGET_FORMAT_RGBA16FLOAT = 8 << Self::VIEW_TARGET_FORMAT_SHIFT_BITS; + const VIEW_TARGET_FORMAT_RB11B10FLOAT = 9 << Self::VIEW_TARGET_FORMAT_SHIFT_BITS; + const VIEW_TARGET_FORMAT_RGB10A2UNORM = 10 << Self::VIEW_TARGET_FORMAT_SHIFT_BITS; } } @@ -2160,20 +2172,17 @@ impl MeshPipelineKey { const SCREEN_SPACE_SPECULAR_TRANSMISSION_SHIFT_BITS: u64 = Self::VIEW_PROJECTION_MASK_BITS.count_ones() as u64 + Self::VIEW_PROJECTION_SHIFT_BITS; + const VIEW_TARGET_FORMAT_MASK_BITS: u64 = 0b1111; + const VIEW_TARGET_FORMAT_SHIFT_BITS: u64 = Self::SCREEN_SPACE_SPECULAR_TRANSMISSION_MASK_BITS + .count_ones() as u64 + + Self::SCREEN_SPACE_SPECULAR_TRANSMISSION_SHIFT_BITS; + pub fn from_msaa_samples(msaa_samples: u32) -> Self { let msaa_bits = (msaa_samples.trailing_zeros() as u64 & Self::MSAA_MASK_BITS) << Self::MSAA_SHIFT_BITS; Self::from_bits_retain(msaa_bits) } - pub fn from_hdr(hdr: bool) -> Self { - if hdr { - MeshPipelineKey::HDR - } else { - MeshPipelineKey::NONE - } - } - pub fn msaa_samples(&self) -> u32 { 1 << ((self.bits() >> Self::MSAA_SHIFT_BITS) & Self::MSAA_MASK_BITS) } @@ -2198,6 +2207,8 @@ impl MeshPipelineKey { _ => PrimitiveTopology::default(), } } + + bevy_render::declare_view_target_format_fn!(); } // Ensure that we didn't overflow the number of bits available in `MeshPipelineKey`. @@ -2579,12 +2590,6 @@ impl SpecializedMeshPipeline for MeshPipeline { } } - let format = if key.contains(MeshPipelineKey::HDR) { - ViewTarget::TEXTURE_FORMAT_HDR - } else { - TextureFormat::bevy_default() - }; - // This is defined here so that custom shaders that use something other than // the mesh binding from bevy_pbr::mesh_bindings can easily make use of this // in their own shaders. @@ -2606,7 +2611,7 @@ impl SpecializedMeshPipeline for MeshPipeline { shader: self.shader.clone(), shader_defs, targets: vec![Some(ColorTargetState { - format, + format: key.view_target_format(), blend, write_mask: ColorWrites::ALL, })], diff --git a/crates/bevy_pbr/src/ssr/mod.rs b/crates/bevy_pbr/src/ssr/mod.rs index f39cf417c2492..3d5cf030995cd 100644 --- a/crates/bevy_pbr/src/ssr/mod.rs +++ b/crates/bevy_pbr/src/ssr/mod.rs @@ -21,7 +21,6 @@ use bevy_ecs::{ system::{lifetimeless::Read, Commands, Query, Res, ResMut}, world::World, }; -use bevy_image::BevyDefault as _; use bevy_light::EnvironmentMapLight; use bevy_reflect::{std_traits::ReflectDefault, Reflect}; use bevy_render::{ @@ -175,7 +174,7 @@ pub struct ViewScreenSpaceReflectionsUniformOffset(u32); #[derive(Clone, Copy, PartialEq, Eq, Hash)] pub struct ScreenSpaceReflectionsPipelineKey { mesh_pipeline_view_key: MeshPipelineViewLayoutKey, - is_hdr: bool, + target_format: TextureFormat, has_environment_maps: bool, } @@ -456,7 +455,7 @@ pub fn prepare_ssr_pipelines( &ssr_pipeline, ScreenSpaceReflectionsPipelineKey { mesh_pipeline_view_key, - is_hdr: extracted_view.hdr, + target_format: extracted_view.target_format, has_environment_maps, }, ); @@ -549,11 +548,7 @@ impl SpecializedRenderPipeline for ScreenSpaceReflectionsPipeline { shader: self.fragment_shader.clone(), shader_defs, targets: vec![Some(ColorTargetState { - format: if key.is_hdr { - ViewTarget::TEXTURE_FORMAT_HDR - } else { - TextureFormat::bevy_default() - }, + format: key.target_format, blend: None, write_mask: ColorWrites::ALL, })], diff --git a/crates/bevy_pbr/src/volumetric_fog/render.rs b/crates/bevy_pbr/src/volumetric_fog/render.rs index 0c558fe2e804d..d03b5d2c37712 100644 --- a/crates/bevy_pbr/src/volumetric_fog/render.rs +++ b/crates/bevy_pbr/src/volumetric_fog/render.rs @@ -17,7 +17,7 @@ use bevy_ecs::{ system::{lifetimeless::Read, Commands, Local, Query, Res, ResMut}, world::World, }; -use bevy_image::{BevyDefault, Image}; +use bevy_image::Image; use bevy_light::{FogVolume, VolumetricFog, VolumetricLight}; use bevy_math::{vec4, Affine3A, Mat4, Vec3, Vec3A, Vec4}; use bevy_mesh::{Mesh, MeshVertexBufferLayoutRef}; @@ -142,6 +142,8 @@ pub struct VolumetricFogPipelineKey { /// Flags that specify features on the pipeline key. flags: VolumetricFogPipelineKeyFlags, + + target_format: TextureFormat, } /// The same as [`VolumetricFog`] and [`FogVolume`], but formatted for @@ -581,11 +583,7 @@ impl SpecializedRenderPipeline for VolumetricFogPipeline { shader: self.shader.clone(), shader_defs, targets: vec![Some(ColorTargetState { - format: if key.flags.contains(VolumetricFogPipelineKeyFlags::HDR) { - ViewTarget::TEXTURE_FORMAT_HDR - } else { - TextureFormat::bevy_default() - }, + format: key.target_format, // Blend on top of what's already in the framebuffer. Doing // the alpha blending with the hardware blender allows us to // avoid having to use intermediate render targets. @@ -667,6 +665,7 @@ pub fn prepare_volumetric_fog_pipelines( mesh_pipeline_view_key, vertex_buffer_layout: plane_mesh.layout.clone(), flags: textureless_flags, + target_format: view.target_format, }; let textureless_pipeline_id = pipelines.specialize( &pipeline_cache, diff --git a/crates/bevy_post_process/src/bloom/upsampling_pipeline.rs b/crates/bevy_post_process/src/bloom/upsampling_pipeline.rs index 775ca55fb3529..bff3bffcab27c 100644 --- a/crates/bevy_post_process/src/bloom/upsampling_pipeline.rs +++ b/crates/bevy_post_process/src/bloom/upsampling_pipeline.rs @@ -15,7 +15,7 @@ use bevy_render::{ *, }, renderer::RenderDevice, - view::ViewTarget, + view::ExtractedView, }; use bevy_shader::Shader; use bevy_utils::default; @@ -38,7 +38,7 @@ pub struct BloomUpsamplingPipeline { #[derive(PartialEq, Eq, Hash, Clone)] pub struct BloomUpsamplingPipelineKeys { composite_mode: BloomCompositeMode, - final_pipeline: bool, + target_format: TextureFormat, } pub fn init_bloom_upscaling_pipeline( @@ -73,12 +73,6 @@ impl SpecializedRenderPipeline for BloomUpsamplingPipeline { type Key = BloomUpsamplingPipelineKeys; fn specialize(&self, key: Self::Key) -> RenderPipelineDescriptor { - let texture_format = if key.final_pipeline { - ViewTarget::TEXTURE_FORMAT_HDR - } else { - BLOOM_TEXTURE_FORMAT - }; - let color_blend = match key.composite_mode { BloomCompositeMode::EnergyConserving => { // At the time of developing this we decided to blend our @@ -119,7 +113,7 @@ impl SpecializedRenderPipeline for BloomUpsamplingPipeline { shader: self.fragment_shader.clone(), entry_point: Some("upsample".into()), targets: vec![Some(ColorTargetState { - format: texture_format, + format: key.target_format, blend: Some(BlendState { color: color_blend, alpha: BlendComponent { @@ -142,15 +136,15 @@ pub fn prepare_upsampling_pipeline( pipeline_cache: Res, mut pipelines: ResMut>, pipeline: Res, - views: Query<(Entity, &Bloom)>, + views: Query<(Entity, &ExtractedView, &Bloom)>, ) { - for (entity, bloom) in &views { + for (entity, view, bloom) in &views { let pipeline_id = pipelines.specialize( &pipeline_cache, &pipeline, BloomUpsamplingPipelineKeys { composite_mode: bloom.composite_mode, - final_pipeline: false, + target_format: BLOOM_TEXTURE_FORMAT, }, ); @@ -159,7 +153,7 @@ pub fn prepare_upsampling_pipeline( &pipeline, BloomUpsamplingPipelineKeys { composite_mode: bloom.composite_mode, - final_pipeline: true, + target_format: view.target_format, }, ); diff --git a/crates/bevy_post_process/src/dof/mod.rs b/crates/bevy_post_process/src/dof/mod.rs index 9b0077d8569a3..5c55529af03f4 100644 --- a/crates/bevy_post_process/src/dof/mod.rs +++ b/crates/bevy_post_process/src/dof/mod.rs @@ -28,7 +28,6 @@ use bevy_ecs::{ system::{lifetimeless::Read, Commands, Query, Res, ResMut}, world::World, }; -use bevy_image::BevyDefault as _; use bevy_math::ops; use bevy_reflect::{prelude::ReflectDefault, Reflect}; use bevy_render::{ @@ -186,8 +185,7 @@ pub struct DepthOfFieldUniform { pub struct DepthOfFieldPipelineKey { /// Whether we're doing Gaussian or bokeh blur. pass: DofPass, - /// Whether we're using HDR. - hdr: bool, + target_format: TextureFormat, /// Whether the render target is multisampled. multisample: bool, } @@ -690,8 +688,7 @@ pub fn prepare_depth_of_field_pipelines( fragment_shader: load_embedded_asset!(asset_server.as_ref(), "dof.wgsl"), }; - // We'll need these two flags to create the `DepthOfFieldPipelineKey`s. - let (hdr, multisample) = (view.hdr, *msaa != Msaa::Off); + let multisample = *msaa != Msaa::Off; // Go ahead and specialize the pipelines. match depth_of_field.mode { @@ -703,7 +700,7 @@ pub fn prepare_depth_of_field_pipelines( &pipeline_cache, &dof_pipeline, DepthOfFieldPipelineKey { - hdr, + target_format: view.target_format, multisample, pass: DofPass::GaussianHorizontal, }, @@ -712,7 +709,7 @@ pub fn prepare_depth_of_field_pipelines( &pipeline_cache, &dof_pipeline, DepthOfFieldPipelineKey { - hdr, + target_format: view.target_format, multisample, pass: DofPass::GaussianVertical, }, @@ -728,7 +725,7 @@ pub fn prepare_depth_of_field_pipelines( &pipeline_cache, &dof_pipeline, DepthOfFieldPipelineKey { - hdr, + target_format: view.target_format, multisample, pass: DofPass::BokehPass0, }, @@ -737,7 +734,7 @@ pub fn prepare_depth_of_field_pipelines( &pipeline_cache, &dof_pipeline, DepthOfFieldPipelineKey { - hdr, + target_format: view.target_format, multisample, pass: DofPass::BokehPass1, }, @@ -755,11 +752,7 @@ impl SpecializedRenderPipeline for DepthOfFieldPipeline { // Build up our pipeline layout. let (mut layout, mut shader_defs) = (vec![], vec![]); let mut targets = vec![Some(ColorTargetState { - format: if key.hdr { - ViewTarget::TEXTURE_FORMAT_HDR - } else { - TextureFormat::bevy_default() - }, + format: key.target_format, blend: None, write_mask: ColorWrites::ALL, })]; diff --git a/crates/bevy_post_process/src/effect_stack/mod.rs b/crates/bevy_post_process/src/effect_stack/mod.rs index 8ad769efaa53a..0544406d57fd7 100644 --- a/crates/bevy_post_process/src/effect_stack/mod.rs +++ b/crates/bevy_post_process/src/effect_stack/mod.rs @@ -18,7 +18,7 @@ use bevy_ecs::{ system::{lifetimeless::Read, Commands, Query, Res, ResMut}, world::World, }; -use bevy_image::{BevyDefault, Image}; +use bevy_image::Image; use bevy_reflect::{std_traits::ReflectDefault, Reflect}; use bevy_render::{ diagnostic::RecordDiagnostics, @@ -433,11 +433,7 @@ pub fn prepare_post_processing_pipelines( &pipeline_cache, &post_processing_pipeline, PostProcessingPipelineKey { - texture_format: if view.hdr { - ViewTarget::TEXTURE_FORMAT_HDR - } else { - TextureFormat::bevy_default() - }, + texture_format: view.target_format, }, ); diff --git a/crates/bevy_post_process/src/motion_blur/pipeline.rs b/crates/bevy_post_process/src/motion_blur/pipeline.rs index dc9dbe8f762f3..3fbefe0a3de39 100644 --- a/crates/bevy_post_process/src/motion_blur/pipeline.rs +++ b/crates/bevy_post_process/src/motion_blur/pipeline.rs @@ -7,7 +7,6 @@ use bevy_ecs::{ resource::Resource, system::{Commands, Query, Res, ResMut}, }; -use bevy_image::BevyDefault as _; use bevy_render::{ globals::GlobalsUniform, render_resource::{ @@ -21,7 +20,7 @@ use bevy_render::{ SpecializedRenderPipelines, TextureFormat, TextureSampleType, }, renderer::RenderDevice, - view::{ExtractedView, Msaa, ViewTarget}, + view::{ExtractedView, Msaa}, }; use bevy_shader::{Shader, ShaderDefVal}; use bevy_utils::default; @@ -111,7 +110,7 @@ pub fn init_motion_blur_pipeline( #[derive(PartialEq, Eq, Hash, Clone, Copy)] pub struct MotionBlurPipelineKey { - hdr: bool, + target_format: TextureFormat, samples: u32, } @@ -144,11 +143,7 @@ impl SpecializedRenderPipeline for MotionBlurPipeline { shader: self.fragment_shader.clone(), shader_defs, targets: vec![Some(ColorTargetState { - format: if key.hdr { - ViewTarget::TEXTURE_FORMAT_HDR - } else { - TextureFormat::bevy_default() - }, + format: key.target_format, blend: None, write_mask: ColorWrites::ALL, })], @@ -174,7 +169,7 @@ pub(crate) fn prepare_motion_blur_pipelines( &pipeline_cache, &pipeline, MotionBlurPipelineKey { - hdr: view.hdr, + target_format: view.target_format, samples: msaa.samples(), }, ); diff --git a/crates/bevy_reflect/src/impls/wgpu_types.rs b/crates/bevy_reflect/src/impls/wgpu_types.rs index b0ca0d2308b82..4b970cd9f040d 100644 --- a/crates/bevy_reflect/src/impls/wgpu_types.rs +++ b/crates/bevy_reflect/src/impls/wgpu_types.rs @@ -16,3 +16,11 @@ impl_reflect_opaque!(::wgpu_types::BlendState( Deserialize, Serialize, )); +impl_reflect_opaque!(::wgpu_types::TextureUsages( + Clone, + Debug, + Hash, + PartialEq, + Deserialize, + Serialize, +)); diff --git a/crates/bevy_render/src/camera.rs b/crates/bevy_render/src/camera.rs index cb5bcb2500bbe..00d2cbcbe09ca 100644 --- a/crates/bevy_render/src/camera.rs +++ b/crates/bevy_render/src/camera.rs @@ -19,9 +19,9 @@ use bevy_asset::{AssetEvent, AssetEventSystems, AssetId, Assets}; use bevy_camera::{ primitives::Frustum, visibility::{self, RenderLayers, VisibleEntities}, - Camera, Camera2d, Camera3d, CameraMainTextureUsages, CameraOutputMode, CameraUpdateSystems, - ClearColor, ClearColorConfig, Exposure, ManualTextureViewHandle, NormalizedRenderTarget, - Projection, RenderTargetInfo, Viewport, + Camera, Camera2d, Camera3d, CameraMainTextureFormat, CameraMainTextureUsages, CameraOutputMode, + CameraUpdateSystems, ClearColor, ClearColorConfig, Exposure, ManualTextureViewHandle, + NormalizedRenderTarget, Projection, RenderTargetInfo, Viewport, }; use bevy_derive::{Deref, DerefMut}; use bevy_ecs::{ @@ -32,7 +32,7 @@ use bevy_ecs::{ lifecycle::HookContext, message::MessageReader, prelude::With, - query::{Has, QueryItem}, + query::{Has, QueryData, QueryItem}, reflect::ReflectComponent, resource::Resource, schedule::IntoScheduleConfigs, @@ -60,6 +60,7 @@ impl Plugin for CameraPlugin { .add_plugins(( ExtractResourcePlugin::::default(), ExtractComponentPlugin::::default(), + ExtractComponentPlugin::::default(), )) .add_systems(PostStartup, camera_system.in_set(CameraUpdateSystems)) .add_systems( @@ -108,6 +109,15 @@ impl ExtractComponent for CameraMainTextureUsages { Some(*item) } } +impl ExtractComponent for CameraMainTextureFormat { + type QueryData = &'static Self; + type QueryFilter = (); + type Out = Self; + + fn extract_component(item: QueryItem) -> Option { + Some(*item) + } +} impl ExtractComponent for Camera2d { type QueryData = &'static Self; type QueryFilter = With; @@ -416,27 +426,29 @@ pub struct ExtractedCamera { pub hdr: bool, } +#[derive(QueryData)] +pub struct CameraQuery<'a> { + main_entity: Entity, + render_entity: RenderEntity, + camera: &'a Camera, + camera_render_graph: &'a CameraRenderGraph, + transform: &'a GlobalTransform, + visible_entities: &'a VisibleEntities, + frustum: &'a Frustum, + camera_main_texture_format: &'a CameraMainTextureFormat, + hdr: Has, + color_grading: Option<&'a ColorGrading>, + exposure: Option<&'a Exposure>, + temporal_jitter: Option<&'a TemporalJitter>, + mip_bias: Option<&'a MipBias>, + render_layers: Option<&'a RenderLayers>, + projection: Option<&'a Projection>, + no_indirect_drawing: Has, +} + pub fn extract_cameras( mut commands: Commands, - query: Extract< - Query<( - Entity, - RenderEntity, - &Camera, - &CameraRenderGraph, - &GlobalTransform, - &VisibleEntities, - &Frustum, - Has, - Option<&ColorGrading>, - Option<&Exposure>, - Option<&TemporalJitter>, - Option<&MipBias>, - Option<&RenderLayers>, - Option<&Projection>, - Has, - )>, - >, + query: Extract>, primary_window: Extract>>, gpu_preprocessing_support: Res, mapper: Extract>, @@ -453,7 +465,7 @@ pub fn extract_cameras( NoIndirectDrawing, ViewUniformOffset, ); - for ( + for CameraQueryItem { main_entity, render_entity, camera, @@ -461,6 +473,7 @@ pub fn extract_cameras( transform, visible_entities, frustum, + camera_main_texture_format, hdr, color_grading, exposure, @@ -469,7 +482,7 @@ pub fn extract_cameras( render_layers, projection, no_indirect_drawing, - ) in query.iter() + } in query.iter() { if !camera.is_active { commands @@ -544,7 +557,6 @@ pub fn extract_cameras( clip_from_view: camera.clip_from_view(), world_from_view: *transform, clip_from_world: None, - hdr, viewport: UVec4::new( viewport_origin.x, viewport_origin.y, @@ -552,6 +564,12 @@ pub fn extract_cameras( viewport_size.y, ), color_grading, + target_format: if hdr { + camera_main_texture_format.hdr_format + } else { + camera_main_texture_format.sdr_format + }, + hdr, }, render_visible_entities, *frustum, diff --git a/crates/bevy_render/src/lib.rs b/crates/bevy_render/src/lib.rs index b3620c7e079fa..28e115c1e0ce8 100644 --- a/crates/bevy_render/src/lib.rs +++ b/crates/bevy_render/src/lib.rs @@ -584,3 +584,60 @@ pub fn get_mali_driver_version(adapter_info: &RenderAdapterInfo) -> Option None } + +#[doc(hidden)] +#[macro_export] +macro_rules! declare_view_target_format_fn { + () => { + /// Create a pipeline key from view target format. + #[inline] + pub fn from_view_target_format(format: TextureFormat) -> Self { + match format { + TextureFormat::R8Unorm => Self::VIEW_TARGET_FORMAT_R8UNORM, + TextureFormat::Rg8Unorm => Self::VIEW_TARGET_FORMAT_RG8UNORM, + TextureFormat::Rgba8Unorm => Self::VIEW_TARGET_FORMAT_RGBA8UNORM, + TextureFormat::Rgba8UnormSrgb => Self::VIEW_TARGET_FORMAT_RGBA8UNORMSRGB, + TextureFormat::Bgra8Unorm => Self::VIEW_TARGET_FORMAT_BGRA8UNORM, + TextureFormat::Bgra8UnormSrgb => Self::VIEW_TARGET_FORMAT_BGRA8UNORMSRGB, + TextureFormat::R16Float => Self::VIEW_TARGET_FORMAT_R16FLOAT, + TextureFormat::Rg16Float => Self::VIEW_TARGET_FORMAT_RG16FLOAT, + TextureFormat::Rgba16Float => Self::VIEW_TARGET_FORMAT_RGBA16FLOAT, + TextureFormat::Rg11b10Ufloat => Self::VIEW_TARGET_FORMAT_RB11B10FLOAT, + TextureFormat::Rgb10a2Unorm => Self::VIEW_TARGET_FORMAT_RGB10A2UNORM, + _ => unreachable!("Unsupported view target format"), + } + } + + /// Get the view target format of this pipeline key. + #[inline] + pub fn view_target_format(&self) -> TextureFormat { + let target_format = *self & Self::VIEW_TARGET_FORMAT_RESERVED_BITS; + + if target_format == Self::VIEW_TARGET_FORMAT_R8UNORM { + TextureFormat::R8Unorm + } else if target_format == Self::VIEW_TARGET_FORMAT_RG8UNORM { + TextureFormat::Rg8Unorm + } else if target_format == Self::VIEW_TARGET_FORMAT_RGBA8UNORM { + TextureFormat::Rgba8Unorm + } else if target_format == Self::VIEW_TARGET_FORMAT_RGBA8UNORMSRGB { + TextureFormat::Rgba8UnormSrgb + } else if target_format == Self::VIEW_TARGET_FORMAT_BGRA8UNORM { + TextureFormat::Bgra8Unorm + } else if target_format == Self::VIEW_TARGET_FORMAT_BGRA8UNORMSRGB { + TextureFormat::Bgra8UnormSrgb + } else if target_format == Self::VIEW_TARGET_FORMAT_R16FLOAT { + TextureFormat::R16Float + } else if target_format == Self::VIEW_TARGET_FORMAT_RG16FLOAT { + TextureFormat::Rg16Float + } else if target_format == Self::VIEW_TARGET_FORMAT_RGBA16FLOAT { + TextureFormat::Rgba16Float + } else if target_format == Self::VIEW_TARGET_FORMAT_RB11B10FLOAT { + TextureFormat::Rg11b10Ufloat + } else if target_format == Self::VIEW_TARGET_FORMAT_RGB10A2UNORM { + TextureFormat::Rgb10a2Unorm + } else { + unreachable!("Unsupported view target format") + } + } + }; +} diff --git a/crates/bevy_render/src/view/mod.rs b/crates/bevy_render/src/view/mod.rs index ea95b7fad725b..a2e0e6107292b 100644 --- a/crates/bevy_render/src/view/mod.rs +++ b/crates/bevy_render/src/view/mod.rs @@ -2,8 +2,8 @@ pub mod visibility; pub mod window; use bevy_camera::{ - primitives::Frustum, CameraMainTextureUsages, ClearColor, ClearColorConfig, Exposure, - MainPassResolutionOverride, NormalizedRenderTarget, + primitives::Frustum, CameraMainTextureFormat, CameraMainTextureUsages, ClearColor, + ClearColorConfig, Exposure, MainPassResolutionOverride, NormalizedRenderTarget, }; use bevy_diagnostic::FrameCount; pub use visibility::*; @@ -29,7 +29,7 @@ use bevy_app::{App, Plugin}; use bevy_color::LinearRgba; use bevy_derive::{Deref, DerefMut}; use bevy_ecs::prelude::*; -use bevy_image::{BevyDefault as _, ToExtents}; +use bevy_image::ToExtents; use bevy_math::{mat3, vec2, vec3, Mat3, Mat4, UVec4, Vec2, Vec3, Vec4, Vec4Swizzles}; use bevy_platform::collections::{hash_map::Entry, HashMap}; use bevy_reflect::{std_traits::ReflectDefault, Reflect}; @@ -299,6 +299,7 @@ pub struct ExtractedView { // stability matters and there is a more direct way to derive the view-projection matrix. pub clip_from_world: Option, pub hdr: bool, + pub target_format: TextureFormat, // uvec4(origin.x, origin.y, width, height) pub viewport: UVec4, pub color_grading: ColorGrading, @@ -605,6 +606,7 @@ pub struct ViewUniformOffset { pub struct ViewTarget { main_textures: MainTargetTextures, main_texture_format: TextureFormat, + hdr: bool, /// 0 represents `main_textures.a`, 1 represents `main_textures.b` /// This is shared across view targets with the same render target main_texture: Arc, @@ -722,8 +724,6 @@ impl From for ColorGradingUniform { pub struct NoIndirectDrawing; impl ViewTarget { - pub const TEXTURE_FORMAT_HDR: TextureFormat = TextureFormat::Rgba16Float; - /// Retrieve this target's main texture's color attachment. pub fn get_color_attachment(&self) -> RenderPassColorAttachment<'_> { if self.main_texture.load(Ordering::SeqCst) == 0 { @@ -811,10 +811,10 @@ impl ViewTarget { self.main_texture_format } - /// Returns `true` if and only if the main texture is [`Self::TEXTURE_FORMAT_HDR`] + /// Returns `true` if the view target is using HDR rendering. #[inline] pub fn is_hdr(&self) -> bool { - self.main_texture_format == ViewTarget::TEXTURE_FORMAT_HDR + self.hdr } /// The final texture this view will render to. @@ -1035,14 +1035,15 @@ pub fn prepare_view_targets( cameras: Query<( Entity, &ExtractedCamera, - &ExtractedView, &CameraMainTextureUsages, + &CameraMainTextureFormat, + Has, &Msaa, )>, view_target_attachments: Res, ) { let mut textures = >::default(); - for (entity, camera, view, texture_usage, msaa) in cameras.iter() { + for (entity, camera, texture_usage, texture_format, hdr, msaa) in cameras.iter() { let (Some(target_size), Some(target)) = (camera.physical_target_size, &camera.target) else { continue; @@ -1052,10 +1053,10 @@ pub fn prepare_view_targets( continue; }; - let main_texture_format = if view.hdr { - ViewTarget::TEXTURE_FORMAT_HDR + let main_texture_format = if hdr { + texture_format.hdr_format } else { - TextureFormat::bevy_default() + texture_format.sdr_format }; let clear_color = match camera.clear_color { @@ -1065,7 +1066,7 @@ pub fn prepare_view_targets( }; let (a, b, sampled, main_texture) = textures - .entry((camera.target.clone(), texture_usage.0, view.hdr, msaa)) + .entry((camera.target.clone(), texture_usage.0, msaa)) .or_insert_with(|| { let descriptor = TextureDescriptor { label: None, @@ -1130,6 +1131,7 @@ pub fn prepare_view_targets( main_textures, main_texture_format, out_texture: out_attachment.clone(), + hdr, }); } } diff --git a/crates/bevy_render/src/view/window/screenshot.rs b/crates/bevy_render/src/view/window/screenshot.rs index 4418c7d5d74d2..648988698aaf5 100644 --- a/crates/bevy_render/src/view/window/screenshot.rs +++ b/crates/bevy_render/src/view/window/screenshot.rs @@ -644,8 +644,8 @@ pub(crate) fn collect_screenshots(world: &mut World) { // The polling for this map call is done every frame when the command queue is submitted. buffer_slice.map_async(wgpu::MapMode::Read, move |result| { let err = result.err(); - if err.is_some() { - panic!("{}", err.unwrap().to_string()); + if let Some(e) = err { + panic!("{}", e.to_string()); } tx.try_send(()).unwrap(); }); diff --git a/crates/bevy_shader/src/shader_cache.rs b/crates/bevy_shader/src/shader_cache.rs index 77a004ecebb8e..c9f8c068bfb26 100644 --- a/crates/bevy_shader/src/shader_cache.rs +++ b/crates/bevy_shader/src/shader_cache.rs @@ -5,7 +5,7 @@ use bevy_platform::collections::{hash_map::EntryRef, HashMap, HashSet}; use core::hash::Hash; use naga::valid::Capabilities; use thiserror::Error; -use tracing::{debug, error}; +use tracing::debug; use wgpu_types::{DownlevelFlags, Features}; /// Source of a shader module. diff --git a/crates/bevy_solari/src/pathtracer/node.rs b/crates/bevy_solari/src/pathtracer/node.rs index 325ea42dac6a9..7cf3c6782853d 100644 --- a/crates/bevy_solari/src/pathtracer/node.rs +++ b/crates/bevy_solari/src/pathtracer/node.rs @@ -105,10 +105,7 @@ impl FromWorld for PathtracerNode { ShaderStages::COMPUTE, ( texture_storage_2d(TextureFormat::Rgba32Float, StorageTextureAccess::ReadWrite), - texture_storage_2d( - ViewTarget::TEXTURE_FORMAT_HDR, - StorageTextureAccess::WriteOnly, - ), + texture_storage_2d(TextureFormat::Rgba16Float, StorageTextureAccess::WriteOnly), uniform_buffer::(true), ), ), diff --git a/crates/bevy_solari/src/realtime/node.rs b/crates/bevy_solari/src/realtime/node.rs index 9d3e8e5d0d9c9..3f96e45c0c203 100644 --- a/crates/bevy_solari/src/realtime/node.rs +++ b/crates/bevy_solari/src/realtime/node.rs @@ -360,10 +360,7 @@ impl FromWorld for SolariLightingNode { &BindGroupLayoutEntries::sequential( ShaderStages::COMPUTE, ( - texture_storage_2d( - ViewTarget::TEXTURE_FORMAT_HDR, - StorageTextureAccess::ReadWrite, - ), + texture_storage_2d(TextureFormat::Rgba16Float, StorageTextureAccess::ReadWrite), storage_buffer_sized(false, None), storage_buffer_sized(false, None), texture_storage_2d(TextureFormat::Rgba32Uint, StorageTextureAccess::ReadWrite), diff --git a/crates/bevy_sprite_render/src/mesh2d/mesh.rs b/crates/bevy_sprite_render/src/mesh2d/mesh.rs index 7b6032306cbde..f76986ae3e79c 100644 --- a/crates/bevy_sprite_render/src/mesh2d/mesh.rs +++ b/crates/bevy_sprite_render/src/mesh2d/mesh.rs @@ -20,7 +20,7 @@ use bevy_ecs::{ query::ROQueryItem, system::{lifetimeless::*, SystemParamItem}, }; -use bevy_image::{BevyDefault, Image, ImageSampler, TextureFormatPixelInfo}; +use bevy_image::{Image, ImageSampler, TextureFormatPixelInfo}; use bevy_math::{Affine3, Vec4}; use bevy_mesh::{Mesh, Mesh2d, MeshTag, MeshVertexBufferLayoutRef}; use bevy_render::prelude::Msaa; @@ -45,7 +45,7 @@ use bevy_render::{ renderer::{RenderDevice, RenderQueue}, sync_world::{MainEntity, MainEntityHashMap}, texture::{DefaultImageSampler, FallbackImage, GpuImage}, - view::{ExtractedView, ViewTarget, ViewUniform, ViewUniformOffset, ViewUniforms}, + view::{ExtractedView, ViewUniform, ViewUniformOffset, ViewUniforms}, Extract, ExtractSchedule, Render, RenderApp, RenderSystems, }; use bevy_transform::components::GlobalTransform; @@ -133,7 +133,7 @@ pub fn check_views_need_specialization( ) { for (view_entity, view, msaa, tonemapping, dither) in &views { let mut view_key = Mesh2dPipelineKey::from_msaa_samples(msaa.samples()) - | Mesh2dPipelineKey::from_hdr(view.hdr); + | Mesh2dPipelineKey::from_view_target_format(view.target_format); if !view.hdr { if let Some(tonemapping) = tonemapping { @@ -492,6 +492,18 @@ bitflags::bitflags! { const TONEMAP_METHOD_SOMEWHAT_BORING_DISPLAY_TRANSFORM = 5 << Self::TONEMAP_METHOD_SHIFT_BITS; const TONEMAP_METHOD_TONY_MC_MAPFACE = 6 << Self::TONEMAP_METHOD_SHIFT_BITS; const TONEMAP_METHOD_BLENDER_FILMIC = 7 << Self::TONEMAP_METHOD_SHIFT_BITS; + const VIEW_TARGET_FORMAT_RESERVED_BITS = Self::VIEW_TARGET_FORMAT_MASK_BITS << Self::VIEW_TARGET_FORMAT_SHIFT_BITS; + const VIEW_TARGET_FORMAT_R8UNORM = 0 << Self::VIEW_TARGET_FORMAT_SHIFT_BITS; + const VIEW_TARGET_FORMAT_RG8UNORM = 1 << Self::VIEW_TARGET_FORMAT_SHIFT_BITS; + const VIEW_TARGET_FORMAT_RGBA8UNORM = 2 << Self::VIEW_TARGET_FORMAT_SHIFT_BITS; + const VIEW_TARGET_FORMAT_RGBA8UNORMSRGB = 3 << Self::VIEW_TARGET_FORMAT_SHIFT_BITS; + const VIEW_TARGET_FORMAT_BGRA8UNORM = 4 << Self::VIEW_TARGET_FORMAT_SHIFT_BITS; + const VIEW_TARGET_FORMAT_BGRA8UNORMSRGB = 5 << Self::VIEW_TARGET_FORMAT_SHIFT_BITS; + const VIEW_TARGET_FORMAT_R16FLOAT = 6 << Self::VIEW_TARGET_FORMAT_SHIFT_BITS; + const VIEW_TARGET_FORMAT_RG16FLOAT = 7 << Self::VIEW_TARGET_FORMAT_SHIFT_BITS; + const VIEW_TARGET_FORMAT_RGBA16FLOAT = 8 << Self::VIEW_TARGET_FORMAT_SHIFT_BITS; + const VIEW_TARGET_FORMAT_RB11B10FLOAT = 9 << Self::VIEW_TARGET_FORMAT_SHIFT_BITS; + const VIEW_TARGET_FORMAT_RGB10A2UNORM = 10 << Self::VIEW_TARGET_FORMAT_SHIFT_BITS; } } @@ -503,6 +515,9 @@ impl Mesh2dPipelineKey { const TONEMAP_METHOD_MASK_BITS: u32 = 0b111; const TONEMAP_METHOD_SHIFT_BITS: u32 = Self::PRIMITIVE_TOPOLOGY_SHIFT_BITS - Self::TONEMAP_METHOD_MASK_BITS.count_ones(); + const VIEW_TARGET_FORMAT_MASK_BITS: u32 = 0b1111; + const VIEW_TARGET_FORMAT_SHIFT_BITS: u32 = + Self::TONEMAP_METHOD_SHIFT_BITS - Self::VIEW_TARGET_FORMAT_MASK_BITS.count_ones(); pub fn from_msaa_samples(msaa_samples: u32) -> Self { let msaa_bits = @@ -510,14 +525,6 @@ impl Mesh2dPipelineKey { Self::from_bits_retain(msaa_bits) } - pub fn from_hdr(hdr: bool) -> Self { - if hdr { - Mesh2dPipelineKey::HDR - } else { - Mesh2dPipelineKey::NONE - } - } - pub fn msaa_samples(&self) -> u32 { 1 << ((self.bits() >> Self::MSAA_SHIFT_BITS) & Self::MSAA_MASK_BITS) } @@ -541,6 +548,8 @@ impl Mesh2dPipelineKey { _ => PrimitiveTopology::default(), } } + + bevy_render::declare_view_target_format_fn!(); } impl SpecializedMeshPipeline for Mesh2dPipeline { @@ -631,11 +640,6 @@ impl SpecializedMeshPipeline for Mesh2dPipeline { let vertex_buffer_layout = layout.0.get_layout(&vertex_attributes)?; - let format = match key.contains(Mesh2dPipelineKey::HDR) { - true => ViewTarget::TEXTURE_FORMAT_HDR, - false => TextureFormat::bevy_default(), - }; - let (depth_write_enabled, label, blend); if key.contains(Mesh2dPipelineKey::BLEND_ALPHA) { label = "transparent_mesh2d_pipeline"; @@ -658,7 +662,7 @@ impl SpecializedMeshPipeline for Mesh2dPipeline { shader: self.shader.clone(), shader_defs, targets: vec![Some(ColorTargetState { - format, + format: key.view_target_format(), blend, write_mask: ColorWrites::ALL, })], diff --git a/crates/bevy_sprite_render/src/render/mod.rs b/crates/bevy_sprite_render/src/render/mod.rs index 675b5da471541..9be0af2cf6592 100644 --- a/crates/bevy_sprite_render/src/render/mod.rs +++ b/crates/bevy_sprite_render/src/render/mod.rs @@ -17,7 +17,7 @@ use bevy_ecs::{ query::ROQueryItem, system::{lifetimeless::*, SystemParamItem}, }; -use bevy_image::{BevyDefault, Image, ImageSampler, TextureAtlasLayout, TextureFormatPixelInfo}; +use bevy_image::{Image, ImageSampler, TextureAtlasLayout, TextureFormatPixelInfo}; use bevy_math::{Affine3A, FloatOrd, Quat, Rect, Vec2, Vec4}; use bevy_mesh::VertexBufferLayout; use bevy_platform::collections::HashMap; @@ -35,7 +35,7 @@ use bevy_render::{ renderer::{RenderDevice, RenderQueue}, sync_world::RenderEntity, texture::{DefaultImageSampler, FallbackImage, GpuImage}, - view::{ExtractedView, Msaa, ViewTarget, ViewUniform, ViewUniformOffset, ViewUniforms}, + view::{ExtractedView, Msaa, ViewUniform, ViewUniformOffset, ViewUniforms}, Extract, }; use bevy_shader::{Shader, ShaderDefVal}; @@ -144,6 +144,18 @@ bitflags::bitflags! { const TONEMAP_METHOD_SOMEWHAT_BORING_DISPLAY_TRANSFORM = 5 << Self::TONEMAP_METHOD_SHIFT_BITS; const TONEMAP_METHOD_TONY_MC_MAPFACE = 6 << Self::TONEMAP_METHOD_SHIFT_BITS; const TONEMAP_METHOD_BLENDER_FILMIC = 7 << Self::TONEMAP_METHOD_SHIFT_BITS; + const VIEW_TARGET_FORMAT_RESERVED_BITS = Self::VIEW_TARGET_FORMAT_MASK_BITS << Self::VIEW_TARGET_FORMAT_SHIFT_BITS; + const VIEW_TARGET_FORMAT_R8UNORM = 0 << Self::VIEW_TARGET_FORMAT_SHIFT_BITS; + const VIEW_TARGET_FORMAT_RG8UNORM = 1 << Self::VIEW_TARGET_FORMAT_SHIFT_BITS; + const VIEW_TARGET_FORMAT_RGBA8UNORM = 2 << Self::VIEW_TARGET_FORMAT_SHIFT_BITS; + const VIEW_TARGET_FORMAT_RGBA8UNORMSRGB = 3 << Self::VIEW_TARGET_FORMAT_SHIFT_BITS; + const VIEW_TARGET_FORMAT_BGRA8UNORM = 4 << Self::VIEW_TARGET_FORMAT_SHIFT_BITS; + const VIEW_TARGET_FORMAT_BGRA8UNORMSRGB = 5 << Self::VIEW_TARGET_FORMAT_SHIFT_BITS; + const VIEW_TARGET_FORMAT_R16FLOAT = 6 << Self::VIEW_TARGET_FORMAT_SHIFT_BITS; + const VIEW_TARGET_FORMAT_RG16FLOAT = 7 << Self::VIEW_TARGET_FORMAT_SHIFT_BITS; + const VIEW_TARGET_FORMAT_RGBA16FLOAT = 8 << Self::VIEW_TARGET_FORMAT_SHIFT_BITS; + const VIEW_TARGET_FORMAT_RB11B10FLOAT = 9 << Self::VIEW_TARGET_FORMAT_SHIFT_BITS; + const VIEW_TARGET_FORMAT_RGB10A2UNORM = 10 << Self::VIEW_TARGET_FORMAT_SHIFT_BITS; } } @@ -153,6 +165,9 @@ impl SpritePipelineKey { const TONEMAP_METHOD_MASK_BITS: u32 = 0b111; const TONEMAP_METHOD_SHIFT_BITS: u32 = Self::MSAA_SHIFT_BITS - Self::TONEMAP_METHOD_MASK_BITS.count_ones(); + const VIEW_TARGET_FORMAT_MASK_BITS: u32 = 0b1111; + const VIEW_TARGET_FORMAT_SHIFT_BITS: u32 = + Self::TONEMAP_METHOD_SHIFT_BITS - Self::VIEW_TARGET_FORMAT_MASK_BITS.count_ones(); #[inline] pub const fn from_msaa_samples(msaa_samples: u32) -> Self { @@ -166,14 +181,7 @@ impl SpritePipelineKey { 1 << ((self.bits() >> Self::MSAA_SHIFT_BITS) & Self::MSAA_MASK_BITS) } - #[inline] - pub const fn from_hdr(hdr: bool) -> Self { - if hdr { - SpritePipelineKey::HDR - } else { - SpritePipelineKey::NONE - } - } + bevy_render::declare_view_target_format_fn!(); } impl SpecializedRenderPipeline for SpritePipeline { @@ -219,11 +227,6 @@ impl SpecializedRenderPipeline for SpritePipeline { } } - let format = match key.contains(SpritePipelineKey::HDR) { - true => ViewTarget::TEXTURE_FORMAT_HDR, - false => TextureFormat::bevy_default(), - }; - let instance_rate_vertex_buffer_layout = VertexBufferLayout { array_stride: 80, step_mode: VertexStepMode::Instance, @@ -272,7 +275,7 @@ impl SpecializedRenderPipeline for SpritePipeline { shader: self.shader.clone(), shader_defs, targets: vec![Some(ColorTargetState { - format, + format: key.view_target_format(), blend: Some(BlendState::ALPHA_BLENDING), write_mask: ColorWrites::ALL, })], @@ -533,7 +536,8 @@ pub fn queue_sprites( }; let msaa_key = SpritePipelineKey::from_msaa_samples(msaa.samples()); - let mut view_key = SpritePipelineKey::from_hdr(view.hdr) | msaa_key; + let mut view_key = + SpritePipelineKey::from_view_target_format(view.target_format) | msaa_key; if !view.hdr { if let Some(tonemapping) = tonemapping { diff --git a/crates/bevy_ui_render/src/box_shadow.rs b/crates/bevy_ui_render/src/box_shadow.rs index 6a8c3a3ac74be..a9efb9da58e46 100644 --- a/crates/bevy_ui_render/src/box_shadow.rs +++ b/crates/bevy_ui_render/src/box_shadow.rs @@ -14,7 +14,6 @@ use bevy_ecs::{ *, }, }; -use bevy_image::BevyDefault as _; use bevy_math::{vec2, Affine2, FloatOrd, Rect, Vec2}; use bevy_mesh::VertexBufferLayout; use bevy_render::sync_world::{MainEntity, TemporaryRenderEntity}; @@ -130,7 +129,7 @@ pub fn init_box_shadow_pipeline( #[derive(Clone, Copy, Hash, PartialEq, Eq)] pub struct BoxShadowPipelineKey { - pub hdr: bool, + pub target_format: TextureFormat, /// Number of samples, a higher value results in better quality shadows. pub samples: u32, } @@ -174,11 +173,7 @@ impl SpecializedRenderPipeline for BoxShadowPipeline { shader: self.shader.clone(), shader_defs, targets: vec![Some(ColorTargetState { - format: if key.hdr { - ViewTarget::TEXTURE_FORMAT_HDR - } else { - TextureFormat::bevy_default() - }, + format: key.target_format, blend: Some(BlendState::ALPHA_BLENDING), write_mask: ColorWrites::ALL, })], @@ -337,7 +332,7 @@ pub fn queue_shadows( &pipeline_cache, &box_shadow_pipeline, BoxShadowPipelineKey { - hdr: view.hdr, + target_format: view.target_format, samples: shadow_samples.copied().unwrap_or_default().0, }, ); diff --git a/crates/bevy_ui_render/src/gradient.rs b/crates/bevy_ui_render/src/gradient.rs index a2fbc7663d2a0..7b9fe268c03f8 100644 --- a/crates/bevy_ui_render/src/gradient.rs +++ b/crates/bevy_ui_render/src/gradient.rs @@ -15,7 +15,6 @@ use bevy_ecs::{ *, }, }; -use bevy_image::prelude::*; use bevy_math::{ ops::{cos, sin}, FloatOrd, Rect, Vec2, @@ -142,7 +141,7 @@ pub fn compute_gradient_line_length(angle: f32, size: Vec2) -> f32 { pub struct UiGradientPipelineKey { anti_alias: bool, color_space: InterpolationColorSpace, - pub hdr: bool, + pub target_format: TextureFormat, } impl SpecializedRenderPipeline for GradientPipeline { @@ -211,11 +210,7 @@ impl SpecializedRenderPipeline for GradientPipeline { shader: self.shader.clone(), shader_defs, targets: vec![Some(ColorTargetState { - format: if key.hdr { - ViewTarget::TEXTURE_FORMAT_HDR - } else { - TextureFormat::bevy_default() - }, + format: key.target_format, blend: Some(BlendState::ALPHA_BLENDING), write_mask: ColorWrites::ALL, })], @@ -616,7 +611,7 @@ pub fn queue_gradient( UiGradientPipelineKey { anti_alias: matches!(ui_anti_alias, None | Some(UiAntiAlias::On)), color_space: gradient.color_space, - hdr: view.hdr, + target_format: view.target_format, }, ); diff --git a/crates/bevy_ui_render/src/lib.rs b/crates/bevy_ui_render/src/lib.rs index d7a152868dd3c..445d569a42375 100644 --- a/crates/bevy_ui_render/src/lib.rs +++ b/crates/bevy_ui_render/src/lib.rs @@ -19,7 +19,7 @@ pub mod ui_texture_slice_pipeline; mod debug_overlay; use bevy_camera::visibility::InheritedVisibility; -use bevy_camera::{Camera, Camera2d, Camera3d}; +use bevy_camera::{Camera, Camera2d, Camera3d, CameraMainTextureFormat}; use bevy_reflect::prelude::ReflectDefault; use bevy_reflect::Reflect; use bevy_shader::load_shader_library; @@ -753,6 +753,7 @@ pub fn extract_ui_camera_view( Entity, RenderEntity, &Camera, + &CameraMainTextureFormat, Has, Option<&UiAntiAlias>, Option<&BoxShadowSamples>, @@ -764,7 +765,16 @@ pub fn extract_ui_camera_view( ) { live_entities.clear(); - for (main_entity, render_entity, camera, hdr, ui_anti_alias, shadow_samples) in &query { + for ( + main_entity, + render_entity, + camera, + camera_main_texture_format, + hdr, + ui_anti_alias, + shadow_samples, + ) in &query + { // ignore inactive cameras if !camera.is_active { commands @@ -801,6 +811,11 @@ pub fn extract_ui_camera_view( ), clip_from_world: None, hdr, + target_format: if hdr { + camera_main_texture_format.hdr_format + } else { + camera_main_texture_format.sdr_format + }, viewport: UVec4::from(( physical_viewport_rect.min, physical_viewport_rect.size(), @@ -1259,7 +1274,7 @@ pub fn queue_uinodes( &pipeline_cache, &ui_pipeline, UiPipelineKey { - hdr: view.hdr, + target_format: view.target_format, anti_alias: matches!(ui_anti_alias, None | Some(UiAntiAlias::On)), }, ); diff --git a/crates/bevy_ui_render/src/pipeline.rs b/crates/bevy_ui_render/src/pipeline.rs index ca81b62fe067c..12a993152b585 100644 --- a/crates/bevy_ui_render/src/pipeline.rs +++ b/crates/bevy_ui_render/src/pipeline.rs @@ -1,6 +1,5 @@ use bevy_asset::{load_embedded_asset, AssetServer, Handle}; use bevy_ecs::prelude::*; -use bevy_image::BevyDefault as _; use bevy_mesh::VertexBufferLayout; use bevy_render::{ render_resource::{ @@ -8,7 +7,7 @@ use bevy_render::{ *, }, renderer::RenderDevice, - view::{ViewTarget, ViewUniform}, + view::ViewUniform, }; use bevy_shader::Shader; use bevy_utils::default; @@ -53,7 +52,7 @@ pub fn init_ui_pipeline( #[derive(Clone, Copy, Hash, PartialEq, Eq)] pub struct UiPipelineKey { - pub hdr: bool, + pub target_format: TextureFormat, pub anti_alias: bool, } @@ -99,11 +98,7 @@ impl SpecializedRenderPipeline for UiPipeline { shader: self.shader.clone(), shader_defs, targets: vec![Some(ColorTargetState { - format: if key.hdr { - ViewTarget::TEXTURE_FORMAT_HDR - } else { - TextureFormat::bevy_default() - }, + format: key.target_format, blend: Some(BlendState::ALPHA_BLENDING), write_mask: ColorWrites::ALL, })], diff --git a/crates/bevy_ui_render/src/ui_material.rs b/crates/bevy_ui_render/src/ui_material.rs index fc3ff836bdc40..40a7b64253e41 100644 --- a/crates/bevy_ui_render/src/ui_material.rs +++ b/crates/bevy_ui_render/src/ui_material.rs @@ -5,7 +5,7 @@ use bevy_ecs::{component::Component, reflect::ReflectComponent}; use bevy_reflect::{prelude::ReflectDefault, Reflect}; use bevy_render::{ extract_component::ExtractComponent, - render_resource::{AsBindGroup, RenderPipelineDescriptor}, + render_resource::{AsBindGroup, RenderPipelineDescriptor, TextureFormat}, }; use bevy_shader::ShaderRef; use derive_more::derive::From; @@ -121,7 +121,7 @@ pub trait UiMaterial: AsBindGroup + Asset + Clone + Sized { } pub struct UiMaterialKey { - pub hdr: bool, + pub target_format: TextureFormat, pub bind_group_data: M::Data, } @@ -132,7 +132,7 @@ where M::Data: PartialEq, { fn eq(&self, other: &Self) -> bool { - self.hdr == other.hdr && self.bind_group_data == other.bind_group_data + self.target_format == other.target_format && self.bind_group_data == other.bind_group_data } } @@ -142,7 +142,7 @@ where { fn clone(&self) -> Self { Self { - hdr: self.hdr, + target_format: self.target_format, bind_group_data: self.bind_group_data.clone(), } } @@ -153,7 +153,7 @@ where M::Data: core::hash::Hash, { fn hash(&self, state: &mut H) { - self.hdr.hash(state); + self.target_format.hash(state); self.bind_group_data.hash(state); } } diff --git a/crates/bevy_ui_render/src/ui_material_pipeline.rs b/crates/bevy_ui_render/src/ui_material_pipeline.rs index da047b8129349..1ed934b79660b 100644 --- a/crates/bevy_ui_render/src/ui_material_pipeline.rs +++ b/crates/bevy_ui_render/src/ui_material_pipeline.rs @@ -9,7 +9,6 @@ use bevy_ecs::{ *, }, }; -use bevy_image::BevyDefault as _; use bevy_math::{Affine2, FloatOrd, Rect, Vec2}; use bevy_mesh::VertexBufferLayout; use bevy_render::{ @@ -155,11 +154,7 @@ where shader: self.fragment_shader.clone(), shader_defs, targets: vec![Some(ColorTargetState { - format: if key.hdr { - ViewTarget::TEXTURE_FORMAT_HDR - } else { - TextureFormat::bevy_default() - }, + format: key.target_format, blend: Some(BlendState::ALPHA_BLENDING), write_mask: ColorWrites::ALL, })], @@ -610,7 +605,7 @@ pub fn queue_ui_material_nodes( &pipeline_cache, &ui_material_pipeline, UiMaterialKey { - hdr: view.hdr, + target_format: view.target_format, bind_group_data: material.key.clone(), }, ); diff --git a/crates/bevy_ui_render/src/ui_texture_slice_pipeline.rs b/crates/bevy_ui_render/src/ui_texture_slice_pipeline.rs index 2a417b6950afb..9bba52b7e1dc2 100644 --- a/crates/bevy_ui_render/src/ui_texture_slice_pipeline.rs +++ b/crates/bevy_ui_render/src/ui_texture_slice_pipeline.rs @@ -141,7 +141,7 @@ pub fn init_ui_texture_slice_pipeline( #[derive(Clone, Copy, Hash, PartialEq, Eq)] pub struct UiTextureSlicePipelineKey { - pub hdr: bool, + pub target_format: TextureFormat, } impl SpecializedRenderPipeline for UiTextureSlicePipeline { @@ -180,11 +180,7 @@ impl SpecializedRenderPipeline for UiTextureSlicePipeline { shader: self.shader.clone(), shader_defs, targets: vec![Some(ColorTargetState { - format: if key.hdr { - ViewTarget::TEXTURE_FORMAT_HDR - } else { - TextureFormat::bevy_default() - }, + format: key.target_format, blend: Some(BlendState::ALPHA_BLENDING), write_mask: ColorWrites::ALL, })], @@ -340,7 +336,9 @@ pub fn queue_ui_slices( let pipeline = pipelines.specialize( &pipeline_cache, &ui_slicer_pipeline, - UiTextureSlicePipelineKey { hdr: view.hdr }, + UiTextureSlicePipelineKey { + target_format: view.target_format, + }, ); transparent_phase.add(TransparentUi { diff --git a/examples/2d/mesh2d_manual.rs b/examples/2d/mesh2d_manual.rs index 79913288767a8..f45f9d671fd5f 100644 --- a/examples/2d/mesh2d_manual.rs +++ b/examples/2d/mesh2d_manual.rs @@ -23,12 +23,12 @@ use bevy::{ BlendState, ColorTargetState, ColorWrites, CompareFunction, DepthBiasState, DepthStencilState, Face, FragmentState, MultisampleState, PipelineCache, PrimitiveState, PrimitiveTopology, RenderPipelineDescriptor, SpecializedRenderPipeline, - SpecializedRenderPipelines, StencilFaceState, StencilState, TextureFormat, - VertexFormat, VertexState, VertexStepMode, + SpecializedRenderPipelines, StencilFaceState, StencilState, VertexFormat, VertexState, + VertexStepMode, }, sync_component::SyncComponentPlugin, sync_world::{MainEntityHashMap, RenderEntity}, - view::{ExtractedView, RenderVisibleEntities, ViewTarget}, + view::{ExtractedView, RenderVisibleEntities}, Extract, Render, RenderApp, RenderStartup, RenderSystems, }, sprite_render::{ @@ -163,10 +163,7 @@ impl SpecializedRenderPipeline for ColoredMesh2dPipeline { let vertex_layout = VertexBufferLayout::from_vertex_formats(VertexStepMode::Vertex, formats); - let format = match key.contains(Mesh2dPipelineKey::HDR) { - true => ViewTarget::TEXTURE_FORMAT_HDR, - false => TextureFormat::bevy_default(), - }; + let format = key.view_target_format(); RenderPipelineDescriptor { vertex: VertexState { @@ -397,7 +394,7 @@ pub fn queue_colored_mesh2d( let draw_colored_mesh2d = transparent_draw_functions.read().id::(); let mesh_key = Mesh2dPipelineKey::from_msaa_samples(msaa.samples()) - | Mesh2dPipelineKey::from_hdr(view.hdr); + | Mesh2dPipelineKey::from_view_target_format(view.target_format); // Queue all entities visible to that view for (render_entity, visible_entity) in visible_entities.iter::() { diff --git a/examples/3d/bloom_3d.rs b/examples/3d/bloom_3d.rs index 982b59745fd45..157c8ff914911 100644 --- a/examples/3d/bloom_3d.rs +++ b/examples/3d/bloom_3d.rs @@ -1,6 +1,8 @@ //! Illustrates bloom post-processing using HDR and emissive materials. +use bevy::render::render_resource::TextureFormat; use bevy::{ + camera::CameraMainTextureFormat, core_pipeline::tonemapping::Tonemapping, math::ops, post_process::bloom::{Bloom, BloomCompositeMode}, @@ -30,6 +32,10 @@ fn setup_scene( clear_color: ClearColorConfig::Custom(Color::BLACK), ..default() }, + CameraMainTextureFormat { + hdr_format: TextureFormat::Rg11b10Ufloat, // `Rg11b10Ufloat` provides better performance on low-end devices. You can also use `Rgba16Float`. + sdr_format: TextureFormat::Rgba8UnormSrgb, + }, Tonemapping::TonyMcMapface, // 1. Using a tonemapper that desaturates to white is recommended Transform::from_xyz(-2.0, 2.5, 5.0).looking_at(Vec3::ZERO, Vec3::Y), Bloom::NATURAL, // 2. Enable bloom for the camera diff --git a/examples/shader_advanced/custom_render_phase.rs b/examples/shader_advanced/custom_render_phase.rs index 866e96adca9da..709c1b9ddab08 100644 --- a/examples/shader_advanced/custom_render_phase.rs +++ b/examples/shader_advanced/custom_render_phase.rs @@ -513,7 +513,7 @@ fn queue_custom_meshes( // Create the key based on the view. // In this case we only care about MSAA and HDR let view_key = MeshPipelineKey::from_msaa_samples(msaa.samples()) - | MeshPipelineKey::from_hdr(view.hdr); + | MeshPipelineKey::from_view_target_format(view.target_format); let rangefinder = view.rangefinder3d(); // Since our phase can work on any 3d mesh we can reuse the default mesh 3d filter diff --git a/examples/shader_advanced/custom_shader_instancing.rs b/examples/shader_advanced/custom_shader_instancing.rs index 4be7a37c2bda4..506fe2c07d947 100644 --- a/examples/shader_advanced/custom_shader_instancing.rs +++ b/examples/shader_advanced/custom_shader_instancing.rs @@ -142,7 +142,7 @@ fn queue_custom( let msaa_key = MeshPipelineKey::from_msaa_samples(msaa.samples()); - let view_key = msaa_key | MeshPipelineKey::from_hdr(view.hdr); + let view_key = msaa_key | MeshPipelineKey::from_view_target_format(view.target_format); let rangefinder = view.rangefinder3d(); for (entity, main_entity) in &material_meshes { let Some(mesh_instance) = render_mesh_instances.render_mesh_queue_data(*main_entity) diff --git a/examples/shader_advanced/specialized_mesh_pipeline.rs b/examples/shader_advanced/specialized_mesh_pipeline.rs index 40602a8429274..bc0e98871136a 100644 --- a/examples/shader_advanced/specialized_mesh_pipeline.rs +++ b/examples/shader_advanced/specialized_mesh_pipeline.rs @@ -31,9 +31,9 @@ use bevy::{ ColorTargetState, ColorWrites, CompareFunction, DepthStencilState, Face, FragmentState, FrontFace, MultisampleState, PipelineCache, PolygonMode, PrimitiveState, RenderPipelineDescriptor, SpecializedMeshPipeline, SpecializedMeshPipelineError, - SpecializedMeshPipelines, TextureFormat, VertexState, + SpecializedMeshPipelines, VertexState, }, - view::{ExtractedView, RenderVisibleEntities, ViewTarget}, + view::{ExtractedView, RenderVisibleEntities}, Render, RenderApp, RenderStartup, RenderSystems, }, }; @@ -223,11 +223,7 @@ impl SpecializedMeshPipeline for CustomMeshPipeline { targets: vec![Some(ColorTargetState { // This isn't required, but bevy supports HDR and non-HDR rendering // so it's generally recommended to specialize the pipeline for that - format: if mesh_key.contains(MeshPipelineKey::HDR) { - ViewTarget::TEXTURE_FORMAT_HDR - } else { - TextureFormat::bevy_default() - }, + format: mesh_key.view_target_format(), // For this example we only use opaque meshes, // but if you wanted to use alpha blending you would need to set it here blend: None, @@ -296,7 +292,7 @@ fn queue_custom_mesh_pipeline( // Create the key based on the view. In this case we only care about MSAA and HDR let view_key = MeshPipelineKey::from_msaa_samples(msaa.samples()) - | MeshPipelineKey::from_hdr(view.hdr); + | MeshPipelineKey::from_view_target_format(view.target_format); // Find all the custom rendered entities that are visible from this // view.