lotus/lib/harmony/resources/miniopencl/mini_opencl.go
2023-08-28 16:54:05 -05:00

147 lines
5.8 KiB
Go

// Package cl was borrowed from the go-opencl library which is more complex and
// doesn't compile well for our needs.
package cl
// #include "cl.h"
import "C"
import (
"errors"
"fmt"
"unsafe"
)
const maxPlatforms = 32
type Platform struct {
id C.cl_platform_id
}
// Obtain the list of platforms available.
func GetPlatforms() ([]*Platform, error) {
var platformIds [maxPlatforms]C.cl_platform_id
var nPlatforms C.cl_uint
if err := C.clGetPlatformIDs(C.cl_uint(maxPlatforms), &platformIds[0], &nPlatforms); err != C.CL_SUCCESS {
return nil, toError(err)
}
platforms := make([]*Platform, nPlatforms)
for i := 0; i < int(nPlatforms); i++ {
platforms[i] = &Platform{id: platformIds[i]}
}
return platforms, nil
}
const maxDeviceCount = 64
type DeviceType uint
const (
DeviceTypeAll DeviceType = C.CL_DEVICE_TYPE_ALL
)
type Device struct {
id C.cl_device_id
}
func (p *Platform) GetAllDevices() ([]*Device, error) {
var deviceIds [maxDeviceCount]C.cl_device_id
var numDevices C.cl_uint
var platformId C.cl_platform_id
if p != nil {
platformId = p.id
}
if err := C.clGetDeviceIDs(platformId, C.cl_device_type(DeviceTypeAll), C.cl_uint(maxDeviceCount), &deviceIds[0], &numDevices); err != C.CL_SUCCESS {
return nil, toError(err)
}
if numDevices > maxDeviceCount {
numDevices = maxDeviceCount
}
devices := make([]*Device, numDevices)
for i := 0; i < int(numDevices); i++ {
devices[i] = &Device{id: deviceIds[i]}
}
return devices, nil
}
var errorMap = map[C.cl_int]string{
C.CL_SUCCESS: "nil",
C.CL_DEVICE_NOT_FOUND: "ErrDeviceNotFound",
C.CL_DEVICE_NOT_AVAILABLE: "ErrDeviceNotAvailable",
C.CL_COMPILER_NOT_AVAILABLE: "ErrCompilerNotAvailable",
C.CL_MEM_OBJECT_ALLOCATION_FAILURE: "ErrMemObjectAllocationFailure",
C.CL_OUT_OF_RESOURCES: "ErrOutOfResources",
C.CL_OUT_OF_HOST_MEMORY: "ErrOutOfHostMemory",
C.CL_PROFILING_INFO_NOT_AVAILABLE: "ErrProfilingInfoNotAvailable",
C.CL_MEM_COPY_OVERLAP: "ErrMemCopyOverlap",
C.CL_IMAGE_FORMAT_MISMATCH: "ErrImageFormatMismatch",
C.CL_IMAGE_FORMAT_NOT_SUPPORTED: "ErrImageFormatNotSupported",
C.CL_BUILD_PROGRAM_FAILURE: "ErrBuildProgramFailure",
C.CL_MAP_FAILURE: "ErrMapFailure",
C.CL_MISALIGNED_SUB_BUFFER_OFFSET: "ErrMisalignedSubBufferOffset",
C.CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST: "ErrExecStatusErrorForEventsInWaitList",
C.CL_INVALID_VALUE: "ErrInvalidValue",
C.CL_INVALID_DEVICE_TYPE: "ErrInvalidDeviceType",
C.CL_INVALID_PLATFORM: "ErrInvalidPlatform",
C.CL_INVALID_DEVICE: "ErrInvalidDevice",
C.CL_INVALID_CONTEXT: "ErrInvalidContext",
C.CL_INVALID_QUEUE_PROPERTIES: "ErrInvalidQueueProperties",
C.CL_INVALID_COMMAND_QUEUE: "ErrInvalidCommandQueue",
C.CL_INVALID_HOST_PTR: "ErrInvalidHostPtr",
C.CL_INVALID_MEM_OBJECT: "ErrInvalidMemObject",
C.CL_INVALID_IMAGE_FORMAT_DESCRIPTOR: "ErrInvalidImageFormatDescriptor",
C.CL_INVALID_IMAGE_SIZE: "ErrInvalidImageSize",
C.CL_INVALID_SAMPLER: "ErrInvalidSampler",
C.CL_INVALID_BINARY: "ErrInvalidBinary",
C.CL_INVALID_BUILD_OPTIONS: "ErrInvalidBuildOptions",
C.CL_INVALID_PROGRAM: "ErrInvalidProgram",
C.CL_INVALID_PROGRAM_EXECUTABLE: "ErrInvalidProgramExecutable",
C.CL_INVALID_KERNEL_NAME: "ErrInvalidKernelName",
C.CL_INVALID_KERNEL_DEFINITION: "ErrInvalidKernelDefinition",
C.CL_INVALID_KERNEL: "ErrInvalidKernel",
C.CL_INVALID_ARG_INDEX: "ErrInvalidArgIndex",
C.CL_INVALID_ARG_VALUE: "ErrInvalidArgValue",
C.CL_INVALID_ARG_SIZE: "ErrInvalidArgSize",
C.CL_INVALID_KERNEL_ARGS: "ErrInvalidKernelArgs",
C.CL_INVALID_WORK_DIMENSION: "ErrInvalidWorkDimension",
C.CL_INVALID_WORK_GROUP_SIZE: "ErrInvalidWorkGroupSize",
C.CL_INVALID_WORK_ITEM_SIZE: "ErrInvalidWorkItemSize",
C.CL_INVALID_GLOBAL_OFFSET: "ErrInvalidGlobalOffset",
C.CL_INVALID_EVENT_WAIT_LIST: "ErrInvalidEventWaitList",
C.CL_INVALID_EVENT: "ErrInvalidEvent",
C.CL_INVALID_OPERATION: "ErrInvalidOperation",
C.CL_INVALID_GL_OBJECT: "ErrInvalidGlObject",
C.CL_INVALID_BUFFER_SIZE: "ErrInvalidBufferSize",
C.CL_INVALID_MIP_LEVEL: "ErrInvalidMipLevel",
C.CL_INVALID_GLOBAL_WORK_SIZE: "ErrInvalidGlobalWorkSize",
C.CL_INVALID_PROPERTY: "ErrInvalidProperty",
}
func toError(code C.cl_int) error {
if err, ok := errorMap[code]; ok {
return errors.New(err)
}
return ErrOther(code)
}
type ErrOther int
func (e ErrOther) Error() string {
return fmt.Sprintf("cl: error %d", int(e))
}
// Size of global device memory in bytes.
func (d *Device) GlobalMemSize() int64 {
val, _ := d.getInfoUlong(C.CL_DEVICE_GLOBAL_MEM_SIZE, true)
return val
}
func (d *Device) getInfoUlong(param C.cl_device_info, panicOnError bool) (int64, error) {
var val C.cl_ulong
if err := C.clGetDeviceInfo(d.id, param, C.size_t(unsafe.Sizeof(val)), unsafe.Pointer(&val), nil); err != C.CL_SUCCESS {
if panicOnError {
panic("Should never fail")
}
return 0, toError(err)
}
return int64(val), nil
}