| ... | @@ -169,6 +169,13 @@ pub const Object = struct { | ... | @@ -169,6 +169,13 @@ 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 |
| | 173 | /// buffer that we can use. We only need to generate this once, this holds the link information |
| | 174 | /// related to that. |
| | 175 | error_push_constant: ?struct { |
| | 176 | push_constant_ptr: SpvModule.Decl.Index, |
| | 177 | } = null, |
| | 178 | |
| 172 | pub fn init(gpa: Allocator) Object { | 179 | pub fn init(gpa: Allocator) Object { |
| 173 | return .{ | 180 | return .{ |
| 174 | .gpa = gpa, | 181 | .gpa = gpa, |
| ... | @@ -2908,30 +2915,118 @@ const NavGen = struct { | ... | @@ -2908,30 +2915,118 @@ const NavGen = struct { |
| 2908 | .flags = .{ .address_space = .global }, | 2915 | .flags = .{ .address_space = .global }, |
| 2909 | }); | 2916 | }); |
| 2910 | const ptr_anyerror_ty_id = try self.resolveType(ptr_anyerror_ty, .direct); | 2917 | const ptr_anyerror_ty_id = try self.resolveType(ptr_anyerror_ty, .direct); |
| 2911 | const kernel_proto_ty_id = try self.functionType(Type.void, &.{ptr_anyerror_ty}); | | |
| 2912 | | | |
| 2913 | const test_id = self.spv.declPtr(spv_test_decl_index).result_id; | | |
| 2914 | | 2918 | |
| 2915 | const spv_decl_index = try self.spv.allocDecl(.func); | 2919 | const spv_decl_index = try self.spv.allocDecl(.func); |
| 2916 | const kernel_id = self.spv.declPtr(spv_decl_index).result_id; | 2920 | const kernel_id = self.spv.declPtr(spv_decl_index).result_id; |
| | 2921 | // for some reason we don't need to decorate the push constant here... |
| | 2922 | try self.spv.declareDeclDeps(spv_decl_index, &.{spv_test_decl_index}); |
| | 2923 | |
| | 2924 | const section = &self.spv.sections.functions; |
| | 2925 | |
| | 2926 | const target = self.getTarget(); |
| 2917 | | 2927 | |
| 2918 | const error_id = self.spv.allocId(); | | |
| 2919 | const p_error_id = self.spv.allocId(); | 2928 | const p_error_id = self.spv.allocId(); |
| | 2929 | switch (target.os.tag) { |
| | 2930 | .opencl => { |
| | 2931 | const kernel_proto_ty_id = try self.functionType(Type.void, &.{ptr_anyerror_ty}); |
| 2920 | | 2932 | |
| 2921 | const section = &self.spv.sections.functions; | 2933 | try section.emit(self.spv.gpa, .OpFunction, .{ |
| 2922 | try section.emit(self.spv.gpa, .OpFunction, .{ | 2934 | .id_result_type = try self.resolveType(Type.void, .direct), |
| 2923 | .id_result_type = try self.resolveType(Type.void, .direct), | 2935 | .id_result = kernel_id, |
| 2924 | .id_result = kernel_id, | 2936 | .function_control = .{}, |
| 2925 | .function_control = .{}, | 2937 | .function_type = kernel_proto_ty_id, |
| 2926 | .function_type = kernel_proto_ty_id, | 2938 | }); |
| 2927 | }); | 2939 | |
| 2928 | try section.emit(self.spv.gpa, .OpFunctionParameter, .{ | 2940 | try section.emit(self.spv.gpa, .OpFunctionParameter, .{ |
| 2929 | .id_result_type = ptr_anyerror_ty_id, | 2941 | .id_result_type = ptr_anyerror_ty_id, |
| 2930 | .id_result = p_error_id, | 2942 | .id_result = p_error_id, |
| 2931 | }); | 2943 | }); |
| 2932 | try section.emit(self.spv.gpa, .OpLabel, .{ | 2944 | |
| 2933 | .id_result = self.spv.allocId(), | 2945 | try section.emit(self.spv.gpa, .OpLabel, .{ |
| 2934 | }); | 2946 | .id_result = self.spv.allocId(), |
| | 2947 | }); |
| | 2948 | }, |
| | 2949 | .vulkan => { |
| | 2950 | const ptr_ptr_anyerror_ty_id = self.spv.allocId(); |
| | 2951 | try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpTypePointer, .{ |
| | 2952 | .id_result = ptr_ptr_anyerror_ty_id, |
| | 2953 | .storage_class = .PushConstant, |
| | 2954 | .type = ptr_anyerror_ty_id, |
| | 2955 | }); |
| | 2956 | |
| | 2957 | if (self.object.error_push_constant == null) { |
| | 2958 | const spv_err_decl_index = try self.spv.allocDecl(.global); |
| | 2959 | try self.spv.declareDeclDeps(spv_err_decl_index, &.{}); |
| | 2960 | |
| | 2961 | const push_constant_struct_ty_id = try self.spv.structType( |
| | 2962 | &.{ptr_anyerror_ty_id}, |
| | 2963 | &.{"error_out_ptr"}, |
| | 2964 | ); |
| | 2965 | try self.spv.decorate(push_constant_struct_ty_id, .Block); |
| | 2966 | try self.spv.decorateMember(push_constant_struct_ty_id, 0, .{ .Offset = .{ .byte_offset = 0 } }); |
| | 2967 | |
| | 2968 | const ptr_push_constant_struct_ty_id = self.spv.allocId(); |
| | 2969 | try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpTypePointer, .{ |
| | 2970 | .id_result = ptr_push_constant_struct_ty_id, |
| | 2971 | .storage_class = .PushConstant, |
| | 2972 | .type = push_constant_struct_ty_id, |
| | 2973 | }); |
| | 2974 | |
| | 2975 | try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpVariable, .{ |
| | 2976 | .id_result_type = ptr_push_constant_struct_ty_id, |
| | 2977 | .id_result = self.spv.declPtr(spv_err_decl_index).result_id, |
| | 2978 | .storage_class = .PushConstant, |
| | 2979 | }); |
| | 2980 | |
| | 2981 | self.object.error_push_constant = .{ |
| | 2982 | .push_constant_ptr = spv_err_decl_index, |
| | 2983 | }; |
| | 2984 | } |
| | 2985 | |
| | 2986 | try self.spv.sections.execution_modes.emit(self.spv.gpa, .OpExecutionMode, .{ |
| | 2987 | .entry_point = kernel_id, |
| | 2988 | .mode = .{ .LocalSize = .{ |
| | 2989 | .x_size = 1, |
| | 2990 | .y_size = 1, |
| | 2991 | .z_size = 1, |
| | 2992 | } }, |
| | 2993 | }); |
| | 2994 | |
| | 2995 | const kernel_proto_ty_id = try self.functionType(Type.void, &.{}); |
| | 2996 | try section.emit(self.spv.gpa, .OpFunction, .{ |
| | 2997 | .id_result_type = try self.resolveType(Type.void, .direct), |
| | 2998 | .id_result = kernel_id, |
| | 2999 | .function_control = .{}, |
| | 3000 | .function_type = kernel_proto_ty_id, |
| | 3001 | }); |
| | 3002 | try section.emit(self.spv.gpa, .OpLabel, .{ |
| | 3003 | .id_result = self.spv.allocId(), |
| | 3004 | }); |
| | 3005 | |
| | 3006 | const spv_err_decl_index = self.object.error_push_constant.?.push_constant_ptr; |
| | 3007 | const push_constant_id = self.spv.declPtr(spv_err_decl_index).result_id; |
| | 3008 | |
| | 3009 | const zero_id = try self.constInt(Type.u32, 0, .direct); |
| | 3010 | // We cannot use OpInBoundsAccessChain to dereference cross-storage class, so we have to use |
| | 3011 | // a load. |
| | 3012 | const tmp = self.spv.allocId(); |
| | 3013 | try section.emit(self.spv.gpa, .OpInBoundsAccessChain, .{ |
| | 3014 | .id_result_type = ptr_ptr_anyerror_ty_id, |
| | 3015 | .id_result = tmp, |
| | 3016 | .base = push_constant_id, |
| | 3017 | .indexes = &.{zero_id}, |
| | 3018 | }); |
| | 3019 | try section.emit(self.spv.gpa, .OpLoad, .{ |
| | 3020 | .id_result_type = ptr_anyerror_ty_id, |
| | 3021 | .id_result = p_error_id, |
| | 3022 | .pointer = tmp, |
| | 3023 | }); |
| | 3024 | }, |
| | 3025 | else => unreachable, |
| | 3026 | } |
| | 3027 | |
| | 3028 | const test_id = self.spv.declPtr(spv_test_decl_index).result_id; |
| | 3029 | const error_id = self.spv.allocId(); |
| 2935 | try section.emit(self.spv.gpa, .OpFunctionCall, .{ | 3030 | try section.emit(self.spv.gpa, .OpFunctionCall, .{ |
| 2936 | .id_result_type = anyerror_ty_id, | 3031 | .id_result_type = anyerror_ty_id, |
| 2937 | .id_result = error_id, | 3032 | .id_result = error_id, |
| ... | @@ -2941,17 +3036,25 @@ const NavGen = struct { | ... | @@ -2941,17 +3036,25 @@ const NavGen = struct { |
| 2941 | try section.emit(self.spv.gpa, .OpStore, .{ | 3036 | try section.emit(self.spv.gpa, .OpStore, .{ |
| 2942 | .pointer = p_error_id, | 3037 | .pointer = p_error_id, |
| 2943 | .object = error_id, | 3038 | .object = error_id, |
| | 3039 | .memory_access = .{ |
| | 3040 | .Aligned = .{ .literal_integer = @sizeOf(u16) }, |
| | 3041 | }, |
| 2944 | }); | 3042 | }); |
| 2945 | try section.emit(self.spv.gpa, .OpReturn, {}); | 3043 | try section.emit(self.spv.gpa, .OpReturn, {}); |
| 2946 | try section.emit(self.spv.gpa, .OpFunctionEnd, {}); | 3044 | try section.emit(self.spv.gpa, .OpFunctionEnd, {}); |
| 2947 | | 3045 | |
| 2948 | try self.spv.declareDeclDeps(spv_decl_index, &.{spv_test_decl_index}); | | |
| 2949 | | | |
| 2950 | // Just generate a quick other name because the intel runtime crashes when the entry- | 3046 | // Just generate a quick other name because the intel runtime crashes when the entry- |
| 2951 | // point name is the same as a different OpName. | 3047 | // point name is the same as a different OpName. |
| 2952 | const test_name = try std.fmt.allocPrint(self.gpa, "test {s}", .{name}); | 3048 | const test_name = try std.fmt.allocPrint(self.gpa, "test {s}", .{name}); |
| 2953 | defer self.gpa.free(test_name); | 3049 | defer self.gpa.free(test_name); |
| 2954 | try self.spv.declareEntryPoint(spv_decl_index, test_name, .Kernel); | 3050 | |
| | 3051 | const execution_mode: spec.ExecutionModel = switch (target.os.tag) { |
| | 3052 | .vulkan => .GLCompute, |
| | 3053 | .opencl => .Kernel, |
| | 3054 | else => unreachable, |
| | 3055 | }; |
| | 3056 | |
| | 3057 | try self.spv.declareEntryPoint(spv_decl_index, test_name, execution_mode); |
| 2955 | } | 3058 | } |
| 2956 | | 3059 | |
| 2957 | fn genNav(self: *NavGen, do_codegen: bool) !void { | 3060 | fn genNav(self: *NavGen, do_codegen: bool) !void { |