Skip to content

Commit

Permalink
Compute shaders
Browse files Browse the repository at this point in the history
  • Loading branch information
DM8AT committed Sep 6, 2024
1 parent 69b8514 commit d32847c
Show file tree
Hide file tree
Showing 5 changed files with 407 additions and 3 deletions.
8 changes: 6 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ OBJGL_FLAGS :=

CREATE_BIN := mkdir -p bin

OBJGL_OBJ := $(OBJ_DIR)/OGL_Instance.o $(OBJ_DIR)/OGL_Window.o $(OBJ_DIR)/OGL_BaseState.o $(OBJ_DIR)/OGL_BindableBase.o $(OBJ_DIR)/OGL_BaseFunctions.o $(OBJ_DIR)/OGL_Shader.o $(OBJ_DIR)/OGL_VertexAttributes.o $(OBJ_DIR)/OGL_UniformBuffer.o $(OBJ_DIR)/OGL_ShaderStorageBuffer.o $(OBJ_DIR)/OGL_IndexBuffer.o $(OBJ_DIR)/OGL_Texture.o $(OBJ_DIR)/OGL_Framebuffer.o
OBJGL_FIL := $(OBGL_DIR)/ObjectGL.hpp $(OBGL_DIR)/OGL_Instance.cpp $(OBGL_DIR)/OGL_Window.cpp $(OBGL_DIR)/OGL_BaseState.cpp $(OBGL_DIR)/OGL_BindableBase.cpp $(OBGL_DIR)/OGL_BaseFunctions.cpp $(OBGL_DIR)/OGL_Shader.cpp $(OBGL_DIR)/OGL_VertexAttributes.cpp $(OBGL_DIR)/OGL_UniformBuffer.cpp $(OBGL_DIR)/OGL_ShaderStorageBuffer.cpp $(OBGL_DIR)/OGL_IndexBuffer.cpp $(OBGL_DIR)/OGL_Texture.cpp $(OBGL_DIR)/OGL_Framebuffer.cpp
OBJGL_OBJ := $(OBJ_DIR)/OGL_Instance.o $(OBJ_DIR)/OGL_Window.o $(OBJ_DIR)/OGL_BaseState.o $(OBJ_DIR)/OGL_BindableBase.o $(OBJ_DIR)/OGL_BaseFunctions.o $(OBJ_DIR)/OGL_Shader.o $(OBJ_DIR)/OGL_VertexAttributes.o $(OBJ_DIR)/OGL_UniformBuffer.o $(OBJ_DIR)/OGL_ShaderStorageBuffer.o $(OBJ_DIR)/OGL_IndexBuffer.o $(OBJ_DIR)/OGL_Texture.o $(OBJ_DIR)/OGL_Framebuffer.o $(OBJ_DIR)/OGL_ComputeShader.o
OBJGL_FIL := $(OBGL_DIR)/ObjectGL.hpp $(OBGL_DIR)/OGL_Instance.cpp $(OBGL_DIR)/OGL_Window.cpp $(OBGL_DIR)/OGL_BaseState.cpp $(OBGL_DIR)/OGL_BindableBase.cpp $(OBGL_DIR)/OGL_BaseFunctions.cpp $(OBGL_DIR)/OGL_Shader.cpp $(OBGL_DIR)/OGL_VertexAttributes.cpp $(OBGL_DIR)/OGL_UniformBuffer.cpp $(OBGL_DIR)/OGL_ShaderStorageBuffer.cpp $(OBGL_DIR)/OGL_IndexBuffer.cpp $(OBGL_DIR)/OGL_Texture.cpp $(OBGL_DIR)/OGL_Framebuffer.cpp $(OBGL_DIR)/OGL_ComputeShader.cpp

all: $(BIN)/$(EXECUTABLE)

Expand Down Expand Up @@ -81,6 +81,10 @@ $(OBJ_DIR)/OGL_Framebuffer.o: $(OBGL_DIR)/OGL_Framebuffer.cpp $(OBGL_DIR)/OGL_Bi
$(CREATE_BIN)
$(CXX) -c $< -o $@ $(CXX_FLAGS) $(OBJGL_FLAGS)

