Skip to content

Commit

Permalink
Message:
Browse files Browse the repository at this point in the history
OBJLoader2 example integration
- Support both module and legacy worker
- TaskManager: Dependency loading allows to provide strings along with to be loaded urls
- Fixed scene clean-up
- Fixed copying transferables on init for all workers
- Example clean-up and better structure, prepare for legacy OBJLoader2Parser worker
- Updated TypeScript definitions
- Intermediate asset return is working (mesh streaming)
- Fixed worker and config id mixup
- OBJLoader2Parser: Encapsulated into one function => simplify serialization
- OBJLoader2Parser: For the example create simple module that only relies on parser
  • Loading branch information
kaisalmen committed Jul 23, 2020
1 parent addd3d4 commit f49dda6
Show file tree
Hide file tree
Showing 11 changed files with 567 additions and 330 deletions.
15 changes: 3 additions & 12 deletions examples/jsm/loaders/OBJLoader2Parallel.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,15 +71,10 @@ OBJLoader2Parallel.prototype = Object.assign( Object.create( OBJLoader2.prototyp
setJsmWorker: function ( preferJsmWorker, jsmWorkerUrl ) {

this.preferJsmWorker = preferJsmWorker === true;

if ( jsmWorkerUrl === undefined || jsmWorkerUrl === null ) {

throw "The url to the jsm worker is not valid. Aborting...";

throw "The url to the jsm worker is not valid. Aborting..."
}

this.jsmWorkerUrl = jsmWorkerUrl;

return this;

},
Expand All @@ -101,19 +96,18 @@ OBJLoader2Parallel.prototype = Object.assign( Object.create( OBJLoader2.prototyp
buildWorkerCode: function () {

let codeBuilderInstructions = new CodeBuilderInstructions( true, true, this.preferJsmWorker );

if ( codeBuilderInstructions.isSupportsJsmWorker() ) {

codeBuilderInstructions.setJsmWorkerUrl( this.jsmWorkerUrl );

}

if ( codeBuilderInstructions.isSupportsStandardWorker() ) {

let objectManipulator = new ObjectManipulator();
let defaultWorkerPayloadHandler = new DefaultWorkerPayloadHandler( this.parser );
let workerRunner = new WorkerRunner( {} );
codeBuilderInstructions.addCodeFragment( CodeSerializer.serializeClass( OBJLoader2Parser, this.parser ) );

codeBuilderInstructions.addCodeFragment( 'const OBJLoader2Parser = ' + OBJLoader2Parser.toString() + ';\n\n' );
codeBuilderInstructions.addCodeFragment( CodeSerializer.serializeClass( ObjectManipulator, objectManipulator ) );
codeBuilderInstructions.addCodeFragment( CodeSerializer.serializeClass( DefaultWorkerPayloadHandler, defaultWorkerPayloadHandler ) );
codeBuilderInstructions.addCodeFragment( CodeSerializer.serializeClass( WorkerRunner, workerRunner ) );
Expand All @@ -122,7 +116,6 @@ OBJLoader2Parallel.prototype = Object.assign( Object.create( OBJLoader2.prototyp
codeBuilderInstructions.addStartCode( startCode );

}

return codeBuilderInstructions;

},
Expand Down Expand Up @@ -169,7 +162,6 @@ OBJLoader2Parallel.prototype = Object.assign( Object.create( OBJLoader2.prototyp
throw "No callback other than the default callback was provided! Aborting!";

}

// check if worker has been initialize before. If yes, skip init
if ( ! this.workerExecutionSupport.isWorkerLoaded( this.preferJsmWorker ) ) {

Expand All @@ -181,7 +173,6 @@ OBJLoader2Parallel.prototype = Object.assign( Object.create( OBJLoader2.prototyp
scope._onAssetAvailable( payload );

};

function scopedOnLoad( message ) {

scope.parser.callbacks.onLoad( scope.baseObject3d, message );
Expand Down
16 changes: 9 additions & 7 deletions examples/jsm/loaders/TaskManager.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ export class TaskManager {
setMaxParallelExecutions(maxParallelExecutions: number): TaskManager;
getMaxParallelExecutions(): number;
supportsTaskType(taskType: string): boolean;
registerTaskType(taskType: string, initFunction: Function, executeFunction: Function, comRoutingFunction: Function, fallback: boolean, dependencyUrls?: string[]): TaskManager;
registerTaskType(taskType: string, initFunction: Function, executeFunction: Function, comRoutingFunction: Function, fallback: boolean, dependencyDescriptions?: any[]): TaskManager;
registerTaskTypeModule(taskType: string, workerModuleUrl: string): TaskManager;
initTaskType(taskType: string, config: object, transferables?: Transferable[]): Promise<void | TaskWorker[]>;
enqueueForExecution(taskType: string, config: object, transferables?: Transferable[]): Promise<any>;
initTaskType(taskType: string, config: object, transferables?: any): Promise<void | TaskWorker[]>;
enqueueForExecution(taskType: string, config: object, assetAvailableFunction: Function, transferables?: any): Promise<any>;
_kickExecutions(): void;
dispose(): TaskManager;
}
Expand All @@ -35,7 +35,7 @@ declare class WorkerTypeDefinition {
code: string;
};
dependencies: {
urls: URL[];
descriptions: any[];
code: string[];
};
workerModuleUrl: URL;
Expand All @@ -47,23 +47,24 @@ declare class WorkerTypeDefinition {
};
getTaskType(): string;
setFunctions(initFunction: Function, executeFunction: Function, comRoutingFunction?: Function): void;
setDependencyUrls(dependencyUrls: string[]): void;
setDependencyDescriptions(dependencyDescriptions: any[]): void;
setWorkerModule(workerModuleUrl: string): void;
isWorkerModule(): boolean;
loadDependencies(): Promise<ArrayBuffer[]>;
generateWorkerCode(dependencies: ArrayBuffer[]): Promise<string[]>;
createWorkers(code: string): Promise<TaskWorker[]>;
createWorkerModules(): Promise<TaskWorker[]>;
initWorkers(instances: TaskWorker[] | MockedTaskWorker[], config: object, transferables: Transferable[]): Promise<TaskWorker[]>;
initWorkers(instances: TaskWorker[] | MockedTaskWorker[], config: object, transferables: any): Promise<TaskWorker[]>;
getAvailableTask(): TaskWorker | MockedTaskWorker | undefined;
hasTask(): boolean;
returnAvailableTask(taskWorker: TaskWorker | MockedTaskWorker): void;
dispose(): void;
}
declare class StoredExecution {
constructor(taskType: string, config: object, resolve: Function, reject: Function, transferables?: Transferable[]);
constructor(taskType: string, config: object, assetAvailableFunction: Function, resolve: Function, reject: Function, transferables?: Transferable[]);
taskType: string;
config: any;
assetAvailableFunction: Function;
resolve: Function;
reject: Function;
transferables: Transferable[];
Expand All @@ -82,5 +83,6 @@ declare class MockedTaskWorker {
};
getId(): number;
postMessage(message: string, transfer?: Transferable[]): void;
terminate(): void;
}
export {};
83 changes: 62 additions & 21 deletions examples/jsm/loaders/TaskManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,14 +88,14 @@ class TaskManager {
* @param {function} executeFunction The function to be called when the worker is executed
* @param {function} comRoutingFunction The function that should handle communication, leave undefined for default behavior
* @param {boolean} fallback Set to true if execution should be performed in main
* @param {String[]} [dependencyUrls]
* @param {Object[]} [dependencyDescriptions]
* @return {TaskManager}
*/
registerTaskType ( taskType, initFunction, executeFunction, comRoutingFunction, fallback, dependencyUrls ) {
registerTaskType ( taskType, initFunction, executeFunction, comRoutingFunction, fallback, dependencyDescriptions ) {

let workerTypeDefinition = new WorkerTypeDefinition( taskType, this.maxParallelExecutions, fallback, this.verbose );
workerTypeDefinition.setFunctions( initFunction, executeFunction, comRoutingFunction );
workerTypeDefinition.setDependencyUrls( dependencyUrls );
workerTypeDefinition.setDependencyDescriptions( dependencyDescriptions );
this.taskTypes.set( taskType, workerTypeDefinition );
return this;

Expand All @@ -122,7 +122,7 @@ class TaskManager {
*
* @param {string} taskType The name of the registered task type.
* @param {object} config Configuration properties as serializable string.
* @param {Transferable[]} [transferables] Any optional {@link ArrayBuffer}.
* @param {Object} [transferables] Any optional {@link ArrayBuffer} encapsulated in object..
*/
async initTaskType ( taskType, config, transferables ) {

Expand All @@ -149,14 +149,15 @@ class TaskManager {
*
* @param {string} taskType The name of the registered task type.
* @param {object} config Configuration properties as serializable string.
* @param {Transferable[]} [transferables] Any optional {@link ArrayBuffer}.
* @param {Function} assetAvailableFunction Invoke this function if an asset become intermediately available
* @param {Object} [transferables] Any optional {@link ArrayBuffer} encapsulated in object.
* @return {Promise}
*/
async enqueueForExecution ( taskType, config, transferables ) {
async enqueueForExecution ( taskType, config, assetAvailableFunction, transferables ) {

let localPromise = new Promise( ( resolveUser, rejectUser ) => {

this.storedExecutions.push( new StoredExecution( taskType, config, resolveUser, rejectUser, transferables ) );
this.storedExecutions.push( new StoredExecution( taskType, config, assetAvailableFunction, resolveUser, rejectUser, transferables ) );

} );
this._kickExecutions();
Expand All @@ -178,12 +179,30 @@ class TaskManager {
this.actualExecutionCount++;
let promiseWorker = new Promise( ( resolveWorker, rejectWorker ) => {

taskWorker.onmessage = resolveWorker;
taskWorker.onmessage = function ( e ) {

// allow intermediate asset provision before flagging execComplete
if ( e.data.cmd === 'assetAvailable' ) {

if ( storedExecution.assetAvailableFunction instanceof Function ) {

storedExecution.assetAvailableFunction( e.data );

}

}
else {

resolveWorker( e );

}

};
taskWorker.onerror = rejectWorker;

taskWorker.postMessage( {
cmd: "execute",
id: taskWorker.getId(),
workerId: taskWorker.getId(),
config: storedExecution.config
}, storedExecution.transferables );

Expand Down Expand Up @@ -268,8 +287,8 @@ class WorkerTypeDefinition {
code: null
},
dependencies: {
/** @type {URL[]} */
urls: [],
/** @type {Object[]} */
descriptions: [],
/** @type {string[]} */
code: []
},
Expand Down Expand Up @@ -334,13 +353,13 @@ class WorkerTypeDefinition {
/**
* Set the url of all dependent libraries (only used in non-module case).
*
* @param {String[]} dependencyUrls URLs of code init and execute functions rely on.
* @param {Object[]} dependencyDescriptions URLs of code init and execute functions rely on.
*/
setDependencyUrls ( dependencyUrls ) {
setDependencyDescriptions ( dependencyDescriptions ) {

if ( dependencyUrls ) {
if ( dependencyDescriptions ) {

dependencyUrls.forEach( url => { this.functions.dependencies.urls.push( new URL( url, window.location.href ) ) } );
dependencyDescriptions.forEach( description => { this.functions.dependencies.descriptions.push( description ) } );

}

Expand Down Expand Up @@ -377,9 +396,20 @@ class WorkerTypeDefinition {

let fileLoader = new FileLoader();
fileLoader.setResponseType( 'arraybuffer' );
for ( let url of this.functions.dependencies.urls ) {
for ( let description of this.functions.dependencies.descriptions ) {

let dep = await fileLoader.loadAsync( url.href, report => { if ( this.verbose ) console.log( report ); } )
let dep;
if ( description.url ) {

let url = new URL( description.url, window.location.href );
dep = await fileLoader.loadAsync( url.href, report => { if ( this.verbose ) console.log( report ); } )

}
if ( description.code ) {

dep = description.code;

}
this.functions.dependencies.code.push( dep );

}
Expand Down Expand Up @@ -469,7 +499,7 @@ class WorkerTypeDefinition {
*
* @param {TaskWorker[]|MockedTaskWorker[]} instances
* @param {object} config
* @param {Transferable[]} transferables
* @param {Object} transferables
* @return {Promise<TaskWorker[]>}
*/
async initWorkers ( instances, config, transferables ) {
Expand All @@ -481,11 +511,20 @@ class WorkerTypeDefinition {
taskWorker.onmessage = resolveWorker;
taskWorker.onerror = rejectWorker;

// ensure all transferables are copies to all workers on int!
let transferablesToWorker;
if ( transferables ) {
transferablesToWorker = {};
for ( let [ key, transferable ] of Object.entries( transferables ) ) {
transferablesToWorker[ key ] = transferable !== null ? transferable.slice( 0 ) : null;
}
}

taskWorker.postMessage( {
cmd: "init",
id: taskWorker.getId(),
workerId: taskWorker.getId(),
config: config
}, transferables );
}, transferablesToWorker );

} );
this.workers.available.push( taskWorker );
Expand Down Expand Up @@ -553,14 +592,16 @@ class StoredExecution {
*
* @param {string} taskType
* @param {object} config
* @param {Function} assetAvailableFunction
* @param {Function} resolve
* @param {Function} reject
* @param {Transferable[]} [transferables]
*/
constructor( taskType, config, resolve, reject, transferables ) {
constructor( taskType, config, assetAvailableFunction, resolve, reject, transferables ) {

this.taskType = taskType;
this.config = config;
this.assetAvailableFunction = assetAvailableFunction;
this.resolve = resolve;
this.reject = reject;
this.transferables = transferables;
Expand Down
Loading

0 comments on commit f49dda6

Please sign in to comment.