Bladeren bron

Added deallocate() to Material.

Mr.doob 12 jaren geleden
bovenliggende
commit
2b4d13ea44
4 gewijzigde bestanden met toevoegingen van 87 en 7 verwijderingen
  1. 1 4
      examples/webgl_test_memory.html
  2. 1 1
      examples/webgl_test_memory2.html
  3. 8 0
      src/materials/Material.js
  4. 77 2
      src/renderers/WebGLRenderer.js

+ 1 - 4
examples/webgl_test_memory.html

@@ -85,14 +85,11 @@
 
 				scene.remove( mesh );
 
-				//
+				// force deallocate
 
 				geometry.deallocate();
 				texture.deallocate();
 
-				// renderer.deallocateObject( mesh );
-				// renderer.deallocateTexture( texture );
-
 			}
 
 		</script>

+ 1 - 1
examples/webgl_test_memory2.html

@@ -131,7 +131,7 @@
 				for ( var i = 0; i < N; i ++ ) {
 
 					var mesh = meshes[ i ];
-					renderer.deallocateMaterial( mesh.material );
+					mesh.material.deallocate();
 
 				}
 

+ 8 - 0
src/materials/Material.js

@@ -5,6 +5,8 @@
 
 THREE.Material = function () {
 
+	THREE.EventTarget.call( this );
+
 	this.id = THREE.MaterialIdCount ++;
 
 	this.name = '';
@@ -114,4 +116,10 @@ THREE.Material.prototype.clone = function ( material ) {
 
 };
 
+THREE.Material.prototype.deallocate = function () {
+
+	this.dispatchEvent( { type: 'deallocate' } );
+
+};
+
 THREE.MaterialIdCount = 0;

+ 77 - 2
src/renderers/WebGLRenderer.js

@@ -448,6 +448,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 	};
 
+	/*
 	this.deallocateMaterial = function ( material ) {
 
 		var program = material.program;
@@ -510,6 +511,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 		}
 
 	};
+	*/
 
 	// Rendering
 
@@ -552,6 +554,14 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 	};
 
+	var onMaterialDeallocate = function () {
+
+		this.removeEventListener( 'deallocate', onMaterialDeallocate );
+
+		deallocateMaterial( this );
+
+	};
+
 	// Internal functions
 
 	// Buffer allocation
@@ -634,7 +644,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 	var deallocateGeometry = function ( geometry ) {
 
-		delete geometry.__webglInit;
+		geometry.__webglInit = undefined;
 
 		if ( geometry.__webglVertexBuffer !== undefined ) _gl.deleteBuffer( geometry.__webglVertexBuffer );
 		if ( geometry.__webglNormalBuffer !== undefined ) _gl.deleteBuffer( geometry.__webglNormalBuffer );
@@ -708,7 +718,70 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 		}
 
-	}
+	};
+
+	var deallocateMaterial = function ( material ) {
+
+		var program = material.program;
+
+		if ( program === undefined ) return;
+
+		material.program = undefined;
+
+		// only deallocate GL program if this was the last use of shared program
+		// assumed there is only single copy of any program in the _programs list
+		// (that's how it's constructed)
+
+		var i, il, programInfo;
+		var deleteProgram = false;
+
+		for ( i = 0, il = _programs.length; i < il; i ++ ) {
+
+			programInfo = _programs[ i ];
+
+			if ( programInfo.program === program ) {
+
+				programInfo.usedTimes --;
+
+				if ( programInfo.usedTimes === 0 ) {
+
+					deleteProgram = true;
+
+				}
+
+				break;
+
+			}
+
+		}
+
+		if ( deleteProgram === true ) {
+
+			// avoid using array.splice, this is costlier than creating new array from scratch
+
+			var newPrograms = [];
+
+			for ( i = 0, il = _programs.length; i < il; i ++ ) {
+
+				programInfo = _programs[ i ];
+
+				if ( programInfo.program !== program ) {
+
+					newPrograms.push( programInfo );
+
+				}
+
+			}
+
+			_programs = newPrograms;
+
+			_gl.deleteProgram( program );
+
+			_this.info.memory.programs --;
+
+		}
+
+	};
 
 	//
 
@@ -4998,6 +5071,8 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 	this.initMaterial = function ( material, lights, fog, object ) {
 
+		material.addEventListener( 'deallocate', onMaterialDeallocate );
+
 		var u, a, identifiers, i, parameters, maxLightCount, maxBones, maxShadows, shaderID;
 
 		if ( material instanceof THREE.MeshDepthMaterial ) {