From ef58251fea8b2f64ef17fbb5794215c7c1b199fc Mon Sep 17 00:00:00 2001 From: firestar99 Date: Thu, 15 Jan 2026 09:50:45 +0100 Subject: [PATCH 1/2] allow zst entry params in input and output positions --- .../src/codegen_cx/entry.rs | 55 +++++++++---------- .../ui/spirv-attr/entry_unit_type.rs | 24 ++++++++ .../ui/spirv-attr/entry_unit_type.stderr | 47 ++++++++++++++++ 3 files changed, 98 insertions(+), 28 deletions(-) create mode 100644 tests/compiletests/ui/spirv-attr/entry_unit_type.rs create mode 100644 tests/compiletests/ui/spirv-attr/entry_unit_type.stderr diff --git a/crates/rustc_codegen_spirv/src/codegen_cx/entry.rs b/crates/rustc_codegen_spirv/src/codegen_cx/entry.rs index e78175785e..0b78839bc5 100644 --- a/crates/rustc_codegen_spirv/src/codegen_cx/entry.rs +++ b/crates/rustc_codegen_spirv/src/codegen_cx/entry.rs @@ -87,7 +87,7 @@ impl<'tcx> CodegenCx<'tcx> { }; for (arg_abi, hir_param) in fn_abi.args.iter().zip(hir_params) { match arg_abi.mode { - PassMode::Direct(_) => {} + PassMode::Direct(_) | PassMode::Ignore => {} PassMode::Pair(..) => { // FIXME(eddyb) implement `ScalarPair` `Input`s, or change // the `FnAbi` readjustment to only use `PassMode::Pair` for @@ -103,16 +103,6 @@ impl<'tcx> CodegenCx<'tcx> { ); } } - // FIXME(eddyb) support these (by just ignoring them) - if there - // is any validation concern, it should be done on the types. - PassMode::Ignore => self.tcx.dcx().span_fatal( - hir_param.ty_span, - format!( - "entry point parameter type not yet supported \ - (`{}` has size `0`)", - arg_abi.layout.ty - ), - ), _ => span_bug!( hir_param.ty_span, "query hooks should've made this `PassMode` impossible: {:#?}", @@ -674,28 +664,37 @@ impl<'tcx> CodegenCx<'tcx> { // starting from the `value_ptr` pointing to a `value_spirv_type` // (e.g. `Input` doesn't use indirection, so we have to load from it). if let ty::Ref(..) = entry_arg_abi.layout.ty.kind() { - call_args.push(value_ptr.unwrap()); match entry_arg_abi.mode { - PassMode::Direct(_) => assert_eq!(value_len, None), - PassMode::Pair(..) => call_args.push(value_len.unwrap()), + PassMode::Direct(_) => { + assert_eq!(value_len, None); + call_args.push(value_ptr.unwrap()); + } + PassMode::Pair(..) => call_args.extend([value_ptr.unwrap(), value_len.unwrap()]), + PassMode::Ignore => (), _ => unreachable!(), } } else { - assert_matches!(entry_arg_abi.mode, PassMode::Direct(_)); - - let value = match storage_class { - Ok(_) => { - assert_eq!(storage_class, Ok(StorageClass::Input)); - bx.load( - entry_arg_abi.layout.spirv_type(hir_param.ty_span, bx), - value_ptr.unwrap(), - entry_arg_abi.layout.align.abi, - ) + match entry_arg_abi.mode { + PassMode::Ignore => {} + PassMode::Direct(_) => { + let value = match storage_class { + Ok(_) => { + assert_eq!(storage_class, Ok(StorageClass::Input)); + bx.load( + entry_arg_abi.layout.spirv_type(hir_param.ty_span, bx), + value_ptr.unwrap(), + entry_arg_abi.layout.align.abi, + ) + } + Err(SpecConstant { .. }) => { + spec_const_id.unwrap().with_type(value_spirv_type) + } + }; + call_args.push(value); + assert_eq!(value_len, None); } - Err(SpecConstant { .. }) => spec_const_id.unwrap().with_type(value_spirv_type), - }; - call_args.push(value); - assert_eq!(value_len, None); + _ => unreachable!(), + } } // FIXME(eddyb) check whether the storage class is compatible with the diff --git a/tests/compiletests/ui/spirv-attr/entry_unit_type.rs b/tests/compiletests/ui/spirv-attr/entry_unit_type.rs new file mode 100644 index 0000000000..895a0c15d0 --- /dev/null +++ b/tests/compiletests/ui/spirv-attr/entry_unit_type.rs @@ -0,0 +1,24 @@ +// build-pass +// compile-flags: -C llvm-args=--disassemble +// normalize-stderr-test "OpSource .*\n" -> "" +// normalize-stderr-test "OpLine .*\n" -> "" +// normalize-stderr-test "%\d+ = OpString .*\n" -> "" +// normalize-stderr-test "(^|\n); .*" -> "" +// normalize-stderr-test "OpCapability VulkanMemoryModel\n" -> "" +// normalize-stderr-test "OpMemoryModel Logical Vulkan" -> "OpMemoryModel Logical Simple" +// ignore-spv1.0 +// ignore-spv1.1 +// ignore-spv1.2 +// ignore-spv1.3 +// ignore-vulkan1.0 +// ignore-vulkan1.1 + +use spirv_std::glam::*; +use spirv_std::{Image, spirv}; + +#[spirv(vertex)] +pub fn main(in1: (), in2: u32, out1: &mut [f32; 3], out2: &mut (), out3: &mut f32) { + *out1 = Default::default(); + *out2 = Default::default(); + *out3 = in2 as f32; +} diff --git a/tests/compiletests/ui/spirv-attr/entry_unit_type.stderr b/tests/compiletests/ui/spirv-attr/entry_unit_type.stderr new file mode 100644 index 0000000000..f5412e82eb --- /dev/null +++ b/tests/compiletests/ui/spirv-attr/entry_unit_type.stderr @@ -0,0 +1,47 @@ + +OpCapability Shader +OpMemoryModel Logical Simple +OpEntryPoint Vertex %1 "main" %2 %3 %4 +OpName %2 "in2" +OpName %3 "out1" +OpName %4 "out3" +OpName %7 "<[f32; 3] as core::default::Default>::default" +OpDecorate %2 Location 0 +OpDecorate %8 ArrayStride 4 +OpDecorate %3 Location 0 +OpDecorate %4 Location 3 +%9 = OpTypeInt 32 0 +%10 = OpTypePointer Input %9 +%11 = OpTypeFloat 32 +%12 = OpConstant %9 3 +%13 = OpTypeArray %11 %12 +%14 = OpTypePointer Output %13 +%15 = OpTypePointer Output %11 +%16 = OpTypeVoid +%17 = OpTypeFunction %16 +%2 = OpVariable %10 Input +%8 = OpTypeArray %11 %12 +%18 = OpTypeFunction %8 +%19 = OpConstant %11 0 +%3 = OpVariable %14 Output +%4 = OpVariable %15 Output +%1 = OpFunction %16 None %17 +%20 = OpLabel +%21 = OpLoad %9 %2 +%22 = OpFunctionCall %8 %7 +%23 = OpCompositeExtract %11 %22 0 +%24 = OpCompositeExtract %11 %22 1 +%25 = OpCompositeExtract %11 %22 2 +%26 = OpCompositeConstruct %13 %23 %24 %25 +OpStore %3 %26 +%27 = OpConvertUToF %11 %21 +OpStore %4 %27 +OpNoLine +OpReturn +OpFunctionEnd +%7 = OpFunction %8 None %18 +%28 = OpLabel +%29 = OpCompositeConstruct %8 %19 %19 %19 +OpNoLine +OpReturnValue %29 +OpFunctionEnd From 14464d6c48fd5184373a123738f21eec997c9c5c Mon Sep 17 00:00:00 2001 From: firestar99 Date: Thu, 15 Jan 2026 09:57:31 +0100 Subject: [PATCH 2/2] compiletest to showcase generic entry points --- .../ui/spirv-attr/entry_generic.rs | 28 ++++++++++++ .../ui/spirv-attr/entry_generic.stderr | 44 +++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 tests/compiletests/ui/spirv-attr/entry_generic.rs create mode 100644 tests/compiletests/ui/spirv-attr/entry_generic.stderr diff --git a/tests/compiletests/ui/spirv-attr/entry_generic.rs b/tests/compiletests/ui/spirv-attr/entry_generic.rs new file mode 100644 index 0000000000..351ea8c762 --- /dev/null +++ b/tests/compiletests/ui/spirv-attr/entry_generic.rs @@ -0,0 +1,28 @@ +// build-pass +// compile-flags: -C llvm-args=--disassemble +// normalize-stderr-test "OpSource .*\n" -> "" +// normalize-stderr-test "OpLine .*\n" -> "" +// normalize-stderr-test "%\d+ = OpString .*\n" -> "" +// normalize-stderr-test "(^|\n); .*" -> "" +// normalize-stderr-test "OpCapability VulkanMemoryModel\n" -> "" +// normalize-stderr-test "OpMemoryModel Logical Vulkan" -> "OpMemoryModel Logical Simple" +// ignore-spv1.0 +// ignore-spv1.1 +// ignore-spv1.2 +// ignore-spv1.3 +// ignore-vulkan1.0 +// ignore-vulkan1.1 + +use spirv_std::glam::*; +use spirv_std::{Image, spirv}; + +#[spirv(vertex)] +pub fn main(in1: T, out1: &mut T) { + *out1 = in1; +} + +pub fn dummy() { + main::(0, &mut 0); + main::(0., &mut 0.); + main::<()>((), &mut ()); +} diff --git a/tests/compiletests/ui/spirv-attr/entry_generic.stderr b/tests/compiletests/ui/spirv-attr/entry_generic.stderr new file mode 100644 index 0000000000..a2d155926b --- /dev/null +++ b/tests/compiletests/ui/spirv-attr/entry_generic.stderr @@ -0,0 +1,44 @@ + +OpCapability Shader +OpMemoryModel Logical Simple +OpEntryPoint Vertex %1 "main::" %2 %3 +OpEntryPoint Vertex %4 "main::" %5 %6 +OpEntryPoint Vertex %7 "main::<()>" +OpName %2 "in1" +OpName %3 "out1" +OpName %5 "in1" +OpName %6 "out1" +OpDecorate %2 Location 0 +OpDecorate %3 Location 0 +OpDecorate %5 Location 0 +OpDecorate %6 Location 0 +%9 = OpTypeFloat 32 +%10 = OpTypePointer Input %9 +%11 = OpTypePointer Output %9 +%12 = OpTypeVoid +%13 = OpTypeFunction %12 +%2 = OpVariable %10 Input +%3 = OpVariable %11 Output +%14 = OpTypeInt 32 0 +%15 = OpTypePointer Input %14 +%16 = OpTypePointer Output %14 +%5 = OpVariable %15 Input +%6 = OpVariable %16 Output +%1 = OpFunction %12 None %13 +%17 = OpLabel +%18 = OpLoad %9 %2 +OpStore %3 %18 +OpNoLine +OpReturn +OpFunctionEnd +%4 = OpFunction %12 None %13 +%19 = OpLabel +%20 = OpLoad %14 %5 +OpStore %6 %20 +OpNoLine +OpReturn +OpFunctionEnd +%7 = OpFunction %12 None %13 +%21 = OpLabel +OpReturn +OpFunctionEnd