|
|
c76ce8 |
/*
|
|
|
c76ce8 |
......... 2015 Ivan Mahonin
|
|
|
c76ce8 |
|
|
|
c76ce8 |
This program is free software: you can redistribute it and/or modify
|
|
|
c76ce8 |
it under the terms of the GNU General Public License as published by
|
|
|
c76ce8 |
the Free Software Foundation, either version 3 of the License, or
|
|
|
c76ce8 |
(at your option) any later version.
|
|
|
c76ce8 |
|
|
|
c76ce8 |
This program is distributed in the hope that it will be useful,
|
|
|
c76ce8 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
c76ce8 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
c76ce8 |
GNU General Public License for more details.
|
|
|
c76ce8 |
|
|
|
c76ce8 |
You should have received a copy of the GNU General Public License
|
|
|
c76ce8 |
along with this program. If not, see <http: licenses="" www.gnu.org="">.</http:>
|
|
|
c76ce8 |
*/
|
|
|
c76ce8 |
|
|
|
c76ce8 |
#include <cassert></cassert>
|
|
|
c76ce8 |
|
|
|
c76ce8 |
#include <iostream></iostream>
|
|
|
c76ce8 |
#include <fstream></fstream>
|
|
|
c76ce8 |
|
|
|
c76ce8 |
#include "clcontext.h"
|
|
|
c76ce8 |
|
|
|
c76ce8 |
|
|
|
c76ce8 |
using namespace std;
|
|
|
c76ce8 |
|
|
|
c76ce8 |
|
|
|
013f0c |
ClContext::ClContext():
|
|
|
013f0c |
err(),
|
|
|
2517eb |
device(),
|
|
|
013f0c |
context(),
|
|
|
013f0c |
queue(),
|
|
|
013f0c |
max_compute_units(),
|
|
|
013f0c |
max_group_size()
|
|
|
013f0c |
{
|
|
|
2517eb |
const int platform_index = 0;
|
|
|
2517eb |
const int device_index = 0;
|
|
|
c76ce8 |
|
|
|
c76ce8 |
// platform
|
|
|
c76ce8 |
cl_uint platform_count = 0;
|
|
|
2517eb |
err |= clGetPlatformIDs(0, NULL, &platform_count);
|
|
|
2517eb |
assert(!err);
|
|
|
f29469 |
//cout << platform_count << " platforms" << endl;
|
|
|
2517eb |
|
|
|
c76ce8 |
vector<cl_platform_id> platforms(platform_count);</cl_platform_id>
|
|
|
2517eb |
err |= clGetPlatformIDs(platforms.size(), &platforms.front(), NULL);
|
|
|
2517eb |
assert(!err);
|
|
|
2517eb |
|
|
|
2517eb |
assert(platform_index < (int)platform_count);
|
|
|
2517eb |
cl_platform_id platform = platforms[platform_index];
|
|
|
c76ce8 |
|
|
|
c76ce8 |
char vendor[256] = { };
|
|
|
2517eb |
err |= clGetPlatformInfo(platform, CL_PLATFORM_VENDOR, sizeof(vendor), vendor, NULL);
|
|
|
c76ce8 |
assert(!err);
|
|
|
2517eb |
//cout << "Use CL platform " << platform_index << " by " << vendor << endl;
|
|
|
c76ce8 |
|
|
|
5890eb |
char platform_version[256];
|
|
|
2517eb |
err |= clGetPlatformInfo(platform, CL_PLATFORM_VERSION, sizeof(platform_version), platform_version, NULL);
|
|
|
5890eb |
assert(!err);
|
|
|
2517eb |
//cout << "Platform " << platform_index << " OpenCL version " << platform_version << endl;
|
|
|
5890eb |
|
|
|
c76ce8 |
// devices
|
|
|
c76ce8 |
|
|
|
c76ce8 |
cl_uint device_count = 0;
|
|
|
2517eb |
err |= clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL, 0, NULL, &device_count);
|
|
|
c76ce8 |
assert(!err);
|
|
|
f29469 |
//cout << device_count << " devices" << endl;
|
|
|
c76ce8 |
|
|
|
2517eb |
vector<cl_device_id> devices(device_count);</cl_device_id>
|
|
|
2517eb |
err |= clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL, devices.size(), &devices.front(), NULL);
|
|
|
c76ce8 |
assert(!err);
|
|
|
c76ce8 |
|
|
|
2517eb |
assert(device_index < (int)device_count);
|
|
|
2517eb |
device = devices[device_index];
|
|
|
2517eb |
|
|
|
5890eb |
char device_name[256];
|
|
|
2517eb |
err |= clGetDeviceInfo(device, CL_DEVICE_NAME, sizeof(device_name), device_name, NULL);
|
|
|
2517eb |
assert(!err);
|
|
|
2517eb |
//cout << "Device " << device_index << " name " << device_name << endl;
|
|
|
5890eb |
|
|
|
5890eb |
char device_version[256];
|
|
|
2517eb |
err |= clGetDeviceInfo(device, CL_DEVICE_VERSION, sizeof(device_version), device_version, NULL);
|
|
|
2517eb |
assert(!err);
|
|
|
2517eb |
//cout << "Device " << device_index << " OpenCL version " << device_version << endl;
|
|
|
2517eb |
|
|
|
2517eb |
err |= clGetDeviceInfo(device, CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(max_compute_units), &max_compute_units, NULL);
|
|
|
2517eb |
assert(!err);
|
|
|
2517eb |
//cout << "Device " << device_index << " max compute units " << max_compute_units << endl;
|
|
|
5890eb |
|
|
|
2517eb |
unsigned int max_dimensions;
|
|
|
2517eb |
err |= clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, sizeof(max_dimensions), &max_dimensions, NULL);
|
|
|
2517eb |
assert(!err);
|
|
|
2517eb |
assert(max_dimensions);
|
|
|
2517eb |
//cout << "Device " << device_index << " max work dimensions " << max_dimensions << endl;
|
|
|
013f0c |
|
|
|
2517eb |
vector<size_t> max_group_sizes(max_dimensions);</size_t>
|
|
|
2517eb |
err |= clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_GROUP_SIZE, max_group_sizes.size()*sizeof(size_t), &max_group_sizes.front(), NULL);
|
|
|
2517eb |
assert(!err);
|
|
|
2517eb |
max_group_size = max_group_sizes.front();
|
|
|
2517eb |
//cout << "Device " << device_index << " max group size " << max_group_size << endl;
|
|
|
013f0c |
|
|
|
60f47b |
size_t timer_resolution;
|
|
|
60f47b |
err |= clGetDeviceInfo(device, CL_DEVICE_PROFILING_TIMER_RESOLUTION, sizeof(timer_resolution), &timer_resolution, NULL);
|
|
|
60f47b |
assert(!err);
|
|
|
60f47b |
//cout << "Device " << device_index << " timer resolution " << timer_resolution << " ns" << endl;
|
|
|
60f47b |
|
|
|
60f47b |
unsigned long long global_mem_size;
|
|
|
60f47b |
err |= clGetDeviceInfo(device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof(global_mem_size), &global_mem_size, NULL);
|
|
|
60f47b |
assert(!err);
|
|
|
60f47b |
//cout << "Device " << device_index << " global mem size " << global_mem_size << endl;
|
|
|
60f47b |
|
|
|
60f47b |
unsigned long long local_mem_size;
|
|
|
60f47b |
err |= clGetDeviceInfo(device, CL_DEVICE_LOCAL_MEM_SIZE, sizeof(local_mem_size), &local_mem_size, NULL);
|
|
|
60f47b |
assert(!err);
|
|
|
60f47b |
//cout << "Device " << device_index << " local mem size " << local_mem_size << endl;
|
|
|
60f47b |
|
|
|
60f47b |
unsigned long long max_constant_buffer_size;
|
|
|
60f47b |
err |= clGetDeviceInfo(device, CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE, sizeof(max_constant_buffer_size), &max_constant_buffer_size, NULL);
|
|
|
60f47b |
assert(!err);
|
|
|
60f47b |
//cout << "Device " << device_index << " max constant buffer size " << max_constant_buffer_size << endl;
|
|
|
60f47b |
|
|
|
60f47b |
// context
|
|
|
c76ce8 |
|
|
|
c7fa36 |
cl_context_properties context_props[] = {
|
|
|
60f47b |
CL_CONTEXT_PLATFORM, (cl_context_properties)platform,
|
|
|
c7fa36 |
CL_NONE };
|
|
|
2517eb |
context = clCreateContext(context_props, 1, &device, callback, NULL, &err);
|
|
|
c76ce8 |
assert(context);
|
|
|
f83e6b |
|
|
|
f83e6b |
// command queue
|
|
|
f83e6b |
|
|
|
60f47b |
cl_command_queue_properties props = 0
|
|
|
60f47b |
| CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE
|
|
|
60f47b |
//| CL_QUEUE_PROFILING_ENABLE
|
|
|
60f47b |
| 0;
|
|
|
60f47b |
queue = clCreateCommandQueue(
|
|
|
60f47b |
context, device, props, NULL);
|
|
|
f83e6b |
assert(queue);
|
|
|
f83e6b |
|
|
|
6b0407 |
//hello();
|
|
|
c76ce8 |
}
|
|
|
c76ce8 |
|
|
|
c76ce8 |
ClContext::~ClContext() {
|
|
|
f83e6b |
clReleaseCommandQueue(queue);
|
|
|
c76ce8 |
clReleaseContext(context);
|
|
|
c76ce8 |
}
|
|
|
c76ce8 |
|
|
|
c7fa36 |
void ClContext::callback(const char *, const void *, size_t, void *) { }
|
|
|
c7fa36 |
|
|
|
f83e6b |
cl_program ClContext::load_program(const std::string &filename) {
|
|
|
f83e6b |
ifstream f(("cl/" + filename).c_str());
|
|
|
f83e6b |
string text((istreambuf_iterator<char>(f)), istreambuf_iterator<char>());</char></char>
|
|
|
f83e6b |
const char *text_pointer = text.c_str();
|
|
|
f83e6b |
cl_program program = clCreateProgramWithSource(context, 1, &text_pointer, NULL, NULL);
|
|
|
f83e6b |
assert(program);
|
|
|
f83e6b |
|
|
|
2517eb |
const char options[] = " -cl-fast-relaxed-math -Werror ";
|
|
|
2517eb |
|
|
|
2517eb |
err = clBuildProgram(program, 1, &device, options, NULL, NULL);
|
|
|
5890eb |
if (err) {
|
|
|
5890eb |
size_t size;
|
|
|
2517eb |
clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, 0, NULL, &size);
|
|
|
5890eb |
char *log = new char[size];
|
|
|
2517eb |
clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, size, log, NULL);
|
|
|
5890eb |
cout << log << endl;
|
|
|
5890eb |
delete[] log;
|
|
|
5890eb |
}
|
|
|
f83e6b |
assert(!err);
|
|
|
f83e6b |
|
|
|
f83e6b |
return program;
|
|
|
f83e6b |
}
|
|
|
f83e6b |
|
|
|
c76ce8 |
void ClContext::hello() {
|
|
|
c76ce8 |
|
|
|
c76ce8 |
// data
|
|
|
c76ce8 |
|
|
|
c76ce8 |
char data[] = "......";
|
|
|
c76ce8 |
|
|
|
c76ce8 |
// buffer
|
|
|
c76ce8 |
|
|
|
c76ce8 |
cl_mem buffer = clCreateBuffer(context, CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR, sizeof(data), data, NULL);
|
|
|
c76ce8 |
assert(buffer);
|
|
|
c76ce8 |
|
|
|
c76ce8 |
// program
|
|
|
c76ce8 |
|
|
|
f83e6b |
cl_program program = load_program("hello.cl");
|
|
|
c76ce8 |
|
|
|
c76ce8 |
// kernel
|
|
|
c76ce8 |
|
|
|
c76ce8 |
cl_kernel kernel = clCreateKernel(program, "hello", NULL);
|
|
|
c76ce8 |
assert(kernel);
|
|
|
c76ce8 |
err = clSetKernelArg(kernel, 0, sizeof(buffer), &buffer);
|
|
|
c76ce8 |
assert(!err);
|
|
|
c76ce8 |
|
|
|
c76ce8 |
size_t work_group_size = sizeof(data);
|
|
|
013f0c |
cl_event event1 = NULL, event2 = NULL;
|
|
|
c76ce8 |
err = clEnqueueNDRangeKernel(
|
|
|
c76ce8 |
queue,
|
|
|
c76ce8 |
kernel,
|
|
|
c76ce8 |
1,
|
|
|
c76ce8 |
NULL,
|
|
|
c76ce8 |
&work_group_size,
|
|
|
c76ce8 |
NULL,
|
|
|
c76ce8 |
0,
|
|
|
c76ce8 |
NULL,
|
|
|
013f0c |
&event1 );
|
|
|
c76ce8 |
assert(!err);
|
|
|
c76ce8 |
|
|
|
c76ce8 |
// read
|
|
|
c76ce8 |
|
|
|
013f0c |
clEnqueueReadBuffer(queue, buffer, CL_TRUE, 0, sizeof(data), data, 1, &event1, &event2);
|
|
|
013f0c |
|
|
|
013f0c |
// wait
|
|
|
013f0c |
|
|
|
013f0c |
clWaitForEvents(1, &event2);
|
|
|
c76ce8 |
cout << data << endl;
|
|
|
f83e6b |
|
|
|
f83e6b |
// deinitialize
|
|
|
f83e6b |
|
|
|
f83e6b |
clReleaseKernel(kernel);
|
|
|
f83e6b |
clReleaseProgram(program);
|
|
|
f83e6b |
clReleaseMemObject(buffer);
|
|
|
c76ce8 |
}
|