Created
May 4, 2023 08:23
-
-
Save chaosddp/df22276dbe12ddc6ab0120994355db0a to your computer and use it in GitHub Desktop.
use ffi and love.data.newByteData to speedup compute shader initialization
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdlib.h> | |
#include <stdio.h> | |
const int FLOAT_PER_PARTICLE = 8; | |
float randff(float max) | |
{ | |
return rand() * (max / RAND_MAX); | |
} | |
void GenerateParticles(float* particles, int particle_count, int width, int height) | |
{ | |
for(int i=0;i<particle_count * FLOAT_PER_PARTICLE;i+=8) | |
{ | |
particles[i] = randff(width); | |
particles[i + 1] = randff(height); | |
particles[i + 2] = randff(100); | |
particles[i + 3] = randff(100); | |
particles[i + 4] = randff(1.0); | |
particles[i + 5] = randff(1.0); | |
particles[i + 6] = randff(1.0); | |
particles[i + 7] = randff(1.0); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- need love2d 12+ to run this script | |
local ffi = require "ffi" | |
-- only tested on windows, but should work on other platform | |
local particles_lib = ffi.load("gen_particles.dll") | |
ffi.cdef[[ | |
void GenerateParticles(float* particles, int particle_count, int width, int height); | |
]] | |
function love.load() | |
computer = love.graphics.newComputeShader([[ | |
layout(std430) buffer; | |
struct Particle { | |
vec2 position; | |
vec2 velocity; | |
vec4 color; | |
}; | |
buffer Particles { | |
Particle particles[]; | |
}; | |
uniform float dt; | |
uniform uint count; | |
layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in; | |
void computemain() { | |
uint index = love_GlobalThreadID.x; | |
// Since the total count isn't evenly divisible by local_size (threadgroup size), | |
// the last group launched will have more threads than we want. | |
if (index >= count) | |
return; | |
// Move | |
particles[index].position += particles[index].velocity * dt; | |
// Bounce | |
vec2 position = particles[index].position; | |
if (position.x < 0. || position.x > 800.) particles[index].velocity.x = -particles[index].velocity.x; | |
if (position.y < 0. || position.y > 600.) particles[index].velocity.y = -particles[index].velocity.y; | |
} | |
]]) | |
renderer = love.graphics.newShader([[ | |
#pragma language glsl4 | |
layout(std430) buffer; | |
struct Particle { | |
vec2 position; | |
vec2 velocity; | |
vec4 color; | |
}; | |
readonly buffer Particles { | |
Particle particles[]; | |
}; | |
#ifdef VERTEX | |
out vec4 vColor; | |
vec4 position(mat4 transform_projection, vec4 vertex_position) { | |
gl_PointSize = 2.; | |
uint index = love_VertexID; | |
vColor = particles[index].color; | |
return transform_projection * vec4(particles[index].position, 0., 1.); | |
} | |
#endif | |
#ifdef PIXEL | |
in vec4 vColor; | |
vec4 effect(vec4 color, Image tex, vec2 texture_coords, vec2 screen_coords) { | |
return vColor; | |
} | |
#endif | |
]]) | |
format = { | |
{ name = 'position', format = 'floatvec2' }, | |
{ name = 'velocity', format = 'floatvec2' }, | |
{ name = 'color', format = 'floatvec4' } | |
} | |
count = 10000000 | |
particles = love.graphics.newBuffer(format, count, { shaderstorage = true }) | |
computer:send('Particles', particles) | |
computer:send("count", count) | |
renderer:send('Particles', particles) | |
local width, height = love.graphics.getDimensions() | |
local data2 = love.data.newByteData(ffi.sizeof("float") * 8 * count) | |
local data_float_ptr = ffi.cast("float *", data2:getFFIPointer()) | |
particles_lib.GenerateParticles(data_float_ptr, count, width, height) | |
particles:setArrayData(data2) | |
mesh = love.graphics.newMesh({{ name = 'VertexPosition', format = 'float' }}, count, 'points') | |
end | |
function love.update(dt) | |
computer:send('dt', dt) | |
local groupCount = math.ceil(count / computer:getLocalThreadgroupSize()) | |
love.graphics.dispatchThreadgroups(computer, groupCount) | |
end | |
function love.draw() | |
love.graphics.setShader(renderer) | |
love.graphics.draw(mesh) | |
love.graphics.setShader() | |
love.graphics.print(count .. ' compute particles @' .. love.timer.getFPS() .. ' FPS') | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment