Pārlūkot izejas kodu

REVIEWED: example: Compute shader Game-of-life

pull/2091/head
Ray pirms 3 gadiem
vecāks
revīzija
1fac09d0f4
6 mainītis faili ar 316 papildinājumiem un 322 dzēšanām
  1. +41
    -0
      examples/others/resources/shaders/glsl430/gol.glsl
  2. +29
    -34
      examples/others/resources/shaders/glsl430/gol_render.glsl
  3. +51
    -54
      examples/others/resources/shaders/glsl430/gol_transfert.glsl
  4. +173
    -164
      examples/others/rlgl_compute_shader.c
  5. +0
    -64
      examples/shaders/resources/shaders/glsl430/gol.glsl
  6. +22
    -6
      src/rlgl.h

+ 41
- 0
examples/others/resources/shaders/glsl430/gol.glsl Parādīt failu

@ -0,0 +1,41 @@
#version 430
// Game of Life logic shader
#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 neighbourCount = 0;
uint x = gl_GlobalInvocationID.x;
uint y = gl_GlobalInvocationID.y;
neighbourCount += fetchGol(x - 1, y - 1); // Top left
neighbourCount += fetchGol(x, y - 1); // Top middle
neighbourCount += fetchGol(x + 1, y - 1); // Top right
neighbourCount += fetchGol(x - 1, y); // Left
neighbourCount += fetchGol(x + 1, y); // Right
neighbourCount += fetchGol(x - 1, y + 1); // Bottom left
neighbourCount += fetchGol(x, y + 1); // Bottom middle
neighbourCount += fetchGol(x + 1, y + 1); // Bottom right
if (neighbourCount == 3) setGol(x, y, 1);
else if (neighbourCount == 2) setGol(x, y, fetchGol(x, y));
else setGol(x, y, 0);
}

examples/shaders/resources/shaders/glsl430/gol_render.glsl → examples/others/resources/shaders/glsl430/gol_render.glsl Parādīt failu

@ -1,34 +1,29 @@
// 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);
}
}
#version 430
// Game of Life rendering shader
// Just renders the content of the ssbo at binding 1 to screen
#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 resolution;
void main()
{
ivec2 coords = ivec2(fragTexCoord*resolution);
if ((golBuffer[coords.x + coords.y*uvec2(resolution).x]) == 1) finalColor = vec4(1.0);
else finalColor = vec4(0.0, 0.0, 0.0, 1.0);
}

examples/shaders/resources/shaders/glsl430/gol_transfert.glsl → examples/others/resources/shaders/glsl430/gol_transfert.glsl Parādīt failu

@ -1,54 +1,51 @@
// 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);
}
}
}
}
}
#version 430
// Game of life transfert shader
#define GOL_WIDTH 768
// Game Of Life Update Command
// NOTE: matches the structure defined on main program
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 cmdIndex = gl_GlobalInvocationID.x;
GolUpdateCmd cmd = commands[cmdIndex];
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);
}
}
}
}

examples/shaders/shaders_compute_gol.c → examples/others/rlgl_compute_shader.c Parādīt failu

