Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!
Ich wollte ein Programm basteln welches alle Sekunde zwischen 1 und 50 Vertices und deren Positionen/Farbe zufällig generiert und in den Vertexbuffer schreibt.
Leider "flackert" die Anzeige: Mal sieht man das Standardface, welches ich zu Beginn übergene, mal sehe ich nichts.
Das ist die idealte Gelegenheit, Cryteks neue Open-Source Software Renderdoc zu testen, da Microsoft PIX (DX SDK) in der Version 2010 abstürzt.
Los gehts!
Zunächst erstelle ich mir gemäß Microsofts Vorgehensweise einen dynamischen Vertexbuffer:
Im Debugmodus "flackert" die Anzeige: Mal sehe ich EIN Dreieck, mal sehe ich einen schwarzen Strich.
Das liegt vielleicht an der Ausführungsgeschwindigkeit... mal sehen
In Renderdoc flackert nichts, jedoch sehe ich nach wie vor nur EIN Dreieck...
Wobei es doch bis zu 100 sein sollen...
So siehts aus:
Verdächtig ist, dass angeblich 120 Vertices (40 Dreiecke) gerendert werden, wobei doch nur 3 Vertices im Input Assembler landen...
"Das Glück des Forschers besteht nicht darin, die Wahrheit zu besitzen, sondern eine Wahrheit zu erringen. Und in diesem fortschreitendem, erfolgreichen Suchen nach der Wahrheit - darin liegt die
eigentliche Befriedigung." Max Planck
Dein Vertexbuffer ist viel zu klein (m_BufferDesc.ByteWidth = sizeof(SVertexType) * 3; // 3?), außerdem kopierst du nicht den kompletten Pufferinhalt:
Quellcode
1
memcpy(ms.pData, vertices, sizeof(vertices))
Beachte, dass sizeof(vertices) hier die größe eines Zeigers liefert.
Quellcode
1
2
3
4
5
6
7
8
9
const size_t bufferSizeInBytes = random * 3 * sizeof(SVertexType);
// fill buffer with random data
if (SUCCEEDED(context->Map(m_VertexBuffer, NULL, D3D11_MAP_WRITE_DISCARD, NULL, &ms)))
{
memcpy(ms.pData, vertices, bufferSizeInBytes);
context->Unmap(m_VertexBuffer, NULL);
}
Und achte darauf den Vertexpuffer groß genug zu allozieren.
"Das Glück des Forschers besteht nicht darin, die Wahrheit zu besitzen, sondern eine Wahrheit zu erringen. Und in diesem fortschreitendem, erfolgreichen Suchen nach der Wahrheit - darin liegt die
eigentliche Befriedigung." Max Planck
den dynamischen Puffer pro Frame mit "discard" zu mappen kann zu ziemlich drastischen Performanzproblemen führen, da der Puffer nicht überschrieben werden darf, wenn die Resource noch von der GPU verwendet wird. In diesem Fall findet ein 'buffer-renaming' statt, d.h. DX stellt dir einen anderen Puffer zur Verfügung. Wenn dein Puffer hinreichend klein ist (z.B. < 4 MB) dann kann es sein, dass der Puffer intern von DX etwas größer angelegt wird und bei jedem 'rename' einfach ein Offset auf den ursprünglichen Zeiger addiert wird. Schlimmer ist es, wenn der interne Speicher komplett aufgebraucht wurde, dann muss ein neuer Puffer alloziert werden und dein Programm wird kurzfristig blockiert.
Ich weiß nicht genau was du tun willst und ob Performanz tatsächlich ein wichtiges Kriterium für dich ist. Aber falls doch, oder falls du dich einfach dafür interessierst:
Es kann von Vorteil sein den Puffer selbst etwas größer zu allozieren (z.B. 3x so groß) und das Offset-Management selbst durchzufüren. D.h. jeden 3x Frame wird der Puffer 'discarded' und dazwischen mit 'MAP_WRITE_NO_OVERWRITE' gemapped. Dadurch verhinderst du (oder verminderst zumindest) das der Puffer voll läuft und komplett neu alloziert werden muss.