Seite 63 von 254

Re: Jammer-Thread

Verfasst: 15.05.2012, 19:47
von eXile
Schrompf hat geschrieben:Stimmt das eigentlich, dass VC11 keine Exen mehr für WinXP und älter erstellen kann?
Das stimmt so, zumindest wenn du auch den Compiler von VC11 (aka Platform Toolset v110) benutzen willst. Du kannst allerdings auch das nächste Visual Studio mit dem Compiler von Visual C++ 2010 benutzen (Platform Toolset v100). Dafür siehe auch diesen Blogpost.

Re: Jammer-Thread

Verfasst: 15.05.2012, 20:12
von CodingCat
Haha, sehr hilfreich, wo wohl das einzig nützliche an VS11 der neue Compiler sein wird. Die neue IDE brauche ich jedenfalls nicht. ;)

Re: Jammer-Thread

Verfasst: 17.05.2012, 09:24
von Krishty
Was für eine Scheiße – ich habe meinen Renderer hinter einer abstrakten Schnittstelle realisiert. Obwohl
  • von dieser Schnittstelle im ganzen Programm nur eine einzige Klasse abgeleitet wird;
  • sowohl diese Klasse als auch alle Implementierungen ihrer Methoden sealed deklariert sind;
  • LTCG eingeschaltet ist; und
  • allen Funktionen, die die Schnittstelle erwarten, immer nur eine Instanz der finalen Klasse übergeben wird,
packt Visual C++ die Virtual Function Calls nicht mit der Kneifzange an. Und das ist ein echtes Desaster, weil jedes Byte, das den Funktionen übergeben wird, am besten sofort und 1:1 in einen Buffer wandern sollte statt erst über den Stapel gereicht zu werden. Ich muss den Mist geinlinet kriegen. Templates sind aber keine Option, weil ich dank C++’ Intoleranz gegenüber Template-Funktionen aus anderen Modulen 8000 Zeilen von Hand kopieren müsste. Microsoft C/C++ „Optimizing“ Compiler ist so eine Wurst.

Und: Was ist der Zweck dieser Seite?! Die beste Optimierung ist, einfach keine Funktionen mehr aufzurufen?!

Re: Jammer-Thread

Verfasst: 17.05.2012, 11:20
von antisteo
Krishty hat geschrieben:Und: Was ist der Zweck dieser Seite?! Die beste Optimierung ist, einfach keine Funktionen mehr aufzurufen?!
Natürlich,
rechne dir nur mal den Speedup aus, den du damit maximal erreichen könntest.

Re: Jammer-Thread

Verfasst: 17.05.2012, 12:10
von Schrompf
Vielleicht kannst Du ja irgendwas drehen, so dass die Klasse nur in der Debug von der Schnittstelle ableitet und in der Release die Schnittstelle einfach ersetzt. Treue OO-Verfechter empfinden das vielleicht als Sakrileg, aber ich hätte mit solchen Konstrukten kein Problem. Wird auch hier und da in Engine-Tutorials empfohlen, wenn ich mich recht erinnere.

Re: Jammer-Thread

Verfasst: 17.05.2012, 12:40
von Krishty
Das Problem ist, dass ich eine Codebase für Logik habe, und zwei Rasterizers für unterschiedliche Produktversionen, die von der Logik benutzt werden könnten. Durch die .hs der Logik käme ich mit einer Forward Declaration des Rasterizers noch durch; durch die .cpps aber nicht – in dem Augenblick, in dem die Logik einen Rasterizer benutzt, muss dieser vollständig definiert sein. Um ihn vollständig zu definieren, muss die entsprechende .h eingebunden sein (es muss ja z.B. eine Größe für den Typ bekannt sein; d.h., dass alle benutzten Direct3D-Objekte definiert sein müssen; obwohl das logisch gesehen absoluter Unsinn ist. Ich hasse C++!). Die ist aber eine andere, je nachdem, welcher Rasterizer benutzt wird.

