1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
use wgpu::*;
pub struct TextureWrapper {
pub width: u32,
pub height: u32,
pub block_size: u32,
pub texture: Texture,
pub view: TextureView,
}
impl TextureWrapper {
pub fn new(
device: &Device,
width: u32,
height: u32,
format: TextureFormat,
usage: TextureUsages,
) -> Self {
let texture = device.create_texture(&TextureDescriptor {
label: None,
size: Extent3d {
width,
height,
depth_or_array_layers: 1,
},
mip_level_count: 1,
sample_count: 1,
dimension: TextureDimension::D2,
format,
usage,
view_formats: &[],
});
let view = texture.create_view(&TextureViewDescriptor::default());
// NOTE: Depth, Stencil, YUVでない限りはNoneにはならないが、念の為`1`にunwrapする。
let block_size = format.block_copy_size(None).unwrap_or(1);
Self {
width,
height,
block_size,
texture,
view,
}
}
/// テクスチャ全体を更新するメソッド
///
/// * queue - queue
/// * data - 更新データ
///
/// `data`がテクスチャサイズと一致しない場合は、クラッシュしないように不足分が白色で埋められる。
pub fn write(&self, queue: &Queue, data: &[u8]) {
self.write_partial(queue, data, 0, 0, self.width, self.height);
}
/// テクスチャを部分的に更新するメソッド
///
/// * queue - queue
/// * data - 更新データ
/// * x - 更新領域の開始X座標
/// * y - 更新領域の開始Y座標
/// * width - 更新領域の幅
/// * height - 更新領域の高さ
///
/// `data`が更新領域サイズと一致しない場合は、クラッシュしないように不足分が白色で埋められる。
pub fn write_partial(
&self,
queue: &Queue,
data: &[u8],
x: u32,
y: u32,
width: u32,
height: u32,
) {
let expected_len = (width * height * self.block_size) as usize;
// `data`が想定サイズより短い場合はエラーになるので不足分を白色で埋める。
let buffer;
let data = if data.len() >= expected_len {
data
} else {
let mut v = Vec::with_capacity(expected_len);
v.extend_from_slice(data);
v.resize(expected_len, 0xff);
buffer = v;
buffer.as_slice()
};
queue.write_texture(
TexelCopyTextureInfo {
texture: &self.texture,
mip_level: 0,
origin: Origin3d { x, y, z: 0 },
aspect: TextureAspect::All,
},
data,
TexelCopyBufferLayout {
offset: 0,
bytes_per_row: Some(width * self.block_size),
rows_per_image: Some(height),
},
Extent3d {
width,
height,
depth_or_array_layers: 1,
},
);
}
}
|