[DX10, C++] Arrayzugriff im PixelShader

Für Fragen zu Grafik APIs wie DirectX und OpenGL sowie Shaderprogrammierung.
Antworten
kkrahl
Beiträge: 56
Registriert: 20.10.2008, 13:41

[DX10, C++] Arrayzugriff im PixelShader

Beitrag von kkrahl »

Hallo allerseits

Ich hänge leider schon wider bei einem Problem, und zwar habe ich folgenden Shader Code:

Variablen:

Code: Alles auswählen

extern Texture2D baseTexture[100];
extern float4 colorMod[100];
Bei dem folgenden PS bekomme ich aber einen Fehler:

Code: Alles auswählen

float4 DefaultPS( VS_OUTPUT input ) : SV_Target
{
return baseTexture[input.TexID].Sample( samLinear, input.TexCoords ) * input.Color * colorMod[input.TexID];
}
Aber folgendes funktioniert einwandfrei:

Code: Alles auswählen

float4 DefaultPS( VS_OUTPUT input ) : SV_Target
{
return baseTexture[9].Sample( samLinear, input.TexCoords ) * input.Color * colorMod[input.TexID];
}
Die Daten sind in jedem Fall immer da!

Kann mir da jemand weiter helfen?

Dank euch
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [DX10, C++] Arrayzugriff im PixelShader

Beitrag von Krishty »

Welchen Fehler denn?

Ich würde als erstes darauf tippen, dass der Shader ungültig ist, weil nicht garantiert werden kann, dass der Arrayzugriff innerhalb der Array-Grenzen liegt. Versuch mal baseTexture[clamp(0, input.TexID, 100)].…

Gruß, Ky
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
kkrahl
Beiträge: 56
Registriert: 20.10.2008, 13:41

Re: [DX10, C++] Arrayzugriff im PixelShader

Beitrag von kkrahl »

Danke für deine raschen Antwort, löst aber leider NICHT mein Problem.
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [DX10, C++] Arrayzugriff im PixelShader

Beitrag von Krishty »

Ohne Fehlermeldung oder Fehlerbeschreibung kann das auch noch dauern …
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
kkrahl
Beiträge: 56
Registriert: 20.10.2008, 13:41

Re: [DX10, C++] Arrayzugriff im PixelShader

Beitrag von kkrahl »

Das ist auch meine Problem, hatte Shader bisher direkt nur im Programm compiliert, habe keinen eigenen Shadercompiler. Kannst du mir da einen empfehlen, bin noch auf der Suche.

Danke

Karl
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [DX10, C++] Arrayzugriff im PixelShader

Beitrag von Krishty »

Du übergibst dem Shader-Compiler zwei Blobs, einen für den Bytecode und einen für Fehlermeldungen. Der mit den Fehlermeldungen enthält hinterher (hoffentlich) einen ASCII-String mit der Fehlermeldung. Den kannst du ja im Debugger auslesen oder in eine Datei schreiben o.ä.

Ansonsten weiß ich, dass AMDs GPU Shader Analyzer die Fehlermeldungen auch anzeigt.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
kkrahl
Beiträge: 56
Registriert: 20.10.2008, 13:41

Re: [DX10, C++] Arrayzugriff im PixelShader

Beitrag von kkrahl »

Folgender Fehler tritt auf:
error X3512: sampler array index must be a literal expression

Thx

Karl
Benutzeravatar
Aramis
Moderator
Beiträge: 1458
Registriert: 25.02.2009, 19:50
Echter Name: Alexander Gessler
Wohnort: 2016
Kontaktdaten:

Re: [DX10, C++] Arrayzugriff im PixelShader

Beitrag von Aramis »

Soll heißen: dynamische Indizes sind für Samplerarrays nicht erlaubt, du musst eine andere Lösung finden. Zum Beispiel eine 3D-Textur.
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [DX10, C++] Arrayzugriff im PixelShader

Beitrag von Krishty »

Falls alle Texturen identischer Ausmaße und Formate sind, kannst du auch eine Ressource vom Typ Texture2DArray nutzen.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
kkrahl
Beiträge: 56
Registriert: 20.10.2008, 13:41

