From 8c09826d58ad219b7229fcce396b967866458e99 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 1 Jun 2017 12:26:27 +0200 Subject: Gawain: Optimize shader uniform access Before this change Gawain was doing list lookup twice, doing string comparison of every and each input which is not efficient and not friendly for CPUs with small cache size. Now we store hash of input name together with actual name and compare hashes first. Additionally, we do everything in a single pass which is much better from cache coherency point of view. This brings Eevee cache population time from 80ms to 60ms on my desktop and from 800ms to 400ms for Clement when navigating in a file from T50027. Reviewers: merwin, dfelinto Subscribers: fclem Differential Revision: https://developer.blender.org/D2697 --- intern/gawain/gawain/shader_interface.h | 1 + intern/gawain/src/shader_interface.c | 52 ++++++++++++++++++--------------- 2 files changed, 29 insertions(+), 24 deletions(-) (limited to 'intern') diff --git a/intern/gawain/gawain/shader_interface.h b/intern/gawain/gawain/shader_interface.h index 5c37d507806..cf10180e3d5 100644 --- a/intern/gawain/gawain/shader_interface.h +++ b/intern/gawain/gawain/shader_interface.h @@ -32,6 +32,7 @@ typedef enum { typedef struct { const char* name; + unsigned name_hash; GLenum gl_type; BuiltinUniform builtin_type; // only for uniform inputs GLint size; diff --git a/intern/gawain/src/shader_interface.c b/intern/gawain/src/shader_interface.c index 4a07f954c36..f0da342f088 100644 --- a/intern/gawain/src/shader_interface.c +++ b/intern/gawain/src/shader_interface.c @@ -49,6 +49,24 @@ static bool match(const char* a, const char* b) return strcmp(a, b) == 0; } +static unsigned hash_string(const char *str) + { + unsigned i = 0, c; + + while ((c = *str++)) + { + i = i * 37 + c; + } + + return i; + } + +static inline void set_input_name(ShaderInput* input, const char* name) + { + input->name = name; + input->name_hash = hash_string(name); + } + // keep these in sync with BuiltinUniform order #define FIRST_MAT4_UNIFORM UNIFORM_MODELVIEW #define LAST_MAT4_UNIFORM UNIFORM_PROJECTION_INV @@ -67,7 +85,7 @@ static bool setup_builtin_uniform(ShaderInput* input, const char* name) const char* builtin_name = BuiltinUniform_name(u); if (match(name, builtin_name)) { - input->name = builtin_name; + set_input_name(input, builtin_name); input->builtin_type = u; return true; } @@ -78,7 +96,7 @@ static bool setup_builtin_uniform(ShaderInput* input, const char* name) const char* builtin_name = BuiltinUniform_name(UNIFORM_NORMAL); if (match(name, builtin_name)) { - input->name = builtin_name; + set_input_name(input, builtin_name); input->builtin_type = UNIFORM_NORMAL; return true; } @@ -89,7 +107,7 @@ static bool setup_builtin_uniform(ShaderInput* input, const char* name) const char* builtin_name = BuiltinUniform_name(UNIFORM_COLOR); if (match(name, builtin_name)) { - input->name = builtin_name; + set_input_name(input, builtin_name); input->builtin_type = UNIFORM_COLOR; return true; } @@ -149,7 +167,7 @@ ShaderInterface* ShaderInterface_create(GLint program) ; // reclaim space from name buffer (don't advance offset) else { - input->name = name; + set_input_name(input, name); name_buffer_offset += name_len + 1; // include NULL terminator } #if SUPPORT_LEGACY_GLSL @@ -181,7 +199,7 @@ ShaderInterface* ShaderInterface_create(GLint program) assert(input->location != -1); #endif - input->name = name; + set_input_name(input, name); name_buffer_offset += name_len + 1; // include NULL terminator #if SUPPORT_LEGACY_GLSL } @@ -233,33 +251,19 @@ void ShaderInterface_discard(ShaderInterface* shaderface) const ShaderInput* ShaderInterface_uniform(const ShaderInterface* shaderface, const char* name) { - // search through custom uniforms first + const unsigned name_hash = hash_string(name); for (uint32_t i = 0; i < shaderface->uniform_ct; ++i) { const ShaderInput* uniform = shaderface->inputs + i; - if (uniform->builtin_type == UNIFORM_CUSTOM) - { #if SUPPORT_LEGACY_GLSL - if (uniform->name == NULL) continue; + if (uniform->name == NULL) continue; #endif - if (match(uniform->name, name)) - return uniform; - } - } + if (uniform->name_hash != name_hash) continue; - // search through builtin uniforms next - for (uint32_t i = 0; i < shaderface->uniform_ct; ++i) - { - const ShaderInput* uniform = shaderface->inputs + i; - -#if SUPPORT_LEGACY_GLSL - if (uniform->name == NULL) continue; -#endif - if (uniform->builtin_type != UNIFORM_CUSTOM) - if (match(uniform->name, name)) - return uniform; + if (match(uniform->name, name)) + return uniform; // TODO: warn if we find a matching builtin, since these can be looked up much quicker --v } -- cgit v1.2.3