Die Frage die ich mir jetzt gestellt habe: Muss ich die Texturen neu auf die Grafikkarte hochladen oder nicht? Ich vermute fast ja, denn die GPU könnte sich ja geändert haben (wenn man zwei Grafikkarten im Rechner hat, und man das Fenster von einem Bildschirm auf den anderen schiebt [wobei: wird dabei ein neues Handle angefordert?])
Ich würde mal behaupten Texturen gehören zum OpenGL-Kontext. Wenn du diesen löschst sind auch die Texturen weg.
Edit: Es könnte aber sein das man den Kontext irgendwie auf ein anderes Fenster übertragen kann. Zitat aus der Doku des QGLWidget (Qt-Framework):
Zitat:
Note that under Windows, the QGLContext belonging to a QGLWidget has to be recreated when the QGLWidget is reparented. This is necessary due to limitations on the Windows platform. This will most likely cause problems for users that have subclassed and installed their own QGLContext on a QGLWidget. It is possible to work around this issue by putting the QGLWidget inside a dummy widget and then reparenting the dummy widget, instead of the QGLWidget. This will side-step the issue altogether, and is what we recommend for users that need this kind of functionality.
Ja, alle Texturen und anderer Objekte (VBO, Listen, ...) werden gelöscht wenn der Context freigegeben wird. Außer du erstellt einen Dummy-Context und teilst mittels wglSharelists die Objekte zwischen dem eigentlichen Context und dem Dummy-Context.
Eine anderer Möglichkeit wäre noch: Unter Windos kann man den OpenGL-Context auch an einen anderen DC (Devicecontext) binden. Dieser DC muss aber das gleiche Pixelformat haben, wie der DC mit dem der OpenGL-Context erstellt wurde.
Joar, da steht was dazu, aber nicht viel . Was ich mich aber Frage: Wenn man zwei Grafikkarten im Rechner stecken hat - und zwei Bildschirme. Funktioniert das dann mit wglShare, wenn man ein Fenster von einem Desktop auf den nächsten zieht? Bekomme ich dann überhaupt den Wechsel mit? (Hab leider nur einen Bildschirm, von daher weiß ich das nicht).
Und kann man sich ein Dummy-Context holen ohne ein spezielles Fensterhandle anlegen zu müssen? Denn wglSharelist wäre für mich auch ganz praktisch um mit einem Thread Texturen hochzuladen, während der andere alles rendert.
Joar, da steht was dazu, aber nicht viel . Was ich mich aber Frage: Wenn man zwei Grafikkarten im Rechner stecken hat - und zwei Bildschirme. Funktioniert das dann mit wglShare, wenn man ein Fenster von einem Desktop auf den nächsten zieht? Bekomme ich dann überhaupt den Wechsel mit? (Hab leider nur einen Bildschirm, von daher weiß ich das nicht).
Habe mich wohl nicht ganz klar ausgedrückt. Mit der Funktion wglShareLists werden nur die Objekte geteilt, damit beim neu erstellen des Contexts die Objekte nicht neu hochgeladen werden müssen. Das Freigeben des alten Context und Erstellen sowie sharen des neuen Context muss man aber selbst durchführen.
Ich habe zwei Bildschirme auf einer Grafikkarte, wenn ich ein OpenGL Programm auf den anderen schiebe ändert sich kein Handle. Wie es bei zwei Grafikkarten aussieht kann ich aber nicht sagen.
Habe mich wohl nicht ganz klar ausgedrückt. Mit der Funktion wglShareLists werden nur die Objekte geteilt, damit beim neu erstellen des Contexts die Objekte nicht neu hochgeladen werden müssen. Das Freigeben des alten Context und Erstellen sowie sharen des neuen Context muss man aber selbst durchführen.
Das war schon klar . War halt nur die Frage, ob das zwischen 2 Grafikkarten funktioniert.
Man benötigt kein eigenes Fenster für den Dummy-RC. Da der DC beim Erstellen des Context nur dazu benötigt wird damit der RC weiß mit welchem Pixelformat er es zu tun bekommt. Deswegen kann der RC auch an einen anderen DC gebunden werden als mit dem er erstellt wurde, wenn dieser der gleiche Pixelformat hat.
// Aktuellen RC freigeben und neuen Erstellen, wenn sich das Handle ändert DeactivateRenderingContext; DestroyRenderingContext(FRC); ReleaseDC(WndHandle, FDC);
// Beenden der Anwendung DeactivateRenderingContext; DestroyRenderingContext(FRC); ReleaseDC(FWindowHandle, FDC);
wglDeleteContext(FDummyRC);
Nach meinem Verständnis müsste es so funktionieren. Ob es auch mit zwei Grafikkarten funktioniert kann ich nicht sicher sagen, wüsste aber nicht warum .
Edit: So müsste es ohne wglShareLists funktionieren.
An die Variante habe ich auch schon gedacht. Allerdings hat der bei mir noch einen Haken (den ich zwar umgehen kann, aber ich will halt wissen, ob es auch ohne der Umgehungsstraße geht ). Und zwar habe ich meine Komponente von TWinControl abgeleitet. Da im Create-Ereignis dort noch kein Handle bereitsteht, da kein Parent vorhanden ist, erzeuge ich den OpenGL-Kram in der CreateHandle-Methode und zerstöre alles beim Destroy-Handle. Wenn also sich der Parent ändert, zerstöre ich alles, um gleich darauf wieder alles zu erzeugen. Nun will ich die hochgeladenen Texturen natürlich da nicht verlieren, wenn es geht. Dafür kann man ja wglSharelist verwenden, in dem ich einfach für das erste Handle das ich bekomme ich einen Dummy-RC erzeuge, der dann alle Änderungen überlebt. Nun ist meine Anwendung allerdings multithreaded - sprich ich habe einen Renderthread und einen Thread, der diesem "Aufgaben stellt". Ist halt eine Coverflow die nicht stocken soll, wenn die Anwendung ansonsten gerade zu tuen hat. Wenn der Coverflow jetzt merkt: Mir fehlt eine Textur, dann sendet er eine Nachricht an den anderen Thread und sagt ihm, für welches Objekt er die Textur braucht. Dieser andere Thread lädt jetzt die Daten von der Festplatte und übergibt sie meinem Coverflow. Nun muss ich die Daten ja wieder in den Renderthread rüberkriegen. Nun könnte ich mir per GetMem die nötigen Daten kopieren, dann einen Zeiger an den Renderthread übergergeben, der die Textur dann hochlädt und per FreeMem freigibt. Nun kann es ja sein das meine Coverflow pro Thread nicht nur eine neue Textur braucht, sondern mehrere. Von daher nutze ich jetzt ein Array, so dass pro Frame mehrere Texturen übertragen werden können. Allerdings halte ich es für unschön soviel Speicher bis zum nächsten Frame zu halten (auch wenn sich die Menschheit an solche Unschönheiten inzwischen gewöhnt hat ). Von daher wäre mir am liebsten, wenn dieser Thread auch die Texturen hochladen könnte (wieder durch wglSharelist). Allerdings: Wie multithreaded geeignet ist OpenGL? Also gibt es da Probleme? Und zu dem Problem mit dem RC: Wenn der Hauptthread bereits eine Textur hochladen möchte bevor meine Komponente das erste Handle bekommt - wie kann ich das supporten? Wegen letzterer Frage habe ich es jetzt halt mit CreateWindow probiert.
Registriert: Do Sep 02, 2004 19:42 Beiträge: 4158
Programmiersprache: FreePascal, C++
Multithread und OpenGL ist meist eher … unschön. Die Variante, die Textur im Speicher zu halten und zum anderen Thread rüberzuschieben ist eigentlich okay. Nur das Laden und Dekodieren von der Festplatte sollte halt im Aufgabenthread geschehen.
greetings
_________________ If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung. current projects: ManiacLab; aioxmpp zombofant network • my photostream „Writing code is like writing poetry“ - source unknown
„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb
Wie multithreaded geeignet ist OpenGL? Also gibt es da Probleme?
Wenn man ein paar Feinheiten beachtet funktioniert es. Der Aufwand steigt aber enorm und der Nutzten ist sehr abhängig vom Treiber (sogar eine schlechtere Performance ist möglich).
wglShareLists schlägt zb. immer Fehl wenn der RC mit dem geteilt werden soll in Benutzung ist. Das heißt man muss den RC im anderen Thread immer deaktivieren (und am besten gleich noch den ganzen Thread anhalten) bevor man wglShareLists ausführt.
Registriert: Do Dez 05, 2002 10:35 Beiträge: 4234 Wohnort: Dortmund
2 Grafikkarten: Um es kurz zu sagen. Das kannst du vergessen. Der RC ist fundamentaler bestandteil der Grafikkarte. Eine andere Grafikkarte hat keinerlei Ahnung was auf der Anderen vor sich geht. Das kann man wunderschön mit einem Autovergleich verbildlichen. Das ist in etwa so als wolltest du bei voller Fahrt den Reifen von Auto 1 and Auto 2 schrauben. Viel Spaß wünsche ich. Ist aber glaube ich relativ, da der Trend nun mal ganz deutlich zu Grafikkarten mir mehr als einem Ausgang gehen. Und Leute die dennoch so ein System betreiben dürften Kummer gewohnt sein.
Was diese ganze ShareLists Geschichte angeht. Finde ich eigentlich auch irgendwo übertrieben. Klar ist es unschön, wenn man alle Daten neu laden muss sobald man den Parent der Komponente ändert. Wobei sich mir da die Frage stellt. Warum sollte man das tun? Im Endeffekt muss der Entwickler, der deine Komponente benutzt, ja auch irgendwo wissen was er tut. Da ist es meiner Meinung nach durchaus auch erlaubt, wenn eine Bibliothek/Komponente sich bei groben Unfug durchaus auch zur Wehr setzt.
Threads: Das Laden der Daten in Threads auszulagern ist sicher keine schlechte Idee. Ob so etwas mit zwei gesharten RCs allerdings den von dir gewünschten Effekt bringt? Keine Ahnung. Ich habe gekoppelte RCs bisher nur genutzt wenn ich die gleichen Texturen mehrfach zur selben Zeit darstellen wollte. Im Endeffekt ist es eine Grafikkarte. Und spätestens die muss bei anstehender Arbeit andere Arbeiten pausieren und warten lassen. Wobei das blanke Hochladen schnell gehen sollte. Das Erstellen von MipMaps aber wieder Zeit kosten dürfte. Nichts desto trotz kannst du da entweder interne Strukturen im Treiber kompromitieren oder wenn es synchronisiert ist, dann wird es nicht schneller werden.
Was ich an deinen Ausführungen komisch fand war die Aussage, dass du den Thread anweist 6 Bilder zu laden und dann den Speicher von allen Bildern übergibst oder zurückbekommst? Mehr in Richtung Multithreading wäre wohl die Art, dass du Ladebefehle absetzt und diese jemand abarbeitet. Wenn ein Ladebefehl fertig ist, dann wird das Resultat zurückgeliefert. Wenn du dann auf der anderen Seite die Daten abgearbeitet hast dann werden die Daten entsorgt. Wirklich zusammenhängend würde ich die Daten nur dann machen, wenn die wirklich zwingend zusammen gehören müssen. Ansonsten würde ich die Albumbilder einzeln laden und via Callback auch einzeln zurückgeben. Und der jenige der die Daten angefordert hat muss entweder so lange warten, die Teile nicht berücksichtigen oder mit Platzhalterdaten arbeiten. Das ist zu mindest meine Vorstellung davon wie so etwas arbeiten sollte.
2 Grafikkarten: Um es kurz zu sagen. Das kannst du vergessen. Der RC ist fundamentaler bestandteil der Grafikkarte. Eine andere Grafikkarte hat keinerlei Ahnung was auf der Anderen vor sich geht. Das kann man wunderschön mit einem Autovergleich verbildlichen. Das ist in etwa so als wolltest du bei voller Fahrt den Reifen von Auto 1 and Auto 2 schrauben. Viel Spaß wünsche ich. Ist aber glaube ich relativ, da der Trend nun mal ganz deutlich zu Grafikkarten mir mehr als einem Ausgang gehen. Und Leute die dennoch so ein System betreiben dürften Kummer gewohnt sein.
Ok, war mir halt nicht sicher, denn die Anwendungen nutzten ja die gleiche OpenGL-dll. Hinzu kommt, dass die wgl-Funktionen Windows spezifisch ist und nicht plattformunabhängig. Von daher hatte ich es für möglich gehalten, dass die OpenGL-DLL bei mehreren Grafikkarten dafür sorgt, dass wglSharelist die Daten gleich auf allen GPU-Treibern verteilt. Wobei dass das nicht geht ist ja irgendwie auch logisch, denn welche OpenGL-Version unterstützt wird, könnte man ja sonst nicht überprüfen. Die interessante Frage bleibt trotzdem: Ändert sich das Handle beim Wechsel der GPU?
Lossy eX hat geschrieben:
Was diese ganze ShareLists Geschichte angeht. Finde ich eigentlich auch irgendwo übertrieben. Klar ist es unschön, wenn man alle Daten neu laden muss sobald man den Parent der Komponente ändert. Wobei sich mir da die Frage stellt. Warum sollte man das tun? Im Endeffekt muss der Entwickler, der deine Komponente benutzt, ja auch irgendwo wissen was er tut. Da ist es meiner Meinung nach durchaus auch erlaubt, wenn eine Bibliothek/Komponente sich bei groben Unfug durchaus auch zur Wehr setzt.
In den meisten Fällen sollte es nicht auftreten - ja. Allerdings weiß ich bei dem Programm wo die Kompo evtl eingesetzt werden soll, dass sich der Parent mal ändert (nemp - Wechsel zwischen Einzelfenstermodus und dem Kompaktmodus, denn dort ändert sich das handle, da das darunterliegende Formular getauscht wird). Und wenn es mit wenig Aufwand möglich gewesen wäre die Texturen zu behalten, wäre es ja schön gewesen.
Lossy eX hat geschrieben:
Was ich an deinen Ausführungen komisch fand war die Aussage, dass du den Thread anweist 6 Bilder zu laden und dann den Speicher von allen Bildern übergibst oder zurückbekommst? Mehr in Richtung Multithreading wäre wohl die Art, dass du Ladebefehle absetzt und diese jemand abarbeitet. Wenn ein Ladebefehl fertig ist, dann wird das Resultat zurückgeliefert. Wenn du dann auf der anderen Seite die Daten abgearbeitet hast dann werden die Daten entsorgt. Wirklich zusammenhängend würde ich die Daten nur dann machen, wenn die wirklich zwingend zusammen gehören müssen. Ansonsten würde ich die Albumbilder einzeln laden und via Callback auch einzeln zurückgeben. Und der jenige der die Daten angefordert hat muss entweder so lange warten, die Teile nicht berücksichtigen oder mit Platzhalterdaten arbeiten. Das ist zu mindest meine Vorstellung davon wie so etwas arbeiten sollte.
Ok, nochmal kurz meine herangehenswiese (Code ist für euch am verständlichsten):
Code:
if FItems[id]^.handle = 0 then begin if not FItems[id]^.askedForTexture then begin PostMessage(FEventHandle, WM_SunFlow_NeedPreview, id, 0); FItems[id]^.askedForTexture := true; end; glBindTexture(GL_TEXTURE_2D, FDefaultTexture); end else begin glBindTexture(GL_TEXTURE_2D, FItems[id]^.texturehandle); end;
Sprich: Wenn keine Textur vorhanden ist, fragt er den anderen Thread asynchron ggf. danach und nimmt dann ersteinmal die Standardtextur, sofern verfügbar.
Da pro Renderaufruf bis zu 31 Cover gezeichnet werden können, wären auch 31 Anfragen für Texturen möglich - was ich allerdings für unwahrscheinlich halte. Wenn nun Vsync aktiviert ist, werden pro Sekunde allerdings nur 60x gerendert. Und wenn ich dann pro Aufruf nur eine Textur hochladen würde, wäre es ein bisschen... Von daher habe ich an eine Queue gedacht. Alternativ könnte ich es auch so machen wie meine Vorlage: Statt PostMessage SendMessage. Sobald er aus SendMessage herauskommt, wüsste ich ja, dass er die Variablen befüllt hat und somit würden gleich beim ersten Mal rendern die nötigen Texturen haben. Nachteil: Wenn der Hauptthread hängt, hängt auch mein Renderthread - wes wegen ich das nicht unbedingt haben will.
Registriert: Do Dez 05, 2002 10:35 Beiträge: 4234 Wohnort: Dortmund
OpenGL32.dll. Ja die ist für die Erstellen des RCs zuständig. Oder besser gesagt, dass die richtige DLL des Treibers angesprochen wird. Was bei 2 Grafikkarten aber zwei vollkommen unterschiedliche sein könnten. Ich denke nicht, dass das Fenster Handle zerstört wird. Das kommt von Windows. Der RC dürfte aber an der Fenstergrenze aufhören zu existieren und ein schwarzes Bild erzeugen.
Es heißt ja nicht, dass du eine Textur pro gezeichnetem Frame hochladen musst. Wenn 2 da sind dann mach halt 2. Keine Ahnung wie schnell oder langsam das geht. Wobei du sagtest VSync und 60 fps. In solch einem Fall muss man doch sicher keine 100% Last Schleife erzeugen.
Mitglieder in diesem Forum: Bing [Bot] und 3 Gäste
Du darfst keine neuen Themen in diesem Forum erstellen. Du darfst keine Antworten zu Themen in diesem Forum erstellen. Du darfst deine Beiträge in diesem Forum nicht ändern. Du darfst deine Beiträge in diesem Forum nicht löschen. Du darfst keine Dateianhänge in diesem Forum erstellen.