Kurz: Ich kriege die virtuellen Funktionsaufrufe nicht weg, ohne Logik und Rasterizers auf Quelltextebene miteinander zu verweben (entweder direkt durch vollständige Typisierung oder durch #ifdef). Das ist ganz große Scheiße, weil es für den Compiler keine Kunst sein sollte, die Aufrufe eindeutig der endgültigen Klasse zuzuordnen und entsprechend zu optimieren. Ich will das auch nicht tun, so lange es der Compiler für mich tun könnte.

Ich verstehe auch nicht, warum Visual C++ das nicht macht – ich habe schon gesehen, dass Leute ihren Klassen 200 virtuelle Funktionen gegeben haben. (Da kann ich ja nicht einmal widersprechen – lieber einmal zu oft virtual als zu selten; und rein theoretisch ist das alles automatisiert wieder auf handabgewogenen virtual-Einsatz optimierbar.) Virtuelle Funktionsaufrufe für all die armseligen Dreizeilerfunktionen; das muss doch ein enormes Optimierungspotential bergen …

Aber die Rasterizers sind sowieso noch ein riesiges Schlachtfeld. Es existiert absolut keine Ordnung im Textursystem – die Texturdaten liegen an so vielen Orten verstreut, dass jeder Rasterizer von selber Pfade zusammenbauen, Dateien suchen, und die dann laden muss; inklusive dazugehöriger Fehlerbehandlung und Datenkonvertierung. Ein gigantischer Haufen gewucherter Scheiße. Bis ich da ein System reingekriegt habe, können noch Monate vergehen.

Re: Jammer-Thread

Verfasst: 17.05.2012, 12:58
von eXile
Krishty hat geschrieben:Aber die Rasterizers sind sowieso noch ein riesiges Schlachtfeld. Es existiert absolut keine Ordnung im Textursystem – die Texturdaten liegen an so vielen Orten verstreut, dass jeder Rasterizer von selber Pfade zusammenbauen, Dateien suchen, und die dann laden muss; inklusive dazugehöriger Fehlerbehandlung und Datenkonvertierung. Ein gigantischer Haufen gewucherter Scheiße. Bis ich da ein System reingekriegt habe, können noch Monate vergehen.
Ich habe keine Ahnung von deinem Framework, aber in der Regel will man doch den Rendering-Teil vom Resourcen-Teil abtrennen? In deinem Beispiel würden beide Rasterizers doch wohl ähnliche Dinge mit dem Dateisystem anstellen, es liest sich aber so, als ob das doppelt implementiert wäre.

Re: Jammer-Thread

Verfasst: 17.05.2012, 13:01
von CodingCat
Templates sind aber keine Option, weil ich dank C++’ Intoleranz gegenüber Template-Funktionen aus anderen Modulen 8000 Zeilen von Hand kopieren müsste.
Weiß ich von dieser Intoleranz? Ich kann den Satz gerade nicht einordnen.

Re: Jammer-Thread

Verfasst: 17.05.2012, 13:02
von dot
Krishty hat geschrieben:Und das ist ein echtes Desaster, weil jedes Byte, das den Funktionen übergeben wird, am besten sofort und 1:1 in einen Buffer wandern sollte statt erst über den Stapel gereicht zu werden.
Also ich kenn dein System jetzt nicht, aber das klingt mir irgendwie so, als ob du dein Interface einfach zu weit unten angesetzt hättest...
Könntest du nicht z.B. in einem Call den kompletten Buffer übergeben?

Re: Jammer-Thread

Verfasst: 17.05.2012, 13:22
von Krishty
Direkt im Voraus: Ich kann bloß die Implementierung der Schnittstelle kontrollieren; wie sie benutzt wird, steht außerhalb meiner Macht.
eXile hat geschrieben:Ich habe keine Ahnung von deinem Framework, aber in der Regel will man doch den Rendering-Teil vom Resourcen-Teil abtrennen? In deinem Beispiel würden beide Rasterizers doch wohl ähnliche Dinge mit dem Dateisystem anstellen, es liest sich aber so, als ob das doppelt implementiert wäre.
Ist es auch. Die Texturen werden mal über Assets identifiziert, dann wieder über eine Datenbank, und einige müssen auch hard-codet werden. Und die Dateipfade unterscheiden sich entsprechend aktueller Renderer-Einstellungen. Verschlimmert wird das dadurch, dass D3D9-Hardware scheinbar kaum palettierte Texturen unterstützt, und ich deswegen einen riesigen Cache aller Texturen, je mit jeder Palette angewandt, in True Color vorhalten muss.

dat chaos
CodingCat hat geschrieben:Weiß ich von dieser Intoleranz? Ich kann den Satz gerade nicht einordnen.
Entschuldige – Übersetzungseinheit statt Modul. Ich meine: Man kann ein Template nicht deklarieren, und in einer anderen Übersetzungseinheit definieren.
dot hat geschrieben:Also ich kenn dein System jetzt nicht, aber das klingt mir irgendwie so, als ob du dein Interface einfach zu weit unten angesetzt hättest...
Könntest du nicht z.B. in einem Call den kompletten Buffer übergeben?
Nein. Ich emuliere ein Legacy-Datenformat, und wo meine Schnittstelle ist, waren vor 15 Jahren mal einzelne glVertex3f-Aufrufe …

Re: Jammer-Thread

Verfasst: 17.05.2012, 13:31
von dot
Krishty hat geschrieben:
CodingCat hat geschrieben:Weiß ich von dieser Intoleranz? Ich kann den Satz gerade nicht einordnen.
Entschuldige – Übersetzungseinheit statt Modul. Ich meine: Man kann ein Template nicht deklarieren, und in einer anderen Übersetzungseinheit definieren.
Vielleicht hilft es schon was, das template nur zu deklarieren und einige konkrete Instanzen dann in der anderen Einheit explizit zu instanzieren?
Krishty hat geschrieben:
dot hat geschrieben:Also ich kenn dein System jetzt nicht, aber das klingt mir irgendwie so, als ob du dein Interface einfach zu weit unten angesetzt hättest...
Könntest du nicht z.B. in einem Call den kompletten Buffer übergeben?
Nein. Ich emuliere ein Legacy-Datenformat, und wo meine Schnittstelle ist, waren vor 15 Jahren mal einzelne glVertex3f-Aufrufe …
Ok, ich geh mal davon aus dass du deine Gründe hast, aber wieso das nun nicht gehen soll erklärt das eigentlich noch nicht ;)
Vielleicht wär es auch sinnvoller, statt soviel Energie in die Optimierung einer ohnehin nicht besonders idealen Schnittstelle zu stecken, es mal dabei zu belassen und stattdessen anzufangen, den alten Code zu refactoren?

