From 14d5da916447f10bb812c3c6a199ab4ab76f61ec Mon Sep 17 00:00:00 2001 From: Ali Cheraghi Date: Sun, 21 Jun 2026 08:49:15 +0330 Subject: [PATCH] spirv: don't put dummy `OpVariable` for non-Function pointers This would raise a validation error when the parameter type is a non-Function opaque pointer. e.g. an `@extern(*addrspace(.constant) const SampledImage, ...)` --- src/codegen/spirv/CodeGen.zig | 3 ++- test/cases/image_sampling_spirv.zig | 42 +++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 test/cases/image_sampling_spirv.zig diff --git a/src/codegen/spirv/CodeGen.zig b/src/codegen/spirv/CodeGen.zig index f6c533c31aadd92f7dc52d1b3898667cf880cbfa..d60ccf8dc1fd3f2d44e2ac3017f7c904f0946bfb 100644 --- a/src/codegen/spirv/CodeGen.zig +++ b/src/codegen/spirv/CodeGen.zig @@ -8112,7 +8112,8 @@ fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier) if (!arg_ty.hasRuntimeBits(zcu)) continue; if (arg_ty.zigTypeTag(zcu) == .pointer and !arg_ty.isSlice(zcu) and - !arg_ty.childType(zcu).hasRuntimeBits(zcu)) + !arg_ty.childType(zcu).hasRuntimeBits(zcu) and + cg.module.storageClass(arg_ty.ptrAddressSpace(zcu)) == .function) { // in logical addressing, pointer arguments to function calls // must be memory object declarations (OpVariable). for pointers to diff --git a/test/cases/image_sampling_spirv.zig b/test/cases/image_sampling_spirv.zig new file mode 100644 index 0000000000000000000000000000000000000000..030727e95c106b6b2521ab72d07bb608b58a22a8 --- /dev/null +++ b/test/cases/image_sampling_spirv.zig @@ -0,0 +1,42 @@ +pub const Image = @SpirvType(.{ .image = .{ + .usage = .{ .sampled = f32 }, + .format = .unknown, + .dim = .@"2d", + .depth = .not_depth, + .arrayed = false, + .multisampled = false, + .access = .unknown, +} }); +pub const SampledImage = @SpirvType(.{ .sampled_image = Image }); + +const image_in = @extern(*addrspace(.constant) const SampledImage, .{ + .name = "image_in", + .decoration = .{ .descriptor = .{ .set = 2, .binding = 0 } }, +}); +const uv_in = @extern(*addrspace(.input) @Vector(2, f32), .{ .name = "uv", .decoration = .{ .location = 0 } }); +const color_out = @extern(*addrspace(.output) @Vector(4, f32), .{ .name = "color", .decoration = .{ .location = 0 } }); + +export fn main() callconv(.{ .spirv_fragment = .{} }) void { + color_out.* = imageSample(image_in, uv_in.*); +} + +fn imageSample( + sampled_image: *addrspace(.constant) const SampledImage, + uv: @Vector(2, f32), +) @Vector(4, f32) { + return asm volatile ( + \\%loaded_sampler = OpLoad %SampledImage %sampled_image + \\%ret = OpImageSampleImplicitLod %Result %loaded_sampler %uv + : [ret] "" (-> @Vector(4, f32)), + : [SampledImage] "t" (SampledImage), + [sampled_image] "" (sampled_image), + [Result] "t" (@Vector(4, f32)), + [uv] "" (uv), + ); +} + +// compile +// output_mode=Exe +// backend=selfhosted +// target=spirv32-vulkan +// emit_bin=true -- 2.54.0