[c++/DirectX]Reset pD3DDevice

kickerxy123

Erfahrenes Mitglied
Hallo!

Ich habe ein Problem beim Reset des pD3DDevices meiner DX-Applikation.
Hier zunächst der (grobe) Ablauf meines Programmes:

initWindow();
initDirectX();

if(lostDevice())
-->solange waten, bis Status D3DERR_DEVICELOST in D3DERR_DEVICENOTRESET geändert ist
-->preReset();
-->pD3DDevice->Reset(pparams);
-->praeReset();

usw.


soweit sollte alles stimmen. Das Problem betrifft nun den Reset an sich. Der Dx-DebuggerOutput meldet mir





......
00000038 6.04019547 [516]
00000039 6.04024124 [516] Direct3D9: :WM_ACTIVATEAPP: DONE Activating app pid=00000204, tid=00000a30
00000040 6.04027605 [516]
00000041 6.05306149 [516] Direct3D9: (ERROR) :The following D3DPOOL_DEFAULT surfaces/buffers/textures still exist
00000042 6.05309105 [516]
00000043 6.05313826 [516] Direct3D9: (ERROR) : D3DRTYPE_SURFACE
00000044 6.05317259 [516]
00000045 6.05321836 [516] Direct3D9: (ERROR) : Memory Address: 04391080 lAllocID=41 dwSize=00000050, (pid=00000204)
00000046 6.05325222 [516]
00000047 6.05329132 [516] Direct3D9: (ERROR) : Stack Back Trace
00000048 6.05332804 [516]
00000049 6.05336952 [516] Direct3D9: (ERROR) : [0] : Address 03D26C86
00000050 6.05340576 [516]
00000051 6.05344629 [516] Direct3D9: (ERROR) : [1] : Address 03DFAB63
00000052 6.05349350 [516]
00000053 6.05353355 [516] Direct3D9: (ERROR) : [2] : Address 03D44539
00000054 6.05356884 [516]
00000055 6.05360842 [516] Direct3D9: (ERROR) : [3] : Address 03D47431
00000056 6.05364323 [516]
00000057 6.05368328 [516] Direct3D9: (ERROR) : [4] : Address 03D438E7
00000058 6.05371666 [516]
00000059 6.05375481 [516] Direct3D9: (ERROR) : [5] : Address 03D5555C
00000060 6.05378962 [516]
00000061 6.05382729 [516] Direct3D9: (ERROR) : [6] : Address 03DF59F3
00000062 6.05386209 [516]
00000063 6.05390024 [516] Direct3D9: (ERROR) : [7] : Address 03D8D112
00000064 6.05393457 [516]
00000065 6.05397272 [516] Direct3D9: (ERROR) : [8] : Address 0040337B
00000066 6.05400801 [516]
00000067 6.05404711 [516] Direct3D9: (ERROR) : [9] : Address 00420D3B
00000068 6.05408096 [516]
00000069 6.05412149 [516] Direct3D9: (ERROR) : [10] : Address 004425CA
00000070 6.05415583 [516]
00000071 6.05419636 [516] Direct3D9: (ERROR) : [11] : Address 004011E7
00000072 6.05423069 [516]
00000073 6.05427217 [516] Direct3D9: (ERROR) : [12] : Address 00401258
00000074 6.05430841 [516]
00000075 6.05434656 [516] Direct3D9: (ERROR) : [13] : Address 7C817077
00000076 6.05438232 [516]
00000077 6.05442142 [516] Direct3D9: (ERROR) : [14] : Address 00000000
00000078 6.05445766 [516]
00000079 6.05449724 [516] Direct3D9: (ERROR) : [15] : Address 00000000
00000080 6.05453157 [516]
00000081 6.05457401 [516] Direct3D9: (ERROR) :All user created D3DPOOL_DEFAULT surfaces must be freed before Reset can succeed. Reset Fails.
00000082 6.05460882 [516]