@ -1,164 +1,173 @@
/*******************************************************************************************
*
* 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 <stdlib.h>
#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;
}
/*******************************************************************************************
*
* raylib [rlgl] example - compute shader - Conway's Game of Life
*
* NOTE: This example requires raylib OpenGL 4.3 versions for compute shaders support,
* 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) and reviewed by Ramon Santamaria (@raysan5)
*
* Copyright (c) 2021 Teddy Astie (@tsnake41)
*
********************************************************************************************/
#include "raylib.h"
#include "rlgl.h"
#include <stdlib.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
// Game Of Life Update Command
typedef 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
} GolUpdateCmd;
// Game Of Life Update Commands SSBO
typedef struct GolUpdateSSBO {
unsigned int count;
GolUpdateCmd commands[MAX_BUFFERED_TRANSFERTS];
} GolUpdateSSBO;
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
InitWindow(GOL_WIDTH, GOL_WIDTH, "raylib [rlgl] example - compute shader - game of life");
const Vector2 resolution = { GOL_WIDTH, GOL_WIDTH };
unsigned int brushSize = 8;
// 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);
UnloadFileText(golLogicCode);
// Game of Life logic compute shader
Shader golRenderShader = LoadShader(NULL, "resources/shaders/glsl430/gol_render.glsl");
int resUniformLoc = GetShaderLocation(golRenderShader, "resolution");
// 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);
UnloadFileText(golTransfertCode);
// SSBOs
unsigned int ssboA = rlLoadShaderBuffer(GOL_WIDTH*GOL_WIDTH*sizeof(unsigned int), NULL, RL_DYNAMIC_COPY);
unsigned int ssboB = rlLoadShaderBuffer(GOL_WIDTH*GOL_WIDTH*sizeof(unsigned int), 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);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose())
{
// Update
//----------------------------------------------------------------------------------
brushSize += (int)GetMouseWheelMove();
if ((IsMouseButtonDown(MOUSE_BUTTON_LEFT) || IsMouseButtonDown(MOUSE_BUTTON_RIGHT))
&& (transfertBuffer.count < MAX_BUFFERED_TRANSFERTS))
{
// Buffer a new command
transfertBuffer.commands[transfertBuffer.count].x = GetMouseX() - brushSize/2;
transfertBuffer.commands[transfertBuffer.count].y = GetMouseY() - brushSize/2;
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);
SetShaderValue(golRenderShader, resUniformLoc, &resolution, SHADER_UNIFORM_VEC2);
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(BLANK);
BeginShaderMode(golRenderShader);
DrawTexture(whiteTex, 0, 0, WHITE);
EndShaderMode();
DrawRectangleLines(GetMouseX() - brushSize/2, GetMouseY() - brushSize/2, brushSize, brushSize, RED);
DrawText("Use Mouse wheel to increase/decrease brush size", 10, 10, 20, WHITE);
DrawFPS(GetScreenWidth() - 100, 10);
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;
}

+ 0
- 64
examples/shaders/resources/shaders/glsl430/gol.glsl Parādīt failu

@ -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);
}
}

+ 22
- 6
src/rlgl.h Parādīt failu

