Add compute shader support from TSnake41/raylib

This commit is contained in:
TSnake41 2021-10-14 21:13:34 +02:00
parent 1c94c52802
commit 3546bf9724
5 changed files with 214 additions and 1 deletions

View File

@ -0,0 +1,57 @@
#version 430
#define GOL_WIDTH 1024
layout (local_size_x = 16, local_size_y = 16, local_size_x = 1) in;
layout(std430, binding = 1) readonly restrict buffer golLayout {
int golBuffer[]; // golBuffer[x, y] = golBuffer[x + gl_NumWorkGroups.x * y]
};
layout(std430, set = 1, binding = 2) writeonly restrict buffer golLayout2 {
int golBufferDest[]; // golBufferDest[x, y] = golBufferDest[x + gl_NumWorkGroups.x * y]
};
#define fetchGol(x, y) ((((x) < 0) || ((y) < 0) || ((x) > GOL_WIDTH) || ((y) > GOL_WIDTH)) \
? (0) \
: golBuffer[(x) + GOL_WIDTH * (y)])
#define setGol(x, y, value) golBufferDest[(x) + GOL_WIDTH * (y)] = value
void main()
{
uint neighbour_count = 0;
uint x = gl_GlobalInvocationID.x;
uint y = gl_GlobalInvocationID.y;
// Top left
neighbour_count += fetchGol(x - 1, y - 1);
// Top middle
neighbour_count += fetchGol(x, y - 1);
// Top right
neighbour_count += fetchGol(x + 1, y - 1);
// Left
neighbour_count += fetchGol(x - 1, y);
// Right
neighbour_count += fetchGol(x + 1, y);
// Bottom left
neighbour_count += fetchGol(x - 1, y + 1);
// Bottom middle
neighbour_count += fetchGol(x, y + 1);
// Bottom right
neighbour_count += fetchGol(x + 1, y + 1);
if (neighbour_count == 3)
setGol(x, y, 1);
else if (neighbour_count == 2)
setGol(x, y, fetchGol(x, y));
else
setGol(x, y, 0);
}

View File

@ -0,0 +1,105 @@
local ffi = require "ffi"
local width, height = 1024, 1024
rl.InitWindow(width, height, "raylib-lua [core] example - compute shader")
local computeShaderCode
do
local f = io.open("resources/gol.glsl", "rb")
assert(f, "Can't read resources/gol.glsl file")
computeShaderCode = f:read "*a"
f:close()
end
local computeShader = rl.rlCompileShader(computeShaderCode, rl.RL_COMPUTE_SHADER)
local csProgram = rl.rlLoadComputeShaderProgram(computeShader)
print(csProgram)
local ssbo_size = ffi.sizeof("int32_t[?]", width * height)
local ssbo_baseBuffer = ffi.new("int32_t[?]", width * height)
for i=0,width * height - 1 do
ssbo_baseBuffer[i] = 0
end
local shader_framebuffer = rl.new("Color[?]", width * height)
local ssbo_image = rl.new "Image" ---@type Image
ssbo_image.data = shader_framebuffer
ssbo_image.width = width
ssbo_image.height = height
ssbo_image.format = rl.PIXELFORMAT_UNCOMPRESSED_R8G8B8A8
ssbo_image.mipmaps = 1
local ssboA = rl.rlLoadShaderBuffer(ssbo_size, ssbo_baseBuffer, rl.RL_STREAM_COPY)
local ssboB = rl.rlLoadShaderBuffer(ssbo_size, ssbo_baseBuffer, rl.RL_STREAM_COPY)
-- Create a texture to apply shader
local renderTexture = rl.LoadRenderTexture(width, height)
local renderShader = rl.LoadShaderFromMemory(nil, [[
#version 430
out vec4 finalColor;
in vec2 fragTexCoord;
layout(std430, binding = 1) readonly buffer golLayout {
int golBuffer[];
};
uniform vec2 res;
void main()
{
ivec2 coords = ivec2(fragTexCoord * res);
if (golBuffer[coords.x + coords.y * uint(res.x)] == 1)
finalColor = vec4(1.0);
else
finalColor = vec4(0.0, 0.0, 0.0, 1.0);
}
]])
local resolution = ffi.new("float[2]", width, height)
local res_uniform = rl.GetShaderLocation(renderShader, "res")
while not rl.WindowShouldClose() do
rl.BeginDrawing()
if rl.IsMouseButtonDown(rl.MOUSE_BUTTON_LEFT) then
rl.rlReadShaderBufferElements(ssboB, ssbo_baseBuffer, ssbo_size, 0)
-- Correct colors
for i=0,(width * height)-1 do
local toggled = ssbo_baseBuffer[i]
shader_framebuffer[i].r = toggled * 255
shader_framebuffer[i].g = toggled * 255
shader_framebuffer[i].b = toggled * 255
shader_framebuffer[i].a = toggled * 255
end
rl.ImageDrawRectangleV(ssbo_image, rl.GetMousePosition(), rl.new("Vector2", 25, 25), rl.WHITE)
for x=0,ssbo_image.width-1 do
for y=0,ssbo_image.height-1 do
ssbo_baseBuffer[x + y * width] = (shader_framebuffer[x + y * width].r > 0)
end
end
rl.rlUpdateShaderBufferElements(ssboB, ssbo_baseBuffer, ssbo_size, 0)
else
rl.rlEnableShader(csProgram)
rl.rlBindShaderBuffer(ssboA, 1)
rl.rlBindShaderBuffer(ssboB, 2)
rl.rlComputeShaderDispatch(width / 16, height / 16, 1)
rl.rlDisableShader()
end
rl.ClearBackground(rl.BLANK)
rl.SetShaderValue(renderShader, res_uniform, resolution, rl.SHADER_UNIFORM_VEC2)
rl.BeginShaderMode(renderShader)
rl.DrawTexture(renderTexture.texture, 0, 0, rl.WHITE)
rl.EndShaderMode()
rl.DrawFPS(0, 0)
rl.EndDrawing()
ssboA, ssboB = ssboB, ssboA
end
rl.CloseWindow()

