func (p *Program) BuildProgram(devices []*Device, options string) error { var cOptions *C.char if options != "" { cOptions = C.CString(options) defer C.free(unsafe.Pointer(cOptions)) } var deviceList []C.cl_device_id var deviceListPtr *C.cl_device_id if devices != nil && len(devices) > 0 { deviceList = buildDeviceIdList(devices) deviceListPtr = &deviceList[0] } numDevices := C.cl_uint(len(deviceList)) if err := C.clBuildProgram(p.clProgram, numDevices, deviceListPtr, cOptions, nil, nil); err != C.CL_SUCCESS { if err != C.CL_BUILD_PROGRAM_FAILURE { return toError(err) } var bLen C.size_t var err C.cl_int err = C.clGetProgramBuildInfo(p.clProgram, p.devices[0].id, C.CL_PROGRAM_BUILD_LOG, 0, nil, &bLen) if err != C.CL_SUCCESS { return toError(err) } buffer := make([]byte, bLen) err = C.clGetProgramBuildInfo(p.clProgram, p.devices[0].id, C.CL_PROGRAM_BUILD_LOG, C.size_t(len(buffer)), unsafe.Pointer(&buffer[0]), &bLen) if err != C.CL_SUCCESS { return toError(err) } return BuildError(string(buffer[:bLen-1])) } return nil }
func (p *Program) Property(dev Device, prop BuildProperty) string { var count C.size_t if ret := C.clGetProgramBuildInfo(p.id, dev.id, C.cl_program_build_info(prop), 0, nil, &count); ret != C.CL_SUCCESS || count < 1 { return "" } buf := make([]C.char, count) if ret := C.clGetProgramBuildInfo(p.id, dev.id, C.cl_program_build_info(prop), count, unsafe.Pointer(&buf[0]), &count); ret != C.CL_SUCCESS || count < 1 { return "" } return C.GoStringN(&buf[0], C.int(count-1)) }
func (p *Program) BuildProgram(devices []*Device, options string) error { var cOptions *C.char if options != "" { cOptions = C.CString(options) defer C.free(unsafe.Pointer(cOptions)) } var deviceList []C.cl_device_id var deviceListPtr *C.cl_device_id numDevices := C.cl_uint(0) if devices != nil && len(devices) > 0 { deviceList = buildDeviceIdList(devices) deviceListPtr = &deviceList[0] } if err := C.clBuildProgram(p.clProgram, numDevices, deviceListPtr, cOptions, nil, nil); err != C.CL_SUCCESS { buffer := make([]byte, 4096) var bLen C.size_t var err C.cl_int for i := 2; i >= 0; i-- { err = C.clGetProgramBuildInfo(p.clProgram, p.devices[0].id, C.CL_PROGRAM_BUILD_LOG, C.size_t(len(buffer)), unsafe.Pointer(&buffer[0]), &bLen) if err == C.CL_INVALID_VALUE && i > 0 && bLen < 1024*1024 { // INVALID_VALUE probably means our buffer isn't large enough buffer = make([]byte, bLen) } else { break } } if err != C.CL_SUCCESS { return toError(err) } return BuildError(string(buffer[:bLen])) } return nil }
func (p *Program) CompileProgramWithCallback(devices []*Device, options string, program_headers []*ProgramHeaders, user_data unsafe.Pointer) error { var cOptions *C.char if options != "" { cOptions = C.CString(options) defer C.free(unsafe.Pointer(cOptions)) } var deviceList []C.cl_device_id var deviceListPtr *C.cl_device_id numDevices := C.cl_uint(len(devices)) if devices != nil && len(devices) > 0 { deviceList = buildDeviceIdList(devices) deviceListPtr = &deviceList[0] } num_headers := len(program_headers) cHeaders := make([]C.cl_program, num_headers) cHeader_names := make([]*C.char, num_headers) for idx, ph := range program_headers { chs := ph.codes chn := C.CString(ph.names) cHeaders[idx] = chs.clProgram cHeader_names[idx] = chn defer C.free(chs) defer C.free(chn) } err := C.CLCompileProgram(p.clProgram, numDevices, deviceListPtr, cOptions, C.cl_uint(num_headers), &cHeaders[0], &cHeader_names[0], user_data) if err != C.CL_SUCCESS { buffer := make([]byte, 4096) var bLen C.size_t var err C.cl_int for _, dev := range p.devices { for i := 2; i >= 0; i-- { err = C.clGetProgramBuildInfo(p.clProgram, dev.id, C.CL_PROGRAM_BUILD_LOG, C.size_t(len(buffer)), unsafe.Pointer(&buffer[0]), &bLen) if err == C.CL_INVALID_VALUE && i > 0 && bLen < 1024*1024 { // INVALID_VALUE probably means our buffer isn't large enough buffer = make([]byte, bLen) } else { break } } if err != C.CL_SUCCESS { return toError(err) } if bLen > 1 { return BuildError{ Device: dev, Message: string(buffer[:bLen-1]), } } } return BuildError{ Device: nil, Message: "build failed and produced no log entries", } } return nil }
func (p *Program) BuildStatus(dev Device) BuildStatus { var c_status C.cl_build_status var count C.size_t if ret := C.clGetProgramBuildInfo(p.id, dev.id, C.CL_PROGRAM_BUILD_STATUS, C.size_t(unsafe.Sizeof(c_status)), unsafe.Pointer(&c_status), &count); ret != C.CL_SUCCESS { return BUILD_ERROR } return BuildStatus(c_status) }
func (ctx *Context) LinkProgramWithCallback(programs []*Program, devices []*Device, options string, user_data unsafe.Pointer) (*Program, error) { var cOptions *C.char if options != "" { cOptions = C.CString(options) defer C.free(unsafe.Pointer(cOptions)) } var deviceList []C.cl_device_id var deviceListPtr *C.cl_device_id numDevices := C.cl_uint(len(devices)) if devices != nil && len(devices) > 0 { deviceList = buildDeviceIdList(devices) deviceListPtr = &deviceList[0] } programList := make([]C.cl_program, len(programs)) for idx, progId := range programs { programList[idx] = progId.clProgram } var err C.cl_int programExe := C.CLLinkProgram(ctx.clContext, numDevices, deviceListPtr, cOptions, C.cl_uint(len(programs)), &programList[0], user_data, &err) p := &Program{clProgram: programExe, devices: devices} if err != C.CL_SUCCESS { buffer := make([]byte, 4096) var bLen C.size_t var err C.cl_int for _, dev := range p.devices { for i := 2; i >= 0; i-- { err = C.clGetProgramBuildInfo(p.clProgram, dev.id, C.CL_PROGRAM_BUILD_LOG, C.size_t(len(buffer)), unsafe.Pointer(&buffer[0]), &bLen) if err == C.CL_INVALID_VALUE && i > 0 && bLen < 1024*1024 { // INVALID_VALUE probably means our buffer isn't large enough buffer = make([]byte, bLen) } else { break } } if err != C.CL_SUCCESS { return nil, toError(err) } if bLen > 1 { return nil, BuildError{ Device: dev, Message: string(buffer[:bLen-1]), } } } return nil, BuildError{ Device: nil, Message: "build failed and produced no log entries", } } return p, nil }
func (p *Program) GetBuildLog(device *Device) (string, error) { var strC [1024]C.char var strN C.size_t if err := C.clGetProgramBuildInfo(p.clProgram, device.id, C.CL_PROGRAM_BUILD_LOG, 1024, unsafe.Pointer(&strC), &strN); err != C.CL_SUCCESS { panic("Should never fail") return "", toError(err) } // OpenCL strings are NUL-terminated, and the terminator is included in strN // Go strings aren't NUL-terminated, so subtract 1 from the length return C.GoStringN((*C.char)(unsafe.Pointer(&strC)), C.int(strN-1)), nil }
func (p *Program) BuildProgram(devices []*Device, options string) error { var optBuffer bytes.Buffer optBuffer.WriteString("-cl-std=CL1.2 -cl-kernel-arg-info ") var cOptions *C.char if options != "" { optBuffer.WriteString(options) } cOptions = C.CString(optBuffer.String()) defer C.free(unsafe.Pointer(cOptions)) var deviceList []C.cl_device_id var deviceListPtr *C.cl_device_id numDevices := C.cl_uint(len(devices)) if devices != nil && len(devices) > 0 { deviceList = buildDeviceIdList(devices) deviceListPtr = &deviceList[0] } if err := C.clBuildProgram(p.clProgram, numDevices, deviceListPtr, cOptions, nil, nil); err != C.CL_SUCCESS { buffer := make([]byte, 4096) var bLen C.size_t var err C.cl_int for _, dev := range p.devices { for i := 2; i >= 0; i-- { err = C.clGetProgramBuildInfo(p.clProgram, dev.id, C.CL_PROGRAM_BUILD_LOG, C.size_t(len(buffer)), unsafe.Pointer(&buffer[0]), &bLen) if err == C.CL_INVALID_VALUE && i > 0 && bLen < 1024*1024 { // INVALID_VALUE probably means our buffer isn't large enough buffer = make([]byte, bLen) } else { break } } if err != C.CL_SUCCESS { return toError(err) } if bLen > 1 { return BuildError{ Device: dev, Message: string(buffer[:bLen-1]), } } } return BuildError{ Device: nil, Message: "build failed and produced no log entries", } } return nil }
// see https://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/clGetProgramBuildInfo.html func GetProgramBuildInfo(prog Program, device DeviceId, paramName ProgramBuildInfo, paramValueSize uint64, paramValue unsafe.Pointer, paramValueSizeRet *uint64) ErrorCode { return ErrorCode(C.clGetProgramBuildInfo(prog, device, C.cl_program_build_info(paramName), C.size_t(paramValueSize), paramValue, (*C.size_t)(paramValueSizeRet))) }
func CLGetProgramBuildInfo(program CL_program, device CL_device_id, param_name CL_program_build_info, param_value_size CL_size_t, param_value *interface{}, param_value_size_ret *CL_size_t) CL_int { if (param_value_size == 0 || param_value == nil) && param_value_size_ret == nil { return CL_INVALID_VALUE } else { var c_param_value_size_ret C.size_t var c_errcode_ret C.cl_int if param_value_size == 0 || param_value == nil { c_errcode_ret = C.clGetProgramBuildInfo(program.cl_program, device.cl_device_id, C.cl_program_build_info(param_name), C.size_t(param_value_size), nil, &c_param_value_size_ret) } else { switch param_name { case CL_PROGRAM_BUILD_STATUS: var value C.cl_build_status c_errcode_ret = C.clGetProgramBuildInfo(program.cl_program, device.cl_device_id, C.cl_program_build_info(param_name), C.size_t(param_value_size), unsafe.Pointer(&value), &c_param_value_size_ret) *param_value = CL_build_status(value) case CL_PROGRAM_BUILD_OPTIONS, CL_PROGRAM_BUILD_LOG: value := make([]C.char, param_value_size) c_errcode_ret = C.clGetProgramBuildInfo(program.cl_program, device.cl_device_id, C.cl_program_build_info(param_name), C.size_t(param_value_size), unsafe.Pointer(&value[0]), &c_param_value_size_ret) *param_value = C.GoStringN(&value[0], C.int(c_param_value_size_ret-1)) case CL_PROGRAM_BINARY_TYPE: var value C.cl_program_binary_type c_errcode_ret = C.clGetProgramBuildInfo(program.cl_program, device.cl_device_id, C.cl_program_build_info(param_name), C.size_t(param_value_size), unsafe.Pointer(&value), &c_param_value_size_ret) *param_value = CL_program_binary_type(value) case CL_PROGRAM_BUILD_GLOBAL_VARIABLE_TOTAL_SIZE: var value C.size_t c_errcode_ret = C.clGetProgramBuildInfo(program.cl_program, device.cl_device_id, C.cl_program_build_info(param_name), C.size_t(param_value_size), unsafe.Pointer(&value), &c_param_value_size_ret) *param_value = CL_size_t(value) default: return CL_INVALID_VALUE } } if param_value_size_ret != nil { *param_value_size_ret = CL_size_t(c_param_value_size_ret) } return CL_int(c_errcode_ret) } }
func (p *Program) GetProgramBinaryType(device *Device) (ProgramBinaryTypes, error) { var binType C.cl_program_binary_type err := C.clGetProgramBuildInfo(p.clProgram, device.id, C.CL_PROGRAM_BINARY_TYPE, C.size_t(unsafe.Sizeof(binType)), unsafe.Pointer(&binType), nil) return ProgramBinaryTypes(binType), toError(err) }
func (p *Program) GetBuildStatus(device *Device) (BuildStatus, error) { var buildStatus C.cl_build_status err := C.clGetProgramBuildInfo(p.clProgram, device.id, C.CL_PROGRAM_BUILD_STATUS, C.size_t(unsafe.Sizeof(buildStatus)), unsafe.Pointer(&buildStatus), nil) return BuildStatus(buildStatus), toError(err) }