diff options
Diffstat (limited to 'src/graphics')
| -rw-r--r-- | src/graphics/texture.rs | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/src/graphics/texture.rs b/src/graphics/texture.rs new file mode 100644 index 0000000..6273b6e --- /dev/null +++ b/src/graphics/texture.rs @@ -0,0 +1,108 @@ +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, Origin3d::ZERO, self.width, self.height); + } + + /// テクスチャを部分的に更新するメソッド + /// + /// * queue - queue + /// * data - 更新データ + /// * origin - 更新領域の開始座標 + /// * width - 更新領域の幅 + /// * height - 更新領域の高さ + /// + /// `data`が更新領域サイズと一致しない場合は、クラッシュしないように不足分が白色で埋められる。 + pub fn write_partial( + &self, + queue: &Queue, + data: &[u8], + origin: Origin3d, + 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, + 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, + }, + ); + } +} |
