zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit e8ccd4fbcd8375d579042b5c38d8370ca271a00f (tree)
parent ffc510a70c3f1c3c28e1b2e444ccc826df121c05
Author: Ali Cheraghi <alichraghi@proton.me>
Date:   Wed, 24 Jun 2026 20:52:21 +0330

spirv: allow specifying texel type for storage images

Diffstat:
Mlib/std/lang.zig | 2+-
Msrc/Sema.zig | 87++++++++++++++++++++++++++++++++++++++-----------------------------------------
Msrc/codegen/spirv/CodeGen.zig | 7++-----
Mtest/behavior/spirv.zig | 2+-
Mtest/cases/compile_errors/SpirvType_vulkan_target.zig | 2+-
5 files changed, 47 insertions(+), 53 deletions(-)

diff --git a/lib/std/lang.zig b/lib/std/lang.zig @@ -838,7 +838,7 @@ pub const Type = union(enum) { pub const Usage = union(enum(u2)) { unknown: type, sampled: type, - storage, + storage: type, }; pub const Format = enum(u4) { diff --git a/src/Sema.zig b/src/Sema.zig @@ -20641,62 +20641,59 @@ fn zirReifySpirvType( break :ip_data .{ .name = name, .zir_index = tracked_inst, - .ty = switch (usage_tag) { - .sampled, .unknown => blk: { - const sampled_type = usage_val.unionPayload(zcu).toType(); - std.hash.autoHash(&hasher, sampled_type.toIntern()); + .ty = blk: { + const sampled_type = usage_val.unionPayload(zcu).toType(); + std.hash.autoHash(&hasher, sampled_type.toIntern()); - if (target.os.tag != .opencl and sampled_type.toIntern() == .void_type) { - return sema.fail(block, operand_src, "'void' type for '{t}' field is only valid under the 'opencl' os", .{usage_tag}); - } - if (target.os.tag == .opencl and sampled_type.toIntern() != .void_type) { - return sema.fail(block, operand_src, "'{t}' field type must be 'void' under the 'opencl' os", .{usage_tag}); - } + if (target.os.tag != .opencl and sampled_type.toIntern() == .void_type) { + return sema.fail(block, operand_src, "'void' type for '{t}' field is only valid under the 'opencl' os", .{usage_tag}); + } + if (target.os.tag == .opencl and sampled_type.toIntern() != .void_type) { + return sema.fail(block, operand_src, "'{t}' field type must be 'void' under the 'opencl' os", .{usage_tag}); + } - if (sampled_type.toIntern() != .void_type and - (!sampled_type.hasRuntimeBits(zcu) or (!sampled_type.isRuntimeFloat() and !sampled_type.isInt(zcu)))) - { - return sema.fail(block, operand_src, "invalid '{t}' field value '{f}'", .{ usage_tag, sampled_type.fmt(pt) }); + if (sampled_type.toIntern() != .void_type and + (!sampled_type.hasRuntimeBits(zcu) or (!sampled_type.isRuntimeFloat() and !sampled_type.isInt(zcu)))) + { + return sema.fail(block, operand_src, "invalid '{t}' field value '{f}'", .{ usage_tag, sampled_type.fmt(pt) }); + } + + if (target.os.tag == .vulkan) { + const ok = (sampled_type.isRuntimeFloat() and sampled_type.bitSize(zcu) == 32) or + (sampled_type.isInt(zcu) and (sampled_type.bitSize(zcu) == 32 or sampled_type.bitSize(zcu) == 64)); + if (!ok) { + return sema.fail( + block, + operand_src, + "'{t}' field value must be a 32-bit int, 64-bit int or 32-bit float under the 'vulkan' os", + .{usage_tag}, + ); } - if (target.os.tag == .vulkan) { - const ok = (sampled_type.isRuntimeFloat() and sampled_type.bitSize(zcu) == 32) or - (sampled_type.isInt(zcu) and (sampled_type.bitSize(zcu) == 32 or sampled_type.bitSize(zcu) == 64)); - if (!ok) { + if (format != .unknown) { + const format_kind: enum { float, sint, uint } = switch (format) { + .rgba32f, .rgba16f, .rgba8unorm, .rgba8snorm, .r32f => .float, + .rgba32i, .rgba16i, .rgba8i, .r32i => .sint, + .rgba32u, .rgba16u, .rgba8u, .r32u => .uint, + .unknown => unreachable, + }; + const matches = switch (format_kind) { + .float => sampled_type.isRuntimeFloat(), + .sint => sampled_type.isInt(zcu) and sampled_type.intInfo(zcu).signedness == .signed, + .uint => sampled_type.isInt(zcu) and sampled_type.intInfo(zcu).signedness == .unsigned, + }; + if (!matches) { return sema.fail( block, operand_src, - "'{t}' field value must be a 32-bit int, 64-bit int or 32-bit float under the 'vulkan' os", - .{usage_tag}, + "image 'format' '.{t}' does not match '{t}' type '{f}' under the 'vulkan' os", + .{ format, usage_tag, sampled_type.fmt(pt) }, ); } - - if (format != .unknown) { - const format_kind: enum { float, sint, uint } = switch (format) { - .rgba32f, .rgba16f, .rgba8unorm, .rgba8snorm, .r32f => .float, - .rgba32i, .rgba16i, .rgba8i, .r32i => .sint, - .rgba32u, .rgba16u, .rgba8u, .r32u => .uint, - .unknown => unreachable, - }; - const matches = switch (format_kind) { - .float => sampled_type.isRuntimeFloat(), - .sint => sampled_type.isInt(zcu) and sampled_type.intInfo(zcu).signedness == .signed, - .uint => sampled_type.isInt(zcu) and sampled_type.intInfo(zcu).signedness == .unsigned, - }; - if (!matches) { - return sema.fail( - block, - operand_src, - "image 'format' '.{t}' does not match '{t}' type '{f}' under the 'vulkan' os", - .{ format, usage_tag, sampled_type.fmt(pt) }, - ); - } - } } + } - break :blk sampled_type.toIntern(); - }, - .storage => .none, + break :blk sampled_type.toIntern(); }, .flags = .{ .tag = .image, diff --git a/src/codegen/spirv/CodeGen.zig b/src/codegen/spirv/CodeGen.zig @@ -2345,10 +2345,7 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id { switch (spirv_type.flags.tag) { .sampler => try cg.sections.globals.emit(gpa, .OpTypeSampler, .{ .id_result = result_id }), .image => { - const sampled_type_id = if (spirv_type.ty == .none) - try cg.intType(.unsigned, 32) - else - try cg.resolveType(Type.fromInterned(spirv_type.ty), .direct); + const sampled_type_id = try cg.resolveType(.fromInterned(spirv_type.ty), .direct); try cg.sections.globals.emit(gpa, .OpTypeImage, .{ .id_result = result_id, .sampled_type = sampled_type_id, @@ -2366,7 +2363,7 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id { .arrayed = @intFromBool(spirv_type.flags.is_arrayed), .ms = @intFromBool(spirv_type.flags.is_multisampled), .sampled = switch (spirv_type.flags.usage) { - .unknown => 1, + .unknown => 0, .sampled => 1, .storage => 2, }, diff --git a/test/behavior/spirv.zig b/test/behavior/spirv.zig @@ -10,7 +10,7 @@ const Image = @SpirvType(.{ .image = .{ } }); const SampledImage = @SpirvType(.{ .sampled_image = Image }); const StorageImage = @SpirvType(.{ .image = .{ - .usage = .storage, + .usage = .{ .storage = u32 }, .format = .unknown, .dim = .@"2d", .depth = .unknown, diff --git a/test/cases/compile_errors/SpirvType_vulkan_target.zig b/test/cases/compile_errors/SpirvType_vulkan_target.zig @@ -1,6 +1,6 @@ comptime { _ = @SpirvType(.{ .image = .{ - .usage = .storage, + .usage = .{ .storage = u32 }, .format = .unknown, .dim = .@"2d", .depth = .unknown,