|
|
@ -17,187 +17,187 @@ 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 |
|
|
|
// 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); |
|
|
|
} |
|
|
|
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(); |
|
|
|
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); |
|
|
|
|
|
|
|
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); |
|
|
|
} |
|
|
|
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(){ |
|
|
|
App a; |
|
|
|
|
|
|
|
NSAppWrapper app; |
|
|
|
|
|
|
|
app.create_window({ |
|
|
|
[&](ContextParameters){ |
|
|
|
a.initialize(); |
|
|
|
}, |
|
|
|
[&](ContextParameters){ |
|
|
|
a.draw(); |
|
|
|
}, |
|
|
|
nullptr |
|
|
|
}); |
|
|
|
|
|
|
|
app.run(); |
|
|
|
|
|
|
|
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; |
|
|
|
App a; |
|
|
|
|
|
|
|
NSAppWrapper app; |
|
|
|
|
|
|
|
app.create_window({ |
|
|
|
[&](ContextParameters){ |
|
|
|
a.initialize(); |
|
|
|
}, |
|
|
|
[&](ContextParameters){ |
|
|
|
a.draw(); |
|
|
|
}, |
|
|
|
nullptr |
|
|
|
}); |
|
|
|
|
|
|
|
app.run(); |
|
|
|
|
|
|
|
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; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|