Added support for shader structures.

This commit is contained in:
2023-12-12 11:28:54 -06:00
parent 09200c3816
commit 5798698ae8
10 changed files with 268 additions and 80 deletions

View File

@ -34,11 +34,10 @@ std::vector<std::shared_ptr<IRenderPass>> UICanvas::getPasses(
.view = ctx.camera->getItem()->getWorldTransform(),
.model = selfTransform
};
data.colors[0] = COLOR_WHITE;
data.colors[1] = COLOR_RED;
data.colors[2] = COLOR_GREEN;
data.colors[3] = COLOR_BLUE;
data.test.first = COLOR_RED;
data.test.random = glm::vec3(0, 1, 0);
data.test.second = COLOR_BLUE;
auto pass = createRenderPass<UIShader, UIShaderData>(
std::ref(*this),

View File

@ -10,4 +10,5 @@ target_sources(${DAWN_TARGET_NAME}
ShaderStage.cpp
SimpleTexturedShader.cpp
UIShader.cpp
ShaderParameter.cpp
)

View File

@ -11,6 +11,9 @@
#include "display/Color.hpp"
#include "display/Texture.hpp"
#include "ShaderParameter.hpp"
#include "ShaderStructure.hpp"
namespace Dawn {
typedef GLuint shadertexturebinding_t;
@ -18,53 +21,32 @@ namespace Dawn {
GLSL_330_CORE
};
struct ShaderOpenGLParameter {
std::string name;
size_t offset;
enum ShaderParameterType type;
int32_t count;
GLint location = -1;
ShaderOpenGLParameter(
const std::string &name,
const void *offset,
const enum ShaderParameterType type
) {
this->name = name;
this->offset = (size_t)offset;
this->type = type;
this->count = 1;
}
ShaderOpenGLParameter(
const std::string &name,
const void *offset,
const enum ShaderParameterType type,
const int32_t count
) {
this->name = name;
this->offset = (size_t)offset;
this->type = type;
this->count = count;
}
};
template<typename T>
class Shader : public IShader<T> {
private:
std::vector<std::shared_ptr<ShaderStage>> stages;
std::vector<struct ShaderOpenGLParameter> parameters;
std::vector<struct ShaderParameter> parameters;
std::vector<struct IShaderStructure> structures;
enum ShaderOpenGLVariant variant;
GLuint shaderProgram = -1;
protected:
/**
* Overridable function to get the stages for the shader.
*
* @param variant The variant of the shader to use.
* @param rel The relative data to use.
* @param stages The stages to add to.
* @param parameters The parameters to add to.
* @param structures The structures to add to.
*/
virtual void getStages(
const enum ShaderOpenGLVariant variant,
const T *rel,
std::vector<std::shared_ptr<ShaderStage>> &stages,
std::vector<struct ShaderOpenGLParameter> &parameters
std::vector<struct ShaderParameter> &parameters,
std::vector<struct IShaderStructure> &structures
) = 0;
public:
@ -82,7 +64,8 @@ namespace Dawn {
variant,
&dummy,
stages,
parameters
parameters,
structures
);
// Create the shader program
@ -108,7 +91,7 @@ namespace Dawn {
std::for_each(
parameters.begin(),
parameters.end(),
[&](struct ShaderOpenGLParameter &param) {
[&](struct ShaderParameter &param) {
// Correct offset
param.offset = param.offset - (size_t)(&dummy);
param.location = glGetUniformLocation(
@ -124,6 +107,28 @@ namespace Dawn {
}
);
// Map structures
std::for_each(
structures.begin(),
structures.end(),
[&](struct IShaderStructure &structure) {
structure.offset = structure.offset - (size_t)(&dummy);
structure.location = glGetUniformBlockIndex(
shaderProgram,
structure.structureName.c_str()
);
assertNoGLError();
assertTrue(
structure.location != -1,
"Failed to get location for structure %s.",
structure.structureName.c_str()
);
// Create the buffer
glGenBuffers(1, &structure.buffer);
}
);
this->bind();
}
@ -191,9 +196,43 @@ namespace Dawn {
default:
assertUnreachable("Unsupported ShaderOpenGLVariant");
}
// Upload structures
for(auto structure : structures) {
switch(structure.structureType) {
case ShaderOpenGLStructureType::STD140: {
// Upload the data
glBindBuffer(GL_UNIFORM_BUFFER, structure.buffer);
assertNoGLError();
glBindBufferBase(GL_UNIFORM_BUFFER, structure.location, structure.buffer);
assertNoGLError();
glBufferData(
GL_UNIFORM_BUFFER,
structure.size,
(void*)((size_t)&this->data + (size_t)structure.offset),
GL_STATIC_DRAW
);
assertNoGLError();
break;
}
default:
assertUnreachable("Unsupported ShaderOpenGLStructureType");
}
}
}
~Shader() {
// Delete the structures
for(auto structure : structures) {
assertTrue(structure.buffer != -1, "Invalid buffer.");
glDeleteBuffers(1, &structure.buffer);
assertNoGLError();
}
// Delete the shader program
glDeleteProgram(shaderProgram);
assertNoGLError();
}
};
}

View File

@ -0,0 +1,20 @@
// Copyright (c) 2023 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#include "ShaderParameter.hpp"
using namespace Dawn;
ShaderParameter::ShaderParameter(
const std::string &name,
const void *offset,
const enum ShaderParameterType type,
const size_t count
) {
this->name = name;
this->offset = (size_t)offset;
this->type = type;
this->count = count;
}

View File

@ -0,0 +1,33 @@
// Copyright (c) 2023 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#pragma once
#include "display/shader/IShader.hpp"
#include "dawnopengl.hpp"
namespace Dawn {
struct ShaderParameter {
std::string name;
size_t offset;
enum ShaderParameterType type;
size_t count;
GLint location = -1;
/**
* Construct a new shader parameter.
*
* @param name Name of the parameter within the shader.
* @param offset Offset, relative to the structure of the data.
* @param type Type of the parameter.
* @param count How many elements in the array (if multiple).
*/
ShaderParameter(
const std::string &name,
const void *offset,
const enum ShaderParameterType type,
const size_t count = 1
);
};
}

View File

@ -0,0 +1,81 @@
// Copyright (c) 2023 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#pragma ocne
#include "display/shader/ShaderParameter.hpp"
namespace Dawn {
enum class ShaderOpenGLStructureType {
STD140
};
struct IShaderStructure {
std::string structureName;
size_t offset;
enum ShaderOpenGLStructureType structureType;
size_t size;
// size_t count;
std::vector<struct ShaderParameter> parameters;
GLint location = -1;
GLuint buffer = -1;
};
template<typename T>
struct ShaderStructure final : public IShaderStructure {
public:
/**
* Constructs a new shader structure. Shader structures allow for larger
* amounts/volumes of data to be passed to the shader in a single call.
* Ideally I wouldn't really need this as I wanted the entire shader to
* basically be a single large structure, but OpenGL doesn't support that
* so I have to do this instead.
*
* @param structureName Structure name within the shader.
* @param offset Offset, within the data structure, that this structure
* starts at.
* @param structureType The type of structure data format to use.
* @param getParameters A callback that, when invoked, will populate the
* parameters vector with the parameters for this
* structure.
*/
ShaderStructure(
const std::string &structureName,
const void *offset,
const enum ShaderOpenGLStructureType structureType,
std::function<
void(const T&, std::vector<struct ShaderParameter>&)
> getParameters
) {
this->structureName = structureName;
this->offset = (size_t)offset;
this->structureType = structureType;
this->size = sizeof(T);
this->parameters = std::vector<struct ShaderParameter>();
T dummy;
getParameters(dummy, this->parameters);
// Update offsets.
std::for_each(
this->parameters.begin(),
this->parameters.end(),
[&](struct ShaderParameter &param) {
param.offset -= (size_t)(&dummy);
// Check for non-aligned OpenGL structures.
if(param.offset % sizeof(glm::vec4) != 0) {
assertUnreachable(
"%s%s%s",
"Non-aligned OpenGL structure detected on param ",
param.name.c_str(),
"!\nEnsure you have padded correctly."
);
}
}
);
}
};
}

View File

@ -11,7 +11,8 @@ void SimpleTexturedShader::getStages(
const enum ShaderOpenGLVariant variant,
const struct SimpleTexturedShaderData *rel,
std::vector<std::shared_ptr<ShaderStage>> &stages,
std::vector<struct ShaderOpenGLParameter> &parameters
std::vector<struct ShaderParameter> &parameters,
std::vector<struct IShaderStructure> &structures
) {
// Stages
std::shared_ptr<ShaderStage> vertex;
@ -61,37 +62,37 @@ void SimpleTexturedShader::getStages(
stages.push_back(fragment);
// Parameters
parameters.push_back(ShaderOpenGLParameter(
parameters.push_back(ShaderParameter(
"u_Projection",
&rel->projection,
ShaderParameterType::MAT4
));
parameters.push_back(ShaderOpenGLParameter(
parameters.push_back(ShaderParameter(
"u_View",
&rel->view,
ShaderParameterType::MAT4
));
parameters.push_back(ShaderOpenGLParameter(
parameters.push_back(ShaderParameter(
"u_Model",
&rel->model,
ShaderParameterType::MAT4
));
parameters.push_back(ShaderOpenGLParameter(
parameters.push_back(ShaderParameter(
"u_Color",
&rel->color,
ShaderParameterType::COLOR
));
parameters.push_back(ShaderOpenGLParameter(
parameters.push_back(ShaderParameter(
"u_HasTexture",
&rel->hasTexture,
ShaderParameterType::BOOLEAN
));
parameters.push_back(ShaderOpenGLParameter(
parameters.push_back(ShaderParameter(
"u_Texture",
&rel->texture,
ShaderParameterType::TEXTURE

View File

@ -22,7 +22,8 @@ namespace Dawn {
const enum ShaderOpenGLVariant variant,
const struct SimpleTexturedShaderData *rel,
std::vector<std::shared_ptr<ShaderStage>> &stages,
std::vector<struct ShaderOpenGLParameter> &parameters
std::vector<struct ShaderParameter> &parameters,
std::vector<struct IShaderStructure> &structures
) override;
};
}

View File

@ -11,7 +11,8 @@ void UIShader::getStages(
const enum ShaderOpenGLVariant variant,
const struct UIShaderData *rel,
std::vector<std::shared_ptr<ShaderStage>> &stages,
std::vector<struct ShaderOpenGLParameter> &parameters
std::vector<struct ShaderParameter> &parameters,
std::vector<struct IShaderStructure> &structures
) {
// Stages
std::shared_ptr<ShaderStage> vertex;
@ -38,10 +39,14 @@ void UIShader::getStages(
ShaderStageType::FRAGMENT,
"#version 330 core\n"
"in vec2 o_TextCoord;\n"
"uniform vec4 u_Color[4];\n"
"layout (std140) uniform ub_Color {\n"
"vec4 first;\n"
"vec3 random;\n"
"vec4 second;\n"
"};\n"
"out vec4 o_Color;\n"
"void main() {\n"
"o_Color = u_Color[2];\n"
"o_Color = second;\n"
"}\n"
);
break;
@ -55,46 +60,46 @@ void UIShader::getStages(
stages.push_back(fragment);
// Parameters
parameters.push_back(ShaderOpenGLParameter(
parameters.push_back(ShaderParameter(
"u_Projection",
&rel->projection,
ShaderParameterType::MAT4
));
parameters.push_back(ShaderOpenGLParameter(
parameters.push_back(ShaderParameter(
"u_View",
&rel->view,
ShaderParameterType::MAT4
));
parameters.push_back(ShaderOpenGLParameter(
parameters.push_back(ShaderParameter(
"u_Model",
&rel->model,
ShaderParameterType::MAT4
));
parameters.push_back(ShaderOpenGLParameter(
"u_Color",
&rel->colors,
ShaderParameterType::COLOR,
4
structures.push_back(ShaderStructure<struct TestStruct>(
"ub_Color",
&rel->test,
ShaderOpenGLStructureType::STD140,
[&](const struct TestStruct &rel, std::vector<struct ShaderParameter> &parameters) {
parameters.push_back(ShaderParameter(
"first",
&rel.first,
ShaderParameterType::COLOR
));
parameters.push_back(ShaderParameter(
"random",
&rel.random,
ShaderParameterType::VEC3
));
parameters.push_back(ShaderParameter(
"second",
&rel.second,
ShaderParameterType::COLOR
));
}
));
// parameters.push_back(ShaderOpenGLParameter(
// "u_Color",
// &rel->color,
// ShaderParameterType::COLOR
// ));
// parameters.push_back(ShaderOpenGLParameter(
// "u_HasTexture",
// &rel->hasTexture,
// ShaderParameterType::BOOLEAN
// ));
// parameters.push_back(ShaderOpenGLParameter(
// "u_Texture",
// &rel->texture,
// ShaderParameterType::TEXTURE
// ));
}

View File

@ -7,11 +7,18 @@
#include "display/shader/Shader.hpp"
namespace Dawn {
struct TestStruct {
struct Color first;
glm::vec3 random;
float_t padded;
struct Color second;
};
struct UIShaderData {
glm::mat4 projection;
glm::mat4 view;
glm::mat4 model;
struct Color colors[4];
struct TestStruct test;
};
class UIShader : public Shader<UIShaderData> {
@ -20,7 +27,8 @@ namespace Dawn {
const enum ShaderOpenGLVariant variant,
const struct UIShaderData *rel,
std::vector<std::shared_ptr<ShaderStage>> &stages,
std::vector<struct ShaderOpenGLParameter> &parameters
std::vector<struct ShaderParameter> &parameters,
std::vector<struct IShaderStructure> &structures
) override;
};
}