Add PipelineManager#restoreContext method for restoring uniforms.

Also add `WebGLShader#syncUniforms` and other code necessary to retain
and reapply uniform state on the GPU.
This commit is contained in:
Ben Richards 2024-01-31 16:46:41 +13:00
parent 9b8bb39e7c
commit 8906e22aeb
4 changed files with 78 additions and 0 deletions

View file

@ -1248,6 +1248,24 @@ var PipelineManager = new Class({
return this.set(this.FX_PIPELINE); return this.set(this.FX_PIPELINE);
}, },
/**
* Restore WebGL resources after context was lost.
*
* Calls `rebind` on this Pipeline Manager.
* Then calls `restoreContext` on each pipeline in turn.
*
* @method Phaser.Renderer.WebGL.PipelineManager#restoreContext
* @since 3.80.0
*/
restoreContext: function ()
{
this.rebind();
this.pipelines.each(function (_, pipeline)
{
pipeline.restoreContext();
});
},
/** /**
* Use this to reset the gl context to the state that Phaser requires to continue rendering. * Use this to reset the gl context to the state that Phaser requires to continue rendering.
* *

View file

@ -1194,6 +1194,24 @@ var WebGLPipeline = new Class({
return this; return this;
}, },
/**
* This method is called if the WebGL context is lost and restored.
* It ensures that uniforms are synced back to the GPU
* for all shaders in this pipeline.
*
* @method Phaser.Renderer.WebGL.WebGLPipeline#restoreContext
* @since 3.80.0
*/
restoreContext: function ()
{
var shaders = this.shaders;
for (var i = 0; i < shaders.length; i++)
{
shaders[i].syncUniforms();
}
},
/** /**
* Binds the vertex buffer to be the active ARRAY_BUFFER on the WebGL context. * Binds the vertex buffer to be the active ARRAY_BUFFER on the WebGL context.
* *

View file

@ -391,6 +391,7 @@ var WebGLShader = new Class({
{ {
name: name, name: name,
location: location, location: location,
setter: null,
value1: null, value1: null,
value2: null, value2: null,
value3: null, value3: null,
@ -418,6 +419,7 @@ var WebGLShader = new Class({
{ {
name: name, name: name,
location: location, location: location,
setter: null,
value1: null, value1: null,
value2: null, value2: null,
value3: null, value3: null,
@ -432,6 +434,25 @@ var WebGLShader = new Class({
return this; return this;
}, },
/**
* Repopulate uniforms on the GPU.
*
* This is called automatically by the pipeline when the context is
* lost and then recovered. By the time this method is called,
* the WebGL resources are already recreated, so we just need to
* re-populate them.
*
* @method Phaser.Renderer.WebGL.WebGLShader#syncUniforms
* @since 3.80.0
*/
syncUniforms: function ()
{
ArrayEach(this.uniforms, function (uniform)
{
uniform.setter.call(this.gl, uniform.location.webGLUniformLocation, uniform.value1, uniform.value2, uniform.value3, uniform.value4);
});
},
/** /**
* Checks to see if the given uniform name exists and is active in this shader. * Checks to see if the given uniform name exists and is active in this shader.
* *
@ -504,6 +525,11 @@ var WebGLShader = new Class({
if (skipCheck || uniform.value1 !== value1) if (skipCheck || uniform.value1 !== value1)
{ {
if (!uniform.setter)
{
uniform.setter = setter;
}
uniform.value1 = value1; uniform.value1 = value1;
this.renderer.setProgram(this.program); this.renderer.setProgram(this.program);
@ -549,6 +575,11 @@ var WebGLShader = new Class({
if (skipCheck || uniform.value1 !== value1 || uniform.value2 !== value2) if (skipCheck || uniform.value1 !== value1 || uniform.value2 !== value2)
{ {
if (!uniform.setter)
{
uniform.setter = setter;
}
uniform.value1 = value1; uniform.value1 = value1;
uniform.value2 = value2; uniform.value2 = value2;
@ -596,6 +627,11 @@ var WebGLShader = new Class({
if (skipCheck || uniform.value1 !== value1 || uniform.value2 !== value2 || uniform.value3 !== value3) if (skipCheck || uniform.value1 !== value1 || uniform.value2 !== value2 || uniform.value3 !== value3)
{ {
if (!uniform.setter)
{
uniform.setter = setter;
}
uniform.value1 = value1; uniform.value1 = value1;
uniform.value2 = value2; uniform.value2 = value2;
uniform.value3 = value3; uniform.value3 = value3;
@ -645,6 +681,11 @@ var WebGLShader = new Class({
if (skipCheck || uniform.value1 !== value1 || uniform.value2 !== value2 || uniform.value3 !== value3 || uniform.value4 !== value4) if (skipCheck || uniform.value1 !== value1 || uniform.value2 !== value2 || uniform.value3 !== value3 || uniform.value4 !== value4)
{ {
if (!uniform.setter)
{
uniform.setter = setter;
}
uniform.value1 = value1; uniform.value1 = value1;
uniform.value2 = value2; uniform.value2 = value2;
uniform.value3 = value3; uniform.value3 = value3;

View file

@ -4,6 +4,7 @@
* *
* @property {string} name - The name of the uniform as defined in the shader. * @property {string} name - The name of the uniform as defined in the shader.
* @property {number} location - The location of the uniform. * @property {number} location - The location of the uniform.
* @property {?function} setter - The setter function called on the WebGL context to set the uniform value.
* @property {number} [value1] - The first cached value of the uniform. * @property {number} [value1] - The first cached value of the uniform.
* @property {number} [value2] - The first cached value of the uniform. * @property {number} [value2] - The first cached value of the uniform.
* @property {number} [value3] - The first cached value of the uniform. * @property {number} [value3] - The first cached value of the uniform.