mirror of
https://github.com/gfx-rs/wgpu.git
synced 2025-12-08 21:26:17 +00:00
Add multiview limits and tests (#8206)
Co-authored-by: Andreas Reich <r_andreas2@web.de> Co-authored-by: Magnus <85136135+SupaMaggie70Incorporated@users.noreply.github.com>
This commit is contained in:
parent
5633ae8649
commit
ad0f3111b7
34
CHANGELOG.md
34
CHANGELOG.md
@ -40,7 +40,7 @@ Bottom level categories:
|
|||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
### Major changes
|
### Major Changes
|
||||||
|
|
||||||
#### `wgpu::Instance::enumerate_adapters` is now `async` & available on WebGPU
|
#### `wgpu::Instance::enumerate_adapters` is now `async` & available on WebGPU
|
||||||
|
|
||||||
@ -73,6 +73,38 @@ SamplerDescriptor {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Multiview on all major platforms and support for multiview bitmasks
|
||||||
|
|
||||||
|
Multiview is a feature that allows rendering the same content to multiple layers of a texture. This is useful primarily in VR where you wish to
|
||||||
|
display almost identical content to 2 views, just with a different perspective. Instead of using 2 draw calls or 2 instances for each object, you
|
||||||
|
can use this feature.
|
||||||
|
|
||||||
|
Multiview is also called view instancing in DX12 land or vertex amplification in Metal land.
|
||||||
|
|
||||||
|
Multiview has been reworked, adding support for Metal, and adding testing and validation to wgpu itself.
|
||||||
|
This change also introduces a view bitmask, a new field in `RenderPassDescriptor` that allows a render pass to render to multiple non-adjacent layers
|
||||||
|
when using the `SELECTIVE_MULTIVIEW` feature. Note that this also influences apps that don't use multiview, as they have to set this mask to `None`.
|
||||||
|
```diff
|
||||||
|
- wgpu::RenderPassDescriptor {
|
||||||
|
- label: None,
|
||||||
|
- color_attachments: &color_attachments,
|
||||||
|
- depth_stencil_attachment: None,
|
||||||
|
- timestamp_writes: None,
|
||||||
|
- occlusion_query_set: None,
|
||||||
|
- }
|
||||||
|
+ wgpu::RenderPassDescriptor {
|
||||||
|
+ label: None,
|
||||||
|
+ color_attachments: &color_attachments,
|
||||||
|
+ depth_stencil_attachment: None,
|
||||||
|
+ timestamp_writes: None,
|
||||||
|
+ occlusion_query_set: None,
|
||||||
|
+ multiview_mask: NonZero::new(3),
|
||||||
|
+ }
|
||||||
|
```
|
||||||
|
One other breaking change worth noting is that in WGSL `@builtin(view_index)` now requires a type of `u32`, where previously it required `i32`.
|
||||||
|
|
||||||
|
By @SupaMaggie70Incorporated in [#8206](https://github.com/gfx-rs/wgpu/pull/8206).
|
||||||
|
|
||||||
### New Features
|
### New Features
|
||||||
|
|
||||||
- Added support for transient textures on Vulkan and Metal. By @opstic in [#8247](https://github.com/gfx-rs/wgpu/pull/8247)
|
- Added support for transient textures on Vulkan and Metal. By @opstic in [#8247](https://github.com/gfx-rs/wgpu/pull/8247)
|
||||||
|
|||||||
@ -224,7 +224,7 @@ impl RenderpassState {
|
|||||||
})],
|
})],
|
||||||
compilation_options: wgpu::PipelineCompilationOptions::default(),
|
compilation_options: wgpu::PipelineCompilationOptions::default(),
|
||||||
}),
|
}),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -322,7 +322,7 @@ impl RenderpassState {
|
|||||||
})],
|
})],
|
||||||
compilation_options: wgpu::PipelineCompilationOptions::default(),
|
compilation_options: wgpu::PipelineCompilationOptions::default(),
|
||||||
}),
|
}),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
@ -370,6 +370,7 @@ impl RenderpassState {
|
|||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
let start_idx = pass_number * draws_per_pass;
|
let start_idx = pass_number * draws_per_pass;
|
||||||
@ -417,6 +418,7 @@ impl RenderpassState {
|
|||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
render_pass.set_pipeline(self.bindless_pipeline.as_ref().unwrap());
|
render_pass.set_pipeline(self.bindless_pipeline.as_ref().unwrap());
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
use std::num::NonZero;
|
||||||
|
|
||||||
use deno_core::cppgc::Ptr;
|
use deno_core::cppgc::Ptr;
|
||||||
use deno_core::op2;
|
use deno_core::op2;
|
||||||
@ -142,6 +143,7 @@ impl GPUCommandEncoder {
|
|||||||
occlusion_query_set: descriptor
|
occlusion_query_set: descriptor
|
||||||
.occlusion_query_set
|
.occlusion_query_set
|
||||||
.map(|query_set| query_set.id),
|
.map(|query_set| query_set.id),
|
||||||
|
multiview_mask: NonZero::new(descriptor.multiview_mask),
|
||||||
};
|
};
|
||||||
|
|
||||||
let (render_pass, err) = self
|
let (render_pass, err) = self
|
||||||
|
|||||||
@ -876,7 +876,7 @@ impl GPUDevice {
|
|||||||
multisample,
|
multisample,
|
||||||
fragment,
|
fragment,
|
||||||
cache: None,
|
cache: None,
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let (id, err) = self.instance.device_create_render_pipeline(
|
let (id, err) = self.instance.device_create_render_pipeline(
|
||||||
|
|||||||
@ -460,6 +460,9 @@ pub(crate) struct GPURenderPassDescriptor {
|
|||||||
/*#[webidl(default = 50000000)]
|
/*#[webidl(default = 50000000)]
|
||||||
#[options(enforce_range = true)]
|
#[options(enforce_range = true)]
|
||||||
pub max_draw_count: u64,*/
|
pub max_draw_count: u64,*/
|
||||||
|
#[webidl(default = 0)]
|
||||||
|
#[options(enforce_range = true)]
|
||||||
|
pub multiview_mask: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(WebIDL)]
|
#[derive(WebIDL)]
|
||||||
|
|||||||
@ -148,7 +148,7 @@ impl crate::framework::Example for Example {
|
|||||||
primitive: wgpu::PrimitiveState::default(),
|
primitive: wgpu::PrimitiveState::default(),
|
||||||
depth_stencil: None,
|
depth_stencil: None,
|
||||||
multisample: wgpu::MultisampleState::default(),
|
multisample: wgpu::MultisampleState::default(),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -276,6 +276,7 @@ impl crate::framework::Example for Example {
|
|||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
// get command encoder
|
// get command encoder
|
||||||
|
|||||||
@ -122,6 +122,7 @@ impl Example {
|
|||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
rpass.set_pipeline(&self.pipeline);
|
rpass.set_pipeline(&self.pipeline);
|
||||||
rpass.set_bind_group(0, &self.global_group, &[]);
|
rpass.set_bind_group(0, &self.global_group, &[]);
|
||||||
@ -229,7 +230,7 @@ impl crate::framework::Example for Example {
|
|||||||
},
|
},
|
||||||
depth_stencil: None,
|
depth_stencil: None,
|
||||||
multisample: wgpu::MultisampleState::default(),
|
multisample: wgpu::MultisampleState::default(),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -106,7 +106,7 @@ impl crate::framework::Example for Example {
|
|||||||
},
|
},
|
||||||
depth_stencil: None,
|
depth_stencil: None,
|
||||||
multisample: wgpu::MultisampleState::default(),
|
multisample: wgpu::MultisampleState::default(),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -129,7 +129,7 @@ impl crate::framework::Example for Example {
|
|||||||
primitive: wgpu::PrimitiveState::default(),
|
primitive: wgpu::PrimitiveState::default(),
|
||||||
depth_stencil: None,
|
depth_stencil: None,
|
||||||
multisample: wgpu::MultisampleState::default(),
|
multisample: wgpu::MultisampleState::default(),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -160,7 +160,7 @@ impl crate::framework::Example for Example {
|
|||||||
},
|
},
|
||||||
depth_stencil: None,
|
depth_stencil: None,
|
||||||
multisample: wgpu::MultisampleState::default(),
|
multisample: wgpu::MultisampleState::default(),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
@ -217,7 +217,7 @@ impl crate::framework::Example for Example {
|
|||||||
primitive: wgpu::PrimitiveState::default(),
|
primitive: wgpu::PrimitiveState::default(),
|
||||||
depth_stencil: None,
|
depth_stencil: None,
|
||||||
multisample: wgpu::MultisampleState::default(),
|
multisample: wgpu::MultisampleState::default(),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
}),
|
}),
|
||||||
bind_group_layout,
|
bind_group_layout,
|
||||||
@ -273,6 +273,7 @@ impl crate::framework::Example for Example {
|
|||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
rpass.set_pipeline(&self.pipeline_triangle_conservative);
|
rpass.set_pipeline(&self.pipeline_triangle_conservative);
|
||||||
@ -295,6 +296,7 @@ impl crate::framework::Example for Example {
|
|||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
rpass.set_pipeline(&self.pipeline_upscale);
|
rpass.set_pipeline(&self.pipeline_upscale);
|
||||||
|
|||||||
@ -256,7 +256,7 @@ impl crate::framework::Example for Example {
|
|||||||
},
|
},
|
||||||
depth_stencil: None,
|
depth_stencil: None,
|
||||||
multisample: wgpu::MultisampleState::default(),
|
multisample: wgpu::MultisampleState::default(),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -298,7 +298,7 @@ impl crate::framework::Example for Example {
|
|||||||
},
|
},
|
||||||
depth_stencil: None,
|
depth_stencil: None,
|
||||||
multisample: wgpu::MultisampleState::default(),
|
multisample: wgpu::MultisampleState::default(),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
Some(pipeline_wire)
|
Some(pipeline_wire)
|
||||||
@ -356,6 +356,7 @@ impl crate::framework::Example for Example {
|
|||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
rpass.push_debug_group("Prepare data for draw.");
|
rpass.push_debug_group("Prepare data for draw.");
|
||||||
rpass.set_pipeline(&self.pipeline);
|
rpass.set_pipeline(&self.pipeline);
|
||||||
|
|||||||
@ -71,7 +71,7 @@ async fn run(event_loop: EventLoop<()>, window: Window) {
|
|||||||
primitive: wgpu::PrimitiveState::default(),
|
primitive: wgpu::PrimitiveState::default(),
|
||||||
depth_stencil: None,
|
depth_stencil: None,
|
||||||
multisample: wgpu::MultisampleState::default(),
|
multisample: wgpu::MultisampleState::default(),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -129,6 +129,7 @@ async fn run(event_loop: EventLoop<()>, window: Window) {
|
|||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
rpass.set_pipeline(&render_pipeline);
|
rpass.set_pipeline(&render_pipeline);
|
||||||
rpass.draw(0..3, 0..1);
|
rpass.draw(0..3, 0..1);
|
||||||
|
|||||||
@ -133,6 +133,7 @@ async fn run(event_loop: EventLoop<()>, viewports: Vec<(Arc<Window>, wgpu::Color
|
|||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -17,6 +17,7 @@ pub mod mesh_shader;
|
|||||||
pub mod mipmap;
|
pub mod mipmap;
|
||||||
pub mod msaa_line;
|
pub mod msaa_line;
|
||||||
pub mod multiple_render_targets;
|
pub mod multiple_render_targets;
|
||||||
|
pub mod multiview;
|
||||||
pub mod ray_cube_compute;
|
pub mod ray_cube_compute;
|
||||||
pub mod ray_cube_fragment;
|
pub mod ray_cube_fragment;
|
||||||
pub mod ray_cube_normals;
|
pub mod ray_cube_normals;
|
||||||
|
|||||||
@ -188,6 +188,12 @@ const EXAMPLES: &[ExampleDesc] = &[
|
|||||||
webgl: false,
|
webgl: false,
|
||||||
webgpu: false,
|
webgpu: false,
|
||||||
},
|
},
|
||||||
|
ExampleDesc {
|
||||||
|
name: "multiview",
|
||||||
|
function: wgpu_examples::multiview::main,
|
||||||
|
webgl: false,
|
||||||
|
webgpu: false,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
fn get_example_name() -> Option<String> {
|
fn get_example_name() -> Option<String> {
|
||||||
|
|||||||
@ -144,6 +144,7 @@ impl crate::framework::Example for Example {
|
|||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
rpass.push_debug_group("Prepare data for draw.");
|
rpass.push_debug_group("Prepare data for draw.");
|
||||||
rpass.set_pipeline(&self.pipeline);
|
rpass.set_pipeline(&self.pipeline);
|
||||||
|
|||||||
@ -104,7 +104,7 @@ impl Example {
|
|||||||
},
|
},
|
||||||
depth_stencil: None,
|
depth_stencil: None,
|
||||||
multisample: wgpu::MultisampleState::default(),
|
multisample: wgpu::MultisampleState::default(),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -170,6 +170,7 @@ impl Example {
|
|||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
if let Some(ref query_sets) = query_sets {
|
if let Some(ref query_sets) = query_sets {
|
||||||
rpass.write_timestamp(&query_sets.timestamp, timestamp_query_index_base);
|
rpass.write_timestamp(&query_sets.timestamp, timestamp_query_index_base);
|
||||||
@ -305,7 +306,7 @@ impl crate::framework::Example for Example {
|
|||||||
},
|
},
|
||||||
depth_stencil: None,
|
depth_stencil: None,
|
||||||
multisample: wgpu::MultisampleState::default(),
|
multisample: wgpu::MultisampleState::default(),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -492,6 +493,7 @@ impl crate::framework::Example for Example {
|
|||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
rpass.set_pipeline(&self.draw_pipeline);
|
rpass.set_pipeline(&self.draw_pipeline);
|
||||||
rpass.set_bind_group(0, &self.bind_group, &[]);
|
rpass.set_bind_group(0, &self.bind_group, &[]);
|
||||||
|
|||||||
@ -77,7 +77,7 @@ impl Example {
|
|||||||
count: sample_count,
|
count: sample_count,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
let mut encoder =
|
let mut encoder =
|
||||||
@ -307,6 +307,7 @@ impl crate::framework::Example for Example {
|
|||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
})
|
})
|
||||||
.execute_bundles(iter::once(&self.bundle));
|
.execute_bundles(iter::once(&self.bundle));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -161,7 +161,7 @@ impl MultiTargetRenderer {
|
|||||||
primitive: wgpu::PrimitiveState::default(),
|
primitive: wgpu::PrimitiveState::default(),
|
||||||
depth_stencil: None,
|
depth_stencil: None,
|
||||||
multisample: wgpu::MultisampleState::default(),
|
multisample: wgpu::MultisampleState::default(),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -182,6 +182,7 @@ impl MultiTargetRenderer {
|
|||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
rpass.set_pipeline(&self.pipeline);
|
rpass.set_pipeline(&self.pipeline);
|
||||||
rpass.set_bind_group(0, &self.bindgroup, &[]);
|
rpass.set_bind_group(0, &self.bindgroup, &[]);
|
||||||
@ -266,7 +267,7 @@ impl TargetRenderer {
|
|||||||
primitive: wgpu::PrimitiveState::default(),
|
primitive: wgpu::PrimitiveState::default(),
|
||||||
depth_stencil: None,
|
depth_stencil: None,
|
||||||
multisample: wgpu::MultisampleState::default(),
|
multisample: wgpu::MultisampleState::default(),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -339,6 +340,7 @@ impl TargetRenderer {
|
|||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
rpass.set_pipeline(&self.pipeline);
|
rpass.set_pipeline(&self.pipeline);
|
||||||
rpass.set_bind_group(0, &self.bindgroup_left, &[]);
|
rpass.set_bind_group(0, &self.bindgroup_left, &[]);
|
||||||
|
|||||||
182
examples/features/src/multiview/mod.rs
Normal file
182
examples/features/src/multiview/mod.rs
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
//! Renders different content to different layers of an array texture using multiview,
|
||||||
|
//! a feature commonly used for VR rendering.
|
||||||
|
|
||||||
|
use std::{num::NonZero, time::Instant};
|
||||||
|
|
||||||
|
use wgpu::util::TextureBlitter;
|
||||||
|
|
||||||
|
const TEXTURE_SIZE: u32 = 512;
|
||||||
|
|
||||||
|
// Change this to demonstrate non-contiguous multiview functionality
|
||||||
|
const LAYER_MASK: u32 = 0b11;
|
||||||
|
|
||||||
|
const NUM_LAYERS: u32 = 32 - LAYER_MASK.leading_zeros();
|
||||||
|
|
||||||
|
pub struct Example {
|
||||||
|
pipeline: wgpu::RenderPipeline,
|
||||||
|
entire_texture_view: wgpu::TextureView,
|
||||||
|
views: Vec<wgpu::TextureView>,
|
||||||
|
start_time: Instant,
|
||||||
|
blitter: TextureBlitter,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl crate::framework::Example for Example {
|
||||||
|
fn init(
|
||||||
|
config: &wgpu::SurfaceConfiguration,
|
||||||
|
_adapter: &wgpu::Adapter,
|
||||||
|
device: &wgpu::Device,
|
||||||
|
_queue: &wgpu::Queue,
|
||||||
|
) -> Self {
|
||||||
|
let shader_src = include_str!("shader.wgsl");
|
||||||
|
|
||||||
|
let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
|
||||||
|
label: None,
|
||||||
|
source: wgpu::ShaderSource::Wgsl(shader_src.into()),
|
||||||
|
});
|
||||||
|
|
||||||
|
let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
||||||
|
label: None,
|
||||||
|
vertex: wgpu::VertexState {
|
||||||
|
buffers: &[],
|
||||||
|
module: &shader,
|
||||||
|
entry_point: Some("vs_main"),
|
||||||
|
compilation_options: Default::default(),
|
||||||
|
},
|
||||||
|
primitive: wgpu::PrimitiveState::default(),
|
||||||
|
fragment: Some(wgpu::FragmentState {
|
||||||
|
module: &shader,
|
||||||
|
entry_point: Some("fs_main"),
|
||||||
|
compilation_options: Default::default(),
|
||||||
|
targets: &[Some(wgpu::ColorTargetState {
|
||||||
|
format: wgpu::TextureFormat::Rgba8Unorm,
|
||||||
|
blend: None,
|
||||||
|
write_mask: wgpu::ColorWrites::ALL,
|
||||||
|
})],
|
||||||
|
}),
|
||||||
|
multiview_mask: NonZero::new(LAYER_MASK),
|
||||||
|
multisample: Default::default(),
|
||||||
|
layout: None,
|
||||||
|
depth_stencil: None,
|
||||||
|
cache: None,
|
||||||
|
});
|
||||||
|
let texture = device.create_texture(&wgpu::TextureDescriptor {
|
||||||
|
label: None,
|
||||||
|
size: wgpu::Extent3d {
|
||||||
|
width: TEXTURE_SIZE,
|
||||||
|
height: TEXTURE_SIZE,
|
||||||
|
depth_or_array_layers: NUM_LAYERS,
|
||||||
|
},
|
||||||
|
mip_level_count: 1,
|
||||||
|
sample_count: 1,
|
||||||
|
dimension: wgpu::TextureDimension::D2,
|
||||||
|
format: wgpu::TextureFormat::Rgba8Unorm,
|
||||||
|
usage: wgpu::TextureUsages::RENDER_ATTACHMENT
|
||||||
|
| wgpu::TextureUsages::COPY_SRC
|
||||||
|
| wgpu::TextureUsages::TEXTURE_BINDING,
|
||||||
|
view_formats: &[],
|
||||||
|
});
|
||||||
|
let entire_texture_view = texture.create_view(&wgpu::TextureViewDescriptor {
|
||||||
|
label: None,
|
||||||
|
format: Some(wgpu::TextureFormat::Rgba8Unorm),
|
||||||
|
dimension: Some(wgpu::TextureViewDimension::D2Array),
|
||||||
|
usage: Some(wgpu::TextureUsages::RENDER_ATTACHMENT),
|
||||||
|
aspect: wgpu::TextureAspect::All,
|
||||||
|
base_mip_level: 0,
|
||||||
|
mip_level_count: None,
|
||||||
|
base_array_layer: 0,
|
||||||
|
array_layer_count: Some(NUM_LAYERS),
|
||||||
|
});
|
||||||
|
let mut views = Vec::new();
|
||||||
|
for i in 0..NUM_LAYERS {
|
||||||
|
views.push(texture.create_view(&wgpu::TextureViewDescriptor {
|
||||||
|
label: None,
|
||||||
|
format: Some(wgpu::TextureFormat::Rgba8Unorm),
|
||||||
|
dimension: Some(wgpu::TextureViewDimension::D2),
|
||||||
|
usage: Some(wgpu::TextureUsages::TEXTURE_BINDING),
|
||||||
|
aspect: wgpu::TextureAspect::All,
|
||||||
|
base_mip_level: 0,
|
||||||
|
mip_level_count: None,
|
||||||
|
base_array_layer: i,
|
||||||
|
array_layer_count: Some(1),
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
let blitter = wgpu::util::TextureBlitter::new(device, config.format);
|
||||||
|
Self {
|
||||||
|
pipeline,
|
||||||
|
entire_texture_view,
|
||||||
|
views,
|
||||||
|
blitter,
|
||||||
|
start_time: Instant::now(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render(&mut self, view: &wgpu::TextureView, device: &wgpu::Device, queue: &wgpu::Queue) {
|
||||||
|
let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor::default());
|
||||||
|
{
|
||||||
|
let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||||
|
label: None,
|
||||||
|
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
|
||||||
|
view: &self.entire_texture_view,
|
||||||
|
depth_slice: None,
|
||||||
|
resolve_target: None,
|
||||||
|
ops: wgpu::Operations {
|
||||||
|
load: wgpu::LoadOp::Clear(wgpu::Color {
|
||||||
|
r: 0.02,
|
||||||
|
g: 0.02,
|
||||||
|
b: 0.02,
|
||||||
|
a: 1.0,
|
||||||
|
}),
|
||||||
|
store: wgpu::StoreOp::Store,
|
||||||
|
},
|
||||||
|
})],
|
||||||
|
depth_stencil_attachment: None,
|
||||||
|
timestamp_writes: None,
|
||||||
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: NonZero::new(LAYER_MASK),
|
||||||
|
});
|
||||||
|
rpass.set_pipeline(&self.pipeline);
|
||||||
|
rpass.draw(0..6, 0..1);
|
||||||
|
}
|
||||||
|
|
||||||
|
let layer = (Instant::now() - self.start_time).as_secs() % NUM_LAYERS as u64;
|
||||||
|
self.blitter
|
||||||
|
.copy(device, &mut encoder, &self.views[layer as usize], view);
|
||||||
|
queue.submit(Some(encoder.finish()));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn required_downlevel_capabilities() -> wgpu::DownlevelCapabilities {
|
||||||
|
Default::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn required_features() -> wgpu::Features {
|
||||||
|
wgpu::Features::MULTIVIEW
|
||||||
|
| if !(LAYER_MASK + 1).is_power_of_two() {
|
||||||
|
wgpu::Features::SELECTIVE_MULTIVIEW
|
||||||
|
} else {
|
||||||
|
wgpu::Features::empty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn required_limits() -> wgpu::Limits {
|
||||||
|
wgpu::Limits {
|
||||||
|
max_multiview_view_count: NUM_LAYERS,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resize(
|
||||||
|
&mut self,
|
||||||
|
_config: &wgpu::SurfaceConfiguration,
|
||||||
|
_device: &wgpu::Device,
|
||||||
|
_queue: &wgpu::Queue,
|
||||||
|
) {
|
||||||
|
// empty
|
||||||
|
}
|
||||||
|
fn update(&mut self, _event: winit::event::WindowEvent) {
|
||||||
|
// empty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn main() {
|
||||||
|
crate::framework::run::<Example>("multiview");
|
||||||
|
}
|
||||||
11
examples/features/src/multiview/shader.wgsl
Normal file
11
examples/features/src/multiview/shader.wgsl
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
const triangles = array<vec2f, 3>(vec2f(-1.0, -1.0), vec2f(3.0, -1.0), vec2f(-1.0, 3.0));
|
||||||
|
|
||||||
|
@vertex
|
||||||
|
fn vs_main(@builtin(vertex_index) vertex_index: u32) -> @builtin(position) vec4f {
|
||||||
|
return vec4f(triangles[vertex_index], 0.0, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@fragment
|
||||||
|
fn fs_main(@builtin(view_index) view_index: u32) -> @location(0) vec4f {
|
||||||
|
return vec4f(f32(view_index) * 0.25 + 0.125, 1.0 - f32(view_index) * 0.25, 1.0 - 0.5 * f32(view_index), 1.0);
|
||||||
|
}
|
||||||
@ -326,7 +326,7 @@ impl crate::framework::Example for Example {
|
|||||||
},
|
},
|
||||||
depth_stencil: None,
|
depth_stencil: None,
|
||||||
multisample: wgpu::MultisampleState::default(),
|
multisample: wgpu::MultisampleState::default(),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -469,6 +469,7 @@ impl crate::framework::Example for Example {
|
|||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
rpass.set_pipeline(&self.blit_pipeline);
|
rpass.set_pipeline(&self.blit_pipeline);
|
||||||
|
|||||||
@ -216,7 +216,7 @@ impl crate::framework::Example for Example {
|
|||||||
},
|
},
|
||||||
depth_stencil: None,
|
depth_stencil: None,
|
||||||
multisample: wgpu::MultisampleState::default(),
|
multisample: wgpu::MultisampleState::default(),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -355,6 +355,7 @@ impl crate::framework::Example for Example {
|
|||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
rpass.set_pipeline(&self.pipeline);
|
rpass.set_pipeline(&self.pipeline);
|
||||||
|
|||||||
@ -317,7 +317,7 @@ impl crate::framework::Example for Example {
|
|||||||
},
|
},
|
||||||
depth_stencil: None,
|
depth_stencil: None,
|
||||||
multisample: wgpu::MultisampleState::default(),
|
multisample: wgpu::MultisampleState::default(),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -455,6 +455,7 @@ impl crate::framework::Example for Example {
|
|||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
rpass.set_pipeline(&self.blit_pipeline);
|
rpass.set_pipeline(&self.blit_pipeline);
|
||||||
|
|||||||
@ -395,7 +395,7 @@ impl crate::framework::Example for Example {
|
|||||||
},
|
},
|
||||||
depth_stencil: None,
|
depth_stencil: None,
|
||||||
multisample: wgpu::MultisampleState::default(),
|
multisample: wgpu::MultisampleState::default(),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -535,6 +535,7 @@ impl crate::framework::Example for Example {
|
|||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
rpass.set_pipeline(&self.pipeline);
|
rpass.set_pipeline(&self.pipeline);
|
||||||
|
|||||||
@ -239,7 +239,7 @@ impl crate::framework::Example for Example {
|
|||||||
},
|
},
|
||||||
depth_stencil: None,
|
depth_stencil: None,
|
||||||
multisample: wgpu::MultisampleState::default(),
|
multisample: wgpu::MultisampleState::default(),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -348,6 +348,7 @@ impl crate::framework::Example for Example {
|
|||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
rpass.set_pipeline(&self.pipeline);
|
rpass.set_pipeline(&self.pipeline);
|
||||||
|
|||||||
@ -309,7 +309,7 @@ impl crate::framework::Example for Example {
|
|||||||
write_mask: Default::default(),
|
write_mask: Default::default(),
|
||||||
})],
|
})],
|
||||||
}),
|
}),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -414,6 +414,7 @@ impl crate::framework::Example for Example {
|
|||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
rpass.set_pipeline(&self.blit_pipeline);
|
rpass.set_pipeline(&self.blit_pipeline);
|
||||||
|
|||||||
@ -68,7 +68,7 @@ async fn run(_path: Option<String>) {
|
|||||||
primitive: wgpu::PrimitiveState::default(),
|
primitive: wgpu::PrimitiveState::default(),
|
||||||
depth_stencil: None,
|
depth_stencil: None,
|
||||||
multisample: wgpu::MultisampleState::default(),
|
multisample: wgpu::MultisampleState::default(),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -95,6 +95,7 @@ async fn run(_path: Option<String>) {
|
|||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
render_pass.set_pipeline(&pipeline);
|
render_pass.set_pipeline(&pipeline);
|
||||||
render_pass.draw(0..3, 0..1);
|
render_pass.draw(0..3, 0..1);
|
||||||
|
|||||||
@ -518,7 +518,7 @@ impl crate::framework::Example for Example {
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
multisample: wgpu::MultisampleState::default(),
|
multisample: wgpu::MultisampleState::default(),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -653,7 +653,7 @@ impl crate::framework::Example for Example {
|
|||||||
bias: wgpu::DepthBiasState::default(),
|
bias: wgpu::DepthBiasState::default(),
|
||||||
}),
|
}),
|
||||||
multisample: wgpu::MultisampleState::default(),
|
multisample: wgpu::MultisampleState::default(),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -771,6 +771,7 @@ impl crate::framework::Example for Example {
|
|||||||
}),
|
}),
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
pass.set_pipeline(&self.shadow_pass.pipeline);
|
pass.set_pipeline(&self.shadow_pass.pipeline);
|
||||||
pass.set_bind_group(0, &self.shadow_pass.bind_group, &[]);
|
pass.set_bind_group(0, &self.shadow_pass.bind_group, &[]);
|
||||||
@ -816,6 +817,7 @@ impl crate::framework::Example for Example {
|
|||||||
}),
|
}),
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
pass.set_pipeline(&self.forward_pass.pipeline);
|
pass.set_pipeline(&self.forward_pass.pipeline);
|
||||||
pass.set_bind_group(0, &self.forward_pass.bind_group, &[]);
|
pass.set_bind_group(0, &self.forward_pass.bind_group, &[]);
|
||||||
|
|||||||
@ -218,7 +218,7 @@ impl crate::framework::Example for Example {
|
|||||||
bias: wgpu::DepthBiasState::default(),
|
bias: wgpu::DepthBiasState::default(),
|
||||||
}),
|
}),
|
||||||
multisample: wgpu::MultisampleState::default(),
|
multisample: wgpu::MultisampleState::default(),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
let entity_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
let entity_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
||||||
@ -252,7 +252,7 @@ impl crate::framework::Example for Example {
|
|||||||
bias: wgpu::DepthBiasState::default(),
|
bias: wgpu::DepthBiasState::default(),
|
||||||
}),
|
}),
|
||||||
multisample: wgpu::MultisampleState::default(),
|
multisample: wgpu::MultisampleState::default(),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -444,6 +444,7 @@ impl crate::framework::Example for Example {
|
|||||||
}),
|
}),
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
rpass.set_bind_group(0, &self.bind_group, &[]);
|
rpass.set_bind_group(0, &self.bind_group, &[]);
|
||||||
|
|||||||
@ -146,7 +146,7 @@ impl<const SRGB: bool> crate::framework::Example for Example<SRGB> {
|
|||||||
},
|
},
|
||||||
depth_stencil: None,
|
depth_stencil: None,
|
||||||
multisample: wgpu::MultisampleState::default(),
|
multisample: wgpu::MultisampleState::default(),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -196,6 +196,7 @@ impl<const SRGB: bool> crate::framework::Example for Example<SRGB> {
|
|||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
rpass.push_debug_group("Prepare data for draw.");
|
rpass.push_debug_group("Prepare data for draw.");
|
||||||
rpass.set_pipeline(&self.pipeline);
|
rpass.set_pipeline(&self.pipeline);
|
||||||
|
|||||||
@ -100,7 +100,7 @@ impl crate::framework::Example for Example {
|
|||||||
bias: Default::default(),
|
bias: Default::default(),
|
||||||
}),
|
}),
|
||||||
multisample: wgpu::MultisampleState::default(),
|
multisample: wgpu::MultisampleState::default(),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -136,7 +136,7 @@ impl crate::framework::Example for Example {
|
|||||||
bias: Default::default(),
|
bias: Default::default(),
|
||||||
}),
|
}),
|
||||||
multisample: wgpu::MultisampleState::default(),
|
multisample: wgpu::MultisampleState::default(),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -222,6 +222,7 @@ impl crate::framework::Example for Example {
|
|||||||
}),
|
}),
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
rpass.set_stencil_reference(1);
|
rpass.set_stencil_reference(1);
|
||||||
|
|||||||
@ -358,7 +358,7 @@ impl crate::framework::Example for Example {
|
|||||||
},
|
},
|
||||||
depth_stencil: None,
|
depth_stencil: None,
|
||||||
multisample: wgpu::MultisampleState::default(),
|
multisample: wgpu::MultisampleState::default(),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None
|
cache: None
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -402,6 +402,7 @@ impl crate::framework::Example for Example {
|
|||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
rpass.set_pipeline(&self.pipeline);
|
rpass.set_pipeline(&self.pipeline);
|
||||||
|
|||||||
@ -358,7 +358,7 @@ fn render_pass(
|
|||||||
primitive: wgpu::PrimitiveState::default(),
|
primitive: wgpu::PrimitiveState::default(),
|
||||||
depth_stencil: None,
|
depth_stencil: None,
|
||||||
multisample: wgpu::MultisampleState::default(),
|
multisample: wgpu::MultisampleState::default(),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
let render_target = device.create_texture(&wgpu::TextureDescriptor {
|
let render_target = device.create_texture(&wgpu::TextureDescriptor {
|
||||||
@ -395,6 +395,7 @@ fn render_pass(
|
|||||||
end_of_pass_write_index: Some(*next_unused_query + 1),
|
end_of_pass_write_index: Some(*next_unused_query + 1),
|
||||||
}),
|
}),
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
*next_unused_query += 2;
|
*next_unused_query += 2;
|
||||||
|
|
||||||
|
|||||||
@ -186,7 +186,7 @@ impl WgpuContext {
|
|||||||
primitive: wgpu::PrimitiveState::default(),
|
primitive: wgpu::PrimitiveState::default(),
|
||||||
depth_stencil: None,
|
depth_stencil: None,
|
||||||
multisample: wgpu::MultisampleState::default(),
|
multisample: wgpu::MultisampleState::default(),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
let surface_config = surface
|
let surface_config = surface
|
||||||
@ -319,6 +319,7 @@ async fn run(event_loop: EventLoop<()>, window: Arc<Window>) {
|
|||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
render_pass.set_pipeline(&wgpu_context_ref.pipeline);
|
render_pass.set_pipeline(&wgpu_context_ref.pipeline);
|
||||||
// (9)
|
// (9)
|
||||||
|
|||||||
@ -567,7 +567,7 @@ impl crate::framework::Example for Example {
|
|||||||
}),
|
}),
|
||||||
// No multisampling is used.
|
// No multisampling is used.
|
||||||
multisample: wgpu::MultisampleState::default(),
|
multisample: wgpu::MultisampleState::default(),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
// No pipeline caching is used
|
// No pipeline caching is used
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
@ -605,7 +605,7 @@ impl crate::framework::Example for Example {
|
|||||||
bias: wgpu::DepthBiasState::default(),
|
bias: wgpu::DepthBiasState::default(),
|
||||||
}),
|
}),
|
||||||
multisample: wgpu::MultisampleState::default(),
|
multisample: wgpu::MultisampleState::default(),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None
|
cache: None
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -750,6 +750,7 @@ impl crate::framework::Example for Example {
|
|||||||
}),
|
}),
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
rpass.execute_bundles([&self.terrain_bundle]);
|
rpass.execute_bundles([&self.terrain_bundle]);
|
||||||
@ -778,6 +779,7 @@ impl crate::framework::Example for Example {
|
|||||||
}),
|
}),
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
rpass.set_pipeline(&self.terrain_pipeline);
|
rpass.set_pipeline(&self.terrain_pipeline);
|
||||||
rpass.set_bind_group(0, &self.terrain_normal_bind_group, &[]);
|
rpass.set_bind_group(0, &self.terrain_normal_bind_group, &[]);
|
||||||
@ -805,6 +807,7 @@ impl crate::framework::Example for Example {
|
|||||||
}),
|
}),
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
rpass.set_pipeline(&self.water_pipeline);
|
rpass.set_pipeline(&self.water_pipeline);
|
||||||
|
|||||||
@ -107,6 +107,7 @@ impl State {
|
|||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
// If you wanted to call any drawing commands, they would go here.
|
// If you wanted to call any drawing commands, they would go here.
|
||||||
|
|||||||
@ -5215,8 +5215,13 @@ const fn glsl_built_in(built_in: crate::BuiltIn, options: VaryingOptions) -> &'s
|
|||||||
"gl_FragCoord"
|
"gl_FragCoord"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Bi::ViewIndex if options.targeting_webgl => "int(gl_ViewID_OVR)",
|
Bi::ViewIndex => {
|
||||||
Bi::ViewIndex => "gl_ViewIndex",
|
if options.targeting_webgl {
|
||||||
|
"gl_ViewID_OVR"
|
||||||
|
} else {
|
||||||
|
"uint(gl_ViewIndex)"
|
||||||
|
}
|
||||||
|
}
|
||||||
// vertex
|
// vertex
|
||||||
Bi::BaseInstance => "uint(gl_BaseInstance)",
|
Bi::BaseInstance => "uint(gl_BaseInstance)",
|
||||||
Bi::BaseVertex => "uint(gl_BaseVertex)",
|
Bi::BaseVertex => "uint(gl_BaseVertex)",
|
||||||
|
|||||||
@ -173,6 +173,7 @@ impl crate::BuiltIn {
|
|||||||
// to this field will get replaced with references to `SPECIAL_CBUF_VAR`
|
// to this field will get replaced with references to `SPECIAL_CBUF_VAR`
|
||||||
// in `Writer::write_expr`.
|
// in `Writer::write_expr`.
|
||||||
Self::NumWorkGroups => "SV_GroupID",
|
Self::NumWorkGroups => "SV_GroupID",
|
||||||
|
Self::ViewIndex => "SV_ViewID",
|
||||||
// These builtins map to functions
|
// These builtins map to functions
|
||||||
Self::SubgroupSize
|
Self::SubgroupSize
|
||||||
| Self::SubgroupInvocationId
|
| Self::SubgroupInvocationId
|
||||||
@ -181,7 +182,7 @@ impl crate::BuiltIn {
|
|||||||
Self::BaseInstance | Self::BaseVertex | Self::WorkGroupSize => {
|
Self::BaseInstance | Self::BaseVertex | Self::WorkGroupSize => {
|
||||||
return Err(Error::Unimplemented(format!("builtin {self:?}")))
|
return Err(Error::Unimplemented(format!("builtin {self:?}")))
|
||||||
}
|
}
|
||||||
Self::PointSize | Self::ViewIndex | Self::PointCoord | Self::DrawID => {
|
Self::PointSize | Self::PointCoord | Self::DrawID => {
|
||||||
return Err(Error::Custom(format!("Unsupported builtin {self:?}")))
|
return Err(Error::Custom(format!("Unsupported builtin {self:?}")))
|
||||||
}
|
}
|
||||||
Self::CullPrimitive => "SV_CullPrimitive",
|
Self::CullPrimitive => "SV_CullPrimitive",
|
||||||
|
|||||||
@ -650,6 +650,8 @@ pub enum Error {
|
|||||||
ResolveArraySizeError(#[from] proc::ResolveArraySizeError),
|
ResolveArraySizeError(#[from] proc::ResolveArraySizeError),
|
||||||
#[error("entry point with stage {0:?} and name '{1}' not found")]
|
#[error("entry point with stage {0:?} and name '{1}' not found")]
|
||||||
EntryPointNotFound(ir::ShaderStage, String),
|
EntryPointNotFound(ir::ShaderStage, String),
|
||||||
|
#[error("requires shader model {1:?} for reason: {0}")]
|
||||||
|
ShaderModelTooLow(String, ShaderModel),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Hash)]
|
#[derive(PartialEq, Eq, Hash)]
|
||||||
|
|||||||
@ -569,6 +569,14 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
|
|||||||
) -> BackendResult {
|
) -> BackendResult {
|
||||||
match *binding {
|
match *binding {
|
||||||
Some(crate::Binding::BuiltIn(builtin)) if !is_subgroup_builtin_binding(binding) => {
|
Some(crate::Binding::BuiltIn(builtin)) if !is_subgroup_builtin_binding(binding) => {
|
||||||
|
if builtin == crate::BuiltIn::ViewIndex
|
||||||
|
&& self.options.shader_model < ShaderModel::V6_1
|
||||||
|
{
|
||||||
|
return Err(Error::ShaderModelTooLow(
|
||||||
|
"used @builtin(view_index) or SV_ViewID".to_string(),
|
||||||
|
ShaderModel::V6_1,
|
||||||
|
));
|
||||||
|
}
|
||||||
let builtin_str = builtin.to_hlsl_str()?;
|
let builtin_str = builtin.to_hlsl_str()?;
|
||||||
write!(self.out, " : {builtin_str}")?;
|
write!(self.out, " : {builtin_str}")?;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -530,6 +530,12 @@ impl Options {
|
|||||||
crate::BuiltIn::PrimitiveIndex if self.lang_version < (2, 3) => {
|
crate::BuiltIn::PrimitiveIndex if self.lang_version < (2, 3) => {
|
||||||
return Err(Error::UnsupportedAttribute("primitive_id".to_string()));
|
return Err(Error::UnsupportedAttribute("primitive_id".to_string()));
|
||||||
}
|
}
|
||||||
|
// macOS: since Metal 2.3
|
||||||
|
// iOS: Since Metal 2.2
|
||||||
|
// https://developer.apple.com/metal/Metal-Shading-Language-Specification.pdf#page=114
|
||||||
|
crate::BuiltIn::ViewIndex if self.lang_version < (2, 2) => {
|
||||||
|
return Err(Error::UnsupportedAttribute("amplification_id".to_string()));
|
||||||
|
}
|
||||||
// macOS: Since Metal 2.2
|
// macOS: Since Metal 2.2
|
||||||
// iOS: Since Metal 2.3 (check depends on https://github.com/gfx-rs/wgpu/issues/4414)
|
// iOS: Since Metal 2.3 (check depends on https://github.com/gfx-rs/wgpu/issues/4414)
|
||||||
crate::BuiltIn::Barycentric if self.lang_version < (2, 3) => {
|
crate::BuiltIn::Barycentric if self.lang_version < (2, 3) => {
|
||||||
@ -674,6 +680,7 @@ impl ResolvedBinding {
|
|||||||
let name = match built_in {
|
let name = match built_in {
|
||||||
Bi::Position { invariant: false } => "position",
|
Bi::Position { invariant: false } => "position",
|
||||||
Bi::Position { invariant: true } => "position, invariant",
|
Bi::Position { invariant: true } => "position, invariant",
|
||||||
|
Bi::ViewIndex => "amplification_id",
|
||||||
// vertex
|
// vertex
|
||||||
Bi::BaseInstance => "base_instance",
|
Bi::BaseInstance => "base_instance",
|
||||||
Bi::BaseVertex => "base_vertex",
|
Bi::BaseVertex => "base_vertex",
|
||||||
@ -701,7 +708,7 @@ impl ResolvedBinding {
|
|||||||
Bi::SubgroupId => "simdgroup_index_in_threadgroup",
|
Bi::SubgroupId => "simdgroup_index_in_threadgroup",
|
||||||
Bi::SubgroupSize => "threads_per_simdgroup",
|
Bi::SubgroupSize => "threads_per_simdgroup",
|
||||||
Bi::SubgroupInvocationId => "thread_index_in_simdgroup",
|
Bi::SubgroupInvocationId => "thread_index_in_simdgroup",
|
||||||
Bi::CullDistance | Bi::ViewIndex | Bi::DrawID => {
|
Bi::CullDistance | Bi::DrawID => {
|
||||||
return Err(Error::UnsupportedBuiltIn(built_in))
|
return Err(Error::UnsupportedBuiltIn(built_in))
|
||||||
}
|
}
|
||||||
Bi::CullPrimitive => "primitive_culled",
|
Bi::CullPrimitive => "primitive_culled",
|
||||||
|
|||||||
@ -301,7 +301,7 @@ impl VaryingContext<'_> {
|
|||||||
St::Vertex | St::Fragment | St::Task | St::Mesh => !self.output,
|
St::Vertex | St::Fragment | St::Task | St::Mesh => !self.output,
|
||||||
St::Compute => false,
|
St::Compute => false,
|
||||||
},
|
},
|
||||||
*ty_inner == Ti::Scalar(crate::Scalar::I32),
|
*ty_inner == Ti::Scalar(crate::Scalar::U32),
|
||||||
),
|
),
|
||||||
Bi::FragDepth => (
|
Bi::FragDepth => (
|
||||||
self.stage == St::Fragment && self.output,
|
self.stage == St::Fragment && self.output,
|
||||||
|
|||||||
@ -1,3 +1,8 @@
|
|||||||
glsl_multiview = 2
|
glsl_multiview = 2
|
||||||
god_mode = true
|
god_mode = true
|
||||||
targets = "SPIRV | GLSL | WGSL"
|
|
||||||
|
[msl]
|
||||||
|
lang_version = [2, 3]
|
||||||
|
|
||||||
|
[hlsl]
|
||||||
|
shader_model = "V6_1"
|
||||||
|
|||||||
@ -1,2 +1,2 @@
|
|||||||
@fragment
|
@fragment
|
||||||
fn main(@builtin(view_index) view_index: i32) {}
|
fn main(@builtin(view_index) view_index: u32) {}
|
||||||
|
|||||||
@ -1,2 +1,2 @@
|
|||||||
@fragment
|
@fragment
|
||||||
fn main(@builtin(view_index) view_index: i32) {}
|
fn main(@builtin(view_index) view_index: u32) {}
|
||||||
|
|||||||
@ -6,7 +6,7 @@ precision highp int;
|
|||||||
|
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
int view_index = gl_ViewIndex;
|
uint view_index = uint(gl_ViewIndex);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@ precision highp int;
|
|||||||
|
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
int view_index = int(gl_ViewID_OVR);
|
uint view_index = gl_ViewID_OVR;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
9
naga/tests/out/hlsl/wgsl-multiview.hlsl
Normal file
9
naga/tests/out/hlsl/wgsl-multiview.hlsl
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
struct FragmentInput_main {
|
||||||
|
uint view_index_1 : SV_ViewID;
|
||||||
|
};
|
||||||
|
|
||||||
|
void main(FragmentInput_main fragmentinput_main)
|
||||||
|
{
|
||||||
|
uint view_index = fragmentinput_main.view_index_1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
12
naga/tests/out/hlsl/wgsl-multiview.ron
Normal file
12
naga/tests/out/hlsl/wgsl-multiview.ron
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
(
|
||||||
|
vertex:[
|
||||||
|
],
|
||||||
|
fragment:[
|
||||||
|
(
|
||||||
|
entry_point:"main",
|
||||||
|
target_profile:"ps_6_1",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
compute:[
|
||||||
|
],
|
||||||
|
)
|
||||||
14
naga/tests/out/msl/wgsl-multiview.msl
Normal file
14
naga/tests/out/msl/wgsl-multiview.msl
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
// language: metal2.3
|
||||||
|
#include <metal_stdlib>
|
||||||
|
#include <simd/simd.h>
|
||||||
|
|
||||||
|
using metal::uint;
|
||||||
|
|
||||||
|
|
||||||
|
struct main_Input {
|
||||||
|
};
|
||||||
|
fragment void main_(
|
||||||
|
uint view_index [[amplification_id]]
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
@ -12,7 +12,7 @@ OpExecutionMode %8 OriginUpperLeft
|
|||||||
OpDecorate %5 BuiltIn ViewIndex
|
OpDecorate %5 BuiltIn ViewIndex
|
||||||
OpDecorate %5 Flat
|
OpDecorate %5 Flat
|
||||||
%2 = OpTypeVoid
|
%2 = OpTypeVoid
|
||||||
%3 = OpTypeInt 32 1
|
%3 = OpTypeInt 32 0
|
||||||
%6 = OpTypePointer Input %3
|
%6 = OpTypePointer Input %3
|
||||||
%5 = OpVariable %6 Input
|
%5 = OpVariable %6 Input
|
||||||
%9 = OpTypeFunction %2
|
%9 = OpTypeFunction %2
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
@fragment
|
@fragment
|
||||||
fn main(@builtin(view_index) view_index: i32) {
|
fn main(@builtin(view_index) view_index: u32) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -674,7 +674,7 @@ impl Player {
|
|||||||
depth_stencil: desc.depth_stencil,
|
depth_stencil: desc.depth_stencil,
|
||||||
multisample: desc.multisample,
|
multisample: desc.multisample,
|
||||||
fragment,
|
fragment,
|
||||||
multiview: desc.multiview,
|
multiview_mask: desc.multiview_mask,
|
||||||
cache: desc.cache.map(|id| self.resolve_pipeline_cache_id(id)),
|
cache: desc.cache.map(|id| self.resolve_pipeline_cache_id(id)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -851,6 +851,7 @@ impl Player {
|
|||||||
depth_stencil_attachment,
|
depth_stencil_attachment,
|
||||||
timestamp_writes,
|
timestamp_writes,
|
||||||
occlusion_query_set,
|
occlusion_query_set,
|
||||||
|
multiview_mask,
|
||||||
} => Command::RunRenderPass {
|
} => Command::RunRenderPass {
|
||||||
pass: self.resolve_render_pass(pass),
|
pass: self.resolve_render_pass(pass),
|
||||||
color_attachments: self.resolve_color_attachments(color_attachments),
|
color_attachments: self.resolve_color_attachments(color_attachments),
|
||||||
@ -858,6 +859,7 @@ impl Player {
|
|||||||
.map(|att| self.resolve_depth_stencil_attachment(att)),
|
.map(|att| self.resolve_depth_stencil_attachment(att)),
|
||||||
timestamp_writes: timestamp_writes.map(|tw| self.resolve_pass_timestamp_writes(tw)),
|
timestamp_writes: timestamp_writes.map(|tw| self.resolve_pass_timestamp_writes(tw)),
|
||||||
occlusion_query_set: occlusion_query_set.map(|qs| self.resolve_query_set_id(qs)),
|
occlusion_query_set: occlusion_query_set.map(|qs| self.resolve_query_set_id(qs)),
|
||||||
|
multiview_mask,
|
||||||
},
|
},
|
||||||
Command::BuildAccelerationStructures { blas, tlas } => {
|
Command::BuildAccelerationStructures { blas, tlas } => {
|
||||||
Command::BuildAccelerationStructures {
|
Command::BuildAccelerationStructures {
|
||||||
|
|||||||
@ -207,7 +207,7 @@ async fn binding_array_sampled_textures(ctx: TestingContext, partially_bound: bo
|
|||||||
depth_stencil: None,
|
depth_stencil: None,
|
||||||
multisample: MultisampleState::default(),
|
multisample: MultisampleState::default(),
|
||||||
cache: None,
|
cache: None,
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut encoder = ctx
|
let mut encoder = ctx
|
||||||
@ -228,6 +228,7 @@ async fn binding_array_sampled_textures(ctx: TestingContext, partially_bound: bo
|
|||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
render_pass.set_pipeline(&pipeline);
|
render_pass.set_pipeline(&pipeline);
|
||||||
render_pass.set_bind_group(0, &bind_group, &[]);
|
render_pass.set_bind_group(0, &bind_group, &[]);
|
||||||
|
|||||||
@ -43,7 +43,7 @@ async fn clip_distances(ctx: TestingContext) {
|
|||||||
write_mask: wgpu::ColorWrites::ALL,
|
write_mask: wgpu::ColorWrites::ALL,
|
||||||
})],
|
})],
|
||||||
}),
|
}),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -87,6 +87,7 @@ async fn clip_distances(ctx: TestingContext) {
|
|||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
rpass.set_pipeline(&pipeline);
|
rpass.set_pipeline(&pipeline);
|
||||||
rpass.draw(0..3, 0..1);
|
rpass.draw(0..3, 0..1);
|
||||||
|
|||||||
@ -346,6 +346,7 @@ static DEVICE_DESTROY_THEN_MORE: GpuTestConfiguration = GpuTestConfiguration::ne
|
|||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
drop(pass);
|
drop(pass);
|
||||||
ctx.queue.submit([encoder_for_render_pass.finish()]);
|
ctx.queue.submit([encoder_for_render_pass.finish()]);
|
||||||
@ -458,7 +459,7 @@ static DEVICE_DESTROY_THEN_MORE: GpuTestConfiguration = GpuTestConfiguration::ne
|
|||||||
depth_stencil: None,
|
depth_stencil: None,
|
||||||
multisample: wgpu::MultisampleState::default(),
|
multisample: wgpu::MultisampleState::default(),
|
||||||
fragment: None,
|
fragment: None,
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -616,7 +617,7 @@ static DIFFERENT_BGL_ORDER_BW_SHADER_AND_API: GpuTestConfiguration = GpuTestConf
|
|||||||
primitive: wgpu::PrimitiveState::default(),
|
primitive: wgpu::PrimitiveState::default(),
|
||||||
depth_stencil: None,
|
depth_stencil: None,
|
||||||
multisample: wgpu::MultisampleState::default(),
|
multisample: wgpu::MultisampleState::default(),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -207,7 +207,7 @@ async fn run_test(ctx: TestingContext, test_data: TestData, expect_noop: bool) {
|
|||||||
write_mask: wgpu::ColorWrites::ALL,
|
write_mask: wgpu::ColorWrites::ALL,
|
||||||
})],
|
})],
|
||||||
}),
|
}),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
};
|
};
|
||||||
let pipeline = ctx.device.create_render_pipeline(&pipeline_desc);
|
let pipeline = ctx.device.create_render_pipeline(&pipeline_desc);
|
||||||
@ -272,6 +272,7 @@ async fn run_test(ctx: TestingContext, test_data: TestData, expect_noop: bool) {
|
|||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
rpass.set_pipeline(&pipeline);
|
rpass.set_pipeline(&pipeline);
|
||||||
@ -697,7 +698,7 @@ async fn indirect_buffer_offsets(ctx: TestingContext) {
|
|||||||
write_mask: wgpu::ColorWrites::ALL,
|
write_mask: wgpu::ColorWrites::ALL,
|
||||||
})],
|
})],
|
||||||
}),
|
}),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
};
|
};
|
||||||
let pipeline = ctx.device.create_render_pipeline(&pipeline_desc);
|
let pipeline = ctx.device.create_render_pipeline(&pipeline_desc);
|
||||||
@ -747,6 +748,7 @@ async fn indirect_buffer_offsets(ctx: TestingContext) {
|
|||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
rpass.set_pipeline(&pipeline);
|
rpass.set_pipeline(&pipeline);
|
||||||
|
|||||||
@ -96,7 +96,7 @@ async fn dual_source_blending_disabled(ctx: TestingContext) {
|
|||||||
primitive: wgpu::PrimitiveState::default(),
|
primitive: wgpu::PrimitiveState::default(),
|
||||||
depth_stencil: None,
|
depth_stencil: None,
|
||||||
multisample: wgpu::MultisampleState::default(),
|
multisample: wgpu::MultisampleState::default(),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@ -159,7 +159,7 @@ async fn dual_source_blending_enabled(ctx: TestingContext) {
|
|||||||
primitive: wgpu::PrimitiveState::default(),
|
primitive: wgpu::PrimitiveState::default(),
|
||||||
depth_stencil: None,
|
depth_stencil: None,
|
||||||
multisample: wgpu::MultisampleState::default(),
|
multisample: wgpu::MultisampleState::default(),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -77,6 +77,7 @@ static DROP_ENCODER_AFTER_ERROR: GpuTestConfiguration = GpuTestConfiguration::ne
|
|||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
// This viewport is invalid because it has negative size.
|
// This viewport is invalid because it has negative size.
|
||||||
|
|||||||
@ -36,6 +36,7 @@ mod instance;
|
|||||||
mod life_cycle;
|
mod life_cycle;
|
||||||
mod mem_leaks;
|
mod mem_leaks;
|
||||||
mod mesh_shader;
|
mod mesh_shader;
|
||||||
|
mod multiview;
|
||||||
mod occlusion_query;
|
mod occlusion_query;
|
||||||
mod oob_indexing;
|
mod oob_indexing;
|
||||||
mod oom;
|
mod oom;
|
||||||
@ -99,6 +100,7 @@ fn all_tests() -> Vec<wgpu_test::GpuTestInitializer> {
|
|||||||
life_cycle::all_tests(&mut tests);
|
life_cycle::all_tests(&mut tests);
|
||||||
mem_leaks::all_tests(&mut tests);
|
mem_leaks::all_tests(&mut tests);
|
||||||
mesh_shader::all_tests(&mut tests);
|
mesh_shader::all_tests(&mut tests);
|
||||||
|
multiview::all_tests(&mut tests);
|
||||||
occlusion_query::all_tests(&mut tests);
|
occlusion_query::all_tests(&mut tests);
|
||||||
oob_indexing::all_tests(&mut tests);
|
oob_indexing::all_tests(&mut tests);
|
||||||
oom::all_tests(&mut tests);
|
oom::all_tests(&mut tests);
|
||||||
|
|||||||
@ -126,7 +126,7 @@ async fn draw_test_with_reports(
|
|||||||
write_mask: wgpu::ColorWrites::ALL,
|
write_mask: wgpu::ColorWrites::ALL,
|
||||||
})],
|
})],
|
||||||
}),
|
}),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -207,6 +207,7 @@ async fn draw_test_with_reports(
|
|||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
rpass.set_pipeline(&pipeline);
|
rpass.set_pipeline(&pipeline);
|
||||||
|
|||||||
@ -242,6 +242,7 @@ fn mesh_pipeline_build(ctx: &TestingContext, info: MeshPipelineTestInfo) {
|
|||||||
}),
|
}),
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
pass.set_pipeline(&pipeline);
|
pass.set_pipeline(&pipeline);
|
||||||
pass.draw_mesh_tasks(1, 1, 1);
|
pass.draw_mesh_tasks(1, 1, 1);
|
||||||
@ -348,6 +349,7 @@ fn mesh_draw(ctx: &TestingContext, draw_type: DrawType) {
|
|||||||
}),
|
}),
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
pass.set_pipeline(&pipeline);
|
pass.set_pipeline(&pipeline);
|
||||||
match draw_type {
|
match draw_type {
|
||||||
|
|||||||
193
tests/tests/wgpu-gpu/multiview/mod.rs
Normal file
193
tests/tests/wgpu-gpu/multiview/mod.rs
Normal file
@ -0,0 +1,193 @@
|
|||||||
|
use std::num::NonZero;
|
||||||
|
|
||||||
|
use wgpu::{Features, Limits};
|
||||||
|
use wgpu_test::{
|
||||||
|
gpu_test, GpuTestConfiguration, GpuTestInitializer, TestParameters, TestingContext,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn all_tests(vec: &mut Vec<GpuTestInitializer>) {
|
||||||
|
vec.push(DRAW_MULTIVIEW_SINGLE);
|
||||||
|
vec.push(DRAW_MULTIVIEW);
|
||||||
|
vec.push(DRAW_MULTIVIEW_NONCONTIGUOUS);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[gpu_test]
|
||||||
|
static DRAW_MULTIVIEW_SINGLE: GpuTestConfiguration = GpuTestConfiguration::new()
|
||||||
|
.parameters(
|
||||||
|
TestParameters::default()
|
||||||
|
.features(Features::MULTIVIEW)
|
||||||
|
.limits(Limits {
|
||||||
|
max_multiview_view_count: 1,
|
||||||
|
..Limits::defaults()
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.run_async(|ctx| run_test(ctx, 0b1));
|
||||||
|
|
||||||
|
#[gpu_test]
|
||||||
|
static DRAW_MULTIVIEW: GpuTestConfiguration = GpuTestConfiguration::new()
|
||||||
|
.parameters(
|
||||||
|
TestParameters::default()
|
||||||
|
.features(Features::MULTIVIEW)
|
||||||
|
.limits(Limits {
|
||||||
|
max_multiview_view_count: 2,
|
||||||
|
..Limits::defaults()
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.run_async(|ctx| run_test(ctx, 0b11));
|
||||||
|
|
||||||
|
#[gpu_test]
|
||||||
|
static DRAW_MULTIVIEW_NONCONTIGUOUS: GpuTestConfiguration = GpuTestConfiguration::new()
|
||||||
|
.parameters(
|
||||||
|
TestParameters::default()
|
||||||
|
.features(Features::MULTIVIEW | Features::SELECTIVE_MULTIVIEW)
|
||||||
|
.limits(Limits {
|
||||||
|
max_multiview_view_count: 4,
|
||||||
|
..Limits::defaults()
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.run_async(|ctx| run_test(ctx, 0b1001));
|
||||||
|
|
||||||
|
async fn run_test(ctx: TestingContext, layer_mask: u32) {
|
||||||
|
let num_layers = 32 - layer_mask.leading_zeros();
|
||||||
|
|
||||||
|
let shader_src = include_str!("shader.wgsl");
|
||||||
|
|
||||||
|
let shader = ctx
|
||||||
|
.device
|
||||||
|
.create_shader_module(wgpu::ShaderModuleDescriptor {
|
||||||
|
label: None,
|
||||||
|
source: wgpu::ShaderSource::Wgsl(shader_src.into()),
|
||||||
|
});
|
||||||
|
|
||||||
|
let pipeline_desc = wgpu::RenderPipelineDescriptor {
|
||||||
|
label: None,
|
||||||
|
vertex: wgpu::VertexState {
|
||||||
|
buffers: &[],
|
||||||
|
module: &shader,
|
||||||
|
entry_point: Some("vs_main"),
|
||||||
|
compilation_options: Default::default(),
|
||||||
|
},
|
||||||
|
primitive: wgpu::PrimitiveState::default(),
|
||||||
|
fragment: Some(wgpu::FragmentState {
|
||||||
|
module: &shader,
|
||||||
|
entry_point: Some("fs_main"),
|
||||||
|
compilation_options: Default::default(),
|
||||||
|
targets: &[Some(wgpu::ColorTargetState {
|
||||||
|
format: wgpu::TextureFormat::R8Unorm,
|
||||||
|
blend: None,
|
||||||
|
write_mask: wgpu::ColorWrites::ALL,
|
||||||
|
})],
|
||||||
|
}),
|
||||||
|
multiview_mask: NonZero::new(layer_mask),
|
||||||
|
multisample: Default::default(),
|
||||||
|
layout: None,
|
||||||
|
depth_stencil: None,
|
||||||
|
cache: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
const TEXTURE_SIZE: u32 = 256;
|
||||||
|
let pipeline = ctx.device.create_render_pipeline(&pipeline_desc);
|
||||||
|
let texture = ctx.device.create_texture(&wgpu::TextureDescriptor {
|
||||||
|
label: None,
|
||||||
|
size: wgpu::Extent3d {
|
||||||
|
width: TEXTURE_SIZE,
|
||||||
|
height: TEXTURE_SIZE,
|
||||||
|
depth_or_array_layers: 32 - layer_mask.leading_zeros(),
|
||||||
|
},
|
||||||
|
mip_level_count: 1,
|
||||||
|
sample_count: 1,
|
||||||
|
dimension: wgpu::TextureDimension::D2,
|
||||||
|
format: wgpu::TextureFormat::R8Unorm,
|
||||||
|
usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::COPY_SRC,
|
||||||
|
view_formats: &[],
|
||||||
|
});
|
||||||
|
let entire_texture_view = texture.create_view(&wgpu::TextureViewDescriptor {
|
||||||
|
label: None,
|
||||||
|
format: Some(wgpu::TextureFormat::R8Unorm),
|
||||||
|
dimension: Some(wgpu::TextureViewDimension::D2Array),
|
||||||
|
usage: Some(wgpu::TextureUsages::RENDER_ATTACHMENT),
|
||||||
|
aspect: wgpu::TextureAspect::All,
|
||||||
|
base_mip_level: 0,
|
||||||
|
mip_level_count: None,
|
||||||
|
base_array_layer: 0,
|
||||||
|
array_layer_count: Some(num_layers),
|
||||||
|
});
|
||||||
|
let readback_buffer = ctx.device.create_buffer(&wgpu::BufferDescriptor {
|
||||||
|
label: None,
|
||||||
|
size: TEXTURE_SIZE as u64 * TEXTURE_SIZE as u64 * num_layers as u64,
|
||||||
|
usage: wgpu::BufferUsages::COPY_DST | wgpu::BufferUsages::MAP_READ,
|
||||||
|
mapped_at_creation: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
let clear_color = 0.0;
|
||||||
|
|
||||||
|
let mut encoder = ctx
|
||||||
|
.device
|
||||||
|
.create_command_encoder(&wgpu::CommandEncoderDescriptor::default());
|
||||||
|
{
|
||||||
|
let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||||
|
label: None,
|
||||||
|
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
|
||||||
|
view: &entire_texture_view,
|
||||||
|
depth_slice: None,
|
||||||
|
resolve_target: None,
|
||||||
|
ops: wgpu::Operations {
|
||||||
|
load: wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT),
|
||||||
|
store: wgpu::StoreOp::Store,
|
||||||
|
},
|
||||||
|
})],
|
||||||
|
depth_stencil_attachment: None,
|
||||||
|
timestamp_writes: None,
|
||||||
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: NonZero::new(layer_mask),
|
||||||
|
});
|
||||||
|
rpass.set_pipeline(&pipeline);
|
||||||
|
rpass.draw(0..6, 0..1);
|
||||||
|
}
|
||||||
|
encoder.copy_texture_to_buffer(
|
||||||
|
wgpu::TexelCopyTextureInfo {
|
||||||
|
texture: &texture,
|
||||||
|
mip_level: 0,
|
||||||
|
origin: wgpu::Origin3d { x: 0, y: 0, z: 0 },
|
||||||
|
aspect: wgpu::TextureAspect::All,
|
||||||
|
},
|
||||||
|
wgpu::TexelCopyBufferInfo {
|
||||||
|
buffer: &readback_buffer,
|
||||||
|
layout: wgpu::TexelCopyBufferLayout {
|
||||||
|
offset: 0,
|
||||||
|
bytes_per_row: Some(TEXTURE_SIZE),
|
||||||
|
rows_per_image: Some(TEXTURE_SIZE),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wgpu::Extent3d {
|
||||||
|
width: TEXTURE_SIZE,
|
||||||
|
height: TEXTURE_SIZE,
|
||||||
|
depth_or_array_layers: num_layers,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
ctx.queue.submit([encoder.finish()]);
|
||||||
|
|
||||||
|
let slice = readback_buffer.slice(..);
|
||||||
|
slice.map_async(wgpu::MapMode::Read, |_| ());
|
||||||
|
|
||||||
|
ctx.async_poll(wgpu::PollType::wait_indefinitely())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let data = slice.get_mapped_range();
|
||||||
|
let each_texture_size = (TEXTURE_SIZE * TEXTURE_SIZE) as usize;
|
||||||
|
assert_eq!(data.len(), each_texture_size * num_layers as usize);
|
||||||
|
for view_idx in 0..num_layers as usize {
|
||||||
|
let target_value = if (layer_mask & (1 << view_idx)) != 0 {
|
||||||
|
(32 + 64 * view_idx) as u8
|
||||||
|
} else {
|
||||||
|
(clear_color * 255.0) as u8
|
||||||
|
};
|
||||||
|
// Some metal devices automatically initialize stuff to 255, so I decided to use 128 instead of that
|
||||||
|
let failed_value = data[each_texture_size * view_idx..each_texture_size * (view_idx + 1)]
|
||||||
|
.iter()
|
||||||
|
.copied()
|
||||||
|
.find(|b| b.abs_diff(target_value) > 1);
|
||||||
|
assert_eq!(failed_value, None, "Expected {target_value}");
|
||||||
|
}
|
||||||
|
}
|
||||||
11
tests/tests/wgpu-gpu/multiview/shader.wgsl
Normal file
11
tests/tests/wgpu-gpu/multiview/shader.wgsl
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
const triangles = array<vec2f, 3>(vec2f(-1.0, -1.0), vec2f(3.0, -1.0), vec2f(-1.0, 3.0));
|
||||||
|
|
||||||
|
@vertex
|
||||||
|
fn vs_main(@builtin(vertex_index) vertex_index: u32) -> @builtin(position) vec4f {
|
||||||
|
return vec4f(triangles[vertex_index], 0.0, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@fragment
|
||||||
|
fn fs_main(@builtin(view_index) view_index: u32) -> @location(0) vec4f {
|
||||||
|
return vec4f(f32(view_index) * 0.25 + 0.125);
|
||||||
|
}
|
||||||
@ -56,7 +56,7 @@ static OCCLUSION_QUERY: GpuTestConfiguration = GpuTestConfiguration::new()
|
|||||||
bias: wgpu::DepthBiasState::default(),
|
bias: wgpu::DepthBiasState::default(),
|
||||||
}),
|
}),
|
||||||
multisample: wgpu::MultisampleState::default(),
|
multisample: wgpu::MultisampleState::default(),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -84,6 +84,7 @@ static OCCLUSION_QUERY: GpuTestConfiguration = GpuTestConfiguration::new()
|
|||||||
}),
|
}),
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: Some(&query_set),
|
occlusion_query_set: Some(&query_set),
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
render_pass.set_pipeline(&pipeline);
|
render_pass.set_pipeline(&pipeline);
|
||||||
|
|
||||||
|
|||||||
@ -129,7 +129,7 @@ static RENDER_PIPELINE_DEFAULT_LAYOUT_BAD_MODULE: GpuTestConfiguration =
|
|||||||
depth_stencil: None,
|
depth_stencil: None,
|
||||||
multisample: Default::default(),
|
multisample: Default::default(),
|
||||||
fragment: None,
|
fragment: None,
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -182,7 +182,7 @@ static RENDER_PIPELINE_DEFAULT_LAYOUT_BAD_BGL_INDEX: GpuTestConfiguration =
|
|||||||
write_mask: wgpu::ColorWrites::ALL,
|
write_mask: wgpu::ColorWrites::ALL,
|
||||||
})],
|
})],
|
||||||
}),
|
}),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -223,7 +223,7 @@ static NO_TARGETLESS_RENDER: GpuTestConfiguration = GpuTestConfiguration::new()
|
|||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
fragment: None,
|
fragment: None,
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -47,7 +47,7 @@ fn test_planar_texture_creation_sampling(
|
|||||||
},
|
},
|
||||||
depth_stencil: None,
|
depth_stencil: None,
|
||||||
multisample: wgpu::MultisampleState::default(),
|
multisample: wgpu::MultisampleState::default(),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -101,6 +101,7 @@ fn test_planar_texture_creation_sampling(
|
|||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
rpass.set_pipeline(&pipeline);
|
rpass.set_pipeline(&pipeline);
|
||||||
rpass.set_bind_group(0, &bind_group, &[]);
|
rpass.set_bind_group(0, &bind_group, &[]);
|
||||||
@ -142,7 +143,7 @@ fn test_planar_texture_rendering(
|
|||||||
},
|
},
|
||||||
depth_stencil: None,
|
depth_stencil: None,
|
||||||
multisample: wgpu::MultisampleState::default(),
|
multisample: wgpu::MultisampleState::default(),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -170,7 +171,7 @@ fn test_planar_texture_rendering(
|
|||||||
},
|
},
|
||||||
depth_stencil: None,
|
depth_stencil: None,
|
||||||
multisample: wgpu::MultisampleState::default(),
|
multisample: wgpu::MultisampleState::default(),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -190,6 +191,7 @@ fn test_planar_texture_rendering(
|
|||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
rpass.set_pipeline(&y_pipeline);
|
rpass.set_pipeline(&y_pipeline);
|
||||||
rpass.draw(0..3, 0..1);
|
rpass.draw(0..3, 0..1);
|
||||||
@ -206,6 +208,7 @@ fn test_planar_texture_rendering(
|
|||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
rpass.set_pipeline(&uv_pipeline);
|
rpass.set_pipeline(&uv_pipeline);
|
||||||
rpass.draw(0..3, 0..1);
|
rpass.draw(0..3, 0..1);
|
||||||
|
|||||||
@ -301,7 +301,7 @@ async fn render_pass_test(ctx: &TestingContext, use_render_bundle: bool) {
|
|||||||
},
|
},
|
||||||
depth_stencil: None,
|
depth_stencil: None,
|
||||||
multisample: MultisampleState::default(),
|
multisample: MultisampleState::default(),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -123,7 +123,7 @@ async fn multi_stage_data_binding_test(ctx: TestingContext) {
|
|||||||
primitive: wgpu::PrimitiveState::default(),
|
primitive: wgpu::PrimitiveState::default(),
|
||||||
depth_stencil: None,
|
depth_stencil: None,
|
||||||
multisample: wgpu::MultisampleState::default(),
|
multisample: wgpu::MultisampleState::default(),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -166,6 +166,7 @@ async fn multi_stage_data_binding_test(ctx: TestingContext) {
|
|||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
rpass.set_pipeline(&pipeline);
|
rpass.set_pipeline(&pipeline);
|
||||||
|
|||||||
@ -84,7 +84,7 @@ static PASS_RESET_VERTEX_BUFFER: GpuTestConfiguration = GpuTestConfiguration::ne
|
|||||||
write_mask: ColorWrites::all(),
|
write_mask: ColorWrites::all(),
|
||||||
})],
|
})],
|
||||||
}),
|
}),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -116,7 +116,7 @@ static PASS_RESET_VERTEX_BUFFER: GpuTestConfiguration = GpuTestConfiguration::ne
|
|||||||
write_mask: ColorWrites::all(),
|
write_mask: ColorWrites::all(),
|
||||||
})],
|
})],
|
||||||
}),
|
}),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -156,6 +156,7 @@ static PASS_RESET_VERTEX_BUFFER: GpuTestConfiguration = GpuTestConfiguration::ne
|
|||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
double_rpass.set_pipeline(&double_pipeline);
|
double_rpass.set_pipeline(&double_pipeline);
|
||||||
@ -192,6 +193,7 @@ static PASS_RESET_VERTEX_BUFFER: GpuTestConfiguration = GpuTestConfiguration::ne
|
|||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
single_rpass.set_pipeline(&single_pipeline);
|
single_rpass.set_pipeline(&single_pipeline);
|
||||||
|
|||||||
@ -68,7 +68,7 @@ async fn test_impl(ctx: &TestingContext) {
|
|||||||
write_mask: wgpu::ColorWrites::ALL,
|
write_mask: wgpu::ColorWrites::ALL,
|
||||||
})],
|
})],
|
||||||
}),
|
}),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -98,6 +98,7 @@ async fn test_impl(ctx: &TestingContext) {
|
|||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
render_pass.set_pipeline(&pipeline);
|
render_pass.set_pipeline(&pipeline);
|
||||||
render_pass.draw(0..3, 0..1);
|
render_pass.draw(0..3, 0..1);
|
||||||
|
|||||||
@ -68,7 +68,7 @@ async fn test_impl(ctx: &TestingContext) {
|
|||||||
write_mask: wgpu::ColorWrites::ALL,
|
write_mask: wgpu::ColorWrites::ALL,
|
||||||
})],
|
})],
|
||||||
}),
|
}),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -98,6 +98,7 @@ async fn test_impl(ctx: &TestingContext) {
|
|||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
render_pass.set_pipeline(&pipeline);
|
render_pass.set_pipeline(&pipeline);
|
||||||
render_pass.draw(0..3, 0..1);
|
render_pass.draw(0..3, 0..1);
|
||||||
|
|||||||
@ -53,7 +53,7 @@ static ALLOW_INPUT_NOT_CONSUMED: GpuTestConfiguration = GpuTestConfiguration::ne
|
|||||||
write_mask: ColorWrites::all(),
|
write_mask: ColorWrites::all(),
|
||||||
})],
|
})],
|
||||||
}),
|
}),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -91,6 +91,7 @@ async fn render_pass_resource_ownership(ctx: TestingContext) {
|
|||||||
}),
|
}),
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: Some(&occlusion_query_set),
|
occlusion_query_set: Some(&occlusion_query_set),
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Drop render pass attachments right away.
|
// Drop render pass attachments right away.
|
||||||
@ -548,7 +549,7 @@ fn resource_setup(ctx: &TestingContext) -> ResourceSetup {
|
|||||||
mask: !0,
|
mask: !0,
|
||||||
alpha_to_coverage_enabled: false,
|
alpha_to_coverage_enabled: false,
|
||||||
},
|
},
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -106,7 +106,7 @@ async fn run_test(
|
|||||||
write_mask: wgpu::ColorWrites::ALL,
|
write_mask: wgpu::ColorWrites::ALL,
|
||||||
})],
|
})],
|
||||||
}),
|
}),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
};
|
};
|
||||||
let pipeline = ctx.device.create_render_pipeline(&pipeline_desc);
|
let pipeline = ctx.device.create_render_pipeline(&pipeline_desc);
|
||||||
@ -203,6 +203,7 @@ async fn run_test(
|
|||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
rpass.set_pipeline(&pipeline);
|
rpass.set_pipeline(&pipeline);
|
||||||
rpass.set_vertex_buffer(0, vertex_buffer.slice(..));
|
rpass.set_vertex_buffer(0, vertex_buffer.slice(..));
|
||||||
@ -318,7 +319,7 @@ async fn run_test_3d(ctx: TestingContext) {
|
|||||||
write_mask: wgpu::ColorWrites::ALL,
|
write_mask: wgpu::ColorWrites::ALL,
|
||||||
})],
|
})],
|
||||||
}),
|
}),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
};
|
};
|
||||||
let pipeline = ctx.device.create_render_pipeline(&pipeline_desc);
|
let pipeline = ctx.device.create_render_pipeline(&pipeline_desc);
|
||||||
@ -386,6 +387,7 @@ async fn run_test_3d(ctx: TestingContext) {
|
|||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
rpass.set_pipeline(&pipeline);
|
rpass.set_pipeline(&pipeline);
|
||||||
rpass.set_vertex_buffer(0, vertex_buffer.slice(..));
|
rpass.set_vertex_buffer(0, vertex_buffer.slice(..));
|
||||||
|
|||||||
@ -69,7 +69,7 @@ async fn scissor_test_impl(
|
|||||||
write_mask: wgpu::ColorWrites::ALL,
|
write_mask: wgpu::ColorWrites::ALL,
|
||||||
})],
|
})],
|
||||||
}),
|
}),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -98,6 +98,7 @@ async fn scissor_test_impl(
|
|||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
render_pass.set_pipeline(&pipeline);
|
render_pass.set_pipeline(&pipeline);
|
||||||
render_pass.set_scissor_rect(
|
render_pass.set_scissor_rect(
|
||||||
|
|||||||
@ -95,7 +95,7 @@ async fn barycentric(ctx: TestingContext) {
|
|||||||
write_mask: wgpu::ColorWrites::ALL,
|
write_mask: wgpu::ColorWrites::ALL,
|
||||||
})],
|
})],
|
||||||
}),
|
}),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -138,6 +138,7 @@ async fn barycentric(ctx: TestingContext) {
|
|||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
rpass.set_pipeline(&pipeline);
|
rpass.set_pipeline(&pipeline);
|
||||||
|
|||||||
@ -150,7 +150,7 @@ async fn pulling_common(
|
|||||||
write_mask: wgpu::ColorWrites::ALL,
|
write_mask: wgpu::ColorWrites::ALL,
|
||||||
})],
|
})],
|
||||||
}),
|
}),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -193,6 +193,7 @@ async fn pulling_common(
|
|||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
rpass.set_pipeline(&pipeline);
|
rpass.set_pipeline(&pipeline);
|
||||||
|
|||||||
@ -113,7 +113,7 @@ async fn reinterpret(
|
|||||||
},
|
},
|
||||||
depth_stencil: None,
|
depth_stencil: None,
|
||||||
multisample: wgpu::MultisampleState::default(),
|
multisample: wgpu::MultisampleState::default(),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
let bind_group = ctx.device.create_bind_group(&wgpu::BindGroupDescriptor {
|
let bind_group = ctx.device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||||
@ -151,6 +151,7 @@ async fn reinterpret(
|
|||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
rpass.set_pipeline(&pipeline);
|
rpass.set_pipeline(&pipeline);
|
||||||
rpass.set_bind_group(0, &bind_group, &[]);
|
rpass.set_bind_group(0, &bind_group, &[]);
|
||||||
|
|||||||
@ -64,7 +64,7 @@ static RESOLVE_WITH_TRANSIENT: GpuTestConfiguration = GpuTestConfiguration::new(
|
|||||||
write_mask: wgpu::ColorWrites::ALL,
|
write_mask: wgpu::ColorWrites::ALL,
|
||||||
})],
|
})],
|
||||||
}),
|
}),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
};
|
};
|
||||||
let pipeline = ctx.device.create_render_pipeline(&pipeline_desc);
|
let pipeline = ctx.device.create_render_pipeline(&pipeline_desc);
|
||||||
@ -119,6 +119,7 @@ static RESOLVE_WITH_TRANSIENT: GpuTestConfiguration = GpuTestConfiguration::new(
|
|||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
rpass.set_pipeline(&pipeline);
|
rpass.set_pipeline(&pipeline);
|
||||||
|
|||||||
@ -314,7 +314,7 @@ async fn vertex_formats_common(ctx: TestingContext, tests: &[Test<'_>]) {
|
|||||||
write_mask: wgpu::ColorWrites::ALL,
|
write_mask: wgpu::ColorWrites::ALL,
|
||||||
})],
|
})],
|
||||||
}),
|
}),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -360,6 +360,7 @@ async fn vertex_formats_common(ctx: TestingContext, tests: &[Test<'_>]) {
|
|||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
rpass.set_vertex_buffer(0, buffer_input.slice(..));
|
rpass.set_vertex_buffer(0, buffer_input.slice(..));
|
||||||
|
|||||||
@ -259,7 +259,7 @@ async fn vertex_index_common(ctx: TestingContext) {
|
|||||||
write_mask: wgpu::ColorWrites::ALL,
|
write_mask: wgpu::ColorWrites::ALL,
|
||||||
})],
|
})],
|
||||||
}),
|
}),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
};
|
};
|
||||||
let builtin_pipeline = ctx.device.create_render_pipeline(&pipeline_desc);
|
let builtin_pipeline = ctx.device.create_render_pipeline(&pipeline_desc);
|
||||||
@ -366,6 +366,7 @@ async fn vertex_index_common(ctx: TestingContext) {
|
|||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|||||||
@ -99,7 +99,7 @@ async fn set_array_stride_to_0(ctx: TestingContext) {
|
|||||||
write_mask: wgpu::ColorWrites::ALL,
|
write_mask: wgpu::ColorWrites::ALL,
|
||||||
})],
|
})],
|
||||||
}),
|
}),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
};
|
};
|
||||||
let mut first_pipeline_desc = pipeline_desc.clone();
|
let mut first_pipeline_desc = pipeline_desc.clone();
|
||||||
@ -148,6 +148,7 @@ async fn set_array_stride_to_0(ctx: TestingContext) {
|
|||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
// The D3D12 backend used to not set the stride of vertex buffers if it was 0.
|
// The D3D12 backend used to not set the stride of vertex buffers if it was 0.
|
||||||
|
|||||||
@ -173,6 +173,7 @@ impl<'ctx> TestCase<'ctx> {
|
|||||||
}),
|
}),
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
ctx.queue.submit([encoder.finish()]);
|
ctx.queue.submit([encoder.finish()]);
|
||||||
} else {
|
} else {
|
||||||
@ -259,6 +260,7 @@ impl<'ctx> TestCase<'ctx> {
|
|||||||
),
|
),
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -284,6 +286,7 @@ impl<'ctx> TestCase<'ctx> {
|
|||||||
),
|
),
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -309,6 +312,7 @@ impl<'ctx> TestCase<'ctx> {
|
|||||||
),
|
),
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -652,7 +652,7 @@ var tex: texture_external;
|
|||||||
write_mask: ColorWrites::ALL,
|
write_mask: ColorWrites::ALL,
|
||||||
})],
|
})],
|
||||||
}),
|
}),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -685,6 +685,7 @@ var tex: texture_external;
|
|||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
pass.set_pipeline(&pipeline);
|
pass.set_pipeline(&pipeline);
|
||||||
|
|||||||
@ -58,7 +58,7 @@ fn frag() -> @location({}) vec4f {{
|
|||||||
primitive: Default::default(),
|
primitive: Default::default(),
|
||||||
depth_stencil: None,
|
depth_stencil: None,
|
||||||
multisample: Default::default(),
|
multisample: Default::default(),
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|||||||
@ -674,6 +674,7 @@ fn transient_invalid_storeop() {
|
|||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
drop(invalid_render_pass);
|
drop(invalid_render_pass);
|
||||||
|
|||||||
@ -218,7 +218,7 @@ impl RenderBundleEncoder {
|
|||||||
}
|
}
|
||||||
sc
|
sc
|
||||||
},
|
},
|
||||||
multiview: desc.multiview,
|
multiview_mask: desc.multiview,
|
||||||
},
|
},
|
||||||
|
|
||||||
is_depth_read_only,
|
is_depth_read_only,
|
||||||
@ -239,7 +239,7 @@ impl RenderBundleEncoder {
|
|||||||
depth_stencil: None,
|
depth_stencil: None,
|
||||||
},
|
},
|
||||||
sample_count: 0,
|
sample_count: 0,
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
},
|
},
|
||||||
is_depth_read_only: false,
|
is_depth_read_only: false,
|
||||||
is_stencil_read_only: false,
|
is_stencil_read_only: false,
|
||||||
|
|||||||
@ -532,7 +532,7 @@ fn clear_texture_via_render_passes(
|
|||||||
sample_count: dst_texture.desc.sample_count,
|
sample_count: dst_texture.desc.sample_count,
|
||||||
color_attachments,
|
color_attachments,
|
||||||
depth_stencil_attachment,
|
depth_stencil_attachment,
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
})
|
})
|
||||||
|
|||||||
@ -71,6 +71,13 @@ pub enum DrawError {
|
|||||||
limit: u32,
|
limit: u32,
|
||||||
max_total: u32,
|
max_total: u32,
|
||||||
},
|
},
|
||||||
|
#[error(
|
||||||
|
"Mesh shader calls in multiview render passes require enabling the `EXPERIMENTAL_MESH_SHADER_MULTIVIEW` feature, and the highest bit ({highest_view_index}) in the multiview mask must be <= `Limits::max_multiview_view_count` ({max_multiviews})"
|
||||||
|
)]
|
||||||
|
MeshPipelineMultiviewLimitsViolated {
|
||||||
|
highest_view_index: u32,
|
||||||
|
max_multiviews: u32,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WebGpuError for DrawError {
|
impl WebGpuError for DrawError {
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
use core::convert::Infallible;
|
use core::{convert::Infallible, num::NonZero};
|
||||||
|
|
||||||
use alloc::{string::String, sync::Arc, vec::Vec};
|
use alloc::{string::String, sync::Arc, vec::Vec};
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
@ -171,6 +171,7 @@ pub enum Command<R: ReferenceType> {
|
|||||||
Option<crate::command::ResolvedRenderPassDepthStencilAttachment<R::TextureView>>,
|
Option<crate::command::ResolvedRenderPassDepthStencilAttachment<R::TextureView>>,
|
||||||
timestamp_writes: Option<crate::command::PassTimestampWrites<R::QuerySet>>,
|
timestamp_writes: Option<crate::command::PassTimestampWrites<R::QuerySet>>,
|
||||||
occlusion_query_set: Option<R::QuerySet>,
|
occlusion_query_set: Option<R::QuerySet>,
|
||||||
|
multiview_mask: Option<NonZero<u32>>,
|
||||||
},
|
},
|
||||||
BuildAccelerationStructures {
|
BuildAccelerationStructures {
|
||||||
blas: Vec<crate::ray_tracing::OwnedBlasBuildEntry<R>>,
|
blas: Vec<crate::ray_tracing::OwnedBlasBuildEntry<R>>,
|
||||||
|
|||||||
@ -1019,6 +1019,7 @@ impl CommandEncoder {
|
|||||||
depth_stencil_attachment,
|
depth_stencil_attachment,
|
||||||
timestamp_writes,
|
timestamp_writes,
|
||||||
occlusion_query_set,
|
occlusion_query_set,
|
||||||
|
multiview_mask,
|
||||||
} => {
|
} => {
|
||||||
api_log!(
|
api_log!(
|
||||||
"Begin encoding render pass with '{}' label",
|
"Begin encoding render pass with '{}' label",
|
||||||
@ -1031,6 +1032,7 @@ impl CommandEncoder {
|
|||||||
depth_stencil_attachment,
|
depth_stencil_attachment,
|
||||||
timestamp_writes,
|
timestamp_writes,
|
||||||
occlusion_query_set,
|
occlusion_query_set,
|
||||||
|
multiview_mask,
|
||||||
);
|
);
|
||||||
match res.as_ref() {
|
match res.as_ref() {
|
||||||
Err(err) => api_log!("Finished encoding render pass ({err:?})"),
|
Err(err) => api_log!("Finished encoding render pass ({err:?})"),
|
||||||
|
|||||||
@ -250,6 +250,8 @@ pub struct RenderPassDescriptor<'a> {
|
|||||||
pub timestamp_writes: Option<&'a PassTimestampWrites>,
|
pub timestamp_writes: Option<&'a PassTimestampWrites>,
|
||||||
/// Defines where the occlusion query results will be stored for this pass.
|
/// Defines where the occlusion query results will be stored for this pass.
|
||||||
pub occlusion_query_set: Option<id::QuerySetId>,
|
pub occlusion_query_set: Option<id::QuerySetId>,
|
||||||
|
/// The multiview array layers that will be used
|
||||||
|
pub multiview_mask: Option<NonZeroU32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Describes the attachments of a render pass.
|
/// Describes the attachments of a render pass.
|
||||||
@ -265,6 +267,8 @@ struct ArcRenderPassDescriptor<'a> {
|
|||||||
pub timestamp_writes: Option<ArcPassTimestampWrites>,
|
pub timestamp_writes: Option<ArcPassTimestampWrites>,
|
||||||
/// Defines where the occlusion query results will be stored for this pass.
|
/// Defines where the occlusion query results will be stored for this pass.
|
||||||
pub occlusion_query_set: Option<Arc<QuerySet>>,
|
pub occlusion_query_set: Option<Arc<QuerySet>>,
|
||||||
|
/// The multiview array layers that will be used
|
||||||
|
pub multiview_mask: Option<NonZeroU32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type RenderBasePass = BasePass<ArcRenderCommand, RenderPassError>;
|
pub type RenderBasePass = BasePass<ArcRenderCommand, RenderPassError>;
|
||||||
@ -292,6 +296,7 @@ pub struct RenderPass {
|
|||||||
depth_stencil_attachment: Option<ResolvedRenderPassDepthStencilAttachment<Arc<TextureView>>>,
|
depth_stencil_attachment: Option<ResolvedRenderPassDepthStencilAttachment<Arc<TextureView>>>,
|
||||||
timestamp_writes: Option<ArcPassTimestampWrites>,
|
timestamp_writes: Option<ArcPassTimestampWrites>,
|
||||||
occlusion_query_set: Option<Arc<QuerySet>>,
|
occlusion_query_set: Option<Arc<QuerySet>>,
|
||||||
|
multiview_mask: Option<NonZeroU32>,
|
||||||
|
|
||||||
// Resource binding dedupe state.
|
// Resource binding dedupe state.
|
||||||
current_bind_groups: BindGroupStateChange,
|
current_bind_groups: BindGroupStateChange,
|
||||||
@ -307,6 +312,7 @@ impl RenderPass {
|
|||||||
color_attachments,
|
color_attachments,
|
||||||
depth_stencil_attachment,
|
depth_stencil_attachment,
|
||||||
occlusion_query_set,
|
occlusion_query_set,
|
||||||
|
multiview_mask,
|
||||||
} = desc;
|
} = desc;
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
@ -316,6 +322,7 @@ impl RenderPass {
|
|||||||
depth_stencil_attachment,
|
depth_stencil_attachment,
|
||||||
timestamp_writes,
|
timestamp_writes,
|
||||||
occlusion_query_set,
|
occlusion_query_set,
|
||||||
|
multiview_mask,
|
||||||
|
|
||||||
current_bind_groups: BindGroupStateChange::new(),
|
current_bind_groups: BindGroupStateChange::new(),
|
||||||
current_pipeline: StateChange::new(),
|
current_pipeline: StateChange::new(),
|
||||||
@ -330,6 +337,7 @@ impl RenderPass {
|
|||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
current_bind_groups: BindGroupStateChange::new(),
|
current_bind_groups: BindGroupStateChange::new(),
|
||||||
current_pipeline: StateChange::new(),
|
current_pipeline: StateChange::new(),
|
||||||
}
|
}
|
||||||
@ -353,6 +361,7 @@ impl fmt::Debug for RenderPass {
|
|||||||
"push constant u32 count",
|
"push constant u32 count",
|
||||||
&self.base.push_constant_data.len(),
|
&self.base.push_constant_data.len(),
|
||||||
)
|
)
|
||||||
|
.field("multiview mask", &self.multiview_mask)
|
||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -806,6 +815,8 @@ pub enum RenderPassErrorInner {
|
|||||||
"Multiview pass texture views with more than one array layer must have D2Array dimension"
|
"Multiview pass texture views with more than one array layer must have D2Array dimension"
|
||||||
)]
|
)]
|
||||||
MultiViewDimensionMismatch,
|
MultiViewDimensionMismatch,
|
||||||
|
#[error("Multiview view count limit violated")]
|
||||||
|
TooManyMultiviewViews,
|
||||||
#[error("missing occlusion query set")]
|
#[error("missing occlusion query set")]
|
||||||
MissingOcclusionQuerySet,
|
MissingOcclusionQuerySet,
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
@ -907,6 +918,7 @@ impl WebGpuError for RenderPassError {
|
|||||||
| RenderPassErrorInner::PushConstantOutOfMemory
|
| RenderPassErrorInner::PushConstantOutOfMemory
|
||||||
| RenderPassErrorInner::MultiViewMismatch
|
| RenderPassErrorInner::MultiViewMismatch
|
||||||
| RenderPassErrorInner::MultiViewDimensionMismatch
|
| RenderPassErrorInner::MultiViewDimensionMismatch
|
||||||
|
| RenderPassErrorInner::TooManyMultiviewViews
|
||||||
| RenderPassErrorInner::MissingOcclusionQuerySet
|
| RenderPassErrorInner::MissingOcclusionQuerySet
|
||||||
| RenderPassErrorInner::PassEnded => return ErrorType::Validation,
|
| RenderPassErrorInner::PassEnded => return ErrorType::Validation,
|
||||||
};
|
};
|
||||||
@ -942,7 +954,7 @@ struct RenderPassInfo {
|
|||||||
extent: wgt::Extent3d,
|
extent: wgt::Extent3d,
|
||||||
|
|
||||||
divergent_discarded_depth_stencil_aspect: Option<(wgt::TextureAspect, Arc<TextureView>)>,
|
divergent_discarded_depth_stencil_aspect: Option<(wgt::TextureAspect, Arc<TextureView>)>,
|
||||||
multiview: Option<NonZeroU32>,
|
multiview_mask: Option<NonZeroU32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RenderPassInfo {
|
impl RenderPassInfo {
|
||||||
@ -996,6 +1008,7 @@ impl RenderPassInfo {
|
|||||||
pending_query_resets: &mut QueryResetMap,
|
pending_query_resets: &mut QueryResetMap,
|
||||||
pending_discard_init_fixups: &mut SurfacesInDiscardState,
|
pending_discard_init_fixups: &mut SurfacesInDiscardState,
|
||||||
snatch_guard: &SnatchGuard<'_>,
|
snatch_guard: &SnatchGuard<'_>,
|
||||||
|
multiview_mask: Option<NonZeroU32>,
|
||||||
) -> Result<Self, RenderPassErrorInner> {
|
) -> Result<Self, RenderPassErrorInner> {
|
||||||
profiling::scope!("RenderPassInfo::start");
|
profiling::scope!("RenderPassInfo::start");
|
||||||
|
|
||||||
@ -1040,8 +1053,11 @@ impl RenderPassInfo {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Multiview is only supported if the feature is enabled
|
// Multiview is only supported if the feature is enabled
|
||||||
if this_multiview.is_some() {
|
if let Some(this_multiview) = this_multiview {
|
||||||
device.require_features(wgt::Features::MULTIVIEW)?;
|
device.require_features(wgt::Features::MULTIVIEW)?;
|
||||||
|
if this_multiview.get() > device.limits.max_multiview_view_count {
|
||||||
|
return Err(RenderPassErrorInner::TooManyMultiviewViews);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
detected_multiview = Some(this_multiview);
|
detected_multiview = Some(this_multiview);
|
||||||
@ -1389,7 +1405,20 @@ impl RenderPassInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let extent = extent.ok_or(RenderPassErrorInner::MissingAttachments)?;
|
let extent = extent.ok_or(RenderPassErrorInner::MissingAttachments)?;
|
||||||
let multiview = detected_multiview.expect("Multiview was not detected, no attachments");
|
|
||||||
|
let detected_multiview =
|
||||||
|
detected_multiview.expect("Multiview was not detected, no attachments");
|
||||||
|
if let Some(mask) = multiview_mask {
|
||||||
|
// 0x01 will have msb 0
|
||||||
|
let mask_msb = 31 - mask.leading_zeros();
|
||||||
|
let detected_mv = detected_multiview.map(NonZeroU32::get).unwrap_or(1);
|
||||||
|
if mask_msb >= detected_mv {
|
||||||
|
return Err(RenderPassErrorInner::MultiViewMismatch);
|
||||||
|
}
|
||||||
|
if mask.get() != (1 << detected_mv) - 1 {
|
||||||
|
device.require_features(wgt::Features::SELECTIVE_MULTIVIEW)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let attachment_formats = AttachmentData {
|
let attachment_formats = AttachmentData {
|
||||||
colors: color_attachments
|
colors: color_attachments
|
||||||
@ -1414,7 +1443,7 @@ impl RenderPassInfo {
|
|||||||
let context = RenderPassContext {
|
let context = RenderPassContext {
|
||||||
attachments: attachment_formats,
|
attachments: attachment_formats,
|
||||||
sample_count,
|
sample_count,
|
||||||
multiview,
|
multiview_mask,
|
||||||
};
|
};
|
||||||
|
|
||||||
let timestamp_writes_hal = if let Some(tw) = timestamp_writes.as_ref() {
|
let timestamp_writes_hal = if let Some(tw) = timestamp_writes.as_ref() {
|
||||||
@ -1450,7 +1479,7 @@ impl RenderPassInfo {
|
|||||||
sample_count,
|
sample_count,
|
||||||
color_attachments: &color_attachments_hal,
|
color_attachments: &color_attachments_hal,
|
||||||
depth_stencil_attachment: depth_stencil,
|
depth_stencil_attachment: depth_stencil,
|
||||||
multiview,
|
multiview_mask,
|
||||||
timestamp_writes: timestamp_writes_hal,
|
timestamp_writes: timestamp_writes_hal,
|
||||||
occlusion_query_set: occlusion_query_set_hal,
|
occlusion_query_set: occlusion_query_set_hal,
|
||||||
};
|
};
|
||||||
@ -1485,7 +1514,7 @@ impl RenderPassInfo {
|
|||||||
is_stencil_read_only,
|
is_stencil_read_only,
|
||||||
extent,
|
extent,
|
||||||
divergent_discarded_depth_stencil_aspect,
|
divergent_discarded_depth_stencil_aspect,
|
||||||
multiview,
|
multiview_mask,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1552,7 +1581,7 @@ impl RenderPassInfo {
|
|||||||
stencil_ops,
|
stencil_ops,
|
||||||
clear_value: (0.0, 0),
|
clear_value: (0.0, 0),
|
||||||
}),
|
}),
|
||||||
multiview: self.multiview,
|
multiview_mask: self.multiview_mask,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
};
|
};
|
||||||
@ -1713,6 +1742,8 @@ impl Global {
|
|||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
|
arc_desc.multiview_mask = desc.multiview_mask;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1731,6 +1762,7 @@ impl Global {
|
|||||||
color_attachments: ArrayVec::new(),
|
color_attachments: ArrayVec::new(),
|
||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
};
|
};
|
||||||
match fill_arc_desc(hub, desc, &mut arc_desc, &cmd_enc.device) {
|
match fill_arc_desc(hub, desc, &mut arc_desc, &cmd_enc.device) {
|
||||||
Ok(()) => (RenderPass::new(cmd_enc, arc_desc), None),
|
Ok(()) => (RenderPass::new(cmd_enc, arc_desc), None),
|
||||||
@ -1816,6 +1848,7 @@ impl Global {
|
|||||||
depth_stencil_attachment: pass.depth_stencil_attachment.take(),
|
depth_stencil_attachment: pass.depth_stencil_attachment.take(),
|
||||||
timestamp_writes: pass.timestamp_writes.take(),
|
timestamp_writes: pass.timestamp_writes.take(),
|
||||||
occlusion_query_set: pass.occlusion_query_set.take(),
|
occlusion_query_set: pass.occlusion_query_set.take(),
|
||||||
|
multiview_mask: pass.multiview_mask,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -1830,6 +1863,7 @@ pub(super) fn encode_render_pass(
|
|||||||
>,
|
>,
|
||||||
mut timestamp_writes: Option<ArcPassTimestampWrites>,
|
mut timestamp_writes: Option<ArcPassTimestampWrites>,
|
||||||
occlusion_query_set: Option<Arc<QuerySet>>,
|
occlusion_query_set: Option<Arc<QuerySet>>,
|
||||||
|
multiview_mask: Option<NonZeroU32>,
|
||||||
) -> Result<(), RenderPassError> {
|
) -> Result<(), RenderPassError> {
|
||||||
let pass_scope = PassErrorScope::Pass;
|
let pass_scope = PassErrorScope::Pass;
|
||||||
|
|
||||||
@ -1868,6 +1902,7 @@ pub(super) fn encode_render_pass(
|
|||||||
&mut pending_query_resets,
|
&mut pending_query_resets,
|
||||||
&mut pending_discard_init_fixups,
|
&mut pending_discard_init_fixups,
|
||||||
parent_state.snatch_guard,
|
parent_state.snatch_guard,
|
||||||
|
multiview_mask,
|
||||||
)
|
)
|
||||||
.map_pass_err(pass_scope)?;
|
.map_pass_err(pass_scope)?;
|
||||||
|
|
||||||
@ -2561,6 +2596,26 @@ fn set_scissor(state: &mut State, rect: Rect<u32>) -> Result<(), RenderPassError
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn validate_mesh_draw_multiview(state: &State) -> Result<(), RenderPassErrorInner> {
|
||||||
|
if let Some(mv) = state.info.multiview_mask {
|
||||||
|
let highest_bit = 31 - mv.leading_zeros();
|
||||||
|
|
||||||
|
let features = state.pass.base.device.features;
|
||||||
|
|
||||||
|
if !features.contains(wgt::Features::EXPERIMENTAL_MESH_SHADER_MULTIVIEW)
|
||||||
|
|| highest_bit > state.pass.base.device.limits.max_mesh_multiview_view_count
|
||||||
|
{
|
||||||
|
return Err(RenderPassErrorInner::Draw(
|
||||||
|
DrawError::MeshPipelineMultiviewLimitsViolated {
|
||||||
|
highest_view_index: highest_bit,
|
||||||
|
max_multiviews: state.pass.base.device.limits.max_mesh_multiview_view_count,
|
||||||
|
},
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn draw(
|
fn draw(
|
||||||
state: &mut State,
|
state: &mut State,
|
||||||
vertex_count: u32,
|
vertex_count: u32,
|
||||||
@ -2645,7 +2700,9 @@ fn draw_mesh_tasks(
|
|||||||
api_log!("RenderPass::draw_mesh_tasks {group_count_x} {group_count_y} {group_count_z}");
|
api_log!("RenderPass::draw_mesh_tasks {group_count_x} {group_count_y} {group_count_z}");
|
||||||
|
|
||||||
state.is_ready(DrawCommandFamily::DrawMeshTasks)?;
|
state.is_ready(DrawCommandFamily::DrawMeshTasks)?;
|
||||||
|
|
||||||
state.flush_bindings()?;
|
state.flush_bindings()?;
|
||||||
|
validate_mesh_draw_multiview(state)?;
|
||||||
|
|
||||||
let groups_size_limit = state
|
let groups_size_limit = state
|
||||||
.pass
|
.pass
|
||||||
@ -2696,6 +2753,10 @@ fn multi_draw_indirect(
|
|||||||
state.is_ready(family)?;
|
state.is_ready(family)?;
|
||||||
state.flush_bindings()?;
|
state.flush_bindings()?;
|
||||||
|
|
||||||
|
if family == DrawCommandFamily::DrawMeshTasks {
|
||||||
|
validate_mesh_draw_multiview(state)?;
|
||||||
|
}
|
||||||
|
|
||||||
state
|
state
|
||||||
.pass
|
.pass
|
||||||
.base
|
.base
|
||||||
@ -2878,6 +2939,10 @@ fn multi_draw_indirect_count(
|
|||||||
state.is_ready(family)?;
|
state.is_ready(family)?;
|
||||||
state.flush_bindings()?;
|
state.flush_bindings()?;
|
||||||
|
|
||||||
|
if family == DrawCommandFamily::DrawMeshTasks {
|
||||||
|
validate_mesh_draw_multiview(state)?;
|
||||||
|
}
|
||||||
|
|
||||||
let stride = get_stride_of_indirect_args(family);
|
let stride = get_stride_of_indirect_args(family);
|
||||||
|
|
||||||
state
|
state
|
||||||
|
|||||||
@ -1478,7 +1478,7 @@ impl Global {
|
|||||||
depth_stencil: desc.depth_stencil.clone(),
|
depth_stencil: desc.depth_stencil.clone(),
|
||||||
multisample: desc.multisample,
|
multisample: desc.multisample,
|
||||||
fragment,
|
fragment,
|
||||||
multiview: desc.multiview,
|
multiview_mask: desc.multiview_mask,
|
||||||
cache,
|
cache,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -61,7 +61,7 @@ impl<T: PartialEq> Eq for AttachmentData<T> {}
|
|||||||
pub(crate) struct RenderPassContext {
|
pub(crate) struct RenderPassContext {
|
||||||
pub attachments: AttachmentData<TextureFormat>,
|
pub attachments: AttachmentData<TextureFormat>,
|
||||||
pub sample_count: u32,
|
pub sample_count: u32,
|
||||||
pub multiview: Option<NonZeroU32>,
|
pub multiview_mask: Option<NonZeroU32>,
|
||||||
}
|
}
|
||||||
#[derive(Clone, Debug, Error)]
|
#[derive(Clone, Debug, Error)]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
@ -144,10 +144,10 @@ impl RenderPassContext {
|
|||||||
res: res.error_ident(),
|
res: res.error_ident(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if self.multiview != other.multiview {
|
if self.multiview_mask != other.multiview_mask {
|
||||||
return Err(RenderPassCompatibilityError::IncompatibleMultiview {
|
return Err(RenderPassCompatibilityError::IncompatibleMultiview {
|
||||||
expected: self.multiview,
|
expected: self.multiview_mask,
|
||||||
actual: other.multiview,
|
actual: other.multiview_mask,
|
||||||
res: res.error_ident(),
|
res: res.error_ident(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4442,8 +4442,11 @@ impl Device {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Multiview is only supported if the feature is enabled
|
// Multiview is only supported if the feature is enabled
|
||||||
if desc.multiview.is_some() {
|
if let Some(mv_mask) = desc.multiview_mask {
|
||||||
self.require_features(wgt::Features::MULTIVIEW)?;
|
self.require_features(wgt::Features::MULTIVIEW)?;
|
||||||
|
if !(mv_mask.get() + 1).is_power_of_two() {
|
||||||
|
self.require_features(wgt::Features::SELECTIVE_MULTIVIEW)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !self
|
if !self
|
||||||
@ -4493,7 +4496,7 @@ impl Device {
|
|||||||
multisample: desc.multisample,
|
multisample: desc.multisample,
|
||||||
fragment_stage,
|
fragment_stage,
|
||||||
color_targets,
|
color_targets,
|
||||||
multiview: desc.multiview,
|
multiview_mask: desc.multiview_mask,
|
||||||
cache: cache.as_ref().map(|it| it.raw()),
|
cache: cache.as_ref().map(|it| it.raw()),
|
||||||
};
|
};
|
||||||
unsafe { self.raw().create_render_pipeline(&pipeline_desc) }.map_err(
|
unsafe { self.raw().create_render_pipeline(&pipeline_desc) }.map_err(
|
||||||
@ -4527,7 +4530,7 @@ impl Device {
|
|||||||
depth_stencil: depth_stencil_state.as_ref().map(|state| state.format),
|
depth_stencil: depth_stencil_state.as_ref().map(|state| state.format),
|
||||||
},
|
},
|
||||||
sample_count: samples,
|
sample_count: samples,
|
||||||
multiview: desc.multiview,
|
multiview_mask: desc.multiview_mask,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut flags = pipeline::PipelineFlags::empty();
|
let mut flags = pipeline::PipelineFlags::empty();
|
||||||
|
|||||||
@ -39,7 +39,7 @@ pub(crate) fn new_render_bundle_encoder_descriptor(
|
|||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
sample_count: context.sample_count,
|
sample_count: context.sample_count,
|
||||||
multiview: context.multiview,
|
multiview: context.multiview_mask,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -195,12 +195,14 @@ impl IntoTrace for ArcCommand {
|
|||||||
depth_stencil_attachment,
|
depth_stencil_attachment,
|
||||||
timestamp_writes,
|
timestamp_writes,
|
||||||
occlusion_query_set,
|
occlusion_query_set,
|
||||||
|
multiview_mask,
|
||||||
} => Command::RunRenderPass {
|
} => Command::RunRenderPass {
|
||||||
pass: pass.into_trace(),
|
pass: pass.into_trace(),
|
||||||
color_attachments: color_attachments.into_trace(),
|
color_attachments: color_attachments.into_trace(),
|
||||||
depth_stencil_attachment: depth_stencil_attachment.map(|d| d.into_trace()),
|
depth_stencil_attachment: depth_stencil_attachment.map(|d| d.into_trace()),
|
||||||
timestamp_writes: timestamp_writes.map(|tw| tw.into_trace()),
|
timestamp_writes: timestamp_writes.map(|tw| tw.into_trace()),
|
||||||
occlusion_query_set: occlusion_query_set.map(|q| q.to_trace()),
|
occlusion_query_set: occlusion_query_set.map(|q| q.to_trace()),
|
||||||
|
multiview_mask,
|
||||||
},
|
},
|
||||||
ArcCommand::BuildAccelerationStructures { blas, tlas } => {
|
ArcCommand::BuildAccelerationStructures { blas, tlas } => {
|
||||||
Command::BuildAccelerationStructures {
|
Command::BuildAccelerationStructures {
|
||||||
@ -660,7 +662,7 @@ impl<'a> IntoTrace for crate::pipeline::ResolvedGeneralRenderPipelineDescriptor<
|
|||||||
depth_stencil: self.depth_stencil,
|
depth_stencil: self.depth_stencil,
|
||||||
multisample: self.multisample,
|
multisample: self.multisample,
|
||||||
fragment: self.fragment.map(|f| f.into_trace()),
|
fragment: self.fragment.map(|f| f.into_trace()),
|
||||||
multiview: self.multiview,
|
multiview_mask: self.multiview_mask,
|
||||||
cache: self.cache.map(|c| c.into_trace()),
|
cache: self.cache.map(|c| c.into_trace()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -467,7 +467,7 @@ pub struct RenderPipelineDescriptor<
|
|||||||
pub fragment: Option<FragmentState<'a, SM>>,
|
pub fragment: Option<FragmentState<'a, SM>>,
|
||||||
/// If the pipeline will be used with a multiview render pass, this indicates how many array
|
/// If the pipeline will be used with a multiview render pass, this indicates how many array
|
||||||
/// layers the attachments will have.
|
/// layers the attachments will have.
|
||||||
pub multiview: Option<NonZeroU32>,
|
pub multiview_mask: Option<NonZeroU32>,
|
||||||
/// The pipeline cache to use when creating this pipeline.
|
/// The pipeline cache to use when creating this pipeline.
|
||||||
pub cache: Option<PLC>,
|
pub cache: Option<PLC>,
|
||||||
}
|
}
|
||||||
@ -539,7 +539,7 @@ pub struct GeneralRenderPipelineDescriptor<
|
|||||||
pub fragment: Option<FragmentState<'a, SM>>,
|
pub fragment: Option<FragmentState<'a, SM>>,
|
||||||
/// If the pipeline will be used with a multiview render pass, this indicates how many array
|
/// If the pipeline will be used with a multiview render pass, this indicates how many array
|
||||||
/// layers the attachments will have.
|
/// layers the attachments will have.
|
||||||
pub multiview: Option<NonZeroU32>,
|
pub multiview_mask: Option<NonZeroU32>,
|
||||||
/// The pipeline cache to use when creating this pipeline.
|
/// The pipeline cache to use when creating this pipeline.
|
||||||
pub cache: Option<PLC>,
|
pub cache: Option<PLC>,
|
||||||
}
|
}
|
||||||
@ -555,7 +555,7 @@ impl<'a, PLL, SM, PLC> From<RenderPipelineDescriptor<'a, PLL, SM, PLC>>
|
|||||||
depth_stencil: value.depth_stencil,
|
depth_stencil: value.depth_stencil,
|
||||||
multisample: value.multisample,
|
multisample: value.multisample,
|
||||||
fragment: value.fragment,
|
fragment: value.fragment,
|
||||||
multiview: value.multiview,
|
multiview_mask: value.multiview_mask,
|
||||||
cache: value.cache,
|
cache: value.cache,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -572,7 +572,7 @@ impl<'a, PLL, SM, PLC> From<MeshPipelineDescriptor<'a, PLL, SM, PLC>>
|
|||||||
depth_stencil: value.depth_stencil,
|
depth_stencil: value.depth_stencil,
|
||||||
multisample: value.multisample,
|
multisample: value.multisample,
|
||||||
fragment: value.fragment,
|
fragment: value.fragment,
|
||||||
multiview: value.multiview,
|
multiview_mask: value.multiview,
|
||||||
cache: value.cache,
|
cache: value.cache,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -84,6 +84,7 @@ metal = [
|
|||||||
"dep:objc",
|
"dep:objc",
|
||||||
"dep:parking_lot",
|
"dep:parking_lot",
|
||||||
"dep:profiling",
|
"dep:profiling",
|
||||||
|
"dep:smallvec",
|
||||||
]
|
]
|
||||||
vulkan = [
|
vulkan = [
|
||||||
"naga/spv-out",
|
"naga/spv-out",
|
||||||
|
|||||||
@ -280,7 +280,7 @@ impl<A: hal::Api> Example<A> {
|
|||||||
blend: Some(wgpu_types::BlendState::ALPHA_BLENDING),
|
blend: Some(wgpu_types::BlendState::ALPHA_BLENDING),
|
||||||
write_mask: wgpu_types::ColorWrites::default(),
|
write_mask: wgpu_types::ColorWrites::default(),
|
||||||
})],
|
})],
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
cache: None,
|
cache: None,
|
||||||
};
|
};
|
||||||
let pipeline = unsafe { device.create_render_pipeline(&pipeline_desc).unwrap() };
|
let pipeline = unsafe { device.create_render_pipeline(&pipeline_desc).unwrap() };
|
||||||
@ -727,7 +727,7 @@ impl<A: hal::Api> Example<A> {
|
|||||||
},
|
},
|
||||||
})],
|
})],
|
||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -329,7 +329,7 @@ fn fill_screen(exposed: &hal::ExposedAdapter<hal::api::Gles>, width: u32, height
|
|||||||
clear_value: wgpu_types::Color::BLUE,
|
clear_value: wgpu_types::Color::BLUE,
|
||||||
})],
|
})],
|
||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: None,
|
||||||
multiview: None,
|
multiview_mask: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
};
|
};
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user