Shadermodell 3 (HLSL-Referenz)
Vertex-Shader und Pixelshader werden von früheren Shaderversionen erheblich vereinfacht. Wenn Sie Shader in der Hardware implementieren, verwenden Sie möglicherweise nicht vs_3_0 oder ps_3_0 mit anderen Shaderversionen, und Sie verwenden keinen Shadertyp mit der Pipeline für feste Funktionen. Diese Änderungen ermöglichen die Vereinfachung von Treibern und der Laufzeit. Die einzige Ausnahme besteht darin, dass softwaregeschützte vs_3_0-Shader mit einer beliebigen Pixelshaderversion verwendet werden können. Wenn Sie einen softwaregeschützten vs_3_0 Shader mit einer vorherigen Pixelshaderversion verwenden, kann der Vertex-Shader nur Ausgabesemantik verwenden, die mit FVF-Codes (Flexible Vertex Format) kompatibel sind.
Die für Vertex-Shaderausgaben verwendete Semantik muss für Pixelshadereingaben verwendet werden. Die Semantik wird verwendet, um die Vertex-Shaderausgabe den Pixel-Shadereingaben zuzuordnen, ähnlich wie die Vertexdeklaration den Vertex-Shadereingaberegistern und vorherigen Shadermodellen zugeordnet wird. Siehe "Abgleichsemantik" in vs. 3.0 und ps 3.0-Shadern.
Zusätzliche Renderzustände im Umbruchmodus wurden hinzugefügt, um die Möglichkeit zusätzlicher Texturkoordinaten in diesem neuen Schema abzudecken. Attribute mit D3DDECLUSAGE_TEXCOORD und Verwendungsindex von 0 bis 15 werden im Umbruchmodus interpoliert, wenn die entsprechende D3DRS_WRAP*- festgelegt wird.
- Vertexshadermodell 3 Features
- Pixelshadermodell 3 Features
- Semantik für vs_3_0 und ps_3_0 Shader
- Änderung des Nebel-, Tiefen- und Schattierungsmodus
- Gleitkomma- und Ganzzahlkonvertierungen
- Angeben der vollständigen oder teilweisen Genauigkeit
- Software-Vertex- und Pixelshader-
Features des Vertex-Shadermodells 3
Die Ausgaberegistertypen des Vertex-Shaders wurden in zwölf Register reduziert (siehe Ausgaberegister). Jedes verwendete Register muss mithilfe der dcl- Anweisung und einer Semantik deklariert werden (z. B. dcl_color0 o0.xyzw).
Das 3_0-Vertex-Shadermodell (vs_3_0) erweitert die Features von vs_2_0 mit leistungsstärkerer Registerindizierung, einer Reihe vereinfachter Ausgaberegister, der Möglichkeit, eine Textur in einem Vertex-Shader zu testen und die Rate zu steuern, mit der Shadereingaben initialisiert werden.
Indizierung eines registers
Alle Register( Eingaberegister und Ausgaberegister) können mithilfe Loop Counter Register indiziert werden (nur Konstantenregister können in früheren Versionen indiziert werden.)
Sie müssen Eingabe- und Ausgaberegister deklarieren, bevor Sie sie indizieren. Sie dürfen jedoch kein Ausgaberegister indiziert, das mit einer Positions- oder Punktgrößensemantik deklariert wurde. Wenn die Indizierung verwendet wird, müssen die Position und psize-Semantik in den Registern o0 bzw. o1 deklariert werden.
Sie dürfen nur einen fortlaufenden Bereich von Registern indizieren; Das heißt, Sie können keine Indizierung über Register durchführen, die nicht deklariert wurden. Diese Einschränkung kann zwar unannelich sein, die Hardwareoptimierung kann jedoch erfolgen. Der Versuch, über nicht zusammenhängende Register hinweg indiziert zu werden, führt zu nicht definierten Ergebnissen. Die Shaderüberprüfung erzwingt diese Einschränkung nicht.
Vereinfachen von Ausgaberegistern
Alle verschiedenen Ausgaberegister wurden in zwölf Ausgaberegister reduziert: 1 für Position, 2 für Farbe, 8 für Textur und 1 für Nebel oder Punktgröße. Diese Register interpolieren alle Daten, die sie für den Pixelshader enthalten. Ausgaberegisterdeklarationen sind erforderlich, und jeder Registrierung werden Semantik zugewiesen.
Die Register können wie folgt aufgeteilt werden:
- Mindestens ein Register muss als Vierkomponentenpositionsregister deklariert werden. Dies ist das einzige Vertex-Shaderregister, das erforderlich ist.
- Die ersten zehn von einem Shader verbrauchten Register können maximal vier Komponenten (xyzw) verwenden.
- Das letzte (oder zwölfte) Register darf nur einen Skalar (z. B. Punktgröße) enthalten.
Eine Auflistung der Register finden Sie unter Register - vs_3_0.
Texturbeispiel in einem Vertex-Shader
Vertex-Shader 3_0 unterstützt die Textursuche im Vertex-Shader mit texldl - vs.
Features des Pixelshadermodells 3
Die Pixelshaderfarb- und Texturregister wurden in zehn Eingaberegister reduziert (siehe Eingaberegistertypen). Das Face Register ist ein Gleitkommaskaerregister. Nur das Zeichen dieses Registers ist gültig. Wenn das Vorzeichen negativ ist, ist der Grundtyp eine Rückseite. Dies kann in einem Pixelshader verwendet werden, um beispielsweise zweiseitige Beleuchtung zu erzielen. Das Positionsregister verweist auf die aktuellen Pixel (x,y).
Die Shaderkonstantenregister können mithilfe von:
Abgleichen der Semantik für vs_3_0 und ps_3_0-Shader
Es gibt einige Einschränkungen für die semantische Verwendung mit vs_3_0 und ps_3_0. Im Allgemeinen müssen Sie vorsichtig sein, wenn Sie eine Semantik für eine Shadereingabe verwenden, die mit einer Semantik übereinstimmt, die für eine Shaderausgabe verwendet wird.
Dieser Pixelshader packt beispielsweise mehrere Namen in einem Register:
ps_3_0
dcl_texcoord0 v0.x
dcl_texcoord1 v0.yz // Valid to pack multiple names into one register
dcl_texcoord2_centroid v1.w
...
Jedes Register weist eine andere Semantik auf. Beachten Sie, dass Sie aufgrund der Verwendung des Schreibformats auch v0.x und v0.yz eine andere (mehrfache) Semantik benennen können.
Angesichts des Pixelshadrs kann der folgende vs_3_0-Shader nicht mit ihm gekoppelt werden:
vs_3_0
...
dcl_texcoord0 o5.x
dcl_texcoord1 o6.yzw
...
Diese beiden Shader haben einen Konflikt mit der Verwendung der D3DDECLUSAGE_TEXCOORD0 Und D3DDECLUSAGE_TEXCOORD1 Semantik.
Schreiben Sie den Vertex-Shader wie folgt um, um die semantische Kollision zu vermeiden:
vs_3_0
...
dcl_texcoord2 o3
dcl_texcoord3 o9
...
Ebenso kann ein semantischer Name, der für verschiedene Eingaberegister im Pixelshader (v0 und v1 im Pixelshader) deklariert ist, nicht in einem einzigen Ausgaberegister in diesem Vertex-Shader verwendet werden. Beispielsweise kann dieser Vertex-Shader nicht mit dem Pixelshader gekoppelt werden, da D3DDECLUSAGE_TEXCOORD1 sowohl für Pixelshadereingaberegister (v0, v1) als auch für das Ausgaberegister des Vertex-Shaders o3 verwendet wird.
vs_3_0
...
dcl_texcoord0 o3.x
dcl_texcoord1 o3.yz
dcl_texcoord2 o3.w // BAD! Would be valid if this were not o3
dcl_texcoord3 o9 ...
Andererseits kann dieser Vertex-Shader nicht mit dem Pixelshader gekoppelt werden, da das Ausgabeformat für einen Parameter mit einer bestimmten Semantik nicht die Daten bereitstellt, die vom Pixelshader angefordert werden:
vs_3_0
...
dcl_texcoord0 o5.x
dcl_texcoord1 o5.yzw
dcl_texcoord2 o7.yz // BAD! Would be valid if w were included
dcl_texcoord3 o9
...
Dieser Vertex-Shader stellt keine Ausgabe mit einem der vom Pixelshader angeforderten semantischen Namen bereit, sodass die Shaderpaarung ungültig ist:
vs_3_0
...
dcl_texcoord0 o5.x
dcl_texcoord1 o5.yzw
dcl_texcoord3 o9
// The pixel shader wants texcoord2, with a w component,
// but it isn't output by this vertex shader at all!
...
Änderungen im Nebel-, Tiefen- und Schattierungsmodus
Wenn D3DRS_SHADEMODE während der Beschneidung und Dreiecksrasterung für flache Schattierung festgelegt wird, werden Attribute mit D3DDECLUSAGE_COLOR als flach schattiert interpoliert. Wenn Komponenten eines Registers mit einer Farbsemantik deklariert werden, aber anderen Komponenten desselben Registers unterschiedliche Semantik zugewiesen werden, werden flache Schattierungsinterpolation (linear oder flach) für die Komponenten in diesem Register ohne Farbsemantik nicht definiert.
Wenn das Rendern von Nebel gewünscht ist, müssen vs_3_0 und ps_3_0 Shader Nebel implementieren. Außerhalb der Shader werden keine Nebelberechnungen durchgeführt. Es gibt kein Nebelregister in vs_3_0, und zusätzliche Semantik D3DDECLUSAGE_FOG (für den pro Vertex berechneten Nebelfaktor) und D3DDECLUSAGE_DEPTH (zum Übergeben eines Tiefenwerts an den Pixelshader zum Berechnen des Nebelmischungsfaktors) wurden hinzugefügt.
Der Zustand der Texturstufe D3DTSS_TEXCOORDINDEX wird ignoriert, wenn Der Pixelshader 3.0 verwendet wird.
Die folgenden Werte wurden hinzugefügt, um diese Änderungen zu berücksichtigen:
// Fog and Depth usages
D3DDECLUSAGE_FOG
D3DDECLUSAGE_DEPTH
// Additional wrap states for vs_3_0 attributes with D3DDECLUSAGE_TEXCOORD
D3DRS_WRAP8
D3DRS_WRAP9
D3DRS_WRAP10
D3DRS_WRAP11
D3DRS_WRAP12
D3DRS_WRAP13
D3DRS_WRAP14
D3DRS_WRAP15
Gleitkomma- und Ganzzahlkonvertierungen
Gleitkommagleichung erfolgt in unterschiedlichen Bereichen (16-Bit, 24-Bit und 32-Bit) in verschiedenen Teilen der Pipeline. Ein Wert, der größer als der dynamische Bereich der Pipeline ist, der diese Pipeline eingibt (z. B. wird eine 32-Bit-Float-Texturzuordnung in einer 24-Bit-Float-Pipeline in ps_2_0) ein nicht definiertes Ergebnis erstellt. Für ein vorhersagbares Verhalten sollten Sie einen solchen Wert auf den maximalen dynamischen Bereich klammern.
Die Konvertierung von einem Gleitkommawert in eine ganze Zahl erfolgt an mehreren Stellen, z. B.:
- Bei begegnungen einer mova - vs Anweisung.
- Während der Texturadressierung.
- Beim Schreiben in ein Nicht-Gleitkomma-Renderziel.
Angeben der vollständigen oder teilweisen Genauigkeit
Sowohl ps_3_0 als auch ps_2_x bieten Unterstützung für zwei Genauigkeitsebenen:
ps_3_0 | ps_2_0 | Präzision | Wert |
---|---|---|---|
x | Voll | fp32 oder höher | |
x | Teilweise Genauigkeit | fp16=s10e5 | |
x | x | Voll | fp24=s16e7 oder höher |
x | x | Teilweise Genauigkeit | fp16=s10e5 |
ps_3_0 unterstützt mehr Genauigkeit als ps_2_0. Standardmäßig treten alle Vorgänge auf der vollständigen Genauigkeitsebene auf.
Partielle Genauigkeit (siehe Pixelshader register Modifiers) wird durch Hinzufügen des _pp Modifizierers zum Shadercode angefordert (sofern die zugrunde liegende Implementierung sie unterstützt). Implementierungen können den Modifizierer immer ignorieren und die betroffenen Vorgänge in voller Genauigkeit ausführen.
Der _pp Modifizierer kann in zwei Kontexten auftreten:
- Übergeben Sie bei einer Texturkoordinatendeklaration Texturkoordinaten mit teilweiser Genauigkeit an den Pixelshader. Dies könnte verwendet werden, wenn Texturkoordinaten Farbdaten an den Pixelshader weiterleiten, was bei einigen Implementierungen möglicherweise schneller mit teilweiser Genauigkeit als mit voller Genauigkeit sein kann.
- Bei jeder Anweisung zum Anfordern der Verwendung von teilweiser Genauigkeit, einschließlich Texturladeanweisungen. Dies gibt an, dass die Implementierung die Anweisung mit teilweiser Genauigkeit ausführen und ein Teilgenauigkeitsergebnis speichern darf. Wenn kein expliziter Modifizierer vorhanden ist, muss die Anweisung mit voller Genauigkeit ausgeführt werden (unabhängig von der Genauigkeit der Eingabeopernden).
Eine Anwendung kann absichtlich entscheiden, die Präzision für die Leistung abzuwägen. Es gibt verschiedene Arten von Shadereingabedaten, die natürliche Kandidaten für die teilweise Genauigkeitsverarbeitung sind:
- Farb iteratoren werden gut durch Teilgenauigkeitswerte dargestellt.
- Texturwerte aus den meisten Formaten können durch Teilgenauigkeitswerte exakt dargestellt werden (Werte, die aus 32-Bit-, Gleitkommaformattexturen entnommen werden, sind eine offensichtliche Ausnahme).
- Konstanten können durch partielle Genauigkeitsdarstellung für den Shader dargestellt werden.
In all diesen Fällen kann der Entwickler die teilweise Genauigkeit angeben, um die Daten zu verarbeiten, und zu wissen, dass keine Eingabedatengenauigkeit verloren geht. In einigen Fällen kann ein Shader erfordern, dass die internen Schritte einer Berechnung mit voller Genauigkeit ausgeführt werden, auch wenn Eingabe- und Endausgabewerte nicht mehr als teilweise Genauigkeit aufweisen.
Software-Vertex- und Pixelshader
Softwareimplementierungen (Laufzeit und Verweis für Vertex-Shader und -Referenz für Pixelshader) von Version 2_0-Shadern und höher haben eine entspannte Überprüfung. Dies ist nützlich für Debugging- und Prototyperstellungszwecke. Die Anwendung gibt den Laufzeit-/Assembler an, dass sie einige der Überprüfungen mit dem _sw Flag im Assembler (z. B. vs_2_sw) entspannt benötigt. Ein Software-Shader funktioniert nicht mit Hardware.
vs_2_sw ist eine Entspannung für die maximalen Kappen von vs_2_x; ebenso ist ps_2_sw eine Entspannung für die maximalen Kappen von ps_2_x. Insbesondere sind die folgenden Überprüfungen entspannt:
Shadermodell | Ressource | Grenze |
---|---|---|
vs_2_sw, vs_3_sw, ps_2_sw, ps_3_sw | Anweisungsanzahl | Unbegrenzt |
vs_2_sw, vs_3_sw, ps_2_sw, ps_3_sw | Float-Konstantenregister | 8192 |
vs_2_sw, vs_3_sw, ps_2_sw, ps_3_sw | Ganzzahlige Konstantenregister | 2048 |
vs_2_sw, vs_3_sw, ps_2_sw, ps_3_sw | Boolesche Konstantenregister | 2048 |
ps_2_sw | Tiefe abhängiger Lesevorgänge | Unbegrenzt |
vs_2_sw | Ablaufsteuerungsanweisungen und Bezeichnungen | Unbegrenzt |
vs_2_sw, vs_3_sw, ps_2_sw, ps_3_sw | Schleifenstart/Schritt/Anzahl | Iterationsstart- und Iterationsschrittgröße für Rep- und Schleifenanweisungen sind 32-Bit-ganzzahlen. Die Anzahl kann bis zu MAX_INT/64 sein. |
vs_2_sw, vs_3_sw, ps_2_sw, ps_3_sw | Portgrenzwerte | Portgrenzwerte für alle Registerdateien sind entspannt. |
vs_3_sw | Anzahl der Interpolatoren | 16 Ausgaberegister in vs_3_sw. |
ps_3_sw | Anzahl der Interpolatoren | 14(16-2) Eingaberegister für ps_3_sw. |
Verwandte Themen