- 44
- 15
MoonCL - либа для параллельных вычислений на видеоядре прямо в Lua скрипте.
Часть рутинного кода написана вместе с нейронкой, её код был проверен вручную, я знаком с такими понятиями, как: буффер, аллокация(alloc) и деаллокация(free), сборщик мусора и т. п. Полных тестов на стабильность не было. Вы имеете полное право закидать меня кокэшками за это.
Скрипт в пре-релизе, если есть какие-то замечания или предложения - Issues и Pull Requests ждут, буду рад получить помощь.
Много кто может задать вопрос: "А нахуя мне OpenCL, если есть effil?". И это справедливо подмечено, вся эта затея пришла в голову чисто случайно, сделано по приколу.
Возможно, эта либа даст кому-нибудь возможность сделать что-то абсурдное или глобальное, хз.
Скрипт в пре-релизе, если есть какие-то замечания или предложения - Issues и Pull Requests ждут, буду рад получить помощь.
Много кто может задать вопрос: "А нахуя мне OpenCL, если есть effil?". И это справедливо подмечено, вся эта затея пришла в голову чисто случайно, сделано по приколу.
Возможно, эта либа даст кому-нибудь возможность сделать что-то абсурдное или глобальное, хз.
Дает возможность считать тяжелую математику параллельно на GPU через OpenCL 1.2 без фризов игры. Вся тяжелая работа выносится в асинхронную очередь, а скрипт просто опрашивает статус в тике. Для пары десятков или сотен проверок она не нужна - быстрее сделать обычным циклом или через FFI. Смысл появляется там, где надо пачками считать тысячи элементов: поиск дистанций, рейкасты по куче хитбоксов, пространственные фильтры или матричные трансформации точек.
Установка
Кинуть папку moonloader в корень игры.Получится примерно так:
moonloader/lib/mooncl/
├── init.lua
└── mooncl.dll
Вшитые ядра
Базовые ядра уже внутри DLL:- batch_distance - дистанция от массива точек до одной целевой
- ray_aabb_intersect - рейкаст луча по массиву хитбоксов (AABB), возвращает дистанцию или -1.0
- mat4_transform_points - умножение массива float4 на матрицу 4x4
- batch_spatial_filter - проверка радиуса, пишет маску 1/0
- batch_clamp / batch_lerp - кламп и интерполяция массивов
Пример использования
Считаем расстояния для 10 000 точек:
require("moonloader")
local mooncl = require("mooncl")
local ffi = require("ffi")
function main()
while not isSampAvailable() do wait(0) end
local ok, dev = mooncl.init()
if not ok then return print("MoonCL init error: " .. dev) end
print("MoonCL run on: " .. dev)
local COUNT = 10000
-- Данные в RAM
local points = mooncl.new_float4_array(COUNT)
for i = 0, COUNT - 1 do
points[i].x, points[i].y, points[i].z, points[i].w = i, i * 0.5, 0.0, 1.0
end
-- Буферы в VRAM
local in_buf = mooncl.create_buffer(COUNT * 16)
local out_buf = mooncl.create_buffer(COUNT * 4)
in_buf:write(points)
-- Настройка ядра
local kernel = mooncl.get_kernel("batch_distance")
kernel:set_buffer(0, in_buf)
kernel:set_float4(1, 0, 0, 0, 0)
kernel:set_buffer(2, out_buf)
kernel:set_int(3, COUNT)
-- Считаем асинхронно
local run_evt = kernel:run_async(COUNT)
while not run_evt:is_done() do wait(0) end
-- Забираем результат
local results = ffi.new("float[?]", COUNT)
local read_evt = out_buf:read_async(results)
while not read_evt:is_done() do wait(0) end
print("Result for 500: " .. results[500])
-- Необязательно, но есть возможность вручную освободить память
in_buf:free()
out_buf:free()
kernel:free()
end
Результат:
Свои ядра
Если ты продвинутый гей, то можно скомпилировать любой свой код ядра на лету прямо в скрипте:
Lua:
local src = [[
__kernel void add(__global const float* a, __global const float* b, __global float* c, int count) {
int id = get_global_id(0);
if (id >= count) return;
c[id] = a[id] + b[id];
}
]]
local kernel, err = mooncl.compile(src, "add")
if not kernel then return print("Compile error:\n" .. err) end
Исходник и инструкция:
GitHub - Loverxzc/MoonCL: Пиши скрипты для САМП с возможностями OpenCL
Пиши скрипты для САМП с возможностями OpenCL. Contribute to Loverxzc/MoonCL development by creating an account on GitHub.