librashader_common/
lib.rs

1//! Common types and conversions for librashader.
2
3/// OpenGL common conversions.
4#[cfg(feature = "opengl")]
5pub mod gl;
6
7/// Vulkan common conversions.
8#[cfg(feature = "vulkan")]
9pub mod vk;
10
11/// WGPU common conversions.
12#[cfg(feature = "wgpu")]
13pub mod wgpu;
14
15/// DXGI common conversions.
16#[cfg(all(target_os = "windows", feature = "dxgi"))]
17pub mod dxgi;
18
19/// Direct3D 9 common conversions.
20#[cfg(all(target_os = "windows", feature = "d3d9"))]
21pub mod d3d9;
22
23/// Direct3D 11 common conversions.
24#[cfg(all(target_os = "windows", feature = "d3d11"))]
25pub mod d3d11;
26
27/// Direct3D 12 common conversions.
28#[cfg(all(target_os = "windows", feature = "d3d12"))]
29pub mod d3d12;
30
31#[cfg(all(target_vendor = "apple", feature = "metal"))]
32pub mod metal;
33
34mod viewport;
35
36#[doc(hidden)]
37pub mod map;
38pub mod shader_features;
39
40pub use viewport::Viewport;
41
42use num_traits::{AsPrimitive, Num};
43use std::convert::Infallible;
44use std::ops::{Add, Sub};
45use std::str::FromStr;
46
47#[repr(u32)]
48#[derive(Default, Copy, Clone, Debug, Eq, PartialEq, Hash)]
49#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
50/// Supported image formats for textures.
51pub enum ImageFormat {
52    #[default]
53    Unknown = 0,
54
55    /* 8-bit */
56    R8Unorm,
57    R8Uint,
58    R8Sint,
59    R8G8Unorm,
60    R8G8Uint,
61    R8G8Sint,
62    R8G8B8A8Unorm,
63    R8G8B8A8Uint,
64    R8G8B8A8Sint,
65    R8G8B8A8Srgb,
66
67    /* 10-bit */
68    A2B10G10R10UnormPack32,
69    A2B10G10R10UintPack32,
70
71    /* 16-bit */
72    R16Uint,
73    R16Sint,
74    R16Sfloat,
75    R16G16Uint,
76    R16G16Sint,
77    R16G16Sfloat,
78    R16G16B16A16Uint,
79    R16G16B16A16Sint,
80    R16G16B16A16Sfloat,
81
82    /* 32-bit */
83    R32Uint,
84    R32Sint,
85    R32Sfloat,
86    R32G32Uint,
87    R32G32Sint,
88    R32G32Sfloat,
89    R32G32B32A32Uint,
90    R32G32B32A32Sint,
91    R32G32B32A32Sfloat,
92}
93
94#[repr(i32)]
95#[derive(Copy, Clone, Default, Debug, Eq, PartialEq, Hash)]
96#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
97/// The filtering mode for a texture sampler.
98pub enum FilterMode {
99    /// Linear filtering.
100    Linear = 0,
101
102    #[default]
103    /// Nearest-neighbour (point) filtering.
104    Nearest,
105}
106
107impl FromStr for WrapMode {
108    type Err = Infallible;
109
110    fn from_str(s: &str) -> Result<Self, Self::Err> {
111        Ok(match s {
112            "clamp_to_border" => WrapMode::ClampToBorder,
113            "clamp_to_edge" => WrapMode::ClampToEdge,
114            "repeat" => WrapMode::Repeat,
115            "mirrored_repeat" => WrapMode::MirroredRepeat,
116            _ => WrapMode::ClampToBorder,
117        })
118    }
119}
120
121impl FromStr for FilterMode {
122    type Err = Infallible;
123
124    fn from_str(s: &str) -> Result<Self, Self::Err> {
125        Ok(match s {
126            "linear" => FilterMode::Linear,
127            "nearest" => FilterMode::Nearest,
128            _ => FilterMode::Nearest,
129        })
130    }
131}
132
133#[repr(i32)]
134#[derive(Copy, Clone, Default, Debug, Eq, PartialEq, Hash)]
135#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
136/// The wrapping (address) mode for a texture sampler.
137pub enum WrapMode {
138    #[default]
139    /// Clamp txture to border.
140    ClampToBorder = 0,
141    /// Clamp texture to edge.
142    ClampToEdge,
143    /// Repeat addressing mode.
144    Repeat,
145    /// Mirrored repeat addressing mode.
146    MirroredRepeat,
147}
148
149impl FromStr for ImageFormat {
150    type Err = Infallible;
151
152    fn from_str(s: &str) -> Result<Self, Self::Err> {
153        Ok(match s {
154            "UNKNOWN" => Self::Unknown,
155
156            "R8_UNORM" => Self::R8Unorm,
157            "R8_UINT" => Self::R8Uint,
158            "R8_SINT" => Self::R8Sint,
159            "R8G8_UNORM" => Self::R8G8Unorm,
160            "R8G8_UINT" => Self::R8Uint,
161            "R8G8_SINT" => Self::R8G8Sint,
162            "R8G8B8A8_UNORM" => Self::R8G8B8A8Unorm,
163            "R8G8B8A8_UINT" => Self::R8G8B8A8Uint,
164            "R8G8B8A8_SINT" => Self::R8G8B8A8Sint,
165            "R8G8B8A8_SRGB" => Self::R8G8B8A8Srgb,
166
167            "A2B10G10R10_UNORM_PACK32" => Self::A2B10G10R10UnormPack32,
168            "A2B10G10R10_UINT_PACK32" => Self::A2B10G10R10UintPack32,
169
170            "R16_UINT" => Self::R16Uint,
171            "R16_SINT" => Self::R16Sint,
172            "R16_SFLOAT" => Self::R16Sfloat,
173            "R16G16_UINT" => Self::R16G16Uint,
174            "R16G16_SINT" => Self::R16G16Sint,
175            "R16G16_SFLOAT" => Self::R16G16Sfloat,
176            "R16G16B16A16_UINT" => Self::R16G16B16A16Uint,
177            "R16G16B16A16_SINT" => Self::R16G16B16A16Sint,
178            "R16G16B16A16_SFLOAT" => Self::R16G16B16A16Sfloat,
179
180            "R32_UINT" => Self::R32Uint,
181            "R32_SINT" => Self::R32Sint,
182            "R32_SFLOAT" => Self::R32Sfloat,
183            "R32G32_UINT" => Self::R32G32Uint,
184            "R32G32_SINT" => Self::R32G32Sint,
185            "R32G32_SFLOAT" => Self::R32G32Sfloat,
186            "R32G32B32A32_UINT" => Self::R32G32B32A32Uint,
187            "R32G32B32A32_SINT" => Self::R32G32B32A32Sint,
188            "R32G32B32A32_SFLOAT" => Self::R32G32B32A32Sfloat,
189            _ => Self::Unknown,
190        })
191    }
192}
193
194/// A size with a width and height.
195#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
196#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
197pub struct Size<T> {
198    pub width: T,
199    pub height: T,
200}
201
202impl<T> Size<T> {
203    /// Create a new `Size<T>` with the given width and height.
204    pub fn new(width: T, height: T) -> Self {
205        Size { width, height }
206    }
207}
208
209impl<T: AsPrimitive<f32>> Size<T> {
210    /// Get the aspect ratio of the size.
211    #[inline(always)]
212    pub fn aspect_ratio(&self) -> f32 {
213        self.width.as_() / self.height.as_()
214    }
215}
216
217impl<T: Sub<Output = T>> Sub for Size<T> {
218    type Output = Size<T>;
219
220    fn sub(self, rhs: Self) -> Self::Output {
221        Self {
222            width: self.width - rhs.width,
223            height: self.height - rhs.height,
224        }
225    }
226}
227
228impl<T: Sub<T, Output = T> + Copy> Sub<T> for Size<T> {
229    type Output = Size<T>;
230
231    fn sub(self, rhs: T) -> Self::Output {
232        Self {
233            width: self.width - rhs,
234            height: self.height - rhs,
235        }
236    }
237}
238
239impl<T: Add<Output = T>> Add for Size<T> {
240    type Output = Size<T>;
241
242    fn add(self, rhs: Self) -> Self::Output {
243        Self {
244            width: self.width + rhs.width,
245            height: self.height + rhs.height,
246        }
247    }
248}
249
250impl<T: Add<T, Output = T> + Copy> Add<T> for Size<T> {
251    type Output = Size<T>;
252
253    fn add(self, rhs: T) -> Self::Output {
254        Self {
255            width: self.width + rhs,
256            height: self.height + rhs,
257        }
258    }
259}
260
261impl<T> From<Size<T>> for [f32; 4]
262where
263    T: Copy + AsPrimitive<f32>,
264{
265    /// Convert a `Size<T>` to a `vec4` uniform.
266    fn from(value: Size<T>) -> Self {
267        [
268            value.width.as_(),
269            value.height.as_(),
270            1.0 / value.width.as_(),
271            1.0 / value.height.as_(),
272        ]
273    }
274}
275
276/// Trait for surface or texture objects that can fetch size.
277pub trait GetSize<C: Num> {
278    type Error;
279    /// Fetch the size of the object
280    fn size(&self) -> Result<Size<C>, Self::Error>;
281}
282
283impl<T: GetSize<u32>> GetSize<f32> for T {
284    type Error = T::Error;
285
286    fn size(&self) -> Result<Size<f32>, Self::Error> {
287        let size = <T as GetSize<u32>>::size(self)?;
288        Ok(Size {
289            width: size.width as f32,
290            height: size.height as f32,
291        })
292    }
293}