Direct3D(X?) Fragen



  • Hi, ich habe eben angefangen mal etwas mit D3D rumzuwurschteln - und schon sind die ersten Fragen aufgetaucht 😉 Sollten aber eigentlich leicht zu beantworten sein..

    1.: In den Beispielen des DirectXSDK gibts eine Funktion "Render()" die zB. so aussieht:

    VOID Render()
    {
        // Clear the backbuffer to a blue color
        g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB( 0, 0, 0 ), 0.0f, 0 );
    
        // Begin the scene
        if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
        {
            g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof( CUSTOMVERTEX ) );
            g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
            g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 1 );
    
            // End the scene
            g_pd3dDevice->EndScene();
        }
    
        // Present the backbuffer contents to the display
        g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
    }
    

    Der MessageLoop sieht so aus:

    while( msg.message != WM_QUIT )
    {
      if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
      {
        TranslateMessage( &msg );
        DispatchMessage( &msg );
      }
      else
        Render();
    }
    

    Meine Frage ist jetzt warum die CPU-Last hierbei nicht auf 100% ansteigt. Denn eigentlich wartet die Funktion "Render" doch nirgendwo? Oder?

    2.: Ich habe zwei Monitore, einen CRT und einen TFT. Die FPS messe ich mit Fraps. Ist das Fenster vollständig auf dem CRT werden mir 85 FPS angezeigt (oh wunder, genau die Refresh-Rate des Monitors). Ist das Fenster allerdings auf meinem TFT habe ich komischerweise nur 43 FPS - und das schwankt dann ab und zu auf 53 FPS. (Der Monitor läuft mit 75HZ)
    Warum ist das so? Warum habe ich da nicht 75 oder zumindest 60 Hz?

    Besten Dank für eure Hilfe im voraus 😃



  • also soweit ich weis ist das so mit beginScene und EndScene alle daten an die GPU (grafikkarte) geshcickt werden, dort werden sie weiter berechent wie das halt auf dem monitor später aussehen wird...

    das ist so geregelt(ich denke mal intern in directX mit threads) dass halt die gpu die arbeit ab hier für den render krams berechnet und somit die CPU die hände frei hat

    so kannst du erst alles berechnet, parallel dazu auf der cpu kannst du z.b. die KI berechnen oder sonst irgendwas machen
    und danach rufst du die present methode auf und alles kommt auf den bildschirm

    beachte: rufst du present direkt nach dem begin/end scene und damit vor dem anderen berechnungen auf, kannst du das gesamte system aber knicken, da das programm dann auf das rendern wartet um es auf den bildschirm zu releasen...



  • Das "die GPU rechnet" erklärt aber nicht dass die CPU nicht unter Volllast läuft. Denn "PeekMessage" kehrt sofort zurück also muss irgendeine Funktion in "Render" kernelgesteuert warten..

    Den letzten Kommentar verstehe ich nicht so ganz - ist aber wie gesagt einfach ein Ausschnitt aus der DirectXSDK Doku.. (also nur eine Demo - kein Spiel oder sowas). Würde mich aber trotzdem interessieren was Du damit meinst 😉



  • Ich vermute mal dass VSync an ist was dazu führt dass eben Present() auf den VSync wartet. Der TFT ist evtl. dein sekundärer Bildschirm? Hängt der auf der selben Grafikkarte? Auf Windows XP wars eigentlich üblich dass die Performance auf einem sekundären Bildschirm signifikant schlechter ist als am primären...



  • @cooky451:
    Dass du auf deinem "Haupt-Monitor" genau 85 Hz hast, liegt vermutlich daran, dass du D3DPRESENT_INTERVAL_ONE eingestellt hast.

    Damit wird D3D angewiesen bei Present() so lange zu warten, dass pro Frame das der Monitor ausgibt auch immer nur ein neues Bild angezeigt wird.

    Das erklärt auch warum du eine so niedrige CPU Auslastung hast: die Render() Funktion wartet in Present(). Stell mal probeweise D3DPRESENT_INTERVAL_IMMEDIATE ein, dann wirst du a) eine höhere Framerate haben und b) eine höhere CPU Auslastung. Auf 100% wirst du damit nicht unbedingt kommen, da Present() auch warten muss bis die Grafikkarte das Bild fertig aufgebaut hat. In der Zeit wartet die CPU auch bloss, daher keine 100% CPU Auslastung.
    (D3D kann asynchron rendern, d.h. nachdem DrawPrimitive() zurückkommt ist noch nicht unbedingt alles fertig gerendert -- erst wenn die fertigen Bilddaten gebraucht werden, wird gewartet)

    Was das Rumschieben des Fensters angeht: das Treibermodell von D3D9 zwingt den Treiber für jeden Monitor einen eigenen "Adapter" zu machen. Und resourcen (Texture, Back-Buffer etc.) können immer nur einem Adapter gehören. Jetzt initialisierst du das D3D Device auf dem ersten Adapter (=dem ersten Monitor), und zeigst es (bzw. einen Teil davon) auf dem 2. Adapter an. Damit das geht, muss D3D den Inhalt des Back-Buffers vom 1. Adapter auf den 2. Adapter kopieren. Ich vermute dass das Treibermodell von D3D9 es auch nicht ermöglicht dass der Treiber dabei irgendwas optimiert. Vermutlich wird dabei sogar der Back-Buffer Inhalt zuerst ins RAM kopiert, und dann vom RAM aus wieder auf den 2. Adapter.

    Falls dein Programm erkennt wann ein Fenster von einem Monitor auf einen anderen verschoben wurde, und dann entsprechend das D3D9 Device zerstört, und mit der "neuen" Adapternummer neu anlegt, dann sollte alles wieder normal laufen, sobald du das Fenster vollständig auf den 2. Monitor verschoben hast, so dass kein Teil des Fensters mehr "raussteht". Genau dieses Verhalten kannst du auch bei den ganzen D3D9 Samples vom SDK beobachten.



  • Super, damit wäre alles geklärt 🙂
    Die DirectX samples kann ich leider noch nicht komplett nachvollziehen, da ich erst heute Abend mit DirectX angefangen habe und mich somit noch durch die "Tuts" kämpfe 😃

    Ach ja - falls jemand abgesehen von "directxtutorial.com" und "msdn.com" noch gute DirectX Einführungen kennt immer her damit!


Anmelden zum Antworten