PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Direkter Zugriff auf Backpuffer vs. AA


Brillus
2004-02-07, 21:34:20
Also ich habe vor kurzen mit 3D-Programmierung angefangen. Dabei habe ich immer mir gewisse Daten für Debugging direkt auf den Backpuffer schreiben gelassen.

Dabei habe ich soeine Konstellation gewählt

lpD3DSurf->LockRect(&rectLock, NULL, 0);
Zeilenbreite = rectLock.Pitch >> 2;
Vram = (int*)rectLock.pBits;
Vram[x+y*Zeilenbreite] = Farbe;


dabei ist mir aufgefallen das dabei AA deaktiviert wird.
ich habe eine Radeon9100 hat jemand ähnliche Erfahrungen? vor allem auch mit andern Graka bzw funktioniert es bei einem von euch.

PS: Habe keinen webspace sonst würde ich ein entsprechendes Prog mal online stellen.

Gast
2004-02-07, 23:20:56
Auzug aus der MSDN:

A multisample back buffer cannot be locked

TheRealTentacle
2004-02-08, 16:29:22
Mal nen dummer Gedanke - wenn es dir möglich ist benutz mal Table Fog. Sollte die MSDN meinen, was ich denke, sollte es mit dem R200 Chip funktionieren, oder irre ich mich da?

zeckensack
2004-02-08, 19:16:57
Original geschrieben von Brillus
Also ich habe vor kurzen mit 3D-Programmierung angefangen. Dabei habe ich immer mir gewisse Daten für Debugging direkt auf den Backpuffer schreiben gelassen.

Dabei habe ich soeine Konstellation gewählt

lpD3DSurf->LockRect(&rectLock, NULL, 0);
Zeilenbreite = rectLock.Pitch >> 2;
Vram = (int*)rectLock.pBits;
Vram[x+y*Zeilenbreite] = Farbe;


dabei ist mir aufgefallen das dabei AA deaktiviert wird.
ich habe eine Radeon9100 hat jemand ähnliche Erfahrungen? vor allem auch mit andern Graka bzw funktioniert es bei einem von euch.

PS: Habe keinen webspace sonst würde ich ein entsprechendes Prog mal online stellen. Locks auf hardware-verwalteten Speicher sind grundsätzlich Design-Fehler, und was dir da passiert, ist ein Beispiel dafür, warum das so ist.

Nimm doch einfach eine Textur ...

Brillus
2004-02-12, 16:32:19
@Tentacle werde es nachher mal ausprobieren(habe gleich Fahrstunde) wenn ich herausbekomme wie es geht und was es ist sag mir im Moment ehrlich gesagt garnichts.

@Zeckensack danke für den Tip werde ich mal ausprobiere wie das dann so wird. Des weitern habe ich ja auch geschrieben das es als Debugfunktion benutzt wurde.(War eine umgeschriebene DirectDrawFunktion).

Dann ist mir gerade aufgefallen das wenn ich aus meinen prg mit Alt+Tab rausspringe und dann wieder rein weilol der Bildschirm nichtmehr die Auflösung ändert und einfach nur weiss bleibt wie bekome ich das weg habe erst an eine Restorefunktion gedacht habe aber in der Reference nicht entsprechendes gefunden und auf welche Windowsnachricht müsste man dort reakiernen?

PS: Hat solange gedaurt mit der Antwort gedauert da ich diesen Thread nach der ersten Antwort eigentlich abgehakt hatte. Ist mir jetzt gerade nur wieder zufällig aufgefallen.

PPS: Entschuldigung @ Gast hätte mich ja eigentlich bedanken gesollt für die antwort deshalb jetzt danke.

TheRealTentacle
2004-02-12, 17:37:42
Bei Table-Fog handelt es sich um Nebel. Nun kann der R200 nur dann RGSSAA verwenden, wenn Table-Fog deaktiviert ist. Meine Vermutung wäre, dass der R200 bei deaktiviertem Table-Fog die Multisampling Buffer benutzt werden können. Bei aktiviertem Fog jedoch nicht, womit ein normales OGSSAA per Supersampling (im Sinne von Hoch-runterrechnen) realisiert werden muss. Da dann die Multisampling Buffer nicht verwendet werden, könnte das von dir versuchte mit dem Backbuffer funktionieren.

