[DX10] Konzept zur Verwaltung von HLSL Shader

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.

[DX10] Konzept zur Verwaltung von HLSL Shader

Beitragvon exploid » 06.02.2010, 19:03

Hallo

Da bin ich wieder und voller Fragen die mich als unwissend definieren. Trotz dessen wird nicht aufgegeben.
Denn mein Ziel ist die Erleuchtung zu gewinnen. :)

Genug der einleitenden Worte. Hier das neue Problem:

Seit 2 Tagen werden Gedanken verbraucht um Microsoft (Effectfiles) HLSL Programme zu verwalten. Mein bisheriges Konzept
ist sehr "löchrig". Versuche kurz und präzise alles zusammenzufassen was bisher erarbeitet wurde.

Meine D3D Klasse befindet sich in einer DLL. Diese soll die HLSL Programme verwalten. Die gesamte Klassendefinition wird euch
erspart zu viel Informationen. Daher nur das wesentliche in kürze:

D3D Klasse:

Code: Alles auswählen
/**
* Class definition for a Direct3D render device, implementing the
* interface RenderDevice
*/
class D3D : public RenderDevice {
public:
D3D(HINSTANCE hDLL);
~D3D(void);

SkinManager* GetSkinManager(void) { return m_pSkinMan; }
VertexCacheManager* GetVertexManager(void) { return m_pVertexMan; }
ModelManager* GetModelManager(void) { return m_pModelMan; }

// initialize the engine stuff
HRESULT Init(HWND);
...

// shader stuff
HRESULT CreateHLSLShader(const void*, UINT *nShaderID);
ID3D10Effect* GetHLSLShader(UINT nShaderID);
HRESULT SetTechnique(char *tc, UINT nShaderID, UINT *nTechniqueID);
HRESULT ActivateTechnique();
//HRESULT SetVariable();
...
private:
ID3D10Effect* m_pHLSLShaders[MAX_SHADER];
UINT m_nNumHLSLShaders;
HLSLTechnique m_HLSLTechniques[MAX_TECHNIQUES][MAX_SHADER];
UINT m_nNumHLSLTechniques[MAX_SHADER];

}; // class
/*----------------------------------------------------------------*/


An diese Klasse wird die Schnittstellendefinition Renderdevice vererbt. Das kennt ihr ja alle mittlerweile zu genüge so dass darauf nicht
eingegangen werden muss was das bedeutet.

Meine Absicht ist eine begrenzte Anzahl von HLSL Shadern zu verwalten. => MAX_SHADER
Jeder Shader darf eine begrenzte Anzahl von Techniken verwenden. => MAX_TECHNIQUES
Diese Techniken werden der D3D Klasse mit folgender Struktur bekannt gegeben:

Code: Alles auswählen
typedef struct HLSLTechnique {
ID3D10EffectTechnique* pTechnique; // D3D10 technique interface
UINT nShaderID; // ID die den Shader kennzeichnet welche die "technique" verwendet
} HLSLTechnique;


Innerhalb der D3D Klasse wird nun Speicherplatz geschaffen über
HLSLTechnique m_HLSLTechniques[MAX_TECHNIQUES][MAX_SHADER];
Hier werden nun die Daten abgelegt für die möglichen Techniken. Jeder Shader kann ja MAX_TECHNIQUES besitzen. Damit die Klasse "weiß"
wie viele Shader bzw. Techniken sie besitzt existieren die beiden Zähler:
UINT m_nNumHLSLShaders;
und
UINT m_nNumHLSLTechniques[MAX_SHADER];

Damit kann die Klasse schon mal mit HLSL "Progrämmchen" und ihren Techniken gefüttert werden.

Weiterhin benötigt die Klasse ein Konzept um die Variablen der HLSL Programme zu speichern um diese während der Laufzeit
zur Verfügung zu stellen. Dazu viel mir folgendes ein:

Code: Alles auswählen

typedef enum HLSLVARIABLE_TYPE {
FLOAT,
VECTOR,
MATRIX,
...
} HLSLVARTYPE

