| ... | ... | @@ -169,6 +169,13 @@ pub const Object = struct { |
| 169 | 169 | /// via the usual `intern_map` mechanism. |
| 170 | 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 | 179 | pub fn init(gpa: Allocator) Object { |
| 173 | 180 | return .{ |
| 174 | 181 | .gpa = gpa, |
| ... | ... | @@ -2908,30 +2915,118 @@ const NavGen = struct { |
| 2908 | 2915 | .flags = .{ .address_space = .global }, |
| 2909 | 2916 | }); |
| 2910 | 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 | 2919 | const spv_decl_index = try self.spv.allocDecl(.func); |
| 2916 | 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 | 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; |
| 2922 | | try section.emit(self.spv.gpa, .OpFunction, .{ |
| 2923 | | .id_result_type = try self.resolveType(Type.void, .direct), |
| 2924 | | .id_result = kernel_id, |
| 2925 | | .function_control = .{}, |
| 2926 | | .function_type = kernel_proto_ty_id, |
| 2927 | | }); |
| 2928 | | try section.emit(self.spv.gpa, .OpFunctionParameter, .{ |
| 2929 | | .id_result_type = ptr_anyerror_ty_id, |
| 2930 | | .id_result = p_error_id, |
| 2931 | | }); |
| 2932 | | try section.emit(self.spv.gpa, .OpLabel, .{ |
| 2933 | | .id_result = self.spv.allocId(), |
| 2934 | | }); |
| 2933 | try section.emit(self.spv.gpa, .OpFunction, .{ |
| 2934 | .id_result_type = try self.resolveType(Type.void, .direct), |
| 2935 | .id_result = kernel_id, |
| 2936 | .function_control = .{}, |
| 2937 | .function_type = kernel_proto_ty_id, |
| 2938 | }); |
| 2939 | |
| 2940 | try section.emit(self.spv.gpa, .OpFunctionParameter, .{ |
| 2941 | .id_result_type = ptr_anyerror_ty_id, |
| 2942 | .id_result = p_error_id, |
| 2943 | }); |
| 2944 | |
| 2945 | try section.emit(self.spv.gpa, .OpLabel, .{ |
| 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 | 3030 | try section.emit(self.spv.gpa, .OpFunctionCall, .{ |
| 2936 | 3031 | .id_result_type = anyerror_ty_id, |
| 2937 | 3032 | .id_result = error_id, |
| ... | ... | @@ -2941,17 +3036,25 @@ const NavGen = struct { |
| 2941 | 3036 | try section.emit(self.spv.gpa, .OpStore, .{ |
| 2942 | 3037 | .pointer = p_error_id, |
| 2943 | 3038 | .object = error_id, |
| 3039 | .memory_access = .{ |
| 3040 | .Aligned = .{ .literal_integer = @sizeOf(u16) }, |
| 3041 | }, |
| 2944 | 3042 | }); |
| 2945 | 3043 | try section.emit(self.spv.gpa, .OpReturn, {}); |
| 2946 | 3044 | try section.emit(self.spv.gpa, .OpFunctionEnd, {}); |
| 2947 | 3045 | |
| 2948 | | try self.spv.declareDeclDeps(spv_decl_index, &.{spv_test_decl_index}); |
| 2949 | | |
| 2950 | 3046 | // Just generate a quick other name because the intel runtime crashes when the entry- |
| 2951 | 3047 | // point name is the same as a different OpName. |
| 2952 | 3048 | const test_name = try std.fmt.allocPrint(self.gpa, "test {s}", .{name}); |
| 2953 | 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 | 3060 | fn genNav(self: *NavGen, do_codegen: bool) !void { |