diff --git a/crates/rustc_codegen_spirv/src/codegen_cx/entry.rs b/crates/rustc_codegen_spirv/src/codegen_cx/entry.rs index ae13b03363..e8a62eebb6 100644 --- a/crates/rustc_codegen_spirv/src/codegen_cx/entry.rs +++ b/crates/rustc_codegen_spirv/src/codegen_cx/entry.rs @@ -545,7 +545,7 @@ impl<'tcx> CodegenCx<'tcx> { Decoration::Location, std::iter::once(Operand::LiteralInt32(*location)), ); - *location += 1; + *location += self.location_count_of_type(value_spirv_type); } // Emit the `OpVariable` with its *Result* ID set to `var`. @@ -565,6 +565,41 @@ impl<'tcx> CodegenCx<'tcx> { } } + fn location_count_of_type(&self, ty: Word) -> u32 { + match self.lookup_type(ty) { + // Arrays take up multiple locations. + SpirvType::Array { count, element } => { + self.builder + .lookup_const_u64(count) + .expect("Array type has invalid count value") as u32 + * self.location_count_of_type(element) + } + // Structs take up one location per field. + SpirvType::Adt { field_types, .. } => { + let mut size = 0; + + for field_type in field_types { + size += self.location_count_of_type(field_type); + } + + size + } + SpirvType::Vector { element, count } => { + // 3 or 4 component vectors take up 2 locations if they have a 64-bit scalar type. + if count > 2 { + match self.lookup_type(element) { + SpirvType::Float(64) | SpirvType::Integer(64, _) => 2, + _ => 1, + } + } else { + 1 + } + } + SpirvType::Matrix { element, count } => count * self.location_count_of_type(element), + _ => 1, + } + } + // Booleans are only allowed in some storage classes. Error if they're in others. // Integers and f64s must be decorated with `#[spirv(flat)]`. fn check_for_bad_types( diff --git a/tests/ui/dis/array_location_calculation.rs b/tests/ui/dis/array_location_calculation.rs new file mode 100644 index 0000000000..ac5c22fd88 --- /dev/null +++ b/tests/ui/dis/array_location_calculation.rs @@ -0,0 +1,31 @@ +// build-pass +// compile-flags: -C llvm-args=--disassemble-globals +// normalize-stderr-test "OpCapability VulkanMemoryModel\n" -> "" +// normalize-stderr-test "OpExtension .SPV_KHR_vulkan_memory_model.\n" -> "" +// normalize-stderr-test "OpMemoryModel Logical Vulkan" -> "OpMemoryModel Logical Simple" +// normalize-stderr-test "OpMemberName %12 0 .0.\n" -> "" + +use spirv_std::{ + self as _, + glam::{DVec3, IVec4, Mat3, Vec4}, +}; + +#[spirv(matrix)] +pub struct Mat4x3 { + pub col_0: Vec4, + pub col_1: Vec4, + pub col_2: Vec4, +} + +#[spirv(fragment)] +pub fn main( + one: [f32; 7], + two: [f32; 3], + three: Mat3, + four: DVec3, + five: IVec4, + six: f32, + seven: Mat4x3, + eight: u32, +) { +} diff --git a/tests/ui/dis/array_location_calculation.stderr b/tests/ui/dis/array_location_calculation.stderr new file mode 100644 index 0000000000..8ab0e9862d --- /dev/null +++ b/tests/ui/dis/array_location_calculation.stderr @@ -0,0 +1,79 @@ +OpCapability Float64 +OpCapability Int16 +OpCapability Int64 +OpCapability Int8 +OpCapability ShaderClockKHR +OpCapability Shader +OpExtension "SPV_KHR_shader_clock" +OpMemoryModel Logical Simple +OpEntryPoint Fragment %1 "main" %2 %3 %4 %5 %6 %7 %8 %9 +OpExecutionMode %1 OriginUpperLeft +%10 = OpString "$OPSTRING_FILENAME/array_location_calculation.rs" +OpMemberName %11 0 "x_axis" +OpMemberName %11 1 "y_axis" +OpMemberName %11 2 "z_axis" +OpName %11 "spirv_std::glam::core::storage::Columns3>" +OpName %12 "spirv_std::glam::Mat3" +OpName %13 "array_location_calculation::main" +OpName %2 "one" +OpName %3 "two" +OpName %4 "three" +OpName %5 "four" +OpName %6 "five" +OpName %7 "six" +OpName %8 "seven" +OpName %9 "eight" +OpMemberName %11 0 "x_axis" +OpMemberName %11 1 "y_axis" +OpMemberName %11 2 "z_axis" +OpMemberName %11 0 "x_axis" +OpMemberName %11 1 "y_axis" +OpMemberName %11 2 "z_axis" +OpDecorate %14 ArrayStride 4 +OpDecorate %15 ArrayStride 4 +OpMemberDecorate %11 0 Offset 0 +OpMemberDecorate %11 1 Offset 16 +OpMemberDecorate %11 2 Offset 32 +OpMemberDecorate %12 0 Offset 0 +OpDecorate %2 Location 0 +OpDecorate %3 Location 7 +OpDecorate %4 Location 10 +OpDecorate %5 Location 13 +OpDecorate %6 Location 15 +OpDecorate %7 Location 16 +OpDecorate %8 Location 17 +OpDecorate %9 Location 20 +%16 = OpTypeVoid +%17 = OpTypeFloat 32 +%18 = OpTypeInt 32 0 +%19 = OpConstant %18 7 +%14 = OpTypeArray %17 %19 +%20 = OpConstant %18 3 +%15 = OpTypeArray %17 %20 +%21 = OpTypeVector %17 3 +%11 = OpTypeStruct %21 %21 %21 +%12 = OpTypeStruct %11 +%22 = OpTypeFloat 64 +%23 = OpTypeVector %22 3 +%24 = OpTypeInt 32 1 +%25 = OpTypeVector %24 4 +%26 = OpTypeVector %17 4 +%27 = OpTypeMatrix %26 3 +%28 = OpTypeFunction %16 %14 %15 %12 %23 %25 %17 %27 %18 +%29 = OpTypeFunction %16 +%30 = OpTypePointer Input %14 +%2 = OpVariable %30 Input +%31 = OpTypePointer Input %15 +%3 = OpVariable %31 Input +%32 = OpTypePointer Input %12 +%4 = OpVariable %32 Input +%33 = OpTypePointer Input %23 +%5 = OpVariable %33 Input +%34 = OpTypePointer Input %25 +%6 = OpVariable %34 Input +%35 = OpTypePointer Input %17 +%7 = OpVariable %35 Input +%36 = OpTypePointer Input %27 +%8 = OpVariable %36 Input +%37 = OpTypePointer Input %18 +%9 = OpVariable %37 Input