Add OpenMP support

This commit is contained in:
shylie 2026-04-18 11:16:07 -04:00
parent 8193df09e0
commit f9caf21322
3 changed files with 96 additions and 78 deletions

View File

@ -2,6 +2,8 @@ cmake_minimum_required(VERSION 3.20)
project(sand) project(sand)
find_package(OpenMP REQUIRED)
find_package(PkgConfig REQUIRED) find_package(PkgConfig REQUIRED)
pkg_check_modules(LUAJIT REQUIRED luajit) pkg_check_modules(LUAJIT REQUIRED luajit)
@ -14,7 +16,7 @@ target_include_directories(sand
PUBLIC include PUBLIC include
PRIVATE ${LUAJIT_INCLUDE_DIRS} PRIVATE ${LUAJIT_INCLUDE_DIRS}
) )
target_link_libraries(sand PRIVATE ${LUAJIT_LIBRARIES}) target_link_libraries(sand PRIVATE ${LUAJIT_LIBRARIES} OpenMP::OpenMP_CXX)
set_target_properties(sand PROPERTIES set_target_properties(sand PROPERTIES
CXX_STANDARD 20 CXX_STANDARD 20
CXX_STANDARD_REQUIRED ON CXX_STANDARD_REQUIRED ON

View File

@ -7,6 +7,12 @@
#include <SDL3/SDL_video.h> #include <SDL3/SDL_video.h>
#include <sand.h> #include <sand.h>
constexpr uint16_t WIDTH = 128;
constexpr uint16_t HEIGHT = 128;
constexpr int WINDOW_WIDTH = 1024;
constexpr int WINDOW_HEIGHT = 1024;
uint8_t lookup[][3] uint8_t lookup[][3]
= { { 0, 0, 0 }, { 50, 0, 0 }, { 100, 100, 100 }, { 200, 200, 200 } }; = { { 0, 0, 0 }, { 50, 0, 0 }, { 100, 100, 100 }, { 200, 200, 200 } };
@ -23,14 +29,15 @@ int main(int argc, char** argv)
.top_middle([](const auto& t) { return t == "stone1"; }); .top_middle([](const auto& t) { return t == "stone1"; });
rb.add_rule("stone1", "air") rb.add_rule("stone1", "air")
.top_middle([](const auto& t) { return t == "air" || t == "offgrid"; })
.bottom_middle([](const auto& t) { return t == "air"; }); .bottom_middle([](const auto& t) { return t == "air"; });
auto s = rb.build(64, 64, "air"); auto s = rb.build(WIDTH, HEIGHT, "air");
SDL_Init(SDL_INIT_VIDEO); SDL_Init(SDL_INIT_VIDEO);
SDL_Window* window = SDL_CreateWindow("sand test", 512, 512, 0); SDL_Window* window
SDL_Surface* surface = SDL_CreateSurface(64, 64, SDL_PIXELFORMAT_RGB24); = SDL_CreateWindow("sand test", WINDOW_WIDTH, WINDOW_HEIGHT, 0);
SDL_Surface* surface
= SDL_CreateSurface(WIDTH, HEIGHT, SDL_PIXELFORMAT_RGB24);
int prev_ms = SDL_GetTicks(); int prev_ms = SDL_GetTicks();
float time = 0; float time = 0;
@ -55,16 +62,22 @@ int main(int argc, char** argv)
int state; int state;
if (time > 0.008 && (state = SDL_GetMouseState(&x, &y))) if (time > 0.008 && (state = SDL_GetMouseState(&x, &y)))
{ {
time = 0; int ix = x * WIDTH / WINDOW_WIDTH;
s.set(x * 64 / 512, y * 64 / 512, state == 1 ? "stone1" : "stone2"); int iy = y * HEIGHT / WINDOW_HEIGHT;
if (ix >= 0 && ix < WIDTH && iy >= 0 && iy < HEIGHT)
{
time = 0;
s.set(ix, iy, state == 1 ? "stone1" : "stone2");
}
} }
SDL_LockSurface(surface); SDL_LockSurface(surface);
for (int i = 0; i < 64; i++) for (int i = 0; i < WIDTH; i++)
{ {
for (int j = 0; j < 64; j++) for (int j = 0; j < HEIGHT; j++)
{ {
memcpy(&static_cast<uint8_t*>(surface->pixels)[3 * (i + j * 64)], memcpy(&static_cast<uint8_t*>(surface->pixels)[3 * (i + j * WIDTH)],
lookup[s.get(i, j)], 3); lookup[s.get(i, j)], 3);
} }
} }
@ -76,6 +89,7 @@ int main(int argc, char** argv)
s.update(); s.update();
} }
SDL_DestroySurface(surface);
SDL_DestroyWindow(window); SDL_DestroyWindow(window);
SDL_Quit(); SDL_Quit();