Re: [DX10, C++] Arrayzugriff im PixelShader

Beitrag von kkrahl »

Danke noch mal für eure rasche Antwort, hab dann auch gestern noch ein wenig rum gespielt. Das einzige was mir da noch eingefallen wär ist ein switch-case aber das find ich nicht wirklich schön und will es daher auch nicht machen. Leider haben die Texturen keine einheitliche größe. Ich wollte das mit dem Array aus performance Gründen machen damit ich nicht jede texture einzeln rein laden muss sonden 100 auf einmal.

Hat ihr da noch welche ideen wie ich das verwirklichen kann? Denn da ich ich den Bereich recht neu bin bin ich auch für jeden Tip bei dem ich was lernen kann dankbar.

Danke noch mal

Karl
Benutzeravatar
Schrompf
Moderator
Beiträge: 4838
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: [DX10, C++] Arrayzugriff im PixelShader

Beitrag von Schrompf »

Ein Texturatlas vielleicht... klappt aber nur, wenn Du keine Texturwiederholung brauchst. Danach wäre die Auswahl der Textur nur noch ein Offset auf die Texturkoordinaten.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
kkrahl
Beiträge: 56
Registriert: 20.10.2008, 13:41

Re: [DX10, C++] Arrayzugriff im PixelShader

Beitrag von kkrahl »

Aber leiter ist Texture-wrap auch eines der Features das ich brauche.

Aber danke
Benutzeravatar
Aramis
Moderator
Beiträge: 1458
Registriert: 25.02.2009, 19:50
Echter Name: Alexander Gessler
Wohnort: 2016
Kontaktdaten:

Re: [DX10, C++] Arrayzugriff im PixelShader

Beitrag von Aramis »

Im Notfall könntest du das Texturwrapping auch im Shader emulieren. Wenn du den Offset und die Ausdehnung einer Subtextur im Atlas kennst ist das kein Problem, dürfte aber nicht so wirklich schnell sein :-)
Benutzeravatar
Zudomon
Establishment
Beiträge: 2253
Registriert: 25.03.2009, 07:20
Kontaktdaten:

Re: [DX10, C++] Arrayzugriff im PixelShader

Beitrag von Zudomon »

Außerdem wäre ein Texturwrapping im Shader kritisch, weil Vorkehrungen bzgl. des Filterings getroffen werden müssten. An den Grenzen einer Subtextur müsste dann ein Saum angebracht sein. Sonst würde man ja bilinear in die nächste Subtextur blenden. Auch müsste man beim Mipmapping beachten, das Texel nicht zwischen verschiedenen Subtexturen gemittelt werden.

Da bezahlst du dann den Texturswitch mit mehr Aufwand bei jedem einzelnen Pixel. Ob sich das lohnt ist sehr fraglich.
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [DX10, C++] Arrayzugriff im PixelShader

Beitrag von Krishty »

Es müssen keine Vorkehrungen getroffen werden. Man muss einfach nur das Filtern von Hand übernehmen … mit denselben Algorithmen wie sie von den nativen Filterfunktionen genutzt werden, nur dass sie nicht mit der Größe der Textur, sondern mit der Größe des Texturausschnitts arbeiten und vorher und nachher ein Offset subtrahiert/addiert wird.

Die Frage ist eher, ob man Zeit und Geduld hat, die Filtern nachschreiben … bilinear geht ja noch, trilinear wird kniffliger und für anisotrop muss man richtig Ahnung haben, vor allem wenn man auf ähnliche Performance kommen möchte wie mit den nativen Texturfunktionen.

Theoretisch ist es durchaus machbar, praktisch lohnt es sich kaum.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Zudomon
Establishment
Beiträge: 2253
Registriert: 25.03.2009, 07:20
Kontaktdaten:

Re: [DX10, C++] Arrayzugriff im PixelShader

Beitrag von Zudomon »

Ist denn ein per Hand geschriebener Filter genauso schnell, wie die in Hardware implementierten?
Wenn man aus eine Textur liest, ist das ja nur ein Texturzugriff... wenn man bilinear filtern möchte, sind es vier, oder nicht?
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [DX10, C++] Arrayzugriff im PixelShader