typedef struct HLSLVariable {
ID3D10EffectVariable* pVariable; // D3D10 variablen interface
HLSLVARTYPE Varablentyp;
UINT nShaderID; // ID die den Shader kennzeichnet welche die Variable verwendet
} HLSLVariable;


Mit diesem Strukturen können der D3D Klasse nun die Variablen mitgeteilt werden. Methoden werden zur Verfügung gestellt
um der Renderfunktion der Applikation den Zugriff auf diese Variablen zu ermöglichen.

Was haltet ihr von dieser Lösung? Ist es einfacher möglich?
Benutzeravatar
exploid
 
Beiträge: 90
Registriert: 21.08.2005, 17:33

Re: [DX10] Konzept zur Verwaltung von HLSL Shader

Beitragvon Stefan Zerbst » 07.02.2010, 20:35

Hi,

ohne zu tief ins Detail zu gehen ein paar schlaue Gegenfragen:

Warum muss das RenderDevice Effekte verwalten bzw. den Zugriff darauf ermöglichen? Es muss Objekte geben die Effekte verwenden und die entsprechenden Effekt-Instanzen deklarieren und speichern.

Ist der Zugriff auf die Effekte auch von außerhalb möglich? Dann sollte man nicht direkt D3D10 Interfaces verwenden, sondern noch durch eigene Interfaces abstrahieren.

Ciao,
Stefan
Stefan Zerbst
Site Admin
 
Beiträge: 155
Registriert: 25.02.2009, 19:54

Re: [DX10] Konzept zur Verwaltung von HLSL Shader

Beitragvon Schrompf » 08.02.2010, 08:28

Zieh das raus in eine eigene Klasse. Also eine, die die Shader verwaltet, und eine pro Shader. Etwa so:

Code: Alles auswählen

class ShaderManager
{
HLSLEffect* CreateEffect( const std::string& pFile); // gibt Zeiger zurück, wirft Exception bei Fehlschlag
};

class HLSLEffect
{
size_t mNumTechniques;
std::vector<HLSLTechnique*> mTechniques;
ID3D10Effect* mD3DEffect;

// Getter dafür
// Konstruktor privat für ShaderManager
};

class HLSLTechnique
{
ID3D10EffectTechnique* mTechnique;
std::vector<Variable> mVariables;
};


Typnamen selbsttätig anpassen. Nebenbei: das typedef vor Strukturen und enums kannst Du Dir sparen. Das war zu C-Zeiten nötig, in C++ ist es nutzlos.
Häuptling von Dreamworlds. Baut an Splitterwelten. Hilft nebenbei an der Open Asset Import Library mit.
Benutzeravatar
Schrompf
Thomas Schulze
Moderator
 
Beiträge: 644
Registriert: 25.02.2009, 23:44
Wohnort: Dresden
Benutzertext: Chronisch überfordert...

Re: [DX10] Konzept zur Verwaltung von HLSL Shader

Beitragvon exploid » 09.02.2010, 15:10

Hallo

Danke für eure Antworten.

@Stefan Zerbst
Warum muss das RenderDevice Effekte verwalten bzw. den Zugriff darauf ermöglichen?

Das war ein Lösungsansatz um dem Modelmanager in der D3D.dll die "Shader" zur Verfügung zu stellen.

Bild

Ist der Zugriff auf die Effekte auch von außerhalb möglich?


Ja :)

@Schrompf

Bin gerade dabei zu verstehen was du geschrieben hast. Anwort folgt. Bitte um Geduld.

Hab das Konzept so verändert:

Bild

Habs nochmal verändert weil der Effekt Manager ja nur mit Model Manager sprechen muss.

Bild
Benutzeravatar
exploid
 
Beiträge: 90
Registriert: 21.08.2005, 17:33

Re: [DX10] Konzept zur Verwaltung von HLSL Shader

Beitragvon exploid » 08.03.2010, 22:26

Guten Abend

