Skip to content

Commit 65c06c2

Browse files
feat(naga): add pack4x{I,U}8Clamp built-ins
1 parent 2aa8a83 commit 65c06c2

17 files changed

Lines changed: 734 additions & 581 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ Bottom level categories:
5151
Naga now infers the correct binding layout when a resource appears only in an assignment to `_`. By @andyleiserson in [#7540](https://github.com/gfx-rs/wgpu/pull/7540).
5252

5353
- Add polyfills for `dot4U8Packed` and `dot4I8Packed` for all backends. By @robamler in [#7494](https://github.com/gfx-rs/wgpu/pull/7494).
54+
- Add polyfilled `pack4x{I,U}8Clamped` built-ins to all backends and WGSL frontend. By @ErichDonGubler in [#7546](https://github.com/gfx-rs/wgpu/pull/7546).
5455

5556
#### DX12
5657

naga/src/back/glsl/mod.rs

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1392,6 +1392,8 @@ impl<'a, W: Write> Writer<'a, W> {
13921392
}
13931393
crate::MathFunction::Pack4xI8
13941394
| crate::MathFunction::Pack4xU8
1395+
| crate::MathFunction::Pack4xI8Clamp
1396+
| crate::MathFunction::Pack4xU8Clamp
13951397
| crate::MathFunction::Unpack4xI8
13961398
| crate::MathFunction::Unpack4xU8
13971399
| crate::MathFunction::QuantizeToF16 => {
@@ -3879,13 +3881,27 @@ impl<'a, W: Write> Writer<'a, W> {
38793881
}
38803882
}
38813883

3882-
fun @ (Mf::Pack4xI8 | Mf::Pack4xU8) => {
3883-
let was_signed = matches!(fun, Mf::Pack4xI8);
3884+
fun @ (Mf::Pack4xI8 | Mf::Pack4xU8 | Mf::Pack4xI8Clamp | Mf::Pack4xU8Clamp) => {
3885+
let was_signed = matches!(fun, Mf::Pack4xI8 | Mf::Pack4xI8Clamp);
3886+
let clamp_bounds = match fun {
3887+
Mf::Pack4xI8Clamp => Some(("-128", "127")),
3888+
Mf::Pack4xU8Clamp => Some(("0", "255")),
3889+
_ => None,
3890+
};
38843891
let const_suffix = if was_signed { "" } else { "u" };
38853892
if was_signed {
38863893
write!(self.out, "uint(")?;
38873894
}
3888-
let write_arg = |this: &mut Self| this.write_expr(arg, ctx);
3895+
let write_arg = |this: &mut Self| -> BackendResult {
3896+
if let Some((min, max)) = clamp_bounds {
3897+
write!(this.out, "clamp(")?;
3898+
this.write_expr(arg, ctx)?;
3899+
write!(this.out, ", {min}{const_suffix}, {max}{const_suffix})")?;
3900+
} else {
3901+
this.write_expr(arg, ctx)?;
3902+
}
3903+
Ok(())
3904+
};
38893905
write!(self.out, "(")?;
38903906
write_arg(self)?;
38913907
write!(self.out, "[0] & 0xFF{const_suffix}) | ((")?;

naga/src/back/hlsl/writer.rs

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,9 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
224224
| crate::MathFunction::Pack4x8snorm
225225
| crate::MathFunction::Pack4x8unorm
226226
| crate::MathFunction::Pack4xI8
227-
| crate::MathFunction::Pack4xU8 => {
227+
| crate::MathFunction::Pack4xU8
228+
| crate::MathFunction::Pack4xI8Clamp
229+
| crate::MathFunction::Pack4xU8Clamp => {
228230
self.need_bake_expressions.insert(arg);
229231
}
230232
crate::MathFunction::CountLeadingZeros => {
@@ -3439,6 +3441,8 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
34393441
Pack4x8unorm,
34403442
Pack4xI8,
34413443
Pack4xU8,
3444+
Pack4xI8Clamp,
3445+
Pack4xU8Clamp,
34423446
Unpack2x16float,
34433447
Unpack2x16snorm,
34443448
Unpack2x16unorm,
@@ -3538,6 +3542,8 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
35383542
Mf::Pack4x8unorm => Function::Pack4x8unorm,
35393543
Mf::Pack4xI8 => Function::Pack4xI8,
35403544
Mf::Pack4xU8 => Function::Pack4xU8,
3545+
Mf::Pack4xI8Clamp => Function::Pack4xI8Clamp,
3546+
Mf::Pack4xU8Clamp => Function::Pack4xU8Clamp,
35413547
// Data Unpacking
35423548
Mf::Unpack2x16float => Function::Unpack2x16float,
35433549
Mf::Unpack2x16snorm => Function::Unpack2x16snorm,
@@ -3638,12 +3644,30 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
36383644
self.write_expr(module, arg, func_ctx)?;
36393645
write!(self.out, "[3], 0.0, 1.0) * {scale}.0)) << 24)")?;
36403646
}
3641-
fun @ (Function::Pack4xI8 | Function::Pack4xU8) => {
3642-
let was_signed = matches!(fun, Function::Pack4xI8);
3647+
fun @ (Function::Pack4xI8
3648+
| Function::Pack4xU8
3649+
| Function::Pack4xI8Clamp
3650+
| Function::Pack4xU8Clamp) => {
3651+
let was_signed =
3652+
matches!(fun, Function::Pack4xI8 | Function::Pack4xI8Clamp);
3653+
let clamp_bounds = match fun {
3654+
Function::Pack4xI8Clamp => Some(("-128", "127")),
3655+
Function::Pack4xU8Clamp => Some(("0", "255")),
3656+
_ => None,
3657+
};
36433658
if was_signed {
36443659
write!(self.out, "uint(")?;
36453660
}
3646-
let write_arg = |this: &mut Self| this.write_expr(module, arg, func_ctx);
3661+
let write_arg = |this: &mut Self| -> BackendResult {
3662+
if let Some((min, max)) = clamp_bounds {
3663+
write!(this.out, "clamp(")?;
3664+
this.write_expr(module, arg, func_ctx)?;
3665+
write!(this.out, ", {min}, {max})")?;
3666+
} else {
3667+
this.write_expr(module, arg, func_ctx)?;
3668+
}
3669+
Ok(())
3670+
};
36473671
write!(self.out, "(")?;
36483672
write_arg(self)?;
36493673
write!(self.out, "[0] & 0xFF) | ((")?;

naga/src/back/msl/writer.rs

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2271,6 +2271,8 @@ impl<W: Write> Writer<W> {
22712271
Mf::Pack2x16float => "",
22722272
Mf::Pack4xI8 => "",
22732273
Mf::Pack4xU8 => "",
2274+
Mf::Pack4xI8Clamp => "",
2275+
Mf::Pack4xU8Clamp => "",
22742276
// data unpacking
22752277
Mf::Unpack4x8snorm => "unpack_snorm4x8_to_float",
22762278
Mf::Unpack4x8unorm => "unpack_unorm4x8_to_float",
@@ -2435,12 +2437,26 @@ impl<W: Write> Writer<W> {
24352437
write!(self.out, "{fun_name}")?;
24362438
self.put_call_parameters(iter::once(arg), context)?;
24372439
}
2438-
fun @ (Mf::Pack4xI8 | Mf::Pack4xU8) => {
2439-
let was_signed = matches!(fun, Mf::Pack4xI8);
2440+
fun @ (Mf::Pack4xI8 | Mf::Pack4xU8 | Mf::Pack4xI8Clamp | Mf::Pack4xU8Clamp) => {
2441+
let was_signed = matches!(fun, Mf::Pack4xI8 | Mf::Pack4xI8Clamp);
2442+
let clamp_bounds = match fun {
2443+
Mf::Pack4xI8Clamp => Some(("-128", "127")),
2444+
Mf::Pack4xU8Clamp => Some(("0", "255")),
2445+
_ => None,
2446+
};
24402447
if was_signed {
24412448
write!(self.out, "uint(")?;
24422449
}
2443-
let write_arg = |this: &mut Self| this.put_expression(arg, context, true);
2450+
let write_arg = |this: &mut Self| -> BackendResult {
2451+
if let Some((min, max)) = clamp_bounds {
2452+
write!(this.out, "{NAMESPACE}::clamp(")?;
2453+
this.put_expression(arg, context, true)?;
2454+
write!(this.out, ", {min}, {max})")?;
2455+
} else {
2456+
this.put_expression(arg, context, true)?;
2457+
}
2458+
Ok(())
2459+
};
24442460
write!(self.out, "(")?;
24452461
write_arg(self)?;
24462462
write!(self.out, "[0] & 0xFF) | ((")?;
@@ -3213,6 +3229,8 @@ impl<W: Write> Writer<W> {
32133229
crate::MathFunction::FirstLeadingBit
32143230
| crate::MathFunction::Pack4xI8
32153231
| crate::MathFunction::Pack4xU8
3232+
| crate::MathFunction::Pack4xI8Clamp
3233+
| crate::MathFunction::Pack4xU8Clamp
32163234
| crate::MathFunction::Unpack4xI8
32173235
| crate::MathFunction::Unpack4xU8 => {
32183236
self.need_bake_expressions.insert(arg);

naga/src/back/spv/block.rs

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1517,12 +1517,13 @@ impl BlockContext<'_> {
15171517
Mf::Pack2x16float => MathOp::Ext(spirv::GLOp::PackHalf2x16),
15181518
Mf::Pack2x16unorm => MathOp::Ext(spirv::GLOp::PackUnorm2x16),
15191519
Mf::Pack2x16snorm => MathOp::Ext(spirv::GLOp::PackSnorm2x16),
1520-
fun @ (Mf::Pack4xI8 | Mf::Pack4xU8) => {
1520+
fun @ (Mf::Pack4xI8 | Mf::Pack4xU8 | Mf::Pack4xI8Clamp | Mf::Pack4xU8Clamp) => {
15211521
let (int_type, is_signed) = match fun {
1522-
Mf::Pack4xI8 => (crate::ScalarKind::Sint, true),
1523-
Mf::Pack4xU8 => (crate::ScalarKind::Uint, false),
1522+
Mf::Pack4xI8 | Mf::Pack4xI8Clamp => (crate::ScalarKind::Sint, true),
1523+
Mf::Pack4xU8 | Mf::Pack4xU8Clamp => (crate::ScalarKind::Uint, false),
15241524
_ => unreachable!(),
15251525
};
1526+
let should_clamp = matches!(fun, Mf::Pack4xI8Clamp | Mf::Pack4xU8Clamp);
15261527
let uint_type_id =
15271528
self.get_numeric_type_id(NumericType::Scalar(crate::Scalar::U32));
15281529

@@ -1563,6 +1564,34 @@ impl BlockContext<'_> {
15631564
));
15641565
extracted = casted;
15651566
}
1567+
if should_clamp {
1568+
let (min, max, clamp_op) = if is_signed {
1569+
(
1570+
crate::Literal::I32(-128),
1571+
crate::Literal::I32(127),
1572+
spirv::GLOp::SClamp,
1573+
)
1574+
} else {
1575+
(
1576+
crate::Literal::U32(0),
1577+
crate::Literal::U32(255),
1578+
spirv::GLOp::UClamp,
1579+
)
1580+
};
1581+
let [min, max] =
1582+
[min, max].map(|lit| self.writer.get_constant_scalar(lit));
1583+
1584+
let clamp_id = self.gen_id();
1585+
block.body.push(Instruction::ext_inst(
1586+
self.writer.gl450_ext_inst_id,
1587+
clamp_op,
1588+
result_type_id,
1589+
clamp_id,
1590+
&[extracted, min, max],
1591+
));
1592+
1593+
extracted = clamp_id;
1594+
}
15661595
let is_last = i == u32::from(VEC_LENGTH - 1);
15671596
if is_last {
15681597
last_instruction = Instruction::quaternary(

naga/src/common/wgsl/to_wgsl.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,8 @@ impl TryToWgsl for crate::MathFunction {
139139
Mf::Pack2x16float => "pack2x16float",
140140
Mf::Pack4xI8 => "pack4xI8",
141141
Mf::Pack4xU8 => "pack4xU8",
142+
Mf::Pack4xI8Clamp => "pack4xI8Clamp",
143+
Mf::Pack4xU8Clamp => "pack4xU8Clamp",
142144
Mf::Unpack4x8snorm => "unpack4x8snorm",
143145
Mf::Unpack4x8unorm => "unpack4x8unorm",
144146
Mf::Unpack2x16snorm => "unpack2x16snorm",

naga/src/front/wgsl/parse/conv.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,8 @@ pub fn map_standard_fun(word: &str) -> Option<crate::MathFunction> {
273273
"pack2x16float" => Mf::Pack2x16float,
274274
"pack4xI8" => Mf::Pack4xI8,
275275
"pack4xU8" => Mf::Pack4xU8,
276+
"pack4xI8Clamp" => Mf::Pack4xI8Clamp,
277+
"pack4xU8Clamp" => Mf::Pack4xU8Clamp,
276278
// data unpacking
277279
"unpack4x8snorm" => Mf::Unpack4x8snorm,
278280
"unpack4x8unorm" => Mf::Unpack4x8unorm,

naga/src/ir/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1187,6 +1187,8 @@ pub enum MathFunction {
11871187
Pack2x16float,
11881188
Pack4xI8,
11891189
Pack4xU8,
1190+
Pack4xI8Clamp,
1191+
Pack4xU8Clamp,
11901192
// data unpacking
11911193
Unpack4x8snorm,
11921194
Unpack4x8unorm,

naga/src/proc/constant_evaluator.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1342,6 +1342,8 @@ impl<'a> ConstantEvaluator<'a> {
13421342
| crate::MathFunction::Pack2x16float
13431343
| crate::MathFunction::Pack4xI8
13441344
| crate::MathFunction::Pack4xU8
1345+
| crate::MathFunction::Pack4xI8Clamp
1346+
| crate::MathFunction::Pack4xU8Clamp
13451347
| crate::MathFunction::Unpack4x8snorm
13461348
| crate::MathFunction::Unpack4x8unorm
13471349
| crate::MathFunction::Unpack2x16snorm

naga/src/proc/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,8 @@ impl super::MathFunction {
262262
Self::Pack2x16float => 1,
263263
Self::Pack4xI8 => 1,
264264
Self::Pack4xU8 => 1,
265+
Self::Pack4xI8Clamp => 1,
266+
Self::Pack4xU8Clamp => 1,
265267
// data unpacking
266268
Self::Unpack4x8snorm => 1,
267269
Self::Unpack4x8unorm => 1,

0 commit comments

Comments
 (0)