Häufig gestellte Fragen zu Direct3D 10

Dieser Artikel enthält einige der häufig gestellten Fragen zu Direct3D 10 aus der Sicht eines Entwicklers, der eine vorhandene Anwendung von Direct3D 9 (D3D9) zu Direct3D 10 (D3D10) portiert.

Konstantenpuffer

Was ist die beste Methode zum Aktualisieren von Konstantenpuffern?

UpdateSubresource und Map mit Discard sollten ungefähr die gleiche Geschwindigkeit aufweisen. Wählen Sie zwischen ihnen, je nachdem, welche die geringste Arbeitsspeichermenge kopiert. Wenn Ihre Daten bereits im Arbeitsspeicher in einem zusammenhängenden Block gespeichert sind, verwenden Sie UpdateSubresource. Wenn Sie Daten von anderen Orten sammeln müssen, verwenden Sie Zuordnung mit Verwerfen.

Was ist die schlechteste Art, Konstantenpuffer zu organisieren?

Die schlechteste Leistung wird erreicht, indem alle Konstanten für einen bestimmten Shader in einem Konstantenpuffer platziert werden. Dies ist zwar häufig die einfachste Möglichkeit zum Portieren von D3D9 zu D3D10, kann jedoch die Leistung beeinträchtigen. Betrachten Sie beispielsweise ein Szenario, das den folgenden Konstantenpuffer verwendet:

cbuffer VSGlobalsCB
{
    matrix  ViewProj;
    matrix  Bones[100];
    matrix  World;
    float   SpecPower;
    float4  BDRFCoefficients;
    float   AppTime;
    uint2   RenderTargetSize;
};

Der Puffer beträgt 6560 Bytes. Angenommen, es gibt eine Anwendung mit 1.000 Zu rendernden Objekten, von denen 100 Gitter und 900 statische Gitter sind. Nehmen Sie außerdem an, dass diese Anwendung schattenabbildend mit einer Lichtquelle verwendet. Dies bedeutet, dass es zwei Läufe gibt: einen für die aus dem Licht gerenderte Tiefenkarte und einen für den Vorwärtsrenderingdurchlauf. Dies führt zu 2000 Draw-Aufrufen. Obwohl nicht jeder Zeichnungsaufruf jeden Teil des Konstantenpuffers aktualisieren muss, wird der gesamte Konstantenpuffer trotzdem aktualisiert und an den Karte gesendet. Dies führt zu einer Aktualisierung von 13 MB Daten pro Frame (2000 Zeichenaufrufe mal 6560 KB).

Wie kann ich meine Konstantenpuffer am besten organisieren?

Die beste Möglichkeit besteht darin, Konstantenpuffer nach Updatehäufigkeit zu organisieren. Konstanten, die mit ähnlichen Häufigkeiten aktualisiert werden, sollten sich im gleichen Puffer befinden. Betrachten Sie beispielsweise das szenario, das unter "Was ist die schlechteste Methode zum Organisieren von Konstantenpuffern?", aber mit einem besseren konstanten Layout dargestellt wird:

cbuffer VSGlobalPerFrameCB
  { 
    float   AppTime; 
  };
cbuffer VSPerSkinnedCB
  { 
    matrix  Bones[100]; 
  };
cbuffer VSPerStaticCB
  {
    matrix  World;
  };
cbuffer VSPerPassCB
  {
    matrix  ViewProj;
    uint2   RenderTargetSize;
  };
cbuffer VSPerMaterialCB
  {
    float   SpecPower;
    float4  BDRFCoefficients;
  };    

Konstantenpuffer werden nach ihrer Updatehäufigkeit aufgeteilt, aber dies ist nur die Hälfte der Lösung. Die Anwendung muss die Konstantenpuffer ordnungsgemäß aktualisieren, um die Aufteilung in vollem Umfang nutzen zu können. Wir gehen von der gleichen Szene wie oben aus: 900 statische Gitter, 100 skinned meshes, one light pass, and one forward pass. Wir gehen auch davon aus, dass einige Konstantenpuffer pro Objekt gespeichert werden. Dies bedeutet, dass jedes Objekt entweder eine VSPerSkinnedCB oder eine VSPerStaticCB enthält, je nachdem, ob es skinned oder statisch ist. Dies geschieht, um eine Verdoppelung der Über die Pipeline gesendeten Matrizen zu vermeiden.

