Skip to content

Commit

Permalink
Extract mesh view layouts logic (#13266)
Browse files Browse the repository at this point in the history
Copied almost verbatim from the volumetric fog PR

# Objective

- Managing mesh view layouts is complicated

## Solution

- Extract it to it's own struct
- This was done as part of #13057 and is copied almost verbatim. I
wanted to keep this part of the PR it's own atomic commit in case we
ever have to revert fog or run a bisect. This change is good whether or
not we have volumetric fog.

Co-Authored-By: @pcwalton
  • Loading branch information
IceSentry authored May 7, 2024
1 parent 1126b5a commit 4737106
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 27 deletions.
33 changes: 9 additions & 24 deletions crates/bevy_pbr/src/render/mesh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,13 @@ use bevy_render::{
texture::{BevyDefault, DefaultImageSampler, ImageSampler, TextureFormatPixelInfo},
view::{
prepare_view_targets, GpuCulling, RenderVisibilityRanges, ViewTarget, ViewUniformOffset,
ViewVisibility, VisibilityRange, VISIBILITY_RANGES_STORAGE_BUFFER_COUNT,
ViewVisibility, VisibilityRange,
},
Extract,
};
use bevy_transform::components::GlobalTransform;
use bevy_utils::{tracing::error, tracing::warn, Entry, HashMap, Parallel};

#[cfg(debug_assertions)]
use bevy_utils::warn_once;
use bytemuck::{Pod, Zeroable};
use nonmax::{NonMaxU16, NonMaxU32};
use static_assertions::const_assert_eq;
Expand Down Expand Up @@ -234,6 +232,7 @@ impl Plugin for MeshRenderPlugin {

render_app
.insert_resource(indirect_parameters_buffer)
.init_resource::<MeshPipelineViewLayouts>()
.init_resource::<MeshPipeline>();
}

Expand Down Expand Up @@ -1034,7 +1033,8 @@ fn collect_meshes_for_gpu_building(

#[derive(Resource, Clone)]
pub struct MeshPipeline {
view_layouts: [MeshPipelineViewLayout; MeshPipelineViewLayoutKey::COUNT],
/// A reference to all the mesh pipeline view layouts.
pub view_layouts: MeshPipelineViewLayouts,
// This dummy white texture is to be used in place of optional StandardMaterial textures
pub dummy_white_gpu_image: GpuImage,
pub clustered_forward_buffer_binding_type: BufferBindingType,
Expand Down Expand Up @@ -1065,18 +1065,12 @@ impl FromWorld for MeshPipeline {
Res<RenderDevice>,
Res<DefaultImageSampler>,
Res<RenderQueue>,
Res<MeshPipelineViewLayouts>,
)> = SystemState::new(world);
let (render_device, default_sampler, render_queue) = system_state.get_mut(world);
let (render_device, default_sampler, render_queue, view_layouts) =
system_state.get_mut(world);
let clustered_forward_buffer_binding_type = render_device
.get_supported_read_only_binding_type(CLUSTERED_FORWARD_STORAGE_BUFFER_COUNT);
let visibility_ranges_buffer_binding_type = render_device
.get_supported_read_only_binding_type(VISIBILITY_RANGES_STORAGE_BUFFER_COUNT);

let view_layouts = generate_view_layouts(
&render_device,
clustered_forward_buffer_binding_type,
visibility_ranges_buffer_binding_type,
);

// A 1x1x1 'all 1.0' texture to use as a dummy texture to use in place of optional StandardMaterial textures
let dummy_white_gpu_image = {
Expand Down Expand Up @@ -1113,7 +1107,7 @@ impl FromWorld for MeshPipeline {
};

MeshPipeline {
view_layouts,
view_layouts: view_layouts.clone(),
clustered_forward_buffer_binding_type,
dummy_white_gpu_image,
mesh_layouts: MeshLayouts::new(&render_device),
Expand Down Expand Up @@ -1141,16 +1135,7 @@ impl MeshPipeline {
}

pub fn get_view_layout(&self, layout_key: MeshPipelineViewLayoutKey) -> &BindGroupLayout {
let index = layout_key.bits() as usize;
let layout = &self.view_layouts[index];

#[cfg(debug_assertions)]
if layout.texture_count > MESH_PIPELINE_VIEW_LAYOUT_SAFE_MAX_TEXTURES {
// Issue our own warning here because Naga's error message is a bit cryptic in this situation
warn_once!("Too many textures in mesh pipeline view layout, this might cause us to hit `wgpu::Limits::max_sampled_textures_per_shader_stage` in some environments.");
}

&layout.bind_group_layout
self.view_layouts.get_view_layout(layout_key)
}
}

Expand Down
74 changes: 71 additions & 3 deletions crates/bevy_pbr/src/render/mesh_view_bindings.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{array, num::NonZeroU64};
use std::{array, num::NonZeroU64, sync::Arc};

use bevy_core_pipeline::{
core_3d::ViewTransmissionTexture,
Expand All @@ -7,10 +7,12 @@ use bevy_core_pipeline::{
get_lut_bind_group_layout_entries, get_lut_bindings, Tonemapping, TonemappingLuts,
},
};
use bevy_derive::{Deref, DerefMut};
use bevy_ecs::{
component::Component,
entity::Entity,
system::{Commands, Query, Res},
system::{Commands, Query, Res, Resource},
world::{FromWorld, World},
};
use bevy_math::Vec4;
use bevy_render::{
Expand All @@ -19,13 +21,19 @@ use bevy_render::{
render_resource::{binding_types::*, *},
renderer::RenderDevice,
texture::{BevyDefault, FallbackImage, FallbackImageMsaa, FallbackImageZero, GpuImage},
view::{Msaa, RenderVisibilityRanges, ViewUniform, ViewUniforms},
view::{
Msaa, RenderVisibilityRanges, ViewUniform, ViewUniforms,
VISIBILITY_RANGES_STORAGE_BUFFER_COUNT,
},
};

#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
use bevy_render::render_resource::binding_types::texture_cube;
use bevy_utils::warn_once;
use environment_map::EnvironmentMapLight;

#[cfg(debug_assertions)]
use crate::MESH_PIPELINE_VIEW_LAYOUT_SAFE_MAX_TEXTURES;
use crate::{
environment_map::{self, RenderViewEnvironmentMapBindGroupEntries},
irradiance_volume::{
Expand All @@ -35,6 +43,7 @@ use crate::{
prepass, FogMeta, GlobalLightMeta, GpuFog, GpuLights, GpuPointLights, LightMeta,
LightProbesBuffer, LightProbesUniform, MeshPipeline, MeshPipelineKey, RenderViewLightProbes,
ScreenSpaceAmbientOcclusionTextures, ShadowSamplers, ViewClusterBindings, ViewShadowBindings,
CLUSTERED_FORWARD_STORAGE_BUFFER_COUNT,
};

#[derive(Clone)]
Expand Down Expand Up @@ -330,6 +339,65 @@ fn layout_entries(
entries.to_vec()
}

/// Stores the view layouts for every combination of pipeline keys.
///
/// This is wrapped in an [`Arc`] so that it can be efficiently cloned and
/// placed inside specializable pipeline types.
#[derive(Resource, Clone, Deref, DerefMut)]
pub struct MeshPipelineViewLayouts(
pub Arc<[MeshPipelineViewLayout; MeshPipelineViewLayoutKey::COUNT]>,
);

impl FromWorld for MeshPipelineViewLayouts {
fn from_world(world: &mut World) -> Self {
// Generates all possible view layouts for the mesh pipeline, based on all combinations of
// [`MeshPipelineViewLayoutKey`] flags.

let render_device = world.resource::<RenderDevice>();

let clustered_forward_buffer_binding_type = render_device
.get_supported_read_only_binding_type(CLUSTERED_FORWARD_STORAGE_BUFFER_COUNT);
let visibility_ranges_buffer_binding_type = render_device
.get_supported_read_only_binding_type(VISIBILITY_RANGES_STORAGE_BUFFER_COUNT);

Self(Arc::new(array::from_fn(|i| {
let key = MeshPipelineViewLayoutKey::from_bits_truncate(i as u32);
let entries = layout_entries(
clustered_forward_buffer_binding_type,
visibility_ranges_buffer_binding_type,
key,
render_device,
);
let texture_count: usize = entries
.iter()
.filter(|entry| matches!(entry.ty, BindingType::Texture { .. }))
.count();

MeshPipelineViewLayout {
bind_group_layout: render_device
.create_bind_group_layout(key.label().as_str(), &entries),
#[cfg(debug_assertions)]
texture_count,
}
})))
}
}

impl MeshPipelineViewLayouts {
pub fn get_view_layout(&self, layout_key: MeshPipelineViewLayoutKey) -> &BindGroupLayout {
let index = layout_key.bits() as usize;
let layout = &self[index];

#[cfg(debug_assertions)]
if layout.texture_count > MESH_PIPELINE_VIEW_LAYOUT_SAFE_MAX_TEXTURES {
// Issue our own warning here because Naga's error message is a bit cryptic in this situation
warn_once!("Too many textures in mesh pipeline view layout, this might cause us to hit `wgpu::Limits::max_sampled_textures_per_shader_stage` in some environments.");
}

&layout.bind_group_layout
}
}

/// Generates all possible view layouts for the mesh pipeline, based on all combinations of
/// [`MeshPipelineViewLayoutKey`] flags.
pub fn generate_view_layouts(
Expand Down

0 comments on commit 4737106

Please sign in to comment.