Re: Jammer-Thread

Verfasst: 17.05.2012, 13:39
von CodingCat
Krishty hat geschrieben:
CodingCat hat geschrieben:Weiß ich von dieser Intoleranz? Ich kann den Satz gerade nicht einordnen.
Entschuldige – Übersetzungseinheit statt Modul. Ich meine: Man kann ein Template nicht deklarieren, und in einer anderen Übersetzungseinheit definieren.
Hm, aber damit Templates überhaupt eine Option wären, bräuchtest du ja auf jeden Fall Compile-Zeit-Konstanten, die über die Implementierung entscheiden. In diesem Fall wäre das doch auch nicht anders als Implementierungswechsel mittels #ifdef? Interessant wäre, ob folgendes geht (und konform ist):

Code: Alles auswählen

// Header
template <Implementation> void foo();

// Modul 1
template <>
void foo<ImplementationA>()
{
   // Definition A
}

// Modul 2
template <>
void foo<ImplementationB>()
{
   // Definition B
}
Ich sehe gerade nichts, was dagegen spricht, finde aber auch nichts Explizites im Standard.

Re: Jammer-Thread

Verfasst: 17.05.2012, 13:43
von dot
Ja sowas geht per extern. Mit VC schon praktisch immer und seit C++11 auch im Standard, verwend ich ab und zu ganz gern...

Re: Jammer-Thread

Verfasst: 17.05.2012, 13:50
von Krishty
Ich checke das mit den Templates kurz.
dot hat geschrieben:Ok, ich geh mal davon aus dass du deine Gründe hast, aber wieso das nun nicht gehen soll erklärt das eigentlich noch nicht
Vielleicht wär es auch sinnvoller, statt soviel Energie in die Optimierung einer ohnehin nicht besonders idealen Schnittstelle zu stecken, es mal dabei zu belassen und stattdessen anzufangen, den alten Code zu refactoren?
Es ist noch nicht einmal Code: Es ist ein Dateiformat, das Bytecode enthält, der eine virtuelle Maschine kontrolliert, die den Rasterizer Vertex für Vertex steuert – durch 200 Opcodes inklusive Subroutinen; Schleifen; bedingter Sprünge; und allem anderen, was einem das Leben schwer macht.
Es liegen ungefähr 8000 Assets in diesem Format vor. Zu anderen Formaten lässt sich das nicht konvertieren, weil die VM je nach Blickwinkel, LoD, und Situation einen anderen Pfad durch die Datei wählt, und dementsprechend unterschiedliche Daten ausspuckt.

