phaser-ce icon indicating copy to clipboard operation
phaser-ce copied to clipboard

WebGL: INVALID_VALUE: vertexAttribPointer: index out of range (Ubuntu)

Open ColaColin opened this issue 7 years ago • 23 comments

A bug in the API:

I am getting WebGL: INVALID_VALUE: vertexAttribPointer: index out of range spam on Firefox as well as on Chromium, running Ubuntu.

There is no condition for it to happen. It just happens always. A "code example" therefore simply is the empty example codepen: https://codepen.io/pen?template=vyKJvw

There is nothing obvious wrong, except those errors being spammed.

Here is the stacktrace from chromium, referencing lines in phaser-arcade-physics.js of 2.7.7:

PIXI.WebGLSpriteBatch.flush @ phaser.js:5153 PIXI.WebGLSpriteBatch.end @ phaser.js:4806 PIXI.WebGLRenderer.renderDisplayObject @ phaser.js:3742 PIXI.WebGLRenderer.render @ phaser.js:3705 updateRender @ phaser.js:21403 update @ phaser.js:21325 updateRAF @ phaser.js:49064 _onLoop @ phaser.js:49047

It happens due to shader.aTextureIndex in the line gl.vertexAttribPointer(shader.aTextureIndex, 1, gl.FLOAT, false, stride, 20); being -1

It is -1 because the getAttributeLocation earlier does indeed seem to return -1 I have no idea why that is however. It reminds me of an issue I had in other WebGL code that was due to some attributes being optimized away since they were not used, but the shader code of the respective shader here does seem to at least superficially use the attribute.

The minimal code to create the issue is to have Phaser in your namespace and start it with:

new Phaser.Game({width: 10, height: 10, renderer: Phaser.AUTO, resolution: 1})

From that point on it spams the warning.

I tested 2.7.7 and 2.7.3, both show the error. 2.6.2 is unaffected

ColaColin avatar Apr 30 '17 15:04 ColaColin

new Phaser.Game({width: 10, height: 10, renderer: Phaser.AUTO, resolution: 1})

I don't see the warning in my Firefox (https://codepen.io/samme/pen/eWWWdz) so it may be platform-specific.

v2.7.7/src/pixi/renderers/webgl/utils/WebGLSpriteBatch.js#L58

samme avatar Apr 30 '17 17:04 samme

Can you try

new Phaser.Game({enableDebug: false});

?

samme avatar Apr 30 '17 17:04 samme

I get the same error here too

phaser.js:18791 WebGL: INVALID_VALUE: vertexAttribPointer: index out of range

I use chrome debug console tool , ubuntu 16.4 LTS

softmixt avatar Apr 30 '17 20:04 softmixt

@softmixt Which platform/OS?

samme avatar Apr 30 '17 20:04 samme

Ubuntu 16.4 LTS

softmixt avatar Apr 30 '17 20:04 softmixt

seleccion_031

softmixt avatar Apr 30 '17 20:04 softmixt

My problem system also runs Ubuntu 16.4 LTS, with a Nvidia GTX 960.

The same machine on Windows 7 does not show the error, neither in Chrome nor in Firefox.

I can try new Phaser.Game({enableDebug: false}); later, as in within 24h.

ColaColin avatar Apr 30 '17 22:04 ColaColin

Here is enableDebug: false: https://codepen.io/samme/pen/EmmwGo

samme avatar Apr 30 '17 22:04 samme

I get back to version v2.6.2 for now I'm going to check it later v2.7.7 using {enableDebug: false} and my g. card is GeForce GTX 1060 6GB/PCIe/SSE2 and I tried all available versions after 2.6.2 and all gave me same error .

softmixt avatar May 01 '17 09:05 softmixt

Running https://codepen.io/samme/pen/EmmwGo does not show any errors anywhere, whatever enableDebug does, setting it to false makes the errors go away.

ColaColin avatar May 01 '17 15:05 ColaColin

