Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_render/src/texture/texture_attachment.rs
6596 views
1
use super::CachedTexture;
2
use crate::render_resource::{TextureFormat, TextureView};
3
use alloc::sync::Arc;
4
use bevy_color::LinearRgba;
5
use core::sync::atomic::{AtomicBool, Ordering};
6
use wgpu::{
7
LoadOp, Operations, RenderPassColorAttachment, RenderPassDepthStencilAttachment, StoreOp,
8
};
9
10
/// A wrapper for a [`CachedTexture`] that is used as a [`RenderPassColorAttachment`].
11
#[derive(Clone)]
12
pub 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
19
impl 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
/// Get this texture view as an attachment. The attachment will be cleared with a value of
34
/// `clear_color` if this is the first time calling this function, otherwise it will be loaded.
35
///
36
/// The returned attachment will always have writing enabled (`store: StoreOp::Load`).
37
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
depth_slice: None,
44
resolve_target: Some(&self.texture.default_view),
45
ops: Operations {
46
load: match (self.clear_color, first_call) {
47
(Some(clear_color), true) => LoadOp::Clear(clear_color.into()),
48
(None, _) | (Some(_), false) => LoadOp::Load,
49
},
50
store: StoreOp::Store,
51
},
52
}
53
} else {
54
self.get_unsampled_attachment()
55
}
56
}
57
58
/// Get this texture view as an attachment, without the resolve target. The attachment will be cleared with
59
/// a value of `clear_color` if this is the first time calling this function, otherwise it will be loaded.
60
///
61
/// The returned attachment will always have writing enabled (`store: StoreOp::Load`).
62
pub fn get_unsampled_attachment(&self) -> RenderPassColorAttachment<'_> {
63
let first_call = self.is_first_call.fetch_and(false, Ordering::SeqCst);
64
65
RenderPassColorAttachment {
66
view: &self.texture.default_view,
67
depth_slice: None,
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
84
/// A wrapper for a [`TextureView`] that is used as a depth-only [`RenderPassDepthStencilAttachment`].
85
#[derive(Clone)]
86
pub struct DepthAttachment {
87
pub view: TextureView,
88
clear_value: Option<f32>,
89
is_first_call: Arc<AtomicBool>,
90
}
91
92
impl DepthAttachment {
93
pub fn new(view: TextureView, clear_value: Option<f32>) -> Self {
94
Self {
95
view,
96
clear_value,
97
is_first_call: Arc::new(AtomicBool::new(clear_value.is_some())),
98
}
99
}
100
101
/// Get this texture view as an attachment. The attachment will be cleared with a value of
102
/// `clear_value` if this is the first time calling this function with `store` == [`StoreOp::Store`],
103
/// and a clear value was provided, otherwise it will be loaded.
104
pub fn get_attachment(&self, store: StoreOp) -> RenderPassDepthStencilAttachment<'_> {
105
let first_call = self
106
.is_first_call
107
.fetch_and(store != StoreOp::Store, Ordering::SeqCst);
108
109
RenderPassDepthStencilAttachment {
110
view: &self.view,
111
depth_ops: Some(Operations {
112
load: if first_call {
113
// If first_call is true, then a clear value will always have been provided in the constructor
114
LoadOp::Clear(self.clear_value.unwrap())
115
} else {
116
LoadOp::Load
117
},
118
store,
119
}),
120
stencil_ops: None,
121
}
122
}
123
}
124
125
/// A wrapper for a [`TextureView`] that is used as a [`RenderPassColorAttachment`] for a view
126
/// target's final output texture.
127
#[derive(Clone)]
128
pub struct OutputColorAttachment {
129
pub view: TextureView,
130
pub format: TextureFormat,
131
is_first_call: Arc<AtomicBool>,
132
}
133
134
impl OutputColorAttachment {
135
pub fn new(view: TextureView, format: TextureFormat) -> Self {
136
Self {
137
view,
138
format,
139
is_first_call: Arc::new(AtomicBool::new(true)),
140
}
141
}
142
143
/// Get this texture view as an attachment. The attachment will be cleared with a value of
144
/// the provided `clear_color` if this is the first time calling this function, otherwise it
145
/// will be loaded.
146
pub fn get_attachment(&self, clear_color: Option<LinearRgba>) -> RenderPassColorAttachment<'_> {
147
let first_call = self.is_first_call.fetch_and(false, Ordering::SeqCst);
148
149
RenderPassColorAttachment {
150
view: &self.view,
151
depth_slice: None,
152
resolve_target: None,
153
ops: Operations {
154
load: match (clear_color, first_call) {
155
(Some(clear_color), true) => LoadOp::Clear(clear_color.into()),
156
(None, _) | (Some(_), false) => LoadOp::Load,
157
},
158
store: StoreOp::Store,
159
},
160
}
161
}
162
}
163
164