Path: blob/main/crates/bevy_render/src/texture/texture_attachment.rs
6596 views
use super::CachedTexture;1use crate::render_resource::{TextureFormat, TextureView};2use alloc::sync::Arc;3use bevy_color::LinearRgba;4use core::sync::atomic::{AtomicBool, Ordering};5use wgpu::{6LoadOp, Operations, RenderPassColorAttachment, RenderPassDepthStencilAttachment, StoreOp,7};89/// A wrapper for a [`CachedTexture`] that is used as a [`RenderPassColorAttachment`].10#[derive(Clone)]11pub struct ColorAttachment {12pub texture: CachedTexture,13pub resolve_target: Option<CachedTexture>,14clear_color: Option<LinearRgba>,15is_first_call: Arc<AtomicBool>,16}1718impl ColorAttachment {19pub fn new(20texture: CachedTexture,21resolve_target: Option<CachedTexture>,22clear_color: Option<LinearRgba>,23) -> Self {24Self {25texture,26resolve_target,27clear_color,28is_first_call: Arc::new(AtomicBool::new(true)),29}30}3132/// Get this texture view as an attachment. The attachment will be cleared with a value of33/// `clear_color` if this is the first time calling this function, otherwise it will be loaded.34///35/// The returned attachment will always have writing enabled (`store: StoreOp::Load`).36pub fn get_attachment(&self) -> RenderPassColorAttachment<'_> {37if let Some(resolve_target) = self.resolve_target.as_ref() {38let first_call = self.is_first_call.fetch_and(false, Ordering::SeqCst);3940RenderPassColorAttachment {41view: &resolve_target.default_view,42depth_slice: None,43resolve_target: Some(&self.texture.default_view),44ops: Operations {45load: match (self.clear_color, first_call) {46(Some(clear_color), true) => LoadOp::Clear(clear_color.into()),47(None, _) | (Some(_), false) => LoadOp::Load,48},49store: StoreOp::Store,50},51}52} else {53self.get_unsampled_attachment()54}55}5657/// Get this texture view as an attachment, without the resolve target. The attachment will be cleared with58/// a value of `clear_color` if this is the first time calling this function, otherwise it will be loaded.59///60/// The returned attachment will always have writing enabled (`store: StoreOp::Load`).61pub fn get_unsampled_attachment(&self) -> RenderPassColorAttachment<'_> {62let first_call = self.is_first_call.fetch_and(false, Ordering::SeqCst);6364RenderPassColorAttachment {65view: &self.texture.default_view,66depth_slice: None,67resolve_target: None,68ops: Operations {69load: match (self.clear_color, first_call) {70(Some(clear_color), true) => LoadOp::Clear(clear_color.into()),71(None, _) | (Some(_), false) => LoadOp::Load,72},73store: StoreOp::Store,74},75}76}7778pub(crate) fn mark_as_cleared(&self) {79self.is_first_call.store(false, Ordering::SeqCst);80}81}8283/// A wrapper for a [`TextureView`] that is used as a depth-only [`RenderPassDepthStencilAttachment`].84#[derive(Clone)]85pub struct DepthAttachment {86pub view: TextureView,87clear_value: Option<f32>,88is_first_call: Arc<AtomicBool>,89}9091impl DepthAttachment {92pub fn new(view: TextureView, clear_value: Option<f32>) -> Self {93Self {94view,95clear_value,96is_first_call: Arc::new(AtomicBool::new(clear_value.is_some())),97}98}99100/// Get this texture view as an attachment. The attachment will be cleared with a value of101/// `clear_value` if this is the first time calling this function with `store` == [`StoreOp::Store`],102/// and a clear value was provided, otherwise it will be loaded.103pub fn get_attachment(&self, store: StoreOp) -> RenderPassDepthStencilAttachment<'_> {104let first_call = self105.is_first_call106.fetch_and(store != StoreOp::Store, Ordering::SeqCst);107108RenderPassDepthStencilAttachment {109view: &self.view,110depth_ops: Some(Operations {111load: if first_call {112// If first_call is true, then a clear value will always have been provided in the constructor113LoadOp::Clear(self.clear_value.unwrap())114} else {115LoadOp::Load116},117store,118}),119stencil_ops: None,120}121}122}123124/// A wrapper for a [`TextureView`] that is used as a [`RenderPassColorAttachment`] for a view125/// target's final output texture.126#[derive(Clone)]127pub struct OutputColorAttachment {128pub view: TextureView,129pub format: TextureFormat,130is_first_call: Arc<AtomicBool>,131}132133impl OutputColorAttachment {134pub fn new(view: TextureView, format: TextureFormat) -> Self {135Self {136view,137format,138is_first_call: Arc::new(AtomicBool::new(true)),139}140}141142/// Get this texture view as an attachment. The attachment will be cleared with a value of143/// the provided `clear_color` if this is the first time calling this function, otherwise it144/// will be loaded.145pub fn get_attachment(&self, clear_color: Option<LinearRgba>) -> RenderPassColorAttachment<'_> {146let first_call = self.is_first_call.fetch_and(false, Ordering::SeqCst);147148RenderPassColorAttachment {149view: &self.view,150depth_slice: None,151resolve_target: None,152ops: Operations {153load: match (clear_color, first_call) {154(Some(clear_color), true) => LoadOp::Clear(clear_color.into()),155(None, _) | (Some(_), false) => LoadOp::Load,156},157store: StoreOp::Store,158},159}160}161}162163164