$(OBJ_DIR)/OGL_ComputeShader.o: $(OBGL_DIR)/OGL_ComputeShader.cpp $(OBGL_DIR)/OGL_BindableBase.cpp $(OBGL_DIR)/ObjectGL.hpp $(OBGL_DIR)/OGL_BaseState.cpp
$(CREATE_BIN)
$(CXX) -c $< -o $@ $(CXX_FLAGS) $(OBJGL_FLAGS)

run: clean all
clear
./$(BIN)/$(EXECUTABLE)
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,6 @@ If you are missing a feature you'd love to have a wrapper for, create an issue u
## Changelog
Here you can look up what changed accross the versions.
Here is a list of all code related chages that happend after the last major release:
- added compute shaders
- Added support for framebuffers
- The window class supports a function that is called on the "Window Resize" event
307 changes: 307 additions & 0 deletions src/ObjectGL/OGL_ComputeShader.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,307 @@
/**
* @file OGL_ComputeShader.cpp
* @author your name (you@domain.com)
* @brief
* @version 0.1
* @date 2024-09-06
*
* @copyright Copyright (c) 2024
*
*/


//ask for access to the background library
#define OGL_KEEP_BG_ACCESS
//include the main header
#include "ObjectGL.hpp"

//stdlib
#include <fstream>

//a macro to ensure that the correct window is bound
#define correctInstanceBinding() if (oglGetCurrentInstance() != this->instance) {this->instance->makeCurrent();}

/**
* @brief attcg a shader to an existing program
*
* @param program the program to link to
* @param source the source code of the shader
* @param type the type of the shader to compile
*
* @return int the compiled shader
*/
int attachShader(GLint program, std::string source, GLenum type)
{
//store the success tatus
GLint status = 0;
//create the vertex shader
GLuint s = glCreateShader(type);
//the program created correctly, so just guess that the shader worked too.

//store the source code
const char* src = source.c_str();
//store the length of the source
int len = (int)source.length();
//attach the shader source code
glShaderSource(s, 1, &src, &len);
//compile the shader
glCompileShader(s);

//get the compile status
glGetShaderiv(s, GL_COMPILE_STATUS, &status);
//check the status
if (status == GL_FALSE)
{
//store the size of the error log
GLint logSize = 0;
//store the error message
glGetShaderiv(s, GL_INFO_LOG_LENGTH, &logSize);
//create the error log
GLchar* buff = new GLchar[logSize];
//get the error
glGetShaderInfoLog(s, logSize, &logSize, buff);
//print the error
std::__throw_runtime_error((std::string("Encounterd a compile error while compiling a shader. Compile Error: \n") + buff).c_str());
//free the buffer
delete[] buff;
//delete the shader
glDeleteShader(s);
//stop the function
return 0;
}

//attach the shader
glAttachShader(program, s);
//return the shader
return s;
}

/**
* @brief compile a shader to an OpenGL shader on the GPU
*
* @param cs the compute shader
* @return GLuint the compiled shader on the GPU
*/
GLuint compileShader(std::string cs)
{
//create the program
GLuint prog = glCreateProgram();
//check if the program could be created
if (prog == 0)
{
//if not, throw an error
std::__throw_runtime_error("Failed to create shader program");
}

//link the vertex shader and store it
GLuint vsg = attachShader(prog, cs, GL_COMPUTE_SHADER);

//link the whole program
glLinkProgram(prog);

//store if the program is linked
GLint status = 0;
//get if the program is linked
glGetProgramiv(prog, GL_LINK_STATUS, &status);
//check if the shader is linked
if (status == GL_FALSE)
{
//store the size of the error log
GLint logSize = 0;
//store the error message
glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logSize);
//create the error log
GLchar* buff = new GLchar[logSize];
//get the error
glGetProgramInfoLog(prog, logSize, &logSize, buff);
//print the error
std::__throw_runtime_error((std::string("Encounterd a linknig error while linking a shader. Linker error: \n") + buff).c_str());
//free the buffer
delete[] buff;
//delete the shader
glDeleteProgram(prog);
//stop the function
return 0;
}