Letzte Nacht hatte ich einen furchtbaren Alptraum:
Das Konzept wurde lebendig und verfolgte mich in meinem Traum. Es griff mich an in der Form eines kleinen fetten
Männchens das rot war. Ein furchtbarer Kampf entbrannte. Am Ende hab ich natürlich gesiegt. Doch das Konzept
hatte sich so verändert:

Bild

Code: Alles auswählen
// effects
typedef struct HLSLTechnique {
ID3D10EffectTechnique* pTechnique;
UINT nShaderID;
} HLSLTechnique;

typedef struct HLSLVariable {
VARID ID;
void* pInterface;
} HLSLVariable;

typedef struct HLSLShader {
ID3D10Effect* m_pHLSLShader;
HLSLTechnique HLSLTechnique[MAX_TECHNIQUES];
//Variablen
} HLSLShader;

/*
* File: D3D_effectman.h *
* effect manager *
*******************************************************************/
#ifndef D3D_EFFECTMAN_H
#define D3D_EFFECTMAN_H
#include "RenderDevice.h" // base class
#include "types.h"
#include "errors.h"

/**
* Class to manage effects
*/
class D3DEffectManager : public EffectManager {
public:
D3DEffectManager(ID3D10Device* pDevice, FILE *pLog);
~D3DEffectManager(void);

HRESULT D3DEffectManager::CreateHLSLShader(wchar_t *chName, UINT *nShaderID);
HRESULT SetTechnique(char *chName, UINT nShaderID, UINT *nTechniqueID);
ID3D10EffectTechnique* GetTechnique(UINT nShaderID, UINT nTechniqueID);
HRESULT SetVertexLayout(VERTEXID nID, UINT nShaderID, UINT nTechniqueID);



protected:
void D3DEffectManager::Log(char *chString, ...);

ID3D10Device* m_pDevice; // directx device

HLSLShader m_HLSLShader[MAX_SHADER];

UINT m_nNumHLSLShaders; // counter of hlsl effect interfaces
UINT m_nNumHLSLTechniques[MAX_SHADER]; // counter of techniques for shader

ID3D10Effect* m_pActiveShader; // interface of active gpu program
ID3D10InputLayout* m_pActiveVertexLayout; // interface of active vertex layout
ID3D10EffectTechnique* m_pActiveTechnique; // interface of active effect technique
FILE* m_pLog;


};// class D3DEffectManager
/*----------------------------------------------------------------*/

#endif

/*
* File: D3D_modelman.h *
* model manager *
*******************************************************************/
#ifndef D3D_MODELMAN_H
#define D3D_MODELMAN_H
#include "RenderDevice.h" // base class
#include "D3D_skinman.h"
#include "D3D_vcache.h"
#include "types.h"
#include "errors.h"


/**
* Class to manage static and dynamic vertex bunches, optionally
* using indices during rendering process.
*/
class D3DModelManager : public ModelManager {
public:
D3DModelManager(D3DSkinManager* pSkinMan, D3DVCManager* pVCMan, FILE *pLog);
~D3DModelManager(void);

HRESULT AddModel(wchar_t *wcName, MODEL *pModel/*, nIDShader*/);

protected:
D3DSkinManager* m_pSkinMan;
D3DVCManager* m_pVCMan;


void Log(char *, ...);

HRESULT LoadXFile(wchar_t *chName);
HRESULT Load3ds(wchar_t *wcName);
FILE* m_pLog;

};// class D3DModelManager
/*----------------------------------------------------------------*/


Mit der roten Linie wollte ich andeuten das die Applikation nun nur mit dem Modelmanager sprechen kann
um Änderungen an Shadern, Buffern oder Texturen zu erzielen. Alle andern Manager sind "gekapselt". Was
haltet ihr davon. Bitte alle die Meinung formulieren.
Benutzeravatar
exploid
 
Beiträge: 90
Registriert: 21.08.2005, 17:33

Re: [DX10] Konzept zur Verwaltung von HLSL Shader

Beitragvon Aramis » 08.03.2010, 22:43

