SKSL Program too large error

412 views
Skip to first unread message

Christian Falch

unread,
Dec 30, 2021, 4:53:55 AM12/30/21
to skia-discuss
Hi!

I'm playing with the SKSL shader language to see if I can find some limitations that we need to document for our React Native Skia library (https://github.com/Shopify/react-native-skia).

After testing out some more complex shader examples (specifically using signed distance field functions to build 3d models with shadows and lightning), I'm getting a "Program too large" error. This seems (after looking at the code) to happen after flattening (inlining?) the SKSL code and measuring its size which is reported to be over the limit. 

The error seems to be thrown in the file src/sksl/analysis/SkSLCheckProgramUnrolledSize.cpp

I have created an example here showing the problem:


Commenting out line 66 makes it work, effectively removing an extra round of calls to the GetDist function.

I have tried marking functions with the noinline directive without any success.

Any ideas why this could be happening?

Christian

Christian Falch

unread,
Dec 30, 2021, 4:59:13 AM12/30/21
to skia-discuss
To be more specific on how to reproduce: comment in line 66 to see the error :)

Brian Salomon

unread,
Dec 30, 2021, 11:44:56 AM12/30/21
to skia-d...@googlegroups.com
Hi Christian,

We've modeled the initial version of SkSL runtime effects on GLSL ES 1.00 (https://www.khronos.org/files/opengles_shading_language.pdf) for maximum compatibility with GPUs. My understanding of the size limits imposed by the GLSL shading language spec is that they are non-specific. To be conforming means to be able to run all the shaders in the OpenGL ES conformance tests but there is no specific maximum size or even clear definition of what the size of a program is. So what programs will bump up against a limit will vary GPU to GPU.

Meanwhile, our CPU implementation flattens the whole program to a single basic block (eliminates branches, function calls) and we wanted to have some way of limiting the size of the block. So we came up with a somewhat arbitrary way of defining program size by adding up statements and expressions and imposed a limit in the code you discovered.

I believe we intend for our limit to be sufficient to run the shaders in the GLES conformance tests. But because in the GPU backend the user SkSL gets converted to GLSL and the GLSL spec is non-specific on this issue it's not guaranteed that anything that makes it past our limit will actually run on a given GPU.

Hopefully when some folks who know more about this are back at work after the holiday break they can fill in some details here as my knowledge is somewhat cursory.

Best,
Brian


--
You received this message because you are subscribed to the Google Groups "skia-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to skia-discuss...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/skia-discuss/2eeced30-ea2f-41b1-8f06-6095e7b23666n%40googlegroups.com.


--

Brian Salomon | Office Hours: go/bsalomon-office | bsal...@google.com

Christian Falch

unread,
Jan 2, 2022, 10:17:51 AM1/2/22
to skia-discuss
Thanks so much for the info, Brian!

From your explanation, it seems like the CPU implementation flattening is also done when running the program on a GPU-based backend? 

I've heard about these limitations in OpenGL - they're probably done because it is hard to analyze these things correctly upfront?

Would be interesting to learn more about how Skia limits these things and if it is possible to write bigger programs than today - because this is super powerful!

Christian

Brian Osman

unread,
Jan 4, 2022, 9:08:24 AM1/4/22
to skia-d...@googlegroups.com
Thanks for the questions! Brian's explanation is accurate, but a couple more details: Skia itself doesn't actually do the flattening when running on the GPU backend (we still emit GLSL with loops present, for example), but we do still check what the total size would be if they were unrolled, inlined, etc... The GLSL ES 1.0 spec is very carefully written such that any valid program could be completely flattened with no branching - this is intentional, because older GPUs worked that way. As a result, some older (or even not-so-old but low-power) GPUs will use the same execution model as our CPU backend. Vectorized execution (as is done on a GPU shader core) requires a fair bit of care once divergent branching can happen, and the logic to analyze and deal with that is much simpler if you can flatten things out (and just execute non-taken paths with no side effects).

It's absolutely possible to write bigger programs, and if we knew we were targeting a GPU that supported ES3+ (for example), we would simply skip the "how big would this program be if unrolled" check. (We have an option to do this, actually, that we use for testing purposes - we don't expose it, because we still want to maintain the invariant that any program we accept is at least theoretically possible to execute on any GPU, and on our CPU backend).

Eventually though - yes, people are going to keep asking for ES3+ features, and we're still figuring out how to handle that from an API perspective.

Lastly: The easiest way to tune that linked shader is to just turn down the MAX_STEPS (even cutting it in half is sufficient to allow the shadows, but I turned it down quite a bit beyond that with no real visual impact).

Christian Falch

unread,
Jan 5, 2022, 11:41:48 AM1/5/22
to skia-discuss
Hi Brian,

Thanks for the feedback, it explains what we're seeing and I also got it working by reducing MAX_STEPS :) :) 

This was basically a test I did to see what kind of limitations we can expect with the shaders, so this makes a lot of sense to us!

Christian

Reply all
Reply to author
Forward
0 new messages