//clean the vertex shader
glDeleteShader(vsg);

//on success, return the shader
return prog;
}

/**
* @brief read a file into a string
*
* @param file the file to read
* @return std::string the read file
*/
std::string readFile(std::string file)
{
//open the file
std::ifstream f(file.c_str());
//check if the file is opend
if (!f.is_open())
{
//else, print an error
std::__throw_runtime_error((std::string("Failed to open file ") + file).c_str());
return "";
}
//store the file output
std::string out;
//store a line
std::string line;
//read the file
while (getline(f, line))
{
//store the line
out += (line + "\n");
}
//close the file
f.close();
//return the string
return out;
}

OGL_ComputeShader::OGL_ComputeShader(const char* input, OGL_ShaderInput type)
{
//just re-compile the shader
this->recompileShader(input, type);
}

void OGL_ComputeShader::recompileShader(std::string cs, OGL_ShaderInput type)
{
//make sure the correct instance is bound
correctInstanceBinding()
//switch over the types
switch (type)
{
//check if the data is in a file
case OGL_SHADER_INPUT_FILE:
{
//read the vertex shader
std::string css = readFile(cs);
//compile the shader
this->shader = compileShader(css);
break;
}

//check if this is the raw data
case OGL_SHADER_INPUT_SOURCE_GLSL:
{
//just compile the data
this->shader = compileShader(cs);
break;
}

default:
break;
}
}

void OGL_ComputeShader::bind()
{
//make sure to bind the correct instace
correctInstanceBinding()

//bind the shader
glUseProgram(this->shader);
//loop over all uniforms
for (OGL_UniformInfo& ui : this->uniforms)
{
//switch over the type
switch (ui.type)
{
case OGL_TYPE_FLOAT:
//set the float
glUniform1fv(ui.location, 1, (float*)((void*)ui.data));
break;

case OGL_TYPE_INT:
//set the int
glUniform1iv(ui.location, 1, (int*)((void*)ui.data));
break;

case OGL_TYPE_UINT:
//set the unsigned int
glUniform1uiv(ui.location, 1, (unsigned int*)((void*)ui.data));
break;

default:
//throw an error
std::__throw_runtime_error("The requested type is not a valid type for an uniform");
break;
}
}
}

void OGL_ComputeShader::unbind()
{
//make sure to bind the correct instace
correctInstanceBinding()
//unbind the shader
glUseProgram(0);
}

OGL_UniformInfo& OGL_ComputeShader::operator[](std::string name)
{
//store the element index
size_t idx = -1;
//iterate over all uniforms
for (size_t i = 0; i < this->uniforms.size(); ++i)
{
//check if this is the correct element
if (this->uniforms[i].name == name)
{
//if it is, store the index
idx = i;
//stop the loop
break;
}
}
//check if the element was found
if (idx != (size_t)-1)
{
//return a reference to the element
return this->uniforms[idx];
}
//store the index of the new element
idx = this->uniforms.size();
//create a new element
this->uniforms.push_back(OGL_UniformInfo());
//set the name to the requested one
this->uniforms[idx].name = name;
//return a reference to the requested element
return this->uniforms[idx];
}

OGL_UniformInfo& OGL_ComputeShader::operator[](size_t index)
{
//check if the element is in range
if (index < this->uniforms.size())
{
//if it is, return a reference to it
return this->uniforms[index];
}
//else, throw an error
std::__throw_runtime_error("The index is out of bounds for an uniform in the requested shader");
}

void OGL_ComputeShader::recalculateUniforms()
{
//loop over all uniforms
for (OGL_UniformInfo& ui : this->uniforms)
{
//get the location
ui.location = glGetUniformLocation(this->shader, ui.name.c_str());
}
}

void OGL_ComputeShader::onDestroy()
{
//make sure to bind the correct instance
correctInstanceBinding()
//delete the program
glDeleteProgram(this->shader);
}
Loading

0 comments on commit d32847c

Please sign in to comment.