Vielleicht solltest du mal einen Blick auf UML werfen - auch so eine Technik über deren Nutzen man sich streiten kann, aber sie ist für Außenstehende deutlich einfacher zugänglich als Header und Paint-Bildchen.
Open Asset Import Library (Assimp) - Multiformat 3D Model-Importer
YIANG - Ein Jump'n'Run in ASCII-Grafik
Benutzeravatar
Aramis
Alexander Gessler
Moderator
 
Beiträge: 744
Registriert: 25.02.2009, 19:50
Wohnort: 2011
Benutzertext: Auch als Athos bekannt …

Re: [DX10] Konzept zur Verwaltung von HLSL Shader

Beitragvon kimmi » 09.03.2010, 11:45

Hier findest du eine OpenSource-Lösung zum Erstellen von UML:
https://sourceforge.net/projects/staruml/
Das hat den Vorteil, daß zumindest alle wissen, was die Pfeile bedeuten sollen und so.

Gruß Kimmi
Benutzeravatar
kimmi
Kim Kulling
Moderator
 
Beiträge: 573
Registriert: 26.02.2009, 09:42
Wohnort: Luebeck

Re: [DX10] Konzept zur Verwaltung von HLSL Shader

Beitragvon exploid » 09.03.2010, 20:11

Hallo Aramis hallo Kimmi

Danke für euren Vorschlag. Schau es mir mal an. Sieht auf dem ersten Blick viel versprechend aus.
Benutzeravatar
exploid
 
Beiträge: 90
Registriert: 21.08.2005, 17:33

Re: [DX10] Konzept zur Verwaltung von HLSL Shader

Beitragvon exploid » 18.03.2010, 20:25

Guten Abend

Es wurde versucht die Gedanken zu sortieren und dabei entstand dieses:


Bild

Skin-Daemon: -speichert Texturen jeder Art und vermeidet die Redundanzen

Vertex-Cache-Daemon: -je nach Anforderung werden hier alle Vertexe gesammelt und "flaschenhalsvermeidend" zur Grafikkarte gesendet

Effekt-Daemon: -verwaltet alle möglichen GPU Programme (GLSL, HLSL, asm)

Modellmanager: -Verwendet Skin, Vertex-Cache und Effekt-Daemon um alle Modelle zu verwalten.
- besitzt die Methoden zum Laden der Modelldaten (dwg, 3ds, x, etc)

Die Applikation verwendet nun das D3D-Interface um den Modelmanager aufzufordern Modelle zu Rendern, anzulegen oder was auch immer
die Applikation benötigt um ein Modell zu "managen". Möglicher Aufruf zum Anlegen eines Modells wäre pModelManager()->CreateModel( wchar_t
wcModelpath, wchar_t wcShaderLocationString, &IDModelID); Der Shader wird weitergeleitet an den Effekt-Daemon und dort geg. compiliert und
gespeichert. Falls andere Modelle den gleichen Shader verwenden wird dieser nicht neu anglegt. Um Redundanzen zu vermeiden wird der selbe Shader verwendet. Die Texturen werden vom Skinmanager angelegt und ebenfalls so das Redundanzen vermieden werden. Die Textur wird physikalisch nur
einmal im Speicher vorkommen auch wenn der Modellmanager sie öfter anlegen will wird dies der Skin-Daemon erkennen. Die Geometrie des Modells
wird vom Modelmanager gespeichert und verwaltet. Hier wurde überlegt ob Batching verwendet wird. Also ein Buffer der Grösse
2^16, 65536 Vertexe und einen IndexBuffer innerhalb des Vertex-Cache-Managers. Wenn der Buffer gefüllt ist wird er zur Grafikkarte gesendet um "Flaschenhalsverzögerungen" zu vermeiden aufgrund der Busüberlastung zwischen GPU und CPU.

Jetzt fehlt "nur" noch das Netzwerkinterface, Scriptinterface (LUA), Eingabeinterface (Maus, Tastatur, Joystick), KI-Interface (für Spiellogik)

Was haltet ihr davon? :)
Benutzeravatar
exploid
 
Beiträge: 90
Registriert: 21.08.2005, 17:33