Was der Debugger mir sagen will, ist natürlich soweit ersichtlich; ich soll erst alle Ressourcen releasen, bevor der Reset erfolgt.
Allerdings finde ich besagtes D3DRTYPE_SURFACE nicht. Um den Fehler einzugrenzen initialisiere ich im Grunde (fast) gar nichts mehr.
Hier ist alles, was ich im Moment initialisiere (nach dem Fenster):
C++:
PDIRECT3DDEVICE9 InitDirectx(void)
{
bool bWindowed = switchbool(SET.STG_FULLSCREEN);
// Direct3D-Objekt erzeugen
PDIRECT3D9 pD3D = Direct3DCreate9(D3D_SDK_VERSION);
PDIRECT3DDEVICE9  m_lpD3DDevice;
PDIRECT3DSURFACE9 m_lpBackBuffer;
    
if(NULL == pD3D)
{
    ccout("Direct3D 9 konnte nicht initialisiert werden, installieren Sie die neuste DirectX-Version!");
    writeToLog("Direct3D 9 konnte nicht initialisiert werden, installieren Sie die neuste DirectX-Version!");
    return NULL;
}

D3DFORMAT d3dformat = D3DFMT_X8R8G8B8;//D3DFMT_R5G6B5;

// Parameter fuer den Modus festlegen

ZeroMemory(&PParams, sizeof(PParams));

PParams.SwapEffect       = D3DSWAPEFFECT_DISCARD;
PParams.hDeviceWindow    = g_hwnd;
PParams.Windowed         = bWindowed;


PParams.BackBufferWidth  = SET.SCREEN_WIDTH;
PParams.BackBufferHeight = SET.SCREEN_HEIGHT;
PParams.BackBufferFormat = d3dformat;
PParams.BackBufferCount  = 1;
PParams.FullScreen_RefreshRateInHz = bWindowed ? D3DPRESENT_RATE_DEFAULT  : SET.SCREEN_REFRESHRATE;

// Z-Buffer erzeugen
PParams.AutoDepthStencilFormat = D3DFMT_D16;
PParams.EnableAutoDepthStencil = TRUE;
PParams.MultiSampleType = D3DMULTISAMPLE_NONE; //_2_SAMPLES;
// PParams.MultiSampleQuality = 1;
PParams.Flags = 0;

PParams.PresentationInterval = bWindowed ? D3DPRESENT_INTERVAL_IMMEDIATE : D3DPRESENT_INTERVAL_ONE;
HRESULT hr;


if(FAILED(hr = pD3D->CreateDevice(
                             D3DADAPTER_DEFAULT, 
                             D3DDEVTYPE_HAL, 
                             g_hwnd, 
                             D3DCREATE_HARDWARE_VERTEXPROCESSING, 
                             &PParams, 
                             &m_lpD3DDevice)))
{
                             
    const char* Err = DXGetErrorDescription9(hr);
    DXTRACE_MSG(Err);
    // Fehler, Geraet kann nicht angelegt werden
    writeToLog("Keine Hardwareunterstüzung, versuche Softwareemulation");
    string line = STR(__LINE__);
    string data = STR(__FILE__);
    ReportError(line,data);
    if(FAILED(hr = pD3D->CreateDevice(
                             D3DADAPTER_DEFAULT, 
                             D3DDEVTYPE_HAL, 
                             g_hwnd, 
                             D3DCREATE_SOFTWARE_VERTEXPROCESSING, 
                             &PParams, 
                             &m_lpD3DDevice)))
    {
        pD3D->Release();
        const char* Err = DXGetErrorDescription9(hr);
        DXTRACE_MSG(Err);
        writeToLog("DirectX kann nicht initialisiert werden, wenden Sie sich bitte an den Support");
        string line = STR(__LINE__);
        string data = STR(__FILE__);
        ReportError(line,data);
        return NULL;
    }
}

// Zeiger auf dem Hintergrundpuffer holen
m_lpD3DDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &m_lpBackBuffer);
pD3D->Release();
return m_lpD3DDevice;
}

