| ... | @@ -169,12 +169,10 @@ pub const Object = struct { | ... | @@ -169,12 +169,10 @@ pub const Object = struct { |
| 169 | /// via the usual `intern_map` mechanism. | 169 | /// via the usual `intern_map` mechanism. |
| 170 | ptr_types: PtrTypeMap = .{}, | 170 | ptr_types: PtrTypeMap = .{}, |
| 171 | | 171 | |
| 172 | /// For test declarations for Vulkan, we have to add a push constant with a pointer to a | 172 | /// For test declarations for Vulkan, we have to add a buffer. |
| 173 | /// buffer that we can use. We only need to generate this once, this holds the link information | 173 | /// We only need to generate this once, this holds the link information |
| 174 | /// related to that. | 174 | /// related to that. |
| 175 | error_push_constant: ?struct { | 175 | error_buffer: ?SpvModule.Decl.Index = null, |
| 176 | push_constant_ptr: SpvModule.Decl.Index, | | |
| 177 | } = null, | | |
| 178 | | 176 | |
| 179 | pub fn init(gpa: Allocator, target: std.Target) Object { | 177 | pub fn init(gpa: Allocator, target: std.Target) Object { |
| 180 | return .{ | 178 | return .{ |
| ... | @@ -1739,15 +1737,34 @@ const NavGen = struct { | ... | @@ -1739,15 +1737,34 @@ const NavGen = struct { |
| 1739 | fn spvStorageClass(self: *NavGen, as: std.builtin.AddressSpace) StorageClass { | 1737 | fn spvStorageClass(self: *NavGen, as: std.builtin.AddressSpace) StorageClass { |
| 1740 | return switch (as) { | 1738 | return switch (as) { |
| 1741 | .generic => if (self.spv.hasFeature(.generic_pointer)) .Generic else .Function, | 1739 | .generic => if (self.spv.hasFeature(.generic_pointer)) .Generic else .Function, |
| | 1740 | .global => { |
| | 1741 | if (self.spv.hasFeature(.kernel)) return .CrossWorkgroup; |
| | 1742 | return .StorageBuffer; |
| | 1743 | }, |
| | 1744 | .push_constant => { |
| | 1745 | assert(self.spv.hasFeature(.shader)); |
| | 1746 | return .PushConstant; |
| | 1747 | }, |
| | 1748 | .output => { |
| | 1749 | assert(self.spv.hasFeature(.shader)); |
| | 1750 | return .Output; |
| | 1751 | }, |
| | 1752 | .uniform => { |
| | 1753 | assert(self.spv.hasFeature(.shader)); |
| | 1754 | return .Uniform; |
| | 1755 | }, |
| | 1756 | .storage_buffer => { |
| | 1757 | assert(self.spv.hasFeature(.shader)); |
| | 1758 | return .StorageBuffer; |
| | 1759 | }, |
| | 1760 | .physical_storage_buffer => { |
| | 1761 | assert(self.spv.hasFeature(.physical_storage_buffer)); |
| | 1762 | return .PhysicalStorageBuffer; |
| | 1763 | }, |
| | 1764 | .constant => .UniformConstant, |
| 1742 | .shared => .Workgroup, | 1765 | .shared => .Workgroup, |
| 1743 | .local => .Function, | 1766 | .local => .Function, |
| 1744 | .global => if (self.spv.hasFeature(.shader)) .PhysicalStorageBuffer else .CrossWorkgroup, | | |
| 1745 | .constant => .UniformConstant, | | |
| 1746 | .push_constant => .PushConstant, | | |
| 1747 | .input => .Input, | 1767 | .input => .Input, |
| 1748 | .output => .Output, | | |
| 1749 | .uniform => .Uniform, | | |
| 1750 | .storage_buffer => .StorageBuffer, | | |
| 1751 | .gs, | 1768 | .gs, |
| 1752 | .fs, | 1769 | .fs, |
| 1753 | .ss, | 1770 | .ss, |
| ... | @@ -2713,38 +2730,32 @@ const NavGen = struct { | ... | @@ -2713,38 +2730,32 @@ const NavGen = struct { |
| 2713 | }); | 2730 | }); |
| 2714 | }, | 2731 | }, |
| 2715 | .vulkan, .opengl => { | 2732 | .vulkan, .opengl => { |
| 2716 | const ptr_ptr_anyerror_ty_id = self.spv.allocId(); | 2733 | if (self.object.error_buffer == null) { |
| 2717 | try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpTypePointer, .{ | | |
| 2718 | .id_result = ptr_ptr_anyerror_ty_id, | | |
| 2719 | .storage_class = .PushConstant, | | |
| 2720 | .type = ptr_anyerror_ty_id, | | |
| 2721 | }); | | |
| 2722 | | | |
| 2723 | if (self.object.error_push_constant == null) { | | |
| 2724 | const spv_err_decl_index = try self.spv.allocDecl(.global); | 2734 | const spv_err_decl_index = try self.spv.allocDecl(.global); |
| 2725 | try self.spv.declareDeclDeps(spv_err_decl_index, &.{}); | 2735 | try self.spv.declareDeclDeps(spv_err_decl_index, &.{}); |
| 2726 | | 2736 | |
| 2727 | const push_constant_struct_ty_id = self.spv.allocId(); | 2737 | const buffer_struct_ty_id = self.spv.allocId(); |
| 2728 | try self.spv.structType(push_constant_struct_ty_id, &.{ptr_anyerror_ty_id}, &.{"error_out_ptr"}); | 2738 | try self.spv.structType(buffer_struct_ty_id, &.{anyerror_ty_id}, &.{"error_out"}); |
| 2729 | try self.spv.decorate(push_constant_struct_ty_id, .Block); | 2739 | try self.spv.decorate(buffer_struct_ty_id, .Block); |
| 2730 | try self.spv.decorateMember(push_constant_struct_ty_id, 0, .{ .Offset = .{ .byte_offset = 0 } }); | 2740 | try self.spv.decorateMember(buffer_struct_ty_id, 0, .{ .Offset = .{ .byte_offset = 0 } }); |
| 2731 | | 2741 | |
| 2732 | const ptr_push_constant_struct_ty_id = self.spv.allocId(); | 2742 | const ptr_buffer_struct_ty_id = self.spv.allocId(); |
| 2733 | try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpTypePointer, .{ | 2743 | try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpTypePointer, .{ |
| 2734 | .id_result = ptr_push_constant_struct_ty_id, | 2744 | .id_result = ptr_buffer_struct_ty_id, |
| 2735 | .storage_class = .PushConstant, | 2745 | .storage_class = self.spvStorageClass(.global), |
| 2736 | .type = push_constant_struct_ty_id, | 2746 | .type = buffer_struct_ty_id, |
| 2737 | }); | 2747 | }); |
| 2738 | | 2748 | |
| | 2749 | const buffer_struct_id = self.spv.declPtr(spv_err_decl_index).result_id; |
| 2739 | try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpVariable, .{ | 2750 | try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpVariable, .{ |
| 2740 | .id_result_type = ptr_push_constant_struct_ty_id, | 2751 | .id_result_type = ptr_buffer_struct_ty_id, |
| 2741 | .id_result = self.spv.declPtr(spv_err_decl_index).result_id, | 2752 | .id_result = buffer_struct_id, |
| 2742 | .storage_class = .PushConstant, | 2753 | .storage_class = self.spvStorageClass(.global), |
| 2743 | }); | 2754 | }); |
| | 2755 | try self.spv.decorate(buffer_struct_id, .{ .DescriptorSet = .{ .descriptor_set = 0 } }); |
| | 2756 | try self.spv.decorate(buffer_struct_id, .{ .Binding = .{ .binding_point = 0 } }); |
| 2744 | | 2757 | |
| 2745 | self.object.error_push_constant = .{ | 2758 | self.object.error_buffer = spv_err_decl_index; |
| 2746 | .push_constant_ptr = spv_err_decl_index, | | |
| 2747 | }; | | |
| 2748 | } | 2759 | } |
| 2749 | | 2760 | |
| 2750 | try self.spv.sections.execution_modes.emit(self.spv.gpa, .OpExecutionMode, .{ | 2761 | try self.spv.sections.execution_modes.emit(self.spv.gpa, .OpExecutionMode, .{ |
| ... | @@ -2767,24 +2778,16 @@ const NavGen = struct { | ... | @@ -2767,24 +2778,16 @@ const NavGen = struct { |
| 2767 | .id_result = self.spv.allocId(), | 2778 | .id_result = self.spv.allocId(), |
| 2768 | }); | 2779 | }); |
| 2769 | | 2780 | |
| 2770 | const spv_err_decl_index = self.object.error_push_constant.?.push_constant_ptr; | 2781 | const spv_err_decl_index = self.object.error_buffer.?; |
| 2771 | const push_constant_id = self.spv.declPtr(spv_err_decl_index).result_id; | 2782 | const buffer_id = self.spv.declPtr(spv_err_decl_index).result_id; |
| 2772 | try decl_deps.append(spv_err_decl_index); | 2783 | try decl_deps.append(spv_err_decl_index); |
| 2773 | | 2784 | |
| 2774 | const zero_id = try self.constInt(Type.u32, 0); | 2785 | const zero_id = try self.constInt(Type.u32, 0); |
| 2775 | // We cannot use OpInBoundsAccessChain to dereference cross-storage class, so we have to use | | |
| 2776 | // a load. | | |
| 2777 | const tmp = self.spv.allocId(); | | |
| 2778 | try section.emit(self.spv.gpa, .OpInBoundsAccessChain, .{ | 2786 | try section.emit(self.spv.gpa, .OpInBoundsAccessChain, .{ |
| 2779 | .id_result_type = ptr_ptr_anyerror_ty_id, | | |
| 2780 | .id_result = tmp, | | |
| 2781 | .base = push_constant_id, | | |
| 2782 | .indexes = &.{zero_id}, | | |
| 2783 | }); | | |
| 2784 | try section.emit(self.spv.gpa, .OpLoad, .{ | | |
| 2785 | .id_result_type = ptr_anyerror_ty_id, | 2787 | .id_result_type = ptr_anyerror_ty_id, |
| 2786 | .id_result = p_error_id, | 2788 | .id_result = p_error_id, |
| 2787 | .pointer = tmp, | 2789 | .base = buffer_id, |
| | 2790 | .indexes = &.{zero_id}, |
| 2788 | }); | 2791 | }); |
| 2789 | }, | 2792 | }, |
| 2790 | else => unreachable, | 2793 | else => unreachable, |
| ... | @@ -4562,7 +4565,8 @@ const NavGen = struct { | ... | @@ -4562,7 +4565,8 @@ const NavGen = struct { |
| 4562 | const field_int_id = blk: { | 4565 | const field_int_id = blk: { |
| 4563 | if (field_ty.isPtrAtRuntime(zcu)) { | 4566 | if (field_ty.isPtrAtRuntime(zcu)) { |
| 4564 | assert(self.spv.hasFeature(.addresses) or | 4567 | assert(self.spv.hasFeature(.addresses) or |
| 4565 | (self.spv.hasFeature(.physical_storage_buffer) and field_ty.ptrAddressSpace(zcu) == .storage_buffer)); | 4568 | (self.spv.hasFeature(.physical_storage_buffer) and |
| | 4569 | field_ty.ptrAddressSpace(zcu) == .storage_buffer)); |
| 4566 | break :blk try self.intFromPtr(field_id); | 4570 | break :blk try self.intFromPtr(field_id); |
| 4567 | } | 4571 | } |
| 4568 | break :blk try self.bitCast(field_int_ty, field_ty, field_id); | 4572 | break :blk try self.bitCast(field_int_ty, field_ty, field_id); |
| ... | @@ -4969,13 +4973,16 @@ const NavGen = struct { | ... | @@ -4969,13 +4973,16 @@ const NavGen = struct { |
| 4969 | if (payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | 4973 | if (payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { |
| 4970 | const pl_ptr_ty_id = try self.ptrType(layout.payload_ty, .Function, .indirect); | 4974 | const pl_ptr_ty_id = try self.ptrType(layout.payload_ty, .Function, .indirect); |
| 4971 | const pl_ptr_id = try self.accessChain(pl_ptr_ty_id, tmp_id, &.{layout.payload_index}); | 4975 | const pl_ptr_id = try self.accessChain(pl_ptr_ty_id, tmp_id, &.{layout.payload_index}); |
| 4972 | const active_pl_ptr_ty_id = try self.ptrType(payload_ty, .Function, .indirect); | 4976 | const active_pl_ptr_id = if (!layout.payload_ty.eql(payload_ty, zcu)) blk: { |
| 4973 | const active_pl_ptr_id = self.spv.allocId(); | 4977 | const active_pl_ptr_ty_id = try self.ptrType(payload_ty, .Function, .indirect); |
| 4974 | try self.func.body.emit(self.spv.gpa, .OpBitcast, .{ | 4978 | const active_pl_ptr_id = self.spv.allocId(); |
| 4975 | .id_result_type = active_pl_ptr_ty_id, | 4979 | try self.func.body.emit(self.spv.gpa, .OpBitcast, .{ |
| 4976 | .id_result = active_pl_ptr_id, | 4980 | .id_result_type = active_pl_ptr_ty_id, |
| 4977 | .operand = pl_ptr_id, | 4981 | .id_result = active_pl_ptr_id, |
| 4978 | }); | 4982 | .operand = pl_ptr_id, |
| | 4983 | }); |
| | 4984 | break :blk active_pl_ptr_id; |
| | 4985 | } else pl_ptr_id; |
| 4979 | | 4986 | |
| 4980 | try self.store(payload_ty, active_pl_ptr_id, payload.?, .{}); | 4987 | try self.store(payload_ty, active_pl_ptr_id, payload.?, .{}); |
| 4981 | } else { | 4988 | } else { |