diff --git a/include/Decoder.h b/include/Decoder.h index 8304bf6..659dc7a 100644 --- a/include/Decoder.h +++ b/include/Decoder.h @@ -1,6 +1,7 @@ #pragma once #include - +#include +#include #include #include #include @@ -12,7 +13,7 @@ struct pattern_info { std::string comments; sf::Vector2i dimensions; - char *pattern; + char *nodes; }; @@ -24,11 +25,11 @@ public: ~Decoder(); pattern_info decodePattern(std::string pattern); - std::vector getPatternList(); + std::vector getPatternList(); private: - std::vector pattern_list; + std::vector pattern_list; }; \ No newline at end of file diff --git a/include/OpenCL.h b/include/OpenCL.h index 3975d30..7a1d17c 100644 --- a/include/OpenCL.h +++ b/include/OpenCL.h @@ -56,6 +56,8 @@ public: // Have CL create and manage the texture for the image buffer. Access Type is the read/write specifier required by OpenCL bool create_image_buffer(std::string buffer_name, sf::Vector2i size, sf::Vector2f position, cl_int access_type); + bool map_buffer(std::string buffer_name, unsigned int size, void* data = nullptr); + // Create a buffer with CL_MEM_READ_ONLY and CL_MEM_COPY_HOST_PTR int create_buffer(std::string buffer_name, cl_uint size, void* data); diff --git a/kernels/conways.cl b/kernels/conways.cl index 48e9292..8c21f1b 100644 --- a/kernels/conways.cl +++ b/kernels/conways.cl @@ -21,11 +21,10 @@ __kernel void conways ( size_t x_pixel = get_global_id(0); size_t y_pixel = get_global_id(1); - - //printf(": %i", y_pixel); - int2 pixel = (int2)(x_pixel, y_pixel); + // if (pixel.x == 0 && pixel.y == 0) + // printf("Run"); //if (pixel.x > 1800) // printf("%i, %i", pixel.x, pixel.y); @@ -39,6 +38,8 @@ __kernel void conways ( if (*buffer_flip == 0){ + // if (pixel.x == 0 && pixel.y == 0) + // printf("Buffer 0"); // Top val = pixel_to_index(*image_res, (int2)(pixel.x, pixel.y+1)); if (val >= 0) @@ -89,7 +90,7 @@ __kernel void conways ( second_node_buffer[base] = 0; } - } else { + } else if (*buffer_flip == 1) { // Top val = pixel_to_index(*image_res, (int2)(pixel.x, pixel.y+1)); @@ -140,5 +141,15 @@ __kernel void conways ( //write_imagef(image, pixel, mix(read_imagef(image, pixel), flavor, 0.01f)); first_node_buffer[base] = 0; } + } else{ + int base = pixel_to_index(*image_res, pixel); + if (first_node_buffer[base]){ + write_imagef(image, pixel, alive); + first_node_buffer[base] = 1; + } else { + write_imagef(image, pixel, dead); + //write_imagef(image, pixel, mix(read_imagef(image, pixel), flavor, 0.01f)); + first_node_buffer[base] = 0; + } } } diff --git a/src/Decoder.cpp b/src/Decoder.cpp index c838879..3bae600 100644 --- a/src/Decoder.cpp +++ b/src/Decoder.cpp @@ -6,7 +6,12 @@ Decoder::Decoder() { std::cout << "Loading patterns..."; for (std::experimental::filesystem::directory_entry p : std::experimental::filesystem::directory_iterator("../assets/patterns/")) { - pattern_list.push_back(p.path().generic_string()); + // good lord c++ + std::string s = p.path().generic_string(); + const char* char_shit = new const char[s.size() + 1]; + memcpy((void*)char_shit, s.c_str(), s.size()+1); + + pattern_list.push_back(char_shit); } std::cout << "Done" << std::endl; @@ -20,124 +25,130 @@ pattern_info Decoder::decodePattern(std::string pattern) { pattern_info info; - //for (int i = 0; i < dimensions.x * dimensions.y; i++) { - // nodes[i] = 0; - //} - - - //std::ifstream file(filename); - - //if (!file.is_open()) { - // std::cout << "unable to open file" << std::endl; - // return info; - //} - - //for (std::string line; std::getline(file, line); ) - //{ - // // Grab the header comments - // if (line[0] == '#') { - - // std::string data = line.substr(3, line.size() - 3); - - // switch (line[1]) { - - // case 'C': { - // info.comments += data; - // break; - // } - // case 'O': { - // info.author += data; - // break; - // } - // case 'N': { - // info.title += data; - // break; - // } - // default: { - // std::cout << "Case : " << line[1] << " not supported" << std::endl; - // } - // } - // } - - // // grab the dimensions - // else if (line[0] == 'x') { - - // // Naively assume that it is in the exact form "x = , y = ," - // std::stringstream ss(line); - - // std::string temp; - // ss >> temp >> temp >> temp; - // info.dimensions.x = std::stoi(temp.substr(0, temp.size() - 1)); - - // ss >> temp >> temp >> temp; - // info.dimensions.y = std::stoi(temp.substr(0, temp.size() - 1)); - // } - - // // Decode the RLE - // else { - - // std::vector> grid; - - // std::stringstream ss(line); - // std::string token; - - // while (std::getline(ss, token, '$')) { - - // std::vector char_line; - // unsigned int token_pos = 0; - // std::string tmp; - - // while (token_pos < token.size()) { - - // char status = -1; - // if (token[token_pos] == 'b') - // status = 0; - // else if (token[token_pos] == 'o') - // status = 1; - // else if (token[token_pos] == '!') - // break; - // else - // tmp += token[token_pos]; - - // token_pos++; - - // if (status >= 0) { - // if (tmp.empty()) { - // char_line.push_back(status); - // } - // else { - // int count = std::stoi(tmp); - // for (int i = 0; i < count; i++) { - // char_line.push_back(status); - // } - // tmp.clear(); - // } - // } - - // } - - // grid.push_back(char_line); - // } - - // int y_mod = 200; - // int x_mod = 200; - // for (int y = 0; y < grid.size(); y++) { - // for (int x = 0; x < grid.at(y).size(); x++) { - // nodes[(y + y_mod) * dimensions.x + (x + x_mod)] = grid.at(y).at(x); - // } - // } - - // } - //} - - //std::cout << info.author << std::endl; - //std::cout << info.title << std::endl; - //std::cout << info.comments << std::endl; + std::ifstream file(pattern); + + if (!file.is_open()) { + std::cout << "unable to open file" << std::endl; + return info; + } + + std::vector> grid; + std::stringstream rle_stream; + + for (std::string line; std::getline(file, line); ) + { + // Grab the header comments + if (line[0] == '#') { + + std::string data = line.substr(3, line.size() - 3); + + switch (line[1]) { + + case 'C': { + info.comments += data; + break; + } + case 'O': { + info.author += data; + break; + } + case 'N': { + info.title += data; + break; + } + default: { + std::cout << "Case : " << line[1] << " not supported" << std::endl; + } + + } + } + + // grab the dimensions + else if (line[0] == 'x') { + + // Naively assume that it is in the exact form "x = , y = ," + std::stringstream ss(line); + + std::string temp; + ss >> temp >> temp >> temp; + info.dimensions.x = std::stoi(temp.substr(0, temp.size() - 1)); + + ss >> temp >> temp >> temp; + info.dimensions.y = std::stoi(temp.substr(0, temp.size() - 1)); + } + + // Decode the RLE + else { + + rle_stream << line; + std::string token; + + while (std::getline(rle_stream, token, '$')) { + + if (rle_stream.eof()) { + + if (token.back() != '!') { + rle_stream.seekg(-token.size(), std::ios::end); + break; + } + } + + std::vector char_line; + unsigned int token_pos = 0; + std::string tmp; + + while (token_pos < token.size()) { + + char status = -1; + if (token[token_pos] == 'b') + status = 0; + else if (token[token_pos] == 'o') + status = 1; + else if (token[token_pos] == '!') + break; + else + tmp += token[token_pos]; + + token_pos++; + + if (status >= 0) { + if (tmp.empty()) { + char_line.push_back(status); + } + else { + int count = std::stoi(tmp); + for (int i = 0; i < count; i++) { + char_line.push_back(status); + } + tmp.clear(); + } + } + + } + + char_line.resize(info.dimensions.x); + grid.push_back(char_line); + } + + rle_stream.clear(); + + } + } + + info.dimensions = sf::Vector2i(grid.at(0).size(), grid.size()); + info.nodes = new char[info.dimensions.x * info.dimensions.y]; + + for (int y = 0; y < grid.size(); y++) { + for (int x = 0; x < grid.at(y).size(); x++) { + info.nodes[y * info.dimensions.x + x] = grid.at(y).at(x); + } + } + file.close(); return info; } -std::vector Decoder::getPatternList() { +std::vector Decoder::getPatternList() { return pattern_list; diff --git a/src/OpenCL.cpp b/src/OpenCL.cpp index e36c194..bb36714 100644 --- a/src/OpenCL.cpp +++ b/src/OpenCL.cpp @@ -279,6 +279,22 @@ bool OpenCL::create_image_buffer(std::string buffer_name, sf::Vector2i size, sf: return true; } +bool OpenCL::map_buffer(std::string buffer_name, unsigned int size, void* data) { + + data = clEnqueueMapBuffer(command_queue, + buffer_map.at(buffer_name), + true, + CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, + 0, + size,0,nullptr,nullptr,&error + ); + + if (vr_assert(error, "clEnqueueMapBuffer")) + return -1; + + return true; +} + int OpenCL::create_buffer(std::string buffer_name, cl_uint size, void* data) { if (buffer_map.count(buffer_name) > 0) { diff --git a/src/main.cpp b/src/main.cpp index c489444..f0da098 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -53,141 +53,34 @@ void generate_nodes(sf::Uint8* nodes) { } -struct rle_info { +void copy_pattern (sf::Uint8* nodes, sf::Vector2i dimensions, sf::Vector2u position, pattern_info pattern) { - std::string title; - std::string author; - std::string comments; - sf::Vector2i dimensions; + for (int x = 0; x < pattern.dimensions.x; x++) { + for (int y = 0; y < pattern.dimensions.y; y++) { -}; - -rle_info load_rle(sf::Uint8* nodes, sf::Vector2i dimensions, std::string filename) { - - rle_info info; - - for (int i = 0; i < dimensions.x * dimensions.y; i++) { - nodes[i] = 0; - } - - - std::ifstream file(filename); - - if (!file.is_open()) { - std::cout << "unable to open file" << std::endl; - return info; - } - - for (std::string line; std::getline(file, line); ) - { - // Grab the header comments - if (line[0] == '#') { - - std::string data = line.substr(3, line.size() - 3); - - switch (line[1]) { + if (position.x + pattern.dimensions.x < dimensions.x || + position.y + pattern.dimensions.y < dimensions.y ) { - case 'C': { - info.comments += data; - break; - } - case 'O': { - info.author += data; - break; - } - case 'N': { - info.title += data; - break; - } - default : { - std::cout << "Case : " << line[1] << " not supported" << std::endl; - } + nodes[(y+position.y) * dimensions.x + (x+position.x)] = pattern.nodes[y * pattern.dimensions.x + x]; } } - - // grab the dimensions - else if (line[0] == 'x') { - - // Naively assume that it is in the exact form "x = , y = ," - std::stringstream ss(line); - - std::string temp; - ss >> temp >> temp >> temp; - info.dimensions.x = std::stoi(temp.substr(0, temp.size() - 1)); - - ss >> temp >> temp >> temp; - info.dimensions.y = std::stoi(temp.substr(0, temp.size() - 1)); - } - - // Decode the RLE - else { - - std::vector> grid; - - std::stringstream ss(line); - std::string token; - - while (std::getline(ss, token, '$')) { - - std::vector char_line; - unsigned int token_pos = 0; - std::string tmp; - - while (token_pos < token.size()) { - - char status = -1; - if (token[token_pos] == 'b') - status = 0; - else if (token[token_pos] == 'o') - status = 1; - else if (token[token_pos] == '!') - break; - else - tmp += token[token_pos]; - - token_pos++; - - if (status >= 0) { - if (tmp.empty()) { - char_line.push_back(status); - } - else { - int count = std::stoi(tmp); - for (int i = 0; i < count; i++) { - char_line.push_back(status); - } - tmp.clear(); - } - } - - } - - grid.push_back(char_line); - } - - int y_mod = 200; - int x_mod = 200; - for (int y = 0; y < grid.size(); y++) { - for (int x = 0; x < grid.at(y).size(); x++) { - nodes[(y+y_mod) * dimensions.x + (x+x_mod)] = grid.at(y).at(x); - } - } - - } } +} - std::cout << info.author << std::endl; - std::cout << info.title << std::endl; - std::cout << info.comments << std::endl; - - return info; +void clear_nodes(sf::Uint8 *nodes, sf::Vector2i dimensions) { + for (int i = 0; i < dimensions.x * dimensions.y; i++) { + nodes[i] = 0; + } } int main() { srand(time(NULL)); + Decoder d; + std::vector pattern_list = d.getPatternList(); + sf::RenderWindow window(sf::VideoMode(WINDOW_X, WINDOW_Y), "conways-game-of-life-opencl"); int simulation_speed = 100; @@ -231,7 +124,6 @@ int main() { sf::Clock sf_delta_clock; fps_counter render_fps; - fps_counter physic_fps; int c = 0; @@ -273,19 +165,14 @@ int main() { while (accumulator_time >= physic_step) { // While the frame has sim time, update accumulator_time -= physic_step; - physic_time += physic_step; - //physic_fps.frame(accumulator_time); - - + physic_time += physic_step; } - cl.run_kernel("conways", image_resolution); ImGui::SFML::Update(window, sf_delta_clock.restart()); render_fps.frame(delta_time); - window.clear(sf::Color::White); - cl.draw(&window); + window.clear(sf::Color::White); ImGui::Begin("Sim"); @@ -293,37 +180,58 @@ int main() { if (ImGui::SliderInt("Simulation Speed", &simulation_speed, 30, 500)) { window.setFramerateLimit(simulation_speed); } + if (ImGui::Button("One shot")) { + + std::cout << "sim" << std::endl; - if (ImGui::Button("Rerun")) { - generate_nodes(nodes); + /*std::cout << buffer_flip << std::endl; + cl.map_buffer("buffer_flip", sizeof(char), &buffer_flip);*/ + } + cl.run_kernel("conways", image_resolution); + cl.draw(&window); + if (buffer_flip == 1) + buffer_flip = 0; + else + buffer_flip = 1; + + ImGui::Columns(2); + + if (ImGui::Button("Load Pattern")) { + clear_nodes(nodes, sf::Vector2i(WINDOW_X, WINDOW_Y)); + pattern_info p = d.decodePattern(pattern_list.at(c)); + copy_pattern(nodes, sf::Vector2i(WINDOW_X, WINDOW_Y), sf::Vector2u(100, 300), p); cl.create_buffer("first_node_buffer", WINDOW_X * WINDOW_Y, (void*)nodes, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR); cl.create_buffer("second_node_buffer", WINDOW_X * WINDOW_Y, (void*)nodes, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR); cl.set_kernel_arg("conways", 2, "first_node_buffer"); cl.set_kernel_arg("conways", 3, "second_node_buffer"); } - const char* l[] = { "Apple", "Banana", "Cherry", "Kiwi", "Mango", "Orange", "Pineapple", "Strawberry", "Watermelon" }; - - if(ImGui::ListBox("asdf", &c, l, 9)) { + if (ImGui::ListBox("", &c, pattern_list.data(), pattern_list.size(), 30)) { } + ImGui::NextColumn(); + + if (ImGui::Button("Rerun")) { + generate_nodes(nodes); + cl.create_buffer("first_node_buffer", WINDOW_X * WINDOW_Y, (void*)nodes, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR); + cl.create_buffer("second_node_buffer", WINDOW_X * WINDOW_Y, (void*)nodes, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR); + cl.set_kernel_arg("conways", 2, "first_node_buffer"); + cl.set_kernel_arg("conways", 3, "second_node_buffer"); + } ImGui::End(); render_fps.draw(); - physic_fps.draw(); ImGui::Render(); + - if (buffer_flip == 1) - buffer_flip = 0; - else - buffer_flip = 1; - + + // ImGui screws stuff up after the render, rendering a drawable resets it window.draw(sf::CircleShape(0)); window.display();