Skip to content

Commit 1fc67d9

Browse files
Merge branch 'main' into preconvert-to-srgb
2 parents 6839571 + f1eace6 commit 1fc67d9

File tree

13 files changed

+168
-107
lines changed

13 files changed

+168
-107
lines changed

crates/bevy_ecs/src/schedule/schedule.rs

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use bevy_utils::{default, prelude::DebugName, TypeIdMap};
1515
use core::{
1616
any::{Any, TypeId},
1717
fmt::{Debug, Write},
18+
ops::Range,
1819
};
1920
use fixedbitset::FixedBitSet;
2021
use log::{error, info, warn};
@@ -752,11 +753,31 @@ new_key_type! {
752753
pub struct SystemSetKey;
753754
}
754755

756+
/// A node in a [`ScheduleGraph`] with a system or conditions that have not been
757+
/// initialized yet.
758+
///
759+
/// We have to defer initialization of nodes in the graph until we have
760+
/// `&mut World` access, so we store these in a list ([`ScheduleGraph::uninit`])
761+
/// until then. In most cases, initialization occurs upon the first run of the
762+
/// schedule.
755763
enum UninitializedId {
764+
/// A system and its conditions that have not been initialized yet.
756765
System(SystemKey),
766+
/// A system set's conditions that have not been initialized yet.
757767
Set {
758768
key: SystemSetKey,
759-
first_uninit_condition: usize,
769+
/// The range of indices in [`SystemSets::conditions`] that correspond
770+
/// to conditions that have not been initialized yet.
771+
///
772+
/// [`SystemSets::conditions`] for a given set may be appended to
773+
/// multiple times (e.g. when `configure_sets` is called multiple with
774+
/// the same set), so we need to track which conditions in that list
775+
/// are newly added and not yet initialized.
776+
///
777+
/// Systems don't need this tracking because each `add_systems` call
778+
/// creates separate nodes in the graph with their own conditions,
779+
/// so all conditions are initialized together.
780+
uninitialized_conditions: Range<usize>,
760781
},
761782
}
762783

