[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Public WebGL] Making GLSL uniform array behavior more consistant






On Mon, Nov 12, 2012 at 12:40 PM, Mark Callow <callow.mark@artspark.co.jp> wrote:

On 2012/11/10 12:06, Gregg Tavares (社用) wrote:
An issue has come up with large uniform arrays.

You can make a shader like this

uniform vec4 array[1000000];  // too many uniforms

void main() {
  gl_FragColor = array[1];
}

This will work on some drivers and fail on others. My reading of the spec says it's supposed to work. The ES spec 2.10.4 page 37

If one or more elements of an array are active, GetActiveUniform will return
the name of the array in name, subject to the restrictions listed above. The type of
the array is returned in type. The size parameter contains the highest array element
index used, plus one. The compiler or linker determines the highest index used.

There will be only one active uniform reported by the GL per uniform array.

This same language is in the OpenGL 2.1 (not ES) spec. haven't checked the OpenGL 4.3 spec.

Some people interpret that to mean it's implementation dependent.
Interpret what (the purple text presumably) to mean what is implementation dependent?

Please note that the language you are quoting says absolutely nothing about how much memory is allocated for the array. It is telling you what getActiveUniform must report about the array. The only implementation-dependent part I see is whether "highest index used" is determined by the compiler or linker. In the example you give, the compiler is as equally capable as the linker of determining that the highest index used is 1.



For WebGL I feel we should be more strict we should either fail all such shaders (shaders that declare more uniforms than could possibly fit even if not using every element) or we should require all such shaders to work.
Modulo buggy drivers, all such shaders should work. Are you aware of drivers that would fail to compile this example?

I know of no desktop drivers that correctly report the array size as 2. I don't have easy access to mobile GPUs to see what they do.

ANGLE reports a size of 442 on my machine
Linux NVidia and Mac NVidia reports a size of 1000000

Ken points out figuring out the highest index is non trivial as in

uniform vec4 array[1000000];
int foo(a, b) {
   return int(a / b);
}
void main() {
   float a = 4;
   float b = 2;
   g_FragColor = array[foo(a,b)];
}

Etc...

Here's a test you can run locally
https://www.khronos.org/registry/webgl/sdk/tests/conformance/uniforms/gl-uniform-unused-array-elements-get-truncated.html

It queries MAX_FRAGMENT_UNIFORM_VECTORS, make an array double that and uses element #5 so according to the spec the size returned by getActiveUniform should be 6

Anyway, that comes back to the original question. To get consistent behavior we have 2 options. 

1) Require validators to compute the correct spec compliant size

2) Don't truncate arrays in WebGL and require the validator to fail a shader that doesn't pack according to the GLSL spec.

2 is far easier to implement since since it only requires compile time constants to figure out.


Regards

    -Mark

--
注意:この電子メールには、株式会社エイチアイの機密情報が含まれている場合が有ります。正式なメール受信者では無い場合はメール複製、 再配信または情報の使用を固く禁じております。エラー、手違いでこのメールを受け取られましたら削除を行い配信者にご連絡をお願いいたし ます.

NOTE: This electronic mail message may contain confidential and privileged information from HI Corporation. If you are not the intended recipient, any disclosure, photocopying, distribution or use of the contents of the received information is prohibited. If you have received this e-mail in error, please notify the sender immediately and permanently delete this message and all related copies.