host.c --serve --pack <dir> serves a pack read at run time (packfile.h), whatever pack the exe was built against: the first pair is built and self-tested like a prepared one (pairBuffers, pairSelfTest), prepared pairs are self-tested too, the ready line says path prebuilt-generic. cl_dynamic.h (IGNEUM_CL_DYNAMIC) opens OpenCL.dll with LoadLibrary and fills a function pointer per entry point, so the mingw build links no import library. test-generic.sh checks the mode through Apple OpenCL with the packs of the CUDA emulation test: PASS (192 found, prepare and swap, 15 sampled hashes equal igneum-pow hash-bound), built against a different placeholder pack than it served. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
78 lines
3.7 KiB
C
78 lines
3.7 KiB
C
/* cl_dynamic.h: OpenCL.dll loaded at run time (Windows). 4 October 2026.
|
|
*
|
|
* The one-click AMD worker (host.c cross-compiled with mingw, build-windows.sh) links no OpenCL import library:
|
|
* every cl* entry point host.c calls is a function pointer filled from OpenCL.dll with LoadLibrary/GetProcAddress.
|
|
* OpenCL.dll is the Khronos ICD loader that the AMD Adrenalin (and NVIDIA, Intel) driver installs in System32, so
|
|
* nothing but the driver is needed on the PC. Included by host.c after <CL/cl.h> when IGNEUM_CL_DYNAMIC is defined;
|
|
* the macros below then rename the calls in the rest of the file. The Mac and Linux builds link the library as before.
|
|
*/
|
|
#ifndef IGNEUM_CL_DYNAMIC_H
|
|
#define IGNEUM_CL_DYNAMIC_H
|
|
#ifdef _WIN32
|
|
#define WIN32_LEAN_AND_MEAN
|
|
#include <windows.h>
|
|
#endif
|
|
#include <stdio.h>
|
|
|
|
#define IG_CL_FUNCS(X) \
|
|
X(clGetPlatformIDs) X(clGetPlatformInfo) X(clGetDeviceIDs) X(clGetDeviceInfo) X(clCreateContext) \
|
|
X(clCreateCommandQueue) X(clCreateProgramWithSource) X(clBuildProgram) X(clGetProgramBuildInfo) X(clCreateKernel) \
|
|
X(clSetKernelArg) X(clEnqueueNDRangeKernel) X(clEnqueueReadBuffer) X(clEnqueueWriteBuffer) X(clCreateBuffer) \
|
|
X(clReleaseMemObject) X(clReleaseKernel) X(clReleaseProgram) X(clReleaseCommandQueue) X(clReleaseContext) \
|
|
X(clFinish) X(clWaitForEvents) X(clReleaseEvent) X(clGetEventProfilingInfo) X(clGetKernelWorkGroupInfo) \
|
|
X(clGetExtensionFunctionAddressForPlatform)
|
|
|
|
/* One pointer per entry point, typed from the header's declaration (so a signature drift is a compile error). */
|
|
#define IG_CL_DECL(f) static __typeof__(f)* ig_##f = NULL;
|
|
IG_CL_FUNCS(IG_CL_DECL)
|
|
#undef IG_CL_DECL
|
|
|
|
static char ig_cl_error[512];
|
|
|
|
/* Returns 1 when OpenCL.dll and every entry point are there; else 0 with ig_cl_error set. */
|
|
static int ig_cl_load(void) {
|
|
#ifdef _WIN32
|
|
HMODULE h = LoadLibraryA("OpenCL.dll");
|
|
if (!h) {
|
|
snprintf(ig_cl_error, sizeof(ig_cl_error), "OpenCL.dll is not installed (the GPU driver provides it: AMD Adrenalin, or the NVIDIA or Intel driver); nothing else is needed");
|
|
return 0;
|
|
}
|
|
#define IG_CL_LOAD(f) ig_##f = (__typeof__(f)*)(void*)GetProcAddress(h, #f); if (!ig_##f) { snprintf(ig_cl_error, sizeof(ig_cl_error), "OpenCL.dll lacks %s", #f); return 0; }
|
|
IG_CL_FUNCS(IG_CL_LOAD)
|
|
#undef IG_CL_LOAD
|
|
return 1;
|
|
#else
|
|
snprintf(ig_cl_error, sizeof(ig_cl_error), "IGNEUM_CL_DYNAMIC is for the Windows build");
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
/* From here on, host.c's calls go through the pointers. */
|
|
#define IG_CL_RENAME(f)
|
|
#define clGetPlatformIDs ig_clGetPlatformIDs
|
|
#define clGetPlatformInfo ig_clGetPlatformInfo
|
|
#define clGetDeviceIDs ig_clGetDeviceIDs
|
|
#define clGetDeviceInfo ig_clGetDeviceInfo
|
|
#define clCreateContext ig_clCreateContext
|
|
#define clCreateCommandQueue ig_clCreateCommandQueue
|
|
#define clCreateProgramWithSource ig_clCreateProgramWithSource
|
|
#define clBuildProgram ig_clBuildProgram
|
|
#define clGetProgramBuildInfo ig_clGetProgramBuildInfo
|
|
#define clCreateKernel ig_clCreateKernel
|
|
#define clSetKernelArg ig_clSetKernelArg
|
|
#define clEnqueueNDRangeKernel ig_clEnqueueNDRangeKernel
|
|
#define clEnqueueReadBuffer ig_clEnqueueReadBuffer
|
|
#define clEnqueueWriteBuffer ig_clEnqueueWriteBuffer
|
|
#define clCreateBuffer ig_clCreateBuffer
|
|
#define clReleaseMemObject ig_clReleaseMemObject
|
|
#define clReleaseKernel ig_clReleaseKernel
|
|
#define clReleaseProgram ig_clReleaseProgram
|
|
#define clReleaseCommandQueue ig_clReleaseCommandQueue
|
|
#define clReleaseContext ig_clReleaseContext
|
|
#define clFinish ig_clFinish
|
|
#define clWaitForEvents ig_clWaitForEvents
|
|
#define clReleaseEvent ig_clReleaseEvent
|
|
#define clGetEventProfilingInfo ig_clGetEventProfilingInfo
|
|
#define clGetKernelWorkGroupInfo ig_clGetKernelWorkGroupInfo
|
|
#define clGetExtensionFunctionAddressForPlatform ig_clGetExtensionFunctionAddressForPlatform
|
|
#endif
|