[Projekt]Grafik-Engine

Hast du keinen Hard-/Softwaretesselierer? Dann würde das 2. Pic noch anständiger aussehen :D
Aber trotzdem schonmal nicht schlecht die Dinger! Wo gefunden?
Weil ikke finde die Lesezeichendatei bei mir nichtmehr ... kein Wunder bei meinem Filemanagement :fresse:

Und dude, mal eine Frage: Hast du schon Multithreading drin? Weil ich stehe bei mir jetzt so, dass ich das meistbenötigte erstmal drinnen habe und es geht (zumindest JETZ GERADE BEI MIR xD). Nun eben die Frage, ob man Threading schon so früh wie möglich einbauen sollte, oder ob es da besser ist das später einfach noch "drüberzulegen" ... denn ich könnte mir schon vorstellen, dass der Synchronisierungsauffwand ziemlich hoch ist!
(Wobei KingofKingzZ hatte ja auch schon was bei sich .. wo ist der eigentlich ? :D )
 
Öhm nein?! :D Mit Tesselation habe ich mich auch noch nicht wirklich befasst.
Gefunden bei http://archive3d.net/

Am besten ist es wohl, seinen Code gleich zu begin auf Multithreading auszulegen. Wenn der Code dann immer größer und größer wird und dann eine Umstellung erfolgt, dann macht das einfach mal mehr Arbeit als wenn man es quasi gleich draus auslegt. Sollte Sinn machen?! :D
Wo er ist weiss ich nicht, hatte glaube ich nicht mehr ganz so viel Zeit?! ^^
 
Am besten ist es wohl, seinen Code gleich zu begin auf Multithreading auszulegen. Wenn der Code dann immer größer und größer wird und dann eine Umstellung erfolgt, dann macht das einfach mal mehr Arbeit als wenn man es quasi gleich draus auslegt. Sollte Sinn machen?! :D
Nachträglich MT-Support einzubauen kann sehr aufwendig werden. Man sollte das daher bereits beim Design berücksichtigen.
 
@AMD: *.3DS kann ich nicht lesen (das habe ich noch nicht implementiert, da ich die sachen auch händisch mache..) Gibts da bei OpenGL zufällig eine vorgefertigte Methode? Weil bei DX (11.x) muss man haufenweise selber machen -.-

Zumindest eine kleine Software-Tesselation kannst du ja einbauen, das ist grob in ~30Min gemacht. ;)


@bingo88: jup, vor allem, wenn man nicht genau weiß, wohin die Calls denn nun laufen und was sie noch alles machen^^ Ich habs neulich geschafft, dass ich in der Update-Methode irgendwie einen Render-Call hatte und dann habe ich die Szene immer 2x gerendert :ugly:
Ich weiß nur wirklich nicht, was besser ist ... wenn man z.B. im Nachhinein noch ein Subsystem implementiert dann muss man da ggf. auch das ganze Threading beachten, während man ohne MT erstmal einfach nur machen kan ....
 
Also OpenGL hat kein eigenes Format... OpenGL hat eig. garnix :ugly:
Daher habe ich auch erstmal das *.obj Format genommen! Kann zwar nicht so viel aber immerhin einfach mit zu arbeiten...
Ich konvertiere mit die Modelle in der Regel mit 3d Studio Max.

Nochmal zu Thema Multi-Threading: Ich hatte ja auch mal die Kollisionserkennung ausgelagert, allerdings waren die Sachen dann asnycron zum anderen Thread, wodurch viele Fehler auftraten... leider alles nicht so leicht :/
 
@fadade Wenn sowohl Spieleprogrammierung als auch MT für dich neu ist, würde ich auf letzteres erst einmal verzichten, bis du mit der Spieleprogrammierung einigermaßen klar kommst. MT kann wirklich zu kaum findbaren Fehlern (und damit ner Menge Frustration) führen. Ich durfte schon mit Threads, OpenMP und MPI im HPC-Umfeld arbeiten, daher kenne ich solche Fehler aus eigener Erfahrung ;-)
 

