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