Slime-Simulation/src/main.cpp

316 lines
10 KiB
C++
Raw Normal View History

2021-10-17 21:59:21 +00:00
#include <SDL2/SDL.h>
#define CL_HPP_TARGET_OPENCL_VERSION 200
#include <CL/opencl.hpp>
2021-10-17 21:59:21 +00:00
#include <iostream>
2021-10-18 04:37:41 +00:00
#include <vector>
#include <chrono>
#include <math.h>
#include <stdlib.h>
#include <time.h>
#include <sstream>
#include <fstream>
2021-10-18 04:37:41 +00:00
struct Agent
2021-10-18 04:37:41 +00:00
{
float x,y,direction;
};
bool get_source(std::string* source);
unsigned long long sys_time_us();
2021-10-17 21:59:21 +00:00
int main(int argc, char* argv[])
{
2021-10-18 04:37:41 +00:00
srand(time(0));
uint32_t u32_width, u32_height;
uint32_t u32_dimensions[2];
2021-10-17 21:59:21 +00:00
if (argc == 1)
{
u32_width = u32_height = 300;
2021-10-17 21:59:21 +00:00
}
else
{
u32_width = atoi(argv[1]);
u32_height = atoi(argv[2]);
2021-10-17 21:59:21 +00:00
}
int i_size = u32_width*u32_height;
u32_dimensions[0] = u32_width;
u32_dimensions[1] = u32_height;
2021-10-17 21:59:21 +00:00
if (SDL_Init(SDL_INIT_VIDEO) < 0)
{
std::cout << "Video Init Error." << std::endl;
}
SDL_Window* window = SDL_CreateWindow("Slime Mold Simulator", SDL_WINDOWPOS_CENTERED-u32_width/2, SDL_WINDOWPOS_CENTERED-u32_height/2, u32_width, u32_height, SDL_WINDOW_SHOWN);
2021-10-17 21:59:21 +00:00
2021-10-18 04:37:41 +00:00
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
2021-10-18 04:37:41 +00:00
SDL_Texture* field_texture = SDL_CreateTexture(renderer, SDL_GetWindowPixelFormat(window), SDL_TEXTUREACCESS_STREAMING, u32_width, u32_height);
2021-10-18 04:37:41 +00:00
SDL_Texture* start_texture = SDL_CreateTexture(renderer, SDL_GetWindowPixelFormat(window), SDL_TEXTUREACCESS_STREAMING, u32_width, u32_height);
2021-10-18 04:37:41 +00:00
float* ground = new float[i_size];
for(int i = 0; i < i_size; i++)
2021-10-18 04:37:41 +00:00
{
ground[i] = 0.0f;
2021-10-18 04:37:41 +00:00
}
int i_agent_count = (int)sqrt(u32_width*u32_height)*1000;
Agent* agents = new Agent[i_agent_count];
2021-10-18 04:37:41 +00:00
{
uint8_t* u8_pixels;
int i_pitch;
SDL_LockTexture(start_texture, NULL, (void**)&u8_pixels,&i_pitch);
int i_created = 0;
uint32_t u32_radius = 1*((u32_width<u32_height)?u32_width:u32_height)/10;
while(i_created < i_agent_count)
2021-10-18 04:37:41 +00:00
{
float r = u32_radius*sqrt((float)rand()/(float)RAND_MAX);
float theta = 2.0f*M_PI*(float)rand()/(float)RAND_MAX;
int x = r*cos(theta)+(int)u32_width/2;
int y = r*sin(theta)+(int)u32_height/2;
agents[i_created].x = x;
agents[i_created].y = y;
agents[i_created].direction = theta+M_PI;
u8_pixels[4*(x+y*u32_width)] = 255;
u8_pixels[4*(x+y*u32_width)+1] = 255;
u8_pixels[4*(x+y*u32_width)+2] = 255;
u8_pixels[4*(x+y*u32_width)+3] = 255;
i_created++;
2021-10-18 04:37:41 +00:00
}
SDL_UnlockTexture(start_texture);
}
/*
bool* bl_start_positions = new bool[u32_width*u32_height];
for(int i = 0; i < u32_width*u32_height; i++)
{
bl_start_positions[i] = false;
2021-10-18 04:37:41 +00:00
}
2021-10-17 21:59:21 +00:00
int i_created = 0;
while(i_created < i_agent_count)
2021-10-18 04:37:41 +00:00
{
int rng_cur = rand()%(u32_width*u32_height/i_agent_count);
int i_x = rand()%u32_width;
int i_y = rand()%u32_height;
if (rng_cur == 0 && !bl_start_positions[i_x+i_y*u32_width])
2021-10-18 04:37:41 +00:00
{
bl_start_positions[i_x+i_y*u32_width] = true;
2021-10-17 21:59:21 +00:00
agents[i_created].x = (float)i_x;
agents[i_created].y = (float)i_y;
agents[i_created].direction = 2.0f*M_PI*((float)(rand()%100)/100.0f);
i_created++;
//ground[i_x+i_y*u32_width] = 1.0f;
2021-10-18 04:37:41 +00:00
}
}
2021-10-17 21:59:21 +00:00
{
uint8_t* u8_pixels;
int i_pitch;
SDL_LockTexture(start_texture, NULL, (void**)&u8_pixels,&i_pitch);
for(uint32_t i = 0; i < u32_width; i++)
{
for(uint32_t j = 0; j < u32_height; j++)
{
u8_pixels[4*(i+j*u32_width)] = (bl_start_positions[i+j*u32_width])?255:0;
u8_pixels[4*(i+j*u32_width)+1] = (bl_start_positions[i+j*u32_width])?255:0;
u8_pixels[4*(i+j*u32_width)+2] = (bl_start_positions[i+j*u32_width])?255:0;
u8_pixels[4*(i+j*u32_width)+3] = 255;
}
}
SDL_UnlockTexture(start_texture);
}
delete[] bl_start_positions;//*/
std::vector<cl::Platform> all_platforms;
cl::Platform::get(&all_platforms);
cl::Platform default_platform=all_platforms[0];
2021-10-17 21:59:21 +00:00
std::cout << "Using platform :" << default_platform.getInfo<CL_PLATFORM_NAME>() << std::endl;
std::vector<cl::Device> all_devices;
default_platform.getDevices(CL_DEVICE_TYPE_ALL, &all_devices);
if (all_devices.size() == 0)
{
std::cout << "Could not find OpenCL device." << std::endl;
exit(1);
}
2021-10-17 21:59:21 +00:00
cl::Device default_device = all_devices[0];
std::cout << "Using device :" << default_device.getInfo<CL_DEVICE_NAME>() << std::endl;
cl::Context context({default_device});
std::string kernel_code;
if (!get_source(&kernel_code))
{
std::cout << "Error reading kernel source." << std::endl;
exit(1);
}
cl::Program::Sources sources;
sources.push_back({kernel_code.c_str(), kernel_code.length()});
cl::Program program(context, sources);
if (program.build({default_device}, "-cl-std=CL2.0") != CL_SUCCESS)
{
std::cout << "Error building: " << program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(default_device) << std::endl;
exit(1);
}
2021-10-17 21:59:21 +00:00
cl::Buffer buffer_agents(context, CL_MEM_READ_WRITE, sizeof(Agent)*i_agent_count);
cl::Buffer buffer_ground(context, CL_MEM_READ_WRITE, sizeof(float)*i_size);
cl::Buffer buffer_ground_swap(context, CL_MEM_READ_WRITE, sizeof(float)*i_size);
cl::Buffer buffer_ground_dimensions(context, CL_MEM_READ_WRITE, sizeof(uint32_t)*2);
cl::Buffer buffer_draw_data(context, CL_MEM_READ_WRITE, sizeof(uint8_t)*4*i_size);
cl::CommandQueue queue(context,default_device);
queue.enqueueWriteBuffer(buffer_agents, CL_TRUE, 0, sizeof(Agent)*i_agent_count, agents);
queue.enqueueWriteBuffer(buffer_ground, CL_TRUE, 0, sizeof(float)*i_size, ground);
queue.enqueueWriteBuffer(buffer_ground_swap, CL_TRUE, 0, sizeof(float)*i_size, ground);
queue.enqueueWriteBuffer(buffer_ground_dimensions, CL_TRUE, 0, sizeof(uint32_t)*2, &u32_dimensions[0]);
cl::Kernel kernel_initialize_globals(program, "initialize_globals");
kernel_initialize_globals.setArg(0, buffer_agents);
kernel_initialize_globals.setArg(1, buffer_ground);
kernel_initialize_globals.setArg(2, buffer_ground_swap);
kernel_initialize_globals.setArg(3, buffer_ground_dimensions);
queue.enqueueNDRangeKernel(kernel_initialize_globals, cl::NullRange, cl::NDRange(1), cl::NullRange);
queue.finish();
cl::Kernel kernel_update_ground(program, "update_ground");
cl::Kernel kernel_iterate_ground(program, "iterate_ground");
cl::Kernel kernel_move_agents(program, "move_agents");
cl::Kernel kernel_emit_agent_pheromones(program, "emit_agent_pheromones");
cl::Kernel kernel_fill_draw_data(program, "fill_draw_data");
queue.enqueueNDRangeKernel(kernel_emit_agent_pheromones, cl::NullRange, cl::NDRange(i_agent_count), cl::NullRange);
queue.enqueueReadBuffer(buffer_ground, CL_TRUE, 0, sizeof(float)*i_size, ground);
queue.finish();//*/
SDL_Rect screen_rect = {0,0,(int)u32_width,(int)u32_height};
unsigned long long ull_time_old, ull_time_now;
ull_time_now = ull_time_old = sys_time_us();
int iteration_duration = 16666/10;
2021-10-18 04:37:41 +00:00
bool pause = true;
2021-10-17 21:59:21 +00:00
2021-10-18 04:37:41 +00:00
while(true)
{
SDL_Event event;
if (1 == SDL_PollEvent(&event))
{
if (event.type == SDL_KEYDOWN)
{
if (event.key.keysym.scancode == SDL_SCANCODE_Q)
{
break;
}
else if (event.key.keysym.scancode == SDL_SCANCODE_P)
{
pause = !pause;
}
else if (event.key.keysym.scancode == SDL_SCANCODE_T)
{
SDL_SetRenderDrawColor(renderer, 0,0,0,0);
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, start_texture, &screen_rect, &screen_rect);
SDL_RenderPresent(renderer);
}
2021-10-18 04:37:41 +00:00
}
}
ull_time_now = sys_time_us();
if (ull_time_now >= ull_time_old + iteration_duration)
2021-10-18 04:37:41 +00:00
{
ull_time_old = ull_time_now;
2021-10-18 04:37:41 +00:00
if (pause)
{
continue;
}
queue.enqueueNDRangeKernel(kernel_update_ground, cl::NullRange, cl::NDRange(i_size), cl::NullRange);
queue.enqueueNDRangeKernel(kernel_iterate_ground, cl::NullRange, cl::NDRange(i_size), cl::NullRange);
queue.enqueueNDRangeKernel(kernel_move_agents, cl::NullRange, cl::NDRange(i_agent_count), cl::NullRange);
queue.enqueueNDRangeKernel(kernel_emit_agent_pheromones, cl::NullRange, cl::NDRange(i_agent_count), cl::NullRange);
2021-10-18 04:37:41 +00:00
kernel_fill_draw_data.setArg(0, buffer_draw_data);
queue.enqueueNDRangeKernel(kernel_fill_draw_data, cl::NullRange, cl::NDRange(i_size), cl::NullRange);
2021-10-18 04:37:41 +00:00
uint8_t* u8_pixels;
int i_pitch;
SDL_LockTexture(field_texture, NULL, (void**)&u8_pixels, &i_pitch);
2021-10-18 04:37:41 +00:00
queue.enqueueReadBuffer(buffer_draw_data, CL_TRUE, 0, sizeof(uint8_t)*4*i_size, u8_pixels);
queue.finish();
2021-10-18 04:37:41 +00:00
SDL_UnlockTexture(field_texture);
2021-10-18 04:37:41 +00:00
SDL_SetRenderDrawColor(renderer, 0,0,0,0);
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, field_texture, &screen_rect, &screen_rect);
SDL_RenderPresent(renderer);
}
}
2021-10-17 21:59:21 +00:00
2021-10-18 04:37:41 +00:00
SDL_DestroyRenderer(renderer);
2021-10-17 21:59:21 +00:00
SDL_DestroyWindow(window);
SDL_Quit();
delete[] agents;
delete[] ground;
return 0;
}
bool get_source(std::string* source)
{
if (source == nullptr)
2021-10-18 04:37:41 +00:00
{
return false;
2021-10-18 04:37:41 +00:00
}
std::ifstream in_file("gpu_kernel.clcpp", std::ios::in);
std::stringstream buffer;
buffer << in_file.rdbuf();
*source = buffer.str();
return true;
}
unsigned long long sys_time_us()
{
return (unsigned long long)(std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch()).count());
2021-10-17 21:59:21 +00:00
}