2018-06-11 18:48:43 +00:00
|
|
|
|
|
|
|
#pragma once
|
2016-07-26 19:27:02 +00:00
|
|
|
|
2018-06-12 11:00:40 +00:00
|
|
|
#include "hwrenderer/data/uniformbuffer.h"
|
|
|
|
#include "v_video.h"
|
|
|
|
#include "gl/data/gl_uniformbuffer.h"
|
2016-07-26 19:27:02 +00:00
|
|
|
#include "gl_shader.h"
|
|
|
|
|
2018-06-11 18:48:43 +00:00
|
|
|
enum class UniformType
|
|
|
|
{
|
|
|
|
Int,
|
|
|
|
UInt,
|
|
|
|
Float,
|
|
|
|
Vec2,
|
|
|
|
Vec3,
|
|
|
|
Vec4,
|
|
|
|
IVec2,
|
|
|
|
IVec3,
|
|
|
|
IVec4,
|
|
|
|
UVec2,
|
|
|
|
UVec3,
|
|
|
|
UVec4,
|
2018-06-12 19:43:35 +00:00
|
|
|
Mat4
|
2018-06-11 18:48:43 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class UniformFieldDesc
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
UniformFieldDesc() { }
|
|
|
|
UniformFieldDesc(const char *name, UniformType type, std::size_t offset) : Name(name), Type(type), Offset(offset) { }
|
|
|
|
|
|
|
|
const char *Name;
|
|
|
|
UniformType Type;
|
|
|
|
std::size_t Offset;
|
|
|
|
};
|
|
|
|
|
2018-06-12 19:43:35 +00:00
|
|
|
template<typename T, int bindingpoint>
|
2018-06-11 18:48:43 +00:00
|
|
|
class ShaderUniforms
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
ShaderUniforms()
|
|
|
|
{
|
|
|
|
memset(&Values, 0, sizeof(Values));
|
|
|
|
}
|
|
|
|
|
|
|
|
~ShaderUniforms()
|
|
|
|
{
|
2018-06-12 11:00:40 +00:00
|
|
|
if (mBuffer != nullptr)
|
|
|
|
delete mBuffer;
|
2018-06-11 18:48:43 +00:00
|
|
|
}
|
|
|
|
|
2018-06-12 19:43:35 +00:00
|
|
|
int BindingPoint() const
|
|
|
|
{
|
|
|
|
return bindingpoint;
|
|
|
|
}
|
|
|
|
|
2018-06-11 18:48:43 +00:00
|
|
|
FString CreateDeclaration(const char *name, const std::vector<UniformFieldDesc> &fields)
|
|
|
|
{
|
|
|
|
mFields = fields;
|
|
|
|
|
|
|
|
FString decl;
|
2018-06-12 19:43:35 +00:00
|
|
|
decl.Format("layout(%s) uniform %s\n{\n", screen->GetUniformLayoutString(bindingpoint).GetChars(), name);
|
2018-06-11 18:48:43 +00:00
|
|
|
for (const auto &field : fields)
|
|
|
|
{
|
|
|
|
decl.AppendFormat("\t%s %s;\n", GetTypeStr(field.Type), field.Name);
|
|
|
|
}
|
|
|
|
decl += "};\n";
|
|
|
|
|
|
|
|
return decl;
|
|
|
|
}
|
|
|
|
|
2018-06-11 20:33:55 +00:00
|
|
|
void Init()
|
2018-06-11 18:48:43 +00:00
|
|
|
{
|
2018-06-12 11:00:40 +00:00
|
|
|
if (mBuffer == nullptr)
|
|
|
|
mBuffer = screen->CreateUniformBuffer(sizeof(T));
|
2018-06-11 18:48:43 +00:00
|
|
|
}
|
|
|
|
|
2018-06-12 19:43:35 +00:00
|
|
|
void Set(bool bind = true)
|
2018-06-11 18:48:43 +00:00
|
|
|
{
|
2018-06-12 11:00:40 +00:00
|
|
|
if (mBuffer != nullptr)
|
|
|
|
mBuffer->SetData(&Values);
|
2018-06-11 18:48:43 +00:00
|
|
|
|
2018-06-12 19:43:35 +00:00
|
|
|
// Let's hope this can be done better when things have moved further ahead.
|
|
|
|
// This really is not the best place to add something that depends on API behavior.
|
|
|
|
if (bind) mBuffer->Bind(bindingpoint);
|
2018-06-11 18:48:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
T *operator->() { return &Values; }
|
|
|
|
const T *operator->() const { return &Values; }
|
|
|
|
|
|
|
|
T Values;
|
|
|
|
|
|
|
|
private:
|
|
|
|
ShaderUniforms(const ShaderUniforms &) = delete;
|
|
|
|
ShaderUniforms &operator=(const ShaderUniforms &) = delete;
|
|
|
|
|
|
|
|
const char *GetTypeStr(UniformType type)
|
|
|
|
{
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
default:
|
|
|
|
case UniformType::Int: return "int";
|
|
|
|
case UniformType::UInt: return "uint";
|
|
|
|
case UniformType::Float: return "float";
|
|
|
|
case UniformType::Vec2: return "vec2";
|
|
|
|
case UniformType::Vec3: return "vec3";
|
|
|
|
case UniformType::Vec4: return "vec4";
|
|
|
|
case UniformType::IVec2: return "ivec2";
|
|
|
|
case UniformType::IVec3: return "ivec3";
|
|
|
|
case UniformType::IVec4: return "ivec4";
|
|
|
|
case UniformType::UVec2: return "uvec2";
|
|
|
|
case UniformType::UVec3: return "uvec3";
|
|
|
|
case UniformType::UVec4: return "uvec4";
|
2018-06-12 19:43:35 +00:00
|
|
|
case UniformType::Mat4: return "mat4";
|
2018-06-11 18:48:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-12 11:00:40 +00:00
|
|
|
IUniformBuffer *mBuffer = nullptr;
|
2018-06-11 18:48:43 +00:00
|
|
|
std::vector<UniformFieldDesc> mFields;
|
|
|
|
};
|
|
|
|
|
2016-07-26 19:27:02 +00:00
|
|
|
class FShaderProgram
|
|
|
|
{
|
|
|
|
public:
|
2016-08-25 23:40:28 +00:00
|
|
|
FShaderProgram();
|
2016-07-26 19:27:02 +00:00
|
|
|
~FShaderProgram();
|
|
|
|
|
|
|
|
enum ShaderType
|
|
|
|
{
|
|
|
|
Vertex,
|
|
|
|
Fragment,
|
|
|
|
NumShaderTypes
|
|
|
|
};
|
|
|
|
|
2016-07-29 19:31:20 +00:00
|
|
|
void Compile(ShaderType type, const char *lumpName, const char *defines, int maxGlslVersion);
|
|
|
|
void Compile(ShaderType type, const char *name, const FString &code, const char *defines, int maxGlslVersion);
|
2016-07-26 19:27:02 +00:00
|
|
|
void SetFragDataLocation(int index, const char *name);
|
|
|
|
void Link(const char *name);
|
|
|
|
void SetAttribLocation(int index, const char *name);
|
2018-06-11 20:33:55 +00:00
|
|
|
void SetUniformBufferLocation(int index, const char *name);
|
2016-07-26 19:27:02 +00:00
|
|
|
void Bind();
|
|
|
|
|
|
|
|
operator GLuint() const { return mProgram; }
|
|
|
|
explicit operator bool() const { return mProgram != 0; }
|
|
|
|
|
|
|
|
private:
|
2016-08-25 23:40:28 +00:00
|
|
|
FShaderProgram(const FShaderProgram &) = delete;
|
|
|
|
FShaderProgram &operator=(const FShaderProgram &) = delete;
|
|
|
|
|
2016-07-29 19:31:20 +00:00
|
|
|
static FString PatchShader(ShaderType type, const FString &code, const char *defines, int maxGlslVersion);
|
|
|
|
|
2016-07-26 19:27:02 +00:00
|
|
|
void CreateShader(ShaderType type);
|
|
|
|
FString GetShaderInfoLog(GLuint handle);
|
|
|
|
FString GetProgramInfoLog(GLuint handle);
|
|
|
|
|
|
|
|
GLuint mProgram = 0;
|
|
|
|
GLuint mShaders[NumShaderTypes];
|
|
|
|
};
|