View File

@ -6,7 +6,7 @@ LUA ?= luajit/src/luajit
WINDRES ?= windres
CFLAGS += -Iluajit/src -Iraylib/src -Iraygui/src
CFLAGS += -Iluajit/src -Iraylib/src -Iraygui/src -DSUPPORT_COMPUTE_SHADERS
LDFLAGS += luajit/src/libluajit.a raylib/src/libraylib.a
MODULES := raymath rlgl easings gestures physac raygui

View File

@ -809,6 +809,47 @@ ffi.cdef [[
} rlRenderBatch;
]]
-- rlgl defines
rl.RL_TEXTURE_WRAP_S = 0x2802
rl.RL_TEXTURE_WRAP_T = 0x2803
rl.RL_TEXTURE_MAG_FILTER = 0x2800
rl.RL_TEXTURE_MIN_FILTER = 0x2801
rl.RL_TEXTURE_FILTER_NEAREST = 0x2600
rl.RL_TEXTURE_FILTER_LINEAR = 0x2601
rl.RL_TEXTURE_FILTER_MIP_NEAREST = 0x2700
rl.RL_TEXTURE_FILTER_NEAREST_MIP_LINEAR = 0x2702
rl.RL_TEXTURE_FILTER_LINEAR_MIP_NEAREST = 0x2701
rl.RL_TEXTURE_FILTER_MIP_LINEAR = 0x2703
rl.RL_TEXTURE_FILTER_ANISOTROPIC = 0x3000
rl.RL_TEXTURE_WRAP_REPEAT = 0x2901
rl.RL_TEXTURE_WRAP_CLAMP = 0x812F
rl.RL_TEXTURE_WRAP_MIRROR_REPEAT = 0x8370
rl.RL_TEXTURE_WRAP_MIRROR_CLAMP = 0x8742
rl.RL_MODELVIEW = 0x1700
rl.RL_PROJECTION = 0x1701
rl.RL_TEXTURE = 0x1702
rl.RL_LINES = 0x0001
rl.RL_TRIANGLES = 0x0004
rl.RL_QUADS = 0x0007
rl.RL_UNSIGNED_BYTE = 0x1401
rl.RL_FLOAT = 0x1406
rl.RL_STREAM_DRAW = 0x88E0
rl.RL_STREAM_READ = 0x88E1
rl.RL_STREAM_COPY = 0x88E2
rl.RL_STATIC_DRAW = 0x88E4
rl.RL_STATIC_READ = 0x88E5
rl.RL_STATIC_COPY = 0x88E6
rl.RL_DYNAMIC_DRAW = 0x88E8
rl.RL_DYNAMIC_READ = 0x88E9
rl.RL_DYNAMIC_COPY = 0x88EA
rl.RL_FRAGMENT_SHADER = 0x8B30
rl.RL_VERTEX_SHADER = 0x8B31
rl.RL_COMPUTE_SHADER = 0x91B9
-- Physac cdef
ffi.cdef [[
typedef enum PhysicsShapeType { PHYSICS_CIRCLE = 0, PHYSICS_POLYGON } PhysicsShapeType;

View File

@ -116,6 +116,16 @@ void rlSetUniform(int locIndex, const void *value, int uniformType, int count)
void rlSetUniformMatrix(int locIndex, Matrix mat)
void rlSetUniformSampler(int locIndex, unsigned int textureId)
void rlSetShader(unsigned int id, int *locs)
unsigned int rlLoadComputeShaderProgram(int shaderId)
void rlComputeShaderDispatch(unsigned int groupX, unsigned int groupY, unsigned int groupZ)
unsigned int rlLoadShaderBuffer(unsigned long long size, const void *data, int usageHint)
void rlUnloadShaderBuffer(unsigned int ssboId)
void rlUpdateShaderBufferElements(unsigned int id, const void *data, unsigned long long dataSize, unsigned long long offset)
unsigned long long rlGetShaderBufferSize(unsigned int id)
void rlReadShaderBufferElements(unsigned int id, void *dest, unsigned long long count, unsigned long long offset)
void rlBindShaderBuffer(unsigned int id, unsigned int index)
void rlCopyBuffersElements(unsigned int destId, unsigned int srcId, unsigned long long destOffset, unsigned long long srcOffset, unsigned long long count)
void rlBindImageTexture(unsigned int id, unsigned int index, unsigned int format, int readonly)
Matrix rlGetMatrixModelview(void)
Matrix rlGetMatrixProjection(void)
Matrix rlGetMatrixTransform(void)