Blame c++/contourgl/clcontext.cpp

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
f83e6b
ClContext::ClContext(): err(), context(), queue() {
c76ce8
c76ce8
	// platform
c76ce8
c76ce8
	cl_uint platform_count = 0;
c76ce8
	clGetPlatformIDs(0, NULL, &platform_count);
c76ce8
	assert(platform_count);
f29469
	//cout << platform_count << " platforms" << endl;
c76ce8
	vector<cl_platform_id> platforms(platform_count);</cl_platform_id>
c76ce8
	clGetPlatformIDs(platforms.size(), &platforms.front(), NULL);
c76ce8
	cl_platform_id platform = platforms[0];
c76ce8
c76ce8
	char vendor[256] = { };
c76ce8
	err = clGetPlatformInfo(platform, CL_PLATFORM_VENDOR, sizeof(vendor), vendor, NULL);
c76ce8
	assert(!err);
f29469
	//cout << "Use CL platform 0 by " << vendor << endl;
c76ce8
5890eb
    char platform_version[256];
5890eb
    err = clGetPlatformInfo(platform, CL_PLATFORM_VERSION, sizeof(platform_version), platform_version, NULL);
5890eb
	assert(!err);
f29469
    //cout << "Platform 0 OpenCL version " << platform_version << endl;
5890eb
c76ce8
	// devices
c76ce8
c76ce8
	cl_uint device_count = 0;
c76ce8
    err = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 0, NULL, &device_count);
c76ce8
    assert(!err);
f29469
    //cout << device_count << " devices" << endl;
c76ce8
c76ce8
    devices.resize(device_count);
c76ce8
    err = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, devices.size(), &devices.front(), NULL);
c76ce8
    assert(!err);
c76ce8
5890eb
    char device_name[256];
5890eb
    clGetDeviceInfo(devices.front(), CL_DEVICE_NAME, sizeof(device_name), device_name, NULL);
f29469
    //cout << "Device 0 name " << device_name << endl;
5890eb
5890eb
    char device_version[256];
5890eb
    clGetDeviceInfo(devices.front(), CL_DEVICE_VERSION, sizeof(device_version), device_version, NULL);
f29469
    //cout << "Device 0 OpenCL version " << device_version << endl;
5890eb
c76ce8
    // context
c76ce8
c7fa36
    cl_context_properties context_props[] = {
c7fa36
    	CL_CONTEXT_PLATFORM, (cl_context_properties)platform,
c7fa36
		CL_NONE };
c7fa36
    context = clCreateContext(context_props, 1, &devices.front(), callback, NULL, &err);
c76ce8
    assert(context);
f83e6b
f83e6b
	// command queue
f83e6b
c7fa36
	queue = clCreateCommandQueue(context, devices.front(), CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE, 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
5890eb
	err = clBuildProgram(program, 1, &devices.front(), "", NULL, NULL);
5890eb
	if (err) {
5890eb
		size_t size;
5890eb
		clGetProgramBuildInfo(program, devices.front(), CL_PROGRAM_BUILD_LOG, 0, NULL, &size);
5890eb
		char *log = new char[size];
5890eb
		clGetProgramBuildInfo(program, devices.front(), 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);
c76ce8
	cl_event event = NULL;
c76ce8
	err = clEnqueueNDRangeKernel(
c76ce8
		queue,
c76ce8
		kernel,
c76ce8
		1,
c76ce8
		NULL,
c76ce8
		&work_group_size,
c76ce8
		NULL,
c76ce8
		0,
c76ce8
		NULL,
c76ce8
		&event );
c76ce8
	assert(!err);
c76ce8
c76ce8
	clWaitForEvents(1, &event);
c76ce8
c76ce8
	// read
c76ce8
c76ce8
	clEnqueueReadBuffer(queue, buffer, CL_TRUE, 0, sizeof(data), data, 0, NULL, &event);
c76ce8
	clWaitForEvents(1, &event);
c76ce8
	cout << data << endl;
f83e6b
f83e6b
	// deinitialize
f83e6b
f83e6b
	clReleaseKernel(kernel);
f83e6b
	clReleaseProgram(program);
f83e6b
	clReleaseMemObject(buffer);
c76ce8
}