naga/back/glsl/
conv.rs

1use crate::back::glsl::{BackendResult, Error, VaryingOptions};
2
3/// Structure returned by [`glsl_scalar`]
4///
5/// It contains both a prefix used in other types and the full type name
6pub(in crate::back::glsl) struct ScalarString<'a> {
7    /// The prefix used to compose other types
8    pub prefix: &'a str,
9    /// The name of the scalar type
10    pub full: &'a str,
11}
12
13/// Helper function that returns scalar related strings
14///
15/// Check [`ScalarString`] for the information provided
16///
17/// # Errors
18/// If a [`Float`](crate::ScalarKind::Float) with an width that isn't 4 or 8
19pub(in crate::back::glsl) const fn glsl_scalar(
20    scalar: crate::Scalar,
21) -> Result<ScalarString<'static>, Error> {
22    use crate::ScalarKind as Sk;
23
24    Ok(match scalar.kind {
25        Sk::Sint => ScalarString {
26            prefix: "i",
27            full: "int",
28        },
29        Sk::Uint => ScalarString {
30            prefix: "u",
31            full: "uint",
32        },
33        Sk::Float => match scalar.width {
34            4 => ScalarString {
35                prefix: "",
36                full: "float",
37            },
38            8 => ScalarString {
39                prefix: "d",
40                full: "double",
41            },
42            _ => return Err(Error::UnsupportedScalar(scalar)),
43        },
44        Sk::Bool => ScalarString {
45            prefix: "b",
46            full: "bool",
47        },
48        Sk::AbstractInt | Sk::AbstractFloat => {
49            return Err(Error::UnsupportedScalar(scalar));
50        }
51    })
52}
53
54/// Helper function that returns the glsl variable name for a builtin
55pub(in crate::back::glsl) const fn glsl_built_in(
56    built_in: crate::BuiltIn,
57    options: VaryingOptions,
58) -> &'static str {
59    use crate::BuiltIn as Bi;
60
61    match built_in {
62        Bi::Position { .. } => {
63            if options.output {
64                "gl_Position"
65            } else {
66                "gl_FragCoord"
67            }
68        }
69        Bi::ViewIndex => {
70            if options.targeting_webgl {
71                "gl_ViewID_OVR"
72            } else {
73                "uint(gl_ViewIndex)"
74            }
75        }
76        // vertex
77        Bi::BaseInstance => "uint(gl_BaseInstance)",
78        Bi::BaseVertex => "uint(gl_BaseVertex)",
79        Bi::ClipDistance => "gl_ClipDistance",
80        Bi::CullDistance => "gl_CullDistance",
81        Bi::InstanceIndex => {
82            if options.draw_parameters {
83                "(uint(gl_InstanceID) + uint(gl_BaseInstanceARB))"
84            } else {
85                // Must match FIRST_INSTANCE_BINDING
86                "(uint(gl_InstanceID) + naga_vs_first_instance)"
87            }
88        }
89        Bi::PointSize => "gl_PointSize",
90        Bi::VertexIndex => "uint(gl_VertexID)",
91        Bi::DrawID => "gl_DrawID",
92        // fragment
93        Bi::FragDepth => "gl_FragDepth",
94        Bi::PointCoord => "gl_PointCoord",
95        Bi::FrontFacing => "gl_FrontFacing",
96        Bi::PrimitiveIndex => "uint(gl_PrimitiveID)",
97        Bi::Barycentric { perspective: true } => "gl_BaryCoordEXT",
98        Bi::Barycentric { perspective: false } => "gl_BaryCoordNoPerspEXT",
99        Bi::SampleIndex => "gl_SampleID",
100        Bi::SampleMask => {
101            if options.output {
102                "gl_SampleMask"
103            } else {
104                "gl_SampleMaskIn"
105            }
106        }
107        // compute
108        Bi::GlobalInvocationId => "gl_GlobalInvocationID",
109        Bi::LocalInvocationId => "gl_LocalInvocationID",
110        Bi::LocalInvocationIndex => "gl_LocalInvocationIndex",
111        Bi::WorkGroupId => "gl_WorkGroupID",
112        Bi::WorkGroupSize => "gl_WorkGroupSize",
113        Bi::NumWorkGroups => "gl_NumWorkGroups",
114        // subgroup
115        Bi::NumSubgroups => "gl_NumSubgroups",
116        Bi::SubgroupId => "gl_SubgroupID",
117        Bi::SubgroupSize => "gl_SubgroupSize",
118        Bi::SubgroupInvocationId => "gl_SubgroupInvocationID",
119        // mesh
120        // TODO: figure out how to map these to glsl things as glsl treats them as arrays
121        Bi::CullPrimitive
122        | Bi::PointIndex
123        | Bi::LineIndices
124        | Bi::TriangleIndices
125        | Bi::MeshTaskSize
126        | Bi::VertexCount
127        | Bi::PrimitiveCount
128        | Bi::Vertices
129        | Bi::Primitives => {
130            unimplemented!()
131        }
132    }
133}
134
135/// Helper function that returns the string corresponding to the address space
136pub(in crate::back::glsl) const fn glsl_storage_qualifier(
137    space: crate::AddressSpace,
138) -> Option<&'static str> {
139    use crate::AddressSpace as As;
140
141    match space {
142        As::Function => None,
143        As::Private => None,
144        As::Storage { .. } => Some("buffer"),
145        As::Uniform => Some("uniform"),
146        As::Handle => Some("uniform"),
147        As::WorkGroup => Some("shared"),
148        As::Immediate => Some("uniform"),
149        As::TaskPayload => unreachable!(),
150    }
151}
152
153/// Helper function that returns the string corresponding to the glsl interpolation qualifier
154pub(in crate::back::glsl) const fn glsl_interpolation(
155    interpolation: crate::Interpolation,
156) -> &'static str {
157    use crate::Interpolation as I;
158
159    match interpolation {
160        I::Perspective => "smooth",
161        I::Linear => "noperspective",
162        I::Flat => "flat",
163        I::PerVertex => unreachable!(),
164    }
165}
166
167/// Return the GLSL auxiliary qualifier for the given sampling value.
168pub(in crate::back::glsl) const fn glsl_sampling(
169    sampling: crate::Sampling,
170) -> BackendResult<Option<&'static str>> {
171    use crate::Sampling as S;
172
173    Ok(match sampling {
174        S::First => return Err(Error::FirstSamplingNotSupported),
175        S::Center | S::Either => None,
176        S::Centroid => Some("centroid"),
177        S::Sample => Some("sample"),
178    })
179}
180
181/// Helper function that returns the glsl dimension string of [`ImageDimension`](crate::ImageDimension)
182pub(in crate::back::glsl) const fn glsl_dimension(dim: crate::ImageDimension) -> &'static str {
183    use crate::ImageDimension as IDim;
184
185    match dim {
186        IDim::D1 => "1D",
187        IDim::D2 => "2D",
188        IDim::D3 => "3D",
189        IDim::Cube => "Cube",
190    }
191}
192
193/// Helper function that returns the glsl storage format string of [`StorageFormat`](crate::StorageFormat)
194pub(in crate::back::glsl) fn glsl_storage_format(
195    format: crate::StorageFormat,
196) -> Result<&'static str, Error> {
197    use crate::StorageFormat as Sf;
198
199    Ok(match format {
200        Sf::R8Unorm => "r8",
201        Sf::R8Snorm => "r8_snorm",
202        Sf::R8Uint => "r8ui",
203        Sf::R8Sint => "r8i",
204        Sf::R16Uint => "r16ui",
205        Sf::R16Sint => "r16i",
206        Sf::R16Float => "r16f",
207        Sf::Rg8Unorm => "rg8",
208        Sf::Rg8Snorm => "rg8_snorm",
209        Sf::Rg8Uint => "rg8ui",
210        Sf::Rg8Sint => "rg8i",
211        Sf::R32Uint => "r32ui",
212        Sf::R32Sint => "r32i",
213        Sf::R32Float => "r32f",
214        Sf::Rg16Uint => "rg16ui",
215        Sf::Rg16Sint => "rg16i",
216        Sf::Rg16Float => "rg16f",
217        Sf::Rgba8Unorm => "rgba8",
218        Sf::Rgba8Snorm => "rgba8_snorm",
219        Sf::Rgba8Uint => "rgba8ui",
220        Sf::Rgba8Sint => "rgba8i",
221        Sf::Rgb10a2Uint => "rgb10_a2ui",
222        Sf::Rgb10a2Unorm => "rgb10_a2",
223        Sf::Rg11b10Ufloat => "r11f_g11f_b10f",
224        Sf::R64Uint => "r64ui",
225        Sf::Rg32Uint => "rg32ui",
226        Sf::Rg32Sint => "rg32i",
227        Sf::Rg32Float => "rg32f",
228        Sf::Rgba16Uint => "rgba16ui",
229        Sf::Rgba16Sint => "rgba16i",
230        Sf::Rgba16Float => "rgba16f",
231        Sf::Rgba32Uint => "rgba32ui",
232        Sf::Rgba32Sint => "rgba32i",
233        Sf::Rgba32Float => "rgba32f",
234        Sf::R16Unorm => "r16",
235        Sf::R16Snorm => "r16_snorm",
236        Sf::Rg16Unorm => "rg16",
237        Sf::Rg16Snorm => "rg16_snorm",
238        Sf::Rgba16Unorm => "rgba16",
239        Sf::Rgba16Snorm => "rgba16_snorm",
240
241        Sf::Bgra8Unorm => {
242            return Err(Error::Custom(
243                "Support format BGRA8 is not implemented".into(),
244            ))
245        }
246    })
247}