Skip to content

Commit 995aaf7

Browse files
committed
Fixed Queue::write_texture on dx12 + refactored and added new test to write_texture.rs
1 parent 1ced67f commit 995aaf7

File tree

3 files changed

+154
-128
lines changed

3 files changed

+154
-128
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ By @Valaphee in [#3402](https://github.com/gfx-rs/wgpu/pull/3402)
9898

9999
- DX12 doesn't support `Features::POLYGON_MODE_POINT``. By @teoxoy in [#4032](https://github.com/gfx-rs/wgpu/pull/4032).
100100
- Set `Features::VERTEX_WRITABLE_STORAGE` based on the right feature level. By @teoxoy in [#4033](https://github.com/gfx-rs/wgpu/pull/4033).
101-
101+
- Fix Queue::write_texture failing on the DX12 backend and added a new test to test writing/copying from different mipmap levels. By @39ali in [#3992](https://github.com/gfx-rs/wgpu/pull/3992)
102102
### Documentation
103103

104104
- Add an overview of `RenderPass` and how render state works. By @kpreid in [#4055](https://github.com/gfx-rs/wgpu/pull/4055)

tests/tests/write_texture.rs

Lines changed: 151 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -4,55 +4,82 @@ use wgpu_test::{initialize_test, TestParameters};
44

55
use wasm_bindgen_test::*;
66

7-
#[test]
8-
#[wasm_bindgen_test]
9-
fn write_texture_subset_2d() {
10-
let size = 256;
11-
let parameters = TestParameters::default().backend_failure(wgpu::Backends::DX12);
7+
fn total_bytes_in_copy(
8+
texture_format: wgpu::TextureFormat,
9+
bytes_per_row: u32,
10+
rows_per_image: u32,
11+
copy_extent: wgpu::Extent3d,
12+
) -> u32 {
13+
let block_size = texture_format.block_size(None).unwrap_or(1);
14+
15+
let block_dim = texture_format.block_dimensions();
16+
17+
let block_width = copy_extent.width / block_dim.0;
18+
let block_height = copy_extent.height / block_dim.1;
19+
20+
let bytes_per_image = bytes_per_row * rows_per_image;
21+
let mut total_bytes = bytes_per_image * (copy_extent.depth_or_array_layers - 1);
22+
23+
if block_height != 0 {
24+
let last_row_bytes = block_width * block_size;
25+
let last_image_bytes = bytes_per_row * (block_height - 1) + last_row_bytes;
26+
total_bytes += last_image_bytes;
27+
}
28+
29+
total_bytes
30+
}
31+
32+
fn test(
33+
format: wgpu::TextureFormat,
34+
bytes_per_row: u32,
35+
rows_per_image: u32,
36+
total_size_in_bytes: u32,
37+
mip_level: u32,
38+
mips_count: u32,
39+
tex_size: wgpu::Extent3d,
40+
write_size: wgpu::Extent3d,
41+
copy_size: wgpu::Extent3d,
42+
) {
43+
let parameters = TestParameters::default();
1244
initialize_test(parameters, |ctx| {
1345
let tex = ctx.device.create_texture(&wgpu::TextureDescriptor {
1446
label: None,
1547
dimension: wgpu::TextureDimension::D2,
16-
size: wgpu::Extent3d {
17-
width: size,
18-
height: size,
19-
depth_or_array_layers: 1,
20-
},
21-
format: wgpu::TextureFormat::R8Uint,
48+
size: tex_size,
49+
format,
2250
usage: wgpu::TextureUsages::COPY_DST
2351
| wgpu::TextureUsages::COPY_SRC
2452
| wgpu::TextureUsages::TEXTURE_BINDING,
25-
mip_level_count: 1,
53+
mip_level_count: mips_count,
2654
sample_count: 1,
2755
view_formats: &[],
2856
});
29-
let data = vec![1u8; size as usize * 2];
57+
58+
let val = (mip_level + 1) as u8;
59+
let data = vec![val; total_size_in_bytes as usize];
60+
3061
// Write the first two rows
3162
ctx.queue.write_texture(
3263
wgpu::ImageCopyTexture {
3364
texture: &tex,
34-
mip_level: 0,
65+
mip_level,
3566
origin: wgpu::Origin3d::ZERO,
3667
aspect: wgpu::TextureAspect::All,
3768
},
3869
bytemuck::cast_slice(&data),
3970
wgpu::ImageDataLayout {
4071
offset: 0,
41-
bytes_per_row: Some(size),
42-
rows_per_image: Some(size),
43-
},
44-
wgpu::Extent3d {
45-
width: size,
46-
height: 2,
47-
depth_or_array_layers: 1,
72+
bytes_per_row: Some(bytes_per_row),
73+
rows_per_image: Some(rows_per_image),
4874
},
75+
write_size,
4976
);
5077

5178
ctx.queue.submit(None);
5279

5380
let read_buffer = ctx.device.create_buffer(&wgpu::BufferDescriptor {
5481
label: None,
55-
size: (size * size) as u64,
82+
size: (total_size_in_bytes) as u64,
5683
usage: wgpu::BufferUsages::MAP_READ | wgpu::BufferUsages::COPY_DST,
5784
mapped_at_creation: false,
5885
});
@@ -64,23 +91,19 @@ fn write_texture_subset_2d() {
6491
encoder.copy_texture_to_buffer(
6592
wgpu::ImageCopyTexture {
6693
texture: &tex,
67-
mip_level: 0,
94+
mip_level,
6895
origin: wgpu::Origin3d::ZERO,
6996
aspect: wgpu::TextureAspect::All,
7097
},
7198
wgpu::ImageCopyBuffer {
7299
buffer: &read_buffer,
73100
layout: wgpu::ImageDataLayout {
74101
offset: 0,
75-
bytes_per_row: Some(size),
76-
rows_per_image: Some(size),
102+
bytes_per_row: Some(bytes_per_row),
103+
rows_per_image: Some(rows_per_image),
77104
},
78105
},
79-
wgpu::Extent3d {
80-
width: size,
81-
height: size,
82-
depth_or_array_layers: 1,
83-
},
106+
copy_size,
84107
);
85108

86109
ctx.queue.submit(Some(encoder.finish()));
@@ -90,107 +113,113 @@ fn write_texture_subset_2d() {
90113
ctx.device.poll(wgpu::Maintain::Wait);
91114
let data: Vec<u8> = slice.get_mapped_range().to_vec();
92115

93-
for byte in &data[..(size as usize * 2)] {
94-
assert_eq!(*byte, 1);
116+
for byte in &data[..(total_size_in_bytes as usize)] {
117+
assert_eq!(*byte, val);
95118
}
96-
for byte in &data[(size as usize * 2)..] {
119+
for byte in &data[(total_size_in_bytes as usize)..] {
97120
assert_eq!(*byte, 0);
98121
}
99122
});
100123
}
101124

102125
#[test]
103126
#[wasm_bindgen_test]
104-
fn write_texture_subset_3d() {
105-
let size = 256;
106-
let depth = 4;
107-
let parameters = TestParameters::default();
108-
initialize_test(parameters, |ctx| {
109-
let tex = ctx.device.create_texture(&wgpu::TextureDescriptor {
110-
label: None,
111-
dimension: wgpu::TextureDimension::D3,
112-
size: wgpu::Extent3d {
113-
width: size,
114-
height: size,
115-
depth_or_array_layers: depth,
116-
},
117-
format: wgpu::TextureFormat::R8Uint,
118-
usage: wgpu::TextureUsages::COPY_DST
119-
| wgpu::TextureUsages::COPY_SRC
120-
| wgpu::TextureUsages::TEXTURE_BINDING,
121-
mip_level_count: 1,
122-
sample_count: 1,
123-
view_formats: &[],
124-
});
125-
let data = vec![1u8; (size * size) as usize * 2];
126-
// Write the first two slices
127-
ctx.queue.write_texture(
128-
wgpu::ImageCopyTexture {
129-
texture: &tex,
130-
mip_level: 0,
131-
origin: wgpu::Origin3d::ZERO,
132-
aspect: wgpu::TextureAspect::All,
133-
},
134-
bytemuck::cast_slice(&data),
135-
wgpu::ImageDataLayout {
136-
offset: 0,
137-
bytes_per_row: Some(size),
138-
rows_per_image: Some(size),
139-
},
140-
wgpu::Extent3d {
141-
width: size,
142-
height: size,
143-
depth_or_array_layers: 2,
144-
},
145-
);
146-
147-
ctx.queue.submit(None);
148-
149-
let read_buffer = ctx.device.create_buffer(&wgpu::BufferDescriptor {
150-
label: None,
151-
size: (size * size * depth) as u64,
152-
usage: wgpu::BufferUsages::MAP_READ | wgpu::BufferUsages::COPY_DST,
153-
mapped_at_creation: false,
154-
});
155-
156-
let mut encoder = ctx
157-
.device
158-
.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None });
127+
fn write_texture_subset_2d() {
128+
let format = wgpu::TextureFormat::R8Uint;
129+
let mips_count = 1;
130+
let tex_size = wgpu::Extent3d {
131+
width: 256,
132+
height: 256,
133+
depth_or_array_layers: 1,
134+
};
135+
136+
let bytes_per_row = tex_size.width;
137+
let rows_per_image = tex_size.height;
138+
139+
let total_bytes_in_copy = total_bytes_in_copy(format, bytes_per_row, rows_per_image, tex_size);
140+
141+
test(
142+
format,
143+
bytes_per_row,
144+
rows_per_image,
145+
total_bytes_in_copy,
146+
0,
147+
mips_count,
148+
tex_size,
149+
tex_size,
150+
tex_size,
151+
);
152+
}
159153

160-
encoder.copy_texture_to_buffer(
161-
wgpu::ImageCopyTexture {
162-
texture: &tex,
163-
mip_level: 0,
164-
origin: wgpu::Origin3d::ZERO,
165-
aspect: wgpu::TextureAspect::All,
166-
},
167-
wgpu::ImageCopyBuffer {
168-
buffer: &read_buffer,
169-
layout: wgpu::ImageDataLayout {
170-
offset: 0,
171-
bytes_per_row: Some(size),
172-
rows_per_image: Some(size),
173-
},
174-
},
175-
wgpu::Extent3d {
176-
width: size,
177-
height: size,
178-
depth_or_array_layers: depth,
179-
},
154+
#[test]
155+
#[wasm_bindgen_test]
156+
fn write_texture_subset_2d_mips() {
157+
let format = wgpu::TextureFormat::R8Uint;
158+
let mips_count = 3;
159+
let tex_size = wgpu::Extent3d {
160+
width: 2048,
161+
height: 2048,
162+
depth_or_array_layers: 1,
163+
};
164+
for mip_level in 0..mips_count {
165+
let mip_w = tex_size.width / (1 << mip_level);
166+
let mip_h = tex_size.height / (1 << mip_level);
167+
let bytes_per_row = mip_w;
168+
let rows_per_image = mip_h;
169+
170+
let mip_extent = wgpu::Extent3d {
171+
width: mip_w,
172+
height: 2,
173+
depth_or_array_layers: tex_size.depth_or_array_layers,
174+
};
175+
176+
let total_bytes_in_copy =
177+
total_bytes_in_copy(format, bytes_per_row, rows_per_image, mip_extent);
178+
179+
test(
180+
format,
181+
bytes_per_row,
182+
rows_per_image,
183+
total_bytes_in_copy,
184+
mip_level,
185+
mips_count,
186+
tex_size,
187+
mip_extent,
188+
mip_extent,
180189
);
190+
}
191+
}
181192

182-
ctx.queue.submit(Some(encoder.finish()));
183-
184-
let slice = read_buffer.slice(..);
185-
slice.map_async(wgpu::MapMode::Read, |_| ());
186-
ctx.device.poll(wgpu::Maintain::Wait);
187-
let data: Vec<u8> = slice.get_mapped_range().to_vec();
188-
189-
for byte in &data[..((size * size) as usize * 2)] {
190-
assert_eq!(*byte, 1);
191-
}
192-
for byte in &data[((size * size) as usize * 2)..] {
193-
assert_eq!(*byte, 0);
194-
}
195-
});
193+
#[test]
194+
#[wasm_bindgen_test]
195+
fn write_texture_subset_3d() {
196+
let format = wgpu::TextureFormat::R8Uint;
197+
let mips_count = 1;
198+
let tex_size = wgpu::Extent3d {
199+
width: 256,
200+
height: 256,
201+
depth_or_array_layers: 4,
202+
};
203+
let copy_size = wgpu::Extent3d {
204+
width: 256,
205+
height: 256,
206+
depth_or_array_layers: 2,
207+
};
208+
209+
let bytes_per_row = tex_size.width;
210+
let rows_per_image = tex_size.height;
211+
212+
let total_bytes_in_copy = total_bytes_in_copy(format, bytes_per_row, rows_per_image, copy_size);
213+
214+
test(
215+
format,
216+
bytes_per_row,
217+
rows_per_image,
218+
total_bytes_in_copy,
219+
0,
220+
mips_count,
221+
tex_size,
222+
copy_size,
223+
copy_size,
224+
);
196225
}

wgpu-hal/src/dx12/command.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ impl crate::BufferTextureCopy {
2020
&self,
2121
format: wgt::TextureFormat,
2222
) -> d3d12_ty::D3D12_PLACED_SUBRESOURCE_FOOTPRINT {
23-
let (block_width, block_height) = format.block_dimensions();
23+
let block_width = format.block_dimensions().0;
2424
d3d12_ty::D3D12_PLACED_SUBRESOURCE_FOOTPRINT {
2525
Offset: self.buffer_layout.offset,
2626
Footprint: d3d12_ty::D3D12_SUBRESOURCE_FOOTPRINT {
@@ -30,10 +30,7 @@ impl crate::BufferTextureCopy {
3030
)
3131
.unwrap(),
3232
Width: self.size.width,
33-
Height: self
34-
.buffer_layout
35-
.rows_per_image
36-
.map_or(self.size.height, |count| count * block_height),
33+
Height: self.size.height,
3734
Depth: self.size.depth,
3835
RowPitch: {
3936
let actual = self.buffer_layout.bytes_per_row.unwrap_or_else(|| {

0 commit comments

Comments
 (0)