**WARNING: BREAKING:** REDESIGNED: rlgl shader loading API function names for more consistency #5631

ADDED: `rlUnloadShader()` to unload shaders (that function was missing and compute shaders leak memory)
RENAMED: `rlCompileShader()` to p `rlLoadShader()` to be consistent with `rlUnloadShader()`
RENAMED: `rlLoadShaderCode()` to `rlLoadShaderProgram()`, more descriptive of return
RENAMED: `rlLoadShaderProgram()` to `rlLoadShaderProgramEx()`
RENAMED: `rlLoadComputeShaderProgram()` to `rlLoadShaderProgramCompute()`
RENAMED: Some functions parameters for consistency
This commit is contained in:
Ray
2026-03-09 14:23:54 +01:00
parent 2b207be11e
commit e40ddfabbb
3 changed files with 170 additions and 166 deletions

View File

@@ -65,8 +65,8 @@ int main(void)
// 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);
unsigned int golLogicShader = rlLoadShader(golLogicCode, RL_COMPUTE_SHADER);
unsigned int golLogicProgram = rlLoadShaderProgramCompute(golLogicShader);
UnloadFileText(golLogicCode);
// Game of Life logic render shader
@@ -75,8 +75,8 @@ int main(void)
// Game of Life transfert shader (CPU<->GPU download and upload)
char *golTransfertCode = LoadFileText("resources/shaders/glsl430/gol_transfert.glsl");
unsigned int golTransfertShader = rlCompileShader(golTransfertCode, RL_COMPUTE_SHADER);
unsigned int golTransfertProgram = rlLoadComputeShaderProgram(golTransfertShader);
unsigned int golTransfertShader = rlLoadShader(golTransfertCode, RL_COMPUTE_SHADER);
unsigned int golTransfertProgram = rlLoadShaderProgramCompute(golTransfertShader);
UnloadFileText(golTransfertCode);
// Load shader storage buffer object (SSBO), id returned
@@ -169,7 +169,9 @@ int main(void)
rlUnloadShaderBuffer(ssboB);
rlUnloadShaderBuffer(ssboTransfert);
// Unload compute shader programs
// Unload compute shader
rlUnloadShader(golLogicShader);
rlUnloadShader(golTransfertShader);
rlUnloadShaderProgram(golTransfertProgram);
rlUnloadShaderProgram(golLogicProgram);

View File

