Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support stencil-only views and copying to/from combined depth-stencil textures #3436

Merged
merged 3 commits into from
Feb 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,34 @@ Bottom level categories:

### Major changes

#### TextureFormat info API

The `describe` fn was removed in favor of separate functions: `block_dimensions`, `is_compressed`, `is_srgb`, `required_features`, `guaranteed_format_features`, `sample_type` and `block_size`.

```diff
- let block_dimensions = format.describe().block_dimensions;
+ let block_dimensions = format.block_dimensions();
- let is_compressed = format.describe().is_compressed();
+ let is_compressed = format.is_compressed();
- let is_srgb = format.describe().srgb;
+ let is_srgb = format.is_srgb();
- let required_features = format.describe().required_features;
+ let required_features = format.required_features();
- let guaranteed_format_features = format.describe().guaranteed_format_features;
+ let guaranteed_format_features = format.guaranteed_format_features();
```

Additionally `sample_type` and `block_size` now take an optional `TextureAspect` and return `Option`s.

```diff
- let sample_type = format.describe().sample_type;
+ let sample_type = format.sample_type(None).expect("combined depth-stencil format requires specifying a TextureAspect");
- let block_size = format.describe().block_size;
+ let block_size = format.block_size(None).expect("combined depth-stencil format requires specifying a TextureAspect");
```

By @teoxoy in [#3436](https://github.com/gfx-rs/wgpu/pull/3436)

#### General

- Change type of `mip_level_count` and `array_layer_count` (members of `TextureViewDescriptor` and `ImageSubresourceRange`) from `Option<NonZeroU32>` to `Option<u32>`. By @teoxoy in [#3445](https://github.com/gfx-rs/wgpu/pull/3445)
Expand All @@ -51,6 +79,7 @@ Bottom level categories:
#### General
teoxoy marked this conversation as resolved.
Show resolved Hide resolved

- Added `TextureFormatFeatureFlags::MULTISAMPLE_X16`. By @Dinnerbone in [#3454](https://github.com/gfx-rs/wgpu/pull/3454)
- Support stencil-only views and copying to/from combined depth-stencil textures. By @teoxoy in [#3436](https://github.com/gfx-rs/wgpu/pull/3436)

#### WebGPU

Expand Down
42 changes: 20 additions & 22 deletions wgpu-core/src/command/clear.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,8 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
.map_err(|_| ClearError::InvalidTexture(dst))?;

// Check if subresource aspects are valid.
let requested_aspects = hal::FormatAspects::from(subresource_range.aspect);
let clear_aspects = hal::FormatAspects::from(dst_texture.desc.format) & requested_aspects;
let clear_aspects =
hal::FormatAspects::new(dst_texture.desc.format, subresource_range.aspect);
if clear_aspects.is_empty() {
return Err(ClearError::MissingTextureAspect {
texture_format: dst_texture.desc.format,
Expand Down Expand Up @@ -310,29 +310,33 @@ fn clear_texture_via_buffer_copies<A: hal::Api>(
encoder: &mut A::CommandEncoder,
dst_raw: &A::Texture,
) {
assert_eq!(
hal::FormatAspects::from(texture_desc.format),
hal::FormatAspects::COLOR
);

// Gather list of zero_buffer copies and issue a single command then to perform them
let mut zero_buffer_copy_regions = Vec::new();
let buffer_copy_pitch = alignments.buffer_copy_pitch.get() as u32;
let format_desc = texture_desc.format.describe();
let (block_width, block_height) = texture_desc.format.block_dimensions();
let block_size = texture_desc.format.block_size(None).unwrap();

let bytes_per_row_alignment =
get_lowest_common_denom(buffer_copy_pitch, format_desc.block_size as u32);
let bytes_per_row_alignment = get_lowest_common_denom(buffer_copy_pitch, block_size);

for mip_level in range.mip_range {
let mut mip_size = texture_desc.mip_level_size(mip_level).unwrap();
// Round to multiple of block size
mip_size.width = align_to(mip_size.width, format_desc.block_dimensions.0 as u32);
mip_size.height = align_to(mip_size.height, format_desc.block_dimensions.1 as u32);
mip_size.width = align_to(mip_size.width, block_width);
mip_size.height = align_to(mip_size.height, block_height);

let bytes_per_row = align_to(
mip_size.width / format_desc.block_dimensions.0 as u32 * format_desc.block_size as u32,
mip_size.width / block_width * block_size,
bytes_per_row_alignment,
);

let max_rows_per_copy = crate::device::ZERO_BUFFER_SIZE as u32 / bytes_per_row;
// round down to a multiple of rows needed by the texture format
let max_rows_per_copy = max_rows_per_copy / format_desc.block_dimensions.1 as u32
* format_desc.block_dimensions.1 as u32;
let max_rows_per_copy = max_rows_per_copy / block_height * block_height;
assert!(
max_rows_per_copy > 0,
"Zero buffer size is too small to fill a single row \
Expand Down Expand Up @@ -370,7 +374,7 @@ fn clear_texture_via_buffer_copies<A: hal::Api>(
y: mip_size.height - num_rows_left,
z,
},
aspect: hal::FormatAspects::all(),
aspect: hal::FormatAspects::COLOR,
},
size: hal::CopyExtent {
width: mip_size.width, // full row
Expand All @@ -396,23 +400,17 @@ fn clear_texture_via_render_passes<A: hal::Api>(
is_color: bool,
encoder: &mut A::CommandEncoder,
) -> Result<(), ClearError> {
assert_eq!(dst_texture.desc.dimension, wgt::TextureDimension::D2);

let extent_base = wgt::Extent3d {
width: dst_texture.desc.size.width,
height: dst_texture.desc.size.height,
depth_or_array_layers: 1, // Only one layer or slice is cleared at a time.
depth_or_array_layers: 1, // Only one layer is cleared at a time.
};

let sample_count = dst_texture.desc.sample_count;
for mip_level in range.mip_range {
let extent = extent_base.mip_level_size(mip_level, dst_texture.desc.dimension);
let layer_or_depth_range = if dst_texture.desc.dimension == wgt::TextureDimension::D3 {
// TODO: We assume that we're allowed to do clear operations on
// volume texture slices, this is not properly specified.
0..extent.depth_or_array_layers
} else {
range.layer_range.clone()
};
for depth_or_layer in layer_or_depth_range {
for depth_or_layer in range.layer_range.clone() {
let color_attachments_tmp;
let (color_attachments, depth_stencil_attachment) = if is_color {
color_attachments_tmp = [Some(hal::ColorAttachment {
Expand Down Expand Up @@ -443,7 +441,7 @@ fn clear_texture_via_render_passes<A: hal::Api>(
encoder.begin_render_pass(&hal::RenderPassDescriptor {
label: Some("(wgpu internal) clear_texture clear pass"),
extent,
sample_count,
sample_count: dst_texture.desc.sample_count,
color_attachments,
depth_stencil_attachment,
multiview: None,
Expand Down
Loading