Re: [DX10] Konzept zur Verwaltung von HLSL Shader

Beitragvon Schrompf » 19.03.2010, 08:48

So richtig bekommst Du meiner Meinung nach nicht die Füße auf den Boden. Zum Einen sind das logische Details: die Geometrieverwaltung muss *sofort* alle neuen Vertexdaten hochladen - kann ja sein, dass jemand das Modell zeichnen will, bevor Du genug Modelle zusammenhast, um den Buffer vollzumachen und hochzuladen. Nebenbei bemerkt musst Du in dieser Version auch nach Vertexstruktur unterscheiden, sonst funktioniert Dein Vertex-zählen nicht mehr. Muss es ja aber auch nicht - die weiche Grenze von 65k Vertizes stammt vom 16Bit-Indexbuffer - dem VertexBuffer ist es nahezu wurscht, wie groß er ist.

Zum Anderen scheint mir immernoch keine Klarheit in Deiner Applikation zu sein. Warum redet die App mit der D3D.dll? Die sollte doch eigentlich eher mit dem Model Manager reden. Du wirst gelegentlich auch Modelle getrennt von Materialien entscheiden wollen - diese Option solltest Du Dir auch offenhalten. Dann wirst Du eine Art Parameterstruktur brauchen - Shader können Parameter deklarieren können, Materialien müssen Werte an Shader-Parameter übergeben können. Das kannst Du erstmal auf später verschieben, aber früher oder später wird sowas nötig sein. Eine Möglichkeit, frame-aktuell Parameter für einzelne Model-Instanzen zu ändern, wird auch nötig werden. Das fehlt uns aktuell noch, und es verhindert unter anderem so banale Sachen wie "lass das Objekt pulsierend aufleuchten, wenn der Spieler es im Fokus hat".

Außerdem kann ich aus guter Erfahrung empfehlen, einen Pass in eine Klasse zu verpacken. Man geht zur Engine und sagt "fang einen neuen Zeichenprozess an, die Parameter, der Kontext, das Renderziel". Daraufhin bekommt man von der Engine eine Zeichenprozess-Instanz zurück, der man dann alle DrawCalls in die Hand drückt. Das hat außerdem den Vorteil, dass Du jedem Renderpass einen Kontext geben kannst - sowas wie "Du bist ein Schattendurchgang für Parallellicht-Shadowmaps, nimm mal die ShadowMap-Shader anstatt der normalen" oder auch "ich render jetzt Spiegelungen, erspar Dir den PräZ-Pass und das Reliefmapping". Sehr nützlich, sowas... hab jedenfalls ich bemerkt.

Ich hoffe, das gibt Dir ein paar Inspirationen... ich will Dich damit nämlich nicht aufhalten! Meine Empfehlung lautet eher gegensätzlich: fang an zu coden. Und Du wirst ganz automatisch feststellen, wo es hängt.

Ach, und nochwas: konzentriere Dich auf eine Shader-Sprache. Du wirst schon genug Ärger damit haben, alle notwendigen Permutationen für einen Effekt zu schreiben. Davon dann auch noch x Varianten für HLSL, GLSlang und Asm zu warten ist reine Idiotie.

Bye, Thomas
Häuptling von Dreamworlds. Baut an Splitterwelten. Hilft nebenbei an der Open Asset Import Library mit.
Benutzeravatar
Schrompf
Thomas Schulze
Moderator
 
Beiträge: 644
Registriert: 25.02.2009, 23:44
Wohnort: Dresden
Benutzertext: Chronisch überfordert...

Re: [DX10] Konzept zur Verwaltung von HLSL Shader

Beitragvon exploid » 20.03.2010, 18:37

Hallo Schrompf

Zunächsteinmal bedanke ich mich für deine Meinung und Gedanken.

