From 4042689f8eb8dccc8e82e98a36bd099a2d7971b5 Mon Sep 17 00:00:00 2001 From: Jinlei Li Date: Fri, 24 Jun 2022 19:09:02 +0800 Subject: [PATCH 1/6] Make the color attachments `Option`-al in render pipelines, render passes, and render bundles --- deno_webgpu/webgpu.idl | 6 +- wgpu-core/src/command/bundle.rs | 2 +- wgpu-core/src/command/clear.rs | 4 +- wgpu-core/src/command/render.rs | 39 ++++--- wgpu-core/src/device/mod.rs | 100 ++++++++++-------- wgpu-core/src/device/trace.rs | 2 +- wgpu-core/src/pipeline.rs | 4 +- wgpu-hal/examples/halmark/main.rs | 8 +- wgpu-hal/src/lib.rs | 4 +- wgpu-hal/src/metal/command.rs | 36 ++++--- wgpu-hal/src/metal/device.rs | 6 ++ wgpu/examples/boids/main.rs | 6 +- wgpu/examples/bunnymark/main.rs | 8 +- wgpu/examples/capture/main.rs | 4 +- wgpu/examples/conservative-raster/main.rs | 16 +-- wgpu/examples/cube/main.rs | 10 +- wgpu/examples/hello-triangle/main.rs | 6 +- wgpu/examples/hello-windows/main.rs | 4 +- wgpu/examples/mipmap/main.rs | 12 +-- wgpu/examples/msaa-line/main.rs | 6 +- wgpu/examples/shadow/main.rs | 6 +- wgpu/examples/skybox/main.rs | 8 +- wgpu/examples/texture-arrays/main.rs | 6 +- wgpu/examples/water/main.rs | 20 ++-- wgpu/src/backend/direct.rs | 11 +- wgpu/src/lib.rs | 6 +- wgpu/tests/shader_primitive_index/mod.rs | 8 +- wgpu/tests/vertex_indices/mod.rs | 8 +- wgpu/tests/zero_init_texture_after_discard.rs | 8 +- 29 files changed, 197 insertions(+), 167 deletions(-) diff --git a/deno_webgpu/webgpu.idl b/deno_webgpu/webgpu.idl index 5ea251e774..e088fa2778 100644 --- a/deno_webgpu/webgpu.idl +++ b/deno_webgpu/webgpu.idl @@ -613,7 +613,7 @@ dictionary GPUMultisampleState { }; dictionary GPUFragmentState : GPUProgrammableStage { - required sequence targets; + required sequence targets; }; dictionary GPUColorTargetState { @@ -908,7 +908,7 @@ GPURenderPassEncoder includes GPUBindingCommandsMixin; GPURenderPassEncoder includes GPURenderCommandsMixin; dictionary GPURenderPassDescriptor : GPUObjectDescriptorBase { - required sequence colorAttachments; + required sequence colorAttachments; GPURenderPassDepthStencilAttachment depthStencilAttachment; GPUQuerySet occlusionQuerySet; }; @@ -947,7 +947,7 @@ enum GPUStoreOp { }; dictionary GPURenderPassLayout: GPUObjectDescriptorBase { - required sequence colorFormats; + required sequence colorFormats; GPUTextureFormat depthStencilFormat; GPUSize32 sampleCount = 1; }; diff --git a/wgpu-core/src/command/bundle.rs b/wgpu-core/src/command/bundle.rs index 1ec147055d..c756137f60 100644 --- a/wgpu-core/src/command/bundle.rs +++ b/wgpu-core/src/command/bundle.rs @@ -114,7 +114,7 @@ pub struct RenderBundleEncoderDescriptor<'a> { pub label: Label<'a>, /// The formats of the color attachments that this render bundle is capable to rendering to. This /// must match the formats of the color attachments in the renderpass this render bundle is executed in. - pub color_formats: Cow<'a, [wgt::TextureFormat]>, + pub color_formats: Cow<'a, [Option]>, /// Information about the depth attachment that this render bundle is capable to rendering to. The format /// must match the format of the depth attachments in the renderpass this render bundle is executed in. pub depth_stencil: Option, diff --git a/wgpu-core/src/command/clear.rs b/wgpu-core/src/command/clear.rs index 3e94843798..bf0c90ff49 100644 --- a/wgpu-core/src/command/clear.rs +++ b/wgpu-core/src/command/clear.rs @@ -408,7 +408,7 @@ fn clear_texture_via_render_passes( for depth_or_layer in layer_or_depth_range { let color_attachments_tmp; let (color_attachments, depth_stencil_attachment) = if is_color { - color_attachments_tmp = [hal::ColorAttachment { + color_attachments_tmp = [Some(hal::ColorAttachment { target: hal::Attachment { view: dst_texture.get_clear_view(mip_level, depth_or_layer), usage: hal::TextureUses::COLOR_TARGET, @@ -416,7 +416,7 @@ fn clear_texture_via_render_passes( resolve_target: None, ops: hal::AttachmentOps::STORE, clear_value: wgt::Color::TRANSPARENT, - }]; + })]; (&color_attachments_tmp[..], None) } else { ( diff --git a/wgpu-core/src/command/render.rs b/wgpu-core/src/command/render.rs index d2746ba621..810114dca8 100644 --- a/wgpu-core/src/command/render.rs +++ b/wgpu-core/src/command/render.rs @@ -173,7 +173,7 @@ impl RenderPassDepthStencilAttachment { pub struct RenderPassDescriptor<'a> { pub label: Label<'a>, /// The color attachments of the render pass. - pub color_attachments: Cow<'a, [RenderPassColorAttachment]>, + pub color_attachments: Cow<'a, [Option]>, /// The depth and stencil attachment of the render pass, if any. pub depth_stencil_attachment: Option<&'a RenderPassDepthStencilAttachment>, } @@ -182,7 +182,7 @@ pub struct RenderPassDescriptor<'a> { pub struct RenderPass { base: BasePass, parent_id: id::CommandEncoderId, - color_targets: ArrayVec, + color_targets: ArrayVec, { hal::MAX_COLOR_ATTACHMENTS }>, depth_stencil_target: Option, // Resource binding dedupe state. @@ -441,7 +441,7 @@ pub enum RenderPassErrorInner { InvalidDepthStencilAttachmentFormat(wgt::TextureFormat), #[error("attachment format {0:?} can not be resolved")] UnsupportedResolveTargetFormat(wgt::TextureFormat), - #[error("necessary attachments are missing")] + #[error("missing color or depth_stencil attachments, at least one is required.")] MissingAttachments, #[error("attachments have differing sizes: {previous:?} is followed by {mismatch:?}")] AttachmentsDimensionMismatch { @@ -646,7 +646,7 @@ impl<'a, A: HalApi> RenderPassInfo<'a, A> { fn start( device: &Device, label: Option<&str>, - color_attachments: &[RenderPassColorAttachment], + color_attachments: &[Option], depth_stencil_attachment: Option<&RenderPassDepthStencilAttachment>, cmd_buf: &mut CommandBuffer, view_guard: &'a Storage, id::TextureViewId>, @@ -722,11 +722,15 @@ impl<'a, A: HalApi> RenderPassInfo<'a, A> { expected: sample_count, }); } + if sample_count != 1 && sample_count != 4 { + return Err(RenderPassErrorInner::InvalidSampleCount(sample_count)); + } attachment_type_name = type_name; Ok(()) }; - let mut colors = ArrayVec::, { hal::MAX_COLOR_ATTACHMENTS }>::new(); + let mut colors = + ArrayVec::>, { hal::MAX_COLOR_ATTACHMENTS }>::new(); let mut depth_stencil = None; if let Some(at) = depth_stencil_attachment { @@ -840,6 +844,12 @@ impl<'a, A: HalApi> RenderPassInfo<'a, A> { } for at in color_attachments { + let at = if let Some(attachment) = at.as_ref() { + attachment + } else { + colors.push(None); + continue; + }; let color_view: &TextureView = cmd_buf .trackers .views @@ -919,7 +929,7 @@ impl<'a, A: HalApi> RenderPassInfo<'a, A> { }); } - colors.push(hal::ColorAttachment { + colors.push(Some(hal::ColorAttachment { target: hal::Attachment { view: &color_view.raw, usage: hal::TextureUses::COLOR_TARGET, @@ -927,28 +937,25 @@ impl<'a, A: HalApi> RenderPassInfo<'a, A> { resolve_target: hal_resolve_target, ops: at.channel.hal_ops(), clear_value: at.channel.clear_value, - }); + })); } - if sample_count != 1 && sample_count != 4 { - return Err(RenderPassErrorInner::InvalidSampleCount(sample_count)); - } + let extent = extent.ok_or(RenderPassErrorInner::MissingAttachments)?; + let multiview = detected_multiview.expect("Multiview was not detected, no attachments"); let view_data = AttachmentData { colors: color_attachments .iter() - .map(|at| view_guard.get(at.view).unwrap()) + .map(|at| at.as_ref().map(|at| view_guard.get(at.view).unwrap())) .collect(), resolves: color_attachments .iter() - .filter_map(|at| at.resolve_target) - .map(|attachment| view_guard.get(attachment).unwrap()) + .filter_map(|at| at.as_ref().map(|at| at.resolve_target)) + .filter_map(|attachment| attachment.as_ref().map(|at| view_guard.get(*at).unwrap())) .collect(), depth_stencil: depth_stencil_attachment.map(|at| view_guard.get(at.view).unwrap()), }; - let extent = extent.ok_or(RenderPassErrorInner::MissingAttachments)?; - let multiview = detected_multiview.expect("Multiview was not detected, no attachments"); let context = RenderPassContext { attachments: view_data.map(|view| view.desc.format), sample_count, @@ -1076,7 +1083,7 @@ impl Global { &self, encoder_id: id::CommandEncoderId, base: BasePassRef, - color_attachments: &[RenderPassColorAttachment], + color_attachments: &[Option], depth_stencil_attachment: Option<&RenderPassDepthStencilAttachment>, ) -> Result<(), RenderPassError> { profiling::scope!("run_render_pass", "CommandEncoder"); diff --git a/wgpu-core/src/device/mod.rs b/wgpu-core/src/device/mod.rs index 38366b0429..8043b3da96 100644 --- a/wgpu-core/src/device/mod.rs +++ b/wgpu-core/src/device/mod.rs @@ -20,7 +20,7 @@ use hal::{CommandEncoder as _, Device as _}; use parking_lot::{Mutex, MutexGuard}; use smallvec::SmallVec; use thiserror::Error; -use wgt::{BufferAddress, TextureFormat, TextureViewDimension}; +use wgt::{BufferAddress, ColorTargetState, TextureFormat, TextureViewDimension}; use std::{borrow::Cow, iter, mem, num::NonZeroU32, ops::Range, ptr}; @@ -52,7 +52,7 @@ pub enum HostMap { #[derive(Clone, Debug, Hash, PartialEq)] #[cfg_attr(feature = "serial-pass", derive(serde::Deserialize, serde::Serialize))] pub(crate) struct AttachmentData { - pub colors: ArrayVec, + pub colors: ArrayVec, { hal::MAX_COLOR_ATTACHMENTS }>, pub resolves: ArrayVec, pub depth_stencil: Option, } @@ -60,7 +60,7 @@ impl Eq for AttachmentData {} impl AttachmentData { pub(crate) fn map U>(&self, fun: F) -> AttachmentData { AttachmentData { - colors: self.colors.iter().map(&fun).collect(), + colors: self.colors.iter().map(|c| c.as_ref().map(&fun)).collect(), resolves: self.resolves.iter().map(&fun).collect(), depth_stencil: self.depth_stencil.as_ref().map(&fun), } @@ -78,8 +78,8 @@ pub(crate) struct RenderPassContext { pub enum RenderPassCompatibilityError { #[error("Incompatible color attachment: the renderpass expected {0:?} but was given {1:?}")] IncompatibleColorAttachment( - ArrayVec, - ArrayVec, + ArrayVec, { hal::MAX_COLOR_ATTACHMENTS }>, + ArrayVec, { hal::MAX_COLOR_ATTACHMENTS }>, ), #[error( "Incompatible depth-stencil attachment: the renderpass expected {0:?} but was given {1:?}" @@ -2465,9 +2465,11 @@ impl Device { .map_or(&[][..], |fragment| &fragment.targets); let depth_stencil_state = desc.depth_stencil.as_ref(); - if !color_targets.is_empty() && { - let first = &color_targets[0]; - color_targets[1..] + let cts: ArrayVec<&ColorTargetState, { hal::MAX_COLOR_ATTACHMENTS }> = + color_targets.iter().filter_map(|x| x.as_ref()).collect(); + if !cts.is_empty() && { + let first = &cts[0]; + cts[1..] .iter() .any(|ct| ct.write_mask != first.write_mask || ct.blend != first.blend) } { @@ -2580,29 +2582,32 @@ impl Device { } for (i, cs) in color_targets.iter().enumerate() { - let error = loop { - let format_features = self.describe_format_features(adapter, cs.format)?; - if !format_features - .allowed_usages - .contains(wgt::TextureUsages::RENDER_ATTACHMENT) - { - break Some(pipeline::ColorStateError::FormatNotRenderable(cs.format)); - } - if cs.blend.is_some() && !format_features.flags.contains(Tfff::FILTERABLE) { - break Some(pipeline::ColorStateError::FormatNotBlendable(cs.format)); - } - if !hal::FormatAspects::from(cs.format).contains(hal::FormatAspects::COLOR) { - break Some(pipeline::ColorStateError::FormatNotColor(cs.format)); - } - if desc.multisample.count > 1 && !format_features.flags.contains(Tfff::MULTISAMPLE) - { - break Some(pipeline::ColorStateError::FormatNotMultisampled(cs.format)); - } + if let Some(cs) = cs.as_ref() { + let error = loop { + let format_features = self.describe_format_features(adapter, cs.format)?; + if !format_features + .allowed_usages + .contains(wgt::TextureUsages::RENDER_ATTACHMENT) + { + break Some(pipeline::ColorStateError::FormatNotRenderable(cs.format)); + } + if cs.blend.is_some() && !format_features.flags.contains(Tfff::FILTERABLE) { + break Some(pipeline::ColorStateError::FormatNotBlendable(cs.format)); + } + if !hal::FormatAspects::from(cs.format).contains(hal::FormatAspects::COLOR) { + break Some(pipeline::ColorStateError::FormatNotColor(cs.format)); + } + if desc.multisample.count > 1 + && !format_features.flags.contains(Tfff::MULTISAMPLE) + { + break Some(pipeline::ColorStateError::FormatNotMultisampled(cs.format)); + } - break None; - }; - if let Some(e) = error { - return Err(pipeline::CreateRenderPipelineError::ColorState(i as u8, e)); + break None; + }; + if let Some(e) = error { + return Err(pipeline::CreateRenderPipelineError::ColorState(i as u8, e)); + } } } @@ -2754,13 +2759,22 @@ impl Device { }; if validated_stages.contains(wgt::ShaderStages::FRAGMENT) { - for (i, state) in color_targets.iter().enumerate() { - match io.get(&(i as wgt::ShaderLocation)) { - Some(output) => { - validation::check_texture_format(state.format, &output.ty).map_err( + for (i, output) in io.iter() { + match color_targets.get(*i as usize) { + Some(state) => { + let format = if let Some(st) = state.as_ref() { + st.format + } else { + return Err( + pipeline::CreateRenderPipelineError::InvalidFragmentOutputLocation( + *i, + ), + ); + }; + validation::check_texture_format(format, &output.ty).map_err( |pipeline| { pipeline::CreateRenderPipelineError::ColorState( - i as u8, + *i as u8, pipeline::ColorStateError::IncompatibleFormat { pipeline, shader: output.ty, @@ -2769,14 +2783,7 @@ impl Device { }, )?; } - None if state.write_mask.is_empty() => {} - None => { - log::warn!("Missing fragment output[{}], expected {:?}", i, state,); - return Err(pipeline::CreateRenderPipelineError::ColorState( - i as u8, - pipeline::ColorStateError::Missing, - )); - } + None => (), } } } @@ -2850,7 +2857,10 @@ impl Device { let pass_context = RenderPassContext { attachments: AttachmentData { - colors: color_targets.iter().map(|state| state.format).collect(), + colors: color_targets + .iter() + .map(|state| state.as_ref().map(|s| s.format)) + .collect(), resolves: ArrayVec::new(), depth_stencil: depth_stencil_state.as_ref().map(|state| state.format), }, @@ -2859,7 +2869,7 @@ impl Device { }; let mut flags = pipeline::PipelineFlags::empty(); - for state in color_targets.iter() { + for state in color_targets.iter().filter_map(|s| s.as_ref()) { if let Some(ref bs) = state.blend { if bs.color.uses_constant() | bs.alpha.uses_constant() { flags |= pipeline::PipelineFlags::BLEND_CONSTANT; diff --git a/wgpu-core/src/device/trace.rs b/wgpu-core/src/device/trace.rs index 636a23de20..8892a8e016 100644 --- a/wgpu-core/src/device/trace.rs +++ b/wgpu-core/src/device/trace.rs @@ -176,7 +176,7 @@ pub enum Command { }, RunRenderPass { base: crate::command::BasePass, - target_colors: Vec, + target_colors: Vec>, target_depth_stencil: Option, }, } diff --git a/wgpu-core/src/pipeline.rs b/wgpu-core/src/pipeline.rs index 199f4ef973..8c31d23e89 100644 --- a/wgpu-core/src/pipeline.rs +++ b/wgpu-core/src/pipeline.rs @@ -249,7 +249,7 @@ pub struct FragmentState<'a> { /// The compiled fragment stage and its entry point. pub stage: ProgrammableStageDescriptor<'a>, /// The effect of draw calls on the color aspect of the output target. - pub targets: Cow<'a, [wgt::ColorTargetState]>, + pub targets: Cow<'a, [Option]>, } /// Describes a render (graphics) pipeline. @@ -317,6 +317,8 @@ pub enum CreateRenderPipelineError { Device(#[from] DeviceError), #[error("pipeline layout is invalid")] InvalidLayout, + #[error("fragment output @location({0}) is invalid")] + InvalidFragmentOutputLocation(u32), #[error("unable to derive an implicit layout")] Implicit(#[from] ImplicitLayoutError), #[error("color state [{0}] is invalid")] diff --git a/wgpu-hal/examples/halmark/main.rs b/wgpu-hal/examples/halmark/main.rs index d9638eb400..383efcdc53 100644 --- a/wgpu-hal/examples/halmark/main.rs +++ b/wgpu-hal/examples/halmark/main.rs @@ -238,11 +238,11 @@ impl Example { }, depth_stencil: None, multisample: wgt::MultisampleState::default(), - color_targets: &[wgt::ColorTargetState { + color_targets: &[Some(wgt::ColorTargetState { format: surface_config.format, blend: Some(wgt::BlendState::ALPHA_BLENDING), write_mask: wgt::ColorWrites::default(), - }], + })], multiview: None, }; let pipeline = unsafe { device.create_render_pipeline(&pipeline_desc).unwrap() }; @@ -646,7 +646,7 @@ impl Example { depth_or_array_layers: 1, }, sample_count: 1, - color_attachments: &[hal::ColorAttachment { + color_attachments: &[Some(hal::ColorAttachment { target: hal::Attachment { view: &surface_tex_view, usage: hal::TextureUses::COLOR_TARGET, @@ -659,7 +659,7 @@ impl Example { b: 0.3, a: 1.0, }, - }], + })], depth_stencil_attachment: None, multiview: None, }; diff --git a/wgpu-hal/src/lib.rs b/wgpu-hal/src/lib.rs index cf43d7d453..a343f111bb 100644 --- a/wgpu-hal/src/lib.rs +++ b/wgpu-hal/src/lib.rs @@ -1024,7 +1024,7 @@ pub struct RenderPipelineDescriptor<'a, A: Api> { /// The fragment stage for this pipeline. pub fragment_stage: Option>, /// The effect of draw calls on the color aspect of the output target. - pub color_targets: &'a [wgt::ColorTargetState], + pub color_targets: &'a [Option], /// If the pipeline will be used with a multiview render pass, this indicates how many array /// layers the attachments will have. pub multiview: Option, @@ -1179,7 +1179,7 @@ pub struct RenderPassDescriptor<'a, A: Api> { pub label: Label<'a>, pub extent: wgt::Extent3d, pub sample_count: u32, - pub color_attachments: &'a [ColorAttachment<'a, A>], + pub color_attachments: &'a [Option>], pub depth_stencil_attachment: Option>, pub multiview: Option, } diff --git a/wgpu-hal/src/metal/command.rs b/wgpu-hal/src/metal/command.rs index 7eaf97b659..589c60cc6a 100644 --- a/wgpu-hal/src/metal/command.rs +++ b/wgpu-hal/src/metal/command.rs @@ -353,24 +353,26 @@ impl crate::CommandEncoder for super::CommandEncoder { //TODO: set visibility results buffer for (i, at) in desc.color_attachments.iter().enumerate() { - let at_descriptor = descriptor.color_attachments().object_at(i as u64).unwrap(); - at_descriptor.set_texture(Some(&at.target.view.raw)); - if let Some(ref resolve) = at.resolve_target { - //Note: the selection of levels and slices is already handled by `TextureView` - at_descriptor.set_resolve_texture(Some(&resolve.view.raw)); + if let Some(at) = at { + let at_descriptor = descriptor.color_attachments().object_at(i as u64).unwrap(); + at_descriptor.set_texture(Some(&at.target.view.raw)); + if let Some(ref resolve) = at.resolve_target { + //Note: the selection of levels and slices is already handled by `TextureView` + at_descriptor.set_resolve_texture(Some(&resolve.view.raw)); + } + let load_action = if at.ops.contains(crate::AttachmentOps::LOAD) { + mtl::MTLLoadAction::Load + } else { + at_descriptor.set_clear_color(conv::map_clear_color(&at.clear_value)); + mtl::MTLLoadAction::Clear + }; + let store_action = conv::map_store_action( + at.ops.contains(crate::AttachmentOps::STORE), + at.resolve_target.is_some(), + ); + at_descriptor.set_load_action(load_action); + at_descriptor.set_store_action(store_action); } - let load_action = if at.ops.contains(crate::AttachmentOps::LOAD) { - mtl::MTLLoadAction::Load - } else { - at_descriptor.set_clear_color(conv::map_clear_color(&at.clear_value)); - mtl::MTLLoadAction::Clear - }; - let store_action = conv::map_store_action( - at.ops.contains(crate::AttachmentOps::STORE), - at.resolve_target.is_some(), - ); - at_descriptor.set_load_action(load_action); - at_descriptor.set_store_action(store_action); } if let Some(ref at) = desc.depth_stencil_attachment { diff --git a/wgpu-hal/src/metal/device.rs b/wgpu-hal/src/metal/device.rs index 4b36e3d757..8d3301554e 100644 --- a/wgpu-hal/src/metal/device.rs +++ b/wgpu-hal/src/metal/device.rs @@ -841,6 +841,12 @@ impl crate::Device for super::Device { for (i, ct) in desc.color_targets.iter().enumerate() { let at_descriptor = descriptor.color_attachments().object_at(i as u64).unwrap(); + let ct = if let Some(color_target) = ct.as_ref() { + color_target + } else { + at_descriptor.set_pixel_format(mtl::MTLPixelFormat::Invalid); + continue; + }; let raw_format = self.shared.private_caps.map_format(ct.format); at_descriptor.set_pixel_format(raw_format); diff --git a/wgpu/examples/boids/main.rs b/wgpu/examples/boids/main.rs index 229e096246..a4764cfd45 100644 --- a/wgpu/examples/boids/main.rs +++ b/wgpu/examples/boids/main.rs @@ -151,7 +151,7 @@ impl framework::Example for Example { fragment: Some(wgpu::FragmentState { module: &draw_shader, entry_point: "main_fs", - targets: &[config.format.into()], + targets: &[Some(config.format.into())], }), primitive: wgpu::PrimitiveState::default(), depth_stencil: None, @@ -272,7 +272,7 @@ impl framework::Example for Example { _spawner: &framework::Spawner, ) { // create render pass descriptor and its color attachments - let color_attachments = [wgpu::RenderPassColorAttachment { + let color_attachments = [Some(wgpu::RenderPassColorAttachment { view, resolve_target: None, ops: wgpu::Operations { @@ -281,7 +281,7 @@ impl framework::Example for Example { load: wgpu::LoadOp::Load, store: true, }, - }]; + })]; let render_pass_descriptor = wgpu::RenderPassDescriptor { label: None, color_attachments: &color_attachments, diff --git a/wgpu/examples/bunnymark/main.rs b/wgpu/examples/bunnymark/main.rs index aaf9f50c06..1d239b07da 100644 --- a/wgpu/examples/bunnymark/main.rs +++ b/wgpu/examples/bunnymark/main.rs @@ -116,11 +116,11 @@ impl framework::Example for Example { fragment: Some(wgpu::FragmentState { module: &shader, entry_point: "fs_main", - targets: &[wgpu::ColorTargetState { + targets: &[Some(wgpu::ColorTargetState { format: config.format, blend: Some(wgpu::BlendState::ALPHA_BLENDING), write_mask: wgpu::ColorWrites::default(), - }], + })], }), primitive: wgpu::PrimitiveState { topology: wgpu::PrimitiveTopology::TriangleStrip, @@ -329,14 +329,14 @@ impl framework::Example for Example { }; let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { label: None, - color_attachments: &[wgpu::RenderPassColorAttachment { + color_attachments: &[Some(wgpu::RenderPassColorAttachment { view, resolve_target: None, ops: wgpu::Operations { load: wgpu::LoadOp::Clear(clear_color), store: true, }, - }], + })], depth_stencil_attachment: None, }); rpass.set_pipeline(&self.pipeline); diff --git a/wgpu/examples/capture/main.rs b/wgpu/examples/capture/main.rs index 6e85a9a16a..610a431532 100644 --- a/wgpu/examples/capture/main.rs +++ b/wgpu/examples/capture/main.rs @@ -91,14 +91,14 @@ async fn create_red_image_with_dimensions( device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None }); encoder.begin_render_pass(&wgpu::RenderPassDescriptor { label: None, - color_attachments: &[wgpu::RenderPassColorAttachment { + color_attachments: &[Some(wgpu::RenderPassColorAttachment { view: &texture.create_view(&wgpu::TextureViewDescriptor::default()), resolve_target: None, ops: wgpu::Operations { load: wgpu::LoadOp::Clear(wgpu::Color::RED), store: true, }, - }], + })], depth_stencil_attachment: None, }); diff --git a/wgpu/examples/conservative-raster/main.rs b/wgpu/examples/conservative-raster/main.rs index 7617d508a3..7703c22466 100644 --- a/wgpu/examples/conservative-raster/main.rs +++ b/wgpu/examples/conservative-raster/main.rs @@ -104,7 +104,7 @@ impl framework::Example for Example { fragment: Some(wgpu::FragmentState { module: &shader_triangle_and_lines, entry_point: "fs_main_red", - targets: &[RENDER_TARGET_FORMAT.into()], + targets: &[Some(RENDER_TARGET_FORMAT.into())], }), primitive: wgpu::PrimitiveState { conservative: true, @@ -127,7 +127,7 @@ impl framework::Example for Example { fragment: Some(wgpu::FragmentState { module: &shader_triangle_and_lines, entry_point: "fs_main_blue", - targets: &[RENDER_TARGET_FORMAT.into()], + targets: &[Some(RENDER_TARGET_FORMAT.into())], }), primitive: wgpu::PrimitiveState::default(), depth_stencil: None, @@ -151,7 +151,7 @@ impl framework::Example for Example { fragment: Some(wgpu::FragmentState { module: &shader_triangle_and_lines, entry_point: "fs_main_white", - targets: &[config.format.into()], + targets: &[Some(config.format.into())], }), primitive: wgpu::PrimitiveState { polygon_mode: wgpu::PolygonMode::Line, @@ -212,7 +212,7 @@ impl framework::Example for Example { fragment: Some(wgpu::FragmentState { module: &shader, entry_point: "fs_main", - targets: &[config.format.into()], + targets: &[Some(config.format.into())], }), primitive: wgpu::PrimitiveState::default(), depth_stencil: None, @@ -266,14 +266,14 @@ impl framework::Example for Example { { let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { label: Some("low resolution"), - color_attachments: &[wgpu::RenderPassColorAttachment { + color_attachments: &[Some(wgpu::RenderPassColorAttachment { view: &self.low_res_target, resolve_target: None, ops: wgpu::Operations { load: wgpu::LoadOp::Clear(wgpu::Color::BLACK), store: true, }, - }], + })], depth_stencil_attachment: None, }); @@ -285,14 +285,14 @@ impl framework::Example for Example { { let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { label: Some("full resolution"), - color_attachments: &[wgpu::RenderPassColorAttachment { + color_attachments: &[Some(wgpu::RenderPassColorAttachment { view, resolve_target: None, ops: wgpu::Operations { load: wgpu::LoadOp::Clear(wgpu::Color::BLACK), store: true, }, - }], + })], depth_stencil_attachment: None, }); diff --git a/wgpu/examples/cube/main.rs b/wgpu/examples/cube/main.rs index c03e3f200c..dadf81b0ac 100644 --- a/wgpu/examples/cube/main.rs +++ b/wgpu/examples/cube/main.rs @@ -273,7 +273,7 @@ impl framework::Example for Example { fragment: Some(wgpu::FragmentState { module: &shader, entry_point: "fs_main", - targets: &[config.format.into()], + targets: &[Some(config.format.into())], }), primitive: wgpu::PrimitiveState { cull_mode: Some(wgpu::Face::Back), @@ -296,7 +296,7 @@ impl framework::Example for Example { fragment: Some(wgpu::FragmentState { module: &shader, entry_point: "fs_wire", - targets: &[wgpu::ColorTargetState { + targets: &[Some(wgpu::ColorTargetState { format: config.format, blend: Some(wgpu::BlendState { color: wgpu::BlendComponent { @@ -307,7 +307,7 @@ impl framework::Example for Example { alpha: wgpu::BlendComponent::REPLACE, }), write_mask: wgpu::ColorWrites::ALL, - }], + })], }), primitive: wgpu::PrimitiveState { front_face: wgpu::FrontFace::Ccw, @@ -364,7 +364,7 @@ impl framework::Example for Example { { let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { label: None, - color_attachments: &[wgpu::RenderPassColorAttachment { + color_attachments: &[Some(wgpu::RenderPassColorAttachment { view, resolve_target: None, ops: wgpu::Operations { @@ -376,7 +376,7 @@ impl framework::Example for Example { }), store: true, }, - }], + })], depth_stencil_attachment: None, }); rpass.push_debug_group("Prepare data for draw."); diff --git a/wgpu/examples/hello-triangle/main.rs b/wgpu/examples/hello-triangle/main.rs index 5fea4c4c0b..0de07f99ed 100644 --- a/wgpu/examples/hello-triangle/main.rs +++ b/wgpu/examples/hello-triangle/main.rs @@ -59,7 +59,7 @@ async fn run(event_loop: EventLoop<()>, window: Window) { fragment: Some(wgpu::FragmentState { module: &shader, entry_point: "fs_main", - targets: &[swapchain_format.into()], + targets: &[Some(swapchain_format.into())], }), primitive: wgpu::PrimitiveState::default(), depth_stencil: None, @@ -108,14 +108,14 @@ async fn run(event_loop: EventLoop<()>, window: Window) { { let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { label: None, - color_attachments: &[wgpu::RenderPassColorAttachment { + color_attachments: &[Some(wgpu::RenderPassColorAttachment { view: &view, resolve_target: None, ops: wgpu::Operations { load: wgpu::LoadOp::Clear(wgpu::Color::GREEN), store: true, }, - }], + })], depth_stencil_attachment: None, }); rpass.set_pipeline(&render_pipeline); diff --git a/wgpu/examples/hello-windows/main.rs b/wgpu/examples/hello-windows/main.rs index ac9bf24dbc..0d0e596110 100644 --- a/wgpu/examples/hello-windows/main.rs +++ b/wgpu/examples/hello-windows/main.rs @@ -123,14 +123,14 @@ async fn run(event_loop: EventLoop<()>, viewports: Vec<(Window, wgpu::Color)>) { { let _rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { label: None, - color_attachments: &[wgpu::RenderPassColorAttachment { + color_attachments: &[Some(wgpu::RenderPassColorAttachment { view: &view, resolve_target: None, ops: wgpu::Operations { load: wgpu::LoadOp::Clear(viewport.desc.background), store: true, }, - }], + })], depth_stencil_attachment: None, }); } diff --git a/wgpu/examples/mipmap/main.rs b/wgpu/examples/mipmap/main.rs index 634528e6e9..7e5e1a574c 100644 --- a/wgpu/examples/mipmap/main.rs +++ b/wgpu/examples/mipmap/main.rs @@ -94,7 +94,7 @@ impl Example { fragment: Some(wgpu::FragmentState { module: &shader, entry_point: "fs_main", - targets: &[TEXTURE_FORMAT.into()], + targets: &[Some(TEXTURE_FORMAT.into())], }), primitive: wgpu::PrimitiveState { topology: wgpu::PrimitiveTopology::TriangleList, @@ -154,14 +154,14 @@ impl Example { let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { label: None, - color_attachments: &[wgpu::RenderPassColorAttachment { + color_attachments: &[Some(wgpu::RenderPassColorAttachment { view: &views[target_mip], resolve_target: None, ops: wgpu::Operations { load: wgpu::LoadOp::Clear(wgpu::Color::WHITE), store: true, }, - }], + })], depth_stencil_attachment: None, }); if let Some(ref query_sets) = query_sets { @@ -288,7 +288,7 @@ impl framework::Example for Example { fragment: Some(wgpu::FragmentState { module: &shader, entry_point: "fs_main", - targets: &[config.format.into()], + targets: &[Some(config.format.into())], }), primitive: wgpu::PrimitiveState { topology: wgpu::PrimitiveTopology::TriangleStrip, @@ -461,14 +461,14 @@ impl framework::Example for Example { }; let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { label: None, - color_attachments: &[wgpu::RenderPassColorAttachment { + color_attachments: &[Some(wgpu::RenderPassColorAttachment { view, resolve_target: None, ops: wgpu::Operations { load: wgpu::LoadOp::Clear(clear_color), store: true, }, - }], + })], depth_stencil_attachment: None, }); rpass.set_pipeline(&self.draw_pipeline); diff --git a/wgpu/examples/msaa-line/main.rs b/wgpu/examples/msaa-line/main.rs index 8364286c1a..27d1e80798 100644 --- a/wgpu/examples/msaa-line/main.rs +++ b/wgpu/examples/msaa-line/main.rs @@ -60,7 +60,7 @@ impl Example { fragment: Some(wgpu::FragmentState { module: shader, entry_point: "fs_main", - targets: &[config.format.into()], + targets: &[Some(config.format.into())], }), primitive: wgpu::PrimitiveState { topology: wgpu::PrimitiveTopology::LineList, @@ -77,7 +77,7 @@ impl Example { let mut encoder = device.create_render_bundle_encoder(&wgpu::RenderBundleEncoderDescriptor { label: None, - color_formats: &[config.format], + color_formats: &[Some(config.format)], depth_stencil: None, sample_count, multiview: None, @@ -275,7 +275,7 @@ impl framework::Example for Example { encoder .begin_render_pass(&wgpu::RenderPassDescriptor { label: None, - color_attachments: &[rpass_color_attachment], + color_attachments: &[Some(rpass_color_attachment)], depth_stencil_attachment: None, }) .execute_bundles(iter::once(&self.bundle)); diff --git a/wgpu/examples/shadow/main.rs b/wgpu/examples/shadow/main.rs index bb8fec5acd..72106ebfd2 100644 --- a/wgpu/examples/shadow/main.rs +++ b/wgpu/examples/shadow/main.rs @@ -642,7 +642,7 @@ impl framework::Example for Example { } else { "fs_main_without_storage" }, - targets: &[sc_desc.format.into()], + targets: &[Some(sc_desc.format.into())], }), primitive: wgpu::PrimitiveState { front_face: wgpu::FrontFace::Ccw, @@ -799,7 +799,7 @@ impl framework::Example for Example { { let mut pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { label: None, - color_attachments: &[wgpu::RenderPassColorAttachment { + color_attachments: &[Some(wgpu::RenderPassColorAttachment { view, resolve_target: None, ops: wgpu::Operations { @@ -811,7 +811,7 @@ impl framework::Example for Example { }), store: true, }, - }], + })], depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment { view: &self.forward_depth, depth_ops: Some(wgpu::Operations { diff --git a/wgpu/examples/skybox/main.rs b/wgpu/examples/skybox/main.rs index a44cb70448..3b4a152c1d 100644 --- a/wgpu/examples/skybox/main.rs +++ b/wgpu/examples/skybox/main.rs @@ -206,7 +206,7 @@ impl framework::Example for Skybox { fragment: Some(wgpu::FragmentState { module: &shader, entry_point: "fs_sky", - targets: &[config.format.into()], + targets: &[Some(config.format.into())], }), primitive: wgpu::PrimitiveState { front_face: wgpu::FrontFace::Cw, @@ -237,7 +237,7 @@ impl framework::Example for Skybox { fragment: Some(wgpu::FragmentState { module: &shader, entry_point: "fs_entity", - targets: &[config.format.into()], + targets: &[Some(config.format.into())], }), primitive: wgpu::PrimitiveState { front_face: wgpu::FrontFace::Cw, @@ -420,7 +420,7 @@ impl framework::Example for Skybox { { let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { label: None, - color_attachments: &[wgpu::RenderPassColorAttachment { + color_attachments: &[Some(wgpu::RenderPassColorAttachment { view, resolve_target: None, ops: wgpu::Operations { @@ -432,7 +432,7 @@ impl framework::Example for Skybox { }), store: true, }, - }], + })], depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment { view: &self.depth_view, depth_ops: Some(wgpu::Operations { diff --git a/wgpu/examples/texture-arrays/main.rs b/wgpu/examples/texture-arrays/main.rs index d09c28b70b..687a0258f7 100644 --- a/wgpu/examples/texture-arrays/main.rs +++ b/wgpu/examples/texture-arrays/main.rs @@ -328,7 +328,7 @@ impl framework::Example for Example { fragment: Some(wgpu::FragmentState { module: fragment_shader_module, entry_point: fragment_entry_point, - targets: &[config.format.into()], + targets: &[Some(config.format.into())], }), primitive: wgpu::PrimitiveState { front_face: wgpu::FrontFace::Ccw, @@ -372,14 +372,14 @@ impl framework::Example for Example { let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { label: None, - color_attachments: &[wgpu::RenderPassColorAttachment { + color_attachments: &[Some(wgpu::RenderPassColorAttachment { view, resolve_target: None, ops: wgpu::Operations { load: wgpu::LoadOp::Clear(wgpu::Color::BLACK), store: true, }, - }], + })], depth_stencil_attachment: None, }); diff --git a/wgpu/examples/water/main.rs b/wgpu/examples/water/main.rs index 1b6085144b..5abe9d1843 100644 --- a/wgpu/examples/water/main.rs +++ b/wgpu/examples/water/main.rs @@ -530,7 +530,7 @@ impl framework::Example for Example { entry_point: "fs_main", // Describes how the colour will be interpolated // and assigned to the output attachment. - targets: &[wgpu::ColorTargetState { + targets: &[Some(wgpu::ColorTargetState { format: config.format, blend: Some(wgpu::BlendState { color: wgpu::BlendComponent { @@ -545,7 +545,7 @@ impl framework::Example for Example { }, }), write_mask: wgpu::ColorWrites::ALL, - }], + })], }), // How the triangles will be rasterized. This is more important // for the terrain because of the beneath-the water shot. @@ -591,7 +591,7 @@ impl framework::Example for Example { fragment: Some(wgpu::FragmentState { module: &terrain_module, entry_point: "fs_main", - targets: &[config.format.into()], + targets: &[Some(config.format.into())], }), primitive: wgpu::PrimitiveState { front_face: wgpu::FrontFace::Ccw, @@ -614,7 +614,7 @@ impl framework::Example for Example { let mut encoder = device.create_render_bundle_encoder(&wgpu::RenderBundleEncoderDescriptor { label: None, - color_formats: &[config.format], + color_formats: &[Some(config.format)], depth_stencil: Some(wgpu::RenderBundleDepthStencil { format: wgpu::TextureFormat::Depth32Float, depth_read_only: false, @@ -735,14 +735,14 @@ impl framework::Example for Example { { let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { label: None, - color_attachments: &[wgpu::RenderPassColorAttachment { + color_attachments: &[Some(wgpu::RenderPassColorAttachment { view: &self.reflect_view, resolve_target: None, ops: wgpu::Operations { load: wgpu::LoadOp::Clear(back_color), store: true, }, - }], + })], // We still need to use the depth buffer here // since the pipeline requires it. depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment { @@ -762,14 +762,14 @@ impl framework::Example for Example { { let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { label: None, - color_attachments: &[wgpu::RenderPassColorAttachment { + color_attachments: &[Some(wgpu::RenderPassColorAttachment { view, resolve_target: None, ops: wgpu::Operations { load: wgpu::LoadOp::Clear(back_color), store: true, }, - }], + })], depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment { view: &self.depth_buffer, depth_ops: Some(wgpu::Operations { @@ -789,14 +789,14 @@ impl framework::Example for Example { { let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { label: None, - color_attachments: &[wgpu::RenderPassColorAttachment { + color_attachments: &[Some(wgpu::RenderPassColorAttachment { view, resolve_target: None, ops: wgpu::Operations { load: wgpu::LoadOp::Load, store: true, }, - }], + })], depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment { view: &self.depth_buffer, depth_ops: None, diff --git a/wgpu/src/backend/direct.rs b/wgpu/src/backend/direct.rs index c9f3cea1b3..390bf6443c 100644 --- a/wgpu/src/backend/direct.rs +++ b/wgpu/src/backend/direct.rs @@ -2031,10 +2031,13 @@ impl crate::Context for Context { let colors = desc .color_attachments .iter() - .map(|ca| wgc::command::RenderPassColorAttachment { - view: ca.view.id, - resolve_target: ca.resolve_target.map(|rt| rt.id), - channel: map_pass_channel(Some(&ca.ops)), + .map(|ca| { + ca.as_ref() + .map(|at| wgc::command::RenderPassColorAttachment { + view: at.view.id, + resolve_target: at.resolve_target.map(|rt| rt.id), + channel: map_pass_channel(Some(&at.ops)), + }) }) .collect::>(); diff --git a/wgpu/src/lib.rs b/wgpu/src/lib.rs index dfa052c231..ffc732a95b 100644 --- a/wgpu/src/lib.rs +++ b/wgpu/src/lib.rs @@ -1413,7 +1413,7 @@ pub struct RenderPassDescriptor<'tex, 'desc> { /// Debug label of the render pass. This will show up in graphics debuggers for easy identification. pub label: Label<'desc>, /// The color attachments of the render pass. - pub color_attachments: &'desc [RenderPassColorAttachment<'tex>], + pub color_attachments: &'desc [Option>], /// The depth and stencil attachment of the render pass, if any. pub depth_stencil_attachment: Option>, } @@ -1465,7 +1465,7 @@ pub struct FragmentState<'a> { /// void with this name in the shader. pub entry_point: &'a str, /// The color state of the render targets. - pub targets: &'a [ColorTargetState], + pub targets: &'a [Option], } /// Describes a render (graphics) pipeline. @@ -1567,7 +1567,7 @@ pub struct RenderBundleEncoderDescriptor<'a> { pub label: Label<'a>, /// The formats of the color attachments that this render bundle is capable to rendering to. This /// must match the formats of the color attachments in the renderpass this render bundle is executed in. - pub color_formats: &'a [TextureFormat], + pub color_formats: &'a [Option], /// Information about the depth attachment that this render bundle is capable to rendering to. This /// must match the format of the depth attachments in the renderpass this render bundle is executed in. pub depth_stencil: Option, diff --git a/wgpu/tests/shader_primitive_index/mod.rs b/wgpu/tests/shader_primitive_index/mod.rs index 921aa112ac..6f067fb51b 100644 --- a/wgpu/tests/shader_primitive_index/mod.rs +++ b/wgpu/tests/shader_primitive_index/mod.rs @@ -152,11 +152,11 @@ fn pulling_common( fragment: Some(wgpu::FragmentState { entry_point: "fs_main", module: &shader, - targets: &[wgpu::ColorTargetState { + targets: &[Some(wgpu::ColorTargetState { format: wgpu::TextureFormat::Rgba8Unorm, blend: None, write_mask: wgpu::ColorWrites::ALL, - }], + })], }), multiview: None, }); @@ -184,14 +184,14 @@ fn pulling_common( .create_command_encoder(&wgpu::CommandEncoderDescriptor::default()); let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { - color_attachments: &[wgpu::RenderPassColorAttachment { + color_attachments: &[Some(wgpu::RenderPassColorAttachment { ops: wgpu::Operations { load: wgpu::LoadOp::Clear(wgpu::Color::WHITE), store: true, }, resolve_target: None, view: &color_view, - }], + })], depth_stencil_attachment: None, label: None, }); diff --git a/wgpu/tests/vertex_indices/mod.rs b/wgpu/tests/vertex_indices/mod.rs index d59c0a5199..d76b436784 100644 --- a/wgpu/tests/vertex_indices/mod.rs +++ b/wgpu/tests/vertex_indices/mod.rs @@ -71,11 +71,11 @@ fn pulling_common( fragment: Some(wgpu::FragmentState { entry_point: "fs_main", module: &shader, - targets: &[wgpu::ColorTargetState { + targets: &[Some(wgpu::ColorTargetState { format: wgpu::TextureFormat::Rgba8Unorm, blend: None, write_mask: wgpu::ColorWrites::ALL, - }], + })], }), multiview: None, }); @@ -106,11 +106,11 @@ fn pulling_common( .create_command_encoder(&wgpu::CommandEncoderDescriptor::default()); let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { - color_attachments: &[wgpu::RenderPassColorAttachment { + color_attachments: &[Some(wgpu::RenderPassColorAttachment { ops: wgpu::Operations::default(), resolve_target: None, view: &dummy, - }], + })], depth_stencil_attachment: None, label: None, }); diff --git a/wgpu/tests/zero_init_texture_after_discard.rs b/wgpu/tests/zero_init_texture_after_discard.rs index 2a7bd8786a..cce48c0fe8 100644 --- a/wgpu/tests/zero_init_texture_after_discard.rs +++ b/wgpu/tests/zero_init_texture_after_discard.rs @@ -14,14 +14,14 @@ fn discarding_color_target_resets_texture_init_state_check_visible_on_copy_after .create_command_encoder(&wgpu::CommandEncoderDescriptor::default()); encoder.begin_render_pass(&wgpu::RenderPassDescriptor { label: Some("Color Discard"), - color_attachments: &[wgpu::RenderPassColorAttachment { + color_attachments: &[Some(wgpu::RenderPassColorAttachment { view: &texture.create_view(&wgpu::TextureViewDescriptor::default()), resolve_target: None, ops: wgpu::Operations { load: wgpu::LoadOp::Load, store: false, // discard! }, - }], + })], depth_stencil_attachment: None, }); ctx.queue.submit([encoder.finish()]); @@ -49,14 +49,14 @@ fn discarding_color_target_resets_texture_init_state_check_visible_on_copy_in_sa .create_command_encoder(&wgpu::CommandEncoderDescriptor::default()); encoder.begin_render_pass(&wgpu::RenderPassDescriptor { label: Some("Color Discard"), - color_attachments: &[wgpu::RenderPassColorAttachment { + color_attachments: &[Some(wgpu::RenderPassColorAttachment { view: &texture.create_view(&wgpu::TextureViewDescriptor::default()), resolve_target: None, ops: wgpu::Operations { load: wgpu::LoadOp::Load, store: false, // discard! }, - }], + })], depth_stencil_attachment: None, }); copy_texture_to_buffer(&mut encoder, &texture, &readback_buffer); From 839544326aef496b57c7c51a07071b165b97ad33 Mon Sep 17 00:00:00 2001 From: Jinlei Li Date: Fri, 24 Jun 2022 20:50:03 +0800 Subject: [PATCH 2/6] vk: `Option`-al color attachments support --- wgpu-hal/src/vulkan/adapter.rs | 27 +++---- wgpu-hal/src/vulkan/command.rs | 72 +++++++++++-------- wgpu-hal/src/vulkan/device.rs | 128 ++++++++++++++++++--------------- wgpu-hal/src/vulkan/mod.rs | 2 +- 4 files changed, 125 insertions(+), 104 deletions(-) diff --git a/wgpu-hal/src/vulkan/adapter.rs b/wgpu-hal/src/vulkan/adapter.rs index 1d3d8f5e2c..1be86d8211 100644 --- a/wgpu-hal/src/vulkan/adapter.rs +++ b/wgpu-hal/src/vulkan/adapter.rs @@ -1059,19 +1059,18 @@ impl super::Instance { || phd_capabilities.supports_extension(vk::KhrMaintenance1Fn::name()), imageless_framebuffers: match phd_features.vulkan_1_2 { Some(features) => features.imageless_framebuffer == vk::TRUE, - None => match phd_features.imageless_framebuffer { - Some(ref ext) => ext.imageless_framebuffer != 0, - None => false, - }, + None => phd_features + .imageless_framebuffer + .map_or(false, |ext| ext.imageless_framebuffer != 0), }, + // imageless_framebuffers: false, image_view_usage: phd_capabilities.properties.api_version >= vk::API_VERSION_1_1 || phd_capabilities.supports_extension(vk::KhrMaintenance2Fn::name()), timeline_semaphores: match phd_features.vulkan_1_2 { Some(features) => features.timeline_semaphore == vk::TRUE, - None => match phd_features.timeline_semaphore { - Some(ref ext) => ext.timeline_semaphore != 0, - None => false, - }, + None => phd_features + .timeline_semaphore + .map_or(false, |ext| ext.timeline_semaphore != 0), }, texture_d24: unsafe { self.shared @@ -1093,13 +1092,15 @@ impl super::Instance { robust_buffer_access: phd_features.core.robust_buffer_access != 0, robust_image_access: match phd_features.robustness2 { Some(ref f) => f.robust_image_access2 != 0, - None => match phd_features.image_robustness { - Some(ref f) => f.robust_image_access != 0, - None => false, - }, + None => phd_features + .image_robustness + .map_or(false, |ext| ext.robust_image_access != 0), }, }; - + println!( + "caps.imageless_framebuffers {}", + private_caps.imageless_framebuffers + ); let capabilities = crate::Capabilities { limits: phd_capabilities.to_wgpu_limits(&phd_features), alignments: phd_capabilities.to_hal_alignments(), diff --git a/wgpu-hal/src/vulkan/command.rs b/wgpu-hal/src/vulkan/command.rs index dbcb1123ee..343fd1e7f0 100644 --- a/wgpu-hal/src/vulkan/command.rs +++ b/wgpu-hal/src/vulkan/command.rs @@ -362,31 +362,37 @@ impl crate::CommandEncoder for super::CommandEncoder { let caps = &self.device.private_caps; for cat in desc.color_attachments { - vk_clear_values.push(vk::ClearValue { - color: cat.make_vk_clear_color(), - }); - vk_image_views.push(cat.target.view.raw); - rp_key.colors.push(super::ColorAttachmentKey { - base: cat.target.make_attachment_key(cat.ops, caps), - resolve: cat - .resolve_target - .as_ref() - .map(|target| target.make_attachment_key(crate::AttachmentOps::STORE, caps)), - }); - fb_key.attachments.push(cat.target.view.attachment.clone()); - if let Some(ref at) = cat.resolve_target { - vk_clear_values.push(mem::zeroed()); - vk_image_views.push(at.view.raw); - fb_key.attachments.push(at.view.attachment.clone()); - } + if let Some(cat) = cat.as_ref() { + vk_clear_values.push(vk::ClearValue { + color: cat.make_vk_clear_color(), + }); + vk_image_views.push(cat.target.view.raw); + let color = super::ColorAttachmentKey { + base: cat.target.make_attachment_key(cat.ops, caps), + resolve: cat.resolve_target.as_ref().map(|target| { + target.make_attachment_key(crate::AttachmentOps::STORE, caps) + }), + }; + + rp_key.colors.push(Some(color)); + fb_key.attachments.push(cat.target.view.attachment.clone()); + if let Some(ref at) = cat.resolve_target { + vk_clear_values.push(mem::zeroed()); + vk_image_views.push(at.view.raw); + println!("fb_key.attachments: {:?}", &at.view.attachment.raw); + fb_key.attachments.push(at.view.attachment.clone()); + } - // Assert this attachment is valid for the detected multiview, as a sanity check - // The driver crash for this is really bad on AMD, so the check is worth it - if let Some(multiview) = desc.multiview { - assert_eq!(cat.target.view.layers, multiview); - if let Some(ref resolve_target) = cat.resolve_target { - assert_eq!(resolve_target.view.layers, multiview); + // Assert this attachment is valid for the detected multiview, as a sanity check + // The driver crash for this is really bad on AMD, so the check is worth it + if let Some(multiview) = desc.multiview { + assert_eq!(cat.target.view.layers, multiview); + if let Some(ref resolve_target) = cat.resolve_target { + assert_eq!(resolve_target.view.layers, multiview); + } } + } else { + rp_key.colors.push(None); } } if let Some(ref ds) = desc.depth_stencil_attachment { @@ -431,25 +437,29 @@ impl crate::CommandEncoder for super::CommandEncoder { min_depth: 0.0, max_depth: 1.0, }]; - let vk_scissors = [render_area]; let raw_pass = self.device.make_render_pass(rp_key).unwrap(); - let raw_framebuffer = self .device .make_framebuffer(fb_key, raw_pass, desc.label) .unwrap(); - let mut vk_attachment_info = vk::RenderPassAttachmentBeginInfo::builder() - .attachments(&vk_image_views) - .build(); let mut vk_info = vk::RenderPassBeginInfo::builder() .render_pass(raw_pass) .render_area(render_area) .clear_values(&vk_clear_values) .framebuffer(raw_framebuffer); - if caps.imageless_framebuffers { - vk_info = vk_info.push_next(&mut vk_attachment_info); + let mut vk_attachment_info = if caps.imageless_framebuffers { + Some( + vk::RenderPassAttachmentBeginInfo::builder() + .attachments(&vk_image_views) + .build(), + ) + } else { + None + }; + if let Some(attachment_info) = vk_attachment_info.as_mut() { + vk_info = vk_info.push_next(attachment_info); } if let Some(label) = desc.label { @@ -462,7 +472,7 @@ impl crate::CommandEncoder for super::CommandEncoder { .cmd_set_viewport(self.active, 0, &vk_viewports); self.device .raw - .cmd_set_scissor(self.active, 0, &vk_scissors); + .cmd_set_scissor(self.active, 0, &[render_area]); self.device .raw .cmd_begin_render_pass(self.active, &vk_info, vk::SubpassContents::INLINE); diff --git a/wgpu-hal/src/vulkan/device.rs b/wgpu-hal/src/vulkan/device.rs index 6d3b868c7b..0a15e7b07b 100644 --- a/wgpu-hal/src/vulkan/device.rs +++ b/wgpu-hal/src/vulkan/device.rs @@ -71,46 +71,49 @@ impl super::DeviceShared { let mut resolve_refs = Vec::with_capacity(color_refs.capacity()); let mut ds_ref = None; let samples = vk::SampleCountFlags::from_raw(e.key().sample_count); - + let unused = vk::AttachmentReference { + attachment: vk::ATTACHMENT_UNUSED, + layout: vk::ImageLayout::UNDEFINED, + }; for cat in e.key().colors.iter() { - color_refs.push(vk::AttachmentReference { - attachment: vk_attachments.len() as u32, - layout: cat.base.layout, - }); - vk_attachments.push({ - let (load_op, store_op) = conv::map_attachment_ops(cat.base.ops); - vk::AttachmentDescription::builder() - .format(cat.base.format) - .samples(samples) - .load_op(load_op) - .store_op(store_op) - .initial_layout(cat.base.layout) - .final_layout(cat.base.layout) - .build() - }); - let at_ref = if let Some(ref rat) = cat.resolve { - let at_ref = vk::AttachmentReference { + if let Some(cat) = cat.as_ref() { + color_refs.push(vk::AttachmentReference { attachment: vk_attachments.len() as u32, - layout: rat.layout, + layout: cat.base.layout, + }); + vk_attachments.push({ + let (load_op, store_op) = conv::map_attachment_ops(cat.base.ops); + vk::AttachmentDescription::builder() + .format(cat.base.format) + .samples(samples) + .load_op(load_op) + .store_op(store_op) + .initial_layout(cat.base.layout) + .final_layout(cat.base.layout) + .build() + }); + if let Some(ref rat) = cat.resolve { + resolve_refs.push(vk::AttachmentReference { + attachment: vk_attachments.len() as u32, + layout: rat.layout, + }); + let (load_op, store_op) = conv::map_attachment_ops(rat.ops); + let vk_attachment = vk::AttachmentDescription::builder() + .format(rat.format) + .samples(vk::SampleCountFlags::TYPE_1) + .load_op(load_op) + .store_op(store_op) + .initial_layout(rat.layout) + .final_layout(rat.layout) + .build(); + vk_attachments.push(vk_attachment); + } else { + resolve_refs.push(unused.clone()); }; - let (load_op, store_op) = conv::map_attachment_ops(rat.ops); - let vk_attachment = vk::AttachmentDescription::builder() - .format(rat.format) - .samples(vk::SampleCountFlags::TYPE_1) - .load_op(load_op) - .store_op(store_op) - .initial_layout(rat.layout) - .final_layout(rat.layout) - .build(); - vk_attachments.push(vk_attachment); - at_ref } else { - vk::AttachmentReference { - attachment: vk::ATTACHMENT_UNUSED, - layout: vk::ImageLayout::UNDEFINED, - } - }; - resolve_refs.push(at_ref); + color_refs.push(unused.clone()); + resolve_refs.push(unused.clone()); + } } if let Some(ref ds) = e.key().depth_stencil { @@ -1574,30 +1577,37 @@ impl crate::Device for super::Device { let mut vk_attachments = Vec::with_capacity(desc.color_targets.len()); for cat in desc.color_targets { - let vk_format = self.shared.private_caps.map_texture_format(cat.format); - compatible_rp_key.colors.push(super::ColorAttachmentKey { - base: super::AttachmentKey::compatible( - vk_format, - vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL, - ), - resolve: None, - }); - - let mut vk_attachment = vk::PipelineColorBlendAttachmentState::builder() - .color_write_mask(vk::ColorComponentFlags::from_raw(cat.write_mask.bits())); - if let Some(ref blend) = cat.blend { - let (color_op, color_src, color_dst) = conv::map_blend_component(&blend.color); - let (alpha_op, alpha_src, alpha_dst) = conv::map_blend_component(&blend.alpha); - vk_attachment = vk_attachment - .blend_enable(true) - .color_blend_op(color_op) - .src_color_blend_factor(color_src) - .dst_color_blend_factor(color_dst) - .alpha_blend_op(alpha_op) - .src_alpha_blend_factor(alpha_src) - .dst_alpha_blend_factor(alpha_dst); + if let Some(cat) = cat.as_ref() { + let vk_format = self.shared.private_caps.map_texture_format(cat.format); + compatible_rp_key + .colors + .push(Some(super::ColorAttachmentKey { + base: super::AttachmentKey::compatible( + vk_format, + vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL, + ), + resolve: None, + })); + + let mut vk_attachment = vk::PipelineColorBlendAttachmentState::builder() + .color_write_mask(vk::ColorComponentFlags::from_raw(cat.write_mask.bits())); + if let Some(ref blend) = cat.blend { + let (color_op, color_src, color_dst) = conv::map_blend_component(&blend.color); + let (alpha_op, alpha_src, alpha_dst) = conv::map_blend_component(&blend.alpha); + vk_attachment = vk_attachment + .blend_enable(true) + .color_blend_op(color_op) + .src_color_blend_factor(color_src) + .dst_color_blend_factor(color_dst) + .alpha_blend_op(alpha_op) + .src_alpha_blend_factor(alpha_src) + .dst_alpha_blend_factor(alpha_dst); + } + vk_attachments.push(vk_attachment.build()); + } else { + vk_attachments.push(vk::PipelineColorBlendAttachmentState::default()); + compatible_rp_key.colors.push(None); } - vk_attachments.push(vk_attachment.build()); } let vk_color_blend = vk::PipelineColorBlendStateCreateInfo::builder() diff --git a/wgpu-hal/src/vulkan/mod.rs b/wgpu-hal/src/vulkan/mod.rs index 29ca466a6f..94d7598995 100644 --- a/wgpu-hal/src/vulkan/mod.rs +++ b/wgpu-hal/src/vulkan/mod.rs @@ -212,7 +212,7 @@ struct DepthStencilAttachmentKey { #[derive(Clone, Eq, Default, Hash, PartialEq)] struct RenderPassKey { - colors: ArrayVec, + colors: ArrayVec, { crate::MAX_COLOR_ATTACHMENTS }>, depth_stencil: Option, sample_count: u32, multiview: Option, From 4c2661c59638d53ee679e83e0d27b52fa718d234 Mon Sep 17 00:00:00 2001 From: Jinlei Li Date: Sat, 25 Jun 2022 16:50:37 +0800 Subject: [PATCH 3/6] dx12: sparse color_attachments support --- wgpu-hal/src/dx12/command.rs | 59 +++++++++++++++++++++++++----------- wgpu-hal/src/dx12/conv.rs | 26 ++++++++-------- wgpu-hal/src/dx12/device.rs | 15 ++++++--- wgpu-hal/src/dx12/mod.rs | 3 +- 4 files changed, 69 insertions(+), 34 deletions(-) diff --git a/wgpu-hal/src/dx12/command.rs b/wgpu-hal/src/dx12/command.rs index 8d1c5e1735..20f26fc78d 100644 --- a/wgpu-hal/src/dx12/command.rs +++ b/wgpu-hal/src/dx12/command.rs @@ -579,10 +579,32 @@ impl crate::CommandEncoder for super::CommandEncoder { unsafe fn begin_render_pass(&mut self, desc: &crate::RenderPassDescriptor) { self.begin_pass(super::PassKind::Render, desc.label); - let mut color_views = [native::CpuDescriptor { ptr: 0 }; crate::MAX_COLOR_ATTACHMENTS]; + let mut null_rtv_handle: Option = None; for (rtv, cat) in color_views.iter_mut().zip(desc.color_attachments.iter()) { - *rtv = cat.target.view.handle_rtv.unwrap().raw; + if let Some(cat) = cat.as_ref() { + *rtv = cat.target.view.handle_rtv.unwrap().raw; + } else { + if null_rtv_handle.is_none() { + let handle = self.rtv_pool.lock().alloc_handle(); + // A null pResource is used to initialize a null descriptor, + // which guarantees D3D11-like null binding behavior (reading 0s, writes are discarded) + self.device.create_render_target_view( + native::WeakPtr::null(), + &native::RenderTargetViewDesc::texture_2d( + winapi::shared::dxgiformat::DXGI_FORMAT_R8G8B8A8_UNORM, + 0, + 0, + ), + handle.raw, + ); + null_rtv_handle = Some(handle); + } + *rtv = null_rtv_handle.unwrap().raw; + } + } + if let Some(handle) = null_rtv_handle { + self.rtv_pool.lock().free_handle(handle); } let ds_view = match desc.depth_stencil_attachment { None => ptr::null(), @@ -605,23 +627,26 @@ impl crate::CommandEncoder for super::CommandEncoder { self.pass.resolves.clear(); for (rtv, cat) in color_views.iter().zip(desc.color_attachments.iter()) { - if !cat.ops.contains(crate::AttachmentOps::LOAD) { - let value = [ - cat.clear_value.r as f32, - cat.clear_value.g as f32, - cat.clear_value.b as f32, - cat.clear_value.a as f32, - ]; - list.clear_render_target_view(*rtv, value, &[]); - } - if let Some(ref target) = cat.resolve_target { - self.pass.resolves.push(super::PassResolve { - src: cat.target.view.target_base, - dst: target.view.target_base, - format: target.view.raw_format, - }); + if let Some(cat) = cat.as_ref() { + if !cat.ops.contains(crate::AttachmentOps::LOAD) { + let value = [ + cat.clear_value.r as f32, + cat.clear_value.g as f32, + cat.clear_value.b as f32, + cat.clear_value.a as f32, + ]; + list.clear_render_target_view(*rtv, value, &[]); + } + if let Some(ref target) = cat.resolve_target { + self.pass.resolves.push(super::PassResolve { + src: cat.target.view.target_base, + dst: target.view.target_base, + format: target.view.raw_format, + }); + } } } + if let Some(ref ds) = desc.depth_stencil_attachment { let mut flags = native::ClearFlags::empty(); let aspects = ds.target.view.format_aspects; diff --git a/wgpu-hal/src/dx12/conv.rs b/wgpu-hal/src/dx12/conv.rs index 8dfd40c92b..4114fba002 100644 --- a/wgpu-hal/src/dx12/conv.rs +++ b/wgpu-hal/src/dx12/conv.rs @@ -267,7 +267,7 @@ fn map_blend_component( } pub fn map_render_targets( - color_targets: &[wgt::ColorTargetState], + color_targets: &[Option], ) -> [d3d12::D3D12_RENDER_TARGET_BLEND_DESC; d3d12::D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT as usize] { let dummy_target = d3d12::D3D12_RENDER_TARGET_BLEND_DESC { @@ -285,17 +285,19 @@ pub fn map_render_targets( let mut raw_targets = [dummy_target; d3d12::D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT as usize]; for (raw, ct) in raw_targets.iter_mut().zip(color_targets.iter()) { - raw.RenderTargetWriteMask = ct.write_mask.bits() as u8; - if let Some(ref blend) = ct.blend { - let (color_op, color_src, color_dst) = map_blend_component(&blend.color, false); - let (alpha_op, alpha_src, alpha_dst) = map_blend_component(&blend.alpha, true); - raw.BlendEnable = 1; - raw.BlendOp = color_op; - raw.SrcBlend = color_src; - raw.DestBlend = color_dst; - raw.BlendOpAlpha = alpha_op; - raw.SrcBlendAlpha = alpha_src; - raw.DestBlendAlpha = alpha_dst; + if let Some(ct) = ct.as_ref() { + raw.RenderTargetWriteMask = ct.write_mask.bits() as u8; + if let Some(ref blend) = ct.blend { + let (color_op, color_src, color_dst) = map_blend_component(&blend.color, false); + let (alpha_op, alpha_src, alpha_dst) = map_blend_component(&blend.alpha, true); + raw.BlendEnable = 1; + raw.BlendOp = color_op; + raw.SrcBlend = color_src; + raw.DestBlend = color_dst; + raw.BlendOpAlpha = alpha_op; + raw.SrcBlendAlpha = alpha_src; + raw.DestBlendAlpha = alpha_dst; + } } } diff --git a/wgpu-hal/src/dx12/device.rs b/wgpu-hal/src/dx12/device.rs index c25f58c767..dd66c1ff78 100644 --- a/wgpu-hal/src/dx12/device.rs +++ b/wgpu-hal/src/dx12/device.rs @@ -134,10 +134,10 @@ impl super::Device { }, private_caps, shared: Arc::new(shared), - rtv_pool: Mutex::new(descriptor::CpuPool::new( + rtv_pool: Arc::new(Mutex::new(descriptor::CpuPool::new( raw, native::DescriptorHeapType::Rtv, - )), + ))), dsv_pool: Mutex::new(descriptor::CpuPool::new( raw, native::DescriptorHeapType::Dsv, @@ -306,7 +306,11 @@ impl super::Device { impl crate::Device for super::Device { unsafe fn exit(self, queue: super::Queue) { - self.rtv_pool.into_inner().destroy(); + Arc::try_unwrap(self.rtv_pool) + .ok() + .unwrap() + .into_inner() + .destroy(); self.dsv_pool.into_inner().destroy(); self.srv_uav_pool.into_inner().destroy(); self.sampler_pool.into_inner().destroy(); @@ -658,6 +662,7 @@ impl crate::Device for super::Device { allocator, device: self.raw, shared: Arc::clone(&self.shared), + rtv_pool: Arc::clone(&self.rtv_pool), list: None, free_lists: Vec::new(), pass: super::PassState::new(), @@ -1283,7 +1288,9 @@ impl crate::Device for super::Device { let mut rtv_formats = [dxgiformat::DXGI_FORMAT_UNKNOWN; d3d12::D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT as usize]; for (rtv_format, ct) in rtv_formats.iter_mut().zip(desc.color_targets) { - *rtv_format = auxil::dxgi::conv::map_texture_format(ct.format); + if let Some(ct) = ct.as_ref() { + *rtv_format = auxil::dxgi::conv::map_texture_format(ct.format); + } } let bias = desc diff --git a/wgpu-hal/src/dx12/mod.rs b/wgpu-hal/src/dx12/mod.rs index e5358cf05d..591ed16b9b 100644 --- a/wgpu-hal/src/dx12/mod.rs +++ b/wgpu-hal/src/dx12/mod.rs @@ -221,7 +221,7 @@ pub struct Device { private_caps: PrivateCapabilities, shared: Arc, // CPU only pools - rtv_pool: Mutex, + rtv_pool: Arc>, dsv_pool: Mutex, srv_uav_pool: Mutex, sampler_pool: Mutex, @@ -329,6 +329,7 @@ pub struct CommandEncoder { allocator: native::CommandAllocator, device: native::Device, shared: Arc, + rtv_pool: Arc>, list: Option, free_lists: Vec, pass: PassState, From 250078355662f37984c26c01fcdecf5b1a426add Mon Sep 17 00:00:00 2001 From: Jinlei Li Date: Sat, 25 Jun 2022 17:49:30 +0800 Subject: [PATCH 4/6] Only non-hole attachments is supported on wasm target and gl backend --- wgpu-hal/src/gles/command.rs | 36 ++++++++++++-------- wgpu-hal/src/gles/device.rs | 2 +- wgpu/src/backend/web.rs | 66 +++++++++++++++++++++--------------- 3 files changed, 62 insertions(+), 42 deletions(-) diff --git a/wgpu-hal/src/gles/command.rs b/wgpu-hal/src/gles/command.rs index 8916fac681..04958610e8 100644 --- a/wgpu-hal/src/gles/command.rs +++ b/wgpu-hal/src/gles/command.rs @@ -429,7 +429,8 @@ impl crate::CommandEncoder for super::CommandEncoder { match desc .color_attachments .first() - .map(|at| &at.target.view.inner) + .filter(|at| at.is_some()) + .map(|at| &at.as_ref().unwrap().target.view.inner) { // default framebuffer (provided externally) Some(&super::TextureInner::DefaultRenderbuffer) => { @@ -444,18 +445,20 @@ impl crate::CommandEncoder for super::CommandEncoder { .push(C::ResetFramebuffer { is_default: false }); for (i, cat) in desc.color_attachments.iter().enumerate() { - let attachment = glow::COLOR_ATTACHMENT0 + i as u32; - self.cmd_buffer.commands.push(C::BindAttachment { - attachment, - view: cat.target.view.clone(), - }); - if let Some(ref rat) = cat.resolve_target { - self.state - .resolve_attachments - .push((attachment, rat.view.clone())); - } - if !cat.ops.contains(crate::AttachmentOps::STORE) { - self.state.invalidate_attachments.push(attachment); + if let Some(cat) = cat.as_ref() { + let attachment = glow::COLOR_ATTACHMENT0 + i as u32; + self.cmd_buffer.commands.push(C::BindAttachment { + attachment, + view: cat.target.view.clone(), + }); + if let Some(ref rat) = cat.resolve_target { + self.state + .resolve_attachments + .push((attachment, rat.view.clone())); + } + if !cat.ops.contains(crate::AttachmentOps::STORE) { + self.state.invalidate_attachments.push(attachment); + } } } if let Some(ref dsat) = desc.depth_stencil_attachment { @@ -505,7 +508,12 @@ impl crate::CommandEncoder for super::CommandEncoder { }); // issue the clears - for (i, cat) in desc.color_attachments.iter().enumerate() { + for (i, cat) in desc + .color_attachments + .iter() + .filter_map(|at| at.as_ref()) + .enumerate() + { if !cat.ops.contains(crate::AttachmentOps::LOAD) { let c = &cat.clear_value; self.cmd_buffer diff --git a/wgpu-hal/src/gles/device.rs b/wgpu-hal/src/gles/device.rs index a52e6b5a66..c554d38a1f 100644 --- a/wgpu-hal/src/gles/device.rs +++ b/wgpu-hal/src/gles/device.rs @@ -1002,7 +1002,7 @@ impl crate::Device for super::Device { let color_targets = { let mut targets = Vec::new(); - for ct in desc.color_targets.iter() { + for ct in desc.color_targets.iter().filter_map(|at| at.as_ref()) { targets.push(super::ColorTargetDesc { mask: ct.write_mask, blend: ct.blend.as_ref().map(conv::map_blend), diff --git a/wgpu/src/backend/web.rs b/wgpu/src/backend/web.rs index f4f40ee412..467c5d0e2c 100644 --- a/wgpu/src/backend/web.rs +++ b/wgpu/src/backend/web.rs @@ -1556,17 +1556,20 @@ impl crate::Context for Context { let targets = frag .targets .iter() - .map(|target| { - let mapped_format = map_texture_format(target.format); - let mut mapped_color_state = web_sys::GpuColorTargetState::new(mapped_format); - if let Some(ref bs) = target.blend { - let alpha = map_blend_component(&bs.alpha); - let color = map_blend_component(&bs.color); - let mapped_blend_state = web_sys::GpuBlendState::new(&alpha, &color); - mapped_color_state.blend(&mapped_blend_state); - } - mapped_color_state.write_mask(target.write_mask.bits()); - mapped_color_state + .filter_map(|t| { + t.as_ref().map(|target| { + let mapped_format = map_texture_format(target.format); + let mut mapped_color_state = + web_sys::GpuColorTargetState::new(mapped_format); + if let Some(ref bs) = target.blend { + let alpha = map_blend_component(&bs.alpha); + let color = map_blend_component(&bs.color); + let mapped_blend_state = web_sys::GpuBlendState::new(&alpha, &color); + mapped_color_state.blend(&mapped_blend_state); + } + mapped_color_state.write_mask(target.write_mask.bits()); + mapped_color_state + }) }) .collect::(); let mapped_fragment_desc = @@ -1690,7 +1693,10 @@ impl crate::Context for Context { let mapped_color_formats = desc .color_formats .iter() - .map(|cf| wasm_bindgen::JsValue::from(map_texture_format(*cf))) + .filter_map(|cf| { + cf.as_ref() + .map(|format| wasm_bindgen::JsValue::from(map_texture_format(*format))) + }) .collect::(); let mut mapped_desc = web_sys::GpuRenderBundleEncoderDescriptor::new(&mapped_color_formats); if let Some(label) = desc.label { @@ -1985,25 +1991,31 @@ impl crate::Context for Context { let mapped_color_attachments = desc .color_attachments .iter() - .map(|ca| { - let load_value = match ca.ops.load { - crate::LoadOp::Clear(color) => wasm_bindgen::JsValue::from(map_color(color)), - crate::LoadOp::Load => wasm_bindgen::JsValue::from(web_sys::GpuLoadOp::Load), - }; + .filter_map(|attachment| { + attachment.as_ref().map(|ca| { + let load_value = match ca.ops.load { + crate::LoadOp::Clear(color) => { + wasm_bindgen::JsValue::from(map_color(color)) + } + crate::LoadOp::Load => { + wasm_bindgen::JsValue::from(web_sys::GpuLoadOp::Load) + } + }; - let mut mapped_color_attachment = web_sys::GpuRenderPassColorAttachment::new( - &load_value, - map_store_op(ca.ops.store), - &ca.view.id.0, - ); + let mut mapped_color_attachment = web_sys::GpuRenderPassColorAttachment::new( + &load_value, + map_store_op(ca.ops.store), + &ca.view.id.0, + ); - if let Some(rt) = ca.resolve_target { - mapped_color_attachment.resolve_target(&rt.id.0); - } + if let Some(rt) = ca.resolve_target { + mapped_color_attachment.resolve_target(&rt.id.0); + } - mapped_color_attachment.store_op(map_store_op(ca.ops.store)); + mapped_color_attachment.store_op(map_store_op(ca.ops.store)); - mapped_color_attachment + mapped_color_attachment + }) }) .collect::(); From f07a8808ed43d10c651538e35b4fdc672d291f8c Mon Sep 17 00:00:00 2001 From: Jinlei Li Date: Sat, 25 Jun 2022 20:06:21 +0800 Subject: [PATCH 5/6] deno_webgpu: `Option`-al color attachments support --- deno_webgpu/src/bundle.rs | 2 +- deno_webgpu/src/command_encoder.rs | 53 ++++++++++--------- deno_webgpu/src/pipeline.rs | 2 +- player/tests/data/quad.ron | 8 +-- .../data/zero-init-texture-rendertarget.ron | 4 +- wgpu-core/src/device/mod.rs | 39 ++++++-------- wgpu-hal/examples/raw-gles.rs | 4 +- wgpu-hal/src/metal/command.rs | 2 +- wgpu-hal/src/vulkan/device.rs | 6 +-- 9 files changed, 59 insertions(+), 61 deletions(-) diff --git a/deno_webgpu/src/bundle.rs b/deno_webgpu/src/bundle.rs index d75d0c5710..b1c5b05617 100644 --- a/deno_webgpu/src/bundle.rs +++ b/deno_webgpu/src/bundle.rs @@ -32,7 +32,7 @@ impl Resource for WebGpuRenderBundle { pub struct CreateRenderBundleEncoderArgs { device_rid: ResourceId, label: Option, - color_formats: Vec, + color_formats: Vec>, depth_stencil_format: Option, sample_count: u32, depth_read_only: bool, diff --git a/deno_webgpu/src/command_encoder.rs b/deno_webgpu/src/command_encoder.rs index 3064f5c297..75dfbfa25e 100644 --- a/deno_webgpu/src/command_encoder.rs +++ b/deno_webgpu/src/command_encoder.rs @@ -78,7 +78,7 @@ pub fn op_webgpu_command_encoder_begin_render_pass( state: &mut OpState, command_encoder_rid: ResourceId, label: Option, - color_attachments: Vec, + color_attachments: Vec>, depth_stencil_attachment: Option, _occlusion_query_set: Option, // not yet implemented ) -> Result { @@ -89,30 +89,35 @@ pub fn op_webgpu_command_encoder_begin_render_pass( let color_attachments = color_attachments .into_iter() .map(|color_attachment| { - let texture_view_resource = state - .resource_table - .get::(color_attachment.view)?; - - let resolve_target = color_attachment - .resolve_target - .map(|rid| { - state - .resource_table - .get::(rid) + let rp_at = if let Some(at) = color_attachment.as_ref() { + let texture_view_resource = state + .resource_table + .get::(at.view)?; + + let resolve_target = at + .resolve_target + .map(|rid| { + state + .resource_table + .get::(rid) + }) + .transpose()? + .map(|texture| texture.0); + + Some(wgpu_core::command::RenderPassColorAttachment { + view: texture_view_resource.0, + resolve_target, + channel: wgpu_core::command::PassChannel { + load_op: at.load_op, + store_op: at.store_op, + clear_value: at.clear_value.unwrap_or_default(), + read_only: false, + }, }) - .transpose()? - .map(|texture| texture.0); - - Ok(wgpu_core::command::RenderPassColorAttachment { - view: texture_view_resource.0, - resolve_target, - channel: wgpu_core::command::PassChannel { - load_op: color_attachment.load_op, - store_op: color_attachment.store_op, - clear_value: color_attachment.clear_value.unwrap_or_default(), - read_only: false, - }, - }) + } else { + None + }; + Ok(rp_at) }) .collect::, AnyError>>()?; diff --git a/deno_webgpu/src/pipeline.rs b/deno_webgpu/src/pipeline.rs index 63958ac7ed..9b135f5d44 100644 --- a/deno_webgpu/src/pipeline.rs +++ b/deno_webgpu/src/pipeline.rs @@ -260,7 +260,7 @@ impl From for wgpu_types::MultisampleState { #[derive(Deserialize)] #[serde(rename_all = "camelCase")] struct GpuFragmentState { - targets: Vec, + targets: Vec>, module: u32, entry_point: String, // TODO(lucacasonato): constants diff --git a/player/tests/data/quad.ron b/player/tests/data/quad.ron index b6153b2f62..11b6378300 100644 --- a/player/tests/data/quad.ron +++ b/player/tests/data/quad.ron @@ -66,9 +66,9 @@ entry_point: "fs_main", ), targets: [ - ( + Some(( format: rgba8unorm, - ), + )), ], )), ), @@ -90,7 +90,7 @@ push_constant_data: [], ), target_colors: [ - ( + Some(( view: Id(0, 1, Empty), resolve_target: None, channel: ( @@ -104,7 +104,7 @@ ), read_only: false, ), - ), + )), ], target_depth_stencil: None, ), diff --git a/player/tests/data/zero-init-texture-rendertarget.ron b/player/tests/data/zero-init-texture-rendertarget.ron index 836198d790..4239acc6aa 100644 --- a/player/tests/data/zero-init-texture-rendertarget.ron +++ b/player/tests/data/zero-init-texture-rendertarget.ron @@ -46,7 +46,7 @@ push_constant_data: [], ), target_colors: [ - ( + Some(( view: Id(0, 1, Empty), resolve_target: None, channel: ( @@ -57,7 +57,7 @@ ), read_only: false, ), - ), + )), ], target_depth_stencil: None, ), diff --git a/wgpu-core/src/device/mod.rs b/wgpu-core/src/device/mod.rs index 8043b3da96..74f37b2007 100644 --- a/wgpu-core/src/device/mod.rs +++ b/wgpu-core/src/device/mod.rs @@ -2760,30 +2760,23 @@ impl Device { if validated_stages.contains(wgt::ShaderStages::FRAGMENT) { for (i, output) in io.iter() { - match color_targets.get(*i as usize) { - Some(state) => { - let format = if let Some(st) = state.as_ref() { - st.format - } else { - return Err( - pipeline::CreateRenderPipelineError::InvalidFragmentOutputLocation( - *i, - ), - ); - }; - validation::check_texture_format(format, &output.ty).map_err( - |pipeline| { - pipeline::CreateRenderPipelineError::ColorState( - *i as u8, - pipeline::ColorStateError::IncompatibleFormat { - pipeline, - shader: output.ty, - }, - ) + if let Some(state) = color_targets.get(*i as usize) { + let format = if let Some(st) = state.as_ref() { + st.format + } else { + return Err( + pipeline::CreateRenderPipelineError::InvalidFragmentOutputLocation(*i), + ); + }; + validation::check_texture_format(format, &output.ty).map_err(|pipeline| { + pipeline::CreateRenderPipelineError::ColorState( + *i as u8, + pipeline::ColorStateError::IncompatibleFormat { + pipeline, + shader: output.ty, }, - )?; - } - None => (), + ) + })?; } } } diff --git a/wgpu-hal/examples/raw-gles.rs b/wgpu-hal/examples/raw-gles.rs index 34ad021478..1620794fb0 100644 --- a/wgpu-hal/examples/raw-gles.rs +++ b/wgpu-hal/examples/raw-gles.rs @@ -163,7 +163,7 @@ fn fill_screen(exposed: &hal::ExposedAdapter, width: u32, height depth_or_array_layers: 1, }, sample_count: 1, - color_attachments: &[hal::ColorAttachment { + color_attachments: &[Some(hal::ColorAttachment { target: hal::Attachment { view: &view, usage: hal::TextureUses::COLOR_TARGET, @@ -171,7 +171,7 @@ fn fill_screen(exposed: &hal::ExposedAdapter, width: u32, height resolve_target: None, ops: hal::AttachmentOps::STORE, clear_value: wgt::Color::BLUE, - }], + })], depth_stencil_attachment: None, multiview: None, }; diff --git a/wgpu-hal/src/metal/command.rs b/wgpu-hal/src/metal/command.rs index 589c60cc6a..9231df9303 100644 --- a/wgpu-hal/src/metal/command.rs +++ b/wgpu-hal/src/metal/command.rs @@ -353,7 +353,7 @@ impl crate::CommandEncoder for super::CommandEncoder { //TODO: set visibility results buffer for (i, at) in desc.color_attachments.iter().enumerate() { - if let Some(at) = at { + if let Some(at) = at.as_ref() { let at_descriptor = descriptor.color_attachments().object_at(i as u64).unwrap(); at_descriptor.set_texture(Some(&at.target.view.raw)); if let Some(ref resolve) = at.resolve_target { diff --git a/wgpu-hal/src/vulkan/device.rs b/wgpu-hal/src/vulkan/device.rs index 0a15e7b07b..82567e67c0 100644 --- a/wgpu-hal/src/vulkan/device.rs +++ b/wgpu-hal/src/vulkan/device.rs @@ -108,11 +108,11 @@ impl super::DeviceShared { .build(); vk_attachments.push(vk_attachment); } else { - resolve_refs.push(unused.clone()); + resolve_refs.push(unused); }; } else { - color_refs.push(unused.clone()); - resolve_refs.push(unused.clone()); + color_refs.push(unused); + resolve_refs.push(unused); } } From 02da0b00ea4f6181ba053a2dd4a637565ef65ee2 Mon Sep 17 00:00:00 2001 From: Jinlei Li Date: Tue, 28 Jun 2022 04:38:46 +0800 Subject: [PATCH 6/6] Follow all suggestions --- wgpu-core/src/command/render.rs | 9 +++-- wgpu-core/src/device/mod.rs | 38 ++++++++++++-------- wgpu-hal/src/dx12/command.rs | 22 ++---------- wgpu-hal/src/dx12/device.rs | 29 +++++++++------ wgpu-hal/src/dx12/mod.rs | 5 +-- wgpu-hal/src/gles/command.rs | 2 +- wgpu-hal/src/vulkan/adapter.rs | 5 --- wgpu-hal/src/vulkan/command.rs | 1 - wgpu-hal/src/vulkan/device.rs | 63 ++++++++++++++++++--------------- 9 files changed, 90 insertions(+), 84 deletions(-) diff --git a/wgpu-core/src/command/render.rs b/wgpu-core/src/command/render.rs index 810114dca8..0b2c0acd42 100644 --- a/wgpu-core/src/command/render.rs +++ b/wgpu-core/src/command/render.rs @@ -950,8 +950,13 @@ impl<'a, A: HalApi> RenderPassInfo<'a, A> { .collect(), resolves: color_attachments .iter() - .filter_map(|at| at.as_ref().map(|at| at.resolve_target)) - .filter_map(|attachment| attachment.as_ref().map(|at| view_guard.get(*at).unwrap())) + .filter_map(|at| match *at { + Some(RenderPassColorAttachment { + resolve_target: Some(resolve), + .. + }) => Some(view_guard.get(resolve).unwrap()), + _ => None, + }) .collect(), depth_stencil: depth_stencil_attachment.map(|at| view_guard.get(at.view).unwrap()), }; diff --git a/wgpu-core/src/device/mod.rs b/wgpu-core/src/device/mod.rs index 74f37b2007..f79c95038f 100644 --- a/wgpu-core/src/device/mod.rs +++ b/wgpu-core/src/device/mod.rs @@ -20,7 +20,7 @@ use hal::{CommandEncoder as _, Device as _}; use parking_lot::{Mutex, MutexGuard}; use smallvec::SmallVec; use thiserror::Error; -use wgt::{BufferAddress, ColorTargetState, TextureFormat, TextureViewDimension}; +use wgt::{BufferAddress, TextureFormat, TextureViewDimension}; use std::{borrow::Cow, iter, mem, num::NonZeroU32, ops::Range, ptr}; @@ -2465,7 +2465,7 @@ impl Device { .map_or(&[][..], |fragment| &fragment.targets); let depth_stencil_state = desc.depth_stencil.as_ref(); - let cts: ArrayVec<&ColorTargetState, { hal::MAX_COLOR_ATTACHMENTS }> = + let cts: ArrayVec<_, { hal::MAX_COLOR_ATTACHMENTS }> = color_targets.iter().filter_map(|x| x.as_ref()).collect(); if !cts.is_empty() && { let first = &cts[0]; @@ -2760,23 +2760,31 @@ impl Device { if validated_stages.contains(wgt::ShaderStages::FRAGMENT) { for (i, output) in io.iter() { - if let Some(state) = color_targets.get(*i as usize) { - let format = if let Some(st) = state.as_ref() { - st.format - } else { + match color_targets.get(*i as usize) { + Some(&Some(ref state)) => { + validation::check_texture_format(state.format, &output.ty).map_err( + |pipeline| { + pipeline::CreateRenderPipelineError::ColorState( + *i as u8, + pipeline::ColorStateError::IncompatibleFormat { + pipeline, + shader: output.ty, + }, + ) + }, + )?; + } + Some(&None) => { return Err( pipeline::CreateRenderPipelineError::InvalidFragmentOutputLocation(*i), ); - }; - validation::check_texture_format(format, &output.ty).map_err(|pipeline| { - pipeline::CreateRenderPipelineError::ColorState( + } + _ => { + return Err(pipeline::CreateRenderPipelineError::ColorState( *i as u8, - pipeline::ColorStateError::IncompatibleFormat { - pipeline, - shader: output.ty, - }, - ) - })?; + pipeline::ColorStateError::Missing, + )); + } } } } diff --git a/wgpu-hal/src/dx12/command.rs b/wgpu-hal/src/dx12/command.rs index 20f26fc78d..ca2f036430 100644 --- a/wgpu-hal/src/dx12/command.rs +++ b/wgpu-hal/src/dx12/command.rs @@ -580,32 +580,14 @@ impl crate::CommandEncoder for super::CommandEncoder { unsafe fn begin_render_pass(&mut self, desc: &crate::RenderPassDescriptor) { self.begin_pass(super::PassKind::Render, desc.label); let mut color_views = [native::CpuDescriptor { ptr: 0 }; crate::MAX_COLOR_ATTACHMENTS]; - let mut null_rtv_handle: Option = None; for (rtv, cat) in color_views.iter_mut().zip(desc.color_attachments.iter()) { if let Some(cat) = cat.as_ref() { *rtv = cat.target.view.handle_rtv.unwrap().raw; } else { - if null_rtv_handle.is_none() { - let handle = self.rtv_pool.lock().alloc_handle(); - // A null pResource is used to initialize a null descriptor, - // which guarantees D3D11-like null binding behavior (reading 0s, writes are discarded) - self.device.create_render_target_view( - native::WeakPtr::null(), - &native::RenderTargetViewDesc::texture_2d( - winapi::shared::dxgiformat::DXGI_FORMAT_R8G8B8A8_UNORM, - 0, - 0, - ), - handle.raw, - ); - null_rtv_handle = Some(handle); - } - *rtv = null_rtv_handle.unwrap().raw; + *rtv = self.null_rtv_handle.raw; } } - if let Some(handle) = null_rtv_handle { - self.rtv_pool.lock().free_handle(handle); - } + let ds_view = match desc.depth_stencil_attachment { None => ptr::null(), Some(ref ds) => { diff --git a/wgpu-hal/src/dx12/device.rs b/wgpu-hal/src/dx12/device.rs index dd66c1ff78..65fde1f422 100644 --- a/wgpu-hal/src/dx12/device.rs +++ b/wgpu-hal/src/dx12/device.rs @@ -125,6 +125,20 @@ impl super::Device { )?, }; + let mut rtv_pool = descriptor::CpuPool::new(raw, native::DescriptorHeapType::Rtv); + let null_rtv_handle = rtv_pool.alloc_handle(); + // A null pResource is used to initialize a null descriptor, + // which guarantees D3D11-like null binding behavior (reading 0s, writes are discarded) + raw.create_render_target_view( + native::WeakPtr::null(), + &native::RenderTargetViewDesc::texture_2d( + winapi::shared::dxgiformat::DXGI_FORMAT_R8G8B8A8_UNORM, + 0, + 0, + ), + null_rtv_handle.raw, + ); + Ok(super::Device { raw, present_queue, @@ -134,10 +148,7 @@ impl super::Device { }, private_caps, shared: Arc::new(shared), - rtv_pool: Arc::new(Mutex::new(descriptor::CpuPool::new( - raw, - native::DescriptorHeapType::Rtv, - ))), + rtv_pool: Mutex::new(rtv_pool), dsv_pool: Mutex::new(descriptor::CpuPool::new( raw, native::DescriptorHeapType::Dsv, @@ -153,6 +164,7 @@ impl super::Device { library: Arc::clone(library), #[cfg(feature = "renderdoc")] render_doc: Default::default(), + null_rtv_handle, }) } @@ -306,11 +318,8 @@ impl super::Device { impl crate::Device for super::Device { unsafe fn exit(self, queue: super::Queue) { - Arc::try_unwrap(self.rtv_pool) - .ok() - .unwrap() - .into_inner() - .destroy(); + self.rtv_pool.lock().free_handle(self.null_rtv_handle); + self.rtv_pool.into_inner().destroy(); self.dsv_pool.into_inner().destroy(); self.srv_uav_pool.into_inner().destroy(); self.sampler_pool.into_inner().destroy(); @@ -662,7 +671,7 @@ impl crate::Device for super::Device { allocator, device: self.raw, shared: Arc::clone(&self.shared), - rtv_pool: Arc::clone(&self.rtv_pool), + null_rtv_handle: self.null_rtv_handle.clone(), list: None, free_lists: Vec::new(), pass: super::PassState::new(), diff --git a/wgpu-hal/src/dx12/mod.rs b/wgpu-hal/src/dx12/mod.rs index 591ed16b9b..1d67d07a49 100644 --- a/wgpu-hal/src/dx12/mod.rs +++ b/wgpu-hal/src/dx12/mod.rs @@ -221,7 +221,7 @@ pub struct Device { private_caps: PrivateCapabilities, shared: Arc, // CPU only pools - rtv_pool: Arc>, + rtv_pool: Mutex, dsv_pool: Mutex, srv_uav_pool: Mutex, sampler_pool: Mutex, @@ -229,6 +229,7 @@ pub struct Device { library: Arc, #[cfg(feature = "renderdoc")] render_doc: crate::auxil::renderdoc::RenderDoc, + null_rtv_handle: descriptor::Handle, } unsafe impl Send for Device {} @@ -329,7 +330,7 @@ pub struct CommandEncoder { allocator: native::CommandAllocator, device: native::Device, shared: Arc, - rtv_pool: Arc>, + null_rtv_handle: descriptor::Handle, list: Option, free_lists: Vec, pass: PassState, diff --git a/wgpu-hal/src/gles/command.rs b/wgpu-hal/src/gles/command.rs index 04958610e8..beaf600e6e 100644 --- a/wgpu-hal/src/gles/command.rs +++ b/wgpu-hal/src/gles/command.rs @@ -430,7 +430,7 @@ impl crate::CommandEncoder for super::CommandEncoder { .color_attachments .first() .filter(|at| at.is_some()) - .map(|at| &at.as_ref().unwrap().target.view.inner) + .and_then(|at| at.as_ref().map(|at| &at.target.view.inner)) { // default framebuffer (provided externally) Some(&super::TextureInner::DefaultRenderbuffer) => { diff --git a/wgpu-hal/src/vulkan/adapter.rs b/wgpu-hal/src/vulkan/adapter.rs index 1be86d8211..878a5ed73c 100644 --- a/wgpu-hal/src/vulkan/adapter.rs +++ b/wgpu-hal/src/vulkan/adapter.rs @@ -1063,7 +1063,6 @@ impl super::Instance { .imageless_framebuffer .map_or(false, |ext| ext.imageless_framebuffer != 0), }, - // imageless_framebuffers: false, image_view_usage: phd_capabilities.properties.api_version >= vk::API_VERSION_1_1 || phd_capabilities.supports_extension(vk::KhrMaintenance2Fn::name()), timeline_semaphores: match phd_features.vulkan_1_2 { @@ -1097,10 +1096,6 @@ impl super::Instance { .map_or(false, |ext| ext.robust_image_access != 0), }, }; - println!( - "caps.imageless_framebuffers {}", - private_caps.imageless_framebuffers - ); let capabilities = crate::Capabilities { limits: phd_capabilities.to_wgpu_limits(&phd_features), alignments: phd_capabilities.to_hal_alignments(), diff --git a/wgpu-hal/src/vulkan/command.rs b/wgpu-hal/src/vulkan/command.rs index 343fd1e7f0..abfc3d6216 100644 --- a/wgpu-hal/src/vulkan/command.rs +++ b/wgpu-hal/src/vulkan/command.rs @@ -379,7 +379,6 @@ impl crate::CommandEncoder for super::CommandEncoder { if let Some(ref at) = cat.resolve_target { vk_clear_values.push(mem::zeroed()); vk_image_views.push(at.view.raw); - println!("fb_key.attachments: {:?}", &at.view.attachment.raw); fb_key.attachments.push(at.view.attachment.clone()); } diff --git a/wgpu-hal/src/vulkan/device.rs b/wgpu-hal/src/vulkan/device.rs index 82567e67c0..6696dcca7b 100644 --- a/wgpu-hal/src/vulkan/device.rs +++ b/wgpu-hal/src/vulkan/device.rs @@ -76,11 +76,11 @@ impl super::DeviceShared { layout: vk::ImageLayout::UNDEFINED, }; for cat in e.key().colors.iter() { - if let Some(cat) = cat.as_ref() { - color_refs.push(vk::AttachmentReference { + let (color_ref, resolve_ref) = if let Some(cat) = cat.as_ref() { + let color_ref = vk::AttachmentReference { attachment: vk_attachments.len() as u32, layout: cat.base.layout, - }); + }; vk_attachments.push({ let (load_op, store_op) = conv::map_attachment_ops(cat.base.ops); vk::AttachmentDescription::builder() @@ -92,11 +92,7 @@ impl super::DeviceShared { .final_layout(cat.base.layout) .build() }); - if let Some(ref rat) = cat.resolve { - resolve_refs.push(vk::AttachmentReference { - attachment: vk_attachments.len() as u32, - layout: rat.layout, - }); + let resolve_ref = if let Some(ref rat) = cat.resolve { let (load_op, store_op) = conv::map_attachment_ops(rat.ops); let vk_attachment = vk::AttachmentDescription::builder() .format(rat.format) @@ -107,13 +103,22 @@ impl super::DeviceShared { .final_layout(rat.layout) .build(); vk_attachments.push(vk_attachment); + + vk::AttachmentReference { + attachment: vk_attachments.len() as u32 - 1, + layout: rat.layout, + } } else { - resolve_refs.push(unused); + unused }; + + (color_ref, resolve_ref) } else { - color_refs.push(unused); - resolve_refs.push(unused); - } + (unused, unused) + }; + + color_refs.push(color_ref); + resolve_refs.push(resolve_ref); } if let Some(ref ds) = e.key().depth_stencil { @@ -1577,18 +1582,7 @@ impl crate::Device for super::Device { let mut vk_attachments = Vec::with_capacity(desc.color_targets.len()); for cat in desc.color_targets { - if let Some(cat) = cat.as_ref() { - let vk_format = self.shared.private_caps.map_texture_format(cat.format); - compatible_rp_key - .colors - .push(Some(super::ColorAttachmentKey { - base: super::AttachmentKey::compatible( - vk_format, - vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL, - ), - resolve: None, - })); - + let (key, attarchment) = if let Some(cat) = cat.as_ref() { let mut vk_attachment = vk::PipelineColorBlendAttachmentState::builder() .color_write_mask(vk::ColorComponentFlags::from_raw(cat.write_mask.bits())); if let Some(ref blend) = cat.blend { @@ -1603,11 +1597,24 @@ impl crate::Device for super::Device { .src_alpha_blend_factor(alpha_src) .dst_alpha_blend_factor(alpha_dst); } - vk_attachments.push(vk_attachment.build()); + + let vk_format = self.shared.private_caps.map_texture_format(cat.format); + ( + Some(super::ColorAttachmentKey { + base: super::AttachmentKey::compatible( + vk_format, + vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL, + ), + resolve: None, + }), + vk_attachment.build(), + ) } else { - vk_attachments.push(vk::PipelineColorBlendAttachmentState::default()); - compatible_rp_key.colors.push(None); - } + (None, vk::PipelineColorBlendAttachmentState::default()) + }; + + compatible_rp_key.colors.push(key); + vk_attachments.push(attarchment); } let vk_color_blend = vk::PipelineColorBlendStateCreateInfo::builder()