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