Schrompf hat geschrieben:Zum Einen sind das logische Details: die Geometrieverwaltung muss *sofort* alle neuen Vertexdaten hochladen - kann ja sein, dass jemand das Modell zeichnen will, bevor Du genug Modelle zusammenhast, um den Buffer vollzumachen und hochzuladen. Nebenbei bemerkt musst Du in dieser Version auch nach Vertexstruktur unterscheiden, sonst funktioniert Dein Vertex-zählen nicht mehr. Muss es ja aber auch nicht - die weiche Grenze von 65k Vertizes stammt vom 16Bit-Indexbuffer - dem VertexBuffer ist es nahezu wurscht, wie groß er ist.


Das ist richtig und aus diesem Grund verfügt der Modelmanager über eine Methode den Vertex-Cache-Demon zu zwingen seinen
"Vertextopf" zur Grafikkarte zu senden um den entsprechenden Vertex Cache zur Renderpipeline zu senden und damit zur
Ausgabe auf den Monitor.

Schrompf hat geschrieben:Warum redet die App mit der D3D.dll?


In der Abbildung wurde versucht das als Interface darzustellen. Die D3D.dll ist für die Applikation nur zugänglich über ein
Interface. Das wurde aus dem Grund so erstellt: Es wird versucht eine "Bauklötzchenarchitektur" zu entwickeln. Jedes
weitere Modul wird als DLL bereitgestellt und mit dem dazugehörigen Interface. Die Applikation kann selbst entscheiden
welches Interface und damit DLL sie benötigt. Vorteil ist dann ein leichter Austausch von "Bauklötzen" und portabilität
auf andere Systeme. Man muss dann nur die DLL anpassen und nicht das gesamte Projekt.

Wenn das nicht gemacht werden würde führt das unweigerlich zu sehr langen Compilierzeiten. Ebenso würden sehr viele
weitere Fehlerquellen auftreten können weil das zu Spaghetticode führen würde wenn jedes Modul direkt für die Applikation
zugänglich wäre.

Schrompf hat geschrieben:Außerdem kann ich aus guter Erfahrung empfehlen, einen Pass in eine Klasse zu verpacken. Man geht zur Engine und sagt "fang einen neuen Zeichenprozess an, die Parameter, der Kontext, das Renderziel". Daraufhin bekommt man von der Engine eine Zeichenprozess-Instanz zurück, der man dann alle DrawCalls in die Hand drückt. Das hat außerdem den Vorteil, dass Du jedem Renderpass einen Kontext geben kannst - sowas wie "Du bist ein Schattendurchgang für Parallellicht-Shadowmaps, nimm mal die ShadowMap-Shader anstatt der normalen" oder auch "ich render jetzt Spiegelungen, erspar Dir den PräZ-Pass und das Reliefmapping". Sehr nützlich, sowas... hab jedenfalls ich bemerkt.


Das ist ein interessanter Ansatz und ist dankend zur Kenntnis genommen worden.

Schrompf hat geschrieben:Meine Empfehlung lautet eher gegensätzlich: fang an zu coden. Und Du wirst ganz automatisch feststellen, wo es hängt.


Das Grobe Gerüst ist schon fertig geschrieben. Es wird aber noch an alle Ecken und Enden gefeilt um den Code besser lesbar zu machen
und das Konzept nachhaltig zu beschreiben. Damit man das auch noch in 10 Jahren nachvollziehen kann was da gemacht wurde und wie
es funktioniert.

Schrompf hat geschrieben:Ach, und nochwas: konzentriere Dich auf eine Shader-Sprache. Du wirst schon genug Ärger damit haben, alle notwendigen Permutationen für einen Effekt zu schreiben. Davon dann auch noch x Varianten für HLSL, GLSlang und Asm zu warten ist reine Idiotie.


Ziel ist es so viele Details wie möglich zu lernen. Es gibt keine gesteckten Ziele sondern das Lernen der unterschiedlich Themengruppen wie Shader etc. soll das Ziel sein.
Benutzeravatar
exploid
 
Beiträge: 90
Registriert: 21.08.2005, 17:33


Zurück zu Programmiersprachen, Quelltext und Bibliotheken

Wer ist online?

Mitglieder in diesem Forum: hagbard und 3 Gäste