Blame c++/contourgl/clcontext.cpp

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