Skip to main content

pebble/wgpu/
samplers.rs

1use std::collections::HashMap;
2
3use crate::{assets::singleton_asset::LazyResource, wgpu::backend::WGPUBackend};
4
5#[derive(Clone, Copy, PartialEq, Eq, Hash)]
6pub enum SamplerKind {
7    LinearRepeat,
8    LinearClamp,
9    LinearClampNoMip,
10    Nearest,
11    NearestClampBorder,
12    CompareLess,
13}
14
15impl SamplerKind {
16    pub fn descriptor(&self) -> wgpu::SamplerDescriptor<'static> {
17        match self {
18            SamplerKind::LinearRepeat => wgpu::SamplerDescriptor {
19                address_mode_u: wgpu::AddressMode::Repeat,
20                address_mode_v: wgpu::AddressMode::Repeat,
21                address_mode_w: wgpu::AddressMode::Repeat,
22                mag_filter: wgpu::FilterMode::Linear,
23                min_filter: wgpu::FilterMode::Linear,
24                mipmap_filter: wgpu::MipmapFilterMode::Linear,
25                ..Default::default()
26            },
27            SamplerKind::LinearClamp => wgpu::SamplerDescriptor {
28                address_mode_u: wgpu::AddressMode::ClampToEdge,
29                address_mode_v: wgpu::AddressMode::ClampToEdge,
30                address_mode_w: wgpu::AddressMode::ClampToEdge,
31                mag_filter: wgpu::FilterMode::Linear,
32                min_filter: wgpu::FilterMode::Linear,
33                mipmap_filter: wgpu::MipmapFilterMode::Linear,
34                ..Default::default()
35            },
36            SamplerKind::LinearClampNoMip => wgpu::SamplerDescriptor {
37                address_mode_u: wgpu::AddressMode::ClampToEdge,
38                address_mode_v: wgpu::AddressMode::ClampToEdge,
39                address_mode_w: wgpu::AddressMode::ClampToEdge,
40                mag_filter: wgpu::FilterMode::Linear,
41                min_filter: wgpu::FilterMode::Linear,
42                mipmap_filter: wgpu::MipmapFilterMode::Linear,
43                lod_min_clamp: 0.0,
44                lod_max_clamp: 0.0,
45                ..Default::default()
46            },
47            SamplerKind::Nearest => wgpu::SamplerDescriptor {
48                mag_filter: wgpu::FilterMode::Nearest,
49                min_filter: wgpu::FilterMode::Nearest,
50                mipmap_filter: wgpu::MipmapFilterMode::Linear,
51                ..Default::default()
52            },
53            SamplerKind::NearestClampBorder => wgpu::SamplerDescriptor {
54                address_mode_u: wgpu::AddressMode::ClampToBorder,
55                address_mode_v: wgpu::AddressMode::ClampToBorder,
56                address_mode_w: wgpu::AddressMode::ClampToBorder,
57                mag_filter: wgpu::FilterMode::Nearest,
58                min_filter: wgpu::FilterMode::Nearest,
59                mipmap_filter: wgpu::MipmapFilterMode::Nearest,
60                border_color: Some(wgpu::SamplerBorderColor::OpaqueWhite),
61                ..Default::default()
62            },
63            SamplerKind::CompareLess => wgpu::SamplerDescriptor {
64                address_mode_u: wgpu::AddressMode::ClampToEdge,
65                address_mode_v: wgpu::AddressMode::ClampToEdge,
66                address_mode_w: wgpu::AddressMode::ClampToEdge,
67                mag_filter: wgpu::FilterMode::Linear,
68                min_filter: wgpu::FilterMode::Linear,
69                mipmap_filter: wgpu::MipmapFilterMode::Linear,
70                compare: Some(wgpu::CompareFunction::Less),
71                ..Default::default()
72            },
73        }
74    }
75}
76
77const ALL_SAMPLER_KINDS: [SamplerKind; 6] = [
78    SamplerKind::LinearRepeat,
79    SamplerKind::LinearClamp,
80    SamplerKind::LinearClampNoMip,
81    SamplerKind::Nearest,
82    SamplerKind::NearestClampBorder,
83    SamplerKind::CompareLess,
84];
85
86/// Every [`SamplerKind`] built once and shared across all materials, rather
87/// than each material instance creating its own duplicate `wgpu::Sampler`.
88pub struct GlobalSamplers {
89    samplers: HashMap<SamplerKind, wgpu::Sampler>,
90}
91
92impl GlobalSamplers {
93    /// Look up a shared sampler by kind. Panics if `kind` is somehow missing
94    /// — every [`SamplerKind`] variant is built eagerly in [`LazyResource::construct`].
95    pub fn get(&self, kind: SamplerKind) -> &wgpu::Sampler {
96        self.samplers
97            .get(&kind)
98            .expect("GlobalSamplers: all SamplerKind variants are built at construction")
99    }
100}
101
102impl LazyResource<WGPUBackend> for GlobalSamplers {
103    type Deps<'a> = ();
104
105    fn construct<'a>(backend: &WGPUBackend, _deps: &()) -> Option<Self> {
106        let samplers = ALL_SAMPLER_KINDS
107            .iter()
108            .map(|&kind| (kind, backend.device.create_sampler(&kind.descriptor())))
109            .collect();
110        Some(Self { samplers })
111    }
112}