GUI-Thread mit OpenGL/DirectX - überhaupt möglich?
-
cooky451 schrieb:
Eine denkbare Umsetzung wäre z.B. noch, dass man ein Textur-Handle hat das einfach vom 3D-Render-Thread ausgetauscht wird. Quasi ein doppelter double-buffer.
Ja klar so. Das "Textur-Handle" muss der Presenter-Thread aber trotzdem nochmal rendern.
-
hustbaer schrieb:
Je nach verwendeter API ist es durchaus möglich sowas zu machen. ...
Mit Trennung müsstest du die Szene von einem eigenen Thread in eine extra Render-Texture rendern lassen.welche api kann das?
opengl kann nur ein context haben der an den thread gebunden ist afaik, ein direct3d9 device kann eh nur von einem thread mit render calls versorgt werden, ist ja eine state machine die nichts von threads weiss und zwischen zwei devices kann man eigentlich keine resourcen teilen. d3d10/11 haben zwar ein deferred context, aber das zeichnet nur auf, es muss dennoch im main-thread abgespielt werden.ist das eine spezielle opengl extension die du meinst?
-
dot schrieb:
Mal eine rein prinzipielle Überlegung: Wenn du 15 fps hast und die Grafikkarte nicht voll ausgelastet ist, dann ist dein Code verbesserungswürdig. Wenn du 15 fps hast und deine Grafikkarte voll ausgelastet ist, wirst du es auch nicht schaffen, dein GUI schneller zu rendern...
Doch, klar. In dem man der GUI eine höhere Priorität zuweißt. Da diese wesentlich leichter zu zeichnen ist, könnte es sein dass man 60 GUI-FPS bekommt wenn man nur einen einzigen 3D-Frame/s opfert.
-
rapso schrieb:
hustbaer schrieb:
Je nach verwendeter API ist es durchaus möglich sowas zu machen. ...
Mit Trennung müsstest du die Szene von einem eigenen Thread in eine extra Render-Texture rendern lassen.welche api kann das?
Jede die Rendertargets zwischen Devices/Kontexten/... sharen kann sollte das können.
Bei OpenGL sollte das mit
wglShareLists
gehen.Bei D3D9Ex/D3D10 über den
pSharedHandle
Parameter der diversen CreateXxx Funktionen: http://msdn.microsoft.com/en-us/library/bb219800(v=vs.85).aspx#Sharing_ResourcesIch hab's selbst noch nie probiert, aber ich sehe keinen Grund warum es nicht funktionieren sollte.
-
hustbaer schrieb:
rapso schrieb:
hustbaer schrieb:
Je nach verwendeter API ist es durchaus möglich sowas zu machen. ...
Mit Trennung müsstest du die Szene von einem eigenen Thread in eine extra Render-Texture rendern lassen.welche api kann das?
Jede die Rendertargets zwischen Devices/Kontexten/... sharen kann sollte das können.
Bei OpenGL sollte das mit
wglShareLists
gehen.Bei D3D9Ex/D3D10 über den
pSharedHandle
Parameter der diversen CreateXxx Funktionen: http://msdn.microsoft.com/en-us/library/bb219800(v=vs.85).aspx#Sharing_ResourcesIch hab's selbst noch nie probiert, aber ich sehe keinen Grund warum es nicht funktionieren sollte.
diese entwicklung ist komplett an mir vorbeigegangen, danke, wuste ich echt nicht. dann waere es interesant zu sehen wie dein vorschlag in der wirklichkeit laeuft, ob D3D bzw der treiber das rendering von zwei devices wirklich interleaven wuerde, oder serialisiert.
-
Bei wglCreateContextAttribsARB kann man soweit ich weiß auch gleich nen zweiten Context angeben mit dem man Objekte shared.
ob D3D bzw der treiber das rendering von zwei devices wirklich interleaven wuerde
Jo, das wäre sicherlich ein Problem, wenn der erst mal in Ruhe alles zu Ende zeichnet und dann ruft "nächstes Bild bitte!".
-
Ich hab' rapso was über 3D APIs erzählen können.
Den Tag mal ich mir rot im Kalender an, und den Kalender lass ich mir in Epoxy eingiessen damit er ewig hältJo, wie das dann flutscht wäre interessant.
Ich vermute aber mal ähnlich gut oder schlecht wie zwei Windowd D3D (bzw. OpenGL) Programme die gleichzeitig mit "presentation interval immediate" Dinge rendern.
Und das zumindest könnte man ja halbwegs einfach ausprobieren.
-
Ehm, nur mal so, ein ganz anderes Problem, das mir gerade aufgefallen ist, als ich nur mal den Message-Loop vom Rest trennen wollte: Die HDCs und HGLRCs scheinen nicht Thread-Safe zu sein. Heißt für mich, dass man unter Windows nur im Window-Thread rendern kann. Was relativ bescheuert ist, aber da lässt sich wohl kaum etwas gegen unternehmen. Und mir scheint auch, dass es da einige Fallstricke gibt. Man kann z.B. nicht einfach mal einen memory-mapped Pointer an glTexImage2D geben, weil das dann blocken könnte. Vielleicht hat hier ja jemand eine Idee, wie man das lösen könnte.
-
Was genau meinst du mit "nicht threadsafe", wie äußert sich das und woher kommen die betreffenden HDCs und HGRCs?
-
Na ja, dass man Get/Peek-Message nur in dem Thread benutzen kann, für den auch das Fenster erstellt wurde, sollte ja klar sein. Und das HWND kann man scheinbar auch nur in dem Thread benutzen, wenn man GetDC aufruft. Diesen DC braucht man ja wieder für wglCreateContext - dessen Rückgabewert man auch nicht einfach in einem anderen Thread benutzen darf. (Und so zieht sich das auch weiter wenn man einen modernen Kontext erstellt.) - Oder gibt es da irgendwo ein "Schlupfloch"?
-
cooky451 schrieb:
Und das HWND kann man scheinbar auch nur in dem Thread benutzen, wenn man GetDC aufruft.
Das wär mir neu.
cooky451 schrieb:
[...] dessen Rückgabewert man auch nicht einfach in einem anderen Thread benutzen darf.
Das wär mir ebenfalls neu.
Du kannst ein HDC nur in einem Thread gleichzeitig benutzen und ein GL Context kann auch zu jedem Zeitpunkt nur in einem Thread aktiv sein. Aber ansonsten...
-
Ah, sehr schön. Gerade probiert, und es funktioniert perfekt, das HWND kann man also auch in einem anderen Thread benutzen. Danke!
Eine kleine Frage noch am Rande*: Vorher hat das Rendern einfach gestoppt, sobald ich das Fenster vergrößert/kleinert habe. Das ist jetzt nicht mehr so, was grundsätzlich positiv ist. Aber dafür flackert es, weil das beim verkleinern scheinbar von Windows einmal komplett mit weiß überschrieben wird. Kann man das irgendwie verhindern indem man WM_PAINT abfängt oder sowas?
* Sollte wohl eher in's WinAPI-Forum, aber wo wir schon mal hier sind..
-
Evtl. einfach mal den Background Brush auf 0 setzen? Ansonten evtl. WM_ERASEBKGND abfangen und in WM_PAINT ValidateRect() aufrufen, sofern du das Fenster schon an anderer Stelle periodisch neu bemalst.
-
dot schrieb:
Evtl. einfach mal den Background Brush auf 0 setzen? Ansonten evtl. WM_ERASEBKGND abfangen
This.
Hier noch was interessantes dazu:
http://stackoverflow.com/a/1750301/1743172
-
Scorcher24 schrieb:
dot schrieb:
Evtl. einfach mal den Background Brush auf 0 setzen? Ansonten evtl. WM_ERASEBKGND abfangen
This.
Hier noch was interessantes dazu:
http://stackoverflow.com/a/1750301/1743172Das mit CS_OWNDC ist afaik allerdings nicht korrekt. Ist aber auch schon ein ganzes Weilchen her, dass ich mich damit mal beschäftigt hab...
-
dot schrieb:
Scorcher24 schrieb:
dot schrieb:
Evtl. einfach mal den Background Brush auf 0 setzen? Ansonten evtl. WM_ERASEBKGND abfangen
This.
Hier noch was interessantes dazu:
http://stackoverflow.com/a/1750301/1743172Das mit CS_OWNDC ist afaik allerdings nicht korrekt. Ist aber auch schon ein ganzes Weilchen her, dass ich mich damit mal beschäftigt hab...
Soweit ich weiss schon und im OpenGL Wiki ist es auch noch so drin:
http://www.opengl.org/wiki/Platform_specifics:_Windows#What_should_I_do_before_the_window_is_created.3FWikis sind nicht das Ende alles Wissens, aber ich vertraue einfach mal auf dieses.
-
CS_OWNDC sollte afaik generell schon seit langem nichtmehr benutzt werden. Es tut afaik nichts anderes, als sicherzustellen, dass das System dir für ein entsprechendes Fenster immer den selben DC liefert. Die saubere Lösung wäre imo, den DC einfach nicht zu Releasen, so lange man ihn noch braucht, anstatt jedesmal einen neuen DC anzufordern und diesen Hack im Betriebssystem zu nutzen, um immer den gleichen DC zu bekommen...
-
Mit
case WM_ERASEBKGND: return TRUE; case WM_PAINT: ValidateRect(hwnd, 0); break;
sieht es schon deutlich besser aus, aber noch nicht fehlerfrei. Wenn man das Fenster verkleinert scheinen zumindest die einzelnen "Objekte" darauf immer noch zu flackern, bzw. einen Frame lang nicht gezeichnet zu werden. Ich fürchte da kann man wohl nicht mehr so viel dran ändern?
-
Was genau für "Objekte drauf"?
-
Den Kram den ich halt mit OpenGL zeichne. Texte, Sprites, ... - Der Unterschied zu vorher ist, dass die Farbe mit der in clear()e jetzt stimmt. (Vorher wurde beim verkleinern ja mit weiß gecleared, was ziemlich schlimm aussah.)