migrate auto_exposure

This commit is contained in:
Emerson Coskey 2025-07-13 20:04:19 -07:00
parent 498b1099a9
commit f9f0451a86
No known key found for this signature in database
3 changed files with 65 additions and 46 deletions

View File

@ -5,9 +5,7 @@ use bevy_render::{
extract_component::ExtractComponentPlugin,
render_asset::RenderAssetPlugin,
render_graph::RenderGraphExt,
render_resource::{
Buffer, BufferDescriptor, BufferUsages, PipelineCache, SpecializedComputePipelines,
},
render_resource::{Buffer, BufferDescriptor, BufferUsages, PipelineCache},
renderer::RenderDevice,
ExtractSchedule, Render, RenderApp, RenderSystems,
};
@ -59,7 +57,6 @@ impl Plugin for AutoExposurePlugin {
};
render_app
.init_resource::<SpecializedComputePipelines<AutoExposurePipeline>>()
.init_resource::<AutoExposureBuffers>()
.add_systems(ExtractSchedule, extract_buffers)
.add_systems(
@ -104,15 +101,16 @@ impl FromWorld for AutoExposureResources {
fn queue_view_auto_exposure_pipelines(
mut commands: Commands,
pipeline_cache: Res<PipelineCache>,
mut compute_pipelines: ResMut<SpecializedComputePipelines<AutoExposurePipeline>>,
pipeline: Res<AutoExposurePipeline>,
mut auto_exposure_pipeline: ResMut<AutoExposurePipeline>,
view_targets: Query<(Entity, &AutoExposure)>,
) {
) -> Result<(), BevyError> {
for (entity, auto_exposure) in view_targets.iter() {
let histogram_pipeline =
compute_pipelines.specialize(&pipeline_cache, &pipeline, AutoExposurePass::Histogram);
let average_pipeline =
compute_pipelines.specialize(&pipeline_cache, &pipeline, AutoExposurePass::Average);
let histogram_pipeline = auto_exposure_pipeline
.variants
.specialize(&pipeline_cache, AutoExposurePass::Histogram)?;
let average_pipeline = auto_exposure_pipeline
.variants
.specialize(&pipeline_cache, AutoExposurePass::Average)?;
commands.entity(entity).insert(ViewAutoExposurePipeline {
histogram_pipeline,
@ -121,4 +119,5 @@ fn queue_view_auto_exposure_pipelines(
metering_mask: auto_exposure.metering_mask.clone(),
});
}
Ok(())
}

View File

@ -100,7 +100,7 @@ impl Node for AutoExposureNode {
let compute_bind_group = render_context.render_device().create_bind_group(
None,
&pipeline.histogram_layout,
&pipeline.layout,
&BindGroupEntries::sequential((
&globals_buffer.buffer,
&auto_exposure_buffers.settings,

View File

@ -12,13 +12,16 @@ use bevy_render::{
};
use bevy_utils::default;
use core::num::NonZero;
use std::result::Result;
#[derive(Resource)]
pub struct AutoExposurePipeline {
pub histogram_layout: BindGroupLayout,
pub histogram_shader: Handle<Shader>,
pub layout: BindGroupLayout,
pub variants: SpecializedCache<ComputePipeline, AutoExposureSpecializer>,
}
pub struct AutoExposureSpecializer;
#[derive(Component)]
pub struct ViewAutoExposurePipeline {
pub histogram_pipeline: CachedComputePipelineId,
@ -39,7 +42,7 @@ pub struct AutoExposureUniform {
pub(super) exponential_transition_distance: f32,
}
#[derive(PartialEq, Eq, Hash, Clone)]
#[derive(PartialEq, Eq, Hash, Clone, SpecializerKey)]
pub enum AutoExposurePass {
Histogram,
Average,
@ -51,43 +54,60 @@ impl FromWorld for AutoExposurePipeline {
fn from_world(world: &mut World) -> Self {
let render_device = world.resource::<RenderDevice>();
Self {
histogram_layout: render_device.create_bind_group_layout(
"compute histogram bind group",
&BindGroupLayoutEntries::sequential(
ShaderStages::COMPUTE,
(
uniform_buffer::<GlobalsUniform>(false),
uniform_buffer::<AutoExposureUniform>(false),
texture_2d(TextureSampleType::Float { filterable: false }),
texture_2d(TextureSampleType::Float { filterable: false }),
texture_1d(TextureSampleType::Float { filterable: false }),
uniform_buffer::<AutoExposureCompensationCurveUniform>(false),
storage_buffer_sized(false, NonZero::<u64>::new(HISTOGRAM_BIN_COUNT * 4)),
storage_buffer_sized(false, NonZero::<u64>::new(4)),
storage_buffer::<ViewUniform>(true),
),
let layout = render_device.create_bind_group_layout(
"compute histogram bind group",
&BindGroupLayoutEntries::sequential(
ShaderStages::COMPUTE,
(
uniform_buffer::<GlobalsUniform>(false),
uniform_buffer::<AutoExposureUniform>(false),
texture_2d(TextureSampleType::Float { filterable: false }),
texture_2d(TextureSampleType::Float { filterable: false }),
texture_1d(TextureSampleType::Float { filterable: false }),
uniform_buffer::<AutoExposureCompensationCurveUniform>(false),
storage_buffer_sized(false, NonZero::<u64>::new(HISTOGRAM_BIN_COUNT * 4)),
storage_buffer_sized(false, NonZero::<u64>::new(4)),
storage_buffer::<ViewUniform>(true),
),
),
histogram_shader: load_embedded_asset!(world, "auto_exposure.wgsl"),
}
);
let shader = load_embedded_asset!(world, "auto_exposure.wgsl");
let base_descriptor = ComputePipelineDescriptor {
layout: vec![layout.clone()],
shader,
..default()
};
let variants = SpecializedCache::new(AutoExposureSpecializer, None, base_descriptor);
Self { layout, variants }
}
}
impl SpecializedComputePipeline for AutoExposurePipeline {
impl Specializer<ComputePipeline> for AutoExposureSpecializer {
type Key = AutoExposurePass;
fn specialize(&self, pass: AutoExposurePass) -> ComputePipelineDescriptor {
ComputePipelineDescriptor {
label: Some("luminance compute pipeline".into()),
layout: vec![self.histogram_layout.clone()],
shader: self.histogram_shader.clone(),
shader_defs: vec![],
entry_point: Some(match pass {
AutoExposurePass::Histogram => "compute_histogram".into(),
AutoExposurePass::Average => "compute_average".into(),
}),
..default()
}
fn specialize(
&self,
key: Self::Key,
descriptor: &mut ComputePipelineDescriptor,
) -> Result<Canonical<Self::Key>, BevyError> {
let (label, entry_point) = match key {
AutoExposurePass::Histogram => (
"auto_exposure_compute_histogram".into(),
"compute_histogram".into(),
),
AutoExposurePass::Average => (
"auto_exposure_compute_average".into(),
"compute_average".into(),
),
};
descriptor.label = Some(label);
descriptor.entry_point = Some(entry_point);
Ok(key)
}
}