@ -662,7 +662,6 @@ RLAPI void rlSetUniformMatrix(int locIndex, Matrix mat);
RLAPI void rlSetUniformSampler(int locIndex, unsigned int textureId); // Set shader value sampler RLAPI void rlSetUniformSampler(int locIndex, unsigned int textureId); // Set shader value sampler
RLAPI void rlSetShader(unsigned int id, int *locs); // Set shader currently active (id and locations) RLAPI void rlSetShader(unsigned int id, int *locs); // Set shader currently active (id and locations)
#if defined(GRAPHICS_API_OPENGL_43)
// Compute shader management // Compute shader management
RLAPI unsigned int rlLoadComputeShaderProgram(unsigned int shaderId); // Load compute shader program RLAPI unsigned int rlLoadComputeShaderProgram(unsigned int shaderId); // Load compute shader program
RLAPI void rlComputeShaderDispatch(unsigned int groupX, unsigned int groupY, unsigned int groupZ); // Dispatch compute shader (equivalent to *draw* for graphics pilepine) RLAPI void rlComputeShaderDispatch(unsigned int groupX, unsigned int groupY, unsigned int groupZ); // Dispatch compute shader (equivalent to *draw* for graphics pilepine)
@ -678,7 +677,6 @@ RLAPI void rlBindShaderBuffer(unsigned int id, unsigned int index);
// Buffer management // Buffer management
RLAPI void rlCopyBuffersElements(unsigned int destId, unsigned int srcId, unsigned long long destOffset, unsigned long long srcOffset, unsigned long long count); // Copy SSBO buffer data RLAPI void rlCopyBuffersElements(unsigned int destId, unsigned int srcId, unsigned long long destOffset, unsigned long long srcOffset, unsigned long long count); // Copy SSBO buffer data
RLAPI void rlBindImageTexture(unsigned int id, unsigned int index, unsigned int format, int readonly); // Bind image texture RLAPI void rlBindImageTexture(unsigned int id, unsigned int index, unsigned int format, int readonly); // Bind image texture
#endif
// Matrix state management // Matrix state management
RLAPI Matrix rlGetMatrixModelview(void); // Get internal modelview matrix RLAPI Matrix rlGetMatrixModelview(void); // Get internal modelview matrix
@ -3836,12 +3834,12 @@ void rlSetShader(unsigned int id, int *locs)
#endif #endif
} }
#if defined(GRAPHICS_API_OPENGL_43)
// Load compute shader program // Load compute shader program
unsigned int rlLoadComputeShaderProgram(unsigned int shaderId) unsigned int rlLoadComputeShaderProgram(unsigned int shaderId)
{ {
unsigned int program = 0; unsigned int program = 0;
#if defined(GRAPHICS_API_OPENGL_43)
GLint success = 0; GLint success = 0;
program = glCreateProgram(); program = glCreateProgram();
glAttachShader(program, shaderId); glAttachShader(program, shaderId);
@ -3880,6 +3878,7 @@ unsigned int rlLoadComputeShaderProgram(unsigned int shaderId)
TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Compute shader program loaded successfully", program); TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Compute shader program loaded successfully", program);
} }
#endif
return program; return program;
} }
@ -3887,17 +3886,21 @@ unsigned int rlLoadComputeShaderProgram(unsigned int shaderId)
// Dispatch compute shader (equivalent to *draw* for graphics pilepine) // Dispatch compute shader (equivalent to *draw* for graphics pilepine)
void rlComputeShaderDispatch(unsigned int groupX, unsigned int groupY, unsigned int groupZ) void rlComputeShaderDispatch(unsigned int groupX, unsigned int groupY, unsigned int groupZ)
{ {
#if defined(GRAPHICS_API_OPENGL_43)
glDispatchCompute(groupX, groupY, groupZ); glDispatchCompute(groupX, groupY, groupZ);
#endif
} }
// Load shader storage buffer object (SSBO) // Load shader storage buffer object (SSBO)
unsigned int rlLoadShaderBuffer(unsigned long long size, const void *data, int usageHint) unsigned int rlLoadShaderBuffer(unsigned long long size, const void *data, int usageHint)
{ {
unsigned int ssbo = 0; unsigned int ssbo = 0;
#if defined(GRAPHICS_API_OPENGL_43)
glGenBuffers(1, &ssbo); glGenBuffers(1, &ssbo);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo); glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
glBufferData(GL_SHADER_STORAGE_BUFFER, size, data, usageHint? usageHint : RL_STREAM_COPY); glBufferData(GL_SHADER_STORAGE_BUFFER, size, data, usageHint? usageHint : RL_STREAM_COPY);
#endif
return ssbo; return ssbo;
} }
@ -3905,23 +3908,29 @@ unsigned int rlLoadShaderBuffer(unsigned long long size, const void *data, int u
// Unload shader storage buffer object (SSBO) // Unload shader storage buffer object (SSBO)
void rlUnloadShaderBuffer(unsigned int ssboId) void rlUnloadShaderBuffer(unsigned int ssboId)
{ {
#if defined(GRAPHICS_API_OPENGL_43)
glDeleteBuffers(1, &ssboId); glDeleteBuffers(1, &ssboId);
#endif
} }
// Update SSBO buffer data // Update SSBO buffer data
void rlUpdateShaderBufferElements(unsigned int id, const void *data, unsigned long long dataSize, unsigned long long offset) void rlUpdateShaderBufferElements(unsigned int id, const void *data, unsigned long long dataSize, unsigned long long offset)
{ {
#if defined(GRAPHICS_API_OPENGL_43)
glBindBuffer(GL_SHADER_STORAGE_BUFFER, id); glBindBuffer(GL_SHADER_STORAGE_BUFFER, id);
glBufferSubData(GL_SHADER_STORAGE_BUFFER, offset, dataSize, data); glBufferSubData(GL_SHADER_STORAGE_BUFFER, offset, dataSize, data);
#endif
} }
// Get SSBO buffer size // Get SSBO buffer size
unsigned long long rlGetShaderBufferSize(unsigned int id) unsigned long long rlGetShaderBufferSize(unsigned int id)
{ {
long long size = 0; long long size = 0;
#if defined(GRAPHICS_API_OPENGL_43)
glBindBuffer(GL_SHADER_STORAGE_BUFFER, id); glBindBuffer(GL_SHADER_STORAGE_BUFFER, id);
glGetInteger64v(GL_SHADER_STORAGE_BUFFER_SIZE, &size); glGetInteger64v(GL_SHADER_STORAGE_BUFFER_SIZE, &size);
#endif
return (size > 0)? size : 0; return (size > 0)? size : 0;
} }
@ -3929,33 +3938,40 @@ unsigned long long rlGetShaderBufferSize(unsigned int id)
// Read SSBO buffer data // Read SSBO buffer data
void rlReadShaderBufferElements(unsigned int id, void *dest, unsigned long long count, unsigned long long offset) void rlReadShaderBufferElements(unsigned int id, void *dest, unsigned long long count, unsigned long long offset)
{ {
#if defined(GRAPHICS_API_OPENGL_43)
glBindBuffer(GL_SHADER_STORAGE_BUFFER, id); glBindBuffer(GL_SHADER_STORAGE_BUFFER, id);
glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, offset, count, dest); glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, offset, count, dest);
#endif
} }
// Bind SSBO buffer // Bind SSBO buffer
void rlBindShaderBuffer(unsigned int id, unsigned int index) void rlBindShaderBuffer(unsigned int id, unsigned int index)
{ {
#if defined(GRAPHICS_API_OPENGL_43)
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, index, id); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, index, id);
#endif
} }
// Copy SSBO buffer data // Copy SSBO buffer data
void rlCopyBuffersElements(unsigned int destId, unsigned int srcId, unsigned long long destOffset, unsigned long long srcOffset, unsigned long long count) void rlCopyBuffersElements(unsigned int destId, unsigned int srcId, unsigned long long destOffset, unsigned long long srcOffset, unsigned long long count)
{ {
#if defined(GRAPHICS_API_OPENGL_43)
glBindBuffer(GL_COPY_READ_BUFFER, srcId); glBindBuffer(GL_COPY_READ_BUFFER, srcId);
glBindBuffer(GL_COPY_WRITE_BUFFER, destId); glBindBuffer(GL_COPY_WRITE_BUFFER, destId);
glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, srcOffset, destOffset, count); glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, srcOffset, destOffset, count);
#endif
} }
// Bind image texture // Bind image texture
void rlBindImageTexture(unsigned int id, unsigned int index, unsigned int format, int readonly) void rlBindImageTexture(unsigned int id, unsigned int index, unsigned int format, int readonly)
{ {
#if defined(GRAPHICS_API_OPENGL_43)
int glInternalFormat = 0, glFormat = 0, glType = 0; int glInternalFormat = 0, glFormat = 0, glType = 0;
rlGetGlTextureFormats(format, &glInternalFormat, &glFormat, &glType); rlGetGlTextureFormats(format, &glInternalFormat, &glFormat, &glType);
glBindImageTexture(index, id, 0, 0, 0, readonly ? GL_READ_ONLY : GL_READ_WRITE, glInternalFormat); glBindImageTexture(index, id, 0, 0, 0, readonly ? GL_READ_ONLY : GL_READ_WRITE, glInternalFormat);
}
#endif #endif
}
// Matrix state management // Matrix state management
//----------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------

Notiek ielāde…
Atcelt
Saglabāt