1515//!
1616//! ```ignore
1717//! let mut encoder = CommandEncoder::new(&render_context, "frame-encoder");
18- //! encoder.with_render_pass(&pass, &mut attachments, depth, |rp_encoder| {
18+ //! encoder.with_render_pass(
19+ //! &pass,
20+ //! RenderPassDestinationInfo { color_format: None, depth_format: None },
21+ //! &mut attachments,
22+ //! depth,
23+ //! |rp_encoder| {
1924//! rp_encoder.set_pipeline(&pipeline)?;
2025//! rp_encoder.draw(0..3, 0..1)?;
2126//! Ok(())
@@ -42,7 +47,11 @@ use super::{
4247 pipeline,
4348 pipeline:: RenderPipeline ,
4449 render_pass:: RenderPass ,
45- texture:: DepthTexture ,
50+ texture:: {
51+ DepthFormat ,
52+ DepthTexture ,
53+ TextureFormat ,
54+ } ,
4655 validation,
4756 viewport:: Viewport ,
4857 RenderContext ,
@@ -53,6 +62,13 @@ use crate::util;
5362// CommandEncoder
5463// ---------------------------------------------------------------------------
5564
65+ /// Destination metadata needed for render-target compatibility validation.
66+ #[ derive( Clone , Copy , Debug ) ]
67+ pub ( crate ) struct RenderPassDestinationInfo {
68+ pub ( crate ) color_format : Option < TextureFormat > ,
69+ pub ( crate ) depth_format : Option < DepthFormat > ,
70+ }
71+
5672/// High-level command encoder for recording GPU work.
5773///
5874/// Created per-frame via `CommandEncoder::new()`. Commands are recorded by
@@ -99,6 +115,7 @@ impl CommandEncoder {
99115 pub ( crate ) fn with_render_pass < ' pass , PassFn , Output > (
100116 & ' pass mut self ,
101117 pass : & ' pass RenderPass ,
118+ destination_info : RenderPassDestinationInfo ,
102119 color_attachments : & ' pass mut RenderColorAttachments < ' pass > ,
103120 depth_texture : Option < & ' pass DepthTexture > ,
104121 func : PassFn ,
@@ -110,6 +127,7 @@ impl CommandEncoder {
110127 let pass_encoder = RenderPassEncoder :: new (
111128 & mut self . inner ,
112129 pass,
130+ destination_info,
113131 color_attachments,
114132 depth_texture,
115133 ) ;
@@ -162,6 +180,10 @@ pub struct RenderPassEncoder<'pass> {
162180 has_stencil : bool ,
163181 /// Sample count for MSAA validation.
164182 sample_count : u32 ,
183+ /// Destination color format when the pass has color output.
184+ destination_color_format : Option < TextureFormat > ,
185+ /// Destination depth format when a depth attachment is present.
186+ destination_depth_format : Option < DepthFormat > ,
165187
166188 // Validation state (compiled out in release without features)
167189 #[ cfg( any( debug_assertions, feature = "render-validation-encoder" ) ) ]
@@ -206,6 +228,7 @@ impl<'pass> RenderPassEncoder<'pass> {
206228 fn new (
207229 encoder : & ' pass mut platform:: command:: CommandEncoder ,
208230 pass : & ' pass RenderPass ,
231+ destination_info : RenderPassDestinationInfo ,
209232 color_attachments : & ' pass mut RenderColorAttachments < ' pass > ,
210233 depth_texture : Option < & ' pass DepthTexture > ,
211234 ) -> Self {
@@ -243,6 +266,8 @@ impl<'pass> RenderPassEncoder<'pass> {
243266 has_depth_attachment,
244267 has_stencil,
245268 sample_count : pass. sample_count ( ) ,
269+ destination_color_format : destination_info. color_format ,
270+ destination_depth_format : destination_info. depth_format ,
246271 #[ cfg( any( debug_assertions, feature = "render-validation-encoder" ) ) ]
247272 current_pipeline : None ,
248273 #[ cfg( any( debug_assertions, feature = "render-validation-encoder" ) ) ]
@@ -304,6 +329,46 @@ impl<'pass> RenderPassEncoder<'pass> {
304329 }
305330 }
306331
332+ #[ cfg( any( debug_assertions, feature = "render-validation-render-targets" , ) ) ]
333+ {
334+ let label = pipeline. pipeline ( ) . label ( ) . unwrap_or ( "unnamed" ) ;
335+
336+ if pipeline. sample_count ( ) != self . sample_count {
337+ return Err ( RenderPassError :: PipelineIncompatible ( format ! (
338+ "Render pipeline '{}' has sample_count={} but pass sample_count={}" ,
339+ label,
340+ pipeline. sample_count( ) ,
341+ self . sample_count
342+ ) ) ) ;
343+ }
344+
345+ if self . uses_color {
346+ if let Some ( dest_format) = self . destination_color_format {
347+ if pipeline. color_target_format ( ) != Some ( dest_format) {
348+ return Err ( RenderPassError :: PipelineIncompatible ( format ! (
349+ "Render pipeline '{}' color format {:?} does not match destination color format {:?}" ,
350+ label,
351+ pipeline. color_target_format( ) ,
352+ dest_format
353+ ) ) ) ;
354+ }
355+ }
356+ }
357+
358+ if self . has_depth_attachment && pipeline. expects_depth_stencil ( ) {
359+ if let Some ( dest_depth_format) = self . destination_depth_format {
360+ if pipeline. depth_format ( ) != Some ( dest_depth_format) {
361+ return Err ( RenderPassError :: PipelineIncompatible ( format ! (
362+ "Render pipeline '{}' depth format {:?} does not match destination depth format {:?}" ,
363+ label,
364+ pipeline. depth_format( ) ,
365+ dest_depth_format
366+ ) ) ) ;
367+ }
368+ }
369+ }
370+ }
371+
307372 // Track current pipeline for draw validation
308373 #[ cfg( any( debug_assertions, feature = "render-validation-encoder" ) ) ]
309374 {
0 commit comments