Skip to content

Commit

Permalink
Link WebGL shaders immediately after compilation (#6076)
Browse files Browse the repository at this point in the history
Co-authored-by: Martin Valigursky <mvaligursky@snapchat.com>
  • Loading branch information
mvaligursky and Martin Valigursky authored Feb 21, 2024
1 parent 45c0bd5 commit cac7efc
Show file tree
Hide file tree
Showing 4 changed files with 5 additions and 45 deletions.
9 changes: 0 additions & 9 deletions src/platform/graphics/webgl/webgl-graphics-device.js
Original file line number Diff line number Diff line change
Expand Up @@ -1352,15 +1352,6 @@ class WebglGraphicsDevice extends GraphicsDevice {
this.gpuProfiler?.restoreContext();
}

/**
* Called after a batch of shaders was created, to guide in their optimal preparation for rendering.
*
* @ignore
*/
endShaderBatch() {
WebglShader.endShaderBatch(this);
}

/**
* Set the active rectangle for rendering on the specified device.
*
Expand Down
35 changes: 5 additions & 30 deletions src/platform/graphics/webgl/webgl-shader.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,8 @@ class CompiledShaderCache {
}
}

// class used to hold a list of recently created shaders forming a batch, to allow their more optimized compilation
class ShaderBatchCache {
shaders = [];

loseContext(device) {
this.shaders = [];
}
}

const _vertexShaderCache = new DeviceCache();
const _fragmentShaderCache = new DeviceCache();
const _shaderBatchCache = new DeviceCache();

/**
* A WebGL implementation of the Shader.
Expand All @@ -58,12 +48,11 @@ class WebglShader {
constructor(shader) {
this.init();

// kick off vertex and fragment shader compilation, but not linking here, as that would
// make it blocking.
// kick off vertex and fragment shader compilation
this.compile(shader.device, shader);

// add the shader to recently created list
WebglShader.getBatchShaders(shader.device).push(shader);
// kick off linking, as this is non-blocking too
this.link(shader.device, shader);

// add it to a device list of all shaders
shader.device.shaders.push(shader);
Expand Down Expand Up @@ -91,22 +80,6 @@ class WebglShader {
this.glFragmentShader = null;
}

static getBatchShaders(device) {
const batchCache = _shaderBatchCache.get(device, () => {
return new ShaderBatchCache();
});
return batchCache.shaders;
}

static endShaderBatch(device) {

// Trigger link step for all recently created shaders. This allows linking to be done in parallel, before
// the blocking wait on the linking result is triggered in finalize function
const shaders = WebglShader.getBatchShaders(device);
shaders.forEach(shader => shader.impl.link(device, shader));
shaders.length = 0;
}

/**
* Dispose the shader when the context has been lost.
*/
Expand Down Expand Up @@ -305,6 +278,8 @@ class WebglShader {
linkStartTime = now();
});

// check the link status of a shader - this is a blocking operation waiting for the shader
// to finish compiling and linking
const linkStatus = gl.getProgramParameter(glProgram, gl.LINK_STATUS);
if (!linkStatus) {

Expand Down
3 changes: 0 additions & 3 deletions src/scene/renderer/forward-renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -530,9 +530,6 @@ class ForwardRenderer extends Renderer {
prevLightMask = lightMask;
}

// process the batch of shaders created here
device.endShaderBatch?.();

return _drawCallList;
}

Expand Down
3 changes: 0 additions & 3 deletions src/scene/renderer/shadow-renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -300,9 +300,6 @@ class ShadowRenderer {
const passFlags = 1 << SHADER_SHADOW;
const shadowPass = this.getShadowPass(light);

// TODO: Similarly to forward renderer, a shader creation part of this loop should be split into a separate loop,
// and endShaderBatch should be called at its end

// Render
const count = visibleCasters.length;
for (let i = 0; i < count; i++) {
Expand Down

0 comments on commit cac7efc

Please sign in to comment.