Skip to main content

bedrock/resources/
sampler.rs

1use bedrock_vk::{self as brvk, TypedVulkanStructure, VkRawHandle};
2
3use crate::*;
4use derives::implements;
5
6pub trait Sampler: VkHandle<Handle = brvk::VkSampler> {}
7DerefContainerBracketImpl!(for Sampler {});
8GuardsImpl!(for Sampler {});
9
10#[derive(VkHandle, VkObject)]
11#[VkObject(type = brvk::VkSampler::OBJECT_TYPE)]
12pub struct SamplerObject<Device: VkHandle<Handle = brvk::VkDevice>>(pub(crate) brvk::VkSampler, pub(crate) Device);
13#[implements]
14impl<Device: VkHandle<Handle = brvk::VkDevice>> Drop for SamplerObject<Device> {
15    #[inline(always)]
16    fn drop(&mut self) {
17        unsafe {
18            crate::vkfn_wrapper::destroy_sampler(self.device_transparent_ref(), VkHandleRefMut::dangling(self.0), None);
19        }
20    }
21}
22unsafe impl<Device: VkHandle<Handle = brvk::VkDevice> + Sync> Sync for SamplerObject<Device> {}
23unsafe impl<Device: VkHandle<Handle = brvk::VkDevice> + Send> Send for SamplerObject<Device> {}
24impl<Device: VkHandle<Handle = brvk::VkDevice>> DeviceChildHandle for SamplerObject<Device> {
25    #[inline(always)]
26    fn device_handle(&self) -> brvk::VkDevice {
27        self.1.native_ptr()
28    }
29}
30impl<Device: crate::Device> DeviceChild for SamplerObject<Device> {
31    type ConcreteDevice = Device;
32
33    #[inline(always)]
34    fn device(&self) -> &Self::ConcreteDevice {
35        &self.1
36    }
37}
38impl<Device: VkHandle<Handle = brvk::VkDevice>> Sampler for SamplerObject<Device> {}
39impl<Device: VkHandle<Handle = brvk::VkDevice>> SamplerObject<Device> {
40    /// Constructs from raw values
41    /// # Safety
42    /// the resource must be created from the parent
43    pub const unsafe fn manage(handle: brvk::VkSampler, parent: Device) -> Self {
44        Self(handle, parent)
45    }
46
47    /// Purges internal values (Drop will not be called for this resource)
48    pub const fn unmanage(self) -> (brvk::VkSampler, Device) {
49        let v = self.0;
50        let p = unsafe { core::ptr::read(&self.1) };
51        core::mem::forget(self);
52
53        (v, p)
54    }
55}
56impl<Device: VkHandle<Handle = brvk::VkDevice> + Clone> SamplerObject<&'_ Device> {
57    /// Owning parent object by cloning it.
58    #[inline(always)]
59    pub fn clone_parent(self) -> SamplerObject<Device> {
60        let r = SamplerObject(self.0, self.1.clone());
61        core::mem::forget(self);
62
63        r
64    }
65}
66impl<Device: crate::Device> SamplerObject<Device> {
67    /// Create a new sampler object
68    /// # Failures
69    /// On failure, this command returns
70    ///
71    /// * `brvk::VK_ERROR_OUT_OF_HOST_MEMORY`
72    /// * `brvk::VK_ERROR_OUT_OF_DEVICE_MEMORY`
73    /// * `brvk::VK_ERROR_TOO_MANY_OBJECTS`
74    #[implements]
75    pub fn new(device: Device, info: &SamplerCreateInfo) -> crate::Result<Self> {
76        Ok(unsafe { Self::manage(device.new_sampler_raw(info, None)?, device) })
77    }
78}
79
80#[repr(transparent)]
81#[derive(Clone)]
82pub struct SamplerCreateInfo(brvk::VkSamplerCreateInfo);
83impl Default for SamplerCreateInfo {
84    #[inline(always)]
85    fn default() -> Self {
86        Self::new()
87    }
88}
89impl SamplerCreateInfo {
90    /// Initialize by default sampler parameters: Linear Filtering, Repeat addressing, no anisotrophy and no lod biases
91    pub const fn new() -> Self {
92        Self(brvk::VkSamplerCreateInfo {
93            sType: brvk::VkSamplerCreateInfo::TYPE,
94            pNext: core::ptr::null(),
95            flags: 0,
96            magFilter: FilterMode::Linear as _,
97            minFilter: FilterMode::Linear as _,
98            mipmapMode: MipmapFilterMode::Linear as _,
99            addressModeU: AddressingMode::Repeat as _,
100            addressModeV: AddressingMode::Repeat as _,
101            addressModeW: AddressingMode::Repeat as _,
102            mipLodBias: 0.0,
103            anisotropyEnable: false as _,
104            compareEnable: false as _,
105            compareOp: CompareOp::Always as _,
106            minLod: 0.0,
107            maxLod: 0.0,
108            borderColor: BorderColor::TransparentBlackF as _,
109            unnormalizedCoordinates: false as _,
110            maxAnisotropy: 1.0,
111        })
112    }
113
114    /// # Safety
115    ///
116    /// `raw` must be a valid [`brvk::VkSamplerCreateInfo`] struct.
117    pub const unsafe fn from_raw(raw: brvk::VkSamplerCreateInfo) -> Self {
118        Self(raw)
119    }
120
121    pub const fn into_raw(self) -> brvk::VkSamplerCreateInfo {
122        self.0
123    }
124
125    /// The magnification and the minification filters to apply to lookups.
126    /// Default: Magnification=`FilterMode::Linear`, Minification=`FilterMode::Linear`
127    pub const fn filter(mut self, mag: FilterMode, min: FilterMode) -> Self {
128        self.0.magFilter = mag as _;
129        self.0.minFilter = min as _;
130
131        self
132    }
133
134    /// The mipmap filter to apply to lookups.
135    /// Default: `MipmapFilterMode::Linear`
136    pub const fn mip_filter(mut self, f: MipmapFilterMode) -> Self {
137        self.0.mipmapMode = f as _;
138
139        self
140    }
141
142    /// The addressing mode for outside [0..1] range for U, V and W coordinates.
143    /// Default: U=`AddressingMode::Repeat`, V=`AddressinMode::Repeat`, W=`AddressingMode::Repeat`
144    pub const fn addressing(mut self, u: AddressingMode, v: AddressingMode, w: AddressingMode) -> Self {
145        self.0.addressModeU = u as _;
146        self.0.addressModeV = v as _;
147        self.0.addressModeW = w as _;
148
149        self
150    }
151
152    /// The bias to be added to mipmap LOD calculation and bias provided by image sampling functions in SPIR-V,
153    /// as described in the `Level-of-Detail Operation` section in Vulkan Specification.
154    /// Default: 0.0
155    pub const fn lod_bias(mut self, bias: f32) -> Self {
156        self.0.mipLodBias = bias;
157
158        self
159    }
160
161    /// The anisotropy value clamp. Specifying `None` switches off the anisotropic filtering
162    /// Default: `None`
163    pub const fn max_anisotropy(mut self, level: Option<f32>) -> Self {
164        self.0.anisotropyEnable = level.is_some() as _;
165        if let Some(l) = level {
166            self.0.maxAnisotropy = l;
167        }
168
169        self
170    }
171
172    /// The comparison function to apply to fetched data before filtering
173    /// as described in the `Depth Compare Operation` section in Vulkan Specification.
174    /// Specifying `None` switches off the comparison against a reference value during lookups.
175    /// Default: `None`
176    pub const fn comparison(mut self, op: Option<CompareOp>) -> Self {
177        self.0.compareEnable = op.is_some() as _;
178        if let Some(c) = op {
179            self.0.compareOp = c as _;
180        }
181
182        self
183    }
184
185    /// The values used to clamp the computed level-of-detail value,
186    /// as described in the `Level-of-Detail Operation` section in Vulkan Specification.
187    /// Default: min_lod=0.0, max_lod=0.0
188    /// # Panics
189    /// `max_lod` must be greater than or equal to `min_lod`
190    pub const fn lod_clamp(mut self, min_lod: f32, max_lod: f32) -> Self {
191        assert!(max_lod >= min_lod);
192        self.0.minLod = min_lod;
193        self.0.maxLod = max_lod;
194
195        self
196    }
197
198    /// Whether to use unnormalized or normalized texel coordinates to address texels of the image.
199    /// Default: `false`
200    /// # Safety
201    /// User must meet the constraints as described in the "Valid Usage" section in the `brvk::VkSamplerCreateInfo` manual page
202    pub const unsafe fn unnormalized_coordinates(mut self, use_unnormalized: bool) -> Self {
203        self.0.unnormalizedCoordinates = use_unnormalized as _;
204
205        self
206    }
207}
208
209/// Specify behavior of sampling with texture coordinates outside an image
210#[repr(C)]
211#[derive(Debug, Clone, PartialEq, Eq, Copy, Hash)]
212pub enum AddressingMode {
213    /// The repeat wrap mode
214    Repeat = brvk::VK_SAMPLER_ADDRESS_MODE_REPEAT as _,
215    /// The mirrored repeat wrap mode
216    MirroredRepeat = brvk::VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT as _,
217    /// The clamp to edge wrap mode
218    ClampToEdge = brvk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE as _,
219    /// The clamp to border wrap mode
220    ClampToBorder = brvk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER as _,
221    /// The mirror clamp to edge wrap mode
222    #[cfg(feature = "VK_KHR_sampler_mirror_clamp_to_edge")]
223    MirrorClampToEdge = brvk::VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE_KHR as _,
224}
225
226/// Specify filter used for texture lookups
227#[repr(C)]
228#[derive(Debug, Clone, PartialEq, Eq, Copy, Hash)]
229pub enum FilterMode {
230    /// Nearest filtering
231    Nearest = brvk::VK_FILTER_NEAREST as _,
232    /// Linear filtering
233    Linear = brvk::VK_FILTER_LINEAR as _,
234}
235
236/// Specify mipmap mode used for texture lookups
237#[repr(C)]
238#[derive(Debug, Clone, PartialEq, Eq, Copy, Hash)]
239pub enum MipmapFilterMode {
240    /// Nearest filtering
241    Nearest = brvk::VK_SAMPLER_MIPMAP_MODE_NEAREST as _,
242    /// Linear filtering
243    Linear = brvk::VK_SAMPLER_MIPMAP_MODE_LINEAR as _,
244}
245
246/// Specify border color used for texture lookups
247#[repr(C)]
248#[derive(Debug, Clone, PartialEq, Eq, Copy, Hash)]
249pub enum BorderColor {
250    /// A transparent, floating-point format, black color
251    TransparentBlackF = brvk::VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK as _,
252    /// A transparent, integer format, black color
253    TransparentBlackI = brvk::VK_BORDER_COLOR_INT_TRANSPARENT_BLACK as _,
254    /// An opaque, floating-point format, black color
255    OpaqueBlackF = brvk::VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK as _,
256    /// An opaque, integer format, black color
257    OpaqueBlackI = brvk::VK_BORDER_COLOR_INT_OPAQUE_BLACK as _,
258    /// An opaque, floating-point format, white color
259    OpaqueWhiteF = brvk::VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE as _,
260    /// An opaque, integer format, white color
261    OpaqueWhiteI = brvk::VK_BORDER_COLOR_INT_OPAQUE_WHITE as _,
262}