Browse Source

Updated builds.

Mugen87 1 year ago
parent
commit
e94c7eae26
5 changed files with 678 additions and 210 deletions
  1. 226 70
      build/three.cjs
  2. 226 70
      build/three.js
  3. 0 0
      build/three.min.js
  4. 226 70
      build/three.module.js
  5. 0 0
      build/three.module.min.js

+ 226 - 70
build/three.cjs

@@ -19120,6 +19120,9 @@ function WebGLShader( gl, type, string ) {
 
 }
 
+// From https://www.khronos.org/registry/webgl/extensions/KHR_parallel_shader_compile/
+const COMPLETION_STATUS_KHR = 0x91B1;
+
 let programIdCount = 0;
 
 function handleSource( string, errorLine ) {
@@ -20007,87 +20010,94 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) {
 
 	gl.linkProgram( program );
 
-	// check for link errors
-	if ( renderer.debug.checkShaderErrors ) {
+	function onFirstUse( self ) {
 
-		const programLog = gl.getProgramInfoLog( program ).trim();
-		const vertexLog = gl.getShaderInfoLog( glVertexShader ).trim();
-		const fragmentLog = gl.getShaderInfoLog( glFragmentShader ).trim();
+		// check for link errors
+		if ( renderer.debug.checkShaderErrors ) {
 
-		let runnable = true;
-		let haveDiagnostics = true;
+			const programLog = gl.getProgramInfoLog( program ).trim();
+			const vertexLog = gl.getShaderInfoLog( glVertexShader ).trim();
+			const fragmentLog = gl.getShaderInfoLog( glFragmentShader ).trim();
 
-		if ( gl.getProgramParameter( program, gl.LINK_STATUS ) === false ) {
+			let runnable = true;
+			let haveDiagnostics = true;
 
-			runnable = false;
+			if ( gl.getProgramParameter( program, gl.LINK_STATUS ) === false ) {
 
-			if ( typeof renderer.debug.onShaderError === 'function' ) {
+				runnable = false;
 
-				renderer.debug.onShaderError( gl, program, glVertexShader, glFragmentShader );
+				if ( typeof renderer.debug.onShaderError === 'function' ) {
 
-			} else {
+					renderer.debug.onShaderError( gl, program, glVertexShader, glFragmentShader );
 
-				// default error reporting
+				} else {
 
-				const vertexErrors = getShaderErrors( gl, glVertexShader, 'vertex' );
-				const fragmentErrors = getShaderErrors( gl, glFragmentShader, 'fragment' );
+					// default error reporting
 
-				console.error(
-					'THREE.WebGLProgram: Shader Error ' + gl.getError() + ' - ' +
-					'VALIDATE_STATUS ' + gl.getProgramParameter( program, gl.VALIDATE_STATUS ) + '\n\n' +
-					'Program Info Log: ' + programLog + '\n' +
-					vertexErrors + '\n' +
-					fragmentErrors
-				);
+					const vertexErrors = getShaderErrors( gl, glVertexShader, 'vertex' );
+					const fragmentErrors = getShaderErrors( gl, glFragmentShader, 'fragment' );
 
-			}
+					console.error(
+						'THREE.WebGLProgram: Shader Error ' + gl.getError() + ' - ' +
+						'VALIDATE_STATUS ' + gl.getProgramParameter( program, gl.VALIDATE_STATUS ) + '\n\n' +
+						'Program Info Log: ' + programLog + '\n' +
+						vertexErrors + '\n' +
+						fragmentErrors
+					);
+
+				}
 
-		} else if ( programLog !== '' ) {
+			} else if ( programLog !== '' ) {
 
-			console.warn( 'THREE.WebGLProgram: Program Info Log:', programLog );
+				console.warn( 'THREE.WebGLProgram: Program Info Log:', programLog );
 
-		} else if ( vertexLog === '' || fragmentLog === '' ) {
+			} else if ( vertexLog === '' || fragmentLog === '' ) {
 
-			haveDiagnostics = false;
+				haveDiagnostics = false;
 
-		}
+			}
 
-		if ( haveDiagnostics ) {
+			if ( haveDiagnostics ) {
 
-			this.diagnostics = {
+				self.diagnostics = {
 
-				runnable: runnable,
+					runnable: runnable,
 
-				programLog: programLog,
+					programLog: programLog,
 
-				vertexShader: {
+					vertexShader: {
 
-					log: vertexLog,
-					prefix: prefixVertex
+						log: vertexLog,
+						prefix: prefixVertex
 
-				},
+					},
 
-				fragmentShader: {
+					fragmentShader: {
 
-					log: fragmentLog,
-					prefix: prefixFragment
+						log: fragmentLog,
+						prefix: prefixFragment
 
-				}
+					}
 
-			};
+				};
+
+			}
 
 		}
 
-	}
+		// Clean up
 
-	// Clean up
+		// Crashes in iOS9 and iOS10. #18402
+		// gl.detachShader( program, glVertexShader );
+		// gl.detachShader( program, glFragmentShader );
 
-	// Crashes in iOS9 and iOS10. #18402
-	// gl.detachShader( program, glVertexShader );
-	// gl.detachShader( program, glFragmentShader );
+		gl.deleteShader( glVertexShader );
+		gl.deleteShader( glFragmentShader );
 
-	gl.deleteShader( glVertexShader );
-	gl.deleteShader( glFragmentShader );
+		cachedUniforms = new WebGLUniforms( gl, program );
+		cachedAttributes = fetchAttributeLocations( gl, program );
+
+	}
 
 	// set up caching for uniform locations
 
@@ -20097,7 +20107,8 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) {
 
 		if ( cachedUniforms === undefined ) {
 
-			cachedUniforms = new WebGLUniforms( gl, program );
+			// Populates cachedUniforms and cachedAttributes
+			onFirstUse( this );
 
 		}
 
@@ -20113,7 +20124,8 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) {
 
 		if ( cachedAttributes === undefined ) {
 
-			cachedAttributes = fetchAttributeLocations( gl, program );
+			// Populates cachedAttributes and cachedUniforms
+			onFirstUse( this );
 
 		}
 
@@ -20121,6 +20133,23 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) {
 
 	};
 
+	// indicate when the program is ready to be used. if the KHR_parallel_shader_compile extension isn't supported,
+	// flag the program as ready immediately. It may cause a stall when it's first used.
+
+	let programReady = ( parameters.rendererExtensionParallelShaderCompile === false );
+
+	this.isReady = function () {
+
+		if ( programReady === false ) {
+
+			programReady = gl.getProgramParameter( program, COMPLETION_STATUS_KHR );
+
+		}
+
+		return programReady;
+
+	};
+
 	// free resource
 
 	this.destroy = function () {
@@ -20622,6 +20651,7 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities
 			rendererExtensionFragDepth: IS_WEBGL2 || extensions.has( 'EXT_frag_depth' ),
 			rendererExtensionDrawBuffers: IS_WEBGL2 || extensions.has( 'WEBGL_draw_buffers' ),
 			rendererExtensionShaderTextureLod: IS_WEBGL2 || extensions.has( 'EXT_shader_texture_lod' ),
+			rendererExtensionParallelShaderCompile: extensions.has( 'KHR_parallel_shader_compile' ),
 
 			customProgramCacheKey: material.customProgramCacheKey()
 
@@ -29037,29 +29067,87 @@ class WebGLRenderer {
 
 		// Compile
 
+		function prepareMaterial( material, scene, object ) {
+
+			if ( material.transparent === true && material.side === DoubleSide && material.forceSinglePass === false ) {
+
+				material.side = BackSide;
+				material.needsUpdate = true;
+				getProgram( material, scene, object );
+
+				material.side = FrontSide;
+				material.needsUpdate = true;
+				getProgram( material, scene, object );
+
+				material.side = DoubleSide;
+
+			} else {
+
+				getProgram( material, scene, object );
+
+			}
+
+		}
+
 		this.compile = function ( scene, camera ) {
 
-			function prepare( material, scene, object ) {
+			currentRenderState = renderStates.get( scene );
+			currentRenderState.init();
 
-				if ( material.transparent === true && material.side === DoubleSide && material.forceSinglePass === false ) {
+			renderStateStack.push( currentRenderState );
 
-					material.side = BackSide;
-					material.needsUpdate = true;
-					getProgram( material, scene, object );
+			scene.traverseVisible( function ( object ) {
 
-					material.side = FrontSide;
-					material.needsUpdate = true;
-					getProgram( material, scene, object );
+				if ( object.isLight && object.layers.test( camera.layers ) ) {
 
-					material.side = DoubleSide;
+					currentRenderState.pushLight( object );
 
-				} else {
+					if ( object.castShadow ) {
+
+						currentRenderState.pushShadow( object );
 
-					getProgram( material, scene, object );
+					}
 
 				}
 
-			}
+			} );
+
+			currentRenderState.setupLights( _this._useLegacyLights );
+
+			scene.traverse( function ( object ) {
+
+				const material = object.material;
+
+				if ( material ) {
+
+					if ( Array.isArray( material ) ) {
+
+						for ( let i = 0; i < material.length; i ++ ) {
+
+							const material2 = material[ i ];
+
+							prepareMaterial( material2, scene, object );
+
+						}
+
+					} else {
+
+						prepareMaterial( material, scene, object );
+
+					}
+
+				}
+
+			} );
+
+			renderStateStack.pop();
+			currentRenderState = null;
+
+		};
+
+		// compileAsync
+
+		this.compileAsync = function ( scene, camera ) {
 
 			currentRenderState = renderStates.get( scene );
 			currentRenderState.init();
@@ -29084,6 +29172,8 @@ class WebGLRenderer {
 
 			currentRenderState.setupLights( _this._useLegacyLights );
 
+			const compiling = new Set();
+
 			scene.traverse( function ( object ) {
 
 				const material = object.material;
@@ -29096,13 +29186,15 @@ class WebGLRenderer {
 
 							const material2 = material[ i ];
 
-							prepare( material2, scene, object );
+							prepareMaterial( material2, scene, object );
+							compiling.add( material2 );
 
 						}
 
 					} else {
 
-						prepare( material, scene, object );
+						prepareMaterial( material, scene, object );
+						compiling.add( material );
 
 					}
 
@@ -29113,6 +29205,60 @@ class WebGLRenderer {
 			renderStateStack.pop();
 			currentRenderState = null;
 
+			// Wait for all the materials in the new object to indicate that they're
+			// ready to be used before resolving the promise.
+
+			return new Promise( ( resolve ) => {
+
+				function checkMaterialsReady() {
+
+					compiling.forEach( function ( material ) {
+
+						const materialProperties = properties.get( material );
+						const program = materialProperties.currentProgram;
+
+						if ( program.isReady() ) {
+
+							// remove any programs that report they're ready to use from the list
+							compiling.delete( material );
+
+						}
+
+					} );
+
+					// once the list of compiling materials is empty, call the callback
+
+					if ( compiling.size === 0 ) {
+
+						resolve( scene );
+						return;
+
+					}
+
+					// if some materials are still not ready, wait a bit and check again
+
+					setTimeout( checkMaterialsReady, 10 );
+
+				}
+
+				if ( extensions.get( 'KHR_parallel_shader_compile' ) !== null ) {
+
+					// If we can check the compilation status of the materials without
+					// blocking then do so right away.
+
+					checkMaterialsReady();
+
+				} else {
+
+					// Otherwise start by waiting a bit to give the materials we just
+					// initialized a chance to finish.
+
+					setTimeout( checkMaterialsReady, 10 );
+
+				}
+
+			} );
+
 		};
 
 		// Animation Loop
@@ -29716,16 +29862,26 @@ class WebGLRenderer {
 
 			}
 
-			const progUniforms = program.getUniforms();
-			const uniformsList = WebGLUniforms.seqWithValue( progUniforms.seq, uniforms );
-
 			materialProperties.currentProgram = program;
-			materialProperties.uniformsList = uniformsList;
+			materialProperties.uniformsList = null;
 
 			return program;
 
 		}
 
+		function getUniformList( materialProperties ) {
+
+			if ( materialProperties.uniformsList === null ) {
+
+				const progUniforms = materialProperties.currentProgram.getUniforms();
+				materialProperties.uniformsList = WebGLUniforms.seqWithValue( progUniforms.seq, materialProperties.uniforms );
+
+			}
+
+			return materialProperties.uniformsList;
+
+		}
+
 		function updateCommonMaterialProperties( material, parameters ) {
 
 			const materialProperties = properties.get( material );
@@ -30053,13 +30209,13 @@ class WebGLRenderer {
 
 				materials.refreshMaterialUniforms( m_uniforms, material, _pixelRatio, _height, _transmissionRenderTarget );
 
-				WebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, textures );
+				WebGLUniforms.upload( _gl, getUniformList( materialProperties ), m_uniforms, textures );
 
 			}
 
 			if ( material.isShaderMaterial && material.uniformsNeedUpdate === true ) {
 
-				WebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, textures );
+				WebGLUniforms.upload( _gl, getUniformList( materialProperties ), m_uniforms, textures );
 				material.uniformsNeedUpdate = false;
 
 			}

+ 226 - 70
build/three.js

@@ -19125,6 +19125,9 @@ console.warn( 'Scripts "build/three.js" and "build/three.min.js" are deprecated
 
 	}
 
+	// From https://www.khronos.org/registry/webgl/extensions/KHR_parallel_shader_compile/
+	const COMPLETION_STATUS_KHR = 0x91B1;
+
 	let programIdCount = 0;
 
 	function handleSource( string, errorLine ) {
@@ -20012,87 +20015,94 @@ console.warn( 'Scripts "build/three.js" and "build/three.min.js" are deprecated
 
 		gl.linkProgram( program );
 
-		// check for link errors
-		if ( renderer.debug.checkShaderErrors ) {
+		function onFirstUse( self ) {
 
-			const programLog = gl.getProgramInfoLog( program ).trim();
-			const vertexLog = gl.getShaderInfoLog( glVertexShader ).trim();
-			const fragmentLog = gl.getShaderInfoLog( glFragmentShader ).trim();
+			// check for link errors
+			if ( renderer.debug.checkShaderErrors ) {
 
-			let runnable = true;
-			let haveDiagnostics = true;
+				const programLog = gl.getProgramInfoLog( program ).trim();
+				const vertexLog = gl.getShaderInfoLog( glVertexShader ).trim();
+				const fragmentLog = gl.getShaderInfoLog( glFragmentShader ).trim();
 
-			if ( gl.getProgramParameter( program, gl.LINK_STATUS ) === false ) {
+				let runnable = true;
+				let haveDiagnostics = true;
 
-				runnable = false;
+				if ( gl.getProgramParameter( program, gl.LINK_STATUS ) === false ) {
 
-				if ( typeof renderer.debug.onShaderError === 'function' ) {
+					runnable = false;
 
-					renderer.debug.onShaderError( gl, program, glVertexShader, glFragmentShader );
+					if ( typeof renderer.debug.onShaderError === 'function' ) {
 
-				} else {
+						renderer.debug.onShaderError( gl, program, glVertexShader, glFragmentShader );
 
-					// default error reporting
+					} else {
 
-					const vertexErrors = getShaderErrors( gl, glVertexShader, 'vertex' );
-					const fragmentErrors = getShaderErrors( gl, glFragmentShader, 'fragment' );
+						// default error reporting
 
-					console.error(
-						'THREE.WebGLProgram: Shader Error ' + gl.getError() + ' - ' +
-						'VALIDATE_STATUS ' + gl.getProgramParameter( program, gl.VALIDATE_STATUS ) + '\n\n' +
-						'Program Info Log: ' + programLog + '\n' +
-						vertexErrors + '\n' +
-						fragmentErrors
-					);
+						const vertexErrors = getShaderErrors( gl, glVertexShader, 'vertex' );
+						const fragmentErrors = getShaderErrors( gl, glFragmentShader, 'fragment' );
 
-				}
+						console.error(
+							'THREE.WebGLProgram: Shader Error ' + gl.getError() + ' - ' +
+							'VALIDATE_STATUS ' + gl.getProgramParameter( program, gl.VALIDATE_STATUS ) + '\n\n' +
+							'Program Info Log: ' + programLog + '\n' +
+							vertexErrors + '\n' +
+							fragmentErrors
+						);
+
+					}
 
-			} else if ( programLog !== '' ) {
+				} else if ( programLog !== '' ) {
 
-				console.warn( 'THREE.WebGLProgram: Program Info Log:', programLog );
+					console.warn( 'THREE.WebGLProgram: Program Info Log:', programLog );
 
-			} else if ( vertexLog === '' || fragmentLog === '' ) {
+				} else if ( vertexLog === '' || fragmentLog === '' ) {
 
-				haveDiagnostics = false;
+					haveDiagnostics = false;
 
-			}
+				}
 
-			if ( haveDiagnostics ) {
+				if ( haveDiagnostics ) {
 
-				this.diagnostics = {
+					self.diagnostics = {
 
-					runnable: runnable,
+						runnable: runnable,
 
-					programLog: programLog,
+						programLog: programLog,
 
-					vertexShader: {
+						vertexShader: {
 
-						log: vertexLog,
-						prefix: prefixVertex
+							log: vertexLog,
+							prefix: prefixVertex
 
-					},
+						},
 
-					fragmentShader: {
+						fragmentShader: {
 
-						log: fragmentLog,
-						prefix: prefixFragment
+							log: fragmentLog,
+							prefix: prefixFragment
 
-					}
+						}
 
-				};
+					};
+
+				}
 
 			}
 
-		}
+			// Clean up
 
-		// Clean up
+			// Crashes in iOS9 and iOS10. #18402
+			// gl.detachShader( program, glVertexShader );
+			// gl.detachShader( program, glFragmentShader );
 
-		// Crashes in iOS9 and iOS10. #18402
-		// gl.detachShader( program, glVertexShader );
-		// gl.detachShader( program, glFragmentShader );
+			gl.deleteShader( glVertexShader );
+			gl.deleteShader( glFragmentShader );
 
-		gl.deleteShader( glVertexShader );
-		gl.deleteShader( glFragmentShader );
+			cachedUniforms = new WebGLUniforms( gl, program );
+			cachedAttributes = fetchAttributeLocations( gl, program );
+
+		}
 
 		// set up caching for uniform locations
 
@@ -20102,7 +20112,8 @@ console.warn( 'Scripts "build/three.js" and "build/three.min.js" are deprecated
 
 			if ( cachedUniforms === undefined ) {
 
-				cachedUniforms = new WebGLUniforms( gl, program );
+				// Populates cachedUniforms and cachedAttributes
+				onFirstUse( this );
 
 			}
 
@@ -20118,7 +20129,8 @@ console.warn( 'Scripts "build/three.js" and "build/three.min.js" are deprecated
 
 			if ( cachedAttributes === undefined ) {
 
-				cachedAttributes = fetchAttributeLocations( gl, program );
+				// Populates cachedAttributes and cachedUniforms
+				onFirstUse( this );
 
 			}
 
@@ -20126,6 +20138,23 @@ console.warn( 'Scripts "build/three.js" and "build/three.min.js" are deprecated
 
 		};
 
+		// indicate when the program is ready to be used. if the KHR_parallel_shader_compile extension isn't supported,
+		// flag the program as ready immediately. It may cause a stall when it's first used.
+
+		let programReady = ( parameters.rendererExtensionParallelShaderCompile === false );
+
+		this.isReady = function () {
+
+			if ( programReady === false ) {
+
+				programReady = gl.getProgramParameter( program, COMPLETION_STATUS_KHR );
+
+			}
+
+			return programReady;
+
+		};
+
 		// free resource
 
 		this.destroy = function () {
@@ -20627,6 +20656,7 @@ console.warn( 'Scripts "build/three.js" and "build/three.min.js" are deprecated
 				rendererExtensionFragDepth: IS_WEBGL2 || extensions.has( 'EXT_frag_depth' ),
 				rendererExtensionDrawBuffers: IS_WEBGL2 || extensions.has( 'WEBGL_draw_buffers' ),
 				rendererExtensionShaderTextureLod: IS_WEBGL2 || extensions.has( 'EXT_shader_texture_lod' ),
+				rendererExtensionParallelShaderCompile: extensions.has( 'KHR_parallel_shader_compile' ),
 
 				customProgramCacheKey: material.customProgramCacheKey()
 
@@ -29042,29 +29072,87 @@ console.warn( 'Scripts "build/three.js" and "build/three.min.js" are deprecated
 
 			// Compile
 
+			function prepareMaterial( material, scene, object ) {
+
+				if ( material.transparent === true && material.side === DoubleSide && material.forceSinglePass === false ) {
+
+					material.side = BackSide;
+					material.needsUpdate = true;
+					getProgram( material, scene, object );
+
+					material.side = FrontSide;
+					material.needsUpdate = true;
+					getProgram( material, scene, object );
+
+					material.side = DoubleSide;
+
+				} else {
+
+					getProgram( material, scene, object );
+
+				}
+
+			}
+
 			this.compile = function ( scene, camera ) {
 
-				function prepare( material, scene, object ) {
+				currentRenderState = renderStates.get( scene );
+				currentRenderState.init();
 
-					if ( material.transparent === true && material.side === DoubleSide && material.forceSinglePass === false ) {
+				renderStateStack.push( currentRenderState );
 
-						material.side = BackSide;
-						material.needsUpdate = true;
-						getProgram( material, scene, object );
+				scene.traverseVisible( function ( object ) {
 
-						material.side = FrontSide;
-						material.needsUpdate = true;
-						getProgram( material, scene, object );
+					if ( object.isLight && object.layers.test( camera.layers ) ) {
 
-						material.side = DoubleSide;
+						currentRenderState.pushLight( object );
 
-					} else {
+						if ( object.castShadow ) {
+
+							currentRenderState.pushShadow( object );
 
-						getProgram( material, scene, object );
+						}
 
 					}
 
-				}
+				} );
+
+				currentRenderState.setupLights( _this._useLegacyLights );
+
+				scene.traverse( function ( object ) {
+
+					const material = object.material;
+
+					if ( material ) {
+
+						if ( Array.isArray( material ) ) {
+
+							for ( let i = 0; i < material.length; i ++ ) {
+
+								const material2 = material[ i ];
+
+								prepareMaterial( material2, scene, object );
+
+							}
+
+						} else {
+
+							prepareMaterial( material, scene, object );
+
+						}
+
+					}
+
+				} );
+
+				renderStateStack.pop();
+				currentRenderState = null;
+
+			};
+
+			// compileAsync
+
+			this.compileAsync = function ( scene, camera ) {
 
 				currentRenderState = renderStates.get( scene );
 				currentRenderState.init();
@@ -29089,6 +29177,8 @@ console.warn( 'Scripts "build/three.js" and "build/three.min.js" are deprecated
 
 				currentRenderState.setupLights( _this._useLegacyLights );
 
+				const compiling = new Set();
+
 				scene.traverse( function ( object ) {
 
 					const material = object.material;
@@ -29101,13 +29191,15 @@ console.warn( 'Scripts "build/three.js" and "build/three.min.js" are deprecated
 
 								const material2 = material[ i ];
 
-								prepare( material2, scene, object );
+								prepareMaterial( material2, scene, object );
+								compiling.add( material2 );
 
 							}
 
 						} else {
 
-							prepare( material, scene, object );
+							prepareMaterial( material, scene, object );
+							compiling.add( material );
 
 						}
 
@@ -29118,6 +29210,60 @@ console.warn( 'Scripts "build/three.js" and "build/three.min.js" are deprecated
 				renderStateStack.pop();
 				currentRenderState = null;
 
+				// Wait for all the materials in the new object to indicate that they're
+				// ready to be used before resolving the promise.
+
+				return new Promise( ( resolve ) => {
+
+					function checkMaterialsReady() {
+
+						compiling.forEach( function ( material ) {
+
+							const materialProperties = properties.get( material );
+							const program = materialProperties.currentProgram;
+
+							if ( program.isReady() ) {
+
+								// remove any programs that report they're ready to use from the list
+								compiling.delete( material );
+
+							}
+
+						} );
+
+						// once the list of compiling materials is empty, call the callback
+
+						if ( compiling.size === 0 ) {
+
+							resolve( scene );
+							return;
+
+						}
+
+						// if some materials are still not ready, wait a bit and check again
+
+						setTimeout( checkMaterialsReady, 10 );
+
+					}
+
+					if ( extensions.get( 'KHR_parallel_shader_compile' ) !== null ) {
+
+						// If we can check the compilation status of the materials without
+						// blocking then do so right away.
+
+						checkMaterialsReady();
+
+					} else {
+
+						// Otherwise start by waiting a bit to give the materials we just
+						// initialized a chance to finish.
+
+						setTimeout( checkMaterialsReady, 10 );
+
+					}
+
+				} );
+
 			};
 
 			// Animation Loop
@@ -29721,16 +29867,26 @@ console.warn( 'Scripts "build/three.js" and "build/three.min.js" are deprecated
 
 				}
 
-				const progUniforms = program.getUniforms();
-				const uniformsList = WebGLUniforms.seqWithValue( progUniforms.seq, uniforms );
-
 				materialProperties.currentProgram = program;
-				materialProperties.uniformsList = uniformsList;
+				materialProperties.uniformsList = null;
 
 				return program;
 
 			}
 
+			function getUniformList( materialProperties ) {
+
+				if ( materialProperties.uniformsList === null ) {
+
+					const progUniforms = materialProperties.currentProgram.getUniforms();
+					materialProperties.uniformsList = WebGLUniforms.seqWithValue( progUniforms.seq, materialProperties.uniforms );
+
+				}
+
+				return materialProperties.uniformsList;
+
+			}
+
 			function updateCommonMaterialProperties( material, parameters ) {
 
 				const materialProperties = properties.get( material );
@@ -30058,13 +30214,13 @@ console.warn( 'Scripts "build/three.js" and "build/three.min.js" are deprecated
 
 					materials.refreshMaterialUniforms( m_uniforms, material, _pixelRatio, _height, _transmissionRenderTarget );
 
-					WebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, textures );
+					WebGLUniforms.upload( _gl, getUniformList( materialProperties ), m_uniforms, textures );
 
 				}
 
 				if ( material.isShaderMaterial && material.uniformsNeedUpdate === true ) {
 
-					WebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, textures );
+					WebGLUniforms.upload( _gl, getUniformList( materialProperties ), m_uniforms, textures );
 					material.uniformsNeedUpdate = false;
 
 				}

File diff suppressed because it is too large
+ 0 - 0
build/three.min.js


+ 226 - 70
build/three.module.js

@@ -19118,6 +19118,9 @@ function WebGLShader( gl, type, string ) {
 
 }
 
+// From https://www.khronos.org/registry/webgl/extensions/KHR_parallel_shader_compile/
+const COMPLETION_STATUS_KHR = 0x91B1;
+
 let programIdCount = 0;
 
 function handleSource( string, errorLine ) {
@@ -20005,87 +20008,94 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) {
 
 	gl.linkProgram( program );
 
-	// check for link errors
-	if ( renderer.debug.checkShaderErrors ) {
+	function onFirstUse( self ) {
 
-		const programLog = gl.getProgramInfoLog( program ).trim();
-		const vertexLog = gl.getShaderInfoLog( glVertexShader ).trim();
-		const fragmentLog = gl.getShaderInfoLog( glFragmentShader ).trim();
+		// check for link errors
+		if ( renderer.debug.checkShaderErrors ) {
 
-		let runnable = true;
-		let haveDiagnostics = true;
+			const programLog = gl.getProgramInfoLog( program ).trim();
+			const vertexLog = gl.getShaderInfoLog( glVertexShader ).trim();
+			const fragmentLog = gl.getShaderInfoLog( glFragmentShader ).trim();
 
-		if ( gl.getProgramParameter( program, gl.LINK_STATUS ) === false ) {
+			let runnable = true;
+			let haveDiagnostics = true;
 
-			runnable = false;
+			if ( gl.getProgramParameter( program, gl.LINK_STATUS ) === false ) {
 
-			if ( typeof renderer.debug.onShaderError === 'function' ) {
+				runnable = false;
 
-				renderer.debug.onShaderError( gl, program, glVertexShader, glFragmentShader );
+				if ( typeof renderer.debug.onShaderError === 'function' ) {
 
-			} else {
+					renderer.debug.onShaderError( gl, program, glVertexShader, glFragmentShader );
 
-				// default error reporting
+				} else {
 
-				const vertexErrors = getShaderErrors( gl, glVertexShader, 'vertex' );
-				const fragmentErrors = getShaderErrors( gl, glFragmentShader, 'fragment' );
+					// default error reporting
 
-				console.error(
-					'THREE.WebGLProgram: Shader Error ' + gl.getError() + ' - ' +
-					'VALIDATE_STATUS ' + gl.getProgramParameter( program, gl.VALIDATE_STATUS ) + '\n\n' +
-					'Program Info Log: ' + programLog + '\n' +
-					vertexErrors + '\n' +
-					fragmentErrors
-				);
+					const vertexErrors = getShaderErrors( gl, glVertexShader, 'vertex' );
+					const fragmentErrors = getShaderErrors( gl, glFragmentShader, 'fragment' );
 
-			}
+					console.error(
+						'THREE.WebGLProgram: Shader Error ' + gl.getError() + ' - ' +
+						'VALIDATE_STATUS ' + gl.getProgramParameter( program, gl.VALIDATE_STATUS ) + '\n\n' +
+						'Program Info Log: ' + programLog + '\n' +
+						vertexErrors + '\n' +
+						fragmentErrors
+					);
+
+				}
 
-		} else if ( programLog !== '' ) {
+			} else if ( programLog !== '' ) {
 
-			console.warn( 'THREE.WebGLProgram: Program Info Log:', programLog );
+				console.warn( 'THREE.WebGLProgram: Program Info Log:', programLog );
 
-		} else if ( vertexLog === '' || fragmentLog === '' ) {
+			} else if ( vertexLog === '' || fragmentLog === '' ) {
 
-			haveDiagnostics = false;
+				haveDiagnostics = false;
 
-		}
+			}
 
-		if ( haveDiagnostics ) {
+			if ( haveDiagnostics ) {
 
-			this.diagnostics = {
+				self.diagnostics = {
 
-				runnable: runnable,
+					runnable: runnable,
 
-				programLog: programLog,
+					programLog: programLog,
 
-				vertexShader: {
+					vertexShader: {
 
-					log: vertexLog,
-					prefix: prefixVertex
+						log: vertexLog,
+						prefix: prefixVertex
 
-				},
+					},
 
-				fragmentShader: {
+					fragmentShader: {
 
-					log: fragmentLog,
-					prefix: prefixFragment
+						log: fragmentLog,
+						prefix: prefixFragment
 
-				}
+					}
 
-			};
+				};
+
+			}
 
 		}
 
-	}
+		// Clean up
 
-	// Clean up
+		// Crashes in iOS9 and iOS10. #18402
+		// gl.detachShader( program, glVertexShader );
+		// gl.detachShader( program, glFragmentShader );
 
-	// Crashes in iOS9 and iOS10. #18402
-	// gl.detachShader( program, glVertexShader );
-	// gl.detachShader( program, glFragmentShader );
+		gl.deleteShader( glVertexShader );
+		gl.deleteShader( glFragmentShader );
 
-	gl.deleteShader( glVertexShader );
-	gl.deleteShader( glFragmentShader );
+		cachedUniforms = new WebGLUniforms( gl, program );
+		cachedAttributes = fetchAttributeLocations( gl, program );
+
+	}
 
 	// set up caching for uniform locations
 
@@ -20095,7 +20105,8 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) {
 
 		if ( cachedUniforms === undefined ) {
 
-			cachedUniforms = new WebGLUniforms( gl, program );
+			// Populates cachedUniforms and cachedAttributes
+			onFirstUse( this );
 
 		}
 
@@ -20111,7 +20122,8 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) {
 
 		if ( cachedAttributes === undefined ) {
 
-			cachedAttributes = fetchAttributeLocations( gl, program );
+			// Populates cachedAttributes and cachedUniforms
+			onFirstUse( this );
 
 		}
 
@@ -20119,6 +20131,23 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) {
 
 	};
 
+	// indicate when the program is ready to be used. if the KHR_parallel_shader_compile extension isn't supported,
+	// flag the program as ready immediately. It may cause a stall when it's first used.
+
+	let programReady = ( parameters.rendererExtensionParallelShaderCompile === false );
+
+	this.isReady = function () {
+
+		if ( programReady === false ) {
+
+			programReady = gl.getProgramParameter( program, COMPLETION_STATUS_KHR );
+
+		}
+
+		return programReady;
+
+	};
+
 	// free resource
 
 	this.destroy = function () {
@@ -20620,6 +20649,7 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities
 			rendererExtensionFragDepth: IS_WEBGL2 || extensions.has( 'EXT_frag_depth' ),
 			rendererExtensionDrawBuffers: IS_WEBGL2 || extensions.has( 'WEBGL_draw_buffers' ),
 			rendererExtensionShaderTextureLod: IS_WEBGL2 || extensions.has( 'EXT_shader_texture_lod' ),
+			rendererExtensionParallelShaderCompile: extensions.has( 'KHR_parallel_shader_compile' ),
 
 			customProgramCacheKey: material.customProgramCacheKey()
 
@@ -29035,29 +29065,87 @@ class WebGLRenderer {
 
 		// Compile
 
+		function prepareMaterial( material, scene, object ) {
+
+			if ( material.transparent === true && material.side === DoubleSide && material.forceSinglePass === false ) {
+
+				material.side = BackSide;
+				material.needsUpdate = true;
+				getProgram( material, scene, object );
+
+				material.side = FrontSide;
+				material.needsUpdate = true;
+				getProgram( material, scene, object );
+
+				material.side = DoubleSide;
+
+			} else {
+
+				getProgram( material, scene, object );
+
+			}
+
+		}
+
 		this.compile = function ( scene, camera ) {
 
-			function prepare( material, scene, object ) {
+			currentRenderState = renderStates.get( scene );
+			currentRenderState.init();
 
-				if ( material.transparent === true && material.side === DoubleSide && material.forceSinglePass === false ) {
+			renderStateStack.push( currentRenderState );
 
-					material.side = BackSide;
-					material.needsUpdate = true;
-					getProgram( material, scene, object );
+			scene.traverseVisible( function ( object ) {
 
-					material.side = FrontSide;
-					material.needsUpdate = true;
-					getProgram( material, scene, object );
+				if ( object.isLight && object.layers.test( camera.layers ) ) {
 
-					material.side = DoubleSide;
+					currentRenderState.pushLight( object );
 
-				} else {
+					if ( object.castShadow ) {
+
+						currentRenderState.pushShadow( object );
 
-					getProgram( material, scene, object );
+					}
 
 				}
 
-			}
+			} );
+
+			currentRenderState.setupLights( _this._useLegacyLights );
+
+			scene.traverse( function ( object ) {
+
+				const material = object.material;
+
+				if ( material ) {
+
+					if ( Array.isArray( material ) ) {
+
+						for ( let i = 0; i < material.length; i ++ ) {
+
+							const material2 = material[ i ];
+
+							prepareMaterial( material2, scene, object );
+
+						}
+
+					} else {
+
+						prepareMaterial( material, scene, object );
+
+					}
+
+				}
+
+			} );
+
+			renderStateStack.pop();
+			currentRenderState = null;
+
+		};
+
+		// compileAsync
+
+		this.compileAsync = function ( scene, camera ) {
 
 			currentRenderState = renderStates.get( scene );
 			currentRenderState.init();
@@ -29082,6 +29170,8 @@ class WebGLRenderer {
 
 			currentRenderState.setupLights( _this._useLegacyLights );
 
+			const compiling = new Set();
+
 			scene.traverse( function ( object ) {
 
 				const material = object.material;
@@ -29094,13 +29184,15 @@ class WebGLRenderer {
 
 							const material2 = material[ i ];
 
-							prepare( material2, scene, object );
+							prepareMaterial( material2, scene, object );
+							compiling.add( material2 );
 
 						}
 
 					} else {
 
-						prepare( material, scene, object );
+						prepareMaterial( material, scene, object );
+						compiling.add( material );
 
 					}
 
@@ -29111,6 +29203,60 @@ class WebGLRenderer {
 			renderStateStack.pop();
 			currentRenderState = null;
 
+			// Wait for all the materials in the new object to indicate that they're
+			// ready to be used before resolving the promise.
+
+			return new Promise( ( resolve ) => {
+
+				function checkMaterialsReady() {
+
+					compiling.forEach( function ( material ) {
+
+						const materialProperties = properties.get( material );
+						const program = materialProperties.currentProgram;
+
+						if ( program.isReady() ) {
+
+							// remove any programs that report they're ready to use from the list
+							compiling.delete( material );
+
+						}
+
+					} );
+
+					// once the list of compiling materials is empty, call the callback
+
+					if ( compiling.size === 0 ) {
+
+						resolve( scene );
+						return;
+
+					}
+
+					// if some materials are still not ready, wait a bit and check again
+
+					setTimeout( checkMaterialsReady, 10 );
+
+				}
+
+				if ( extensions.get( 'KHR_parallel_shader_compile' ) !== null ) {
+
+					// If we can check the compilation status of the materials without
+					// blocking then do so right away.
+
+					checkMaterialsReady();
+
+				} else {
+
+					// Otherwise start by waiting a bit to give the materials we just
+					// initialized a chance to finish.
+
+					setTimeout( checkMaterialsReady, 10 );
+
+				}
+
+			} );
+
 		};
 
 		// Animation Loop
@@ -29714,16 +29860,26 @@ class WebGLRenderer {
 
 			}
 
-			const progUniforms = program.getUniforms();
-			const uniformsList = WebGLUniforms.seqWithValue( progUniforms.seq, uniforms );
-
 			materialProperties.currentProgram = program;
-			materialProperties.uniformsList = uniformsList;
+			materialProperties.uniformsList = null;
 
 			return program;
 
 		}
 
+		function getUniformList( materialProperties ) {
+
+			if ( materialProperties.uniformsList === null ) {
+
+				const progUniforms = materialProperties.currentProgram.getUniforms();
+				materialProperties.uniformsList = WebGLUniforms.seqWithValue( progUniforms.seq, materialProperties.uniforms );
+
+			}
+
+			return materialProperties.uniformsList;
+
+		}
+
 		function updateCommonMaterialProperties( material, parameters ) {
 
 			const materialProperties = properties.get( material );
@@ -30051,13 +30207,13 @@ class WebGLRenderer {
 
 				materials.refreshMaterialUniforms( m_uniforms, material, _pixelRatio, _height, _transmissionRenderTarget );
 
-				WebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, textures );
+				WebGLUniforms.upload( _gl, getUniformList( materialProperties ), m_uniforms, textures );
 
 			}
 
 			if ( material.isShaderMaterial && material.uniformsNeedUpdate === true ) {
 
-				WebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, textures );
+				WebGLUniforms.upload( _gl, getUniformList( materialProperties ), m_uniforms, textures );
 				material.uniformsNeedUpdate = false;
 
 			}

File diff suppressed because it is too large
+ 0 - 0
build/three.module.min.js


Some files were not shown because too many files changed in this diff