|
JLI Spieleprogrammierung
|
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen |
Autor |
Nachricht |
RayJunx JLI'ler
Alter: 43 Anmeldedatum: 16.01.2006 Beiträge: 130 Wohnort: Bayern Medaillen: Keine
|
Verfasst am: 17.01.2006, 17:03 Titel: Flaschenhals der Direct X Performance |
|
|
Habe die Ehre!
da bin ich schon wieder, man möge mir verzeihen aber ich bin auf ein irrwitziges Performance Paradoxum gestoßen, folgendes:
Auf der Suche nach dem Flaschenhals:
Eigentlich wollte ich nur Ausloten welche Programmteile bei der Grafikausgabe
die meiste Leistung schlucken und wieviel Leistung noch durch Optimierung
herausgeholt werden kann.
Grundlage: Ein Programm das exakt die Methoden aus dem Buch zur
erzeugung von Sprites (sprite.cpp) und des ResourceManagers verwendet
um 2D Texturen auf den Monitor zu zaubert und dabei die Framerate
anzeigt. Es geht um die Performance. ( Man kann auch das Asteroid Programm
verwenden, ist im prinzip dasselbe ).
Wenn ich 2000 Objekte darstelle erhalte ich bei einer Auflösung von
1600x1200 Pixel 25+-1 Frames pro Sekunde. Texturgröße 64x64 Pix
Und zwar EGAL ob ich die Bilder drehe, scaliere, oder animiere
alleine "draw" scheint die Performance zu schlucken.
Wenn ich zweimal drawe halbiert sich die Framerate näherungsweiße.
Es liegt aber auch nicht an den Klassenzugriff, wenn ich die
Set rotation aufruhfe, mehrfach wie auch die anderen Funktionen
hat es keinen einfluß auf die Performance.
vorläufiges Fazit. Angewendete Effekte spielen keine Rolle,
einzig die anzahl der draw aufruhfe. Aber das kann doch nicht
sein? Wenn die grafikkarte richtig genutzt wird
müßte ich doch viel mehr grafiken direkt mappen können,
als ich grafiken, scaliere, rotieren und DANN auf den
bildschirm stempeln kann. Wo liegt der hund begraben?
Wenn ich die Auflösung der Grafik bis runter auf 16x16 schraube
ändert das nämlich auch in keiner weiße die Performance !?
Rechner: 3,2GHZ AMD 2GIG RAM 512 ATI-X850 256MB Grafikkarte
Hier habe ich einen Auszug der den Draw befehl der Sprite klasse
zeigt. Es würde mich sehr freuen wenn mir jemand sagen kann
woran das ganze Programm lahmt. Man will ja weder Leistung
noch Grafikpower verschenken, nicht wenn nur irgendwo ein
Flaschenhals das Programm herunterwürgt.
gruß an alle!
Rayjunx
Code: |
// Sprite zeichnen
void CSprite::Draw(void)
{
// Sprite in der passenden Animationsstufe zeichnen
m_lpSprite->Draw(m_AnimationVec[m_CurrentImage],
0,
&m_vScale,
&m_vRotationCenter,
m_Rotation,
&m_vPosition,
0xFFFFFFFF);
}
|
_________________ Just a Freak |
|
Nach oben |
|
|
PeaceKiller JLI Master
Alter: 35 Anmeldedatum: 28.11.2002 Beiträge: 970
Medaillen: Keine
|
Verfasst am: 17.01.2006, 17:21 Titel: |
|
|
Soviel ich weiß verwendet die Erstausgabe von JLI mit DX8 (oder war's 9?) für jedes Sprite ein extra DX-Spriteobjekt. Das könnte ein Flaschenhals sein.
Außerdem ist das verhalten völlig normal auf heutigen GPUs. Die sind heutzutage auf wenige Calls mit vielen Polygonen ausgelegt. Also macht es einen riesen Unterschied, ob du 10*100 000 Polygone zeichnest, oder 100 000*10 Polygone. _________________ »If the automobile had followed the same development cycle as the computer, a Rolls-Royce would today cost $100, get a million miles per gallon, and explode once a year, killing everyone inside.«
– Robert X. Cringely, InfoWorld magazine |
|
Nach oben |
|
|
RayJunx JLI'ler
Alter: 43 Anmeldedatum: 16.01.2006 Beiträge: 130 Wohnort: Bayern Medaillen: Keine
|
Verfasst am: 17.01.2006, 17:31 Titel: auf der suche |
|
|
Hi!
erstmal danke die ideen sind schonmal gut. Es sieht so aus als würde das buch schon die 9directx verwenden.
das eigene sprite objekte erzeugt werden könnte ein argument sein,
kann man das den irgendwie umgehen?
Anbei ist der direct3d code, ist unverändert von mir aus dem buch
übernommen worden.
Würde es klasse finden wenn man auf mehr objekte hochschrauben
könnte ohne das die performance sich alleine an der anzahl
aufhängt.
vielleicht findet ja jemand die achilles sehne
gruß
Rayjunx
Code: |
#include "Direct3D.h"
#include "global.h"
#include <dxerr9.h>
CDirect3D::CDirect3D()
{
m_lpD3D = NULL;
m_lpD3DFont = NULL;
m_lpD3DDevice = NULL;
m_lpBackBuffer = NULL;
}
CDirect3D::~CDirect3D()
{
CleanUp();
}
// Direct3D initialisieren
BOOL CDirect3D::Init(HWND hWnd, BOOL bWindowed)
{
// Direct3D-Objekt erzeugen
m_lpD3D = Direct3DCreate9(D3D_SDK_VERSION);
if(NULL == m_lpD3D)
{
// Fehler, D3D-Objekt wurde nicht erzeugt
return FALSE;
}
// Parameter für den Modus festlegen
D3DPRESENT_PARAMETERS PParams;
ZeroMemory(&PParams,sizeof(PParams));
PParams.SwapEffect = D3DSWAPEFFECT_DISCARD;
PParams.hDeviceWindow = hWnd;
PParams.Windowed = bWindowed;
PParams.BackBufferWidth = SCR_WIDTH;
PParams.BackBufferHeight = SCR_HEIGHT;
PParams.BackBufferFormat = D3DFMT_A8R8G8B8;
HRESULT hr;
// Direct3D-Gerät anlegen
if(FAILED(hr = m_lpD3D->CreateDevice(
D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&PParams,
&m_lpD3DDevice)))
{
// Fehler, Gerät kann nicht angelegt werden
const char* Err = DXGetErrorDescription9(hr);
DXTRACE_MSG(Err);
return FALSE;
}
// Schrift erzeugen
CreateFont();
// Zeiger auf dem Hintergrundpuffer holen
m_lpD3DDevice->GetBackBuffer(0,0,
D3DBACKBUFFER_TYPE_MONO,
&m_lpBackBuffer);
return TRUE;
}
// Zeiger auf den Hintergrundbuffer zurückgeben
LPDIRECT3DSURFACE9 CDirect3D::GetBackbuffer(void)
{
return m_lpBackBuffer;
}
// Farbe für den Backbuffer festlegen
void CDirect3D::SetClearColor(D3DCOLOR Color)
{
m_ClearColor = Color;
}
// Text an Position x,y ausgeben
void CDirect3D::DrawText(LPCSTR Text, int x, int y, D3DCOLOR TextColor)
{
RECT r = { x, y, 0, 0 };
// Größe des Rechtecks berechnen
m_lpD3DFont->DrawText(Text, -1, &r, DT_CALCRECT, TextColor);
// Text ausgeben
m_lpD3DFont->DrawText(Text, -1, &r, DT_CENTER, TextColor);
}
// Methoden zum Start/Beenden der Szene
void CDirect3D::BeginScene(void)
{
m_lpD3DDevice->Clear(0,0,D3DCLEAR_TARGET,m_ClearColor,0,0);
m_lpD3DDevice->BeginScene();
}
void CDirect3D::EndScene(void)
{
m_lpD3DDevice->EndScene();
m_lpD3DDevice->Present(0,0,0,0);
}
// Erzeugen der D3D-Schrift
void CDirect3D::CreateFont(void)
{
// Struktur für die Beschreibung der Schriftart
// anlegen und Elemente mit 0 initialisieren
LOGFONT LogFont = { 0 };
// das Element lfFaceName muss den Namen der
// gewünschten Schriftart enthalten
strcpy(LogFont.lfFaceName, "system");
// nach erfolgreichem Aufruf zeigt lpD3DFont
// auf ein Objekt vom Typ D3DXFont
D3DXCreateFontIndirect(m_lpD3DDevice,
&LogFont,
&m_lpD3DFont);
}
// Diese Methode zeichnet eine Ellipse
void CDirect3D::DrawEllipse(int x1,int y1, int x2, int y2, LPDIRECT3DSURFACE9 lpSurface)
{
HDC hDC;
if(FAILED(lpSurface->GetDC(&hDC)))
{
DXTRACE_MSG("DC ist nicht verfügbar");
}
else
{
// Ellipse zeichnen
Ellipse(hDC,x1,y1,x2,y2);
// Wichtig! Device Context wieder freigeben
lpSurface->ReleaseDC(hDC);
}
}
// Screenshot erzeugen
void CDirect3D::CreateScreenshot(char* Filename)
{
// temporäre Oberfläche für den Screenshot anlegen
LPDIRECT3DSURFACE9 lpSurface;
m_lpD3DDevice->CreateOffscreenPlainSurface(
SCR_WIDTH,SCR_HEIGHT,
D3DFMT_A8R8G8B8,
D3DPOOL_SYSTEMMEM,
&lpSurface,0);
// Inhalt des Frontbuffer in die Oberfläche kopieren
m_lpD3DDevice->GetFrontBufferData(0,lpSurface);
// Oberfläche in Datei speichern
D3DXSaveSurfaceToFile(Filename,D3DXIFF_BMP,
lpSurface,0,NULL);
// temporäre Oberfläche wieder freigeben
lpSurface->Release();
}
// das Direct3D-Device zurückgeben
LPDIRECT3DDEVICE9 CDirect3D::GetDevice(void)
{
return m_lpD3DDevice;
}
// Freigeben der Objekte
void CDirect3D::CleanUp(void)
{
// testen, ob die Objekt angelegt
// wurden und ggf. freigeben
if(NULL != m_lpD3DFont)
{
m_lpD3DFont->Release();
m_lpD3DFont = NULL;
}
if(NULL != m_lpBackBuffer)
{
m_lpBackBuffer->Release();
m_lpBackBuffer = NULL;
}
if(NULL != m_lpD3DDevice)
{
m_lpD3DDevice->Release();
m_lpD3DDevice = NULL;
}
if(NULL != m_lpD3D)
{
m_lpD3D->Release();
m_lpD3D = NULL;
}
}
|
_________________ Just a Freak |
|
Nach oben |
|
|
Patrick Dark JLI Master
Anmeldedatum: 25.10.2004 Beiträge: 1895 Wohnort: Düren Medaillen: Keine
|
|
Nach oben |
|
|
GreveN JLI Master
Alter: 38 Anmeldedatum: 08.01.2004 Beiträge: 901 Wohnort: Sachsen - Dresden Medaillen: Keine
|
Verfasst am: 17.01.2006, 17:54 Titel: |
|
|
Im Buch wird meines Wissens auch das D3DX-Spriteobjekt verwendet, und das ist sowieso nicht grade für seine überragende Performance bekannt, zudem ist der Code im Buch nunmal auch eher auf leichte Verständlichkeit als auf Highspeed ausgerichtet, von daher finde ich 25 FPS bei 2000 Objekten... naja... angemessen.
Lässt sich natürlich einiges mehr rausholen, wenn du das ganze per Hand machst, immer 4 Vertices + Textur drauf und du hast dein Sprite. Und an dieser Stelle gehts auch schon los, die Vertices sollten nach Möglichkeit im schnellen Grafikkartenspeicher liegen, das spart beim Rendern wertvolle Zeit, jedoch solltest du auch nicht für jedes kleine Kacksprite einen eigenen Vertexbuffer anlegen sondern mehrere zusammenfassen, wie Peace Killer schon sagte, ist das Rendern großer Datenmengen aus einem Buffer auf einen Rutsch wesentlich schneller als viele kleine Buffer zu rendern. Ordentlich Speed können auch nochmal Indexbuffer bringen. Ansonsten drauf achten, dass du nach Möglichkeit den best optimiertesten Primitiventyp verwendest (in OGL z.B. Triangle-Strips), dass du nicht unbedingt mehr renderst wie nötig (Stichwort Culling), wobei wiederum zusagen ist, dass es moderne GPU's einen Feuchten schert, ob sie mal eben ein paar Hundert Polygone mehr oder weniger zu Rendern haben, also an dieser Stelle mit dem Filtern und Sortieren nicht übertreiben. Weiterhin solltest du eine gewisse Sortierung in deine zu rendernden Objekte bringen, um z.B. unnötige Texturswitches zu vermeiden, usw. usf., um dir nur mal 'nen groben Überblick zu geben.
Über das Thema kann man ganze Bücher schreiben.
p.s.: Ich hab die Erfahrung gemacht, dass du moderne Grafikkarten eher durch das übermäßige Verpulvern von Füllrate in die Knie zwingst, als durch überflüssige Geometrie. |
|
Nach oben |
|
|
RayJunx JLI'ler
Alter: 43 Anmeldedatum: 16.01.2006 Beiträge: 130 Wohnort: Bayern Medaillen: Keine
|
Verfasst am: 17.01.2006, 18:45 Titel: weiha |
|
|
na da hab ich aber was losgetreten.
mußte eben auch feststellen das ich auf über die bisherige sprite methode auch weit mehr als 256 theoretischen texturenspeicher reinladen.
er verbraucht nur immer mehr normalen arbeitsspeicher. außerdem läuft
alles dadurch garnicht langsamer, was mir sagt das er von vornherein scheinbar nicht den grafikkarten speicher verwendet!??
ach man eigentlich will ich ja nur 2d texturen darstellen,
mit alphachanal überblendung, rotation, position, und das wars.
kann ich den ohne großes taram einfach solche optimierten
elemente erzeugen im grafikspeicher anlegen und verwalten?
ich dachte immer im buch stand das das schon im grafikkarten speicher abgelegt wird, siehe beispiel oben... ??? _________________ Just a Freak |
|
Nach oben |
|
|
fast hawk Senior JLI'ler
Anmeldedatum: 15.07.2005 Beiträge: 237 Wohnort: Freiburg Medaillen: Keine
|
Verfasst am: 17.01.2006, 18:52 Titel: |
|
|
Schon wieder ein doppelpost(du musst nur ein mal auf absenden gehen)!!
Du kannst des auch mit surface machen dann musst du sie aber
händisch rotieren. Dafür aber deutlich schneller vorallem bei großen Flächen
und wenigen. _________________ Jetziges Projekt: The Ring War
Status: 40%
-----------------------------------
Nicht weil es schwer ist, wagen wir es nicht, sondern weil wir es nicht wagen, ist es schwer.
--
Lucius Annaeus Seneca (4)
röm. Philosoph, Dramatiker und Staatsmann |
|
Nach oben |
|
|
GreveN JLI Master
Alter: 38 Anmeldedatum: 08.01.2004 Beiträge: 901 Wohnort: Sachsen - Dresden Medaillen: Keine
|
Verfasst am: 17.01.2006, 18:52 Titel: |
|
|
Hm... das sauber mit ordentlich Speed hinzukriegen erfordert schon "etwas" Arbeit und Erfahrung, allerdings ist der Lerneffekt auch nicht zu verachten.
Wenn du meinst, dass du soweit bist, dass du dir auch losgelöst vom Buch etwas aneignen könntest, dann könntest du z.B. mal mit diversen Fix-und-Fertig-Engines rumspielen, HGE z.B. ist vom Design und Aufbau her zumindest relativ leicht zugänglich und liefert performancemäßig brauchbare Ergebnisse. |
|
Nach oben |
|
|
51m0n JLI'ler
Alter: 32 Anmeldedatum: 06.01.2006 Beiträge: 167 Wohnort: Erkelenz Medaillen: Keine
|
Verfasst am: 17.01.2006, 19:16 Titel: |
|
|
Hi
fast hawk hat Folgendes geschrieben: |
Du kannst des auch mit surface machen dann musst du sie aber
händisch rotieren. Dafür aber deutlich schneller vorallem bei großen Flächen
und wenigen. |
Ist es Ratsam stattdessen Surfaces zu nehmen? Ich hatte nämlich teilweise das gefühl, dass es dadurch etwas lansamer wurde. Oder irre ich mich? _________________ Teigwaren
heißen Teigwaren,
weil sie früher einmal Teig waren |
|
Nach oben |
|
|
GreveN JLI Master
Alter: 38 Anmeldedatum: 08.01.2004 Beiträge: 901 Wohnort: Sachsen - Dresden Medaillen: Keine
|
Verfasst am: 17.01.2006, 19:20 Titel: |
|
|
Hängt davon ab, reden wir von DirectDraw-Surfaces? |
|
Nach oben |
|
|
RayJunx JLI'ler
Alter: 43 Anmeldedatum: 16.01.2006 Beiträge: 130 Wohnort: Bayern Medaillen: Keine
|
Verfasst am: 17.01.2006, 19:20 Titel: nachgelesen |
|
|
hi,
habe mich noch etwas schlau gelesen. Also einmal ist es ganz gut das program wie ich es verwende verwaltet die texturen dann, bzw schiebt sie in den schnellsten bereich laut buch, auf die grafikkarte bzw agp speicher, und soweit bin ich ja mit den ergebnissen ganz zufrieden.
außerdem belegen die texturen nicht die ungepackte größe so wie aussieht
eine 137mb textur (pixel mal 4byte) schluckt zum beispiel ca 12mb mehr arbeitsspeicher wenn ich ihn zum auslagern bringe. also irgendwie weiß ich nicht wie ers tut aber mit 1000 objekten bei 60hz was der rate meines
tfts entspricht fahr ich ganz gut. auch bei 1920x1200er auflösung.
ich habe auch gesehen das es maßgeblich von der prozessorleistung
abhäng, ein über oder untertakten meiner grafikkarte hat nämlich
praktisch auch keine auswirkung, bzw es hängt auch primär von
der geschwindigkeit der speicheranbindung ab, so bisher mein eindruck
werde jetzt erstmal damit arbeiten wenn ich dann wirklich an die grenzen kommen sollte kann ich sicher was anderes ausloten.
eine frage habe ich noch, wie viel schneller wären den andere
routinen? Kann mal eben einer einfach 2000 bildchen mit 64x64
pixel mit "seiner" engine darstellen und schaun ob er auf 60 frames
kommt? bzw wieviele sprites er bei 60 frames fahren kann ?
gruß
Rayjunx _________________ Just a Freak |
|
Nach oben |
|
|
GreveN JLI Master
Alter: 38 Anmeldedatum: 08.01.2004 Beiträge: 901 Wohnort: Sachsen - Dresden Medaillen: Keine
|
Verfasst am: 17.01.2006, 19:22 Titel: |
|
|
Lol, da sollten 1000 FPS fast kein Problem sein. |
|
Nach oben |
|
|
51m0n JLI'ler
Alter: 32 Anmeldedatum: 06.01.2006 Beiträge: 167 Wohnort: Erkelenz Medaillen: Keine
|
Verfasst am: 17.01.2006, 19:24 Titel: |
|
|
GreveN hat Folgendes geschrieben: | Hängt davon ab, reden wir von DirectDraw-Surfaces? |
Ja _________________ Teigwaren
heißen Teigwaren,
weil sie früher einmal Teig waren |
|
Nach oben |
|
|
AFE-GmdG JLI MVP
Alter: 45 Anmeldedatum: 19.07.2002 Beiträge: 1374 Wohnort: Irgendwo im Universum... Medaillen: Keine
|
Verfasst am: 17.01.2006, 19:26 Titel: |
|
|
Also mit meiner 3D-Engine Rendere ich derzeit etwa 100000 Polygone flüssig - wobei ich definitif sagen kann, dass ich den selben Vertex und Indexbuffer nutze, keine Texturchanges drinn hab und einfach nur ein und das selbe Objekt nur sehr oft pro Frame rendere. Aber 3D ist ja eh nicht mit Spritebasiertem 2D zu vergleichen... _________________
CPP: | float o=0.075,h=1.5,T,r,O,l,I;int _,L=80,s=3200;main(){for(;s%L||
(h-=o,T= -2),s;4 -(r=O*O)<(l=I*I)|++ _==L&&write(1,(--s%L?_<(L)?--_
%6:6:7)+\"World! \\n\",1)&&(O=I=l=_=r=0,T+=o /2))O=I*2*O+h,I=l+T-r;} |
|
|
Nach oben |
|
|
GreveN JLI Master
Alter: 38 Anmeldedatum: 08.01.2004 Beiträge: 901 Wohnort: Sachsen - Dresden Medaillen: Keine
|
Verfasst am: 17.01.2006, 20:29 Titel: |
|
|
Wie gesagt, kann ich aus Erfahrung bestätigen, dass Geometrie heutzutage fast kein Problem darstellt, problematisch wirds nach meinen persönlichen Erfahrungen bei den Füllraten, insbesondere auch, wenn man ohne z-Buffer arbeitet.
51m0n hat Folgendes geschrieben: | GreveN hat Folgendes geschrieben: | Hängt davon ab, reden wir von DirectDraw-Surfaces? |
Ja |
DD ist im Großen und Ganzen immer noch sehr fix, besonders unter 16 Bit. Etwas problematisch wirds nur dann, wenn du deine Sprites rotieren, skalieren bzw. transparent machen willst. DD bietet da keinen direkten Support über die GPU, d.h. du musst das alles per Hand machen und das ist im Normalfall nicht so wahnsinnig schnell. |
|
Nach oben |
|
|
|
|
Du kannst keine Beiträge in dieses Forum schreiben. Du kannst auf Beiträge in diesem Forum nicht antworten. Du kannst deine Beiträge in diesem Forum nicht bearbeiten. Du kannst deine Beiträge in diesem Forum nicht löschen. Du kannst an Umfragen in diesem Forum nicht mitmachen.
|
Powered by phpBB © 2001, 2005 phpBB Group Deutsche Übersetzung von phpBB.de
|