Wir teilen den Rahmen in drei Phasen auf. Die erste Phase ist der Anfang des Frames und beinhaltet kein Rendering, nur ständige Updates.

Frame beginnen

  • Aktualisieren von VSGlobalPerFrameCB für die Anwendungszeit (4 Byte)
  • Update 100 VSPerSkinnedCB für die 100 skinned-Objekte (640000 Bytes)
  • Aktualisieren von VSPerStaticCB für 900 statische Objekte (57600 Bytes)

Als Nächstes folgt der Schattenkartendurchlauf. Beachten Sie, dass der einzige Konstantenpuffer, der tatsächlich aktualisiert wird, VSPerPassCB ist. Alle anderen Konstantenpuffer wurden während des Startframedurchlaufs aktualisiert. Obwohl diese Konstantenpuffer weiterhin gebunden werden müssen, ist die Menge an Informationen, die an das Video Karte übergeben werden, minimal, da die Puffer bereits aktualisiert wurden.

Schattendurchlauf

  • Aktualisieren von VSPerPassCB (72 Byte)
  • Zeichnen von 100 skinned meshes (100 binds, no updates)
  • Zeichnen von 900 statischen Gittern (100 Bindungen, keine Updates)

Ebenso muss der Vorwärtsrenderingdurchlauf nur materialbezogene Daten aktualisieren, da er nicht pro Gitternetz gespeichert wurde. Wenn wir davon ausgehen, dass in der Szene 500 Materialien verwendet werden:

Vorwärtspass

  • Aktualisieren von VSPerPassCB (72 Byte)
  • Update 500 VSPerMaterialCBs (10000 Bytes)

Dies ergibt insgesamt nur 707 KB. Obwohl dies ein sehr erfundenes Szenario ist, veranschaulicht es, wie viel konstanter Aktualisierungsaufwand reduziert werden kann, indem Konstanten nach Häufigkeit von Updates sortiert werden.

Was geschieht, wenn ich nicht genügend Platz habe, um einzelne Konstantenpuffer für meine Gitter, Materialien usw. zu speichern?

Sie können immer ein mehrstufiges System von Konstantenpuffern verwenden. Erstellen Sie Konstantenpuffer mit variabler Größe (16 Bytes, 32 Bytes, 64 Bytes usw.) bis zur größten erforderlichen Konstantenpuffergröße. Wenn es an der Zeit ist, einen Konstantenpuffer an einen Shader zu binden, wählen Sie den kleinsten Konstantenpuffer aus, der die vom Shader benötigten Daten enthalten kann. Obwohl dieser Ansatz etwas weniger effizient ist, ist er ein guter Zwischenschritt.

Ich verwende konstanten Puffer zwischen verschiedenen Shadern. Ein Shader kann alle Konstanten verwenden, ein anderer kann jedoch einige der Konstanten verwenden. Was ist die beste Methode, um diese zu aktualisieren?

Ein Ansatz besteht darin, den Konstantenpuffer noch weiter aufzuteilen. Es kommt jedoch ein Punkt, an dem zu viele Konstantenpuffer gebunden sind. Verschieben Sie in diesem Fall die Konstanten, die wahrscheinlich von mehreren Shadern nicht verwendet werden, an das Ende des Konstantenpuffers. Verwenden Sie beim Abrufen der Variablendaten aus dem Shader das flag D3D10_SVF_USED aus dem D3D10_SHADER_VARIABLE_DESC, um zu bestimmen, ob die Variable verwendet wird. Indem Sie nicht verwendete Variablen am Ende des Konstantenpuffers platzieren, können Sie einen kleineren Puffer an den Shader binden, der diese Variablen nicht verwendet, wodurch die Updatekosten eingespart werden.

Um wie viel kann ich meine Bildfrequenz verbessern, wenn ich die Knochen meines Charakters nur einmal pro Frame hochlade, anstatt einmal pro Pass/Zeichnen?

