Browse Source

Improve performance of Shader:send when the Shader is not active.

It now defers uploading the uniforms to the program object until the shader becomes active again, instead of activating the shader program and deactivating it each time Shader:send is called.

--HG--
branch : minor
Alex Szpakowski 8 years ago
parent
commit
80f269d252
2 changed files with 33 additions and 21 deletions
  1. 31 21
      src/modules/graphics/opengl/Shader.cpp
  2. 2 0
      src/modules/graphics/opengl/Shader.h

+ 31 - 21
src/modules/graphics/opengl/Shader.cpp

@@ -548,13 +548,19 @@ void Shader::attach(bool temporary)
 
 
 		if (!temporary)
 		if (!temporary)
 		{
 		{
-			// make sure all sent textures are properly bound to their respective texture units
-			// note: list potentially contains texture ids of deleted/invalid textures!
+			// Make sure all textures are properly bound to their respective
+			// texture units.
 			for (int i = 1; i < (int) textureUnits.size(); ++i)
 			for (int i = 1; i < (int) textureUnits.size(); ++i)
 			{
 			{
 				if (textureUnits[i].active)
 				if (textureUnits[i].active)
 					gl.bindTextureToUnit(textureUnits[i].texture, i, false);
 					gl.bindTextureToUnit(textureUnits[i].texture, i, false);
 			}
 			}
+
+			// send any pending uniforms to the shader program.
+			for (const auto &p : pendingUniformUpdates)
+				updateUniform(p.first, p.second);
+
+			pendingUniformUpdates.clear();
 		}
 		}
 	}
 	}
 }
 }
@@ -587,11 +593,15 @@ const Shader::UniformInfo *Shader::getUniformInfo(const std::string &name) const
 
 
 void Shader::updateUniform(const UniformInfo *info, int count, bool internalUpdate)
 void Shader::updateUniform(const UniformInfo *info, int count, bool internalUpdate)
 {
 {
+	if (current != this)
+	{
+		pendingUniformUpdates.push_back(std::make_pair(info, count));
+		return;
+	}
+
 	if (!internalUpdate)
 	if (!internalUpdate)
 		flushStreamDraws();
 		flushStreamDraws();
 
 
-	TemporaryAttacher attacher(this, !internalUpdate);
-
 	int location = info->location;
 	int location = info->location;
 	UniformType type = info->baseType;
 	UniformType type = info->baseType;
 
 
@@ -682,7 +692,9 @@ void Shader::sendTextures(const UniformInfo *info, Texture **textures, int count
 	if (info->baseType != UNIFORM_SAMPLER)
 	if (info->baseType != UNIFORM_SAMPLER)
 		return;
 		return;
 
 
-	if (!internalUpdate)
+	bool shaderactive = current == this;
+
+	if (!internalUpdate && shaderactive)
 		flushStreamDraws();
 		flushStreamDraws();
 
 
 	count = std::min(count, info->count);
 	count = std::min(count, info->count);
@@ -721,14 +733,17 @@ void Shader::sendTextures(const UniformInfo *info, Texture **textures, int count
 		{
 		{
 			GLuint gltex = (GLuint) textures[i]->getHandle();
 			GLuint gltex = (GLuint) textures[i]->getHandle();
 
 
-			gl.bindTextureToUnit(gltex, texunit, false);
+			if (shaderactive)
+				gl.bindTextureToUnit(gltex, texunit, false);
 
 
-			// store texture id so it can be re-bound to the proper texture unit later
+			// Store texture id so it can be re-bound to the texture unit later.
 			textureUnits[texunit].texture = gltex;
 			textureUnits[texunit].texture = gltex;
 		}
 		}
 		else
 		else
 		{
 		{
-			gl.bindTextureToUnit((GLuint) 0, texunit, false);
+			if (shaderactive)
+				gl.bindTextureToUnit((GLuint) 0, texunit, false);
+
 			textureUnits[texunit].texture = 0;
 			textureUnits[texunit].texture = 0;
 			textureUnits[texunit].active = false;
 			textureUnits[texunit].active = false;
 		}
 		}
@@ -812,7 +827,8 @@ void Shader::setVideoTextures(GLuint ytexture, GLuint cbtexture, GLuint crtextur
 		{
 		{
 			// Store texture id so it can be re-bound later.
 			// Store texture id so it can be re-bound later.
 			textureUnits[videoTextureUnits[i]].texture = textures[i];
 			textureUnits[videoTextureUnits[i]].texture = textures[i];
-			gl.bindTextureToUnit(textures[i], videoTextureUnits[i], false);
+			if (current == this)
+				gl.bindTextureToUnit(textures[i], videoTextureUnits[i], false);
 		}
 		}
 	}
 	}
 }
 }
@@ -824,7 +840,7 @@ void Shader::checkSetScreenParams()
 	auto gfx = Module::getInstance<Graphics>(Module::M_GRAPHICS);
 	auto gfx = Module::getInstance<Graphics>(Module::M_GRAPHICS);
 	bool canvasActive = gfx->isCanvasActive();
 	bool canvasActive = gfx->isCanvasActive();
 
 
-	if (view == lastViewport && canvasWasActive == canvasActive)
+	if ((view == lastViewport && canvasWasActive == canvasActive) || current != this)
 		return;
 		return;
 
 
 	// In the shader, we do pixcoord.y = gl_FragCoord.y * params.z + params.w.
 	// In the shader, we do pixcoord.y = gl_FragCoord.y * params.z + params.w.
@@ -850,12 +866,8 @@ void Shader::checkSetScreenParams()
 	}
 	}
 
 
 	GLint location = builtinUniforms[BUILTIN_SCREEN_SIZE];
 	GLint location = builtinUniforms[BUILTIN_SCREEN_SIZE];
