Minor blitshader bug

Started by AeroShark333, April 23, 2020, 12:20:58 AM

Previous topic - Next topic

AeroShark333

Hello,

I believe I've found a minor blitshader bug, it's mostly about the blits that follow (whether these use another blitshader or no blitshader) after you are done using the blitshader in a single draw call.
I do follow the instructions I've read elsewhere on this forums:
Quote from: EgonOlsen on March 09, 2016, 08:49:22 AM
It should work. At least I see no reason, why it shouldn't. Just make sure not to do this:


fb.setBlittingShader(...);
fb.blit(...);
fb.setBlittingShader(null);


That doesn't work, because blits are buffered but the shader isn't. If you need to reset the shader in the process, make sure to execute the blits before. You can force this by blitting a dummy blit from some other texture. Like:


fb.setBlittingShader(...);
fb.blit(...);
fb.blit(...); // <- Dummy-blit (1x1 transparent pixel with some other texture or something)
fb.setBlittingShader(null);


Now in my case, I use:
fb.setBlittingShader(shader1);
fb.blit(...);
fb.blit(...); // <- Dummy-blit (1x1 transparent pixel with some other texture or something)
fb.setBlittingShader(null);
fb.setBlittingShader(shader1);
fb.blit(...);
fb.blit(...); // <- Dummy-blit (1x1 transparent pixel with some other texture or something)
fb.setBlittingShader(null);
fb.setBlittingShader(shader2);
fb.blit(...);
fb.blit(...); // <- Dummy-blit (1x1 transparent pixel with some other texture or something)
fb.setBlittingShader(null);


Every blit using the first shader seems to go fine but once another shader or no shader is used, blitting is kinda broken (not on all devices but most).
- When you blit (after having used the first shader) with no shader, something that doesn't match the original texture you're trying to blit is shown.
- When you blit (after having used the first shader) with another shader, either nothing is shown or the correct result is shown. (50/50 depending on device)
- When you blit (after having used the first shader) with no/another shader AND you used fb.display() before these blits, then the correct result will be shown in all cases.

So it seems that now fb.display() is required if
- you want to keep blitting normally after the first blits with shader
- you want to use another blitshader to blit with
Though, I'm not sure if fb.display() is intended to be used like that

Cheers,
Abiram

MichaelJPCT

what about flush() or sync() ?

EgonOlsen

#2
I'm not sure about this. Actually, I don't even understand my comment from back then anymore. Because, if you set a new blitting shader, buffered blits are executed anyway. I don't see why you should still need this dummy texture hack. fb.display() executes stored blits as well, but it also does something more. It shouldn't really hurt to use it, but I fail to see why it helps in this case. I've uploaded a new jar that adds a new method to FrameBuffer called flushBlittingPipeline() which does what it says. Maybe you can try to use that in addition or in replacement of the dummy texture blit and see if that helps.

As MichealJPCT suggested, flush() or sync() might be worth a try. There's an undocumented config switch to enable those for blitting. Set Config.blittingMode  to 9 for a flush(), to 10 for a sync() and to 11 for both and see, if that helps. I doubt it, but there has to be a reason why I put those in there...

Edit: looking at the code, these config values only enable sync() and flush() BEFORE the actual blitting. If you want to execute them afterwards as well, just add a 4 to these values.

AeroShark333

Quote from: EgonOlsen on April 23, 2020, 09:21:46 AM
I'm not sure about this. Actually, I don't even understand my comment from back then anymore. Because, if you set a new blitting shader, buffered blits are executed anyway. I don't see why you should still need this dummy texture hack. fb.display() executes stored blits as well, but it also does something more. It shouldn't really hurt to use it, but I fail to see why it helps in this case. I've uploaded a new jar that adds a new method to FrameBuffer called flushBlittingPipeline() which does what it says. Maybe you can try to use that in addition or in replacement of the dummy texture blit and see if that helps.

As MichealJPCT suggested, flush() or sync() might be worth a try. There's an undocumented config switch to enable those for blitting. Set Config.blittingMode  to 9 for a flush(), to 10 for a sync() and to 11 for both and see, if that helps. I doubt it, but there has to be a reason why I put those in there...

Edit: looking at the code, these config values only enable sync() and flush() BEFORE the actual blitting. If you want to execute them afterwards as well, just add a 4 to these values.
I first downloaded the jar from the jPCT downloads page but I guess that wasn't the right new jar...
So I used that beta link later (from another thread): http://jpct.de/download/beta/jpct_ae.jar which did have the FrameBuffer#flushBlittingPipeline()
I'm not sure if the dummy blit helps anything but I believe it did help to push the shadered blits. I guess it doesn't do any harm anyway but yeah, not ideal I suppose.

Anyway, back to the multiple (shadered) blits:
Using FrameBuffer#flushBlittingPipeline() after the having blitted using the first shader doesn't work
I tried to use FrameBuffer#sync() before too but it didn't work. I haven't tried FrameBuffer#flush() before yet but it also didn't really work.
The blittingMode's 9, 10, 11, 13, 14 and 15 all didn't work.
So far only using FrameBuffer#display() seems to work...
But I believe the idea of having multiple FrameBuffer#display() calls in one draw call isn't how it's intended to be..?

EgonOlsen

Opps, yes...I forgot the link. But you found it anyway... ;)

You can call display() multiple times per frame, but it will increase the internal frame counter (not a big deal though) and it's mainly done for rendering into textures. But I still don't see why this helps while flushBlittingPipeline doesn't. They aren't that different. I'll move over some additional stuff from display() into flush... for you to try out. I'll report back with a link.

EgonOlsen

Ok, I've updated https://jpct.de/download/beta/jpct_ae.jar. If that still doesn't have the same effect as display(), then I can do one more thing to it. Please let me know how it works out.

AeroShark333

Quote from: EgonOlsen on April 23, 2020, 06:14:46 PM
Ok, I've updated https://jpct.de/download/beta/jpct_ae.jar. If that still doesn't have the same effect as display(), then I can do one more thing to it. Please let me know how it works out.
FrameBuffer#flushBlittingPipeline() seems to work now without any additional FrameBuffer#display() calls (except for the final call at the end of the draw call).

EgonOlsen

Ok...it remains a mystery to me. All I've added is setting a flag that reenables some vertex buffers that shouldn't have been disabled in the first place. Well...as long as it works now.

AeroShark333

Quote from: EgonOlsen on April 23, 2020, 07:48:22 PM
Ok...it remains a mystery to me. All I've added is setting a flag that reenables some vertex buffers that shouldn't have been disabled in the first place. Well...as long as it works now.
Yeah, I guess this solution will do :)
I'll see if I can get rid of these transparant blits as well

Thank you both for helping