You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
212 lines
5.2 KiB
212 lines
5.2 KiB
#include <cl2.hpp>
|
|
#include <NSWrapper.hpp>
|
|
#include <NSGLWrapper.hpp>
|
|
#include <png.hpp>
|
|
|
|
#include <moggle/core/gl.hpp>
|
|
#include <moggle/core/shader.hpp>
|
|
#include <moggle/core/vao.hpp>
|
|
#include <moggle/core/vbo.hpp>
|
|
|
|
#include <OpenGL/OpenGL.h>
|
|
#include <OpenGL/CGLDevice.h>
|
|
#include <OpenCL/opencl.h>
|
|
|
|
#include <vector>
|
|
#include <iostream>
|
|
#include <fstream>
|
|
#include <cassert>
|
|
#include <memory>
|
|
|
|
using namespace std;
|
|
|
|
std::string slurp(std::string file_name){
|
|
std::ifstream f(file_name);
|
|
if (!f) throw std::runtime_error(std::string("Unable to open file: ") + file_name);
|
|
return {std::istreambuf_iterator<char>(f), std::istreambuf_iterator<char>()};
|
|
}
|
|
|
|
struct Vertex{
|
|
moggle::vector3<GLfloat> position;
|
|
moggle::vector2<GLfloat> tex_coord;
|
|
};
|
|
|
|
const Vertex quad[] = {
|
|
// x y z u v
|
|
{{ 1, -1, 0}, {1, 0}},
|
|
{{-1, -1, 0}, {0, 0}},
|
|
{{ 1, 1, 0}, {1, 1}},
|
|
{{-1, 1, 0}, {0, 1}}
|
|
};
|
|
|
|
struct App {
|
|
moggle::shader_program program;
|
|
moggle::vao v;
|
|
moggle::vbo<Vertex> quad_vbo;
|
|
|
|
// ptrs to postpone construction, should clean this up
|
|
unique_ptr<cl::Context> cl_context;
|
|
unique_ptr<cl::Device> cl_device;
|
|
unique_ptr<cl::CommandQueue> cl_queue;
|
|
unique_ptr<cl::ImageGL> cl_image;
|
|
unique_ptr<cl::Program> cl_program;
|
|
unique_ptr<KernelOp> k_initialize;
|
|
unique_ptr<KernelOp> k_update;
|
|
|
|
float time = 0;
|
|
GLuint gl_texture = 0;
|
|
size_t W = 128;
|
|
size_t H = 128;
|
|
|
|
enum {
|
|
POS_ATTR,
|
|
TEX_ATTR
|
|
};
|
|
|
|
void load_shader(){
|
|
auto vs = moggle::shader::from_file(moggle::shader_type::vertex, "Fractal.vsh");
|
|
auto fs = moggle::shader::from_file(moggle::shader_type::fragment, "Fractal.fsh");
|
|
|
|
program.attach(vs);
|
|
program.attach(fs);
|
|
|
|
program.bind_attribute(POS_ATTR, "position");
|
|
program.bind_attribute(TEX_ATTR, "tex_coord");
|
|
|
|
program.link();
|
|
}
|
|
|
|
void create_vao(){
|
|
v.bind();
|
|
quad_vbo.bind(GL_ARRAY_BUFFER);
|
|
quad_vbo.data(quad);
|
|
|
|
moggle::gl::enable_vertex_attribute_array(POS_ATTR);
|
|
moggle::gl::enable_vertex_attribute_array(TEX_ATTR);
|
|
|
|
v.attribute(POS_ATTR, quad_vbo, &Vertex::position);
|
|
v.attribute(TEX_ATTR, quad_vbo, &Vertex::tex_coord);
|
|
}
|
|
|
|
GLuint create_gl_texture(){
|
|
GLuint tex = 0;
|
|
moggle::gl::active_texture(GL_TEXTURE0);
|
|
moggle::gl::generate_textures(1, &tex);
|
|
moggle::gl::bind_texture(GL_TEXTURE_2D, tex);
|
|
moggle::gl::texture_image_2d(GL_TEXTURE_2D, 0, GL_RGBA, W, H, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
|
moggle::gl::texture_parameter_i(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
moggle::gl::texture_parameter_i(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
return tex;
|
|
}
|
|
|
|
// shared with opengl
|
|
void initialize_cl(GLContext & gl_context){
|
|
CGLShareGroupObj sharegroup = CGLGetShareGroup(gl_context.ctx);
|
|
|
|
cl_int err = 0;
|
|
cl_context_properties properties[] = {
|
|
CL_CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE, (cl_context_properties)sharegroup,
|
|
0
|
|
};
|
|
|
|
cl_context = make_unique<cl::Context>(CL_DEVICE_TYPE_CPU, properties, nullptr, nullptr, &err);
|
|
cl::checky(err);
|
|
|
|
cl_device = make_unique<cl::Device>(cl_context->getInfo<CL_CONTEXT_DEVICES>().front());
|
|
|
|
cl_queue = make_unique<cl::CommandQueue>(*cl_context, *cl_device, 0, &err);
|
|
cl::checky(err);
|
|
}
|
|
|
|
void load_cl_kernels(){
|
|
cl_int err = 0;
|
|
|
|
// build the program
|
|
cl_program = make_unique<cl::Program>(*cl_context, slurp("Kernel.cl"), true, &err);
|
|
cout << cl_program->getBuildInfo<CL_PROGRAM_BUILD_LOG>(*cl_device) << std::endl;
|
|
|
|
cl::checky(err);
|
|
cout << *cl_program << endl;
|
|
|
|
// grab the kernels
|
|
k_initialize = make_unique<KernelOp>(*cl_program, "initialize", &err);
|
|
cl::checky(err);
|
|
k_update = make_unique<KernelOp>(*cl_program, "update", &err);
|
|
cl::checky(err);
|
|
}
|
|
|
|
void initialize(GLContext & gl_context){
|
|
// gl part
|
|
load_shader();
|
|
create_vao();
|
|
gl_texture = create_gl_texture();
|
|
|
|
// cl part
|
|
initialize_cl(gl_context);
|
|
load_cl_kernels();
|
|
|
|
cl_int err = 0;
|
|
|
|
// obtain cl memory object
|
|
cl_image = make_unique<cl::ImageGL>(*cl_context, CL_MEM_READ_WRITE, GL_TEXTURE_2D, 0, gl_texture, &err);
|
|
cl::checky(err);
|
|
std::cout << *cl_image << std::endl;
|
|
|
|
cl::checky((*k_initialize)(*cl_queue, W, H, W, H, *cl_image));
|
|
// no need for finish here, as we will always do a finish in draw(), before gl calls
|
|
}
|
|
|
|
void draw(){
|
|
time += 1/60.0f;
|
|
|
|
cl::checky((*k_update)(*cl_queue, W, H, W, H, *cl_image, *cl_image));
|
|
cl::checky(cl_queue->finish());
|
|
|
|
moggle::gl::clear_color(0.65f, 0.65f, 0.65f, 1.0f);
|
|
moggle::gl::clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
|
|
program.use();
|
|
|
|
moggle::gl::bind_texture(GL_TEXTURE_2D, gl_texture);
|
|
program.uniform<GLint>("tex").set(0);
|
|
|
|
v.bind();
|
|
|
|
moggle::gl::draw_arrays(GL_TRIANGLE_STRIP, 0, 4);
|
|
}
|
|
|
|
void resize(size_t w, size_t h){
|
|
W = w;
|
|
H = h;
|
|
|
|
gl_texture = create_gl_texture();
|
|
|
|
cl_int err = 0;
|
|
cl_image = make_unique<cl::ImageGL>(*cl_context, CL_MEM_READ_WRITE, GL_TEXTURE_2D, 0, gl_texture, &err);
|
|
cl::checky(err);
|
|
std::cout << *cl_image << std::endl;
|
|
cl::checky((*k_initialize)(*cl_queue, W, H, W, H, *cl_image));
|
|
}
|
|
};
|
|
|
|
int main() {
|
|
App a;
|
|
|
|
NSAppWrapper app;
|
|
|
|
app.create_window({
|
|
[&](ContextParameters ctxp){
|
|
a.initialize(ctxp.context);
|
|
},
|
|
[&](ContextParameters){
|
|
a.draw();
|
|
},
|
|
[&](ContextParameters, CGFloat w, CGFloat h){
|
|
a.resize(size_t(floor(w)), size_t(floor(h)));
|
|
}
|
|
});
|
|
|
|
app.run();
|
|
}
|
|
|
|
|
|
|