D3D9 Present() zwei mal aufrufen



  • Also das Problem liegt darin, dass ich in der eigentlich Szene zwar nur einmal Present aufrufe, da wenn ich auf Pause drücke meine Draw-Funktion garn icht aufgerufen wird, jedoch Cleare ich die alte gerenderte Szene nicht, sodass der Present aufruf aus dem Frame davor dann der erste ist, und beim Pause-Drücken dann der zweite.
    Clearen möchte ich die Szene jedoch nicht, da ich keinen schwarzen Hintergrund möchte und die Szene neuzeichen wäre auch nicht gerade optimal.



  • Pikkolini schrieb:

    .. und die Szene neuzeichen wäre auch nicht gerade optimal.

    Warum nicht?


  • Mod

    je nach presentation parametern wird der backbuffer kopiert oder gegen den frontbuffer getauscht. um dich darauf aufmerksam zu machen, cleart d3d abwechselnt mit pink und tuerkis den hintergrund.
    es ist also reiner zufall dass es im release funktioniert.
    present sorgt dafuer, dass das angezeigt wird, was du zwischen diesem present und dem letzten present gezeichnet hast, es kann sein dass der treiber tripplebuffert oder wegen sli karten quadbuffert oder ...

    du kannst
    1. die scene neu zeichnen und darueber deinen text dann present
    2. die scene in ein temporaeres surfaces kopieren und dann vor dem text auf den backbuffer blitten (z.b. mit stretchrect)
    3. presentation paramenters umstellen dass du blitting haben willst, statt swap.



  • rapso schrieb:

    3. presentation paramenters umstellen dass du blitting haben willst, statt swap.

    Bei swap würde er keinen pinken/grünen Bildschirm mit der Debug-Runtime bekommen.
    -> er hat vermutlich discard eingestellt.



  • Also ich habe mal versucht den Swapeffekt zu ändern, jedoch scheitern alle Versuche, einen Device zu erstellen, wenn ich kein D3DSWAPEFFECT_DISCARD benutze. Ich habe auch schon ein bisschen mit den PresentationInterval rumprobiert, jedoch bekomme ich es damit auch nicht hin, D3DSWAPEFFECT_COPYoder D3DSWAPEFFECT_FLIP zum laufen zu bringen. Hier mal meine momentanen PresentationParamter:

    D3DPRESENT_PARAMETERS d3dpp;
    std::memset(&d3dpp, 0, sizeof(d3dpp));
    d3dpp.BackBufferWidth = width;
    d3dpp.BackBufferHeight = height;
    d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
    d3dpp.BackBufferCount = D3DPRESENT_BACK_BUFFERS_MAX;
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
    d3dpp.hDeviceWindow = hWnd;
    d3dpp.Windowed = true;
    d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
    

  • Mod

    versuch mal d3dpp.BackBufferCount auf 1 zu stellen. ansonsten sieht es ok aus fuer mich.



  • Im "Windowed" Mode würde ich D3DSWAPEFFECT_COPY empfehlen, das ist der "natürliche" Swap-Effekt für Windowed (d.h. kein zusätzlicher Overhead). Zumindest mit D3D9 ohne Desktop-Composition. Mit D3D > 9 und/oder Desktop-Composition kenn ich mich nicht aus, k.a. ob das da anders läuft.

    Und wie rapso schon geschrieben hat, solltest du BackBufferCount auf 1 stellen.



  • Ok, mit BackBufferCount auf 1 funktioniert es, jedoch musste ich gerade feststellen, dass das ganze mit multisampling nicht mehr funktioniert, da meldet mir die Debug-Runtime immer

    Direct3D9: (ERROR) :Multisampling requires D3DSWAPEFFECT_DISCARD. ValidatePresentParameters fails.
    D3D9 Helper: IDirect3D9::CreateDevice failed: D3DERR_INVALIDCALL
    

    Das ist ja dann auch nicht das gelbe vom Ei...



  • MS braucht eben zwingend D3DSWAPEFFECT_DISCARD. Ich wuerde generell immer D3DSWAPEFFECT_DISCARD nehmen, da das auch von der Doku empfohlen wird (erlaubt Optimierungen).



  • Pikkolini schrieb:

    Ok, mit BackBufferCount auf 1 funktioniert es, jedoch musste ich gerade feststellen, dass das ganze mit multisampling nicht mehr funktioniert, da meldet mir die Debug-Runtime immer

    Direct3D9: (ERROR) :Multisampling requires D3DSWAPEFFECT_DISCARD. ValidatePresentParameters fails.
    D3D9 Helper: IDirect3D9::CreateDevice failed: D3DERR_INVALIDCALL
    

    Das ist ja dann auch nicht das gelbe vom Ei...

    Ok.
    Was willst du jetzt von uns?
    Du machst was, was mit DISCARD nicht geht. Sagen wir machs halt anders. Das willst du nicht. Sagen wir dir dann nimm halt SWAP. Jetzt sagst du du willst aber doch DISCARD verwenden.
    Was jetzt?
    Sind wir wieder zurück bei "machs halt anders" (aka. ruf nicht 2x Present auf).


  • Mod

    Pikkolini schrieb:

    Ok, mit BackBufferCount auf 1 funktioniert es, jedoch musste ich gerade feststellen, dass das ganze mit multisampling nicht mehr funktioniert, da meldet mir die Debug-Runtime immer

    Direct3D9: (ERROR) :Multisampling requires D3DSWAPEFFECT_DISCARD. ValidatePresentParameters fails.
    D3D9 Helper: IDirect3D9::CreateDevice failed: D3DERR_INVALIDCALL
    

    Das ist ja dann auch nicht das gelbe vom Ei...

    hab die 3 gelb variationen vom ei nochmal erweitert, du hast die freie wahl

    du kannst
    1. die scene neu zeichnen und darueber deinen text, dann present
    2. die scene in ein temporaeres surfaces kopieren und dann vor dem text auf den backbuffer blitten (z.b. mit stretchrect)
    3. presentation paramenters umstellen dass du blitting haben willst, statt swap/discard, falls du kein antialiasing verwendest



  • Also obwohl Variante 1 dann wohl wesentlich sinnvoller ist, habe ich mal rein aus Lerneffekt an Variante zwei probiert.
    Das ist bisher rumgekommen:

    LPDIRECT3DSURFACE9 tempSurf = nullptr;
    if (FAILED(d3dd->CreateOffscreenPlainSurface(screenWidth, screenHeight, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &tempSurf, nullptr)))
    	throw std::runtime_error("Pausieren fehlgeschlagen");
    
    if (FAILED(d3dd->GetFrontBufferData(0, tempSurf)))
    	throw std::runtime_error("Pausieren fehlgeschlagen");
    
    LPDIRECT3DSURFACE9 backBuffer = nullptr;
    if (FAILED(d3dd->GetRenderTarget(0, &backBuffer)))
    	throw std::runtime_error("Pausieren fehlgeschlagen");
    
    RECT rect = {gameX, gameY, gameWidth, gameHeight};
    
    d3dd->UpdateSurface(tempSurf, &rect, backBuffer, nullptr);
    

    Das Problem dabei ist jetzt, dass mein BackBuffer das Format D3DFMT_X8R8G8B8 und GetFrontBufferData das Format D3DFMT_A8R8G8B8.
    Deswegen schlägt dann auch UpdateSurface fehl. Gibt es da eine möglichkeit, die beiden Formate ineinander zu überführen, indem man z.B. den Alpha-Wert einfach ignoriert?
    Wenn nicht ist auch wurscht, benutze jetzt eh Variante 1.


  • Mod

    wieso gibst du nicht beiden das selbe format?


Anmelden zum Antworten