feat(viz): graph_force_layout_gpu compute + spatial hash (issue 0049h)

Layout force-directed en GPU usando 5 compute shaders 4.3 + spatial hash
grid 64x64. API simetrica con graph_force_layout (CPU) para que el consumer
pueda swappear sin cambios. atomicCompSwap loop para float-add portable.

- cpp/functions/viz/graph_force_layout_gpu.{h,cpp,md}: nuevo modulo
- cpp/functions/gfx/gl_loader: anade glDispatchCompute, glMemoryBarrier,
  glBindBufferBase, glGetBufferSubData (Windows wgl)
- cpp/tests/test_graph_force_layout_gpu.cpp: smoke + pinned + CPU vs GPU.
  Crea ventana GLFW oculta GL 4.3; SKIP si headless o sin compute.
- demos_graph: checkbox "GPU layout" para swappear CPU/GPU en runtime
- issue movido a dev/issues/completed/
This commit is contained in:
2026-04-29 23:29:16 +02:00
parent 982a9f9a2b
commit 35312ea66e
11 changed files with 1096 additions and 2 deletions
+8
View File
@@ -49,6 +49,10 @@ PFNGLFRAMEBUFFERTEXTUREPROC fn_glFramebufferTexture = nullptr;
PFNGLBUFFERSUBDATAPROC fn_glBufferSubData = nullptr;
PFNGLVERTEXATTRIBIPOINTERPROC fn_glVertexAttribIPointer = nullptr;
PFNGLTEXBUFFERPROC fn_glTexBuffer = nullptr;
PFNGLDISPATCHCOMPUTEPROC fn_glDispatchCompute = nullptr;
PFNGLMEMORYBARRIERPROC fn_glMemoryBarrier = nullptr;
PFNGLBINDBUFFERBASEPROC fn_glBindBufferBase = nullptr;
PFNGLGETBUFFERSUBDATAPROC fn_glGetBufferSubData = nullptr;
namespace fn::gfx {
@@ -104,6 +108,10 @@ bool gl_loader_init() {
LOAD(glBufferSubData);
LOAD(glVertexAttribIPointer);
LOAD(glTexBuffer);
LOAD(glDispatchCompute);
LOAD(glMemoryBarrier);
LOAD(glBindBufferBase);
LOAD(glGetBufferSubData);
#undef LOAD
return true;