bort_vk/
sampler.rs

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    // dependencies
14    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    // Getters
52
53    #[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}