#pragma once #include "gfx/gpu_ssbo.h" #include namespace fn::gfx { // Binner 2D. nx*ny bins; SSBO interno uint[nx*ny] row-major (idx = y*nx + x). struct GpuHistogram2D { unsigned int program = 0; unsigned int loc_count = 0; unsigned int loc_nx = 0; unsigned int loc_ny = 0; unsigned int loc_min = 0; unsigned int loc_inv_range = 0; Ssbo bins; int nx = 0; int ny = 0; }; GpuHistogram2D gpu_histogram_2d_create(int nx, int ny); void gpu_histogram_2d_clear(GpuHistogram2D& h); // Acumula un SSBO vec2[count] (interpretado como float pares) en bins 2D. // Samples es un Ssbo float[2*count] (xy interleaved). xmin/xmax/ymin/ymax // definen el rango; samples fuera se descartan. // // Tras esta llamada se requiere barrier_storage()/barrier_buffer_update() // segun lo que vaya despues. void gpu_histogram_2d_accumulate(GpuHistogram2D& h, const Ssbo& samples_xy, int count, float xmin, float xmax, float ymin, float ymax); // Lee bins a CPU. out debe tener al menos nx*ny enteros. void gpu_histogram_2d_readback(const GpuHistogram2D& h, unsigned int* out); // Convertir uint[nx*ny] a float[nx*ny] normalizado (max=1.0). Helper CPU // para alimentar heatmap_cpp_viz / contour_cpp_viz que esperan z[]. void gpu_histogram_2d_to_density(const unsigned int* counts, int nx, int ny, float* out_density); void gpu_histogram_2d_destroy(GpuHistogram2D& h); } // namespace fn::gfx