Oder ist da ein Denkfehler meinerseits?

Verwenden solltest du das dann dennoch nicht. Denn das ist nur eine Chip speziefische Eigenschaft, die durch einen BUG herforgerufen wird. (Trifft auf R200 und RV250 zu)

zeckensack
2004-02-12, 18:27:48
Original geschrieben von Brillus
Dann ist mir gerade aufgefallen das wenn ich aus meinen prg mit Alt+Tab rausspringe und dann wieder rein weilol der Bildschirm nichtmehr die Auflösung ändert und einfach nur weiss bleibt wie bekome ich das weg habe erst an eine Restorefunktion gedacht habe aber in der Reference nicht entsprechendes gefunden und auf welche Windowsnachricht müsste man dort reakiernen?WM_ACTIVATE bzw WM_ACTIVATEAPP.

Variante 1 - nur Fullscreen, unsichtbar wenn nicht aktiv
Bei Deaktivierung das Fenster minimieren (ShowWindow(SW_SHOWMINNOACTIVE)) und ChangeDisplaySettings(0,0) aufrufen, um die Desktopauflösung zurück zu kriegen.

Bei Aktivierung deine gewünschte Auflösung wiederherstellen (aber bitte mit CDS_FULLSCREEN), und das Fenster wieder maximieren (ShowWindow(SW_SHOWMAXIMIZED)).

Variante 2 - Gefenstert und Fullscreen
Auf WM_SYSCOMMAND mit wParam==SC_MAXIMIZE mit dem Auflösungswechsel ins Vollbild reagieren.
Auf die Deaktivierung (wie oben) und auf WM_SYSCOMMAND mit wParam==SC_RESTORE mit Wechsel auf die Desktopauflösung reagieren, das Fenster aber nicht minimieren. Die Nachricht muss unbedingt auch an die DefWndProc weitergereicht werden, damit dein Fenster auch die Grösse ändert.

Demirug
2004-02-12, 19:06:14
Original geschrieben von zeckensack
WM_ACTIVATE bzw WM_ACTIVATEAPP.

Variante 1 - nur Fullscreen, unsichtbar wenn nicht aktiv
Bei Deaktivierung das Fenster minimieren (ShowWindow(SW_SHOWMINNOACTIVE)) und ChangeDisplaySettings(0,0) aufrufen, um die Desktopauflösung zurück zu kriegen.

Bei Aktivierung deine gewünschte Auflösung wiederherstellen (aber bitte mit CDS_FULLSCREEN), und das Fenster wieder maximieren (ShowWindow(SW_SHOWMAXIMIZED)).

Variante 2 - Gefenstert und Fullscreen
Auf WM_SYSCOMMAND mit wParam==SC_MAXIMIZE mit dem Auflösungswechsel ins Vollbild reagieren.
Auf die Deaktivierung (wie oben) und auf WM_SYSCOMMAND mit wParam==SC_RESTORE mit Wechsel auf die Desktopauflösung reagieren, das Fenster aber nicht minimieren. Die Nachricht muss unbedingt auch an die DefWndProc weitergereicht werden, damit dein Fenster auch die Grösse ändert.

Zecki, wie man an dem kurzen Codebeispiel erkennen kann kommt hier D3D zum Einsatz. Da funktionieren deine gut gemeinten OpenGL Tipps nicht.

Um den Auflösungswechsel kümmert sich D3D schon von aleine. Bei Alt+Tab oder auch CTRL+ALT+DEL geht ein D3D Device in den Lost State. Ein gerät in diesem Zustand wird beim Aufruf der Present Methode ein D3DERR_DEVICELOST als Ergebniss zurückgegeben. Daraufhin ruft man Reset auf und erzeugt alle Resourcen die im Grafikkartenram liegen neu.

Umschalten zwischen Fenster und Vollbild geht ebenfall über die Reset Methode.

Es ist allerdings trotzdem eine gute Idee WM_ACTIVATE bzw WM_ACTIVATEAPP zu verarbeiten um den Renderloop zu starten bzw zu stoppen sonst braucht die App auch im Hintergrund fleisig CPU-Leistung.

Brillus
2004-02-12, 20:08:11
@Tentakel:Also hab mal getestet mit dem Fog sieht für mich so aus also ob bei Fog nur die y-Achse Übersampelt wird (2AA) und ohne Fog es korrektes RGSS ist. habe mal ein Bild angefängt wo man es sieht.