Sie können die Bildfrequenz je nach Menge redundanter Daten zwischen 8 und 50 Prozent verbessern. Im schlimmsten Fall wird die Leistung nicht beeinträchtigt.

Wie viele Konstantenpuffer sollte ich gleichzeitig gebunden haben?

Binden Sie die minimale Anzahl von Konstantenpuffern, die benötigt werden, um alle Daten in den Shader zu erhalten. In einem realistischen Szenario ist fünf die empfohlene Anzahl von konstanten Puffern, die verwendet werden sollen. Die Gemeinsame Nutzung von Konstantenpuffern zwischen Shadern (Bindung derselben CB an VS und PS) kann auch die Leistung verbessern.

Fallen Kosten für das Binden von Konstantenpuffern an, ohne sie zu verwenden?

Ja, wenn Sie den Puffer nicht verwenden möchten, rufen Sie VSSetConsantBuffer oder PSSetConstantBuffer nicht auf. Dieser zusätzliche API-Mehraufwand kann sich im Laufe mehrerer Draw-Aufrufe summieren.

State

Wie kann der Zustand in D3D10 am besten verwaltet werden?

Die beste Lösung besteht darin, ihren gesamten Zustand im Voraus zu kennen und die Zustandsobjekte im Voraus zu erstellen. Dies bedeutet, dass zur Renderzeit die Zustandsbindung der einzige Vorgang ist, der ausgeführt werden muss. D3D10 filtert auch Duplikate aus.

Mein Spiel wurde dynamisch geladen oder enthält benutzergenerierte Inhalte. Ich kann nicht alle meine Zustandsobjekte im Voraus laden. Wie sollte ich vorgehen?

Hier gibt es zwei Lösungen. Die erste besteht darin, zustandsbehaftete Objekte direkt zu erstellen und D3D10 Duplikate herausfiltern zu lassen. Dies wird jedoch nicht für Szenarien mit vielen Zustandsobjektänderungen pro Frame empfohlen. Eine bessere Lösung besteht darin, die Zustandsobjekte selbst zu hashen und ein Zustandsobjekt nur dann zu erstellen, wenn eines, das den Anforderungen entspricht, in der Hashtabelle nicht gefunden wird. Der Grund für die Verwendung einer benutzerdefinierten Hashtabelle ist, dass eine Anwendung einen schnellen Hash basierend auf dem für diese Anwendung spezifischen Verwendungsszenario auswählen kann. Wenn eine Anwendung beispielsweise nur das rendertargetwritemask in BlendState ändert und alle anderen Werte gleich bleibt, kann die Anwendung einen Hash aus dem rendertargetwritemask anstelle der gesamten Struktur generieren.

Der AlphaTest-Zustand ist nicht mehr vorhanden. Wo ist denn das Repository?

AlphaTest sollte jetzt die Leistung im Shader aufweisen. Weitere Informationen finden Sie im FixedFuncEMU-Beispiel.

Was ist mit Clipebenen des Benutzers passiert?

Benutzerclipebenen wurden in den Shader verschoben. Es gibt zwei Möglichkeiten, dies zu behandeln. Die erste besteht darin, SV_ClipDistance aus dem Vertex-Shader oder dem Geometry-Shader auszugeben. Die andere Option besteht darin, das Verwerfen im Pixel-Shader basierend auf einem Wert zu verwenden, der vom Vertexshader oder dem Geometry-Shader übergeben wird. Experimentieren Sie mit beiden, um zu sehen, was für Ihr bestimmtes Szenario schneller ist. Die Verwendung von SV_ClipDistance kann dazu führen, dass die Hardware eine geometriebasierte Clippingroutine verwendet, die dazu führen kann, dass geometriegebundene Zeichnungsaufrufe langsamer ausgeführt werden. Ebenso verschiebt die Verwendung von Verwerfen die Arbeit auf den Pixelshader, was dazu führen kann, dass pixelgebundene Zeichnungsaufrufe langsamer ausgeführt werden.

Clears respektieren keine Zustandseinstellungen, z. B. meine Scissor Rect-Einstellungen in meinem Rasterisierungszustand.

