summaryrefslogtreecommitdiff
path: root/src/graphics
diff options
context:
space:
mode:
Diffstat (limited to 'src/graphics')
-rw-r--r--src/graphics/texture.rs108
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,
+ },
+ );
+ }
+}