Skip to content

Commit

Permalink
Support stencil-only views and copying to/from combined depth-stencil…
Browse files Browse the repository at this point in the history
… textures (#3436)
  • Loading branch information
teoxoy authored Feb 15, 2023
1 parent ee33f4d commit c51edd3
Show file tree
Hide file tree
Showing 40 changed files with 1,872 additions and 912 deletions.
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

- 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

0 comments on commit c51edd3

Please sign in to comment.