Skip to content

Commit 4123eda

Browse files
committed
location assignment: proper location layout algorithm, as required by spec
https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#interfaces-iointerfaces-locations
1 parent 1e3e298 commit 4123eda

File tree

5 files changed

+43
-34
lines changed

5 files changed

+43
-34
lines changed

crates/rustc_codegen_spirv/src/codegen_cx/entry.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -727,7 +727,16 @@ impl<'tcx> CodegenCx<'tcx> {
727727
Decoration::Location,
728728
std::iter::once(Operand::LiteralBit32(*location)),
729729
);
730-
*location += value_layout.size.bytes().div_ceil(16) as u32;
730+
let spirv_type = self.lookup_type(value_spirv_type);
731+
if let Some(location_size) = spirv_type.location_size(self) {
732+
*location += location_size;
733+
} else {
734+
*location += 1;
735+
self.tcx.dcx().span_err(
736+
hir_param.ty_span,
737+
"Type not supported in Input or Output declarations",
738+
);
739+
}
731740
};
732741

733742
// Emit `OpDecorate`s based on attributes.

crates/rustc_codegen_spirv/src/spirv_type.rs

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,33 @@ impl SpirvType<'_> {
276276
id
277277
}
278278

279+
/// Returns how many Input / Output `location`s this type occupies, or None if this type is not allowed to be sent.
280+
///
281+
/// See [Vulkan Spec 16.1.4. Location and Component Assignment](https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#interfaces-iointerfaces-locations)
282+
pub fn location_size(&self, cx: &CodegenCx<'_>) -> Option<u32> {
283+
let result = match *self {
284+
// bools cannot be in an Input / Output interface
285+
Self::Bool => return None,
286+
Self::Integer(_, _) | Self::Float(_) => 1,
287+
Self::Vector { .. } => 1,
288+
Self::Adt { field_types, .. } => {
289+
let mut locations = 0;
290+
for f in field_types {
291+
locations += cx.lookup_type(*f).location_size(cx)?
292+
}
293+
locations
294+
}
295+
Self::Matrix { element, count } => cx.lookup_type(element).location_size(cx)? * count,
296+
Self::Array { element, count } => {
297+
let count = cx.builder.lookup_const_scalar(count).unwrap();
298+
let count: u32 = count.try_into().unwrap();
299+
cx.lookup_type(element).location_size(cx)? * count
300+
}
301+
_ => return None,
302+
};
303+
Some(result)
304+
}
305+
279306
pub fn sizeof(&self, cx: &CodegenCx<'_>) -> Option<Size> {
280307
let result = match *self {
281308
// Types that have a dynamic size, or no concept of size at all.
@@ -287,12 +314,9 @@ impl SpirvType<'_> {
287314
Self::Vector { size, .. } => size,
288315
Self::Matrix { element, count } => cx.lookup_type(element).sizeof(cx)? * count as u64,
289316
Self::Array { element, count } => {
290-
cx.lookup_type(element).sizeof(cx)?
291-
* cx.builder
292-
.lookup_const_scalar(count)
293-
.unwrap()
294-
.try_into()
295-
.unwrap()
317+
let count = cx.builder.lookup_const_scalar(count).unwrap();
318+
let count = count.try_into().unwrap();
319+
cx.lookup_type(element).sizeof(cx)? * count
296320
}
297321
Self::Pointer { .. } => cx.tcx.data_layout.pointer_size,
298322
Self::Image { .. }

tests/compiletests/ui/spirv-attr/location_assignment_array_f32.stderr

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ OpName %2 "out1"
55
OpName %3 "out2"
66
OpName %6 "<[f32OpDecorate %7 ArrayStride 4
77
OpDecorate %2 Location 0
8-
OpDecorate %3 Location 1
8+
OpDecorate %3 Location 3
99
%8 = OpTypeFloat 32
1010
%9 = OpTypeInt 32 0
1111
%10 = OpConstant %9 3
@@ -37,11 +37,3 @@ OpFunctionEnd
3737
OpNoLine
3838
OpReturnValue %25
3939
OpFunctionEnd
40-
error: error:0:0 - [VUID-StandaloneSpirv-OpEntryPoint-08722] Entry-point has conflicting output location assignment at location 1, component 0
41-
OpEntryPoint Vertex %1 "main" %out1 %out2
42-
|
43-
= note: spirv-val failed
44-
= note: module `$TEST_BUILD_DIR/spirv-attr/location_assignment_array_f32.vulkan1.2`
45-
46-
error: aborting due to 1 previous error
47-

tests/compiletests/ui/spirv-attr/location_assignment_many_f32_struct.stderr

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ OpMemberDecorate %6 0 Offset 0
1515
OpMemberDecorate %6 1 Offset 4
1616
OpMemberDecorate %6 2 Offset 8
1717
OpDecorate %2 Location 0
18-
OpDecorate %3 Location 1
18+
OpDecorate %3 Location 3
1919
%7 = OpTypeFloat 32
2020
%5 = OpTypeStruct %7 %7 %7
2121
%8 = OpTypePointer Output %5
@@ -38,11 +38,3 @@ OpStore %3 %12
3838
OpNoLine
3939
OpReturn
4040
OpFunctionEnd
41-
error: error:0:0 - [VUID-StandaloneSpirv-OpEntryPoint-08722] Entry-point has conflicting output location assignment at location 1, component 0
42-
OpEntryPoint Vertex %1 "main" %out1 %out2
43-
|
44-
= note: spirv-val failed
45-
= note: module `$TEST_BUILD_DIR/spirv-attr/location_assignment_many_f32_struct.vulkan1.2`
46-
47-
error: aborting due to 1 previous error
48-

tests/compiletests/ui/spirv-attr/location_assignment_vec3_f32.stderr

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ OpName %3 "out2"
1212
OpMemberDecorate %6 0 Offset 0
1313
OpMemberDecorate %6 1 Offset 12
1414
OpDecorate %2 Location 0
15-
OpDecorate %3 Location 1
15+
OpDecorate %3 Location 2
1616
%7 = OpTypeFloat 32
1717
%8 = OpTypeVector %7 3
1818
%5 = OpTypeStruct %8 %7
@@ -36,11 +36,3 @@ OpStore %3 %13
3636
OpNoLine
3737
OpReturn
3838
OpFunctionEnd
39-
error: error:0:0 - [VUID-StandaloneSpirv-OpEntryPoint-08722] Entry-point has conflicting output location assignment at location 1, component 0
40-
OpEntryPoint Vertex %1 "main" %out1 %out2
41-
|
42-
= note: spirv-val failed
43-
= note: module `$TEST_BUILD_DIR/spirv-attr/location_assignment_vec3_f32.vulkan1.2`
44-
45-
error: aborting due to 1 previous error
46-

0 commit comments

Comments
 (0)