--- name: gpu_compute_program kind: function lang: cpp domain: gfx version: "1.0.0" purity: impure signature: "ComputeCompileResult compile_compute(const std::string& user_body, int local_size_x, const std::string& preamble); ComputeCompileResult compile_compute_2d(const std::string& user_body, int local_size_x, int local_size_y, const std::string& preamble); void delete_compute_program(unsigned int program)" description: "Compila compute shaders GLSL 4.3 prepending automaticamente #version, layout(local_size_*) y un preamble opcional. Devuelve CompileResult con program GL listo o err_msg/err_line. Pareja para fragments de gl_shader pero para computes." tags: [opengl, compute, shader, glsl, compile, gpu, gfx] uses_functions: ["gl_loader_cpp_gfx"] uses_types: [] returns: [] returns_optional: false error_type: "error_go_core" imports: [GL/gl.h, GL/glext.h, regex] tested: false tests: [] test_file_path: "" file_path: "cpp/functions/gfx/gpu_compute_program.cpp" framework: opengl params: - name: user_body desc: "Cuerpo del compute shader: declaraciones de SSBOs (layout std430 binding=N), uniforms, helpers y void main(). NO debe llevar #version ni layout(local_size_*)." - name: local_size_x desc: "Numero de invocaciones por workgroup en X. Defaults: 64 (1D), 8 (2D)." - name: local_size_y desc: "Variante 2D: invocaciones por workgroup en Y. Default 8." - name: preamble desc: "GLSL opcional inyectado entre layout y user_body. Aqui se inyectan los snippets de gpu_rng_glsl o helpers comunes." output: "ComputeCompileResult con program=GL id si ok=true; si ok=false, err_line apunta al user_body (no al header) y err_msg trae el log completo de glGetShaderInfoLog/glGetProgramInfoLog." --- # gpu_compute_program Mismo patron que `gl_shader::compile_fragment`, especializado para compute shaders 4.3+. ## Estructura del shader resultante ```glsl #version 430 core layout(local_size_x = ) in; // o local_size_x,y para 2D // opcional: rng, helpers // declaraciones + main() ``` El `err_line` se ajusta restando las lineas del header para que apunte al texto que el caller escribio. ## Ejemplo basico ```cpp const char* body = R"glsl( layout(std430, binding = 0) buffer Out { float vals[]; }; uniform uint u_count; void main() { uint i = gl_GlobalInvocationID.x; if (i >= u_count) return; vals[i] = float(i) * 0.5; } )glsl"; auto r = fn::gfx::compile_compute(body, 64); if (!r.ok) { std::fprintf(stderr, "line %d: %s\n", r.err_line, r.err_msg.c_str()); return; } glUseProgram(r.program); ``` ## Con preamble (RNG inyectado) ```cpp auto rng = fn::gfx::glsl_rng_preamble(/*seed_binding=*/9); auto r = fn::gfx::compile_compute(body, 64, rng); ``` El user_body ya puede llamar `rng_uniform(i)`, `rng_normal(i)` etc. — definidas por el preamble. ## Notas - El context GL debe ser current y `gl_loader_init()` ya invocado. - Tras un `delete_compute_program` el id queda invalido para todos los `glUseProgram` posteriores. - Liberar siempre con `delete_compute_program` para evitar leaks (el destructor de C++ no lo hace porque `program` es un `unsigned int`).