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 4 => Ok("int"),
27 8 => Ok("int64_t"),
28 _ => Err(Error::UnsupportedScalar(self)),
29 },
30 crate::ScalarKind::Uint => match self.width {
31 4 => Ok("uint"),
32 8 => Ok("uint64_t"),
33 _ => Err(Error::UnsupportedScalar(self)),
34 },
35 crate::ScalarKind::Float => match self.width {
36 2 => Ok("half"),
37 4 => Ok("float"),
38 8 => Ok("double"),
39 _ => Err(Error::UnsupportedScalar(self)),
40 },
41 crate::ScalarKind::Bool => Ok("bool"),
42 crate::ScalarKind::AbstractInt | crate::ScalarKind::AbstractFloat => {
43 Err(Error::UnsupportedScalar(self))
44 }
45 }
46 }
47}
48
49impl crate::TypeInner {
50 pub(super) const fn is_matrix(&self) -> bool {
51 match *self {
52 Self::Matrix { .. } => true,
53 _ => false,
54 }
55 }
56
57 pub(super) fn size_hlsl(&self, gctx: crate::proc::GlobalCtx) -> Result<u32, Error> {
58 match *self {
59 Self::Matrix {
60 columns,
61 rows,
62 scalar,
63 } => {
64 let stride = Alignment::from(rows) * scalar.width as u32;
65 let last_row_size = rows as u32 * scalar.width as u32;
66 Ok(((columns as u32 - 1) * stride) + last_row_size)
67 }
68 Self::Array { base, size, stride } => {
69 let count = match size.resolve(gctx)? {
70 crate::proc::IndexableLength::Known(size) => size,
71 crate::proc::IndexableLength::Dynamic => 1,
73 };
74 let last_el_size = gctx.types[base].inner.size_hlsl(gctx)?;
75 Ok(((count - 1) * stride) + last_el_size)
76 }
77 _ => Ok(self.size(gctx)),
78 }
79 }
80
81 pub(super) fn hlsl_type_id<'a>(
83 base: crate::Handle<crate::Type>,
84 gctx: crate::proc::GlobalCtx,
85 names: &'a crate::FastHashMap<crate::proc::NameKey, String>,
86 ) -> Result<Cow<'a, str>, Error> {
87 Ok(match gctx.types[base].inner {
88 crate::TypeInner::Scalar(scalar) => Cow::Borrowed(scalar.to_hlsl_str()?),
89 crate::TypeInner::Vector { size, scalar } => Cow::Owned(format!(
90 "{}{}",
91 scalar.to_hlsl_str()?,
92 common::vector_size_str(size)
93 )),
94 crate::TypeInner::Matrix {
95 columns,
96 rows,
97 scalar,
98 } => Cow::Owned(format!(
99 "{}{}x{}",
100 scalar.to_hlsl_str()?,
101 common::vector_size_str(columns),
102 common::vector_size_str(rows),
103 )),
104 crate::TypeInner::Array {
105 base,
106 size: crate::ArraySize::Constant(size),
107 ..
108 } => Cow::Owned(format!(
109 "array{size}_{}_",
110 Self::hlsl_type_id(base, gctx, names)?
111 )),
112 crate::TypeInner::Struct { .. } => {
113 Cow::Borrowed(&names[&crate::proc::NameKey::Type(base)])
114 }
115 _ => unreachable!(),
116 })
117 }
118}
119
120impl crate::StorageFormat {
121 pub(super) const fn to_hlsl_str(self) -> &'static str {
122 match self {
123 Self::R16Float | Self::R32Float => "float",
124 Self::R8Unorm | Self::R16Unorm => "unorm float",
125 Self::R8Snorm | Self::R16Snorm => "snorm float",
126 Self::R8Uint | Self::R16Uint | Self::R32Uint => "uint",
127 Self::R8Sint | Self::R16Sint | Self::R32Sint => "int",
128 Self::R64Uint => "uint64_t",
129
130 Self::Rg16Float | Self::Rg32Float => "float4",
131 Self::Rg8Unorm | Self::Rg16Unorm => "unorm float4",
132 Self::Rg8Snorm | Self::Rg16Snorm => "snorm float4",
133
134 Self::Rg8Sint | Self::Rg16Sint | Self::Rg32Uint => "int4",
135 Self::Rg8Uint | Self::Rg16Uint | Self::Rg32Sint => "uint4",
136
137 Self::Rg11b10Ufloat => "float4",
138
139 Self::Rgba16Float | Self::Rgba32Float => "float4",
140 Self::Rgba8Unorm | Self::Bgra8Unorm | Self::Rgba16Unorm | Self::Rgb10a2Unorm => {
141 "unorm float4"
142 }
143 Self::Rgba8Snorm | Self::Rgba16Snorm => "snorm float4",
144
145 Self::Rgba8Uint | Self::Rgba16Uint | Self::Rgba32Uint | Self::Rgb10a2Uint => "uint4",
146 Self::Rgba8Sint | Self::Rgba16Sint | Self::Rgba32Sint => "int4",
147 }
148 }
149}
150
151impl crate::BuiltIn {
152 pub(super) fn to_hlsl_str(self) -> Result<&'static str, Error> {
153 Ok(match self {
154 Self::Position { .. } => "SV_Position",
155 Self::ClipDistance => "SV_ClipDistance",
157 Self::CullDistance => "SV_CullDistance",
158 Self::InstanceIndex => "SV_InstanceID",
159 Self::VertexIndex => "SV_VertexID",
160 Self::FragDepth => "SV_Depth",
162 Self::FrontFacing => "SV_IsFrontFace",
163 Self::PrimitiveIndex => "SV_PrimitiveID",
164 Self::SampleIndex => "SV_SampleIndex",
165 Self::SampleMask => "SV_Coverage",
166 Self::GlobalInvocationId => "SV_DispatchThreadID",
168 Self::LocalInvocationId => "SV_GroupThreadID",
169 Self::LocalInvocationIndex => "SV_GroupIndex",
170 Self::WorkGroupId => "SV_GroupID",
171 Self::NumWorkGroups => "SV_GroupID",
175 Self::SubgroupSize
177 | Self::SubgroupInvocationId
178 | Self::NumSubgroups
179 | Self::SubgroupId => unreachable!(),
180 Self::BaseInstance | Self::BaseVertex | Self::WorkGroupSize => {
181 return Err(Error::Unimplemented(format!("builtin {self:?}")))
182 }
183 Self::PointSize | Self::ViewIndex | Self::PointCoord | Self::DrawID => {
184 return Err(Error::Custom(format!("Unsupported builtin {self:?}")))
185 }
186 })
187 }
188}
189
190impl crate::Interpolation {
191 pub(super) const fn to_hlsl_str(self) -> Option<&'static str> {
193 match self {
194 Self::Perspective => None,
197 Self::Linear => Some("noperspective"),
198 Self::Flat => Some("nointerpolation"),
199 }
200 }
201}
202
203impl crate::Sampling {
204 pub(super) const fn to_hlsl_str(self) -> Option<&'static str> {
206 match self {
207 Self::Center | Self::First | Self::Either => None,
208 Self::Centroid => Some("centroid"),
209 Self::Sample => Some("sample"),
210 }
211 }
212}
213
214impl crate::AtomicFunction {
215 pub(super) const fn to_hlsl_suffix(self) -> &'static str {
217 match self {
218 Self::Add | Self::Subtract => "Add",
219 Self::And => "And",
220 Self::InclusiveOr => "Or",
221 Self::ExclusiveOr => "Xor",
222 Self::Min => "Min",
223 Self::Max => "Max",
224 Self::Exchange { compare: None } => "Exchange",
225 Self::Exchange { .. } => "CompareExchange",
226 }
227 }
228}