Error show when I bind a new state like this :

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8"/>
    <title>Hello Phaser</title>
    <script src="phaser.min.js"></script>
	<script>
	window.onload = function() {
		
			var StateExample = function ( game ){};
			
			/**
			* @type {{init: Boot.init, preload: Boot.preload, create: Boot.create}}
			*/
			StateExample.prototype = {

					/**
					 * Set Game initialization settings
					 */
					init: function ()
					{
						//this.input.maxPointers = 1;
						//this.game.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL;
					},
					preload: function ()
					{
						 // Example Assets
						 this.game.load.image( 'phaser_logo', 'img.png' );
					
					},
					create: function ()
					{
						// Set background for our game
						this.phaser_logo        = this.game.add.sprite( 100, 150, 'phaser_logo' );
					}

			};

			var game = new Phaser.Game( {
								enableDebug: false,
								width: 800,
								height: 600,
								renderer: Phaser.AUTO,
								parent: "game",
								transparent: true,
								antialias: true,
										} );
										
			  game.state.add( "StateExample", StateExample );
			  			  
			  game.state.start( "StateExample" );
	};
	
	</script>
</head>
<body>
<div id="game"></div>
</body>
</html>

this use v2.7.7 if I use v2.6.2 error doesn't show up anymore :(

the result of that code in chrome is this : seleccion_037

and result same code in firefox is this : seleccion_038

softmixt avatar May 01 '17 19:05 softmixt

The debug canvas is drawn each frame unless it's disabled (via enableDebug: false) so that's probably what's causing it in an "empty" game.

If you set a breakpoint on the line that's emitting the warning (INVALID_VALUE…) you should be able to see which render object it's linked to.

samme avatar May 03 '17 07:05 samme

I have the same issue under Arch Linux in chrome and i get errors in firefox aswell

TheSuspiciousWombat avatar May 03 '17 12:05 TheSuspiciousWombat

Even with enableDebug: false still shows the error, so checking a bit what line comes that i doscover it comming from this part :

