c74fd4ae0d
Stack base de compute shaders OpenGL 4.3 para cargas Monte Carlo intensivas en GPU. Reutiliza el patron de graph_force_layout_gpu (SSBO + compute) y se integra con el resto del registry sin nuevos simbolos en gl_loader (todo lo que se necesita ya estaba expuesto). - gpu_ssbo: lifecycle de Shader Storage Buffer Objects. - gpu_compute_program: compila compute GLSL 4.3 con preamble inyectable (mismo pattern de gl_shader::compile_fragment). - gpu_dispatch: dispatch_1d/2d/3d con ceil(N/local) automatico + barrier helpers (storage, uniform, image, buffer_update, all). - gpu_rng_glsl: PCG32 GLSL (uniform/normal/below) + SplitMix64 seed walkers para sembrar deterministicamente N walkers desde un master seed. - gpu_histogram_1d: SSBO float[N] -> uint[nbins] via atomicAdd. - gpu_histogram_2d: SSBO float[2N] xy-interleaved -> uint[nx*ny] + to_density helper para alimentar heatmap_cpp_viz. - gpu_reduce: workgroup-shared sum/min/max/mean (local 256, partials CPU). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
105 lines
3.3 KiB
C++
105 lines
3.3 KiB
C++
#include "gfx/gl_loader.h"
|
|
#include "gfx/gpu_compute_program.h"
|
|
|
|
#include <cstdio>
|
|
#include <regex>
|
|
#include <string>
|
|
|
|
namespace fn::gfx {
|
|
|
|
static int parse_err_line(const char* log) {
|
|
std::regex re1(R"(ERROR:\s*\d+:(\d+):)");
|
|
std::regex re2(R"(\d+\((\d+)\))");
|
|
std::cmatch m;
|
|
if (std::regex_search(log, m, re1)) return std::stoi(m[1].str());
|
|
if (std::regex_search(log, m, re2)) return std::stoi(m[1].str());
|
|
return -1;
|
|
}
|
|
|
|
static int count_lines(const std::string& s) {
|
|
int n = 0;
|
|
for (char c : s) if (c == '\n') ++n;
|
|
return n;
|
|
}
|
|
|
|
static ComputeCompileResult compile_with_layout(const std::string& layout_line,
|
|
const std::string& user_body,
|
|
const std::string& preamble) {
|
|
ComputeCompileResult r;
|
|
|
|
// Header fijo. count = lineas que sumamos antes del user_body, para
|
|
// restar al err_line del log.
|
|
std::string header = "#version 430 core\n";
|
|
header += layout_line;
|
|
if (!preamble.empty()) {
|
|
header += preamble;
|
|
if (preamble.back() != '\n') header += '\n';
|
|
}
|
|
int header_lines = count_lines(header);
|
|
|
|
const char* srcs[2] = { header.c_str(), user_body.c_str() };
|
|
|
|
GLuint sh = glCreateShader(GL_COMPUTE_SHADER);
|
|
glShaderSource(sh, 2, srcs, nullptr);
|
|
glCompileShader(sh);
|
|
|
|
GLint ok = 0;
|
|
glGetShaderiv(sh, GL_COMPILE_STATUS, &ok);
|
|
if (!ok) {
|
|
GLint len = 0;
|
|
glGetShaderiv(sh, GL_INFO_LOG_LENGTH, &len);
|
|
r.err_msg.resize(static_cast<std::size_t>(len));
|
|
if (len > 0) glGetShaderInfoLog(sh, len, nullptr, &r.err_msg[0]);
|
|
int line = parse_err_line(r.err_msg.c_str());
|
|
r.err_line = (line > header_lines) ? (line - header_lines) : line;
|
|
glDeleteShader(sh);
|
|
return r;
|
|
}
|
|
|
|
GLuint prog = glCreateProgram();
|
|
glAttachShader(prog, sh);
|
|
glLinkProgram(prog);
|
|
glDeleteShader(sh);
|
|
|
|
glGetProgramiv(prog, GL_LINK_STATUS, &ok);
|
|
if (!ok) {
|
|
GLint len = 0;
|
|
glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &len);
|
|
r.err_msg.resize(static_cast<std::size_t>(len));
|
|
if (len > 0) glGetProgramInfoLog(prog, len, nullptr, &r.err_msg[0]);
|
|
r.err_line = parse_err_line(r.err_msg.c_str());
|
|
glDeleteProgram(prog);
|
|
return r;
|
|
}
|
|
|
|
r.program = prog;
|
|
r.ok = true;
|
|
return r;
|
|
}
|
|
|
|
ComputeCompileResult compile_compute(const std::string& user_body,
|
|
int local_size_x,
|
|
const std::string& preamble) {
|
|
char buf[64];
|
|
std::snprintf(buf, sizeof(buf),
|
|
"layout(local_size_x = %d) in;\n", local_size_x);
|
|
return compile_with_layout(buf, user_body, preamble);
|
|
}
|
|
|
|
ComputeCompileResult compile_compute_2d(const std::string& user_body,
|
|
int local_size_x,
|
|
int local_size_y,
|
|
const std::string& preamble) {
|
|
char buf[96];
|
|
std::snprintf(buf, sizeof(buf),
|
|
"layout(local_size_x = %d, local_size_y = %d) in;\n",
|
|
local_size_x, local_size_y);
|
|
return compile_with_layout(buf, user_body, preamble);
|
|
}
|
|
|
|
void delete_compute_program(unsigned int program) {
|
|
if (program) glDeleteProgram(program);
|
|
}
|
|
|
|
} // namespace fn::gfx
|