Das Problem ist doch ganz einfach, aber die Lösung scheint echt schwer zu implementieren zu sein.
0000 Engine: Ich habe einen Frame fertig.
0000 Treiber: @GPU1: hast du Zeit?
0000 GPU1: Klaro.
0000 Treiber: @Engine: OK, gib her das Ding.
0000 Treiber: @GPU1: Dann mach mal Frame #1.
0000 GPU1: Okidoki.
0002 Engine: Ich habe einen neuen Frame.
0002 Treiber: @GPU1: Hast du Zeit?
0002 GPU1: Du spinnst wohl? Hast mir doch gerade erst etwas gegeben.
0002 Treiber: @GPU2: Hast du Zeit?
0002 GPU2: Jup
0002 Treiber: @Engine: Dann lass mal sehen was du hast.
0002 Treiber: @GPU2: Frame #2 ist deine Aufgabe. Bitteschön.
0002 GPU2: OK, bin beschäftigt.
0004 Engine: Frame #3 ist bereit.
0004 Treiber: @GPU1: Entschuldige bitte die Störung, aber ich muss nochmal fragen. Hast du Zeit?
0004 GPU1: Habe ich dir schon ein Ergebnis geschickt, du Depp?
0004 Treiber: Hmm, *grübel* ich glaube nicht.
0004 Treiber: @GPU2: Hast du Zeit?
0004 GPU2: Hast du Alzheimer oder was? Deckst mich hier gerade erst mit massig Arbeit ein und fragst dann blöde ob ich Zeit habe? Nein!
0004 Treiber: Pffff... @Engine: Keine Zeit.
0004 Engine: Was? vorhin ging's doch so schnell, was trödelst du da rum?
0005 Engine: Na, kanns losgehen?
0005 Treiber: Ne.
0006 Engine: Immer noch nicht?
0006 Treiber: Nerf' nicht, sonst mache ich einen BSOD!
0006 Engine: Schon gut, ich warte auf dein Kommando.
0010 Engine: Dumdidum... *gähn*.
0020 GPU1: *schwitz* ich bin fertig.
0020 Treiber: @GPU1: Na endlich.
0020 Treiber: @Monitor: Anzeigen, aber zackig.
0020 Monitor: Ich mache alle 16,6ms ein neues Bild, das hast du so gewollt. 60Hz... Naja mir egal, wird erledigt.
0020 Treiber: @Engine: Ich habe wieder Zeit für dich. Gib deinen Frame #3 her.
0020 Engine: Die Spielzeit in dem Frame war 0004. Das gibt einen heftigen Ruckler. An mir lag's nicht, falls der Spieler fragt!
0020 Treiber: Was interessiert mich der Spieler? @GPU1: Frame #3 für dich.
0020 GPU1: OK.
0022 Engine: Ich habe Frame #4 für euch Pappnasen.
0022 GPU2: Bin fertig *freu*.
0022 Treiber: @GPU2: Ach, das ging ja fix. nur 20ms genau wie GPU1. *kurz-grübel..* (was könnte ich mit dieser Information machen? - Ach egal.)
0022 Treiber: @Monitor: Ein neues Bild, bitte anzeigen.
0022 Monitor: Ich frag' nicht, was du geraucht hast. Du magst Tearing? OK.
0022 Treiber: @Engine: Gib' deinen Frame her, GPU2 kühlt schon ab.
0022 Treiber: @GPU2: Frame #4 für dich.
0022 GPU2: Ihr seid völlig lernresistent, was? Naja mir egal. OK.
0024 Engine: Frame #5 ist fertig.
0024 Treiber: Lass mich in Ruhe.
...
Das habe ich vorhin mitgeschnmitten mit der Radeon to IRC Bridge. ;-)
Wie wir sehen, herrscht überall Gleichgültigkeit. Keiner interessiert sich für den Anderen und deswegen kommen diese Ruckler zustande.
Würde der Treiber die Aufgabe nicht sofort an die GPU leiten, könnte er die Engine zwingen zu warten. Dann würden weniger Ruckler auftreten. Natürlich muss diese Wartezeit dynamisch angepasst werden, denn nicht jeder Frame kann in der selben Zeit berechnet werden. Der Einfachheit halber mal idealisiert: Wenn sich also herausstellt, dass eine GPU für den Frame 20ms benötigt, so kann der Treiber der Engine alle 10ms einen neuen Frame abnehmen und alternierend an die GPUs verteilen. Allen wäre geholfen und Mikroruckler würden nicht mehr auftreten.
Aber wo kämen wir denn da hin...