Skip to main content

par_term_render/
gpu_utils.rs

1//! Common GPU utilities for texture and sampler creation.
2//!
3//! This module provides reusable helper functions for common wgpu operations
4//! to reduce code duplication across renderer modules.
5
6#![allow(dead_code)]
7
8use wgpu::{
9    AddressMode, Device, Extent3d, FilterMode, Queue, Sampler, SamplerDescriptor, Texture,
10    TextureDescriptor, TextureDimension, TextureFormat, TextureUsages,
11};
12
13/// Create a sampler with the specified filter mode and ClampToEdge address mode.
14///
15/// This allows choosing between nearest-neighbor (sharp/pixel art) and
16/// linear (smooth) filtering for texture sampling.
17pub fn create_sampler_with_filter(
18    device: &Device,
19    filter: FilterMode,
20    label: Option<&str>,
21) -> Sampler {
22    device.create_sampler(&SamplerDescriptor {
23        label,
24        address_mode_u: AddressMode::ClampToEdge,
25        address_mode_v: AddressMode::ClampToEdge,
26        address_mode_w: AddressMode::ClampToEdge,
27        mag_filter: filter,
28        min_filter: filter,
29        mipmap_filter: FilterMode::Nearest,
30        ..Default::default()
31    })
32}
33
34/// Create a linear sampler with ClampToEdge address mode.
35///
36/// This is the most common sampler configuration, suitable for:
37/// - Terminal cell rendering
38/// - Sixel graphics
39/// - UI textures
40pub fn create_linear_sampler(device: &Device, label: Option<&str>) -> Sampler {
41    device.create_sampler(&SamplerDescriptor {
42        label,
43        address_mode_u: AddressMode::ClampToEdge,
44        address_mode_v: AddressMode::ClampToEdge,
45        address_mode_w: AddressMode::ClampToEdge,
46        mag_filter: FilterMode::Linear,
47        min_filter: FilterMode::Linear,
48        mipmap_filter: FilterMode::Nearest,
49        ..Default::default()
50    })
51}
52
53/// Create a linear sampler with Repeat address mode.
54///
55/// Suitable for:
56/// - Tiled background textures
57/// - Shader channel textures that should tile
58pub fn create_repeat_sampler(device: &Device, label: Option<&str>) -> Sampler {
59    device.create_sampler(&SamplerDescriptor {
60        label,
61        address_mode_u: AddressMode::Repeat,
62        address_mode_v: AddressMode::Repeat,
63        address_mode_w: AddressMode::Repeat,
64        mag_filter: FilterMode::Linear,
65        min_filter: FilterMode::Linear,
66        mipmap_filter: FilterMode::Linear,
67        ..Default::default()
68    })
69}
70
71/// Create an RGBA texture with the specified dimensions.
72///
73/// The texture is created with:
74/// - COPY_DST usage (for writing data)
75/// - TEXTURE_BINDING usage (for sampling in shaders)
76///
77/// # Arguments
78/// * `device` - The wgpu device
79/// * `width` - Texture width in pixels
80/// * `height` - Texture height in pixels
81/// * `label` - Optional debug label
82pub fn create_rgba_texture(
83    device: &Device,
84    width: u32,
85    height: u32,
86    label: Option<&str>,
87) -> Texture {
88    device.create_texture(&TextureDescriptor {
89        label,
90        size: Extent3d {
91            width,
92            height,
93            depth_or_array_layers: 1,
94        },
95        mip_level_count: 1,
96        sample_count: 1,
97        dimension: TextureDimension::D2,
98        format: TextureFormat::Rgba8UnormSrgb,
99        usage: TextureUsages::COPY_DST | TextureUsages::TEXTURE_BINDING,
100        view_formats: &[],
101    })
102}
103
104/// Create an RGBA texture with render target usage.
105///
106/// Similar to `create_rgba_texture` but also includes RENDER_ATTACHMENT usage
107/// for use as a render target (e.g., for intermediate textures in shader pipelines).
108///
109/// # Arguments
110/// * `device` - The wgpu device
111/// * `width` - Texture width in pixels
112/// * `height` - Texture height in pixels
113/// * `format` - Texture format (usually matches surface format)
114/// * `label` - Optional debug label
115pub fn create_render_texture(
116    device: &Device,
117    width: u32,
118    height: u32,
119    format: TextureFormat,
120    label: Option<&str>,
121) -> Texture {
122    device.create_texture(&TextureDescriptor {
123        label,
124        size: Extent3d {
125            width,
126            height,
127            depth_or_array_layers: 1,
128        },
129        mip_level_count: 1,
130        sample_count: 1,
131        dimension: TextureDimension::D2,
132        format,
133        usage: TextureUsages::COPY_DST
134            | TextureUsages::TEXTURE_BINDING
135            | TextureUsages::RENDER_ATTACHMENT,
136        view_formats: &[],
137    })
138}
139
140/// Write RGBA pixel data to a texture.
141///
142/// # Arguments
143/// * `queue` - The wgpu queue
144/// * `texture` - The target texture
145/// * `data` - RGBA pixel data (4 bytes per pixel)
146/// * `width` - Image width in pixels
147/// * `height` - Image height in pixels
148pub fn write_rgba_texture(queue: &Queue, texture: &Texture, data: &[u8], width: u32, height: u32) {
149    queue.write_texture(
150        wgpu::TexelCopyTextureInfo {
151            texture,
152            mip_level: 0,
153            origin: wgpu::Origin3d::ZERO,
154            aspect: wgpu::TextureAspect::All,
155        },
156        data,
157        wgpu::TexelCopyBufferLayout {
158            offset: 0,
159            bytes_per_row: Some(4 * width),
160            rows_per_image: Some(height),
161        },
162        Extent3d {
163            width,
164            height,
165            depth_or_array_layers: 1,
166        },
167    );
168}
169
170/// Write RGBA pixel data to a specific region of a texture.
171///
172/// # Arguments
173/// * `queue` - The wgpu queue
174/// * `texture` - The target texture
175/// * `data` - RGBA pixel data (4 bytes per pixel)
176/// * `x` - X offset in pixels
177/// * `y` - Y offset in pixels
178/// * `width` - Region width in pixels
179/// * `height` - Region height in pixels
180pub fn write_rgba_texture_region(
181    queue: &Queue,
182    texture: &Texture,
183    data: &[u8],
184    x: u32,
185    y: u32,
186    width: u32,
187    height: u32,
188) {
189    queue.write_texture(
190        wgpu::TexelCopyTextureInfo {
191            texture,
192            mip_level: 0,
193            origin: wgpu::Origin3d { x, y, z: 0 },
194            aspect: wgpu::TextureAspect::All,
195        },
196        data,
197        wgpu::TexelCopyBufferLayout {
198            offset: 0,
199            bytes_per_row: Some(4 * width),
200            rows_per_image: Some(height),
201        },
202        Extent3d {
203            width,
204            height,
205            depth_or_array_layers: 1,
206        },
207    );
208}