Clears wurden vom Pipelinestatus getrennt. Um das Verhalten im D3D9-Stil zu erhalten, emulieren Sie Clears, indem Sie ein Vollbild-Quad zeichnen.

Ich setz meine Zustände wieder auf den Standardwert, um einen Renderingfehler zu diagnostizieren. Jetzt zeigt mein Bildschirm nur schwarz an, obwohl ich weiß, dass ich Objekte auf den Bildschirm ziehe.

Stellen Sie beim Zurücksetzen des Zustands auf Standardwerte (NULL) sicher, dass die SampleMask im Aufruf von OMSetBlendState nie 0 ist. Wenn SampleMask auf 0 festgelegt ist, werden alle Beispiele logisch UND mit 0 angegeben. In diesem Szenario bestehen keine Beispiele den Blendtest.

Wo ist der Zustand D3DSAMP\SRGBTEXTURE hin?

SRGB wurde als Teil des Samplerzustands entfernt und ist nun an das Texturformat gebunden. Das Binden einer SRGB-Textur führt zu derselben Stichprobenerstellung, die Sie erhalten würden, wenn Sie D3DSAMP_SRGBTEXTURE in Direct3D 9 angeben.

Formate

Welches D3D9-Format entspricht welchem D3D10-Format?

Weitere Informationen finden Sie unter Überlegungen zu Direct3D 9 zu Direct3D 10.

Was ist mit A8R8G8B8 Texturformaten passiert?

Sie sind in D3D10 veraltet. Sie können Ihre Texturen als R8G8B8A8 neu erstellen, oder Sie können beim Laden schwemmen, oder Sie können im Shader schwemmen.

Gewusst wie palettisierte Texturen verwenden?

Platzieren Sie Ihre Farbpalette in einer Textur oder einem Konstantenpuffer, und binden Sie sie an die Pipeline. Führen Sie im Pixel-Shader eine indirekte Suche mit dem Index in Ihrer palettisierten Textur aus.

Was sind diese neuen SRGB-Formate?

SRGB wurde als Teil des Samplerzustands entfernt und ist nun an das Texturformat gebunden. Das Binden einer SRGB-Textur führt zu derselben Stichprobenerstellung, die Sie erhalten würden, wenn Sie D3DSAMP_SRGBTEXTURE in Direct3D 9 angeben.

Wo sind Dreiecksfans hin?

Dreieckslüflüge sind in D3D10 veraltet. Dreieckslüflüge müssen entweder in der Inhaltspipeline oder beim Laden konvertiert werden.

Shaderverknüpfung

Meine Direct3D 9-Shader kompilieren sich gut zu ShaderModell 4.0, aber wenn ich sie an die Pipeline binde, erhalten ich Verknüpfungsfehler, die in der Debugausgabe mit der Debuglaufzeit angezeigt werden.

Shaderverknüpfung ist in D3D10 viel strenger. Elemente in einer nachfolgenden Phase müssen in der Reihenfolge gelesen werden, in der sie aus der vorherigen Phase ausgegeben werden. Beispiel:

Ein Vertex-Shader gibt Folgendes aus:

    float4 Pos  : SV_POSITION;
    float3 Norm : NORMAL;
    float2 Tex  : TEXCOORD0;

Ein Pixel-Shader liest Folgendes ein:

        float3 Norm : NORMAL;
        float2 Tex  : TEXCOORD0;

Obwohl die Position im Pixel-Shader nicht benötigt wird, führt dies zu einem Verknüpfungsfehler, da die Position vom Vertex-Shader ausgegeben, aber nicht vom Pixel-Shader gelesen wird. Die korrektere Version würde wie folgt aussehen:

Ein Vertex-Shader gibt Folgendes aus:

        float3 Norm : NORMAL;
        float2 Tex  : TEXCOORD0;
        float4 Pos  : SV_POSITION;

Ein Pixel-Shader liest Folgendes ein:

        float3 Norm : NORMAL;
        float2 Tex  : TEXCOORD0;

In diesem Fall gibt der Vertex-Shader dieselben Informationen aus, aber jetzt liest der Pixel-Shader Dinge in der Auftragsausgabe. Da der Pixel-Shader nach Tex nichts liest, müssen wir uns keine Sorgen machen, dass der VS mehr Informationen ausgibt, als der PS liest.

