Skip to main content

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;
39pub mod string;
40
41pub use viewport::Viewport;
42
43use num_traits::{AsPrimitive, Num};
44use std::convert::Infallible;
45use std::ops::{Add, Sub};
46use std::str::FromStr;
47
48#[repr(u32)]
49#[derive(Default, Copy, Clone, Debug, Eq, PartialEq, Hash)]
50#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
51/// Supported image formats for textures.
52pub enum ImageFormat {
53    #[default]
54    Unknown = 0,
55
56    /* 8-bit */
57    R8Unorm,
58    R8Uint,
59    R8Sint,
60    R8G8Unorm,
61    R8G8Uint,
62    R8G8Sint,
63    R8G8B8A8Unorm,
64    R8G8B8A8Uint,
65    R8G8B8A8Sint,
66    R8G8B8A8Srgb,
67
68    /* 10-bit */
69    A2B10G10R10UnormPack32,
70    A2B10G10R10UintPack32,
71
72    /* 16-bit */
73    R16Uint,
74    R16Sint,
75    R16Sfloat,
76    R16G16Uint,
77    R16G16Sint,
78    R16G16Sfloat,
79    R16G16B16A16Uint,
80    R16G16B16A16Sint,
81    R16G16B16A16Sfloat,
82
83    /* 32-bit */
84    R32Uint,
85    R32Sint,
86    R32Sfloat,
87    R32G32Uint,
88    R32G32Sint,
89    R32G32Sfloat,
90    R32G32B32A32Uint,
91    R32G32B32A32Sint,
92    R32G32B32A32Sfloat,
93}
94
95#[repr(i32)]
96#[derive(Copy, Clone, Default, Debug, Eq, PartialEq, Hash)]
97#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
98/// The filtering mode for a texture sampler.
99pub enum FilterMode {
100    /// Linear filtering.
101    Linear = 0,
102
103    #[default]
104    /// Nearest-neighbour (point) filtering.
105    Nearest,
106}
107
108impl FromStr for WrapMode {
109    type Err = Infallible;
110
111    fn from_str(s: &str) -> Result<Self, Self::Err> {
112        Ok(match s {
113            "clamp_to_border" => WrapMode::ClampToBorder,
114            "clamp_to_edge" => WrapMode::ClampToEdge,
115            "repeat" => WrapMode::Repeat,
116            "mirrored_repeat" => WrapMode::MirroredRepeat,
117            _ => WrapMode::ClampToBorder,
118        })
119    }
120}
121
122impl FromStr for FilterMode {
123    type Err = Infallible;
124
125    fn from_str(s: &str) -> Result<Self, Self::Err> {
126        Ok(match s {
127            "linear" => FilterMode::Linear,
128            "nearest" => FilterMode::Nearest,
129            _ => FilterMode::Nearest,
130        })
131    }
132}
133
134/// Supported HDR (and SDR) color spaces for HDR shaders.
135#[repr(u32)]
136#[derive(Default, Copy, Clone, Debug, Eq, PartialEq, Hash)]
137#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
138pub enum ColorSpace {
139    /// Standard dynamic range / sRGB nonlinear (no HDR).
140    #[default]
141    Sdr = 0,
142    /// HDR10: BT.2020 primaries with PQ (ST.2084) transfer, stored as
143    /// 10-bit unorm (A2R10G10B10).
144    Hdr10 = 1,
145    /// scRGB: BT.709 primaries, linear, extended range. Typically stored as
146    /// FP16 (R16G16B16A16Sfloat) where 1.0 corresponds to 80 nits.
147    ScRgb = 2,
148    /// PQ-encoded data stored in an scRGB FP16 surface.
149    PqScRgb = 3,
150}
151
152impl ColorSpace {
153    /// Whether this color space is an HDR color space or not.
154    pub fn is_hdr(&self) -> bool {
155        !matches!(*self, ColorSpace::Sdr)
156    }
157}
158
159#[repr(i32)]
160#[derive(Copy, Clone, Default, Debug, Eq, PartialEq, Hash)]
161#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
162/// The wrapping (address) mode for a texture sampler.
163pub enum WrapMode {
164    #[default]
165    /// Clamp txture to border.
166    ClampToBorder = 0,
167    /// Clamp texture to edge.
168    ClampToEdge,
169    /// Repeat addressing mode.
170    Repeat,
171    /// Mirrored repeat addressing mode.
172    MirroredRepeat,
173}
174
175impl FromStr for ImageFormat {
176    type Err = Infallible;
177
178    fn from_str(s: &str) -> Result<Self, Self::Err> {
179        Ok(match s {
180            "UNKNOWN" => Self::Unknown,
181
182            "R8_UNORM" => Self::R8Unorm,
183            "R8_UINT" => Self::R8Uint,
184            "R8_SINT" => Self::R8Sint,
185            "R8G8_UNORM" => Self::R8G8Unorm,
186            "R8G8_UINT" => Self::R8Uint,
187            "R8G8_SINT" => Self::R8G8Sint,
188            "R8G8B8A8_UNORM" => Self::R8G8B8A8Unorm,
189            "R8G8B8A8_UINT" => Self::R8G8B8A8Uint,
190            "R8G8B8A8_SINT" => Self::R8G8B8A8Sint,
191            "R8G8B8A8_SRGB" => Self::R8G8B8A8Srgb,
192
193            "A2B10G10R10_UNORM_PACK32" => Self::A2B10G10R10UnormPack32,
194            "A2B10G10R10_UINT_PACK32" => Self::A2B10G10R10UintPack32,
195
196            "R16_UINT" => Self::R16Uint,
197            "R16_SINT" => Self::R16Sint,
198            "R16_SFLOAT" => Self::R16Sfloat,
199            "R16G16_UINT" => Self::R16G16Uint,
200            "R16G16_SINT" => Self::R16G16Sint,
201            "R16G16_SFLOAT" => Self::R16G16Sfloat,
202            "R16G16B16A16_UINT" => Self::R16G16B16A16Uint,
203            "R16G16B16A16_SINT" => Self::R16G16B16A16Sint,
204            "R16G16B16A16_SFLOAT" => Self::R16G16B16A16Sfloat,
205
206            "R32_UINT" => Self::R32Uint,
207            "R32_SINT" => Self::R32Sint,
208            "R32_SFLOAT" => Self::R32Sfloat,
209            "R32G32_UINT" => Self::R32G32Uint,
210            "R32G32_SINT" => Self::R32G32Sint,
211            "R32G32_SFLOAT" => Self::R32G32Sfloat,
212            "R32G32B32A32_UINT" => Self::R32G32B32A32Uint,
213            "R32G32B32A32_SINT" => Self::R32G32B32A32Sint,
214            "R32G32B32A32_SFLOAT" => Self::R32G32B32A32Sfloat,
215            _ => Self::Unknown,
216        })
217    }
218}
219
220/// A size with a width and height.
221#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
222#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
223pub struct Size<T> {
224    pub width: T,
225    pub height: T,
226}
227
228impl<T> Size<T> {
229    /// Create a new `Size<T>` with the given width and height.
230    pub fn new(width: T, height: T) -> Self {
231        Size { width, height }
232    }
233}
234
235impl<T: AsPrimitive<f32>> Size<T> {
236    /// Get the aspect ratio of the size.
237    #[inline(always)]
238    pub fn aspect_ratio(&self) -> f32 {
239        self.width.as_() / self.height.as_()
240    }
241}
242
243impl<T: Sub<Output = T>> Sub for Size<T> {
244    type Output = Size<T>;
245
246    fn sub(self, rhs: Self) -> Self::Output {
247        Self {
248            width: self.width - rhs.width,
249            height: self.height - rhs.height,
250        }
251    }
252}
253
254impl<T: Sub<T, Output = T> + Copy> Sub<T> for Size<T> {
255    type Output = Size<T>;
256
257    fn sub(self, rhs: T) -> Self::Output {
258        Self {
259            width: self.width - rhs,
260            height: self.height - rhs,
261        }
262    }
263}
264
265impl<T: Add<Output = T>> Add for Size<T> {
266    type Output = Size<T>;
267
268    fn add(self, rhs: Self) -> Self::Output {
269        Self {
270            width: self.width + rhs.width,
271            height: self.height + rhs.height,
272        }
273    }
274}
275
276impl<T: Add<T, Output = T> + Copy> Add<T> for Size<T> {
277    type Output = Size<T>;
278
279    fn add(self, rhs: T) -> Self::Output {
280        Self {
281            width: self.width + rhs,
282            height: self.height + rhs,
283        }
284    }
285}
286
287impl<T> From<Size<T>> for [f32; 4]
288where
289    T: Copy + AsPrimitive<f32>,
290{
291    /// Convert a `Size<T>` to a `vec4` uniform.
292    fn from(value: Size<T>) -> Self {
293        [
294            value.width.as_(),
295            value.height.as_(),
296            1.0 / value.width.as_(),
297            1.0 / value.height.as_(),
298        ]
299    }
300}
301
302/// Trait for surface or texture objects that can fetch size.
303pub trait GetSize<C: Num> {
304    type Error;
305    /// Fetch the size of the object
306    fn size(&self) -> Result<Size<C>, Self::Error>;
307}
308
309impl<T: GetSize<u32>> GetSize<f32> for T {
310    type Error = T::Error;
311
312    fn size(&self) -> Result<Size<f32>, Self::Error> {
313        let size = <T as GetSize<u32>>::size(self)?;
314        Ok(Size {
315            width: size.width as f32,
316            height: size.height as f32,
317        })
318    }
319}