eXile, jetzt bitte keine Paper über Programmflusskontrolle und Sprachoptimierung – Emulieren ist schon schwer genug; ich muss irgendwann fertigwerden ;)

Ich erreiche mit meiner Emulation bereits die 40-fache Leistung des Originals mit angehängtem Glide Wrapper. Trotzdem zeigt mir der Profiler, dass 8 % meiner Rechenzeit mit dem Kopieren der Funktionsparameter für die virtuellen Aufrufe verschwendet werden, obwohl es völlig unnötig ist. Hass.

Re: Jammer-Thread

Verfasst: 17.05.2012, 13:55
von dot
wtf :D

Wer macht denn sowas :shock:

Re: Jammer-Thread

Verfasst: 17.05.2012, 13:59
von CodingCat
dot hat geschrieben:Ja sowas geht per extern. Mit VC schon praktisch immer und seit C++11 auch im Standard, verwend ich ab und zu ganz gern...
Naja, mit extern geht das Ganze doch gerade wieder kaputt. Wir wollen hier schließlich einen implementierungsunabhängigen Header, und nicht für jede Spezialisierung noch einen redundanden extern-Header. Aber VC10 schluckt mein Beispiel von eben tatsächlich willig. In dieser Form sind Templates durchaus eine hübsche Alternative zu #ifdefs.

Re: Jammer-Thread

Verfasst: 17.05.2012, 14:07
von eXile
Krishty hat geschrieben:Es ist ein Dateiformat, das Bytecode enthält, der eine virtuelle Maschine kontrolliert, die den Rasterizer Vertex für Vertex steuert – durch 200 Opcodes inklusive Subroutinen; Schleifen; bedingter Sprünge; und allem anderen, was einem das Leben schwer macht.
Bild

Re: Jammer-Thread

Verfasst: 17.05.2012, 14:14
von CodingCat
what's changed in fxc from 9.29.952.3111 to 9.30.960.8229 (the one from win8 SDK) ?!

couse with 9.29.952.3111 (/O3 /Op /Gfp /Zpr /Tcs_5_0) all my compute shaders compile and run JUST FINE (about 70 different kernels - they all pass unit tests)
but with 9.30.960.8229 (/O3 /Op /Gfp /Zpr /Tcs_5_0) about 70% of my compute shaders FAILS that same unit tests !!!

they fail mainly around atomic operations on shared memory (and some of them on atomic on RWByteAddressBuffer) - the 'old' value returned from InterlockedAdd is total garbage
(looking at disassembly the return value in register is thrown away and the other unrelated register is taken as 'out' value by compiller)

