| ... | @@ -20641,62 +20641,59 @@ fn zirReifySpirvType( | ... | @@ -20641,62 +20641,59 @@ fn zirReifySpirvType( |
| 20641 | break :ip_data .{ | 20641 | break :ip_data .{ |
| 20642 | .name = name, | 20642 | .name = name, |
| 20643 | .zir_index = tracked_inst, | 20643 | .zir_index = tracked_inst, |
| 20644 | .ty = switch (usage_tag) { | 20644 | .ty = blk: { |
| 20645 | .sampled, .unknown => blk: { | 20645 | const sampled_type = usage_val.unionPayload(zcu).toType(); |
| 20646 | const sampled_type = usage_val.unionPayload(zcu).toType(); | 20646 | std.hash.autoHash(&hasher, sampled_type.toIntern()); |
| 20647 | std.hash.autoHash(&hasher, sampled_type.toIntern()); | | |
| 20648 | | 20647 | |
| 20649 | if (target.os.tag != .opencl and sampled_type.toIntern() == .void_type) { | 20648 | if (target.os.tag != .opencl and sampled_type.toIntern() == .void_type) { |
| 20650 | return sema.fail(block, operand_src, "'void' type for '{t}' field is only valid under the 'opencl' os", .{usage_tag}); | 20649 | return sema.fail(block, operand_src, "'void' type for '{t}' field is only valid under the 'opencl' os", .{usage_tag}); |
| 20651 | } | 20650 | } |
| 20652 | if (target.os.tag == .opencl and sampled_type.toIntern() != .void_type) { | 20651 | if (target.os.tag == .opencl and sampled_type.toIntern() != .void_type) { |
| 20653 | return sema.fail(block, operand_src, "'{t}' field type must be 'void' under the 'opencl' os", .{usage_tag}); | 20652 | return sema.fail(block, operand_src, "'{t}' field type must be 'void' under the 'opencl' os", .{usage_tag}); |
| 20654 | } | 20653 | } |
| 20655 | | 20654 | |
| 20656 | if (sampled_type.toIntern() != .void_type and | 20655 | if (sampled_type.toIntern() != .void_type and |
| 20657 | (!sampled_type.hasRuntimeBits(zcu) or (!sampled_type.isRuntimeFloat() and !sampled_type.isInt(zcu)))) | 20656 | (!sampled_type.hasRuntimeBits(zcu) or (!sampled_type.isRuntimeFloat() and !sampled_type.isInt(zcu)))) |
| 20658 | { | 20657 | { |
| 20659 | return sema.fail(block, operand_src, "invalid '{t}' field value '{f}'", .{ usage_tag, sampled_type.fmt(pt) }); | 20658 | return sema.fail(block, operand_src, "invalid '{t}' field value '{f}'", .{ usage_tag, sampled_type.fmt(pt) }); |
| | 20659 | } |
| | 20660 | |
| | 20661 | if (target.os.tag == .vulkan) { |
| | 20662 | const ok = (sampled_type.isRuntimeFloat() and sampled_type.bitSize(zcu) == 32) or |
| | 20663 | (sampled_type.isInt(zcu) and (sampled_type.bitSize(zcu) == 32 or sampled_type.bitSize(zcu) == 64)); |
| | 20664 | if (!ok) { |
| | 20665 | return sema.fail( |
| | 20666 | block, |
| | 20667 | operand_src, |
| | 20668 | "'{t}' field value must be a 32-bit int, 64-bit int or 32-bit float under the 'vulkan' os", |
| | 20669 | .{usage_tag}, |
| | 20670 | ); |
| 20660 | } | 20671 | } |
| 20661 | | 20672 | |
| 20662 | if (target.os.tag == .vulkan) { | 20673 | if (format != .unknown) { |
| 20663 | const ok = (sampled_type.isRuntimeFloat() and sampled_type.bitSize(zcu) == 32) or | 20674 | const format_kind: enum { float, sint, uint } = switch (format) { |
| 20664 | (sampled_type.isInt(zcu) and (sampled_type.bitSize(zcu) == 32 or sampled_type.bitSize(zcu) == 64)); | 20675 | .rgba32f, .rgba16f, .rgba8unorm, .rgba8snorm, .r32f => .float, |
| 20665 | if (!ok) { | 20676 | .rgba32i, .rgba16i, .rgba8i, .r32i => .sint, |
| | 20677 | .rgba32u, .rgba16u, .rgba8u, .r32u => .uint, |
| | 20678 | .unknown => unreachable, |
| | 20679 | }; |
| | 20680 | const matches = switch (format_kind) { |
| | 20681 | .float => sampled_type.isRuntimeFloat(), |
| | 20682 | .sint => sampled_type.isInt(zcu) and sampled_type.intInfo(zcu).signedness == .signed, |
| | 20683 | .uint => sampled_type.isInt(zcu) and sampled_type.intInfo(zcu).signedness == .unsigned, |
| | 20684 | }; |
| | 20685 | if (!matches) { |
| 20666 | return sema.fail( | 20686 | return sema.fail( |
| 20667 | block, | 20687 | block, |
| 20668 | operand_src, | 20688 | operand_src, |
| 20669 | "'{t}' field value must be a 32-bit int, 64-bit int or 32-bit float under the 'vulkan' os", | 20689 | "image 'format' '.{t}' does not match '{t}' type '{f}' under the 'vulkan' os", |
| 20670 | .{usage_tag}, | 20690 | .{ format, usage_tag, sampled_type.fmt(pt) }, |
| 20671 | ); | 20691 | ); |
| 20672 | } | 20692 | } |
| 20673 | | | |
| 20674 | if (format != .unknown) { | | |
| 20675 | const format_kind: enum { float, sint, uint } = switch (format) { | | |
| 20676 | .rgba32f, .rgba16f, .rgba8unorm, .rgba8snorm, .r32f => .float, | | |
| 20677 | .rgba32i, .rgba16i, .rgba8i, .r32i => .sint, | | |
| 20678 | .rgba32u, .rgba16u, .rgba8u, .r32u => .uint, | | |
| 20679 | .unknown => unreachable, | | |
| 20680 | }; | | |
| 20681 | const matches = switch (format_kind) { | | |
| 20682 | .float => sampled_type.isRuntimeFloat(), | | |
| 20683 | .sint => sampled_type.isInt(zcu) and sampled_type.intInfo(zcu).signedness == .signed, | | |
| 20684 | .uint => sampled_type.isInt(zcu) and sampled_type.intInfo(zcu).signedness == .unsigned, | | |
| 20685 | }; | | |
| 20686 | if (!matches) { | | |
| 20687 | return sema.fail( | | |
| 20688 | block, | | |
| 20689 | operand_src, | | |
| 20690 | "image 'format' '.{t}' does not match '{t}' type '{f}' under the 'vulkan' os", | | |
| 20691 | .{ format, usage_tag, sampled_type.fmt(pt) }, | | |
| 20692 | ); | | |
| 20693 | } | | |
| 20694 | } | | |
| 20695 | } | 20693 | } |
| | 20694 | } |
| 20696 | | 20695 | |
| 20697 | break :blk sampled_type.toIntern(); | 20696 | break :blk sampled_type.toIntern(); |
| 20698 | }, | | |
| 20699 | .storage => .none, | | |
| 20700 | }, | 20697 | }, |
| 20701 | .flags = .{ | 20698 | .flags = .{ |
| 20702 | .tag = .image, | 20699 | .tag = .image, |