Commit 784ef175 authored by Johannes Braun's avatar Johannes Braun
Browse files

Caching uniform informations and auto-casting when updating (only one...

Caching uniform informations and auto-casting when updating (only one uniform(...) method now for all types); Optimized uniform update situations.
parent 861333e2
<linespace version="1.0">
<item name="subdivisions" value="40"/>
<item name="radial-subdivision" value="10"/>
<item name="subdivisions" value="4"/>
<item name="radial-subdivision" value="4"/>
<item name="generator" value="gpu"/>
</linespace>
......@@ -9,7 +9,6 @@ uniform struct
{
uint num_bounces;
uint current_sample;
uint max_samples;
float clamp_direct;
float clamp_indirect;
uint bounce_thresholds;
......
......@@ -21,14 +21,14 @@ uniform struct {
sampler2D map_displacement;
sampler2D map_emissive;
vec3 color_diffuse;
vec3 color_ambient;
vec3 color_diffuse;
vec3 color_specular;
vec3 color_transparent;
vec3 color_emissive;
bool has_diffuse;
bool has_ambient;
bool has_diffuse;
bool has_specular;
bool has_transparent;
bool has_normal;
......@@ -60,14 +60,14 @@ layout(location = 6) out vec4 out_final_lighting;
void main()
{
vec2 parallax_texcoord = out_texcoord;
if(u_material.has_displacement){
vec3 to_eye = normalize(out_camera_position - out_fragment_position);
float height = dot(luminance, texture2D(u_material.map_displacement, out_texcoord).rgb);
//Our heightmap only has one color channel.
float v = height * scaleBias.r - scaleBias.g;
parallax_texcoord = out_texcoord + (to_eye.xy * v);
parallax_texcoord = out_texcoord + (to_eye.xy * v);
}
out_final_position = out_view_position;
......@@ -78,41 +78,19 @@ void main()
discard;
}
out_final_normal = u_material.has_normal ?
vec4((out_tangent_space)*(normalize((texture( u_material.map_normal, parallax_texcoord).xyz)*2.0 - 1.0)), 0) :
out_final_normal = u_material.has_normal ?
vec4((out_tangent_space)*(normalize((texture( u_material.map_normal, parallax_texcoord).xyz)*2.0 - 1.0)), 0) :
vec4(out_normal.rgb, 0);
if(u_material.color_transparent.xyz != vec3(0) || u_material.has_transparent)
{
out_final_spec = vec4(u_material.color_transparent, -(u_material.specular_exponent / 100.0)) * (u_material.has_transparent ? vec4(texture(u_material.map_transparent, parallax_texcoord).xyz, 1) : vec4(vec3(1), 1));
}
else
else
{
out_final_spec = vec4(u_material.color_specular, u_material.specular_exponent / 100.0) * (u_material.has_specular ? texture(u_material.map_specular, parallax_texcoord) : vec4(1));
}
out_final_id = u_color_id;
out_final_lighting = u_material.has_emissive ? vec4(texture(u_material.map_emissive, parallax_texcoord).xyz, 1) : vec4(u_material.color_emissive, 1);
}
#include "program.h"
#include <util/log.h>
namespace glare
{
namespace core
......@@ -36,6 +34,21 @@ namespace glare
gl::detachShader(m_handle, shader->id());
Log_Debug << "Program was linked successfully.";
}
int num_uniforms;
gl::getProgramiv(m_handle, gl::ProgramParameter::eActiveUniforms, &num_uniforms);
for (int i = 0; i < num_uniforms; ++i) {
UniformInfo data;
int max_length = 200;
char* name = new char[max_length];
gl::getActiveUniform(m_handle, i, max_length, &data.size, &data.type, name);
data.index = i;
data.name = name;
m_uniforms[data.name] = data;
delete[] name;
}
}
Program::Program(std::shared_ptr<Shader> shader)
......@@ -66,87 +79,7 @@ namespace glare
{
gl::useProgram(m_handle);
}
void Program::uniform1i(const std::string& name, int32_t value) const
{
gl::programUniform1i(m_handle, uniformLocation(name), value);
}
void Program::uniform1i64(const std::string& name, int64_t value) const
{
gl::programUniformi64(m_handle, uniformLocation(name), value);
}
void Program::uniform1ui(const std::string& name, uint32_t value) const
{
gl::programUniform1ui(m_handle, uniformLocation(name), value);
}
void Program::uniform1ui64(const std::string& name, uint64_t value) const
{
gl::programUniformui64(m_handle, uniformLocation(name), value);
}
void Program::uniform1f(const std::string& name, float value) const
{
gl::programUniform1f(m_handle, uniformLocation(name), value);
}
void Program::uniform1d(const std::string& name, double value) const
{
gl::programUniform1d(m_handle, uniformLocation(name), value);
}
void Program::uniform2f(const std::string& name, glm::vec2 value) const
{
gl::programUniform2fv(m_handle, uniformLocation(name), 1, glm::value_ptr(value));
}
void Program::uniform3f(const std::string& name, glm::vec3 value) const
{
gl::programUniform3fv(m_handle, uniformLocation(name), 1, glm::value_ptr(value));
}
void Program::uniform4f(const std::string& name, glm::vec4 value) const
{
gl::programUniform4fv(m_handle, uniformLocation(name), 1, glm::value_ptr(value));
}
void Program::uniform2i(const std::string& name, glm::ivec2 value) const
{
gl::programUniform2iv(m_handle, uniformLocation(name), 1, glm::value_ptr(value));
}
void Program::uniform3i(const std::string& name, glm::ivec3 value) const
{
gl::programUniform3iv(m_handle, uniformLocation(name), 1, glm::value_ptr(value));
}
void Program::uniform4i(const std::string& name, glm::ivec4 value) const
{
gl::programUniform4iv(m_handle, uniformLocation(name), 1, glm::value_ptr(value));
}
void Program::uniform2ui(const std::string& name, glm::uvec2 value) const
{
gl::programUniform2uiv(m_handle, uniformLocation(name), 1, glm::value_ptr(value));
}
void Program::uniform3ui(const std::string& name, glm::uvec3 value) const
{
gl::programUniform3uiv(m_handle, uniformLocation(name), 1, glm::value_ptr(value));
}
void Program::uniform4ui(const std::string& name, glm::uvec4 value) const
{
gl::programUniform4uiv(m_handle, uniformLocation(name), 1, glm::value_ptr(value));
}
void Program::uniformMat4(const std::string& name, glm::mat4 value) const
{
gl::programUniformMatrix4fv(m_handle, uniformLocation(name), 1, false, glm::value_ptr(value));
}
void Program::storageBuffer(const std::string& name, const Buffer<gl::BufferType::eShaderStorage> &buffer) const
{
buffer.bind(bufferBlock(name));
......@@ -162,6 +95,14 @@ namespace glare
return gl::getUniformLocation(m_handle, uniform);
}
UniformInfo Program::uniformInfo(const std::string &uniform) const
{
if (m_uniforms.count(uniform) != 0) {
return m_uniforms.at(uniform);
}
return empty_uniform_info;
}
int Program::bufferBlock(const std::string& block) const
{
const unsigned index = gl::getProgramResourceIndex(m_handle, gl::ProgramInterface::eShaderStorageBlock, block);
......@@ -178,5 +119,193 @@ namespace glare
{
return (global % local == 0) ? global / local : global / local + 1;
}
void Program::uniformUpdate(gl::UniformType type, unsigned location, const void* data) const
{
switch (type)
{
case gl::UniformType::eFloat:
gl::programUniform1f(m_handle, location, *(reinterpret_cast<const float*>(data)));
break;
case gl::UniformType::eFloat2:
gl::programUniform2fv(m_handle, location, 1, (reinterpret_cast<const float*>(data)));
break;
case gl::UniformType::eFloat3:
gl::programUniform3fv(m_handle, location, 1, (reinterpret_cast<const float*>(data)));
break;
case gl::UniformType::eFloat4:
gl::programUniform4fv(m_handle, location, 1, (reinterpret_cast<const float*>(data)));
break;
case gl::UniformType::eDouble:
gl::programUniform1d(m_handle, location, *(reinterpret_cast<const double*>(data)));
break;
case gl::UniformType::eDouble2:
gl::programUniform2dv(m_handle, location, 1, (reinterpret_cast<const double*>(data)));
break;
case gl::UniformType::eDouble3:
gl::programUniform3dv(m_handle, location, 1, (reinterpret_cast<const double*>(data)));
break;
case gl::UniformType::eDouble4:
gl::programUniform4dv(m_handle, location, 1, (reinterpret_cast<const double*>(data)));
break;
case gl::UniformType::eBool:
case gl::UniformType::eInt:
gl::programUniform1i(m_handle, location, *(reinterpret_cast<const int*>(data)));
break;
case gl::UniformType::eBool2:
case gl::UniformType::eInt2:
gl::programUniform2iv(m_handle, location, 1, (reinterpret_cast<const int*>(data)));
break;
case gl::UniformType::eBool3:
case gl::UniformType::eInt3:
gl::programUniform3iv(m_handle, location, 1, (reinterpret_cast<const int*>(data)));
break;
case gl::UniformType::eBool4:
case gl::UniformType::eInt4:
gl::programUniform4iv(m_handle, location, 1, (reinterpret_cast<const int*>(data)));
break;
case gl::UniformType::eUInt:
gl::programUniform1ui(m_handle, location, *(reinterpret_cast<const unsigned*>(data)));
break;
case gl::UniformType::eUInt2:
gl::programUniform2uiv(m_handle, location, 1, (reinterpret_cast<const unsigned*>(data)));
break;
case gl::UniformType::eUInt3:
gl::programUniform3uiv(m_handle, location, 1, (reinterpret_cast<const unsigned*>(data)));
break;
case gl::UniformType::eUInt4:
gl::programUniform4uiv(m_handle, location, 1, (reinterpret_cast<const unsigned*>(data)));
break;
case gl::UniformType::eFloatMat2:
gl::programUniformMatrix2fv(m_handle, location, 1, false, (reinterpret_cast<const float*>(data)));
break;
case gl::UniformType::eFloatMat3:
gl::programUniformMatrix3fv(m_handle, location, 1, false, (reinterpret_cast<const float*>(data)));
break;
case gl::UniformType::eFloatMat4:
gl::programUniformMatrix4fv(m_handle, location, 1, false, (reinterpret_cast<const float*>(data)));
break;
case gl::UniformType::eFloatMat2x3:
gl::programUniformMatrix2x3fv(m_handle, location, 1, false, (reinterpret_cast<const float*>(data)));
break;
case gl::UniformType::eFloatMat2x4:
gl::programUniformMatrix2x4fv(m_handle, location, 1, false, (reinterpret_cast<const float*>(data)));
break;
case gl::UniformType::eFloatMat3x2:
gl::programUniformMatrix3x2fv(m_handle, location, 1, false, (reinterpret_cast<const float*>(data)));
break;
case gl::UniformType::eFloatMat3x4:
gl::programUniformMatrix3x4fv(m_handle, location, 1, false, (reinterpret_cast<const float*>(data)));
break;
case gl::UniformType::eFloatMat4x2:
gl::programUniformMatrix4x2fv(m_handle, location, 1, false, (reinterpret_cast<const float*>(data)));
break;
case gl::UniformType::eFloatMat4x3:
gl::programUniformMatrix4x3fv(m_handle, location, 1, false, (reinterpret_cast<const float*>(data)));
break;
case gl::UniformType::eDoubleMat2:
gl::programUniformMatrix2dv(m_handle, location, 1, false, (reinterpret_cast<const double*>(data)));
break;
case gl::UniformType::eDoubleMat3:
gl::programUniformMatrix3dv(m_handle, location, 1, false, (reinterpret_cast<const double*>(data)));
break;
case gl::UniformType::eDoubleMat4:
gl::programUniformMatrix4dv(m_handle, location, 1, false, (reinterpret_cast<const double*>(data)));
break;
case gl::UniformType::eDoubleMat2x3:
gl::programUniformMatrix2x3dv(m_handle, location, 1, false, (reinterpret_cast<const double*>(data)));
break;
case gl::UniformType::eDoubleMat2x4:
gl::programUniformMatrix2x4dv(m_handle, location, 1, false, (reinterpret_cast<const double*>(data)));
break;
case gl::UniformType::eDoubleMat3x2:
gl::programUniformMatrix3x2dv(m_handle, location, 1, false, (reinterpret_cast<const double*>(data)));
break;
case gl::UniformType::eDoubleMat3x4:
gl::programUniformMatrix3x4dv(m_handle, location, 1, false, (reinterpret_cast<const double*>(data)));
break;
case gl::UniformType::eDoubleMat4x2:
gl::programUniformMatrix4x2dv(m_handle, location, 1, false, (reinterpret_cast<const double*>(data)));
break;
case gl::UniformType::eDoubleMat4x3:
gl::programUniformMatrix4x3dv(m_handle, location, 1, false, (reinterpret_cast<const double*>(data)));
break;
case gl::UniformType::eSampler1d:
case gl::UniformType::eSampler2d:
case gl::UniformType::eSampler3d:
case gl::UniformType::eSamplerCube:
case gl::UniformType::eSampler1dShadow:
case gl::UniformType::eSampler2dShadow:
case gl::UniformType::eSampler1dArray:
case gl::UniformType::eSampler2dArray:
case gl::UniformType::eSampler1dArrayShadow:
case gl::UniformType::eSampler2dArrayShadow:
case gl::UniformType::eSampler2dMultisample:
case gl::UniformType::eSampler2dMultisampleArray:
case gl::UniformType::eSamplerCubeShadow:
case gl::UniformType::eSamplerBuffer:
case gl::UniformType::eSampler2dRect:
case gl::UniformType::eSampler2dRectShadow:
case gl::UniformType::eIntSampler1d:
case gl::UniformType::eIntSampler2d:
case gl::UniformType::eIntSampler3d:
case gl::UniformType::eIntSamplerCube:
case gl::UniformType::eIntSampler1dArray:
case gl::UniformType::eIntSampler2dArray:
case gl::UniformType::eIntSampler2dMultisample:
case gl::UniformType::eIntSampler2dMultisampleArray:
case gl::UniformType::eIntSamplerBuffer:
case gl::UniformType::eIntSampler2dRect:
case gl::UniformType::eUIntSampler1d:
case gl::UniformType::eUIntSampler2d:
case gl::UniformType::eUIntSampler3d:
case gl::UniformType::eUIntSamplerCube:
case gl::UniformType::eUIntSampler1dArray:
case gl::UniformType::eUIntSampler2dArray:
case gl::UniformType::eUIntSampler2dMultisample:
case gl::UniformType::eUIntSampler2dMultisampleArray:
case gl::UniformType::eUIntSamplerBuffer:
case gl::UniformType::eUIntSampler2dRect:
case gl::UniformType::eImage1d:
case gl::UniformType::eImage2d:
case gl::UniformType::eImage3d:
case gl::UniformType::eImage2dRect:
case gl::UniformType::eImageCube:
case gl::UniformType::eImageBuffer:
case gl::UniformType::eImage1dArray:
case gl::UniformType::eImage2dArray:
case gl::UniformType::eImage2dMultisample:
case gl::UniformType::eImage2dMultisampleArray:
case gl::UniformType::eIntImage1d:
case gl::UniformType::eIntImage2d:
case gl::UniformType::eIntImage3d:
case gl::UniformType::eIntImage2dRect:
case gl::UniformType::eIntImageCube:
case gl::UniformType::eIntImageBuffer:
case gl::UniformType::eIntImage1dArray:
case gl::UniformType::eIntImage2dArray:
case gl::UniformType::eIntImage1dMultisample:
case gl::UniformType::eIntImage1dMultisampleArray:
case gl::UniformType::eUIntImage1d:
case gl::UniformType::eUIntImage2d:
case gl::UniformType::eUIntImage3d:
case gl::UniformType::eUIntImage2dRect:
case gl::UniformType::eUIntImageCube:
case gl::UniformType::eUIntImageBuffer:
case gl::UniformType::eUIntImage1dArray:
case gl::UniformType::eUIntImage2dArray:
case gl::UniformType::eUIntImage2dMultisample:
case gl::UniformType::eUIntImage2dMultisampleArray:
case gl::UniformType::eUIntImageAtomicCounter:
gl::programUniformui64(m_handle, location, *reinterpret_cast<const uint64_t*>(data));
break;
}
}
}
}
\ No newline at end of file
#ifndef INCLUDE_SHADER_PROGRAM_H
#define INCLUDE_SHADER_PROGRAM_H
#include <string>
#include <cinttypes>
#include <map>
#include <string>
#include <glm/ext.hpp>
#include <util/opengl.h>
#include <util/files.h>
#include <util/log.h>
#include "shader.h"
......@@ -14,6 +16,16 @@ namespace glare
{
namespace core
{
struct UniformInfo
{
unsigned index;
std::string name;
int size;
gl::UniformType type;
};
const UniformInfo empty_uniform_info{ 0, "", -1 };
class Program
{
public:
......@@ -32,25 +44,11 @@ namespace glare
// We're getting generic again
void use() const;
// base types
void uniform1i(const std::string& name, int32_t value) const;
void uniform1i64(const std::string& name, int64_t value) const;
void uniform1ui(const std::string& name, uint32_t value) const;
void uniform1ui64(const std::string& name, uint64_t value) const;
void uniform1f(const std::string& name, float value) const;
void uniform1d(const std::string& name, double value) const;
// structures
void uniform2f(const std::string& name, glm::vec2 value) const;
void uniform3f(const std::string& name, glm::vec3 value) const;
void uniform4f(const std::string& name, glm::vec4 value) const;
void uniform2i(const std::string& name, glm::ivec2 value) const;
void uniform3i(const std::string& name, glm::ivec3 value) const;
void uniform4i(const std::string& name, glm::ivec4 value) const;
void uniform2ui(const std::string& name, glm::uvec2 value) const;
void uniform3ui(const std::string& name, glm::uvec3 value) const;
void uniform4ui(const std::string& name, glm::uvec4 value) const;
void uniformMat4(const std::string& name, glm::mat4 value) const;
template<typename T> void uniform(const std::string &name, const T& data) const;
template<> void uniform<bool>(const std::string &name, const bool& data) const;
template<> void uniform<glm::bvec2>(const std::string &name, const glm::bvec2& data) const;
template<> void uniform<glm::bvec3>(const std::string &name, const glm::bvec3& data) const;
template<> void uniform<glm::bvec4>(const std::string &name, const glm::bvec4& data) const;
// buffers
void storageBuffer(const std::string& name, const Buffer<gl::BufferType::eShaderStorage> &buffer) const;
......@@ -61,16 +59,217 @@ namespace glare
// resource getters
int attributeLocation(const std::string &attribute) const;
int uniformLocation(const std::string &uniform) const;
UniformInfo uniformInfo(const std::string &uniform) const;
int bufferBlock(const std::string& block) const;
unsigned id() const;
private:
void uniformUpdate(gl::UniformType type, unsigned location, const void* data) const;
unsigned invocations(unsigned global, unsigned local);
template<typename T>
bool typeValid(gl::UniformType type) const;
gl::handle::shader_program m_handle;
std::map<std::string, UniformInfo> m_uniforms;
};
template<> void Program::uniform<bool>(const std::string &name, const bool& data) const
{
uniform<int>(name, int(data));
}
template<> void Program::uniform<glm::bvec2>(const std::string &name, const glm::bvec2& data) const
{
uniform<glm::ivec2>(name, data);
}
template<> void Program::uniform<glm::bvec3>(const std::string &name, const glm::bvec3& data) const
{
uniform<glm::ivec3>(name, data);
}
template<> void Program::uniform<glm::bvec4>(const std::string &name, const glm::bvec4& data) const
{
uniform<glm::ivec4>(name, data);
}
template<typename T>
void Program::uniform(const std::string &name, const T& data) const
{
if (m_uniforms.count(name) != 0) {
const auto& d = m_uniforms.at(name);
#ifndef NDEBUG
if (!typeValid<T>(d.type))
{
Log_Error << "Type " << typeid(T).name() << " might not be a good choice for the uniform \"" << d.name << "\". Do you use a different type in your shader?";
}
#endif
uniformUpdate(d.type, d.index, reinterpret_cast<const unsigned char*>(&data));
}
}
template<typename T>
bool Program::typeValid(gl::UniformType type) const
{
switch (type)
{
case gl::UniformType::eInt:
return typeid(T) == typeid(int) || typeid(T) == typeid(int);
case gl::UniformType::eInt2:
return typeid(T) == typeid(glm::ivec2) || typeid(T) == typeid(glm::uvec2);
case gl::UniformType::eInt3:
return typeid(T) == typeid(glm::ivec3) || typeid(T) == typeid(glm::uvec3);
case gl::UniformType::eInt4:
return typeid(T) == typeid(glm::ivec4) || typeid(T) == typeid(glm::uvec4);
case gl::UniformType::eBool:
return typeid(T) == typeid(unsigned) || typeid(T) == typeid(bool) || typeid(T) == typeid(int);
case gl::UniformType::eBool2:
return typeid(T) == typeid(glm::uvec2) || typeid(T) == typeid(glm::bvec2) || typeid(T) == typeid(glm::ivec2);
case gl::UniformType::eBool3:
return typeid(T) == typeid(glm::uvec3) || typeid(T) == typeid(glm::bvec3) || typeid(T) == typeid(glm::ivec3);
case gl::UniformType::eBool4:
return typeid(T) == typeid(glm::uvec4) || typeid(T) == typeid(glm::bvec4) || typeid(T) == typeid(glm::ivec4);
case gl::UniformType::eUInt:
return typeid(T) == typeid(unsigned);
case gl::UniformType::eUInt2:
return typeid(T) == typeid(glm::uvec2);
case gl::UniformType::eUInt3:
return typeid(T) == typeid(glm::uvec3);
case gl::UniformType::eUInt4:
return typeid(T) == typeid(glm::uvec4);
case gl::UniformType::eFloatMat2:
return typeid(T) == typeid(glm::mat2);
case gl::UniformType::eFloatMat3:
return typeid(T) == typeid(glm::mat3);
case gl::UniformType::eFloatMat4:
return typeid(T) == typeid(glm::mat4);
case gl::UniformType::eFloatMat2x3:
return typeid(T) == typeid(glm::mat2x3);
case gl::UniformType::eFloatMat2x4:
return typeid(T) == typeid(glm::mat2x4);
case gl::UniformType::eFloatMat3x2:
return typeid(T) == typeid(glm::mat3x2);
case gl::UniformType::eFloatMat3x4:
return typeid(T) == typeid(glm::mat3x4);