-
Notifications
You must be signed in to change notification settings - Fork 345
Description
Many developers will agree that freezing the interface the user interacts with results in a bad user experience. It is for this reason that developers may choose to perform some tasks asynchronously. Currently with WebGL compiling a shader / linking a program can freeze the browser for a short while; depending on the complexity of the shader and the user's hardware. On mobile this is usually way more noticeable.
Some would argue it's up to the developer to perform all shader generating, compiling and program linking at the very start of their web app or game. But there are valid reasons to generate and compile shaders at a later moment. E.g. loading in a new model at a later time (streaming?), or the user changing the game's quality settings during runtime. Or perhaps the app performs computations based on the user's input.
This is why I propose that, whatever function will compile the shader, should be either done forcefully asynchronously, or at least provide the option to do so, to prevent the browser from temporarily freezing. Said function would return a Promise, passing the compiled and validated shader to the resolve function and passing any error messages to the reject function.
Promises are The Future of Async Javascript™ and it only seemed logical to choose Promises over callback functions. With the introduction of async functions (already implemented in some browsers!) I believe Promises have become a more strong and important feature of the Javascript language.
Continuing Apple's example of using the Metal API, a common path to compile a shader (library) may look something like this (ignoring any error handling):
async function createRenderPipelineState() {
const source = await fetch(/* url */).then(response => response.text())
const library = await gpu.createLibrary(source)
const vertexF = library.functionWithName('vertex_main')
const fragmentF = library.functionWithName('fragment_main')
/** etc **/
return gpu.createRenderPipelineState(pipelineDescriptor);
}