Ergebnis ist ein schwarzer Hintergrund. Zwinge ich nun meine Anwendung zum Reset (Windowstaste->Wieder aktivieren) wird (nachdem der Status auf "NOTRESETTET" steht) folgender Code ausgeführt:
C++:
bool resetD3DDevice(void)
{
//hier ggf. neue Dx-Einstellungen
bool bWindowed = switchbool(SET.STG_FULLSCREEN);
D3DFORMAT d3dformat = D3DFMT_X8R8G8B8;//D3DFMT_R5G6B5;

ZeroMemory(&PParams, sizeof(PParams));

PParams.SwapEffect       = D3DSWAPEFFECT_DISCARD;
PParams.hDeviceWindow    = g_hwnd;
PParams.Windowed         = bWindowed;


PParams.BackBufferWidth  = SET.SCREEN_WIDTH;
PParams.BackBufferHeight = SET.SCREEN_HEIGHT;
PParams.BackBufferFormat = d3dformat;
PParams.BackBufferCount  = 1;
PParams.FullScreen_RefreshRateInHz = bWindowed ? D3DPRESENT_RATE_DEFAULT  : SET.SCREEN_REFRESHRATE;



// Z-Buffer erzeugen
PParams.AutoDepthStencilFormat = D3DFMT_D16;
PParams.EnableAutoDepthStencil = TRUE;
PParams.MultiSampleType = D3DMULTISAMPLE_NONE; //_2_SAMPLES;
// PParams.MultiSampleQuality = 1;
PParams.Flags = 0;

PParams.PresentationInterval = bWindowed ? D3DPRESENT_INTERVAL_IMMEDIATE : D3DPRESENT_INTERVAL_ONE;




if(FAILED(pD3DDevice->Reset(&PParams))) {writeToLog("Failed to reset DX");return false;}
return true;
}

Ich frage mich, welche Ressource ich da releasen sollte :confused:

Vielleicht habe ich aber auch ein Brett vorm Kopf oder die Initialisierung ist schon nicht ideal?
(Allerdings geht im Grunde mit dieser Initialisierung alles->Sound,Text,Grafiken...)


Ich hoffe, ihr könnt mir weiterhelfen.

mfg
kickerxy123


#edit:

kann es auch an dem Fenster liegen?
Es wird bei mir mit folgenden Parametern aufgerufen: WS_VISIBLE | WS_OVERLAPPED | WS_EX_TOPMOST | WS_POPUP | WS_CAPTION | WS_DLGFRAME

und kurze Zeit später rufe ich dann diesen Code auf:
C++:
    SET.SCREEN_WIDTH = GetSystemMetrics(SM_CXSCREEN);
    SET.SCREEN_HEIGHT = GetSystemMetrics(SM_CYSCREEN);
    SetWindowLongPtr(hwnd,GWL_STYLE,WS_VISIBLE |WS_POPUP| WS_EX_TOPMOST);
    UpdateWindow(hwnd);
    SetWindowPos(hwnd,HWND_TOP,0,0,SET.SCREEN_WIDTH, SET.SCREEN_HEIGHT,SWP_SHOWWINDOW);

Nach der Initialisierung sieht meine Implementierung der Windows- Nachrichtenschleife wie folgt aus:
C++:
while (msg.message != WM_QUIT)
{
while(g_messageboxInterrupt == true)Sleep(10);//Nachrichten werden dann in der cccout-funktion behandelt!


    if(GS != _WINDOWS) PREVIOUS_GS = GS;   

    focus = GetForegroundWindow();
    
    if(focus == g_hwnd && GS == _WINDOWS) //Fenster wird gerade vom User reaktiviert
    {//DirectX neu initialisieren!!
         if(isDeviceLost()){}
         GS = PREVIOUS_GS;
    }
    if(focus != g_hwnd) 
    {
        GS = _WINDOWS; //wenn Spiel minimiert ist//nicht aktiv
    }
    else 
    {
        GS = PREVIOUS_GS;
    }

          if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
          {
              TranslateMessage(&msg);
              DispatchMessage(&msg);    
          }
          else
          {
              if(g_needD3DReset)
              {
                  if(isDeviceLost()){}
                  else g_needD3DReset = false;
                  
                  continue;
              }
//hier folgt alles andere (z.B. Zeichnen, Sound, Reaktion auf Eingaben etc.
//testweise habe ich allerdings auch an dieser Stelle ein "continue" eingefügt; sodass ich in dem Teil auch einen Fehler ausschließe...
 
Zuletzt bearbeitet:
Den Backbuffer von

m_lpD3DDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &m_lpBackBuffer);

musst du vor dem Reset freigeben.
 
Zurück