bevy_render/texture/
texture_attachment.rs1use super::CachedTexture;
2use crate::render_resource::{TextureFormat, TextureView};
3use alloc::sync::Arc;
4use bevy_color::LinearRgba;
5use core::sync::atomic::{AtomicBool, Ordering};
6use wgpu::{
7 LoadOp, Operations, RenderPassColorAttachment, RenderPassDepthStencilAttachment, StoreOp,
8};
9
10#[derive(Clone)]
12pub struct ColorAttachment {
13 pub texture: CachedTexture,
14 pub resolve_target: Option<CachedTexture>,
15 clear_color: Option<LinearRgba>,
16 is_first_call: Arc<AtomicBool>,
17}
18
19impl ColorAttachment {
20 pub fn new(
21 texture: CachedTexture,
22 resolve_target: Option<CachedTexture>,
23 clear_color: Option<LinearRgba>,
24 ) -> Self {
25 Self {
26 texture,
27 resolve_target,
28 clear_color,
29 is_first_call: Arc::new(AtomicBool::new(true)),
30 }
31 }
32
33 pub fn get_attachment(&self) -> RenderPassColorAttachment {
38 if let Some(resolve_target) = self.resolve_target.as_ref() {
39 let first_call = self.is_first_call.fetch_and(false, Ordering::SeqCst);
40
41 RenderPassColorAttachment {
42 view: &resolve_target.default_view,
43 resolve_target: Some(&self.texture.default_view),
44 ops: Operations {
45 load: match (self.clear_color, first_call) {
46 (Some(clear_color), true) => LoadOp::Clear(clear_color.into()),
47 (None, _) | (Some(_), false) => LoadOp::Load,
48 },
49 store: StoreOp::Store,
50 },
51 }
52 } else {
53 self.get_unsampled_attachment()
54 }
55 }
56
57 pub fn get_unsampled_attachment(&self) -> RenderPassColorAttachment {
62 let first_call = self.is_first_call.fetch_and(false, Ordering::SeqCst);
63
64 RenderPassColorAttachment {
65 view: &self.texture.default_view,
66 resolve_target: None,
67 ops: Operations {
68 load: match (self.clear_color, first_call) {
69 (Some(clear_color), true) => LoadOp::Clear(clear_color.into()),
70 (None, _) | (Some(_), false) => LoadOp::Load,
71 },
72 store: StoreOp::Store,
73 },
74 }
75 }
76
77 pub(crate) fn mark_as_cleared(&self) {
78 self.is_first_call.store(false, Ordering::SeqCst);
79 }
80}
81
82#[derive(Clone)]
84pub struct DepthAttachment {
85 pub view: TextureView,
86 clear_value: Option<f32>,
87 is_first_call: Arc<AtomicBool>,
88}
89
90impl DepthAttachment {
91 pub fn new(view: TextureView, clear_value: Option<f32>) -> Self {
92 Self {
93 view,
94 clear_value,
95 is_first_call: Arc::new(AtomicBool::new(clear_value.is_some())),
96 }
97 }
98
99 pub fn get_attachment(&self, store: StoreOp) -> RenderPassDepthStencilAttachment {
103 let first_call = self
104 .is_first_call
105 .fetch_and(store != StoreOp::Store, Ordering::SeqCst);
106
107 RenderPassDepthStencilAttachment {
108 view: &self.view,
109 depth_ops: Some(Operations {
110 load: if first_call {
111 LoadOp::Clear(self.clear_value.unwrap())
113 } else {
114 LoadOp::Load
115 },
116 store,
117 }),
118 stencil_ops: None,
119 }
120 }
121}
122
123#[derive(Clone)]
126pub struct OutputColorAttachment {
127 pub view: TextureView,
128 pub format: TextureFormat,
129 is_first_call: Arc<AtomicBool>,
130}
131
132impl OutputColorAttachment {
133 pub fn new(view: TextureView, format: TextureFormat) -> Self {
134 Self {
135 view,
136 format,
137 is_first_call: Arc::new(AtomicBool::new(true)),
138 }
139 }
140
141 pub fn get_attachment(&self, clear_color: Option<LinearRgba>) -> RenderPassColorAttachment {
145 let first_call = self.is_first_call.fetch_and(false, Ordering::SeqCst);
146
147 RenderPassColorAttachment {
148 view: &self.view,
149 resolve_target: None,
150 ops: Operations {
151 load: match (clear_color, first_call) {
152 (Some(clear_color), true) => LoadOp::Clear(clear_color.into()),
153 (None, _) | (Some(_), false) => LoadOp::Load,
154 },
155 store: StoreOp::Store,
156 },
157 }
158 }
159}