| 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,11 +3639,8 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.builtin.CallingConvention) union(enu |
| 3639 | else => false, | 3639 | else => false, |
| 3640 | }, | 3640 | }, |
| 3641 | .stage2_spirv64 => switch (cc) { | 3641 | .stage2_spirv64 => switch (cc) { |
| 3642 | .spirv_device, | 3642 | .spirv_device, .spirv_kernel => true, |
| 3643 | .spirv_kernel, | 3643 | .spirv_fragment, .spirv_vertex => target.os.tag == .vulkan, |
| 3644 | .spirv_fragment, | ||
| 3645 | .spirv_vertex, | ||
| 3646 | => true, | ||
| 3647 | else => false, | 3644 | else => false, |
| 3648 | }, | 3645 | }, |
| 3649 | }; | 3646 | }; |
src/codegen/spirv.zig+13-9| ... | @@ -1640,13 +1640,18 @@ const NavGen = struct { | ... | @@ -1640,13 +1640,18 @@ const NavGen = struct { |
| 1640 | 1640 | ||
| 1641 | comptime assert(zig_call_abi_ver == 3); | 1641 | comptime assert(zig_call_abi_ver == 3); |
| 1642 | switch (fn_info.cc) { | 1642 | switch (fn_info.cc) { |
| 1643 | .auto, .spirv_kernel, .spirv_fragment, .spirv_vertex => {}, | 1643 | .auto, |
| 1644 | else => @panic("TODO"), | 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 | 1652 | // Guaranteed by callConvSupportsVarArgs, there are nog SPIR-V CCs which support |
| 1648 | if (fn_info.is_var_args) | 1653 | // varargs. |
| 1649 | return self.fail("VarArgs functions are unsupported for SPIR-V", .{}); | 1654 | assert(!fn_info.is_var_args); |
| 1650 | 1655 | ||
| 1651 | // Note: Logic is different from functionType(). | 1656 | // Note: Logic is different from functionType(). |
| 1652 | const param_ty_ids = try self.gpa.alloc(IdRef, fn_info.param_types.len); | 1657 | const param_ty_ids = try self.gpa.alloc(IdRef, fn_info.param_types.len); |
| ... | @@ -2969,11 +2974,10 @@ const NavGen = struct { | ... | @@ -2969,11 +2974,10 @@ const NavGen = struct { |
| 2969 | try self.func.prologue.emit(self.spv.gpa, .OpFunction, .{ | 2974 | try self.func.prologue.emit(self.spv.gpa, .OpFunction, .{ |
| 2970 | .id_result_type = return_ty_id, | 2975 | .id_result_type = return_ty_id, |
| 2971 | .id_result = result_id, | 2976 | .id_result = result_id, |
| 2972 | .function_control = switch (fn_info.cc) { | ||
| 2973 | .@"inline" => .{ .Inline = true }, | ||
| 2974 | else => .{}, | ||
| 2975 | }, | ||
| 2976 | .function_type = prototype_ty_id, | 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 | comptime assert(zig_call_abi_ver == 3); | 2983 | comptime assert(zig_call_abi_ver == 3); |
src/link/SpirV.zig+26-19| ... | @@ -161,28 +161,35 @@ pub fn updateExports( | ... | @@ -161,28 +161,35 @@ pub fn updateExports( |
| 161 | }, | 161 | }, |
| 162 | }; | 162 | }; |
| 163 | const nav_ty = ip.getNav(nav_index).typeOf(ip); | 163 | const nav_ty = ip.getNav(nav_index).typeOf(ip); |
| 164 | const target = zcu.getTarget(); | ||
| 164 | if (ip.isFunctionType(nav_ty)) { | 165 | if (ip.isFunctionType(nav_ty)) { |
| 165 | const target = zcu.getTarget(); | ||
| 166 | const spv_decl_index = try self.object.resolveNav(zcu, nav_index); | 166 | const spv_decl_index = try self.object.resolveNav(zcu, nav_index); |
| 167 | const execution_model = switch (Type.fromInterned(nav_ty).fnCallingConvention(zcu)) { | 167 | const cc = Type.fromInterned(nav_ty).fnCallingConvention(zcu); |
| 168 | .spirv_vertex => spec.ExecutionModel.Vertex, | 168 | const execution_model: spec.ExecutionModel = switch (target.os.tag) { |
| 169 | .spirv_fragment => spec.ExecutionModel.Fragment, | 169 | .vulkan => switch (cc) { |
| 170 | .spirv_kernel => spec.ExecutionModel.Kernel, | 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 | else => unreachable, | 183 | else => unreachable, |
| 172 | }; | 184 | }; |
| 173 | const is_vulkan = target.os.tag == .vulkan; | 185 | |
| 174 | 186 | for (export_indices) |export_idx| { | |
| 175 | if ((!is_vulkan and execution_model == .Kernel) or | 187 | const exp = zcu.all_exports.items[export_idx]; |
| 176 | (is_vulkan and (execution_model == .Fragment or execution_model == .Vertex))) | 188 | try self.object.spv.declareEntryPoint( |
| 177 | { | 189 | spv_decl_index, |
| 178 | for (export_indices) |export_idx| { | 190 | exp.opts.name.toSlice(ip), |
| 179 | const exp = zcu.all_exports.items[export_idx]; | 191 | execution_model, |
| 180 | try self.object.spv.declareEntryPoint( | 192 | ); |
| 181 | spv_decl_index, | ||
| 182 | exp.opts.name.toSlice(ip), | ||
| 183 | execution_model, | ||
| 184 | ); | ||
| 185 | } | ||
| 186 | } | 193 | } |
| 187 | } | 194 | } |
| 188 | 195 | ||
| ... | @@ -258,7 +265,7 @@ pub fn flushModule(self: *SpirV, arena: Allocator, tid: Zcu.PerThread.Id, prog_n | ... | @@ -258,7 +265,7 @@ pub fn flushModule(self: *SpirV, arena: Allocator, tid: Zcu.PerThread.Id, prog_n |
| 258 | const linked_module = self.linkModule(arena, module, sub_prog_node) catch |err| switch (err) { | 265 | const linked_module = self.linkModule(arena, module, sub_prog_node) catch |err| switch (err) { |
| 259 | error.OutOfMemory => return error.OutOfMemory, | 266 | error.OutOfMemory => return error.OutOfMemory, |
| 260 | else => |other| { | 267 | else => |other| { |
| 261 | log.err("error while linking: {s}\n", .{@errorName(other)}); | 268 | log.err("error while linking: {s}", .{@errorName(other)}); |
| 262 | return error.FlushFailure; | 269 | return error.FlushFailure; |
| 263 | }, | 270 | }, |
| 264 | }; | 271 | }; |