Ich benötige eine Shadersignatur, um ein Eingabelayout zu erstellen, aber ich lade meine Gitternetze und erstelle Layouts, bevor ich Shader erstelle. Wie gehe ich vor?

Eine Lösung besteht darin, die Reihenfolge zu ändern und Shader vor dem Laden von Gittern zu laden. Dies ist jedoch viel einfacher gesagt als getan. Sie können die Eingabelayouts jederzeit bei Bedarf erstellen, wenn sie von der Anwendung benötigt werden. Sie müssen eine Version der Shadersignatur beibehalten. Sie sollten einen Hash basierend auf dem Shader- und Pufferlayout erstellen und das Eingabelayout nur dann erstellen, wenn es noch nicht vorhanden ist.

Aufrufe zeichnen

Was ist mein Limit für Zeichnungsaufrufe für D3D10, um 60 Hz zu erreichen? 30 Hz?

Direct3D 9 hatte aufgrund der CPU-Kosten pro Draw-Aufruf eine Einschränkung für die Anzahl von Zeichnungsaufrufen. Bei Direct3D 10 wurden die Kosten für jeden Zeichnungsaufruf reduziert. Es gibt jedoch keine eindeutige Korrelation mehr zwischen Zeichnungsaufrufen und Bildraten. Da Draw-Aufrufe häufig viele Unterstützungsaufrufe erfordern (konstante Pufferaktualisierungen, Texturbindungen, Zustandseinstellungen usw.), ist die Auswirkung der Framerate der API jetzt stärker von der gesamten API-Nutzung abhängig, als einfach die Aufrufanzahl zu zeichnen.

Ressourcen

Welchen Ressourcennutzungstyp sollte ich für welche Vorgänge verwenden?

Verwenden Sie den folgenden Spickzettel:

  • Die CPU aktualisiert die Ressource mehrmals pro Frame: D3D10_USAGE_DYNAMIC
  • Die CPU aktualisiert die Ressource weniger als einmal pro Frame: D3D10_USAGE_DEFAULT
  • Die CPU aktualisiert die Ressource nicht: D3D10_USAGE_IMMUTABLE
  • Die CPU muss die Ressource lesen: D3D10_USAGE_STAGING

Da Konstantenpuffer immer regelmäßig aktualisiert werden sollen, entsprechen sie nicht dem "Spickzettel". Welche Ressourcentypen für Konstantenpuffer verwendet werden sollen, finden Sie im Abschnitt Konstantenpuffer .

Was ist mit DrawPrimitiveUP und DrawIndexedPrimitiveUP passiert?

Sie sind in D3D10 nicht mehr vorhanden. Verwenden Sie für dynamische Geometrie einen großen D3D10_USAGE_DYNAMIC Puffer. Ordnen Sie ihn am Anfang des Frames mit D3D10_MAP_WRITE_DISCARD zu. Bei jedem nachfolgenden Zeichnungsaufruf wird der Schreibzeiger über die Position der zuvor gezeichneten Scheitelpunkte herübergezogen und dem Puffer D3D10_MAP_WRITE_NO_OVERWRITE zugeordnet. Wenn Sie sich dem Ende des Puffers vor dem Ende des Frames nähern, umschließen Sie den Schreibzeiger auf den Anfang, und ordnen Sie D3D10_MAP_WRITE_DISCARD zu.

Kann ich 16-Bit- und 32-Bit-Indizes in denselben dynamischen Geometriepuffer schreiben?

Ja, das ist möglich, aber dies kann für bestimmte Hardware zu Leistungseinbußen führen. Es ist sicherer, separate Puffer für dynamische 16-Bit-Indexdaten und 32-Bit-Indexdaten zu erstellen.

Gewusst wie Daten von der GPU an die CPU zurücklesen?

Sie müssen eine Stagingressource verwenden. Kopieren Sie die Daten aus der GPU-Ressource mithilfe von CopyResource in die Stagingressource. Ordnen Sie die Stagingressource zum Lesen der Daten zu.

Meine Anwendung war von der StretchRect-Funktionalität abhängig.

