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