@@ -1243,7 +1243,7 @@ Shader LoadShaderFromMemory(const char *vsCode, const char *fsCode)
{
Shader shader = { 0 };
shader.id = rlLoadShaderCode(vsCode, fsCode);
shader.id = rlLoadShaderProgram(vsCode, fsCode);
if (shader.id == 0)
{

View File

@@ -762,7 +762,7 @@ RLAPI unsigned char *rlReadScreenPixels(int width, int height); // Rea
// Framebuffer management (fbo)
RLAPI unsigned int rlLoadFramebuffer(void); // Load an empty framebuffer
RLAPI void rlFramebufferAttach(unsigned int fboId, unsigned int texId, int attachType, int texType, int mipLevel); // Attach texture/renderbuffer to a framebuffer
RLAPI void rlFramebufferAttach(unsigned int id, unsigned int texId, int attachType, int texType, int mipLevel); // Attach texture/renderbuffer to a framebuffer
RLAPI bool rlFramebufferComplete(unsigned int id); // Verify framebuffer is complete
RLAPI void rlUnloadFramebuffer(unsigned int id); // Delete framebuffer from GPU
// WARNING: Copy and resize framebuffer functionality only defined for software backend
@@ -770,13 +770,14 @@ RLAPI void rlCopyFramebuffer(int x, int y, int width, int height, int format, vo
RLAPI void rlResizeFramebuffer(int width, int height); // Resize internal framebuffer
// Shaders management
RLAPI unsigned int rlLoadShaderCode(const char *vsCode, const char *fsCode); // Load shader from code strings
RLAPI unsigned int rlCompileShader(const char *shaderCode, int type); // Compile custom shader and return shader id (type: RL_VERTEX_SHADER, RL_FRAGMENT_SHADER, RL_COMPUTE_SHADER)
RLAPI void rlUnloadShader(unsigned int id); // Unload shader, loaded with rlCompileShader()
RLAPI unsigned int rlLoadShaderProgram(unsigned int vShaderId, unsigned int fShaderId); // Load custom shader program
RLAPI unsigned int rlLoadShader(const char *code, int type); // Load (compile) shader and return shader id (type: RL_VERTEX_SHADER, RL_FRAGMENT_SHADER, RL_COMPUTE_SHADER)
RLAPI unsigned int rlLoadShaderProgram(const char *vsCode, const char *fsCode); // Load shader from code strings
RLAPI unsigned int rlLoadShaderProgramEx(unsigned int vsId, unsigned int fsId); // Load shader program, using already loaded shader ids
RLAPI unsigned int rlLoadShaderProgramCompute(unsigned int csId); // Load compute shader program
RLAPI void rlUnloadShader(unsigned int id); // Unload shader, loaded with rlLoadShader()
RLAPI void rlUnloadShaderProgram(unsigned int id); // Unload shader program
RLAPI int rlGetLocationUniform(unsigned int shaderId, const char *uniformName); // Get shader location uniform, requires shader program id
RLAPI int rlGetLocationAttrib(unsigned int shaderId, const char *attribName); // Get shader location attribute, requires shader program id
RLAPI int rlGetLocationUniform(unsigned int id, const char *uniformName); // Get shader location uniform, requires shader program id
RLAPI int rlGetLocationAttrib(unsigned int id, const char *attribName); // Get shader location attribute, requires shader program id
RLAPI void rlSetUniform(int locIndex, const void *value, int uniformType, int count); // Set shader value uniform
RLAPI void rlSetUniformMatrix(int locIndex, Matrix mat); // Set shader value matrix
RLAPI void rlSetUniformMatrices(int locIndex, const Matrix *mat, int count); // Set shader value matrices
@@ -784,7 +785,6 @@ RLAPI void rlSetUniformSampler(int locIndex, unsigned int textureId);
RLAPI void rlSetShader(unsigned int id, int *locs); // Set shader currently active (id and locations)
// Compute shader management
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 pipeline)
// Shader buffer storage object management (ssbo)
@@ -3837,12 +3837,12 @@ unsigned int rlLoadFramebuffer(void)
return fboId;
}
// Attach color buffer texture to an fbo (unloads previous attachment)
// Attach color buffer texture to a framebuffer object (unloads previous attachment)
// NOTE: Attach type: 0-Color, 1-Depth renderbuffer, 2-Depth texture
void rlFramebufferAttach(unsigned int fboId, unsigned int texId, int attachType, int texType, int mipLevel)
void rlFramebufferAttach(unsigned int id, unsigned int texId, int attachType, int texType, int mipLevel)
{
#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2))
glBindFramebuffer(GL_FRAMEBUFFER, fboId);
glBindFramebuffer(GL_FRAMEBUFFER, id);
switch (attachType)
{
@@ -4179,93 +4179,14 @@ void rlUnloadVertexBuffer(unsigned int vboId)
// Shaders management
//-----------------------------------------------------------------------------------------------
// Load shader from code strings
// NOTE: If shader string is NULL, using default vertex/fragment shaders
unsigned int rlLoadShaderCode(const char *vsCode, const char *fsCode)
{
unsigned int id = 0; // Shader program id
if (!isGpuReady) { TRACELOG(RL_LOG_WARNING, "GL: GPU is not ready to load data, trying to load before InitWindow()?"); return id; }
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
unsigned int vertexShaderId = 0;
unsigned int fragmentShaderId = 0;
// Compile vertex shader (if provided)
// NOTE: If not vertex shader is provided, use default one
if (vsCode != NULL) vertexShaderId = rlCompileShader(vsCode, GL_VERTEX_SHADER);
else vertexShaderId = RLGL.State.defaultVShaderId;
// Compile fragment shader (if provided)
// NOTE: If not vertex shader is provided, use default one
if (fsCode != NULL) fragmentShaderId = rlCompileShader(fsCode, GL_FRAGMENT_SHADER);
else fragmentShaderId = RLGL.State.defaultFShaderId;
// In case vertex and fragment shader are the default ones, no need to recompile, assign the default shader program id
if ((vertexShaderId == RLGL.State.defaultVShaderId) && (fragmentShaderId == RLGL.State.defaultFShaderId)) id = RLGL.State.defaultShaderId;
else if ((vertexShaderId > 0) && (fragmentShaderId > 0))
{
// One of or both shader are new, a new shader program needs to be compiled
id = rlLoadShaderProgram(vertexShaderId, fragmentShaderId);
// Detaching and deleting vertex/fragment shaders (if not default ones)
// WARNING: Detach shader before deletion to make sure memory is freed
if (vertexShaderId != RLGL.State.defaultVShaderId)
{
// WARNING: Shader program linkage could fail and returned id is 0
if (id > 0) glDetachShader(id, vertexShaderId);
glDeleteShader(vertexShaderId);
}
if (fragmentShaderId != RLGL.State.defaultFShaderId)
{
// WARNING: Shader program linkage could fail and returned id is 0
if (id > 0) glDetachShader(id, fragmentShaderId);
glDeleteShader(fragmentShaderId);
}
// In case shader program loading failed, assign default shader
if (id == 0)
{
// In case shader loading fails, reassigning default shader
TRACELOG(RL_LOG_WARNING, "SHADER: Failed to load custom shader code, using default shader");
id = RLGL.State.defaultShaderId;
}
/*
else
{
// Get available shader uniforms
// NOTE: This information is useful for debug...
int uniformCount = -1;
glGetProgramiv(id, GL_ACTIVE_UNIFORMS, &uniformCount);
for (int i = 0; i < uniformCount; i++)
{
int namelen = -1;
int num = -1;
char name[256] = { 0 }; // Assume no variable names longer than 256
GLenum type = GL_ZERO;
// Get the name of the uniforms
glGetActiveUniform(id, i, sizeof(name) - 1, &namelen, &num, &type, name);
name[namelen] = 0;
TRACELOG(RL_LOG_DEBUG, "SHADER: [ID %i] Active uniform (%s) set at location: %i", id, name, glGetUniformLocation(id, name));
}
}
*/
}
#endif
return id;
}
// Compile custom shader and return shader id
unsigned int rlCompileShader(const char *shaderCode, int type)
// Load (compile) shader and return shader id
unsigned int rlLoadShader(const char *code, int type)
{
unsigned int shaderId = 0;
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
shaderId = glCreateShader(type);
glShaderSource(shaderId, 1, &shaderCode, NULL);
glShaderSource(shaderId, 1, &code, NULL);
GLint success = 0;
glCompileShader(shaderId);
@@ -4323,8 +4244,87 @@ unsigned int rlCompileShader(const char *shaderCode, int type)
return shaderId;
}
// Load custom shader strings and return program id
unsigned int rlLoadShaderProgram(unsigned int vShaderId, unsigned int fShaderId)
// Load shader program from code strings
// NOTE: If shader string is NULL, using default vertex/fragment shaders
unsigned int rlLoadShaderProgram(const char *vsCode, const char *fsCode)
{
unsigned int id = 0; // Shader program id
if (!isGpuReady) { TRACELOG(RL_LOG_WARNING, "GL: GPU is not ready to load data, trying to load before InitWindow()?"); return id; }
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
unsigned int vertexShaderId = 0;
unsigned int fragmentShaderId = 0;
// Compile vertex shader (if provided)
// NOTE: If not vertex shader is provided, use default one
if (vsCode != NULL) vertexShaderId = rlLoadShader(vsCode, GL_VERTEX_SHADER);
else vertexShaderId = RLGL.State.defaultVShaderId;
// Compile fragment shader (if provided)
// NOTE: If not vertex shader is provided, use default one
if (fsCode != NULL) fragmentShaderId = rlLoadShader(fsCode, GL_FRAGMENT_SHADER);
else fragmentShaderId = RLGL.State.defaultFShaderId;
// In case vertex and fragment shader are the default ones, no need to recompile, assign the default shader program id
if ((vertexShaderId == RLGL.State.defaultVShaderId) && (fragmentShaderId == RLGL.State.defaultFShaderId)) id = RLGL.State.defaultShaderId;
else if ((vertexShaderId > 0) && (fragmentShaderId > 0))
{
// One of or both shader are new, a new shader program needs to be compiled
id = rlLoadShaderProgramEx(vertexShaderId, fragmentShaderId);
// Detaching and deleting vertex/fragment shaders (if not default ones)
// WARNING: Detach shader before deletion to make sure memory is freed
if (vertexShaderId != RLGL.State.defaultVShaderId)
{
// WARNING: Shader program linkage could fail and returned id is 0
if (id > 0) glDetachShader(id, vertexShaderId);
glDeleteShader(vertexShaderId);
}
if (fragmentShaderId != RLGL.State.defaultFShaderId)
{
// WARNING: Shader program linkage could fail and returned id is 0
if (id > 0) glDetachShader(id, fragmentShaderId);
glDeleteShader(fragmentShaderId);
}
// In case shader program loading failed, assign default shader
if (id == 0)
{
// In case shader loading fails, reassigning default shader
TRACELOG(RL_LOG_WARNING, "SHADER: Failed to load custom shader code, using default shader");
id = RLGL.State.defaultShaderId;
}
/*
else
{
// Get available shader uniforms
// NOTE: This information is useful for debug...
int uniformCount = -1;
glGetProgramiv(id, GL_ACTIVE_UNIFORMS, &uniformCount);
for (int i = 0; i < uniformCount; i++)
{
int namelen = -1;
int num = -1;
char name[256] = { 0 }; // Assume no variable names longer than 256
GLenum type = GL_ZERO;
// Get the name of the uniforms
glGetActiveUniform(id, i, sizeof(name) - 1, &namelen, &num, &type, name);
name[namelen] = 0;
TRACELOG(RL_LOG_DEBUG, "SHADER: [ID %i] Active uniform (%s) set at location: %i", id, name, glGetUniformLocation(id, name));
}
}
*/
}
#endif
return id;
}
// Load shader program from already loaded shader ids
unsigned int rlLoadShaderProgramEx(unsigned int vsId, unsigned int fsId)
{
unsigned int programId = 0;
if (!isGpuReady) { TRACELOG(RL_LOG_WARNING, "GL: GPU is not ready to load data, trying to load before InitWindow()?"); return programId; }
@@ -4333,8 +4333,8 @@ unsigned int rlLoadShaderProgram(unsigned int vShaderId, unsigned int fShaderId)
GLint success = 0;
programId = glCreateProgram();
glAttachShader(programId, vShaderId);
glAttachShader(programId, fShaderId);
glAttachShader(programId, vsId);
glAttachShader(programId, fsId);
// Default attribute shader locations must be bound before linking
// NOTE: There is no problem with binding a generic attribute index to an attribute variable name
@@ -4388,14 +4388,57 @@ unsigned int rlLoadShaderProgram(unsigned int vShaderId, unsigned int fShaderId)
return programId;
}
// Unload shader program
void rlUnloadShaderProgram(unsigned int id)
// Load compute shader program
unsigned int rlLoadShaderProgramCompute(unsigned int csId)
{
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
glDeleteProgram(id);
unsigned int programId = 0;
TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Unloaded shader program data from VRAM (GPU)", id);
#if defined(GRAPHICS_API_OPENGL_43)
GLint success = 0;
programId = glCreateProgram();
glAttachShader(programId, csId);
glLinkProgram(programId);
// NOTE: All uniform variables are intitialised to 0 when a program links
glGetProgramiv(programId, GL_LINK_STATUS, &success);
if (success == GL_FALSE)
{
TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to link compute shader program", programId);
int maxLength = 0;
glGetProgramiv(programId, GL_INFO_LOG_LENGTH, &maxLength);
if (maxLength > 0)
{
int length = 0;
char *log = (char *)RL_CALLOC(maxLength, sizeof(char));
glGetProgramInfoLog(programId, maxLength, &length, log);
TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Link error: %s", programId, log);
RL_FREE(log);
}
glDeleteProgram(programId);
programId = 0;
}
else
{
// Get the size of compiled shader program (not available on OpenGL ES 2.0)
// NOTE: If GL_LINK_STATUS is GL_FALSE, program binary length is zero
//GLint binarySize = 0;
//glGetProgramiv(id, GL_PROGRAM_BINARY_LENGTH, &binarySize);
TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Compute shader program loaded successfully", programId);
}
#else
TRACELOG(RL_LOG_WARNING, "SHADER: Compute shaders not supported, enable GRAPHICS_API_OPENGL_43");
#endif
return programId;
}
// Delete shader
@@ -4408,13 +4451,23 @@ void rlUnloadShader(unsigned int id)
#endif
}
// Unload shader program
void rlUnloadShaderProgram(unsigned int id)
{
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
glDeleteProgram(id);
TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Unloaded shader program data from VRAM (GPU)", id);
#endif
}
// Get shader location uniform
// NOTE: First parameter refers to shader program id
int rlGetLocationUniform(unsigned int shaderId, const char *uniformName)
int rlGetLocationUniform(unsigned int id, const char *uniformName)
{
int location = -1;
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
location = glGetUniformLocation(shaderId, uniformName);
location = glGetUniformLocation(id, uniformName);
//if (location == -1) TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to find shader uniform: %s", shaderId, uniformName);
//else TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Shader uniform (%s) set at location: %i", shaderId, uniformName, location);
@@ -4424,11 +4477,11 @@ int rlGetLocationUniform(unsigned int shaderId, const char *uniformName)
// Get shader location attribute
// NOTE: First parameter refers to shader program id
int rlGetLocationAttrib(unsigned int shaderId, const char *attribName)
int rlGetLocationAttrib(unsigned int id, const char *attribName)
{
int location = -1;
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
location = glGetAttribLocation(shaderId, attribName);
location = glGetAttribLocation(id, attribName);
//if (location == -1) TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to find shader attribute: %s", shaderId, attribName);
//else TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Shader attribute (%s) set at location: %i", shaderId, attribName, location);
@@ -4538,57 +4591,6 @@ void rlSetShader(unsigned int id, int *locs)
#endif
}
// Load compute shader program
unsigned int rlLoadComputeShaderProgram(unsigned int shaderId)
{
unsigned int programId = 0;
#if defined(GRAPHICS_API_OPENGL_43)
GLint success = 0;
programId = glCreateProgram();
glAttachShader(programId, shaderId);
glLinkProgram(programId);
// NOTE: All uniform variables are intitialised to 0 when a program links
glGetProgramiv(programId, GL_LINK_STATUS, &success);
if (success == GL_FALSE)
{
TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to link compute shader program", programId);
int maxLength = 0;
glGetProgramiv(programId, GL_INFO_LOG_LENGTH, &maxLength);
if (maxLength > 0)
{
int length = 0;
char *log = (char *)RL_CALLOC(maxLength, sizeof(char));
glGetProgramInfoLog(programId, maxLength, &length, log);
TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Link error: %s", programId, log);
RL_FREE(log);
}
glDeleteProgram(programId);
programId = 0;
}
else
{
// Get the size of compiled shader program (not available on OpenGL ES 2.0)
// NOTE: If GL_LINK_STATUS is GL_FALSE, program binary length is zero
//GLint binarySize = 0;
//glGetProgramiv(id, GL_PROGRAM_BINARY_LENGTH, &binarySize);
TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Compute shader program loaded successfully", programId);
}
#else
TRACELOG(RL_LOG_WARNING, "SHADER: Compute shaders not enabled. Define GRAPHICS_API_OPENGL_43");
#endif
return programId;
}
// Dispatch compute shader (equivalent to *draw* for graphics pilepine)
void rlComputeShaderDispatch(unsigned int groupX, unsigned int groupY, unsigned int groupZ)
{
@@ -5081,10 +5083,10 @@ static void rlLoadShaderDefault(void)
// NOTE: Compiled vertex/fragment shaders are not deleted,
// they are kept for re-use as default shaders in case some shader loading fails
RLGL.State.defaultVShaderId = rlCompileShader(defaultVShaderCode, GL_VERTEX_SHADER); // Compile default vertex shader
RLGL.State.defaultFShaderId = rlCompileShader(defaultFShaderCode, GL_FRAGMENT_SHADER); // Compile default fragment shader
RLGL.State.defaultVShaderId = rlLoadShader(defaultVShaderCode, GL_VERTEX_SHADER); // Compile default vertex shader
RLGL.State.defaultFShaderId = rlLoadShader(defaultFShaderCode, GL_FRAGMENT_SHADER); // Compile default fragment shader
RLGL.State.defaultShaderId = rlLoadShaderProgram(RLGL.State.defaultVShaderId, RLGL.State.defaultFShaderId);
RLGL.State.defaultShaderId = rlLoadShaderProgramEx(RLGL.State.defaultVShaderId, RLGL.State.defaultFShaderId);
if (RLGL.State.defaultShaderId > 0)
{