1

最近,我在使用 DirectX 9 的 3D 应用程序中发现了一个错误。该错误是每次我 alt-tab 或 ctrl-alt-delete 时,程序都会冻结或似乎什么也不做。我环顾四周,发现我需要使用IDirect3DDevice9::TestCooperativeLevel和重置我的设备IDirect3DDevice9::Reset。但我目前正在努力的是(据我所知)在我Reset使用设备之前,我需要释放资源D3DPOOL_MANAGE重置设备之前释放资源并在重置后重新分配资源给它?我该怎么做呢?下面是我的设备重置代码(在IsDeviceLost()函数中)。

DirectX.h

#pragma once
#pragma comment(lib, "d3d9.lib")

#include<d3d9.h>
#include<d3dx9math.h>

#include"Window.h"
#include"Vertex.h"
#include"Shader.h"

#define VERTEXFORMAT (D3DFVF_XYZ | D3DFVF_TEX1) //Flags for the Flexible Vertex Format (FVF)

class Shader;

class DirectX
{
public:
    DirectX(std::string windowTitle, int x, int y, unsigned int windowWidth, unsigned int windowHeight, bool fullscreen);
    virtual ~DirectX();

    static LPDIRECT3D9 direct3D;
    static LPDIRECT3DDEVICE9 device;
    static IDirect3DVertexDeclaration9* vertexDec;
    static ID3DXEffect* currentShaderEffect;

    void CheckShaderVersion();
    bool IsDeviceLost();

protected:
    D3DPRESENT_PARAMETERS direct3DPresPara;

    Window *window;
    unsigned int width;
    unsigned int height;
    D3DXMATRIX projMatrix;

private:
    void Initialize(bool fullscreenMode);
};

直接.cpp

#include"DirectX.h"

LPDIRECT3D9 DirectX::direct3D = NULL;
LPDIRECT3DDEVICE9 DirectX::device = NULL;
IDirect3DVertexDeclaration9* DirectX::vertexDec = NULL;
ID3DXEffect* DirectX::currentShaderEffect = NULL;

DirectX::DirectX(std::string windowTitle, int x, int y, unsigned int windowWidth, unsigned int windowHeight, bool fullscreen)
{
    width = windowWidth;
    height = windowHeight;

    window = new Window(windowTitle.c_str(), windowWidth, windowHeight, x, y, fullscreen);

    Initialize(fullscreen);

    D3DXMatrixPerspectiveFovLH( &projMatrix,
                                D3DXToRadian(45),
                                (float)width/(float)height,
                                1.0f,
                                15000.0f);

    //device->SetTransform(D3DTS_PROJECTION, &projMatrix);
}

DirectX::~DirectX()
{
    direct3D->Release();
    device->Release();
    vertexDec->Release();

    delete vertexDec;
    delete currentShaderEffect;
    delete window;
}

void DirectX::Initialize(bool fullscreenMode)
{
    direct3D = Direct3DCreate9(D3D_SDK_VERSION);

    ZeroMemory(&direct3DPresPara, sizeof(direct3DPresPara));

    switch(fullscreenMode)
    {
        case true:
            direct3DPresPara.Windowed = false;
        break;
        case false:
            direct3DPresPara.Windowed = true;
    }

    direct3DPresPara.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; //turns off VSync, comment this line of code to turn VSync back on
    direct3DPresPara.SwapEffect = D3DSWAPEFFECT_DISCARD;
    direct3DPresPara.hDeviceWindow = window->GetHandle();
    direct3DPresPara.BackBufferFormat = D3DFMT_X8R8G8B8;
    direct3DPresPara.BackBufferWidth = width;
    direct3DPresPara.BackBufferHeight = height;
    direct3DPresPara.EnableAutoDepthStencil = TRUE;
    direct3DPresPara.AutoDepthStencilFormat = D3DFMT_D16;

    direct3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window->GetHandle(), D3DCREATE_SOFTWARE_VERTEXPROCESSING, &direct3DPresPara, &device);

    D3DVERTEXELEMENT9 vertexElement[] = {   {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
                                            {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
                                            D3DDECL_END()};

    device->CreateVertexDeclaration(vertexElement, &vertexDec);

    //currentShaderEffect = 0;
}

void DirectX::CheckShaderVersion()
{
    D3DCAPS9 caps;

    device->GetDeviceCaps(&caps);

    bool stop = false;
    int i = 6;
    while(!stop)
    {
        if(caps.VertexShaderVersion < D3DVS_VERSION(i, 0))
        {
            i--;
        }
        else
        {
            std::cout << "you are using shader model " << i << std::endl;
            stop = true;
        }
    }

    //std::cout << caps.VertexShaderVersion << std::endl;
    //std::cout << D3DVS_VERSION(3, 0) << std::endl;
}

bool DirectX::IsDeviceLost()
{
    HRESULT result = device->TestCooperativeLevel();

    if(result == D3DERR_DEVICELOST)
    {
        Sleep(20); //Sleep for a little bit then try again.
        return true;
    }
    else if(result == D3DERR_DRIVERINTERNALERROR)
    {
        MessageBox(0, "Internal Driver Error. The program will now exit.", 0, 0);
        PostQuitMessage(0);
        return true;
    }
    else if(result == D3DERR_DEVICENOTRESET)
    {
        device->Reset(&direct3DPresPara);
        return false;
    }
    else
    {
        return false;
    }
}

任何帮助或建议将不胜感激。谢谢

4

1 回答 1

3

您不需要在D3DPOOL_MANAGED中释放资源。您需要在 D3DPOOL_DEFAULT 中释放资源。

如果您使用 D3DX 对象(ID3DXFont、ID3DXMesh、ID3DXSprite),它们通常具有“OnLostDevice”和“OnResetDevice”方法。您应该在适当的情况下调用这些方法。

如果一个对象没有任何处理“DeviceLost”状态的方法,它们应该被释放,只需在重置设备之前销毁该对象,然后重新加载它。

请注意,D3DPOOL_MANAGED 对象由驱动程序自动重新加载,不需要您提供任何“帮助”来处理重置/设备丢失。您确实需要照顾所有其他对象。

除了我所说/写的内容之外,您显然应该阅读 DirectX SDK 文档。他们在文档中涵盖了丢失的设备,并且 DirectX 示例通常可以很好地在设备重置后幸存下来。

于 2013-11-14T14:47:42.477 回答