فهرست منبع

Event system implementation for deallocating geometries and textures.
It's hard to test because, I think, chrome is now automatically deallocating stuff on it's own
@alteredq I've done a combined deallocateGeometry and some things here and there would need to be refactored but... what do you think?

Mr.doob 12 سال پیش
والد
کامیت
b81e23e898
4فایلهای تغییر یافته به همراه142 افزوده شده و 3 حذف شده
  1. 6 3
      examples/webgl_test_memory.html
  2. 8 0
      src/core/Geometry.js
  3. 120 0
      src/renderers/WebGLRenderer.js
  4. 8 0
      src/textures/Texture.js

+ 6 - 3
examples/webgl_test_memory.html

@@ -26,7 +26,7 @@
 			var camera, scene, renderer;
 
 			init();
-			setInterval( render, 1000 / 60 );
+			animate();
 
 			function init() {
 
@@ -87,8 +87,11 @@
 
 				//
 
-				renderer.deallocateObject( mesh );
-				renderer.deallocateTexture( texture );
+				geometry.deallocate();
+				texture.deallocate();
+
+				// renderer.deallocateObject( mesh );
+				// renderer.deallocateTexture( texture );
 
 			}
 

+ 8 - 0
src/core/Geometry.js

@@ -9,6 +9,8 @@
 
 THREE.Geometry = function () {
 
+	THREE.EventTarget.call( this );
+
 	this.id = THREE.GeometryIdCount ++;
 
 	this.name = '';
@@ -732,6 +734,12 @@ THREE.Geometry.prototype = {
 
 		return geometry;
 
+	},
+
+	deallocate: function () {
+
+		this.dispatchEvent( { type: 'deallocate' } );
+
 	}
 
 };

+ 120 - 0
src/renderers/WebGLRenderer.js

@@ -527,6 +527,29 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 	};
 
+	// Events
+
+	var onGeometryDeallocate = function () {
+
+		this.removeEventListener( 'deallocate', onGeometryDeallocate );
+
+		deallocateGeometry( this );
+
+		_this.info.memory.geometries --;
+
+	};
+
+	var onTextureDeallocate = function () {
+
+		this.removeEventListener( 'deallocate', onTextureDeallocate );
+
+		deallocateTexture( this );
+
+		_this.info.memory.textures --;
+
+
+	};
+
 	// Internal functions
 
 	// Buffer allocation
@@ -607,6 +630,94 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 	// Buffer deallocation
 
+	var deallocateGeometry = function ( geometry ) {
+
+		if ( geometry.__webglVertexBuffer !== undefined ) _gl.deleteBuffer( geometry.__webglVertexBuffer );
+		if ( geometry.__webglNormalBuffer !== undefined ) _gl.deleteBuffer( geometry.__webglNormalBuffer );
+		if ( geometry.__webglTangentBuffer !== undefined ) _gl.deleteBuffer( geometry.__webglTangentBuffer );
+		if ( geometry.__webglColorBuffer !== undefined ) _gl.deleteBuffer( geometry.__webglColorBuffer );
+		if ( geometry.__webglUVBuffer !== undefined ) _gl.deleteBuffer( geometry.__webglUVBuffer );
+		if ( geometry.__webglUV2Buffer !== undefined ) _gl.deleteBuffer( geometry.__webglUV2Buffer );
+
+		if ( geometry.__webglSkinIndicesBuffer !== undefined ) _gl.deleteBuffer( geometry.__webglSkinIndicesBuffer );
+		if ( geometry.__webglSkinWeightsBuffer !== undefined ) _gl.deleteBuffer( geometry.__webglSkinWeightsBuffer );
+
+		if ( geometry.__webglFaceBuffer !== undefined ) _gl.deleteBuffer( geometry.__webglFaceBuffer );
+		if ( geometry.__webglLineBuffer !== undefined ) _gl.deleteBuffer( geometry.__webglLineBuffer );
+
+		if ( geometry.__webglLineDistanceBuffer !== undefined ) _gl.deleteBuffer( geometry.__webglLineDistanceBuffer );
+
+		// geometry groups
+
+		if ( geometry.geometryGroups !== undefined ) {
+
+			for ( var g in geometry.geometryGroups ) {
+
+				var geometryGroup = geometry.geometryGroups[ g ];
+
+				if ( geometryGroup.numMorphTargets !== undefined ) {
+
+					for ( var m = 0, ml = geometryGroup.numMorphTargets; m < ml; m ++ ) {
+
+						_gl.deleteBuffer( geometryGroup.__webglMorphTargetsBuffers[ m ] );
+
+					}
+
+				}
+
+				if ( geometryGroup.numMorphNormals !== undefined ) {
+
+					for ( var m = 0, ml = geometryGroup.numMorphNormals; m < ml; m ++ ) {
+
+						_gl.deleteBuffer( geometryGroup.__webglMorphNormalsBuffers[ m ] );
+
+					}
+
+				}
+
+				deleteCustomAttributesBuffers( geometryGroup );
+
+			}
+
+		}
+
+		// custom attributes
+
+		if ( geometry.__webglCustomAttributesList !== undefined ) {
+
+			for ( var id in geometry.__webglCustomAttributesList ) {
+
+				_gl.deleteBuffer( geometry.__webglCustomAttributesList[ id ].buffer );
+
+			}
+
+		}
+
+	};
+
+	var deallocateTexture = function ( texture ) {
+
+		if ( texture.image && texture.image.__webglTextureCube ) {
+
+			// cube texture
+
+			_gl.deleteTexture( texture.image.__webglTextureCube );
+
+		} else {
+
+			// 2D texture
+
+			if ( ! texture.__webglInit ) return;
+
+			texture.__webglInit = false;
+			_gl.deleteTexture( texture.__webglTexture );
+
+		}
+
+	}
+
+	//
+
 	function deleteParticleBuffers ( geometry ) {
 
 		_gl.deleteBuffer( geometry.__webglVertexBuffer );
@@ -4484,6 +4595,12 @@ THREE.WebGLRenderer = function ( parameters ) {
 			object._modelViewMatrix = new THREE.Matrix4();
 			object._normalMatrix = new THREE.Matrix3();
 
+			if ( object.geometry !== undefined ) {
+
+				object.geometry.addEventListener( 'deallocate', onGeometryDeallocate );
+
+			}
+
 			if ( object instanceof THREE.Mesh ) {
 
 				geometry = object.geometry;
@@ -6660,6 +6777,9 @@ THREE.WebGLRenderer = function ( parameters ) {
 			if ( ! texture.__webglInit ) {
 
 				texture.__webglInit = true;
+
+				texture.addEventListener( 'deallocate', onTextureDeallocate );
+
 				texture.__webglTexture = _gl.createTexture();
 
 				_this.info.memory.textures ++;

+ 8 - 0
src/textures/Texture.js

@@ -6,6 +6,8 @@
 
 THREE.Texture = function ( image, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
 
+	THREE.EventTarget.call( this );
+
 	this.id = THREE.TextureIdCount ++;
 
 	this.name = '';
@@ -73,6 +75,12 @@ THREE.Texture.prototype = {
 
 		return texture;
 
+	},
+
+	deallocate: function () {
+
+		this.dispatchEvent( { type: 'deallocate' } );
+
 	}
 
 };