Path: blob/main/crates/bevy_post_process/src/auto_exposure/node.rs
6596 views
use super::{1buffers::AutoExposureBuffers,2compensation_curve::GpuAutoExposureCompensationCurve,3pipeline::{AutoExposurePipeline, ViewAutoExposurePipeline},4AutoExposureResources,5};6use bevy_ecs::{7query::QueryState,8system::lifetimeless::Read,9world::{FromWorld, World},10};11use bevy_render::{12diagnostic::RecordDiagnostics,13globals::GlobalsBuffer,14render_asset::RenderAssets,15render_graph::*,16render_resource::*,17renderer::RenderContext,18texture::{FallbackImage, GpuImage},19view::{ExtractedView, ViewTarget, ViewUniform, ViewUniformOffset, ViewUniforms},20};2122#[derive(RenderLabel, Debug, Clone, Hash, PartialEq, Eq)]23pub struct AutoExposure;2425pub struct AutoExposureNode {26query: QueryState<(27Read<ViewUniformOffset>,28Read<ViewTarget>,29Read<ViewAutoExposurePipeline>,30Read<ExtractedView>,31)>,32}3334impl FromWorld for AutoExposureNode {35fn from_world(world: &mut World) -> Self {36Self {37query: QueryState::new(world),38}39}40}4142impl Node for AutoExposureNode {43fn update(&mut self, world: &mut World) {44self.query.update_archetypes(world);45}4647fn run(48&self,49graph: &mut RenderGraphContext,50render_context: &mut RenderContext,51world: &World,52) -> Result<(), NodeRunError> {53let view_entity = graph.view_entity();54let pipeline_cache = world.resource::<PipelineCache>();55let pipeline = world.resource::<AutoExposurePipeline>();56let resources = world.resource::<AutoExposureResources>();5758let view_uniforms_resource = world.resource::<ViewUniforms>();59let view_uniforms = &view_uniforms_resource.uniforms;60let view_uniforms_buffer = view_uniforms.buffer().unwrap();6162let globals_buffer = world.resource::<GlobalsBuffer>();6364let auto_exposure_buffers = world.resource::<AutoExposureBuffers>();6566let (67Ok((view_uniform_offset, view_target, auto_exposure, view)),68Some(auto_exposure_buffers),69) = (70self.query.get_manual(world, view_entity),71auto_exposure_buffers.buffers.get(&view_entity),72)73else {74return Ok(());75};7677let (Some(histogram_pipeline), Some(average_pipeline)) = (78pipeline_cache.get_compute_pipeline(auto_exposure.histogram_pipeline),79pipeline_cache.get_compute_pipeline(auto_exposure.mean_luminance_pipeline),80) else {81return Ok(());82};8384let source = view_target.main_texture_view();8586let fallback = world.resource::<FallbackImage>();87let mask = world88.resource::<RenderAssets<GpuImage>>()89.get(&auto_exposure.metering_mask);90let mask = mask91.map(|i| &i.texture_view)92.unwrap_or(&fallback.d2.texture_view);9394let Some(compensation_curve) = world95.resource::<RenderAssets<GpuAutoExposureCompensationCurve>>()96.get(&auto_exposure.compensation_curve)97else {98return Ok(());99};100101let diagnostics = render_context.diagnostic_recorder();102103let compute_bind_group = render_context.render_device().create_bind_group(104None,105&pipeline.histogram_layout,106&BindGroupEntries::sequential((107&globals_buffer.buffer,108&auto_exposure_buffers.settings,109source,110mask,111&compensation_curve.texture_view,112&compensation_curve.extents,113resources.histogram.as_entire_buffer_binding(),114&auto_exposure_buffers.state,115BufferBinding {116buffer: view_uniforms_buffer,117size: Some(ViewUniform::min_size()),118offset: 0,119},120)),121);122123let mut compute_pass =124render_context125.command_encoder()126.begin_compute_pass(&ComputePassDescriptor {127label: Some("auto_exposure"),128timestamp_writes: None,129});130let pass_span = diagnostics.time_span(&mut compute_pass, "auto_exposure");131132compute_pass.set_bind_group(0, &compute_bind_group, &[view_uniform_offset.offset]);133compute_pass.set_pipeline(histogram_pipeline);134compute_pass.dispatch_workgroups(135view.viewport.z.div_ceil(16),136view.viewport.w.div_ceil(16),1371,138);139compute_pass.set_pipeline(average_pipeline);140compute_pass.dispatch_workgroups(1, 1, 1);141142pass_span.end(&mut compute_pass);143144Ok(())145}146}147148149