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