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 => {
54 let address_mode = if cfg!(target_arch = "wasm32") {
55 wgpu::AddressMode::ClampToEdge
56 } else {
57 wgpu::AddressMode::ClampToBorder
58 };
59 wgpu::SamplerDescriptor {
60 address_mode_u: address_mode,
61 address_mode_v: address_mode,
62 address_mode_w: address_mode,
63 mag_filter: wgpu::FilterMode::Nearest,
64 min_filter: wgpu::FilterMode::Nearest,
65 mipmap_filter: wgpu::MipmapFilterMode::Nearest,
66 border_color: if cfg!(target_arch = "wasm32") {
67 None
68 } else {
69 Some(wgpu::SamplerBorderColor::OpaqueWhite)
70 },
71 ..Default::default()
72 }
73 }
74 SamplerKind::CompareLess => wgpu::SamplerDescriptor {
75 address_mode_u: wgpu::AddressMode::ClampToEdge,
76 address_mode_v: wgpu::AddressMode::ClampToEdge,
77 address_mode_w: wgpu::AddressMode::ClampToEdge,
78 mag_filter: wgpu::FilterMode::Linear,
79 min_filter: wgpu::FilterMode::Linear,
80 mipmap_filter: wgpu::MipmapFilterMode::Linear,
81 compare: Some(wgpu::CompareFunction::Less),
82 ..Default::default()
83 },
84 }
85 }
86}
87
88const ALL_SAMPLER_KINDS: [SamplerKind; 6] = [
89 SamplerKind::LinearRepeat,
90 SamplerKind::LinearClamp,
91 SamplerKind::LinearClampNoMip,
92 SamplerKind::Nearest,
93 SamplerKind::NearestClampBorder,
94 SamplerKind::CompareLess,
95];
96
97pub struct GlobalSamplers {
100 samplers: HashMap<SamplerKind, wgpu::Sampler>,
101}
102
103impl GlobalSamplers {
104 pub fn get(&self, kind: SamplerKind) -> &wgpu::Sampler {
107 self.samplers
108 .get(&kind)
109 .expect("GlobalSamplers: all SamplerKind variants are built at construction")
110 }
111}
112
113impl LazyResource<WGPUBackend> for GlobalSamplers {
114 type Deps<'a> = ();
115
116 fn construct<'a>(backend: &WGPUBackend, _deps: &()) -> Option<Self> {
117 let samplers = ALL_SAMPLER_KINDS
118 .iter()
119 .map(|&kind| (kind, backend.device.create_sampler(&kind.descriptor())))
120 .collect();
121 Some(Self { samplers })
122 }
123}