renderer: spirv binary must be aligned to u32

This commit is contained in:
Mitchell Hashimoto
2023-11-16 21:03:32 -08:00
parent 4742cd308d
commit 76a88e3fbe

View File

@ -64,7 +64,9 @@ pub fn loadFromFile(
// Convert to SPIR-V
const spirv: []const u8 = spirv: {
var list = std.ArrayList(u8).init(alloc);
// SpirV pointer must be aligned to 4 bytes since we expect
// a slice of words.
var list = std.ArrayListAligned(u8, @alignOf(u32)).init(alloc);
var errlog: SpirvLog = .{ .alloc = alloc };
defer errlog.deinit();
spirvFromGlsl(list.writer(), &errlog, glsl) catch |err| {
@ -190,6 +192,31 @@ pub const SpirvLog = struct {
/// Convert SPIR-V binary to MSL.
pub fn mslFromSpv(alloc: Allocator, spv: []const u8) ![:0]const u8 {
return try spvCross(alloc, spvcross.c.SPVC_BACKEND_MSL, spv, null);
}
/// Convert SPIR-V binary to GLSL..
pub fn glslFromSpv(alloc: Allocator, spv: []const u8) ![:0]const u8 {
const c = spvcross.c;
return try spvCross(alloc, c.SPVC_BACKEND_GLSL, spv, (struct {
fn setOptions(options: c.spvc_compiler_options) error{SpvcFailed}!void {
if (c.spvc_compiler_options_set_uint(
options,
c.SPVC_COMPILER_OPTION_GLSL_VERSION,
330,
) != c.SPVC_SUCCESS) {
return error.SpvcFailed;
}
}
}).setOptions);
}
fn spvCross(
alloc: Allocator,
backend: spvcross.c.spvc_backend,
spv: []const u8,
comptime optionsFn_: ?*const fn (c: spvcross.c.spvc_compiler_options) error{SpvcFailed}!void,
) ![:0]const u8 {
// Spir-V is always a multiple of 4 because it is written as a series of words
if (@mod(spv.len, 4) != 0) return error.SpirvInvalid;
@ -219,11 +246,11 @@ pub fn mslFromSpv(alloc: Allocator, spv: []const u8) ![:0]const u8 {
return error.SpvcFailed;
}
// Build our compiler to MSL
// Build our compiler to GLSL
var compiler: c.spvc_compiler = undefined;
if (c.spvc_context_create_compiler(
ctx,
c.SPVC_BACKEND_MSL,
backend,
ir,
c.SPVC_CAPTURE_MODE_TAKE_OWNERSHIP,
&compiler,
@ -231,6 +258,20 @@ pub fn mslFromSpv(alloc: Allocator, spv: []const u8) ![:0]const u8 {
return error.SpvcFailed;
}
// Setup our options if we have any
if (optionsFn_) |optionsFn| {
var options: c.spvc_compiler_options = undefined;
if (c.spvc_compiler_create_compiler_options(compiler, &options) != c.SPVC_SUCCESS) {
return error.SpvcFailed;
}
try optionsFn(options);
if (c.spvc_compiler_install_compiler_options(compiler, options) != c.SPVC_SUCCESS) {
return error.SpvcFailed;
}
}
// Compile the resulting string. This string pointer is owned by the
// context so we don't need to free it.
var result: [*:0]const u8 = undefined;
@ -286,7 +327,7 @@ test "shadertoy to msl" {
const src = try testGlslZ(alloc, test_crt);
defer alloc.free(src);
var spvlist = std.ArrayList(u8).init(alloc);
var spvlist = std.ArrayListAligned(u8, @alignOf(u32)).init(alloc);
defer spvlist.deinit();
try spirvFromGlsl(spvlist.writer(), null, src);