PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Brainstorming: Gemeinsame Wrapper-API für D3D und OGL


zeckensack
2003-08-05, 14:57:34
Für Test-Applikationen, bei denen man sich für API-spezifisches Verhalten interessiert (ala FSAA-Tester).

Idee von micki :wink:

1)Man braucht eine init-Funktion, die ein Fenster erzeugt. GL kann das nicht mit Bordmitteln, D3D dagegen schon. Dieser Unterschied muß versteckt werden.

2)Vertex arrays sind am ehesten portabel. Immediate mode ala GL ist für sehr einfache Tests zwar lecker, aber AFAIK recht schwierig auf D3D umzusetzen.

3)Für Analyseverfahren braucht's solide Screen-Cap-Funktionalität.

4)Für Geschwindigkeitsmessungen sollten verlässliche Timing-Funktionen integriert sein.

5)Das Feature-Set sollte sich auf das für Tests nötige Minimum beschränken. Womit die Sache kompliziert wird ;)
a)Blending? Welche Modi sind wichtig?
b)Texturen? Welche Filter, clamp-Verhalten sind wichtig? Wieviel Multitexturing und wieviel Combiner-Flexibilität ist nötig, um Chips zu vermessen?
c)Stencil-Ops? Z-Tests?
d)Matrix-Operationen und Transformation?

Fire away =)

Matti
2003-08-05, 16:41:52
1. die Init-Funktion dürfte kein Problem sein. Fast jeder hat sich doch eine Init-Funktion geschrieben z.B. InitGL(xres,yres,bpp,fullscreen), damit man nicht jedesmal ca. 3 Setien Quellcode ins Projekt einfügen muß.

2. Vertex-Arrays bieten die beste Performance, aber für Testzwecke ist die Performance imo zweitrangig. Ich finde das System von OpenGL mit glBegin(...) und glEnd komfortabler. Es müßten Tris, Quads und vielleicht noch Tristrips unterstützt werden. Bei d3d sehe ich auch kein Problem, weil man doch die Vertics speichern könnte, und wenn die 3. Vertex hinzukommt eben ein Dreieck zeichnen.

3. unter OpenGL mit glReadPixels kein Problem und unter DirectX könnte man es mit Blt lösen.

4. GetTickCount ist sehr zuverlässig, aber die Genauigkeit ist nur 10 ms. Etwas genaueres wäre natürlich besser, aber ich hab keine Ahnung, was man da nehmen könnte. DX bietet zwar den Performance-Counter, aber OpenGL hat sowas nicht.

5.
a) eigentlich nur glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA)
eventuell noch glBlendFunc(GL_SRC_COLOR,GL_ONE)
mit und ohne Alpha-Test!
b) bilinear mit und ohne Mip-Mapping, trilinear
c) Z-Tests: GL_LESS, GL_LEQUAL (für mehrfaches Rendern der Szene)
mit und ohne Z-Test, mit und ohne Z-Buffer schreiben

che g
2003-08-05, 16:54:42
ad 4) QueryPerformanceCounter() sollte genau genug sein

micki
2003-08-05, 17:08:39
man könnte auch einfach den instructioncount auslesen :/

MfG
micki

Demirug
2003-08-05, 17:18:58
Original geschrieben von micki
man könnte auch einfach den instructioncount auslesen :/

MfG
micki

Ja aber dann bitte den Process auf eine CPU festnageln. Ich habe hier noch sein ein Programm das so schlau sein wollte.

micki
2003-08-05, 17:32:19
meinst du das programm von prof.dr. micro soft ?

fehler kann man immer machen, hat nichts mit "schlauheit" zu tun, dass jemand mit nem singlecpu system sowas nicht testen konnte ist normal, früher zur doszeiten konnten wir auch nicht jede mögliche hardwarekonfiguration testen und die games semmelten ab...

MfG
micki

Demirug
2003-08-05, 17:38:13
Original geschrieben von micki
meinst du das programm von prof.dr. micro soft ?

fehler kann man immer machen, hat nichts mit "schlauheit" zu tun, dass jemand mit nem singlecpu system sowas nicht testen konnte ist normal, früher zur doszeiten konnten wir auch nicht jede mögliche hardwarekonfiguration testen und die games semmelten ab...

MfG
micki

Nein ist nicht von MS. Das ganze ist ein Echtzeit-Profiler der wenn er mit mehr als einer CPU läuft immer ganz merkwürdige Ausführungszeiten anzeigt.

che g
2003-08-05, 18:38:37
Was habt ihr gegen den Vorschlag?

zeckensack
2003-08-06, 14:53:59
Original geschrieben von che g
Was habt ihr gegen den Vorschlag? Nichts :)

Ich kenne da ganz zufällig jemanden *hüstl*, der einen bis auf Taktzyklen genauen Timer hat. Dabei wird QPC für den Abgleich benutzt.

Wie soll die nach außen sichtbare API für's Timing aussehen?
Das ganze wäre ja höchstwahrscheinlich eine DLL ...

Xmas
2003-08-06, 20:38:38
Original geschrieben von zeckensack
Wie soll die nach außen sichtbare API für's Timing aussehen?
Das ganze wäre ja höchstwahrscheinlich eine DLL ...
Eine Funktion Time() oder ähnlich die einen Float- oder Double-Wert mit der Anzahl der vergangenen Sekunden zurückgibt, entweder seit Einschalten des Rechners oder seit dem Initialisieren der DLL. Mehr ist IMO absolut nicht notwendig.

