#pragma once

#include <string>

namespace fn::gfx {

struct ComputeCompileResult {
    unsigned int program = 0;   // GL program id, 0 si falla
    bool ok = false;
    int err_line = -1;          // linea en user_body, -1 si no parseable
    std::string err_msg;        // log completo de GL para debug
};

// Compila un compute shader GLSL 4.3. Prepende automaticamente:
//   #version 430 core
//   layout(local_size_x = <local_size_x>) in;
//   <preamble>
//   <user_body>
//
// El user_body NO debe llevar #version ni layout(local_size_x). Si lleva,
// la compilacion fallara con redefinicion. Lo unico obligatorio es void main().
//
// preamble es opcional: aqui se inyectan helpers GLSL (RNG de gpu_rng_glsl,
// declaraciones de SSBOs std430, uniforms compartidos, etc).
//
// Si falla, program = 0 y err_msg / err_line describen el problema. El
// err_line se ajusta restando las lineas del prefijo (#version + layout +
// preamble) para mapear al user_body que el caller escribio.
ComputeCompileResult compile_compute(const std::string& user_body,
                                     int local_size_x = 64,
                                     const std::string& preamble = "");

// Variante 2D: emite layout(local_size_x = lx, local_size_y = ly).
ComputeCompileResult compile_compute_2d(const std::string& user_body,
                                        int local_size_x = 8,
                                        int local_size_y = 8,
                                        const std::string& preamble = "");

// Libera el programa. Seguro con id == 0.
void delete_compute_program(unsigned int program);

} // namespace fn::gfx
