From 573eee7ee2ce02b2a3fc58303385c2dd10f87461 Mon Sep 17 00:00:00 2001 From: aardgoose Date: Fri, 24 May 2019 21:35:05 +0100 Subject: [PATCH 01/18] WIP demo parallel compile --- src/renderers/WebGLRenderer.js | 25 ++++- src/renderers/webgl/WebGLProgram.js | 166 ++++++++++++++++++---------- 2 files changed, 129 insertions(+), 62 deletions(-) diff --git a/src/renderers/WebGLRenderer.js b/src/renderers/WebGLRenderer.js index 2bc6744bf912f..bb910a607233d 100644 --- a/src/renderers/WebGLRenderer.js +++ b/src/renderers/WebGLRenderer.js @@ -714,6 +714,8 @@ function WebGLRenderer( parameters ) { var program = setProgram( camera, fog, material, object ); + if ( ! program.ready ) return; + var updateBuffers = false; if ( _currentGeometryProgram.geometry !== geometry.id || @@ -1417,6 +1419,8 @@ function WebGLRenderer( parameters ) { var program = setProgram( camera, scene.fog, material, object ); + if ( ! program.ready ) return; + _currentGeometryProgram.geometry = null; _currentGeometryProgram.program = null; _currentGeometryProgram.wireframe = false; @@ -1462,13 +1466,14 @@ function WebGLRenderer( parameters ) { // changed glsl or parameters releaseMaterialProgramReference( material ); - } else if ( lightsHash.stateID !== lightsStateHash.stateID || + } else if ( program.ready && ( + lightsHash.stateID !== lightsStateHash.stateID || lightsHash.directionalLength !== lightsStateHash.directionalLength || lightsHash.pointLength !== lightsStateHash.pointLength || lightsHash.spotLength !== lightsStateHash.spotLength || lightsHash.rectAreaLength !== lightsStateHash.rectAreaLength || lightsHash.hemiLength !== lightsStateHash.hemiLength || - lightsHash.shadowsLength !== lightsStateHash.shadowsLength ) { + lightsHash.shadowsLength !== lightsStateHash.shadowsLength ) ) { lightsHash.stateID = lightsStateHash.stateID; lightsHash.directionalLength = lightsStateHash.directionalLength; @@ -1480,7 +1485,7 @@ function WebGLRenderer( parameters ) { programChange = false; - } else if ( parameters.shaderID !== undefined ) { + } else if ( program.ready && parameters.shaderID !== undefined ) { // same glsl and uniform list return; @@ -1528,6 +1533,13 @@ function WebGLRenderer( parameters ) { } + if (! program.ready && ! program.isLinked( _this, material ) ) { + + materialProperties.lightsHash = {}; + return; + + } + var programAttributes = program.getAttributes(); if ( material.morphTargets ) { @@ -1691,8 +1703,11 @@ function WebGLRenderer( parameters ) { var refreshMaterial = false; var refreshLights = false; - var program = materialProperties.program, - p_uniforms = program.getUniforms(), + var program = materialProperties.program; + + if ( ! program.ready ) return false; + + var p_uniforms = program.getUniforms(), m_uniforms = materialProperties.shader.uniforms; if ( state.useProgram( program.program ) ) { diff --git a/src/renderers/webgl/WebGLProgram.js b/src/renderers/webgl/WebGLProgram.js index 177fc82f07f68..d05e9722e834e 100644 --- a/src/renderers/webgl/WebGLProgram.js +++ b/src/renderers/webgl/WebGLProgram.js @@ -607,6 +607,8 @@ function WebGLProgram( renderer, extensions, code, material, shader, parameters, } + var parallelShaderExt = extensions.get( 'KHR_parallel_shader_compile' ); + var vertexGlsl = prefixVertex + vertexShader; var fragmentGlsl = prefixFragment + fragmentShader; @@ -632,70 +634,30 @@ function WebGLProgram( renderer, extensions, code, material, shader, parameters, } - gl.linkProgram( program ); - - // check for link errors - if ( renderer.debug.checkShaderErrors ) { - - var programLog = gl.getProgramInfoLog( program ).trim(); - var vertexLog = gl.getShaderInfoLog( glVertexShader ).trim(); - var fragmentLog = gl.getShaderInfoLog( glFragmentShader ).trim(); - var vertexErrors = getShaderErrors( gl, glVertexShader ); - var fragmentErrors = getShaderErrors( gl, glFragmentShader ); - - var runnable = true; - var haveDiagnostics = true; - - if ( gl.getProgramParameter( program, gl.LINK_STATUS ) === false ) { - - runnable = false; - - console.error( 'THREE.WebGLProgram: shader error: ', gl.getError(), 'gl.VALIDATE_STATUS', gl.getProgramParameter( program, gl.VALIDATE_STATUS ), 'gl.getProgramInfoLog', programLog, vertexErrors, fragmentErrors ); - - } else if ( programLog !== '' ) { - - console.warn( 'THREE.WebGLProgram: gl.getProgramInfoLog()', programLog ); - - } else if ( vertexLog === '' || fragmentLog === '' ) { - - haveDiagnostics = false; - - } - - if ( haveDiagnostics ) { - - this.diagnostics = { - - runnable: runnable, - material: material, - - programLog: programLog, - - vertexShader: { + this.program = program; + this.vertexShader = glVertexShader; + this.fragmentShader = glFragmentShader; + this.parallelShaderExt = parallelShaderExt; + this.prefixVertex = prefixVertex; + this.prefixFragment = prefixFragment; - log: vertexLog, - prefix: prefixVertex + gl.linkProgram( program ); - }, + this.ready = true; - fragmentShader: { +// var status = gl.getProgramParameter( program, parallelShaderExt.COMPLETION_STATUS_KHR ); - log: fragmentLog, - prefix: prefixFragment + if ( parallelShaderExt === null ) { - } + // check for link errors + this.checkLink( renderer, material ); - }; + } else { - } + this.ready = false; } - // clean up - - gl.deleteShader( glVertexShader ); - gl.deleteShader( glFragmentShader ); - // set up caching for uniform locations var cachedUniforms; @@ -768,12 +730,102 @@ function WebGLProgram( renderer, extensions, code, material, shader, parameters, this.id = programIdCount ++; this.code = code; this.usedTimes = 1; - this.program = program; - this.vertexShader = glVertexShader; - this.fragmentShader = glFragmentShader; return this; } +Object.assign( WebGLProgram.prototype, { + + isLinked: function ( renderer, material ) { + + var gl = renderer.context; + + if ( gl.getProgramParameter( this.program, this.parallelShaderExt.COMPLETION_STATUS_KHR ) == true ) { + + this.checkLink( renderer, material ); + this.ready = true; + + } else { + + console.log( 'not ready' ); + + } + + return this.ready; + + }, + + checkLink: function ( renderer, material ) { + + // check for link errors + + var gl = renderer.context; + var program = this.program; + var glVertexShader = this.vertexShader; + var glFragmentShader = this.fragmentShader; + + if ( renderer.debug.checkShaderErrors ) { + + var programLog = gl.getProgramInfoLog( program ).trim(); + var vertexLog = gl.getShaderInfoLog( glVertexShader ).trim(); + var fragmentLog = gl.getShaderInfoLog( glFragmentShader ).trim(); + var vertexErrors = getShaderErrors( gl, glVertexShader ); + var fragmentErrors = getShaderErrors( gl, glFragmentShader ); + + var runnable = true; + var haveDiagnostics = true; + + if ( gl.getProgramParameter( program, gl.LINK_STATUS ) === false ) { + + runnable = false; + + console.error( 'THREE.WebGLProgram: shader error: ', gl.getError(), 'gl.VALIDATE_STATUS', gl.getProgramParameter( program, gl.VALIDATE_STATUS ), 'gl.getProgramInfoLog', programLog, vertexErrors, fragmentErrors ); + + } else if ( programLog !== '' ) { + + console.warn( 'THREE.WebGLProgram: gl.getProgramInfoLog()', programLog ); + + } else if ( vertexLog === '' || fragmentLog === '' ) { + + haveDiagnostics = false; + + } + + if ( haveDiagnostics ) { + + this.diagnostics = { + + runnable: runnable, + material: material, + + programLog: programLog, + + vertexShader: { + + log: vertexLog, + prefix: this.prefixVertex + + }, + + fragmentShader: { + + log: fragmentLog, + prefix: this.prefixFragment + + } + + }; + + } + + } + + gl.deleteShader( glVertexShader ); + gl.deleteShader( glFragmentShader ); + + } + +} ); + export { WebGLProgram }; From 2d30ed58772302420cd9a8bcb8cb3e16706168f4 Mon Sep 17 00:00:00 2001 From: aardgoose Date: Sat, 25 May 2019 16:09:02 +0100 Subject: [PATCH 02/18] WIP --- src/renderers/WebGLRenderer.js | 2 +- src/renderers/webgl/WebGLCapabilities.js | 5 ++++- src/renderers/webgl/WebGLProgram.js | 11 ++++------- src/renderers/webgl/WebGLShader.d.ts | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/renderers/WebGLRenderer.js b/src/renderers/WebGLRenderer.js index bb910a607233d..3e7c84d711a2e 100644 --- a/src/renderers/WebGLRenderer.js +++ b/src/renderers/WebGLRenderer.js @@ -1533,7 +1533,7 @@ function WebGLRenderer( parameters ) { } - if (! program.ready && ! program.isLinked( _this, material ) ) { + if ( ! program.ready && ! program.isLinked( _this, material ) ) { materialProperties.lightsHash = {}; return; diff --git a/src/renderers/webgl/WebGLCapabilities.js b/src/renderers/webgl/WebGLCapabilities.js index 4eafd2132f9ce..7d1a0e9c93282 100644 --- a/src/renderers/webgl/WebGLCapabilities.js +++ b/src/renderers/webgl/WebGLCapabilities.js @@ -85,6 +85,7 @@ function WebGLCapabilities( gl, extensions, parameters ) { var floatVertexTextures = vertexTextures && floatFragmentTextures; var maxSamples = isWebGL2 ? gl.getParameter( gl.MAX_SAMPLES ) : 0; + var parallelShaderCompile = extensions.get( 'KHR_parallel_shader_compile' ); return { @@ -110,7 +111,9 @@ function WebGLCapabilities( gl, extensions, parameters ) { floatFragmentTextures: floatFragmentTextures, floatVertexTextures: floatVertexTextures, - maxSamples: maxSamples + maxSamples: maxSamples, + + parallelShaderCompile: parallelShaderCompile }; diff --git a/src/renderers/webgl/WebGLProgram.js b/src/renderers/webgl/WebGLProgram.js index d05e9722e834e..43e138119dfd6 100644 --- a/src/renderers/webgl/WebGLProgram.js +++ b/src/renderers/webgl/WebGLProgram.js @@ -607,7 +607,7 @@ function WebGLProgram( renderer, extensions, code, material, shader, parameters, } - var parallelShaderExt = extensions.get( 'KHR_parallel_shader_compile' ); + var parallelShaderExt = capabilities.parallelShaderCompile; var vertexGlsl = prefixVertex + vertexShader; var fragmentGlsl = prefixFragment + fragmentShader; @@ -615,8 +615,8 @@ function WebGLProgram( renderer, extensions, code, material, shader, parameters, // console.log( '*VERTEX*', vertexGlsl ); // console.log( '*FRAGMENT*', fragmentGlsl ); - var glVertexShader = WebGLShader( gl, gl.VERTEX_SHADER, vertexGlsl, renderer.debug.checkShaderErrors ); - var glFragmentShader = WebGLShader( gl, gl.FRAGMENT_SHADER, fragmentGlsl, renderer.debug.checkShaderErrors ); + var glVertexShader = WebGLShader( gl, gl.VERTEX_SHADER, vertexGlsl ); + var glFragmentShader = WebGLShader( gl, gl.FRAGMENT_SHADER, fragmentGlsl ); gl.attachShader( program, glVertexShader ); gl.attachShader( program, glFragmentShader ); @@ -643,14 +643,11 @@ function WebGLProgram( renderer, extensions, code, material, shader, parameters, gl.linkProgram( program ); - this.ready = true; - -// var status = gl.getProgramParameter( program, parallelShaderExt.COMPLETION_STATUS_KHR ); - if ( parallelShaderExt === null ) { // check for link errors this.checkLink( renderer, material ); + this.ready = true; } else { diff --git a/src/renderers/webgl/WebGLShader.d.ts b/src/renderers/webgl/WebGLShader.d.ts index 8ff468bfe72a2..f02159dc86a7e 100644 --- a/src/renderers/webgl/WebGLShader.d.ts +++ b/src/renderers/webgl/WebGLShader.d.ts @@ -1,3 +1,3 @@ export class WebGLShader { - constructor(gl: any, type: string, string: string, debug: boolean); + constructor(gl: any, type: string, string: string); } From bc791346426cbcb3ec803c73c29ec8ea79c86293 Mon Sep 17 00:00:00 2001 From: aardgoose Date: Thu, 30 May 2019 17:05:49 +0100 Subject: [PATCH 03/18] adjust to lhash --- src/renderers/WebGLRenderer.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/renderers/WebGLRenderer.js b/src/renderers/WebGLRenderer.js index 05e7e2512e6b6..d271333f58c24 100644 --- a/src/renderers/WebGLRenderer.js +++ b/src/renderers/WebGLRenderer.js @@ -1524,7 +1524,6 @@ function WebGLRenderer( parameters ) { if ( ! program.ready && ! program.isLinked( _this, material ) ) { - materialProperties.lightsHash = {}; return; } From 756ab0274a131e6ab7b424da2d4be8e8517c8d68 Mon Sep 17 00:00:00 2001 From: aardgoose Date: Thu, 30 May 2019 22:55:51 +0100 Subject: [PATCH 04/18] make material specific --- src/renderers/webgl/WebGLProgram.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/renderers/webgl/WebGLProgram.js b/src/renderers/webgl/WebGLProgram.js index e12afa99b9b1e..06ceea7a86ebb 100644 --- a/src/renderers/webgl/WebGLProgram.js +++ b/src/renderers/webgl/WebGLProgram.js @@ -643,15 +643,15 @@ function WebGLProgram( renderer, extensions, code, material, shader, parameters, gl.linkProgram( program ); - if ( parallelShaderExt === null ) { + if ( parallelShaderExt !== null && material.parallelCompile ) { - // check for link errors - this.checkLink( renderer, material ); - this.ready = true; + this.ready = false; } else { - this.ready = false; + // check for link errors + this.checkLink( renderer, material ); + this.ready = true; } From 4359c68e13bf647e53c3570a35a4b48711a5f887 Mon Sep 17 00:00:00 2001 From: aardgoose Date: Thu, 30 May 2019 22:56:46 +0100 Subject: [PATCH 05/18] WIP shared programs etc --- src/renderers/WebGLRenderer.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/renderers/WebGLRenderer.js b/src/renderers/WebGLRenderer.js index d271333f58c24..f50958b7a696a 100644 --- a/src/renderers/WebGLRenderer.js +++ b/src/renderers/WebGLRenderer.js @@ -1468,7 +1468,7 @@ function WebGLRenderer( parameters ) { // changed glsl or parameters releaseMaterialProgramReference( material ); - } else if ( materialProperties.lightsStateVersion !== lightsStateVersion ) { + } else if ( program.ready && materialProperties.lightsStateVersion !== lightsStateVersion ) { materialProperties.lightsStateVersion = lightsStateVersion; @@ -1524,10 +1524,13 @@ function WebGLRenderer( parameters ) { if ( ! program.ready && ! program.isLinked( _this, material ) ) { + materialProperties.retry = true; return; } + materialProperties.retry = false; + var programAttributes = program.getAttributes(); if ( material.morphTargets ) { @@ -1660,7 +1663,7 @@ function WebGLRenderer( parameters ) { } - if ( material.needsUpdate ) { + if ( material.needsUpdate || materialProperties.retry ) { initMaterial( material, fog, object ); material.needsUpdate = false; From 60bce20e884512d0b9ec0f63b684495e360a3da9 Mon Sep 17 00:00:00 2001 From: aardgoose Date: Thu, 30 May 2019 22:57:04 +0100 Subject: [PATCH 06/18] default to no parallel compile --- src/materials/Material.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/materials/Material.js b/src/materials/Material.js index 53686cecd415f..326a015696777 100644 --- a/src/materials/Material.js +++ b/src/materials/Material.js @@ -61,6 +61,7 @@ function Material() { this.premultipliedAlpha = false; this.visible = true; + this.parallelCompile = false; this.userData = {}; From adff02299fe7ca0f543d402288776f4c1166c891 Mon Sep 17 00:00:00 2001 From: aardgoose Date: Fri, 31 May 2019 14:32:58 +0100 Subject: [PATCH 07/18] testing --- src/materials/MeshStandardMaterial.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/materials/MeshStandardMaterial.js b/src/materials/MeshStandardMaterial.js index cbbe32dc34d1c..57bde8635dcf7 100644 --- a/src/materials/MeshStandardMaterial.js +++ b/src/materials/MeshStandardMaterial.js @@ -109,6 +109,7 @@ function MeshStandardMaterial( parameters ) { this.skinning = false; this.morphTargets = false; this.morphNormals = false; + this.parallelCompile = true; this.setValues( parameters ); From eb44c9ad29c0180cb8a68e82cf804ea676d8b897 Mon Sep 17 00:00:00 2001 From: aardgoose Date: Mon, 3 Jun 2019 10:48:05 +0100 Subject: [PATCH 08/18] remove testing parts --- src/materials/MeshStandardMaterial.js | 1 - src/renderers/webgl/WebGLProgram.js | 4 ---- 2 files changed, 5 deletions(-) diff --git a/src/materials/MeshStandardMaterial.js b/src/materials/MeshStandardMaterial.js index 57bde8635dcf7..cbbe32dc34d1c 100644 --- a/src/materials/MeshStandardMaterial.js +++ b/src/materials/MeshStandardMaterial.js @@ -109,7 +109,6 @@ function MeshStandardMaterial( parameters ) { this.skinning = false; this.morphTargets = false; this.morphNormals = false; - this.parallelCompile = true; this.setValues( parameters ); diff --git a/src/renderers/webgl/WebGLProgram.js b/src/renderers/webgl/WebGLProgram.js index 06ceea7a86ebb..e22435ec13128 100644 --- a/src/renderers/webgl/WebGLProgram.js +++ b/src/renderers/webgl/WebGLProgram.js @@ -743,10 +743,6 @@ Object.assign( WebGLProgram.prototype, { this.checkLink( renderer, material ); this.ready = true; - } else { - - console.log( 'not ready' ); - } return this.ready; From 368e91b270afd34bb22484188daaa6b405d752ff Mon Sep 17 00:00:00 2001 From: aardgoose Date: Mon, 3 Jun 2019 12:25:49 +0100 Subject: [PATCH 09/18] add sync mode to preserve .compile() behaviour --- src/renderers/WebGLRenderer.js | 10 +++++----- src/renderers/webgl/WebGLProgram.js | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/renderers/WebGLRenderer.js b/src/renderers/WebGLRenderer.js index f50958b7a696a..48b7adfecdde3 100644 --- a/src/renderers/WebGLRenderer.js +++ b/src/renderers/WebGLRenderer.js @@ -1044,13 +1044,13 @@ function WebGLRenderer( parameters ) { for ( var i = 0; i < object.material.length; i ++ ) { - initMaterial( object.material[ i ], scene.fog, object ); + initMaterial( object.material[ i ], scene.fog, object, true ); } } else { - initMaterial( object.material, scene.fog, object ); + initMaterial( object.material, scene.fog, object, true ); } @@ -1441,7 +1441,7 @@ function WebGLRenderer( parameters ) { } - function initMaterial( material, fog, object ) { + function initMaterial( material, fog, object, sync ) { var materialProperties = properties.get( material ); @@ -1522,7 +1522,7 @@ function WebGLRenderer( parameters ) { } - if ( ! program.ready && ! program.isLinked( _this, material ) ) { + if ( ! program.ready && ! program.isLinked( _this, material, sync ) ) { materialProperties.retry = true; return; @@ -1665,7 +1665,7 @@ function WebGLRenderer( parameters ) { if ( material.needsUpdate || materialProperties.retry ) { - initMaterial( material, fog, object ); + initMaterial( material, fog, object, false ); material.needsUpdate = false; } diff --git a/src/renderers/webgl/WebGLProgram.js b/src/renderers/webgl/WebGLProgram.js index e22435ec13128..22fb191d502b2 100644 --- a/src/renderers/webgl/WebGLProgram.js +++ b/src/renderers/webgl/WebGLProgram.js @@ -734,11 +734,11 @@ function WebGLProgram( renderer, extensions, code, material, shader, parameters, Object.assign( WebGLProgram.prototype, { - isLinked: function ( renderer, material ) { + isLinked: function ( renderer, material, sync ) { var gl = renderer.context; - if ( gl.getProgramParameter( this.program, this.parallelShaderExt.COMPLETION_STATUS_KHR ) == true ) { + if ( gl.getProgramParameter( this.program, this.parallelShaderExt.COMPLETION_STATUS_KHR ) == true || sync ) { this.checkLink( renderer, material ); this.ready = true; From 2a88ce0750aad5b596d69def6ed10a816c33fb42 Mon Sep 17 00:00:00 2001 From: aardgoose Date: Tue, 4 Jun 2019 21:29:16 +0100 Subject: [PATCH 10/18] limit simultaneous compiles --- src/renderers/webgl/WebGLProgram.js | 97 ++++++++++++++++++++--------- 1 file changed, 69 insertions(+), 28 deletions(-) diff --git a/src/renderers/webgl/WebGLProgram.js b/src/renderers/webgl/WebGLProgram.js index 22fb191d502b2..090efce470c03 100644 --- a/src/renderers/webgl/WebGLProgram.js +++ b/src/renderers/webgl/WebGLProgram.js @@ -8,6 +8,8 @@ import { ShaderChunk } from '../shaders/ShaderChunk.js'; import { NoToneMapping, AddOperation, MixOperation, MultiplyOperation, EquirectangularRefractionMapping, CubeRefractionMapping, SphericalReflectionMapping, EquirectangularReflectionMapping, CubeUVRefractionMapping, CubeUVReflectionMapping, CubeReflectionMapping, PCFSoftShadowMap, PCFShadowMap, ACESFilmicToneMapping, CineonToneMapping, Uncharted2ToneMapping, ReinhardToneMapping, LinearToneMapping, GammaEncoding, RGBDEncoding, RGBM16Encoding, RGBM7Encoding, RGBEEncoding, sRGBEncoding, LinearEncoding } from '../../constants.js'; var programIdCount = 0; +var maxParallel = 1; +var currentParallel = 0; function addLineNumbers( string ) { @@ -609,47 +611,36 @@ function WebGLProgram( renderer, extensions, code, material, shader, parameters, var parallelShaderExt = capabilities.parallelShaderCompile; - var vertexGlsl = prefixVertex + vertexShader; - var fragmentGlsl = prefixFragment + fragmentShader; - - // console.log( '*VERTEX*', vertexGlsl ); - // console.log( '*FRAGMENT*', fragmentGlsl ); - - var glVertexShader = WebGLShader( gl, gl.VERTEX_SHADER, vertexGlsl ); - var glFragmentShader = WebGLShader( gl, gl.FRAGMENT_SHADER, fragmentGlsl ); + this.prefixVertex = prefixVertex; + this.prefixFragment = prefixFragment; - gl.attachShader( program, glVertexShader ); - gl.attachShader( program, glFragmentShader ); + this.vertexShader = vertexShader; + this.fragmentShader = fragmentShader; - // Force a particular attribute to index 0. + this.program = program; + this.parameters = parameters; + this.parallelShaderExt = parallelShaderExt; + this.pending = false; - if ( material.index0AttributeName !== undefined ) { + if ( parallelShaderExt !== null && material.parallelCompile ) { - gl.bindAttribLocation( program, 0, material.index0AttributeName ); + if ( currentParallel < maxParallel ) { - } else if ( parameters.morphTargets === true ) { + this.compileAndLink( renderer, material ); + currentParallel ++; - // programs with morphTargets displace position out of attribute 0 - gl.bindAttribLocation( program, 0, 'position' ); + } else { - } + this.pending = true; - this.program = program; - this.vertexShader = glVertexShader; - this.fragmentShader = glFragmentShader; - this.parallelShaderExt = parallelShaderExt; - this.prefixVertex = prefixVertex; - this.prefixFragment = prefixFragment; - - gl.linkProgram( program ); - - if ( parallelShaderExt !== null && material.parallelCompile ) { + } this.ready = false; } else { // check for link errors + this.compileAndLink( renderer, material ); this.checkLink( renderer, material ); this.ready = true; @@ -734,14 +725,64 @@ function WebGLProgram( renderer, extensions, code, material, shader, parameters, Object.assign( WebGLProgram.prototype, { + compileAndLink: function ( renderer, material ) { + + var gl = renderer.context; + + var program = this.program; + var vertexGlsl = this.prefixVertex + this.vertexShader; + var fragmentGlsl = this.prefixFragment + this.fragmentShader; + + this.startFrame = renderer.info.render.frame; + + // console.log( '*VERTEX*', vertexGlsl ); + // console.log( '*FRAGMENT*', fragmentGlsl ); + + var glVertexShader = WebGLShader( gl, gl.VERTEX_SHADER, vertexGlsl ); + var glFragmentShader = WebGLShader( gl, gl.FRAGMENT_SHADER, fragmentGlsl ); + + gl.attachShader( program, glVertexShader ); + gl.attachShader( program, glFragmentShader ); + + // Force a particular attribute to index 0. + + if ( material.index0AttributeName !== undefined ) { + + gl.bindAttribLocation( program, 0, material.index0AttributeName ); + + } else if ( this.parameters.morphTargets === true ) { + + // programs with morphTargets displace position out of attribute 0 + gl.bindAttribLocation( program, 0, 'position' ); + + } + + gl.linkProgram( program ); + + this.vertexShader = glVertexShader; + this.fragmentShader = glFragmentShader; + + }, + isLinked: function ( renderer, material, sync ) { var gl = renderer.context; - if ( gl.getProgramParameter( this.program, this.parallelShaderExt.COMPLETION_STATUS_KHR ) == true || sync ) { + if ( this.pending && currentParallel < maxParallel ) { + + this.compileAndLink( renderer, material ); + currentParallel ++; + this.pending = false; + + } + + if ( ( ! this.pending && gl.getProgramParameter( this.program, this.parallelShaderExt.COMPLETION_STATUS_KHR ) == true ) || sync ) { this.checkLink( renderer, material ); this.ready = true; + currentParallel --; + + console.log( 'done', this.startFrame, renderer.info.render.frame - this.startFrame ); } From 774b5c8383d1c9fb0e2d63fd62c1c2ef4da5ed21 Mon Sep 17 00:00:00 2001 From: aardgoose Date: Mon, 16 Sep 2019 10:55:39 +0100 Subject: [PATCH 11/18] document capability --- docs/api/en/renderers/WebGLRenderer.html | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/api/en/renderers/WebGLRenderer.html b/docs/api/en/renderers/WebGLRenderer.html index fbf2f2c39d90e..b8eac906a6bf3 100644 --- a/docs/api/en/renderers/WebGLRenderer.html +++ b/docs/api/en/renderers/WebGLRenderer.html @@ -133,6 +133,7 @@

[property:Object capabilities]

- [page:Integer maxVertexUniforms]: The value of *gl.MAX_VERTEX_UNIFORM_VECTORS*. The maximum number of uniforms that can be used in a vertex shader.
- [page:String precision]: The shader precision currently being used by the renderer.
+ - [page:Boolean parallelShaderCompile]: whether the context supports the [link:https://www.khronos.org/registry/webgl/extensions/KHR_parallel_shader_compile/ KHR_parallel_shader_compile] extension..
- [page:Boolean vertexTextures]: *true* if [property:Integer maxVertexTextures] is greater than 0 (i.e. vertext textures can be used).

From b2f5822ec6cdc1d8c8e87a93259b7e331b9de53c Mon Sep 17 00:00:00 2001 From: aardgoose Date: Mon, 16 Sep 2019 11:00:49 +0100 Subject: [PATCH 12/18] doc update --- docs/api/en/renderers/WebGLRenderer.html | 2 +- docs/api/zh/renderers/WebGLRenderer.html | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/api/en/renderers/WebGLRenderer.html b/docs/api/en/renderers/WebGLRenderer.html index b8eac906a6bf3..b54691120afd8 100644 --- a/docs/api/en/renderers/WebGLRenderer.html +++ b/docs/api/en/renderers/WebGLRenderer.html @@ -132,8 +132,8 @@

[property:Object capabilities]

The number of textures that can be used in a vertex shader.
- [page:Integer maxVertexUniforms]: The value of *gl.MAX_VERTEX_UNIFORM_VECTORS*. The maximum number of uniforms that can be used in a vertex shader.
- - [page:String precision]: The shader precision currently being used by the renderer.
- [page:Boolean parallelShaderCompile]: whether the context supports the [link:https://www.khronos.org/registry/webgl/extensions/KHR_parallel_shader_compile/ KHR_parallel_shader_compile] extension..
+ - [page:String precision]: The shader precision currently being used by the renderer.
- [page:Boolean vertexTextures]: *true* if [property:Integer maxVertexTextures] is greater than 0 (i.e. vertext textures can be used).

diff --git a/docs/api/zh/renderers/WebGLRenderer.html b/docs/api/zh/renderers/WebGLRenderer.html index d2f9b026c3893..1d03718690940 100644 --- a/docs/api/zh/renderers/WebGLRenderer.html +++ b/docs/api/zh/renderers/WebGLRenderer.html @@ -113,6 +113,7 @@

[property:Object capabilities]

- [page:Integer maxVaryings]: *gl.MAX_VARYING_VECTORS*的值,着色器可使用矢量的数量
- [page:Integer maxVertexTextures]: *gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS*的值,顶点着色器可使用的纹理数量。
- [page:Integer maxVertexUniforms]: *gl.MAX_VERTEX_UNIFORM_VECTORS*的值,顶点着色器可使用的全局变量(uniforms)数量
+ - [page:Boolean parallelShaderCompile]: whether the context supports the [link:https://www.khronos.org/registry/webgl/extensions/KHR_parallel_shader_compile/ KHR_parallel_shader_compile] extension..
- [page:String precision]: 渲染器当前使用的着色器的精度
- [page:Boolean vertexTextures]: 如果[property:Integer maxVertexTextures]大于0,此值为*true* (即可以使用顶点纹理)

From 715f6f3c6cd67bf2eb95b9c6663dbf300022aaa2 Mon Sep 17 00:00:00 2001 From: aardgoose Date: Mon, 16 Sep 2019 11:06:07 +0100 Subject: [PATCH 13/18] use getContext() --- src/renderers/webgl/WebGLProgram.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/renderers/webgl/WebGLProgram.js b/src/renderers/webgl/WebGLProgram.js index 0efb306aefd23..a2695cc34e0e0 100644 --- a/src/renderers/webgl/WebGLProgram.js +++ b/src/renderers/webgl/WebGLProgram.js @@ -686,7 +686,7 @@ function WebGLProgram( renderer, extensions, code, material, shader, parameters, this.pending = false; this.numMultiviewViews = numMultiviewViews; - if ( parallelShaderExt !== null && material.parallelCompile ) { + if ( parallelShaderExt !== null && renderer.parallelCompile ) { if ( currentParallel < maxParallel ) { @@ -766,7 +766,7 @@ Object.assign( WebGLProgram.prototype, { compileAndLink: function ( renderer, material ) { - var gl = renderer.context; + var gl = renderer.getContext(); var program = this.program; var vertexGlsl = this.prefixVertex + this.vertexShader; @@ -805,7 +805,7 @@ Object.assign( WebGLProgram.prototype, { isLinked: function ( renderer, material, sync ) { - var gl = renderer.context; + var gl = renderer.getContext(); if ( this.pending && currentParallel < maxParallel ) { @@ -833,7 +833,7 @@ Object.assign( WebGLProgram.prototype, { // check for link errors - var gl = renderer.context; + var gl = renderer.getContext(); var program = this.program; var glVertexShader = this.vertexShader; var glFragmentShader = this.fragmentShader; From c04a23172e83f32b4bad1c12625d25e2e495a0ab Mon Sep 17 00:00:00 2001 From: aardgoose Date: Mon, 16 Sep 2019 11:06:28 +0100 Subject: [PATCH 14/18] remove Material.parallelCompile --- src/materials/Material.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/materials/Material.js b/src/materials/Material.js index b0cb3e0d2692a..ee22bec3fa1c7 100644 --- a/src/materials/Material.js +++ b/src/materials/Material.js @@ -70,7 +70,6 @@ function Material() { this.premultipliedAlpha = false; this.visible = true; - this.parallelCompile = false; this.toneMapped = true; From 810c9c21032eb8613a6676818f5595753c7cc4e0 Mon Sep 17 00:00:00 2001 From: aardgoose Date: Mon, 16 Sep 2019 14:49:26 +0100 Subject: [PATCH 15/18] move switch back to material --- src/materials/Material.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/materials/Material.js b/src/materials/Material.js index ee22bec3fa1c7..c134bd31a7304 100644 --- a/src/materials/Material.js +++ b/src/materials/Material.js @@ -69,6 +69,7 @@ function Material() { this.alphaTest = 0; this.premultipliedAlpha = false; + this.parallelCompile = false; this.visible = true; this.toneMapped = true; From 9ac963f23206940b544027b64ac0eb2b8a643996 Mon Sep 17 00:00:00 2001 From: aardgoose Date: Mon, 16 Sep 2019 14:52:54 +0100 Subject: [PATCH 16/18] fix race on destruction and tidy --- src/renderers/webgl/WebGLProgram.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/renderers/webgl/WebGLProgram.js b/src/renderers/webgl/WebGLProgram.js index a2695cc34e0e0..9945c961c082b 100644 --- a/src/renderers/webgl/WebGLProgram.js +++ b/src/renderers/webgl/WebGLProgram.js @@ -686,7 +686,7 @@ function WebGLProgram( renderer, extensions, code, material, shader, parameters, this.pending = false; this.numMultiviewViews = numMultiviewViews; - if ( parallelShaderExt !== null && renderer.parallelCompile ) { + if ( parallelShaderExt !== null && material.parallelCompile ) { if ( currentParallel < maxParallel ) { @@ -746,6 +746,14 @@ function WebGLProgram( renderer, extensions, code, material, shader, parameters, this.destroy = function () { + if ( ! this.ready && ! this.pending ) { + + // parallel compilation incomplete + + currentParallel --; + + } + gl.deleteProgram( program ); this.program = undefined; @@ -810,8 +818,8 @@ Object.assign( WebGLProgram.prototype, { if ( this.pending && currentParallel < maxParallel ) { this.compileAndLink( renderer, material ); - currentParallel ++; this.pending = false; + currentParallel ++; } @@ -821,7 +829,7 @@ Object.assign( WebGLProgram.prototype, { this.ready = true; currentParallel --; - console.log( 'done', this.startFrame, renderer.info.render.frame - this.startFrame ); + console.log( 'THREE.WebGLProgram: parallel compile frame count', renderer.info.render.frame - this.startFrame ); } From 25d3707095eff0ac5c10e76879e7ae57086c35b4 Mon Sep 17 00:00:00 2001 From: aardgoose Date: Tue, 17 Sep 2019 11:11:51 +0100 Subject: [PATCH 17/18] Add global default --- src/materials/Material.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/materials/Material.js b/src/materials/Material.js index c134bd31a7304..54fb7b7ac87be 100644 --- a/src/materials/Material.js +++ b/src/materials/Material.js @@ -69,7 +69,7 @@ function Material() { this.alphaTest = 0; this.premultipliedAlpha = false; - this.parallelCompile = false; + this.parallelCompile = Material.DefaultParallelCompile; this.visible = true; this.toneMapped = true; @@ -80,6 +80,8 @@ function Material() { } +Material.DefaultParallelCompile = false; + Material.prototype = Object.assign( Object.create( EventDispatcher.prototype ), { constructor: Material, From e8ddd765e09236f08e990744bd3569f4134e68a4 Mon Sep 17 00:00:00 2001 From: aardgoose Date: Fri, 20 Sep 2019 10:55:56 +0100 Subject: [PATCH 18/18] pass extension in parameters --- src/renderers/webgl/WebGLProgram.js | 2 +- src/renderers/webgl/WebGLPrograms.js | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/renderers/webgl/WebGLProgram.js b/src/renderers/webgl/WebGLProgram.js index f000fffc02c47..5a42cb3c6f77f 100644 --- a/src/renderers/webgl/WebGLProgram.js +++ b/src/renderers/webgl/WebGLProgram.js @@ -721,7 +721,7 @@ function WebGLProgram( renderer, extensions, code, material, shader, parameters } - var parallelShaderExt = capabilities.parallelShaderCompile; + var parallelShaderExt = parameters.parallelShaderCompile; this.prefixVertex = prefixVertex; this.prefixFragment = prefixFragment; diff --git a/src/renderers/webgl/WebGLPrograms.js b/src/renderers/webgl/WebGLPrograms.js index e8dadaa580cd5..9079ad5a90016 100644 --- a/src/renderers/webgl/WebGLPrograms.js +++ b/src/renderers/webgl/WebGLPrograms.js @@ -139,6 +139,7 @@ function WebGLPrograms( renderer, extensions, capabilities ) { precision: precision, isWebGL2: capabilities.isWebGL2, supportsVertexTextures: capabilities.vertexTextures, + parallelShaderCompile: capabilities.parallelShaderCompile, outputEncoding: getTextureEncodingFromMap( ( ! currentRenderTarget ) ? null : currentRenderTarget.texture, renderer.gammaOutput ), map: !! material.map, mapEncoding: getTextureEncodingFromMap( material.map, renderer.gammaInput ),