From f9caf213225d775d39f09e670444e15ac2435420 Mon Sep 17 00:00:00 2001 From: shylie Date: Sat, 18 Apr 2026 11:16:07 -0400 Subject: [PATCH] Add OpenMP support --- CMakeLists.txt | 4 +- src/main.cpp | 32 ++++++++---- src/sand.cpp | 138 +++++++++++++++++++++++++------------------------ 3 files changed, 96 insertions(+), 78 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3652580..15bf11d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,6 +2,8 @@ cmake_minimum_required(VERSION 3.20) project(sand) +find_package(OpenMP REQUIRED) + find_package(PkgConfig REQUIRED) pkg_check_modules(LUAJIT REQUIRED luajit) @@ -14,7 +16,7 @@ target_include_directories(sand PUBLIC include 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 CXX_STANDARD 20 CXX_STANDARD_REQUIRED ON diff --git a/src/main.cpp b/src/main.cpp index 1e300b7..512a981 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -7,6 +7,12 @@ #include #include +constexpr uint16_t WIDTH = 128; +constexpr uint16_t HEIGHT = 128; + +constexpr int WINDOW_WIDTH = 1024; +constexpr int WINDOW_HEIGHT = 1024; + uint8_t lookup[][3] = { { 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"; }); rb.add_rule("stone1", "air") - .top_middle([](const auto& t) { return t == "air" || t == "offgrid"; }) .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_Window* window = SDL_CreateWindow("sand test", 512, 512, 0); - SDL_Surface* surface = SDL_CreateSurface(64, 64, SDL_PIXELFORMAT_RGB24); + SDL_Window* window + = SDL_CreateWindow("sand test", WINDOW_WIDTH, WINDOW_HEIGHT, 0); + SDL_Surface* surface + = SDL_CreateSurface(WIDTH, HEIGHT, SDL_PIXELFORMAT_RGB24); int prev_ms = SDL_GetTicks(); float time = 0; @@ -55,16 +62,22 @@ int main(int argc, char** argv) int state; if (time > 0.008 && (state = SDL_GetMouseState(&x, &y))) { - time = 0; - s.set(x * 64 / 512, y * 64 / 512, state == 1 ? "stone1" : "stone2"); + int ix = x * WIDTH / WINDOW_WIDTH; + 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); - 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(surface->pixels)[3 * (i + j * 64)], + memcpy(&static_cast(surface->pixels)[3 * (i + j * WIDTH)], lookup[s.get(i, j)], 3); } } @@ -76,6 +89,7 @@ int main(int argc, char** argv) s.update(); } + SDL_DestroySurface(surface); SDL_DestroyWindow(window); SDL_Quit(); diff --git a/src/sand.cpp b/src/sand.cpp index 81f8ead..7a382eb 100644 --- a/src/sand.cpp +++ b/src/sand.cpp @@ -267,77 +267,79 @@ uint16_t Sand::get(uint16_t x, uint16_t y) 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)]; - - 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 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 += 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 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;