Wenn ich eine Engine mache die mehrere Render-, bzw. Displaycontexte benötigt (Ausgabe in verschiedene Fenster), hat jeder Context einen eigenen Thread. Die Threads untereinander teilen sich mit wglShareLists den Rendercontext (da ja alle den gleichen Inhalt präsentieren). Die einzelnen Threads rendern dann eigentlich nur (bzw. "lesen" nur Daten), sollte also kein Synchronisationsproblem werden. Aber wie steht es mit den Shadern? Da ich ja beim rendern aus dem Thread Daten an einen Shader passieren muss (Uniform), denke ich bekomme ich da Konflikte wenn zwei Threads parallel jedoch in ihre eigenen Contexte rendern, aber das gleiche Shaderprogramm benutzen? Wie könnte ich das absichern?
Registriert: Do Sep 02, 2004 19:42 Beiträge: 4158
Programmiersprache: FreePascal, C++
Wenn ich das richtig verstehe, müsstest du den Shader einfach für jeden Thread einmal neu erzeugen (also Laden, das Programmobjekt erstellen und alles) und dann nur die Version des jeweiligen Threads benutzen.
Gruß Lord Horazont
_________________ 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
Hmm, ja, das habe ich auch schon überlegt, nur das Problem ist, dass ich meine Shader dynamisch erzeuge je nach Materialdefinition (also unterschiedlicher Shader ob z.b. Spekular oder Bump Textur vorhanden ist, etc.), das würde den Aufwand und Sinn sprengen, diese Shader mehrfach zu erstellen und für jeden Thread separat zu binden... Ich brauche die Threads ja nur für den Editor, wo ich mehrere Fenster für die Anzeige brauche, in der eigentlichen Anwendung hab ich dann nur einen Render-Thread. Da mir deshalb die Performance im Editor eigentlich mehr oder weniger egal ist, gäbe es eine Möglichkeit den Ausführenden Code inkl. Shader etc. zu "sperren" bis der Thread fertig ist und dann erst der nächste rann kann?
Registriert: Do Dez 05, 2002 10:35 Beiträge: 4234 Wohnort: Dortmund
Script hat geschrieben:
Da mir deshalb die Performance im Editor eigentlich mehr oder weniger egal ist, gäbe es eine Möglichkeit den Ausführenden Code inkl. Shader etc. zu "sperren" bis der Thread fertig ist und dann erst der nächste rann kann?
Die Möglichkeit gibt es natürlich. Aber dann wäre der eigentliche Sinn der Threads aber erheblich geschmälert. Denn was bringt es mehrere Threads zu benutzen, wenn einer immer auf die Anderen warten müsste. Also du hättest zwar Threads aber würdest dafür sorgen, dass nie 2 Threads gleichzeitig laufen. Dann könntest du auch gleich ganz auf Threads verzichten und würdest dir auch die lästige synchronisiererei sparen.
Ich weiß auch nicht was du da vor hast. Aber für einen Editor brauchst du normal auch keinen Renderloop. Sondern dort würde es genügen zu zeichnen, wenn sich etwas verändert hat. Animationen mal ausgenommen. Dann muss natürlich häufiger gerendert werden.
Was du evtl auch berücksichtigen solltest ist, dass die Threads nicht abwechselnd dran kommen. Sondern die Ausführungszeiten können schon entsprechend variieren. Wenn du 2 wirklich seperate RenderThreads hast, dann dürften animationen etc nicht auseinander laufen sondern müssten Synchron ablaufen.
Hmm, das geht leider nicht mit dem Aufbau meiner Engine... der für die Modelle etwa so aussieht:
x Modelle
jedes Modell hat x Materialien
jedes Material (hier steckt der Shader) hat x Texturen (Diffuse, Specular, Normal, etc.)
Wenn ich jetzt über den Thread rendere, müsste ich ja so für jedes vorhandene Modell und dessen Materialien einmal den Shader laden... da dem Shader aber erst beim rendern des Modells die nötigen Werte übgeben werden, würde dies eine grosse Redundanz bedeuten...
Da ich die Threads eigentlich nur brauche um in verschiedene Fenster zu rendern ohne das Render-Context dauernd wechseln zu müssen, bietet sich wohl nur noch eine serielle Verarbeitung der Threads an um Überschneidungen zu verhindern... und wie mache ich das am besten, dass welcher Thread wann merkt, wann er dran kommt?
argh, jetzt bist du mir grad noch zuvor gekommen mit absenden
Wie grad oben geschrieben ist's mir eigentlich egal, dass ich beim Editor die volle Performance von parallelen Threads nicht ausnutzen kann, da ich mehr darauf aus bin, die separaten Rendercontexte eines jeden Threads nutzen zu können. Ich könnte das auch in meiner Hauptanwendung mehrere Rendercontexte aufmachen, aber dann muss ich dauernd zwischen diesen wechseln und da ich kontinuierliche Animationen darstellen will und sowieso immer updaten muss, spare ich mir diesen Wechsel bei den Threads ein... hmm oder?
Registriert: Do Dez 05, 2002 10:35 Beiträge: 4234 Wohnort: Dortmund
Also ich weiß nicht wie deine Anwendung aussieht. Aber mitunter gibt es auch die Möglichkeit einen RC zu erstellen und dann dort 2 Ansichten hinein zu rendern. Der Viewport muss ja nicht den kompletten RC ausnutzen. Aber du bräuchtest dann in jedem Fall ein einziges Fenster.
Eine TCriticalSection kappselt einen Bereich der nur von dem selben Thread betreten werden darf. Wenn jemand anderes diese Section betreten möchte, dann muss er so lange warten bis sie wieder verlassen wurde. Allerdings stelle ich mir dort wirklich die Frage ob der Nachteil des RC Wechselns wirklich so groß ist, dass es die durch Threads verstärkte Synchronisation rechtfertigt? Denn selbst wenn du Daten an die Threads übergeben willst oder Daten verändern willst, die die Threads benutzen, dann musst du auch Synchronisieren. Und das muss dann für jeden Thread ein mal gemacht werden.
Ich will ja nicht nur z.b 2 Ansichten rendern, ich will x Ansichten rendern, das ganze soll also sehr dynamisch einsetzbar sein, deshalb klappt das wohl auch nicht, mehrere Ansichten in einen Rendercontext zu zeichnen.
Hmm, schlussendlich ist es schon eine Geschwindigkeitsfrage... angenommen ich habe 10 Fenster offen im Editor die irgendetwas anzeigen, so müsste ich, wenn alle regelmässig erneuert werden, 10 mal den Rendercontext aktivieren bzw. wechseln. Ich hab gelesen, dass da schon Millisekunden drauf gehen das ganze einmal umzustellen und das dann z.b. 10 mal hmm... ich glaube da muss doch die Variante z.B. wie du sagst mit dem sicheren Bereich für einen Thread doch schneller sein?
Zitat:
PS: Wie aktivierst du eigentlich deinen RC?
Da ich im Moment erst nur einen Context habe, benutze ich ActivateRenderingContext, mit den Threads würde ich dann jedoch direkt mit den Funktionen der wgl arbeiten, also wglMakeCurrent (und wglShareLists für den gemeinsamen RC).
Registriert: Do Dez 05, 2002 10:35 Beiträge: 4234 Wohnort: Dortmund
Die Idee mit einem RC hätte evtl. funktioniert, wenn du 2 oder 4 Ansichten hast. Bin aber insgeheim auch nicht davon ausgegangen, dass das genügen würde.
Ja okay. Bei Threads würde das Wechseln des RCs wegfallen. Das stimmt natürlich irgendwo. Allerdings kostet diese Synchronisierung (TCriticalSection) natürlich auch irgendwo Zeit. Bzw hast du zwar die Möglichkeit Parallel zu arbeiten aber du würdest es unterdrücken. Wobei du bei deinen Einschätzungen aber realistisch sein solltest. 10 klingt für mich nicht realistisch. Denn du hast 10 Renderloops und jeder würde der GPU etwas abverangen. Also muss die GPU schon eine dicke Leistung haben damit es nicht zu extrem langsam wird. Besonders mir großen Effekten dürfte man da schnell ans Ende gelangen.
Durch Threads bekommst du aber durchaus auch Probleme. Ich hatte mir vor einigen Jahren mal angewöhnt in einem Thread zu rendern. Im Endeffekt hatte ich es aber sein lassen. Weil die Threads haben alles kompliziert gemacht. Selbst die einfachsten Sachen sind irgendwo ausgeartet, denn das eigentliche TForm wurde im VCL Thread erstellt und gerendert wurde in einem seperaten Thread. Denn die GDI/VCL ist nicht Threadsafe.
- Beim Verändern der Fenstergröße zum Beispiel wird die Fenstergröße angepasst wärend OpenGL noch zeichnet. Für den Moment der Größenänderung wurde der Speicher des Framebuffers verzerrt dargestellt. Erst wenn das nächste Mal gezeichnet wurde konnte auch der Viewport angepasst werden. Bzw ohne Threads kann das Fenster auch nicht in der Größe verändert werden wenn gerade gezeichnet wird.
- Bei der Auswahl von Objekten. Das Fenster realisiert eine Mausbewegung. Dann müssen die Koordinaten an den Thread übertragen werden + info, dass eine Auswahl stattfinden soll. Erst wenn der Thread mit seinem aktuellen Bild fertig ist kann er picken. Und erst wenn das fertig ist kann die Methode die das Picken angeworfen hat zurückkehren. Denn wenn die Beendet ist muss das Ergebniss da sein. So lange muss sie warten. Anschließend wird das gepickte an den Thread gereicht, damit es markiert werden kann. Aber der Thread rechnet bereits wieder an einem Bild. Also hat so etwas grunssätzlich ein Bild Verzögerung.
Ich bin nicht gegen Threads. Ganz im Gegenteil. Ich finde mittlerweile sind sie wichtiger denn je. Nur denke ich, dass es beim Rendern da eher hinderlich sein dürfte. Ich persönlich würde wohl in dem VCL Thread nur die Fenster verwalten und Rendern. Alles Andere so weit es mit OpenGL nichts zu tun hat und sinnvoll ausgelagert werden kann würde ich in Threads auslagern. Das ist aber nur meine Meinung und keines wegs allgemeingültig.
RC aktivieren. Genau. Du musst einmal in jedem Fall mit ActivateRenderingContext aktivieren oder per Hand die Extension laden und sonst nur mit wglMakeCurrent ist das Schnellste. Wie lange das Wechseln allerdings dauert kann ich dir nicht sagen. Aber ja. Sehr billig ist der Aufruf nicht.
Aber ich denke im Endeffekt liegt diese Entscheidung bei dir. Nur solltest du es evtl. so aufbauen, dass du im Falle, dass es nicht funktioniert doch wechseln könntest. Jetzt erst mal dahingestellt von welcher Methode zu welcher Methode.
Danke für deine ausführliche Antwort, bin froh deine Erfahrungen zu lesen!
Hehe, ja, 10 ist mal so hoch gepokert, jedoch meine ich auch nicht 10 Ansichten der ganzen Scene, es können z.b. auch nur Ansichten eines einzelnen Modelles sein, eines Partikelsystems oder einfach nur ein Quad mit Textur und Belichtung drauf.
Hmm, irgendwie, also WENN ich es mit Threads mal versuchen würde bin ich mit TCriticalSection auch nicht ganz glücklich, da ja scheinbar wenn der gesetzt ist auch kein anderer Thread aus dem Bereich lesen kann... also ich verzieh mich mal in die Denkerpose und schau mal was aus der Sache raus kommt
Registriert: Do Dez 05, 2002 10:35 Beiträge: 4234 Wohnort: Dortmund
Also eine TCriticalSection sperrt grundsätzlich nur die Ausführung von Code. Einen Speicherschutz gibt es nicht. Du müsstest dann nur die Section entsprechend setzen, dass der Code zum Lesen nicht innerhalb der Section ist.
Du kannst ja auch einfach mal ein kleines Testprojekt machen in dem du einen sehr sehr einfache RCs benutzt. Also nicht perfekt mit allen Effekten/Shadern etc sondern eben so aufbauen, dass du mehr als 4 Fenster hast. Oder eben auch die 10. Wenn du wärend dem Rendern (innerhalb der Section), dann evtl noch ein sleep(1) oder 3 einfügst simulierst du arbeit. Dann würdest du zu mindest recht schnell sehen ob es dort Probleme gibt. Du solltest dort aber auch ein bisschen Interaktion mit einbauen. Also mit der Maus mal objekte auswählen/verschieben etc. Nur alles einfacher als im richtigen Editor.
Denn für den Fall, dass das nicht funktioniert wäre das in jedem Falle besser als wie wenn dein Editor schon halb fertig wäre. Und falls es doch geht hast du schon einen Ansatz wie man damit arbeiten könnte.
Mitglieder in diesem Forum: 0 Mitglieder und 18 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.