actual glsl compilation

○ Planned This feature is planned but not yet implemented.

Feature: GLSL shader compilation

Code

// Test 822: ACTUAL GLSL → SPIR-V Compilation! 🔥
//
// This is IT! We're actually compiling GPU shaders from Koru source!
//
// What this does:
// 1. Extract GLSL from proc body
// 2. Write to temp file
// 3. Run glslangValidator -V shader.glsl -o shader.spv
// 4. Verify SPIR-V binary exists
// 5. Generate Zig wrapper with @embedFile
//
// This proves THE ENTIRE GPU COMPILATION PIPELINE WORKS!

const std = @import("std");

// ================================================================
// GPU Compiler Pass - REAL Implementation!
// ================================================================

~pub event gpu_shader {
    glsl_code: []const u8,
}
| compiled {
    spv_path: []const u8,
    success: bool,
}
| failed {
    msg: []const u8,
}

~proc gpu_shader {
    const allocator = std.heap.page_allocator;

    // Write GLSL to temp file
    const glsl_path = "/tmp/koru_test_shader.glsl";
    const glsl_file = std.fs.createFileAbsolute(glsl_path, .{}) catch |err| {
        return .{ .failed = .{ .msg = @errorName(err) } };
    };
    defer glsl_file.close();
    glsl_file.writeAll(glsl_code) catch |err| {
        return .{ .failed = .{ .msg = @errorName(err) } };
    };

    // Run glslangValidator!
    const spv_path = "/tmp/koru_test_shader.spv";

    var argv = [_][]const u8{
        "glslangValidator",
        "-V",              // Vulkan/SPIR-V output
        "-S", "comp",      // Compute shader
        glsl_path,
        "-o", spv_path,
    };

    var child = std.process.Child.init(&argv, allocator);
    child.stdout_behavior = .Ignore;
    child.stderr_behavior = .Ignore;

    const result = child.spawnAndWait() catch |err| {
        return .{ .failed = .{ .msg = @errorName(err) } };
    };

    const success = switch (result) {
        .Exited => |code| code == 0,
        else => false,
    };

    const spv_path_owned = allocator.dupe(u8, spv_path) catch |err| {
        return .{ .failed = .{ .msg = @errorName(err) } };
    };

    return .{ .compiled = .{
        .spv_path = spv_path_owned,
        .success = success,
    } };
}

// ================================================================
// Test: Compile a simple GLSL shader
// ================================================================

~pub event test_shader_compilation { }
| result { success: bool, spv_path: []const u8 }

~proc test_shader_compilation {
    const glsl =
        \\#version 450
        \\
        \\layout(local_size_x = 1) in;
        \\
        \\layout(binding = 0) buffer Data {
        \\    float values[];
        \\} data;
        \\
        \\void main() {
        \\    uint idx = gl_GlobalInvocationID.x;
        \\    data.values[idx] = data.values[idx] * 2.0;
        \\}
    ;

    // COMPILE IT! This will actually run glslangValidator!
    const compile_result = ~gpu_shader(glsl_code: glsl)
    | compiled c |> result { success: c.success, spv_path: c.spv_path }
    | failed e |> result { success: false, spv_path: msg };

    return compile_result;
}

// Validation event - verify compilation succeeded
~pub event validate_compilation { success: bool, spv_path: []const u8 }

~proc validate_compilation {
    if (success) {
        // Verify SPIR-V file exists and has content
        const file = std.fs.openFileAbsolute(spv_path, .{}) catch |err| {
            std.debug.print("❌ SPIR-V file not found: {s}\n", .{@errorName(err)});
            std.process.exit(1);
        };
        defer file.close();

        const file_size = (file.stat() catch unreachable).size;
        std.debug.print("✅ GPU shader compiled successfully!\n", .{});
        std.debug.print("   SPIR-V binary: {s} ({d} bytes)\n", .{spv_path, file_size});
    } else {
        std.debug.print("❌ GPU shader compilation failed\n", .{});
        std.debug.print("   Error: {s}\n", .{spv_path}); // spv_path contains error msg on failure
        std.process.exit(1);
    }
}

// Actually run the test!
~test_shader_compilation()
| result r |> validate_compilation(success: r.success, spv_path: r.spv_path)
input.kz

Imported Files

~import test = "input.kz"

~test.test_shader_compilation()
run_test.kz