@Zeckensack:Hab mal die Version 1 benutzt da ich bei der zweiten nicht ganz alles verstanden habe wie du es gemeint hast. So wirklich bringdst mir aber nicht zwar wechselt nun die Auflösung korrekt aber es bleibt weiterhin einfach nur weiss und 2. stellt der Monitor auf 60Hertz wohigehen er sonst aber wenn ich das Programm starte bei Korrekten 85Hertz ist.

Hier mal mein Codteil von der Callback

case WM_ACTIVATE:
wactive = LOWORD(wParam);
if(wactive==WA_ACTIVE ||wactive==WA_CLICKACTIVE)
{
DEVMODE mode;
ZeroMemory(&mode,sizeof(DEVMODE));
mode.dmSize=sizeof(DEVMODE);
mode.dmPelsHeight=HOEHE;
mode.dmPelsWidth=BREITE;
mode.dmDisplayFlags=DM_PELSHEIGHT|DM_PELSWIDTH;
ChangeDisplaySettings(&mode,CDS_FULLSCREEN);
ShowWindow(hWnd,SW_SHOWMAXIMIZED);
}
else if (wactive==WA_INACTIVE)
{
ShowWindow(hWnd,SW_SHOWMINNOACTIVE);
ChangeDisplaySettings(0,0);
}
break;
case WM_ACTIVATEAPP:
bactive =(BOOL)wParam;
if(bactive)
{
DEVMODE mode;
ZeroMemory(&mode,sizeof(DEVMODE));
mode.dmSize=sizeof(DEVMODE);
mode.dmPelsHeight=HOEHE;
mode.dmPelsWidth=BREITE;
mode.dmDisplayFlags=DM_PELSHEIGHT|DM_PELSWIDTH;
ChangeDisplaySettings(&mode,CDS_FULLSCREEN);
ShowWindow(hWnd,SW_SHOWMAXIMIZED);
}
else
{
ShowWindow(hWnd,SW_SHOWMINNOACTIVE);
ChangeDisplaySettings(0,0);
}
break;

und hier von meiner Nachrichtenschleife
while(true)
{
//Testen ob eine Nachricht vorliegt
if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
//bei WM_QUIT Schleife beenden
if(msg.message == WM_QUIT)
{
break;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
//Wenn keine Nachricht vorliegt
else
{
if(GetTickCount()>next)//Testen ob die Zeit für nächste Frame gekommen ist
{
next=GetTickCount()+FRAMEZEIT;//Zeit für das näachste Frame Berechen
nj_Render();
}
}
}

wobei die Funktion nj_Render() auch noch alle Funktionen aufruft welche für Soundausgabe,Spielereingabe etc. zuständig sind.

Godmode
2004-02-12, 20:29:49
kann es sein dass deine Nachrichtenschleife nicht mehr aufgerufen wird und dadurch die Renderfunktion auch blockiert wird?

Brillus
2004-02-12, 20:33:25
nj_Render() wird definitv aufgerufen das man am soun Hört das der Input abgefragt wird und auch der Sound gesetzt wird.

Demirug
2004-02-12, 20:39:24
Durch einen ALT+TAB geht ein D3D Device in den Lost Status dann ist nichts mehr mit rendern bevor man es nicht mit Reset wieder in den Activ Status versetzt hat. s. oben^^

zeckensack
2004-02-12, 21:12:21
Öhm ja, dann 'tschuldigung :D

Brillus
2004-02-12, 23:24:33
Das Reset schläg bei mir immer mit D3DERR_DEVICELOST fehl.

Habe auch schon probiert vorm Restore den Backpuffer und die Texturen zu Releasen hat aber nicht geklappt. Weierhin der selbe Fehler;

Für Restore benutze ich den selben D3DPRESENT_PARAMETERS wie vorher beim erstellen des Device(Globale Variable)

Edit so sieht das entsprechende Teil bei mir im Moment aus
habe mittlerweile auch wie man sieht probiert die D3DPRESENT_PARAMETERS Struktur neu zu bauen genauso wie die alte fafü den Fall das hier ein Fehler aufgetreten wäre.

HRESULT h;
h=lpD3DDevice->Present(NULL, NULL, NULL, NULL);
Log("Present");
Log(DXGetErrorString9(h));
if(h==D3DERR_DEVICELOST)
{

h=lpD3DDevice->TestCooperativeLevel();
Log("Cooperative"),
Log(DXGetErrorString9(h));
if (h==D3DERR_DEVICENOTRESET)
{
D3DADAPTERINFO* pAdapter = &Adapterinfo[dwAdapter];
D3DDEVICEINFO* pDevice = &pAdapter->Devices[pAdapter->dwAkt_Device];
D3DMODEINFO* pMode = &pDevice->Modus[pDevice->dwAkt_Mode];
D3DPRESENT_PARAMETERS d3dpp;
// Lege die Variablen für das Direct3D Device fest
ZeroMemory(&d3dpp, sizeof(D3DPRESENT_PARAMETERS));
d3dpp.Windowed = FALSE;
d3dpp.BackBufferCount = 1;
d3dpp.MultiSampleType = pDevice->MultiSampleType;
d3dpp.SwapEffect = D3DSWAPEFFECT_FLIP;
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = pMode->DepthStencilFormat;
d3dpp.hDeviceWindow = hWnd;
d3dpp.BackBufferWidth = pMode->dwBreite;
x=pMode->dwBreite;
d3dpp.BackBufferHeight = pMode->dwHoehe;
y=pMode->dwHoehe;
d3dpp.BackBufferFormat = pMode->Format;

d3dpp.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
Log("Reset:");
Log(DXGetErrorString9(lpD3DDevice->Reset(&d3dpp)));
}
}

Langsam fange ich ehrlich an zu verzweifelen

EDIT: bei dem Quellecode den ich da oben habe ist der Fehler beim Reset immer D3DERR_INVALIDCALL. Tut mir Leid das ich da etwas falsch geschriben habe aber diese Post habe ich sooft umgeschrieben das ich selbst nicht mehr genau wusste was ich rein geschrieben hatte). Habe es auch schon sFolgender weise probiert