Naja gut, ich würde trotzdem mal sagen, das selbs diese einfachen Formate für Hobbyprojekte ausreichen (nur wenn man dann noch Xtreme-Animations etc. einbaut, dann wird es wahrscheinlich komfortabler auf ein anderes Format zu wechseln). Das mit der Kolisionserkennung habe ich mir auch schon angesehen, ist momentan bei mir (auch?) das performance-kritischste.
Laut meiner Kenntnis müsste es aber schon schneller sein, wenn man für die Kollisionsberechnung immer einen neuen Thread startet und der Hauptthread auf den wartet, als dass man die Collision-Funktion einfach so aufruft. Und wenn du weißt, was deine Kollisionen alles für Werte manipulieren, dann kannst du in der Zeit ja mal Audio-Kram/Clean-Up/... machen (für Kollisionssounds müsste dann natürlich nach der Kollisionsberechnung nochmal im Audiosystem entsprechend ein Buffer befüllt werden o.ä.)

@fadade Wenn sowohl Spieleprogrammierung als auch MT für dich neu ist, würde ich auf letzteres erst einmal verzichten, bis du mit der Spieleprogrammierung einigermaßen klar kommst. MT kann wirklich zu kaum findbaren Fehlern (und damit ner Menge Frustration) führen. Ich durfte schon mit Threads, OpenMP und MPI im HPC-Umfeld arbeiten, daher kenne ich solche Fehler aus eigener Erfahrung ;-)

Mal OT: Kann es eigentlich noch passieren, dass zwei Threads gleichzeitig auf einen Speicherbereich zugreifen? Und wenn ja, was passiert dann? (einer liest, einer schreibt; beide schreiben; beide lesen ...) Kommt dann einfach nur eine Exception?

Und der bingo hat ein Bingo erzielt :D
Jop, also 3D-Programmierung hab ich noch nie gemacht, und Threading früher mal (ein paar Threads erstellen, die irgendwelche Devices in Unix "betreuen" und eine Kommunikationsmöglichkeit bieten). Wobei jetzt so Libraryfunktionen (Tesselation, Meshtests, ...) lasse ich schon asynchron laufen; wobei bei den Sachen ist das ja auch noch einfach^^
ich denke mal (für mich) wäre es dann auch klüger später wenn allet geht einfach mal etwas in einen Tread zu stecken und dann guggn was passiert :ugly:
 
Mal OT: Kann es eigentlich noch passieren, dass zwei Threads gleichzeitig auf einen Speicherbereich zugreifen? Und wenn ja, was passiert dann? (einer liest, einer schreibt; beide schreiben; beide lesen ...) Kommt dann einfach nur eine Exception?
Das kann immer noch passieren. Ob und wie so etwas gewünscht ist, hängt von der Anwendung ab. Und eine Exception gibt es da keineswegs, das ist ja grad das Nette bei Threads. In 10.000 Fällen funktionierts und in einem nicht ;-)

Beispiel: Zwei Threads (A, B) greifen gemeinsam auf einen int zu. Wenn beide Threads nur lesend zugreifen, kann relativ wenig passieren (Ausnahme: Thread B *muss* nach Thread A lesen, etc.). Problematisch wird es z. B. bei sogenannten Read-Modify-Write Operationen, da diese nicht atomar (atomar ~ "nicht unterbrechbar") sind. Thread A liest die Variable und erhöht sie um 1. Bevor A den Wert zurück in den Speicher schreiben kann, wird der Programmfluss aber an Thread B übergeben (A wird unterbrochen). Dieser liest den aktuellen Wert (nicht um 1 erhöht, A hat ja noch nicht gespeichert!) und erhöht ihn ebenfalls um 1. B speichert den Wert und A ist wieder an der Reihe. A hat aber nicht mitbekommen, dass B ebenfalls den Wert erhöht hat und speichert seinen eigenen Wert. Anstatt also die Variable um 2 zu erhöhen, wurde nur einmal inkrementiert. Dies bezeichnet man als "Lost Update". Und glaub mir, bei sowas fliegt keine Exception :ugly:

Man darf auch keinerlei Annahmen treffen, welcher Thread wann und wie ausgeführt wird. Das regelt nämlich das Betriebssystem. Du als Entwickler musst daher dafür sorgen, dass dein Programm mit solchen Sachen klar kommt (Vermeiden von Deadlocks, Race conditions, nichtatomaren RMW-Operationen, etc.). Dazu gibt es Konzepte zur THreadsynchronisierung: Semaphore, Barrieren, Locks, etc. Die muss man aber auch gut einsetzen können, da man ansonsten viel der durch MT gewonnenen Performance wieder verschenkt. Ich habe schon COde gesehen, der wurde durchs Synchronisieren wieder seriell ;)
 
