Seite 1 von 1

[DX10, C++] Arrayzugriff im PixelShader

Verfasst: 19.03.2009, 19:52
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

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

Verfasst: 19.03.2009, 22:20
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

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

Verfasst: 19.03.2009, 23:10
von kkrahl
Danke für deine raschen Antwort, löst aber leider NICHT mein Problem.

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

Verfasst: 19.03.2009, 23:20
von Krishty
Ohne Fehlermeldung oder Fehlerbeschreibung kann das auch noch dauern …

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

Verfasst: 19.03.2009, 23:39
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

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

Verfasst: 19.03.2009, 23:42
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.

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

Verfasst: 20.03.2009, 00:18
von kkrahl
Folgender Fehler tritt auf:
error X3512: sampler array index must be a literal expression

Thx

Karl

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

Verfasst: 20.03.2009, 00:23
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.

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

Verfasst: 20.03.2009, 00:38
von Krishty
Falls alle Texturen identischer Ausmaße und Formate sind, kannst du auch eine Ressource vom Typ Texture2DArray nutzen.

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

Verfasst: 20.03.2009, 11:56
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

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

Verfasst: 20.03.2009, 14:55
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.

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

Verfasst: 20.03.2009, 15:45
von kkrahl
Aber leiter ist Texture-wrap auch eines der Features das ich brauche.

Aber danke

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

Verfasst: 20.03.2009, 23:38
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 :-)

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

Verfasst: 25.03.2009, 16:19
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.

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

Verfasst: 25.03.2009, 16:39
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.

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

Verfasst: 25.03.2009, 17:08
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?

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

Verfasst: 25.03.2009, 17:19
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.

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

Verfasst: 25.03.2009, 17:24
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.

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

Verfasst: 25.03.2009, 17:28
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.

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

Verfasst: 26.03.2009, 03:44
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 :)

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

Verfasst: 26.03.2009, 12:45
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 … ?

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

Verfasst: 26.03.2009, 13:43
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