1use crate::{Device, DeviceOwned, ALLOCATION_CALLBACK_NONE};
2use ash::{
3 prelude::VkResult,
4 vk::{self, Handle},
5};
6use std::sync::Arc;
7
8#[derive(Clone)]
9pub struct Sampler {
10 handle: vk::Sampler,
11 properties: SamplerProperties,
12
13 device: Arc<Device>,
15}
16
17impl Sampler {
18 pub fn new(device: Arc<Device>, properties: SamplerProperties) -> VkResult<Self> {
19 let handle = unsafe {
20 device
21 .inner()
22 .create_sampler(&properties.create_info_builder(), ALLOCATION_CALLBACK_NONE)
23 }?;
24
25 Ok(Self {
26 handle,
27 properties,
28 device,
29 })
30 }
31
32 pub unsafe fn new_from_create_info(
33 device: Arc<Device>,
34 create_info_builder: vk::SamplerCreateInfoBuilder,
35 ) -> VkResult<Self> {
36 let properties = SamplerProperties::from_create_info_builder(&create_info_builder);
37
38 let handle = unsafe {
39 device
40 .inner()
41 .create_sampler(&create_info_builder, ALLOCATION_CALLBACK_NONE)
42 }?;
43
44 Ok(Self {
45 handle,
46 properties,
47 device,
48 })
49 }
50
51 #[inline]
54 pub fn handle(&self) -> vk::Sampler {
55 self.handle
56 }
57
58 #[inline]
59 pub fn properties(&self) -> &SamplerProperties {
60 &self.properties
61 }
62}
63
64impl DeviceOwned for Sampler {
65 #[inline]
66 fn device(&self) -> &Arc<Device> {
67 &self.device
68 }
69
70 #[inline]
71 fn handle_raw(&self) -> u64 {
72 self.handle.as_raw()
73 }
74}
75
76impl Drop for Sampler {
77 fn drop(&mut self) {
78 unsafe {
79 self.device
80 .inner()
81 .destroy_sampler(self.handle, ALLOCATION_CALLBACK_NONE);
82 }
83 }
84}
85
86#[derive(Debug, Clone, Copy)]
87pub struct SamplerProperties {
88 pub flags: vk::SamplerCreateFlags,
89 pub mag_filter: vk::Filter,
90 pub min_filter: vk::Filter,
91 pub mipmap_mode: vk::SamplerMipmapMode,
92 pub address_mode: [vk::SamplerAddressMode; 3],
93 pub mip_lod_bias: f32,
94 pub max_anisotropy: Option<f32>,
95 pub compare_op: Option<vk::CompareOp>,
96 pub min_lod: f32,
97 pub max_lod: f32,
98 pub border_color: vk::BorderColor,
99 pub unnormalized_coordinates: bool,
100}
101
102impl Default for SamplerProperties {
103 fn default() -> Self {
104 Self {
105 flags: vk::SamplerCreateFlags::empty(),
106 mag_filter: vk::Filter::NEAREST,
107 min_filter: vk::Filter::NEAREST,
108 mipmap_mode: vk::SamplerMipmapMode::NEAREST,
109 address_mode: [vk::SamplerAddressMode::CLAMP_TO_EDGE; 3],
110 mip_lod_bias: 0.,
111 max_anisotropy: None,
112 compare_op: None,
113 min_lod: 0.,
114 max_lod: vk::LOD_CLAMP_NONE,
115 border_color: vk::BorderColor::FLOAT_TRANSPARENT_BLACK,
116 unnormalized_coordinates: false,
117 }
118 }
119}
120
121impl SamplerProperties {
122 pub fn write_create_info_builder<'a>(
123 &'a self,
124 builder: vk::SamplerCreateInfoBuilder<'a>,
125 ) -> vk::SamplerCreateInfoBuilder {
126 builder
127 .flags(self.flags)
128 .mag_filter(self.mag_filter)
129 .min_filter(self.min_filter)
130 .mipmap_mode(self.mipmap_mode)
131 .address_mode_u(self.address_mode[0])
132 .address_mode_v(self.address_mode[1])
133 .address_mode_w(self.address_mode[2])
134 .mip_lod_bias(self.mip_lod_bias)
135 .anisotropy_enable(self.max_anisotropy.is_some())
136 .max_anisotropy(self.max_anisotropy.unwrap_or(0.))
137 .compare_enable(self.compare_op.is_some())
138 .compare_op(self.compare_op.unwrap_or(vk::CompareOp::NEVER))
139 .min_lod(self.min_lod)
140 .max_lod(self.max_lod)
141 .border_color(self.border_color)
142 .unnormalized_coordinates(self.unnormalized_coordinates)
143 }
144
145 pub fn create_info_builder(&self) -> vk::SamplerCreateInfoBuilder {
146 self.write_create_info_builder(vk::SamplerCreateInfo::builder())
147 }
148
149 pub fn from_create_info_builder(create_info: &vk::SamplerCreateInfoBuilder) -> Self {
150 Self {
151 flags: create_info.flags,
152 mag_filter: create_info.mag_filter,
153 min_filter: create_info.min_filter,
154 mipmap_mode: create_info.mipmap_mode,
155 address_mode: [
156 create_info.address_mode_u,
157 create_info.address_mode_v,
158 create_info.address_mode_w,
159 ],
160 mip_lod_bias: create_info.mip_lod_bias,
161 max_anisotropy: if create_info.anisotropy_enable != 0 {
162 Some(create_info.max_anisotropy)
163 } else {
164 None
165 },
166 compare_op: if create_info.compare_enable != 0 {
167 Some(create_info.compare_op)
168 } else {
169 None
170 },
171 min_lod: create_info.min_lod,
172 max_lod: create_info.max_lod,
173 border_color: create_info.border_color,
174 unnormalized_coordinates: create_info.unnormalized_coordinates != 0,
175 }
176 }
177}