Beitrag von Krishty »

Ja, bilinear sind es vier Texturzugriffe.

Die Filter sind nicht in Hardware implementiert. Die Texturfunktionen werden im Shader-Core durchgeführt wie jeder andere Code auch, die Textureinheiten können eigentlich nichts anderes als Load()s. Dadurch skaliert afaik die ALU-Auslastung besser mit der Auslastung der Textureinheiten. (Zumindest ist das bei ATI so, bei Nvidia weiß ich es nicht)
D3D10 unterstützt das ja noch zusätzlich, indem es dem Pixel-Shader die Änderungsrate der Geometrie zur Verfügung stellt.

Wenn man den Filter selbst implementiert, ersetzt man also die nativen Texturfunktionen im wahrsten Sinne des Wortes … wie schwierig das für identische Performance zu optimieren ist, übersteigt allerdings meinen Horizont.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Aramis
Moderator
Beiträge: 1458
Registriert: 25.02.2009, 19:50
Echter Name: Alexander Gessler
Wohnort: 2016
Kontaktdaten:

Re: [DX10, C++] Arrayzugriff im PixelShader

Beitrag von Aramis »

Allerdings kann der Buildin-Filteralgo von den Hardwareeinheiten bzw. vom Treiber spezifisch optimiert werden, ich würde mir also nicht sonderlich gute Chancen ausrechnen da von Hand auch nur grob ranzukommen. Man könnte aber auch einfach an die Subtexturen am Rand noch 1-5 zusätzliche Reihen und Spalten einfügen, womit der Hardwarefilter wieder benutzt werden könnte.
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [DX10, C++] Arrayzugriff im PixelShader

Beitrag von Krishty »

Stimmt, die berühmte winkelabhängige Anisotropie … andererseits, selbst wenn eine Textur bereits im Cache liegt, liegt das ALU:TEX-Verhältnis bei 4:1, sonst sogar noch höher … ohne das implementiert zu haben können wir nur mutmaßen.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Zudomon
Establishment
Beiträge: 2253
Registriert: 25.03.2009, 07:20
Kontaktdaten:

Re: [DX10, C++] Arrayzugriff im PixelShader

Beitrag von Zudomon »

@kkrahl
Das Problem an deinem Texturarray ist, dass es keins ist.

Deine Dekleration:

Code: Alles auswählen

Texture2D baseTexture[100];
Versuch stattdessen mal:

Code: Alles auswählen

Texture2DArray baseTextureArray;
Dann sollte das auch mit dem Index so klappen, wie du wolltest :)
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [DX10, C++] Arrayzugriff im PixelShader

Beitrag von Krishty »

kkrahl hat geschrieben:Leider haben die Texturen keine einheitliche größe.
Damit ist es mit dem Texture2DArray hin. Aber wenn die Größen und Formate nicht allzu weit auseinander liegen, könnte man sich vielleicht auf einen gemeinsamen Nenner einigen … ?
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
kkrahl
Beiträge: 56
Registriert: 20.10.2008, 13:41

Re: [DX10, C++] Arrayzugriff im PixelShader

Beitrag von kkrahl »

Dank euch für den vielen Input!

Habe das ganze aber nun vorerst mal so abgeändert das ich die Texturen einzel lade, da ich die Engine auch nun schon weiter entwickelt habe und mir aufgefallen ist das die Draworder random sein muss um alle möglichen Features meiner 2DEngine umzusetzen und ich in das Array immer nur einen Teil des gesamten Bereichs eingeblendet hatte. Durch das ganze Randomizing hätte ich die DatenArrays immer umordnen/sortieren müssen was auch zu einem Performanceverlust führen würde.

Konnte auch nicht wirklich den großen Performanceunterschied entdecken wenn ich 100 Elemente auf einmal zum Shader schicke oder auch nur eines, lang bei unter 5%.

@ Krishty: Da das ganze Teil einer generischen 2DEngine ist welche eine GUI via Files konfigurieren lässt sind auch die Texturen nicht in ihrer Größe limitiert und können zwischen 1x1 und 10.000x10.000 groß sein.

Danke euch noch vielmals für die vielen Anregungen!

Karl
Antworten