Da dies im Wesentlichen ein Wrapper für grundlegende Direct3D-Funktionen war, wurde es aus der API entfernt. Ein Teil der StretchRect-Funktionalität wurde in D3DX10LoadTextureFromTexture verschoben. Für Formatkonvertierungen und Kopieren von Texturen kann D3DX10LoadTextureFromTexture den Auftrag ausführen. Vorgänge wie das Konvertieren von einer Größe in eine andere erfordern jedoch wahrscheinlich einen Render-in-Textur-Vorgang in der Anwendung.

Es gibt keine Offsets oder Größen für Zuordnungsaufrufe für Ressourcen. Diese gab es bei Sperranrufen auf Direct3D 9; warum haben sie sich geändert?

Die Offsets und Größen für Lock-Aufrufe in Direct3D 9 waren im Grunde API-Unordnung und wurden vom Treiber häufig ignoriert. Offsets sollten stattdessen von der Anwendung aus dem im Map-Aufruf zurückgegebenen Zeiger berechnet werden.

Tiefe als Textur

Was ist schneller? Verwenden Sie Tiefe als Textur oder Schreibtiefe für Alpha und lesen Sie das?

Dies ist anwendungs- und hardwarespezifisch. Verwenden Sie, je nachdem, was die meiste Bandbreite spart. Wenn Sie bereits mehrere Renderziele verwenden und über einen zusätzlichen Kanal verfügen, ist die Schreibtiefe aus dem Shader möglicherweise eine bessere Lösung. Außerdem können Sie durch Schreiben der Tiefe in alpha oder ein anderes Renderziel lineare Tiefenwerte schreiben, die Berechnungen beschleunigen können, die auf den Tiefenpuffer zugreifen müssen.

Kann ich eine Textur als Eingabe und als Tiefenschablonentextur gebunden lassen, solange ich Tiefenschreibvorgänge deaktiviere?

Nicht in D3D10.

MSAA

Kann ich eine MSAA-Tiefenschablonentextur auflösen?

Nicht in D3D10. Sie können jedoch einzelne Beispiele aus der MSAA-Textur probieren. Weitere Informationen finden Sie im Abschnitt HLSL .

Warum stürzt meine Anwendung ab, sobald ich MSAA aktiviert habe?

Stellen Sie sicher, dass Sie eine MSAA-Beispielanzahl und -Qualitätsnummer aktivieren, die tatsächlich vom Treiber aufgezählt werden.

Crashes

Meine Anwendung stürzt in D3D10 oder im Treiber ab, und ich weiß nicht, warum.

Der erste Schritt besteht darin, die Debuglaufzeit zu aktivieren (D3D10_CREATE_DEVICE_DEBUG Flag, das an D3D10CreateDevice übergeben wird). Dadurch werden die häufigsten Fehler als Debugausgabe verfügbar gemacht.

PIX stürzt ab, wenn ich versuche, meine Anwendung damit zu verwenden.

Der erste Schritt besteht darin, die Debugruntime zu aktivieren (D3D10_CREATE_DEVICE_DEBUG Flag, das an D3D10CreateDevice übergeben wird). PIX hat eine viel höhere Wahrscheinlichkeit, dass abstürzt, wenn die Debugausgabe nicht sauber ist.

Mein Spiel hat unter D3D10 auf 32-Bit Vista keine virtuellen Adressräume mehr. Bei D3D9 gibt es keine Probleme.

Es gab einige Probleme mit D3D10 und dem virtuellen Adressraum. Dies wurde in KB940105 behoben. Wenn das Problem dadurch nicht behoben wird, stellen Sie sicher, dass Sie nicht mehr Ressourcen erstellen, die in D3D10 zugeordnet (gesperrt) werden können, als Sie in D3D9 erstellt haben. Denken Sie auch an die Portierung zu 64-Bit, da dies in Zukunft häufiger vorkommen wird.

Prädiziertes Rendering

Ich habe prädiziertes Rendering verwendet (basierend auf Okklusionsabfrageergebnissen). Warum ist meine App immer noch die gleiche Geschwindigkeit?

