/*
* opencog/persist/gpu/GpuAtomTable_dispatch.cc
*
* Runtime dispatch for GpuAtomTable: tries CUDA first, falls
* back to OpenCL. All public gpu_* functions route through here.
*
* Copyright (C) 2026 OpenCog Foundation
*
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
#include "GpuAtomTable.h"
#include <cstdio>
#include <cstring>
/* ================================================================
* gpu_table_alloc -- try CUDA, fall back to OpenCL.
* ================================================================ */
extern "C"
int gpu_table_alloc(GpuAtomTable* t)
{
memset(t, 0, sizeof(GpuAtomTable));
t->backend = GPU_BACKEND_NONE;
#ifdef HAVE_CUDA
if (cuda_table_alloc(t) == 0)
{
t->backend = GPU_BACKEND_CUDA;
fprintf(stderr, "GpuAtomTable: using CUDA backend\n");
return 0;
}
fprintf(stderr, "GpuAtomTable: CUDA failed, trying OpenCL...\n");
#endif
#ifdef HAVE_OPENCL
if (ocl_table_alloc(t) == 0)
{
t->backend = GPU_BACKEND_OPENCL;
fprintf(stderr, "GpuAtomTable: using OpenCL backend\n");
return 0;
}
fprintf(stderr, "GpuAtomTable: OpenCL failed\n");
#endif
fprintf(stderr, "GpuAtomTable: no GPU backend available\n");
return -1;
}
/* ================================================================
* gpu_table_free
* ================================================================ */
extern "C"
void gpu_table_free(GpuAtomTable* t)
{
switch (t->backend)
{
#ifdef HAVE_CUDA
case GPU_BACKEND_CUDA: cuda_table_free(t); break;
#endif
#ifdef HAVE_OPENCL
case GPU_BACKEND_OPENCL: ocl_table_free(t); break;
#endif
default: break;
}
t->backend = GPU_BACKEND_NONE;
}
/* ================================================================
* gpu_table_clear
* ================================================================ */
extern "C"
void gpu_table_clear(GpuAtomTable* t)
{
switch (t->backend)
{
#ifdef HAVE_CUDA
case GPU_BACKEND_CUDA: cuda_table_clear(t); break;
#endif
#ifdef HAVE_OPENCL
case GPU_BACKEND_OPENCL: ocl_table_clear(t); break;
#endif
default: break;
}
}
/* ================================================================
* gpu_store_node
* ================================================================ */
extern "C"
int gpu_store_node(GpuAtomTable* t, uint32_t slot,
uint16_t type, const char* name, uint16_t name_len)
{
switch (t->backend)
{
#ifdef HAVE_CUDA
case GPU_BACKEND_CUDA:
return cuda_store_node(t, slot, type, name, name_len);
#endif
#ifdef HAVE_OPENCL
case GPU_BACKEND_OPENCL:
return ocl_store_node(t, slot, type, name, name_len);
#endif
default: return -1;
}
}
/* ================================================================
* gpu_store_link
* ================================================================ */
extern "C"
int gpu_store_link(GpuAtomTable* t, uint32_t slot,
uint16_t type,
const uint32_t* outgoing, uint16_t arity)
{
switch (t->backend)
{
#ifdef HAVE_CUDA
case GPU_BACKEND_CUDA:
return cuda_store_link(t, slot, type, outgoing, arity);
#endif
#ifdef HAVE_OPENCL
case GPU_BACKEND_OPENCL:
return ocl_store_link(t, slot, type, outgoing, arity);
#endif
default: return -1;
}
}
/* ================================================================
* gpu_fetch_node
* ================================================================ */
extern "C"
int gpu_fetch_node(const GpuAtomTable* t, uint32_t slot,
uint16_t* type, char* name_buf, uint16_t* name_len)
{
switch (t->backend)
{
#ifdef HAVE_CUDA
case GPU_BACKEND_CUDA:
return cuda_fetch_node(t, slot, type, name_buf, name_len);
#endif
#ifdef HAVE_OPENCL
case GPU_BACKEND_OPENCL:
return ocl_fetch_node(t, slot, type, name_buf, name_len);
#endif
default: return -1;
}
}
/* ================================================================
* gpu_fetch_link
* ================================================================ */
extern "C"
int gpu_fetch_link(const GpuAtomTable* t, uint32_t slot,
uint16_t* type, uint32_t* out_buf, uint16_t* arity)
{
switch (t->backend)
{
#ifdef HAVE_CUDA
case GPU_BACKEND_CUDA:
return cuda_fetch_link(t, slot, type, out_buf, arity);
#endif
#ifdef HAVE_OPENCL
case GPU_BACKEND_OPENCL:
return ocl_fetch_link(t, slot, type, out_buf, arity);
#endif
default: return -1;
}
}
/* ================================================================
* gpu_table_barrier
* ================================================================ */
extern "C"
void gpu_table_barrier(GpuAtomTable* t)
{
switch (t->backend)
{
#ifdef HAVE_CUDA
case GPU_BACKEND_CUDA: cuda_table_barrier(t); break;
#endif
#ifdef HAVE_OPENCL
case GPU_BACKEND_OPENCL: ocl_table_barrier(t); break;
#endif
default: break;
}
}
/* ================================================================
* gpu_table_build_incoming
* ================================================================ */
extern "C"
int gpu_table_build_incoming(GpuAtomTable* t)
{
switch (t->backend)
{
#ifdef HAVE_CUDA
case GPU_BACKEND_CUDA: return cuda_table_build_incoming(t);
#endif
#ifdef HAVE_OPENCL
case GPU_BACKEND_OPENCL: return ocl_table_build_incoming(t);
#endif
default: return -1;
}
}
/* ================================================================
* gpu_fetch_incoming
* ================================================================ */
extern "C"
int gpu_fetch_incoming(const GpuAtomTable* t, uint32_t slot,
uint32_t* buf, uint32_t max, uint32_t* count)
{
switch (t->backend)
{
#ifdef HAVE_CUDA
case GPU_BACKEND_CUDA: return cuda_fetch_incoming(t, slot, buf, max, count);
#endif
#ifdef HAVE_OPENCL
case GPU_BACKEND_OPENCL: return ocl_fetch_incoming(t, slot, buf, max, count);
#endif
default: return -1;
}
}
/* ================================================================
* gpu_intersect_incoming
* ================================================================ */
extern "C"
int gpu_intersect_incoming(const GpuAtomTable* t, uint32_t a, uint32_t b,
uint32_t* out, uint32_t max, uint32_t* count)
{
switch (t->backend)
{
#ifdef HAVE_CUDA
case GPU_BACKEND_CUDA: return cuda_intersect_incoming(t, a, b, out, max, count);
#endif
#ifdef HAVE_OPENCL
case GPU_BACKEND_OPENCL: return ocl_intersect_incoming(t, a, b, out, max, count);
#endif
default: return -1;
}
}