| author | |
| committer | |
| log | 6de456c179d81b9118ecd26eb9d7c90213bac313 |
| tree | 1dda74e9dad818e8d00d03438b3bf636470011c6 |
| parent | 9b42bc1ce5a1d688aa2167a068a3b75d69888c12 |
| signature |
* Fragment and Vertex CCs are only valid for SPIR-V when
running under Vulkan.
* Emit GLCompute instead of Kernel for SPIR-V kernels.3 files changed, 41 insertions(+), 33 deletions(-)
src/Zcu.zig+2-5| ... | ... | @@ -3639,11 +3639,8 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.builtin.CallingConvention) union(enu |
| 3639 | 3639 | else => false, |
| 3640 | 3640 | }, |
| 3641 | 3641 | .stage2_spirv64 => switch (cc) { |
| 3642 | .spirv_device, | |
| 3643 | .spirv_kernel, | |
| 3644 | .spirv_fragment, | |
| 3645 | .spirv_vertex, | |
| 3646 | => true, | |
| 3642 | .spirv_device, .spirv_kernel => true, | |
| 3643 | .spirv_fragment, .spirv_vertex => target.os.tag == .vulkan, | |
| 3647 | 3644 | else => false, |
| 3648 | 3645 | }, |
| 3649 | 3646 | }; |
src/codegen/spirv.zig+13-9| ... | ... | @@ -1640,13 +1640,18 @@ const NavGen = struct { |
| 1640 | 1640 | |
| 1641 | 1641 | comptime assert(zig_call_abi_ver == 3); |
| 1642 | 1642 | switch (fn_info.cc) { |
| 1643 | .auto, .spirv_kernel, .spirv_fragment, .spirv_vertex => {}, | |
| 1644 | else => @panic("TODO"), | |
| 1643 | .auto, | |
| 1644 | .spirv_kernel, | |
| 1645 | .spirv_fragment, | |
| 1646 | .spirv_vertex, | |
| 1647 | .spirv_device, | |
| 1648 | => {}, | |
| 1649 | else => unreachable, | |
| 1645 | 1650 | } |
| 1646 | 1651 | |
| 1647 | // TODO: Put this somewhere in Sema.zig | |
| 1648 | if (fn_info.is_var_args) | |
| 1649 | return self.fail("VarArgs functions are unsupported for SPIR-V", .{}); | |
| 1652 | // Guaranteed by callConvSupportsVarArgs, there are nog SPIR-V CCs which support | |
| 1653 | // varargs. | |
| 1654 | assert(!fn_info.is_var_args); | |
| 1650 | 1655 | |
| 1651 | 1656 | // Note: Logic is different from functionType(). |
| 1652 | 1657 | const param_ty_ids = try self.gpa.alloc(IdRef, fn_info.param_types.len); |
| ... | ... | @@ -2969,11 +2974,10 @@ const NavGen = struct { |
| 2969 | 2974 | try self.func.prologue.emit(self.spv.gpa, .OpFunction, .{ |
| 2970 | 2975 | .id_result_type = return_ty_id, |
| 2971 | 2976 | .id_result = result_id, |
| 2972 | .function_control = switch (fn_info.cc) { | |
| 2973 | .@"inline" => .{ .Inline = true }, | |
| 2974 | else => .{}, | |
| 2975 | }, | |
| 2976 | 2977 | .function_type = prototype_ty_id, |
| 2978 | // Note: the backend will never be asked to generate an inline function | |
| 2979 | // (this is handled in sema), so we don't need to set function_control here. | |
| 2980 | .function_control = .{}, | |
| 2977 | 2981 | }); |
| 2978 | 2982 | |
| 2979 | 2983 | comptime assert(zig_call_abi_ver == 3); |
src/link/SpirV.zig+26-19| ... | ... | @@ -161,28 +161,35 @@ pub fn updateExports( |
| 161 | 161 | }, |
| 162 | 162 | }; |
| 163 | 163 | const nav_ty = ip.getNav(nav_index).typeOf(ip); |
| 164 | const target = zcu.getTarget(); | |
| 164 | 165 | if (ip.isFunctionType(nav_ty)) { |
| 165 | const target = zcu.getTarget(); | |
| 166 | 166 | const spv_decl_index = try self.object.resolveNav(zcu, nav_index); |
| 167 | const execution_model = switch (Type.fromInterned(nav_ty).fnCallingConvention(zcu)) { | |
| 168 | .spirv_vertex => spec.ExecutionModel.Vertex, | |
| 169 | .spirv_fragment => spec.ExecutionModel.Fragment, | |
| 170 | .spirv_kernel => spec.ExecutionModel.Kernel, | |
| 167 | const cc = Type.fromInterned(nav_ty).fnCallingConvention(zcu); | |
| 168 | const execution_model: spec.ExecutionModel = switch (target.os.tag) { | |
| 169 | .vulkan => switch (cc) { | |
| 170 | .spirv_vertex => .Vertex, | |
| 171 | .spirv_fragment => .Fragment, | |
| 172 | .spirv_kernel => .GLCompute, | |
| 173 | // TODO: We should integrate with the Linkage capability and export this function | |
| 174 | .spirv_device => return, | |
| 175 | else => unreachable, | |
| 176 | }, | |
| 177 | .opencl => switch (cc) { | |
| 178 | .spirv_kernel => .Kernel, | |
| 179 | // TODO: We should integrate with the Linkage capability and export this function | |
| 180 | .spirv_device => return, | |
| 181 | else => unreachable, | |
| 182 | }, | |
| 171 | 183 | else => unreachable, |
| 172 | 184 | }; |
| 173 | const is_vulkan = target.os.tag == .vulkan; | |
| 174 | ||
| 175 | if ((!is_vulkan and execution_model == .Kernel) or | |
| 176 | (is_vulkan and (execution_model == .Fragment or execution_model == .Vertex))) | |
| 177 | { | |
| 178 | for (export_indices) |export_idx| { | |
| 179 | const exp = zcu.all_exports.items[export_idx]; | |
| 180 | try self.object.spv.declareEntryPoint( | |
| 181 | spv_decl_index, | |
| 182 | exp.opts.name.toSlice(ip), | |
| 183 | execution_model, | |
| 184 | ); | |
| 185 | } | |
| 185 | ||
| 186 | for (export_indices) |export_idx| { | |
| 187 | const exp = zcu.all_exports.items[export_idx]; | |
| 188 | try self.object.spv.declareEntryPoint( | |
| 189 | spv_decl_index, | |
| 190 | exp.opts.name.toSlice(ip), | |
| 191 | execution_model, | |
| 192 | ); | |
| 186 | 193 | } |
| 187 | 194 | } |
| 188 | 195 | |
| ... | ... | @@ -258,7 +265,7 @@ pub fn flushModule(self: *SpirV, arena: Allocator, tid: Zcu.PerThread.Id, prog_n |
| 258 | 265 | const linked_module = self.linkModule(arena, module, sub_prog_node) catch |err| switch (err) { |
| 259 | 266 | error.OutOfMemory => return error.OutOfMemory, |
| 260 | 267 | else => |other| { |
| 261 | log.err("error while linking: {s}\n", .{@errorName(other)}); | |
| 268 | log.err("error while linking: {s}", .{@errorName(other)}); | |
| 262 | 269 | return error.FlushFailure; |
| 263 | 270 | }, |
| 264 | 271 | }; |