Typumwandlung für Shaderkonstanten und Texelformate

Design Patterns, Erklärungen zu Algorithmen, Optimierung, Softwarearchitektur
Forumsregeln
Wenn das Problem mit einer Programmiersprache direkt zusammenhängt, bitte HIER posten.
Antworten
Benutzeravatar
B.G.Michi
Establishment
Beiträge: 163
Registriert: 07.03.2006, 20:38
Alter Benutzername: B.G.Michi
Kontaktdaten:

Typumwandlung für Shaderkonstanten und Texelformate

Beitrag von B.G.Michi »

Guten Tag

Zwei meiner Klassen müssen vermutlich geändert werden: es geht um Texture und ShaderConstantBuffer. Beide haben gemeinsam, dass sie mit verschiedenen Eingabedaten umgehen müssen. Bei der Textur sind es die verschiedenen Texelformate und bei den Shaderkonstanten alle möglichen Arten von Skalar, Vektor, Matrix mit bool, int, float als Typ.

Jetzt dachte ich mir lass ich den Compiler die Arbeit machen und verpacke das ganze in Templates.
Am Beispiel der Textur: ich schreibe mir also eine Klasse für jedes Texelformat und eine Konvertierungsfunktion:

Code: Alles auswählen

enum TexelFormat {
    R8, RGBA32, ..., RGBA128F, ... // insgesamt 34 verschiedene
};

template<TexelFormat FORMAT>
class Texel { /* ... */ };

template<TexelFormat DEST, TexelFormat SRC>
void Convert(const Texel<SRC>* _pSrc, Texel<DEST>* _pDest, ...)
{
    for(int x ...)
        _pDest[x] = (Texel<DEST>)(_pSrc[x]);
}

// Textur
class Texture {
    void* m_pData;
    TexelFormat m_Format;
    /* ... */
    template<TexelFormat SRC>
    void Write(const Texel<SRC>* _pData, ...)
    {
        template_for<0, 34> // template for loop über alle möglichen Zielformate
            if(template_x == m_Format)
                Convert<SRC, template_x>(_pData, m_pData, ...);
    }
}
Das funktioniert soweit auch wunderbar, das Problem ist allerdings, dass alle Convert<SRC, DEST>s in die DLL wandern. Dadurch braucht gcc zum linken nur der Textur ca. 5 Minuten und die DLL wird doch recht groß. Für die Shaderkonstanten hatte ich mir das ähnlich vorgestellt. Der Shader wird aus der Datei geladen und bekommt eine Write-Funktion wie die Textur. Allerdings sind es hier um einiges mehr verschiedene Formate ((Skalar, Vektor2, Vektor3, ..., Matrix 2x2, Matrix3x3, ..., Matrix2x2_ColumnMajor, ...) x (bool, int, float)), ihr versteht worauf ich hinaus will?...

Wie würdet ihr das handhaben? Muss beim Aufruf von Write/Read das Format/der Typ bekannt sein? Oder soll ich mir eine Convert-Funktion ohne Template schreiben (Performance?)

Vielen Dank fürs Durchlesen :)
mfg JFF_B.G.Michi
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: Typumwandlung für Shaderkonstanten und Texelformate

Beitrag von CodingCat »

Rein interessehalber: Zu was übersetzt du template_for? Ansonsten: Du lässt den Compiler 34×34 Funktionen erzeugen?! In diesem Fall hilft Entkopplung durch ein gemeinsames Zwischenformat, am effizientesten ganz einfach über einen temporären Puffer in diesem Zwischenformat. Dann hast du statt 34×34 nur noch 34 Dekodier- und 34 Kodierfunktionen.

Die Templates sind natürlich schön, weil ohne Zwischenpuffer. Wenn die Funktionen nicht in der DLL landen müssen, könntest du die Templates einfach bei Bedarf den Compiler erzeugen lassen (Code in Header und implizite Instantiierung).
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
B.G.Michi
Establishment
Beiträge: 163
Registriert: 07.03.2006, 20:38
Alter Benutzername: B.G.Michi
Kontaktdaten:

Re: Typumwandlung für Shaderkonstanten und Texelformate

Beitrag von B.G.Michi »

template_for sieht so aus (es bedarf allerdings immer einer kleinen Helferklasse weil es leider keine Template-Lambdas gibt :) )

Code: Alles auswählen

template<int START, int END, int STEP = 1>
class template_for
{
public:
    template<class ACTION, class... ARGS>
    static inline void run(ARGS&&... _Args)
    {
        ACTION::template step<START>(forward<ARGS>(_Args)...);
        template_for<START + STEP, END, STEP>::template run<ACTION, ARGS...>(forward<ARGS>(_Args)...);
    }
};

template<int END, int STEP>
class template_for<END, END, STEP>
{
public:
    template<class ACTION, class... ARGS>
    static inline void run(ARGS&&...) {}
};

// verwendung:
template<TexelFormat SRC>
class SelectConvert { public:
template<int DEST> static inline void step(TexelFormat _SrcFormat, const Texel<SRC>* _pSrc, void* _pDest, ...)
{
    if((TexelFormat)DEST == _SrcFormat)
        Convert<SRC, (TexelFormat)DEST>(_pSrc, _pDest, ...);
}

// in Write:
template_for<0, 34>::Loop<SelectConvert<SRC>>(_pData, m_pData, ...);
Es landen genau genommen nicht alle 34*34 Converts in der DLL sondern nur die (SRC-Formate die die DLL selbst aufruft) * 34. Die Write/Read-Funktionen ist ja selbst Templates. MSVC hat das ganz gut verkraftet, die DLL war dann mit Textur und Shaderkonstanten im Debug-Modus ca. 2-3 MB größer als ohne diese Template-Spielereien. Finde ich verkraftbar. Allerdings wollte ich nun auf GCC umsteigen und wie gesagt: 5 Minuten linken nur für die Textur. Mit Shaderkonstanten hab ich nach 10 Minuten abgebrochen.
Zuletzt geändert von B.G.Michi am 15.12.2012, 16:32, insgesamt 1-mal geändert.
Benutzeravatar
Krishty
Establishment
Beiträge: 8238
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Typumwandlung für Shaderkonstanten und Texelformate

Beitrag von Krishty »

Das habe ich auch mal gemacht, nur, dass ich auch die Konvertierung durch den Compiler habe vornehmen lassen (indem das RGB-Layout in den Integern der Template-Parameter kodiert war). Wenn ich mich recht erinnere, hatte das bei 17×17 Funktionen etwa andernhalb Megabyte Text erzeugt :D

Warum müssen die Daten konvertiert werden? Können die nicht direkt im richtigen Format gespeichert werden? Wozu 17 Formate, reichen nicht drei oder vier?
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: Typumwandlung für Shaderkonstanten und Texelformate

Beitrag von CodingCat »

Die Dekodier- und Kodierfunktionen mit gemeinsamem Zwischenformat lassen sich btw. natürlich genauso per Template erzeugen, nur kommen dann nicht mehrere 100 Funktionen dabei raus. ;) Und wie Krishty andeutet, will man derlei Konvertierungen auf keinen Fall regelmäßig durchführen, sondern dann für die Zukunft gleich im richtigen Format zwischenspeichern.
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Antworten