-
 	if (location >= 0)
 	if (location >= 0)
-	{
-		TemporaryAttacher attacher(this, true);
 		glUniform4fv(location, 1, params);
 		glUniform4fv(location, 1, params);
-	}
 
 
 	canvasWasActive = canvasActive;
 	canvasWasActive = canvasActive;
 	lastViewport = view;
 	lastViewport = view;
@@ -863,22 +875,21 @@ void Shader::checkSetScreenParams()
 
 
 void Shader::checkSetPointSize(float size)
 void Shader::checkSetPointSize(float size)
 {
 {
-	if (size == lastPointSize)
+	if (size == lastPointSize || current != this)
 		return;
 		return;
 
 
 	GLint location = builtinUniforms[BUILTIN_POINT_SIZE];
 	GLint location = builtinUniforms[BUILTIN_POINT_SIZE];
-
 	if (location >= 0)
 	if (location >= 0)
-	{
-		TemporaryAttacher attacher(this, true);
 		glUniform1f(location, size);
 		glUniform1f(location, size);
-	}
 
 
 	lastPointSize = size;
 	lastPointSize = size;
 }
 }
 
 
 void Shader::checkSetBuiltinUniforms()
 void Shader::checkSetBuiltinUniforms()
 {
 {
+	if (current != this)
+		return;
+
 	checkSetScreenParams();
 	checkSetScreenParams();
 
 
 	// We use a more efficient method for sending transformation matrices to
 	// We use a more efficient method for sending transformation matrices to
@@ -888,10 +899,9 @@ void Shader::checkSetBuiltinUniforms()
 		checkSetPointSize(gl.getPointSize());
 		checkSetPointSize(gl.getPointSize());
 
 
 		auto gfx = Module::getInstance<graphics::Graphics>(Module::M_GRAPHICS);
 		auto gfx = Module::getInstance<graphics::Graphics>(Module::M_GRAPHICS);
-		const Matrix4 &curproj = gfx->getProjection();
 
 
+		const Matrix4 &curproj = gfx->getProjection();
 		const Matrix4 &curxform = gfx->getTransform();
 		const Matrix4 &curxform = gfx->getTransform();
-		TemporaryAttacher attacher(this, true);
 
 
 		bool tpmatrixneedsupdate = false;
 		bool tpmatrixneedsupdate = false;
 
 

+ 2 - 0
src/modules/graphics/opengl/Shader.h

@@ -243,6 +243,8 @@ private:
 	// Texture unit pool for setting images
 	// Texture unit pool for setting images
 	std::vector<TextureUnit> textureUnits;
 	std::vector<TextureUnit> textureUnits;
 
 
+	std::vector<std::pair<const UniformInfo *, int>> pendingUniformUpdates;
+
 	bool canvasWasActive;
 	bool canvasWasActive;
 	Rect lastViewport;
 	Rect lastViewport;