Skip to content

Commit 110d737

Browse files
[naga msl-out] Fix truncation of pulled vertices (#7458)
Fixes #7410
1 parent c860a2c commit 110d737

16 files changed

+1744
-20
lines changed

naga/src/back/msl/writer.rs

Lines changed: 44 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use alloc::{
55
vec::Vec,
66
};
77
use core::{
8+
cmp::Ordering,
89
fmt::{Display, Error as FmtError, Formatter, Write},
910
iter,
1011
};
@@ -6384,14 +6385,12 @@ template <typename A>
63846385
// from the buffer elements.
63856386
for attribute in vbm.attributes {
63866387
let location = attribute.shader_location;
6387-
let am_option = am_resolved.get(&location);
6388-
if am_option.is_none() {
6388+
let Some(am) = am_resolved.get(&location) else {
63896389
// This bound attribute isn't used in this entry point, so
63906390
// don't bother extracting the data. Too bad we emitted the
63916391
// unpacking function earlier -- it might not get used.
63926392
continue;
6393-
}
6394-
let am = am_option.unwrap();
6393+
};
63956394
let attribute_name = &am.name;
63966395
let attribute_ty_name = &am.ty_name;
63976396

@@ -6401,36 +6400,62 @@ template <typename A>
64016400
.expect("Should have generated this unpacking function earlier.");
64026401
let func_name = &func.name;
64036402

6404-
write!(self.out, "{}{attribute_name} = ", back::Level(2),)?;
6405-
64066403
// Check dimensionality of the attribute compared to the unpacking
6407-
// function. If attribute dimension is < unpack dimension, then
6408-
// we need to explicitly cast down the result. Otherwise, if attribute
6409-
// dimension > unpack dimension, we have to pad out the unpack value
6410-
// from a vec4(0, 0, 0, 1) of matching scalar type.
6404+
// function. If attribute dimension > unpack dimension, we have to
6405+
// pad out the unpack value from a vec4(0, 0, 0, 1) of matching
6406+
// scalar type. Otherwise, if attribute dimension is < unpack
6407+
// dimension, then we need to explicitly truncate the result.
6408+
6409+
let needs_padding_or_truncation = am.dimension.cmp(&func.dimension);
6410+
6411+
if needs_padding_or_truncation != Ordering::Equal {
6412+
// Emit a comment flagging that a conversion is happening,
6413+
// since the actual logic can be at the end of a long line.
6414+
writeln!(
6415+
self.out,
6416+
"{}// {attribute_ty_name} <- {:?}",
6417+
back::Level(2),
6418+
attribute.format
6419+
)?;
6420+
}
6421+
6422+
write!(self.out, "{}{attribute_name} = ", back::Level(2),)?;
64116423

6412-
let needs_truncate_or_padding = am.dimension != func.dimension;
6413-
if needs_truncate_or_padding {
6424+
if needs_padding_or_truncation == Ordering::Greater {
6425+
// Needs padding: emit constructor call for wider type
64146426
write!(self.out, "{attribute_ty_name}(")?;
64156427
}
64166428

6429+
// Emit call to unpacking function
64176430
write!(self.out, "{func_name}({elem_name}.data[{offset}]",)?;
64186431
for i in (offset + 1)..(offset + func.byte_count) {
64196432
write!(self.out, ", {elem_name}.data[{i}]")?;
64206433
}
64216434
write!(self.out, ")")?;
64226435

6423-
if needs_truncate_or_padding {
6424-
let zero_value = if am.ty_is_int { "0" } else { "0.0" };
6425-
let one_value = if am.ty_is_int { "1" } else { "1.0" };
6426-
for i in func.dimension..am.dimension {
6436+
match needs_padding_or_truncation {
6437+
Ordering::Greater => {
6438+
// Padding
6439+
let zero_value = if am.ty_is_int { "0" } else { "0.0" };
6440+
let one_value = if am.ty_is_int { "1" } else { "1.0" };
6441+
for i in func.dimension..am.dimension {
6442+
write!(
6443+
self.out,
6444+
", {}",
6445+
if i == 3 { one_value } else { zero_value }
6446+
)?;
6447+
}
6448+
write!(self.out, ")")?;
6449+
}
6450+
Ordering::Less => {
6451+
// Truncate to the first `am.dimension` components
64276452
write!(
64286453
self.out,
6429-
", {}",
6430-
if i == 3 { one_value } else { zero_value }
6454+
".{}",
6455+
&"xyzw"[0..usize::try_from(am.dimension).unwrap()]
64316456
)?;
64326457
}
6433-
write!(self.out, ")")?;
6458+
Ordering::Equal => {}
64346459
}
64356460

64366461
writeln!(self.out, ";")?;
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
targets = "METAL"
2+
3+
[msl_pipeline]
4+
allow_and_force_point_size = false
5+
vertex_pulling_transform = true
6+
7+
[[msl_pipeline.vertex_buffer_mappings]]
8+
attributes = [
9+
{ offset = 0, shader_location = 0, format = "Uint8" },
10+
{ offset = 16, shader_location = 1, format = "Uint8x2" },
11+
{ offset = 32, shader_location = 2, format = "Uint8x4" },
12+
{ offset = 48, shader_location = 3, format = "Sint8" },
13+
{ offset = 64, shader_location = 4, format = "Sint8x2" },
14+
{ offset = 80, shader_location = 5, format = "Sint8x4" },
15+
{ offset = 96, shader_location = 6, format = "Unorm8" },
16+
{ offset = 112, shader_location = 7, format = "Unorm8x2" },
17+
{ offset = 128, shader_location = 8, format = "Unorm8x4" },
18+
{ offset = 144, shader_location = 9, format = "Snorm8" },
19+
{ offset = 160, shader_location = 10, format = "Snorm8x2" },
20+
{ offset = 176, shader_location = 11, format = "Snorm8x4" },
21+
{ offset = 192, shader_location = 12, format = "Uint16" },
22+
{ offset = 208, shader_location = 13, format = "Uint16x2" },
23+
{ offset = 224, shader_location = 14, format = "Uint16x4" },
24+
{ offset = 240, shader_location = 15, format = "Sint16" },
25+
{ offset = 256, shader_location = 16, format = "Sint16x2" },
26+
{ offset = 272, shader_location = 17, format = "Sint16x4" },
27+
{ offset = 288, shader_location = 18, format = "Unorm16" },
28+
{ offset = 304, shader_location = 19, format = "Unorm16x2" },
29+
{ offset = 320, shader_location = 20, format = "Unorm16x4" },
30+
{ offset = 336, shader_location = 21, format = "Snorm16" },
31+
{ offset = 352, shader_location = 22, format = "Snorm16x2" },
32+
{ offset = 368, shader_location = 23, format = "Snorm16x4" },
33+
{ offset = 384, shader_location = 24, format = "Float16" },
34+
{ offset = 400, shader_location = 25, format = "Float16x2" },
35+
{ offset = 416, shader_location = 26, format = "Float16x4" },
36+
{ offset = 432, shader_location = 27, format = "Float32" },
37+
{ offset = 448, shader_location = 28, format = "Float32x2" },
38+
{ offset = 464, shader_location = 29, format = "Float32x3" },
39+
{ offset = 480, shader_location = 30, format = "Float32x4" },
40+
{ offset = 496, shader_location = 31, format = "Uint32" },
41+
{ offset = 512, shader_location = 32, format = "Uint32x2" },
42+
{ offset = 528, shader_location = 33, format = "Uint32x3" },
43+
{ offset = 544, shader_location = 34, format = "Uint32x4" },
44+
{ offset = 560, shader_location = 35, format = "Sint32" },
45+
{ offset = 576, shader_location = 36, format = "Sint32x2" },
46+
{ offset = 592, shader_location = 37, format = "Sint32x3" },
47+
{ offset = 608, shader_location = 38, format = "Sint32x4" },
48+
{ offset = 624, shader_location = 39, format = "unorm10-10-10-2" },
49+
{ offset = 640, shader_location = 40, format = "unorm8x4-bgra" },
50+
]
51+
id = 1
52+
indexed_by_vertex = true
53+
stride = 644
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// Tests for the vertex pulling transform in the MSL backend.
2+
//
3+
// Test loading a scalar from each vertex format.
4+
//
5+
// (Note: only the wgsl files are different for each of the -formats-xN tests.
6+
// The toml files are all the same.)
7+
8+
struct VertexOutput {
9+
@builtin(position) position: vec4<f32>,
10+
}
11+
12+
struct VertexInput {
13+
@location( 0) v_uint8 : u32,
14+
@location( 1) v_uint8x2 : u32,
15+
@location( 2) v_uint8x4 : u32,
16+
@location( 3) v_sint8 : i32,
17+
@location( 4) v_sint8x2 : i32,
18+
@location( 5) v_sint8x4 : i32,
19+
@location( 6) v_unorm8 : f32,
20+
@location( 7) v_unorm8x2 : f32,
21+
@location( 8) v_unorm8x4 : f32,
22+
@location( 9) v_snorm8 : f32,
23+
@location(10) v_snorm8x2 : f32,
24+
@location(11) v_snorm8x4 : f32,
25+
@location(12) v_uint16 : u32,
26+
@location(13) v_uint16x2 : u32,
27+
@location(14) v_uint16x4 : u32,
28+
@location(15) v_sint16 : i32,
29+
@location(16) v_sint16x2 : i32,
30+
@location(17) v_sint16x4 : i32,
31+
@location(18) v_unorm16 : f32,
32+
@location(19) v_unorm16x2 : f32,
33+
@location(20) v_unorm16x4 : f32,
34+
@location(21) v_snorm16 : f32,
35+
@location(22) v_snorm16x2 : f32,
36+
@location(23) v_snorm16x4 : f32,
37+
@location(24) v_float16 : f32,
38+
@location(25) v_float16x2 : f32,
39+
@location(26) v_float16x4 : f32,
40+
@location(27) v_float32 : f32,
41+
@location(28) v_float32x2 : f32,
42+
@location(29) v_float32x3 : f32,
43+
@location(30) v_float32x4 : f32,
44+
@location(31) v_uint32 : u32,
45+
@location(32) v_uint32x2 : u32,
46+
@location(33) v_uint32x3 : u32,
47+
@location(34) v_uint32x4 : u32,
48+
@location(35) v_sint32 : i32,
49+
@location(36) v_sint32x2 : i32,
50+
@location(37) v_sint32x3 : i32,
51+
@location(38) v_sint32x4 : i32,
52+
@location(39) v_unorm10_10_10_2: f32,
53+
@location(40) v_unorm8x4_bgra: f32,
54+
}
55+
56+
@vertex
57+
fn render_vertex(
58+
v_in: VertexInput,
59+
) -> VertexOutput
60+
{
61+
return VertexOutput(vec4f(v_in.v_uint8));
62+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
targets = "METAL"
2+
3+
[msl_pipeline]
4+
allow_and_force_point_size = false
5+
vertex_pulling_transform = true
6+
7+
[[msl_pipeline.vertex_buffer_mappings]]
8+
attributes = [
9+
{ offset = 0, shader_location = 0, format = "Uint8" },
10+
{ offset = 16, shader_location = 1, format = "Uint8x2" },
11+
{ offset = 32, shader_location = 2, format = "Uint8x4" },
12+
{ offset = 48, shader_location = 3, format = "Sint8" },
13+
{ offset = 64, shader_location = 4, format = "Sint8x2" },
14+
{ offset = 80, shader_location = 5, format = "Sint8x4" },
15+
{ offset = 96, shader_location = 6, format = "Unorm8" },
16+
{ offset = 112, shader_location = 7, format = "Unorm8x2" },
17+
{ offset = 128, shader_location = 8, format = "Unorm8x4" },
18+
{ offset = 144, shader_location = 9, format = "Snorm8" },
19+
{ offset = 160, shader_location = 10, format = "Snorm8x2" },
20+
{ offset = 176, shader_location = 11, format = "Snorm8x4" },
21+
{ offset = 192, shader_location = 12, format = "Uint16" },
22+
{ offset = 208, shader_location = 13, format = "Uint16x2" },
23+
{ offset = 224, shader_location = 14, format = "Uint16x4" },
24+
{ offset = 240, shader_location = 15, format = "Sint16" },
25+
{ offset = 256, shader_location = 16, format = "Sint16x2" },
26+
{ offset = 272, shader_location = 17, format = "Sint16x4" },
27+
{ offset = 288, shader_location = 18, format = "Unorm16" },
28+
{ offset = 304, shader_location = 19, format = "Unorm16x2" },
29+
{ offset = 320, shader_location = 20, format = "Unorm16x4" },
30+
{ offset = 336, shader_location = 21, format = "Snorm16" },
31+
{ offset = 352, shader_location = 22, format = "Snorm16x2" },
32+
{ offset = 368, shader_location = 23, format = "Snorm16x4" },
33+
{ offset = 384, shader_location = 24, format = "Float16" },
34+
{ offset = 400, shader_location = 25, format = "Float16x2" },
35+
{ offset = 416, shader_location = 26, format = "Float16x4" },
36+
{ offset = 432, shader_location = 27, format = "Float32" },
37+
{ offset = 448, shader_location = 28, format = "Float32x2" },
38+
{ offset = 464, shader_location = 29, format = "Float32x3" },
39+
{ offset = 480, shader_location = 30, format = "Float32x4" },
40+
{ offset = 496, shader_location = 31, format = "Uint32" },
41+
{ offset = 512, shader_location = 32, format = "Uint32x2" },
42+
{ offset = 528, shader_location = 33, format = "Uint32x3" },
43+
{ offset = 544, shader_location = 34, format = "Uint32x4" },
44+
{ offset = 560, shader_location = 35, format = "Sint32" },
45+
{ offset = 576, shader_location = 36, format = "Sint32x2" },
46+
{ offset = 592, shader_location = 37, format = "Sint32x3" },
47+
{ offset = 608, shader_location = 38, format = "Sint32x4" },
48+
{ offset = 624, shader_location = 39, format = "unorm10-10-10-2" },
49+
{ offset = 640, shader_location = 40, format = "unorm8x4-bgra" },
50+
]
51+
id = 1
52+
indexed_by_vertex = true
53+
stride = 644
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// Tests for the vertex pulling transform in the MSL backend.
2+
//
3+
// Test loading `vec2` from each vertex format.
4+
//
5+
// (Note: only the wgsl files are different for each of the -formats-xN tests.
6+
// The toml files are all the same.)
7+
8+
struct VertexOutput {
9+
@builtin(position) position: vec4<f32>,
10+
}
11+
12+
struct VertexInput {
13+
@location( 0) v_uint8 : vec2<u32>,
14+
@location( 1) v_uint8x2 : vec2<u32>,
15+
@location( 2) v_uint8x4 : vec2<u32>,
16+
@location( 3) v_sint8 : vec2<i32>,
17+
@location( 4) v_sint8x2 : vec2<i32>,
18+
@location( 5) v_sint8x4 : vec2<i32>,
19+
@location( 6) v_unorm8 : vec2<f32>,
20+
@location( 7) v_unorm8x2 : vec2<f32>,
21+
@location( 8) v_unorm8x4 : vec2<f32>,
22+
@location( 9) v_snorm8 : vec2<f32>,
23+
@location(10) v_snorm8x2 : vec2<f32>,
24+
@location(11) v_snorm8x4 : vec2<f32>,
25+
@location(12) v_uint16 : vec2<u32>,
26+
@location(13) v_uint16x2 : vec2<u32>,
27+
@location(14) v_uint16x4 : vec2<u32>,
28+
@location(15) v_sint16 : vec2<i32>,
29+
@location(16) v_sint16x2 : vec2<i32>,
30+
@location(17) v_sint16x4 : vec2<i32>,
31+
@location(18) v_unorm16 : vec2<f32>,
32+
@location(19) v_unorm16x2 : vec2<f32>,
33+
@location(20) v_unorm16x4 : vec2<f32>,
34+
@location(21) v_snorm16 : vec2<f32>,
35+
@location(22) v_snorm16x2 : vec2<f32>,
36+
@location(23) v_snorm16x4 : vec2<f32>,
37+
@location(24) v_float16 : vec2<f32>,
38+
@location(25) v_float16x2 : vec2<f32>,
39+
@location(26) v_float16x4 : vec2<f32>,
40+
@location(27) v_float32 : vec2<f32>,
41+
@location(28) v_float32x2 : vec2<f32>,
42+
@location(29) v_float32x3 : vec2<f32>,
43+
@location(30) v_float32x4 : vec2<f32>,
44+
@location(31) v_uint32 : vec2<u32>,
45+
@location(32) v_uint32x2 : vec2<u32>,
46+
@location(33) v_uint32x3 : vec2<u32>,
47+
@location(34) v_uint32x4 : vec2<u32>,
48+
@location(35) v_sint32 : vec2<i32>,
49+
@location(36) v_sint32x2 : vec2<i32>,
50+
@location(37) v_sint32x3 : vec2<i32>,
51+
@location(38) v_sint32x4 : vec2<i32>,
52+
@location(39) v_unorm10_10_10_2: vec2<f32>,
53+
@location(40) v_unorm8x4_bgra: vec2<f32>,
54+
}
55+
56+
@vertex
57+
fn render_vertex(
58+
v_in: VertexInput,
59+
) -> VertexOutput
60+
{
61+
return VertexOutput(vec4f(v_in.v_uint8.x));
62+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
targets = "METAL"
2+
3+
[msl_pipeline]
4+
allow_and_force_point_size = false
5+
vertex_pulling_transform = true
6+
7+
[[msl_pipeline.vertex_buffer_mappings]]
8+
attributes = [
9+
{ offset = 0, shader_location = 0, format = "Uint8" },
10+
{ offset = 16, shader_location = 1, format = "Uint8x2" },
11+
{ offset = 32, shader_location = 2, format = "Uint8x4" },
12+
{ offset = 48, shader_location = 3, format = "Sint8" },
13+
{ offset = 64, shader_location = 4, format = "Sint8x2" },
14+
{ offset = 80, shader_location = 5, format = "Sint8x4" },
15+
{ offset = 96, shader_location = 6, format = "Unorm8" },
16+
{ offset = 112, shader_location = 7, format = "Unorm8x2" },
17+
{ offset = 128, shader_location = 8, format = "Unorm8x4" },
18+
{ offset = 144, shader_location = 9, format = "Snorm8" },
19+
{ offset = 160, shader_location = 10, format = "Snorm8x2" },
20+
{ offset = 176, shader_location = 11, format = "Snorm8x4" },
21+
{ offset = 192, shader_location = 12, format = "Uint16" },
22+
{ offset = 208, shader_location = 13, format = "Uint16x2" },
23+
{ offset = 224, shader_location = 14, format = "Uint16x4" },
24+
{ offset = 240, shader_location = 15, format = "Sint16" },
25+
{ offset = 256, shader_location = 16, format = "Sint16x2" },
26+
{ offset = 272, shader_location = 17, format = "Sint16x4" },
27+
{ offset = 288, shader_location = 18, format = "Unorm16" },
28+
{ offset = 304, shader_location = 19, format = "Unorm16x2" },
29+
{ offset = 320, shader_location = 20, format = "Unorm16x4" },
30+
{ offset = 336, shader_location = 21, format = "Snorm16" },
31+
{ offset = 352, shader_location = 22, format = "Snorm16x2" },
32+
{ offset = 368, shader_location = 23, format = "Snorm16x4" },
33+
{ offset = 384, shader_location = 24, format = "Float16" },
34+
{ offset = 400, shader_location = 25, format = "Float16x2" },
35+
{ offset = 416, shader_location = 26, format = "Float16x4" },
36+
{ offset = 432, shader_location = 27, format = "Float32" },
37+
{ offset = 448, shader_location = 28, format = "Float32x2" },
38+
{ offset = 464, shader_location = 29, format = "Float32x3" },
39+
{ offset = 480, shader_location = 30, format = "Float32x4" },
40+
{ offset = 496, shader_location = 31, format = "Uint32" },
41+
{ offset = 512, shader_location = 32, format = "Uint32x2" },
42+
{ offset = 528, shader_location = 33, format = "Uint32x3" },
43+
{ offset = 544, shader_location = 34, format = "Uint32x4" },
44+
{ offset = 560, shader_location = 35, format = "Sint32" },
45+
{ offset = 576, shader_location = 36, format = "Sint32x2" },
46+
{ offset = 592, shader_location = 37, format = "Sint32x3" },
47+
{ offset = 608, shader_location = 38, format = "Sint32x4" },
48+
{ offset = 624, shader_location = 39, format = "unorm10-10-10-2" },
49+
{ offset = 640, shader_location = 40, format = "unorm8x4-bgra" },
50+
]
51+
id = 1
52+
indexed_by_vertex = true
53+
stride = 644

0 commit comments

Comments
 (0)