zeckensack
2003-08-06, 20:55:53
Vorschlag
1)Rendering
Nur Dreiecke. Nur indizierte Geometrie (vertex arrays & index arrays).
Damit lassen sich auch Strips/Fans rendern, indem man etwas am Index-Buffer spielt :)

Culling geht dann aber nicht transparent, ich würde sowieso vorschlagen, das wegzulassen.

Da's kein Culling gibt, man manchmal aber Pixel verwerfen möchte, würde ich einen glColorMask-ähnlichen Mechanismus vorschlagen, der Einfachheit halber aber nur eine Maske für alle Kanäle.

So weit zur Vorüberlegung.


xxxColorMask(bool enable_writes);
xxxDepthMask(bool enable_writes);
Sollte selbsterklärend sein :)

xxxSelectVertexComponent(enum vertex_component,void* component_source,unsigned int stride);

Hängt einen 'Vertex stream' (System-RAM) an eine enumeriertes Vertex-Attribut. Ich würde erstmal Position, Farbe, Texturkoordinaten vorschlagen, wobei ich Mechanismen für verschiedene Datenformate für zu kompliziert halte. Das würde ich gerne über die Enum lösen, zB
XXX_position3 3 floats
XXX_position4 4 floats
XXX_color 4 unsigned char
XXX_texcoord2 2 floats
XXX_texcoord3 3 floats
XXX_texcoord4 4 floats

Die 4d-Variante von Position ist nicht absolut notwendig, das müsste man noch ausdiskutieren ...

Jedenfalls, damit könnte man sich dann ein Vertex-Layout zusammenstückeln. Wenn man eine Komponente abschalten will, übergibt man NULL für den Zeiger.


xxxTransferVertsToHardwareBuffer(unsigned int element_count);

Überträgt die aktuell ausgewählten vertices in einen schnellen HW-Buffer. Dieser Aufruf ist optional. Der HW-Buffer wird durch diesen Aufruf Quelle für's Rendering. Er wird deselektiert und zerstört durch einen weiteren Aufruf von xxxSelectVertexComponent.

Analog dazu für Indizes
xxxSetIndexSource(enum index_type,void* source);
index_type ist entweder
XXX_unsigned_short oder
XXX_unsigned_int

xxxTransferIndicesToHardwareBuffer(unsigned int index_count);

xxxDrawGeometry(unsigned int index_count);

Zeichnet Dreiecke, indem aus dem vorher definierten Vertex Array index_count Elemente geholt werden. Die Reihenfolge steht im aktuell ausgewählten index buffer.


Meinungen?

micki
2003-08-06, 22:06:56
ColorMask würde ich zum blending dazuzählen, GL_ZERO für src und dst. für depth würde ich vorschlagen dass noch die depthfunc drinne ist (nutzt man doch so gerne beim overdraw test hier :D )

nen taktgenauen timer bekommt man bei
http://www.cpp-home.com/ unter contest da den testsource, das kann man dann wieder auf zeit umrechnen, denk ich mir.

für vertexformate wären enums sicherlich gut, ich hoffe aber wir können schöne c++ kapselung mit namespaces nutzen und nicht nur xxx_... :D


für die buffer (texturen,vertices,indices...) sollte man vor jedem nutzen vielleicht eine validierung haben, ob die buffer noch ok sind, (oder callbacks oder desgleichen,) weil wenn man vielleicht während des laufs die API wecheln könnte und dann alle buffer dann neu in die graka schieben müßte?


MfG
micki

zeckensack
2003-08-07, 13:13:45
Juhuuuuuu :wink:

Interessiert das (außer micki) niemanden?
Niemand einen Test in der Pipeline, der durch Multi-API-Tauglichkeit aufgebohrt werden kann?

Wenn dem so ist, dann höre ich jetzt sofort auf, zu denken :D

zeckensack
2003-08-07, 13:20:27
Original geschrieben von Xmas
Eine Funktion Time() oder ähnlich die einen Float- oder Double-Wert mit der Anzahl der vergangenen Sekunden zurückgibt, entweder seit Einschalten des Rechners oder seit dem Initialisieren der DLL. Mehr ist IMO absolut nicht notwendig. class
AbsTimer
{
public:
AbsTimer();
void reset();
double elapsed_seconds();

void write_timer_speed(char* target);
private:
static double tune(double max_t);

private:
x86_timestamp first_ts;
static double scale;
static bool init_done;
};

class
RelTimer
{
public:
void reset();
double elapsed_seconds();

void write_timer_speed(char* target) {a_time.write_timer_speed(target);}
private:
AbsTimer a_time;
};
Liefert signifikante Ergebnisse bis hinunter zu einzelnen Taktzyklen (in Sekunden).
Gleicht sich beim erzeugen der ersten Instanz automatisch ab (Referenz: QPC). Kann auch explizit abgeglichen werden, wobei eine maximal für den Abgleich verbratbare Zeitspanne als Parameter genommen wird.

Ein RelTimer-Objekt liefert immer die seit der letzten Abfrage vertstrichene zurück.
Ein AbsTimer-Objekt liefert die Zeit seit Erzeugung der Instanz zurück.

Der Quellcode steht unter LGPL.
... und ist von mir :D

Demirug
2003-08-07, 13:23:11
Sorry es ist einfach zu heiss für sowas.

Das grösste Problem sehe ich bei der Configuration der Pipelines. Man sollte da unter umständen einfach ein Configfile/text nehmen und auswerten lassen.