Stellen Sie zunächst sicher, dass das Rendering, das Sie überspringen möchten, tatsächlich der Anwendungsengpass ist. Wenn es sich nicht um den Engpass handelt, hilft das Überspringen des Renderings nicht bei der Bildfrequenz.

Stellen Sie zweitens sicher, dass zwischen dem Problem der Abfrage und dem Rendering, das Sie prädikatieren möchten, genügend Zeit vergangen ist. Wenn die Abfrage noch nicht abgeschlossen ist, bis der Renderaufruf auf die GPU trifft, erfolgt das Rendering trotzdem.

Drittens überspringt die Prädierung nur bestimmte Aufrufe. Die Aufrufe, die übersprungen werden, sind Draw, Clear, Copy, Update, ResolveSubresource und GenerateMips. Zustandseinstellungen, IA-Setup, Zuordnungs- und Create-Aufrufe berücksichtigen keine Prädication. Wenn es viele Zustandseinstellungsaufrufe um den zu prädizierten Zeichnungsaufruf gibt, werden diese Zustände weiterhin festgelegt.

Geometrie-Shader

Soll ich den Geometry-Shader verwenden, um meine zu tesseln (hier etwas einfügen)?

Nein. Der Geometry-Shader sollte NICHT für die Tessellation verwendet werden.

Kann ich den geometrie-Shader verwenden, um Geometrie zu erstellen?

Ja, in sehr begrenzten Szenarien. Der Geometrieshader in den aktuellen D3D10 (2008) Teilen ist nicht für viele Erweiterungen ausgestattet. Dies kann sich in Zukunft ändern. Video Karte Anbieter haben aufgrund vorhandener Point-Sprite-Hardware möglicherweise einen speziellen Pfad für ein bis vier Erweiterungen. Jede andere Erweiterung müsste sehr begrenzt sein. Die Samples ParticlesGS und PipesGS erreichen hohe Bildfrequenzen, indem sie nur eine begrenzte Erweiterung durchführen. Pro Frame werden nur wenige Punkte erweitert.

Wofür sollte ich den Geometry-Shader verwenden?

Alles, was Vorgänge für einen gesamten Grundtyp erfordert, z. B. Silhouettenerkennung, baryzentrische Koordinaten usw. Verwenden Sie sie auch, um auszuwählen, an welchen Slice eines Renderzielarrays Grundtypen gesendet werden sollen.

Kann ich variable Geometriemengen aus dem Geometrie-Shader ausgeben?

Ja, aber dies kann zu Leistungsproblemen führen. Nehmen wir das Beispiel der Ausgabe von 1 Punkt für einen Aufruf und 4 Punkte für einen anderen Aufruf. Dies entspricht zwar den Erweiterungsrichtlinien, kann jedoch dazu führen, dass die Geometrie-Shaderthreads seriell ausgeführt werden.

Woher weiß D3D10, wie man Adjacencyindizes für mein Gitter generiert? Oder warum wird D3D10 nicht ordnungsgemäß gerendert, wenn ich anspeziere, dass der Geometrie-Shader Adjacency-Informationen benötigt?

Die Adjacency-Informationen werden nicht von D3D10, sondern von der Anwendung erstellt. Adjacencyindizes werden von der Anwendung generiert und müssen sechs Indizes pro Grundtyp enthalten; der sechs sind die ungeraden nummerierten Indizes die randanliegenden Scheitelpunkte. Id3DX10Mesh::GenerateAdjacencyAndPointsReps kann verwendet werden, um diese Daten zu generieren.

HLSL

Sind ganzzahlige und bitweise Anweisungen langsam?

Sie können sein. Verschiedene D3D10-Karten können möglicherweise nur ganzzahlige Vorgänge für eine Teilmenge der verfügbaren ALU-Einheiten ausgeben. Dies hängt stark von der Hardware ab. Empfehlungen zum Behandeln ganzzahliger Vorgänge auf dieser hardwarebasierten Hardware finden Sie von Ihrem jeweiligen Hardwarehersteller. Achten Sie auch sehr auf Umwandlungen zwischen Typen.

Was ist mit VPOS passiert?

