Mandelbrot in OpenGL and something else in OpenCL
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.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

216 lines
5.2 KiB

//
// main.cpp
// XcodeOpenCL
//
// Created by Joshua Moerman on 28/03/14.
//
//
#include "cl2.hpp"
#include "NSWrapper.hpp"
#include "../../CodeTA/ImageStreams/include/png.hpp"
#include <OpenGL/gl3.h>
#include <vector>
#include <iostream>
#include <fstream>
#include <sstream>
#include <cassert>
#include <cmath>
using namespace std;
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
const GLfloat quad[] = {
// x y z, r g b
1, -1, 0, 1, 0, 0,
-1, -1, 0, 0, 1, 0,
1, 1, 0, 0, 0, 1,
-1, 1, 0, 1, 1, 1
};
static void check_shader(GLuint s){
GLint logLength;
glGetShaderiv(s, GL_INFO_LOG_LENGTH, &logLength);
if (logLength > 0) {
GLchar *log = (GLchar *)malloc(logLength);
glGetShaderInfoLog(s, logLength, &logLength, log);
std::cout << "Shader compile log:\n%s" << log << std::endl;
free(log);
}
}
string slurp(string filename) {
ifstream in(filename);
stringstream sstr;
sstr << in.rdbuf();
return sstr.str();
}
struct App {
float time;
GLuint program;
GLint uniform;
GLuint vao;
GLuint posBufferName;
void initialize(){
time = 0;
program = glCreateProgram();
auto v_source_str = slurp("Fractal.vsh");
auto v_source = v_source_str.c_str();
GLuint v = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(v, 1, &v_source, NULL);
glCompileShader(v);
check_shader(v);
auto f_source_str = slurp("Fractal.fsh");
auto f_source = f_source_str.c_str();
GLuint f = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(f, 1, &f_source, NULL);
glCompileShader(f);
check_shader(f);
glAttachShader(program, v);
glAttachShader(program, f);
glBindAttribLocation(program, 0, "position");
glBindAttribLocation(program, 1, "color");
glLinkProgram(program);
uniform = glGetUniformLocation(program, "rotation");
glDetachShader(program, v);
glDeleteShader(v);
glDetachShader(program, f);
glDeleteShader(f);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glGenBuffers(1, &posBufferName);
glBindBuffer(GL_ARRAY_BUFFER, posBufferName);
glBufferData(GL_ARRAY_BUFFER, 4*6*4, quad, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6*4, BUFFER_OFFSET(0));
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6*4, BUFFER_OFFSET(3*4));
}
void draw(){
time += 1/60.0f;
glClearColor(0.65f, 0.65f, 0.65f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(program);
glUniform1f(uniform, time);
glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
};
int main(){
const bool mandelbrot = false;
if(mandelbrot) {
App a;
NSAppWrapper app;
app.create_window({
[&](ContextParameters){
a.initialize();
},
[&](ContextParameters){
a.draw();
},
nullptr
});
app.run();
return 0;
}
// else, this other weird thing
auto context = cl::Context::getDefault();
cout << context << endl;
cl_int err = 0;
// build the program
auto KernelSource = slurp("Kernel.cl");
cl::Program program(context, {KernelSource.c_str(), KernelSource.size()}, true, &err);
check(err);
cout << program << endl;
// grab the kernel
KernelOp kernel(program, "square", &err);
check(err);
// create a queue
cl::CommandQueue queue(context, context.getInfo<CL_CONTEXT_DEVICES>().front());
// make a lot of data
constexpr size_t W = 1280 * 4;
constexpr size_t H = 800 * 4;
std::vector<cl_float> input_vector(W*H);
for(int y = 0; y < H; ++y){
for(int x = 0; x < W; ++x){
input_vector[x + W*y] = 10 * ((x / double(W) - 0.5) + 1.3371337*(y / double(H) - 0.5));
}
}
// transfer data into buffers
cl::Buffer input(context, input_vector.begin(), input_vector.end(), false, true);
int r = 80, g = 40, b = 20;
// DO IT (in place)
for(int i = 0; i < r; ++i){
check(kernel(queue, W, H, input, W, input));
}
// read back
queue.finish();
auto red = input_vector;
// DO IT (in place)
for(int i = 0; i < g; ++i){
check(kernel(queue, W, H, input, W, input));
}
// read back
queue.finish();
auto green = input_vector;
// DO IT (in place)
for(int i = 0; i < b; ++i){
check(kernel(queue, W, H, input, W, input));
}
// read back
queue.finish();
auto& blue = input_vector;
// test
cout << "opencl is done" << endl;
png::ostream<> image(W, H, "test.png");
for(int i = 0; i < red.size(); ++i){
image << png::ostream<>::pixel(blue[i], red[i], green[i]);
}
cout << "png is saved" << endl;
}