Skip to content

Commit 83e7c45

Browse files
committed
Texture formats, camera extraction
1 parent 2a08f7a commit 83e7c45

6 files changed

Lines changed: 119 additions & 61 deletions

File tree

crates/bevy_core_pipeline/src/skybox/mod.rs

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,9 @@ use bevy_ecs::{
88
schedule::IntoScheduleConfigs,
99
system::{Commands, Local, Query, Res, ResMut},
1010
};
11-
use bevy_image::BevyDefault;
1211
use bevy_light::Skybox;
1312
use bevy_math::Mat4;
1413
use bevy_render::{
15-
camera::ExtractedCamera,
1614
extract_component::{ComponentUniforms, DynamicUniformIndex, UniformComponentPlugin},
1715
render_asset::RenderAssets,
1816
render_resource::{
@@ -22,7 +20,7 @@ use bevy_render::{
2220
renderer::RenderDevice,
2321
sync_world::RenderEntity,
2422
texture::GpuImage,
25-
view::{Msaa, ViewTarget, ViewUniform, ViewUniforms},
23+
view::{ExtractedView, Msaa, ViewUniform, ViewUniforms},
2624
Extract, ExtractSchedule, GpuResourceAppExt, Render, RenderApp, RenderStartup, RenderSystems,
2725
};
2826
use bevy_shader::Shader;
@@ -131,7 +129,7 @@ fn init_skybox_pipeline(mut commands: Commands, asset_server: Res<AssetServer>)
131129

132130
#[derive(PartialEq, Eq, Hash, Clone, Copy)]
133131
struct SkyboxPipelineKey {
134-
hdr: bool,
132+
color_target_format: TextureFormat,
135133
samples: u32,
136134
depth_format: TextureFormat,
137135
}
@@ -171,11 +169,7 @@ impl SpecializedRenderPipeline for SkyboxPipeline {
171169
fragment: Some(FragmentState {
172170
shader: self.shader.clone(),
173171
targets: vec![Some(ColorTargetState {
174-
format: if key.hdr {
175-
ViewTarget::TEXTURE_FORMAT_HDR
176-
} else {
177-
TextureFormat::bevy_default()
178-
},
172+
format: key.color_target_format,
179173
// BlendState::REPLACE is not needed here, and None will be potentially much faster in some cases.
180174
blend: None,
181175
write_mask: ColorWrites::ALL,
@@ -195,14 +189,14 @@ fn prepare_skybox_pipelines(
195189
pipeline_cache: Res<PipelineCache>,
196190
mut pipelines: ResMut<SpecializedRenderPipelines<SkyboxPipeline>>,
197191
pipeline: Res<SkyboxPipeline>,
198-
cameras: Query<(Entity, &ExtractedCamera, &Msaa), With<Skybox>>,
192+
cameras: Query<(Entity, &ExtractedView, &Msaa), With<Skybox>>,
199193
) {
200-
for (entity, camera, msaa) in &cameras {
194+
for (entity, view, msaa) in &cameras {
201195
let pipeline_id = pipelines.specialize(
202196
&pipeline_cache,
203197
&pipeline,
204198
SkyboxPipelineKey {
205-
hdr: camera.hdr,
199+
color_target_format: view.texture_format,
206200
samples: msaa.samples(),
207201
depth_format: CORE_3D_DEPTH_FORMAT,
208202
},

crates/bevy_pbr/src/deferred/mod.rs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ use bevy_core_pipeline::{
1818
tonemapping::{DebandDither, Tonemapping},
1919
};
2020
use bevy_ecs::prelude::*;
21-
use bevy_image::BevyDefault as _;
2221
use bevy_light::{EnvironmentMapLight, IrradianceVolume, ShadowFilteringMethod};
2322
use bevy_render::{
2423
camera::ExtractedCamera,
@@ -350,11 +349,7 @@ impl SpecializedRenderPipeline for DeferredLightingLayout {
350349
shader: self.deferred_lighting_shader.clone(),
351350
shader_defs,
352351
targets: vec![Some(ColorTargetState {
353-
format: if key.contains(MeshPipelineKey::HDR) {
354-
ViewTarget::TEXTURE_FORMAT_HDR
355-
} else {
356-
TextureFormat::bevy_default()
357-
},
352+
format: key.main_pass_color_attachment_format(),
358353
blend: None,
359354
write_mask: ColorWrites::ALL,
360355
})],
@@ -445,7 +440,7 @@ pub fn prepare_deferred_lighting_pipelines(
445440
) {
446441
for (
447442
entity,
448-
camera,
443+
_camera,
449444
view,
450445
tonemapping,
451446
dither,
@@ -466,7 +461,11 @@ pub fn prepare_deferred_lighting_pipelines(
466461
continue;
467462
}
468463

469-
let mut view_key = MeshPipelineKey::from_hdr(camera.hdr);
464+
let is_hdr = view.texture_format == ViewTarget::TEXTURE_FORMAT_HDR;
465+
let mut view_key = MeshPipelineKey::from_hdr(is_hdr);
466+
if !is_hdr {
467+
view_key |= MeshPipelineKey::sdr_color_attachment_format_bits(view.texture_format);
468+
}
470469

471470
if normal_prepass {
472471
view_key |= MeshPipelineKey::NORMAL_PREPASS;
@@ -491,7 +490,7 @@ pub fn prepare_deferred_lighting_pipelines(
491490
// Always true, since we're in the deferred lighting pipeline
492491
view_key |= MeshPipelineKey::DEFERRED_PREPASS;
493492

494-
if !camera.hdr {
493+
if !is_hdr {
495494
if let Some(tonemapping) = tonemapping {
496495
view_key |= MeshPipelineKey::TONEMAP_IN_SHADER;
497496
view_key |= match tonemapping {

crates/bevy_pbr/src/meshlet/material_pipeline_prepare.rs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,11 @@ use bevy_mesh::VertexBufferLayout;
1818
use bevy_mesh::{Mesh, MeshVertexBufferLayout, MeshVertexBufferLayoutRef, MeshVertexBufferLayouts};
1919
use bevy_platform::collections::{HashMap, HashSet};
2020
use bevy_render::erased_render_asset::ErasedRenderAssets;
21-
use bevy_render::{camera::TemporalJitter, render_resource::*, view::ExtractedView};
21+
use bevy_render::{
22+
camera::TemporalJitter,
23+
render_resource::*,
24+
view::{ExtractedView, ViewTarget},
25+
};
2226
use bevy_utils::default;
2327
use core::any::{Any, TypeId};
2428

@@ -78,8 +82,12 @@ pub fn prepare_material_meshlet_meshes_main_opaque_pass(
7882
has_irradiance_volumes,
7983
) in &mut views
8084
{
85+
let is_hdr = view.texture_format == ViewTarget::TEXTURE_FORMAT_HDR;
8186
let mut view_key =
82-
MeshPipelineKey::from_msaa_samples(1) | MeshPipelineKey::from_hdr(view.hdr);
87+
MeshPipelineKey::from_msaa_samples(1) | MeshPipelineKey::from_hdr(is_hdr);
88+
if !is_hdr {
89+
view_key |= MeshPipelineKey::sdr_color_attachment_format_bits(view.texture_format);
90+
}
8391

8492
if normal_prepass {
8593
view_key |= MeshPipelineKey::NORMAL_PREPASS;
@@ -126,7 +134,7 @@ pub fn prepare_material_meshlet_meshes_main_opaque_pass(
126134
}
127135
}
128136

129-
if !view.hdr {
137+
if !is_hdr {
130138
if let Some(tonemapping) = tonemapping {
131139
view_key |= MeshPipelineKey::TONEMAP_IN_SHADER;
132140
view_key |= tonemapping_pipeline_key(*tonemapping);
@@ -294,8 +302,12 @@ pub fn prepare_material_meshlet_meshes_prepass(
294302
(normal_prepass, motion_vector_prepass, deferred_prepass),
295303
) in &mut views
296304
{
305+
let is_hdr = view.texture_format == ViewTarget::TEXTURE_FORMAT_HDR;
297306
let mut view_key =
298-
MeshPipelineKey::from_msaa_samples(1) | MeshPipelineKey::from_hdr(view.hdr);
307+
MeshPipelineKey::from_msaa_samples(1) | MeshPipelineKey::from_hdr(is_hdr);
308+
if !is_hdr {
309+
view_key |= MeshPipelineKey::sdr_color_attachment_format_bits(view.texture_format);
310+
}
299311

300312
if normal_prepass.is_some() {
301313
view_key |= MeshPipelineKey::NORMAL_PREPASS;

crates/bevy_pbr/src/render/mesh.rs

Lines changed: 51 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,12 @@ use bevy_ecs::{
2828
relationship::RelationshipSourceCollection,
2929
system::{lifetimeless::*, SystemParamItem},
3030
};
31-
use bevy_image::{BevyDefault, ImageSampler, TextureFormatPixelInfo};
31+
use bevy_image::{ImageSampler, TextureFormatPixelInfo};
3232
use bevy_light::{
3333
EnvironmentMapLight, IrradianceVolume, NotShadowCaster, NotShadowReceiver,
3434
ShadowFilteringMethod, TransmittedShadowReceiver,
3535
};
36+
use bevy_log::warn_once;
3637
use bevy_math::{Affine3, Affine3Ext, Rect, UVec2, Vec3, Vec4};
3738
use bevy_mesh::{
3839
skinning::SkinnedMesh, BaseMeshPipelineKey, Mesh, Mesh3d, MeshTag, MeshVertexBufferLayoutRef,
@@ -401,10 +402,12 @@ pub fn check_views_need_specialization(
401402
has_ssr,
402403
) in views.iter_mut()
403404
{
404-
// HACK: we should be specializing by texture format, not bool hdr, but mesh pipeline keys have limited space.
405405
let is_hdr = view.texture_format == ViewTarget::TEXTURE_FORMAT_HDR;
406406
let mut view_key =
407407
MeshPipelineKey::from_msaa_samples(msaa.samples()) | MeshPipelineKey::from_hdr(is_hdr);
408+
if !is_hdr {
409+
view_key |= MeshPipelineKey::sdr_color_attachment_format_bits(view.texture_format);
410+
}
408411

409412
if normal_prepass {
410413
view_key |= MeshPipelineKey::NORMAL_PREPASS;
@@ -3108,13 +3111,16 @@ bitflags::bitflags! {
31083111
const SCREEN_SPACE_SPECULAR_TRANSMISSION_MEDIUM = 1 << Self::SCREEN_SPACE_SPECULAR_TRANSMISSION_SHIFT_BITS;
31093112
const SCREEN_SPACE_SPECULAR_TRANSMISSION_HIGH = 2 << Self::SCREEN_SPACE_SPECULAR_TRANSMISSION_SHIFT_BITS;
31103113
const SCREEN_SPACE_SPECULAR_TRANSMISSION_ULTRA = 3 << Self::SCREEN_SPACE_SPECULAR_TRANSMISSION_SHIFT_BITS;
3114+
const SDR_COLOR_ATTACHMENT_FORMAT_RESERVED_BITS = Self::SDR_COLOR_ATTACHMENT_FORMAT_MASK_BITS
3115+
<< Self::SDR_COLOR_ATTACHMENT_FORMAT_SHIFT_BITS;
31113116
const ALL_RESERVED_BITS =
31123117
Self::BLEND_RESERVED_BITS.bits() |
31133118
Self::MSAA_RESERVED_BITS.bits() |
31143119
Self::TONEMAP_METHOD_RESERVED_BITS.bits() |
31153120
Self::SHADOW_FILTER_METHOD_RESERVED_BITS.bits() |
31163121
Self::VIEW_PROJECTION_RESERVED_BITS.bits() |
3117-
Self::SCREEN_SPACE_SPECULAR_TRANSMISSION_RESERVED_BITS.bits();
3122+
Self::SCREEN_SPACE_SPECULAR_TRANSMISSION_RESERVED_BITS.bits() |
3123+
Self::SDR_COLOR_ATTACHMENT_FORMAT_RESERVED_BITS.bits();
31183124
}
31193125
}
31203126

@@ -3142,6 +3148,11 @@ impl MeshPipelineKey {
31423148
const SCREEN_SPACE_SPECULAR_TRANSMISSION_SHIFT_BITS: u64 =
31433149
Self::VIEW_PROJECTION_MASK_BITS.count_ones() as u64 + Self::VIEW_PROJECTION_SHIFT_BITS;
31443150

3151+
const SDR_COLOR_ATTACHMENT_FORMAT_MASK_BITS: u64 = 0b11;
3152+
const SDR_COLOR_ATTACHMENT_FORMAT_SHIFT_BITS: u64 =
3153+
Self::SCREEN_SPACE_SPECULAR_TRANSMISSION_MASK_BITS.count_ones() as u64
3154+
+ Self::SCREEN_SPACE_SPECULAR_TRANSMISSION_SHIFT_BITS;
3155+
31453156
pub fn from_msaa_samples(msaa_samples: u32) -> Self {
31463157
let msaa_bits =
31473158
(msaa_samples.trailing_zeros() as u64 & Self::MSAA_MASK_BITS) << Self::MSAA_SHIFT_BITS;
@@ -3156,6 +3167,42 @@ impl MeshPipelineKey {
31563167
}
31573168
}
31583169

3170+
/// Returns the bits for [`ExtractedView::texture_format`] for non-HDR views
3171+
pub fn sdr_color_attachment_format_bits(format: TextureFormat) -> Self {
3172+
let code: u64 = match format {
3173+
TextureFormat::Rgba8UnormSrgb => 0,
3174+
TextureFormat::Bgra8UnormSrgb => 1,
3175+
TextureFormat::Rgba8Unorm => 2,
3176+
_ => {
3177+
warn_once!(
3178+
"Unknown main pass format {:?}, mesh pipeline uses Rgba8UnormSrgb",
3179+
format
3180+
);
3181+
0
3182+
}
3183+
};
3184+
Self::from_bits_retain(
3185+
(code & Self::SDR_COLOR_ATTACHMENT_FORMAT_MASK_BITS)
3186+
<< Self::SDR_COLOR_ATTACHMENT_FORMAT_SHIFT_BITS,
3187+
)
3188+
}
3189+
3190+
/// Color format of the main pass color attachment for this pipeline key.
3191+
pub fn main_pass_color_attachment_format(&self) -> TextureFormat {
3192+
if self.contains(MeshPipelineKey::HDR) {
3193+
ViewTarget::TEXTURE_FORMAT_HDR
3194+
} else {
3195+
let code = (self.bits() >> Self::SDR_COLOR_ATTACHMENT_FORMAT_SHIFT_BITS)
3196+
& Self::SDR_COLOR_ATTACHMENT_FORMAT_MASK_BITS;
3197+
match code {
3198+
0 => TextureFormat::Rgba8UnormSrgb,
3199+
1 => TextureFormat::Bgra8UnormSrgb,
3200+
2 => TextureFormat::Rgba8Unorm,
3201+
_ => TextureFormat::Rgba8UnormSrgb,
3202+
}
3203+
}
3204+
}
3205+
31593206
pub fn msaa_samples(&self) -> u32 {
31603207
1 << ((self.bits() >> Self::MSAA_SHIFT_BITS) & Self::MSAA_MASK_BITS)
31613208
}
@@ -3611,11 +3658,7 @@ impl SpecializedMeshPipeline for MeshPipeline {
36113658
}
36123659
}
36133660

3614-
let format = if key.contains(MeshPipelineKey::HDR) {
3615-
ViewTarget::TEXTURE_FORMAT_HDR
3616-
} else {
3617-
TextureFormat::bevy_default()
3618-
};
3661+
let format = key.main_pass_color_attachment_format();
36193662

36203663
// This is defined here so that custom shaders that use something other than
36213664
// the mesh binding from bevy_pbr::mesh_bindings can easily make use of this

crates/bevy_render/src/camera.rs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use crate::{
1212
view::{
1313
ColorGrading, ExtractedView, ExtractedWindows, Msaa, NoIndirectDrawing,
1414
RenderExtractedVisibleEntities, RenderVisibleEntities, RenderVisibleEntitiesClass,
15-
RetainedViewEntity, ViewUniformOffset, VisibilityExtractionSystemParam,
15+
RetainedViewEntity, ViewTarget, ViewUniformOffset, VisibilityExtractionSystemParam,
1616
},
1717
Extract, ExtractSchedule, Render, RenderApp, RenderSystems,
1818
};
@@ -53,6 +53,10 @@ use bevy_window::{PrimaryWindow, Window, WindowCreated, WindowResized, WindowSca
5353
use itertools::Either;
5454
use wgpu::TextureFormat;
5555

56+
/// Main-pass color [`TextureFormat`] keyed by camera render entity.
57+
#[derive(Resource, Default, Deref, DerefMut)]
58+
pub struct CameraMainPassTextureFormats(pub HashMap<Entity, TextureFormat>);
59+
5660
#[derive(Default)]
5761
pub struct CameraPlugin;
5862

@@ -80,6 +84,7 @@ impl Plugin for CameraPlugin {
8084

8185
if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
8286
render_app
87+
.init_resource::<CameraMainPassTextureFormats>()
8388
.init_resource::<SortedCameras>()
8489
.init_resource::<DirtySpecializations>()
8590
.init_resource::<DirtyWireframeSpecializations>()
@@ -462,6 +467,7 @@ pub struct ExtractedCamera {
462467

463468
pub fn extract_cameras(
464469
mut commands: Commands,
470+
mut main_pass_formats: ResMut<CameraMainPassTextureFormats>,
465471
query: Extract<
466472
Query<(
467473
Entity,
@@ -496,6 +502,7 @@ pub fn extract_cameras(
496502
gpu_preprocessing_support: Res<GpuPreprocessingSupport>,
497503
visibility_extraction_system_param: VisibilityExtractionSystemParam,
498504
) {
505+
main_pass_formats.clear();
499506
let primary_window = primary_window.iter().next();
500507
type ExtractedCameraComponents = (
501508
ExtractedCamera,
@@ -590,7 +597,7 @@ pub fn extract_cameras(
590597
// removed from it.
591598

592599
let target = render_target.normalize(primary_window);
593-
let texture_format = target
600+
let output_texture_format = target
594601
.as_ref()
595602
.and_then(|target| {
596603
target.get_texture_view_format(
@@ -600,6 +607,14 @@ pub fn extract_cameras(
600607
)
601608
})
602609
.unwrap_or(TextureFormat::bevy_default());
610+
let texture_format = if hdr {
611+
ViewTarget::TEXTURE_FORMAT_HDR
612+
} else if compositing_space.is_some_and(|s| *s == CompositingSpace::Srgb) {
613+
TextureFormat::Rgba8Unorm
614+
} else {
615+
output_texture_format
616+
};
617+
main_pass_formats.insert(render_entity, texture_format);
603618

604619
let mut commands = commands.entity(render_entity);
605620
commands.insert((

0 commit comments

Comments
 (0)