I’m apologising in advance if this was asked before, but with recent changes my custom shader filters extended from BitmapFilter
stopped working. Previously, this was all I had to do to get it work:
var customFilter = new CustomFilter();
bitmap.filters = [customFilter];
Currently when I do it, the shader code is not executing, even __initShader()
method is not executing. I tried changing __numShaderPasses
but it didn’t make shader execute.
When I add shader to Bitmap
directly, i. e.:
bitmap.shader = new CustomShader();
the shader executes correctly, but it is a multipass shader and I need to pass information to shader about what pass it is currently in, which I cannot do this way (or haven’t found a way to do it yet). I was doing this in the __initShader()
method previously:
private override function __initShader (renderSession:RenderSession, pass:Int):Shader {
__customShader.data.pass.value = [pass];
return __customShader;
}
I had hoped that .shader
would provide a suitable workaround, but it seems we’ll have to do more. The way we used framebuffers before for shader filters was not suitable for mobile targets, and requires a rework.
I’ve opened an issue here: https://github.com/openfl/openfl/issues/1704
Well, using .shader
directly would be fine with me, but I’m not sure if multipass shaders work at all right now. I noticed that Shader
class has __numPasses
property, but changing this doesn’t seem to do anything (I didn’t investigated thoroughly how shaders are currently executed).
If shader executed __numPasses
and there was some way to know in shader code which pass we are currently in (for example I used uniform float uPass
, float due int to float conversion slowdown in some graphic cards), it would solve my problems. But I’m not too sure about framebuffer
object management in multipass scenario or what is a best way to do this to be mobile friendly.
Interesting, I did not know about int to float conversion being costly on some graphics cards
I think that might be what happened with our framebuffers. I heard that you need to not use a framebuffer again in the same frame, or ideally not even in the next frame, due to the way buffering works on the graphics card. We used the same framebuffer again heavily, which might be why mobile performance was shipwrecked
Well, yes and sadly, yes.
GPUs are optimised for floating point arithmetics, so almost everything integer based will probably be slower. I’m not sure if checking against integer in if
statement is slower than checking against float, but I used float just in case.
As far as I know, it’s generally not good idea to read and write to same buffer in one shader pass, but in some algorithms (like with what I’m dealing right now) you have no other choice, so I think there definitely should be an option to do that. It probably shouldn’t be used on standard “Flash” filters because of slowdowns on mobile, but for some special cases it is a reasonable tradeoff.
Just to be certain – is there currently any way at all to apply two passes of the same shader or two different shaders on one object? Second solution would probably work better for me anyway.
We need to re-evaluate support for framebuffer/GL shader-based filters. I think if we use a new framebuffer for each texture (instead of reusing the same framebuffers) it might solve some of the bottlenecks we hit before
2 Likes