few of them (purelly ALU kernels without atomics) fail on math operations (or index calculations for indexing ByteAddressBuffer - it's hard to tell without debugger ;])

http://forums.create.msdn.com/forums/t/103143.aspx
Ich glaube, damit ist DX 11.1 für mich erstmal wieder gestorben ...

Re: Jammer-Thread

Verfasst: 17.05.2012, 14:17
von Krishty
dot hat geschrieben:wtf :D

Wer macht denn sowas :shock:
Das muss vor 20 Jahren mal ziemlich effizient gewesen sein: Damals gab es keine Z-Buffer, und statt die Polygone im Programm zu sortieren, wurden sie zu Bytecode kompiliert, der sie je nach Betrachtungswinkel in der korrekten Zeichenreihenfolge ausspuckt. Und wenn man eh schon Sprünge drin hat, kann man auch Animationen u.Ä. damit realisieren und muss sich in der eigentlichen Programmlogik um nichts weiter kümmern, als ein paar Variablen hochzuzählen und die VM machen zu lassen.


Aaalso, bezüglich der Templates:

Das Template ist die Hauptschleife der virtuellen Maschine. Die ist ein riesiges fettes Stück von 8000 Zeilen; da hängen nochmal 2000 Zeilen privater Abhängigkeiten dran; und mit zunehmender Optimierung wird es auch immer mehr Text. Ich weigere mich deshalb vehement, die Definition in irgendeinen Header zu stecken – sie wird nur in logic.hpp deklariert:

template <bool debug> void run(IRasterizer & r);

Es gibt nun eine logic.cpp, in der sie definiert wird:

template <
    bool debug // 'if's mit globalen Variablen kosten 2,7 % Leistung gegenüber 'if's mit Template-Parametern, Branch Prediction und OOOE am Arsch
> void run(IRasterizer & r) {
    r.draw();
    // lots
    // of
    // fucking
    // complicated
    // stuff
}


Dort werden gleichzeitig Instanzierungen ausgelöst, damit die von den Übersetzungseinheiten, die sie aufrufen, gefunden werden können (fehlende spitze und runde Klammern beachten, da es sich nicht um Funktionsaufrufe oder Spezialisierungen handelt):

template void run<true>;
template void run<false>;


Schließlich, im GUI-Teil:

if(isInDebugMode) {
    run<true>(myRasterizer);
} else {
    run<false>(myRasterizer);
}


Nehmen wir rein hypothetisch an, ich machte nun den Rasterizer zu einem Template-Parameter, damit die Funktionsaufrufe nicht mehr durch die Schnittstelle gehen müssten. Das wäre bei der Deklaration der Funktion kein Problem; beim Aufruf auch nicht, weil ich dort den endgültigen Rasterizer-Typ kenne. Bei der Definition der Funktion flöge ich aber auf die Schnauze: Um das Template für den Rasterizer instanzieren zu können, brauche ich den Quelltext. Ich müsste also die Definition der VM-Template-Funktion aus der Logik herausziehen, und im Rasterizer- oder GUI-Quelltext mitsamt aller Abhängigkeiten #includen, um dort die Instanzierung mit dem definierten und bekannten Rasterizer als Template-Parameter auszulösen.

Möglich wäre es schon, aber ich würde es hassen. Das soll der Compiler für mich machen; der kennt sowieso das ganze Programm und muss sich nicht darum scheren, Logik und Rasterizer und GUI getrennt zu halten um in diesem Irrsinn nicht dem Wahnsinn zu verfallen …

Re: Jammer-Thread

Verfasst: 17.05.2012, 14:22
von CodingCat
Krishty hat geschrieben:Bei der Definition der Funktion flöge ich aber auf die Schnauze: Um das Template für den Rasterizer instanzieren zu können, brauche ich den Quelltext. Ich müsste also die Definition der VM-Template-Funktion aus der Logik herausziehen, und im Rasterizer- oder GUI-Quelltext mitsamt aller Abhängigkeiten #includen, um dort die Instanzierung mit dem definierten und bekannten Rasterizer als Template-Parameter auszulösen.
Ja, es sei denn, du begnügst dich mit Forward Declarations der Rasterizer-Implementierungen und freien Funktions-Templates. :|

Re: Jammer-Thread

Verfasst: 17.05.2012, 14:25
von Krishty
CodingCat hat geschrieben:es sei denn, du begnügst dich mit Forward Declarations der Rasterizer-Implementierungen und freien Funktions-Templates. :|
Kluges Kätzchen! Freie Funktionen und Funktionsparameter lassen sich perfekt vordeklarieren. Statt rasterizer.draw(vertex); müsste ich also draw(vertex, rasterizer); schreiben, könnte aber dafür die Implementierung der draw-Funktion zur Implementierung des Rasterizers verschieben. Clever. Kriegst auch ein Brekkie.

Re: Jammer-Thread

Verfasst: 17.05.2012, 15:27
von CodingCat
Jep. Das Grundproblem, das Klassen im C++-Modulsystem streng genommen unbrauchbar macht. :evil:

Re: Jammer-Thread

Verfasst: 17.05.2012, 15:36
von CodingCat
Die Debug Runtime meckert: Texture2D-HLSL-Objekte sind nicht kompatibel mit einelementigen Texture2DArray-Views. Tatsächlich funktioniert das aber prima, wie ich es von einer vernünftigen API auch erwartet hätte. Diese ganze Pseudoabstraktion steht mir bis hier oben, soll ich jetzt ernsthaft sämtlichen HLSL-Code für beide Fälle identisch kopieren? :twisted:

Re: Jammer-Thread

Verfasst: 17.05.2012, 16:40
von Artificial Mind
make CUDA Samples @ Linux hat geschrieben:/usr/bin/ld: warning: libnvidia-tls.so.280.13, needed by /usr/lib/nvidia-current/libGL.so, not found (try using -rpath or -rpath-link)
/usr/bin/ld: warning: libnvidia-glcore.so.280.13, needed by /usr/lib/nvidia-current/libGL.so, not found (try using -rpath or -rpath-link)
/usr/lib/nvidia-current/libGL.so: undefined reference to `_nv018tls'
...
Ich bekomme CUDA auf Linux nicht zum Laufen weil ich den 295er Treiber habe, aber CUDA anscheinend den 280er haben möchte ... oder irgend sowas. Wieso kann man auf Linux nichts einfaches haben? Wieso kann das nicht im Repo liegen und mit sudo apt-get install nvidia-cuda oder so ohne Probleme funktionieren ... gut wie man produktiv man auf Linux ist, wenn man irgendwas installieren möchte, was nicht im Repo ist.

EDIT: Ich bin über jeden Lösungsvorschlag erfreut!

Re: Jammer-Thread

Verfasst: 17.05.2012, 16:44
von simbad
Mach nen symbolischen link
ln -s <source> <destination>

Re: Jammer-Thread

Verfasst: 17.05.2012, 16:48
von Artificial Mind
und das ist ok, selbst wenn das unterschiedliche Versionen sind? Oo

Es schien nur ein Pfad in der ld.so.conf zu fehlen, denn die gewünschten Libs waren irgendwo bei CUDA dabei...

Re: Jammer-Thread

Verfasst: 17.05.2012, 16:59
von antisteo
Artificial Mind hat geschrieben:Wieso kann man auf Linux nichts einfaches haben? Wieso kann das nicht im Repo liegen und mit sudo apt-get install nvidia-cuda oder so ohne Probleme funktionieren ... gut wie man produktiv man auf Linux ist, wenn man irgendwas installieren möchte, was nicht im Repo ist.

EDIT: Ich bin über jeden Lösungsvorschlag erfreut!
Du kannst nicht alles haben.
Du kannst nicht erwarten, dass die OpenSource-Community dir proprietäre Treiber pflegt.
Lösungsvorschlag: An Mesa mitwirken, sodass NVIDIA auch einen OpenSource-Treiber für OpenCL/CUDA bekommt.

Re: Jammer-Thread

Verfasst: 17.05.2012, 17:07
von Artificial Mind
Ist es nicht auch in NVIDIAs Interesse, einen vernünftigen Support und einfachen Einstieg in CUDA zu haben, auch für Linux?

Deinen Lösungsvorschlag finde ich ok, sobald ich genügend Erfahrung habe, um auch wirklich eine Hilfe sein zu können, werde ich mir das auch ernsthaft überlegen.

Re: Jammer-Thread

Verfasst: 17.05.2012, 17:42
von antisteo
Artificial Mind hat geschrieben:Ist es nicht auch in NVIDIAs Interesse, einen vernünftigen Support und einfachen Einstieg in CUDA zu haben, auch für Linux?
Ja,
mit ihrem proprietären Treiber.
Artificial Mind hat geschrieben:Deinen Lösungsvorschlag finde ich ok, sobald ich genügend Erfahrung habe, um auch wirklich eine Hilfe sein zu können, werde ich mir das auch ernsthaft überlegen.
Feel free.
Der erste Schritt ist sowieso, den Sourcecode des bisherigen Treibers zu lesen und ein bisschen Daten-Mitschnitte zur Grafikkarte analysieren.

Re: Jammer-Thread

Verfasst: 18.05.2012, 19:23
von CodingCat
GPU Computing - wenn alles richtig aussieht, und doch nichts geht. Wie schön, dass man nicht reingucken kann (wenn NSight mal nicht abstürzt, zeigt es mir ausgerechnet das, was mich am wenigsten weiterbringt).
Stream Compaction
Stream Compaction