From 1fac09d0f4d409d33c0fe529b46bc8132b18ccd9 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 31 Oct 2021 12:28:04 +0100 Subject: REVIEWED: example: Compute shader Game-of-life --- .../shaders/resources/shaders/glsl430/gol.glsl | 64 -------- .../resources/shaders/glsl430/gol_render.glsl | 34 ----- .../resources/shaders/glsl430/gol_transfert.glsl | 54 ------- examples/shaders/shaders_compute_gol.c | 164 --------------------- 4 files changed, 316 deletions(-) delete mode 100644 examples/shaders/resources/shaders/glsl430/gol.glsl delete mode 100644 examples/shaders/resources/shaders/glsl430/gol_render.glsl delete mode 100644 examples/shaders/resources/shaders/glsl430/gol_transfert.glsl delete mode 100644 examples/shaders/shaders_compute_gol.c (limited to 'examples/shaders') diff --git a/examples/shaders/resources/shaders/glsl430/gol.glsl b/examples/shaders/resources/shaders/glsl430/gol.glsl deleted file mode 100644 index 47b1a55f..00000000 --- a/examples/shaders/resources/shaders/glsl430/gol.glsl +++ /dev/null @@ -1,64 +0,0 @@ -// Game of Life logic shader -#version 430 - -#define GOL_WIDTH 768 - -layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in; - -layout(std430, binding = 1) readonly restrict buffer golLayout { - uint golBuffer[]; // golBuffer[x, y] = golBuffer[x + gl_NumWorkGroups.x * y] -}; - -layout(std430, binding = 2) writeonly restrict buffer golLayout2 { - uint 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); - } -} diff --git a/examples/shaders/resources/shaders/glsl430/gol_render.glsl b/examples/shaders/resources/shaders/glsl430/gol_render.glsl deleted file mode 100644 index bbc16eed..00000000 --- a/examples/shaders/resources/shaders/glsl430/gol_render.glsl +++ /dev/null @@ -1,34 +0,0 @@ -// Game of Life rendering shader -// Just renders the content of the ssbo at binding 1 to screen. -#version 430 - -#define GOL_WIDTH 768 - -// Input vertex attributes (from vertex shader) -in vec2 fragTexCoord; - -// Output fragment color -out vec4 finalColor; - -// Input game of life grid. -layout(std430, binding = 1) readonly buffer golLayout -{ - uint golBuffer[]; -}; - -// Output resolution -uniform vec2 res; - -void main() -{ - ivec2 coords = ivec2(fragTexCoord * res); - - if (golBuffer[coords.x + coords.y * uvec2(res).x] == 1) - { - finalColor = vec4(1.0); - } - else - { - finalColor = vec4(0.0, 0.0, 0.0, 1.0); - } -} diff --git a/examples/shaders/resources/shaders/glsl430/gol_transfert.glsl b/examples/shaders/resources/shaders/glsl430/gol_transfert.glsl deleted file mode 100644 index 40d54458..00000000 --- a/examples/shaders/resources/shaders/glsl430/gol_transfert.glsl +++ /dev/null @@ -1,54 +0,0 @@ -// Game of life transfert shader. -#version 430 -#define GOL_WIDTH 768 - -// Structure definitions -struct GolUpdateCmd { - uint x; // x coordinate of the gol command - uint y; // y coordinate of the gol command - uint w; // width of the filled zone - uint enabled; // whether to enable or disable zone -}; - -// Local compute unit size. -layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in; - -// Output game of life grid buffer. -layout(std430, binding = 1) buffer golBufferLayout -{ - uint golBuffer[]; // golBuffer[x, y] = golBuffer[x + GOL_WIDTH * y] -}; - -// Command buffer -layout(std430, binding = 3) readonly restrict buffer golUpdateLayout -{ - uint count; - GolUpdateCmd commands[]; -}; - -#define isInside(x, y) (((x) >= 0) && ((y) >= 0) && ((x) < GOL_WIDTH) && ((y) < GOL_WIDTH)) -#define getBufferIndex(x, y) ((x) + GOL_WIDTH * (y)) - -void main() -{ - uint cmd_index = gl_GlobalInvocationID.x; - GolUpdateCmd cmd = commands[cmd_index]; - - for (uint x = cmd.x; x < (cmd.x + cmd.w); x++) - { - for (uint y = cmd.y; y < (cmd.y + cmd.w); y++) - { - if (isInside(x, y)) - { - if (cmd.enabled != 0) - { - atomicOr(golBuffer[getBufferIndex(x, y)], 1); - } - else - { - atomicAnd(golBuffer[getBufferIndex(x, y)], 0); - } - } - } - } -} diff --git a/examples/shaders/shaders_compute_gol.c b/examples/shaders/shaders_compute_gol.c deleted file mode 100644 index c5645ee2..00000000 --- a/examples/shaders/shaders_compute_gol.c +++ /dev/null @@ -1,164 +0,0 @@ -/******************************************************************************************* -* -* raylib [shaders] example - Compute shaders Conway's Game of Life -* -* NOTE: This example requires raylib OpenGL 4.3 versions for compute shaders support, -* -* NOTE: Shaders used in this example are #version 430 (OpenGL 4.3). -* -* This example has been created using raylib 4.0 (www.raylib.com) -* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) -* -* Example contributed by Teddy Astie (@tsnake41) -* -* Copyright (c) 2021 Teddy Astie (@tsnake41) -* -********************************************************************************************/ - -#include - -#include "raylib.h" -#include "rlgl.h" - -// IMPORTANT: This must match gol*.glsl GOL_WIDTH constant. -// This must be a multiple of 16 (check golLogic compute dispatch). -#define GOL_WIDTH 768 - -// Maximum amount of queued draw commands (squares draw from mouse down events). -#define MAX_BUFFERED_TRANSFERTS 48 - -struct GolUpdateCmd -{ - unsigned int x; // x coordinate of the gol command - unsigned int y; // y coordinate of the gol command - unsigned int w; // width of the filled zone - unsigned int enabled; // whether to enable or disable zone -}; - -struct GolUpdateSSBO -{ - unsigned int count; - struct GolUpdateCmd commands[MAX_BUFFERED_TRANSFERTS]; -}; - -int main(void) -{ - // Initialization - //-------------------------------------------------------------------------------------- - InitWindow(GOL_WIDTH, GOL_WIDTH, "raylib [shaders] example - compute shader gol"); - - const Vector2 resolution = { GOL_WIDTH, GOL_WIDTH }; - unsigned int brushSize = 1; - - // Game of Life logic compute shader - char *golLogicCode = LoadFileText("resources/shaders/glsl430/gol.glsl"); - unsigned int golLogicShader = rlCompileShader(golLogicCode, RL_COMPUTE_SHADER); - unsigned int golLogicProgram = rlLoadComputeShaderProgram(golLogicShader); - MemFree(golLogicCode); - - // Game of Life logic compute shader - Shader golRenderShader = LoadShader(NULL, "resources/shaders/glsl430/gol_render.glsl"); - int resUniformLoc = GetShaderLocation(golRenderShader, "res"); - - // Game of Life transfert shader - char *golTransfertCode = LoadFileText("resources/shaders/glsl430/gol_transfert.glsl"); - unsigned int golTransfertShader = rlCompileShader(golTransfertCode, RL_COMPUTE_SHADER); - unsigned int golTransfertProgram = rlLoadComputeShaderProgram(golTransfertShader); - MemFree(golTransfertCode); - - // SSBOs - unsigned int ssboA = rlLoadShaderBuffer(sizeof(unsigned int) * GOL_WIDTH * GOL_WIDTH, NULL, RL_DYNAMIC_COPY); - unsigned int ssboB = rlLoadShaderBuffer(sizeof(unsigned int) * GOL_WIDTH * GOL_WIDTH, NULL, RL_DYNAMIC_COPY); - - struct GolUpdateSSBO transfertBuffer; - transfertBuffer.count = 0; - - int transfertSSBO = rlLoadShaderBuffer(sizeof(struct GolUpdateSSBO), NULL, RL_DYNAMIC_COPY); - - // Create a white texture of the size of the window to update - // each pixel of the window using the fragment shader. - Image whiteImage = GenImageColor(GOL_WIDTH, GOL_WIDTH, WHITE); - Texture whiteTex = LoadTextureFromImage(whiteImage); - UnloadImage(whiteImage); - - while (!WindowShouldClose()) - { - if (IsKeyPressed(KEY_UP)) brushSize *= 2; - else if (IsKeyPressed(KEY_DOWN) && (brushSize != 1)) brushSize /= 2; - - if ((IsMouseButtonDown(MOUSE_BUTTON_LEFT) || IsMouseButtonDown(MOUSE_BUTTON_RIGHT)) - && (transfertBuffer.count < MAX_BUFFERED_TRANSFERTS)) - { - // Buffer a new command - transfertBuffer.commands[transfertBuffer.count].x = GetMouseX(); - transfertBuffer.commands[transfertBuffer.count].y = GetMouseY(); - transfertBuffer.commands[transfertBuffer.count].w = brushSize; - transfertBuffer.commands[transfertBuffer.count].enabled = IsMouseButtonDown(MOUSE_BUTTON_LEFT); - transfertBuffer.count++; - } - else if (transfertBuffer.count > 0) - { - // Process transfert buffer - - // Send SSBO buffer to GPU - rlUpdateShaderBufferElements(transfertSSBO, &transfertBuffer, sizeof(struct GolUpdateSSBO), 0); - // Process ssbo command - rlEnableShader(golTransfertProgram); - rlBindShaderBuffer(ssboA, 1); - rlBindShaderBuffer(transfertSSBO, 3); - rlComputeShaderDispatch(transfertBuffer.count, 1, 1); // each GPU unit will process a command - rlDisableShader(); - - transfertBuffer.count = 0; - } - else - { - // Process game of life logic - rlEnableShader(golLogicProgram); - rlBindShaderBuffer(ssboA, 1); - rlBindShaderBuffer(ssboB, 2); - rlComputeShaderDispatch(GOL_WIDTH / 16, GOL_WIDTH / 16, 1); - rlDisableShader(); - - // ssboA <-> ssboB - int temp = ssboA; - ssboA = ssboB; - ssboB = temp; - } - - rlBindShaderBuffer(ssboA, 1); - - BeginDrawing(); - - ClearBackground(BLANK); - SetShaderValue(golRenderShader, resUniformLoc, &resolution, SHADER_UNIFORM_VEC2); - - BeginShaderMode(golRenderShader); - DrawTexture(whiteTex, 0, 0, WHITE); - EndShaderMode(); - - DrawFPS(0, 0); - - EndDrawing(); - } - - // De-Initialization - //-------------------------------------------------------------------------------------- - - // Unload shader buffers objects. - rlUnloadShaderBuffer(ssboA); - rlUnloadShaderBuffer(ssboB); - rlUnloadShaderBuffer(transfertSSBO); - - // Unload compute shader programs - rlUnloadShaderProgram(golTransfertProgram); - rlUnloadShaderProgram(golLogicProgram); - - UnloadTexture(whiteTex); // Unload white texture - UnloadShader(golRenderShader); // Unload rendering fragment shader - - CloseWindow(); // Close window and OpenGL context - //-------------------------------------------------------------------------------------- - - return 0; -} -- cgit v1.2.3