Browse Source

Renderer: Fixed WebGLPrograms factorization.

tschw 10 years ago
parent
commit
b8533a25d6

+ 34 - 61
src/renderers/WebGLRenderer.js

@@ -82,8 +82,6 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 	var _this = this,
 
-	_programs = [],
-
 	// internal state cache
 
 	_currentProgram = null,
@@ -131,7 +129,6 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 	_infoMemory = {
 
-		programs: 0,
 		geometries: 0,
 		textures: 0
 
@@ -150,10 +147,16 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 		render: _infoRender,
 		memory: _infoMemory,
-		programs: _programs
+		programs: []
 
 	};
 
+	Object.defineProperty( _infoMemory, 'programs', { get: function() {
+
+		return _this.info.programs.length;
+
+	} } );
+
 	// initialize
 
 	var _gl;
@@ -589,41 +592,13 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 	function releaseMaterialProgramReference( material ) {
 
-		var program = properties.get( material ).program.program;
-
-		if ( program === undefined ) return;
+		var programInfo = properties.get( material ).program;
 
 		material.program = undefined;
 
-		for ( var i = 0, n = _programs.length; i !== n; ++ i ) {
-
-			var programInfo = _programs[ i ];
-
-			if ( programInfo.program === program ) {
-
-				var newReferenceCount = -- programInfo.usedTimes;
-
-				if ( newReferenceCount === 0 ) {
-
-					// the last material that has been using the program let
-					// go of it, so remove it from the (unordered) _programs
-					// set and deallocate the GL resource
-
-					var newLength = n - 1;
-
-					_programs[ i ] = _programs[ newLength ];
-					_programs.pop();
-
-					_gl.deleteProgram( program );
-
-					_infoMemory.programs = newLength;
-
-				}
-
-				break;
-
-			}
+		if ( programInfo !== undefined ) {
 
+			programCache.releaseProgram( programInfo );
 		}
 
 	}
@@ -1442,15 +1417,15 @@ THREE.WebGLRenderer = function ( parameters ) {
 		var parameters = programCache.getParameters( material, lights, fog, object );
 		var code = programCache.getProgramCode( material, parameters );
 
-
+		var program = materialProperties.program;
 		var programChange = true;
 
-		if ( ! materialProperties.program ) {
+		if ( program === undefined ) {
 
 			// new material
 			material.addEventListener( 'dispose', onMaterialDispose );
 
-		} else if ( materialProperties.program.code !== code ) {
+		} else if ( program.code !== code ) {
 
 			// changed glsl or parameters
 			releaseMaterialProgramReference( material );
@@ -1467,41 +1442,39 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 		}
 
-		if ( parameters.shaderID ) {
+		if ( programChange ) {
 
-			var shader = THREE.ShaderLib[ parameters.shaderID ];
+			if ( parameters.shaderID ) {
 
-			materialProperties.__webglShader = {
-				name: material.type,
-				uniforms: THREE.UniformsUtils.clone( shader.uniforms ),
-				vertexShader: shader.vertexShader,
-				fragmentShader: shader.fragmentShader
-			};
+				var shader = THREE.ShaderLib[ parameters.shaderID ];
 
-		} else {
+				materialProperties.__webglShader = {
+					name: material.type,
+					uniforms: THREE.UniformsUtils.clone( shader.uniforms ),
+					vertexShader: shader.vertexShader,
+					fragmentShader: shader.fragmentShader
+				};
 
-			materialProperties.__webglShader = {
-				name: material.type,
-				uniforms: material.uniforms,
-				vertexShader: material.vertexShader,
-				fragmentShader: material.fragmentShader
-			};
+			} else {
 
-		}
+				materialProperties.__webglShader = {
+					name: material.type,
+					uniforms: material.uniforms,
+					vertexShader: material.vertexShader,
+					fragmentShader: material.fragmentShader
+				};
 
-		material.__webglShader = materialProperties.__webglShader;
+			}
 
-		var program = programCache.getProgram( material, parameters, code );
+			material.__webglShader = materialProperties.__webglShader;
 
-		if ( programChange ) {
+			program = programCache.acquireProgram( material, parameters, code );
 
-			program.usedTimes ++;
+			materialProperties.program = program;
+			material.program = program;
 
 		}
 
-		materialProperties.program = program;
-		material.program = program;
-
 		var attributes = program.getAttributes();
 
 		if ( material.morphTargets ) {

+ 9 - 0
src/renderers/webgl/WebGLProgram.js

@@ -454,6 +454,15 @@ THREE.WebGLProgram = ( function () {
 
 		};
 
+		// free resource
+
+		this.destroy = function() {
+
+			gl.deleteProgram( program );
+			this.program = undefined;
+
+		};
+
 		// DEPRECATED
 
 		Object.defineProperties( this, {

+ 21 - 4
src/renderers/webgl/WebGLPrograms.js

@@ -1,6 +1,6 @@
 THREE.WebGLPrograms = function ( renderer, capabilities ) {
 
-	var programs = [];
+	var programs = renderer.info.programs;
 
 	var shaderIDs = {
 		MeshDepthMaterial: 'depth',
@@ -230,7 +230,7 @@ THREE.WebGLPrograms = function ( renderer, capabilities ) {
 
 	};
 
-	this.getProgram = function ( material, parameters, code ) {
+	this.acquireProgram = function ( material, parameters, code ) {
 
 		var program;
 
@@ -242,6 +242,7 @@ THREE.WebGLPrograms = function ( renderer, capabilities ) {
 			if ( programInfo.code === code ) {
 
 				program = programInfo;
+				++ program.usedTimes;
 
 				break;
 
@@ -256,8 +257,24 @@ THREE.WebGLPrograms = function ( renderer, capabilities ) {
 
 		}
 
-		return program ;
+		return program;
 
-	}
+	};
+
+	this.releaseProgram = function( program ) {
+
+		if ( -- program.usedTimes === 0 ) {
+
+			// Remove from unordered set
+			var i = programs.indexOf( program );
+			programs[ i ] = programs[ programs.length - 1 ];
+			programs.pop();
+
+			// Free WebGL resources
+			program.destroy();
+
+		}
+
+	};
 
 };