SkImageFilters::Shader examples?

497 views
Skip to first unread message

Giuseppe

unread,
May 3, 2022, 1:35:49 PM5/3/22
to skia-discuss
Hello,

Is there an example somewhere about the SkImageFilters::Shader?

I need to build an image filter with a custom shader that applies a motion blur, so I'm looking for some examples, especially about the uniforms the image filter might pass to the shader, containing the surface content.

I already built an SkRuntimeShader which works correctly, but now I need an imageFilter, because I need to apply it to a paint object passed to the saveLayer function.

Thank you!

Brian Osman

unread,
May 3, 2022, 1:47:53 PM5/3/22
to skia-d...@googlegroups.com
There are two examples in: https://source.chromium.org/chromium/chromium/src/+/main:third_party/skia/gm/runtimeimagefilter.cpp

The second one (rtif_unsharp) is fairly minimal so might be the easiest to work from. The basic idea is that if you already have a runtime shader that does what you want, you can have the "content" that you're filtering be a `uniform shader` input to that shader. When you make the SkImageFilters::RuntimeShader call, you can give it a SkRuntimeShaderBuilder that already has any uniform values you want populated. You also specify two parallel arrays. One has the names of `uniform shader` variables in your SkSL. The other has `SkImageFilter` nodes that are bound to those child shaders when the filter is evaluated. Any child that's left as `nullptr` is bound to the "implicit" image filter input (eg, the layer contents, if you're applying the filter as part of a saveLayer call).

--
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/80565085-30b5-46ac-b412-1c1f0e872902n%40googlegroups.com.

Giuseppe

unread,
May 5, 2022, 2:58:09 AM5/5/22
to skia-discuss
Thanks! It's exactly what I needed

Mike Clifton

unread,
Apr 2, 2024, 11:02:22 PMApr 2
to skia-discuss
I'm having trouble getting this to work on Windows. On Mac, the example you point to does exactly what I expect - the first shader in runtimeimagefilter.cpp makes a little wavy effect on the implicit input.

But on Windows I can't get the shader to run at all with an implicit input. All the same code, but with the shader in effect, the result is just blank. I'm not seeing any errors, just doesn't seem to work.

Do you think I built Skia wrong for Windows, maybe missed a build option required to enable RuntimeShader to work? SkSl is working for me on Windows. I can get SkRuntimeShaderBuilder::makeShader to work, but it doesn't work with this implicit input (the layer contents).

John Stiles

unread,
Apr 3, 2024, 1:31:38 PMApr 3
to skia-d...@googlegroups.com
If you are building your Windows app with MSVC and building Skia with Clang, that has been known to cause issues. If so, go into your Skia GN args and add this line:

is_trivial_abi = false

I believe this isn't necessary on the latest versions of Skia, but so you might also try updating to the latest version of Skia.
If that doesn't help, you may need to step into Skia with the debugger and see if you can figure out where it is giving up.


Mike Clifton

unread,
Apr 4, 2024, 7:13:28 PMApr 4
to skia-discuss
Unfortunately, that didn't fix it. What I see happening is if I have a SkRuntimeShaderBuilder object and I call this:

myShaderBuilder->child("iContent") = nullptr;

My understanding is that that will set up the "implicit" image filter input. And it does appear to do that on Mac. I have iContent defined like this in my shader:

uniform shader iContent;

And I can sample pixels on Mac, it all works. But inside that child assignment on Windows, I end up with a runtime exception here:

BuilderChild& operator=(std::nullptr_t) {
            if (!fChild) {
                SkDEBUGFAIL("Assigning to missing child");
            } else {
                fOwner->fChildren[(size_t)fChild->index] = SkRuntimeEffect::ChildPtr{};
            }
            return *this;
        }

Unhandled exception at 0x00007FF749AE334C : An invalid parameter was passed to a function that considers invalid parameters fatal.

fChildren has a size of 0. I'll have to switch over and double-check, but on Mac I believe on entering this function, it has a size of 1. Has it already made room for the implicit image filter input on Mac, but not Windows?

John Stiles

unread,
Apr 5, 2024, 10:30:11 AMApr 5
to skia-d...@googlegroups.com
The children array is made right here, just a few lines away from the snippet you sent: https://source.chromium.org/chromium/chromium/src/+/main:third_party/skia/include/effects/SkRuntimeEffect.h;l=427;drc=49dd7ed24beca1c0fcaf2a6cf65e98c05e620359

    explicit SkRuntimeEffectBuilder(sk_sp<SkRuntimeEffect> effect)

            : fEffect(std::move(effect))

            , fUniforms(SkData::MakeZeroInitialized(fEffect->uniformSize()))

            , fChildren(fEffect->children().size()) {}


If it's zero-sized, it would have to mean that the effect that was passed-in doesn't actually use any child shaders.

You should be able to step into the initial construction of the SkRuntimeShaderBuilder and see this array getting constructed and sized. Let me know what you see.



Mike Clifton

unread,
Apr 5, 2024, 12:33:45 PMApr 5
to skia-discuss
I stripped things down to what I think is the bare minimum:

auto result = SkRuntimeEffect::MakeForShader(SkString("\
uniform shader iContent;\
vec4 main(vec2 coord)\
{\
return iContent.eval(coord) * sin(coord.x * 0.1);\
}\
"));
printf("Children size: %d\n", result.effect->children().size());

On Mac, this prints out a value of 1. On Windows, 13875748 !!! But the shader claims to compile here on Windows with no errors, just a messed up children array. Shaders do work on my Windows build, just not if you try to use a shader as a uniform (that implicit input).

Next I built Skia in debug mode and stepped my way through to this function: SkRuntimeEffect::MakeInternal. In there, it sets up a child called "iContent" as I would expect. As I step back out, everything looks fine until I get back out of Skia and into my program and the effect object somehow appears to be corrupted. At this point I'm suspecting some build issue, but everything else about Skia is working just fine. The version of C++ or something? Mysterious...

John Stiles

unread,
Apr 5, 2024, 12:37:31 PMApr 5
to skia-d...@googlegroups.com
This does sound like a build issue. If you are building Skia with one set of build flags, but your MSVC build has different flags, things will be haywire. (i.e. if Skia is built in release, but your MSVC build has Skia set up with debug flags.)


Mike Clifton

unread,
Apr 5, 2024, 1:37:39 PMApr 5
to skia-discuss
Good point. Where do I find all the flags Skia is using once I've set it up and built it? (So that I can try to reproduce them in MSVC.)

By the way, thanks for your help in figuring this out. We're not quite there yet, but I really appreciate it.

John Stiles

unread,
Apr 5, 2024, 4:03:46 PMApr 5
to skia-d...@googlegroups.com

Mike Clifton

unread,
Apr 5, 2024, 7:35:33 PMApr 5
to skia-discuss
Everything in that file is commented out, I suppose its default state. Do you think I should turn something on? The comments seem to indicate that it should all be handled when building with MSVC. (I believe Skia is built with MSVC by default. I have not configured clang on Windows. I see that it is recommended, but I have not taken that route, and everything else in Skia seems to be working great.)

Does something look weird in my Skia build configuration? (I've tried debug both true and false)

bin/gn gen out/Debug --args='is_debug=true is_official_build=false is_component_build=true skia_use_system_expat=false skia_use_system_libjpeg_turbo=false skia_use_system_libpng=false skia_use_system_libwebp=false skia_use_system_zlib=false skia_use_system_icu=false skia_use_system_harfbuzz=false skia_use_gl=true is_trivial_abi=false'

Mike Clifton

unread,
Apr 8, 2024, 4:07:47 PMApr 8
to skia-discuss
This is so weird. I tried a completely different approach: Instead of building Skia manually, I tried getting it from vcpkg. I get the same problem, where the children array looks good until I step out of Skia and back into my application, at which point it goes haywire.

But...there's some good news! I tried building my application in Release mode, with a Release build of Skia, and it all works now!

In my Debug app, I'm still getting this shader failure, whether I'm using a Debug or Release build of Skia. I guess maybe I'm not defining something I should in my app, but I can't figure out what it might be. SK_DEBUG is defined - what else?

It's really good that this is working in a Release build, but I'll need to debug as well. Any ideas what else I need to set up for my debug build of my app? I've been using a lot of Skia features for a long time, and it's just now this implicit shader input thing that is failing. But my guess now is my app is somehow slightly misconfigured in its Debug build.

John Stiles

unread,
Apr 9, 2024, 1:13:56 PMApr 9
to skia-d...@googlegroups.com
Sorry to be the bearer of bad news, but I don't think we can help further with this issue. We do build and test on MSVC, and the tests there are all passing in both Debug and Release configurations: https://status.skia.org/?filter=Search&repo=skia&search=%5ETest-Win2019

So the issue seems to be somewhere in how your program is configured in Debug mode. It sounds like we have covered all of the reasons that I know about which can cause issues here (SK_DEBUG out of sync, [[clang::trivial_abi]]) but you've managed to hit a snag that is unfamiliar to me :(

If it were me, I would set up a new empty app from scratch with nothing in it and try to get that working. If you are up for it, I'd also suggest following the documentation steps about using clang-cl. https://skia.org/docs/user/build/#windows 

This is because Skia is significantly faster when built with Clang; MSVC builds lack SSE/AVX optimizations. Also, it's the configuration all of us on the team are using/testing when on Windows, and it's how Skia is built when it's used as part of Windows applications at Google. Using MSVC is the road less traveled, for sure. 

If you manage to narrow down the issue any further, please let us know. I'd be happy to upstream a fix if it turns out to be an MSVC-specific issue that our tests weren't catching.



Mike Clifton

unread,
Apr 9, 2024, 3:04:09 PMApr 9
to skia-discuss
Ok, fair enough. If I figure anything out I'll update the group.

In the short term, I was able to build Skia on Windows using clang, but the same problem persists. Maybe that's good news, in a way? At least it's not a compiler bug?'

But the clang instructions on this page appear to be incomplete:  https://skia.org/docs/user/build/#windows Besides this argument to bin/gn gen:

clang_win="C:\Program Files\LLVM"

I also found that you need to specify this (or whatever your specific version might be):

clang_win_version="17.0.1"

You also need is_trivial_abi=false, otherwise not just the shader, but lots of Skia stuff was failing.

In fact, I'd love to see a recommended set of arguments to bin/gn gen. I have something building, but I'm not too confident that I'm setting it up correctly. But I'll keep experimenting.

John Stiles

unread,
Apr 10, 2024, 2:33:15 PMApr 10
to skia-discuss
Thanks for the feedback!  I've added a note about is_trivial_abi to the docs.

We found that there is already existing code which auto-detects the LLVM version and so manually setting clang_win_version shouldn't be necessary, but the auto-detection code assumed a particular version-number format (12.34.56) and wouldn't detect un-dotted versions like 12. Greg is adding a fix here:  http://review.skia.org/838737  If this fix doesn't work for you, please let us know.

In general I think we already document most of the critical gn arguments that users should actually use. Most gn arguments can be ignored unless you are a Skia developer, except for a few critical ones like enabling different GPU backends. If you notice another gap in the docs, let me know and I will shore it up.
Reply all
Reply to author
Forward
0 new messages