vkdoom_m/src/common/rendering/gles/gles_shaderprogram.h
Magnus Norddahl d853961a83 Fix vulkan buffers not using the stream usage for the 2d drawer
Add BufferUsageType enum to clarify what kind of usage is expected by the buffer allocated by SetData
2021-10-26 22:43:38 -04:00

159 lines
No EOL
3.5 KiB
C++

#pragma once
#include "gles_system.h"
#include "gles_shader.h"
#include "hwrenderer/postprocessing/hw_postprocess.h"
namespace OpenGLESRenderer
{
class FShaderProgram : public PPShaderBackend
{
public:
FShaderProgram();
~FShaderProgram();
enum ShaderType
{
Vertex,
Fragment,
NumShaderTypes
};
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);
void Link(const char *name);
void SetUniformBufferLocation(int index, const char *name);
void Bind();
GLuint Handle() { return mProgram; }
//explicit operator bool() const { return mProgram != 0; }
std::unique_ptr<IDataBuffer> Uniforms;
GLuint mProgram = 0;
private:
FShaderProgram(const FShaderProgram &) = delete;
FShaderProgram &operator=(const FShaderProgram &) = delete;
void CompileShader(ShaderType type);
FString PatchShader(ShaderType type, const FString &code, const char *defines, int maxGlslVersion);
void CreateShader(ShaderType type);
FString GetShaderInfoLog(GLuint handle);
FString GetProgramInfoLog(GLuint handle);
GLuint mShaders[NumShaderTypes];
FString mShaderSources[NumShaderTypes];
FString mShaderNames[NumShaderTypes];
TArray<std::pair<FString, int>> samplerstobind;
};
template<typename T>
class ShaderUniformsGles
{
public:
ShaderUniformsGles()
{
memset(&Values, 0, sizeof(Values));
}
~ShaderUniformsGles()
{
if (mBuffer != nullptr)
delete mBuffer;
}
FString CreateDeclaration(const char* name, const std::vector<UniformFieldDesc>& fields)
{
mFields = fields;
FString decl;
decl += "\n";
for (size_t i = 0; i < fields.size(); i++)
{
decl.AppendFormat("\tuniform %s %s;\n", GetTypeStr(fields[i].Type), fields[i].Name);
}
decl += "\n";
return decl;
}
void Init()
{
if (mBuffer == nullptr)
mBuffer = screen->CreateDataBuffer(-1, false, false);
}
void SetData()
{
if (mBuffer != nullptr)
mBuffer->SetData(sizeof(T), &Values, BufferUsageType::Static);
}
IDataBuffer* GetBuffer() const
{
// OpenGL needs to mess around with this in ways that should not be part of the interface.
return mBuffer;
}
T* operator->() { return &Values; }
const T* operator->() const { return &Values; }
T Values;
std::vector<UniformFieldDesc> mFields;
std::vector<int> UniformLocation;
private:
ShaderUniformsGles(const ShaderUniformsGles&) = delete;
ShaderUniformsGles& operator=(const ShaderUniformsGles&) = delete;
IDataBuffer* mBuffer = nullptr;
private:
static 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";
case UniformType::Mat4: return "mat4";
}
}
};
class FPresentShaderBase
{
public:
virtual ~FPresentShaderBase() {}
virtual void Bind() = 0;
ShaderUniformsGles<PresentUniforms> Uniforms;
protected:
virtual void Init(const char * vtx_shader_name, const char * program_name);
std::unique_ptr<FShaderProgram> mShader;
};
class FPresentShader : public FPresentShaderBase
{
public:
void Bind() override;
};
}