View File

@ -267,77 +267,79 @@ uint16_t Sand::get(uint16_t x, uint16_t y)
void Sand::update() void Sand::update()
{ {
for (uint32_t i = 0; i < width; i++) int n;
#pragma omp parallel for private(n)
for (n = 0; n < width * height; n++)
{ {
for (uint32_t j = 0; j < height; j++) int i = n % width;
int j = n / height;
auto& current_rule = rules[get(i, j)];
unsigned __int128 neighbors = 0;
if (i > 0 && j > 0)
{ {
auto& current_rule = rules[get(i, j)]; neighbors += get(i - 1, j - 1);
unsigned __int128 neighbors = 0;
if (i > 0 && j > 0)
{
neighbors += get(i - 1, j - 1);
}
neighbors <<= 16;
if (j > 0)
{
neighbors += get(i, j - 1);
}
neighbors <<= 16;
if (i < width - 1 && j > 0)
{
neighbors += get(i + 1, j);
}
neighbors <<= 16;
if (i > 0)
{
neighbors += get(i - 1, j);
}
neighbors <<= 16;
if (i < width - 1)
{
neighbors += get(i + 1, j);
}
neighbors <<= 16;
if (i > 0 && j < height - 1)
{
neighbors += get(i - 1, j + 1);
}
neighbors <<= 16;
if (j < height - 1)
{
neighbors += get(i, j + 1);
}
neighbors <<= 16;
if (i < width - 1 && j < height - 1)
{
neighbors += get(i + 1, j + 1);
}
uint16_t result = default_conversions[get(i, j)];
if (!current_rule.empty())
{
std::pair<unsigned __int128, uint16_t> element = { neighbors, 0 };
bool (*fn)(decltype(element), decltype(element))
= [](decltype(element) a, decltype(element) b) -> bool
{ return a.first > b.first; };
const auto& found = binary_search(element, current_rule.data(), 0,
current_rule.size(), fn);
if (found.first == neighbors)
{
result = found.second;
}
}
elements[i + j * width + !iter * width * height] = result;
} }
neighbors <<= 16;
if (j > 0)
{
neighbors += get(i, j - 1);
}
neighbors <<= 16;
if (i < width - 1 && j > 0)
{
neighbors += get(i + 1, j);
}
neighbors <<= 16;
if (i > 0)
{
neighbors += get(i - 1, j);
}
neighbors <<= 16;
if (i < width - 1)
{
neighbors += get(i + 1, j);
}
neighbors <<= 16;
if (i > 0 && j < height - 1)
{
neighbors += get(i - 1, j + 1);
}
neighbors <<= 16;
if (j < height - 1)
{
neighbors += get(i, j + 1);
}
neighbors <<= 16;
if (i < width - 1 && j < height - 1)
{
neighbors += get(i + 1, j + 1);
}
uint16_t result = default_conversions[get(i, j)];
if (!current_rule.empty())
{
std::pair<unsigned __int128, uint16_t> element = { neighbors, 0 };
bool (*fn)(decltype(element), decltype(element))
= [](decltype(element) a, decltype(element) b) -> bool
{ return a.first > b.first; };
const auto& found = binary_search(element, current_rule.data(), 0,
current_rule.size(), fn);
if (found.first == neighbors)
{
result = found.second;
}
}
elements[i + j * width + !iter * width * height] = result;
} }
iter = !iter; iter = !iter;