forked from microo8/blackcl
-
Notifications
You must be signed in to change notification settings - Fork 0
/
device.go
140 lines (124 loc) · 3.44 KB
/
device.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package blackcl
/*
#cgo CFLAGS: -I CL
#cgo !darwin LDFLAGS: -lOpenCL
#cgo darwin LDFLAGS: -framework OpenCL
#define CL_SILENCE_DEPRECATION
#ifdef __APPLE__
#include <OpenCL/opencl.h>
#else
#include <CL/cl.h>
#endif
*/
import "C"
import (
"unsafe"
)
//DeviceType is an enum of device types
type DeviceType uint
//All values of DeviceType
const (
DeviceTypeCPU DeviceType = C.CL_DEVICE_TYPE_CPU
DeviceTypeGPU DeviceType = C.CL_DEVICE_TYPE_GPU
DeviceTypeAccelerator DeviceType = C.CL_DEVICE_TYPE_ACCELERATOR
DeviceTypeDefault DeviceType = C.CL_DEVICE_TYPE_DEFAULT
DeviceTypeAll DeviceType = C.CL_DEVICE_TYPE_ALL
)
//Device the only needed entrence for the BlackCL
//represents the device on which memory can be allocated and kernels run
//it abstracts away all the complexity of contexts/platforms/queues
type Device struct {
id C.cl_device_id
ctx C.cl_context
queue C.cl_command_queue
programs []C.cl_program
}
//Release releases the device
func (d *Device) Release() error {
for _, p := range d.programs {
err := toErr(C.clReleaseProgram(p))
if err != nil {
return err
}
}
err := toErr(C.clReleaseCommandQueue(d.queue))
if err != nil {
return err
}
err = toErr(C.clReleaseContext(d.ctx))
if err != nil {
return err
}
return toErr(C.clReleaseDevice(d.id))
}
func (d *Device) getInfoString(param C.cl_device_info, panicOnError bool) (string, error) {
var strC [1024]C.char
var strN C.size_t
err := toErr(C.clGetDeviceInfo(d.id, param, 1024, unsafe.Pointer(&strC), &strN))
if err != nil {
return "", err
}
return C.GoStringN((*C.char)(unsafe.Pointer(&strC)), C.int(strN)), nil
}
func (d *Device) String() string {
return d.Name() + " " + d.Vendor()
}
//Name device info - name
func (d *Device) Name() string {
str, _ := d.getInfoString(C.CL_DEVICE_NAME, true)
return str
}
//Vendor device info - vendor
func (d *Device) Vendor() string {
str, _ := d.getInfoString(C.CL_DEVICE_VENDOR, true)
return str
}
//Extensions device info - extensions
func (d *Device) Extensions() string {
str, _ := d.getInfoString(C.CL_DEVICE_EXTENSIONS, true)
return str
}
//OpenCLCVersion device info - OpenCL C Version
func (d *Device) OpenCLCVersion() string {
str, _ := d.getInfoString(C.CL_DEVICE_OPENCL_C_VERSION, true)
return str
}
//Profile device info - profile
func (d *Device) Profile() string {
str, _ := d.getInfoString(C.CL_DEVICE_PROFILE, true)
return str
}
//Version device info - version
func (d *Device) Version() string {
str, _ := d.getInfoString(C.CL_DEVICE_VERSION, true)
return str
}
//DriverVersion device info - driver version
func (d *Device) DriverVersion() string {
str, _ := d.getInfoString(C.CL_DRIVER_VERSION, true)
return str
}
//AddProgram copiles program source
//if an error ocurres in building the program the AddProgram will panic
func (d *Device) AddProgram(source string) {
var ret C.cl_int
csource := C.CString(source)
defer C.free(unsafe.Pointer(csource))
p := C.clCreateProgramWithSource(d.ctx, 1, &csource, nil, &ret)
err := toErr(ret)
if err != nil {
panic(err)
}
ret = C.clBuildProgram(p, 1, &d.id, nil, nil, nil)
if ret != C.CL_SUCCESS {
if ret == C.CL_BUILD_PROGRAM_FAILURE {
var n C.size_t
C.clGetProgramBuildInfo(p, d.id, C.CL_PROGRAM_BUILD_LOG, 0, nil, &n)
log := make([]byte, int(n))
C.clGetProgramBuildInfo(p, d.id, C.CL_PROGRAM_BUILD_LOG, n, unsafe.Pointer(&log[0]), nil)
panic(string(log))
}
panic(toErr(ret))
}
d.programs = append(d.programs, p)
}