|
|
572d9c |
/*
|
|
|
572d9c |
......... 2015 Ivan Mahonin
|
|
|
572d9c |
|
|
|
572d9c |
This program is free software: you can redistribute it and/or modify
|
|
|
572d9c |
it under the terms of the GNU General Public License as published by
|
|
|
572d9c |
the Free Software Foundation, either version 3 of the License, or
|
|
|
572d9c |
(at your option) any later version.
|
|
|
572d9c |
|
|
|
572d9c |
This program is distributed in the hope that it will be useful,
|
|
|
572d9c |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
572d9c |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
572d9c |
GNU General Public License for more details.
|
|
|
572d9c |
|
|
|
572d9c |
You should have received a copy of the GNU General Public License
|
|
|
572d9c |
along with this program. If not, see <http: licenses="" www.gnu.org="">.</http:>
|
|
|
572d9c |
*/
|
|
|
572d9c |
|
|
|
f83e6b |
#include <cassert></cassert>
|
|
|
f83e6b |
|
|
|
f83e6b |
#include <algorithm></algorithm>
|
|
|
6b0407 |
#include <iostream></iostream>
|
|
|
f83e6b |
|
|
|
572d9c |
#include "clrender.h"
|
|
|
f83e6b |
#include "measure.h"
|
|
|
572d9c |
|
|
|
572d9c |
|
|
|
572d9c |
using namespace std;
|
|
|
572d9c |
|
|
|
572d9c |
|
|
|
f83e6b |
ClRender::ClRender(ClContext &cl):
|
|
|
f83e6b |
cl(cl),
|
|
|
f83e6b |
contour_program(),
|
|
|
013f0c |
contour_draw_kernel(),
|
|
|
2517eb |
contour_draw_workgroup_size(),
|
|
|
f83e6b |
surface(),
|
|
|
013f0c |
paths_buffer(),
|
|
|
f83e6b |
mark_buffer(),
|
|
|
67876c |
surface_image(),
|
|
|
c7fa36 |
prev_event()
|
|
|
f83e6b |
{
|
|
|
b09c5d |
contour_program = cl.load_program("contour-fs.cl");
|
|
|
2517eb |
assert(contour_program);
|
|
|
2517eb |
|
|
|
013f0c |
contour_draw_kernel = clCreateKernel(contour_program, "draw", NULL);
|
|
|
013f0c |
assert(contour_draw_kernel);
|
|
|
2517eb |
|
|
|
2517eb |
cl.err |= clGetKernelWorkGroupInfo(
|
|
|
2517eb |
contour_draw_kernel,
|
|
|
2517eb |
cl.device,
|
|
|
2517eb |
CL_KERNEL_WORK_GROUP_SIZE,
|
|
|
2517eb |
sizeof(contour_draw_workgroup_size),
|
|
|
2517eb |
&contour_draw_workgroup_size,
|
|
|
2517eb |
NULL );
|
|
|
2517eb |
assert(!cl.err);
|
|
|
572d9c |
}
|
|
|
572d9c |
|
|
|
572d9c |
ClRender::~ClRender() {
|
|
|
f83e6b |
send_surface(NULL);
|
|
|
013f0c |
send_paths(NULL, 0);
|
|
|
013f0c |
clReleaseKernel(contour_draw_kernel);
|
|
|
f83e6b |
clReleaseProgram(contour_program);
|
|
|
f83e6b |
}
|
|
|
f83e6b |
|
|
|
f83e6b |
void ClRender::send_surface(Surface *surface) {
|
|
|
c7fa36 |
if (!surface && !this->surface) return;
|
|
|
f83e6b |
|
|
|
c7fa36 |
cl.err |= clFinish(cl.queue);
|
|
|
5890eb |
assert(!cl.err);
|
|
|
c7fa36 |
prev_event = NULL;
|
|
|
f83e6b |
|
|
|
f83e6b |
if (this->surface) {
|
|
|
f83e6b |
clReleaseMemObject(mark_buffer);
|
|
|
67876c |
clReleaseMemObject(surface_image);
|
|
|
f83e6b |
}
|
|
|
f83e6b |
|
|
|
f83e6b |
this->surface = surface;
|
|
|
f83e6b |
|
|
|
f83e6b |
if (this->surface) {
|
|
|
5890eb |
//Measure t("ClRender::send_surface");
|
|
|
f83e6b |
|
|
|
f83e6b |
mark_buffer = clCreateBuffer(
|
|
|
f83e6b |
cl.context, CL_MEM_READ_WRITE,
|
|
|
2517eb |
(surface->count() + 2)*sizeof(cl_int2), NULL,
|
|
|
2517eb |
&cl.err );
|
|
|
2517eb |
assert(!cl.err);
|
|
|
f83e6b |
assert(mark_buffer);
|
|
|
f83e6b |
|
|
|
2517eb |
char zero = 0;
|
|
|
2517eb |
cl.err |= clEnqueueFillBuffer(
|
|
|
2517eb |
cl.queue, mark_buffer,
|
|
|
2517eb |
&zero, 1,
|
|
|
2517eb |
0, surface->count()*sizeof(cl_int2),
|
|
|
c7fa36 |
0, NULL, NULL );
|
|
|
c7fa36 |
assert(!cl.err);
|
|
|
c7fa36 |
|
|
|
2517eb |
surface_image = clCreateBuffer(
|
|
|
2517eb |
cl.context, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR,
|
|
|
2517eb |
surface->count()*sizeof(Color), surface->data,
|
|
|
2517eb |
&cl.err );
|
|
|
2517eb |
assert(!cl.err);
|
|
|
2517eb |
assert(surface_image);
|
|
|
2517eb |
|
|
|
2517eb |
cl.err |= clSetKernelArg(contour_draw_kernel, 0, sizeof(surface->width), &surface->width);
|
|
|
2517eb |
cl.err |= clSetKernelArg(contour_draw_kernel, 1, sizeof(surface->width), &surface->height);
|
|
|
2517eb |
cl.err |= clSetKernelArg(contour_draw_kernel, 2, sizeof(mark_buffer), &mark_buffer);
|
|
|
013f0c |
cl.err |= clSetKernelArg(contour_draw_kernel, 3, sizeof(surface_image), &surface_image);
|
|
|
c7fa36 |
assert(!cl.err);
|
|
|
f83e6b |
|
|
|
c7fa36 |
cl.err |= clFinish(cl.queue);
|
|
|
5890eb |
assert(!cl.err);
|
|
|
f83e6b |
}
|
|
|
f83e6b |
}
|
|
|
f83e6b |
|
|
|
f83e6b |
Surface* ClRender::receive_surface() {
|
|
|
f83e6b |
if (surface) {
|
|
|
5890eb |
//Measure t("ClRender::receive_surface");
|
|
|
f83e6b |
|
|
|
2517eb |
cl.err |= clEnqueueReadBuffer(
|
|
|
c7fa36 |
cl.queue, surface_image, CL_FALSE,
|
|
|
2517eb |
0, surface->count()*sizeof(Color), surface->data,
|
|
|
6b0407 |
prev_event ? 1 : 0,
|
|
|
6b0407 |
prev_event ? &prev_event : NULL,
|
|
|
6b0407 |
NULL );
|
|
|
5890eb |
assert(!cl.err);
|
|
|
c7fa36 |
|
|
|
c7fa36 |
cl.err |= clFinish(cl.queue);
|
|
|
c7fa36 |
assert(!cl.err);
|
|
|
028154 |
prev_event = NULL;
|
|
|
f83e6b |
}
|
|
|
f83e6b |
return surface;
|
|
|
572d9c |
}
|
|
|
572d9c |
|
|
|
2517eb |
void ClRender::remove_paths() {
|
|
|
013f0c |
if (paths_buffer) {
|
|
|
2517eb |
cl.err |= clFinish(cl.queue);
|
|
|
2517eb |
assert(!cl.err);
|
|
|
2517eb |
prev_event = NULL;
|
|
|
2517eb |
|
|
|
013f0c |
clReleaseMemObject(paths_buffer);
|
|
|
013f0c |
paths_buffer = NULL;
|
|
|
f83e6b |
}
|
|
|
2517eb |
}
|
|
|
2517eb |
|
|
|
2517eb |
void ClRender::send_paths(const void *paths, int size) {
|
|
|
2517eb |
if (!paths_buffer && (!paths || size <= 0)) return;
|
|
|
2517eb |
|
|
|
2517eb |
remove_paths();
|
|
|
f83e6b |
|
|
|
013f0c |
if (paths && size > 0) {
|
|
|
c7fa36 |
//Measure t("ClRender::send_path");
|
|
|
f83e6b |
|
|
|
013f0c |
paths_buffer = clCreateBuffer(
|
|
|
2517eb |
cl.context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
|
|
|
2517eb |
size, const_cast<void*>(paths),</void*>
|
|
|
2517eb |
&cl.err );
|
|
|
5890eb |
assert(!cl.err);
|
|
|
2517eb |
assert(paths_buffer);
|
|
|
f83e6b |
|
|
|
2517eb |
cl.err |= clSetKernelArg(contour_draw_kernel, 4, sizeof(paths_buffer), &paths_buffer);
|
|
|
5890eb |
assert(!cl.err);
|
|
|
c7fa36 |
}
|
|
|
c7fa36 |
}
|
|
|
f83e6b |
|
|
|
013f0c |
void ClRender::draw() {
|
|
|
c7fa36 |
//Measure t("ClRender::contour");
|
|
|
f83e6b |
|
|
|
013f0c |
cl_event event = prev_event;
|
|
|
2517eb |
size_t count = contour_draw_workgroup_size;
|
|
|
b09c5d |
size_t group_size = count;
|
|
|
c7fa36 |
cl.err |= clEnqueueNDRangeKernel(
|
|
|
c7fa36 |
cl.queue,
|
|
|
013f0c |
contour_draw_kernel,
|
|
|
c7fa36 |
1,
|
|
|
2517eb |
NULL,
|
|
|
2517eb |
&count,
|
|
|
b09c5d |
&group_size,
|
|
|
013f0c |
event ? 1 : 0,
|
|
|
013f0c |
event ? &event : NULL,
|
|
|
c7fa36 |
&prev_event );
|
|
|
c7fa36 |
assert(!cl.err);
|
|
|
572d9c |
}
|
|
|
572d9c |
|
|
|
f29469 |
void ClRender::wait() {
|
|
|
f29469 |
if (prev_event) {
|
|
|
013f0c |
cl.err |= clWaitForEvents(1, &prev_event);
|
|
|
013f0c |
assert(!cl.err);
|
|
|
f29469 |
prev_event = NULL;
|
|
|
f29469 |
}
|
|
|
f29469 |
}
|
|
|
572d9c |
|
|
|
b09c5d |
|
|
|
b09c5d |
// ------------------------------------------------
|
|
|
b09c5d |
|
|
|
b09c5d |
|
|
|
b09c5d |
ClRender2::ClRender2(ClContext &cl):
|
|
|
b09c5d |
cl(cl),
|
|
|
b09c5d |
contour_program(),
|
|
|
b09c5d |
contour_reset_kernel(),
|
|
|
b09c5d |
contour_paths_kernel(),
|
|
|
b09c5d |
contour_draw_kernel(),
|
|
|
b09c5d |
surface(),
|
|
|
b09c5d |
points_count(),
|
|
|
b09c5d |
paths_buffer(),
|
|
|
b09c5d |
points_buffer(),
|
|
|
b09c5d |
samples_buffer(),
|
|
|
b09c5d |
surface_image(),
|
|
|
b09c5d |
prev_event()
|
|
|
b09c5d |
{
|
|
|
b09c5d |
contour_program = cl.load_program("contour-sort.cl");
|
|
|
b09c5d |
assert(contour_program);
|
|
|
b09c5d |
|
|
|
b09c5d |
contour_reset_kernel = clCreateKernel(contour_program, "reset", &cl.err);
|
|
|
b09c5d |
assert(!cl.err);
|
|
|
b09c5d |
assert(contour_reset_kernel);
|
|
|
b09c5d |
|
|
|
b09c5d |
contour_paths_kernel = clCreateKernel(contour_program, "paths", &cl.err);
|
|
|
b09c5d |
assert(!cl.err);
|
|
|
b09c5d |
assert(contour_paths_kernel);
|
|
|
b09c5d |
|
|
|
b09c5d |
contour_draw_kernel = clCreateKernel(contour_program, "draw", &cl.err);
|
|
|
b09c5d |
assert(!cl.err);
|
|
|
b09c5d |
assert(contour_draw_kernel);
|
|
|
b09c5d |
|
|
|
b09c5d |
samples_buffer = clCreateBuffer(
|
|
|
b09c5d |
cl.context, CL_MEM_READ_WRITE,
|
|
|
b09c5d |
1024*1024*1024, NULL,
|
|
|
b09c5d |
&cl.err );
|
|
|
b09c5d |
assert(!cl.err);
|
|
|
b09c5d |
assert(samples_buffer);
|
|
|
b09c5d |
|
|
|
b09c5d |
cl.err |= clSetKernelArg(contour_reset_kernel, 0, sizeof(samples_buffer), &samples_buffer);
|
|
|
b09c5d |
cl.err |= clSetKernelArg(contour_paths_kernel, 2, sizeof(samples_buffer), &samples_buffer);
|
|
|
b09c5d |
cl.err |= clSetKernelArg(contour_draw_kernel, 2, sizeof(samples_buffer), &samples_buffer);
|
|
|
b09c5d |
assert(!cl.err);
|
|
|
b09c5d |
}
|
|
|
b09c5d |
|
|
|
b09c5d |
ClRender2::~ClRender2() {
|
|
|
b09c5d |
remove_paths();
|
|
|
b09c5d |
remove_surface();
|
|
|
b09c5d |
|
|
|
b09c5d |
cl.err |= clReleaseMemObject(samples_buffer);
|
|
|
b09c5d |
assert(!cl.err);
|
|
|
b09c5d |
samples_buffer = NULL;
|
|
|
b09c5d |
|
|
|
b09c5d |
clReleaseKernel(contour_reset_kernel);
|
|
|
b09c5d |
clReleaseKernel(contour_paths_kernel);
|
|
|
b09c5d |
clReleaseKernel(contour_draw_kernel);
|
|
|
b09c5d |
clReleaseProgram(contour_program);
|
|
|
b09c5d |
}
|
|
|
b09c5d |
|
|
|
b09c5d |
void ClRender2::remove_surface() {
|
|
|
b09c5d |
wait();
|
|
|
b09c5d |
|
|
|
b09c5d |
if (surface) {
|
|
|
b09c5d |
cl.err |= clReleaseMemObject(surface_image);
|
|
|
b09c5d |
assert(!cl.err);
|
|
|
b09c5d |
surface = NULL;
|
|
|
b09c5d |
}
|
|
|
b09c5d |
}
|
|
|
b09c5d |
|
|
|
b09c5d |
void ClRender2::send_surface(Surface *surface) {
|
|
|
b09c5d |
if (!surface && !this->surface) return;
|
|
|
b09c5d |
|
|
|
b09c5d |
remove_surface();
|
|
|
b09c5d |
|
|
|
b09c5d |
assert(surface);
|
|
|
b09c5d |
this->surface = surface;
|
|
|
b09c5d |
|
|
|
b09c5d |
//Measure t("ClRender::send_surface");
|
|
|
b09c5d |
|
|
|
b09c5d |
surface_image = clCreateBuffer(
|
|
|
b09c5d |
cl.context, CL_MEM_READ_WRITE,
|
|
|
b09c5d |
surface->count()*sizeof(Color), NULL,
|
|
|
b09c5d |
&cl.err );
|
|
|
b09c5d |
assert(!cl.err);
|
|
|
b09c5d |
assert(surface_image);
|
|
|
b09c5d |
|
|
|
b09c5d |
cl.err |= clEnqueueWriteBuffer(
|
|
|
b09c5d |
cl.queue, surface_image, false,
|
|
|
b09c5d |
0, surface->count()*sizeof(Color), surface->data,
|
|
|
b09c5d |
0, NULL, NULL );
|
|
|
b09c5d |
assert(!cl.err);
|
|
|
b09c5d |
|
|
|
b09c5d |
cl.err |= clSetKernelArg(contour_paths_kernel, 0, sizeof(surface->width), &surface->width);
|
|
|
b09c5d |
cl.err |= clSetKernelArg(contour_paths_kernel, 1, sizeof(surface->height), &surface->height);
|
|
|
b09c5d |
cl.err |= clSetKernelArg(contour_draw_kernel, 0, sizeof(surface->width), &surface->width);
|
|
|
b09c5d |
cl.err |= clSetKernelArg(contour_draw_kernel, 1, sizeof(surface_image), &surface_image);
|
|
|
b09c5d |
assert(!cl.err);
|
|
|
b09c5d |
}
|
|
|
b09c5d |
|
|
|
b09c5d |
Surface* ClRender2::receive_surface() {
|
|
|
b09c5d |
if (surface) {
|
|
|
b09c5d |
//Measure t("ClRender::receive_surface");
|
|
|
b09c5d |
|
|
|
b09c5d |
cl.err |= clEnqueueReadBuffer(
|
|
|
b09c5d |
cl.queue, surface_image, CL_FALSE,
|
|
|
b09c5d |
0, surface->count()*sizeof(Color), surface->data,
|
|
|
b09c5d |
prev_event ? 1 : 0,
|
|
|
b09c5d |
prev_event ? &prev_event : NULL,
|
|
|
b09c5d |
NULL );
|
|
|
b09c5d |
assert(!cl.err);
|
|
|
b09c5d |
|
|
|
b09c5d |
wait();
|
|
|
b09c5d |
}
|
|
|
b09c5d |
return surface;
|
|
|
b09c5d |
}
|
|
|
b09c5d |
|
|
|
b09c5d |
void ClRender2::remove_paths() {
|
|
|
b09c5d |
wait();
|
|
|
b09c5d |
|
|
|
b09c5d |
if (paths_buffer) {
|
|
|
b09c5d |
cl.err |= clReleaseMemObject(paths_buffer);
|
|
|
b09c5d |
assert(!cl.err);
|
|
|
b09c5d |
paths_buffer = NULL;
|
|
|
b09c5d |
}
|
|
|
b09c5d |
|
|
|
b09c5d |
if (points_buffer) {
|
|
|
b09c5d |
cl.err |= clReleaseMemObject(points_buffer);
|
|
|
b09c5d |
assert(!cl.err);
|
|
|
b09c5d |
points_buffer = NULL;
|
|
|
b09c5d |
points_count = 0;
|
|
|
b09c5d |
}
|
|
|
b09c5d |
}
|
|
|
b09c5d |
|
|
|
b09c5d |
void ClRender2::send_paths(const Path *paths, int paths_count, const Point *points, int points_count) {
|
|
|
b09c5d |
remove_paths();
|
|
|
b09c5d |
|
|
|
b09c5d |
assert(paths);
|
|
|
b09c5d |
assert(paths_count > 0);
|
|
|
b09c5d |
|
|
|
b09c5d |
assert(points);
|
|
|
b09c5d |
assert(points_count > 0);
|
|
|
b09c5d |
|
|
|
b09c5d |
paths_buffer = clCreateBuffer(
|
|
|
b09c5d |
cl.context, CL_MEM_READ_ONLY,
|
|
|
b09c5d |
paths_count*sizeof(Path), NULL,
|
|
|
b09c5d |
&cl.err );
|
|
|
b09c5d |
assert(!cl.err);
|
|
|
b09c5d |
assert(paths_buffer);
|
|
|
b09c5d |
|
|
|
b09c5d |
cl.err |= clEnqueueWriteBuffer(
|
|
|
b09c5d |
cl.queue, paths_buffer, false,
|
|
|
b09c5d |
0, paths_count*sizeof(Path), paths,
|
|
|
b09c5d |
0, NULL, NULL );
|
|
|
b09c5d |
assert(!cl.err);
|
|
|
b09c5d |
|
|
|
b09c5d |
points_buffer = clCreateBuffer(
|
|
|
b09c5d |
cl.context, CL_MEM_READ_ONLY,
|
|
|
b09c5d |
points_count*sizeof(Point), NULL,
|
|
|
b09c5d |
&cl.err );
|
|
|
b09c5d |
assert(!cl.err);
|
|
|
b09c5d |
assert(points_buffer);
|
|
|
b09c5d |
this->points_count = points_count;
|
|
|
b09c5d |
|
|
|
b09c5d |
cl.err |= clEnqueueWriteBuffer(
|
|
|
b09c5d |
cl.queue, points_buffer, false,
|
|
|
b09c5d |
0, points_count*sizeof(Point), points,
|
|
|
b09c5d |
0, NULL, NULL );
|
|
|
b09c5d |
assert(!cl.err);
|
|
|
b09c5d |
|
|
|
b09c5d |
cl.err |= clSetKernelArg(contour_paths_kernel, 3, sizeof(points_buffer), &points_buffer);
|
|
|
b09c5d |
cl.err |= clSetKernelArg(contour_draw_kernel, 3, sizeof(paths_buffer), &paths_buffer);
|
|
|
b09c5d |
assert(!cl.err);
|
|
|
b09c5d |
|
|
|
b09c5d |
wait();
|
|
|
b09c5d |
}
|
|
|
b09c5d |
|
|
|
b09c5d |
void ClRender2::draw() {
|
|
|
b09c5d |
//Measure t("ClRender::contour");
|
|
|
b09c5d |
|
|
|
b09c5d |
cl_event prepare_event;
|
|
|
b09c5d |
cl_event paths_event;
|
|
|
b09c5d |
|
|
|
b09c5d |
size_t count = surface->height;
|
|
|
b09c5d |
cl.err |= clEnqueueNDRangeKernel(
|
|
|
b09c5d |
cl.queue,
|
|
|
b09c5d |
contour_reset_kernel,
|
|
|
b09c5d |
1,
|
|
|
b09c5d |
NULL,
|
|
|
b09c5d |
&count,
|
|
|
b09c5d |
NULL,
|
|
|
b09c5d |
prev_event ? 1 : 0,
|
|
|
b09c5d |
prev_event ? &prev_event : NULL,
|
|
|
b09c5d |
&prepare_event );
|
|
|
b09c5d |
assert(!cl.err);
|
|
|
b09c5d |
|
|
|
b09c5d |
count = points_count - 1;
|
|
|
b09c5d |
cl.err |= clEnqueueNDRangeKernel(
|
|
|
b09c5d |
cl.queue,
|
|
|
b09c5d |
contour_paths_kernel,
|
|
|
b09c5d |
1,
|
|
|
b09c5d |
NULL,
|
|
|
b09c5d |
&count,
|
|
|
b09c5d |
NULL,
|
|
|
b09c5d |
1,
|
|
|
b09c5d |
&prepare_event,
|
|
|
b09c5d |
&paths_event );
|
|
|
b09c5d |
assert(!cl.err);
|
|
|
b09c5d |
|
|
|
b09c5d |
count = surface->height;
|
|
|
b09c5d |
cl.err |= clEnqueueNDRangeKernel(
|
|
|
b09c5d |
cl.queue,
|
|
|
b09c5d |
contour_draw_kernel,
|
|
|
b09c5d |
1,
|
|
|
b09c5d |
NULL,
|
|
|
b09c5d |
&count,
|
|
|
b09c5d |
NULL,
|
|
|
b09c5d |
1,
|
|
|
b09c5d |
&paths_event,
|
|
|
b09c5d |
&prev_event );
|
|
|
b09c5d |
assert(!cl.err);
|
|
|
b09c5d |
}
|
|
|
b09c5d |
|
|
|
b09c5d |
void ClRender2::wait() {
|
|
|
b09c5d |
cl.err |= clFinish(cl.queue);
|
|
|
b09c5d |
assert(!cl.err);
|
|
|
b09c5d |
prev_event = NULL;
|
|
|
b09c5d |
}
|
|
|
b09c5d |
|
|
|
b09c5d |
|
|
|
105dfe |
// ------------------------------------------------
|
|
|
105dfe |
|
|
|
105dfe |
|
|
|
105dfe |
ClRender3::ClRender3(ClContext &cl):
|
|
|
105dfe |
cl(cl),
|
|
|
105dfe |
contour_program(),
|
|
|
105dfe |
contour_clear_kernel(),
|
|
|
105dfe |
contour_path_kernel(),
|
|
|
105dfe |
contour_fill_kernel(),
|
|
|
105dfe |
surface(),
|
|
|
105dfe |
points_buffer(),
|
|
|
105dfe |
mark_buffer(),
|
|
|
105dfe |
surface_image(),
|
|
|
105dfe |
prev_event()
|
|
|
105dfe |
{
|
|
|
105dfe |
contour_program = cl.load_program("contour-base.cl");
|
|
|
105dfe |
assert(contour_program);
|
|
|
105dfe |
|
|
|
105dfe |
contour_clear_kernel = clCreateKernel(contour_program, "clear", &cl.err);
|
|
|
105dfe |
assert(!cl.err);
|
|
|
105dfe |
assert(contour_clear_kernel);
|
|
|
105dfe |
|
|
|
105dfe |
contour_path_kernel = clCreateKernel(contour_program, "path", &cl.err);
|
|
|
105dfe |
assert(!cl.err);
|
|
|
105dfe |
assert(contour_path_kernel);
|
|
|
105dfe |
|
|
|
105dfe |
contour_fill_kernel = clCreateKernel(contour_program, "fill", &cl.err);
|
|
|
105dfe |
assert(!cl.err);
|
|
|
105dfe |
assert(contour_fill_kernel);
|
|
|
105dfe |
}
|
|
|
105dfe |
|
|
|
105dfe |
ClRender3::~ClRender3() {
|
|
|
105dfe |
send_points(NULL, 0);
|
|
|
105dfe |
send_surface(NULL);
|
|
|
105dfe |
|
|
|
105dfe |
clReleaseKernel(contour_path_kernel);
|
|
|
105dfe |
clReleaseKernel(contour_fill_kernel);
|
|
|
82f284 |
clReleaseKernel(contour_clear_kernel);
|
|
|
105dfe |
clReleaseProgram(contour_program);
|
|
|
105dfe |
}
|
|
|
105dfe |
|
|
|
105dfe |
void ClRender3::send_surface(Surface *surface) {
|
|
|
105dfe |
if (this->surface) {
|
|
|
105dfe |
wait();
|
|
|
105dfe |
cl.err |= clReleaseMemObject(surface_image);
|
|
|
105dfe |
assert(!cl.err);
|
|
|
105dfe |
surface_image = NULL;
|
|
|
105dfe |
}
|
|
|
105dfe |
|
|
|
105dfe |
this->surface = surface;
|
|
|
105dfe |
|
|
|
105dfe |
if (this->surface) {
|
|
|
105dfe |
//Measure t("ClRender::send_surface");
|
|
|
105dfe |
|
|
|
105dfe |
int zero_mark[4] = { };
|
|
|
105dfe |
|
|
|
105dfe |
surface_image = clCreateBuffer(
|
|
|
105dfe |
cl.context, CL_MEM_READ_WRITE,
|
|
|
105dfe |
surface->count()*sizeof(Color), NULL,
|
|
|
105dfe |
&cl.err );
|
|
|
105dfe |
assert(!cl.err);
|
|
|
105dfe |
assert(surface_image);
|
|
|
105dfe |
|
|
|
105dfe |
mark_buffer = clCreateBuffer(
|
|
|
105dfe |
cl.context, CL_MEM_READ_WRITE,
|
|
|
105dfe |
surface->count()*sizeof(zero_mark), NULL,
|
|
|
105dfe |
&cl.err );
|
|
|
105dfe |
assert(!cl.err);
|
|
|
105dfe |
assert(mark_buffer);
|
|
|
105dfe |
|
|
|
105dfe |
cl.err |= clEnqueueWriteBuffer(
|
|
|
105dfe |
cl.queue, surface_image, false,
|
|
|
105dfe |
0, surface->count()*sizeof(Color), surface->data,
|
|
|
105dfe |
0, NULL, NULL );
|
|
|
105dfe |
assert(!cl.err);
|
|
|
105dfe |
|
|
|
105dfe |
cl.err |= clSetKernelArg(contour_clear_kernel, 0, sizeof(surface->width), &surface->width);
|
|
|
105dfe |
cl.err |= clSetKernelArg(contour_clear_kernel, 1, sizeof(surface->height), &surface->height);
|
|
|
105dfe |
cl.err |= clSetKernelArg(contour_clear_kernel, 2, sizeof(mark_buffer), &mark_buffer);
|
|
|
105dfe |
assert(!cl.err);
|
|
|
105dfe |
|
|
|
105dfe |
size_t count = surface->count();
|
|
|
105dfe |
cl.err |= clEnqueueNDRangeKernel(
|
|
|
105dfe |
cl.queue, contour_clear_kernel,
|
|
|
105dfe |
1, NULL, &count, NULL,
|
|
|
105dfe |
0, NULL, NULL );
|
|
|
105dfe |
assert(!cl.err);
|
|
|
105dfe |
|
|
|
105dfe |
cl.err |= clSetKernelArg(contour_path_kernel, 0, sizeof(surface->width), &surface->width);
|
|
|
105dfe |
cl.err |= clSetKernelArg(contour_path_kernel, 1, sizeof(surface->height), &surface->height);
|
|
|
105dfe |
cl.err |= clSetKernelArg(contour_path_kernel, 2, sizeof(mark_buffer), &mark_buffer);
|
|
|
105dfe |
assert(!cl.err);
|
|
|
105dfe |
|
|
|
105dfe |
cl.err |= clSetKernelArg(contour_fill_kernel, 0, sizeof(surface->width), &surface->width);
|
|
|
105dfe |
cl.err |= clSetKernelArg(contour_fill_kernel, 1, sizeof(surface->height), &surface->height);
|
|
|
105dfe |
cl.err |= clSetKernelArg(contour_fill_kernel, 2, sizeof(mark_buffer), &mark_buffer);
|
|
|
105dfe |
cl.err |= clSetKernelArg(contour_fill_kernel, 3, sizeof(surface_image), &surface_image);
|
|
|
105dfe |
assert(!cl.err);
|
|
|
105dfe |
|
|
|
105dfe |
wait();
|
|
|
105dfe |
}
|
|
|
105dfe |
}
|
|
|
105dfe |
|
|
|
105dfe |
Surface* ClRender3::receive_surface() {
|
|
|
105dfe |
if (surface) {
|
|
|
105dfe |
//Measure t("ClRender::receive_surface");
|
|
|
105dfe |
|
|
|
105dfe |
cl.err |= clEnqueueReadBuffer(
|
|
|
105dfe |
cl.queue, surface_image, CL_FALSE,
|
|
|
105dfe |
0, surface->count()*sizeof(Color), surface->data,
|
|
|
105dfe |
prev_event ? 1 : 0,
|
|
|
105dfe |
prev_event ? &prev_event : NULL,
|
|
|
105dfe |
NULL );
|
|
|
105dfe |
assert(!cl.err);
|
|
|
105dfe |
|
|
|
105dfe |
wait();
|
|
|
105dfe |
}
|
|
|
105dfe |
return surface;
|
|
|
105dfe |
}
|
|
|
105dfe |
|
|
|
105dfe |
void ClRender3::send_points(const vec2f *points, int count) {
|
|
|
105dfe |
if (points_buffer) {
|
|
|
105dfe |
wait();
|
|
|
105dfe |
cl.err |= clReleaseMemObject(points_buffer);
|
|
|
105dfe |
assert(!cl.err);
|
|
|
105dfe |
points_buffer = NULL;
|
|
|
105dfe |
}
|
|
|
105dfe |
|
|
|
105dfe |
if (points && count > 0) {
|
|
|
105dfe |
points_buffer = clCreateBuffer(
|
|
|
105dfe |
cl.context, CL_MEM_READ_ONLY,
|
|
|
105dfe |
count*sizeof(vec2f), NULL,
|
|
|
105dfe |
&cl.err );
|
|
|
105dfe |
assert(!cl.err);
|
|
|
105dfe |
assert(points_buffer);
|
|
|
105dfe |
|
|
|
105dfe |
cl.err |= clEnqueueWriteBuffer(
|
|
|
105dfe |
cl.queue, points_buffer, false,
|
|
|
105dfe |
0, count*sizeof(vec2f), points,
|
|
|
105dfe |
0, NULL, NULL );
|
|
|
105dfe |
assert(!cl.err);
|
|
|
105dfe |
|
|
|
105dfe |
cl.err |= clSetKernelArg(contour_path_kernel, 3, sizeof(points_buffer), &points_buffer);
|
|
|
105dfe |
assert(!cl.err);
|
|
|
105dfe |
|
|
|
105dfe |
wait();
|
|
|
105dfe |
}
|
|
|
105dfe |
}
|
|
|
105dfe |
|
|
|
105dfe |
void ClRender3::draw(const Path &path) {
|
|
|
105dfe |
//Measure t("ClRender::contour");
|
|
|
105dfe |
|
|
|
105dfe |
assert(surface);
|
|
|
105dfe |
assert(points_buffer);
|
|
|
105dfe |
|
|
|
f14ea7 |
ContextRect bounds;
|
|
|
f14ea7 |
bounds.minx = max(1, path.bounds.minx);
|
|
|
f14ea7 |
bounds.maxx = min(surface->width, path.bounds.maxx);
|
|
|
f14ea7 |
bounds.miny = max(0, path.bounds.miny);
|
|
|
f14ea7 |
bounds.maxy = min(surface->height, path.bounds.maxy);
|
|
|
105dfe |
int invert_int = path.invert ? 1 : 0;
|
|
|
105dfe |
int evenodd_int = path.evenodd ? 1 : 0;
|
|
|
f14ea7 |
if ( bounds.minx >= bounds.maxx
|
|
|
f14ea7 |
|| bounds.miny >= bounds.maxy
|
|
|
f14ea7 |
|| path.begin >= path.end ) return;
|
|
|
105dfe |
|
|
|
105dfe |
cl.err |= clSetKernelArg(contour_path_kernel, 4, sizeof(path.begin), &path.begin);
|
|
|
82f284 |
cl.err |= clSetKernelArg(contour_path_kernel, 5, sizeof(path.end), &path.end);
|
|
|
f14ea7 |
cl.err |= clSetKernelArg(contour_path_kernel, 6, sizeof(bounds), &bounds);
|
|
|
105dfe |
assert(!cl.err);
|
|
|
105dfe |
|
|
|
f14ea7 |
cl.err |= clSetKernelArg(contour_fill_kernel, 1, sizeof(bounds.maxy), &bounds.maxy); // restrict height
|
|
|
105dfe |
cl.err |= clSetKernelArg(contour_fill_kernel, 4, sizeof(path.color), &path.color);
|
|
|
f14ea7 |
cl.err |= clSetKernelArg(contour_fill_kernel, 5, sizeof(bounds), &bounds);
|
|
|
f14ea7 |
cl.err |= clSetKernelArg(contour_fill_kernel, 6, sizeof(invert_int), &invert_int);
|
|
|
f14ea7 |
cl.err |= clSetKernelArg(contour_fill_kernel, 7, sizeof(evenodd_int), &evenodd_int);
|
|
|
105dfe |
assert(!cl.err);
|
|
|
105dfe |
|
|
|
105dfe |
|
|
|
105dfe |
cl_event path_event;
|
|
|
105dfe |
|
|
|
105dfe |
size_t group_size = 1;
|
|
|
105dfe |
|
|
|
105dfe |
size_t offset = path.begin;
|
|
|
105dfe |
size_t count = ((path.end - path.begin - 1)/group_size + 1)*group_size;
|
|
|
105dfe |
cl.err |= clEnqueueNDRangeKernel(
|
|
|
105dfe |
cl.queue,
|
|
|
105dfe |
contour_path_kernel,
|
|
|
105dfe |
1,
|
|
|
105dfe |
&offset,
|
|
|
105dfe |
&count,
|
|
|
105dfe |
NULL,//&group_size,
|
|
|
105dfe |
prev_event ? 1 : 0,
|
|
|
105dfe |
prev_event ? &prev_event : NULL,
|
|
|
105dfe |
&path_event );
|
|
|
105dfe |
assert(!cl.err);
|
|
|
105dfe |
|
|
|
f14ea7 |
offset = bounds.miny;
|
|
|
f14ea7 |
count = ((bounds.maxy - bounds.miny - 1)/group_size + 1)*group_size;
|
|
|
105dfe |
cl.err |= clEnqueueNDRangeKernel(
|
|
|
105dfe |
cl.queue,
|
|
|
105dfe |
contour_fill_kernel,
|
|
|
105dfe |
1,
|
|
|
105dfe |
&offset,
|
|
|
105dfe |
&count,
|
|
|
105dfe |
NULL,//&group_size,
|
|
|
105dfe |
1,
|
|
|
105dfe |
&path_event,
|
|
|
105dfe |
&prev_event );
|
|
|
105dfe |
assert(!cl.err);
|
|
|
105dfe |
}
|
|
|
105dfe |
|
|
|
105dfe |
void ClRender3::wait() {
|
|
|
105dfe |
cl.err |= clFinish(cl.queue);
|
|
|
105dfe |
assert(!cl.err);
|
|
|
105dfe |
prev_event = NULL;
|
|
|
105dfe |
}
|
|
|
105dfe |
|