#pragma once

namespace fn::gfx {

// Despacha un compute con num_invocations hilos totales (1D), agrupados en
// workgroups de tamano local_size_x. Calcula ceil(num/local). El programa
// debe estar activo (glUseProgram llamado antes) y los SSBOs ya bindeados.
//
// Ejemplo: dispatch_1d(N, 64) emite glDispatchCompute((N+63)/64, 1, 1).
void dispatch_1d(int num_invocations, int local_size_x = 64);

// Variante 2D para grids tipo (width, height) — heatmaps, samples_to_grid_2d,
// histogram_2d. Local 8x8 = 64 invocaciones por workgroup.
void dispatch_2d(int width, int height,
                 int local_size_x = 8, int local_size_y = 8);

// Variante 3D (poco usada — expuesta por completitud).
void dispatch_3d(int x, int y, int z,
                 int local_size_x = 4, int local_size_y = 4, int local_size_z = 4);

// Helpers de glMemoryBarrier para los casos comunes despues de un dispatch.
// barrier_storage: el siguiente compute leera SSBOs escritos en este pase.
void barrier_storage();
// barrier_uniform: cambios subsiguientes a uniforms se ven correctamente.
void barrier_uniform();
// barrier_image: image2D writes -> reads (si se usan imageStore en compute).
void barrier_image();
// barrier_buffer_update: glGetBufferSubData / glBufferSubData veran lo escrito
// por el compute. Necesario antes de readback a CPU.
void barrier_buffer_update();
// barrier_all: GL_ALL_BARRIER_BITS — usar en debug; conservador y caro.
void barrier_all();

} // namespace fn::gfx