Wenn Sie eine Eingabe für Ihren Pixelshader als SV_POSITION deklarieren, erhalten Sie das gleiche Verhalten wie beim Deklarieren als VPOS.

Gewusst wie eine MSAA-Textur?

Deklarieren Sie Ihre Textur in Ihrem Shader als Texture2DMS. Anschließend können Sie einzelne Beispiele mithilfe der Sample-Methoden aus dem Texture2DMS-Objekt abrufen.

Gewusst wie feststellen, ob tatsächlich eine Shadervariable in einem Konstantenpuffer verwendet wird?

Sehen Sie sich die reflektierte D3D10_SHADER_VARIABLE_DESC Struktur für diese Variable an. Für uFlags sollte das flag D3D10_SVF_USED festgelegt sein.

Gewusst wie feststellen, ob eine Shadervariable in einem Konstantenpuffer tatsächlich FX10 verwendet?

Dies ist derzeit mit FX10 nicht möglich.

Ich habe keine Kontrolle über Konstantenpuffer, die FX10 erstellt. Wie werden sie erstellt und aktualisiert?

Alle von FX10 verwalteten Konstantenpuffer werden als D3D10_USAGE_DEFAULT-Ressourcen erstellt und mithilfe von UpdateSubresource aktualisiert. Da FX10 einen Sicherungsspeicher für alle konstanten Daten behält, ist UpdateSubresource der beste Ansatz für die Aktualisierung dieser Daten.

Gewusst wie die Pipeline für feste Funktionen mithilfe von Shadern emulieren?

Siehe FixedFuncEMU-Beispiel.

Sollte ich die neuen Compilerhinweise \[unroll\], \[loop\], \[branch\] usw. verwenden?

Im Allgemeinen nicht. Der Compiler versucht häufig beide Methoden und wählt die schnellste. In einigen Fällen kann die Verwendung von [unroll] erforderlich sein, z. B. wenn ein Texturabruf innerhalb einer Schleife Zugriff auf einen Farbverlauf benötigt.

Macht die Partielle Genauigkeit bei D3D10 einen Unterschied? Ich kann die Teilgenauigkeit in meinem D3D9 HLSL angeben, aber nicht in meinem D3D10 HLSL.

Alle D3D10-Vorgänge werden für die Ausführung mit einer Gleitkommagenauigkeit von 32 Bit angegeben. Daher sollte die partielle Genauigkeit in D3D10 keinen Unterschied machen.

In D3D9 konnte ich HW PCF-Schattenfilterung durchführen, indem ich einen Tiefenpuffer als Textur bindet und reguläre tex2d hlsl-Anweisungen verwende. Gewusst wie auf D3D10?

Sie müssen einen Vergleichs-Samplerzustand verwenden und sampleCmp-Anweisungen verwenden.

Wie funktioniert diese Registrierung Schlüsselwort (keyword) in D3D10?

Das Register Schlüsselwort (keyword) in D3D10 gilt jetzt für den Slot, an den eine bestimmte Ressource gebunden ist. In diesem Fall kann es sich bei der Ressource um einen Puffer (konstant oder anderweitig), Textur oder Sampler handeln.

  • Verwenden Sie für Konstantenpuffer die Syntax register(bN), wobei N der Eingabeslot ist (0-15).
  • Verwenden Sie für Texturen die Syntax register(tN), wobei N der Eingabeslot ist (0-127).
  • Verwenden Sie für Sampler die Syntax register(sN), wobei N der Eingabeslot ist (0-127).

Gewusst wie eine Variable in einem Konstantenpuffer platzieren, wenn register nur verwendet wird, um anzugeben, wo der gesamte Puffer gebunden werden soll?

Verwenden Sie die packoffset-Schlüsselwort (keyword). Das Argument für packoffset hat die Form c[0-4095]. [x,y,z,w]. Beispiel:

        cbuffer cbLotsOfEmptySpace
        {
        float   IWaste2Floats   : packoffset(c0.z);
        float4  IWasteMore  : packoffset(c13);
        };

In diesem Konstantenpuffer wird IWaste2Floats am dritten Float (12. Byte) im Konstantenpuffer platziert. IWasteMore wird am 13. float4 oder 52. Float im Konstantenpuffer platziert.