1use crate::common;
2
3use alloc::{borrow::Cow, format, string::String};
4
5use super::Error;
6use crate::proc::Alignment;
7
8impl crate::ScalarKind {
9 pub(super) fn to_hlsl_cast(self) -> &'static str {
10 match self {
11 Self::Float => "asfloat",
12 Self::Sint => "asint",
13 Self::Uint => "asuint",
14 Self::Bool | Self::AbstractInt | Self::AbstractFloat => unreachable!(),
15 }
16 }
17}
18
19impl crate::Scalar {
20 pub(super) const fn to_hlsl_str(self) -> Result<&'static str, Error> {
24 match self.kind {
25 crate::ScalarKind::Sint => match self.width {
26 2 => Ok("int16_t"),
27 4 => Ok("int"),
28 8 => Ok("int64_t"),
29 _ => Err(Error::UnsupportedScalar(self)),
30 },
31 crate::ScalarKind::Uint => match self.width {
32 2 => Ok("uint16_t"),
33 4 => Ok("uint"),
34 8 => Ok("uint64_t"),
35 _ => Err(Error::UnsupportedScalar(self)),
36 },
37 crate::ScalarKind::Float => match self.width {
38 2 => Ok("half"),
39 4 => Ok("float"),
40 8 => Ok("double"),
41 _ => Err(Error::UnsupportedScalar(self)),
42 },
43 crate::ScalarKind::Bool => Ok("bool"),
44 crate::ScalarKind::AbstractInt | crate::ScalarKind::AbstractFloat => {
45 Err(Error::UnsupportedScalar(self))
46 }
47 }
48 }
49}
50
51impl crate::TypeInner {
52 pub(super) const fn is_matrix(&self) -> bool {
53 match *self {
54 Self::Matrix { .. } => true,
55 _ => false,
56 }
57 }
58
59 pub(super) fn size_hlsl(&self, gctx: crate::proc::GlobalCtx) -> Result<u32, Error> {
60 match *self {
61 Self::Matrix {
62 columns,
63 rows,
64 scalar,
65 } => {
66 let stride = Alignment::from(rows) * scalar.width as u32;
67 let last_row_size = rows as u32 * scalar.width as u32;
68 Ok(((columns as u32 - 1) * stride) + last_row_size)
69 }
70 Self::Array { base, size, stride } => {
71 let count = match size.resolve(gctx)? {
72 crate::proc::IndexableLength::Known(size) => size,
73 crate::proc::IndexableLength::Dynamic => 1,
75 };
76 let last_el_size = gctx.types[base].inner.size_hlsl(gctx)?;
77 Ok(((count - 1) * stride) + last_el_size)
78 }
79 _ => Ok(self.size(gctx)),
80 }
81 }
82
83 pub(super) fn hlsl_type_id<'a>(
85 base: crate::Handle<crate::Type>,
86 gctx: crate::proc::GlobalCtx,
87 names: &'a crate::FastHashMap<crate::proc::NameKey, String>,
88 ) -> Result<Cow<'a, str>, Error> {
89 Ok(match gctx.types[base].inner {
90 crate::TypeInner::Scalar(scalar) => Cow::Borrowed(scalar.to_hlsl_str()?),
91 crate::TypeInner::Vector { size, scalar } => Cow::Owned(format!(
92 "{}{}",
93 scalar.to_hlsl_str()?,
94 common::vector_size_str(size)
95 )),
96 crate::TypeInner::Matrix {
97 columns,
98 rows,
99 scalar,
100 } => Cow::Owned(format!(
101 "{}{}x{}",
102 scalar.to_hlsl_str()?,
103 common::vector_size_str(columns),
104 common::vector_size_str(rows),
105 )),
106 crate::TypeInner::Array {
107 base,
108 size: crate::ArraySize::Constant(size),
109 ..
110 } => Cow::Owned(format!(
111 "array{size}_{}_",
112 Self::hlsl_type_id(base, gctx, names)?
113 )),
114 crate::TypeInner::Struct { .. } => {
115 Cow::Borrowed(&names[&crate::proc::NameKey::Type(base)])
116 }
117 _ => unreachable!(),
118 })
119 }
120}
121
122impl crate::StorageFormat {
123 pub(super) const fn to_hlsl_str(self) -> &'static str {
124 match self {
125 Self::R16Float | Self::R32Float => "float",
126 Self::R8Unorm | Self::R16Unorm => "unorm float",
127 Self::R8Snorm | Self::R16Snorm => "snorm float",
128 Self::R8Uint | Self::R16Uint | Self::R32Uint => "uint",
129 Self::R8Sint | Self::R16Sint | Self::R32Sint => "int",
130 Self::R64Uint => "uint64_t",
131
132 Self::Rg16Float | Self::Rg32Float => "float4",
133 Self::Rg8Unorm | Self::Rg16Unorm => "unorm float4",
134 Self::Rg8Snorm | Self::Rg16Snorm => "snorm float4",
135
136 Self::Rg8Sint | Self::Rg16Sint | Self::Rg32Uint => "int4",
137 Self::Rg8Uint | Self::Rg16Uint | Self::Rg32Sint => "uint4",
138
139 Self::Rg11b10Ufloat => "float4",
140
141 Self::Rgba16Float | Self::Rgba32Float => "float4",
142 Self::Rgba8Unorm | Self::Bgra8Unorm | Self::Rgba16Unorm | Self::Rgb10a2Unorm => {
143 "unorm float4"
144 }
145 Self::Rgba8Snorm | Self::Rgba16Snorm => "snorm float4",
146
147 Self::Rgba8Uint | Self::Rgba16Uint | Self::Rgba32Uint | Self::Rgb10a2Uint => "uint4",
148 Self::Rgba8Sint | Self::Rgba16Sint | Self::Rgba32Sint => "int4",
149 }
150 }
151}
152
153impl crate::BuiltIn {
154 pub(super) fn to_hlsl_str(self) -> Result<Option<&'static str>, Error> {
157 Ok(Some(match self {
158 Self::Position { .. } => "SV_Position",
159 Self::ClipDistances => "SV_ClipDistance",
161 Self::CullDistance => "SV_CullDistance",
162 Self::InstanceIndex => "SV_InstanceID",
163 Self::VertexIndex => "SV_VertexID",
164 Self::FragDepth => "SV_Depth",
166 Self::FrontFacing => "SV_IsFrontFace",
167 Self::PrimitiveIndex => "SV_PrimitiveID",
168 Self::Barycentric { .. } => "SV_Barycentrics",
169 Self::SampleIndex => "SV_SampleIndex",
170 Self::SampleMask => "SV_Coverage",
171 Self::GlobalInvocationId => "SV_DispatchThreadID",
173 Self::LocalInvocationId => "SV_GroupThreadID",
174 Self::LocalInvocationIndex => "SV_GroupIndex",
175 Self::WorkGroupId => "SV_GroupID",
176 Self::NumWorkGroups => "SV_GroupID",
180 Self::ViewIndex => "SV_ViewID",
181 Self::SubgroupSize
183 | Self::SubgroupInvocationId
184 | Self::NumSubgroups
185 | Self::SubgroupId => unreachable!(),
186 Self::BaseInstance | Self::BaseVertex | Self::WorkGroupSize => {
187 return Err(Error::Unimplemented(format!("builtin {self:?}")))
188 }
189 Self::PointSize | Self::PointCoord | Self::DrawIndex => {
190 return Err(Error::Custom(format!("Unsupported builtin {self:?}")))
191 }
192 Self::CullPrimitive => "SV_CullPrimitive",
193 Self::MeshTaskSize
194 | Self::VertexCount
195 | Self::PrimitiveCount
196 | Self::Vertices
197 | Self::Primitives
198 | Self::PointIndex
199 | Self::LineIndices
200 | Self::TriangleIndices => return Ok(None),
201 Self::RayInvocationId
202 | Self::NumRayInvocations
203 | Self::InstanceCustomData
204 | Self::GeometryIndex
205 | Self::WorldRayOrigin
206 | Self::WorldRayDirection
207 | Self::ObjectRayOrigin
208 | Self::ObjectRayDirection
209 | Self::RayTmin
210 | Self::RayTCurrentMax
211 | Self::ObjectToWorld
212 | Self::WorldToObject
213 | Self::HitKind => unreachable!(),
214 }))
215 }
216}
217
218impl crate::Interpolation {
219 pub(super) const fn to_hlsl_str(self) -> Option<&'static str> {
221 match self {
222 Self::Perspective => None,
225 Self::Linear => Some("noperspective"),
226 Self::Flat => Some("nointerpolation"),
227 Self::PerVertex => Some("nointerpolation"),
228 }
229 }
230}
231
232impl crate::Sampling {
233 pub(super) const fn to_hlsl_str(self) -> Option<&'static str> {
235 match self {
236 Self::Center | Self::First | Self::Either => None,
237 Self::Centroid => Some("centroid"),
238 Self::Sample => Some("sample"),
239 }
240 }
241}
242
243impl crate::AtomicFunction {
244 pub(super) const fn to_hlsl_suffix(self) -> &'static str {
246 match self {
247 Self::Add | Self::Subtract => "Add",
248 Self::And => "And",
249 Self::InclusiveOr => "Or",
250 Self::ExclusiveOr => "Xor",
251 Self::Min => "Min",
252 Self::Max => "Max",
253 Self::Exchange { compare: None } => "Exchange",
254 Self::Exchange { .. } => "CompareExchange",
255 }
256 }
257}