Das klingt jetzt sehr ermutigend :D

Macht es eigentlich Sinn dann auch z.B. Matrixmultiplikationen und so zu "threaden"? Sprich Thread1 rechnet erste spalte aus, der nächste die 2. usw. oder ist da der Zeitaufwand für die Threadumgebung zu hoch?
Weil gerade, dort wo man weiß, dass nur in die neue Matrix nur eindeutig geschrieben wird und aus den alten nur gelesen wird, könnte man MT ja ansetzen ....
 
Naja, bei Spielen kommen 4x4 Matrizen zum Einsatz, da lohnt es sich nicht wirklich, das mit Threads zu parallelisieren (Verwaltungsaufwand >> Nutzen). Was eher Sinn machen könnte, ist z. B. das Multiplizieren mit einer Menge Vektoren zu parallelisieren. Das macht ja auch eine Grafikkarte, beispielsweise bei der Transformation von Objekt- in Weltkoordinaten.

Grundsätzlich ist Matrixmultiplikation schon ein Bereich, wo viel parallelisiert wird. Allerdings sind die Matrizen dann auch wesentlich größer (bspw. beim Lösen linearer Gleichungssysteme) ;-)

Ehrlich gesagt habe ich bisher MT nur im Zusammenhang mit Subsystemen gesehen, bspw. Physik, Netzwerk oder Sound. Vieles, was mit Objektdaten zu tun hat, lässt sich halt über Shader viel einfacher realisieren. GPUs haben auch ein wesentlich besseres Thread-Management, oftmals gibt es da spezielle Bereiche im Chip für. Normales MT wird hingegen zum großen Teil vom OS verwaltet (deswegen benötigt bspw. AMDs Bulldozer auch einen Patch für Windows 7).
 
Wie schon geschrieben, in 3D-Spielen sind die Matrizen oft 4x4 groß. Parallelisieren ist da nur bei einer großen Anzahl an unabhängigen Berechnungen sinnvoll. Einzelne Matrix/Vektor-Operationen lassen sich aber gut mit den Vektor-Erweiterungen der CPU beschleunigen(SSE, AVX).
 
Okay, wenn ich wüsste, wie das geht, würde ich es auch mal probieren :D :ugly:
Aber aber sonst behalte ich erstmal mein "Durcheinander-Threading"-Konzept bei

Vielleicht hat der TE ja auch schon MT eingebaut und teilt dies mit ^^
 
Hmmmm... nach ein bisschen Recherche scheint es mir so, als würde der Compiler für C# (bzw. Jit) das nicht nutzen.
Mit Mono solls gehen, aber noch etwas includen möchte ich eigentlich nicht^^
Allerdings konnte ich eben auch einfach durch die "Try-and-Error"-Methode wieder bisschen was optimieren :D
 
C# erzeugt auch keinen nativen Code wie C++ das beispielsweise macht. C# erzeugt Byte-Code, der von der .Net Runtime ausgeführt wird (macht Java auch). Da ist nix mit Assemblercode einstreuen ;)
 
Jop, und deswegen wundert es mich auch, dass man mit Mono trotzdem irgendwie die Unterstützunng bekommt^^
(Habe ich bisher aber auch nicht probiert, also keine Ahnung ob das wirklich stimmt)

Nur mal ein anders Problem (auch @AMD :P)
Bei mir steigt die RAM-Nutzung praktisch in jedem Fall an, wobei ich nichts rendere, außer Buffer leeren und dann wieder mit der Farbe schwarz befüllen ...
Sobald ich z.B. das Fenster minimiere, anklicke, verschiebe, ..... jedes mögliche Event, löst irgendwie einen Anstieg um ~4-100kB aus. :what: Auch wenn ich nichts mache, so alle 10 sec. passiert das. Ist das immer so, oder muss das irgendwie an meinem Code liegen?
 
