Skip to content

Commit

Permalink
UPBGE: Avoid calling glGetUniformLocation while setting a uniform thr…
Browse files Browse the repository at this point in the history
…ough BL_Shader. (#733)

All the setUniform functions in BL_Shader are using name to identify the uniform,
these functions call RAS_Shader::GetUniformLocation.

This last function was naively calling indirectly glGetUniformLocation, but even
simple OpenGL calls cost more than caching.
Fortunatly OpenGL allows to enumerate all active uniforms thanks to glGetActiveUniform,
this function is used in GPUShader side inside function GPU_shader_get_uniform_infos
constructing a list of GPUUniformInfo storing the uniform location, size, type and
name.

These uniform info are used in RAS_Shader::ExtractUniformInfos which insert the
info in a map associating to the name the location, size and type> This map is then
used into GetUniformLocation.

Tested with a 4 uniforms shader and 1000 updates :
Previous : 3.26ms
Current : 2.88ms
  • Loading branch information
panzergame authored Jul 25, 2018
1 parent 155b83a commit 18e5a96
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 6 deletions.
10 changes: 10 additions & 0 deletions source/blender/gpu/GPU_shader.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,16 @@ void GPU_shader_unbind(void);

int GPU_shader_program(GPUShader *shader);

typedef struct GPUUniformInfo
{
unsigned int location;
unsigned int size;
unsigned int type;
char name[255];
} GPUUniformInfo;

int GPU_shader_get_uniform_infos(GPUShader *shader, GPUUniformInfo **infos);

void *GPU_shader_get_interface(GPUShader *shader);
void GPU_shader_set_interface(GPUShader *shader, void *interface);
int GPU_shader_get_uniform(GPUShader *shader, const char *name);
Expand Down
21 changes: 21 additions & 0 deletions source/blender/gpu/intern/gpu_shader.c
Original file line number Diff line number Diff line change
Expand Up @@ -598,6 +598,27 @@ void GPU_shader_free(GPUShader *shader)
MEM_freeN(shader);
}

int GPU_shader_get_uniform_infos(GPUShader *shader, GPUUniformInfo **infos)
{
int count;
glGetProgramiv(shader->program, GL_ACTIVE_UNIFORMS, &count);

if (count == 0) {
*infos = NULL;
return 0;
}

*infos = MEM_callocN(sizeof(GPUUniformInfo) * count, "GPUUniformInfo");

for (unsigned int i = 0; i < count; ++i) {
GPUUniformInfo *info = &((*infos)[i]);
glGetActiveUniform(shader->program, i, 255, NULL, (int *)&info->size, &info->type, info->name);
info->location = GPU_shader_get_uniform(shader, info->name);
}

return count;
}

int GPU_shader_get_uniform(GPUShader *shader, const char *name)
{
return glGetUniformLocation(shader->program, name);
Expand Down
29 changes: 23 additions & 6 deletions source/gameengine/Rasterizer/RAS_Shader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,8 @@ bool RAS_Shader::LinkProgram()
return false;
}

ExtractUniformInfos();

m_error = false;
return true;
}
Expand All @@ -321,6 +323,20 @@ void RAS_Shader::ValidateProgram()
}
}

void RAS_Shader::ExtractUniformInfos()
{
m_uniformInfos.clear();

GPUUniformInfo *infos;
const unsigned int count = GPU_shader_get_uniform_infos(m_shader, &infos);

for (unsigned short i = 0; i < count; ++i) {
const GPUUniformInfo& gpuinfo = infos[i];
const UniformInfo info = {gpuinfo.location, (unsigned short)gpuinfo.size, gpuinfo.type};
m_uniformInfos.emplace(gpuinfo.name, info);
}
}

bool RAS_Shader::GetError()
{
return m_error;
Expand Down Expand Up @@ -474,13 +490,14 @@ void RAS_Shader::BindAttribute(const std::string& attr, int loc)
int RAS_Shader::GetUniformLocation(const std::string& name, bool debug)
{
BLI_assert(m_shader != nullptr);
int location = GPU_shader_get_uniform(m_shader, name.c_str());

if (location == -1 && debug) {
CM_Error("invalid uniform value: " << name << ".");
const auto& it = m_uniformInfos.find(name);
if (it == m_uniformInfos.end()) {
if (debug) {
CM_Error("invalid uniform value: " << name << ".");
}
return -1;
}

return location;
return it->second.location;
}

void RAS_Shader::SetUniform(int uniform, const mt::vec2 &vec)
Expand Down
13 changes: 13 additions & 0 deletions source/gameengine/Rasterizer/RAS_Shader.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#include <string>
#include <vector>
#include <unordered_map>

#define SORT_UNIFORMS 1

Expand Down Expand Up @@ -107,6 +108,16 @@ class RAS_Shader
};

protected:
struct UniformInfo
{
unsigned int location;
unsigned short size;
unsigned int type;
};

/// Information (location, type, size) on existing uniforms.
std::unordered_map<std::string, UniformInfo> m_uniformInfos;

typedef std::vector<RAS_Uniform *> RAS_UniformVec;
typedef std::vector<RAS_DefUniform *> RAS_UniformVecDef;

Expand All @@ -129,6 +140,7 @@ class RAS_Shader
// Compiles and links the shader
virtual bool LinkProgram();
void ValidateProgram();
void ExtractUniformInfos();

// search by location
RAS_Uniform *FindUniform(const int location);
Expand All @@ -140,6 +152,7 @@ class RAS_Shader
RAS_Shader();
virtual ~RAS_Shader();


bool GetError();
bool Ok() const;
GPUShader *GetGPUShader();
Expand Down

0 comments on commit 18e5a96

Please sign in to comment.