@@ -793,8 +814,8 @@ pub struct ScheduleGraph {
793814
pub system_conditions: SecondaryMap<SystemKey, Vec<ConditionWithAccess>>,
794815
/// Data about system sets in the schedule
795816
system_sets: SystemSets,
796-
/// Systems that have not been initialized yet; for system sets, we store the index of the first uninitialized condition
797-
/// (all the conditions after that index still need to be initialized)
817+
/// Systems, their conditions, and system set conditions that need to be
818+
/// initialized before the schedule can be run.
798819
uninit: Vec<UninitializedId>,
799820
/// Directed acyclic graph of the hierarchy (which systems/sets are children of which sets)
800821
hierarchy: Dag,
@@ -807,7 +828,6 @@ pub struct ScheduleGraph {
807828
anonymous_sets: usize,
808829
changed: bool,
809830
settings: ScheduleBuildSettings,
810-
811831
passes: BTreeMap<TypeId, Box<dyn ScheduleBuildPassObj>>,
812832
}
813833

@@ -1101,9 +1121,10 @@ impl ScheduleGraph {
11011121

11021122
// system init has to be deferred (need `&mut World`)
11031123
let system_set_conditions = self.system_sets.conditions.entry(key).unwrap().or_default();
1124+
let start = system_set_conditions.len();
11041125
self.uninit.push(UninitializedId::Set {
11051126
key,
1106-
first_uninit_condition: system_set_conditions.len(),
1127+
uninitialized_conditions: start..(start + conditions.len()),
11071128
});
11081129
system_set_conditions.extend(conditions.into_iter().map(ConditionWithAccess::new));
11091130

@@ -1189,11 +1210,9 @@ impl ScheduleGraph {
11891210
}
11901211
UninitializedId::Set {
11911212
key,
1192-
first_uninit_condition,
1213+
uninitialized_conditions,
11931214
} => {
1194-
for condition in self.system_sets.conditions[key]
1195-
.iter_mut()
1196-
.skip(first_uninit_condition)
1215+
for condition in &mut self.system_sets.conditions[key][uninitialized_conditions]
11971216
{
11981217
condition.access = condition.condition.initialize(world);
11991218
}

crates/bevy_pbr/src/pbr_material.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,23 @@ pub struct StandardMaterial {
386386
///
387387
/// [`Mesh::generate_tangents`]: bevy_render::mesh::Mesh::generate_tangents
388388
/// [`Mesh::with_generated_tangents`]: bevy_render::mesh::Mesh::with_generated_tangents
389+
///
390+
/// # Usage
391+
///
392+
/// ```
393+
/// # use bevy_asset::{AssetServer, Handle};
394+
/// # use bevy_ecs::change_detection::Res;
395+
/// # use bevy_image::{Image, ImageLoaderSettings};
396+
/// #
397+
/// fn load_normal_map(asset_server: Res<AssetServer>) {
398+
/// let normal_handle: Handle<Image> = asset_server.load_with_settings(
399+
/// "textures/parallax_example/cube_normal.png",
400+
/// // The normal map texture is in linear color space. Lighting won't look correct
401+
/// // if `is_srgb` is `true`, which is the default.
402+
/// |settings: &mut ImageLoaderSettings| settings.is_srgb = false,
403+
/// );
404+
/// }
405+
/// ```
389406
#[texture(9)]
390407
#[sampler(10)]
391408
#[dependency]

crates/bevy_pbr/src/render/mesh.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3016,7 +3016,7 @@ impl<P: PhaseItem, const I: usize> RenderCommand<P> for SetMeshBindGroup<I> {
30163016
);
30173017
};
30183018

3019-
let mut dynamic_offsets: [u32; 3] = Default::default();
3019+
let mut dynamic_offsets: [u32; 5] = Default::default();
30203020
let mut offset_count = 0;
30213021
if let PhaseItemExtraIndex::DynamicOffset(dynamic_offset) = item.extra_index() {
30223022
dynamic_offsets[offset_count] = dynamic_offset;

crates/bevy_pbr/src/render/pbr_fragment.wgsl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,6 @@ fn pbr_input_from_standard_material(
377377
var perceptual_roughness: f32 = pbr_bindings::material.perceptual_roughness;
378378
#endif // BINDLESS
379379

380-
let roughness = lighting::perceptualRoughnessToRoughness(perceptual_roughness);
381380
#ifdef VERTEX_UVS
382381
if ((flags & pbr_types::STANDARD_MATERIAL_FLAGS_METALLIC_ROUGHNESS_TEXTURE_BIT) != 0u) {
383382
let metallic_roughness =
@@ -627,7 +626,7 @@ fn pbr_input_from_standard_material(
627626
var specular_occlusion: f32 = 1.0;
628627
#ifdef VERTEX_UVS
629628
if ((flags & pbr_types::STANDARD_MATERIAL_FLAGS_OCCLUSION_TEXTURE_BIT) != 0u) {
630-
diffuse_occlusion *=
629+
diffuse_occlusion *=
631630
#ifdef MESHLET_MESH_MATERIAL_PASS
632631
textureSampleGrad(
633632
#else // MESHLET_MESH_MATERIAL_PASS
@@ -660,7 +659,8 @@ fn pbr_input_from_standard_material(
660659
diffuse_occlusion = min(diffuse_occlusion, ssao_multibounce);
661660
// Use SSAO to estimate the specular occlusion.
662661
// Lagarde and Rousiers 2014, "Moving Frostbite to Physically Based Rendering"
663-
specular_occlusion = saturate(pow(NdotV + ssao, exp2(-16.0 * roughness - 1.0)) - 1.0 + ssao);
662+
let roughness = lighting::perceptualRoughnessToRoughness(pbr_input.material.perceptual_roughness);
663+
specular_occlusion = saturate(pow(NdotV + ssao, exp2(-16.0 * roughness - 1.0)) - 1.0 + ssao);
664664
#endif
665665
pbr_input.diffuse_occlusion = diffuse_occlusion;
666666
pbr_input.specular_occlusion = specular_occlusion;

crates/bevy_pbr/src/render/pbr_lighting.wgsl

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -235,16 +235,13 @@ fn fresnel(f0: vec3<f32>, LdotH: f32) -> vec3<f32> {
235235
// Multiscattering approximation:
236236
// <https://google.github.io/filament/Filament.html#listing_energycompensationimpl>
237237
fn specular_multiscatter(
238-
input: ptr<function, LightingInput>,
239238
D: f32,
240239
V: f32,
241240
F: vec3<f32>,
241+
F0: vec3<f32>,
242+
F_ab: vec2<f32>,
242243
specular_intensity: f32,
243244
) -> vec3<f32> {
244-
// Unpack.
245-
let F0 = (*input).F0_;
246-
let F_ab = (*input).F_ab;
247-
248245
var Fr = (specular_intensity * D * V) * F;
249246
Fr *= 1.0 + F0 * (1.0 / F_ab.x - 1.0);
250247
return Fr;
@@ -329,7 +326,7 @@ fn specular(
329326
let F = fresnel(F0, LdotH);
330327

331328
// Calculate the specular light.
332-
let Fr = specular_multiscatter(input, D, V, F, specular_intensity);
329+
let Fr = specular_multiscatter(D, V, F, F0, (*input).F_ab, specular_intensity);
333330
return Fr;
334331
}
335332

@@ -397,7 +394,7 @@ fn specular_anisotropy(
397394
let Fa = fresnel(F0, LdotH);
398395

399396
// Calculate the specular light.
400-
let Fr = specular_multiscatter(input, Da, Va, Fa, specular_intensity);
397+
let Fr = specular_multiscatter(Da, Va, Fa, F0, (*input).F_ab, specular_intensity);
401398
return Fr;
402399
}
403400

@@ -482,7 +479,7 @@ fn cubemap_uv(direction: vec3<f32>, cubemap_type: u32) -> vec2<f32> {
482479
),
483480
max_axis != abs_direction.x
484481
);
485-
482+
486483
var face_uv: vec2<f32>;
487484
var divisor: f32;
488485
var corner_uv: vec2<u32> = vec2(0, 0);
@@ -500,12 +497,12 @@ fn cubemap_uv(direction: vec3<f32>, cubemap_type: u32) -> vec2<f32> {
500497
face_uv = (face_uv / divisor) * 0.5 + 0.5;
501498

502499
switch cubemap_type {
503-
case CUBEMAP_TYPE_CROSS_VERTICAL: {
504-
face_size = vec2(1.0/3.0, 1.0/4.0);
500+
case CUBEMAP_TYPE_CROSS_VERTICAL: {
501+
face_size = vec2(1.0/3.0, 1.0/4.0);
505502
corner_uv = vec2<u32>((0x111102u >> (4 * face_index)) & 0xFu, (0x132011u >> (4 * face_index)) & 0xFu);
506503
}
507-
case CUBEMAP_TYPE_CROSS_HORIZONTAL: {
508-
face_size = vec2(1.0/4.0, 1.0/3.0);
504+
case CUBEMAP_TYPE_CROSS_HORIZONTAL: {
505+
face_size = vec2(1.0/4.0, 1.0/3.0);
509506
corner_uv = vec2<u32>((0x131102u >> (4 * face_index)) & 0xFu, (0x112011u >> (4 * face_index)) & 0xFu);
510507
}
511508
case CUBEMAP_TYPE_SEQUENCE_HORIZONTAL: {
@@ -765,7 +762,7 @@ fn directional_light(
765762
view_bindings::clustered_decal_sampler,
766763
decal_uv - floor(decal_uv),
767764
0.0
768-
).r;
765+
).r;
769766
} else {
770767
texture_sample = 0f;
771768
}

crates/bevy_pbr/src/render/shadow_sampling.wgsl

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -422,11 +422,7 @@ fn sample_shadow_cubemap_gaussian(
422422
) -> f32 {
423423
// Create an orthonormal basis so we can apply a 2D sampling pattern to a
424424
// cubemap.
425-
var up = vec3(0.0, 1.0, 0.0);
426-
if (dot(up, normalize(light_local)) > 0.99) {
427-
up = vec3(1.0, 0.0, 0.0); // Avoid creating a degenerate basis.
428-
}
429-
let basis = orthonormalize(light_local, up) * scale * distance_to_light;
425+
let basis = orthonormalize(normalize(light_local)) * scale * distance_to_light;
430426

431427
var sum: f32 = 0.0;
432428
sum += sample_shadow_cubemap_at_offset(
@@ -469,11 +465,7 @@ fn sample_shadow_cubemap_jittered(
469465
) -> f32 {
470466
// Create an orthonormal basis so we can apply a 2D sampling pattern to a
471467
// cubemap.
472-
var up = vec3(0.0, 1.0, 0.0);
473-
if (dot(up, normalize(light_local)) > 0.99) {
474-
up = vec3(1.0, 0.0, 0.0); // Avoid creating a degenerate basis.
475-
}
476-
let basis = orthonormalize(light_local, up) * scale * distance_to_light;
468+
let basis = orthonormalize(normalize(light_local)) * scale * distance_to_light;
477469

478470
let rotation_matrix = random_rotation_matrix(vec2(1.0), temporal);
479471

@@ -553,11 +545,7 @@ fn search_for_blockers_in_shadow_cubemap(
553545
) -> f32 {
554546
// Create an orthonormal basis so we can apply a 2D sampling pattern to a
555547
// cubemap.
556-
var up = vec3(0.0, 1.0, 0.0);
557-
if (dot(up, normalize(light_local)) > 0.99) {
558-
up = vec3(1.0, 0.0, 0.0); // Avoid creating a degenerate basis.
559-
}
560-
let basis = orthonormalize(light_local, up) * scale * distance_to_light;
548+
let basis = orthonormalize(normalize(light_local)) * scale * distance_to_light;
561549

562550
var sum: vec2<f32> = vec2(0.0);
563551
sum += search_for_blockers_in_shadow_cubemap_at_offset(

crates/bevy_render/src/maths.wgsl

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -63,17 +63,19 @@ fn mat4x4_to_mat3x3(m: mat4x4<f32>) -> mat3x3<f32> {
6363
return mat3x3<f32>(m[0].xyz, m[1].xyz, m[2].xyz);
6464
}
6565

66-
// Creates an orthonormal basis given a Z vector and an up vector (which becomes
67-
// Y after orthonormalization).
66+
// Creates an orthonormal basis given a normalized Z vector.
6867
//
6968
// The results are equivalent to the Gram-Schmidt process [1].
7069
//
7170
// [1]: https://math.stackexchange.com/a/1849294
72-
fn orthonormalize(z_unnormalized: vec3<f32>, up: vec3<f32>) -> mat3x3<f32> {
73-
let z_basis = normalize(z_unnormalized);
74-
let x_basis = normalize(cross(z_basis, up));
75-
let y_basis = cross(z_basis, x_basis);
76-
return mat3x3(x_basis, y_basis, z_basis);
71+
fn orthonormalize(z_normalized: vec3<f32>) -> mat3x3<f32> {
72+
var up = vec3(0.0, 1.0, 0.0);
73+
if (abs(dot(up, z_normalized)) > 0.99) {
74+
up = vec3(1.0, 0.0, 0.0); // Avoid creating a degenerate basis.
75+
}
76+
let x_basis = normalize(cross(z_normalized, up));
77+
let y_basis = cross(z_normalized, x_basis);
78+
return mat3x3(x_basis, y_basis, z_normalized);
7779
}
7880

7981
// Returns true if any part of a sphere is on the positive side of a plane.

crates/bevy_render/src/renderer/mod.rs

Lines changed: 45 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use bevy_tasks::ComputeTaskPool;
77
use bevy_utils::WgpuWrapper;
88
pub use graph_runner::*;
99
pub use render_device::*;
10-
use tracing::{debug, error, info, info_span, trace, warn};
10+
use tracing::{debug, error, info, info_span, warn};
1111

1212
use crate::{
1313
diagnostic::{internal::DiagnosticsRecorder, RecordDiagnostics},
@@ -145,6 +145,33 @@ const GPU_NOT_FOUND_ERROR_MESSAGE: &str = if cfg!(target_os = "linux") {
145145
"Unable to find a GPU! Make sure you have installed required drivers!"
146146
};
147147

148+
#[cfg(not(target_family = "wasm"))]
149+
fn find_adapter_by_name(
150+
instance: &Instance,
151+
options: &WgpuSettings,
152+
compatible_surface: Option<&wgpu::Surface<'_>>,
153+
adapter_name: &str,
154+
) -> Option<Adapter> {
155+
for adapter in
156+
instance.enumerate_adapters(options.backends.expect(
157+
"The `backends` field of `WgpuSettings` must be set to use a specific adapter.",
158+
))
159+
{
160+
tracing::trace!("Checking adapter: {:?}", adapter.get_info());
161+
let info = adapter.get_info();
162+
if let Some(surface) = compatible_surface {
163+
if !adapter.is_surface_supported(surface) {
164+
continue;
165+
}
166+
}
167+
168+
if info.name.eq_ignore_ascii_case(adapter_name) {
169+
return Some(adapter);
170+
}
171+
}
172+
None
173+
}
174+
148175
/// Initializes the renderer by retrieving and preparing the GPU instance, device and queue
149176
/// for the specified backend.
150177
pub async fn initialize_renderer(
@@ -153,36 +180,30 @@ pub async fn initialize_renderer(
153180
request_adapter_options: &RequestAdapterOptions<'_, '_>,
154181
desired_adapter_name: Option<String>,
155182
) -> (RenderDevice, RenderQueue, RenderAdapterInfo, RenderAdapter) {
183+
#[cfg(not(target_family = "wasm"))]
184+
let mut selected_adapter = desired_adapter_name.and_then(|adapter_name| {
185+
find_adapter_by_name(
186+
instance,
187+
options,
188+
request_adapter_options.compatible_surface,
189+
&adapter_name,
190+
)
191+
});
192+
#[cfg(target_family = "wasm")]
156193
let mut selected_adapter = None;
157-
if let Some(adapter_name) = &desired_adapter_name {
158-
debug!("Searching for adapter with name: {}", adapter_name);
159-
for adapter in instance.enumerate_adapters(options.backends.expect(
160-
"The `backends` field of `WgpuSettings` must be set to use a specific adapter.",
161-
)) {
162-
trace!("Checking adapter: {:?}", adapter.get_info());
163-
let info = adapter.get_info();
164-
if let Some(surface) = request_adapter_options.compatible_surface {
165-
if !adapter.is_surface_supported(surface) {
166-
continue;
167-
}
168-
}
169194

170-
if info
171-
.name
172-
.to_lowercase()
173-
.contains(&adapter_name.to_lowercase())
174-
{
175-
selected_adapter = Some(adapter);
176-
break;
177-
}
178-
}
179-
} else {
195+
#[cfg(target_family = "wasm")]
196+
if desired_adapter_name.is_some() {
197+
warn!("Choosing an adapter is not supported on wasm.");
198+
}
199+
200+
if selected_adapter.is_none() {
180201
debug!(
181202
"Searching for adapter with options: {:?}",
182203
request_adapter_options
183204
);
184205
selected_adapter = instance.request_adapter(request_adapter_options).await.ok();
185-
};
206+
}
186207

187208
let adapter = selected_adapter.expect(GPU_NOT_FOUND_ERROR_MESSAGE);
188209
let adapter_info = adapter.get_info();

0 commit comments

Comments
 (0)