lib/choir/src/backends/gpu/spirv/emitter/plan.zig
daab053ee43316e1809a84551d573ddd1e5bf3d2
1 const std = @import("std");
2 const abi = @import("choir_abi");
3 const choir = @import("../../../../root.zig");
4
5 const codegen = @import("codegen.zig");
6
7 const ir = choir.ir;
8
9 /// SPIR-V words for one module, and the push-constant layout the emitter gave
10 /// the requested entry.
11 pub const Emission = struct {
12 words: []u32,
13 push_constants: abi.PushConstants,
14 };
15
16 /// Emits `module` and returns the layout of `entry_name`'s push-constant
17 /// block. A hand-written `spirv.module` declares no block, so its layout is
18 /// empty. `controls` contains only float modes the selected device reports.
19 pub fn emitPlanWords(
20 result_allocator: std.mem.Allocator,
21 module: *ir.Operation,
22 entry_name: []const u8,
23 limits: abi.Limits,
24 controls: codegen.FloatControls,
25 ) abi.Error!Emission {
26 std.debug.assert(entry_name.len > 0);
27 std.debug.assert(limits.valid());
28 var emitter = codegen.SpirvCodegen.init(result_allocator);
29 defer emitter.deinit();
30 emitter.limits = limits;
31 emitter.entry_name = entry_name;
32 emitter.float_controls = controls;
33 const words = emitter.emitModuleWords(module) catch |err| return mapCodegenError(err);
34 return .{ .words = words, .push_constants = emitter.entry_push_constants orelse .{} };
35 }
36
37 fn mapCodegenError(err: codegen.SpirvCodegenError) abi.Error {
38 return switch (err) {
39 error.OutOfMemory => error.OutOfMemory,
40 error.UnsupportedOperation, error.UnsupportedStageMemory, error.UnsupportedHelperSignature => error.UnsupportedOperation,
41 error.UnsupportedFunctionSignature,
42 error.UnsupportedType,
43 error.UnsupportedMask,
44 error.UnsupportedAddressSpace,
45 error.UnsupportedControlFlow,
46 => error.CapabilityMismatch,
47 else => error.InvalidArtifact,
48 };
49 }
50
51 test {
52 std.testing.refAllDecls(@This());
53 }