Das liegt wohl an deinem Code ;)
Hatte gerade mal eine Szene rendern lassen und es bleibt konstant bei 71,500 MB
 
hmmm, seeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeehhhhhhhhhhhhhhhhhhhhhhhhhhhhrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr merkwürdig!

Code:
// Nicht auf Keyevents reagieren
using (var factory = _SwapChain.GetParent<DXGI.Factory>())
  factory.SetWindowAssociation(_MainRenderForm.Handle, [U][B]DXGI.WindowAssociationFlags.IgnoreAll[/B][/U]);

//Render Target View; wird später angebunden!
DX11.Texture2D backBufferTexture = DX11.Resource.FromSwapChain<DX11.Texture2D>(_SwapChain, 0);
_RenderTargetView = new DX11.RenderTargetView(_RenderDevice, backBufferTexture);

So, und wenn ich jetzt nur rendern lasse, dann steigt es alle ~10 sec immer noch um etwa 4kB. und wenn ich nebenbei noch Tasten drücke (die ich ja eigentlich ignoriere), dann steigt es sehr schnell an. Also Taste gedrückt halten und ich brauche pro Sekunde locker 0,5MB mehr RAM, ohne dass ich überhaupt ein Keyboarddevice erstellt habe :ugly:
(Werden vielleicht irgendwo die Eventargs gespeichert? Aber die müssten dann ja auch irgendwie wieder released werden ... automatisch?!)
Wahrscheinlich sollte ich dazu mal mit den VS-Analysetools arbeiten können, aber die zeigen mir alles mögliche an :fresse:

Naja gut, wenns bei euch klappt, dann ist das ja wenigstens schonmal was, C# ist eben seeehr anspruchsvoll ... in dem Fall :devil: (bzw. in meinem Fall :P :lol: )
 
Ich würde jetzt mal spontan auf das new DX11.RenderTarget-Dingens tippen. Wenn das bei jedem Frame gemacht wird, wird natürlich in jedme Frame auch ein neues Objekt erzeugt. C# hat zwar einen Garbage Collector, der räumt aber auch nur ab und an mal auf (wg. Performance). Wenn möglich vielleicht solche Aufrufe vermeiden und stattdessen in einer Variable speichern?
 
upps, also der Code wird nur einmal beim Laden ausgeführt; aber sonst wärs klar ;)

Da ich jetzt die komplette Update-methode blockiert habe und er nur ROOT rendert, kann ich genau sagen, dass er nur folgendes ausführt:
Code:
public void RenderRoot()
{
	//Setting Effectparameters
	if (_mRootEffect == null)
	{
		InitRenderRootData();
	}
[I][/I]
	// configure the Input Assembler and Layouts
	_DevContext.InputAssembler.InputLayout = _mRootInpLayout;
	_DevContext.InputAssembler.PrimitiveTopology = DX11.PrimitiveTopology.TriangleList;
	_DevContext.InputAssembler.SetVertexBuffers(0, new DX11.VertexBufferBinding(_mRootVertexBuffer, Marshal.SizeOf(typeof(VERTEXPOSITIONCOLOR)), 0));
	_DevContext.InputAssembler.SetIndexBuffer(_mRootIndexBuffer, DXGI.Format.R32_UInt, 0);

	_mRootEffectMatrix.SetMatrix(Matrix.Identity);
	_mRootEffectPass.Apply(_DevContext);
	_DevContext.DrawIndexed(9, 0, 0);
}

Dort ist zwar auch das new DX11.VertexBufferBinding, aber das kann nicht Disposed werden und auch wenn ich es auslagere, ändert es nichts. (und davor und danach wird eben noch das bisherige bild gelöscht, bzw. das aktuelle gesetzt). Also ich muss jetzt aber mal sagen, dass selbst wenn ich GAR NICHTS MACHE, also wirklich GAR NICHTS, dass die RAM-Nutzung trotzdem ansteigt, wenn ich irgendwie das Fenster verschiebe, anklicke, Tasten drücke .... (Es pendelt sich auch nicht ein, und nix). :wall:

Naja ich denke mal dazu ist .NET gemacht worden^^
Aber ich möchte diesen Thread auch nicht zu sehr damit zulümmelnl. Vielleicht findet sich im Inet noch irgendwas dazu ...........
 
Zurück