PIXI.WebGLSpriteBatch.prototype.flush = function () {
    // If the batch is length 0 then return as there is nothing to draw
    if (this.currentBatchSize === 0) {
        return;
    }

    var gl = this.gl;
    var shader;

    if (this.dirty) {
        this.dirty = false;

        shader = this.defaultShader.shaders[gl.id];

        // bind the main texture
        gl.activeTexture(gl.TEXTURE0);

        // bind the buffers
        gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
        // this is the same for each shader?
        var stride = this.vertexSize; //this.vertSize * 4;
        gl.vertexAttribPointer(shader.aVertexPosition, 2, gl.FLOAT, false, stride, 0);
        gl.vertexAttribPointer(shader.aTextureCoord, 2, gl.FLOAT, false, stride, 8);

        // color attributes will be interpreted as unsigned bytes and normalized
        gl.vertexAttribPointer(shader.colorAttribute, 4, gl.UNSIGNED_BYTE, true, stride, 16);

        // Texture index
        gl.vertexAttribPointer(shader.aTextureIndex, 1, gl.FLOAT, false, stride, 20);
    }

for this function : gl.vertexAttribPointer(shader.aTextureIndex, 1, gl.FLOAT, false, stride, 20); parametet value for shader.aTextureIndex it is -1 so what i did is that i add a conditional check for shader.aTextureIndex hope solve that console info annoying alert seleccion_002

softmixt avatar May 03 '17 20:05 softmixt

Same issue on Ubuntu, on FF and Chrome. Both using phaser 2.7.7 and 2.7.10

Leprosy avatar May 30 '17 20:05 Leprosy

Getting same issue. Chrome, Ubuntu GNOME.

MariusAlch avatar Jul 06 '17 23:07 MariusAlch

Ubuntu 17.04, Chrome 59.0.3071.115. Still having this issue. Using phaser 2.8.5. Do exist a workaround to make it work properly?

kidasov avatar Sep 04 '17 16:09 kidasov

Ultimately someone needs to figure out why the aTextureIndex attribute value is missing.

If you just want to silence the error, you can overwrite PIXI.WebGLSpriteBatch#flush: https://gist.github.com/samme/c4d0928c94a345976ee022884b2bce58

samme avatar Sep 05 '17 20:09 samme

found something. assuming this is the latest non ce version of phaser: https://github.com/photonstorm/phaser/blob/master/v2/src/pixi/renderers/webgl/shaders/PixiShader.js#L102-L118

// get and store the attributes
this.aVertexPosition = gl.getAttribLocation(program, 'aVertexPosition');
this.aTextureCoord = gl.getAttribLocation(program, 'aTextureCoord');
this.colorAttribute = gl.getAttribLocation(program, 'aColor');

// Begin worst hack eva //

// WHY??? ONLY on my chrome pixel the line above returns -1 when using filters?
// maybe its something to do with the current state of the gl context.
// I'm convinced this is a bug in the chrome browser as there is NO reason why this should be returning -1 especially as it only manifests on my chrome pixel
// If theres any webGL people that know why could happen please help :)
if(this.colorAttribute === -1)
{
	 this.colorAttribute = 2;
}

this.attributes = [this.aVertexPosition, this.aTextureCoord, this.colorAttribute];

there is a comment about "line above returns -1", and in that repo the direct line above the comment is:

this.colorAttribute = gl.getAttribLocation(program, 'aColor');

comparing with current ce master: https://github.com/photonstorm/phaser-ce/blob/master/src/pixi/renderers/webgl/shaders/PixiShader.js#L191-L209

// get and store the attributes
this.aVertexPosition = gl.getAttribLocation(program, 'aVertexPosition');
this.aTextureCoord = gl.getAttribLocation(program, 'aTextureCoord');
this.colorAttribute = gl.getAttribLocation(program, 'aColor');
this.aTextureIndex = gl.getAttribLocation(program, 'aTextureIndex');


// Begin worst hack eva //

// WHY??? ONLY on my chrome pixel the line above returns -1 when using filters?
// maybe its something to do with the current state of the gl context.
// I'm convinced this is a bug in the chrome browser as there is NO reason why this should be returning -1 especially as it only manifests on my chrome pixel
// If theres any webGL people that know why could happen please help :)
if(this.colorAttribute === -1)
{
	 this.colorAttribute = 2;
}

this.attributes = [this.aVertexPosition, this.aTextureCoord, this.colorAttribute, this.aTextureIndex];

the direct line above would be:

this.aTextureIndex = gl.getAttribLocation(program, 'aTextureIndex');

but thats probably irrelevant, but interestingly on my linux chromium 61.0.3163.100 this.colorAttribute is always 2 (before the if), but this.aTextureIndex is always -1, hmmm...

after some trial and error, this seems to work for me:

diff --git a/src/pixi/renderers/webgl/shaders/PixiShader.js b/src/pixi/renderers/webgl/shaders/PixiShader.js
index 92197a766..7161ce7d3 100644
--- a/src/pixi/renderers/webgl/shaders/PixiShader.js
+++ b/src/pixi/renderers/webgl/shaders/PixiShader.js
@@ -206,10 +206,16 @@ PIXI.PixiShader.prototype.initDefaultShader = function () {
         this.colorAttribute = 2;
     }
 
-    this.attributes = [this.aVertexPosition, this.aTextureCoord, this.colorAttribute, this.aTextureIndex];
-
     // End worst hack eva //
 
+    // this might be related to above `this.colorAttribute === -1` bug?
+    if(this.aTextureIndex === -1)
+    {
+        this.aTextureIndex = 3;
+    }
+
+    this.attributes = [this.aVertexPosition, this.aTextureCoord, this.colorAttribute, this.aTextureIndex];
+
     // add those custom shaders!
     for (var key in this.uniforms)
     {

oskude avatar Oct 02 '17 18:10 oskude

I found discussion about same issue https://www.gamedev.net/forums/topic/524172-glgetattriblocation-and-a--1-return-value/ Looks like compiler optimizes shader code, and removes unused variable. If you look at shader code that used for NON-multi-textured case Vertex shader:

PIXI.PixiShader.defaultVertexSrc = [
    '// PixiShader Vertex Shader',
    '// With multi-texture rendering',
    'attribute vec2 aVertexPosition;',
    'attribute vec2 aTextureCoord;',
    'attribute vec4 aColor;',
    'attribute float aTextureIndex;',

    'uniform vec2 projectionVector;',
    'uniform vec2 offsetVector;',

    'varying vec2 vTextureCoord;',
    'varying vec4 vColor;',
    'varying float vTextureIndex;',

    'const vec2 center = vec2(-1.0, 1.0);',

    'void main(void) {',
    '   if (aTextureIndex > 0.0) gl_Position = vec4(0.0);',
    '   gl_Position = vec4( ((aVertexPosition + offsetVector) / projectionVector) + center , 0.0, 1.0);',
    '   vTextureCoord = aTextureCoord;',
    '   vColor = vec4(aColor.rgb * aColor.a, aColor.a);',
    '   vTextureIndex = aTextureIndex;',
    '}'
];

aTextureIndex attribute used only to assigns value to vTextureIndex and vTextureIndex is not used in fragment shader

this.fragmentSrc = [
            'precision lowp float;',
            'varying vec2 vTextureCoord;',
            'varying vec4 vColor;',
            'varying float vTextureIndex;',
            'uniform sampler2D uSampler;',
            'void main(void) {',
            '   gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor ;',
            '}'
        ];

This variable used only in multi-textured shader, and in non-multi-textured shader compiler just removes vTextureIndex and aTextureIndex to optimize code. Thats why

this.aTextureIndex = gl.getAttribLocation(program, 'aTextureIndex');

returns -1 We should make check as it already done for aColor attribute:

if(this.colorAttribute === -1)
    {
        this.colorAttribute = 2;
    }

right after that I suggest to add a check, same as patch in previous comment

if(this.aTextureIndex === -1)
    {
        this.aTextureIndex = 3;
    }

So, this is not "worst hack eva", this is workaround for compiler optimizations :D

makryl avatar Jan 03 '18 14:01 makryl

this.aTextureIndex = 3;

Why 3?

samme avatar Jan 03 '18 17:01 samme

shader has 4 attributes

    'attribute vec2 aVertexPosition;',
    'attribute vec2 aTextureCoord;',
    'attribute vec4 aColor;',
    'attribute float aTextureIndex;',

aVertexPosition - index 0 aTextureCoord - index 1 aColor - index 2 aTextureIndex - index 3 atrtributes should have this indexes usually

makryl avatar Jan 03 '18 18:01 makryl

actually we dont know what indexes compiler will set to attributes may be it would be cleaner way to check if attribute exists in flush method of WebGLSpriteBatch https://github.com/photonstorm/phaser-ce/blob/9192c3d085bd3a412cd40633fcdda5da59a2864a/src/pixi/renderers/webgl/utils/WebGLSpriteBatch.js#L584

gl.vertexAttribPointer(shader.aTextureIndex, 1, gl.FLOAT, false, stride, 20);

change to

if (shader.aTextureIndex !== -1) {
    gl.vertexAttribPointer(shader.aTextureIndex, 1, gl.FLOAT, false, stride, 20);
}

and may be it should be same for colorAttribute https://github.com/photonstorm/phaser-ce/blob/9192c3d085bd3a412cd40633fcdda5da59a2864a/src/pixi/renderers/webgl/utils/WebGLSpriteBatch.js#L581

aTextureIndex used also in WebGLFastSpriteBatch.start https://github.com/photonstorm/phaser-ce/blob/9192c3d085bd3a412cd40633fcdda5da59a2864a/src/pixi/renderers/webgl/utils/WebGLFastSpriteBatch.js#L442 but i dont know is it affected by this issue

makryl avatar Jan 03 '18 18:01 makryl