if(h==D3DERR_DEVICELOST)
{

h=lpD3DDevice->TestCooperativeLevel();
Log("Cooperative"),
Log(DXGetErrorString9(h));
if (h==D3DERR_DEVICENOTRESET)
{
D3DADAPTERINFO* pAdapter = &Adapterinfo[dwAdapter];
D3DDEVICEINFO* pDevice = &pAdapter->Devices[pAdapter->dwAkt_Device];
D3DMODEINFO* pMode = &pDevice->Modus[pDevice->dwAkt_Mode];
D3DPRESENT_PARAMETERS d3dpp;
// Lege die Variablen für das Direct3D Device fest
ZeroMemory(&d3dpp, sizeof(D3DPRESENT_PARAMETERS));
d3dpp.Windowed = FALSE;
d3dpp.BackBufferCount = 1;
d3dpp.MultiSampleType = pDevice->MultiSampleType;
d3dpp.SwapEffect = D3DSWAPEFFECT_FLIP;
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = pMode->DepthStencilFormat;
d3dpp.hDeviceWindow = hWnd;
d3dpp.BackBufferWidth = BREITE;
d3dpp.BackBufferHeight = HOEHE;
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
// WICHTIG: Ohne dies Flag können wir BackBuffer nicht ver-
// riegeln, also nicht selbst darauf malen!!!
d3dpp.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
Log("Reset:");
Log(DXGetErrorString9(lpD3DDevice->Reset(&d3dpp)));
}
}

der fehler bleibt der gleiche. Kann es sein das ich vielleicht im D3DPRESENT_PARAMETERS etwas zuviel angegeben habe oder was vergessen habe? Im SDK finde ich azu nichts.

zeckensack
2004-02-13, 14:56:08
Ich verschiebe den Thread erstmal ins Progger-Forum.

Brillus
2004-02-13, 22:34:25
Also habe das Problem gefunden. Lag am Backbuffer.

Wundere mich nur das das Release nicht korrekt angenommen wurde. Habe jetzt die Zeile mit dem GetBackpuffer auskommentiert dann klappts. Da ich nun , wie empfohlen, statt direkt auf den Backpuffer zu schreiben in eine Textur brauch ich ihn auch nichtmehr.

Danke an alle die mir geholfen haben.