Wow, those are some quality suggestions. Thank you!Chief Blur Buster wrote:Fantastic! For me, I don't bother, I just use a fixed interval timer, but a badness trigger is interesting!
You could even do it on a per pixel basis. But that is waaaaay overkill.
Remember, for defeating the LCD voltage balancing (inversion) built into monitors, some monitors never burn in, others burn in slowly, and some do burn in fast. So you need a configurable modifier for phase switch velocity (e.g. 2x more frequent, 2x less frequent, etc), even in the worst case scenario, you dont need to phase swap more often than once a minute (so slow down your badness algoritm for those burnin-resistant monitors). So because of this, I never bothered doing an advanced guess of phase-swap necessity. But that can help make phase swaps less frequent!
Also, clever algorithms (e.g. two 50% opacity frames instead of two 100% opacity frames) can eliminate the "bright" flicker of phase swaps done via the repeat-frame technique. You can also for example mathematically calculate opacities, like if you need to flickerlessly convert frame-dark-dark into frame-dark-dark-dark (A 33% lengthening of a cycle), you instead do frame-33%frame-dark-dark. Basically a dark duplicate frame of one-third brightness.
The goal is make sure same number of photons are hitting human eyeballs per BFI cycle, even when the BFI cycle is varying (due to a phaseswap). That reduces flicker of random BFI shortenings/lengthenings.
In other words: Instead of trying to reduce frequency if phase swaps, why not simply make phase swaps invisible instead? Simpler math and easier for other code maintainers.
It maintains the same average number of photons hitting the eyeballs. This algorithm, IMHO, is more useful than complicated "badness" algorithms (useful as they are): Remember, keep it easy for other programmers.
Or keep both (badness algorithm AND phaseswap flicker reduction).
Also, try to detect missed frames (e.g. double vsync) and keep in phase with the monitor, not the game frame. Otherwise you're out of sync, burn in is occuring when you think it is not. Done via extrapolation from microsecond clock to guess correct phase to resync after accidentally missed frames (double VSYNC's, system freezes, etc). Basically, freeze interval divided by known rolling-average vsync interval (remember: when updating a vsync interval estimate, discard the outlier odd vsync-intervals to prevent mucking-up vsync guess). Dividing the freeze interval (get microsecond timestamp right after return of next blocking pageflip call) by the known vsync interval, returns a nearly-integer, and gives you a very good guess of what voltage inversion phase the monitor is currently in. Declare good number if near integer (within 0.1 of being an integer). Ignore if result doesn't look integer. If good, then if odd number, you are in sync, if even number, update your phase flag. (Don't need to phase swap at that instant). Other formulas may be better but, this is the easiest lowest common denominator for guessing the monitor inversion polarity after a long system freeze.
For the burnin prevention "phase-swaps":
My personal opinion in order of priority, IMHO, is:
- Phase swap on fixed integer trigger (user configurable) - maybe even just simple count of unbalanced frames
- Phase swap flicker elimination algorithm - simple opacity (alpha) formula
- Strong Phase resync logic after system freezes.
- More advanced phase swap algorithms (e.g. more complex badness factors).
I am very glad you confirm this solved the software BFI burn in problem.
Lowest interval is better for burn in prevention but it also causes (fake) micro stuttering. Sometimes it is not worth to trade because this may become annoying. But your suggestion to make swapping part seamless by showing frames with predetermined opacity is interesting and definitely needs a try.
The main goal of badness thing is actually dynamically finding an optimal timing for swap algorithm to kick in. Because a fixed interval might not provide the best result. But this might not be needed because of the opaque frames technique.
There is a interval cvar for controlling phase switch in seconds level. I mean if a person wants 2x more frequent then he can lower the interval to half. Is not this the same thing or I am missing a point? And my AUO B156HAN panel burns in a few seconds(60hz to 108hz overclocked. Maybe that is why but there should be support for people who use overclocked panels as well). Is it really enough to swap once each minute?Chief Blur Buster wrote:... you need a configurable modifier for phase switch velocity (e.g. 2x more frequent, 2x less frequent, etc), even in the worst case scenario, you dont need to phase swap more often than once a minute
For Badness,
n -> Percentage of ((+) Phase Normal - (+) Phase Black) out of total (+) Phase frame count. [Can be 0 to 100]
l -> Percentage of ((-) Phase Normal - (-) Phase Black) out of total (-) Phase frame count. [Can be 0 to 100]
What do you think about this table: (N and L are both negative but shown as positive)
The table consists output of "badness (decreases with brightness output, increases with phase unbalance)" function on several different values. Considering it is a logarithmic function, it can be seen from the table that 1, 0 is almost e^4 times better than 48, 0. And 0, 0 is better than 1, 0 by infinite times. Do you really think that the difference between 0,0 - 1,0 is infinite times bigger than the difference between 1,0 - 48,0?
Also is not it strange that 49-51 or 1-99 are equal to 50-50. Considering it decreases with brightness output and increases with phase unbalance, is this possible?
If I can make it seamless by using non opaque frames, badness will only need to depend on burn in inducing factor/phase unbalance. And that will make the job a lot easier.
Assuming that there will still be burn-in issue, function like this will be needed to avoid coding a lot of if statements. But priority of developing it will not be high because since the switching will be seamless, switching can occur much more frequently. So that automatic phase unbalance detection algorithm that is connected with this badness function will not need to kick in most of the time. Maybe if the opaque frame method make it 100% seamless, there won't be need for this function at all, just like you point out.
It is necessary to detect missed frames, but it is not easy I think. Using microsecond clock can only yield predicted results. And if this result is used, it can even break a working strobing frame sequence. I did not test this method before but it seems by your point that results are quite good. So I will also probably work on that.Chief Blur Buster wrote:Also, try to detect missed frames (e.g. double vsync) and keep in phase with the monitor, not the game frame. Otherwise you're out of sync, burn in is occuring when you think it is not. Done via extrapolation from microsecond clock to guess correct phase to resync after accidentally missed frames (double VSYNC's, system freezes, etc). Basically, freeze interval divided by known rolling-average vsync interval (remember: when updating a vsync interval estimate, discard the outlier odd vsync-intervals to prevent mucking-up vsync guess). Dividing the freeze interval (get microsecond timestamp right after return of next blocking pageflip call) by the known vsync interval, returns a nearly-integer, and gives you a very good guess of what voltage inversion phase the monitor is currently in. Declare good number if near integer (within 0.1 of being an integer). Ignore if result doesn't look integer. If good, then if odd number, you are in sync, if even number, update your phase flag. (Don't need to phase swap at that instant). Other formulas may be better but, this is the easiest lowest common denominator for guessing the monitor inversion polarity after a long system freeze.
I am also thinking that maybe there is some kind of public or private API in graphics driver for this? Instead of bothering with this, using a handy API would be much better.