Skip to main content

ranim_render/pipelines/
oit_resolve.rs

1use std::ops::Deref;
2
3use bevy_ecs::prelude::*;
4
5use crate::{
6    ResolutionInfo, WgpuContext,
7    resource::{GpuResource, OUTPUT_TEXTURE_FORMAT, PipelinesPool},
8    schedule::{FrameTarget, RenderContext, RenderProfiler},
9};
10
11pub(crate) fn resolve(
12    mut render: RenderContext,
13    ctx: Res<WgpuContext>,
14    pipelines: Res<PipelinesPool>,
15    resolution: Res<ResolutionInfo>,
16    target: Res<FrameTarget>,
17    profiler: Res<RenderProfiler>,
18) {
19    let mut pass = render
20        .encoder()
21        .begin_render_pass(&wgpu::RenderPassDescriptor {
22            label: Some("OIT Resolve Pass"),
23            color_attachments: &[Some(wgpu::RenderPassColorAttachment {
24                view: &target.render_view,
25                resolve_target: None,
26                depth_slice: None,
27                ops: wgpu::Operations {
28                    load: wgpu::LoadOp::Load,
29                    store: wgpu::StoreOp::Store,
30                },
31            })],
32            depth_stencil_attachment: None,
33            timestamp_writes: None,
34            occlusion_query_set: None,
35            multiview_mask: None,
36        });
37    profiler.scope_pass("oit::resolve", &mut pass, |pass| {
38        pass.set_pipeline(&pipelines.get_or_init::<OITResolvePipeline>(&ctx));
39        pass.set_bind_group(0, &resolution.bind_group, &[]);
40        pass.set_bind_group(1, &target.depth_bind_group, &[]);
41        pass.draw(0..3, 0..1);
42    });
43    drop(pass);
44    render
45        .encoder()
46        .clear_buffer(&resolution.pixel_count_buffer.buffer, 0, None);
47}
48
49pub struct OITResolvePipeline {
50    pipeline: wgpu::RenderPipeline,
51}
52
53impl Deref for OITResolvePipeline {
54    type Target = wgpu::RenderPipeline;
55    fn deref(&self) -> &Self::Target {
56        &self.pipeline
57    }
58}
59
60impl OITResolvePipeline {
61    pub fn depth_bind_group_layout(ctx: &WgpuContext) -> wgpu::BindGroupLayout {
62        ctx.device
63            .create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
64                label: Some("OIT Resolve Depth BGL"),
65                entries: &[wgpu::BindGroupLayoutEntry {
66                    binding: 0,
67                    visibility: wgpu::ShaderStages::FRAGMENT,
68                    ty: wgpu::BindingType::Texture {
69                        sample_type: wgpu::TextureSampleType::Depth,
70                        view_dimension: wgpu::TextureViewDimension::D2,
71                        multisampled: false,
72                    },
73                    count: None,
74                }],
75            })
76    }
77}
78
79impl GpuResource for OITResolvePipeline {
80    fn new(wgpu_ctx: &WgpuContext) -> Self {
81        let WgpuContext { device, .. } = wgpu_ctx;
82
83        let module =
84            &device.create_shader_module(wgpu::include_wgsl!("./shaders/oit_resolve.wgsl"));
85
86        let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
87            label: Some("OIT Resolve Pipeline Layout"),
88            bind_group_layouts: &[
89                Some(&ResolutionInfo::create_bind_group_layout(wgpu_ctx)),
90                Some(&Self::depth_bind_group_layout(wgpu_ctx)),
91            ],
92            immediate_size: 0,
93        });
94
95        let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
96            label: Some("OIT Resolve Pipeline"),
97            layout: Some(&pipeline_layout),
98            vertex: wgpu::VertexState {
99                module,
100                entry_point: Some("vs_main"),
101                buffers: &[],
102                compilation_options: wgpu::PipelineCompilationOptions::default(),
103            },
104            fragment: Some(wgpu::FragmentState {
105                module,
106                entry_point: Some("fs_main"),
107                compilation_options: wgpu::PipelineCompilationOptions::default(),
108                targets: &[Some(wgpu::ColorTargetState {
109                    format: OUTPUT_TEXTURE_FORMAT,
110                    blend: Some(wgpu::BlendState::ALPHA_BLENDING),
111                    write_mask: wgpu::ColorWrites::ALL,
112                })],
113            }),
114            primitive: wgpu::PrimitiveState {
115                topology: wgpu::PrimitiveTopology::TriangleList,
116                ..Default::default()
117            },
118            depth_stencil: None, // No depth attachment
119            multisample: wgpu::MultisampleState {
120                count: 1,
121                mask: !0,
122                alpha_to_coverage_enabled: false,
123            },
124            multiview_mask: None,
125            cache: None,
126        });
127
128        Self { pipeline }
129    }
130}