mirror of
https://github.com/gfx-rs/wgpu.git
synced 2025-02-16 17:02:32 +00:00
Relax render pass color_attachments validation (#2778)
* Make the color attachments `Option`-al in render pipelines, render passes, and render bundles * vk: `Option`-al color attachments support * dx12: sparse color_attachments support * Only non-hole attachments is supported on wasm target and gl backend * deno_webgpu: `Option`-al color attachments support * Follow all suggestions
This commit is contained in:
parent
892c272d18
commit
61796b1d59
@ -32,7 +32,7 @@ impl Resource for WebGpuRenderBundle {
|
||||
pub struct CreateRenderBundleEncoderArgs {
|
||||
device_rid: ResourceId,
|
||||
label: Option<String>,
|
||||
color_formats: Vec<wgpu_types::TextureFormat>,
|
||||
color_formats: Vec<Option<wgpu_types::TextureFormat>>,
|
||||
depth_stencil_format: Option<wgpu_types::TextureFormat>,
|
||||
sample_count: u32,
|
||||
depth_read_only: bool,
|
||||
|
@ -78,7 +78,7 @@ pub fn op_webgpu_command_encoder_begin_render_pass(
|
||||
state: &mut OpState,
|
||||
command_encoder_rid: ResourceId,
|
||||
label: Option<String>,
|
||||
color_attachments: Vec<GpuRenderPassColorAttachment>,
|
||||
color_attachments: Vec<Option<GpuRenderPassColorAttachment>>,
|
||||
depth_stencil_attachment: Option<GpuRenderPassDepthStencilAttachment>,
|
||||
_occlusion_query_set: Option<u32>, // not yet implemented
|
||||
) -> Result<WebGpuResult, AnyError> {
|
||||
@ -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::<super::texture::WebGpuTextureView>(color_attachment.view)?;
|
||||
let rp_at = if let Some(at) = color_attachment.as_ref() {
|
||||
let texture_view_resource = state
|
||||
.resource_table
|
||||
.get::<super::texture::WebGpuTextureView>(at.view)?;
|
||||
|
||||
let resolve_target = color_attachment
|
||||
.resolve_target
|
||||
.map(|rid| {
|
||||
state
|
||||
.resource_table
|
||||
.get::<super::texture::WebGpuTextureView>(rid)
|
||||
let resolve_target = at
|
||||
.resolve_target
|
||||
.map(|rid| {
|
||||
state
|
||||
.resource_table
|
||||
.get::<super::texture::WebGpuTextureView>(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::<Result<Vec<_>, AnyError>>()?;
|
||||
|
||||
|
@ -260,7 +260,7 @@ impl From<GpuMultisampleState> for wgpu_types::MultisampleState {
|
||||
#[derive(Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct GpuFragmentState {
|
||||
targets: Vec<wgpu_types::ColorTargetState>,
|
||||
targets: Vec<Option<wgpu_types::ColorTargetState>>,
|
||||
module: u32,
|
||||
entry_point: String,
|
||||
// TODO(lucacasonato): constants
|
||||
|
@ -613,7 +613,7 @@ dictionary GPUMultisampleState {
|
||||
};
|
||||
|
||||
dictionary GPUFragmentState : GPUProgrammableStage {
|
||||
required sequence<GPUColorTargetState> targets;
|
||||
required sequence<GPUColorTargetState?> targets;
|
||||
};
|
||||
|
||||
dictionary GPUColorTargetState {
|
||||
@ -908,7 +908,7 @@ GPURenderPassEncoder includes GPUBindingCommandsMixin;
|
||||
GPURenderPassEncoder includes GPURenderCommandsMixin;
|
||||
|
||||
dictionary GPURenderPassDescriptor : GPUObjectDescriptorBase {
|
||||
required sequence<GPURenderPassColorAttachment> colorAttachments;
|
||||
required sequence<GPURenderPassColorAttachment?> colorAttachments;
|
||||
GPURenderPassDepthStencilAttachment depthStencilAttachment;
|
||||
GPUQuerySet occlusionQuerySet;
|
||||
};
|
||||
@ -947,7 +947,7 @@ enum GPUStoreOp {
|
||||
};
|
||||
|
||||
dictionary GPURenderPassLayout: GPUObjectDescriptorBase {
|
||||
required sequence<GPUTextureFormat> colorFormats;
|
||||
required sequence<GPUTextureFormat?> colorFormats;
|
||||
GPUTextureFormat depthStencilFormat;
|
||||
GPUSize32 sampleCount = 1;
|
||||
};
|
||||
|
@ -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,
|
||||
),
|
||||
|
@ -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,
|
||||
),
|
||||
|
@ -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<wgt::TextureFormat>]>,
|
||||
/// 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<wgt::RenderBundleDepthStencil>,
|
||||
|
@ -408,7 +408,7 @@ fn clear_texture_via_render_passes<A: hal::Api>(
|
||||
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<A: hal::Api>(
|
||||
resolve_target: None,
|
||||
ops: hal::AttachmentOps::STORE,
|
||||
clear_value: wgt::Color::TRANSPARENT,
|
||||
}];
|
||||
})];
|
||||
(&color_attachments_tmp[..], None)
|
||||
} else {
|
||||
(
|
||||
|
@ -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<RenderPassColorAttachment>]>,
|
||||
/// 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<RenderCommand>,
|
||||
parent_id: id::CommandEncoderId,
|
||||
color_targets: ArrayVec<RenderPassColorAttachment, { hal::MAX_COLOR_ATTACHMENTS }>,
|
||||
color_targets: ArrayVec<Option<RenderPassColorAttachment>, { hal::MAX_COLOR_ATTACHMENTS }>,
|
||||
depth_stencil_target: Option<RenderPassDepthStencilAttachment>,
|
||||
|
||||
// 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<A>,
|
||||
label: Option<&str>,
|
||||
color_attachments: &[RenderPassColorAttachment],
|
||||
color_attachments: &[Option<RenderPassColorAttachment>],
|
||||
depth_stencil_attachment: Option<&RenderPassDepthStencilAttachment>,
|
||||
cmd_buf: &mut CommandBuffer<A>,
|
||||
view_guard: &'a Storage<TextureView<A>, 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::ColorAttachment<A>, { hal::MAX_COLOR_ATTACHMENTS }>::new();
|
||||
let mut colors =
|
||||
ArrayVec::<Option<hal::ColorAttachment<A>>, { 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<A> = 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,30 @@ 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| 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()),
|
||||
};
|
||||
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 +1088,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
&self,
|
||||
encoder_id: id::CommandEncoderId,
|
||||
base: BasePassRef<RenderCommand>,
|
||||
color_attachments: &[RenderPassColorAttachment],
|
||||
color_attachments: &[Option<RenderPassColorAttachment>],
|
||||
depth_stencil_attachment: Option<&RenderPassDepthStencilAttachment>,
|
||||
) -> Result<(), RenderPassError> {
|
||||
profiling::scope!("run_render_pass", "CommandEncoder");
|
||||
|
@ -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<T> {
|
||||
pub colors: ArrayVec<T, { hal::MAX_COLOR_ATTACHMENTS }>,
|
||||
pub colors: ArrayVec<Option<T>, { hal::MAX_COLOR_ATTACHMENTS }>,
|
||||
pub resolves: ArrayVec<T, { hal::MAX_COLOR_ATTACHMENTS }>,
|
||||
pub depth_stencil: Option<T>,
|
||||
}
|
||||
@ -60,7 +60,7 @@ impl<T: PartialEq> Eq for AttachmentData<T> {}
|
||||
impl<T> AttachmentData<T> {
|
||||
pub(crate) fn map<U, F: Fn(&T) -> U>(&self, fun: F) -> AttachmentData<U> {
|
||||
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<TextureFormat, { hal::MAX_COLOR_ATTACHMENTS }>,
|
||||
ArrayVec<TextureFormat, { hal::MAX_COLOR_ATTACHMENTS }>,
|
||||
ArrayVec<Option<TextureFormat>, { hal::MAX_COLOR_ATTACHMENTS }>,
|
||||
ArrayVec<Option<TextureFormat>, { hal::MAX_COLOR_ATTACHMENTS }>,
|
||||
),
|
||||
#[error(
|
||||
"Incompatible depth-stencil attachment: the renderpass expected {0:?} but was given {1:?}"
|
||||
@ -2465,9 +2465,11 @@ impl<A: HalApi> Device<A> {
|
||||
.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<_, { 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<A: HalApi> Device<A> {
|
||||
}
|
||||
|
||||
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,13 @@ impl<A: HalApi> Device<A> {
|
||||
};
|
||||
|
||||
if validated_stages.contains(wgt::ShaderStages::FRAGMENT) {
|
||||
for (i, state) in color_targets.iter().enumerate() {
|
||||
match io.get(&(i as wgt::ShaderLocation)) {
|
||||
Some(output) => {
|
||||
for (i, output) in io.iter() {
|
||||
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,
|
||||
*i as u8,
|
||||
pipeline::ColorStateError::IncompatibleFormat {
|
||||
pipeline,
|
||||
shader: output.ty,
|
||||
@ -2769,11 +2774,14 @@ impl<A: HalApi> Device<A> {
|
||||
},
|
||||
)?;
|
||||
}
|
||||
None if state.write_mask.is_empty() => {}
|
||||
None => {
|
||||
log::warn!("Missing fragment output[{}], expected {:?}", i, state,);
|
||||
Some(&None) => {
|
||||
return Err(
|
||||
pipeline::CreateRenderPipelineError::InvalidFragmentOutputLocation(*i),
|
||||
);
|
||||
}
|
||||
_ => {
|
||||
return Err(pipeline::CreateRenderPipelineError::ColorState(
|
||||
i as u8,
|
||||
*i as u8,
|
||||
pipeline::ColorStateError::Missing,
|
||||
));
|
||||
}
|
||||
@ -2850,7 +2858,10 @@ impl<A: HalApi> Device<A> {
|
||||
|
||||
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 +2870,7 @@ impl<A: HalApi> Device<A> {
|
||||
};
|
||||
|
||||
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;
|
||||
|
@ -176,7 +176,7 @@ pub enum Command {
|
||||
},
|
||||
RunRenderPass {
|
||||
base: crate::command::BasePass<crate::command::RenderCommand>,
|
||||
target_colors: Vec<crate::command::RenderPassColorAttachment>,
|
||||
target_colors: Vec<Option<crate::command::RenderPassColorAttachment>>,
|
||||
target_depth_stencil: Option<crate::command::RenderPassDepthStencilAttachment>,
|
||||
},
|
||||
}
|
||||
|
@ -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<wgt::ColorTargetState>]>,
|
||||
}
|
||||
|
||||
/// 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")]
|
||||
|
@ -238,11 +238,11 @@ impl<A: hal::Api> Example<A> {
|
||||
},
|
||||
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<A: hal::Api> Example<A> {
|
||||
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<A: hal::Api> Example<A> {
|
||||
b: 0.3,
|
||||
a: 1.0,
|
||||
},
|
||||
}],
|
||||
})],
|
||||
depth_stencil_attachment: None,
|
||||
multiview: None,
|
||||
};
|
||||
|
@ -163,7 +163,7 @@ fn fill_screen(exposed: &hal::ExposedAdapter<hal::api::Gles>, 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<hal::api::Gles>, width: u32, height
|
||||
resolve_target: None,
|
||||
ops: hal::AttachmentOps::STORE,
|
||||
clear_value: wgt::Color::BLUE,
|
||||
}],
|
||||
})],
|
||||
depth_stencil_attachment: None,
|
||||
multiview: None,
|
||||
};
|
||||
|
@ -579,11 +579,15 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
|
||||
|
||||
unsafe fn begin_render_pass(&mut self, desc: &crate::RenderPassDescriptor<super::Api>) {
|
||||
self.begin_pass(super::PassKind::Render, desc.label);
|
||||
|
||||
let mut color_views = [native::CpuDescriptor { ptr: 0 }; crate::MAX_COLOR_ATTACHMENTS];
|
||||
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 {
|
||||
*rtv = self.null_rtv_handle.raw;
|
||||
}
|
||||
}
|
||||
|
||||
let ds_view = match desc.depth_stencil_attachment {
|
||||
None => ptr::null(),
|
||||
Some(ref ds) => {
|
||||
@ -605,23 +609,26 @@ impl crate::CommandEncoder<super::Api> 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;
|
||||
|
@ -267,7 +267,7 @@ fn map_blend_component(
|
||||
}
|
||||
|
||||
pub fn map_render_targets(
|
||||
color_targets: &[wgt::ColorTargetState],
|
||||
color_targets: &[Option<wgt::ColorTargetState>],
|
||||
) -> [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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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: 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,6 +318,7 @@ impl super::Device {
|
||||
|
||||
impl crate::Device<super::Api> for super::Device {
|
||||
unsafe fn exit(self, queue: super::Queue) {
|
||||
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();
|
||||
@ -658,6 +671,7 @@ impl crate::Device<super::Api> for super::Device {
|
||||
allocator,
|
||||
device: self.raw,
|
||||
shared: Arc::clone(&self.shared),
|
||||
null_rtv_handle: self.null_rtv_handle.clone(),
|
||||
list: None,
|
||||
free_lists: Vec::new(),
|
||||
pass: super::PassState::new(),
|
||||
@ -1283,7 +1297,9 @@ impl crate::Device<super::Api> 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
|
||||
|
@ -229,6 +229,7 @@ pub struct Device {
|
||||
library: Arc<native::D3D12Lib>,
|
||||
#[cfg(feature = "renderdoc")]
|
||||
render_doc: crate::auxil::renderdoc::RenderDoc,
|
||||
null_rtv_handle: descriptor::Handle,
|
||||
}
|
||||
|
||||
unsafe impl Send for Device {}
|
||||
@ -329,6 +330,7 @@ pub struct CommandEncoder {
|
||||
allocator: native::CommandAllocator,
|
||||
device: native::Device,
|
||||
shared: Arc<DeviceShared>,
|
||||
null_rtv_handle: descriptor::Handle,
|
||||
list: Option<native::GraphicsCommandList>,
|
||||
free_lists: Vec<native::GraphicsCommandList>,
|
||||
pass: PassState,
|
||||
|
@ -429,7 +429,8 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
|
||||
match desc
|
||||
.color_attachments
|
||||
.first()
|
||||
.map(|at| &at.target.view.inner)
|
||||
.filter(|at| at.is_some())
|
||||
.and_then(|at| at.as_ref().map(|at| &at.target.view.inner))
|
||||
{
|
||||
// default framebuffer (provided externally)
|
||||
Some(&super::TextureInner::DefaultRenderbuffer) => {
|
||||
@ -444,18 +445,20 @@ impl crate::CommandEncoder<super::Api> 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<super::Api> 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
|
||||
|
@ -1002,7 +1002,7 @@ impl crate::Device<super::Api> 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),
|
||||
|
@ -1024,7 +1024,7 @@ pub struct RenderPipelineDescriptor<'a, A: Api> {
|
||||
/// The fragment stage for this pipeline.
|
||||
pub fragment_stage: Option<ProgrammableStage<'a, A>>,
|
||||
/// The effect of draw calls on the color aspect of the output target.
|
||||
pub color_targets: &'a [wgt::ColorTargetState],
|
||||
pub color_targets: &'a [Option<wgt::ColorTargetState>],
|
||||
/// If the pipeline will be used with a multiview render pass, this indicates how many array
|
||||
/// layers the attachments will have.
|
||||
pub multiview: Option<NonZeroU32>,
|
||||
@ -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<ColorAttachment<'a, A>>],
|
||||
pub depth_stencil_attachment: Option<DepthStencilAttachment<'a, A>>,
|
||||
pub multiview: Option<NonZeroU32>,
|
||||
}
|
||||
|
@ -353,24 +353,26 @@ impl crate::CommandEncoder<super::Api> 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.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 {
|
||||
//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 {
|
||||
|
@ -841,6 +841,12 @@ impl crate::Device<super::Api> 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);
|
||||
|
@ -1059,19 +1059,17 @@ 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),
|
||||
},
|
||||
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 +1091,11 @@ 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),
|
||||
},
|
||||
};
|
||||
|
||||
let capabilities = crate::Capabilities {
|
||||
limits: phd_capabilities.to_wgpu_limits(&phd_features),
|
||||
alignments: phd_capabilities.to_hal_alignments(),
|
||||
|
@ -362,31 +362,36 @@ impl crate::CommandEncoder<super::Api> 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)
|
||||
}),
|
||||
};
|
||||
|
||||
// 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);
|
||||
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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
rp_key.colors.push(None);
|
||||
}
|
||||
}
|
||||
if let Some(ref ds) = desc.depth_stencil_attachment {
|
||||
@ -431,25 +436,29 @@ impl crate::CommandEncoder<super::Api> 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 +471,7 @@ impl crate::CommandEncoder<super::Api> 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);
|
||||
|
@ -71,46 +71,54 @@ 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 {
|
||||
let (color_ref, resolve_ref) = if let Some(cat) = cat.as_ref() {
|
||||
let color_ref = vk::AttachmentReference {
|
||||
attachment: vk_attachments.len() as u32,
|
||||
layout: rat.layout,
|
||||
layout: cat.base.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);
|
||||
at_ref
|
||||
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 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)
|
||||
.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);
|
||||
|
||||
vk::AttachmentReference {
|
||||
attachment: vk_attachments.len() as u32 - 1,
|
||||
layout: rat.layout,
|
||||
}
|
||||
} else {
|
||||
unused
|
||||
};
|
||||
|
||||
(color_ref, resolve_ref)
|
||||
} else {
|
||||
vk::AttachmentReference {
|
||||
attachment: vk::ATTACHMENT_UNUSED,
|
||||
layout: vk::ImageLayout::UNDEFINED,
|
||||
}
|
||||
(unused, unused)
|
||||
};
|
||||
resolve_refs.push(at_ref);
|
||||
|
||||
color_refs.push(color_ref);
|
||||
resolve_refs.push(resolve_ref);
|
||||
}
|
||||
|
||||
if let Some(ref ds) = e.key().depth_stencil {
|
||||
@ -1574,30 +1582,39 @@ impl crate::Device<super::Api> 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 (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 {
|
||||
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);
|
||||
}
|
||||
|
||||
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());
|
||||
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 {
|
||||
(None, vk::PipelineColorBlendAttachmentState::default())
|
||||
};
|
||||
|
||||
compatible_rp_key.colors.push(key);
|
||||
vk_attachments.push(attarchment);
|
||||
}
|
||||
|
||||
let vk_color_blend = vk::PipelineColorBlendStateCreateInfo::builder()
|
||||
|
@ -212,7 +212,7 @@ struct DepthStencilAttachmentKey {
|
||||
|
||||
#[derive(Clone, Eq, Default, Hash, PartialEq)]
|
||||
struct RenderPassKey {
|
||||
colors: ArrayVec<ColorAttachmentKey, { crate::MAX_COLOR_ATTACHMENTS }>,
|
||||
colors: ArrayVec<Option<ColorAttachmentKey>, { crate::MAX_COLOR_ATTACHMENTS }>,
|
||||
depth_stencil: Option<DepthStencilAttachmentKey>,
|
||||
sample_count: u32,
|
||||
multiview: Option<NonZeroU32>,
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
});
|
||||
|
||||
|
@ -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,
|
||||
});
|
||||
|
||||
|
@ -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.");
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
});
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
});
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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::<ArrayVec<_, { wgc::MAX_COLOR_ATTACHMENTS }>>();
|
||||
|
||||
|
@ -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::<js_sys::Array>();
|
||||
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::<js_sys::Array>();
|
||||
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::<js_sys::Array>();
|
||||
|
||||
|
@ -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<RenderPassColorAttachment<'tex>>],
|
||||
/// The depth and stencil attachment of the render pass, if any.
|
||||
pub depth_stencil_attachment: Option<RenderPassDepthStencilAttachment<'tex>>,
|
||||
}
|
||||
@ -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<ColorTargetState>],
|
||||
}
|
||||
|
||||
/// 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<TextureFormat>],
|
||||
/// 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<RenderBundleDepthStencil>,
|
||||
|
@ -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,
|
||||
});
|
||||
|
@ -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,
|
||||
});
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user