Extract mesh view layouts logic (#13266)
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
This commit is contained in:
parent
1126b5a3d6
commit
4737106bdd
@ -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;
|
||||
@ -234,6 +232,7 @@ impl Plugin for MeshRenderPlugin {
|
||||
|
||||
render_app
|
||||
.insert_resource(indirect_parameters_buffer)
|
||||
.init_resource::<MeshPipelineViewLayouts>()
|
||||
.init_resource::<MeshPipeline>();
|
||||
}
|
||||
|
||||
@ -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,
|
||||
@ -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 = {
|
||||
@ -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),
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
use std::{array, num::NonZeroU64};
|
||||
use std::{array, num::NonZeroU64, sync::Arc};
|
||||
|
||||
use bevy_core_pipeline::{
|
||||
core_3d::ViewTransmissionTexture,
|
||||
@ -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::{
|
||||
@ -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::{
|
||||
@ -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)]
|
||||
@ -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(
|
||||
|
Loading…
Reference in New Issue
Block a user