[Bf-blender-cvs] [8c09826d58a] blender2.8: Gawain: Optimize shader uniform access

Sergey Sharybin noreply at git.blender.org
Thu Jun 1 12:34:02 CEST 2017


Commit: 8c09826d58ad219b7229fcce396b967866458e99
Author: Sergey Sharybin
Date:   Thu Jun 1 12:26:27 2017 +0200
Branches: blender2.8
https://developer.blender.org/rB8c09826d58ad219b7229fcce396b967866458e99

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

===================================================================

M	intern/gawain/gawain/shader_interface.h
M	intern/gawain/src/shader_interface.c

===================================================================

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
 		}




More information about the Bf-blender-cvs mailing list